diff --git a/.github/workflows/kernel-replay.yml b/.github/workflows/kernel-replay.yml new file mode 100644 index 0000000..fb380c9 --- /dev/null +++ b/.github/workflows/kernel-replay.yml @@ -0,0 +1,82 @@ +name: Independent kernel replay + +# Slower, independent checks of the compiled environment, run weekly and on demand: +# - leanchecker replays every declaration of every math0 module through the Lean kernel, +# which catches environment tampering that the elaborator would not; +# - axiom-audit (leanprover-community) checks that every declaration under `Math0` uses only +# propext, Classical.choice and Quot.sound, independently of math0's own audit commands. +on: + schedule: + - cron: "17 4 * * 1" + workflow_dispatch: + pull_request: + paths: + - .github/workflows/kernel-replay.yml + +# A replay takes over an hour; let a running one finish, and queue at most one newer run behind it. +concurrency: + group: kernel-replay-${{ github.ref }} + cancel-in-progress: false + +jobs: + leanchecker: + name: leanchecker (shard ${{ matrix.shard }} of 4) + runs-on: ubuntu-latest + timeout-minutes: 350 + strategy: + fail-fast: false + matrix: + shard: [0, 1, 2, 3] + env: + LEAN_NUM_THREADS: "2" + steps: + - uses: actions/checkout@v4 + - name: Add swap (single proof files need up to 8 GB; the runner has 16 GB) + run: | + swap=/mnt/math0.swap + if [ ! -d /mnt ] || [ "$(df --output=avail -BG /mnt | tail -1 | tr -dc 0-9)" -lt 30 ]; then swap=/math0.swap; fi + sudo fallocate -l 20G "$swap" && sudo chmod 600 "$swap" && sudo mkswap "$swap" >/dev/null && sudo swapon "$swap" + free -h + - uses: leanprover/lean-action@v1 + with: + lake-package-directory: lean + use-github-cache: false + build: false + - name: Build every module, two at a time + run: scripts/verify.sh --clean + - name: Replay this shard's modules through the kernel + working-directory: lean + env: + LEAN_NUM_THREADS: "1" + run: | + mods=$(find Math0 -name '*.lean' | sed 's/\.lean$//; s#/#.#g' | sort | awk -v s=${{ matrix.shard }} 'NR % 4 == s') + echo "$mods" | wc -l + lake env leanchecker -v $mods + axiom-audit: + name: axiom-audit + runs-on: ubuntu-latest + timeout-minutes: 330 + env: + LEAN_NUM_THREADS: "2" + steps: + - uses: actions/checkout@v4 + - name: Add swap (single proof files need up to 8 GB; the runner has 16 GB) + run: | + swap=/mnt/math0.swap + if [ ! -d /mnt ] || [ "$(df --output=avail -BG /mnt | tail -1 | tr -dc 0-9)" -lt 30 ]; then swap=/math0.swap; fi + sudo fallocate -l 20G "$swap" && sudo chmod 600 "$swap" && sudo mkswap "$swap" >/dev/null && sudo swapon "$swap" + free -h + - uses: leanprover/lean-action@v1 + with: + lake-package-directory: lean + use-github-cache: false + build: false + - name: Build every module, two at a time + run: scripts/verify.sh --clean + - name: Audit axioms (leanprover-community/axiom-audit) + uses: leanprover/lean-action@v1 + with: + lake-package-directory: lean + use-github-cache: false + build: false + axiom-audit: true diff --git a/.github/workflows/lean.yml b/.github/workflows/lean.yml new file mode 100644 index 0000000..875fb59 --- /dev/null +++ b/.github/workflows/lean.yml @@ -0,0 +1,52 @@ +name: Lean verification + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +# A newer push to the same pull request supersedes an older run. +concurrency: + group: lean-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + build: + name: Build and audit every result + runs-on: ubuntu-latest + timeout-minutes: 330 + env: + # At most two Lean processes at once: heavy proof files peak at about 8 GB each. + LEAN_NUM_THREADS: "2" + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # the freeze check reads the history of FROZEN.sha256 + - name: Add swap (single proof files need up to 8 GB; the runner has 16 GB) + run: | + swap=/mnt/math0.swap + if [ ! -d /mnt ] || [ "$(df --output=avail -BG /mnt | tail -1 | tr -dc 0-9)" -lt 30 ]; then swap=/math0.swap; fi + sudo fallocate -l 20G "$swap" && sudo chmod 600 "$swap" && sudo mkswap "$swap" >/dev/null && sudo swapon "$swap" + free -h + - name: Frozen statements are unchanged, append-only, and committed before their proofs + env: + BASE: ${{ github.event_name == 'pull_request' && format('origin/{0}', github.base_ref) || github.event.before }} + ORDER: ${{ github.event_name == 'pull_request' && '--order' || '' }} + run: | + if [ -n "$BASE" ]; then python3 scripts/check_freeze.py --base "$BASE" $ORDER + else python3 scripts/check_freeze.py; fi + - name: Install Lean and fetch Mathlib's prebuilt cache + uses: leanprover/lean-action@v1 + with: + lake-package-directory: lean + # No GitHub cache: every math0 module (and every formal-conjectures module it imports) + # is elaborated and checked by the kernel again on every run, never replayed. + use-github-cache: false + build: false + - name: Rebuild every result from scratch and re-run every audit + run: | + expected=$(python3 -c 'import json; print(len(json.load(open("catalog.json"))["results"]))') + scripts/verify.sh --clean --expect "$expected" + - name: The audit commands reject what they should + run: scripts/test_audit.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..17df95c --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# Lean / Lake +lean/.lake/ +# LaTeX build products +*.aux +*.log +*.out +*.toc +*.fdb_latexmk +*.fls +*.synctex.gz +*.bbl +*.blg +# Python +__pycache__/ diff --git a/CONTENTS.md b/CONTENTS.md new file mode 100644 index 0000000..72cd140 --- /dev/null +++ b/CONTENTS.md @@ -0,0 +1,185 @@ +# Contents + +**153 results, every one checked by the Lean kernel against a fixed statement:** 43 against statements published by a third party (formal-conjectures), and 110 against statements that math0 formalized from OEIS and froze before the proof. + +| Classification | Count | +|---|---| +| New result (conjecture settled; no earlier resolution found) | 74 | +| First formal proof of a known result | 55 | +| Independent formal proof (an implying Lean proof already exists elsewhere) | 18 | +| Misformalization found (upstream statement does not match the problem) | 6 | + +## New result (conjecture settled; no earlier resolution found) + +An independent assessor judged the difficulty of each of these: 0 substantial and 74 routine (a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search). Most of these conjectures had stayed open for lack of attention, not because they were hard; each result page gives the assessor's reasons. + +| # | Result | Area | Upstream statement | Lean | Difficulty | +|---|---|---|---|---|---| +| 1 | [3 × 3 lower triangles with neighbours differing by at most two: a(n) = 1047 n - 1459 for n > 2 (A195249)](results/oeis-a195249/README.md) | Discrete geometry | [`Math0.Statements.A195249.statement`](lean/Math0/Statements/OEIS/A195249.lean) (math0, from OEIS A195249) | [A195249.lean](lean/Math0/Frontier/OEIS/A195249.lean) | routine | +| 2 | [3^(3^18) + 2 is divisible by 31^2, so Hilliard's squarefree conjecture (A083020) fails](results/oeis-a083020/README.md) | Discrete geometry | [`def statement`](lean/Math0/Statements/OEIS/A083020.lean) (math0, from OEIS A083020) | [A083020.lean](lean/Math0/Frontier/OEIS/A083020.lean) | routine | +| 3 | [A090905: every row ends at twice the largest prime of the previous row (Murthy's conjecture proved)](results/oeis-a090905/README.md) | Discrete geometry | [`Math0.Statements.A090905.statement`](lean/Math0/Statements/OEIS/A090905.lean) (math0, from OEIS A090905) | [A090905.lean](lean/Math0/Frontier/OEIS/A090905.lean) | routine | +| 4 | [A106505: common sides of A/2A primitive triangles are periodic mod 8, so a(n+5) = a(n) + 8](results/oeis-a106505/README.md) | Discrete geometry | [`Math0.Statements.A106505.statement`](lean/Math0/Statements/OEIS/A106505.lean) (math0, from OEIS A106505) | [A106505.lean](lean/Math0/Frontier/OEIS/A106505.lean) | routine | +| 5 | [A123710: the rows of inv(floor(n/k)) with four nonzero entries are 6 and the proper prime powers](results/oeis-a123710/README.md) | Discrete geometry | [`Math0.Statements.A123710.statement`](lean/Math0/Statements/OEIS/A123710.lean) (math0, from OEIS A123710) | [A123710.lean](lean/Math0/Frontier/OEIS/A123710.lean) | routine | +| 6 | [A126127: Israel's conjectured bivariate g.f. of the inverse square of A061554 holds](results/oeis-a126127/README.md) | Discrete geometry | [`Math0.Statements.A126127.statement`](lean/Math0/Statements/OEIS/A126127.lean) (math0, from OEIS A126127) | [A126127.lean](lean/Math0/Frontier/OEIS/A126127.lean) | routine | +| 7 | [A127752 mod 2 is the first Feigenbaum symbolic sequence A035263](results/oeis-a127752/README.md) | Discrete geometry | [`Math0.Statements.A127752.statement`](lean/Math0/Statements/OEIS/A127752.lean) (math0, from OEIS A127752) | [A127752.lean](lean/Math0/Frontier/OEIS/A127752.lean) | routine | +| 8 | [A144637: (1/18) 6^n a(n)/n! is odd iff n = 2^k with k >= 1](results/oeis-a144637/README.md) | Discrete geometry | [`Math0.Statements.A144637.statement`](lean/Math0/Statements/OEIS/A144637.lean) (math0, from OEIS A144637) | [A144637.lean](lean/Math0/Frontier/OEIS/A144637.lean) | routine | +| 9 | [A172164: the second differences of the Theodorus-spiral turns are always 18, 19, 20 or 21](results/oeis-a172164/README.md) | Discrete geometry | [`Math0.Statements.A172164.statement`](lean/Math0/Statements/OEIS/A172164.lean) (math0, from OEIS A172164) | [A172164.lean](lean/Math0/Frontier/OEIS/A172164.lean) | routine | +| 10 | [A178295: collinear 4-subsets of {0,...,4}^n number 9^n/2 + 3*7^n/2 - 2*5^n (Mathar's conjecture, all three formulas)](results/oeis-a178295/README.md) | Discrete geometry | [`Math0.Statements.A178295.statement`](lean/Math0/Statements/OEIS/A178295.lean) (math0, from OEIS A178295) | [A178295.lean](lean/Math0/Frontier/OEIS/A178295.lean) | routine | +| 11 | [A223395: walks on the 4 x 4 grid graph satisfy Hardin's recurrence, Barker's g.f. and closed form](results/oeis-a223395/README.md) | Discrete geometry | [`Math0.Statements.A223395.statement`](lean/Math0/Statements/OEIS/A223395.lean) (math0, from OEIS A223395) | [A223395.lean](lean/Math0/Frontier/OEIS/A223395.lean) | routine | +| 12 | [A249151(k) = k exactly when k + 1 is prime (Karttunen's conjecture, A249434/A249151)](results/oeis-a249434/README.md) | Discrete geometry | [`Math0.Statements.A249434.statement`](lean/Math0/Statements/OEIS/A249434.lean) (math0, from OEIS A249434) | [A249434.lean](lean/Math0/Frontier/OEIS/A249434.lean) | routine | +| 13 | [A275815: Jones's conjecture a(n) = 8(n-2)^2 for n >= 6 holds](results/oeis-a275815/README.md) | Discrete geometry | [`Math0.Statements.A275815.statement`](lean/Math0/Statements/OEIS/A275815.lean) (math0, from OEIS A275815) | [A275815.lean](lean/Math0/Frontier/OEIS/A275815.lean) | routine | +| 14 | [A308107: Barker's rational generating function and order-15 recurrence for the sum of smallest sides of scalene integer triangles](results/oeis-a308107/README.md) | Discrete geometry | [`Math0.Statements.A308107.statement`](lean/Math0/Statements/OEIS/A308107.lean) (math0, from OEIS A308107) | [A308107.lean](lean/Math0/Frontier/OEIS/A308107.lean) | routine | +| 15 | [A308121: for odd n > 1, row 2n is row n with its halves swapped](results/oeis-a308121/README.md) | Discrete geometry | [`Math0.Statements.A308121.statement`](lean/Math0/Statements/OEIS/A308121.lean) (math0, from OEIS A308121) | [A308121.lean](lean/Math0/Frontier/OEIS/A308121.lean) | routine | +| 16 | [A332010: the average first letter of one-descent derangements has denominator 2^(n-2)](results/oeis-a332010/README.md) | Discrete geometry | [`Math0.Statements.A332010.statement`](lean/Math0/Statements/OEIS/A332010.lean) (math0, from OEIS A332010) | [A332010.lean](lean/Math0/Frontier/OEIS/A332010.lean) | routine | +| 17 | [A334595: a(n) = 1 iff n is a power of two, and the records occur exactly at 1 and 2^k + 1](results/oeis-a334595/README.md) | Discrete geometry | [`Math0.Statements.A334595.statement`](lean/Math0/Statements/OEIS/A334595.lean) (math0, from OEIS A334595) | [A334595.lean](lean/Math0/Frontier/OEIS/A334595.lean) | routine | +| 18 | [A338885: the smallest number in row 655 is 104, not A228286(655) = 115](results/oeis-a338885/README.md) | Discrete geometry | [`Math0.Statements.A338885.statement`](lean/Math0/Statements/OEIS/A338885.lean) (math0, from OEIS A338885) | [A338885.lean](lean/Math0/Frontier/OEIS/A338885.lean) | routine | +| 19 | [A342645: diagonals of the eventual Mahonian-column polynomials](results/oeis-a342645/README.md) | Discrete geometry | [`Math0.Statements.A342645.statement`](lean/Math0/Statements/OEIS/A342645.lean) (math0, from OEIS A342645) | [A342645.lean](lean/Math0/Frontier/OEIS/A342645.lean) | routine | +| 20 | [A348484: no two squares two steps apart; the conjectured formula holds](results/oeis-a348484/README.md) | Discrete geometry | [`Math0.Statements.A348484.statement`](lean/Math0/Statements/OEIS/A348484.lean) (math0, from OEIS A348484) | [A348484.lean](lean/Math0/Frontier/OEIS/A348484.lean) | routine | +| 21 | [A355339: the central even run of the knight-move triangle has length 1 iff n = 2^m - 2](results/oeis-a355339/README.md) | Discrete geometry | [`Math0.Statements.A355339.statement`](lean/Math0/Statements/OEIS/A355339.lean) (math0, from OEIS A355339) | [A355339.lean](lean/Math0/Frontier/OEIS/A355339.lean) | routine | +| 22 | [A363609: a(k^3) = 6k(k+2), the cube is the optimal polycube of k^3 dice](results/oeis-a363609/README.md) | Discrete geometry | [`def statement`](lean/Math0/Statements/OEIS/A363609.lean) (math0, from OEIS A363609) | [A363609.lean](lean/Math0/Frontier/OEIS/A363609.lean) | routine | +| 23 | [A386538: moving the circle's center off the grid enlarges the max lattice polygon (counterexample at n = 7)](results/oeis-a386538/README.md) | Discrete geometry | [`Math0.Statements.A386538.statement`](lean/Math0/Statements/OEIS/A386538.lean) (math0, from OEIS A386538) | [A386538.lean](lean/Math0/Frontier/OEIS/A386538.lean) | routine | +| 24 | [Alexandersson's recurrence for the row polynomials of A395454 holds (rows counted from 1)](results/oeis-a395454/README.md) | Discrete geometry | [`Math0.Statements.A395454.statement`](lean/Math0/Statements/OEIS/A395454.lean) (math0, from OEIS A395454) | [A395454.lean](lean/Math0/Frontier/OEIS/A395454.lean) | routine | +| 25 | [Bar tilings of the smallest-perimeter rectangle: a(n+1) = 4 a(n) for odd n >= 3 (A394981)](results/oeis-a394981/README.md) | Discrete geometry | [`def statement`](lean/Math0/Statements/OEIS/A394981.lean) (math0, from OEIS A394981) | [A394981.lean](lean/Math0/Frontier/OEIS/A394981.lean) | routine | +| 26 | [Barker's order-20 recurrence for the lines through an 8 x n grid holds](results/oeis-a160848/README.md) | Discrete geometry | [`Math0.Statements.A160848.statement`](lean/Math0/Statements/OEIS/A160848.lean) (math0, from OEIS A160848) | [A160848.lean](lean/Math0/Frontier/OEIS/A160848.lean) | routine | +| 27 | [Columns 1 and 2 of the theta-series triangle A355360 are P(x)^3 and 2P(x)^6](results/oeis-a355360/README.md) | Discrete geometry | [`Math0.Statements.A355360.statement`](lean/Math0/Statements/OEIS/A355360.lean) (math0, from OEIS A355360) | [A355360.lean](lean/Math0/Frontier/OEIS/A355360.lean) | routine | +| 28 | [Diagonal sums of A368846 equal A229580 (Luschny's conjecture)](results/oeis-a368846/README.md) | Discrete geometry | [`Math0.Statements.A368846.statement`](lean/Math0/Statements/OEIS/A368846.lean) (math0, from OEIS A368846) | [A368846.lean](lean/Math0/Frontier/OEIS/A368846.lean) | routine | +| 29 | [Domino towers of height 2 and of height n-1, n-2, n-3 (A333650): all four Kagey/Luschny conjectures](results/oeis-a333650/README.md) | Discrete geometry | [`Math0.Statements.A333650.statement`](lean/Math0/Statements/OEIS/A333650.lean) (math0, from OEIS A333650) | [A333650.lean](lean/Math0/Frontier/OEIS/A333650.lean) | routine | +| 30 | [Even and odd legs with odd prime factors ≡ 3 (mod 4): a(n)/n → π (A354571, A354570)](results/oeis-a354571/README.md) | Discrete geometry | [`Math0.Statements.A354571.statement`](lean/Math0/Statements/OEIS/A354571.lean) (math0, from OEIS A354571) | [A354571.lean](lean/Math0/Frontier/OEIS/A354571.lean) | routine | +| 31 | [Internal n-gons in a regular n-gon: triple points occur only for n = 3, 4, 6, and otherwise there are n k^2 + 1 regions (Shannon's A357216 conjecture)](results/oeis-a357216/README.md) | Discrete geometry | [`Math0.Statements.A357216.statement`](lean/Math0/Statements/OEIS/A357216.lean) (math0, from OEIS A357216) | [A357216.lean](lean/Math0/Frontier/OEIS/A357216.lean) | routine | +| 32 | [Irwin's nested sums give column 0 of the triangle A132615 (A132616)](results/oeis-a132616/README.md) | Discrete geometry | [`Math0.Statements.A132616.statement`](lean/Math0/Statements/OEIS/A132616.lean) (math0, from OEIS A132616) | [A132616.lean](lean/Math0/Frontier/OEIS/A132616.lean) | routine | +| 33 | [Kagey's conjecture for A278212: a(n) = floor(A275815(n)/2), via exact bishop and queen maxima from flow (LP-dual) certificates](results/oeis-a278212/README.md) | Discrete geometry | [`Math0.Statements.A278212.statement`](lean/Math0/Statements/OEIS/A278212.lean) (math0, from OEIS A278212) | [A278212.lean](lean/Math0/Frontier/OEIS/A278212.lean) | routine | +| 34 | [Kagey's order-10 recurrence for no-leaf subgraphs of the 5 × n grid holds](results/oeis-a320099/README.md) | Discrete geometry | [`Math0.Statements.A320099.statement`](lean/Math0/Statements/OEIS/A320099.lean) (math0, from OEIS A320099) | [A320099.lean](lean/Math0/Frontier/OEIS/A320099.lean) | routine | +| 35 | [Kurkov's recursion for the row polynomials of convolution triangles holds](results/oeis-a357583/README.md) | Discrete geometry | [`Math0.Statements.A357583.statement`](lean/Math0/Statements/OEIS/A357583.lean) (math0, from OEIS A357583) | [A357583.lean](lean/Math0/Frontier/OEIS/A357583.lean) | routine | +| 36 | [Kurkov's rook-tour conjecture for A001040: 2·n!·a(n) counts opposite-line Hamiltonian paths of K_n □ K_2](results/oeis-a001040/README.md) | Discrete geometry | [`Math0.Statements.A001040.statement`](lean/Math0/Statements/OEIS/A001040.lean) (math0, from OEIS A001040) | [A001040.lean](lean/Math0/Frontier/OEIS/A001040.lean) | routine | +| 37 | [Mathar's order-6 recurrence for A121750 (even-length columns in deco polyominoes) holds for all n >= 7](results/oeis-a121750/README.md) | Discrete geometry | [`Math0.Statements.A121750.statement`](lean/Math0/Statements/OEIS/A121750.lean) (math0, from OEIS A121750) | [A121750.lean](lean/Math0/Frontier/OEIS/A121750.lean) | routine | +| 38 | [O'Sullivan's Gaussian-polynomial / Chebyshev representation conjecture (A267486), proved](results/oeis-a267486/README.md) | Discrete geometry | [`Math0.Statements.A267486.statement`](lean/Math0/Statements/OEIS/A267486.lean) (math0, from OEIS A267486) | [A267486.lean](lean/Math0/Frontier/OEIS/A267486.lean) | routine | +| 39 | [OEIS A350900: Schulte's gcd-ratio double sum is a Dirichlet convolution](results/oeis-a350900/README.md) | Discrete geometry | [`Math0.Statements.A350900.statement`](lean/Math0/Statements/OEIS/A350900.lean) (math0, from OEIS A350900) | [A350900.lean](lean/Math0/Frontier/OEIS/A350900.lean) | routine | +| 40 | [Prime-Minesweeper on the A060734 array: a(n) < 6, and a(n) = 5 only at n = 6](results/oeis-a326407/README.md) | Discrete geometry | [`Math0.Statements.A326407.statement`](lean/Math0/Statements/OEIS/A326407.lean) (math0, from OEIS A326407) | [A326407.lean](lean/Math0/Frontier/OEIS/A326407.lean) | routine | +| 41 | [Schulte's conjectures on A281000, T(n,k) = C(2n+1,2k+1)·Cat(n-k): antidiagonal sums and matrix inverse](results/oeis-a281000/README.md) | Discrete geometry | [`Math0.Statements.A281000.statement`](lean/Math0/Statements/OEIS/A281000.lean) (math0, from OEIS A281000) | [A281000.lean](lean/Math0/Frontier/OEIS/A281000.lean) | routine | +| 42 | [Signed A350557 is the matrix inverse of A350512, proved](results/oeis-a350557/README.md) | Discrete geometry | [`Math0.Statements.A350557.statement`](lean/Math0/Statements/OEIS/A350557.lean) (math0, from OEIS A350557) | [A350557.lean](lean/Math0/Frontier/OEIS/A350557.lean) | routine | +| 43 | [Stephan's conjectured g.f. for A242396 is false (first failure at n = 97)](results/oeis-a242396/README.md) | Discrete geometry | [`Math0.Statements.A242396.statement`](lean/Math0/Statements/OEIS/A242396.lean) (math0, from OEIS A242396) | [A242396.lean](lean/Math0/Frontier/OEIS/A242396.lean) | routine | +| 44 | [The Golomb-row triangle A113676 and Levine's sequence A014644](results/oeis-a113676/README.md) | Discrete geometry | [`Math0.Statements.A113676.statement`](lean/Math0/Statements/OEIS/A113676.lean) (math0, from OEIS A113676) | [A113676.lean](lean/Math0/Frontier/OEIS/A113676.lean) | routine | +| 45 | [The generating function of A022445 (closed self-avoiding walks in the strip {0,1,2} x Z)](results/oeis-a022445/README.md) | Discrete geometry | [`Math0.Statements.A022445.statement`](lean/Math0/Statements/OEIS/A022445.lean) (math0, from OEIS A022445) | [A022445.lean](lean/Math0/Frontier/OEIS/A022445.lean) | routine | +| 46 | [The inverse of the 1/Catalan band triangle (A127767) has integer entries](results/oeis-a127767/README.md) | Discrete geometry | [`Math0.Statements.A127767.statement`](lean/Math0/Statements/OEIS/A127767.lean) (math0, from OEIS A127767) | [A127767.lean](lean/Math0/Frontier/OEIS/A127767.lean) | routine | +| 47 | [The inverse of the triangle 1/n! [k ≤ n ≤ 2k] is an integer triangle](results/oeis-a127755/README.md) | Discrete geometry | [`Math0.Statements.A127755.statement`](lean/Math0/Statements/OEIS/A127755.lean) (math0, from OEIS A127755) | [A127755.lean](lean/Math0/Frontier/OEIS/A127755.lean) | routine | +| 48 | [The least number of inequivalent cells of a (6k+5)-iamond is 3(k+1)](results/oeis-a369366/README.md) | Discrete geometry | [`def statement`](lean/Math0/Statements/OEIS/A369366.lean) (math0, from OEIS A369366) | [A369366.lean](lean/Math0/Frontier/OEIS/A369366.lean) | routine | +| 49 | [The row sums of the generalized Deutsch triangle A188474 are A137398](results/oeis-a188474/README.md) | Discrete geometry | [`Math0.Statements.A188474.statement`](lean/Math0/Statements/OEIS/A188474.lean) (math0, from OEIS A188474) | [A188474.lean](lean/Math0/Frontier/OEIS/A188474.lean) | routine | +| 50 | [The row-LCM of denominators of the cube of the mean matrix is n · lcm(1..n)²](results/oeis-a119936/README.md) | Discrete geometry | [`Math0.Statements.A119936.statement`](lean/Math0/Statements/OEIS/A119936.lean) (math0, from OEIS A119936) | [A119936.lean](lean/Math0/Frontier/OEIS/A119936.lean) | routine | +| 51 | [The subword complexity polynomial S(n,x) has leading coefficient n(n+1)/2 (A341761, Guo's conjecture)](results/oeis-a341761/README.md) | Discrete geometry | [`Math0.Statements.A341761.statement`](lean/Math0/Statements/OEIS/A341761.lean) (math0, from OEIS A341761) | [A341761.lean](lean/Math0/Frontier/OEIS/A341761.lean) | routine | +| 52 | [The toothpick spiral around n hexagonal cells (A182617): a(n) = 2n + ceil(sqrt(12n - 3))](results/oeis-a182617/README.md) | Discrete geometry | [`Math0.Statements.A182617.statement`](lean/Math0/Statements/OEIS/A182617.lean) (math0, from OEIS A182617) | [A182617.lean](lean/Math0/Frontier/OEIS/A182617.lean) | routine | +| 53 | [The triple-gcd Pascal triangle A129455: T(n,k) is an integer, divisible by C(n,k), and T(n,k)/C(n,k) is a sixth power](results/oeis-a129455/README.md) | Discrete geometry | [`Math0.Statements.A129455.statement`](lean/Math0/Statements/OEIS/A129455.lean) (math0, from OEIS A129455) | [A129455.lean](lean/Math0/Frontier/OEIS/A129455.lean) | routine | +| 54 | [A116184: Adamchuk's conjectures on 37^3 dividing the numerator of sum_{k=1}^{36} 1/k^n](results/oeis-a116184/README.md) | Number theory | [`Math0.Statements.A116184.statement`](lean/Math0/Statements/OEIS/A116184.lean) (math0, from OEIS A116184) | [A116184.lean](lean/Math0/Frontier/OEIS/A116184.lean) | routine | +| 55 | [A262957: Israel's b(n), c(n) are coprime integers and a(n) = b(n)](results/oeis-a262957/README.md) | Number theory | [`Math0.Statements.A262957.statement`](lean/Math0/Statements/OEIS/A262957.lean) (math0, from OEIS A262957) | [A262957.lean](lean/Math0/Frontier/OEIS/A262957.lean) | routine | +| 56 | [A356360: the continued-fraction denominators are 1 or prime](results/oeis-a356360/README.md) | Number theory | [`Math0.Statements.A356360.statement`](lean/Math0/Statements/OEIS/A356360.lean) (math0, from OEIS A356360) | [A356360.lean](lean/Math0/Frontier/OEIS/A356360.lean) | routine | +| 57 | [A375522: S2(n) - S1(n) = 1 fails at n = 42 (the difference is 5)](results/oeis-a375522/README.md) | Number theory | [`Math0.Statements.A375522.statement`](lean/Math0/Statements/OEIS/A375522.lean) (math0, from OEIS A375522) | [A375522.lean](lean/Math0/Frontier/OEIS/A375522.lean) | routine | +| 58 | [Convergents of [1; 1/2, 1/3, ..., 1/n]: numerator + denominator = 2^(v2(n!) + v2((n+1)!)) (A092054)](results/oeis-a092054/README.md) | Number theory | [`Math0.Statements.A092054.statement`](lean/Math0/Statements/OEIS/A092054.lean) (math0, from OEIS A092054) | [A092054.lean](lean/Math0/Frontier/OEIS/A092054.lean) | routine | +| 59 | [Imaginary parts of the convergents of [1+i; 1+i, 1+i, ...] are A317974(n+1)/A138573(n)](results/oeis-a093726/README.md) | Number theory | [`Math0.Statements.A093726.statement`](lean/Math0/Statements/OEIS/A093726.lean) (math0, from OEIS A093726) | [A093726.lean](lean/Math0/Frontier/OEIS/A093726.lean) | routine | +| 60 | [OEIS A362086: every denominator of 1/(2-3/(3-4/(...(n-1)-n/(-3)))) except 9 is 1 or a prime](results/oeis-a362086/README.md) | Number theory | [`Math0.Statements.A362086.statement`](lean/Math0/Statements/OEIS/A362086.lean) (math0, from OEIS A362086) | [A362086.lean](lean/Math0/Frontier/OEIS/A362086.lean) | routine | +| 61 | [OEIS A363482: apart from 49, every denominator of 1/(2-3/(3-4/(...(n-1)-n/(-5)))) is 1 or a prime](results/oeis-a363482/README.md) | Number theory | [`Math0.Statements.A363482.statement`](lean/Math0/Statements/OEIS/A363482.lean) (math0, from OEIS A363482) | [A363482.lean](lean/Math0/Frontier/OEIS/A363482.lean) | routine | +| 62 | [Repunit residues: a(n) = n - 1 exactly for long period primes](results/oeis-a335012/README.md) | Number theory | [`Math0.Statements.A335012.statement`](lean/Math0/Statements/OEIS/A335012.lean) (math0, from OEIS A335012) | [A335012.lean](lean/Math0/Frontier/OEIS/A335012.lean) | routine | +| 63 | [Zeros of a(3n) for the signed Stern sequence A005590 are exactly the fibbinary numbers](results/oeis-a005590/README.md) | Number theory | [`Math0.Statements.A005590.statement`](lean/Math0/Statements/OEIS/A005590.lean) (math0, from OEIS A005590) | [A005590.lean](lean/Math0/Frontier/OEIS/A005590.lean) | routine | +| 64 | [A326602: a(n) is odd iff n is a square](results/oeis-a326602/README.md) | Sequences and series | [`Math0.Statements.A326602.statement`](lean/Math0/Statements/OEIS/A326602.lean) (math0, from OEIS A326602) | [A326602.lean](lean/Math0/Frontier/OEIS/A326602.lean) | routine | +| 65 | [A351743: from n = 139 the sequence is affine in 42-blocks, which proves Sycamore's, Sigrist's and the A355149 conjectures](results/oeis-a351743/README.md) | Sequences and series | [`Math0.Statements.A351743.statement`](lean/Math0/Statements/OEIS/A351743.lean) (math0, from OEIS A351743) | [A351743.lean](lean/Math0/Frontier/OEIS/A351743.lean) | routine | +| 66 | [A386655 modulo 6 is eventually periodic with pattern [1, 0, 3, 0, 3, 2]](results/oeis-a386655/README.md) | Sequences and series | [`Math0.Statements.A386655.statement`](lean/Math0/Statements/OEIS/A386655.lean) (math0, from OEIS A386655) | [A386655.lean](lean/Math0/Frontier/OEIS/A386655.lean) | routine | +| 67 | [Every n not divisible by 5 has a multiple with only prime digits (A342992)](results/oeis-a342992/README.md) | Sequences and series | [`def statement`](lean/Math0/Statements/OEIS/A342992.lean) (math0, from OEIS A342992) | [A342992.lean](lean/Math0/Frontier/OEIS/A342992.lean) | routine | +| 68 | [Lang's conjecture a(n) = A250400(n+1)/(n+1) for A294512 fails at n = 164](results/oeis-a294512/README.md) | Sequences and series | [`Math0.Statements.A294512.statement`](lean/Math0/Statements/OEIS/A294512.lean) (math0, from OEIS A294512) | [A294512.lean](lean/Math0/Frontier/OEIS/A294512.lean) | routine | +| 69 | [Odd descending-by-2 multiples exist exactly when 125 does not divide 2n+1 (A062887)](results/oeis-a062887/README.md) | Sequences and series | [`Math0.Statements.A062887.statement`](lean/Math0/Statements/OEIS/A062887.lean) (math0, from OEIS A062887) | [A062887.lean](lean/Math0/Frontier/OEIS/A062887.lean) | routine | +| 70 | [Odd terms of A323695 occur only at n = k(k+2)](results/oeis-a323695/README.md) | Sequences and series | [`Math0.Statements.A323695.statement`](lean/Math0/Statements/OEIS/A323695.lean) (math0, from OEIS A323695) | [A323695.lean](lean/Math0/Frontier/OEIS/A323695.lean) | routine | +| 71 | [The 1089-trick map has two 9-digit fixed points (A393794 uniqueness conjecture is false)](results/oeis-a393794/README.md) | Sequences and series | [`Math0.Statements.A393794.statement`](lean/Math0/Statements/OEIS/A393794.lean) (math0, from OEIS A393794) | [A393794.lean](lean/Math0/Frontier/OEIS/A393794.lean) | routine | +| 72 | [The only fixed points of reverse(x) - maxdigit(x) are 0 and 89](results/oeis-a097154/README.md) | Sequences and series | [`Math0.Statements.A097154.statement`](lean/Math0/Statements/OEIS/A097154.lean) (math0, from OEIS A097154) | [A097154.lean](lean/Math0/Frontier/OEIS/A097154.lean) | routine | +| 73 | [There are no 5-Rotation Cycle Primes (A086004, Conjecture 2)](results/oeis-a086004/README.md) | Sequences and series | [`Math0.Statements.A086004.statement`](lean/Math0/Statements/OEIS/A086004.lean) (math0, from OEIS A086004) | [A086004.lean](lean/Math0/Frontier/OEIS/A086004.lean) | routine | +| 74 | [Yanev's identity for A073642 (sum of the positions of the 1-bits)](results/oeis-a073642/README.md) | Sequences and series | [`Math0.Statements.A073642.statement`](lean/Math0/Statements/OEIS/A073642.lean) (math0, from OEIS A073642) | [A073642.lean](lean/Math0/Frontier/OEIS/A073642.lean) | routine | + +## First formal proof of a known result + +| # | Result | Area | Upstream statement | Lean | +|---|---|---|---|---| +| 1 | [Maximal tensor rank is at most twice the generic rank (Blekherman–Teitler)](results/arxiv-0805-3777-ismaxrank-le-two-mul-isgenericrank/README.md) | Algebraic geometry, Linear algebra | [`Arxiv.«0805.3777».isMaxRank_le_two_mul_isGenericRank`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/0805.3777/TensorRank.lean) | [Arxiv_0805_3777_isMaxRank_le_two_mul_isGenericRank.lean](lean/Math0/Arxiv/Arxiv_0805_3777_isMaxRank_le_two_mul_isGenericRank.lean) | +| 2 | [The Jacobian conjecture in dimension 2n implies the Poisson conjecture in dimension n](results/arxiv-math-0608009-poisson-conjecture-variants-jacobian-implication/README.md) | Algebraic geometry, Nonassociative algebra | [`Arxiv.«math.0608009».poisson_conjecture.variants.jacobian_implication`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/math.0608009/PoissonConjecture.lean) | [Arxiv_math_0608009_poisson_conjecture_variants_jacobian_implication.lean](lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_jacobian_implication.lean) | +| 3 | [The Poisson conjecture fails in dimension three](results/arxiv-math-0608009-poisson-conjecture-variants-dimension-three/README.md) | Algebraic geometry, Nonassociative algebra | [`Arxiv.«math.0608009».poisson_conjecture.variants.dimension_three`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/math.0608009/PoissonConjecture.lean) | [Arxiv_math_0608009_poisson_conjecture_variants_dimension_three.lean](lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_dimension_three.lean) | +| 4 | [A 7-regular 3-critical 3-uniform hypergraph on 9 vertices (Erdős Problem 834, chromatic version)](results/erdos834-erdos-834-parts-ii/README.md) | Combinatorics | [`Erdos834.erdos_834.parts.ii`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/834.lean) | [Erdos834_erdos_834_parts_ii.lean](lean/Math0/ErdosProblems/Erdos834_erdos_834_parts_ii.lean) | +| 5 | [Gowers–Long lower bound: F(k²) ≥ k³ for 2-increasing sequences of triples](results/arxiv-1609-08688-maximallength-ge-of-issquare/README.md) | Combinatorics | [`Arxiv.«1609.08688».maximalLength_ge_of_isSquare`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/1609.08688/sIncreasingrTuples.lean) | [Arxiv_1609_08688_maximalLength_ge_of_isSquare.lean](lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_ge_of_isSquare.lean) | +| 6 | [K_{n,n+1} is extremal for Erdős Problem 816](results/erdos816-erdos-816-variants-complete-bipartite/README.md) | Combinatorics | [`Erdos816.erdos_816.variants.complete_bipartite`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/816.lean) | [Erdos816_erdos_816_variants_complete_bipartite.lean](lean/Math0/ErdosProblems/Erdos816_erdos_816_variants_complete_bipartite.lean) | +| 7 | [Moon–Moser: a graph on n vertices has at most n − log₂ n + 1 maximal-clique sizes](results/erdos775-erdos-775-variants-moon-moser/README.md) | Combinatorics | [`Erdos775.erdos_775.variants.moon_moser`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/775.lean) | [Erdos775_erdos_775_variants_moon_moser.lean](lean/Math0/ErdosProblems/Erdos775_erdos_775_variants_moon_moser.lean) | +| 8 | [Projective planes exist for every prime-power order (Erdős 723, existence variant)](results/erdos723-erdos-723-variants-prime-power-is-projplane-order/README.md) | Combinatorics | [`Erdos723.erdos_723.variants.prime_power_is_projplane_order`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/723.lean) | [Erdos723_erdos_723_variants_prime_power_is_projplane_order.lean](lean/Math0/ErdosProblems/Erdos723_erdos_723_variants_prime_power_is_projplane_order.lean) | +| 9 | [Supermultiplicativity of F gives arbitrarily large m with F(m) ≥ m^α (Gowers–Long)](results/arxiv-1609-08688-maximallength-pow/README.md) | Combinatorics | [`Arxiv.«1609.08688».maximalLength_pow`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/1609.08688/sIncreasingrTuples.lean) | [Arxiv_1609_08688_maximalLength_pow.lean](lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_pow.lean) | +| 10 | [The Johnson graph J(18, 9) has chromatic number at least 11](results/erdos835-johnsongraph-18-9-chromaticnumber/README.md) | Combinatorics | [`Erdos835.johnsonGraph_18_9_chromaticNumber`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/835.lean) | [Erdos835_johnsonGraph_18_9_chromaticNumber.lean](lean/Math0/ErdosProblems/Erdos835_johnsonGraph_18_9_chromaticNumber.lean) | +| 11 | [Grechuk's example: 1117175146 is not a prime plus at most three powers of two](results/erdos10-erdos-10-variants-grechuk-example/README.md) | Combinatorics, Number theory | [`Erdos10.erdos_10.variants.grechuk_example`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/10.lean) | [Erdos10_erdos_10_variants_grechuk_example.lean](lean/Math0/ErdosProblems/Erdos10_erdos_10_variants_grechuk_example.lean) | +| 12 | [Erdős 1048: the component of {|zⁿ| ≤ 1} containing 0 has diameter exactly 2](results/erdos1048-erdos-1048-variants-diam-ge-two-is-best/README.md) | Complex analysis | [`Erdos1048.erdos_1048.variants.diam_ge_two_is_best`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1048.lean) | [Erdos1048_erdos_1048_variants_diam_ge_two_is_best.lean](lean/Math0/ErdosProblems/Erdos1048_erdos_1048_variants_diam_ge_two_is_best.lean) | +| 13 | [A211343: positive entries are smallest parts of consecutive-part partitions; last positive column is A109814(n)](results/oeis-a211343/README.md) | Discrete geometry | [`Math0.Statements.A211343.statement`](lean/Math0/Statements/OEIS/A211343.lean) (math0, from OEIS A211343) | [A211343.lean](lean/Math0/Frontier/OEIS/A211343.lean) | +| 14 | [A265649: both of Werner Schulte's closed forms hold](results/oeis-a265649/README.md) | Discrete geometry | [`Math0.Statements.A265649.statement`](lean/Math0/Statements/OEIS/A265649.lean) (math0, from OEIS A265649) | [A265649.lean](lean/Math0/Frontier/OEIS/A265649.lean) | +| 15 | [A344710: non-obtuse lattice triangles with sides >= sqrt(n) have |det| > (sqrt 3 / 2) n](results/oeis-a344710/README.md) | Discrete geometry | [`Math0.Statements.A344710.statement`](lean/Math0/Statements/OEIS/A344710.lean) (math0, from OEIS A344710) | [A344710.lean](lean/Math0/Frontier/OEIS/A344710.lean) | +| 16 | [A373359: Schreier-set row lengths equal the Zeckendorf weight A007895](results/oeis-a373359/README.md) | Discrete geometry | [`Math0.Statements.A373359.statement`](lean/Math0/Statements/OEIS/A373359.lean) (math0, from OEIS A373359) | [A373359.lean](lean/Math0/Frontier/OEIS/A373359.lean) | +| 17 | [An equiangular decagon with sides in arithmetic progression (A215010)](results/oeis-a215010/README.md) | Discrete geometry | [`Math0.Statements.A215010.statement`](lean/Math0/Statements/OEIS/A215010.lean) (math0, from OEIS A215010) | [A215010.lean](lean/Math0/Frontier/OEIS/A215010.lean) | +| 18 | [Collinear 5-point sets in the grid {0,…,4}^n number (7^n − 5^n)/2 (Hardin's conjecture, A081200)](results/oeis-a081200/README.md) | Discrete geometry | [`Math0.Statements.A081200.statement`](lean/Math0/Statements/OEIS/A081200.lean) (math0, from OEIS A081200) | [A081200.lean](lean/Math0/Frontier/OEIS/A081200.lean) | +| 19 | [Column sums of strictly superdiagonal reversed partitions by maximum are A000245](results/oeis-a388724/README.md) | Discrete geometry | [`Math0.Statements.A388724.statement`](lean/Math0/Statements/OEIS/A388724.lean) (math0, from OEIS A388724) | [A388724.lean](lean/Math0/Frontier/OEIS/A388724.lean) | +| 20 | [Denominators of Curtz's polynomials are Farhi's d(n+1,k+1) (A141412, Marcus's conjecture)](results/oeis-a141412/README.md) | Discrete geometry | [`Math0.Statements.A141412.statement`](lean/Math0/Statements/OEIS/A141412.lean) (math0, from OEIS A141412) | [A141412.lean](lean/Math0/Frontier/OEIS/A141412.lean) | +| 21 | [Divisors of the terms of row n of A176206 are the parts of the partitions of n](results/oeis-a176206/README.md) | Discrete geometry | [`Math0.Statements.A176206.statement`](lean/Math0/Statements/OEIS/A176206.lean) (math0, from OEIS A176206) | [A176206.lean](lean/Math0/Frontier/OEIS/A176206.lean) | +| 22 | [Domino-tileable Young diagrams are exactly the colour-balanced ones (A300789)](results/oeis-a300789/README.md) | Discrete geometry | [`Math0.Statements.A300789.statement`](lean/Math0/Statements/OEIS/A300789.lean) (math0, from OEIS A300789) | [A300789.lean](lean/Math0/Frontier/OEIS/A300789.lean) | +| 23 | [Edges of the all-chords graph of a triangle with n general-position points per side (A367119)](results/oeis-a367119/README.md) | Discrete geometry | [`Math0.Statements.A367119.statement`](lean/Math0/Statements/OEIS/A367119.lean) (math0, from OEIS A367119) | [A367119.lean](lean/Math0/Frontier/OEIS/A367119.lean) | +| 24 | [Every odd prime is a side of a Heronian triangle (A229159)](results/oeis-a229159/README.md) | Discrete geometry | [`Math0.Statements.A229159.statement`](lean/Math0/Statements/OEIS/A229159.lean) (math0, from OEIS A229159) | [A229159.lean](lean/Math0/Frontier/OEIS/A229159.lean) | +| 25 | [Fixed polyominoes with n cells and width n-2: T(n,n-2) = 8n^2 - 51n + 86 (A308359)](results/oeis-a308359/README.md) | Discrete geometry | [`Math0.Statements.A308359.statement`](lean/Math0/Statements/OEIS/A308359.lean) (math0, from OEIS A308359) | [A308359.lean](lean/Math0/Frontier/OEIS/A308359.lean) | +| 26 | [Goodman–Goodman covering theorem for balls in ℝ^d (Erdős 1121, higher-dimensional variant)](results/erdos1121-erdos-1121-variants-higher-dimension/README.md) | Discrete geometry | [`Erdos1121.erdos_1121.variants.higher_dimension`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1121.lean) | [Erdos1121_erdos_1121_variants_higher_dimension.lean](lean/Math0/ErdosProblems/Erdos1121_erdos_1121_variants_higher_dimension.lean) | +| 27 | [Hanna's conjecture A124418(n,k) = k! * A124526(n,k) (partitions with k mixed-parity blocks) proved](results/oeis-a124526/README.md) | Discrete geometry | [`Math0.Statements.A124526.statement`](lean/Math0/Statements/OEIS/A124526.lean) (math0, from OEIS A124526) | [A124526.lean](lean/Math0/Frontier/OEIS/A124526.lean) | +| 28 | [Kurkov's recursion computes the free cumulants (A350499)](results/oeis-a350499/README.md) | Discrete geometry | [`Math0.Statements.A350499.statement`](lean/Math0/Statements/OEIS/A350499.lean) (math0, from OEIS A350499) | [A350499.lean](lean/Math0/Frontier/OEIS/A350499.lean) | +| 29 | [Layman's floor formula for collinear triples in a 3 × n grid (A057566), as printed until its October 2026 correction, fails at n = 24](results/oeis-a057566/README.md) | Discrete geometry | [`Math0.Statements.A057566.statement`](lean/Math0/Statements/OEIS/A057566.lean) (math0, from OEIS A057566) | [A057566.lean](lean/Math0/Frontier/OEIS/A057566.lean) | +| 30 | [Mathar's generating function for column 3 of A270668 (domino tilings of (4k+1)x5 boards with central hole)](results/oeis-a270668/README.md) | Discrete geometry | [`Math0.Statements.A270668.statement`](lean/Math0/Statements/OEIS/A270668.lean) (math0, from OEIS A270668) | [A270668.lean](lean/Math0/Frontier/OEIS/A270668.lean) | +| 31 | [No primitive Heronian triangle has integer circumradius](results/oeis-a392943/README.md) | Discrete geometry | [`Math0.Statements.A392943.statement`](lean/Math0/Statements/OEIS/A392943.lean) (math0, from OEIS A392943) | [A392943.lean](lean/Math0/Frontier/OEIS/A392943.lean) | +| 32 | [Perimeters of primitive Heronian isosceles triangles: A308222(n) = 2 · A096033(n + 2)](results/oeis-a308222/README.md) | Discrete geometry | [`Math0.Statements.A308222.statement`](lean/Math0/Statements/OEIS/A308222.lean) (math0, from OEIS A308222) | [A308222.lean](lean/Math0/Frontier/OEIS/A308222.lean) | +| 33 | [Records of the XOR-triangle zero count A334592 are exactly the powers of two](results/oeis-a334592/README.md) | Discrete geometry | [`Math0.Statements.A334592.statement`](lean/Math0/Statements/OEIS/A334592.lean) (math0, from OEIS A334592) | [A334592.lean](lean/Math0/Frontier/OEIS/A334592.lean) | +| 34 | [Row lengths of the Schreier-set triangle A373345 are A007895 (number of Zeckendorf summands)](results/oeis-a373345/README.md) | Discrete geometry | [`Math0.Statements.A373345.statement`](lean/Math0/Statements/OEIS/A373345.lean) (math0, from OEIS A373345) | [A373345.lean](lean/Math0/Frontier/OEIS/A373345.lean) | +| 35 | [Ternary digits of 2^n: column k has least period 2*3^(k-1) and balanced digits for k ≥ 2](results/oeis-a265210/README.md) | Discrete geometry | [`Math0.Statements.A265210.statement`](lean/Math0/Statements/OEIS/A265210.lean) (math0, from OEIS A265210) | [A265210.lean](lean/Math0/Frontier/OEIS/A265210.lean) | +| 36 | [The corrected floor formula for collinear triples in a 3 x n grid (OEIS A057566) holds for all n](results/oeis-a057566b/README.md) | Discrete geometry | [`Math0.Statements.A057566b.statement`](lean/Math0/Statements/OEIS/A057566b.lean) (math0, from OEIS A057566 (formula as corrected on 21 Oct 2026)) | [A057566b.lean](lean/Math0/Frontier/OEIS/A057566b.lean) | +| 37 | [The gcd of the interior binomial coefficients of row n equals Λ-exp(n)·Λ-exp(n−1) (A328202, Maiga's conjecture)](results/oeis-a328202/README.md) | Discrete geometry | [`Math0.Statements.A328202.statement`](lean/Math0/Statements/OEIS/A328202.lean) (math0, from OEIS A328202) | [A328202.lean](lean/Math0/Frontier/OEIS/A328202.lean) | +| 38 | [The longest path on the black squares of an even chessboard has (n^2-n+2)/2 squares (A075855)](results/oeis-a075855/README.md) | Discrete geometry | [`Math0.Statements.A075855.statement`](lean/Math0/Statements/OEIS/A075855.lean) (math0, from OEIS A075855) | [A075855.lean](lean/Math0/Frontier/OEIS/A075855.lean) | +| 39 | [Γ_{3⊕3} (equal-sign pairs in S₃ × S₃) is not 2-generated](results/arxiv-2605-12342-conjecture-1-variants-rank-3-3/README.md) | Group theory | [`Arxiv.«2605.12342».conjecture_1.variants.rank_3_3`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/2605.12342/Conjecture1.lean) | [Arxiv_2605_12342_conjecture_1_variants_rank_3_3.lean](lean/Math0/Arxiv/Arxiv_2605_12342_conjecture_1_variants_rank_3_3.lean) | +| 40 | [Erdős 367 (higher full parts): the product of r-full parts beats n^(1+ε) infinitely often](results/erdos367-erdos-367-variants-higher-full-parts/README.md) | Number theory | [`Erdos367.erdos_367.variants.higher_full_parts`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/367.lean) | [Erdos367_erdos_367_variants_higher_full_parts.lean](lean/Math0/ErdosProblems/Erdos367_erdos_367_variants_higher_full_parts.lean) | +| 41 | [Erdős Problem 1000: liminf φ_A(k)/n_k = 0 forces limsup φ_A(k)/n_k = 1](results/erdos1000-erdos-1000-variants-limsup-eq-one/README.md) | Number theory | [`Erdos1000.erdos_1000.variants.limsup_eq_one`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1000.lean) | [Erdos1000_erdos_1000_variants_limsup_eq_one.lean](lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_limsup_eq_one.lean) | +| 42 | [Every n is x² + y² − z² with max(x², y², z²) ≤ n + 2√n](results/erdos1148-erdos-1148-variants-weaker/README.md) | Number theory | [`Erdos1148.erdos_1148.variants.weaker`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1148.lean) | [Erdos1148_erdos_1148_variants_weaker.lean](lean/Math0/ErdosProblems/Erdos1148_erdos_1148_variants_weaker.lean) | +| 43 | [Integer partial sums of the Calkin-Wilf ratios fusc(k)/fusc(k+1) at n = 2*4^k-1 and 2*4^k-2 (A355076)](results/oeis-a355076/README.md) | Number theory | [`Math0.Statements.A355076.statement`](lean/Math0/Statements/OEIS/A355076.lean) (math0, from OEIS A355076) | [A355076.lean](lean/Math0/Frontier/OEIS/A355076.lean) | +| 44 | [Mahler's Z-numbers form a Lebesgue-null set](results/bugeaud09-problem-10-9-variants-measure-zero/README.md) | Number theory | [`Bugeaud09.problem_10_9.variants.measure_zero`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_9.lean) | [Bugeaud09_problem_10_9_variants_measure_zero.lean](lean/Math0/Books/Bugeaud09_problem_10_9_variants_measure_zero.lean) | +| 45 | [Quet's integrality conjecture for A091817 holds](results/oeis-a091817/README.md) | Number theory | [`Math0.Statements.A091817.statement`](lean/Math0/Statements/OEIS/A091817.lean) (math0, from OEIS A091817) | [A091817.lean](lean/Math0/Frontier/OEIS/A091817.lean) | +| 46 | [The fractional parts of (3/2)^n have infinitely many accumulation points](results/equidistribution-isaccumulationpoint-three-halves-pow-infinite/README.md) | Number theory | [`Equidistribution.isAccumulationPoint_three_halves_pow_infinite`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Books/UniformDistributionOfSequences/Equidistribution.lean) | [Equidistribution_isAccumulationPoint_three_halves_pow_infinite.lean](lean/Math0/Books/Equidistribution_isAccumulationPoint_three_halves_pow_infinite.lean) | +| 47 | [The multiples of 3 avoid sums equal to powers of two and have density 1/3](results/erdos1136-erdos-1136-variants-multiples-of-three/README.md) | Number theory | [`Erdos1136.erdos_1136.variants.multiples_of_three`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1136.lean) | [Erdos1136_erdos_1136_variants_multiples_of_three.lean](lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_multiples_of_three.lean) | +| 48 | [The p-adic Littlewood conjecture for real quadratic irrationals](results/bugeaud08-problem-10-8-variants-quadratic/README.md) | Number theory | [`Bugeaud08.problem_10_8.variants.quadratic`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_8.lean) | [Bugeaud08_problem_10_8_variants_quadratic.lean](lean/Math0/Books/Bugeaud08_problem_10_8_variants_quadratic.lean) | +| 49 | [The period of 1/11^n is 2 * 11^(n-1)](results/oeis-a334603/README.md) | Number theory | [`Math0.Statements.A334603.statement`](lean/Math0/Statements/OEIS/A334603.lean) (math0, from OEIS A334603) | [A334603.lean](lean/Math0/Frontier/OEIS/A334603.lean) | +| 50 | [The set of Mahler Z-numbers is countable, so its Hausdorff dimension is 0, which is less than 1](results/bugeaud09-problem-10-9-variants-dimh-lt-one/README.md) | Number theory | [`Bugeaud09.problem_10_9.variants.dimH_lt_one`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_9.lean) | [Bugeaud09_problem_10_9_variants_dimH_lt_one.lean](lean/Math0/Books/Bugeaud09_problem_10_9_variants_dimH_lt_one.lean) | +| 51 | [A115026 has a term greater than 370: a(119) = 371](results/oeis-a115026/README.md) | Sequences and series | [`Math0.Statements.A115026.statement`](lean/Math0/Statements/OEIS/A115026.lean) (math0, from OEIS A115026) | [A115026.lean](lean/Math0/Frontier/OEIS/A115026.lean) | +| 52 | [Denominators of Sum C(k)/4^(k-1): Groux's and Staunton's conjectures (A120069)](results/oeis-a120069/README.md) | Sequences and series | [`Math0.Statements.A120069.statement`](lean/Math0/Statements/OEIS/A120069.lean) (math0, from OEIS A120069) | [A120069.lean](lean/Math0/Frontier/OEIS/A120069.lean) | +| 53 | [Positivity of the exponential Mertens function (A209802)](results/oeis-a209802/README.md) | Sequences and series | [`Math0.Statements.A209802.statement`](lean/Math0/Statements/OEIS/A209802.lean) (math0, from OEIS A209802) | [A209802.lean](lean/Math0/Frontier/OEIS/A209802.lean) | +| 54 | [Repdigits with repdigit digital product are repunits from a(16) = 1111 on (A201060)](results/oeis-a201060/README.md) | Sequences and series | [`def statement`](lean/Math0/Statements/OEIS/A201060.lean) (math0, from OEIS A201060) | [A201060.lean](lean/Math0/Frontier/OEIS/A201060.lean) | +| 55 | [Reverse-divisor numbers are 1, 12, 78 or 89 mod 100 (A071685, Dale's conjecture)](results/oeis-a071685/README.md) | Sequences and series | [`def statement`](lean/Math0/Statements/OEIS/A071685.lean) (math0, from OEIS A071685) | [A071685.lean](lean/Math0/Frontier/OEIS/A071685.lean) | + +## Independent formal proof (an implying Lean proof already exists elsewhere) + +| # | Result | Area | Upstream statement | Lean | +|---|---|---|---|---| +| 1 | [Erdős 1026: no constant c > 1 is admissible (Cambie's construction)](results/erdos1026-erdos-1026-variants-upper-bound/README.md) | Combinatorics | [`Erdos1026.erdos_1026.variants.upper_bound`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1026.lean) | [Erdos1026_erdos_1026_variants_upper_bound.lean](lean/Math0/ErdosProblems/Erdos1026_erdos_1026_variants_upper_bound.lean) | +| 2 | [Erdős Problem 1008: every graph with m edges has a C4-free subgraph with at least √m/2 edges](results/erdos1008-erdos-1008-variants-lower-bound/README.md) | Combinatorics | [`Erdos1008.erdos_1008.variants.lower_bound`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1008.lean) | [Erdos1008_erdos_1008_variants_lower_bound.lean](lean/Math0/ErdosProblems/Erdos1008_erdos_1008_variants_lower_bound.lean) | +| 3 | [Erdős–Hajnal: infinite chromatic number with independent sets of size m/2 − cm for every c > 1/4](results/erdos750-erdos-750-variants-c-gt-quarter/README.md) | Combinatorics | [`Erdos750.erdos_750.variants.c_gt_quarter`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/750.lean) | [Erdos750_erdos_750_variants_c_gt_quarter.lean](lean/Math0/ErdosProblems/Erdos750_erdos_750_variants_c_gt_quarter.lean) | +| 4 | [Rademacher's theorem: ⌊n²/4⌋+1 edges force ⌊n/2⌋ triangles](results/erdos1010-erdos-1010-variants-rademacher/README.md) | Combinatorics | [`Erdos1010.erdos_1010.variants.rademacher`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1010.lean) | [Erdos1010_erdos_1010_variants_rademacher.lean](lean/Math0/ErdosProblems/Erdos1010_erdos_1010_variants_rademacher.lean) | +| 5 | [Cliques in the non-commuting graph have at most [G : Z(G)] vertices](results/erdos1098-erdos-1098-variants-upper-bound/README.md) | Combinatorics, Group theory | [`Erdos1098.erdos_1098.variants.upper_bound`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1098.lean) | [Erdos1098_erdos_1098_variants_upper_bound.lean](lean/Math0/ErdosProblems/Erdos1098_erdos_1098_variants_upper_bound.lean) | +| 6 | [Erdős Problem 1193 (i): the lower density of {n : 1_A*1_A(n) = g(n)} need not be 0](results/erdos1193-erdos-1193-parts-i/README.md) | Combinatorics, Number theory | [`Erdos1193.erdos_1193.parts.i`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1193.lean) | [Erdos1193_erdos_1193_parts_i.lean](lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_i.lean) | +| 7 | [Erdős Problem 1193 (ii): the upper density of {n : 1_A*1_A(n) = g(n)} need not be bounded away from 1](results/erdos1193-erdos-1193-parts-ii/README.md) | Combinatorics, Number theory | [`Erdos1193.erdos_1193.parts.ii`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1193.lean) | [Erdos1193_erdos_1193_parts_ii.lean](lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_ii.lean) | +| 8 | [A397315: a 14-point blackout of the 5 x 8 grid refutes T(n,m) = n + m](results/oeis-a397315/README.md) | Discrete geometry | [`Math0.Statements.A397315.statement`](lean/Math0/Statements/OEIS/A397315.lean) (math0, from OEIS A397315) | [A397315.lean](lean/Math0/Frontier/OEIS/A397315.lean) | +| 9 | [Schulte's alternating quadratic sum over the Schröder-peaks triangle (A060693)](results/oeis-a060693/README.md) | Discrete geometry | [`def statement`](lean/Math0/Statements/OEIS/A060693.lean) (math0, from OEIS A060693) | [A060693.lean](lean/Math0/Frontier/OEIS/A060693.lean) | +| 10 | [Erdős–Wetzel theorem: if ℵ₁ < 𝔠, families of entire functions with countably many values at each point are countable](results/erdos1119-erdos-1119-variants-erdos-wetzel/README.md) | Logic, Complex analysis | [`Erdos1119.erdos_1119.variants.erdos_wetzel`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1119.lean) | [Erdos1119_erdos_1119_variants_erdos_wetzel.lean](lean/Math0/ErdosProblems/Erdos1119_erdos_1119_variants_erdos_wetzel.lean) | +| 11 | [An odd n with a(n) > 1 and 2^n ≡ 2^{a(n)} (mod n), where a(n) is the largest prime exponent of n (OEIS A051903, Ordowski)](results/oeisa51903-conjecture3/README.md) | Number theory | [`OeisA51903.conjecture3`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/OEIS/51903.lean) | [OeisA51903_conjecture3.lean](lean/Math0/OEIS/OeisA51903_conjecture3.lean) | +| 12 | [Erdős Problem 1000: φ_A(k)/n_k does not tend to 0](results/erdos1000-erdos-1000-variants-not-tendsto-zero/README.md) | Number theory | [`Erdos1000.erdos_1000.variants.not_tendsto_zero`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1000.lean) | [Erdos1000_erdos_1000_variants_not_tendsto_zero.lean](lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_not_tendsto_zero.lean) | +| 13 | [Müller's set avoids sums equal to powers of two and has density 1/2 (Erdős 1136)](results/erdos1136-erdos-1136-variants-mueller/README.md) | Number theory | [`Erdos1136.erdos_1136.variants.mueller`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1136.lean) | [Erdos1136_erdos_1136_variants_mueller.lean](lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_mueller.lean) | +| 14 | [No odd n with a(n) > 1 has b^n ≡ b^{a(n)} (mod n) for all b (OEIS A051903)](results/oeisa51903-conjecture2/README.md) | Number theory | [`OeisA51903.conjecture2`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/OEIS/51903.lean) | [OeisA51903_conjecture2.lean](lean/Math0/OEIS/OeisA51903_conjecture2.lean) | +| 15 | [Sets avoiding sums equal to powers of two have lower density at most 1/2 (Müller)](results/erdos1136-erdos-1136-variants-upper-bound/README.md) | Number theory | [`Erdos1136.erdos_1136.variants.upper_bound`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1136.lean) | [Erdos1136_erdos_1136_variants_upper_bound.lean](lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_upper_bound.lean) | +| 16 | [Sieving [N] by half the classes mod 1000 primes below N^{9/10} can leave more than N/10 (Green's Problem 44 refuted as formalized)](results/green44-green-44/README.md) | Number theory | [`Green44.green_44`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/GreensOpenProblems/44.lean) | [Green44_green_44.lean](lean/Math0/GreensOpenProblems/Green44_green_44.lean) | +| 17 | [∑_{i=1..n} C(2n-i-1, i-1)/i is never an integer for n > 1 (A175385)](results/oeis-a175385/README.md) | Number theory | [`Math0.Statements.A175385.statement`](lean/Math0/Statements/OEIS/A175385.lean) (math0, from OEIS A175385) | [A175385.lean](lean/Math0/Frontier/OEIS/A175385.lean) | +| 18 | [Finite free Stam inequality in degree 2 (First Proof, Problem 4, n = 2): it holds with equality](results/arxiv-2602-05192-four-2/README.md) | Real analysis | [`Arxiv.«2602.05192».four_2`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/2602.05192/FirstProof4.lean) | [Arxiv_2602_05192_four_2.lean](lean/Math0/Arxiv/Arxiv_2602_05192_four_2.lean) | + +## Misformalization found (upstream statement does not match the problem) + +| # | Result | Area | Upstream statement | Lean | +|---|---|---|---|---| +| 1 | [Erdős 319: no constant answer works for every N (formalization defect)](results/erdos319-erdos-319/README.md) | Combinatorics | [`Erdos319.erdos_319`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/319.lean) | [Erdos319_erdos_319.lean](lean/Math0/ErdosProblems/Erdos319_erdos_319.lean) | +| 2 | [A sequence with ratio floor 1 + c/log n that is dense mod 1 for every irrational (Bugeaud 10.6, ratio reading)](results/bugeaud06-problem-10-6-variant-1/README.md) | Number theory | [`Bugeaud06.problem_10_6_variant_1`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_6.lean) | [Bugeaud06_problem_10_6_variant_1.lean](lean/Math0/Books/Bugeaud06_problem_10_6_variant_1.lean) | +| 3 | [Erdős 1180, "optimal" variant: false as stated (C_ε grows exponentially in 1/ε, because the constant must cover all primes)](results/erdos1180-erdos-1180-variants-optimal/README.md) | Number theory | [`Erdos1180.erdos_1180.variants.optimal`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1180.lean) | [Erdos1180_erdos_1180_variants_optimal.lean](lean/Math0/ErdosProblems/Erdos1180_erdos_1180_variants_optimal.lean) | +| 4 | [Erdős 142 (Θ variant): no k-independent order of magnitude for r_k(N)](results/erdos142-erdos-142-variants-istheta/README.md) | Number theory | [`Erdos142.erdos_142.variants.isTheta`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/142.lean) | [Erdos142_erdos_142_variants_isTheta.lean](lean/Math0/ErdosProblems/Erdos142_erdos_142_variants_isTheta.lean) | +| 5 | [Erdős 142: no single k-independent asymptotic formula for r_k(N)](results/erdos142-erdos-142/README.md) | Number theory | [`Erdos142.erdos_142`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/142.lean) | [Erdos142_erdos_142.lean](lean/Math0/ErdosProblems/Erdos142_erdos_142.lean) | +| 6 | [Erdős 409(i): no constant iteration count works for every starting value (formalization defect)](results/erdos409-erdos-409-parts-i/README.md) | Number theory | [`Erdos409.erdos_409.parts.i`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/409.lean) | [Erdos409_erdos_409_parts_i.lean](lean/Math0/ErdosProblems/Erdos409_erdos_409_parts_i.lean) | diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index c5812ff..6787b5c 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ its own repository and is listed below. | [covering-min-modulus](https://github.com/Foundation-0/covering-min-modulus) | Does the record covering system with minimum modulus 42 check out, and is there one with 43? | Not started. | | [gfq-codes](https://github.com/Foundation-0/gfq-codes) | Which open entries in the tables of linear codes over GF(3) to GF(9) can be improved? | Not started. | | [rigid-realizations](https://github.com/Foundation-0/rigid-realizations) (with [physics0](https://github.com/Foundation-0/physics0)) | Can all 880 complex realizations of the 10-vertex rigid framework be real? | Not started. | +| [Lean-verified results](RESULTS.md) (in this repository: `lean/`, `results/`) | Which neglected OEIS conjectures, and which statements in formal-conjectures, can be settled with proofs checked by the Lean kernel? | Formally verified (Lean kernel); manuscripts not peer reviewed. | ## How results are checked in every project diff --git a/RESULTS.md b/RESULTS.md new file mode 100644 index 0000000..24fc882 --- /dev/null +++ b/RESULTS.md @@ -0,0 +1,251 @@ +# math0 results + +**Mathematics produced by Claude and checked by the Lean kernel.** This is one of the projects listed in +math0's [README](README.md). + +math0 is a collection of mathematical results produced by Claude, an AI model developed by +Anthropic. It adds one rule that natural-language manuscripts cannot meet on their own: + +> A result is listed here only if a complete Lean 4 proof of it exists, compiled against +> Mathlib, using no axioms beyond `propext`, `Classical.choice` and `Quot.sound`, **and the +> statement it proves either was written by someone else, or was formalized by math0 and frozen +> before the proof, and is shown next to its source text.** + +Two kinds of statement are used (see [Two tracks](#two-tracks)): + +* **Written by someone else** (the formal-conjectures track). These come from Google DeepMind's + [formal-conjectures](https://github.com/google-deepmind/formal-conjectures) repository, a public, + independently curated collection of formalized open problems: Erdős problems, Ben Green's 100 + open problems, OEIS conjectures, Wikipedia lists, problems from papers and books. math0 imports + that repository at a pinned commit. Each math0 proof states its theorem as *the type of the + upstream declaration* and is checked against it syntactically, so it cannot quietly prove an + easier statement than the one the problem's curators wrote down. +* **Formalized by math0** (the frontier track). Here math0 writes the statement itself, from a + conjecture in an OEIS entry. Its definitions are checked by the kernel against the OEIS data, + but its fidelity to the OEIS text rests on a separate reviewing agent and on you. So every + result page quotes the OEIS conjecture next to the formal statement, each statement is frozen by + hash before the proof, and CI rejects any change to a frozen statement. + +## Highlights + + +**153 verified results.** 74 new results, 55 first formal proofs of known results, 18 independent formal proofs, 6 misformalization reports. Full list: [CONTENTS.md](CONTENTS.md). + +New results: OEIS conjectures settled, each checked by the Lean kernel, with no earlier proof or counterexample found by an independent novelty referee. An independent assessor judged the difficulty of each of these: 0 substantial and 74 routine (a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search). Most of these conjectures had stayed open for lack of attention, not because they were hard; each result page gives the assessor's reasons. + +* [3 × 3 lower triangles with neighbours differing by at most two: a(n) = 1047 n - 1459 for n > 2 (A195249)](results/oeis-a195249/README.md) ([paper](results/oeis-a195249/paper.pdf)) +* [3^(3^18) + 2 is divisible by 31^2, so Hilliard's squarefree conjecture (A083020) fails](results/oeis-a083020/README.md) ([paper](results/oeis-a083020/paper.pdf)) +* [A090905: every row ends at twice the largest prime of the previous row (Murthy's conjecture proved)](results/oeis-a090905/README.md) ([paper](results/oeis-a090905/paper.pdf)) +* [A106505: common sides of A/2A primitive triangles are periodic mod 8, so a(n+5) = a(n) + 8](results/oeis-a106505/README.md) ([paper](results/oeis-a106505/paper.pdf)) +* [A123710: the rows of inv(floor(n/k)) with four nonzero entries are 6 and the proper prime powers](results/oeis-a123710/README.md) +* [A126127: Israel's conjectured bivariate g.f. of the inverse square of A061554 holds](results/oeis-a126127/README.md) +* [A127752 mod 2 is the first Feigenbaum symbolic sequence A035263](results/oeis-a127752/README.md) ([paper](results/oeis-a127752/paper.pdf)) +* [A144637: (1/18) 6^n a(n)/n! is odd iff n = 2^k with k >= 1](results/oeis-a144637/README.md) +* [A172164: the second differences of the Theodorus-spiral turns are always 18, 19, 20 or 21](results/oeis-a172164/README.md) ([paper](results/oeis-a172164/paper.pdf)) +* [A178295: collinear 4-subsets of {0,...,4}^n number 9^n/2 + 3*7^n/2 - 2*5^n (Mathar's conjecture, all three formulas)](results/oeis-a178295/README.md) ([paper](results/oeis-a178295/paper.pdf)) +* [A223395: walks on the 4 x 4 grid graph satisfy Hardin's recurrence, Barker's g.f. and closed form](results/oeis-a223395/README.md) ([paper](results/oeis-a223395/paper.pdf)) +* [A249151(k) = k exactly when k + 1 is prime (Karttunen's conjecture, A249434/A249151)](results/oeis-a249434/README.md) ([paper](results/oeis-a249434/paper.pdf)) +* [A275815: Jones's conjecture a(n) = 8(n-2)^2 for n >= 6 holds](results/oeis-a275815/README.md) +* [A308107: Barker's rational generating function and order-15 recurrence for the sum of smallest sides of scalene integer triangles](results/oeis-a308107/README.md) ([paper](results/oeis-a308107/paper.pdf)) +* [A308121: for odd n > 1, row 2n is row n with its halves swapped](results/oeis-a308121/README.md) ([paper](results/oeis-a308121/paper.pdf)) +* [A332010: the average first letter of one-descent derangements has denominator 2^(n-2)](results/oeis-a332010/README.md) ([paper](results/oeis-a332010/paper.pdf)) +* [A334595: a(n) = 1 iff n is a power of two, and the records occur exactly at 1 and 2^k + 1](results/oeis-a334595/README.md) ([paper](results/oeis-a334595/paper.pdf)) +* [A338885: the smallest number in row 655 is 104, not A228286(655) = 115](results/oeis-a338885/README.md) ([paper](results/oeis-a338885/paper.pdf)) +* [A342645: diagonals of the eventual Mahonian-column polynomials](results/oeis-a342645/README.md) +* [A348484: no two squares two steps apart; the conjectured formula holds](results/oeis-a348484/README.md) ([paper](results/oeis-a348484/paper.pdf)) +* [A355339: the central even run of the knight-move triangle has length 1 iff n = 2^m - 2](results/oeis-a355339/README.md) ([paper](results/oeis-a355339/paper.pdf)) +* [A363609: a(k^3) = 6k(k+2), the cube is the optimal polycube of k^3 dice](results/oeis-a363609/README.md) ([paper](results/oeis-a363609/paper.pdf)) +* [A386538: moving the circle's center off the grid enlarges the max lattice polygon (counterexample at n = 7)](results/oeis-a386538/README.md) ([paper](results/oeis-a386538/paper.pdf)) +* [Alexandersson's recurrence for the row polynomials of A395454 holds (rows counted from 1)](results/oeis-a395454/README.md) ([paper](results/oeis-a395454/paper.pdf)) +* [Bar tilings of the smallest-perimeter rectangle: a(n+1) = 4 a(n) for odd n >= 3 (A394981)](results/oeis-a394981/README.md) ([paper](results/oeis-a394981/paper.pdf)) +* [Barker's order-20 recurrence for the lines through an 8 x n grid holds](results/oeis-a160848/README.md) ([paper](results/oeis-a160848/paper.pdf)) +* [Columns 1 and 2 of the theta-series triangle A355360 are P(x)^3 and 2P(x)^6](results/oeis-a355360/README.md) +* [Diagonal sums of A368846 equal A229580 (Luschny's conjecture)](results/oeis-a368846/README.md) +* [Domino towers of height 2 and of height n-1, n-2, n-3 (A333650): all four Kagey/Luschny conjectures](results/oeis-a333650/README.md) ([paper](results/oeis-a333650/paper.pdf)) +* [Even and odd legs with odd prime factors ≡ 3 (mod 4): a(n)/n → π (A354571, A354570)](results/oeis-a354571/README.md) ([paper](results/oeis-a354571/paper.pdf)) +* [Internal n-gons in a regular n-gon: triple points occur only for n = 3, 4, 6, and otherwise there are n k^2 + 1 regions (Shannon's A357216 conjecture)](results/oeis-a357216/README.md) ([paper](results/oeis-a357216/paper.pdf)) +* [Irwin's nested sums give column 0 of the triangle A132615 (A132616)](results/oeis-a132616/README.md) +* [Kagey's conjecture for A278212: a(n) = floor(A275815(n)/2), via exact bishop and queen maxima from flow (LP-dual) certificates](results/oeis-a278212/README.md) ([paper](results/oeis-a278212/paper.pdf)) +* [Kagey's order-10 recurrence for no-leaf subgraphs of the 5 × n grid holds](results/oeis-a320099/README.md) +* [Kurkov's recursion for the row polynomials of convolution triangles holds](results/oeis-a357583/README.md) +* [Kurkov's rook-tour conjecture for A001040: 2·n!·a(n) counts opposite-line Hamiltonian paths of K_n □ K_2](results/oeis-a001040/README.md) +* [Mathar's order-6 recurrence for A121750 (even-length columns in deco polyominoes) holds for all n >= 7](results/oeis-a121750/README.md) ([paper](results/oeis-a121750/paper.pdf)) +* [O'Sullivan's Gaussian-polynomial / Chebyshev representation conjecture (A267486), proved](results/oeis-a267486/README.md) +* [OEIS A350900: Schulte's gcd-ratio double sum is a Dirichlet convolution](results/oeis-a350900/README.md) ([paper](results/oeis-a350900/paper.pdf)) +* [Prime-Minesweeper on the A060734 array: a(n) < 6, and a(n) = 5 only at n = 6](results/oeis-a326407/README.md) ([paper](results/oeis-a326407/paper.pdf)) +* [Schulte's conjectures on A281000, T(n,k) = C(2n+1,2k+1)·Cat(n-k): antidiagonal sums and matrix inverse](results/oeis-a281000/README.md) ([paper](results/oeis-a281000/paper.pdf)) +* [Signed A350557 is the matrix inverse of A350512, proved](results/oeis-a350557/README.md) +* [Stephan's conjectured g.f. for A242396 is false (first failure at n = 97)](results/oeis-a242396/README.md) ([paper](results/oeis-a242396/paper.pdf)) +* [The Golomb-row triangle A113676 and Levine's sequence A014644](results/oeis-a113676/README.md) ([paper](results/oeis-a113676/paper.pdf)) +* [The generating function of A022445 (closed self-avoiding walks in the strip {0,1,2} x Z)](results/oeis-a022445/README.md) +* [The inverse of the 1/Catalan band triangle (A127767) has integer entries](results/oeis-a127767/README.md) ([paper](results/oeis-a127767/paper.pdf)) +* [The inverse of the triangle 1/n! [k ≤ n ≤ 2k] is an integer triangle](results/oeis-a127755/README.md) +* [The least number of inequivalent cells of a (6k+5)-iamond is 3(k+1)](results/oeis-a369366/README.md) ([paper](results/oeis-a369366/paper.pdf)) +* [The row sums of the generalized Deutsch triangle A188474 are A137398](results/oeis-a188474/README.md) +* [The row-LCM of denominators of the cube of the mean matrix is n · lcm(1..n)²](results/oeis-a119936/README.md) ([paper](results/oeis-a119936/paper.pdf)) +* [The subword complexity polynomial S(n,x) has leading coefficient n(n+1)/2 (A341761, Guo's conjecture)](results/oeis-a341761/README.md) ([paper](results/oeis-a341761/paper.pdf)) +* [The toothpick spiral around n hexagonal cells (A182617): a(n) = 2n + ceil(sqrt(12n - 3))](results/oeis-a182617/README.md) +* [The triple-gcd Pascal triangle A129455: T(n,k) is an integer, divisible by C(n,k), and T(n,k)/C(n,k) is a sixth power](results/oeis-a129455/README.md) ([paper](results/oeis-a129455/paper.pdf)) +* [A116184: Adamchuk's conjectures on 37^3 dividing the numerator of sum_{k=1}^{36} 1/k^n](results/oeis-a116184/README.md) ([paper](results/oeis-a116184/paper.pdf)) +* [A262957: Israel's b(n), c(n) are coprime integers and a(n) = b(n)](results/oeis-a262957/README.md) ([paper](results/oeis-a262957/paper.pdf)) +* [A356360: the continued-fraction denominators are 1 or prime](results/oeis-a356360/README.md) ([paper](results/oeis-a356360/paper.pdf)) +* [A375522: S2(n) - S1(n) = 1 fails at n = 42 (the difference is 5)](results/oeis-a375522/README.md) ([paper](results/oeis-a375522/paper.pdf)) +* [Convergents of [1; 1/2, 1/3, ..., 1/n]: numerator + denominator = 2^(v2(n!) + v2((n+1)!)) (A092054)](results/oeis-a092054/README.md) ([paper](results/oeis-a092054/paper.pdf)) +* [Imaginary parts of the convergents of [1+i; 1+i, 1+i, ...] are A317974(n+1)/A138573(n)](results/oeis-a093726/README.md) ([paper](results/oeis-a093726/paper.pdf)) +* [OEIS A362086: every denominator of 1/(2-3/(3-4/(...(n-1)-n/(-3)))) except 9 is 1 or a prime](results/oeis-a362086/README.md) ([paper](results/oeis-a362086/paper.pdf)) +* [OEIS A363482: apart from 49, every denominator of 1/(2-3/(3-4/(...(n-1)-n/(-5)))) is 1 or a prime](results/oeis-a363482/README.md) ([paper](results/oeis-a363482/paper.pdf)) +* [Repunit residues: a(n) = n - 1 exactly for long period primes](results/oeis-a335012/README.md) ([paper](results/oeis-a335012/paper.pdf)) +* [Zeros of a(3n) for the signed Stern sequence A005590 are exactly the fibbinary numbers](results/oeis-a005590/README.md) ([paper](results/oeis-a005590/paper.pdf)) +* [A326602: a(n) is odd iff n is a square](results/oeis-a326602/README.md) ([paper](results/oeis-a326602/paper.pdf)) +* [A351743: from n = 139 the sequence is affine in 42-blocks, which proves Sycamore's, Sigrist's and the A355149 conjectures](results/oeis-a351743/README.md) ([paper](results/oeis-a351743/paper.pdf)) +* [A386655 modulo 6 is eventually periodic with pattern [1, 0, 3, 0, 3, 2]](results/oeis-a386655/README.md) ([paper](results/oeis-a386655/paper.pdf)) +* [Every n not divisible by 5 has a multiple with only prime digits (A342992)](results/oeis-a342992/README.md) ([paper](results/oeis-a342992/paper.pdf)) +* [Lang's conjecture a(n) = A250400(n+1)/(n+1) for A294512 fails at n = 164](results/oeis-a294512/README.md) ([paper](results/oeis-a294512/paper.pdf)) +* [Odd descending-by-2 multiples exist exactly when 125 does not divide 2n+1 (A062887)](results/oeis-a062887/README.md) ([paper](results/oeis-a062887/paper.pdf)) +* [Odd terms of A323695 occur only at n = k(k+2)](results/oeis-a323695/README.md) ([paper](results/oeis-a323695/paper.pdf)) +* [The 1089-trick map has two 9-digit fixed points (A393794 uniqueness conjecture is false)](results/oeis-a393794/README.md) ([paper](results/oeis-a393794/paper.pdf)) +* [The only fixed points of reverse(x) - maxdigit(x) are 0 and 89](results/oeis-a097154/README.md) ([paper](results/oeis-a097154/paper.pdf)) +* [There are no 5-Rotation Cycle Primes (A086004, Conjecture 2)](results/oeis-a086004/README.md) ([paper](results/oeis-a086004/paper.pdf)) +* [Yanev's identity for A073642 (sum of the positions of the 1-bits)](results/oeis-a073642/README.md) ([paper](results/oeis-a073642/paper.pdf)) + + +## Two tracks + +1. **Third-party statements.** Proofs of statements in formal-conjectures, checked against the + upstream declaration with no possibility of restating the goal. +2. **The neglected frontier.** The curated lists (Erdős problems, Green's list, formal-conjectures) + are now swept continuously by several groups and automated reviewers. The referees in our first + track kept finding that "open" items had been settled weeks earlier. So math0 also mines + material almost nobody revisits: conjectures that OEIS contributors left in sequence entries, + in the "unglamorous" corners of number theory and geometry. These include patterns in series, + awkward fractions (Egyptian fractions, odd continued fractions, harmonic-number denominators) + and irregular shapes (lattice polygons, integer triangles, grid configurations). + Each such statement is formalized by one agent, with its definitions checked by the kernel + against the OEIS data. A second agent then reviews it for fidelity to the OEIS text and freezes + it (by hash) before a third agent attempts a proof or counterexample, which is checked with + `#math0_settles`. + + Frozen statements are listed in + [`lean/Math0/Statements/FROZEN.sha256`](lean/Math0/Statements/FROZEN.sha256), and CI enforces + three rules. Each file must still match its hash. The list is append-only: a frozen line can + never be edited or removed, even together with its statement. And from 26 October 2026, each + new statement is committed, in its own commit, before the proof that settles it, so the order + is visible in the git history and the statement can be reviewed on its own. The statements + frozen before that date were committed together with their proofs; they are listed in + [`FROZEN_WITH_PROOF.txt`](lean/Math0/Statements/FROZEN_WITH_PROOF.txt), and for them the + freeze order is recorded only in the pipeline's logs. Statements that are frozen but not yet + settled are compiled by CI too, through + [`lean/Math0/Statements.lean`](lean/Math0/Statements.lean). + + Whether each statement says what its OEIS author meant is a judgement, not a machine check. Every + statement has therefore had two agent reviews: one before it was frozen, and one adversarial pass + (29 Oct 2026) that produced [review packets](review/fidelity/README.md) of ten statements each, + quoting the OEIS text beside the Lean statement. The packets are meant to make human review + quick; they are not a substitute for it. + +## Why verification first + +Proof-shaped text is cheap to produce and expensive to check, whether a human or a model wrote +it. Large collections of AI-generated manuscripts already have to issue withdrawals when referees +find gaps. math0 treats the kernel-checked proof as the deliverable and the manuscript as +commentary on it. If the Lean proof compiles and the audit passes, the theorem holds; the +manuscript only explains why. + +## What every result carries + +| Artifact | Where | +|---|---| +| Lean proof of the exact upstream statement | [`lean/Math0/`](lean/Math0) | +| Machine audit (statement match + axiom whitelist) | last line of every Lean file, re-run by CI | +| Classification after adversarial review | [`CONTENTS.md`](CONTENTS.md), [`catalog.json`](catalog.json) | +| Human-readable manuscript (LaTeX + PDF) | `results//` | + +Results are classified honestly, after independent referees have tried to refute them: + +* **New result (conjecture settled; no earlier resolution found):** the conjecture was stated as + open in its source, the formal statement is faithful, the proof settles it, and an independent + novelty referee found no earlier proof or counterexample. This says nothing about difficulty: + many of the OEIS conjectures settled here yield to short, elementary arguments, and some + counterexamples refute the conjecture only as literally stated. The result pages say so where + it applies. +* **First formal proof of a known result:** the mathematics was known, but no machine-checked + proof of it existed. +* **Independent formal proof:** a Lean proof of an implying statement already exists elsewhere. + It is listed for completeness, not as a contribution. +* **Misformalization found:** the upstream statement can be settled for a reason unrelated to the + intended mathematics (a degenerate case, a missing hypothesis). That is not a solution of the + problem. It is reported so that the statement can be fixed upstream. + +## How the audit works + +[`lean/Math0/Audit.lean`](lean/Math0/Audit.lean) defines the commands that end every result +file: + +```lean +#math0_proves Math0.Erdos10.erdos_10_grechuk_example Erdos10.erdos_10.variants.grechuk_example +#math0_refutes ... -- our theorem's type must be exactly `¬ (upstream type)` +#math0_answers ... -- value questions: upstream `X.answer` replaced by an explicit value +#math0_refutes_every_answer ... -- misformalized value questions: false for every possible answer +#math0_settles ... -- frontier track: proves or refutes a frozen math0 statement (a sorry-free Prop) +``` + +Each command fails the build unless: + +1. the type of our theorem is syntactically identical to the upstream statement, or to its + negation (up to metadata only, with no unfolding); and +2. `Lean.collectAxioms` reports nothing beyond `propext`, `Classical.choice` and `Quot.sound`. + This rejects `sorry`, `native_decide` (`Lean.ofReduceBool`) and any custom axiom. + +CI ([`.github/workflows/lean.yml`](.github/workflows/lean.yml)) runs on every push and pull +request. It uses no build cache other than Mathlib's prebuilt oleans, so every math0 module (and +every formal-conjectures module it imports) is elaborated and checked by the kernel again, never +replayed. It then checks that exactly one statement check ran per catalogue entry, checks the +frozen statements ([`scripts/check_freeze.py`](scripts/check_freeze.py)), and runs the audit's +own tests in [`tests/audit/`](tests/audit): files that the audit must reject (a `sorry`, +`native_decide`, a custom axiom, a weaker or merely definitionally equal statement, a statement +hiding a `sorry`, the wrong polarity) and a file it must accept. A weekly workflow +([`kernel-replay.yml`](.github/workflows/kernel-replay.yml)) also replays every declaration of +every math0 module through the kernel with `leanchecker`, and runs the independent +[axiom-audit](https://github.com/leanprover-community/axiom-audit). Locally: + +```sh +scripts/verify.sh --clean # needs elan; fetches the Mathlib cache and rebuilds every result +scripts/test_audit.sh # the audit's own tests +``` + +## How the results were produced + +All mathematics and Lean code here was produced by Claude running in Claude Code, orchestrated as +multi-agent workflows: + +1. **Triage.** Every one of the 2,787 open or unproven research statements in formal-conjectures + was read and scored for tractability. Statements that can be "solved" vacuously (for example + by restating the question as its own answer) were flagged and excluded. +2. **Prove.** For each selected statement, a solver agent works out the mathematics and then + iterates against the Lean compiler until the proof is complete and the audit passes. +3. **Referee.** Independent agents try to refute every claimed proof. They recompile it, check + for forbidden constructs and modified dependencies, judge whether the formal statement is + faithful to the intended problem, and, for open problems, search the literature for prior + resolutions. + +Human review of the manuscripts is welcome. Please open an issue for any error, including a +misclassification. + +## Layout + +``` +README.md the math0 hub +RESULTS.md this file +CONTENTS.md catalogue of results (generated from catalog.json) +catalog.json machine-readable list of every claim math0 makes +history.md release log +results// per-result README, manuscript (paper.tex, paper.pdf), citation +lean/ Lake project: Math0/Audit.lean, Math0//.lean +scripts/ verify.sh, test_audit.sh, check_freeze.py, gen_contents.py, gen_root.py +tests/audit/ files the audit must reject (fail/) or accept (pass/) +``` + +## License + +Lean code and scripts: Apache-2.0. Manuscripts and documentation: CC-BY-4.0. Statements imported +from formal-conjectures remain under their original licenses. diff --git a/catalog.json b/catalog.json new file mode 100644 index 0000000..7c1fe10 --- /dev/null +++ b/catalog.json @@ -0,0 +1,4221 @@ +{ + "formal_conjectures_commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "results": [ + { + "id": "Arxiv/0805.3777/TensorRank::isMaxRank_le_two_mul_isGenericRank", + "slug": "arxiv-0805-3777-ismaxrank-le-two-mul-isgenericrank", + "title": "Maximal tensor rank is at most twice the generic rank (Blekherman–Teitler)", + "area": "Algebraic geometry, Linear algebra", + "source": "arXiv:0805.3777", + "source_url": "https://arxiv.org/abs/0805.3777", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/Arxiv/0805.3777/TensorRank.lean", + "decl": "Arxiv.«0805.3777».isMaxRank_le_two_mul_isGenericRank", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Arxiv/Arxiv_0805_3777_isMaxRank_le_two_mul_isGenericRank.lean", + "our_decl": "Math0.Arxiv.«0805.3777».isMaxRank_le_two_mul_isGenericRank", + "summary": "Let ds be any list of dimensions, and consider complex tensors (Holor ℂ ds) with the product topology on HolorIndex ds → ℂ. Suppose r is a generic rank: there is an open dense set U of tensors, all of CP rank exactly r. Suppose R is the maximal rank: R is the largest CP rank of any tensor of format ds. Then R ≤ 2r. This is [BT15, Theorem 1] (Blekherman–Teitler), as formalized in formal-conjectures (FormalConjectures/Arxiv/0805.3777/TensorRank.lean).", + "notes": "The source is G. Blekherman and Z. Teitler, \"On maximum, typical and generic ranks\", Math. Ann. 362 (2015), 1021–1031, doi:10.1007/s00208-014-1150-3, arXiv:1402.2371, Theorem 1. It states that the maximum rank is at most twice the generic rank for any nondegenerate irreducible variety. The case here is the Segre variety, i.e. tensors. The upstream file is FormalConjectures/Arxiv/0805.3777/TensorRank.lean, which builds on Friedland, LAA 436 (2012), arXiv:0805.3777. It has no formal_proof link for this item, and I know of no earlier Lean proof.", + "date": "2026-10-17" + }, + { + "id": "Arxiv/1609.08688/sIncreasingrTuples::maximalLength_ge_of_isSquare", + "slug": "arxiv-1609-08688-maximallength-ge-of-issquare", + "title": "Gowers–Long lower bound: F(k²) ≥ k³ for 2-increasing sequences of triples", + "area": "Combinatorics", + "source": "arXiv:1609.08688", + "source_url": "https://arxiv.org/abs/1609.08688", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/Arxiv/1609.08688/sIncreasingrTuples.lean", + "decl": "Arxiv.«1609.08688».maximalLength_ge_of_isSquare", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_ge_of_isSquare.lean", + "our_decl": "Math0.Arxiv.«1609.08688».maximalLength_ge_of_isSquare", + "summary": "Say that a triple a = (a_1,a_2,a_3) is 2-less than b = (b_1,b_2,b_3) if a_i < b_i for at least two coordinates i. A finite sequence of triples is 2-increasing if every earlier term is 2-less than every later term. Let F(n) be the largest length of a 2-increasing sequence of triples with all coordinates in {1,...,n}. (Formally, F(n) is the sSup in ℕ of the set of such lengths.) If n is a perfect square then (√n)^3 ≤ F(n), i.e. F(k^2) ≥ k^3 for every natural number k.", + "notes": "The source is W. T. Gowers and J. Long, \"The length of an s-increasing sequence of r-tuples\", arXiv:1609.08688, published in Combinatorics, Probability and Computing 30 (2021), 686–721. Proposition 1.4 states F(n) ≤ n^2 for all n, and F(n) ≥ n^{3/2} when n is a perfect square, using the lexicographic construction of triples ((a,b),(a,c),(b,c)). The result is known and elementary. In formal-conjectures, both the pinned checkout and the latest upstream HEAD (d9ce556, 2026-10-17) still leave `maximalLength_ge_of_isSquare` as `sorry`. The upper bound `maximalLength_le` is already proved upstream. I found no existing Lean proof of the lower bound.", + "date": "2026-10-17" + }, + { + "id": "Arxiv/1609.08688/sIncreasingrTuples::maximalLength_pow", + "slug": "arxiv-1609-08688-maximallength-pow", + "title": "Supermultiplicativity of F gives arbitrarily large m with F(m) ≥ m^α (Gowers–Long)", + "area": "Combinatorics", + "source": "arXiv:1609.08688", + "source_url": "https://arxiv.org/abs/1609.08688", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/Arxiv/1609.08688/sIncreasingrTuples.lean", + "decl": "Arxiv.«1609.08688».maximalLength_pow", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_pow.lean", + "our_decl": "Math0.Arxiv.«1609.08688».maximalLength_pow", + "summary": "Let F(n) be the largest length of a sequence of triples in {1,…,n}^3 that is 2-increasing: every earlier triple is strictly smaller than every later one in at least two of the three coordinates. Let n > 1 be a natural number and e a real number with F(n) = n^e. Then (m : ℝ)^e ≤ F(m) for arbitrarily large natural numbers m, i.e. ∃ᶠ m in atTop.", + "notes": "W. T. Gowers and J. Long, \"The length of an s-increasing sequence of r-tuples\", arXiv:1609.08688; Combinatorics, Probability and Computing 30 (2021), 686–721. Section 1 notes that F is supermultiplicative, F(mn) ≥ F(m)F(n), using the lexicographic product of sequences. So F(n) = n^α implies F(n^k) ≥ n^{αk}, which gives arbitrarily large m with F(m) ≥ m^α. This is the upstream statement `maximalLength_pow`, which is tagged \"research solved\" and was proved upstream only by sorry. I found no existing Lean formalization.", + "date": "2026-10-17" + }, + { + "id": "Arxiv/2602.05192/FirstProof4::four_2", + "slug": "arxiv-2602-05192-four-2", + "title": "Finite free Stam inequality in degree 2 (First Proof, Problem 4, n = 2): it holds with equality", + "area": "Real analysis", + "source": "arXiv:2602.05192", + "source_url": "https://arxiv.org/abs/2602.05192", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/Arxiv/2602.05192/FirstProof4.lean", + "decl": "Arxiv.«2602.05192».four_2", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/Arxiv/Arxiv_2602_05192_four_2.lean", + "our_decl": "Math0.Arxiv.«2602.05192».four_2", + "summary": "Let p and q be monic real polynomials of degree 2, each having 2 real roots counted with multiplicity. Let p ⊞_2 q be their finite additive convolution, Σ_{k=0}^{2} c_k x^{2-k} with c_k = Σ_{i+j=k} (2-i)!(2-j)!/(2!(2-k)!) a_i b_j, where a_i and b_j are the coefficients of x^{2-i} in p and x^{2-j} in q. For a monic polynomial with simple roots λ_1,…,λ_n, set Φ_n(p) = Σ_i (Σ_{j≠i} 1/(λ_i-λ_j))^2, and set Φ_n(p) = ∞ when p has a repeated root. Then, in [0,∞], 1/Φ_2(p) + 1/Φ_2(q) ≤ 1/Φ_2(p ⊞_2 q). In fact equality always holds.", + "notes": "The problem is First Proof (Abouzaid, Blumberg, Hairer, Kileel, Kolda, Nelson, Spielman, Srivastava, Ward, Weinberger, Williams), arXiv:2602.05192v2, Problem 4: the finite free Stam / harmonic-mean inequality for ⊞_n. ⊞_n is the finite free additive convolution of Marcus–Spielman–Srivastava (\"Finite free convolutions of polynomials\"; \"Interlacing families II\"). The general statement was answered affirmatively by the First Proof solutions. It was formalized in Lean 4 by FrenzyMath's Archon in the repository frenzymath/Archon-FirstProof-Results, file FirstProof/FirstProof4/Problem4.lean, theorem harmonic_mean_inequality_full, for all n ≥ 2 with zero sorrys according to its README. Upstream links that file as `formal_proof` on `four`. The n = 2 case is an elementary identity: ⊞_2 adds discriminants (second cumulants), so equality holds.", + "date": "2026-10-17" + }, + { + "id": "Arxiv/2605.12342/Conjecture1::conjecture_1.variants.rank_3_3", + "slug": "arxiv-2605-12342-conjecture-1-variants-rank-3-3", + "title": "Γ_{3⊕3} (equal-sign pairs in S₃ × S₃) is not 2-generated", + "area": "Group theory", + "source": "arXiv:2605.12342", + "source_url": "https://arxiv.org/abs/2605.12342", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/Arxiv/2605.12342/Conjecture1.lean", + "decl": "Arxiv.«2605.12342».conjecture_1.variants.rank_3_3", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Arxiv/Arxiv_2605_12342_conjecture_1_variants_rank_3_3.lean", + "our_decl": "Math0.Arxiv.«2605.12342».rank_3_3", + "summary": "Let Γ = Γ_{3⊕3} = {(σ₁, σ₂) ∈ S₃ × S₃ : sgn σ₁ = sgn σ₂}. In the formal statement Γ is the kernel of (σ₁,σ₂) ↦ sgn σ₁ · sgn σ₂⁻¹. For all h₁, h₂ ∈ Γ, the subgroup of Γ generated by {h₁, h₂} is not all of Γ. So Γ is not 2-generated, which is the rank-3 claim Fernandes records in arXiv:2605.12342.", + "notes": "V. H. Fernandes, \"Groups of permutations that are even on maximal proper subsets, and related monoids\", arXiv:2605.12342 (2026). It states, as a GAP computation, that Γ3⊕3, Γ4⊕3 and Γ4⊕4 are not 2-generated, so rank(Γ3⊕3) = 3, and gives Conjecture 1 for all other (m, n). It also follows from elementary group theory: Γ3⊕3 is the generalized dihedral group Dih(C3×C3), and any 2-generated subgroup of it has order at most 9. Existing Lean work: K. Kitamura, github.com/KitaKen1/fernandes-conjecture-1-lean, proves only the main conjecture_1 (the non-exceptional cases are 2-generated), not the rank-3 exceptions. Upstream formal-conjectures main (checked 2026-10-17) still has `sorry` for conjecture_1.variants.rank_3_3.", + "date": "2026-10-17" + }, + { + "id": "Arxiv/math.0608009/PoissonConjecture::poisson_conjecture.variants.dimension_three", + "slug": "arxiv-math-0608009-poisson-conjecture-variants-dimension-three", + "title": "The Poisson conjecture fails in dimension three", + "area": "Algebraic geometry, Nonassociative algebra", + "source": "arXiv:math.0608009", + "source_url": "https://arxiv.org/abs/math.0608009", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/Arxiv/math.0608009/PoissonConjecture.lean", + "decl": "Arxiv.«math.0608009».poisson_conjecture.variants.dimension_three", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_dimension_three.lean", + "our_decl": "Math0.Arxiv.«math.0608009».poisson_conjecture_dimension_three", + "summary": "Let K be a field of characteristic zero and P_3(K) = K[x_1,x_2,x_3,y_1,y_2,y_3] with the canonical Poisson bracket {f,g} = sum_i (d_{x_i} f d_{y_i} g - d_{y_i} f d_{x_i} g). Then some K-algebra endomorphism phi of P_3(K) is not bijective even though it preserves the bracket on generators ({phi(v), phi(w)} = {v, w} for all variables v, w). So PC_3 (every Poisson endomorphism of P_3(K) is an automorphism) is false. Formally: for every field K with CharZero K, ¬ PoissonConjectureFor K 3.", + "notes": "[AvdE07] K. Adjamagbo and A. van den Essen, arXiv:math/0608009, Acta Math. Vietnam. 32 (2007): defines PC_n (Notations 5), Lemma 2 (preserving brackets on generators suffices), and Theorem 7 (JC_{2n} ⇒ PC_n ⇒ DC_n ⇒ JC_n). [Alp26] L. Alpöge (2026): counterexample to the Jacobian conjecture in dimension 3. The upstream formal-conjectures file FormalConjectures/Wikipedia/JacobianConjecture.lean formalizes a variant G with Jacobian determinant 1 that is not injective (det_jacobian_G, aeval_G_eq). Upstream FormalConjectures/Arxiv/math.0608009/PoissonConjecture.lean marks dimension_three as \"research solved\" with a sorry proof, no formal_proof link, and a docstring describing exactly this cotangent-lift argument. [Lon26] C. D. Long, arXiv:2608.23777, settles PC_2 and is not relevant to n=3.", + "date": "2026-10-17" + }, + { + "id": "Arxiv/math.0608009/PoissonConjecture::poisson_conjecture.variants.jacobian_implication", + "slug": "arxiv-math-0608009-poisson-conjecture-variants-jacobian-implication", + "title": "The Jacobian conjecture in dimension 2n implies the Poisson conjecture in dimension n", + "area": "Algebraic geometry, Nonassociative algebra", + "source": "arXiv:math.0608009", + "source_url": "https://arxiv.org/abs/math.0608009", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/Arxiv/math.0608009/PoissonConjecture.lean", + "decl": "Arxiv.«math.0608009».poisson_conjecture.variants.jacobian_implication", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_jacobian_implication.lean", + "our_decl": "Math0.Arxiv.«math.0608009».jacobian_implication", + "summary": "Let K be a field of characteristic zero and n a natural number. Suppose the Jacobian conjecture holds in 2n variables over K: every polynomial map F : K^{2n} -> K^{2n} whose Jacobian determinant is a unit of K[x_1,...,x_{2n}] has a polynomial two-sided compositional inverse. Then every K-algebra endomorphism phi of K[x_1..x_n, y_1..y_n] that preserves the canonical Poisson bracket {f,g} = sum_i (d_{x_i} f d_{y_i} g - d_{y_i} f d_{x_i} g) on the generators, i.e. {phi(X_v), phi(X_w)} = {X_v, X_w} for all v, w, is bijective. (Adjamagbo and van den Essen, arXiv math/0608009, Theorems 1 and 7.)", + "notes": "K. Adjamagbo and A. van den Essen, \"On the equivalence of the Jacobian, Dixmier and Poisson conjectures in any characteristic\", arXiv math/0608009, published as \"A proof of the equivalence of the Dixmier, Jacobian and Poisson conjectures\", Acta Math. Vietnam. 32 (2007) 205-214. Theorem 1 / Theorem 7 there state JC_{2n} ⇒ PC_n ⇒ DC_n ⇒ JC_n; JC_{2n} ⇒ PC_n is the step proved here. Related: Bass-Connell-Wright 1982 (DC_n ⇒ JC_n); Tsuchimoto and Belov-Kanel-Kontsevich (JC_{2n} ⇒ DC_n). Upstream records JC as false in dimension 3 (Alpöge 2026) and PC_2 as false (Long 2026), so the hypothesis here is false for n ≥ 2 and the case that still matters, JC_2 ⇒ PC_1, is nontrivial. Upstream has no formal_proof link for this item.", + "date": "2026-10-17" + }, + { + "id": "Books/BugeaudDistributionModuloOne/Problem10_6::problem_10_6_variant_1", + "slug": "bugeaud06-problem-10-6-variant-1", + "title": "A sequence with ratio floor 1 + c/log n that is dense mod 1 for every irrational (Bugeaud 10.6, ratio reading)", + "area": "Number theory", + "source": "Books / BugeaudDistributionModuloOne / Problem10_6", + "source_url": "", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_6.lean", + "decl": "Bugeaud06.problem_10_6_variant_1", + "category": "research open" + }, + "mode": "proves", + "classification": "misformalization", + "lean_file": "lean/Math0/Books/Bugeaud06_problem_10_6_variant_1.lean", + "our_decl": "Math0.Bugeaud06.problem_10_6_variant_1", + "summary": "There is a strictly increasing sequence m : ℕ → ℕ with two properties. First, it is \"genuinely sublacunary\": for some c > 0, m(n+1)/m(n) ≥ 1 + c/log n for all sufficiently large n. Second, for every irrational ξ, the points ξ·m(n) mod 1 are dense in ℝ/ℤ.", + "notes": "- **Ajtai, Havas, Komlós (1983):** M. Ajtai, I. Havas and J. Komlós, \"Every group admits a bad topology\", in Studies in Pure Mathematics (to the memory of P. Turán), Birkhäuser, Basel, 1983, pp. 21–34. For any ε_n → 0+ there are integers m_n with m_{n+1}/m_n > 1 + ε_n such that (ξ m_n) is uniformly distributed mod 1 for every irrational ξ. This implies `problem_10_6_variant_1`.\n- **Bugeaud (2012):** Y. Bugeaud, Distribution Modulo One and Diophantine Approximation, Cambridge Tracts in Mathematics 193.\n - The Chapter 2 notes (p. 45) cite the AHK result above.\n - Problem 10.6 is on p. 215; it was checked against the text of the book.\n- **Boshernitzan (1983):** M. D. Boshernitzan, Monatsh. Math. 96 (1983), 173–181. Bugeaud cites it as \"see also [121]\" for the AHK result.\n- **Formal Lean proofs:** none found, either in formal_conjectures or as a formal_proof link. Upstream has `formal_proof` links only for the growth and sparsity variants (rwst fork, commit 63c3e72). - Y. Bugeaud, Distribution Modulo One and Diophantine Approximation, Cambridge Tracts in Math. 193 (2012):\n - Problem 10.6 is on p. 215, after the remarks on Furstenberg's 2^n 3^m and on Pollington and de Mathan.\n - §2.8 Notes, p. 45, states the Ajtai–Havas–Komlós theorem: for any ε_n → 0 there is an integer sequence with m_{n+1}/m_n > 1 + ε_n that is u.d. mod 1 for every irrational ξ (\"see also [121]\").\n - PDF used: https://staff.dc.uba.ar/becher/aa/Bugeaud2012.pdf\n\n(Abridged; the manuscript discusses the literature in full.)", + "date": "2026-10-17" + }, + { + "id": "Books/BugeaudDistributionModuloOne/Problem10_8::problem_10_8.variants.quadratic", + "slug": "bugeaud08-problem-10-8-variants-quadratic", + "title": "The p-adic Littlewood conjecture for real quadratic irrationals", + "area": "Number theory", + "source": "Books / BugeaudDistributionModuloOne / Problem10_8", + "source_url": "", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_8.lean", + "decl": "Bugeaud08.problem_10_8.variants.quadratic", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Books/Bugeaud08_problem_10_8_variants_quadratic.lean", + "our_decl": "Math0.Bugeaud08.problem_10_8_quadratic", + "summary": "Let p be a prime and ξ a real number whose minimal polynomial over ℚ has degree 2. Then inf over integers q ≥ 1 of q · |q|_p · ‖qξ‖ is 0. Here ‖·‖ is the distance to the nearest integer, |·|_p is the p-adic absolute value, and the infimum is the real sInf of the set {q · padicNorm p q · distToNearestInt(qξ) : q ∈ ℕ, q ≥ 1}.", + "notes": "de Mathan, B. and Teulié, O., \"Problèmes diophantiens simultanés\", Monatshefte für Mathematik 143 (2004), 229–245. They proved the p-adic Littlewood conjecture for quadratic irrationals, in a stronger form with a log factor. The problem is stated as Problem 10.8 in Bugeaud, \"Distribution modulo one and Diophantine approximation\" (CUP, 2012), Chapter 10. The elementary Pell/units argument used here is the standard proof of the quadratic case. I found no prior Lean formalization: there is no formal_proof attribute on Bugeaud08.problem_10_8.variants.quadratic, nothing in Mathlib, and the related formal_conjectures statement LittlewoodConjecture.padic_littlewood_conjecture is open and sorried.", + "date": "2026-10-17" + }, + { + "id": "Books/BugeaudDistributionModuloOne/Problem10_9::problem_10_9.variants.dimH_lt_one", + "slug": "bugeaud09-problem-10-9-variants-dimh-lt-one", + "title": "The set of Mahler Z-numbers is countable, so its Hausdorff dimension is 0, which is less than 1", + "area": "Number theory", + "source": "Books / BugeaudDistributionModuloOne / Problem10_9", + "source_url": "", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_9.lean", + "decl": "Bugeaud09.problem_10_9.variants.dimH_lt_one", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Books/Bugeaud09_problem_10_9_variants_dimH_lt_one.lean", + "our_decl": "Math0.Bugeaud09.dimH_lt_one", + "summary": "A Z-number is a real ξ > 0 such that the fractional part {ξ (3/2)^n} lies in [0, 1/2) for every integer n ≥ 1. The set Z of all Z-numbers has Hausdorff dimension < 1, i.e. dimH {ξ : ℝ | IsZNumber ξ} < 1 in ℝ≥0∞. Flatto, Lagarias and Pollington (1995) proved this result, recorded in Bugeaud, Problem 10.9. We prove something stronger, going back to Mahler (1968): Z is countable, so dimH Z = 0.", + "notes": "Mahler, K. \"An unsolved problem on the powers of 3/2\", J. Austral. Math. Soc. 8 (1968) 313-321: shows each interval [k, k+1) contains at most one Z-number, so the set of Z-numbers is countable (hence of Lebesgue measure 0 and Hausdorff dimension 0). Flatto, Lagarias and Pollington, \"On the range of fractional parts {ξ(p/q)^n}\", Acta Arith. 70 (1995) 125-147, credited by the upstream docstring; for this particular set their result is weaker than Mahler's countability. Bugeaud, \"Distribution modulo one and Diophantine approximation\" (CUP 2012), Ch. 10, Problem 10.9. I know of no prior Lean formalization: the upstream formal_conjectures statement is `sorry` with no formal_proof link, and Mathlib has no Z-number results.", + "date": "2026-10-17" + }, + { + "id": "Books/BugeaudDistributionModuloOne/Problem10_9::problem_10_9.variants.measure_zero", + "slug": "bugeaud09-problem-10-9-variants-measure-zero", + "title": "Mahler's Z-numbers form a Lebesgue-null set", + "area": "Number theory", + "source": "Books / BugeaudDistributionModuloOne / Problem10_9", + "source_url": "", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_9.lean", + "decl": "Bugeaud09.problem_10_9.variants.measure_zero", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Books/Bugeaud09_problem_10_9_variants_measure_zero.lean", + "our_decl": "Math0.Bugeaud09.measure_zero", + "summary": "A Z-number is a real number ξ > 0 such that the fractional part {ξ (3/2)^n} lies in [0, 1/2) for every integer n ≥ 1. The set of Z-numbers has Lebesgue measure zero (Mahler 1968; Bugeaud, Distribution modulo one and Diophantine approximation, Problem 10.9, measure-zero variant). Formally: MeasureTheory.volume {ξ : ℝ | IsZNumber ξ} = 0.", + "notes": "K. Mahler, \"An unsolved problem on the powers of 3/2\", J. Austral. Math. Soc. 8 (1968) 313-321: at most one Z-number in each interval [k, k+1) (n ≥ 0 normalization), so Z-numbers are countable, with counting function O(x^0.7). This gives measure zero. Y. Bugeaud, Distribution Modulo One and Diophantine Approximation (CUP 2012), Ch. 10, Problem 10.9. Flatto–Lagarias–Pollington, Acta Arith. 70 (1995), is the source of the related dimH variant. I know of no earlier Lean formalization: the upstream formal-conjectures item is a `sorry` with no formal_proof link. I could not search GitHub because session access is limited to configured repositories.", + "date": "2026-10-17" + }, + { + "id": "Books/UniformDistributionOfSequences/Equidistribution::isAccumulationPoint_three_halves_pow_infinite", + "slug": "equidistribution-isaccumulationpoint-three-halves-pow-infinite", + "title": "The fractional parts of (3/2)^n have infinitely many accumulation points", + "area": "Number theory", + "source": "Books / UniformDistributionOfSequences / Equidistribution", + "source_url": "", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/Books/UniformDistributionOfSequences/Equidistribution.lean", + "decl": "Equidistribution.isAccumulationPoint_three_halves_pow_infinite", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Books/Equidistribution_isAccumulationPoint_three_halves_pow_infinite.lean", + "our_decl": "Math0.Equidistribution.isAccumulationPoint_three_halves_pow_infinite", + "summary": "Let r_n = {(3/2)^n} be the fractional part of (3/2)^n for n = 0, 1, 2, .... Call x an accumulation point of (r_n) if x lies in the closure of {r_n : n ∈ ℕ} \\ {x}. Then the set of accumulation points of (r_n) is infinite. (Vijayaraghavan's theorem, cited in Kuipers–Niederreiter, Uniform Distribution of Sequences, Ch. 1.)", + "notes": "T. Vijayaraghavan, \"On the fractional parts of the powers of a number\", J. London Math. Soc. 15 (1940), 159–160, proves that {(p/q)^n}, and in particular {(3/2)^n}, has infinitely many limit points. Kuipers & Niederreiter, Uniform Distribution of Sequences (1974), Ch. 1 notes cite it in the source referenced by the upstream file. Upstream google-deepmind/formal-conjectures (main, checked 2026-10-17) still has `sorry` for this theorem, and I know of no previous Lean proof.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/10::erdos_10.variants.grechuk_example", + "slug": "erdos10-erdos-10-variants-grechuk-example", + "title": "Grechuk's example: 1117175146 is not a prime plus at most three powers of two", + "area": "Combinatorics, Number theory", + "source": "Erdős Problem #10", + "source_url": "https://www.erdosproblems.com/10", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/10.lean", + "decl": "Erdos10.erdos_10.variants.grechuk_example", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos10_erdos_10_variants_grechuk_example.lean", + "our_decl": "Math0.Erdos10.erdos_10_grechuk_example", + "summary": "Let N = 1117175146. There is no prime p and no multiset of at most three natural numbers e_1, ..., e_k (k ≤ 3, repetitions allowed) with N = p + 2^{e_1} + ... + 2^{e_k}. Formally: 1117175146 ∉ sumPrimeAndTwoPows 3, where sumPrimeAndTwoPows k = { p + Σ_{e ∈ pows} 2^e : p prime, pows a multiset of naturals with card pows ≤ k }.", + "notes": "Sources:\n- erdosproblems.com/10: the problem is open; it records Bogdan Grechuk's observation that 1117175146 is not a prime plus at most 3 powers of 2, without showing how it was verified. The local problems.yaml lists problem 10 with status open and formalized \"yes\", with no Lean proof noted for this example.\n- Related references: Granville and Soundararajan (1998), the conjecture this example bears on for even integers; Crocker (1971), the infinitude construction.\n- The upstream formal_proof link for the infinite variant `erdos_10.variants.grechuk` (DaryxXx gist e112c74c…, Main.lean) does not contain 1117175146. The `two_pows` link is to anatoliiohorodnyk/lean-fc-proofs, whose (truncated) listing has no grechuk_example file.\n- A web search for \"1117175146\" with Lean found nothing.\n- Conclusion: the statement is known (a computational fact due to Grechuk), and this appears to be its first Lean formalization.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1000::erdos_1000.variants.limsup_eq_one", + "slug": "erdos1000-erdos-1000-variants-limsup-eq-one", + "title": "Erdős Problem 1000: liminf φ_A(k)/n_k = 0 forces limsup φ_A(k)/n_k = 1", + "area": "Number theory", + "source": "Erdős Problem #1000", + "source_url": "https://www.erdosproblems.com/1000", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1000.lean", + "decl": "Erdos1000.erdos_1000.variants.limsup_eq_one", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_limsup_eq_one.lean", + "our_decl": "Math0.Erdos1000.limsup_eq_one", + "summary": "Let n_0 < n_1 < n_2 < ... be a strictly increasing sequence of positive integers. Let φ_A(k) be the number of integers 1 ≤ m ≤ n_k such that n_k / gcd(m, n_k) divides no n_j with j < k. Put r_k = φ_A(k)/n_k. If liminf_{k→∞} r_k = 0, then limsup_{k→∞} r_k = 1. (Erdős [Er64b], recorded as erdosproblems.com/1000.)", + "notes": "The result is Erdős, P., \"Problems and results on diophantine approximations\", Compositio Math. 16 (1964), 52-65 [Er64b]: if liminf φ_A(k)/n_k = 0 then limsup φ_A(k)/n_k = 1. The function φ_A was introduced by Cassels, \"Some metrical theorems in Diophantine approximation. I\", Proc. Cambridge Philos. Soc. (1950) [Ca50b]. Cassels's existence result (liminf of the Cesàro averages equal to 0) shows the hypothesis can hold. Haight's PhD thesis [Ha] settled the main problem: the averages can tend to 0. The problem is erdosproblems.com/1000, listed as \"proved (Lean)\". That status refers to the main problem, whose existing formalization is https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1000.lean. That file covers only the main existence theorem, not the limsup_eq_one variant.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1000::erdos_1000.variants.not_tendsto_zero", + "slug": "erdos1000-erdos-1000-variants-not-tendsto-zero", + "title": "Erdős Problem 1000: φ_A(k)/n_k does not tend to 0", + "area": "Number theory", + "source": "Erdős Problem #1000", + "source_url": "https://www.erdosproblems.com/1000", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1000.lean", + "decl": "Erdos1000.erdos_1000.variants.not_tendsto_zero", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_not_tendsto_zero.lean", + "our_decl": "Math0.Erdos1000.not_tendsto_zero", + "summary": "Let n_0 < n_1 < n_2 < ... be a strictly increasing sequence of positive integers. Let φ_A(k) be the number of integers 1 ≤ m ≤ n_k such that n_k / gcd(m, n_k) divides none of the earlier terms n_j with j < k. Then φ_A(k)/n_k does not tend to 0 as k → ∞. (Erdős [Er64b], erdosproblems.com/1000.)", + "notes": "Erdős, Problems and results on diophantine approximations, Compositio Math. 1964 [Er64b], where Erdős proves that lim φ_A(k)/n_k ≠ 0 and that liminf = 0 forces limsup = 1. Cassels [Ca50b] introduced φ_A. Haight solved the main question. erdosproblems.com/1000 lists the problem as \"proved (Lean)\"; that formal proof (plby/lean-proofs src/v4.29.1/ErdosProblems/Erdos1000.lean) covers only Haight's main theorem. math0 had already committed a proof of upstream erdos_1000.variants.limsup_eq_one (lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_limsup_eq_one.lean), and this result follows from it directly.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1008::erdos_1008.variants.lower_bound", + "slug": "erdos1008-erdos-1008-variants-lower-bound", + "title": "Erdős Problem 1008: every graph with m edges has a C4-free subgraph with at least √m/2 edges", + "area": "Combinatorics", + "source": "Erdős Problem #1008", + "source_url": "https://www.erdosproblems.com/1008", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1008.lean", + "decl": "Erdos1008.erdos_1008.variants.lower_bound", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/ErdosProblems/Erdos1008_erdos_1008_variants_lower_bound.lean", + "our_decl": "Math0.Erdos1008.lower_bound", + "summary": "There is a constant c > 0 such that for every finite type V and every simple graph G on V, some subgraph H ≤ G contains no copy of the 4-cycle C4 and satisfies c · m^{1/2} ≤ |E(H)|, where m = |E(G)|. (Erdős, [Er71], called this bound \"trivial\" and asked for m^{2/3}.) We prove it with c = 1/2.", + "notes": "The source is Erdős [Er71], \"Some unsolved problems in graph theory and combinatorial analysis\" (1971), which notes that ≫ m^{1/2} is trivial and asks for m^{2/3}. The m^{2/3} bound was proved by Conlon, Fox and Sudakov [CFS14b], \"Large subgraphs without complete bipartite graphs\" (arXiv:1401.6711), and Hunter gave a simpler proof in the erdosproblems forum. The main statement is formalized in Lean at https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1008.lean (Aristotle / Boris Alexeev), with constant 1/2 and exponent 2/3, and erdosproblems.com lists 1008 as \"proved (Lean)\". The exponent-1/2 variant follows immediately from that formalized result. The folklore argument used here (max degree versus maximum matching, m ≤ 2Δν) is standard.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1010::erdos_1010.variants.rademacher", + "slug": "erdos1010-erdos-1010-variants-rademacher", + "title": "Rademacher's theorem: ⌊n²/4⌋+1 edges force ⌊n/2⌋ triangles", + "area": "Combinatorics", + "source": "Erdős Problem #1010", + "source_url": "https://www.erdosproblems.com/1010", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1010.lean", + "decl": "Erdos1010.erdos_1010.variants.rademacher", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/ErdosProblems/Erdos1010_erdos_1010_variants_rademacher.lean", + "our_decl": "Math0.Erdos1010.erdos_1010_rademacher", + "summary": "For every n ∈ ℕ and every simple graph G on the vertex set Fin n with exactly ⌊n²/4⌋ + 1 edges, G contains at least ⌊n/2⌋ triangles (3-cliques).", + "notes": "Rademacher (1941, unpublished, reported by Erdős): a graph with ⌊n²/4⌋+1 edges has at least ⌊n/2⌋ triangles. Erdős, \"On a theorem of Rademacher-Turán\", Illinois J. Math. 6 (1962) 122-127, proves t⌊n/2⌋ for t < cn. Lovász–Simonovits (1976) and Nikiforov–Khadzhiivanov, C. R. Acad. Bulgare Sci. (1981), settle the case t < ⌊n/2⌋ (erdosproblems #1010, status: proved). An existing Lean 4 formalization of the general statement, which implies this variant at t = 1, is plby/lean-proofs src/latest/ErdosProblems/Erdos1010.lean (commit 8822f7ddef30fadbd92e1c6ab4ed897af356af5e, theorem erdos_1010 at L612). It is linked through the formal_proof attribute on Erdos1010.erdos_1010 in /home/user/math0/lean/.lake/packages/formal_conjectures/FormalConjectures/ErdosProblems/1010.lean.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1026::erdos_1026.variants.upper_bound", + "slug": "erdos1026-erdos-1026-variants-upper-bound", + "title": "Erdős 1026: no constant c > 1 is admissible (Cambie's construction)", + "area": "Combinatorics", + "source": "Erdős Problem #1026", + "source_url": "https://www.erdosproblems.com/1026", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1026.lean", + "decl": "Erdos1026.erdos_1026.variants.upper_bound", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/ErdosProblems/Erdos1026_erdos_1026_variants_upper_bound.lean", + "our_decl": "Math0.Erdos1026.upper_bound", + "summary": "Call c admissible if for every ε > 0, for all sufficiently large n, every sequence x_1,...,x_n of distinct positive reals has a monotone (non-decreasing or non-increasing) subsequence whose sum is at least (c − ε)/√n · Σ_i x_i. Then every admissible constant satisfies c ≤ 1, i.e. 1 is an upper bound of the set of admissible constants.", + "notes": "- Erdős, \"Some unsolved problems in graph theory and combinatorial analysis\" (1971) [Er71]: the original problem.\n- erdosproblems.com/1026 forum: van Doorn's precise formulation, and Cambie's construction showing c ≤ 1.\n- Tidor, Wang and Yang, arXiv:1608.04153 [TWY16], and Wagner, J. Graph Theory 2017 [Wa17]: the weighted Erdős–Szekeres theorem, which gives c ≥ 1 and hence c = 1.\n- Hanani 1957 [Ha57]: c ≥ 1/√2.\n- Steele 1995 [St95].\n- Existing Lean formalization by Aristotle and Boris Alexeev: https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1026.lean. Its theorem `c_opt_eq_k_div_sq_add_a` gives the exact c_opt(n) for all n, which implies the upper bound. erdosproblems problems.yaml lists the status as \"solved (Lean)\", last updated 2025-12-12.\n- Background: Tao's blog post https://terrytao.wordpress.com/2025/12/08/the-story-of-erdos-problem-126/.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1048::erdos_1048.variants.diam_ge_two_is_best", + "slug": "erdos1048-erdos-1048-variants-diam-ge-two-is-best", + "title": "Erdős 1048: the component of {|zⁿ| ≤ 1} containing 0 has diameter exactly 2", + "area": "Complex analysis", + "source": "Erdős Problem #1048", + "source_url": "https://www.erdosproblems.com/1048", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1048.lean", + "decl": "Erdos1048.erdos_1048.variants.diam_ge_two_is_best", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos1048_erdos_1048_variants_diam_ge_two_is_best.lean", + "our_decl": "Math0.Erdos1048.diam_ge_two_is_best", + "summary": "For every natural number n ≥ 1, the connected component containing 0 of the level set {z ∈ ℂ : |zⁿ| ≤ 1} has (extended) diameter exactly 2. So the Erdős–Herzog–Piranian bound, which says the component containing 0 has diameter ≥ 2 when all roots lie in |z| ≤ r ≤ 1/2, is attained by f(z) = zⁿ.", + "notes": "- Erdős, P., Herzog, F. and Piranian, G., \"Metric properties of polynomials\", J. Analyse Math. 6 (1958), 125–148. This is the source of the diam ≥ 2 bound for 0 ≤ r ≤ 1/2 and of the remark that zⁿ shows it is sharp.\n- Pommerenke, Ch., \"On metric properties of complex polynomials\", Michigan Math. J. (1961), 97–115.\n- erdosproblems.com/1048: status \"disproved (Lean)\" as of 2026-01-27.\n- The existing Lean proof at https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1048.lean (Aristotle / Boris Alexeev) covers only the main disproof, `not_erdos_1048`, through Pommerenke's zⁿ − rⁿ example with r > 1. It does not prove `erdos_1048.variants.diam_ge_two_is_best`.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1098::erdos_1098.variants.upper_bound", + "slug": "erdos1098-erdos-1098-variants-upper-bound", + "title": "Cliques in the non-commuting graph have at most [G : Z(G)] vertices", + "area": "Combinatorics, Group theory", + "source": "Erdős Problem #1098", + "source_url": "https://www.erdosproblems.com/1098", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1098.lean", + "decl": "Erdos1098.erdos_1098.variants.upper_bound", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/ErdosProblems/Erdos1098_erdos_1098_variants_upper_bound.lean", + "our_decl": "Math0.Erdos1098.upper_bound", + "summary": "Let G be a group and let Γ(G) be its non-commuting graph: the vertices are the elements of G, and g and h are adjacent iff gh ≠ hg. If the centre Z(G) has finite index n = [G : Z(G)], then Γ(G) contains no complete subgraph on n + 1 vertices (Lean: `(nonCommutingGraph G).CliqueFree ((Subgroup.center G).index + 1)` under `[(Subgroup.center G).FiniteIndex]`). This is the remark Neumann (1976) made in answering Erdős Problem 1098.", + "notes": "B. H. Neumann, \"A problem of Paul Erdős on groups\", J. Austral. Math. Soc. Ser. A 21 (1976), 467–472. It proves that Γ(G) has no infinite clique iff [G:Z(G)] < ∞, and remarks that a clique has at most [G:Z(G)] vertices. erdosproblems.com/1098 lists the problem as \"proved (Lean)\" (problems.yaml, 2026-05-02). The existing Lean formalization is plby/lean-proofs, src/v4.29.1/ErdosProblems/Erdos1098.lean, which is linked as formal_proof on upstream erdos_1098. Its theorem `erdos1098` contains the same coset-injection bound S.card ≤ Nat.card (G ⧸ center G) for pairwise non-commuting finsets under finite index, and `IsFIZGroup.isPEGroup` uses the same argument.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1119::erdos_1119.variants.erdos_wetzel", + "slug": "erdos1119-erdos-1119-variants-erdos-wetzel", + "title": "Erdős–Wetzel theorem: if ℵ₁ < 𝔠, families of entire functions with countably many values at each point are countable", + "area": "Logic, Complex analysis", + "source": "Erdős Problem #1119", + "source_url": "https://www.erdosproblems.com/1119", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1119.lean", + "decl": "Erdos1119.erdos_1119.variants.erdos_wetzel", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/ErdosProblems/Erdos1119_erdos_1119_variants_erdos_wetzel.lean", + "our_decl": "Math0.Erdos1119.erdos_wetzel", + "summary": "Assume ℵ₁ < 𝔠. Let F be a set of entire functions ℂ → ℂ such that for every z₀ ∈ ℂ the set of values {f(z₀) : f ∈ F} is countable. Then F is countable. (Formally, the hypothesis ℵ_1 < 𝔠 is stated in an arbitrary universe `Cardinal.{u_1}`.)", + "notes": "- Erdős, P., \"An interpolation problem associated with the continuum hypothesis\", Michigan Math. J. 11 (1964), 9–10. This is the original theorem: ¬CH implies the family is countable, and CH gives an uncountable counterexample.\n- Hayman, W. K., Research problems in function theory (1974), Problem 2.46.\n- Kumar–Shelah, Fund. Math. 2017, and Schilhan–Weinert, J. London Math. Soc. 2024. These give the independence of the general-cardinal problem.\n- Earlier formalizations:\n - plby/lean-proofs (Boris Alexeev; Codex/GPT), src/latest/ErdosProblems/Erdos1119.lean at commit 8822f7ddef30fadbd92e1c6ab4ed897af356af5e. It proves easy_case and `erdos_1119` (ℵ_1 < 𝔠 → pointwise-countable entire family is countable), and aliases it to `erdos_1119.variants.erdos_wetzel`.\n - Collin Yuanjie Ren, Lean proof of the full Wetzel/CH biconditional (github.com/CollinYuanjieRen/awards, jsp-000930-cyr). It is credited in the erdosproblems.com formal_status note, and the formalized state there is \"yes\".\n - L. C. Paulson, \"Wetzel's Problem and the Continuum Hypothesis\", Isabelle AFP (2022).", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1121::erdos_1121.variants.higher_dimension", + "slug": "erdos1121-erdos-1121-variants-higher-dimension", + "title": "Goodman–Goodman covering theorem for balls in ℝ^d (Erdős 1121, higher-dimensional variant)", + "area": "Discrete geometry", + "source": "Erdős Problem #1121", + "source_url": "https://www.erdosproblems.com/1121", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1121.lean", + "decl": "Erdos1121.erdos_1121.variants.higher_dimension", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos1121_erdos_1121_variants_higher_dimension.lean", + "our_decl": "Math0.Erdos1121.erdos_1121_higher_dimension", + "summary": "Let d, n be natural numbers, c_1,…,c_n points of ℝ^d and r_1,…,r_n > 0. Suppose that for every nonzero v ∈ ℝ^d and every t ∈ ℝ, if the hyperplane {p : ⟨v,p⟩ = t} meets none of the closed balls B_i = B̄(c_i, r_i), then either ⟨v,c_i⟩ < t for all i or ⟨v,c_i⟩ > t for all i. Then there is z ∈ ℝ^d with ⋃_i B_i ⊆ B̄(z, R), where R = Σ_i r_i.", + "notes": "The result is Goodman, A. W. and Goodman, R. E., \"A circle covering theorem\", Amer. Math. Monthly 52 (1945), 494–498. The upstream docstring notes that their proof generalises to higher dimensions. Hadwiger, \"Nonseparable convex systems\", Amer. Math. Monthly 54 (1947), 583–585, extends it to convex bodies. Bezdek and Litvak, \"Packing convex bodies by cylinders\", Discrete Comput. Geom. (2016), 725–738, give an alternative proof. erdosproblems.com/1121 lists the problem as \"proved (Lean)\". That refers to the 2D statement, whose existing Lean proof (https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1121.lean, by Aristotle and Amogh Parab) is restricted to EuclideanSpace ℝ (Fin 2). The higher-dimensional variant has no formal_proof link in the pinned upstream or the current upstream main branch.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1136::erdos_1136.variants.mueller", + "slug": "erdos1136-erdos-1136-variants-mueller", + "title": "Müller's set avoids sums equal to powers of two and has density 1/2 (Erdős 1136)", + "area": "Number theory", + "source": "Erdős Problem #1136", + "source_url": "https://www.erdosproblems.com/1136", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1136.lean", + "decl": "Erdos1136.erdos_1136.variants.mueller", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_mueller.lean", + "our_decl": "Math0.Erdos1136.erdos_1136_mueller", + "summary": "Let M be the set of natural numbers n such that n ≡ 3·2^i (mod 2^{i+2}) for some i ≥ 0. Then (1) no a, b ∈ M (not necessarily distinct) satisfy a + b = 2^k for any k ≥ 0, and (2) M has natural density 1/2: #(M ∩ [0,b)) / b → 1/2 as b → ∞.", + "notes": "The result is H. Müller, \"Über ein additiv-zahlentheoretisches Problem von P. Erdős\", Mitt. Math. Ges. Hamburg (2011), 75-78. erdosproblems.com/1136 lists the status \"proved (Lean)\" (2026-04-19). Earlier Lean proofs exist:\n- plby/lean-proofs src/v4.29.1/ErdosProblems/Erdos1136.lean (by Aristotle, L. Luccioli and W. van Doorn), which proves the same set is sum-free (`A_sumfree`) and has density 1/2 (`A_density_half`).\n- Luccioli's gist on live.lean-lang.org.\n- Woett/Lean-files ErdosProblem1136.lean.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1136::erdos_1136.variants.multiples_of_three", + "slug": "erdos1136-erdos-1136-variants-multiples-of-three", + "title": "The multiples of 3 avoid sums equal to powers of two and have density 1/3", + "area": "Number theory", + "source": "Erdős Problem #1136", + "source_url": "https://www.erdosproblems.com/1136", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1136.lean", + "decl": "Erdos1136.erdos_1136.variants.multiples_of_three", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_multiples_of_three.lean", + "our_decl": "Math0.Erdos1136.erdos_1136_multiples_of_three", + "summary": "Let A = {n ∈ ℕ : 3 ∣ n}. (i) For all a, b ∈ A (not necessarily distinct) and all k ≥ 0, a + b ≠ 2^k. (ii) A has natural density 1/3: the quantity #(A ∩ [0, b)) / #[0, b) tends to 1/3 as b → ∞. This is the trivial benchmark in Erdős Problem 1136, which asks for a set with lower density greater than 1/3 and the same avoidance property.", + "notes": "Erdős Problem 1136 (erdosproblems.com/1136; problems.yaml gives status \"proved (Lean)\", last updated 2026-04-19). H. Müller, \"Über ein additiv-zahlentheoretisches Problem von P. Erdős\", Mitt. Math. Ges. Hamburg (2011), 75-78: Müller's set has density 1/2, and density 1/2 is optimal. The density-1/3 example using multiples of 3 is a folklore fact noted as trivial in the upstream docstring. The existing Lean proof at plby/lean-proofs (src/v4.29.1/ErdosProblems/Erdos1136.lean) formalizes the main problem, Müller's set and the upper bound, but not the multiples-of-3 variant.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1136::erdos_1136.variants.upper_bound", + "slug": "erdos1136-erdos-1136-variants-upper-bound", + "title": "Sets avoiding sums equal to powers of two have lower density at most 1/2 (Müller)", + "area": "Number theory", + "source": "Erdős Problem #1136", + "source_url": "https://www.erdosproblems.com/1136", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1136.lean", + "decl": "Erdos1136.erdos_1136.variants.upper_bound", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_upper_bound.lean", + "our_decl": "Math0.Erdos1136.upper_bound", + "summary": "Let A ⊆ ℕ be such that a + b ≠ 2^k for all a, b ∈ A (not necessarily distinct) and all k ≥ 0. Then the lower natural density of A, liminf_{N→∞} |A ∩ [0, N)| / N, is at most 1/2.", + "notes": "Müller, Helmut, \"Über ein additiv-zahlentheoretisches Problem von P. Erdős\", Mitt. Math. Ges. Hamburg (2011), 75-78. Müller proves the existence of a set with density 1/2 and that every such set has density at most 1/2. erdosproblems.com/1136 has status \"proved (Lean)\" in problems.yaml (formal_status Lean, 2026-04-19). The existing Lean proof is linked from the upstream formal_proof attribute: https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1136.lean (Aristotle, Lorenzo Luccioli, Wouter van Doorn). It contains `sumfree_upperDensity_le_half`, an upper density ≤ 1/2 bound for any power-of-two-sum-free S ⊆ ℕ, and `main_result`. Related formalizations are Luccioli's gist (mathlib v4.28.0) and https://github.com/Woett/Lean-files/blob/main/ErdosProblem1136.lean.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1148::erdos_1148.variants.weaker", + "slug": "erdos1148-erdos-1148-variants-weaker", + "title": "Every n is x² + y² − z² with max(x², y², z²) ≤ n + 2√n", + "area": "Number theory", + "source": "Erdős Problem #1148", + "source_url": "https://www.erdosproblems.com/1148", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1148.lean", + "decl": "Erdos1148.erdos_1148.variants.weaker", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos1148_erdos_1148_variants_weaker.lean", + "our_decl": "Math0.Erdos1148.erdos_1148_weaker", + "summary": "For every natural number n there exist natural numbers x, y, z with n = x² + y² − z² (the subtraction is truncated subtraction on ℕ) and x², y², z² ≤ n + 2√n, where √n is the real square root. This is the relaxed form of Erdős Problem 1148, which [Va99] calls \"obvious\".", + "notes": "[Va99] \"Some of Paul's favorite problems\", the booklet for the conference \"Paul Erdős and his mathematics\" (Budapest, 1999), calls the n + 2√n relaxation \"obvious\". The main Erdős 1148 problem (bound ≤ n, for large n) was proved by Chojecki [Ch26], \"Bounded Representations by x²+y²−z²\" (2026). Its Lean proof is plby/lean-proofs src/latest/ErdosProblems/Erdos1148.lean at commit 8822f7d, and it covers only the main theorem for large n, not the weaker variant for every n. In erdosproblems.com's problems.yaml, problem 1148 has status \"proved (Lean)\" and OEIS entries A390380 and A393168. The upstream formal-conjectures file FormalConjectures/ErdosProblems/1148.lean has a formal_proof link on erdos_1148 only.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1180::erdos_1180.variants.optimal", + "slug": "erdos1180-erdos-1180-variants-optimal", + "title": "Erdős 1180, \"optimal\" variant: false as stated (C_ε grows exponentially in 1/ε, because the constant must cover all primes)", + "area": "Number theory", + "source": "Erdős Problem #1180", + "source_url": "https://www.erdosproblems.com/1180", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1180.lean", + "decl": "Erdos1180.erdos_1180.variants.optimal", + "category": "research open" + }, + "mode": "refutes", + "classification": "misformalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos1180_erdos_1180_variants_optimal.lean", + "our_decl": "Math0.Erdos1180.not_erdos_1180_variants_optimal", + "summary": "For ε > 0 let C(ε) be the least natural number C such that for every prime p and every residue a mod p there is a multiset s of integers n with 1 ≤ n ≤ p^ε and gcd(n,p)=1, |s| ≤ C, and Σ_{n∈s} n^{-1} ≡ a (mod p). If no such C exists, C(ε) = 0 (Lean's sInf ∅ = 0). The upstream statement says: for every δ > 0, C(ε) ≤ ε^{-(1+δ)} for all sufficiently small ε > 0. We prove the negation: there is a δ > 0 (δ = 1 works) such that C(ε) > ε^{-2} for arbitrarily small ε > 0, namely ε = 1/(m+1) for every large m.", + "notes": "Erdős and Graham, Old and new problems and results in combinatorial number theory (1980), the source of the question. Shparlinski, Arch. Math. (Basel) 2002, pp. 445–448: at most ε⁻³ summands for all p ≥ P(ε). Glibichuk, Mat. Zametki 2006, pp. 384–395: at most ε⁻² summands for all p ≥ P(ε); his covering lemma is the 8XY = F_p result for antisymmetric Y with |X||Y| > p. erdosproblems.com/1180 is marked proved, and its remark that \"it may be that C_ε ≤ ε^{-1-o(1)}\" is meant for large primes. The upstream formal-conjectures file 1180.lean already notes, in the docstring of variants.shparlinski, that no polynomial bound can hold for all primes. Upstream also links Lean proofs of the main statement and the shparlinski, glibichuk and lower_bound variants (plby/lean-proofs and linrock/math-proofs). The Glibichuk part of this file is adapted from plby/lean-proofs. The \"optimal\" variant has no prior formal resolution I know of. Its falsity as formalized follows from the small-prime obstruction that the upstream file itself states. - erdosproblems.com/1180. The ε^{-1-o(1)} question is listed there as still open. The page credits Shparlinski with ≪ε^{-3}, Glibichuk with ≪ε^{-2}, and Croot with (log p)^{3+o(1)}.\n- [Sh02] I. E. Shparlinski, \"On a question of Erdős and Graham\", Arch. Math. (Basel) 78 (2002), 445–448.\n- [Gl06] A. A. Glibichuk, Mat. Zametki 79 (2006), 384–395 (mathnet.ru mzm2708): N = 8([1/ε+1/2]+1)^2 summands for sufficiently large p.\n\n(Abridged; the manuscript discusses the literature in full.)", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1193::erdos_1193.parts.i", + "slug": "erdos1193-erdos-1193-parts-i", + "title": "Erdős Problem 1193 (i): the lower density of {n : 1_A*1_A(n) = g(n)} need not be 0", + "area": "Combinatorics, Number theory", + "source": "Erdős Problem #1193", + "source_url": "https://www.erdosproblems.com/1193", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1193.lean", + "decl": "Erdos1193.erdos_1193.parts.i", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_i.lean", + "our_decl": "Math0.Erdos1193.erdos_1193_parts_i", + "summary": "It is not true that for every A ⊆ ℕ and every non-decreasing g : ℕ → ℕ with g(n) > 0 for all n, the set {n ∈ ℕ : 1_A ∗ 1_A(n) = g(n)} has lower natural density 0. Here 1_A ∗ 1_A(n) = #{(a,b) ∈ ℕ² : a + b = n, a ∈ A, b ∈ A} counts ordered representations (with 0 ∈ ℕ). The lower density of S is liminf_{N→∞} #(S ∩ [0,N)) / N.", + "notes": "The problem is Erdős Problem #1193 (erdosproblems.com/1193), from P. Erdős, \"A survey of problems in combinatorial number theory\", Ann. Discrete Math. (1980), 89–115. The site marks it \"solved (Lean)\": the literal question is trivially false via A = ℕ, which gives 1_A∗1_A(n) = n+1. The existing Lean formalization is plby/lean-proofs src/v4.29.1/ErdosProblems/Erdos1193.lean (Aristotle / Pietro Monticone; forum thread erdosproblems.com/forum/thread/1193#post-5360). It is linked from the upstream variant erdos_1193.variants.sumRep_univ and proves the key identity conv_ind univ n = n+1, but not the density step.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/1193::erdos_1193.parts.ii", + "slug": "erdos1193-erdos-1193-parts-ii", + "title": "Erdős Problem 1193 (ii): the upper density of {n : 1_A*1_A(n) = g(n)} need not be bounded away from 1", + "area": "Combinatorics, Number theory", + "source": "Erdős Problem #1193", + "source_url": "https://www.erdosproblems.com/1193", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/1193.lean", + "decl": "Erdos1193.erdos_1193.parts.ii", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_ii.lean", + "our_decl": "Math0.Erdos1193.erdos_1193_parts_ii", + "summary": "There is no real constant c < 1 such that for every A ⊆ ℕ and every monotone g : ℕ → ℕ with g(n) > 0 for all n, the set {n ∈ ℕ : sumRep A n = g n} has upper density < c. Here sumRep A n is the number of ordered pairs (a, b) ∈ A × A with a + b = n (i.e. 1_A * 1_A(n)), and the upper density of S ⊆ ℕ is limsup_{N→∞} |S ∩ [0, N)| / N.", + "notes": "Erdős, P., \"A survey of problems in combinatorial number theory\", Ann. Discrete Math. (1980), 89-115 [Er80]. erdosproblems.com/1193 says the question as stated is trivially \"no\" because of A = ℕ (1_A*1_A(n) = n+1), and its data file gives the status as \"solved (Lean)\" (2026-04-13). An existing Lean formalization is linked from the upstream formal_conjectures file: https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1193.lean.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/142::erdos_142", + "slug": "erdos142-erdos-142", + "title": "Erdős 142: no single k-independent asymptotic formula for r_k(N)", + "area": "Number theory", + "source": "Erdős Problem #142", + "source_url": "https://www.erdosproblems.com/142", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/142.lean", + "decl": "Erdos142.erdos_142", + "category": "research open" + }, + "mode": "refutes_every_answer", + "classification": "misformalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos142_erdos_142.lean", + "our_decl": "Math0.Erdos142.erdos_142_refuted", + "summary": "Let r_k(N) = Set.IsAPOfLengthFree.maxCard k N be the largest size of a subset of {1,...,N} that contains no non-trivial k-term arithmetic progression. The upstream statement says that for every k ∈ ℕ, the sequence N ↦ r_k(N) is asymptotically equivalent (as N → ∞) to erdos_142.answer : ℕ → ℝ, which is one fixed function that does not depend on k. We prove that this fails for every possible choice of that function: ∀ a : ℕ → ℝ, ¬ ∀ k, (fun N => (r k N : ℝ)) ~[atTop] a.", + "notes": "Erdős Problem 142 ($10000 prize) is open. In erdosproblems problems.yaml, entry \"142\" has status \"open\" and formal_status \"unformalized\". The OEIS sequences A003002–A003005 give r_3 through r_6. Known bounds include:\n- Szemerédi: r_k(N) = o(N).\n- Behrend and Rankin: lower bounds of the form N·exp(-c(log N)^{1/ℓ}).\n- Kelley–Meka (2023) and Bloom–Sisask: r_3(N) ≤ N·exp(-c(log N)^{1/9}).\n- Green–Tao: k = 4.\n- Leng–Sah–Sawhney (2024): k ≥ 5.\n\nNo asymptotic formula r_k(N) ~ f_k(N) is known for any k ≥ 3. The Lean result does not touch this question. It only shows that the upstream statement, with one answer for every k ∈ ℕ including k = 1 and k = 2, is false, which is a trivial consequence of r_1(N) = N and r_2(N) ≤ 1. Sources:\n- erdosproblems.com/142: the problem is open, $10000 prize; the page says an asymptotic formula is \"still far out of reach, even for k=3\", lists bounds by Kelley–Meka (k=3), Green–Tao (k=4) and Leng–Sah–Sawhney (k≥5), and notes Erdős's [Er80] remark that it is not known whether r_k/r_{k+1} → 0.\n- erdosproblems.com/forum/thread/142: only one unrelated comment, and nothing about the formal statement.\n\nUpstream formal-conjectures history (google-deepmind/formal-conjectures):\n- Commit 2c24ebe7 (#7327, 2026-10-14, M. Firsching): introduced the k-independent top-level `def erdos_142.answer : ℕ → ℝ := sorry`.\n- Commit 7f64240c (#5810, 2026-09-12, S. Mercuri): changed Θ to ~ (fixes #5628 and #4922).\n\n(Abridged; the manuscript discusses the literature in full.)", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/142::erdos_142.variants.isTheta", + "slug": "erdos142-erdos-142-variants-istheta", + "title": "Erdős 142 (Θ variant): no k-independent order of magnitude for r_k(N)", + "area": "Number theory", + "source": "Erdős Problem #142", + "source_url": "https://www.erdosproblems.com/142", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/142.lean", + "decl": "Erdos142.erdos_142.variants.isTheta", + "category": "research open" + }, + "mode": "refutes_every_answer", + "classification": "misformalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos142_erdos_142_variants_isTheta.lean", + "our_decl": "Math0.Erdos142.not_isTheta", + "summary": "Let r_k(N) = Set.IsAPOfLengthFree.maxCard k N be the largest size of a subset of {1,...,N} that contains no non-trivial k-term arithmetic progression. The upstream statement asks for one function answer : ℕ → ℝ such that for every k ∈ ℕ, (N ↦ r_k(N)) =Θ[atTop] answer. We prove the negation for every possible value of the unknown: for all a : ℕ → ℝ, ¬ ∀ k : ℕ, (fun N => (r k N : ℝ)) =Θ[atTop] a.", + "notes": "Erdős Problem 142 (erdosproblems.com/142, $10000 prize, listed open, OEIS A003002–A003005) asks for the order of magnitude, or an asymptotic formula, of r_k(N), the largest subset of {1,...,N} with no k-term AP.\n\nKnown results:\n- Szemerédi: r_k(N) = o(N).\n- Behrend (k = 3) and Rankin (general k): lower bounds of the form N·exp(−c(log N)^{1/ℓ}).\n- Gowers: upper bounds for general k.\n- Kelley–Meka (2023), improved by Bloom–Sisask: r_3(N) ≤ N·exp(−c(log N)^{1/12}), later exponent 1/9.\n- Green–Tao: bounds for r_4.\n- Leng–Sah–Sawhney (2024): r_k(N) ≤ N·exp(−(log log N)^{c_k}).\n\nThe order of magnitude of r_k is open for every k ≥ 3.\n\nThe facts the refutation uses are trivial and belong to the formal library: r_1(N) = N (`Set.IsAPOfLengthFree.maxCard_one`), and r_2(N) ≤ 1 because any two points form a 2-term AP. I know of no previous Lean artifact reporting that `erdos_142.variants.isTheta` (or the sibling `erdos_142`) is false because its answer does not depend on k. - erdosproblems.com/142: open, $10000; it gives order of magnitude as the \"more reasonable\" goal and cites [Er80], [Va99]. Best known bounds: Kelley–Meka 2023 (k=3), Green–Tao 2017 (k=4), Leng–Sah–Sawhney 2024 (k≥5). Lower bounds: Behrend 1946 and Rankin 1961.\n- erdosproblems.com/forum/thread/142: a single comment by jleng01 (2026-08-09), unrelated to formalization.\n- google-deepmind/formal-conjectures PR #5446 (open, 2026-09-10): flags 142.lean:37,56 as answer slots that cannot depend on the required binder k.\n\n(Abridged; the manuscript discusses the literature in full.)", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/319::erdos_319", + "slug": "erdos319-erdos-319", + "title": "Erdős 319: no constant answer works for every N (formalization defect)", + "area": "Combinatorics", + "source": "Erdős Problem #319", + "source_url": "https://www.erdosproblems.com/319", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/319.lean", + "decl": "Erdos319.erdos_319", + "category": "research open" + }, + "mode": "refutes_every_answer", + "classification": "misformalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos319_erdos_319.lean", + "our_decl": "Math0.Erdos319.erdos_319_refuted", + "summary": "For N ∈ ℕ, let S_N be the set of sizes |A| of finite sets A ⊆ {1,…,N} for which there is δ : ℕ → {±1} with ∑_{n∈A} δ(n)/n = 0 and ∑_{n∈A'} δ(n)/n ≠ 0 for every nonempty proper subset A' ⊊ A. The upstream statement claims that a single natural number erdos_319.answer is the greatest element of S_N for every N. We prove the negation for every possible value: for every c ∈ ℕ, it is not true that c = max S_N for all N.", + "notes": "Erdős Problem 319 (erdosproblems.com/319). problems.yaml lists it as status open, last updated 2025-08-31, with formal_status \"unformalized\" and formalized \"yes\"; no Lean proof is recorded. By the upstream file's comments, c(N) = Θ(N): trivially c(N) ≤ N, and a lower bound c(N) ≥ (1 − 1/e + o(1))N, observed by Adenwalla, follows from Croot, \"On unit fractions with denominators in short intervals\", Acta Arith. 2001. The refutation here concerns only the defective constant-answer formalization and says nothing about the open problem. - Erdős Problem #319: https://www.erdosproblems.com/319. Status open. It cites [ErGr80], Erdős–Graham, Old and New Problems and Results in Combinatorial Number Theory (1980). Its only result is Adenwalla's lower bound c(N) ≥ (1−1/e+o(1))N, derived from E. S. Croot III, \"On unit fractions with denominators in short intervals\", Acta Arith. 99 (2001) 99–114.\n- Forum thread: https://www.erdosproblems.com/forum/thread/319. It has 0 comments and nothing about an upper bound or an exact value.\n\n(Abridged; the manuscript discusses the literature in full.)", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/367::erdos_367.variants.higher_full_parts", + "slug": "erdos367-erdos-367-variants-higher-full-parts", + "title": "Erdős 367 (higher full parts): the product of r-full parts beats n^(1+ε) infinitely often", + "area": "Number theory", + "source": "Erdős Problem #367", + "source_url": "https://www.erdosproblems.com/367", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/367.lean", + "decl": "Erdos367.erdos_367.variants.higher_full_parts", + "category": "research open" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos367_erdos_367_variants_higher_full_parts.lean", + "our_decl": "Math0.Erdos367.higher_full_parts", + "summary": "Let $B_r(m)=\\prod_{p^a\\,\\|\\,m,\\ a\\ge r} p^a$ be the $r$-full part of $m$ (with $B_r(0)=1$). For all integers $r\\ge 3$ and $k\\ge 2$ there is some $\\varepsilon=\\varepsilon(r,k)>0$ such that\n$$\\limsup_{n\\to\\infty}\\frac{\\prod_{n\\le m0\" wording; status open (also open in local problems.yaml, formalized 2026-08-20).\n- Forum thread erdosproblems.com/forum/thread/367:\n - post-1766, Woett (van Doorn), 20 Nov 2025: proposes the ε=ε(r,k) reading.\n - post-6910, ScottHughes, 10 Jun 2026: claims an affirmative resolution for all r,k≥2 with any ε<(r+1)/r², via n=(t^r−1)^r (odd r) and n=(t^r+1)^r−1 (even r). These constructions trivially give ε<1/r.\n- Repository: https://github.com/scottdhughes/erdos367\n\n(Abridged.)", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/409::erdos_409.parts.i", + "slug": "erdos409-erdos-409-parts-i", + "title": "Erdős 409(i): no constant iteration count works for every starting value (formalization defect)", + "area": "Number theory", + "source": "Erdős Problem #409", + "source_url": "https://www.erdosproblems.com/409", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/409.lean", + "decl": "Erdos409.erdos_409.parts.i", + "category": "research open" + }, + "mode": "refutes_every_answer", + "classification": "misformalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos409_erdos_409_parts_i.lean", + "our_decl": "Math0.Erdos409.erdos_409_parts_i_refuted", + "summary": "The upstream statement says: for every n > 0, the least i ≥ 0 such that the i-th iterate of f(m) = φ(m) + 1, started at n, is prime equals one fixed natural number `erdos_409.parts.i.answer` (a constant that does not depend on n). We prove the negation for every possible value of that constant: for all a ∈ ℕ, it is not the case that for every n > 0, a is the least element of {i : f^[i](n) is prime}.", + "notes": "erdosproblems.com/409 (problems.yaml: status open, last_update 2025-08-31; OEIS A039651, A229487) asks how many iterations of n ↦ φ(n)+1 are needed to reach a prime. The answer is a function c(n), as in OEIS A039651, whose values include c(2)=0 and c(4)=1. The solver did not settle the actual asymptotic question, which the upstream erdos_409.parts.i.isTheta/isBigO/isLittleO variants state. The refutation uses only the fact that c(n) is not constant. erdosproblems.com/409 (open; attributed to Finucane, [ErGr80, p.81], Guy B41; it reads the question as bounding F(n), notes F(n)=o(n) is trivial and F(n)=1 infinitely often, per comments by S. Cambie). OEIS A039651 (number of iterations of n -> phi(n)+1 to reach a prime: a(1)=1, a(2)=0, a(3)=0, a(4)=1, so the value is not constant) and A229487. Local problems.yaml entry for 409: status open (2025-08-31), formalized yes. Upstream google-deepmind/formal-conjectures FormalConjectures/ErdosProblems/409.lean on main still declares `def erdos_409.parts.i.answer : ℕ := sorry` with the per-n IsLeast claim. The file has isTheta/isBigO/isLittleO variants with c : ℕ → ℕ that state the intended problem correctly. Formal Conjectures paper (arXiv 2605.13171) gives the misformalization taxonomy (translation-level error). I found no prior public report of this specific defect.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/723::erdos_723.variants.prime_power_is_projplane_order", + "slug": "erdos723-erdos-723-variants-prime-power-is-projplane-order", + "title": "Projective planes exist for every prime-power order (Erdős 723, existence variant)", + "area": "Combinatorics", + "source": "Erdős Problem #723", + "source_url": "https://www.erdosproblems.com/723", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/723.lean", + "decl": "Erdos723.erdos_723.variants.prime_power_is_projplane_order", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos723_erdos_723_variants_prime_power_is_projplane_order.lean", + "our_decl": "Math0.Erdos723.prime_power_is_projplane_order", + "summary": "For every natural number n that is a prime power, there exist types P, L (in Type), a membership (incidence) relation between P and L, Fintype structures on P and L, and a projective plane structure pp on (P, L) whose order is exactly n.", + "notes": "The construction of the Desarguesian projective plane PG(2, q) for every prime power q goes back to O. Veblen and W. H. Bussey, \"Finite projective geometries\", Trans. AMS 7 (1906), 241–259. Standard textbook sources are M. Hall, \"Combinatorial Theory\", and P. Dembowski, \"Finite Geometries\" (1968). The open converse is the prime power conjecture (Erdős Problem 723). Related results are Bruck–Ryser (1949), and Lam–Thiel–Swiercz (1989), who showed there is no plane of order 10. In Lean, Mathlib's Combinatorics/Configuration.lean has `Configuration.ofField` (the ProjectivePlane instance on ℙ(K³)) and `ProjectivePlane.card_points`, and LinearAlgebra/Projectivization/Cardinality.lean has `Projectivization.card_of_finrank`. Mathlib does not state the order of ofField or the existence of a plane of every prime-power order, and erdosproblems.com lists 723 as formal_status \"unformalized\".", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/750::erdos_750.variants.c_gt_quarter", + "slug": "erdos750-erdos-750-variants-c-gt-quarter", + "title": "Erdős–Hajnal: infinite chromatic number with independent sets of size m/2 − cm for every c > 1/4", + "area": "Combinatorics", + "source": "Erdős Problem #750", + "source_url": "https://www.erdosproblems.com/750", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/750.lean", + "decl": "Erdos750.erdos_750.variants.c_gt_quarter", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/ErdosProblems/Erdos750_erdos_750_variants_c_gt_quarter.lean", + "our_decl": "Math0.Erdos750.c_gt_quarter", + "summary": "For every real c > 1/4 (formally c ∈ ℝ≥0) there is a graph G, on a vertex type in any prescribed universe, with chromatic number ∞, such that every set S of m ≥ 1 vertices contains an independent set I with m/2 − c·m ≤ |I|. The subtraction is truncated subtraction in ℝ≥0.", + "notes": "The problem and its variants:\n- Erdős and Hajnal [ErHa67b], \"On chromatic graphs\", Mat. Lapok (1967), 1–4: graphs of infinite chromatic number in which every m-vertex subgraph has an independent set of size at least m/2 − cm, for any c > 1/4. The classical example is the shift graph with the random-cut argument used here.\n- Erdős, Hajnal and Szemerédi [EHS82]: the f(m) = εm case, via a comment by Sellke on erdosproblems.\n- Chojecki with GPT-5.5 Pro (ulam.ai/research/erdos750.pdf): the general f → ∞ case.\n- Stiebitz [St85], Sachs and Stiebitz [SaSt89], Müller and Stehlík [MuSt19]: the generalised Mycielskian chromatic bound used in that proof.\n\nExisting Lean proofs:\n- plby/lean-proofs src/latest/ErdosProblems/Erdos750.lean, commit 8822f7dd: an unconditional `theorem erdos_750` in formal-conjectures form. It implies variants.c_gt_quarter directly by taking f(m) = c·m.\n- Jayyhk/erdos-lean problems/750/Erdos750.lean.\n- Shashi456/erdos-formalizations: the conditional version.\n- erdosproblems.com lists #750 as \"proved (Lean)\", last updated 2025-08-31.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/775::erdos_775.variants.moon_moser", + "slug": "erdos775-erdos-775-variants-moon-moser", + "title": "Moon–Moser: a graph on n vertices has at most n − log₂ n + 1 maximal-clique sizes", + "area": "Combinatorics", + "source": "Erdős Problem #775", + "source_url": "https://www.erdosproblems.com/775", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/775.lean", + "decl": "Erdos775.erdos_775.variants.moon_moser", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos775_erdos_775_variants_moon_moser.lean", + "our_decl": "Math0.Erdos775.erdos_775_moon_moser", + "summary": "There is a real constant C such that for every n ∈ ℕ and every simple graph G on Fin n, the number of distinct sizes of maximal cliques of G (the ncard of SimpleGraph.cliqueSizes G = {k | ∃ S : Finset, S is a maximal clique, |S| = k}) is at most n − log₂ n + C. Here Real.logb 2 0 = 0. We prove it with C = 1, for every n including n = 0.", + "notes": "J. W. Moon and L. Moser, \"On cliques in graphs\", Israel J. Math. 3 (1965), 23-28. Proves that the number of distinct maximal-clique sizes on n vertices is at most n − ⌊log₂ n⌋, which is the n − log₂ n + O(1) upper bound. J. H. Spencer, \"On cliques in graphs\", Israel J. Math. 9 (1971), 419-421. Gives the matching lower-bound construction. J. Gao, \"On cliques in hypergraphs\", arXiv:2510.14804 (2025). Settles the main 3-uniform hypergraph question. erdosproblems.com/775 has status \"disproved (Lean)\". The existing Lean proof (github.com/plby/lean-proofs src/v4.29.1/ErdosProblems/Erdos775.lean, by Aristotle and L. Luccioli) covers only Gao's hypergraph theorem, not the graph Moon–Moser variant.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/816::erdos_816.variants.complete_bipartite", + "slug": "erdos816-erdos-816-variants-complete-bipartite", + "title": "K_{n,n+1} is extremal for Erdős Problem 816", + "area": "Combinatorics", + "source": "Erdős Problem #816", + "source_url": "https://www.erdosproblems.com/816", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/816.lean", + "decl": "Erdos816.erdos_816.variants.complete_bipartite", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos816_erdos_816_variants_complete_bipartite.lean", + "our_decl": "Math0.Erdos816.erdos_816_complete_bipartite", + "summary": "For every natural number n, the complete bipartite graph K_{n,n+1} (vertex set Fin n ⊕ Fin (n+1), so 2n+1 vertices) has exactly n^2 + n edges, and it does not contain two distinct vertices u ≠ v with deg u = deg v that are joined by a path of length 3.", + "notes": "Erdős Problem 816 (Erdős–Hajnal), erdosproblems.com/816 (status: proved, not marked as Lean). [Er91] Erdős, Problems and results in combinatorial analysis and combinatorial number theory (1991), where K_{n,n+1} is the standard example showing that n^2+n edges do not suffice. [ChMa25] K. Chen and J. Ma, arXiv:2503.19569 (2025), proved the main conjecture and showed that for n ≥ 600, K_{n,n+1} is the unique exception with n^2+n edges. The main theorem has an existing Lean proof at plby/lean-proofs (commit 8822f7d, src/latest/ErdosProblems/Erdos816.lean, L939), but that file contains no K_{n,n+1} or complete_bipartite lemma. So this variant appears to be formalized here for the first time.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/834::erdos_834.parts.ii", + "slug": "erdos834-erdos-834-parts-ii", + "title": "A 7-regular 3-critical 3-uniform hypergraph on 9 vertices (Erdős Problem 834, chromatic version)", + "area": "Combinatorics", + "source": "Erdős Problem #834", + "source_url": "https://www.erdosproblems.com/834", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/834.lean", + "decl": "Erdos834.erdos_834.parts.ii", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos834_erdos_834_parts_ii.lean", + "our_decl": "Math0.Erdos834.erdos_834_parts_ii", + "summary": "There exist n and a 3-uniform hypergraph H on the vertex set {0,…,n−1} such that: (1) H has weak chromatic number exactly 3, meaning it has a vertex 3-coloring with no monochromatic edge but no such coloring with 0, 1 or 2 colors; (2) for every edge e of H, the hypergraph H − e is 2-colorable; (3) for every vertex v, the hypergraph made of the edges of H that avoid v is 2-colorable; and (4) every vertex of {0,…,n−1} lies in at least 7 edges. This is the question of Erdős and Lovász, Erdős Problem 834, part (ii), answered positively by Li [Li25] with a 22-edge example.", + "notes": "Erdős Problem 834 (erdosproblems.com/834, from [Er74d, p.282], a problem of Erdős and Lovász). It was solved by R. Li, \"On an Erdős–Lovász problem: 3-critical 3-graphs of minimum degree 7\", arXiv:2512.24850 (Dec 2025). For the transversal reading, Li shows there are at most 10 edges, so some vertex has degree at most 6, and K_5^(3) shows this is sharp. For the chromatic reading, Li gives an explicit 9-vertex 3-graph with minimum degree 7 (22 edges per the solver) and backs it with witness 2-colorings and a verification script, not a Lean proof. The erdosproblems database (problems.yaml) lists status \"solved\" (not \"(Lean)\") and formal_status \"unformalized\". The formal-conjectures statement Erdos834.erdos_834.parts.ii is still sorry. The solver's witness is a different, 21-edge 7-regular hypergraph on 9 vertices.", + "date": "2026-10-17" + }, + { + "id": "ErdosProblems/835::johnsonGraph_18_9_chromaticNumber", + "slug": "erdos835-johnsongraph-18-9-chromaticnumber", + "title": "The Johnson graph J(18, 9) has chromatic number at least 11", + "area": "Combinatorics", + "source": "Erdős Problem #835", + "source_url": "https://www.erdosproblems.com/835", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/ErdosProblems/835.lean", + "decl": "Erdos835.johnsonGraph_18_9_chromaticNumber", + "category": "research solved" + }, + "mode": "proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/ErdosProblems/Erdos835_johnsonGraph_18_9_chromaticNumber.lean", + "our_decl": "Math0.Erdos835.johnsonGraph_18_9_chromaticNumber", + "summary": "Let J(18, 9) be the Johnson graph. Its vertices are the 9-element subsets of an 18-element set, and two vertices are adjacent when they share exactly 8 elements. Then χ(J(18, 9)) > 9 + 1, so χ(J(18, 9)) ≥ 11. This is the case k = 9 of Erdős Problem 835, which asks whether χ(J(2k, k)) = k + 1 for some k > 2.", + "notes": "Erdős Problem 835 (erdosproblems.com/835). problems.yaml lists its status as \"verifiable\" and its formal_status as \"unformalized\"; there is no \"(Lean)\" marker. The general question stays open, but the k = 9 case is known. The odd-k lower bound χ(J(2k,k)) > k+1 follows from Johnson's bound for constant-weight codes (S. M. Johnson, 1962) through α(J(2k,k)) ≤ A(2k,4,k). For k = 9 this gives α ≤ 4420 and χ ≥ ⌈48620/4420⌉ = 11. The bound is tabulated on A. E. Brouwer's Johnson-graphs page (aeb.win.tue.nl/graphs/Johnson.html). Ma and Tang (2025, github.com/QuanyuTang/erdos-problem-835) prove χ(J(2k,k)) > k+1 for every k > 2 with k+1 composite, which includes k = 9. No previous sorry-free Lean proof was found: in formal_conjectures, indepNum_johnson_le_johnsonBound is sorry, and every upstream lower-bound statement depends on it or is itself sorry.", + "date": "2026-10-17" + }, + { + "id": "GreensOpenProblems/44::green_44", + "slug": "green44-green-44", + "title": "Sieving [N] by half the classes mod 1000 primes below N^{9/10} can leave more than N/10 (Green's Problem 44 refuted as formalized)", + "area": "Number theory", + "source": "Ben Green's 100 open problems, #44", + "source_url": "https://people.maths.ox.ac.uk/greenbj/papers/open-problems.pdf#problem.44", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/GreensOpenProblems/44.lean", + "decl": "Green44.green_44", + "category": "research open" + }, + "mode": "refutes", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/GreensOpenProblems/Green44_green_44.lean", + "our_decl": "Math0.Green44.green_44_false", + "summary": "Green's Open Problem 44 (from Erdős 1980, Section 6, Problem 3): sieve [N] by removing half the residue classes mod p_i, for primes 2 ≤ p_1 < ... < p_1000 < N^{9/10}. Does the remaining set have size at most N/10? The formal statement Green44.green_44 says yes: for all N, all strictly increasing p : Fin 1000 → ℕ of primes with p_999^10 < N^9, and all A_i ⊆ ZMod p_i with |A_i| = ⌊p_i/2⌋, the set {x ∈ [1,N] : x mod p_i ∉ A_i for all i} has 10·|remaining| ≤ N. We prove the negation. Counterexample: N = 100000, p_0 < ... < p_999 the 1000 consecutive primes 20011, ..., 30161, and A_i the upper half {⌈p_i/2⌉, ..., p_i − 1} of the residues mod p_i.", + "notes": "Sources:\n- Erdős, \"A survey of problems in combinatorial number theory\", Ann. Discrete Math. 6 (1980) 89-115, p.107, §6 Problem 3 (scan at https://users.renyi.hu/~p_erdos/1980-03.pdf).\n- B. Green, 100 Open Problems, Problem 44 (https://people.maths.ox.ac.uk/greenbj/papers/open-problems.pdf, Dec 2025 version; no update recorded).\n- Erdős Problem #1202 (https://www.erdosproblems.com/1202): \"resolved in the negative by Price and GPT-5.4 Pro\". It identifies the problem with Green #44. Last edited 2026-04-12; local DB marks it solved on 2026-04-04. Write-up: https://www.overleaf.com/read/qyhdmrchqnvb.\n- #1202 forum thread (https://www.erdosproblems.com/forum/thread/1202): Z. Hunter and T. Bloom, 16-17 Apr 2026, on large-sieve bounds and refinements.\n- Justin Sun Prize catalog entry JSP-001007 (TheJustinSunPrize/awards, problems/catalog-1001-1022.md): \"Solved, Price and GPT-5.4 Pro\".\n- Existing Lean formalization: github.com/tester-lean/awards @ f26433803cfbd924569aebbdcc1c39321ecb9971, submissions/jsp-001007. Theorems JSP001007.green44_counterexample (every k ≥ 1, all large N, more than N/10 survivors, p^10 < N^9, |A_i| = (p-1)/2) and JSP001007.not_green44_conjecture. Submitted as https://github.com/TheJustinSunPrize/awards/issues/104 on 2026-09-16; pending and unreviewed. Its header cites formal-conjectures Green44.\n\n(Abridged.)", + "date": "2026-10-17" + }, + { + "id": "OEIS-frontier/A001040", + "slug": "oeis-a001040", + "title": "Kurkov's rook-tour conjecture for A001040: 2·n!·a(n) counts opposite-line Hamiltonian paths of K_n □ K_2", + "area": "Discrete geometry", + "source": "OEIS A001040", + "source_url": "https://oeis.org/A001040", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A001040.lean", + "decl": "Math0.Statements.A001040.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A001040.lean", + "our_decl": "Math0.Frontier.A001040.result", + "summary": "For every n ≥ 1, take the n × 2 board with squares (i,c), i ∈ [n], c ∈ {0,1}. Two different squares are a rook move apart when they share a row i or a line c (this is the graph K_n □ K_2). An open tour is a sequence that visits every square exactly once, with consecutive squares a rook move apart; a tour and its reversal count separately. Count the tours whose first and last squares lie on different lines. Kurkov conjectured that this count is 2·n!·a(n), where a(0)=0, a(1)=1 and a(m+1) = m·a(m) + a(m−1) (OEIS A001040). The statement is proved.", + "notes": "Conjecture as stated in OEIS: %C A001040 Conjecture: 2*n!*a(n) is the number of open tours by a rook on an (n X 2) chessboard which ends at the opposite line of length n. - _Mikhail Kurkov_, Nov 19 2019\n\nReferees: OEIS sources (read from the local mirror):\n- A001040: Kurkov's conjecture, Nov 19 2019, still marked as a conjecture in revision #140 of Oct 15 2026. The entry also has Paul Barry's 2004 formula a(n+1) = Sum_k C(n-k,k)(n-k)!/k!.\n- A001053: the companion same-line conjecture, still open in revision #131 of Oct 22 2026.\n- A096121: Hugo van der Sanden, 2004, counts directed Hamiltonian paths of the 2 x n rook graph. It contains:\n - the recurrence a(n+1) = n(n+1)(a(n)+a(n-1));\n - an unattributed \"Further refinement\" formula whose two summands are exactly the opposite-line and same-line counts, though they are not labeled as such;\n - Kurkov's Feb 2019 conjecture that the total is 2*n!*A102038(n);\n - Grossman's 2024 shoe-arrangement reading;\n - a citation of Y. Cha's 2011 FSU thesis, Example 5.1.1, which I could not open (HTTP 403).\n- A102038: equals A001040 + A001053.\n- A269565: Andrew Howroyd's array of directed Hamiltonian paths in K_n x K_m.\n- A360878: Andrew Howroyd's May 2025 switch-decomposition formula for undirected paths.\n- A276356 and A089039: the Hamiltonian-cycle analogue.\n\nOther sources:\n- MathOverflow q/469606 (Kurkov, Apr 2024), \"On a A089039 and pair of sequences with simple recursion\". I read it: Max Alekseyev proves only the cycle formula, using Zeilberger's algorithm.\n- Web searches found no prior proof of the path refinement. They covered arXiv, MSE, MO, Google-style queries on rook tours of 2 x n boards, Hamiltonian paths of K_n x K_2, and the shoe or jealousy-free linear arrangements.", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Paul Barry's formula a(n+1) = Sum_k C(n-k,k)(n-k)!/k! in A001040 (%F), combined with the standard decomposition of a Hamiltonian path of K_n x K_2 into runs within one line joined by switch rows. The \"Further refinement\" formula in A096121 already has the opposite-line count as its first summand, without saying so.", + "justification": "Split a directed Hamiltonian path of the 2 x n rook graph at its moves between the two lines. The path ends on the opposite line exactly when there is an odd number 2q-1 of such switches. The path is then fixed by three choices: the start line, the ordered switch rows, and how the free squares of each line fill q ordered slots. This gives 2 n! times the sum over k of C(n-1-k,k)(n-1-k)!/k!, term by term. That sum is Paul Barry's formula for a(n), already listed in the entry. Each step is a short, standard counting argument of well under a page. The Lean proof is long and checks the closed form through a first-step recursion instead of the bijection, but that is formalization work, not a new mathematical idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A005590", + "slug": "oeis-a005590", + "title": "Zeros of a(3n) for the signed Stern sequence A005590 are exactly the fibbinary numbers", + "area": "Number theory", + "source": "OEIS A005590", + "source_url": "https://oeis.org/A005590", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A005590.lean", + "decl": "Math0.Statements.A005590.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A005590.lean", + "our_decl": "Math0.Frontier.A005590.result", + "summary": "Let a : N -> Z be given by a(0)=0, a(1)=1, a(2n)=a(n), a(2n+1)=a(n+1)-a(n) (OEIS A005590). Then for every n >= 0, a(3n)=0 if and only if n is fibbinary (OEIS A003714), i.e. the binary representation of n has no two adjacent 1 bits. This is Ralf Stephan's 2003 conjecture.", + "notes": "Conjecture as stated in OEIS: Conjecture: a(3n)=0 iff n in A003714. - _Ralf Stephan_, May 02 2003\n\nReferees: I found no prior resolution.\n- OEIS A005590 (local mirror, rev #97, Nov 2025) still marks Stephan's 2003 claim as a conjecture.\n- Related OEIS entries: A003714, A277335 (= 3·A003714, the zero set of A005590, not cross-linked to it), A290258.\n- R. Stephan, arXiv:math/0409509: the conjecture is not listed. R. Stephan, arXiv:math/0307027: lists A005590 only in a table.\n- J.-P. Allouche and J. Shallit, 'The ring of k-regular sequences', TCS 98 (1992): Example 7 shows 2-regularity only.\n- J.-P. Allouche and M. Mendès France, arXiv:1202.0211: links A005590 to Thue–Morse, nothing on zeros.\n- No hits in S. Northshield, arXiv:1503.03433; C. Defant, arXiv:1506.07824; B. Reznick, arXiv:math/0610601; or S. Fried, arXiv:2607.24832 (abstract only).\n- Not in the OEIS Open / Tsoukalas et al. 492-conjecture set (arXiv:2608.11941, 2605.22763) and not in google-deepmind/formal-conjectures.\n- Not checked: B. Reznick, 'A new sequence with many properties', Abstracts AMS 5 (1984) 16. Its scan is on oeis.org, which is rate-limited here.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The defining recursion read as a 2-regular linear representation: (a(2m),a(2m+1)) and (a(2m+1),a(2m+2)) are fixed linear images of (a(m),a(m+1)). This is the standard way to handle zero sets of 2-regular sequences (Allouche-Shallit), and the entry already notes that the sequence is 2-regular.", + "justification": "The proof follows the pair (a(m), a(m+1)) along the binary digits of m. The pair stays at (0,1) or (1,1) while the digits form blocks 0 and 11. As soon as a 0 is read in state (1,1), the pair lands on (1,0), and from then on a one-line sign invariant (x>0 and y=0} a(n) x^n = (1 - 4x + 10x^2 - 14x^3 + 27x^4 - 18x^5 + 10x^6 - 6x^7) / ((1 + x^2)^2 (1 - 2x)^2).\nIn Lean this is stated in Z[[X]] with the denominator cleared.", + "notes": "Conjecture as stated in OEIS: %F A022445 G.f.: (-6*x^7+10*x^6-18*x^5+27*x^4-14*x^3+10*x^2-4*x+1) / ((1+x^2)^2*(1-2*x)^2) (conjectured). - _Ralf Stephan_, Apr 28 2004\n\nReferees: OEIS A022445 (local mirror and current github.com/oeis/oeisdata, %I #10 May 16 2019): GF marked \"(conjectured). - Ralf Stephan, Apr 28 2004\". Sister entry A022444: GF also still conjectured. Related entries A038578 and A038579 have rooted area GFs credited to Labelle by E. Deutsch (Apr 29 2004). Other related entries: A007825, A038577, A302408. J. Labelle, \"Self-avoiding walks and polyominoes in strips\", Bull. ICA 23 (1998) 88-98; full text not accessible, so I cannot rule out that it has the perimeter GF, but the OEIS has kept it \"conjectured\" since 2004. M. von Thaden, \"Self-avoiding polygons on a three-row square-lattice strip\", arXiv:2607.27397 (Jul 2026): unrooted polygon counts on Z×{0,1,2}, does not mention A022445. M. Bousquet-Mélou & R. Brak, \"Exactly solved models\", and A. J. Guttmann & I. Jensen, \"Polygons in strips\", both in Polygons, Polyominoes and Polycubes, LNP 775 (2009): unrooted polygon GFs only. Not relevant to this GF: Batchelor–Yung 1994 (transfer-matrix SAWs across strips); Dyhr–Gilbert–Kennedy arXiv:1008.4321; Zeilberger arXiv:math/9506214 and Benjamin, Fib. Quart. 44 (2006) (two-row strip). jOEIS programs for A022444/A022445 use brute-force enumeration. I found no prior proof of the A022445 GF in any of these sources.", + "date": "2026-10-26", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Standard transfer-matrix / row-by-row decomposition of self-avoiding polygons in a strip of fixed width (e.g. Stanley, EC1 Sec. 4.7). In a 3-column strip every horizontal cut meets the polygon in 0 or 2 vertical edges, so the polygons are row-convex with three row states. The same method gives the area generating function of the same objects, A038579, credited to Labelle (Bull. ICA 23, 1998) and cited in the entry.", + "justification": "The proof rests on one observation: a self-avoiding polygon in the strip {0,1,2} x Z crosses each horizontal cut in an even number of distinct columns, at most three, so in 0 or 2 of them. The polygon is therefore two strands, with three possible states per row, and its perimeter series comes from a 3-state transfer matrix (in Lean, a linear recursion for half-strip excursions), with rooting handled by marking column-0 vertices; clearing denominators is then algebra. This is the textbook transfer-matrix method for polygons in narrow strips; it fits in about a page and is the same calculation that gave the area version (A038579) attributed to Labelle. The Lean formalization is long, but the mathematical idea is standard.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A057566", + "slug": "oeis-a057566", + "title": "Layman's floor formula for collinear triples in a 3 × n grid (A057566), as printed until its October 2026 correction, fails at n = 24", + "area": "Discrete geometry", + "source": "OEIS A057566", + "source_url": "https://oeis.org/A057566", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A057566.lean", + "decl": "Math0.Statements.A057566.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-refutes", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A057566.lean", + "our_decl": "Math0.Frontier.A057566.result : ¬ Math0.Statements.A057566.statement", + "summary": "Let a(n) be the number of 3-element collinear subsets of the 3 × n grid {0,1,2} × {0,...,n-1}. Layman's conjecture (OEIS A057566, Oct 2000), as printed in the entry until 21 Oct 2026, says that for every n ≥ 3, a(n) = 5*floor((2n^3 - 3n^2 - n)/24) + floor((2(n-1)^3 - 3(n-1)^2 - (n-1))/24) + n. The frozen statement is this conjecture for all n ≥ 3. We prove it is false: the identity fails at n = 24. On 21 Oct 2026, after this statement was frozen, OEIS corrected the formula to a(n) = 5*floor((2n^3 - 3n^2 - 2n + 3)/24) + floor((2(n-1)^3 - 3(n-1)^2 - 2(n-1) + 3)/24) + n. This result concerns only the formula as printed before that correction; the corrected formula is not refuted, and it agrees with a brute-force count for n <= 60 and with the proved closed form 3*C(n,3) + n + 2*floor((n-1)^2/4) for n <= 20000.", + "notes": "Correction (noted 26 Oct 2026): OEIS A057566 now reads \"Conjecture: a(n) = 5*floor((2n^3 - 3n^2 - 2n + 3)/24) + floor((2(n-1)^3 - 3(n-1)^2 - 2(n-1) + 3)/24) + n, which fits all of the listed terms. [Corrected by Alper Ferudun, Oct 21 2026]\" (oeisdata, checked 26 Oct 2026). The statement here was frozen from the earlier text, quoted below, which is what the Lean file refutes. Reported in review of math0 PR #1.\n\nConjecture as stated in OEIS: %F A057566 Conjecture: a(n) = 5*floor((2n^3 - 3n^2 - n)/24) + floor((2(n-1)^3 - 3(n-1)^2 - (n-1))/24) + n, which fits all of the listed terms. (John W. Layman, author of the entry, Oct 04 2000)\n\nReferees: There is no explicit published refutation, but OEIS already contains everything needed:\n- A057566 data lists a(24) = 6360. Layman's formula gives 6365 there. Paolo Xausa's b-file (2024) covers n = 0..10000.\n- A057566 %F, R. J. Mathar, May 23 2010: a(n) = n^3/2 - n^2 + n + (1-(-1)^n)/4, with recurrence signature (3,-2,-2,3,-1) and g.f. x(1-x+4x^2+2x^3)/((1+x)(x-1)^4).\n- A262402, proof by N. J. A. Sloane, Dec 16 2017, following Jared Nash's formula and his linked PDF \"Formula for number of triangles in a 3 X n grid\". It proves the number of collinear triples with one point per row in a 3 x n grid is n + 2*floor((n-1)^2/4). Hence a(n) = 3*C(n,3) + n + 2*floor((n-1)^2/4).\n- A334704 (N. J. A. Sloane and Tom Duff, 2020) tabulates collinear-triple counts for n x k grids up to 50 x 50; row 3 is A057566.\n- I searched the web (arXiv including 2609.25133, general search) and found no explicit statement that Layman's floor conjecture fails.", + "date": "2026-10-21" + }, + { + "id": "OEIS-frontier/A057566b", + "slug": "oeis-a057566b", + "title": "The corrected floor formula for collinear triples in a 3 x n grid (OEIS A057566) holds for all n", + "area": "Discrete geometry", + "source": "OEIS A057566 (formula as corrected on 21 Oct 2026)", + "source_url": "https://oeis.org/A057566", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A057566b.lean", + "decl": "Math0.Statements.A057566b.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A057566b.lean", + "our_decl": "Math0.Frontier.A057566b.result", + "summary": "Let a(n) be the number of 3-element collinear subsets of the grid {0,1,2} x {0,...,n-1}. Then for every n >= 0, a(n) = 5*floor((2n^3 - 3n^2 - 2n + 3)/24) + floor((2(n-1)^3 - 3(n-1)^2 - 2(n-1) + 3)/24) + n, with true floors (equivalently integer floor division, since both numerators are nonnegative for n >= 0).", + "notes": "Conjecture as stated in OEIS: Conjecture: a(n) = 5*floor((2n^3 - 3n^2 - 2n + 3)/24) + floor((2(n-1)^3 - 3(n-1)^2 - 2(n-1) + 3)/24) + n, which fits all of the listed terms. [Corrected by _Alper Ferudun_, Oct 21 2026] (OEIS A057566, %F line; original conjecture by John W. Layman, Oct 2000)\n\nReferees: - OEIS A057566 revision #30 (Oct 22 2026): corrected floor conjecture (Layman 2000, corrected by Alper Ferudun Oct 21 2026), still marked \"Conjecture\". The same entry has R. J. Mathar's formula (May 23 2010), a(n) = n^3/2 - n^2 + n + (1-(-1)^n)/4, with g.f. x*(1-x+4x^2+2x^3)/((1+x)(x-1)^4) and the order-5 recurrence. The floor formula is equivalent to this closed form by a mod-24 residue check.\n- OEIS A334704 (Sloane 2020, data by Tom Duff): A057566 is row 3 of the m x n collinear-triple array. Cross-references checked: A000938 (Larrosa Cañestro gcd-sum formula, 2010; Guy & Kelly, Canad. Math. Bull. 11 (1968)), A047264, A010686.\n- Ko Yun Tung, Puk Hoi Chun, Yeung Wai Kwan, \"On the generalisations of the No-Three-in-Line problem\", Hang Lung Mathematics Awards 2025 (bronze), Thm 2.2.1: exact count S(p,q) of collinear triples by slope in an m x n lattice. It specializes to the 3 x n case.\n- No explicit proof of the floor form itself was found. Searched: arXiv 2607.24832 (S. Fried, Further proofs of conjectures from the OEIS) and arXiv 2609.25133 (neither treats A057566), MSE/MO, SeqFan archives, and the web.", + "date": "2026-10-29" + }, + { + "id": "OEIS-frontier/A060693", + "slug": "oeis-a060693", + "title": "Schulte's alternating quadratic sum over the Schröder-peaks triangle (A060693)", + "area": "Discrete geometry", + "source": "OEIS A060693", + "source_url": "https://oeis.org/A060693", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A060693.lean", + "decl": "def statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/Frontier/OEIS/A060693.lean", + "our_decl": "Math0.Frontier.A060693.result", + "summary": "Let T(n,k) be the number of Schröder paths from (0,0) to (2n,0) (steps U=(1,1), D=(1,-1), H=(2,0), never going below the x-axis) that have exactly k peaks (a peak is a U step immediately followed by a D step). Then for every n ≥ 0,\n Σ_{k=0}^{n} (-1)^k · T(n,k) · (n+1-k)^2 = 1 + n + n^2.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: Sum_{k=0..n} (-1)^k*T(n,k)*(n+1-k)^2 = 1+n+n^2. - _Werner Schulte_, Jan 11 2017\"\n\nReferees: Prior Lean proof: the-omega-institute/trureturing, PR #7436 by ElonSG, \"prove: OEIS A060693 Schröder-path peak identity (Schulte 2017)\", merged into dev on 2026-09-13 (https://github.com/the-omega-institute/trureturing/pull/7436). It supersedes PR #7402 (https://github.com/the-omega-institute/trureturing/pull/7402), with pre-registration issue #7384 (https://github.com/the-omega-institute/trureturing/issues/7384). The file is D5/S1/Recurrence/Invariants/SchroederPeakAlternatingQuadraticMoment.lean and the theorem is schulte_a060693. The result also follows directly from the OEIS A060693 formula T_n(x) = C_n(x+1) with C_n the Narayana row polynomial (Mitch Harris, Jan 2007), plus the Narayana values N(n,1)=1 and N(n,2)=n(n-1)/2 (A001263). The OEIS entry (local mirror, %I #147, Oct 04 2026) still says \"Conjecture\". The identity is not in the OEIS Open benchmark (arXiv:2608.11941; tadamcz.com/oeis-open results.json). LANTERN (arXiv:2609.32264), cited in the entry, is about cross-reference relations and does not address this conjecture.", + "date": "2026-10-21" + }, + { + "id": "OEIS-frontier/A062887", + "slug": "oeis-a062887", + "title": "Odd descending-by-2 multiples exist exactly when 125 does not divide 2n+1 (A062887)", + "area": "Sequences and series", + "source": "OEIS A062887", + "source_url": "https://oeis.org/A062887", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A062887.lean", + "decl": "Math0.Statements.A062887.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A062887.lean", + "our_decl": "Math0.Frontier.A062887.result", + "summary": "Call a positive integer N admissible if all of its decimal digits are odd and, reading from left to right, each digit is 2 less (mod 10) than the one before it. Examples are 975, 75, 319 and 9753197. Let a(n) be the smallest admissible multiple of 2n+1, or 0 if there is none. Then for every n ≥ 0, a(n) = 0 if and only if 125 divides 2n+1.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: The only numbers n for which a(n)=0 are those for which 2*n+1 is divisible by 125. - _Sean A. Irvine_, Apr 14 2023\"\n\nReferees: OEIS A062887 (Amarnath Murthy, 2001; conjecture added by Sean A. Irvine, Apr 14 2023; entry unchanged as of revision #12, checked in the local mirror dated 2026-10-17 and upstream oeisdata). Related: OEIS A062886 (Nathaniel Johnston, May 2011: zeros match 25 | 2n+1 for n ≤ 500, observed but not proved); OEIS A062885 (even-digit analogue: John W. Layman's argument for a(25) = −1, plus a Don Reble analysis file a062885.txt that I could not retrieve). Web searches (OEIS, MSE/MO-style queries, phrases about repeated 31975/97531 blocks and divisibility by 125) found no prior proof or counterexample.", + "date": "2026-10-19", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Standard facts: an integer is congruent mod 125 to its last three digits, and Euler's theorem (every number coprime to 10 divides some number made of a repeated decimal block, the usual repunit argument). The sibling entry A062886 already uses the same last-digits argument with modulus 25.", + "justification": "One direction is a finite check. Every admissible number either has at most two digits or ends in 975, 753, 531, 319 or 197, and none of these is divisible by 125. The other direction repeats the admissible block 31975 (which is divisible by 25) q times with q = phi(99999 m'). This is the textbook argument that a number coprime to 10 divides a suitable repunit. The whole proof takes under a page and uses only standard elementary number theory, so it is routine, even though the Lean formalization took real work.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A071685", + "slug": "oeis-a071685", + "title": "Reverse-divisor numbers are 1, 12, 78 or 89 mod 100 (A071685, Dale's conjecture)", + "area": "Sequences and series", + "source": "OEIS A071685", + "source_url": "https://oeis.org/A071685", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A071685.lean", + "decl": "def statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A071685.lean", + "our_decl": "Math0.Frontier.A071685.result", + "summary": "Let R(n) be the decimal digit reversal of n, with leading zeros dropped. Suppose n is not a palindrome (R(n) ≠ n), 10 does not divide n, and either n | R(n) or R(n) | n. Then n mod 100 is 1, 12, 78 or 89.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: every term mod 100 is equal to 1, 12, 78, or 89. - _Harvey P. Dale_, Dec 13 2017\"\n\nReferees: D. J. Hoey, \"Palintiples\", rec.puzzles archive (arithmetic/digits/palintiples.s), May 1992 (https://djm.cc/rpa-output/arithmetic/digits/palintiples.s): a finite-state classification of every base-10 N = C·R(N) with C > 1. C is 4 or 9, and N is 87…12 or 98…01. OEIS A031877 comment (Hasler 2014, annotated by Sloane Oct 19 2014): \"All terms are of the form 87...12 = 4*21...78 or 98...01 = 9*10...89. [This was proved by Hoey, 1992.]\" L. F. Klosinski and D. C. Smolarski, \"On the Reversing of Digits\", Math. Mag. 42 (1969) 208-210: k ∈ {1, 4, 9}. D. W. Wilson's theorem (1997) in A001232/A008918: terms are 99·m and 198·m with m a 0/1 palindrome with no singleton digits, so they are ≡ 89 and ≡ 78 (mod 100). N. J. A. Sloane, \"2178 And All That\", arXiv:1307.0453, Fib. Quart. 52 (2014) 99-120. L. H. Kendrick, \"Young Graphs: 1089 et al.\", J. Integer Seq. 18 (2015) 15.9.7. B. V. Holt, INTEGERS 14 (2014) A42. Webster and Williams, Math. Spectrum 45 (2012/13) 96-102. M. F. Hasler, A001232 comment (Oct 2022): terms begin and end with 109*89. Dale's conjecture (Dec 2017) came after all of these. The OEIS entry was not updated to mark it resolved, and I found no prior Lean formalization.", + "date": "2026-10-20" + }, + { + "id": "OEIS-frontier/A073642", + "slug": "oeis-a073642", + "title": "Yanev's identity for A073642 (sum of the positions of the 1-bits)", + "area": "Sequences and series", + "source": "OEIS A073642", + "source_url": "https://oeis.org/A073642", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A073642.lean", + "decl": "Math0.Statements.A073642.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A073642.lean", + "our_decl": "Math0.Frontier.A073642.result", + "summary": "Let a(n) be the sum of the positions of the 1-bits of n (if n = 2^b + 2^c + ... with distinct exponents, then a(n) = b + c + ...). Let A011371(n) = n - s(n), where s(n) is the number of 1's in the binary expansion of n; by Legendre's formula this equals v2(n!). Let A007814(k) = v2(k), the 2-adic valuation. Then for every n > 0, a(n) = (3*A011371(n) - Sum_{k=1..n} A007814(k)^2)/2, with the right-hand side computed exactly in Q.", + "notes": "Conjecture as stated in OEIS: A073642 (if n = 2^b+2^c+..., a(n)=b+c+...): \"Conjecture: a(n) = (3*A011371(n) - Sum_{k=1..n} A007814(k)^2)/2 for n > 0. - _Velin Yanev_, Sep 09 2017\". Siblings: A059906: \"Conjecture: a(n) = n - (1/2)*Sum_{k=1..n} (sqrt(2)^A007814(k) + (-sqrt(2))^A007814(k)) = -Sum_{k=1..n} (-1)^k * 2^floor(k/2) * floor(n/2^k). - _Velin Yanev_, Dec 01 2016\". A048702: \"Conjecture: a(n) = 2^floor(log_2(n)) * Sum_{i=1..n} 1/(2^v_2(i))\" and \"Conjecture: a(n) = n*2^floor(log_2(n)) - Sum_{i=1..floor(log_2(n))} 2^(floor(log_2(n)) - i)*floor(n/(2^i)).\"\n\nReferees: I found no prior resolution.\n- **OEIS entry.** A073642 (#121, Jul 05 2026) still lists \"Conjecture ... Velin Yanev, Sep 09 2017\", with no proof note or %E edit about it.\n- **Related OEIS entries.** A011371, A007814, A029931, A115364, A198192 and A198193 contain no such identity, and no OEIS sequence holds the partial sums of A007814(k)^2.\n- **Fried, \"Proofs of some conjectures of Yanev\" (2025).** This OEIS attachment covers only A000188, A001157 and A006519, and A073642 does not link to it.\n- **Fried's OEIS papers.** None of these mentions A073642: arXiv:2410.07237, JIS 28 (2025) Art. 25.4.3, JIS 29 (2026) Art. 26.1.8, and arXiv:2607.24832.\n- **Formalization datasets.** A073642 is not in google-deepmind/formal-conjectures, in Epoch's OEIS Open / LeanOpenProblems (arXiv:2608.11941), or in alphaproof-nexus-results.\n- **Ingredients of the proof.** These are classical: Legendre's formula v2(n!) = n - s2(n), and Sum_{k<=n} f(v2(k)) = Sum_j (f(j)-f(j-1)) floor(n/2^j). The identity also follows from Gutkovskiy's 2019 g.f. in the entry.", + "date": "2026-10-20", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Gutkovskiy's g.f. in the entry, (1/(1-x)) * Sum_{k>=1} k*x^(2^k)/(1+x^(2^k)), together with Legendre's formula A011371(n) = Sum_j floor(n/2^j) and the classical count Sum_{k<=n} f(v2(k)) = Sum_j (f(j)-f(j-1)) floor(n/2^j). Alternatively it follows directly from the binary-increment step n -> n+1 (Stephan's recursion in the entry gives the same thing).", + "justification": "The identity is equivalent to the local step 2a(n+1) + v2(n+1)^2 = 2a(n) + 3*v2(n+1). This is immediate: if n ends in t one-bits, then adding 1 clears bit positions 0..t-1 and sets bit t, so a(n+1) = a(n) - t(t-1)/2 + t. Summing this step over n is the whole proof. You can also get it in a few lines by writing both sides as Sum_j c_j*floor(n/2^j), using Legendre's formula and the standard count of multiples of 2^j, or by reading it off Gutkovskiy's g.f. in the entry. It takes a few lines of classical bit-counting, and the manuscript itself says it claims no new method.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A075855", + "slug": "oeis-a075855", + "title": "The longest path on the black squares of an even chessboard has (n^2-n+2)/2 squares (A075855)", + "area": "Discrete geometry", + "source": "OEIS A075855", + "source_url": "https://oeis.org/A075855", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A075855.lean", + "decl": "Math0.Statements.A075855.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A075855.lean", + "our_decl": "Math0.Frontier.A075855.result", + "summary": "Let n = 2m be even, with m >= 1. Use the n x n board with rows and columns numbered 0..n-1, and call square (i,j) black when i+j is even. Two black squares are adjacent when they are diagonal neighbours, that is |di| = |dj| = 1. A path is a sequence of distinct black squares in which each square is adjacent to the next. Claim: the largest number of squares on such a path is a(n) = (n^2 - n + 2)/2 = 2m^2 - m + 1. In the frozen statement, a n is computed by exhaustive search, and the file's lemma a_spec shows it is the greatest path length.", + "notes": "Conjecture as stated in OEIS: %F A075855: \"For n odd, a(n)=(n-1)^2/2+1. For n even, it is conjectured that a(n)=(n^2-n+2)/2 (it is easy to show this is a lower bound).\" (entry by Jon Perry, Oct 15 2002; edited by Dean Hickerson, Oct 25 2002). Barker's 'Empirical g.f.' (Apr 12 2012) is equivalent.\n\nReferees: - USAMO 2008 Problem 3 (proposed by Gabriel Carroll): S_n = {(x,y) in Z^2 : |x|+|y+1/2| < n} cannot be partitioned into fewer than n unit-step paths. Under the isomorphism (i,j) -> ((i-j)/2, (i+j)/2 - m), S_m is the graph of black squares of the 2m x 2m board with diagonal adjacency. Adding the uncovered squares as one-point paths then gives the A075855 upper bound 2m^2 - m + 1 directly. See the AoPS wiki page 2008_USAMO_Problems/Problem_3 and Evan Chen's USAMO 2008 solution notes.\n- Evan Chen, \"Iberoamerican 2019/5\" (Twitch Solves ISL Ep. 109), https://web.evanchen.cc/twitch/Ep109-Iberoamerican-2019-5-Solution.pdf. It uses USAMO 2008/3 as the claim that the \"blue zigzags\" (the diagonal-move graph on one colour class of a (2m)x(2m) vertex grid) need at least m paths.\n- Lean formalization of USAMO 2008/3: compfiles, https://github.com/dwrensha/compfiles/blob/main/Compfiles/Usa2008P3.lean (problem usa2008_p3; no sorry).\n- OEIS A075855 (Jon Perry, 2002; edited by Dean Hickerson) still states the even case as a conjecture. OEIS A249333 (Richard Stanley) cross-references it as \"conjecturally the same as b(n+1) for A075855\", which this result also settles.\n- I found no explicit statement anywhere of the A075855 to USAMO 2008/3 link. The classification rests on this one-line reduction to a known theorem, not on a direct citation.", + "date": "2026-10-19" + }, + { + "id": "OEIS-frontier/A081200", + "slug": "oeis-a081200", + "title": "Collinear 5-point sets in the grid {0,…,4}^n number (7^n − 5^n)/2 (Hardin's conjecture, A081200)", + "area": "Discrete geometry", + "source": "OEIS A081200", + "source_url": "https://oeis.org/A081200", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A081200.lean", + "decl": "Math0.Statements.A081200.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A081200.lean", + "our_decl": "Math0.Frontier.A081200.result", + "summary": "For every n ≥ 0, the number of 5-element subsets of the grid {0,1,2,3,4}^n ⊂ ℝ^n that lie on one real line equals a(n) = Σ_{k=0}^{n} C(n,k)·6^{n−k}·(k mod 2), the 6th binomial transform of 0,1,0,1,…. Equivalently the count is (7^n − 5^n)/2.", + "notes": "Conjecture as stated in OEIS: %C A081200 Conjecture (verified up to a(9)): Number of collinear 5-tuples of points in a 5 X 5 X 5 X ... n-dimensional cubic grid. - Ron Hardin, May 24 2010\n\nReferees: P. Erdős and J. L. Selfridge, \"On a combinatorial game\", J. Combin. Theory Ser. A 14 (1973) 298-301 (states that the n-dimensional hypercube of side k has ((k+2)^n - k^n)/2 winning lines; k=5 gives (7^n-5^n)/2 = A081200); S. W. Golomb and A. W. Hales, \"Hypercube Tic-Tac-Toe\", More Games of No Chance, MSRI Publ. 42 (2002), 167-182, Theorem 1 (same count, same word encoding and 2-to-1 reversal proof; work dates to before 1972); the border-shell proof is credited to Leo Moser in R. Honsberger, Mathematical Morsels (cut-the-knot.org/proofs/tictactoe.shtml); O. Patashnik, \"Qubic: 4x4x4 Tic-Tac-Toe\", Math. Mag. 53 (1980) (k^n game has ((k+2)^n - k^n)/2 lines); OEIS A005059 (k=3 analogue stated without a conjecture label, D. W. Wilson c. 1999). Related open Hardin comments that the same argument settles: A081199 (k=4) and A081201 (k=6).", + "date": "2026-10-24" + }, + { + "id": "OEIS-frontier/A083020", + "slug": "oeis-a083020", + "title": "3^(3^18) + 2 is divisible by 31^2, so Hilliard's squarefree conjecture (A083020) fails", + "area": "Discrete geometry", + "source": "OEIS A083020", + "source_url": "https://oeis.org/A083020", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A083020.lean", + "decl": "def statement", + "category": "OEIS conjecture" + }, + "mode": "settles-refutes", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A083020.lean", + "our_decl": "Math0.Frontier.A083020.result", + "summary": "The conjecture (Cino Hilliard, 2003, OEIS A083020) says that 3^(3^n) + 2 is squarefree for every n ≥ 0. We prove it is false: 31^2 = 961 divides 3^(3^18) + 2, so that number is not squarefree.", + "notes": "Conjecture as stated in OEIS: %C A083020 Conjecture: These numbers have no repeating factors or 3^(3^n) + 2 is squarefree. (entry by Cino Hilliard, May 31 2003)\n\nReferees: I found no prior resolution. Sources checked: the OEIS A083020 entry (local mirror and https://raw.githubusercontent.com/oeis/oeisdata/main/seq/A083/A083020.seq, revision #20 of Jan 04 2026, which still states the conjecture with no refutation), cross-referenced/related entries A055777, A129290, A129291, A113913, A140331 and A061678, R. Stephan's \"Prove or Disprove. 100 Conjectures from the OEIS\" (arXiv:math/0409509, which does not contain A083020), and primepuzzles.net Conjecture 107 (unrelated). I also ran web searches for \"3^(3^n)+2 squarefree\", \"Cino Hilliard 3^3^n+2 seqfan\" and \"3^{3^n}+2 squarefree mathoverflow/stackexchange\". None of these reported a counterexample or a proof.", + "date": "2026-10-21", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Euler's theorem (3^930 ≡ 1 mod 31^2) plus a direct search for a prime p and an n with p^2 | 3^(3^n)+2", + "justification": "The refutation is a single explicit counterexample: 31^2 divides 3^(3^18)+2. To find it you reduce 3^n modulo φ(p^2) for small primes p and check whether 3^(3^n) ≡ -2 (mod p^2). This is a short modular-exponentiation search, and a few lines of code find (n, p) = (18, 31) at once. Checking it only needs Euler's theorem and the congruence 3^159 ≡ -2 (mod 961). No new idea or construction was needed, and the counterexample is a genuine failure of the conjecture as its author meant it, not a degenerate case.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A086004", + "slug": "oeis-a086004", + "title": "There are no 5-Rotation Cycle Primes (A086004, Conjecture 2)", + "area": "Sequences and series", + "source": "OEIS A086004", + "source_url": "https://oeis.org/A086004", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A086004.lean", + "decl": "Math0.Statements.A086004.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A086004.lean", + "our_decl": "Math0.Frontier.A086004.result", + "summary": "Let rot be the rotation of A086002. For a number n with d decimal digits, rot(n) swaps the block of the first floor(d/2) digits with the block of the last floor(d/2) digits; when d is odd, the centre digit stays where it is. Let f(n) = n + rot(n). Then no prime p has f(p), f^2(p), f^3(p), f^4(p) and f^5(p) all prime.", + "notes": "Conjecture as stated in OEIS: \"Conjecture 2: There are no 5-Rotation Cycle Primes.\" (A086004, entry by _Chuck Seggelin_, Jul 07 2003. Conjecture 1 was settled by R. J. Mathar in 2009. Chai Wah Wu added on Aug 20 2015 that 4-rotation cycle primes exist (A261458), and in A261458 he proved there are none surviving 6 applications.)\n\nReferees: I found no prior resolution. OEIS A086004 (Seggelin 2003, last edited Jun 2025) still lists Conjecture 2 as open. OEIS A261458 (Chai Wah Wu, Aug 2015) proves the weaker statement that no chain of 6 steps exists, using a leading-digit/carry argument, and gives 4-step examples such as 10010905789. Mathar's 2009 comment on A086004 proves Conjecture 1 (even digit counts) only. Web searches (OEIS-indexed pages, arXiv, StackExchange-style queries, primepuzzles) found nothing on the 5-step case. The SeqFan archive could not be reached from here, so it was not checked.", + "date": "2026-10-19", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Mathar's factorization f(n) = (10^k+1)(a+b) for even digit counts (A086004 comment) and Wu's no-carry, fixed-digit-length argument in A261458, together with the elementary block decomposition f(n) = 10^(m+1)S + 2M*10^m + S", + "justification": "The proof is a one-page argument about decimal digits. It reuses Mathar's factorization for even digit counts and Wu's setup from A261458, where the first four iterates must keep the same odd number of digits. On top of that it makes one simple observation: the centre digit M becomes 2M mod 10, and if M is at most 4 then f(n) is fixed by the rotation, so the next iterate is 2f(n) and cannot be prime. A five-case check on the centre digit (it must run 9, 8, 6, 2) then finishes the proof. Wu stopped at six steps in 2015, but the extra step uses a short and standard idea that a competent mathematician working from the material in the entry and its cross-references would find quickly.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A090905", + "slug": "oeis-a090905", + "title": "A090905: every row ends at twice the largest prime of the previous row (Murthy's conjecture proved)", + "area": "Discrete geometry", + "source": "OEIS A090905", + "source_url": "https://oeis.org/A090905", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A090905.lean", + "decl": "Math0.Statements.A090905.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A090905.lean", + "our_decl": "Math0.Frontier.A090905.result", + "summary": "Split 1, 2, 3, ... into consecutive groups. Group 1 is (1). Group n+1 starts right after group n. Its length is the least k ≥ len(n) such that the product of group n divides the product of group n+1. Let B_k be the Bertrand primes A006992: B_1 = 2, and B_{k+1} is the largest prime below 2B_k.\n\nClaim: for every n > 4,\n- group n-1 has a largest prime p,\n- the last term of group n is 2p,\n- p = B_{n-1}.", + "notes": "Conjecture as stated in OEIS: %C Conjecture: For n > 4 the last term of the n-th group is 2p where p is the largest prime in the (n-1)th group. And these are the Bertrand primes. (Amarnath Murthy, Dec 13 2003)\n\nReferees: I found no prior proof or refutation.\n- OEIS A090904, A090905, A090906 and A090907 (Murthy, Dec 2003; last edited Dec 2016) state the claim only as a conjecture. A090907 adds \"verified for 4= 5, without proof.\n- Related: A113117 and A113118 (L. Quet, 2006), A093911 (Murthy's variant), and A006992 (Bertrand primes).\n- The key analytic input is Nagura's theorem (J. Nagura, Proc. Japan Acad. 28 (1952) 177-181: for x >= 25 there is a prime between x and 6x/5). The Lean development reproves the form it needs (a prime in (5x/3, 2x) for x >= 83) from scratch.\n- Searches of arXiv, MathOverflow/MSE, SeqFan-style queries and the formal-conjectures repository found no prior resolution and no prior formalization.", + "date": "2026-10-20", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Nagura's theorem (1952: a prime in (x, 6x/5) for x >= 25), which gives the ratio bounds 5/3 between consecutive Bertrand primes (A006992), combined with Legendre's formula for the factorial divisibility (2a)!^2 | (2b)!(2c)! and a finite computer check of the first rows", + "justification": "Take consecutive Bertrand primes b < a < c, so that row n is [2b+1, 2a]. The prime c lies in row n, and the first multiple of c after 2a is 2c, so the next row must reach 2c. Ending at 2c is enough because (2a)!^2 divides (2b)!(2c)!, which follows from a short Legendre-formula check on floor functions plus a small prime-power case. The only deep input is a known prime-gap bound (Nagura 1952), and the first rows are checked by computer. The whole argument is elementary and fits in about a page; the scouting pass found it straight away. The long Lean file mostly reproves Nagura's bound with Chebyshev weights, which is formalization work, not a new idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A091817", + "slug": "oeis-a091817", + "title": "Quet's integrality conjecture for A091817 holds", + "area": "Number theory", + "source": "OEIS A091817", + "source_url": "https://oeis.org/A091817", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A091817.lean", + "decl": "Math0.Statements.A091817.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A091817.lean", + "our_decl": "Math0.Frontier.A091817.result", + "summary": "For every prime p >= 3, write H(p-3) = 1 + 1/2 + ... + 1/(p-3) = N/D in lowest terms (H(0) = 0/1). Then p divides 2N - 3D. Equivalently, every term a(n) = (2N - 3D)/p of OEIS A091817 (p the (n+1)-th prime, n >= 1) is an integer.", + "notes": "Conjecture as stated in OEIS: Leroy Quet conjectures that the terms are always integral. This is true for p < 3*10^4. (Entry: (2*numerator(H(p-3)) - 3*denominator(H(p-3)))/p, Bouayoun and Stephan, Mar 07 2004)\n\nReferees: - OEIS A091817 and its history (oeis.org/history?seq=A091817): the conjecture is still stated as open, verified for p < 3*10^4, and has no proof note.\n- Classical source: H(p-1) ≡ 0 (mod p) (Wolstenholme 1862; Hardy & Wright, An Introduction to the Theory of Numbers, Thm 115).\n- Explicit reflection congruence H_{p-k} ≡ H_{k-1} (mod p), 1 <= k <= p-1: Z.-W. Sun & L.-L. Zhao, \"Arithmetic theory of harmonic numbers (II)\", Colloq. Math. 130 (2013), 67-78, arXiv:0911.4433 (proof of (2.2)). Taking k = 3 gives H_{p-3} ≡ 3/2 (mod p), which settles the conjecture at once.\n- The same lemma is cited in arXiv:1108.2361 (Lemma 2.1 of its ref. [13]) and arXiv:1803.02966.\n- Analogous k = 2 fact in OEIS A064169 (Adamchuk, Jun 09 2006: p divides a(p-2)).\n- No prior formalization found:\n - not in google-deepmind/formal-conjectures (checked locally at commit c77fdd4);\n - not among the OEIS Open benchmark statements (Adamczewski, arXiv:2608.11941);\n - no other formal proof turned up in searches.", + "date": "2026-10-18" + }, + { + "id": "OEIS-frontier/A092054", + "slug": "oeis-a092054", + "title": "Convergents of [1; 1/2, 1/3, ..., 1/n]: numerator + denominator = 2^(v2(n!) + v2((n+1)!)) (A092054)", + "area": "Number theory", + "source": "OEIS A092054", + "source_url": "https://oeis.org/A092054", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A092054.lean", + "decl": "Math0.Statements.A092054.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A092054.lean", + "our_decl": "Math0.Frontier.A092054.result", + "summary": "For every n >= 1, write the convergent [1; 1/2, 1/3, ..., 1/n] = 1 + 1/(1/2 + 1/(1/3 + ... + 1/(1/n))) in lowest terms as p/q. Then p + q is a power of 2, namely p + q = 2^a(n). Here a(n) is the base-2 logarithm, and a(n) = Sum_{k=1..n} A001511(floor((k+1)/2)) = 2n + 1 - s2(n) - s2(n+1) = A011371(n) + A011371(n+1). In these formulas A001511 is the ruler function, s2 = A000120 is the binary digit sum, and A011371(m) = m - s2(m).", + "notes": "Conjecture as stated in OEIS: It appears that a(n) = Sum_{k=1..n} A001511(floor((k+1)/2)). Equivalently, a(n) = 2n + 1 - A000120(n) - A000120(n+1) = A011371(n) + A011371(n+1). - _Franklin T. Adams-Watters_, Feb 02 2006\n\nReferees: No prior explicit proof of A092054's conjectured formula found. Relevant partial or adjacent sources:\n- OEIS A092054 (#43, Aug 09 2026): the formula is still marked \"It appears\".\n- M. A. Suchenek, \"Elementary Yet Precise Worst-Case Analysis of Floyd's Heap-Construction Program\", Fundamenta Informaticae 120 (2012) 75-92, doi:10.3233/FI-2012-751. It proves 2N-2s2(N)-e2(N) for heap construction, which is algebraically equivalent to the conjectured formula. It does not prove the continued-fraction statement; the link to A092054 rests only on an OEIS comment.\n- OEIS A001901: reduced Wallis numerators, \"Subsequence of A000079\" (powers of 2). Ordowski (2024): A001901(n) = numerator of [1;1,1/2,...,1/n].\n- OEIS A056982 (Weisstein): 4^A005187(n) = denominator of prod_{k<=n}(1-1/(4k^2)). This gives the even-index exponent.\n- OEIS A001902 and A092053 (Hanna 2004): the convergent numerators are the Wallis denominators.\n- N. A. Draim, \"Pi in the form of a continued fraction with infinite terms\", Fibonacci Quarterly 7.3 (1969) 275-276, https://www.mathstat.dal.ca/FQ/Scanned/7-3/draim.pdf: Wallis partial products equal the convergents of a continued fraction with partial numerators (n-1)n.\n- Kummer/Legendre: v2(C(2m,m)) = s2(m), v2(m!) = m - s2(m).", + "date": "2026-10-21", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The cross-referenced entries already link the convergents to the partial Wallis products (A001902 and A092053 comments; Ordowski's [1;1,1/2,...,1/n] formula in A001901/A001902; Draim 1969), and A001901 is recorded as a subsequence of the powers of 2. Combine this with the closed form W(2m) = 16^m/((2m+1)·C(2m,m)^2), Kummer's theorem v2(C(2m,m)) = s2(m) (also in A056982 for even n), and Legendre's formula v2(m!) = m - s2(m).", + "justification": "The proof writes the convergents as P(n)/Q(n) using a three-term recurrence and checks closed forms for P and P+Q by a short induction. The odd parts of the factorials divide the odd double factorial because C(2m,m) is an integer, and Legendre's formula gives the exponent. Each step is standard: the link to Wallis products and the power-of-2 property are already recorded in the cross-referenced entries, and the manuscript itself calls the result a short consequence of classical facts. The informal argument is about a page; most of the work went into the Lean formalization.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A093726", + "slug": "oeis-a093726", + "title": "Imaginary parts of the convergents of [1+i; 1+i, 1+i, ...] are A317974(n+1)/A138573(n)", + "area": "Number theory", + "source": "OEIS A093726", + "source_url": "https://oeis.org/A093726", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A093726.lean", + "decl": "Math0.Statements.A093726.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A093726.lean", + "our_decl": "Math0.Frontier.A093726.result", + "summary": "Let c_n = (1+i) + 1/((1+i) + ... + 1/(1+i)) be the continued fraction with n partial quotients 1+i, so c_1 = 1+i and c_{n+1} = (1+i) + 1/c_n. Write c_n = (A093725(n) + a(n) i)/A093727(n) in Mathematica's Numerator/Denominator form (A093727(n) = lcm of the denominators of Re c_n and Im c_n). Let A317974 be 0,0,1,1 and A138573 be 0,1,2,5, both continued by u(n) = 2(u(n-1)+u(n-2)+u(n-3)) - u(n-4). Then for every n >= 1, a(n)/A093727(n) = A317974(n+1)/A138573(n) as rational numbers.", + "notes": "Conjecture as stated in OEIS: Conjecture: a(n)/A093727(n) = A317974(n+1)/A138573(n). - _Zhuorui He_, Jun 16 2026\n\nReferees: OEIS A093726 rev #13 (Jun 20 2026): the formula is still marked \"Conjecture: a(n)/A093727(n) = A317974(n+1)/A138573(n). - Zhuorui He, Jun 16 2026\"; there is no later %E edit recording a proof. Related prior work: Peter Bala's 2014 formula in OEIS A138573 that A138573(n) = |U(n)|^2 for the Gaussian Lucas sequence U(n) = (1+i)U(n-1) + U(n-2), which covers the denominator part only. A317974 (rev #35, Jun 30 2026) has no relevant formula. Not covered by S. Fried, \"Further proofs of conjectures from the OEIS\", arXiv:2607.24832 (Jul 2026); I checked its full text for the A-numbers. Fried's earlier papers (arXiv:2410.07237; JIS 2025 and 2026) predate the conjecture. No MathOverflow, Math StackExchange, SeqFan or arXiv resolution found. Sources: https://raw.githubusercontent.com/oeis/oeisdata/main/seq/A093/A093726.seq, https://arxiv.org/abs/2607.24832", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The classical continuant formula c_n = U(n+1)/U(n) for U(n) = (1+i)U(n-1) + U(n-2), together with Peter Bala's 2014 formula in A138573: A138573(n) = |U(n)|^2, and the o.g.f. as a Hadamard product of x/(1-(1+i)x-x^2) and x/(1-(1-i)x-x^2). The same Hadamard-product argument puts Im(U(n+1) conj U(n)) in the signature-(2,2,2,-1) recurrence space, so four initial values match it with A317974(n+1).", + "justification": "The convergent is c_n = U(n+1)/U(n) = U(n+1)conj(U(n))/|U(n)|^2 for the Gaussian continuants U. A138573 already records that the denominator |U(n)|^2 equals A138573(n). The numerator's imaginary part Q(n) = Im(U(n+1)conj U(n)) is built from the same characteristic roots, so it satisfies the same order-4 recurrence. Matching four initial values identifies it with A317974(n+1). The whole argument is standard continued-fraction and linear-recurrence bookkeeping, plus a short check that a(n)/A093727(n) is just Im c_n. It fits in well under a page and leans mainly on a formula already in a cross-referenced entry.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A097154", + "slug": "oeis-a097154", + "title": "The only fixed points of reverse(x) - maxdigit(x) are 0 and 89", + "area": "Sequences and series", + "source": "OEIS A097154", + "source_url": "https://oeis.org/A097154", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A097154.lean", + "decl": "Math0.Statements.A097154.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A097154.lean", + "our_decl": "Math0.Frontier.A097154.result", + "summary": "For a natural number x, let rev(x) be its decimal reversal (rev 0 = 0, trailing zeros are dropped) and maxdig(x) its largest decimal digit (maxdig 0 = 0). Let f(x) = rev(x) - maxdig(x). Then f(x) = x if and only if x = 0 or x = 89.", + "notes": "Conjecture as stated in OEIS: \"a(89)=-1 because 89 is the first number that will not reach zero: 98-9=89. It is conjectured that 0 and 89 are the only fixed points of f.\" (A097154, entry by _Jason Earls_, Aug 01 2004. The same sentence appears in A097155 and A097157.)\n\nReferees: **OEIS (local mirror, cross-checked against the current raw GitHub oeisdata files).**\n- A097154 (#4, Dec 15 2017), A097155 (#11, last edited Aug 29 2025) and A097157 (#3) all still say \"It is conjectured that 0 and 89 are the only fixed points of f\".\n- None has an %E line, comment, formula or link recording a proof or counterexample. A097155's only %E is a 2011 data correction by Harvey P. Dale.\n- The cross-referenced entries A097153, A097156 and A097158 (Earls, Aug 2004; extensions by Robert G. Wilson v and Klaus Brockhaus) are purely computational.\n- A grep of the whole local oeisdata mirror finds no other entry that references A097153 through A097158.\n\n**Web searches.** Queries covered the exact map text, \"reversal minus largest digit\", SeqFan 2004, Math StackExchange/MathOverflow-style phrasing, and an extended search. None found a proof.\n- Hits were only the OEIS pages themselves.\n- Unrelated digit-reversal work also came up: arXiv 2410.11784 (1089 attractor), arXiv 2404.06656 (reverse divisors), arXiv math/0511366, and OEIS A393794 (fixed points of the 1089-trick map, Havenaar 2026, a different map).\n- A GMAT forum problem covers only the two-digit equation reverse(n) = n + 9, which has eight solutions (12, ..., 89). That is a different condition and does not address this conjecture.\n\nNo prior resolution was found, so this appears to be the first written proof, and it is Lean-verified.", + "date": "2026-10-19", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The standard fact that a number is congruent to its digit sum mod 9, so rev(x) ≡ x (mod 9). This forces maxdig(x) = 9 at a nonzero fixed point. A units-digit comparison mod 10 and a size bound then finish it.", + "justification": "A fixed point satisfies rev(x) = x + maxdig(x). Reversal keeps the digit sum, so maxdig(x) must be divisible by 9, which leaves only rev(x) = x + 9. Comparing the leading and units digits mod 10 and bounding the middle block then gives x = 10a + (a+1), and the largest-digit condition picks out 89. That is under a page of textbook digit arithmetic that a competent mathematician would find quickly. The entry itself carries the keyword 'easy', and the length of the Lean proof reflects formalization effort, not mathematical depth.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A106505", + "slug": "oeis-a106505", + "title": "A106505: common sides of A/2A primitive triangles are periodic mod 8, so a(n+5) = a(n) + 8", + "area": "Discrete geometry", + "source": "OEIS A106505", + "source_url": "https://oeis.org/A106505", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A106505.lean", + "decl": "Math0.Statements.A106505.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A106505.lean", + "our_decl": "Math0.Frontier.A106505.result", + "summary": "Let IsSide(c) mean there are natural numbers x, y such that x, y, c are the sides of a non-degenerate triangle in which the angle opposite y is twice the angle opposite x, and gcd(x, y, c) = 1. Let a(n) be the n-th smallest such c (1-indexed): 5, 7, 9, 11, 13, 15, 16, 17, ... Then a(n+5) = a(n) + 8 for every n > 2 (Ralf Stephan's conjecture in OEIS A106505).", + "notes": "Conjecture as stated in OEIS: \"Conjecture: for n>2, a(n+5) = a(n) + 8. - _Ralf Stephan_, Nov 16 2010.\" Also: \"Empirical g.f.: ... - _Colin Barker_, Oct 05 2013\"\n\nReferees: No earlier proof found. OEIS A106505 (GitHub oeisdata main, rev #21, Apr 23 2021) still states it as a conjecture (Ralf Stephan, Nov 16 2010), with an empirical g.f. by Colin Barker (2013). OEIS A321499 (M. F. Hasler, Nov 2018; rev #24, Feb 2025) proves that {d²(2m+d)} = odd numbers > 1 together with multiples of 8 > 8, and records a(n+5) = a(n) + 8 for A321499 (D. A. Corneth). It still says \"Cf. A106505 (conjectured to be the sequence without the 3)\". The closely related A321501 complement analysis (Hasler) is also there. Related OEIS entries: A343063 and A343064 (B. Schott, 2021), which give the parametrization a = m² − k², b = mk, c = k² with gcd(m,k) = 1 and k < m < 2k, but no set characterization; and A229849, which says A106505 \"seems\" to give those values. Parametrization background: M. N. Deshpande, Math. Gazette (2002); K. Zelator, arXiv 1208.0497; R. S. Luthar (1984). None of these addresses the conjecture. Not covered in S. Fried, arXiv 2410.07237 or arXiv 2607.24832, nor in Adamczewski's OEIS Open benchmark (arXiv 2608.11941), which uses the Tsoukalas et al. dataset in epoch-research/LeanOpenProblems; also absent from google-deepmind/formal-conjectures.", + "date": "2026-10-19", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The entry's own %F formula: the terms are the values s^2 - r^2 with r < s < 2r and gcd(r,s) = 1 (classical parametrization of A/2A triangles, Luthar 1984; A343063). With that formula, a parity argument mod 8 plus the families (m, m+1) and (2j+1, 2j+3) give the set {odd >= 5} together with {8m : m >= 2}. Cross-reference A321499 (Hasler) already proves the same set with 3 added and records a(n+5) = a(n) + 8 there.", + "justification": "The proof works out the set of common sides. A coprime difference of squares s^2 - r^2 is either odd or divisible by 8. Two one-line families of triangles realize every odd c >= 5 and every multiple of 8 from 16 on, and the small cases are checked by hand. Since the set is periodic mod 8 with five residues per period, the recurrence follows at once. This is about half a page of elementary number theory, using the formula already given in the entry, and the cross-referenced A321499 already contains the same set characterization. The Lean work (deriving y^2 = x(x+c) from the arccos definition, plus the counting with Nat.nth) is formalization effort and adds no mathematical depth.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A113676", + "slug": "oeis-a113676", + "title": "The Golomb-row triangle A113676 and Levine's sequence A014644", + "area": "Discrete geometry", + "source": "OEIS A113676", + "source_url": "https://oeis.org/A113676", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A113676.lean", + "decl": "Math0.Statements.A113676.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A113676.lean", + "our_decl": "Math0.Frontier.A113676.result", + "summary": "Let G be Golomb's sequence A001462 (G(1)=1, G(2)=G(3)=2, G(4)=G(5)=3, ...; n occurs G(n) times, nondecreasing). Let H be G with one 2 removed: H(1)=1 and H(j)=G(j+1) for j>=2. Cut H into consecutive rows: row 1 is [H(1)], and row n+2 has as many terms as the sum of row n+1. Let a(n) be the length of row n. Levine's array has row 1 = [1,1], and row k+1 lists 1 c_1 times, 2 c_2 times, ..., where row k = [c_1, c_2, ...]. A014644(k) is the last term of Levine row k. Claim (both conjectures of van Lamoen and Hanna, 2005): (1) for every n>=2, a(n) = A014644(n+2) - A014644(n+1); (2) the last term of row 1 is A014644(1), and for every n>=2 the last term of row n is A014644(n+1).", + "notes": "Conjecture as stated in OEIS: %C Conjecture: a(n) for n>1 gives first differences of Lionel Levine's sequence A014644(n) for n>=3. %C Conjecture: Final elements of the rows form A014644 except for duplicate 2. (Floor van Lamoen and Paul D. Hanna, Nov 06 2005)\n\nReferees: No prior proof found.\n- OEIS A113676 (van Lamoen & Hanna, Nov 2005; rev #9, Mar 2025) still lists both conjectures.\n- OEIS A001462 has van Lamoen's related conjecture (Nov 06 2005), still unresolved in the Aug 2026 revision.\n- OEIS A014643 has the %Y note \"Rows converge to A001462\".\n- J. Claes and R. Miyamoto, \"Golombic and Levine sequences\", arXiv:2602.10992 [math.CO] (Feb 2026), p. 3, eqs. (3)–(4). It observes that Γ maps the first n Golomb terms to the first A001463(n) terms (so the A014643 rows are Golomb prefixes), and that |a| = #Γa and #a = (Γa)(|a|). These are the key ingredients, but the paper does not mention A113676 or prove its conjectures.\n- Cross-checked entries: A014644, A014643, A011784, A012257, A001463, A113722, A113724, A113730 and A304679. None records a resolution.", + "date": "2026-10-20", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The fact that from row 2 on, the rows of Levine's array (A014643) are initial segments of Golomb's sequence A001462. A014643's cross-reference note \"Rows converge to A001462\" points to this, and Claes and Miyamoto, arXiv:2602.10992, p. 3, eqs. (3)-(4) state it: the Levine step maps the first n Golomb terms to the first A001463(n) terms. Golomb's self-describing property gives it at once.", + "justification": "The one real idea is that each Levine row from row 2 on is a prefix of Golomb's sequence, so its sum is the length of the next row. That is immediate from Golomb's self-describing property and is already known: A014643 hints at it and Claes and Miyamoto state it. Everything else is a telescoping sum and a short induction showing that the triangle's rows are the blocks of G between consecutive Levine row lengths; both conjectures then follow. The whole argument fits in about a page of elementary steps, and the manuscript itself calls the result \"a short consequence\" of known facts.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A115026", + "slug": "oeis-a115026", + "title": "A115026 has a term greater than 370: a(119) = 371", + "area": "Sequences and series", + "source": "OEIS A115026", + "source_url": "https://oeis.org/A115026", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A115026.lean", + "decl": "Math0.Statements.A115026.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-refutes", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A115026.lean", + "our_decl": "Math0.Frontier.A115026.result : ¬ Math0.Statements.A115026.statement", + "summary": "Let F(m) be the sum of d^L over the decimal digits d of m, where L is the number of digits of m (A101337). For n >= 1, a(n) is the smallest element of the cycle that the orbit n, F(n), F(F(n)), ... eventually enters (A115026). Harvey P. Dale conjectured that a(n) <= 370 for all n >= 1. This is false: a(119) = 371.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: no term is greater than 370. - _Harvey P. Dale_, Jun 08 2022\"\n\nReferees: OEIS A151543, \"Smallest precursor of n-th cycle in the 'Recurring Digital Invariant Variant' problem\" (N. J. A. Sloane, May 15 2009, based on an email from Eric Angelini, Feb 18 2009, with a cycle table by Hans Havermann). Its table entry \"13 { 119, 1, {371}}\" names 119 as the smallest number whose orbit under A101337 ends in the fixed point 371, so a(119) = 371. The same table has \"19 { 407, 1, {407}}\" and other cycles with minima above 370. Related pre-2022 OEIS entries: A151544 (2009) lists the cycle elements, including 371 and 407. A157714 (Havermann, Mar 2009) lists numbers in cycles of period greater than 1, such as 2929 and 18829. A005188 lists the narcissistic numbers 153, 370, 371, 407, 1634, ...; since 371 is a fixed point, a(371) = 371 > 370 trivially. Angelini's page \"A Recurring Digital Invariant Variant\" is at cetteadressecomportecinquantesignes.com/RecurDigit.htm, with a cached copy at oeis.org/A151543/a151543.pdf. The A115026 entry itself (revision #12, Jun 08 2022, unchanged upstream) still states the conjecture and has no correction or %E extension. Web searches found no explicit published retraction of Dale's comment. Sources: https://oeis.org/A115026, https://oeis.org/A151543, https://en.wikipedia.org/wiki/Narcissistic_number", + "date": "2026-10-18" + }, + { + "id": "OEIS-frontier/A116184", + "slug": "oeis-a116184", + "title": "A116184: Adamchuk's conjectures on 37^3 dividing the numerator of sum_{k=1}^{36} 1/k^n", + "area": "Number theory", + "source": "OEIS A116184", + "source_url": "https://oeis.org/A116184", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A116184.lean", + "decl": "Math0.Statements.A116184.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A116184.lean", + "our_decl": "Math0.Frontier.A116184.result", + "summary": "Let H(n) = sum_{k=1}^{36} 1/k^n, a rational number. Claim (a): for every k >= 0, 37^3 divides the numerator of H(3 + 36k). Claim (b): if p > 37 is a prime and 37^3 divides the numerator of H(p), then p = 37k - 1 for some natural number k, that is, p ≡ -1 (mod 37).", + "notes": "Conjecture as stated in OEIS: Conjecture: All terms of the arithmetic progression 3+36k belong to a(n). ... It appears that all primes in a(n) that are greater than 37 are of the form 37k-1. (Alexander Adamchuk, Apr 08 2007)\n\nReferees: No explicit prior resolution of the A116184 conjecture found. OEIS A116184 is unchanged (rev #6, Feb 16 2025) with no %E line or resolving comment, and no other mirror entry cross-references it. Classical ingredients that make it an easy corollary:\n- J.W.L. Glaisher, Q. J. Math. 31 (1900) 321-353: H(p-1,m) ≡ -m(m+1)/(2(m+2))·p^2·B_{p-2-m} (mod p^3) for odd m ≤ p-3.\n- Z.-H. Sun, \"Congruences concerning Bernoulli numbers and Bernoulli polynomials\", Discrete Appl. Math. 105 (2000) 193-223: Thm 5.1(a) (k ≤ p-4) and the power-sum formula S_k ≡ pB_k + (p^2/2)kB_{k-1} + (p^3/6)k(k-1)B_{k-2} (mod p^3), as quoted in C. Levaillant, arXiv:2005.09434, Results 2 and 4.\n- J. Zhao, arXiv:math/0301252: (p, p-2n-1) is irregular iff H(p-1, 2n-1) ≡ 0 (mod p^3) for p ≥ 2n+3.\n- Kummer congruences, plus (37,32) being an irregular pair.\n- R. Meštrović, arXiv:1111.3057, eq. (22).\n- OEIS A007408 comment (Adamchuk 2006): 37^3 | numerator of H(36,3), i.e. the k=0 case.", + "date": "2026-10-19", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Euler's theorem: since 37 does not divide k for 1 <= k <= 36, whether 37^3 divides the numerator of H(36,n) depends only on n mod phi(37^3) = 49284, so both claims reduce to checking one period. Alternatively, it follows from the classical power-sum congruence of Glaisher/Sun, S_m = p B_m + (p^2/2) m B_{m-1} + ... (mod p^3), together with Kummer's congruences and the fact that (37,32) is the only irregular pair of 37.", + "justification": "Both claims are about one fixed modulus, 37^3, and the denominator of H(36,n) is prime to 37. By Euler's theorem, whether n is a term depends only on n mod 49284. Both conjectures therefore reduce to a finite computation over one period. For (b), a prime above 37 is coprime to 49284, so only the residues coprime to 49284 need checking. The manuscript's truncated binomial expansion only makes this check cheaper. Its alternative derivation also takes just a few lines from Sun's power-sum congruence, Kummer's congruences and the irregular pair (37,32). No new idea was needed.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A119936", + "slug": "oeis-a119936", + "title": "The row-LCM of denominators of the cube of the mean matrix is n · lcm(1..n)²", + "area": "Discrete geometry", + "source": "OEIS A119936", + "source_url": "https://oeis.org/A119936", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A119936.lean", + "decl": "Math0.Statements.A119936.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A119936.lean", + "our_decl": "Math0.Frontier.A119936.result", + "summary": "Let A be the lower-triangular matrix with A(i,j) = 1/i for j ≤ i and 0 otherwise. Its cube has entries r(n,m) = (1/n) Σ_{m ≤ l ≤ k ≤ n} 1/(k l) for 1 ≤ m ≤ n. Let a(n) be the lcm, over m = 1..n, of the reduced denominators of r(n,m). Then for every n ≥ 1, a(n)/n³ = A002944(n)² = (lcm(1..n)/n)². Equivalently, a(n) = n · lcm(1,…,n)². This is the equation that OEIS A119936 (Wolfdieter Lang, 2006) labels a conjecture.", + "notes": "Conjecture as stated in OEIS: %F A119936 a(n)/n^3 = A027451(n) = A002944(n)^2 (the second equation is a conjecture). (Wolfdieter Lang, Jul 20 2006)\n\nReferees: I found no prior proof or counterexample.\n- OEIS A119936 (Lang 2006, edit #22 Nov 2019) still calls a(n)/n^3 = A002944(n)^2 a conjecture.\n- A027451 states (lcm(1..n)/n)^2 as a formula (Meijer, 2009) without proof. Detlefs' comment there begins \"It appears\".\n- A120078 and A120079 say \"conjectured to be A027451\".\n- Crowley, arXiv:1207.1126, says only that a denominator \"appears to be\" A119936.\n- Fried's OEIS-conjecture series does not mention A119936 or the related sequences: arXiv:2410.07237 / JIS 25.4.3, JIS 26.1.8, arXiv:2606.09913, arXiv:2607.24832.\n- Sloane, math/0409509: no mention.\n- Web, MSE/MO and SeqFan searches turned up nothing.", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The standard p-adic argument in which a sum has a single term of minimal valuation, the same idea as the classical proof that the harmonic numbers H_n are not integers (Taeisinger/Kürschák), applied to the explicit formula r(n,m) = (1/n) Σ_{m≤l≤k≤n} 1/(kl) and to v_p(lcm(1..n)) = floor(log_p n).", + "justification": "The divisibility a(n) | n·lcm(1..n)^2 is immediate, because each product kl divides lcm(1..n)^2. For the reverse divisibility, take each prime p separately and use the column m equal to the largest multiple of p^e that is at most n, where p^e ≤ n < p^{e+1}. In that column, k = l = m is the only term whose valuation reaches -2e, so the full p-power survives in the denominator. This is the textbook unique-minimal-valuation trick used for harmonic sums. The whole argument fits in under a page, and the scout record set it out almost in full before any formalization, so it is a short, standard proof and not a new idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A120069", + "slug": "oeis-a120069", + "title": "Denominators of Sum C(k)/4^(k-1): Groux's and Staunton's conjectures (A120069)", + "area": "Sequences and series", + "source": "OEIS A120069", + "source_url": "https://oeis.org/A120069", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A120069.lean", + "decl": "Math0.Statements.A120069.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A120069.lean", + "our_decl": "Math0.Frontier.A120069.result", + "summary": "Let C(k) be the Catalan numbers, r(n) = Sum_{k=1..n} C(k)/4^(k-1), and a(n) the denominator of r(n) in lowest terms (A120069). Let A283208(n) be the least e >= 0 such that 2^e (2n+1)/(n+1) c(2n) is a nonnegative integer, where c(2n) = Pochhammer(1/2,n)/n!. Then for every n >= 1: (Groux) a(n) = denominator(C(n)/4^(n-1)), and (Staunton) a(n) = 2^(A283208(n) - 2), with the exponent taken in the integers.", + "notes": "Conjecture as stated in OEIS: A120069 (Denominators of partial sums r(n) = Sum_{k=1..n} C(k)/2^(2(k-1)), C = Catalan): \"Conjecture: a(n) = denominator(Catalan(n)/4^(n-1)). - _Groux Roland_, Dec 11 2010\" and \"Conjecture: a(n) = 2^(A283208(n)-2). - _Alexander Staunton_, Feb 28 2026\"\n\nReferees: OEIS sources (read from the local mirror; A120069 also checked against GitHub oeisdata main):\n- A120778, formula by Groux Roland, Jan 04 2011: sum_{k=0..n} C(k)/4^k = 2(1 - binomial(2n+2,n+1)/4^(n+1)).\n- A119951, comment by Pieter Mostert, Oct 12 2012: r(n) = sum_{k=1..n} C(k)/4^(k-1) = 4 - binomial(2n+2,n+1)/2^(2n-1).\n- A120777, which records:\n - Johannes W. Meijer, Jul 06 2009: a(n) = denominator(C(2n+2,n+1)/2^(2n+1)).\n - Peter Luschny's new name, Apr 2024: a(n) = 2^(2n - v2(Catalan(n))).\n - Amiram Eldar, Apr 18 2024: a(n) = 2^(2n - A048881(n)) = 2^A283208(n).\n - A comment that its terms coincide with the denominators of sum_{k=0..n} C(k)/4^k.\n- A283208:\n - Comment: 2^a(n) is the denominator of 2^(-2n)·A001700(n).\n - Formula by Zabolotskii, 2021: a(n) = A005187(n+1) - 1.\n\nCombining these gives A120069(n) = A120777(n)/4 = 2^(A283208(n)-2) = den(C(n)/4^(n-1)). No explicit paper, MSE/MO post or SeqFan message resolving the A120069 conjectures by name was found. A120069 #30 (Mar 10 2026) still lists both as conjectures.\n\nWeb pages:\n- https://oeis.org/A120778\n- https://oeis.org/A120777\n- https://oeis.org/A119951\n- arXiv:0906.4290, \"Asymptotics of partial sums of central binomial coefficients and Catalan numbers\". Found in search; related, but I did not read it.", + "date": "2026-10-20" + }, + { + "id": "OEIS-frontier/A121750", + "slug": "oeis-a121750", + "title": "Mathar's order-6 recurrence for A121750 (even-length columns in deco polyominoes) holds for all n >= 7", + "area": "Discrete geometry", + "source": "OEIS A121750", + "source_url": "https://oeis.org/A121750", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A121750.lean", + "decl": "Math0.Statements.A121750.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A121750.lean", + "our_decl": "Math0.Frontier.A121750.result", + "summary": "Let a(n) be the total number of columns of even length over all deco polyominoes of height n (OEIS A121750). The polyominoes are encoded as column lists, as in the statement file. Then for every n >= 7:\na(n) - (n+2)a(n-1) + (-n^2+4n-2)a(n-2) + (n^3-3n^2-4n+11)a(n-3) - (n-1)(n^2-11n+26)a(n-4) + (-n^3+5n^2+7n-43)a(n-5) + (n-3)(n-5)^2 a(n-6) = 0.", + "notes": "Conjecture as stated in OEIS: %F Conjecture D-finite with recurrence a(n) +(-n-2)*a(n-1) +(-n^2+4*n-2)*a(n-2) +(n^3-3*n^2-4*n+11)*a(n-3) -(n-1)*(n^2-11*n+26)*a(n-4) +(-n^3+5*n^2+7*n-43)*a(n-5) +(n-3)*(n-5)^2*a(n-6)=0. - R. J. Mathar, Jul 26 2022\n\nReferees: I found no published proof of this recurrence. Sources checked:\n- OEIS A121750, local mirror and upstream raw oeisdata (revision #13, 2024-08-20, still says 'Conjecture'). Cross-references A121748, A121747, A121749, A121751 also contain no proof.\n- E. Barcucci, S. Brunetti, F. Del Ristoro, 'Succession rules and deco polyominoes', RAIRO ITA 34 (2000) 1-14. Full text read; it does not treat even-length columns.\n- E. Barcucci, A. Del Lungo, R. Pinzani, TCS 159 (1996) 29-42.\n- E. Deutsch, E. Pergola, R. Pinzani, 'Six bijections between deco polyominoes and permutations', arXiv:0810.2876. It gives the definition of directed height and has no even-column results.\n- S. B. Ekhad, X. Yang, D. Zeilberger, arXiv:1707.04654. It predates the 2022 conjecture.\n- S. Fried, arXiv:2410.07237; JIS 28 (2025) Art. 25.4.3; JIS vol. 29 fried21; arXiv:2607.24832. None covers A121750.\n- T. Niu, arXiv:2605.15500, 2605.04369, 2605.08444, 2605.16553 (2026). None covers A121750.\n- M. Kauers, C. Koutschan, arXiv:2303.02793. Does not cover A121750.\n\nNote: the order-6 recurrence would follow routinely from Deutsch's first-order recurrence in the same entry (holonomic closure). That recurrence is stated in the entry without proof.", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Deutsch's first-order recurrence in the same entry, a(n) = n*a(n-1) + d(n-1) + (n-1)!*floor((n-1)/2), together with the closure properties of D-finite sequences (Stanley 1980). The row-polynomial recurrence for Q[n] in the cross-referenced A121748 gives the same route. Both are stated in OEIS without proof.", + "justification": "The proof splits each deco polyomino at its first column, the standard recursive decomposition, and uses the fact that shifting columns does not change the count. This gives a small first-order system for the counts and even-column totals. The order-6 recurrence then follows by unrolling the system six steps in each parity class and expanding a polynomial identity, which is a mechanical computation. The manuscript itself says the recurrence follows by routine closure arguments from Deutsch's first-order recurrence in the same entry. The new part is deriving that first-order relation from the definition, which takes about a page of standard combinatorics and needs no new idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A123710", + "slug": "oeis-a123710", + "title": "A123710: the rows of inv(floor(n/k)) with four nonzero entries are 6 and the proper prime powers", + "area": "Discrete geometry", + "source": "OEIS A123710", + "source_url": "https://oeis.org/A123710", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A123710.lean", + "decl": "Math0.Statements.A123710.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A123710.lean", + "our_decl": "Math0.Frontier.A123710.result", + "summary": "Let A be the lower-triangular matrix with A(n,k) = floor(n/k) (A010766), and let T = A^{-1} (A123706). Let R(n) be the number of nonzero entries in row n of T (A123709), and let a(n) be the n-th smallest n with R(n) = 4 (A123710, offset 1). Let A025475(n) be the n-th term of 1, 4, 8, 9, 16, 25, ... (1 and the prime powers p^m with m >= 2). Hasler's conjecture: a(n) = A025475(n) for all n > 2. Equivalently, R(n) = 4 exactly when n = 6 or n is a proper prime power.", + "notes": "Conjecture as stated in OEIS: %F A123710 a(n) = A025475(n) for n>2 (conjectured). - _M. F. Hasler_, Feb 12 2012\n\nReferees: OEIS sequences, all read from the local mirror and checked against https://raw.githubusercontent.com/oeis/oeisdata/main/seq/:\n- A123710 (#27, Sep 05 2025): formula still marked \"(conjectured)\" (Hasler, Feb 12 2012).\n- A123709: Hasler's 2^k / omega formula with the n = 6 exception, given without proof. Links Luschny's seqcomp message http://groups.google.com/group/seqcomp/msg/2aabf27ef9b698ef (Feb 2012). The visible part of that thread has the closed form and asks for a proof of A123712 = A178212, but nothing on A123710.\n- A123706: Perez Herrero closed form T(n,k) = mu(n/k) - mu(n/(k+1)) (Feb 21 2012), without proof.\n- A123711 and A200511, A123712 and A178212: related conjectures, still open.\n- A206706: Luschny's variant triangle.\n\nOther sources:\n- OEIS wiki, \"Sequences determined by prime signature\": lists A123711 and A123712 under \"Examples which need to be checked\".\n- S. Fried, JIS 28 (2025) Art. 25.4.3; JIS 29 (2026) Art. 26.1.8; arXiv:2607.24832 (Jul 2026). None treat A123710.\n\nSearches of arXiv, MathOverflow and MSE found no proof of A123710. The SeqFan Feb 2012 archive was unreachable.", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The closed form T(n,k) = mu(n/k) - mu(n/(k+1)) given in cross-referenced A123706 (Perez Herrero, 2012), together with Hasler's 2^k / omega description of A123709 (exception n = 6). Checking the closed form is a one-line Moebius inversion (sum over d | m of mu(d) = [m = 1]).", + "justification": "The proof uses the closed form T(n,k) = f(k) - f(k+1), with f(k) = mu(n/k) when k | n and 0 otherwise. That formula is already stated in cross-referenced A123706, and checking it is a short Moebius-inversion and Abel-summation calculation. Row n then has one nonzero entry for each place where f changes value. If n is not squarefree, the support of f has 2^omega(n) elements and no two of them are consecutive, so the row has 2^(omega+1) nonzero entries; this gives 4 exactly for proper prime powers. For squarefree n, a short case check (two consecutive divisors k, k+1 force k(k+1) | n) leaves only n = 6. All of this is an elementary page-length argument that follows from material already in the entry's cross-references.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A124526", + "slug": "oeis-a124526", + "title": "Hanna's conjecture A124418(n,k) = k! * A124526(n,k) (partitions with k mixed-parity blocks) proved", + "area": "Discrete geometry", + "source": "OEIS A124526", + "source_url": "https://oeis.org/A124526", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A124526.lean", + "decl": "Math0.Statements.A124526.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A124526.lean", + "our_decl": "Math0.Frontier.A124526.result", + "summary": "For all n >= 0 and 0 <= k <= floor(n/2): the number A124418(n,k) of set partitions of {1,...,n} with exactly k blocks containing both an odd and an even entry equals k! * A049020(floor(n/2),k) * A049020(floor((n+1)/2),k), where A049020(m,k) = sum_{i=0}^{m} S2(m,i) * C(i,k) and S2 is the Stirling number of the second kind. (The proof does not need the bound k <= floor(n/2); the identity holds for every k.)", + "notes": "Conjecture as stated in OEIS: A124526: \"A124418(n,k) = k!*T(n,k) (conjecture).\"; A124418 %F: \"Conjecture: T(n,k) = k!*A049020([n/2],k)*A049020([(n+1)/2],k) ... - _Paul D. Hanna_, Nov 08 2006\"\n\nReferees: OEIS entries read from the local mirror: A124526, A124418 (Hanna's 2006 conjecture in %F; Heinz's 2013 alternative Maple program uses the equivalent product formula), A049020 (cites East–Gray and Halverson–Jacobson), A244489, A124419 (k=0 column: Bell(floor(n/2))·Bell(ceil(n/2))), A124529, A362495.\n\nPrior proofs, stated in partition-monoid and partition-category language:\n- J. East and R. D. Gray, \"Diagram monoids and Graham–Houghton graphs: Idempotents and generating sets of ideals\", J. Combin. Theory Ser. A 146 (2017) 63–128, doi:10.1016/j.jcta.2016.09.001, arXiv:1404.2359. Proof of Theorem 7.5 and Remark 7.7: |J_r(P_n)| = ρ_{nr}^2·r!, with ρ_{nr} = Σ_j S(n,j)C(j,r). This is the even-n case.\n- T. Halverson and T. N. Jacobson, \"Set-partition tableaux and representations of diagram algebras\", arXiv:1808.08118 (Algebraic Combinatorics 2020), Remark 3.23: the rank-m diagrams in P_k number |W^m_k|^2·m!, where |W^m_k| = A049020(k,m).\n- I. Đurđev, I. Dolinka and J. East, \"Sandwich semigroups in diagram categories\", arXiv:1910.10286 (Internat. J. Algebra Comput. 2021), Proposition 4.11 and Remark 4.12: for the partition category P_{mn}, |D_r| = r!·[Σ_q C(q,r)S(m,q)]·[Σ_q C(q,r)S(n,q)]. Taking m = ⌈n/2⌉ and n = ⌊n/2⌋ gives the full conjecture.\n\nChecked and not relevant: Yaqubi–Mirzavaziri arXiv:2608.30097; Ehrenborg–Hedmark–Hettle (JIS 2017, odd/even block sizes); Shattuck arXiv:1401.6588.", + "date": "2026-10-21" + }, + { + "id": "OEIS-frontier/A126127", + "slug": "oeis-a126127", + "title": "A126127: Israel's conjectured bivariate g.f. of the inverse square of A061554 holds", + "area": "Discrete geometry", + "source": "OEIS A126127", + "source_url": "https://oeis.org/A126127", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A126127.lean", + "decl": "Math0.Statements.A126127.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A126127.lean", + "our_decl": "Math0.Frontier.A126127.result", + "summary": "Let M be the infinite lower-triangular matrix with M(n,k) = binomial(n, floor((n-k)/2)) for 0 <= k <= n (A061554), and let T = M^(-2) (A126127). Then, as formal power series in x, y over Q, sum_{n>=0} sum_{k=0}^{n} T(n,k) x^n y^k = (1-x)(1-x+x^2) / (1 - xy + 3x^2 - x^3 y + x^4).", + "notes": "Conjecture as stated in OEIS: %F A126127 G.f. as triangle (conjectured): (1-x)*(1-x+x^2)/(1-x*y+3*x^2-x^3*y+x^4). - _Robert Israel_, Jul 07 2019\n\nReferees: OEIS A126127 (Gary W. Adamson, 2006): conjectured g.f. by Robert Israel, Jul 07 2019, still marked conjectured upstream (oeisdata seq/A126/A126127.seq, %I #10, no %E edits). OEIS A130777: \"Inverse of triangle in A061554\", Riordan array ((1-x)/(1+x^2), x/(1+x^2)) by Paul Barry, May 21 2009; together with the standard Riordan group product rule (Shapiro, Getu, Woan, Woodson, 1991), this makes the conjecture an immediate corollary, but no source found states or proves the g.f. of the square. OEIS A061554: Riordan array (1/(1-x-x^2c(x^2)), x c(x^2)) by Philippe Deléham, 2007. Web searches (OEIS, arXiv, MathOverflow/Math StackExchange, SeqFan) found no prior proof or counterexample.", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The cross-referenced entry A130777 says it is the inverse of A061554 and gives it as the Riordan array ((1-x)/(1+x^2), x/(1+x^2)) (Paul Barry, 2009). Its row-polynomial o.g.f. (1-z)/(1-xz+z^2) is the bivariate g.f. of M^(-1). The standard Riordan group product (g,f)*(h,l) = (g*(h o f), l o f) then gives M^(-2) = (g*(g o f), f o f), where g*(g o f) = (1-x)(1-x+x^2)/(1+3x^2+x^4) and f o f = x(1+x^2)/(1+3x^2+x^4). That is exactly Israel's g.f.", + "justification": "A130777, which A126127 itself points to as the inverse of A061554, already identifies M^(-1) as the Riordan array ((1-x)/(1+x^2), x/(1+x^2)). The conjecture is about the square of that array. Squaring it with the standard Riordan product rule and simplifying two short rational functions gives the stated g.f. in a few lines. The Lean proof avoids Riordan machinery and uses recurrences instead, but that is formalization effort, not a new mathematical idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A127752", + "slug": "oeis-a127752", + "title": "A127752 mod 2 is the first Feigenbaum symbolic sequence A035263", + "area": "Discrete geometry", + "source": "OEIS A127752", + "source_url": "https://oeis.org/A127752", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A127752.lean", + "decl": "Math0.Statements.A127752.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A127752.lean", + "our_decl": "Math0.Frontier.A127752.result", + "summary": "Let A(n,k) = 1/(3n+1) if k <= n <= 2k and 0 otherwise (n, k >= 0), and let a(n) be the row sums of the inverse of this lower-triangular matrix. Equivalently, a is defined by forward substitution: a(n) = 3n+1 - sum_{j 11, 1 -> 10 (offset 1). Then for every n >= 0, a(n) mod 2 = A035263(n+1). This is Paul Barry's 2007 conjecture.", + "notes": "Conjecture as stated in OEIS: a(n) mod 2 is first Feigenbaum symbolic sequence A035263 (conjecture). (Paul Barry, Jan 28 2007; checked to 2048 terms by Antti Karttunen, Sep 29 2018)\n\nReferees: OEIS A127752 (P. Barry, Jan 28 2007; current version #11, Feb 11 2021) still says \"(conjecture)\", with A. Karttunen's 2018 check of the first 2048 terms. A127751 (#5) still calls it conjectural, and the related A127750, A127749 and A111967 conjectures (Fredholm-Rueppel parity for the 1/(2n+1) triangle) remain open. Checked and not relevant: S. Fried, \"On the inverse of a certain triangular matrix and its connection to the largest odd divisor\", NNTDM 32(2) (2026) 255-262, which covers A127793 and A000265, not A127752; S. Fried, JIS 28 (2025) Art. 25.4.3 and JIS 29 (2026) Art. 26.1.8; S. Fried, arXiv:2607.24832. No prior proof or counterexample found, and no existing formalization in formal-conjectures.", + "date": "2026-10-25", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The row-n equation of the lower-triangular system A s = 1, i.e. sum_{ceil(n/2)<=j<=n} s(j) = 3n+1. Taking differences of consecutive rows gives s(0)=1, s(2m+2)=3 and s(2m+1)=s(m)+3. Compare this with the formula a(2n)=1-a(n), a(2n+1)=1 already listed in A035263 (equivalently, the parity of the 2-adic valuation of 2n).", + "justification": "The whole argument is to write row n of A s = 1 as a window sum, sum_{j=ceil(n/2)}^{n} s(j) = 3n+1, and subtract consecutive rows. This gives s(2m+2)=3 and s(2m+1)=s(m)+3, which also yields a closed form in terms of the 2-adic valuation of n+1. Parity then follows by a one-line induction against the recursion a(2n)=1-a(n), a(2n+1)=1, which is already listed in A035263. This is a half-page, standard telescoping argument that a competent mathematician would find within minutes. Most of the effort went into the formalization (morphic-word indexing, matrix-inverse link), not into new mathematics.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A127755", + "slug": "oeis-a127755", + "title": "The inverse of the triangle 1/n! [k ≤ n ≤ 2k] is an integer triangle", + "area": "Discrete geometry", + "source": "OEIS A127755", + "source_url": "https://oeis.org/A127755", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A127755.lean", + "decl": "Math0.Statements.A127755.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A127755.lean", + "our_decl": "Math0.Frontier.A127755.result", + "summary": "Let A(n,k) = 1/n! if k ≤ n ≤ 2k and A(n,k) = 0 otherwise (n, k ≥ 0), viewed as an infinite lower-triangular matrix over Q. Let T be its inverse, computed by forward substitution: T(n,k) = n!·([n = k] − Σ_{j n. Then T(n,k) is an integer for all 0 ≤ k ≤ n. This was conjectured by Paul Barry in OEIS A127755.", + "notes": "Conjecture as stated in OEIS: %C A127755 It is conjectured that this is an integer triangle. Row sums are A127756. (_Paul Barry_, Jan 28 2007)\n\nReferees: I found no prior proof or counterexample for A127755. Sources checked:\n- Local mirror and current GitHub oeisdata entry for A127755 (revision #5, Sep 29 2018), still marked conjectured.\n- Related OEIS entries: A127756; A101688 (the 0/1 triangle [k<=n<=2k]); A111967 (its inverse, by Barry, 2005), with A127755(n,k) = k!·A111967(n,k).\n- A127749: R. J. Mathar (Apr 21 2021) gives T(n,k) = (2k+1)·A111967(n,k), the same diagonal-scaling argument applied to the 1/(2n+1) sibling.\n- A127793: FUNG Cheok Yin (Sep 2022) gives a formula implying integrality for the 1/floor((n+2)/2) sibling. Sela Fried, \"On the inverse of a certain triangular matrix and its connection to the largest odd divisor\", Notes Num. Theor. Disc. Math. 32(2) (2026) 255-262, doi:10.7546/nntdm.2026.32.2.255-262, proves it; the paper does not mention A127755.\n- Sibling integrality conjectures that are also still open in OEIS: A127710, A127711, A127771.\n- Web searches (OEIS/SeqFan/arXiv/MathOverflow/MSE-style queries) found nothing more.", + "date": "2026-10-26", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Factor A = D^{-1}·B, where D = diag(n!) and B is the 0/1 unitriangular triangle A101688. Then A^{-1} = B^{-1}·D, so T(n,k) = k!·A111967(n,k). A111967 is the inverse of B (cross-referenced), and the inverse of a unitriangular integer matrix has integer entries. The forward-substitution recursion shows the same thing directly, because n!·A(n,j) is 0 or 1.", + "justification": "The conjecture follows in a few lines. Multiplying row n by n! turns A into the 0/1 lower-unitriangular matrix A101688. Its inverse (A111967) is therefore an integer matrix, and A^{-1} is that inverse with column k scaled by k!. R. J. Mathar already gave the same diagonal-scaling argument for the sibling entry A127749, and the Lean proof is just a strong induction on the forward-substitution recursion. No new idea was needed, so the result is routine, even though it had stayed formally open since 2007.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A127767", + "slug": "oeis-a127767", + "title": "The inverse of the 1/Catalan band triangle (A127767) has integer entries", + "area": "Discrete geometry", + "source": "OEIS A127767", + "source_url": "https://oeis.org/A127767", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A127767.lean", + "decl": "Math0.Statements.A127767.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A127767.lean", + "our_decl": "Math0.Frontier.A127767.result", + "summary": "Let C(n) be the Catalan numbers. Let A be the infinite lower-triangular matrix with A(n,k) = 1/C(n) if k ≤ n ≤ 2k and A(n,k) = 0 otherwise. Let T be its inverse, which is also lower triangular. Then every entry T(n,k) with 0 ≤ k ≤ n is an integer. In the frozen statement, T is defined by forward substitution: T(n,k) = C(n)·([n=k] − Σ_{j n.", + "notes": "Conjecture as stated in OEIS: %C It is conjectured that all elements of the triangle are integers. (Paul Barry, Jan 28 2007)\n\nReferees: - OEIS A127767 (P. Barry, Jan 28 2007). Local mirror and current GitHub oeisdata, #11 Sep 30 2018: the conjecture is still marked as conjectured, with no proof or formula. Cross-references: A127768, A127769, A127770, A000108.\n- OEIS A101688: the 0/1 triangle [k<=n<=2k].\n- OEIS A111967: inverse of A101688. It is an integer triangle because A101688 is unitriangular. T(n,k) = A000108(k)·A111967(n,k) is the identity that settles A127767.\n- OEIS A127749, R. J. Mathar, Apr 21 2021: T(n,k) = (2k+1)·A111967(n,k). This is the same factorisation applied to a sibling triangle. It is the closest prior use of the method, but it does not resolve A127767.\n- OEIS A127793: the integrality conjecture for the 1/floor((n+2)/2) sibling was proved by FUNG Cheok Yin (Sep 2022) and by S. Fried, \"On the inverse of a certain triangular matrix and its connection to the largest odd divisor\", Notes Num. Theor. Disc. Math. 32(2) (2026) 255-262, doi:10.7546/nntdm.2026.32.2.255-262 (https://nntdm.net/papers/nntdm-32/NNTDM-32-2-255-262.pdf). This covers A127793 only; there is no general remark that would cover A127767.\n- Siblings with the same still-open integrality conjecture, all settled by the same argument: A127710, A127711, A127755, A127771.\n- No relevant hits on arXiv, MathOverflow/MSE or SeqFan for A127767.", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The factorization A = diag(1/C_n) * M, where M(n,k) = [k <= n <= 2k] is the lower unitriangular 0/1 triangle A101688. Its inverse is the integer triangle A111967, so T = M^{-1} * diag(C_k), that is, T(n,k) = C_k * A111967(n,k). The same factorization appears in R. J. Mathar's 2021 formula for the sibling triangle A127749.", + "justification": "The conjecture follows from one observation. Every nonzero entry in row n of A equals 1/C(n), so A is the 0/1 band matrix [k<=n<=2k] with each row scaled by 1/C(n). That band matrix is lower unitriangular, so its inverse has integer entries. Inverting A then just multiplies column k of that integer inverse by C(k). This is standard linear algebra that fits in a few lines. The method was already used for the sibling triangle A127749, and the manuscript itself calls the result an elementary observation. The integrality conjecture was meant literally, and the proof settles it as stated.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A129455", + "slug": "oeis-a129455", + "title": "The triple-gcd Pascal triangle A129455: T(n,k) is an integer, divisible by C(n,k), and T(n,k)/C(n,k) is a sixth power", + "area": "Discrete geometry", + "source": "OEIS A129455", + "source_url": "https://oeis.org/A129455", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A129455.lean", + "decl": "Math0.Statements.A129455.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A129455.lean", + "our_decl": "Math0.Frontier.A129455.result", + "summary": "Let G(m) = A129454(m+1) = prod_{i,j,k=1..m} gcd(i,j,k), so G(0) = 1. For all 0 <= k <= n: (1) G(k)·G(n-k) divides G(n), so T(n,k) = G(n)/(G(k)G(n-k)) is an integer; (2) the binomial coefficient C(n,k) divides T(n,k); (3) T(n,k)/C(n,k) = m^6 for some natural number m. This is Peter Bala's 2007 conjecture from OEIS A129455, with the Lean T defined by natural-number division as in the frozen statement.", + "notes": "Conjecture as stated in OEIS: It appears that the T(n,k) are always integers. This would follow from the conjectured prime factorization given in A129454. Calculation suggests that the binomial coefficients C(n,k) divide T(n,k) and that T(n,k)/C(n,k) are perfect sixth powers. (Peter Bala, Apr 16 2007)\n\nReferees: OEIS A129455, A129454 and A129453: the local mirror matches GitHub oeisdata (revisions #9, #8 and #9, Feb 2024), and all three still state the claims as conjectures. OEIS A092287: Greathouse (Apr 2013) confirmed the square-case prime factorization. Wanli Ma, \"Generalized factorials characterized by Dirichlet convolution\", arXiv:2509.13354 (Sept 2025), Section 2.2 and Theorems 2.5-2.6: proves that the q-tuple gcd product equals prod_p p^{sum floor(n/p^i)^q}, and that the generalized binomial coefficients for superadditive x are integers. With q=3 this implies only the integrality part of A129455; the paper does not mention A129454/A129455, C(n,k) divisibility or sixth powers. A.B. Mingarelli, \"Abstract factorials\", arXiv:0705.4299 / NNTDM 19 (2013): general framework, no gcd products. A224479/A224497 (Forgues, Luschny 2013): square-case formulas G2(n) = n!*A224479(n)^2, the analogue of the perfect-square property of A129453, but nothing for the cubic case. I found no source proving that C(n,k) divides T(n,k) or that T(n,k)/C(n,k) is a sixth power for A129455.", + "date": "2026-10-25", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The prime factorization v_p(A129454(n+1)) = sum_t floor(n/p^t)^3 conjectured in A129454 (cubic analogue of the A092287 formula Greathouse confirmed; stated for general q in Ma, arXiv:2509.13354), together with Legendre's formula and Kummer's carry theorem for v_p(C(n,k)).", + "justification": "Counting multiples of each prime power gives the Legendre-type formula v_p(G(n)) = sum_t floor(n/p^t)^3, which A129454 already points to and which is published in general form. With A = floor(k/p^t), B = floor((n-k)/p^t) and a carry c in {0,1}, the identity (A+B+c)^3 = A^3+B^3+c+3[AB(A+B)+c(A+B)(A+B+1)] has an even bracket. By Kummer's theorem the carries c add up to v_p(C(n,k)), so all three claims follow at once. The whole argument is under a page of standard elementary number theory and needs no new idea. Bala's comment itself says integrality would follow from the factorization.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A132616", + "slug": "oeis-a132616", + "title": "Irwin's nested sums give column 0 of the triangle A132615 (A132616)", + "area": "Discrete geometry", + "source": "OEIS A132616", + "source_url": "https://oeis.org/A132616", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A132616.lean", + "decl": "Math0.Statements.A132616.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A132616.lean", + "our_decl": "Math0.Frontier.A132616.result", + "summary": "Let T be the infinite lower-triangular matrix with T(0,0) = 1 in which, for every n ≥ 0, row n+1 is row n of T^(2n-1) followed by a 1. For n = 0 the formal exponent is 0, which gives the same row [1, 1]. Let a(n) = T(n,0) (OEIS A132616). Define nest 0 c = 1 and nest (m+1) c = Sum_{i=1..c+2m} nest m i. Then nest(n-1, 1) is Irwin's nested sum Sum_{i_1=1..1+2(n-2)} Sum_{i_2=1..i_1+2(n-3)} ... Sum_{i_(n-1)=1..i_(n-2)} 1. Claim: for every n ≥ 2, a(n) = nest(n-1, 1).", + "notes": "Conjecture as stated in OEIS: %F A132616 From Benedict W. J. Irwin, Nov 29 2016: Conjecture: a(n) is described by a series of nested sums, a(2) = Sum_{i=1..1} 1, a(3) = Sum_{i=1..1+2} Sum_{j=1..i} 1, a(4) = Sum_{i=1..1+4} Sum_{j=1..i+2} Sum_{k=1..j} 1, a(5) = Sum_{i=1..1+6} Sum_{j=1..i+4} Sum_{k=1..j+2} Sum_{l=1..k} 1, and so on.\n\nReferees: I found no prior proof or counterexample. Checked: the OEIS entries A132616 and A132615 (Hanna 2007, which includes the unproved \"alternate generating method\", an equivalent partial-sums form of Irwin's sums), A132617, A132618, A132619, A132610, A101479, A101481 (Kirchner 2017 recurrence, different triangle), and A304190, A304191, A304193 (Hanna 2018, conjectural g.f. links). Local mirror versions match current GitHub oeisdata, with no %E line recording a proof. Also checked S. Fried, \"Proofs of several conjectures from the OEIS\", JIS 28 (2025) Art. 25.4.3 (https://cs.uwaterloo.ca/journals/JIS/VOL28/Fried/fried15.html); S. Fried, \"Proofs of ten conjectures from the OEIS\", JIS 29 (2026) Art. 26.1.8 (https://cs.uwaterloo.ca/journals/JIS/VOL29/Fried/fried21.html); arXiv:2410.07237; arXiv:2606.09913, which proves Irwin's A007405 conjecture but not this one; and arXiv:2607.24832. None mentions A132616 or A132615. Unrelated constructions: P. Barry, arXiv:1804.06801, and arXiv:1203.4419 (Hanna's triangle A096651). Web searches of MathOverflow, Math StackExchange and SeqFan returned only the OEIS pages.", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "", + "justification": "The proof strengthens the claim to every power of the triangle: the (n,k) entry of T^p is Irwin's nested sum with outer bound p. Somos's two-argument program a(n,k) in the entry and Hanna's partial-sums \"alternate generating method\" in A132615 already point to this generalization. The proof then checks the semigroup law M_p M_q = M_{p+q} by a short double induction: when p goes up by one, row n+1 changes by row n of M at a shifted exponent, and the induction hypothesis matches the two sides. It ends with uniqueness of T, so M_1 = T. This is a standard strengthen-the-induction argument of about half a page, which a competent combinatorialist would find quickly once looking at the powers, a natural move for a triangle defined by its own powers. So it is routine, even though no proof had been published before.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A141412", + "slug": "oeis-a141412", + "title": "Denominators of Curtz's polynomials are Farhi's d(n+1,k+1) (A141412, Marcus's conjecture)", + "area": "Discrete geometry", + "source": "OEIS A141412", + "source_url": "https://oeis.org/A141412", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A141412.lean", + "decl": "Math0.Statements.A141412.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A141412.lean", + "our_decl": "Math0.Frontier.A141412.result", + "summary": "Let P(0,x)=1 and P(n+1,x) = (-1)^(n+1)/(n+2) + x * sum_{i=0}^{n} (-1)^i/(i+1) * P(n-i,x) over Q, and let c(n,k) = [x^k] P(n,x) (computed by the matching recursion c in the statement file). Let T(n,k) be the reduced denominator of c(n,k), and let d(n,k) be the reduced denominator of |s(n,k)| * k!/n!, where |s(n,k)| is the unsigned Stirling number of the first kind (Nat.stirlingFirst). Then T(n,k) = d(n+1,k+1) for every 0 <= k <= n. The proof gives this for all n and k.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: T(n, k) = d(n+1, k+1), with d(n,k) = denominator(A000254(n, k)*k!/n!) where A000254 are the unsigned Stirling numbers of the 1st kind. See d(n,k) in Farhi link. - _Michel Marcus_, Oct 18 2018\"\n\nReferees: P. Flajolet, X. Gourdon and B. Salvy, \"Sur une famille de polynômes issus de l'analyse numérique\", Gazette des Mathématiciens 55 (1993) 67-78, also INRIA Research Report RR-1857 (Feb 1993), https://inria.hal.science/inria-00074815/document. Eq. (3) is the generating function log(1+z)/(z(1-x·log(1+z))), and eq. (6) is P_n(x) = (-1)^n/(n+1)! Σ_k s_{n+1,k+1}(k+1)!(-x)^k, which gives the conjecture at once. This paper is cited in A141412's own %D line. The OEIS records the same identity in A140749 %F (Paul Curtz, Jul 17 2008, numerators = those of A048594(n+1,k+1)/(n+1)!) and A141412 %F (G. C. Greubel, Oct 24 2023, \"Equals denominators of A048594(n+1,k+1)/(n+1)!\"), with A048594's column e.g.f. log(1+x)^k. Farhi's d(n,k) comes from B. Farhi, arXiv:1810.07560 (Funct. Approx. Comment. Math. 61 (2019)). I found no earlier formal proof.", + "date": "2026-10-20" + }, + { + "id": "OEIS-frontier/A144637", + "slug": "oeis-a144637", + "title": "A144637: (1/18) 6^n a(n)/n! is odd iff n = 2^k with k >= 1", + "area": "Discrete geometry", + "source": "OEIS A144637", + "source_url": "https://oeis.org/A144637", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A144637.lean", + "decl": "Math0.Statements.A144637.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A144637.lean", + "our_decl": "Math0.Frontier.A144637.result", + "summary": "Let S(n,k) be A144385: the number of partitions of {1,...,k} into exactly n blocks, each of size 1, 2 or 3. Let T = A144633 be the transpose of the inverse of the upper unitriangular matrix M(i,j) = S(i,j). Let a(n) = T(n,2), and y(n) = (1/18) 6^n a(n) / n!. Then for every n >= 0, y(n) is an odd integer if and only if n = 2^k for some k >= 1.", + "notes": "Conjecture as stated in OEIS: Conjecture: (1/18)*6^(n)*a(n)/n! is odd iff n = 2^k for k >= 1. (End) - _Peter Bala_, Feb 19 2026\n\nReferees: OEIS A144637 (Bala conjecture, Feb 19 2026; entry revision #25, Mar 14 2026; no proof recorded). The companion conjecture in OEIS A144636 (Bala, Feb 16 2026) is also unresolved. OEIS A144633 and A144385 give the definitions. Checked with nothing found on either conjecture: S. Fried, \"Proofs of Ten Conjectures From the OEIS\", J. Integer Sequences 29 (2026), Art. 26.1.8; S. Fried, \"Further proofs of conjectures from the OEIS\", arXiv:2607.24832 (full text grepped); Epoch AI, \"OEIS Open\", arXiv:2608.11941 and github.com/epoch-research/LeanOpenProblems (no A14463x file); Engbers–Galvin–Smyth, \"Restricted Stirling and Lah number matrices and their inverses\", JCTA 2019 (integrality of inverses, not parity). No prior proof or counterexample found.", + "date": "2026-10-26", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Bala's formula in the entry: (1/18)A(6x) satisfies 36y^3 + 3y^2 + (1+6x)y = x^2 (this follows from Jovovic's e.g.f. B(x)^2/2, where B is the series reversion of x + x^2/2 + x^3/6, as given in A144636).", + "justification": "The entry already gives the algebraic equation 36y^3 + 3y^2 + (1+6x)y = x^2 for y(x) = A(6x)/18. Rewritten as y = x^2 - 6xy - 3y^2 - 36y^3 with y(0) = 0, it determines each coefficient from earlier ones using only integer arithmetic, so every coefficient is an integer. Reducing mod 2 gives y = x^2 + y^2 over F_2, and the Frobenius map then forces y = sum over k >= 1 of x^(2^k). The whole argument takes a few lines and uses standard tricks. The Lean proof is long only because it also has to derive the cubic from the matrix-inverse definition.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A160848", + "slug": "oeis-a160848", + "title": "Barker's order-20 recurrence for the lines through an 8 x n grid holds", + "area": "Discrete geometry", + "source": "OEIS A160848", + "source_url": "https://oeis.org/A160848", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A160848.lean", + "decl": "Math0.Statements.A160848.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A160848.lean", + "our_decl": "Math0.Frontier.A160848.result", + "summary": "Let a(n) be the number of lines in the plane through at least 2 points of the 8 x n grid {0..n-1} x {0..7} (OEIS A160848). Then for every n > 21: a(n) = -a(n-2) + a(n-5) + a(n-6) + 2a(n-7) + a(n-8) + a(n-9) - a(n-11) - a(n-12) - 2a(n-13) - a(n-14) - a(n-15) + a(n-18) + a(n-20) (Colin Barker's 2017 conjecture).", + "notes": "Conjecture as stated in OEIS: Conjectures from _Colin Barker_, Dec 25 2017: \"a(n) = -a(n-2) + a(n-5) + a(n-6) + 2*a(n-7) + a(n-8) + a(n-9) - a(n-11) - a(n-12) - 2*a(n-13) - a(n-14) - a(n-15) + a(n-18) + a(n-20) for n>21\", with g.f. denominator (1-x)^3(1+x)(1-x+x^2)(1+x^2)(1+x+x^2)(1+...+x^4)(1+...+x^6).\n\nReferees: - OEIS A160848 (local mirror, revision #13 of Dec 25 2017): Barker's g.f. and order-20 recurrence are labelled \"Conjectures from Colin Barker, Dec 25 2017\", with no later %E. Siblings A160845, A160846, A160847, A160849 and A160850 are likewise still conjectural or empirical; A295707 is the parent array.\n- S. Mustonen, \"On lines and their intersection points in a rectangular grid of points\", http://www.survo.fi/papers/PointsInGrid.pdf (2009). Section 3 proves L(m,n) = ½[f(m,n,1) - f(m,n,2)]. Appendix 2, eq. (38), gives the second-difference recursion L(m,n) = 2L(m,n-1) - L(m,n-2) + 2ψ1 + 2ψ4 with periodic residuals, supported by a heuristic \"bearing points\" argument and numerical checks; that recursion is the basis of the Mathematica code in the OEIS entry.\n- P. Haukkanen and J. K. Merikoski, arXiv:1108.1041 (2011), Remark 2: for n1 ≠ n2, \"Mustonen [5] conjectured a recursive formula\", and the question is \"more difficult\".\n- A.-M. Ernvall-Hytönen, K. Matomäki, P. Haukkanen and J. K. Merikoski, \"Formulas for the number of gridlines\", Monatsh. Math. 164 (2011) 157-170: proves Mustonen's recursions only for n×n and (n-1)×n grids.\n- S. Mustonen, \"On lines through a given number of points in a rectangular grid of points\", LinesInGrid2.pdf: covers square grids only.\n\nNo prior proof or counterexample of Barker's A160848 recurrence was found.", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The entry's own formula a(n) = (1/2)(f(8,n,1) - f(8,n,2)), with f(m,n,k) = Sum (n-|kx|)(m-|ky|) over coprime (x,y), proved by Mustonen (PointsInGrid.pdf, Section 3) and repeated in the parent array A295707. Taking the second difference in n gives a periodic residual, which is Mustonen's eq. (38) for m=8.", + "justification": "The conjecture follows readily from the slope-sum formula already in the entry. With 8 rows, y ranges over a bounded set, and for each fixed y the second difference in n of Sum_x (n-|kx|)[gcd(x,y)=1] is a gcd indicator that is periodic with period at most 7 (at most 6 for the k=2 term). So the second difference of a(n) is eventually a combination of sequences with periods 1..7. That means a(n) is annihilated by (1-x)^2 times lcm(1-x^q : q<=7), which is exactly Barker's denominator (1-x)^3 Phi_2...Phi_7. The manuscript re-derives the counting formula via \"first pairs\" and checks the period-420 identity by kernel computation, but the underlying idea is a standard half-page quasi-polynomial argument.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A172164", + "slug": "oeis-a172164", + "title": "A172164: the second differences of the Theodorus-spiral turns are always 18, 19, 20 or 21", + "area": "Discrete geometry", + "source": "OEIS A172164", + "source_url": "https://oeis.org/A172164", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A172164.lean", + "decl": "Math0.Statements.A172164.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A172164.lean", + "our_decl": "Math0.Frontier.A172164.result", + "summary": "Let S(k) = sum_{i=1}^{k} arctan(1/sqrt i) be the total central angle of the first k triangles of the spiral of Theodorus. Triangle i covers the angular sector [S(i-1), S(i)], and turn n is the angle range [2pi(n-1), 2pi n]. Let c(n) be the number of triangles i >= 1 that lie entirely inside turn n, that is, with 2pi(n-1) <= S(i-1) and S(i) <= 2pi n. Then for every n >= 2, the difference a(n) = c(n) - c(n-1) is one of 18, 19, 20, 21. This is Dumortier's conjecture in OEIS A172164.", + "notes": "Conjecture as stated in OEIS: \"Conjecture : The terms are only 18,19,20,21 (From the first thousand turns, there are 2,3% of 18, 36,5% of 19, 46,2% of 20 and 15% of 21). No period found. Probably due to Pi transcendence.\" (Sebastien Dumortier, Jan 27 2010)\n\nReferees: I found no prior proof or counterexample.\n\nOEIS entries (local mirror, identical to the raw GitHub copy):\n- A172164 (Dumortier, 2010): the conjecture, with numerical frequency checks by R. G. Wilson v (1e5 turns) and H. Kociemba (1e7 turns), 2013. Still listed as a conjecture at edit #25, Aug 2026.\n- A137515: \"the number added grows by 18, 19, 20 or 21 (tested up to 5000 terms)\"; restated by H. P. Dale in 2019 with no proof.\n- A072895: Kociemba's comment that floor((pi n + c)^2 - 1/6) with c = -K/2 = 1.0788914983... differs from A072895(n) by at most 1, and equals it for n < 1e9 (numerical only).\n- A105459: Hlawka's Schneckenkonstante K, with the formula Sum_{x= 71, and a finite interval computation covers n <= 70. This is about a page of standard effective asymptotics plus a finite check, and the scout's own plan (Euler-Maclaurin plus a check of small n) already calls every step standard. The Lean work, including the kernel-evaluated interval certificate, was heavy, but that is formalization effort and not new mathematics.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A175385", + "slug": "oeis-a175385", + "title": "∑_{i=1..n} C(2n-i-1, i-1)/i is never an integer for n > 1 (A175385)", + "area": "Number theory", + "source": "OEIS A175385", + "source_url": "https://oeis.org/A175385", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A175385.lean", + "decl": "Math0.Statements.A175385.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/Frontier/OEIS/A175385.lean", + "our_decl": "Math0.Frontier.A175385.result", + "summary": "For every integer n ≥ 2, the rational number S(n) = ∑_{i=1}^{n} C(2n-i-1, i-1)/i is not an integer. This is the Shevelev–Seidov conjecture from OEIS A175385.", + "notes": "Conjecture as stated in OEIS: We conjecture that Sum_{i=1..n} ((1/i)*C(2n-i-1,i-1)) is not an integer for n>1. (Vladimir Shevelev, Zak Seidov, Apr 24 2010)\n\nReferees: OEIS A175386 (cross-reference of A175385), comment by Ralf Stephan, May 25 2026: the conjecture was proved by an autonomous AI agent (AlphaProof Nexus). Lean file: https://github.com/google-deepmind/alphaproof-nexus-results/blob/main/APNOutputs/OEIS/oeis_175386_conjecture_0.lean (theorem target_theorem_0: for n > 1, the denominator of S(n) is not 1; checked, no sorry). Papers: G. Tsoukalas et al., \"Advancing Mathematics Research with AI-Driven Formal Proof Search\", arXiv:2605.22763 (May 2026); T. Adamczewski, \"OEIS Open: How many conjectures can language models turn into theorems?\", arXiv:2608.11941 (Aug 2026), cited by OEIS for the proof on p. 15, Appendix A. Classical implication: P. S. Bruckman, \"Lucas Pseudoprimes Are Odd\", Fibonacci Quarterly 32(2) (1994) 155-157 (https://www.mathstat.dal.ca/FQ/Scanned/32-2/bruckman2.pdf). No even composite N has N | L_N − 1, and with 2n·S(n) = L_{2n} − 1 this settles the conjecture. The A175385 entry itself (https://oeis.org/A175385, history up to #14, Mar 2023) records no proof.", + "date": "2026-10-18" + }, + { + "id": "OEIS-frontier/A176206", + "slug": "oeis-a176206", + "title": "Divisors of the terms of row n of A176206 are the parts of the partitions of n", + "area": "Discrete geometry", + "source": "OEIS A176206", + "source_url": "https://oeis.org/A176206", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A176206.lean", + "decl": "Math0.Statements.A176206.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A176206.lean", + "our_decl": "Math0.Frontier.A176206.result", + "summary": "Row n of A176206 lists n - k repeated p(k) times for k = 0, ..., n-1, where p is the partition function. Pol's conjecture says that for every n >= 1, the multiset of all divisors of all terms of row n equals the multiset of all parts of all partitions of n. Divisors and parts are counted with multiplicity: each term t of the row contributes each divisor of t once, and each partition contributes all of its parts.", + "notes": "Conjecture as stated in OEIS: %C Conjecture: all divisors of all terms in row n are also all parts of all partitions of n. (Omar E. Pol, Nov 2020)\n\nReferees: OEIS A066633 (number of k's in all partitions of n): g.f. x^k/(1-x^k)*Prod 1/(1-x^m) by V. Jovovic (Jan 2002); T(n,k) = Sum_{j= 0. (2) a(n) = 21 a(n-1) - 143 a(n-2) + 315 a(n-3) for every n >= 3. (3) As formal power series over Q, sum a(n) x^n = x(-5+41x) / ((9x-1)(7x-1)(5x-1)).", + "notes": "Conjecture as stated in OEIS: Conjecture: a(n) = 9^n/2+3*7^n/2-2*5^n. a(n)= +21*a(n-1) -143*a(n-2) +315*a(n-3). G.f.: x*(-5+41*x)/((9*x-1)*(7*x-1)*(5*x-1)). [_R. J. Mathar_, May 24 2010]\n\nReferees: No published resolution of the A178295 formula was found. Local mirror oeisdata seq/A178/A178295.seq (%I #15, Jul 22 2025): the formula is still labelled \"Conjecture [R. J. Mathar, May 24 2010]\", with no %E lines and no cross-references to it.\n\nRelated sources:\n- **R. J. Mathar, \"Points on a line in the finite d-dimensional simple cubic lattice\"** (oeis.org/A178294/a178294.pdf). Its abstract calls it a \"mostly speculative summary\", fitting Hardin's tables to Ehrhart polynomials. I saw only search snippets and an independent report, not the full text: the mirror has only an LFS pointer, and oeis.org and the Wayback Machine were inaccessible.\n- **the-omega-institute/trureturing, GitHub issue #7376 (Sep 12–13, 2026).** A Lean proof of sibling A178294 (triples in the 4^n grid). Its literature check found \"no proof or refutation as of 2026-09-13\" and says the Mathar PDF gives the formula only as a fit. It does not mention A178295.\n- **Classical full-line count ((k+2)^n - k^n)/2**, which gives the (7^n-5^n)/2 ingredient (A081200, itself still labelled a Hardin conjecture in OEIS):\n - P. Erdős and J. L. Selfridge, J. Combin. Theory Ser. A 14 (1973) 298-301.\n - S. W. Golomb and A. W. Hales, \"Hypercube Tic-Tac-Toe\", MSRI Publ. 42 (2002), Theorem 1.\n - L. Moser's proof, via Honsberger.\n - O. Patashnik, Math. Mag. 53 (1980).\n- **Same-batch siblings, still labelled conjectures:** A081199, A081200, A081201, A178294, A178296-A178299.\n- **Checked, no relevant result:** arXiv:2609.25133 (Kudriashov, Sep 2026), arXiv:2404.02369, arXiv:1107.0327.", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The classical tic-tac-toe line count ((k+2)^n - k^n)/2 for the grid {0,...,k-1}^n (Erdos-Selfridge 1973; Golomb-Hales 2002, Theorem 1; Moser's word-counting proof). With k=5 this gives the (7^n-5^n)/2 full lines, which is OEIS A081200. The same word-counting method gives (9^n-5^n)/2 runs of four consecutive collinear points.", + "justification": "Any line meeting {0,...,4}^n in 4 or more points has a primitive direction in {0,±1}^n, because a coordinate step of 2 or more allows at most 3 points. So a collinear 4-set is either 4 consecutive points on such a line, which Golomb-Hales word counting gives as (9^n-5^n)/2 (9 choices per coordinate, not all constant, up to reversal), or one of the 3 non-consecutive 4-subsets of a full 5-point line, giving 3(7^n-5^n)/2. The recurrence and generating function then follow mechanically from the closed form. This is a standard argument of under a page, an easy variant of the classical count; the manuscript itself calls it short and elementary. The formalized route through a finite classification of columns is formalization engineering, not a new mathematical idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A182617", + "slug": "oeis-a182617", + "title": "The toothpick spiral around n hexagonal cells (A182617): a(n) = 2n + ceil(sqrt(12n - 3))", + "area": "Discrete geometry", + "source": "OEIS A182617", + "source_url": "https://oeis.org/A182617", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A182617.lean", + "decl": "Math0.Statements.A182617.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A182617.lean", + "our_decl": "Math0.Frontier.A182617.result", + "summary": "For the toothpick spiral on the hexagonal net, encoded as in Math0.Statements.A182617, let a(n) be the least number t of toothpicks at which at least n cells are ON. Then for every n > 0, a(n) = 2n + ceil(sqrt(12n - 3)). This is Librandi's conjecture from 2017.", + "notes": "Conjecture as stated in OEIS: %F A182617 Conjecture: a(n) = 2*n + ceiling(sqrt(12*n - 3)), for n > 0. - _Vincenzo Librandi_, Sep 20 2017\n\nReferees: OEIS A182617 (rev #35, Sep 23 2025): the formula is still marked \"Conjecture\", with no %E lines recording a resolution. No other OEIS entry in the local mirror references A182617. Related known results:\n- A135708, minimal edge count of an n-cell polyhex, 3n + ceil(sqrt(12n-3)), attributed to H. Harborth; Kupitz 1991.\n- A135711, minimal polyhex perimeter, 2*ceil(sqrt(12n-3)).\n- F. Harary and H. Harborth, \"Extremal animals\", J. Combin. Inform. System Sci. 1 (1976): spiral animals attain the minimum.\n- G. Malen, É. Roldán and R. Toalá-Enríquez, \"Extremal {p,q}-Animals\", Ann. Comb. (2023), arXiv:2109.05331, Cor. 1.9.\n- É. Roldán and R. Toalá-Enríquez, \"Isoperimetric Formulas for Hyperbolic Animals\", arXiv:2206.14910.\n- A036496 (W. C. Yang): ceil(sqrt(12n-3)) for a triangular-lattice spiral.\n- Applegate, Pol and Sloane, \"The Toothpick Sequence and Other Sequences from Cellular Automata\", Congr. Numer. 206 (2010), arXiv:1004.3036: background only, no formula for A182617.\nNone of these states or proves the A182617 formula. They imply it only together with the extra fact that the toothpick walk's vertex set at time a(n) equals the vertex set of the extremal n-cell spiral, which I found nowhere in print.", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Harborth's formula 3n + ceil(sqrt(12n-3)) for the minimal edge count of an n-cell polyhex (A135708), which spiral polyhexes attain (Harary-Harborth 1976). Together with Euler's formula this gives |V| = 2n + ceil(sqrt(12n-3)) + 1 for the n-cell spiral. The toothpick path at stage n covers exactly the spiral's vertices, so a(n) = |V| - 1. The ring-by-ring increments listed in A182618 lead to the same result.", + "justification": "The walk is an explicit spiral. Ring m of vertices is visited during times 6m^2+2m to 6m^2+14m+7. Cell s of cell ring j becomes ON at time 6j^2 - 1 + 2s + c, where c (1 to 6) is one more than the number of ring corners passed so far. With n = 3j(j-1)+1+s we have 12n-3 = (6j-3)^2 + 12s, and checking which pair of consecutive squares this lies between gives ceil(sqrt(12n-3)) = 6j-3+c. Equivalently, the result is Harborth's known spiral-polyhex edge count combined with Euler's formula. That is about a page of standard counting. The long Lean proof (coordinates, case analysis over the six sides) is formalization effort, not a new idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A188474", + "slug": "oeis-a188474", + "title": "The row sums of the generalized Deutsch triangle A188474 are A137398", + "area": "Discrete geometry", + "source": "OEIS A188474", + "source_url": "https://oeis.org/A188474", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A188474.lean", + "decl": "Math0.Statements.A188474.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A188474.lean", + "our_decl": "Math0.Frontier.A188474.result", + "summary": "Let T(n,k) = sum_{j=0}^{n-k+1} (j/(n+2-j)) C(n+2-j, n-k+1) C(n+2-j, k+1) 2^(j-1), computed in Q, for 0 <= k <= n. Let A137398(m) be the number of subsequences p of S = (0,1,...,2m-1) of length m with 0 in p such that, with q the complementary subsequence, no index i < m has the property that exchanging p(i) and q(i) leaves both p and q strictly increasing. Then for every n >= 0, sum_{k=0}^{n} T(n,k) = A137398(n+2). (This is Paul Barry's 2011 conjecture \"Row sums are A137398(n+1)\", in the current offset of A137398.)", + "notes": "Conjecture as stated in OEIS: %C A188474 Row sums are A137398(n+1) (conjecture). Diagonal sums are A188476. (_Paul Barry_, Apr 01 2011)\n\nReferees: No prior explicit resolution of Barry's conjecture found. The A188474 entry (local mirror, revision #6, Mar 30 2012) still marks the row-sum claim as \"(conjecture)\". The relevant prior material that makes it nearly immediate:\n- **Callan's comment on OEIS A137398 (Nov 25 2021).** A137398 counts Grand Dyck paths starting with U with no peak at height 1 and no valley at height −1, with g.f. satisfying F = x(C−1)+2x(C−1)F. This is exactly the row-sum g.f. of A188474.\n- **OEIS A137398 G.f. line.** 2x²/(1−2x−4x²+√(1−4x)), the same function after rationalizing; the original authors' recurrence a(n)=2a(n−1)+2a(n−2)+Σ C(k)a(n−k−1) is also on the entry.\n- **OEIS A100754 (E. Deutsch).** Deutsch's g.f. tzr/(1−tzr) with the Narayana function r, from which Barry's r-family g.f. follows.\n- **Goy & Shattuck, Carpathian Math. Publ. 15(2) (2023) 420–436, arXiv:2303.10223.** Thm 5 eq. (25) proves that a Fine-number determinant equals A137398, taking A137398's recurrence as its definition. It does not address A188474.\n\nSearches came up empty for arXiv, the web generally, and SeqFan (not specifically found or checked). They covered \"A188474\", \"A137398\", \"generalized Deutsch triangle\", the term string 1,2,7,22,74,252,875,3078, and Barry's Riordan/Pascal-like papers (JIS 2007, 2011, 2019; arXiv 2606.22070).", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Vandermonde's identity and the ballot/Lagrange formula (j/N)C(2N,N-j) = [x^N](xC(x)^2)^j give the row-sum g.f. x^2C^2/(1-2x^2C^2). That equals the g.f. 2x^2/(1-2x-4x^2+sqrt(1-4x)) stated in A137398 (%F), and also Callan's 2021 path decomposition F = x(C-1)+2x(C-1)F in A137398.", + "justification": "The row sum collapses with one application of Vandermonde's identity to the sum of 2^(j-1)(j/N)C(2N,N-j) over j. The ballot formula turns this into a geometric series in x^2C(x)^2, and a few lines of algebra show it equals the generating function already printed in A137398, which matches Callan's path decomposition there. The Lean proof does more work, because it starts from A137398's combinatorial definition: it shows that a swap keeps both lists increasing exactly when the walk has a \"hump\", which is Callan's path model, and then counts with first-passage numbers. That is only a short observation plus formalization effort, so the mathematics is standard and fits in about a page.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A195249", + "slug": "oeis-a195249", + "title": "3 × 3 lower triangles with neighbours differing by at most two: a(n) = 1047 n - 1459 for n > 2 (A195249)", + "area": "Discrete geometry", + "source": "OEIS A195249", + "source_url": "https://oeis.org/A195249", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A195249.lean", + "decl": "Math0.Statements.A195249.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A195249.lean", + "our_decl": "Math0.Frontier.A195249.result", + "summary": "Let a(n) be the number of fillings (x0,...,x5) of the six cells of the lower triangle of a 3 × 3 array (rows of lengths 1, 2, 3) with entries in {0,...,n}, such that any two king-adjacent cells (horizontal, vertical or diagonal neighbours) have entries differing by at most 2. The adjacent pairs are 0-1, 0-2, 1-2, 1-3, 2-3, 1-4, 2-4, 3-4, 2-5, 4-5. Then a(n) = 1047 n - 1459 for every n > 2. This is Hardin's empirical formula from OEIS A195249.", + "notes": "Conjecture as stated in OEIS: %F Empirical: a(n) = 1047*n - 1459 for n>2. (R. H. Hardin, Sep 13 2011); %F Conjectures from Colin Barker, May 06 2018: G.f.: x*(64 + 601*x + 288*x^2 + 94*x^3) / (1 - x)^2. a(n) = 2*a(n-1) - a(n-2) for n>4.\n\nReferees: I found no prior proof of A195249 or of row 3 of A195248. The local OEIS mirror entries for A195249, A195248 and A195214 have no %E lines and still mark the formulas 'Empirical'. The closest prior work is Robert Israel's comment (Nov 21 2017) on the sibling sequence OEIS A195232 ('one or less' variant), which proves the analogous linearity in k with the same span argument; this is a direct template for the current proof. Israel's Ehrhart-polynomial comment on A195220 (Oct 06 2019) is related. Hardin's own 'Generalizing' note on A195248 gives no proof. Searches I checked that turned up nothing relevant: Dougherty-Bliss & Kauers, 'Hardinian Arrays', Electron. J. Combin. 31(2) P9 (arXiv:2309.00487), which treats a different Hardin family; Ekhad-Yang-Zeilberger arXiv:1707.04654, which treats Mathar's conjectures; and web, arXiv and MathOverflow searches for the formula, the A-numbers and the entry's name text.", + "date": "2026-10-20", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The standard bounded-span (translation) argument, written down by Robert Israel (Nov 21 2017) for the sibling table A195232: any two cells of the triangle are joined by at most two neighbouring steps, so every valid filling spans at most 4. Hence a(n) = sum over s of N_s*(n+1-s), which is linear in n once n >= 3. A finite count of shapes (or of T(8,4) = 1047 plus a(3..7)) fixes the constants. This is also Hardin's 'Generalizing' remark in A195248 (slope = A195214(3)).", + "justification": "The proof uses one standard observation. Every entry lies within 4 of the apex, so fillings are translates of finitely many shapes. That makes a(n) affine in n beyond a small threshold, and a finite computation (T(8,4) = 1047 and a(3) to a(7)) supplies the slope and intercept. The manuscript itself says this is essentially Israel's bounded-span argument from the sibling sequence A195232. No new idea is needed: it is a short argument plus a direct computation, and the work beyond that is formalization.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A201060", + "slug": "oeis-a201060", + "title": "Repdigits with repdigit digital product are repunits from a(16) = 1111 on (A201060)", + "area": "Sequences and series", + "source": "OEIS A201060", + "source_url": "https://oeis.org/A201060", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A201060.lean", + "decl": "def statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A201060.lean", + "our_decl": "Math0.Frontier.A201060.result", + "summary": "Let a(1) < a(2) < ... list the repdigits (all decimal digits equal; 0 counts) whose digital product is also a repdigit. Then a(n) is a repunit (all digits equal to 1) for every n >= 16. Formally: forall n >= 16, IsRepunit (a n), where a n = Nat.nth IsTerm (n - 1).", + "notes": "Conjecture as stated in OEIS: \"Conjecture: a(n) is repunit for n >= 16.\" (A201060, entry by _Jaroslav Krizek_, Nov 26 2011)\n\nReferees: Main citations:\n- R. Obláth, \"Une propriété des puissances parfaites\", Mathesis 65 (1956), 356–364. It shows that the only perfect powers with all decimal digits equal to some a != 1 are 4, 8 and 9.\n- Y. Bugeaud and M. Mignotte, \"On integers with identical digits\", Mathematika 46 (1999), 411–417. It shows that no decimal repunit with two or more digits is a perfect power.\nTogether these say that no repdigit >= 10 is a perfect power, and the A201060 conjecture follows directly, since d^k >= 16 for 2 <= d <= 9 and k >= 4.\n\nBoth results are restated in O. Kihel and F. Luca, \"Perfect Powers With All Equal Digits But One\", J. Integer Seq. 8 (2005), Article 05.5.7, Introduction (https://cs.uwaterloo.ca/journals/JIS/VOL8/Kihel/kihel7.html). See also A. Gica and L. Panaitopol, \"On Oblath's Problem\", J. Integer Seq. 6 (2003), Article 03.3.5, which is linked from OEIS A018885 and A368049. The Wikipedia article \"Repdigit\" (https://en.wikipedia.org/wiki/Repdigit) covers the related Nagell–Ljunggren equation and cites Bugeaud–Mignotte 2002.\n\nThe OEIS entry A201060 (local mirror, revision #11, 2012) still labels the statement as a conjecture, and I found no web or arXiv discussion that names A201060.", + "date": "2026-10-20" + }, + { + "id": "OEIS-frontier/A209802", + "slug": "oeis-a209802", + "title": "Positivity of the exponential Mertens function (A209802)", + "area": "Sequences and series", + "source": "OEIS A209802", + "source_url": "https://oeis.org/A209802", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A209802.lean", + "decl": "Math0.Statements.A209802.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A209802.lean", + "our_decl": "Math0.Frontier.A209802.result", + "summary": "Let mu_e be the exponential Möbius function (A166234). It is multiplicative with mu_e(p^e) = mu(e), so mu_e(n) = prod_{p | n} mu(v_p(n)). Let a(n) = sum_{k=1}^{n} mu_e(k) (A209802). Then a(n) > 0 for every n >= 1. This is Zumkeller's conjecture in the OEIS entry.", + "notes": "Conjecture as stated in OEIS: A209802 (Partial sums of exponential Möbius function, A166234): \"Analog of Mertens's function, A002321; conjecture: a(n) > 0.\" (entry by _Reinhard Zumkeller_, Mar 13 2012)\n\nReferees: No explicit resolution of the A209802 conjecture found:\n- OEIS A209802 (https://oeis.org/A209802) and its history (https://oeis.org/history?seq=A209802, versions 1-29) still list \"conjecture: a(n) > 0\"; nothing about a proof is recorded.\n- A166234 (exponential Möbius function) and A368405 add nothing on positivity.\n\nPrior results that imply the conjecture at once:\n- K. Rogers, \"The Schnirelmann density of the squarefree integers\", Proc. Amer. Math. Soc. 15 (1964) 515-516, doi:10.1090/S0002-9939-1964-0163893-X. It proves Q(n) >= 53n/88 for all n, with equality only at n = 176.\n- L. Moser and R. A. MacLeod, \"The error term for the squarefree integers\", Canad. Math. Bull. 9 (1966), doi:10.4153/CMB-1966-039-4.\n- The same bound is recorded in an OEIS A013928 comment (M. Marcus 2012; C. R. Greathouse IV 2016).\n- L. Tóth, \"On certain arithmetic functions involving exponential divisors, II\", Annales Univ. Sci. Budapest. Sect. Comp. 27 (2007) 155-166, arXiv:0708.3557. It gives mu_e taking values in {-1, 0, 1} with mu_e(p) = 1, and the asymptotic sum mu_e(n) = c x + O(x^{1/2} log x) with c about 0.36094. That settles positivity only for large x.\n\nTogether these give a(n) >= 2Q(n) - n >= 9n/44 > 0 for all n >= 1.\n\nAlso checked, with nothing relevant found:\n- Lelechenko, arXiv:1405.7597\n- Cao and Zhai, J. Integer Seq. 13 (2010)\n- Web, MathOverflow and Math StackExchange searches", + "date": "2026-10-18" + }, + { + "id": "OEIS-frontier/A211343", + "slug": "oeis-a211343", + "title": "A211343: positive entries are smallest parts of consecutive-part partitions; last positive column is A109814(n)", + "area": "Discrete geometry", + "source": "OEIS A211343", + "source_url": "https://oeis.org/A211343", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A211343.lean", + "decl": "Math0.Statements.A211343.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A211343.lean", + "our_decl": "Math0.Frontier.A211343.result", + "summary": "Let T(n,k) be the triangle in which column k (k >= 1) begins in row k(k+1)/2 and lists 1, 0^(k-1), 2, 0^(k-1), 3, ... going down. In other words, for 1 <= k and k(k+1)/2 <= n we have T(n,k) = j/k + 1 when k divides j = n - k(k+1)/2, and T(n,k) = 0 otherwise. Two claims are made. (1) For n >= 1 and any entry (n,k) of the triangle with T(n,k) > 0, n has a partition into k consecutive parts m, m+1, ..., m+k-1, and T(n,k) is the smallest part of every such partition. (2) For n >= 1, A109814(n), the largest k such that n is a sum of k consecutive positive integers, is the largest column k of row n with T(n,k) > 0.", + "notes": "Conjecture as stated in OEIS: %C Conjecture 1: T(n,k) is the smallest part of the partition of n into k consecutive parts, if T(n,k) > 0. %C Conjecture 2: the last positive integer in the row n is in the column A109814(n). (Omar E. Pol, Apr 30 2017)\n\nReferees: OEIS (local mirror): A261699 comment by Peter Munn, Jul 30 2017 (\"A211343(n,k) = abs(n/d - d/2) + 1/2, smallest part\"; one-to-one link between odd divisors and partitions into k consecutive parts). A286013 comment by Peter Munn, Jun 18 2017 (trapezoid proof of the largest-part companion conjecture, which carries over directly to smallest parts). A285898 comment by David A. Corneth, Apr 28 2017 (n has a partition into k consecutive parts iff (n - C(k,2))/k is a positive integer). A196020 formula by Max Alekseyev, Nov 18 2013 (T(n,k) = 2n/k - k on the support), combined with the A211343 formula T = floor((1+A196020)/2). A237048 property by Hartmut F. W. Hoft, Oct 2014. A286000 \"Theorem\" (Pol). A379632 (Pol, Dec 2024: \"Positive terms of A211343\", \"Right border gives A118235\"). A118235 (smallest part of partitions into consecutive parts). A109814 (Jaap Spies / David W. Wilson: 2n = k(2m+k-1)). The classical background is Sylvester's enumeration of partitions into consecutive parts. Not retrievable (web.archive.org unreachable): Joerg Arndt, SeqFan, Jun 3 2017, proof of the A285914/A204217 conjectures. Web searches found no counterexample and no paper on A211343 specifically.", + "date": "2026-10-24" + }, + { + "id": "OEIS-frontier/A215010", + "slug": "oeis-a215010", + "title": "An equiangular decagon with sides in arithmetic progression (A215010)", + "area": "Discrete geometry", + "source": "OEIS A215010", + "source_url": "https://oeis.org/A215010", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A215010.lean", + "decl": "Math0.Statements.A215010.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-refutes", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A215010.lean", + "our_decl": "Math0.Frontier.A215010.result : ¬ Math0.Statements.A215010.statement", + "summary": "Garcia's conjecture (OEIS A215010) says that hexagons are the only equiangular simple convex polygons whose integer side lengths are the N terms t, t+d, ..., t+(N-1)d (with d ≥ 1) of an arithmetic progression, in some order. Formally: if N ≥ 3, every side t + σ(k)·d is positive, and Σ_k (t + σ(k)d)·exp(2πik/N) = 0 for a permutation σ of Fin N, then N = 6. We prove that this is false. Take N = 10 and t = d = 1, with consecutive sides (1, 4, 5, 8, 9, 2, 3, 6, 7, 10), so σ = (0, 3, 4, 7, 8, 1, 2, 5, 6, 9). This gives an equiangular decagon.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: hexagons are the only simple convex polygons with equal interior angles with such property, due to the fact that cos(Pi/3) = 1/2.\" Here 'such property' means integer side lengths in arithmetic progression t+m*d, as in the entry name. (entry by _Robin Garcia_, Jul 31 2012)\n\nReferees: Prior refutations, all at least as old as or published soon after Garcia's 2012 conjecture:\n\n(1) OEIS A118887 (H. Pfoertner, May 03 2006). \"Number of ways to place n objects with weights 1,...,n evenly spaced around a circle so it balances.\" T. D. Noe, Sep 13 2005: \"Also number of equiangular polygons whose sides are some permutation of 1,2,3,...,n.\" The data have included a(10)=24, a(12)=732, a(14)=720, a(15)=48 since the first revision in 2006. W. Edwin Clark (Sep 14 2005) proved there are no solutions when n is a prime power. J. Sondow (Oct 17 2013) records that Murray Klamkin proved solutions exist when n is not a prime power, and adds the formula a(A024619(n)) > 0. The problem was proposed by Brendan McKay on the SeqFan mailing list, Sep 12 2005. https://oeis.org/A118887\n\n(2) G. J. Woeginger, \"Nothing new about equiangular polygons\", Amer. Math. Monthly 120(9) (2013) 849–850, doi:10.4169/amer.math.monthly.120.09.849. Abstract: \"We survey results on equiangular n-vertex polygons with edge lengths in arithmetic progression. Such a polygon exists if and only if n has at least two distinct prime factors.\" This is exactly the A215010 setting, and it gives n = 10, 12, 14, 15, ... as counterexamples.\n\n(3) Supporting references:\n- D. Ball, \"Equiangular polygons\", Math. Gazette 86 (2002) 396–407.\n- A. Bernoff, \"Bernoff's Puzzler\", MuddMath Newsletter 4(1) (2005), p. 10.\n- M. Munteanu and L. Munteanu, \"Rational equiangular polygons\", Applied Math. 4 (2013) 1460–1465, doi:10.4236/am.2013.410197.\n- U. Abel, \"Coincidence of the barycentre and the geometric centre of weighted points\", Math. Gazette (online Oct 2019). It restates the criterion: at least two distinct prime factors.\n\nA215010 itself (history checked through revision #43, Jan 23 2015) never cites any of these, and its conjecture remains uncorrected. I found no earlier formalization in Lean or any other proof assistant.", + "date": "2026-10-18" + }, + { + "id": "OEIS-frontier/A223395", + "slug": "oeis-a223395", + "title": "A223395: walks on the 4 x 4 grid graph satisfy Hardin's recurrence, Barker's g.f. and closed form", + "area": "Discrete geometry", + "source": "OEIS A223395", + "source_url": "https://oeis.org/A223395", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A223395.lean", + "decl": "Math0.Statements.A223395.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A223395.lean", + "our_decl": "Math0.Frontier.A223395.result", + "summary": "Let a(n) be the number of walks with n vertices in the 4 x 4 grid graph P4 x P4 (the number of n x 1 arrays over the nodes 0..15 where vertically adjacent entries are adjacent nodes). Then (1) a(n) = 3a(n-1) + 2a(n-2) - 4a(n-3) for all n >= 4 (in Z); (2) (1 - x)(1 - 2x - 4x^2) * sum_{n>=1} a(n) x^n = 8x(2 - 3x^2) as formal power series over Z; (3) a(n) = (8 + (11 - 5 sqrt5)(1 - sqrt5)^n + (1 + sqrt5)^n (11 + 5 sqrt5)) / 5 for all n >= 1 (in R).", + "notes": "Conjecture as stated in OEIS: \"Empirical: a(n) = 3*a(n-1) + 2*a(n-2) - 4*a(n-3).\" and \"Conjectures from _Colin Barker_, Aug 20 2018: G.f.: 8*x*(2 - 3*x^2) / ((1 - x)*(1 - 2*x - 4*x^2)) ...\"\n\nReferees: OEIS sources (local mirror):\n- A223395 (R. H. Hardin, Mar 19 2013; Barker's conjectures added Aug 20 2018; rev #7). The recurrence is still \"Empirical\" and the g.f. and closed form are still \"Conjectures\"; there are no %E lines.\n- A223402 (rev #8, Oct 03 2025). The column k=1 recurrence is still listed as empirical.\n- A223372 (the 3x3 analogue, also empirical).\n- A081057 (P. D. Hanna 2003; g.f. and recurrence by M. Somos and V. Jovovic, Mar 2003; R. J. Mathar, Oct 2010: \"apparently\" counts walks from a corner of the 4x4 board; D. Scambler, Oct 2010: decomposition into independent horizontal and vertical walks, giving a binomial convolution of Fibonacci numbers; I. M. Gessel 2022). It has the same signature (3,2,−4), but for corner-start walks only. I observed that A223395(n) = 2(A081057(n) + A081057(n+1)); this identity is not recorded anywhere.\n- A052899 (same signature; R. Jehn's Oct 2024 comment on walks leaving a 4x4 board).\n\nGeneral theory (implies the result routinely but does not state it):\n- D. Cvetković, M. Doob, H. Sachs, Spectra of Graphs (1980), Thm 1.11: the generating function of total walk counts, in terms of the characteristic polynomials of G and its complement.\n- P. Rowlinson, \"The main eigenvalues of a graph: a survey\", Appl. Anal. Discrete Math. 1 (2007) 455–471.\n- The classical spectrum of P_m□P_n, {2cos(iπ/(m+1)) + 2cos(jπ/(n+1))}.\n\nChecked and not relevant (they concern a different Hardin family):\n- R. Dougherty-Bliss & M. Kauers, \"Hardinian Arrays\", arXiv:2309.00487.\n- G. Spahn & R. Dougherty-Bliss, \"Rectangular Hardinian Arrays\" (2024).\n\nWeb searches (arXiv, MathOverflow/MSE, general) found no explicit prior proof of the A223395 recurrence, g.f. or closed form.", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The transfer-matrix method, a(n) = 1^T A^(n-1) 1 for the adjacency matrix A of P4 x P4, together with standard main-eigenvalue theory (Cvetkovic-Doob-Sachs). The main eigenvalues of P4 x P4 are 1+sqrt5, 1 and 1-sqrt5, which are the roots of (x-1)(x^2-2x-4). In practice everything reduces to the finite check A^3·1 + 4·1 = 3A^2·1 + 2A·1 on 16 vertices.", + "justification": "The sequence counts walks in a fixed 16-vertex graph, so it equals 1^T A^(n-1) 1. Its recurrence therefore comes from the polynomial of least degree that annihilates the all-ones vector under A. The proof checks the identity A^3·1 + 4·1 = 3A^2·1 + 2A·1 directly at every vertex, which comes down to three small symmetric 4x4 arrays, and then applies A repeatedly to get the identity for all n. The generating function and the closed form follow from the recurrence and the first three terms by routine algebra. This is a textbook transfer-matrix or main-eigenvalue argument plus a finite computation, and the manuscript itself calls it routine.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A229159", + "slug": "oeis-a229159", + "title": "Every odd prime is a side of a Heronian triangle (A229159)", + "area": "Discrete geometry", + "source": "OEIS A229159", + "source_url": "https://oeis.org/A229159", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A229159.lean", + "decl": "Math0.Statements.A229159.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A229159.lean", + "our_decl": "Math0.Frontier.A229159.result", + "summary": "For every prime p > 2 there are natural numbers x, y, z, A such that x, y, z satisfy the strict triangle inequalities (x < y + z, y < x + z, z < x + y), Heron's formula 16 A^2 = (x+y+z)(-x+y+z)(x-y+z)(x+y-z) holds in Z, and at least one of x, y, z equals p.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: for all prime p > 2 there exists an integer-sided triangle with integer area where at least one side is of length p.\" (entry by _Michel Lagneau_, Sep 17 2013)\n\nReferees: Classical formula (n, (n^2-1)/2, (n^2+1)/2) for odd n, credited to the Pythagoreans (Proclus, Commentary on Euclid's Elements I.47; H. Eves, An Introduction to the History of Mathematics, sec. 3-4; cf. Euclid, Elements X, Lemma 1 before Prop. 29). OEIS A046079, comment by Richard R. Forberg, May 31 2013: \"For odd n: L = (n^2-1)/2 and H = L+1\". In the same entry, Ant King (Jan 29 2011) notes that for n > 2 the n with exactly one Pythagorean triangle on leg n are the primes and their doubles. OEIS A042965 (Sloane, May 30 2014): the primes that are a difference of two squares are exactly the odd primes. Related: A009004 (short legs of Pythagorean triangles). Mathlib has the Pythagorean triple classification (Mathlib/NumberTheory/PythagoreanTriples.lean) but not this Heronian statement. I found no source that addresses A229159's conjecture directly; it is resolved immediately by the classical formula.", + "date": "2026-10-18" + }, + { + "id": "OEIS-frontier/A242396", + "slug": "oeis-a242396", + "title": "Stephan's conjectured g.f. for A242396 is false (first failure at n = 97)", + "area": "Discrete geometry", + "source": "OEIS A242396", + "source_url": "https://oeis.org/A242396", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A242396.lean", + "decl": "Math0.Statements.A242396.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-refutes", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A242396.lean", + "our_decl": "Math0.Frontier.A242396.result", + "summary": "Let a(n) be the number of rows (closed horizontal strips j*sqrt(3)/2 <= y <= (j+1)*sqrt(3)/2) of the unit equilateral-triangle tiling that meet the circle of radius n. Stephan's conjecture says that sum_{n>=1} a(n) x^n * (x^14 - x^13 - x + 1) = -2x^14 + 4x^13 + 2x^12 + 2x^11 + 2x^10 + 2x^9 + 2x^8 + 4x^7 + 2x^6 + 2x^5 + 2x^4 + 2x^3 + 2x^2 + 4x in Z[[x]]. We prove that this identity is false.", + "notes": "Conjecture as stated in OEIS: G.f., conjectured: (-2*x^14 + 4*x^13 + 2*x^12 + 2*x^11 + 2*x^10 + 2*x^9 + 2*x^8 + 4*x^7 + 2*x^6 + 2*x^5 + 2*x^4 + 2*x^3 + 2*x^2 + 4*x)/(x^14 - x^13 - x + 1). - _Ralf Stephan_, May 18 2014 (also: Asymptotics from g.f.: a(n) ~ 30/13 * n. - _Ralf Stephan_, May 18 2014)\n\nReferees: Sources checked:\n- The OEIS A242396 entry, from the local mirror and https://raw.githubusercontent.com/oeis/oeisdata/main/seq/A242/A242396.seq. Both show revision #18 (May 31, 2014), and the g.f. is still marked \"conjectured\" with no correction.\n- The cross-referenced entries A242394 and A242395.\n- A mirror search for the sequences ⌊2n/√3⌋ and 2⌊2n/√3⌋+2. The only match was A242396 itself.\n- Ralf Stephan's conjecture list at ark.in-berlin.de/conj.txt, which covers only the 2004–2005 list.\n- Four papers on proving OEIS conjectures, none of which mention A242396:\n - arXiv:2607.24832, \"Further proofs of conjectures from the OEIS\"\n - arXiv:2410.07237\n - S. Fried, JIS vol. 28 (fried15)\n - S. Fried, JIS vol. 29 (fried21)\n- General web searches (arXiv, MathOverflow/Math StackExchange, SeqFan). These found no counterexample or refutation of Stephan's g.f. for A242396.\n\nNo prior resolution was found.", + "date": "2026-10-21", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Elementary closed form a(n) = 2*floor(2n/sqrt(3)) + 2, which is what the entry's own Small Basic program computes, together with direct evaluation of a(83), a(84), a(96), a(97) and comparison of the x^97 coefficient after clearing the denominator (1-x)(1-x^13).", + "justification": "A row meets the circle exactly when its vertical extent overlaps [-n, n]. That gives a(n) = 2*floor(2n/sqrt(3)) + 2, which is also what the entry's own program computes for n up to 100. A rational g.f. with denominator (1-x)(1-x^13) would force a(n+13) - a(n) = 30 for every n. Because the slope 4/sqrt(3) is irrational, this cannot hold for all n, and a direct computation of four values gives the first failure at n = 97 (226 instead of 224). The refutation needs only this short argument and a finite check: Stephan's g.f. was a fit to the 61 listed terms, and no new idea was required. The counterexample is a real failure of the g.f. for the sequence as defined, not a degenerate or excluded case.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A249434", + "slug": "oeis-a249434", + "title": "A249151(k) = k exactly when k + 1 is prime (Karttunen's conjecture, A249434/A249151)", + "area": "Discrete geometry", + "source": "OEIS A249434", + "source_url": "https://oeis.org/A249434", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A249434.lean", + "decl": "Math0.Statements.A249434.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A249434.lean", + "our_decl": "Math0.Frontier.A249434.result", + "summary": "Let P(k) = prod_{j=0..k} C(k,j) be the product of row k of Pascal's triangle. For every k >= 0, k is the largest m with m! | P(k) if and only if k+1 is prime. Equivalently, A249151(k) = k iff k+1 is prime, so A006093 = {k : A249151(k) = k}.", + "notes": "Conjecture as stated in OEIS: %C A249434 It seems that A006093 gives all those k for which A249151(k) = k. If that is true, then this is a disjoint union of A006093 and A249429. (_Antti Karttunen_, Nov 02 2014; the same claim appears in A249151: 'A006093 seems to give all such k, that a(k) = k', and %Y A249434 'Subsequences: A006093 (conjectured)')\n\nReferees: OEIS A249434, A249151, A249431 (Antti Karttunen, Oct/Nov 2014; latest revisions Aug–Sep 2025 still say \"seems\"/\"conjectured\"; no %E proof record). J. C. Lagarias and H. Mehta, \"Products of binomial coefficients and unreduced Farey fractions\", arXiv:1409.4145 (Int. J. Number Theory 2016): formulas for ord_p of the row product G_n, including ord_p(G_n) = 0 iff n = a·p^k − 1 with 1 ≤ a ≤ p−1. This is a related ingredient, but the paper does not state or prove the conjecture. L. Du and J. C. Lagarias, arXiv:2006.15439, and Du–Lagarias–Yangjit, arXiv:2112.14422: related, but they do not address the conjecture. The conjecture is not in the AlphaProof Nexus / formal-conjectures auto_oeis set of 492 (Tsoukalas et al., arXiv:2605.22763) or in OEIS Open (Adamczewski, arXiv:2608.11941). No MathOverflow, Math StackExchange or SeqFan resolution was found.", + "date": "2026-10-25", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "A001142's product formula P(k) = prod_{j=1..k} j^(2j-1-k), giving P(k)/k! = prod_{j= s(u) whenever f(u) >= 1, then shows the excess is either negative or greater than e. All of this is about a page of elementary p-adic valuation bookkeeping (Legendre/Kummer-type sums) that someone fluent in such calculations would find quickly, so it is routine. The fact that the conjecture stayed open in the OEIS reflects lack of attention, not hidden difficulty.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A262957", + "slug": "oeis-a262957", + "title": "A262957: Israel's b(n), c(n) are coprime integers and a(n) = b(n)", + "area": "Number theory", + "source": "OEIS A262957", + "source_url": "https://oeis.org/A262957", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A262957.lean", + "decl": "Math0.Statements.A262957.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A262957.lean", + "our_decl": "Math0.Frontier.A262957.result", + "summary": "Let cf(n) be the value of 1 - 1/(2 + 1/(3 - 1/(4 + ... (n+1) + (-1)^(n+1)/1))), where the integers 1, ..., n+1 are used, the sign after k is (-1)^k, and the innermost tail is 1. Let a(n) be the numerator of cf(n) in lowest terms. Robert Israel defined b and c by b(1)=2, b(2)=3, c(1)=3, c(2)=5 and, for both, x(n+1) = (((-1)^n(n-1) + n(n+2)) x(n) - (1 + (-1)^n(n+1)) x(n-1)) / (n - (-1)^n). Claim (Israel's conjecture, OEIS A262957): for every n >= 1, b(n) and c(n) are integers with gcd(b(n), c(n)) = 1, and a(n) = b(n).", + "notes": "Conjecture as stated in OEIS: Conjecture: b(n) and c(n) are coprime for all n, so that a(n) = b(n). I have verified this for n <= 10000. - _Robert Israel_, Dec 22 2015 [b(1)=2, b(2)=3, c(1)=3, c(2)=5, b(n+1) = (((-1)^n*(n-1)+n*(n+2))*b(n) - (1+(-1)^n*(n+1))*b(n-1))/(n-(-1)^n), same recurrence for c]\n\nReferees: OEIS A262957 (local mirror, rev #80, Mar 2025): Robert Israel's comment of Dec 22 2015 states the conjecture, verified for n <= 10000, and it is still listed as open. Peter Bala, \"A note on A262957 and A263295\" (Dec 24 2015, linked from the OEIS entry): proves the simple continued fraction expansion [0;1,1,2,1,3,4,1,5,6,...] of the limit, but not Israel's recurrence or the coprimality. The cross-referenced entries A263295, A346590, A244279 and A244280 contain no proof. A262957 is absent from Tom Adamczewski, \"OEIS Open: How many conjectures can language models turn into theorems?\", arXiv:2608.11941 (2026), and from the epoch-research/LeanOpenProblems and LeanOpenProblems-results repositories. Web searches of arXiv, MathOverflow, Math StackExchange and SeqFan found no prior resolution. The proof uses the classical determinant identity for continued-fraction convergents (p_{k+1}q_k - p_k q_{k+1} = ±1).", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The classical fundamental recurrence and determinant identity for continued-fraction convergents, P_k Q_{k-1} - P_{k-1} Q_k = ±1 (e.g. Lorentzen-Waadeland), applied to the finite continued fraction 1 - 1/(2 + 1/(3 - ...)) whose last partial denominator is (n+1) ± 1.", + "justification": "The n-th iterate is a finite continued fraction with integer partial denominators and numerators ±1. Its value is therefore (P_n ± P_{n-1})/(Q_n ± Q_{n-1}) for the standard convergents, and that numerator and denominator are coprime by the textbook determinant identity. The only remaining step is to check that these sums satisfy Israel's recurrence. That is a polynomial identity in two cases by parity, which a computer-algebra system or ring normalisation settles mechanically. Spotting that Israel's b, c are just the convergent numerators and denominators is the one small insight, and it is the obvious guess, so the whole argument is well under a page of standard continued-fraction theory.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A265210", + "slug": "oeis-a265210", + "title": "Ternary digits of 2^n: column k has least period 2*3^(k-1) and balanced digits for k ≥ 2", + "area": "Discrete geometry", + "source": "OEIS A265210", + "source_url": "https://oeis.org/A265210", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A265210.lean", + "decl": "Math0.Statements.A265210.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A265210.lean", + "our_decl": "Math0.Frontier.A265210.result", + "summary": "Let T(n,k) be the k-th base-3 digit (from the least significant end) of 2^n, i.e. the digit at the place 3^(k-1). Column k consists of the rows n with 3^(k-1) ≤ 2^n. Then for every k ≥ 1: (i) p(k) = 2*3^(k-1) is a period of column k (T(n+p(k),k) = T(n,k) for every row n in the column), and no q with 0 < q < p(k) is a period; (ii) for k ≥ 2, in every block of p(k) consecutive rows m, ..., m+p(k)-1 (m in the column) the digits 0, 1 and 2 occur equally often (in fact exactly 2*3^(k-2) times each). This is Conjecture 1 of OEIS A265210 (L. Edson Jeffery, 2015).", + "notes": "Conjecture as stated in OEIS: Conjecture 1: The sequence in column k is periodic, with period p(k) = 2*3^(k-1) = A008776(k-1), k >= 1, and in which the numbers 0,1,2 appear with equal frequency, for each k>1. (_L. Edson Jeffery_, Dec 04 2015)\n\nReferees: E. de Faria and C. Tresser, \"On Sloane's persistence problem\", arXiv:1307.1188 (2013), Section 3.1, Lemma 3 and the paragraph after it. It shows 2^n mod 3^k has minimum period 2*3^(k-1) and that every allowable length-k ternary tail appears exactly once per period. This predates the Dec 2015 OEIS conjecture.\nJ. C. Lagarias, \"Ternary expansions of powers of 2\", J. London Math. Soc. 79 (2009) 562-588, arXiv:math/0512006, proof of Thm 1.4, eq. (3.3): 2 is a primitive root mod 3^k, so 2^n runs over all units mod 3^k.\nY. N. Aliyev, \"Digits of powers of 2 in ternary numeral system\", Notes Number Theory Discrete Math. 29(3) (2023) 474-485, Lemmas 3.2-3.3 and Observation I. It gives ord_{3^(n+1)} 2 = 2*3^n and shows the last-k-digit tails are periodic with period 2*3^(k-1) and run through all endings that don't end in 0.\nAlso standard textbook material (2 is a primitive root mod 3^k; e.g. LeVeque, Rosen) and the A008776 comment (J. Song, 2021).\nOEIS A265210 itself (rev. #18, Dec 2015) still lists the statement as a conjecture and has no proof note. The single-column least-period refinement is not stated explicitly in these sources, but it is a short elementary consequence of the same facts.", + "date": "2026-10-24" + }, + { + "id": "OEIS-frontier/A265649", + "slug": "oeis-a265649", + "title": "A265649: both of Werner Schulte's closed forms hold", + "area": "Discrete geometry", + "source": "OEIS A265649", + "source_url": "https://oeis.org/A265649", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A265649.lean", + "decl": "Math0.Statements.A265649.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A265649.lean", + "our_decl": "Math0.Frontier.A265649.result", + "summary": "Let T(0,0)=1, T(0,k)=0 for k>0, and T(n,k) = T(n-1,k-1) + (2n-1+k)·T(n-1,k) for n ≥ 1, with T(n,-1)=0. Then (i) for all 0 ≤ k ≤ n, T(n,k) = 2^(n-k)·(n-k)!·C(n,k)·Σ_{j=0}^{n-k} (-1/4)^j·C(2j+k,j)·C(n,j+k). (ii) For all n ≥ 1 and 0 ≤ k ≤ n, T(n,k) = (-1)^k·Σ_{j=0}^{n-1} A001497(n-1,j)·A021009(j+1,k). Here A001497(n,m) = (2n-m)!/(m!(n-m)!2^(n-m)) is the Bessel triangle and A021009(n,m) = (-1)^m·n!·C(n,m)/m! is the signed Laguerre triangle, both zero outside 0 ≤ m ≤ n.", + "notes": "Conjecture as stated in OEIS: %F A265649 Conjecture: T(n,k) = 2^(n-k)*(n-k)!*binomial(n,k)*(Sum_{j=0..n-k} (-1/4)^j* binomial(2*j+k,j)*binomial(n,j+k)). %F A265649 Conjecture: T(n,k) = (-1)^k*Sum_{j=0..n-1} A001497(n-1,j)*A021009(j+1,k). (_Werner Schulte_, Dec 11 2015)\n\nReferees: No explicit prior proof of either formula was found, and OEIS A265649 (rev. #40, Mar 2024) still marks both as \"Conjecture\". Both are immediate special cases of known results:\n(1) L. C. Hsu and P. J.-S. Shiue, \"A unified approach to generalized Stirling numbers\", Adv. Appl. Math. 20 (1998) 366-384: generalized Stirling numbers S(n,k;α,β,r), whose defining connection relation directly gives the product formula.\n(2) R. S. Maier, \"Boson Operator Ordering Identities from Generalized Stirling and Eulerian Numbers\", arXiv:2308.10332 (v4, 9 Feb 2024), linked from the A265649 entry. Eq. (18) gives the product formula S(α,γ;r1+r2) = S(α,β;r1)S(β,γ;r2). §5, p. 19 identifies A265649 = S_{n,k}(-2,1;1). Pp. 17-18 identify A001497 = b̂^(1) = S(-2,-1;1) and A021009 = L̂^(1) = S(-1,1;1) (signed), and Thm 5.1 (ii'), (iv') gives their closed forms. Eq. (72) states the r=0 analogue S(-2,1;0) = S(-2,-1;0)S(-1,1;0) of Conjecture 2. Thm 5.2(vi) gives a different, proved 2F1 closed form for S_{n,k}(-2,1;1).\nConjecture 2 = S(-2,-1;0)·S(-1,1;1), and Conjecture 1 = S(-2,2;2)·S(2,1;-1), reindexed; both checked numerically.\nAlso checked, with no A265649 resolution found: P. Barry, arXiv:1702.04011, Example 1 (displays the array as the exponential Riordan array [1/sqrt(1-2x), 1/sqrt(1-2x)-1], with no proof of the conjectures); S. Fried's OEIS-conjecture series (arXiv:2410.07237; JIS 28 (2025) Art. 25.4.3; JIS 29 (2026) Art. 26.1.8; arXiv:2607.24832); cross-referencing entries A370419, A347204 and A035342.", + "date": "2026-10-29" + }, + { + "id": "OEIS-frontier/A267486", + "slug": "oeis-a267486", + "title": "O'Sullivan's Gaussian-polynomial / Chebyshev representation conjecture (A267486), proved", + "area": "Discrete geometry", + "source": "OEIS A267486", + "source_url": "https://oeis.org/A267486", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A267486.lean", + "decl": "Math0.Statements.A267486.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A267486.lean", + "our_decl": "Math0.Frontier.A267486.result", + "summary": "Fix m, n ≥ 0 and put N = n + ⌊m/2⌋, so that 2n + m + 1 - (m mod 2) = 2N + 1. Let g = g(m;n) be mn for odd m and (2n+1)m/2 for even m. Let G(m;n,x) be the coefficient of t^m in (1+t) ∏_{k=1}^{N} (1 + t² + 2t T_k(x/2)), where T_k is the Chebyshev polynomial of the first kind. Write a(m;n,k) = [x^k] G(m;n,x). The claim is that deg_x G(m;n,x) ≤ g, and that the Gaussian polynomial satisfies [2N+1, m]_q = Σ_{k=0}^{g} a(m;n,k) (1+q²)^k q^{g-k}. The Gaussian polynomial is the one defined by the q-Pascal rule [M+1,m+1] = [M,m] + q^{m+1}[M,m+1].", + "notes": "Conjecture as stated in OEIS: %C A267486 Conjecture: More generally, the Gaussian polynomial [2*n+m+1-(m mod 2),m]_q = Sum_{k=0..g(m;n)} a(m;n,k)*(1+q^2)^k*q^(g(m;n)-k), for m >= 0, n >= 0, where g(m;n) = m*n if m is odd and (2*n+1)*m/2 if m is even, and ... a(m;n,k) = [x^k]G(m;n,x), G(m;n,x) = (d^m/dt^m)G(m;n,t,x)/m!|_{t=0}, G(m;n,t,x) = (1+t)*Product_{k=1..n+(m - m mod 2)/2}(1 + t^2 + 2*t*T(k,x/2)). (Stephen O'Sullivan, entry author, 2016)\n\nReferees: - OEIS A267486 (local mirror, revision #23, May 30 2026) and its siblings A267120, A267482, A267483, A267484, A267485 all state the same general conjecture with no recorded proof.\n- A267482: W. Lang (Oct 19 2019) proves the m=1 case only, settling T. Baruchel's 2018 conjecture R(n,x) = S(n,x) + S(n-1,x) via [2n+1]_q = q^n S(2n, q^(1/2)+q^(-1/2)).\n- S. O'Sullivan, 'A class of high-order Runge-Kutta-Chebyshev stability polynomials', J. Comput. Phys. 300 (2015) 665-678, arXiv:1507.08631, Eqs. (19)-(20): the representation [P,k]_q = Sum r_g q^(G_k/2-g)(1+q^2)^g, with generating function (1-t)·Prod_{k=1..N}(1+t^2-2tC_k), is stated without proof (P = 2N+1).\n- O'Sullivan's follow-ups arXiv:1702.03818 and arXiv:1712.03971 do not treat it.\n- The classical Cauchy/Rothe finite q-binomial theorem, Prod_{j=0..M-1}(1+q^j t) = Sum_m q^(C(m,2))[M,m]_q t^m, makes the general identity a direct corollary, though I found no source that writes out this deduction for the conjecture.\n- Not related to this conjecture: J.-C. Liu, arXiv:2509.06357 (Chebyshev expansions of MacMahon-type q-series).", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The Cauchy/Rothe finite q-binomial theorem, prod_{j=0}^{M-1}(1+q^j t) = sum_m q^{C(m,2)} [M,m]_q t^m, combined with the standard Chebyshev identity 2T_k((q+1/q)/2) = q^k + q^{-k}.", + "justification": "Put x = q + 1/q. Then 2T_k(x/2) = q^k + q^{-k}, so each factor 1 + t^2 + 2tT_k(x/2) splits as (1+tq^k)(1+tq^{-k}), and (1+t) times the product equals prod_{j=-N}^{N}(1+tq^j). The classical finite q-binomial theorem then gives the coefficient of t^m as q^{-g}[2N+1,m]_q, which is exactly the claimed expansion. The degree bound follows because [2N+1,m]_q has q-span 2g. This is the full proof, well under a page, built from two textbook facts. It settles the general conjecture as the author intended it, not only some degenerate reading.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A270668", + "slug": "oeis-a270668", + "title": "Mathar's generating function for column 3 of A270668 (domino tilings of (4k+1)x5 boards with central hole)", + "area": "Discrete geometry", + "source": "OEIS A270668", + "source_url": "https://oeis.org/A270668", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A270668.lean", + "decl": "Math0.Statements.A270668.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A270668.lean", + "our_decl": "Math0.Frontier.A270668.result", + "summary": "Let c_k = T(2k, 2) be the number of domino tilings of the (4k+1) x 5 board with its central cell removed (c_0 = 1 for the 1 x 5 strip with its middle cell removed). Then, in Q[[x]],\n sum_{k>=0} c_k x^k = (-1 - 4x + 543x^2 - 6238x^3 + 17032x^4 - 6238x^5 + 543x^6 - 4x^7 - x^8) / ((x-1)(x^2-7x+1)(x^2-23x+1)(x^4-161x^3+576x^2-161x+1)).\nThis is R. J. Mathar's 2016 conjectured g.f. for \"column 3\" of OEIS A270668. Equivalently, (sum c_k x^k) * den = num.", + "notes": "Conjecture as stated in OEIS: %F A270668 Conjectured g.f. for column 3: ( -1 -4*x +543*x^2 -6238*x^3 +17032*x^4 -6238*x^5 +543*x^6 -4*x^7 -x^8 ) / ( (x-1) *(x^2-7*x+1) *(x^2-23*x+1) *(x^4 -161*x^3 +576*x^2 -161*x +1) ). - _R. J. Mathar_, Mar 23 2016\n\nReferees: R. J. Mathar, \"A270668: Domino tilings with one monomer in the center\", PDF linked from OEIS A270668 (https://oeis.org/A270668/a270668.pdf), dated Apr 13 2016. It counts the 5 x (2m+1) floor with a central monomer by the transfer-matrix method: 50 states, nine centre configurations, and left/right Hadamard products of rational g.f.s in x = z^5. It appears to derive the column-3 g.f. that Mathar had conjectured on Mar 23 2016 in OEIS A270668 (still labelled \"Conjectured\" there). I saw its content only through search-engine extracts; the full PDF could not be downloaded. Related but not resolving: OEIS A143659 / M. Ciucu arXiv:0710.4500 (diagonal); A189003/A189006 (5xn corner-removed, same characteristic polynomial t^4-15t^3+32t^2-15t+1); A003775, A006238; B. E. Tenner, EJC 11(2) R17 (2005); Byun-Goddard arXiv:2502.05918; Stanley EC1 section 4.2.5 (Hadamard products of rational series). No prior Lean or other formalization found.", + "date": "2026-10-25" + }, + { + "id": "OEIS-frontier/A275815", + "slug": "oeis-a275815", + "title": "A275815: Jones's conjecture a(n) = 8(n-2)^2 for n >= 6 holds", + "area": "Discrete geometry", + "source": "OEIS A275815", + "source_url": "https://oeis.org/A275815", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A275815.lean", + "decl": "Math0.Statements.A275815.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A275815.lean", + "our_decl": "Math0.Frontier.A275815.result", + "summary": "For n >= 6, take a set S of squares on the n x n board and put a queen on each square of S. All queens have the same colour, so a queen may move along any of its 8 directions only to an empty square, and only through empty squares. Let M(S) be the total number of moves available to all the queens. Then the maximum of M(S) over all S is exactly 8(n-2)^2. In the formal version, a n = (board n).powerset.sup (totalMoves n), and the claim is that a n = 8 * (n - 2)^2 for every n >= 6.", + "notes": "Conjecture as stated in OEIS: Conjecture: a(n) = 8(n-2)^2 for n >= 6. - _Alec Jones_, Nov 16 2016\n\nReferees: The OEIS entry A275815 (#43, Jul 11 2021) still lists Jones's formula as a conjecture, with keyword \"more\". It records Wu's bounds 8(n-2)^2 <= a(n) <= 8n^2 (Nov 2016), a(6) from Branicky (Feb 2021) and a(7)-a(32) from Randell's MiniZinc runs (Jul 2021).\n\nJim Randell, \"Enigma 69: Maximum queen moves\", https://enigmaticcode.wordpress.com/2013/03/10/enigma-69-maximum-queen-moves/, has only computation: a 6x6 exhaustive check (2017), a MiniZinc model run up to 64x64 (2020) and solver comparisons (2025). It gives no general proof.\n\nThe cross-referenced entries A278211, A278212 and A278214 contain no proof. A278214's T(n, n^2-k) = 8k for k <= (n-2)^2 is only the easy per-empty-square bound.\n\nWeb searches of arXiv, MathOverflow, Math StackExchange, Puzzling, SeqFan and the chess-puzzle literature found no general proof or counterexample.\n\nThe one prior proof found is internal: math0's own results/oeis-a278212 (2026-10-24) already proves a(n) = 8(n-2)^2 for n >= 7 (Math0/Frontier/OEIS/A278212.lean). The present file adds the exact n=6 case (a(6) = 128, already known by computer) and states the full conjecture formally.\n\nShort proof (29 Oct 2026): the queen upper bound M <= 8(n-2)^2 also has a one-page charging proof for n >= 8, written up in results/oeis-a275815/short-proof.md and checked by two independent agents; it is not formalized in Lean.", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The charging proof in results/oeis-a275815/short-proof.md (n >= 8), plus the finite cases n = 6, 7; Wu's border placement gives the lower bound.", + "justification": "A short argument settles the general case, so no computer-found flow certificate is needed. Counting moves line by line gives an exact formula, which leaves only the empty border squares to be paid for. Each interior queen pays 2 along each line to an empty border square at most 2 squares away, and that covers every border square except a deficit of at most 1 at each corner, paid by a queen near the corner that kept its units. This is about a page of standard double counting and charging for n >= 10, and n = 6..9 are finite computations whose values are already in the entry's data. The only new part beyond math0's earlier A278212 result is n = 6, a finite check of a known value. A one-page charging proof of the queen bound for n >= 8 was found during this assessment and then verified by two independent checks (a hand re-derivation and an exhaustive and randomized computer search for counterexamples): see results/oeis-a275815/short-proof.md. It is not formalized in Lean.", + "challenged": true, + "revision": "", + "date": "2026-10-29" + } + }, + { + "id": "OEIS-frontier/A278212", + "slug": "oeis-a278212", + "title": "Kagey's conjecture for A278212: a(n) = floor(A275815(n)/2), via exact bishop and queen maxima from flow (LP-dual) certificates", + "area": "Discrete geometry", + "source": "OEIS A278212", + "source_url": "https://oeis.org/A278212", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A278212.lean", + "decl": "Math0.Statements.A278212.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A278212.lean", + "our_decl": "Math0.Frontier.A278212.result", + "summary": "For every n >= 1, let a(n) be the largest total number of moves that same-colored bishops can make on an n x n board, and queenMax(n) the same for queens. A piece can only move to an empty square, and every square it passes must be empty. Then a(n) = floor(queenMax(n)/2). More precisely, the proof shows the following. For bishops, a(4) = 20, a(5) = 38 and a(n) = 4(n-2)^2 for n >= 6. For queens, queenMax(4) is 40 or 41, queenMax(5) is 76 or 77, queenMax(6) is 128 or 129, and queenMax(n) = 8(n-2)^2 for n >= 7. That last formula also settles Alec Jones's conjecture on A275815 for n >= 7. The cases n <= 3 come from the listed values.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: a(n) = floor(A275815(n)/2). - _Peter Kagey_, Nov 24 2016\" (also A275815: \"Conjecture: a(n) = 8(n-2)^2 for n >= 6. - _Alec Jones_, Nov 16 2016\")\n\nReferees: I found no prior resolution, only computation and partial bounds:\n- OEIS A278212 (#36, Nov 19 2023): Kagey's 2016 conjecture is still listed as open. It records Chai Wah Wu's bounds 4(n-2)² ≤ a(n) ≤ 4n² (Nov 2016), Andrew Howroyd's a(n) ≤ 4(n-2)²+4 (Oct 2023), and terms a(7)–a(50) computed by Christian Sievers with an ILP (PuLP), after M. S. Branicky's a(6).\n- OEIS A275815 (#43, Jul 2021): Alec Jones's conjecture a(n)=8(n-2)² for n≥6 is still a conjecture, with keyword \"more\". It records Wu's bounds 8(n-2)² ≤ a(n) ≤ 8n² and terms a(7)–a(32) computed by Jim Randell with MiniZinc.\n- Jim Randell, Enigma 69 \"Maximum queen moves\" (enigmaticcode.wordpress.com, 2013, comments through 2025): the 6×6 case is verified by computer and the border formula is called \"presumed\". There is no general proof.\n- Related entries A278211, A278213 and A278214 contain no proof.\n- Searches of arXiv, MathOverflow, Math StackExchange, Puzzling, SeqFan and Google Scholar-style queries found no general proof or counterexample.\n\nShort proof (29 Oct 2026): the queen upper bound M <= 8(n-2)^2 also has a one-page charging proof for n >= 8, written up in results/oeis-a275815/short-proof.md and checked by two independent agents; it is not formalized in Lean.", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Howroyd's per-diagonal bound in the entry (with a short corner argument) for bishops; for queens, the one-page charging proof in results/oeis-a275815/short-proof.md (verified 29 Oct 2026, not formalized).", + "justification": "Earlier rated substantial, because the queen upper bound 8(n-2)^2 seemed to need the computer-found LP-dual certificates used in the Lean proof. That bound turns out to have a one-page elementary proof for n >= 8: count moves line by line, which leaves only the empty border squares to pay for, and let each interior queen pay 2 units along each of its lines to an empty border square at most 2 squares away. A one-page charging proof of the queen bound for n >= 8 was found while assessing A275815 and then verified by two independent checks (a hand re-derivation and an exhaustive and randomized computer search for counterexamples): see results/oeis-a275815/short-proof.md. It is not formalized in Lean. With it, the whole result is a short argument plus small finite cases, so it is now rated routine. The bishop half was always routine.", + "challenged": false, + "revision": "First rated substantial, by the assessor and again by a second, adversarial assessor (26 Oct 2026), because the queen bound seemed to need computer-found certificates. Revised to routine on 29 Oct 2026, after a one-page proof of that bound was found and independently verified (results/oeis-a275815/short-proof.md).", + "date": "2026-10-29" + } + }, + { + "id": "OEIS-frontier/A281000", + "slug": "oeis-a281000", + "title": "Schulte's conjectures on A281000, T(n,k) = C(2n+1,2k+1)·Cat(n-k): antidiagonal sums and matrix inverse", + "area": "Discrete geometry", + "source": "OEIS A281000", + "source_url": "https://oeis.org/A281000", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A281000.lean", + "decl": "Math0.Statements.A281000.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A281000.lean", + "our_decl": "Math0.Frontier.A281000.result", + "summary": "Let T(n,k) = C(2n+1,2k+1)·C(2n-2k,n-k)/(n+1-k) = C(2n+1,2k+1)·Cat(n-k) for 0 ≤ k ≤ n, and T(n,k) = 0 for k > n. Let N(n,j) = C(n-1,j-1)·C(n,j-1)/j be the Narayana numbers, s = A001003 the little Schröder numbers, with s(0) = 1 and s(n) = Σ_{j=1..n} 2^{j-1} N(n,j) for n ≥ 1, and b = A103365 the first column of the inverse of the lower-unitriangular Narayana matrix, so that Σ_{j=1..n} N(n,j) b(j) = [n = 1]. Then:\n(1) for every n ≥ 0, Σ_{k=0..⌊n/2⌋} T(n-k,k) = s(n+1);\n(2) (corrected reading) for every n ≥ 0, Σ_{k=0..n} T(n,k)(2k+1)Cat(k)·b(k+1) = 0^n;\n(3) for every N, the inverse over ℚ of the N×N leading block of T is the N×N leading block of U(n,k) = T(n,k)·b(n+1-k).", + "notes": "Conjecture as stated in OEIS: %F A281000 Conjectures: (1) Antidiagonal sums equal A001003(n+1); (2) Sum_{k=0..n} (-1)^k*T(n,k)*(2*k+1)*A000108(k)*A103365(k) = A000007(n); (3) Matrix inverse equals T(n,k)*A103365(n+1-k). (Werner Schulte, Jan 12 2017)\n\nReferees: No prior resolution found. Sources checked:\n- Local OEIS mirror: A281000 (#17, Nov 25 2018), A280580, A103365, A103364, A238390, A097610, A001003, A006318, A126120, A180874. No entry other than A281000 itself mentions A281000.\n- arXiv 2607.24832 and 2410.07237 (Sela Fried, proofs of OEIS conjectures); no mention.\n- arXiv 2608.11941 (Adamczewski, \"OEIS Open\") and the epoch-research/LeanOpenProblems-results repo; A281000 is not among its conjectures.\n- Web searches on arXiv, MathOverflow, the OEIS wiki and SeqFan; no hits.\n\nClosest prior material, which makes the result routine without explicitly resolving it:\n- T. Copeland, comment in A238390 (Jan 30 2016): the inverse pair C(n,k)·A126120(n−k) ↔ C(n,k)·m(n−k), with m(2j) = (−1)^j·A238390(j). Its odd–odd block gives conjecture (3).\n- V. Kotesovec, Mathematica in A103365 (2014), and P. D. Hanna's g.f. (2009): link A103365 to x/BesselJ(1,2x), so (−1)^j·A238390(j) = Cat(j)·A103365(j+1).\n- P. Bala, A103364 (2013): generalized Riordan array (1/E(y), y).\n- P. Barry, A097610 (Apr 2010): diagonal sums of the Motzkin triangle are the aerated large Schröder numbers. Restricting to an odd number of level steps gives half of that, which is conjecture (1).", + "date": "2026-10-25", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The scaling T(n,k) = (2n+1)!/(2k+1)! * c(n-k) with c(j) = 1/(j!(j+1)!), together with P. D. Hanna's g.f. in A103365 (A(x) = 1/B(x), B(x) = Sum x^n/[n!(n+1)!/2^n]), gives (3) at once; T. Copeland's inverse-pair comment in A238390 (Jan 30 2016) gives the same. (2) is the first column of (3). (1) follows from P. Barry's comment in A097610 (diagonal sums of the Motzkin triangle are the aerated large Schroeder numbers) plus a short g.f. parity argument, or from a Vandermonde/Narayana binomial identity.", + "justification": "The inverse in (3) is immediate once you see that T and the Narayana triangle are both diagonal conjugates of the same Toeplitz matrix built from c(j) = 1/(j!(j+1)!). Inverting that Toeplitz matrix is exactly the reciprocal power series that Hanna's g.f. in A103365 already records. Conjecture (2), read as its evidently intended column-0 case, is just the first column of T*T^{-1} = I. Conjecture (1) takes about a page, either with Vandermonde's identity and Cloitre's Narayana formula for A001003 or with the Motzkin bivariate g.f. that Barry's A097610 comment points to. The paper itself calls the result routine, and none of these steps needs a new idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A294512", + "slug": "oeis-a294512", + "title": "Lang's conjecture a(n) = A250400(n+1)/(n+1) for A294512 fails at n = 164", + "area": "Sequences and series", + "source": "OEIS A294512", + "source_url": "https://oeis.org/A294512", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A294512.lean", + "decl": "Math0.Statements.A294512.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-refutes", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A294512.lean", + "our_decl": "Math0.Frontier.A294512.result : ¬ Math0.Statements.A294512.statement", + "summary": "Let V(n) = sum_{k=0}^{n} 1/((k+1)(3k+1)) and let a(n) be the denominator of V(n) in lowest terms (OEIS A294512). Let A250400(m) be the numerator, in lowest terms, of the harmonic mean m / sum_{j=1}^{m} 1/(j(3j-2)) of the first m octagonal numbers. Lang's conjecture (A294512, FORMULA, 2017) says that A250400(n+1)/(n+1) = a(n) in Q for every n >= 0. This is false. The first failure is at n = 164, where A250400(165)/165 = a(164)/11.", + "notes": "Conjecture as stated in OEIS: A294512 (Denominators of partial sums of the reciprocals of octagonal numbers), FORMULA: \"a(n) = A250400(n+1)/(n+1), n >= 0. [conjecture].\" (entry by _Wolfdieter Lang_, Nov 01 2017). Companion A294513 (Lang, Nov 02 2017): \"a(n) = 2*A250327(n+1)/(n+1) [conjecture].\"\n\nReferees: OEIS A294512 (W. Lang, Nov 01 2017; history #1-#13, last edit Nov 12 2017, formula \"a(n) = A250400(n+1)/(n+1), n >= 0. [conjecture]\" still present). OEIS A250401 (C. Barker 2014; Lang comment Nov 01 2017 conditional on \"n+1 divides A250400(n+1)\", still present, history #1-#19). OEIS A250400 (C. Barker, Nov 21 2014, b-file n=1..1000, which contains A250400(165) = 15*a(164)). Sibling Lang conjectures in A294513, A294515 are unresolved there too. Not in google-deepmind/formal-conjectures (FormalConjectures/OEIS); not in Tsoukalas et al. / Epoch OEIS Open (arXiv 2608.11941; github.com/epoch-research/LeanOpenProblems-results; SeqFan thread \"Language models resolving OEIS conjectures\", Aug 2026). No SeqFan, MathOverflow, MSE or arXiv discussion found. Independent check: the failures for n < 3000 are exactly n = 164 (gcd 11) and n = 2413 (gcd 17).", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "A harmonic-mean identity that follows straight from the definitions in A294512/A250400: H(n+1) = (n+1)/V(n), so A250400(n+1) = (n+1)*a(n)/gcd(n+1, numerator V(n)). Barker's b-file for A250400 (m <= 1000) already lists A250400(165) = 15*a(164).", + "justification": "Since the harmonic mean is (n+1)/V(n), the conjecture holds exactly when n+1 is coprime to the numerator of V(n). Checking that condition with exact rational arithmetic finds the first failure at n = 164, where 11 divides both 165 and num V(164). The Lean proof confirms the identity 11*A250400(165) = 165*a(164) by kernel evaluation. The paper's hand argument for why 11 divides the numerator is a nice touch but not needed: the result is a direct finite search, and the relevant value was already in Barker's A250400 table. This is a genuine counterexample to the conjecture as intended, not a degenerate case.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A300789", + "slug": "oeis-a300789", + "title": "Domino-tileable Young diagrams are exactly the colour-balanced ones (A300789)", + "area": "Discrete geometry", + "source": "OEIS A300789", + "source_url": "https://oeis.org/A300789", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A300789.lean", + "decl": "Math0.Statements.A300789.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A300789.lean", + "our_decl": "Math0.Frontier.A300789.result", + "summary": "For every integer partition y = (y_1 >= y_2 >= ... >= y_m), the Young diagram of y can be tiled by dominoes if and only if the number of odd parts in even positions equals the number of odd parts in odd positions. So the Heinz numbers of domino-tileable partitions (A300789) are exactly the Heinz numbers of partitions whose odd parts appear as often in even as in odd positions. Equivalently, a(n) = b(n) for all n >= 1, where a(n) and b(n) are the n-th smallest Heinz numbers of the two classes.", + "notes": "Conjecture as stated in OEIS: %C A300789 This sequence is conjectured to be the Heinz numbers of integer partitions in which the odd parts appear as many times in even as in odd positions. (_Gus Wiseman_, Mar 12 2018)\n\nReferees: Already known, so the Lean proof is a first formalization, not a new result:\n- Classical 2-core / beta-number theory. I.G. Macdonald, Symmetric Functions and Hall Polynomials (2nd ed. 1995), Ch. I §1 Ex. 8, pp. 12-15: the r-core is empty iff the beta-numbers are equidistributed mod r. D.E. Littlewood, Modular representations of symmetric groups, Proc. Roy. Soc. A 209 (1951) 333-353.\n- Explicit statement of the parity form. S.P. Albion, \"Proof of some Littlewood identities conjectured by Lee, Rains and Warnaar\", arXiv:2108.12766, Lemma 2.1: empty 2-core (i.e. domino-tileable) iff {lambda_i + 2n - i} has n even and n odd elements, which is equivalent to the A300789 parity condition.\n- Black = white criterion for Young diagrams. Codeforces Round 609 editorial, problem 1268B/1269D \"Domino for Young\" (Dec 2019, codeforces.com/blog/entry/72358).\n- OEIS. A304710 (A. P. Heinz, May 2018) states the equivalence as fact: \"number of partitions of 2n where the number of odd parts in even positions differs from the number of odd parts in odd positions\". A000712 has Meeussen's 2013 comment and Karlsson's Dec 2025 comment. Heinz's Maple program and b-file for A300789 use the criterion.\n- The A300789 entry itself (rev #11, May 22 2018, local mirror = GitHub) still says \"conjectured\" and has no %E updates.", + "date": "2026-10-18" + }, + { + "id": "OEIS-frontier/A308107", + "slug": "oeis-a308107", + "title": "A308107: Barker's rational generating function and order-15 recurrence for the sum of smallest sides of scalene integer triangles", + "area": "Discrete geometry", + "source": "OEIS A308107", + "source_url": "https://oeis.org/A308107", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A308107.lean", + "decl": "Math0.Statements.A308107.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A308107.lean", + "our_decl": "Math0.Frontier.A308107.result", + "summary": "Let a(n) be the sum of the smallest side k over all integer triples k < i < j with j < k + i and k + i + j = n, i.e. over all scalene integer triangles of perimeter n. Then (1) sum_{n>=0} a(n) x^n = x^9 (2 + 2x + 2x^2 + x^3) / ((1-x)^4 (1+x)^3 (1+x^2)^2 (1+x+x^2)^2) as formal power series over Q, and (2) for every n > 15, a(n) = -a(n-1) + 2a(n-3) + 4a(n-4) + 2a(n-5) - a(n-6) - 5a(n-7) - 5a(n-8) - a(n-9) + 2a(n-10) + 4a(n-11) + 2a(n-12) - a(n-14) - a(n-15).", + "notes": "Conjecture as stated in OEIS: %F A308107 Conjectures from Colin Barker, May 13 2019: (Start) G.f.: x^9*(2 + 2*x + 2*x^2 + x^3) / ((1 - x)^4*(1 + x)^3*(1 + x^2)^2*(1 + x + x^2)^2). a(n) = -a(n-1) + 2*a(n-3) + ... - a(n-15) for n>15. (End)\n\nReferees: The OEIS entry A308107 (local mirror and current GitHub oeisdata, version #14 of Sep 12 2021) still marks Barker's May 13 2019 g.f. and recurrence as conjectures, with no proof note or %E edit. Its cross-reference A307686 and the related entries A308108, A308109 and A308158 also leave their Barker conjectures unproved. A005044 has Roger Cuculière's comment that scalene triangles of perimeter n+6 correspond to all triangles of perimeter n; this gives a reduction, not a proof. Sela Fried's proofs of OEIS conjectures (arXiv:2410.07237; JIS 28, 2025, Art. 25.4.3; JIS 29, 2026, Art. 26.1.8; arXiv:2607.24832) do not cover A308107 or any triangle sequence near it. Andrews–Paule–Riese (MacMahon's Partition Analysis IX, k-gon partitions), Hirschhorn on k-gon partitions, and arXiv:2308.01912 on Alcuin's sequence treat only the unweighted triangle count. I found no prior proof or counterexample.", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Standard parametrization of integer triangles (as in Alcuin's sequence A005044 / Andrews-Paule-Riese k-gon partitions): scalene triangles of perimeter n are (k,i,j)=(v+w, v+w+u, 2v+w+u) with u,v,w>=1 and 2u+4v+3w=n, so the g.f. is sum (v+w) x^(2u+4v+3w) = x^9(2-x^3-x^4)/((1-x^2)(1-x^3)^2(1-x^4)^2). Alternatively, Cuculiere's bijection in A005044 reduces it to A307686.", + "justification": "The proof writes each scalene integer triangle with three positive parameters in one linear relation, 2u+4v+3w=n, with smallest side v+w. Summing this linear weight over the parameters gives the rational generating function in a few lines by a standard MacMahon-type calculation. The order-15 recurrence then follows directly from the denominator. The paper itself calls the argument elementary and a routine computation. The Lean proof's chain of shift bijections is only formalization effort, not a new idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A308121", + "slug": "oeis-a308121", + "title": "A308121: for odd n > 1, row 2n is row n with its halves swapped", + "area": "Discrete geometry", + "source": "OEIS A308121", + "source_url": "https://oeis.org/A308121", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A308121.lean", + "decl": "Math0.Statements.A308121.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A308121.lean", + "our_decl": "Math0.Frontier.A308121.result", + "summary": "Let T(n,k) = b_n·k − a_n·r_k(n), where r_1(n) < ... < r_φ(n)(n) are the totatives of n and a_n/b_n is φ(n)/n in lowest terms (A076512/A109395). Row n is (T(n,1), ..., T(n,φ(n))). Claim (Charlie Neder's conjecture): for every odd n > 1, row n splits into two halves A, B of equal length with row n = A ++ B, and row 2n = B ++ A.", + "notes": "Conjecture as stated in OEIS: Conjecture: If n is odd, then row 2n can be obtained from row n by interchanging the first and second halves. (Charlie Neder, Jun 05 2019)\n\nReferees: - OEIS A308121 (Jamie Morken, May 13 2019; last edited Aug 05 2019, revision #47). Charlie Neder's conjecture of Jun 05 2019 is still marked \"Conjecture,\" with no %E or comment recording a proof.\n- The two entries that cite it, A307964 and A309497, do not resolve it.\n- The cross-referenced entries A109395, A076512, A038566 and A076511 contain nothing about the conjecture.\n- The classical background is phi(2n) = phi(n) for odd n and the bijection between totatives of n and of 2n; see arXiv 0907.1689, which treats a related map as a routine exercise.\n- A308121 is absent from google-deepmind/formal-conjectures, and so from the OEIS Open benchmark (arXiv 2608.11941).\n- Web searches (arXiv, MSE/MO, OEIS wiki) found no prior proof or counterexample. The SeqFan archive could not be reached (503 / connection reset).", + "date": "2026-10-25", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The classical fact that for odd n, phi(2n) = phi(n) and the totatives of 2n are the odd residues coprime to n. They are 2r-n for the totatives r > n/2, followed by n+2r for the totatives r < n/2. The symmetry r -> n-r (implicit in the entry's x+y = A109395(n) comment) shows that each half contains phi(n)/2 totatives.", + "justification": "For odd n, the totatives of 2n are 2r-n for the totatives r of n above n/2, followed by n+2r for those below n/2. The symmetry r -> n-r puts exactly half of the totatives on each side of n/2. The reduced form of phi(2n)/(2n) is (a_n/2)/b_n, and after substituting both facts the identity T(2n,k) = T(n,k±phi(n)/2) is two lines of algebra using a_n n = b_n phi(n). This is a short, standard elementary argument, about a page, and a competent number theorist would find it quickly. The manuscript itself calls the argument elementary. The length of the Lean proof reflects list bookkeeping, not mathematical depth.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A308222", + "slug": "oeis-a308222", + "title": "Perimeters of primitive Heronian isosceles triangles: A308222(n) = 2 · A096033(n + 2)", + "area": "Discrete geometry", + "source": "OEIS A308222", + "source_url": "https://oeis.org/A308222", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A308222.lean", + "decl": "Math0.Statements.A308222.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A308222.lean", + "our_decl": "Math0.Frontier.A308222.result", + "summary": "Let a(n) be the n-th smallest perimeter of a primitive Heronian isosceles triangle (integer sides with no common divisor, integer area, two sides equal). Let A096033(n) be the n-th smallest difference z - x, where x is a leg and z the hypotenuse of a primitive Pythagorean triangle. Then for every n ≥ 1, a(n) = 2 · A096033(n + 2).", + "notes": "Conjecture as stated in OEIS: %F a(n) = 2*A096033(n+2) (conjectured). (Peter Kagey, May 16 2019)\n\nReferees: Main prior resolution: Math StackExchange answer 3230072 by user \"George\", 2019-05-17 (https://math.stackexchange.com/a/3230072), answering Peter Kagey's question 3230019, \"Semiperimeter of isosceles Heronian triangles\". It is linked in the A308222 %H line. It derives that primitive isosceles Heronian triangles are (u^2+v^2, u^2+v^2, 2(u^2-v^2)) or (u^2+v^2, u^2+v^2, 4uv) with semiperimeters 2u^2 or (u+v)^2, citing J. R. Carlson, \"Determination of Heronian Triangles\", Fibonacci Quarterly 8 (1970) 499-506, Lemma 2.\n\nAlso: Wikipedia, \"Integer triangle\", section \"Isosceles Heronian triangles\" (the same parametrization: two copies of a Pythagorean triangle joined along a leg). The A096033 comment (Weimholt, 2010) says A096033 is the odd squares together with the numbers 2n^2.\n\nNo prior formalization found. OEIS A308222 (local mirror, #20, Aug 12 2022) still marks the formula \"(conjectured)\".", + "date": "2026-10-19" + }, + { + "id": "OEIS-frontier/A308359", + "slug": "oeis-a308359", + "title": "Fixed polyominoes with n cells and width n-2: T(n,n-2) = 8n^2 - 51n + 86 (A308359)", + "area": "Discrete geometry", + "source": "OEIS A308359", + "source_url": "https://oeis.org/A308359", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A308359.lean", + "decl": "Math0.Statements.A308359.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A308359.lean", + "our_decl": "Math0.Frontier.A308359.result", + "summary": "For every n >= 5, the number T(n, n-2) of fixed polyominoes with n cells whose convex hull has width n-2 equals 8n^2 - 51n + 86. A fixed polyomino is a finite edge-connected set of grid cells, taken up to translation. The statement file encodes it as the normalized set S in N x N that has min x = 0 and min y = 0. The height is unrestricted.", + "notes": "Conjecture as stated in OEIS: %F A308359 Conjecture: T(n,n-2) = 8*n^2 - 51*n + 86 for n >= 5. (Entry by _R. J. Mathar_, May 22 2019; last edit Oct 10 2022.)\n\nReferees: A. Goupil, H. Cloutier, F. Nouboud, \"Enumeration of inscribed polyominos\", FPSAC 2010, DMTCS proc. AN (2010) 737-748 (https://dmtcs.episciences.org/2808; hal-01186234; cited in OEIS A196593). Theorem 1 gives pmin(b,k) = 2k+2b-3bk-8+8*C(b+k-2,b-1), so pmin(w,3) = 4w^2-3w-2. Theorem 3 (k=2, b>2) gives pmin+1(b,2) = 4b^2-16b+18. Since T(n,n-2) = pmin(n-2,3) + pmin+1(n-2,2) = 8(n-2)^2-19(n-2)+16 = 8n^2-51n+86, Mathar's 2019 conjecture follows directly. The OEIS A308359 entry (last edited Oct 2022) still says \"Conjecture\" and has no proof note. Related but not resolving: L. Marin, \"Counting Polyominoes in a Rectangle b x h\", arXiv:2406.16413 (EPTCS 403, 2024), which covers fixed width and any height. I found no MathOverflow, Math StackExchange or SeqFan discussion explicitly proving the A308359 formula.", + "date": "2026-10-19" + }, + { + "id": "OEIS-frontier/A320099", + "slug": "oeis-a320099", + "title": "Kagey's order-10 recurrence for no-leaf subgraphs of the 5 × n grid holds", + "area": "Discrete geometry", + "source": "OEIS A320099", + "source_url": "https://oeis.org/A320099", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A320099.lean", + "decl": "Math0.Statements.A320099.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A320099.lean", + "our_decl": "Math0.Frontier.A320099.result", + "summary": "Let a(n) be the number of edge subsets S of the 5 × n grid graph (all vertices kept) such that no vertex has degree exactly 1 in S (OEIS A320099). Then for every n > 10, a(n) = 103 a(n-1) + 1063 a(n-2) - 1873 a(n-3) - 20274 a(n-4) + 44071 a(n-5) - 10365 a(n-6) - 20208 a(n-7) + 5959 a(n-8) + 2300 a(n-9) - 500 a(n-10). This is an identity of integers.", + "notes": "Conjecture as stated in OEIS: %F A320099 Conjecture: a(n) = 103*a(n-1) + 1063*a(n-2) - 1873*a(n-3) - 20274*a(n-4) + 44071*a(n-5) - 10365*a(n-6) - 20208*a(n-7) + 5959*a(n-8) + 2300*a(n-9) - 500*a(n-10) for n > 10. (_Peter Kagey_, Oct 05 2018)\n\nReferees: - OEIS A320099 (Peter Kagey, Oct 05 2018; latest revision #20, Jun 09 2019): the recurrence is still listed as \"Conjecture\", with no proof recorded.\n- Related entries with no proof for 5×n: A320097 (4×n; Kagey's conjecture and Colin Barker's empirical generating function, both unproved in OEIS), A301976 (3×n, Barker's conjectures), A320101 (the n×k table) and A093129 (2×n).\n- Prior formal work on a different sequence: the-omega-institute/trureturing issue #7458 and PR #7536 (Sep 13, 2026) give a Lean transfer-matrix proof of the 3×n recurrence (A301976). The repository has no issue or pull request for A320099 or A320097.\n- Peter Kagey's problem page https://peterkagey.com/problems/083/ covers only the 2×n case.\n- General transfer-matrix background: Raff, arXiv:0809.2551; Golin et al., ANALCO 2005.\n- No arXiv, MathOverflow, Math StackExchange or SeqFan source proving or refuting the order-10 recurrence for the 5×n grid was found.", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Standard column transfer-matrix method (e.g. Raff, arXiv:0809.2551). A 32 x 32 matrix T has rows and columns indexed by the sets of horizontal edges between adjacent columns, and a(n) = (T^n)[0,0]. The recurrence then reduces to a finite check: the row vector e_0 is annihilated by x*P(T), where P is Kagey's characteristic polynomial. A Cayley-Hamilton argument does the same job.", + "justification": "The proof writes a(n) as an entry of the n-th power of the standard 32 x 32 column transfer matrix, which is the textbook way to count local subgraph patterns on a strip of fixed width. The recurrence then follows from one finite linear identity among the first 11 rows of powers of T, checked by direct computation, and multiplying that identity by T^m extends it to every n. No new idea was needed: the method is standard, and once set up the conjecture is a finite computation. Most of the Lean work goes into formalizing the edge-set/column-data bijection, and that effort does not make the mathematics substantial.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A323695", + "slug": "oeis-a323695", + "title": "Odd terms of A323695 occur only at n = k(k+2)", + "area": "Sequences and series", + "source": "OEIS A323695", + "source_url": "https://oeis.org/A323695", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A323695.lean", + "decl": "Math0.Statements.A323695.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A323695.lean", + "our_decl": "Math0.Frontier.A323695.result", + "summary": "Let a(N) be the coefficient of x^N in Sum_{m>=0} x^m (1 - x^(m+1))^m / (1 + x^(m+1))^(m+1) (OEIS A323695, offset 0). If a(n) is odd, then n = k(k+2) for some natural number k. Equivalently, if a(n) is odd then n + 1 is a perfect square.", + "notes": "Conjecture as stated in OEIS: A323695 (G.f.: Sum_{n>=0} x^n (1 - x^(n+1))^n/(1 + x^(n+1))^(n+1)): \"Odd terms occur only at n = k*(k+2) for k >= 0 (conjecture);\" (_Paul D. Hanna_, Feb 23 2019). A324300 (G.f.: Sum_{n>=0} x^n (x^(n+1)+i)^n/(1 + i x^(n+1))^(n+1)): \"Odd terms occur only at n = k*(k+2) for k >= 0 (conjecture);\" (Hanna, Feb 21 2019).\n\nReferees: OEIS A323695 (Hanna, Feb 23 2019; still labeled \"(conjecture)\" at rev #24, Dec 15 2024; history checked) and its cross-references A323696, A324300 (same conjecture for an i-variant, also unproved), A323675 and A323680. Sibling results proved by others, which do not cover A323695: A325046, odd terms iff N = m(m+1), in S. Fried, \"Further proofs of conjectures from the OEIS\", arXiv:2607.24832 (Thm 50), also in google-deepmind/alphaproof-nexus-results; A323557, odd terms at r(r+1), in T. Adamczewski, \"OEIS Open\", arXiv:2608.11941 and AlphaProof Nexus (Tsoukalas et al.). A323695 is in neither google-deepmind/formal-conjectures nor epoch-research/LeanOpenProblems. It is not mentioned in Fried's arXiv:2410.07237 (JIS 25.4.3), JIS 26.1.8 or arXiv:2606.09913. MathOverflow, Math StackExchange and SeqFan searches found nothing.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Reduce the entry's own g.f. modulo 2. Since 1 - x^(m+1) = 1 + x^(m+1) mod 2, each summand becomes x^m/(1+x^(m+1)), and the series becomes the standard Lambert series Sum_m x^m/(1-x^(m+1)) = Sum_n d(n+1) x^n. The classical fact that d(N) is odd iff N is a perfect square finishes the proof.", + "justification": "The proof reduces the generating function modulo 2. There the numerator and denominator of each summand have the same base, so the m-th summand cancels down to x^m/(1+x^(m+1)). The sum is then the classical Lambert series for the divisor function, so a(n) is congruent mod 2 to d(n+1), and d(n+1) is odd exactly when n+1 is a square, by pairing each divisor d with N/d. This is a few lines of standard reasoning that a competent mathematician would find almost at once; the manuscript itself calls the result elementary. Unlike the sibling entries A323557 and A325046, nothing fails to cancel here, and the conjecture is the intended statement, not a degenerate reading of it.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A326407", + "slug": "oeis-a326407", + "title": "Prime-Minesweeper on the A060734 array: a(n) < 6, and a(n) = 5 only at n = 6", + "area": "Discrete geometry", + "source": "OEIS A326407", + "source_url": "https://oeis.org/A326407", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A326407.lean", + "decl": "Math0.Statements.A326407.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A326407.lean", + "our_decl": "Math0.Frontier.A326407.result", + "summary": "Write the positive integers into the square array A060734. The cell in row r, column c (both counted from 0) holds val(r,c) = (c+1)^2 - r if r <= c, and r^2 + 1 + c if r > c. Every positive integer appears in exactly one cell. Set a(n) = -1 if n is prime. Otherwise a(n) is the number of primes in the king-move neighbouring cells of n's cell. There are up to 8 such cells, 5 on row 0 or column 0, and 3 at the corner (0,0). Claim: for every n >= 1 we have a(n) < 6, and a(n) = 5 holds exactly when n = 6.", + "notes": "Conjecture as stated in OEIS: %C a(n) < 6 (conjectured). %C a(n) = 5 for n={6} (conjectured). %C Set of n such that a(n) = 4 is unbounded (conjectured). (Witold Tatkiewicz, Oct 02 2019)\n\nReferees: OEIS A326407 (Tatkiewicz, Oct 2019; last edit #27, Mar 20 2020) still lists \"a(n) < 6\" and \"a(n) = 5 for n={6}\" as conjectured, with no %E edits or proof links. OEIS A327893 (hexagonal spiral, De Vlieger 2019) records Tatkiewicz's parity argument bounding its terms by 4. That is the same technique applied to a different grid, not a proof for A326407. OEIS A326408 and A326409 state \"a(n) < 5\" without \"(conjectured)\" but give no proof. A326405, A326406, A326410, A060734, A136626 and A136627 contain nothing relevant. Web searches (arXiv, MathOverflow/Math StackExchange, SeqFan, general) found no prior proof or counterexample for A326407.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Checkerboard parity of the A060734 array: val(i,j) is congruent to i+j+1 mod 2. This is the same parity technique that the OEIS records in A327893 (Tatkiewicz's comment bounding the hexagonal-spiral Minesweeper terms by 4), applied to this grid.", + "justification": "The whole proof rests on one observation: in A060734 the entry in cell (i,j) has the parity of i+j+1. So for any interior cell, either its four orthogonal neighbours or its four diagonal neighbours hold even numbers, and only the cell of 2 can break this. That gives at most 4 primes everywhere except the cell of 6, which is next to 2. The edge cells and the few cells near 2 take a short parity check or direct evaluation. This is a standard argument of well under a page, and the OEIS already uses the same parity method for the sibling hexagonal entry A327893. The conjectures are settled as they were intended. The third conjecture, that a(n)=4 for infinitely many n, is not touched and remains open.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A326602", + "slug": "oeis-a326602", + "title": "A326602: a(n) is odd iff n is a square", + "area": "Sequences and series", + "source": "OEIS A326602", + "source_url": "https://oeis.org/A326602", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A326602.lean", + "decl": "Math0.Statements.A326602.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A326602.lean", + "our_decl": "Math0.Frontier.A326602.result", + "summary": "Let A(x) = Sum_{n>=0} (x^(2n-1)+1)^n x^n / (1+x^(2n+1))^(n+1) in Z[[x]] (the n=0 summand is 1/(1+x)), and let a(n) = [x^(2n)] A(x). Then for every n >= 0, a(n) is odd if and only if n is a perfect square (n = k^2 for some k >= 0, so 0 counts as a square).", + "notes": "Conjecture as stated in OEIS: A326602 (G.f.: Sum_{n>=0} (x^(2n-1)+1)^n x^n/(1+x^(2n+1))^(n+1), an even function; a(n) = [x^(2n)]): \"a(n) is odd iff n is square (conjecture).\" (_Paul D. Hanna_, Aug 08 2019). Same family: A323689 (Sum (x^n+i)^n/(1+i x^n)^(n+1)): \"Odd terms occur only at n = k^2 for k >= 0 (conjecture);\" (Hanna, Feb 14 2019); A323675 (Sum x^n (x^n+i)^n/(1+i x^(n+1))^(n+1)): \"It appears that odd terms occur only at n*(n+1)\" (Hanna, Feb 10 2019); A323690 (Sum (x^(n+1)+i)^n/(1+i x^n)^(n+1)): \"the first column consists of all the odd terms\" (triangle rows start at n(n+1)) (Hanna, Feb 13 2019).\n\nReferees: No prior resolution of A326602 found.\n- OEIS A326602 (local mirror and upstream oeisdata) is still at revision #19, Aug 11 2019, and still says \"a(n) is odd iff n is square (conjecture)\". No later edits or proof links.\n\nClosest prior work (same involution or parity method, different sequences):\n- A323557 (odd terms only at n(n+1)): proved by AlphaProof Nexus (github.com/google-deepmind/alphaproof-nexus-results, APNOutputs/OEIS/oeis_323557_conjecture_0.lean) and in T. Adamczewski, \"OEIS Open: How many conjectures can language models turn into theorems?\", arXiv:2608.11941, Appendix A. Also R. Stephan's comment of Jun 01 2026 on A323557.\n- A325046: S. Fried, \"Proof of a conjecture stated in A325046\" (OEIS a325046.pdf, 2025), and \"Further proofs of conjectures from the OEIS\", arXiv:2607.24832, Sec. 3.8 / Thm 50.\n\nNeither arXiv paper mentions A326602, and A326602 is absent from google-deepmind/formal-conjectures, so it was not in the Tsoukalas et al. or OEIS Open benchmark sets.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The involution/parity method already used for the cross-referenced sibling A323557: Ralf Stephan's comment of Jun 01 2026 in that entry, the AlphaProof Nexus Lean file, and Adamczewski, arXiv:2608.11941, Appendix A. Fried's proof for A325046 uses the same idea. The new proof also uses the standard fact that the central binomial coefficient C(2k,k) is even for k >= 1.", + "justification": "The proof expands each summand using the binomial theorem and the series for (1+y)^-(n+1). Modulo 2 it rewrites the coefficient of x^N as a sum of trinomial coefficients T(n,m,i) over triples with n+m+2nm = N+2i. Both the weight and the condition are symmetric in n and m, so the off-diagonal terms cancel in pairs. Each diagonal term is a multiple of a central binomial coefficient, so it is even except when i = n, which forces N = 2n^2. The whole argument fits in about a page, and it is a direct adaptation of the involution proof for the cross-referenced entry A323557, which that entry already cites; the manuscript itself calls it a fairly routine adaptation.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A328202", + "slug": "oeis-a328202", + "title": "The gcd of the interior binomial coefficients of row n equals Λ-exp(n)·Λ-exp(n−1) (A328202, Maiga's conjecture)", + "area": "Discrete geometry", + "source": "OEIS A328202", + "source_url": "https://oeis.org/A328202", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A328202.lean", + "decl": "Math0.Statements.A328202.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A328202.lean", + "our_decl": "Math0.Frontier.A328202.result", + "summary": "For every n ≥ 4, let G(n) = gcd{ C(n,k) : 2 ≤ k ≤ n−2 }. Let L(m) = p if m = p^t is a prime power (p prime, t ≥ 1), and L(m) = 1 otherwise (A014963, the exponential of the von Mangoldt function). Then G(n) = L(n)·L(n−1).", + "notes": "Conjecture as stated in OEIS: %F A328202 a(n) = A014963(n) * A014963(n - 1) (conjecture). - _Jon Maiga_, Oct 08 2019; also %C (From _Robert Israel_, Oct 16 2019): 'If p is a Fermat prime > 3, a(p)=2*p. If p is a Mersenne prime, a(p+1)=2*p. Conjecture: these are the only cases where a(n)>n.'\n\nReferees: G. Kaplan and D. Levy, \"GCD of truncated rows in Pascal's triangle\", Integers 4 (2004), #A14 (https://math.colgate.edu/~integers/e14/e14.pdf). Theorem 4 with Theorem 7 at t=1 (h(n,1)=1 for n>=4), or equivalently Theorem 9, gives g(n,2) = lcm(g(n-1,1), g(n,1)) = A014963(n)*A014963(n-1). This proves the A328202 formula in 2004, before the 2019 OEIS conjecture, and the paper's Table 2 matches the sequence data. Also relevant: H. Joris, C. Oestreicher and J. Steinig, \"The greatest common divisor of certain sets of binomial coefficients\", J. Number Theory 21 (1985) 101-119, which gives a general formula for gcd{C(n,k): r<=k<=s} (not checked directly). Background: Ram (1909) for the g(n,1) case. The OEIS entry (rev #46, Oct 10 2026) still labels the formula \"(conjecture)\" and does not cite these papers.", + "date": "2026-10-25" + }, + { + "id": "OEIS-frontier/A332010", + "slug": "oeis-a332010", + "title": "A332010: the average first letter of one-descent derangements has denominator 2^(n-2)", + "area": "Discrete geometry", + "source": "OEIS A332010", + "source_url": "https://oeis.org/A332010", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A332010.lean", + "decl": "Math0.Statements.A332010.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A332010.lean", + "our_decl": "Math0.Frontier.A332010.result : Math0.Statements.A332010.statement", + "summary": "For every n ≥ 2, take the derangements of {1, ..., n} (in one-line notation) that have exactly one descent. The average of their first letters, written in lowest terms, has denominator 2^(n-2). This is Kagey's conjecture T(n,1) = 2^(n-2) in OEIS A332010.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: T(n, 1) = 2^(n-2).\" (A332010, entry by Peter Kagey, Feb 04 2020)\n\nReferees: No prior resolution found.\n- OEIS A332010 and A332009 (Peter Kagey, Feb 04 2020; last edits Mar 30 2024) still state \"Conjecture: T(n,1) = 2^(n-2)\" and \"Conjecture: T(n,1) = A083329(n-1)\", with no proof recorded in comments or %E lines. I checked both the local mirror and raw.githubusercontent oeisdata.\n- Related known facts:\n - A219836 (Callan 2012; links to Fu–Lin–Zeng arXiv:1507.05184 and Alexandersson arXiv:2609.07325) gives a recurrence implying there are 2^(n-2) derangements with one descent. That is only the unreduced denominator.\n - M. Conger, arXiv math/0508112, proves E[π(1) | des = k] = k+1 over all permutations; this is the analogue for all permutations that the A332010 comment cites.\n - Kagey, arXiv:2112.05281, treats expected π(1) given k-cycles and does not address derangements by descents.\n - Eriksen–Freij–Wästlund, arXiv:0811.1925 / EJC 16 (2009) R32, and Han–Xin (2007) cover derangements with prescribed descent sets, with no first-letter averages.\n- Searches of Math StackExchange, arXiv and SeqFan found nothing. MathOverflow was not reachable through the search tool.", + "date": "2026-10-19", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Standard fact that a permutation with one descent is an increasing word on a set A followed by an increasing word on its complement (a Grassmannian permutation). A219836 already implies the count 2^(n-2).", + "justification": "A permutation with exactly one descent is sorted(A) followed by sorted(complement of A). Checking fixed points run by run shows it is a derangement exactly when 1 is not in A and n is in A. That gives 2^(n-2) such derangements, and their first letter is min A. Summing min A over these sets gives 3*2^(n-2) - 1, which is odd, so the reduced denominator is 2^(n-2). This is a half-page counting argument built on a textbook description of one-descent permutations, and the count itself already follows from A219836. It needs no new idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A333650", + "slug": "oeis-a333650", + "title": "Domino towers of height 2 and of height n-1, n-2, n-3 (A333650): all four Kagey/Luschny conjectures", + "area": "Discrete geometry", + "source": "OEIS A333650", + "source_url": "https://oeis.org/A333650", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A333650.lean", + "decl": "Math0.Statements.A333650.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A333650.lean", + "our_decl": "Math0.Frontier.A333650.result", + "summary": "Let T(n,k) count domino towers (brick-wall pattern: a brick of layer i has a left end ≡ i mod 2 in half-brick units; the bottom layer is a contiguous row of b ≥ 1 bricks, normalised to start at 0; each brick above the base overlaps a brick below by at least half a brick) with n bricks and k layers. Then:\n(1) for n > 1, T(n,2) = A000071(n+2) = F(n+2) - 1;\n(2) for n ≥ 2, T(n,n-1) = A339252(n-2), where a(0)=1, a(1)=4, a(2)=11, a(m+3)=4a(m+2)-4a(m+1);\n(3) for n ≥ 3, T(n,n-2) = A339254(n-3), where a(0..4)=1,7,24,70,193 and a(m+5)=6a(m+4)-12a(m+3)+8a(m+2);\n(4) for n ≥ 4, T(n,n-3) = A339029(n-4), the coefficients of (1+4x-20x^2+8x^3+33x^4-4x^5-33x^6)/(1-2x)^4.", + "notes": "Conjecture as stated in OEIS: %C A333650 Conjecture: For n > 1, T(n,2) = A000071(n+2). [entry author _Peter Kagey_, Mar 31 2020]; Conjecture: T(n,n-1) = A339252(n-2). - _Peter Kagey_, Nov 21 2020; Conjecture: T(n,n-2) = A339254(n-3). - _Peter Luschny_, Nov 29 2020; Conjecture: T(n,n-3) = A339029(n-4). - _Peter Luschny_, Dec 01 2020 (summarised by Luschny as T(2n+k, n+k) = d_n(n+k-1), k>=1, 0<=n<=3).\n\nReferees: OEIS A333650 (Kagey, Mar 2020; conjectures by Kagey Nov 21 2020 and Luschny Nov 29 / Dec 1 2020; still marked Conjecture as of revision #68, Aug 12 2022). A339494 (Luschny, Dec 2020): unproved remark that towers of height <=2 by base size form the binomial triangle C(k,n-k) (A030528), whose row sums are Fibonacci numbers, which is essentially the height-2 argument. A339495 assumes the height-2 formula. A339252, A339254, A339029: closed forms of the target sequences only. Definition of domino towers: A264746, A320314; Bona, Handbook of Enumerative Combinatorics, pp. 25-27; Gouyou-Beauchamps & Viennot 1988; Bétréma & Penaud 1993; Zeilberger arXiv:1208.2258. Related papers with no height enumeration: Ekhad & Zeilberger arXiv:1212.4105; T. M. Brown, Convex Domino Towers (JIS 2017, arXiv:1608.01562) and k-omino towers (arXiv:1608.01563); A. Haupt, S-omino towers (JIS 2021, arXiv:1810.10428); Ardila arXiv:1409.2562. Math StackExchange 2949131 and 3659431 (Kagey): symmetric towers and the 4^(n-1) variant only. No prior proof or counterexample of any of the four conjectures found.", + "date": "2026-10-19", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Height 2: a diagonal binomial sum, T(n,2) = sum_b C(b+1, n-b), which equals F(n+2)-1 by the standard Fibonacci identity (Luschny already noted the binomial-triangle link in A339494). Near-diagonals: the standard row-by-row transfer-matrix recursion on translation-normalized rows, compared with the closed forms 2^h times a polynomial already recorded in A339252, A339254 and A339029.", + "justification": "The height-2 conjecture comes down to one observation: the second-row bricks pick distinct positions among the b+1 positions above a base of b bricks. That gives a diagonal binomial sum, which is a textbook Fibonacci identity. For heights n-1, n-2 and n-3 the excess over one brick per row is at most 3. Then only 13 translation-normalized row states can occur, and a single brick over a single brick always has exactly 2 placements. So the count is a finite transfer-matrix recursion whose solutions are 2^h times polynomials of degree at most 3, checked by induction against a finite table. These are standard enumerative techniques that need no new idea, and once the state space is written down the proof is a finite computation matched to closed forms already recorded in the cross-referenced entries.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A334592", + "slug": "oeis-a334592", + "title": "Records of the XOR-triangle zero count A334592 are exactly the powers of two", + "area": "Discrete geometry", + "source": "OEIS A334592", + "source_url": "https://oeis.org/A334592", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A334592.lean", + "decl": "Math0.Statements.A334592.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A334592.lean", + "our_decl": "Math0.Frontier.A334592.result", + "summary": "Let a(n) be the number of zeros in the XOR-triangle whose top row is the binary expansion of n, with the most significant bit first. Each later row is the XOR of adjacent pairs in the row above, down to a row of length 1. Then n is a record position (n >= 1 and a(m) < a(n) for all 1 <= m < n) if and only if n = 2^k for some k >= 0.", + "notes": "Conjecture as stated in OEIS: %C A334592 Conjecture: Records occur at powers of two. (entry by _Peter Kagey_, May 07 2020)\n\nReferees: The key fact is published. H. Harborth, \"Solution of Steinhaus's problem with plus and minus signs\", J. Combin. Theory Ser. A 12 (1972) 253-259, is credited with observing that the minimum weight of a nonzero binary Steinhaus triangle of size n is n. J. M. Brunat and M. Maureso prove it in \"Small and large weights in Steinhaus triangles\" (arXiv:1707.06698, 2017), Theorem 4.4: for n >= 4, w1 = n and W1 = {1^n, 10^(n-1), 0^(n-1)1}. Their extended abstract is \"Extreme weights in Steinhaus triangles\", Electron. Notes Discrete Math. 54 (2016) 349-354. The A334592 record conjecture is an immediate corollary: a(n) <= T(L) - L = T(L-1) = a(2^(L-1)). The OEIS entries A334592 and A334593 (local mirror, still at #19 / #22 from May 2020) have no %E note marking the conjecture resolved. The MathOverflow thread q/359138 linked from the entry could not be fetched. Other sources seen: arXiv:1702.03236 (Chappelon, periodic balanced binary triangles) and arXiv:2508.05159 (balanced Steinhaus triangles, which mentions Chang 1983 on the smallest weights).", + "date": "2026-10-26" + }, + { + "id": "OEIS-frontier/A334595", + "slug": "oeis-a334595", + "title": "A334595: a(n) = 1 iff n is a power of two, and the records occur exactly at 1 and 2^k + 1", + "area": "Discrete geometry", + "source": "OEIS A334595", + "source_url": "https://oeis.org/A334595", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A334595.lean", + "decl": "Math0.Statements.A334595.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A334595.lean", + "our_decl": "Math0.Frontier.A334595.result", + "summary": "Let a(n) be the number obtained as follows. Write n in binary, most significant bit first. Build the XOR-triangle whose first row is that bit string; each later row is the pairwise XOR of adjacent entries of the row above. Read the right side of the triangle from the top-right corner downward, and interpret it as a binary numeral with the first entry as the most significant bit. Then:\n(1) For n >= 1, a(n) = 1 if and only if n is a power of two.\n(2) The record positions are exactly {1} together with {2^k + 1 : k >= 1}. Here n >= 1 is a record position when a(n) > a(m) for every 1 <= m < n.", + "notes": "Conjecture as stated in OEIS: Conjecture: Records occur at 1 and at 2^n + 1. / Conjecture: a(n) = 1 if and only if n is a power of two. (_Peter Kagey_, May 07 2020)\n\nReferees: I found no earlier proof or counterexample for either A334595 conjecture.\n- OEIS A334595 (Peter Kagey, May 2020): unchanged since revision #18 (May 09 2020), with both statements still labeled \"Conjecture\".\n- MathOverflow 359138, \"Number triangle\" (user DSM, with answers by YCor and Ilya Bogdanov): treats the boundary operator φ_k with φ_k^3 = 1 and counts rotationally symmetric triangles (A334556/A334596). It does not address records or a(n) = 1.\n- OEIS A334727 (Rémy Sigrist, 2020): states that the left-diagonal map is a self-inverse permutation.\n- Paul D. Hanna's XOR binomial transform entries (OEIS A099884, A099900, A099902): note that the transform is self-inverse.\nThese are the known ingredients that make the result elementary. Web searches of SeqFan, arXiv, MathOverflow and Math StackExchange found no resolution.", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The classical fact that the binomial transform over GF(2) (the Pascal matrix mod 2) is an involution. This is the self-inverse XOR binomial transform of A099884, and also the self-inverse permutation stated in the sibling entry A334727, which gives the left-diagonal version of A334595. Reading the right diagonal of a row is the same as reading the left diagonal of the reversed row.", + "justification": "Reverse the row, so that the right diagonal becomes the left diagonal. The digits of a(n) are then the GF(2) binomial transform of the bits of n. That transform is a classical involution, and A334727 already records it for this family. So a is a bijection on L-bit strings with a(n) < 2^L. Both conjectures then come down to working out three explicit preimages, of 1, of 2^L-1 and of 2^L-2, which takes about a page of elementary argument. No new idea was needed. The length of the Lean formalization does not make the mathematics substantial.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A334603", + "slug": "oeis-a334603", + "title": "The period of 1/11^n is 2 * 11^(n-1)", + "area": "Number theory", + "source": "OEIS A334603", + "source_url": "https://oeis.org/A334603", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A334603.lean", + "decl": "Math0.Statements.A334603.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A334603.lean", + "our_decl": "Math0.Frontier.A334603.result", + "summary": "For every n >= 1, the period of the decimal expansion of 1/11^n is 2 * 11^(n-1). Equivalently, the multiplicative order of 10 modulo 11^n is 2 * 11^(n-1). This is the FORMULA conjecture of OEIS A334603.", + "notes": "Conjecture as stated in OEIS: Comment: \"Conjecture proposed by the authors in References page 205: if p is a prime with gcd(p,30) = 1 and if the period of 1/p is m then the period of 1/p^n is m*p^(n-1).\" Formula: \"a(n) = 2 * 11^(n-1) [conjectured, see comments].\" (_Bernard Schott_, May 07 2020)\n\nReferees: The result is classical; no formalization of this specific statement was found.\n\nClassical theory: Gauss, Disquisitiones Arithmeticae (1801), on orders modulo p^n and on periods of decimal fractions with prime-power denominators (Arts. 85-89, 312-318). Standard elementary number theory texts (Ireland-Rosen; Niven-Zuckerman-Montgomery) state the lifting lemma: if p is odd and a^{ord_p a} = 1 + p*c with p ∤ c, then ord_{p^n}(a) = p^{n-1} * ord_p(a). Mathlib's ZMod.orderOf_one_add_mul_prime is that lemma for 1 + p*a.\n\nExplicit decimal-period statements:\n- K. A. Ross, \"Repeating Decimals: A Period Piece\", Mathematics Magazine 83 (2010), 33-45. If n is the largest exponent with period(1/p^n) = period(1/p), then period(1/p^a) = period(1/p) * p^(a-n) for a > n. For p = 11, period(1/121) = 22 ≠ 2, so n = 1.\n- S. Yao and A. Toyohara, \"The length of the repeating decimal\", arXiv:2507.01295 (2025), Theorem 2.1: l_{p^n} = p^{n-(m_p+1)} * l_p, where m_p = v_p((10^{l_p} - 1)/p). For p = 11 this gives m = v_11(9) = 0, so l_{11^n} = 2*11^(n-1).\n- Wikipedia, \"Repeating decimal\": the period of 1/p^2 is usually p*T_p, with the only known exceptions 3, 487 and 56598313.\n- OEIS A045616 (primes with 10^(p-1) ≡ 1 mod p^2) lists exactly these exceptions, and 11 is not among them.\n- John D. Cook, \"Reciprocals of prime powers\" (blog, 2021-09-28) checks 1/121 explicitly: period 22.\n\nIn the OEIS itself, A055272 has a Sep 2026 comment by E. Rodríguez proving the analogous 7^n case with the same lifting argument.\n\nSide note: the general conjecture of De Koninck and Mercier quoted in the A334603 comments (not the formalized statement) is false at p = 487.\n\nSources: https://arxiv.org/abs/2507.01295 ; https://en.wikipedia.org/wiki/Repeating_decimal ; https://www.johndcook.com/blog/2021/09/28/reciprocals-of-prime-powers/ ; https://oeis.org/A045616 (read from the local mirror)", + "date": "2026-10-18" + }, + { + "id": "OEIS-frontier/A335012", + "slug": "oeis-a335012", + "title": "Repunit residues: a(n) = n - 1 exactly for long period primes", + "area": "Number theory", + "source": "OEIS A335012", + "source_url": "https://oeis.org/A335012", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A335012.lean", + "decl": "Math0.Statements.A335012.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A335012.lean", + "our_decl": "Math0.Frontier.A335012.result", + "summary": "For n >= 1 let a(n) be the number of distinct values R_k mod n for 1 <= k <= n, where R_k = (10^k - 1)/9 is the k-th repunit. Then a(n) = n - 1 if and only if n is a long period prime (A006883): n is prime and either n = 2 or the multiplicative order of 10 modulo n is n - 1.", + "notes": "Conjecture as stated in OEIS: Conjecture: a(n) = n-1 if and only if n is a long period prime (A006883), that is, n is a prime and the decimal expansion of 1/n has period n-1. (entry by _Sen-Peng Eu_, May 19 2020)\n\nReferees: OEIS A335012 (Sen-Peng Eu, May 19 2020): the current revision #31 (Mar 12 2026) still lists this as a conjecture, with no %E line recording a resolution. In the same entry, Robert Israel's comment (Jun 25 2020) gives a(n) = A084680(n), the order of 10 mod n, when gcd(n,30) = 1. That implicitly settles the coprime-to-30 case but not n divisible by 2, 3 or 5. Cross-references: A006883 (long period primes, including 2) and A084680; neither mentions a proof. Background only: https://en.wikipedia.org/wiki/Repunit (pigeonhole argument that some repunit is a multiple of n; R_k ≡ k mod 3), https://en.wikipedia.org/wiki/Full_reptend_prime, https://mathworld.wolfram.com/FullReptendPrime.html. Web searches of arXiv, MathOverflow, Math StackExchange, SeqFan and the Google index found no earlier proof or counterexample.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Robert Israel's comment in A335012 itself, a(n) = A084680(n) (the order of 10 mod n) when gcd(n,30)=1, together with ord_n(10) <= phi(n) <= n-1 (equality forcing n prime), and the standard congruence R_k ≡ k (mod 3).", + "justification": "The proof is an elementary argument of about a page. If n is even or a multiple of 5, every repunit is odd, or is 1 mod 5, so too few residues are hit. For gcd(n,10)=1 the residues are purely periodic with period L = min{k : n | R_k}. When 3 does not divide n, L = ord_n(10) <= phi(n), and L = n-1 forces n to be prime. When 3 divides n, R_k ≡ k (mod 3) forces 3 | L, while n-1 ≡ 2 (mod 3). The main case, gcd(n,30)=1, is essentially Israel's comment in the entry, and the cases of multiples of 2, 3 and 5 are quick standard observations, so a competent number theorist would find the whole proof quickly.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A338885", + "slug": "oeis-a338885", + "title": "A338885: the smallest number in row 655 is 104, not A228286(655) = 115", + "area": "Discrete geometry", + "source": "OEIS A338885", + "source_url": "https://oeis.org/A338885", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A338885.lean", + "decl": "Math0.Statements.A338885.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-refutes", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A338885.lean", + "our_decl": "Math0.Frontier.A338885.result : ¬ Math0.Statements.A338885.statement", + "summary": "Kagey's conjecture in OEIS A338885 says that for every n ≥ 2, the smallest k for which a diagonal lattice rectangle (integer vertices, no side parallel to the x-axis) lies in the n X k box [0,n]×[0,k] and touches all four of its sides is A228286(n) = min{x + y*z : x, y, z ≥ 1, x*y + z = n}. This is false. For n = 655, the value k = 104 is in the row, but A228286(655) = 115 ≥ 105. So A228286(655) is not the least element of row 655.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: The smallest number in the n-th row is A228286(n).\" (entry by _Peter Kagey_, Nov 14 2020; a second conjecture in the same entry, \"The largest number in the n-th row is A033638(n)\", is true; see approach)\n\nReferees: I found no prior resolution.\n- OEIS A338885 (Kagey, Nov 14 2020): I checked both the local mirror and the latest raw oeisdata version (rev #22, Sep 11 2021). The conjecture is still listed, with no counterexample noted, and the b-file covers only rows 2..101.\n- Cross-references (local mirror): A228286, A228287, A228288, A338886, A338887, A033638, A085582, A113751. None of them mentions a resolution.\n- Code Golf SE question 213754 \"Rectangles in rectangles\", read via the Stack Exchange API: neither the answers nor the comments mention the conjecture.\n- Web searches (OEIS/A338885, Kagey, SeqFan, the min x+yz / ab+cd formulations, ARML 2013) turned up nothing relevant.\n- Independent computation: n = 655 is the smallest counterexample (row min 104 vs A228286 = 115). Further counterexamples are at n = 845, 909 and 1019 for n <= 1200.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Finite computer search, using the elementary parametrization that k is in row n iff n = a+b, k = c+d and ab = cd for positive a, b, c, d (the explicit rectangle with vertices (4,0),(655,42),(651,104),(0,62); 4*651 = 42*62 = 2604)", + "justification": "The conjecture is refuted by one counterexample, n = 655, found by a direct search. The row minimum there is 104, from an explicit lattice rectangle, while A228286(655) = 115; the lower bound is a finite check over about 2400 pairs (x, y). The only setup is the observation that the side vectors' coordinates satisfy a+b = n, c+d = k and ab = cd, which takes a few lines, and after that the search is mechanical (I reproduced it independently: counterexamples at n = 655, 845, 909 and 1019 below 1100). The counterexample is an ordinary row of the triangle and falls within the conjecture's intended meaning, so the result is not literal-only, but no new mathematical idea was needed.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A341761", + "slug": "oeis-a341761", + "title": "The subword complexity polynomial S(n,x) has leading coefficient n(n+1)/2 (A341761, Guo's conjecture)", + "area": "Discrete geometry", + "source": "OEIS A341761", + "source_url": "https://oeis.org/A341761", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A341761.lean", + "decl": "Math0.Statements.A341761.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A341761.lean", + "our_decl": "Math0.Frontier.A341761.result", + "summary": "For a word w, complexity(w) is the number of distinct nonempty factors (contiguous subwords) of w. Let S(n,x) be the sum of complexity(w) over all x^n words w of length n on an alphabet of x letters. For every n >= 0 there is a polynomial P in Q[X] with P(x) = S(n,x) for every natural number x, and the coefficient of x^n in P is n(n+1)/2.", + "notes": "Conjecture as stated in OEIS: Conjecture: the coefficient of x^n in S(n,x) is n*(n+1)/2. (Shiyao Guo, entry author, Feb 19 2021)\n\nReferees: OEIS A341761 (Shiyao Guo, 2021; still labelled \"Conjecture\" in rev #33, Mar 2024), cross-referenced with OEIS A340885. Shiyao Guo (Mivik), \"On the Expected Subword Complexity of Random Words\", https://mivik.moe/2021/research/expected-subword-complexity-en/, and the Chinese version https://mivik.moe/2021/research/expected-subword-complexity/ (updated 2026-03-26, still calls it an unproven conjecture). Related work that does not settle it: S. Janson, S. Lonardi, W. Szpankowski, \"On average sequence complexity\", TCS 326 (2004); I. Gheorghiciuc, M. D. Ward, \"On correlation polynomials and subword complexity\", DMTCS Proc. AH (AofA 2007), https://dmtcs.episciences.org/3553; Ahmadi and Ward, \"Asymptotic Analysis of the kth Subword Complexity\" (Entropy, 2020); Ivanko (Trudy IMM UrO RAN, 2008). I found no prior proof.", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Standard grouping of words by equality pattern (set partition of positions), giving S(n,x) = sum over patterns p of c(p)·x(x-1)...(x-k(p)+1). This is the same falling-factorial reasoning behind Guo's own remark in his linked blog post that S(n,x) is a polynomial of degree at most n.", + "justification": "The proof groups words by which positions carry equal letters, so S(n,x) becomes a sum of c(p) times falling factorials of x, and only the pattern with all letters distinct reaches degree n. A word with n distinct letters has n(n+1)/2 distinct factors, which settles it. Put another way, once S(n,x) is known to be a polynomial of degree at most n (as Guo already noted), its leading coefficient is the limit of the expected complexity as x grows, and almost every word then has distinct letters. This is a standard argument of a few lines that a competent combinatorialist would find right away, and the paper itself calls it elementary. Proving the conjecture as stated is what the author intended, so the result is not literal-only.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A342645", + "slug": "oeis-a342645", + "title": "A342645: diagonals of the eventual Mahonian-column polynomials", + "area": "Discrete geometry", + "source": "OEIS A342645", + "source_url": "https://oeis.org/A342645", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A342645.lean", + "decl": "Math0.Statements.A342645.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A342645.lean", + "our_decl": "Math0.Frontier.A342645.result", + "summary": "For x ≥ n, the number M(x,n) of permutations of x letters with major index n is a polynomial P_n(x) of degree ≤ n. Let T(n,k) = n!·[x^k]P_n(x). The triangle is computed by Newton interpolation of M(x,n) at x = n,…,2n.\n\n(Diagonals) For every m ≥ 0 there is Q ∈ ℚ[X] with deg Q = 2m and leading coefficient |A290030(m)/A053657(m+1)| such that T(n,n−m) = Q(n) for every n ≥ m. Here A290030(m) is the x^m-coefficient of the numerator L·B_m^(x) of Nørlund's polynomial B_m^(x) = m![t^m](t/(e^t−1))^x, where L is the least common denominator of its coefficients. A053657(m+1) = ∏_p p^{Σ_k ⌊m/((p−1)p^k)⌋}.\n\n(Formulas) T(n,n) = 1; T(n,n−1) = (n²−3n)/2; T(n,n−2) = (3n⁴−22n³+21n²−2n)/24; T(n,n−3) = (n⁶−13n⁵+37n⁴+13n³−134n²+96n)/48. Each holds for every n at which the left side is an entry of the triangle.", + "notes": "Conjecture as stated in OEIS: %C A342645 Conjecture: For each m, T(n,n-m) is a polynomial of degree 2m whose leading coefficient is abs(A290030(m)/A053657(m+1)). %F Conjectures: T(n,n) = 1. T(n,n-1) = (-3n + n^2)/2. T(n,n-2) = (-2n + 21n^2 - 22n^3 + 3n^4)/24. T(n,n-3) = (96n - 134n^2 + 13n^3 + 37n^4 - 13n^5 + n^6)/48. (Peter Kagey, Mar 17 2021)\n\nReferees: The conjecture itself has no prior resolution that I found. OEIS A342645 (Kagey, Mar 17 2021; last edit #25, Aug 12 2022) still states both conjectures, and the local mirror equals upstream oeisdata. Known ingredients:\n(1) The column polynomial via Euler's pentagonal expansion: E. Netto, Lehrbuch der Combinatorik (p. 96); D. Knuth, TAOCP Vol. 3, Sec. 5.1.1; Mike Earnest, MSE answer https://math.stackexchange.com/a/4065913 (linked in the entry); also G. Hegedus, arXiv:1002.2054, Thm 1.4.\n(2) Stirling polynomials: c(N,N-k) is a polynomial of degree 2k with leading coefficient 1/(2^k k!) (C. Jordan, Calculus of Finite Differences; I. Gessel and R. Stanley, Stirling polynomials, JCTA 24 (1978)); s(n,n-k) = C(n-1,k) B_k^(n).\n(3) Denominators of Norlund polynomials: J.-L. Chabert, Integer-valued polynomials on prime numbers and logarithm power expansion, Eur. J. Combin. 28 (2007) 754-761; A. Adelberg, Discrete Math. 204 (1999), Cor. 3; F. Bencherif, Sur une propriete des polynomes de Norlund, Actes CIRM 2(2) (2010) 71-77, Lemma 1 (d_n B_n^(x) is primitive in Z[x], with d_n = M_n/n! = A001898(n) and M_n = A053657(n+1)). Together with the OEIS A053657 comment a(n) = (n-1)!*A001898(n-1) (Bala, citing Chabert-Cahen), this already gives |A290030(m)/A053657(m+1)| = 1/(2^m m!).\nNot found: any source combining these into the diagonal polynomiality of A342645 or its four FORMULA identities, on arXiv, OEIS, MSE search results, or SeqFan search results. MSE pages could not be fetched directly from this machine.", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The column formula P_n(x) = sum_j e_j C(x+n-j-1, n-j), with e_j the pentagonal-number coefficients of prod(1-q^i). It is in Mike Earnest's MSE answer linked from the entry and in Netto and Knuth (TAOCP 3, Sec. 5.1.1). The Stirling polynomial fact that c(N,N-r) is a polynomial of degree 2r with leading coefficient 1/(2^r r!) (Graham-Knuth-Patashnik (6.44), Jordan, Gessel-Stanley 1978). The A053657 comment citing Chabert-Cahen that (t/(e^t-1))^x = sum_n P(n,x) t^n/A053657(n+1) with P(n,x) primitive in Z[x]. With the leading x-coefficient (-1/2)^m/m! of [t^m](t/(e^t-1))^x, this gives |A290030(m)/A053657(m+1)| = 1/(2^m m!).", + "justification": "Expanding the known column polynomial into falling factorials gives T(n,k) = sum_j e_j n(n-1)...(n-j+1) c(n-j,k). The term j of T(n,n-m) then has degree 2m-j by the classical Stirling-polynomial fact, so the degree is 2m and the leading coefficient 1/(2^m m!) comes from j=0. Putting in e_0..e_3 = 1,-1,-1,0 and the closed forms of c(N,N-r) for r ≤ 3 gives the four formulas. Matching 1/(2^m m!) with |A290030(m)/A053657(m+1)| follows directly from the Chabert-Cahen primitivity statement recorded in A053657. The whole argument is about a page of standard material. The 2500-line Lean proof re-derives the Norlund denominators from von Staudt-Clausen and Adams' theorem, but that is formalization effort, not new mathematics.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A342992", + "slug": "oeis-a342992", + "title": "Every n not divisible by 5 has a multiple with only prime digits (A342992)", + "area": "Sequences and series", + "source": "OEIS A342992", + "source_url": "https://oeis.org/A342992", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A342992.lean", + "decl": "def statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A342992.lean", + "our_decl": "Math0.Frontier.A342992.result", + "summary": "For every integer n >= 1 with 5 not dividing n, there is some k such that k*n is positive and every decimal digit of k*n is prime (in {2,3,5,7}). Equivalently, a(n) > 0 for A342992 (Sariyar's conjecture).", + "notes": "Conjecture as stated in OEIS: \"Conjecture: a(n) > 0 for all n that are not divisible by 5.\" (A342992, entry by _Metin Sariyar_, Apr 13 2021. Corneth added that a(625k) = 0.)\n\nReferees: No prior explicit proof of the A342992 conjecture was found. The entry still lists it as a conjecture (#60, Apr 22 2021) with no later %E edits.\n\nClosest prior material:\n(1) OEIS A078239 (Murthy 2002; Robert Israel, Feb 2018). Comment: \"Besides multiples of 10, 625 and its odd multiples have a(n)=0\". Its Maple program implicitly assumes a prime-digit multiple exists for every n with 10∤n and 625∤n. This is an unproved assertion. A078250 (Howroyd, 2024) repeats the comment.\n(2) OEIS A053316 (Henry Bottomley, Mar 2000; formula corrected by Israel, 2019): an n-digit number with digits 2 and 3 that is divisible by 2^n. This is exactly the proof's block lemma. The digits-{1,2} version is A053312, the 1971 All-Union olympiad problem (cut-the-knot.org/arithmetic/DivisibilityFromSovietMO.shtml).\n(3) IMO Shortlist 1994 N7, \"wobbly numbers\" (prase.cz/kalva/short/soln/sh94n7.html): the same technique of combining a 2-power block with the coprime-to-10 part by repetition.\n(4) Galperin & Reid, \"Multiples Without Large Digits\", Amer. Math. Monthly 126 (2019), as cited by John D. Cook (johndcook.com/blog/2025/12/16/multiples-with-no-large-digits/), with the citation's page numbers disputed by a reader comment. It covers digits 1–5 and does not imply this result.\n(5) C. W. Wu, \"Pigeonholes and repunits\", Amer. Math. Monthly 121 (2014): the related {0,1} case.\n\nThe result is elementary and folklore-adjacent, but no source states or proves it for prime digits or for digits {2,3}.", + "date": "2026-10-20", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The classical block lemma (OEIS A053316, Bottomley 2000; a {2,3} variant of the 1971 All-Union Olympiad problem A053312): for every j there is a j-digit number with digits 2 and 3 that is divisible by 2^j. Combine it with Euler's theorem 10^phi(m) ≡ 1 (mod m) for m coprime to 10, and repeat the block m times, as in the IMO Shortlist 1994 N7 solution.", + "justification": "Write n = 2^e m with m odd and coprime to 10. Take a block of L = phi(m)(e+1) digits from {2,3} that is divisible by 2^L; this is the textbook digit-by-digit induction recorded in A053316. Concatenating m copies of the block gives a number divisible by both 2^e and m, by Euler's theorem. Both steps are standard olympiad techniques and the whole argument fits in well under a page. The work is not new mathematics; it is mainly noticing that these known pieces apply directly to Sariyar's conjecture.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A344710", + "slug": "oeis-a344710", + "title": "A344710: non-obtuse lattice triangles with sides >= sqrt(n) have |det| > (sqrt 3 / 2) n", + "area": "Discrete geometry", + "source": "OEIS A344710", + "source_url": "https://oeis.org/A344710", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A344710.lean", + "decl": "Math0.Statements.A344710.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A344710.lean", + "our_decl": "Math0.Frontier.A344710.result", + "summary": "For every n >= 1, let a(n) be the least value of |det(B-A, C-A)| (twice the area) over lattice triangles ABC in Z^2 that are non-degenerate and non-obtuse and have all three squared side lengths >= n. Then sqrt(3/4) * n < a(n). This is Waldmann's conjectured inequality in OEIS A344710.", + "notes": "Conjecture as stated in OEIS: Formula: \"a(n) > sqrt(3/4)*n (conjectured).\" Comment: \"Conjectured next terms (from the conjectured inequality a(n) > sqrt(3/4)*n) are a(50,...,64) ?= 45, 48, 48, 52, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56.\" (entry by _Jonathan F. Waldmann_, May 26 2021). A344845 has the same inequality a(n) > sqrt(3/4)*m (conjectured), by the same author, May 29 2021.\n\nReferees: A. Mazel, I. Stuhl, Y. Suhov, \"High-density hard-core model on Z^2 and norm equations in ring Z[...]\", arXiv:1909.11648 (v1 25 Sep 2019; v3 22 Jun 2023). Lemma 3.4.4, eq. (3.1): sqrt(3)D^2/2 < S(D) < sqrt(3)D^2/2 + sqrt(2)D. S(D) is twice the minimal area of non-obtuse Z^2-triangles with sides >= D, so A344710(n) = S(sqrt n). The paper calls the lower bound \"obvious\". D. Krachun, \"Triangles on Z^2 and sliding phenomenon\" / \"Extreme Gibbs measures for high-density hard-core model on Z^2\", arXiv:1912.07566 (Dec 2019 / Jun 2020). Definition 2.1 gives the same S(D) for all D > 0, and Theorem 2 gives S(D) = (sqrt3/2)D^2 + O(D^{4/5}). The underlying inequality is the classical one: a non-obtuse triangle with all sides >= D has area >= (sqrt3/4)D^2, since area = (1/2)ab sin C with the largest angle C in [60,90] degrees. Equality would need an equilateral lattice triangle, and Z^2 has none. OEIS A344710 and A344845 (local mirror and GitHub, revisions #84/#52 of Feb 2022) still list the inequality as conjectured.", + "date": "2026-10-18" + }, + { + "id": "OEIS-frontier/A348484", + "slug": "oeis-a348484", + "title": "A348484: no two squares two steps apart; the conjectured formula holds", + "area": "Discrete geometry", + "source": "OEIS A348484", + "source_url": "https://oeis.org/A348484", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A348484.lean", + "decl": "Math0.Statements.A348484.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A348484.lean", + "our_decl": "Math0.Frontier.A348484.result", + "summary": "For every n >= 1, let a(n) be the largest number of squares you can choose on an n x n board so that no two chosen squares are exactly two steps apart in the same row or in the same column. Then a(n) = n^2/2 if n ≡ 0 (mod 4), a(n) = (n^2+1)/2 if n is odd, and a(n) = n^2/2 + 2 if n ≡ 2 (mod 4). (This is Yang Hong's conjecture in OEIS A348484.)", + "notes": "Conjecture as stated in OEIS: %F A348484 Conjectures: a(n) = n^2/2 for n == 0 (mod 4). a(n) = (n^2 + 1)/2 for n == 1 or 3 (mod 4). a(n) = n^2/2 + 2 for n == 2 (mod 4). (Entry by _Yang Hong_, Oct 20 2021; last edit #33, Dec 06 2022.)\n\nReferees: OEIS A348484 (Yang Hong, Oct 20 2021; latest revision #33, Dec 06 2022) still marks the formulas as \"Conjectures\". R. J. Mathar's Dec 2022 comment gives a 2×2-block checkerboard construction. Its g.f. -x(1+2x-2x^2+2x^3+x^4)/((1+x)(1+x^2)(x-1)^3) matches the conjectured values, but he states it only as a lower bound. Cross-reference: A048716 (the 1-D row condition, k AND 4k = 0). I found no published or online proof of the upper bound on arXiv, Math StackExchange, MathOverflow, SeqFan or general web search. The result does follow directly from the standard fact that a grid graph P_a□P_b has independence number ⌈ab/2⌉, because the \"two apart\" graph is a disjoint union of four such grids.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The matching lower bound is already in the entry: R. J. Mathar's comment gives the 2x2-block checkerboard construction and a g.f. whose coefficients are the conjectured values. The upper bound follows from the standard fact that the grid graph P_r x P_s has independence number ceil(rs/2), which is proved by tiling it with dominoes plus at most one monomino. Split the cells by (i mod 2, j mod 2). The \"two steps apart\" graph is then a disjoint union of four grid graphs whose sides are ceil(n/2) or floor(n/2).", + "justification": "The proof needs two observations. First, split the cells by row and column parity, so the \"two apart\" graph becomes four ordinary grid graphs. Second, use the textbook fact that an r x s grid graph has independence number ceil(rs/2): a checkerboard gives the lower bound and a domino tiling with at most one monomino gives the upper bound. Adding up the four grids gives the conjectured values directly. The lower-bound construction was already in the entry as Mathar's comment, and the whole argument fits in well under a page. The manuscript itself calls the result elementary. Writing the pairing as an involution on the board is a convenience for the Lean proof, not a new mathematical idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A350499", + "slug": "oeis-a350499", + "title": "Kurkov's recursion computes the free cumulants (A350499)", + "area": "Discrete geometry", + "source": "OEIS A350499", + "source_url": "https://oeis.org/A350499", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A350499.lean", + "decl": "Math0.Statements.A350499.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A350499.lean", + "our_decl": "Math0.Frontier.A350499.result", + "summary": "Take indeterminate moments m_1, m_2, ... over Z, and set m_0 = 1. Let M(x) = x + m_1 x^2 + m_2 x^3 + ..., let W = M^<-1> be its compositional inverse, and let C(x) = x / W(x) = sum c_n x^n, so c_n are the free cumulants. Kurkov's array is defined by R(1,k) = m_k and, for n > 1, R(n,k) = R(n-1,k+1) - sum_{j=1}^{n-1} R(j,k) R(n-j,1). Claim: R(n,1) = c_n for every n >= 1, as an identity in Z[m_1, m_2, ...].", + "notes": "Conjecture as stated in OEIS: Conjecture: free cumulants in terms of the free moments are R(n,1) for n > 0 where R(n,k) = R(n-1,k+1) - Sum_{j=1..n-1} R(j,k)*R(n-j,1) for n > 1, k > 0 with R(1,k) = m_k for k > 0. - _Mikhail Kurkov_, Mar 30 2025\n\nReferees: The conjecture is an immediate special case of the free-cumulant \"products as arguments\" formula, using the identification R(n,k) = κ_n(a^k, a, …, a):\n- R. Speicher, \"Multiplicative functions on the lattice of non-crossing partitions and free convolution\", Math. Ann. 298 (1994) 611–628. This contains the case where one argument is a product.\n- B. Krawczyk and R. Speicher, \"Combinatorics of free cumulants\", J. Combin. Theory Ser. A 90 (2000) 267–292, arXiv:math/9905094, Theorem 2.2.\n- A. Nica and R. Speicher, Lectures on the Combinatorics of Free Probability, LMS Lecture Note Series 335, CUP 2006, Theorem 11.12.\n\nApplying the formula to κ_{n−1}(a^k·a, a, …, a) gives Kurkov's recursion directly.\n\nNo explicit prior proof of Kurkov's formulation was found. OEIS A350499 (%I #63, Apr 04 2025; same in the current oeisdata) still lists it as \"Conjecture … – Mikhail Kurkov, Mar 30 2025\". The related entries A134264 and A133437 and the entry's own links (Copeland's blog, MathOverflow 412573, Zhou arXiv:1405.5296) do not address it.", + "date": "2026-10-29" + }, + { + "id": "OEIS-frontier/A350557", + "slug": "oeis-a350557", + "title": "Signed A350557 is the matrix inverse of A350512, proved", + "area": "Discrete geometry", + "source": "OEIS A350557", + "source_url": "https://oeis.org/A350557", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A350557.lean", + "decl": "Math0.Statements.A350557.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A350557.lean", + "our_decl": "Math0.Frontier.A350557.result", + "summary": "Let T be the A350557 triangle: T(n,0) = (2n)!/(2^n n!) = (2n-1)!!, and for 1 ≤ k ≤ n, T(n,k) = (2n-1)!! · Σ_{i=k}^{n} C(i-1,k-1)/(2i-1)!!. Set T(n,k) = 0 for k > n. Let L be the A350512 triangle: L(n,0) = 1, and for 1 ≤ k ≤ n, L(n,k) = C(n-1,k-1)(2k(n-k)+n)/k. Set L(n,k) = 0 for k > n. Define M(n,k) = (-1)^(n-k) T(n,k). Then M and L are inverse lower-triangular matrices: for all n, j ≥ 0, Σ_{k=0}^{n} L(n,k) M(k,j) = [n=j] and Σ_{k=0}^{n} M(n,k) L(k,j) = [n=j]. This is Werner Schulte's 2022 conjecture.", + "notes": "Conjecture as stated in OEIS: %F A350557 Conjecture: M(n,k) = (-1)^(n-k) * T(n,k) is matrix inverse of A350512. (Werner Schulte, entry author, Jan 2022)\n\nReferees: No prior resolution found. Sources checked:\n(1) OEIS A350557 and A350512, in both the local mirror and the current raw.githubusercontent oeisdata. The conjecture is still marked open, there are no %E lines, and neither entry has been edited since Jan 18 2022. Across the full mirror, no other entry cross-references A350557 or A350512. I also read A286286, A249349 and A103450.\n(2) google-deepmind/formal-conjectures (local checkout from Oct 2026): neither sequence is formalized.\n(3) google-deepmind/alphaproof-nexus-results (Tsoukalas et al., arXiv:2605.22763): A350557 is not among the APNOutputs/OEIS files, and the paper does not mention it.\n(4) Adamczewski, \"OEIS Open\" (arXiv:2608.11941): its appendix of resolved conjectures does not include A350557.\n(5) \"Further proofs of conjectures from the OEIS\" (arXiv:2607.24832) and S. Fried, \"Proofs of some conjectures from the OEIS\" (arXiv:2410.07237): A350557 is not mentioned in either.\n(6) Web searches for the A-numbers, the defining formulas, the column g.f. (1+2kx)x^k/(1-x)^(k+1), and Schulte together with the inverse: the only hit is the OEIS page, which still states the claim as a conjecture.\nThe result is mathematically elementary (a recurrence plus binomial inversion), but there is no published or recorded proof, so I classify it as a new result.", + "date": "2026-10-26", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The recurrence T(n,k) = C(n-1,k-1) + (2n-1)T(n-1,k), already listed as a formula in A350557, together with A350512's column g.f. (1+2kx)x^k/(1-x)^(k+1) (equivalently L(n+1,j) = (2j+1)C(n,j) + C(n,j-1)) and standard binomial (Pascal) inversion.", + "justification": "The proof brings in a bidiagonal matrix A with entries 1 and 2n-1. Then A*M = B, where B is a shifted signed Pascal matrix, and this is just the recurrence for T already stated in the A350557 entry. B*L = A follows from a one-line Pascal decomposition of A350512 plus ordinary binomial inversion. Cancelling the unitriangular A gives M*L = I, and L*M = I follows because the matrices are square. That is about a page of standard triangle and binomial-inversion manipulation, and it uses formulas already in the two entries. No new idea is needed, and the referees themselves call it elementary.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A350900", + "slug": "oeis-a350900", + "title": "OEIS A350900: Schulte's gcd-ratio double sum is a Dirichlet convolution", + "area": "Discrete geometry", + "source": "OEIS A350900", + "source_url": "https://oeis.org/A350900", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A350900.lean", + "decl": "Math0.Statements.A350900.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A350900.lean", + "our_decl": "Math0.Frontier.A350900.result", + "summary": "Let a(f; n) = Sum_{i=1..n} Sum_{k=1..n} f(gcd(i,n)/gcd(gcd(i,k),n)). Then: (1) for every complex arithmetic function f and every n > 0, a(f; n) = ((f·φ) * A057660)(n), where f·φ is the pointwise product with Euler's totient, * is Dirichlet convolution, and A057660(m) = Sum_{k=1..m} m/gcd(m,k). (2) If f is multiplicative, so is a(f; ·). (3) For n > 0, the row sum Sum_{k=1..n} T(n,k) of the A350900 triangle T(n,k) = Sum_{i=1..n} gcd(i,n)/gcd(gcd(i,k),n) equals a(id; n). (4) For n > 0, that row sum equals (A002618 * A057660)(n), where A002618(n) = n·φ(n).", + "notes": "Conjecture as stated in OEIS: Conjecture: Let f be an arbitrary arithmetic function. Define for n > 0 the sequence a(f; n) = Sum_{i=1..n, k=1..n} f(gcd(i,n)/gcd(gcd(i,k),n)); a(f; n) equals Dirichlet convolution of f(n)*A000010(n) and A057660(n); if f is multiplicative, then a(f; n) is multiplicative; row sums of this triangle use f(n) = n (see formula section). Also %F: Conjecture: Row sums equal Dirichlet convolution of A002618 and A057660. (Werner Schulte, Jan 21 2022)\n\nReferees: I did not query oeis.org; OEIS entries were read from the local mirror dated 2026-10-17.\n- A350900 (Werner Schulte, Jan 21 2022; last edit #13, May 24 2024): both claims are still labeled \"Conjecture\", and no %E line records a proof.\n- A373059 (Seiichi Manyama, May 21 2024; \"Row sums of A350900\"): states a(n) = Sum_{d|n} phi(n/d)(n/d) sigma_2(d^2)/sigma(d^2) = (A002618*A057660)(n) without proof or conjecture label. Amiram Eldar (May 27 2024) added the multiplicative formula and the Dirichlet g.f. zeta(s)zeta(s-2)^2/zeta(s-1)^2. This is a prior unproved assertion of part 4.\n- Related OEIS identities, also without proof: A350156 (Schulte, the analogous claim for f(n/gcd(i,k,n))); A371492, A371628, A373060, A373061, A372962, A372964, A372968 (Manyama, May 2024; sums of gcd(x_1,n)/gcd(x_1,...,x_k,n)).\n- A057660 (= Sum_{d|n} d*phi(d)).\n- Classical background: Cesaro's identity; L. Toth, \"A survey of gcd-sum functions\", JIS 13 (2010) 10.8.1; O. Bordelles, \"A Multidimensional Cesaro Type Identity and Applications\", JIS 18 (2015) 15.3.7; P. Bala, \"GCD sum theorems. Two Multivariable Cesaro Type Identities\" (A368743 attachment; I could not retrieve its text).\n- Checked and not relevant: S. Fried, \"Further proofs of conjectures from the OEIS\", arXiv:2607.24832 (A350900 is not among its sequences); D. Himane, NNTDM 31 (2025) (a different Schulte conjecture, about A006472).\nNo prior proof or counterexample of the A350900 conjecture was found.", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Cesàro's identity Sum_{k=1..n} F(gcd(k,n)) = Sum_{d|n} F(d) phi(n/d) (Tóth's gcd-sum survey, JIS 2010), together with the formula A057660(n) = Sum_{d|n} d*phi(d), which is already in cross-referenced entry A057660. Part (4) was already stated as a formula in A373059.", + "justification": "Set g = gcd(i,n). The summand depends on i only through g, and its dependence on k has period g. Apply Cesàro's identity once to group the i, use periodicity to collapse the k-sum to one period, apply Cesàro's identity again, and re-index the divisors. This gives a(f;n) = ((f*phi) * 1 * (id*phi))(n), and 1 * (id*phi) is A057660 by its own %F line. Multiplicativity then follows from standard closure properties, and the row-sum parts follow by exchanging the sums and taking f = id. The whole argument fits in under a page of standard gcd-sum manipulation, and the manuscript itself calls it routine.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A351743", + "slug": "oeis-a351743", + "title": "A351743: from n = 139 the sequence is affine in 42-blocks, which proves Sycamore's, Sigrist's and the A355149 conjectures", + "area": "Sequences and series", + "source": "OEIS A351743", + "source_url": "https://oeis.org/A351743", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A351743.lean", + "decl": "Math0.Statements.A351743.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A351743.lean", + "our_decl": "Math0.Frontier.A351743.result", + "summary": "Let a(1)=1 and let a(n+1) be the greatest divisor of s(n)=a(1)+...+a(n) that is prime to a(n) (OEIS A351743; s is A355149). Then:\n(1) a(n)=1 for infinitely many n, and a(n)=2 for infinitely many n (Sycamore).\n(2) a(2(n+21)-1) = a(2n-1) for all n >= 70 (Sigrist).\n(3) There is a 21-periodic integer sequence b with a(2(n+21)) = 3645 a(2n) + b(n) for all n >= 70 (Sigrist).\n(4) There is a 42-periodic integer sequence c with s(n+42) = 3645 s(n) + c(n) for all n >= 138 (A355149 conjecture).", + "notes": "Conjecture as stated in OEIS: A351743 (a(1)=1; a(n+1) = greatest divisor of s(n) prime to a(n), s = partial sums): \"Conjecture: a(n)=1 occurs infinitely many times, and therefore so does a(n)=2.\" (_David James Sycamore_, Jun 07 2022) and \"Conjectures from _Rémy Sigrist_, Jun 20 2022: (Start) - a(2*(n+21)-1) = a(2*n-1) for n >= 70, - a(2*(n+21)) = 3645*a(2*n) + b(n) for n >= 70 (where b is 21-periodic). (End)\". A355149 (partial sums of A351743): \"Conjecture: a(n + 42) = 3645*a(n) + b(n) for n >= 138 (where b is 42-periodic).\"\n\nReferees: OEIS A351743 (David James Sycamore, Jun 07 2022) states the conjecture that 1 and 2 occur infinitely often. Its formula section, from Rémy Sigrist on Jun 20 2022, adds the conjectures a(2(n+21)-1) = a(2n-1) and a(2(n+21)) = 3645 a(2n) + b(n), both for n >= 70. OEIS A355149 (De Vlieger, Sigrist and Sycamore, Jun 21 2022; last edit #11 Nov 17 2022) states the conjecture s(n+42) = 3645 s(n) + b(n) for n >= 138. Both entries still list these as open conjectures in the current oeisdata. The only other entry that cites them is A357735, which has nothing on them. I searched the full text of S. Fried's OEIS-conjecture papers (arXiv:2410.07237; J. Integer Seq. 28 (2025) 25.4.3; J. Integer Seq. 29 (2026) 26.1.8; arXiv:2607.24832) and none mentions these sequences. Searches of the web, arXiv, MathOverflow/MSE and SeqFan found no proof or counterexample.", + "date": "2026-10-20", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Sigrist's own conjectured formulas in A351743 (%F) and A355149 (%F), which already describe the block structure; the proof makes that structure an explicit affine ansatz in Y_m = (3645^m-1)/3644 and checks it by a finite computation.", + "justification": "The proof writes a and s on each 42-term block as affine functions of Y_m = (3645^m-1)/3644. The 42 coefficient rows come from the computed data, and Sigrist's conjectures already describe this shape. Each of the 42 steps of the recursion is then shown to hold for every value of the parameter, using two elementary gcd lemmas and a finite check of small divisibility and coprimality facts. Together with a direct computation of the first 139 terms, this proves all four conjectures. This is the standard way to certify an eventually periodic or affine pattern in a recursively defined sequence, and once the ansatz is set up it reduces to a finite computation. No new idea was needed, even though the conjectures had stayed open since 2022.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A354571", + "slug": "oeis-a354571", + "title": "Even and odd legs with odd prime factors ≡ 3 (mod 4): a(n)/n → π (A354571, A354570)", + "area": "Discrete geometry", + "source": "OEIS A354571", + "source_url": "https://oeis.org/A354571", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A354571.lean", + "decl": "Math0.Statements.A354571.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A354571.lean", + "our_decl": "Math0.Frontier.A354571.result", + "summary": "A354571 lists the even legs k of primitive Pythagorean triangles in increasing order, each repeated once per triangle. A leg is included when every odd prime factor of k is ≡ 3 (mod 4) and k has at least one odd prime factor. A354570 lists the odd legs k in the same way, for k whose prime factors are all ≡ 3 (mod 4). Selle's conjecture says that a(n)/n → π for A354571 and A354570(n)/n → π. The formal `statement` is the conjunction of these two limits, with each sequence read as the n-th term of the list where k appears #legTriangles(k) times.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: lim_{n->oo} a(n)/n = Pi. Also, lim_{n->oo} A354570(n)/n = Pi.\" (Lothar Selle, Jun 04 2022; same text in A354570)\n\nReferees: No prior resolution found.\n- OEIS A354571 and A354570 (Lothar Selle, Jun 2022; last edited Aug 2022) still state lim a(n)/n = Pi as a conjecture. Checked in the local mirror and in upstream raw.githubusercontent.com/oeis/oeisdata.\n- Selle, \"Kleines Handbuch Pythagoreische Zahlentripel\" (BoD 2022), ch. 2.3.10, is cited only for the equality of the two limits; I could not access the book.\n- Related unproved Selle conjectures appear in A120427, A120890 and A354569.\n- Web searches (arXiv, MathOverflow, Math.SE, SeqFan) found no proof or counterexample.\n- The underlying asymptotic is a standard consequence of Wiener–Ikehara/Delange applied to (1-2^-s)zeta(s)/L(s,chi4), using L(1,chi4) = pi/4. D. N. Lehmer (Amer. J. Math. 22, 1900) treats similar Pythagorean counting asymptotics, but not this restricted case.", + "date": "2026-10-20", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Classical count of primitive Pythagorean triangles with a given leg (2^(omega-1) coprime factorizations), combined with the Wiener–Ikehara / Delange Tauberian theorem applied to sum_{m odd, all p|m ≡ 3 mod 4} 2^omega(m) m^-s = (1-2^-s) zeta(s)/L(s,chi_4), with L(1,chi_4) = pi/4 and L(s,chi_4) ≠ 0 on Re s = 1.", + "justification": "The proof counts primitive triangles with a given leg using coprime factorizations, which gives the classical multiplicity 2^(omega-1). That reduces both counting functions to the summatory function of a multiplicative weight g, whose Dirichlet series is (1-2^-s)zeta(s)/L(s,chi_4). The Wiener–Ikehara (or Delange) theorem, together with L(1,chi_4) = pi/4 and the fact that L(s,chi_4) has no zeros on Re s = 1, then gives S(N) ~ 2N/pi. A short dyadic summation and the inversion from the counting function to the n-th term finish the proof. Each step is a textbook application of standard analytic number theory, and the manuscript itself calls it routine. Most of the work went into formalization: Wiener–Ikehara had to be proved from scratch in Lean. That effort does not make the mathematics substantial.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A355076", + "slug": "oeis-a355076", + "title": "Integer partial sums of the Calkin-Wilf ratios fusc(k)/fusc(k+1) at n = 2*4^k-1 and 2*4^k-2 (A355076)", + "area": "Number theory", + "source": "OEIS A355076", + "source_url": "https://oeis.org/A355076", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A355076.lean", + "decl": "Math0.Statements.A355076.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A355076.lean", + "our_decl": "Math0.Frontier.A355076.result", + "summary": "Let fusc be Stern's diatomic sequence (fusc 0 = 0, fusc 1 = 1, fusc(2n) = fusc n, fusc(2n+1) = fusc n + fusc(n+1)), and let a(n) be the denominator of s(n) = sum_{k=0}^{n} fusc(k)/fusc(k+1). Then for every k >= 0, a(n) = 1 when n = 2*4^k - 1 or n = 2*4^k - 2. In other words, s(n) is an integer for those n.", + "notes": "Conjecture as stated in OEIS: Conjecture: a(n) = 1 for n of the form 2*4^k - 1 or 2*4^k - 2 for some k >= 0. (entry by _Rémy Sigrist_, Jun 18 2022)\n\nReferees: - **Row-sum theorem (the key ingredient):** K. Siddharth Choudary and A. Satyanarayana Reddy, \"Calkin-Wilf tree\", arXiv:2003.13466 [math.CO], Mar 2020, accepted in Resonance. Theorem 1.1, Part 11: the sum of all elements in level n (root at level 1) is 3·2^{n−2} − 1/2, proved by induction.\n- **Earlier statement of the same fact:** OEIS A052940, comment by Carl Najafi (Jul 10 2011): 3·2^n − 1 is the numerator of the sum of terms at the n-th level of the Calkin-Wilf tree.\n- **Classical facts:** OEIS A002487 records a(2^k) = 1 and a(2^k − 1) = k (Adamchuk comment), and that a(n)/a(n+1) enumerates the rationals (Stern; N. Calkin and H. Wilf, \"Recounting the rationals\", Amer. Math. Monthly 107 (2000)).\n- **The conjecture itself:** OEIS A355076 (R. Sigrist, Jun 18 2022, rev. #11) is still listed as a conjecture with no %E edits. A355075 is the matching numerators entry. I found no explicit resolution anywhere; the result follows immediately from the Choudary–Reddy row sum plus the classical facts above.", + "date": "2026-10-18" + }, + { + "id": "OEIS-frontier/A355339", + "slug": "oeis-a355339", + "title": "A355339: the central even run of the knight-move triangle has length 1 iff n = 2^m - 2", + "area": "Discrete geometry", + "source": "OEIS A355339", + "source_url": "https://oeis.org/A355339", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A355339.lean", + "decl": "Math0.Statements.A355339.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A355339.lean", + "our_decl": "Math0.Frontier.A355339.result", + "summary": "Let T(n,k) be the knight-move triangle A355320. It is defined by T(0,0)=1, with zero entries outside |k| <= 2n, and T(n,k) = T(n-1,k-2) + T(n-1,k+2) + T(n-2,k-1) + T(n-2,k+1). Let a(n) be the length of the maximal block of consecutive even entries of row n that contains the centre k=0. It is 0 if T(n,0) is odd, and a(0)=0. Then for every n >= 0, a(n) = 1 if and only if n > 0 and n = 2^m - 2 for some m >= 0 (equivalently, n+2 = 2^{t+2} for some t >= 0).", + "notes": "Conjecture as stated in OEIS: %F Conjecture: a(n) = 1 iff n > 0 and n belongs to A000918. (Rémy Sigrist, Jun 29 2022)\n\nReferees: - OEIS A355339 (Rémy Sigrist, Jun 29 2022): the conjecture is in %F and is still unresolved at revision #10, with no %E extensions (checked in the local mirror and upstream oeisdata on GitHub).\n- OEIS A355320 (the triangle; its %F gives T(n,0)=A096609(n) and T(n,1)=A096610(n), but nothing on parity).\n- OEIS A096608–A096612 (Kimberling 2004, Catalan knight paths in the right half-plane), A096587, A361292, A000918, A002605: no parity results.\n- J.-L. Baril, N. Hassler, S. Kirgizov, J. L. Ramírez, \"Grand zigzag knight's paths\", arXiv:2402.04851 (ECA 2024): its only parity remark (Remark 3.2) concerns zigzag path counts being even when n ≡ k (mod 2), not this conjecture.\n- J.-L. Baril, J. L. Ramírez, \"Knight's paths towards Catalan numbers\", arXiv:2206.12087: nothing on parity.\n- Web searches of arXiv, MathOverflow/MSE, SeqFan and general sources found no prior proof or counterexample.\n- No formalization in google-deepmind formal-conjectures.", + "date": "2026-10-19", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The row-polynomial recurrence R_{n+1}=(1+X^4)R_n+(X^3+X^5)R_{n-1} given in A355320 (%F and PARI code), reduced mod 2 using 1+X^4=(1+X^2)^2, combined with Lucas's theorem for p=2.", + "justification": "By symmetry, the claim reduces to two parity facts: T(n,0) is even for n>=1, and T(n,1) is odd exactly when n+2 is a power of 2. Both come out of a standard technique. Reduce the row recurrence already stated in A355320 modulo 2. There 1+X^4=(1+X^2)^2 and X^3+X^5=X^3(1+X^2), so the recurrence has an explicit binomial closed form (a sum over compositions of n). The coefficient parities then follow from Lucas's theorem (equivalently, Kummer's carry criterion) by a short carry argument. The whole argument is about a page of elementary mod-2 polynomial algebra and binomial parity, the kind of thing a competent combinatorialist would find quickly. The conjecture most likely stayed open because the entry is obscure, not because it is hard.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A355360", + "slug": "oeis-a355360", + "title": "Columns 1 and 2 of the theta-series triangle A355360 are P(x)^3 and 2P(x)^6", + "area": "Discrete geometry", + "source": "OEIS A355360", + "source_url": "https://oeis.org/A355360", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A355360.lean", + "decl": "Math0.Statements.A355360.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A355360.lean", + "our_decl": "Math0.Frontier.A355360.result", + "summary": "Let A(x,y) = sum_m a_m(y) x^m be the series (a_m in Z[y]) computed by the entry's recursion a_0 = 1, a_{m+1} = y a_m - [x^{m+1}] F(a_0 + ... + a_m x^m). Here F(B) = sum_{n in Z} (-1)^n x^{n(n+1)/2} B^n = sum_{n>=0} (-1)^n x^{n(n+1)/2} (B^n - B^{-(n+1)}), and this recursion is the unique solution of x y A = F(A). Let T(n,k) = [x^n y^k] A. Then for every n >= 0:\n- T(n+1, 1) = A000716(n), the number of partitions of n into parts of 3 kinds;\n- T(n+2, 2) = 2 * A023005(n), twice the number of partitions of n into parts of 6 kinds.\nEquivalently, the y- and y^2-coefficients of A are x P^3 and 2 x^2 P^6, where P = prod_{k>=1} 1/(1-x^k). These are Hanna's conjectures (C.1) and (C.2).", + "notes": "Conjecture as stated in OEIS: %C A355360 Conjectures. (C.1) Column 1 equals A000716, the number of partitions into parts of 3 kinds. (C.2) Column 2 equals twice A023005, the number of partitions into parts of 6 kinds. (Paul D. Hanna, Jul 19 2022)\n\nReferees: OEIS A355360: Paul D. Hanna, Jul 19 2022. Last edit %I #7 Jul 20 2022, in both the local mirror and raw.githubusercontent oeisdata main. It has no %E lines and (C.1)/(C.2) are still labeled \"Conjectures.\"\n\nRelated entries:\n- A355350: same column conjectures, still open.\n- A355870: column-1 conjecture, still open.\n- A354650: asserts column 1 = A000716 for a different theta table, with no proof given. It cites arXiv:2609.32264 (LANTERN), which is about relation-mining and does not cover these entries.\n- A355361 through A355365: asymptotics only.\n\nNot covered in:\n- the epoch-research/LeanOpenProblems-results metadata and runs (arXiv:2608.11941; Tsoukalas et al., arXiv:2605.22763);\n- google-deepmind/formal-conjectures (FormalConjectures/OEIS/355360.lean returns 404);\n- S. Fried's arXiv:2410.07237, JIS 28 (2025) no. 4, JIS 29 (2026) Article 26.1.8, and arXiv:2607.24832 (that paper covers A355372, not A355360).\n\nWeb searches of MathOverflow, Math StackExchange, SeqFan and arXiv found no proof or counterexample. The underlying tool, Jacobi's identity prod (1-q^k)^3 = sum (-1)^n (2n+1) q^{n(n+1)/2}, is classical.", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The entry's own formula (3), x*y*A*P = prod_{n>=1}(1 - x^n*A)(1 - x^(n-1)/A) (Jacobi triple product), or equivalently Jacobi's classical identity prod(1-x^k)^3 = sum_{n>=0} (-1)^n (2n+1) x^{n(n+1)/2}", + "justification": "Put A = 1+u. Formula (3) of the entry turns into x*y*(1+u)^2 = u*G(1+u), where G(A) = prod(1-x^n)(1-x^n A)(1-x^n/A). G is invariant under A -> 1/A and G(1) = P^{-3}, so G(1+u) = P^{-3}(1 + O(u^2)). Comparing the y and y^2 coefficients then gives u = xyP^3 + 2(xyP^3)^2 + O(y^3). Pairing n with -1-n and applying Jacobi's cube identity gives the same few-line computation. The Lean proof is long only because it proves Jacobi's identity from scratch and checks the PARI-style recursion; that is formalization effort, not a new mathematical idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A356360", + "slug": "oeis-a356360", + "title": "A356360: the continued-fraction denominators are 1 or prime", + "area": "Number theory", + "source": "OEIS A356360", + "source_url": "https://oeis.org/A356360", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A356360.lean", + "decl": "Math0.Statements.A356360.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A356360.lean", + "our_decl": "Math0.Frontier.A356360.result", + "summary": "For n >= 3, let a(n) be the denominator, in lowest terms, of the continued fraction 1/(2 - 3/(3 - 4/(4 - ... ((n-1) - n/(n+1))))). Then every a(n) is 1 or a prime. This is the conjecture Mohammed Bouras stated in OEIS A356360 (2022).", + "notes": "Conjecture as stated in OEIS: A356360: \"Conjecture: The sequence contains only 1's and the primes.\" (_Mohammed Bouras_, Oct 15 2022). The same sentence appears in A369797 (Feb 2024), A370726 (Feb 2024) and A372763 ('Conjecture 1', May 2024). A372761: \"Conjecture 1: Except for 4, the sequence contains only 1's and the primes.\" A362086: \"Conjecture: Except for 9, every term of this sequence is either a prime or 1.\" A363482: \"Conjecture: Except for 49, every term of this sequence is either a prime or 1.\" (all by Bouras)\n\nReferees: OEIS A356360 (mirror 2026-10-17, rev #31 Aug 2024): still marked \"Conjecture\". It has an unproved comment \"Same as A128059(n), A145737(n-1), A097302(n-2) for n>5\", and its formula \"a(n)=2n-1 if prime else 1 (n != 5)\" is labeled \"From the conjecture\". M. Bouras, \"The Distribution Of Prime Numbers And The Continued Fractions\", Zenodo doi:10.5281/zenodo.7212512 (2022; also viXra 2209.0101): proves only the closed form (Thm 1.1) and states Conjecture 3.1, verified to n=10000. M. Bouras, \"A New Primes-Generating Sequence\", arXiv:2509.09745 (2025), Table 2 (k=1 row = A356360): observation only, no proof. Bouras slides, Zenodo 10992128: \"Conjecture 2\", no proof. AlphaProof Nexus results / formal-conjectures auto_oeis THEOREM_MAPPING and T. Adamczewski, \"OEIS Open\", arXiv:2608.11941: A356360 is not included; only the sibling A372761 Conj. 2 was resolved. Related but distinct: A356247 conjectures proved by B. Cloitre (2025, OEIS attachment). No prior proof or counterexample found.", + "date": "2026-10-20", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The closed form and gcd formula already in the entry, a(n) = (2n-1)/gcd(2n-1, A051403(n-2)+A051403(n-3)), proved as Theorem 1.1 of Bouras's linked paper. Combined with A051403(j) = (j+2)*A003422(j+1)/2, this reduces the question to the elementary fact that an odd composite 2m+3 with m >= 4 divides m!. The same denominator-of-factorial pattern appears in A145737 (Detlefs: a(n) = denominator(n!*3n(n+1)/(2(2n+1))) = 2n+1 if prime, else 1).", + "justification": "The gcd formula already in the entry gives a(n) | 2n-1 at once, so the prime case is immediate. The composite case needs only that an odd composite c = 2m+3 with m >= 4 divides m!, a textbook Wilson-style lemma with a short case split on whether c = p^2. Together with checking n = 3, 4, 5 directly, the whole argument fits in under a page and uses no new idea. The longer Lean development is formalization effort and does not make the mathematics deeper.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A357216", + "slug": "oeis-a357216", + "title": "Internal n-gons in a regular n-gon: triple points occur only for n = 3, 4, 6, and otherwise there are n k^2 + 1 regions (Shannon's A357216 conjecture)", + "area": "Discrete geometry", + "source": "OEIS A357216", + "source_url": "https://oeis.org/A357216", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A357216.lean", + "decl": "Math0.Statements.A357216.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A357216.lean", + "our_decl": "Math0.Frontier.A357216.result", + "summary": "Take the regular n-gon with vertices V_j = exp(2πij/n). Divide each side into k+1 equal parts. For m = 1..k, the m-th internal n-gon joins the m-th division points of consecutive sides. Its side (j, m-1) is the segment from the m-th division point of side j to the m-th division point of side j+1. The statement has two parts.\n(1) For n >= 3, some k gives a point lying on three distinct drawn sides if and only if n is 3, 4 or 6.\n(2) For n = 5 and for every n >= 7 and every k >= 0, the open polygon minus all n*k drawn sides has exactly n*k^2 + 1 connected components.", + "notes": "Conjecture as stated in OEIS: %C Conjecture: the only n-gons that contain non-simple intersections are the 3-gon (triangle), 4-gon (square), and 6-gon (hexagon). %F Conjectured formula for all columns for n >= 7: T(n,k) = n*k^2 + 1. %F Conjectured formula for all rows except for n = 3, 4, 6: T(n,k) = n*k^2 + 1. (Scott R. Shannon, Sep 18 2022; the same conjecture appears in A357235 (vertices n*k^2+n) and A357254 (edges 2n*k^2+n))\n\nReferees: I found no prior resolution. The OEIS entries A357216, A357235 and A357254 (Scott R. Shannon, Sep 2022, last revised Sep 21 2022, no %E lines) still list both claims as conjectures, in the local mirror and the current GitHub oeisdata. The related entries for the triangle (A356984, with Talmon Silver's classification for n = 3 only), the square (A357058) and the hexagon (A357196) give no general proof. arXiv API searches for \"A357216\" and \"internal n-gons\" returned nothing. Web searches covering MathOverflow, Math StackExchange, SeqFan and Google-Scholar-style queries found only the OEIS entries themselves. Sela Fried, \"Proofs of some Conjectures from the OEIS\" (arXiv:2410.07237) is unrelated. The key tool, Niven's theorem (cos(2*pi/n) is rational only for n = 1, 2, 3, 4, 6), is classical.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Niven's theorem (cos(2*pi/n) is rational only for n = 1, 2, 3, 4, 6), combined with the Euler-formula count of regions already cited in the entry's %F line (T = edges - vertices + 1).", + "justification": "The proof first notes that two chords can only cross if they cut off the same corner or adjacent corners. So any triple point involves just four consecutive vertices, and in an affine frame these depend only on u = 2cos(2*pi/n). With every chord parameter rational, the condition for three chords to meet is linear in u with a nonzero rational coefficient, so u would be rational, which Niven's theorem rules out for n = 5 and n >= 7. Explicit rational triple points for n = 3, 4, 6, and the standard count (a chord crossed at p distinct interior points adds p + 1 regions) giving n*k^2 + 1, complete the proof. The whole argument is about a page of elementary coordinate geometry plus a classical theorem. The long Lean file reflects the effort of formalizing the topology, not a hard mathematical idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A357583", + "slug": "oeis-a357583", + "title": "Kurkov's recursion for the row polynomials of convolution triangles holds", + "area": "Discrete geometry", + "source": "OEIS A357583", + "source_url": "https://oeis.org/A357583", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A357583.lean", + "decl": "Math0.Statements.A357583.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A357583.lean", + "our_decl": "Math0.Frontier.A357583.result", + "summary": "For an integer sequence s(1), s(2), ..., let T_s(n,k) = [z^n] A(z)^k with A(z) = sum_{j>=1} s(j) z^j be its convolution triangle. Define polynomials R(n,k) in Z[x] by R(1,k) = s(k) and R(n,k) = R(n-1,k+1) + x*R(n-1,1)*R(1,k) for n > 1. Then for every n > 0 the row polynomial sum_{k=0}^{n} T_s(n,k) x^k equals x*R(n,1). In particular (s = Bell numbers) the row polynomials of A357583 are x*R(n,1) with R(1,k) = Bell(k). Both parts of the frozen statement (the Bell case and the case of an arbitrary integer sequence) are proved.", + "notes": "Conjecture as stated in OEIS: Conjecture: row polynomials are x*R(n,1) for n > 0 where R(n,k) = R(n-1,k+1) + x*R(n-1,1)*R(1,k) for n > 1, k > 0 with R(1,k) = Bell(k) for k > 0. The same recursion seems to work for self-convolution of any other sequence. - _Mikhail Kurkov_, Apr 05 2025\n\nReferees: I found no prior resolution.\n- The OEIS entries A357583 and A340991 are unchanged upstream since Apr 06 2025 (#10 and #24) and still say \"Conjecture\" (Mikhail Kurkov, Apr 05 2025).\n- A357368, by P. Luschny, defines the convolution-triangle (PMatrix) terminology and gives the row-polynomial recursion P(n,x)=x Σ a(n-k) P(k,x), but not Kurkov's R recursion.\n- Kurkov's sibling conjectures of the same shape are still open on OEIS: A350499, A263634, A356145, A055356.\n- Neither entry is in google-deepmind/formal-conjectures, which is the corpus behind the Tsoukalas et al. dataset and Epoch's OEIS Open benchmark (arXiv 2608.11941).\n- Sela Fried's arXiv 2607.24832 and 2410.07237 do not mention either entry.\n- Searches of arXiv, MathOverflow and GitHub (including the-omega-institute/trureturing) found nothing on this recursion.\n\nRelevant background: D. E. Knuth, \"Convolution polynomials\" (arXiv:math/9207221), on the convolution-triangle framework.", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The standard bivariate generating function of a convolution (Riordan/PMatrix) triangle, sum_n E_n(x) z^n = 1/(1 - x A(z)) with A(z) = sum_{j>=1} s(j) z^j, which gives the row-polynomial recursion E(n) = x * sum_j s(j) E(n-j). That recursion is the PMatrix construction of A357368, and the referee notes record P(n,x) = x*sum a(n-k) P(k,x) there. Unrolling Kurkov's recursion gives the closed form R(n,k) = sum_{j=0}^{n-1} s(k+j) E(n-1-j).", + "justification": "The proof guesses the closed form R(n,k) = sum_j s(k+j) E(n-1-j), where E(n) are the row polynomials, and checks it by a one-line induction. The step uses only the standard recursion E(n) = x*sum_j s(j) E(n-j), which is just the row generating function 1/(1 - xA(z)) of a convolution triangle. Setting k = 1 then gives x*R(n,1) = E(n) at once. A competent mathematician would find this in well under a page, and the general-sequence case is no harder than the Bell case, so the result is routine even though the conjecture had stood open on OEIS.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A362086", + "slug": "oeis-a362086", + "title": "OEIS A362086: every denominator of 1/(2-3/(3-4/(...(n-1)-n/(-3)))) except 9 is 1 or a prime", + "area": "Number theory", + "source": "OEIS A362086", + "source_url": "https://oeis.org/A362086", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A362086.lean", + "decl": "Math0.Statements.A362086.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A362086.lean", + "our_decl": "Math0.Frontier.A362086.result", + "summary": "For n >= 3 let a(n) be the reduced denominator of 1/(2 - 3/(3 - 4/(4 - ... ((n-1) - n/(-3))))), evaluated in Q from the inside out. Then for every n >= 3 with a(n) != 9, a(n) is 1 or a prime. (Mohammed Bouras's conjecture; the value 9 occurs at n = 5.)", + "notes": "Conjecture as stated in OEIS: Conjecture: Except for 9, every term of this sequence is either a prime or 1. (Mohammed Bouras, May 28 2023)\n\nReferees: OEIS A362086 (local mirror, revision #35, May 09 2024): \"Conjecture: Except for 9, every term of this sequence is either a prime or 1.\" No proof is recorded. Related prior work, none of which settles A362086:\n- M. Bouras, \"A New Primes-Generating Sequence\", arXiv:2509.09745 (2025). Lists A362086 in its Table 1 family; the primality property is stated only as a conjecture.\n- B. Cloitre, \"On the sequence A356247\" (2025), OEIS attachment a356247_1.pdf. Proves Conjectures 1-3 for the innermost -1 analogue, A356247.\n- T. Adamczewski, \"OEIS Open: How many conjectures can language models turn into theorems?\", arXiv:2608.11941 (2026), together with the AlphaProof Nexus Lean files oeis_363347_conjecture_2.lean and oeis_a363102_conjecture_1.lean. Proves the analogues for innermost -2 (A363102) and -4 (A363347).\nA362086 appears in neither the alphaproof-nexus-results repository nor the epoch-research LeanOpenProblems and LeanOpenProblems-results repositories. Searches of arXiv, MathOverflow and Math StackExchange found no proof or counterexample.\n\nReading note (fidelity pass, 29 Oct 2026): the statement exempts every term equal to 9. Read strictly, the conjecture exempts only the single term a(5) = 9, which also needs the value 9 to occur only once. That holds for n < 1200 by exact computation but is not part of the Lean result.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The entry's own formula a(n) = (n^2+n-3)/gcd(n^2+n-3, 3*A051403(n-3) + n*A051403(n-4)), with A051403 written in left factorials (its %F), combined with the factorial-valuation and size argument already used for the sibling conjectures A363102 (Adamczewski, arXiv:2608.11941, Appendix A), A356247 (Cloitre) and A363482.", + "justification": "The closed form for the unreduced fraction is essentially the gcd formula already listed in the entry. It reduces the denominator to N/gcd(N, 3(n-1)(n-3)!) with N = n^2+n-3, which is roughly n^2. The rest is the standard template from the solved sibling sequences: a prime p up to n-3 that survives in the denominator must divide N to a higher power than it divides (n-3)!, and this is impossible because of size, apart from a small N = 3p^2 case. Prime factors above n must be at least n+1, so at most one fits, and the cases n < 36 are a finite check. The argument is about a page and a direct adaptation of known proofs, with no new idea, so it is routine.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A363482", + "slug": "oeis-a363482", + "title": "OEIS A363482: apart from 49, every denominator of 1/(2-3/(3-4/(...(n-1)-n/(-5)))) is 1 or a prime", + "area": "Number theory", + "source": "OEIS A363482", + "source_url": "https://oeis.org/A363482", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A363482.lean", + "decl": "Math0.Statements.A363482.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A363482.lean", + "our_decl": "Math0.Frontier.A363482.result", + "summary": "For n >= 3 let t_n = -5 and t_k = k - (k+1)/t_{k+1} for k = n-1, ..., 2. Let a(n) be the denominator, in lowest terms, of 1/t_2 = 1/(2-3/(3-4/(...(n-1)-n/(-5)))). Then for every n >= 3, either a(n) = 49, or a(n) = 1, or a(n) is prime. This is Bouras' conjecture (2023). The value 49 occurs only at n = 6.", + "notes": "Conjecture as stated in OEIS: Conjecture: Except for 49, every term of this sequence is either a prime or 1. (Mohammed Bouras, Jun 04 2023; 'The conjecture holds through n=10000' - Bill McEachen, Jul 08 2025)\n\nReferees: No prior resolution of A363482 found. Sources checked:\n- OEIS A363482 (local mirror, identical to upstream oeisdata #29, Jul 13 2025): conjecture plus a numerical check to n = 10000 (McEachen), no proof.\n- Bouras, \"A New Primes-Generating Sequence\", arXiv:2509.09745 (2025): lists A363482 as the k=5 case of n^2+(k-2)n-k, with observations only.\n- Epoch OEIS Open benchmark (github.com/epoch-research/LeanOpenProblems-results, metadata/oeis/conjectures.json): A363482 is absent.\n- google-deepmind/formal-conjectures: no A363482 file.\n- google-deepmind/alphaproof-nexus-results: no A363482 file.\n\nRelated prior results on sibling sequences:\n- A363102 (endpoint -2) proved: T. Adamczewski, \"OEIS Open: How many conjectures can language models turn into theorems?\", arXiv:2608.11941 (2026), Appendix A; also AlphaProof Nexus oeis_a363102_conjecture_1.lean.\n- A356247 (endpoint -1) proved: B. Cloitre, \"On the sequence A356247\" (2025, OEIS-hosted PDF a356247_1.pdf; not readable here).\n- A363347 (endpoint -4) conjectures 1-2 proved: AlphaProof Nexus oeis_363347_conjecture_2.lean; Adamczewski, arXiv:2608.11941.\n\nThe proof here follows the same template as the A363102 proof.\n\nReading note (fidelity pass, 29 Oct 2026): the statement exempts every term equal to 49. Read strictly, the conjecture exempts only the single term a(6) = 49, which also needs the value 49 to occur only once. That holds for n < 1200 by exact computation but is not part of the Lean result.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The entry's own formula a(n) = (n^2+3n-5)/gcd(n^2+3n-5, 5*A051403(n-3)+n*A051403(n-4)), which reduces to N/gcd(N, 5(n-1)(n-3)!), combined with the p-adic/Legendre-bound template of Adamczewski's proof of the sibling conjecture A363102 (arXiv:2608.11941, Appendix A, linked from cross-reference A363102).", + "justification": "The closed form for the reduced denominator, a(n) = N/gcd(N, 5(n-1)(n-3)!) with N = n^2+3n-5, is essentially the formula already in the entry, and it comes from a standard convergent recurrence. From there the proof is about a page of elementary number theory, and it is the same argument already published for the sibling sequence A363102 (endpoint -2) and its relatives. If a prime p <= n-3 divides a(n), Legendre's bound forces a high power of p to divide N, which is too big except in a small case (N = 3p^2) that is easy to handle. Any prime factor above n-3 is in fact at least n+2, because N + c factors for c = 0, 1, 5, 7, and since N < (n+2)^2 there is room for only one such factor. The cases n <= 35 are a finite check. The manuscript itself says it adapts the existing template, so no new idea was needed.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A363609", + "slug": "oeis-a363609", + "title": "A363609: a(k^3) = 6k(k+2), the cube is the optimal polycube of k^3 dice", + "area": "Discrete geometry", + "source": "OEIS A363609", + "source_url": "https://oeis.org/A363609", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A363609.lean", + "decl": "def statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A363609.lean", + "our_decl": "Math0.Frontier.A363609.result", + "summary": "Each standard die has opposite faces summing to 7, all dice have the same chirality, and each die may take any of its 24 rotations. Build a face-connected polycube from n dice. A face is visible when the neighbouring cell is empty; faces underneath and faces facing an internal cavity also count. a(n) is the least possible number of visible pips. Claim: for every k > 1, a(k^3) = 6(k+2)k.", + "notes": "Conjecture as stated in OEIS: %F A363609 Conjecture: a(k^3) = 6*(k+2)*k for k > 1. (Unattributed formula line. Entry by _Matt Donahoe_, Jun 11 2023; last edit #45, Sep 03 2023.)\n\nReferees: I found no prior resolution.\n- OEIS A363609, by Matt Donahoe, Jun 11 2023 (revision #45, Sep 03 2023): the local mirror is identical to oeis/oeisdata main on GitHub, and it still states the formula as \"Conjecture: a(k^3) = 6*(k+2)*k for k > 1\".\n- Michael S. Branicky's formulas in the same entry, Jun 11 and Jun 15 2023: these give only upper bounds and loose bounds.\n- Donahoe's program, https://github.com/mdonahoe/oeis/blob/main/A363609/dice.py, with its out.txt: a heuristic search over box-plus-slab layouts, with no optimality proof.\n- OEIS A193416, minimum surface area of polycubes: the unweighted analogue, a(n^3) = 6n^2.\n- AMC 10A 2002 Problem 18 (https://artofproblemsolving.com/wiki/index.php/2002_AMC_10A_Problems/Problem_18): computes the minimum for the 3x3x3 cube alone, 90. It does not show that the cube is optimal among all polycubes.\n- Loomis and Whitney, Bull. AMS 55 (1949) 961-962: the classical inequality behind the projection step.\n- Searches of arXiv, MathOverflow, Math StackExchange, Puzzling and SeqFan turned up no proof and no counterexample.", + "date": "2026-10-19", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Discrete Loomis-Whitney inequality (Loomis and Whitney 1949), the standard projection bound behind A193416's a(n^3)=6n^2, and AM-GM, together with a 64-case finite check per die", + "justification": "The value 6k(k+2) splits as surface area 6k^2 plus 12k. That second term counts the pairs of perpendicular exposed faces on the cube. The proof matches this split. First it checks a finite inequality for one die: the pips shown are at least the number of exposed faces plus the number of exposed perpendicular pairs. Then it bounds the faces by projections and Loomis-Whitney, as in the known surface-area result (A193416). It bounds the perpendicular pairs by taking an extreme cell in each slice, then uses |P| <= l1*l2*l3 and AM-GM. The edge term is a neat observation, but it is a direct analogue of the standard projection argument. The whole proof fits in about a page and uses only standard tools, so a competent mathematician working on the problem would likely find it quickly.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A367119", + "slug": "oeis-a367119", + "title": "Edges of the all-chords graph of a triangle with n general-position points per side (A367119)", + "area": "Discrete geometry", + "source": "OEIS A367119", + "source_url": "https://oeis.org/A367119", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A367119.lean", + "decl": "Math0.Statements.A367119.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A367119.lean", + "our_decl": "Math0.Frontier.A367119.result", + "summary": "Take the equilateral triangle with corners 0, 1 and 1/2 + (√3/2)i. Let B be the three corners together with exactly n points in the relative interior of each side, and no other points. Draw the segment between every pair of distinct points of B; pairs on a common side give pieces of that side. Assume general position: no interior point of the triangle lies on three pairwise distinct drawn segments. Form the planar graph whose vertices are the points of B together with every point where two drawn segments meet in a single point. Two distinct vertices are adjacent when they lie on a common drawn segment and no vertex lies strictly between them. Then for every n ≥ 0 this graph has (3/2)(3n^4 + 4n^3 + 3n^2 + 4n + 2) edges. This was conjectured by Shannon and Sloane for OEIS A367119.", + "notes": "Conjecture as stated in OEIS: %F Conjecture: a(n) = (3/2)*(3*n^4 + 4*n^3 + 3*n^2 + 4*n + 2). (Scott R. Shannon and N. J. A. Sloane, Nov 05 2023)\n\nReferees: OEIS sources (read from the local mirror and checked against GitHub oeisdata main):\n- A367119 (Shannon and Sloane, Nov 05 2023): the edge formula is still marked \"Conjecture\"; last edited Nov 09 2023.\n- A367117: \"Theorem: a(n) = (3/4)*(n+1)*(3*n^3+n^2+4)\" for the vertex count of the same configuration. This is the key prior result, since the edge formula follows from it by degree counting: E = 2V + 3(n^2−1).\n- A213827: \"a(n) = (A367177 [sic, i.e. A367117](n) − 3*(n+1))/3 – Shannon & Sloane, Nov 09 2023\". This is the interior-crossing count n^2(n+1)(3n+1)/4 per side-orbit.\n- A367183 (Nov 13 2023): T(3,k) = A367117(k) appears apart from its \"Conjectured\" rows.\n- A365929: Sloane's proof (Nov 07 2023) of the crossing count for the corner-free triangle variant.\n- A366932 and A367015: the analogous edge and region conjectures, marked \"now a theorem\" by Sloane on Dec 31 2025.\n- A392261, A392282, A392228 (Shannon and Sloane, Jan 2026): Shannon's attached proof (a392261.txt) of the general vertex, edge and region formulas for k general points per side of a regular n-gon without corners. The local mirror holds only a git-lfs pointer and the file could not be fetched; oeis.org was not queried, as instructed.\n- A367190 and A366253: the triangle row (n=3) with corners is listed as a conjecture.\n\nWeb searches (arXiv, Math StackExchange, general) found no paper or post that explicitly proves the A367119 or A367118 conjecture. The general method is the classical Euler-formula and crossing-count argument for chord arrangements (Moser's circle problem; Poonen–Rubinstein, arXiv math/9508209).", + "date": "2026-10-20" + }, + { + "id": "OEIS-frontier/A368846", + "slug": "oeis-a368846", + "title": "Diagonal sums of A368846 equal A229580 (Luschny's conjecture)", + "area": "Discrete geometry", + "source": "OEIS A368846", + "source_url": "https://oeis.org/A368846", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A368846.lean", + "decl": "Math0.Statements.A368846.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A368846.lean", + "our_decl": "Math0.Frontier.A368846.result", + "summary": "Let T(n,k) = (-1)^(n+k)·2·C(2k-1,n)·C(2n+1,2k) for k > 0 and T(n,0) = 0^n. Let A229580(n) be the number of colorings of the n X 2 array with colors 0..2 that have exactly one mistake and introduce colors in row-major 0..2 order. Here the array is connected horizontally and antidiagonally, and a mistake is an edge whose two ends have the same color. Then for every k ≥ 0, |Σ_{j=0}^{k} T(k+j,k)| = A229580(k+1). Both sides equal 1 for k = 0 and (2k+1)·2^(2k-1) for k ≥ 1.", + "notes": "Conjecture as stated in OEIS: %C A368846 Conjecture: |Sum_{j=0..k} T(k + j, k)| = A229580(k + 1) for k >= 0. (_Peter Luschny_, Jan 07 2024)\n\nReferees: No prior proof or counterexample found. Checked: the A368846 entry (local mirror and the current oeisdata GitHub raw file, both rev #26, Feb 17 2025, still \"Conjecture\", no %E). A229580: closed form (2n-1)*2^(2n-3) credited to Gerson W. Barbosa/Gerald Hillier, 2018, given without proof; the recurrence and g.f. are marked \"Empirical\". OEIS entries citing A229580 (A383608, A385601, A386227 by Navarrete, 2025) and A368846 (A368847, A368848, A369134, A369135, A369120). T. Curtright, arXiv:2401.00586 and arXiv:2502.09633; T. Curtright and C. Vignat, arXiv:2504.18998 (they discuss diagonals of the inverse matrix, not column sums of M, and call combinatorial interpretations an open question). Blair–Flórez–Mukherjee, arXiv:2203.13205, is linked from A229580; I read only its link, not the paper. Web searches on arXiv, MSE, MathOverflow and SeqFan topics found nothing.", + "date": "2026-10-29", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The closed form A229580(n) = (2n-1)*2^(2n-3) is already listed in A229580 (Barbosa/Hillier, given without proof). The column sum is the standard alternating binomial sum Sum_n (-1)^n C(N,n) C(2n+1,2k), read off as a coefficient of (1+X)(1-(1+X)^2)^N = -(1+X) X^N (X+2)^N (equivalently, the N-th finite difference of a polynomial of degree N+1).", + "justification": "The proof has two easy parts. First, the terms with n < k vanish, so the column sum is 2(-1)^k times an alternating binomial sum. That sum is one coefficient of an explicit polynomial and comes to -(2k+1)4^(k-1), which is a few lines of standard generating-function or finite-difference work. Second, the array graph is just a path on 2n cells taken in row-major order. Counting 3-colourings of it with exactly one monochromatic edge, up to relabelling the colours, gives (2n-1)*3*2^(2n-2)/6. This matches the closed form already listed in A229580. Each step is textbook material and the whole argument fits in well under a page, so the result is routine. The length of the Lean formalization does not change that.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A369366", + "slug": "oeis-a369366", + "title": "The least number of inequivalent cells of a (6k+5)-iamond is 3(k+1)", + "area": "Discrete geometry", + "source": "OEIS A369366", + "source_url": "https://oeis.org/A369366", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A369366.lean", + "decl": "def statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A369366.lean", + "our_decl": "Math0.Frontier.A369366.result", + "summary": "For every k >= 0, the least number of inequivalent cells over all polyiamonds with n = 6k+5 cells is 3(k+1). Two cells of P are equivalent when a symmetry of the triangular grid maps P onto itself and one cell to the other. This is Exley's conjecture in OEIS A369366, a(6k+5) = 3(k+1).", + "notes": "Conjecture as stated in OEIS: %C A369366 Conjecture: a(6k+5) = 3(k+1) for all k >= 0. Observed for k = 0, 1, 2 (n = 5, 11, 17). The next test case is a(23), predicted to be 12. (From _Peter Exley_, Apr 07 2026)\n\nReferees: OEIS A369366 (local mirror revision #14, Apr 14 2026, identical to oeisdata main): Exley's comment of Apr 07 2026 states the conjecture and already proves the lower bound a(6k+5) >= 3(k+1) (no rotations are possible when n = 6k+5, so |G_max| = 2). No upper-bound construction or full proof appears in the entry or its %E history. Cross-references checked: A369365, A369367, A369363, A369364, A367758, A367759, A373637, A376798, A376799. The only related proof is Mason and von Brömssen's formula proof for the polyomino analog A367758 (square lattice, a different problem). Exley's linked GitHub repo github.com/pexley-math/oeis-A369366 and the account page return 404 and could not be inspected. Web searches (arXiv, general web) found no prior resolution.", + "date": "2026-10-20", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Exley's own comment in A369366, which already sketches the lower bound a(6k+5) >= ceiling(n/2) = 3(k+1) (an odd n rules out half-turns, and n = 2 mod 3 rules out 3-fold rotations). The matching upper bound comes from the straight row of 6k+5 triangles, which has one mirror symmetry.", + "justification": "The lower bound was already argued in the entry's own comment. The only missing part was a polyiamond that reaches the bound. The obvious candidate works: a straight row of 2m+1 triangles is symmetric under the mirror through its middle cell, so it has at most m+1 classes, which is 3(k+1) when n = 6k+5. Both halves are a few lines of elementary symmetry counting, and the paper itself calls them elementary. The Lean work is careful, but the mathematics needed no new idea.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A373345", + "slug": "oeis-a373345", + "title": "Row lengths of the Schreier-set triangle A373345 are A007895 (number of Zeckendorf summands)", + "area": "Discrete geometry", + "source": "OEIS A373345", + "source_url": "https://oeis.org/A373345", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A373345.lean", + "decl": "Math0.Statements.A373345.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A373345.lean", + "our_decl": "Math0.Frontier.A373345.result", + "summary": "Let A371176 be the increasing sequence of positive integers k whose binary weight (number of ones) is at most the ruler function v2(2k), i.e. at most one more than the index of the lowest set bit. Equivalently, these are the encodings sum 2^(s-1) of the finite Schreier sets S, meaning nonempty sets of positive integers with |S| <= min S. Row n of A373345 is the Schreier set encoded by A371176(n). Claim: for every n >= 1, row n has exactly as many elements as the Zeckendorf representation of n has terms. In the formal statement, (T n).length = (Nat.zeckendorf n).length.", + "notes": "Conjecture as stated in OEIS: %Y A373345 Cf. A007895 (conjectured row lengths) ... (Paolo Xausa, Jun 01 2024). Likewise %Y A373557 Cf. ... A007895 (conjectured row lengths) (Paolo Xausa, Jun 09 2024).\n\nReferees: OEIS A371176 (Mikhail Kurkov, 2024): the formula a(n) = b(n)*A001316(b(n))/2 with b(n) = A048679(n), and the recursion a(n) = 2^(A072649(n)-1) + [c(n)>0]*2*a(c(n)), were present by Apr 20 2024 (oeisdata commit 6ea59dd), before the A373345 conjecture of Jun 1 2024. Both were stated without proof and imply popcount(A371176(n)) = A007895(n). Kurkov's comment of Oct 21 2024 states the explicit Zeckendorf-rewriting description of A371176(n).\nH. V. Chu, \"The Fibonacci Sequence and Schreier-Zeckendorf Sets\", J. Integer Sequences 22 (2019), Art. 19.6.5 (arXiv:1906.10962), Theorem 3: a cardinality-preserving bijection between Schreier sets and Zeckendorf sets, which also preserves colex/binary order.\nGitHub issue the-omega-institute/trureturing #9050 (\"Research: full Schreier-Zeckendorf row-length identity (OEIS A373345)\", by AlyciaBHZ, Sep 20 2026; confirmed when the manuscript was checked) presents the identity as an elementary consequence of Chu's bijection, as paper mathematics with no Lean formalization.\nBackground only: A. Bird, \"Jozef Schreier, Schreier sets and the Fibonacci sequence\", Out Of The Norm blog, 2012, gives the binary ordering and the R/S block recursion but does not mention Zeckendorf. H. V. Chu, arXiv:2606.21865 (2026), is a survey and does not state the identity.\nNo prior Lean formalization found.", + "date": "2026-10-25" + }, + { + "id": "OEIS-frontier/A373359", + "slug": "oeis-a373359", + "title": "A373359: Schreier-set row lengths equal the Zeckendorf weight A007895", + "area": "Discrete geometry", + "source": "OEIS A373359", + "source_url": "https://oeis.org/A373359", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A373359.lean", + "decl": "Math0.Statements.A373359.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A373359.lean", + "our_decl": "Math0.Frontier.A373359.result", + "summary": "Let A371176 be the increasing sequence of positive integers k with popcount(k) <= v_2(2k), i.e. popcount(k) <= (index of the lowest 1-bit of k) + 1. These are the binary codes of the Schreier sets X (|X| <= min X). Row n of A373359 is the set of 1-based positions of the 1-bits of A371176(n). For every n >= 1, row n has as many elements as there are terms in the Zeckendorf representation of n. Equivalently, popcount(A371176(n)) = A007895(n).", + "notes": "Conjecture as stated in OEIS: %Y A373359 Cf. A007895 (conjectured row lengths), A373346 (row sums), A373347. (_Paolo Xausa_, Jun 04 2024; the same 'conjectured row lengths' cross-reference appears in A373345 and A373579)\n\nReferees: - OEIS A373359 and A373345 (Paolo Xausa, Jun 2024): \"A007895 (conjectured row lengths)\". Local mirror and upstream are unchanged.\n- OEIS A371176 (Mikhail Kurkov, Mar 14 2024):\n - formula a(n) = 2^(A072649(n)-1) + [c(n)>0]*2*a(c(n)) with c = A066628;\n - formula a(n) = b(n)*A001316(b(n))/2 with b = A048679;\n - Kurkov comment of Oct 21 2024: A371176(n) is the Zeckendorf representation of n with the 01->1 rewrite and k-1 zeros appended. Each implies popcount(A371176(n)) = A007895(n).\n- A007895 formula a(n) = A000120(A003714(n)) (Zumkeller 2005).\n- GitHub issue the-omega-institute/trureturing #9050 (Sep 20 2026): https://github.com/the-omega-institute/trureturing/issues/9050. An informal proof of the A373345/A373359 row-length identity, via Chu's bijection plus order preservation and via Bird's recursive blocks.\n- H. V. Chu, \"The Fibonacci Sequence and Schreier-Zeckendorf Sets\", J. Integer Seq. 22 (2019), Art. 19.6.5 (arXiv:1906.10962): the bijection between Schreier sets and Zeckendorf sets.\n- A. Bird, \"Jozef Schreier, Schreier sets and the Fibonacci sequence\", Out Of The Norm blog, May 13 2012: binary ordering of Schreier sets and |M_n| = F_n.\n- H. V. Chu, arXiv:2606.21865 (2026), a survey that does not state the binary-rank theorem.\n- I found no prior Lean or other formal proof.", + "date": "2026-10-26" + }, + { + "id": "OEIS-frontier/A375522", + "slug": "oeis-a375522", + "title": "A375522: S2(n) - S1(n) = 1 fails at n = 42 (the difference is 5)", + "area": "Number theory", + "source": "OEIS A375522", + "source_url": "https://oeis.org/A375522", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A375522.lean", + "decl": "Math0.Statements.A375522.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-refutes", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A375522.lean", + "our_decl": "Math0.Frontier.A375522.result", + "summary": "Let p_k be the k-th prime. Define s(0) = 0 and s(k) = s(k-1) + 1/(p_k b(k)), where b(k) = 1 + floor(1/((1 - s(k-1)) p_k)) (this is A375781). Write s(n) = S1(n)/S2(n) in lowest terms (S2 = A375522, S1 = A375521). Sigrist and Sloane conjectured that S2(n) - S1(n) = 1 for every n >= 1 except n = 4 and n = 6. This is false: S2(42) - S1(42) = 5. Lean: theorem result : ¬ statement.", + "notes": "Conjecture as stated in OEIS: The differences S2(n) - S1(n) are surprisingly small: for n = 1,2,...,34 the values S2(n) - S1(n) are: 1, 1, 1, 2, 1, 2, 1, 1, ..., 1 suggesting the conjecture that they are always 1 except for n = 4 and 6 (compare the Theorem in A374983). (Rémy Sigrist and N. J. A. Sloane, Aug 30 2024)\n\nReferees: The conjecture is in OEIS A375522 (R. Sigrist and N. J. A. Sloane, Aug 30 2024; comment added Aug 31 2024; current revision #25, Apr 22 2025). It is restated as still open (\"it seems\") in A375528 (Sloane, Sep/Oct 2024). Related: A375521, A375781, A374983/A375516 (harmonic analogue, proved by Sigrist), and Sloane, \"A Nasty Surprise in a Sequence and Other OEIS Stories\", Rutgers Experimental Math Seminar, Oct 10 2024 (slides list these sequences and a general Conjecture 4, with no counterexample). Sigrist and Sloane, \"Dampening Down a Divergent Series\", is still cited on OEIS as a manuscript in preparation. No prior counterexample or proof turned up in the OEIS histories, arXiv (e.g. Fried arXiv:2607.24832 does not cover it), web searches, or google-deepmind/formal-conjectures. The SeqFan archive could not be reached.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The entry's own recursion (its Maple/Mathematica programs), run as a finite computation modulo a smooth modulus such as (190!)^2. If 1 - s(n-1) = 1/D, then 1 - s(n) = m/(D(D+m)) with m = p_n - (D mod p_n).", + "justification": "The conjecture is refuted by one computed value: S2(42) - S1(42) = 5. Note that S2(42) has about 4*10^11 digits, so it cannot be computed directly. The only idea needed is a standard one. The difference S2(n) - S1(n) is the small numerator of the remainder 1 - s(n), and it depends only on the huge denominator modulo small numbers, so you track that denominator modulo a large smooth modulus and account for the precision lost when you cancel the gcd at each step. That bookkeeping lemma takes about a page and is elementary. Once it is set up, the result is a finite computation, so the work is routine, although the counterexample is real and was out of reach of the authors' direct computation up to n = 34.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A386538", + "slug": "oeis-a386538", + "title": "A386538: moving the circle's center off the grid enlarges the max lattice polygon (counterexample at n = 7)", + "area": "Discrete geometry", + "source": "OEIS A386538", + "source_url": "https://oeis.org/A386538", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A386538.lean", + "decl": "Math0.Statements.A386538.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-refutes", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A386538.lean", + "our_decl": "Math0.Frontier.A386538.result : ¬ Math0.Statements.A386538.statement", + "summary": "Conjecture (OEIS A386538, Felix Huber): for every n ≥ 0, the largest area of a polygon with vertices on Z^2 inside the closed disk of radius n is the same whether the disk's center is a grid point or any point of the plane. In the frozen encoding: for all n : ℕ, ⨆_{c ∈ ℝ²} vol(conv(Z² ∩ B(c, n))) = vol(conv(Z² ∩ B(0, n))). We prove the negation. At n = 7 with center c0 = (5/12, 5/24), the convex hull of the lattice points in B(c0, 7) has area at least 277/2 = 138.5. The convex hull for the center 0 has area at most 3457/25 = 138.28; its true value is 138 = a(7).", + "notes": "Conjecture as stated in OEIS: \"Conjecture: The maximum possible area of a polygon within the circle would be the same if only the vertices but not the center were fixed on grid points.\" (entry by _Felix Huber_, Aug 05 2025). The same conjecture appears for ellipses in A386539, which has T(n,n) = A386538(n).\n\nReferees: Sources checked:\n- Local OEIS mirror and raw.githubusercontent.com/oeis/oeisdata, A386538: #23, Aug 19 2025, no %E lines. A386539: #19, Aug 19 2025.\n- Entries that cite A386538/A386539: A398490, A396223, A391113. None addresses the conjecture.\n- Cross-references read: A066643, A123690, A125228, A288247, A322106, A322107, A357577, A108126. None resolves it. A123690 and A295344 concern lattice-point counts with an off-grid center, not polygon areas.\n- Web searches for the A386538 number, the entry's wording, Felix Huber plus counterexample, SeqFan, and MathOverflow/Math.SE on convex hulls of lattice points in a shifted disk.\n\nRelated but not resolving:\n- J. Zhao, \"The Largest Circle Enclosing n Lattice Points\", https://arxiv.org/abs/2505.06234, and its sequel https://arxiv.org/pdf/2609.16081\n- Bárány–Larman and Balog–Deshouillers on the integer convex hull of a disk (vertex counts, origin-centered only), e.g. https://www.renyi.hu/~barany/cikkek/73.pdf\n\nNo prior proof or counterexample found.\n\nOEIS data (found in the fidelity pass of 29 Oct 2026 and recomputed exactly): with the centre on a grid point, the largest polygon is the convex hull of the grid points in the disk. Its area differs from the listed terms at n = 13, 17, 18, 22, 23 (516, 888, 990, 1498, 1628, against the listed 512, 880, 986, 1490, 1624). The entry's Maple and Mathematica programs use a shortcut that does not compute this area. The counterexample at n = 7, where the listed a(7) = 138 is correct, is unaffected.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "Direct finite search: exact convex-hull area computation of the lattice points in disks of radius n around rational centres, compared with a(7)=138 from the entry's own data.", + "justification": "The conjecture is refuted by one explicit counterexample. With radius 7 and centre (5/12, 5/24), the lattice points in the disk have a convex hull of area 281/2, which beats a(7) = 138. Finding it took only a search over rational centres with exact hull areas, and checking it means comparing the areas of two explicit lattice polygons, a 12-gon and a 15-gon. No new idea was needed, and the extra work in Lean (trapezoid decompositions and measure-theory bookkeeping) does not change that. This is the conjecture as the author meant it, not a degenerate case, so it is genuinely settled, but the mathematics is routine.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A386655", + "slug": "oeis-a386655", + "title": "A386655 modulo 6 is eventually periodic with pattern [1, 0, 3, 0, 3, 2]", + "area": "Sequences and series", + "source": "OEIS A386655", + "source_url": "https://oeis.org/A386655", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A386655.lean", + "decl": "Math0.Statements.A386655.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A386655.lean", + "our_decl": "Math0.Frontier.A386655.result", + "summary": "Let a(n) = sum_{k=0..n} C(n,k) 2^(k(k+1)) (2^k - (n-k))^(n-k-1), where the k = n term is read as 2^(n^2) and 0^0 = 1. Then for every n >= 6, a(n) mod 6 equals the entry with index (n-6) mod 6 of [1, 0, 3, 0, 3, 2]. Equivalently, a(n) mod 6 = 1, 0, 3, 0, 3, 2 for n ≡ 0, 1, 2, 3, 4, 5 (mod 6). (Paul D. Hanna's conjecture, OEIS A386655.)", + "notes": "Conjecture as stated in OEIS: A386655 (E.g.f.: Sum_{n>=0} (2^n*x + LambertW(x))^n / n!): \"Conjecture: for n >= 6, a(n) (mod 6) equals [1, 0, 3, 0, 3, 2] repeating.\" (_Paul D. Hanna_, Aug 23 2025). Analogues: A386656 (q=3) [4,3,2,1,0,1], A386657 (q=4) [1,2,3,2,3,4], A386658 (q=5) [4,3,0,3,0,5].\n\nReferees: I found no earlier resolution.\n- OEIS A386655 (local mirror and current GitHub oeisdata, revision #14, Aug 24 2025) still states the mod-6 claim as a conjecture by Paul D. Hanna, with no %E edit or proof note.\n- The cross-referenced sister entries A386656, A386657 and A386658 (q = 3, 4, 5) state analogous mod-6 conjectures, none marked proved. The related entry A386648 also has an open mod-6 conjecture.\n- Web searches turned up only OEIS pages (e.g. https://oeis.org/A386648, https://oeis.org/A136524) and no paper, arXiv preprint, MathOverflow/Math StackExchange post or SeqFan message proving or refuting the A386655 conjecture.\n- The classical tool used is the expansion e^(cW(x)) = Sum_k c(c-k)^(k-1) x^k/k! (the tree-function/Lambert W identity), together with Fermat's little theorem and the binomial-transform identity Sum_m C(n,m)C(m,j)x^m = C(n,j)x^j(1+x)^(n-j).", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The entry's explicit formula a(n) = Sum_{k=0..n} C(n,k) 2^(k(k+1)) (2^k-(n-k))^(n-k-1), combined with Fermat's little theorem mod 2 and mod 3 and the standard identity Sum_m C(n,m) C(m,j) x^m = C(n,j) x^j (1+x)^(n-j).", + "justification": "The proof starts from the explicit sum formula already given in the entry and works modulo 2 and modulo 3 separately. Modulo 2 only the k=0 term survives, which is immediate. Modulo 3, writing 2 = -1 and using Fermat's little theorem makes each summand a 6-periodic function of n-k. Such a function can be written with C(m,j), j <= 2, and (-1)^m, and a standard binomial-transform identity then gives a(n) = 1-n^2 or n^2-n mod 3; CRT finishes. This is an elementary argument of about a page, the kind of residue computation a competent mathematician would carry out quickly, so it is routine. The scout had already outlined it before the proof attempt.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A388724", + "slug": "oeis-a388724", + "title": "Column sums of strictly superdiagonal reversed partitions by maximum are A000245", + "area": "Discrete geometry", + "source": "OEIS A388724", + "source_url": "https://oeis.org/A388724", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A388724.lean", + "decl": "Math0.Statements.A388724.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A388724.lean", + "our_decl": "Math0.Frontier.A388724.result", + "summary": "Let T(n,k) be the number of reversed integer partitions y = (y_1 <= ... <= y_m) of n (positive parts, weakly increasing, sum n) that are strictly superdiagonal (y_i > i for all i) and have maximum part k. Then for every k >= 1, sum_n T(n,k) = A000245(k-1), where A000245(0) = 0 and A000245(K) = 3(2K)!/((K+2)!(K-1)!) for K >= 1.", + "notes": "Conjecture as stated in OEIS: Conjecture: Column sums are A000245. - _Gus Wiseman_, Sep 24 2025\n\nReferees: OEIS A388724 (rev #12, Oct 06 2025; the conjecture is still listed and no %E resolution is recorded). M. Archibald, A. Blecher, S. Elizalde, A. Knopfmacher, \"Subdiagonal and superdiagonal partitions\", Afrika Matematika 36:77 (2025), doi:10.1007/s13370-025-01282-0. Theorem 2.3 and its proof give a bijection from superdiagonal weakly increasing partitions with largest part m to pairs (P in D_m, 0 ≤ h < final E-run length of P), plus the generating function for fixed largest part. Theorem 2.2's proof gives a bijection from partitions with k parts and largest part s to the ballot paths B_{k-1,s}. Combined with the shift y_i -> y_i - 1 and the classical identity sum over D_m of final descent length = A000245(m) (E. Deutsch, \"Dyck path enumeration\", Discrete Math. 204 (1999); the A000245 comment by Homberger on total returns), or with Catalan-triangle row sums (A009766, which has A000245 as a diagonal), this yields the conjecture immediately. No explicit prior statement or proof of the column-sum identity was found on OEIS, arXiv, MathOverflow, Math StackExchange or the web.", + "date": "2026-10-25" + }, + { + "id": "OEIS-frontier/A392943", + "slug": "oeis-a392943", + "title": "No primitive Heronian triangle has integer circumradius", + "area": "Discrete geometry", + "source": "OEIS A392943", + "source_url": "https://oeis.org/A392943", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A392943.lean", + "decl": "Math0.Statements.A392943.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "known-result-first-formalization", + "lean_file": "lean/Math0/Frontier/OEIS/A392943.lean", + "our_decl": "Math0.Frontier.A392943.result", + "summary": "Let x, y, z be positive integers satisfying the strict triangle inequalities, with gcd(x, y, z) = 1, and let K be a natural number with 16K^2 = (x+y+z)(-x+y+z)(x-y+z)(x+y-z), i.e. K is the area. Then there is no natural number R with 4KR = xyz. In other words, no primitive Heronian triangle has integer circumradius. This is Felix Huber's conjecture in OEIS A392943.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: There is no primitive Heronian triangle with integer circumradius.\" (entry by _Felix Huber_, Feb 04 2026)\n\nReferees: Ronald van Luijk, \"The diameter of the circumcircle of a Heron triangle\", Elemente der Mathematik 63 (2008), 118–121. The relevant parts are:\n- Theorem 2, (4)⇒(5): if gcd(a,b,c,d) = 1, every prime divisor of the circumdiameter d is ≡ 1 mod 4.\n- Corollary 5: for a prime p ≢ 1 mod 4, p^{v_p(d)} divides gcd(a,b,c).\n- Proof of Theorem 1: it states explicitly that a Heron triangle with integer circumradius has all sides even.\n\nEarlier related work:\n- A.-V. Kramer & F. Luca, \"Some remarks on Heron triangles\", Acta Acad. Paedagog. Agriensis Sect. Mat. (N.S.) 27 (2000) 25–38. Shows no power of 2 is the circumradius of a Heron triangle.\n- M. Aassila, \"Some results on Heron triangles\", Elem. Math. 56 (2001) 143–146.\n\nAlso related, with full text not checked: E. Read, \"Integer triangles with integer circumradii\", Math. Gazette 107 (2023) 241–248.\n\nOEIS A392943 (Huber, Feb 2026) cites none of these, and no proof has been added to the entry.", + "date": "2026-10-19" + }, + { + "id": "OEIS-frontier/A393794", + "slug": "oeis-a393794", + "title": "The 1089-trick map has two 9-digit fixed points (A393794 uniqueness conjecture is false)", + "area": "Sequences and series", + "source": "OEIS A393794", + "source_url": "https://oeis.org/A393794", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A393794.lean", + "decl": "Math0.Statements.A393794.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-refutes", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A393794.lean", + "our_decl": "Math0.Frontier.A393794.result", + "summary": "Let rev(m) be the decimal reversal of m (leading zeros dropped), and let T(x) = D + rev(D) with D = |x - rev(x)|. Havenaar's conjecture in A393794 says that for every n >= 1, a(n) = 110*(10^(n+1) - 1) is the only fixed point of T with exactly n+4 decimal digits. This is false. For n = 5, x = 108910890 has 9 digits and satisfies T(x) = x, but x is not a(5) = 109999890.", + "notes": "Conjecture as stated in OEIS: \"a(n) is the unique fixed point of the 1089-trick map T among all (n+4)-digit numbers (verified exhaustively for n = 1..4; conjectured for all n >= 1).\" (comment in A393794, entry by _Remco Havenaar_, Feb 27 2026; the entry names the sequence 'Fixed points of the 1089-trick map' and gives a(n) = 110*(10^(n+1)-1))\n\nReferees: OEIS A393794 (Havenaar, Feb 27 2026; #19, Mar 10 2026, no correction as of GitHub oeisdata mirror). OEIS A001232 (numbers k with 9k = rev k; includes non-primitive 10891089; structure theorem by D. W. Wilson 1997 and M. F. Hasler 2022), from which 10*A001232 ⊂ Fix(T) follows trivially. R. Havenaar, SYNTRIAD/digit-dynamics GitHub repo (initial commit 2026-03-09): papers/paper_A.tex still states the uniqueness conjecture, while data/results_export.json experiment id 10 (truc_1089, 7-digit domain, 2026-02-25) lists 108910890 among T's fixed points without remark. Neither source states the contradiction. Y. Almirantis and W. Li, arXiv:2408.02527 and arXiv:2410.11784 (Fibonacci Quart. 64 (2026) 281-310) study the related two-option reversal map Phi, with Phi(Phi(x)) = T(x) in the relevant range; arXiv:2410.11784, which predates the conjecture, lists 108910890 twice: in Table 2 as part of the 2-cycle {10891089, 108910890} of Phi, and in Appendix A.2 among the outputs of the two-step 1089 trick on eight-digit numbers; it does not consider the fixed points of T. OEIS A124074 (S. Dumortier, 2006) studies a variant of Phi whose example already shows the 2-cycle 1089 -> 10890 -> 1089. No published refutation found: this is the first explicit refutation, and it is mathematically elementary.", + "date": "2026-10-18", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "The counterexample answers the conjecture as its author meant it. 108910890 is an ordinary 9-digit positive fixed point of T, which is exactly the uniqueness the conjecture claims. Nothing in the entry sets numbers of this kind apart.", + "follows_from": "The entry's own proof that T(a(n)) = a(n) works for any k with 9k = rev(k): rev(10k) = 9k, so D = k and T(10k) = 10k. Cross-reference A001232 lists such k, including the non-primitive term 10891089 (its 5th term; Hasler's comment there describes the concatenated terms 1089 0...0 1089). This gives 10*10891089 = 108910890, a second 9-digit fixed point. A direct exhaustive search of 9-digit numbers also finds it.", + "justification": "The refutation is one explicit 9-digit number whose fixed-point property is checked by a few lines of arithmetic. Where it comes from is immediate from the entry itself: the entry's proof uses only 9k = rev(k), and it points to A001232, whose listed data includes the non-primitive term 10891089. Extending this to every n >= 5 (using 1089 0...0 1089) is equally elementary. The number had also already appeared in the conjecturer's own computational output and in Almirantis-Li. No new idea was needed, so this is routine.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A394981", + "slug": "oeis-a394981", + "title": "Bar tilings of the smallest-perimeter rectangle: a(n+1) = 4 a(n) for odd n >= 3 (A394981)", + "area": "Discrete geometry", + "source": "OEIS A394981", + "source_url": "https://oeis.org/A394981", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A394981.lean", + "decl": "def statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A394981.lean", + "our_decl": "Math0.Frontier.A394981.result", + "summary": "Let a(n) be the number of tilings, counted up to the symmetries of the rectangle, of the rows(n) x cols(n) rectangle by the n bars 1x1, 1x2, ..., 1xn, each used exactly once. Here rows(n) = floor((n+1)/2) and cols(n) = (n(n+1)/2)/rows(n). For n = 2m+1 the rectangle is (m+1) x (2m+1), and for n = 2m+2 it is (m+1) x (2m+3). In Lean, a(n) is the frozen bitmask-search definition: it sums the stabilizer sizes of all tilings found by the search and divides by the order of the symmetry group (Burnside). Claim (A394981 conjecture, read for odd n >= 3): for every odd n >= 3, a(n+1) = 4 a(n). The literal case n = 1 fails, a(2) = 1 != 4 = 4 a(1), and the statement excludes it.", + "notes": "Conjecture as stated in OEIS: %F A394981 Conjecture: If n is odd, then a(n+1) = 4*a(n). (Unattributed formula line. Entry by _Gary Yane_, Apr 08 2026; a(1)-a(2) corrected by _Pontus von Brömssen_, May 13 2026.)\n\nReferees: The OEIS A394981 entry (Gary Yane, Apr 08 2026; a(1)-a(2) corrected by Pontus von Brömssen, May 13 2026; revision #42, May 16 2026, the same in the local mirror and upstream oeisdata) still states the identity as a conjecture, with keyword \"more\" and no proof reference. No other OEIS entry cites it. Cross-references A254414/A254458/A254607/A329279 are unrelated counts. Searches found no proof or counterexample on arXiv, MathOverflow, Math StackExchange, SeqFan or the general web. Nearest work, all on a different problem: arXiv:2606.05439, Blanco, Dougherty-Bliss, Ter-Saakov and Zeilberger, \"In How Many Ways can a Rectangle be Rectangled?\" (tilings by bars of any length); arXiv:2607.29369, Martinez (L-tetromino tilings).", + "date": "2026-10-20", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "", + "justification": "The proof is short and elementary, about a page of informal argument. Because all bar lengths differ, no tiling has a nontrivial symmetry, so a(n) is a quarter of the raw tiling count. Every bar longer than half the width must lie horizontally, and these bars take one row each, so they all cover the middle column. A case split on where bar m+1 sits divides the larger rectangle's tilings into four classes. Deleting one or two middle or edge columns gives a bijection from each class to the tilings of the smaller rectangle. This pigeonhole and column-deletion argument would come quickly to a competent combinatorialist. The 2400-line Lean file reflects the work of formalizing it, not the difficulty of the mathematics. The proof needs the hypothesis n >= 3 because the identity fails at n = 1. That case is a degenerate exception, and the intended conjecture is fully settled.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A395454", + "slug": "oeis-a395454", + "title": "Alexandersson's recurrence for the row polynomials of A395454 holds (rows counted from 1)", + "area": "Discrete geometry", + "source": "OEIS A395454", + "source_url": "https://oeis.org/A395454", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A395454.lean", + "decl": "Math0.Statements.A395454.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-proves", + "classification": "new-result", + "lean_file": "lean/Math0/Frontier/OEIS/A395454.lean", + "our_decl": "Math0.Frontier.A395454.result", + "summary": "Let E2(j,i) be the second-order Eulerian numbers (A201637): E2(0,0)=1, E2(0,i)=0 for i>=1, and E2(j+1,i) = (2j+1-i)E2(j,i-1) + (i+1)E2(j,i). Let T(n,k) = sum_{j=0}^n (-1)^{n-j} C(n,j) E2(j,n-k), the triangle A395454, and let P_m(t) = sum_{k=0}^m T(m,k) t^k be its row polynomials in the entry's numbering (P_0 = 1, P_1 = 0, P_2 = 2t, ...). Then for every m >= 2, in Z[t],\nP_m = (m-1)(1+t) P_{m-1} + (t - t^2) P'_{m-1} + 2(m-1) t P_{m-2}.\nEquivalently, with the rows counted from 1 (P1(n) = P_{n-1}), for every n >= 3: P1(n) = (n - 2t + nt - 2) P1(n-1) + (t - t^2) P1'(n-1) + t(2n-4) P1(n-2). This is Alexandersson's conjecture in the form fixed by the frozen statement.", + "notes": "Conjecture as stated in OEIS: %F A395454 Conjecture: Let P(n) be the generating polynomial (in t) of row n. Then P(n) = (n - 2*t + n*t - 2)*P(n-1) + (t - t^2)*P'(n-1) + t*(2*n-4)*P(n-2). - Per W. Alexandersson, Jun 27 2026\n\nReferees: No earlier resolution found. Closest related work:\n- S.-M. Ma and Y.-N. Yeh, \"Eulerian polynomials, Stirling permutations of the second kind and perfect matchings,\" Electron. J. Combin. 24(4) (2017) #P4.27, arXiv:1607.01311. Its Thm 17 is an analogous recurrence for Stirling-derangement polynomials by cycle ascent plateaus (a different family). Its Cor 18 is the A053871 row-sum recurrence. Its Prop 9 implies that A395454 row n is the distribution of n - casc over Stirling derangements.\n- G.-H. Duh, Y.-C. R. Lin, S.-M. Ma and Y.-N. Yeh, arXiv:1612.07391 (2016).\n- S.-M. Ma, S. Kitaev, J. Yeh and Y.-N. Yeh, arXiv:2601.20665 (2026).\n- S. Fried, \"Further proofs of conjectures from the OEIS,\" arXiv:2607.24832 (2026). Does not cover A395454.\n\nOEIS A395454 (#30, Oct 14 2026; Luschny's entry, Alexandersson's conjecture of Jun 27 2026) still lists the formula as a conjecture, with no proof recorded in any comment, %E line or link. Read with the entry's offset-0 numbering the formula is false; read with rows counted from 1 it holds.", + "date": "2026-10-24", + "assessment": { + "depth": "routine", + "literal_only": false, + "intended_status": "", + "follows_from": "The standard differential recurrence for second-order Eulerian polynomials, E_{j+1}(x) = (1+2jx)E_j(x) + x(1-x)E_j'(x). This is a direct reformulation of the triangle recurrence in A201637 and Graham-Knuth-Patashnik Section 6.2. It is pushed through the alternating binomial transform that defines A395454 using Pascal's rule.", + "justification": "The proof takes the standard recurrence for the reversed second-order Eulerian polynomials, applies it inside the alternating binomial transform (Pascal's rule and k*C(n,k) = n*C(n-1,k-1)), and then compares coefficients term by term. Altogether this is about a page of index bookkeeping, and the paper itself calls the argument routine. The result proves the reading the author evidently meant, with rows counted from 1 (an off-by-one in the indexing). That reading reduces at t=1 to the A053871 recurrence. The literal offset-0 reading fails trivially at n=2. No new idea or construction was needed.", + "challenged": false, + "revision": "", + "date": "2026-10-26" + } + }, + { + "id": "OEIS-frontier/A397315", + "slug": "oeis-a397315", + "title": "A397315: a 14-point blackout of the 5 x 8 grid refutes T(n,m) = n + m", + "area": "Discrete geometry", + "source": "OEIS A397315", + "source_url": "https://oeis.org/A397315", + "statement_origin": "math0", + "upstream": { + "repo": "math0", + "commit": "", + "file": "lean/Math0/Statements/OEIS/A397315.lean", + "decl": "Math0.Statements.A397315.statement", + "category": "OEIS conjecture" + }, + "mode": "settles-refutes", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/Frontier/OEIS/A397315.lean", + "our_decl": "Math0.Frontier.A397315.result", + "summary": "Pemmasani's conjecture in OEIS A397315 says this. Let T(n,k) be the largest number of points that can be blacked out of the grid {0..k-1} x {0..n-1} so that every lattice rectangle (tilted rectangles included) is still determined by its set of visible vertices. Then T(n,m) = n + m whenever min(n,m) >= 4, except T(4,4) = 7 and T(4,5) = T(5,4) = 8. We prove the negation. The 5 x 8 grid (n = 5, k = 8) has a valid blackout of 14 points, so T(5,8) >= 14, which is more than the predicted 5 + 8 = 13.", + "notes": "Conjecture as stated in OEIS: \"Conjecture: T(n,m) = n+m whenever min(n,m) >= 4, except T(4,4) = 7 and T(4,5) = 8 (verified on seven cells through 6 X 6).\" (entry by _Arjun Pemmasani_, Sep 02 2026; comment in the entry, which was last revised Sep 12 2026)\n\nReferees: The refutation is in Arjun Pemmasani's GitHub repository \"Kagey-Problems\" (https://github.com/apemm/Kagey-Problems), which the OEIS entry A397315 links in its %H line. These are the files that record it:\n- kagey-problems/problem001/data/ledger.md, \"Outcomes, part 2 (2026-10-17)\", commit 45b175b, 2026-10-17: blackout(5,8) = 14 and blackout(6,8) = 15. The 5 x 8 maximum blackouts form one orbit of 4.\n- The JIS paper draft kagey-problems/problem001/jis/pemmasani.tex, file sections/sec07_five.tex. Its Theorem \"the guess fails\" states f(5,8) = 14 and f(6,8) = 15. Theorem \"five rows\" states f(5,m) = m+6 for every m >= 8.\n- The Lean proof kagey-problems/lean/KageyProblems/Problem001/Kernel.lean, theorem kfvalue_5_8 (f(5,8) = 14, kernel-checked), commit 8df4162, 2026-10-18. CollarBoards.lean has fval_five: f(5,m) = m+6 for m >= 8.\n- kagey-problems/problem001/README.md says: \"The guess f = h+m for both sides at least 4 fails at 5 x 8 and 6 x 8.\"\n\nThe source problem is Peter Kagey's Open Problem Collection, Problem 001 (https://peterkagey.com/problems/001/); his page lists no values. The companion entry A399580 has nothing on 5 x 8. Neither OEIS entry, in the local mirror or on GitHub (#38 and #24), has been updated with the refutation yet.", + "date": "2026-10-18" + }, + { + "id": "OEIS/51903::conjecture2", + "slug": "oeisa51903-conjecture2", + "title": "No odd n with a(n) > 1 has b^n ≡ b^{a(n)} (mod n) for all b (OEIS A051903)", + "area": "Number theory", + "source": "OEIS 51903", + "source_url": "https://oeis.org/51903", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/OEIS/51903.lean", + "decl": "OeisA51903.conjecture2", + "category": "research open" + }, + "mode": "refutes", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/OEIS/OeisA51903_conjecture2.lean", + "our_decl": "Math0.OeisA51903.not_conjecture2", + "summary": "Let a(n) be the largest exponent in the prime factorization of n (OEIS A051903; a(1) = 0). Thomas Ordowski (Dec 2019) asked: are there odd numbers n with a(n) > 1 and b^n ≡ b^{a(n)} (mod n) for every natural number b? The upstream formal statement says such an n exists. We prove its negation: there is no odd n with a(n) > 1 such that b^n ≡ b^{a(n)} (mod n) for all b ∈ ℕ.", + "notes": "OEIS A051903 comments: Thomas Ordowski, Dec 02 2019, posed questions (*), (**) and (***). Ansh Mishra, Sep 30 2026, added \"Answer to (**): No. Answer to (***): Yes. See Mishra and Senthilkumar (2026)\". Ansh Mishra and Aryan Senthilkumar, \"On Two Questions of Ordowski about the Largest Exponent in a Prime Factorization\", Zenodo preprint, 2026-09-30, https://zenodo.org/records/23064142 (doi:10.5281/zenodo.23064142). It includes Lean 4 / Mathlib proofs, `A051903Core.not_conj2` and `OeisA51903.conjecture2_solved`, of the negation of OeisA51903.conjecture2 using only the standard axioms. That paper credits T. Adamczewski, fc-review-results (https://github.com/tadamcz/fc-review-results, runs of 11, 21 and 23 Sep 2026, entry OEIS/51903), with answering (**) negatively by the same p^(e-1) | e argument and with a Lean proof. The upstream formal_conjectures docstring of OeisA51903.conjecture1 also gives the same divisibility argument, with φ in place of λ. - OEIS A051903, comments by T. Ordowski (Dec 02 2019) stating problems (*), (**) and (***). Comment \"Answer to (**): No. Answer to (***): Yes. See Mishra and Senthilkumar (2026)\" by Ansh Mishra (Sep 30 2026), approved as revision #152 on Oct 11 2026. https://oeis.org/A051903 and https://oeis.org/history?seq=A051903\n\n(Abridged.)", + "date": "2026-10-17" + }, + { + "id": "OEIS/51903::conjecture3", + "slug": "oeisa51903-conjecture3", + "title": "An odd n with a(n) > 1 and 2^n ≡ 2^{a(n)} (mod n), where a(n) is the largest prime exponent of n (OEIS A051903, Ordowski)", + "area": "Number theory", + "source": "OEIS 51903", + "source_url": "https://oeis.org/51903", + "upstream": { + "repo": "google-deepmind/formal-conjectures", + "commit": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "file": "FormalConjectures/OEIS/51903.lean", + "decl": "OeisA51903.conjecture3", + "category": "research open" + }, + "mode": "proves", + "classification": "known-result-already-formalized", + "lean_file": "lean/Math0/OEIS/OeisA51903_conjecture3.lean", + "our_decl": "Math0.OeisA51903.conjecture3", + "summary": "Let a(n) be the largest exponent in the prime factorization of n (OEIS A051903). Ordowski (Dec 2019) asked whether some odd n has a(n) > 1 and 2^n ≡ 2^{a(n)} (mod n). The answer is yes. The formal statement is ∃ n : ℕ, Odd n ∧ 1 < a n ∧ 2 ^ n ≡ 2 ^ (a n) [MOD n], with a n defined as the foldr max of the multiplicities over n.primeFactorsList. The witness is n = 9687963167864344937 = 7 · 631 · 881 · 3511² · 201961.", + "notes": "- OEIS A051903, https://oeis.org/A051903:\n - Thomas Ordowski's comment of Dec 02 2019 poses questions (*), (**) and (***).\n - Ansh Mishra's comment of Sep 30 2026 reads \"Answer to (**): No. Answer to (***): Yes. See Mishra and Senthilkumar (2026).\"\n- A. Mishra and A. Senthilkumar, \"On Two Questions of Ordowski about the Largest Exponent in a Prime Factorization\", Zenodo preprint, 2026-09-30, doi:10.5281/zenodo.23064142, https://zenodo.org/records/23064142.\n - It gives the same witness n0 = 9687963167864344937 = 7·631·881·3511²·201961, proves that n0 is minimal, and includes Lean 4 proofs of OeisA51903.conjecture2 (negative) and conjecture3 (positive) against the unmodified formal-conjectures file. The relevant files are lean/DMSolutions/OEIS_A051903/{Core,Solution,CheckAnswer}.lean and logs/lean_check.log.\n- F. G. Dorais and D. Klyve, \"A Wieferich prime search up to 6.7×10^15\", J. Integer Seq. 14 (2011). The minimality argument relies on this search.\n- T. Adamczewski, tadamcz/fc-review-results (entry OEIS/51903). The Zenodo README cites it as prior work: an earlier negative answer to (**), with (***) still regarded as open as of 2026-09-23.\n\n(Abridged.)", + "date": "2026-10-17" + } + ] +} \ No newline at end of file diff --git a/history.md b/history.md new file mode 100644 index 0000000..990fac3 --- /dev/null +++ b/history.md @@ -0,0 +1,11 @@ +# History + +Every change to what math0 claims is recorded here. Withdrawn or reclassified results stay listed, +with the reason. + +## October 17, 2026: initial release + +* Verification infrastructure: a Lean 4 project pinned to Mathlib `v4.33.1` and + google-deepmind/formal-conjectures `c77fdd4`, with the `#math0_proves` / `#math0_refutes` / + `#math0_answers` audit commands and CI. +* First results; see [CONTENTS.md](CONTENTS.md). diff --git a/lean/Math0.lean b/lean/Math0.lean new file mode 100644 index 0000000..de4db15 --- /dev/null +++ b/lean/Math0.lean @@ -0,0 +1,166 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Audit +import Math0.Statements +import Math0.Arxiv.Arxiv_0805_3777_isMaxRank_le_two_mul_isGenericRank +import Math0.Arxiv.Arxiv_1609_08688_maximalLength_ge_of_isSquare +import Math0.Arxiv.Arxiv_1609_08688_maximalLength_pow +import Math0.Arxiv.Arxiv_2602_05192_four_2 +import Math0.Arxiv.Arxiv_2605_12342_conjecture_1_variants_rank_3_3 +import Math0.Arxiv.Arxiv_math_0608009_poisson_conjecture_variants_dimension_three +import Math0.Arxiv.Arxiv_math_0608009_poisson_conjecture_variants_jacobian_implication +import Math0.Books.Bugeaud06_problem_10_6_variant_1 +import Math0.Books.Bugeaud08_problem_10_8_variants_quadratic +import Math0.Books.Bugeaud09_problem_10_9_variants_dimH_lt_one +import Math0.Books.Bugeaud09_problem_10_9_variants_measure_zero +import Math0.Books.Equidistribution_isAccumulationPoint_three_halves_pow_infinite +import Math0.ErdosProblems.Erdos1000_erdos_1000_variants_limsup_eq_one +import Math0.ErdosProblems.Erdos1000_erdos_1000_variants_not_tendsto_zero +import Math0.ErdosProblems.Erdos1008_erdos_1008_variants_lower_bound +import Math0.ErdosProblems.Erdos1010_erdos_1010_variants_rademacher +import Math0.ErdosProblems.Erdos1026_erdos_1026_variants_upper_bound +import Math0.ErdosProblems.Erdos1048_erdos_1048_variants_diam_ge_two_is_best +import Math0.ErdosProblems.Erdos1098_erdos_1098_variants_upper_bound +import Math0.ErdosProblems.Erdos10_erdos_10_variants_grechuk_example +import Math0.ErdosProblems.Erdos1119_erdos_1119_variants_erdos_wetzel +import Math0.ErdosProblems.Erdos1121_erdos_1121_variants_higher_dimension +import Math0.ErdosProblems.Erdos1136_erdos_1136_variants_mueller +import Math0.ErdosProblems.Erdos1136_erdos_1136_variants_multiples_of_three +import Math0.ErdosProblems.Erdos1136_erdos_1136_variants_upper_bound +import Math0.ErdosProblems.Erdos1148_erdos_1148_variants_weaker +import Math0.ErdosProblems.Erdos1180_erdos_1180_variants_optimal +import Math0.ErdosProblems.Erdos1193_erdos_1193_parts_i +import Math0.ErdosProblems.Erdos1193_erdos_1193_parts_ii +import Math0.ErdosProblems.Erdos142_erdos_142 +import Math0.ErdosProblems.Erdos142_erdos_142_variants_isTheta +import Math0.ErdosProblems.Erdos319_erdos_319 +import Math0.ErdosProblems.Erdos367_erdos_367_variants_higher_full_parts +import Math0.ErdosProblems.Erdos409_erdos_409_parts_i +import Math0.ErdosProblems.Erdos723_erdos_723_variants_prime_power_is_projplane_order +import Math0.ErdosProblems.Erdos750_erdos_750_variants_c_gt_quarter +import Math0.ErdosProblems.Erdos775_erdos_775_variants_moon_moser +import Math0.ErdosProblems.Erdos816_erdos_816_variants_complete_bipartite +import Math0.ErdosProblems.Erdos834_erdos_834_parts_ii +import Math0.ErdosProblems.Erdos835_johnsonGraph_18_9_chromaticNumber +import Math0.Frontier.OEIS.A001040 +import Math0.Frontier.OEIS.A005590 +import Math0.Frontier.OEIS.A022445 +import Math0.Frontier.OEIS.A057566 +import Math0.Frontier.OEIS.A057566b +import Math0.Frontier.OEIS.A060693 +import Math0.Frontier.OEIS.A062887 +import Math0.Frontier.OEIS.A071685 +import Math0.Frontier.OEIS.A073642 +import Math0.Frontier.OEIS.A075855 +import Math0.Frontier.OEIS.A081200 +import Math0.Frontier.OEIS.A083020 +import Math0.Frontier.OEIS.A086004 +import Math0.Frontier.OEIS.A090905 +import Math0.Frontier.OEIS.A091817 +import Math0.Frontier.OEIS.A092054 +import Math0.Frontier.OEIS.A093726 +import Math0.Frontier.OEIS.A097154 +import Math0.Frontier.OEIS.A106505 +import Math0.Frontier.OEIS.A113676 +import Math0.Frontier.OEIS.A115026 +import Math0.Frontier.OEIS.A116184 +import Math0.Frontier.OEIS.A119936 +import Math0.Frontier.OEIS.A120069 +import Math0.Frontier.OEIS.A121750 +import Math0.Frontier.OEIS.A123710 +import Math0.Frontier.OEIS.A124526 +import Math0.Frontier.OEIS.A126127 +import Math0.Frontier.OEIS.A127752 +import Math0.Frontier.OEIS.A127755 +import Math0.Frontier.OEIS.A127767 +import Math0.Frontier.OEIS.A129455 +import Math0.Frontier.OEIS.A132616 +import Math0.Frontier.OEIS.A141412 +import Math0.Frontier.OEIS.A144637 +import Math0.Frontier.OEIS.A160848 +import Math0.Frontier.OEIS.A172164 +import Math0.Frontier.OEIS.A175385 +import Math0.Frontier.OEIS.A176206 +import Math0.Frontier.OEIS.A178295 +import Math0.Frontier.OEIS.A182617 +import Math0.Frontier.OEIS.A188474 +import Math0.Frontier.OEIS.A195249 +import Math0.Frontier.OEIS.A201060 +import Math0.Frontier.OEIS.A209802 +import Math0.Frontier.OEIS.A211343 +import Math0.Frontier.OEIS.A215010 +import Math0.Frontier.OEIS.A223395 +import Math0.Frontier.OEIS.A229159 +import Math0.Frontier.OEIS.A242396 +import Math0.Frontier.OEIS.A249434 +import Math0.Frontier.OEIS.A262957 +import Math0.Frontier.OEIS.A265210 +import Math0.Frontier.OEIS.A265649 +import Math0.Frontier.OEIS.A267486 +import Math0.Frontier.OEIS.A270668 +import Math0.Frontier.OEIS.A275815 +import Math0.Frontier.OEIS.A278212 +import Math0.Frontier.OEIS.A281000 +import Math0.Frontier.OEIS.A294512 +import Math0.Frontier.OEIS.A300789 +import Math0.Frontier.OEIS.A308107 +import Math0.Frontier.OEIS.A308121 +import Math0.Frontier.OEIS.A308222 +import Math0.Frontier.OEIS.A308359 +import Math0.Frontier.OEIS.A320099 +import Math0.Frontier.OEIS.A323695 +import Math0.Frontier.OEIS.A326407 +import Math0.Frontier.OEIS.A326602 +import Math0.Frontier.OEIS.A328202 +import Math0.Frontier.OEIS.A332010 +import Math0.Frontier.OEIS.A333650 +import Math0.Frontier.OEIS.A334592 +import Math0.Frontier.OEIS.A334595 +import Math0.Frontier.OEIS.A334603 +import Math0.Frontier.OEIS.A335012 +import Math0.Frontier.OEIS.A338885 +import Math0.Frontier.OEIS.A341761 +import Math0.Frontier.OEIS.A342645 +import Math0.Frontier.OEIS.A342992 +import Math0.Frontier.OEIS.A344710 +import Math0.Frontier.OEIS.A348484 +import Math0.Frontier.OEIS.A350499 +import Math0.Frontier.OEIS.A350557 +import Math0.Frontier.OEIS.A350900 +import Math0.Frontier.OEIS.A351743 +import Math0.Frontier.OEIS.A354571 +import Math0.Frontier.OEIS.A355076 +import Math0.Frontier.OEIS.A355339 +import Math0.Frontier.OEIS.A355360 +import Math0.Frontier.OEIS.A356360 +import Math0.Frontier.OEIS.A357216 +import Math0.Frontier.OEIS.A357583 +import Math0.Frontier.OEIS.A362086 +import Math0.Frontier.OEIS.A363482 +import Math0.Frontier.OEIS.A363609 +import Math0.Frontier.OEIS.A367119 +import Math0.Frontier.OEIS.A368846 +import Math0.Frontier.OEIS.A369366 +import Math0.Frontier.OEIS.A373345 +import Math0.Frontier.OEIS.A373359 +import Math0.Frontier.OEIS.A375522 +import Math0.Frontier.OEIS.A386538 +import Math0.Frontier.OEIS.A386655 +import Math0.Frontier.OEIS.A388724 +import Math0.Frontier.OEIS.A392943 +import Math0.Frontier.OEIS.A393794 +import Math0.Frontier.OEIS.A394981 +import Math0.Frontier.OEIS.A395454 +import Math0.Frontier.OEIS.A397315 +import Math0.GreensOpenProblems.Green44_green_44 +import Math0.OEIS.OeisA51903_conjecture2 +import Math0.OEIS.OeisA51903_conjecture3 + +/-! +# math0 + +Root module: imports every verified result. Building it re-runs every audit (`#math0_proves`, +`#math0_refutes`, `#math0_answers`), so `lake build` fails on any `sorry`, non-standard axiom, or +mismatch with the upstream statement. +-/ diff --git a/lean/Math0/Arxiv/Arxiv_0805_3777_isMaxRank_le_two_mul_isGenericRank.lean b/lean/Math0/Arxiv/Arxiv_0805_3777_isMaxRank_le_two_mul_isGenericRank.lean new file mode 100644 index 0000000..d561f05 --- /dev/null +++ b/lean/Math0/Arxiv/Arxiv_0805_3777_isMaxRank_le_two_mul_isGenericRank.lean @@ -0,0 +1,65 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.Arxiv.«0805.3777».TensorRank +import Math0.Audit + +/-! +# Maximal rank is at most twice the generic rank (Blekherman–Teitler) + +Blekherman and Teitler [BT15, Theorem 1] proved that the maximal rank of tensors of a given +format is at most twice the generic rank. We prove exactly the formal statement +`Arxiv.«0805.3777».isMaxRank_le_two_mul_isGenericRank` from formal-conjectures, where the generic +rank `r` is witnessed by an open dense set `U` of tensors of rank `r`. Given any tensor `T`, the +set `T - U` is open and nonempty, so it meets the dense set `U`; this gives `u ∈ U` with +`T - u ∈ U`, and `T = u + (T - u)` is a sum of two tensors of rank `r`, so `cprank T ≤ 2r`. +-/ + +open Arxiv.«0805.3777» + +namespace Math0.Arxiv.«0805.3777» + +/-- The map `x ↦ T - x` on complex holors is continuous for the product topology. -/ +lemma continuous_sub_left {ds : List ℕ} (T : Holor ℂ ds) : + Continuous (fun x : Holor ℂ ds => T - x) := by + have h : Continuous (fun x : HolorIndex ds → ℂ => (show HolorIndex ds → ℂ from T) - x) := + continuous_const.sub continuous_id + exact h + +/-- A holor of CP rank at most `n` (in the sense of `Holor.CPRankMax`) has `cprank ≤ n`. -/ +lemma cprank_le_of_cprankMax {ds : List ℕ} {n : ℕ} {x : Holor ℂ ds} + (h : Holor.CPRankMax n x) : x.cprank ≤ n := by + classical + unfold Holor.cprank + exact Nat.find_min' _ h + +/-- Every holor satisfies `CPRankMax (cprank x) x`. -/ +lemma cprankMax_cprank {ds : List ℕ} (x : Holor ℂ ds) : Holor.CPRankMax x.cprank x := by + classical + unfold Holor.cprank + exact Nat.find_spec (p := fun n => Holor.CPRankMax n x) _ + +/-- The maximal rank is at most twice the generic rank [BT15, Theorem 1]. -/ +theorem isMaxRank_le_two_mul_isGenericRank : + type_of% @Arxiv.«0805.3777».isMaxRank_le_two_mul_isGenericRank := by + intro ds r R hr hR + obtain ⟨U, hUo, hUd, hUr⟩ := hr + obtain ⟨T, hT⟩ := hR.1 + subst hT + obtain ⟨u₀, hu₀⟩ := hUd.nonempty + have hV : IsOpen ((fun x : Holor ℂ ds => T - x) ⁻¹' U) := + hUo.preimage (continuous_sub_left T) + have hVne : ((fun x : Holor ℂ ds => T - x) ⁻¹' U).Nonempty := + ⟨T - u₀, by simpa using hu₀⟩ + obtain ⟨u, huV, huU⟩ := hUd.inter_open_nonempty _ hV hVne + have h1 : Holor.CPRankMax r u := hUr u huU ▸ cprankMax_cprank u + have h2 : Holor.CPRankMax r (T - u) := hUr (T - u) huV ▸ cprankMax_cprank (T - u) + have h3 := Holor.cprankMax_add h1 h2 + rw [add_sub_cancel] at h3 + have := cprank_le_of_cprankMax h3 + show T.cprank ≤ 2 * r + omega + +end Math0.Arxiv.«0805.3777» + +#math0_proves Math0.Arxiv.«0805.3777».isMaxRank_le_two_mul_isGenericRank Arxiv.«0805.3777».isMaxRank_le_two_mul_isGenericRank diff --git a/lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_ge_of_isSquare.lean b/lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_ge_of_isSquare.lean new file mode 100644 index 0000000..f8e7f1b --- /dev/null +++ b/lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_ge_of_isSquare.lean @@ -0,0 +1,106 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.Arxiv.«1609.08688».sIncreasingrTuples +import Math0.Audit + +/-! +# A 2-increasing sequence of length `n ^ (3/2)` (Gowers–Long) + +Let `F(n)` be the maximal length of a sequence of triples in `[1, n]^3` in which every earlier +triple is smaller than every later one in at least two coordinates. Gowers and Long +[arXiv:1609.08688, Proposition 1.4] observe that `F(n) ≥ n ^ (3/2)` when `n` is a perfect square. +We prove exactly the formal statement `Arxiv.«1609.08688».maximalLength_ge_of_isSquare`: +if `n = k * k` then `k ^ 3 ≤ F(n)`. The witness lists, for `(a, b, c) ∈ [0, k)^3` in +lexicographic order, the triple `(a k + b + 1, a k + c + 1, b k + c + 1)`, i.e. the pairs +`((a, b), (a, c), (b, c))` written in base `k`. When the first index that changes is `a`, `b` +or `c`, the coordinates `{1, 2}`, `{1, 3}` or `{2, 3}` respectively increase. Boundedness of the +set of lengths (needed for `le_csSup`) comes from the pigeonhole bound `n ^ 2`. +-/ + +open Arxiv.«1609.08688» + +namespace Math0.Arxiv.«1609.08688» + +/-- The triple `((a,b),(a,c),(b,c))` with pairs encoded in base `k`, shifted to start at `1`. -/ +def triple (k a b c : ℕ) : Fin 3 → ℕ := ![a * k + b + 1, a * k + c + 1, b * k + c + 1] + +/-- The sequence of all triples `triple k a b c` for `a, b, c < k`, in lexicographic order. -/ +def seq (k : ℕ) : List (Fin 3 → ℕ) := + (List.range k).flatMap fun a => (List.range k).flatMap fun b => + (List.range k).map fun c => triple k a b c + +/-- The sequence has length `k ^ 3`. -/ +lemma length_seq (k : ℕ) : (seq k).length = k ^ 3 := by + simp [seq, List.length_flatMap] + ring + +/-- Changing `a` to a larger value increases the first two coordinates. -/ +lemma lt₂_of_lt_a {k a b c a' b' c' : ℕ} (ha : a < a') (hb : b < k) (hc : c < k) : + lt₂ (triple k a b c) (triple k a' b' c') := by + have h : (a + 1) * k ≤ a' * k := Nat.mul_le_mul_right _ ha + refine ⟨0, 1, by decide, ?_, ?_⟩ <;> simp [triple] <;> nlinarith + +/-- Keeping `a` and increasing `b` increases the first and third coordinates. -/ +lemma lt₂_of_lt_b {k a b c b' c' : ℕ} (hb : b < b') (hc : c < k) : + lt₂ (triple k a b c) (triple k a b' c') := by + have h : (b + 1) * k ≤ b' * k := Nat.mul_le_mul_right _ hb + refine ⟨0, 2, by decide, ?_, ?_⟩ <;> simp [triple] <;> nlinarith + +/-- Keeping `a, b` and increasing `c` increases the second and third coordinates. -/ +lemma lt₂_of_lt_c {k a b c c' : ℕ} (hc : c < c') : + lt₂ (triple k a b c) (triple k a b c') := by + refine ⟨1, 2, by decide, ?_, ?_⟩ <;> simp [triple] <;> omega + +/-- The sequence `seq k` is `2`-increasing. -/ +lemma isIncreasing₂_seq (k : ℕ) : IsIncreasing₂ (seq k) := by + unfold IsIncreasing₂ seq + simp only [List.pairwise_flatMap, List.pairwise_map, List.mem_range, List.mem_flatMap, + List.mem_map] + refine ⟨fun a _ => ⟨fun b _ => ?_, ?_⟩, ?_⟩ + · exact List.pairwise_lt_range.imp fun h => lt₂_of_lt_c h + · refine List.pairwise_lt_range.imp_of_mem fun _ _ h => ?_ + rintro _ ⟨c, hc, rfl⟩ _ ⟨c', -, rfl⟩ + exact lt₂_of_lt_b h hc + · refine List.pairwise_lt_range.imp_of_mem fun _ _ h => ?_ + rintro _ ⟨b, hb, c, hc, rfl⟩ _ ⟨b', -, c', -, rfl⟩ + exact lt₂_of_lt_a h hb hc + +/-- All coordinates of all triples of `seq k` lie in `[1, k * k]`. -/ +lemma range_seq (k : ℕ) : ∀ t ∈ seq k, Set.range t ⊆ Set.Icc 1 (k * k) := by + intro t ht + simp only [seq, List.mem_flatMap, List.mem_range, List.mem_map] at ht + obtain ⟨a, ha, b, hb, c, hc, rfl⟩ := ht + rintro _ ⟨i, rfl⟩ + fin_cases i <;> simp [triple] <;> nlinarith + +/-- For `n ≥ 2`, every `2`-increasing sequence of triples in `[1, n]` has length at most +`F(n)` (the set of lengths is bounded above by `n ^ 2` by pigeonhole). -/ +lemma length_le_maximalLength {n : ℕ} (hn : 2 ≤ n) {s : List (Fin 3 → ℕ)} + (hs₁ : ∀ a ∈ s, Set.range a ⊆ Set.Icc 1 n) (hs₂ : IsIncreasing₂ s) : + s.length ≤ maximalLength n := by + rw [maximalLength] + refine le_csSup ⟨n ^ 2, ?_⟩ ⟨s, hs₁, hs₂, rfl⟩ + rintro _ ⟨t, ht₁, ht₂, rfl⟩ + by_contra hle + obtain ⟨i, j, hij, h0, h1⟩ := exists_pair_of_mem_Icc hn ht₁ (Nat.lt_of_not_ge hle) + have hp : t.Pairwise lt₂ := ht₂ + rcases lt_or_gt_of_ne hij with hij | hji + · exact (not_lt₂_of_exists 0 1 zero_ne_one h0.ge h1.ge) (List.pairwise_iff_get.1 hp i j hij) + · exact (not_lt₂_of_exists 0 1 zero_ne_one h0.le h1.le) (List.pairwise_iff_get.1 hp j i hji) + +/-- If `n` is a perfect square then `F(n) ≥ (√n) ^ 3`. -/ +theorem maximalLength_ge_of_isSquare : + type_of% @Arxiv.«1609.08688».maximalLength_ge_of_isSquare := by + rintro n ⟨k, rfl⟩ + rw [Nat.sqrt_eq] + rcases Nat.lt_or_ge k 2 with hk | hk + · interval_cases k + · simp + · simp [maximalLength_one] + · rw [← length_seq k] + exact length_le_maximalLength (by nlinarith) (range_seq k) (isIncreasing₂_seq k) + +end Math0.Arxiv.«1609.08688» + +#math0_proves Math0.Arxiv.«1609.08688».maximalLength_ge_of_isSquare Arxiv.«1609.08688».maximalLength_ge_of_isSquare diff --git a/lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_pow.lean b/lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_pow.lean new file mode 100644 index 0000000..3d0b919 --- /dev/null +++ b/lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_pow.lean @@ -0,0 +1,167 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.Arxiv.«1609.08688».sIncreasingrTuples +import Math0.Audit + +/-! +# Powers of `F(n)` propagate to arbitrarily large `m` (Gowers–Long) + +Let `F(n)` be the maximal length of a sequence of triples in `[1, n]^3` in which every earlier +triple is smaller than every later one in at least two coordinates. Gowers and Long +[arXiv:1609.08688] note that if `F(n) = n ^ α` for some `n > 1`, then `F(m) ≥ m ^ α` for +arbitrarily large `m`. We prove exactly the formal statement +`Arxiv.«1609.08688».maximalLength_pow`. The key step is supermultiplicativity +`F(a) F(b) ≤ F(a b)`: given optimal sequences `s` (in `[1, a]`) and `t` (in `[1, b]`), the +sequence of triples `b (x - 1) + y` for `x ∈ s`, `y ∈ t`, listed lexicographically in `(x, y)`, +is `2`-increasing with coordinates in `[1, a b]`. Induction gives `F(n) ^ j ≤ F(n ^ j)`, and +`(n ^ j) ^ α = (n ^ α) ^ j = F(n) ^ j`, so `m = n ^ j` works for every `j`. +-/ + +open Arxiv.«1609.08688» + +namespace Math0.Arxiv.«1609.08688» + +namespace MaximalLengthPow + +/-- Every `2`-increasing sequence of triples in `[1, n]` has length at most `(n + 2) ^ 2` +(pigeonhole on the first two coordinates, applied in the larger box `[1, n + 2]`). -/ +lemma length_le_sq {n : ℕ} {s : List (Fin 3 → ℕ)} + (hs₁ : ∀ a ∈ s, Set.range a ⊆ Set.Icc 1 n) (hs₂ : IsIncreasing₂ s) : + s.length ≤ (n + 2) ^ 2 := by + have hs₁' : ∀ a ∈ s, Set.range a ⊆ Set.Icc 1 (n + 2) := fun a ha => + (hs₁ a ha).trans (Set.Icc_subset_Icc le_rfl (by omega)) + by_contra hle + obtain ⟨i, j, hij, h0, h1⟩ := exists_pair_of_mem_Icc (by omega) hs₁' (Nat.lt_of_not_ge hle) + have hp : s.Pairwise lt₂ := hs₂ + rcases lt_or_gt_of_ne hij with hij | hji + · exact (not_lt₂_of_exists 0 1 zero_ne_one h0.ge h1.ge) (List.pairwise_iff_get.1 hp i j hij) + · exact (not_lt₂_of_exists 0 1 zero_ne_one h0.le h1.le) (List.pairwise_iff_get.1 hp j i hji) + +/-- The set of lengths whose supremum defines `F(n)` is bounded above. -/ +lemma bddAbove_lengths (n : ℕ) : + BddAbove { List.length s | (s) (_ : ∀ a ∈ s, Set.range a ⊆ Set.Icc 1 n) + (_ : IsIncreasing₂ s) } := by + refine ⟨(n + 2) ^ 2, ?_⟩ + rintro _ ⟨s, hs₁, hs₂, rfl⟩ + exact length_le_sq hs₁ hs₂ + +/-- Every `2`-increasing sequence of triples in `[1, n]` has length at most `F(n)`. -/ +lemma length_le_F {n : ℕ} {s : List (Fin 3 → ℕ)} + (hs₁ : ∀ a ∈ s, Set.range a ⊆ Set.Icc 1 n) (hs₂ : IsIncreasing₂ s) : + s.length ≤ maximalLength n := + le_csSup (bddAbove_lengths n) ⟨s, hs₁, hs₂, rfl⟩ + +/-- The supremum `F(n)` is attained by some `2`-increasing sequence. -/ +lemma exists_length_eq_F (n : ℕ) : ∃ s : List (Fin 3 → ℕ), + (∀ a ∈ s, Set.range a ⊆ Set.Icc 1 n) ∧ IsIncreasing₂ s ∧ s.length = maximalLength n := by + have hmem : maximalLength n ∈ { List.length s | (s) (_ : ∀ a ∈ s, Set.range a ⊆ Set.Icc 1 n) + (_ : IsIncreasing₂ s) } := + Nat.sSup_mem ⟨0, ⟨[], by simp, isIncreasing₂_nil, rfl⟩⟩ (bddAbove_lengths n) + obtain ⟨s, hs₁, hs₂, h⟩ := hmem + exact ⟨s, hs₁, hs₂, h⟩ + +/-- The combined triple with coordinates `b (x_i - 1) + y_i`. -/ +def comb (b : ℕ) (x y : Fin 3 → ℕ) : Fin 3 → ℕ := fun i => b * (x i - 1) + y i + +/-- The product sequence: all `comb b x y` with `x ∈ s`, `y ∈ t`, lexicographically. -/ +def prodSeq (b : ℕ) (s t : List (Fin 3 → ℕ)) : List (Fin 3 → ℕ) := + s.flatMap fun x => t.map (comb b x) + +/-- The product sequence has length `|s| |t|`. -/ +lemma length_prodSeq (b : ℕ) (s t : List (Fin 3 → ℕ)) : + (prodSeq b s t).length = s.length * t.length := by + simp [prodSeq, List.length_flatMap] + +/-- Coordinates of the product sequence lie in `[1, a b]`. -/ +lemma range_prodSeq {a b : ℕ} {s t : List (Fin 3 → ℕ)} + (hs : ∀ x ∈ s, Set.range x ⊆ Set.Icc 1 a) (ht : ∀ y ∈ t, Set.range y ⊆ Set.Icc 1 b) : + ∀ z ∈ prodSeq b s t, Set.range z ⊆ Set.Icc 1 (a * b) := by + intro z hz + simp only [prodSeq, List.mem_flatMap, List.mem_map] at hz + obtain ⟨x, hx, y, hy, rfl⟩ := hz + rintro _ ⟨i, rfl⟩ + have hxi := hs x hx ⟨i, rfl⟩ + have hyi := ht y hy ⟨i, rfl⟩ + simp only [Set.mem_Icc] at hxi hyi ⊢ + obtain ⟨u, hu⟩ : ∃ u, x i = u + 1 := ⟨x i - 1, by omega⟩ + have h1 : b * (u + 1) ≤ b * a := Nat.mul_le_mul_left b (by omega) + simp only [comb, hu, Nat.add_sub_cancel] + constructor + · omega + · rw [mul_comm a b]; nlinarith + +/-- Within a block (fixed `x`), the order of `t` is preserved. -/ +lemma lt₂_comb_right {b : ℕ} {x y y' : Fin 3 → ℕ} (h : lt₂ y y') : + lt₂ (comb b x y) (comb b x y') := by + obtain ⟨i, j, hij, hi, hj⟩ := h + exact ⟨i, j, hij, by simp only [comb]; omega, by simp only [comb]; omega⟩ + +/-- Between blocks, `x <₂ x'` forces `comb b x y <₂ comb b x' y'`. -/ +lemma lt₂_comb_left {a b : ℕ} {x x' y y' : Fin 3 → ℕ} + (hx : Set.range x ⊆ Set.Icc 1 a) (hy : Set.range y ⊆ Set.Icc 1 b) + (hy' : Set.range y' ⊆ Set.Icc 1 b) (h : lt₂ x x') : + lt₂ (comb b x y) (comb b x' y') := by + have key : ∀ k, x k < x' k → comb b x y k < comb b x' y' k := by + intro k hk + have hxk := hx ⟨k, rfl⟩ + have hyk := hy ⟨k, rfl⟩ + have hyk' := hy' ⟨k, rfl⟩ + simp only [Set.mem_Icc] at hxk hyk hyk' + have h1 : b * ((x k - 1) + 1) ≤ b * (x' k - 1) := Nat.mul_le_mul_left b (by omega) + simp only [comb] + rw [mul_add, mul_one] at h1 + omega + obtain ⟨i, j, hij, hi, hj⟩ := h + exact ⟨i, j, hij, key i hi, key j hj⟩ + +/-- The product of two `2`-increasing sequences is `2`-increasing. -/ +lemma isIncreasing₂_prodSeq {a b : ℕ} {s t : List (Fin 3 → ℕ)} + (hs : ∀ x ∈ s, Set.range x ⊆ Set.Icc 1 a) (ht : ∀ y ∈ t, Set.range y ⊆ Set.Icc 1 b) + (hs₂ : IsIncreasing₂ s) (ht₂ : IsIncreasing₂ t) : + IsIncreasing₂ (prodSeq b s t) := by + unfold IsIncreasing₂ prodSeq at * + rw [List.pairwise_flatMap] + refine ⟨fun x _ => ?_, ?_⟩ + · rw [List.pairwise_map] + exact ht₂.imp lt₂_comb_right + · refine hs₂.imp_of_mem fun {x x'} hx _ h => ?_ + intro z hz z' hz' + simp only [List.mem_map] at hz hz' + obtain ⟨y, hy, rfl⟩ := hz + obtain ⟨y', hy', rfl⟩ := hz' + exact lt₂_comb_left (hs x hx) (ht y hy) (ht y' hy') h + +/-- Supermultiplicativity: `F(a) F(b) ≤ F(a b)`. -/ +lemma F_mul_le (a b : ℕ) : maximalLength a * maximalLength b ≤ maximalLength (a * b) := by + obtain ⟨s, hs₁, hs₂, hs⟩ := exists_length_eq_F a + obtain ⟨t, ht₁, ht₂, ht⟩ := exists_length_eq_F b + rw [← hs, ← ht, ← length_prodSeq b s t] + exact length_le_F (range_prodSeq hs₁ ht₁) (isIncreasing₂_prodSeq hs₁ ht₁ hs₂ ht₂) + +/-- `F(n) ^ j ≤ F(n ^ j)`. -/ +lemma F_pow_le (n j : ℕ) : maximalLength n ^ j ≤ maximalLength (n ^ j) := by + induction j with + | zero => simp [maximalLength_one] + | succ j ih => + rw [pow_succ, pow_succ] + exact (Nat.mul_le_mul_right _ ih).trans (F_mul_le _ _) + +end MaximalLengthPow + +open MaximalLengthPow in +/-- If `F(n) = n ^ e` for some `n > 1`, then `m ^ e ≤ F(m)` for arbitrarily large `m` +(namely for every power `m = n ^ j`). -/ +theorem maximalLength_pow : type_of% @Arxiv.«1609.08688».maximalLength_pow := by + intro n e hn h + rw [Filter.frequently_atTop] + intro N + refine ⟨n ^ N, (Nat.lt_pow_self hn).le, ?_⟩ + have h1 : ((n ^ N : ℕ) : ℝ) ^ e = (maximalLength n : ℝ) ^ N := by + rw [h, Nat.cast_pow, Real.rpow_pow_comm (Nat.cast_nonneg n)] + rw [h1] + exact_mod_cast F_pow_le n N + +end Math0.Arxiv.«1609.08688» + +#math0_proves Math0.Arxiv.«1609.08688».maximalLength_pow Arxiv.«1609.08688».maximalLength_pow diff --git a/lean/Math0/Arxiv/Arxiv_2602_05192_four_2.lean b/lean/Math0/Arxiv/Arxiv_2602_05192_four_2.lean new file mode 100644 index 0000000..707d2af --- /dev/null +++ b/lean/Math0/Arxiv/Arxiv_2602_05192_four_2.lean @@ -0,0 +1,122 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.Arxiv.«2602.05192».FirstProof4 +import Math0.Audit + +/-! +# First Proof, Problem 4 in degree 2: the finite free Stam inequality is an equality + +Problem 4 of *First Proof* (arXiv:2602.05192) asks whether +`1 / Φ_n(p ⊞_n q) ≥ 1 / Φ_n(p) + 1 / Φ_n(q)` for monic real-rooted polynomials `p, q` of +degree `n`, where `⊞_n` is the finite additive convolution and `Φ_n` is the sum of squared +"Coulomb forces" between the roots (`∞` when there is a repeated root). We prove the upstream +statement `four_2`, the case `n = 2`. Writing `p = (X - a)(X - b)` and `q = (X - c)(X - d)`, a +direct computation gives `p ⊞_2 q = X² - sX + t` with `s = a + b + c + d` and +`t = ab + cd + (a + b)(c + d)/2`, whose discriminant is `(a - b)² + (c - d)²`: discriminants +add. Since `1 / Φ_2((X - x)(X - y)) = (x - y)² / 2` (also when `x = y`, where both sides are `0`), +the inequality holds with equality. +-/ + +open Polynomial Finset ENNReal Arxiv.«2602.05192» + +namespace Math0.Arxiv.«2602.05192» + +/-- The roots of `(X - x)(X - y)` are `{x, y}`. -/ +lemma roots_quad (x y : ℝ) : ((X - C x) * (X - C y)).roots = {x, y} := by + rw [roots_mul (mul_ne_zero (X_sub_C_ne_zero x) (X_sub_C_ne_zero y))] + simp [roots_X_sub_C] + +/-- For a monic quadratic with roots `x, y`, `1 / Φ = (x - y)² / 2`. This includes the case of +a double root, where `Φ = ⊤` and both sides vanish. -/ +lemma inv_Φ_quad (x y : ℝ) : + 1 / Φ ((X - C x) * (X - C y)) = ENNReal.ofReal ((x - y) ^ 2 / 2) := by + unfold Φ + rw [roots_quad] + by_cases h : x = y + · subst h + simp + · have hnd : ({x, y} : Multiset ℝ).Nodup := by simp [h] + rw [if_pos hnd] + have hxy : x - y ≠ 0 := sub_ne_zero.mpr h + have hyx : y - x ≠ 0 := sub_ne_zero.mpr (Ne.symm h) + have hts : ({x, y} : Multiset ℝ).toFinset = {x, y} := by + ext z; simp + simp only [hts] + rw [Finset.sum_pair h] + have e1 : ({x, y} : Finset ℝ).erase x = {y} := by + ext z; simp; aesop + have e2 : ({x, y} : Finset ℝ).erase y = {x} := by + ext z; simp; aesop + rw [e1, e2] + simp only [Finset.sum_singleton] + have hpos : 0 < (x - y) ^ 2 / 2 := by positivity + have : (1 / (x - y)) ^ 2 + (1 / (y - x)) ^ 2 = ((x - y) ^ 2 / 2)⁻¹ := by + field_simp + ring + rw [this, one_div] + change (ENNReal.ofReal _)⁻¹ = _ + rw [← ENNReal.ofReal_inv_of_pos (by positivity), inv_inv] + +/-- A monic real polynomial of degree 2 with two roots (counted with multiplicity) splits as +`(X - a)(X - b)`. -/ +lemma quad_eq (p : ℝ[X]) (hd : p.degree = (2 : ℕ)) (hr : p.roots.card = 2) (hm : p.Monic) : + ∃ a b, p = (X - C a) * (X - C b) := by + have hnat : p.natDegree = 2 := natDegree_eq_of_degree_eq_some hd + have h := prod_multiset_X_sub_C_of_monic_of_roots_card_eq hm (by rw [hr, hnat]) + obtain ⟨a, b, hab⟩ := Multiset.card_eq_two.mp hr + refine ⟨a, b, ?_⟩ + rw [← h, hab] + simp + +/-- The finite additive convolution `⊞_2` of `(X - a)(X - b)` and `(X - c)(X - d)`. -/ +lemma conv_eq (a b c d : ℝ) : + finiteAdditiveConvolution 2 ((X - C a) * (X - C b)) ((X - C c) * (X - C d)) = + X ^ 2 - C (a + b + c + d) * X + C (a * b + c * d + (a + b) * (c + d) / 2) := by + have hp : ∀ x y : ℝ, (X - C x) * (X - C y) = X ^ 2 + C (-(x + y)) * X + C (x * y) := by + intro x y + simp only [map_neg, map_add, map_mul] + ring + have c0 : ∀ x y : ℝ, ((X - C x) * (X - C y)).coeff 0 = x * y := by + intro x y; rw [hp]; simp + have c1 : ∀ x y : ℝ, ((X - C x) * (X - C y)).coeff 1 = -(x + y) := by + intro x y; rw [hp]; simp [coeff_C] + have c2 : ∀ x y : ℝ, ((X - C x) * (X - C y)).coeff 2 = 1 := by + intro x y; rw [hp]; simp + simp only [finiteAdditiveConvolution, sum_range_succ, sum_range_zero] + simp [Finset.Nat.antidiagonal_succ, c0, c1, c2, Nat.factorial] + simp only [smul_eq_C_mul, div_eq_mul_inv, map_add, map_neg, map_mul, mul_one] + ring + +/-- A monic real quadratic `X² - sX + t` with nonnegative discriminant `r = s² - 4t` factors as +`(X - (s + √r)/2)(X - (s - √r)/2)`. -/ +lemma quad_factor (s t r : ℝ) (hr : 0 ≤ r) (h : s ^ 2 - r = 4 * t) : + X ^ 2 - C s * X + C t = (X - C ((s + √r) / 2)) * (X - C ((s - √r) / 2)) := by + have h1 : (s + √r) / 2 + (s - √r) / 2 = s := by ring + have h2 : (s + √r) / 2 * ((s - √r) / 2) = t := by + have := Real.sq_sqrt hr + linear_combination (-1/4 : ℝ) * this + (1/4 : ℝ) * h + calc X ^ 2 - C s * X + C t + = X ^ 2 - C ((s + √r) / 2 + (s - √r) / 2) * X + C ((s + √r) / 2 * ((s - √r) / 2)) := by + rw [h1, h2] + _ = (X - C ((s + √r) / 2)) * (X - C ((s - √r) / 2)) := by + simp only [map_add, map_mul] + ring + +/-- For monic real-rooted quadratics `p, q`, `1/Φ₂(p) + 1/Φ₂(q) ≤ 1/Φ₂(p ⊞₂ q)` +(in fact with equality). -/ +theorem four_2 : type_of% @Arxiv.«2602.05192».four_2 := by + intro p q hpd hpr hqd hqr hpm hqm + obtain ⟨a, b, rfl⟩ := quad_eq p hpd hpr hpm + obtain ⟨c, d, rfl⟩ := quad_eq q hqd hqr hqm + have hD : 0 ≤ (a - b) ^ 2 + (c - d) ^ 2 := by positivity + rw [conv_eq, quad_factor (a + b + c + d) _ ((a - b) ^ 2 + (c - d) ^ 2) hD (by ring), + inv_Φ_quad, inv_Φ_quad, inv_Φ_quad, ← ENNReal.ofReal_add (by positivity) (by positivity)] + apply le_of_eq + congr 1 + have : (√((a - b) ^ 2 + (c - d) ^ 2)) ^ 2 = (a - b) ^ 2 + (c - d) ^ 2 := Real.sq_sqrt hD + linear_combination (-1/2 : ℝ) * this + +end Math0.Arxiv.«2602.05192» + +#math0_proves Math0.Arxiv.«2602.05192».four_2 Arxiv.«2602.05192».four_2 diff --git a/lean/Math0/Arxiv/Arxiv_2605_12342_conjecture_1_variants_rank_3_3.lean b/lean/Math0/Arxiv/Arxiv_2605_12342_conjecture_1_variants_rank_3_3.lean new file mode 100644 index 0000000..4dca649 --- /dev/null +++ b/lean/Math0/Arxiv/Arxiv_2605_12342_conjecture_1_variants_rank_3_3.lean @@ -0,0 +1,222 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.Arxiv.«2605.12342».Conjecture1 +import Math0.Audit + +/-! +# `Γ_{3⊕3}` is not 2-generated + +Fernandes [arXiv:2605.12342] studies `Γ_{m⊕n} ≤ S_m × S_n`, the pairs of permutations with equal +sign, and records that `Γ_{3⊕3}` has rank `3`. We prove exactly the formal statement +`Arxiv.«2605.12342».conjecture_1.variants.rank_3_3`: no two elements generate `Γ_{3⊕3}`. +The group is `(C₃ × C₃) ⋊ C₂` with `C₂` acting by inversion: the even part `A₃ × A₃` is abelian +of exponent `3`, and each odd element `x` is an involution with `x n x⁻¹ = n⁻¹` for even `n` +(checked by `decide` on `S₃`). Two even elements only generate even elements. If `x` is odd, +then `⟨x, y⟩ ⊆ ⟨c⟩ ∪ x⟨c⟩` for an even `c` (namely `y` or `x y`), and its even part +`{1, c, c²}` misses `(ρ, 1)` or `(1, ρ)`, where `ρ` is a 3-cycle. +-/ + +open Arxiv.«2605.12342» Equiv.Perm + +namespace Math0.Arxiv.«2605.12342» + +-- Helpers live in `Rank33` to avoid clashes with sibling files for the same paper. +namespace Rank33 + +/-- Membership in `Γ_{3⊕3}` means the two components have the same sign. -/ +lemma mem_gamma {g : Equiv.Perm (Fin 3) × Equiv.Perm (Fin 3)} : + g ∈ gammaSubgroup 3 3 ↔ sign g.1 = sign g.2 := by + simp only [gammaSubgroup, signDiffHom, MonoidHom.mem_ker, MonoidHom.mul_apply, + MonoidHom.inv_apply, MonoidHom.coe_comp, Function.comp_apply, MonoidHom.coe_fst, + MonoidHom.coe_snd, mul_inv_eq_one] + +/-- The parity homomorphism on `Γ_{3⊕3}`: the sign of the first (equivalently second) +component. -/ +noncomputable def par : gammaSubgroup 3 3 →* ℤˣ := + (sign.comp (MonoidHom.fst _ _)).comp (gammaSubgroup 3 3).subtype + +/-- `par g` is the sign of the first component. -/ +lemma par_apply (g : gammaSubgroup 3 3) : + par g = sign (g : Equiv.Perm (Fin 3) × Equiv.Perm (Fin 3)).1 := rfl + +/-- The second component has the same sign as the first. -/ +lemma sign_snd (g : gammaSubgroup 3 3) : + sign (g : Equiv.Perm (Fin 3) × Equiv.Perm (Fin 3)).2 = par g := + (mem_gamma.1 g.2).symm + +/-- Odd permutations of `Fin 3` are involutions. -/ +lemma perm_sq_of_odd : ∀ a : Equiv.Perm (Fin 3), sign a = -1 → a * a = 1 := by decide + +/-- Even permutations of `Fin 3` have order dividing `3`. -/ +lemma perm_cube_of_even : ∀ a : Equiv.Perm (Fin 3), sign a = 1 → a ^ 3 = 1 := by decide + +/-- Odd permutations of `Fin 3` invert even ones by conjugation. -/ +lemma perm_conj_of_odd : ∀ x n : Equiv.Perm (Fin 3), sign x = -1 → sign n = 1 → + x * n * x⁻¹ = n⁻¹ := by decide + +/-- The 3-cycle `0 ↦ 1 ↦ 2 ↦ 0` used to build the two separating elements. -/ +def rot3 : Equiv.Perm (Fin 3) := finRotate 3 + +/-- For an even pair `c`, the set `{1, c, c²}` cannot contain both `(rot3, 1)` and `(1, rot3)`. -/ +lemma perm_sep : ∀ c : Equiv.Perm (Fin 3) × Equiv.Perm (Fin 3), sign c.1 = 1 → sign c.2 = 1 → + ¬ ((((rot3, 1) : Equiv.Perm (Fin 3) × Equiv.Perm (Fin 3)) = 1 ∨ + (rot3, 1) = c ∨ (rot3, 1) = c ^ 2) ∧ + (((1, rot3) : Equiv.Perm (Fin 3) × Equiv.Perm (Fin 3)) = 1 ∨ + (1, rot3) = c ∨ (1, rot3) = c ^ 2)) := by + unfold rot3 + decide + +/-- Odd elements of `Γ_{3⊕3}` are involutions. -/ +lemma sq_eq_one {g : gammaSubgroup 3 3} (h : par g = -1) : g * g = 1 := by + have h2 := sign_snd g + rw [h] at h2 + rw [par_apply] at h + apply Subtype.ext + ext1 + · exact perm_sq_of_odd _ h + · exact perm_sq_of_odd _ h2 + +/-- Even elements of `Γ_{3⊕3}` have order dividing `3`. -/ +lemma cube_eq_one {g : gammaSubgroup 3 3} (h : par g = 1) : g ^ 3 = 1 := by + have h2 := sign_snd g + rw [h] at h2 + rw [par_apply] at h + apply Subtype.ext + ext1 + · exact perm_cube_of_even _ h + · exact perm_cube_of_even _ h2 + +/-- Odd elements of `Γ_{3⊕3}` invert even ones by conjugation. -/ +lemma conj_eq_inv {x n : gammaSubgroup 3 3} (hx : par x = -1) (hn : par n = 1) : + x * n * x⁻¹ = n⁻¹ := by + have hx2 := sign_snd x + have hn2 := sign_snd n + rw [hx] at hx2 + rw [hn] at hn2 + rw [par_apply] at hx hn + apply Subtype.ext + ext1 + · exact perm_conj_of_odd _ _ hx hn + · exact perm_conj_of_odd _ _ hx2 hn2 + +/-- For `x` odd and `c` even, the set `{c ^ k} ∪ {x * c ^ k}` is a subgroup of `Γ_{3⊕3}`. -/ +def dihedralSub (x c : gammaSubgroup 3 3) (hx : par x = -1) (hc : par c = 1) : + Subgroup (gammaSubgroup 3 3) where + carrier := {g | ∃ k : ℤ, g = c ^ k ∨ g = x * c ^ k} + one_mem' := ⟨0, Or.inl (zpow_zero c).symm⟩ + mul_mem' := by + have hxx : x * x = 1 := sq_eq_one hx + have hcomm : ∀ k : ℤ, c ^ k * x = x * c ^ (-k) := by + intro k + have h1 : x * c ^ (-k) * x⁻¹ = c ^ k := by + rw [← conj_zpow, conj_eq_inv hx hc, inv_zpow', neg_neg] + rw [← h1, mul_assoc, inv_mul_cancel, mul_one] + rintro a b ⟨k, rfl | rfl⟩ ⟨l, rfl | rfl⟩ + · exact ⟨k + l, Or.inl (zpow_add c k l).symm⟩ + · refine ⟨-k + l, Or.inr ?_⟩ + rw [← mul_assoc, hcomm, mul_assoc, zpow_add] + · refine ⟨k + l, Or.inr ?_⟩ + rw [mul_assoc, zpow_add] + · refine ⟨-k + l, Or.inl ?_⟩ + rw [mul_assoc, ← mul_assoc (c ^ k), hcomm, ← mul_assoc, ← mul_assoc, hxx, one_mul, + zpow_add] + inv_mem' := by + have hxx : x * x = 1 := sq_eq_one hx + have hxinv : x⁻¹ = x := inv_eq_of_mul_eq_one_right hxx + have hcomm : ∀ k : ℤ, c ^ k * x = x * c ^ (-k) := by + intro k + have h1 : x * c ^ (-k) * x⁻¹ = c ^ k := by + rw [← conj_zpow, conj_eq_inv hx hc, inv_zpow', neg_neg] + rw [← h1, mul_assoc, inv_mul_cancel, mul_one] + rintro a ⟨k, rfl | rfl⟩ + · exact ⟨-k, Or.inl (zpow_neg c k).symm⟩ + · refine ⟨k, Or.inr ?_⟩ + rw [mul_inv_rev, hxinv, ← zpow_neg, hcomm, neg_neg] + +/-- If `x` is odd, then `x` and any `y` do not generate `Γ_{3⊕3}`. -/ +lemma closure_ne_top_of_odd (x y : gammaSubgroup 3 3) (hx : par x = -1) : + Subgroup.closure {x, y} ≠ ⊤ := by + obtain ⟨c, hc, hy⟩ : ∃ c : gammaSubgroup 3 3, par c = 1 ∧ (y = c ∨ y = x * c) := by + rcases Int.units_eq_one_or (par y) with h | h + · exact ⟨y, h, Or.inl rfl⟩ + · refine ⟨x * y, ?_, Or.inr ?_⟩ + · rw [map_mul, hx, h]; rfl + · rw [← mul_assoc, sq_eq_one hx, one_mul] + intro htop + have hle : Subgroup.closure {x, y} ≤ dihedralSub x c hx hc := by + rw [Subgroup.closure_le] + rintro g (rfl | rfl) + · exact ⟨0, Or.inr (by simp)⟩ + · rcases hy with rfl | rfl + · exact ⟨1, Or.inl (by simp)⟩ + · exact ⟨1, Or.inr (by simp)⟩ + rw [htop] at hle + have key : ∀ g : gammaSubgroup 3 3, par g = 1 → g = 1 ∨ g = c ∨ g = c ^ 2 := by + intro g hg + obtain ⟨k, hk | hk⟩ := hle (Subgroup.mem_top g) + · subst hk + rw [zpow_eq_zpow_emod' k (cube_eq_one hc)] + have : k % ((3 : ℕ) : ℤ) = 0 ∨ k % ((3 : ℕ) : ℤ) = 1 ∨ k % ((3 : ℕ) : ℤ) = 2 := by omega + rcases this with h | h | h <;> rw [h] + · left; simp + · right; left; simp + · right; right; rfl + · subst hk + rw [map_mul, map_zpow, hx, hc, one_zpow, mul_one] at hg + exact absurd hg (by decide) + have hA : ((rot3, 1) : Equiv.Perm (Fin 3) × Equiv.Perm (Fin 3)) ∈ gammaSubgroup 3 3 := + mem_gamma.2 (by unfold rot3; decide) + have hB : ((1, rot3) : Equiv.Perm (Fin 3) × Equiv.Perm (Fin 3)) ∈ gammaSubgroup 3 3 := + mem_gamma.2 (by unfold rot3; decide) + have hrot3 : sign rot3 = 1 := by unfold rot3; decide + have kA := key ⟨_, hA⟩ hrot3 + have kB := key ⟨_, hB⟩ (sign_one : sign (1 : Equiv.Perm (Fin 3)) = 1) + have hc2 := sign_snd c + rw [hc] at hc2 + rw [par_apply] at hc + apply perm_sep _ hc hc2 + constructor + · rcases kA with h | h | h + · left; exact congrArg Subtype.val h + · right; left; exact congrArg Subtype.val h + · right; right; exact congrArg Subtype.val h + · rcases kB with h | h | h + · left; exact congrArg Subtype.val h + · right; left; exact congrArg Subtype.val h + · right; right; exact congrArg Subtype.val h + +/-- If `x` and `y` are both even, they only generate the even part, a proper subgroup. -/ +lemma closure_ne_top_of_even (x y : gammaSubgroup 3 3) (hx : par x = 1) (hy : par y = 1) : + Subgroup.closure {x, y} ≠ ⊤ := by + intro htop + have hle : Subgroup.closure {x, y} ≤ par.ker := by + rw [Subgroup.closure_le] + rintro g (rfl | rfl) + · exact hx + · exact hy + rw [htop] at hle + have hS : ((Equiv.swap 0 1, Equiv.swap 0 1) : Equiv.Perm (Fin 3) × Equiv.Perm (Fin 3)) ∈ + gammaSubgroup 3 3 := mem_gamma.2 rfl + have h := hle (Subgroup.mem_top ⟨_, hS⟩) + rw [MonoidHom.mem_ker, par_apply] at h + exact absurd h (by decide : ¬ sign (Equiv.swap (0 : Fin 3) 1) = 1) + +end Rank33 + +open Rank33 + +/-- **`Γ_{3⊕3}` is not 2-generated** (Fernandes): no two elements of the group of pairs of +permutations of `Fin 3` with equal sign generate it. -/ +theorem rank_3_3 : type_of% @Arxiv.«2605.12342».conjecture_1.variants.rank_3_3 := by + intro h₁ h₂ + rcases Int.units_eq_one_or (par h₁) with e1 | o1 + · rcases Int.units_eq_one_or (par h₂) with e2 | o2 + · exact closure_ne_top_of_even h₁ h₂ e1 e2 + · rw [Set.pair_comm] + exact closure_ne_top_of_odd h₂ h₁ o2 + · exact closure_ne_top_of_odd h₁ h₂ o1 + +end Math0.Arxiv.«2605.12342» + +#math0_proves Math0.Arxiv.«2605.12342».rank_3_3 Arxiv.«2605.12342».conjecture_1.variants.rank_3_3 diff --git a/lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_dimension_three.lean b/lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_dimension_three.lean new file mode 100644 index 0000000..3187199 --- /dev/null +++ b/lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_dimension_three.lean @@ -0,0 +1,219 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.Arxiv.«math.0608009».PoissonConjecture +import Math0.Audit + +/-! +# The Poisson conjecture fails in dimension three + +The Poisson conjecture $PC_n$ of Adjamagbo and van den Essen (arXiv:math/0608009) asserts that +every endomorphism of the canonical Poisson algebra $K[x_1,\dots,x_n,y_1,\dots,y_n]$ over a +field of characteristic zero is an automorphism. We prove exactly the formal statement +`Arxiv.«math.0608009».poisson_conjecture.variants.dimension_three`, i.e. `¬ PC_3`. +The witness is the cotangent (symplectic) lift of the Jacobian-determinant-one, non-injective +polynomial map `G : K³ → K³` recorded in `FormalConjectures.Wikipedia.JacobianConjecture`: +$x_i \mapsto G_i(x)$ and $y_k \mapsto \sum_l A_{kl}(x)\, y_l$, where $A = \operatorname{adj}(JG)$ +is the (polynomial) inverse of the Jacobian matrix. The bracket relations reduce to +$A \cdot JG = 1$ and to an explicit polynomial identity for the entries of $A$ (checked by `ring`). +The lift is not surjective: it identifies the points $(1,0,1,0,0,0)$ and $(0,3,-71,0,0,0)$, which +`x_1` separates, so `x_1` is not in its image. +-/ + +namespace Math0.Arxiv.«math.0608009» + +-- Helpers live in `Dim3` to avoid clashes with sibling files for the same paper. +namespace Dim3 + +open MvPolynomial JacobianConjecture _root_.Arxiv.«math.0608009» + +variable {K : Type*} [Field K] + +/-- The first coordinate of `K³`. -/ +noncomputable abbrev x₀ : MvPolynomial (Fin 3) K := X 0 +/-- The second coordinate of `K³`. -/ +noncomputable abbrev x₁ : MvPolynomial (Fin 3) K := X 1 +/-- The third coordinate of `K³`. -/ +noncomputable abbrev x₂ : MvPolynomial (Fin 3) K := X 2 + +/-- Entry `(0, 0)` of the adjugate of the Jacobian matrix of `G`, in expanded form. -/ +noncomputable def a00 : MvPolynomial (Fin 3) K := + 24 * x₀ ^ 6 * x₁ * x₂ + 72 * x₀ ^ 5 * x₁ ^ 2 + 12 * x₀ ^ 5 * x₂ + 12 * x₀ ^ 4 * x₁ - 8 * x₀ ^ 3 + +/-- Entry `(0, 1)` of the adjugate of the Jacobian matrix of `G`, in expanded form. -/ +noncomputable def a01 : MvPolynomial (Fin 3) K := + 12 * x₀ ^ 4 * x₁ * x₂ + 36 * x₀ ^ 3 * x₁ ^ 2 + 6 * x₀ ^ 3 * x₂ + 6 * x₀ ^ 2 * x₁ - 3 * x₀ + +/-- Entry `(0, 2)` of the adjugate of the Jacobian matrix of `G`, in expanded form. -/ +noncomputable def a02 : MvPolynomial (Fin 3) K := + -72 * x₀ ^ 5 * x₁ * x₂ ^ 2 - 360 * x₀ ^ 4 * x₁ ^ 2 * x₂ - 36 * x₀ ^ 4 * x₂ ^ 2 - 432 * x₀ ^ 3 * x₁ ^ 3 - 120 * x₀ ^ 3 * x₁ * x₂ - 108 * x₀ ^ 2 * x₁ ^ 2 + 18 * x₀ ^ 2 * x₂ + 42 * x₀ * x₁ + 1 + +/-- Entry `(1, 0)` of the adjugate of the Jacobian matrix of `G`, in expanded form. -/ +noncomputable def a10 : MvPolynomial (Fin 3) K := + -24 * x₀ ^ 6 * x₁ ^ 2 * x₂ - 72 * x₀ ^ 5 * x₁ ^ 3 - 24 * x₀ ^ 5 * x₁ * x₂ - 48 * x₀ ^ 4 * x₁ ^ 2 - 6 * x₀ ^ 4 * x₂ + 2 * x₀ ^ 3 * x₁ + 3 * x₀ ^ 2 + +/-- Entry `(1, 1)` of the adjugate of the Jacobian matrix of `G`, in expanded form. -/ +noncomputable def a11 : MvPolynomial (Fin 3) K := + -12 * x₀ ^ 4 * x₁ ^ 2 * x₂ - 36 * x₀ ^ 3 * x₁ ^ 3 - 12 * x₀ ^ 3 * x₁ * x₂ - 24 * x₀ ^ 2 * x₁ ^ 2 - 3 * x₀ ^ 2 * x₂ + 1 + +/-- Entry `(1, 2)` of the adjugate of the Jacobian matrix of `G`, in expanded form. -/ +noncomputable def a12 : MvPolynomial (Fin 3) K := + 72 * x₀ ^ 5 * x₁ ^ 2 * x₂ ^ 2 + 360 * x₀ ^ 4 * x₁ ^ 3 * x₂ + 72 * x₀ ^ 4 * x₁ * x₂ ^ 2 + 432 * x₀ ^ 3 * x₁ ^ 4 + 300 * x₀ ^ 3 * x₁ ^ 2 * x₂ + 18 * x₀ ^ 3 * x₂ ^ 2 + 324 * x₀ ^ 2 * x₁ ^ 3 + 42 * x₀ ^ 2 * x₁ * x₂ + 12 * x₀ * x₁ ^ 2 - 6 * x₀ * x₂ - 16 * x₁ + +/-- Entry `(2, 0)` of the adjugate of the Jacobian matrix of `G`, in expanded form. -/ +noncomputable def a20 : MvPolynomial (Fin 3) K := + 96 * x₀ ^ 6 * x₁ ^ 4 * x₂ + 288 * x₀ ^ 5 * x₁ ^ 5 + 192 * x₀ ^ 5 * x₁ ^ 3 * x₂ + 480 * x₀ ^ 4 * x₁ ^ 4 + 144 * x₀ ^ 4 * x₁ ^ 2 * x₂ + 256 * x₀ ^ 3 * x₁ ^ 3 + 48 * x₀ ^ 3 * x₁ * x₂ + 36 * x₀ ^ 2 * x₁ ^ 2 + 6 * x₀ ^ 2 * x₂ - 6 * x₀ * x₁ - 1 + +/-- Entry `(2, 1)` of the adjugate of the Jacobian matrix of `G`, in expanded form. -/ +noncomputable def a21 : MvPolynomial (Fin 3) K := + 48 * x₀ ^ 4 * x₁ ^ 4 * x₂ + 144 * x₀ ^ 3 * x₁ ^ 5 + 96 * x₀ ^ 3 * x₁ ^ 3 * x₂ + 240 * x₀ ^ 2 * x₁ ^ 4 + 72 * x₀ ^ 2 * x₁ ^ 2 * x₂ + 132 * x₀ * x₁ ^ 3 + 24 * x₀ * x₁ * x₂ + 24 * x₁ ^ 2 + 3 * x₂ + +/-- Entry `(2, 2)` of the adjugate of the Jacobian matrix of `G`, in expanded form. -/ +noncomputable def a22 : MvPolynomial (Fin 3) K := + -288 * x₀ ^ 5 * x₁ ^ 4 * x₂ ^ 2 - 1440 * x₀ ^ 4 * x₁ ^ 5 * x₂ - 576 * x₀ ^ 4 * x₁ ^ 3 * x₂ ^ 2 - 1728 * x₀ ^ 3 * x₁ ^ 6 - 2640 * x₀ ^ 3 * x₁ ^ 4 * x₂ - 432 * x₀ ^ 3 * x₁ ^ 2 * x₂ ^ 2 - 3024 * x₀ ^ 2 * x₁ ^ 5 - 1728 * x₀ ^ 2 * x₁ ^ 3 * x₂ - 144 * x₀ ^ 2 * x₁ * x₂ ^ 2 - 1776 * x₀ * x₁ ^ 4 - 468 * x₀ * x₁ ^ 2 * x₂ - 18 * x₀ * x₂ ^ 2 - 356 * x₁ ^ 3 - 42 * x₁ * x₂ + +/-- The adjugate of the Jacobian matrix of `G`, written out explicitly. -/ +noncomputable def adjG : Fin 3 → Fin 3 → MvPolynomial (Fin 3) K := + ![![a00, a01, a02], ![a10, a11, a12], ![a20, a21, a22]] + +set_option maxHeartbeats 4000000 in +/-- `adjG` is the adjugate of the (upstream) Jacobian matrix of `G`. -/ +theorem adjugate_eq (i j : Fin 3) : (G K).Jacobian.adjugate i j = adjG i j := by + fin_cases i <;> fin_cases j <;> + simp only [G, RegularFunction.Jacobian, Matrix.adjugate_fin_three, Matrix.of_apply, + adjG, a00, a01, a02, a10, a11, a12, a20, a21, a22, + x₀, x₁, x₂, ← map_ofNat (C : K →+* MvPolynomial (Fin 3) K), + Matrix.cons_val', Matrix.cons_val_zero, Matrix.cons_val_one, Matrix.cons_val_two, + Matrix.head_cons, Matrix.tail_cons, map_add, map_neg, Derivation.map_one_eq_zero, + pderiv_mul, pderiv_pow, pderiv_C, pderiv_X_self, pderiv_X_of_ne, ne_eq, Fin.reduceEq, + not_false_eq_true, Fin.zero_eta, Fin.mk_one, Fin.reduceFinMk, Fin.isValue] <;> + simp only [map_ofNat] <;> ring + +/-- Since `det (JG) = 1`, the adjugate is a left inverse of the Jacobian matrix. -/ +theorem adjG_mul (k i : Fin 3) : + ∑ m, adjG k m * pderiv m (G K i) = if k = i then 1 else 0 := by + have h := congrFun (congrFun (Matrix.adjugate_mul (G K).Jacobian) k) i + rw [det_jacobian_G, one_smul, Matrix.mul_apply, Matrix.one_apply] at h + simp only [adjugate_eq] at h + simp only [RegularFunction.Jacobian, Matrix.of_apply] at h + exact h + +set_option maxHeartbeats 4000000 in +/-- The integrability identity that makes the momenta of the lift Poisson-commute. -/ +theorem adjG_comm (k l a : Fin 3) : + ∑ m, (pderiv m (adjG k a : MvPolynomial (Fin 3) K) * adjG l m - + adjG k m * pderiv m (adjG l a)) = 0 := by + fin_cases k <;> fin_cases l <;> fin_cases a <;> + simp only [Fin.sum_univ_three, adjG, a00, a01, a02, a10, a11, a12, a20, a21, a22, + x₀, x₁, x₂, ← map_ofNat (C : K →+* MvPolynomial (Fin 3) K), + Matrix.cons_val', Matrix.cons_val_zero, Matrix.cons_val_one, Matrix.cons_val_two, + Matrix.head_cons, Matrix.tail_cons, map_add, map_neg, map_sub, Derivation.map_one_eq_zero, + pderiv_mul, pderiv_pow, pderiv_C, pderiv_X_self, pderiv_X_of_ne, ne_eq, Fin.reduceEq, + not_false_eq_true, Fin.zero_eta, Fin.mk_one, Fin.reduceFinMk, Fin.isValue] <;> + simp only [map_ofNat] <;> ring + +/-- Polynomials in the position variables do not depend on the momentum variables. -/ +theorem pderiv_inr_rename (m : Fin 3) (f : MvPolynomial (Fin 3) K) : + pderiv (Sum.inr m) (rename (Sum.inl : Fin 3 → Fin 3 ⊕ Fin 3) f) = 0 := by + induction f using MvPolynomial.induction_on with + | C a => simp + | add p q hp hq => simp [hp, hq] + | mul_X p n h => simp [h] + +/-- The `k`-th momentum of the cotangent lift: `∑ l, A k l (x) * y l`. -/ +noncomputable def mom (k : Fin 3) : MvPolynomial (Fin 3 ⊕ Fin 3) K := + ∑ l, rename Sum.inl (adjG k l) * X (Sum.inr l) + +/-- Derivative of a momentum with respect to a momentum variable. -/ +theorem pderiv_inr_mom (m k : Fin 3) : + pderiv (Sum.inr m) (mom k : MvPolynomial (Fin 3 ⊕ Fin 3) K) = + rename Sum.inl (adjG k m) := by + simp [mom, pderiv_inr_rename, pderiv_X, Pi.single_apply] + +/-- Derivative of a momentum with respect to a position variable. -/ +theorem pderiv_inl_mom (m k : Fin 3) : + pderiv (Sum.inl m) (mom k : MvPolynomial (Fin 3 ⊕ Fin 3) K) = + ∑ l, rename Sum.inl (pderiv m (adjG k l)) * X (Sum.inr l) := by + simp [mom, pderiv_rename Sum.inl_injective, mul_comm] + +/-- The images of two position variables Poisson-commute. -/ +theorem bracket_pos_pos (i j : Fin 3) : + poissonBracket (rename Sum.inl (G K i) : MvPolynomial (Fin 3 ⊕ Fin 3) K) + (rename Sum.inl (G K j)) = 0 := by + simp [poissonBracket, pderiv_inr_rename] + +/-- The image of a position variable and the image of a momentum variable are canonically +paired. -/ +theorem bracket_pos_mom (i k : Fin 3) : + poissonBracket (rename Sum.inl (G K i) : MvPolynomial (Fin 3 ⊕ Fin 3) K) (mom k) = + if i = k then 1 else 0 := by + simp only [poissonBracket, pderiv_inr_mom, pderiv_inr_rename, zero_mul, sub_zero, + pderiv_rename Sum.inl_injective, ← map_mul, ← map_sum] + have h := adjG_mul (K := K) k i + simp_rw [mul_comm (pderiv _ (G K i))] + rw [h] + rcases eq_or_ne k i with rfl | hne + · simp + · simp [hne, hne.symm] + +/-- The images of two momentum variables Poisson-commute. -/ +theorem bracket_mom_mom (k l : Fin 3) : + poissonBracket (mom k : MvPolynomial (Fin 3 ⊕ Fin 3) K) (mom l) = 0 := by + simp only [poissonBracket, pderiv_inl_mom, pderiv_inr_mom] + have h := fun a => congrArg (rename (Sum.inl : Fin 3 → Fin 3 ⊕ Fin 3)) (adjG_comm (K := K) k l a) + simp only [map_sum, map_sub, map_mul, map_zero] at h + simp only [Fin.sum_univ_three] at h ⊢ + linear_combination X (Sum.inr 0) * h 0 + X (Sum.inr 1) * h 1 + X (Sum.inr 2) * h 2 + +variable (K) in +/-- The cotangent lift of `G`: `x i ↦ G i (x)`, `y k ↦ ∑ l, A k l (x) * y l`. -/ +noncomputable def lift : + MvPolynomial (Fin 3 ⊕ Fin 3) K →ₐ[K] MvPolynomial (Fin 3 ⊕ Fin 3) K := + aeval (Sum.elim (fun i => rename Sum.inl (G K i)) mom) + +/-- The cotangent lift of `G` preserves the canonical Poisson bracket. -/ +theorem isPoissonEndomorphism_lift : IsPoissonEndomorphism (lift K) := by + intro v w + rcases v with i | k <;> rcases w with j | l + · simp [lift, bracket_pos_pos] + · simp [lift, bracket_pos_mom] + · rw [poissonBracket_swap, poissonBracket_X_inr_inl] + simp only [lift, aeval_X, Sum.elim_inl, Sum.elim_inr, bracket_pos_mom] + rcases eq_or_ne k j with rfl | hne + · simp + · simp [hne, hne.symm] + · simp [lift, bracket_mom_mom] + +/-- The cotangent lift of `G` is not surjective: `x 0` is not in its image. -/ +theorem not_surjective_lift : ¬ Function.Surjective (lift K) := by + intro hs + obtain ⟨f, hf⟩ := hs (X (Sum.inl 0)) + have key : ∀ r : Fin 3 ⊕ Fin 3 → K, + aeval r (lift K f) = aeval (fun v => aeval r (lift K (X v))) f := fun r => by + rw [lift, comp_aeval_apply] + simp + have hpq : (fun v => aeval (Sum.elim ![1, 0, 1] 0 : Fin 3 ⊕ Fin 3 → K) (lift K (X v))) = + (fun v => aeval (Sum.elim ![0, 3, -71] 0 : Fin 3 ⊕ Fin 3 → K) (lift K (X v))) := by + funext v + rcases v with i | k + · simp only [lift, aeval_X, Sum.elim_inl, aeval_rename, Sum.elim_comp_inl] + exact congrFun (aeval_G_eq K) i + · simp [lift, mom] + have h1 := key (Sum.elim ![1, 0, 1] 0) + have h2 := key (Sum.elim ![0, 3, -71] 0) + rw [hf, hpq, ← h2, hf] at h1 + simp at h1 + +end Dim3 + +/-- The Poisson conjecture fails in dimension three: over every field of characteristic zero, +the cotangent lift of the Jacobian-determinant-one map `G` is a non-surjective (hence +non-bijective) endomorphism of the canonical Poisson algebra `P₃(K)`. -/ +theorem poisson_conjecture_dimension_three : + type_of% @Arxiv.«math.0608009».poisson_conjecture.variants.dimension_three := by + intro K _ _ h + exact Dim3.not_surjective_lift (h (Dim3.lift K) Dim3.isPoissonEndomorphism_lift).2 + +end Math0.Arxiv.«math.0608009» + +#math0_proves Math0.Arxiv.«math.0608009».poisson_conjecture_dimension_three Arxiv.«math.0608009».poisson_conjecture.variants.dimension_three diff --git a/lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_jacobian_implication.lean b/lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_jacobian_implication.lean new file mode 100644 index 0000000..f2664f9 --- /dev/null +++ b/lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_jacobian_implication.lean @@ -0,0 +1,130 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.Arxiv.«math.0608009».PoissonConjecture +import Math0.Audit + +/-! +# The Jacobian conjecture in dimension `2n` implies the Poisson conjecture in dimension `n` + +Adjamagbo and van den Essen [AvdE07, Theorems 1 and 7] observed that $JC_{2n}$ implies $PC_n$: +every endomorphism of the canonical Poisson algebra $P_n(K)$ is an automorphism, provided the +Jacobian conjecture holds in $2n$ variables. We prove exactly the formal statement +`Arxiv.«math.0608009».poisson_conjecture.variants.jacobian_implication` from +formal-conjectures. If `φ` preserves the canonical bracket on generators, its Jacobian matrix +`B` (with `B a w = ∂_a φ(X_w)`) satisfies `Bᵀ J B = J` for Mathlib's symplectic form `J`, +so `B` is symplectic and `det B` is a unit. After reindexing the variables by +`Fin (2n) ≃ Fin n ⊕ Fin n`, the Jacobian conjecture provides a polynomial two-sided inverse +`G` of `F = (φ(X_v))_v`; then `bind₁ G` inverts `bind₁ F`, and `φ` is a conjugate of `bind₁ F` +by renaming isomorphisms, hence bijective. The characteristic-zero hypothesis is not used. +-/ + +open MvPolynomial JacobianConjecture Matrix + +namespace Math0.Arxiv.«math.0608009» + +section Helpers + +variable {K : Type*} [Field K] + +/-- The Poisson bracket of the components of a polynomial map is, up to sign, the +congruence of Mathlib's symplectic form `J` by its Jacobian matrix: +`(Bᵀ J B) v w = -{f v, f w}` where `B a w = ∂_a (f w)`. -/ +theorem jacobian_transpose_J_jacobian {n : ℕ} + (f : Fin n ⊕ Fin n → MvPolynomial (Fin n ⊕ Fin n) K) : + (RegularFunction.Jacobian f)ᵀ * Matrix.J (Fin n) (MvPolynomial (Fin n ⊕ Fin n) K) * + RegularFunction.Jacobian f = Matrix.of fun v w => -poissonBracket (f v) (f w) := by + refine Matrix.ext fun v w => ?_ + simp [Matrix.mul_apply, Fintype.sum_sum_type, Matrix.J, RegularFunction.Jacobian, + poissonBracket, Matrix.one_apply, Finset.sum_sub_distrib] + ring + +/-- The Jacobian matrix of the identity map `X` is the identity matrix. -/ +theorem jacobian_X {σ : Type*} [Fintype σ] [DecidableEq σ] : + RegularFunction.Jacobian (X : σ → MvPolynomial σ K) = 1 := by + refine Matrix.ext fun a b => ?_ + simp [RegularFunction.Jacobian, Matrix.one_apply, Pi.single_apply, eq_comm] + +/-- The Jacobian matrix of a Poisson endomorphism is symplectic, so its determinant is a +unit. -/ +theorem isUnit_det_jacobian {n : ℕ} + (φ : MvPolynomial (Fin n ⊕ Fin n) K →ₐ[K] MvPolynomial (Fin n ⊕ Fin n) K) + (hφ : Arxiv.«math.0608009».IsPoissonEndomorphism φ) : + IsUnit (RegularFunction.Jacobian fun v => φ (X v)).det := by + have hmem : (RegularFunction.Jacobian fun v => φ (X v)) ∈ + symplecticGroup (Fin n) (MvPolynomial (Fin n ⊕ Fin n) K) := by + rw [SymplecticGroup.mem_iff', jacobian_transpose_J_jacobian] + have h1 := jacobian_transpose_J_jacobian (K := K) (n := n) X + rw [jacobian_X, transpose_one, Matrix.one_mul, Matrix.mul_one] at h1 + rw [h1] + refine Matrix.ext fun v w => ?_ + simp only [Matrix.of_apply] + rw [hφ v w] + exact SymplecticGroup.symplectic_det hmem + +/-- Transporting a polynomial map along a bijection `e` of the variables transports its +Jacobian matrix by reindexing and renaming. -/ +theorem jacobian_rename {σ τ : Type*} [Fintype σ] [Fintype τ] (e : σ ≃ τ) + (f : τ → MvPolynomial τ K) : + RegularFunction.Jacobian (fun i => rename e.symm (f (e i))) = + ((RegularFunction.Jacobian f).submatrix e e).map (rename e.symm) := by + refine Matrix.ext fun a b => ?_ + simp only [RegularFunction.Jacobian, Matrix.of_apply, Matrix.map_apply, Matrix.submatrix_apply] + have := pderiv_rename (R := K) e.symm.injective (e a) (f (e b)) + simpa using this + +/-- Assuming the Jacobian conjecture in `2n` variables, an algebra endomorphism of +`K[X_v : v ∈ Fin n ⊕ Fin n]` whose Jacobian determinant is a unit is bijective. -/ +theorem bijective_of_jacobianConjecture {n : ℕ} (h : JacobianConjectureProp K (Fin (2 * n))) + (φ : MvPolynomial (Fin n ⊕ Fin n) K →ₐ[K] MvPolynomial (Fin n ⊕ Fin n) K) + (hφ : IsUnit (RegularFunction.Jacobian fun v => φ (X v)).det) : + Function.Bijective φ := by + set e : Fin (2 * n) ≃ Fin n ⊕ Fin n := (finCongr (two_mul n)).trans finSumFinEquiv.symm + set F : RegularFunction K (Fin (2 * n)) (Fin (2 * n)) := fun i => rename e.symm (φ (X (e i))) + have hF : IsUnit F.Jacobian.det := by + have hJ : F.Jacobian = _ := jacobian_rename e (fun v => φ (X v)) + have hd := RingHom.map_det + ((rename e.symm : MvPolynomial (Fin n ⊕ Fin n) K →ₐ[K] MvPolynomial (Fin (2 * n)) K) : + MvPolynomial (Fin n ⊕ Fin n) K →+* MvPolynomial (Fin (2 * n)) K) + ((RegularFunction.Jacobian fun v => φ (X v)).submatrix e e) + rw [RingHom.mapMatrix_apply, det_submatrix_equiv_self] at hd + rw [hJ] + convert hφ.map + (rename e.symm : MvPolynomial (Fin n ⊕ Fin n) K →ₐ[K] MvPolynomial (Fin (2 * n)) K) + exact hd.symm + obtain ⟨G, hGF, hFG⟩ := h F hF + have h1 : (bind₁ G).comp (bind₁ F) = AlgHom.id K _ := by + rw [bind₁_comp_bind₁] + have : (fun i => bind₁ G (F i)) = X := hGF + rw [this, bind₁_X_left] + have h2 : (bind₁ F).comp (bind₁ G) = AlgHom.id K _ := by + rw [bind₁_comp_bind₁] + have : (fun i => bind₁ F (G i)) = X := hFG + rw [this, bind₁_X_left] + have hbF : Function.Bijective (bind₁ F) := by + refine Function.bijective_iff_has_inverse.mpr ⟨bind₁ G, fun p => ?_, fun p => ?_⟩ + · exact congrArg + (fun ψ : MvPolynomial (Fin (2 * n)) K →ₐ[K] MvPolynomial (Fin (2 * n)) K => ψ p) h1 + · exact congrArg + (fun ψ : MvPolynomial (Fin (2 * n)) K →ₐ[K] MvPolynomial (Fin (2 * n)) K => ψ p) h2 + have hφeq : φ = (rename e).comp ((bind₁ F).comp (rename e.symm)) := by + apply MvPolynomial.algHom_ext + intro v + simp [F, rename_rename] + rw [hφeq] + exact (renameEquiv K e).bijective.comp (hbF.comp (renameEquiv K e.symm).bijective) + +end Helpers + +/-- The Jacobian conjecture in dimension `2n` implies the Poisson conjecture in dimension `n` +([AvdE07], Theorems 1 and 7): if every polynomial self-map of `K^(2n)` with unit Jacobian +determinant has a polynomial inverse, then every endomorphism of the canonical Poisson algebra +`P_n(K)` is bijective. -/ +theorem jacobian_implication : + type_of% @Arxiv.«math.0608009».poisson_conjecture.variants.jacobian_implication := by + intro K _ _ n h φ hφ + exact bijective_of_jacobianConjecture h φ (isUnit_det_jacobian φ hφ) + +end Math0.Arxiv.«math.0608009» + +#math0_proves Math0.Arxiv.«math.0608009».jacobian_implication Arxiv.«math.0608009».poisson_conjecture.variants.jacobian_implication diff --git a/lean/Math0/Audit.lean b/lean/Math0/Audit.lean new file mode 100644 index 0000000..1e0cc98 --- /dev/null +++ b/lean/Math0/Audit.lean @@ -0,0 +1,130 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Lean + +/-! +# Audit commands + +Every result in math0 is checked by two commands, which fail the build on any problem. + +* `#math0_audit foo` fails unless the axioms used by `foo` are among `propext`, + `Classical.choice` and `Quot.sound`. In particular it rejects `sorryAx`, + `Lean.ofReduceBool` / `Lean.trustCompiler` (from `native_decide`), and custom axioms. +* `#math0_proves foo bar` fails unless the type of `foo` is syntactically identical to the type + of `bar` (the published upstream statement), and `#math0_refutes foo bar` fails unless the + type of `foo` is exactly `¬` (type of `bar`). The comparison is up to metadata annotations and + nothing else: no unfolding, no defeq. +-/ + +namespace Math0.Audit + +open Lean Elab Command Meta + +/-- The only axioms a math0 result may depend on. -/ +def permittedAxioms : List Name := [``propext, ``Classical.choice, ``Quot.sound] + +/-- Remove every `mdata` node, so that annotations do not affect comparisons. -/ +partial def stripMData : Expr → Expr + | .mdata _ e => stripMData e + | .app f a => .app (stripMData f) (stripMData a) + | .lam n t b bi => .lam n (stripMData t) (stripMData b) bi + | .forallE n t b bi => .forallE n (stripMData t) (stripMData b) bi + | .letE n t v b nd => .letE n (stripMData t) (stripMData v) (stripMData b) nd + | .proj s i e => .proj s i (stripMData e) + | e => e + +/-- Fail unless `n` depends only on the permitted axioms. -/ +def auditAxioms (n : Name) : CommandElabM Unit := do + let axioms ← liftCoreM <| collectAxioms n + let bad := axioms.filter (· ∉ permittedAxioms) + unless bad.isEmpty do + throwError "math0 audit failed: '{n}' depends on non-permitted axioms {bad.toList}" + logInfo m!"math0 audit: '{n}' depends on axioms {axioms.toList.mergeSort (·.toString < ·.toString)}" + +elab "#math0_audit " id:ident : command => do + let n ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo id + auditAxioms n + +/-- Fail unless `ours` has exactly the type `f theirs.type` and the same universe parameters. -/ +def checkStatement (ours theirs : Name) (f : Expr → Expr) (verb : String) : CommandElabM Unit := do + let o ← getConstInfo ours + let t ← getConstInfo theirs + unless o.levelParams == t.levelParams do + throwError "math0 statement check failed: universe parameters differ for '{ours}' and '{theirs}'" + unless stripMData o.type == f (stripMData t.type) do + throwError "math0 statement check failed: '{ours}' does not {verb} '{theirs}'.\n\ + ours: {o.type}\ntheirs: {t.type}" + auditAxioms ours + logInfo m!"math0 statement check: '{ours}' {verb}s '{theirs}'" + +elab "#math0_proves " ours:ident ppSpace theirs:ident : command => do + let o ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo ours + let t ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo theirs + checkStatement o t id "prove" + +elab "#math0_refutes " ours:ident ppSpace theirs:ident : command => do + let o ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo ours + let t ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo theirs + checkStatement o t mkNot "refute" + +/-- For a value question: the upstream statement mentions an unknown `theirAns` (declared upstream +as `def theirAns : T := sorry`). `ours` must have exactly the upstream type with every occurrence +of the constant `theirAns` replaced by the constant `ourAns`, which must not depend on `sorryAx`. -/ +elab "#math0_answers " ours:ident ppSpace theirs:ident " with " theirAns:ident " := " ourAns:ident : + command => do + let o ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo ours + let t ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo theirs + let ta ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo theirAns + let oa ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo ourAns + auditAxioms oa + checkStatement o t (fun e => e.replace fun + | .const n us => if n == ta then some (.const oa us) else none + | _ => none) "answer" + +/-- Misformalization reports for value questions: `ours` must have exactly the type +`∀ a, ¬ (upstream type with the unknown `theirAns` replaced by `a`)`, i.e. the upstream statement +is false whatever value is chosen for its unknown. -/ +elab "#math0_refutes_every_answer " ours:ident ppSpace theirs:ident " with " theirAns:ident : + command => do + let o ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo ours + let t ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo theirs + let ta ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo theirAns + let oi ← getConstInfo o + let ti ← getConstInfo t + let ai ← getConstInfo ta + unless oi.levelParams == ti.levelParams && ai.levelParams.isEmpty do + throwError "math0 statement check failed: universe parameters differ or the unknown is polymorphic" + let expected ← liftTermElabM do + withLocalDeclD `a ai.type fun a => do + let body := (stripMData ti.type).replace fun + | .const n _ => if n == ta then some a else none + | _ => none + mkForallFVars #[a] (mkNot body) + unless stripMData oi.type == stripMData expected do + throwError "math0 statement check failed: '{o}' does not refute '{t}' for every value of '{ta}'.\n\ + ours: {oi.type}\nexpected: {expected}" + auditAxioms o + logInfo m!"math0 statement check: '{o}' refutes '{t}' for every value of '{ta}'" + +/-- For statements that math0 formalizes itself (they live in `Math0/Statements/`, each a +`def statement : Prop` written and reviewed before any proof attempt): `ours` must have type exactly +`stmt` or exactly `¬ stmt`, and both `stmt` and `ours` must use only the permitted axioms (so the +statement cannot hide a `sorry`). -/ +elab "#math0_settles " ours:ident ppSpace stmt:ident : command => do + let o ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo ours + let s ← liftCoreM <| realizeGlobalConstNoOverloadWithInfo stmt + let si ← getConstInfo s + unless si.levelParams.isEmpty && stripMData si.type == .sort .zero do + throwError "math0 statement check failed: '{s}' must be a universe-monomorphic definition of type Prop" + unless si matches .defnInfo _ do + throwError "math0 statement check failed: '{s}' must be a definition" + auditAxioms s + let ty := stripMData (← getConstInfo o).type + let verb ← if ty == .const s [] then pure "proves" + else if ty == mkNot (.const s []) then pure "refutes" + else throwError "math0 statement check failed: the type of '{o}' is neither '{s}' nor '¬ {s}'" + auditAxioms o + logInfo m!"math0 statement check: '{o}' {verb} '{s}'" + +end Math0.Audit diff --git a/lean/Math0/Books/Bugeaud06_problem_10_6_variant_1.lean b/lean/Math0/Books/Bugeaud06_problem_10_6_variant_1.lean new file mode 100644 index 0000000..d137587 --- /dev/null +++ b/lean/Math0/Books/Bugeaud06_problem_10_6_variant_1.lean @@ -0,0 +1,396 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.Books.BugeaudDistributionModuloOne.Problem10_6 +import Math0.Audit + +/-! +# A sequence with ratio floor `1 + c / log n`, dense mod one for all irrationals (Bugeaud 10.6) + +Bugeaud (*Distribution modulo one and Diophantine approximation*, Problem 10.6) asks for a +"very rapidly increasing" sequence `(m_n)` of positive integers such that `({ξ m_n})` is dense +modulo one for every irrational `ξ`. We prove exactly the formal statement +`Bugeaud06.problem_10_6_variant_1`, which reads "very rapidly increasing" as: `m` is strictly +increasing and `m (n+1) / m n ≥ 1 + c / log n` eventually, for some `c > 0`. +The witness enumerates the set of all powers of two together with blocks +`B_k = {A + r W + (D + r) j : r, j < K}` with `K = 2^k`, `D = 2^(2^(4^k))`, `W = 2 D K`, +`A = K W` (a power of two). Inside `[A, 2A)` all gaps are `≥ D = A / (2 K^2)`, and because the +powers of two are in the set, an element `≥ A` has index `≥ log₂ A ≥ 2^(4^k)`, so +`D / (2A) = 1 / (4 · 4^k)` beats `(1/8) / log n`. Density: by Dirichlet and a stepping +argument we pick `r < K` with `ξ (D + r) ≡ s (mod 1)`, `s ∈ [η/2, η]`; then the `K` points +`ξ (A + r W) + j s` walk around the circle with steps `s ≤ η` and hit any interval of length `η`. +-/ + +namespace Math0.Bugeaud06 + +open Filter + +/-- The exponent `M k = 2 ^ (4 ^ k)` fixing the scale of block `k`. -/ +def bM (k : ℕ) : ℕ := 2 ^ (4 ^ k) + +/-- The side length `K k = 2 ^ k` of block `k`. -/ +def bK (k : ℕ) : ℕ := 2 ^ k + +/-- The base difference `D k = 2 ^ M k` of block `k`. -/ +def bD (k : ℕ) : ℕ := 2 ^ bM k + +/-- The spacing `W k = 2 D K` between the sub-progressions of block `k`. -/ +def bW (k : ℕ) : ℕ := 2 * bD k * bK k + +/-- The starting point `A k = K W` of block `k`. -/ +def bA (k : ℕ) : ℕ := bK k * bW k + +/-- The dyadic level of block `k`: `A k = 2 ^ L k`. -/ +def bL (k : ℕ) : ℕ := bM k + 2 * k + 1 + +/-- The element of block `k` with parameters `r, j`. -/ +def elt (k r j : ℕ) : ℕ := bA k + r * bW k + (bD k + r) * j + +/-- The set: all powers of two, together with all block elements. -/ +def S : Set ℕ := + {x | (∃ i, x = 2 ^ i) ∨ ∃ k r j, r < bK k ∧ j < bK k ∧ x = elt k r j} + +/-- The sequence enumerating `S` increasingly. -/ +noncomputable def seq : ℕ → ℕ := Nat.nth (· ∈ S) + +/-- The side length is at most the base difference: `K k ≤ D k`. -/ +lemma bK_le_bD (k : ℕ) : bK k ≤ bD k := by + unfold bK bD bM + refine Nat.pow_le_pow_right (by norm_num) ?_ + calc k ≤ 2 ^ k := (Nat.lt_two_pow_self).le + _ ≤ 2 ^ (4 ^ k) := Nat.pow_le_pow_right (by norm_num) + ((Nat.lt_two_pow_self).le.trans (Nat.pow_le_pow_left (by norm_num : 2 ≤ 4) k)) + +/-- The base difference is positive. -/ +lemma bD_pos (k : ℕ) : 0 < bD k := by unfold bD; positivity + +/-- The side length is positive. -/ +lemma bK_pos (k : ℕ) : 0 < bK k := by unfold bK; positivity + +/-- The starting point of block `k` is the power of two `2 ^ L k`. -/ +lemma bA_eq (k : ℕ) : bA k = 2 ^ bL k := by + unfold bA bW bD bK bL; ring + +/-- `2 A = 4 D · 4^k`, i.e. `D / (2 A) = 1 / (4 · 4^k)`. -/ +lemma bA_eq' (k : ℕ) : 2 * bA k = 4 * bD k * 4 ^ k := by + unfold bA bW bK + have : (4 : ℕ) ^ k = 2 ^ k * 2 ^ k := by rw [← mul_pow]; norm_num + rw [this]; ring + +/-- The key inequality `(D + r) j + D ≤ W` for `r, j < K`: a sub-progression plus one gap +fits below the next sub-progression. -/ +lemma key_bound {k r j : ℕ} (hr : r < bK k) (hj : j < bK k) : + (bD k + r) * j + bD k ≤ bW k := by + have h1 := bK_le_bD k + have h2 : (bD k + r) * (j + 1) ≤ (bD k + bK k) * bK k := + Nat.mul_le_mul (by omega) (by omega) + have h3 : (bD k + bK k) * bK k ≤ 2 * bD k * bK k := by + nlinarith + unfold bW + nlinarith + +/-- Every element of block `k` is at least its starting point `A k`. -/ +lemma elt_ge {k r j : ℕ} : bA k ≤ elt k r j := by + unfold elt; omega + +/-- Every element of block `k` stays at distance `≥ D` below `2 A`. -/ +lemma elt_add_le {k r j : ℕ} (hr : r < bK k) (hj : j < bK k) : + elt k r j + bD k ≤ 2 * bA k := by + have h := key_bound hr hj + have h2 : (r + 1) * bW k ≤ bK k * bW k := Nat.mul_le_mul_right _ hr + unfold elt bA + nlinarith + +/-- Two elements of the same block differ by at least `D`. -/ +lemma within_gap {k r j r' j' : ℕ} (hr : r < bK k) (hj : j < bK k) (hr' : r' < bK k) + (hj' : j' < bK k) (h : elt k r j < elt k r' j') : elt k r j + bD k ≤ elt k r' j' := by + have key := key_bound hr hj + have key' := key_bound hr' hj' + have hD := bD_pos k + unfold elt at * + rcases lt_trichotomy r r' with h1 | rfl | h1 + · have : (r + 1) * bW k ≤ r' * bW k := Nat.mul_le_mul_right _ h1 + nlinarith + · have h2 : j < j' := by + by_contra h3 + have : (bD k + r) * j' ≤ (bD k + r) * j := Nat.mul_le_mul_left _ (by omega) + omega + have : (bD k + r) * (j + 1) ≤ (bD k + r) * j' := Nat.mul_le_mul_left _ h2 + nlinarith + · have : (r' + 1) * bW k ≤ r * bW k := Nat.mul_le_mul_right _ h1 + nlinarith + +/-- The dyadic levels of distinct blocks are separated: `L k + 1 ≤ L k'` for `k < k'`. -/ +lemma bL_lt {k k' : ℕ} (h : k < k') : bL k + 1 ≤ bL k' := by + have : bM k ≤ bM k' := by + unfold bM + exact Nat.pow_le_pow_right (by norm_num) (Nat.pow_le_pow_right (by norm_num) h.le) + unfold bL + omega + +/-- `2 A k = 2 ^ (L k + 1)`. -/ +lemma two_mul_bA (k : ℕ) : 2 * bA k = 2 ^ (bL k + 1) := by + rw [bA_eq, pow_succ]; ring + +/-- Gap after a block element. -/ +lemma gap_block {k r j y : ℕ} (hr : r < bK k) (hj : j < bK k) (hy : y ∈ S) + (h : elt k r j < y) : elt k r j + bD k ≤ y := by + have hge := @elt_ge k r j + have hle := elt_add_le hr hj + rcases hy with ⟨i, rfl⟩ | ⟨k', r', j', hr', hj', rfl⟩ + · rcases Nat.lt_or_ge (bL k) i with hi | hi + · have : 2 ^ (bL k + 1) ≤ 2 ^ i := Nat.pow_le_pow_right (by norm_num) hi + rw [two_mul_bA] at hle + omega + · have : 2 ^ i ≤ 2 ^ bL k := Nat.pow_le_pow_right (by norm_num) hi + rw [bA_eq] at hge + omega + · have hge' := @elt_ge k' r' j' + have hle' := elt_add_le hr' hj' + rcases lt_trichotomy k k' with hk | rfl | hk + · have := bL_lt hk + have : 2 ^ (bL k + 1) ≤ 2 ^ bL k' := Nat.pow_le_pow_right (by norm_num) this + rw [two_mul_bA] at hle + rw [bA_eq] at hge' + omega + · exact within_gap hr hj hr' hj' h + · have := bL_lt hk + have : 2 ^ (bL k' + 1) ≤ 2 ^ bL k := Nat.pow_le_pow_right (by norm_num) this + rw [two_mul_bA] at hle' + rw [bA_eq] at hge + omega + +/-- Gap after a power of two that is not the start of a block. -/ +lemma gap_filler {i y : ℕ} (hi : ∀ k, i ≠ bL k) (hy : y ∈ S) (h : 2 ^ i < y) : + 2 * 2 ^ i ≤ y := by + rcases hy with ⟨i', rfl⟩ | ⟨k, r, j, hr, hj, rfl⟩ + · have : i < i' := (Nat.pow_lt_pow_iff_right (by norm_num)).1 h + have : 2 ^ (i + 1) ≤ 2 ^ i' := Nat.pow_le_pow_right (by norm_num) this + rw [pow_succ] at this + omega + · have hge := @elt_ge k r j + have hle := elt_add_le hr hj + rw [two_mul_bA] at hle + have h1 : 2 ^ i < 2 ^ (bL k + 1) := by omega + have h2 : i < bL k + 1 := (Nat.pow_lt_pow_iff_right (by norm_num)).1 h1 + have h3 : i + 1 ≤ bL k := by have := hi k; omega + have : 2 ^ (i + 1) ≤ 2 ^ bL k := Nat.pow_le_pow_right (by norm_num) h3 + rw [pow_succ, ← bA_eq] at this + omega + +/-- Every element of `S` is a block element, or a power of two not at a block level. -/ +lemma S_cases {x : ℕ} (hx : x ∈ S) : + (∃ k r j, r < bK k ∧ j < bK k ∧ x = elt k r j) ∨ (∃ i, x = 2 ^ i ∧ ∀ k, i ≠ bL k) := by + rcases hx with ⟨i, rfl⟩ | h + · by_cases hi : ∃ k, i = bL k + · obtain ⟨k, rfl⟩ := hi + left + refine ⟨k, 0, 0, bK_pos k, bK_pos k, ?_⟩ + simp [elt, bA_eq] + · push Not at hi + exact Or.inr ⟨i, rfl, hi⟩ + · exact Or.inl h + +/-- `S` is infinite, since it contains every power of two. -/ +lemma S_infinite : (Set.ofPred (· ∈ S)).Infinite := by + have : Set.range (fun i : ℕ => 2 ^ i) ⊆ Set.ofPred (· ∈ S) := by + rintro _ ⟨i, rfl⟩ + exact Or.inl ⟨i, rfl⟩ + exact Set.Infinite.mono this + (Set.infinite_range_of_injective (Nat.pow_right_injective le_rfl)) + +/-- The enumeration of `S` is strictly increasing. -/ +lemma seq_strictMono : StrictMono seq := Nat.nth_strictMono S_infinite + +/-- Every term of the enumeration lies in `S`. -/ +lemma seq_mem (n : ℕ) : seq n ∈ S := Nat.nth_mem_of_infinite S_infinite n + +/-- The range of the enumeration is exactly `S`. -/ +lemma range_seq : Set.range seq = S := Nat.range_nth_of_infinite S_infinite + +/-- Index bound: `seq n ≤ 2 ^ n`, because `1, 2, ..., 2 ^ n` are `n + 1` elements of `S`. -/ +lemma seq_le_pow (n : ℕ) : seq n ≤ 2 ^ n := by + have hmem : ∀ i, 2 ^ i ∈ Set.range seq := fun i => by + rw [range_seq]; exact Or.inl ⟨i, rfl⟩ + choose f hf using hmem + have hfm : StrictMono f := fun i i' h => by + rw [← seq_strictMono.lt_iff_lt, hf, hf] + exact Nat.pow_lt_pow_right (by norm_num) h + calc seq n ≤ seq (f n) := seq_strictMono.monotone (hfm.id_le n) + _ = 2 ^ n := hf n + +/-- All terms are positive. -/ +lemma seq_pos (n : ℕ) : 0 < seq n := by + rcases seq_mem n with ⟨i, h⟩ | ⟨k, r, j, -, -, h⟩ + · rw [h]; positivity + · rw [h]; have := @elt_ge k r j; rw [bA_eq] at this + have : 0 < 2 ^ bL k := by positivity + omega + +/-- The ratio floor: `seq (n+1) / seq n ≥ 1 + (1/8) / log n` for all `n ≥ 2`. -/ +lemma sublacunary : _root_.Bugeaud06.IsGenuinelySublacunary seq := by + refine ⟨1 / 8, by norm_num, ?_⟩ + filter_upwards [eventually_ge_atTop 2] with n hn + have hxy : seq n < seq (n + 1) := seq_strictMono (Nat.lt_succ_self n) + have hy := seq_mem (n + 1) + have hxpos : (0 : ℝ) < seq n := by exact_mod_cast seq_pos n + have hn2 : (2 : ℝ) ≤ n := by exact_mod_cast hn + have hlog2 := Real.log_two_gt_d9 + have hlogn : Real.log 2 ≤ Real.log n := Real.log_le_log (by norm_num) hn2 + have hlpos : 0 < Real.log n := by linarith + rw [le_div_iff₀ hxpos] + rcases S_cases (seq_mem n) with ⟨k, r, j, hr, hj, hx⟩ | ⟨i, hx, hi⟩ + · have hgap := gap_block hr hj hy (hx ▸ hxy) + rw [← hx] at hgap + have hle := elt_add_le hr hj + rw [← hx, bA_eq'] at hle + have hge := @elt_ge k r j + rw [← hx, bA_eq] at hge + -- index bound + have hL : bL k ≤ n := by + have := hge.trans (seq_le_pow n) + exact (Nat.pow_le_pow_iff_right (by norm_num)).1 this + have hM : 2 ^ (4 ^ k) ≤ n := by + have : bM k ≤ bL k := by unfold bL; omega + unfold bM at this + omega + have hMR : (2 : ℝ) ^ (4 ^ k) ≤ n := by exact_mod_cast hM + have hlog : (4 : ℝ) ^ k * Real.log 2 ≤ Real.log n := by + have := Real.log_le_log (by positivity) hMR + rw [Real.log_pow] at this + push_cast at this + exact this + have hgapR : (seq n : ℝ) + bD k ≤ seq (n + 1) := by exact_mod_cast hgap + have hleR : (seq n : ℝ) + bD k ≤ 4 * bD k * 4 ^ k := by exact_mod_cast hle + have hDpos : (0 : ℝ) < bD k := by exact_mod_cast bD_pos k + have h4 : (0 : ℝ) < 4 ^ k := by positivity + have hlog' : (4 : ℝ) ^ k / 2 ≤ Real.log n := by nlinarith + have hkey : 1 / 8 / Real.log n * seq n ≤ bD k := by + rw [div_div, div_mul_eq_mul_div, one_mul, div_le_iff₀ (by positivity)] + nlinarith [mul_le_mul_of_nonneg_left hlog' hDpos.le] + nlinarith + · have hgap := gap_filler hi hy (hx ▸ hxy) + rw [← hx] at hgap + have hgapR : 2 * (seq n : ℝ) ≤ seq (n + 1) := by exact_mod_cast hgap + have : 1 / 8 / Real.log n ≤ 1 := by + rw [div_le_one hlpos]; linarith + nlinarith + +/-- Stepping lemma, positive step. -/ +lemma step_pos {δ η u a : ℝ} (hδ : 0 < δ) (hδη : δ ≤ η) {N : ℕ} (hN : 1 ≤ N * δ) : + ∃ j : ℕ, j ≤ N ∧ ∃ z : ℤ, a ≤ u + j * δ + z ∧ u + j * δ + z ≤ a + η := by + have hw0 : 0 ≤ Int.fract (a - u) := Int.fract_nonneg _ + have hw1 : Int.fract (a - u) < 1 := Int.fract_lt_one _ + have hfl := Int.floor_add_fract (a - u) + refine ⟨⌈Int.fract (a - u) / δ⌉₊, ?_, ⌊a - u⌋, ?_, ?_⟩ + · apply Nat.ceil_le.2 + rw [div_le_iff₀ hδ] + linarith + · have h1 := Nat.le_ceil (Int.fract (a - u) / δ) + rw [div_le_iff₀ hδ] at h1 + linarith + · have h2 := Nat.ceil_lt_add_one (div_nonneg hw0 hδ.le) + have h3 := mul_lt_mul_of_pos_right h2 hδ + rw [add_mul, div_mul_cancel₀ _ hδ.ne'] at h3 + linarith + +/-- Stepping lemma, step of either sign. -/ +lemma step_any {δ η u a : ℝ} (hδ : δ ≠ 0) (hδη : |δ| ≤ η) {N : ℕ} (hN : 1 ≤ N * |δ|) : + ∃ j : ℕ, j ≤ N ∧ ∃ z : ℤ, a ≤ u + j * δ + z ∧ u + j * δ + z ≤ a + η := by + rcases lt_or_gt_of_ne hδ with h | h + · rw [abs_of_neg h] at hδη hN + obtain ⟨j, hj, z, h1, h2⟩ := + step_pos (u := -u) (a := -a - η) (neg_pos.2 h) hδη hN + refine ⟨j, hj, -z, ?_, ?_⟩ <;> push_cast <;> linarith + · rw [abs_of_pos h] at hδη hN + exact step_pos h hδη hN + +/-- For irrational `ξ`, every open interval `(a, b)` contains some `ξ x + z` with `x ∈ S`, `z ∈ ℤ`. -/ +lemma dense_aux (ξ : ℝ) (hξ : Irrational ξ) (a b : ℝ) (hab : a < b) : + ∃ x ∈ S, ∃ z : ℤ, a < ξ * x + z ∧ ξ * x + z < b := by + obtain ⟨η, hη⟩ : ∃ η : ℝ, η = (b - a) / 2 := ⟨_, rfl⟩ + have hηpos : 0 < η := by rw [hη]; linarith + -- Dirichlet's theorem gives a small nonzero `δ = q ξ - round (q ξ)`. + obtain ⟨n0, hn0⟩ : ∃ n0 : ℕ, n0 = ⌈2 / η⌉₊ + 1 := ⟨_, rfl⟩ + obtain ⟨q, hq0, -, hq⟩ := Real.exists_nat_abs_mul_sub_round_le ξ (n := n0) (by omega) + obtain ⟨R, hR⟩ : ∃ R : ℤ, R = round ((q : ℝ) * ξ) := ⟨_, rfl⟩ + rw [← hR] at hq + obtain ⟨δ, hδ⟩ : ∃ δ : ℝ, δ = (q : ℝ) * ξ - R := ⟨_, rfl⟩ + rw [← hδ] at hq + have hδ0 : δ ≠ 0 := by + have hirr : Irrational ((q : ℝ) * ξ) := hξ.natCast_mul (by omega) + have := hirr.ne_int R + intro h; apply this; rw [hδ] at h; linarith + have hδη : |δ| ≤ η / 2 := by + refine hq.trans ?_ + rw [div_le_iff₀ (by positivity)] + have h1 := Nat.le_ceil (2 / η) + have h2 : (n0 : ℝ) = ⌈2 / η⌉₊ + 1 := by rw [hn0]; push_cast; ring + rw [h2] + have h3 : 2 / η * (η / 2) = 1 := by field_simp + nlinarith + have hδpos : 0 < |δ| := abs_pos.2 hδ0 + obtain ⟨N1, hN1⟩ : ∃ N1 : ℕ, N1 = ⌈1 / |δ|⌉₊ := ⟨_, rfl⟩ + have hN1' : 1 ≤ (N1 : ℝ) * |δ| := by + have := Nat.le_ceil (1 / |δ|) + rw [div_le_iff₀ hδpos, ← hN1] at this + exact this + obtain ⟨N2, hN2⟩ : ∃ N2 : ℕ, N2 = ⌈2 / η⌉₊ := ⟨_, rfl⟩ + -- the block we use + obtain ⟨k, hk⟩ : ∃ k : ℕ, k = N1 * q + N2 := ⟨_, rfl⟩ + have hKk : k < bK k := Nat.lt_two_pow_self + -- first step: choose `r` with `ξ (D + r)` close to a small positive number mod 1 + obtain ⟨j1, hj1, z1, h1a, h1b⟩ := + step_any (u := ξ * (bD k : ℝ)) (a := η / 2) hδ0 hδη hN1' + have hrK : j1 * q < bK k := by + have : j1 * q ≤ N1 * q := Nat.mul_le_mul_right _ hj1 + omega + obtain ⟨s, hs⟩ : ∃ s : ℝ, s = ξ * (bD k : ℝ) + j1 * δ + z1 := ⟨_, rfl⟩ + rw [← hs] at h1a h1b + have hspos : 0 < s := by linarith + have hsη : s ≤ η := by linarith + have hN2s : 1 ≤ (N2 : ℝ) * s := by + have h1 := Nat.le_ceil (2 / η) + rw [← hN2] at h1 + have h2 : 2 / η * (η / 2) = 1 := by field_simp + nlinarith + -- second step: walk along the progression with difference `D + r` + obtain ⟨j2, hj2, z2, h2a, h2b⟩ := + step_pos (u := ξ * ((bA k : ℝ) + (j1 * q : ℕ) * bW k)) (a := a + η / 2) hspos hsη hN2s + have hjK : j2 < bK k := by omega + have hid : ξ * (elt k (j1 * q) j2 : ℝ) + ((z2 + j2 * (z1 - j1 * R) : ℤ) : ℝ) = + ξ * ((bA k : ℝ) + (j1 * q : ℕ) * bW k) + j2 * s + z2 := by + rw [hs, hδ]; simp only [elt]; push_cast; ring + refine ⟨elt k (j1 * q) j2, Or.inr ⟨k, j1 * q, j2, hrK, hjK, rfl⟩, + z2 + j2 * (z1 - j1 * R), ?_, ?_⟩ + · rw [hid]; linarith + · rw [hid]; linarith + +/-- For irrational `ξ`, the points `ξ · seq n` are dense in `ℝ / ℤ`. -/ +lemma dense_seq (ξ : ℝ) (hξ : Irrational ξ) : + Dense (Set.range fun n => (↑(ξ * seq n) : AddCircle (1 : ℝ))) := by + have hT : Dense {t : ℝ | ∃ x ∈ S, ∃ z : ℤ, t = ξ * x + z} := by + rw [dense_iff_exists_between] + intro a b hab + obtain ⟨x, hx, z, h1, h2⟩ := dense_aux ξ hξ a b hab + exact ⟨_, ⟨x, hx, z, rfl⟩, h1, h2⟩ + have hsurj : Function.Surjective (fun t : ℝ => (t : AddCircle (1 : ℝ))) := + QuotientAddGroup.mk_surjective + have hcont : Continuous (fun t : ℝ => (t : AddCircle (1 : ℝ))) := AddCircle.continuous_mk' 1 + refine (hsurj.denseRange.dense_image hcont hT).mono ?_ + rintro _ ⟨t, ⟨x, hx, z, rfl⟩, rfl⟩ + rw [← range_seq] at hx + obtain ⟨n, rfl⟩ := hx + refine ⟨n, ?_⟩ + apply QuotientAddGroup.eq.2 + rw [AddSubgroup.mem_zmultiples_iff] + exact ⟨z, by simp⟩ + +/-- There is a strictly increasing sequence with consecutive ratios at least `1 + c / log n` +which is dense modulo one for every irrational dilation. -/ +theorem problem_10_6_variant_1 : type_of% @Bugeaud06.problem_10_6_variant_1 := + ⟨seq, seq_strictMono, sublacunary, dense_seq⟩ + +end Math0.Bugeaud06 + +#math0_proves Math0.Bugeaud06.problem_10_6_variant_1 Bugeaud06.problem_10_6_variant_1 diff --git a/lean/Math0/Books/Bugeaud08_problem_10_8_variants_quadratic.lean b/lean/Math0/Books/Bugeaud08_problem_10_8_variants_quadratic.lean new file mode 100644 index 0000000..7104670 --- /dev/null +++ b/lean/Math0/Books/Bugeaud08_problem_10_8_variants_quadratic.lean @@ -0,0 +1,247 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.Books.BugeaudDistributionModuloOne.Problem10_8 +import Math0.Audit + +/-! +# The p-adic Littlewood conjecture for quadratic irrationals (Bugeaud 10.8, quadratic case) + +Bugeaud (*Distribution modulo one and Diophantine approximation*, Problem 10.8) states the +p-adic Littlewood conjecture of de Mathan and Teulié: `inf_{q ≥ 1} q · |q|_p · ‖q ξ‖ = 0`. +We prove the formal statement `Bugeaud08.problem_10_8.variants.quadratic`: the conjecture +holds for every real `ξ` whose minimal polynomial over `ℚ` has degree two. Clearing +denominators, `s = 2 N ξ + B` satisfies `s ^ 2 = m` for a positive non-square integer `m`. +For each `k`, a nontrivial solution of the Pell equation `x ^ 2 - m p ^ (2k) y ^ 2 = 1` gives +`Y = p ^ k |y|` with `x ^ 2 - m Y ^ 2 = 1`, so `s Y` is within `1 / (|s| Y)` of `± x`; taking +`q = 2 N Y` yields `q · |q|_p · ‖q ξ‖ ≤ 2 N / (|s| p ^ k) → 0`. +-/ + +namespace Math0.Bugeaud08 + +open Polynomial + +/-- A real number of degree two over `ℚ` is a root of a monic rational quadratic. -/ +lemma quad_coeffs (ξ : ℝ) (hξ : (minpoly ℚ ξ).natDegree = 2) : + ∃ c₀ c₁ : ℚ, ξ ^ 2 + (c₁ : ℝ) * ξ + c₀ = 0 := by + have hint : IsIntegral ℚ ξ := by + by_contra h + rw [minpoly.eq_zero h] at hξ + simp at hξ + have hmon := minpoly.monic hint + have hroot := minpoly.aeval ℚ ξ + rw [aeval_eq_sum_range, hξ] at hroot + have h2 : (minpoly ℚ ξ).coeff 2 = 1 := by + have := hmon.leadingCoeff + rwa [Polynomial.leadingCoeff, hξ] at this + refine ⟨(minpoly ℚ ξ).coeff 0, (minpoly ℚ ξ).coeff 1, ?_⟩ + simp [Finset.sum_range_succ, h2, Algebra.smul_def] at hroot + linear_combination hroot + +/-- A real number of degree two over `ℚ` is not rational. -/ +lemma not_rat (ξ : ℝ) (hξ : (minpoly ℚ ξ).natDegree = 2) (r : ℚ) : ξ ≠ r := by + rintro rfl + have : (minpoly ℚ ((r : ℝ))).natDegree = 1 := by + rw [minpoly.natDegree_eq_one_iff] + exact ⟨r, rfl⟩ + omega + +/-- Clearing denominators: `(2 N ξ + B) ^ 2` is an integer `m` for some `N > 0`, `B ∈ ℤ`. -/ +lemma int_data (ξ : ℝ) (c₀ c₁ : ℚ) (h : ξ ^ 2 + (c₁ : ℝ) * ξ + c₀ = 0) : + ∃ (N : ℕ) (B m : ℤ), 0 < N ∧ (2 * N * ξ + B) ^ 2 = m := by + refine ⟨c₁.den * c₀.den, c₁.num * c₀.den, + (c₁.num * c₀.den) ^ 2 - 4 * (c₁.den * c₀.den) * (c₀.num * c₁.den), by positivity, ?_⟩ + have hB : ((c₁.den * c₀.den : ℕ) : ℝ) * c₁ = ((c₁.num * c₀.den : ℤ) : ℝ) := by + push_cast + rw [Rat.cast_def c₁] + field_simp + have hC : ((c₁.den * c₀.den : ℕ) : ℝ) * c₀ = ((c₀.num * c₁.den : ℤ) : ℝ) := by + push_cast + rw [Rat.cast_def c₀] + field_simp + set N : ℝ := ((c₁.den * c₀.den : ℕ) : ℝ) + set B : ℝ := ((c₁.num * c₀.den : ℤ) : ℝ) + have hm : (((c₁.num * c₀.den) ^ 2 - 4 * (c₁.den * c₀.den) * (c₀.num * c₁.den) : ℤ) : ℝ) + = B ^ 2 - 4 * N * ((c₀.num * c₁.den : ℤ) : ℝ) := by + simp only [N, B] + push_cast + ring + rw [hm] + linear_combination 4 * N ^ 2 * h - 4 * N * ξ * hB - 4 * N * hC + +/-- For irrational `ξ`, the shifted multiple `2 N ξ + B` is nonzero. -/ +lemma s_ne_zero (ξ : ℝ) (N : ℕ) (B : ℤ) (hN : 0 < N) (hirr : ∀ r : ℚ, ξ ≠ r) : + 2 * N * ξ + B ≠ 0 := by + intro h0 + have hNr : (0:ℝ) < N := by exact_mod_cast hN + apply hirr ((-B) / (2 * N) : ℚ) + push_cast + field_simp + linarith + +/-- For irrational `ξ`, `m p ^ (2k)` is never a perfect square. -/ +lemma not_square (ξ : ℝ) (N : ℕ) (B m : ℤ) (hN : 0 < N) (hs : (2 * N * ξ + B) ^ 2 = m) + (hirr : ∀ r : ℚ, ξ ≠ r) (p : ℕ) (hp : p.Prime) (k : ℕ) : + ¬ IsSquare (m * (p : ℤ) ^ (2 * k)) := by + rintro ⟨t, ht⟩ + have hNr : (0:ℝ) < N := by exact_mod_cast hN + have hp0 : (0:ℝ) < p := by exact_mod_cast hp.pos + have hpk : (0:ℝ) < (p:ℝ) ^ k := by positivity + have h1 : ((2 * N * ξ + B) * (p:ℝ) ^ k) ^ 2 = (t:ℝ) ^ 2 := by + have : ((m * (p : ℤ) ^ (2 * k) : ℤ) : ℝ) = ((t * t : ℤ) : ℝ) := by rw [ht] + push_cast at this + rw [mul_pow, hs, ← pow_mul, mul_comm k 2, this] + ring + rcases sq_eq_sq_iff_eq_or_eq_neg.mp h1 with h2 | h2 + · apply hirr ((t / p ^ k - B) / (2 * N) : ℚ) + push_cast + field_simp + linear_combination h2 + · apply hirr ((-t / p ^ k - B) / (2 * N) : ℚ) + push_cast + field_simp + linear_combination h2 + +/-- One of `x, -x` is within `1 / (|s| Y)` of `s Y` when `x ^ 2 - s ^ 2 Y ^ 2 = 1`. -/ +lemma pell_close (s Y x : ℝ) (hY : 0 < Y) (h : x ^ 2 - s ^ 2 * Y ^ 2 = 1) : + ∃ n : ℝ, (n = x ∨ n = -x) ∧ |s * Y - n| * (|s| * Y) ≤ 1 := by + have huv : |x - s * Y| * |x + s * Y| = 1 := by + rw [← abs_mul] + have : (x - s * Y) * (x + s * Y) = 1 := by linear_combination h + rw [this, abs_one] + have hsum : 2 * (|s| * Y) ≤ |x - s * Y| + |x + s * Y| := by + have := abs_sub (x + s * Y) (x - s * Y) + have e : x + s * Y - (x - s * Y) = 2 * (s * Y) := by ring + rw [e, abs_mul, abs_mul, abs_of_pos hY] at this + norm_num at this + linarith [abs_nonneg (x - s * Y)] + by_cases hv : |s| * Y ≤ |x + s * Y| + · refine ⟨x, Or.inl rfl, ?_⟩ + rw [abs_sub_comm] + calc |x - s * Y| * (|s| * Y) ≤ |x - s * Y| * |x + s * Y| := + mul_le_mul_of_nonneg_left hv (abs_nonneg _) + _ = 1 := huv + · refine ⟨-x, Or.inr rfl, ?_⟩ + have hu : |s| * Y ≤ |x - s * Y| := by linarith + have e : s * Y - -x = x + s * Y := by ring + rw [e] + calc |x + s * Y| * (|s| * Y) ≤ |x + s * Y| * |x - s * Y| := + mul_le_mul_of_nonneg_left hu (abs_nonneg _) + _ = 1 := by rw [mul_comm]; exact huv + +/-- The key estimate: for each `k` some `q ≥ 1` has +`q |q|_p ‖q ξ‖ ≤ 2 N / (|2 N ξ + B| p ^ k)`, via the Pell equation for `m p ^ (2k)`. -/ +lemma approx (ξ : ℝ) (N p : ℕ) (B m : ℤ) (hN : 0 < N) (hs : (2 * N * ξ + B) ^ 2 = m) + (hd0 : ∀ k : ℕ, 0 < m * (p : ℤ) ^ (2 * k)) + (hdsq : ∀ k : ℕ, ¬ IsSquare (m * (p : ℤ) ^ (2 * k))) + (hp : p.Prime) (hs0 : 2 * N * ξ + B ≠ 0) (k : ℕ) : + ∃ q : ℕ, 1 ≤ q ∧ (q:ℝ) * (padicNorm p q : ℝ) * distToNearestInt (q * ξ) ≤ + 2 * N / (|2 * N * ξ + B| * p ^ k) := by + obtain ⟨x, y, hxy, hy0⟩ := Pell.exists_of_not_isSquare (hd0 k) (hdsq k) + set s : ℝ := 2 * N * ξ + B with hs_def + have hNr : (0:ℝ) < N := by exact_mod_cast hN + have hp0 : (0:ℝ) < p := by exact_mod_cast hp.pos + have hpk : (0:ℝ) < (p:ℝ) ^ k := by positivity + set Y : ℕ := p ^ k * y.natAbs with hY_def + have hYpos : 0 < Y := by + have := hp.pos + have : 0 < y.natAbs := Int.natAbs_pos.mpr hy0 + positivity + have hYr : (0:ℝ) < Y := by exact_mod_cast hYpos + have hYcast : (Y:ℝ) = (p:ℝ) ^ k * |(y:ℝ)| := by + simp [Y] + have hpell : (x:ℝ) ^ 2 - s ^ 2 * (Y:ℝ) ^ 2 = 1 := by + have : ((x ^ 2 - m * (p : ℤ) ^ (2 * k) * y ^ 2 : ℤ) : ℝ) = ((1 : ℤ) : ℝ) := by rw [hxy] + push_cast at this + rw [hYcast, hs, mul_pow, sq_abs] + rw [← this] + ring + obtain ⟨n, hn, hclose⟩ := pell_close s Y x hYr hpell + set q : ℕ := 2 * N * Y with hq_def + have hq1 : 1 ≤ q := by + have : 0 < q := by positivity + omega + refine ⟨q, hq1, ?_⟩ + -- distance bound + have hn_int : ∃ z : ℤ, (z : ℝ) = n - B * Y := by + rcases hn with h | h + · exact ⟨x - B * Y, by push_cast; rw [h]⟩ + · exact ⟨-x - B * Y, by push_cast; rw [h]⟩ + obtain ⟨z, hz⟩ := hn_int + have hqξ : (q:ℝ) * ξ - z = s * Y - n := by + rw [hz, hq_def, hs_def] + push_cast + ring + have hdist : distToNearestInt (q * ξ) * (|s| * Y) ≤ 1 := by + have h1 : distToNearestInt (q * ξ) ≤ |(q:ℝ) * ξ - z| := round_le _ _ + rw [hqξ] at h1 + have : 0 < |s| * Y := by positivity + calc distToNearestInt (q * ξ) * (|s| * Y) ≤ |s * Y - n| * (|s| * Y) := by gcongr + _ ≤ 1 := hclose + -- p-adic bound + have hpad : (padicNorm p q : ℝ) ≤ ((p:ℝ) ^ k)⁻¹ := by + have := Fact.mk hp + have hdvd : ((p ^ k : ℕ) : ℤ) ∣ ((q : ℕ) : ℤ) := by + refine Int.natCast_dvd_natCast.mpr ?_ + exact ⟨2 * N * y.natAbs, by rw [hq_def, hY_def]; ring⟩ + have := padicNorm.dvd_iff_norm_le.mp hdvd + rw [Int.cast_natCast] at this + have h2 : ((padicNorm p q : ℚ) : ℝ) ≤ (((p : ℚ) ^ (-(k : ℤ)) : ℚ) : ℝ) := by + exact_mod_cast this + refine h2.trans_eq ?_ + push_cast + rw [zpow_neg, zpow_natCast] + have hpn0 : (0:ℝ) ≤ (padicNorm p q : ℝ) := by + have := padicNorm.nonneg (p := p) (q : ℚ) + exact_mod_cast this + have hd0' : 0 ≤ distToNearestInt (q * ξ) := distToNearestInt_nonneg _ + have hsY : 0 < |s| * Y := by positivity + have hdist' : distToNearestInt (q * ξ) ≤ 1 / (|s| * Y) := by + rw [le_div_iff₀ hsY]; exact hdist + calc (q:ℝ) * (padicNorm p q : ℝ) * distToNearestInt (q * ξ) + ≤ (q:ℝ) * ((p:ℝ) ^ k)⁻¹ * (1 / (|s| * Y)) := by gcongr + _ = 2 * N / (|s| * p ^ k) := by + rw [hq_def] + push_cast + field_simp + +/-- The p-adic Littlewood conjecture holds for real quadratic irrationals: for every prime `p` +and every real `ξ` of degree two over `ℚ`, `inf_{q ≥ 1} q |q|_p ‖q ξ‖ = 0`. -/ +theorem problem_10_8_quadratic : type_of% @Bugeaud08.problem_10_8.variants.quadratic := by + intro ξ p hp hξ + obtain ⟨c₀, c₁, h⟩ := quad_coeffs ξ hξ + obtain ⟨N, B, m, hN, hs⟩ := int_data ξ c₀ c₁ h + have hirr := not_rat ξ hξ + have hs0 := s_ne_zero ξ N B hN hirr + have hm : 0 < m := by + have : (0:ℝ) < m := by rw [← hs]; positivity + exact_mod_cast this + have hd0 : ∀ k : ℕ, 0 < m * (p : ℤ) ^ (2 * k) := fun k => by + have := hp.pos + positivity + have hdsq := not_square ξ N B m hN hs hirr p hp + apply csInf_eq_of_forall_ge_of_forall_gt_exists_lt + · exact ⟨_, 1, le_refl _, rfl⟩ + · rintro x ⟨q, -, rfl⟩ + have := padicNorm.nonneg (p := p) (q : ℚ) + have h1 : (0:ℝ) ≤ (padicNorm p q : ℝ) := by exact_mod_cast this + have h2 := distToNearestInt_nonneg ((q:ℝ) * ξ) + positivity + · intro w hw + set s : ℝ := 2 * N * ξ + B with hs_def + have hsa : 0 < |s| := abs_pos.mpr hs0 + have hNr : (0:ℝ) < N := by exact_mod_cast hN + obtain ⟨k, hk⟩ := exists_nat_gt (2 * N / (|s| * w)) + have hpk : (k : ℝ) < (p : ℝ) ^ k := by + exact_mod_cast Nat.lt_pow_self hp.one_lt + have hp0 : (0:ℝ) < p := by exact_mod_cast hp.pos + have hpk0 : (0:ℝ) < (p:ℝ) ^ k := by positivity + obtain ⟨q, hq, hle⟩ := approx ξ N p B m hN hs hd0 hdsq hp hs0 k + refine ⟨_, ⟨q, hq, rfl⟩, hle.trans_lt ?_⟩ + rw [div_lt_iff₀ (by positivity)] + rw [div_lt_iff₀ (by positivity)] at hk + nlinarith + +end Math0.Bugeaud08 + +#math0_proves Math0.Bugeaud08.problem_10_8_quadratic Bugeaud08.problem_10_8.variants.quadratic diff --git a/lean/Math0/Books/Bugeaud09_problem_10_9_variants_dimH_lt_one.lean b/lean/Math0/Books/Bugeaud09_problem_10_9_variants_dimH_lt_one.lean new file mode 100644 index 0000000..a470218 --- /dev/null +++ b/lean/Math0/Books/Bugeaud09_problem_10_9_variants_dimH_lt_one.lean @@ -0,0 +1,86 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.Books.BugeaudDistributionModuloOne.Problem10_9 +import Math0.Audit + +/-! +# Z-numbers form a set of Hausdorff dimension zero + +Problem 10.9 of Bugeaud's *Distribution modulo one and Diophantine approximation* concerns +Mahler's Z-numbers: reals `ξ > 0` with `{ξ (3/2)^n} ∈ [0, 1/2)` for all `n ≥ 1`. The variant +`dimH_lt_one` records the theorem of Flatto, Lagarias and Pollington that the set of Z-numbers +has Hausdorff dimension `< 1`. We prove the (much stronger) classical fact, going back to +Mahler, that the set of Z-numbers is countable, hence of Hausdorff dimension `0 < 1`. +The key point: if `g_n = ⌊ξ (3/2)^n⌋` then the Z-number condition forces +`3 g_n ≤ 2 g_{n+1} ≤ 3 g_n + 1`, so `g_{n+1}` is determined by `g_n`; hence all `g_n` are +determined by `g_1`, and since `|ξ - η| (3/2)^n < 1/2` whenever `g_n(ξ) = g_n(η)`, the map +`ξ ↦ ⌊3ξ/2⌋` is injective on Z-numbers. +-/ + +namespace Math0.Bugeaud09 + +/-- If `x` and `3x/2` both have fractional part `< 1/2`, then `3⌊x⌋ ≤ 2⌊3x/2⌋ ≤ 3⌊x⌋ + 1`. -/ +private lemma floor_bounds (x : ℝ) (hx : Int.fract x < 1 / 2) (hx' : Int.fract (x * (3 / 2)) < 1 / 2) : + 3 * ⌊x⌋ ≤ 2 * ⌊x * (3 / 2)⌋ ∧ 2 * ⌊x * (3 / 2)⌋ ≤ 3 * ⌊x⌋ + 1 := by + rw [Int.fract] at hx hx' + have h1 := Int.floor_le x + have h2 := Int.floor_le (x * (3 / 2)) + constructor + · have : ((3 * ⌊x⌋ - 2 * ⌊x * (3 / 2)⌋ : ℤ) : ℝ) < 1 := by push_cast; linarith + have : (3 * ⌊x⌋ - 2 * ⌊x * (3 / 2)⌋ : ℤ) < 1 := by exact_mod_cast this + omega + · have : ((2 * ⌊x * (3 / 2)⌋ - 3 * ⌊x⌋ : ℤ) : ℝ) < 2 := by push_cast; linarith + have : (2 * ⌊x * (3 / 2)⌋ - 3 * ⌊x⌋ : ℤ) < 2 := by exact_mod_cast this + omega + +/-- For two Z-numbers, the floors of `ξ (3/2)^n` agree for all `n ≥ 1` as soon as they agree +for `n = 1`. -/ +private lemma floor_eq_of_floor_eq {ξ η : ℝ} (hξ : IsZNumber ξ) (hη : IsZNumber η) + (h : ⌊ξ * (3 / 2)⌋ = ⌊η * (3 / 2)⌋) (m : ℕ) : + ⌊ξ * (3 / 2) ^ (m + 1)⌋ = ⌊η * (3 / 2) ^ (m + 1)⌋ := by + induction m with + | zero => simpa using h + | succ m ih => + have e1 : ξ * (3 / 2 : ℝ) ^ (m + 1 + 1) = ξ * (3 / 2) ^ (m + 1) * (3 / 2) := by ring + have e2 : η * (3 / 2 : ℝ) ^ (m + 1 + 1) = η * (3 / 2) ^ (m + 1) * (3 / 2) := by ring + have a := floor_bounds (ξ * (3 / 2) ^ (m + 1)) (hξ.2 _ (by omega)) (e1 ▸ hξ.2 _ (by omega)) + have b := floor_bounds (η * (3 / 2) ^ (m + 1)) (hη.2 _ (by omega)) (e2 ▸ hη.2 _ (by omega)) + rw [e1, e2] + omega + +/-- The map `ξ ↦ ⌊3ξ/2⌋` is injective on Z-numbers. -/ +private lemma injOn_floor : Set.InjOn (fun ξ : ℝ => ⌊ξ * (3 / 2)⌋) {ξ : ℝ | IsZNumber ξ} := by + intro ξ hξ η hη h + change IsZNumber ξ at hξ + change IsZNumber η at hη + by_contra hne + have hpos : 0 < |ξ - η| := abs_pos.mpr (sub_ne_zero.mpr hne) + obtain ⟨n, hn⟩ := pow_unbounded_of_one_lt (1 / (2 * |ξ - η|)) (by norm_num : (1 : ℝ) < 3 / 2) + have hf := floor_eq_of_floor_eq hξ hη h n + have fx := hξ.2 (n + 1) (by omega) + have fy := hη.2 (n + 1) (by omega) + rw [Int.fract] at fx fy + have lx := Int.floor_le (ξ * (3 / 2) ^ (n + 1)) + have ly := Int.floor_le (η * (3 / 2) ^ (n + 1)) + rw [hf] at fx lx + have hd : |ξ - η| * (3 / 2 : ℝ) ^ (n + 1) < 1 / 2 := by + rw [← abs_of_pos (by positivity : (0 : ℝ) < (3 / 2) ^ (n + 1)), ← abs_mul, abs_lt, sub_mul] + constructor <;> linarith + have hpow : (3 / 2 : ℝ) ^ n ≤ (3 / 2) ^ (n + 1) := + pow_le_pow_right₀ (by norm_num) (by omega) + rw [div_lt_iff₀ (by positivity)] at hn + nlinarith + +/-- The set of Z-numbers is countable. -/ +private lemma countable_zNumbers : {ξ : ℝ | IsZNumber ξ}.Countable := + (Set.mapsTo_univ _ _).countable_of_injOn injOn_floor Set.countable_univ + +/-- The set of Z-numbers has Hausdorff dimension `< 1` (indeed `= 0`, being countable). -/ +theorem dimH_lt_one : type_of% @Bugeaud09.problem_10_9.variants.dimH_lt_one := by + rw [countable_zNumbers.dimH_zero] + exact zero_lt_one + +end Math0.Bugeaud09 + +#math0_proves Math0.Bugeaud09.dimH_lt_one Bugeaud09.problem_10_9.variants.dimH_lt_one diff --git a/lean/Math0/Books/Bugeaud09_problem_10_9_variants_measure_zero.lean b/lean/Math0/Books/Bugeaud09_problem_10_9_variants_measure_zero.lean new file mode 100644 index 0000000..777721e --- /dev/null +++ b/lean/Math0/Books/Bugeaud09_problem_10_9_variants_measure_zero.lean @@ -0,0 +1,85 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.Books.BugeaudDistributionModuloOne.Problem10_9 +import Math0.Audit + +/-! +# Mahler's Z-numbers form a null set (Bugeaud, Problem 10.9, measure-zero variant) + +A Z-number is a real `ξ > 0` with `{ξ (3/2)^n} ∈ [0, 1/2)` for every `n ≥ 1`; Mahler [Mah68] +asked whether any exist (Bugeaud, *Distribution modulo one and Diophantine approximation*, +Problem 10.9). We prove exactly the formal statement +`Bugeaud09.problem_10_9.variants.measure_zero`: the set of Z-numbers has Lebesgue measure zero. +Following Mahler, put `g_n = ⌊ξ (3/2)^n⌋`. Since `{ξ (3/2)^n} < 1/2` for all `n ≥ 1`, we get +`3 g_n ≤ 2 g_{n+1} ≤ 3 g_n + 1`, so `g_{n+1}` is determined by `g_n`. Hence two Z-numbers with +the same `g_1` have all `g_n` equal, so `|ξ - η| (3/2)^n < 1` for all `n` and `ξ = η`. Thus +`ξ ↦ ⌊3ξ/2⌋` is injective on Z-numbers, the set is countable, and countable sets are null. +-/ + +namespace Math0.Bugeaud09 + +/-- Mahler's recurrence: for a Z-number `ξ` and `n ≥ 1`, with `g_n = ⌊ξ (3/2)^n⌋`, +we have `3 g_n ≤ 2 g_{n+1} ≤ 3 g_n + 1`. -/ +lemma floor_step {ξ : ℝ} (hξ : IsZNumber ξ) {n : ℕ} (hn : 1 ≤ n) : + 3 * ⌊ξ * (3 / 2 : ℝ) ^ n⌋ ≤ 2 * ⌊ξ * (3 / 2 : ℝ) ^ (n + 1)⌋ ∧ + 2 * ⌊ξ * (3 / 2 : ℝ) ^ (n + 1)⌋ ≤ 3 * ⌊ξ * (3 / 2 : ℝ) ^ n⌋ + 1 := by + have h1 := hξ.2 n hn + have h2 := hξ.2 (n + 1) (by omega) + have hx' : ξ * (3 / 2 : ℝ) ^ (n + 1) = 3 / 2 * (ξ * (3 / 2 : ℝ) ^ n) := by + rw [pow_succ]; ring + rw [hx'] at h2 ⊢ + generalize ξ * (3 / 2 : ℝ) ^ n = x at h1 h2 ⊢ + have ha := Int.floor_le x + have hb := Int.floor_le (3 / 2 * x) + rw [Int.fract] at h1 h2 + constructor + · have h : ((3 * ⌊x⌋ : ℤ) : ℝ) < ((2 * ⌊3 / 2 * x⌋ + 1 : ℤ) : ℝ) := by + push_cast; linarith + have := Int.cast_lt.mp h + omega + · have h : ((2 * ⌊3 / 2 * x⌋ : ℤ) : ℝ) < ((3 * ⌊x⌋ + 2 : ℤ) : ℝ) := by + push_cast; linarith + have := Int.cast_lt.mp h + omega + +/-- Two Z-numbers with the same `⌊ξ (3/2)⌋` have the same `⌊ξ (3/2)^n⌋` for every `n ≥ 1`. -/ +lemma floor_eq_of_floor_one_eq {ξ η : ℝ} (hξ : IsZNumber ξ) (hη : IsZNumber η) + (h1 : ⌊ξ * (3 / 2 : ℝ) ^ 1⌋ = ⌊η * (3 / 2 : ℝ) ^ 1⌋) : + ∀ n, 1 ≤ n → ⌊ξ * (3 / 2 : ℝ) ^ n⌋ = ⌊η * (3 / 2 : ℝ) ^ n⌋ := by + intro n hn + induction n, hn using Nat.le_induction with + | base => exact h1 + | succ n hn ih => + have := floor_step hξ hn + have := floor_step hη hn + omega + +/-- Mahler: a Z-number is determined by `⌊ξ (3/2)⌋`. -/ +lemma injOn_floor : + Set.InjOn (fun ξ : ℝ => ⌊ξ * (3 / 2 : ℝ) ^ 1⌋) {ξ : ℝ | IsZNumber ξ} := by + intro ξ hξ η hη h1 + have hall := floor_eq_of_floor_one_eq hξ hη h1 + by_contra hne + have hpos : 0 < |ξ - η| := abs_pos.mpr (sub_ne_zero.mpr hne) + obtain ⟨n, hn⟩ := pow_unbounded_of_one_lt (1 / |ξ - η|) (by norm_num : (1 : ℝ) < 3 / 2) + have hle : (3 / 2 : ℝ) ^ n ≤ (3 / 2 : ℝ) ^ (n + 1) := + pow_le_pow_right₀ (by norm_num) (Nat.le_succ n) + have hlt := Int.abs_sub_lt_one_of_floor_eq_floor (hall (n + 1) (by omega)) + rw [← sub_mul, abs_mul, abs_of_pos (by positivity : (0 : ℝ) < (3 / 2) ^ (n + 1))] at hlt + have : 1 < |ξ - η| * (3 / 2 : ℝ) ^ (n + 1) := by + rw [div_lt_iff₀ hpos] at hn + nlinarith + linarith + +/-- The set of Z-numbers is countable. -/ +lemma countable_zNumbers : {ξ : ℝ | IsZNumber ξ}.Countable := + (Set.mapsTo_univ _ _).countable_of_injOn injOn_floor Set.countable_univ + +/-- Mahler (1968): the set of Z-numbers has Lebesgue measure zero. -/ +theorem measure_zero : type_of% @Bugeaud09.problem_10_9.variants.measure_zero := + countable_zNumbers.measure_zero _ + +end Math0.Bugeaud09 + +#math0_proves Math0.Bugeaud09.measure_zero Bugeaud09.problem_10_9.variants.measure_zero diff --git a/lean/Math0/Books/Equidistribution_isAccumulationPoint_three_halves_pow_infinite.lean b/lean/Math0/Books/Equidistribution_isAccumulationPoint_three_halves_pow_infinite.lean new file mode 100644 index 0000000..bc859c4 --- /dev/null +++ b/lean/Math0/Books/Equidistribution_isAccumulationPoint_three_halves_pow_infinite.lean @@ -0,0 +1,146 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.Books.UniformDistributionOfSequences.Equidistribution +import Math0.Audit + +/-! +# The fractional parts of `(3/2)^n` have infinitely many accumulation points + +Kuipers and Niederreiter (*Uniform Distribution of Sequences*, Chapter 1) recall that it is +unknown whether `((3/2)^n)` is equidistributed modulo `1`; it is known (Vijayaraghavan) that +`{(3/2)^n}` has infinitely many accumulation points. We prove exactly the formal statement +`Equidistribution.isAccumulationPoint_three_halves_pow_infinite`. Write `r_n = {(3/2)^n}` and +suppose the set `L` of accumulation points is finite. By compactness and injectivity of `r`, +`r_n` is eventually within any `ε` of `L`. Since `2 r_{n+1} - 3 r_n` is an integer and the finitely +many numbers `2ℓ' - 3ℓ` (`ℓ, ℓ' ∈ L`) are isolated from the other integers, for small `ε` the +deviations `δ_n = r_n - ℓ_n` satisfy `δ_{n+1} = (3/2) δ_n` while staying below `ε`, which forces +`δ_n = 0`. Hence `r_n ∈ L` for all large `n`, contradicting injectivity of `n ↦ r_n`. +-/ + +namespace Math0.Equidistribution + +open Filter Topology + +/-- Integers are uniformly isolated from any real `d`. -/ +lemma exists_int_isolated (d : ℝ) : ∃ η > 0, ∀ m : ℤ, |(m : ℝ) - d| < η → (m : ℝ) = d := by + by_cases h : ((round d : ℤ) : ℝ) = d + · refine ⟨1, one_pos, fun m hm => ?_⟩ + rw [← h] at hm ⊢ + have : |((m - round d : ℤ) : ℝ)| < 1 := by push_cast; exact hm + rw [← Int.cast_abs] at this + have h2 : |m - round d| < 1 := by exact_mod_cast this + have : m - round d = 0 := by rw [abs_lt] at h2; omega + have : m = round d := by omega + rw [this] + · refine ⟨|d - round d|, abs_pos.2 (sub_ne_zero.2 (Ne.symm h)), fun m hm => ?_⟩ + have := round_le d m + rw [abs_sub_comm] at hm + linarith + +/-- The isolation radius can be taken arbitrarily small. -/ +lemma eventually_int_isolated (d : ℝ) : + ∀ᶠ η in 𝓝[>] (0 : ℝ), ∀ m : ℤ, |(m : ℝ) - d| < η → (m : ℝ) = d := by + obtain ⟨η₀, hη₀, h⟩ := exists_int_isolated d + filter_upwards [Ioo_mem_nhdsGT hη₀] with η hη m hm + exact h m (hm.trans hη.2) + +/-- The basic relation: `2 {(3/2)^(n+1)} - 3 {(3/2)^n}` is an integer. -/ +lemma two_mul_fract_succ_sub (n : ℕ) : + ∃ m : ℤ, 2 * Int.fract ((3 / 2 : ℝ) ^ (n + 1)) - 3 * Int.fract ((3 / 2 : ℝ) ^ n) = m := by + refine ⟨3 * ⌊(3 / 2 : ℝ) ^ n⌋ - 2 * ⌊(3 / 2 : ℝ) ^ (n + 1)⌋, ?_⟩ + simp only [Int.fract, pow_succ] + push_cast + ring + +/-- The sequence `{(3/2)^n}` of fractional parts has infinitely many accumulation points. -/ +theorem isAccumulationPoint_three_halves_pow_infinite : + type_of% @Equidistribution.isAccumulationPoint_three_halves_pow_infinite := by + intro hL + set r : ℕ → ℝ := fun n => Int.fract ((3 / 2 : ℝ) ^ n) with hr + set L := {x | Equidistribution.IsAccumulationPoint x r} with hLdef + have hinj : Function.Injective r := Equidistribution.fract_three_halves_pow_injective + -- Step A: the sequence is eventually close to `L`. + have hA : ∀ ε > 0, ∀ᶠ n in atTop, ∃ ℓ ∈ L, |r n - ℓ| < ε := by + intro ε hε + by_contra h + rw [not_eventually] at h + simp only [not_exists, not_and, not_lt] at h + rw [Nat.frequently_atTop_iff_infinite] at h + set S := {n | ∀ ℓ ∈ L, ε ≤ |r n - ℓ|} + have hSi : (r '' S).Infinite := h.image hinj.injOn + have hsub : r '' S ⊆ Set.Icc 0 1 := by + rintro _ ⟨n, -, rfl⟩ + exact ⟨Int.fract_nonneg _, (Int.fract_lt_one _).le⟩ + obtain ⟨x, -, hx⟩ := hSi.exists_accPt_of_subset_isCompact isCompact_Icc hsub + have hxc : x ∈ closure (r '' S \ {x}) := + mem_closure_iff_clusterPt.2 (accPt_principal_iff_clusterPt.1 hx) + have hxL : x ∈ L := by + show x ∈ closure (Set.range r \ {x}) + refine closure_mono ?_ hxc + exact Set.sdiff_subset_sdiff_left (Set.image_subset_range _ _) + obtain ⟨_, ⟨⟨n, hn, rfl⟩, -⟩, hd⟩ := Metric.mem_closure_iff.1 hxc ε hε + have := hn x hxL + rw [Real.dist_eq, abs_sub_comm] at hd + linarith + -- Step B: choose `ε`. + have hev : ∀ᶠ η in 𝓝[>] (0 : ℝ), ∀ p ∈ L ×ˢ L, + ∀ m : ℤ, |(m : ℝ) - (2 * p.2 - 3 * p.1)| < η → (m : ℝ) = 2 * p.2 - 3 * p.1 := + (hL.prod hL).eventually_all.2 fun p _ => eventually_int_isolated _ + obtain ⟨η, hη, hηpos⟩ := (hev.and self_mem_nhdsWithin).exists + set ε := η / 5 with hεdef + have hε : 0 < ε := by have : (0 : ℝ) < η := hηpos; positivity + -- Step C: the linear relation between consecutive deviations. + have hC : ∀ n, ∀ ℓ ∈ L, ∀ ℓ' ∈ L, |r n - ℓ| < ε → |r (n + 1) - ℓ'| < ε → + 2 * (r (n + 1) - ℓ') = 3 * (r n - ℓ) := by + intro n ℓ hℓ ℓ' hℓ' h1 h2 + obtain ⟨m, hm⟩ := two_mul_fract_succ_sub n + have key := hη (ℓ, ℓ') ⟨hℓ, hℓ'⟩ m (by + rw [← hm] + have e : 2 * Int.fract ((3 / 2 : ℝ) ^ (n + 1)) - 3 * Int.fract ((3 / 2 : ℝ) ^ n) - + (2 * ℓ' - 3 * ℓ) = 2 * (r (n + 1) - ℓ') - 3 * (r n - ℓ) := by simp [hr]; ring + rw [e] + calc |2 * (r (n + 1) - ℓ') - 3 * (r n - ℓ)| + ≤ |2 * (r (n + 1) - ℓ')| + |3 * (r n - ℓ)| := abs_sub _ _ + _ = 2 * |r (n + 1) - ℓ'| + 3 * |r n - ℓ| := by + rw [abs_mul, abs_mul]; norm_num + _ < η := by linarith) + simp only at key + have : 2 * r (n + 1) - 3 * r n = m := by simp only [hr]; exact hm + linarith + obtain ⟨N, hN⟩ := eventually_atTop.1 (hA ε hε) + -- Step D: the sequence lies in `L` from `N` on. + have hD : ∀ n ≥ N, r n ∈ L := by + intro n hn + obtain ⟨ℓ, hℓ, hd⟩ := hN n hn + set δ := r n - ℓ with hδ + have hind : ∀ k : ℕ, ∃ ℓk ∈ L, r (n + k) - ℓk = (3 / 2 : ℝ) ^ k * δ ∧ + |r (n + k) - ℓk| < ε := by + intro k + induction k with + | zero => exact ⟨ℓ, hℓ, by simp [hδ], by simpa using hd⟩ + | succ k ih => + obtain ⟨ℓk, hℓk, e, hk⟩ := ih + obtain ⟨ℓ', hℓ', h'⟩ := hN (n + k + 1) (by omega) + refine ⟨ℓ', hℓ', ?_, h'⟩ + have := hC (n + k) ℓk hℓk ℓ' hℓ' hk h' + rw [pow_succ, show n + (k + 1) = n + k + 1 by omega] + linarith + by_cases hδ0 : δ = 0 + · have : r n = ℓ := by linarith + rw [this]; exact hℓ + · exfalso + have hpos : 0 < |δ| := abs_pos.2 hδ0 + obtain ⟨k, hk⟩ := pow_unbounded_of_one_lt (ε / |δ|) (by norm_num : (1 : ℝ) < 3 / 2) + obtain ⟨ℓk, -, e, hlt⟩ := hind k + rw [e, abs_mul, abs_of_pos (by positivity : (0 : ℝ) < (3 / 2) ^ k)] at hlt + rw [div_lt_iff₀ hpos] at hk + linarith + -- Step E: contradiction with injectivity. + exact Set.infinite_of_injective_forall_mem (f := fun k : ℕ => r (N + k)) + (fun a b h => by simpa using hinj h) (fun k => hD _ (by omega)) hL + +end Math0.Equidistribution + +#math0_proves Math0.Equidistribution.isAccumulationPoint_three_halves_pow_infinite + Equidistribution.isAccumulationPoint_three_halves_pow_infinite diff --git a/lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_limsup_eq_one.lean b/lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_limsup_eq_one.lean new file mode 100644 index 0000000..087f9e3 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_limsup_eq_one.lean @@ -0,0 +1,156 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1000» +import Math0.Audit + +/-! +# Erdős Problem 1000: if `liminf φ_A(k)/n_k = 0` then `limsup φ_A(k)/n_k = 1` + +For a strictly increasing sequence of positive integers `n_0 < n_1 < ⋯`, `φ_A(k)` counts the +`1 ≤ m ≤ n_k` such that `n_k / gcd(m, n_k)` divides no earlier `n_j` (Cassels; Erdős, +erdosproblems.com/1000). We prove Erdős's observation, exactly as stated upstream: if the ratios +`φ_A(k)/n_k` have liminf `0`, then their limsup is `1`. Since `φ_A(k) ≥ φ(n_k)` and +`φ(N)/N ≥ 1/B!` when all prime factors of `N` are `≤ B`, a small ratio forces a prime factor +`p > max(P, n_K)` of some `n_k`; at the first index `k'` with `p ∣ n_{k'}` (necessarily `k' > K`), +every `m ≤ n_{k'}` prime to `p` is counted, so `φ_A(k')/n_{k'} ≥ 1 - 1/p ≥ 1 - 1/(P+1)`. +-/ + +open Filter Topology Erdos1000 + +namespace Math0.Erdos1000 + +/-- `φ_A(k) ≤ n_k`: the counted set is a subset of `[1, n_k]`. -/ +theorem phiSeq_le (n : ℕ → ℕ) (k : ℕ) : phiSeq n k ≤ n k := by + unfold phiSeq + refine (Finset.card_filter_le _ _).trans ?_ + simp + +/-- If every prime factor of `N > 0` is at most `B`, then `φ(N)/N ≥ 1/B!` +(from `φ(N) · ∏_{p ∣ N} p = N · ∏_{p ∣ N} (p - 1) ≥ N` and `∏_{p ∣ N} p ∣ B!`). -/ +theorem totient_ratio_ge {N B : ℕ} (hN : 0 < N) (hB : ∀ p ∈ N.primeFactors, p ≤ B) : + (1 : ℝ) / (B.factorial : ℝ) ≤ (N.totient : ℝ) / N := by + have h1 : N ≤ N.totient * ∏ p ∈ N.primeFactors, p := by + rw [Nat.totient_mul_prod_primeFactors] + have : 1 ≤ ∏ p ∈ N.primeFactors, (p - 1) := by + apply Nat.one_le_iff_ne_zero.mpr + rw [Finset.prod_ne_zero_iff] + intro p hp + have := (Nat.prime_of_mem_primeFactors hp).two_le + omega + nlinarith + have h2 : ∏ p ∈ N.primeFactors, p ≤ B.factorial := by + rw [← Finset.prod_Ico_id_eq_factorial] + apply Nat.le_of_dvd (by rw [Finset.prod_Ico_id_eq_factorial]; exact Nat.factorial_pos B) + apply Finset.prod_dvd_prod_of_subset + intro p hp + have := (Nat.prime_of_mem_primeFactors hp).two_le + have := hB p hp + simp only [Finset.mem_Ico] + omega + have h3 : N ≤ N.totient * B.factorial := h1.trans (Nat.mul_le_mul_left _ h2) + have hNr : (0 : ℝ) < N := by exact_mod_cast hN + have hBr : (0 : ℝ) < B.factorial := by exact_mod_cast Nat.factorial_pos B + rw [div_le_div_iff₀ hBr hNr] + have : (N : ℝ) ≤ N.totient * B.factorial := by exact_mod_cast h3 + linarith + +/-- If `p` is prime, `p ∣ n_k`, and `p` divides no earlier `n_j`, then +`φ_A(k)/n_k ≥ 1 - 1/p`: every `m ≤ n_k` with `p ∤ m` is counted. -/ +theorem ratio_ge (n : ℕ → ℕ) (hn : StrictMono n) (hn0 : 0 < n 0) {p k : ℕ} (hp : p.Prime) + (hk : p ∣ n k) (hmin : ∀ j < k, ¬ p ∣ n j) : + (1 : ℝ) - 1 / (p : ℝ) ≤ (phiSeq n k : ℝ) / (n k : ℝ) := by + set N := n k with hNdef + have hN : 0 < N := hn0.trans_le (hn.monotone (Nat.zero_le k)) + have hsub : (Finset.Icc 1 N).filter (fun m => ¬ p ∣ m) ⊆ + (Finset.Icc 1 N).filter (fun m => ∀ j < k, ¬ (N / Nat.gcd m N) ∣ n j) := by + intro m hm + simp only [Finset.mem_filter] at hm ⊢ + refine ⟨hm.1, fun j hj hdvd => ?_⟩ + have hg : N = (N / Nat.gcd m N) * Nat.gcd m N := (Nat.div_mul_cancel (Nat.gcd_dvd_right m N)).symm + have hpd : p ∣ N / Nat.gcd m N := by + have : p ∣ (N / Nat.gcd m N) * Nat.gcd m N := hg ▸ hk + rcases (Nat.Prime.dvd_mul hp).1 this with h | h + · exact h + · exact absurd (h.trans (Nat.gcd_dvd_left m N)) hm.2 + exact hmin j hj (hpd.trans hdvd) + have hcard1 : ((Finset.Icc 1 N).filter (fun m => ¬ p ∣ m)).card ≤ phiSeq n k := + Finset.card_le_card hsub + have hcard2 : ((Finset.Icc 1 N).filter (fun m => p ∣ m)).card + + ((Finset.Icc 1 N).filter (fun m => ¬ p ∣ m)).card = N := by + rw [Finset.card_filter_add_card_filter_not]; simp + have hcard3 : ((Finset.Icc 1 N).filter (fun m => p ∣ m)).card = N / p := by + rw [← Nat.Ioc_filter_dvd_card_eq_div] + rfl + have h1 : N ≤ phiSeq n k + N / p := by omega + have h1r : (N : ℝ) ≤ (phiSeq n k : ℝ) + ((N / p : ℕ) : ℝ) := by exact_mod_cast h1 + have h2r : ((N / p : ℕ) : ℝ) ≤ (N : ℝ) / (p : ℝ) := Nat.cast_div_le + have hNr : (0 : ℝ) < N := by exact_mod_cast hN + have hpr : (0 : ℝ) < p := by exact_mod_cast hp.pos + rw [le_div_iff₀ hNr] + have : (N : ℝ) / p = (1 / p) * N := by field_simp + nlinarith + +/-- Erdős: for a strictly increasing sequence of positive integers, if +`liminf φ_A(k)/n_k = 0` then `limsup φ_A(k)/n_k = 1`. -/ +theorem limsup_eq_one : type_of% @Erdos1000.erdos_1000.variants.limsup_eq_one := by + intro n hn hn0 h + set f := fun k : ℕ => (phiSeq n k : ℝ) / (n k : ℝ) with hf + have hpos : ∀ k, 0 < n k := fun k => hn0.trans_le (hn.monotone (Nat.zero_le k)) + have hf0 : ∀ k, 0 ≤ f k := fun k => by positivity + have hf1 : ∀ k, f k ≤ 1 := fun k => by + rw [hf] + dsimp only + rw [div_le_one (by exact_mod_cast hpos k)]; exact_mod_cast phiSeq_le n k + have hbdd : IsBoundedUnder (· ≤ ·) atTop f := isBoundedUnder_of ⟨1, hf1⟩ + have hbdd' : IsBoundedUnder (· ≥ ·) atTop f := isBoundedUnder_of ⟨0, hf0⟩ + have key : ∀ P K : ℕ, ∃ k ≥ K, 1 - 1 / ((P:ℝ) + 1) ≤ f k := by + intro P K + set B := max P (n K) with hB + have hc : (0:ℝ) < 1 / (B.factorial : ℝ) := by positivity + have hfreq : ∃ᶠ k in atTop, f k < 1 / (B.factorial : ℝ) := by + apply frequently_lt_of_liminf_lt hbdd.isCoboundedUnder_flip + rw [h]; exact hc + obtain ⟨k, hk⟩ := hfreq.exists + have hex0 : ∃ p ∈ (n k).primeFactors, B < p := by + by_contra hcon + push Not at hcon + have h1 := totient_ratio_ge (hpos k) hcon + have h2 := erdos_1000.variants.totient_le n hn hn0 k + have h3 : ((n k).totient : ℝ) / n k ≤ f k := by + apply div_le_div_of_nonneg_right (by exact_mod_cast h2) (by positivity) + linarith + obtain ⟨p, hp, hBp⟩ := hex0 + have hpp := Nat.prime_of_mem_primeFactors hp + have hpdvd := Nat.dvd_of_mem_primeFactors hp + have hex : ∃ i, p ∣ n i := ⟨k, hpdvd⟩ + classical + refine ⟨Nat.find hex, ?_, ?_⟩ + · by_contra hlt + push Not at hlt + have h1 : n (Nat.find hex) ≤ n K := hn.monotone hlt.le + have h2 := Nat.le_of_dvd (hpos _) (Nat.find_spec hex) + have h3 : n K ≤ B := le_max_right _ _ + omega + · have h1 := ratio_ge n hn hn0 hpp (Nat.find_spec hex) (fun j hj => Nat.find_min hex hj) + have h2 : (P:ℝ) + 1 ≤ p := by + have : P ≤ B := le_max_left _ _ + exact_mod_cast (show P + 1 ≤ p by omega) + have h3 : 1 / (p:ℝ) ≤ 1 / ((P:ℝ)+1) := one_div_le_one_div_of_le (by positivity) h2 + show 1 - 1 / ((P:ℝ) + 1) ≤ (phiSeq n (Nat.find hex) : ℝ) / (n (Nat.find hex) : ℝ) + linarith + apply le_antisymm + · exact limsup_le_of_le hbdd'.isCoboundedUnder_flip (Eventually.of_forall hf1) + · apply le_of_forall_pos_lt_add + intro ε hε + obtain ⟨P, hP⟩ := exists_nat_one_div_lt hε + have : 1 - 1/((P:ℝ)+1) ≤ limsup f atTop := by + apply le_limsup_of_frequently_le _ hbdd + rw [frequently_atTop] + intro K + exact key P K + linarith + +end Math0.Erdos1000 + +#math0_proves Math0.Erdos1000.limsup_eq_one Erdos1000.erdos_1000.variants.limsup_eq_one diff --git a/lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_not_tendsto_zero.lean b/lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_not_tendsto_zero.lean new file mode 100644 index 0000000..01526a6 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_not_tendsto_zero.lean @@ -0,0 +1,138 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1000» +import Math0.Audit + +/-! +# Erdős Problem 1000: `φ_A(k)/n_k` does not tend to `0` + +For a strictly increasing sequence of positive integers `n_0 < n_1 < ⋯`, `φ_A(k)` counts the +`1 ≤ m ≤ n_k` such that `n_k / gcd(m, n_k)` divides no earlier `n_j` (Cassels; Erdős [Er64b], +erdosproblems.com/1000). We prove Erdős's observation, exactly as stated upstream: the ratios +`φ_A(k)/n_k` do not tend to `0`. If they did, they would eventually be `< 1/2`, say from index `K` +on, and also eventually `< 1/B!` with `B = max 2 n_K`. Since `φ_A(k) ≥ φ(n_k)` and `φ(N)/N ≥ 1/B!` +whenever all prime factors of `N` are `≤ B`, some `n_k` then has a prime factor `p > B`. At the +first index `k'` with `p ∣ n_{k'}` (necessarily `k' > K`, as `n_{k'} ≥ p > n_K`) every `m ≤ n_{k'}` +prime to `p` is counted, so `φ_A(k')/n_{k'} ≥ 1 - 1/p ≥ 1/2`, a contradiction. +-/ + +open Filter Topology Erdos1000 + +namespace Math0.Erdos1000 + +/-- If every prime factor of `N > 0` is at most `B`, then `φ(N)/N ≥ 1/B!` +(from `φ(N) · ∏_{p ∣ N} p = N · ∏_{p ∣ N} (p - 1) ≥ N` and `∏_{p ∣ N} p ∣ B!`). -/ +theorem totient_ratio_ge_inv_factorial {N B : ℕ} (hN : 0 < N) + (hB : ∀ p ∈ N.primeFactors, p ≤ B) : + (1 : ℝ) / (B.factorial : ℝ) ≤ (N.totient : ℝ) / N := by + have h1 : N ≤ N.totient * ∏ p ∈ N.primeFactors, p := by + rw [Nat.totient_mul_prod_primeFactors] + have : 1 ≤ ∏ p ∈ N.primeFactors, (p - 1) := by + apply Nat.one_le_iff_ne_zero.mpr + rw [Finset.prod_ne_zero_iff] + intro p hp + have := (Nat.prime_of_mem_primeFactors hp).two_le + omega + nlinarith + have h2 : ∏ p ∈ N.primeFactors, p ≤ B.factorial := by + rw [← Finset.prod_Ico_id_eq_factorial] + apply Nat.le_of_dvd (by rw [Finset.prod_Ico_id_eq_factorial]; exact Nat.factorial_pos B) + apply Finset.prod_dvd_prod_of_subset + intro p hp + have := (Nat.prime_of_mem_primeFactors hp).two_le + have := hB p hp + simp only [Finset.mem_Ico] + omega + have h3 : N ≤ N.totient * B.factorial := h1.trans (Nat.mul_le_mul_left _ h2) + have hNr : (0 : ℝ) < N := by exact_mod_cast hN + have hBr : (0 : ℝ) < B.factorial := by exact_mod_cast Nat.factorial_pos B + rw [div_le_div_iff₀ hBr hNr] + have : (N : ℝ) ≤ N.totient * B.factorial := by exact_mod_cast h3 + linarith + +/-- If `p` is prime, `p ∣ n_k`, and `p` divides no earlier `n_j`, then +`φ_A(k)/n_k ≥ 1 - 1/p`: every `m ≤ n_k` with `p ∤ m` is counted. -/ +theorem phiSeq_ratio_ge_of_new_prime (n : ℕ → ℕ) (hn : StrictMono n) (hn0 : 0 < n 0) + {p k : ℕ} (hp : p.Prime) (hk : p ∣ n k) (hmin : ∀ j < k, ¬ p ∣ n j) : + (1 : ℝ) - 1 / (p : ℝ) ≤ (phiSeq n k : ℝ) / (n k : ℝ) := by + set N := n k with hNdef + have hN : 0 < N := hn0.trans_le (hn.monotone (Nat.zero_le k)) + have hsub : (Finset.Icc 1 N).filter (fun m => ¬ p ∣ m) ⊆ + (Finset.Icc 1 N).filter (fun m => ∀ j < k, ¬ (N / Nat.gcd m N) ∣ n j) := by + intro m hm + simp only [Finset.mem_filter] at hm ⊢ + refine ⟨hm.1, fun j hj hdvd => ?_⟩ + have hg : N = (N / Nat.gcd m N) * Nat.gcd m N := + (Nat.div_mul_cancel (Nat.gcd_dvd_right m N)).symm + have hpd : p ∣ N / Nat.gcd m N := by + have : p ∣ (N / Nat.gcd m N) * Nat.gcd m N := hg ▸ hk + rcases (Nat.Prime.dvd_mul hp).1 this with h | h + · exact h + · exact absurd (h.trans (Nat.gcd_dvd_left m N)) hm.2 + exact hmin j hj (hpd.trans hdvd) + have hcard1 : ((Finset.Icc 1 N).filter (fun m => ¬ p ∣ m)).card ≤ phiSeq n k := + Finset.card_le_card hsub + have hcard2 : ((Finset.Icc 1 N).filter (fun m => p ∣ m)).card + + ((Finset.Icc 1 N).filter (fun m => ¬ p ∣ m)).card = N := by + rw [Finset.card_filter_add_card_filter_not]; simp + have hcard3 : ((Finset.Icc 1 N).filter (fun m => p ∣ m)).card = N / p := by + rw [← Nat.Ioc_filter_dvd_card_eq_div] + rfl + have h1 : N ≤ phiSeq n k + N / p := by omega + have h1r : (N : ℝ) ≤ (phiSeq n k : ℝ) + ((N / p : ℕ) : ℝ) := by exact_mod_cast h1 + have h2r : ((N / p : ℕ) : ℝ) ≤ (N : ℝ) / (p : ℝ) := Nat.cast_div_le + have hNr : (0 : ℝ) < N := by exact_mod_cast hN + have hpr : (0 : ℝ) < p := by exact_mod_cast hp.pos + rw [le_div_iff₀ hNr] + have : (N : ℝ) / p = (1 / p) * N := by field_simp + nlinarith + +/-- Erdős: for a strictly increasing sequence of positive integers `n`, the ratios +`φ_A(k)/n_k` do not tend to `0`. -/ +theorem not_tendsto_zero : type_of% @Erdos1000.erdos_1000.variants.not_tendsto_zero := by + intro n hn hn0 htend + set f := fun k : ℕ => (phiSeq n k : ℝ) / (n k : ℝ) with hf + have hpos : ∀ k, 0 < n k := fun k => hn0.trans_le (hn.monotone (Nat.zero_le k)) + -- eventually `f k < 1/2` + have hev : ∀ᶠ k in atTop, f k < 1 / 2 := htend.eventually (gt_mem_nhds (by norm_num)) + obtain ⟨K, hK⟩ := eventually_atTop.1 hev + set B := max 2 (n K) with hB + have hc : (0 : ℝ) < 1 / (B.factorial : ℝ) := by positivity + have hev2 : ∀ᶠ k in atTop, f k < 1 / (B.factorial : ℝ) := htend.eventually (gt_mem_nhds hc) + obtain ⟨k, hk⟩ := hev2.exists + -- `n k` has a prime factor `p > B` + have hex0 : ∃ p ∈ (n k).primeFactors, B < p := by + by_contra hcon + push Not at hcon + have h1 := totient_ratio_ge_inv_factorial (hpos k) hcon + have h2 := erdos_1000.variants.totient_le n hn hn0 k + have h3 : ((n k).totient : ℝ) / n k ≤ f k := by + apply div_le_div_of_nonneg_right (by exact_mod_cast h2) (by positivity) + linarith + obtain ⟨p, hp, hBp⟩ := hex0 + have hpp := Nat.prime_of_mem_primeFactors hp + have hpdvd := Nat.dvd_of_mem_primeFactors hp + have hex : ∃ i, p ∣ n i := ⟨k, hpdvd⟩ + classical + -- the first index at which `p` appears is `≥ K` + have hge : K ≤ Nat.find hex := by + by_contra hlt + push Not at hlt + have h1 : n (Nat.find hex) ≤ n K := hn.monotone hlt.le + have h2 := Nat.le_of_dvd (hpos _) (Nat.find_spec hex) + have h3 : n K ≤ B := le_max_right _ _ + omega + have h1 := phiSeq_ratio_ge_of_new_prime n hn hn0 hpp (Nat.find_spec hex) + (fun j hj => Nat.find_min hex hj) + have h2 : (2 : ℝ) ≤ p := by + have : 2 ≤ B := le_max_left _ _ + exact_mod_cast (show 2 ≤ p by omega) + have h3 : 1 / (p : ℝ) ≤ 1 / 2 := one_div_le_one_div_of_le (by norm_num) h2 + have h4 := hK _ hge + have h5 : f (Nat.find hex) = (phiSeq n (Nat.find hex) : ℝ) / (n (Nat.find hex) : ℝ) := rfl + linarith + +end Math0.Erdos1000 + +#math0_proves Math0.Erdos1000.not_tendsto_zero Erdos1000.erdos_1000.variants.not_tendsto_zero diff --git a/lean/Math0/ErdosProblems/Erdos1008_erdos_1008_variants_lower_bound.lean b/lean/Math0/ErdosProblems/Erdos1008_erdos_1008_variants_lower_bound.lean new file mode 100644 index 0000000..04469ad --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1008_erdos_1008_variants_lower_bound.lean @@ -0,0 +1,199 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1008» +import Math0.Audit + +/-! +# Erdős Problem 1008: the trivial `√m` lower bound for `C₄`-free subgraphs + +Erdős Problem 1008 asks whether every graph with `m` edges has a `C₄`-free subgraph with +`≫ m^{2/3}` edges; in [Er71] Erdős remarks that `≫ m^{1/2}` is trivial. This file proves exactly +the upstream statement `erdos_1008.variants.lower_bound`, with the constant `c = 1/2`: every finite +graph `G` with `m` edges has a `C₄`-free subgraph with at least `√m / 2` edges. +Let `Δ` be the maximum degree and `M` a maximum matching. Every edge of `G` meets an edge of `M` +(otherwise `M` could be enlarged), and at most `2Δ` edges meet a given edge, so `m ≤ 2|M|Δ`; +hence `max(Δ, |M|) ≥ √(m/2) ≥ √m/2`. Both the star at a maximum-degree vertex (all its edges +share the centre, while a `C₄` has two disjoint edges) and the matching (all degrees at most one, +while `C₄` is `2`-regular) are `C₄`-free. +-/ + +open SimpleGraph + +namespace Math0.Erdos1008 + +/-- The graph spanned by a finset `s` of edges of `G` is a subgraph of `G` with exactly +`s.card` edges. -/ +theorem fromEdgeSet_finset {V : Type} (G : SimpleGraph V) [Fintype G.edgeSet] + (s : Finset (Sym2 V)) (hs : s ⊆ G.edgeFinset) : + fromEdgeSet (s : Set (Sym2 V)) ≤ G ∧ + (fromEdgeSet (s : Set (Sym2 V))).edgeSet.ncard = s.card := by + have hs' : ∀ e ∈ s, e ∈ G.edgeSet := fun e he => by simpa using hs he + refine ⟨fun x y h => ?_, ?_⟩ + · rw [fromEdgeSet_adj] at h + exact (mem_edgeSet G).1 (hs' _ h.1) + · rw [edgeSet_fromEdgeSet] + have : (s : Set (Sym2 V)) \ Sym2.diagSet = s := by + ext e + constructor + · exact fun h => h.1 + · intro he + exact ⟨he, fun hd => G.not_isDiag_of_mem_edgeSet (hs' _ he) hd⟩ + rw [this, Set.ncard_coe_finset] + +/-- A finset of edges is a matching when any two of its edges sharing a vertex are equal. -/ +def IsMatch {V : Type} (M : Finset (Sym2 V)) : Prop := + ∀ e ∈ M, ∀ e' ∈ M, ∀ x, x ∈ e → x ∈ e' → e = e' + +/-- Every finite graph has a matching `M` (a maximum one) with `|E(G)| ≤ 2 |M| Δ(G)`: by +maximality every edge meets an edge of `M`, and each edge of `M` meets at most `2 Δ(G)` edges. -/ +theorem exists_matching {V : Type} [Fintype V] [DecidableEq V] (G : SimpleGraph V) + [DecidableRel G.Adj] : ∃ M : Finset (Sym2 V), M ⊆ G.edgeFinset ∧ IsMatch M ∧ + G.edgeFinset.card ≤ 2 * M.card * G.maxDegree := by + classical + set S := G.edgeFinset.powerset.filter (fun M => IsMatch M) with hS + have hne : S.Nonempty := + ⟨∅, Finset.mem_filter.2 ⟨Finset.empty_mem_powerset _, by simp [IsMatch]⟩⟩ + obtain ⟨M, hMS, hmax⟩ := S.exists_max_image Finset.card hne + simp only [hS, Finset.mem_filter, Finset.mem_powerset] at hMS + obtain ⟨hMsub, hMm⟩ := hMS + refine ⟨M, hMsub, hMm, ?_⟩ + -- every edge meets an edge of M + have hcover : ∀ e ∈ G.edgeFinset, ∃ f ∈ M, ∃ x, x ∈ f ∧ x ∈ e := by + intro e he + by_contra hcon + push Not at hcon + have heM : e ∉ M := by + intro heM + induction e using Sym2.ind with + | _ a b => exact hcon _ heM a (Sym2.mem_mk_left a b) (Sym2.mem_mk_left a b) + have hins : insert e M ∈ S := by + simp only [hS, Finset.mem_filter, Finset.mem_powerset] + refine ⟨Finset.insert_subset he hMsub, ?_⟩ + intro e1 he1 e2 he2 x hx1 hx2 + rw [Finset.mem_insert] at he1 he2 + rcases he1 with rfl | he1 <;> rcases he2 with rfl | he2 + · rfl + · exact absurd hx1 (hcon _ he2 x hx2) + · exact absurd hx2 (hcon _ he1 x hx1) + · exact hMm _ he1 _ he2 x hx1 hx2 + have := hmax _ hins + rw [Finset.card_insert_of_notMem heM] at this + omega + have hsub : G.edgeFinset ⊆ M.biUnion + (fun f => G.edgeFinset.filter (fun e => ∃ x, x ∈ f ∧ x ∈ e)) := by + intro e he + obtain ⟨f, hf, hx⟩ := hcover e he + exact Finset.mem_biUnion.2 ⟨f, hf, Finset.mem_filter.2 ⟨he, hx⟩⟩ + have hbound : ∀ f ∈ M, + (G.edgeFinset.filter (fun e => ∃ x, x ∈ f ∧ x ∈ e)).card ≤ 2 * G.maxDegree := by + intro f _ + induction f using Sym2.ind with + | _ a b => + have : G.edgeFinset.filter (fun e => ∃ x, x ∈ s(a, b) ∧ x ∈ e) ⊆ + G.incidenceFinset a ∪ G.incidenceFinset b := by + intro e he + simp only [Finset.mem_filter, Sym2.mem_iff] at he + obtain ⟨he, x, hx, hxe⟩ := he + rw [Finset.mem_union, mem_incidenceFinset, mem_incidenceFinset] + rw [mem_edgeFinset] at he + rcases hx with rfl | rfl + · exact Or.inl ⟨he, hxe⟩ + · exact Or.inr ⟨he, hxe⟩ + calc _ ≤ (G.incidenceFinset a ∪ G.incidenceFinset b).card := Finset.card_le_card this + _ ≤ (G.incidenceFinset a).card + (G.incidenceFinset b).card := Finset.card_union_le _ _ + _ = G.degree a + G.degree b := by + rw [card_incidenceFinset_eq_degree, card_incidenceFinset_eq_degree] + _ ≤ G.maxDegree + G.maxDegree := add_le_add (G.degree_le_maxDegree a) + (G.degree_le_maxDegree b) + _ = 2 * G.maxDegree := by ring + calc G.edgeFinset.card ≤ _ := Finset.card_le_card hsub + _ ≤ ∑ f ∈ M, (G.edgeFinset.filter (fun e => ∃ x, x ∈ f ∧ x ∈ e)).card := + Finset.card_biUnion_le + _ ≤ ∑ f ∈ M, 2 * G.maxDegree := Finset.sum_le_sum hbound + _ = 2 * M.card * G.maxDegree := by rw [Finset.sum_const, smul_eq_mul]; ring + +/-- A copy of `C₄` in `H` yields four distinct vertices `a, b, c, d` with `a ~ b ~ c ~ d`. -/ +theorem exists_c4 {V : Type} {H : SimpleGraph V} (h : cycleGraph 4 ⊑ H) : + ∃ a b c d : V, H.Adj a b ∧ H.Adj b c ∧ H.Adj c d ∧ + a ≠ b ∧ a ≠ c ∧ a ≠ d ∧ b ≠ c ∧ b ≠ d ∧ c ≠ d := by + obtain ⟨f⟩ := h + refine ⟨f 0, f 1, f 2, f 3, f.toHom.map_adj (by decide), f.toHom.map_adj (by decide), + f.toHom.map_adj (by decide), ?_, ?_, ?_, ?_, ?_, ?_⟩ <;> + exact f.injective.ne (by decide) + +/-- A graph all of whose edges contain a fixed vertex `v` (a star) is `C₄`-free. -/ +theorem free_of_star {V : Type} {H : SimpleGraph V} (v : V) + (hv : ∀ x y, H.Adj x y → x = v ∨ y = v) : (cycleGraph 4).Free H := by + intro h + obtain ⟨a, b, c, d, hab, -, hcd, h1, h2, h3, h4, h5, h6⟩ := exists_c4 h + rcases hv _ _ hab with rfl | rfl <;> rcases hv _ _ hcd with rfl | rfl <;> simp_all + +/-- A graph in which every vertex has at most one neighbour (a matching) is `C₄`-free. -/ +theorem free_of_matching {V : Type} {H : SimpleGraph V} + (hv : ∀ x y z, H.Adj x y → H.Adj x z → y = z) : (cycleGraph 4).Free H := by + intro h + obtain ⟨a, b, c, d, hab, hbc, -, -, h2, -⟩ := exists_c4 h + exact h2 (hv _ _ _ hab.symm hbc) + + +/-- If `m ≤ 2ab` and `a, b ≤ k` then `√m / 2 ≤ k`. -/ +theorem real_bound (m a b k : ℕ) (hm : m ≤ 2 * a * b) (ha : a ≤ k) (hb : b ≤ k) : + (1 / 2 : ℝ) * (m : ℝ) ^ (1 / 2 : ℝ) ≤ k := by + rw [← Real.sqrt_eq_rpow] + have h1 : (m : ℝ) ≤ (2 * k : ℝ) ^ 2 := by + have : m ≤ 4 * k * k := by + calc m ≤ 2 * a * b := hm + _ ≤ 2 * k * k := by gcongr + _ ≤ 4 * k * k := by gcongr; norm_num + have : (m : ℝ) ≤ 4 * k * k := by exact_mod_cast this + nlinarith + have h2 : Real.sqrt m ≤ 2 * k := Real.sqrt_le_iff.2 ⟨by positivity, h1⟩ + linarith + +/-- Every finite graph with `m` edges has a `C₄`-free subgraph with at least `(1/2) m^{1/2}` +edges; so the upstream statement holds with `c = 1/2`. -/ +theorem lower_bound : type_of% @Erdos1008.erdos_1008.variants.lower_bound := by + refine ⟨1 / 2, by norm_num, ?_⟩ + intro V _ G + classical + obtain ⟨M, hMsub, hMm, hcard⟩ := exists_matching G + have hm : G.edgeSet.ncard = G.edgeFinset.card := by + rw [← coe_edgeFinset, Set.ncard_coe_finset] + rw [hm] + by_cases hle : G.maxDegree ≤ M.card + · obtain ⟨hH, hHc⟩ := fromEdgeSet_finset G M hMsub + refine ⟨_, hH, ?_, ?_⟩ + · apply free_of_matching + intro x y z hxy hxz + rw [fromEdgeSet_adj] at hxy hxz + have := hMm _ hxy.1 _ hxz.1 x (Sym2.mem_mk_left x y) (Sym2.mem_mk_left x z) + exact Sym2.congr_right.1 this + · rw [hHc] + exact real_bound _ _ _ _ hcard le_rfl hle + · have hpos : 0 < G.maxDegree := by omega + have : Nonempty V := by + by_contra hne + rw [not_nonempty_iff] at hne + rw [maxDegree_of_subsingleton] at hpos + omega + obtain ⟨v, hv⟩ := G.exists_maximal_degree_vertex + have hsub : G.incidenceFinset v ⊆ G.edgeFinset := by + intro e he + rw [mem_incidenceFinset] at he + rw [mem_edgeFinset] + exact he.1 + obtain ⟨hH, hHc⟩ := fromEdgeSet_finset G _ hsub + refine ⟨_, hH, ?_, ?_⟩ + · apply free_of_star v + intro x y hxy + rw [fromEdgeSet_adj, Finset.mem_coe, mem_incidenceFinset] at hxy + rcases (Sym2.mem_iff.1 hxy.1.2) with h | h + · exact Or.inl h.symm + · exact Or.inr h.symm + · rw [hHc, card_incidenceFinset_eq_degree, ← hv] + exact real_bound _ _ _ _ hcard (by omega) le_rfl + +end Math0.Erdos1008 + +#math0_proves Math0.Erdos1008.lower_bound Erdos1008.erdos_1008.variants.lower_bound diff --git a/lean/Math0/ErdosProblems/Erdos1010_erdos_1010_variants_rademacher.lean b/lean/Math0/ErdosProblems/Erdos1010_erdos_1010_variants_rademacher.lean new file mode 100644 index 0000000..ccccb17 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1010_erdos_1010_variants_rademacher.lean @@ -0,0 +1,333 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1010» +import Math0.Audit + +/-! +# Rademacher's theorem on triangles (Erdős Problem 1010, Rademacher variant) + +Rademacher (1941, published by Erdős) proved that every graph on `n` vertices with +`⌊n²/4⌋ + 1` edges contains at least `⌊n/2⌋` triangles. We prove exactly the formal statement +`Erdos1010.erdos_1010.variants.rademacher` from formal-conjectures. The proof works with vertex +subsets `S` of a fixed finite graph and proves the stronger "at least `⌊|S|²/4⌋ + 1` edges" +version by strong induction on `|S|`: take a triangle `xyz` (Mantel's theorem, proved by the same +induction); if some edge of it, say `xy`, has `d(x) + d(y) ≤ |S|`, delete `x, y`, apply induction +and add the triangle `xyz`; otherwise every vertex outside `xyz` adjacent to `k` of `x, y, z` +gives at least `k - 1` triangles with an edge of `xyz`, which already yields `⌊|S|/2⌋` triangles. +-/ + +namespace Math0.Erdos1010 + +open Finset + +variable {V : Type*} [Fintype V] [DecidableEq V] (G : SimpleGraph V) [DecidableRel G.Adj] + +/-- The adjacency indicator `[v ~ w]`. -/ +def ind (v w : V) : ℕ := if G.Adj v w then 1 else 0 + +/-- The degree of `v` inside the vertex set `S`. -/ +def dg (S : Finset V) (v : V) : ℕ := ∑ w ∈ S, ind G v w + +/-- The degree sum inside `S`, i.e. twice the number of edges of the induced subgraph. -/ +def D (S : Finset V) : ℕ := ∑ v ∈ S, dg G S v + +/-- The triangles of `G` contained in `S`. -/ +def tri (S : Finset V) : Finset (Finset V) := (G.cliqueFinset 3).filter (· ⊆ S) + +omit [Fintype V] [DecidableEq V] in +/-- No loops. -/ +lemma ind_self (v : V) : ind G v v = 0 := by simp [ind] + +omit [Fintype V] [DecidableEq V] in +/-- The indicator is symmetric. -/ +lemma ind_comm (v w : V) : ind G v w = ind G w v := by + simp only [ind, G.adj_comm] + +omit [Fintype V] [DecidableEq V] in +/-- The indicator of an edge is `1`. -/ +lemma ind_of_adj {v w : V} (h : G.Adj v w) : ind G v w = 1 := by simp [ind, h] + +omit [Fintype V] in +/-- Splitting off one vertex from a degree. -/ +lemma dg_erase {S : Finset V} {x : V} (hx : x ∈ S) (v : V) : + dg G S v = ind G v x + dg G (S.erase x) v := by + unfold dg; rw [add_sum_erase _ _ hx] + +omit [Fintype V] in +/-- Deleting a vertex `x` from `S` lowers the degree sum by `2 d_S(x)`. -/ +lemma D_erase {S : Finset V} {x : V} (hx : x ∈ S) : + D G S = D G (S.erase x) + 2 * dg G S x := by + unfold D + rw [← add_sum_erase _ _ hx] + have h1 : ∀ v ∈ S.erase x, dg G S v = ind G x v + dg G (S.erase x) v := by + intro v _; rw [dg_erase G hx, ind_comm] + rw [sum_congr rfl h1, sum_add_distrib] + have h2 : dg G S x = ∑ v ∈ S.erase x, ind G x v := by + rw [dg_erase G hx, ind_self, zero_add]; rfl + omega + +omit [Fintype V] [DecidableEq V] in +/-- The degree as the size of a neighbourhood. -/ +lemma dg_eq_card (S : Finset V) (v : V) : dg G S v = (S.filter (G.Adj v)).card := by + rw [card_filter]; rfl + +omit [Fintype V] in +/-- Two vertices whose degree sum in `S` exceeds `|S|` have a common neighbour in `S`. -/ +lemma exists_common {S : Finset V} {x y : V} (h : S.card < dg G S x + dg G S y) : + ∃ z ∈ S, G.Adj x z ∧ G.Adj y z := by + rw [dg_eq_card, dg_eq_card] at h + have h1 := card_union_add_card_inter (S.filter (G.Adj x)) (S.filter (G.Adj y)) + have h2 : (S.filter (G.Adj x) ∪ S.filter (G.Adj y)).card ≤ S.card := + card_le_card (union_subset (filter_subset _ _) (filter_subset _ _)) + have h3 : (S.filter (G.Adj x) ∩ S.filter (G.Adj y)).Nonempty := by + rw [← card_pos]; omega + obtain ⟨z, hz⟩ := h3 + simp only [mem_inter, mem_filter] at hz + exact ⟨z, hz.1.1, hz.1.2, hz.2.2⟩ + +omit [Fintype V] [DecidableEq V] in +/-- A positive degree sum gives an edge. -/ +lemma exists_adj_of_D_pos {S : Finset V} (h : 0 < D G S) : ∃ x ∈ S, ∃ y ∈ S, G.Adj x y := by + by_contra hc + simp only [not_exists, not_and] at hc + have : D G S = 0 := by + unfold D dg + apply sum_eq_zero + intro v hv + apply sum_eq_zero + intro w hw + simp [ind, hc v hv w hw] + omega + +omit [Fintype V] in +/-- Deleting both ends of an edge `xy`. -/ +lemma D_erase_two {S : Finset V} {x y : V} (hx : x ∈ S) (hy : y ∈ S) (hxy : G.Adj x y) : + D G S + 2 = D G ((S.erase x).erase y) + 2 * dg G S x + 2 * dg G S y := by + have hy' : y ∈ S.erase x := mem_erase.2 ⟨(G.ne_of_adj hxy).symm, hy⟩ + rw [D_erase G hx, D_erase G hy', dg_erase G hx y, ind_of_adj G hxy.symm] + ring + +/-- `⌊(M+2)²/4⌋ = ⌊M²/4⌋ + M + 1`. -/ +lemma sq_div_four (M : ℕ) : (M + 2) ^ 2 / 4 = M ^ 2 / 4 + M + 1 := by + have : (M + 2) ^ 2 = M ^ 2 + (M + 1) * 4 := by ring + rw [this, Nat.add_mul_div_right _ _ (by norm_num)] + ring + +omit [Fintype V] in +/-- Deleting two vertices only shrinks the set. -/ +lemma card_erase_two_lt {S : Finset V} {x : V} (hx : x ∈ S) (y : V) : + ((S.erase x).erase y).card < S.card := + lt_of_le_of_lt card_erase_le (card_erase_lt_of_mem hx) + +omit [Fintype V] in +/-- The induction step for the edge count: deleting the ends of an edge `xy` with +`d(x) + d(y) ≤ |S|` keeps the hypothesis "at least `⌊|S|²/4⌋ + 1` edges". -/ +lemma step_bound {S : Finset V} {x y : V} (hx : x ∈ S) (hy : y ∈ S) (hxy : G.Adj x y) + (hdeg : dg G S x + dg G S y ≤ S.card) (hD : 2 * (S.card ^ 2 / 4 + 1) ≤ D G S) : + ((S.erase x).erase y).card + 2 = S.card ∧ + 2 * (((S.erase x).erase y).card ^ 2 / 4 + 1) ≤ D G ((S.erase x).erase y) := by + have hy' : y ∈ S.erase x := mem_erase.2 ⟨(G.ne_of_adj hxy).symm, hy⟩ + have hc : ((S.erase x).erase y).card + 2 = S.card := by + have := card_erase_add_one hx + have := card_erase_add_one hy' + omega + refine ⟨hc, ?_⟩ + have := D_erase_two G hx hy hxy + rw [← hc, sq_div_four] at hD + rw [← hc] at hdeg + omega + +omit [Fintype V] in +/-- Mantel's theorem, in the form needed here: at least `⌊|S|²/4⌋ + 1` edges inside `S` force a +triangle inside `S`. -/ +lemma mantel : ∀ (k : ℕ) (S : Finset V), S.card = k → 2 * (S.card ^ 2 / 4 + 1) ≤ D G S → + ∃ x ∈ S, ∃ y ∈ S, ∃ z ∈ S, G.Adj x y ∧ G.Adj x z ∧ G.Adj y z := by + intro k + induction k using Nat.strong_induction_on with + | _ k ih => + intro S hk hD + obtain ⟨x, hx, y, hy, hxy⟩ := exists_adj_of_D_pos G (S := S) (by omega) + by_cases hdeg : S.card < dg G S x + dg G S y + · obtain ⟨z, hz, hxz, hyz⟩ := exists_common G hdeg + exact ⟨x, hx, y, hy, z, hz, hxy, hxz, hyz⟩ + · obtain ⟨hc, hD'⟩ := step_bound G hx hy hxy (by omega) hD + obtain ⟨a, ha, b, hb, c, hc', h1, h2, h3⟩ := ih _ (by omega) _ rfl hD' + exact ⟨a, mem_of_mem_erase (mem_of_mem_erase ha), b, mem_of_mem_erase (mem_of_mem_erase hb), + c, mem_of_mem_erase (mem_of_mem_erase hc'), h1, h2, h3⟩ + +/-- A triangle with vertices in `S` belongs to `tri G S`. -/ +lemma mem_tri {S : Finset V} {a b c : V} (ha : a ∈ S) (hb : b ∈ S) (hc : c ∈ S) + (hab : G.Adj a b) (hac : G.Adj a c) (hbc : G.Adj b c) : + ({a, b, c} : Finset V) ∈ tri G S := by + unfold tri + rw [mem_filter, SimpleGraph.mem_cliqueFinset_iff, SimpleGraph.is3Clique_triple_iff] + refine ⟨⟨hab, hac, hbc⟩, ?_⟩ + intro v hv + simp only [mem_insert, mem_singleton] at hv + rcases hv with rfl | rfl | rfl <;> assumption + +/-- `tri` is monotone. -/ +lemma tri_mono {S T : Finset V} (h : S ⊆ T) : tri G S ⊆ tri G T := by + intro U hU + simp only [tri, mem_filter] at hU ⊢ + exact ⟨hU.1, hU.2.trans h⟩ + +/-- Case 1: some edge `xy` of the triangle `xyz` has `d(x) + d(y) ≤ |S|`. -/ +lemma case_one {S : Finset V} {x y z : V} (hx : x ∈ S) (hy : y ∈ S) (hz : z ∈ S) + (hxy : G.Adj x y) (hxz : G.Adj x z) (hyz : G.Adj y z) + (hdeg : dg G S x + dg G S y ≤ S.card) (hD : 2 * (S.card ^ 2 / 4 + 1) ≤ D G S) + (ih : 2 * (((S.erase x).erase y).card ^ 2 / 4 + 1) ≤ D G ((S.erase x).erase y) → + ((S.erase x).erase y).card / 2 ≤ (tri G ((S.erase x).erase y)).card) : + S.card / 2 ≤ (tri G S).card := by + obtain ⟨hc, hD'⟩ := step_bound G hx hy hxy hdeg hD + have h1 := ih hD' + have hsub : insert ({x, y, z} : Finset V) (tri G ((S.erase x).erase y)) ⊆ tri G S := by + apply insert_subset (mem_tri G hx hy hz hxy hxz hyz) + exact tri_mono G ((erase_subset _ _).trans (erase_subset _ _)) + have hnot : ({x, y, z} : Finset V) ∉ tri G ((S.erase x).erase y) := by + intro h + have := (mem_filter.1 h).2 (mem_insert_self x _) + simp at this + have := card_le_card hsub + rw [card_insert_of_notMem hnot] at this + omega + +/-- Case 2: every edge `uv` of the triangle `xyz` has `d(u) + d(v) > |S|`. -/ +lemma case_two {S : Finset V} {x y z : V} (hx : x ∈ S) (hy : y ∈ S) (hz : z ∈ S) + (hxy : G.Adj x y) (hxz : G.Adj x z) (hyz : G.Adj y z) + (h1 : S.card < dg G S x + dg G S y) (h2 : S.card < dg G S y + dg G S z) + (h3 : S.card < dg G S x + dg G S z) : + S.card / 2 ≤ (tri G S).card := by + have hne1 := G.ne_of_adj hxy + have hne2 := G.ne_of_adj hxz + have hne3 := G.ne_of_adj hyz + have hy' : y ∈ S.erase x := mem_erase.2 ⟨hne1.symm, hy⟩ + have hz' : z ∈ (S.erase x).erase y := mem_erase.2 ⟨hne3.symm, mem_erase.2 ⟨hne2.symm, hz⟩⟩ + have hcard : (((S.erase x).erase y).erase z).card + 3 = S.card := by + have := card_erase_add_one hx + have := card_erase_add_one hy' + have := card_erase_add_one hz' + omega + have dx : dg G S x = 2 + dg G (((S.erase x).erase y).erase z) x := by + rw [dg_erase G hx, dg_erase G hy', dg_erase G hz', ind_self, ind_of_adj G hxy, + ind_of_adj G hxz] + ring + have dy : dg G S y = 2 + dg G (((S.erase x).erase y).erase z) y := by + rw [dg_erase G hx, dg_erase G hy', dg_erase G hz', ind_self, ind_of_adj G hxy.symm, + ind_of_adj G hyz] + ring + have dz : dg G S z = 2 + dg G (((S.erase x).erase y).erase z) z := by + rw [dg_erase G hx, dg_erase G hy', dg_erase G hz', ind_self, ind_of_adj G hxz.symm, + ind_of_adj G hyz.symm] + ring + let p : Fin 3 → V := ![x, y, x] + let r : Fin 3 → V := ![y, z, z] + have hpr : ∀ i, p i ∈ S ∧ r i ∈ S ∧ G.Adj (p i) (r i) := by + intro i; fin_cases i <;> simp [p, r, hx, hy, hz, hxy, hxz, hyz] + have hpr' : ∀ i, (p i = x ∨ p i = y ∨ p i = z) ∧ (r i = x ∨ r i = y ∨ r i = z) := by + intro i; fin_cases i <;> simp [p, r] + set R := ((S.erase x).erase y).erase z with hR + have hRmem : ∀ w ∈ R, w ∈ S ∧ w ≠ x ∧ w ≠ y ∧ w ≠ z := by + intro w hw; simp only [R, mem_erase] at hw; tauto + let P := (R ×ˢ (univ : Finset (Fin 3))).filter + (fun q => G.Adj (p q.2) q.1 ∧ G.Adj (r q.2) q.1) + let f : V × Fin 3 → Finset V := fun q => {p q.2, r q.2, q.1} + have hP : dg G R x + dg G R y + dg G R z ≤ P.card + R.card := by + simp only [P] + rw [card_filter, sum_product, card_eq_sum_ones R] + unfold dg + rw [← sum_add_distrib, ← sum_add_distrib, ← sum_add_distrib] + apply sum_le_sum + intro w _ + simp only [Fin.sum_univ_three, p, r, ind] + by_cases ha : G.Adj x w <;> by_cases hb : G.Adj y w <;> by_cases hc : G.Adj z w <;> + simp [ha, hb, hc] + have hinj : Set.InjOn f P := by + rintro ⟨w, i⟩ hq ⟨w', i'⟩ hq' hf + simp only [P, coe_filter, mem_product] at hq hq' + obtain ⟨hw, hwx, hwy, hwz⟩ := hRmem w hq.1.1 + simp only [f] at hf + have ew : w ∈ ({p i', r i', w'} : Finset V) := by rw [← hf]; simp + simp only [mem_insert, mem_singleton] at ew + have hww : w = w' := by + rcases ew with h | h | h + · rcases (hpr' i').1 with h' | h' | h' + · exact absurd (h.trans h') hwx + · exact absurd (h.trans h') hwy + · exact absurd (h.trans h') hwz + · rcases (hpr' i').2 with h' | h' | h' + · exact absurd (h.trans h') hwx + · exact absurd (h.trans h') hwy + · exact absurd (h.trans h') hwz + · exact h + subst hww + have ex : x ∈ ({p i, r i, w} : Finset V) ↔ x ∈ ({p i', r i', w} : Finset V) := by rw [hf] + have ey : y ∈ ({p i, r i, w} : Finset V) ↔ y ∈ ({p i', r i', w} : Finset V) := by rw [hf] + have ez : z ∈ ({p i, r i, w} : Finset V) ↔ z ∈ ({p i', r i', w} : Finset V) := by rw [hf] + clear hf hq hq' hpr hpr' hRmem + fin_cases i <;> fin_cases i' <;> + first + | rfl + | (exfalso + simp [p, r, hne1, hne2, hne3, hne1.symm, hwx.symm, hwy.symm] at ex ey ez) + have hsub : insert ({x, y, z} : Finset V) (P.image f) ⊆ tri G S := by + apply insert_subset (mem_tri G hx hy hz hxy hxz hyz) + intro T hT + rw [mem_image] at hT + obtain ⟨⟨w, i⟩, hq, rfl⟩ := hT + simp only [P, mem_filter, mem_product] at hq + exact mem_tri G (hpr i).1 (hpr i).2.1 (hRmem w hq.1.1).1 (hpr i).2.2 hq.2.1 hq.2.2 + have hnot : ({x, y, z} : Finset V) ∉ P.image f := by + intro h + rw [mem_image] at h + obtain ⟨⟨w, i⟩, hq, hf⟩ := h + simp only [P, mem_filter, mem_product] at hq + obtain ⟨-, hwx, hwy, hwz⟩ := hRmem w hq.1.1 + have hw : w ∈ ({x, y, z} : Finset V) := hf ▸ (by simp [f]) + simp only [mem_insert, mem_singleton] at hw + tauto + have := card_le_card hsub + rw [card_insert_of_notMem hnot, card_image_of_injOn hinj] at this + omega + +/-- The main induction: at least `⌊|S|²/4⌋ + 1` edges inside `S` give at least `⌊|S|/2⌋` +triangles inside `S`. -/ +lemma main : ∀ (k : ℕ) (S : Finset V), S.card = k → 2 * (S.card ^ 2 / 4 + 1) ≤ D G S → + S.card / 2 ≤ (tri G S).card := by + intro k + induction k using Nat.strong_induction_on with + | _ k ih => + intro S hk hD + obtain ⟨x, hx, y, hy, z, hz, hxy, hxz, hyz⟩ := mantel G _ S rfl hD + by_cases c1 : dg G S x + dg G S y ≤ S.card + · exact case_one G hx hy hz hxy hxz hyz c1 hD + (fun h => ih _ (hk ▸ card_erase_two_lt hx y) _ rfl h) + by_cases c2 : dg G S y + dg G S z ≤ S.card + · exact case_one G hy hz hx hyz hxy.symm hxz.symm c2 hD + (fun h => ih _ (hk ▸ card_erase_two_lt hy z) _ rfl h) + by_cases c3 : dg G S x + dg G S z ≤ S.card + · exact case_one G hx hz hy hxz hxy hyz.symm c3 hD + (fun h => ih _ (hk ▸ card_erase_two_lt hx z) _ rfl h) + exact case_two G hx hy hz hxy hxz hyz (by omega) (by omega) (by omega) + +omit [DecidableEq V] in +/-- The degree sum over all vertices is twice the number of edges. -/ +lemma D_univ : D G univ = 2 * G.edgeFinset.card := by + rw [← G.sum_degrees_eq_twice_card_edges] + unfold D + apply sum_congr rfl + intro v _ + rw [dg_eq_card, ← G.card_neighborFinset_eq_degree, G.neighborFinset_eq_filter] + +/-- Rademacher's theorem: every graph on `n` vertices with `⌊n²/4⌋ + 1` edges contains at least +`⌊n/2⌋` triangles. -/ +theorem erdos_1010_rademacher : type_of% @Erdos1010.erdos_1010.variants.rademacher := by + intro n G h + classical + have key := main G _ (univ : Finset (Fin n)) rfl (by rw [D_univ, h]; simp) + simpa [tri] using key + +end Math0.Erdos1010 + +#math0_proves Math0.Erdos1010.erdos_1010_rademacher Erdos1010.erdos_1010.variants.rademacher diff --git a/lean/Math0/ErdosProblems/Erdos1026_erdos_1026_variants_upper_bound.lean b/lean/Math0/ErdosProblems/Erdos1026_erdos_1026_variants_upper_bound.lean new file mode 100644 index 0000000..20e8d71 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1026_erdos_1026_variants_upper_bound.lean @@ -0,0 +1,213 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1026» +import Math0.Audit + +/-! +# Erdős Problem 1026: the constant `c` is at most `1` (Cambie's construction) + +Erdős Problem 1026 (erdosproblems.com/1026, in van Doorn's formulation) asks for the largest `c` +such that every sequence of `n` distinct positive reals has a monotone subsequence whose sum is at +least `(c - o(1)) n^{-1/2} ∑ xᵢ`. We prove the upstream statement `1 ∈ upperBounds +admissibleConstants`, i.e. no constant `c > 1` is admissible. The proof uses Cambie's +construction: for `n = k ^ 2` split the indices into `k` consecutive blocks of length `k`, make +the values increase inside each block and decrease from block to block, all within `[1, 1 + 1/k]`. +An increasing subsequence meets only one block and a decreasing one meets each block at most once, +so every monotone subsequence has at most `k` terms and sum at most `k + 1`, while the total sum +is at least `k ^ 2`; this rules out every `c > 1` once `k` is large. +-/ + +namespace Math0.Erdos1026 + +/-- The block-reversed rank of `i`: block `i / k` contributes `-k * (i / k)`, position `i % k` +within the block contributes `i % k`. -/ +noncomputable def rank (k i : ℕ) : ℝ := ((i % k : ℕ) : ℝ) - (k : ℝ) * ((i / k : ℕ) : ℝ) + +/-- Within a block the rank increases; across blocks it decreases. -/ +theorem rank_cases {k i j : ℕ} (hk : 0 < k) (hij : i < j) : + (i / k = j / k ∧ rank k i < rank k j) ∨ (i / k < j / k ∧ rank k j < rank k i) := by + have hdiv : i / k ≤ j / k := Nat.div_le_div_right hij.le + have hi := Nat.div_add_mod i k + have hj := Nat.div_add_mod j k + have hik := Nat.mod_lt i hk + have hjk := Nat.mod_lt j hk + rcases hdiv.lt_or_eq with h | h + · right + refine ⟨h, ?_⟩ + have h1 : ((i / k : ℕ) : ℝ) + 1 ≤ ((j / k : ℕ) : ℝ) := by exact_mod_cast h + have h2 : ((j % k : ℕ) : ℝ) + 1 ≤ (k : ℝ) := by exact_mod_cast hjk + have h3 : (0 : ℝ) ≤ ((i % k : ℕ) : ℝ) := Nat.cast_nonneg _ + have h4 : (0 : ℝ) ≤ (k : ℝ) := Nat.cast_nonneg _ + unfold rank + nlinarith + · left + refine ⟨h, ?_⟩ + have hlt : i % k < j % k := by + rw [h] at hi + omega + unfold rank + rw [h] + have : ((i % k : ℕ) : ℝ) < ((j % k : ℕ) : ℝ) := by exact_mod_cast hlt + linarith + +/-- Bounds on the rank for `i < k ^ 2`. -/ +theorem rank_bounds {k i : ℕ} (hk : 0 < k) (hi : i < k ^ 2) : + 0 ≤ rank k i + (k : ℝ) ^ 2 ∧ rank k i + (k : ℝ) ^ 2 ≤ 2 * (k : ℝ) ^ 2 := by + have h1 := Nat.mod_lt i hk + have h2 : k * (i / k) ≤ i := Nat.mul_div_le i k + have h3 : ((i % k : ℕ) : ℝ) ≤ (k : ℝ) := by exact_mod_cast h1.le + have h4 : (k : ℝ) * ((i / k : ℕ) : ℝ) ≤ (k : ℝ) ^ 2 := by + have : k * (i / k) ≤ k ^ 2 := by omega + exact_mod_cast this + have h5 : (1 : ℝ) ≤ (k : ℝ) := by exact_mod_cast hk + have h6 : (0 : ℝ) ≤ ((i % k : ℕ) : ℝ) := Nat.cast_nonneg _ + have h7 : (0 : ℝ) ≤ (k : ℝ) * ((i / k : ℕ) : ℝ) := by positivity + unfold rank + constructor <;> nlinarith + +/-- Cambie's sequence of length `k ^ 2`: `xᵢ = 1 + (rank k i + k ^ 2) / (2 k ^ 3)`. -/ +noncomputable def cambie (k : ℕ) (i : Fin (k ^ 2)) : ℝ := + 1 + (rank k i + (k : ℝ) ^ 2) / (2 * (k : ℝ) ^ 3) + +/-- Cambie's sequence is ordered exactly like the rank. -/ +theorem cambie_lt_iff {k : ℕ} (hk : 0 < k) (i j : Fin (k ^ 2)) : + cambie k i < cambie k j ↔ rank k i < rank k j := by + have : (0 : ℝ) < 2 * (k : ℝ) ^ 3 := by positivity + unfold cambie + constructor + · intro h + have := (div_lt_div_iff_of_pos_right this).mp (by linarith : (rank k i + (k : ℝ) ^ 2) / (2 * (k : ℝ) ^ 3) < (rank k j + (k : ℝ) ^ 2) / (2 * (k : ℝ) ^ 3)) + linarith + · intro h + have := (div_lt_div_iff_of_pos_right this).mpr (by linarith : rank k i + (k : ℝ) ^ 2 < rank k j + (k : ℝ) ^ 2) + linarith + +/-- All values of Cambie's sequence lie in `[1, 1 + 1/k]`. -/ +theorem cambie_bounds {k : ℕ} (hk : 0 < k) (i : Fin (k ^ 2)) : + 1 ≤ cambie k i ∧ cambie k i ≤ 1 + 1 / (k : ℝ) := by + obtain ⟨h1, h2⟩ := rank_bounds hk i.isLt + have hk' : (0 : ℝ) < k := by exact_mod_cast hk + have : (0 : ℝ) < 2 * (k : ℝ) ^ 3 := by positivity + unfold cambie + constructor + · have : 0 ≤ (rank k i + (k : ℝ) ^ 2) / (2 * (k : ℝ) ^ 3) := div_nonneg h1 this.le + linarith + · have : (rank k i + (k : ℝ) ^ 2) / (2 * (k : ℝ) ^ 3) ≤ 1 / (k : ℝ) := by + rw [div_le_div_iff₀ this hk'] + nlinarith + linarith + +/-- Cambie's sequence consists of distinct numbers. -/ +theorem cambie_injective {k : ℕ} (hk : 0 < k) : Function.Injective (cambie k) := by + intro i j h + by_contra hne + rcases lt_or_gt_of_ne hne with hlt | hlt + · rcases rank_cases hk (show (i : ℕ) < j from hlt) with ⟨_, h'⟩ | ⟨_, h'⟩ + · exact absurd h ((cambie_lt_iff hk i j).mpr h').ne + · exact absurd h ((cambie_lt_iff hk j i).mpr h').ne' + · rcases rank_cases hk (show (j : ℕ) < i from hlt) with ⟨_, h'⟩ | ⟨_, h'⟩ + · exact absurd h ((cambie_lt_iff hk j i).mpr h').ne' + · exact absurd h ((cambie_lt_iff hk i j).mpr h').ne + +/-- An increasing subsequence of Cambie's sequence has at most `k` terms. -/ +theorem card_le_of_monotoneOn {k : ℕ} (hk : 0 < k) {I : Finset (Fin (k ^ 2))} + (hI : MonotoneOn (cambie k) ↑I) : I.card ≤ k := by + have aux : ∀ i ∈ I, ∀ j ∈ I, (i : ℕ) < j → (i : ℕ) % k ≠ (j : ℕ) % k := by + intro i hi j hj hij hmod + rcases rank_cases hk hij with ⟨hd, _⟩ | ⟨_, h'⟩ + · have := Nat.div_add_mod (i : ℕ) k + have := Nat.div_add_mod (j : ℕ) k + rw [hd, hmod] at * + omega + · have h1 := hI (Finset.mem_coe.mpr hi) (Finset.mem_coe.mpr hj) (le_of_lt hij) + have h2 := (cambie_lt_iff hk j i).mpr h' + linarith + have := Finset.card_le_card_of_injOn (fun i : Fin (k ^ 2) => (i : ℕ) % k) (t := Finset.range k) + (fun i _ => Finset.mem_coe.mpr (Finset.mem_range.mpr (Nat.mod_lt _ hk))) (by + intro i hi j hj h + simp only at h + by_contra hne + rcases lt_or_gt_of_ne hne with hlt | hlt + · exact aux i hi j hj hlt h + · exact aux j hj i hi hlt h.symm) + simpa using this + +/-- A decreasing subsequence of Cambie's sequence has at most `k` terms. -/ +theorem card_le_of_antitoneOn {k : ℕ} (hk : 0 < k) {I : Finset (Fin (k ^ 2))} + (hI : AntitoneOn (cambie k) ↑I) : I.card ≤ k := by + have aux : ∀ i ∈ I, ∀ j ∈ I, (i : ℕ) < j → (i : ℕ) / k ≠ (j : ℕ) / k := by + intro i hi j hj hij hdiv + rcases rank_cases hk hij with ⟨_, h'⟩ | ⟨hd, _⟩ + · have h1 := hI (Finset.mem_coe.mpr hi) (Finset.mem_coe.mpr hj) (le_of_lt hij) + have h2 := (cambie_lt_iff hk i j).mpr h' + linarith + · omega + have := Finset.card_le_card_of_injOn (fun i : Fin (k ^ 2) => (i : ℕ) / k) (t := Finset.range k) + (fun i _ => Finset.mem_coe.mpr (Finset.mem_range.mpr (by + rw [Nat.div_lt_iff_lt_mul hk] + have := i.isLt + nlinarith))) (by + intro i hi j hj h + simp only at h + by_contra hne + rcases lt_or_gt_of_ne hne with hlt | hlt + · exact aux i hi j hj hlt h + · exact aux j hj i hi hlt h.symm) + simpa using this + +/-- Every monotone subsequence sum of Cambie's sequence is at most `k + 1`. -/ +theorem sum_le {k : ℕ} (hk : 0 < k) {S : ℝ} + (hS : S ∈ Erdos1026.monotonicSubsequenceSums (cambie k)) : S ≤ k + 1 := by + obtain ⟨I, hI, rfl⟩ := hS + have hcard : I.card ≤ k := hI.elim (card_le_of_monotoneOn hk) (card_le_of_antitoneOn hk) + have hk' : (0 : ℝ) < k := by exact_mod_cast hk + calc ∑ i ∈ I, cambie k i ≤ ∑ _i ∈ I, (1 + 1 / (k : ℝ)) := + Finset.sum_le_sum fun i _ => (cambie_bounds hk i).2 + _ = (I.card : ℝ) * (1 + 1 / (k : ℝ)) := by rw [Finset.sum_const, nsmul_eq_mul] + _ ≤ (k : ℝ) * (1 + 1 / (k : ℝ)) := by gcongr + _ = k + 1 := by field_simp + +/-- The total sum of Cambie's sequence is at least `k ^ 2`. -/ +theorem total_ge {k : ℕ} (hk : 0 < k) : (k : ℝ) ^ 2 ≤ ∑ i, cambie k i := by + calc (k : ℝ) ^ 2 = ∑ _i : Fin (k ^ 2), (1 : ℝ) := by simp + _ ≤ ∑ i, cambie k i := Finset.sum_le_sum fun i _ => (cambie_bounds hk i).1 + +/-- No constant `c > 1` is admissible: `1` is an upper bound of `admissibleConstants`. -/ +theorem upper_bound : type_of% @Erdos1026.erdos_1026.variants.upper_bound := by + intro c hc + by_contra hnot + have hlt : 1 < c := not_le.mp hnot + set δ : ℝ := (c - 1) / 2 with hδ + have hδpos : 0 < δ := by rw [hδ]; linarith + obtain ⟨N, hN⟩ := Filter.eventually_atTop.mp (hc δ hδpos) + obtain ⟨m, hm⟩ := exists_nat_gt (1 / δ) + set k : ℕ := max (max N m) 1 with hkdef + have hk : 0 < k := by omega + have hkN : N ≤ k ^ 2 := by + have : k ≤ k ^ 2 := by nlinarith + omega + have hkm : (m : ℝ) ≤ k := by exact_mod_cast (show m ≤ k by omega) + obtain ⟨S, hS, hle⟩ := hN (k ^ 2) hkN (cambie k) (cambie_injective hk) + (fun i => lt_of_lt_of_le one_pos (cambie_bounds hk i).1) + have hS' := sum_le hk hS + have htot := total_ge hk + have hk' : (0 : ℝ) < k := by exact_mod_cast hk + have hsqrt : Real.sqrt ((k ^ 2 : ℕ) : ℝ) = k := by + push_cast + exact Real.sqrt_sq hk'.le + rw [hsqrt] at hle + have hce : c - δ = 1 + δ := by rw [hδ]; ring + rw [hce] at hle + have h1 : (1 + δ) / (k : ℝ) * (k : ℝ) ^ 2 ≤ (1 + δ) / (k : ℝ) * ∑ i, cambie k i := by + gcongr + have h2 : (1 + δ) / (k : ℝ) * (k : ℝ) ^ 2 = (1 + δ) * k := by + field_simp + have h3 : 1 < δ * k := by + have := (div_lt_iff₀ hδpos).mp hm + nlinarith + nlinarith + +end Math0.Erdos1026 + +#math0_proves Math0.Erdos1026.upper_bound Erdos1026.erdos_1026.variants.upper_bound diff --git a/lean/Math0/ErdosProblems/Erdos1048_erdos_1048_variants_diam_ge_two_is_best.lean b/lean/Math0/ErdosProblems/Erdos1048_erdos_1048_variants_diam_ge_two_is_best.lean new file mode 100644 index 0000000..2065e9a --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1048_erdos_1048_variants_diam_ge_two_is_best.lean @@ -0,0 +1,62 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1048» +import Math0.Audit + +/-! +# Erdős Problem 1048: the bound `diam ≥ 2` is attained by `zⁿ` + +Erdős, Herzog and Piranian [EHP58] showed that when all roots of a monic polynomial `f` lie in +`|z| ≤ r ≤ 1/2`, the component of `{z : |f(z)| ≤ 1}` containing `0` has diameter at least `2`. +We prove that this is best possible: for `f = Xⁿ` with `n ≥ 1`, the connected component of the +level set `{z : |zⁿ| ≤ 1}` containing `0` has (extended) diameter exactly `2`. The level set is +the closed unit disk, which is convex and hence preconnected, so it is its own connected +component; its diameter is at most `2` by the triangle inequality and at least `2` since it +contains `1` and `-1`. +-/ + +namespace Math0.Erdos1048 + +open Polynomial Erdos1043 + +/-- For `n ≥ 1`, the level set `{z : ‖zⁿ‖ ≤ 1}` is the closed unit disk. -/ +theorem levelSet_X_pow (n : ℕ) (hn : 1 ≤ n) : + levelSet ((X : ℂ[X]) ^ n) = Metric.closedBall (0 : ℂ) 1 := by + ext z + simp only [levelSet, Set.mem_ofPred_eq, eval_pow, eval_X, norm_pow, Metric.mem_closedBall, + dist_zero_right] + exact pow_le_one_iff_of_nonneg (norm_nonneg z) (by omega) + +/-- The closed unit disk in `ℂ` has extended diameter exactly `2`. -/ +theorem ediam_closedBall_one : + Metric.ediam (Metric.closedBall (0 : ℂ) 1) = 2 := by + apply le_antisymm + · apply Metric.ediam_le + intro x hx y hy + rw [Metric.mem_closedBall, dist_zero_right] at hx hy + rw [edist_dist] + have : dist x y ≤ 2 := by + calc dist x y ≤ ‖x‖ + ‖y‖ := by rw [dist_eq_norm]; exact norm_sub_le x y + _ ≤ 2 := by linarith + calc ENNReal.ofReal (dist x y) ≤ ENNReal.ofReal 2 := ENNReal.ofReal_le_ofReal this + _ = 2 := by norm_num + · have h1 : (1 : ℂ) ∈ Metric.closedBall (0 : ℂ) 1 := by simp + have h2 : (-1 : ℂ) ∈ Metric.closedBall (0 : ℂ) 1 := by simp + have := Metric.edist_le_ediam_of_mem h1 h2 + have he : edist (1 : ℂ) (-1) = 2 := by + rw [edist_dist, dist_eq_norm] + norm_num + rwa [he] at this + +/-- For every `n ≥ 1`, the connected component containing `0` of the level set +`{z : ‖zⁿ‖ ≤ 1}` has extended diameter exactly `2`. -/ +theorem diam_ge_two_is_best : type_of% @Erdos1048.erdos_1048.variants.diam_ge_two_is_best := by + intro n hn + rw [levelSet_X_pow n hn, (convex_closedBall (0 : ℂ) 1).isPreconnected.connectedComponentIn + (Metric.mem_closedBall_self zero_le_one)] + exact ediam_closedBall_one + +end Math0.Erdos1048 + +#math0_proves Math0.Erdos1048.diam_ge_two_is_best Erdos1048.erdos_1048.variants.diam_ge_two_is_best diff --git a/lean/Math0/ErdosProblems/Erdos1098_erdos_1098_variants_upper_bound.lean b/lean/Math0/ErdosProblems/Erdos1098_erdos_1098_variants_upper_bound.lean new file mode 100644 index 0000000..4519a65 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1098_erdos_1098_variants_upper_bound.lean @@ -0,0 +1,54 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1098» +import Math0.Audit + +/-! +# Erdős Problem 1098: cliques in the non-commuting graph are bounded by the index of the centre + +Let `Γ(G)` be the non-commuting graph of a group `G` (vertices the elements of `G`, with `g ~ h` +iff `gh ≠ hg`); see erdosproblems.com/1098 and Neumann [Ne76]. We prove Neumann's remark, exactly +as stated upstream: if the centre `Z(G)` has finite index `n`, then `Γ(G)` has no clique on +`n + 1` vertices. The proof is a pigeonhole argument: two distinct vertices of a clique cannot lie +in the same coset of `Z(G)`, since then `y = x z` with `z` central and `x, y` would commute; so a +clique injects into `G ⧸ Z(G)`, which has exactly `n` elements. +-/ + +namespace Math0.Erdos1098 + +/-- Two elements in the same left coset of the centre commute. -/ +theorem commute_of_mk_eq {G : Type*} [Group G] {x y : G} + (h : (QuotientGroup.mk x : G ⧸ Subgroup.center G) = QuotientGroup.mk y) : + x * y = y * x := by + rw [QuotientGroup.eq] at h + have hz := Subgroup.mem_center_iff.mp h + have hy : y = x * (x⁻¹ * y) := by group + rw [hy] + have := hz x + calc x * (x * (x⁻¹ * y)) = x * ((x⁻¹ * y) * x) := by rw [this] + _ = x * (x⁻¹ * y) * x := by group + +/-- A clique of the non-commuting graph maps injectively to `G ⧸ Z(G)`. -/ +theorem injOn_mk_of_isClique {G : Type*} [Group G] {t : Finset G} + (ht : (_root_.Erdos1098.nonCommutingGraph G).IsClique (t : Set G)) : + Set.InjOn (QuotientGroup.mk : G → G ⧸ Subgroup.center G) (t : Set G) := by + intro x hx y hy hxy + by_contra hne + exact ht hx hy hne (commute_of_mk_eq hxy) + +/-- If the centre of `G` has finite index `n`, then the non-commuting graph of `G` contains no +complete subgraph on `n + 1` vertices. -/ +theorem upper_bound : type_of% @Erdos1098.erdos_1098.variants.upper_bound := by + intro G _ _ t ht + have hfin : Finite (G ⧸ Subgroup.center G) := Subgroup.finite_quotient_of_finiteIndex + let _ : Fintype (G ⧸ Subgroup.center G) := Fintype.ofFinite _ + have hle : t.card ≤ (Finset.univ : Finset (G ⧸ Subgroup.center G)).card := + Finset.card_le_card_of_injOn _ (fun _ _ => Finset.mem_coe.mpr (Finset.mem_univ _)) + (injOn_mk_of_isClique ht.isClique) + rw [Finset.card_univ, ← Nat.card_eq_fintype_card, ← Subgroup.index, ht.card_eq] at hle + omega + +end Math0.Erdos1098 + +#math0_proves Math0.Erdos1098.upper_bound Erdos1098.erdos_1098.variants.upper_bound diff --git a/lean/Math0/ErdosProblems/Erdos10_erdos_10_variants_grechuk_example.lean b/lean/Math0/ErdosProblems/Erdos10_erdos_10_variants_grechuk_example.lean new file mode 100644 index 0000000..2fabe84 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos10_erdos_10_variants_grechuk_example.lean @@ -0,0 +1,145 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«10» +import Math0.Audit + +/-! +# Erdős Problem 10: Grechuk's example 1117175146 + +Erdős Problem 10 asks whether every large integer is a prime plus a bounded number of powers +of two. Bogdan Grechuk observed that `1117175146` is not the sum of a prime and at most three +powers of two; this file proves exactly the upstream statement +`1117175146 ∉ sumPrimeAndTwoPows 3`. Any power of two `≤ 1117175146` is `2 ^ e` with `e ≤ 30`, +so it suffices to check, for every choice of at most three exponents in `[0, 30]` whose powers +sum to `s ≤ 1117175146`, that `1117175146 - s` has a proper divisor from an explicit list of 38 +small primes (2 handles every even remainder; the odd remainders need primes up to 19391). +This finite certificate check is carried out by the Lean kernel (`decide +kernel`). +-/ + +namespace Math0.Erdos10 + +/-- Candidate small prime factors (2 plus every least prime factor that occurs). -/ +def wit : List ℕ := [2, 3, 5, 7, 11, 13, 17, 19, 23, 37, 41, 47, 59, 61, 73, 79, 89, 97, 101, 103, + 107, 131, 163, 199, 211, 229, 257, 379, 547, 659, 877, 1381, 1481, 1699, 2099, 7283, 7703, 19391] + +/-- `good m` certifies that `m` is not prime: either `m < 2`, or some listed `q ≥ 2` is a +proper divisor of `m`. -/ +def good (m : ℕ) : Bool := m < 2 || wit.any (fun q => m % q == 0 && q < m) + +/-- A certified number is not prime. -/ +theorem not_prime_of_good {m : ℕ} (h : good m = true) : ¬ m.Prime := by + intro hp + unfold good at h + rcases Bool.or_eq_true_iff.1 h with h | h + · have := hp.two_le + simp at h + omega + · obtain ⟨q, hq, hq'⟩ := List.any_eq_true.1 h + simp only [Bool.and_eq_true, beq_iff_eq, decide_eq_true_eq] at hq' + have hq2 : 2 ≤ q := by + simp only [wit, List.mem_cons, List.not_mem_nil, or_false] at hq + rcases hq with h | h | h | h | h | h | h | h | h | h | h | h | h | h | h | h | h | h | h | + h | h | h | h | h | h | h | h | h | h | h | h | h | h | h | h | h | h | h <;> omega + rcases hp.eq_one_or_self_of_dvd q (Nat.dvd_of_mod_eq_zero hq'.1) with h | h <;> omega + + +/-- Every sum of three powers of two not exceeding `1117175146` leaves a certified remainder. -/ +def check3 : Bool := + (List.range 31).all fun x => (List.range 31).all fun y => (List.range 31).all fun z => + !(2 ^ x + 2 ^ y + 2 ^ z ≤ 1117175146) || good (1117175146 - (2 ^ x + 2 ^ y + 2 ^ z)) + +/-- Every sum of two powers of two not exceeding `1117175146` leaves a certified remainder. -/ +def check2 : Bool := + (List.range 31).all fun x => (List.range 31).all fun y => + !(2 ^ x + 2 ^ y ≤ 1117175146) || good (1117175146 - (2 ^ x + 2 ^ y)) + +/-- Every power of two not exceeding `1117175146` leaves a certified remainder. -/ +def check1 : Bool := + (List.range 31).all fun x => !(2 ^ x ≤ 1117175146) || good (1117175146 - 2 ^ x) + +/-- Kernel verification of `check3`. -/ +theorem check3_eq : check3 = true := by decide +kernel + +/-- Kernel verification of `check2`. -/ +theorem check2_eq : check2 = true := by decide +kernel + +/-- Kernel verification of `check1`. -/ +theorem check1_eq : check1 = true := by decide +kernel + +/-- `1117175146` itself is certified (it is even and larger than 2). -/ +theorem good_N : good 1117175146 = true := by decide +kernel + +/-- An exponent whose power of two is at most `1117175146` is at most 30. -/ +theorem exp_lt {x : ℕ} (h : 2 ^ x ≤ 1117175146) : x < 31 := by + by_contra hx + have : 2 ^ 31 ≤ 2 ^ x := Nat.pow_le_pow_right (by norm_num) (by omega) + norm_num at this + omega + +/-- Unpacked form of `check3_eq`: a three-term certificate for arbitrary exponents. -/ +theorem spec3 {x y z : ℕ} (hs : 2 ^ x + 2 ^ y + 2 ^ z ≤ 1117175146) : + good (1117175146 - (2 ^ x + 2 ^ y + 2 ^ z)) = true := by + have := Nat.one_le_two_pow (n := x) + have := Nat.one_le_two_pow (n := y) + have := Nat.one_le_two_pow (n := z) + have hx : x < 31 := exp_lt (by omega) + have hy : y < 31 := exp_lt (by omega) + have hz : z < 31 := exp_lt (by omega) + have h := check3_eq + unfold check3 at h + rw [List.all_eq_true] at h + have h := h x (List.mem_range.2 hx) + rw [List.all_eq_true] at h + have h := h y (List.mem_range.2 hy) + rw [List.all_eq_true] at h + have h := h z (List.mem_range.2 hz) + simpa [hs] using h + +/-- Unpacked form of `check2_eq`: a two-term certificate for arbitrary exponents. -/ +theorem spec2 {x y : ℕ} (hs : 2 ^ x + 2 ^ y ≤ 1117175146) : + good (1117175146 - (2 ^ x + 2 ^ y)) = true := by + have := Nat.one_le_two_pow (n := x) + have := Nat.one_le_two_pow (n := y) + have hx : x < 31 := exp_lt (by omega) + have hy : y < 31 := exp_lt (by omega) + have h := check2_eq + unfold check2 at h + rw [List.all_eq_true] at h + have h := h x (List.mem_range.2 hx) + rw [List.all_eq_true] at h + have h := h y (List.mem_range.2 hy) + simpa [hs] using h + +/-- Unpacked form of `check1_eq`: a one-term certificate for arbitrary exponents. -/ +theorem spec1 {x : ℕ} (hs : 2 ^ x ≤ 1117175146) : good (1117175146 - 2 ^ x) = true := by + have hx : x < 31 := exp_lt hs + have h := check1_eq + unfold check1 at h + rw [List.all_eq_true] at h + have h := h x (List.mem_range.2 hx) + simpa [hs] using h + +/-- Grechuk's observation: `1117175146` is not a prime plus at most three powers of two. -/ +theorem erdos_10_grechuk_example : type_of% @Erdos10.erdos_10.variants.grechuk_example := by + rintro ⟨p, pows, hp, hcard, h⟩ + induction pows using Quotient.inductionOn with + | h l => + rcases l with _ | ⟨a, _ | ⟨b, _ | ⟨c, _ | ⟨d, l⟩⟩⟩⟩ + · simp at h + exact not_prime_of_good (h ▸ good_N) hp + · simp at h + have hs : 2 ^ a ≤ 1117175146 := by omega + exact not_prime_of_good (show p = 1117175146 - 2 ^ a by omega ▸ spec1 hs) hp + · simp at h + have hs : 2 ^ a + 2 ^ b ≤ 1117175146 := by omega + exact not_prime_of_good (show p = 1117175146 - (2 ^ a + 2 ^ b) by omega ▸ spec2 hs) hp + · simp at h + have hs : 2 ^ a + 2 ^ b + 2 ^ c ≤ 1117175146 := by omega + exact not_prime_of_good (show p = 1117175146 - (2 ^ a + 2 ^ b + 2 ^ c) by omega ▸ spec3 hs) hp + · simp at hcard + omega + +end Math0.Erdos10 + +#math0_proves Math0.Erdos10.erdos_10_grechuk_example Erdos10.erdos_10.variants.grechuk_example diff --git a/lean/Math0/ErdosProblems/Erdos1119_erdos_1119_variants_erdos_wetzel.lean b/lean/Math0/ErdosProblems/Erdos1119_erdos_1119_variants_erdos_wetzel.lean new file mode 100644 index 0000000..01cde42 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1119_erdos_1119_variants_erdos_wetzel.lean @@ -0,0 +1,94 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1119» +import Math0.Audit + +/-! +# Erdős's answer to Wetzel's problem (Erdős Problem 1119, variant) + +Wetzel asked whether a family of entire functions taking only countably many values at each +point of `ℂ` must itself be countable. Erdős [Er64g] showed that the answer is yes when +`ℵ₁ < 𝔠`; we prove the upstream formal statement `erdos_1119.variants.erdos_wetzel`. +If the family `F` were uncountable, choose `G ⊆ F` with `#G = ℵ₁`. By the identity theorem two +distinct entire functions agree only on a discrete, hence countable, subset of `ℂ`, so the union +`S` of all coincidence sets of distinct pairs from `G` has cardinality at most +`ℵ₁ · ℵ₁ · ℵ₀ = ℵ₁ < 𝔠 = #ℂ`. A point `z ∉ S` makes `f ↦ f z` injective on `G`, so `F` takes +`ℵ₁` (uncountably many) values at `z`, a contradiction. +-/ + +namespace Math0.Erdos1119 + +open Cardinal Set Filter Topology + +/-- Two distinct entire functions agree on only countably many points: by the identity theorem +their coincidence set is discrete, and a discrete subset of `ℂ` is countable. -/ +theorem countable_setOf_eq {f g : ℂ → ℂ} (hf : Differentiable ℂ f) (hg : Differentiable ℂ g) + (hfg : f ≠ g) : {z | f z = g z}.Countable := by + have hfa : AnalyticOnNhd ℂ f univ := fun z _ => hf.analyticAt z + have hga : AnalyticOnNhd ℂ g univ := fun z _ => hg.analyticAt z + rcases hfa.eqOn_or_eventually_ne_of_preconnected hga isPreconnected_univ with h | h + · exact absurd (funext fun z => h (mem_univ z)) hfg + · have := isDiscrete_of_codiscreteWithin (U := univ) (s := {z | f z = g z}) h + simpa using (HereditarilyLindelofSpace.isLindelof _).countable_of_isDiscrete this + +universe u + +/-- The hypothesis `ℵ₁ < 𝔠` does not depend on the universe in which it is stated. -/ +theorem aleph_one_lt_continuum_zero (h : (ℵ_ 1 : Cardinal.{u}) < 𝔠) : + (ℵ_ 1 : Cardinal.{0}) < 𝔠 := by + rw [← lift_lt.{0, u}, lift_aleph, Ordinal.lift_one, lift_continuum] + exact h + +/-- **Erdős–Wetzel.** If `ℵ₁ < 𝔠`, then every family of entire functions taking only countably +many distinct values at each point of `ℂ` is countable. -/ +theorem erdos_wetzel : type_of% @Erdos1119.erdos_1119.variants.erdos_wetzel := by + intro h F hF hval + by_contra hFc + -- an uncountable family contains a subfamily `G` of cardinality exactly `ℵ₁` + have h1 : ℵ₁ ≤ #F := by + rw [aleph_one_le_iff] + exact lt_of_not_ge fun h' => hFc (le_aleph0_iff_set_countable.mp h') + obtain ⟨G, hGF, hG⟩ := le_mk_iff_exists_subset.mp h1 + -- coincidence sets of distinct pairs from `G` + let A : G × G → Set ℂ := fun p => {z | p.1.1 z = p.2.1 z ∧ p.1 ≠ p.2} + have hA : ∀ p, (A p).Countable := by + intro p + by_cases hp : p.1 = p.2 + · simp [A, hp] + · exact (countable_setOf_eq (hF _ (hGF p.1.2)) (hF _ (hGF p.2.2)) + (fun e => hp (Subtype.ext e))).mono (fun z hz => hz.1) + -- their union has cardinality at most `ℵ₁` + have hS : #(⋃ p, A p) ≤ ℵ₁ := by + calc #(⋃ p, A p) ≤ #(G × G) * ⨆ p, #(A p) := mk_iUnion_le _ + _ ≤ ℵ₁ * ℵ₀ := by + gcongr + · rw [mk_prod, lift_id, hG, mul_eq_self (aleph0_le_aleph 1)] + · exact ciSup_le' fun p => le_aleph0_iff_set_countable.mpr (hA p) + _ = ℵ₁ := by + rw [mul_eq_max (aleph0_le_aleph 1) le_rfl] + exact max_eq_left (aleph0_le_aleph 1) + -- since `ℵ₁ < 𝔠 = #ℂ`, some point `z` lies outside the union + have hex : ∃ z, z ∉ ⋃ p, A p := by + by_contra hall + simp only [not_exists, not_not] at hall + have : #(⋃ p, A p) = 𝔠 := by rw [eq_univ_of_forall hall, mk_univ_complex] + exact absurd (hS.trans_lt (aleph_one_lt_continuum_zero h)) (by rw [this]; exact lt_irrefl _) + obtain ⟨z, hz⟩ := hex + -- evaluation at `z` is injective on `G`, so `F` takes uncountably many values at `z` + have hinj : InjOn (fun f : ℂ → ℂ => f z) G := by + intro f hf g hg hfg + by_contra hne + exact hz (mem_iUnion.mpr ⟨(⟨f, hf⟩, ⟨g, hg⟩), hfg, fun e => hne (congrArg Subtype.val e)⟩) + have himg : #((fun f : ℂ → ℂ => f z) '' G) = ℵ₁ := by + rw [mk_image_eq_of_injOn _ _ hinj, hG] + have hsub : (fun f : ℂ → ℂ => f z) '' G ⊆ {y | ∃ f ∈ F, f z = y} := by + rintro _ ⟨f, hf, rfl⟩ + exact ⟨f, hGF hf, rfl⟩ + have hc := (hval z).mono hsub + rw [← le_aleph0_iff_set_countable, himg] at hc + exact absurd hc (not_le.mpr aleph0_lt_aleph_one) + +end Math0.Erdos1119 + +#math0_proves Math0.Erdos1119.erdos_wetzel Erdos1119.erdos_1119.variants.erdos_wetzel diff --git a/lean/Math0/ErdosProblems/Erdos1121_erdos_1121_variants_higher_dimension.lean b/lean/Math0/ErdosProblems/Erdos1121_erdos_1121_variants_higher_dimension.lean new file mode 100644 index 0000000..088cc65 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1121_erdos_1121_variants_higher_dimension.lean @@ -0,0 +1,168 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1121» +import Math0.Audit + +/-! +# Erdős Problem 1121 in higher dimensions (Goodman–Goodman) + +Let `B_i = closedBall (c i) (r i)` (`r i > 0`) be finitely many balls in `ℝ^d` such that every +hyperplane disjoint from all the balls has all the centres strictly on one side. We prove the +upstream statement that all the balls lie in one ball of radius `R = ∑ r i`, as conjectured by +Erdős and proved by Goodman and Goodman (1945). The centre is the weighted centroid +`z = R⁻¹ • ∑ r i • c i`. For `p ∈ B_i` and `v = p - z ≠ 0`, project onto `v`: the balls become +intervals `[a_j - r_j‖v‖, a_j + r_j‖v‖]` with `a_j = ⟪v, c_j⟫`. The separation hypothesis forces +each gap `(e_j, U]` (with `e_j = a_j + r_j‖v‖`, `U = max e`) to be covered by the intervals with +larger right end, so a length (Lebesgue measure) bound and a weighted sum over `j` give +`U ≤ ⟪v, z⟫ + R‖v‖`; since `⟪v, p⟫ ≤ U`, this yields `‖v‖² ≤ R‖v‖`. +-/ + +namespace Math0.Erdos1121 + +/-- If a half-open interval `(x, U]` is covered by finitely many closed intervals, its length is +at most the total length of the covering intervals. -/ +theorem length_le_of_cover {ι : Type*} (S : Finset ι) (lo hi : ι → ℝ) + (hlh : ∀ l ∈ S, lo l ≤ hi l) (x U : ℝ) + (hcov : Set.Ioc x U ⊆ ⋃ l ∈ S, Set.Icc (lo l) (hi l)) : + U - x ≤ ∑ l ∈ S, (hi l - lo l) := by + have h1 : MeasureTheory.volume (Set.Ioc x U) ≤ + ∑ l ∈ S, MeasureTheory.volume (Set.Icc (lo l) (hi l)) := + (MeasureTheory.measure_mono hcov).trans (MeasureTheory.measure_biUnion_finset_le S _) + rw [Real.volume_Ioc] at h1 + simp only [Real.volume_Icc] at h1 + rw [← ENNReal.ofReal_sum_of_nonneg (fun l hl => sub_nonneg.mpr (hlh l hl))] at h1 + exact (ENNReal.ofReal_le_ofReal_iff + (Finset.sum_nonneg fun l hl => sub_nonneg.mpr (hlh l hl))).mp h1 + +/-- Summing `r j * r l` over ordered pairs with `e j < e l`, twice, is at most the sum over all +pairs of distinct indices. -/ +theorem two_mul_sum_lt_le {n : ℕ} (r e : Fin n → ℝ) (hr : ∀ i, 0 ≤ r i) : + 2 * ∑ j, ∑ l ∈ Finset.univ.filter (fun l => e j < e l), r j * r l ≤ + (∑ i, r i) ^ 2 - ∑ i, r i ^ 2 := by + have h1 : ∀ j l, (if e j < e l then r j * r l else 0) + (if e l < e j then r l * r j else 0) ≤ + r j * r l - if j = l then r j * r l else 0 := by + intro j l + by_cases hjl : j = l + · subst hjl; simp + · simp only [hjl, if_false, sub_zero] + have := mul_nonneg (hr j) (hr l) + split_ifs with h2 h3 h3 + · exact absurd h3 (lt_asymm h2) + · linarith + · linarith [mul_comm (r j) (r l)] + · linarith + have hc : ∑ j, ∑ l, (if e j < e l then r j * r l else 0) = + ∑ j, ∑ l, (if e l < e j then r l * r j else 0) := Finset.sum_comm + simp only [Finset.sum_filter] + rw [two_mul] + nth_rewrite 2 [hc] + rw [← Finset.sum_add_distrib] + calc ∑ j, ((∑ l, if e j < e l then r j * r l else 0) + ∑ l, if e l < e j then r l * r j else 0) + = ∑ j, ∑ l, ((if e j < e l then r j * r l else 0) + if e l < e j then r l * r j else 0) := by + refine Finset.sum_congr rfl fun j _ => ?_ + rw [Finset.sum_add_distrib] + _ ≤ ∑ j, ∑ l, (r j * r l - if j = l then r j * r l else 0) := + Finset.sum_le_sum fun j _ => Finset.sum_le_sum fun l _ => h1 j l + _ = (∑ i, r i) ^ 2 - ∑ i, r i ^ 2 := by + simp only [Finset.sum_sub_distrib, Finset.sum_ite_eq, Finset.mem_univ, if_true, sq, + Finset.sum_mul_sum] + +/-- Goodman–Goodman in `ℝ^d`: if no hyperplane disjoint from finitely many balls separates their +centres, then all the balls lie in a single ball whose radius is the sum of their radii. -/ +theorem erdos_1121_higher_dimension : type_of% @Erdos1121.erdos_1121.variants.higher_dimension := by + intro d n c r hr hsep + refine ⟨(∑ i, r i)⁻¹ • ∑ i, r i • c i, ?_⟩ + intro p hp + rw [Set.mem_iUnion] at hp + obtain ⟨i, hi⟩ := hp + set R := ∑ i, r i with hR + have hRpos : 0 < R := Finset.sum_pos (fun j _ => hr j) ⟨i, Finset.mem_univ _⟩ + set z := R⁻¹ • ∑ i, r i • c i with hz + rw [Metric.mem_closedBall, dist_eq_norm] + set v := p - z with hv + by_cases hv0 : v = 0 + · rw [hv0, norm_zero]; exact hRpos.le + set N := ‖v‖ with hNdef + have hN : 0 < N := norm_pos_iff.mpr hv0 + set a : Fin n → ℝ := fun j => inner ℝ v (c j) with ha + set e : Fin n → ℝ := fun j => a j + r j * N with he + obtain ⟨k, -, hk⟩ := Finset.exists_max_image Finset.univ e ⟨i, Finset.mem_univ _⟩ + have hproj : ∀ j, ∀ q ∈ Metric.closedBall (c j) (r j), + inner ℝ v q ∈ Set.Icc (a j - r j * N) (a j + r j * N) := by + intro j q hq + rw [Metric.mem_closedBall, dist_eq_norm] at hq + have h1 : |inner ℝ v (q - c j)| ≤ N * ‖q - c j‖ := abs_real_inner_le_norm v (q - c j) + have h2 : N * ‖q - c j‖ ≤ N * r j := mul_le_mul_of_nonneg_left hq hN.le + rw [inner_sub_right] at h1 + have h3 := abs_le.mp (h1.trans h2) + simp only [ha] + constructor <;> nlinarith [h3.1, h3.2] + have hcov : ∀ j, Set.Ioc (e j) (e k) ⊆ + ⋃ l ∈ Finset.univ.filter (fun l => e j < e l), Set.Icc (a l - r l * N) (a l + r l * N) := by + intro j t ht + by_contra hnot + simp only [Set.mem_iUnion, Finset.mem_filter, Finset.mem_univ, true_and, not_exists] at hnot + have hmiss : ∀ l, ∀ q ∈ Metric.closedBall (c l) (r l), inner ℝ v q ≠ t := by + intro l q hq heq + have hpl := hproj l q hq + rw [heq] at hpl + by_cases hjl : e j < e l + · exact hnot l hjl hpl + · have : e l < t := lt_of_le_of_lt (not_lt.mp hjl) ht.1 + have : t ≤ e l := hpl.2 + linarith + rcases hsep v t hv0 hmiss with hall | hall + · have hak := hall k + have hjk : e j < e k := lt_of_lt_of_le ht.1 ht.2 + apply hnot k hjk + have : 0 ≤ r k * N := mul_nonneg (hr k).le hN.le + exact ⟨by simp only [ha] at hak ⊢; linarith, ht.2⟩ + · have haj := hall j + have : 0 ≤ r j * N := mul_nonneg (hr j).le hN.le + have : e j < t := ht.1 + simp only [he, ha] at this haj + linarith + have hlen : ∀ j, e k - e j ≤ + ∑ l ∈ Finset.univ.filter (fun l => e j < e l), 2 * N * r l := by + intro j + have := length_le_of_cover (Finset.univ.filter (fun l => e j < e l)) + (fun l => a l - r l * N) (fun l => a l + r l * N) + (fun l _ => by have := mul_nonneg (hr l).le hN.le; linarith) (e j) (e k) (hcov j) + refine this.trans (le_of_eq ?_) + refine Finset.sum_congr rfl fun l _ => ?_ + ring + have hsum : ∑ j, r j * (e k - e j) ≤ N * (R ^ 2 - ∑ j, r j ^ 2) := by + calc ∑ j, r j * (e k - e j) + ≤ ∑ j, r j * ∑ l ∈ Finset.univ.filter (fun l => e j < e l), 2 * N * r l := + Finset.sum_le_sum fun j _ => mul_le_mul_of_nonneg_left (hlen j) (hr j).le + _ = N * (2 * ∑ j, ∑ l ∈ Finset.univ.filter (fun l => e j < e l), r j * r l) := by + simp only [Finset.mul_sum] + refine Finset.sum_congr rfl fun j _ => Finset.sum_congr rfl fun l _ => ?_ + ring + _ ≤ N * (R ^ 2 - ∑ j, r j ^ 2) := + mul_le_mul_of_nonneg_left (two_mul_sum_lt_le r e fun i => (hr i).le) hN.le + have hsa : ∑ j, r j * a j = R * inner ℝ v z := by + rw [hz, inner_smul_right, inner_sum] + simp only [inner_smul_right, ha] + rw [← mul_assoc, mul_inv_cancel₀ hRpos.ne', one_mul] + have hpU : inner ℝ v p ≤ e k := le_trans (hproj i p hi).2 (hk i (Finset.mem_univ _)) + have hexp : ∑ j, r j * (e k - e j) = R * e k - R * inner ℝ v z - N * ∑ j, r j ^ 2 := by + have : ∀ j, r j * (e k - e j) = e k * r j - r j * a j - N * r j ^ 2 := by + intro j; simp only [he]; ring + rw [Finset.sum_congr rfl fun j _ => this j, Finset.sum_sub_distrib, Finset.sum_sub_distrib, + ← Finset.mul_sum, ← Finset.mul_sum, hsa] + ring + have hvv : inner ℝ v p - inner ℝ v z = N ^ 2 := by + rw [← inner_sub_right, ← hv, real_inner_self_eq_norm_sq] + have key : R * N ^ 2 ≤ N * R ^ 2 := by nlinarith + have : N ≤ R := by + by_contra hcon + push Not at hcon + have : R * N * R < R * N * N := mul_lt_mul_of_pos_left hcon (mul_pos hRpos hN) + nlinarith + exact this + +end Math0.Erdos1121 + +#math0_proves Math0.Erdos1121.erdos_1121_higher_dimension Erdos1121.erdos_1121.variants.higher_dimension diff --git a/lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_mueller.lean b/lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_mueller.lean new file mode 100644 index 0000000..d293827 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_mueller.lean @@ -0,0 +1,245 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1136» +import Math0.Audit + +/-! +# Erdős Problem 1136: Müller's set avoids powers of two and has density 1/2 + +Erdős Problem 1136 asks for a set `A ⊆ ℕ` of large lower density such that no sum `a + b` +(`a, b ∈ A`, not necessarily distinct) is a power of two. Müller (2011) showed that the set `M` +of naturals congruent to `3 · 2^i` modulo `2^(i+2)` for some `i` works, with density `1/2`. We +prove exactly this. Elements of `M` are the numbers `2^i (4q+3)`; for `i ≤ j` the sum +`2^i (4q+3) + 2^j (4r+3)` is `2^i` times an odd number `≥ 3` (if `i < j`) or `2^(i+1)` times an +odd number `≥ 3` (if `i = j`), so it is never a power of two. For the density, the counting +function `c(b) = #(M ∩ [0, b))` satisfies `c(b) = ⌊b/4⌋ + c(⌊(b+1)/2⌋)`, from which +`2 c(b) ≤ b ≤ 2 c(b) + 2k + ⌊b/2^k⌋` for every `k`, and `c(b)/b → 1/2` follows. +-/ + +namespace Math0.Erdos1136 + +open _root_.Erdos1136 Filter Topology + +/-- Membership in Müller's set: `n` is in it iff `n = 2^i (4q+3)` for some `i, q`. -/ +theorem mem_muellerSet_iff (n : ℕ) : + n ∈ muellerSet ↔ ∃ i q : ℕ, n = 2 ^ i * (4 * q + 3) := by + constructor + · rintro ⟨i, hi⟩ + have hlt : 3 * 2 ^ i < 2 ^ (i + 2) := by + rw [pow_add]; have := pow_pos (by norm_num : (0:ℕ) < 2) i; omega + have h1 : n % 2 ^ (i + 2) = 3 * 2 ^ i := by + rw [hi, Nat.mod_eq_of_lt hlt] + have h2 := Nat.mod_add_div n (2 ^ (i + 2)) + rw [h1] at h2 + refine ⟨i, n / 2 ^ (i + 2), ?_⟩ + generalize n / 2 ^ (i + 2) = q at h2 ⊢ + rw [← h2]; ring + · rintro ⟨i, q, rfl⟩ + refine ⟨i, ?_⟩ + have : 2 ^ i * (4 * q + 3) = 3 * 2 ^ i + 2 ^ (i + 2) * q := by ring + rw [this] + exact Nat.add_mul_mod_self_left _ _ _ + +/-- A sum `2^i (4q+3) + 2^j (4r+3)` with `i ≤ j` is never a power of two. -/ +theorem sum_ne_pow_of_le (i j q r k : ℕ) (hij : i ≤ j) : + 2 ^ i * (4 * q + 3) + 2 ^ j * (4 * r + 3) ≠ 2 ^ k := by + intro h + obtain ⟨d, rfl⟩ := Nat.exists_eq_add_of_le hij + have hfac : 2 ^ i * (4 * q + 3 + 2 ^ d * (4 * r + 3)) = 2 ^ k := by + rw [← h, pow_add]; ring + have hdvd : (4 * q + 3 + 2 ^ d * (4 * r + 3)) ∣ 2 ^ k := Dvd.intro_left _ hfac + obtain ⟨l, -, hl⟩ := (Nat.dvd_prime_pow Nat.prime_two).1 hdvd + rcases d with _ | d + · rcases l with _ | _ | _ | l + · simp at hl; omega + · simp at hl; omega + · simp at hl; omega + · rw [pow_add] at hl + simp at hl + omega + · rcases l with _ | l + · simp at hl + omega + · have h3 : 4 * q + 3 + 2 * (2 ^ d * (4 * r + 3)) = 2 * 2 ^ l := by + calc 4 * q + 3 + 2 * (2 ^ d * (4 * r + 3)) = 4 * q + 3 + 2 ^ (d + 1) * (4 * r + 3) := by + ring + _ = 2 ^ (l + 1) := hl + _ = 2 * 2 ^ l := by ring + generalize 2 ^ d * (4 * r + 3) = y at h3 + generalize 2 ^ l = z at h3 + omega + +/-- Müller's set avoids powers of two. -/ +theorem avoids : AvoidsPowersOfTwo muellerSet := by + intro a ha b hb k + obtain ⟨i, q, rfl⟩ := (mem_muellerSet_iff a).1 ha + obtain ⟨j, r, rfl⟩ := (mem_muellerSet_iff b).1 hb + rcases le_total i j with hij | hij + · exact sum_ne_pow_of_le i j q r k hij + · rw [add_comm]; exact sum_ne_pow_of_le j i r q k hij + +/-- `0` is not in Müller's set. -/ +theorem zero_not_mem : (0 : ℕ) ∉ muellerSet := by + rw [mem_muellerSet_iff] + rintro ⟨i, q, h⟩ + have : 2 ^ i * (4 * q + 3) ≠ 0 := by positivity + exact this h.symm + +/-- Doubling: `2m` is in Müller's set iff `m` is. -/ +theorem two_mul_mem_iff (m : ℕ) : 2 * m ∈ muellerSet ↔ m ∈ muellerSet := by + rw [mem_muellerSet_iff, mem_muellerSet_iff] + constructor + · rintro ⟨i, q, h⟩ + cases i with + | zero => simp at h; omega + | succ i => + refine ⟨i, q, ?_⟩ + have : 2 * m = 2 * (2 ^ i * (4 * q + 3)) := by rw [h]; ring + omega + · rintro ⟨i, q, h⟩ + exact ⟨i + 1, q, by rw [h, pow_succ]; ring⟩ + +/-- An odd number is in Müller's set iff it is `3 mod 4`. -/ +theorem odd_mem_iff (m : ℕ) : 2 * m + 1 ∈ muellerSet ↔ (2 * m + 1) % 4 = 3 := by + rw [mem_muellerSet_iff] + constructor + · rintro ⟨i, q, h⟩ + cases i with + | zero => simp at h; omega + | succ i => + have : 2 * m + 1 = 2 * (2 ^ i * (4 * q + 3)) := by rw [h]; ring + omega + · intro h + exact ⟨0, (2 * m + 1) / 4, by simp; omega⟩ + +open Classical in +/-- The counting function `c(b) = #(M ∩ [0, b))` of Müller's set. -/ +noncomputable def cnt (b : ℕ) : ℕ := Nat.count (· ∈ muellerSet) b + +open Classical in +/-- One-step recursion for the counting function. -/ +theorem cnt_succ (b : ℕ) : cnt (b + 1) = cnt b + if b ∈ muellerSet then 1 else 0 := by + unfold cnt + exact Nat.count_succ _ _ + +/-- `c(b+1) = c(b) + 1` when `b ∈ M`. -/ +theorem cnt_succ_of_mem {b : ℕ} (h : b ∈ muellerSet) : cnt (b + 1) = cnt b + 1 := by + rw [cnt_succ, if_pos h] + +/-- `c(b+1) = c(b)` when `b ∉ M`. -/ +theorem cnt_succ_of_not_mem {b : ℕ} (h : b ∉ muellerSet) : cnt (b + 1) = cnt b := by + rw [cnt_succ, if_neg h, add_zero] + +/-- The key recursion `c(b) = ⌊b/4⌋ + c(⌊(b+1)/2⌋)`: odd members are the numbers `≡ 3 mod 4`, +even members are the doubles of members. -/ +theorem cnt_rec (b : ℕ) : cnt b = b / 4 + cnt ((b + 1) / 2) := by + induction b with + | zero => simp + | succ b ih => + obtain ⟨m, rfl | rfl⟩ := Nat.even_or_odd' b + · have e1 : (2 * m + 1) / 2 = m := by omega + have e2 : (2 * m + 1 + 1) / 2 = m + 1 := by omega + rw [e1] at ih + rw [e2] + by_cases hm : m ∈ muellerSet + · have hm' : 2 * m ∈ muellerSet := (two_mul_mem_iff m).2 hm + rw [cnt_succ_of_mem hm', cnt_succ_of_mem hm, ih] + omega + · have hm' : 2 * m ∉ muellerSet := fun h => hm ((two_mul_mem_iff m).1 h) + rw [cnt_succ_of_not_mem hm', cnt_succ_of_not_mem hm, ih] + omega + · have e1 : (2 * m + 1 + 1) / 2 = m + 1 := by omega + have e2 : (2 * m + 1 + 1 + 1) / 2 = m + 1 := by omega + rw [e1] at ih + rw [e2] + by_cases hm : (2 * m + 1) % 4 = 3 + · rw [cnt_succ_of_mem ((odd_mem_iff m).2 hm), ih] + omega + · rw [cnt_succ_of_not_mem (fun h => hm ((odd_mem_iff m).1 h)), ih] + omega + +/-- Upper bound: `2 c(b) ≤ b`. -/ +theorem two_mul_cnt_le (b : ℕ) : 2 * cnt b ≤ b := by + induction b using Nat.strong_induction_on with + | _ b ih => + rcases Nat.lt_or_ge b 2 with hb | hb + · interval_cases b + · simp [cnt] + · rw [cnt_succ_of_not_mem zero_not_mem]; simp [cnt] + · rw [cnt_rec b] + have := ih ((b + 1) / 2) (by omega) + omega + +/-- An elementary inequality for floor division. -/ +theorem succ_div_le (b m : ℕ) (hm : 0 < m) : (b + 1) / m ≤ b / m + 1 := by + calc (b + 1) / m ≤ (b + m) / m := Nat.div_le_div_right (by omega) + _ = b / m + 1 := Nat.add_div_right b hm + +/-- Lower bound: for every `k`, `b ≤ 2 c(b) + 2k + ⌊b / 2^k⌋`. -/ +theorem le_two_mul_cnt (k b : ℕ) : b ≤ 2 * cnt b + 2 * k + b / 2 ^ k := by + induction k generalizing b with + | zero => simp + | succ k ih => + have h1 := ih ((b + 1) / 2) + rw [Nat.div_div_eq_div_mul] at h1 + have h2 := succ_div_le b (2 * 2 ^ k) (by positivity) + rw [cnt_rec b, pow_succ, mul_comm (2 ^ k) 2] + generalize (b + 1) / (2 * 2 ^ k) = x at h1 h2 + generalize b / (2 * 2 ^ k) = y at h1 h2 ⊢ + omega + +/-- The partial densities of Müller's set are `c(b) / b`. -/ +theorem ncard_eq_cnt (b : ℕ) : ((muellerSet ∩ Set.univ) ∩ Set.Iio b).ncard = cnt b := by + classical + rw [cnt, Nat.count_eq_card_filter_range, ← Set.ncard_coe_finset] + congr 1 + ext x + simp [and_comm] + +/-- Müller's set has natural density `1/2`. -/ +theorem density : muellerSet.HasDensity (1 / 2) := by + unfold Set.HasDensity + have hfun : (fun b : ℕ => muellerSet.partialDensity Set.univ b) = + fun b => (cnt b : ℝ) / b := by + funext b + simp only [Set.partialDensity, ncard_eq_cnt, Set.univ_inter, Set.ncard_Iio_nat] + rw [hfun, Metric.tendsto_atTop] + intro ε hε + obtain ⟨k, hk⟩ := exists_pow_lt_of_lt_one hε (by norm_num : (1 / 2 : ℝ) < 1) + obtain ⟨N, hN⟩ := exists_nat_gt (2 * k / ε) + refine ⟨N + 1, fun b hb => ?_⟩ + have hbN : (N : ℝ) + 1 ≤ b := by exact_mod_cast hb + have hbpos : (0 : ℝ) < b := by + have : (0 : ℝ) ≤ N := Nat.cast_nonneg N + linarith + have hupR : (2 * cnt b : ℝ) ≤ b := by exact_mod_cast two_mul_cnt_le b + have hdivR : ((b / 2 ^ k : ℕ) : ℝ) ≤ (b : ℝ) * (1 / 2) ^ k := by + have := Nat.cast_div_le (α := ℝ) (m := b) (n := 2 ^ k) + rw [one_div_pow, ← div_eq_mul_one_div] + simpa using this + have hlowR : (b : ℝ) ≤ 2 * cnt b + 2 * k + b * (1 / 2) ^ k := by + have : (b : ℝ) ≤ 2 * cnt b + 2 * k + ((b / 2 ^ k : ℕ) : ℝ) := by + exact_mod_cast le_two_mul_cnt k b + linarith + have hNb : 2 * (k : ℝ) < ε * b := by + have h1 : 2 * (k : ℝ) / ε < b := by linarith + rw [div_lt_iff₀ hε] at h1 + linarith + have hpow : (b : ℝ) * (1 / 2) ^ k < b * ε := mul_lt_mul_of_pos_left hk hbpos + have hεb : 0 < ε * b := mul_pos hε hbpos + rw [Real.dist_eq, abs_lt] + constructor + · rw [lt_sub_iff_add_lt, lt_div_iff₀ hbpos] + nlinarith + · rw [sub_lt_iff_lt_add, div_lt_iff₀ hbpos] + nlinarith + +/-- Müller's theorem: the set of integers congruent to `3 · 2^i mod 2^(i+2)` for some `i` has no +two (not necessarily distinct) elements summing to a power of two, and has natural density `1/2`. -/ +theorem erdos_1136_mueller : type_of% @_root_.Erdos1136.erdos_1136.variants.mueller := + ⟨avoids, density⟩ + +end Math0.Erdos1136 + +#math0_proves Math0.Erdos1136.erdos_1136_mueller Erdos1136.erdos_1136.variants.mueller diff --git a/lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_multiples_of_three.lean b/lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_multiples_of_three.lean new file mode 100644 index 0000000..881eaad --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_multiples_of_three.lean @@ -0,0 +1,86 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1136» +import Math0.Audit + +/-! +# Erdős Problem 1136: the multiples of three avoid powers of two and have density 1/3 + +Erdős Problem 1136 asks for a set `A ⊆ ℕ` of lower density greater than `1/3` such that no sum +`a + b` (`a, b ∈ A`, not necessarily distinct) is a power of two. The trivial benchmark is the set +of multiples of `3`, which has density exactly `1/3`; we prove both facts. If `3 ∣ a` and `3 ∣ b` +then `3 ∣ a + b`, while no power of two is divisible by the prime `3`. For the density, the +multiples of `3` below `b` are exactly `3k` for `k < ⌊(b+2)/3⌋`, so the count `c(b)` satisfies +`b ≤ 3 c(b) ≤ b + 2`, whence `|c(b)/b - 1/3| ≤ 2/(3b) → 0`. +-/ + +namespace Math0.Erdos1136 + +open _root_.Erdos1136 Filter Topology + +/-- No two multiples of three sum to a power of two. -/ +theorem avoids_multiples_of_three : AvoidsPowersOfTwo {n : ℕ | 3 ∣ n} := by + intro a ha b hb k hk + have h3 : 3 ∣ 2 ^ k := hk ▸ dvd_add ha hb + have : 3 ∣ 2 := Nat.prime_three.dvd_of_dvd_pow h3 + omega + +/-- The multiples of three below `b` are the images of `k < ⌊(b+2)/3⌋` under `k ↦ 3k`. -/ +theorem inter_Iio_eq_image (b : ℕ) : + ({n : ℕ | 3 ∣ n} ∩ Set.univ) ∩ Set.Iio b = (fun k => 3 * k) '' Set.Iio ((b + 2) / 3) := by + ext n + simp only [Set.mem_inter_iff, Set.mem_ofPred_eq, Set.mem_univ, and_true, Set.mem_Iio, + Set.mem_image] + constructor + · rintro ⟨⟨k, rfl⟩, hk⟩ + exact ⟨k, by omega, rfl⟩ + · rintro ⟨k, hk, rfl⟩ + exact ⟨dvd_mul_right 3 k, by omega⟩ + +/-- The number of multiples of three below `b` is `⌊(b+2)/3⌋`. -/ +theorem ncard_inter_Iio (b : ℕ) : + (({n : ℕ | 3 ∣ n} ∩ Set.univ) ∩ Set.Iio b).ncard = (b + 2) / 3 := by + rw [inter_Iio_eq_image, Set.ncard_image_of_injective _ (mul_right_injective₀ (by norm_num)), + Set.ncard_Iio_nat] + +/-- The multiples of three have natural density `1/3`. -/ +theorem density_multiples_of_three : Set.HasDensity {n : ℕ | 3 ∣ n} (1 / 3) := by + unfold Set.HasDensity + have hfun : (fun b : ℕ => Set.partialDensity {n : ℕ | 3 ∣ n} Set.univ b) = + fun b => (((b + 2) / 3 : ℕ) : ℝ) / b := by + funext b + simp only [Set.partialDensity, ncard_inter_Iio, Set.univ_inter, Set.ncard_Iio_nat] + rw [hfun, Metric.tendsto_atTop] + intro ε hε + obtain ⟨N, hN⟩ := exists_nat_gt (1 / ε) + refine ⟨N + 1, fun b hb => ?_⟩ + have hbN : (N : ℝ) + 1 ≤ b := by exact_mod_cast hb + have hbpos : (0 : ℝ) < b := by + have : (0 : ℝ) ≤ N := Nat.cast_nonneg N + linarith + set c := (b + 2) / 3 with hc + have h1 : b ≤ 3 * c := by omega + have h2 : 3 * c ≤ b + 2 := by omega + have h1R : (b : ℝ) ≤ 3 * c := by exact_mod_cast h1 + have h2R : (3 * c : ℝ) ≤ b + 2 := by exact_mod_cast h2 + have hεb : 1 < ε * b := by + have h3 : 1 / ε < b := by linarith + rw [div_lt_iff₀ hε] at h3 + linarith + rw [Real.dist_eq, abs_lt] + constructor + · rw [lt_sub_iff_add_lt, lt_div_iff₀ hbpos] + nlinarith + · rw [sub_lt_iff_lt_add, div_lt_iff₀ hbpos] + nlinarith + +/-- The set of multiples of three has no two (not necessarily distinct) elements summing to a +power of two, and has natural density `1/3`. -/ +theorem erdos_1136_multiples_of_three : + type_of% @_root_.Erdos1136.erdos_1136.variants.multiples_of_three := + ⟨avoids_multiples_of_three, density_multiples_of_three⟩ + +end Math0.Erdos1136 + +#math0_proves Math0.Erdos1136.erdos_1136_multiples_of_three Erdos1136.erdos_1136.variants.multiples_of_three diff --git a/lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_upper_bound.lean b/lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_upper_bound.lean new file mode 100644 index 0000000..edd260a --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_upper_bound.lean @@ -0,0 +1,70 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1136» +import Math0.Audit + +/-! +# Erdős Problem 1136: lower density at most 1/2 + +Erdős Problem 1136 concerns sets `A ⊆ ℕ` such that no sum `a + b` (`a, b ∈ A`, not necessarily +distinct) is a power of two. Müller (2011) showed that such a set has lower density at most +`1/2`, and we prove exactly this. Since `2^j + 2^j = 2^(j+1)`, no power of two lies in `A`. +For `n = 2^j`, the map `x ↦ x` for `x < n` and `x ↦ 2n - x` for `x > n` sends +`A ∩ [0, 2n)` injectively into `[0, n)`, because a collision would give `x + y = 2^(j+1)`. +Hence the partial density of `A` at `2^(j+1)` is at most `1/2` for every `j`, so the liminf of the +partial densities is at most `1/2`. +-/ + +namespace Math0.Erdos1136 + +open _root_.Erdos1136 Filter Topology + +/-- A set avoiding sums equal to powers of two contains no power of two. -/ +theorem pow_not_mem {A : Set ℕ} (hA : AvoidsPowersOfTwo A) (j : ℕ) : 2 ^ j ∉ A := by + intro h + exact hA _ h _ h (j + 1) (by rw [pow_succ]; ring) + +/-- The counting bound `#(A ∩ [0, 2^(j+1))) ≤ 2^j`. -/ +theorem ncard_le {A : Set ℕ} (hA : AvoidsPowersOfTwo A) (j : ℕ) : + (A ∩ Set.Iio (2 * 2 ^ j)).ncard ≤ 2 ^ j := by + set n := 2 ^ j with hn + have hpow : 2 * n = 2 ^ (j + 1) := by rw [hn, pow_succ]; ring + have key := Set.ncard_le_ncard_of_injOn (s := A ∩ Set.Iio (2 * n)) (t := Set.Iio n) + (fun x => if x < n then x else 2 * n - x) ?_ ?_ (Set.finite_Iio n) + · simpa using key + · rintro x ⟨hxA, hx⟩ + simp only [Set.mem_Iio] at hx ⊢ + have hxn : x ≠ n := fun h => pow_not_mem hA j (by rw [← hn, ← h]; exact hxA) + have hn0 : 0 < n := by positivity + split_ifs with h + · exact h + · omega + · rintro x ⟨hxA, hx⟩ y ⟨hyA, hy⟩ hxy + simp only [Set.mem_Iio] at hx hy + have hxn : x ≠ n := fun h => pow_not_mem hA j (by rw [← hn, ← h]; exact hxA) + have hyn : y ≠ n := fun h => pow_not_mem hA j (by rw [← hn, ← h]; exact hyA) + have hsum : x + y ≠ 2 * n := hpow ▸ hA x hxA y hyA (j + 1) + simp only at hxy + split_ifs at hxy with h1 h2 h2 <;> omega + +/-- A set avoiding sums equal to powers of two has lower density at most `1/2`. -/ +theorem upper_bound : type_of% @_root_.Erdos1136.erdos_1136.variants.upper_bound := by + intro A hA + unfold Set.lowerDensity + apply liminf_le_of_frequently_le + · rw [frequently_atTop] + intro a + refine ⟨2 * 2 ^ a, ?_, ?_⟩ + · have := Nat.lt_two_pow_self (n := a); omega + · simp only [Set.partialDensity, Set.inter_univ, Set.univ_inter, Set.ncard_Iio_nat] + have h := ncard_le hA a + rw [div_le_iff₀ (by positivity)] + have : ((A ∩ Set.Iio (2 * 2 ^ a)).ncard : ℝ) ≤ (2 ^ a : ℕ) := by exact_mod_cast h + push_cast at this ⊢ + linarith + · exact ⟨0, eventually_map.2 (Eventually.of_forall fun b => by positivity)⟩ + +end Math0.Erdos1136 + +#math0_proves Math0.Erdos1136.upper_bound _root_.Erdos1136.erdos_1136.variants.upper_bound diff --git a/lean/Math0/ErdosProblems/Erdos1148_erdos_1148_variants_weaker.lean b/lean/Math0/ErdosProblems/Erdos1148_erdos_1148_variants_weaker.lean new file mode 100644 index 0000000..be7921e --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1148_erdos_1148_variants_weaker.lean @@ -0,0 +1,72 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1148» +import Math0.Audit + +/-! +# Erdős Problem 1148: the weaker variant with bound `n + 2√n` + +Erdős Problem 1148 asks whether every large `n` is `x² + y² - z²` with `max(x², y², z²) ≤ n`; +the booklet [Va99] remarks that this is "obvious" if the bound `n` is relaxed to `n + 2√n`. +We prove this relaxed statement, `Erdos1148.erdos_1148.variants.weaker`, for every natural +number `n`. Writing `n = s² + d` with `s = ⌊√n⌋` and `0 ≤ d ≤ 2s`, we take `(s, 0, 0)` if +`d = 0`, `(s, t + 1, t)` if `d = 2t + 1`, and `(s + 1, s - t, s - t + 1)` if `d = 2t ≥ 2`; +in each case the identity is elementary algebra, all squares other than `(s + 1)²` are at most +`s² ≤ n`, and `(s + 1)² ≤ n + 2s ≤ n + 2√n` because `n ≥ s² + 2` in the last case. +-/ + +namespace Math0.Erdos1148 + +/-- Arithmetic core: if `s² ≤ n < (s + 1)²` then `n = x² + y² - z²` with all of +`x², y², z²` at most `n + 2s`. -/ +lemma exists_rep_of_sqrt_bounds (s n : ℕ) (h1 : s * s ≤ n) (h2 : n < (s + 1) * (s + 1)) : + ∃ x y z : ℕ, n = x ^ 2 + y ^ 2 - z ^ 2 ∧ x ^ 2 ≤ n + 2 * s ∧ y ^ 2 ≤ n + 2 * s ∧ + z ^ 2 ≤ n + 2 * s := by + obtain ⟨d, rfl⟩ : ∃ d, n = s * s + d := ⟨n - s * s, by omega⟩ + have hd : d ≤ 2 * s := by nlinarith + obtain ⟨t, ht | ht⟩ := Nat.even_or_odd' d + · subst ht + rcases Nat.eq_zero_or_pos t with rfl | htpos + · refine ⟨s, 0, 0, ?_, ?_, ?_, ?_⟩ + · ring_nf; omega + · nlinarith + · nlinarith + · nlinarith + · obtain ⟨u, rfl⟩ := Nat.exists_eq_add_of_le (show t ≤ s by omega) + refine ⟨t + u + 1, u, u + 1, ?_, ?_, ?_, ?_⟩ + · have e : (t + u + 1) ^ 2 + u ^ 2 = (t + u) * (t + u) + 2 * t + (u + 1) ^ 2 := by ring + omega + · nlinarith + · nlinarith + · nlinarith + · subst ht + refine ⟨s, t + 1, t, ?_, ?_, ?_, ?_⟩ + · have e : s ^ 2 + (t + 1) ^ 2 = s * s + (2 * t + 1) + t ^ 2 := by ring + omega + · nlinarith + · have : t + 1 ≤ s := by omega + nlinarith + · nlinarith + +/-- Transfer a natural-number bound `m ≤ n + 2⌊√n⌋` to the real bound `m ≤ n + 2√n`. -/ +lemma cast_le_add_two_sqrt {m n : ℕ} (h : m ≤ n + 2 * Nat.sqrt n) : + (m : ℝ) ≤ n + 2 * Real.sqrt n := by + have hs : ((Nat.sqrt n : ℕ) : ℝ) ≤ Real.sqrt n := Real.nat_sqrt_le_real_sqrt + have hc : (m : ℝ) ≤ (n : ℝ) + 2 * ((Nat.sqrt n : ℕ) : ℝ) := by exact_mod_cast h + linarith + +/-- Every natural number `n` can be written as `n = x² + y² - z²` with +`max(x², y², z²) ≤ n + 2√n`. -/ +theorem erdos_1148_weaker : type_of% @Erdos1148.erdos_1148.variants.weaker := by + intro n + obtain ⟨x, y, z, h, hx, hy, hz⟩ := + exists_rep_of_sqrt_bounds (Nat.sqrt n) n (Nat.sqrt_le n) (Nat.lt_succ_sqrt n) + refine ⟨x, y, z, h, ?_, ?_, ?_⟩ + · exact_mod_cast cast_le_add_two_sqrt hx + · exact_mod_cast cast_le_add_two_sqrt hy + · exact_mod_cast cast_le_add_two_sqrt hz + +end Math0.Erdos1148 + +#math0_proves Math0.Erdos1148.erdos_1148_weaker Erdos1148.erdos_1148.variants.weaker diff --git a/lean/Math0/ErdosProblems/Erdos1180_erdos_1180_variants_optimal.lean b/lean/Math0/ErdosProblems/Erdos1180_erdos_1180_variants_optimal.lean new file mode 100644 index 0000000..2714f25 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1180_erdos_1180_variants_optimal.lean @@ -0,0 +1,1073 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1180» +import Math0.Audit + +/-! +# Erdős Problem 1180: the "optimal" variant is false as stated + +Erdős Problem 1180 (Erdős–Graham) asks whether, for each `ε > 0`, every residue modulo every +prime `p` is a sum of at most `C_ε` inverses `n⁻¹` with `1 ≤ n ≤ p ^ ε`; upstream `C ε` is the +least such constant (minimum over *all* primes). The upstream variant +`erdos_1180.variants.optimal` asserts `C ε ≤ ε⁻¹ ^ (1 + δ)` for every `δ > 0` and all small +`ε > 0`. We refute it: for `ε = 1 / (m + 1)` and a Bertrand prime `2 ^ m < p < 2 ^ (m + 1)` +we have `p ^ ε < 2`, so the only admissible denominator is `1` and representing `-1` needs +`p - 1 ≥ 2 ^ m` summands; hence `C ε ≥ 2 ^ m > (m + 1) ^ 2 = ε⁻¹ ^ 2`. This lower bound needs +the defining set of `C ε` to be nonempty, i.e. the (true) main statement `erdos_1180`, which we +prove following Glibichuk (2006): sums of reciprocals of primes in `k` disjoint blocks give an +antisymmetric set `B` with `|B|² > p`, Glibichuk's covering lemma (via an energy argument and +Cauchy–Davenport) gives `8 · B · B = ZMod p`, and each element of `B · B` is a sum of `k²` +inverses of products of two small primes. This formalization of Glibichuk's argument is adapted +(lists replaced by multisets, upstream `Represents` used directly) from the Apache-2.0 proof in +`plby/lean-proofs` (`ErdosProblems/Erdos1180.lean`). +-/ + +open scoped Pointwise +open Finset + +namespace Math0.Erdos1180 + +/- Glibichuk covering lemma -/ + +section Glibichuk + +variable {p : ℕ} [NeZero p] + +/-- The image of `X × Y` under `(x, y) ↦ x + ξ y`. -/ +noncomputable def affImg (ξ : ZMod p) (X Y : Finset (ZMod p)) : Finset (ZMod p) := + (X ×ˢ Y).image fun z ↦ z.1 + ξ * z.2 + +/-- The number of pairs of points of `X × Y` with the same image under `(x, y) ↦ x + ξ y`. -/ +noncomputable def affEnergy (ξ : ZMod p) (X Y : Finset (ZMod p)) : ℕ := + #{z ∈ (X ×ˢ Y) ×ˢ (X ×ˢ Y) | z.1.1 + ξ * z.1.2 = z.2.1 + ξ * z.2.2} + +omit [NeZero p] in +/-- The energy is the sum of the squares of the fibre sizes. -/ +lemma affEnergy_eq_sum_sq (ξ : ZMod p) (X Y : Finset (ZMod p)) : + affEnergy ξ X Y = ∑ a ∈ affImg ξ X Y, #{z ∈ X ×ˢ Y | z.1 + ξ * z.2 = a} ^ 2 := by + classical + simp_rw [affEnergy, sq, ← card_product] + rw [← card_disjiUnion] + swap + · aesop (add simp [Set.PairwiseDisjoint, Set.Pairwise, disjoint_left]) + · congr + aesop (add simp [affImg]) + +omit [NeZero p] in +/-- Cauchy–Schwarz: `(|X||Y|)² ≤ |X + ξY| · E_ξ(X, Y)`. -/ +lemma card_sq_le_card_affImg_mul_energy (ξ : ZMod p) (X Y : Finset (ZMod p)) : + (#X * #Y) ^ 2 ≤ #(affImg ξ X Y) * affEnergy ξ X Y := by + classical + let D := X ×ˢ Y + let f : ZMod p × ZMod p → ZMod p := fun z ↦ z.1 + ξ * z.2 + calc + (#X * #Y) ^ 2 = (∑ a ∈ affImg ξ X Y, #{z ∈ D | f z = a}) ^ 2 := by + rw [← card_product] + congr 1 + rw [sum_card_fiberwise_eq_card_filter, filter_eq_self.2] + intro z hz + exact mem_image.mpr ⟨z, hz, rfl⟩ + _ ≤ #(affImg ξ X Y) * ∑ a ∈ affImg ξ X Y, #{z ∈ D | f z = a} ^ 2 := by + simpa using sum_mul_sq_le_sq_mul_sq (R := ℕ) + (affImg ξ X Y) 1 (fun a ↦ #{z ∈ D | f z = a}) + _ = #(affImg ξ X Y) * affEnergy ξ X Y := by + rw [affEnergy_eq_sum_sq] + +/-- The nonzero residues. -/ +noncomputable def units' (p : ℕ) [NeZero p] : Finset (ZMod p) := univ.erase 0 + +/-- There are `p - 1` nonzero residues. -/ +@[simp] lemma card_units' : #(units' p) = p - 1 := by + classical + rw [units', card_erase_of_mem (mem_univ 0), card_univ, ZMod.card] + +/-- Double counting a filtered product. -/ +lemma sum_card_filter_eq {α β : Type*} + (s : Finset α) (t : Finset β) (P : α → β → Prop) [DecidableRel P] : + ∑ a ∈ s, #(t.filter (P a)) = #((s ×ˢ t).filter fun z ↦ P z.1 z.2) := by + classical + rw [card_filter, sum_product] + apply sum_congr rfl + intro a _ + rw [card_filter] + +/-- The total energy over all nonzero slopes, as one count. -/ +lemma sum_affEnergy_eq_card (X Y : Finset (ZMod p)) : + ∑ ξ ∈ units' p, affEnergy ξ X Y = + #{w ∈ units' p ×ˢ ((X ×ˢ Y) ×ˢ (X ×ˢ Y)) | + w.2.1.1 + w.1 * w.2.1.2 = w.2.2.1 + w.1 * w.2.2.2} := by + classical + unfold affEnergy + exact sum_card_filter_eq (units' p) ((X ×ˢ Y) ×ˢ (X ×ˢ Y)) + (fun ξ (w : (ZMod p × ZMod p) × (ZMod p × ZMod p)) ↦ + w.1.1 + ξ * w.1.2 = w.2.1 + ξ * w.2.2) + +omit [NeZero p] in +/-- Two distinct points determine at most one slope under which they collide. -/ +lemma slope_unique (hp : p.Prime) {ξ η : ZMod p} + {u v : ZMod p × ZMod p} (huv : u ≠ v) + (hξ : u.1 + ξ * u.2 = v.1 + ξ * v.2) + (hη : u.1 + η * u.2 = v.1 + η * v.2) : ξ = η := by + have := Fact.mk hp + have hy : u.2 ≠ v.2 := by + intro hy + apply huv + apply Prod.ext + · rw [hy] at hξ + exact add_right_cancel hξ + · exact hy + have hmul : (ξ - η) * (u.2 - v.2) = 0 := by + linear_combination hξ - hη + rcases mul_eq_zero.mp hmul with h | h + · exact sub_eq_zero.mp h + · exact (hy (sub_eq_zero.mp h)).elim + +/-- `∑_{ξ ≠ 0} E_ξ(X, Y) ≤ (p - 1)|X||Y| + (|X||Y|)²`. -/ +lemma sum_affEnergy_le (hp : p.Prime) (X Y : Finset (ZMod p)) : + ∑ ξ ∈ units' p, affEnergy ξ X Y ≤ #(units' p) * (#X * #Y) + (#X * #Y) ^ 2 := by + classical + let D := X ×ˢ Y + let U := units' p ×ˢ (D ×ˢ D) + let C := U.filter fun w ↦ w.2.1.1 + w.1 * w.2.1.2 = w.2.2.1 + w.1 * w.2.2.2 + let Cd := C.filter fun w ↦ w.2.1 = w.2.2 + let Co := C.filter fun w ↦ w.2.1 ≠ w.2.2 + have hsum : ∑ ξ ∈ units' p, affEnergy ξ X Y = #C := by + simpa [C, U, D] using sum_affEnergy_eq_card (p := p) X Y + have hsplit : #Cd + #Co = #C := by + simpa [Cd, Co] using card_filter_add_card_filter_not (s := C) (fun w ↦ w.2.1 = w.2.2) + have hdiag : #Cd ≤ #(units' p ×ˢ D) := by + refine card_le_card_of_injOn (fun w ↦ (w.1, w.2.1)) ?_ ?_ + · intro w hw + simp only [Cd, C, U, mem_filter, coe_filter, Set.mem_ofPred_eq, mem_product] at hw + exact mem_product.mpr ⟨hw.1.1.1, hw.1.1.2.1⟩ + · intro w hw w' hw' heq + simp only [Cd, C, U, coe_filter, Set.mem_ofPred_eq, mem_filter] at hw hw' + have hξ : w.1 = w'.1 := congrArg (fun z ↦ z.1) heq + have hu : w.2.1 = w'.2.1 := congrArg (fun z ↦ z.2) heq + have hv : w.2.2 = w'.2.2 := by rw [← hw.2, hu, hw'.2] + exact Prod.ext hξ (Prod.ext hu hv) + have hoff : #Co ≤ #(D ×ˢ D) := by + refine card_le_card_of_injOn (fun w ↦ w.2) ?_ ?_ + · intro w hw + simp only [Co, C, U, mem_filter, coe_filter, Set.mem_ofPred_eq, mem_product] at hw + exact mem_product.mpr hw.1.1.2 + · intro w hw w' hw' heq + simp only [Co, C, U, coe_filter, Set.mem_ofPred_eq, mem_filter] at hw hw' + have hξ : w.1 = w'.1 := by + apply slope_unique hp hw.2 hw.1.2 + simpa [heq] using hw'.1.2 + exact Prod.ext hξ heq + rw [hsum, ← hsplit] + calc + #Cd + #Co ≤ #(units' p ×ˢ D) + #(D ×ˢ D) := Nat.add_le_add hdiag hoff + _ = #(units' p) * (#X * #Y) + (#X * #Y) ^ 2 := by simp [D, pow_two] + +/-- Some nonzero slope has energy at most the average. -/ +lemma exists_good_slope (hp : p.Prime) (X Y : Finset (ZMod p)) : + ∃ ξ ∈ units' p, + (affEnergy ξ X Y : ℚ) ≤ (#X * #Y : ℚ) + (#X * #Y : ℚ) ^ 2 / #(units' p) := by + classical + have hGpos : 0 < #(units' p) := by + rw [card_units'] + exact Nat.sub_pos_of_lt hp.one_lt + have hnat := sum_affEnergy_le (p := p) hp X Y + have hcast : (∑ ξ ∈ units' p, (affEnergy ξ X Y : ℚ)) ≤ + (#(units' p) : ℚ) * (#X * #Y : ℚ) + (#X * #Y : ℚ) ^ 2 := by + exact_mod_cast hnat + have hsum : (∑ ξ ∈ units' p, (affEnergy ξ X Y : ℚ)) ≤ + ∑ ξ ∈ units' p, ((#X * #Y : ℚ) + (#X * #Y : ℚ) ^ 2 / #(units' p)) := by + refine hcast.trans (le_of_eq ?_) + simp only [sum_const, nsmul_eq_mul] + field_simp [Nat.ne_of_gt hGpos] + exact exists_le_of_sum_le (card_pos.mp hGpos) hsum + +omit [NeZero p] in +/-- Replacing `ξ` by `-ξ` does not change the energy (swap the `Y`-coordinates). -/ +lemma affEnergy_neg (ξ : ZMod p) (X Y : Finset (ZMod p)) : + affEnergy (-ξ) X Y = affEnergy ξ X Y := by + classical + let sw : ((ZMod p × ZMod p) × (ZMod p × ZMod p)) → + ((ZMod p × ZMod p) × (ZMod p × ZMod p)) := fun w ↦ ((w.1.1, w.2.2), (w.2.1, w.1.2)) + have hinv : Function.Involutive sw := by + rintro ⟨⟨x₁, y₁⟩, ⟨x₂, y₂⟩⟩ + rfl + unfold affEnergy + apply card_bijective sw hinv.bijective + rintro ⟨⟨x₁, y₁⟩, ⟨x₂, y₂⟩⟩ + simp only [mem_filter, mem_product] + constructor + · rintro ⟨⟨⟨hx₁, hy₁⟩, ⟨hx₂, hy₂⟩⟩, h⟩ + refine ⟨⟨⟨hx₁, hy₂⟩, ⟨hx₂, hy₁⟩⟩, ?_⟩ + dsimp [sw] + linear_combination h + · rintro ⟨⟨⟨hx₁, hy₂⟩, ⟨hx₂, hy₁⟩⟩, h⟩ + refine ⟨⟨⟨hx₁, hy₁⟩, ⟨hx₂, hy₂⟩⟩, ?_⟩ + dsimp [sw] at h + linear_combination h + +/-- If `|X||Y| > p` and the slope `ξ` has small energy then `|X + ξY| > p / 2`. -/ +lemma card_affImg_large (hp : p.Prime) (hp2 : 2 < p) + (X Y : Finset (ZMod p)) (ξ : ZMod p) (hprod : p < #X * #Y) + (henergy : (affEnergy ξ X Y : ℚ) ≤ (#X * #Y : ℚ) + (#X * #Y : ℚ) ^ 2 / #(units' p)) : + p < 2 * #(affImg ξ X Y) := by + classical + let q : ℚ := #X * #Y + let s : ℚ := #(affImg ξ X Y) + let e : ℚ := affEnergy ξ X Y + let r : ℚ := ((p - 1 : ℕ) : ℚ) + rw [card_units'] at henergy + have hrposN : 0 < p - 1 := Nat.sub_pos_of_lt hp.one_lt + have hrpos : (0 : ℚ) < r := by + dsimp [r] + exact_mod_cast hrposN + have hrEq : r = (p : ℚ) - 1 := by + dsimp [r] + rw [Nat.cast_sub hp.one_lt.le] + norm_num + have hqpos : (0 : ℚ) < q := by + dsimp [q] + exact_mod_cast (lt_trans hp.pos hprod) + have hpq : (p : ℚ) < q := by + dsimp [q] + exact_mod_cast hprod + have hcauchy : q ^ 2 ≤ s * e := by + dsimp [q, s, e] + exact_mod_cast card_sq_le_card_affImg_mul_energy (p := p) ξ X Y + by_contra hlarge + have hsNat : 2 * #(affImg ξ X Y) ≤ p := Nat.le_of_not_gt hlarge + have hpodd : ¬ Even p := by + rw [hp.even_iff] + omega + have hslt : 2 * #(affImg ξ X Y) < p := by + apply lt_of_le_of_ne hsNat + intro heq + exact hpodd ⟨#(affImg ξ X Y), by omega⟩ + have hs : 2 * s ≤ r := by + dsimp [s, r] + exact_mod_cast (show 2 * #(affImg ξ X Y) ≤ p - 1 by omega) + have he0 : 0 ≤ e := by positivity + have hc2 : 2 * q ^ 2 ≤ r * e := by + have h₁ := mul_le_mul_of_nonneg_left hcauchy (show (0 : ℚ) ≤ 2 by norm_num) + have h₂ := mul_le_mul_of_nonneg_right hs he0 + nlinarith + have hemul : e * r ≤ q * r + q ^ 2 := by + have h := mul_le_mul_of_nonneg_right henergy (le_of_lt hrpos) + dsimp [q, e, r] at h ⊢ + field_simp [ne_of_gt hrpos] at h + simpa [pow_two, mul_add, mul_comm, mul_left_comm, mul_assoc] using h + nlinarith [hrEq] + +/-- There is a nonzero `ξ` such that both `X + ξY` and `X - ξY` have more than `p / 2` +elements. -/ +lemma exists_two_large_affImg (hp : p.Prime) (hp2 : 2 < p) + (X Y : Finset (ZMod p)) (hprod : p < #X * #Y) : + ∃ ξ ∈ units' p, p < 2 * #(affImg ξ X Y) ∧ p < 2 * #(affImg (-ξ) X Y) := by + obtain ⟨ξ, hξ, henergy⟩ := exists_good_slope (p := p) hp X Y + refine ⟨ξ, hξ, card_affImg_large hp hp2 X Y ξ hprod henergy, ?_⟩ + apply card_affImg_large hp hp2 X Y (-ξ) hprod + simpa [affEnergy_neg] using henergy + +/-- `Y` contains no pair `y, -y`. -/ +def Antisymm (Y : Finset (ZMod p)) : Prop := + ∀ y ∈ Y, -y ∉ Y + +/-- `XY + XY + XY + XY`. -/ +noncomputable def sum4 (X Y : Finset (ZMod p)) : Finset (ZMod p) := + (X * Y + X * Y) + (X * Y + X * Y) + +/-- Eight-fold sums of products `xy`. -/ +noncomputable def sum8 (X Y : Finset (ZMod p)) : Finset (ZMod p) := + sum4 X Y + sum4 X Y + +/-- A set with more than `p / 2` elements meets its negative. -/ +lemma inter_neg_nonempty (A : Finset (ZMod p)) (hA : p < 2 * #A) : + (A ∩ A.image fun z ↦ -z).Nonempty := by + classical + by_contra hne + have hd : Disjoint A (A.image fun z ↦ -z) := by + rw [disjoint_iff_inter_eq_empty] + exact not_nonempty_iff_eq_empty.mp hne + have hcardImage : #(A.image fun z ↦ -z) = #A := card_image_iff.mpr neg_injective.injOn + have hle : #(A ∪ A.image fun z ↦ -z) ≤ p := by + calc + _ ≤ #(univ : Finset (ZMod p)) := card_le_card (subset_univ _) + _ = p := ZMod.card p + have hsplit := card_union_of_disjoint hd + omega + +/-- **Glibichuk's lemma.** If `|X||Y| > p` and `Y` is antisymmetric, then every residue is a sum +of eight products `xy` with `x ∈ X`, `y ∈ Y`. -/ +theorem glibichuk (hp : p.Prime) (hp2 : 2 < p) + (X Y : Finset (ZMod p)) (hprod : p < #X * #Y) (hanti : Antisymm Y) : + sum8 X Y = univ := by + classical + have := Fact.mk hp + obtain ⟨ξ, -, hplus, hminus⟩ := exists_two_large_affImg (p := p) hp hp2 X Y hprod + obtain ⟨z, hz⟩ := inter_neg_nonempty (p := p) (affImg ξ X Y) hplus + have hz₁ : z ∈ affImg ξ X Y := (mem_inter.mp hz).1 + obtain ⟨z', hz₂, hzz'⟩ := mem_image.mp (mem_inter.mp hz).2 + rw [affImg] at hz₁ hz₂ + obtain ⟨⟨x₁, y₁⟩, hxy₁, h₁⟩ := mem_image.mp hz₁ + obtain ⟨⟨x₂, y₂⟩, hxy₂, h₂⟩ := mem_image.mp hz₂ + obtain ⟨hx₁, hy₁⟩ := mem_product.mp hxy₁ + obtain ⟨hx₂, hy₂⟩ := mem_product.mp hxy₂ + have hc : y₁ + y₂ ≠ 0 := by + intro hy + have hy' : y₂ = -y₁ := by linear_combination hy + exact hanti y₁ hy₁ (hy' ▸ hy₂) + have hrel : ξ * (y₁ + y₂) = -(x₁ + x₂) := by + linear_combination h₁ + h₂ - hzz' + have hmap : Set.MapsTo (fun z ↦ (y₁ + y₂) * z) (affImg (-ξ) X Y) (sum4 X Y) := by + intro w hw + rw [affImg] at hw + obtain ⟨⟨x₃, y₃⟩, hxy₃, rfl⟩ := mem_image.mp hw + obtain ⟨hx₃, hy₃⟩ := mem_product.mp hxy₃ + have hp₁ : x₃ * y₁ ∈ X * Y := mul_mem_mul hx₃ hy₁ + have hp₂ : x₃ * y₂ ∈ X * Y := mul_mem_mul hx₃ hy₂ + have hp₃ : x₁ * y₃ ∈ X * Y := mul_mem_mul hx₁ hy₃ + have hp₄ : x₂ * y₃ ∈ X * Y := mul_mem_mul hx₂ hy₃ + have heq : (y₁ + y₂) * (x₃ + -ξ * y₃) = x₃ * y₁ + x₃ * y₂ + (x₁ * y₃ + x₂ * y₃) := by + linear_combination -y₃ * hrel + show (y₁ + y₂) * (x₃ + -ξ * y₃) ∈ sum4 X Y + rw [heq] + exact add_mem_add (add_mem_add hp₁ hp₂) (add_mem_add hp₃ hp₄) + have hinj : Set.InjOn (fun z ↦ (y₁ + y₂) * z) (affImg (-ξ) X Y) := by + intro a _ b _ hab + exact (mul_left_cancel₀ hc) hab + have h4 : #(affImg (-ξ) X Y) ≤ #(sum4 X Y) := card_le_card_of_injOn _ hmap hinj + have h4large : p < 2 * #(sum4 X Y) := lt_of_lt_of_le hminus (Nat.mul_le_mul_left 2 h4) + have h4ne : (sum4 X Y).Nonempty := by + rw [← card_pos] + omega + have hCD := ZMod.cauchy_davenport hp h4ne h4ne + have h8 : p ≤ #(sum8 X Y) := by + rw [sum8] + refine le_trans ?_ hCD + simp only [le_min_iff] + exact ⟨le_rfl, by omega⟩ + exact eq_of_subset_of_card_le (subset_univ _) (by simpa using h8) + +end Glibichuk + +/- Prime blocks -/ + +section PrimeBlocks + +variable {p k L H : ℕ} + +/-- The product `∏ᵢ q i (u i)` of the chosen denominators. -/ +def denProd (q : Fin k → Fin L → ℕ) (u : Fin k → Fin L) : ℕ := + ∏ i, q i (u i) + +/-- The numerator of `∑ᵢ 1 / q i (u i)` over the common denominator `denProd q u`. -/ +def recNum (q : Fin k → Fin L → ℕ) (u : Fin k → Fin L) : ℕ := + ∑ i, ∏ j ∈ univ.erase i, q j (u j) + +/-- The residue `∑ᵢ (q i (u i))⁻¹` in `ZMod p`. -/ +def recSum (p : ℕ) (q : Fin k → Fin L → ℕ) (u : Fin k → Fin L) : ZMod p := + ∑ i, ((q i (u i) : ZMod p)⁻¹) + +/-- The set of all residues `recSum p q u`. -/ +noncomputable def recSet (p : ℕ) (q : Fin k → Fin L → ℕ) : Finset (ZMod p) := + univ.image (recSum p q) + +/-- Clearing denominators: `denProd · recSum = recNum` in `ZMod p`. -/ +lemma denProd_mul_recSum (hp : p.Prime) (q : Fin k → Fin L → ℕ) (u : Fin k → Fin L) + (hq_lt : ∀ i j, q i j < p) (hq_pos : ∀ i j, 0 < q i j) : + (denProd q u : ZMod p) * recSum p q u = recNum q u := by + classical + have := Fact.mk hp + rw [recSum, mul_sum] + simp only [denProd, recNum, Nat.cast_sum, Nat.cast_prod] + apply sum_congr rfl + intro i _ + have hqi : (q i (u i) : ZMod p) ≠ 0 := by + rw [ne_eq, ZMod.natCast_eq_zero_iff] + exact Nat.not_dvd_of_pos_of_lt (hq_pos i (u i)) (hq_lt i (u i)) + rw [← mul_prod_erase univ (fun j ↦ (q j (u j) : ZMod p)) (mem_univ i)] + field_simp + +/-- `denProd q u ≤ H ^ k`. -/ +lemma denProd_le (q : Fin k → Fin L → ℕ) (u : Fin k → Fin L) + (hq_le : ∀ i j, q i j ≤ H) : denProd q u ≤ H ^ k := by + calc + denProd q u ≤ ∏ _i : Fin k, H := prod_le_prod' fun i _ ↦ hq_le i (u i) + _ = H ^ k := by simp + +/-- `recNum q u ≤ k H ^ (k - 1)`. -/ +lemma recNum_le (q : Fin k → Fin L → ℕ) (u : Fin k → Fin L) (hq_le : ∀ i j, q i j ≤ H) : + recNum q u ≤ k * H ^ (k - 1) := by + calc + recNum q u ≤ ∑ _i : Fin k, H ^ (k - 1) := by + apply sum_le_sum + intro i _ + calc + ∏ j ∈ univ.erase i, q j (u j) ≤ ∏ _j ∈ univ.erase i, H := + prod_le_prod' fun j _ ↦ hq_le j (u j) + _ = H ^ (k - 1) := by simp [card_erase_of_mem] + _ = k * H ^ (k - 1) := by simp + +/-- If `u i ≠ v i`, the prime `q i (u i)` does not divide `denProd q v`. -/ +lemma not_dvd_denProd (q : Fin k → Fin L → ℕ) (u v : Fin k → Fin L) + (hq_prime : ∀ i j, (q i j).Prime) + (hq_inj : Function.Injective fun ij : Fin k × Fin L ↦ q ij.1 ij.2) + {i : Fin k} (hi : u i ≠ v i) : ¬ q i (u i) ∣ denProd q v := by + intro hd + rw [denProd] at hd + obtain ⟨j, _, hj⟩ := (Prime.dvd_finsetProd_iff (Nat.prime_iff.mp (hq_prime i (u i))) _).mp hd + have hqeq : q i (u i) = q j (v j) := + (Nat.prime_dvd_prime_iff_eq (hq_prime i (u i)) (hq_prime j (v j))).mp hj + have hpairs : (i, u i) = (j, v j) := hq_inj hqeq + have hij : i = j := congrArg Prod.fst hpairs + subst hij + exact hi (congrArg Prod.snd hpairs) + +/-- No chosen prime `q i (u i)` divides `recNum q u`. -/ +lemma not_dvd_recNum (q : Fin k → Fin L → ℕ) (u : Fin k → Fin L) + (hq_prime : ∀ i j, (q i j).Prime) + (hq_inj : Function.Injective fun ij : Fin k × Fin L ↦ q ij.1 ij.2) + (i : Fin k) : ¬ q i (u i) ∣ recNum q u := by + classical + let term : Fin k → ℕ := fun a ↦ ∏ j ∈ univ.erase a, q j (u j) + have hterm : ¬ q i (u i) ∣ term i := by + apply (Nat.prime_iff.mp (hq_prime i (u i))).not_dvd_finsetProd + intro j hj hd + have hqeq : q i (u i) = q j (u j) := + (Nat.prime_dvd_prime_iff_eq (hq_prime i (u i)) (hq_prime j (u j))).mp hd + have hpairs : (i, u i) = (j, u j) := hq_inj hqeq + exact (mem_erase.mp hj).1 (congrArg Prod.fst hpairs).symm + have hrest : q i (u i) ∣ ∑ a ∈ univ.erase i, term a := by + apply dvd_sum + intro a ha + apply dvd_prod_of_mem (fun j ↦ q j (u j)) + exact mem_erase.mpr ⟨fun h ↦ (mem_erase.mp ha).1 h.symm, mem_univ i⟩ + have hdecomp : recNum q u = term i + ∑ a ∈ univ.erase i, term a := by + rw [recNum] + exact (add_sum_erase univ term (mem_univ i)).symm + intro hnum + apply hterm + rw [hdecomp] at hnum + exact (Nat.dvd_add_iff_left hrest).mpr hnum + +/-- Distinct choice vectors give distinct cross products. -/ +lemma cross_ne (q : Fin k → Fin L → ℕ) (u v : Fin k → Fin L) + (hq_prime : ∀ i j, (q i j).Prime) + (hq_inj : Function.Injective fun ij : Fin k × Fin L ↦ q ij.1 ij.2) + (huv : u ≠ v) : recNum q u * denProd q v ≠ recNum q v * denProd q u := by + obtain ⟨i, hi⟩ := Function.ne_iff.mp huv + have hrD : q i (u i) ∣ denProd q u := by + rw [denProd] + exact dvd_prod_of_mem (fun j ↦ q j (u j)) (mem_univ i) + have hrDv := not_dvd_denProd q u v hq_prime hq_inj hi + have hrN := not_dvd_recNum q u hq_prime hq_inj i + intro heq + have hrLeft : q i (u i) ∣ recNum q u * denProd q v := by + rw [heq] + exact dvd_mul_of_dvd_right hrD _ + exact hrN ((hq_prime i (u i)).dvd_mul.mp hrLeft |>.resolve_right hrDv) + +/-- `recNum q u · denProd q v ≤ k H ^ (2k - 1)`. -/ +lemma cross_le (hk : 0 < k) (q : Fin k → Fin L → ℕ) (u v : Fin k → Fin L) + (hq_le : ∀ i j, q i j ≤ H) : recNum q u * denProd q v ≤ k * H ^ (2 * k - 1) := by + calc + recNum q u * denProd q v ≤ (k * H ^ (k - 1)) * H ^ k := + Nat.mul_le_mul (recNum_le q u hq_le) (denProd_le q v hq_le) + _ = k * H ^ (2 * k - 1) := by + rw [mul_assoc, ← pow_add] + congr 2 + omega + +/-- If `2 k H ^ (2k - 1) < p`, the map `u ↦ recSum p q u` is injective. -/ +lemma recSum_injective (hp : p.Prime) (hk : 0 < k) (q : Fin k → Fin L → ℕ) + (hq_prime : ∀ i j, (q i j).Prime) + (hq_inj : Function.Injective fun ij : Fin k × Fin L ↦ q ij.1 ij.2) + (hq_le : ∀ i j, q i j ≤ H) (hHlt : H < p) (hsmall : 2 * k * H ^ (2 * k - 1) < p) : + Function.Injective (recSum p q) := by + intro u v huv + by_contra huvne + have hq_lt : ∀ i j, q i j < p := fun i j ↦ lt_of_le_of_lt (hq_le i j) hHlt + have hq_pos : ∀ i j, 0 < q i j := fun i j ↦ (hq_prime i j).pos + have hu := denProd_mul_recSum hp q u hq_lt hq_pos + have hv := denProd_mul_recSum hp q v hq_lt hq_pos + set A := recNum q u * denProd q v with hA + set B := recNum q v * denProd q u with hB + have hcast : (A : ZMod p) = (B : ZMod p) := by + rw [hA, hB] + push_cast + rw [← hu, ← hv, huv] + ring + have hmod : A % p = B % p := (ZMod.natCast_eq_natCast_iff' A B p).mp hcast + have hAle : A ≤ k * H ^ (2 * k - 1) := cross_le hk q u v hq_le + have hBle : B ≤ k * H ^ (2 * k - 1) := cross_le hk q v u hq_le + have hAp : A < p := by nlinarith + have hBp : B < p := by nlinarith + rw [Nat.mod_eq_of_lt hAp, Nat.mod_eq_of_lt hBp] at hmod + exact cross_ne q u v hq_prime hq_inj huvne hmod + +/-- Under the same hypotheses there are exactly `L ^ k` residues `recSum p q u`. -/ +lemma card_recSet (hp : p.Prime) (hk : 0 < k) (q : Fin k → Fin L → ℕ) + (hq_prime : ∀ i j, (q i j).Prime) + (hq_inj : Function.Injective fun ij : Fin k × Fin L ↦ q ij.1 ij.2) + (hq_le : ∀ i j, q i j ≤ H) (hHlt : H < p) (hsmall : 2 * k * H ^ (2 * k - 1) < p) : + #(recSet p q) = L ^ k := by + classical + rw [recSet, card_image_iff.mpr + (recSum_injective hp hk q hq_prime hq_inj hq_le hHlt hsmall).injOn] + simp + +/-- `recNum q u > 0`. -/ +lemma recNum_pos (hk : 0 < k) (q : Fin k → Fin L → ℕ) (u : Fin k → Fin L) + (hq_pos : ∀ i j, 0 < q i j) : 0 < recNum q u := by + rw [recNum] + apply sum_pos' + · exact fun _ _ ↦ Nat.zero_le _ + · exact ⟨⟨0, hk⟩, mem_univ _, prod_pos fun j _ ↦ hq_pos j (u j)⟩ + +/-- The set `recSet p q` contains no pair `y, -y`. -/ +lemma recSet_antisymm (hp : p.Prime) (hk : 0 < k) (q : Fin k → Fin L → ℕ) + (hq_prime : ∀ i j, (q i j).Prime) (hq_le : ∀ i j, q i j ≤ H) (hHlt : H < p) + (hsmall : 2 * k * H ^ (2 * k - 1) < p) : + Antisymm (p := p) (recSet p q) := by + classical + intro y hy hny + rw [recSet] at hy hny + obtain ⟨u, _, rfl⟩ := mem_image.mp hy + obtain ⟨v, _, hvneg⟩ := mem_image.mp hny + have hq_lt : ∀ i j, q i j < p := fun i j ↦ lt_of_le_of_lt (hq_le i j) hHlt + have hq_pos : ∀ i j, 0 < q i j := fun i j ↦ (hq_prime i j).pos + have hu := denProd_mul_recSum hp q u hq_lt hq_pos + have hv := denProd_mul_recSum hp q v hq_lt hq_pos + set A := recNum q u * denProd q v with hA + set B := recNum q v * denProd q u with hB + have hsumcast : ((A + B : ℕ) : ZMod p) = 0 := by + rw [hA, hB] + push_cast + rw [← hu, ← hv, hvneg] + ring + have hpdiv : p ∣ A + B := (ZMod.natCast_eq_zero_iff (A + B) p).mp hsumcast + have hAle : A ≤ k * H ^ (2 * k - 1) := cross_le hk q u v hq_le + have hBle : B ≤ k * H ^ (2 * k - 1) := cross_le hk q v u hq_le + have hApos : 0 < A := mul_pos (recNum_pos hk q u hq_pos) (prod_pos fun i _ ↦ hq_pos i (v i)) + exact Nat.not_dvd_of_pos_of_lt (by omega) (by nlinarith) hpdiv + +/-- The `k²` denominators `q i (u i) · q j (v j)` from expanding `recSum q u · recSum q v`. -/ +noncomputable def prodDenoms (q : Fin k → Fin L → ℕ) (u v : Fin k → Fin L) : Multiset ℕ := + ((univ : Finset (Fin k)) ×ˢ (univ : Finset (Fin k))).val.map + fun ij ↦ q ij.1 (u ij.1) * q ij.2 (v ij.2) + +/-- There are `k²` such denominators. -/ +lemma card_prodDenoms (q : Fin k → Fin L → ℕ) (u v : Fin k → Fin L) : + Multiset.card (prodDenoms q u v) = k ^ 2 := by + simp [prodDenoms, pow_two] + +/-- Their inverses sum to `recSum q u · recSum q v`. -/ +lemma sum_prodDenoms (hp : p.Prime) (q : Fin k → Fin L → ℕ) (u v : Fin k → Fin L) : + ((prodDenoms q u v).map fun n : ℕ ↦ (n : ZMod p)⁻¹).sum = recSum p q u * recSum p q v := by + have := Fact.mk hp + rw [prodDenoms, Multiset.map_map, ← Finset.sum_eq_multiset_sum, recSum, recSum, + Fintype.sum_mul_sum, sum_product] + apply sum_congr rfl + intro i _ + apply sum_congr rfl + intro j _ + simp only [Function.comp_apply, Nat.cast_mul] + rw [mul_inv_rev, mul_comm] + +/-- Each such denominator `n` satisfies `1 ≤ n ≤ p ^ ε` and is coprime to `p`. -/ +lemma prodDenoms_admissible (hp : p.Prime) {ε : ℝ} (q : Fin k → Fin L → ℕ) (u v : Fin k → Fin L) + (hq_prime : ∀ i j, (q i j).Prime) (hq_le : ∀ i j, q i j ≤ H) + (hHlt : H < p) (hHsq : (H : ℝ) ^ 2 ≤ (p : ℝ) ^ ε) : + ∀ n ∈ prodDenoms q u v, 1 ≤ n ∧ (n : ℝ) ≤ (p : ℝ) ^ ε ∧ n.Coprime p := by + intro n hn + rw [prodDenoms, Multiset.mem_map] at hn + obtain ⟨⟨i, j⟩, -, rfl⟩ := hn + have hqi_lt : q i (u i) < p := lt_of_le_of_lt (hq_le i (u i)) hHlt + have hqj_lt : q j (v j) < p := lt_of_le_of_lt (hq_le j (v j)) hHlt + refine ⟨Nat.one_le_iff_ne_zero.mpr + (mul_pos (hq_prime i (u i)).pos (hq_prime j (v j)).pos).ne', ?_, ?_⟩ + · refine le_trans ?_ hHsq + have := Nat.mul_le_mul (hq_le i (u i)) (hq_le j (v j)) + rw [← pow_two] at this + exact_mod_cast this + · apply Nat.Coprime.symm + rw [hp.coprime_iff_not_dvd] + intro hdvd + rcases hp.dvd_mul.mp hdvd with hdvd | hdvd + · exact Nat.not_dvd_of_pos_of_lt (hq_prime i (u i)).pos hqi_lt hdvd + · exact Nat.not_dvd_of_pos_of_lt (hq_prime j (v j)).pos hqj_lt hdvd + +/-- Representations add: concatenate the multisets of denominators. -/ +lemma represents_add {ε : ℝ} {a b : ZMod p} {s t : Multiset ℕ} + (hs : _root_.Erdos1180.Represents ε p a s) (ht : _root_.Erdos1180.Represents ε p b t) : + _root_.Erdos1180.Represents ε p (a + b) (s + t) := by + refine ⟨fun n hn ↦ ?_, ?_⟩ + · rcases Multiset.mem_add.mp hn with hn | hn + · exact hs.1 n hn + · exact ht.1 n hn + · rw [Multiset.map_add, Multiset.sum_add, hs.2, ht.2] + +/-- `a` is a sum of exactly `m` admissible inverses. -/ +def ExactRep (ε : ℝ) (p m : ℕ) (a : ZMod p) : Prop := + ∃ s : Multiset ℕ, Multiset.card s = m ∧ _root_.Erdos1180.Represents ε p a s + +/-- Exact representability is compatible with sumsets. -/ +lemma exactRep_add {m n : ℕ} {S T : Finset (ZMod p)} {ε : ℝ} + (hS : ∀ a ∈ S, ExactRep ε p m a) (hT : ∀ b ∈ T, ExactRep ε p n b) : + ∀ z ∈ S + T, ExactRep ε p (m + n) z := by + classical + intro z hz + obtain ⟨a, ha, b, hb, rfl⟩ := mem_add.mp hz + obtain ⟨s, hs, hsr⟩ := hS a ha + obtain ⟨t, ht, htr⟩ := hT b hb + exact ⟨s + t, by rw [Multiset.card_add, hs, ht], represents_add hsr htr⟩ + +/-- Every element of `recSet · recSet` is a sum of exactly `k²` admissible inverses. -/ +lemma mul_exactRep (hp : p.Prime) {ε : ℝ} (q : Fin k → Fin L → ℕ) + (hq_prime : ∀ i j, (q i j).Prime) (hq_le : ∀ i j, q i j ≤ H) + (hHlt : H < p) (hHsq : (H : ℝ) ^ 2 ≤ (p : ℝ) ^ ε) : + ∀ z ∈ recSet p q * recSet p q, ExactRep ε p (k ^ 2) z := by + classical + intro z hz + obtain ⟨a, ha, b, hb, rfl⟩ := mem_mul.mp hz + rw [recSet] at ha hb + obtain ⟨u, _, rfl⟩ := mem_image.mp ha + obtain ⟨v, _, rfl⟩ := mem_image.mp hb + exact ⟨prodDenoms q u v, card_prodDenoms q u v, + prodDenoms_admissible hp q u v hq_prime hq_le hHlt hHsq, sum_prodDenoms hp q u v⟩ + +/-- Every element of the eightfold sumset is a sum of exactly `8k²` admissible inverses. -/ +lemma sum8_exactRep [NeZero p] (hp : p.Prime) {ε : ℝ} (q : Fin k → Fin L → ℕ) + (hq_prime : ∀ i j, (q i j).Prime) (hq_le : ∀ i j, q i j ≤ H) + (hHlt : H < p) (hHsq : (H : ℝ) ^ 2 ≤ (p : ℝ) ^ ε) : + ∀ z ∈ sum8 (recSet p q) (recSet p q), ExactRep ε p (8 * k ^ 2) z := by + have h1 := mul_exactRep (ε := ε) hp q hq_prime hq_le hHlt hHsq + have h2 := exactRep_add h1 h1 + have h4 := exactRep_add h2 h2 + have h8 := exactRep_add h4 h4 + have e : k ^ 2 + k ^ 2 + (k ^ 2 + k ^ 2) + (k ^ 2 + k ^ 2 + (k ^ 2 + k ^ 2)) = 8 * k ^ 2 := by + ring + rw [e] at h8 + exact h8 + +end PrimeBlocks + +/- Asymptotic estimates -/ + +section Asymptotics + +open Filter Topology Asymptotics Real + +/-- `(n + 1)² ≤ 2 ^ n` for `n ≥ 6`. -/ +lemma sq_succ_le_two_pow (n : ℕ) (hn : 6 ≤ n) : (n + 1) ^ 2 ≤ 2 ^ n := by + induction n, hn using Nat.le_induction with + | base => norm_num + | succ n hn ih => + calc + (n + 1 + 1) ^ 2 ≤ 2 * (n + 1) ^ 2 := by nlinarith + _ ≤ 2 * 2 ^ n := Nat.mul_le_mul_left 2 ih + _ = 2 ^ (n + 1) := by rw [pow_succ]; ring + +/-- `log x ≤ c x ^ r` eventually, for `r, c > 0`. -/ +lemma ev_log_le {r c : ℝ} (hr : 0 < r) (hc : 0 < c) : + ∀ᶠ x : ℝ in atTop, log x ≤ c * x ^ r := by + have hbound := (isLittleO_log_rpow_atTop hr).bound hc + filter_upwards [hbound, eventually_ge_atTop (1 : ℝ)] with x hx hx1 + rw [Real.norm_eq_abs, abs_of_nonneg (log_nonneg hx1), Real.norm_eq_abs, + abs_of_nonneg (rpow_nonneg (by positivity) _)] at hx + exact hx + +/-- `c n ^ a < n ^ b` eventually, for `a < b`. -/ +lemma ev_mul_rpow_lt {a b c : ℝ} (hab : a < b) : + ∀ᶠ n : ℕ in atTop, c * (n : ℝ) ^ a < (n : ℝ) ^ b := by + have ht := tendsto_rpow_atTop (sub_pos.mpr hab) + have h : ∀ᶠ x : ℝ in atTop, c * x ^ a < x ^ b := by + filter_upwards [eventually_gt_atTop (0 : ℝ), ht.eventually_gt_atTop c] with x hx hxc + calc + c * x ^ a < x ^ (b - a) * x ^ a := mul_lt_mul_of_pos_right hxc (rpow_pos_of_pos hx a) + _ = x ^ b := by + rw [← Real.rpow_add hx] + congr 1 + ring + exact tendsto_natCast_atTop_atTop.eventually h + +/-- `π(n) ≥ n ^ t` eventually, for `t < 1` (from Chebyshev's lower bound). -/ +lemma ev_primeCounting_ge {t : ℝ} (ht1 : t < 1) : + ∀ᶠ n : ℕ in atTop, (n : ℝ) ^ t ≤ Nat.primeCounting n := by + have hlogReal := ev_log_le (sub_pos.mpr ht1) (show 0 < log 2 / 2 by positivity) + have hlog := tendsto_natCast_atTop_atTop.eventually hlogReal + filter_upwards [eventually_ge_atTop 6, hlog] with n hn hlogn + have hnpos : (0 : ℝ) < n := by exact_mod_cast (lt_of_lt_of_le (by norm_num : 0 < 6) hn) + have hlogpos : 0 < log (n : ℝ) := log_pos (by + exact_mod_cast (lt_of_lt_of_le (by norm_num : 1 < 6) hn)) + have hsquareR : ((n + 1 : ℕ) : ℝ) ^ 2 ≤ (2 : ℝ) ^ n := by + exact_mod_cast sq_succ_le_two_pow n hn + have hnum : log ((n : ℝ) + 1) ≤ (n : ℝ) * log 2 / 2 := by + have hlogpow := log_le_log (by positivity : (0 : ℝ) < ((n + 1 : ℕ) : ℝ) ^ 2) hsquareR + rw [Real.log_pow, Real.log_pow] at hlogpow + push_cast at hlogpow + linarith + refine le_trans ?_ (Chebyshev.pi_ge n) + rw [le_div_iff₀ hlogpos] + have hrpow : (n : ℝ) ^ t * (n : ℝ) ^ (1 - t) = n := by + rw [← Real.rpow_add hnpos] + norm_num + have hmul := mul_le_mul_of_nonneg_left hlogn (rpow_nonneg hnpos.le t) + have hmul' : (n : ℝ) ^ t * log n ≤ (n : ℝ) * log 2 / 2 := by + calc + _ ≤ (n : ℝ) ^ t * (log 2 / 2 * (n : ℝ) ^ (1 - t)) := hmul + _ = (log 2 / 2) * ((n : ℝ) ^ t * (n : ℝ) ^ (1 - t)) := by ring + _ = (n : ℝ) * log 2 / 2 := by rw [hrpow]; ring + linarith + +/-- `⌊n ^ a⌋₊`. -/ +noncomputable def fpow (a : ℝ) (n : ℕ) : ℕ := ⌊(n : ℝ) ^ a⌋₊ + +/-- `⌊n ^ a⌋₊ ≤ n ^ a`. -/ +lemma fpow_le (a : ℝ) (n : ℕ) : (fpow a n : ℝ) ≤ (n : ℝ) ^ a := + Nat.floor_le (rpow_nonneg (Nat.cast_nonneg n) a) + +/-- `n ^ a / 2 < ⌊n ^ a⌋₊` when `n ^ a ≥ 1`. -/ +lemma half_lt_fpow {a : ℝ} {n : ℕ} (hpow : 1 ≤ (n : ℝ) ^ a) : (n : ℝ) ^ a / 2 < fpow a n := by + simpa [fpow] using Nat.div_two_lt_floor hpow + +/-- `⌊n ^ a⌋₊ → ∞` for `a > 0`. -/ +lemma tendsto_fpow {a : ℝ} (ha : 0 < a) : Tendsto (fpow a) atTop atTop := by + rw [tendsto_atTop_atTop] + intro N + have ht := (tendsto_rpow_atTop ha).comp tendsto_natCast_atTop_atTop + obtain ⟨M, hM⟩ := eventually_atTop.1 (ht.eventually_ge_atTop (N : ℝ)) + refine ⟨M, fun n hn ↦ ?_⟩ + exact (Nat.le_floor_iff (rpow_nonneg (Nat.cast_nonneg n) a)).mpr (by + simpa only [Function.comp_apply] using hM n hn) + +/-- `⌊n ^ a⌋₊ < n` eventually, for `a < 1`. -/ +lemma ev_fpow_lt {a : ℝ} (ha : a < 1) : ∀ᶠ n : ℕ in atTop, fpow a n < n := by + filter_upwards [ev_mul_rpow_lt (c := 1) ha] with n hn + have hreal : (fpow a n : ℝ) < n := lt_of_le_of_lt (fpow_le a n) (by simpa using hn) + exact_mod_cast hreal + +/-- `2k ⌊n ^ δ⌋₊ ^ (2k - 1) < n` eventually, when `(2k - 1) δ < 1`. -/ +lemma ev_clearing {k : ℕ} {δ : ℝ} (hmargin : ((2 * k - 1 : ℕ) : ℝ) * δ < 1) : + ∀ᶠ n : ℕ in atTop, 2 * k * (fpow δ n) ^ (2 * k - 1) < n := by + have hcmp := ev_mul_rpow_lt (c := (2 * k : ℝ)) (a := δ * (2 * k - 1 : ℕ)) (b := 1) (by + simpa [mul_comm] using hmargin) + filter_upwards [hcmp] with n hn + have hpow : ((fpow δ n : ℝ) ^ (2 * k - 1)) ≤ (((n : ℝ) ^ δ) ^ (2 * k - 1)) := + pow_le_pow_left₀ (by positivity) (fpow_le δ n) _ + have hreal : ((2 * k * (fpow δ n) ^ (2 * k - 1) : ℕ) : ℝ) < n := by + calc + _ = (2 * k : ℝ) * (fpow δ n : ℝ) ^ (2 * k - 1) := by norm_num + _ ≤ (2 * k : ℝ) * (((n : ℝ) ^ δ) ^ (2 * k - 1)) := by gcongr + _ = (2 * k : ℝ) * (n : ℝ) ^ (δ * (2 * k - 1 : ℕ)) := by + rw [← Real.rpow_natCast, ← Real.rpow_mul (by positivity)] + _ < (n : ℝ) ^ (1 : ℝ) := hn + _ = n := by simp + exact_mod_cast hreal + +/-- `⌊n ^ δ⌋₊ ² ≤ n ^ ε` when `2δ ≤ ε`. -/ +lemma fpow_sq_le {δ ε : ℝ} {n : ℕ} (hn : 1 ≤ n) (hmargin : 2 * δ ≤ ε) : + (fpow δ n : ℝ) ^ 2 ≤ (n : ℝ) ^ ε := by + have hnreal : (1 : ℝ) ≤ n := by exact_mod_cast hn + calc + (fpow δ n : ℝ) ^ 2 ≤ ((n : ℝ) ^ δ) ^ 2 := pow_le_pow_left₀ (by positivity) (fpow_le δ n) _ + _ = (n : ℝ) ^ (2 * δ) := by + rw [← Real.rpow_natCast, ← Real.rpow_mul (by positivity)] + norm_num [mul_comm] + _ ≤ (n : ℝ) ^ ε := Real.rpow_le_rpow_of_exponent_le hnreal hmargin + +/-- `n < ⌊n ^ γ⌋₊ ^ (2k)` eventually, when `2kγ > 1`. -/ +lemma ev_lt_fpow_pow {k : ℕ} {γ : ℝ} (hk : 0 < k) (hγ : 0 < γ) (hmargin : 1 < (2 * k : ℝ) * γ) : + ∀ᶠ n : ℕ in atTop, n < (fpow γ n) ^ (2 * k) := by + have hcmp := ev_mul_rpow_lt (c := (2 : ℝ) ^ (2 * k : ℕ)) (a := 1) (b := (2 * k : ℕ) * γ) (by + push_cast + exact hmargin) + have hpowOne := + ((tendsto_rpow_atTop hγ).comp tendsto_natCast_atTop_atTop).eventually_ge_atTop 1 + filter_upwards [hcmp, hpowOne] with n hnGrow hnOne + have hlow := half_lt_fpow hnOne + have hlowPow : (((n : ℝ) ^ γ / 2) ^ (2 * k)) < (fpow γ n : ℝ) ^ (2 * k) := + pow_lt_pow_left₀ hlow (by positivity) (by omega) + have hbase : (n : ℝ) < ((n : ℝ) ^ γ / 2) ^ (2 * k) := by + have hpowEq : (n : ℝ) ^ ((2 * k : ℕ) * γ) = ((n : ℝ) ^ γ) ^ (2 * k) := by + rw [mul_comm, Real.rpow_mul (by positivity), Real.rpow_natCast] + rw [div_pow, ← hpowEq, lt_div_iff₀ (by positivity)] + simpa [mul_comm] using hnGrow + have hreal : (n : ℝ) < (((fpow γ n) ^ (2 * k) : ℕ) : ℝ) := by + push_cast + exact hbase.trans hlowPow + exact_mod_cast hreal + +/-- `k ⌊n ^ γ⌋₊ ≤ π(⌊n ^ δ⌋₊)` eventually, when `γ < δ t` with `0 < t < 1`. -/ +lemma ev_prime_supply {k : ℕ} {δ γ t : ℝ} (hδ : 0 < δ) (ht0 : 0 < t) (ht1 : t < 1) + (hmargin : γ < δ * t) : + ∀ᶠ n : ℕ in atTop, k * fpow γ n ≤ #(Nat.primesLE (fpow δ n)) := by + have hprimeAtH := (tendsto_fpow hδ).eventually (ev_primeCounting_ge ht1) + have hcmp := ev_mul_rpow_lt (c := (k : ℝ) * (2 : ℝ) ^ t) (a := γ) (b := δ * t) hmargin + have hpowOne := + ((tendsto_rpow_atTop hδ).comp tendsto_natCast_atTop_atTop).eventually_ge_atTop 1 + filter_upwards [hprimeAtH, hcmp, hpowOne] with n hprime hgrow hnOne + have hHlow := half_lt_fpow hnOne + have hHlowPow : (((n : ℝ) ^ δ / 2) ^ t) < (fpow δ n : ℝ) ^ t := + Real.rpow_lt_rpow (by positivity) hHlow ht0 + have hbase : (k : ℝ) * (n : ℝ) ^ γ < ((n : ℝ) ^ δ / 2) ^ t := by + rw [Real.div_rpow (by positivity) (by norm_num : (0 : ℝ) ≤ 2), ← Real.rpow_mul (by positivity), + lt_div_iff₀ (rpow_pos_of_pos (by norm_num) _)] + simpa [mul_assoc, mul_comm, mul_left_comm] using hgrow + have hKLreal : ((k * fpow γ n : ℕ) : ℝ) ≤ Nat.primeCounting (fpow δ n) := by + apply le_of_lt + calc + _ = (k : ℝ) * (fpow γ n : ℝ) := by norm_num + _ ≤ (k : ℝ) * (n : ℝ) ^ γ := by + gcongr + exact fpow_le γ n + _ < ((n : ℝ) ^ δ / 2) ^ t := hbase + _ < (fpow δ n : ℝ) ^ t := hHlowPow + _ ≤ Nat.primeCounting (fpow δ n) := hprime + rw [Nat.primesLE_card_eq_primeCounting] + exact_mod_cast hKLreal + +/-- All size conditions needed for the prime-block construction at the prime `n`, with +`H = ⌊n ^ δ⌋₊` and `L = ⌊n ^ γ⌋₊`. -/ +def Good (ε : ℝ) (k : ℕ) (δ γ : ℝ) (n : ℕ) : Prop := + 2 < n ∧ + fpow δ n < n ∧ + 2 * k * (fpow δ n) ^ (2 * k - 1) < n ∧ + (fpow δ n : ℝ) ^ 2 ≤ (n : ℝ) ^ ε ∧ + n < (fpow γ n) ^ (2 * k) ∧ + k * fpow γ n ≤ #(Nat.primesLE (fpow δ n)) + +/-- Under the margin conditions, all large `n` are good. -/ +lemma ev_good {ε δ γ t : ℝ} {k : ℕ} + (hk : 0 < k) (hδ : 0 < δ) (hγ : 0 < γ) (hδone : δ < 1) + (hclear : ((2 * k - 1 : ℕ) : ℝ) * δ < 1) + (hdenom : 2 * δ ≤ ε) (hgrow : 1 < (2 * k : ℝ) * γ) + (ht0 : 0 < t) (ht1 : t < 1) (hsupply : γ < δ * t) : + ∀ᶠ n : ℕ in atTop, Good ε k δ γ n := by + filter_upwards [eventually_gt_atTop 2, ev_fpow_lt hδone, ev_clearing (k := k) hclear, + ev_lt_fpow_pow hk hγ hgrow, ev_prime_supply (k := k) hδ ht0 ht1 hsupply] + with n hn hHn hsmalln hlargen hprimesn + exact ⟨hn, hHn, hsmalln, fpow_sq_le (by omega) hdenom, hlargen, hprimesn⟩ + +/-- A choice of parameters satisfying the margin conditions, for any `ε > 0`. -/ +lemma choose_params {ε : ℝ} (hε : 0 < ε) : + ∃ (k : ℕ) (δ γ t : ℝ), + 0 < k ∧ 0 < δ ∧ 0 < γ ∧ δ < 1 ∧ + ((2 * k - 1 : ℕ) : ℝ) * δ < 1 ∧ + 2 * δ ≤ ε ∧ 1 < (2 * k : ℝ) * γ ∧ + 0 < t ∧ t < 1 ∧ γ < δ * t := by + obtain ⟨k, hkbig⟩ := exists_nat_gt (2 / ε + 1) + have hkR : (1 : ℝ) < k := by + have : 0 < 2 / ε := div_pos (by norm_num) hε + linarith + have hk : 0 < k := by exact_mod_cast (lt_trans (by norm_num : (0 : ℝ) < 1) hkR) + set d : ℝ := 4 * k - 1 with hd + set δ : ℝ := 2 / d with hδdef + set s : ℝ := 1 / (2 * k) with hsdef + set γ : ℝ := (δ + s) / 2 with hγdef + set t : ℝ := (γ / δ + 1) / 2 with htdef + have h2kpos : (0 : ℝ) < 2 * k := by positivity + have hdpos : 0 < d := by rw [hd]; linarith + have hδ : 0 < δ := div_pos (by norm_num) hdpos + have hs : 0 < s := div_pos (by norm_num) h2kpos + have hsδ : s < δ := by + rw [hsdef, hδdef, div_lt_div_iff₀ h2kpos hdpos, hd] + linarith + have hγ : 0 < γ := by rw [hγdef]; positivity + have hγδ : γ < δ := by rw [hγdef]; linarith + have hδone : δ < 1 := by + rw [hδdef, div_lt_one hdpos, hd] + linarith + have hclear : ((2 * k - 1 : ℕ) : ℝ) * δ < 1 := by + have hkcast : (((2 * k - 1 : ℕ) : ℝ)) = 2 * (k : ℝ) - 1 := by + rw [Nat.cast_sub (by omega : 1 ≤ 2 * k)] + norm_num + rw [hkcast, hδdef, ← mul_div_assoc, div_lt_one hdpos, hd] + linarith + have hkε : 2 + ε < (k : ℝ) * ε := by + calc + 2 + ε = (2 / ε + 1) * ε := by field_simp + _ < (k : ℝ) * ε := mul_lt_mul_of_pos_right hkbig hε + have hdenom : 2 * δ ≤ ε := by + have hfour : (4 : ℝ) < ε * d := by + rw [hd] + nlinarith + rw [hδdef, show 2 * (2 / d) = 4 / d by ring, div_le_iff₀ hdpos] + linarith + have hgrow : 1 < (2 * k : ℝ) * γ := by + have hone : (2 * k : ℝ) * s = 1 := by rw [hsdef]; field_simp + calc + 1 = (2 * k : ℝ) * s := hone.symm + _ < (2 * k : ℝ) * γ := mul_lt_mul_of_pos_left (by rw [hγdef]; linarith) h2kpos + have hratio0 : 0 < γ / δ := div_pos hγ hδ + have hratio1 : γ / δ < 1 := (div_lt_one hδ).mpr hγδ + have ht0 : 0 < t := by rw [htdef]; positivity + have ht1 : t < 1 := by rw [htdef]; linarith + have hdt : δ * t = (γ + δ) / 2 := by + rw [htdef] + field_simp + have hsupply : γ < δ * t := by rw [hdt]; linarith + exact ⟨k, δ, γ, t, hk, hδ, hγ, hδone, hclear, hdenom, hgrow, ht0, ht1, hsupply⟩ + +end Asymptotics + +/- Assembly -/ + +/-- For a good prime, every residue is a sum of exactly `8k²` admissible inverses. -/ +lemma exactRep_of_good {ε δ γ : ℝ} {k p : ℕ} (hp : p.Prime) (hk : 0 < k) + (hpar : Good ε k δ γ p) (a : ZMod p) : ExactRep ε p (8 * k ^ 2) a := by + classical + have : NeZero p := ⟨hp.ne_zero⟩ + obtain ⟨hp2, hHlt, hsmall, hHsq, hlarge, hsupply⟩ := hpar + have hcard : Fintype.card (Fin k × Fin (fpow γ p)) ≤ #(Nat.primesLE (fpow δ p)) := by + simpa using hsupply + obtain ⟨e, he⟩ := Function.Embedding.exists_of_card_le_finset hcard + let q : Fin k → Fin (fpow γ p) → ℕ := fun i j ↦ e (i, j) + have hq_mem : ∀ i j, q i j ∈ Nat.primesLE (fpow δ p) := fun i j ↦ he ⟨(i, j), rfl⟩ + have hq_prime : ∀ i j, (q i j).Prime := fun i j ↦ Nat.prime_of_mem_primesLE (hq_mem i j) + have hq_le : ∀ i j, q i j ≤ fpow δ p := fun i j ↦ Nat.le_of_mem_primesLE (hq_mem i j) + have hq_inj : Function.Injective (fun ij : Fin k × Fin (fpow γ p) ↦ q ij.1 ij.2) := by + intro x y hxy + exact e.injective hxy + have hcardB : #(recSet p q) = (fpow γ p) ^ k := + card_recSet hp hk q hq_prime hq_inj hq_le hHlt hsmall + have hprod : p < #(recSet p q) * #(recSet p q) := by + rw [hcardB, ← pow_add, ← two_mul] + exact hlarge + have hanti := recSet_antisymm hp hk q hq_prime hq_le hHlt hsmall + have hcover := glibichuk hp hp2 (recSet p q) (recSet p q) hprod hanti + have ha : a ∈ sum8 (recSet p q) (recSet p q) := by rw [hcover]; exact mem_univ a + exact sum8_exactRep hp q hq_prime hq_le hHlt hHsq a ha + +/-- The upstream statement `Erdos1180.erdos_1180` (Glibichuk's theorem): for every `ε > 0` +there is `C` such that, for every prime `p`, every residue mod `p` is a sum of at most `C` +inverses of integers `1 ≤ n ≤ p ^ ε`. -/ +theorem exists_bound (ε : ℝ) (hε : 0 < ε) : ∃ C : ℕ, ∀ p : ℕ, p.Prime → ∀ a : ZMod p, + ∃ s : Multiset ℕ, Multiset.card s ≤ C ∧ _root_.Erdos1180.Represents ε p a s := by + obtain ⟨k, δ, γ, t, hk, hδ, hγ, hδone, hclear, hdenom, hgrow, ht0, ht1, hsupply⟩ := + choose_params hε + obtain ⟨P₀, hP₀⟩ := Filter.eventually_atTop.1 + (ev_good hk hδ hγ hδone hclear hdenom hgrow ht0 ht1 hsupply) + refine ⟨max (8 * k ^ 2) P₀, fun p hp a ↦ ?_⟩ + have : NeZero p := ⟨hp.ne_zero⟩ + by_cases hlarge : P₀ ≤ p + · obtain ⟨s, hs, hrep⟩ := exactRep_of_good hp hk (hP₀ p hlarge) a + exact ⟨s, hs ▸ le_max_left _ _, hrep⟩ + · -- small primes: use `a.val` copies of the denominator `1` + refine ⟨Multiset.replicate a.val 1, ?_, ?_, ?_⟩ + · rw [Multiset.card_replicate] + exact (a.val_lt.trans (Nat.lt_of_not_ge hlarge)).le.trans (le_max_right _ _) + · intro n hn + rw [Multiset.eq_of_mem_replicate hn] + refine ⟨le_rfl, ?_, Nat.coprime_one_left p⟩ + rw [Nat.cast_one] + exact Real.one_le_rpow (by exact_mod_cast hp.one_le) hε.le + · simp + +/- The refutation -/ + +section Refutation + +open Filter Topology + +/-- If `p < 2 ^ k`, the only positive integer `n ≤ p ^ (1 / k)` is `n = 1`. -/ +theorem eq_one_of_le_rpow {k p n : ℕ} (hk : 0 < k) (hp : p < 2 ^ k) + (h1 : 1 ≤ n) (hn : (n : ℝ) ≤ (p : ℝ) ^ ((1 : ℝ) / k)) : n = 1 := by + by_contra hne + have h2 : (2 : ℝ) ≤ (p : ℝ) ^ ((1 : ℝ) / k) := by + have : 2 ≤ n := by omega + exact le_trans (by exact_mod_cast this) hn + have hpow : (2 : ℝ) ^ k ≤ ((p : ℝ) ^ ((1 : ℝ) / k)) ^ k := pow_le_pow_left₀ (by norm_num) h2 k + have e : ((p : ℝ) ^ ((1 : ℝ) / k)) ^ k = p := by + rw [← Real.rpow_natCast, ← Real.rpow_mul (Nat.cast_nonneg p), + one_div_mul_cancel (by positivity), Real.rpow_one] + rw [e] at hpow + have : (p : ℝ) < 2 ^ k := by exact_mod_cast hp + linarith + +/-- If `p < 2 ^ k`, every representation of `-1` with exponent `1 / k` has at least `p - 1` +summands, since all denominators equal `1`. -/ +theorem card_ge_of_represents_neg_one {k p : ℕ} (hk : 0 < k) (hp : p.Prime) (hpk : p < 2 ^ k) + {s : Multiset ℕ} (hs : _root_.Erdos1180.Represents ((1 : ℝ) / k) p (-1) s) : + p - 1 ≤ Multiset.card s := by + have := Fact.mk hp + obtain ⟨hmem, hsum⟩ := hs + have hall : ∀ n ∈ s, n = 1 := fun n hn => + eq_one_of_le_rpow hk hpk (hmem n hn).1 (hmem n hn).2.1 + have hs1 : s = Multiset.replicate (Multiset.card s) 1 := Multiset.eq_replicate_card.mpr hall + rw [hs1] at hsum + simp only [Multiset.map_replicate, Nat.cast_one, inv_one, Multiset.sum_replicate, + nsmul_eq_mul, mul_one] at hsum + have h0 : ((Multiset.card s + 1 : ℕ) : ZMod p) = 0 := by + push_cast + rw [hsum] + ring + rw [ZMod.natCast_eq_zero_iff] at h0 + have := Nat.le_of_dvd (by omega) h0 + omega + +/-- `(m + 1) ^ 2 < 2 ^ m` for `m ≥ 6`. -/ +theorem sq_succ_lt_two_pow (m : ℕ) (hm : 6 ≤ m) : (m + 1) ^ 2 < 2 ^ m := by + induction m, hm using Nat.le_induction with + | base => norm_num + | succ n hn ih => + calc + (n + 1 + 1) ^ 2 ≤ 2 * (n + 1) ^ 2 := by nlinarith + _ < 2 * 2 ^ n := by omega + _ = 2 ^ (n + 1) := by rw [pow_succ]; ring + +/-- The upstream statement `erdos_1180.variants.optimal` is false. -/ +theorem not_erdos_1180_variants_optimal : + ¬ (type_of% @_root_.Erdos1180.erdos_1180.variants.optimal) := by + intro H + have h1 := H 1 one_pos + have ht : Tendsto (fun m : ℕ => (1 : ℝ) / ((m : ℝ) + 1)) atTop (𝓝[>] 0) := by + apply tendsto_nhdsWithin_of_tendsto_nhds_of_eventually_within + · exact tendsto_one_div_add_atTop_nhds_zero_nat + · exact Eventually.of_forall fun m => by + simp only [Set.mem_Ioi] + positivity + obtain ⟨M, hM⟩ := eventually_atTop.1 (ht.eventually h1) + set m := M + 10 with hmdef + have hm := hM m (by omega) + have hk : (0 : ℕ) < m + 1 := by omega + have hcast : (1 : ℝ) / ((m : ℝ) + 1) = (1 : ℝ) / ((m + 1 : ℕ) : ℝ) := by push_cast; rfl + rw [hcast] at hm + have hinv : ((1 : ℝ) / ((m + 1 : ℕ) : ℝ))⁻¹ ^ ((1 : ℝ) + 1) = (((m + 1) ^ 2 : ℕ) : ℝ) := by + rw [one_div, inv_inv, show ((1 : ℝ) + 1) = ((2 : ℕ) : ℝ) by norm_num, Real.rpow_natCast] + push_cast + ring + rw [hinv] at hm + -- a Bertrand prime in `(2 ^ m, 2 ^ (m + 1))` + obtain ⟨p, hp, hlt, hle⟩ := Nat.exists_prime_lt_and_le_two_mul (2 ^ m) (by positivity) + have h2m : 2 < 2 ^ m := by + calc 2 < 2 ^ 2 := by norm_num + _ ≤ 2 ^ m := Nat.pow_le_pow_right (by norm_num) (by omega) + have hplt : p < 2 ^ (m + 1) := by + rcases lt_or_eq_of_le hle with h | h + · rw [pow_succ]; omega + · exfalso + have hdvd : 2 ∣ p := ⟨2 ^ m, by rw [h]⟩ + rcases hp.eq_one_or_self_of_dvd 2 hdvd with h' | h' + · omega + · omega + -- the set defining `C ε` is nonempty, so `C ε` belongs to it + set ε : ℝ := (1 : ℝ) / ((m + 1 : ℕ) : ℝ) with hεdef + have hεpos : 0 < ε := by positivity + obtain ⟨C₀, hC₀⟩ := exists_bound ε hεpos + have hmem : _root_.Erdos1180.C ε ∈ {C : ℕ | ∀ p : ℕ, p.Prime → ∀ a : ZMod p, + ∃ s : Multiset ℕ, s.card ≤ C ∧ _root_.Erdos1180.Represents ε p a s} := + Nat.sInf_mem ⟨C₀, hC₀⟩ + obtain ⟨s, hscard, hs⟩ := hmem p hp (-1) + have hge := card_ge_of_represents_neg_one hk hp hplt hs + have hbig : 2 ^ m ≤ _root_.Erdos1180.C ε := by omega + have hsmall := sq_succ_lt_two_pow m (by omega) + have : ((2 ^ m : ℕ) : ℝ) ≤ (_root_.Erdos1180.C ε : ℝ) := by exact_mod_cast hbig + have : (((m + 1) ^ 2 : ℕ) : ℝ) < ((2 ^ m : ℕ) : ℝ) := by exact_mod_cast hsmall + linarith + +end Refutation + +end Math0.Erdos1180 + +#math0_refutes Math0.Erdos1180.not_erdos_1180_variants_optimal Erdos1180.erdos_1180.variants.optimal diff --git a/lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_i.lean b/lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_i.lean new file mode 100644 index 0000000..68356a1 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_i.lean @@ -0,0 +1,44 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1193» +import Math0.Audit + +/-! +# Erdős Problem 1193 (i): the lower density need not vanish + +Erdős [Er80] asked whether, for every `A ⊆ ℕ` and every non-decreasing positive `g : ℕ → ℕ`, the +set `{n : 1_A ∗ 1_A(n) = g(n)}` always has lower density `0`. As recorded on +erdosproblems.com, the answer as stated is trivially no, and this file proves the upstream +statement `Erdos1193.erdos_1193.parts.i` (the negation of the universal claim). The +counterexample is `A = ℕ`, `g n = n + 1`: every `n` has exactly `n + 1` ordered representations +`n = a + b` with `a, b ∈ ℕ`, so the set in question is all of `ℕ`, whose lower density is `1`. +-/ + +namespace Math0.Erdos1193 + +open AdditiveCombinatorics + +/-- With `A = ℕ`, the representation function is `n ↦ n + 1`. -/ +theorem sumRep_univ_eq (n : ℕ) : sumRep (Set.univ : Set ℕ) n = n + 1 := by + simp + +/-- The set of all natural numbers has lower density `1`. -/ +theorem lowerDensity_univ : (Set.univ : Set ℕ).lowerDensity = 1 := by + exact (Set.HasDensity.univ (β := ℕ)).liminf_eq + +/-- Not every set `{n | sumRep A n = g n}` with `g` monotone and positive has lower density `0`: +`A = ℕ`, `g n = n + 1` is a counterexample. -/ +theorem erdos_1193_parts_i : type_of% @Erdos1193.erdos_1193.parts.i := by + intro h + have hmono : Monotone (fun n : ℕ => n + 1) := fun a b hab => Nat.succ_le_succ hab + have hpos : ∀ n : ℕ, 0 < (fun n : ℕ => n + 1) n := fun n => Nat.succ_pos n + have h0 := h Set.univ (fun n => n + 1) hmono hpos + have hset : {n : ℕ | sumRep Set.univ n = n + 1} = Set.univ := + Set.eq_univ_of_forall fun n => sumRep_univ_eq n + rw [hset, lowerDensity_univ] at h0 + exact one_ne_zero h0 + +end Math0.Erdos1193 + +#math0_proves Math0.Erdos1193.erdos_1193_parts_i Erdos1193.erdos_1193.parts.i diff --git a/lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_ii.lean b/lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_ii.lean new file mode 100644 index 0000000..73ecb10 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_ii.lean @@ -0,0 +1,45 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«1193» +import Math0.Audit + +/-! +# Erdős Problem 1193 (ii): the upper density need not be bounded away from `1` + +Erdős [Er80] asked whether there is a constant `c < 1` such that, for every `A ⊆ ℕ` and every +non-decreasing positive `g : ℕ → ℕ`, the set `{n : 1_A ∗ 1_A(n) = g(n)}` has upper density `< c`. +As recorded on erdosproblems.com, the answer as stated is trivially no, and this file proves the +upstream statement `Erdos1193.erdos_1193.parts.ii` (the negation of that existence claim). The +counterexample is `A = ℕ`, `g n = n + 1`: every `n` has exactly `n + 1` ordered representations +`n = a + b` with `a, b ∈ ℕ`, so the set in question is all of `ℕ`, whose upper density is `1`, +which is not `< c` for any `c < 1`. +-/ + +namespace Math0.Erdos1193 + +open AdditiveCombinatorics + +/-- With `A = ℕ`, the representation function is `n ↦ n + 1`. -/ +theorem parts_ii_sumRep_univ (n : ℕ) : sumRep (Set.univ : Set ℕ) n = n + 1 := by + simp + +/-- The set of all natural numbers has upper density `1`. -/ +theorem upperDensity_univ_nat : (Set.univ : Set ℕ).upperDensity = 1 := by + exact (Set.HasDensity.univ (β := ℕ)).limsup_eq + +/-- There is no constant `c < 1` bounding the upper density of `{n | sumRep A n = g n}` for all +`A` and all monotone positive `g`: `A = ℕ`, `g n = n + 1` gives upper density `1`. -/ +theorem erdos_1193_parts_ii : type_of% @Erdos1193.erdos_1193.parts.ii := by + rintro ⟨c, hc1, h⟩ + have hmono : Monotone (fun n : ℕ => n + 1) := fun a b hab => Nat.succ_le_succ hab + have hpos : ∀ n : ℕ, 0 < (fun n : ℕ => n + 1) n := fun n => Nat.succ_pos n + have h0 := h Set.univ (fun n => n + 1) hmono hpos + have hset : {n : ℕ | sumRep Set.univ n = n + 1} = Set.univ := + Set.eq_univ_of_forall fun n => parts_ii_sumRep_univ n + rw [hset, upperDensity_univ_nat] at h0 + linarith + +end Math0.Erdos1193 + +#math0_proves Math0.Erdos1193.erdos_1193_parts_ii Erdos1193.erdos_1193.parts.ii diff --git a/lean/Math0/ErdosProblems/Erdos142_erdos_142.lean b/lean/Math0/ErdosProblems/Erdos142_erdos_142.lean new file mode 100644 index 0000000..80adfeb --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos142_erdos_142.lean @@ -0,0 +1,77 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«142» +import Math0.Audit + +/-! +# Erdős Problem 142: the uniform asymptotic formula is refuted + +Erdős Problem 142 asks for an asymptotic formula `f_k` with `r_k(N) ~ f_k(N)`, where `r_k(N)` is +the largest size of a subset of `{1, …, N}` with no non-trivial `k`-term arithmetic progression. +The upstream formalization uses a single unknown `erdos_142.answer : ℕ → ℝ` that does not depend +on `k`, while quantifying over every `k`. We prove that no choice of this function works: +`r_1(N) = N` (every set is free of 1-term progressions) while `r_2(N) ≤ 1` (any two distinct +elements form a 2-term progression), and these cannot both be asymptotic to the same function, +since that would force the bounded sequence `r_2(N)` to tend to infinity. +-/ + +namespace Math0.Erdos142 + +open Asymptotics Filter + +/-- A set of naturals free of non-trivial 2-term progressions has at most one element. -/ +theorem card_le_one_of_free_two {S : Finset ℕ} (hS : (S : Set ℕ).IsAPOfLengthFree 2) : + S.card ≤ 1 := by + by_contra h + rw [not_le] at h + obtain ⟨a, ha, b, hb, hab⟩ := Finset.one_lt_card.1 h + rcases lt_or_gt_of_ne hab with hlt | hlt + · have hsub : ({a, b} : Set ℕ) ⊆ (S : Set ℕ) := by + intro x hx + rcases hx with rfl | rfl <;> simp_all + have := hS _ hsub (Nat.isAPOfLength_pair hlt) + norm_num at this + · have hsub : ({b, a} : Set ℕ) ⊆ (S : Set ℕ) := by + intro x hx + rcases hx with rfl | rfl <;> simp_all + have := hS _ hsub (Nat.isAPOfLength_pair hlt) + norm_num at this + +/-- `r_2(N) ≤ 1` for every `N`. -/ +theorem r_two_le_one (N : ℕ) : Erdos142.r 2 N ≤ 1 := by + show Set.IsAPOfLengthFree.maxCard 2 N ≤ 1 + unfold Set.IsAPOfLengthFree.maxCard + apply csSup_le + · refine ⟨0, ∅, Finset.empty_subset _, ?_, rfl⟩ + intro t ht hap + have ht' : t = ∅ := Set.subset_empty_iff.1 (by simpa using ht) + subst ht' + exact absurd hap (Set.not_isAPOfLength_empty (by norm_num)) + · rintro n ⟨S, -, hS, rfl⟩ + exact card_le_one_of_free_two hS + +/-- No single function `a : ℕ → ℝ` satisfies `r_k(N) ~ a(N)` for every `k`. -/ +theorem erdos_142_refuted : + ∀ a : ℕ → ℝ, ¬ ∀ k : ℕ, (fun N => (Erdos142.r k N : ℝ)) ~[atTop] a := by + intro a h + have h1 := h 1 + have h2 := h 2 + have h12 : (fun N => (Erdos142.r 1 N : ℝ)) ~[atTop] (fun N => (Erdos142.r 2 N : ℝ)) := + h1.trans h2.symm + have htop1 : Tendsto (fun N => (Erdos142.r 1 N : ℝ)) atTop atTop := by + have : (fun N => (Erdos142.r 1 N : ℝ)) = fun N : ℕ => (N : ℝ) := by + funext N + simp [Erdos142.r, Set.IsAPOfLengthFree.maxCard_one] + rw [this] + exact tendsto_natCast_atTop_atTop + have htop2 := h12.tendsto_atTop htop1 + have hev := htop2.eventually_gt_atTop 1 + obtain ⟨N, hN⟩ := hev.exists + have := r_two_le_one N + have : (Erdos142.r 2 N : ℝ) ≤ 1 := by exact_mod_cast this + linarith + +end Math0.Erdos142 + +#math0_refutes_every_answer Math0.Erdos142.erdos_142_refuted Erdos142.erdos_142 with Erdos142.erdos_142.answer diff --git a/lean/Math0/ErdosProblems/Erdos142_erdos_142_variants_isTheta.lean b/lean/Math0/ErdosProblems/Erdos142_erdos_142_variants_isTheta.lean new file mode 100644 index 0000000..12e26ab --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos142_erdos_142_variants_isTheta.lean @@ -0,0 +1,68 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«142» +import Math0.Audit + +/-! +# Erdős Problem 142 (order of magnitude variant): no single answer works for all `k` + +Erdős Problem 142 asks for the order of magnitude of `r_k(N)`, the largest size of a subset of +`{1, …, N}` with no non-trivial `k`-term arithmetic progression. The upstream statement +`erdos_142.variants.isTheta` asks for one function `answer : ℕ → ℝ`, *independent of `k`*, with +`r_k =Θ answer` for every `k`. We prove that no such function exists, whatever the value of the +unknown `answer`. Indeed `r_1(N) = N`, while `r_2(N) ≤ 1` because any two distinct elements +form a 2-term progression; `Θ`-equivalence is transitive and symmetric, so `N =O(1)`, which is +absurd. This is a formalization defect (the answer should depend on `k`), not progress on the +research problem. +-/ + +namespace Math0.Erdos142 + +open Asymptotics Filter + +/-- A set of naturals that is free of non-trivial 2-term arithmetic progressions has at most +one element: two distinct elements `a < b` form the progression `{a, b}`. -/ +theorem isTheta_card_le_one_of_free {S : Finset ℕ} (h : (S : Set ℕ).IsAPOfLengthFree 2) : + S.card ≤ 1 := by + rw [Finset.card_le_one] + intro a ha b hb + by_contra hab + rcases lt_or_gt_of_ne hab with hlt | hlt + · have h1 := h {a, b} (by + intro x hx; rcases hx with rfl | rfl <;> simpa using (by assumption)) + (Nat.isAPOfLength_pair hlt) + norm_num at h1 + · have h1 := h {b, a} (by + intro x hx; rcases hx with rfl | rfl <;> simpa using (by assumption)) + (Nat.isAPOfLength_pair hlt) + norm_num at h1 + +/-- `r_2(N) ≤ 1` for every `N`. -/ +theorem isTheta_r_two_le_one (N : ℕ) : Erdos142.r 2 N ≤ 1 := by + unfold Erdos142.r Set.IsAPOfLengthFree.maxCard + apply csSup_le' + rintro n ⟨S, _, hS, rfl⟩ + exact isTheta_card_le_one_of_free (by exact_mod_cast hS) + +/-- For every candidate `answer : ℕ → ℝ`, it is false that `r_k =Θ answer` for all `k` +simultaneously (already `k = 1` and `k = 2` are incompatible). -/ +theorem not_isTheta : ∀ a : ℕ → ℝ, + ¬ ∀ k : ℕ, (fun N => (Erdos142.r k N : ℝ)) =Θ[atTop] a := by + intro a h + have h12 : (fun N => (Erdos142.r 1 N : ℝ)) =O[atTop] (fun N => (Erdos142.r 2 N : ℝ)) := + ((h 1).trans (h 2).symm).isBigO + have h2b : (fun N => (Erdos142.r 2 N : ℝ)) =O[atTop] (fun _ => (1 : ℝ)) := by + apply Asymptotics.IsBigO.of_bound 1 + filter_upwards with N + simp only [Real.norm_eq_abs, abs_one, mul_one, Nat.abs_cast] + exact_mod_cast isTheta_r_two_le_one N + have h3 := h12.trans h2b + simp only [Erdos142.r, Set.IsAPOfLengthFree.maxCard_one] at h3 + rw [Asymptotics.isBigO_one_iff] at h3 + exact Filter.not_isBoundedUnder_of_tendsto_atTop + (tendsto_norm_atTop_atTop.comp tendsto_natCast_atTop_atTop) h3 + +end Math0.Erdos142 + +#math0_refutes_every_answer Math0.Erdos142.not_isTheta Erdos142.erdos_142.variants.isTheta with Erdos142.erdos_142.variants.isTheta.answer diff --git a/lean/Math0/ErdosProblems/Erdos319_erdos_319.lean b/lean/Math0/ErdosProblems/Erdos319_erdos_319.lean new file mode 100644 index 0000000..5b678c4 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos319_erdos_319.lean @@ -0,0 +1,76 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«319» +import Math0.Audit + +/-! +# Erdős Problem 319: the constant-answer formulation is refuted + +Erdős Problem 319 asks for `c(N)`, the largest size of `A ⊆ {1, …, N}` that carries signs +`δ : A → {-1, 1}` with `∑_{n ∈ A} δ(n)/n = 0` while no nonempty proper subset of `A` has signed +sum zero. The upstream statement `erdos_319` uses one unknown `erdos_319.answer : ℕ` that does not +depend on `N`, while quantifying over every `N`. We prove that no natural number works: for `N = 0` +only `A = ∅` is allowed, so the maximum is `0`, while for `N = 6` the set `{2, 3, 6}` with +`1/2 - 1/3 - 1/6 = 0` is admissible, so the maximum is at least `3`. This is a defect of the +formalization (the intended answer depends on `N`, see the upstream `isTheta` variant), not a +resolution of the mathematical problem. +-/ + +open scoped Finset + +namespace Math0.Erdos319 + +/-- The sign pattern `+1` at `2` and `-1` elsewhere, used on `{2, 3, 6}`. -/ +def δ₀ : ℕ → ℤˣ := fun n => if n = 2 then 1 else -1 + +/-- `1/2 - 1/3 - 1/6 = 0`. -/ +theorem sum_witness : ∑ n ∈ ({2, 3, 6} : Finset ℕ), (δ₀ n : ℚ) / n = 0 := by + simp [δ₀, Finset.sum_insert] + norm_num + +/-- No nonempty proper subset of `{2, 3, 6}` has signed reciprocal sum zero under `δ₀`. -/ +theorem proper_witness : ∀ A' ⊂ ({2, 3, 6} : Finset ℕ), A'.Nonempty → + ∑ n ∈ A', (δ₀ n : ℚ) / n ≠ 0 := by + intro A' hA' hne + have hmem : A' ∈ (({2, 3, 6} : Finset ℕ).powerset.erase {2, 3, 6}) := by + rw [Finset.mem_erase, Finset.mem_powerset] + exact ⟨hA'.ne, hA'.subset⟩ + have hpow : (({2, 3, 6} : Finset ℕ).powerset.erase {2, 3, 6}) = + {∅, {2}, {3}, {6}, {2, 3}, {2, 6}, {3, 6}} := by decide + rw [hpow] at hmem + simp only [Finset.mem_insert, Finset.mem_singleton] at hmem + rcases hmem with rfl | rfl | rfl | rfl | rfl | rfl | rfl + · simp at hne + all_goals simp [δ₀, Finset.sum_insert] + all_goals norm_num + +/-- For `N = 6`, the size `3` is attained (by `A = {2, 3, 6}`). -/ +theorem three_mem : 3 ∈ { #A | (A) (_ : A ⊆ Finset.Icc 1 6) + (_ : ∃ δ : ℕ → ℤˣ, ∑ n ∈ A, (δ n : ℚ) / n = 0 ∧ + ∀ A' ⊂ A, A'.Nonempty → ∑ n ∈ A', (δ n : ℚ) / n ≠ 0) } := + ⟨{2, 3, 6}, by decide, ⟨δ₀, sum_witness, proper_witness⟩, by decide⟩ + +/-- For `N = 0`, the only attainable size is `0`, since `A ⊆ Icc 1 0 = ∅`. -/ +theorem eq_zero_of_mem {c : ℕ} (hc : c ∈ { #A | (A) (_ : A ⊆ Finset.Icc 1 0) + (_ : ∃ δ : ℕ → ℤˣ, ∑ n ∈ A, (δ n : ℚ) / n = 0 ∧ + ∀ A' ⊂ A, A'.Nonempty → ∑ n ∈ A', (δ n : ℚ) / n ≠ 0) }) : c = 0 := by + obtain ⟨A, hA, -, rfl⟩ := hc + have : A = ∅ := by + simpa using hA + simp [this] + +/-- No single natural number `c` is the maximum size of an admissible set for every `N`. -/ +theorem erdos_319_refuted : ∀ c : ℕ, ¬ ∀ N : ℕ, IsGreatest + { #A | (A) (_ : A ⊆ Finset.Icc 1 N) + (_ : ∃ δ : ℕ → ℤˣ, ∑ n ∈ A, (δ n : ℚ) / n = 0 ∧ + ∀ A' ⊂ A, A'.Nonempty → ∑ n ∈ A', (δ n : ℚ) / n ≠ 0) } c := by + intro c h + have h0 : c = 0 := eq_zero_of_mem (h 0).1 + have h6 : 3 ≤ c := (h 6).2 three_mem + omega + +end Math0.Erdos319 + +#math0_refutes_every_answer Math0.Erdos319.erdos_319_refuted Erdos319.erdos_319 with + Erdos319.erdos_319.answer diff --git a/lean/Math0/ErdosProblems/Erdos367_erdos_367_variants_higher_full_parts.lean b/lean/Math0/ErdosProblems/Erdos367_erdos_367_variants_higher_full_parts.lean new file mode 100644 index 0000000..a72b690 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos367_erdos_367_variants_higher_full_parts.lean @@ -0,0 +1,143 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«367» +import Math0.Audit + +/-! +# Erdős Problem 367: products of `r`-full parts beat `n^(1+ε)` infinitely often + +For `r ≥ 3`, `k ≥ 2` let `B_r(m)` be the `r`-full part of `m` (Erdős–Graham; erdosproblems.com/367). +We prove the upstream statement exactly as formalized: for every such `r, k` there is an +`ε = ε(r, k) > 0` (we take `ε = 1/(2r)`) with +`limsup_{n → ∞} (∏_{n ≤ m < n+k} B_r(m)) / n^(1+ε) = ∞` in `EReal`. +Take `t = 2^(rj)`, `A = t + 1` and `n = A^r - 1`. Then `B_r(n+1) = B_r(A^r) = A^r` since every +prime exponent of `A^r` is a multiple of `r`, and `t = A - 1 ∣ A^r - 1 = n`, so the `2`-part of +`n` contributes `B_r(n) ≥ t`. Hence the product is `≥ t·A^r`, while `n^(1+ε) ≤ A^r·√A`, so the +ratio is `≥ t/√(t+1) → ∞` as `j → ∞`. +-/ + +open Filter Erdos367 + +namespace Math0.Erdos367 + +/-- The `r`-full part `B r m` is always positive (an empty product is `1`). -/ +theorem B_pos (r m : ℕ) : 0 < B r m := by + unfold B + apply Finset.prod_pos + intro i hi + have hi' := (Finset.mem_filter.mp hi).1 + have hp : i.Prime := Nat.prime_of_mem_primeFactors (by simpa using hi') + exact pow_pos hp.pos _ + +/-- An `r`-th power is its own `r`-full part: `B_r(A^r) = A^r` for `A ≠ 0`. -/ +theorem B_pow_self (r A : ℕ) (hA : A ≠ 0) : B r (A ^ r) = A ^ r := by + unfold B + rw [Finset.filter_true_of_mem] + · exact Nat.prod_factorization_pow_eq_self (pow_ne_zero _ hA) + · intro i hi + rw [Finsupp.mem_support_iff] at hi + rw [Nat.factorization_pow] at hi ⊢ + simp only [Finsupp.smul_apply, smul_eq_mul] at hi ⊢ + have : A.factorization i ≠ 0 := by + intro h; rw [h] at hi; simp at hi + calc r = r * 1 := by ring + _ ≤ r * A.factorization i := Nat.mul_le_mul_left _ (Nat.one_le_iff_ne_zero.mpr this) + +/-- If `2^e ∣ n ≠ 0` with `1 ≤ r ≤ e`, then the `2`-part of `n` is `r`-full, so `2^e ≤ B_r(n)`. -/ +theorem two_pow_le_B (r n e : ℕ) (hn : n ≠ 0) (hr1 : 1 ≤ r) (hr : r ≤ e) (h : 2 ^ e ∣ n) : + 2 ^ e ≤ B r n := by + have he : e ≤ n.factorization 2 := (Nat.prime_two.pow_dvd_iff_le_factorization hn).mp h + calc 2 ^ e ≤ 2 ^ n.factorization 2 := Nat.pow_le_pow_right (by norm_num) he + _ ≤ B r n := by + unfold B + apply Finset.single_le_prod' (f := fun i => i ^ n.factorization i) + · intro i hi + have hi' := (Finset.mem_filter.mp hi).1 + have hp : i.Prime := Nat.prime_of_mem_primeFactors (by simpa using hi') + exact Nat.one_le_pow _ _ hp.pos + · rw [Finset.mem_filter, Finsupp.mem_support_iff] + omega + +/-- For `k ≥ 2` the product over `[n, n+k)` is at least `B_r(n)·B_r(n+1)`. -/ +theorem pair_le_prod (r n k : ℕ) (hk : 2 ≤ k) : + B r n * B r (n + 1) ≤ ∏ m ∈ Finset.Ico n (n + k), B r m := by + have hsub : ({n, n + 1} : Finset ℕ) ⊆ Finset.Ico n (n + k) := by + intro x hx + simp only [Finset.mem_insert, Finset.mem_singleton] at hx + rw [Finset.mem_Ico] + omega + have := Finset.prod_le_prod_of_subset_of_one_le' hsub (f := fun m => B r m) + (fun i _ _ => B_pos r i) + rw [Finset.prod_pair (by omega)] at this + exact this + +/-- For all `r ≥ 3`, `k ≥ 2` there is `ε > 0` (namely `1/(2r)`) such that +`limsup (∏_{n ≤ m < n+k} B_r(m)) / n^(1+ε) = ⊤`. -/ +theorem higher_full_parts : type_of% @Erdos367.erdos_367.variants.higher_full_parts := by + intro r k hr hk + refine ⟨1 / (2 * r), by positivity, ?_⟩ + rw [EReal.eq_top_iff_forall_lt] + intro y + refine lt_of_lt_of_le (EReal.coe_lt_coe_iff.mpr (lt_add_one y)) ?_ + apply le_limsup_of_frequently_le' + rw [frequently_atTop] + intro a + set M : ℝ := y + 1 with hM + set j : ℕ := a + ⌈(M + 1) ^ 2⌉₊ + 1 with hj + set t : ℕ := 2 ^ (r * j) with ht + set A : ℕ := t + 1 with hA + set n : ℕ := A ^ r - 1 with hn + have hr0 : r ≠ 0 := by omega + have htj : j ≤ t := by + have h1 : j < 2 ^ j := Nat.lt_two_pow_self + have h2 : 2 ^ j ≤ 2 ^ (r * j) := Nat.pow_le_pow_right (by norm_num) (by nlinarith) + omega + have hAr : A ≤ A ^ r := Nat.le_self_pow hr0 A + have hn1 : n + 1 = A ^ r := by omega + have htn : t ≤ n := by omega + have hn0 : n ≠ 0 := by + have : 1 ≤ j := by omega + omega + have hdvd : 2 ^ (r * j) ∣ n := by + have := Nat.sub_dvd_pow_sub_pow A 1 r + simpa [hA, ht] using this + have hBn : t ≤ B r n := two_pow_le_B r n (r * j) hn0 (by omega) (by nlinarith) hdvd + have hBn1 : B r (n + 1) = A ^ r := by rw [hn1]; exact B_pow_self r A (by omega) + have hP : t * A ^ r ≤ ∏ m ∈ Finset.Ico n (n + k), B r m := by + calc t * A ^ r ≤ B r n * B r (n + 1) := by rw [hBn1]; exact Nat.mul_le_mul_right _ hBn + _ ≤ _ := pair_le_prod r n k hk + refine ⟨n, by omega, ?_⟩ + rw [EReal.coe_le_coe_iff] + have hPR : (t:ℝ) * (A:ℝ) ^ r ≤ ((∏ m ∈ Finset.Ico n (n + k), B r m : ℕ) : ℝ) := by + exact_mod_cast hP + have hnR : (0:ℝ) < n := by exact_mod_cast Nat.pos_of_ne_zero hn0 + have hnA : (n:ℝ) ≤ (A:ℝ) ^ r := by exact_mod_cast (by omega : n ≤ A ^ r) + have hApos : (0:ℝ) < A := by positivity + have hpow : ((A:ℝ) ^ r) ^ (1 + 1 / (2 * (r:ℝ))) = (A:ℝ) ^ r * √(A:ℝ) := by + rw [Real.rpow_add (by positivity), Real.rpow_one, ← Real.rpow_natCast_mul hApos.le, + Real.sqrt_eq_rpow] + congr 2 + field_simp + have h1 : (n:ℝ) ^ (1 + 1 / (2 * (r:ℝ))) ≤ (A:ℝ) ^ r * √(A:ℝ) := by + rw [← hpow]; exact Real.rpow_le_rpow hnR.le hnA (by positivity) + have hsq : (√(A:ℝ)) ^ 2 = A := Real.sq_sqrt hApos.le + have hceil : (M + 1) ^ 2 ≤ (t:ℝ) := + le_trans (Nat.le_ceil _) (by exact_mod_cast (by omega : ⌈(M + 1) ^ 2⌉₊ ≤ t)) + have hA' : (A:ℝ) = t + 1 := by rw [hA]; push_cast; ring + have hrp : (0:ℝ) < (n:ℝ) ^ (1 + 1 / (2 * (r:ℝ))) := Real.rpow_pos_of_pos hnR _ + rw [le_div_iff₀ hrp] + rcases le_or_gt M 0 with hM0 | hM0 + · have : (0:ℝ) ≤ ((∏ m ∈ Finset.Ico n (n + k), B r m : ℕ) : ℝ) := by positivity + nlinarith + · have hs : M + 1 ≤ √(A:ℝ) := by + rw [Real.le_sqrt (by linarith) hApos.le]; linarith + have hst : M * √(A:ℝ) ≤ t := by nlinarith + calc M * (n:ℝ) ^ (1 + 1 / (2 * (r:ℝ))) ≤ M * ((A:ℝ) ^ r * √(A:ℝ)) := by gcongr + _ = (M * √(A:ℝ)) * (A:ℝ) ^ r := by ring + _ ≤ t * (A:ℝ) ^ r := by gcongr + _ ≤ _ := hPR + +end Math0.Erdos367 + +#math0_proves Math0.Erdos367.higher_full_parts Erdos367.erdos_367.variants.higher_full_parts diff --git a/lean/Math0/ErdosProblems/Erdos409_erdos_409_parts_i.lean b/lean/Math0/ErdosProblems/Erdos409_erdos_409_parts_i.lean new file mode 100644 index 0000000..fb012a5 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos409_erdos_409_parts_i.lean @@ -0,0 +1,52 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«409» +import Math0.Audit + +/-! +# Erdős Problem 409 (i): the constant-answer formulation is refuted + +Erdős Problem 409 asks how many iterations of `n ↦ φ(n) + 1` are needed, starting from `n`, +before a prime is reached. The upstream statement `erdos_409.parts.i` uses one unknown +`erdos_409.parts.i.answer : ℕ` that does not depend on `n`, while quantifying over every `n > 0`. +We prove that no natural number works: for `n = 2` the least number of iterations is `0` +(since `2` is prime), while for `n = 4` it is not `0` (since `4` is not prime; in fact it is `1`, +as `φ(4) + 1 = 3`). This is a defect of the formalization (the intended answer is a function of +`n`, see the upstream `isTheta`/`isBigO`/`isLittleO` variants), not a resolution of the +mathematical problem. +-/ + +open scoped Nat + +namespace Math0.Erdos409 + +/-- If the least number of iterations from `2` is `a`, then `a = 0`, because `2` is prime. -/ +theorem eq_zero_of_isLeast_two {a : ℕ} + (h : IsLeast { i | (φ · + 1)^[i] 2 |>.Prime } a) : a = 0 := by + have h0 : (0 : ℕ) ∈ { i | (φ · + 1)^[i] 2 |>.Prime } := by + simp only [Set.mem_ofPred_eq, Function.iterate_zero, id_eq] + exact Nat.prime_two + have := h.2 h0 + omega + +/-- `0` is not the least number of iterations from `4`, because `4` is not prime. -/ +theorem not_isLeast_four_zero : ¬ IsLeast { i | (φ · + 1)^[i] 4 |>.Prime } 0 := by + intro h + have h1 := h.1 + simp only [Set.mem_ofPred_eq, Function.iterate_zero, id_eq] at h1 + exact absurd h1 (by decide) + +/-- No single natural number `a` is the least number of iterations of `n ↦ φ(n) + 1` needed to +reach a prime for every `n > 0`. -/ +theorem erdos_409_parts_i_refuted : ∀ a : ℕ, ¬ ∀ (n : ℕ) (_ : 0 < n), + IsLeast { i | (φ · + 1)^[i] n |>.Prime } a := by + intro a h + have h2 : a = 0 := eq_zero_of_isLeast_two (h 2 (by norm_num)) + subst h2 + exact not_isLeast_four_zero (h 4 (by norm_num)) + +end Math0.Erdos409 + +#math0_refutes_every_answer Math0.Erdos409.erdos_409_parts_i_refuted Erdos409.erdos_409.parts.i + with Erdos409.erdos_409.parts.i.answer diff --git a/lean/Math0/ErdosProblems/Erdos723_erdos_723_variants_prime_power_is_projplane_order.lean b/lean/Math0/ErdosProblems/Erdos723_erdos_723_variants_prime_power_is_projplane_order.lean new file mode 100644 index 0000000..804d79e --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos723_erdos_723_variants_prime_power_is_projplane_order.lean @@ -0,0 +1,60 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«723» +import Math0.Audit + +/-! +# Projective planes of every prime-power order (Erdős Problem 723, existence variant) + +Erdős Problem 723 (the prime power conjecture) asks whether every finite projective plane has +prime-power order. The converse direction, recorded upstream as +`Erdos723.erdos_723.variants.prime_power_is_projplane_order`, is classical: for every prime power +`n = p ^ k` there is a finite projective plane of order `n`. We prove exactly that formal statement. +The witness is the Desarguesian plane `PG(2, q)` over the finite field `K = GaloisField p k` +(`q = p ^ k`): points and lines are both `ℙ K (Fin 3 → K)`, with incidence given by orthogonality, +as already packaged in Mathlib (`Configuration.ofField`). Counting points two ways gives +`order² + order + 1 = q² + q + 1`, and injectivity of `x ↦ x² + x + 1` on `ℕ` gives `order = q`. +-/ + +namespace Math0.Erdos723 + +open Configuration +open scoped LinearAlgebra.Projectivization + +/-- The map `x ↦ x² + x + 1` is injective on `ℕ`. -/ +lemma sq_add_add_one_injective {a b : ℕ} (h : a ^ 2 + a + 1 = b ^ 2 + b + 1) : a = b := by + rcases lt_trichotomy a b with hab | hab | hab + · have : a ^ 2 < b ^ 2 := Nat.pow_lt_pow_left hab (by norm_num) + omega + · exact hab + · have : b ^ 2 < a ^ 2 := Nat.pow_lt_pow_left hab (by norm_num) + omega + +/-- For every prime power `n` there is a finite projective plane of order `n`, namely the +projective plane over the finite field with `n` elements. -/ +theorem prime_power_is_projplane_order : + type_of% @Erdos723.erdos_723.variants.prime_power_is_projplane_order := by + intro n hn + obtain ⟨p, k, hp, hk, rfl⟩ := (isPrimePow_nat_iff n).1 hn + have : Fact p.Prime := ⟨hp⟩ + classical + let K := GaloisField p k + have : Fintype K := Fintype.ofFinite K + have : Fintype (ℙ K (Fin 3 → K)) := Fintype.ofFinite _ + refine ⟨ℙ K (Fin 3 → K), ℙ K (Fin 3 → K), inferInstance, inferInstance, inferInstance, + inferInstance, ?_⟩ + -- number of points via the order of the plane + have h1 := ProjectivePlane.card_points (ℙ K (Fin 3 → K)) (ℙ K (Fin 3 → K)) + -- number of points of `ℙ² (K)` via `|K|` + have h2 : Nat.card (ℙ K (Fin 3 → K)) = ∑ i ∈ Finset.range 3, Nat.card K ^ i := + Projectivization.card_of_finrank K (Fin 3 → K) (by simp) + have hK : Nat.card K = p ^ k := GaloisField.card p k hk.ne' + rw [Nat.card_eq_fintype_card, h1, hK] at h2 + simp [Finset.sum_range_succ] at h2 + apply sq_add_add_one_injective + linarith + +end Math0.Erdos723 + +#math0_proves Math0.Erdos723.prime_power_is_projplane_order Erdos723.erdos_723.variants.prime_power_is_projplane_order diff --git a/lean/Math0/ErdosProblems/Erdos750_erdos_750_variants_c_gt_quarter.lean b/lean/Math0/ErdosProblems/Erdos750_erdos_750_variants_c_gt_quarter.lean new file mode 100644 index 0000000..650dadb --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos750_erdos_750_variants_c_gt_quarter.lean @@ -0,0 +1,164 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«750» +import Math0.Audit + +/-! +# Erdős Problem 750: the Erdős–Hajnal bound for `f(m) = c·m`, `c > 1/4` + +Erdős Problem 750 asks for graphs of infinite chromatic number in which every `m`-vertex +subgraph has an independent set of size at least `m/2 - f(m)`; Erdős and Hajnal [ErHa67b] did +this for `f(m) = c·m` with any `c > 1/4`. We prove this variant using the shift graph, whose +vertices are pairs `i < j` of naturals with `(i, j)` adjacent to `(j, k)`. It is not +`k`-colourable for any `k`: the sets `T i = {colour (i, j) : j > i}` of colours cannot all differ, +and `T i = T j` with `i < j` makes `(i, j)` share its colour with some neighbour `(j, l)`. For a +finite set `S` of `m` vertices, every `X ⊆ ℕ` gives the independent set +`{(i, j) ∈ S : i ∈ X, j ∉ X}`, and averaging over all subsets `X` of the endpoints shows that one +of them has at least `m/4 ≥ m/2 - c·m` elements. +-/ + +namespace Math0.Erdos750 + +open Finset + +universe u u_1 + +/-- Vertices of the shift graph: pairs `(i, j)` of natural numbers with `i < j`, lifted to an +arbitrary universe. -/ +abbrev ShiftV : Type u := ULift.{u} {p : ℕ × ℕ // p.1 < p.2} + +/-- The shift graph: `(i, j)` is adjacent to `(j, k)`. -/ +def shiftGraph : SimpleGraph ShiftV.{u} where + Adj x y := x.down.1.2 = y.down.1.1 ∨ y.down.1.2 = x.down.1.1 + symm := ⟨fun _ _ h => Or.symm h⟩ + loopless := ⟨fun x h => by + have := x.down.2 + rcases h with h | h <;> omega⟩ + +/-- Adjacency in the shift graph. -/ +theorem shiftGraph_adj {x y : ShiftV.{u}} : + shiftGraph.Adj x y ↔ x.down.1.2 = y.down.1.1 ∨ y.down.1.2 = x.down.1.1 := Iff.rfl + +/-- The shift graph is not `k`-colourable for any `k`. -/ +theorem shiftGraph_not_colorable (k : ℕ) : ¬ shiftGraph.{u}.Colorable k := by + rintro ⟨C⟩ + let T : ℕ → Set (Fin k) := fun i => {c | ∃ j, ∃ h : i < j, C ⟨⟨(i, j), h⟩⟩ = c} + have key : ∀ a b, a < b → T a = T b → False := by + intro a b hab hT + have hmem : C ⟨⟨(a, b), hab⟩⟩ ∈ T b := by + rw [← hT] + exact ⟨b, hab, rfl⟩ + obtain ⟨l, hbl, hl⟩ := hmem + exact C.valid (show shiftGraph.Adj (⟨⟨(a, b), hab⟩⟩ : ShiftV) ⟨⟨(b, l), hbl⟩⟩ from + shiftGraph_adj.mpr (Or.inl rfl)) hl.symm + obtain ⟨a, b, hab, hT⟩ := Finite.exists_ne_map_eq_of_infinite T + rcases lt_or_gt_of_ne hab with h | h + · exact key a b h hT + · exact key b a h hT.symm + +/-- The shift graph has infinite chromatic number. -/ +theorem shiftGraph_chromaticNumber : shiftGraph.{u}.chromaticNumber = ⊤ := by + by_contra h + obtain ⟨n, hn⟩ := SimpleGraph.chromaticNumber_ne_top_iff_exists.mp h + exact shiftGraph_not_colorable n hn + +/-- For distinct `a, b ∈ U`, exactly a quarter of the subsets of `U` contain `a` but not `b`. -/ +theorem four_mul_card_filter_powerset (U : Finset ℕ) {a b : ℕ} (ha : a ∈ U) (hb : b ∈ U) + (hab : a ≠ b) : + 4 * (U.powerset.filter (fun X => a ∈ X ∧ b ∉ X)).card = 2 ^ U.card := by + have h : U.powerset.filter (fun X => a ∈ X ∧ b ∉ X) = + ((U.erase a).erase b).powerset.image (insert a) := by + ext X + simp only [mem_filter, mem_powerset, mem_image] + constructor + · rintro ⟨hXU, haX, hbX⟩ + refine ⟨X.erase a, ?_, insert_erase haX⟩ + intro x hx + rw [mem_erase] at hx + rw [mem_erase, mem_erase] + exact ⟨fun h => hbX (h ▸ hx.2), hx.1, hXU hx.2⟩ + · rintro ⟨Y, hY, rfl⟩ + refine ⟨insert_subset ha (hY.trans ((erase_subset _ _).trans (erase_subset _ _))), + mem_insert_self _ _, ?_⟩ + rw [mem_insert] + rintro (h | h) + · exact hab h.symm + · have := hY h + simp at this + have hinj : Set.InjOn (insert a) (((U.erase a).erase b).powerset : Set (Finset ℕ)) := by + intro Y hY Y' hY' h + rw [mem_coe, mem_powerset] at hY hY' + have haY : a ∉ Y := fun h => by + have := hY h + simp at this + have haY' : a ∉ Y' := fun h => by + have := hY' h + simp at this + rw [← erase_insert haY, ← erase_insert haY'] + exact congrArg (fun Z => Z.erase a) h + rw [h, card_image_of_injOn hinj, card_powerset, card_erase_of_mem (mem_erase.mpr ⟨hab.symm, hb⟩), + card_erase_of_mem ha] + have h2 : 1 < U.card := one_lt_card.mpr ⟨a, ha, b, hb, hab⟩ + obtain ⟨n, hn⟩ : ∃ n, U.card = n + 2 := ⟨U.card - 2, by omega⟩ + rw [hn, show n + 2 - 1 - 1 = n by omega] + ring + +/-- Averaging over cuts: every finite set `S` of vertices of the shift graph contains at least +`|S| / 4` pairs `(i, j)` with `i ∈ X` and `j ∉ X`, for a suitable `X`. -/ +theorem exists_large_cut (S : Finset ShiftV.{u}) : + ∃ X : Finset ℕ, S.card ≤ 4 * (S.filter (fun p => p.down.1.1 ∈ X ∧ p.down.1.2 ∉ X)).card := by + set U : Finset ℕ := S.image (fun p => p.down.1.1) ∪ S.image (fun p => p.down.1.2) + have hsum : ∑ X ∈ U.powerset, S.card ≤ + ∑ X ∈ U.powerset, 4 * (S.filter (fun p => p.down.1.1 ∈ X ∧ p.down.1.2 ∉ X)).card := by + apply le_of_eq + calc ∑ X ∈ U.powerset, S.card = ∑ p ∈ S, 2 ^ U.card := by + rw [sum_const, sum_const, card_powerset, smul_eq_mul, smul_eq_mul, mul_comm] + _ = ∑ p ∈ S, 4 * (U.powerset.filter (fun X => p.down.1.1 ∈ X ∧ p.down.1.2 ∉ X)).card := by + refine sum_congr rfl (fun p hp => ?_) + exact (four_mul_card_filter_powerset U (mem_union_left _ (mem_image_of_mem _ hp)) + (mem_union_right _ (mem_image_of_mem _ hp)) (ne_of_lt p.down.2)).symm + _ = ∑ p ∈ S, ∑ X ∈ U.powerset, + 4 * (if p.down.1.1 ∈ X ∧ p.down.1.2 ∉ X then 1 else 0) := by + simp only [card_filter, mul_sum] + _ = ∑ X ∈ U.powerset, ∑ p ∈ S, + 4 * (if p.down.1.1 ∈ X ∧ p.down.1.2 ∉ X then 1 else 0) := sum_comm + _ = ∑ X ∈ U.powerset, 4 * (S.filter (fun p => p.down.1.1 ∈ X ∧ p.down.1.2 ∉ X)).card := by + simp only [card_filter, mul_sum] + obtain ⟨X, -, hX⟩ := exists_le_of_sum_le ⟨∅, empty_mem_powerset _⟩ hsum + exact ⟨X, hX⟩ + +/-- Erdős–Hajnal: for every `c > 1/4` there is a graph of infinite chromatic number in which every +set of `m ≥ 1` vertices contains an independent set of size at least `m/2 - c·m`. -/ +theorem c_gt_quarter : type_of% @Erdos750.erdos_750.variants.c_gt_quarter.{u_1} := by + intro c hc + refine ⟨ShiftV.{u_1}, shiftGraph, shiftGraph_chromaticNumber, ?_⟩ + intro m S hm hS + have hfin : S.Finite := Set.finite_of_ncard_pos (hS ▸ hm) + obtain ⟨X, hX⟩ := exists_large_cut hfin.toFinset + refine ⟨{p | p ∈ S ∧ p.down.1.1 ∈ X ∧ p.down.1.2 ∉ X}, fun p hp => hp.1, ?_, ?_⟩ + · intro p hp q hq _ hadj + rcases shiftGraph_adj.mp hadj with h | h + · exact hp.2.2 (by rw [h]; exact hq.2.1) + · exact hq.2.2 (by rw [h]; exact hp.2.1) + · have hcard : ({p | p ∈ S ∧ p.down.1.1 ∈ X ∧ p.down.1.2 ∉ X} : Set ShiftV).ncard = + (hfin.toFinset.filter (fun p => p.down.1.1 ∈ X ∧ p.down.1.2 ∉ X)).card := by + rw [← Set.ncard_coe_finset] + congr 1 + ext p + simp + have hScard : hfin.toFinset.card = m := by rw [← hS, Set.ncard_eq_toFinset_card S hfin] + rw [hcard] + set k := (hfin.toFinset.filter (fun p => p.down.1.1 ∈ X ∧ p.down.1.2 ∉ X)).card + have h4 : (m : NNReal) ≤ 4 * k := by rw [← hScard]; exact_mod_cast hX + calc (m : NNReal) / 2 - c * m ≤ m / 2 - 1 / 4 * m := + tsub_le_tsub_left (mul_le_mul_of_nonneg_right hc.le (by positivity)) _ + _ ≤ k := by + rw [tsub_le_iff_right, ← NNReal.coe_le_coe] + rw [← NNReal.coe_le_coe] at h4 + push_cast at h4 ⊢ + linarith + +end Math0.Erdos750 + +#math0_proves Math0.Erdos750.c_gt_quarter Erdos750.erdos_750.variants.c_gt_quarter diff --git a/lean/Math0/ErdosProblems/Erdos775_erdos_775_variants_moon_moser.lean b/lean/Math0/ErdosProblems/Erdos775_erdos_775_variants_moon_moser.lean new file mode 100644 index 0000000..a7757e2 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos775_erdos_775_variants_moon_moser.lean @@ -0,0 +1,163 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«775» +import Math0.Audit + +/-! +# Erdős Problem 775 (Moon–Moser): at most `n - log₂ n + O(1)` clique sizes + +Moon and Moser (1965) showed that a graph on `n` vertices has maximal cliques of at most +`n - log₂ n + O(1)` different sizes; together with Spencer's construction this settles the graph +case of Erdős Problem 775 (erdosproblems.com/775). We prove the upstream statement with the +explicit constant `C = 1`, for every `n` (including `n = 0`). Fix a maximum clique `K` of size +`ω`. Every maximal clique has size in `[1, ω]`, so there are at most `ω` sizes; and a maximal +clique `S` is determined by `S \ K` (two maximal cliques agreeing outside `K` have a union that +is a clique), so there are at most `2 ^ (n - ω)` maximal cliques. With `L = ⌊log₂ n⌋`, either +`ω ≤ n - L`, or `2 ^ (n - ω) ≤ 2 ^ (L - 1) ≤ n - L`; and `log₂ n < L + 1`. +-/ + +open Finset + +namespace Math0.Erdos775 + +/-- The predicate "`S` is a maximal clique of `G`" on finsets. -/ +abbrev IsMaxCl {V : Type} (G : SimpleGraph V) (S : Finset V) : Prop := + Maximal (fun T : Finset V => G.IsClique (T : Set V)) S + +/-- Two maximal cliques that agree outside a clique `K` are equal: their union is a clique. -/ +theorem eq_of_sdiff_eq {V : Type} [DecidableEq V] {G : SimpleGraph V} {K S S' : Finset V} + (hK : G.IsClique (K : Set V)) (hS : IsMaxCl G S) (hS' : IsMaxCl G S') + (h : S \ K = S' \ K) : S = S' := by + have memK : ∀ x, x ∈ S → x ∉ S' → x ∈ K := by + intro x hx hx' + by_contra hxK + have : x ∈ S \ K := mem_sdiff.2 ⟨hx, hxK⟩ + rw [h] at this + exact hx' (mem_sdiff.1 this).1 + have memK' : ∀ x, x ∈ S' → x ∉ S → x ∈ K := by + intro x hx hx' + by_contra hxK + have : x ∈ S' \ K := mem_sdiff.2 ⟨hx, hxK⟩ + rw [← h] at this + exact hx' (mem_sdiff.1 this).1 + have hU : G.IsClique ((S ∪ S' : Finset V) : Set V) := by + intro a ha b hb hab + simp only [coe_union, Set.mem_union, mem_coe] at ha hb + by_cases haS : a ∈ S <;> by_cases hbS : b ∈ S + · exact hS.prop haS hbS hab + · have hb' : b ∈ S' := hb.resolve_left hbS + by_cases haS' : a ∈ S' + · exact hS'.prop haS' hb' hab + · exact hK (memK a haS haS') (memK' b hb' hbS) hab + · have ha' : a ∈ S' := ha.resolve_left haS + by_cases hbS' : b ∈ S' + · exact hS'.prop ha' hbS' hab + · exact hK (memK' a ha' haS) (memK b hbS hbS') hab + · exact hS'.prop (ha.resolve_left haS) (hb.resolve_left hbS) hab + have e1 : S = S ∪ S' := hS.eq_of_le hU subset_union_left + have e2 : S' = S ∪ S' := hS'.eq_of_le hU subset_union_right + exact e1.trans e2.symm + +/-- The number of clique sizes is at most `2 ^ (|V| - |K|)` for any clique `K`, since a maximal +clique `S` is determined by `S \ K ⊆ V \ K`. -/ +theorem ncard_cliqueSizes_le_two_pow {V : Type} [Fintype V] [DecidableEq V] + (G : SimpleGraph V) {K : Finset V} (hK : G.IsClique (K : Set V)) : + G.cliqueSizes.ncard ≤ 2 ^ (Fintype.card V - K.card) := by + classical + set M : Finset (Finset V) := univ.filter (fun S => IsMaxCl G S) with hM + have hsub : G.cliqueSizes ⊆ ((M.image Finset.card : Finset ℕ) : Set ℕ) := by + rintro k ⟨S, hS, rfl⟩ + simp only [coe_image, Set.mem_image, mem_coe] + exact ⟨S, by simpa [hM] using hS, rfl⟩ + calc G.cliqueSizes.ncard ≤ ((M.image Finset.card : Finset ℕ) : Set ℕ).ncard := + Set.ncard_le_ncard hsub (Finset.finite_toSet _) + _ = (M.image Finset.card).card := Set.ncard_coe_finset _ + _ ≤ M.card := card_image_le + _ ≤ ((univ \ K).powerset).card := by + apply Finset.card_le_card_of_injOn (fun S => S \ K) + · intro S _ + simp only [coe_powerset, Set.mem_preimage, Set.mem_powerset_iff, coe_subset] + exact sdiff_subset_sdiff (subset_univ _) le_rfl + · intro S hS S' hS' h + simp only [hM, coe_filter, mem_univ, true_and, Set.mem_ofPred_eq] at hS hS' + exact eq_of_sdiff_eq hK hS hS' h + _ = 2 ^ (Fintype.card V - K.card) := by + rw [card_powerset, card_univ_sdiff] + +/-- In a nonempty finite graph, every clique size lies in `[1, |K|]` for a maximum clique `K`. -/ +theorem ncard_cliqueSizes_le_card {V : Type} [Fintype V] [Nonempty V] + (G : SimpleGraph V) {K : Finset V} (hK : G.IsMaximumClique K) : + G.cliqueSizes.ncard ≤ K.card := by + have hsub : G.cliqueSizes ⊆ ((Finset.Icc 1 K.card : Finset ℕ) : Set ℕ) := by + rintro k ⟨S, hS, rfl⟩ + simp only [coe_Icc, Set.mem_Icc] + refine ⟨?_, hK.maximum S hS.prop⟩ + rw [Nat.one_le_iff_ne_zero, Ne, card_eq_zero] + rintro rfl + obtain ⟨v⟩ := ‹Nonempty V› + have h1 : G.IsClique (({v} : Finset V) : Set V) := by simp + have := hS.eq_of_le h1 (empty_subset _) + simp at this + calc G.cliqueSizes.ncard ≤ ((Finset.Icc 1 K.card : Finset ℕ) : Set ℕ).ncard := + Set.ncard_le_ncard hsub (Finset.finite_toSet _) + _ = K.card := by rw [Set.ncard_coe_finset]; simp + +/-- `log₂ n < ⌊log₂ n⌋ + 1`. -/ +theorem logb_lt_log_add_one (n : ℕ) : Real.logb 2 n < (Nat.log 2 n : ℝ) + 1 := by + rcases Nat.eq_zero_or_pos n with rfl | hn + · simp + · rw [Real.logb_lt_iff_lt_rpow (by norm_num) (by exact_mod_cast hn)] + have := Nat.lt_pow_succ_log_self (b := 2) (by norm_num) n + have h2 : ((n : ℕ) : ℝ) < ((2 ^ (Nat.log 2 n + 1) : ℕ) : ℝ) := by exact_mod_cast this + have e : ((Nat.log 2 n : ℝ) + 1) = ((Nat.log 2 n + 1 : ℕ) : ℝ) := by push_cast; ring + rw [e, Real.rpow_natCast] + exact_mod_cast h2 + +/-- The arithmetic core: if `t ≤ k` and `t ≤ 2^(n-k)` with `k ≤ n`, then +`t ≤ n - ⌊log₂ n⌋`. -/ +theorem nat_bound (n k t : ℕ) (hn : 1 ≤ n) (h1 : t ≤ k) (h2 : t ≤ 2 ^ (n - k)) (hk : k ≤ n) : + t + Nat.log 2 n ≤ n := by + set L := Nat.log 2 n with hL + have hpow : 2 ^ L ≤ n := Nat.pow_log_le_self 2 (by omega) + by_cases hc : k + L ≤ n + · omega + · have hL1 : 1 ≤ L := by omega + have h3 : 2 ^ (n - k) ≤ 2 ^ (L - 1) := Nat.pow_le_pow_right (by norm_num) (by omega) + have h4 : L - 1 < 2 ^ (L - 1) := Nat.lt_two_pow_self + have h5 : 2 ^ L = 2 ^ (L - 1) + 2 ^ (L - 1) := by + rw [← two_mul, ← pow_succ']; congr 1; omega + omega + +/-- Moon–Moser with `C = 1`: every graph on `n` vertices has at most `n - log₂ n + 1` +clique sizes. -/ +theorem main_bound (n : ℕ) (G : SimpleGraph (Fin n)) : + (G.cliqueSizes.ncard : ℝ) ≤ (n : ℝ) - Real.logb 2 (n : ℝ) + 1 := by + rcases Nat.eq_zero_or_pos n with rfl | hn + · have hsub : G.cliqueSizes ⊆ {0} := by + rintro k ⟨S, _, rfl⟩ + simp [Finset.eq_empty_of_isEmpty S] + have := Set.ncard_le_ncard hsub (Set.finite_singleton 0) + simp only [Set.ncard_singleton] at this + simp only [CharP.cast_eq_zero, Real.logb_zero, sub_zero, zero_add] + exact_mod_cast this + · have : Nonempty (Fin n) := ⟨⟨0, hn⟩⟩ + obtain ⟨K, hK⟩ := G.maximumClique_exists + have h1 := ncard_cliqueSizes_le_card G hK + have h2 := ncard_cliqueSizes_le_two_pow G hK.isClique + have hk : K.card ≤ n := by simpa using card_le_univ K + rw [Fintype.card_fin] at h2 + have key := nat_bound n K.card _ hn h1 h2 hk + have hlog := logb_lt_log_add_one n + have key' : ((G.cliqueSizes.ncard : ℕ) : ℝ) + (Nat.log 2 n : ℝ) ≤ (n : ℝ) := by + exact_mod_cast key + linarith + +/-- **Moon–Moser.** There is a constant `C` (namely `C = 1`) such that every graph on `n` +vertices has at most `n - log₂ n + C` distinct sizes of maximal cliques. -/ +theorem erdos_775_moon_moser : type_of% @Erdos775.erdos_775.variants.moon_moser := + ⟨1, main_bound⟩ + +end Math0.Erdos775 + +#math0_proves Math0.Erdos775.erdos_775_moon_moser Erdos775.erdos_775.variants.moon_moser diff --git a/lean/Math0/ErdosProblems/Erdos816_erdos_816_variants_complete_bipartite.lean b/lean/Math0/ErdosProblems/Erdos816_erdos_816_variants_complete_bipartite.lean new file mode 100644 index 0000000..b94f0f3 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos816_erdos_816_variants_complete_bipartite.lean @@ -0,0 +1,76 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«816» +import Math0.Audit + +/-! +# Erdős Problem 816: the extremal example `K_{n,n+1}` + +Erdős Problem 816 (Erdős–Hajnal) asks whether every graph on `2n+1` vertices with `n^2+n+1` +edges contains two vertices of equal degree joined by a path of length `3`. The complete +bipartite graph `K_{n,n+1}` shows that `n^2+n` edges do not suffice; this file proves exactly the +upstream statement `erdos_816.variants.complete_bipartite`: for every `n`, `K_{n,n+1}` has +`n^2+n` edges and has no two distinct vertices of equal degree joined by a path of length `3`. +The edge count is `|Fin n| * |Fin (n+1)| = n(n+1)`. Vertices on the left side have degree +`n+1` and vertices on the right side have degree `n`, so equal-degree vertices lie on the same +side, while any walk of length `3` alternates sides and hence joins opposite sides. +-/ + +namespace Math0.Erdos816 + +open SimpleGraph + +open scoped Classical in +/-- `K_{n,n+1}` has exactly `n^2 + n` edges. -/ +theorem card_edgeFinset (n : ℕ) : + (completeBipartiteGraph (Fin n) (Fin (n + 1))).edgeFinset.card = n ^ 2 + n := by + rw [← Set.ncard_coe_finset, coe_edgeFinset, Set.ncard_def, + encard_edgeSet_completeBipartiteGraph] + simp only [ENat.card_eq_coe_fintype_card, Fintype.card_fin] + rw [← Nat.cast_mul, ENat.toNat_natCast] + ring + +open scoped Classical in +/-- In `K_{n,n+1}`, every vertex of the left part `Fin n` has degree `n + 1`. -/ +theorem degree_inl (n : ℕ) (a : Fin n) : + (completeBipartiteGraph (Fin n) (Fin (n + 1))).degree (Sum.inl a) = n + 1 := by + rw [← card_neighborFinset_eq_degree] + have : (completeBipartiteGraph (Fin n) (Fin (n + 1))).neighborFinset (Sum.inl a) = + Finset.univ.map Function.Embedding.inr := by + ext w; cases w <;> simp + rw [this]; simp + +open scoped Classical in +/-- In `K_{n,n+1}`, every vertex of the right part `Fin (n + 1)` has degree `n`. -/ +theorem degree_inr (n : ℕ) (b : Fin (n + 1)) : + (completeBipartiteGraph (Fin n) (Fin (n + 1))).degree (Sum.inr b) = n := by + rw [← card_neighborFinset_eq_degree] + have : (completeBipartiteGraph (Fin n) (Fin (n + 1))).neighborFinset (Sum.inr b) = + Finset.univ.map Function.Embedding.inl := by + ext w; cases w <;> simp + rw [this]; simp + +open scoped Classical in +/-- `K_{n,n+1}` contains no two distinct vertices of equal degree joined by a path of length 3: +a walk of length 3 joins opposite sides, and the two sides have different degrees. -/ +theorem not_hasEqualDegreePathThree (n : ℕ) : + ¬ Erdos816.HasEqualDegreePathThree (completeBipartiteGraph (Fin n) (Fin (n + 1))) := by + rintro ⟨u, v, -, hdeg, p, -, hlen⟩ + match p with + | .cons h1 (.cons h2 (.cons h3 .nil)) => + rename_i x y + rcases u with a | a <;> rcases v with c | c <;> rcases x with x | x <;> + rcases y with y | y <;> simp at h1 h2 h3 <;> + simp only [degree_inl, degree_inr] at hdeg <;> omega + +/-- For every `n`, the complete bipartite graph `K_{n,n+1}` on `2n+1` vertices has `n^2 + n` +edges and contains no two vertices of the same degree joined by a path of length `3`. -/ +theorem erdos_816_complete_bipartite : + type_of% @Erdos816.erdos_816.variants.complete_bipartite := by + intro n + exact ⟨card_edgeFinset n, not_hasEqualDegreePathThree n⟩ + +end Math0.Erdos816 + +#math0_proves Math0.Erdos816.erdos_816_complete_bipartite Erdos816.erdos_816.variants.complete_bipartite diff --git a/lean/Math0/ErdosProblems/Erdos834_erdos_834_parts_ii.lean b/lean/Math0/ErdosProblems/Erdos834_erdos_834_parts_ii.lean new file mode 100644 index 0000000..22dcd9a --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos834_erdos_834_parts_ii.lean @@ -0,0 +1,117 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«834» +import Math0.Audit + +/-! +# A 3-critical 3-uniform hypergraph of minimum degree 7 (Erdős Problem 834, part ii) + +Erdős and Lovász asked whether there is a 3-critical 3-uniform hypergraph in which every vertex +has degree at least 7, where (in the chromatic formulation) 3-critical means that the weak +chromatic number is 3 and deleting any edge, or any vertex together with its incident edges, +leaves a 2-colorable hypergraph. Li [Li25] answered this positively with a 22-edge example on 9 +vertices. We prove exactly the formal statement `Erdos834.erdos_834.parts.ii` with a different, +21-edge, 7-regular example on `Fin 9` found by a SAT search. Uniformity, the degrees and an +explicit proper 3-coloring are checked by `decide`; non-2-colorability is checked by kernel +`decide` over all `2^9` maps `Fin 9 → Fin 2`; and for every edge and every vertex we exhibit an +explicit proper 2-coloring of the remaining hypergraph. +-/ + +namespace Math0.Erdos834 + +/-- The witness: a 7-regular 3-uniform hypergraph with 21 edges on the vertex set `Fin 9`. -/ +def H : Finset (Finset (Fin 9)) := + {{0, 1, 4}, {0, 1, 5}, {0, 1, 6}, {0, 2, 6}, {0, 4, 6}, {0, 5, 6}, {0, 5, 8}, {1, 3, 5}, + {1, 3, 8}, {1, 4, 6}, {1, 5, 8}, {2, 3, 4}, {2, 3, 7}, {2, 4, 6}, {2, 4, 7}, {2, 6, 7}, + {2, 7, 8}, {3, 4, 7}, {3, 5, 8}, {3, 7, 8}, {5, 7, 8}} + +/-- Every edge of `H` has exactly three vertices. -/ +lemma H_uniform : H.IsUniform 3 := by + unfold Finset.IsUniform; decide +kernel + +/-- Every vertex of `H` lies in at least (in fact exactly) seven edges. -/ +lemma H_deg : ∀ v : Fin 9, 7 ≤ H.hypergraphDegree v := by + unfold Finset.hypergraphDegree; decide +kernel + +/-- `H` has a proper 3-coloring, with color classes `{0,1,2,3}`, `{4,5,6,7}`, `{8}`. -/ +lemma H_col3 : H.HypergraphColorable 3 := + ⟨![0, 0, 0, 0, 1, 1, 1, 1, 2], by unfold Finset.IsProperHypergraphColoring; decide +kernel⟩ + +/-- `H` has no proper 2-coloring (checked over all `2^9` maps `Fin 9 → Fin 2`). -/ +lemma H_not2 : ∀ c : Fin 9 → Fin 2, ¬ H.IsProperHypergraphColoring c := by + unfold Finset.IsProperHypergraphColoring; decide +kernel + +/-- `H` is not colorable with fewer than three colors. -/ +lemma H_not_lt3 : ∀ j < 3, ¬ H.HypergraphColorable j := by + intro j hj ⟨c, hc⟩ + interval_cases j + · exact Fin.elim0 (c 0) + · obtain ⟨x, -, y, -, hxy⟩ := hc {0, 1, 4} (by decide +kernel) + exact hxy (Subsingleton.elim _ _) + · exact H_not2 c hc + +/-- For each edge `e` of `H`, a 2-coloring under which `e` is the only monochromatic edge. -/ +def edgeColoring (e : Finset (Fin 9)) : Fin 9 → Fin 2 := + if e = {0, 1, 4} then ![0, 0, 0, 1, 0, 1, 1, 1, 0] + else if e = {0, 1, 5} then ![0, 0, 0, 1, 1, 0, 1, 0, 1] + else if e = {0, 1, 6} then ![0, 0, 1, 0, 1, 1, 0, 0, 1] + else if e = {0, 2, 6} then ![0, 1, 0, 0, 1, 1, 0, 1, 0] + else if e = {0, 4, 6} then ![0, 1, 1, 0, 0, 1, 0, 1, 0] + else if e = {0, 5, 6} then ![0, 1, 1, 0, 1, 0, 0, 0, 1] + else if e = {0, 5, 8} then ![0, 1, 0, 1, 0, 0, 1, 1, 0] + else if e = {1, 3, 5} then ![0, 1, 0, 1, 0, 1, 1, 1, 0] + else if e = {1, 3, 8} then ![0, 0, 0, 0, 1, 1, 1, 1, 0] + else if e = {1, 4, 6} then ![0, 1, 0, 0, 1, 0, 1, 1, 1] + else if e = {1, 5, 8} then ![0, 1, 1, 0, 1, 1, 0, 0, 1] + else if e = {2, 3, 4} then ![0, 1, 0, 0, 0, 0, 1, 1, 1] + else if e = {2, 3, 7} then ![0, 0, 0, 0, 1, 1, 1, 0, 1] + else if e = {2, 4, 6} then ![0, 0, 1, 0, 1, 1, 1, 0, 1] + else if e = {2, 4, 7} then ![0, 1, 1, 0, 1, 1, 0, 1, 0] + else if e = {2, 6, 7} then ![0, 1, 1, 0, 0, 1, 1, 1, 0] + else if e = {2, 7, 8} then ![0, 0, 0, 1, 1, 1, 1, 0, 0] + else if e = {3, 4, 7} then ![0, 0, 0, 1, 1, 1, 1, 1, 0] + else if e = {3, 5, 8} then ![0, 0, 0, 1, 1, 1, 1, 0, 1] + else if e = {3, 7, 8} then ![0, 1, 1, 0, 1, 1, 0, 0, 0] + else ![0, 0, 0, 0, 1, 1, 1, 1, 1] -- the edge {5, 7, 8} + +/-- `edgeColoring e` properly 2-colors `H` with the edge `e` deleted. -/ +lemma edgeColoring_proper : + ∀ e ∈ H, (H.erase e).IsProperHypergraphColoring (edgeColoring e) := by + unfold Finset.IsProperHypergraphColoring; decide +kernel + +/-- Deleting any single edge of `H` leaves a 2-colorable hypergraph. -/ +lemma H_erase : ∀ e ∈ H, (H.erase e).HypergraphColorable 2 := + fun e he ↦ ⟨edgeColoring e, edgeColoring_proper e he⟩ + +/-- For each vertex `v`, a 2-coloring of `H` with all edges through `v` deleted. -/ +def vertexColoring : Fin 9 → Fin 9 → Fin 2 := + ![![0, 0, 0, 1, 0, 1, 1, 1, 0], + ![0, 0, 0, 0, 1, 0, 1, 1, 1], + ![0, 0, 0, 0, 1, 1, 1, 0, 1], + ![0, 0, 0, 0, 1, 1, 1, 0, 1], + ![0, 0, 0, 1, 0, 1, 1, 1, 0], + ![0, 0, 0, 0, 1, 0, 1, 1, 1], + ![0, 0, 1, 0, 1, 1, 0, 0, 1], + ![0, 0, 0, 0, 1, 1, 1, 0, 1], + ![0, 0, 0, 0, 1, 1, 1, 1, 0]] + +/-- `vertexColoring v` properly 2-colors the edges of `H` avoiding `v`. -/ +lemma vertexColoring_proper : + ∀ v : Fin 9, (H.filter (fun e ↦ v ∉ e)).IsProperHypergraphColoring (vertexColoring v) := by + unfold Finset.IsProperHypergraphColoring; decide +kernel + +/-- Deleting any single vertex of `H` (with its incident edges) leaves a 2-colorable +hypergraph. -/ +lemma H_vertex : ∀ v : Fin 9, (H.filter (fun e ↦ v ∉ e)).HypergraphColorable 2 := + fun v ↦ ⟨vertexColoring v, vertexColoring_proper v⟩ + +/-- **Erdős Problem 834 (ii).** There is a 3-uniform hypergraph with weak chromatic number 3 +such that deleting any edge, or any vertex with its incident edges, makes it 2-colorable, and in +which every vertex has degree at least 7. -/ +theorem erdos_834_parts_ii : type_of% @Erdos834.erdos_834.parts.ii := + ⟨9, H, H_uniform, ⟨H_col3, H_not_lt3⟩, H_erase, H_vertex, H_deg⟩ + +end Math0.Erdos834 + +#math0_proves Math0.Erdos834.erdos_834_parts_ii Erdos834.erdos_834.parts.ii diff --git a/lean/Math0/ErdosProblems/Erdos835_johnsonGraph_18_9_chromaticNumber.lean b/lean/Math0/ErdosProblems/Erdos835_johnsonGraph_18_9_chromaticNumber.lean new file mode 100644 index 0000000..7a40595 --- /dev/null +++ b/lean/Math0/ErdosProblems/Erdos835_johnsonGraph_18_9_chromaticNumber.lean @@ -0,0 +1,140 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.ErdosProblems.«835» +import Math0.Audit + +/-! +# Erdős Problem 835: the chromatic number of `J(18, 9)` exceeds `10` + +Erdős Problem 835 asks whether the `k`-subsets of a `2k`-set can be coloured with `k + 1` colours +so that every `(k + 1)`-subset sees all colours; equivalently whether `χ(J(2k, k)) = k + 1`. +The upstream file records the case `k = 9`: `χ(J(18, 9)) > 10`. We prove it by first proving +Johnson's bound `α(J(n, k)) ≤ johnsonBound n 4 k` for the independence number (the upstream +lemma `indepNum_johnson_le_johnsonBound`, in full generality), via double counting: if `F` is a +family of `k`-subsets of `S` with pairwise intersections of size at most `k - 2`, then +`k * |F| = ∑_{i ∈ S} |{A ∈ F : i ∈ A}|`, and the sets `A \ {i}` with `i ∈ A ∈ F` form a family of +the same kind with parameters `(|S| - 1, k - 1)`. Evaluating gives `α(J(18, 9)) ≤ 4420`, hence +`χ(J(18, 9)) ≥ ⌈48620 / 4420⌉ = 11`. +-/ + +namespace Math0.Erdos835 + +open Finset SimpleGraph + +/-- Johnson's bound for constant-weight codes of minimum distance `4`: a family `F` of `k`-subsets +of a finset `S` whose distinct members meet in at most `k - 2` elements has at most +`johnsonBound #S 4 k` members. -/ +theorem card_le_johnsonBound {α : Type*} [DecidableEq α] : + ∀ (k : ℕ) (S : Finset α) (F : Finset (Finset α)), + (∀ A ∈ F, A ⊆ S ∧ #A = k) → + (∀ A ∈ F, ∀ B ∈ F, A ≠ B → #(A ∩ B) + 1 < k) → + #F ≤ Erdos835.johnsonBound #S 4 k := by + intro k + induction k with + | zero => + intro S F hF _ + have hsub : F ⊆ {∅} := fun A hA => by + simpa [← card_eq_zero] using (hF A hA).2 + calc #F ≤ 1 := (card_le_card hsub).trans (by simp) + _ = _ := by cases #S <;> rfl + | succ k ih => + intro S F hF hP + have hle1 : k = 0 ∨ #S = 0 → #F ≤ 1 := by + rintro (rfl | h0) + · rw [card_le_one] + intro A hA B hB + by_contra hAB + have := hP A hA B hB hAB + omega + · rw [card_eq_zero] at h0 + subst h0 + have hsub : F ⊆ {∅} := fun A hA => by + simpa using (hF A hA).1 + exact (card_le_card hsub).trans (by simp) + rcases hS : #S with _ | n + · exact (hle1 (Or.inr hS)).trans (by rfl) + by_cases hk : k = 0 + · subst hk + exact (hle1 (Or.inl rfl)).trans (by simp [Erdos835.johnsonBound]) + rw [Erdos835.johnsonBound, if_neg (by omega), Nat.le_div_iff_mul_le (by omega)] + -- each point lies in at most `johnsonBound n 4 k` members of `F` + have h2 : ∀ i ∈ S, #{A ∈ F | i ∈ A} ≤ Erdos835.johnsonBound n 4 k := by + intro i hi + have hinj : Set.InjOn (fun A : Finset α => A.erase i) ({A ∈ F | i ∈ A} : Finset _) := by + intro A hA B hB hAB + simp only [coe_filter, Set.mem_ofPred_eq] at hA hB + have := congrArg (insert i) hAB + simpa [insert_erase hA.2, insert_erase hB.2] using this + have := ih (S.erase i) (({A ∈ F | i ∈ A} : Finset _).image (fun A => A.erase i)) ?_ ?_ + · rwa [card_erase_of_mem hi, hS, card_image_of_injOn hinj] at this + · simp only [mem_image, mem_filter] + rintro _ ⟨A, ⟨hA, hiA⟩, rfl⟩ + refine ⟨erase_subset_erase _ (hF A hA).1, ?_⟩ + rw [card_erase_of_mem hiA, (hF A hA).2] + rfl + · simp only [mem_image, mem_filter] + rintro _ ⟨A, ⟨hA, hiA⟩, rfl⟩ _ ⟨B, ⟨hB, hiB⟩, rfl⟩ hne + have hAB : A ≠ B := fun h => hne (h ▸ rfl) + have h1 := hP A hA B hB hAB + have h3 : A.erase i ∩ B.erase i = (A ∩ B).erase i := by + ext x; simp; tauto + rw [h3, card_erase_of_mem (mem_inter.2 ⟨hiA, hiB⟩)] + have h5 : 0 < #(A ∩ B) := card_pos.2 ⟨i, mem_inter.2 ⟨hiA, hiB⟩⟩ + omega + -- double counting the incidences `i ∈ A` + have h1 : ∑ t ∈ F, #(S ∩ t) ≤ #S * Erdos835.johnsonBound n 4 k := sum_card_inter_le h2 + have h4 : ∑ t ∈ F, #(S ∩ t) = #F * (k + 1) := by + rw [sum_const_nat] + intro t ht + rw [inter_eq_right.2 (hF t ht).1, (hF t ht).2] + rw [hS] at h1 + linarith + +/-- Johnson's bound for the independence number of the Johnson graph: +`α(J(n, k)) ≤ johnsonBound n 4 k` (the upstream lemma `indepNum_johnson_le_johnsonBound`). -/ +theorem indepNum_johnson_le : type_of% @Erdos835.indepNum_johnson_le_johnsonBound := by + intro n k + obtain ⟨s, hs⟩ := (J(n, k)).exists_isNIndepSet_indepNum + rw [← hs.card_eq] + have h := card_le_johnsonBound k (univ : Finset (Fin n)) + (s.map (Function.Embedding.subtype _)) ?_ ?_ + · simpa using h + · simp only [mem_map, Function.Embedding.subtype_apply] + rintro _ ⟨a, -, rfl⟩ + exact ⟨subset_univ _, a.2⟩ + · simp only [mem_map, Function.Embedding.subtype_apply] + rintro _ ⟨a, ha, rfl⟩ _ ⟨b, hb, rfl⟩ hne + have hab : a ≠ b := fun h => hne (h ▸ rfl) + have := hs.isIndepSet (mem_coe.2 ha) (mem_coe.2 hb) hab + rcases not_johnson_adj_iff_lt.1 this with h | h + · exact absurd h hab + · exact h + +/-- The Johnson bound evaluates to `4420` for `n = 18`, distance `4`, weight `9`. -/ +theorem johnsonBound_18_4_9 : Erdos835.johnsonBound 18 4 9 = 4420 := by decide + +/-- The chromatic number of the Johnson graph `J(18, 9)` is at least `11`, i.e. greater than +`9 + 1`. -/ +theorem johnsonGraph_18_9_chromaticNumber : + type_of% @Erdos835.johnsonGraph_18_9_chromaticNumber := by + have hc := card_div_indepNum_le_chromaticNumber (G := J(18, 9)) + have hα : α(J(18, 9)) ≤ 4420 := + johnsonBound_18_4_9 ▸ indepNum_johnson_le (n := 18) (k := 9) + have : Nonempty {s : Finset (Fin 18) // #s = 9} := + ⟨⟨(univ : Finset (Fin 18)).filter (fun i => i.val < 9), by decide⟩⟩ + have hpos : 0 < α(J(18, 9)) := indepNum_pos + have hcard : Nat.card {s : Finset (Fin 18) // #s = 9} = 48620 := by + rw [Nat.card_eq_fintype_card, Fintype.card_finset_len] + decide + have h10 : 10 < ⌈(Nat.card {s : Finset (Fin 18) // #s = 9} / α(J(18, 9)) : ℚ≥0)⌉₊ := by + rw [Nat.lt_ceil, hcard, lt_div_iff₀ (by exact_mod_cast hpos)] + have : ((10 * α(J(18, 9)) : ℕ) : ℚ≥0) < ((48620 : ℕ) : ℚ≥0) := by + exact_mod_cast (by omega) + simpa using this + show (10 : ℕ∞) < _ + exact lt_of_lt_of_le (by exact_mod_cast h10) hc + +end Math0.Erdos835 + +#math0_proves Math0.Erdos835.johnsonGraph_18_9_chromaticNumber Erdos835.johnsonGraph_18_9_chromaticNumber diff --git a/lean/Math0/Frontier/OEIS/A001040.lean b/lean/Math0/Frontier/OEIS/A001040.lean new file mode 100644 index 0000000..3cd408a --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A001040.lean @@ -0,0 +1,780 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A001040 +import Math0.Audit + +/-! +# Kurkov's rook-tour conjecture for A001040 + +We prove that the number of open rook tours (directed Hamiltonian paths of `K_n □ K_2`) of the +`n × 2` board whose first and last squares lie on different lines of length `n` is +`2 · n! · a(n)`, where `a(n+1) = n a(n) + a(n-1)`, `a(0) = 0`, `a(1) = 1` (A001040). + +**First-step analysis.** Fix the current square `x` on line `c` and the set `U` of squares still to +be visited (`x ∉ U`). By symmetry the number of ways to finish, ending on a line `t`, depends only +on `F` (rows with both squares in `U`), `A` (rows with only their line-`c` square in `U`), `B` +(rows with only their other square in `U`), whether the partner of `x` is in `U`, and whether +`c = t`. The next square is the partner of `x`, a square of a full row on line `c`, or a single +square on line `c`; this gives a recursion (`card_paths`). + +**Closed form.** A path with `i` switches between the lines is determined by the ordered switch +rows (`F^{(i)}` choices) and the arrangement of the remaining squares of each line into the +ordered slots of that line (rising factorials). We do not need this bijection: we only check that +the closed form `G` satisfies the recursion (`G_rec`, `g_rec`). + +**Summation.** From a fixed corner of the full board the count is +`∑_k (n-1)^{(2k)} ((k+1)^{(n-1-2k)})^2`; its terms satisfy +`w(m+2,k+1) = (m+2)^2 w(m+1,k+1) + (m+2)(m+1) w(m,k)` (the identity +`n(n-2k) + k^2 = (n-k)^2`), so the sum is `(n-1)! a(n)`. Multiplying by the `2n` starting +squares gives `2 · n! · a(n)`. +-/ + +namespace Math0.Frontier.A001040 +open Nat +open Math0.Statements.A001040 + +/-- `n.ascFactorial (k+1) = n * (n+1).ascFactorial k`. -/ +private lemma asc_succ_left (n k : ℕ) : n.ascFactorial (k + 1) = n * (n + 1).ascFactorial k := by + rw [Nat.ascFactorial_succ, Nat.succ_ascFactorial] + +/-- Closed form for the number of paths with exactly `i` switches from a square on line `c` +having no partner, when `F` rows are full, `A` rows have only their line-`c` square and `B` rows +only their other square: `F^{(i)}` ways for the switch rows, then the free squares of each line +are distributed into the ordered slots of that line (rising factorials). -/ +private def G (i F A B : ℕ) : ℕ := + F.descFactorial i * ((i + 2) / 2).ascFactorial (A + F - i) * + ((i + 1) / 2).ascFactorial (B + F - i) + +/-- `G` vanishes when there are more switches than full rows. -/ +private lemma G_eq_zero {i F : ℕ} (A B : ℕ) (h : F < i) : G i F A B = 0 := by + simp [G, Nat.descFactorial_eq_zero_iff_lt.mpr h] + +/-- `G` with `F = i + m`, written without truncated subtraction. -/ +private lemma G_add (i m A B : ℕ) : G i (i + m) A B = + (i + m).descFactorial i * ((i + 2) / 2).ascFactorial (A + m) * + ((i + 1) / 2).ascFactorial (B + m) := by + unfold G + rw [show A + (i + m) - i = A + m by omega, show B + (i + m) - i = B + m by omega] + +/-- Key ascending factorial identity. -/ +private lemma asc_key (i N : ℕ) : ((i + 2) / 2).ascFactorial (N + 1) = + (N + 1) * ((i + 2) / 2).ascFactorial N + + (if i = 0 then 0 else ((i + 2) / 2 - 1).ascFactorial (N + 1)) := by + rcases Nat.eq_zero_or_pos i with rfl | hi + · show (1 : ℕ).ascFactorial (N + 1) = (N + 1) * (1 : ℕ).ascFactorial N + 0 + rw [Nat.ascFactorial_succ]; ring + · rw [if_neg (by omega)] + obtain ⟨k, hk⟩ : ∃ k, (i + 2) / 2 = k + 1 := ⟨(i + 2) / 2 - 1, by omega⟩ + rw [hk, show k + 1 - 1 = k by omega, asc_succ_left k, Nat.ascFactorial_succ] + ring + +/-- The first summand of the recursion for `G` in closed form. -/ +private lemma T1 (i m A B : ℕ) : (i + m) * G i (i + m - 1) A (B + 1) = + m * (i + m).descFactorial i * ((i + 2) / 2).ascFactorial (A + m - 1) * + ((i + 1) / 2).ascFactorial (B + m) := by + rcases m with _ | m + · rcases i with _ | i + · simp + · rw [G_eq_zero _ _ (by omega)]; simp + · rw [show i + (m + 1) - 1 = i + m by omega, G_add, + show A + (m + 1) - 1 = A + m by omega, show B + 1 + m = B + (m + 1) by omega] + have h1 := Nat.succ_descFactorial_succ (i + m) i + have h2 := Nat.descFactorial_succ (i + m + 1) i + rw [show i + m + 1 - i = m + 1 by omega] at h2 + rw [show i + (m + 1) = i + m + 1 by omega] + have : (i + m + 1) * (i + m).descFactorial i = (m + 1) * (i + m + 1).descFactorial i := by + rw [← h1, h2] + calc (i + m + 1) * ((i + m).descFactorial i * ((i + 2) / 2).ascFactorial (A + m) * + ((i + 1) / 2).ascFactorial (B + (m + 1))) + = ((i + m + 1) * (i + m).descFactorial i) * ((i + 2) / 2).ascFactorial (A + m) * + ((i + 1) / 2).ascFactorial (B + (m + 1)) := by ring + _ = _ := by rw [this] + +/-- The second summand of the recursion for `G` in closed form. -/ +private lemma T2 (i m A B : ℕ) : (if i = 0 then 0 else (i + m) * G (i - 1) (i + m - 1) B A) = + if i = 0 then 0 else (i + m).descFactorial i * ((i + 1) / 2).ascFactorial (B + m) * + ((i + 2) / 2 - 1).ascFactorial (A + m) := by + rcases i with _ | i + · simp + · rw [if_neg (by omega), if_neg (by omega), show i + 1 + m - 1 = i + m by omega, + show i + 1 - 1 = i by omega, G_add, show (i + 1 + 1) / 2 = (i + 2) / 2 by omega, + show (i + 1 + 2) / 2 - 1 = (i + 1) / 2 by omega, show i + 1 + m = i + m + 1 by omega, + Nat.succ_descFactorial_succ] + ring + +/-- The third summand of the recursion for `G` in closed form. -/ +private lemma T3 (i m A B : ℕ) : A * G i (i + m) (A - 1) B = + A * (i + m).descFactorial i * ((i + 2) / 2).ascFactorial (A + m - 1) * + ((i + 1) / 2).ascFactorial (B + m) := by + rcases A with _ | A + · simp + · rw [G_add, show A + 1 - 1 + m = A + 1 + m - 1 by omega]; ring + +/-- First-step recursion satisfied by the closed form `G`. -/ +private lemma G_rec (i F A B : ℕ) : G i F A B = + (if F = 0 ∧ A = 0 ∧ B = 0 ∧ i = 0 then 1 else 0) + F * G i (F - 1) A (B + 1) + + (if i = 0 then 0 else F * G (i - 1) (F - 1) B A) + A * G i F (A - 1) B := by + rcases lt_or_ge F i with h | h + · rw [G_eq_zero A B h, G_eq_zero _ _ (show F < i from h)] + rcases Nat.eq_zero_or_pos F with rfl | hF + · simp + omega + · rw [G_eq_zero _ _ (show F - 1 < i by omega)] + rw [if_neg (by omega), if_neg (by omega), G_eq_zero _ _ (show F - 1 < i - 1 by omega)] + simp + obtain ⟨m, rfl⟩ : ∃ m, F = i + m := ⟨F - i, by omega⟩ + rw [T1, T2, T3, G_add] + rcases Nat.eq_zero_or_pos (A + m) with hAm | hAm + · obtain ⟨rfl, rfl⟩ : A = 0 ∧ m = 0 := ⟨by omega, by omega⟩ + rcases Nat.eq_zero_or_pos i with rfl | hi + · rcases B with _ | B <;> simp [Nat.zero_ascFactorial] + · rw [if_neg (by omega), if_neg (by omega)] + simp + · obtain ⟨N, hN⟩ : ∃ N, A + m = N + 1 := ⟨A + m - 1, by omega⟩ + rw [if_neg (by omega), hN, asc_key, show N + 1 - 1 = N by omega] + rcases Nat.eq_zero_or_pos i with rfl | hi + · simp only [if_true] + have : (N + 1 : ℕ) = m + A := by omega + rw [this]; ring + · rw [if_neg (by omega), if_neg (by omega)] + have : (N + 1 : ℕ) = m + A := by omega + rw [this]; ring + + + +/-- `g F A B s`: the closed form summed over the numbers of switches of the right parity +(`s` = the path ends on the line it starts on). -/ +private def g (F A B : ℕ) (s : Bool) : ℕ := + ∑ k ∈ Finset.range (F + 1), G (2 * k + (if s then 0 else 1)) F A B + +/-- First-step recursion for `g`: move to a full row of the current line (then either keep +its partner for later or not), or to a single square of the current line. -/ +private lemma g_rec (F A B : ℕ) (s : Bool) : g F A B s = + (if F = 0 ∧ A = 0 ∧ B = 0 ∧ s = true then 1 else 0) + F * g (F - 1) A (B + 1) s + + F * g (F - 1) B A (!s) + A * g F (A - 1) B s := by + unfold g + rw [Finset.sum_congr rfl (fun k _ => G_rec (2 * k + (if s then 0 else 1)) F A B)] + simp only [Finset.sum_add_distrib] + congr 1 + congr 1 + congr 1 + · -- base + rw [Finset.sum_range_succ'] + rw [Finset.sum_eq_zero (fun k _ => if_neg (by omega))] + cases s <;> simp + · rcases F with _ | F + · simp + · rw [Finset.sum_range_succ, G_eq_zero _ _ (show F + 1 - 1 < 2 * (F + 1) + _ by omega), + Finset.mul_sum] + simp + · rcases F with _ | F + · simp + · rw [Finset.mul_sum] + cases s + · simp only [Bool.not_false, if_false, if_true, Bool.false_eq_true] + rw [Finset.sum_range_succ, if_neg (by omega), + show 2 * (F + 1) + 1 - 1 = 2 * (F + 1) by omega, + G_eq_zero _ _ (show F + 1 - 1 < 2 * (F + 1) by omega)] + simp only [mul_zero, add_zero, Nat.add_sub_cancel] + apply Finset.sum_congr rfl + intro k _ + rw [if_neg (by omega)] + · simp only [Bool.not_true, if_false, if_true, Bool.false_eq_true] + rw [Finset.sum_range_succ', if_pos (by omega), add_zero] + simp only [Nat.add_sub_cancel] + apply Finset.sum_congr rfl + intro k _ + rw [if_neg (by omega), show 2 * (k + 1) + 0 - 1 = 2 * k + 1 by omega] + · rw [Finset.mul_sum] + +/-- The paired summand `m^{(2k)} ((k+1)^{(m-2k)})^2` (falling and rising factorials). -/ +private def w (m k : ℕ) : ℕ := m.descFactorial (2 * k) * ((k + 1).ascFactorial (m - 2 * k)) ^ 2 + +/-- `w m k` vanishes when `m < 2k`. -/ +private lemma w_eq_zero {m k : ℕ} (h : m < 2 * k) : w m k = 0 := by + simp [w, Nat.descFactorial_eq_zero_iff_lt.mpr h] + +/-- Pairing the two terms with `2k` and `2k+1` switches gives `w m k`. -/ +private lemma G_pair (m k : ℕ) : G (2 * k + 1) m 0 1 + G (2 * k) m 0 0 = w m k := by + unfold G w + have e1 : (2 * k + 1 + 2) / 2 = k + 1 := by omega + have e2 : (2 * k + 1 + 1) / 2 = k + 1 := by omega + have e3 : (2 * k + 2) / 2 = k + 1 := by omega + have e4 : (2 * k + 1) / 2 = k := by omega + have e5 : 1 + m - (2 * k + 1) = m - 2 * k := by omega + have e6 : 0 + m - (2 * k) = m - 2 * k := by omega + have e7 : 0 + m - (2 * k + 1) = m - 2 * k - 1 := by omega + simp only [e1, e2, e4, e5, e6, e7, Nat.descFactorial_succ] + rcases lt_or_ge m (2 * k) with h | h + · simp [Nat.descFactorial_eq_zero_iff_lt.mpr h] + obtain ⟨N, rfl⟩ : ∃ N, m = 2 * k + N := ⟨m - 2 * k, by omega⟩ + rw [show 2 * k + N - 2 * k = N by omega] + rcases N with _ | N + · simp + · rw [show N + 1 - 1 = N by omega, asc_succ_left k, Nat.ascFactorial_succ] + ring + +/-- The count of opposite-line paths from a fixed start, as a sum of `w`. -/ +private lemma E_sum (m : ℕ) : + g m 0 1 false + g m 0 0 true = ∑ k ∈ Finset.range (m + 1), w m k := by + unfold g + rw [← Finset.sum_add_distrib] + apply Finset.sum_congr rfl + intro k _ + simpa using G_pair m k + +/-- Recursion of `w` at `k = 0`. -/ +private lemma w_rec0 (m : ℕ) : w (m + 2) 0 = (m + 2) ^ 2 * w (m + 1) 0 := by + simp [w, Nat.factorial_succ] + ring + +/-- Termwise recursion of `w`, the identity `n(n-2k) + k^2 = (n-k)^2` in disguise. -/ +private lemma w_rec (m j : ℕ) : + w (m + 2) (j + 1) = (m + 2) ^ 2 * w (m + 1) (j + 1) + (m + 2) * (m + 1) * w m j := by + rcases lt_or_ge m (2 * j) with h | h + · rw [w_eq_zero (by omega), w_eq_zero (by omega), w_eq_zero h]; simp + obtain ⟨N, rfl⟩ : ∃ N, m = 2 * j + N := ⟨m - 2 * j, by omega⟩ + unfold w + rw [show 2 * (j + 1) = 2 * j + 1 + 1 by ring, show 2 * j + N + 2 = 2 * j + N + 1 + 1 by ring, + Nat.succ_descFactorial_succ, Nat.succ_descFactorial_succ, Nat.succ_descFactorial_succ, + Nat.descFactorial_succ, show 2 * j + N - 2 * j = N by omega, + show 2 * j + N + 1 + 1 - (2 * j + 1 + 1) = N by omega, + show 2 * j + N + 1 - (2 * j + 1 + 1) = N - 1 by omega, show j + 1 + 1 = j + 2 by ring] + rcases N with _ | N + · simp; ring + · rw [show N + 1 - 1 = N by omega, Nat.ascFactorial_succ, asc_succ_left (j + 1)] + rw [show j + 1 + 1 = j + 2 by ring] + ring + +/-- The sum of `w` equals `m! * a (m+1)`. -/ +private lemma S_eq (m : ℕ) : ∑ k ∈ Finset.range (m + 1), w m k = m ! * a (m + 1) := by + induction m using Nat.strong_induction_on with + | _ m ih => + rcases m with _ | _ | m + · simp [w, a] + · simp [w, a, Finset.sum_range_succ] + · rw [Finset.sum_range_succ', w_rec0] + simp only [w_rec, Finset.sum_add_distrib, ← Finset.mul_sum] + have h1 : ∑ k ∈ Finset.range (m + 2), w (m + 1) (k + 1) + w (m + 1) 0 = + ∑ k ∈ Finset.range (m + 1 + 1), w (m + 1) k := by + rw [← Finset.sum_range_succ', Finset.sum_range_succ, w_eq_zero (by omega), add_zero] + have h2 : ∑ k ∈ Finset.range (m + 2), w m k = ∑ k ∈ Finset.range (m + 1), w m k := by + rw [Finset.sum_range_succ, w_eq_zero (by omega), add_zero] + have e : a (m + 1 + 1 + 1) = (m + 2) * a (m + 2) + a (m + 1) := by + show a (m + 1 + 2) = _; rw [a] + rw [h2, ih m (by omega)] + have h3 := ih (m + 1) (by omega) + rw [← h1] at h3 + calc (m + 2) ^ 2 * ∑ k ∈ Finset.range (m + 2), w (m + 1) (k + 1) + + (m + 2) * (m + 1) * (m ! * a (m + 1)) + (m + 2) ^ 2 * w (m + 1) 0 + = (m + 2) ^ 2 * (∑ k ∈ Finset.range (m + 2), w (m + 1) (k + 1) + w (m + 1) 0) + + (m + 2) * (m + 1) * (m ! * a (m + 1)) := by ring + _ = _ := by + rw [h3, e]; simp only [Nat.factorial_succ] + ring + +variable {n : ℕ} + +/-- The other line. -/ +private def oth (c : Fin 2) : Fin 2 := 1 - c + +/-- The other line differs. -/ +private lemma oth_ne (c : Fin 2) : oth c ≠ c := by fin_cases c <;> decide +/-- The other line differs (symmetric form). -/ +private lemma ne_oth (c : Fin 2) : c ≠ oth c := fun h => oth_ne c h.symm +/-- `oth` is an involution. -/ +private lemma oth_oth (c : Fin 2) : oth (oth c) = c := by fin_cases c <;> decide +/-- Every line is `c` or `oth c`. -/ +private lemma eq_or_eq_oth (c d : Fin 2) : d = c ∨ d = oth c := by + fin_cases c <;> fin_cases d <;> decide +/-- Ending on line `t` from the other line. -/ +private lemma decide_oth (c t : Fin 2) : decide (oth c = t) = !decide (c = t) := by + fin_cases c <;> fin_cases t <;> decide + +/-- Rows with both squares in `U`. -/ +private def full (U : Finset (Fin n × Fin 2)) (c : Fin 2) : ℕ := + (Finset.univ.filter fun r : Fin n => (r, c) ∈ U ∧ (r, oth c) ∈ U).card + +/-- Rows whose only square in `U` is the one on line `c`. -/ +private def only (U : Finset (Fin n × Fin 2)) (c : Fin 2) : ℕ := + (Finset.univ.filter fun r : Fin n => (r, c) ∈ U ∧ (r, oth c) ∉ U).card + +/-- `full` does not depend on the line. -/ +private lemma full_oth (U : Finset (Fin n × Fin 2)) (c : Fin 2) : full U (oth c) = full U c := by + unfold full + congr 1 + ext r + simp only [Finset.mem_filter, Finset.mem_univ, true_and, oth_oth] + tauto + +/-- Removing a square of a full row. -/ +private lemma full_erase_both {U : Finset (Fin n × Fin 2)} {r : Fin n} {c : Fin 2} + (h1 : (r, c) ∈ U) (h2 : (r, oth c) ∈ U) : full (U.erase (r, c)) c = full U c - 1 := by + unfold full + rw [← Finset.card_erase_of_mem + (s := Finset.univ.filter fun r' : Fin n => (r', c) ∈ U ∧ (r', oth c) ∈ U) + (a := r) (by simp [h1, h2])] + congr 1 + ext r' + simp only [Finset.mem_filter, Finset.mem_univ, true_and, Finset.mem_erase, ne_eq, + Prod.mk.injEq, oth_ne, and_false, not_false_eq_true] + tauto + +/-- Removing a square of a full row does not change the singles of its line. -/ +private lemma only_erase_both {U : Finset (Fin n × Fin 2)} {r : Fin n} {c : Fin 2} + (h2 : (r, oth c) ∈ U) : only (U.erase (r, c)) c = only U c := by + unfold only + congr 1 + ext r' + simp only [Finset.mem_filter, Finset.mem_univ, true_and, Finset.mem_erase, ne_eq, + Prod.mk.injEq, oth_ne, and_false, not_false_eq_true, and_true] + constructor + · rintro ⟨⟨_, h⟩, h'⟩; exact ⟨h, h'⟩ + · rintro ⟨h, h'⟩ + refine ⟨⟨?_, h⟩, h'⟩ + rintro rfl; exact h' h2 + +/-- Removing a square of a full row creates a single on the other line. -/ +private lemma only_erase_both_oth {U : Finset (Fin n × Fin 2)} {r : Fin n} {c : Fin 2} + (h1 : (r, c) ∈ U) (h2 : (r, oth c) ∈ U) : + only (U.erase (r, c)) (oth c) = only U (oth c) + 1 := by + unfold only + rw [oth_oth] + rw [← Finset.card_insert_of_notMem + (s := Finset.univ.filter fun r' : Fin n => (r', oth c) ∈ U ∧ (r', c) ∉ U) + (a := r) (by simp [h1])] + congr 1 + ext r' + simp only [Finset.mem_filter, Finset.mem_univ, true_and, Finset.mem_erase, ne_eq, + Prod.mk.injEq, oth_ne, and_false, not_false_eq_true, Finset.mem_insert, and_true] + by_cases hr : r' = r + · subst hr; simp [h2] + · simp [hr] + +/-- Removing a single square does not change the full rows. -/ +private lemma full_erase_single {U : Finset (Fin n × Fin 2)} {r : Fin n} {c : Fin 2} + (h2 : (r, oth c) ∉ U) : full (U.erase (r, c)) c = full U c := by + unfold full + congr 1 + ext r' + simp only [Finset.mem_filter, Finset.mem_univ, true_and, Finset.mem_erase, ne_eq, + Prod.mk.injEq, oth_ne, and_false, not_false_eq_true, and_true] + by_cases hr : r' = r + · subst hr; simp [h2] + · simp [hr] + +/-- Removing a single square. -/ +private lemma only_erase_single {U : Finset (Fin n × Fin 2)} {r : Fin n} {c : Fin 2} + (h1 : (r, c) ∈ U) (h2 : (r, oth c) ∉ U) : only (U.erase (r, c)) c = only U c - 1 := by + unfold only + rw [← Finset.card_erase_of_mem + (s := Finset.univ.filter fun r' : Fin n => (r', c) ∈ U ∧ (r', oth c) ∉ U) + (a := r) (by simp [h1, h2])] + congr 1 + ext r' + simp only [Finset.mem_filter, Finset.mem_univ, true_and, Finset.mem_erase, ne_eq, + Prod.mk.injEq, oth_ne, and_false, not_false_eq_true, and_true] + tauto + +/-- Removing a single square does not change the singles of the other line. -/ +private lemma only_erase_single_oth {U : Finset (Fin n × Fin 2)} {r : Fin n} {c : Fin 2} + (h2 : (r, oth c) ∉ U) : only (U.erase (r, c)) (oth c) = only U (oth c) := by + unfold only + rw [oth_oth] + congr 1 + ext r' + simp only [Finset.mem_filter, Finset.mem_univ, true_and, Finset.mem_erase, ne_eq, + Prod.mk.injEq, oth_ne, and_false, not_false_eq_true, and_true] + by_cases hr : r' = r + · subst hr; simp [h2] + · simp [hr] + + + +/-- Paths from `x` (excluded) through exactly the squares of `U`, ending on line `t`. -/ +private noncomputable def paths (x : Fin n × Fin 2) (U : Finset (Fin n × Fin 2)) (t : Fin 2) : + Finset (List (Fin n × Fin 2)) := + U.toList.permutations.toFinset.filter fun l => (x :: l).IsChain RookMove ∧ (l.getLastD x).2 = t + +/-- Orderings of a finset are exactly the duplicate-free lists with its elements. -/ +private lemma perm_toList_iff {U : Finset (Fin n × Fin 2)} {l : List (Fin n × Fin 2)} : + l.Perm U.toList ↔ l.Nodup ∧ ∀ s, s ∈ l ↔ s ∈ U := by + constructor + · intro h + exact ⟨h.nodup_iff.mpr U.nodup_toList, fun s => by rw [h.mem_iff, Finset.mem_toList]⟩ + · rintro ⟨hl, hs⟩ + exact (List.perm_ext_iff_of_nodup hl U.nodup_toList).mpr fun s => by + rw [hs, Finset.mem_toList] + +/-- Membership in `paths`. -/ +private lemma mem_paths {x : Fin n × Fin 2} {U : Finset (Fin n × Fin 2)} {t : Fin 2} + {l : List (Fin n × Fin 2)} : l ∈ paths x U t ↔ + (l.Nodup ∧ ∀ s, s ∈ l ↔ s ∈ U) ∧ (x :: l).IsChain RookMove ∧ + (l.getLastD x).2 = t := by + rw [paths, Finset.mem_filter, List.mem_toFinset, List.mem_permutations, perm_toList_iff] + +/-- No squares left: only the empty continuation, if we are on the target line. -/ +private lemma card_paths_empty (x : Fin n × Fin 2) (t : Fin 2) : + (paths x ∅ t).card = if x.2 = t then 1 else 0 := by + have : paths x ∅ t = if x.2 = t then {[]} else ∅ := by + ext l + rw [mem_paths] + rcases l with _ | ⟨y, l⟩ + · split_ifs with h <;> simp [h, List.getLastD] + · have : ¬ ((y :: l).Nodup ∧ + ∀ s, s ∈ y :: l ↔ s ∈ (∅ : Finset (Fin n × Fin 2))) := by + rintro ⟨_, h⟩ + simpa using (h y).mp (by simp) + constructor + · rintro ⟨h, _⟩; exact absurd h this + · intro h; split_ifs at h <;> simp at h + rw [this] + split_ifs <;> simp + +/-- Splitting off the first square of an ordering of `U`. -/ +private lemma mem_cons_iff_erase {y : Fin n × Fin 2} {U : Finset (Fin n × Fin 2)} + {l : List (Fin n × Fin 2)} : + ((y :: l).Nodup ∧ ∀ s, s ∈ y :: l ↔ s ∈ U) ↔ + y ∈ U ∧ l.Nodup ∧ ∀ s, s ∈ l ↔ s ∈ U.erase y := by + constructor + · rintro ⟨hn, hs⟩ + rw [List.nodup_cons] at hn + refine ⟨(hs y).mp (by simp), hn.2, fun s => ?_⟩ + rw [Finset.mem_erase, ← hs s, List.mem_cons] + constructor + · intro h; exact ⟨fun e => hn.1 (e ▸ h), Or.inr h⟩ + · rintro ⟨h1, h2 | h2⟩ + · exact absurd h2 h1 + · exact h2 + · rintro ⟨hy, hn, hs⟩ + refine ⟨List.nodup_cons.mpr ⟨fun h => ?_, hn⟩, fun s => ?_⟩ + · exact (Finset.mem_erase.mp ((hs y).mp h)).1 rfl + · rw [List.mem_cons, hs s, Finset.mem_erase] + constructor + · rintro (rfl | ⟨_, h⟩) + · exact hy + · exact h + · intro h + by_cases e : s = y + · exact Or.inl e + · exact Or.inr ⟨e, h⟩ + +/-- First-step decomposition of the paths. -/ +private lemma paths_eq_biUnion {x : Fin n × Fin 2} {U : Finset (Fin n × Fin 2)} {t : Fin 2} + (hU : U.Nonempty) : + paths x U t = (U.filter (RookMove x)).biUnion fun y => + (paths y (U.erase y) t).map ⟨List.cons y, List.cons_injective⟩ := by + ext l + simp only [Finset.mem_biUnion, Finset.mem_filter, Finset.mem_map, Function.Embedding.coeFn_mk] + constructor + · intro hl + rw [mem_paths] at hl + rcases l with _ | ⟨y, l⟩ + · obtain ⟨s, hs⟩ := hU + exact absurd ((hl.1.2 s).mpr hs) (by simp) + · obtain ⟨h1, h2, h3⟩ := hl + rw [mem_cons_iff_erase] at h1 + rw [List.isChain_cons_cons] at h2 + refine ⟨y, ⟨h1.1, h2.1⟩, l, ?_, rfl⟩ + rw [mem_paths] + exact ⟨h1.2, h2.2, by rw [List.getLastD_cons] at h3; exact h3⟩ + · rintro ⟨y, ⟨hy, hxy⟩, l', hl', rfl⟩ + rw [mem_paths] at hl' ⊢ + refine ⟨mem_cons_iff_erase.mpr ⟨hy, hl'.1⟩, + List.isChain_cons_cons.mpr ⟨hxy, hl'.2.1⟩, ?_⟩ + rw [List.getLastD_cons]; exact hl'.2.2 + +/-- First-step recursion for the number of paths. -/ +private lemma card_paths_succ {x : Fin n × Fin 2} {U : Finset (Fin n × Fin 2)} {t : Fin 2} + (hU : U.Nonempty) : + (paths x U t).card = ∑ y ∈ U.filter (RookMove x), (paths y (U.erase y) t).card := by + rw [paths_eq_biUnion hU, Finset.card_biUnion] + · simp + · intro y _ y' _ hne + simp only [Function.onFun] + rw [Finset.disjoint_left] + intro l h1 h2 + simp only [Finset.mem_map, Function.Embedding.coeFn_mk] at h1 h2 + obtain ⟨l1, _, rfl⟩ := h1 + obtain ⟨l2, _, e⟩ := h2 + exact hne (List.cons.inj e).1.symm + + +/-- The predicted number of paths from `x` through `U` ending on line `t`: either the partner of +`x` is kept for later, or (if present) it is the next square. -/ +private def Φ (x : Fin n × Fin 2) (U : Finset (Fin n × Fin 2)) (t : Fin 2) : ℕ := + g (full U x.2) (only U x.2) (only U (oth x.2)) (decide (x.2 = t)) + + if (x.1, oth x.2) ∈ U then + g (full U x.2) (only U (oth x.2) - 1) (only U x.2) (!decide (x.2 = t)) else 0 + +/-- The base values of `g`. -/ +private lemma g_zero (s : Bool) : g 0 0 0 s = if s then 1 else 0 := by + cases s <;> simp [g, G] + +/-- `Φ` after stepping to a square of a full row of the current line. -/ +private lemma Φ_both {U : Finset (Fin n × Fin 2)} {r : Fin n} {c t : Fin 2} + (h1 : (r, c) ∈ U) (h2 : (r, oth c) ∈ U) : + Φ (r, c) (U.erase (r, c)) t = + g (full U c - 1) (only U c) (only U (oth c) + 1) (decide (c = t)) + + g (full U c - 1) (only U (oth c)) (only U c) (!decide (c = t)) := by + unfold Φ + have hm : (r, oth c) ∈ U.erase (r, c) := + Finset.mem_erase.mpr ⟨by simp [oth_ne], h2⟩ + simp only + rw [full_erase_both h1 h2, only_erase_both h2, only_erase_both_oth h1 h2, if_pos hm, + Nat.add_sub_cancel] + +/-- `Φ` after stepping to a single square of the current line. -/ +private lemma Φ_single {U : Finset (Fin n × Fin 2)} {r : Fin n} {c t : Fin 2} + (h1 : (r, c) ∈ U) (h2 : (r, oth c) ∉ U) : + Φ (r, c) (U.erase (r, c)) t = + g (full U c) (only U c - 1) (only U (oth c)) (decide (c = t)) := by + unfold Φ + have hm : (r, oth c) ∉ U.erase (r, c) := fun h => h2 (Finset.mem_of_mem_erase h) + simp only + rw [full_erase_single h2, only_erase_single h1 h2, only_erase_single_oth h2, if_neg hm, + add_zero] + +/-- `Φ` after stepping to the other square of the current row. -/ +private lemma Φ_partner {U : Finset (Fin n × Fin 2)} {r : Fin n} {c t : Fin 2} + (hx : (r, c) ∉ U) (h : (r, oth c) ∈ U) : + Φ (r, oth c) (U.erase (r, oth c)) t = + g (full U c) (only U (oth c) - 1) (only U c) (!decide (c = t)) := by + unfold Φ + have hx' : (r, oth (oth c)) ∉ U := by rw [oth_oth]; exact hx + have hm : (r, oth (oth c)) ∉ U.erase (r, oth c) := fun h' => hx' (Finset.mem_of_mem_erase h') + simp only + rw [full_erase_single hx', only_erase_single h hx', only_erase_single_oth hx', if_neg hm, + add_zero, full_oth, oth_oth, decide_oth] + +/-- Squares of the current line whose partner is present correspond to full rows. -/ +private lemma card_full_rows (U : Finset (Fin n × Fin 2)) (c : Fin 2) : + ((U.filter fun y => y.2 = c).filter fun y => (y.1, oth c) ∈ U).card = full U c := by + unfold full + apply Finset.card_nbij' Prod.fst (fun r => (r, c)) + · intro y hy + simp only [Finset.coe_filter, Set.mem_ofPred_eq, Finset.mem_filter, Finset.mem_univ, + true_and] at hy ⊢ + obtain ⟨⟨h1, h2⟩, h3⟩ := hy + exact ⟨by rw [← h2]; exact h1, h3⟩ + · intro r hr + simp only [Finset.coe_filter, Set.mem_ofPred_eq, Finset.mem_filter, Finset.mem_univ, + true_and] at hr ⊢ + exact ⟨⟨hr.1, by simp⟩, hr.2⟩ + · intro y hy + simp only [Finset.coe_filter, Set.mem_ofPred_eq, Finset.mem_filter] at hy + obtain ⟨r, d⟩ := y + simp only at hy ⊢ + rw [hy.1.2] + · intro r _ + rfl + +/-- Squares of the current line whose partner is absent correspond to singles. -/ +private lemma card_only_rows (U : Finset (Fin n × Fin 2)) (c : Fin 2) : + ((U.filter fun y => y.2 = c).filter fun y => ¬ (y.1, oth c) ∈ U).card = only U c := by + unfold only + apply Finset.card_nbij' Prod.fst (fun r => (r, c)) + · intro y hy + simp only [Finset.coe_filter, Set.mem_ofPred_eq, Finset.mem_filter, Finset.mem_univ, + true_and] at hy ⊢ + obtain ⟨⟨h1, h2⟩, h3⟩ := hy + exact ⟨by rw [← h2]; exact h1, h3⟩ + · intro r hr + simp only [Finset.coe_filter, Set.mem_ofPred_eq, Finset.mem_filter, Finset.mem_univ, + true_and] at hr ⊢ + exact ⟨⟨hr.1, by simp⟩, hr.2⟩ + · intro y hy + simp only [Finset.coe_filter, Set.mem_ofPred_eq, Finset.mem_filter] at hy + obtain ⟨r, d⟩ := y + simp only at hy ⊢ + rw [hy.1.2] + · intro r _ + rfl + +/-- Main counting lemma: the number of paths from `x` through `U` ending on line `t` is +`Φ x U t`, by induction on `#U`. -/ +private theorem card_paths (k : ℕ) : + ∀ (U : Finset (Fin n × Fin 2)) (x : Fin n × Fin 2) (t : Fin 2), + U.card = k → x ∉ U → (paths x U t).card = Φ x U t := by + induction k with + | zero => + intro U x t hU _ + rw [Finset.card_eq_zero] at hU + subst hU + rw [card_paths_empty] + simp [Φ, full, only, g_zero] + | succ k ih => + intro U x t hU hx + have hne : U.Nonempty := by rw [← Finset.card_pos, hU]; omega + rw [card_paths_succ hne] + rw [Finset.sum_congr rfl (fun y hy => ih (U.erase y) y t + (by rw [Finset.card_erase_of_mem (Finset.mem_filter.mp hy).1, hU]; rfl) + (Finset.notMem_erase y U))] + obtain ⟨r, c⟩ := x + rw [← Finset.sum_filter_add_sum_filter_not _ (fun y => y.2 = c)] + have hsame : (U.filter (RookMove (r, c))).filter (fun y => y.2 = c) = + U.filter (fun y => y.2 = c) := by + ext ⟨r', d⟩ + simp only [Finset.mem_filter, RookMove] + constructor + · rintro ⟨⟨h1, _⟩, h3⟩; exact ⟨h1, h3⟩ + · rintro ⟨h1, h3⟩ + refine ⟨⟨h1, ?_, Or.inr h3.symm⟩, h3⟩ + rintro e; rw [e] at hx; exact hx h1 + have hpart : ∑ y ∈ (U.filter (RookMove (r, c))).filter (fun y => ¬ y.2 = c), + Φ y (U.erase y) t = + if (r, oth c) ∈ U then g (full U c) (only U (oth c) - 1) (only U c) (!decide (c = t)) + else 0 := by + have hset : (U.filter (RookMove (r, c))).filter (fun y => ¬ y.2 = c) = + U.filter (fun y => y = (r, oth c)) := by + ext ⟨r', d⟩ + simp only [Finset.mem_filter, RookMove, Prod.mk.injEq] + constructor + · rintro ⟨⟨h1, _, h2⟩, h3⟩ + refine ⟨h1, ?_, ?_⟩ + · rcases h2 with h2 | h2 + · exact h2.symm + · exact absurd h2.symm h3 + · rcases eq_or_eq_oth c d with h | h + · exact absurd h h3 + · exact h + · rintro ⟨h1, rfl, rfl⟩ + exact ⟨⟨h1, by simp [ne_oth], Or.inl rfl⟩, oth_ne c⟩ + rw [hset, Finset.filter_eq' U (r, oth c)] + split_ifs with h + · rw [Finset.sum_singleton, Φ_partner hx h] + · rw [Finset.sum_empty] + have hsum : ∑ y ∈ U.filter (fun y => y.2 = c), Φ y (U.erase y) t = + full U c * (g (full U c - 1) (only U c) (only U (oth c) + 1) (decide (c = t)) + + g (full U c - 1) (only U (oth c)) (only U c) (!decide (c = t))) + + only U c * g (full U c) (only U c - 1) (only U (oth c)) (decide (c = t)) := by + rw [← Finset.sum_filter_add_sum_filter_not _ (fun y => (y.1, oth c) ∈ U)] + have e1 : ∀ y ∈ (U.filter (fun y => y.2 = c)).filter (fun y => (y.1, oth c) ∈ U), + Φ y (U.erase y) t = + g (full U c - 1) (only U c) (only U (oth c) + 1) (decide (c = t)) + + g (full U c - 1) (only U (oth c)) (only U c) (!decide (c = t)) := by + rintro ⟨r', d⟩ hy + simp only [Finset.mem_filter] at hy + obtain ⟨⟨h1, h2⟩, h3⟩ := hy + subst h2 + exact Φ_both h1 h3 + have e2 : ∀ y ∈ (U.filter (fun y => y.2 = c)).filter (fun y => ¬ (y.1, oth c) ∈ U), + Φ y (U.erase y) t = g (full U c) (only U c - 1) (only U (oth c)) (decide (c = t)) := by + rintro ⟨r', d⟩ hy + simp only [Finset.mem_filter] at hy + obtain ⟨⟨h1, h2⟩, h3⟩ := hy + subst h2 + exact Φ_single h1 h3 + rw [Finset.sum_congr rfl e1, Finset.sum_congr rfl e2] + rw [Finset.sum_const, Finset.sum_const, card_full_rows, card_only_rows, smul_eq_mul, + smul_eq_mul] + rw [hsame, hsum, hpart] + have hbase : + ¬ (full U c = 0 ∧ only U c = 0 ∧ only U (oth c) = 0 ∧ decide (c = t) = true) := by + rintro ⟨hF, hA, hB, _⟩ + obtain ⟨⟨r', d⟩, hy⟩ := hne + unfold full at hF + unfold only at hA hB + rw [Finset.card_eq_zero, Finset.filter_eq_empty_iff] at hF hA hB + rcases eq_or_eq_oth c d with rfl | rfl + · by_cases h : (r', oth d) ∈ U + · exact hF (Finset.mem_univ r') ⟨hy, h⟩ + · exact hA (Finset.mem_univ r') ⟨hy, h⟩ + · by_cases h : (r', c) ∈ U + · exact hF (Finset.mem_univ r') ⟨h, hy⟩ + · exact hB (Finset.mem_univ r') ⟨hy, by rw [oth_oth]; exact h⟩ + unfold Φ + simp only + rw [g_rec (full U c) (only U c) (only U (oth c)) (decide (c = t)), if_neg hbase] + ring + +/-- The count from a fixed starting square of the full board. -/ +private lemma Φ_init (m : ℕ) (x : Fin (m + 1) × Fin 2) : + Φ x (Finset.univ.erase x) (oth x.2) = m ! * a (m + 1) := by + obtain ⟨r, c⟩ := x + unfold Φ + simp only + have hF : full (Finset.univ.erase (r, c)) c = m := by + unfold full + rw [show (Finset.univ.filter fun r' : Fin (m + 1) => (r', c) ∈ Finset.univ.erase (r, c) ∧ + (r', oth c) ∈ Finset.univ.erase (r, c)) = Finset.univ.erase r by + ext r' + simp [Finset.mem_erase, oth_ne]] + rw [Finset.card_erase_of_mem (Finset.mem_univ r), Finset.card_univ, Fintype.card_fin] + rfl + have hA : only (Finset.univ.erase (r, c)) c = 0 := by + unfold only + rw [Finset.card_eq_zero, Finset.filter_eq_empty_iff] + rintro r' _ ⟨_, h⟩ + exact h (Finset.mem_erase.mpr ⟨by simp [oth_ne], Finset.mem_univ _⟩) + have hB : only (Finset.univ.erase (r, c)) (oth c) = 1 := by + unfold only + rw [Finset.card_eq_one] + refine ⟨r, ?_⟩ + ext r' + simp [Finset.mem_erase, oth_oth, oth_ne] + have hm : (r, oth c) ∈ Finset.univ.erase (r, c) := + Finset.mem_erase.mpr ⟨by simp [oth_ne], Finset.mem_univ _⟩ + rw [hF, hA, hB, if_pos hm] + have : decide (c = oth c) = false := by simp [ne_oth] + rw [this] + simp only [Bool.not_false, Nat.sub_self] + rw [E_sum, S_eq] + +/-- Kurkov's conjecture holds: for `n ≥ 1` the number of open rook tours of the `n × 2` board +ending on the opposite line is `2 · n! · a(n)`. -/ +theorem result : statement := by + intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩ + rw [ncard_eq_card_tours] + have htours : tours (m + 1) = Finset.univ.biUnion fun x => + (paths x (Finset.univ.erase x) (oth x.2)).map ⟨List.cons x, List.cons_injective⟩ := by + ext l + rw [mem_tours] + simp only [Finset.mem_biUnion, Finset.mem_univ, true_and, Finset.mem_map, + Function.Embedding.coeFn_mk] + constructor + · rintro ⟨⟨hnd, hall, hch⟩, hend⟩ + obtain ⟨s, hs, u, hu, hsu⟩ := hend + rcases l with _ | ⟨x, l'⟩ + · simp at hs + · refine ⟨x, l', ?_, rfl⟩ + rw [mem_paths] + have h1 := mem_cons_iff_erase.mp + ⟨hnd, fun s => ⟨fun _ => Finset.mem_univ s, fun _ => hall s⟩⟩ + refine ⟨h1.2, hch, ?_⟩ + simp only [List.head?_cons, Option.mem_def, Option.some.injEq] at hs + rw [List.getLast?_cons, Option.mem_def, Option.some.injEq] at hu + subst hs + rw [List.getLastD_eq_getLast?, hu] + rcases eq_or_eq_oth x.2 u.2 with h | h + · exact absurd h.symm hsu + · exact h + · rintro ⟨x, l', hl', rfl⟩ + rw [mem_paths] at hl' + obtain ⟨⟨hnd, hmem⟩, hch, hlast⟩ := hl' + have h1 := mem_cons_iff_erase.mpr ⟨Finset.mem_univ x, hnd, hmem⟩ + refine ⟨⟨h1.1, fun s => (h1.2 s).mpr (Finset.mem_univ s), hch⟩, ?_⟩ + refine ⟨x, by simp, l'.getLastD x, ?_, ?_⟩ + · rw [List.getLast?_cons, List.getLastD_eq_getLast?]; rfl + · rw [hlast]; exact ne_oth x.2 + rw [htours, Finset.card_biUnion] + · simp only [Finset.card_map] + rw [Finset.sum_congr rfl (fun x _ => card_paths _ _ x _ rfl (Finset.notMem_erase x _))] + rw [Finset.sum_congr rfl (fun x _ => Φ_init m x)] + rw [Finset.sum_const, Finset.card_univ, Fintype.card_prod, Fintype.card_fin, + Fintype.card_fin, smul_eq_mul, Nat.factorial_succ] + ring + · intro y _ y' _ hne + simp only [Function.onFun] + rw [Finset.disjoint_left] + intro l h1 h2 + simp only [Finset.mem_map, Function.Embedding.coeFn_mk] at h1 h2 + obtain ⟨l1, _, rfl⟩ := h1 + obtain ⟨l2, _, e⟩ := h2 + exact hne (List.cons.inj e).1.symm + +end Math0.Frontier.A001040 + +#math0_settles Math0.Frontier.A001040.result Math0.Statements.A001040.statement diff --git a/lean/Math0/Frontier/OEIS/A005590.lean b/lean/Math0/Frontier/OEIS/A005590.lean new file mode 100644 index 0000000..151c667 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A005590.lean @@ -0,0 +1,175 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A005590 +import Math0.Audit + +/-! +# Zeros of `a(3n)` for the signed Stern sequence A005590 are the fibbinary numbers + +We prove Ralf Stephan's conjecture: `a(3n) = 0 ↔ n` is fibbinary (no two adjacent 1 bits). + +**Automaton.** Put `v(m) = (a(m), a(m+1))`. Then `v(2m) = (x, y - x)` and +`v(2m+1) = (y - x, y)` where `(x, y) = v(m)`. Reading the bits of `m` from the most significant +one, starting at `v(0) = (0, 1)`, define a three-state automaton `st`: +state `0` (`v = (0,1)`), state `1` (`v = (1,1)`), state `2` (an absorbing "dead" state). +Transitions: bit `0` maps `0 ↦ 0`, `1 ↦ 2`, `2 ↦ 2`; bit `1` maps `0 ↦ 1`, `1 ↦ 0`, `2 ↦ 2`. +In the dead state `v = (x, y)` satisfies `P(x,y) : (0 < x ∧ y < x) ∨ (x < 0 ∧ x < y)`; this is +preserved by both linear maps, `(1,0)` satisfies it, and it forces `x ≠ 0`. Hence +`a(m) = 0 ↔ st(m) = 0`. + +**Multiples of three.** `3·(2k) = 2·(3k)`, `3·(4k+1) = 2·(2·(3k)+1)+1` and +`3·(4k+3) = 2·(2·(3k+2))+1`. So `st(6k) = 0 ↔ st(3k) = 0`, `st(12k+3) = 0 ↔ st(3k) = 0`, and +`st(12k+9) ≠ 0` always. The fibbinary property satisfies the same recursion: +`fib(2k) ↔ fib(k)`, `fib(4k+1) ↔ fib(k)`, `¬ fib(4k+3)`. Strong induction finishes. +-/ + +namespace Math0.Frontier.A005590 +open Math0.Statements.A005590 + +/-- The automaton state of `m`, read from the most significant bit (values `0`, `1`, `2`). -/ +private def st : ℕ → ℕ + | 0 => 0 + | n + 1 => + if (n + 1) % 2 = 0 then (if st ((n + 1) / 2) = 0 then 0 else 2) + else (if st ((n + 1) / 2) = 0 then 1 else if st ((n + 1) / 2) = 1 then 0 else 2) + decreasing_by all_goals omega + +/-- `st 0 = 0`. -/ +private lemma st_zero : st 0 = 0 := by rw [st] + +/-- Transition on bit `0`. -/ +private lemma st_even (k : ℕ) : st (2 * k) = if st k = 0 then 0 else 2 := by + rcases Nat.eq_zero_or_pos k with rfl | hk + · simp [st_zero] + · obtain ⟨j, rfl⟩ : ∃ j, k = j + 1 := ⟨k - 1, by omega⟩ + have e : 2 * (j + 1) = (2 * j + 1) + 1 := by ring + rw [e, st] + have h1 : (2 * j + 1 + 1) % 2 = 0 := by omega + have h2 : (2 * j + 1 + 1) / 2 = j + 1 := by omega + rw [if_pos h1, h2] + +/-- Transition on bit `1`. -/ +private lemma st_odd (k : ℕ) : + st (2 * k + 1) = if st k = 0 then 1 else if st k = 1 then 0 else 2 := by + rw [st] + have h1 : ¬ (2 * k + 1) % 2 = 0 := by omega + have h2 : (2 * k + 1) / 2 = k := by omega + rw [if_neg h1, h2] + +/-- The invariant linking the automaton state of `m` with `(a m, a (m+1))`. -/ +private def Inv (m : ℕ) : Prop := + (st m = 0 ∧ a m = 0 ∧ a (m + 1) = 1) ∨ (st m = 1 ∧ a m = 1 ∧ a (m + 1) = 1) ∨ + (st m = 2 ∧ ((0 < a m ∧ a (m + 1) < a m) ∨ (a m < 0 ∧ a m < a (m + 1)))) + +/-- The invariant holds for every `m`. -/ +private lemma inv_all (m : ℕ) : Inv m := by + induction m using Nat.strong_induction_on with + | _ m ih => + obtain ⟨k, rfl | rfl⟩ := Nat.even_or_odd' m + · rcases Nat.eq_zero_or_pos k with rfl | hk + · left + exact ⟨st_zero, a_zero, a_one⟩ + · have IH := ih k (by omega) + unfold Inv at IH ⊢ + rw [st_even, a_even, a_odd] + rcases IH with ⟨h0, h1, h2⟩ | ⟨h0, h1, h2⟩ | ⟨h0, h1⟩ + · left; rw [h0, h1, h2]; simp + · right; right; rw [h0, h1, h2]; simp + · right; right; rw [h0]; simp; omega + · have IH := ih k (by omega) + unfold Inv at IH ⊢ + have e : 2 * k + 1 + 1 = 2 * (k + 1) := by ring + rw [st_odd, a_odd, e, a_even] + rcases IH with ⟨h0, h1, h2⟩ | ⟨h0, h1, h2⟩ | ⟨h0, h1⟩ + · right; left; rw [h0, h1, h2]; simp + · left; rw [h0, h1, h2]; simp + · right; right; rw [h0]; simp; omega + +/-- `a m = 0` exactly when the automaton is in state `0`. -/ +private lemma a_eq_zero_iff (m : ℕ) : a m = 0 ↔ st m = 0 := by + rcases inv_all m with ⟨h0, h1, _⟩ | ⟨h0, h1, _⟩ | ⟨h0, h1⟩ + · simp [h0, h1] + · simp [h0, h1] + · rw [h0]; constructor + · intro h; omega + · intro h; omega + +/-- The state is always at most `2`. -/ +private lemma st_le (m : ℕ) : st m ≤ 2 := by + rcases inv_all m with ⟨h0, _⟩ | ⟨h0, _⟩ | ⟨h0, _⟩ <;> omega + +/-- One step of the fibbinary recursion: look at the two lowest bits, then drop one bit. -/ +private lemma fib_iff (n : ℕ) : + IsFibbinary n ↔ ¬ (n % 2 = 1 ∧ (n / 2) % 2 = 1) ∧ IsFibbinary (n / 2) := by + unfold IsFibbinary + constructor + · intro h + refine ⟨?_, ?_⟩ + · intro ⟨h1, h2⟩ + apply h 0 + rw [Nat.testBit_zero, Nat.testBit_succ, Nat.testBit_zero] + simp [h1, h2] + · intro i + rw [← Nat.testBit_succ, ← Nat.testBit_succ] + exact h (i + 1) + · intro ⟨h1, h2⟩ i + cases i with + | zero => + rw [Nat.testBit_zero, Nat.testBit_succ, Nat.testBit_zero] + simp only [decide_eq_true_eq] + exact h1 + | succ i => + rw [Nat.testBit_succ, Nat.testBit_succ] + exact h2 i + +/-- `0` is fibbinary. -/ +private lemma fib_zero : IsFibbinary 0 := by + intro i; simp + +/-- The state of `3n` is `0` exactly when `n` is fibbinary. -/ +private lemma st_three_mul (n : ℕ) : st (3 * n) = 0 ↔ IsFibbinary n := by + induction n using Nat.strong_induction_on with + | _ n ih => + rcases Nat.eq_zero_or_pos n with rfl | hn + · simp [st_zero, fib_zero] + · have hmod : n % 2 = 0 ∨ n % 4 = 1 ∨ n % 4 = 3 := by omega + rcases hmod with h | h | h + · -- n = 2k + obtain ⟨k, rfl⟩ : ∃ k, n = 2 * k := ⟨n / 2, by omega⟩ + have e : 3 * (2 * k) = 2 * (3 * k) := by ring + have h3 : (2 * k) / 2 = k := by omega + rw [e, st_even, fib_iff, h3, ← ih k (by omega)] + constructor + · intro hs + refine ⟨by omega, ?_⟩ + by_contra hc; rw [if_neg hc] at hs; omega + · intro ⟨_, hs⟩; rw [if_pos hs] + · -- n = 4k + 1 + obtain ⟨k, rfl⟩ : ∃ k, n = 4 * k + 1 := ⟨n / 4, by omega⟩ + have e : 3 * (4 * k + 1) = 2 * (2 * (3 * k) + 1) + 1 := by ring + have h3 : (4 * k + 1) / 2 / 2 = k := by omega + rw [e, st_odd, st_odd, fib_iff, fib_iff (_ / 2), h3, ← ih k (by omega)] + have hl := st_le (3 * k) + have h4 : (4 * k + 1) / 2 % 2 = 0 := by omega + rw [h4] + rcases (show st (3 * k) = 0 ∨ st (3 * k) = 1 ∨ st (3 * k) = 2 by omega) with + hs | hs | hs <;> simp [hs] + · -- n = 4k + 3 + obtain ⟨k, rfl⟩ : ∃ k, n = 4 * k + 3 := ⟨n / 4, by omega⟩ + have e : 3 * (4 * k + 3) = 2 * (2 * (3 * k + 2)) + 1 := by ring + rw [e, st_odd, st_even, fib_iff] + have h3 : (4 * k + 3) % 2 = 1 := by omega + have h4 : (4 * k + 3) / 2 % 2 = 1 := by omega + rw [h3, h4] + rcases (show st (3 * k + 2) = 0 ∨ st (3 * k + 2) ≠ 0 by omega) with hs | hs <;> + simp [hs] + +/-- Stephan's conjecture: `a(3n) = 0` iff `n` is fibbinary. -/ +theorem result : statement := by + intro n + rw [a_eq_zero_iff, st_three_mul] + +end Math0.Frontier.A005590 + +#math0_settles Math0.Frontier.A005590.result Math0.Statements.A005590.statement diff --git a/lean/Math0/Frontier/OEIS/A022445.lean b/lean/Math0/Frontier/OEIS/A022445.lean new file mode 100644 index 0000000..a75b368 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A022445.lean @@ -0,0 +1,1651 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A022445 +import Math0.Audit + +/-! +# The generating function of A022445 (closed self-avoiding walks in the strip `{0,1,2} × ℤ`) + +We prove Ralf Stephan's conjecture +`∑ a(n) xⁿ = (1 - 4x + 10x² - 14x³ + 27x⁴ - 18x⁵ + 10x⁶ - 6x⁷) / ((1 + x²)² (1 - 2x)²)`. + +**Walks as lists.** `a n` (`n ≠ 1`) counts the lists of vertices `0, w₁, …, w_{2n-1}, 0` of +closed walks in the strip whose inner vertices are distinct and differ from `0` (`a_eq_GLs`). +Dropping the final `0`, these are the self-avoiding walks of `2n - 1` steps from the origin to one +of its three neighbours `(1, 0)`, `(0, 1)`, `(0, -1)` (`GLs_Q`). + +**Cuts.** A self-avoiding walk in the strip crosses a horizontal cut (between two adjacent rows) +along vertical edges in distinct columns. If it starts on one side and ends on the other, it +crosses only once as soon as one of the three columns is unavailable (`once`); if it starts and +ends on the same side, it leaves that side at most once (`conv`). + +**Excursions.** An *excursion* (`exc σ r S c₁ c₂ ℓ`) is a self-avoiding walk of `ℓ` steps in the +half-strip on side `σ` of row `r`, from column `c₁` to column `c₂` of row `r`, avoiding the +columns `S` of row `r`. By `conv`, it is either a straight horizontal segment, or a segment in +row `r`, an excursion from the next row, and a segment in row `r` (`exc_decomp`). Hence the +numbers of excursions satisfy a finite linear recursion (`exc_card`): their number is `Ef c₁ c₂ ℓ`, +with `p ℓ` excursions between adjacent columns and `q ℓ` between columns `0` and `2`, where +`p (ℓ + 3) = p (ℓ + 1) + q ℓ`, `q (ℓ + 3) = 2 p ℓ + q (ℓ + 1)`. + +**Decomposition.** By `once`, a walk from `0` to `(0, ±1)` is an excursion from `0` on the side +of row `0` away from `(0, ±1)`, followed by an excursion beyond row `±1` (`Q1_card`). A walk from +`0` to `(1, 0)` first steps to `(0, ±1)`, makes an excursion beyond row `±1`, and ends with an +excursion on the other side of row `0` that avoids the origin (`Q10_card`). + +**Generating functions.** `p` lives on odd and `q` on even lengths; with +`P(x) = ∑ p(2m+1) xᵐ`, `Q(x) = ∑ q(2m) xᵐ` one has `P = 1 + x (P + Q)`, `Q = x (1 + Q + 2xP)`, +so `(1 - 2x)(1 + x²) P = 1 - x + x²` and `(1 - 2x)(1 + x²) Q = x + x²`. The decomposition gives +`∑ a(n) xⁿ = 1 + 2 (x² P² + x Q² + x² P + x² Q + x³ P Q)` (`a_formula`), and clearing +denominators yields the claimed identity (`gf_main`). +-/ + +namespace Math0.Frontier.A022445 +open Math0.Statements.A022445 + +/-- Adjacency in the square lattice: `v` is one unit step from `u`. -/ +private def Adj (u v : ℤ × ℤ) : Prop := ∃ d : Fin 4, v = u + step d + +/-- Coordinates of adjacent vertices. -/ +private lemma adj_iff {u v : ℤ × ℤ} : Adj u v ↔ + (v.1 = u.1 + 1 ∧ v.2 = u.2) ∨ (v.1 = u.1 - 1 ∧ v.2 = u.2) ∨ + (v.1 = u.1 ∧ v.2 = u.2 + 1) ∨ (v.1 = u.1 ∧ v.2 = u.2 - 1) := by + constructor + · rintro ⟨d, rfl⟩ + fin_cases d <;> simp [step] <;> omega + · rintro (⟨h1, h2⟩ | ⟨h1, h2⟩ | ⟨h1, h2⟩ | ⟨h1, h2⟩) + · exact ⟨0, Prod.ext (by simp [step, h1]) (by simp [step, h2])⟩ + · exact ⟨1, Prod.ext (by simp [step, h1]; ring) (by simp [step, h2])⟩ + · exact ⟨2, Prod.ext (by simp [step, h1]) (by simp [step, h2])⟩ + · exact ⟨3, Prod.ext (by simp [step, h1]) (by simp [step, h2]; ring)⟩ + +/-- Adjacency is symmetric. -/ +private lemma adj_symm {u v : ℤ × ℤ} (h : Adj u v) : Adj v u := by + rw [adj_iff] at h ⊢; omega + +/-- All walks of `k` steps from `p`, as lists of their `k + 1` vertices. -/ +private def walksFrom : ℤ × ℤ → ℕ → Finset (List (ℤ × ℤ)) + | p, 0 => {[p]} + | p, k + 1 => Finset.univ.biUnion fun d : Fin 4 => (walksFrom (p + step d) k).image (List.cons p) + +/-- Membership in `walksFrom`. -/ +private lemma mem_walksFrom {k : ℕ} {p : ℤ × ℤ} {l : List (ℤ × ℤ)} : + l ∈ walksFrom p k ↔ l.length = k + 1 ∧ l.head? = some p ∧ l.IsChain Adj := by + induction k generalizing p l with + | zero => + simp only [walksFrom, Finset.mem_singleton, zero_add] + constructor + · rintro rfl; simp + · rintro ⟨hl, hh, -⟩ + obtain ⟨a, rfl⟩ := List.length_eq_one_iff.1 hl + simp at hh; rw [hh] + | succ k ih => + simp only [walksFrom, Finset.mem_biUnion, Finset.mem_univ, true_and, Finset.mem_image, ih] + constructor + · rintro ⟨d, l', ⟨hlen, hhead, hc⟩, rfl⟩ + refine ⟨by simp [hlen], rfl, hc.cons fun y hy => ⟨d, ?_⟩⟩ + rw [hhead] at hy; cases hy; rfl + · rintro ⟨hlen, hhead, hc⟩ + match l, hlen, hhead, hc with + | a :: b :: l'', hlen, hhead, hc => + simp only [List.head?_cons, Option.some.injEq] at hhead + subst hhead + obtain ⟨d, hd⟩ := (List.isChain_cons_cons.1 hc).1 + exact ⟨d, b :: l'', ⟨by simpa using hlen, by simp [hd], (List.isChain_cons_cons.1 hc).2⟩, + rfl⟩ + +/-- List version of `Ext`: the walk `W` (its vertex list, starting at `p`) has its vertices +`1, …, k` in the strip, ends at `0`, and its vertices `1, …, k - 1` are distinct and not in +`vis`. -/ +private def ExtL (vis : List (ℤ × ℤ)) (W : List (ℤ × ℤ)) : Prop := + (∀ v ∈ W.tail, InStrip v) ∧ W.getLast? = some 0 ∧ (∀ v ∈ W.tail.dropLast, v ∉ vis) ∧ + W.tail.dropLast.Nodup + +/-- Decidability of `ExtL`. -/ +private instance (vis : List (ℤ × ℤ)) : DecidablePred (ExtL vis) := fun W => by + unfold ExtL; infer_instance + +/-- List version of `G`. -/ +private def GLs (vis : List (ℤ × ℤ)) (p : ℤ × ℤ) (k : ℕ) : ℕ := + ((walksFrom p k).filter (ExtL vis)).card + +/-- `GLs` with no steps left. -/ +private lemma GLs_zero (vis : List (ℤ × ℤ)) (p : ℤ × ℤ) : GLs vis p 0 = if p = 0 then 1 else 0 := by + unfold GLs + rw [walksFrom, Finset.filter_singleton] + by_cases hp : p = 0 <;> simp [ExtL, hp] + +/-- Unfolding `ExtL` by one step. -/ +private lemma extL_cons (vis : List (ℤ × ℤ)) (p q : ℤ × ℤ) (R : List (ℤ × ℤ)) : + ExtL vis (p :: q :: R) ↔ + InStrip q ∧ (R.length ≠ 0 → q ∉ vis) ∧ ExtL (q :: vis) (q :: R) := by + cases R with + | nil => simp [ExtL] + | cons r R => + simp only [ExtL, List.tail_cons, List.mem_cons, List.getLast?_cons_cons, + List.dropLast_cons_cons, List.nodup_cons, List.length_cons, ne_eq, Nat.add_one_ne_zero, + not_false_eq_true, forall_const, forall_eq_or_imp, not_or] + constructor + · rintro ⟨⟨h1, h2⟩, h3, ⟨h4, h5⟩, h6, h7⟩ + exact ⟨h1, h4, h2, h3, fun v hv => ⟨fun e => h6 (e ▸ hv), h5 v hv⟩, h7⟩ + · rintro ⟨h1, h4, h2, h3, h5, h7⟩ + exact ⟨⟨h1, h2⟩, h3, ⟨h4, fun v hv => (h5 v hv).2⟩, fun hm => (h5 q hm).1 rfl, h7⟩ + +/-- The four unit steps are distinct. -/ +private lemma step_inj {d d' : Fin 4} (h : step d = step d') : d = d' := by + fin_cases d <;> fin_cases d' <;> simp_all [step] + +/-- `GLs` satisfies the same one-step recursion as `G`. -/ +private lemma GLs_succ (vis : List (ℤ × ℤ)) (p : ℤ × ℤ) (k : ℕ) : + GLs vis p (k + 1) = ∑ d : Fin 4, + if InStrip (p + step d) ∧ (k ≠ 0 → p + step d ∉ vis) then + GLs ((p + step d) :: vis) (p + step d) k else 0 := by + unfold GLs + rw [walksFrom, Finset.filter_biUnion, Finset.card_biUnion] + · refine Finset.sum_congr rfl fun d _ => ?_ + rw [Finset.filter_image, Finset.card_image_of_injective _ List.cons_injective] + split_ifs with h + · congr 1 + apply Finset.filter_congr + intro W hW + obtain ⟨hlen, hhead, -⟩ := mem_walksFrom.1 hW + match W, hlen, hhead with + | q :: R, hlen, hhead => + simp only [List.head?_cons, Option.some.injEq] at hhead + subst hhead + simp only [List.length_cons, add_left_inj] at hlen + rw [extL_cons, hlen] + exact ⟨fun h' => h'.2.2, fun h' => ⟨h.1, h.2, h'⟩⟩ + · rw [Finset.card_eq_zero, Finset.filter_eq_empty_iff] + intro W hW hE + obtain ⟨hlen, hhead, -⟩ := mem_walksFrom.1 hW + match W, hlen, hhead with + | q :: R, hlen, hhead => + simp only [List.head?_cons, Option.some.injEq] at hhead + subst hhead + simp only [List.length_cons, add_left_inj] at hlen + rw [extL_cons, hlen] at hE + exact h ⟨hE.1, hE.2.1⟩ + · intro d _ d' _ hdd' + simp only [Function.onFun] + rw [Finset.disjoint_left] + intro l h1 h2 + simp only [Finset.mem_filter, Finset.mem_image] at h1 h2 + obtain ⟨⟨W, hW, rfl⟩, -⟩ := h1 + obtain ⟨⟨W', hW', hWW⟩, -⟩ := h2 + obtain ⟨-, h1, -⟩ := mem_walksFrom.1 hW + obtain ⟨-, h2, -⟩ := mem_walksFrom.1 hW' + have : W' = W := List.cons_injective hWW + subst this + rw [h1, Option.some.injEq] at h2 + exact hdd' (step_inj (add_left_cancel h2)) + +/-- `G` agrees with its list version `GLs`. -/ +private lemma G_eq_GLs (k : ℕ) : ∀ (vis : List (ℤ × ℤ)) (p : ℤ × ℤ), G vis p k = GLs vis p k := by + induction k with + | zero => intro vis p; rw [G_zero, GLs_zero] + | succ k ih => intro vis p; rw [G_succ, GLs_succ]; simp only [ih] + +/-- `a n` counts lists of vertices (`n ≠ 1`). -/ +private lemma a_eq_GLs (n : ℕ) (hn : n ≠ 1) : a n = GLs [0] 0 (2 * n) := by + rw [a_eq_G n hn, G_eq_GLs] + + +/-! ### Crossing a horizontal cut -/ + +/-- Elements of the two parts of a duplicate-free concatenation differ. -/ +private lemma nodup_ne {L1 L2 : List (ℤ × ℤ)} (hn : (L1 ++ L2).Nodup) {a b : ℤ × ℤ} + (ha : a ∈ L1) (hb : b ∈ L2) : a ≠ b := + (List.nodup_append.1 hn).2.2 a ha b hb + +/-- The last vertex of the first part of a walk is adjacent to the first vertex of the second. -/ +private lemma adj_junction {L1 L2 : List (ℤ × ℤ)} (hc : (L1 ++ L2).IsChain Adj) (h1 : L1 ≠ []) + (h2 : L2 ≠ []) : Adj (L1.getLast h1) (L2.head h2) := + hc.rel_getLast_head_of_append h1 h2 + +/-- A self-avoiding walk in the strip that starts on the `q`-side of a horizontal cut and ends on +the other side crosses the cut only once, provided some crossing column `c` is not available +(one of `(c, ρ1)`, `(c, ρ2)` is not on the walk): three crossings would use three distinct +columns, i.e. all of them. -/ +private lemma once (q : ℤ × ℤ → Bool) (ρ1 ρ2 : ℤ) + (hq : ∀ a b, Adj a b → q a = true → q b = false → a.1 = b.1 ∧ a.2 = ρ1 ∧ b.2 = ρ2) + {l : List (ℤ × ℤ)} (hc : l.IsChain Adj) (hn : l.Nodup) (hs : ∀ v ∈ l, InStrip v) + (hmiss : ∃ c : ℤ, 0 ≤ c ∧ c ≤ 2 ∧ ((c, ρ1) ∉ l ∨ (c, ρ2) ∉ l)) + (hh : ∀ v ∈ l.head?, q v = true) (hl : ∀ v ∈ l.getLast?, q v = false) : + ∀ v ∈ l.dropWhile q, q v = false := by + intro v hv + by_contra hqv + rw [Bool.not_eq_false] at hqv + obtain ⟨A, hA⟩ : ∃ A, A = l.takeWhile q := ⟨_, rfl⟩ + obtain ⟨R, hR⟩ : ∃ R, R = l.dropWhile q := ⟨_, rfl⟩ + obtain ⟨X, hX⟩ : ∃ X, X = R.takeWhile (fun v => !q v) := ⟨_, rfl⟩ + obtain ⟨R', hR'⟩ : ∃ R', R' = R.dropWhile (fun v => !q v) := ⟨_, rfl⟩ + obtain ⟨Y, hY⟩ : ∃ Y, Y = R'.takeWhile q := ⟨_, rfl⟩ + obtain ⟨Z, hZ⟩ : ∃ Z, Z = R'.dropWhile q := ⟨_, rfl⟩ + rw [← hR] at hv + have hlAR : l = A ++ R := by rw [hA, hR, List.takeWhile_append_dropWhile] + have hRXR : R = X ++ R' := by rw [hX, hR', List.takeWhile_append_dropWhile] + have hRYZ : R' = Y ++ Z := by rw [hY, hZ, List.takeWhile_append_dropWhile] + have hl4 : l = A ++ X ++ Y ++ Z := by rw [hlAR, hRXR, hRYZ]; simp + have hAq : ∀ w ∈ A, q w = true := fun w hw => by rw [hA] at hw; exact List.mem_takeWhile_imp hw + have hXq : ∀ w ∈ X, q w = false := fun w hw => by + rw [hX] at hw; simpa using List.mem_takeWhile_imp hw + have hYq : ∀ w ∈ Y, q w = true := fun w hw => by rw [hY] at hw; exact List.mem_takeWhile_imp hw + have hRne : R ≠ [] := List.ne_nil_of_mem hv + have hlne : l ≠ [] := by rintro rfl; simp [hR] at hRne + have hAne : A ≠ [] := by + obtain ⟨a, l', rfl⟩ := List.exists_cons_of_ne_nil hlne + have : q a = true := hh a (by simp) + rw [hA, List.takeWhile_cons_of_pos this]; simp + have hXne : X ≠ [] := by + have h0 := List.head_dropWhile_not q (hR ▸ hRne) + obtain ⟨r, R0, hr⟩ := List.exists_cons_of_ne_nil hRne + have : q r = false := by + have e : (l.dropWhile q).head (hR ▸ hRne) = r := by simp [← hR, hr] + rwa [e] at h0 + rw [hX, hr, List.takeWhile_cons_of_pos (by simp [this])]; simp + have hvR' : v ∈ R' := by + rw [hRXR, List.mem_append] at hv + rcases hv with h | h + · have := hXq v h; rw [hqv] at this; exact absurd this (by simp) + · exact h + have hR'ne : R' ≠ [] := List.ne_nil_of_mem hvR' + have hYne : Y ≠ [] := by + have h0 := List.head_dropWhile_not (fun v => !q v) (hR' ▸ hR'ne) + obtain ⟨r, R0, hr⟩ := List.exists_cons_of_ne_nil hR'ne + have : q r = true := by + have e : (R.dropWhile (fun v => !q v)).head (hR' ▸ hR'ne) = r := by simp [← hR', hr] + rw [e] at h0; simpa using h0 + rw [hY, hr, List.takeWhile_cons_of_pos this]; simp + have hZne : Z ≠ [] := by + intro hZ0 + have hlast : l.getLast? = Y.getLast? := by + rw [hl4, hZ0, List.append_nil, List.getLast?_append_of_ne_nil _ hYne] + obtain ⟨y, hy⟩ : ∃ y, Y.getLast? = some y := Option.isSome_iff_exists.1 (by simpa using hYne) + have h1 := hl y (by rw [hlast, hy]; rfl) + have h2 := hYq y (List.mem_of_getLast? hy) + rw [h1] at h2; exact absurd h2 (by simp) + have hZq : q (Z.head hZne) = false := by + have h0 := List.head_dropWhile_not q (hZ ▸ hZne) + have e : (R'.dropWhile q).head (hZ ▸ hZne) = Z.head hZne := by simp [hZ] + rwa [e] at h0 + -- the three crossings + have hc1 : Adj (A.getLast hAne) (X.head hXne) := by + have h := adj_junction (L1 := A) (L2 := X ++ Y ++ Z) (by rw [hl4] at hc; simpa using hc) + hAne (by simp [hXne]) + rwa [List.head_append_of_ne_nil (by simp [hXne]), List.head_append_of_ne_nil hXne] at h + have hc2 : Adj (X.getLast hXne) (Y.head hYne) := by + have h := adj_junction (L1 := A ++ X) (L2 := Y ++ Z) (by rw [hl4] at hc; simpa using hc) + (by simp [hXne]) (by simp [hYne]) + rwa [List.head_append_of_ne_nil hYne, List.getLast_append_of_ne_nil _ hXne] at h + have hc3 : Adj (Y.getLast hYne) (Z.head hZne) := by + have h := adj_junction (L1 := A ++ X ++ Y) (L2 := Z) (by rw [hl4] at hc; simpa using hc) + (by simp [hYne]) hZne + rwa [List.getLast_append_of_ne_nil _ hYne] at h + obtain ⟨e1, e1a, e1b⟩ := hq _ _ hc1 (hAq _ (List.getLast_mem _)) (hXq _ (List.head_mem _)) + obtain ⟨e2, e2a, e2b⟩ := hq _ _ (adj_symm hc2) (hYq _ (List.head_mem _)) + (hXq _ (List.getLast_mem _)) + obtain ⟨e3, e3a, e3b⟩ := hq _ _ hc3 (hYq _ (List.getLast_mem _)) hZq + -- distinctness + have hn1 : (A ++ (X ++ Y ++ Z)).Nodup := by rw [hl4] at hn; simpa using hn + have hn2 : ((A ++ X) ++ (Y ++ Z)).Nodup := by rw [hl4] at hn; simpa using hn + have d1 : A.getLast hAne ≠ Y.head hYne := + nodup_ne hn1 (List.getLast_mem _) (by simp [List.head_mem]) + have d2 : A.getLast hAne ≠ Y.getLast hYne := + nodup_ne hn1 (List.getLast_mem _) (by simp [List.getLast_mem]) + have d3 : X.getLast hXne ≠ Z.head hZne := + nodup_ne hn2 (by simp [List.getLast_mem]) (by simp [List.head_mem]) + have memA : ∀ w ∈ A, w ∈ l := fun w hw => by rw [hl4]; simp [hw] + have memX : ∀ w ∈ X, w ∈ l := fun w hw => by rw [hl4]; simp [hw] + have memY : ∀ w ∈ Y, w ∈ l := fun w hw => by rw [hl4]; simp [hw] + have memZ : ∀ w ∈ Z, w ∈ l := fun w hw => by rw [hl4]; simp [hw] + have s1 := hs _ (memA _ (List.getLast_mem hAne)) + have s2 := hs _ (memY _ (List.head_mem hYne)) + have s3 := hs _ (memY _ (List.getLast_mem hYne)) + unfold InStrip at s1 s2 s3 + have n12 : (A.getLast hAne).1 ≠ (Y.head hYne).1 := fun h => d1 (Prod.ext h (by rw [e1a, e2a])) + have n13 : (A.getLast hAne).1 ≠ (Y.getLast hYne).1 := fun h => d2 (Prod.ext h (by rw [e1a, e3a])) + have n23 : (Y.head hYne).1 ≠ (Y.getLast hYne).1 := fun h => + d3 (Prod.ext (by rw [← e2, h, e3]) (by rw [e2b, e3b])) + obtain ⟨c, hc0, hc2', hcm⟩ := hmiss + have key : c = (A.getLast hAne).1 ∨ c = (Y.head hYne).1 ∨ c = (Y.getLast hYne).1 := by omega + rcases key with h | h | h + · rcases hcm with hm | hm + · exact hm (by rw [h, ← e1a]; exact memA _ (List.getLast_mem _)) + · exact hm (by rw [h, e1, ← e1b]; exact memX _ (List.head_mem _)) + · rcases hcm with hm | hm + · exact hm (by rw [h, ← e2a]; exact memY _ (List.head_mem _)) + · exact hm (by rw [h, e2, ← e2b]; exact memX _ (List.getLast_mem _)) + · rcases hcm with hm | hm + · exact hm (by rw [h, ← e3a]; exact memY _ (List.getLast_mem _)) + · exact hm (by rw [h, e3, ← e3b]; exact memZ _ (List.head_mem _)) + + +/-- A self-avoiding walk in the strip that starts and ends on the `q`-side of a horizontal cut +leaves that side at most once. -/ +private lemma conv (q : ℤ × ℤ → Bool) (ρ1 ρ2 : ℤ) + (hq : ∀ a b, Adj a b → q a = true → q b = false → a.1 = b.1 ∧ a.2 = ρ1 ∧ b.2 = ρ2) + {l : List (ℤ × ℤ)} (hc : l.IsChain Adj) (hn : l.Nodup) (hs : ∀ v ∈ l, InStrip v) + (hh : ∀ v ∈ l.head?, q v = true) (hl : ∀ v ∈ l.getLast?, q v = true) : + ∀ v ∈ (l.dropWhile q).dropWhile (fun v => !q v), q v = true := by + intro v hv + obtain ⟨A, hA⟩ : ∃ A, A = l.takeWhile q := ⟨_, rfl⟩ + obtain ⟨R, hR⟩ : ∃ R, R = l.dropWhile q := ⟨_, rfl⟩ + rw [← hR] at hv + have hlAR : l = A ++ R := by rw [hA, hR, List.takeWhile_append_dropWhile] + have hAq : ∀ w ∈ A, q w = true := fun w hw => by rw [hA] at hw; exact List.mem_takeWhile_imp hw + have hRne : R ≠ [] := by rintro rfl; simp at hv + have hlne : l ≠ [] := by rintro rfl; simp [hR] at hRne + have hAne : A ≠ [] := by + obtain ⟨a, l', rfl⟩ := List.exists_cons_of_ne_nil hlne + have : q a = true := hh a (by simp) + rw [hA, List.takeWhile_cons_of_pos this]; simp + have hRq : q (R.head hRne) = false := by + have h0 := List.head_dropWhile_not q (hR ▸ hRne) + have e : (l.dropWhile q).head (hR ▸ hRne) = R.head hRne := by simp [hR] + rwa [e] at h0 + have hc' : (A ++ R).IsChain Adj := hlAR ▸ hc + have hn' : (A ++ R).Nodup := hlAR ▸ hn + have hc1 : Adj (A.getLast hAne) (R.head hRne) := adj_junction hc' hAne hRne + obtain ⟨-, e1a, -⟩ := hq _ _ hc1 (hAq _ (List.getLast_mem _)) hRq + have hmissR : ((A.getLast hAne).1, ρ1) ∉ R := by + intro hm + exact nodup_ne hn' (List.getLast_mem hAne) hm (Prod.ext rfl e1a) + have s1 := hs _ (by rw [hlAR]; exact List.mem_append_left _ (List.getLast_mem hAne)) + unfold InStrip at s1 + have key := once (fun v => !q v) ρ2 ρ1 + (fun a b hab ha hb => by + obtain ⟨h1, h2, h3⟩ := hq b a (adj_symm hab) (by simpa using hb) (by simpa using ha) + exact ⟨h1.symm, h3, h2⟩) + hc'.right_of_append (List.nodup_append.1 hn').2.1 + (fun w hw => hs w (by rw [hlAR]; exact List.mem_append_right _ hw)) + ⟨_, s1.1, s1.2, Or.inr hmissR⟩ + (fun w hw => by + rw [List.head?_eq_some_head hRne, Option.mem_def, Option.some.injEq] at hw + subst hw; simp [hRq]) + (fun w hw => by + have : w ∈ l.getLast? := by rw [hlAR, List.getLast?_append_of_ne_nil _ hRne]; exact hw + simp [hl w this]) + v hv + simpa using key + +/-- Decomposition form of `once`. -/ +private lemma once_split (q : ℤ × ℤ → Bool) (ρ1 ρ2 : ℤ) + (hq : ∀ a b, Adj a b → q a = true → q b = false → a.1 = b.1 ∧ a.2 = ρ1 ∧ b.2 = ρ2) + {l : List (ℤ × ℤ)} (hc : l.IsChain Adj) (hn : l.Nodup) (hs : ∀ v ∈ l, InStrip v) + (hmiss : ∃ c : ℤ, 0 ≤ c ∧ c ≤ 2 ∧ ((c, ρ1) ∉ l ∨ (c, ρ2) ∉ l)) + (hh : ∀ v ∈ l.head?, q v = true) (hl : ∀ v ∈ l.getLast?, q v = false) : + ∃ A B, l = A ++ B ∧ (∀ v ∈ A, q v = true) ∧ (∀ v ∈ B, q v = false) := + ⟨l.takeWhile q, l.dropWhile q, List.takeWhile_append_dropWhile.symm, + fun _ hv => List.mem_takeWhile_imp hv, once q ρ1 ρ2 hq hc hn hs hmiss hh hl⟩ + +/-- Decomposition form of `conv`. -/ +private lemma conv_split (q : ℤ × ℤ → Bool) (ρ1 ρ2 : ℤ) + (hq : ∀ a b, Adj a b → q a = true → q b = false → a.1 = b.1 ∧ a.2 = ρ1 ∧ b.2 = ρ2) + {l : List (ℤ × ℤ)} (hc : l.IsChain Adj) (hn : l.Nodup) (hs : ∀ v ∈ l, InStrip v) + (hh : ∀ v ∈ l.head?, q v = true) (hl : ∀ v ∈ l.getLast?, q v = true) : + ∃ A X B, l = A ++ X ++ B ∧ (∀ v ∈ A, q v = true) ∧ (∀ v ∈ X, q v = false) ∧ + (∀ v ∈ B, q v = true) := + ⟨l.takeWhile q, (l.dropWhile q).takeWhile (fun v => !q v), + (l.dropWhile q).dropWhile (fun v => !q v), + by rw [List.append_assoc, List.takeWhile_append_dropWhile, List.takeWhile_append_dropWhile], + fun _ hv => List.mem_takeWhile_imp hv, + fun _ hv => by simpa using List.mem_takeWhile_imp hv, + conv q ρ1 ρ2 hq hc hn hs hh hl⟩ + +/-! ### Half-strips and horizontal segments -/ + +/-- `+1` (up) or `-1` (down). -/ +private def dir : Bool → ℤ + | true => 1 + | false => -1 + +/-- `v` lies on side `σ` of row `r` (row `r` included): above it for `σ = true`. -/ +private def onSide (σ : Bool) (r : ℤ) (v : ℤ × ℤ) : Prop := if σ then r ≤ v.2 else v.2 ≤ r + +/-- Decidability of `onSide`. -/ +private instance (σ : Bool) (r : ℤ) (v : ℤ × ℤ) : Decidable (onSide σ r v) := by + unfold onSide; split <;> infer_instance + +/-- `v` is not strictly beyond row `r` on side `σ`. -/ +private def near (σ : Bool) (r : ℤ) (v : ℤ × ℤ) : Bool := + if σ then decide (v.2 ≤ r) else decide (r ≤ v.2) + +/-- A unit step from `near` to not `near` crosses between rows `r` and `r + dir σ` vertically. -/ +private lemma near_hq (σ : Bool) (r : ℤ) (a b : ℤ × ℤ) (hab : Adj a b) (ha : near σ r a = true) + (hb : near σ r b = false) : a.1 = b.1 ∧ a.2 = r ∧ b.2 = r + dir σ := by + rw [adj_iff] at hab + cases σ <;> simp [near, dir] at ha hb ⊢ <;> omega + +/-- The decomposition of a self-avoiding walk in a half-strip from row `r` to row `r`: a piece in +row `r`, an excursion strictly beyond row `r` (possibly empty), and a piece in row `r`. -/ +private lemma half_split (σ : Bool) (r : ℤ) {l : List (ℤ × ℤ)} (hc : l.IsChain Adj) + (hn : l.Nodup) (hs : ∀ v ∈ l, InStrip v ∧ onSide σ r v) (hh : ∀ v ∈ l.head?, v.2 = r) + (hl : ∀ v ∈ l.getLast?, v.2 = r) : + ∃ A X B, l = A ++ X ++ B ∧ (∀ v ∈ A, v.2 = r) ∧ + (∀ v ∈ X, v.2 ≠ r ∧ onSide σ (r + dir σ) v) ∧ (∀ v ∈ B, v.2 = r) := by + have hnear : ∀ v, onSide σ r v → (near σ r v = true ↔ v.2 = r) := by + intro v hv; cases σ <;> simp [near, onSide] at hv ⊢ <;> omega + have hfar : ∀ v, onSide σ r v → near σ r v = false → v.2 ≠ r ∧ onSide σ (r + dir σ) v := by + intro v hv hf; cases σ <;> simp [near, onSide, dir] at hv hf ⊢ <;> omega + obtain ⟨A, X, B, hl3, hA, hX, hB⟩ := conv_split (near σ r) r (r + dir σ) (near_hq σ r) hc hn + (fun v hv => (hs v hv).1) + (fun v hv => (hnear v (hs v (List.mem_of_mem_head? hv)).2).2 (hh v hv)) + (fun v hv => (hnear v (hs v (List.mem_of_getLast? hv)).2).2 (hl v hv)) + have mem : ∀ v, v ∈ A ∨ v ∈ X ∨ v ∈ B → v ∈ l := fun v hv => by + rw [hl3]; simp only [List.mem_append]; tauto + exact ⟨A, X, B, hl3, fun v hv => (hnear v (hs v (mem v (Or.inl hv))).2).1 (hA v hv), + fun v hv => hfar v (hs v (mem v (Or.inr (Or.inl hv)))).2 (hX v hv), + fun v hv => (hnear v (hs v (mem v (Or.inr (Or.inr hv)))).2).1 (hB v hv)⟩ + + +/-- The columns of the horizontal segment from column `a` to column `b`, in order. -/ +private def cols (a b : Fin 3) : List (Fin 3) := + ![![[0], [0, 1], [0, 1, 2]], ![[1, 0], [1], [1, 2]], ![[2, 1, 0], [2, 1], [2]]] a b + +/-- A column as an integer. -/ +private def ci (c : Fin 3) : ℤ := ((c : ℕ) : ℤ) + +/-- An integer in `[0, 2]` as a column. -/ +private def colOf (z : ℤ) : Fin 3 := ⟨z.toNat % 3, Nat.mod_lt _ (by norm_num)⟩ + +/-- Columns lie in `[0, 2]`. -/ +private lemma ci_bounds (c : Fin 3) : 0 ≤ ci c ∧ ci c ≤ 2 := by + have := c.isLt; unfold ci; omega + +/-- `colOf` inverts `ci`. -/ +private lemma colOf_ci (c : Fin 3) : colOf (ci c) = c := by + apply Fin.ext; simp [colOf, ci] + +/-- `ci` inverts `colOf` on `[0, 2]`. -/ +private lemma ci_colOf {z : ℤ} (h0 : 0 ≤ z) (h2 : z ≤ 2) : ci (colOf z) = z := by + simp only [ci, colOf]; omega + +/-- `ci` is injective. -/ +private lemma ci_inj {a b : Fin 3} (h : ci a = ci b) : a = b := by + rw [← colOf_ci a, h, colOf_ci] + +/-- The horizontal segment in row `r` from column `a` to column `b`. -/ +private def hseg (r : ℤ) (a b : Fin 3) : List (ℤ × ℤ) := (cols a b).map fun c => (ci c, r) + +/-- Membership in a horizontal segment. -/ +private lemma mem_hseg {r : ℤ} {a b : Fin 3} {v : ℤ × ℤ} : + v ∈ hseg r a b ↔ ∃ c ∈ cols a b, v = (ci c, r) := by + simp [hseg, eq_comm] + +/-- A horizontal segment lies in its row and in the strip. -/ +private lemma hseg_row {r : ℤ} {a b : Fin 3} {v : ℤ × ℤ} (hv : v ∈ hseg r a b) : + v.2 = r ∧ InStrip v := by + obtain ⟨c, -, rfl⟩ := mem_hseg.1 hv + exact ⟨rfl, ci_bounds c⟩ + +/-- A horizontal segment is nonempty. -/ +private lemma hseg_ne_nil (r : ℤ) (a b : Fin 3) : hseg r a b ≠ [] := by + fin_cases a <;> fin_cases b <;> simp [hseg, cols] + +/-- The first vertex of a horizontal segment. -/ +private lemma hseg_head? (r : ℤ) (a b : Fin 3) : (hseg r a b).head? = some (ci a, r) := by + fin_cases a <;> fin_cases b <;> simp [hseg, cols] + +/-- The last vertex of a horizontal segment. -/ +private lemma hseg_getLast? (r : ℤ) (a b : Fin 3) : (hseg r a b).getLast? = some (ci b, r) := by + fin_cases a <;> fin_cases b <;> simp [hseg, cols] + +/-- The length of a horizontal segment. -/ +private lemma hseg_length (r : ℤ) (a b : Fin 3) : (hseg r a b).length = (cols a b).length := by + simp [hseg] + +/-- A segment has at least one column. -/ +private lemma cols_length_pos (a b : Fin 3) : 1 ≤ (cols a b).length := by + fin_cases a <;> fin_cases b <;> simp [cols] + +/-- A horizontal segment is a walk. -/ +private lemma hseg_chain (r : ℤ) (a b : Fin 3) : (hseg r a b).IsChain Adj := by + fin_cases a <;> fin_cases b <;> simp [hseg, cols, ci, adj_iff] + +/-- Placing columns in a row is injective. -/ +private lemma hseg_map_inj (r : ℤ) : Function.Injective fun c : Fin 3 => (ci c, r) := + fun _ _ h => ci_inj (Prod.mk.inj h).1 + +/-- Two segments in the same row are disjoint iff their column lists are. -/ +private lemma hseg_append_nodup {r : ℤ} {a b c d : Fin 3} : + (hseg r a b ++ hseg r c d).Nodup ↔ (cols a b ++ cols c d).Nodup := by + rw [hseg, hseg, ← List.map_append, List.nodup_map_iff (hseg_map_inj r)] + +/-- A horizontal segment has no repeated vertex. -/ +private lemma hseg_nodup (r : ℤ) (a b : Fin 3) : (hseg r a b).Nodup := by + rw [hseg, List.nodup_map_iff (hseg_map_inj r)] + fin_cases a <;> fin_cases b <;> decide + +/-- A self-avoiding walk inside a row is the horizontal segment between its ends. -/ +private lemma row_unique {r : ℤ} {l : List (ℤ × ℤ)} (hne : l ≠ []) + (hrow : ∀ v ∈ l, v.2 = r ∧ InStrip v) (hn : l.Nodup) (hc : l.IsChain Adj) : + l = hseg r (colOf (l.head hne).1) (colOf (l.getLast hne).1) := by + have key : ∀ v ∈ l, v.2 = r ∧ 0 ≤ v.1 ∧ v.1 ≤ 2 := fun v hv => + ⟨(hrow v hv).1, (hrow v hv).2.1, (hrow v hv).2.2⟩ + match l, hne, key, hn, hc with + | [(a1, a2)], _, key, _, _ => + obtain ⟨ha, h0, h2⟩ := key (a1, a2) (by simp) + simp only at ha h0 h2 + subst ha + simp only [List.head_cons, List.getLast_singleton] + obtain h | h | h : a1 = 0 ∨ a1 = 1 ∨ a1 = 2 := by omega + all_goals subst h; simp [hseg, cols, colOf, ci] + | [(a1, a2), (b1, b2)], _, key, _, hc => + obtain ⟨ha, ha0, ha2⟩ := key (a1, a2) (by simp) + obtain ⟨hb, hb0, hb2⟩ := key (b1, b2) (by simp) + have hab := (List.isChain_cons_cons.1 hc).1 + rw [adj_iff] at hab + simp only at ha hb ha0 ha2 hb0 hb2 hab + subst ha hb + simp only [List.head_cons, List.getLast_cons_cons, List.getLast_singleton] + obtain ⟨h1, h2⟩ | ⟨h1, h2⟩ | ⟨h1, h2⟩ | ⟨h1, h2⟩ : + (a1 = 0 ∧ b1 = 1) ∨ (a1 = 1 ∧ b1 = 0) ∨ (a1 = 1 ∧ b1 = 2) ∨ (a1 = 2 ∧ b1 = 1) := by + omega + all_goals subst h1 h2; simp [hseg, cols, colOf, ci] + | [(a1, a2), (b1, b2), (c1, c2)], _, key, hn, hc => + obtain ⟨ha, ha0, ha2⟩ := key (a1, a2) (by simp) + obtain ⟨hb, hb0, hb2⟩ := key (b1, b2) (by simp) + obtain ⟨hc', hc0, hc2⟩ := key (c1, c2) (by simp) + have hab := (List.isChain_cons_cons.1 hc).1 + have hbc := (List.isChain_cons_cons.1 (List.isChain_cons_cons.1 hc).2).1 + have hac : (a1, a2) ≠ (c1, c2) := by simp only [List.nodup_cons] at hn; simp_all + rw [adj_iff] at hab hbc + simp only at ha hb hc' ha0 ha2 hb0 hb2 hc0 hc2 hab hbc + subst ha hb hc' + have hac' : a1 ≠ c1 := fun h => hac (by rw [h]) + simp only [List.head_cons, List.getLast_cons_cons, List.getLast_singleton] + obtain ⟨h1, h2, h3⟩ | ⟨h1, h2, h3⟩ : + (a1 = 0 ∧ b1 = 1 ∧ c1 = 2) ∨ (a1 = 2 ∧ b1 = 1 ∧ c1 = 0) := by omega + all_goals subst h1 h2 h3; simp [hseg, cols, colOf, ci] + | a :: b :: c :: d :: t, _, key, hn, _ => + exfalso + obtain ⟨ha, ha0, ha2⟩ := key a (by simp) + obtain ⟨hb, hb0, hb2⟩ := key b (by simp) + obtain ⟨hc', hc0, hc2⟩ := key c (by simp) + obtain ⟨hd, hd0, hd2⟩ := key d (by simp) + simp only [List.nodup_cons, List.mem_cons, not_or] at hn + have n1 : a.1 ≠ b.1 := fun h => hn.1.1 (Prod.ext h (by rw [ha, hb])) + have n2 : a.1 ≠ c.1 := fun h => hn.1.2.1 (Prod.ext h (by rw [ha, hc'])) + have n3 : a.1 ≠ d.1 := fun h => hn.1.2.2.1 (Prod.ext h (by rw [ha, hd])) + have n4 : b.1 ≠ c.1 := fun h => hn.2.1.1 (Prod.ext h (by rw [hb, hc'])) + have n5 : b.1 ≠ d.1 := fun h => hn.2.1.2.1 (Prod.ext h (by rw [hb, hd])) + have n6 : c.1 ≠ d.1 := fun h => hn.2.2.1.1 (Prod.ext h (by rw [hc', hd])) + omega + +/-! ### Counting excursions in a half-strip -/ + +/-- Counting a finset that is a disjoint union of injective images, the pieces being told apart +by a function `g`. -/ +private lemma card_eq_sum {α β ι : Type} [DecidableEq α] + (S : Finset α) (I : Finset ι) (T : ι → Finset β) (F : ι → β → α) (g : α → ι) + (hinj : ∀ i ∈ I, ∀ x ∈ T i, ∀ y ∈ T i, F i x = F i y → x = y) + (hg : ∀ i ∈ I, ∀ x ∈ T i, g (F i x) = i) + (hS : ∀ a, a ∈ S ↔ ∃ i ∈ I, ∃ x ∈ T i, F i x = a) : + S.card = ∑ i ∈ I, (T i).card := by + have hS' : S = I.biUnion fun i => (T i).image (F i) := by + ext a; rw [hS]; simp [Finset.mem_biUnion, Finset.mem_image] + rw [hS', Finset.card_biUnion] + · exact Finset.sum_congr rfl fun i hi => + Finset.card_image_of_injOn fun x hx y hy h => hinj i hi x hx y hy h + · intro i hi j hj hij + simp only [Function.onFun] + rw [Finset.disjoint_left] + intro a ha hb + simp only [Finset.mem_image] at ha hb + obtain ⟨x, hx, rfl⟩ := ha + obtain ⟨y, hy, hyx⟩ := hb + exact hij ((hg i hi x hx).symm.trans (hyx ▸ hg j hj y hy)) + +/-- Self-avoiding walks of `ℓ` steps in the half-strip on side `σ` of row `r`, from column `c1` +to column `c2` of row `r`, whose vertices in row `r` avoid the columns in `S`. -/ +private def exc (σ : Bool) (r : ℤ) (S : Finset (Fin 3)) (c1 c2 : Fin 3) (ℓ : ℕ) : + Finset (List (ℤ × ℤ)) := + (walksFrom (ci c1, r) ℓ).filter fun l => l.getLast? = some (ci c2, r) ∧ l.Nodup ∧ + ∀ v ∈ l, InStrip v ∧ onSide σ r v ∧ ∀ c ∈ S, v ≠ (ci c, r) + +/-- Membership in `exc`. -/ +private lemma mem_exc {σ : Bool} {r : ℤ} {S : Finset (Fin 3)} {c1 c2 : Fin 3} {ℓ : ℕ} + {l : List (ℤ × ℤ)} : l ∈ exc σ r S c1 c2 ℓ ↔ + l.length = ℓ + 1 ∧ l.head? = some (ci c1, r) ∧ l.IsChain Adj ∧ + l.getLast? = some (ci c2, r) ∧ l.Nodup ∧ + ∀ v ∈ l, InStrip v ∧ onSide σ r v ∧ ∀ c ∈ S, v ≠ (ci c, r) := by + simp only [exc, Finset.mem_filter, mem_walksFrom, and_assoc] + +/-- The two end segments in row `r` are disjoint and avoid `S`. -/ +private def okSeg (S : Finset (Fin 3)) (c1 c1' c2' c2 : Fin 3) : Prop := + (cols c1 c1' ++ cols c2' c2).Nodup ∧ ∀ c ∈ cols c1 c1' ++ cols c2' c2, c ∉ S + +/-- Decidability of `okSeg`. -/ +private instance (S : Finset (Fin 3)) (c1 c1' c2' c2 : Fin 3) : + Decidable (okSeg S c1 c1' c2' c2) := by unfold okSeg; infer_instance + +/-- Beyond row `r + dir σ` on side `σ` means on side `σ` of row `r`, off row `r`. -/ +private lemma onSide_step {σ : Bool} {r : ℤ} {v : ℤ × ℤ} (h : onSide σ (r + dir σ) v) : + onSide σ r v ∧ v.2 ≠ r := by + cases σ <;> simp [onSide, dir] at h ⊢ <;> omega + +/-- A vertical unit step towards side `σ`. -/ +private lemma adj_vert (σ : Bool) (c r : ℤ) : Adj (c, r) (c, r + dir σ) := by + rw [adj_iff]; cases σ <;> simp [dir, sub_eq_add_neg] + +/-- Leaving row `r` from `(c, r)` to side `σ`. -/ +private lemma adj_exit {σ : Bool} {r c : ℤ} {v : ℤ × ℤ} (h : Adj (c, r) v) (hv : v.2 ≠ r) + (hs : onSide σ (r + dir σ) v) : v = (c, r + dir σ) := by + rw [adj_iff] at h + apply Prod.ext <;> cases σ <;> simp [onSide, dir] at h hs ⊢ <;> omega + +/-- An excursion with its end segments is an excursion. -/ +private lemma exc_build2 {σ : Bool} {r : ℤ} {S : Finset (Fin 3)} {c1 c2 c1' c2' : Fin 3} {ℓ : ℕ} + (hok : okSeg S c1 c1' c2' c2) (hlen : (cols c1 c1').length + (cols c2' c2).length ≤ ℓ) + {X : List (ℤ × ℤ)} + (hX : X ∈ exc σ (r + dir σ) ∅ c1' c2' (ℓ - (cols c1 c1').length - (cols c2' c2).length)) : + hseg r c1 c1' ++ X ++ hseg r c2' c2 ∈ exc σ r S c1 c2 ℓ := by + obtain ⟨hXl, hXh, hXc, hXt, hXn, hXp⟩ := mem_exc.1 hX + have hXne : X ≠ [] := by rintro rfl; simp at hXl + rw [mem_exc] + refine ⟨?_, ?_, ?_, ?_, ?_, ?_⟩ + · simp only [List.length_append, hseg_length]; omega + · rw [List.append_assoc, List.head?_append_of_ne_nil _ (hseg_ne_nil _ _ _), hseg_head?] + · refine List.IsChain.append (List.IsChain.append (hseg_chain _ _ _) hXc ?_) (hseg_chain _ _ _) ?_ + · intro x hx y hy + rw [hseg_getLast?, Option.mem_def, Option.some.injEq] at hx + rw [hXh, Option.mem_def, Option.some.injEq] at hy + subst hx hy; exact adj_vert σ _ _ + · intro x hx y hy + rw [List.getLast?_append_of_ne_nil _ hXne, hXt, Option.mem_def, Option.some.injEq] at hx + rw [hseg_head?, Option.mem_def, Option.some.injEq] at hy + subst hx hy; exact adj_symm (adj_vert σ _ _) + · rw [List.getLast?_append_of_ne_nil _ (hseg_ne_nil _ _ _), hseg_getLast?] + · have h12 := (hseg_append_nodup (r := r)).2 hok.1 + rw [List.nodup_append] at h12 ⊢ + rw [List.nodup_append] + refine ⟨⟨h12.1, hXn, fun a ha b hb hab => ?_⟩, h12.2.1, fun a ha b hb hab => ?_⟩ + · subst hab; exact (onSide_step (hXp a hb).2.1).2 (hseg_row ha).1 + · rw [List.mem_append] at ha + rcases ha with ha | ha + · exact h12.2.2 a ha b hb hab + · subst hab; exact (onSide_step (hXp a ha).2.1).2 (hseg_row hb).1 + · intro v hv + simp only [List.mem_append] at hv + have hseg_case : ∀ a b, v ∈ hseg r a b → (∀ c ∈ cols a b, c ∉ S) → + InStrip v ∧ onSide σ r v ∧ ∀ c ∈ S, v ≠ (ci c, r) := by + intro a b hv' hS + obtain ⟨c, hc, rfl⟩ := mem_hseg.1 hv' + refine ⟨ci_bounds c, by cases σ <;> simp [onSide], fun c' hc' he => ?_⟩ + have := ci_inj (Prod.mk.inj he).1 + subst this; exact hS c hc hc' + rcases hv with (hv | hv) | hv + · exact hseg_case _ _ hv fun c hc => hok.2 c (List.mem_append_left _ hc) + · obtain ⟨h1, h2, -⟩ := hXp v hv + exact ⟨h1, (onSide_step h2).1, fun c _ he => (onSide_step h2).2 (by rw [he])⟩ + · exact hseg_case _ _ hv fun c hc => hok.2 c (List.mem_append_right _ hc) + +/-- The straight segment is an excursion. -/ +private lemma exc_build1 {σ : Bool} {r : ℤ} {S : Finset (Fin 3)} {c1 c2 : Fin 3} {ℓ : ℕ} + (hlen : ℓ + 1 = (cols c1 c2).length) (hS : ∀ c ∈ cols c1 c2, c ∉ S) : + hseg r c1 c2 ∈ exc σ r S c1 c2 ℓ := by + rw [mem_exc] + refine ⟨by rw [hseg_length, hlen], hseg_head? _ _ _, hseg_chain _ _ _, hseg_getLast? _ _ _, + hseg_nodup _ _ _, fun v hv => ?_⟩ + obtain ⟨c, hc, rfl⟩ := mem_hseg.1 hv + refine ⟨ci_bounds c, by cases σ <;> simp [onSide], fun c' hc' he => ?_⟩ + have := ci_inj (Prod.mk.inj he).1 + subst this; exact hS c hc hc' + +/-- The structure of an excursion: straight, or two end segments around an excursion from the +next row. -/ +private lemma exc_decomp {σ : Bool} {r : ℤ} {S : Finset (Fin 3)} {c1 c2 : Fin 3} {ℓ : ℕ} + {l : List (ℤ × ℤ)} (hl : l ∈ exc σ r S c1 c2 ℓ) : + (l = hseg r c1 c2 ∧ ℓ + 1 = (cols c1 c2).length ∧ ∀ c ∈ cols c1 c2, c ∉ S) ∨ + ∃ c1' c2' X, okSeg S c1 c1' c2' c2 ∧ (cols c1 c1').length + (cols c2' c2).length ≤ ℓ ∧ + X ∈ exc σ (r + dir σ) ∅ c1' c2' (ℓ - (cols c1 c1').length - (cols c2' c2).length) ∧ + l = hseg r c1 c1' ++ X ++ hseg r c2' c2 := by + obtain ⟨hlen, hhead, hc, hlast, hn, hp⟩ := mem_exc.1 hl + have hlne : l ≠ [] := by rintro rfl; simp at hlen + obtain ⟨A, X, B, rfl, hA, hX, hB⟩ := half_split σ r hc hn (fun v hv => ⟨(hp v hv).1, (hp v hv).2.1⟩) + (fun v hv => by rw [hhead, Option.mem_def, Option.some.injEq] at hv; rw [← hv]) + (fun v hv => by rw [hlast, Option.mem_def, Option.some.injEq] at hv; rw [← hv]) + have hheadv : (A ++ X ++ B).head hlne = (ci c1, r) := by + rw [List.head?_eq_some_head hlne, Option.some.injEq] at hhead; exact hhead + have hlastv : (A ++ X ++ B).getLast hlne = (ci c2, r) := by + rw [List.getLast?_eq_some_getLast hlne, Option.some.injEq] at hlast; exact hlast + have memS : ∀ v ∈ A ++ X ++ B, ∀ c ∈ S, v ≠ (ci c, r) := fun v hv => (hp v hv).2.2 + by_cases hXe : X = [] + · -- straight + subst hXe + left + have hrow : ∀ v ∈ A ++ [] ++ B, v.2 = r ∧ InStrip v := by + intro v hv + simp only [List.append_nil, List.mem_append] at hv + rcases hv with hv | hv + · exact ⟨hA v hv, (hp v (by simp [hv])).1⟩ + · exact ⟨hB v hv, (hp v (by simp [hv])).1⟩ + have hu := row_unique hlne hrow hn hc + rw [hheadv, hlastv, colOf_ci, colOf_ci] at hu + refine ⟨hu, by rw [← hlen, hu, hseg_length], fun c hc' hcS => ?_⟩ + have hmem : (ci c, r) ∈ A ++ [] ++ B := by rw [hu]; exact mem_hseg.2 ⟨c, hc', rfl⟩ + exact memS _ hmem c hcS rfl + · right + have hAne : A ≠ [] := by + rintro rfl + have : (X ++ B).head (by simpa using hlne) = X.head hXe := List.head_append_of_ne_nil hXe + have h1 : X.head hXe = (ci c1, r) := by rw [← this]; simpa using hheadv + exact (hX _ (List.head_mem hXe)).1 (by rw [h1]) + have hBne : B ≠ [] := by + rintro rfl + have h1 : X.getLast hXe = (ci c2, r) := by + rw [← hlastv]; simp [List.getLast_append_of_ne_nil _ hXe] + exact (hX _ (List.getLast_mem hXe)).1 (by rw [h1]) + have hcA : A.IsChain Adj := hc.left_of_append.left_of_append + have hcX : X.IsChain Adj := hc.left_of_append.right_of_append + have hcB : B.IsChain Adj := hc.right_of_append + have hnA : A.Nodup := (List.nodup_append.1 (List.nodup_append.1 hn).1).1 + have hnX : X.Nodup := (List.nodup_append.1 (List.nodup_append.1 hn).1).2.1 + have hnB : B.Nodup := (List.nodup_append.1 hn).2.1 + have hrowA : ∀ v ∈ A, v.2 = r ∧ InStrip v := fun v hv => ⟨hA v hv, (hp v (by simp [hv])).1⟩ + have hrowB : ∀ v ∈ B, v.2 = r ∧ InStrip v := fun v hv => ⟨hB v hv, (hp v (by simp [hv])).1⟩ + have huA := row_unique hAne hrowA hnA hcA + have huB := row_unique hBne hrowB hnB hcB + have hAh : A.head hAne = (ci c1, r) := by + rw [← hheadv, List.head_append_of_ne_nil (by simp [hAne]), List.head_append_of_ne_nil hAne] + have hBl : B.getLast hBne = (ci c2, r) := by + rw [← hlastv, List.getLast_append_of_ne_nil _ hBne] + rw [hAh, colOf_ci] at huA + rw [hBl, colOf_ci] at huB + set c1' := colOf (A.getLast hAne).1 with hc1' + set c2' := colOf (B.head hBne).1 with hc2' + -- the ends of `X` + have j1 : Adj (A.getLast hAne) (X.head hXe) := by + have := adj_junction (L1 := A) (L2 := X ++ B) (by simpa using hc) hAne (by simp [hXe]) + rwa [List.head_append_of_ne_nil hXe] at this + have j2 : Adj (X.getLast hXe) (B.head hBne) := by + have := adj_junction (L1 := A ++ X) (L2 := B) hc (by simp [hXe]) hBne + rwa [List.getLast_append_of_ne_nil _ hXe] at this + have hAl : A.getLast hAne = (ci c1', r) := by + have h1 := hrowA _ (List.getLast_mem hAne) + exact Prod.ext (by rw [hc1', ci_colOf h1.2.1 h1.2.2]) h1.1 + have hBh : B.head hBne = (ci c2', r) := by + have h1 := hrowB _ (List.head_mem hBne) + exact Prod.ext (by rw [hc2', ci_colOf h1.2.1 h1.2.2]) h1.1 + have hXh : X.head hXe = (ci c1', r + dir σ) := by + rw [hAl] at j1 + exact adj_exit j1 (hX _ (List.head_mem hXe)).1 (hX _ (List.head_mem hXe)).2 + have hXl : X.getLast hXe = (ci c2', r + dir σ) := by + rw [hBh] at j2 + exact adj_exit (adj_symm j2) (hX _ (List.getLast_mem hXe)).1 + (hX _ (List.getLast_mem hXe)).2 + have hlenA : A.length = (cols c1 c1').length := by rw [huA, hseg_length] + have hlenB : B.length = (cols c2' c2).length := by rw [huB, hseg_length] + have hlenX : 1 ≤ X.length := List.length_pos_iff.2 hXe + simp only [List.length_append] at hlen + have hnAB : (A ++ B).Nodup := by + have hsub : List.Sublist (A ++ B) (A ++ X ++ B) := by + rw [List.append_assoc]; exact (List.sublist_append_right X B).append_left A + exact hn.sublist hsub + refine ⟨c1', c2', X, ⟨?_, ?_⟩, by omega, ?_, by rw [← huA, ← huB]⟩ + · rw [← hseg_append_nodup (r := r), ← huA, ← huB]; exact hnAB + · intro c hc' hcS + have hmem : (ci c, r) ∈ A ++ B := by + rw [huA, huB, List.mem_append] + rw [List.mem_append] at hc' + rcases hc' with h | h + · exact Or.inl (mem_hseg.2 ⟨c, h, rfl⟩) + · exact Or.inr (mem_hseg.2 ⟨c, h, rfl⟩) + exact memS _ (by simp only [List.mem_append] at hmem ⊢; tauto) c hcS rfl + · rw [mem_exc] + refine ⟨by omega, by rw [List.head?_eq_some_head hXe, hXh], hcX, + by rw [List.getLast?_eq_some_getLast hXe, hXl], hnX, fun v hv => ⟨(hp v (by simp [hv])).1, + (hX v hv).2, by simp⟩⟩ + +/-- Recovering the columns where an excursion leaves and re-enters row `r`. -/ +private def gEx (r : ℤ) (l : List (ℤ × ℤ)) : Option (Fin 3 × Fin 3) := + match l.filter (fun v => decide (v.2 ≠ r)) with + | [] => none + | x :: xs => some (colOf x.1, colOf ((x :: xs).getLast (List.cons_ne_nil _ _)).1) + +/-- A horizontal segment has no vertex off its row. -/ +private lemma filter_hseg (r : ℤ) (a b : Fin 3) : + (hseg r a b).filter (fun v => decide (v.2 ≠ r)) = [] := by + rw [List.filter_eq_nil_iff]; intro v hv; simp [(hseg_row hv).1] + +/-- `gEx` of a straight excursion. -/ +private lemma gEx_hseg (r : ℤ) (a b : Fin 3) : gEx r (hseg r a b) = none := by + unfold gEx; rw [filter_hseg] + +/-- `gEx` recovers the columns where the inner excursion starts and ends. -/ +private lemma gEx_mid (r : ℤ) (a b c d : Fin 3) (X : List (ℤ × ℤ)) (hXne : X ≠ []) + (hX : ∀ v ∈ X, v.2 ≠ r) : + gEx r (hseg r a b ++ X ++ hseg r c d) = + some (colOf (X.head hXne).1, colOf (X.getLast hXne).1) := by + have : (hseg r a b ++ X ++ hseg r c d).filter (fun v => decide (v.2 ≠ r)) = X := by + rw [List.filter_append, List.filter_append, filter_hseg, filter_hseg, + List.filter_eq_self.2 (fun v hv => by simpa using hX v hv)] + simp + obtain ⟨x, xs, rfl⟩ := List.exists_cons_of_ne_nil hXne + unfold gEx; rw [this]; rfl + +/-- The recursion for excursions in a half-strip. -/ +private lemma exc_card (σ : Bool) (r : ℤ) (S : Finset (Fin 3)) (c1 c2 : Fin 3) (ℓ : ℕ) : + (exc σ r S c1 c2 ℓ).card = + (if ℓ + 1 = (cols c1 c2).length ∧ ∀ c ∈ cols c1 c2, c ∉ S then 1 else 0) + + ∑ c1' : Fin 3, ∑ c2' : Fin 3, + if okSeg S c1 c1' c2' c2 ∧ (cols c1 c1').length + (cols c2' c2).length ≤ ℓ then + (exc σ (r + dir σ) ∅ c1' c2' (ℓ - (cols c1 c1').length - (cols c2' c2).length)).card + else 0 := by + let T : Option (Fin 3 × Fin 3) → Finset (List (ℤ × ℤ)) := fun + | none => if ℓ + 1 = (cols c1 c2).length ∧ ∀ c ∈ cols c1 c2, c ∉ S then {[]} else ∅ + | some (c1', c2') => + if okSeg S c1 c1' c2' c2 ∧ (cols c1 c1').length + (cols c2' c2).length ≤ ℓ then + exc σ (r + dir σ) ∅ c1' c2' (ℓ - (cols c1 c1').length - (cols c2' c2).length) else ∅ + let F : Option (Fin 3 × Fin 3) → List (ℤ × ℤ) → List (ℤ × ℤ) := fun + | none, _ => hseg r c1 c2 + | some (c1', c2'), X => hseg r c1 c1' ++ X ++ hseg r c2' c2 + rw [card_eq_sum (exc σ r S c1 c2 ℓ) Finset.univ T F (gEx r) ?_ ?_ ?_] + · rw [Fintype.sum_option, Fintype.sum_prod_type] + congr 1 + · simp only [T]; split_ifs <;> simp + · refine Finset.sum_congr rfl fun c1' _ => Finset.sum_congr rfl fun c2' _ => ?_ + simp only [T]; split_ifs <;> simp + · rintro (_ | ⟨c1', c2'⟩) - x hx y hy hxy + · simp only [T] at hx hy; split_ifs at hx hy <;> simp_all + · simp only [F] at hxy + exact List.append_cancel_left (List.append_cancel_right hxy) + · rintro (_ | ⟨c1', c2'⟩) - x hx + · exact gEx_hseg r c1 c2 + · simp only [T] at hx + split_ifs at hx with h + · obtain ⟨hl, hh, -, ht, -, hp⟩ := mem_exc.1 hx + have hne : x ≠ [] := by rintro rfl; simp at hl + simp only [F] + rw [gEx_mid r _ _ _ _ x hne fun v hv => (onSide_step (hp v hv).2.1).2] + rw [List.head?_eq_some_head hne, Option.some.injEq] at hh + rw [List.getLast?_eq_some_getLast hne, Option.some.injEq] at ht + rw [hh, ht, colOf_ci, colOf_ci] + · simp at hx + · intro l + constructor + · intro hl + rcases exc_decomp hl with ⟨rfl, h1, h2⟩ | ⟨c1', c2', X, hok, hlen, hX, rfl⟩ + · refine ⟨none, Finset.mem_univ _, [], ?_, rfl⟩ + simp only [T]; rw [if_pos ⟨h1, h2⟩]; exact Finset.mem_singleton_self _ + · refine ⟨some (c1', c2'), Finset.mem_univ _, X, ?_, rfl⟩ + simp only [T]; rw [if_pos ⟨hok, hlen⟩]; exact hX + · rintro ⟨i, -, x, hx, rfl⟩ + rcases i with _ | ⟨c1', c2'⟩ + · simp only [T] at hx; split_ifs at hx with h + · exact exc_build1 h.1 h.2 + · simp at hx + · simp only [T] at hx; split_ifs at hx with h + · exact exc_build2 h.1 h.2 hx + · simp at hx + +/-! ### The excursion numbers -/ + +/-- `pq ℓ = (p ℓ, q ℓ)`: the numbers of excursions between adjacent columns, resp. between +the two boundary columns. -/ +private def pq : ℕ → ℕ × ℕ + | 0 => (0, 0) + | 1 => (1, 0) + | 2 => (0, 1) + | n + 3 => ((pq (n + 1)).1 + (pq n).2, 2 * (pq n).1 + (pq (n + 1)).2) + +/-- The number of excursions of `ℓ` steps from column `c1` to column `c2`. -/ +private def Ef (c1 c2 : Fin 3) (ℓ : ℕ) : ℕ := + if c1 = c2 then (if ℓ = 0 then 1 else 0) + else if (c1 = 0 ∧ c2 = 2) ∨ (c1 = 2 ∧ c2 = 0) then (pq ℓ).2 else (pq ℓ).1 + +/-- `Ef` satisfies the recursion of `exc_card`. -/ +private lemma Ef_rec (c1 c2 : Fin 3) (ℓ : ℕ) : + Ef c1 c2 ℓ = + (if ℓ + 1 = (cols c1 c2).length ∧ ∀ c ∈ cols c1 c2, c ∉ (∅ : Finset (Fin 3)) then 1 else 0) + + ∑ c1' : Fin 3, ∑ c2' : Fin 3, + if okSeg ∅ c1 c1' c2' c2 ∧ (cols c1 c1').length + (cols c2' c2).length ≤ ℓ then + Ef c1' c2' (ℓ - (cols c1 c1').length - (cols c2' c2).length) + else 0 := by + rcases ℓ with _ | _ | _ | n + all_goals + fin_cases c1 <;> fin_cases c2 <;> + simp (config := {decide := true}) [Fin.sum_univ_three, okSeg, cols, Ef, pq] + all_goals ring + +/-- The number of excursions (avoiding nothing) is `Ef`. -/ +private lemma exc_Ef (ℓ : ℕ) : + ∀ (σ : Bool) (r : ℤ) (c1 c2 : Fin 3), (exc σ r ∅ c1 c2 ℓ).card = Ef c1 c2 ℓ := by + induction ℓ using Nat.strong_induction_on with + | _ ℓ ih => + intro σ r c1 c2 + rw [exc_card, Ef_rec] + congr 1 + refine Finset.sum_congr rfl fun c1' _ => Finset.sum_congr rfl fun c2' _ => ?_ + split_ifs with h + · exact ih _ (by have := cols_length_pos c1 c1'; have := cols_length_pos c2' c2; omega) _ _ _ _ + · rfl + +/-- The number of excursions ending at column `1` whose vertices in the base row avoid +column `0`. -/ +private def E0 (c : Fin 3) (ℓ : ℕ) : ℕ := + if c = 1 then (if ℓ = 0 then 1 else 0) + else if c = 2 then (if ℓ = 1 then 1 else 0) + (if 2 ≤ ℓ then (pq (ℓ - 2)).1 else 0) else 0 + +/-- The number of excursions ending at column `1` that avoid column `0` of the base row. -/ +private lemma exc_E0 (σ : Bool) (r : ℤ) (c : Fin 3) (ℓ : ℕ) : + (exc σ r {0} c 1 ℓ).card = E0 c ℓ := by + rw [exc_card] + simp only [exc_Ef] + rcases ℓ with _ | _ | n + all_goals + fin_cases c <;> simp (config := {decide := true}) [Fin.sum_univ_three, okSeg, cols, Ef, E0] + + +/-! ### Closed walks as walks from the origin to a neighbour of the origin -/ + +/-- Column `0`. -/ +private lemma ci_zero : ci 0 = 0 := rfl +/-- Column `1`. -/ +private lemma ci_one : ci 1 = 1 := rfl +/-- Column `2`. -/ +private lemma ci_two : ci 2 = 2 := rfl + +/-- Self-avoiding walks of `j` steps in the strip from the origin to `u`. -/ +private def Qset (u : ℤ × ℤ) (j : ℕ) : Finset (List (ℤ × ℤ)) := + (walksFrom 0 j).filter fun Q => Q.getLast? = some u ∧ Q.Nodup ∧ ∀ v ∈ Q, InStrip v + +/-- Membership in `Qset`. -/ +private lemma mem_Qset {u : ℤ × ℤ} {j : ℕ} {Q : List (ℤ × ℤ)} : + Q ∈ Qset u j ↔ Q.length = j + 1 ∧ Q.head? = some 0 ∧ Q.IsChain Adj ∧ + Q.getLast? = some u ∧ Q.Nodup ∧ ∀ v ∈ Q, InStrip v := by + simp only [Qset, Finset.mem_filter, mem_walksFrom, and_assoc] + +/-- The three neighbours of the origin in the strip. -/ +private def nb : Fin 3 → ℤ × ℤ := ![(1, 0), (0, 1), (0, -1)] + +/-- Every neighbour of the origin in the strip is one of `nb`. -/ +private lemma nb_of_adj {u : ℤ × ℤ} (h : Adj u 0) (hs : InStrip u) : ∃ i, u = nb i := by + rw [adj_iff] at h + unfold InStrip at hs + obtain ⟨u1, u2⟩ := u + simp only [Prod.fst_zero, Prod.snd_zero] at h hs + rcases h with ⟨h1, h2⟩ | ⟨h1, h2⟩ | ⟨h1, h2⟩ | ⟨h1, h2⟩ + · omega + · exact ⟨0, by simp [nb]; constructor <;> omega⟩ + · exact ⟨2, by simp [nb]; constructor <;> omega⟩ + · exact ⟨1, by simp [nb]; constructor <;> omega⟩ + +/-- The `nb i` are neighbours of the origin. -/ +private lemma adj_nb (i : Fin 3) : Adj (nb i) 0 := by + fin_cases i <;> simp [nb, adj_iff] + +/-- The origin lies in the strip. -/ +private lemma instrip_zero : InStrip (0 : ℤ × ℤ) := by simp [InStrip] + +/-- A duplicate-free list with at least two entries has distinct ends. -/ +private lemma head_ne_getLast {l : List (ℤ × ℤ)} (hn : l.Nodup) (h2 : 2 ≤ l.length) (hne : l ≠ []) : + l.head hne ≠ l.getLast hne := by + match l, hn, h2, hne with + | a :: b :: t, hn, _, _ => + simp only [List.head_cons, List.getLast_cons_cons] + intro h + have hm : (b :: t).getLast (List.cons_ne_nil _ _) ∈ b :: t := List.getLast_mem _ + rw [← h] at hm + exact (List.nodup_cons.1 hn).1 hm + +/-- `GLs [0] 0 k` counts walks from the origin to one of its neighbours. -/ +private lemma GLs_Q (k : ℕ) (hk : 2 ≤ k) : + GLs [0] 0 k = ∑ i : Fin 3, (Qset (nb i) (k - 1)).card := by + unfold GLs + refine card_eq_sum _ Finset.univ (fun i => Qset (nb i) (k - 1)) (fun _ Q => Q ++ [0]) + (fun W => if W.dropLast.getLast? = some (nb 0) then 0 + else if W.dropLast.getLast? = some (nb 1) then 1 else 2) ?_ ?_ ?_ + · intro i _ x _ y _ h + exact List.append_cancel_right h + · intro i _ Q hQ + obtain ⟨-, -, -, hl, -⟩ := mem_Qset.1 hQ + simp only [List.dropLast_concat, hl] + fin_cases i <;> simp [nb] + · intro W + simp only [Finset.mem_filter, mem_walksFrom, Finset.mem_univ, true_and] + constructor + · rintro ⟨⟨hlen, hhead, hc⟩, hstrip, hlast, havoid, hnd⟩ + obtain ⟨W', rfl⟩ : ∃ W', W = 0 :: W' := by + match W, hhead with + | a :: W', hhead => simp at hhead; exact ⟨W', by rw [hhead]⟩ + have hW'ne : W' ≠ [] := by rintro rfl; simp at hlen; omega + have hW'last : W'.getLast hW'ne = 0 := by + rw [List.getLast?_cons, List.getLast?_eq_some_getLast hW'ne] at hlast + simpa using hlast + have hW' : W' = W'.dropLast ++ [0] := by + rw [← hW'last]; exact (List.dropLast_append_getLast hW'ne).symm + set W'' := W'.dropLast with hW'' + simp only [List.tail_cons] at hstrip havoid hnd + rw [← hW''] at havoid hnd + have hW''ne : W'' ≠ [] := by + intro h + rw [h] at hW' + rw [hW'] at hlen; simp at hlen; omega + have hWeq : 0 :: W' = (0 :: W'') ++ [0] := by rw [hW']; simp + rw [hWeq] at hc hlen + have hu : Adj ((0 :: W'').getLast (List.cons_ne_nil _ _)) 0 := + adj_junction (L2 := [0]) hc (List.cons_ne_nil _ _) (List.cons_ne_nil _ _) + have hus : InStrip ((0 :: W'').getLast (List.cons_ne_nil _ _)) := by + rw [List.getLast_cons hW''ne] + exact hstrip _ (by rw [hW']; exact List.mem_append_left _ (List.getLast_mem _)) + obtain ⟨i, hi⟩ := nb_of_adj hu hus + refine ⟨i, 0 :: W'', ?_, hWeq.symm⟩ + rw [mem_Qset] + refine ⟨by simp at hlen ⊢; omega, rfl, hc.left_of_append, ?_, ?_, ?_⟩ + · rw [List.getLast?_eq_some_getLast (List.cons_ne_nil _ _), hi] + · exact List.nodup_cons.2 ⟨fun h => havoid 0 h (by simp), hnd⟩ + · intro v hv + rcases List.mem_cons.1 hv with rfl | hv + · exact instrip_zero + · exact hstrip v (by rw [hW']; exact List.mem_append_left _ hv) + · rintro ⟨i, Q, hQ, rfl⟩ + obtain ⟨hlen, hhead, hc, hlast, hn, hs⟩ := mem_Qset.1 hQ + obtain ⟨Q', rfl⟩ : ∃ Q', Q = 0 :: Q' := by + match Q, hhead with + | a :: Q', hhead => simp at hhead; exact ⟨Q', by rw [hhead]⟩ + refine ⟨⟨by simp at hlen ⊢; omega, by simp, ?_⟩, ?_, List.getLast?_concat, ?_, ?_⟩ + · refine List.IsChain.append hc (List.isChain_singleton _) ?_ + intro x hx y hy + rw [hlast, Option.mem_def, Option.some.injEq] at hx + simp only [List.head?_cons, Option.mem_def, Option.some.injEq] at hy + rw [← hx, ← hy]; exact adj_nb i + · intro v hv + simp only [List.cons_append, List.tail_cons, List.mem_append, List.mem_singleton] at hv + rcases hv with hv | rfl + · exact hs v (List.mem_cons_of_mem _ hv) + · exact instrip_zero + · simp only [List.cons_append, List.tail_cons, List.dropLast_concat] + intro v hv h0 + simp only [List.mem_singleton] at h0 + subst h0 + exact (List.nodup_cons.1 hn).1 hv + · simp only [List.cons_append, List.tail_cons, List.dropLast_concat] + exact (List.nodup_cons.1 hn).2 + +/-- `near σ r` is the closed half-plane on side `!σ` of row `r`. -/ +private lemma near_true_iff (σ : Bool) (r : ℤ) (v : ℤ × ℤ) : near σ r v = true ↔ onSide (!σ) r v := by + cases σ <;> simp [near, onSide] + +/-- Vertices beyond row `dir σ` on side `σ` are not `near`. -/ +private lemma near_false_of {σ : Bool} {v : ℤ × ℤ} (h : onSide σ (dir σ) v) : near σ 0 v = false := by + cases σ <;> simp [near, onSide, dir] at h ⊢ <;> omega + +/-- Vertices that are not `near σ 0` lie beyond row `dir σ` on side `σ`. -/ +private lemma onSide_of_near_false {σ : Bool} {v : ℤ × ℤ} (h : near σ 0 v = false) : + onSide σ (dir σ) v := by + cases σ <;> simp [near, onSide, dir] at h ⊢ <;> omega + +/-- Recovering a split `A ++ X` along a predicate. -/ +private lemma split_take {q : ℤ × ℤ → Bool} {A X : List (ℤ × ℤ)} (hA : ∀ v ∈ A, q v = true) + (hX : ∀ v ∈ X.head?, q v = false) : + (A ++ X).takeWhile q = A ∧ (A ++ X).dropWhile q = X := by + constructor + · rw [List.takeWhile_append_of_pos hA] + cases X with + | nil => simp + | cons x xs => rw [List.takeWhile_cons_of_neg (by simp [hX x (by simp)])]; simp + · rw [List.dropWhile_append_of_pos hA] + cases X with + | nil => simp + | cons x xs => rw [List.dropWhile_cons_of_neg (by simp [hX x (by simp)])] + +/-- A split `A ++ X` along a predicate is unique. -/ +private lemma split_inj {q : ℤ × ℤ → Bool} {A X A' X' : List (ℤ × ℤ)} (hA : ∀ v ∈ A, q v = true) + (hX : ∀ v ∈ X.head?, q v = false) (hA' : ∀ v ∈ A', q v = true) + (hX' : ∀ v ∈ X'.head?, q v = false) (h : A ++ X = A' ++ X') : A = A' ∧ X = X' := by + have h1 := split_take hA hX + have h2 := split_take hA' hX' + rw [h] at h1 + exact ⟨h1.1.symm.trans h2.1, h1.2.symm.trans h2.2⟩ + +/-- Excursions on side `!σ` of row `0` are `near σ 0`. -/ +private lemma exc_near {σ : Bool} {S : Finset (Fin 3)} {c1 c2 : Fin 3} {ℓ : ℕ} {A : List (ℤ × ℤ)} + (h : A ∈ exc (!σ) 0 S c1 c2 ℓ) : ∀ v ∈ A, near σ 0 v = true := fun v hv => + (near_true_iff σ 0 v).2 ((mem_exc.1 h).2.2.2.2.2 v hv).2.1 + +/-- Excursions beyond row `dir σ` on side `σ` are not `near σ 0`. -/ +private lemma exc_far {σ : Bool} {S : Finset (Fin 3)} {c1 c2 : Fin 3} {ℓ : ℕ} {X : List (ℤ × ℤ)} + (h : X ∈ exc σ (dir σ) S c1 c2 ℓ) : ∀ v ∈ X, near σ 0 v = false := fun v hv => + near_false_of ((mem_exc.1 h).2.2.2.2.2 v hv).2.1 + +/-- A property of all entries holds for the head. -/ +private lemma head?_mem_of {l : List (ℤ × ℤ)} {P : ℤ × ℤ → Prop} (h : ∀ v ∈ l, P v) : + ∀ v ∈ l.head?, P v := fun v hv => h v (List.mem_of_mem_head? hv) + +/-- A vertical unit step from row `0`. -/ +private lemma adj_vert0 (σ : Bool) (c : ℤ) : Adj (c, 0) (c, dir σ) := by + simpa using adj_vert σ c 0 + +/-- Walks from the origin to `(0, ±1)`: an excursion on the far side of the origin's row, +followed by an excursion on the near side. -/ +private lemma Q1_card (σ : Bool) (j : ℕ) (hj : 2 ≤ j) : + (Qset (0, dir σ) j).card = ∑ c : Fin 3, ∑ ℓ ∈ Finset.range j, + (exc (!σ) 0 ∅ 0 c ℓ).card * (exc σ (dir σ) ∅ c 0 (j - 1 - ℓ)).card := by + rw [card_eq_sum (Qset (0, dir σ) j) (Finset.univ ×ˢ Finset.range j) + (fun p => exc (!σ) 0 ∅ 0 p.1 p.2 ×ˢ exc σ (dir σ) ∅ p.1 0 (j - 1 - p.2)) + (fun _ x => x.1 ++ x.2) + (fun Q => (colOf (((Q.takeWhile (near σ 0)).getLast?).getD 0).1, + (Q.takeWhile (near σ 0)).length - 1)) ?_ ?_ ?_] + · rw [Finset.sum_product]; simp only [Finset.card_product] + · rintro ⟨c, ℓ⟩ - ⟨A, X⟩ hAX ⟨A', X'⟩ hAX' h + simp only [Finset.mem_product] at hAX hAX' h + have := split_inj (exc_near hAX.1) (head?_mem_of (exc_far hAX.2)) (exc_near hAX'.1) + (head?_mem_of (exc_far hAX'.2)) h + rw [this.1, this.2] + · rintro ⟨c, ℓ⟩ - ⟨A, X⟩ hAX + simp only [Finset.mem_product] at hAX + simp only + rw [(split_take (exc_near hAX.1) (head?_mem_of (exc_far hAX.2))).1] + obtain ⟨hl, -, -, ht, -⟩ := mem_exc.1 hAX.1 + rw [ht, hl]; simp [colOf_ci] + · intro Q + constructor + · intro hQ + obtain ⟨hlen, hhead, hc, hlast, hn, hs⟩ := mem_Qset.1 hQ + obtain ⟨P, rfl⟩ : ∃ P, Q = 0 :: P := by + match Q, hhead with + | a :: P, hhead => simp at hhead; exact ⟨P, by rw [hhead]⟩ + have hPlen : P.length = j := by simpa using hlen + have hPne : P ≠ [] := by rintro rfl; simp at hPlen; omega + have hP0 : (0 : ℤ × ℤ) ∉ P := (List.nodup_cons.1 hn).1 + have hPn : P.Nodup := (List.nodup_cons.1 hn).2 + have hPc : P.IsChain Adj := hc.tail + have hPs : ∀ v ∈ P, InStrip v := fun v hv => hs v (List.mem_cons_of_mem _ hv) + have hPlast : P.getLast hPne = (0, dir σ) := by + rw [List.getLast?_cons, List.getLast?_eq_some_getLast hPne] at hlast; simpa using hlast + have hPhead : near σ 0 (P.head hPne) = true := by + have hadj : Adj 0 (P.head hPne) := by + obtain ⟨b, P', hP'⟩ := List.exists_cons_of_ne_nil hPne + subst hP' + exact (List.isChain_cons_cons.1 hc).1 + obtain ⟨i, hi⟩ := nb_of_adj (adj_symm hadj) (hPs _ (List.head_mem _)) + have hne := head_ne_getLast hPn (by omega) hPne + rw [hPlast, hi] at hne + rw [hi] + fin_cases i <;> cases σ <;> simp [nb, near, dir] at hne ⊢ + obtain ⟨A, X, hPAX, hA, hX⟩ := once_split (near σ 0) 0 (dir σ) + (fun a b hab ha hb => by simpa using near_hq σ 0 a b hab ha hb) hPc hPn hPs + ⟨0, le_refl _, by norm_num, Or.inl hP0⟩ + (fun v hv => by + rw [List.head?_eq_some_head hPne, Option.mem_def, Option.some.injEq] at hv + rw [← hv]; exact hPhead) + (fun v hv => by + rw [List.getLast?_eq_some_getLast hPne, Option.mem_def, Option.some.injEq] at hv + rw [← hv, hPlast]; cases σ <;> simp [near, dir]) + have hAne : A ≠ [] := by + have hm : P.head hPne ∈ A ++ X := by rw [← hPAX]; exact List.head_mem hPne + rcases List.mem_append.1 hm with h | h + · exact List.ne_nil_of_mem h + · have := hX _ h; rw [hPhead] at this; simp at this + have hXne : X ≠ [] := by + have hm : P.getLast hPne ∈ A ++ X := by rw [← hPAX]; exact List.getLast_mem hPne + rcases List.mem_append.1 hm with h | h + · have := hA _ h; rw [hPlast] at this; cases σ <;> simp [near, dir] at this + · exact List.ne_nil_of_mem h + subst hPAX + have j1 : Adj (A.getLast hAne) (X.head hXne) := adj_junction hPc hAne hXne + obtain ⟨e1, e1a, e1b⟩ := near_hq σ 0 _ _ j1 (hA _ (List.getLast_mem _)) + (hX _ (List.head_mem _)) + have hs1 := hPs _ (List.mem_append_left _ (List.getLast_mem hAne)) + unfold InStrip at hs1 + set c := colOf (A.getLast hAne).1 with hcdef + have hAl : A.getLast hAne = (ci c, 0) := Prod.ext (by rw [hcdef, ci_colOf hs1.1 hs1.2]) e1a + have hXh : X.head hXne = (ci c, dir σ) := + Prod.ext (by rw [← e1, hcdef, ci_colOf hs1.1 hs1.2]) (by simpa using e1b) + have hlenAX : A.length + X.length = j := by simpa using hPlen + have hXlen : 1 ≤ X.length := List.length_pos_iff.2 hXne + refine ⟨(c, A.length), Finset.mem_product.2 ⟨Finset.mem_univ _, + Finset.mem_range.2 (by omega)⟩, (0 :: A, X), Finset.mem_product.2 ⟨?_, ?_⟩, by simp⟩ + · rw [mem_exc] + refine ⟨by simp, by rw [List.head?_cons, ci_zero]; rfl, ?_, ?_, ?_, ?_⟩ + · have : ((0 :: A) ++ X).IsChain Adj := by simpa using hc + exact this.left_of_append + · rw [List.getLast?_eq_some_getLast (List.cons_ne_nil _ _), List.getLast_cons hAne, hAl] + · exact List.nodup_cons.2 ⟨fun h => hP0 (List.mem_append_left _ h), + (List.nodup_append.1 hPn).1⟩ + · intro v hv + rcases List.mem_cons.1 hv with rfl | hv + · exact ⟨instrip_zero, by cases σ <;> simp [onSide], by simp⟩ + · exact ⟨hPs v (List.mem_append_left _ hv), (near_true_iff σ 0 v).1 (hA v hv), by simp⟩ + · rw [mem_exc] + refine ⟨by dsimp only; omega, by rw [List.head?_eq_some_head hXne, hXh], hPc.right_of_append, ?_, + (List.nodup_append.1 hPn).2.1, fun v hv => ⟨hPs v (List.mem_append_right _ hv), + onSide_of_near_false (hX v hv), by simp⟩⟩ + rw [List.getLast?_eq_some_getLast hXne, ← List.getLast_append_of_ne_nil hPne hXne, + hPlast, ci_zero] + · rintro ⟨⟨c, ℓ⟩, hp, ⟨A, X⟩, hAX, rfl⟩ + simp only [Finset.mem_product, Finset.mem_univ, true_and, Finset.mem_range] at hp hAX + obtain ⟨hAl, hAh, hAc, hAt, hAn, hAp⟩ := mem_exc.1 hAX.1 + obtain ⟨hXl, hXh, hXc, hXt, hXn, hXp⟩ := mem_exc.1 hAX.2 + have hAne : A ≠ [] := by rintro rfl; simp at hAl + have hXne : X ≠ [] := by rintro rfl; simp at hXl + rw [mem_Qset] + refine ⟨by simp only [List.length_append]; omega, ?_, ?_, ?_, ?_, ?_⟩ + · rw [List.head?_append_of_ne_nil _ hAne, hAh, ci_zero]; rfl + · refine List.IsChain.append hAc hXc fun x hx y hy => ?_ + rw [hAt, Option.mem_def, Option.some.injEq] at hx + rw [hXh, Option.mem_def, Option.some.injEq] at hy + rw [← hx, ← hy]; exact adj_vert0 σ _ + · rw [List.getLast?_append_of_ne_nil _ hXne, hXt, ci_zero] + · refine List.nodup_append.2 ⟨hAn, hXn, fun a ha b hb hab => ?_⟩ + have h1 := exc_near hAX.1 a ha + have h2 := exc_far hAX.2 b hb + rw [hab, h2] at h1; simp at h1 + · intro v hv + rcases List.mem_append.1 hv with hv | hv + · exact (hAp v hv).1 + · exact (hXp v hv).1 + + +/-- The side of the origin's row on which the second vertex of `Q` lies (`true`: above). -/ +private def firstSide (Q : List (ℤ × ℤ)) : Bool := decide (0 < ((Q.tail.head?).getD 0).2) + +/-- `firstSide` of a walk starting `0, (0, dir σ), …`. -/ +private lemma firstSide_eq {σ : Bool} {c : Fin 3} {ℓ : ℕ} {A : List (ℤ × ℤ)} + (hA : A ∈ exc σ (dir σ) ∅ 0 c ℓ) (X : List (ℤ × ℤ)) : firstSide (0 :: (A ++ X)) = σ := by + obtain ⟨hAl, hAh, -⟩ := mem_exc.1 hA + have hAne : A ≠ [] := by rintro rfl; simp at hAl + unfold firstSide + rw [List.tail_cons, List.head?_append_of_ne_nil _ hAne, hAh] + cases σ <;> simp [dir] + +/-- Walks from the origin to `(1, 0)`: a first step to `(0, ±1)`, an excursion on that side of +the origin's row, and an excursion on the other side that avoids the origin. -/ +private lemma Q10_card (j : ℕ) (hj : 2 ≤ j) : + (Qset (1, 0) j).card = ∑ σ : Bool, ∑ c : Fin 3, ∑ ℓ ∈ Finset.range (j - 1), + (exc σ (dir σ) ∅ 0 c ℓ).card * (exc (!σ) 0 {0} c 1 (j - 2 - ℓ)).card := by + rw [card_eq_sum (Qset (1, 0) j) ((Finset.univ ×ˢ Finset.univ) ×ˢ Finset.range (j - 1)) + (fun p => exc p.1.1 (dir p.1.1) ∅ 0 p.1.2 p.2 ×ˢ exc (!p.1.1) 0 {0} p.1.2 1 (j - 2 - p.2)) + (fun _ x => 0 :: (x.1 ++ x.2)) + (fun Q => ((firstSide Q, colOf ((((Q.tail.takeWhile + (fun v => !near (firstSide Q) 0 v)).getLast?).getD 0).1)), + (Q.tail.takeWhile (fun v => !near (firstSide Q) 0 v)).length - 1)) ?_ ?_ ?_] + · rw [Finset.sum_product, Finset.sum_product]; simp only [Finset.card_product] + · rintro ⟨⟨σ, c⟩, ℓ⟩ - ⟨A, X⟩ hAX ⟨A', X'⟩ hAX' h + simp only [Finset.mem_product] at hAX hAX' + simp only [List.cons.injEq, true_and] at h + have := split_inj (q := fun v => !near σ 0 v) + (fun v hv => by simp [exc_far hAX.1 v hv]) + (head?_mem_of (fun v hv => by simp [exc_near hAX.2 v hv])) + (fun v hv => by simp [exc_far hAX'.1 v hv]) + (head?_mem_of (fun v hv => by simp [exc_near hAX'.2 v hv])) h + rw [this.1, this.2] + · rintro ⟨⟨σ, c⟩, ℓ⟩ - ⟨A, X⟩ hAX + simp only [Finset.mem_product] at hAX + simp only + rw [firstSide_eq hAX.1 X, List.tail_cons, + (split_take (q := fun v => !near σ 0 v) (fun v hv => by simp [exc_far hAX.1 v hv]) + (head?_mem_of (fun v hv => by simp [exc_near hAX.2 v hv]))).1] + obtain ⟨hl, -, -, ht, -⟩ := mem_exc.1 hAX.1 + rw [ht, hl]; simp [colOf_ci] + · intro Q + constructor + · intro hQ + obtain ⟨hlen, hhead, hc, hlast, hn, hs⟩ := mem_Qset.1 hQ + obtain ⟨P, rfl⟩ : ∃ P, Q = 0 :: P := by + match Q, hhead with + | a :: P, hhead => simp at hhead; exact ⟨P, by rw [hhead]⟩ + have hPlen : P.length = j := by simpa using hlen + have hPne : P ≠ [] := by rintro rfl; simp at hPlen; omega + have hP0 : (0 : ℤ × ℤ) ∉ P := (List.nodup_cons.1 hn).1 + have hPn : P.Nodup := (List.nodup_cons.1 hn).2 + have hPc : P.IsChain Adj := hc.tail + have hPs : ∀ v ∈ P, InStrip v := fun v hv => hs v (List.mem_cons_of_mem _ hv) + have hPlast : P.getLast hPne = (1, 0) := by + rw [List.getLast?_cons, List.getLast?_eq_some_getLast hPne] at hlast; simpa using hlast + obtain ⟨σ, hσ⟩ : ∃ σ : Bool, P.head hPne = (0, dir σ) := by + have hadj : Adj 0 (P.head hPne) := by + obtain ⟨b, P', hP'⟩ := List.exists_cons_of_ne_nil hPne + subst hP' + exact (List.isChain_cons_cons.1 hc).1 + obtain ⟨i, hi⟩ := nb_of_adj (adj_symm hadj) (hPs _ (List.head_mem _)) + have hne := head_ne_getLast hPn (by omega) hPne + rw [hPlast, hi] at hne + fin_cases i + · simp [nb] at hne + · exact ⟨true, by rw [hi]; simp [nb, dir]⟩ + · exact ⟨false, by rw [hi]; simp [nb, dir]⟩ + obtain ⟨A, X, hPAX, hA, hX⟩ := once_split (fun v => !near σ 0 v) (dir σ) 0 + (fun a b hab ha hb => by + have := near_hq σ 0 b a (adj_symm hab) (by simpa using hb) (by simpa using ha) + exact ⟨this.1.symm, by rw [this.2.2, zero_add], this.2.1⟩) + hPc hPn hPs ⟨0, le_refl _, by norm_num, Or.inr fun h => hP0 h⟩ + (fun v hv => by + rw [List.head?_eq_some_head hPne, Option.mem_def, Option.some.injEq] at hv + rw [← hv, hσ]; cases σ <;> simp [near, dir]) + (fun v hv => by + rw [List.getLast?_eq_some_getLast hPne, Option.mem_def, Option.some.injEq] at hv + rw [← hv, hPlast]; cases σ <;> simp [near]) + have hAne : A ≠ [] := by + have hm : P.head hPne ∈ A ++ X := by rw [← hPAX]; exact List.head_mem hPne + rcases List.mem_append.1 hm with h | h + · exact List.ne_nil_of_mem h + · have := hX _ h; rw [hσ] at this; cases σ <;> simp [near, dir] at this + have hXne : X ≠ [] := by + have hm : P.getLast hPne ∈ A ++ X := by rw [← hPAX]; exact List.getLast_mem hPne + rcases List.mem_append.1 hm with h | h + · have := hA _ h; rw [hPlast] at this; cases σ <;> simp [near] at this + · exact List.ne_nil_of_mem h + subst hPAX + have j1 : Adj (A.getLast hAne) (X.head hXne) := adj_junction hPc hAne hXne + obtain ⟨e1, e1a, e1b⟩ := near_hq σ 0 _ _ (adj_symm j1) + (by simpa using hX _ (List.head_mem hXne)) (by simpa using hA _ (List.getLast_mem hAne)) + have hs1 := hPs _ (List.mem_append_left _ (List.getLast_mem hAne)) + unfold InStrip at hs1 + set c := colOf (A.getLast hAne).1 with hcdef + have hAl : A.getLast hAne = (ci c, dir σ) := + Prod.ext (by rw [hcdef, ci_colOf hs1.1 hs1.2]) (by rw [e1b, zero_add]) + have hXh : X.head hXne = (ci c, 0) := + Prod.ext (by rw [e1, hcdef, ci_colOf hs1.1 hs1.2]) e1a + have hAh : A.head hAne = (ci 0, dir σ) := by + rw [ci_zero, ← hσ, List.head_append_of_ne_nil hAne] + have hlenAX : A.length + X.length = j := by simpa using hPlen + have hAlen : 1 ≤ A.length := List.length_pos_iff.2 hAne + have hXlen : 1 ≤ X.length := List.length_pos_iff.2 hXne + refine ⟨((σ, c), A.length - 1), Finset.mem_product.2 ⟨Finset.mem_product.2 + ⟨Finset.mem_univ _, Finset.mem_univ _⟩, Finset.mem_range.2 (by omega)⟩, (A, X), + Finset.mem_product.2 ⟨?_, ?_⟩, rfl⟩ + · rw [mem_exc] + refine ⟨by dsimp only; omega, by rw [List.head?_eq_some_head hAne, hAh], + hPc.left_of_append, by rw [List.getLast?_eq_some_getLast hAne, hAl], + (List.nodup_append.1 hPn).1, fun v hv => ⟨hPs v (List.mem_append_left _ hv), + onSide_of_near_false (by simpa using hA v hv), by simp⟩⟩ + · rw [mem_exc] + refine ⟨by dsimp only; omega, by rw [List.head?_eq_some_head hXne, hXh], + hPc.right_of_append, ?_, (List.nodup_append.1 hPn).2.1, fun v hv => + ⟨hPs v (List.mem_append_right _ hv), (near_true_iff σ 0 v).1 (by simpa using hX v hv), + ?_⟩⟩ + · rw [List.getLast?_eq_some_getLast hXne, ← List.getLast_append_of_ne_nil hPne hXne, + hPlast, ci_one] + · intro c' hc' he + rw [Finset.mem_singleton] at hc' + subst hc' + rw [ci_zero] at he + subst he + exact hP0 (List.mem_append_right _ hv) + · rintro ⟨⟨⟨σ, c⟩, ℓ⟩, hp, ⟨A, X⟩, hAX, rfl⟩ + simp only [Finset.mem_product, Finset.mem_univ, true_and, Finset.mem_range] at hp hAX + obtain ⟨hAl, hAh, hAc, hAt, hAn, hAp⟩ := mem_exc.1 hAX.1 + obtain ⟨hXl, hXh, hXc, hXt, hXn, hXp⟩ := mem_exc.1 hAX.2 + have hAne : A ≠ [] := by rintro rfl; simp at hAl + have hXne : X ≠ [] := by rintro rfl; simp at hXl + have hAX0 : (0 : ℤ × ℤ) ∉ A ++ X := by + intro h0 + rcases List.mem_append.1 h0 with h | h + · have := exc_far hAX.1 _ h + cases σ <;> simp [near] at this + · exact (hXp _ h).2.2 0 (Finset.mem_singleton_self _) (by rw [ci_zero]; rfl) + rw [mem_Qset] + refine ⟨by simp only [List.length_cons, List.length_append]; omega, rfl, ?_, ?_, ?_, ?_⟩ + · have hc2 : (A ++ X).IsChain Adj := by + refine List.IsChain.append hAc hXc fun x hx y hy => ?_ + rw [hAt, Option.mem_def, Option.some.injEq] at hx + rw [hXh, Option.mem_def, Option.some.injEq] at hy + rw [← hx, ← hy]; exact adj_symm (adj_vert0 σ _) + have : ([0] ++ (A ++ X)).IsChain Adj := by + refine List.IsChain.append (List.isChain_singleton _) hc2 fun x hx y hy => ?_ + simp only [List.getLast?_singleton, Option.mem_def, Option.some.injEq] at hx + rw [List.head?_append_of_ne_nil _ hAne, hAh, Option.mem_def, Option.some.injEq] at hy + rw [← hx, ← hy, ci_zero]; exact adj_vert0 σ 0 + simpa using this + · rw [List.getLast?_cons, List.getLast?_append_of_ne_nil _ hXne, hXt, ci_one]; rfl + · refine List.nodup_cons.2 ⟨hAX0, List.nodup_append.2 ⟨hAn, hXn, fun a ha b hb hab => ?_⟩⟩ + have h1 := exc_far hAX.1 a ha + have h2 := exc_near hAX.2 b hb + rw [hab, h2] at h1; simp at h1 + · intro v hv + rcases List.mem_cons.1 hv with rfl | hv + · exact instrip_zero + · rcases List.mem_append.1 hv with hv | hv + · exact (hAp v hv).1 + · exact (hXp v hv).1 + +open Finset + +/-! ### The generating function -/ + +/-- `rr m = (p (2m+1), q (2m))`, the nonzero excursion numbers (`pq_par`). -/ +private def rr : ℕ → ℕ × ℕ + | 0 => (1, 0) + | 1 => (1, 1) + | m + 2 => ((rr (m + 1)).1 + (rr (m + 1)).2, 2 * (rr m).1 + (rr (m + 1)).2) + +/-- Recursion for `(rr n).1`. -/ +private lemma rr_fst_succ : ∀ n, (rr (n + 1)).1 = (rr n).1 + (rr n).2 + | 0 => rfl + | _ + 1 => rfl + +/-- Recursion for `(rr n).2`. -/ +private lemma rr_snd_succ_succ (n : ℕ) : (rr (n + 2)).2 = 2 * (rr n).1 + (rr (n + 1)).2 := rfl + +/-- The defining recursion of `pq`. -/ +private lemma pq_succ3 (n : ℕ) : + pq (n + 3) = ((pq (n + 1)).1 + (pq n).2, 2 * (pq n).1 + (pq (n + 1)).2) := by + rw [pq] + +/-- Excursions between adjacent columns have odd length, between columns `0` and `2` even. -/ +private lemma pq_par : ∀ m, pq (2 * m) = (0, (rr m).2) ∧ pq (2 * m + 1) = ((rr m).1, 0) + | 0 => ⟨rfl, rfl⟩ + | 1 => ⟨rfl, rfl⟩ + | m + 2 => by + obtain ⟨h1, h2⟩ := pq_par m + obtain ⟨h3, h4⟩ := pq_par (m + 1) + have h3' : pq (2 * m + 1 + 1) = (0, (rr (m + 1)).2) := by + rw [show 2 * m + 1 + 1 = 2 * (m + 1) by ring]; exact h3 + have h4' : pq (2 * (m + 1) + 1) = ((rr (m + 1)).1, 0) := h4 + constructor + · rw [show 2 * (m + 2) = 2 * m + 1 + 3 by ring, pq_succ3, h3', h2] + simp [rr_snd_succ_succ] + · rw [show 2 * (m + 2) + 1 = 2 * (m + 1) + 3 by ring, pq_succ3, h4', h3] + simp [rr] + +/-- `p` vanishes at even lengths. -/ +private lemma p_even (i : ℕ) : (pq (2 * i)).1 = 0 := by rw [(pq_par i).1] +/-- `q` at even lengths. -/ +private lemma q_even (i : ℕ) : (pq (2 * i)).2 = (rr i).2 := by rw [(pq_par i).1] +/-- `p` at odd lengths. -/ +private lemma p_odd (i : ℕ) : (pq (2 * i + 1)).1 = (rr i).1 := by rw [(pq_par i).2] +/-- `q` vanishes at odd lengths. -/ +private lemma q_odd (i : ℕ) : (pq (2 * i + 1)).2 = 0 := by rw [(pq_par i).2] + +/-- Splitting a sum over `[0, 2m)` into even and odd indices. -/ +private lemma sum_range_two_mul (F : ℕ → ℕ) (m : ℕ) : + ∑ ℓ ∈ range (2 * m), F ℓ = ∑ i ∈ range m, (F (2 * i) + F (2 * i + 1)) := by + induction m with + | zero => simp + | succ m ih => + rw [show 2 * (m + 1) = 2 * m + 1 + 1 by ring, sum_range_succ, sum_range_succ, ih, + sum_range_succ] + ring + +/-- The walks to `(0, ±1)`, in terms of `rr`. -/ +private lemma S1_eq (m j : ℕ) (hj : j = 2 * m + 3) : + ∑ c : Fin 3, ∑ ℓ ∈ range j, Ef 0 c ℓ * Ef c 0 (j - 1 - ℓ) = + ∑ i ∈ range (m + 1), (rr i).1 * (rr (m - i)).1 + + ∑ i ∈ range (m + 2), (rr i).2 * (rr (m + 1 - i)).2 := by + subst hj + rw [Fin.sum_univ_three] + simp only [Ef, Fin.isValue, Fin.reduceEq, if_true, if_false, and_false, or_false, + and_self, or_true, and_true] + have hA : ∑ ℓ ∈ range (2 * m + 3), + (if ℓ = 0 then 1 else 0) * (if 2 * m + 3 - 1 - ℓ = 0 then 1 else 0) = 0 := by + apply sum_eq_zero + intro ℓ _ + split_ifs <;> omega + have hB : ∑ ℓ ∈ range (2 * m + 3), (pq ℓ).1 * (pq (2 * m + 3 - 1 - ℓ)).1 = + ∑ i ∈ range (m + 1), (rr i).1 * (rr (m - i)).1 := by + rw [show 2 * m + 3 = 2 * (m + 1) + 1 by ring, sum_range_succ, sum_range_two_mul, p_even, + zero_mul, add_zero] + apply sum_congr rfl + intro i hi + rw [mem_range] at hi + rw [p_even, zero_mul, zero_add, p_odd, + show 2 * (m + 1) + 1 - 1 - (2 * i + 1) = 2 * (m - i) + 1 by omega, p_odd] + have hC : ∑ ℓ ∈ range (2 * m + 3), (pq ℓ).2 * (pq (2 * m + 3 - 1 - ℓ)).2 = + ∑ i ∈ range (m + 2), (rr i).2 * (rr (m + 1 - i)).2 := by + rw [show 2 * m + 3 = 2 * (m + 1) + 1 by ring, sum_range_succ, sum_range_two_mul, + sum_range_succ (fun i => (rr i).2 * (rr (m + 1 - i)).2)] + congr 1 + · apply sum_congr rfl + intro i hi + rw [mem_range] at hi + rw [q_odd, zero_mul, add_zero, q_even, + show 2 * (m + 1) + 1 - 1 - 2 * i = 2 * (m + 1 - i) by omega, q_even] + · rw [q_even, show 2 * (m + 1) + 1 - 1 - 2 * (m + 1) = 2 * 0 by omega, q_even] + simp + rw [hA, hB, hC, zero_add] + +/-- The walks to `(1, 0)` (one direction of the first step), in terms of `rr`. -/ +private lemma S2_eq (m j : ℕ) (hj : j = 2 * m + 3) : + ∑ c : Fin 3, ∑ ℓ ∈ range (j - 1), Ef 0 c ℓ * E0 c (j - 2 - ℓ) = + (rr m).1 + (rr m).2 + ∑ i ∈ range m, (rr i).2 * (rr (m - 1 - i)).1 := by + subst hj + rw [Fin.sum_univ_three] + simp only [Ef, E0, Fin.isValue, Fin.reduceEq, if_true, if_false, and_false, + or_false, and_self, and_true, mul_zero, sum_const_zero, + zero_add, mul_add, sum_add_distrib] + have e1 : 2 * m + 3 - 1 = 2 * m + 1 + 1 := by omega + rw [e1] + have hB : ∑ ℓ ∈ range (2 * m + 1 + 1), (pq ℓ).1 * (if 2 * m + 3 - 2 - ℓ = 0 then 1 else 0) = + (rr m).1 := by + rw [sum_range_succ, show 2 * m + 3 - 2 - (2 * m + 1) = 0 by omega, if_pos rfl, mul_one, + p_odd] + rw [sum_eq_zero, zero_add] + intro ℓ hℓ + rw [mem_range] at hℓ + rw [if_neg (by omega), mul_zero] + have hC : ∑ ℓ ∈ range (2 * m + 1 + 1), (pq ℓ).2 * (if 2 * m + 3 - 2 - ℓ = 1 then 1 else 0) = + (rr m).2 := by + rw [sum_range_succ, sum_range_succ, show 2 * m + 3 - 2 - (2 * m + 1) = 0 by omega, + show 2 * m + 3 - 2 - 2 * m = 1 by omega, if_pos rfl, if_neg (by omega), mul_one, + mul_zero, add_zero, q_even] + rw [sum_eq_zero, zero_add] + intro ℓ hℓ + rw [mem_range] at hℓ + rw [if_neg (by omega), mul_zero] + have hD : ∑ ℓ ∈ range (2 * m + 1 + 1), + (pq ℓ).2 * (if 2 ≤ 2 * m + 3 - 2 - ℓ then (pq (2 * m + 3 - 2 - ℓ - 2)).1 else 0) = + ∑ i ∈ range m, (rr i).2 * (rr (m - 1 - i)).1 := by + rw [sum_range_succ, sum_range_succ, if_neg (by omega), if_neg (by omega), mul_zero, + mul_zero, add_zero, add_zero, sum_range_two_mul] + apply sum_congr rfl + intro i hi + rw [mem_range] at hi + rw [q_odd, zero_mul, add_zero, q_even, if_pos (by omega), + show 2 * m + 3 - 2 - 2 * i - 2 = 2 * (m - 1 - i) + 1 by omega, p_odd] + rw [hB, hC, hD] + ring + +open PowerSeries + +/-- The generating function of `(rr m).1`. -/ +private noncomputable def PP : PowerSeries ℤ := mk fun i => ((rr i).1 : ℤ) + +/-- The generating function of `(rr m).2`. -/ +private noncomputable def QQ : PowerSeries ℤ := mk fun i => ((rr i).2 : ℤ) + +/-- The functional equation of `PP`. -/ +private lemma PP_eq : PP = 1 + X * (PP + QQ) := by + ext n + rcases n with _ | n + · simp [PP, rr] + · rw [map_add, coeff_succ_X_mul, coeff_one, map_add] + simp [PP, QQ, rr_fst_succ] + +/-- The functional equation of `QQ`. -/ +private lemma QQ_eq : QQ = X * (1 + QQ + X * (PP + PP)) := by + ext n + rcases n with _ | _ | n + · simp [QQ, rr] + · rw [coeff_succ_X_mul] + simp [QQ, PP, rr] + · rw [coeff_succ_X_mul, map_add, map_add, coeff_succ_X_mul, coeff_one] + simp [QQ, PP, rr_snd_succ_succ] + ring + +/-- Solving for `PP`. -/ +private lemma PP_sol : (1 - 2 * X) * (1 + X ^ 2) * PP = 1 - X + X ^ 2 := by + linear_combination (1 - X) * PP_eq + X * QQ_eq + +/-- Solving for `QQ`. -/ +private lemma QQ_sol : (1 - 2 * X) * (1 + X ^ 2) * QQ = X + X ^ 2 := by + linear_combination (1 - X) * QQ_eq + 2 * X ^ 2 * PP_eq + +/-- Coefficients of a product of two generating functions. -/ +private lemma coeff_mul_PQ (m : ℕ) (f g : ℕ → ℕ) : + coeff m (mk (fun i => (f i : ℤ)) * mk (fun i => (g i : ℤ))) = + ((∑ i ∈ range (m + 1), f i * g (m - i) : ℕ) : ℤ) := by + rw [coeff_mul, Finset.Nat.sum_antidiagonal_eq_sum_range_succ_mk] + simp + +/-- The generating function identity from the formula for `a (m + 2)`. -/ +private theorem gf_main (a : ℕ → ℕ) (h0 : a 0 = 1) (h1 : a 1 = 0) + (h : ∀ m, a (m + 2) = + 2 * ((rr m).1 + (rr m).2 + ∑ i ∈ range m, (rr i).2 * (rr (m - 1 - i)).1) + + 2 * (∑ i ∈ range (m + 1), (rr i).1 * (rr (m - i)).1 + + ∑ i ∈ range (m + 2), (rr i).2 * (rr (m + 1 - i)).2)) : + mk (fun n => (a n : ℤ)) * ((1 + X ^ 2) ^ 2 * (1 - 2 * X) ^ 2) = + -6 * X ^ 7 + 10 * X ^ 6 - 18 * X ^ 5 + 27 * X ^ 4 - 14 * X ^ 3 + 10 * X ^ 2 - 4 * X + 1 := by + set F : PowerSeries ℤ := + X ^ 2 * (PP * PP) + X * (QQ * QQ) + X ^ 2 * PP + X ^ 2 * QQ + X ^ 3 * (QQ * PP) with hF + have hA : mk (fun n => (a n : ℤ)) = 1 + F + F := by + ext n + rcases n with _ | _ | m + · simp [hF, h0] + · simp [hF, h1, coeff_succ_X_mul, coeff_X_pow_mul', QQ, rr] + · rw [coeff_mk, h m, map_add, map_add, coeff_one, if_neg (by omega)] + have hF2 : coeff (m + 1 + 1) F = + ((∑ i ∈ range (m + 1), (rr i).1 * (rr (m - i)).1 : ℕ) : ℤ) + + ((∑ i ∈ range (m + 2), (rr i).2 * (rr (m + 1 - i)).2 : ℕ) : ℤ) + + (rr m).1 + (rr m).2 + + ((∑ i ∈ range m, (rr i).2 * (rr (m - 1 - i)).1 : ℕ) : ℤ) := by + rw [hF, map_add, map_add, map_add, map_add, coeff_succ_X_mul, coeff_X_pow_mul', + coeff_X_pow_mul', coeff_X_pow_mul', coeff_X_pow_mul', if_pos (by omega), + if_pos (by omega), if_pos (by omega)] + simp only [PP, QQ, coeff_mul_PQ, coeff_mk, show m + 1 + 1 - 2 = m by omega] + rcases m with _ | m + · simp + · rw [if_pos (by omega), show m + 1 + 1 + 1 - 3 = m by omega] + simp only [show m + 1 - 1 = m by omega, show m + 1 + 1 + 1 = m + 1 + 2 by omega] + rw [hF2] + push_cast + ring + rw [hA] + have key : (1 + F + F) * ((1 + X ^ 2) ^ 2 * (1 - 2 * X) ^ 2) = + ((1 - 2 * X) * (1 + X ^ 2)) ^ 2 + 2 * (X ^ 2 * ((1 - 2 * X) * (1 + X ^ 2) * PP) ^ 2 + + X * ((1 - 2 * X) * (1 + X ^ 2) * QQ) ^ 2 + + X ^ 2 * ((1 - 2 * X) * (1 + X ^ 2)) * ((1 - 2 * X) * (1 + X ^ 2) * PP) + + X ^ 2 * ((1 - 2 * X) * (1 + X ^ 2)) * ((1 - 2 * X) * (1 + X ^ 2) * QQ) + + X ^ 3 * ((1 - 2 * X) * (1 + X ^ 2) * QQ) * ((1 - 2 * X) * (1 + X ^ 2) * PP)) := by + rw [hF]; ring + rw [key, PP_sol, QQ_sol] + ring + +/-- The first term. -/ +private lemma a_zero : a 0 = 1 := by + rw [a_eq_GLs 0 (by omega), show 2 * 0 = 0 from rfl, GLs_zero, if_pos rfl] + +/-- The number of closed walks of length `2 (m + 2)`, from the decomposition. -/ +private lemma a_formula (m : ℕ) : a (m + 2) = + 2 * ((rr m).1 + (rr m).2 + ∑ i ∈ Finset.range m, (rr i).2 * (rr (m - 1 - i)).1) + + 2 * (∑ i ∈ Finset.range (m + 1), (rr i).1 * (rr (m - i)).1 + + ∑ i ∈ Finset.range (m + 2), (rr i).2 * (rr (m + 1 - i)).2) := by + rw [a_eq_GLs (m + 2) (by omega), GLs_Q _ (by omega), Fin.sum_univ_three] + have n0 : nb 0 = (1, 0) := rfl + have n1 : nb 1 = (0, dir true) := rfl + have n2 : nb 2 = (0, dir false) := rfl + rw [n0, n1, n2, Q10_card (2 * (m + 2) - 1) (by omega), Q1_card true (2 * (m + 2) - 1) (by omega), + Q1_card false (2 * (m + 2) - 1) (by omega)] + simp only [exc_Ef, exc_E0, Fintype.sum_bool] + rw [S1_eq m (2 * (m + 2) - 1) (by omega), S2_eq m (2 * (m + 2) - 1) (by omega)] + ring + +/-- Ralf Stephan's conjecture holds: the generating function of A022445 is +`(-6x⁷ + 10x⁶ - 18x⁵ + 27x⁴ - 14x³ + 10x² - 4x + 1) / ((1 + x²)² (1 - 2x)²)`. -/ +theorem result : statement := gf_main a a_zero a_one a_formula + +end Math0.Frontier.A022445 + +#math0_settles Math0.Frontier.A022445.result Math0.Statements.A022445.statement diff --git a/lean/Math0/Frontier/OEIS/A057566.lean b/lean/Math0/Frontier/OEIS/A057566.lean new file mode 100644 index 0000000..a4064cf --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A057566.lean @@ -0,0 +1,41 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A057566 +import Math0.Audit + +/-! +# Layman's floor formula for A057566 fails at `n = 24` + +The conjectured identity +`a(n) = 5*floor((2n^3 - 3n^2 - n)/24) + floor((2(n-1)^3 - 3(n-1)^2 - (n-1))/24) + n` +for the number `a(n)` of collinear triples in a `3 × n` grid is false for `n = 24`. +The grid `3 × 24` has `a 24 = 6360` collinear triples (the kernel evaluates the fast counter +`fastA 24`, which equals `a 24` by `a_eq_fastA`; this is also the listed OEIS term), while the +formula gives `5 * 1079 + 946 + 24 = 6365`. The floors are turned into integer division with +`statement_iff_ediv` and evaluated by `norm_num`. + +(For comparison, the true count is `3 * C(n, 3) + ⌈n/2⌉^2 + ⌊n/2⌋^2`: triples inside one row, +plus triples with one point per row in columns `x, y, z` with `x + z = 2y`.) +-/ + +namespace Math0.Frontier.A057566 +open Math0.Statements.A057566 + +/-- The `3 × 24` grid has exactly `6360` collinear triples (the kernel evaluates the fast +counter `fastA`, which equals `a` by `a_eq_fastA`). -/ +private theorem a_24 : a 24 = 6360 := by + rw [a_eq_fastA] + decide +kernel + +/-- Layman's formula is false: at `n = 24` it predicts `6365`, but `a 24 = 6360`. -/ +theorem result : ¬ statement := by + rw [statement_iff_ediv] + intro h + have h24 := h 24 (by norm_num) + rw [a_24] at h24 + norm_num at h24 + +end Math0.Frontier.A057566 + +#math0_settles Math0.Frontier.A057566.result Math0.Statements.A057566.statement diff --git a/lean/Math0/Frontier/OEIS/A057566b.lean b/lean/Math0/Frontier/OEIS/A057566b.lean new file mode 100644 index 0000000..9c4945f --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A057566b.lean @@ -0,0 +1,318 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A057566b +import Math0.Audit + +/-! +# The corrected floor formula for collinear triples in a `3 × n` grid + +We prove the corrected conjecture (Layman, corrected by Ferudun, Oct 2026) for every `n ≥ 0`: +`a(n) = 5*floor((2n^3 - 3n^2 - 2n + 3)/24) + floor((2(n-1)^3 - 3(n-1)^2 - 2(n-1) + 3)/24) + n`, +where `a(n)` is the number of 3-element collinear subsets of the grid `{0, 1, 2} × {0, …, n - 1}`. + +**Counting.** A collinear 3-subset either lies in one row (`3 * C(n, 3)` of them), or has one +point in each row, in columns `x, y, z` with `x + z = 2y` (two points in one row and the third +in another row are never collinear). The transversal triples are parametrized by `(k, l)` with +`(x, z) = (2k, 2l)` or `(2k + 1, 2l + 1)`, giving `⌈n/2⌉^2 + ⌊n/2⌋^2` of them. Formally, +`a n = 3 * C(n, 3) + ⌈n/2⌉^2 + ⌊n/2⌋^2` is proved by an explicit bijection `g` from a disjoint +sum `dom n` onto the set of collinear triples (`Finset.card_nbij`). + +**Floor identity.** With `N(m) = 2m^3 - 3m^2 - 2m + 3` one has the polynomial identity +`5 N(n) + N(n - 1) = 12n^3 - 24n^2 + 15`, while `24 a(n) = 12n^3 - 24n^2 + 24n + 12 (n mod 2)`. +So the formula is equivalent to `5 (N(n) mod 24) + (N(n - 1) mod 24) = 15 - 12 (n mod 2)`, +which depends only on `n mod 24` and is checked for the 24 residues. +-/ + +namespace Math0.Frontier.A057566b +open Math0.Statements.A057566b + +/-- The embedding of the column index `j` into row `i` of the grid. -/ +private def rowEmb (i : ℕ) : ℕ ↪ ℕ × ℕ := + ⟨fun j => (i, j), fun a b h => by simpa using h⟩ + +/-- `rowEmb i j = (i, j)`. -/ +private theorem rowEmb_apply (i j : ℕ) : rowEmb i j = (i, j) := rfl + +/-- The parameter set: a row `i < 3` with a 3-subset of the columns, or a pair `(k, l)` of +half-columns for an even transversal triple, or a pair `(k, l)` for an odd one. -/ +private def dom (n : ℕ) : Finset ((ℕ × Finset ℕ) ⊕ ((ℕ × ℕ) ⊕ (ℕ × ℕ))) := + (Finset.range 3 ×ˢ (Finset.range n).powersetCard 3).disjSum + ((Finset.range ((n + 1) / 2) ×ˢ Finset.range ((n + 1) / 2)).disjSum + (Finset.range (n / 2) ×ˢ Finset.range (n / 2))) + +/-- The parametrization of the collinear triples: a 3-subset of one row, or the transversal +triple in columns `(2k, k + l, 2l)`, or in columns `(2k + 1, k + l + 1, 2l + 1)`. -/ +private def g : (ℕ × Finset ℕ) ⊕ ((ℕ × ℕ) ⊕ (ℕ × ℕ)) → Finset (ℕ × ℕ) + | Sum.inl (i, t) => t.map (rowEmb i) + | Sum.inr (Sum.inl (x, z)) => {(0, 2 * x), (1, x + z), (2, 2 * z)} + | Sum.inr (Sum.inr (x, z)) => {(0, 2 * x + 1), (1, x + z + 1), (2, 2 * z + 1)} + +/-- The size of the parameter set. -/ +private theorem card_dom (n : ℕ) : + (dom n).card = 3 * n.choose 3 + (n + 1) / 2 * ((n + 1) / 2) + n / 2 * (n / 2) := by + simp [dom, Finset.card_disjSum, Finset.card_product, Finset.card_powersetCard] + ring + +/-- Every 3-subset of a single row is in the image of `g`. -/ +private theorem surj_row (n i : ℕ) (hi : i < 3) (x y z : ℕ) (hx : x < n) (hy : y < n) + (hz : z < n) (hxy : x ≠ y) (hxz : x ≠ z) (hyz : y ≠ z) : + ∃ a ∈ dom n, g a = {(i, x), (i, y), (i, z)} := by + refine ⟨Sum.inl (i, {x, y, z}), ?_, ?_⟩ + · simp only [dom, Finset.inl_mem_disjSum, Finset.mem_product, Finset.mem_range, + Finset.mem_powersetCard] + refine ⟨hi, ?_, ?_⟩ + · intro w hw + simp only [Finset.mem_insert, Finset.mem_singleton] at hw + simp only [Finset.mem_range] + omega + · rw [Finset.card_eq_three] + exact ⟨x, y, z, hxy, hxz, hyz, rfl⟩ + · simp [g, rowEmb_apply] + +/-- Every transversal triple `{(0, x), (1, y), (2, z)}` with `x + z = 2y` is in the image of +`g`. -/ +private theorem surj_trans (n x y z : ℕ) (hx : x < n) (hz : z < n) (h : x + z = 2 * y) + (s : Finset (ℕ × ℕ)) (hs : s = {(0, x), (1, y), (2, z)}) : + ∃ a ∈ dom n, g a = s := by + subst hs + rcases Nat.even_or_odd' x with ⟨k, rfl | rfl⟩ + · obtain ⟨l, rfl⟩ : ∃ l, z = 2 * l := ⟨z / 2, by omega⟩ + obtain rfl : y = k + l := by omega + refine ⟨Sum.inr (Sum.inl (k, l)), ?_, rfl⟩ + simp only [dom, Finset.inr_mem_disjSum, Finset.inl_mem_disjSum, Finset.mem_product, + Finset.mem_range] + omega + · obtain ⟨l, rfl⟩ : ∃ l, z = 2 * l + 1 := ⟨z / 2, by omega⟩ + obtain rfl : y = k + l + 1 := by omega + refine ⟨Sum.inr (Sum.inr (k, l)), ?_, rfl⟩ + simp only [dom, Finset.inr_mem_disjSum, Finset.mem_product, Finset.mem_range] + omega + +/-- The closed form `a n = 3 * C(n, 3) + ⌈n/2⌉^2 + ⌊n/2⌋^2`, via the bijection `g`. -/ +private theorem a_eq (n : ℕ) : + a n = 3 * n.choose 3 + (n + 1) / 2 * ((n + 1) / 2) + n / 2 * (n / 2) := by + rw [← card_dom, a] + symm + apply Finset.card_nbij g + · rintro (⟨i, t⟩ | ⟨x, z⟩ | ⟨x, z⟩) hx + · simp only [Finset.mem_coe, dom, Finset.inl_mem_disjSum, Finset.mem_product, + Finset.mem_range, Finset.mem_powersetCard] at hx + obtain ⟨hi, ht, htc⟩ := hx + simp only [Finset.mem_coe, Finset.mem_filter, Finset.mem_powersetCard] + refine ⟨⟨?_, ?_⟩, ?_⟩ + · intro w hw + simp only [g, Finset.mem_map, rowEmb_apply] at hw + obtain ⟨j, hj, rfl⟩ := hw + have := ht hj + simp only [Finset.mem_range] at this + simp [grid, hi, this] + · simp [g, htc] + · intro p hp q hq r hr + simp only [g, Finset.mem_map, rowEmb_apply] at hp hq hr + obtain ⟨_, _, rfl⟩ := hp + obtain ⟨_, _, rfl⟩ := hq + obtain ⟨_, _, rfl⟩ := hr + simp [cross] + · simp only [Finset.mem_coe, dom, Finset.inr_mem_disjSum, Finset.inl_mem_disjSum, + Finset.mem_product, Finset.mem_range] at hx + simp only [Finset.mem_coe, Finset.mem_filter, Finset.mem_powersetCard, g] + refine ⟨⟨?_, ?_⟩, ?_⟩ + · intro w hw + simp only [Finset.mem_insert, Finset.mem_singleton] at hw + rcases hw with rfl | rfl | rfl <;> simp [grid] <;> omega + · rw [Finset.card_eq_three] + exact ⟨_, _, _, by simp, by simp, by simp, rfl⟩ + · rw [isCollinear_triple] + simp only [cross] + push_cast + ring + · simp only [Finset.mem_coe, dom, Finset.inr_mem_disjSum, + Finset.mem_product, Finset.mem_range] at hx + simp only [Finset.mem_coe, Finset.mem_filter, Finset.mem_powersetCard, g] + refine ⟨⟨?_, ?_⟩, ?_⟩ + · intro w hw + simp only [Finset.mem_insert, Finset.mem_singleton] at hw + rcases hw with rfl | rfl | rfl <;> simp [grid] <;> omega + · rw [Finset.card_eq_three] + exact ⟨_, _, _, by simp, by simp, by simp, rfl⟩ + · rw [isCollinear_triple] + simp only [cross] + push_cast + ring + · rintro (⟨i, t⟩ | ⟨x, z⟩ | ⟨x, z⟩) hx (⟨i', t'⟩ | ⟨x', z'⟩ | ⟨x', z'⟩) hx' h + · simp only [Finset.mem_coe, dom, Finset.inl_mem_disjSum, Finset.mem_product, + Finset.mem_range, Finset.mem_powersetCard] at hx hx' + simp only [g] at h + obtain ⟨j, hj⟩ : t.Nonempty := Finset.card_pos.1 (by omega) + have hm : (i, j) ∈ t'.map (rowEmb i') := by rw [← h]; exact Finset.mem_map_of_mem _ hj + simp only [Finset.mem_map, rowEmb_apply, Prod.mk.injEq] at hm + obtain ⟨_, _, rfl, rfl⟩ := hm + rw [Finset.map_inj] at h + rw [h] + · have h0 : (0, 2 * x') ∈ g (Sum.inl (i, t)) := by rw [h]; simp [g] + have h1 : (1, x' + z') ∈ g (Sum.inl (i, t)) := by rw [h]; simp [g] + simp only [g, Finset.mem_map, rowEmb_apply, Prod.mk.injEq] at h0 h1 + omega + · have h0 : (0, 2 * x' + 1) ∈ g (Sum.inl (i, t)) := by rw [h]; simp [g] + have h1 : (1, x' + z' + 1) ∈ g (Sum.inl (i, t)) := by rw [h]; simp [g] + simp only [g, Finset.mem_map, rowEmb_apply, Prod.mk.injEq] at h0 h1 + omega + · have h0 : (0, 2 * x) ∈ g (Sum.inl (i', t')) := by rw [← h]; simp [g] + have h1 : (1, x + z) ∈ g (Sum.inl (i', t')) := by rw [← h]; simp [g] + simp only [g, Finset.mem_map, rowEmb_apply, Prod.mk.injEq] at h0 h1 + omega + · have h0 : (0, 2 * x) ∈ g (Sum.inr (Sum.inl (x', z'))) := by rw [← h]; simp [g] + have h2 : (2, 2 * z) ∈ g (Sum.inr (Sum.inl (x', z'))) := by rw [← h]; simp [g] + simp [g] at h0 h2 + simp only [Sum.inr.injEq, Sum.inl.injEq, Prod.mk.injEq] + omega + · have h0 : (0, 2 * x) ∈ g (Sum.inr (Sum.inr (x', z'))) := by rw [← h]; simp [g] + simp [g] at h0 + omega + · have h0 : (0, 2 * x + 1) ∈ g (Sum.inl (i', t')) := by rw [← h]; simp [g] + have h1 : (1, x + z + 1) ∈ g (Sum.inl (i', t')) := by rw [← h]; simp [g] + simp only [g, Finset.mem_map, rowEmb_apply, Prod.mk.injEq] at h0 h1 + omega + · have h0 : (0, 2 * x + 1) ∈ g (Sum.inr (Sum.inl (x', z'))) := by rw [← h]; simp [g] + simp [g] at h0 + omega + · have h0 : (0, 2 * x + 1) ∈ g (Sum.inr (Sum.inr (x', z'))) := by rw [← h]; simp [g] + have h2 : (2, 2 * z + 1) ∈ g (Sum.inr (Sum.inr (x', z'))) := by rw [← h]; simp [g] + simp [g] at h0 h2 + simp only [Sum.inr.injEq, Prod.mk.injEq] + omega + · intro s hs + simp only [Finset.mem_coe, Finset.mem_filter, Finset.mem_powersetCard] at hs + obtain ⟨⟨hsub, hcard⟩, hcol⟩ := hs + obtain ⟨⟨p1, p2⟩, ⟨q1, q2⟩, ⟨r1, r2⟩, hpq, hpr, hqr, rfl⟩ := Finset.card_eq_three.1 hcard + rw [isCollinear_triple] at hcol + have hp := hsub (by simp : (p1, p2) ∈ ({(p1, p2), (q1, q2), (r1, r2)} : Finset (ℕ × ℕ))) + have hq := hsub (by simp : (q1, q2) ∈ ({(p1, p2), (q1, q2), (r1, r2)} : Finset (ℕ × ℕ))) + have hr := hsub (by simp : (r1, r2) ∈ ({(p1, p2), (q1, q2), (r1, r2)} : Finset (ℕ × ℕ))) + simp only [grid, Finset.mem_product, Finset.mem_range] at hp hq hr + simp only [ne_eq, Prod.mk.injEq] at hpq hpr hqr + simp only [cross] at hcol + rw [Set.mem_image] + simp only [Finset.mem_coe] + by_cases hrow : p1 = q1 ∧ q1 = r1 + · obtain ⟨rfl, rfl⟩ := hrow + exact surj_row n p1 hp.1 p2 q2 r2 hp.2 hq.2 hr.2 (by omega) (by omega) (by omega) + · rcases (show p1 = 0 ∨ p1 = 1 ∨ p1 = 2 by omega) with rfl | rfl | rfl <;> + rcases (show q1 = 0 ∨ q1 = 1 ∨ q1 = 2 by omega) with rfl | rfl | rfl <;> + rcases (show r1 = 0 ∨ r1 = 1 ∨ r1 = 2 by omega) with rfl | rfl | rfl <;> + push_cast at hcol <;> (try ring_nf at hcol) <;> + first + | omega + | (refine surj_trans n p2 q2 r2 ?_ ?_ ?_ _ ?_ <;> + first + | omega + | rfl + | (ext ⟨u, v⟩; simp only [Finset.mem_insert, Finset.mem_singleton, + Prod.mk.injEq]; omega)) + | (refine surj_trans n p2 r2 q2 ?_ ?_ ?_ _ ?_ <;> + first + | omega + | rfl + | (ext ⟨u, v⟩; simp only [Finset.mem_insert, Finset.mem_singleton, + Prod.mk.injEq]; omega)) + | (refine surj_trans n q2 p2 r2 ?_ ?_ ?_ _ ?_ <;> + first + | omega + | rfl + | (ext ⟨u, v⟩; simp only [Finset.mem_insert, Finset.mem_singleton, + Prod.mk.injEq]; omega)) + | (refine surj_trans n q2 r2 p2 ?_ ?_ ?_ _ ?_ <;> + first + | omega + | rfl + | (ext ⟨u, v⟩; simp only [Finset.mem_insert, Finset.mem_singleton, + Prod.mk.injEq]; omega)) + | (refine surj_trans n r2 p2 q2 ?_ ?_ ?_ _ ?_ <;> + first + | omega + | rfl + | (ext ⟨u, v⟩; simp only [Finset.mem_insert, Finset.mem_singleton, + Prod.mk.injEq]; omega)) + | (refine surj_trans n r2 q2 p2 ?_ ?_ ?_ _ ?_ <;> + first + | omega + | rfl + | (ext ⟨u, v⟩; simp only [Finset.mem_insert, Finset.mem_singleton, + Prod.mk.injEq]; omega)) + +/-- `6 * C(n, 3) = n (n - 1) (n - 2)` and `2 * C(n, 2) = n (n - 1)` over `ℤ`. -/ +private theorem choose_three (n : ℕ) : + (6 * n.choose 3 : ℤ) = n * (n - 1) * (n - 2) ∧ (2 * n.choose 2 : ℤ) = n * (n - 1) := by + induction n with + | zero => simp + | succ n ih => + rw [Nat.choose_succ_succ, Nat.choose_succ_succ, Nat.choose_one_right] + push_cast + constructor + · linear_combination 3 * ih.2 + ih.1 + · linear_combination ih.2 + +/-- The residues of the two numerators modulo `24`, for a residue `r` of `n` modulo `24`: +`5 * (N(r) mod 24) + (N(r - 1) mod 24) = 15 - 12 * (r mod 2)`, where +`N(m) = 2m^3 - 3m^2 - 2m + 3` (a finite check). -/ +private theorem resid (r : ℤ) (h0 : 0 ≤ r) (h1 : r < 24) : + 5 * ((2 * r ^ 3 - 3 * r ^ 2 - 2 * r + 3) % 24) + + (2 * (r - 1) ^ 3 - 3 * (r - 1) ^ 2 - 2 * (r - 1) + 3) % 24 = 15 - 12 * (r % 2) := by + interval_cases r <;> norm_num + +/-- `2 * (⌈n/2⌉^2 + ⌊n/2⌋^2) = n^2 + (n mod 2)`. -/ +private theorem sq_half (n : ℕ) : + (((n + 1) / 2 * ((n + 1) / 2) + n / 2 * (n / 2) : ℕ) : ℤ) * 2 = + (n : ℤ) ^ 2 + (n : ℤ) % 2 := by + obtain ⟨k, rfl | rfl⟩ := Nat.even_or_odd' n + · rw [show (2 * k + 1) / 2 = k by omega, show 2 * k / 2 = k by omega] + push_cast + rw [show (2 * (k : ℤ)) % 2 = 0 by omega] + ring + · rw [show (2 * k + 1 + 1) / 2 = k + 1 by omega, show (2 * k + 1) / 2 = k by omega] + push_cast + rw [show (2 * (k : ℤ) + 1) % 2 = 1 by omega] + ring + +/-- The corrected floor formula holds for every `n ≥ 0`. -/ +theorem result : statement := by + rw [statement_iff_ediv] + intro n + have h3 := (choose_three n).1 + have hS := sq_half n + rw [a_eq] + rw [show ((3 * n.choose 3 + (n + 1) / 2 * ((n + 1) / 2) + n / 2 * (n / 2) : ℕ) : ℤ) = + 3 * (n.choose 3 : ℤ) + (((n + 1) / 2 * ((n + 1) / 2) + n / 2 * (n / 2) : ℕ) : ℤ) by + push_cast; ring] + generalize (((n + 1) / 2 * ((n + 1) / 2) + n / 2 * (n / 2) : ℕ) : ℤ) = S at hS ⊢ + generalize (n.choose 3 : ℤ) = C at h3 ⊢ + generalize (n : ℤ) = m at h3 hS ⊢ + have hN1 : (2 * m ^ 3 - 3 * m ^ 2 - 2 * m + 3) % 24 + = (2 * (m % 24) ^ 3 - 3 * (m % 24) ^ 2 - 2 * (m % 24) + 3) % 24 := by + have hmr : m ≡ m % 24 [ZMOD 24] := (Int.mod_modEq m 24).symm + have : 2 * m ^ 3 - 3 * m ^ 2 - 2 * m + 3 ≡ + 2 * (m % 24) ^ 3 - 3 * (m % 24) ^ 2 - 2 * (m % 24) + 3 [ZMOD 24] := by gcongr + exact this + have hN2 : (2 * (m - 1) ^ 3 - 3 * (m - 1) ^ 2 - 2 * (m - 1) + 3) % 24 + = (2 * (m % 24 - 1) ^ 3 - 3 * (m % 24 - 1) ^ 2 - 2 * (m % 24 - 1) + 3) % 24 := by + have hmr : m ≡ m % 24 [ZMOD 24] := (Int.mod_modEq m 24).symm + have : 2 * (m - 1) ^ 3 - 3 * (m - 1) ^ 2 - 2 * (m - 1) + 3 ≡ + 2 * (m % 24 - 1) ^ 3 - 3 * (m % 24 - 1) ^ 2 - 2 * (m % 24 - 1) + 3 [ZMOD 24] := by + gcongr + exact this + have hpar : m % 24 % 2 = m % 2 := Int.emod_emod_of_dvd m (by norm_num) + have hρ := resid (m % 24) (Int.emod_nonneg m (by norm_num)) (Int.emod_lt_of_pos m (by norm_num)) + have hu := Int.mul_ediv_add_emod (2 * m ^ 3 - 3 * m ^ 2 - 2 * m + 3) 24 + have hw := Int.mul_ediv_add_emod (2 * (m - 1) ^ 3 - 3 * (m - 1) ^ 2 - 2 * (m - 1) + 3) 24 + rw [hN1] at hu + rw [hN2] at hw + rw [hpar] at hρ + have key : 24 * (3 * C + S - (5 * ((2 * m ^ 3 - 3 * m ^ 2 - 2 * m + 3) / 24) + + ((2 * (m - 1) ^ 3 - 3 * (m - 1) ^ 2 - 2 * (m - 1) + 3) / 24) + m)) = 0 := by + linear_combination 12 * h3 + 12 * hS - 5 * hu - hw + hρ + omega + +end Math0.Frontier.A057566b + +#math0_settles Math0.Frontier.A057566b.result Math0.Statements.A057566b.statement diff --git a/lean/Math0/Frontier/OEIS/A060693.lean b/lean/Math0/Frontier/OEIS/A060693.lean new file mode 100644 index 0000000..ed97b0b --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A060693.lean @@ -0,0 +1,296 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A060693 +import Math0.Audit + +/-! +# Schulte's alternating quadratic sum over the Schröder-peaks triangle + +We prove Werner Schulte's conjecture for A060693: for every `n ≥ 0`, +`∑_{k=0}^{n} (-1)^k · T(n,k) · (n+1-k)^2 = 1 + n + n^2`, +where `T(n,k)` counts Schröder paths of semilength `n` with `k` peaks. + +**Idea.** Write `(n+1-k)^2 = (n+1)^2 - (2n+1)·k + k(k-1)`, so the sum is +`(n+1)^2 S₀ - (2n+1) S₁ + S₂` with `S_r = ∑_k (-1)^k k^{(r)} T(n,k)` (falling factorials +`1, k, k(k-1)`). We compute these three alternating moments for the generalized counts +`cnt m h b k` of the statement file (paths of width `m` from height `h`, an initial `D` counting +as a peak when `b`), using the three-term recursion `cnt_step`. With `m = h + 2s` the moments are +* `S₀ = [s = 0]·(b ∧ h ≠ 0 ? -1 : 1)`, +* `S₁ = [s = 0]·(b ∧ h ≠ 0 ? -1 : 0) + [s ≥ 1]·(b ? h - 1 : -(h+1))`, +* `S₂ = [s ≥ 1]·((h+1)(s-1)(s+h) + (b ? 2h - 2h(s-1)(s+h-1) : 0))`, + +proved by strong induction on `m` (an initial `D` after a `U` shifts the peak index, which turns +the weight `(-1)^k k^{(r)}` into a combination of lower moments). Combinatorially these are the +coefficients of `t^0, t^1, t^2` after substituting `x = t - 1` for the peak variable, i.e. +counts of Dyck paths with `0`, `1`, `2` peaks (each `H` is a peak `UD` that was "flattened"). +Finally peaks number at most `n` (`2·peaks + h ≤ width + 2b`), so for `h = 0`, `b = false`, +`s = n` we get `S₀ = [n = 0]`, `S₁ = -[n ≥ 1]`, `S₂ = n(n-1)`, and the sum is +`2n + 1 + n(n-1) = n^2 + n + 1` for `n ≥ 1` and `1` for `n = 0`. +-/ + +namespace Math0.Frontier.A060693 +open Math0.Statements.A060693 +open Math0.Statements.A060693.Step + +/-! ### A bound on the number of peaks -/ + +/-- Each peak uses up a `U` and a `D` (except a leading `D` when `b`), so +`2·peaks + h ≤ width + 2b` for a valid walk from height `h`. -/ +private theorem peaks_bound : ∀ (p : List Step) (h : ℕ) (b : Bool), valid h p = true → + 2 * peaksFrom b p + h ≤ width p + 2 * b.toNat + | [], h, b => by simp [valid, peaksFrom]; intro h0; omega + | U :: p, h, b => by + intro hv + have := peaks_bound p (h + 1) true hv + simp only [peaksFrom, width_cons, Step.dx, Bool.toNat_true] at this ⊢ + omega + | D :: p, 0, b => by simp [valid] + | D :: p, h + 1, b => by + intro hv + have := peaks_bound p h false hv + simp only [peaksFrom, width_cons, Step.dx, Bool.toNat_false] at this ⊢ + cases b <;> simp <;> omega + | H :: p, h, b => by + intro hv + have := peaks_bound p h false hv + simp only [peaksFrom, width_cons, Step.dx, Bool.toNat_false] at this ⊢ + omega + +/-- A Schröder path of width `m` has at most `m / 2` peaks. -/ +private theorem cnt_peaks (m k : ℕ) (hk : m < 2 * k) : cnt m 0 false k = 0 := by + rw [cnt, List.countP_eq_zero] + intro w hw + rw [mem_words] at hw + simp only [Bool.and_eq_true, beq_iff_eq, not_and] + intro hv hpk + have := peaks_bound w 0 false hv + simp at this + omega + +/-! ### Weighted sums and their recursion -/ + +/-- The weighted count `∑_k w(k) · cnt m h b k`. -/ +private def W (w : ℕ → ℤ) (m h : ℕ) (b : Bool) : ℤ := + ∑ k ∈ Finset.range (m + 1), w k * (cnt m h b k : ℤ) + +/-- The range of summation may be enlarged. -/ +private theorem W_eq_range (w : ℕ → ℤ) (m h : ℕ) (b : Bool) (N : ℕ) (hN : m + 1 ≤ N) : + ∑ k ∈ Finset.range N, w k * (cnt m h b k : ℤ) = W w m h b := by + unfold W + symm + apply Finset.sum_subset + · intro k hk + simp only [Finset.mem_range] at hk ⊢ + omega + · intro k hk hk' + simp only [Finset.mem_range, not_lt] at hk hk' + rw [cnt_eq_zero m h b k (by omega)] + simp + +/-- `W` vanishes below the diagonal. -/ +private theorem W_zero_lt (w : ℕ → ℤ) (m h : ℕ) (b : Bool) (hm : m < h) : W w m h b = 0 := by + unfold W + apply Finset.sum_eq_zero + intro k _ + rw [cnt_eq_zero m h b k (Or.inl hm)] + simp + +/-- `W` is linear in the weight. -/ +private theorem W_lin (w u v : ℕ → ℤ) (a c : ℤ) (hw : ∀ k, w k = a * u k + c * v k) + (m h : ℕ) (b : Bool) : W w m h b = a * W u m h b + c * W v m h b := by + unfold W + rw [Finset.mul_sum, Finset.mul_sum, ← Finset.sum_add_distrib] + apply Finset.sum_congr rfl + intro k _ + rw [hw] + ring + +/-- The contribution of an initial `D` step. -/ +private def Dpart (w : ℕ → ℤ) (m : ℕ) : ℕ → Bool → ℤ + | 0, _ => 0 + | h + 1, false => W w (m + 1) h false + | h + 1, true => W (fun k => w (k + 1)) (m + 1) h false + +/-- The recursion for `W`, from `cnt_step`. -/ +private theorem W_step (w : ℕ → ℤ) (m h : ℕ) (b : Bool) : + W w (m + 2) h b = W w (m + 1) (h + 1) true + W w m h false + Dpart w m h b := by + have e : W w (m + 2) h b = ∑ k ∈ Finset.range (m + 3), + (w k * (cnt (m + 1) (h + 1) true k : ℤ) + w k * (cnt m h false k : ℤ) + + w k * (dTerm (cnt (m + 1)) h b k : ℤ)) := by + unfold W + apply Finset.sum_congr rfl + intro k _ + rw [cnt_step, step] + push_cast + ring + rw [e, Finset.sum_add_distrib, Finset.sum_add_distrib, W_eq_range _ _ _ _ _ (by omega), + W_eq_range _ _ _ _ _ (by omega)] + congr 1 + rcases h with _ | h + · simp [dTerm, Dpart] + · cases b + · simp only [dTerm, Dpart] + exact W_eq_range _ _ _ _ _ (by omega) + · rw [Finset.sum_range_succ'] + simp only [dTerm, Dpart, Nat.cast_zero, mul_zero, add_zero] + exact W_eq_range _ _ _ _ _ (by omega) + +private theorem cnt00 (b : Bool) (k : ℕ) : cnt 0 0 b k = if k = 0 then 1 else 0 := by + rcases k with _ | k <;> cases b <;> simp [cnt, words, valid, peaksFrom] + +private theorem W_base0 (w : ℕ → ℤ) (b : Bool) : W w 0 0 b = w 0 := by + simp [W, cnt00] + +private theorem W_base1f (w : ℕ → ℤ) : W w 1 1 false = w 0 := by + simp [W, cnt, words, valid, peaksFrom] + +private theorem W_base1t (w : ℕ → ℤ) : W w 1 1 true = w 1 := by + simp [W, cnt, words, valid, peaksFrom] + +/-- A generic closed-form principle: if `F` matches the base cases and satisfies the recursion +(with the initial-`D` shift expressed through `L`), then `W w m h b = F h s b` for `m = h + 2s`. -/ +private theorem closed_gen (w : ℕ → ℤ) (F : ℕ → ℕ → Bool → ℤ) (L : ℕ → ℕ → ℤ) + (h0 : ∀ b, F 0 0 b = w 0) (h1f : F 1 0 false = w 0) (h1t : F 1 0 true = w 1) + (hsh : ∀ m h s, h + 2 * s = m + 1 → + W (fun k => w (k + 1)) (m + 1) h false = -W w (m + 1) h false + L h s) + (hrec : ∀ h s b, 2 ≤ h + 2 * s → F h s b = + (if s = 0 then 0 else F (h + 1) (s - 1) true + F h (s - 1) false) + + (if h = 0 then 0 else if b then -F (h - 1) s false + L (h - 1) s else F (h - 1) s false)) : + ∀ m h s b, h + 2 * s = m → W w m h b = F h s b := by + intro m + induction m using Nat.strong_induction_on with + | _ m ih => + intro h s b hm + match m, ih, hm with + | 0, _, hm => + obtain ⟨rfl, rfl⟩ : h = 0 ∧ s = 0 := by omega + rw [W_base0, h0] + | 1, _, hm => + obtain ⟨rfl, rfl⟩ : h = 1 ∧ s = 0 := by omega + cases b + · rw [W_base1f, h1f] + · rw [W_base1t, h1t] + | m + 2, ih, hm => + rw [hrec h s b (by omega), W_step] + have hA : W w (m + 1) (h + 1) true + W w m h false = + (if s = 0 then 0 else F (h + 1) (s - 1) true + F h (s - 1) false) := by + rcases s with _ | s + · rw [W_zero_lt _ _ _ _ (by omega), W_zero_lt _ _ _ _ (by omega)] + simp + · rw [ih (m + 1) (by omega) (h + 1) s true (by omega), ih m (by omega) h s false (by omega)] + simp + have hC : Dpart w m h b = + (if h = 0 then 0 else if b then -F (h - 1) s false + L (h - 1) s + else F (h - 1) s false) := by + rcases h with _ | h + · simp [Dpart] + · cases b + · simp only [Dpart, Nat.add_one_ne_zero, if_false, Nat.add_sub_cancel, + Bool.false_eq_true] + exact ih (m + 1) (by omega) h s false (by omega) + · simp only [Dpart, Nat.add_one_ne_zero, if_false, if_true, Nat.add_sub_cancel] + rw [hsh m h s (by omega), ih (m + 1) (by omega) h s false (by omega)] + rw [hA, hC] + +/-! ### The three moments -/ + +/-- Weight `(-1)^k`. -/ +private def w0 (k : ℕ) : ℤ := (-1) ^ k + +/-- Weight `(-1)^k · k`. -/ +private def w1 (k : ℕ) : ℤ := (-1) ^ k * k + +/-- Weight `(-1)^k · k(k-1)`. -/ +private def w2 (k : ℕ) : ℤ := (-1) ^ k * ((k : ℤ) * ((k : ℤ) - 1)) + +/-- Closed form of the zeroth moment. -/ +private def F0 (h s : ℕ) (b : Bool) : ℤ := + if s = 0 then (if b = true ∧ h ≠ 0 then -1 else 1) else 0 + +/-- Closed form of the first moment. -/ +private def F1 (h s : ℕ) (b : Bool) : ℤ := + if s = 0 then (if b = true ∧ h ≠ 0 then -1 else 0) + else (if b then (h : ℤ) - 1 else -((h : ℤ) + 1)) + +/-- Closed form of the second moment. -/ +private def F2 (h s : ℕ) (b : Bool) : ℤ := + if s = 0 then 0 + else ((h : ℤ) + 1) * ((s : ℤ) - 1) * ((s : ℤ) + h) + + (if b then 2 * (h : ℤ) - 2 * (h : ℤ) * ((s : ℤ) - 1) * ((s : ℤ) + h - 1) else 0) + +private theorem W0_closed : ∀ m h s b, h + 2 * s = m → W w0 m h b = F0 h s b := by + apply closed_gen w0 F0 (fun _ _ => 0) + · intro b; cases b <;> simp [F0, w0] + · simp [F0, w0] + · simp [F0, w0] + · intro m h s _ + rw [W_lin (fun k => w0 (k + 1)) w0 w0 (-1) 0 (fun k => by simp [w0, pow_succ])] + ring + · intro h s b hs + rcases s with _ | _ | s <;> rcases h with _ | _ | h <;> cases b <;> simp [F0] <;> omega + +private theorem W1_closed : ∀ m h s b, h + 2 * s = m → W w1 m h b = F1 h s b := by + apply closed_gen w1 F1 (fun h s => -F0 h s false) + · intro b; cases b <;> simp [F1, w1] + · simp [F1, w1] + · simp [F1, w1] + · intro m h s hs + rw [W_lin (fun k => w1 (k + 1)) w1 w0 (-1) (-1) (fun k => by simp [w1, w0, pow_succ]; ring), + W0_closed (m + 1) h s false hs] + ring + · intro h s b hs + rcases s with _ | _ | s <;> rcases h with _ | _ | h <;> cases b <;> simp [F0, F1] + +private theorem W2_closed : ∀ m h s b, h + 2 * s = m → W w2 m h b = F2 h s b := by + apply closed_gen w2 F2 (fun h s => -2 * F1 h s false) + · intro b; cases b <;> simp [F2, w2] + · simp [F2, w2] + · simp [F2, w2] + · intro m h s hs + rw [W_lin (fun k => w2 (k + 1)) w2 w1 (-1) (-2) (fun k => by simp [w2, w1, pow_succ]; ring), + W1_closed (m + 1) h s false hs] + ring + · intro h s b hs + rcases s with _ | _ | s <;> rcases h with _ | _ | h <;> cases b <;> simp [F1, F2] <;> + ring_nf + +/-! ### The identity -/ + +/-- Schulte's conjecture holds: `∑_{k=0}^{n} (-1)^k T(n,k) (n+1-k)^2 = 1 + n + n^2`. -/ +theorem result : statement := by + intro n + have hT : ∀ k, (T n k : ℤ) = (cnt (2 * n) 0 false k : ℤ) := fun k => by rw [T_eq_cnt] + simp_rw [hT] + have hext : ∑ k ∈ Finset.range (n + 1), + (-1 : ℤ) ^ k * (cnt (2 * n) 0 false k : ℤ) * ((n : ℤ) + 1 - k) ^ 2 = + ∑ k ∈ Finset.range (2 * n + 1), + (-1 : ℤ) ^ k * (cnt (2 * n) 0 false k : ℤ) * ((n : ℤ) + 1 - k) ^ 2 := by + apply Finset.sum_subset + · intro k hk + simp only [Finset.mem_range] at hk ⊢ + omega + · intro k hk hk' + simp only [Finset.mem_range, not_lt] at hk hk' + rw [cnt_peaks (2 * n) k (by omega)] + simp + rw [hext] + have hsplit : ∑ k ∈ Finset.range (2 * n + 1), + (-1 : ℤ) ^ k * (cnt (2 * n) 0 false k : ℤ) * ((n : ℤ) + 1 - k) ^ 2 = + ((n : ℤ) + 1) ^ 2 * W w0 (2 * n) 0 false - (2 * (n : ℤ) + 1) * W w1 (2 * n) 0 false + + W w2 (2 * n) 0 false := by + simp only [W, Finset.mul_sum, ← Finset.sum_sub_distrib, ← Finset.sum_add_distrib] + apply Finset.sum_congr rfl + intro k _ + simp only [w0, w1, w2] + ring + rw [hsplit, W0_closed (2 * n) 0 n false (by omega), W1_closed (2 * n) 0 n false (by omega), + W2_closed (2 * n) 0 n false (by omega)] + rcases n with _ | n + · simp [F0, F1, F2] + · simp [F0, F1, F2] + ring + +end Math0.Frontier.A060693 + +#math0_settles Math0.Frontier.A060693.result Math0.Statements.A060693.statement diff --git a/lean/Math0/Frontier/OEIS/A062887.lean b/lean/Math0/Frontier/OEIS/A062887.lean new file mode 100644 index 0000000..c8c65c7 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A062887.lean @@ -0,0 +1,151 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A062887 +import Math0.Audit + +/-! +# Odd descending-by-2 multiples exist exactly when `125 ∤ 2n+1` (A062887) + +We prove Irvine's conjecture: `a(n) = 0` if and only if `125 ∣ 2n+1`. + +* If `125 ∣ 2n+1` and `N` has the digit property, then `N` is `ofDigits 10 (gen x L)` with + `x ∈ {1,3,5,7,9}`. For `L ≤ 2` we have `0 < N < 100`, and for `L ≥ 3` the residue of `N` + modulo `1000` is the three-digit tail `531`, `753`, `975`, `197` or `319`, none divisible by + `125`. So no multiple of `2n+1` has the property, and `a(n) = 0`. +* If `125 ∤ m = 2n+1`, write `m ∣ 25 m'` with `m'` coprime to `10`. Let + `S_q = ofDigits 10 (gen 5 (5q))`, the block `31975` repeated `q` times; it has the property + for `q ≥ 1`. We have `S_{q+1} = 31975 + 10^5 S_q`, hence `25 ∣ S_q` and + `99999 S_q + 31975 = 31975 · 100000^q`. With `q = φ(99999 m')` Euler's theorem gives + `100000^q ≡ 1 (mod 99999 m')`, so `99999 m' ∣ 99999 S_q`, i.e. `m' ∣ S_q`, and therefore + `m ∣ 25 m' ∣ S_q`. So a multiple of `m` with the property exists and `a(n) ≠ 0`. +-/ + +namespace Math0.Frontier.A062887 +open Math0.Statements.A062887 + +/-- `a n = 0` exactly when no number with the digit property is a multiple of `2n+1`. -/ +private theorem a_eq_zero_iff (n : ℕ) : a n = 0 ↔ ¬∃ N, IsDesc2 N ∧ 2 * n + 1 ∣ N := by + unfold a + split_ifs with h + · have hpos := (Nat.find_spec h).1.1 + constructor + · intro h0; omega + · intro hn; exact absurd h hn + · simp [h] + +/-- No number with the digit property is divisible by `125`. -/ +private theorem not_dvd_125 {N : ℕ} (hN : IsDesc2 N) : ¬125 ∣ N := by + obtain ⟨x, L, hx, hxo, hL, hd⟩ := exists_gen_of_isDesc2 hN + have hNe : N = Nat.ofDigits 10 (gen x L) := by rw [← hd, Nat.ofDigits_digits] + have hx' : x ∈ [1, 3, 5, 7, 9] := by + have : ∀ y < 10, Odd y → y ∈ [1, 3, 5, 7, 9] := by decide + exact this x hx hxo + intro h125 + simp only [List.mem_cons, List.not_mem_nil, or_false] at hx' + rcases L with _ | _ | _ | L + · omega + · rcases hx' with rfl | rfl | rfl | rfl | rfl <;> + simp [gen, Nat.ofDigits_cons] at hNe <;> omega + · rcases hx' with rfl | rfl | rfl | rfl | rfl <;> + simp [gen, Nat.ofDigits_cons] at hNe <;> omega + · rcases hx' with rfl | rfl | rfl | rfl | rfl <;> + simp [gen, Nat.ofDigits_cons] at hNe <;> omega + +/-- The block `31975` repeated `q` times. -/ +private def S (q : ℕ) : ℕ := Nat.ofDigits 10 (gen 5 (5 * q)) + +/-- Appending one more block: `S (q+1) = 31975 + 10^5 S q`. -/ +private theorem S_succ (q : ℕ) : S (q + 1) = 31975 + 100000 * S q := by + unfold S + rw [show 5 * (q + 1) = 5 * q + 1 + 1 + 1 + 1 + 1 by ring] + simp [gen, Nat.ofDigits_cons] + ring + +/-- `25 ∣ S q`. -/ +private theorem dvd_S_25 (q : ℕ) : 25 ∣ S q := by + induction q with + | zero => simp [S, gen] + | succ q ih => + rw [S_succ] + exact dvd_add (by norm_num) (dvd_mul_of_dvd_right ih _) + +/-- The geometric-sum identity `99999 S q + 31975 = 31975 · 100000^q`. -/ +private theorem S_geom (q : ℕ) : 99999 * S q + 31975 = 31975 * 100000 ^ q := by + induction q with + | zero => simp [S, gen] + | succ q ih => + rw [S_succ, pow_succ] + nlinarith [ih] + +/-- If `m'` is coprime to `10`, then `m'` divides some `S q` with `q ≥ 1`. -/ +private theorem exists_dvd_S {m' : ℕ} (h2 : Nat.Coprime m' 2) (h5 : Nat.Coprime m' 5) : + ∃ q, 1 ≤ q ∧ 25 * m' ∣ S q := by + set n := 99999 * m' with hn + have hcop : Nat.Coprime 10 n := by + rw [hn] + refine Nat.Coprime.mul_right (by norm_num) ?_ + rw [show (10 : ℕ) = 2 * 5 by norm_num] + exact Nat.Coprime.mul_left (Nat.coprime_comm.mp h2) (Nat.coprime_comm.mp h5) + have hm'pos : 0 < m' := by + rcases Nat.eq_zero_or_pos m' with h | h + · subst h; simp at h2 + · exact h + have hnpos : 0 < n := by rw [hn]; positivity + refine ⟨Nat.totient n, Nat.totient_pos.mpr hnpos, ?_⟩ + have h1 : 10 ^ Nat.totient n ≡ 1 [MOD n] := Nat.ModEq.pow_totient hcop + have h2' : 100000 ^ Nat.totient n ≡ 1 [MOD n] := by + have := h1.pow 5 + rw [one_pow, ← pow_mul, mul_comm, pow_mul] at this + simpa using this + have h3 : 99999 * S (Nat.totient n) + 31975 ≡ 0 + 31975 [MOD n] := by + rw [S_geom] + simpa using h2'.mul_left 31975 + have h4 : 99999 * S (Nat.totient n) ≡ 0 [MOD n] := Nat.ModEq.add_right_cancel' _ h3 + have h5' : n ∣ 99999 * S (Nat.totient n) := (Nat.modEq_zero_iff_dvd).mp h4 + rw [hn] at h5' + have hm : m' ∣ S (Nat.totient n) := Nat.dvd_of_mul_dvd_mul_left (by norm_num) h5' + have hc25 : Nat.Coprime 25 m' := by + rw [show (25 : ℕ) = 5 ^ 2 by norm_num] + exact Nat.Coprime.pow_left 2 (Nat.coprime_comm.mp h5) + exact Nat.Coprime.mul_dvd_of_dvd_of_dvd hc25 (dvd_S_25 _) hm + +/-- An odd `m` with `125 ∤ m` divides `25 m'` for some `m'` coprime to `2` and `5`. -/ +private theorem exists_cofactor {m : ℕ} (hodd : ¬2 ∣ m) (h125 : ¬125 ∣ m) : + ∃ m', Nat.Coprime m' 2 ∧ Nat.Coprime m' 5 ∧ m ∣ 25 * m' := by + have cop : ∀ k, ¬2 ∣ k → ¬5 ∣ k → Nat.Coprime k 2 ∧ Nat.Coprime k 5 := fun k h2 h5 => + ⟨Nat.coprime_comm.mp ((Nat.Prime.coprime_iff_not_dvd Nat.prime_two).mpr h2), + Nat.coprime_comm.mp ((Nat.Prime.coprime_iff_not_dvd (by norm_num)).mpr h5)⟩ + by_cases h25 : 25 ∣ m + · obtain ⟨k, rfl⟩ := h25 + have hk2 : ¬2 ∣ k := fun h => hodd (dvd_mul_of_dvd_right h _) + have hk5 : ¬5 ∣ k := by + rintro ⟨j, rfl⟩ + exact h125 ⟨j, by ring⟩ + exact ⟨k, (cop k hk2 hk5).1, (cop k hk2 hk5).2, dvd_refl _⟩ + · by_cases h5 : 5 ∣ m + · obtain ⟨k, rfl⟩ := h5 + have hk2 : ¬2 ∣ k := fun h => hodd (dvd_mul_of_dvd_right h _) + have hk5 : ¬5 ∣ k := by + rintro ⟨j, rfl⟩ + exact h25 ⟨j, by ring⟩ + exact ⟨k, (cop k hk2 hk5).1, (cop k hk2 hk5).2, ⟨5, by ring⟩⟩ + · exact ⟨m, (cop m hodd h5).1, (cop m hodd h5).2, dvd_mul_left _ _⟩ + +/-- Irvine's conjecture for A062887: `a(n) = 0` exactly when `125 ∣ 2n+1`. -/ +theorem result : statement := by + intro n + rw [a_eq_zero_iff] + constructor + · intro hne + by_contra h125 + obtain ⟨m', h2, h5, hdvd⟩ := exists_cofactor (m := 2 * n + 1) (by omega) h125 + obtain ⟨q, hq, hS⟩ := exists_dvd_S h2 h5 + exact hne ⟨S q, isDesc2_ofDigits_gen 5 (5 * q) (by norm_num) (by decide) (by omega), + dvd_trans hdvd hS⟩ + · rintro h125 ⟨N, hN, hdvd⟩ + exact not_dvd_125 hN (dvd_trans h125 hdvd) + +end Math0.Frontier.A062887 + +#math0_settles Math0.Frontier.A062887.result Math0.Statements.A062887.statement diff --git a/lean/Math0/Frontier/OEIS/A071685.lean b/lean/Math0/Frontier/OEIS/A071685.lean new file mode 100644 index 0000000..c2f2ecd --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A071685.lean @@ -0,0 +1,184 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A071685 +import Math0.Audit + +/-! +# Reverse-divisor numbers are `1`, `12`, `78` or `89` mod `100` + +We prove H. P. Dale's conjecture on A071685: if `n` is not a palindrome, `10 ∤ n`, and +`n ∣ R n` or `R n ∣ n` (`R` the decimal reversal), then `n mod 100 ∈ {1, 12, 78, 89}`. + +**Idea.** Let `n ≥ 10` have `d` digits and put `P = 10^(d-2)`. Write +`rev2 x = 10 (x % 10) + x / 10` for the swap of the two digits of `x < 100`. Peeling off the +last two digits of `n` with `R_cons` gives `R n / P = rev2 (n % 100)`: the leading two digits +of `R n` are the last two digits of `n`, swapped. Applying this to `R n` (which has the same +length and `R (R n) = n`) gives `n / P = rev2 (R n % 100)`. + +*Forward case* `R n = k n` (`k ≠ 1`). With `A = n / P ∈ [10, 99]` and `B = n % 100`: +`A = rev2 (k B mod 100)`, and comparing `k A P ≤ k n = R n < (rev2 B + 1) P` and +`rev2 B · P ≤ R n = k n < k (A + 1) P` gives `k A ≤ rev2 B < k (A + 1)`, so `k ≤ 9`. +A finite check over `k < 10`, `B < 100` (kernel `decide`) leaves only `(k, B) = (4, 78)` and +`(9, 89)`. + +*Backward case* `n = k R n`. Then `m = R n` ends in a nonzero digit (else `10 ∣ n`), +`R m = n = k m` and `R m ≠ m`, so `(k, m % 100) ∈ {(4, 78), (9, 89)}` and +`n % 100 = k m % 100 ∈ {12, 1}`. +-/ + +namespace Math0.Frontier.A071685 +open Math0.Statements.A071685 + +/-- Swap the two decimal digits of a number below `100`. -/ +private def rev2 (x : ℕ) : ℕ := 10 * (x % 10) + x / 10 + +/-- For `n ≥ 10`, `n` has two more digits than `n / 100`. -/ +private theorem len_two {n : ℕ} (hn : 10 ≤ n) : + (Nat.digits 10 n).length = (Nat.digits 10 (n / 100)).length + 2 := by + have h1 : 0 < n := by omega + have h2 : 0 < n / 10 := by omega + have h3 : n / 10 / 10 = n / 100 := by omega + rw [len_cons h1, len_cons h2, h3] + +/-- The leading two digits of `R n` are the last two digits of `n`, swapped. -/ +private theorem R_div_P {n : ℕ} (hn : 10 ≤ n) : + R n / 10 ^ (Nat.digits 10 (n / 100)).length = rev2 (n % 100) := by + have h1 : 0 < n := by omega + have h2 : 0 < n / 10 := by omega + have h3 : n / 10 / 10 = n / 100 := by omega + have e1 := R_cons h1 + have e2 := R_cons h2 + have e3 := len_cons h2 + rw [h3] at e2 e3 + have hlt := R_lt (n / 100) + rw [e3, e2, pow_succ] at e1 + have hP0 : 0 < 10 ^ (Nat.digits 10 (n / 100)).length := by positivity + generalize 10 ^ (Nat.digits 10 (n / 100)).length = P at e1 hlt hP0 ⊢ + generalize R (n / 100) = r at e1 hlt + have e : R n = r + P * (10 * (n % 10) + n / 10 % 10) := by rw [e1]; ring + rw [e, Nat.add_mul_div_left _ _ hP0, Nat.div_eq_of_lt hlt, zero_add] + unfold rev2 + omega + +/-- If `n ≥ 10` does not end in `0`, then `R n ≥ 10`. -/ +private theorem R_ge {n : ℕ} (hn : 10 ≤ n) (h : n % 10 ≠ 0) : 10 ≤ R n := by + by_contra hc + have := (Nat.digits_length_le_iff (k := 1) (by norm_num : 1 < 10) (R n)).2 (by omega) + rw [len_R h, len_two hn] at this + omega + +/-- The leading two digits of `n` are the last two digits of `R n`, swapped. -/ +private theorem div_P {n : ℕ} (hn : 10 ≤ n) (h : n % 10 ≠ 0) : + n / 10 ^ (Nat.digits 10 (n / 100)).length = rev2 (R n % 100) := by + have hR := R_ge hn h + have e := R_div_P hR + rw [R_R h] at e + have hl : (Nat.digits 10 (R n / 100)).length = (Nat.digits 10 (n / 100)).length := by + have a := len_two hR + have b := len_two hn + rw [len_R h] at a + omega + rw [hl] at e + exact e + +/-- For `n ≥ 10`, `10 · 10^(d-2) ≤ n` where `d` is the number of digits of `n`. -/ +private theorem P_le {n : ℕ} (hn : 10 ≤ n) : + 10 * 10 ^ (Nat.digits 10 (n / 100)).length ≤ n := by + rcases Nat.eq_zero_or_pos (n / 100) with h0 | h0 + · rw [h0] + simp + omega + · have := Nat.base_pow_length_digits_le 10 (n / 100) (by norm_num) h0.ne' + omega + +/-- The two-digit constraints on `(k, B)` in the forward case `R n = k n`, `B = n % 100`. -/ +private def Ok (k B : ℕ) : Prop := B % 10 ≠ 0 ∧ k ≠ 1 ∧ 10 ≤ rev2 (B * k % 100) ∧ + k * rev2 (B * k % 100) ≤ rev2 B ∧ rev2 B < k * (rev2 (B * k % 100) + 1) + +/-- `Ok` is decidable. -/ +private instance : DecidableRel Ok := fun k B => by unfold Ok; infer_instance + +/-- The finite check: the only solutions of the two-digit constraints are `(4, 78)` +and `(9, 89)`. -/ +private theorem check : + ∀ k < 10, ∀ B < 100, Ok k B → (k = 4 ∧ B = 78) ∨ (k = 9 ∧ B = 89) := by + decide +kernel + +/-- Forward case: if `R n = n k`, `n` is not a palindrome and does not end in `0`, then +`(k, n % 100)` is `(4, 78)` or `(9, 89)`. -/ +private theorem fwd {n k : ℕ} (h10 : n % 10 ≠ 0) (hk : R n = n * k) (hpal : R n ≠ n) : + (k = 4 ∧ n % 100 = 78) ∨ (k = 9 ∧ n % 100 = 89) := by + have hn : 10 ≤ n := by + by_contra hc + apply hpal + have h0 : 0 < n := by omega + have e := R_cons h0 + rw [Nat.div_eq_of_lt (by omega : n < 10)] at e + rw [e, Nat.mod_eq_of_lt (by omega : n < 10)] + simp [R] + have hA := div_P hn h10 + have hB := R_div_P hn + have hRge := R_ge hn h10 + rw [hk] at hRge + have hk0 : 0 < k := Nat.pos_of_ne_zero (by rintro rfl; simp at hRge) + have hlo := P_le hn + have hP0 : 0 < 10 ^ (Nat.digits 10 (n / 100)).length := by positivity + generalize 10 ^ (Nat.digits 10 (n / 100)).length = P at hA hB hlo hP0 + rw [hk] at hA hB + have hmod : n * k % 100 = n % 100 * k % 100 := (Nat.mod_mul_mod n k 100).symm + rw [hmod] at hA + have hk1 : k ≠ 1 := by + rintro rfl + exact hpal (by rw [hk, mul_one]) + have hAP : n / P * P ≤ n := Nat.div_mul_le_self n P + have hnlt : n < (n / P + 1) * P := (Nat.div_lt_iff_lt_mul hP0).1 (Nat.lt_succ_self _) + have hRP : n * k / P * P ≤ n * k := Nat.div_mul_le_self (n * k) P + have hRlt : n * k < (n * k / P + 1) * P := (Nat.div_lt_iff_lt_mul hP0).1 (Nat.lt_succ_self _) + have hA10 : 10 ≤ n / P := (Nat.le_div_iff_mul_le hP0).2 hlo + rw [hA, hB] at * + have hkA : k * rev2 (n % 100 * k % 100) ≤ rev2 (n % 100) := by + have h1 : k * rev2 (n % 100 * k % 100) * P < (rev2 (n % 100) + 1) * P := + calc k * rev2 (n % 100 * k % 100) * P = k * (rev2 (n % 100 * k % 100) * P) := by ring + _ ≤ k * n := Nat.mul_le_mul_left _ hAP + _ = n * k := mul_comm _ _ + _ < _ := hRlt + have := Nat.lt_of_mul_lt_mul_right h1 + omega + have hBk : rev2 (n % 100) < k * (rev2 (n % 100 * k % 100) + 1) := by + have h1 : rev2 (n % 100) * P < k * (rev2 (n % 100 * k % 100) + 1) * P := + calc rev2 (n % 100) * P ≤ n * k := hRP + _ = k * n := mul_comm _ _ + _ < k * ((rev2 (n % 100 * k % 100) + 1) * P) := + Nat.mul_lt_mul_of_pos_left hnlt (by omega) + _ = _ := by ring + exact Nat.lt_of_mul_lt_mul_right h1 + have hk10 : k < 10 := by + have : k * 10 ≤ k * rev2 (n % 100 * k % 100) := Nat.mul_le_mul_left _ hA10 + have : rev2 (n % 100) ≤ 99 := by unfold rev2; omega + omega + have hB100 : n % 100 < 100 := Nat.mod_lt _ (by norm_num) + have hB10 : n % 100 % 10 ≠ 0 := by omega + rcases check k hk10 (n % 100) hB100 ⟨hB10, hk1, hA10, hkA, hBk⟩ with + ⟨h1, h2⟩ | ⟨h1, h2⟩ + · exact Or.inl ⟨h1, h2⟩ + · exact Or.inr ⟨h1, h2⟩ + +/-- Dale's conjecture on A071685: every term `n` satisfies `n mod 100 ∈ {1, 12, 78, 89}`. -/ +theorem result : statement := by + rintro n ⟨hpal, h10, hdiv⟩ + have hB0 : n % 10 ≠ 0 := fun e => h10 (Nat.dvd_of_mod_eq_zero e) + rcases hdiv with ⟨k, hk⟩ | ⟨k, hk⟩ + · rcases fwd hB0 hk hpal with ⟨_, h⟩ | ⟨_, h⟩ <;> omega + · have hm0 : R n % 10 ≠ 0 := by + intro e + apply h10 + rw [hk] + exact Dvd.dvd.mul_right (Nat.dvd_of_mod_eq_zero e) k + have hRm : R (R n) = R n * k := by rw [R_R hB0]; exact hk + have hpm : R (R n) ≠ R n := by rw [R_R hB0]; exact fun e => hpal e.symm + rcases fwd hm0 hRm hpm with ⟨rfl, h⟩ | ⟨rfl, h⟩ <;> omega + +end Math0.Frontier.A071685 + +#math0_settles Math0.Frontier.A071685.result Math0.Statements.A071685.statement diff --git a/lean/Math0/Frontier/OEIS/A073642.lean b/lean/Math0/Frontier/OEIS/A073642.lean new file mode 100644 index 0000000..39eea19 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A073642.lean @@ -0,0 +1,99 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A073642 +import Math0.Audit + +/-! +# Yanev's identity for A073642 (sum of the positions of the 1-bits) + +We prove Velin Yanev's conjecture: for every `n > 0`, +`a(n) = (3 * A011371(n) - ∑_{k=1}^{n} A007814(k)^2) / 2`, where `a(n)` is the sum of the +positions of the 1-bits of `n`, `A011371(n) = v₂(n!)` and `A007814(k) = v₂(k)`. + +**Idea.** Write `v = v₂(n+1)`. Since `v₂((n+1)!) = v₂(n!) + v` and the sum of squares gains +`v²`, the identity `2 a(n) + ∑_{k ≤ n} v₂(k)² = 3 v₂(n!)` (true at `n = 0`) follows by induction +from the local identity `2 a(n+1) + v² = 2 a(n) + 3 v`. That identity, together with the +popcount identity `s(n+1) + v = s(n) + 1` (`s` = number of 1-bits), is proved by strong +induction on `n` using `a(2k) = a(2k+1) = a(k) + s(k)`, `s(2k) = s(k)`, `s(2k+1) = s(k) + 1`, +`v₂(2k+1) = 0` and `v₂(2k) = v₂(k) + 1`. +-/ + +namespace Math0.Frontier.A073642 +open Math0.Statements.A073642 + +/-- The number of 1-bits of `n` (the binary weight). -/ +private def L (n : ℕ) : ℕ := (Nat.bitIndices n).length + +/-- `a(2k) = a(k) + s(k)`. -/ +private lemma a_two_mul (k : ℕ) : a (2 * k) = a k + L k := by + simp [a, L] + +/-- `a(2k+1) = a(k) + s(k)`. -/ +private lemma a_two_mul_add_one (k : ℕ) : a (2 * k + 1) = a k + L k := by + simp [a, L] + +/-- `s(2k) = s(k)`. -/ +private lemma L_two_mul (k : ℕ) : L (2 * k) = L k := by simp [L] + +/-- `s(2k+1) = s(k) + 1`. -/ +private lemma L_two_mul_add_one (k : ℕ) : L (2 * k + 1) = L k + 1 := by simp [L] + +/-- `v₂(2k) = v₂(k) + 1` for `k ≠ 0`. -/ +private lemma v2_two_mul {k : ℕ} (hk : k ≠ 0) : + padicValNat 2 (2 * k) = padicValNat 2 k + 1 := by + rw [padicValNat.mul (by norm_num) hk, padicValNat.self (by norm_num)]; ring + +/-- `v₂(2k+1) = 0`. -/ +private lemma v2_odd (k : ℕ) : padicValNat 2 (2 * k + 1) = 0 := + padicValNat.eq_zero_of_not_dvd (by omega) + +/-- Popcount identity: `s(n+1) + v₂(n+1) = s(n) + 1`. -/ +private lemma L_succ (n : ℕ) : L (n + 1) + padicValNat 2 (n + 1) = L n + 1 := by + induction n using Nat.strong_induction_on with + | _ n ih => + obtain ⟨k, rfl | rfl⟩ := Nat.even_or_odd' n + · rw [L_two_mul_add_one, L_two_mul, v2_odd] + · have h := ih k (by omega) + rw [show 2 * k + 1 + 1 = 2 * (k + 1) by ring, L_two_mul, v2_two_mul (by omega), + L_two_mul_add_one] + omega + +/-- Local identity: `2 a(n+1) + v₂(n+1)² = 2 a(n) + 3 v₂(n+1)`. -/ +private lemma key (n : ℕ) : + 2 * a (n + 1) + padicValNat 2 (n + 1) ^ 2 = 2 * a n + 3 * padicValNat 2 (n + 1) := by + induction n using Nat.strong_induction_on with + | _ n ih => + obtain ⟨k, rfl | rfl⟩ := Nat.even_or_odd' n + · rw [a_two_mul_add_one, a_two_mul, v2_odd]; ring + · have h := ih k (by omega) + have hL := L_succ k + rw [show 2 * k + 1 + 1 = 2 * (k + 1) by ring, a_two_mul, v2_two_mul (by omega), + a_two_mul_add_one] + nlinarith + +/-- The identity in `ℕ`: `2 a(n) + ∑_{k=1}^{n} v₂(k)² = 3 v₂(n!)`. -/ +private lemma main (n : ℕ) : + 2 * a n + ∑ k ∈ Finset.Icc 1 n, padicValNat 2 k ^ 2 = 3 * padicValNat 2 n.factorial := by + induction n with + | zero => simp [a] + | succ n ih => + rw [Finset.sum_Icc_succ_top (by omega), Nat.factorial_succ, + padicValNat.mul (by omega) (Nat.factorial_ne_zero n)] + have := key n + linarith + +/-- Yanev's conjecture holds: for every `n > 0`, +`a(n) = (3 * A011371(n) - ∑_{k=1}^{n} A007814(k)^2) / 2`. -/ +theorem result : statement := by + intro n _ + have h := main n + have h' : (2 * (a n : ℚ) + ∑ k ∈ Finset.Icc 1 n, ((padicValNat 2 k : ℕ) : ℚ) ^ 2) = + 3 * (padicValNat 2 n.factorial : ℚ) := by exact_mod_cast h + rw [eq_div_iff (by norm_num : (2:ℚ) ≠ 0), A011371_eq_padicValNat_factorial] + simp only [A007814] + linarith + +end Math0.Frontier.A073642 + +#math0_settles Math0.Frontier.A073642.result Math0.Statements.A073642.statement diff --git a/lean/Math0/Frontier/OEIS/A075855.lean b/lean/Math0/Frontier/OEIS/A075855.lean new file mode 100644 index 0000000..9c90794 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A075855.lean @@ -0,0 +1,381 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A075855 +import Math0.Audit + +/-! +# The longest path on the black squares of an even chessboard (A075855) + +We prove the conjecture in OEIS A075855: for even `n = 2m ≥ 2`, the longest path through +diagonally adjacent black squares of the `n × n` board covers `(n^2 - n + 2)/2 = 2m^2 - m + 1` +squares. + +**Upper bound (weights).** Give the black square `(i, j)` weight `-1` if +`i + j < n` and `i` is odd, or `i + j ≥ n` and `i` is even (`mi`), and weight `+1` otherwise. +Diagonal neighbours lie in rows of different parity, so two adjacent squares on the same side of +the anti-diagonal `i + j = n` have opposite weights. Hence two adjacent `+1` squares are the ends +of one of the `m` "useful" edges `(i, j) — (i+1, j+1)` with `i + j = n - 2`, `i` even (`us` +marks their lower ends; `plus_plus`). Walking along a path `h :: l` from its far end, `key` +shows `|h :: l| + [h is useful and its partner is not on the path] ≤ +2·#(-1 squares) + #(useful squares) + [h has weight +1]`: a step onto a `+1` square from a `+1` +square uses a useful edge whose lower end is either the new square or the previous square, +which then still had its credit. So a path has at most `2·m(m-1) + m + 1` squares, because the +board has `m (m-1)` squares of weight `-1` and `m` useful squares (`count_mi`, `count_us`, +via injections into `range m ×ˢ range (m-1)` and `range m`). + +**Lower bound (construction).** Cut the board into `m` strips of two rows. Snake upwards: +strip `2k` left to right in full (`2m` squares), strip `2k+1` right to left without its two +end squares (`2m - 2` squares); `blk` is one such pair of strips. For odd `m` finish with a full +strip, for even `m` with the corner `(n - 2, 0)`. This misses exactly `m - 1` squares. +-/ + +namespace Math0.Frontier.A075855 +open Math0.Statements.A075855 + +/-! ### Upper bound -/ + +/-- The cells of weight `-1` on the board of side `n` (`n` even): below the anti-diagonal +`i + j = n` in odd rows, and on or above it in even rows. -/ +private def mi (n : ℕ) (c : ℕ × ℕ) : Bool := + decide ((c.1 + c.2 < n ∧ c.1 % 2 = 1) ∨ (n ≤ c.1 + c.2 ∧ c.1 % 2 = 0)) + +/-- The lower ends `(i, j)` (`i + j = n - 2`, `i` even) of the `n / 2` "useful" edges +`(i, j) — (i + 1, j + 1)`, the only edges joining two cells of weight `+1`. -/ +private def us (n : ℕ) (c : ℕ × ℕ) : Bool := decide (c.1 + c.2 + 2 = n ∧ c.1 % 2 = 0) + +/-- Two adjacent black cells of weight `+1` are the two ends of a useful edge. -/ +private lemma plus_plus {n : ℕ} {c d : ℕ × ℕ} (hn : n % 2 = 0) (hc : IsBlack n c) + (hd : IsBlack n d) (hadj : Adj c d) (h1 : mi n c = false) (h2 : mi n d = false) : + (us n c = true ∧ d = (c.1 + 1, c.2 + 1)) ∨ (us n d = true ∧ c = (d.1 + 1, d.2 + 1)) := by + rw [adj_iff_of_isBlack hc hd] at hadj + obtain ⟨a, b⟩ := c + obtain ⟨e, f⟩ := d + simp only [IsBlack, mi, us, decide_eq_true_eq, decide_eq_false_iff_not, Prod.mk.injEq] at * + omega + +/-- The main inequality, by induction along the path (from its far end): for a path `h :: l`, +`|h :: l| + [h is useful and its partner is not on the path] + ≤ 2 · #(weight -1 cells) + #(useful cells) + [h has weight +1]`. -/ +private lemma key (n : ℕ) (hn : n % 2 = 0) : ∀ (l : List (ℕ × ℕ)) (h : ℕ × ℕ), + IsBoardPath n (h :: l) → + (h :: l).length + (if us n h = true ∧ (h.1 + 1, h.2 + 1) ∉ l then 1 else 0) ≤ + 2 * (h :: l).countP (mi n) + (h :: l).countP (us n) + (if mi n h = true then 0 else 1) := by + intro l + induction l with + | nil => + intro h _ + simp only [List.countP_cons, List.countP_nil, List.length_cons, List.length_nil] + split_ifs <;> simp_all + | cons d l ih => + intro h hP + rw [isBoardPath_cons_cons] at hP + obtain ⟨hh, hnot, hadj, hP'⟩ := hP + have ih' := ih d hP' + have hd : IsBlack n d := hP'.1 d List.mem_cons_self + have key2 : mi n h = false → mi n d = false → + ((us n h = true ∧ (h.1 + 1, h.2 + 1) ∈ d :: l) ∨ + (us n d = true ∧ (d.1 + 1, d.2 + 1) ∉ l)) := by + intro h1 h2 + rcases plus_plus hn hh hd hadj h1 h2 with ⟨hu, he⟩ | ⟨hu, he⟩ + · exact Or.inl ⟨hu, by rw [← he]; exact List.mem_cons_self⟩ + · exact Or.inr ⟨hu, by rw [← he]; exact fun hm => hnot (List.mem_cons_of_mem _ hm)⟩ + have e2 : (if us n h = true ∧ (h.1 + 1, h.2 + 1) ∉ d :: l then 1 else 0) ≤ + (if us n h = true then 1 else 0) := by + split_ifs with h1 h2 + · exact le_rfl + · exact absurd h1.1 h2 + · exact Nat.zero_le _ + · exact le_rfl + have e3 : mi n h = false → mi n d = false → + (if us n h = true ∧ (h.1 + 1, h.2 + 1) ∉ d :: l then 1 else 0) + 1 ≤ + (if us n h = true then 1 else 0) + + (if us n d = true ∧ (d.1 + 1, d.2 + 1) ∉ l then 1 else 0) := by + intro h1 h2 + rcases key2 h1 h2 with ⟨hu, hm⟩ | ⟨hu, hm⟩ + · rw [if_neg (fun hh => hh.2 hm), if_pos hu] + exact Nat.le_add_right _ _ + · rw [if_pos (show us n d = true ∧ (d.1 + 1, d.2 + 1) ∉ l from ⟨hu, hm⟩)] + omega + simp only [List.countP_cons, List.length_cons] at ih' ⊢ + by_cases hmh : mi n h = true <;> by_cases hmd : mi n d = true + · simp only [hmh, hmd, ↓reduceIte] at ih' ⊢ + omega + · simp only [hmh, hmd, ↓reduceIte, Bool.false_eq_true] at ih' ⊢ + omega + · simp only [hmh, hmd, ↓reduceIte, Bool.false_eq_true] at ih' ⊢ + omega + · have e4 := e3 (by simpa using hmh) (by simpa using hmd) + simp only [hmh, hmd, ↓reduceIte, Bool.false_eq_true] at ih' ⊢ + omega + +/-- A list that `f` maps injectively into `s` has length at most `s.card`. -/ +private lemma len_le_of_inj {α β : Type} [DecidableEq β] (l : List α) (hl : l.Nodup) + (f : α → β) (s : Finset β) (hinj : ∀ x ∈ l, ∀ y ∈ l, f x = f y → x = y) + (hs : ∀ x ∈ l, f x ∈ s) : l.length ≤ s.card := by + have h1 : (l.map f).Nodup := hl.map_on hinj + calc l.length = (l.map f).length := by simp + _ = (l.map f).toFinset.card := (List.toFinset_card_of_nodup h1).symm + _ ≤ s.card := Finset.card_le_card (by + intro y hy + simp only [List.mem_toFinset, List.mem_map] at hy + obtain ⟨x, hx, rfl⟩ := hy + exact hs x hx) + +/-- A path on the board of side `2m` contains at most `m` useful cells. -/ +private lemma count_us (m : ℕ) (l : List (ℕ × ℕ)) (hl : IsBoardPath (2 * m) l) : + l.countP (us (2 * m)) ≤ m := by + rw [List.countP_eq_length_filter] + have := len_le_of_inj (l.filter (us (2 * m))) (hl.2.1.filter _) (fun c => c.1 / 2) + (Finset.range m) ?_ ?_ + · simpa using this + · intro x hx y hy hxy + simp only [List.mem_filter, us, decide_eq_true_eq] at hx hy + obtain ⟨x1, x2⟩ := x + obtain ⟨y1, y2⟩ := y + simp only [Prod.mk.injEq] at hxy hx hy ⊢ + omega + · intro x hx + simp only [List.mem_filter, us, decide_eq_true_eq] at hx + simp only [Finset.mem_range] + omega + +/-- A path on the board of side `2m` contains at most `m (m - 1)` cells of weight `-1`. -/ +private lemma count_mi (m : ℕ) (l : List (ℕ × ℕ)) (hl : IsBoardPath (2 * m) l) : + l.countP (mi (2 * m)) ≤ m * (m - 1) := by + rw [List.countP_eq_length_filter] + have := len_le_of_inj (l.filter (mi (2 * m))) (hl.2.1.filter _) + (fun c => (c.1 / 2, if c.1 % 2 = 1 then c.2 / 2 else c.2 / 2 - 1)) + (Finset.range m ×ˢ Finset.range (m - 1)) ?_ ?_ + · simpa using this + · intro x hx y hy hxy + simp only [List.mem_filter, mi, decide_eq_true_eq] at hx hy + have hbx := hl.1 x hx.1 + have hby := hl.1 y hy.1 + obtain ⟨x1, x2⟩ := x + obtain ⟨y1, y2⟩ := y + simp only [IsBlack] at hbx hby + simp only [Prod.mk.injEq] at hxy hx hy ⊢ + split_ifs at hxy <;> omega + · intro x hx + simp only [List.mem_filter, mi, decide_eq_true_eq] at hx + have hbx := hl.1 x hx.1 + obtain ⟨x1, x2⟩ := x + simp only [IsBlack] at hbx + simp only [Finset.mem_product, Finset.mem_range] + split_ifs <;> omega + +/-- Upper bound: a path on the board of side `2m` has at most `2 m^2 - m + 1` cells. -/ +private lemma upper (m : ℕ) (l : List (ℕ × ℕ)) (hl : IsBoardPath (2 * m) l) : + l.length + m ≤ 2 * (m * m) + 1 := by + cases l with + | nil => simp; exact Nat.le_mul_self m |>.trans (by omega) + | cons h l => + have h1 := key (2 * m) (by omega) l h hl + have h2 := count_us m _ hl + have h3 := count_mi m _ hl + have h4 : m * (m - 1) = m * m - m := Nat.mul_sub_one m m + have h5 := Nat.le_mul_self m + split_ifs at h1 <;> omega + +/-! ### Lower bound -/ + +/-- Gluing two paths: disjoint, with the last square of the first adjacent to the first square +of the second. -/ +private lemma isBoardPath_append {n : ℕ} {l₁ l₂ : List (ℕ × ℕ)} (h₁ : IsBoardPath n l₁) + (h₂ : IsBoardPath n l₂) (hd : ∀ a ∈ l₁, ∀ b ∈ l₂, a ≠ b) + (hc : ∀ x ∈ l₁.getLast?, ∀ y ∈ l₂.head?, Adj x y) : IsBoardPath n (l₁ ++ l₂) := + ⟨fun c hc => (List.mem_append.1 hc).elim (h₁.1 c) (h₂.1 c), + List.nodup_append.2 ⟨h₁.2.1, h₂.2.1, hd⟩, List.isChain_append.2 ⟨h₁.2.2, h₂.2.2, hc⟩⟩ + +/-- The zigzag through rows `4k, 4k+1` from left to right (`2m` squares), then back through +rows `4k+2, 4k+3` from right to left, leaving out the two end squares (`2m - 2` squares). -/ +private def blk (m k : ℕ) : List (ℕ × ℕ) := + (List.range (4 * m - 2)).map fun t => + if t < 2 * m then (4 * k + t % 2, t) else (4 * k + 2 + t % 2, 4 * m - 2 - t) + +/-- The first `q` blocks, one after the other. -/ +private def blks (m : ℕ) : ℕ → List (ℕ × ℕ) + | 0 => [] + | q + 1 => blks m q ++ blk m q + +/-- The left-to-right zigzag through rows `r, r+1` (`2m` squares). -/ +private def strip (m r : ℕ) : List (ℕ × ℕ) := + (List.range (2 * m)).map fun t => (r + t % 2, t) + +/-- A block is a path in rows `4k, …, 4k+3`; its only square in column `0` is `(4k, 0)`; it +runs from `(4k, 0)` to `(4k+3, 1)` and has `4m - 2` squares. -/ +private lemma blk_props (m k : ℕ) (hk : 4 * k + 4 ≤ 2 * m) : + IsBoardPath (2 * m) (blk m k) ∧ + (∀ c ∈ blk m k, 4 * k ≤ c.1 ∧ c.1 < 4 * k + 4 ∧ (c.2 = 0 → c.1 % 4 = 0)) ∧ + (blk m k).head? = some (4 * k, 0) ∧ (blk m k).getLast? = some (4 * k + 3, 1) ∧ + (blk m k).length = 4 * m - 2 := by + refine ⟨⟨?_, ?_, ?_⟩, ?_, ?_, ?_, ?_⟩ + · intro c hc + simp only [blk, List.mem_map, List.mem_range] at hc + obtain ⟨t, ht, rfl⟩ := hc + simp only [IsBlack] + split_ifs <;> simp only <;> omega + · refine List.Nodup.map_on ?_ List.nodup_range + intro x hx y hy hxy + simp only [List.mem_range] at hx hy + split_ifs at hxy <;> simp only [Prod.mk.injEq] at hxy <;> omega + · rw [blk, List.isChain_map, List.isChain_range] + intro t ht + simp only [Adj, ne_eq, Prod.ext_iff, Nat.succ_eq_add_one] + split_ifs <;> simp only <;> omega + · intro c hc + simp only [blk, List.mem_map, List.mem_range] at hc + obtain ⟨t, ht, rfl⟩ := hc + split_ifs <;> simp only <;> omega + · simp only [blk, List.head?_map, List.head?_range] + rw [if_neg (by omega)] + simp only [Option.map_some, Option.some.injEq] + rw [if_pos (by omega)] + simp + · simp only [blk, List.getLast?_map, List.getLast?_range] + rw [if_neg (by omega)] + simp only [Option.map_some, Option.some.injEq] + rw [if_neg (by omega)] + simp only [Prod.mk.injEq] + omega + · simp [blk] + +/-- The first `q` blocks form a path in rows `< 4q` whose squares in column `0` lie in rows +divisible by `4`; it ends at `(4q - 1, 1)` and has `q (4m - 2)` squares. -/ +private lemma blks_props (m : ℕ) : ∀ q, 4 * q ≤ 2 * m → + IsBoardPath (2 * m) (blks m q) ∧ + (∀ c ∈ blks m q, c.1 < 4 * q ∧ (c.2 = 0 → c.1 % 4 = 0)) ∧ + (∀ x ∈ (blks m q).getLast?, x = (4 * q - 1, 1)) ∧ + (blks m q).length = q * (4 * m - 2) := by + intro q + induction q with + | zero => intro _; simp [blks, isBoardPath_nil] + | succ q ih => + intro hq + obtain ⟨h1, h2, h3, h4⟩ := ih (by omega) + obtain ⟨b1, b2, b3, b4, b5⟩ := blk_props m q (by omega) + refine ⟨?_, ?_, ?_, ?_⟩ + · refine isBoardPath_append h1 b1 ?_ ?_ + · intro a ha b hb hab + have := (h2 a ha).1 + have := (b2 b hb).1 + subst hab + omega + · intro x hx y hy + rw [h3 x hx] + rw [b3, Option.mem_some_iff] at hy + subst hy + cases q with + | zero => simp [blks] at hx + | succ q => + simp only [Adj, ne_eq, Prod.ext_iff] + omega + · intro c hc + rcases List.mem_append.1 hc with hc | hc + · have := h2 c hc + omega + · have := b2 c hc + omega + · intro x hx + simp only [blks, List.getLast?_append, b4, Option.some_or, Option.mem_some_iff] at hx + subst hx + rw [show 4 * (q + 1) - 1 = 4 * q + 3 by omega] + · simp only [blks, List.length_append, h4, b5] + ring + +/-- A path with `2 m^2 - m + 1` squares on the board of side `2m`, `m ≥ 1`. -/ +private lemma lower (m : ℕ) (hm : 1 ≤ m) : + ∃ l, IsBoardPath (2 * m) l ∧ l.length + m = 2 * (m * m) + 1 := by + obtain ⟨q, rfl | rfl⟩ := Nat.even_or_odd' m + · -- `m = 2 (q' + 1)`: all blocks, then the corner `(4 q' + 2, 0)` + obtain ⟨q', rfl⟩ : ∃ q', q = q' + 1 := ⟨q - 1, by omega⟩ + obtain ⟨h1, h2, h3, h4⟩ := blks_props (2 * (q' + 1)) (q' + 1) (by omega) + refine ⟨blks (2 * (q' + 1)) (q' + 1) ++ [(4 * q' + 2, 0)], ?_, ?_⟩ + · refine isBoardPath_append h1 (isBoardPath_singleton ⟨by omega, by omega, by simp; omega⟩) + ?_ ?_ + · intro a ha b hb hab + rw [List.mem_singleton] at hb + subst hb + subst hab + have := (h2 _ ha).2 rfl + omega + · intro x hx y hy + rw [h3 x hx] + simp only [List.head?_cons, Option.mem_some_iff] at hy + subst hy + simp only [Adj, ne_eq, Prod.ext_iff] + omega + · rw [List.length_append, h4, List.length_singleton] + have : 4 * (2 * (q' + 1)) - 2 = 8 * q' + 6 := by omega + rw [this] + ring + · -- `m = 2 q + 1`: the first `q` blocks, then the top strip + obtain ⟨h1, h2, h3, h4⟩ := blks_props (2 * q + 1) q (by omega) + have s1 : IsBoardPath (2 * (2 * q + 1)) (strip (2 * q + 1) (4 * q)) := by + refine ⟨?_, ?_, ?_⟩ + · intro c hc + simp only [strip, List.mem_map, List.mem_range] at hc + obtain ⟨t, ht, rfl⟩ := hc + simp only [IsBlack] + omega + · refine List.Nodup.map_on ?_ List.nodup_range + intro x hx y hy hxy + simp only [Prod.mk.injEq] at hxy + exact hxy.2 + · rw [strip, List.isChain_map, List.isChain_range] + intro t ht + simp only [Adj, ne_eq, Prod.ext_iff, Nat.succ_eq_add_one] + omega + refine ⟨blks (2 * q + 1) q ++ strip (2 * q + 1) (4 * q), isBoardPath_append h1 s1 ?_ ?_, ?_⟩ + · intro a ha b hb hab + simp only [strip, List.mem_map, List.mem_range] at hb + obtain ⟨t, ht, rfl⟩ := hb + have := (h2 a ha).1 + subst hab + simp only at this + omega + · intro x hx y hy + rw [h3 x hx] + simp only [strip, List.head?_map, List.head?_range] at hy + rw [if_neg (by omega)] at hy + simp only [Option.map_some, Option.mem_some_iff] at hy + subst hy + cases q with + | zero => simp [blks] at hx + | succ q => + simp only [Adj, ne_eq, Prod.ext_iff] + omega + · rw [List.length_append, h4] + simp only [strip, List.length_map, List.length_range] + have : 4 * (2 * q + 1) - 2 = 8 * q + 2 := by omega + rw [this] + ring + +/-- **A075855, even case.** For even `n ≥ 2`, the longest path on the black squares of the +`n × n` chessboard covers exactly `(n^2 - n + 2) / 2` squares. -/ +theorem result : statement := by + intro n hn hev + obtain ⟨m, rfl⟩ : ∃ m, n = 2 * m := by + obtain ⟨k, hk⟩ := hev + exact ⟨k, by omega⟩ + have hm : 1 ≤ m := by omega + have hv : ((2 * m) ^ 2 - 2 * m + 2) / 2 = 2 * (m * m) - m + 1 := by + have h1 : (2 * m) ^ 2 = 4 * (m * m) := by ring + have h2 := Nat.le_mul_self m + rw [h1] + omega + rw [hv] + have h2 := Nat.le_mul_self m + obtain ⟨l, hl, hlen⟩ := lower m hm + apply le_antisymm + · obtain ⟨l', hl', hlen'⟩ := (a_spec (2 * m)).1 + have := upper m l' hl' + omega + · have := (a_spec (2 * m)).2 (show l.length ∈ {k | ∃ l, IsBoardPath (2 * m) l ∧ l.length = k} + from ⟨l, hl, rfl⟩) + omega + +end Math0.Frontier.A075855 + +#math0_settles Math0.Frontier.A075855.result Math0.Statements.A075855.statement diff --git a/lean/Math0/Frontier/OEIS/A081200.lean b/lean/Math0/Frontier/OEIS/A081200.lean new file mode 100644 index 0000000..30165f3 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A081200.lean @@ -0,0 +1,340 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A081200 +import Math0.Audit + +/-! +# Collinear 5-point sets in the grid `{0, …, 4}^n` (A081200) + +We prove Hardin's conjecture in OEIS A081200: the number of 5-element subsets of the grid +`{0, …, 4}^n` that lie on a real line is `a n`, the 6th binomial transform of `0, 1, 0, 1, …`. + +**Lines are words.** A word `w ∈ {0, 1, 2, 3, 4, ↑, ↓}^n` (here `Fin 7`, with `5 = ↑`, `6 = ↓`) +gives the five points `pt w t` (`t = 0, …, 4`) whose `i`-th coordinate is `c` if `w i = c` is a +constant, `t` if `w i = ↑` and `4 - t` if `w i = ↓` (`ev`). If some letter is `↑` or `↓` (the +set `NC n` of non-constant words) these points are distinct and collinear (`card_line`, +`line_collinear`). Conversely (`exists_line`), let `s` be a collinear set of 5 grid points. +Collinearity gives the integer identities `(x_i - z_i)(y_j - z_j) = (x_j - z_j)(y_i - z_i)` +for `x, y, z ∈ s` (`P_of_collinear`). Hence a coordinate that takes the same value at two +distinct points of `s` is constant on `s`; since `s` has two distinct points, some coordinate +`i₀` is injective on `s`, so it takes each value `t ∈ {0, …, 4}` at exactly one point `q t`. +For every other coordinate `j`, the identity with `x = q t, y = q 4, z = q 0` says +`t (q₄ - q₀) = 4 (q_t - q₀)` (values at `j`); a finite check (`H`) shows the only solutions +in `{0, …, 4}` are the constant, `t ↦ t` and `t ↦ 4 - t`. So `s` is the line of a word. + +**Counting.** Two words in `NC n` give the same line iff they are equal or one is the other with +`↑` and `↓` swapped (`line_eq`, `line_rev`; the finite check is `F`), and this swap has no fixed +points on `NC n`. So the number of lines is `|NC n| / 2 = (7^n - 5^n)/2`, and +`2 a n = 7^n - 5^n` by the binomial theorem for `(6 + 1)^n` and `(6 - 1)^n` (`a_eq`). +-/ + +namespace Math0.Frontier.A081200 +open Math0.Statements.A081200 + +/-- The value at parameter `t` of a letter `c`: the constant `c` for `c < 5`, `t` for `c = 5` +(increasing), `4 - t` for `c = 6` (decreasing). -/ +private def ev (c : Fin 7) (t : Fin 5) : Fin 5 := + if h : c.val < 5 then ⟨c.val, h⟩ else if c.val = 5 then t else Fin.rev t + +/-- Swap the two non-constant letters `5` and `6`. -/ +private def rw7 (c : Fin 7) : Fin 7 := if c = 5 then 6 else if c = 6 then 5 else c + +/-- The letter of a coordinate whose values at parameters `0` and `4` are `u0` and `u4`. -/ +private def code (u0 u4 : Fin 5) : Fin 7 := + if u0 = u4 then ⟨u0.val, by omega⟩ else if u0.val = 0 then 5 else 6 + +/-- The point with parameter `t` on the line of the word `w`. -/ +private def pt {n : ℕ} (w : Fin n → Fin 7) (t : Fin 5) : Fin n → Fin 5 := fun i => ev (w i) t + +/-- The five points of the line of the word `w`. -/ +private def line {n : ℕ} (w : Fin n → Fin 7) : Finset (Fin n → Fin 5) := + Finset.univ.image (pt w) + +/-- The constant letters `0, …, 4`. -/ +private def T : Finset (Fin 7) := Finset.univ.filter (fun c => c.val < 5) + +/-- The non-constant words: those having some letter `5` or `6`. -/ +private def NC (n : ℕ) : Finset (Fin n → Fin 7) := Finset.univ \ Fintype.piFinset (fun _ => T) + +/-- Membership in `NC`. -/ +private lemma mem_NC {n : ℕ} {w : Fin n → Fin 7} : w ∈ NC n ↔ ∃ i, 5 ≤ (w i).val := by + simp [NC, T, Fintype.mem_piFinset] + +/-! ### Finite checks -/ + +/-- A non-constant letter gives an injective coordinate. -/ +private lemma ev_inj : ∀ c : Fin 7, 5 ≤ c.val → ∀ t u, ev c t = ev c u → t = u := by + decide +kernel + +/-- A constant letter gives a constant coordinate. -/ +private lemma ev_const : ∀ c : Fin 7, c.val < 5 → ∀ t, ev c t = ev c 0 := by + decide +kernel + +/-- A non-constant letter gives an involution. -/ +private lemma ev_invol : ∀ c : Fin 7, 5 ≤ c.val → ∀ t, ev c (ev c t) = t := by + decide +kernel + +/-- Swapping the direction letters reverses the parameter. -/ +private lemma ev_rw7 : ∀ c : Fin 7, ∀ t, ev (rw7 c) t = ev c (Fin.rev t) := by + decide +kernel + +/-- Swapping keeps non-constant letters non-constant and moves them. -/ +private lemma rw7_ge : ∀ c : Fin 7, 5 ≤ c.val → 5 ≤ (rw7 c).val ∧ rw7 c ≠ c := by + decide +kernel + +/-- Each coordinate is an affine function of the parameter. -/ +private lemma ev_affine : ∀ c : Fin 7, ∀ t : Fin 5, + ((ev c t : ℕ) : ℤ) = (ev c 0 : ℕ) + (t : ℕ) * (((ev c 1 : ℕ) : ℤ) - (ev c 0 : ℕ)) := by + decide +kernel + +/-- An affine relation `t (u4 - u0) = 4 (v - u0)` between a coordinate on `{0, …, 4}` and the +parameter forces the coordinate to be constant, `t` or `4 - t`. -/ +private lemma H : ∀ u0 u1 u4 t v : Fin 5, + ((u4 : ℕ) : ℤ) - (u0 : ℕ) = (((u1 : ℕ) : ℤ) - (u0 : ℕ)) * 4 → + ((t : ℕ) : ℤ) * (((u4 : ℕ) : ℤ) - (u0 : ℕ)) = (((v : ℕ) : ℤ) - (u0 : ℕ)) * 4 → + ev (code u0 u4) t = v := by + decide +kernel + +/-- If two words describe the same points with the reparametrisation `ev a ∘ ev a'`, then the +words agree (when `a' = a`) or are swaps of each other (otherwise). -/ +private lemma F : ∀ a a' b b' : Fin 7, 5 ≤ a.val → 5 ≤ a'.val → + (∀ t, ev b (ev a (ev a' t)) = ev b' t) → (a' = a → b' = b) ∧ (a' ≠ a → b' = rw7 b) := by + decide +kernel + +/-! ### Lines of words -/ + +/-- The points of the line of a non-constant word are distinct. -/ +private lemma pt_inj {n : ℕ} {w : Fin n → Fin 7} (hw : w ∈ NC n) : Function.Injective (pt w) := by + obtain ⟨i, hi⟩ := mem_NC.1 hw + intro t u h + exact ev_inj _ hi t u (congrFun h i) + +/-- The line of a non-constant word has 5 points. -/ +private lemma card_line {n : ℕ} {w : Fin n → Fin 7} (hw : w ∈ NC n) : (line w).card = 5 := by + rw [line, Finset.card_image_of_injective _ (pt_inj hw)] + simp + +/-- The line of a word is collinear. -/ +private lemma line_collinear {n : ℕ} (w : Fin n → Fin 7) : + Collinear ℝ (toReal n '' (line w : Set (Fin n → Fin 5))) := by + rw [collinear_iff_exists_forall_eq_smul_vadd] + refine ⟨toReal n (pt w 0), fun i => ((ev (w i) 1 : ℕ) : ℝ) - (ev (w i) 0 : ℕ), ?_⟩ + rintro p ⟨x, hx, rfl⟩ + simp only [line, Finset.coe_image, Finset.coe_univ, Set.image_univ, Set.mem_range] at hx + obtain ⟨t, rfl⟩ := hx + refine ⟨((t : ℕ) : ℝ), ?_⟩ + funext i + simp only [toReal, pt, vadd_eq_add, Pi.add_apply, Pi.smul_apply, smul_eq_mul] + have h := congrArg (fun z : ℤ => (z : ℝ)) (ev_affine (w i) t) + push_cast at h + linarith + +/-- Reversing all direction letters gives the same line. -/ +private lemma line_rev {n : ℕ} (w : Fin n → Fin 7) : line (fun j => rw7 (w j)) = line w := by + have h : ∀ t, pt (fun j => rw7 (w j)) t = pt w (Fin.rev t) := + fun t => funext fun j => ev_rw7 _ _ + ext x + simp only [line, Finset.mem_image, Finset.mem_univ, true_and, h] + constructor + · rintro ⟨t, rfl⟩ + exact ⟨_, rfl⟩ + · rintro ⟨t, rfl⟩ + exact ⟨Fin.rev t, by rw [Fin.rev_rev]⟩ + +/-- Two non-constant words with the same line are equal or swaps of each other. -/ +private lemma line_eq {n : ℕ} {w w' : Fin n → Fin 7} (hw : w ∈ NC n) (hw' : w' ∈ NC n) + (h : line w' = line w) : w' = w ∨ w' = fun j => rw7 (w j) := by + obtain ⟨i₀, hi₀⟩ := mem_NC.1 hw + have hpt : ∀ t, pt w (ev (w i₀) (ev (w' i₀) t)) = pt w' t := by + intro t + have : pt w' t ∈ line w := h ▸ Finset.mem_image_of_mem _ (Finset.mem_univ t) + simp only [line, Finset.mem_image, Finset.mem_univ, true_and] at this + obtain ⟨u, hu⟩ := this + have hu' : ev (w i₀) u = ev (w' i₀) t := congrFun hu i₀ + rw [← hu', ev_invol _ hi₀, hu] + have ha' : 5 ≤ (w' i₀).val := by + by_contra hlt' + have hlt : (w' i₀).val < 5 := by omega + have e : pt w' 1 = pt w' 0 := by rw [← hpt 1, ← hpt 0, ev_const _ hlt 1] + exact absurd (pt_inj hw' e) (by decide) + have hj : ∀ j t, ev (w j) (ev (w i₀) (ev (w' i₀) t)) = ev (w' j) t := + fun j t => congrFun (hpt t) j + by_cases he : w' i₀ = w i₀ + · left + funext j + exact (F _ _ _ _ hi₀ ha' (hj j)).1 he + · right + funext j + exact (F _ _ _ _ hi₀ ha' (hj j)).2 he + +/-! ### Collinear sets are lines -/ + +/-- Collinearity of grid points as integer identities between coordinate differences. -/ +private lemma P_of_collinear {n : ℕ} {s : Finset (Fin n → Fin 5)} + (hs : Collinear ℝ (toReal n '' (s : Set (Fin n → Fin 5)))) + {x y z : Fin n → Fin 5} (hx : x ∈ s) (hy : y ∈ s) (hz : z ∈ s) (i j : Fin n) : + (((x i : ℕ) : ℤ) - (z i : ℕ)) * (((y j : ℕ) : ℤ) - (z j : ℕ)) = + (((x j : ℕ) : ℤ) - (z j : ℕ)) * (((y i : ℕ) : ℤ) - (z i : ℕ)) := by + rw [collinear_iff_of_mem (Set.mem_image_of_mem _ (Finset.mem_coe.2 hz))] at hs + obtain ⟨v, hv⟩ := hs + obtain ⟨r, hr⟩ := hv _ (Set.mem_image_of_mem _ (Finset.mem_coe.2 hx)) + obtain ⟨r', hr'⟩ := hv _ (Set.mem_image_of_mem _ (Finset.mem_coe.2 hy)) + have e1 := congrFun hr i + have e2 := congrFun hr j + have e3 := congrFun hr' i + have e4 := congrFun hr' j + simp only [toReal, vadd_eq_add, Pi.add_apply, Pi.smul_apply, smul_eq_mul] at e1 e2 e3 e4 + have : (((x i : ℕ) : ℝ) - (z i : ℕ)) * (((y j : ℕ) : ℝ) - (z j : ℕ)) = + (((x j : ℕ) : ℝ) - (z j : ℕ)) * (((y i : ℕ) : ℝ) - (z i : ℕ)) := by + rw [e1, e2, e3, e4]; ring + exact_mod_cast this + +/-- Every collinear 5-point set of grid points is the line of a non-constant word. -/ +private lemma exists_line {n : ℕ} {s : Finset (Fin n → Fin 5)} (hcard : s.card = 5) + (hs : Collinear ℝ (toReal n '' (s : Set (Fin n → Fin 5)))) : ∃ w ∈ NC n, line w = s := by + obtain ⟨y, hy, z, hz, hyz⟩ := Finset.one_lt_card.1 (by omega : 1 < s.card) + obtain ⟨i₀, hi₀⟩ := Function.ne_iff.1 hyz + have key : ∀ x ∈ s, ∀ x' ∈ s, x i₀ = x' i₀ → x = x' := by + intro x hx x' hx' h + by_contra hne + obtain ⟨j, hj⟩ := Function.ne_iff.1 hne + have hj' : ((x' j : ℕ) : ℤ) - (x j : ℕ) ≠ 0 := by + intro h0 + apply hj + apply Fin.ext + omega + have h1 := P_of_collinear hs hy hx' hx i₀ j + have h2 := P_of_collinear hs hz hx' hx i₀ j + rw [h, sub_self, mul_zero] at h1 h2 + have e1 := (mul_eq_zero.1 h1).resolve_right hj' + have e2 := (mul_eq_zero.1 h2).resolve_right hj' + apply hi₀ + apply Fin.ext + omega + have himg : s.image (fun x => x i₀) = Finset.univ := by + apply Finset.eq_univ_of_card + rw [Finset.card_image_of_injOn (fun x hx x' hx' h => key x hx x' hx' h), hcard] + simp + have hex : ∀ t : Fin 5, ∃ x ∈ s, x i₀ = t := by + intro t + have : t ∈ s.image (fun x => x i₀) := himg ▸ Finset.mem_univ t + simpa using this + choose q hqs hqi using hex + have hpt : ∀ t, pt (fun j => code (q 0 j) (q 4 j)) t = q t := by + intro t + funext j + have e0 : ((q 0 i₀ : ℕ) : ℤ) = 0 := by rw [hqi]; rfl + have e1 : ((q 1 i₀ : ℕ) : ℤ) = 1 := by rw [hqi]; rfl + have e4 : ((q 4 i₀ : ℕ) : ℤ) = 4 := by rw [hqi]; rfl + have et : ((q t i₀ : ℕ) : ℤ) = (t : ℕ) := by rw [hqi] + have h1 := P_of_collinear hs (hqs 1) (hqs 4) (hqs 0) i₀ j + have h2 := P_of_collinear hs (hqs t) (hqs 4) (hqs 0) i₀ j + rw [e0, e1, e4] at h1 + rw [e0, e4, et] at h2 + exact H _ (q 1 j) _ _ _ (by linear_combination h1) (by linear_combination h2) + refine ⟨fun j => code (q 0 j) (q 4 j), ?_, ?_⟩ + · rw [mem_NC] + refine ⟨i₀, ?_⟩ + simp only [hqi] + decide + · have hl : line (fun j => code (q 0 j) (q 4 j)) = Finset.univ.image q := by + simp only [line] + congr 1 + funext t + exact hpt t + rw [hl] + apply Finset.eq_of_subset_of_card_le + · intro x hx + simp only [Finset.mem_image, Finset.mem_univ, true_and] at hx + obtain ⟨t, rfl⟩ := hx + exact hqs t + · rw [hcard, Finset.card_image_of_injective] + · simp + intro t u h + have := congrFun h i₀ + rwa [hqi, hqi] at this + +/-! ### Counting -/ + +/-- The collinear 5-point sets are exactly the lines of non-constant words. -/ +private lemma set_eq (n : ℕ) : + {s : Finset (Fin n → Fin 5) | s.card = 5 ∧ Collinear ℝ (toReal n '' (s : Set (Fin n → Fin 5)))} + = ↑((NC n).image line) := by + ext s + simp only [Set.mem_ofPred_eq, Finset.coe_image, Set.mem_image, Finset.mem_coe] + constructor + · rintro ⟨hc, hs⟩ + exact exists_line hc hs + · rintro ⟨w, hw, rfl⟩ + exact ⟨card_line hw, line_collinear w⟩ + +/-- There are `7^n - 5^n` non-constant words. -/ +private lemma card_NC (n : ℕ) : (NC n).card = 7 ^ n - 5 ^ n := by + rw [NC, Finset.card_sdiff_of_subset (Finset.subset_univ _), Fintype.card_piFinset] + have hT : T.card = 5 := by decide + simp [hT] + +/-- Each line comes from exactly two non-constant words. -/ +private lemma two_mul_card (n : ℕ) : 2 * ((NC n).image line).card = (NC n).card := by + rw [Finset.card_eq_sum_card_image line (NC n), Finset.sum_const_nat (m := 2), mul_comm] + intro s hs + obtain ⟨w, hw, rfl⟩ := Finset.mem_image.1 hs + obtain ⟨i₀, hi₀⟩ := mem_NC.1 hw + have hrev : (fun j => rw7 (w j)) ∈ NC n := mem_NC.2 ⟨i₀, (rw7_ge _ hi₀).1⟩ + have hne : w ≠ fun j => rw7 (w j) := fun e => (rw7_ge _ hi₀).2 (congrFun e i₀).symm + have : (NC n).filter (fun w' => line w' = line w) = {w, fun j => rw7 (w j)} := by + ext w' + simp only [Finset.mem_filter, Finset.mem_insert, Finset.mem_singleton] + constructor + · rintro ⟨hw', h⟩ + exact line_eq hw hw' h + · rintro (rfl | rfl) + · exact ⟨hw, rfl⟩ + · exact ⟨hrev, line_rev w⟩ + rw [this, Finset.card_pair hne] + +/-- `2 a n = 7^n - 5^n`, by the binomial theorem for `(6 + 1)^n` and `(6 - 1)^n`. -/ +private lemma a_eq (n : ℕ) : 2 * a n + 5 ^ n = 7 ^ n := by + have hterm : ∀ k : ℕ, ((k % 2 : ℕ) : ℤ) * 2 = 1 - (-1) ^ k := by + intro k + rcases Nat.even_or_odd k with he | ho + · rw [Nat.even_iff.1 he, he.neg_one_pow] + norm_num + · rw [Nat.odd_iff.1 ho, ho.neg_one_pow] + norm_num + have h7 : (7 : ℤ) ^ n = ∑ k ∈ Finset.range (n + 1), (n.choose k : ℤ) * 6 ^ (n - k) := by + rw [show (7 : ℤ) = 1 + 6 by norm_num, add_pow] + apply Finset.sum_congr rfl + intro k _ + ring + have h5 : (5 : ℤ) ^ n = + ∑ k ∈ Finset.range (n + 1), (n.choose k : ℤ) * 6 ^ (n - k) * (-1) ^ k := by + rw [show (5 : ℤ) = -1 + 6 by norm_num, add_pow] + apply Finset.sum_congr rfl + intro k _ + ring + have key : ((2 * a n : ℕ) : ℤ) = 7 ^ n - 5 ^ n := by + rw [h7, h5, ← Finset.sum_sub_distrib] + simp only [a, binomialTransform, A000035, Nat.cast_mul, Nat.cast_sum, Nat.cast_pow, + Nat.cast_ofNat] + rw [Finset.mul_sum] + apply Finset.sum_congr rfl + intro k _ + linear_combination ((n.choose k : ℤ) * 6 ^ (n - k)) * hterm k + have : ((2 * a n : ℕ) : ℤ) + 5 ^ n = 7 ^ n := by rw [key]; ring + exact_mod_cast this + +/-- Hardin's conjecture (A081200): the number of collinear 5-point subsets of `{0, …, 4}^n` +is `a n`. -/ +theorem result : statement := by + intro n + rw [set_eq, Set.ncard_coe_finset] + have h1 := two_mul_card n + have h2 := card_NC n + have h3 := a_eq n + omega + +end Math0.Frontier.A081200 + +#math0_settles Math0.Frontier.A081200.result Math0.Statements.A081200.statement diff --git a/lean/Math0/Frontier/OEIS/A083020.lean b/lean/Math0/Frontier/OEIS/A083020.lean new file mode 100644 index 0000000..5d3fdcf --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A083020.lean @@ -0,0 +1,53 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A083020 +import Math0.Audit + +/-! +# `3^(3^18) + 2` is divisible by `31^2` (A083020) + +We refute Cino Hilliard's conjecture that every number `3^(3^n) + 2` is squarefree. + +Counterexample: `n = 18`. Since `φ(31^2) = 930`, we have `3^930 ≡ 1 (mod 961)` (checked +directly). Write `3^18 = 387420489 = 930 · 416581 + 159`. Then +`3^(3^18) = (3^930)^416581 · 3^159 ≡ 3^159 ≡ 959 ≡ -2 (mod 961)`, so +`961 = 31 · 31` divides `3^(3^18) + 2`, and this number is not squarefree because `31` is not a +unit. (More generally `961 ∣ 3^(3^n) + 2` exactly when `n ≡ 18 (mod 60)`, so infinitely many of +these numbers fail to be squarefree; one counterexample suffices here.) +-/ + +namespace Math0.Frontier.A083020 +open Math0.Statements.A083020 + +/-- `3^930 ≡ 1 (mod 961)`: the order of `3` modulo `31^2` divides `φ(31^2) = 930`. -/ +private theorem pow_930 : 3 ^ 930 ≡ 1 [MOD 961] := by + unfold Nat.ModEq + decide +kernel + +/-- `3^(3^18) = (3^930)^416581 · 3^159`, from `3^18 = 930 · 416581 + 159`. -/ +private theorem split_exp : (3 : ℕ) ^ (3 ^ 18) = (3 ^ 930) ^ 416581 * 3 ^ 159 := by + rw [← pow_mul, ← pow_add] + norm_num + +/-- `31 · 31` divides `3^(3^18) + 2`. -/ +private theorem sq_dvd : 31 * 31 ∣ 3 ^ (3 ^ 18) + 2 := by + have h : (3 ^ 930) ^ 416581 * 3 ^ 159 + 2 ≡ 1 ^ 416581 * 3 ^ 159 + 2 [MOD 961] := + ((pow_930.pow 416581).mul_right _).add_right _ + have h0 : 1 ^ 416581 * 3 ^ 159 + 2 ≡ 0 [MOD 961] := by + unfold Nat.ModEq + decide +kernel + rw [split_exp] + exact Nat.modEq_zero_iff_dvd.1 (h.trans h0) + +/-- Hilliard's conjecture fails: `3^(3^18) + 2` is divisible by `31^2`, so it is not +squarefree. -/ +theorem result : ¬ statement := by + intro h + have hu : IsUnit (31 : ℕ) := h 18 31 sq_dvd + rw [Nat.isUnit_iff] at hu + omega + +end Math0.Frontier.A083020 + +#math0_settles Math0.Frontier.A083020.result Math0.Statements.A083020.statement diff --git a/lean/Math0/Frontier/OEIS/A086004.lean b/lean/Math0/Frontier/OEIS/A086004.lean new file mode 100644 index 0000000..8676640 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A086004.lean @@ -0,0 +1,227 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A086004 +import Math0.Audit + +/-! +# There are no 5-Rotation Cycle Primes (A086004, Conjecture 2) + +We prove Seggelin's Conjecture 2: no prime `p` has `rotAdd^[j] p` prime for all +`j = 1, …, 5`, where `rotAdd n = n + rot n` is the rotate-and-add map of A086002. + +**Even digit counts.** If `n` has `2k ≥ 2` digits then +`rotAdd n = (⌊n/10^k⌋ + n mod 10^k)·(10^k + 1)` (R. J. Mathar). If this is prime, the first factor +is `1`, which forces `n = 10^k`, not prime. So a prime `n` with `rotAdd n` prime has an odd +number `2m + 1` of digits (`odd_range`). + +**Odd digit counts.** Put `P = 10^m` and write `n = X·10P + M·P + Y` with `Y < P`, `M < 10` +(`M` the centre digit). Then `rot n = Y·10P + M·P + X` and +`rotAdd n = S·10P + 2M·P + S` with `S = X + Y` (`rotAdd_odd`). Since `rot n < 10^(2m+1)`, the +number of digits grows by at most one per step, so along a chain of primes +`p, rotAdd p, …, rotAdd^[5] p` the first five terms all have the same `2m + 1` digits +(`stay`). When `rotAdd n` keeps `2m + 1` digits, `S < P`, so the centre digit of `rotAdd n` is +`2M mod 10`; and if `M ≤ 4` then `rotAdd n = S·10P + 2M·P + S` is fixed by `rot`, so the next +term is `2·rotAdd n`, which is not prime (`mid`). + +**The centre digits.** Hence the centre digits `M₀, M₁, M₂, M₃` of the first four terms are all +`≥ 5` and satisfy `M_{j+1} = 2M_j mod 10`. But `M₀ ≥ 5`, `M₁ = 2M₀ − 10 ≥ 5` force `M₀ ∈ {8, 9}`, +`M₂ ≥ 5` forces `M₀ = 9`, and then `M₁ = 8`, `M₂ = 6`, `M₃ = 2 < 5`, a contradiction. +-/ + +namespace Math0.Frontier.A086004 +open Math0.Statements.A086004 + +/-- Block arithmetic: for `S < P`, `S·10P + K·P + S` has remainder `S` and quotient `10S + K` +modulo/by `P`. -/ +private lemma blocks {P S K : ℕ} (hP : 0 < P) (hS : S < P) : + (S * (P * 10) + K * P + S) % P = S ∧ (S * (P * 10) + K * P + S) / P = 10 * S + K := by + have e : S * (P * 10) + K * P + S = S + P * (10 * S + K) := by ring + rw [e, Nat.add_mul_mod_self_left, Nat.mod_eq_of_lt hS, Nat.add_mul_div_left _ _ hP, + Nat.div_eq_of_lt hS] + simp + +/-- For `n` with `2m + 1` digits, `rot n = Y·10^(m+1) + M·10^m + X` where `Y = n mod 10^m`, +`M` is the centre digit and `X = ⌊n/10^(m+1)⌋`. -/ +private lemma rot_odd {m n : ℕ} (h1 : 10 ^ (2 * m) ≤ n) (h2 : n < 10 ^ (2 * m + 1)) : + rot n = n % 10 ^ m * (10 ^ m * 10) + n / 10 ^ m % 10 * 10 ^ m + n / (10 ^ m * 10) := by + have hlen : (Nat.digits 10 n).length = 2 * m + 1 := length_digits_eq h1 h2 + unfold rot + simp only [hlen] + have e1 : (2 * m + 1) / 2 = m := by omega + have e2 : 2 * m + 1 - m = m + 1 := by omega + rw [e1, e2, show m + 1 - m = 1 by omega, pow_succ, pow_one] + +/-- For `n` with `2k` digits, `rotAdd n = (⌊n/10^k⌋ + n mod 10^k)·(10^k + 1)` (R. J. Mathar). -/ +private lemma rotAdd_even {k n : ℕ} (hlen : (Nat.digits 10 n).length = 2 * k) : + rotAdd n = (n / 10 ^ k + n % 10 ^ k) * (10 ^ k + 1) := by + unfold rotAdd rot + simp only [hlen] + have e1 : 2 * k / 2 = k := by omega + have e2 : 2 * k - k = k := by omega + rw [e1, e2, Nat.sub_self, pow_zero, Nat.mod_one, zero_mul, add_zero] + have := Nat.div_add_mod n (10 ^ k) + nth_rewrite 1 [← this] + ring + +/-- If `n` and `rotAdd n` are prime then `n` has an odd number `2m + 1` of digits. -/ +private lemma odd_range {n : ℕ} (hn : n.Prime) (hf : (rotAdd n).Prime) : + ∃ m, 10 ^ (2 * m) ≤ n ∧ n < 10 ^ (2 * m + 1) := by + have hn0 : n ≠ 0 := hn.ne_zero + obtain ⟨k, hk | hk⟩ := Nat.even_or_odd' (Nat.digits 10 n).length + · exfalso + have hk1 : 1 ≤ k := by + rcases Nat.eq_zero_or_pos k with rfl | h + · simp only [mul_zero, List.length_eq_zero_iff] at hk + exact absurd hk (Nat.digits_ne_nil_iff_ne_zero.mpr hn0) + · exact h + have hlo : 10 ^ (2 * k - 1) ≤ n := (Nat.lt_digits_length_iff (by norm_num) n).1 (by omega) + have hP : 10 ^ k ≤ n := le_trans (Nat.pow_le_pow_right (by norm_num) (by omega)) hlo + rw [rotAdd_even hk, Nat.prime_mul_iff] at hf + rcases hf with ⟨-, h⟩ | ⟨-, h⟩ + · have : 0 < 10 ^ k := by positivity + omega + · have hq : 1 ≤ n / 10 ^ k := (Nat.le_div_iff_mul_le (by positivity)).2 (by simpa using hP) + have hr : n % 10 ^ k = 0 := by omega + have h10 : 10 ∣ n := + dvd_trans (dvd_pow_self 10 (by omega)) (Nat.dvd_of_mod_eq_zero hr) + have h2 : 2 ∣ n := dvd_trans (by norm_num) h10 + have h10' : 10 ≤ 10 ^ k := by + calc 10 = 10 ^ 1 := by norm_num + _ ≤ 10 ^ k := Nat.pow_le_pow_right (by norm_num) hk1 + rcases hn.eq_one_or_self_of_dvd 2 h2 with e | e <;> omega + · refine ⟨k, (Nat.lt_digits_length_iff (by norm_num) n).1 (by omega), ?_⟩ + rw [← hk] + exact Nat.lt_base_pow_length_digits (by norm_num) + +/-- `n = ⌊n/10P⌋·10P + (⌊n/P⌋ mod 10)·P + n mod P`. -/ +private lemma decomp (P n : ℕ) : n = n / (P * 10) * (P * 10) + n / P % 10 * P + n % P := by + have h1 := Nat.div_add_mod n P + have h2 := Nat.div_add_mod (n / P) 10 + rw [Nat.div_div_eq_div_mul] at h2 + calc n = P * (n / P) + n % P := h1.symm + _ = P * (10 * (n / (P * 10)) + n / P % 10) + n % P := by rw [h2] + _ = _ := by ring + +/-- For `n` with `2m + 1` digits, `rotAdd n = S·10^(m+1) + 2M·10^m + S` with +`S = ⌊n/10^(m+1)⌋ + n mod 10^m` and `M` the centre digit. -/ +private lemma rotAdd_odd {m n : ℕ} (h1 : 10 ^ (2 * m) ≤ n) (h2 : n < 10 ^ (2 * m + 1)) : + rotAdd n = (n / (10 ^ m * 10) + n % 10 ^ m) * (10 ^ m * 10) + + 2 * (n / 10 ^ m % 10) * 10 ^ m + (n / (10 ^ m * 10) + n % 10 ^ m) := by + unfold rotAdd + rw [rot_odd h1 h2] + nth_rewrite 1 [decomp (10 ^ m) n] + ring + +/-- For `n` with `2m + 1` digits, `rot n < 10^(2m+1)`. -/ +private lemma rot_lt {m n : ℕ} (h1 : 10 ^ (2 * m) ≤ n) (h2 : n < 10 ^ (2 * m + 1)) : + rot n < 10 ^ (2 * m + 1) := by + rw [rot_odd h1 h2] + set P := 10 ^ m with hP + have hP0 : 0 < P := by positivity + have e : 10 ^ (2 * m + 1) = P * (P * 10) := by rw [hP]; ring + rw [e] at h2 ⊢ + have hX : n / (P * 10) < P := (Nat.div_lt_iff_lt_mul (by positivity)).2 h2 + have hY : n % P < P := Nat.mod_lt _ hP0 + have hM : n / P % 10 < 10 := Nat.mod_lt _ (by norm_num) + have a1 : (n % P + 1) * (P * 10) ≤ P * (P * 10) := Nat.mul_le_mul_right _ hY + have a2 : n / P % 10 * P ≤ 9 * P := Nat.mul_le_mul_right _ (by omega) + nlinarith + +/-- If `n` has `2m + 1` digits and `rotAdd n`, `rotAdd (rotAdd n)` are prime, then `rotAdd n` +still has `2m + 1` digits (it cannot reach `2m + 3` digits, and `2m + 2` is excluded by +`odd_range`). -/ +private lemma stay {m n : ℕ} (h1 : 10 ^ (2 * m) ≤ n) (h2 : n < 10 ^ (2 * m + 1)) + (hp1 : (rotAdd n).Prime) (hp2 : (rotAdd (rotAdd n)).Prime) : + rotAdd n < 10 ^ (2 * m + 1) := by + obtain ⟨m', h1', h2'⟩ := odd_range hp1 hp2 + have hr := rot_lt h1 h2 + have hup : rotAdd n < 10 ^ (2 * m + 2) := by + have : 10 ^ (2 * m + 2) = 10 * 10 ^ (2 * m + 1) := by ring + unfold rotAdd + omega + rcases le_or_gt m' m with h | h + · exact lt_of_lt_of_le h2' (Nat.pow_le_pow_right (by norm_num) (by omega)) + · have := Nat.pow_le_pow_right (show 0 < 10 by norm_num) (show 2 * m + 2 ≤ 2 * m' by omega) + omega + +/-- If `n` and `rotAdd n` both have `2m + 1` digits, the centre digit of `rotAdd n` is twice the +centre digit `M` of `n` modulo `10`, and if `M < 5` then `rot` fixes `rotAdd n`, so +`rotAdd (rotAdd n) = 2·rotAdd n`. -/ +private lemma mid {m n : ℕ} (h1 : 10 ^ (2 * m) ≤ n) (h2 : n < 10 ^ (2 * m + 1)) + (h3 : rotAdd n < 10 ^ (2 * m + 1)) : + rotAdd n / 10 ^ m % 10 = 2 * (n / 10 ^ m % 10) % 10 ∧ + (n / 10 ^ m % 10 < 5 → rotAdd (rotAdd n) = 2 * rotAdd n) := by + have e := rotAdd_odd h1 h2 + have h1' : 10 ^ (2 * m) ≤ rotAdd n := le_trans h1 (Nat.le_add_right _ _) + have hr := rot_odd h1' h3 + set P := 10 ^ m with hP + have hP0 : 0 < P := by positivity + set S := n / (P * 10) + n % P with hS + set M := n / P % 10 with hM + have eP : 10 ^ (2 * m + 1) = P * 10 * P := by rw [hP]; ring + have hSP : S < P := by + rw [eP, e] at h3 + have : S * (P * 10) < P * (P * 10) := by nlinarith + exact Nat.lt_of_mul_lt_mul_right this + obtain ⟨hmod, hdiv⟩ := blocks (K := 2 * M) hP0 hSP + rw [← e] at hmod hdiv + refine ⟨by rw [hdiv]; omega, fun hM5 => ?_⟩ + have hdiv2 : rotAdd n / (P * 10) = S := by + rw [← Nat.div_div_eq_div_mul, hdiv] + omega + have hmid : (10 * S + 2 * M) % 10 = 2 * M := by omega + show rotAdd n + rot (rotAdd n) = 2 * rotAdd n + rw [hr, hmod, hdiv, hdiv2, hmid, e] + ring + +/-- Twice a prime is not prime. -/ +private lemma not_prime_two_mul {x : ℕ} (hx : x.Prime) : ¬ (2 * x).Prime := by + intro h2 + rcases Nat.prime_mul_iff.1 h2 with ⟨_, e⟩ | ⟨_, e⟩ + · exact hx.ne_one e + · norm_num at e + +/-- Conjecture 2 of A086004 holds: there are no 5-Rotation Cycle Primes. -/ +theorem result : statement := by + rintro p ⟨h0, h⟩ + have p1 : (rotAdd p).Prime := h 1 (by norm_num) (by norm_num) + have p2 : (rotAdd (rotAdd p)).Prime := h 2 (by norm_num) (by norm_num) + have p3 : (rotAdd (rotAdd (rotAdd p))).Prime := h 3 (by norm_num) (by norm_num) + have p4 : (rotAdd (rotAdd (rotAdd (rotAdd p)))).Prime := h 4 (by norm_num) (by norm_num) + have p5 : (rotAdd (rotAdd (rotAdd (rotAdd (rotAdd p))))).Prime := + h 5 (by norm_num) (by norm_num) + obtain ⟨m, l0, u0⟩ := odd_range h0 p1 + have u1 := stay l0 u0 p1 p2 + have l1 : 10 ^ (2 * m) ≤ rotAdd p := le_trans l0 (Nat.le_add_right _ _) + have u2 := stay l1 u1 p2 p3 + have l2 : 10 ^ (2 * m) ≤ rotAdd (rotAdd p) := le_trans l1 (Nat.le_add_right _ _) + have u3 := stay l2 u2 p3 p4 + have l3 : 10 ^ (2 * m) ≤ rotAdd (rotAdd (rotAdd p)) := le_trans l2 (Nat.le_add_right _ _) + have u4 := stay l3 u3 p4 p5 + obtain ⟨a0, b0⟩ := mid l0 u0 u1 + obtain ⟨a1, b1⟩ := mid l1 u1 u2 + obtain ⟨a2, b2⟩ := mid l2 u2 u3 + obtain ⟨-, b3⟩ := mid l3 u3 u4 + have c0 : 5 ≤ p / 10 ^ m % 10 := by + by_contra hc + exact not_prime_two_mul p1 (b0 (by omega) ▸ p2) + have c1 : 5 ≤ rotAdd p / 10 ^ m % 10 := by + by_contra hc + exact not_prime_two_mul p2 (b1 (by omega) ▸ p3) + have c2 : 5 ≤ rotAdd (rotAdd p) / 10 ^ m % 10 := by + by_contra hc + exact not_prime_two_mul p3 (b2 (by omega) ▸ p4) + have c3 : 5 ≤ rotAdd (rotAdd (rotAdd p)) / 10 ^ m % 10 := by + by_contra hc + exact not_prime_two_mul p4 (b3 (by omega) ▸ p5) + have c4 : p / 10 ^ m % 10 < 10 := Nat.mod_lt _ (by norm_num) + generalize p / 10 ^ m % 10 = M0 at a0 c0 c4 + generalize rotAdd p / 10 ^ m % 10 = M1 at a0 a1 c1 + generalize rotAdd (rotAdd p) / 10 ^ m % 10 = M2 at a1 a2 c2 + generalize rotAdd (rotAdd (rotAdd p)) / 10 ^ m % 10 = M3 at a2 c3 + interval_cases M0 <;> omega + +end Math0.Frontier.A086004 + +#math0_settles Math0.Frontier.A086004.result Math0.Statements.A086004.statement diff --git a/lean/Math0/Frontier/OEIS/A090905.lean b/lean/Math0/Frontier/OEIS/A090905.lean new file mode 100644 index 0000000..7f74244 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A090905.lean @@ -0,0 +1,918 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A090905 +import Math0.Audit + +/-! +# A090905: each row ends at twice the largest prime of the previous row + +We prove Murthy's conjecture: for `n > 4`, group `n - 1` has a largest prime `p`, the last term +of group `n` is `2 p`, and `p` is the Bertrand prime `A006992(n - 1)`. + +Write `B k = bertrand k`, so `B (k + 1)` is the largest prime below `2 B k`. We show that for +`n ≥ 10`, row `n` is the block `[2 B (n - 2) + 1, 2 B (n - 1)]`. Rows `1, …, 10` are checked by +computation. For the inductive step let `b < a < c` be three consecutive Bertrand primes, with +row `n` equal to `[2b + 1, 2a]`. Then row `n + 1` starts at `2a + 1`, and: + +* The prime `c` lies in row `n`, but none of `2a + 1, …, 2c - 1` is a multiple of `c`. So the + new row must reach `2c`. +* Ending at `2c` works. The row product `(2a)! / (2b)!` divides `(2c)! / (2a)!`, because + `(2a)!² ∣ (2b)! (2c)!`. By Legendre's formula this means that for every prime `ℓ`, + `∑ⱼ (⌊2b/ℓʲ⌋ + ⌊2c/ℓʲ⌋ - 2⌊2a/ℓʲ⌋) ≥ 0`. Each term is `≥ 0`, using `2b > a` and `3c > 5a`, + except when `c < ℓʲ ≤ 2a`. Then the term is `-1`, `ℓʲ` is not prime because there is no + prime in `(c, 2a)`, and the term `j = 1` is `≥ 1`. +* The length condition `2c - 2a ≥ 2a - 2b` also follows from `2b > a` and `3c > 5a`. + +The inequalities `3c > 5a` (and `3a > 5b`) say that there is a prime between `5x/3` and `2x` +(Nagura's theorem, in the form needed here). We prove it for `x ≥ 83`, in two ranges: + +* for `x < 10⁶`, by a ladder of 53 explicit primes `163, 193, …, 1789201`, each less than + `6/5` times the one before; +* for `x ≥ 10⁶`, with Chebyshev's method. Write `T(N) = log N! = ∑_{d ≤ N} Λ(d) ⌊N/d⌋`. For a + weight list `W` of pairs `(c_k, k)` with `k ∣ 420` and `∑ c_k / k = 0`, the sum + `G(N) = ∑ c_k T(N/k) = ∑_{d ≤ N} Λ(d) H(⌊N/d⌋)` with `H(n) = ∑ c_k ⌊n/k⌋` is `420`-periodic. + Stirling's bounds give `G(420 m) = D m + O(log m)`. Chebyshev's weight + `(1,1), (-1,2), (-1,3), (-1,5), (1,30)` has `H ≤ 1`, which gives `ψ(N) ≥ 0.92129 N - O(log N)`. + A 19-term weight with `H ≥ 1` off multiples of `420` gives + `ψ(N) ≤ 1.06901 N + ψ(N/420) + O(log N)`. Since `2 · 0.92129 > (5/3) · 1.06901 + 0.0056`, + this leaves a gap of about `0.055 x`, which beats `ψ - θ ≤ 2 √x log x` once `x ≥ 10⁶`. +-/ + +namespace Math0.Frontier.A090905 +open Math0.Statements.A090905 +open Finset +open scoped ArithmeticFunction + +/-! ### `log N!` as a von Mangoldt sum -/ + +/-- `log M! = ∑_{d ≤ M} Λ(d) ⌊M/d⌋`. -/ +private theorem log_factorial_eq_sum (M : ℕ) : + Real.log (M.factorial : ℝ) = ∑ d ∈ Ioc 0 M, Λ d * ((M / d : ℕ) : ℝ) := by + induction M with + | zero => simp + | succ M ih => + rw [Nat.factorial_succ, Nat.cast_mul, Real.log_mul (by positivity) (by positivity), ih] + have key : ∀ d ∈ Ioc 0 (M + 1), Λ d * (((M + 1) / d : ℕ) : ℝ) = + Λ d * ((M / d : ℕ) : ℝ) + if d ∣ M + 1 then Λ d else 0 := by + intro d _ + rw [Nat.succ_div] + split_ifs <;> push_cast <;> ring + rw [sum_congr rfl key, sum_add_distrib, ← sum_filter] + have h1 : ∑ d ∈ Ioc 0 (M + 1), Λ d * ((M / d : ℕ) : ℝ) = + ∑ d ∈ Ioc 0 M, Λ d * ((M / d : ℕ) : ℝ) := by + rw [sum_Ioc_succ_top (by omega), Nat.div_eq_of_lt (by omega)] + simp + have h2 : (Ioc 0 (M + 1)).filter (· ∣ M + 1) = (M + 1).divisors := by + ext d + simp only [mem_filter, mem_Ioc, Nat.mem_divisors] + constructor + · rintro ⟨_, h⟩; exact ⟨h, by omega⟩ + · rintro ⟨h, _⟩; exact ⟨⟨Nat.pos_of_dvd_of_pos h (by omega), Nat.le_of_dvd (by omega) h⟩, h⟩ + rw [h1, h2, ArithmeticFunction.vonMangoldt_sum] + push_cast + ring + +/-- `log ⌊N/k⌋! = ∑_{d ≤ N} Λ(d) ⌊⌊N/d⌋/k⌋`. -/ +private theorem log_factorial_div_eq_sum (N k : ℕ) (hk : 0 < k) : + Real.log ((N / k).factorial : ℝ) = ∑ d ∈ Ioc 0 N, Λ d * ((N / d / k : ℕ) : ℝ) := by + rw [log_factorial_eq_sum] + have hsub : Ioc 0 (N / k) ⊆ Ioc 0 N := Ioc_subset_Ioc_right (Nat.div_le_self _ _) + rw [← sum_subset hsub] + · apply sum_congr rfl + intro d _ + rw [Nat.div_div_eq_div_mul, Nat.div_div_eq_div_mul, mul_comm d k] + · intro d hd hd' + simp only [mem_Ioc, not_and, not_le] at hd hd' + have : N / d / k = 0 := by + rw [Nat.div_div_eq_div_mul] + apply Nat.div_eq_of_lt + have := hd' hd.1 + have h3 : N < k * (N / k + 1) := Nat.lt_mul_div_succ N hk + nlinarith + simp [this] + +/-! ### Chebyshev weights -/ + +/-- The step function `H(n) = ∑ c_k ⌊n/k⌋` of a weight list `W` of pairs `(c_k, k)`. -/ +private def Hw (W : List (ℤ × ℕ)) (n : ℕ) : ℤ := (W.map (fun p => p.1 * ((n / p.2 : ℕ) : ℤ))).sum + +/-- The weighted log-factorial sum `G(N) = ∑ c_k log ⌊N/k⌋!`. -/ +private noncomputable def Gw (W : List (ℤ × ℕ)) (N : ℕ) : ℝ := + (W.map (fun p => (p.1 : ℝ) * Real.log ((N / p.2).factorial : ℝ))).sum + +/-- `G(N) = ∑_{d ≤ N} Λ(d) H(⌊N/d⌋)`. -/ +private theorem Gw_eq (W : List (ℤ × ℕ)) (hW : ∀ p ∈ W, 0 < p.2) (N : ℕ) : + Gw W N = ∑ d ∈ Ioc 0 N, Λ d * (Hw W (N / d) : ℝ) := by + induction W with + | nil => simp [Gw, Hw] + | cons p W ih => + have ih' := ih (fun q hq => hW q (List.mem_cons_of_mem _ hq)) + simp only [Gw, Hw, List.map_cons, List.sum_cons] at ih' ⊢ + rw [ih', log_factorial_div_eq_sum N p.2 (hW p List.mem_cons_self), mul_sum, ← sum_add_distrib] + apply sum_congr rfl + intro d _ + simp only [Int.cast_add, Int.cast_mul, Int.cast_natCast] + ring + +/-- `ψ` at a natural number. -/ +private theorem psi_nat (N : ℕ) : Chebyshev.psi N = ∑ d ∈ Ioc 0 N, Λ d := by + simp [Chebyshev.psi] + +/-- If `H ≤ 1` everywhere, then `G(N) ≤ ψ(N)`. -/ +private theorem Gw_le_psi (W : List (ℤ × ℕ)) (hW : ∀ p ∈ W, 0 < p.2) (hH : ∀ n, Hw W n ≤ 1) + (N : ℕ) : Gw W N ≤ Chebyshev.psi N := by + rw [Gw_eq W hW, psi_nat] + apply sum_le_sum + intro d _ + have h1 : (Hw W (N / d) : ℝ) ≤ 1 := by exact_mod_cast hH _ + have h2 := ArithmeticFunction.vonMangoldt_nonneg (n := d) + nlinarith + +/-- If `H ≥ 0` everywhere and `H ≥ 1` off multiples of `P`, then `ψ(N) ≤ G(N) + ψ(N/P)`. -/ +private theorem psi_le_Gw (W : List (ℤ × ℕ)) (hW : ∀ p ∈ W, 0 < p.2) (P : ℕ) (hP : 0 < P) + (hH0 : ∀ n, 0 ≤ Hw W n) (hH1 : ∀ n, n % P ≠ 0 → 1 ≤ Hw W n) (N : ℕ) : + Chebyshev.psi N ≤ Gw W N + Chebyshev.psi (N / P : ℕ) := by + rw [Gw_eq W hW, psi_nat, psi_nat] + rw [← sum_filter_add_sum_filter_not (Ioc 0 N) (fun d => N / d % P = 0)] + have hA : ∑ d ∈ (Ioc 0 N).filter (fun d => N / d % P = 0), Λ d ≤ ∑ d ∈ Ioc 0 (N / P), Λ d := by + apply sum_le_sum_of_subset_of_nonneg + · intro d hd + simp only [mem_filter, mem_Ioc] at hd ⊢ + obtain ⟨⟨hd0, hdN⟩, hm⟩ := hd + refine ⟨hd0, ?_⟩ + have hpos : 0 < N / d := Nat.div_pos hdN hd0 + have hge : P ≤ N / d := Nat.le_of_dvd hpos (Nat.dvd_of_mod_eq_zero hm) + rw [Nat.le_div_iff_mul_le hP] + have := Nat.div_mul_le_self N d + calc d * P ≤ d * (N / d) := Nat.mul_le_mul_left _ hge + _ = N / d * d := mul_comm _ _ + _ ≤ N := this + · intro i _ _; exact ArithmeticFunction.vonMangoldt_nonneg + have hB : ∑ d ∈ (Ioc 0 N).filter (fun d => ¬ N / d % P = 0), Λ d ≤ + ∑ d ∈ Ioc 0 N, Λ d * (Hw W (N / d) : ℝ) := by + calc ∑ d ∈ (Ioc 0 N).filter (fun d => ¬ N / d % P = 0), Λ d + ≤ ∑ d ∈ (Ioc 0 N).filter (fun d => ¬ N / d % P = 0), Λ d * (Hw W (N / d) : ℝ) := by + apply sum_le_sum + intro d hd + simp only [mem_filter] at hd + have h1 : (1 : ℝ) ≤ (Hw W (N / d) : ℝ) := by exact_mod_cast hH1 _ hd.2 + have h2 := ArithmeticFunction.vonMangoldt_nonneg (n := d) + nlinarith + _ ≤ ∑ d ∈ Ioc 0 N, Λ d * (Hw W (N / d) : ℝ) := by + apply sum_le_sum_of_subset_of_nonneg (filter_subset _ _) + intro d _ _ + have h1 : (0 : ℝ) ≤ (Hw W (N / d) : ℝ) := by exact_mod_cast hH0 _ + exact mul_nonneg ArithmeticFunction.vonMangoldt_nonneg h1 + linarith + +/-! ### Numerical constants and Stirling bounds -/ + +/-- Bounds on `log 3`. -/ +private theorem log_three_bounds : 1.098612 < Real.log 3 ∧ Real.log 3 < 1.098613 := by + have h := Real.abs_log_sub_add_sum_range_le (x := 1/4) (by norm_num [abs_of_pos]) 16 + have h4 : Real.log (1 - 1/4) = Real.log 3 - 2 * Real.log 2 := by + rw [show (1:ℝ) - 1/4 = 3 / 2^2 by norm_num, Real.log_div (by norm_num) (by norm_num), + Real.log_pow]; push_cast; ring + rw [h4] at h + simp only [Finset.sum_range_succ, Finset.sum_range_zero] at h + norm_num [abs_of_pos] at h + rw [abs_le] at h + have := Real.log_two_gt_d9 + have := Real.log_two_lt_d9 + constructor <;> nlinarith [h.1, h.2] + +/-- Bounds on `log 5`. -/ +private theorem log_five_bounds : 1.609437 < Real.log 5 ∧ Real.log 5 < 1.609438 := by + have h := Real.abs_log_sub_add_sum_range_le (x := 1/5) (by norm_num [abs_of_pos]) 16 + have h4 : Real.log (1 - 1/5) = 2 * Real.log 2 - Real.log 5 := by + rw [show (1:ℝ) - 1/5 = 2^2 / 5 by norm_num, Real.log_div (by norm_num) (by norm_num), + Real.log_pow]; push_cast; ring + rw [h4] at h + simp only [Finset.sum_range_succ, Finset.sum_range_zero] at h + norm_num [abs_of_pos] at h + rw [abs_le] at h + have := Real.log_two_gt_d9 + have := Real.log_two_lt_d9 + constructor <;> nlinarith [h.1, h.2] + +/-- Bounds on `log 7`. -/ +private theorem log_seven_bounds : 1.945910 < Real.log 7 ∧ Real.log 7 < 1.945911 := by + have h := Real.abs_log_sub_add_sum_range_le (x := 1/8) (by norm_num [abs_of_pos]) 16 + have h4 : Real.log (1 - 1/8) = Real.log 7 - 3 * Real.log 2 := by + rw [show (1:ℝ) - 1/8 = 7 / 2^3 by norm_num, Real.log_div (by norm_num) (by norm_num), + Real.log_pow]; push_cast; ring + rw [h4] at h + simp only [Finset.sum_range_succ, Finset.sum_range_zero] at h + norm_num [abs_of_pos] at h + rw [abs_le] at h + have := Real.log_two_gt_d9 + have := Real.log_two_lt_d9 + constructor <;> nlinarith [h.1, h.2] + +/-- Stirling lower bound: `log M! ≥ M log M - M + (log M)/2 + 1/2`. -/ +private theorem log_fact_lower (M : ℕ) (hM : 1 ≤ M) : + (M : ℝ) * Real.log M - M + Real.log M / 2 + 1 / 2 ≤ Real.log (M.factorial : ℝ) := by + have h := Stirling.le_log_factorial_stirling (n := M) (by omega) + have h2 : 1 ≤ Real.log (2 * Real.pi) := by + rw [Real.le_log_iff_exp_le (by positivity)] + have := Real.exp_one_lt_d9 + have := Real.pi_gt_three + linarith + linarith + +/-- Stirling upper bound: `log M! ≤ M log M - M + (log M)/2 + 1`. -/ +private theorem log_fact_upper (M : ℕ) (hM : 1 ≤ M) : + Real.log (M.factorial : ℝ) ≤ (M : ℝ) * Real.log M - M + Real.log M / 2 + 1 := by + obtain ⟨n, rfl⟩ : ∃ n, M = n + 1 := ⟨M - 1, by omega⟩ + have h := Stirling.log_stirlingSeq'_antitone (Nat.zero_le n) + simp only [Function.comp_apply, Stirling.stirlingSeq_one] at h + rw [Stirling.log_stirlingSeq_formula] at h + have e1 : Real.log (Real.exp 1 / √2) = 1 - Real.log 2 / 2 := by + rw [Real.log_div (by positivity) (by positivity), Real.log_exp, Real.log_sqrt (by norm_num)] + have e2 : Real.log (2 * ((n + 1 : ℕ) : ℝ)) = Real.log 2 + Real.log ((n + 1 : ℕ) : ℝ) := + Real.log_mul (by norm_num) (by positivity) + have e3 : Real.log (((n + 1 : ℕ) : ℝ) / Real.exp 1) = Real.log ((n + 1 : ℕ) : ℝ) - 1 := by + rw [Real.log_div (by positivity) (by positivity), Real.log_exp] + rw [e1, e2, e3] at h + nlinarith + +/-! ### Evaluating `G(P m)` -/ + +/-- `∑ c_k (P/k) log(P/k)`. -/ +private noncomputable def D1 (W : List (ℤ × ℕ)) (P : ℕ) : ℝ := + (W.map fun p => (p.1 : ℝ) * ((P / p.2 : ℕ) : ℝ) * Real.log ((P / p.2 : ℕ) : ℝ)).sum +/-- `∑ c_k log(P/k)`. -/ +private noncomputable def D2 (W : List (ℤ × ℕ)) (P : ℕ) : ℝ := + (W.map fun p => (p.1 : ℝ) * Real.log ((P / p.2 : ℕ) : ℝ)).sum +/-- `∑ c_k`. -/ +private def Sw (W : List (ℤ × ℕ)) : ℤ := (W.map Prod.fst).sum +/-- Upper error constant from Stirling. -/ +private noncomputable def Eu (W : List (ℤ × ℕ)) : ℝ := + (W.map fun p => if 0 ≤ p.1 then (p.1 : ℝ) else (p.1 : ℝ) / 2).sum +/-- Lower error constant from Stirling. -/ +private noncomputable def El (W : List (ℤ × ℕ)) : ℝ := + (W.map fun p => if 0 ≤ p.1 then (p.1 : ℝ) / 2 else (p.1 : ℝ)).sum +/-- `∑ c_k (P/k)` (zero for a balanced weight). -/ +private def Rw (W : List (ℤ × ℕ)) (P : ℕ) : ℤ := (W.map fun p => p.1 * ((P / p.2 : ℕ) : ℤ)).sum + +/-- Stirling bounds for one term `c log (r m)!`. -/ +private theorem term_bounds (c : ℤ) (r m : ℕ) (hr : 1 ≤ r) (hm : 1 ≤ m) : + (c : ℝ) * Real.log ((r * m).factorial : ℝ) ≤ + ((m : ℝ) * Real.log m - m) * ((c * r : ℤ) : ℝ) + m * ((c : ℝ) * r * Real.log r) + + (c : ℝ) * Real.log r / 2 + (c : ℝ) / 2 * Real.log m + + (if 0 ≤ c then (c : ℝ) else (c : ℝ) / 2) ∧ + ((m : ℝ) * Real.log m - m) * ((c * r : ℤ) : ℝ) + m * ((c : ℝ) * r * Real.log r) + + (c : ℝ) * Real.log r / 2 + (c : ℝ) / 2 * Real.log m + + (if 0 ≤ c then (c : ℝ) / 2 else (c : ℝ)) ≤ + (c : ℝ) * Real.log ((r * m).factorial : ℝ) := by + have hrm : 1 ≤ r * m := Nat.one_le_iff_ne_zero.mpr (by positivity) + have hU := log_fact_upper (r * m) hrm + have hL := log_fact_lower (r * m) hrm + have hlog : Real.log ((r * m : ℕ) : ℝ) = Real.log r + Real.log m := by + push_cast + exact Real.log_mul (by positivity) (by positivity) + rw [hlog] at hU hL + push_cast at hU hL ⊢ + have key : (c : ℝ) * (((r : ℝ) * m) * (Real.log r + Real.log m) - r * m + + (Real.log r + Real.log m) / 2) = + ((m : ℝ) * Real.log m - m) * ((c : ℝ) * r) + m * ((c : ℝ) * r * Real.log r) + + (c : ℝ) * Real.log r / 2 + (c : ℝ) / 2 * Real.log m := by ring + split_ifs with hc + · have hc' : (0 : ℝ) ≤ c := by exact_mod_cast hc + constructor <;> nlinarith + · have hc' : (c : ℝ) < 0 := by exact_mod_cast not_le.mp hc + constructor <;> nlinarith + +/-- Two-sided bounds for `G(P m)` when every `k` divides `P`. -/ +private theorem Gw_bounds (W : List (ℤ × ℕ)) (P m : ℕ) (hm : 1 ≤ m) + (hW : ∀ p ∈ W, 0 < p.2 ∧ p.2 ∣ P ∧ p.2 ≤ P) : + Gw W (P * m) ≤ ((m : ℝ) * Real.log m - m) * (Rw W P : ℝ) + m * D1 W P + D2 W P / 2 + + (Sw W : ℝ) / 2 * Real.log m + Eu W ∧ + ((m : ℝ) * Real.log m - m) * (Rw W P : ℝ) + m * D1 W P + D2 W P / 2 + + (Sw W : ℝ) / 2 * Real.log m + El W ≤ Gw W (P * m) := by + induction W with + | nil => simp [Gw, Rw, D1, D2, Sw, Eu, El] + | cons p W ih => + obtain ⟨ih1, ih2⟩ := ih (fun q hq => hW q (List.mem_cons_of_mem _ hq)) + obtain ⟨hp0, hpd, hpP⟩ := hW p List.mem_cons_self + have hr : 1 ≤ P / p.2 := (Nat.one_le_div_iff hp0).mpr hpP + have hdiv : P * m / p.2 = P / p.2 * m := (Nat.div_mul_right_comm hpd m).symm + obtain ⟨t1, t2⟩ := term_bounds p.1 (P / p.2) m hr hm + simp only [Gw, Rw, D1, D2, Sw, Eu, El, List.map_cons, List.sum_cons, hdiv] at ih1 ih2 t1 t2 ⊢ + push_cast at ih1 ih2 t1 t2 ⊢ + constructor <;> linarith + +/-- Chebyshev's weight `T(x) - T(x/2) - T(x/3) - T(x/5) + T(x/30)`. -/ +private def WL : List (ℤ × ℕ) := [(1, 1), (-1, 2), (-1, 3), (-1, 5), (1, 30)] + +/-- A weight with `H ≥ 1` off multiples of `420` and `H ≥ 0` everywhere. -/ +private def WU : List (ℤ × ℕ) := [(1, 1), (-1, 2), (-1, 3), (-1, 5), (1, 6), (-1, 7), (1, 10), + (-1, 12), (1, 14), (-1, 20), (-1, 30), (1, 35), (-1, 42), (1, 60), (-1, 70), (1, 84), (-1, 105), + (1, 210), (-4, 420)] + +/-- `H(n) = H(n mod P) + ⌊n/P⌋ ∑ c_k (P/k)`. -/ +private theorem Hw_mod (W : List (ℤ × ℕ)) (P : ℕ) (hW : ∀ p ∈ W, 0 < p.2 ∧ p.2 ∣ P) (n : ℕ) : + Hw W n = Hw W (n % P) + ((n / P : ℕ) : ℤ) * Rw W P := by + induction W with + | nil => simp [Hw, Rw] + | cons p W ih => + have ih' := ih (fun q hq => hW q (List.mem_cons_of_mem _ hq)) + obtain ⟨hp0, k, hk⟩ := hW p List.mem_cons_self + simp only [Hw, Rw, List.map_cons, List.sum_cons] at ih' ⊢ + have hdiv : n / p.2 = n % P / p.2 + (P / p.2) * (n / P) := by + subst hk + rw [Nat.mul_div_cancel_left k hp0] + conv_lhs => rw [← Nat.mod_add_div n (p.2 * k), mul_assoc] + exact Nat.add_mul_div_left _ _ hp0 + rw [ih', hdiv] + push_cast + ring + +/-- Chebyshev's step function is at most `1`. -/ +private theorem HL_le (n : ℕ) : Hw WL n ≤ 1 := by + have hR : Rw WL 30 = 0 := by decide + rw [Hw_mod WL 30 (by decide) n, hR, mul_zero, add_zero] + have h : ∀ r, r < 30 → Hw WL r ≤ 1 := by decide + exact h _ (Nat.mod_lt _ (by norm_num)) + +/-- The upper step function is `≥ 0`, and `≥ 1` off multiples of `420`. -/ +private theorem HU_spec (n : ℕ) : 0 ≤ Hw WU n ∧ (n % 420 ≠ 0 → 1 ≤ Hw WU n) := by + have hR : Rw WU 420 = 0 := by decide + rw [Hw_mod WU 420 (by decide) n, hR, mul_zero, add_zero] + have h : ∀ r, r < 420 → 0 ≤ Hw WU r ∧ (r ≠ 0 → 1 ≤ Hw WU r) := by decide +kernel + exact h _ (Nat.mod_lt _ (by norm_num)) + +/-- `log (2^a 3^b 5^c 7^d)`. -/ +private theorem log_smooth (a b c d : ℕ) : + Real.log ((2:ℝ) ^ a * 3 ^ b * 5 ^ c * 7 ^ d) = + a * Real.log 2 + b * Real.log 3 + c * Real.log 5 + d * Real.log 7 := by + rw [Real.log_mul (by positivity) (by positivity), Real.log_mul (by positivity) (by positivity), + Real.log_mul (by positivity) (by positivity), Real.log_pow, Real.log_pow, Real.log_pow, + Real.log_pow] + +/-- Constants of the lower weight: `D1 = 420 · 0.92129…`. -/ +private theorem D_WL : 386.94 ≤ D1 WL 420 ∧ -6.05 ≤ D2 WL 420 := by + have h420 := log_smooth 2 1 1 1 + have h210 := log_smooth 1 1 1 1 + have h140 := log_smooth 2 0 1 1 + have h84 := log_smooth 2 1 0 1 + have h14 := log_smooth 1 0 0 1 + norm_num at h420 h210 h140 h84 h14 + have := Real.log_two_gt_d9 + have := Real.log_two_lt_d9 + have := log_three_bounds + have := log_five_bounds + have := log_seven_bounds + simp only [D1, D2, WL, List.map_cons, List.map_nil, List.sum_cons, List.sum_nil] + norm_num + constructor <;> linarith + +/-- Constants of the upper weight: `D1 = 420 · 1.06900…`. -/ +private theorem D_WU : D1 WU 420 ≤ 448.99 ∧ D2 WU 420 ≤ -9.37 := by + have h420 := log_smooth 2 1 1 1 + have h210 := log_smooth 1 1 1 1 + have h140 := log_smooth 2 0 1 1 + have h84 := log_smooth 2 1 0 1 + have h70 := log_smooth 1 0 1 1 + have h60 := log_smooth 2 1 1 0 + have h42 := log_smooth 1 1 0 1 + have h35 := log_smooth 0 0 1 1 + have h30 := log_smooth 1 1 1 0 + have h21 := log_smooth 0 1 0 1 + have h14 := log_smooth 1 0 0 1 + have h12 := log_smooth 2 1 0 0 + have h10 := log_smooth 1 0 1 0 + have h6 := log_smooth 1 1 0 0 + have h4 := log_smooth 2 0 0 0 + norm_num at h420 h210 h140 h84 h70 h60 h42 h35 h30 h21 h14 h12 h10 h6 h4 + have := Real.log_two_gt_d9 + have := Real.log_two_lt_d9 + have := log_three_bounds + have := log_five_bounds + have := log_seven_bounds + simp only [D1, D2, WU, List.map_cons, List.map_nil, List.sum_cons, List.sum_nil] + norm_num + constructor <;> linarith + +/-- The remaining constants of the two weights. -/ +private theorem consts : Sw WL = -1 ∧ Sw WU = -6 ∧ El WL = -2 ∧ Eu WU = 1 ∧ Rw WL 420 = 0 ∧ + Rw WU 420 = 0 := by + refine ⟨by decide, by decide, ?_, ?_, by decide, by decide⟩ + · simp only [El, WL, List.map_cons, List.map_nil, List.sum_cons, List.sum_nil]; norm_num + · simp only [Eu, WU, List.map_cons, List.map_nil, List.sum_cons, List.sum_nil]; norm_num + +/-- Lower bound `ψ(420 m) ≥ 386.94 m - O(log m)`. -/ +private theorem psi_lower (m : ℕ) (hm : 1 ≤ m) : + 386.94 * (m : ℝ) - 6.05 / 2 - Real.log m / 2 - 2 ≤ Chebyshev.psi ((420 * m : ℕ) : ℝ) := by + have hW : ∀ p ∈ WL, 0 < p.2 ∧ p.2 ∣ 420 ∧ p.2 ≤ 420 := by decide + have h1 := Gw_le_psi WL (fun p hp => (hW p hp).1) HL_le (420 * m) + have h2 := (Gw_bounds WL 420 m hm hW).2 + obtain ⟨hD1, hD2⟩ := D_WL + obtain ⟨hS, -, hEl, -, hR, -⟩ := consts + rw [hS, hEl, hR] at h2 + have hm' : (1 : ℝ) ≤ m := by exact_mod_cast hm + have : 386.94 * (m : ℝ) ≤ m * D1 WL 420 := by nlinarith + push_cast at h2 + linarith + +/-- Upper bound `ψ(420 m) ≤ 448.99 m + ψ(m) - O(1)`. -/ +private theorem psi_upper (m : ℕ) (hm : 1 ≤ m) : + Chebyshev.psi ((420 * m : ℕ) : ℝ) ≤ + 448.99 * (m : ℝ) - 9.37 / 2 - 3 * Real.log m + 1 + Chebyshev.psi (m : ℝ) := by + have hW : ∀ p ∈ WU, 0 < p.2 ∧ p.2 ∣ 420 ∧ p.2 ≤ 420 := by decide + have h1 := psi_le_Gw WU (fun p hp => (hW p hp).1) 420 (by norm_num) (fun n => (HU_spec n).1) + (fun n hn => (HU_spec n).2 hn) (420 * m) + rw [show 420 * m / 420 = m by omega] at h1 + have h2 := (Gw_bounds WU 420 m hm hW).1 + obtain ⟨hD1, hD2⟩ := D_WU + obtain ⟨-, hS, -, hEu, -, hR⟩ := consts + rw [hS, hEu, hR] at h2 + have hm' : (1 : ℝ) ≤ m := by exact_mod_cast hm + have : (m : ℝ) * D1 WU 420 ≤ 448.99 * m := by nlinarith + push_cast at h2 + linarith + +/-! ### A prime between `5x/3` and `2x` -/ + +/-- If `(A, B]` has no prime, then `θ(B) = θ(A)`. -/ +private theorem theta_eq_of_no_prime (A B : ℕ) (hAB : A ≤ B) + (h : ∀ p, A < p → p ≤ B → ¬ p.Prime) : + Chebyshev.theta (B : ℝ) = Chebyshev.theta (A : ℝ) := by + simp only [Chebyshev.theta, Nat.floor_natCast] + congr 1 + ext p + simp only [mem_filter, mem_Ioc] + constructor + · rintro ⟨⟨h0, hB⟩, hp⟩ + refine ⟨⟨h0, ?_⟩, hp⟩ + by_contra hA + exact h p (by omega) hB hp + · rintro ⟨⟨h0, hA⟩, hp⟩ + exact ⟨⟨h0, by omega⟩, hp⟩ + +/-- For `x ≥ 10⁶` there is a prime `p` with `5x < 3p < 6x` (analytic part). -/ +private theorem exists_prime_large (a : ℕ) (ha : 1000000 ≤ a) : + ∃ p, p.Prime ∧ 5 * a < 3 * p ∧ 3 * p < 6 * a := by + obtain ⟨m0, hm0⟩ : ∃ m0, m0 = (2 * a - 1) / 420 := ⟨_, rfl⟩ + obtain ⟨m1, hm1⟩ : ∃ m1, m1 = (5 * a / 3) / 420 + 1 := ⟨_, rfl⟩ + have hm0' : 1 ≤ m0 := by omega + have hm1' : 1 ≤ m1 := by omega + have n1 : 420 * m0 ≤ 2 * a - 1 := by omega + have n2 : 2 * a ≤ 420 * m0 + 420 := by omega + have n3 : 5 * a / 3 ≤ 420 * m1 := by omega + have n4 : 3 * (420 * m1) ≤ 5 * a + 1260 := by omega + have n5 : m1 * 196 ≤ a := by omega + have n6 : m0 ≤ a := by omega + have n7 : m1 ≤ a := by omega + have n8 : 1 ≤ 2 * a - 1 := by omega + have n9 : 2 * a - 1 ≤ 2 * a := by omega + by_contra hne + have hnp : ∀ p, 5 * a / 3 < p → p ≤ 2 * a - 1 → ¬ p.Prime := by + intro p h1 h2 hp + apply hne + exact ⟨p, hp, by omega, by omega⟩ + have hθ := theta_eq_of_no_prime (5 * a / 3) (2 * a - 1) (by omega) hnp + clear hne hnp hm0 hm1 + obtain ⟨x, hx⟩ : ∃ x : ℝ, x = (a : ℝ) := ⟨_, rfl⟩ + have hx6 : (1000000 : ℝ) ≤ x := by rw [hx]; exact_mod_cast ha + obtain ⟨s, hs⟩ : ∃ s : ℝ, s = √x := ⟨_, rfl⟩ + have hs2 : s ^ 2 = x := by rw [hs]; exact Real.sq_sqrt (by linarith) + have hs1000 : 1000 ≤ s := by + rw [hs, show (1000 : ℝ) = √1000000 by + rw [show (1000000 : ℝ) = 1000 ^ 2 by norm_num, Real.sqrt_sq (by norm_num)]] + exact Real.sqrt_le_sqrt hx6 + obtain ⟨lx, hlx⟩ : ∃ lx : ℝ, lx = Real.log x := ⟨_, rfl⟩ + have hlx0 : 0 ≤ lx := by rw [hlx]; exact Real.log_nonneg (by linarith) + have hl2 := Real.log_two_gt_d9 + have hl2' := Real.log_two_lt_d9 + have hl5 := log_five_bounds + have hlog1000 : Real.log 1000 ≤ 6.9078 := by + have := log_smooth 3 0 3 0 + norm_num at this + rw [this]; linarith [hl5.2] + have hlogs : Real.log s ≤ Real.log 1000 + s / 1000 - 1 := by + have h1 := Real.log_le_sub_one_of_pos (show 0 < s / 1000 by positivity) + rw [Real.log_div (by positivity) (by norm_num)] at h1 + linarith + have hlxs : lx = 2 * Real.log s := by + rw [hlx, ← hs2, Real.log_pow]; push_cast; ring + have hL : lx ≤ 11.8157 + s / 500 := by rw [hlxs]; linarith + have hsL : s * lx ≤ 11.8157 * s + s ^ 2 / 500 := by + have := mul_le_mul_of_nonneg_left hL (show 0 ≤ s by linarith) + calc s * lx ≤ s * (11.8157 + s / 500) := this + _ = 11.8157 * s + s ^ 2 / 500 := by ring + -- lower bound for `ψ(2a - 1)` and `θ(2a - 1)` + have hA : (((420 * m0 : ℕ) : ℝ)) ≤ ((2 * a - 1 : ℕ) : ℝ) := by exact_mod_cast n1 + have hψA := Chebyshev.psi_mono hA + have hlow := psi_lower m0 hm0' + have hlogm0 : Real.log (m0 : ℝ) ≤ lx := by + rw [hlx] + apply Real.log_le_log (by exact_mod_cast hm0') + rw [hx]; exact_mod_cast n6 + have hm0r : 2 * x ≤ 420 * (m0 : ℝ) + 420 := by rw [hx]; exact_mod_cast n2 + have h2a1 : (1 : ℝ) ≤ ((2 * a - 1 : ℕ) : ℝ) := by exact_mod_cast n8 + have hθA := Chebyshev.psi_sub_theta_le h2a1 + have h2ax : (((2 * a - 1 : ℕ) : ℝ)) ≤ 2 * x := by + rw [hx]; exact_mod_cast n9 + have hsqA : √(((2 * a - 1 : ℕ) : ℝ)) ≤ 1.4143 * s := by + rw [show 1.4143 * s = √((1.4143 * s) ^ 2) from (Real.sqrt_sq (by positivity)).symm] + apply Real.sqrt_le_sqrt + have e : (1.4143 * s) ^ 2 = 2.00024449 * x := by rw [mul_pow, hs2]; norm_num + rw [e]; linarith + have hlogA : Real.log (((2 * a - 1 : ℕ) : ℝ)) ≤ Real.log 2 + lx := by + rw [hlx, ← Real.log_mul (by norm_num) (by linarith)] + exact Real.log_le_log (by linarith) h2ax + have hprodA : √(((2 * a - 1 : ℕ) : ℝ)) * Real.log (((2 * a - 1 : ℕ) : ℝ)) ≤ + 1.4143 * s * (Real.log 2 + lx) := + mul_le_mul hsqA hlogA (Real.log_nonneg h2a1) (by positivity) + -- upper bound for `ψ(⌊5a/3⌋)` and `θ(⌊5a/3⌋)` + have hB : ((5 * a / 3 : ℕ) : ℝ) ≤ ((420 * m1 : ℕ) : ℝ) := by exact_mod_cast n3 + have hψB := Chebyshev.psi_mono hB + have hθB := Chebyshev.theta_le_psi ((5 * a / 3 : ℕ) : ℝ) + have hup := psi_upper m1 hm1' + have hm1r : 3 * (420 * (m1 : ℝ)) ≤ 5 * x + 1260 := by rw [hx]; exact_mod_cast n4 + have hm1one : (1 : ℝ) ≤ m1 := by exact_mod_cast hm1' + have hψm1 := Chebyshev.psi_le hm1one + have hlogm1 : Real.log (m1 : ℝ) ≤ lx := by + rw [hlx] + apply Real.log_le_log (by linarith) + rw [hx]; exact_mod_cast n7 + have hlogm1' : 0 ≤ Real.log (m1 : ℝ) := Real.log_nonneg hm1one + have hsqm1 : √(m1 : ℝ) ≤ s / 14 := by + rw [show s / 14 = √((s / 14) ^ 2) from (Real.sqrt_sq (by positivity)).symm] + apply Real.sqrt_le_sqrt + have : (m1 : ℝ) * 196 ≤ x := by rw [hx]; exact_mod_cast n5 + have e : (s / 14) ^ 2 = x / 196 := by rw [div_pow, hs2]; norm_num + rw [e]; linarith + have hprodm1 : √(m1 : ℝ) * Real.log (m1 : ℝ) ≤ s / 14 * lx := + mul_le_mul hsqm1 hlogm1 hlogm1' (by positivity) + have hlog4 : Real.log 4 = 2 * Real.log 2 := by + rw [show (4:ℝ) = 2 ^ 2 by norm_num, Real.log_pow]; push_cast; ring + rw [hlog4] at hψm1 + have hss : 1000 * s ≤ s ^ 2 := by + have h := mul_le_mul_of_nonneg_right hs1000 (show (0:ℝ) ≤ s by linarith) + rw [sq]; linarith + have hl2m1 : Real.log 2 * m1 ≤ 0.6932 * m1 := + mul_le_mul_of_nonneg_right (by linarith) (by linarith) + have hl2s : Real.log 2 * s ≤ 0.6932 * s := + mul_le_mul_of_nonneg_right (by linarith) (by linarith) + have e1 : 1.4143 * s * (Real.log 2 + lx) = 1.4143 * (Real.log 2 * s) + 1.4143 * (s * lx) := by + ring + have e2 : s / 14 * lx = (s * lx) / 14 := by ring + have e3 : 2 * Real.log 2 * (m1 : ℝ) = 2 * (Real.log 2 * m1) := by ring + have e4 : 2 * √(m1 : ℝ) * Real.log m1 = 2 * (√(m1 : ℝ) * Real.log m1) := by ring + have e5 : 2 * √(((2 * a - 1 : ℕ) : ℝ)) * Real.log (((2 * a - 1 : ℕ) : ℝ)) = + 2 * (√(((2 * a - 1 : ℕ) : ℝ)) * Real.log (((2 * a - 1 : ℕ) : ℝ))) := by ring + rw [e3, e4] at hψm1 + rw [e5] at hθA + rw [e1] at hprodA + rw [e2] at hprodm1 + linarith + +/-- A ladder of primes, each less than `6/5` times the previous one (starting from `138`). -/ +private def ladder : List ℕ := [163, 193, 229, 271, 317, 379, 449, 523, 619, 739, 883, 1051, 1259, + 1499, 1789, 2143, 2557, 3067, 3677, 4409, 5281, 6337, 7603, 9109, 10909, 13063, 15671, 18803, + 22549, 27043, 32443, 38923, 46703, 56041, 67247, 80687, 96823, 116177, 139409, 167269, 200713, + 240853, 289021, 346793, 416149, 499363, 599231, 719071, 862879, 1035451, 1242517, 1491013, + 1789201] + +/-- `chainOK q L`: each entry of `L` is less than `6/5` times the previous one. -/ +private def chainOK : ℕ → List ℕ → Bool + | _, [] => true + | q, p :: L => decide (5 * p < 6 * q) && chainOK p L + +/-- A ladder of primes covers every `x` in its range. -/ +private theorem ladder_aux (L : List ℕ) (hL : ∀ p ∈ L, p.Prime) : ∀ q, chainOK q L = true → ∀ b, + 3 * q ≤ 5 * b → 5 * b < 3 * L.getLastD q → ∃ p, p.Prime ∧ 5 * b < 3 * p ∧ 3 * p < 6 * b := by + induction L with + | nil => intro q _ b h1 h2; simp at h2; omega + | cons p L ih => + intro q hq b h1 h2 + simp only [chainOK, Bool.and_eq_true, decide_eq_true_eq] at hq + rcases Nat.lt_or_ge (5 * b) (3 * p) with h | h + · exact ⟨p, hL p List.mem_cons_self, h, by omega⟩ + · rw [List.getLastD_cons] at h2 + exact ih (fun r hr => hL r (List.mem_cons_of_mem _ hr)) p hq.2 b h h2 + +/-- The ladder consists of primes. -/ +private theorem ladder_prime : ∀ p ∈ ladder, p.Prime := by + simp only [ladder, List.forall_mem_cons, List.not_mem_nil, IsEmpty.forall_iff, implies_true, + and_true] + and_intros <;> norm_num + +/-- For every `x ≥ 83` there is a prime `p` with `5x < 3p < 6x`. -/ +private theorem exists_prime (b : ℕ) (hb : 83 ≤ b) : + ∃ p, p.Prime ∧ 5 * b < 3 * p ∧ 3 * p < 6 * b := by + rcases Nat.lt_or_ge b 1000000 with h | h + · exact ladder_aux ladder ladder_prime 138 (by decide) b (by omega) (by simp [ladder]; omega) + · exact exists_prime_large b h + +/-! ### The divisibility `(2a)!² ∣ (2b)! (2c)!` -/ + +/-- The floor inequalities behind Legendre's formula, for one prime power `y`. -/ +private theorem pointwise (b a c y : ℕ) (hy : 0 < y) (h2 : a < 2 * b) (h3 : 5 * a < 3 * c) : + 2 * (2 * a / y) ≤ 2 * b / y + 2 * c / y + 1 ∧ + (¬ (c < y ∧ y ≤ 2 * a) → 2 * (2 * a / y) ≤ 2 * b / y + 2 * c / y) ∧ + (13 ≤ 2 * a / y → 2 * (2 * a / y) + 1 ≤ 2 * b / y + 2 * c / y) := by + set k := 2 * a / y with hk + set q1 := 2 * b / y with hq1 + set q2 := 2 * c / y with hq2 + have ek := Nat.div_mul_le_self (2 * a) y + have ek' := Nat.lt_div_mul_add (a := 2 * a) hy + have e1' := Nat.lt_div_mul_add (a := 2 * b) hy + have e2' := Nat.lt_div_mul_add (a := 2 * c) hy + rw [← hk] at ek ek' + rw [← hq1] at e1' + rw [← hq2] at e2' + have A : k < 2 * q1 + 2 := by + have : k * y < (2 * q1 + 2) * y := by nlinarith + exact Nat.lt_of_mul_lt_mul_right this + have B : 5 * k < 3 * q2 + 3 := by + have : (5 * k) * y < (3 * q2 + 3) * y := by nlinarith + exact Nat.lt_of_mul_lt_mul_right this + have C : y ≤ c → 2 ≤ q2 := by + intro hyc + rw [hq2, Nat.le_div_iff_mul_le hy]; omega + have D : y ≤ 2 * a → 1 ≤ q2 := by + intro hya + rw [hq2, Nat.le_div_iff_mul_le hy]; omega + have E : 2 * a < y → k = 0 := by + intro hya + rw [hk]; exact Nat.div_eq_of_lt hya + have F : 1 ≤ k → y ≤ 2 * a := by + intro hk1 + by_contra hcon + have := E (by omega); omega + refine ⟨?_, ?_, ?_⟩ + · rcases Nat.eq_zero_or_pos k with h0 | h0 + · omega + · have := D (F h0); omega + · intro hn + rcases Nat.lt_or_ge (2 * a) y with hya | hya + · have := E hya; omega + · have hyc : y ≤ c := by omega + have := C hyc + omega + · intro h13 + omega + +/-- `(2a)!² ∣ (2b)! (2c)!` for consecutive chain primes `b < a < c` (via Legendre). -/ +private theorem fact_dvd (b a c : ℕ) (hb : 83 ≤ b) (h1 : 5 * b < 3 * a) (h2 : a < 2 * b) + (h3 : 5 * a < 3 * c) (h4 : c < 2 * a) (hgap : ∀ q, c < q → q < 2 * a → ¬ q.Prime) : + (2 * a).factorial * (2 * a).factorial ∣ (2 * b).factorial * (2 * c).factorial := by + rw [← Nat.factorization_prime_le_iff_dvd (by positivity) (by positivity)] + intro p hp + rw [Nat.factorization_mul (by positivity) (by positivity), + Nat.factorization_mul (by positivity) (by positivity)] + simp only [Finsupp.add_apply] + have hB : ∀ n, n ≤ 2 * c → Nat.log p n < 2 * c + 1 := fun n hn => + lt_of_le_of_lt (Nat.log_le_self p n) (by omega) + rw [Nat.factorization_factorial hp (hB (2 * a) (by omega)), + Nat.factorization_factorial hp (hB (2 * b) (by omega)), + Nat.factorization_factorial hp (hB (2 * c) le_rfl), ← sum_add_distrib, ← sum_add_distrib] + have hp2 := hp.two_le + have hpos : ∀ i, 0 < p ^ i := fun i => Nat.pow_pos hp.pos + by_cases hj : ∃ j ∈ Ico 1 (2 * c + 1), c < p ^ j ∧ p ^ j ≤ 2 * a + · obtain ⟨j, hjT, hcj, hja⟩ := hj + have huniq : ∀ i, i ≠ j → ¬ (c < p ^ i ∧ p ^ i ≤ 2 * a) := by + rintro i hij ⟨hci, hia⟩ + rcases Nat.lt_or_gt_of_ne hij with h | h + · have e : p ^ (i + 1) ≤ p ^ j := Nat.pow_le_pow_right hp.pos h + rw [pow_succ] at e + nlinarith + · have e : p ^ (j + 1) ≤ p ^ i := Nat.pow_le_pow_right hp.pos h + rw [pow_succ] at e + nlinarith + have hj1 : j ≠ 1 := by + rintro rfl + rw [pow_one] at hcj hja + rcases Nat.lt_or_ge p (2 * a) with hlt | hge + · exact hgap p hcj hlt hp + · have : p = 2 * a := by omega + have h2p : 2 ∣ p := ⟨a, this⟩ + have := (Nat.prime_dvd_prime_iff_eq Nat.prime_two hp).mp h2p + omega + have hj2 : 2 ≤ j := by simp only [mem_Ico] at hjT; omega + have h13 : 13 ≤ 2 * a / p ^ 1 := by + rw [pow_one, Nat.le_div_iff_mul_le hp.pos] + have e : p ^ 2 ≤ p ^ j := Nat.pow_le_pow_right hp.pos hj2 + rcases Nat.lt_or_ge p 13 with hp13 | hp13 + · omega + · nlinarith + have h1T : 1 ∈ (Ico 1 (2 * c + 1)).erase j := by + simp only [mem_erase, mem_Ico]; omega + rw [← add_sum_erase _ _ hjT, ← add_sum_erase _ _ hjT, ← add_sum_erase _ _ h1T, + ← add_sum_erase _ _ h1T] + have hrest : ∑ x ∈ ((Ico 1 (2 * c + 1)).erase j).erase 1, (2 * a / p ^ x + 2 * a / p ^ x) ≤ + ∑ x ∈ ((Ico 1 (2 * c + 1)).erase j).erase 1, (2 * b / p ^ x + 2 * c / p ^ x) := by + apply sum_le_sum + intro i hi + simp only [mem_erase] at hi + have := (pointwise b a c (p ^ i) (hpos i) h2 h3).2.1 (huniq i hi.2.1) + omega + have hjj := (pointwise b a c (p ^ j) (hpos j) h2 h3).1 + have h11 := (pointwise b a c (p ^ 1) (hpos 1) h2 h3).2.2 h13 + omega + · push Not at hj + apply sum_le_sum + intro i hi + have := (pointwise b a c (p ^ i) (hpos i) h2 h3).2.1 (by + rintro ⟨h5, h6⟩; exact absurd h6 (not_le.mpr (hj i hi h5))) + omega + +/-! ### The inductive step on rows -/ + +/-- `n + i ∣ n (n+1) ⋯ (n+k-1)` for `i < k`. -/ +private theorem dvd_ascFactorial_of_lt (n k i : ℕ) (h : i < k) : n + i ∣ n.ascFactorial k := by + induction k with + | zero => omega + | succ k ih => + rw [Nat.ascFactorial_succ] + rcases Nat.lt_or_ge i k with h' | h' + · exact Dvd.dvd.mul_left (ih h') _ + · have : i = k := by omega + subst this; exact Dvd.intro _ rfl + +/-- A prime `c` divides none of `n, …, n + k - 1` when `c < n` and `n + k ≤ 2c`. -/ +private theorem not_dvd_ascFactorial (c n k : ℕ) (hc : c.Prime) (hn : c < n) (hk : n + k ≤ 2 * c) : + ¬ c ∣ n.ascFactorial k := by + induction k with + | zero => rw [Nat.ascFactorial_zero]; exact hc.not_dvd_one + | succ k ih => + rw [Nat.ascFactorial_succ] + intro hdvd + rcases (Nat.Prime.dvd_mul hc).mp hdvd with h | h + · obtain ⟨t, ht⟩ := h + have h1 : c * 1 < c * t := by rw [mul_one]; omega + have h2 : c * t < c * 2 := by omega + have := Nat.lt_of_mul_lt_mul_left h1 + have := Nat.lt_of_mul_lt_mul_left h2 + omega + · exact ih (by omega) h + +/-- If row `n` is `[2b+1, 2a]`, the least admissible length of row `n + 1` is `2c - 2a`. -/ +private theorem step_core (b a c : ℕ) (hb : 83 ≤ b) (h1 : 5 * b < 3 * a) (h2 : a < 2 * b) + (h3 : 5 * a < 3 * c) (h4 : c < 2 * a) (hc : c.Prime) + (hgap : ∀ q, c < q → q < 2 * a → ¬ q.Prime) : + IsLeast {k | 2 * a - 2 * b ≤ k ∧ + (2 * b + 1).ascFactorial (2 * a - 2 * b) ∣ (2 * a + 1).ascFactorial k} (2 * c - 2 * a) := by + have hX := Nat.factorial_mul_ascFactorial (2 * b) (2 * a - 2 * b) + have hY := Nat.factorial_mul_ascFactorial (2 * a) (2 * c - 2 * a) + rw [show 2 * b + (2 * a - 2 * b) = 2 * a by omega] at hX + rw [show 2 * a + (2 * c - 2 * a) = 2 * c by omega] at hY + have hD := fact_dvd b a c hb h1 h2 h3 h4 hgap + refine ⟨⟨by omega, ?_⟩, ?_⟩ + · have hpos : 0 < (2 * b).factorial * (2 * a).factorial := by positivity + apply Nat.dvd_of_mul_dvd_mul_left hpos + have e1 : (2 * b).factorial * (2 * a).factorial * (2 * b + 1).ascFactorial (2 * a - 2 * b) = + (2 * a).factorial * (2 * a).factorial := by rw [← hX]; ring + have e2 : (2 * b).factorial * (2 * a).factorial * (2 * a + 1).ascFactorial (2 * c - 2 * a) = + (2 * b).factorial * (2 * c).factorial := by rw [← hY]; ring + rw [e1, e2] + exact hD + · rintro k ⟨_, hk2⟩ + by_contra hlt + have hcX : c ∣ (2 * b + 1).ascFactorial (2 * a - 2 * b) := by + have := dvd_ascFactorial_of_lt (2 * b + 1) (2 * a - 2 * b) (c - (2 * b + 1)) (by omega) + rwa [show 2 * b + 1 + (c - (2 * b + 1)) = c by omega] at this + exact not_dvd_ascFactorial c (2 * a + 1) k hc (by omega) (by omega) (hcX.trans hk2) + +/-- The recursion of the Bertrand primes. -/ +private theorem bertrand_succ (n : ℕ) (hn : 1 ≤ n) : + bertrand (n + 1) = Nat.findGreatest Nat.Prime (2 * bertrand n - 1) := by + obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩ + simp only [bertrand, Nat.add_sub_cancel] + exact Function.iterate_succ_apply' _ m 2 + +/-- The largest prime below `2b` is prime, exceeds `5b/3`, and leaves a prime-free gap. -/ +private theorem chain_step (b : ℕ) (hb : 83 ≤ b) : + (Nat.findGreatest Nat.Prime (2 * b - 1)).Prime ∧ + 5 * b < 3 * Nat.findGreatest Nat.Prime (2 * b - 1) ∧ + Nat.findGreatest Nat.Prime (2 * b - 1) < 2 * b ∧ + ∀ q, Nat.findGreatest Nat.Prime (2 * b - 1) < q → q < 2 * b → ¬ q.Prime := by + obtain ⟨p, hp, hp1, hp2⟩ := exists_prime b hb + have hle : p ≤ 2 * b - 1 := by omega + have hc := Nat.findGreatest_spec hle hp + have hpc := Nat.le_findGreatest hle hp + have hcle := Nat.findGreatest_le (P := Nat.Prime) (2 * b - 1) + refine ⟨hc, by omega, by omega, ?_⟩ + intro q hq1 hq2 + exact Nat.findGreatest_is_greatest hq1 (by omega) + +/-- `B (j + 8) ≥ 83`. -/ +private theorem bertrand_ge (j : ℕ) : 83 ≤ bertrand (j + 8) := by + induction j with + | zero => decide +kernel + | succ j ih => + rw [show j + 1 + 8 = (j + 8) + 1 by ring, bertrand_succ _ (by omega)] + have := (chain_step _ ih).2.1 + omega + +/-- For `n ≥ 10`, row `n` is `[2 B(n-2) + 1, 2 B(n-1)]`. -/ +private theorem rows (j : ℕ) : a (j + 10) = 2 * bertrand (j + 8) + 1 ∧ + len (j + 10) = 2 * bertrand (j + 9) - 2 * bertrand (j + 8) := by + induction j with + | zero => + have h1 : a 10 = 167 := by decide +kernel + have h2 : len 10 = 160 := by decide +kernel + have h3 : bertrand 8 = 83 := by decide +kernel + have h4 : bertrand 9 = 163 := by decide +kernel + simp only [zero_add, h1, h2, h3, h4] + norm_num + | succ j ih => + obtain ⟨iha, ihl⟩ := ih + have hb := bertrand_ge j + have hab : bertrand (j + 9) = Nat.findGreatest Nat.Prime (2 * bertrand (j + 8) - 1) := + bertrand_succ (j + 8) (by omega) + have hac : bertrand (j + 10) = Nat.findGreatest Nat.Prime (2 * bertrand (j + 9) - 1) := + bertrand_succ (j + 9) (by omega) + obtain ⟨_, ha1, ha2, _⟩ := chain_step _ hb + rw [← hab] at ha1 ha2 + have ha83 : 83 ≤ bertrand (j + 9) := by omega + obtain ⟨hc0, hc1, hc2, hc3⟩ := chain_step _ ha83 + rw [← hac] at hc0 hc1 hc2 hc3 + have hstep := step_core (bertrand (j + 8)) (bertrand (j + 9)) (bertrand (j + 10)) hb ha1 ha2 + hc1 hc2 hc0 hc3 + have hA : a (j + 1 + 10) = 2 * bertrand (j + 9) + 1 := by + rw [show j + 1 + 10 = (j + 10) + 1 by ring, a_succ _ (by omega), iha, ihl] + omega + refine ⟨by rw [hA], ?_⟩ + have hL := len_succ_isLeast (j + 10) (by omega) + rw [iha, ihl, show j + 10 + 1 = j + 1 + 10 by ring, hA] at hL + rw [show j + 1 + 9 = j + 10 by ring, show j + 1 + 8 = j + 9 by ring] + exact hL.unique hstep + +/-! ### The statement -/ + +/-- The conclusion for one concrete small row. -/ +private theorem small_case (m lo hi p L : ℕ) (hlo : a m = lo) (hhi : last m = hi) + (hL : last (m + 1) = L) (hB : bertrand m = p) (hp : p.Prime) (h1 : lo ≤ p) (h2 : p ≤ hi) + (h3 : L = 2 * p) (hgap : ∀ q, p < q → q ≤ hi → ¬ q.Prime) : + ∃ p, IsGreatest {q : ℕ | q.Prime ∧ a m ≤ q ∧ q ≤ last m} p ∧ + last (m + 1) = 2 * p ∧ p = bertrand m := by + refine ⟨p, ⟨⟨hp, by omega, by omega⟩, ?_⟩, by omega, hB.symm⟩ + rintro q ⟨hq, _, hq2⟩ + by_contra hlt + exact hgap q (by omega) (by omega) hq + +/-- Murthy's conjecture (A090905): for `n > 4` the largest prime `p` of group `n - 1` exists, +the last term of group `n` is `2p`, and `p` is the Bertrand prime `A006992(n - 1)`. -/ +theorem result : statement := by + intro n hn + rcases (show n ≤ 10 ∨ 11 ≤ n by omega) with hs | hb + · interval_cases n + · exact small_case 4 5 8 7 14 (by decide +kernel) (by decide +kernel) (by decide +kernel) + (by decide +kernel) (by norm_num) (by norm_num) (by norm_num) (by norm_num) + (fun q h1 h2 => by interval_cases q; norm_num) + · exact small_case 5 9 14 13 26 (by decide +kernel) (by decide +kernel) (by decide +kernel) + (by decide +kernel) (by norm_num) (by norm_num) (by norm_num) (by norm_num) + (fun q h1 h2 => by interval_cases q; norm_num) + · exact small_case 6 15 26 23 46 (by decide +kernel) (by decide +kernel) (by decide +kernel) + (by decide +kernel) (by norm_num) (by norm_num) (by norm_num) (by norm_num) + (fun q h1 h2 => by interval_cases q <;> norm_num) + · exact small_case 7 27 46 43 86 (by decide +kernel) (by decide +kernel) (by decide +kernel) + (by decide +kernel) (by norm_num) (by norm_num) (by norm_num) (by norm_num) + (fun q h1 h2 => by interval_cases q <;> norm_num) + · exact small_case 8 47 86 83 166 (by decide +kernel) (by decide +kernel) (by decide +kernel) + (by decide +kernel) (by norm_num) (by norm_num) (by norm_num) (by norm_num) + (fun q h1 h2 => by interval_cases q <;> norm_num) + · exact small_case 9 87 166 163 326 (by decide +kernel) (by decide +kernel) (by decide +kernel) + (by decide +kernel) (by norm_num) (by norm_num) (by norm_num) (by norm_num) + (fun q h1 h2 => by interval_cases q <;> norm_num) + · obtain ⟨j, rfl⟩ : ∃ j, n = j + 11 := ⟨n - 11, by omega⟩ + rw [show j + 11 - 1 = j + 10 by omega] + obtain ⟨ha0, hl0⟩ := rows j + obtain ⟨ha1, hl1⟩ := rows (j + 1) + have hb := bertrand_ge j + have hab : bertrand (j + 9) = Nat.findGreatest Nat.Prime (2 * bertrand (j + 8) - 1) := + bertrand_succ (j + 8) (by omega) + have hac : bertrand (j + 10) = Nat.findGreatest Nat.Prime (2 * bertrand (j + 9) - 1) := + bertrand_succ (j + 9) (by omega) + obtain ⟨_, ha1', ha2', _⟩ := chain_step _ hb + rw [← hab] at ha1' ha2' + have ha83 : 83 ≤ bertrand (j + 9) := by omega + obtain ⟨hc0, hc1, hc2, hc3⟩ := chain_step _ ha83 + rw [← hac] at hc0 hc1 hc2 hc3 + simp only [show j + 1 + 10 = j + 11 by ring, show j + 1 + 9 = j + 10 by ring, + show j + 1 + 8 = j + 9 by ring] at ha1 hl1 + have hlast0 : last (j + 10) = 2 * bertrand (j + 9) := by + simp only [last, ha0, hl0]; omega + have hlast1 : last (j + 11) = 2 * bertrand (j + 10) := by + simp only [last, ha1, hl1]; omega + refine ⟨bertrand (j + 10), ⟨⟨hc0, ?_, ?_⟩, ?_⟩, hlast1, rfl⟩ + · rw [ha0]; omega + · rw [hlast0]; omega + · rintro q ⟨hq, _, hq2⟩ + rw [hlast0] at hq2 + by_contra hlt + rcases Nat.lt_or_ge q (2 * bertrand (j + 9)) with h | h + · exact hc3 q (by omega) h hq + · have hq' : q = 2 * bertrand (j + 9) := by omega + have h2q : 2 ∣ q := ⟨_, hq'⟩ + have := (Nat.prime_dvd_prime_iff_eq Nat.prime_two hq).mp h2q + omega + +end Math0.Frontier.A090905 + +#math0_settles Math0.Frontier.A090905.result Math0.Statements.A090905.statement diff --git a/lean/Math0/Frontier/OEIS/A091817.lean b/lean/Math0/Frontier/OEIS/A091817.lean new file mode 100644 index 0000000..70bee19 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A091817.lean @@ -0,0 +1,153 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A091817 +import Math0.Audit + +/-! +# Quet's integrality conjecture for A091817 holds + +For every prime `p ≥ 3`, writing `H(p-3) = N/D` in lowest terms, `p ∣ 2N - 3D`; hence every +term `a n = (2N - 3D)/p` of A091817 is an integer. + +Idea: work in `ZMod p`. Put `S m = ∑_{k=1}^{m} k⁻¹ ∈ ZMod p`. For `m < p` the rational +`H m * m!` is an integer `A` with `A ≡ m! * S m (mod p)` (induction on `m`, using that +`1, …, m` are units mod `p`). Since `x ↦ x⁻¹` permutes `ZMod p`, `S (p-1) = ∑_x x⁻¹ = ∑_x x = 0` +(for `p` odd), and removing the last two terms `(-2)⁻¹ + (-1)⁻¹ = -3/2` gives +`2 * S (p-3) = 3`. From `N * m! = A * D` and `m! ≢ 0 (mod p)` we get `N ≡ S (p-3) * D`, so +`2N - 3D ≡ (2 S (p-3) - 3) D = 0 (mod p)`. +-/ + +namespace Math0.Frontier.A091817 +open Math0.Statements.A091817 + +/-- The partial harmonic sum `∑_{k=1}^{m} k⁻¹` computed in `ZMod p`. -/ +private def invSum (p m : ℕ) : ZMod p := ∑ k ∈ Finset.range m, ((k : ZMod p) + 1)⁻¹ + +/-- Recursion for the harmonic numbers: `H (m+1) = H m + 1/(m+1)`. -/ +private theorem H_succ (m : ℕ) : H (m + 1) = H m + 1 / ((m : ℚ) + 1) := by + simp [H, List.range_succ] + +/-- For `m < p`, `H m * m!` is an integer `A`, and `A ≡ m! * invSum p m (mod p)`. -/ +private theorem key (p : ℕ) [Fact p.Prime] : ∀ m, m < p → ∃ a : ℤ, + H m * (m.factorial : ℚ) = a ∧ (a : ZMod p) = (m.factorial : ZMod p) * invSum p m := by + intro m + induction m with + | zero => intro _; exact ⟨0, by simp [H], by simp [invSum]⟩ + | succ m ih => + intro hm + obtain ⟨a, h1, h2⟩ := ih (by omega) + refine ⟨a * (m + 1) + m.factorial, ?_, ?_⟩ + · rw [H_succ, Nat.factorial_succ] + push_cast + rw [← h1] + field_simp + · have hne : ((m : ZMod p) + 1) ≠ 0 := by + have : ((m + 1 : ℕ) : ZMod p) ≠ 0 := by + rw [Ne, ZMod.natCast_eq_zero_iff] + intro hd + have := Nat.le_of_dvd (by omega) hd + omega + exact_mod_cast this + rw [invSum, Finset.sum_range_succ, ← invSum, Nat.factorial_succ] + push_cast + rw [h2] + have : ((m : ZMod p) + 1) * (m.factorial : ZMod p) * ((m : ZMod p) + 1)⁻¹ + = (m.factorial : ZMod p) := by + rw [mul_comm ((m : ZMod p) + 1), mul_assoc, mul_inv_cancel₀ hne, mul_one] + linear_combination (-1 : ZMod p) * this + +/-- For an odd prime `p`, `∑_{k=1}^{p} k⁻¹ = 0` in `ZMod p` (the term `k = p` is `0⁻¹ = 0`): +inversion permutes `ZMod p`, and `∑_x x = 0`. -/ +private theorem invSum_self (p : ℕ) [hp : Fact p.Prime] (h2 : p ≠ 2) : invSum p p = 0 := by + have hsum : ∑ x : ZMod p, x⁻¹ = 0 := by + have e : ∑ x : ZMod p, x⁻¹ = ∑ x : ZMod p, x := + Equiv.sum_comp (Equiv.inv (ZMod p)) (fun x => x) + rw [e] + have := FiniteField.sum_pow_lt_card_sub_one (ZMod p) 1 (by + rw [ZMod.card]; have := hp.out.two_le; omega) + simpa using this + have hrange : ∑ k ∈ Finset.range p, ((k : ZMod p))⁻¹ = ∑ x : ZMod p, x⁻¹ := by + apply Finset.sum_nbij' (fun k : ℕ => (k : ZMod p)) (fun x : ZMod p => x.val) + · intro a _; exact Finset.mem_univ _ + · intro x _; rw [Finset.mem_range]; exact ZMod.val_lt x + · intro a ha; rw [Finset.mem_range] at ha; exact ZMod.val_cast_of_lt ha + · intro x _; exact ZMod.natCast_zmod_val x + · intro a _; rfl + rw [← hsum, ← hrange, invSum] + have := Finset.sum_range_succ' (fun k => ((k : ZMod p))⁻¹) p + rw [Finset.sum_range_succ] at this + simp only [ZMod.natCast_self, inv_zero, add_zero, Nat.cast_zero] at this + rw [this] + simp + +/-- For an odd prime `p`, `2 * ∑_{k=1}^{p-3} k⁻¹ = 3` in `ZMod p`. -/ +private theorem invSum_val (p : ℕ) [hp : Fact p.Prime] (h2 : p ≠ 2) : + 2 * invSum p (p - 3) = 3 := by + obtain ⟨q, rfl⟩ : ∃ q, p = q + 3 := ⟨p - 3, by have := hp.out.two_le; omega⟩ + have h0 := invSum_self (q + 3) h2 + rw [Nat.add_sub_cancel] + rw [invSum, Finset.sum_range_succ, Finset.sum_range_succ, Finset.sum_range_succ, ← invSum] at h0 + have hq : ((q : ZMod (q + 3))) = -3 := by + have : (((q + 3 : ℕ)) : ZMod (q + 3)) = 0 := ZMod.natCast_self _ + push_cast at this; linear_combination this + have htwo : (2 : ZMod (q + 3)) ≠ 0 := by + have : ((2 : ℕ) : ZMod (q + 3)) ≠ 0 := by + rw [Ne, ZMod.natCast_eq_zero_iff] + intro hd + have := Nat.le_of_dvd (by omega) hd + omega + exact_mod_cast this + have k1 : ((q : ZMod (q + 3)) + 1)⁻¹ = -2⁻¹ := by + rw [hq, show (-3 : ZMod (q + 3)) + 1 = -2 by ring, inv_neg] + have k2 : (((q + 1 : ℕ) : ZMod (q + 3)) + 1)⁻¹ = -1 := by + push_cast; rw [hq, show (-3 : ZMod (q + 3)) + 1 + 1 = -1 by ring, inv_neg, inv_one] + have k3 : (((q + 2 : ℕ) : ZMod (q + 3)) + 1)⁻¹ = 0 := by + push_cast; rw [hq, show (-3 : ZMod (q + 3)) + 2 + 1 = 0 by ring, inv_zero] + rw [k1, k2, k3] at h0 + have : (2 : ZMod (q + 3)) * 2⁻¹ = 1 := mul_inv_cancel₀ htwo + linear_combination 2 * h0 + this + +/-- Quet's conjecture (A091817): for every `n ≥ 1`, with `p` the `(n+1)`-th prime and +`H(p-3) = N/D` in lowest terms, `(2N - 3D)/p` is an integer. -/ +theorem result : statement := by + intro n hn + have hp : (primeAt n).Prime := by rw [primeAt_eq_nth]; exact Nat.prime_nth_prime n + have hp3 : 3 ≤ primeAt n := by + rw [primeAt_eq_nth] + have := Nat.nth_strictMono (p := Nat.Prime) Nat.infinite_setOfPred_prime (show 0 < n by omega) + rw [Nat.nth_prime_zero_eq_two] at this + omega + show ∃ z : ℤ, term (primeAt n) = z + generalize primeAt n = p at hp hp3 + have := Fact.mk hp + obtain ⟨A, h1, h2⟩ := key p (p - 3) (by omega) + have hND : (H (p - 3)).num * ((p - 3).factorial : ℤ) = A * (H (p - 3)).den := by + have : ((H (p - 3)).num : ℚ) * (p - 3).factorial = A * (H (p - 3)).den := by + rw [← h1, ← Rat.mul_den_eq_num]; ring + exact_mod_cast this + have hfac : ((p - 3).factorial : ZMod p) ≠ 0 := by + rw [Ne, ZMod.natCast_eq_zero_iff, hp.dvd_factorial]; omega + have hz : ((2 * (H (p - 3)).num - 3 * ((H (p - 3)).den : ℤ) : ℤ) : ZMod p) = 0 := by + have := congrArg (Int.cast : ℤ → ZMod p) hND + push_cast at this + rw [h2] at this + have hS := invSum_val p (by omega) + have hN : ((H (p - 3)).num : ZMod p) = invSum p (p - 3) * (H (p - 3)).den := by + apply mul_right_cancel₀ hfac; linear_combination this + push_cast + rw [hN]; linear_combination ((H (p - 3)).den : ZMod p) * hS + rw [ZMod.intCast_zmod_eq_zero_iff_dvd] at hz + obtain ⟨z, hz⟩ := hz + refine ⟨z, ?_⟩ + have hq : ((2 * (H (p - 3)).num - 3 * ((H (p - 3)).den : ℤ) : ℤ) : ℚ) = (p : ℚ) * z := by + exact_mod_cast hz + have hp0 : (p : ℚ) ≠ 0 := by exact_mod_cast hp.ne_zero + unfold term + rw [div_eq_iff hp0] + push_cast at hq ⊢ + linear_combination hq + +end Math0.Frontier.A091817 + +#math0_settles Math0.Frontier.A091817.result Math0.Statements.A091817.statement diff --git a/lean/Math0/Frontier/OEIS/A092054.lean b/lean/Math0/Frontier/OEIS/A092054.lean new file mode 100644 index 0000000..706326c --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A092054.lean @@ -0,0 +1,390 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A092054 +import Math0.Audit + +/-! +# Convergents of `[1; 1/2, 1/3, …]`: numerator plus denominator is a power of two (A092054) + +We prove the conjecture in OEIS A092054 (Franklin T. Adams-Watters, 2006): for every `n ≥ 1`, +writing the convergent `[1; 1/2, …, 1/n] = p/q` in lowest terms, `p + q = 2 ^ a(n)` with +`a(n) = v₂(n!) + v₂((n+1)!) = A011371(n) + A011371(n+1) = 2n + 1 - s₂(n) - s₂(n+1) += Σ_{k=1}^n A001511(⌊(k+1)/2⌋)`. + +**Convergents.** With a variable last tail `t > 0`, the continued fraction +`[1; 1/2, …, 1/n, t]` equals `(P n · t + n P (n-1)) / (Q n · t + n Q (n-1))`, where +`P, Q` are the scaled convergent numerators/denominators: `P 0 = 1, P 1 = 1, +P (n+2) = P (n+1) + (n+1)(n+2) P n` and `Q 0 = 0, Q 1 = 1` with the same recursion +(`tailEval_range`). Hence `conv n = P n / Q n` (`conv_eq`). + +**Closed forms.** With `D m = (2m-1)!!`: `P (2m) = D(m)² (2m+1)`, `P (2m+1) = D(m+1)²` (so +`P n` is odd), and `T = P + Q` satisfies `T (2m) = 4^m (m!)²`, +`T (2m+1) = 2^(2m+1) m! (m+1)!` (`P_closed`, `T_closed`, by induction). + +**Reduction.** Write `m! = 2^v w` with `w` odd. Since `m! m! ∣ (2m)! = 2^m m! D(m)`, `w ∣ D(m)` +(`odd_part`). So `T n = 2^e u` with `u ∣ P n` and `e = v₂(n!) + v₂((n+1)!)` (`key`). As +`P n` is odd, `gcd(P n, Q n) = gcd(P n, T n) = u`, so `p + q = T n / u = 2^e` +(`num_add_den_eq`). Legendre's formula `v₂(m!) = m - s₂(m)` and +`v₂((n+2)!) - v₂(n!) = v₂((n+1)(n+2)) = A001511(⌊(n+2)/2⌋)` give the other three forms. +-/ + +namespace Math0.Frontier.A092054 +open Math0.Statements.A092054 +open scoped Nat + +/-- Continued fraction with a variable last tail: `tailEval [x₀, …, x_k] t = +x₀ + 1/(x₁ + 1/(⋯ + 1/(x_k + 1/t)))`, and `tailEval [] t = t`. -/ +private def tailEval : List ℚ → ℚ → ℚ + | [], t => t + | x :: l, t => x + 1 / tailEval l t + +/-- `cfEval (l ++ [y])` is `tailEval l y`. -/ +private lemma cfEval_append_singleton (l : List ℚ) (y : ℚ) : + cfEval (l ++ [y]) = tailEval l y := by + induction l with + | nil => rfl + | cons x l ih => + cases l with + | nil => rfl + | cons z zs => + show x + 1 / cfEval ((z :: zs) ++ [y]) = x + 1 / tailEval (z :: zs) y + rw [ih] + +/-- Appending a partial quotient `x` replaces the tail `t` by `x + 1/t`. -/ +private lemma tailEval_append (l : List ℚ) (x t : ℚ) : + tailEval (l ++ [x]) t = tailEval l (x + 1 / t) := by + induction l with + | nil => rfl + | cons z l ih => simp only [List.cons_append, tailEval, ih] + +/-- The partial quotients `1/(k+1)`. -/ +private def pq (k : ℕ) : ℚ := 1 / ((k : ℚ) + 1) + +/-- The numerators (scaled): `P 0 = 1`, `P 1 = 1`, `P (n+2) = P (n+1) + (n+1)(n+2) P n`. -/ +private def P : ℕ → ℕ + | 0 => 1 + | 1 => 1 + | n + 2 => P (n + 1) + (n + 1) * (n + 2) * P n + +/-- The denominators (scaled): `Q 0 = 0`, `Q 1 = 1`, `Q (n+2) = Q (n+1) + (n+1)(n+2) Q n`. -/ +private def Q : ℕ → ℕ + | 0 => 0 + | 1 => 1 + | n + 2 => Q (n + 1) + (n + 1) * (n + 2) * Q n + +/-- The denominators are positive from index `1` on. -/ +private lemma Q_pos : ∀ n, 0 < Q (n + 1) + | 0 => by decide + | n + 1 => by + have := Q_pos n + show 0 < Q (n + 1) + (n + 1) * (n + 2) * Q n + omega + +/-- The Möbius form of the truncated continued fraction with a variable tail. -/ +private lemma tailEval_range (m : ℕ) (t : ℚ) (ht : 0 < t) : + tailEval ((List.range (m + 1)).map pq) t = + ((P (m + 1) : ℚ) * t + (m + 1) * P m) / ((Q (m + 1) : ℚ) * t + (m + 1) * Q m) := by + induction m generalizing t with + | zero => + simp [tailEval, pq, P, Q] + field_simp + | succ m ih => + rw [List.range_succ, List.map_append, List.map_singleton, tailEval_append] + have hs : 0 < pq (m + 1) + 1 / t := by + unfold pq; positivity + rw [ih _ hs] + have h1 := Q_pos m + have h2 := Q_pos (m + 1) + have hP : (P (m + 2) : ℚ) = P (m + 1) + (m + 1) * (m + 2) * P m := by + simp [P] + have hQ : (Q (m + 2) : ℚ) = Q (m + 1) + (m + 1) * (m + 2) * Q m := by + simp [Q] + rw [hP, hQ] + unfold pq + push_cast + have hd1 : (0 : ℚ) < (Q (m + 1) : ℚ) * (1 / ((m : ℚ) + 1 + 1) + 1 / t) + (m + 1) * Q m := by + have : (0 : ℚ) < Q (m + 1) := by exact_mod_cast h1 + positivity + have hd2 : (0 : ℚ) < ((Q (m + 1) : ℚ) + (m + 1) * (m + 2) * Q m) * t + (m + 1 + 1) * Q (m + 1) := by + have : (0 : ℚ) < Q (m + 1) := by exact_mod_cast h1 + positivity + rw [div_eq_div_iff hd1.ne' hd2.ne'] + field_simp + ring + +/-- `conv n` is the continued fraction of the list `[pq 0, …, pq (n-1)]`. -/ +private lemma conv_eq_pq (n : ℕ) : conv n = cfEval ((List.range n).map pq) := by + unfold conv + congr 1 + induction n with + | zero => rfl + | succ n ih => + simp only [List.range_succ, List.map_append, List.bind_eq_flatMap, + List.flatMap_append] at ih ⊢ + rw [ih] + simp [pq] + +/-- The convergents: `conv n = P n / Q n` for `n ≥ 1`. -/ +private lemma conv_eq (n : ℕ) (hn : 1 ≤ n) : conv n = (P n : ℚ) / Q n := by + obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩ + rw [conv_eq_pq, List.range_succ, List.map_append, List.map_singleton] + rw [cfEval_append_singleton] + cases m with + | zero => simp [tailEval, P, Q, pq] + | succ m => + rw [tailEval_range m _ (by unfold pq; positivity)] + have h1 := Q_pos m + have hP : (P (m + 2) : ℚ) = P (m + 1) + (m + 1) * (m + 2) * P m := by + simp [P] + have hQ : (Q (m + 2) : ℚ) = Q (m + 1) + (m + 1) * (m + 2) * Q m := by + simp [Q] + rw [hP, hQ] + unfold pq + push_cast + have : (0 : ℚ) < Q (m + 1) := by exact_mod_cast h1 + field_simp + ring + +/-! ### Closed forms -/ + +/-- The recursion of `P`. -/ +private lemma P_succ_succ (n : ℕ) : P (n + 2) = P (n + 1) + (n + 1) * (n + 2) * P n := rfl + +/-- The recursion of `Q`. -/ +private lemma Q_succ_succ (n : ℕ) : Q (n + 2) = Q (n + 1) + (n + 1) * (n + 2) * Q n := rfl + +/-- The odd double factorial `D m = 1 · 3 ⋯ (2m - 1)`. -/ +private def D : ℕ → ℕ + | 0 => 1 + | m + 1 => (2 * m + 1) * D m + +/-- `(2m-1)!!` is odd. -/ +private lemma D_odd (m : ℕ) : Odd (D m) := by + induction m with + | zero => decide + | succ m ih => exact (odd_two_mul_add_one m).mul ih + +/-- `(2m-1)!! ∣ (2m+1)!!`. -/ +private lemma D_dvd_succ (m : ℕ) : D m ∣ D (m + 1) := Dvd.intro_left _ rfl + +/-- `(2m)! = 2^m · m! · (2m-1)!!`. -/ +private lemma factorial_two_mul (m : ℕ) : (2 * m)! = 2 ^ m * m ! * D m := by + induction m with + | zero => rfl + | succ m ih => + rw [show 2 * (m + 1) = 2 * m + 1 + 1 by ring, Nat.factorial_succ, Nat.factorial_succ, ih, + Nat.factorial_succ] + simp only [D, pow_succ] + ring + +/-- Closed form of the numerators: `P (2m) = ((2m-1)!!)² (2m+1)`, `P (2m+1) = ((2m+1)!!)²`. -/ +private lemma P_closed (m : ℕ) : P (2 * m) = D m ^ 2 * (2 * m + 1) ∧ P (2 * m + 1) = D (m + 1) ^ 2 := by + induction m with + | zero => exact ⟨rfl, rfl⟩ + | succ m ih => + obtain ⟨h0, h1⟩ := ih + have e0 : P (2 * (m + 1)) = D (m + 1) ^ 2 * (2 * (m + 1) + 1) := by + rw [show 2 * (m + 1) = 2 * m + 2 by ring, P_succ_succ, h0, h1] + simp only [D] + ring + refine ⟨e0, ?_⟩ + rw [show 2 * (m + 1) + 1 = 2 * m + 1 + 2 by ring, P_succ_succ, + show 2 * m + 1 + 1 = 2 * (m + 1) by ring, e0, h1] + simp only [D] + ring + +/-- `T n = P n + Q n` satisfies the same recursion. -/ +private lemma T_succ_succ (n : ℕ) : + P (n + 2) + Q (n + 2) = (P (n + 1) + Q (n + 1)) + (n + 1) * (n + 2) * (P n + Q n) := by + rw [P_succ_succ, Q_succ_succ] + ring + +/-- Closed form of `T n = P n + Q n`: `T (2m) = 4^m (m!)²`, `T (2m+1) = 2^(2m+1) m! (m+1)!`. -/ +private lemma T_closed (m : ℕ) : + P (2 * m) + Q (2 * m) = 4 ^ m * (m !) ^ 2 ∧ + P (2 * m + 1) + Q (2 * m + 1) = 2 ^ (2 * m + 1) * m ! * (m + 1)! := by + induction m with + | zero => exact ⟨rfl, rfl⟩ + | succ m ih => + obtain ⟨h0, h1⟩ := ih + have e0 : P (2 * (m + 1)) + Q (2 * (m + 1)) = 4 ^ (m + 1) * ((m + 1)!) ^ 2 := by + rw [show 2 * (m + 1) = 2 * m + 2 by ring, T_succ_succ, h0, h1] + simp only [Nat.factorial_succ, pow_succ, pow_mul] + push_cast + ring + refine ⟨e0, ?_⟩ + rw [show 2 * (m + 1) + 1 = 2 * m + 1 + 2 by ring, T_succ_succ, + show 2 * m + 1 + 1 = 2 * (m + 1) by ring, e0, h1] + simp only [Nat.factorial_succ, pow_succ, pow_mul] + push_cast + ring + +/-- The scaled numerators are odd. -/ +private lemma P_odd (n : ℕ) : Odd (P n) := by + obtain ⟨m, rfl | rfl⟩ := Nat.even_or_odd' n + · rw [(P_closed m).1] + exact ((D_odd m).pow).mul (odd_two_mul_add_one m) + · rw [(P_closed m).2] + exact (D_odd (m + 1)).pow + +/-! ### 2-adic valuations -/ + +/-- `V k = v₂(k!)`. -/ +private def V (k : ℕ) : ℕ := padicValNat 2 (k !) + +/-- An odd number has `2`-adic valuation `0`. -/ +private lemma pv_odd {o : ℕ} (ho : Odd o) : padicValNat 2 o = 0 := + padicValNat.eq_zero_of_not_dvd (by rwa [← even_iff_two_dvd, Nat.not_even_iff_odd]) + +/-- `v₂(2^k · o) = k` for odd `o`. -/ +private lemma pv_two_pow_mul_odd (k : ℕ) {o : ℕ} (ho : Odd o) : padicValNat 2 (2 ^ k * o) = k := by + rw [padicValNat.mul (by positivity) (by rintro rfl; simp at ho), padicValNat.prime_pow, + pv_odd ho, add_zero] + +/-- The odd part `w` of `m!` divides `(2m-1)!!` (because `(2m choose m)` is an integer). -/ +private lemma odd_part (m : ℕ) : ∃ v w, m ! = 2 ^ v * w ∧ Odd w ∧ w ∣ D m := by + obtain ⟨v, w, hw, h⟩ := Nat.exists_eq_two_pow_mul_odd (Nat.factorial_ne_zero m) + refine ⟨v, w, h, hw, ?_⟩ + have h1 : m ! * m ! ∣ m ! * (2 ^ m * D m) := by + have := Nat.factorial_mul_factorial_dvd_factorial_add m m + rw [← two_mul, factorial_two_mul] at this + rw [show m ! * (2 ^ m * D m) = 2 ^ m * m ! * D m by ring] + exact this + have h2 : m ! ∣ 2 ^ m * D m := Nat.dvd_of_mul_dvd_mul_left (Nat.factorial_pos m) h1 + have h3 : w ∣ 2 ^ m * D m := (Dvd.intro_left _ h.symm).trans h2 + have hc : Nat.Coprime w (2 ^ m) := Nat.Coprime.pow_right _ (Nat.coprime_two_right.mpr hw) + exact hc.dvd_of_dvd_mul_left h3 + +/-- `v₂((2m)!) = m + v₂(m!)`, given `m! = 2^v w` with `w` odd. -/ +private lemma V_two_mul (m v w : ℕ) (h : m ! = 2 ^ v * w) (hw : Odd w) : V (2 * m) = m + v := by + unfold V + rw [factorial_two_mul, h, show 2 ^ m * (2 ^ v * w) * D m = 2 ^ (m + v) * (w * D m) by ring, + pv_two_pow_mul_odd _ (hw.mul (D_odd m))] + +/-- `v₂((2m+1)!) = v₂((2m)!)`. -/ +private lemma V_two_mul_add_one (m : ℕ) : V (2 * m + 1) = V (2 * m) := by + unfold V + rw [Nat.factorial_succ, padicValNat.mul (by omega) (Nat.factorial_ne_zero _), + pv_odd (odd_two_mul_add_one m), zero_add] + +/-- The key factorization: `P n + Q n = 2^e · u` with `u ∣ P n` and `e = v₂(n!) + v₂((n+1)!)`. -/ +private lemma key (n : ℕ) : ∃ e u, P n + Q n = 2 ^ e * u ∧ u ∣ P n ∧ e = V n + V (n + 1) := by + obtain ⟨m, rfl | rfl⟩ := Nat.even_or_odd' n + · obtain ⟨v, w, h, hw, hd⟩ := odd_part m + refine ⟨2 * m + 2 * v, w ^ 2, ?_, ?_, ?_⟩ + · rw [(T_closed m).1, h, show (4 : ℕ) ^ m = 2 ^ (2 * m) by rw [pow_mul]; norm_num] + ring + · rw [(P_closed m).1] + exact (pow_dvd_pow_of_dvd hd 2).mul_right _ + · rw [V_two_mul_add_one, V_two_mul m v w h hw] + ring + · obtain ⟨v, w, h, hw, hd⟩ := odd_part m + obtain ⟨v', w', h', hw', hd'⟩ := odd_part (m + 1) + refine ⟨2 * m + 1 + v + v', w * w', ?_, ?_, ?_⟩ + · rw [(T_closed m).2, h, h'] + ring + · rw [(P_closed m).2, pow_two] + exact mul_dvd_mul (hd.trans (D_dvd_succ m)) hd' + · rw [V_two_mul_add_one, V_two_mul m v w h hw, show 2 * m + 1 + 1 = 2 * (m + 1) by ring, + V_two_mul (m + 1) v' w' h' hw'] + ring + +/-- If `a + b = 2^e u` with `u ∣ a` and `a` odd, then `a/b` in lowest terms has +numerator plus denominator `2^e`. -/ +private lemma num_add_den_eq (a b e u : ℕ) (hb : 0 < b) (hT : a + b = 2 ^ e * u) (hu : u ∣ a) + (ha : Odd a) : ((a : ℚ) / b).num.natAbs + ((a : ℚ) / b).den = 2 ^ e := by + have hg : Nat.gcd a b = u := by + rw [← Nat.gcd_self_add_right a b, hT] + apply Nat.dvd_antisymm + · have hc : Nat.Coprime (Nat.gcd a (2 ^ e * u)) (2 ^ e) := by + apply Nat.Coprime.pow_right + exact Nat.coprime_two_right.mpr (ha.of_dvd_nat (Nat.gcd_dvd_left _ _)) + exact hc.dvd_of_dvd_mul_left (Nat.gcd_dvd_right _ _) + · exact Nat.dvd_gcd hu (Dvd.intro_left _ rfl) + have hu0 : 0 < u := by + rcases Nat.eq_zero_or_pos u with h | h + · subst h; simp at hT; omega + · exact h + have hub : u ∣ b := hg ▸ Nat.gcd_dvd_right a b + have hcop : Nat.Coprime (a / u) (b / u) := by + have := Nat.coprime_div_gcd_div_gcd (m := a) (n := b) (by rw [hg]; exact hu0) + rwa [hg] at this + obtain ⟨a', rfl⟩ := hu + obtain ⟨b', rfl⟩ := hub + rw [Nat.mul_div_cancel_left _ hu0, Nat.mul_div_cancel_left _ hu0] at hcop + have hb' : 0 < b' := Nat.pos_of_mul_pos_left hb + have hq : ((u * a' : ℕ) : ℚ) / ((u * b' : ℕ) : ℚ) = ((a' : ℤ) : ℚ) / ((b' : ℤ) : ℚ) := by + push_cast + rw [mul_div_mul_left _ _ (by exact_mod_cast hu0.ne')] + have hc' : Nat.Coprime (a' : ℤ).natAbs (b' : ℤ).natAbs := by simpa using hcop + rw [hq] + have h1 := Rat.num_div_eq_of_coprime (a := (a' : ℤ)) (b := (b' : ℤ)) (by exact_mod_cast hb') hc' + have h2 := Rat.den_div_eq_of_coprime (a := (a' : ℤ)) (b := (b' : ℤ)) (by exact_mod_cast hb') hc' + rw [h1, Int.natAbs_natCast] + have h3 : (((a' : ℤ) : ℚ) / ((b' : ℤ) : ℚ)).den = b' := by exact_mod_cast h2 + rw [h3] + have : u * (a' + b') = u * 2 ^ e := by rw [mul_add, hT, mul_comm] + exact Nat.eq_of_mul_eq_mul_left hu0 this + +/-! ### The combinatorial identities -/ + +/-- Legendre: `v₂(m!) = m - s₂(m)`. -/ +private lemma V_eq (m : ℕ) : V m = A011371 m := by + have := sub_one_mul_padicValNat_factorial (p := 2) m + simpa [V, A011371, binWeight] using this + +/-- `v₂(m!) + s₂(m) = m`. -/ +private lemma V_add_binWeight (m : ℕ) : V m + binWeight m = m := by + rw [V_eq, A011371] + have := Nat.digit_sum_le 2 m + unfold binWeight + omega + +/-- `v₂((n+2)!) = v₂(n!) + A001511(⌊(n+2)/2⌋)`. -/ +private lemma V_add_two (n : ℕ) : V (n + 2) = V n + ruler ((n + 1 + 1) / 2) := by + unfold V ruler + rw [Nat.factorial_succ, Nat.factorial_succ, padicValNat.mul (by omega) (by positivity), + padicValNat.mul (by omega) (Nat.factorial_ne_zero _)] + obtain ⟨j, rfl | rfl⟩ := Nat.even_or_odd' n + · rw [show (2 * j + 1 + 1) / 2 = j + 1 by omega, + pv_odd (odd_two_mul_add_one j), show 2 * (j + 1) = 2 * j + 1 + 1 by ring] + ring + · rw [show (2 * j + 1 + 1 + 1) / 2 = j + 1 by omega, + show 2 * j + 1 + 1 + 1 = 2 * (j + 1) + 1 by ring, pv_odd (odd_two_mul_add_one (j + 1)), + show 2 * (j + 1) = 2 * j + 1 + 1 by ring] + ring + +/-- The ruler-function sum equals `v₂(n!) + v₂((n+1)!)`. -/ +private lemma ruler_sum (n : ℕ) : ∑ k ∈ Finset.Icc 1 n, ruler ((k + 1) / 2) = V n + V (n + 1) := by + induction n with + | zero => simp [V] + | succ n ih => + rw [Finset.sum_Icc_succ_top (by omega), ih, V_add_two] + ring + +/-- The main theorem. -/ +theorem result : statement := by + intro n hn + obtain ⟨e, u, hT, hu, he⟩ := key n + have hsum : num n + den n = 2 ^ e := by + unfold num den + rw [conv_eq n hn] + obtain ⟨k, rfl⟩ : ∃ k, n = k + 1 := ⟨n - 1, by omega⟩ + exact num_add_den_eq _ _ _ _ (Q_pos k) hT hu (P_odd _) + have ha : a n = V n + V (n + 1) := by + unfold a + rw [hsum, Nat.log_pow (by norm_num), he] + refine ⟨?_, ?_, ?_, ?_⟩ + · rw [hsum, ha, ← he] + · rw [ha, ruler_sum] + · have h1 := V_add_binWeight n + have h2 := V_add_binWeight (n + 1) + rw [ha] + push_cast + omega + · rw [ha, V_eq, V_eq] + +end Math0.Frontier.A092054 + +#math0_settles Math0.Frontier.A092054.result Math0.Statements.A092054.statement diff --git a/lean/Math0/Frontier/OEIS/A093726.lean b/lean/Math0/Frontier/OEIS/A093726.lean new file mode 100644 index 0000000..1cd6a76 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A093726.lean @@ -0,0 +1,171 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A093726 +import Math0.Audit + +/-! +# Imaginary parts of the convergents of `[1+i; 1+i, 1+i, …]` + +We prove Zhuorui He's conjecture: for every `n ≥ 1`, +`a(n)/A093727(n) = A317974(n+1)/A138573(n)`, i.e. the imaginary part of the `n`-th convergent +`c_n` of `(1+i) + 1/((1+i) + ⋯)` equals `A317974(n+1)/A138573(n)`. + +**Continuants.** Let `U 0 = 0`, `U 1 = 1`, `U (k+2) = (1+i) U (k+1) + U k` in `ℤ[i]` (stored as +pairs `(re, im)`). Then `c_n = U(n+1)/U(n)`, so with `S n = |U n|²`, +`P n + Q n · i = U (n+1) · conj (U n)` we get `c_n = (P n / S n, Q n / S n)`. This is proved by +induction from `c_{n+1} = (1+i) + 1/c_n`, using the integer identities +`P (n+1) = S (n+1) + P n`, `Q (n+1) = S (n+1) - Q n` and `P n² + Q n² = S n · S (n+1)`. + +**Recurrences.** Expanding `U (n+4)`, `U (n+5)` through `U n`, `U (n+1)`, the polynomial +identities `S (n+4) = 2(S (n+3) + S (n+2) + S (n+1)) - S n` (same for `Q`) are checked by `ring`. +Comparing four initial values gives `S n = A138573 n` and `Q n = A317974 (n+1)`. +`A138573` is nondecreasing and `A138573 1 = 1`, so `S n ≠ 0` for `n ≥ 1`. + +**Numerators.** Finally `a(n)/A093727(n) = num(y)·(L/den y)/L = y` with +`y = Im c_n` and `L = lcm(den (Re c_n), den y)`, since `den y ∣ L`. +-/ + +namespace Math0.Frontier.A093726 +open Math0.Statements.A093726 + +/-- One step of the recurrence `U (k+2) = (1+i) U (k+1) + U k` on Gaussian integers written as +pairs `(re, im)`: `step b a = (1+i) b + a`. -/ +private def step (b a : ℤ × ℤ) : ℤ × ℤ := (b.1 - b.2 + a.1, b.1 + b.2 + a.2) + +/-- The continuants `U 0 = 0`, `U 1 = 1`, `U (k+2) = (1+i) U (k+1) + U k`, as pairs. -/ +private def U : ℕ → ℤ × ℤ + | 0 => (0, 0) + | 1 => (1, 0) + | k + 2 => step (U (k + 1)) (U k) + +/-- `S n = |U n|²`. -/ +private def S (n : ℕ) : ℤ := (U n).1 ^ 2 + (U n).2 ^ 2 + +/-- `P n = Re (U (n+1) · conj (U n))`. -/ +private def P (n : ℕ) : ℤ := (U (n + 1)).1 * (U n).1 + (U (n + 1)).2 * (U n).2 + +/-- `Q n = Im (U (n+1) · conj (U n))`. -/ +private def Q (n : ℕ) : ℤ := (U (n + 1)).2 * (U n).1 - (U (n + 1)).1 * (U n).2 + +/-- `S` satisfies the order-4 recurrence of `A138573`. -/ +private lemma S_rec (n : ℕ) : + S (n + 4) = 2 * S (n + 3) + 2 * S (n + 2) + 2 * S (n + 1) - S n := by + have e4 : U (n + 4) = step (U (n + 3)) (U (n + 2)) := rfl + have e3 : U (n + 3) = step (U (n + 2)) (U (n + 1)) := rfl + have e2 : U (n + 2) = step (U (n + 1)) (U n) := rfl + simp only [S, e4, e3, e2, step] + ring + +/-- `Q` satisfies the same order-4 recurrence (that of `A317974`). -/ +private lemma Q_rec (n : ℕ) : + Q (n + 4) = 2 * Q (n + 3) + 2 * Q (n + 2) + 2 * Q (n + 1) - Q n := by + have e5 : U (n + 5) = step (U (n + 4)) (U (n + 3)) := rfl + have e4 : U (n + 4) = step (U (n + 3)) (U (n + 2)) := rfl + have e3 : U (n + 3) = step (U (n + 2)) (U (n + 1)) := rfl + have e2 : U (n + 2) = step (U (n + 1)) (U n) := rfl + simp only [Q, e5, e4, e3, e2, step] + ring + +/-- `S n = A138573 n` and `Q n = A317974 (n+1)`, by induction on four consecutive values. -/ +private lemma S_eq_Q_eq (n : ℕ) : + (S n = A138573 n ∧ S (n + 1) = A138573 (n + 1) ∧ S (n + 2) = A138573 (n + 2) ∧ + S (n + 3) = A138573 (n + 3)) ∧ + (Q n = A317974 (n + 1) ∧ Q (n + 1) = A317974 (n + 2) ∧ Q (n + 2) = A317974 (n + 3) ∧ + Q (n + 3) = A317974 (n + 4)) := by + induction n with + | zero => decide + | succ n ih => + obtain ⟨⟨h0, h1, h2, h3⟩, ⟨g0, g1, g2, g3⟩⟩ := ih + refine ⟨⟨h1, h2, h3, ?_⟩, ⟨g1, g2, g3, ?_⟩⟩ + · rw [S_rec, h0, h1, h2, h3] + show _ = 2 * A138573 (n + 3) + 2 * A138573 (n + 2) + 2 * A138573 (n + 1) - A138573 n + ring + · rw [Q_rec, g0, g1, g2, g3] + show _ = 2 * (A317974 (n + 4) + A317974 (n + 3) + A317974 (n + 2)) - A317974 (n + 1) + ring + +/-- `A138573` is nonnegative and nondecreasing (four consecutive values at a time). -/ +private lemma A138573_mono (n : ℕ) : + 0 ≤ A138573 n ∧ A138573 n ≤ A138573 (n + 1) ∧ A138573 (n + 1) ≤ A138573 (n + 2) ∧ + A138573 (n + 2) ≤ A138573 (n + 3) := by + induction n with + | zero => decide + | succ n ih => + obtain ⟨h0, h1, h2, h3⟩ := ih + refine ⟨by linarith, h2, h3, ?_⟩ + show A138573 (n + 3) ≤ + 2 * A138573 (n + 3) + 2 * A138573 (n + 2) + 2 * A138573 (n + 1) - A138573 n + linarith + +/-- `A138573 (n+1) ≥ 1`. -/ +private lemma A138573_pos (n : ℕ) : 1 ≤ A138573 (n + 1) := by + induction n with + | zero => decide + | succ n ih => exact ih.trans (A138573_mono (n + 1)).2.1 + +/-- `|U (n+1)|² ≠ 0`. -/ +private lemma S_pos (n : ℕ) : (S (n + 1) : ℚ) ≠ 0 := by + rw [(S_eq_Q_eq (n + 1)).1.1] + have := A138573_pos n + exact_mod_cast (by omega : A138573 (n + 1) ≠ 0) + +/-- One step of the continued fraction: if `c = (p/s, q/s)` with `p² + q² = s s'` then +`(1+i) + 1/c = ((s'+p)/s', (s'-q)/s')`. -/ +private lemma alg (p q s s' : ℚ) (hs : s ≠ 0) (hs' : s' ≠ 0) (hL : p ^ 2 + q ^ 2 = s * s') : + gadd (1, 1) (ginv (p / s, q / s)) = ((s' + p) / s', (s' - q) / s') := by + have hd : p / s * (p / s) + q / s * (q / s) = s' / s := by + field_simp + linear_combination hL + simp only [gadd, ginv, hd, Prod.mk.injEq] + constructor + · field_simp + · field_simp + ring + +/-- The convergents are `conv n = (P n / S n, Q n / S n)` for `n ≥ 1`. -/ +private lemma conv_eq (m : ℕ) : + conv (m + 1) = ((P (m + 1) : ℚ) / S (m + 1), (Q (m + 1) : ℚ) / S (m + 1)) := by + induction m with + | zero => + rw [show P 1 = 1 by decide, show Q 1 = 1 by decide, show S 1 = 1 by decide] + simp [conv, cfValue] + | succ m ih => + have hc : conv (m + 2) = gadd (1, 1) (ginv (conv (m + 1))) := rfl + have hP : P (m + 2) = S (m + 2) + P (m + 1) := by + have e : U (m + 3) = step (U (m + 2)) (U (m + 1)) := rfl + simp only [P, S, e, step] + ring + have hQ : Q (m + 2) = S (m + 2) - Q (m + 1) := by + have e : U (m + 3) = step (U (m + 2)) (U (m + 1)) := rfl + simp only [Q, S, e, step] + ring + have hL : (P (m + 1) : ℚ) ^ 2 + (Q (m + 1) : ℚ) ^ 2 = S (m + 1) * S (m + 2) := by + have : P (m + 1) ^ 2 + Q (m + 1) ^ 2 = S (m + 1) * S (m + 2) := by + simp only [P, Q, S] + ring + exact_mod_cast this + rw [hc, ih, alg _ _ _ _ (S_pos m) (S_pos (m + 1)) hL, hP, hQ] + push_cast + rfl + +/-- Zhuorui He's conjecture on A093726: `a(n)/A093727(n) = A317974(n+1)/A138573(n)` for `n ≥ 1`; +both sides are the imaginary part of the `n`-th convergent. -/ +theorem result : statement := by + intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩ + have hl : (a (m + 1) : ℚ) / (A093727 (m + 1) : ℚ) = (conv (m + 1)).2 := by + simp only [a, A093727, gnumIm, gden] + set z := conv (m + 1) + have hd : z.2.den ∣ Nat.lcm z.1.den z.2.den := Nat.dvd_lcm_right _ _ + have hL : (Nat.lcm z.1.den z.2.den : ℚ) ≠ 0 := by + exact_mod_cast Nat.lcm_ne_zero z.1.den_nz z.2.den_nz + have h2 : (z.2.den : ℚ) ≠ 0 := by exact_mod_cast z.2.den_nz + rw [Int.cast_mul, Int.cast_natCast, Nat.cast_div hd h2] + rw [show (z.2.num : ℚ) * ((Nat.lcm z.1.den z.2.den : ℚ) / z.2.den) / + (Nat.lcm z.1.den z.2.den : ℚ) = z.2.num / z.2.den by field_simp, Rat.num_div_den] + rw [hl, conv_eq, (S_eq_Q_eq (m + 1)).1.1, (S_eq_Q_eq (m + 1)).2.1] + +end Math0.Frontier.A093726 + +#math0_settles Math0.Frontier.A093726.result Math0.Statements.A093726.statement diff --git a/lean/Math0/Frontier/OEIS/A097154.lean b/lean/Math0/Frontier/OEIS/A097154.lean new file mode 100644 index 0000000..3f98ebc --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A097154.lean @@ -0,0 +1,144 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A097154 +import Math0.Audit + +/-! +# The only fixed points of `reverse(x) - maxdigit(x)` are `0` and `89` + +We prove Earls' conjecture from A097154: `f x = x` iff `x = 0` or `x = 89`. + +Idea. `f x = x` means `rev x = x + c` with `c = maxDigit x ≤ 9`. Reversal keeps the digit sum, +so `rev x ≡ x (mod 9)` and `9 ∣ c`. If `x ≠ 0` its leading digit is nonzero, so `c = 9`. +A one-digit `x` has `rev x = x`, impossible. Otherwise write the little-endian digit list as +`b :: (M ++ [a])` (`b` the units digit, `a` the leading digit, `M` the middle block), with +`m`, `r` the values of `M` and of its reversal and `P = 10 ^ |M|`. Then +`x = b + 10 m + 10 P a` and `rev x = a + 10 r + 10 P b`. Mod `10`, `a ≡ b - 1`, so either +`b = a + 1` or `a = 9, b = 0`. The second case gives `r = m + 9P ≥ P`, impossible. The first +gives `r + P = m + 1`, so `r = 0` (as `m < P`); then all middle digits vanish, `m = 0` and +`P = 1`, i.e. `M = []`. Hence `x = 10 a + (a + 1)` and its largest digit `a + 1` is `9`, +so `x = 89`. +-/ + +namespace Math0.Frontier.A097154 +open Math0.Statements.A097154 + +/-- Every element of a list is at most its `foldr max 0`. -/ +private theorem le_foldr_max : ∀ (l : List ℕ) (d : ℕ), d ∈ l → d ≤ l.foldr max 0 + | [], d, h => by simp at h + | e :: l, d, h => by + simp only [List.foldr_cons] + rcases List.mem_cons.1 h with rfl | h + · exact le_max_left _ _ + · exact le_trans (le_foldr_max l d h) (le_max_right _ _) + +/-- A digit list made of zeros has value `0`. -/ +private theorem ofDigits_eq_zero : ∀ L : List ℕ, (∀ d ∈ L, d = 0) → Nat.ofDigits 10 L = 0 + | [], _ => rfl + | e :: L, h => by + rw [Nat.ofDigits_cons, h e List.mem_cons_self, + ofDigits_eq_zero L (fun d hd => h d (List.mem_cons_of_mem e hd))] + +/-- Reversing a digit list does not change its value mod `9`. -/ +private theorem ofDigits_reverse_mod (L : List ℕ) : + Nat.ofDigits 10 L.reverse % 9 = Nat.ofDigits 10 L % 9 := by + have h1 := Nat.ofDigits_modEq 10 9 L + have h2 := Nat.ofDigits_modEq 10 9 L.reverse + norm_num [Nat.ofDigits_one, List.sum_reverse] at h1 h2 + exact h2.trans h1.symm + +/-- The core: a nonempty digit list with nonzero leading digit whose reversal exceeds it by its +largest digit is `[9, 8]` (the number `89`). -/ +private theorem key (L : List ℕ) (hL : ∀ d ∈ L, d < 10) (hlast : ∀ h : L ≠ [], L.getLast h ≠ 0) + (heq : Nat.ofDigits 10 L.reverse = Nat.ofDigits 10 L + L.foldr max 0) (hne : L ≠ []) : + L = [9, 8] := by + have hmod := ofDigits_reverse_mod L + have hc9 : L.foldr max 0 ≤ 9 := foldr_max_le L 9 fun d hd => by have := hL d hd; omega + rcases L with _ | ⟨b, T⟩ + · exact absurd rfl hne + rcases List.eq_nil_or_concat' T with rfl | ⟨M, a, rfl⟩ + · -- one digit: `rev x = x` + have hb := le_foldr_max [b] b List.mem_cons_self + have hb0 := hlast (by simp) + simp only [List.reverse_singleton, List.getLast_singleton] at heq hb0 + omega + · set c := (b :: (M ++ [a])).foldr max 0 + have ha : a ≤ c := le_foldr_max _ a (by simp) + have hb : b ≤ c := le_foldr_max _ b (by simp) + have ha0 : a ≠ 0 := by + have := hlast (by simp) + simpa using this + have ha9 : a < 10 := hL a (by simp) + have hb9 : b < 10 := hL b (by simp) + have hx : Nat.ofDigits 10 (b :: (M ++ [a])) = + b + 10 * Nat.ofDigits 10 M + 10 * (10 ^ M.length * a) := by + simp only [Nat.ofDigits_cons, Nat.ofDigits_append, Nat.ofDigits_nil] + ring + have hrx : Nat.ofDigits 10 (b :: (M ++ [a])).reverse = + a + 10 * Nat.ofDigits 10 M.reverse + 10 * (10 ^ M.length * b) := by + simp only [List.reverse_cons, List.reverse_append, List.reverse_nil, List.nil_append, + List.singleton_append, Nat.ofDigits_append, Nat.ofDigits_cons, Nat.ofDigits_nil, + List.length_cons, List.length_reverse, pow_succ] + ring + have hmP : Nat.ofDigits 10 M < 10 ^ M.length := Nat.ofDigits_lt_base_pow_length (by norm_num) + fun d hd => hL d (by simp [hd]) + have hrP : Nat.ofDigits 10 M.reverse < 10 ^ M.length := by + have := Nat.ofDigits_lt_base_pow_length (b := 10) (l := M.reverse) (by norm_num) + fun d hd => hL d (by simp [List.mem_reverse.1 hd]) + simpa using this + have hP1 : 1 ≤ 10 ^ M.length := Nat.one_le_pow _ _ (by norm_num) + have hzero : Nat.ofDigits 10 M.reverse = 0 → Nat.ofDigits 10 M = 0 := fun h0 => + ofDigits_eq_zero M fun d hd => by + have := le_ofDigits_of_mem M.reverse d (List.mem_reverse.2 hd) + omega + have hlen : 1 ≤ M.length → 10 ≤ 10 ^ M.length := fun h1 => + le_trans (by norm_num) (Nat.pow_le_pow_right (by norm_num) h1) + generalize Nat.ofDigits 10 M = m at hx hmP hzero + generalize Nat.ofDigits 10 M.reverse = r at hrx hrP hzero + generalize hP : 10 ^ M.length = P at hx hrx hmP hrP hP1 hlen + rw [hx, hrx] at heq hmod + have hc' : c = 9 := by omega + have hab : b = a + 1 ∨ (a = 9 ∧ b = 0) := by omega + rcases hab with rfl | ⟨rfl, rfl⟩ + · have e1 : P * (a + 1) = P * a + P := by ring + have hr0 : r = 0 := by omega + have hm0 : m = 0 := hzero hr0 + have hlen0 : M.length = 0 := by omega + have hMnil : M = [] := List.length_eq_zero_iff.1 hlen0 + subst hMnil + have hcle : c ≤ a + 1 := foldr_max_le _ _ fun d hd => by + simp only [List.nil_append, List.mem_cons, List.not_mem_nil, or_false] at hd + omega + have : a = 8 := by omega + subst this + rfl + · simp at heq + omega + +/-- Earls' conjecture (A097154): `0` and `89` are the only fixed points of +`f(x) = reverse(x) - maxdigit(x)`. -/ +theorem result : statement := by + intro x + constructor + · intro h + by_cases hx : x = 0 + · exact Or.inl hx + · right + have hrev : rev x = x + maxDigit x := by + have := maxDigit_le_rev x + unfold f at h + omega + have hL := key (Nat.digits 10 x) (fun d hd => Nat.digits_lt_base (by norm_num) hd) + (fun _ => Nat.getLast_digit_ne_zero 10 hx) + (by rw [Nat.ofDigits_digits]; exact hrev) (Nat.digits_ne_nil_iff_ne_zero.mpr hx) + have := Nat.ofDigits_digits 10 x + rw [hL, show Nat.ofDigits 10 [9, 8] = 89 by decide] at this + exact this.symm + · rintro (rfl | rfl) + · exact f_examples.2.2.2.2.1 + · exact f_examples.2.2.2.2.2.2.2 + +end Math0.Frontier.A097154 + +#math0_settles Math0.Frontier.A097154.result Math0.Statements.A097154.statement diff --git a/lean/Math0/Frontier/OEIS/A106505.lean b/lean/Math0/Frontier/OEIS/A106505.lean new file mode 100644 index 0000000..b2e6f42 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A106505.lean @@ -0,0 +1,142 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A106505 +import Math0.Audit + +/-! +# A106505: the common sides are periodic modulo 8, so `a(n + 5) = a(n) + 8` + +We prove Stephan's conjecture `a(n + 5) = a(n) + 8` for `n > 2` by determining the set of +common sides: for `c ≥ 9`, `IsSide c` holds iff `c` is odd or a multiple of `8`. + +* *Necessity* (`isSide_mod`). From `y² = x (x + c)` with `c ≡ 2, 4, 6 (mod 8)`, a check of + residues mod `8` forces `x` and `y` even (if `x` is odd then `y` is odd, so `x² ≡ y² ≡ 1` and + `x c ≡ 0 (mod 8)`, i.e. `8 ∣ c`); together with `2 ∣ c` this contradicts primitivity. +* *Sufficiency.* `c = 2m + 1` (`m ≥ 2`) is realised by `(x, y) = (m², m (m + 1))`, and + `c = 8 (j + 1)` (`j ≥ 1`) by `(x, y) = (n², n (n + 2))` with `n = 2j + 1`. + +Hence `IsSide (c + 8) ↔ IsSide c` for `c ≥ 9`, so each window of `8` consecutive integers from +`9` on contains exactly `5` common sides: `count IsSide (N + 8) = count IsSide N + 5` for +`N ≥ 9`. Since `a 3 = 9`, for `n ≥ 3` the common side `c = a n ≥ 9` has `count IsSide c = n - 1`, +so `c + 8` is a common side with `count = n + 4`, i.e. `a (n + 5) = c + 8`. +-/ + +namespace Math0.Frontier.A106505 +open Math0.Statements.A106505 + +/-- Residue check mod 8: if `y² ≡ x (x + c)` and `c ≡ 2, 4, 6 (mod 8)`, then `x, y` are even. -/ +private theorem residue_check : ∀ a b e : Fin 8, + (b.val * b.val) % 8 = (a.val * ((a.val + e.val) % 8)) % 8 → e.val % 2 = 0 → e.val ≠ 0 → + a.val % 2 = 0 ∧ b.val % 2 = 0 := by + decide + +/-- A common side is odd or a multiple of `8`. -/ +private theorem isSide_mod {c : ℕ} (h : IsSide c) : c % 2 = 1 ∨ c % 8 = 0 := by + obtain ⟨x, y, h, hg⟩ := h + obtain ⟨-, -, -, hyy⟩ := (isDoubleAngleTriangle_iff x y c).1 h + by_contra hc + have h2 : (c % 8) % 2 = 0 := by omega + have h8 : c % 8 ≠ 0 := by omega + have hm : ((y % 8) * (y % 8)) % 8 = ((x % 8) * ((x % 8 + c % 8) % 8)) % 8 := by + rw [← Nat.add_mod, ← Nat.mul_mod, ← Nat.mul_mod, hyy] + obtain ⟨hx, hy⟩ := residue_check ⟨x % 8, Nat.mod_lt _ (by norm_num)⟩ + ⟨y % 8, Nat.mod_lt _ (by norm_num)⟩ ⟨c % 8, Nat.mod_lt _ (by norm_num)⟩ hm h2 h8 + simp only at hx hy + have h2x : 2 ∣ x := by omega + have h2y : 2 ∣ y := by omega + have h2c : 2 ∣ c := by omega + have : 2 ∣ Nat.gcd (Nat.gcd x y) c := Nat.dvd_gcd (Nat.dvd_gcd h2x h2y) h2c + rw [hg] at this + omega + +/-- Every odd `c = 2m + 1 ≥ 5` is a common side: `(x, y) = (m², m(m+1))`. -/ +private theorem isSide_odd (m : ℕ) (hm : 2 ≤ m) : IsSide (2 * m + 1) := by + refine ⟨m * m, m * (m + 1), (isDoubleAngleTriangle_iff _ _ _).2 ⟨?_, ?_, ?_, ?_⟩, ?_⟩ + · nlinarith + · nlinarith + · nlinarith + · ring + · have h1 : Nat.Coprime m (2 * m + 1) := by + rw [show 2 * m + 1 = 1 + 2 * m by ring, Nat.coprime_add_mul_right_right] + exact Nat.coprime_one_right m + have hcop : Nat.Coprime (m * m) (2 * m + 1) := Nat.Coprime.mul_left h1 h1 + exact Nat.Coprime.coprime_dvd_left (Nat.gcd_dvd_left _ _) hcop + +/-- Every `c = 8(j + 1) ≥ 16` is a common side: with `n = 2j + 1`, `(x, y) = (n², n(n+2))`. -/ +private theorem isSide_eight (j : ℕ) (hj : 1 ≤ j) : IsSide (8 * j + 8) := by + refine ⟨(2 * j + 1) * (2 * j + 1), (2 * j + 1) * (2 * j + 3), + (isDoubleAngleTriangle_iff _ _ _).2 ⟨?_, ?_, ?_, ?_⟩, ?_⟩ + · nlinarith + · nlinarith + · nlinarith + · ring + · have h1 : Nat.Coprime (2 * j + 1) (8 * j + 8) := by + have e : 8 * j + 8 = 4 + 4 * (2 * j + 1) := by ring + rw [e, Nat.coprime_add_mul_right_right] + rw [show (4 : ℕ) = 2 ^ 2 by norm_num] + apply Nat.Coprime.pow_right + rw [Nat.coprime_comm, Nat.Prime.coprime_iff_not_dvd Nat.prime_two] + omega + have hcop : Nat.Coprime ((2 * j + 1) * (2 * j + 1)) (8 * j + 8) := Nat.Coprime.mul_left h1 h1 + exact Nat.Coprime.coprime_dvd_left (Nat.gcd_dvd_left _ _) hcop + +/-- Above `8`, the common sides are exactly the odd numbers and the multiples of `8`. -/ +private theorem isSide_iff_large {c : ℕ} (hc : 9 ≤ c) : IsSide c ↔ c % 2 = 1 ∨ c % 8 = 0 := by + constructor + · exact isSide_mod + · rintro (h | h) + · obtain ⟨m, rfl⟩ : ∃ m, c = 2 * m + 1 := ⟨c / 2, by omega⟩ + exact isSide_odd m (by omega) + · obtain ⟨j, rfl⟩ : ∃ j, c = 8 * j + 8 := ⟨c / 8 - 1, by omega⟩ + exact isSide_eight j (by omega) + +/-- Periodicity of `IsSide` above `8`. -/ +private theorem isSide_add_eight {c : ℕ} (hc : 9 ≤ c) : IsSide (c + 8) ↔ IsSide c := by + rw [isSide_iff_large hc, isSide_iff_large (by omega)] + omega + +/-- The set of common sides is infinite. -/ +private theorem isSide_infinite : (Set.ofPred IsSide).Infinite := by + apply Set.infinite_of_forall_exists_gt + intro a + exact ⟨2 * (a + 2) + 1, isSide_odd (a + 2) (by omega), by omega⟩ + +/-- Counting periodicity: each block of `8` consecutive integers from `9` on contains `5` +common sides. -/ +private theorem count_add_eight (N : ℕ) (hN : 9 ≤ N) : + Nat.count IsSide (N + 8) = Nat.count IsSide N + 5 := by + induction N, hN using Nat.le_induction with + | base => decide +kernel + | succ N hN ih => + rw [show N + 1 + 8 = N + 8 + 1 by ring, Nat.count_succ IsSide (N + 8), + Nat.count_succ IsSide N, ih] + by_cases h : IsSide N + · rw [if_pos h, if_pos ((isSide_add_eight hN).2 h)] + · rw [if_neg h, if_neg (fun h' => h ((isSide_add_eight hN).1 h'))] + +/-- The third common side is `9`. -/ +private theorem nth_two : Nat.nth IsSide 2 = 9 := by + have h9 : IsSide 9 := by decide +kernel + have hc : Nat.count IsSide 9 = 2 := by decide +kernel + have := Nat.nth_count h9 + rwa [hc] at this + +/-- Stephan's conjecture for A106505: `a(n + 5) = a(n) + 8` for all `n > 2`. -/ +theorem result : statement := by + intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩ + simp only [a, show m + 1 + 5 - 1 = m + 5 by omega, Nat.add_sub_cancel] + set c := Nat.nth IsSide m with hcdef + have hpc : IsSide c := Nat.nth_mem_of_infinite isSide_infinite m + have hcount : Nat.count IsSide c = m := Nat.count_nth_of_infinite isSide_infinite m + have hc9 : 9 ≤ c := by + rw [← nth_two, hcdef] + exact (Nat.nth_le_nth isSide_infinite).2 (by omega) + have hp8 : IsSide (c + 8) := (isSide_add_eight hc9).2 hpc + have := Nat.nth_count hp8 + rwa [count_add_eight c hc9, hcount] at this + +end Math0.Frontier.A106505 + +#math0_settles Math0.Frontier.A106505.result Math0.Statements.A106505.statement diff --git a/lean/Math0/Frontier/OEIS/A113676.lean b/lean/Math0/Frontier/OEIS/A113676.lean new file mode 100644 index 0000000..5277f71 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A113676.lean @@ -0,0 +1,208 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A113676 +import Math0.Audit + +/-! +# The Golomb-row triangle A113676 and Levine's sequence A014644 + +We prove both conjectures of Floor van Lamoen and Paul D. Hanna (2005). + +Write `G = golomb`, `P(l) = [G 1, …, G l]` and `L k = (levineRow k).length`. + +**Levine's rows are prefixes of Golomb's sequence.** Applying Levine's map `levineAux · 1` to +`P(l)` (`l ≥ 2`) gives `1^G(1) 2^G(2) ⋯ l^G(l)`, which is a stage of the self-generating +construction of Golomb's sequence, hence again a prefix `P(l')`. Since `levineRow 2 = [1, 2]`, +induction gives `levineRow k = P(L k)` for all `k ≥ 2`. Moreover `L (k + 1) = sum (levineRow k)`, +so `L k ≤ L (k + 1)`; the final term of `levineRow (k + 1)` is +`A014644 (k + 1) = G (L (k + 1))`, and also `A014644 (k + 2) = L (k + 1)`. + +**Telescoping.** Splitting `P(L (k + 1)) = P(L k) ++ [G (L k + 1), …, G (L (k + 1))]` and taking +sums gives `G (L k + 1) + ⋯ + G (L (k + 1)) = L (k + 2) - L (k + 1)` for `k ≥ 2`. + +**The rows.** Since `H j = G (j + 1)` for `j ≥ 2`, the row recursion and the telescoping identity +give by induction `rowEnd n + 1 = L (n + 1)` for all `n ≥ 1`. Hence for `n ≥ 2`, row `n` is +`[G (L n + 1), …, G (L (n + 1))]`, its length is +`L (n + 1) - L n = A014644 (n + 2) - A014644 (n + 1)`, and (as `L n < L (n + 1)`, by induction +on the differences) its last term is `G (L (n + 1)) = A014644 (n + 1)`. +-/ + +namespace Math0.Frontier.A113676 +open Math0.Statements.A113676 + +/-- Golomb's sequence is positive from index `1` on. -/ +private lemma golomb_pos {i : ℕ} (hi : 1 ≤ i) : 1 ≤ golomb i := by + obtain ⟨j, rfl⟩ : ∃ j, i = j + 1 := ⟨i - 1, by omega⟩ + have hlen := (golombAux_pos_length j).2 + rw [golomb_eq_getD (m := j) (by omega), List.getD_eq_getElem _ _ (by omega)] + exact (golombAux_pos_length j).1 _ (List.getElem_mem _) + +/-- A block of `c` consecutive Golomb terms (from index `s + 1` on) has sum at least `c`. -/ +private lemma le_sum_map_golomb (s c : ℕ) : c ≤ ((List.range' (s + 1) c).map golomb).sum := by + have h := List.length_le_sum_of_one_le ((List.range' (s + 1) c).map golomb) (by + intro x hx + rw [List.mem_map] at hx + obtain ⟨i, hi, rfl⟩ := hx + rw [List.mem_range'_1] at hi + exact golomb_pos (by omega)) + simpa using h + +/-- The rows of Levine's array (from row `1` on) have at least two terms. -/ +private lemma two_le_length_levineRow (k : ℕ) (hk : 1 ≤ k) : 2 ≤ (levineRow k).length := by + induction k, hk using Nat.le_induction with + | base => decide + | succ k hk ih => + obtain ⟨j, rfl⟩ : ∃ j, k = j + 1 := ⟨k - 1, by omega⟩ + rw [levineRow_add_two, length_levineAux] + exact ih.trans (List.length_le_sum_of_one_le _ (levineRow_pos _)) + +/-- The length of row `k + 1` of Levine's array is the sum of row `k` (`k ≥ 1`). -/ +private lemma length_levineRow_succ (k : ℕ) (hk : 1 ≤ k) : + (levineRow (k + 1)).length = (levineRow k).sum := by + obtain ⟨j, rfl⟩ : ∃ j, k = j + 1 := ⟨k - 1, by omega⟩ + rw [levineRow_add_two, length_levineAux] + +/-- Row lengths of Levine's array are nondecreasing (from row `1` on). -/ +private lemma length_levineRow_le (k : ℕ) (hk : 1 ≤ k) : + (levineRow k).length ≤ (levineRow (k + 1)).length := by + rw [length_levineRow_succ k hk] + exact List.length_le_sum_of_one_le _ (levineRow_pos _) + +/-- Rows `k ≥ 2` of Levine's array are prefixes of Golomb's sequence. -/ +private lemma levineRow_eq (k : ℕ) (hk : 2 ≤ k) : + levineRow k = (List.range' 1 (levineRow k).length).map golomb := by + induction k, hk using Nat.le_induction with + | base => decide + | succ k hk ih => + obtain ⟨j, rfl⟩ : ∃ j, k = j + 1 := ⟨k - 1, by omega⟩ + have h2 := two_le_length_levineRow (j + 1) (by omega) + have e : levineRow (j + 1 + 1) = golombAux ((levineRow (j + 1)).length - 2) := by + have hm := levineAux_map golomb (levineRow (j + 1)).length 1 + rw [← ih] at hm + rw [levineRow_add_two, hm, golombAux_eq_flatMap, Nat.sub_add_cancel h2] + rw [e] + exact golombAux_eq_map _ + +/-- Telescoping: for `k ≥ 2`, the Golomb terms of indices `L k + 1, …, L (k + 1)` sum to +`L (k + 2) - L (k + 1)`, where `L k = (levineRow k).length`. -/ +private lemma sum_block (k : ℕ) (hk : 2 ≤ k) : + (levineRow (k + 1)).length + + ((List.range' ((levineRow k).length + 1) + ((levineRow (k + 1)).length - (levineRow k).length)).map golomb).sum = + (levineRow (k + 2)).length := by + have hle := length_levineRow_le k (by omega) + have hsplit : List.range' 1 (levineRow (k + 1)).length = + List.range' 1 (levineRow k).length ++ + List.range' ((levineRow k).length + 1) + ((levineRow (k + 1)).length - (levineRow k).length) := by + rw [show (levineRow k).length + 1 = 1 + (levineRow k).length by omega, + List.range'_append_1, Nat.add_sub_cancel' hle] + have e1 := levineRow_eq (k + 1) (by omega) + rw [hsplit, List.map_append, ← levineRow_eq k hk] at e1 + have s3 := congrArg List.sum e1 + rw [List.sum_append] at s3 + have s1 : (levineRow (k + 2)).length = (levineRow (k + 1)).sum := + length_levineRow_succ (k + 1) (by omega) + have s2 : (levineRow (k + 1)).length = (levineRow k).sum := length_levineRow_succ k (by omega) + omega + +/-- The row ends of the triangle: `rowEnd n + 1 = L (n + 1)` for `n ≥ 1`. -/ +private lemma rowEnd_eq (n : ℕ) (hn : 1 ≤ n) : + rowEnd n + 1 = (levineRow (n + 1)).length ∧ + rowEnd (n + 1) + 1 = (levineRow (n + 2)).length := by + induction n, hn using Nat.le_induction with + | base => decide + | succ n hn ih => + obtain ⟨ih1, ih2⟩ := ih + refine ⟨ih2, ?_⟩ + have h2 : 2 ≤ (levineRow (n + 1)).length := two_le_length_levineRow (n + 1) (by omega) + have hb : (levineRow (n + 2)).length + + ((List.range' ((levineRow (n + 1)).length + 1) + ((levineRow (n + 2)).length - (levineRow (n + 1)).length)).map golomb).sum = + (levineRow (n + 3)).length := sum_block (n + 1) (by omega) + have e : rowEnd (n + 2) = rowEnd (n + 1) + + ((List.range' (rowEnd n + 1) (rowEnd (n + 1) - rowEnd n)).map H).sum := rfl + show rowEnd (n + 2) + 1 = (levineRow (n + 3)).length + rw [e, map_H_range'_golomb _ _ (by omega), + show rowEnd n + 1 + 1 = (levineRow (n + 1)).length + 1 by omega, + show rowEnd (n + 1) - rowEnd n = + (levineRow (n + 2)).length - (levineRow (n + 1)).length by omega] + omega + +/-- Levine's row lengths are strictly increasing from row `2` on. -/ +private lemma length_levineRow_lt (k : ℕ) (hk : 1 ≤ k) : + (levineRow (k + 1)).length < (levineRow (k + 2)).length := by + induction k, hk using Nat.le_induction with + | base => decide + | succ k hk ih => + have hb : (levineRow (k + 2)).length + + ((List.range' ((levineRow (k + 1)).length + 1) + ((levineRow (k + 2)).length - (levineRow (k + 1)).length)).map golomb).sum = + (levineRow (k + 3)).length := sum_block (k + 1) (by omega) + have hs := le_sum_map_golomb (levineRow (k + 1)).length + ((levineRow (k + 2)).length - (levineRow (k + 1)).length) + show (levineRow (k + 2)).length < (levineRow (k + 3)).length + omega + +/-- The last term of `map f (range' s (c + 1))`. -/ +private lemma getLast?_map_range' (f : ℕ → ℕ) (s c : ℕ) : + ((List.range' s (c + 1)).map f).getLast? = some (f (s + c)) := by + rw [List.range'_1_concat, List.map_append, List.getLast?_append] + simp + +/-- Both conjectures of van Lamoen and Hanna hold: the row lengths `a n` (`n ≥ 2`) are the first +differences of Levine's sequence A014644 from its third term on, and the final elements of the +rows are A014644 with its duplicate `2` removed. -/ +theorem result : statement := by + -- Row `m + 2` is the block of Golomb terms of indices `L (m + 2) + 1, …, L (m + 3)`. + have hrow : ∀ m : ℕ, row (m + 2) = (List.range' ((levineRow (m + 2)).length + 1) + ((levineRow (m + 3)).length - (levineRow (m + 2)).length)).map golomb := by + intro m + have h0 : 2 ≤ (levineRow (m + 2)).length := two_le_length_levineRow (m + 2) (by omega) + have h1 : rowEnd (m + 1) + 1 = (levineRow (m + 2)).length := (rowEnd_eq (m + 1) (by omega)).1 + have h2 : rowEnd (m + 1 + 1) + 1 = (levineRow (m + 3)).length := + (rowEnd_eq (m + 1) (by omega)).2 + show row (m + 1 + 1) = _ + rw [row_succ, map_H_range'_golomb _ _ (by omega), + show rowEnd (m + 1) + 1 + 1 = (levineRow (m + 2)).length + 1 by omega, + show rowEnd (m + 1 + 1) - rowEnd (m + 1) = + (levineRow (m + 3)).length - (levineRow (m + 2)).length by omega] + have hA : ∀ k : ℕ, 1 ≤ k → A014644 (k + 1) = (levineRow k).length := by + intro k hk + obtain ⟨j, rfl⟩ : ∃ j, k = j + 1 := ⟨k - 1, by omega⟩ + exact A014644_add_two j (List.ne_nil_of_length_pos + (by have := two_le_length_levineRow (j + 1) (by omega); omega)) + refine ⟨?_, ?_, ?_⟩ + · intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 2 := ⟨n - 2, by omega⟩ + have hlt : (levineRow (m + 2)).length < (levineRow (m + 3)).length := + length_levineRow_lt (m + 1) (by omega) + have hA3 : A014644 (m + 2 + 2) = (levineRow (m + 3)).length := hA (m + 3) (by omega) + have hA2 : A014644 (m + 2 + 1) = (levineRow (m + 2)).length := hA (m + 2) (by omega) + rw [a, hrow m, List.length_map, List.length_range', hA3, hA2] + push_cast [hlt.le] + ring + · rw [row_one] + rfl + · intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 2 := ⟨n - 2, by omega⟩ + have hlt : (levineRow (m + 2)).length < (levineRow (m + 3)).length := + length_levineRow_lt (m + 1) (by omega) + have hlast : A014644 (m + 2 + 1) = golomb (levineRow (m + 3)).length := by + have e := levineRow_eq (m + 3) (by omega) + obtain ⟨d, hd⟩ : ∃ d, (levineRow (m + 3)).length = d + 1 := + ⟨_, (Nat.succ_pred_eq_of_pos (by omega)).symm⟩ + rw [hd] at e + show (levineRow (m + 3)).getLastD 0 = _ + rw [List.getLastD_eq_getLast?, hd, e, getLast?_map_range', Option.getD_some, + Nat.add_comm] + obtain ⟨c, hc⟩ : ∃ c, (levineRow (m + 3)).length - (levineRow (m + 2)).length = c + 1 := + ⟨_, (Nat.succ_pred_eq_of_pos (by omega)).symm⟩ + rw [hrow m, hc, getLast?_map_range', hlast] + congr 2 + omega + +end Math0.Frontier.A113676 + +#math0_settles Math0.Frontier.A113676.result Math0.Statements.A113676.statement diff --git a/lean/Math0/Frontier/OEIS/A115026.lean b/lean/Math0/Frontier/OEIS/A115026.lean new file mode 100644 index 0000000..96cb04b --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A115026.lean @@ -0,0 +1,32 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A115026 +import Math0.Audit + +/-! +# A115026 has a term greater than 370: `a 119 = 371` + +The orbit of `119` under A101337 is `119 ↦ 1³ + 1³ + 9³ = 731 ↦ 7³ + 3³ + 1³ = 371`, and `371` +is a fixed point (`3³ + 7³ + 1³ = 371`, a narcissistic number). So the limit cycle of `119` is +`{371}` and `a 119 = 371 > 370`, refuting Dale's conjecture. The value `a 119 = 371` is checked +by the kernel, evaluating the frozen definition `a` directly (as `a_data` does for `a 1, …, a 65`). +-/ + +namespace Math0.Frontier.A115026 +open Math0.Statements.A115026 + +/-- The 119th term of A115026 is `371` (kernel evaluation of `a`). -/ +private theorem a_119 : a 119 = 371 := by + decide +kernel + +/-- Dale's conjecture fails: `a 119 = 371 > 370`. -/ +theorem result : ¬ statement := by + intro h + have h119 := h 119 (by norm_num) + rw [a_119] at h119 + omega + +end Math0.Frontier.A115026 + +#math0_settles Math0.Frontier.A115026.result Math0.Statements.A115026.statement diff --git a/lean/Math0/Frontier/OEIS/A116184.lean b/lean/Math0/Frontier/OEIS/A116184.lean new file mode 100644 index 0000000..c6384a9 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A116184.lean @@ -0,0 +1,201 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A116184 +import Math0.Audit + +/-! +# A116184: Adamchuk's conjectures on `37^3 ∣ numerator (∑_{k=1}^{36} 1/k^n)` + +We prove both claims of the comment in OEIS A116184: (a) `37^3` divides the numerator of +`H(36, n) = ∑_{k=1}^{36} 1/k^n` for every `n = 3 + 36k`, and (b) every prime term `p > 37` +satisfies `p ≡ -1 (mod 37)`. + +By `isTerm_iff_check`, `IsTerm n` holds iff `∑_c c^n ≡ 0 (mod 37^3)`, where `c` runs over the +36 residues `36!/k mod 37^3`. Each `c` is prime to `37`, so `c^36 = 1 + 37 a_c` in +`ZMod (37^3)` (Fermat), and the binomial theorem truncated at `37^3` gives, writing +`n = r + 36 t`, +`c^n = c^r (1 + 37 a_c t + 37^2 a_c^2 t (t - 1) / 2)`. +Summing, `∑ c^n = S₀(r) + 37 t S₁(r) + 37^2 (t (t - 1) / 2) S₂(r)` with `S_j(r) = ∑ c^r a_c^j`. + +* (a) For `r = 3` one computes `S₀(3) ≡ 0 (mod 37^3)`, `S₁(3) ≡ 0 (mod 37^2)` and + `S₂(3) ≡ 0 (mod 37)`, so the sum vanishes for every `t`. +* (b) The expression only depends on `r = n mod 36` and `t mod 37^2`. A prime `p > 37` has `r` + odd and prime to `3` and `p ≢ 0 (mod 37)`; a kernel-checked search over the `12 · 1369` such + pairs `(r, t mod 37^2)` shows the sum vanishes only when `p ≡ 36 (mod 37)`. +-/ + +namespace Math0.Frontier.A116184 +open Math0.Statements.A116184 + +/-- `A c = (c^36 mod 37^3 - 1) / 37`, so that `c^36 ≡ 1 + 37 * A c (mod 37^3)`. -/ +private def A (c : ℕ) : ℕ := (c ^ 36 % 50653 - 1) / 37 + +/-- Every coefficient `c` satisfies `c^36 ≡ 1 + 37 * A c (mod 37^3)` (kernel-checked). -/ +private theorem A_spec : ∀ c ∈ coeffs, c ^ 36 % 50653 = 1 + 37 * A c := by decide +kernel + +/-- `s0 r = ∑ c^r`. -/ +private def s0 (r : ℕ) : ℕ := (coeffs.map (fun c => c ^ r)).sum +/-- `s1 r = ∑ c^r * A c`. -/ +private def s1 (r : ℕ) : ℕ := (coeffs.map (fun c => c ^ r * A c)).sum +/-- `s2 r = ∑ c^r * (A c)^2`. -/ +private def s2 (r : ℕ) : ℕ := (coeffs.map (fun c => c ^ r * A c ^ 2)).sum + +/-- `check n` says that `∑ c^n` vanishes in `ZMod (37^3)`. -/ +private theorem check_iff (n : ℕ) : + check n = true ↔ (coeffs.map (fun c : ℕ => (c : ZMod 50653) ^ n)).sum = 0 := by + rw [check, beq_iff_eq, ← Nat.dvd_iff_mod_eq_zero, ← ZMod.natCast_eq_zero_iff, + Nat.cast_list_sum, List.map_map] + have hf : ((Nat.cast : ℕ → ZMod 50653) ∘ fun c => c ^ n % 50653) = + fun c : ℕ => (c : ZMod 50653) ^ n := by + funext c; simp [ZMod.natCast_mod] + rw [hf] + +/-- If `x^36 = 1 + 37 a` in `ZMod (37^3)`, then +`x^(r + 36 t) = x^r (1 + 37 a t + 37^2 a^2 t (t - 1) / 2)`. -/ +private theorem key_pow (x a : ZMod 50653) (hx : x ^ 36 = 1 + 37 * a) (r t : ℕ) : + x ^ (r + 36 * t) = x ^ r * (1 + 37 * a * t + 1369 * 25327 * a ^ 2 * t * (t - 1)) := by + rw [pow_add, pow_mul, hx] + congr 1 + have h : (50653 : ZMod 50653) = 0 := by decide + induction t with + | zero => simp + | succ t ih => + rw [pow_succ, ih] + push_cast + linear_combination (-1369 * a ^ 2 * t + 25327 * a ^ 3 * t * (t - 1)) * h + +/-- Distributing a sum over `f c * (1 + α g c + β g c ^ 2)`. -/ +private theorem sum_expand (L : List ℕ) (f g : ℕ → ZMod 50653) (α β : ZMod 50653) : + (L.map (fun c => f c * (1 + α * g c + β * g c ^ 2))).sum = + (L.map f).sum + α * (L.map (fun c => f c * g c)).sum + + β * (L.map (fun c => f c * g c ^ 2)).sum := by + induction L with + | nil => simp + | cons c L ih => simp only [List.map_cons, List.sum_cons, ih]; ring + +/-- `∑ c^(r + 36 t) = s0 r + 37 t s1 r + 37^2 t (t - 1) / 2 s2 r` in `ZMod (37^3)`. -/ +private theorem sum_pow (r t : ℕ) : + (coeffs.map (fun c : ℕ => (c : ZMod 50653) ^ (r + 36 * t))).sum = + (s0 r : ZMod 50653) + 37 * t * (s1 r : ZMod 50653) + + 1369 * 25327 * t * (t - 1) * (s2 r : ZMod 50653) := by + have h1 : coeffs.map (fun c : ℕ => (c : ZMod 50653) ^ (r + 36 * t)) = + coeffs.map (fun c : ℕ => ((c : ZMod 50653) ^ r) * (1 + (37 * t) * (A c : ZMod 50653) + + (1369 * 25327 * t * (t - 1)) * (A c : ZMod 50653) ^ 2)) := by + apply List.map_congr_left + intro c hc + have hx : (c : ZMod 50653) ^ 36 = 1 + 37 * (A c : ZMod 50653) := by + have := A_spec c hc + rw [← Nat.cast_pow, ← ZMod.natCast_mod, this]; push_cast; ring + rw [key_pow _ _ hx]; ring + rw [h1, sum_expand] + simp only [s0, s1, s2, Nat.cast_list_sum, List.map_map, Function.comp_def, Nat.cast_mul, + Nat.cast_pow] + +/-- The value of `∑ c^(r + 36 t)` only depends on `t mod 37^2`. -/ +private theorem reduce_t (a0 a1 a2 : ZMod 50653) (t : ℕ) : + a0 + 37 * (t : ZMod 50653) * a1 + 1369 * 25327 * (t : ZMod 50653) * (t - 1) * a2 = + a0 + 37 * ((t % 1369 : ℕ) : ZMod 50653) * a1 + + 1369 * 25327 * ((t % 1369 : ℕ) : ZMod 50653) * ((t % 1369 : ℕ) - 1) * a2 := by + have h : (50653 : ZMod 50653) = 0 := by decide + have ht : (t : ZMod 50653) = + ((t % 1369 : ℕ) : ZMod 50653) + 1369 * ((t / 1369 : ℕ) : ZMod 50653) := by + have := congrArg (Nat.cast : ℕ → ZMod 50653) (Nat.mod_add_div t 1369) + push_cast at this + exact this.symm + rw [ht] + set u := ((t % 1369 : ℕ) : ZMod 50653) + set q := ((t / 1369 : ℕ) : ZMod 50653) + linear_combination (q * a1 + 37 * 25327 * q * (2 * u - 1 + 1369 * q) * a2) * h + +/-- Table of `s0 r mod 37^3`. -/ +private def T0 : List ℕ := + [36, 17797, 22866, 0, 8214, 49284, 19425, 10952, 30007, 2738, 43216, 24642, 37333, 23273, 47064, + 28749, 17353, 19166, 34447, 9583, 42106, 36963, 42143, 21904, 5587, 24642, 20424, 28749, 3404, + 5476, 36926, 19166, 40441, 24642, 6512, 1406] +/-- Table of `s1 r mod 37^3`. -/ +private def T1 : List ℕ := + [27255, 37851, 5130, 10952, 37185, 925, 47846, 23199, 25461, 42698, 17066, 25900, 12906, 11840, + 35963, 16502, 22617, 13024, 32498, 31598, 46293, 9990, 28931, 18204, 44978, 9953, 46169, 34854, + 17651, 7474, 23664, 18278, 25941, 25086, 32483, 40830] +/-- Table of `s2 r mod 37^3`. -/ +private def T2 : List ℕ := + [8850, 16404, 22783, 7215, 33961, 31556, 5163, 23268, 45035, 21525, 35844, 23502, 34570, 32968, + 7630, 40875, 4218, 9719, 17569, 4064, 31462, 29196, 41991, 38605, 13321, 30976, 30212, 11949, + 25518, 47635, 43575, 16202, 23121, 47622, 35174, 35312] + +/-- `T0` tabulates `s0 r mod 37^3` (kernel-checked). -/ +private theorem T0_spec : ∀ r < 36, T0.getD r 0 = s0 r % 50653 := by decide +kernel +/-- `T1` tabulates `s1 r mod 37^3` (kernel-checked). -/ +private theorem T1_spec : ∀ r < 36, T1.getD r 0 = s1 r % 50653 := by decide +kernel +/-- `T2` tabulates `s2 r mod 37^3` (kernel-checked). -/ +private theorem T2_spec : ∀ r < 36, T2.getD r 0 = s2 r % 50653 := by decide +kernel + +/-- The test performed for one pair `(r, u)`. -/ +private def okU (r a0 a1 a2 u : ℕ) : Bool := + (r + 36 * u) % 37 == 0 || + (a0 + 37 * u * a1 + 1369 * 25327 * u * (u + 50652) * a2) % 50653 != 0 || + (r + 36 * u) % 37 == 36 + +/-- The finite check behind part (b) (kernel-checked). -/ +private theorem finite_b_aux : ∀ r < 36, r % 2 = 1 → r % 3 ≠ 0 → ∀ u < 1369, + okU r (T0.getD r 0) (T1.getD r 0) (T2.getD r 0) u = true := by + decide +kernel + +/-- The finite check behind part (b), unpacked. -/ +private theorem finite_b (r u : ℕ) (hr : r < 36) (h2 : r % 2 = 1) (h3 : r % 3 ≠ 0) + (hu : u < 1369) (h37 : (r + 36 * u) % 37 ≠ 0) + (hz : (T0.getD r 0 + 37 * u * T1.getD r 0 + 1369 * 25327 * u * (u + 50652) * T2.getD r 0) + % 50653 = 0) : + (r + 36 * u) % 37 = 36 := by + have := finite_b_aux r hr h2 h3 u hu + simp only [okU, Bool.or_eq_true, beq_iff_eq, bne_iff_ne, ne_eq] at this + omega + +/-- Part (a): every `3 + 36 k` is a term. -/ +private theorem part_a (k : ℕ) : IsTerm (3 + 36 * k) := by + rw [isTerm_iff_check, check_iff, sum_pow] + have h0 : (s0 3 : ZMod 50653) = 0 := by + rw [ZMod.natCast_eq_zero_iff]; decide +kernel + have h1 : ((37 * s1 3 : ℕ) : ZMod 50653) = 0 := by + rw [ZMod.natCast_eq_zero_iff]; decide +kernel + have h2 : ((1369 * s2 3 : ℕ) : ZMod 50653) = 0 := by + rw [ZMod.natCast_eq_zero_iff]; decide +kernel + push_cast at h1 h2 + linear_combination h0 + (k : ZMod 50653) * h1 + + 25327 * (k : ZMod 50653) * ((k : ZMod 50653) - 1) * h2 + +/-- Part (b): every prime term `p > 37` satisfies `p ≡ -1 (mod 37)`. -/ +private theorem part_b (p : ℕ) (hp : p.Prime) (h37 : 37 < p) (ht : IsTerm p) : + ∃ k : ℕ, p = 37 * k - 1 := by + have h2 : p % 2 ≠ 0 := fun h => by + have := hp.eq_one_or_self_of_dvd 2 (Nat.dvd_of_mod_eq_zero h); omega + have h3 : p % 3 ≠ 0 := fun h => by + have := hp.eq_one_or_self_of_dvd 3 (Nat.dvd_of_mod_eq_zero h); omega + have h37' : p % 37 ≠ 0 := fun h => by + have := hp.eq_one_or_self_of_dvd 37 (Nat.dvd_of_mod_eq_zero h); omega + rw [isTerm_iff_check, check_iff] at ht + have hpe : p = p % 36 + 36 * (p / 36) := (Nat.mod_add_div p 36).symm + rw [hpe, sum_pow, reduce_t] at ht + have hr : p % 36 < 36 := Nat.mod_lt _ (by norm_num) + have hu : p / 36 % 1369 < 1369 := Nat.mod_lt _ (by norm_num) + generalize hR : p % 36 = r at ht hr + generalize hU : p / 36 % 1369 = u at ht hu + have hz : (T0.getD r 0 + 37 * u * T1.getD r 0 + 1369 * 25327 * u * (u + 50652) * T2.getD r 0) + % 50653 = 0 := by + rw [← Nat.dvd_iff_mod_eq_zero, ← ZMod.natCast_eq_zero_iff, T0_spec r hr, T1_spec r hr, + T2_spec r hr] + push_cast [ZMod.natCast_mod] + have h : (50653 : ZMod 50653) = 0 := by decide + linear_combination ht + (1369 * 25327 * (u : ZMod 50653) * (s2 r : ZMod 50653)) * h + have key := finite_b r u hr (by omega) (by omega) hu (by omega) hz + exact ⟨p / 37 + 1, by omega⟩ + +/-- Adamchuk's conjecture on A116184 holds: (a) `37^3` divides the numerator of `H(36, 3 + 36k)` +for every `k ≥ 0`, and (b) every prime `p > 37` with `37^3 ∣ numerator (H(36, p))` satisfies +`p ≡ -1 (mod 37)`. -/ +theorem result : statement := ⟨part_a, part_b⟩ + +end Math0.Frontier.A116184 + +#math0_settles Math0.Frontier.A116184.result Math0.Statements.A116184.statement diff --git a/lean/Math0/Frontier/OEIS/A119936.lean b/lean/Math0/Frontier/OEIS/A119936.lean new file mode 100644 index 0000000..27e5800 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A119936.lean @@ -0,0 +1,198 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A119936 +import Math0.Audit + +/-! +# The row-LCM of denominators of the cube of the mean matrix is `n · lcm(1..n)²` + +We prove Wolfdieter Lang's conjecture (A119936): `a(n)/n³ = A002944(n)²`, i.e. +`a(n) = n · L²` with `L = lcm(1, …, n)`. + +Write `D = n · L²` and `N(m) = ∑_{m ≤ l ≤ k ≤ n} L²/(k l)` (each summand is a natural number since +`k, l ∣ L`). Then `N(m) = D · r(n,m)` by `r_eq_explicit`. Writing `r = num/den` in lowest terms, +`|num| · D = N(m) · den`, so: + +* `den ∣ D` for every `m` (as `den` is coprime to `num`), hence `a(n) ∣ D`; +* if `p ∤ N(m)` then every prime power `p^k ∣ D` divides `den`. + +For a prime `p` let `e = ⌊log_p n⌋` (so `v_p(L) = e`) and `m = ⌊n/p^e⌋ · p^e`. The only +multiple of `p^e` in `[m, n]` is `m` itself, so for every pair `(k, l) ≠ (m, m)` one of `k, l` +has `v_p < e`, the other `v_p ≤ e`, hence `p ∣ L²/(k l)`; while `p ∤ L²/m²` because +`v_p(L²) = 2e ≤ v_p(m²)`. Thus `p ∤ N(m)`, and every prime power dividing `D` divides `a(n)`, +so `D ∣ a(n)`. +-/ + +namespace Math0.Frontier.A119936 +open Math0.Statements.A119936 + +/-- Every `k ∈ [1, n]` divides `lcm(1, …, n)`. -/ +private lemma dvd_lcmUpTo {n k : ℕ} (hk1 : 1 ≤ k) (hkn : k ≤ n) : k ∣ lcmUpTo n := + Finset.dvd_lcm (s := Finset.Icc 1 n) (f := id) (Finset.mem_Icc.2 ⟨hk1, hkn⟩) + +/-- `lcm(1, …, n) ≠ 0`. -/ +private lemma lcmUpTo_ne_zero (n : ℕ) : lcmUpTo n ≠ 0 := Nat.lcmUpto_ne_zero n + +/-- The `p`-adic valuation of `lcm(1, …, n)` is `⌊log_p n⌋`. -/ +private lemma factorization_lcmUpTo (n : ℕ) {p : ℕ} (hp : p.Prime) : + (lcmUpTo n).factorization p = Nat.log p n := Nat.factorization_lcmUpto n hp + +/-- `k l ∣ L²` for `k, l ∈ [1, n]`. -/ +private lemma mul_dvd_sq {n k l : ℕ} (hk : 1 ≤ k) (hkn : k ≤ n) (hl : 1 ≤ l) (hln : l ≤ n) : + k * l ∣ lcmUpTo n ^ 2 := by + rw [sq] + exact mul_dvd_mul (dvd_lcmUpTo hk hkn) (dvd_lcmUpTo hl hln) + +/-- The row entry scaled by `n · L²`: `N n m = ∑_{m ≤ l ≤ k ≤ n} L²/(k l)`. -/ +private def N (n m : ℕ) : ℕ := + ∑ k ∈ Finset.Icc m n, ∑ l ∈ Finset.Icc m k, lcmUpTo n ^ 2 / (k * l) + +/-- `N n m = n · L² · r(n, m)`. -/ +private lemma N_cast {n m : ℕ} (hm : 1 ≤ m) (hmn : m ≤ n) : + ((N n m : ℕ) : ℚ) = ((n * lcmUpTo n ^ 2 : ℕ) : ℚ) * r n m := by + rw [r_eq_explicit hm hmn, N] + have hn : (n : ℚ) ≠ 0 := by exact_mod_cast (show n ≠ 0 by omega) + have h1 : ((n * lcmUpTo n ^ 2 : ℕ) : ℚ) * + (1 / (n : ℚ) * ∑ k ∈ Finset.Icc m n, ∑ l ∈ Finset.Icc m k, 1 / ((k : ℚ) * l)) = + ((lcmUpTo n : ℚ) ^ 2) * ∑ k ∈ Finset.Icc m n, ∑ l ∈ Finset.Icc m k, 1 / ((k : ℚ) * l) := by + push_cast + field_simp + rw [h1, Finset.mul_sum] + push_cast + refine Finset.sum_congr rfl fun k hk => ?_ + rw [Finset.mul_sum] + refine Finset.sum_congr rfl fun l hl => ?_ + rw [Finset.mem_Icc] at hk hl + have hk0 : (k : ℚ) ≠ 0 := by exact_mod_cast (show k ≠ 0 by omega) + have hl0 : (l : ℚ) ≠ 0 := by exact_mod_cast (show l ≠ 0 by omega) + rw [Nat.cast_div (mul_dvd_sq (by omega) hk.2 (by omega) (by omega)) (by push_cast; positivity)] + push_cast + field_simp + +/-- If `M = D · q` with `M, D` natural, then `|num q| · D = M · den q`. -/ +private lemma num_mul_eq {q : ℚ} {D M : ℕ} (h : (M : ℚ) = (D : ℚ) * q) : + q.num.natAbs * D = M * q.den := by + have hq : (q.num : ℚ) = q * q.den := (Rat.mul_den_eq_num q).symm + have h2 : (q.num * D : ℤ) = (M * q.den : ℤ) := by + have : ((q.num * D : ℤ) : ℚ) = ((M * q.den : ℤ) : ℚ) := by + push_cast + rw [hq, h] + ring + exact_mod_cast this + have h3 := congrArg Int.natAbs h2 + simpa [Int.natAbs_mul] using h3 + +/-- If `M = D · q` with `M, D` natural, then `den q ∣ D`. -/ +private lemma den_dvd_of {q : ℚ} {D M : ℕ} (h : (M : ℚ) = (D : ℚ) * q) : q.den ∣ D := by + have := num_mul_eq h + refine Nat.Coprime.dvd_of_dvd_mul_left q.reduced.symm ⟨M, ?_⟩ + rw [this, Nat.mul_comm] + +/-- If `M = D · q` with `M, D` natural and the prime `p` does not divide `M`, then every power +`p^k ∣ D` divides `den q`. -/ +private lemma pow_dvd_den {q : ℚ} {D M p k : ℕ} (h : (M : ℚ) = (D : ℚ) * q) (hp : p.Prime) + (hM : ¬ p ∣ M) (hk : p ^ k ∣ D) : p ^ k ∣ q.den := by + have := num_mul_eq h + have hc : Nat.Coprime (p ^ k) M := + Nat.Coprime.pow_left _ ((Nat.Prime.coprime_iff_not_dvd hp).2 hM) + refine hc.dvd_of_dvd_mul_left ?_ + rw [← this] + exact Dvd.dvd.mul_left hk _ + +/-- For `1 ≤ k ≤ n`, `v_p(k) ≤ ⌊log_p n⌋`. -/ +private lemma factorization_le_log {p n k : ℕ} (hp : p.Prime) (hk : 1 ≤ k) (hkn : k ≤ n) : + k.factorization p ≤ Nat.log p n := + Nat.le_log_of_pow_le hp.one_lt + ((Nat.le_of_dvd (by omega) (Nat.ordProj_dvd k p)).trans hkn) + +/-- If not both `k` and `l` are multiples of `p^e` (`e = ⌊log_p n⌋`), then `p ∣ L²/(k l)`. -/ +private lemma p_dvd_term {p n k l : ℕ} (hp : p.Prime) (hk : 1 ≤ k) (hkn : k ≤ n) (hl : 1 ≤ l) + (hln : l ≤ n) (h : ¬ (p ^ Nat.log p n ∣ k ∧ p ^ Nat.log p n ∣ l)) : + p ∣ lcmUpTo n ^ 2 / (k * l) := by + have hq : lcmUpTo n ^ 2 / (k * l) * (k * l) = lcmUpTo n ^ 2 := + Nat.div_mul_cancel (mul_dvd_sq hk hkn hl hln) + by_contra hnd + have hpL : p ^ Nat.log p n ∣ lcmUpTo n := + (hp.pow_dvd_iff_le_factorization (lcmUpTo_ne_zero n)).2 + (factorization_lcmUpTo n hp).ge + have hpe : p ^ (2 * Nat.log p n) ∣ lcmUpTo n ^ 2 := by + rw [pow_mul'] + exact pow_dvd_pow_of_dvd hpL 2 + have hc : Nat.Coprime (p ^ (2 * Nat.log p n)) (lcmUpTo n ^ 2 / (k * l)) := + Nat.Coprime.pow_left _ ((Nat.Prime.coprime_iff_not_dvd hp).2 hnd) + have hkl : p ^ (2 * Nat.log p n) ∣ k * l := by + refine hc.dvd_of_dvd_mul_left ?_ + rw [hq] + exact hpe + rw [hp.pow_dvd_iff_le_factorization (by positivity), + Nat.factorization_mul (by omega) (by omega), Finsupp.add_apply] at hkl + have hke := factorization_le_log hp hk hkn + have hle := factorization_le_log hp hl hln + apply h + rw [hp.pow_dvd_iff_le_factorization (by omega), hp.pow_dvd_iff_le_factorization (by omega)] + omega + +/-- For a multiple `m ≥ 1` of `p^e` (`e = ⌊log_p n⌋`), `p ∤ L²/(m m)`. -/ +private lemma not_p_dvd_term {p n m : ℕ} (hp : p.Prime) (hm : 1 ≤ m) (hmn : m ≤ n) + (hpm : p ^ Nat.log p n ∣ m) : ¬ p ∣ lcmUpTo n ^ 2 / (m * m) := by + have hq : lcmUpTo n ^ 2 / (m * m) * (m * m) = lcmUpTo n ^ 2 := + Nat.div_mul_cancel (mul_dvd_sq hm hmn hm hmn) + intro hd + have h1 : p ^ (2 * Nat.log p n + 1) ∣ lcmUpTo n ^ 2 := by + rw [← hq, pow_succ, mul_comm, two_mul, pow_add] + exact mul_dvd_mul hd (mul_dvd_mul hpm hpm) + rw [hp.pow_dvd_iff_le_factorization (pow_ne_zero 2 (lcmUpTo_ne_zero n)), + Nat.factorization_pow, Finsupp.smul_apply, factorization_lcmUpTo n hp, smul_eq_mul] at h1 + omega + +/-- For every prime `p` there is a column `m` with `p ∤ N n m`. -/ +private lemma exists_good {p n : ℕ} (hp : p.Prime) (hn : 1 ≤ n) : + ∃ m, 1 ≤ m ∧ m ≤ n ∧ ¬ p ∣ N n m := by + set e := Nat.log p n with he + have hpe : p ^ e ≤ n := Nat.pow_log_le_self p (by omega) + have hpe0 : 0 < p ^ e := pow_pos hp.pos e + set c := n / p ^ e with hc + have hc1 : 1 ≤ c := Nat.div_pos hpe hpe0 + have hlt : n < p ^ e * (c + 1) := Nat.lt_mul_div_succ n hpe0 + refine ⟨c * p ^ e, ?_, Nat.div_mul_le_self n (p ^ e), ?_⟩ + · nlinarith + have hmn : c * p ^ e ≤ n := Nat.div_mul_le_self n (p ^ e) + have hm1 : 1 ≤ c * p ^ e := by nlinarith + have hmem : c * p ^ e ∈ Finset.Icc (c * p ^ e) n := Finset.mem_Icc.2 ⟨le_rfl, hmn⟩ + rw [N, ← Finset.add_sum_erase _ _ hmem, Finset.Icc_self, Finset.sum_singleton] + have hrest : p ∣ ∑ k ∈ (Finset.Icc (c * p ^ e) n).erase (c * p ^ e), + ∑ l ∈ Finset.Icc (c * p ^ e) k, lcmUpTo n ^ 2 / (k * l) := by + refine Finset.dvd_sum fun k hk => Finset.dvd_sum fun l hl => ?_ + rw [Finset.mem_erase, Finset.mem_Icc] at hk + rw [Finset.mem_Icc] at hl + refine p_dvd_term hp (by omega) hk.2.2 (by omega) (by omega) ?_ + rintro ⟨⟨j, hj⟩, -⟩ + rw [← he] at hj + have h1 : c * p ^ e < p ^ e * j := by omega + have h2 : p ^ e * j < p ^ e * (c + 1) := by omega + have h3 : c < j := by nlinarith + have h4 : j < c + 1 := Nat.lt_of_mul_lt_mul_left h2 + omega + intro hd + exact not_p_dvd_term hp hm1 hmn (dvd_mul_left _ _) ((Nat.dvd_add_left hrest).1 hd) + +/-- The integer form: `a(n) = n · lcm(1, …, n)²` for `n ≥ 1`. -/ +private lemma a_eq {n : ℕ} (hn : 1 ≤ n) : a n = n * lcmUpTo n ^ 2 := by + apply Nat.dvd_antisymm + · refine Finset.lcm_dvd fun m hm => ?_ + rw [Finset.mem_Icc] at hm + exact den_dvd_of (N_cast hm.1 hm.2) + · rw [Nat.dvd_iff_prime_pow_dvd_dvd] + intro p k hp hpk + obtain ⟨m, hm1, hmn, hpN⟩ := exists_good hp hn + exact (pow_dvd_den (N_cast hm1 hmn) hp hpN hpk).trans + (Finset.dvd_lcm (Finset.mem_Icc.2 ⟨hm1, hmn⟩)) + +/-- Lang's conjecture: `a(n)/n³ = A002944(n)²` for all `n ≥ 1`. -/ +theorem result : statement := + statement_iff.2 fun _ hn => a_eq hn + +end Math0.Frontier.A119936 + +#math0_settles Math0.Frontier.A119936.result Math0.Statements.A119936.statement diff --git a/lean/Math0/Frontier/OEIS/A120069.lean b/lean/Math0/Frontier/OEIS/A120069.lean new file mode 100644 index 0000000..b0cf603 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A120069.lean @@ -0,0 +1,139 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A120069 +import Math0.Audit + +/-! +# Denominators of `∑ C(k)/4^(k-1)`: Groux's and Staunton's conjectures (A120069) + +We prove both conjectures for every `n ≥ 1`. + +* Closed form: `r(m+1) = 4 - (2m+3) C(m+1)/4^m`, by induction from + `(k+2) C(k+1) = 2(2k+1) C(k)`. +* Write `C(m+1) = 2^v u` with `u` odd. Since `C(m+1) ≤ 4^m` we get `v ≤ 2m`, so + `C(m+1)/4^m = u/2^(2m-v)` and its denominator is `2^(2m-v)` (Groux's side). +* `r(m+1) = 4 - (2m+3)u/2^(2m-v)` and `(2m+3)u` is odd, so `a(m+1) = 2^(2m-v)`. +* `w(n) = (2n+1)/(n+1) c(2n) = (2n+1) C(n)/4^n`, so `2^e w(m+1)` is an integer exactly when + `e ≥ 2m+2-v`; thus `A283208(m+1) = 2m+2-v` and `2^(A283208(m+1)-2) = 2^(2m-v) = a(m+1)` + (Staunton's side). +-/ + +namespace Math0.Frontier.A120069 +open Math0.Statements.A120069 + +/-- Closed form of the partial sums: `r(m+1) = 4 - (2m+3) C(m+1)/4^m`. -/ +private theorem r_succ_closed (m : ℕ) : + r (m + 1) = 4 - (2 * m + 3) * (catalan (m + 1) : ℚ) / 4 ^ m := by + induction m with + | zero => norm_num [r, catalan_one] + | succ m ih => + have hs : r (m + 1 + 1) = r (m + 1) + (catalan (m + 1 + 1) : ℚ) / 4 ^ (m + 1) := by + rw [r, r, Finset.sum_Icc_succ_top (by omega)] + congr 1 + rw [show 2 * (m + 1 + 1 - 1) = 2 * (m + 1) by omega, pow_mul] + norm_num + have hc : ((m + 1 + 2 : ℕ) : ℚ) * catalan (m + 1 + 1) + = (2 * (2 * (m + 1) + 1) : ℕ) * catalan (m + 1) := by + exact_mod_cast succ_succ_mul_catalan (m + 1) + rw [hs, ih] + push_cast at hc ⊢ + rw [pow_succ] + field_simp + linear_combination (2 : ℚ) * hc + +/-- `C(m+1) ≤ 4^m`. -/ +private theorem catalan_succ_le (m : ℕ) : catalan (m + 1) ≤ 4 ^ m := by + induction m with + | zero => simp [catalan_one] + | succ m ih => + have h := succ_succ_mul_catalan (m + 1) + have : (m + 1 + 2) * catalan (m + 1 + 1) ≤ (m + 1 + 2) * 4 ^ (m + 1) := by + rw [h, pow_succ] + nlinarith + exact Nat.le_of_mul_le_mul_left this (by omega) + +/-- Catalan numbers are nonzero. -/ +private theorem catalan_ne_zero' (n : ℕ) : catalan n ≠ 0 := by + intro h + have := succ_mul_catalan_eq_centralBinom n + rw [h, mul_zero] at this + exact (Nat.centralBinom_pos n).ne' this.symm + +/-- An odd number over `2^k` has denominator `2^k`. -/ +private theorem den_odd_div_two_pow {u : ℕ} (k : ℕ) (hu : Odd u) : + ((u : ℚ) / 2 ^ k).den = 2 ^ k := by + have h := Rat.den_div_eq_of_coprime (a := (u : ℤ)) (b := (2 ^ k : ℤ)) (by positivity) (by + simp only [Int.natAbs_natCast, Int.natAbs_pow] + exact Nat.Coprime.pow_right _ hu.coprime_two_right) + push_cast at h + exact_mod_cast h + +/-- `w n = (2n+1) C(n)/4^n`. -/ +private theorem w_eq (n : ℕ) : w n = (2 * n + 1) * (catalan n : ℚ) / 4 ^ n := by + have h1 := four_pow_mul_vietoris n + have h2 : ((n + 1 : ℕ) : ℚ) * catalan n = n.centralBinom := by + exact_mod_cast succ_mul_catalan_eq_centralBinom n + have hv : vietoris n = (n.centralBinom : ℚ) / 4 ^ n := by + rw [← h1] + field_simp + rw [w, hv, ← h2] + push_cast + field_simp + +/-- Both conjectures (Groux 2010, Staunton 2026) hold for every `n ≥ 1`. -/ +theorem result : statement := by + intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩ + obtain ⟨v, u, hu, hCu⟩ := Nat.exists_eq_two_pow_mul_odd (catalan_ne_zero' (m + 1)) + have hv : v ≤ 2 * m := by + have h1 : 2 ^ v ≤ catalan (m + 1) := by + rw [hCu] + exact Nat.le_mul_of_pos_right _ hu.pos + have h2 := h1.trans (catalan_succ_le m) + rw [show (4 : ℕ) ^ m = 2 ^ (2 * m) by rw [pow_mul]; norm_num] at h2 + exact (Nat.pow_le_pow_iff_right (by norm_num)).mp h2 + have h4 : (4 : ℚ) ^ m = 2 ^ (2 * m - v) * 2 ^ v := by + rw [← pow_add, Nat.sub_add_cancel hv, pow_mul] + norm_num + have hkey : (catalan (m + 1) : ℚ) / 4 ^ m = (u : ℚ) / 2 ^ (2 * m - v) := by + rw [hCu, h4] + push_cast + field_simp + have hodd : Odd ((2 * m + 3) * u) := by + refine Odd.mul ?_ hu + exact ⟨m + 1, by ring⟩ + have hr : r (m + 1) = 4 - (((2 * m + 3) * u : ℕ) : ℚ) / 2 ^ (2 * m - v) := by + rw [r_succ_closed, mul_div_assoc, hkey] + push_cast + ring + have ha : a (m + 1) = 2 ^ (2 * m - v) := by + rw [a, hr, Rat.ofNat_sub_den, den_odd_div_two_pow _ hodd] + have hw : w (m + 1) = (((2 * m + 3) * u : ℕ) : ℚ) / 2 ^ (2 * m - v + 2) := by + rw [w_eq, hCu, pow_succ, h4, pow_add] + push_cast + field_simp + ring + have hA : A283208 (m + 1) = 2 * m + 2 - v := by + apply A283208_eq_of + · refine ⟨(2 * m + 3) * u, ?_⟩ + rw [hw, show 2 * m + 2 - v = 2 * m - v + 2 by omega] + field_simp + · right + rintro ⟨k, hk⟩ + rw [hw, show 2 * m + 2 - v - 1 = 2 * m - v + 1 by omega, pow_succ 2 (2 * m - v + 1)] at hk + have h2 : (((2 * m + 3) * u : ℕ) : ℚ) = 2 * k := by + rw [← hk] + field_simp + have h3 : (2 * m + 3) * u = 2 * k := by exact_mod_cast h2 + exact (Nat.not_even_iff_odd.mpr hodd) ⟨k, by omega⟩ + refine ⟨?_, ?_⟩ + · rw [ha, show m + 1 - 1 = m by omega, hkey, den_odd_div_two_pow _ hu] + · rw [ha, hA, show ((2 * m + 2 - v : ℕ) : ℤ) - 2 = ((2 * m - v : ℕ) : ℤ) by omega, + zpow_natCast] + push_cast + rfl + +end Math0.Frontier.A120069 + +#math0_settles Math0.Frontier.A120069.result Math0.Statements.A120069.statement diff --git a/lean/Math0/Frontier/OEIS/A121750.lean b/lean/Math0/Frontier/OEIS/A121750.lean new file mode 100644 index 0000000..3193c66 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A121750.lean @@ -0,0 +1,392 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A121750 +import Math0.Audit + +/-! +# Mathar's recurrence for A121750 (even columns in deco polyominoes) + +We prove R. J. Mathar's conjectured order-6 D-finite recurrence for A121750 for every `n ≥ 7`. + +**Translation invariance.** Shifting every column of a list in `tails r b` up by one cell gives +exactly `tails (r + 1) (b + 1)` (`tails_shift`), and keeps column lengths. Hence the table entry +`(tab r).getD b` (count, total even columns) only depends on `r - b`: it equals +`(cnt (r - b), tot (r - b))`, where `cnt m`, `tot m` are the entries at bottom `0`, and +`tot m = a (m + 1)`. + +**Recurrences.** The recursion of `tab` at bottom `0` becomes +`cnt (r+1) = 1 + gS cnt r` and `tot (r+1) = [r+1 odd] + hS cnt r + gS tot r`, with +`gS f r = ∑_{t ≤ r} ∑_{j ≤ t} f (r - j)` and `hS f r` the same sum restricted to odd `t`. +Peeling off `j = 0` gives `gS f (r+1) = gS f r + (r + 2) f (r + 1)` and +`hS f (r+1) + hS f r = gS f r + f (r + 1) ⌊(r + 2)/2⌋`. + +**Algebra.** For `n = r + 8`, write `r = 2s + p` (`p ∈ {0,1}`). Starting from the free values +`gS tot r`, `hS cnt r`, `gS cnt r`, seven steps of these recurrences express +`a(n-6), …, a(n)` as polynomials in `s` and the three free values; substituting into Mathar's +left-hand side gives `0` identically (`alg0`, `alg1`, by `ring`). The case `n = 7` is the +kernel-checked `recurrence_data`. +-/ + +namespace Math0.Frontier.A121750 +open Math0.Statements.A121750 + +/-- Shift every cell of a column list up by one. -/ +private def sh (cs : List (ℕ × ℕ)) : List (ℕ × ℕ) := cs.map fun c => (c.1 + 1, c.2 + 1) + +/-- `range' (b + 1) n` is `range' b n` shifted by one. -/ +private lemma range'_succ_left (b n : ℕ) : + List.range' (b + 1) n = (List.range' b n).map (· + 1) := by + induction n generalizing b with + | zero => simp + | succ n ih => rw [List.range'_succ, List.range'_succ, List.map_cons, ih] + +/-- Translation invariance: `tails (r + 1) (b + 1)` is `tails r b` shifted up by one. -/ +private lemma tails_shift (r b : ℕ) : tails (r + 1) (b + 1) = (tails r b).map sh := by + induction r generalizing b with + | zero => + rcases b with _ | b + · simp [tails, sh] + · simp [tails] + | succ r ih => + rw [tails, tails, List.map_append] + congr 1 + · by_cases h : b ≤ r + 1 + · rw [if_pos (by omega), if_pos h]; simp [sh] + · rw [if_neg (by omega), if_neg h]; simp + · rw [show r + 1 + 1 - (b + 1) = r + 1 - b by omega, range'_succ_left] + simp only [List.flatMap_map, List.map_flatMap] + congr 1 + funext t + rw [show t + 1 + 1 - (b + 1) = t + 1 - b by omega, range'_succ_left] + simp only [List.flatMap_map, ih, List.map_map] + congr 1 + +/-- Shifting does not change column lengths. -/ +private lemma evenCols_sh (cs : List (ℕ × ℕ)) : evenCols (sh cs) = evenCols cs := by + simp only [evenCols, sh, List.countP_map] + congr 1 + funext c + simp + +/-- Translation invariance of the table entries. -/ +private lemma tab_shift (r b : ℕ) : (tab (r + 1)).getD (b + 1) (0, 0) = (tab r).getD b (0, 0) := by + rw [tab_getD, tab_getD, tails_shift, List.length_map, List.map_map] + simp only [Function.comp_def, evenCols_sh] + +/-- Table entries depend only on `r - b`. -/ +private lemma tab_sub (r b : ℕ) (h : b ≤ r) : + (tab r).getD b (0, 0) = (tab (r - b)).getD 0 (0, 0) := by + induction b generalizing r with + | zero => rfl + | succ b ih => + obtain ⟨r, rfl⟩ : ∃ r', r = r' + 1 := ⟨r - 1, by omega⟩ + rw [tab_shift, ih r (by omega), Nat.add_sub_add_right] + +/-- `cnt m = |tails m 0|`, the number of deco polyominoes of height `m + 1`. -/ +private def cnt (m : ℕ) : ℕ := ((tab m).getD 0 (0, 0)).1 + +/-- `tot m = a (m + 1)`, the total number of even columns over `tails m 0`. -/ +private def tot (m : ℕ) : ℕ := ((tab m).getD 0 (0, 0)).2 + +/-- `gS f r = ∑_{t ≤ r} ∑_{j ≤ t} f (r - j)`. -/ +private def gS (f : ℕ → ℕ) (r : ℕ) : ℕ := + ∑ t ∈ Finset.range (r + 1), ∑ j ∈ Finset.range (t + 1), f (r - j) + +/-- `hS f r = ∑_{t ≤ r, t odd} ∑_{j ≤ t} f (r - j)`. -/ +private def hS (f : ℕ → ℕ) (r : ℕ) : ℕ := + ∑ t ∈ Finset.range (r + 1), eo 0 t * ∑ j ∈ Finset.range (t + 1), f (r - j) + +/-- `oddCnt k` is the number of odd `t < k`. -/ +private def oddCnt (k : ℕ) : ℕ := ∑ t ∈ Finset.range k, eo 0 t + +/-- A list sum over `range' 0 n` as a `Finset` sum. -/ +private lemma lsum (f : ℕ → ℕ) (n : ℕ) : + ((List.range' 0 n).map f).sum = ∑ i ∈ Finset.range n, f i := by + rw [← List.range_eq_range'] + induction n with + | zero => simp + | succ n ih => rw [List.sum_range_succ, Finset.sum_range_succ, ih] + +/-- The recursion of `tab` at bottom `0`, using translation invariance. -/ +private lemma row0 (r : ℕ) : (tab (r + 1)).getD 0 (0, 0) = + (1 + gS cnt r, eo 0 (r + 1) + hS cnt r + gS tot r) := by + have key : ∀ t ∈ Finset.range (r + 1), ∀ j ∈ Finset.range (t + 1), + (tab r).getD j (0, 0) = (cnt (r - j), tot (r - j)) := by + intro t ht j hj + simp only [Finset.mem_range] at ht hj + rw [tab_sub r j (by omega)] + rfl + have e1 : ∀ t ∈ Finset.range (r + 1), + ∑ j ∈ Finset.range (t + 1), ((tab r).getD j (0, 0)).1 = + ∑ j ∈ Finset.range (t + 1), cnt (r - j) := fun t ht => + Finset.sum_congr rfl fun j hj => by rw [key t ht j hj] + have e2 : ∀ t ∈ Finset.range (r + 1), + ∑ j ∈ Finset.range (t + 1), ((tab r).getD j (0, 0)).2 = + ∑ j ∈ Finset.range (t + 1), tot (r - j) := fun t ht => + Finset.sum_congr rfl fun j hj => by rw [key t ht j hj] + rw [tab, nextRow, List.getD_eq_getElem?_getD, List.getElem?_map, + List.getElem?_range (by omega)] + simp only [Option.map_some, Option.getD_some, Nat.sub_zero, List.sum_map_add, lsum] + refine Prod.ext ?_ ?_ + · show 1 + _ = 1 + _ + rw [gS] + congr 1 + exact Finset.sum_congr rfl e1 + · show eo 0 (r + 1) + (_ + _) = eo 0 (r + 1) + hS cnt r + gS tot r + rw [hS, gS, add_assoc] + congr 2 + · exact Finset.sum_congr rfl fun t ht => by rw [e1 t ht] + · exact Finset.sum_congr rfl e2 + +/-- Peeling `j = 0` off the inner sum. -/ +private lemma inner_succ (f : ℕ → ℕ) (r t : ℕ) : + ∑ j ∈ Finset.range (t + 1), f (r + 1 - j) = ∑ j ∈ Finset.range t, f (r - j) + f (r + 1) := by + rw [Finset.sum_range_succ'] + simp + +/-- `gS f (r + 1) = gS f r + (r + 2) f (r + 1)`. -/ +private lemma gS_succ (f : ℕ → ℕ) (r : ℕ) : gS f (r + 1) = gS f r + (r + 2) * f (r + 1) := by + rw [gS, gS] + simp_rw [inner_succ] + rw [Finset.sum_add_distrib, Finset.sum_const, Finset.card_range, smul_eq_mul, + Finset.sum_range_succ' (fun t => ∑ j ∈ Finset.range t, f (r - j))] + simp only [Finset.range_zero, Finset.sum_empty, add_zero] + +/-- Consecutive parities add up to one. -/ +private lemma eo_add (t : ℕ) : eo 0 (t + 1) + eo 0 t = 1 := by + unfold eo; split_ifs <;> omega + +/-- `hS f (r + 1) + hS f r = gS f r + f (r + 1) · oddCnt (r + 2)`. -/ +private lemma hS_succ (f : ℕ → ℕ) (r : ℕ) : + hS f (r + 1) + hS f r = gS f r + f (r + 1) * oddCnt (r + 2) := by + rw [hS, hS, gS, oddCnt] + simp_rw [inner_succ, mul_add] + rw [Finset.sum_add_distrib, + Finset.sum_range_succ' (fun t => eo 0 t * ∑ j ∈ Finset.range t, f (r - j))] + simp only [Finset.range_zero, Finset.sum_empty, mul_zero, add_zero] + rw [← Finset.sum_mul, mul_comm (∑ t ∈ Finset.range (r + 1 + 1), eo 0 t), add_right_comm, + ← Finset.sum_add_distrib] + congr 1 + refine Finset.sum_congr rfl fun t _ => ?_ + rw [← add_mul, eo_add, one_mul] + +/-- `oddCnt k = ⌊k / 2⌋`. -/ +private lemma oddCnt_eq (k : ℕ) : oddCnt k = k / 2 := by + induction k with + | zero => rfl + | succ k ih => + rw [oddCnt, Finset.sum_range_succ, ← oddCnt, ih] + unfold eo; split_ifs <;> omega + +/-- The first recurrence, in `ℤ`. -/ +private lemma Z1 (r : ℕ) : + (tot (r + 1) : ℤ) = (((r + 1) % 2 : ℕ) : ℤ) + hS cnt r + gS tot r := by + have h : tot (r + 1) = eo 0 (r + 1) + hS cnt r + gS tot r := by rw [tot, row0] + have he : eo 0 (r + 1) = (r + 1) % 2 := by unfold eo; split_ifs <;> omega + rw [h, he] + push_cast + ring + +/-- `gS tot (r + 1) = gS tot r + (r + 2) tot (r + 1)` in `ℤ`. -/ +private lemma Z2 (r : ℕ) : (gS tot (r + 1) : ℤ) = gS tot r + ((r : ℤ) + 2) * tot (r + 1) := by + rw [gS_succ]; push_cast; ring + +/-- The `hS` recurrence in `ℤ`. -/ +private lemma Z3 (r : ℕ) : (hS cnt (r + 1) : ℤ) = + gS cnt r + cnt (r + 1) * (((r + 2) / 2 : ℕ) : ℤ) - hS cnt r := by + have h := hS_succ cnt r + rw [oddCnt_eq] at h + have h' : ((hS cnt (r + 1) + hS cnt r : ℕ) : ℤ) = + ((gS cnt r + cnt (r + 1) * ((r + 2) / 2) : ℕ) : ℤ) := by rw [h] + rw [Nat.cast_add, Nat.cast_add, Nat.cast_mul] at h' + linarith + +/-- `cnt (r + 1) = 1 + gS cnt r` in `ℤ`. -/ +private lemma Z4 (r : ℕ) : (cnt (r + 1) : ℤ) = 1 + gS cnt r := by + have h : cnt (r + 1) = 1 + gS cnt r := by rw [cnt, row0] + rw [h]; push_cast; ring + +/-- `gS cnt (r + 1) = gS cnt r + (r + 2) cnt (r + 1)` in `ℤ`. -/ +private lemma Z5 (r : ℕ) : (gS cnt (r + 1) : ℤ) = gS cnt r + ((r : ℤ) + 2) * cnt (r + 1) := by + rw [gS_succ]; push_cast; ring + +/-- `a (k + 1) = tot k`. -/ +private lemma a_tot (k : ℕ) : (a (k + 1) : ℤ) = tot k := by + rw [a_eq_aDP]; rfl + +/-- The algebraic core for a base index `x = 2s + 0`: seven steps of the recurrences, +then Mathar's identity, as a polynomial identity. -/ +private lemma alg0 (s x : ℤ) {v1 v2 v3 v4 v5 v6 v7 gv0 gv1 gv2 gv3 gv4 gv5 gv6 hu0 hu1 hu2 hu3 hu4 hu5 hu6 gu0 gu1 gu2 gu3 gu4 gu5 u1 u2 u3 u4 u5 u6 e1 e2 e3 e4 e5 e6 e7 c2 c3 c4 c5 c6 c7 k0 k1 k2 k3 k4 k5 : ℤ} + (hv1 : v1 = e1 + hu0 + gv0) + (hv2 : v2 = e2 + hu1 + gv1) + (hv3 : v3 = e3 + hu2 + gv2) + (hv4 : v4 = e4 + hu3 + gv3) + (hv5 : v5 = e5 + hu4 + gv4) + (hv6 : v6 = e6 + hu5 + gv5) + (hv7 : v7 = e7 + hu6 + gv6) + (hg1 : gv1 = gv0 + (k0 + 2) * v1) + (hg2 : gv2 = gv1 + (k1 + 2) * v2) + (hg3 : gv3 = gv2 + (k2 + 2) * v3) + (hg4 : gv4 = gv3 + (k3 + 2) * v4) + (hg5 : gv5 = gv4 + (k4 + 2) * v5) + (hg6 : gv6 = gv5 + (k5 + 2) * v6) + (hh1 : hu1 = gu0 + u1 * c2 - hu0) + (hh2 : hu2 = gu1 + u2 * c3 - hu1) + (hh3 : hu3 = gu2 + u3 * c4 - hu2) + (hh4 : hu4 = gu3 + u4 * c5 - hu3) + (hh5 : hu5 = gu4 + u5 * c6 - hu4) + (hh6 : hu6 = gu5 + u6 * c7 - hu5) + (hu1' : u1 = 1 + gu0) + (hu2' : u2 = 1 + gu1) + (hu3' : u3 = 1 + gu2) + (hu4' : u4 = 1 + gu3) + (hu5' : u5 = 1 + gu4) + (hu6' : u6 = 1 + gu5) + (hgu1 : gu1 = gu0 + (k0 + 2) * u1) + (hgu2 : gu2 = gu1 + (k1 + 2) * u2) + (hgu3 : gu3 = gu2 + (k2 + 2) * u3) + (hgu4 : gu4 = gu3 + (k3 + 2) * u4) + (hgu5 : gu5 = gu4 + (k4 + 2) * u5) + (he1 : e1 = 1) + (he2 : e2 = 0) + (he3 : e3 = 1) + (he4 : e4 = 0) + (he5 : e5 = 1) + (he6 : e6 = 0) + (he7 : e7 = 1) + (hc2 : c2 = s + 1) + (hc3 : c3 = s + 1) + (hc4 : c4 = s + 2) + (hc5 : c5 = s + 2) + (hc6 : c6 = s + 3) + (hc7 : c7 = s + 3) + (hk0 : k0 = 2 * s + 0) + (hk1 : k1 = 2 * s + 1) + (hk2 : k2 = 2 * s + 2) + (hk3 : k3 = 2 * s + 3) + (hk4 : k4 = 2 * s + 4) + (hk5 : k5 = 2 * s + 5) + (hx : x = 2 * s + 0) + : v7 + (-(x + 8) - 2) * v6 + (-(x + 8) ^ 2 + 4 * (x + 8) - 2) * v5 + ((x + 8) ^ 3 - 3 * (x + 8) ^ 2 - 4 * (x + 8) + 11) * v4 - ((x + 8) - 1) * ((x + 8) ^ 2 - 11 * (x + 8) + 26) * v3 + (-(x + 8) ^ 3 + 5 * (x + 8) ^ 2 + 7 * (x + 8) - 43) * v2 + ((x + 8) - 3) * ((x + 8) - 5) ^ 2 * v1 = 0 := by + subst_vars + ring + +/-- The algebraic core for a base index `x = 2s + 1`: seven steps of the recurrences, +then Mathar's identity, as a polynomial identity. -/ +private lemma alg1 (s x : ℤ) {v1 v2 v3 v4 v5 v6 v7 gv0 gv1 gv2 gv3 gv4 gv5 gv6 hu0 hu1 hu2 hu3 hu4 hu5 hu6 gu0 gu1 gu2 gu3 gu4 gu5 u1 u2 u3 u4 u5 u6 e1 e2 e3 e4 e5 e6 e7 c2 c3 c4 c5 c6 c7 k0 k1 k2 k3 k4 k5 : ℤ} + (hv1 : v1 = e1 + hu0 + gv0) + (hv2 : v2 = e2 + hu1 + gv1) + (hv3 : v3 = e3 + hu2 + gv2) + (hv4 : v4 = e4 + hu3 + gv3) + (hv5 : v5 = e5 + hu4 + gv4) + (hv6 : v6 = e6 + hu5 + gv5) + (hv7 : v7 = e7 + hu6 + gv6) + (hg1 : gv1 = gv0 + (k0 + 2) * v1) + (hg2 : gv2 = gv1 + (k1 + 2) * v2) + (hg3 : gv3 = gv2 + (k2 + 2) * v3) + (hg4 : gv4 = gv3 + (k3 + 2) * v4) + (hg5 : gv5 = gv4 + (k4 + 2) * v5) + (hg6 : gv6 = gv5 + (k5 + 2) * v6) + (hh1 : hu1 = gu0 + u1 * c2 - hu0) + (hh2 : hu2 = gu1 + u2 * c3 - hu1) + (hh3 : hu3 = gu2 + u3 * c4 - hu2) + (hh4 : hu4 = gu3 + u4 * c5 - hu3) + (hh5 : hu5 = gu4 + u5 * c6 - hu4) + (hh6 : hu6 = gu5 + u6 * c7 - hu5) + (hu1' : u1 = 1 + gu0) + (hu2' : u2 = 1 + gu1) + (hu3' : u3 = 1 + gu2) + (hu4' : u4 = 1 + gu3) + (hu5' : u5 = 1 + gu4) + (hu6' : u6 = 1 + gu5) + (hgu1 : gu1 = gu0 + (k0 + 2) * u1) + (hgu2 : gu2 = gu1 + (k1 + 2) * u2) + (hgu3 : gu3 = gu2 + (k2 + 2) * u3) + (hgu4 : gu4 = gu3 + (k3 + 2) * u4) + (hgu5 : gu5 = gu4 + (k4 + 2) * u5) + (he1 : e1 = 0) + (he2 : e2 = 1) + (he3 : e3 = 0) + (he4 : e4 = 1) + (he5 : e5 = 0) + (he6 : e6 = 1) + (he7 : e7 = 0) + (hc2 : c2 = s + 1) + (hc3 : c3 = s + 2) + (hc4 : c4 = s + 2) + (hc5 : c5 = s + 3) + (hc6 : c6 = s + 3) + (hc7 : c7 = s + 4) + (hk0 : k0 = 2 * s + 1) + (hk1 : k1 = 2 * s + 2) + (hk2 : k2 = 2 * s + 3) + (hk3 : k3 = 2 * s + 4) + (hk4 : k4 = 2 * s + 5) + (hk5 : k5 = 2 * s + 6) + (hx : x = 2 * s + 1) + : v7 + (-(x + 8) - 2) * v6 + (-(x + 8) ^ 2 + 4 * (x + 8) - 2) * v5 + ((x + 8) ^ 3 - 3 * (x + 8) ^ 2 - 4 * (x + 8) + 11) * v4 - ((x + 8) - 1) * ((x + 8) ^ 2 - 11 * (x + 8) + 26) * v3 + (-(x + 8) ^ 3 + 5 * (x + 8) ^ 2 + 7 * (x + 8) - 43) * v2 + ((x + 8) - 3) * ((x + 8) - 5) ^ 2 * v1 = 0 := by + subst_vars + ring + +/-- Mathar's identity at `n = r + 8`, in terms of `tot`. -/ +private lemma key (r : ℕ) : + (tot (r + 1 + 1 + 1 + 1 + 1 + 1 + 1) : ℤ) + (-((r : ℤ) + 8) - 2) * (tot (r + 1 + 1 + 1 + 1 + 1 + 1) : ℤ) + (-((r : ℤ) + 8) ^ 2 + 4 * ((r : ℤ) + 8) - 2) * (tot (r + 1 + 1 + 1 + 1 + 1) : ℤ) + (((r : ℤ) + 8) ^ 3 - 3 * ((r : ℤ) + 8) ^ 2 - 4 * ((r : ℤ) + 8) + 11) * (tot (r + 1 + 1 + 1 + 1) : ℤ) - (((r : ℤ) + 8) - 1) * (((r : ℤ) + 8) ^ 2 - 11 * ((r : ℤ) + 8) + 26) * (tot (r + 1 + 1 + 1) : ℤ) + (-((r : ℤ) + 8) ^ 3 + 5 * ((r : ℤ) + 8) ^ 2 + 7 * ((r : ℤ) + 8) - 43) * (tot (r + 1 + 1) : ℤ) + (((r : ℤ) + 8) - 3) * (((r : ℤ) + 8) - 5) ^ 2 * (tot (r + 1) : ℤ) = 0 := by + obtain ⟨s, rfl | rfl⟩ := Nat.even_or_odd' r + · exact alg0 (s : ℤ) ((2 * s : ℕ) : ℤ) + (Z1 (2 * s)) (Z1 (2 * s + 1)) (Z1 (2 * s + 1 + 1)) (Z1 (2 * s + 1 + 1 + 1)) + (Z1 (2 * s + 1 + 1 + 1 + 1)) (Z1 (2 * s + 1 + 1 + 1 + 1 + 1)) (Z1 (2 * s + 1 + 1 + 1 + 1 + 1 + 1)) (Z2 (2 * s)) + (Z2 (2 * s + 1)) (Z2 (2 * s + 1 + 1)) (Z2 (2 * s + 1 + 1 + 1)) (Z2 (2 * s + 1 + 1 + 1 + 1)) + (Z2 (2 * s + 1 + 1 + 1 + 1 + 1)) (Z3 (2 * s)) (Z3 (2 * s + 1)) (Z3 (2 * s + 1 + 1)) + (Z3 (2 * s + 1 + 1 + 1)) (Z3 (2 * s + 1 + 1 + 1 + 1)) (Z3 (2 * s + 1 + 1 + 1 + 1 + 1)) (Z4 (2 * s)) + (Z4 (2 * s + 1)) (Z4 (2 * s + 1 + 1)) (Z4 (2 * s + 1 + 1 + 1)) (Z4 (2 * s + 1 + 1 + 1 + 1)) + (Z4 (2 * s + 1 + 1 + 1 + 1 + 1)) (Z5 (2 * s)) (Z5 (2 * s + 1)) (Z5 (2 * s + 1 + 1)) + (Z5 (2 * s + 1 + 1 + 1)) (Z5 (2 * s + 1 + 1 + 1 + 1)) (by omega) (by omega) + (by omega) (by omega) (by omega) (by omega) + (by omega) (by omega) (by omega) (by omega) + (by omega) (by omega) (by omega) (by push_cast; ring) + (by push_cast; ring) (by push_cast; ring) (by push_cast; ring) (by push_cast; ring) + (by push_cast; ring) (by push_cast; ring) + · exact alg1 (s : ℤ) ((2 * s + 1 : ℕ) : ℤ) + (Z1 (2 * s + 1)) (Z1 (2 * s + 1 + 1)) (Z1 (2 * s + 1 + 1 + 1)) (Z1 (2 * s + 1 + 1 + 1 + 1)) + (Z1 (2 * s + 1 + 1 + 1 + 1 + 1)) (Z1 (2 * s + 1 + 1 + 1 + 1 + 1 + 1)) (Z1 (2 * s + 1 + 1 + 1 + 1 + 1 + 1 + 1)) (Z2 (2 * s + 1)) + (Z2 (2 * s + 1 + 1)) (Z2 (2 * s + 1 + 1 + 1)) (Z2 (2 * s + 1 + 1 + 1 + 1)) (Z2 (2 * s + 1 + 1 + 1 + 1 + 1)) + (Z2 (2 * s + 1 + 1 + 1 + 1 + 1 + 1)) (Z3 (2 * s + 1)) (Z3 (2 * s + 1 + 1)) (Z3 (2 * s + 1 + 1 + 1)) + (Z3 (2 * s + 1 + 1 + 1 + 1)) (Z3 (2 * s + 1 + 1 + 1 + 1 + 1)) (Z3 (2 * s + 1 + 1 + 1 + 1 + 1 + 1)) (Z4 (2 * s + 1)) + (Z4 (2 * s + 1 + 1)) (Z4 (2 * s + 1 + 1 + 1)) (Z4 (2 * s + 1 + 1 + 1 + 1)) (Z4 (2 * s + 1 + 1 + 1 + 1 + 1)) + (Z4 (2 * s + 1 + 1 + 1 + 1 + 1 + 1)) (Z5 (2 * s + 1)) (Z5 (2 * s + 1 + 1)) (Z5 (2 * s + 1 + 1 + 1)) + (Z5 (2 * s + 1 + 1 + 1 + 1)) (Z5 (2 * s + 1 + 1 + 1 + 1 + 1)) (by omega) (by omega) + (by omega) (by omega) (by omega) (by omega) + (by omega) (by omega) (by omega) (by omega) + (by omega) (by omega) (by omega) (by push_cast; ring) + (by push_cast; ring) (by push_cast; ring) (by push_cast; ring) (by push_cast; ring) + (by push_cast; ring) (by push_cast; ring) + + +/-- Mathar's conjectured recurrence holds for every `n ≥ 7`. -/ +theorem result : statement := by + intro n hn + rcases Nat.lt_or_ge n 8 with h | h + · obtain rfl : n = 7 := by omega + exact recurrence_data 7 (by decide) + · obtain ⟨r, rfl⟩ : ∃ r, n = r + 8 := ⟨n - 8, by omega⟩ + have h0 : (a (r + 8) : ℤ) = tot (r + 1 + 1 + 1 + 1 + 1 + 1 + 1) := a_tot _ + have h1 : (a (r + 8 - 1) : ℤ) = tot (r + 1 + 1 + 1 + 1 + 1 + 1) := by + rw [show r + 8 - 1 = r + 1 + 1 + 1 + 1 + 1 + 1 + 1 by omega]; exact a_tot _ + have h2 : (a (r + 8 - 2) : ℤ) = tot (r + 1 + 1 + 1 + 1 + 1) := by + rw [show r + 8 - 2 = r + 1 + 1 + 1 + 1 + 1 + 1 by omega]; exact a_tot _ + have h3 : (a (r + 8 - 3) : ℤ) = tot (r + 1 + 1 + 1 + 1) := by + rw [show r + 8 - 3 = r + 1 + 1 + 1 + 1 + 1 by omega]; exact a_tot _ + have h4 : (a (r + 8 - 4) : ℤ) = tot (r + 1 + 1 + 1) := by + rw [show r + 8 - 4 = r + 1 + 1 + 1 + 1 by omega]; exact a_tot _ + have h5 : (a (r + 8 - 5) : ℤ) = tot (r + 1 + 1) := by + rw [show r + 8 - 5 = r + 1 + 1 + 1 by omega]; exact a_tot _ + have h6 : (a (r + 8 - 6) : ℤ) = tot (r + 1) := by + rw [show r + 8 - 6 = r + 1 + 1 by omega]; exact a_tot _ + rw [h0, h1, h2, h3, h4, h5, h6] + push_cast + linear_combination key r + +end Math0.Frontier.A121750 + +#math0_settles Math0.Frontier.A121750.result Math0.Statements.A121750.statement diff --git a/lean/Math0/Frontier/OEIS/A123710.lean b/lean/Math0/Frontier/OEIS/A123710.lean new file mode 100644 index 0000000..a0a11ba --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A123710.lean @@ -0,0 +1,473 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A123710 +import Math0.Audit + +/-! +# A123710: the rows of `inv(⌊n/k⌋)` with four nonzero entries are `6` and the proper prime powers + +We prove Hasler's conjecture `a(n) = A025475(n)` for `n > 2`. + +**Closed form of the inverse.** Let `g n k = μ(n/k)` if `k ∣ n` and `0` otherwise. Then row `n` +of the inverse of `A(n,k) = ⌊n/k⌋` is `T(n,k) = g n k - g n (k+1)` (`T_eq_F`). Indeed, by Abel +summation and `⌊k/j⌋ - ⌊(k-1)/j⌋ = [j ∣ k]`, +`∑_k (g n k - g n (k+1)) ⌊k/j⌋ = ∑_{j ∣ k ∣ n} μ(n/k) = ∑_{d ∣ n/j} μ(d) = [j = n]` (`key`), so +these rows form a left inverse of every truncation, which must be the matrix inverse. + +**Counting.** Hence `A123709 n` is the number of `k ∈ [1, n]` with `g n k ≠ g n (k+1)` +(`A123709_eq_card`); every such `k` has `g n k ≠ 0` or `g n (k+1) ≠ 0`. +* For `n = p^a`, `a ≥ 2`, `g n` is supported on `{p^(a-1), p^a}` with values `-1, 1`, and the + change points are exactly `p^(a-1) - 1, p^(a-1), p^a - 1, p^a` (`card_C_pp`). +* For `n = p` prime the change points lie in `{1, p - 1, p}` (`card_C_prime`). +* If `p < q` are primes dividing `n ≠ 6`, then with `A = n/p`: `A - 1, A, n - 1, n` are change + points (`A ± 1` cannot divide `n`, since consecutive divisors `d, d+1` of `n` give + `d(d+1) ∣ n`), and since `g n (n/q) = -1 ≠ 0 = g n (A - 1)` with `n/q < A - 1`, there is one + more change point in `[n/q, A - 1)` (`card_C_two`). So there are at least `5`. +Together with `A123709 1 = 1`, `A123709 6 = 4` this gives +`IsTerm n ↔ n = 6 ∨ n` is a proper prime power (`isTerm_iff`). + +**Indexing.** Both predicates agree from `7` on and have exactly two elements below `7`, so their +`nth` elements agree from index `2` on (`nth_shift`). +-/ + +namespace Math0.Frontier.A123710 +open Math0.Statements.A123710 +open Finset + +/-! ### The closed form of the inverse -/ + +/-- `g n k = μ(n / k)` if `k ∣ n`, and `0` otherwise. -/ +private def g (n k : ℕ) : ℤ := if k ∣ n then ArithmeticFunction.moebius (n / k) else 0 + +/-- The closed form of row `n` of the inverse: `F n k = g n k - g n (k + 1)`. -/ +private def F (n k : ℕ) : ℤ := g n k - g n (k + 1) + +/-- `g n k = 0` when `k ∤ n`. -/ +private lemma g_eq_zero {n k : ℕ} (h : ¬ k ∣ n) : g n k = 0 := by simp [g, h] + +/-- `g n k = 0` when `0 < n < k`. -/ +private lemma g_of_gt {n k : ℕ} (hn : 1 ≤ n) (h : n < k) : g n k = 0 := + g_eq_zero fun hd => absurd (Nat.le_of_dvd (by omega) hd) (by omega) + +/-- `g n n = μ 1 = 1`. -/ +private lemma g_self {n : ℕ} (hn : 1 ≤ n) : g n n = 1 := by + rw [g, if_pos dvd_rfl, Nat.div_self (by omega), ArithmeticFunction.moebius_apply_one] + +/-- `g n (n / q) = μ q = -1` for a prime `q ∣ n`. -/ +private lemma g_div_prime {n q : ℕ} (hn : 1 ≤ n) (hq : q.Prime) (hqn : q ∣ n) : + g n (n / q) = -1 := by + rw [g, if_pos (Nat.div_dvd_of_dvd hqn), Nat.div_div_self hqn (by omega), + ArithmeticFunction.moebius_apply_prime hq] + +/-- `F n k = 0` when `0 < n < k`. -/ +private lemma F_of_gt {n k : ℕ} (hn : 1 ≤ n) (h : n < k) : F n k = 0 := by + rw [F, g_of_gt hn h, g_of_gt hn (by omega), sub_zero] + +/-- Abel summation. -/ +private lemma abel (u v : ℕ → ℤ) (N : ℕ) : + ∑ l ∈ range N, (u (l + 1) - u (l + 1 + 1)) * v (l + 1) = + ∑ l ∈ range N, u (l + 1) * (v (l + 1) - v l) - u (N + 1) * v N + u 1 * v 0 := by + induction N with + | zero => simp + | succ N ih => rw [sum_range_succ, ih, sum_range_succ]; ring + +/-- `∑_{d ∣ m} μ d = [m = 1]`. -/ +private lemma sum_moebius_divisors (m : ℕ) : + ∑ d ∈ m.divisors, ArithmeticFunction.moebius d = if m = 1 then 1 else 0 := by + rw [← ArithmeticFunction.coe_mul_zeta_apply, ArithmeticFunction.moebius_mul_coe_zeta, + ArithmeticFunction.one_apply] + +/-- `∑_{d ∣ n, j ∣ d} μ(n/d) = [j = n]`. -/ +private lemma sum_divisors_dvd {n j : ℕ} (hn : 1 ≤ n) (hj : 1 ≤ j) : + ∑ d ∈ n.divisors, (if j ∣ d then ArithmeticFunction.moebius (n / d) else 0) = + if j = n then 1 else 0 := by + have h1 : ∑ d ∈ n.divisors, (if j ∣ d then ArithmeticFunction.moebius (n / d) else 0) = + ∑ d ∈ n.divisors, (if j ∣ n / d then ArithmeticFunction.moebius d else 0) := by + rw [← Nat.sum_div_divisors n (fun d => if j ∣ n / d then ArithmeticFunction.moebius d else 0)] + refine sum_congr rfl fun d hd => ?_ + rw [Nat.mem_divisors] at hd + rw [Nat.div_div_self hd.1 hd.2] + rw [h1] + by_cases hjn : j ∣ n + · obtain ⟨m, rfl⟩ := hjn + have hm : m ≠ 0 := by rintro rfl; simp at hn + have h2 : ∀ d ∈ (j * m).divisors, + (if j ∣ j * m / d then ArithmeticFunction.moebius d else 0) = + if d ∣ m then ArithmeticFunction.moebius d else 0 := by + intro d hd + rw [Nat.mem_divisors] at hd + have : j ∣ j * m / d ↔ d ∣ m := by + rw [Nat.dvd_div_iff_mul_dvd hd.1, mul_comm d j] + exact Nat.mul_dvd_mul_iff_left (by omega) + simp only [this] + rw [sum_congr rfl h2] + rw [← sum_subset (Nat.divisors_subset_of_dvd (by omega) (Dvd.intro_left j rfl))] + · rw [sum_congr rfl (fun d hd => if_pos (Nat.dvd_of_mem_divisors hd)), sum_moebius_divisors] + by_cases hm1 : m = 1 + · subst hm1; simp + · rw [if_neg hm1, if_neg] + intro h + apply hm1 + exact (Nat.eq_of_mul_eq_mul_left (by omega : 0 < j) (by rw [mul_one]; exact h)).symm + · intro d _ hd + rw [if_neg] + exact fun h => hd (Nat.mem_divisors.2 ⟨h, hm⟩) + · rw [if_neg (fun h : j = n => hjn (by rw [h]))] + exact sum_eq_zero fun d hd => + if_neg fun h => hjn (h.trans (Nat.div_dvd_of_dvd (Nat.dvd_of_mem_divisors hd))) + +/-- Row `n` of `F · A = I`: `∑_{k=1}^{n} F(n,k) ⌊k/j⌋ = [j = n]`. -/ +private lemma key {n j : ℕ} (hn : 1 ≤ n) (hj : 1 ≤ j) : + ∑ l ∈ range n, F n (l + 1) * (((l + 1) / j : ℕ) : ℤ) = if j = n then 1 else 0 := by + have e1 := abel (g n) (fun l => ((l / j : ℕ) : ℤ)) n + simp only [Nat.zero_div, Nat.cast_zero, mul_zero, add_zero] at e1 + rw [g_of_gt hn (by omega : n < n + 1), zero_mul, sub_zero] at e1 + simp only [F] + rw [e1, ← sum_divisors_dvd hn hj] + have e2 : ∀ l, (((l + 1) / j : ℕ) : ℤ) - ((l / j : ℕ) : ℤ) = if j ∣ l + 1 then 1 else 0 := by + intro l + rw [Nat.succ_div] + split_ifs <;> push_cast <;> ring + simp only [e2] + rw [Nat.divisors, sum_filter, sum_Ico_eq_sum_range, Nat.add_sub_cancel] + refine sum_congr rfl fun l _ => ?_ + rw [add_comm 1 l, g] + split_ifs <;> simp + +/-- The `N × N` truncation of `F`. -/ +private def Fmat (N : ℕ) : Matrix (Fin N) (Fin N) ℤ := + Matrix.of fun i j => F ((i : ℕ) + 1) ((j : ℕ) + 1) + +/-- `F` is a left inverse of every truncation of `⌊n/k⌋`. -/ +private lemma Fmat_mul_floorMat (N : ℕ) : Fmat N * floorMat N = 1 := by + ext i j + rw [Matrix.mul_apply, Matrix.one_apply] + simp only [Fmat, floorMat, Matrix.of_apply] + rw [Fin.sum_univ_eq_sum_range + (fun l => F ((i : ℕ) + 1) (l + 1) * (((l + 1) / ((j : ℕ) + 1) : ℕ) : ℤ)) N] + have hi := i.isLt + have hN : range N = range (((i : ℕ) + 1) + (N - ((i : ℕ) + 1))) := by congr 1; omega + rw [hN, Finset.sum_range_add, key (by omega) (by omega)] + rw [Finset.sum_eq_zero (s := range (N - ((i : ℕ) + 1))) fun x _ => by + rw [F_of_gt (by omega) (by omega), zero_mul], add_zero] + by_cases e : i = j + · subst e; simp + · rw [if_neg e, if_neg] + intro e' + exact e (Fin.ext (by omega)) + +/-- The closed form of the inverse: `T n k = g n k - g n (k + 1)` for `1 ≤ k ≤ n`. -/ +private lemma T_eq_F {n k : ℕ} (hk : 1 ≤ k) (hkn : k ≤ n) : T n k = F n k := by + have h : Tmat n = Fmat n := by rw [Tmat_eq_inv, Matrix.inv_eq_left_inv (Fmat_mul_floorMat n)] + have := congrFun (congrFun h ⟨n - 1, by omega⟩) ⟨k - 1, by omega⟩ + simp only [Tmat, Fmat, Matrix.of_apply] at this + rwa [Nat.sub_add_cancel (by omega : 1 ≤ n), Nat.sub_add_cancel hk] at this + +/-! ### Counting the change points -/ + +/-- The change points of `g n` in `[1, n]`: the nonzero entries of row `n`. -/ +private def C (n : ℕ) : Finset ℕ := {k ∈ Icc 1 n | F n k ≠ 0} + +private lemma A123709_eq_card (n : ℕ) : A123709 n = #(C n) := by + rw [A123709, C] + congr 1 + refine filter_congr fun k hk => ?_ + rw [mem_Icc] at hk + rw [A123706_eq_T, T_eq_F hk.1 hk.2] + +private lemma mem_C {n k : ℕ} : k ∈ C n ↔ 1 ≤ k ∧ k ≤ n ∧ g n k ≠ g n (k + 1) := by + simp only [C, mem_filter, mem_Icc, F, ne_eq, sub_eq_zero, and_assoc] + +private lemma ne_zero_of_ne {x y : ℤ} (h : x ≠ y) : x ≠ 0 ∨ y ≠ 0 := by + by_cases hx : x = 0 + · exact Or.inr fun hy => h (hx.trans hy.symm) + · exact Or.inl hx + +/-- Two consecutive divisors `d, d + 1` of `n` satisfy `d (d + 1) ∣ n`. -/ +private lemma consec {d n : ℕ} (h1 : d ∣ n) (h2 : d + 1 ∣ n) : d * (d + 1) ∣ n := + (Nat.coprime_self_add_right.2 (Nat.coprime_one_right d)).mul_dvd_of_dvd_of_dvd h1 h2 + +/-- `g n (n - 1) = 0` for `n ≥ 3`. -/ +private lemma g_pred {n : ℕ} (hn : 3 ≤ n) : g n (n - 1) = 0 := by + apply g_eq_zero + intro hd + obtain ⟨c, rfl⟩ : ∃ c, n = c + 1 := ⟨n - 1, by omega⟩ + rw [Nat.add_sub_cancel] at hd + have := (Nat.coprime_self_add_right.2 (Nat.coprime_one_right c)).eq_one_of_dvd hd + omega + +/-- A discrete intermediate value statement: if `u a ≠ u (a + d)`, `u` changes somewhere in +`[a, a + d)`. -/ +private lemma ivt (u : ℕ → ℤ) (a : ℕ) : + ∀ d, u a ≠ u (a + d) → ∃ j, a ≤ j ∧ j < a + d ∧ u j ≠ u (j + 1) + | 0, h => absurd rfl h + | d + 1, h => by + by_cases h' : u a = u (a + d) + · exact ⟨a + d, by omega, by omega, fun e => h (h'.trans e)⟩ + · obtain ⟨j, h1, h2, h3⟩ := ivt u a d h' + exact ⟨j, h1, by omega, h3⟩ + +/-- For a proper prime power `p ^ a` there are exactly four change points. -/ +private lemma card_C_pp {p a : ℕ} (hp : p.Prime) (ha : 2 ≤ a) : #(C (p ^ a)) = 4 := by + obtain ⟨b, rfl⟩ : ∃ b, a = b + 2 := ⟨a - 2, by omega⟩ + have hp2 := hp.two_le + have hB2 : 2 ≤ p ^ (b + 1) := le_trans hp2 (Nat.le_self_pow (by omega) p) + have hnB : 2 * p ^ (b + 1) ≤ p ^ (b + 2) := by + rw [pow_succ p (b + 1), mul_comm]; exact Nat.mul_le_mul_left _ hp2 + have hn1 : 1 ≤ p ^ (b + 2) := by omega + have hdiv : p ^ (b + 2) / p = p ^ (b + 1) := by + rw [pow_succ p (b + 1), Nat.mul_div_cancel _ hp.pos] + have supp : ∀ k, g (p ^ (b + 2)) k ≠ 0 → k = p ^ (b + 1) ∨ k = p ^ (b + 2) := by + intro k hk + by_cases hkd : k ∣ p ^ (b + 2) + · obtain ⟨i, hi, rfl⟩ := (Nat.dvd_prime_pow hp).1 hkd + rw [g, if_pos hkd, Nat.pow_div hi hp.pos] at hk + by_cases h0 : b + 2 - i = 0 + · right; congr 1; omega + · rw [ArithmeticFunction.moebius_apply_prime_pow hp h0] at hk + split_ifs at hk with h1 + · left; congr 1; omega + · exact absurd rfl hk + · exact absurd (g_eq_zero hkd) hk + have gz : ∀ k, k ≠ p ^ (b + 1) → k ≠ p ^ (b + 2) → g (p ^ (b + 2)) k = 0 := fun k h1 h2 => by + by_contra h + rcases supp k h with h' | h' <;> contradiction + have gB : g (p ^ (b + 2)) (p ^ (b + 1)) = -1 := by + rw [← hdiv]; exact g_div_prime hn1 hp (dvd_pow_self p (by omega)) + have gN : g (p ^ (b + 2)) (p ^ (b + 2)) = 1 := g_self hn1 + generalize p ^ (b + 2) = N at * + generalize p ^ (b + 1) = B at * + have hC : C N = {B - 1, B, N - 1, N} := by + ext k + rw [mem_C] + simp only [mem_insert, mem_singleton] + constructor + · rintro ⟨h1, h2, h3⟩ + rcases ne_zero_of_ne h3 with h | h + · rcases supp _ h with h | h <;> omega + · rcases supp _ h with h | h <;> omega + · rintro (rfl | rfl | rfl | rfl) + · refine ⟨by omega, by omega, ?_⟩ + rw [gz _ (by omega) (by omega), show B - 1 + 1 = B by omega, gB]; norm_num + · refine ⟨by omega, by omega, ?_⟩ + rw [gB, gz _ (by omega) (by omega)]; norm_num + · refine ⟨by omega, by omega, ?_⟩ + rw [gz _ (by omega) (by omega), show N - 1 + 1 = N by omega, gN]; norm_num + · refine ⟨by omega, le_rfl, ?_⟩ + rw [gN, gz _ (by omega) (by omega)]; norm_num + rw [hC, card_insert_of_notMem (by simp only [mem_insert, mem_singleton]; omega), + card_insert_of_notMem (by simp only [mem_insert, mem_singleton]; omega), + card_insert_of_notMem (by simp only [mem_singleton]; omega), card_singleton] + +/-- For a prime `p` there are at most three change points. -/ +private lemma card_C_prime {p : ℕ} (hp : p.Prime) : #(C p) ≤ 3 := by + have supp : ∀ k, g p k ≠ 0 → k = 1 ∨ k = p := fun k hk => by + by_cases hkd : k ∣ p + · exact hp.eq_one_or_self_of_dvd k hkd + · exact absurd (g_eq_zero hkd) hk + have hsub : C p ⊆ {1, p - 1, p} := by + intro k hk + rw [mem_C] at hk + obtain ⟨h1, h2, h3⟩ := hk + simp only [mem_insert, mem_singleton] + rcases ne_zero_of_ne h3 with h | h + · rcases supp _ h with h | h <;> omega + · rcases supp _ h with h | h <;> omega + exact (card_le_card hsub).trans card_le_three + +/-- If `p` and `p + 1` are both prime, then `p = 2`. -/ +private lemma eq_two_of_succ {p : ℕ} (hp : p.Prime) (hq : (p + 1).Prime) : p = 2 := by + rcases hp.eq_two_or_odd' with h | ⟨r, hr⟩ + · exact h + · have h2 := hp.two_le + rcases hq.eq_one_or_self_of_dvd 2 ⟨r + 1, by omega⟩ with h | h <;> omega + +/-- If two primes `p < q` divide `n ≠ 6`, there are at least five change points. -/ +private lemma card_C_two {n p q : ℕ} (hn : 1 ≤ n) (hp : p.Prime) (hq : q.Prime) (hpq : p < q) + (hpn : p ∣ n) (hqn : q ∣ n) (h6 : n ≠ 6) : 5 ≤ #(C n) := by + have hp2 := hp.two_le + have hq3 : 3 ≤ q := by omega + obtain ⟨m, hnm⟩ : p * q ∣ n := + ((Nat.coprime_primes hp hq).2 hpq.ne).mul_dvd_of_dvd_of_dvd hpn hqn + have hm : 1 ≤ m := by + rcases Nat.eq_zero_or_pos m with h | h + · rw [h, mul_zero] at hnm; omega + · exact h + have hA : n / p = q * m := by rw [hnm, mul_assoc, Nat.mul_div_cancel_left _ hp.pos] + have hB : n / q = p * m := by + rw [hnm, mul_comm p q, mul_assoc, Nat.mul_div_cancel_left _ hq.pos] + have hnA : n = q * m * p := by rw [hnm]; ring + have gN := g_self hn + have gA : g n (q * m) = -1 := hA ▸ g_div_prime hn hp hpn + have gB : g n (p * m) = -1 := hB ▸ g_div_prime hn hq hqn + have hnot : ¬ (m = 1 ∧ q = p + 1) := by + rintro ⟨rfl, rfl⟩ + have := eq_two_of_succ hp hq + subst this + exact h6 (by rw [hnm]) + have hA3 : 3 ≤ q * m := le_trans hq3 (Nat.le_mul_of_pos_right q hm) + have hnA2 : 2 * (q * m) ≤ n := by rw [hnA, mul_comm _ p]; exact Nat.mul_le_mul_right _ hp2 + have hBA : p * m + 2 ≤ q * m := by + rcases Nat.eq_or_lt_of_le hm with h | h + · subst h + have : q ≠ p + 1 := fun e => hnot ⟨rfl, e⟩ + rw [mul_one, mul_one] + omega + · nlinarith + have hB1 : 2 ≤ p * m := le_trans hp2 (Nat.le_mul_of_pos_right p hm) + have gA1 : g n (q * m + 1) = 0 := by + apply g_eq_zero + intro hd + have h1 := consec (⟨p, hnA⟩ : q * m ∣ n) hd + rw [hnA] at h1 + have h2 := Nat.le_of_dvd hp.pos (Nat.dvd_of_mul_dvd_mul_left (by omega) h1) + have : q ≤ q * m := Nat.le_mul_of_pos_right q hm + omega + have gAm : g n (q * m - 1) = 0 := by + apply g_eq_zero + intro hd + obtain ⟨c, hc⟩ : ∃ c, q * m = c + 1 := ⟨q * m - 1, by omega⟩ + rw [hc, Nat.add_sub_cancel] at hd + have h1 := consec hd (⟨p, hc ▸ hnA⟩ : c + 1 ∣ n) + rw [hnA, hc, mul_comm c] at h1 + have h2 := Nat.dvd_of_mul_dvd_mul_left (by omega) h1 + rcases hp.eq_one_or_self_of_dvd c h2 with h3 | h3 + · omega + · apply hnot + have hm1 : m = 1 := by + by_contra hm1 + have : 2 ≤ m := by omega + nlinarith + subst hm1 + omega + have gn1 : g n (n - 1) = 0 := g_pred (by omega) + have gnp : g n (n + 1) = 0 := g_of_gt hn (by omega) + clear hA hB hnot hnA hnm + generalize q * m = A at * + generalize p * m = B at * + obtain ⟨j, hj1, hj2, hj3⟩ := ivt (g n) B (A - 1 - B) (by + rw [show B + (A - 1 - B) = A - 1 by omega, gB, gAm]; norm_num) + have hsub : ({j, A - 1, A, n - 1, n} : Finset ℕ) ⊆ C n := by + intro k hk + simp only [mem_insert, mem_singleton] at hk + rw [mem_C] + rcases hk with rfl | rfl | rfl | rfl | rfl + · exact ⟨by omega, by omega, hj3⟩ + · refine ⟨by omega, by omega, ?_⟩ + rw [show A - 1 + 1 = A by omega, gAm, gA]; norm_num + · refine ⟨by omega, by omega, ?_⟩ + rw [gA, gA1]; norm_num + · refine ⟨by omega, by omega, ?_⟩ + rw [show n - 1 + 1 = n by omega, gn1, gN]; norm_num + · refine ⟨by omega, le_rfl, ?_⟩ + rw [gN, gnp]; norm_num + have hcard : #({j, A - 1, A, n - 1, n} : Finset ℕ) = 5 := by + rw [card_insert_of_notMem (by simp only [mem_insert, mem_singleton]; omega), + card_insert_of_notMem (by simp only [mem_insert, mem_singleton]; omega), + card_insert_of_notMem (by simp only [mem_insert, mem_singleton]; omega), + card_insert_of_notMem (by simp only [mem_singleton]; omega), card_singleton] + exact hcard ▸ card_le_card hsub + +/-! ### The terms of A123710 -/ + +/-- `n` is a term of A123710 iff `n = 6` or `n` is a proper prime power. -/ +private lemma isTerm_iff (n : ℕ) : IsTerm n ↔ n = 6 ∨ ∃ p k, p.Prime ∧ 2 ≤ k ∧ n = p ^ k := by + rw [IsTerm] + constructor + · intro h + rcases Nat.lt_or_ge n 2 with hn | hn + · interval_cases n + · rw [A123709_eq_Rf] at h; exact absurd h (by decide +kernel) + · rw [A123709_eq_Rf] at h; exact absurd h (by decide +kernel) + · rw [A123709_eq_card] at h + obtain ⟨p, hpdef⟩ : ∃ p, p = n.minFac := ⟨_, rfl⟩ + have hp : p.Prime := hpdef ▸ Nat.minFac_prime (by omega) + have hpn : p ∣ n := hpdef ▸ Nat.minFac_dvd n + have hmin : ∀ q, q.Prime → q ∣ n → p ≤ q := fun q hq hqn => + hpdef ▸ Nat.minFac_le_of_dvd hq.two_le hqn + clear hpdef + by_cases hall : ∀ d, d.Prime → d ∣ n → d = p + · obtain ⟨e, he⟩ : ∃ e, n = p ^ e := + ⟨_, Nat.eq_prime_pow_of_unique_prime_dvd (by omega) (fun hd hdn => hall _ hd hdn)⟩ + rcases e with _ | _ | e + · rw [pow_zero] at he; omega + · rw [pow_one] at he + subst he + have := card_C_prime hp + omega + · exact Or.inr ⟨p, e + 2, hp, by omega, he⟩ + · push Not at hall + obtain ⟨q, hq, hqn, hqp⟩ := hall + have hpq : p < q := lt_of_le_of_ne (hmin q hq hqn) (Ne.symm hqp) + by_cases h6 : n = 6 + · exact Or.inl h6 + · have := card_C_two (by omega) hp hq hpq hpn hqn h6 + omega + · rintro (rfl | ⟨p, k, hp, hk, rfl⟩) + · rw [A123709_eq_Rf]; decide +kernel + · rw [A123709_eq_card, card_C_pp hp hk] + +/-- Two predicates that agree from `K` on and have the same count below `K` have the same counts +from `K` on. -/ +private lemma count_shift {p q : ℕ → Prop} [DecidablePred p] [DecidablePred q] {K : ℕ} + (hpq : ∀ x, K ≤ x → (p x ↔ q x)) (hc : Nat.count p K = Nat.count q K) : + ∀ b, Nat.count p (K + b) = Nat.count q (K + b) + | 0 => hc + | b + 1 => by + rw [← add_assoc, Nat.count_succ, Nat.count_succ, count_shift hpq hc b] + by_cases h : p (K + b) + · rw [if_pos h, if_pos ((hpq _ (by omega)).1 h)] + · rw [if_neg h, if_neg (fun h' => h ((hpq _ (by omega)).2 h'))] + +/-- Two predicates that agree from `K` on and have the same count `c` below `K` (the second one +holding infinitely often) have the same `nth` elements from index `c` on. -/ +private lemma nth_shift {p q : ℕ → Prop} [DecidablePred p] [DecidablePred q] {K : ℕ} + (hpq : ∀ x, K ≤ x → (p x ↔ q x)) (hc : Nat.count p K = Nat.count q K) + (hq : (Set.ofPred q).Infinite) (i : ℕ) : + Nat.nth p (Nat.count q K + i) = Nat.nth q (Nat.count q K + i) := by + obtain ⟨x, hx⟩ : ∃ x, x = Nat.nth q (Nat.count q K + i) := ⟨_, rfl⟩ + have hqx : q x := hx ▸ Nat.nth_mem_of_infinite hq _ + have hcx : Nat.count q x = Nat.count q K + i := hx ▸ Nat.count_nth_of_infinite hq _ + have hKx : K ≤ x := by + by_contra hlt + have h1 := Nat.count_monotone q (show x + 1 ≤ K by omega) + rw [Nat.count_succ, if_pos hqx] at h1 + omega + have hpx : p x := (hpq x hKx).2 hqx + have hcp : Nat.count p x = Nat.count q x := by + obtain ⟨b, hb⟩ := Nat.exists_eq_add_of_le hKx + rw [hb] + exact count_shift hpq hc b + rw [← hx, ← hcx, ← hcp, Nat.nth_count hpx] + +/-- Hasler's conjecture: from the third term on, A123710 lists the proper prime powers, i.e. +`a n = A025475 n` for `n > 2`. -/ +theorem result : statement := by + intro n hn + have hT : ∀ x, 7 ≤ x → (IsTerm x ↔ IsA025475 x) := by + intro x hx + rw [isTerm_iff, IsA025475] + constructor + · rintro (h | h) + · omega + · exact Or.inr h + · rintro (h | h) + · omega + · exact Or.inr h + have c1 : Nat.count IsTerm 7 = 2 := by decide +kernel + have c2 : Nat.count IsA025475 7 = 2 := by decide +kernel + have hinf : (Set.ofPred IsA025475).Infinite := + Set.infinite_of_injective_forall_mem (f := fun k : ℕ => 2 ^ (k + 2)) + (fun a b h => by + have := Nat.pow_right_injective (le_refl 2) h + simpa using this) + (fun k => Or.inr ⟨2, k + 2, Nat.prime_two, by omega, rfl⟩) + have := nth_shift hT (c1.trans c2.symm) hinf (n - 3) + rw [c2] at this + rw [a, A025475, show n - 1 = 2 + (n - 3) by omega] + exact this + +end Math0.Frontier.A123710 + +#math0_settles Math0.Frontier.A123710.result Math0.Statements.A123710.statement diff --git a/lean/Math0/Frontier/OEIS/A124526.lean b/lean/Math0/Frontier/OEIS/A124526.lean new file mode 100644 index 0000000..cd7caf0 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A124526.lean @@ -0,0 +1,682 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A124526 +import Math0.Audit + +/-! +# Hanna's conjecture A124418(n,k) = k! · A124526(n,k) (mixed-parity blocks) + +We prove Paul D. Hanna's conjecture (2006): the number of set partitions of `{1, …, n}` with +exactly `k` blocks containing both an odd and an even entry equals +`k! · A049020(⌊n/2⌋, k) · A049020(⌈n/2⌉, k)`, where `A049020(m,k) = ∑ᵢ S2(m,i) C(i,k)`. + +**Refined count.** Fix a predicate `c` on `ℕ` and a finset `s` with `o` elements satisfying `c` +and `e` elements satisfying `¬ c`. For a partition `P` of `s` let `nC P`, `nN P`, `nM P` be the +numbers of parts meeting `c`, meeting `¬ c`, and meeting both. We show that the number +`cnt s i j k` of partitions with `(nC, nN, nM) = (i, j, k)` is +`F(o,e,i,j,k) = S2(o,i) · S2(e,j) · C(i,k) · C(j,k) · k!`. + +**Induction by insertion.** Every partition of `insert a s` (`a ∉ s`) arises in exactly one +way from a partition `P` of `s`, either by adding the singleton `{a}` or by adding `a` to a part +`b` of `P` (`ins`, proved bijective using `recP`, which deletes `a`). If `c a`, the singleton +raises `nC` by one; adding `a` to a part meeting `c` changes nothing (`nC P` choices); adding +`a` to a part not meeting `c` raises `nC` and `nM` by one (`nN P - nM P` choices). This gives +`cnt(insert a s; i+1, j, k+1) = cnt(s; i, j, k+1) + (i+1) cnt(s; i+1, j, k+1) + + (j-k) cnt(s; i, j, k)` (and the degenerate cases), which `F` satisfies by +`S2(o+1,i+1) = (i+1) S2(o,i+1) + S2(o,i)`, Pascal's rule and `C(j,k+1)(k+1) = C(j,k)(j-k)`. +The case `¬ c a` follows by exchanging `c` and `¬ c`. + +**Specialisation.** Take `c = Odd`, `s = {1, …, n}` (so `o = ⌈n/2⌉`, `e = ⌊n/2⌋`) and sum over +`i, j ≤ n`: the double sum factors as `k! · A049020(⌈n/2⌉,k) · A049020(⌊n/2⌋,k)`. +-/ + +namespace Math0.Frontier.A124526 +open Math0.Statements.A124526 Finset + +/-! ### Inserting a new element into a partition -/ + +section Insert + +variable {a : ℕ} {t : Finset ℕ} + +/-- Parts of the partition obtained by inserting `a` into `P`: as a new singleton (`none`), or +into an existing part `b` (`some b`). -/ +private def insP (a : ℕ) (P : Finpartition t) : Option P.parts → Finset (Finset ℕ) + | none => insert {a} P.parts + | some b => insert (insert a b.1) (P.parts.erase b.1) + +/-- An element outside `t` lies in no part of a partition of `t`. -/ +private lemma notMem_part (ha : a ∉ t) (P : Finpartition t) {p : Finset ℕ} (hp : p ∈ P.parts) : + a ∉ p := fun h => ha (P.subset hp h) + +/-- Inserting `a ∉ t` into a partition of `t`, as a new singleton part or into an existing +part. -/ +private def ins (ha : a ∉ t) (P : Finpartition t) (x : Option P.parts) : + Finpartition (insert a t) := + Finpartition.ofExistsUnique (insP a P x) + (by + intro p hp + cases x with + | none => + simp only [insP, mem_insert] at hp + rcases hp with rfl | hp + · simp + · exact (P.subset hp).trans (subset_insert _ _) + | some b => + simp only [insP, mem_insert, mem_erase] at hp + rcases hp with rfl | ⟨-, hp⟩ + · exact insert_subset_insert _ (P.subset b.2) + · exact (P.subset hp).trans (subset_insert _ _)) + (by + intro y hy + rw [mem_insert] at hy + cases x with + | none => + rcases hy with hy | hy + · refine ⟨{a}, ⟨by simp [insP], by simp [hy]⟩, ?_⟩ + rintro p ⟨hp, hyp⟩ + simp only [insP, mem_insert] at hp + rcases hp with rfl | hp + · rfl + · exact absurd (hy ▸ hyp) (notMem_part ha P hp) + · refine ⟨P.part y, ⟨by simp [insP, hy], P.mem_part hy⟩, ?_⟩ + rintro p ⟨hp, hyp⟩ + simp only [insP, mem_insert] at hp + rcases hp with rfl | hp + · simp only [mem_singleton] at hyp; subst hyp; exact absurd hy ha + · exact (P.part_eq_of_mem hp hyp).symm + | some b => + rcases hy with hy | hy + · refine ⟨insert a b.1, ⟨by simp [insP], by simp [hy]⟩, ?_⟩ + rintro p ⟨hp, hyp⟩ + simp only [insP, mem_insert, mem_erase] at hp + rcases hp with rfl | ⟨-, hp⟩ + · rfl + · exact absurd (hy ▸ hyp) (notMem_part ha P hp) + · by_cases hyb : y ∈ b.1 + · refine ⟨insert a b.1, ⟨by simp [insP], mem_insert_of_mem hyb⟩, ?_⟩ + rintro p ⟨hp, hyp⟩ + simp only [insP, mem_insert, mem_erase] at hp + rcases hp with rfl | ⟨hpb, hp⟩ + · rfl + · exact absurd (P.eq_of_mem_parts hp b.2 hyp hyb) hpb + · have hq : P.part y ≠ b.1 := fun h => hyb (h ▸ P.mem_part hy) + refine ⟨P.part y, ⟨by simp [insP, hy, hq], P.mem_part hy⟩, ?_⟩ + rintro p ⟨hp, hyp⟩ + simp only [insP, mem_insert, mem_erase] at hp + rcases hp with rfl | ⟨-, hp⟩ + · rcases mem_insert.1 hyp with rfl | h + · exact absurd hy ha + · exact absurd h hyb + · exact (P.part_eq_of_mem hp hyp).symm) + (by + cases x with + | none => + simp only [insP, mem_insert, not_or] + exact ⟨fun h => by simpa using congrArg (a ∈ ·) h.symm, P.empty_notMem_parts⟩ + | some b => + simp only [insP, mem_insert, mem_erase, not_or, not_and] + exact ⟨fun h => by simpa using congrArg (a ∈ ·) h.symm, + fun _ => P.empty_notMem_parts⟩) + +/-- The parts of `ins ha P x`. -/ +private lemma ins_parts (ha : a ∉ t) (P : Finpartition t) (x : Option P.parts) : + (ins ha P x).parts = insP a P x := rfl + +/-- The parts of `P` can be recovered from those of `ins ha P x`: delete `a` from every part and +discard the empty set. -/ +private lemma rec_insP (ha : a ∉ t) (P : Finpartition t) (x : Option P.parts) : + ((insP a P x).image (·.erase a)).erase ∅ = P.parts := by + have himg : ∀ S ⊆ P.parts, S.image (·.erase a) = S := fun S hS => by + ext p + simp only [mem_image] + constructor + · rintro ⟨q, hq, rfl⟩ + rwa [erase_eq_of_notMem (notMem_part ha P (hS hq))] + · intro hp + exact ⟨p, hp, erase_eq_of_notMem (notMem_part ha P (hS hp))⟩ + cases x with + | none => + rw [insP, image_insert, himg _ subset_rfl, erase_singleton, erase_insert_eq_erase, + erase_eq_of_notMem P.empty_notMem_parts] + | some b => + rw [insP, image_insert, himg _ (erase_subset _ _), erase_insert (notMem_part ha P b.2), + insert_erase b.2] + exact erase_eq_of_notMem P.empty_notMem_parts + +/-- Inserting as a new singleton never gives the same parts as inserting into an old part. -/ +private lemma insP_none_ne_some (ha : a ∉ t) (P : Finpartition t) (b : P.parts) : + insP a P none ≠ insP a P (some b) := by + intro h + have h1 : ({a} : Finset ℕ) ∈ insP a P (some b) := by rw [← h]; simp [insP] + simp only [insP, mem_insert, mem_erase] at h1 + rcases h1 with h1 | ⟨-, h1⟩ + · obtain ⟨y, hy⟩ := P.nonempty_of_mem_parts b.2 + have hy' : y ∈ ({a} : Finset ℕ) := h1 ▸ mem_insert_of_mem hy + rw [mem_singleton] at hy' + subst hy' + exact notMem_part ha P b.2 hy + · exact notMem_part ha P h1 (mem_singleton_self a) + +/-- Insertion is injective on pairs (partition of `t`, choice). -/ +private lemma ins_injective (ha : a ∉ t) : + Function.Injective fun σ : (Σ P : Finpartition t, Option P.parts) => ins ha σ.1 σ.2 := by + rintro ⟨P, x⟩ ⟨P', x'⟩ h + have hparts : insP a P x = insP a P' x' := congrArg Finpartition.parts h + have hPP : P = P' := Finpartition.ext (by rw [← rec_insP ha P x, hparts, rec_insP ha P' x']) + subst hPP + cases x with + | none => + cases x' with + | none => rfl + | some b' => exact absurd hparts (insP_none_ne_some ha P b') + | some b => + cases x' with + | none => exact absurd hparts.symm (insP_none_ne_some ha P b) + | some b' => + have h1 : insert a b.1 ∈ insP a P (some b') := by rw [← hparts]; simp [insP] + simp only [insP, mem_insert, mem_erase] at h1 + rcases h1 with h1 | ⟨-, h1⟩ + · have h2 := congrArg (·.erase a) h1 + simp only [erase_insert (notMem_part ha P b.2), + erase_insert (notMem_part ha P b'.2)] at h2 + obtain rfl : b = b' := Subtype.ext h2 + rfl + · exact absurd (mem_insert_self a b.1) (notMem_part ha P h1) + +/-- Deleting `a` from a partition of `insert a t`. -/ +private def recP (ha : a ∉ t) (R : Finpartition (insert a t)) : Finpartition t := + Finpartition.ofExistsUnique ((R.parts.image (·.erase a)).erase ∅) + (by + intro p hp + simp only [mem_erase, mem_image] at hp + obtain ⟨-, q, hq, rfl⟩ := hp + intro y hy + rw [mem_erase] at hy + exact (mem_insert.1 (R.subset hq hy.2)).resolve_left hy.1) + (by + intro y hy + have hy' : y ∈ insert a t := mem_insert_of_mem hy + have hya : y ≠ a := fun h => ha (h ▸ hy) + have hmem : y ∈ (R.part y).erase a := mem_erase.2 ⟨hya, R.mem_part hy'⟩ + refine ⟨(R.part y).erase a, ⟨?_, hmem⟩, ?_⟩ + · simp only [mem_erase, mem_image] + exact ⟨ne_empty_of_mem hmem, _, R.part_mem.2 hy', rfl⟩ + · rintro p ⟨hp, hyp⟩ + simp only [mem_erase, mem_image] at hp + obtain ⟨-, q, hq, rfl⟩ := hp + rw [R.part_eq_of_mem hq (mem_of_mem_erase hyp)]) + (by simp) + +/-- The parts of `recP ha R`. -/ +private lemma recP_parts (ha : a ∉ t) (R : Finpartition (insert a t)) : + (recP ha R).parts = (R.parts.image (·.erase a)).erase ∅ := rfl + +/-- Every partition of `insert a t` arises by insertion. -/ +private lemma ins_surjective (ha : a ∉ t) : + Function.Surjective fun σ : (Σ P : Finpartition t, Option P.parts) => ins ha σ.1 σ.2 := by + intro R + have haR : a ∈ insert a t := mem_insert_self a t + have hBR : R.part a ∈ R.parts := R.part_mem.2 haR + have haB : a ∈ R.part a := R.mem_part haR + by_cases hBa : R.part a = {a} + · refine ⟨⟨recP ha R, none⟩, ?_⟩ + apply Finpartition.ext + show insP a (recP ha R) none = R.parts + ext p + simp only [insP, recP_parts, mem_insert, mem_erase, mem_image] + constructor + · rintro (rfl | ⟨hp0, q, hq, rfl⟩) + · rw [← hBa]; exact hBR + · by_cases haq : a ∈ q + · have hqB := R.eq_of_mem_parts hq hBR haq haB + rw [hqB, hBa] at hp0 + simp at hp0 + · rwa [erase_eq_of_notMem haq] + · intro hp + by_cases hap : a ∈ p + · left; rw [← hBa]; exact R.eq_of_mem_parts hp hBR hap haB + · right; exact ⟨R.ne_empty hp, p, hp, erase_eq_of_notMem hap⟩ + · have hb0 : (R.part a).erase a ≠ ∅ := by + rw [Ne, erase_eq_empty_iff, not_or] + exact ⟨ne_empty_of_mem haB, hBa⟩ + have hb : (R.part a).erase a ∈ (recP ha R).parts := by + rw [recP_parts, mem_erase, mem_image] + exact ⟨hb0, _, hBR, rfl⟩ + refine ⟨⟨recP ha R, some ⟨_, hb⟩⟩, ?_⟩ + apply Finpartition.ext + show insP a (recP ha R) (some ⟨_, hb⟩) = R.parts + ext p + simp only [insP, recP_parts, insert_erase haB, mem_insert, mem_erase, mem_image] + constructor + · rintro (rfl | ⟨hpb, hp0, q, hq, rfl⟩) + · exact hBR + · by_cases haq : a ∈ q + · exact (hpb (by rw [R.eq_of_mem_parts hq hBR haq haB])).elim + · rwa [erase_eq_of_notMem haq] + · intro hp + by_cases hap : a ∈ p + · left; exact R.eq_of_mem_parts hp hBR hap haB + · right + refine ⟨?_, R.ne_empty hp, p, hp, erase_eq_of_notMem hap⟩ + intro hpe + obtain ⟨y, hy⟩ := nonempty_iff_ne_empty.2 hb0 + have hyp : y ∈ p := by rw [hpe]; exact hy + have hpB := R.eq_of_mem_parts hp hBR hyp (mem_of_mem_erase hy) + rw [hpB] at hap + exact hap haB + +/-- Counting partitions of `insert a t` via insertion. -/ +private lemma card_filter_ins (ha : a ∉ t) (f : Finpartition (insert a t) → Prop) + [DecidablePred f] : + #(univ.filter f) = + ∑ P : Finpartition t, #(univ.filter fun x : Option P.parts => f (ins ha P x)) := by + rw [← card_sigma] + symm + refine card_bij (fun σ _ => ins ha σ.1 σ.2) ?_ ?_ ?_ + · intro σ hσ + simp only [mem_sigma, mem_filter, mem_univ, true_and] at hσ + simpa using hσ + · intro σ₁ _ σ₂ _ h + exact ins_injective ha h + · intro R hR + obtain ⟨σ, hσ⟩ := ins_surjective ha R + refine ⟨σ, ?_, hσ⟩ + simp only [mem_sigma, mem_filter, mem_univ, true_and] + simp only at hσ + rw [hσ] + simpa using hR + +/-- Filtered cardinality of the parts after inserting as a singleton. -/ +private lemma card_filter_insP_none (ha : a ∉ t) (P : Finpartition t) (p : Finset ℕ → Prop) + [DecidablePred p] : + #((insP a P none).filter p) = #(P.parts.filter p) + if p {a} then 1 else 0 := by + have hn : ({a} : Finset ℕ) ∉ P.parts := fun h => notMem_part ha P h (mem_singleton_self a) + rw [insP, filter_insert] + split_ifs with h + · rw [card_insert_of_notMem (fun h' => hn (mem_filter.1 h').1)] + · rw [add_zero] + +/-- Filtered cardinality of the parts after inserting into the part `b`. -/ +private lemma card_filter_insP_some (ha : a ∉ t) (P : Finpartition t) (b : P.parts) + (p : Finset ℕ → Prop) [DecidablePred p] : + #((insP a P (some b)).filter p) + (if p b.1 then 1 else 0) = + #(P.parts.filter p) + if p (insert a b.1) then 1 else 0 := by + have hn : insert a b.1 ∉ (P.parts.filter p).erase b.1 := fun h => + notMem_part ha P (mem_filter.1 (mem_of_mem_erase h)).1 (mem_insert_self a b.1) + rw [insP, filter_insert, filter_erase] + by_cases h1 : p b.1 <;> by_cases h2 : p (insert a b.1) + · rw [if_pos h1, if_pos h2, if_pos h2, card_insert_of_notMem hn, + card_erase_add_one (mem_filter.2 ⟨b.2, h1⟩)] + · rw [if_pos h1, if_neg h2, if_neg h2, card_erase_add_one (mem_filter.2 ⟨b.2, h1⟩), add_zero] + · have hb : b.1 ∉ P.parts.filter p := fun h => h1 (mem_filter.1 h).2 + rw [if_neg h1, if_pos h2, if_pos h2, erase_eq_of_notMem hb, + card_insert_of_notMem (by rwa [erase_eq_of_notMem hb] at hn)] + · have hb : b.1 ∉ P.parts.filter p := fun h => h1 (mem_filter.1 h).2 + rw [if_neg h1, if_neg h2, if_neg h2, erase_eq_of_notMem hb] + +/-- If `p` does not distinguish `b` from `insert a b`, the filtered count is unchanged. -/ +private lemma card_filter_insP_some_eq (ha : a ∉ t) (P : Finpartition t) (b : P.parts) + (p : Finset ℕ → Prop) [DecidablePred p] (h : p (insert a b.1) ↔ p b.1) : + #((insP a P (some b)).filter p) = #(P.parts.filter p) := by + have := card_filter_insP_some ha P b p + by_cases hb : p b.1 + · rw [if_pos hb, if_pos (h.2 hb)] at this; omega + · rw [if_neg hb, if_neg (mt h.1 hb)] at this; omega + +/-- If `p` holds for `insert a b` but not for `b`, the filtered count goes up by one. -/ +private lemma card_filter_insP_some_succ (ha : a ∉ t) (P : Finpartition t) (b : P.parts) + (p : Finset ℕ → Prop) [DecidablePred p] (h1 : p (insert a b.1)) (h2 : ¬ p b.1) : + #((insP a P (some b)).filter p) = #(P.parts.filter p) + 1 := by + have := card_filter_insP_some ha P b p + rw [if_pos h1, if_neg h2] at this; omega + +end Insert + +/-! ### Statistics of a partition relative to a predicate `c` -/ + +section Stats + +variable (c : ℕ → Prop) [DecidablePred c] + +/-- Number of parts meeting `c`. -/ +private def nC {s : Finset ℕ} (P : Finpartition s) : ℕ := #(P.parts.filter fun b => ∃ x ∈ b, c x) + +/-- Number of parts meeting `¬ c`. -/ +private def nN {s : Finset ℕ} (P : Finpartition s) : ℕ := + #(P.parts.filter fun b => ∃ x ∈ b, ¬ c x) + +/-- Number of parts meeting both `c` and `¬ c` (mixed parts). -/ +private def nM {s : Finset ℕ} (P : Finpartition s) : ℕ := + #(P.parts.filter fun b => (∃ x ∈ b, c x) ∧ ∃ x ∈ b, ¬ c x) + +/-- The number of partitions of `s` with `i` parts meeting `c`, `j` parts meeting `¬ c` and `k` +mixed parts. -/ +private def cnt (s : Finset ℕ) (i j k : ℕ) : ℕ := + #(univ.filter fun P : Finpartition s => nC c P = i ∧ nN c P = j ∧ nM c P = k) + +/-- The closed form `S(o,i) S(e,j) C(i,k) C(j,k) k!` of `cnt`. -/ +private def F (o e i j k : ℕ) : ℕ := + Nat.stirlingSecond o i * Nat.stirlingSecond e j * (i.choose k * j.choose k * k.factorial) + +/-- Parts not meeting `c` are exactly the non-mixed parts meeting `¬ c`. -/ +private lemma card_filter_not_C {s : Finset ℕ} (P : Finpartition s) : + #(P.parts.filter fun b => ¬ ∃ x ∈ b, c x) = nN c P - nM c P := by + have h := card_filter_add_card_filter_not (s := P.parts.filter fun b => ∃ x ∈ b, ¬ c x) + (fun b => ∃ x ∈ b, c x) + rw [filter_filter, filter_filter] at h + have e1 : (P.parts.filter fun b => (∃ x ∈ b, ¬ c x) ∧ ∃ x ∈ b, c x) = + P.parts.filter fun b => (∃ x ∈ b, c x) ∧ ∃ x ∈ b, ¬ c x := + filter_congr fun b _ => and_comm + have e2 : (P.parts.filter fun b => (∃ x ∈ b, ¬ c x) ∧ ¬ ∃ x ∈ b, c x) = + P.parts.filter fun b => ¬ ∃ x ∈ b, c x := by + refine filter_congr fun b hb => ⟨fun h => h.2, fun h => ⟨?_, h⟩⟩ + obtain ⟨y, hy⟩ := P.nonempty_of_mem_parts hb + exact ⟨y, hy, fun hy' => h ⟨y, hy, hy'⟩⟩ + rw [e1, e2] at h + unfold nN nM + omega + +variable {c} +variable {a : ℕ} {t : Finset ℕ} + +/-- Statistics after inserting `a` (with `c a`) as a singleton. -/ +private lemma stats_none (ha : a ∉ t) (hc : c a) (P : Finpartition t) : + nC c (ins ha P none) = nC c P + 1 ∧ nN c (ins ha P none) = nN c P ∧ + nM c (ins ha P none) = nM c P := by + simp only [nC, nN, nM, ins_parts, card_filter_insP_none ha] + simp [hc] + +omit [DecidablePred c] in +/-- `∃ x ∈ insert a b, ¬ c x ↔ ∃ x ∈ b, ¬ c x` when `c a`. -/ +private lemma exists_not_insert (hc : c a) (b : Finset ℕ) : + (∃ x ∈ insert a b, ¬ c x) ↔ ∃ x ∈ b, ¬ c x := by + constructor + · rintro ⟨x, hx, hcx⟩ + rcases mem_insert.1 hx with rfl | hx + · exact absurd hc hcx + · exact ⟨x, hx, hcx⟩ + · rintro ⟨x, hx, hcx⟩ + exact ⟨x, mem_insert_of_mem hx, hcx⟩ + +/-- Statistics after inserting `a` (with `c a`) into a part meeting `c`. -/ +private lemma stats_some_C (ha : a ∉ t) (hc : c a) (P : Finpartition t) (b : P.parts) + (hb : ∃ x ∈ b.1, c x) : + nC c (ins ha P (some b)) = nC c P ∧ nN c (ins ha P (some b)) = nN c P ∧ + nM c (ins ha P (some b)) = nM c P := by + have e1 : ∃ x ∈ insert a b.1, c x := ⟨a, mem_insert_self _ _, hc⟩ + simp only [nC, nN, nM, ins_parts] + refine ⟨?_, ?_, ?_⟩ + · exact card_filter_insP_some_eq ha P b (fun b => ∃ x ∈ b, c x) (iff_of_true e1 hb) + · exact card_filter_insP_some_eq ha P b (fun b => ∃ x ∈ b, ¬ c x) (exists_not_insert hc b.1) + · exact card_filter_insP_some_eq ha P b (fun b => (∃ x ∈ b, c x) ∧ ∃ x ∈ b, ¬ c x) + (and_congr (iff_of_true e1 hb) (exists_not_insert hc b.1)) + +/-- Statistics after inserting `a` (with `c a`) into a part not meeting `c`. -/ +private lemma stats_some_N (ha : a ∉ t) (hc : c a) (P : Finpartition t) (b : P.parts) + (hb : ¬ ∃ x ∈ b.1, c x) : + nC c (ins ha P (some b)) = nC c P + 1 ∧ nN c (ins ha P (some b)) = nN c P ∧ + nM c (ins ha P (some b)) = nM c P + 1 := by + have e1 : ∃ x ∈ insert a b.1, c x := ⟨a, mem_insert_self _ _, hc⟩ + have hN : ∃ x ∈ b.1, ¬ c x := by + obtain ⟨y, hy⟩ := P.nonempty_of_mem_parts b.2 + exact ⟨y, hy, fun hy' => hb ⟨y, hy, hy'⟩⟩ + simp only [nC, nN, nM, ins_parts] + refine ⟨?_, ?_, ?_⟩ + · exact card_filter_insP_some_succ ha P b (fun b => ∃ x ∈ b, c x) e1 hb + · exact card_filter_insP_some_eq ha P b (fun b => ∃ x ∈ b, ¬ c x) (exists_not_insert hc b.1) + · exact card_filter_insP_some_succ ha P b (fun b => (∃ x ∈ b, c x) ∧ ∃ x ∈ b, ¬ c x) + ⟨e1, (exists_not_insert hc b.1).2 hN⟩ (fun h => hb h.1) + +/-- The number of ways to insert `a` (with `c a`) into `P` reaching given statistics. -/ +private lemma card_choices (ha : a ∉ t) (hc : c a) (P : Finpartition t) (i j k : ℕ) : + #(univ.filter fun x : Option P.parts => + nC c (ins ha P x) = i ∧ nN c (ins ha P x) = j ∧ nM c (ins ha P x) = k) = + (if nC c P + 1 = i ∧ nN c P = j ∧ nM c P = k then 1 else 0) + + (nC c P * (if nC c P = i ∧ nN c P = j ∧ nM c P = k then 1 else 0) + + (nN c P - nM c P) * (if nC c P + 1 = i ∧ nN c P = j ∧ nM c P + 1 = k then 1 else 0)) := by + rw [card_filter, Fintype.sum_option] + obtain ⟨h1, h2, h3⟩ := stats_none ha hc P + rw [h1, h2, h3] + congr 1 + let g : Finset ℕ → ℕ := fun b => if ∃ x ∈ b, c x then + (if nC c P = i ∧ nN c P = j ∧ nM c P = k then 1 else 0) else + (if nC c P + 1 = i ∧ nN c P = j ∧ nM c P + 1 = k then 1 else 0) + have hsum : ∀ b : P.parts, (if nC c (ins ha P (some b)) = i ∧ nN c (ins ha P (some b)) = j ∧ + nM c (ins ha P (some b)) = k then 1 else 0) = g b.1 := by + intro b + by_cases hb : ∃ x ∈ b.1, c x + · obtain ⟨e1, e2, e3⟩ := stats_some_C ha hc P b hb + simp only [g, if_pos hb, e1, e2, e3] + · obtain ⟨e1, e2, e3⟩ := stats_some_N ha hc P b hb + simp only [g, if_neg hb, e1, e2, e3] + rw [Fintype.sum_congr _ _ hsum, Finset.sum_coe_sort (s := P.parts) (f := g)] + simp only [g] + rw [sum_ite, sum_const, sum_const, smul_eq_mul, smul_eq_mul, card_filter_not_C c P] + rfl + +/-- The insertion recurrence, before evaluating the sums. -/ +private lemma cnt_insert (ha : a ∉ t) (hc : c a) (i j k : ℕ) : + cnt c (insert a t) i j k = + ∑ P : Finpartition t, (if nC c P + 1 = i ∧ nN c P = j ∧ nM c P = k then 1 else 0) + + (∑ P : Finpartition t, nC c P * (if nC c P = i ∧ nN c P = j ∧ nM c P = k then 1 else 0) + + ∑ P : Finpartition t, (nN c P - nM c P) * + (if nC c P + 1 = i ∧ nN c P = j ∧ nM c P + 1 = k then 1 else 0)) := by + rw [cnt, card_filter_ins ha, ← sum_add_distrib, ← sum_add_distrib] + exact sum_congr rfl fun P _ => card_choices ha hc P i j k + +/-- First sum of the recurrence, `i = 0`. -/ +private lemma sum1_zero (j k : ℕ) : + ∑ P : Finpartition t, (if nC c P + 1 = 0 ∧ nN c P = j ∧ nM c P = k then 1 else 0) = 0 := + sum_eq_zero fun _ _ => if_neg fun h => Nat.succ_ne_zero _ h.1 + +/-- First sum of the recurrence. -/ +private lemma sum1_succ (i j k : ℕ) : + ∑ P : Finpartition t, (if nC c P + 1 = i + 1 ∧ nN c P = j ∧ nM c P = k then 1 else 0) = + cnt c t i j k := by + rw [cnt, card_filter] + exact sum_congr rfl fun P _ => by simp only [Nat.add_right_cancel_iff] + +/-- Second sum of the recurrence. -/ +private lemma sum2 (i j k : ℕ) : + ∑ P : Finpartition t, nC c P * (if nC c P = i ∧ nN c P = j ∧ nM c P = k then 1 else 0) = + i * cnt c t i j k := by + rw [cnt, card_filter, mul_sum] + refine sum_congr rfl fun P _ => ?_ + split_ifs with h + · rw [h.1] + · simp + +/-- Third sum of the recurrence, `i = 0`. -/ +private lemma sum3_zero_left (j k : ℕ) : + ∑ P : Finpartition t, (nN c P - nM c P) * + (if nC c P + 1 = 0 ∧ nN c P = j ∧ nM c P + 1 = k then 1 else 0) = 0 := + sum_eq_zero fun P _ => by rw [if_neg fun h => Nat.succ_ne_zero _ h.1, mul_zero] + +/-- Third sum of the recurrence, `k = 0`. -/ +private lemma sum3_zero_right (i j : ℕ) : + ∑ P : Finpartition t, (nN c P - nM c P) * + (if nC c P + 1 = i ∧ nN c P = j ∧ nM c P + 1 = 0 then 1 else 0) = 0 := + sum_eq_zero fun P _ => by rw [if_neg fun h => Nat.succ_ne_zero _ h.2.2, mul_zero] + +/-- Third sum of the recurrence. -/ +private lemma sum3_succ (i j k : ℕ) : + ∑ P : Finpartition t, (nN c P - nM c P) * + (if nC c P + 1 = i + 1 ∧ nN c P = j ∧ nM c P + 1 = k + 1 then 1 else 0) = + (j - k) * cnt c t i j k := by + rw [cnt, card_filter, mul_sum] + refine sum_congr rfl fun P _ => ?_ + simp only [Nat.add_right_cancel_iff] + split_ifs with h + · rw [h.2.1, h.2.2] + · simp + +/-- The insertion step: if the closed form holds for `t`, it holds for `insert a t` (`c a`). -/ +private lemma step (ha : a ∉ t) (hc : c a) + (IH : ∀ i j k, cnt c t i j k = F #(t.filter c) #(t.filter fun x => ¬ c x) i j k) + (i j k : ℕ) : + cnt c (insert a t) i j k = F (#(t.filter c) + 1) #(t.filter fun x => ¬ c x) i j k := by + rw [cnt_insert ha hc] + rcases i with _ | i + · rw [sum1_zero, sum2, sum3_zero_left, F, Nat.stirlingSecond_succ_zero] + simp + · rw [sum1_succ, sum2] + rcases k with _ | k + · rw [sum3_zero_right, IH, IH] + simp only [F, Nat.stirlingSecond_succ_succ, Nat.choose_zero_right, Nat.factorial_zero] + ring + · rw [sum3_succ, IH, IH, IH] + simp only [F, Nat.stirlingSecond_succ_succ, Nat.choose_succ_succ', Nat.factorial_succ] + have hj := Nat.choose_succ_right_eq j k + generalize j - k = d at hj ⊢ + generalize #(t.filter c) = o + generalize #(t.filter fun x => ¬ c x) = e + zify at hj ⊢ + linear_combination (-((Nat.stirlingSecond o i : ℤ) * (Nat.stirlingSecond e j : ℤ) * + (i.choose k : ℤ) * (k.factorial : ℤ))) * hj + +variable (c) + +/-- Swapping `c` and `¬ c` swaps the first two statistics. -/ +private lemma cnt_not (s : Finset ℕ) (i j k : ℕ) : + cnt (fun x => ¬ c x) s i j k = cnt c s j i k := by + unfold cnt + congr 1 + apply filter_congr + intro P _ + have e1 : nC (fun x => ¬ c x) P = nN c P := rfl + have e2 : nN (fun x => ¬ c x) P = nC c P := by + unfold nN nC + congr 1 + exact filter_congr fun b _ => by simp only [not_not] + have e3 : nM (fun x => ¬ c x) P = nM c P := by + unfold nM + congr 1 + exact filter_congr fun b _ => by simp only [not_not]; exact and_comm + rw [e1, e2, e3] + tauto + +/-- `F` is symmetric. -/ +private lemma F_comm (o e i j k : ℕ) : F o e i j k = F e o j i k := by + unfold F; ring + +/-- The refined count: `cnt c s i j k = S(o,i) S(e,j) C(i,k) C(j,k) k!`, where `o`, `e` are the +numbers of elements of `s` satisfying `c`, `¬ c`. -/ +private theorem cnt_eq (s : Finset ℕ) : + ∀ i j k, cnt c s i j k = F #(s.filter c) #(s.filter fun x => ¬ c x) i j k := by + induction s using Finset.induction_on with + | empty => + intro i j k + have hP : ∀ P : Finpartition (∅ : Finset ℕ), P.parts = ∅ := fun P => by + ext b + simp only [notMem_empty, iff_false] + intro hb + exact P.ne_empty hb (subset_empty.1 (P.subset hb)) + have hcard : Fintype.card (Finpartition (∅ : Finset ℕ)) = 1 := by + rw [Fintype.card_eq_one_iff] + exact ⟨⊥, fun P => Finpartition.ext (by rw [hP, hP])⟩ + simp only [cnt, nC, nN, nM, hP, filter_empty, card_empty] + rcases i with _ | i <;> rcases j with _ | j <;> rcases k with _ | k <;> + simp [F, hcard, Nat.stirlingSecond_zero_succ] + | insert a t ha IH => + intro i j k + by_cases hc : c a + · have h1 : #((insert a t).filter c) = #(t.filter c) + 1 := by + rw [filter_insert, if_pos hc, card_insert_of_notMem (fun h => ha (mem_filter.1 h).1)] + have h2 : #((insert a t).filter fun x => ¬ c x) = #(t.filter fun x => ¬ c x) := by + rw [filter_insert, if_neg (not_not.2 hc)] + rw [h1, h2] + exact step ha hc IH i j k + · have IH' : ∀ i j k, cnt (fun x => ¬ c x) t i j k = + F #(t.filter fun x => ¬ c x) #(t.filter fun x => ¬ ¬ c x) i j k := by + intro i j k + rw [cnt_not, IH, F_comm] + congr 2 + exact filter_congr fun x _ => not_not.symm + have h1 : #((insert a t).filter c) = #(t.filter c) := by + rw [filter_insert, if_neg hc] + have h2 : #((insert a t).filter fun x => ¬ c x) = #(t.filter fun x => ¬ c x) + 1 := by + rw [filter_insert, if_pos hc, card_insert_of_notMem (fun h => ha (mem_filter.1 h).1)] + have h3 := step (c := fun x => ¬ c x) ha hc IH' j i k + rw [cnt_not] at h3 + rw [h3, h1, h2, F_comm] + congr 2 + exact filter_congr fun x _ => not_not + +end Stats + +/-! ### Specialisation to `{1, …, n}` and parity -/ + +/-- `{1, …, n}` has `⌈n/2⌉` odd and `⌊n/2⌋` even elements. -/ +private lemma card_odd (n : ℕ) : + #((Icc 1 n).filter Odd) = (n + 1) / 2 ∧ #((Icc 1 n).filter fun x => ¬ Odd x) = n / 2 := by + induction n with + | zero => simp + | succ n ih => + rw [← Finset.insert_Icc_right_eq_Icc_add_one (by omega : 1 ≤ n + 1), filter_insert, + filter_insert] + have hn : n + 1 ∉ Icc 1 n := by simp + by_cases h : Odd (n + 1) + · rw [if_pos h, if_neg (not_not.2 h), + card_insert_of_notMem (fun h' => hn (mem_filter.1 h').1)] + obtain ⟨m, hm⟩ := h + omega + · rw [if_neg h, if_pos h, card_insert_of_notMem (fun h' => hn (mem_filter.1 h').1)] + rw [Nat.not_odd_iff_even] at h + obtain ⟨m, hm⟩ := h + omega + +/-- Summing `S(m,i) C(i,k)` over a longer range gives `A049020 m k`. -/ +private lemma sum_eq_A049020 {m N : ℕ} (h : m ≤ N) (k : ℕ) : + ∑ i ∈ range (N + 1), Nat.stirlingSecond m i * i.choose k = A049020 m k := by + unfold A049020 + symm + apply sum_subset (range_subset_range.2 (by omega)) + intro i hi hi' + rw [mem_range] at hi' + rw [Nat.stirlingSecond_eq_zero_of_lt (by omega), zero_mul] + +/-- Hanna's conjecture: `A124418(n,k) = k! · A049020(⌊n/2⌋,k) · A049020(⌈n/2⌉,k)`. -/ +theorem result : statement := by + intro n k _ + have hmix : ∀ P : Finpartition (Icc 1 n), #(P.parts.filter IsMixed) = nM Odd P := fun P => by + unfold nM + congr 1 + exact filter_congr fun b _ => by simp only [IsMixed, Nat.not_odd_iff_even] + have hle : ∀ (P : Finpartition (Icc 1 n)) (p : Finset ℕ → Prop) [DecidablePred p], + #(P.parts.filter p) < n + 1 := fun P p _ => by + have h1 := card_filter_le P.parts p + have h2 := P.card_parts_le_card + simp only [Nat.card_Icc] at h2 + omega + have hfib : A124418 n k = ∑ ij ∈ range (n + 1) ×ˢ range (n + 1), + cnt Odd (Icc 1 n) ij.1 ij.2 k := by + rw [A124418] + simp only [hmix] + rw [card_eq_sum_card_fiberwise (f := fun P => (nC Odd P, nN Odd P)) + (t := range (n + 1) ×ˢ range (n + 1))] + · refine sum_congr rfl fun ij _ => ?_ + rw [cnt, filter_filter] + congr 1 + apply filter_congr + intro P _ + simp only [Prod.ext_iff] + tauto + · intro P _ + simp only [mem_coe, mem_product, mem_range] + exact ⟨hle P _, hle P _⟩ + rw [hfib, sum_product] + obtain ⟨ho, he⟩ := card_odd n + simp only [cnt_eq Odd (Icc 1 n), ho, he, F] + rw [T, ← sum_eq_A049020 (by omega : n / 2 ≤ n) k, + ← sum_eq_A049020 (by omega : (n + 1) / 2 ≤ n) k, sum_mul_sum, mul_sum] + rw [sum_comm] + refine sum_congr rfl fun j _ => ?_ + rw [mul_sum] + refine sum_congr rfl fun i _ => ?_ + ring + +end Math0.Frontier.A124526 + +#math0_settles Math0.Frontier.A124526.result Math0.Statements.A124526.statement diff --git a/lean/Math0/Frontier/OEIS/A126127.lean b/lean/Math0/Frontier/OEIS/A126127.lean new file mode 100644 index 0000000..19a9d53 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A126127.lean @@ -0,0 +1,363 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A126127 +import Math0.Audit + +/-! +# A126127: the conjectured g.f. of the inverse square of A061554 holds + +We prove Robert Israel's conjecture +`∑_{n,k} T(n,k) x^n y^k = (1-x)(1-x+x^2)/(1-xy+3x^2-x^3y+x^4)`, where `T = M^(-2)` and +`M(n,k) = binomial(n, floor((n-k)/2))` (A061554). + +* The inverse `N = M⁻¹` is the Riordan array `((1-x)/(1+x^2), x/(1+x^2))`. We define it by its + recurrence `N(n,k) + N(n-2,k) = N(n-1,k-1) + [k = 0]([n = 0] - [n = 1])` and check + `M · N = 1` with the production matrix of `M`: the rows of `M` satisfy + `M(n+1,k) = M(n,k-1) + M(n,k+1)` (`k ≥ 1`) and `M(n+1,0) = M(n,0) + M(n,1)` (Pascal's rule), + and the same recurrence of `N` gives `N(i+1,k) + N(i-1,k) = N(i,k-1)` (with `N(-1,k)` read as + `N(0,k)`), so row `n+1` of `M · N` is row `n` shifted one step right. +* With `W(m,k) = ∑_j N(m,j+1) N(j,k)`, the recurrence of `N` in both factors of + `T = N · N` gives `T(n+2,k) + T(n,k) = T(n+1,k-1) - W(n+1,k) - [k = 0] N(n+1,0)` and + `W(m+2,k) + W(m,k) = T(m+1,k)`. Adding the first identity at `n` and `n+2` and using the + second gives `T(n+4,k) + 3T(n+2,k) + T(n,k) = T(n+3,k-1) + T(n+1,k-1)`, which is the + denominator; rows `0..3` give the numerator `1 - 2x + 2x^2 - x^3`. +-/ + +namespace Math0.Frontier.A126127 +open Math0.Statements.A126127 +open Finset + +/-- The explicit inverse of `M`, given by the recurrence +`N(n,k) + N(n-2,k) = N(n-1,k-1) + [k = 0]([n = 0] - [n = 1])`. -/ +private def N : ℕ → ℕ → ℤ + | 0, k => if k = 0 then 1 else 0 + | 1, 0 => -1 + | 1, k + 1 => N 0 k + | n + 2, 0 => -N n 0 + | n + 2, k + 1 => N (n + 1) k - N n (k + 1) + +/-- Column-zero recurrence for `N`. -/ +private theorem N_rec0 (n : ℕ) : N (n + 2) 0 + N n 0 = 0 := by + simp [N] + +/-- Main recurrence for `N`. -/ +private theorem N_rec (n k : ℕ) : N (n + 2) (k + 1) + N n (k + 1) = N (n + 1) k := by + simp [N] + +/-- `N` is lower triangular. -/ +private theorem N_eq_zero : ∀ n k, n < k → N n k = 0 + | 0, k, h => by simp [N]; omega + | 1, 0, h => by omega + | 1, k + 1, h => by simp [N]; omega + | n + 2, 0, h => by omega + | n + 2, k + 1, h => by + simp only [N] + rw [N_eq_zero (n + 1) k (by omega), N_eq_zero n (k + 1) (by omega)] + simp + +/-- Row recurrence of `M` (columns `≥ 1`). -/ +private theorem M_succ_succ (n k : ℕ) : M (n + 1) (k + 1) = M n k + M n (k + 2) := by + unfold M + by_cases hk : k ≤ n + · rw [if_pos (by omega), if_pos hk] + have e1 : (n + 1 - (k + 1)) / 2 = (n - k) / 2 := by omega + rw [e1] + by_cases hk2 : k + 2 ≤ n + · rw [if_pos hk2] + have e2 : (n - k) / 2 = (n - (k + 2)) / 2 + 1 := by omega + rw [e2, Nat.choose_succ_succ] + push_cast + ring + · rw [if_neg hk2] + have e2 : (n - k) / 2 = 0 := by omega + rw [e2] + simp + · rw [if_neg (by omega), if_neg hk, if_neg (by omega)] + simp + +/-- Row recurrence of `M` (column `0`). -/ +private theorem M_succ_zero (n : ℕ) : M (n + 1) 0 = M n 0 + M n 1 := by + unfold M + rcases Nat.even_or_odd' n with ⟨a, rfl | rfl⟩ + · rcases a with _ | a + · simp + · rw [if_pos (by omega), if_pos (by omega), if_pos (by omega)] + have e1 : (2 * (a + 1) + 1 - 0) / 2 = a + 1 := by omega + have e2 : (2 * (a + 1) - 0) / 2 = a + 1 := by omega + have e3 : (2 * (a + 1) - 1) / 2 = a := by omega + rw [e1, e2, e3, Nat.choose_succ_succ] + push_cast + ring + · rw [if_pos (by omega), if_pos (by omega), if_pos (by omega)] + have e1 : (2 * a + 1 + 1 - 0) / 2 = a + 1 := by omega + have e2 : (2 * a + 1 - 0) / 2 = a := by omega + have e3 : (2 * a + 1 - 1) / 2 = a := by omega + rw [e1, e2, e3, Nat.choose_succ_succ, Nat.choose_symm_half] + push_cast + ring + +/-- `N(i-1,k)` for `i ≥ 1`, and `N(0,k)` for `i = 0`. -/ +private def prevN (i k : ℕ) : ℤ := + match i with + | 0 => N 0 k + | i + 1 => N i k + +/-- The production-matrix identity `P · N = N · Sᵀ`. -/ +private theorem N_shift (i k : ℕ) : + N (i + 1) k + prevN i k = if k = 0 then 0 else N i (k - 1) := by + rcases i with _ | i <;> rcases k with _ | k + · simp [N, prevN] + · simp [N, prevN] + · simp only [prevN, if_true] + exact N_rec0 i + · simp only [prevN, Nat.add_sub_cancel, if_neg (Nat.succ_ne_zero k)] + exact N_rec i k + +/-- `M · N = 1`, as a finite sum over any range `L > n`. -/ +private theorem M_mul_N (n : ℕ) : + ∀ L k, n < L → ∑ j ∈ range L, M n j * N j k = if n = k then 1 else 0 := by + induction n with + | zero => + intro L k hL + obtain ⟨L, rfl⟩ : ∃ L', L = L' + 1 := ⟨L - 1, by omega⟩ + rw [sum_range_succ', sum_eq_zero (fun j _ => by rw [M_eq_zero 0 (j + 1) (by omega), zero_mul])] + rcases k with _ | k <;> simp [M, N] + | succ n ih => + intro L k hL + obtain ⟨L, rfl⟩ : ∃ L', L = L' + 1 := ⟨L - 1, by omega⟩ + rw [sum_range_succ'] + simp only [M_succ_succ, M_succ_zero, add_mul, sum_add_distrib] + have h2 : ∑ j ∈ range L, M n (j + 2) * N (j + 1) k + M n 1 * N 0 k = + ∑ j ∈ range (L + 1), M n (j + 1) * N j k := by + rw [sum_range_succ'] + have h3 : ∑ j ∈ range (L + 1), M n (j + 1) * N j k + M n 0 * N 0 k = + ∑ j ∈ range (L + 2), M n j * prevN j k := by + rw [sum_range_succ' _ (L + 1)] + rfl + have h1 : ∑ j ∈ range L, M n j * N (j + 1) k = ∑ j ∈ range (L + 2), M n j * N (j + 1) k := by + rw [sum_range_succ, sum_range_succ, M_eq_zero n L (by omega), + M_eq_zero n (L + 1) (by omega)] + ring + have key : ∑ j ∈ range (L + 2), M n j * N (j + 1) k + ∑ j ∈ range (L + 2), M n j * prevN j k + = ∑ j ∈ range (L + 2), M n j * (if k = 0 then 0 else N j (k - 1)) := by + rw [← sum_add_distrib] + refine sum_congr rfl (fun j _ => ?_) + rw [← N_shift] + ring + calc _ = ∑ j ∈ range (L + 2), M n j * N (j + 1) k + + ∑ j ∈ range (L + 2), M n j * prevN j k := by + rw [← h3, ← h2, h1] + ring + _ = _ := key + _ = _ := by + rcases k with _ | k + · simp + · simp only [if_neg (Nat.succ_ne_zero k), Nat.add_sub_cancel] + rw [ih (L + 2) k (by omega)] + simp + +/-- The inverse computed by forward substitution is `N`. -/ +private theorem Minv_eq_N (n : ℕ) : ∀ k, Minv n k = N n k := by + induction n using Nat.strong_induction_on with + | _ n ih => + intro k + by_cases hk : k ≤ n + · rw [Minv_rec n k hk, sum_congr rfl (fun j hj => by rw [ih j (mem_range.mp hj) k])] + have h := M_mul_N n (n + 1) k (by omega) + rw [sum_range_succ, M_diag, one_mul] at h + by_cases hnk : k = n + · subst hnk + rw [if_pos rfl] at h ⊢ + linarith + · rw [if_neg hnk] + rw [if_neg (Ne.symm hnk)] at h + linarith + · rw [Minv_eq_zero n k (by omega), N_eq_zero n k (by omega)] + +/-- `T(n,k) = ∑_{j ≤ n} N(n,j) N(j,k)`. -/ +private def Tn (n k : ℕ) : ℤ := ∑ j ∈ range (n + 1), N n j * N j k + +/-- The statement's `T` (built from `Minv`) equals `Tn`. -/ +private theorem T_eq_Tn (n k : ℕ) : T n k = Tn n k := by + unfold T Tn + refine sum_congr rfl (fun j _ => ?_) + rw [Minv_eq_N, Minv_eq_N] + +/-- The auxiliary sum `W(m,k) = ∑_j N(m,j+1) N(j,k)`. -/ +private def Wn (m k : ℕ) : ℤ := ∑ j ∈ range m, N m (j + 1) * N j k + +/-- `Tn` as a sum over any range `L > n`. -/ +private theorem Tn_ext (n k L : ℕ) (h : n < L) : ∑ j ∈ range L, N n j * N j k = Tn n k := by + obtain ⟨d, rfl⟩ : ∃ d, L = n + 1 + d := ⟨L - (n + 1), by omega⟩ + rw [sum_range_add, sum_eq_zero (s := range d) + (fun x _ => by rw [N_eq_zero n _ (by omega), zero_mul]), add_zero] + rfl + +/-- `Wn` as a sum over any range `L ≥ m`. -/ +private theorem Wn_ext (m k L : ℕ) (h : m ≤ L) : + ∑ j ∈ range L, N m (j + 1) * N j k = Wn m k := by + obtain ⟨d, rfl⟩ : ∃ d, L = m + d := ⟨L - m, by omega⟩ + rw [sum_range_add, sum_eq_zero (s := range d) + (fun x _ => by rw [N_eq_zero m _ (by omega), zero_mul]), add_zero] + rfl + +/-- `T(n+2,k) + T(n,k) = T(n+1,k-1) - W(n+1,k) - N(n+1,0) N(0,k)`. -/ +private theorem Tn_AB (n k : ℕ) : + Tn (n + 2) k + Tn n k = + (if k = 0 then 0 else Tn (n + 1) (k - 1)) - Wn (n + 1) k - N (n + 1) 0 * N 0 k := by + have h1 : Tn (n + 2) k + Tn n k = ∑ j ∈ range (n + 2), N (n + 1) j * N (j + 1) k := by + rw [← Tn_ext n k (n + 3) (by omega), Tn, ← sum_add_distrib, sum_range_succ'] + simp only [← add_mul, N_rec, N_rec0, zero_mul, add_zero] + have h2 : ∑ j ∈ range (n + 2), N (n + 1) j * N (j + 1) k = + ∑ j ∈ range (n + 2), N (n + 1) j * (if k = 0 then 0 else N j (k - 1)) + - ∑ j ∈ range (n + 2), N (n + 1) j * prevN j k := by + rw [← sum_sub_distrib] + refine sum_congr rfl (fun j _ => ?_) + rw [← N_shift] + ring + have h3 : ∑ j ∈ range (n + 2), N (n + 1) j * prevN j k = + Wn (n + 1) k + N (n + 1) 0 * N 0 k := by + rw [sum_range_succ'] + rfl + have h4 : ∑ j ∈ range (n + 2), N (n + 1) j * (if k = 0 then 0 else N j (k - 1)) = + if k = 0 then 0 else Tn (n + 1) (k - 1) := by + rcases k with _ | k + · simp + · simp only [if_neg (Nat.succ_ne_zero k)] + rfl + rw [h1, h2, h3, h4] + ring + +/-- `W(m+2,k) + W(m,k) = T(m+1,k)`. -/ +private theorem Wn_C (m k : ℕ) : Wn (m + 2) k + Wn m k = Tn (m + 1) k := by + rw [← Wn_ext m k (m + 2) (by omega), Wn, ← sum_add_distrib] + simp only [← add_mul, N_rec] + rfl + +/-- The column recurrence of `T` read off the denominator `1 - xy + 3x^2 - x^3y + x^4`. -/ +private theorem Tn_R (n k : ℕ) : + Tn (n + 4) k + 3 * Tn (n + 2) k + Tn n k = + (if k = 0 then 0 else Tn (n + 3) (k - 1) + Tn (n + 1) (k - 1)) := by + have a1 : Tn (n + 4) k + Tn (n + 2) k = + (if k = 0 then 0 else Tn (n + 3) (k - 1)) - Wn (n + 3) k - N (n + 3) 0 * N 0 k := + Tn_AB (n + 2) k + have a2 := Tn_AB n k + have c : Wn (n + 3) k + Wn (n + 1) k = Tn (n + 2) k := Wn_C (n + 1) k + have r : N (n + 3) 0 + N (n + 1) 0 = 0 := N_rec0 (n + 1) + rcases k with _ | k + · simp only [if_true] at a1 a2 ⊢ + linear_combination a1 + a2 - c - N 0 0 * r + · simp only [if_neg (Nat.succ_ne_zero k)] at a1 a2 ⊢ + linear_combination a1 + a2 - c - N 0 (k + 1) * r + +open MvPowerSeries + +/-- The coefficient of `x^(m 0) y^(m 1)` in `gf` is `T(m 0, m 1)`. -/ +private theorem coeff_gf_eq (m : Fin 2 →₀ ℕ) : coeff m gf = (T (m 0) (m 1) : ℚ) := by + show (if m 1 ≤ m 0 then (T (m 0) (m 1) : ℚ) else 0) = _ + split_ifs with h + · rfl + · rw [T_eq_zero _ _ (by omega)] + simp + +/-- Coefficients of `gf` times the monomial `c x^a y^b`. -/ +private theorem coeff_gf_mul (m : Fin 2 →₀ ℕ) (a b : ℕ) (c : ℚ) : + coeff m (gf * monomial (Finsupp.single 0 a + Finsupp.single 1 b) c) = + if a ≤ m 0 ∧ b ≤ m 1 then (T (m 0 - a) (m 1 - b) : ℚ) * c else 0 := by + rw [coeff_mul_monomial] + have hle : (Finsupp.single 0 a + Finsupp.single 1 b ≤ m) ↔ (a ≤ m 0 ∧ b ≤ m 1) := by + rw [Finsupp.le_def] + simp [Fin.forall_fin_two] + by_cases h : a ≤ m 0 ∧ b ≤ m 1 + · rw [if_pos (hle.mpr h), if_pos h, coeff_gf_eq] + simp [Finsupp.tsub_apply] + · rw [if_neg (mt hle.mp h), if_neg h] + +/-- Coefficients of the monomial `c x^a y^b`. -/ +private theorem coeff_mono (m : Fin 2 →₀ ℕ) (a b : ℕ) (c : ℚ) : + coeff m (monomial (Finsupp.single 0 a + Finsupp.single 1 b) c) = + if m 0 = a ∧ m 1 = b then c else 0 := by + rw [coeff_monomial] + congr 1 + rw [Finsupp.ext_iff] + simp [Fin.forall_fin_two] + +/-- The denominator as a sum of monomials. -/ +private theorem den_eq : den = monomial (Finsupp.single 0 0 + Finsupp.single 1 0) 1 + - monomial (Finsupp.single 0 1 + Finsupp.single 1 1) 1 + + monomial (Finsupp.single 0 2 + Finsupp.single 1 0) 3 + - monomial (Finsupp.single 0 3 + Finsupp.single 1 1) 1 + + monomial (Finsupp.single 0 4 + Finsupp.single 1 0) (1 : ℚ) := by + have h3 : (3 : MvPowerSeries (Fin 2) ℚ) = monomial 0 3 := by + rw [monomial_zero_eq_C_apply, map_ofNat] + simp only [den, X_pow_eq] + simp only [X_def, h3, monomial_mul_monomial, Finsupp.single_zero, add_zero, + zero_add, mul_one, ← monomial_zero_one] + +/-- The numerator `(1-x)(1-x+x^2) = 1 - 2x + 2x^2 - x^3` as a sum of monomials. -/ +private theorem num_eq : ((1 - X 0) * (1 - X 0 + X 0 ^ 2) : MvPowerSeries (Fin 2) ℚ) = + monomial (Finsupp.single 0 0 + Finsupp.single 1 0) 1 + - monomial (Finsupp.single 0 1 + Finsupp.single 1 0) 2 + + monomial (Finsupp.single 0 2 + Finsupp.single 1 0) 2 + - monomial (Finsupp.single 0 3 + Finsupp.single 1 0) (1 : ℚ) := by + have e : ((1 - X 0) * (1 - X 0 + X 0 ^ 2) : MvPowerSeries (Fin 2) ℚ) = + 1 - 2 * X 0 + 2 * X 0 ^ 2 - X 0 ^ 3 := by ring + have h2 : (2 : MvPowerSeries (Fin 2) ℚ) = monomial 0 2 := by + rw [monomial_zero_eq_C_apply, map_ofNat] + rw [e] + simp only [X_pow_eq] + simp only [X_def, h2, monomial_mul_monomial, Finsupp.single_zero, add_zero, + zero_add, mul_one, ← monomial_zero_one] + +/-- The coefficient identity `[x^n y^k] (G · den) = [x^n y^k] (1-x)(1-x+x^2)`, over `ℤ`. -/ +private theorem main_int (n k : ℕ) : + T n k - (if 1 ≤ n ∧ 1 ≤ k then T (n - 1) (k - 1) else 0) + + (if 2 ≤ n then T (n - 2) k * 3 else 0) + - (if 3 ≤ n ∧ 1 ≤ k then T (n - 3) (k - 1) else 0) + + (if 4 ≤ n then T (n - 4) k else 0) = + (if n = 0 ∧ k = 0 then 1 else 0) - (if n = 1 ∧ k = 0 then 2 else 0) + + (if n = 2 ∧ k = 0 then 2 else 0) - (if n = 3 ∧ k = 0 then 1 else 0) := by + by_cases hn : 4 ≤ n + · obtain ⟨n, rfl⟩ : ∃ n', n = n' + 4 := ⟨n - 4, by omega⟩ + have e1 : n + 4 - 1 = n + 3 := by omega + have e2 : n + 4 - 2 = n + 2 := by omega + have e3 : n + 4 - 3 = n + 1 := by omega + have e4 : n + 4 - 4 = n := by omega + have h := Tn_R n k + simp only [e1, e2, e3, e4, T_eq_Tn] + rcases k with _ | k + · simp only [if_true] at h + split_ifs <;> first | omega | linarith | simp_all + · simp only [if_neg (Nat.succ_ne_zero k), Nat.add_sub_cancel] at h + simp only [Nat.add_sub_cancel] + split_ifs <;> first | omega | linarith | simp_all + · by_cases hk : k < 4 + · have hsmall : ∀ n < 4, ∀ k < 4, + T n k - (if 1 ≤ n ∧ 1 ≤ k then T (n - 1) (k - 1) else 0) + + (if 2 ≤ n then T (n - 2) k * 3 else 0) + - (if 3 ≤ n ∧ 1 ≤ k then T (n - 3) (k - 1) else 0) + + (if 4 ≤ n then T (n - 4) k else 0) = + (if n = 0 ∧ k = 0 then 1 else 0) - (if n = 1 ∧ k = 0 then 2 else 0) + + (if n = 2 ∧ k = 0 then 2 else 0) - (if n = 3 ∧ k = 0 then 1 else 0) := by + decide +kernel + exact hsmall n (by omega) k hk + · have z1 : T n k = 0 := T_eq_zero _ _ (by omega) + have z2 : T (n - 1) (k - 1) = 0 := T_eq_zero _ _ (by omega) + have z3 : T (n - 2) k = 0 := T_eq_zero _ _ (by omega) + have z4 : T (n - 3) (k - 1) = 0 := T_eq_zero _ _ (by omega) + have z5 : T (n - 4) k = 0 := T_eq_zero _ _ (by omega) + have hk0 : k ≠ 0 := by omega + simp [z1, z2, z3, z4, z5, hk0] + +/-- Robert Israel's conjectured g.f. for A126127 holds. -/ +theorem result : statement := by + rw [statement_iff, den_eq, num_eq] + ext m + simp only [mul_add, mul_sub, map_add, map_sub, coeff_gf_mul, coeff_mono] + simp only [Nat.sub_zero, mul_one, zero_le, and_true, if_true] + exact_mod_cast main_int (m 0) (m 1) + +end Math0.Frontier.A126127 + +#math0_settles Math0.Frontier.A126127.result Math0.Statements.A126127.statement diff --git a/lean/Math0/Frontier/OEIS/A127752.lean b/lean/Math0/Frontier/OEIS/A127752.lean new file mode 100644 index 0000000..b5df6b4 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A127752.lean @@ -0,0 +1,136 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A127752 +import Math0.Audit + +/-! +# A127752 mod 2 is the first Feigenbaum symbolic sequence A035263 + +We prove Paul Barry's conjecture `a(n) mod 2 = A035263(n+1)`. + +**The recursion for `a`.** The defining forward substitution says that the sum of `a j` over +`⌈n/2⌉ ≤ j ≤ n` is `3n+1`. Comparing the windows for `n = 2m`, `2m+1` and `2m+2` gives +`a(2m+2) = 3` and `a(2m+1) = a(m) + 3`, while `a(0) = 1`. So `a(2m)` is odd and +`a(2m+1) ≡ a(m) + 1 (mod 2)`. + +**The recursion for A035263.** The infinite word is a fixed point of `0 ↦ 11, 1 ↦ 10`, so its +letter at (0-based) position `2m` is `1` and its letter at position `2m+1` is `1` if the letter +at position `m` is `0` and `0` otherwise. With `c(m) = A035263(m+1)` this reads `c(2m) = 1`, +`c(2m+1) = 1 - c(m)`. + +Both sequences satisfy the same recursion mod 2, so strong induction finishes. +-/ + +namespace Math0.Frontier.A127752 +open Math0.Statements.A127752 +open Finset + +/-- The window identity: the sum of `a j` over `⌈n/2⌉ ≤ j ≤ n` is `3n+1`. -/ +private theorem sum_Ico_a (n lo hi : ℕ) (hlo : lo = (n + 1) / 2) (hhi : hi = n + 1) : + ∑ j ∈ Ico lo hi, a j = 3 * n + 1 := by + have h := a_rec n + have hfilter : (range (n + 1)).filter (fun j => n ≤ 2 * j) = Ico lo hi := by + ext j; simp only [mem_filter, mem_range, mem_Ico]; omega + rw [← hfilter, Finset.sum_filter, Finset.sum_range_succ, if_pos (by omega)] + linarith + +/-- `a(2m+2) = 3`. -/ +private theorem a_even (m : ℕ) : a (2 * m + 2) = 3 := by + have h1 := sum_Ico_a (2 * m + 1) (m + 1) (2 * m + 2) (by omega) (by omega) + have h2 := sum_Ico_a (2 * m + 2) (m + 1) (2 * m + 2 + 1) (by omega) (by omega) + rw [Finset.sum_Ico_succ_top (by omega : m + 1 ≤ 2 * m + 2)] at h2 + push_cast at h1 h2 + linarith + +/-- `a(2m+1) = a(m) + 3`. -/ +private theorem a_odd (m : ℕ) : a (2 * m + 1) = a m + 3 := by + have h1 := sum_Ico_a (2 * m) m (2 * m + 1) (by omega) (by omega) + have h2 := sum_Ico_a (2 * m + 1) (m + 1) (2 * m + 1 + 1) (by omega) (by omega) + rw [Finset.sum_Ico_succ_top (by omega : m + 1 ≤ 2 * m + 1)] at h2 + rw [Finset.sum_eq_sum_Ico_succ_bot (by omega : m < 2 * m + 1)] at h1 + push_cast at h1 h2 + linarith + +/-- `a(0) = 1`. -/ +private theorem a_zero : a 0 = 1 := by + have h := a_rec 0 + simpa using h + +/-- The morphism in a uniform shape: `sigma x = [1, b]` with `b = 1` iff `x = 0`. -/ +private theorem sigma_eq (x : ℕ) : sigma x = [1, if x = 0 then 1 else 0] := by + unfold sigma; split <;> simp_all + +/-- Even positions of `l.flatMap sigma` carry the letter `1`. -/ +private theorem flatMap_getD_even (l : List ℕ) (i : ℕ) (hi : i < l.length) : + (l.flatMap sigma).getD (2 * i) 0 = 1 := by + induction l generalizing i with + | nil => simp at hi + | cons x t ih => + rw [List.flatMap_cons, sigma_eq] + cases i with + | zero => rfl + | succ i => + rw [show 2 * (i + 1) = 2 * i + 1 + 1 by ring] + simp only [List.cons_append, List.nil_append, List.getD_cons_succ] + exact ih i (by simp at hi; omega) + +/-- Position `2i+1` of `l.flatMap sigma` is `1` if position `i` of `l` is `0`, else `0`. -/ +private theorem flatMap_getD_odd (l : List ℕ) (i : ℕ) (hi : i < l.length) : + (l.flatMap sigma).getD (2 * i + 1) 0 = if l.getD i 0 = 0 then 1 else 0 := by + induction l generalizing i with + | nil => simp at hi + | cons x t ih => + rw [List.flatMap_cons, sigma_eq] + cases i with + | zero => rfl + | succ i => + rw [show 2 * (i + 1) + 1 = 2 * i + 1 + 1 + 1 by ring] + simp only [List.cons_append, List.nil_append, List.getD_cons_succ] + exact ih i (by simp at hi; omega) + +/-- `m + 1 ≤ 2^m`. -/ +private theorem succ_le_two_pow (m : ℕ) : m + 1 ≤ 2 ^ m := Nat.lt_two_pow_self + +/-- `A035263(2m+1) = 1`. -/ +private theorem A035263_odd_index (m : ℕ) : A035263 (2 * m + 1) = 1 := by + have hk : 2 * m + 1 ≤ 2 ^ (m + 1) := by + have := succ_le_two_pow m; rw [pow_succ]; omega + rw [A035263_eq (n := 2 * m + 1) (k := m + 1) (by omega) hk, word, + show 2 * m + 1 - 1 = 2 * m by omega] + exact flatMap_getD_even _ _ (by rw [word_length]; exact Nat.lt_two_pow_self) + +/-- `A035263(2m+2) = 1` if `A035263(m+1) = 0`, and `0` otherwise. -/ +private theorem A035263_even_index (m : ℕ) : + A035263 (2 * m + 2) = if A035263 (m + 1) = 0 then 1 else 0 := by + have hk : 2 * m + 2 ≤ 2 ^ (m + 1) := by + have := succ_le_two_pow m; rw [pow_succ]; omega + rw [A035263_eq (n := 2 * m + 2) (k := m + 1) (by omega) hk, word, + show 2 * m + 2 - 1 = 2 * m + 1 by omega, + flatMap_getD_odd _ _ (by rw [word_length]; exact Nat.lt_two_pow_self), + A035263_eq (n := m + 1) (k := m) (by omega) (succ_le_two_pow m), + show m + 1 - 1 = m by omega] + +/-- Barry's conjecture: `a(n) mod 2 = A035263(n+1)` for every `n ≥ 0`. -/ +theorem result : statement := by + intro n + induction n using Nat.strong_induction_on with + | _ n ih => + rcases Nat.even_or_odd' n with ⟨m, rfl | rfl⟩ + · rw [A035263_odd_index m] + cases m with + | zero => rw [Nat.mul_zero, a_zero]; rfl + | succ m => rw [show 2 * (m + 1) = 2 * m + 2 by ring, a_even]; rfl + · have ihm := ih m (by omega) + rw [show 2 * m + 1 + 1 = 2 * m + 2 by ring, A035263_even_index, a_odd] + split_ifs with h + · rw [h] at ihm + push_cast at ihm ⊢ + omega + · have h' : (A035263 (m + 1) : ℤ) ≠ 0 := by exact_mod_cast h + push_cast + omega + +end Math0.Frontier.A127752 + +#math0_settles Math0.Frontier.A127752.result Math0.Statements.A127752.statement diff --git a/lean/Math0/Frontier/OEIS/A127755.lean b/lean/Math0/Frontier/OEIS/A127755.lean new file mode 100644 index 0000000..9b15286 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A127755.lean @@ -0,0 +1,64 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A127755 +import Math0.Audit + +/-! +# The inverse of the triangle `1/n! [k ≤ n ≤ 2k]` is an integer triangle + +We prove Paul Barry's conjecture from OEIS A127755: every entry `T(n,k)` of the inverse of the +triangle `A(n,k) = 1/n!` (for `k ≤ n ≤ 2k`, `0` otherwise) is an integer. + +The idea: the forward-substitution recursion already shows integrality, because +`n! · A(n,j) = [j ≤ n ≤ 2j]` is `0` or `1`. Hence +`T(n,k) = n! [n = k] - ∑_{j < n} [j ≤ n ≤ 2j] T(j,k)`, +and strong induction on `n` shows that every `T(n,k)` lies in the image of `ℤ → ℚ`. +(Equivalently `A = D⁻¹ B` with `D = diag(n!)` and `B` a `0/1` unitriangular matrix, so +`A⁻¹ = B⁻¹ D` is integral.) +-/ + +namespace Math0.Frontier.A127755 +open Math0.Statements.A127755 Finset + +/-- `n! · A(n,j)` is the `0/1` indicator of `j ≤ n ≤ 2j`. -/ +private lemma factorial_mul_A (n j : ℕ) : + (n.factorial : ℚ) * A n j = if j ≤ n ∧ n ≤ 2 * j then 1 else 0 := by + have hc : (n.factorial : ℚ) ≠ 0 := by exact_mod_cast (Nat.factorial_pos n).ne' + unfold A + split_ifs + · field_simp + · simp + +/-- A `0/1` indicator is an integer. -/ +private lemma ite_mem (p : Prop) [Decidable p] : + (if p then (1 : ℚ) else 0) ∈ (Int.castRingHom ℚ).range := by + split_ifs + · exact Subring.one_mem _ + · exact Subring.zero_mem _ + +/-- Every entry `T(n,k)` (for all `k`) lies in the image of `ℤ` in `ℚ`, by strong induction +on `n` using the recursion `T_spec`. -/ +private lemma T_mem (n : ℕ) : ∀ k : ℕ, T n k ∈ (Int.castRingHom ℚ).range := by + induction n using Nat.strong_induction_on with + | _ n ih => + intro k + rw [T_spec] + by_cases hk : k ≤ n + · rw [if_pos hk, mul_sub, Finset.mul_sum] + refine Subring.sub_mem _ (Subring.mul_mem _ ⟨n.factorial, by simp⟩ (ite_mem _)) + (Subring.sum_mem _ fun j hj => ?_) + rw [← mul_assoc, factorial_mul_A] + exact Subring.mul_mem _ (ite_mem _) (ih j (Finset.mem_range.mp hj) k) + · rw [if_neg hk] + exact Subring.zero_mem _ + +/-- OEIS A127755 (conjecture of Paul Barry): the inverse triangle has integer entries. -/ +theorem result : statement := by + intro n k _ + obtain ⟨z, hz⟩ := T_mem n k + exact ⟨z, by simpa using hz.symm⟩ + +end Math0.Frontier.A127755 + +#math0_settles Math0.Frontier.A127755.result Math0.Statements.A127755.statement diff --git a/lean/Math0/Frontier/OEIS/A127767.lean b/lean/Math0/Frontier/OEIS/A127767.lean new file mode 100644 index 0000000..6778ed2 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A127767.lean @@ -0,0 +1,67 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A127767 +import Math0.Audit + +/-! +# The inverse of the `1/C(n)` band triangle (A127767) has integer entries + +We prove Paul Barry's conjecture that every entry `T(n,k)` of the inverse of the triangle +`A(n,k) = 1/C(n)` for `k ≤ n ≤ 2k` (and `0` otherwise) is an integer. + +**Idea.** Write `A = D·M` with `D = diag(1/C(n))` and `M(n,k) = [k ≤ n ≤ 2k]`, a lower +unitriangular `0/1` matrix. Then `A⁻¹ = M⁻¹·D⁻¹`, so `T(n,k) = M⁻¹(n,k)·C(k)`, and `M⁻¹` is +integral since `M` is unitriangular over `ℤ`. Concretely, we prove by strong induction on `n` +that `T(n,k)` is an integer multiple of `C(k)`: by the forward-substitution recursion +`T(n,k) = C(n)·([n = k] - ∑_{j + intro k + have h' : ∀ m, m < n → ∃ z : ℤ, T m k = (z : ℚ) * (cat k : ℚ) := fun m hm => ih m hm k + choose! f hf using h' + have hc : (cat n : ℚ) ≠ 0 := by exact_mod_cast (cat_pos n).ne' + rw [T_spec] + by_cases hk : k ≤ n + · rw [if_pos hk] + refine ⟨(if n = k then 1 else 0) - + ∑ j ∈ range n, (if j ≤ n ∧ n ≤ 2 * j then f j else 0), ?_⟩ + have hs : ∑ j ∈ range n, A n j * T j k + = (cat k : ℚ) / (cat n : ℚ) * + ∑ j ∈ range n, ((if j ≤ n ∧ n ≤ 2 * j then f j else 0 : ℤ) : ℚ) := by + rw [Finset.mul_sum] + refine Finset.sum_congr rfl fun j hj => ?_ + rw [hf j (Finset.mem_range.mp hj), A] + split_ifs <;> push_cast <;> ring + rw [hs] + by_cases hnk : n = k + · subst hnk + push_cast + field_simp + · push_cast + simp only [hnk, if_false] + field_simp + ring + · exact ⟨0, by rw [if_neg hk]; simp⟩ + +/-- **A127767 conjecture.** Every entry `T(n,k)`, `0 ≤ k ≤ n`, of the inverse triangle is an +integer. -/ +theorem result : statement := by + intro n k _ + obtain ⟨z, hz⟩ := T_eq_int_mul_cat n k + exact ⟨z * (cat k : ℤ), by rw [hz]; push_cast; ring⟩ + +end Math0.Frontier.A127767 + +#math0_settles Math0.Frontier.A127767.result Math0.Statements.A127767.statement diff --git a/lean/Math0/Frontier/OEIS/A129455.lean b/lean/Math0/Frontier/OEIS/A129455.lean new file mode 100644 index 0000000..0b99278 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A129455.lean @@ -0,0 +1,231 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A129455 +import Math0.Audit + +/-! +# The triple-gcd Pascal triangle A129455: integrality and sixth powers + +We prove Peter Bala's conjecture: writing `G(m) = A129454(m+1) = ∏_{i,j,k ∈ [1,m]} gcd(i,j,k)`, +for all `0 ≤ k ≤ n` the quotient `T(n,k) = G(n)/(G(k) G(n-k))` is an integer, `C(n,k) ∣ T(n,k)`, +and `T(n,k)/C(n,k)` is a perfect sixth power. + +**Idea.** Let `L(d) = p` if `d = p^t` is a prime power and `L(d) = 1` otherwise (so +`log L = Λ`, the von Mangoldt function). Since `∑_{d ∣ g} Λ(d) = log g`, every `g ≥ 1` satisfies +`g = ∏_{d ∣ g} L(d)`. Applying this to every `gcd(i,j,k)` and to every factor of `m!`, and +counting multiples of `d` in `[1,m]`, we get for `m ≤ N` +`G(m) = ∏_{d=1}^N L(d)^{⌊m/d⌋^3}` and `m! = ∏_{d=1}^N L(d)^{⌊m/d⌋}`. +Fix `d ≥ 1` and put `F = ⌊n/d⌋`, `A = ⌊k/d⌋`, `B = ⌊(n-k)/d⌋`; then `F = A + B + c` with +`c ∈ {0,1}`. Hence `C(n,k) = n!/(k!(n-k)!) = ∏ L(d)^c`, and +`F^3 = A^3 + B^3 + c + 3(AB(A+B) + c(A+B)(A+B+1))`, where `AB(A+B)` and `(A+B)(A+B+1)` are +even. So `G(n) = G(k) G(n-k) C(n,k) M^6` with `M = ∏ L(d)^{e_d}`, +`e_d = (AB(A+B) + c(A+B)(A+B+1))/2`, which gives all three claims at once. +-/ + +namespace Math0.Frontier.A129455 +open Math0.Statements.A129455 + +/-- `L d = p` when `d` is a power `p ^ t` (`t ≥ 1`) of a prime `p`, and `1` otherwise; its +logarithm is the von Mangoldt function. -/ +private def L (d : ℕ) : ℕ := if IsPrimePow d then d.minFac else 1 + +/-- `L` is positive. -/ +private lemma L_pos (d : ℕ) : 0 < L d := by + unfold L + split_ifs + · exact Nat.minFac_pos _ + · exact one_pos + +/-- `log (L d) = Λ d`. -/ +private lemma log_L (d : ℕ) : Real.log (L d : ℝ) = ArithmeticFunction.vonMangoldt d := by + rw [ArithmeticFunction.vonMangoldt_apply] + unfold L + split_ifs <;> simp + +/-- Every positive `g` is the product of `L d` over the divisors `d` of `g`. -/ +private lemma prod_divisors_L (g : ℕ) (hg : 0 < g) : ∏ d ∈ g.divisors, L d = g := by + have h1 : (0 : ℝ) < ((∏ d ∈ g.divisors, L d : ℕ) : ℝ) := by + exact_mod_cast Finset.prod_pos fun d _ => L_pos d + have h2 : (0 : ℝ) < (g : ℝ) := by exact_mod_cast hg + have h3 : Real.log ((∏ d ∈ g.divisors, L d : ℕ) : ℝ) = Real.log g := by + rw [Nat.cast_prod, Real.log_prod (fun d _ => by exact_mod_cast (L_pos d).ne'), + ← ArithmeticFunction.vonMangoldt_sum] + exact Finset.sum_congr rfl fun d _ => log_L d + exact_mod_cast Real.log_injOn_pos (Set.mem_Ioi.2 h1) (Set.mem_Ioi.2 h2) h3 + +/-- For `1 ≤ g ≤ N`, `g = ∏_{d=1}^N L(d)^{[d ∣ g]}`. -/ +private lemma decomp (N g : ℕ) (hg : 0 < g) (hgN : g ≤ N) : + g = ∏ d ∈ Finset.Icc 1 N, L d ^ (if d ∣ g then 1 else 0) := by + have hfilt : (Finset.Icc 1 N).filter (· ∣ g) = g.divisors := by + ext d + simp only [Finset.mem_filter, Finset.mem_Icc, Nat.mem_divisors] + constructor + · rintro ⟨_, h⟩ + exact ⟨h, hg.ne'⟩ + · rintro ⟨h, _⟩ + have := Nat.le_of_dvd hg h + have : 0 < d := Nat.pos_of_dvd_of_pos h hg + exact ⟨⟨this, by omega⟩, h⟩ + simp only [pow_ite, pow_one, pow_zero] + rw [← Finset.prod_filter, hfilt, prod_divisors_L g hg] + +/-- The number of multiples of `d` in `[1, m]` is `m / d`. -/ +private lemma count_mult (d m : ℕ) : + ∑ i ∈ Finset.Icc 1 m, (if d ∣ i then 1 else 0) = m / d := by + rw [Finset.sum_boole] + have : Finset.Icc 1 m = Finset.Ioc 0 m := by + ext x + simp only [Finset.mem_Icc, Finset.mem_Ioc] + omega + rw [this] + exact_mod_cast Nat.Ioc_filter_dvd_card_eq_div m d + +/-- `m! = ∏_{d=1}^N L(d)^{⌊m/d⌋}` for `m ≤ N`. -/ +private lemma factorial_eq (N m : ℕ) (hm : m ≤ N) : + m.factorial = ∏ d ∈ Finset.Icc 1 N, L d ^ (m / d) := by + have h1 : m.factorial = ∏ i ∈ Finset.Icc 1 m, i := by + rw [← Finset.prod_Ico_id_eq_factorial] + rfl + rw [h1] + calc ∏ i ∈ Finset.Icc 1 m, i + = ∏ i ∈ Finset.Icc 1 m, ∏ d ∈ Finset.Icc 1 N, L d ^ (if d ∣ i then 1 else 0) := by + refine Finset.prod_congr rfl fun i hi => ?_ + rw [Finset.mem_Icc] at hi + exact decomp N i (by omega) (by omega) + _ = ∏ d ∈ Finset.Icc 1 N, ∏ i ∈ Finset.Icc 1 m, L d ^ (if d ∣ i then 1 else 0) := + Finset.prod_comm + _ = ∏ d ∈ Finset.Icc 1 N, L d ^ (m / d) := by + refine Finset.prod_congr rfl fun d _ => ?_ + rw [Finset.prod_pow_eq_pow_sum, count_mult] + +/-- `A129454 (m+1) = ∏_{d=1}^N L(d)^{⌊m/d⌋^3}` for `m ≤ N`. -/ +private lemma G_eq (N m : ℕ) (hm : m ≤ N) : + A129454 (m + 1) = ∏ d ∈ Finset.Icc 1 N, L d ^ ((m / d) ^ 3) := by + unfold A129454 + rw [Nat.add_sub_cancel] + calc ∏ i ∈ Finset.Icc 1 m, ∏ j ∈ Finset.Icc 1 m, ∏ k ∈ Finset.Icc 1 m, + Nat.gcd (Nat.gcd i j) k + = ∏ i ∈ Finset.Icc 1 m, ∏ j ∈ Finset.Icc 1 m, ∏ k ∈ Finset.Icc 1 m, + ∏ d ∈ Finset.Icc 1 N, L d ^ (if d ∣ Nat.gcd (Nat.gcd i j) k then 1 else 0) := by + refine Finset.prod_congr rfl fun i _ => Finset.prod_congr rfl fun j _ => + Finset.prod_congr rfl fun k hk => ?_ + rw [Finset.mem_Icc] at hk + exact decomp N _ (Nat.gcd_pos_of_pos_right _ (by omega)) + (le_trans (Nat.gcd_le_right _ (by omega)) (by omega)) + _ = ∏ i ∈ Finset.Icc 1 m, ∏ j ∈ Finset.Icc 1 m, ∏ d ∈ Finset.Icc 1 N, + ∏ k ∈ Finset.Icc 1 m, L d ^ (if d ∣ Nat.gcd (Nat.gcd i j) k then 1 else 0) := + Finset.prod_congr rfl fun _ _ => Finset.prod_congr rfl fun _ _ => Finset.prod_comm + _ = ∏ i ∈ Finset.Icc 1 m, ∏ d ∈ Finset.Icc 1 N, ∏ j ∈ Finset.Icc 1 m, + ∏ k ∈ Finset.Icc 1 m, L d ^ (if d ∣ Nat.gcd (Nat.gcd i j) k then 1 else 0) := + Finset.prod_congr rfl fun _ _ => Finset.prod_comm + _ = ∏ d ∈ Finset.Icc 1 N, ∏ i ∈ Finset.Icc 1 m, ∏ j ∈ Finset.Icc 1 m, + ∏ k ∈ Finset.Icc 1 m, L d ^ (if d ∣ Nat.gcd (Nat.gcd i j) k then 1 else 0) := + Finset.prod_comm + _ = ∏ d ∈ Finset.Icc 1 N, L d ^ ((m / d) ^ 3) := by + refine Finset.prod_congr rfl fun d _ => ?_ + simp only [Finset.prod_pow_eq_pow_sum] + congr 1 + have hsplit : ∀ i j k : ℕ, (if d ∣ Nat.gcd (Nat.gcd i j) k then 1 else 0) = + (if d ∣ i then 1 else 0) * (if d ∣ j then 1 else 0) * (if d ∣ k then 1 else 0) := by + intro i j k + simp only [Nat.dvd_gcd_iff] + by_cases hi : d ∣ i <;> by_cases hj : d ∣ j <;> by_cases hk : d ∣ k <;> simp [hi, hj, hk] + simp only [hsplit, ← Finset.mul_sum, ← Finset.sum_mul, count_mult] + ring + +/-- Parity: `AB(A+B) + c(A+B)(A+B+1)` is even. -/ +private lemma two_dvd (A B c : ℕ) : 2 ∣ A * B * (A + B) + c * (A + B) * (A + B + 1) := by + rw [← even_iff_two_dvd] + have h1 : Even (A * B * (A + B)) := by + rcases Nat.even_or_odd A with hA | hA + · exact (hA.mul_right B).mul_right _ + · rcases Nat.even_or_odd B with hB | hB + · exact (hB.mul_left A).mul_right _ + · exact (hA.add_odd hB).mul_left _ + have h2 : Even (c * (A + B) * (A + B + 1)) := by + rw [mul_assoc] + exact (Nat.even_mul_succ_self (A + B)).mul_left c + exact h1.add h2 + +/-- The cubic identity behind the sixth powers. -/ +private lemma cube_identity (A B c : ℕ) (hc : c = 0 ∨ c = 1) : + (A + B + c) ^ 3 = + A ^ 3 + B ^ 3 + c + 6 * ((A * B * (A + B) + c * (A + B) * (A + B + 1)) / 2) := by + obtain ⟨q, hq⟩ := two_dvd A B c + rw [hq, Nat.mul_div_cancel_left q (by norm_num)] + rcases hc with rfl | rfl + · nlinarith [hq] + · nlinarith [hq] + +/-- The main identity: `G(n) = G(n-k) G(k) (C(n,k) M^6)`. -/ +private lemma main_identity (n k : ℕ) (hk : k ≤ n) : + ∃ M : ℕ, A129454 (n + 1) = A129454 (n - k + 1) * A129454 (k + 1) * (n.choose k * M ^ 6) := by + set c : ℕ → ℕ := fun d => if d ≤ k % d + (n - k) % d then 1 else 0 with hc_def + have hF : ∀ d ∈ Finset.Icc 1 n, n / d = k / d + (n - k) / d + c d := by + intro d hd + rw [Finset.mem_Icc] at hd + have := Nat.add_div (a := k) (b := n - k) (c := d) (by omega) + rw [Nat.add_sub_cancel' hk] at this + exact this + have hc01 : ∀ d, c d = 0 ∨ c d = 1 := by + intro d + simp only [hc_def] + split_ifs <;> simp + set e : ℕ → ℕ := fun d => + ((k / d) * ((n - k) / d) * (k / d + (n - k) / d) + + c d * (k / d + (n - k) / d) * (k / d + (n - k) / d + 1)) / 2 with he_def + refine ⟨∏ d ∈ Finset.Icc 1 n, L d ^ e d, ?_⟩ + -- binomial coefficient + have hchoose : n.choose k = ∏ d ∈ Finset.Icc 1 n, L d ^ c d := by + have h1 := Nat.choose_mul_factorial_mul_factorial hk + rw [factorial_eq n n le_rfl, factorial_eq n k hk, factorial_eq n (n - k) (Nat.sub_le n k)] + at h1 + have h2 : ∏ d ∈ Finset.Icc 1 n, L d ^ (n / d) = + (∏ d ∈ Finset.Icc 1 n, L d ^ c d) * + ((∏ d ∈ Finset.Icc 1 n, L d ^ (k / d)) * + ∏ d ∈ Finset.Icc 1 n, L d ^ ((n - k) / d)) := by + rw [← Finset.prod_mul_distrib, ← Finset.prod_mul_distrib] + refine Finset.prod_congr rfl fun d hd => ?_ + rw [hF d hd, ← pow_add, ← pow_add] + ring_nf + rw [h2, mul_assoc] at h1 + have hpos : 0 < (∏ d ∈ Finset.Icc 1 n, L d ^ (k / d)) * + ∏ d ∈ Finset.Icc 1 n, L d ^ ((n - k) / d) := by + apply Nat.mul_pos <;> exact Finset.prod_pos fun d _ => pow_pos (L_pos d) _ + exact Nat.eq_of_mul_eq_mul_right hpos h1 + rw [G_eq n n le_rfl, G_eq n (n - k) (Nat.sub_le n k), G_eq n k hk, hchoose, + ← Finset.prod_pow, ← Finset.prod_mul_distrib, ← Finset.prod_mul_distrib, + ← Finset.prod_mul_distrib] + refine Finset.prod_congr rfl fun d hd => ?_ + have hcube : + (k / d + (n - k) / d + c d) ^ 3 = (k / d) ^ 3 + ((n - k) / d) ^ 3 + c d + 6 * e d := + cube_identity (k / d) ((n - k) / d) (c d) (hc01 d) + rw [hF d hd, hcube] + ring + +/-- A129454 is positive. -/ +private lemma A129454_pos (m : ℕ) : 0 < A129454 m := by + unfold A129454 + refine Finset.prod_pos fun i _ => Finset.prod_pos fun j _ => Finset.prod_pos fun k hk => ?_ + rw [Finset.mem_Icc] at hk + exact Nat.gcd_pos_of_pos_right _ (by omega) + +/-- Bala's conjecture on A129455 holds: `T(n,k)` is an integer, `C(n,k) ∣ T(n,k)`, and +`T(n,k)/C(n,k)` is a perfect sixth power. -/ +theorem result : statement := by + intro n k hk + obtain ⟨M, hM⟩ := main_identity n k hk + have hpos : 0 < A129454 (n - k + 1) * A129454 (k + 1) := + Nat.mul_pos (A129454_pos _) (A129454_pos _) + have hT : T n k = n.choose k * M ^ 6 := by + unfold T + rw [hM, Nat.mul_div_cancel_left _ hpos] + refine ⟨Dvd.intro _ hM.symm, ?_, M, ?_⟩ + · rw [hT] + exact dvd_mul_right _ _ + · rw [hT, Nat.mul_div_cancel_left _ (Nat.choose_pos hk)] + +end Math0.Frontier.A129455 + +#math0_settles Math0.Frontier.A129455.result Math0.Statements.A129455.statement diff --git a/lean/Math0/Frontier/OEIS/A132616.lean b/lean/Math0/Frontier/OEIS/A132616.lean new file mode 100644 index 0000000..786dcd9 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A132616.lean @@ -0,0 +1,161 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A132616 +import Math0.Audit + +/-! +# Irwin's nested sums for column 0 of the triangle A132615 + +We prove Irwin's conjecture: for `n ≥ 2`, `a(n) = T(n, 0)` equals the `n - 1` nested sums +`Sum_{i_1=1..1+2(n-2)} Sum_{i_2=1..i_1+2(n-3)} ⋯ Sum_{i_(n-1)=1..i_(n-2)} 1`. + +**The powers of `T`.** Define `N p n k` by `N p 0 k = [k = 0]` and +`N p (n+1) k = [k = n+1] + Sum_{i if k = 0 then 1 else 0 + | p, n + 1, k => (if k = n + 1 then 1 else 0) + ∑ i ∈ range p, N (2 * n - 1 + i) n k + +/-- Unfolding `N` on a successor row. -/ +private lemma N_succ (p n k : ℕ) : + N p (n + 1) k = (if k = n + 1 then 1 else 0) + ∑ i ∈ range p, N (2 * n - 1 + i) n k := by + rw [N] + +/-- Row `0` of `N` does not depend on the exponent. -/ +private lemma N_zero_row (p k : ℕ) : N p 0 k = if k = 0 then 1 else 0 := by + rw [N] + +/-- The increment of `N` in the exponent. -/ +private lemma N_step (p n k : ℕ) : + N (p + 1) (n + 1) k = N p (n + 1) k + N (2 * n - 1 + p) n k := by + rw [N_succ, N_succ, sum_range_succ, add_assoc] + +/-- `N` is lower triangular. -/ +private lemma N_upper : ∀ (p n k : ℕ), n < k → N p n k = 0 + | p, 0, k, h => by rw [N_zero_row, if_neg (by omega)] + | p, n + 1, k, h => by + rw [N_succ, if_neg (by omega), zero_add] + exact sum_eq_zero fun i _ => N_upper _ n k (by omega) + +/-- `N` has ones on the diagonal. -/ +private lemma N_diag : ∀ p n, N p n n = 1 + | p, 0 => by rw [N_zero_row, if_pos rfl] + | p, n + 1 => by + rw [N_succ, if_pos rfl, sum_eq_zero fun i _ => N_upper _ n (n + 1) (by omega), add_zero] + +/-- The exponent `0` gives the identity matrix. -/ +private lemma N_zero_left : ∀ n k, N 0 n k = if k = n then 1 else 0 + | 0, k => by rw [N_zero_row] + | n + 1, k => by rw [N_succ, sum_range_zero, add_zero] + +/-- The semigroup law `N p * N q = N (p + q)`. -/ +private lemma N_mul : ∀ n p q k, ∑ m ∈ range (n + 1), N p n m * N q m k = N (p + q) n k + | 0, p, q, k => by + rw [sum_range_one, N_zero_row, if_pos rfl, one_mul, N_zero_row, N_zero_row] + | n + 1, p, q, k => by + induction p with + | zero => + rw [sum_range_succ, sum_eq_zero fun m hm => by + rw [N_zero_left, if_neg (by simp at hm; omega), zero_mul]] + rw [N_zero_left, if_pos rfl, one_mul, zero_add, zero_add] + | succ p ih => + have h1 : ∑ m ∈ range (n + 1 + 1), N (p + 1) (n + 1) m * N q m k = + ∑ m ∈ range (n + 1 + 1), N p (n + 1) m * N q m k + + ∑ m ∈ range (n + 1 + 1), N (2 * n - 1 + p) n m * N q m k := by + rw [← sum_add_distrib] + exact sum_congr rfl fun m _ => by rw [N_step, add_mul] + have h2 : ∑ m ∈ range (n + 1 + 1), N (2 * n - 1 + p) n m * N q m k = + N (2 * n - 1 + p + q) n k := by + rw [sum_range_succ, N_upper _ n (n + 1) (by omega), zero_mul, add_zero] + exact N_mul n _ q k + rw [h1, ih, h2, show p + 1 + q = (p + q) + 1 by omega, N_step, add_assoc] + +/-- If `tri n` has entries `N 1`, then its `e`-th power has entries `N e`. -/ +private lemma tri_pow_of (n : ℕ) (h : ∀ i j : Fin (n + 1), tri n i j = N 1 i j) : + ∀ e (i j : Fin (n + 1)), (tri n ^ e) i j = N e i j := by + intro e + induction e with + | zero => + intro i j + rw [pow_zero, Matrix.one_apply, N_zero_left] + by_cases hij : i = j + · rw [if_pos hij, if_pos (by rw [hij])] + · rw [if_neg hij, if_neg (fun h' => hij (Fin.ext h'.symm))] + | succ e ih => + intro i j + rw [pow_succ, Matrix.mul_apply] + simp only [ih, h] + rw [Fin.sum_univ_eq_sum_range (fun m => N e i m * N 1 m j) (n + 1)] + have hi : (i : ℕ) + 1 ≤ n + 1 := i.isLt + rw [← sum_range_add_sum_Ico _ hi, N_mul, sum_eq_zero fun m hm => by + rw [N_upper e i m (by simp at hm; omega), zero_mul], add_zero] + +/-- The truncations of the triangle have entries `N 1`. -/ +private lemma tri_eq : ∀ n (i j : Fin (n + 1)), tri n i j = N 1 i j + | 0, i, j => by + have hi : i = 0 := Fin.ext (by have := i.isLt; simp) + have hj : j = 0 := Fin.ext (by have := j.isLt; simp) + subst hi; subst hj + rw [Fin.val_zero, N_diag] + rfl + | n + 1, i, j => by + simp only [tri, Matrix.of_apply] + split_ifs with hi hj hj + · exact tri_eq n _ _ + · rw [N_upper]; omega + · rw [tri_pow_of n (tri_eq n), Fin.val_last] + have hi' : (i : ℕ) = n + 1 := by omega + rw [hi', N_succ, if_neg (by omega), zero_add, sum_range_one, add_zero] + · have hi' : (i : ℕ) = n + 1 := by omega + have hj' : (j : ℕ) = n + 1 := by omega + rw [hi', hj', N_diag] + +/-- `a n = N 1 n 0`. -/ +private lemma a_eq (n : ℕ) : a n = N 1 n 0 := by + unfold a T + rw [dif_pos (Nat.zero_le n), tri_eq, Fin.val_last] + +/-- Irwin's nested sums in terms of `N`. -/ +private lemma nest_eq : ∀ m c, nest m c = N (c + 2 * m - 2) m 0 + | 0, c => by rw [nest, N_zero_row, if_pos rfl] + | m + 1, c => by + rw [nest, show c + 2 * (m + 1) - 2 = c + 2 * m by omega, N_succ, if_neg (by omega), + zero_add, ← Ico_add_one_right_eq_Icc, sum_Ico_eq_sum_range, + show c + 2 * m + 1 - 1 = c + 2 * m by omega] + refine sum_congr rfl fun i _ => ?_ + rw [nest_eq m (1 + i)] + rcases Nat.eq_zero_or_pos m with rfl | hm + · rw [N_zero_row, N_zero_row] + · congr 1; omega + +/-- Irwin's conjecture holds. -/ +theorem result : statement := by + intro n hn + obtain ⟨n', rfl⟩ : ∃ n', n = n' + 1 := ⟨n - 1, by omega⟩ + rw [a_eq, Nat.add_sub_cancel, nest_eq, N_succ, if_neg (by omega), zero_add, sum_range_one] + congr 1 + omega + +end Math0.Frontier.A132616 + +#math0_settles Math0.Frontier.A132616.result Math0.Statements.A132616.statement diff --git a/lean/Math0/Frontier/OEIS/A141412.lean b/lean/Math0/Frontier/OEIS/A141412.lean new file mode 100644 index 0000000..74dc351 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A141412.lean @@ -0,0 +1,157 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A141412 +import Math0.Audit + +/-! +# Denominators of Curtz's polynomials are Farhi's `d(n+1,k+1)` + +We prove Marcus's conjecture on A141412: `T(n,k) = d(n+1,k+1)` for all `n, k`. + +The idea is generating functions in `ℚ⟦X⟧`. Write `L = log(1+X) = ∑_{j ≥ 1} (-1)^(j+1) X^j/j`. +The recursion defining `c n k = [x^k] P(n,x)` says that the column series +`Cs k = ∑_n c(n,k) X^n` satisfy `X · Cs 0 = L` and `Cs (k+1) = L · Cs k`, so +`X · Cs k = L^(k+1)`. On the other side, the series +`F m = ∑_N (-1)^(N+m) |s(N,m)| m!/N! X^N` satisfy `(1+X) F(m+1)' = (m+1) F(m)` (this is +the Stirling recurrence `|s(N+1,m+1)| = N |s(N,m+1)| + |s(N,m)|`), `F 0 = 1`, and have zero +constant term for `m ≥ 1`; since `(1+X) L' = 1`, the powers `L^m` satisfy the same +differential recursion, so `F m = L^m` by uniqueness (`PowerSeries.derivative.ext`, after +cancelling the nonzero factor `1+X`). Comparing coefficients of `X^(n+1)` gives +`c n k = (-1)^(n+k) |s(n+1,k+1)| (k+1)!/(n+1)!`, and a sign does not change a denominator. +-/ + +namespace Math0.Frontier.A141412 +open Math0.Statements.A141412 PowerSeries + +/-- The power series `log(1+X) = ∑_{n ≥ 1} (-1)^(n+1) X^n / n`. -/ +private noncomputable def L : ℚ⟦X⟧ := + PowerSeries.mk fun n => if n = 0 then 0 else (-1 : ℚ) ^ (n + 1) / n + +/-- The exponential generating function of the signed Stirling numbers of the first kind, +scaled by `m!`: `F m = ∑_N s(N,m) m!/N! X^N` with `s(N,m) = (-1)^(N+m) |s(N,m)|`. -/ +private noncomputable def F (m : ℕ) : ℚ⟦X⟧ := + PowerSeries.mk fun N => + (-1 : ℚ) ^ (N + m) * (Nat.stirlingFirst N m : ℚ) * (m.factorial : ℚ) / (N.factorial : ℚ) + +/-- The column generating function `∑_n c(n,k) X^n`. -/ +private noncomputable def Cs (k : ℕ) : ℚ⟦X⟧ := + PowerSeries.mk fun n => c n k + +/-- Coefficients of `(1+X) g'`. -/ +private lemma coeff_one_add_X_mul_deriv (g : ℚ⟦X⟧) (N : ℕ) : + coeff N ((1 + X) * d⁄dX ℚ g) = coeff (N + 1) g * (N + 1) + coeff N g * N := by + cases N with + | zero => + rw [add_mul, one_mul, map_add, coeff_zero_X_mul, coeff_derivative] + simp + | succ n => + rw [add_mul, one_mul, map_add, coeff_succ_X_mul, coeff_derivative, coeff_derivative] + push_cast + ring + +/-- `(1+X) · log(1+X)' = 1`. -/ +private lemma one_add_X_mul_deriv_L : (1 + X) * d⁄dX ℚ L = 1 := by + ext N + rw [coeff_one_add_X_mul_deriv, coeff_one] + cases N with + | zero => simp [L] + | succ n => + simp only [L, coeff_mk, if_false, Nat.succ_ne_zero] + push_cast + field_simp + ring + +/-- The derivative identity `(1+X) F(m+1)' = (m+1) F(m)`, from the Stirling recurrence. -/ +private lemma one_add_X_mul_deriv_F (m : ℕ) : + (1 + X) * d⁄dX ℚ (F (m + 1)) = C ((m : ℚ) + 1) * F m := by + ext N + rw [coeff_one_add_X_mul_deriv, coeff_C_mul] + simp only [F, coeff_mk] + rw [Nat.stirlingFirst_succ_succ, Nat.factorial_succ N, Nat.factorial_succ m] + have hN : (N.factorial : ℚ) ≠ 0 := by positivity + push_cast + field_simp + ring + +/-- `F m = log(1+X)^m`. -/ +private lemma F_eq (m : ℕ) : F m = L ^ m := by + induction m with + | zero => + ext N + cases N with + | zero => simp [F] + | succ n => simp [F] + | succ m ih => + apply derivative.ext + · have h1 : (1 + X : ℚ⟦X⟧) ≠ 0 := by + intro h + have := congrArg (constantCoeff (R := ℚ)) h + simp at this + apply mul_left_cancel₀ h1 + have key : (1 + X) * d⁄dX ℚ (L ^ (m + 1)) = C ((m : ℚ) + 1) * L ^ m := by + rw [derivative_pow, Nat.add_sub_cancel] + calc (1 + X) * (((m + 1 : ℕ) : ℚ⟦X⟧) * L ^ m * d⁄dX ℚ L) + = ((m + 1 : ℕ) : ℚ⟦X⟧) * L ^ m * ((1 + X) * d⁄dX ℚ L) := by ring + _ = C ((m : ℚ) + 1) * L ^ m := by + rw [one_add_X_mul_deriv_L, mul_one, ← map_natCast (C (R := ℚ)), Nat.cast_succ] + rw [one_add_X_mul_deriv_F, ih, key] + · rw [map_pow] + simp [F, L, ← coeff_zero_eq_constantCoeff_apply] + +/-- `c n 0 = (-1)^n/(n+1)` for all `n`. -/ +private lemma c_zero (n : ℕ) : c n 0 = (-1 : ℚ) ^ n / ((n : ℚ) + 1) := by + cases n with + | zero => simp [c] + | succ n => simp [c] + +/-- `Cs (k+1) = log(1+X) · Cs k`, i.e. the recursion of `c`. -/ +private lemma Cs_succ (k : ℕ) : Cs (k + 1) = L * Cs k := by + ext n + rw [coeff_mul] + cases n with + | zero => simp [Cs, L, c] + | succ n => + rw [Finset.Nat.sum_antidiagonal_succ, Finset.Nat.sum_antidiagonal_eq_sum_range_succ_mk] + simp only [Cs, L, coeff_mk, c, if_true, zero_mul, zero_add, Nat.succ_ne_zero, if_false] + refine Finset.sum_congr rfl fun i _ => ?_ + push_cast + ring + +/-- `X · Cs k = log(1+X)^(k+1)`. -/ +private lemma X_mul_Cs (k : ℕ) : X * Cs k = L ^ (k + 1) := by + induction k with + | zero => + ext n + cases n with + | zero => simp [L] + | succ n => + rw [coeff_succ_X_mul, pow_one] + simp only [Cs, L, coeff_mk, c_zero, Nat.succ_ne_zero, if_false] + push_cast + ring + | succ k ih => + rw [Cs_succ, pow_succ, ← ih] + ring + +/-- Closed form: `c n k = s(n+1,k+1) (k+1)!/(n+1)!` with the signed Stirling number. -/ +private lemma c_eq (n k : ℕ) : + c n k = (-1 : ℚ) ^ (n + 1 + (k + 1)) * ((Nat.stirlingFirst (n + 1) (k + 1) : ℚ) * + ((k + 1).factorial : ℚ) / ((n + 1).factorial : ℚ)) := by + have h := congrArg (coeff (n + 1)) (X_mul_Cs k) + rw [coeff_succ_X_mul, ← F_eq] at h + simp only [Cs, F, coeff_mk] at h + rw [h] + ring + +/-- Marcus's conjecture holds: `T(n,k) = d(n+1,k+1)` (in fact for all `n, k`). -/ +theorem result : statement := by + intro n k _ + rw [T, d, c_eq] + rcases neg_one_pow_eq_or ℚ (n + 1 + (k + 1)) with h | h + · rw [h, one_mul] + · rw [h, neg_one_mul, Rat.neg_den] + +end Math0.Frontier.A141412 + +#math0_settles Math0.Frontier.A141412.result Math0.Statements.A141412.statement diff --git a/lean/Math0/Frontier/OEIS/A144637.lean b/lean/Math0/Frontier/OEIS/A144637.lean new file mode 100644 index 0000000..b4f51d0 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A144637.lean @@ -0,0 +1,386 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A144637 +import Math0.Audit + +/-! +# A144637: `(1/18) 6^n a(n) / n!` is odd iff `n = 2^k`, `k ≥ 1` + +We prove Peter Bala's conjecture for column `2` of A144633. + +**Composition.** Let `f(x) = x + x^2/2 + x^3/6`. Row `d` of A144385 has e.g.f. `f^d / d!` +(`fS_pow`, by comparing derivatives with the A144385 recurrence). The defining relation of the +inverse matrix, `∑_j T(j,2) S(j,n) = [n = 2]`, says exactly that the e.g.f. +`A(x) = ∑ a(n) x^n / n!` satisfies `A(f(x)) = x^2/2` (`subst_Aser`, using Mathlib's +`PowerSeries.subst`). Since `(x^2/2)` and `f` satisfy `2u^3 + 3u^2 + 18(1+f)u = 9f^2` with +`u = x^2/2`, and substitution of `f` is injective (triangular with unit diagonal), we get +`2A^3 + 3A^2 + 18(1+x)A = 9x^2` (`Aser_cubic`). + +**Integer recursion.** With `Y(x) = A(6x)/18 = ∑ y(n) x^n` this becomes +`Y = x^2 - 6xY - 3Y^2 - 36Y^3` (`Yser_cubic`). As `y(0) = 0`, the coefficient of `x^n` on the +right only involves `y(i)` with `i < n`, so every `y(n)` is an integer (`y_mem`) and `Y` lifts to +`Z ∈ ℤ[[x]]` with the same equation. + +**Parity.** Reducing mod `2` gives `W = x^2 + W^2` in `𝔽₂[[x]]`, and in characteristic `2`, +`[x^n] W^2 = [2 ∣ n] w(n/2)`. Hence `w(n) = [n = 2] + [2 ∣ n] w(n/2)` with `w(0) = 0`, and +strong induction gives `w(n) = 1 ↔ n = 2^k` with `k ≥ 1` (`parity`). +-/ + +namespace Math0.Frontier.A144637 +open Math0.Statements.A144637 +open PowerSeries Nat + +/-- `f(x) = x + x^2/2 + x^3/6`, the e.g.f. of a single block of size `1`, `2` or `3`. -/ +private noncomputable def fS : ℚ⟦X⟧ := X + C (1 / 2 : ℚ) * X ^ 2 + C (1 / 6 : ℚ) * X ^ 3 + +/-- The coefficients of `f`. -/ +private lemma coeff_fS (n : ℕ) : coeff n fS = + if n = 1 then 1 else if n = 2 then 1 / 2 else if n = 3 then 1 / 6 else 0 := by + simp only [fS, map_add, coeff_C_mul, coeff_X_pow, coeff_X] + rcases n with _ | _ | _ | _ | n <;> simp + +/-- `f(0) = 0`. -/ +private lemma constantCoeff_fS : constantCoeff fS = 0 := by + rw [← coeff_zero_eq_constantCoeff_apply, coeff_fS]; simp + +/-- `f' = 1 + x + x^2/2`. -/ +private lemma derivative_fS : d⁄dX ℚ fS = 1 + X + C (1 / 2 : ℚ) * X ^ 2 := by + ext n + rw [coeff_derivative, coeff_fS] + simp only [map_add, coeff_C_mul, coeff_X_pow, coeff_X, coeff_one] + rcases n with _ | _ | _ | n + · norm_num + · norm_num + · norm_num + · split_ifs <;> first | (exfalso; omega) | norm_num + +/-- The exact halving `(m+2)(m+1)/2` in `ℕ`, cast to `ℚ`. -/ +private lemma cast_half (m : ℕ) : + (((m + 2) * (m + 1) / 2 : ℕ) : ℚ) = (m + 2) * (m + 1) / 2 := by + have h : 2 ∣ (m + 2) * (m + 1) := by + rw [mul_comm]; exact even_iff_two_dvd.mp (Nat.even_mul_succ_self (m + 1)) + rw [Nat.cast_div h (by norm_num)] + push_cast; ring + +/-- `S(d+1, 0) = 0`. -/ +private lemma S_zero_right (d : ℕ) : S (d + 1) 0 = 0 := S_eq_zero_of_lt (by omega) + +/-- Row `d` of A144385 has e.g.f. `f^d / d!`: `f^d = d! · ∑ S(d,k) x^k / k!`. Proved by +comparing derivatives, using the A144385 recurrence `S_succ`. -/ +private lemma fS_pow (d : ℕ) : + fS ^ d = C (d ! : ℚ) * mk (fun k => (S d k : ℚ) / (k ! : ℚ)) := by + induction d with + | zero => + ext k + rw [pow_zero, coeff_one, coeff_C_mul, coeff_mk, S_zero] + rcases k with _ | k <;> simp + | succ d ih => + apply derivative.ext + · rw [derivative_pow, Nat.add_sub_cancel, ih, derivative_fS] + set G := mk (fun k => (S d k : ℚ) / (k ! : ℚ)) with hG + have e : + ((d + 1 : ℕ) : ℚ⟦X⟧) * (C (d ! : ℚ) * G) * (1 + X + C (1 / 2 : ℚ) * X ^ 2) = + C (((d + 1 : ℕ) : ℚ) * d !) * (G + X * G + C (1 / 2 : ℚ) * (X ^ 2 * G)) := by + simp only [map_mul, map_natCast]; ring + rw [e] + ext k + rw [coeff_derivative, coeff_C_mul, coeff_C_mul, coeff_mk, S_succ, map_add, map_add, + coeff_C_mul, coeff_X_pow_mul'] + rcases k with _ | _ | k + · simp only [coeff_zero_X_mul, hG, coeff_mk] + simp [Nat.factorial] + · simp only [coeff_succ_X_mul, hG, coeff_mk] + simp [Nat.factorial] + ring + · simp only [coeff_succ_X_mul, hG, coeff_mk] + rw [if_pos (by omega), if_pos (by omega), if_pos (by omega), if_pos (by omega), + show k + 1 + 1 + 1 - 1 = k + 2 by omega, show k + 1 + 1 + 1 - 2 = k + 1 by omega, + show k + 1 + 1 + 1 - 3 = k by omega, show k + 1 + 1 - 2 = k by omega] + push_cast + rw [cast_half] + simp only [Nat.factorial_succ] + push_cast + field_simp + ring + · rw [map_pow, constantCoeff_fS, map_mul, constantCoeff_C, + ← coeff_zero_eq_constantCoeff_apply (mk _), coeff_mk, S_zero_right] + simp + +/-- `f` can be substituted into power series (its constant term is `0`). -/ +private lemma hasSubst_fS : HasSubst fS := HasSubst.of_constantCoeff_zero' constantCoeff_fS + +/-- `[x^k] f^d = d! S(d,k) / k!`. -/ +private lemma coeff_fS_pow (d k : ℕ) : + coeff k (fS ^ d) = (d ! : ℚ) * (S d k : ℚ) / (k ! : ℚ) := by + rw [fS_pow, coeff_C_mul, coeff_mk]; ring + +/-- The coefficients of the composition `Q(f(x))`, as a finite sum. -/ +private lemma coeff_subst_fS (Q : ℚ⟦X⟧) (n : ℕ) : + coeff n (Q.subst fS) = + ∑ d ∈ Finset.range (n + 1), coeff d Q * ((d ! : ℚ) * S d n / n !) := by + rw [coeff_subst' hasSubst_fS, finsum_eq_sum_of_support_subset (s := Finset.range (n + 1))] + · simp only [coeff_fS_pow, smul_eq_mul] + · intro d hd + rw [Function.mem_support] at hd + simp only [Finset.coe_range, Set.mem_Iio] + by_contra h + apply hd + rw [coeff_fS_pow, S_eq_zero_of_lt (by omega)] + simp + +/-- Composition with `f` is injective: the system is triangular with unit diagonal +(`S(n,n) = 1`). -/ +private lemma subst_fS_inj (Q : ℚ⟦X⟧) (h : Q.subst fS = 0) : Q = 0 := by + ext n + induction n using Nat.strong_induction_on with + | _ n ih => + have e := coeff_subst_fS Q n + rw [h, map_zero, Finset.sum_range_succ, Finset.sum_eq_zero + (fun d hd => by rw [ih d (Finset.mem_range.mp hd), map_zero, zero_mul]), S_self, + Nat.cast_one, mul_one, div_self (by positivity), mul_one, zero_add] at e + rw [map_zero, ← e] + +/-- `A(x) = ∑ a(n) x^n / n!`, the e.g.f. of column `2` of A144633. -/ +private noncomputable def Aser : ℚ⟦X⟧ := mk (fun n => (a n : ℚ) / (n ! : ℚ)) + +/-- `A(f(x)) = x^2/2`: this is exactly the defining relation `∑_j T(j,2) S(j,n) = [n = 2]` +of the inverse matrix (`sum_T_mul_S`). -/ +private lemma subst_Aser : Aser.subst fS = C (1 / 2 : ℚ) * X ^ 2 := by + ext n + rw [coeff_subst_fS, coeff_C_mul, coeff_X_pow] + have key := sum_T_mul_S 2 n (n + 1) (Nat.lt_succ_self n) + have e : ∑ d ∈ Finset.range (n + 1), coeff d Aser * ((d ! : ℚ) * S d n / n !) = + ((∑ d ∈ Finset.range (n + 1), T d 2 * (S d n : ℤ) : ℤ) : ℚ) / n ! := by + rw [Int.cast_sum, Finset.sum_div] + apply Finset.sum_congr rfl + intro d _ + simp only [Aser, coeff_mk, a] + push_cast + field_simp + rw [e, key] + by_cases hn : n = 2 + · subst hn; norm_num [Nat.factorial] + · rw [if_neg (Ne.symm hn), if_neg hn]; simp + +/-- The algebraic equation `2A^3 + 3A^2 + 18(1+x)A = 9x^2`: substituting `f` turns it into a +polynomial identity (since `A(f) = x^2/2`), and substitution by `f` is injective. -/ +private lemma Aser_cubic : + 2 * Aser ^ 3 + 3 * Aser ^ 2 + 18 * (1 + X) * Aser - 9 * X ^ 2 = 0 := by + apply subst_fS_inj + rw [← coe_substAlgHom hasSubst_fS] + simp only [map_sub, map_add, map_mul, map_pow, map_ofNat, map_one, substAlgHom_X] + rw [coe_substAlgHom, subst_Aser, fS] + have hu : 2 * C (1 / 2 : ℚ) = 1 := by + rw [← map_ofNat C 2, ← map_mul]; norm_num + have hv : 6 * C (1 / 6 : ℚ) = 1 := by + rw [← map_ofNat C 6, ← map_mul]; norm_num + set u := C (1 / 2 : ℚ) + set v := C (1 / 6 : ℚ) + linear_combination (6*X^6*u^2*v + 18*X^6*u*v^2 + 54*X^6*v^3 + 36*X^4*u*v + 108*X^4*v^2 + + 54*X^2*v) * hu + (-2*X^6*u^3 - 6*X^6*u^2*v - 18*X^6*u*v^2 + 9*X^6*v^2 - 12*X^4*u^2 - + 36*X^4*u*v + 18*X^4*v - 18*X^2*u + 9*X^2) * hv + +/-- `Y(x) = ∑ y(n) x^n = A(6x)/18`. -/ +private noncomputable def Yser : ℚ⟦X⟧ := mk (fun n => y n) + +/-- `Y(x) = A(6x)/18`. -/ +private lemma Yser_eq : Yser = C (1 / 18 : ℚ) * rescale (6 : ℚ) Aser := by + ext n + simp only [Yser, Aser, y, coeff_mk, coeff_C_mul, coeff_rescale] + ring + +/-- `Y = x^2 - 6xY - 3Y^2 - 36Y^3`. -/ +private lemma Yser_cubic : Yser = X ^ 2 - C (6 : ℚ) * (X * Yser) - C (3 : ℚ) * (Yser * Yser) - + C (36 : ℚ) * (Yser * (Yser * Yser)) := by + have h := congrArg (rescale (6 : ℚ)) Aser_cubic + simp only [map_sub, map_add, map_mul, map_pow, map_ofNat, map_one, rescale_X, map_zero] at h + have h18 : 18 * C (1 / 18 : ℚ) = 1 := by + rw [← map_ofNat C 18, ← map_mul]; norm_num + have h6 : C (6 : ℚ) = 6 := map_ofNat C 6 + have h3 : C (3 : ℚ) = 3 := map_ofNat C 3 + have h36 : C (36 : ℚ) = 36 := map_ofNat C 36 + rw [h6, h3, h36, Yser_eq] + set c := C (1 / 18 : ℚ) + set B := rescale (6 : ℚ) Aser + have h324 : (324 : ℚ⟦X⟧) * (c * B - (X ^ 2 - 6 * (X * (c * B)) - 3 * (c * B * (c * B)) - + 36 * (c * B * (c * B * (c * B))))) = 0 := by + linear_combination h + B * (648 * B ^ 2 * c ^ 2 + 36 * B ^ 2 * c + 2 * B ^ 2 + 54 * B * c + + 3 * B + 108 * X + 18) * h18 + have hne : (324 : ℚ⟦X⟧) ≠ 0 := by + intro h0 + have := congrArg (coeff 0) h0 + rw [← map_ofNat C 324, coeff_C, if_pos rfl, map_zero] at this + norm_num at this + exact sub_eq_zero.mp ((mul_eq_zero.mp h324).resolve_left hne) + +/-- `y(0) = 0`. -/ +private lemma y_zero : y 0 = 0 := by + simp [y, a, T_eq_zero_of_lt (show 0 < 2 by norm_num)] + +/-- The subring of rationals that are integers. -/ +private abbrev Zr : Subring ℚ := (Int.castRingHom ℚ).range + +/-- The coefficients of `Y` are the `y(n)`. -/ +private lemma coeff_Yser (n : ℕ) : coeff n Yser = y n := coeff_mk _ _ + +/-- `[x^j] Y^2` is an integer when `y(i)` is for all `i < j` (as `y(0) = 0`). -/ +private lemma sq_mem (j : ℕ) (hj : ∀ i < j, y i ∈ Zr) : coeff j (Yser * Yser) ∈ Zr := by + rw [coeff_mul] + refine Subring.sum_mem _ fun p hp => ?_ + rw [Finset.HasAntidiagonal.mem_antidiagonal] at hp + rw [coeff_Yser, coeff_Yser] + by_cases h1 : p.1 = 0 + · rw [h1, y_zero, zero_mul]; exact Subring.zero_mem _ + by_cases h2 : p.2 = 0 + · rw [h2, y_zero, mul_zero]; exact Subring.zero_mem _ + exact Subring.mul_mem _ (hj _ (by omega)) (hj _ (by omega)) + +/-- `[x^j] Y^3` is an integer when `y(i)` is for all `i < j` (as `y(0) = 0`). -/ +private lemma cube_mem (j : ℕ) (hj : ∀ i < j, y i ∈ Zr) : + coeff j (Yser * (Yser * Yser)) ∈ Zr := by + rw [coeff_mul] + refine Subring.sum_mem _ fun p hp => ?_ + rw [Finset.HasAntidiagonal.mem_antidiagonal] at hp + rw [coeff_Yser] + by_cases h1 : p.1 = 0 + · rw [h1, y_zero, zero_mul]; exact Subring.zero_mem _ + by_cases h2 : p.2 = 0 + · rw [h2, coeff_zero_eq_constantCoeff_apply, map_mul, ← coeff_zero_eq_constantCoeff_apply, + coeff_Yser, y_zero, zero_mul, mul_zero] + exact Subring.zero_mem _ + exact Subring.mul_mem _ (hj _ (by omega)) (sq_mem _ fun i hi => hj i (by omega)) + +/-- Every `y(n)` is an integer (strong induction on the recursion from `Yser_cubic`). -/ +private lemma y_mem (n : ℕ) : y n ∈ Zr := by + induction n using Nat.strong_induction_on with + | _ n ih => + rw [← coeff_Yser, Yser_cubic] + simp only [map_sub, coeff_C_mul] + refine Subring.sub_mem _ (Subring.sub_mem _ (Subring.sub_mem _ ?_ ?_) ?_) ?_ + · rw [coeff_X_pow]; split_ifs + · exact Subring.one_mem _ + · exact Subring.zero_mem _ + · refine Subring.mul_mem _ ⟨6, by simp⟩ ?_ + rcases n with _ | n + · rw [coeff_zero_X_mul]; exact Subring.zero_mem _ + · rw [coeff_succ_X_mul, coeff_Yser]; exact ih n (by omega) + · exact Subring.mul_mem _ ⟨3, by simp⟩ (sq_mem n ih) + · exact Subring.mul_mem _ ⟨36, by simp⟩ (cube_mem n ih) + +/-- `Y` is the image of an integer power series `Z` satisfying the same cubic equation. -/ +private lemma exists_Z : ∃ Z : ℤ⟦X⟧, map (Int.castRingHom ℚ) Z = Yser ∧ + Z = X ^ 2 - 6 * X * Z - 3 * Z ^ 2 - 36 * Z ^ 3 := by + choose z hz using fun n => y_mem n + refine ⟨mk z, ?_, ?_⟩ + · ext n; rw [coeff_map, coeff_mk, hz, coeff_Yser] + · have hm : map (Int.castRingHom ℚ) (mk z) = Yser := by + ext n; rw [coeff_map, coeff_mk, hz, coeff_Yser] + apply map_injective (Int.castRingHom ℚ) Int.cast_injective + simp only [map_sub, map_mul, map_pow, map_ofNat, map_X, hm] + have h6 : C (6 : ℚ) = 6 := map_ofNat C 6 + have h3 : C (3 : ℚ) = 3 := map_ofNat C 3 + have h36 : C (36 : ℚ) = 36 := map_ofNat C 36 + have := Yser_cubic + rw [h6, h3, h36] at this + linear_combination this + +/-- In characteristic `2`, `[x^n] W^2 = [2 ∣ n] · [x^(n/2)] W` (Frobenius, via +`ZMod.expand_card` on a truncation). -/ +private lemma coeff_mul_self_two (W : (ZMod 2)⟦X⟧) (n : ℕ) : + coeff n (W * W) = if 2 ∣ n then coeff (n / 2) W else 0 := by + rw [coeff_mul_eq_coeff_trunc_mul_trunc W W (Nat.lt_succ_self n), ← Polynomial.coe_mul, + Polynomial.coeff_coe, ← sq, ← ZMod.expand_card, Polynomial.coeff_expand two_pos, + coeff_trunc] + split_ifs with h1 h2 + · rfl + · exfalso; apply h2; omega + · rfl + +/-- If `W ∈ 𝔽₂[[x]]` has `W(0) = 0` and `W = x^2 + W^2`, then `[x^n] W = 1` exactly when +`n = 2^k` with `k ≥ 1`. -/ +private lemma parity (W : (ZMod 2)⟦X⟧) (h0 : coeff 0 W = 0) (hW : W = X ^ 2 + W * W) + (n : ℕ) : + coeff n W = 1 ↔ ∃ k : ℕ, 1 ≤ k ∧ n = 2 ^ k := by + have hrec : ∀ m, coeff m W = (if m = 2 then 1 else 0) + + (if 2 ∣ m then coeff (m / 2) W else 0) := by + intro m + conv_lhs => rw [hW] + rw [map_add, coeff_X_pow, coeff_mul_self_two] + have h1 : coeff 1 W = 0 := by rw [hrec]; simp + induction n using Nat.strong_induction_on with + | _ n ih => + rcases n with _ | _ | _ | n + · rw [h0] + constructor + · intro h; exact absurd h (by decide) + · rintro ⟨k, -, hk⟩; exact absurd hk.symm (pow_ne_zero _ (by norm_num)) + · rw [h1] + constructor + · intro h; exact absurd h (by decide) + · rintro ⟨k, hk1, hk⟩ + have : 2 ≤ 2 ^ k := by + calc 2 = 2 ^ 1 := by norm_num + _ ≤ 2 ^ k := Nat.pow_le_pow_right (by norm_num) hk1 + omega + · rw [hrec, if_pos rfl, if_pos (by norm_num), show (0 + 1 + 1) / 2 = 1 by norm_num, h1] + simp only [add_zero, true_iff] + exact ⟨1, le_rfl, rfl⟩ + · rw [hrec, if_neg (by omega), zero_add] + by_cases hd : 2 ∣ n + 1 + 1 + 1 + · have ih' : coeff ((n + 1 + 1 + 1) / 2) W = 1 ↔ + ∃ k : ℕ, 1 ≤ k ∧ (n + 1 + 1 + 1) / 2 = 2 ^ k := ih _ (by omega) + rw [if_pos hd, ih'] + obtain ⟨m, hm⟩ := hd + rw [hm, Nat.mul_div_cancel_left _ (by norm_num)] + constructor + · rintro ⟨k, hk1, hk⟩ + exact ⟨k + 1, by omega, by rw [hk, pow_succ]; ring⟩ + · rintro ⟨k, hk1, hk⟩ + obtain ⟨j, rfl⟩ : ∃ j, k = j + 1 := ⟨k - 1, by omega⟩ + refine ⟨j, ?_, ?_⟩ + · rcases j with _ | j + · simp at hk; omega + · omega + · rw [pow_succ] at hk; omega + · rw [if_neg hd] + constructor + · intro h; exact absurd h (by decide) + · rintro ⟨k, hk1, hk⟩ + exfalso + apply hd + rw [hk] + exact dvd_pow_self 2 (by omega) + +/-- Bala's conjecture holds: `y(n)` is an odd integer iff `n = 2^k` with `k ≥ 1`. -/ +theorem result : statement := by + obtain ⟨Z, hZ, hZc⟩ := exists_Z + set W := map (Int.castRingHom (ZMod 2)) Z with hWdef + have hW : W = X ^ 2 + W * W := by + have h := congrArg (map (Int.castRingHom (ZMod 2))) hZc + simp only [map_sub, map_mul, map_pow, map_ofNat, map_X] at h + have h2 : (2 : (ZMod 2)⟦X⟧) = 0 := by + rw [← map_ofNat C 2] + rw [show (OfNat.ofNat 2 : ZMod 2) = 0 by decide, map_zero] + linear_combination h - (3 * X * W + 2 * W ^ 2 + 18 * W ^ 3) * h2 + have hz : ∀ n, ((coeff n Z : ℤ) : ℚ) = y n := by + intro n + rw [← coeff_Yser, ← hZ, coeff_map]; rfl + have hw : ∀ n, coeff n W = ((coeff n Z : ℤ) : ZMod 2) := by + intro n; rw [hWdef, coeff_map]; rfl + have h0 : coeff 0 W = 0 := by + rw [hw] + have : ((coeff 0 Z : ℤ) : ℚ) = ((0 : ℤ) : ℚ) := by rw [hz, y_zero]; simp + rw [Int.cast_injective this]; simp + intro n + rw [← parity W h0 hW n, hw, ZMod.intCast_eq_one_iff_odd] + constructor + · rintro ⟨m, hm, hy⟩ + have : coeff n Z = m := Int.cast_injective ((hz n).trans hy) + rw [this]; exact hm + · intro h + exact ⟨coeff n Z, h, (hz n).symm⟩ + +end Math0.Frontier.A144637 + +#math0_settles Math0.Frontier.A144637.result Math0.Statements.A144637.statement diff --git a/lean/Math0/Frontier/OEIS/A160848.lean b/lean/Math0/Frontier/OEIS/A160848.lean new file mode 100644 index 0000000..ef07a7a --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A160848.lean @@ -0,0 +1,299 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A160848 +import Math0.Audit + +/-! +# Barker's order-20 recurrence for the lines through an `8 × n` grid holds + +We prove Colin Barker's conjecture for A160848: for all `n > 21`, +`a(n) = -a(n-2) + a(n-5) + a(n-6) + 2a(n-7) + a(n-8) + a(n-9) - a(n-11) - a(n-12) - 2a(n-13) +- a(n-14) - a(n-15) + a(n-18) + a(n-20)`. + +**Column decomposition.** By `a_eq_aFast`, `a(n)` counts pairs `i < j < 8n` with `goodF i j` +(the two smallest grid points of a line). Adding the column `x = n` adds +`D(n) = 1 + ∑_{x rfl + +/-- `countI j (m + k)` splits off the last `k` candidates `i`. -/ +private lemma countI_add (j m k : ℕ) : + countI j (m + k) = countI j m + ∑ y ∈ Finset.range k, (goodF (m + y) j).toNat := by + induction k with + | zero => simp + | succ k ih => rw [← Nat.add_assoc, countI_succ, ih, Finset.sum_range_succ, Nat.add_assoc] + +/-- `countI j (8n)` as a sum over the columns `x < n` and rows `y < 8`. -/ +private lemma countI_mul (j n : ℕ) : + countI j (8 * n) = + ∑ x ∈ Finset.range n, ∑ y ∈ Finset.range 8, (goodF (8 * x + y) j).toNat := by + induction n with + | zero => rfl + | succ n ih => rw [Nat.mul_succ, countI_add, ih]; exact (Finset.sum_range_succ _ n).symm + +/-- `countJ (m + k)` splits off the last `k` values of `j`. -/ +private lemma countJ_add (m k : ℕ) : + countJ (m + k) = countJ m + ∑ t ∈ Finset.range k, countI (m + t) (m + t) := by + induction k with + | zero => simp + | succ k ih => rw [← Nat.add_assoc, countJ_succ, ih, Finset.sum_range_succ, Nat.add_assoc] + +/-- The number of good pairs whose larger point lies in column `n`. -/ +private def D (n : ℕ) : ℕ := ∑ t ∈ Finset.range 8, countI (8 * n + t) (8 * n + t) + +/-- Adding the column `n` adds `D n` lines. -/ +private lemma aFast_succ (n : ℕ) : aFast (n + 1) = aFast n + D n := by + unfold aFast D + rw [Nat.mul_succ, countJ_add] + +/-- The number of good pairs from column `x` to column `n`. -/ +private def C (n x : ℕ) : ℕ := + ∑ t ∈ Finset.range 8, ∑ y ∈ Finset.range 8, (goodF (8 * x + y) (8 * n + t)).toNat + +/-- `goodF` between the points `(x, y)` and `(n, t)` of the grid. -/ +private lemma goodF_eq {x y n t : ℕ} (hy : y < 8) (ht : t < 8) : + goodF (8 * x + y) (8 * n + t) = decide (Nat.gcd (n - x) (t - y + (y - t)) = 1 ∧ + ¬(n ≤ 2 * x ∧ t ≤ 2 * y ∧ 2 * y < 8 + t)) := by + have h1 : (8 * x + y) / 8 = x := by omega + have h2 : (8 * x + y) % 8 = y := by omega + have h3 : (8 * n + t) / 8 = n := by omega + have h4 : (8 * n + t) % 8 = t := by omega + rw [goodF, h1, h2, h3, h4] + +/-- The pairs inside column `n` contribute exactly one line (the vertical one). -/ +private lemma diag_part (n : ℕ) : + ∑ t ∈ Finset.range 8, ∑ y ∈ Finset.range t, (goodF (8 * n + y) (8 * n + t)).toNat = 1 := by + have : ∀ t ∈ Finset.range 8, + ∑ y ∈ Finset.range t, (goodF (8 * n + y) (8 * n + t)).toNat = + ∑ y ∈ Finset.range t, + (decide (Nat.gcd 0 (t - y + (y - t)) = 1 ∧ ¬(t ≤ 2 * y ∧ 2 * y < 8 + t))).toNat := by + intro t ht + apply Finset.sum_congr rfl + intro y hy + rw [Finset.mem_range] at ht hy + rw [goodF_eq (by omega) ht] + simp [show n ≤ 2 * n by omega] + rw [Finset.sum_congr rfl this] + decide + +/-- `D n = ∑_{x ?_ + rw [countI_add, countI_mul, Finset.sum_comm (s := Finset.range n)] + + +/-- The indicator of `gcd(a, b) = 1`. -/ +private def u (a b : ℕ) : ℕ := (decide (Nat.gcd a b = 1)).toNat + +/-- `G a`: the number of row pairs `(t, y)` with `gcd(a, |t-y|) = 1`. -/ +private def G (a : ℕ) : ℕ := + 8 * u a 0 + 14 * u a 1 + 12 * u a 2 + 10 * u a 3 + 8 * u a 4 + 6 * u a 5 + 4 * u a 6 + 2 * u a 7 + +/-- `Gb a`: the number of row pairs `(t, y)` with `gcd(a, |t-y|) = 1` and +`t ≤ 2y < 8 + t` (the point `2(x,y) - (n,t)` has a valid row). -/ +private def Gb (a : ℕ) : ℕ := 8 * u a 0 + 12 * u a 1 + 8 * u a 2 + 4 * u a 3 + +/-- Closed form of `C n x` in terms of `a = n - x`. -/ +private lemma C_eq (n x : ℕ) : + (C n x : ℤ) = G (n - x) - if n ≤ 2 * x then (Gb (n - x) : ℤ) else 0 := by + have hC : C n x = ∑ t ∈ Finset.range 8, ∑ y ∈ Finset.range 8, + (decide (Nat.gcd (n - x) (t - y + (y - t)) = 1 ∧ + ¬(n ≤ 2 * x ∧ t ≤ 2 * y ∧ 2 * y < 8 + t))).toNat := by + unfold C + refine Finset.sum_congr rfl fun t ht => Finset.sum_congr rfl fun y hy => ?_ + rw [goodF_eq (Finset.mem_range.1 hy) (Finset.mem_range.1 ht)] + rw [hC] + generalize n - x = a + by_cases hs : n ≤ 2 * x + · simp [hs, Finset.sum_range_succ, G, Gb, u] + ring + · simp [hs, Finset.sum_range_succ, G, u] + ring + + +/-- `hcl m = G m - [m even, m ≥ 2] Gb (m/2)`: the second difference of `a`. -/ +private def hcl (m : ℕ) : ℤ := (G m : ℤ) - if m % 2 = 0 ∧ 2 ≤ m then (Gb (m / 2) : ℤ) else 0 + +/-- Shifting both columns by one changes `C` only when `n = 2x + 1`. -/ +private lemma C_succ_sub (n x : ℕ) : + (C (n + 1) (x + 1) : ℤ) - C n x = -(if n = 2 * x + 1 then (Gb (n - x) : ℤ) else 0) := by + rw [C_eq, C_eq, Nat.add_sub_add_right] + by_cases h1 : n = 2 * x + 1 + · rw [if_pos (by omega), if_neg (by omega), if_pos h1]; ring + · rw [if_neg h1] + by_cases h2 : n ≤ 2 * x + · rw [if_pos (by omega), if_pos h2]; ring + · rw [if_neg (by omega), if_neg h2]; ring + +/-- The only `x < n` with `n = 2x + 1` is `x = n / 2`, for odd `n`. -/ +private lemma sum_odd (n : ℕ) : + ∑ x ∈ Finset.range n, (if n = 2 * x + 1 then (Gb (n - x) : ℤ) else 0) = + if (n + 1) % 2 = 0 ∧ 2 ≤ n + 1 then (Gb ((n + 1) / 2) : ℤ) else 0 := by + by_cases hn : n % 2 = 1 + · rw [if_pos (by omega)] + rw [Finset.sum_eq_single (n / 2)] + · rw [if_pos (by omega), show n - n / 2 = (n + 1) / 2 by omega] + · intro x _ hx + rw [if_neg (by omega)] + · intro h + exact absurd (Finset.mem_range.2 (by omega)) h + · rw [if_neg (by omega)] + exact Finset.sum_eq_zero fun x _ => if_neg (by omega) + +/-- `D (n + 1) - D n = hcl (n + 1)`. -/ +private lemma D_succ (n : ℕ) : (D (n + 1) : ℤ) = D n + hcl (n + 1) := by + rw [D_eq, D_eq] + push_cast + rw [Finset.sum_range_succ'] + have h0 : (C (n + 1) 0 : ℤ) = G (n + 1) := by + rw [C_eq]; simp + have hs : ∑ x ∈ Finset.range n, (C (n + 1) (x + 1) : ℤ) = + ∑ x ∈ Finset.range n, (C n x : ℤ) - + ∑ x ∈ Finset.range n, (if n = 2 * x + 1 then (Gb (n - x) : ℤ) else 0) := by + rw [← Finset.sum_sub_distrib] + refine Finset.sum_congr rfl fun x _ => ?_ + linarith [C_succ_sub n x] + rw [hs, sum_odd, h0, hcl] + ring + +/-- The second difference of `a` is `hcl`. -/ +private lemma second_diff (m : ℕ) : (a (m + 2) : ℤ) - 2 * a (m + 1) + a m = hcl (m + 1) := by + rw [a_eq_aFast, a_eq_aFast, a_eq_aFast, aFast_succ (m + 1), aFast_succ m] + push_cast + rw [D_succ] + ring + +/-- `gcd(a mod K + K, b) = gcd(a, b)` when `b ∣ K`. -/ +private lemma gcd_mod_add (a b K : ℕ) (hb : b ∣ K) : Nat.gcd (a % K + K) b = Nat.gcd a b := by + have h1 : Nat.gcd (a % K + K) b = Nat.gcd ((a % K + K) % b) b := + (Nat.gcd_comm _ _).trans (Nat.gcd_rec _ _) + have h2 : Nat.gcd a b = Nat.gcd (a % b) b := (Nat.gcd_comm _ _).trans (Nat.gcd_rec _ _) + have h3 : (a % K + K) % b = a % b := by + obtain ⟨c, rfl⟩ := hb + rw [Nat.add_mul_mod_self_left, Nat.mod_mul_right_mod] + rw [h1, h2, h3] + +/-- `u` is unchanged by `a ↦ a mod K + K` when `b ∣ K`. -/ +private lemma u_mod_add (a b K : ℕ) (hb : b ∣ K) : u (a % K + K) b = u a b := by + simp only [u, gcd_mod_add a b K hb] + +/-- `gcd(a, 0) = a ≠ 1` for `a ≥ 2`. -/ +private lemma u_zero (a : ℕ) (ha : 2 ≤ a) : u a 0 = 0 := by + unfold u + simp only [Nat.gcd_zero_right] + rw [decide_eq_false (by omega)] + rfl + +/-- `G` has period `420` on `a ≥ 2`. -/ +private lemma G_period (a : ℕ) (ha : 2 ≤ a) : G (a % 420 + 420) = G a := by + unfold G + rw [u_zero a ha, u_zero _ (by omega)] + rw [u_mod_add a 1 420 (by norm_num), u_mod_add a 2 420 (by norm_num), + u_mod_add a 3 420 (by norm_num), u_mod_add a 4 420 (by norm_num), + u_mod_add a 5 420 (by norm_num), u_mod_add a 6 420 (by norm_num), + u_mod_add a 7 420 (by norm_num)] + +/-- `Gb` has period `210` on `a ≥ 2`. -/ +private lemma Gb_period (a : ℕ) (ha : 2 ≤ a) : Gb (a % 210 + 210) = Gb a := by + unfold Gb + rw [u_zero a ha, u_zero _ (by omega)] + rw [u_mod_add a 1 210 (by norm_num), u_mod_add a 2 210 (by norm_num), + u_mod_add a 3 210 (by norm_num)] + +/-- `hcl` has period `420` on `m ≥ 3`. -/ +private lemma hcl_period (m : ℕ) (hm : 3 ≤ m) : hcl (m % 420 + 420) = hcl m := by + unfold hcl + rw [G_period m (by omega)] + by_cases he : m % 2 = 0 + · rw [if_pos (by omega), if_pos (by omega), + show (m % 420 + 420) / 2 = (m / 2) % 210 + 210 by omega, Gb_period _ (by omega)] + · rw [if_neg (by omega), if_neg (by omega)] + +/-- `hcl` evaluated at a canonical representative mod `420`. -/ +private def hp (m : ℕ) : ℤ := hcl (m % 420 + 420) + +/-- For `k ≥ 3`, `hcl (N + k)` only depends on `N mod 420`. -/ +private lemma hcl_eq (N k : ℕ) (hk : 3 ≤ k) : hcl (N + k) = hp (N % 420 + k) := by + unfold hp + rw [← hcl_period (N + k) (by omega), show (N + k) % 420 = (N % 420 + k) % 420 by omega] + +set_option maxRecDepth 100000 in +/-- Kernel check: `∑_j r_j hcl(m - j) = 0` on every residue class mod `420`. -/ +private lemma key : ∀ s < 420, hp (s + 21) + 2 * hp (s + 20) + 4 * hp (s + 19) + 6 * hp (s + 18) + + 8 * hp (s + 17) + 9 * hp (s + 16) + 9 * hp (s + 15) + 7 * hp (s + 14) + 4 * hp (s + 13) + - 4 * hp (s + 11) - 7 * hp (s + 10) - 9 * hp (s + 9) - 9 * hp (s + 8) - 8 * hp (s + 7) + - 6 * hp (s + 6) - 4 * hp (s + 5) - 2 * hp (s + 4) - hp (s + 3) = 0 := by + decide +kernel + +/-- Barker's recurrence for A160848 holds for every `n > 21`. -/ +theorem result : statement := by + intro n hn + obtain ⟨N, rfl⟩ : ∃ N, n = N + 22 := ⟨n - 22, by omega⟩ + unfold Recurrence + simp only [show N + 22 - 2 = N + 20 by omega, show N + 22 - 5 = N + 17 by omega, + show N + 22 - 6 = N + 16 by omega, show N + 22 - 7 = N + 15 by omega, + show N + 22 - 8 = N + 14 by omega, show N + 22 - 9 = N + 13 by omega, + show N + 22 - 11 = N + 11 by omega, show N + 22 - 12 = N + 10 by omega, + show N + 22 - 13 = N + 9 by omega, show N + 22 - 14 = N + 8 by omega, + show N + 22 - 15 = N + 7 by omega, show N + 22 - 18 = N + 4 by omega, + show N + 22 - 20 = N + 2 by omega] + have e : ∀ k, 2 ≤ k → (a (N + k + 2) : ℤ) - 2 * a (N + k + 1) + a (N + k) = + hp (N % 420 + (k + 1)) := by + intro k hk + rw [second_diff, Nat.add_assoc, hcl_eq N (k + 1) (by omega)] + have e0 := e 20 (by norm_num) + have e1 := e 19 (by norm_num) + have e2 := e 18 (by norm_num) + have e3 := e 17 (by norm_num) + have e4 := e 16 (by norm_num) + have e5 := e 15 (by norm_num) + have e6 := e 14 (by norm_num) + have e7 := e 13 (by norm_num) + have e8 := e 12 (by norm_num) + have e10 := e 10 (by norm_num) + have e11 := e 9 (by norm_num) + have e12 := e 8 (by norm_num) + have e13 := e 7 (by norm_num) + have e14 := e 6 (by norm_num) + have e15 := e 5 (by norm_num) + have e16 := e 4 (by norm_num) + have e17 := e 3 (by norm_num) + have e18 := e 2 (by norm_num) + have hk := key (N % 420) (Nat.mod_lt _ (by norm_num)) + norm_num at e0 e1 e2 e3 e4 e5 e6 e7 e8 e10 e11 e12 e13 e14 e15 e16 e17 e18 + linear_combination e0 + 2 * e1 + 4 * e2 + 6 * e3 + 8 * e4 + 9 * e5 + 9 * e6 + 7 * e7 + 4 * e8 + - 4 * e10 - 7 * e11 - 9 * e12 - 9 * e13 - 8 * e14 - 6 * e15 - 4 * e16 - 2 * e17 - e18 + hk + +end Math0.Frontier.A160848 + +#math0_settles Math0.Frontier.A160848.result Math0.Statements.A160848.statement diff --git a/lean/Math0/Frontier/OEIS/A172164.lean b/lean/Math0/Frontier/OEIS/A172164.lean new file mode 100644 index 0000000..b263a3a --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A172164.lean @@ -0,0 +1,423 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A172164 +import Math0.Audit + +/-! +# A172164: the second differences of the turns of the spiral of Theodorus are 18, 19, 20, 21 + +We prove Dumortier's conjecture: every term `a n` (`n ≥ 2`) lies in `{18, 19, 20, 21}`. + +**Two one-step inequalities.** With `p = √k`, `q = √(k+1)`: +`arctan (1/q) ≤ 1/q ≤ 2(q - p)` (since `2pq ≤ p² + q²`), so `E k = S k - 2√k` is antitone; and for +`k ≥ 1`, `arctan (1/q) ≥ 1/q - 1/(3q³) ≥ 2(q - p) + 2/q - 2/p`, so `E k - 2/√k` is monotone. +Hence on a window `K₀ ≤ k`: `E k ≤ e := E K₀`, and up to `K₂`: `E k ≥ e - V`, `V = 2/√K₀ - 2/√K₂`. + +**Counting.** For a threshold `θ` let `K` be the last index with `S K ≤ θ` and `L` the first with +`θ ≤ S L` (`L = K` if `S K = θ`, else `L = K + 1`). The complete triangles of turn `m` are +`L_{m-1} + 1, …, K_m`, so `a n = (K_n - L_{n-1}) - (K_{n-1} - L_{n-2})`. + +**Squeeze.** With `T_i = 2π(n-2+i) - e` the window bounds give `2√K_i ≤ T_i + V`, +`2√(K_i+1) > T_i`, and `2√K_i ≥ T_i` when `S K_i` hits the threshold. Squaring and using +`T₂² + T₀² - 2T₁² = 8π²` gives `|a n - 2π²| < 2 + V T₁ + V²/2`, and for `n ≥ 71` (where +`√K₀ ≥ 200`) the error `V T₁ + V²/2 ≤ 0.13`, while `2π² ≈ 19.74`. So `17 < a n < 22`. +The terms `n ≤ 70` are the kernel-checked data `a_data` of the statement file. +-/ + +namespace Math0.Frontier.A172164 +open Math0.Statements.A172164 +open Real Finset + +/-- One triangle angle is at most the increment of `2√k`: `arctan (1/√(k+1)) ≤ 2(√(k+1) - √k)`, +from `arctan x ≤ x` and `2√k √(k+1) ≤ 2k + 1`. -/ +private theorem step_upper (k : ℕ) : + arctan (1 / √((k : ℝ) + 1)) ≤ 2 * (√((k : ℝ) + 1) - √(k : ℝ)) := by + have hq : 0 < √((k : ℝ) + 1) := Real.sqrt_pos.2 (by positivity) + have hp : 0 ≤ √(k : ℝ) := Real.sqrt_nonneg _ + have hq2 : √((k : ℝ) + 1) ^ 2 = (k : ℝ) + 1 := Real.sq_sqrt (by positivity) + have hp2 : √(k : ℝ) ^ 2 = (k : ℝ) := Real.sq_sqrt (by positivity) + set q := √((k : ℝ) + 1) + set p := √(k : ℝ) + have hq1 : 1 ≤ q := by + rw [Real.one_le_sqrt]; have : (0 : ℝ) ≤ k := by positivity + linarith + have h1 : arctan (1 / q) ≤ 1 / q := by + rcases eq_or_lt_of_le hq1 with h | h + · rw [← h, div_one, Real.arctan_one] + have := Real.pi_lt_d2 + linarith + · have h' : 1 / q < 1 := by rw [div_lt_one hq]; exact h + have := (arctan_alt_bounds (x := 1 / q) (by positivity) h' 0).2 + simpa using this + have h2 : 1 / q ≤ 2 * (q - p) := by + rw [div_le_iff₀ hq] + nlinarith [sq_nonneg (q - p)] + linarith + +/-- For `k ≥ 1`, `arctan (1/√(k+1)) ≥ 2(√(k+1) - √k) + 2/√(k+1) - 2/√k`, from +`arctan x ≥ x - x³/3` and an algebraic identity in `p = √k`, `q = √(k+1)`. -/ +private theorem step_lower (k : ℕ) (hk : 1 ≤ k) : + 2 * (√((k : ℝ) + 1) - √(k : ℝ)) + 2 / √((k : ℝ) + 1) - 2 / √(k : ℝ) ≤ + arctan (1 / √((k : ℝ) + 1)) := by + have hk1 : (1 : ℝ) ≤ k := by exact_mod_cast hk + have hq : 0 < √((k : ℝ) + 1) := Real.sqrt_pos.2 (by positivity) + have hp : 0 < √(k : ℝ) := Real.sqrt_pos.2 (by positivity) + have hq2 : √((k : ℝ) + 1) ^ 2 = (k : ℝ) + 1 := Real.sq_sqrt (by positivity) + have hp2 : √(k : ℝ) ^ 2 = (k : ℝ) := Real.sq_sqrt (by positivity) + set q := √((k : ℝ) + 1) + set p := √(k : ℝ) + have hpq : p < q := by nlinarith + have hx1 : 1 / q < 1 := by + rw [div_lt_one hq]; nlinarith + have h1 := (arctan_alt_bounds (x := 1 / q) (by positivity) hx1 1).1 + simp [Finset.sum_range_succ] at h1 + have hN : 0 < 6 * q ^ 3 - 3 * p * q ^ 2 - p - 6 * p * q ^ 3 * (q - p) := by + have e : (6 * q ^ 3 - 3 * p * q ^ 2 - p - 6 * p * q ^ 3 * (q - p)) * (q + p) = + 3 * q ^ 3 * (q - p) + q * (2 * q - p) + 1 := by + have : p ^ 2 = q ^ 2 - 1 := by rw [hp2, hq2]; ring + linear_combination (6 * p * q ^ 3 - 3 * q ^ 2 - 1) * this + have h3 : 0 < 3 * q ^ 3 * (q - p) + q * (2 * q - p) + 1 := by + have : 0 < q - p := by linarith + have : 0 < 2 * q - p := by linarith + positivity + rw [← e] at h3 + exact pos_of_mul_pos_left h3 (by linarith) + have key : 2 * (q - p) + 2 / q - 2 / p ≤ q⁻¹ - (q⁻¹) ^ 3 / 3 := by + have e : q⁻¹ - (q⁻¹) ^ 3 / 3 - (2 * (q - p) + 2 / q - 2 / p) = + (6 * q ^ 3 - 3 * p * q ^ 2 - p - 6 * p * q ^ 3 * (q - p)) / (3 * p * q ^ 3) := by + field_simp; ring + have : 0 ≤ (6 * q ^ 3 - 3 * p * q ^ 2 - p - 6 * p * q ^ 3 * (q - p)) / (3 * p * q ^ 3) := by + positivity + linarith + rw [one_div] + have h4 : (q ^ 3)⁻¹ / (2 + 1) = q⁻¹ ^ 3 / 3 := by rw [inv_pow]; norm_num + linarith + +/-- `S k - 2√k` is antitone. -/ +private theorem E_anti (k m : ℕ) (h : k ≤ m) : S m - 2 * √(m : ℝ) ≤ S k - 2 * √(k : ℝ) := by + induction m, h using Nat.le_induction with + | base => exact le_rfl + | succ m _ ih => + rw [S_succ] + have := step_upper m + push_cast + linarith + +/-- `S k - 2√k - 2/√k` is monotone on `k ≥ 1`. -/ +private theorem E_mono (k m : ℕ) (hk : 1 ≤ k) (h : k ≤ m) : + S k - 2 * √(k : ℝ) - 2 / √(k : ℝ) ≤ S m - 2 * √(m : ℝ) - 2 / √(m : ℝ) := by + induction m, h using Nat.le_induction with + | base => exact le_rfl + | succ m hm ih => + rw [S_succ] + have := step_lower m (by omega) + push_cast + linarith + +/-- `S` is unbounded. -/ +private theorem S_unbounded (θ : ℝ) : ∃ k, θ < S k := by + obtain ⟨N, hN⟩ := exists_nat_ge ((2 * |θ| + 2) ^ 2) + refine ⟨N + 2, ?_⟩ + have h1 := S_ge (N + 2) (by omega) + have h2 : 2 * |θ| + 2 ≤ √((N + 2 : ℕ) : ℝ) := by + rw [Real.le_sqrt (by positivity) (by positivity)] + push_cast + linarith + have h3 := le_abs_self θ + nlinarith [abs_nonneg θ] + +/-- One triangle adds less than `π/2`. -/ +private theorem S_lt_succ_of_le {K : ℕ} {θ : ℝ} (h : S K ≤ θ) : S (K + 1) < θ + π / 2 := by + rw [S_succ] + have := arctan_lt_pi_div_two (1 / √((K : ℝ) + 1)) + linarith + +/-- Monotonicity of `S`, in the form used for the indices. -/ +private theorem le_of_S_lt {a b : ℕ} (h : S a < S (b + 1)) : a ≤ b := by + by_contra hc + have := S_strictMono.monotone (show b + 1 ≤ a by omega) + linarith + +/-- For `θ ≥ 0`: `K` is the largest index with `S K ≤ θ`, and `L` the least index with +`θ ≤ S L`; `L = K` exactly when `S K = θ`, otherwise `L = K + 1`. -/ +private theorem exists_KL (θ : ℝ) (hθ : 0 ≤ θ) : ∃ K L : ℕ, S K ≤ θ ∧ θ < S (K + 1) ∧ + (∀ j, θ ≤ S j ↔ L ≤ j) ∧ ((L = K ∧ S K = θ) ∨ L = K + 1) := by + classical + have hex := S_unbounded θ + have hk : θ < S (Nat.find hex) := Nat.find_spec hex + have hk0 : Nat.find hex ≠ 0 := by + intro h; rw [h, S_zero] at hk; linarith + obtain ⟨K, hK⟩ : ∃ K, Nat.find hex = K + 1 := ⟨Nat.find hex - 1, by omega⟩ + have hKle : S K ≤ θ := by + by_contra h; rw [not_le] at h + exact Nat.find_min hex (show K < Nat.find hex by omega) h + rw [hK] at hk + rcases eq_or_lt_of_le hKle with heq | hlt + · refine ⟨K, K, hKle, hk, fun j => ⟨fun hj => ?_, fun hj => ?_⟩, Or.inl ⟨rfl, heq⟩⟩ + · by_contra hc; rw [not_le] at hc + have := S_strictMono hc; linarith + · have := S_strictMono.monotone hj; linarith + · refine ⟨K, K + 1, hKle, hk, fun j => ⟨fun hj => ?_, fun hj => ?_⟩, Or.inr rfl⟩ + · by_contra hc; rw [not_le] at hc + have := S_strictMono.monotone (show j ≤ K by omega); linarith + · have := S_strictMono.monotone hj; linarith + +/-- `c m = K - L`, where `K` is the last index with `S K ≤ 2πm` and `L` the first with +`2π(m-1) ≤ S L`: the complete triangles of turn `m` are `L+1, …, K`. -/ +private theorem c_formula (m : ℕ) (x y : ℝ) (hx : (m : ℝ) = x) (hy : 2 * π * (x - 1) = y) (K L : ℕ) + (hK1 : S K ≤ 2 * π * x) (hK2 : 2 * π * x < S (K + 1)) (hL : ∀ j, y ≤ S j ↔ L ≤ j) + (hLK : L ≤ K) : (c m : ℤ) = K - L := by + have hT : turnTriangles m = Set.Icc (L + 1) K := by + ext i + simp only [turnTriangles, Set.mem_ofPred_eq, Set.mem_Icc] + rw [hx, hy, hL] + have : S i ≤ 2 * π * x ↔ i ≤ K := by + constructor + · intro h; exact le_of_S_lt (lt_of_le_of_lt h hK2) + · intro h; exact le_trans (S_strictMono.monotone h) hK1 + rw [this] + omega + rw [c, hT, ncard_Icc_nat] + omega + + +/-- The error term `V T₁ + V²/2` is at most `0.13` once `P = √K₀ ≥ 200`. -/ +private theorem bound_X (p P Q V T0 : ℝ) (hp0 : 0 < p) (hp : p < 3.1416) (hP : 200 ≤ P) + (hPQ : P ≤ Q) (hV0 : 0 ≤ V) (hVP : V * P ^ 2 ≤ 2 * (Q - P)) (hV : V ≤ 1 / 100) + (hT0a : 2 * P ≤ T0) (hT0b : T0 < 2 * P + 1 / P) (hQb : 2 * Q ≤ T0 + 4 * p + V) : + V * (T0 + 2 * p) + V ^ 2 / 2 ≤ 13 / 100 := by + have hP0 : 0 < P := by linarith + have hinvP : 1 / P ≤ 1 / 200 := one_div_le_one_div_of_le (by norm_num) hP + have hT1pos : 0 < T0 + 2 * p := by linarith + have hQP : Q - P ≤ 2 * p + 3 / 400 := by linarith + have hQP0 : 0 ≤ Q - P := by linarith + have hT1b : T0 + 2 * p ≤ 2 * P + 2 * p + 1 / 200 := by linarith + have k1 : V * (T0 + 2 * p) * P ^ 2 ≤ 2 * (2 * p + 3 / 400) * (2 * P + 2 * p + 1 / 200) := by + have h1 := mul_le_mul_of_nonneg_right hVP hT1pos.le + have h2 : 2 * (Q - P) * (T0 + 2 * p) ≤ 2 * (2 * p + 3 / 400) * (2 * P + 2 * p + 1 / 200) := by + have := mul_le_mul hQP hT1b hT1pos.le (by linarith) + linarith + have e : V * (T0 + 2 * p) * P ^ 2 = V * P ^ 2 * (T0 + 2 * p) := by ring + linarith + have k2 : 2 * (2 * p + 3 / 400) * (2 * P + 2 * p + 1 / 200) ≤ + 2 * (6291 / 1000) * (2 * P + 6291 / 1000) := by + have := mul_le_mul (show 2 * p + 3 / 400 ≤ 6291 / 1000 by linarith) + (show 2 * P + 2 * p + 1 / 200 ≤ 2 * P + 6291 / 1000 by linarith) (by linarith) (by norm_num) + linarith + have k3 : 2 * (6291 / 1000 : ℝ) * (2 * P + 6291 / 1000) ≤ 129 / 1000 * P ^ 2 := by + nlinarith [mul_nonneg (sub_nonneg.2 hP) hP0.le] + have k4 : V * (T0 + 2 * p) ≤ 129 / 1000 := by + have hP20 : 0 < P ^ 2 := by positivity + have : V * (T0 + 2 * p) * P ^ 2 ≤ 129 / 1000 * P ^ 2 := by linarith + exact le_of_mul_le_mul_right this hP20 + have k5 : V ^ 2 / 2 ≤ 1 / 1000 := by nlinarith + linarith + +/-- The final squeeze: `2π² - 2 - X < a < 2π² + 2 + X` with `X ≤ 0.13`. -/ +private theorem final_bound (p T0 V A K1 K2 L0 L1 : ℝ) (hp1 : 3.14 < p) (hp2 : p < 3.1416) + (hA : A = K2 - L1 - (K1 - L0)) + (hX : V * (T0 + 2 * p) + V ^ 2 / 2 ≤ 13 / 100) + (F1 : 4 * K2 ≤ (T0 + 4 * p + V) ^ 2) (F2 : (T0 + 4 * p) ^ 2 < 4 * (K2 + 1)) + (F3 : 4 * L0 ≤ (T0 + V) ^ 2 + 4) (F4 : T0 ^ 2 ≤ 4 * L0) + (F5 : (T0 + 2 * p) ^ 2 - 2 < 2 * (K1 + L1)) (F6 : 2 * (K1 + L1) ≤ (T0 + 2 * p + V) ^ 2 + 2) : + 17 < A ∧ A < 22 := by + have I1 : (T0 + 4 * p + V) ^ 2 + (T0 + V) ^ 2 - 2 * (T0 + 2 * p) ^ 2 = + 8 * p ^ 2 + 4 * (V * (T0 + 2 * p)) + 2 * V ^ 2 := by ring + have I2 : (T0 + 4 * p) ^ 2 + T0 ^ 2 - 2 * (T0 + 2 * p + V) ^ 2 = + 8 * p ^ 2 - 4 * (V * (T0 + 2 * p)) - 2 * V ^ 2 := by ring + have hp3 : p ^ 2 < 987 / 100 := by nlinarith + have hp4 : 985 / 100 < p ^ 2 := by nlinarith + constructor <;> linarith + + +/-- `(2√x)² = 4x`. -/ +private theorem two_sqrt_sq (x : ℝ) (hx : 0 ≤ x) : (2 * √x) ^ 2 = 4 * x := by + rw [mul_pow, Real.sq_sqrt hx]; ring + +/-- The analytic core: for three consecutive turns with `r0 ≥ 69`, the second difference lies +strictly between `17` and `22`. -/ +private theorem core (r0 : ℝ) (hr : 69 ≤ r0) (K0 K1 K2 L0 L1 : ℕ) + (h0a : S K0 ≤ 2 * π * r0) (h0b : 2 * π * r0 < S (K0 + 1)) + (h1a : S K1 ≤ 2 * π * (r0 + 1)) (h1b : 2 * π * (r0 + 1) < S (K1 + 1)) + (h2a : S K2 ≤ 2 * π * (r0 + 2)) (h2b : 2 * π * (r0 + 2) < S (K2 + 1)) + (hL0 : (L0 = K0 ∧ S K0 = 2 * π * r0) ∨ L0 = K0 + 1) + (hL1 : (L1 = K1 ∧ S K1 = 2 * π * (r0 + 1)) ∨ L1 = K1 + 1) : + 17 < ((K2 : ℤ) - L1) - ((K1 : ℤ) - L0) ∧ ((K2 : ℤ) - L1) - ((K1 : ℤ) - L0) < 22 := by + have hpi := Real.pi_pos + have hpi1 := Real.pi_gt_d2 + have hpi2 := Real.pi_lt_d4 + have hK01 : K0 ≤ K1 := le_of_S_lt (by linarith) + have hK12 : K1 ≤ K2 := le_of_S_lt (by linarith) + set e := S K0 - 2 * √(K0 : ℝ) with he_def + have he : e ≤ 0 := by + have := E_anti 0 K0 (Nat.zero_le _) + simp only [S_zero, Nat.cast_zero, Real.sqrt_zero] at this + linarith + -- upper bounds on `S - 2√·` beyond `K0` + have hb : ∀ (K : ℕ) (θ : ℝ), K0 ≤ K → θ < S (K + 1) → θ - e < 2 * √((K : ℝ) + 1) := by + intro K θ hK hθ + have := E_anti K0 (K + 1) (by omega) + push_cast at this + linarith + have hc : ∀ (K : ℕ) (θ : ℝ), K0 ≤ K → S K = θ → θ - e ≤ 2 * √(K : ℝ) := by + intro K θ hK hθ + have := E_anti K0 K hK + linarith + -- `K0` is large + have hb0 := hb K0 _ le_rfl h0b + have hK0big : (40000 : ℝ) ≤ K0 := by + have hm : 3.14 * 69 ≤ π * r0 := mul_le_mul hpi1.le hr (by norm_num) hpi.le + have h1 : (216 : ℝ) < √((K0 : ℝ) + 1) := by linarith + rw [Real.lt_sqrt (by norm_num)] at h1 + linarith + have hK0pos : 1 ≤ K0 := by + have : (1 : ℝ) ≤ K0 := by linarith + exact_mod_cast this + have hP : (200 : ℝ) ≤ √(K0 : ℝ) := by + rw [Real.le_sqrt (by norm_num) (by positivity)]; linarith + have hP2 : √(K0 : ℝ) ^ 2 = K0 := Real.sq_sqrt (by positivity) + have hPQ : √(K0 : ℝ) ≤ √(K2 : ℝ) := Real.sqrt_le_sqrt (by exact_mod_cast hK01.trans hK12) + set P := √(K0 : ℝ) with hP_def + set Q := √(K2 : ℝ) with hQ_def + set V := 2 / P - 2 / Q with hV_def + have hP0 : 0 < P := by linarith + have hQ0 : 0 < Q := by linarith + have hV0 : 0 ≤ V := by + rw [hV_def, sub_nonneg] + exact div_le_div_of_nonneg_left (by norm_num) hP0 hPQ + have hVP : V * P ^ 2 ≤ 2 * (Q - P) := by + have e1 : V * P * Q = 2 * (Q - P) := by + rw [hV_def]; field_simp + have := mul_le_mul_of_nonneg_left hPQ (mul_nonneg hV0 hP0.le) + have e2 : V * P ^ 2 = V * P * P := by ring + linarith + have hVlt : V ≤ 2 / P := by + rw [hV_def]; have : 0 < 2 / Q := by positivity + linarith + have hVsmall : V ≤ 1 / 100 := by + calc V ≤ 2 / P := hVlt + _ ≤ 2 / 200 := div_le_div_of_nonneg_left (by norm_num) (by norm_num) hP + _ = 1 / 100 := by norm_num + -- lower bounds on `S - 2√·` up to `K2` + have ha : ∀ (K : ℕ) (θ : ℝ), K0 ≤ K → K ≤ K2 → S K ≤ θ → 2 * √(K : ℝ) ≤ θ - e + V := by + intro K θ h1 h2 h3 + have := E_mono K0 K hK0pos h1 + have hs1 : P ≤ √(K : ℝ) := Real.sqrt_le_sqrt (by exact_mod_cast h1) + have hs2 : √(K : ℝ) ≤ Q := Real.sqrt_le_sqrt (by exact_mod_cast h2) + have : 2 / Q ≤ 2 / √(K : ℝ) := div_le_div_of_nonneg_left (by norm_num) (by linarith) hs2 + rw [hV_def] + linarith + set T0 := 2 * π * r0 - e with hT0_def + have hT0a : 2 * P ≤ T0 := by rw [hT0_def, he_def]; linarith + have hsq1 : √((K0 : ℝ) + 1) ≤ P + 1 / (2 * P) := by + rw [Real.sqrt_le_left (by positivity)] + have h4 : 0 ≤ 1 / (4 * P ^ 2) := by positivity + have : (P + 1 / (2 * P)) ^ 2 = P ^ 2 + 1 + 1 / (4 * P ^ 2) := by field_simp; ring + rw [this] + linarith + have hT0b : T0 < 2 * P + 1 / P := by + have : 2 * (1 / (2 * P)) = 1 / P := by field_simp + linarith + have hQb : 2 * Q ≤ T0 + 4 * π + V := by + have := ha K2 _ (hK01.trans hK12) le_rfl h2a + rw [hT0_def]; linarith + have hX := bound_X π P Q V T0 hpi hpi2 hP hPQ hV0 hVP hVsmall hT0a hT0b hQb + -- the six facts + have hK0r : (0 : ℝ) ≤ K0 := by positivity + have hK1r : (0 : ℝ) ≤ K1 := by positivity + have hK2r : (0 : ℝ) ≤ K2 := by positivity + have F1 : 4 * (K2 : ℝ) ≤ (T0 + 4 * π + V) ^ 2 := by + rw [← two_sqrt_sq _ hK2r] + exact pow_le_pow_left₀ (by positivity) hQb 2 + have F2 : (T0 + 4 * π) ^ 2 < 4 * ((K2 : ℝ) + 1) := by + have := hb K2 _ (hK01.trans hK12) h2b + have h' : T0 + 4 * π < 2 * √((K2 : ℝ) + 1) := by linarith + rw [← two_sqrt_sq ((K2 : ℝ) + 1) (by positivity)] + exact pow_lt_pow_left₀ h' (by linarith) two_ne_zero + have G0 : T0 ^ 2 < 4 * ((K0 : ℝ) + 1) := by + rw [← two_sqrt_sq _ (by positivity)] + exact pow_lt_pow_left₀ hb0 (by linarith) two_ne_zero + have G0' : 4 * (K0 : ℝ) ≤ T0 ^ 2 := by + rw [← two_sqrt_sq _ hK0r] + exact pow_le_pow_left₀ (by positivity) hT0a 2 + have F3 : 4 * (L0 : ℝ) ≤ (T0 + V) ^ 2 + 4 := by + have hL : (L0 : ℝ) ≤ K0 + 1 := by + rcases hL0 with ⟨h, -⟩ | h <;> subst h <;> push_cast <;> linarith + have : T0 ^ 2 ≤ (T0 + V) ^ 2 := pow_le_pow_left₀ (by linarith) (by linarith) 2 + linarith + have F4 : T0 ^ 2 ≤ 4 * (L0 : ℝ) := by + rcases hL0 with ⟨h, h'⟩ | h + · rw [h] + have := hc K0 _ le_rfl h' + rw [← two_sqrt_sq _ hK0r] + exact pow_le_pow_left₀ (by linarith) this 2 + · subst h; push_cast; linarith + have G1 : (T0 + 2 * π) ^ 2 < 4 * ((K1 : ℝ) + 1) := by + have := hb K1 _ hK01 h1b + have h' : T0 + 2 * π < 2 * √((K1 : ℝ) + 1) := by linarith + rw [← two_sqrt_sq _ (by positivity)] + exact pow_lt_pow_left₀ h' (by linarith) two_ne_zero + have G1' : 4 * (K1 : ℝ) ≤ (T0 + 2 * π + V) ^ 2 := by + have := ha K1 _ hK01 hK12 h1a + have h' : 2 * √(K1 : ℝ) ≤ T0 + 2 * π + V := by linarith + rw [← two_sqrt_sq _ hK1r] + exact pow_le_pow_left₀ (by positivity) h' 2 + have F5 : (T0 + 2 * π) ^ 2 - 2 < 2 * ((K1 : ℝ) + L1) := by + rcases hL1 with ⟨h, h'⟩ | h + · rw [h] + have := hc K1 _ hK01 h' + have h'' : T0 + 2 * π ≤ 2 * √(K1 : ℝ) := by linarith + have : (T0 + 2 * π) ^ 2 ≤ 4 * (K1 : ℝ) := by + rw [← two_sqrt_sq _ hK1r] + exact pow_le_pow_left₀ (by linarith) h'' 2 + linarith + · subst h; push_cast; linarith + have F6 : 2 * ((K1 : ℝ) + L1) ≤ (T0 + 2 * π + V) ^ 2 + 2 := by + have hL : (L1 : ℝ) ≤ K1 + 1 := by + rcases hL1 with ⟨h, -⟩ | h <;> subst h <;> push_cast <;> linarith + linarith + obtain ⟨r1, r2⟩ := final_bound π T0 V (((K2 : ℤ) - L1) - ((K1 : ℤ) - L0) : ℤ) K1 K2 L0 L1 + hpi1 hpi2 (by push_cast; ring) hX F1 F2 F3 F4 F5 F6 + constructor + · exact_mod_cast r1 + · exact_mod_cast r2 + +/-- Dumortier's conjecture for A172164: every term `a n` (`n ≥ 2`) is `18`, `19`, `20` or `21`. -/ +theorem result : statement := by + intro n hn + rcases le_or_gt n 70 with h70 | h70 + · have hmem : a n ∈ (List.range 69).map (fun i => a (i + 2)) := + List.mem_map.2 ⟨n - 2, List.mem_range.2 (by omega), by rw [show n - 2 + 2 = n by omega]⟩ + have hall : ∀ x ∈ (List.range 69).map (fun i => a (i + 2)), + x = 18 ∨ x = 19 ∨ x = 20 ∨ x = 21 := by + rw [a_data]; decide + exact hall _ hmem + · obtain ⟨r0, hr0⟩ : ∃ r0 : ℝ, r0 = (n : ℝ) - 2 := ⟨_, rfl⟩ + have hn71 : (71 : ℝ) ≤ n := by exact_mod_cast h70 + have hr : 69 ≤ r0 := by rw [hr0]; linarith + have hpi := Real.pi_pos + obtain ⟨K0, L0, h0a, h0b, hL0, hL0'⟩ := exists_KL (2 * π * r0) (by positivity) + obtain ⟨K1, L1, h1a, h1b, hL1, hL1'⟩ := exists_KL (2 * π * (r0 + 1)) (by positivity) + obtain ⟨K2, L2, h2a, h2b, -, -⟩ := exists_KL (2 * π * (r0 + 2)) (by positivity) + have hL0K1 : L0 ≤ K1 := by + have h1 : L0 ≤ K0 + 1 := by rcases hL0' with ⟨h, -⟩ | h <;> omega + have h2 : K0 + 1 ≤ K1 := le_of_S_lt (by have := S_lt_succ_of_le h0a; linarith) + omega + have hL1K2 : L1 ≤ K2 := by + have h1 : L1 ≤ K1 + 1 := by rcases hL1' with ⟨h, -⟩ | h <;> omega + have h2 : K1 + 1 ≤ K2 := le_of_S_lt (by have := S_lt_succ_of_le h1a; linarith) + omega + have hcn : (c n : ℤ) = K2 - L1 := + c_formula n (r0 + 2) (2 * π * (r0 + 1)) (by rw [hr0]; ring) (by ring) K2 L1 h2a h2b hL1 hL1K2 + have hcn1 : (c (n - 1) : ℤ) = K1 - L0 := + c_formula (n - 1) (r0 + 1) (2 * π * r0) + (by rw [Nat.cast_sub (by omega), hr0]; push_cast; ring) + (by ring) K1 L0 h1a h1b hL0 hL0K1 + obtain ⟨l, u⟩ := core r0 hr K0 K1 K2 L0 L1 h0a h0b h1a h1b h2a h2b hL0' hL1' + have ha : a n = ((K2 : ℤ) - L1) - ((K1 : ℤ) - L0) := by rw [a, hcn, hcn1] + omega + +end Math0.Frontier.A172164 + +#math0_settles Math0.Frontier.A172164.result Math0.Statements.A172164.statement diff --git a/lean/Math0/Frontier/OEIS/A175385.lean b/lean/Math0/Frontier/OEIS/A175385.lean new file mode 100644 index 0000000..e9d6fee --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A175385.lean @@ -0,0 +1,307 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A175385 +import Math0.Audit + +/-! +# `∑_{i=1..n} C(2n-i-1, i-1)/i` is never an integer for `n > 1` (A175385) + +We prove the Shevelev–Seidov conjecture from OEIS A175385. + +**Step 1 (closed form).** From `(2n-i)·C(2n-i-1,i-1) = i·C(2n-i,i)` we get +`2n·C(2n-i-1,i-1)/i = C(2n-i,i) + C(2n-i-1,i-1)`. Summing, and using the diagonal sums +`F(m+1) = ∑_k C(m-k,k)` of Pascal's triangle (`Nat.fib_succ_eq_sum_choose`), gives +`2n·S(n) + 1 = F(2n+1) + F(2n-1) = L(2n)` (the Lucas number). So if `S(n) = k ∈ ℤ` then +`L(2n) = 2nk + 1`. + +**Step 2 (Lucas numbers in a ring).** In any commutative ring with `α² = α + 1` we have +`α^(j+1) = F(j+1)α + F(j)`, and `β = 1 - α` satisfies the same equation, so +`L(2n) = α^(2n) + β^(2n)` there. + +**Step 3 (contradiction).** +* `n` even: `4 ∣ 2n`, but `F` has period 6 mod 4 and `L(2n) mod 4 ∈ {2, 3}`. +* `n` odd with smallest prime factor `p = 5`: in `ZMod 5`, `α = β = 3`, so + `L(2n) = 2·9^n = -2 ≠ 1`. +* `n` odd with smallest prime factor `p ∉ {2, 5}`: take `α = (1+√5)/2` in the algebraic closure + `K` of `ZMod p`. Frobenius permutes the roots of `X² - X - 1`, so `α^(p²) = α` and + `α^(p²-1) = 1`. From `L(2n) = 1` in `K` and `αβ = -1`, `x = α^(2n)` satisfies + `x² - x + 1 = 0`, hence `α^(6n) = -1` and `α^(12n) = 1`. Every prime factor of `p² - 1` is + smaller than `p`, so `gcd(n, p² - 1) = 1`, the order of `α` divides `12`, and since `n` is odd, + `α^6 = -1`. With `α² = α + 1` this forces `20 = 0` in `K`, i.e. `p ∣ 20`, a contradiction. +-/ + +namespace Math0.Frontier.A175385 +open Math0.Statements.A175385 +open Finset + +/-- `F(m+1) = ∑_{k ≤ m} C(m-k, k)`. -/ +private lemma fib_succ_eq_sum_range (m : ℕ) : + Nat.fib (m + 1) = ∑ k ∈ range (m + 1), Nat.choose (m - k) k := by + rw [Nat.fib_succ_eq_sum_choose, ← Finset.Nat.sum_antidiagonal_swap] + exact Finset.Nat.sum_antidiagonal_eq_sum_range_succ (fun i j => Nat.choose j i) m + +/-- Truncation: if `m < 2N` then `F(m+1) = ∑_{k < N} C(m-k, k)`. -/ +private lemma fib_succ_eq_sum_range' (m N : ℕ) (h : m < 2 * N) : + Nat.fib (m + 1) = ∑ k ∈ range N, Nat.choose (m - k) k := by + have h1 : ∑ k ∈ range N, Nat.choose (m - k) k = + ∑ k ∈ range (N + m + 1), Nat.choose (m - k) k := by + apply Finset.sum_subset + · intro x hx; simp only [mem_range] at hx ⊢; omega + · intro x hx hx' + simp only [mem_range] at hx hx' + exact Nat.choose_eq_zero_of_lt (by omega) + have h2 : ∑ k ∈ range (m + 1), Nat.choose (m - k) k = + ∑ k ∈ range (N + m + 1), Nat.choose (m - k) k := by + apply Finset.sum_subset + · intro x hx; simp only [mem_range] at hx ⊢; omega + · intro x hx hx' + simp only [mem_range] at hx hx' + exact Nat.choose_eq_zero_of_lt (by omega) + rw [h1, ← h2, fib_succ_eq_sum_range] + +/-- The termwise identity `2n·C(2n-i-1,i-1)/i = C(2n-i,i) + C(2n-i-1,i-1)`, written with +`n = m + 1` and `i = j + 1`. -/ +private lemma term_identity (m j : ℕ) (hj : j ≤ m) : + (2 * ((m : ℚ) + 1)) * (((Nat.choose (2 * m - j) j : ℕ) : ℚ) / ((j : ℚ) + 1)) = + ((Nat.choose (2 * m + 1 - j) (j + 1) : ℕ) : ℚ) + ((Nat.choose (2 * m - j) j : ℕ) : ℚ) := by + have h := Nat.add_one_mul_choose_eq (2 * m - j) j + have he : 2 * m - j + 1 = 2 * m + 1 - j := by omega + rw [he] at h + have hq : ((2 * m + 1 - j : ℕ) : ℚ) * (Nat.choose (2 * m - j) j : ℚ) = + (Nat.choose (2 * m + 1 - j) (j + 1) : ℚ) * ((j : ℚ) + 1) := by exact_mod_cast h + have hc : ((2 * m + 1 - j : ℕ) : ℚ) = 2 * (m : ℚ) + 1 - j := by + rw [Nat.cast_sub (by omega)]; push_cast; ring + rw [hc] at hq + have hj1 : (j : ℚ) + 1 ≠ 0 := by positivity + field_simp + linear_combination hq + +/-- Reindex `S (m+1)` as a sum over `j = i - 1 ∈ [0, m]`. -/ +private lemma S_succ (m : ℕ) : + S (m + 1) = ∑ j ∈ range (m + 1), ((Nat.choose (2 * m - j) j : ℕ) : ℚ) / ((j : ℚ) + 1) := by + unfold S + symm + apply Finset.sum_nbij' (· + 1) (· - 1) + · intro x hx; simp only [mem_range, mem_Icc] at hx ⊢; omega + · intro x hx; simp only [mem_range, mem_Icc] at hx ⊢; omega + · intro x hx; simp + · intro x hx; simp only [mem_Icc] at hx ⊢; omega + · intro x hx + simp only [mem_range] at hx + have e1 : 2 * (m + 1) - (x + 1) - 1 = 2 * m - x := by omega + rw [e1, Nat.add_sub_cancel] + push_cast + rfl + +/-- The closed form `2n·S(n) + 1 = F(2n+1) + F(2n-1)` (with `n = m + 1`). -/ +private lemma main_identity (m : ℕ) : + 2 * ((m : ℚ) + 1) * S (m + 1) + 1 = (Nat.fib (2 * m + 3) : ℚ) + Nat.fib (2 * m + 1) := by + rw [S_succ, Finset.mul_sum] + rw [Finset.sum_congr rfl (fun j hj => term_identity m j (by simp at hj; omega))] + rw [Finset.sum_add_distrib] + have hA : (Nat.fib (2 * m + 3) : ℚ) = + ∑ j ∈ range (m + 1), ((Nat.choose (2 * m + 1 - j) (j + 1) : ℕ) : ℚ) + 1 := by + have := fib_succ_eq_sum_range' (2 * m + 2) (m + 2) (by omega) + rw [Finset.sum_range_succ'] at this + rw [show 2 * m + 3 = 2 * m + 2 + 1 by ring, this] + push_cast + congr 1 + have hB : (Nat.fib (2 * m + 1) : ℚ) = + ∑ j ∈ range (m + 1), ((Nat.choose (2 * m - j) j : ℕ) : ℚ) := by + rw [fib_succ_eq_sum_range' (2 * m) (m + 1) (by omega)]; push_cast; rfl + rw [hA, hB]; ring + +/-- If `α² = α + 1` in a commutative ring then `α^(j+1) = F(j+1)·α + F(j)`. -/ +private lemma pow_eq_fib {R : Type*} [CommRing R] (α : R) (hα : α ^ 2 = α + 1) (j : ℕ) : + α ^ (j + 1) = (Nat.fib (j + 1) : R) * α + Nat.fib j := by + induction j with + | zero => simp + | succ j ih => + rw [pow_succ, ih, Nat.fib_add_two] + push_cast + linear_combination (Nat.fib (j + 1) : R) * hα + +/-- If `α² = α + 1` then `F(2m+3) + F(2m+1) = α^(2m+2) + (1-α)^(2m+2)` (a Lucas number). -/ +private lemma lucas {R : Type*} [CommRing R] (α : R) (hα : α ^ 2 = α + 1) (m : ℕ) : + ((Nat.fib (2 * m + 3) + Nat.fib (2 * m + 1) : ℕ) : R) = + α ^ (2 * (m + 1)) + (1 - α) ^ (2 * (m + 1)) := by + have hβ : (1 - α) ^ 2 = (1 - α) + 1 := by linear_combination hα + have e : 2 * (m + 1) = (2 * m + 1) + 1 := by ring + rw [e, pow_eq_fib α hα, pow_eq_fib (1 - α) hβ] + have h3 : Nat.fib (2 * m + 3) = Nat.fib (2 * m + 1) + Nat.fib (2 * m + 1 + 1) := + Nat.fib_add_two + rw [h3] + push_cast + ring + +/-- In a field of characteristic `p`, a root `α` of `X² - X - 1` satisfies `α^(p²-1) = 1`: +Frobenius sends `α` to a root, i.e. to `α` or `1 - α`, and in both cases `α^(p²) = α`. -/ +private lemma frob {K : Type*} [Field K] (p : ℕ) [Fact p.Prime] [CharP K p] (α : K) + (hα : α ^ 2 = α + 1) : α ^ (p ^ 2 - 1) = 1 := by + have hy : (α ^ p) ^ 2 = α ^ p + 1 := by + rw [← pow_mul, mul_comm, pow_mul, hα, add_pow_char, one_pow] + have hprod : (α ^ p - α) * (α ^ p - (1 - α)) = 0 := by linear_combination hy - hα + have hpp : α ^ (p ^ 2) = α := by + rw [sq, pow_mul] + rcases mul_eq_zero.mp hprod with h | h + · rw [sub_eq_zero.mp h, sub_eq_zero.mp h] + · rw [sub_eq_zero.mp h, sub_pow_char, one_pow, sub_eq_zero.mp h]; ring + have hα0 : α ≠ 0 := by rintro rfl; norm_num at hα + have hp1 : 1 ≤ p ^ 2 := Nat.one_le_pow _ _ (Fact.out : p.Prime).pos + have : α ^ (p ^ 2 - 1) * α = 1 * α := by + rw [← pow_succ, Nat.sub_add_cancel hp1, hpp, one_mul] + exact mul_right_cancel₀ hα0 this + +/-- The only primes dividing `20` are `2` and `5`. -/ +private lemma prime_dvd_twenty (p : ℕ) (hp : p.Prime) (h : p ∣ 20) : p = 2 ∨ p = 5 := by + have hle : p ≤ 20 := Nat.le_of_dvd (by norm_num) h + interval_cases p <;> simp_all <;> norm_num at hp + +/-- The core argument: in a field of characteristic `p ∉ {2, 5}` with `α² = α + 1`, if `N` is +odd and coprime to `p² - 1` then `α^(2N) + (1-α)^(2N) ≠ 1`. -/ +private lemma field_part {K : Type*} [Field K] (p : ℕ) [hp : Fact p.Prime] [CharP K p] + (hp2 : p ≠ 2) (hp5 : p ≠ 5) (α : K) (hα : α ^ 2 = α + 1) (N : ℕ) (hN : Odd N) + (hcop : Nat.Coprime N (p ^ 2 - 1)) : α ^ (2 * N) + (1 - α) ^ (2 * N) ≠ 1 := by + intro h + set x := α ^ (2 * N) with hx + have hprod : x * (1 - α) ^ (2 * N) = 1 := by + rw [hx, ← mul_pow, show α * (1 - α) = -1 by linear_combination -hα, pow_mul, neg_one_sq, + one_pow] + have hx2 : x ^ 2 - x + 1 = 0 := by linear_combination x * h - hprod + have h6 : α ^ (6 * N) = -1 := by + have : α ^ (6 * N) = x ^ 3 := by rw [hx, ← pow_mul]; ring_nf + rw [this]; linear_combination (x + 1) * hx2 + have h12 : α ^ (12 * N) = 1 := by + rw [show 12 * N = 6 * N * 2 by ring, pow_mul, h6]; norm_num + have hd1 : orderOf α ∣ 12 * N := orderOf_dvd_of_pow_eq_one h12 + have hd2 : orderOf α ∣ p ^ 2 - 1 := orderOf_dvd_of_pow_eq_one (frob p α hα) + have hcop' : Nat.Coprime (orderOf α) N := (hcop.coprime_dvd_right hd2).symm + have hd3 : orderOf α ∣ 12 := hcop'.dvd_of_dvd_mul_right hd1 + have h12' : α ^ 12 = 1 := orderOf_dvd_iff_pow_eq_one.mp hd3 + obtain ⟨t, rfl⟩ := hN + have h6' : α ^ 6 = -1 := by + rw [show 6 * (2 * t + 1) = 12 * t + 6 by ring, pow_add, pow_mul, h12', one_pow, + one_mul] at h6 + exact h6 + have h20 : (20 : K) = 0 := by + linear_combination (14 - 8 * α) * h6' + + (8 * α ^ 5 - 6 * α ^ 4 + 2 * α ^ 3 - 4 * α ^ 2 - 2 * α - 6) * hα + have h20' : ((20 : ℕ) : K) = 0 := by exact_mod_cast h20 + rw [CharP.cast_eq_zero_iff K p] at h20' + rcases prime_dvd_twenty p hp.out h20' with h' | h' <;> contradiction + +/-- Fibonacci numbers have period `6` modulo `4`. -/ +private lemma fib_add_six_mod (j : ℕ) : Nat.fib (j + 6) % 4 = Nat.fib j % 4 := by + have h := Nat.fib_add 5 j + rw [show 5 + j + 1 = j + 6 by ring, show Nat.fib 5 = 5 by rfl, + show Nat.fib (5 + 1) = 8 by rfl] at h + omega + +/-- `F(j) ≡ F(j mod 6) (mod 4)`. -/ +private lemma fib_mod_four (j : ℕ) : Nat.fib j % 4 = Nat.fib (j % 6) % 4 := by + induction j using Nat.strong_induction_on with + | _ j ih => + by_cases hj : j < 6 + · rw [Nat.mod_eq_of_lt hj] + · obtain ⟨i, rfl⟩ : ∃ i, j = i + 6 := ⟨j - 6, by omega⟩ + rw [fib_add_six_mod, ih i (by omega), show (i + 6) % 6 = i % 6 by omega] + +/-- For `m` odd (`n = m + 1` even), `L(2n) = F(2m+3) + F(2m+1)` is `2` or `3` modulo `4`. -/ +private lemma T_mod_four (m : ℕ) (hm : m % 2 = 1) : + (Nat.fib (2 * m + 3) + Nat.fib (2 * m + 1)) % 4 = 2 ∨ + (Nat.fib (2 * m + 3) + Nat.fib (2 * m + 1)) % 4 = 3 := by + rw [Nat.add_mod, fib_mod_four (2 * m + 3), fib_mod_four (2 * m + 1)] + have : m % 6 = 1 ∨ m % 6 = 3 ∨ m % 6 = 5 := by omega + rcases this with h | h | h + · rw [show (2 * m + 3) % 6 = 5 by omega, show (2 * m + 1) % 6 = 3 by omega]; decide + · rw [show (2 * m + 3) % 6 = 3 by omega, show (2 * m + 1) % 6 = 1 by omega]; decide + · rw [show (2 * m + 3) % 6 = 1 by omega, show (2 * m + 1) % 6 = 5 by omega]; decide + +/-- An odd `n > 1` is coprime to `p² - 1`, where `p` is its smallest prime factor: every prime +factor of `p² - 1 = (p-1)(p+1)` is less than `p`. -/ +private lemma coprime_minFac (n : ℕ) (hn : 1 < n) (hodd : Odd n) : + Nat.Coprime n (n.minFac ^ 2 - 1) := by + have hp : n.minFac.Prime := Nat.minFac_prime (by omega) + have hp2 : 2 ≤ n.minFac := hp.two_le + obtain ⟨r, hr⟩ : ∃ r, n.minFac = r + 1 := ⟨n.minFac - 1, by omega⟩ + have hpodd : n.minFac % 2 = 1 := by + have := Odd.of_dvd_nat hodd (Nat.minFac_dvd n) + exact Nat.odd_iff.mp this + have hsq : n.minFac ^ 2 - 1 = r * (r + 2) := by + rw [hr, show (r + 1) ^ 2 = r * (r + 2) + 1 by ring, Nat.add_sub_cancel] + rw [hsq] + apply Nat.coprime_of_dvd + intro q hq hqn hqr + have hqge : n.minFac ≤ q := Nat.minFac_le_of_dvd hq.two_le hqn + have hqodd : q % 2 = 1 := Nat.odd_iff.mp (Odd.of_dvd_nat hodd hqn) + rcases (Nat.Prime.dvd_mul hq).mp hqr with h | h + · have : q ≤ r := Nat.le_of_dvd (by omega) h + omega + · have : q ≤ r + 2 := Nat.le_of_dvd (by omega) h + have hq' : q = r + 1 ∨ q = r + 2 := by omega + rcases hq' with hq' | hq' + · rw [hq'] at h + have h1 : r + 1 ∣ 1 := (Nat.dvd_add_right (dvd_refl (r + 1))).mp h + have := Nat.le_of_dvd (by norm_num) h1 + omega + · omega + +/-- **A175385.** For every `n > 1`, `∑_{i=1}^{n} C(2n-i-1, i-1)/i` is not an integer. -/ +theorem result : statement := by + intro n hn ⟨k, hk⟩ + obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩ + have hid := main_identity m + rw [hk] at hid + have hZ : 2 * ((m : ℤ) + 1) * k + 1 = ((Nat.fib (2 * m + 3) + Nat.fib (2 * m + 1) : ℕ) : ℤ) := by + push_cast + exact_mod_cast hid + rcases Nat.even_or_odd (m + 1) with hev | hodd + · obtain ⟨t, ht⟩ := hev + have hmod := T_mod_four m (by omega) + have h4 : ((Nat.fib (2 * m + 3) + Nat.fib (2 * m + 1) : ℕ) : ℤ) = 4 * (t * k) + 1 := by + rw [← hZ] + have : ((m : ℤ) + 1) = 2 * t := by exact_mod_cast (by omega : m + 1 = 2 * t) + rw [this]; ring + omega + · have key : ∀ (R : Type) [CommRing R] (q : ℕ) [CharP R q], q ∣ m + 1 → + ((Nat.fib (2 * m + 3) + Nat.fib (2 * m + 1) : ℕ) : R) = 1 := by + intro R _ q _ hq + have h1 : ((m + 1 : ℕ) : R) = 0 := (CharP.cast_eq_zero_iff R q _).mpr hq + have h2 := congrArg (fun z : ℤ => (z : R)) hZ + simp only [Int.cast_add, Int.cast_mul, Int.cast_ofNat, Int.cast_natCast, Int.cast_one] at h2 + push_cast at h1 h2 ⊢ + rw [← h2, h1]; ring + have hp : (m + 1).minFac.Prime := Nat.minFac_prime (by omega) + have hpd : (m + 1).minFac ∣ m + 1 := Nat.minFac_dvd _ + have hp2 : (m + 1).minFac ≠ 2 := by + intro h2 + rw [h2] at hpd + exact (Nat.not_even_iff_odd.mpr hodd) (even_iff_two_dvd.mpr hpd) + by_cases hp5 : (m + 1).minFac = 5 + · rw [hp5] at hpd + have h := key (ZMod 5) 5 hpd + rw [lucas (3 : ZMod 5) (by decide) m] at h + have h13 : (1 - 3 : ZMod 5) = 3 := by decide + have h9 : (3 : ZMod 5) ^ 2 = -1 := by decide + rw [h13, pow_mul, h9, Odd.neg_one_pow hodd] at h + revert h; decide + · set p := (m + 1).minFac with hpdef + have := Fact.mk hp + obtain ⟨s, hs⟩ := IsAlgClosed.exists_eq_mul_self (5 : AlgebraicClosure (ZMod p)) + have h2 : (2 : AlgebraicClosure (ZMod p)) ≠ 0 := by + intro h + have h' : ((2 : ℕ) : AlgebraicClosure (ZMod p)) = 0 := by exact_mod_cast h + rw [CharP.cast_eq_zero_iff _ p] at h' + exact hp2 ((Nat.prime_dvd_prime_iff_eq hp Nat.prime_two).mp h') + have hα : ((1 + s) / 2) ^ 2 = (1 + s) / 2 + 1 := by + field_simp + linear_combination -hs + apply field_part p hp2 hp5 ((1 + s) / 2) hα (m + 1) hodd + (coprime_minFac (m + 1) (by omega) hodd) + rw [← lucas _ hα m] + exact key _ p hpd + +end Math0.Frontier.A175385 + +#math0_settles Math0.Frontier.A175385.result Math0.Statements.A175385.statement diff --git a/lean/Math0/Frontier/OEIS/A176206.lean b/lean/Math0/Frontier/OEIS/A176206.lean new file mode 100644 index 0000000..b322022 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A176206.lean @@ -0,0 +1,165 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A176206 +import Math0.Audit + +/-! +# Divisors of the terms of row `n` of A176206 are the parts of the partitions of `n` + +We prove Omar E. Pol's conjecture (A176206): for every `n ≥ 1`, the multiset of all divisors +of all terms of row `n` equals the multiset of all parts of all partitions of `n`. + +Compare multiplicities of a fixed `d`. Write `c d t ∈ {0, 1}` for the multiplicity of `d` among +the divisors of `t`. Since row `n` holds `n - k` repeated `p k` times (`k < n`), the left side +has `H d n = ∑_{k h (Nat.mem_divisors.1 h') + +/-- The total number of parts equal to `d` over all partitions of `n` (the right side). -/ +private def F (d n : ℕ) : ℕ := ∑ π : n.Partition, π.parts.count d + +/-- The number of copies of `d` among the divisors of the terms of row `n` (the left side). -/ +private def H (d n : ℕ) : ℕ := ∑ k ∈ Finset.range n, p k * c d (n - k) + +/-- No partition of `n < d` has a part equal to `d`. -/ +private lemma F_lt {d n : ℕ} (h : n < d) : F d n = 0 := by + refine Finset.sum_eq_zero fun π _ => Multiset.count_eq_zero.2 fun hd => ?_ + have := part_le π hd + omega + +/-- No term `n - k ∈ [1, n]` of row `n < d` is divisible by `d`. -/ +private lemma H_lt {d n : ℕ} (h : n < d) : H d n = 0 := by + refine Finset.sum_eq_zero fun k hk => ?_ + rw [Finset.mem_range] at hk + rw [c_eq, if_neg] + · simp + · rintro ⟨hdv, hne⟩ + have := Nat.le_of_dvd (by omega) hdv + omega + +/-- Removing one part `d` gives the recursion `F d n = F d (n - d) + p (n - d)`. -/ +private lemma F_ge {d n : ℕ} (hd : 1 ≤ d) (h : d ≤ n) : F d n = F d (n - d) + p (n - d) := by + rw [F, ← Finset.sum_filter_of_ne (p := fun π : n.Partition => d ∈ π.parts) + (fun π _ hπ => Multiset.count_ne_zero.1 hπ)] + rw [Finset.sum_subtype (Finset.univ.filter fun π : n.Partition => d ∈ π.parts) + (p := fun π : n.Partition => d ∈ π.parts) (by simp)] + rw [← Fintype.sum_equiv (Nat.Partition.partitionWithPartEquiv hd h).symm + (fun σ : (n - d).Partition => σ.parts.count d + 1) _ (fun σ => by + simp [Nat.Partition.partitionWithPartEquiv_symm_apply_parts])] + rw [Finset.sum_add_distrib, F, p] + simp + +/-- The left side satisfies the same recursion, `H d n = H d (n - d) + p (n - d)`. -/ +private lemma H_ge {d n : ℕ} (hd : 1 ≤ d) (h : d ≤ n) : H d n = H d (n - d) + p (n - d) := by + obtain ⟨m, rfl⟩ : ∃ m, n = m + d := ⟨n - d, by omega⟩ + rw [Nat.add_sub_cancel, H, Finset.sum_range_add, H] + congr 1 + · refine Finset.sum_congr rfl fun k hk => ?_ + rw [Finset.mem_range] at hk + rw [c_eq, c_eq] + congr 2 + apply propext + have : m + d - k = (m - k) + d := by omega + rw [this, Nat.dvd_add_self_right] + omega + · rw [Finset.sum_eq_single 0] + · rw [c_eq, if_pos] + · simp + · constructor + · simp + · omega + · intro x hx hx0 + rw [Finset.mem_range] at hx + rw [c_eq, if_neg] + · simp + · rintro ⟨hdv, hne⟩ + have := Nat.le_of_dvd (by omega) hdv + omega + · simp; omega + +/-- Parts are positive, so no part equals `0`. -/ +private lemma F_zero (n : ℕ) : F 0 n = 0 := + Finset.sum_eq_zero fun π _ => Multiset.count_eq_zero.2 fun h => lt_irrefl 0 (π.parts_pos h) + +/-- `0` is never a divisor of a positive number. -/ +private lemma H_zero (n : ℕ) : H 0 n = 0 := by + refine Finset.sum_eq_zero fun k _ => ?_ + rw [c_eq, if_neg] + · simp + · rintro ⟨h0, hne⟩ + exact hne (Nat.eq_zero_of_zero_dvd h0) + +/-- The two counts agree, by strong induction on `n`. -/ +private lemma F_eq_H (d n : ℕ) : F d n = H d n := by + rcases Nat.eq_zero_or_pos d with rfl | hd + · rw [F_zero, H_zero] + induction n using Nat.strong_induction_on with + | _ n ih => + rcases lt_or_ge n d with h | h + · rw [F_lt h, H_lt h] + · rw [F_ge hd h, H_ge hd h, ih _ (by omega)] + +/-- Summing a function over a `flatMap`. -/ +private lemma list_sum_flatMap (L : List ℕ) (g : ℕ → List ℕ) (f : ℕ → ℕ) : + ((L.flatMap g).map f).sum = (L.map fun k => ((g k).map f).sum).sum := by + induction L with + | nil => simp + | cons a L ih => simp [List.flatMap_cons, List.map_append, List.sum_append, ih] + +/-- A sum over `List.range n` is a sum over `Finset.range n`. -/ +private lemma list_sum_range (h : ℕ → ℕ) (n : ℕ) : + ((List.range n).map h).sum = ∑ k ∈ Finset.range n, h k := by + induction n with + | zero => simp + | succ n ih => + rw [List.range_succ, List.map_append, List.sum_append, ih, Finset.sum_range_succ] + simp + +/-- The multiplicity of `d` on the left side of the statement is `H d n`. -/ +private lemma lhs_count (d n : ℕ) : + ((row n : Multiset ℕ).map fun b => b.divisors.val.count d).sum = H d n := by + show ((row n).map (c d)).sum = H d n + rw [row, rowOf, list_sum_flatMap, H, ← list_sum_range] + congr 1 + refine List.map_congr_left fun k _ => ?_ + rw [List.map_replicate, List.sum_replicate, smul_eq_mul] + +/-- Pol's conjecture (A176206) holds: for every `n ≥ 1`, the divisors of the terms of row `n` +are, as a multiset, the parts of all partitions of `n`. -/ +theorem result : statement := by + intro n _ + refine Multiset.ext' fun d => ?_ + rw [Multiset.count_bind, Multiset.count_bind, lhs_count, ← F_eq_H] + rfl + +end Math0.Frontier.A176206 + +#math0_settles Math0.Frontier.A176206.result Math0.Statements.A176206.statement diff --git a/lean/Math0/Frontier/OEIS/A178295.lean b/lean/Math0/Frontier/OEIS/A178295.lean new file mode 100644 index 0000000..6f2d819 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A178295.lean @@ -0,0 +1,415 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A178295 +import Math0.Audit + +/-! +# A178295: collinear 4-subsets of `{0, …, 4}ⁿ` (Mathar's conjecture is true) + +We prove all three of Mathar's formulas: `a(n) = 9^n/2 + 3*7^n/2 - 2*5^n`, the recurrence +`a(n) = 21 a(n-1) - 143 a(n-2) + 315 a(n-3)` and the rational generating function. + +*Idea.* Count ordered 4-tuples `f : Fin 4 → Pt n` of distinct collinear points instead; each +4-set is the image of exactly `24` of them (`card_E`). Transposing, such a tuple is a family +`G : Fin n → Col` of *columns* `G i = (f 0 i, f 1 i, f 2 i, f 3 i) ∈ {0, …, 4}⁴`, and the +conditions become: any two columns are *compatible* (`RR`: the planar points `(G i a, G j a)` +are collinear) and the four rows are distinct (`card_E_V`). Under these conditions every column +is constant or injective (`const_of_RR`), compatibility is transitive through a non-constant +column (`RR_trans`), and the `120` injective columns fall into `48` compatibility classes: +`12` classes of size `4` (value set of span `3`) and `36` of size `2` (span `4`). These finite +facts about `{0, …, 4}⁴` are checked by the kernel (`rep_sep`, `cover_check`, `count_check`). +So the good families are the disjoint union, over the `48` classes, of the families of columns +each constant or in the class, not all constant (`V_eq`, `W_disj`), giving +`24 a(n) = 12 (9^n - 5^n) + 36 (7^n - 5^n)` (`card_V`). The recurrence and the generating +function follow from the closed form. +-/ + +namespace Math0.Frontier.A178295 +open Math0.Statements.A178295 + +/-! ### Columns -/ + +/-- A column: the values of one coordinate at the four points of an ordered 4-tuple. -/ +private abbrev Col := Fin 4 → Fin 5 + +/-- The entries of a column, as integers. -/ +private def zc (u : Col) (a : Fin 4) : ℤ := ((u a : ℕ) : ℤ) + +/-- Two columns are compatible: the four planar points `(u a, w a)` are collinear. -/ +private def RR (u w : Col) : Prop := + ∀ a b c : Fin 4, (zc u b - zc u a) * (zc w c - zc w a) = (zc w b - zc w a) * (zc u c - zc u a) + +/-- Boolean version of `RR`. -/ +private def RRb (u w : Col) : Bool := + (List.finRange 4).all fun a => (List.finRange 4).all fun b => (List.finRange 4).all fun c => + minorB ((u a : ℕ), (u b : ℕ), (u c : ℕ)) ((w a : ℕ), (w b : ℕ), (w c : ℕ)) + +/-- `RRb` decides `RR`. -/ +private theorem RRb_iff (u w : Col) : RRb u w = true ↔ RR u w := by + unfold RRb RR + simp only [List.all_eq_true, List.mem_finRange, forall_const, minorB_iff, zc] + +/-- `RR` is decided by `RRb`. -/ +private instance (u w : Col) : Decidable (RR u w) := decidable_of_iff _ (RRb_iff u w) + +/-- Integer entries are equal iff the entries are. -/ +private theorem zc_eq {u : Col} {a b : Fin 4} : zc u a = zc u b ↔ u a = u b := by + unfold zc + constructor + · intro h; exact Fin.ext (by exact_mod_cast h) + · intro h; rw [h] + +/-- Compatibility is symmetric. -/ +private theorem RR_symm {u w : Col} (h : RR u w) : RR w u := fun a b c => (h a b c).symm + +/-- A constant column is compatible with every column. -/ +private theorem RR_const_right (u : Col) {w : Col} (hw : ∀ a, w a = w 0) : RR u w := by + intro a b c + have h1 : zc w c = zc w a := zc_eq.2 ((hw c).trans (hw a).symm) + have h2 : zc w b = zc w a := zc_eq.2 ((hw b).trans (hw a).symm) + rw [h1, h2]; ring + +/-- Compatibility is transitive through a non-constant column. -/ +private theorem RR_trans {u v w : Col} {a₀ b₀ : Fin 4} (hv : v a₀ ≠ v b₀) (h1 : RR v u) + (h2 : RR v w) : RR u w := by + intro a b c + set D := zc v b₀ - zc v a₀ with hD + have hD0 : D ≠ 0 := sub_ne_zero.mpr (fun h => hv (zc_eq.1 h).symm) + have hA : ∀ x y, D * (zc u y - zc u x) = (zc u b₀ - zc u a₀) * (zc v y - zc v x) := by + intro x y + linear_combination h1 a₀ b₀ y - h1 a₀ b₀ x + have hB : ∀ x y, D * (zc w y - zc w x) = (zc w b₀ - zc w a₀) * (zc v y - zc v x) := by + intro x y + linear_combination h2 a₀ b₀ y - h2 a₀ b₀ x + apply mul_left_cancel₀ (pow_ne_zero 2 hD0) + calc D ^ 2 * ((zc u b - zc u a) * (zc w c - zc w a)) + = (D * (zc u b - zc u a)) * (D * (zc w c - zc w a)) := by ring + _ = (D * (zc w b - zc w a)) * (D * (zc u c - zc u a)) := by + rw [hA a b, hB a c, hB a b, hA a c]; ring + _ = D ^ 2 * ((zc w b - zc w a) * (zc u c - zc u a)) := by ring + +/-- If `w` is compatible with `t`, and `w` takes equal values at two indices where `t` does +not, then `w` is constant. -/ +private theorem const_of_RR {w t : Col} {a b : Fin 4} (h : RR w t) (hw : w a = w b) + (ht : t a ≠ t b) : ∀ c, w c = w a := by + intro c + have h' := h a b c + rw [zc_eq.2 hw.symm, sub_self, zero_mul] at h' + have hne : zc t b - zc t a ≠ 0 := sub_ne_zero.mpr (fun e => ht (zc_eq.1 e).symm) + have := (mul_eq_zero.1 h'.symm).resolve_left hne + exact zc_eq.1 (sub_eq_zero.1 this) + +/-! ### Finite data: the 48 classes of injective columns -/ + +/-- Representatives of the 48 classes of injective columns (the first 12 have span 3). -/ +private def repL : List (List ℕ) := + [[0, 1, 2, 3], [0, 1, 3, 2], [0, 2, 1, 3], [0, 2, 3, 1], [0, 3, 1, 2], [0, 3, 2, 1], + [1, 0, 2, 3], [1, 0, 3, 2], [1, 2, 0, 3], [1, 2, 3, 0], [1, 3, 0, 2], [1, 3, 2, 0], + [0, 1, 2, 4], [0, 1, 3, 4], [0, 1, 4, 2], [0, 1, 4, 3], [0, 2, 1, 4], [0, 2, 3, 4], + [0, 2, 4, 1], [0, 2, 4, 3], [0, 3, 1, 4], [0, 3, 2, 4], [0, 3, 4, 1], [0, 3, 4, 2], + [0, 4, 1, 2], [0, 4, 1, 3], [0, 4, 2, 1], [0, 4, 2, 3], [0, 4, 3, 1], [0, 4, 3, 2], + [1, 0, 2, 4], [1, 0, 3, 4], [1, 0, 4, 2], [1, 0, 4, 3], [1, 2, 0, 4], [1, 2, 4, 0], + [1, 3, 0, 4], [1, 3, 4, 0], [1, 4, 0, 2], [1, 4, 0, 3], [1, 4, 2, 0], [1, 4, 3, 0], + [2, 0, 1, 4], [2, 0, 3, 4], [2, 0, 4, 1], [2, 0, 4, 3], [2, 1, 0, 4], [2, 1, 4, 0]] + +/-- The `k`-th representative column. -/ +private def rep (k : Fin 48) : Col := + fun a => ⟨((repL.getD k.val []).getD a.val 0) % 5, Nat.mod_lt _ (by norm_num)⟩ + +/-- Boolean test for constant columns. -/ +private def constB (u : Col) : Bool := (List.finRange 4).all fun a => decide (u a = u 0) + +/-- `constB` decides constancy. -/ +private theorem constB_iff (u : Col) : constB u = true ↔ ∀ a, u a = u 0 := by + simp [constB, List.all_eq_true] + +/-- Boolean test for injective columns. -/ +private def injB (u : Col) : Bool := + (List.finRange 4).all fun a => (List.finRange 4).all fun b => decide (u a = u b → a = b) + +/-- `injB` decides injectivity. -/ +private theorem injB_iff (u : Col) : injB u = true ↔ Function.Injective u := by + simp only [injB, List.all_eq_true, List.mem_finRange, forall_const, decide_eq_true_eq] + rfl + +/-- Every representative is injective. -/ +private theorem rep_injB : ∀ k : Fin 48, injB (rep k) = true := by decide +kernel + +/-- Distinct representatives are incompatible. -/ +private theorem rep_sep : ∀ k k' : Fin 48, k ≠ k' → RRb (rep k) (rep k') = false := by + decide +kernel + +/-- Every injective column is compatible with some representative. -/ +private theorem cover_check : + (L 4).all (fun u => !injB u || (List.finRange 48).any (fun k => RRb (rep k) u)) = true := by + decide +kernel + +/-- The number of columns compatible with each representative. -/ +private theorem count_check : + ∀ k : Fin 48, (L 4).countP (RRb (rep k)) = if k.val < 12 then 9 else 7 := by + decide +kernel + +/-- There are 5 constant columns. -/ +private theorem const_check : (L 4).countP constB = 5 := by decide +kernel + +/-! ### Consequences of the finite checks -/ + +/-- Counting columns with a property via the list `L 4` of all columns. -/ +private theorem card_filter_col (P : Col → Prop) [DecidablePred P] (B : Col → Bool) + (hB : ∀ u, B u = true ↔ P u) : (Finset.univ.filter P).card = (L 4).countP B := by + rw [Finset.card_def, Finset.filter_val, univ_val, Multiset.filter_coe, Multiset.coe_card, + List.countP_eq_length_filter] + congr 1 + apply List.filter_congr + intro u _ + rw [Bool.eq_iff_iff, decide_eq_true_iff, hB] + +/-- Every injective column is compatible with some representative. -/ +private theorem cover (u : Col) (hu : Function.Injective u) : ∃ k : Fin 48, RR (rep k) u := by + have h := List.all_eq_true.1 cover_check u (mem_L 4 u) + rw [← injB_iff] at hu + simp only [hu, Bool.not_true, Bool.false_or, List.any_eq_true, List.mem_finRange, + true_and] at h + obtain ⟨k, hk⟩ := h + exact ⟨k, (RRb_iff _ _).1 hk⟩ + +/-- The constant columns. -/ +private def Cst : Finset Col := Finset.univ.filter fun u => ∀ a, u a = u 0 + +/-- The columns compatible with the `k`-th representative. -/ +private def A (k : Fin 48) : Finset Col := Finset.univ.filter fun w => RR (rep k) w + +/-- There are `5` constant columns. -/ +private theorem card_Cst : Cst.card = 5 := by + rw [Cst, card_filter_col _ constB constB_iff, const_check] + +/-- `9` columns are compatible with each of the first `12` representatives, `7` with the +others. -/ +private theorem card_A (k : Fin 48) : (A k).card = if k.val < 12 then 9 else 7 := by + rw [A, card_filter_col _ (RRb (rep k)) (RRb_iff _), count_check] + +/-- Constant columns are compatible with every representative. -/ +private theorem Cst_sub_A (k : Fin 48) : Cst ⊆ A k := by + intro u hu + simp only [Cst, A, Finset.mem_filter, Finset.mem_univ, true_and] at hu ⊢ + exact RR_const_right _ hu + +/-- The good column families: pairwise compatible columns, and the four rows distinct. -/ +private def V (n : ℕ) : Finset (Fin n → Col) := + Finset.univ.filter fun G => + (∀ i j, RR (G i) (G j)) ∧ ∀ a b : Fin 4, (∀ i, G i a = G i b) → a = b + +/-- Column families whose columns are all compatible with the `k`-th representative, not all +constant. -/ +private def W (n : ℕ) (k : Fin 48) : Finset (Fin n → Col) := + Fintype.piFinset (fun _ => A k) \ Fintype.piFinset (fun _ => Cst) + +/-- Membership in `W n k`. -/ +private theorem mem_W {n : ℕ} {k : Fin 48} {G : Fin n → Col} : + G ∈ W n k ↔ (∀ i, RR (rep k) (G i)) ∧ ∃ i a, G i a ≠ G i 0 := by + simp only [W, Finset.mem_sdiff, Fintype.mem_piFinset, A, Cst, Finset.mem_filter, + Finset.mem_univ, true_and, not_forall] + +/-- The good families are those whose columns are all compatible with one representative, +not all constant. -/ +private theorem V_eq (n : ℕ) : V n = Finset.univ.biUnion (W n) := by + ext G + simp only [V, Finset.mem_filter, Finset.mem_univ, true_and, Finset.mem_biUnion, mem_W] + constructor + · rintro ⟨hR, hD⟩ + have hnc : ∃ i a, G i a ≠ G i 0 := by + by_contra hc + simp only [not_exists, not_not] at hc + have := hD 1 0 (fun i => hc i 1) + exact absurd this (by decide) + obtain ⟨i₀, a₀, ha₀⟩ := hnc + have hinj : Function.Injective (G i₀) := by + intro a b hab + by_contra hne + have : ¬ ∀ i, G i a = G i b := fun h => hne (hD a b h) + simp only [not_forall] at this + obtain ⟨j, hj⟩ := this + have hc := const_of_RR (hR i₀ j) hab hj + exact ha₀ ((hc a₀).trans (hc 0).symm) + obtain ⟨k, hk⟩ := cover (G i₀) hinj + exact ⟨k, fun j => RR_trans (a₀ := a₀) (b₀ := 0) ha₀ (RR_symm hk) (hR i₀ j), i₀, a₀, ha₀⟩ + · rintro ⟨k, hk, i₀, a₀, ha₀⟩ + have hrep : Function.Injective (rep k) := (injB_iff _).1 (rep_injB k) + refine ⟨fun i j => RR_trans (a₀ := 0) (b₀ := 1) + (fun h => absurd (hrep h) (by decide)) (hk i) (hk j), ?_⟩ + intro a b hab + by_contra hne + have hc := const_of_RR (RR_symm (hk i₀)) (hab i₀) (fun h => hne (hrep h)) + exact ha₀ ((hc a₀).trans (hc 0).symm) + +/-- The pieces `W n k` are pairwise disjoint. -/ +private theorem W_disj (n : ℕ) : + ((Finset.univ : Finset (Fin 48)) : Set (Fin 48)).PairwiseDisjoint (W n) := by + intro k _ k' _ hkk' + rw [Function.onFun, Finset.disjoint_left] + intro G hG hG' + rw [mem_W] at hG hG' + obtain ⟨hk, i₀, a₀, ha₀⟩ := hG + have h := RR_trans (a₀ := a₀) (b₀ := 0) ha₀ (RR_symm (hk i₀)) (RR_symm (hG'.1 i₀)) + have := rep_sep k k' hkk' + rw [(RRb_iff _ _).2 h] at this + exact Bool.noConfusion this + +/-- The size of the piece `W n k`. -/ +private theorem card_W (n : ℕ) (k : Fin 48) : + (W n k).card = (if k.val < 12 then 9 else 7) ^ n - 5 ^ n := by + rw [W, Finset.card_sdiff_of_subset (Fintype.piFinset_subset _ _ fun _ => Cst_sub_A k), + Fintype.card_piFinset_const, Fintype.card_piFinset_const, card_A, card_Cst] + +/-- The number of good column families. -/ +private theorem card_V (n : ℕ) : (V n).card = 12 * (9 ^ n - 5 ^ n) + 36 * (7 ^ n - 5 ^ n) := by + rw [V_eq, Finset.card_biUnion (W_disj n)] + have h : ∀ k : Fin 48, (W n k).card = + if k.val < 12 then 9 ^ n - 5 ^ n else 7 ^ n - 5 ^ n := by + intro k; rw [card_W]; split_ifs <;> rfl + rw [Finset.sum_congr rfl (fun k _ => h k), Finset.sum_ite, Finset.sum_const, Finset.sum_const, + smul_eq_mul, smul_eq_mul] + have h12 : (Finset.univ.filter fun k : Fin 48 => k.val < 12).card = 12 := by decide + have h36 : (Finset.univ.filter fun k : Fin 48 => ¬ k.val < 12).card = 36 := by decide + rw [h12, h36] + +/-! ### Ordered 4-tuples -/ + +/-- Ordered 4-tuples of distinct collinear grid points. -/ +private def E (n : ℕ) : Finset (Fin 4 → Pt n) := + Finset.univ.filter fun f => Function.Injective f ∧ ∀ a b c, Coll3 (f a) (f b) (f c) + +/-- Transposition: ordered collinear 4-tuples are the good column families. -/ +private theorem card_E_V (n : ℕ) : (E n).card = (V n).card := by + refine Finset.card_bij' (fun f _ => fun i a => f a i) (fun G _ => fun a i => G i a) ?_ ?_ ?_ ?_ + · intro f hf + simp only [E, V, Finset.mem_filter, Finset.mem_univ, true_and] at hf ⊢ + exact ⟨fun i j a b c => hf.2 a b c i j, fun a b h => hf.1 (funext h)⟩ + · intro G hG + simp only [E, V, Finset.mem_filter, Finset.mem_univ, true_and] at hG ⊢ + exact ⟨fun a b h => hG.2 a b (fun i => congrFun h i), fun a b c i j => hG.1 i j a b c⟩ + · intro f _; rfl + · intro G _; rfl + +/-- Each 4-element set is the image of exactly `24` injective maps from `Fin 4`. -/ +private theorem fiber_card {α : Type*} [Fintype α] [DecidableEq α] (s : Finset α) + (hs : s.card = 4) : + (Finset.univ.filter fun f : Fin 4 → α => + Function.Injective f ∧ Finset.univ.image f = s).card = 24 := by + have key : (Finset.univ.filter fun f : Fin 4 → α => + Function.Injective f ∧ Finset.univ.image f = s).card = + (Finset.univ : Finset (Fin 4 ↪ s)).card := by + refine Finset.card_bij' (fun f hf => ⟨fun a => ⟨f a, ?_⟩, ?_⟩) + (fun g _ => fun a => ((g a : s) : α)) (fun _ _ => Finset.mem_univ _) ?_ ?_ ?_ + · have h := (Finset.mem_filter.1 hf).2.2 + rw [← h] + exact Finset.mem_image_of_mem f (Finset.mem_univ a) + · intro a b h + exact (Finset.mem_filter.1 hf).2.1 (congrArg Subtype.val h) + · intro g _ + simp only [Finset.mem_filter, Finset.mem_univ, true_and] + have hg : Function.Injective fun a => ((g a : s) : α) := + fun a b h => g.injective (Subtype.ext h) + refine ⟨hg, ?_⟩ + apply Finset.eq_of_subset_of_card_le + · intro x hx + obtain ⟨a, _, rfl⟩ := Finset.mem_image.1 hx + exact (g a).2 + · rw [hs, Finset.card_image_of_injective _ hg]; simp + · intro f _; rfl + · intro g _; rfl + rw [key, Finset.card_univ, Fintype.card_embedding_eq] + simp [hs] + +/-- Each collinear 4-set corresponds to `24` ordered 4-tuples. -/ +private theorem card_E (n : ℕ) : (E n).card = 24 * a n := by + have hmaps : ((E n : Finset (Fin 4 → Pt n)) : Set (Fin 4 → Pt n)).MapsTo + (fun f => Finset.univ.image f) + ((Finset.univ : Finset (Pt n)).powersetCard 4 |>.filter IsCollinear) := by + intro f hf + simp only [E, Finset.coe_filter, Finset.mem_univ, true_and, Set.mem_ofPred_eq] at hf + simp only [Finset.coe_filter, Finset.mem_powersetCard, Finset.subset_univ, true_and, + Set.mem_ofPred_eq] + refine ⟨?_, ?_⟩ + · rw [Finset.card_image_of_injective _ hf.1]; simp + · intro p hp q hq r hr + obtain ⟨x, _, rfl⟩ := Finset.mem_image.1 hp + obtain ⟨y, _, rfl⟩ := Finset.mem_image.1 hq + obtain ⟨z, _, rfl⟩ := Finset.mem_image.1 hr + exact hf.2 x y z + rw [Finset.card_eq_sum_card_fiberwise hmaps] + have hfib : ∀ s ∈ ((Finset.univ : Finset (Pt n)).powersetCard 4 |>.filter IsCollinear), + ((E n).filter fun f => Finset.univ.image f = s).card = 24 := by + intro s hs + rw [Finset.mem_filter, Finset.mem_powersetCard] at hs + rw [← fiber_card s hs.1.2] + congr 1 + ext f + simp only [E, Finset.mem_filter, Finset.mem_univ, true_and] + constructor + · rintro ⟨⟨hinj, _⟩, himg⟩; exact ⟨hinj, himg⟩ + · rintro ⟨hinj, himg⟩ + refine ⟨⟨hinj, fun x y z => ?_⟩, himg⟩ + have mem : ∀ x, f x ∈ s := fun x => himg ▸ Finset.mem_image_of_mem f (Finset.mem_univ x) + exact hs.2 _ (mem x) _ (mem y) _ (mem z) + rw [Finset.sum_congr rfl hfib, Finset.sum_const, smul_eq_mul, mul_comm] + rfl + +/-! ### The closed form and the conjecture -/ + +/-- The count, multiplied by `24`. -/ +private theorem a_mul (n : ℕ) : 24 * a n = 12 * (9 ^ n - 5 ^ n) + 36 * (7 ^ n - 5 ^ n) := by + rw [← card_E, card_E_V, card_V] + +/-- Mathar's closed form. -/ +private theorem closed (n : ℕ) : (a n : ℚ) = 9 ^ n / 2 + 3 * 7 ^ n / 2 - 2 * 5 ^ n := by + have h := a_mul n + have h9 : 5 ^ n ≤ 9 ^ n := Nat.pow_le_pow_left (by norm_num) n + have h7 : 5 ^ n ≤ 7 ^ n := Nat.pow_le_pow_left (by norm_num) n + have hq : (24 : ℚ) * a n = 12 * ((9 : ℚ) ^ n - 5 ^ n) + 36 * ((7 : ℚ) ^ n - 5 ^ n) := by + have := congrArg (fun x : ℕ => (x : ℚ)) h + push_cast [Nat.cast_sub h9, Nat.cast_sub h7] at this + linear_combination this + linear_combination hq / 24 + +/-- Mathar's conjecture for A178295 holds. -/ +theorem result : statement := by + refine ⟨closed, ?_, ?_⟩ + · intro n hn + obtain ⟨m, rfl⟩ := Nat.exists_eq_add_of_le' hn + have e1 : m + 3 - 1 = m + 2 := by omega + have e2 : m + 3 - 2 = m + 1 := by omega + have e3 : m + 3 - 3 = m := by omega + rw [e1, e2, e3] + apply Int.cast_injective (α := ℚ) + push_cast + rw [closed, closed, closed, closed] + ring + · rw [genFun_iff] + ext n + rw [show PowerSeries.mk (fun n => (a n : ℚ)) * den = + PowerSeries.C (-1 : ℚ) * PowerSeries.mk (fun n => (a n : ℚ)) + + PowerSeries.C (21 : ℚ) * (PowerSeries.mk (fun n => (a n : ℚ)) * PowerSeries.X ^ 1) + + PowerSeries.C (-143 : ℚ) * (PowerSeries.mk (fun n => (a n : ℚ)) * PowerSeries.X ^ 2) + + PowerSeries.C (315 : ℚ) * (PowerSeries.mk (fun n => (a n : ℚ)) * PowerSeries.X ^ 3) by + unfold den; simp only [map_neg, map_one, map_ofNat]; ring] + rw [show (PowerSeries.X * (-5 + 41 * PowerSeries.X) : PowerSeries ℚ) = + PowerSeries.C (-5 : ℚ) * PowerSeries.X ^ 1 + PowerSeries.C (41 : ℚ) * PowerSeries.X ^ 2 by + simp only [map_neg, map_ofNat]; ring] + simp only [map_add, PowerSeries.coeff_C_mul, PowerSeries.coeff_mul_X_pow', + PowerSeries.coeff_mk, PowerSeries.coeff_C] + rcases n with _ | _ | _ | m + · simp [closed]; norm_num + · simp [closed]; norm_num + · simp [closed]; norm_num + · have e1 : m + 3 - 1 = m + 2 := by omega + have e2 : m + 3 - 2 = m + 1 := by omega + have e3 : m + 3 - 3 = m := by omega + simp only [show 1 ≤ m + 3 by omega, show 2 ≤ m + 3 by omega, show 3 ≤ m + 3 by omega, + if_true, e1, e2, e3, show m + 2 ≠ 0 by omega, show m + 1 ≠ 0 by omega, if_false, closed] + ring + +end Math0.Frontier.A178295 + +#math0_settles Math0.Frontier.A178295.result Math0.Statements.A178295.statement diff --git a/lean/Math0/Frontier/OEIS/A182617.lean b/lean/Math0/Frontier/OEIS/A182617.lean new file mode 100644 index 0000000..7798a6a --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A182617.lean @@ -0,0 +1,838 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A182617 +import Math0.Audit + +/-! +# The toothpick spiral around `n` hexagonal cells (A182617): `a(n) = 2n + ⌈√(12n - 3)⌉` + +We prove Librandi's conjecture: for `n ≥ 1`, the first time at which the toothpick spiral has +`n` cells ON is `2n + ⌈√(12n - 3)⌉`. + +**The spiral in closed form.** In the brick-wall coordinates of the statement, the walk visits +"vertex ring" `m ≥ 0` during the times `bs m, …, bs m + 12 m + 7` with `bs m = 6 m² + 2 m`. The +`k`-th vertex of ring `m` is `pos m k`, a piecewise-linear function with six sides (two +horizontal rows and four staircases). Conversely `rg` and `off` (piecewise linear, with `max` +and halving) compute the ring and the offset of any vertex, so every vertex `v` gets an explicit +visit time `Q v = bs (rg v) + off v`, and `Q` is injective. A case analysis over the sides of +a ring (`LL`) shows the local rule of the spiral: arriving at `pos m k` from its predecessor, +either the left turn is the successor, or the left turn is an already visited vertex (on ring +`m - 1`, or the start for `m = 0`) and the right turn is the successor. By induction on `t` +(`inv`, `mem_walk`) the walk after `t` toothpicks covers exactly the vertices with `Q ≤ t`. + +**Cells.** Cells are enumerated ring by ring: `cpos j s` is cell `s ∈ [1, 6 j]` of cell ring +`j` (and `cpos 0 0` is the centre); this is a bijection onto all cells. For each cell, an +explicit vertex is visited last, at time `Tz j s = 6 j² - 1 + 2 s + cc j s`, where +`cc j s ∈ {1, …, 6}` is one more than the number of corners of the cell ring passed so far +(`cell_complete`). With `n = 3 j (j - 1) + 1 + s` one has +`12 n - 3 = (6 j - 3)² + 12 s`, and squeezing between consecutive squares gives +`⌈√(12 n - 3)⌉ = 6 j - 3 + cc j s`, i.e. `Tz j s = 2 n + ⌈√(12 n - 3)⌉` (`TT_eq`). Since +this is strictly increasing in `n`, the cells ON after `t` toothpicks are exactly the cells +with index `n` satisfying `2 n + ⌈√(12 n - 3)⌉ ≤ t`, and the count follows. +-/ + +namespace Math0.Frontier.A182617 +open Math0.Statements.A182617 + +/-- The ring index of a vertex: the spiral visits the vertices of ring `m` at times `bs m, …, bs m + +12 m + 7`. -/ +private def rg (v : Pt) : ℤ := + if v.2 ≤ 0 then max (max (-v.2) ((1 - v.1 - v.2) / 2)) ((v.1 - v.2 - 1) / 2) + else max (max (v.2 - 1) ((v.1 + v.2 - 2) / 2)) ((v.2 - v.1 - 2) / 2) + +/-- The offset of the vertex `v` inside ring `m` (six sides `A`–`F` of the ring). -/ +private def offm (m : ℤ) (v : Pt) : ℤ := + if v.2 ≤ 0 then + (if v.1 + v.2 ≤ 1 - 2 * m then v.1 + 2 * m - v.2 + else if v.2 = -m then 3 * m + v.1 else 4 * m + v.1 + v.2) + else + (if v.1 + v.2 ≥ 2 * m + 2 then 8 * m + 4 - v.1 + v.2 + else if v.2 = m + 1 then 9 * m + 5 - v.1 else 10 * m + 6 - v.1 - v.2) + +/-- The offset of a vertex inside its ring. -/ +private def off (v : Pt) : ℤ := offm (rg v) v + +/-- The vertex of ring `m` with offset `k` (for `0 ≤ k ≤ 12 m + 7`). -/ +private def pos (m k : ℤ) : Pt := + if k ≤ 2 * m then (-2 * m + (k + 1) / 2, -(k / 2)) + else if k ≤ 4 * m + 2 then (k - 3 * m, -m) + else if k ≤ 6 * m + 2 then (m + 2 + (k - 4 * m - 2) / 2, -m + (k - 4 * m - 1) / 2) + else if k ≤ 8 * m + 3 then (2 * m + 2 - (k - 6 * m - 2) / 2, (k - 6 * m - 1) / 2) + else if k ≤ 10 * m + 7 then (9 * m + 5 - k, m + 1) + else (-m - 2 - (k - 10 * m - 7) / 2, m + 1 - (k - 10 * m - 6) / 2) + +/-- `rg` and `off` invert `pos` on valid ring/offset pairs. -/ +private lemma D2 (m k : ℤ) (hm : 0 ≤ m) (hk : 0 ≤ k) (hk' : k ≤ 12 * m + 7) : + rg (pos m k) = m ∧ off (pos m k) = k := by + have hr : rg (pos m k) = m := by + unfold pos + split_ifs <;> (unfold rg; omega) + refine ⟨hr, ?_⟩ + unfold off; rw [hr] + unfold pos + split_ifs <;> (unfold offm; omega) + +/-- Ring indices are nonnegative. -/ +private lemma rg_nonneg (v : Pt) : 0 ≤ rg v := by unfold rg; omega + +/-- Every vertex is `pos (rg v) (off v)`, with a valid offset. -/ +private lemma D1 (v : Pt) : 0 ≤ off v ∧ off v ≤ 12 * rg v + 7 ∧ pos (rg v) (off v) = v := by + obtain ⟨x, y⟩ := v + unfold off + have h0 := rg_nonneg (x, y) + generalize hm : rg (x, y) = m at h0 ⊢ + unfold rg at hm + simp only at hm + unfold offm + simp only + split_ifs with h1 h2 h3 h4 h5 <;> + (unfold pos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega) + +/-- The time at which ring `m` starts: `6 m² + 2 m`. -/ +private def bs (m : ℤ) : ℤ := 6 * m * m + 2 * m + +/-- The visit time of a vertex in the spiral (proved to be correct in `mem_walk`). -/ +private def Q (v : Pt) : ℤ := bs (rg v) + off v + +/-- Ring `m` has `12 m + 8` vertices. -/ +private lemma bs_succ (m : ℤ) : bs (m + 1) = bs m + 12 * m + 8 := by unfold bs; ring + +/-- Later rings start after earlier rings end. -/ +private lemma bs_mono {a b : ℤ} (ha : 0 ≤ a) (hab : a < b) : bs a + 12 * a + 8 ≤ bs b := by + unfold bs; nlinarith + +/-- Ring start times are nonnegative. -/ +private lemma bs_nonneg {a : ℤ} (ha : 0 ≤ a) : 0 ≤ bs a := by unfold bs; nlinarith + +/-- The visit time of `pos m k`. -/ +private lemma Q_pos (m k : ℤ) (hm : 0 ≤ m) (hk : 0 ≤ k) (hk' : k ≤ 12 * m + 7) : + Q (pos m k) = bs m + k := by + obtain ⟨h1, h2⟩ := D2 m k hm hk hk' + unfold Q; rw [h1, h2] + +/-- Visit times are nonnegative. -/ +private lemma Q_nonneg (v : Pt) : 0 ≤ Q v := by + have := D1 v; have := rg_nonneg v; have := bs_nonneg (rg_nonneg v); unfold Q; omega + +/-- Different vertices have different visit times. -/ +private lemma Q_inj {u v : Pt} (h : Q u = Q v) : u = v := by + have hu := D1 u; have hv := D1 v + have h0u := rg_nonneg u; have h0v := rg_nonneg v + unfold Q at h + have hr : rg u = rg v := by + rcases lt_trichotomy (rg u) (rg v) with h1 | h1 | h1 + · have := bs_mono h0u h1; omega + · exact h1 + · have := bs_mono h0v h1; omega + have ho : off u = off v := by rw [hr] at h; omega + rw [← hu.2.2, ← hv.2.2, hr, ho] + +/-- `pos` on side `A` of a ring (extended range). -/ +private lemma pos_A (m k : ℤ) (_hm : 0 ≤ m) (h0 : 0 ≤ k) (h1 : k ≤ 2 * m + 1) : + pos m k = (-2 * m + (k + 1) / 2, -(k / 2)) := by + unfold pos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega + +/-- `pos` on side `B` of a ring. -/ +private lemma pos_B (m k : ℤ) (_hm : 0 ≤ m) (h0 : 2 * m ≤ k) (h1 : k ≤ 4 * m + 2) : + pos m k = (k - 3 * m, -m) := by + unfold pos; split_ifs <;> rw [Prod.mk.injEq] <;> omega + +/-- `pos` on side `C` of a ring (extended range). -/ +private lemma pos_C (m k : ℤ) (hm : 0 ≤ m) (h0 : 4 * m + 1 ≤ k) (h1 : k ≤ 6 * m + 3) : + pos m k = (m + 2 + (k - 4 * m - 2) / 2, -m + (k - 4 * m - 1) / 2) := by + unfold pos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega + +/-- `pos` on side `D` of a ring (extended range). -/ +private lemma pos_D (m k : ℤ) (hm : 0 ≤ m) (h0 : 6 * m + 2 ≤ k) (h1 : k ≤ 8 * m + 4) : + pos m k = (2 * m + 2 - (k - 6 * m - 2) / 2, (k - 6 * m - 1) / 2) := by + unfold pos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega + +/-- `pos` on side `E` of a ring. -/ +private lemma pos_E (m k : ℤ) (hm : 0 ≤ m) (h0 : 8 * m + 3 ≤ k) (h1 : k ≤ 10 * m + 7) : + pos m k = (9 * m + 5 - k, m + 1) := by + unfold pos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega + +/-- `pos` on side `F` of a ring (and beyond). -/ +private lemma pos_F (m k : ℤ) (hm : 0 ≤ m) (h0 : 10 * m + 6 ≤ k) : + pos m k = (-m - 2 - (k - 10 * m - 7) / 2, m + 1 - (k - 10 * m - 6) / 2) := by + unfold pos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega + +/-- `turns` in explicit coordinates. -/ +private lemma turns_eq (p : Pt) (x y : ℤ) : turns p (x, y) = + if (x + y) % 2 = 0 then + (if p = (x + 1, y) then ((x - 1, y), (x, y + 1)) + else if p = (x, y + 1) then ((x + 1, y), (x - 1, y)) else ((x, y + 1), (x + 1, y))) + else + (if p = (x + 1, y) then ((x, y - 1), (x - 1, y)) + else if p = (x - 1, y) then ((x + 1, y), (x, y - 1)) else ((x - 1, y), (x + 1, y))) := by + simp only [turns, nbrs] + split_ifs <;> rfl + +/-- The local step property at `v`, coming from `p`, with intended next vertex `n`: either the left +turn is `n`, or the left turn is an earlier vertex and the right turn is `n`. -/ +private def LLgoal (p v n : Pt) (m k : ℤ) : Prop := + (turns p v).1 = n ∨ ((turns p v).2 = n ∧ ∃ m' k', 0 ≤ m' ∧ 0 ≤ k' ∧ k' ≤ 12 * m' + 7 ∧ + (m' < m ∨ (m' = m ∧ k' < k)) ∧ (turns p v).1 = pos m' k') + +set_option maxHeartbeats 4000000 in +/-- The local step property for a generic vertex of ring `m ≥ 1`. -/ +private lemma LL_gen (m k : ℤ) (hm : 1 ≤ m) (hk1 : 1 ≤ k) (hk2 : k ≤ 12 * m + 6) : + LLgoal (pos m (k - 1)) (pos m k) (pos m (k + 1)) m k := by + unfold LLgoal + rcases (by omega : k ≤ 2 * m ∨ (2 * m + 1 ≤ k ∧ k ≤ 4 * m + 1) ∨ k = 4 * m + 2 ∨ + (4 * m + 3 ≤ k ∧ k ≤ 6 * m + 2) ∨ (6 * m + 3 ≤ k ∧ k ≤ 8 * m + 3) ∨ + (8 * m + 4 ≤ k ∧ k ≤ 10 * m + 6) ∨ k = 10 * m + 7 ∨ 10 * m + 8 ≤ k) with + h | h | h | h | h | h | h | h + · rw [pos_A m k (by omega) (by omega) (by omega), pos_A m (k - 1) (by omega) (by omega) (by omega), + pos_A m (k + 1) (by omega) (by omega) (by omega), turns_eq] + simp only [Prod.mk.injEq] + split_ifs <;> simp only [Prod.mk.injEq] <;> first + | omega + | (left; omega) + | (right; refine ⟨by omega, m - 1, k - 1, by omega, by omega, by omega, by omega, ?_⟩ + rw [pos_A (m - 1) (k - 1) (by omega) (by omega) (by omega)]; simp only [Prod.mk.injEq]; omega) + · rw [pos_B m k (by omega) (by omega) (by omega), pos_B m (k - 1) (by omega) (by omega) (by omega), + pos_B m (k + 1) (by omega) (by omega) (by omega), turns_eq] + simp only [Prod.mk.injEq, and_true] + split_ifs <;> simp only [Prod.mk.injEq, and_true] <;> first + | omega + | (left; omega) + | (right; refine ⟨by omega, m - 1, k - 3, by omega, by omega, by omega, by omega, ?_⟩ + rw [pos_B (m - 1) (k - 3) (by omega) (by omega) (by omega)]; simp only [Prod.mk.injEq]; omega) + · rw [pos_B m k (by omega) (by omega) (by omega), pos_B m (k - 1) (by omega) (by omega) (by omega), + pos_C m (k + 1) (by omega) (by omega) (by omega), turns_eq] + simp only [Prod.mk.injEq, and_true] + split_ifs <;> simp only [Prod.mk.injEq] <;> first + | omega + · rw [pos_C m k (by omega) (by omega) (by omega), pos_C m (k - 1) (by omega) (by omega) (by omega), + pos_C m (k + 1) (by omega) (by omega) (by omega), turns_eq] + simp only [Prod.mk.injEq] + split_ifs <;> simp only [Prod.mk.injEq] <;> first + | omega + | (left; omega) + | (right; refine ⟨by omega, m - 1, k - 5, by omega, by omega, by omega, by omega, ?_⟩ + rw [pos_C (m - 1) (k - 5) (by omega) (by omega) (by omega)]; simp only [Prod.mk.injEq]; omega) + · rw [pos_D m k (by omega) (by omega) (by omega), pos_D m (k - 1) (by omega) (by omega) (by omega), + pos_D m (k + 1) (by omega) (by omega) (by omega), turns_eq] + simp only [Prod.mk.injEq] + split_ifs <;> simp only [Prod.mk.injEq] <;> first + | omega + | (left; omega) + | (right; refine ⟨by omega, m - 1, k - 7, by omega, by omega, by omega, by omega, ?_⟩ + rw [pos_D (m - 1) (k - 7) (by omega) (by omega) (by omega)]; simp only [Prod.mk.injEq]; omega) + · rw [pos_E m k (by omega) (by omega) (by omega), pos_E m (k - 1) (by omega) (by omega) (by omega), + pos_E m (k + 1) (by omega) (by omega) (by omega), turns_eq] + simp only [Prod.mk.injEq, and_true] + split_ifs <;> simp only [Prod.mk.injEq, and_true] <;> first + | omega + | (left; omega) + | (right; refine ⟨by omega, m - 1, k - 9, by omega, by omega, by omega, by omega, ?_⟩ + rw [pos_E (m - 1) (k - 9) (by omega) (by omega) (by omega)]; simp only [Prod.mk.injEq]; omega) + · rw [pos_E m k (by omega) (by omega) (by omega), pos_E m (k - 1) (by omega) (by omega) (by omega), + pos_F m (k + 1) (by omega) (by omega), turns_eq] + simp only [Prod.mk.injEq, and_true] + split_ifs <;> simp only [Prod.mk.injEq] <;> first + | omega + · rw [pos_F m k (by omega) (by omega), pos_F m (k - 1) (by omega) (by omega), + pos_F m (k + 1) (by omega) (by omega), turns_eq] + simp only [Prod.mk.injEq] + split_ifs <;> simp only [Prod.mk.injEq] <;> first + | omega + | (left; omega) + | (right; refine ⟨by omega, m - 1, k - 11, by omega, by omega, by omega, by omega, ?_⟩ + rw [pos_F (m - 1) (k - 11) (by omega) (by omega)]; simp only [Prod.mk.injEq]; omega) + +/-- The local step property at the first vertex of a ring. -/ +private lemma LL_start (m : ℤ) (hm : 1 ≤ m) : + LLgoal (pos (m - 1) (12 * m - 5)) (pos m 0) (pos m 1) m 0 := by + unfold LLgoal + rw [pos_F (m - 1) (12 * m - 5) (by omega) (by omega), pos_A m 0 (by omega) (by omega) (by omega), + pos_A m 1 (by omega) (by omega) (by omega), turns_eq] + simp only [Prod.mk.injEq] + split_ifs <;> simp only [Prod.mk.injEq] <;> first + | omega + +/-- The local step property at the last vertex of a ring. -/ +private lemma LL_end (m : ℤ) (hm : 0 ≤ m) : + LLgoal (pos m (12 * m + 6)) (pos m (12 * m + 7)) (pos (m + 1) 0) m (12 * m + 7) := by + unfold LLgoal + rw [pos_F m (12 * m + 6) (by omega) (by omega), pos_F m (12 * m + 7) (by omega) (by omega), + pos_A (m + 1) 0 (by omega) (by omega) (by omega), turns_eq] + simp only [Prod.mk.injEq] + split_ifs <;> simp only [Prod.mk.injEq] <;> first + | omega + +/-- The local step property in ring `0`. -/ +private lemma LL_zero (k : ℤ) (hk1 : 1 ≤ k) (hk2 : k ≤ 6) : + LLgoal (pos 0 (k - 1)) (pos 0 k) (pos 0 (k + 1)) 0 k := by + unfold LLgoal + interval_cases k + · rw [show pos 0 (1 - 1) = (0, 0) by decide, show pos 0 1 = (1, 0) by decide, + show pos 0 (1 + 1) = (2, 0) by decide, turns_eq] + norm_num + · rw [show pos 0 (2 - 1) = (1, 0) by decide, show pos 0 2 = (2, 0) by decide, + show pos 0 (2 + 1) = (2, 1) by decide, turns_eq] + norm_num + · rw [show pos 0 (3 - 1) = (2, 0) by decide, show pos 0 3 = (2, 1) by decide, + show pos 0 (3 + 1) = (1, 1) by decide, turns_eq] + norm_num + · rw [show pos 0 (4 - 1) = (2, 1) by decide, show pos 0 4 = (1, 1) by decide, + show pos 0 (4 + 1) = (0, 1) by decide, turns_eq] + norm_num + · rw [show pos 0 (5 - 1) = (1, 1) by decide, show pos 0 5 = (0, 1) by decide, + show pos 0 (5 + 1) = (-1, 1) by decide, turns_eq] + norm_num + exact ⟨0, le_rfl, 0, le_rfl, by norm_num, by norm_num, by decide⟩ + · rw [show pos 0 (6 - 1) = (0, 1) by decide, show pos 0 6 = (-1, 1) by decide, + show pos 0 (6 + 1) = (-2, 1) by decide, turns_eq] + norm_num + +/-- The ring/offset pair visited just before `(m, k)`. -/ +private def prv (m k : ℤ) : ℤ × ℤ := if k = 0 then (m - 1, 12 * m - 5) else (m, k - 1) + +/-- The ring/offset pair visited just after `(m, k)`. -/ +private def nxt (m k : ℤ) : ℤ × ℤ := if k = 12 * m + 7 then (m + 1, 0) else (m, k + 1) + +/-- The local step property at every vertex other than the start. -/ +private lemma LL (m k : ℤ) (hm : 0 ≤ m) (hk : 0 ≤ k) (hk' : k ≤ 12 * m + 7) (h0 : 0 < m ∨ 0 < k) : + LLgoal (pos (prv m k).1 (prv m k).2) (pos m k) (pos (nxt m k).1 (nxt m k).2) m k := by + by_cases hk0 : k = 0 + · subst hk0 + have : nxt m 0 = (m, 0 + 1) := by unfold nxt; rw [if_neg (by omega)] + rw [this]; unfold prv; simp only [if_true] + exact LL_start m (by omega) + · have hp : prv m k = (m, k - 1) := by unfold prv; rw [if_neg hk0] + rw [hp] + by_cases hk7 : k = 12 * m + 7 + · subst hk7 + have : nxt m (12 * m + 7) = (m + 1, 0) := by unfold nxt; simp + rw [this] + have e : 12 * m + 7 - 1 = 12 * m + 6 := by ring + simp only; rw [e] + exact LL_end m hm + · have : nxt m k = (m, k + 1) := by unfold nxt; rw [if_neg hk7] + rw [this] + rcases (by omega : m = 0 ∨ 1 ≤ m) with h | h + · subst h; exact LL_zero k (by omega) (by omega) + · exact LL_gen m k h (by omega) (by omega) + +/-- `step` on a list with at least two entries. -/ +private lemma step_cons (v p : Pt) (rest : List Pt) : + step (v :: p :: rest) = + if (turns p v).1 ∉ v :: p :: rest then (turns p v).1 :: v :: p :: rest + else if (turns p v).2 ∉ v :: p :: rest then (turns p v).2 :: v :: p :: rest + else v :: p :: rest := rfl + +/-- One more toothpick is one more `step`. -/ +private lemma walk_succ (t : ℕ) (ht : 1 ≤ t) : walk (t + 1) = step (walk t) := by + obtain ⟨s, rfl⟩ : ∃ s, t = s + 1 := ⟨t - 1, by omega⟩ + simp only [walk] + exact Function.iterate_succ_apply' step s _ + +/-- Lexicographic order on ring/offset pairs gives the order of visit times. -/ +private lemma Q_lex {m k m' k' : ℤ} (hm' : 0 ≤ m') (hk' : k' ≤ 12 * m' + 7) (hk : 0 ≤ k) + (h : m' < m ∨ (m' = m ∧ k' < k)) : bs m' + k' < bs m + k := by + rcases h with h | ⟨rfl, h⟩ + · have := bs_mono hm' h; omega + · omega + +/-- The predecessor is visited one step earlier. -/ +private lemma Q_prv (m k : ℤ) (hm : 0 ≤ m) (hk : 0 ≤ k) (hk' : k ≤ 12 * m + 7) (h0 : 0 < m ∨ 0 < k) : + Q (pos (prv m k).1 (prv m k).2) + 1 = bs m + k := by + unfold prv; split_ifs with h + · simp only + rw [Q_pos (m - 1) (12 * m - 5) (by omega) (by omega) (by omega)] + have := bs_succ (m - 1); rw [sub_add_cancel] at this; omega + · simp only + rw [Q_pos m (k - 1) (by omega) (by omega) (by omega)]; ring + +/-- The successor is visited one step later. -/ +private lemma Q_nxt (m k : ℤ) (hm : 0 ≤ m) (hk : 0 ≤ k) (hk' : k ≤ 12 * m + 7) : + Q (pos (nxt m k).1 (nxt m k).2) = bs m + k + 1 := by + unfold nxt; split_ifs with h + · simp only + rw [Q_pos (m + 1) 0 (by omega) (by omega) (by omega), bs_succ]; omega + · simp only + rw [Q_pos m (k + 1) (by omega) (by omega) (by omega)]; ring + +/-- `(1, 0)` is visited at time `1`. -/ +private lemma Q10 : Q (1, 0) = 1 := by + have := Q_pos 0 1 (by norm_num) (by norm_num) (by norm_num) + rw [show pos 0 1 = (1, 0) by decide] at this + rw [this]; norm_num [bs] + +/-- `(0, 0)` is visited at time `0`. -/ +private lemma Q00 : Q (0, 0) = 0 := by + have := Q_pos 0 0 (by norm_num) (by norm_num) (by norm_num) + rw [show pos 0 0 = (0, 0) by decide] at this + rw [this]; norm_num [bs] + +/-- The walk invariant: after `t ≥ 1` toothpicks the walk ends at the vertices with visit times `t` +and `t - 1`, and covers exactly the vertices with visit time at most `t`. -/ +private lemma inv (t : ℕ) (ht : 1 ≤ t) : ∃ v p rest, walk t = v :: p :: rest ∧ Q v = t ∧ Q p + 1 = t ∧ + ∀ u, u ∈ walk t ↔ Q u ≤ t := by + induction t, ht using Nat.le_induction with + | base => + refine ⟨(1, 0), (0, 0), [], rfl, by rw [Q10]; norm_num, by rw [Q00]; norm_num, ?_⟩ + intro u + constructor + · intro h + change u ∈ [(1, 0), (0, 0)] at h + simp only [List.mem_cons, List.not_mem_nil, or_false] at h + rcases h with rfl | rfl + · rw [Q10]; norm_num + · rw [Q00]; norm_num + · intro h + have h0 := Q_nonneg u + change u ∈ [(1, 0), (0, 0)] + simp only [List.mem_cons, List.not_mem_nil, or_false] + rcases (by have := Q10; have := Q00; push_cast at h; omega : Q u = Q (1, 0) ∨ Q u = Q (0, 0)) with h1 | h1 + · exact Or.inl (Q_inj h1) + · exact Or.inr (Q_inj h1) + | succ t ht ih => + obtain ⟨v, p, rest, hw, hv, hp, hmem⟩ := ih + obtain ⟨hk0, hk1, hpos⟩ := D1 v + have hm0 := rg_nonneg v + have hQv : Q v = bs (rg v) + off v := rfl + have h0 : 0 < rg v ∨ 0 < off v := by + by_contra hc + have e1 : rg v = 0 := by omega + have e2 : off v = 0 := by omega + rw [e1, e2] at hQv; norm_num [bs] at hQv; omega + have hpp : pos (prv (rg v) (off v)).1 (prv (rg v) (off v)).2 = p := by + apply Q_inj + have := Q_prv (rg v) (off v) hm0 hk0 hk1 h0 + omega + have hQn := Q_nxt (rg v) (off v) hm0 hk0 hk1 + have hL := LL (rg v) (off v) hm0 hk0 hk1 h0 + rw [hpp, hpos] at hL + set n := pos (nxt (rg v) (off v)).1 (nxt (rg v) (off v)).2 with hn + have hnmem : n ∉ walk t := by + rw [hmem]; omega + rw [walk_succ t ht, hw, step_cons] + rw [hw] at hnmem hmem + have key : ∀ u, u ∈ n :: v :: p :: rest ↔ Q u ≤ ((t + 1 : ℕ) : ℤ) := by + intro u + rw [List.mem_cons, hmem] + push_cast + constructor + · rintro (rfl | h) + · omega + · omega + · intro h + by_cases h' : Q u ≤ t + · exact Or.inr h' + · left; apply Q_inj; omega + rcases hL with hL | ⟨hR, m', k', hm', hk', hk'', hlex, hl⟩ + · rw [hL, if_pos hnmem] + exact ⟨n, v, p :: rest, rfl, by push_cast; omega, by push_cast; omega, key⟩ + · have hlm : (turns p v).1 ∈ v :: p :: rest := by + rw [hmem, hl, Q_pos m' k' hm' hk' hk''] + have := Q_lex hm' hk'' hk0 hlex + omega + rw [if_neg (not_not.mpr hlm), hR, if_pos hnmem] + exact ⟨n, v, p :: rest, rfl, by push_cast; omega, by push_cast; omega, key⟩ + +/-- The vertices covered after `t` toothpicks are exactly those with visit time at most `t`. -/ +private lemma mem_walk (t : ℕ) (u : Pt) : u ∈ walk t ↔ Q u ≤ t := by + rcases Nat.eq_zero_or_pos t with rfl | ht + · simp only [walk, List.mem_cons, List.not_mem_nil, or_false, Nat.cast_zero] + constructor + · rintro rfl; rw [Q00] + · intro h; have := Q_nonneg u; apply Q_inj; rw [Q00]; omega + · obtain ⟨_, _, _, _, _, _, h⟩ := inv t ht + exact h u + +/-- The lower-left corner of cell number `s` (`1 ≤ s ≤ 6 j`) of cell ring `j`; `cpos 0 0` is the +central cell. -/ +private def cpos (j s : ℤ) : Pt := + if s ≤ j then (-j - s, j - s) + else if s ≤ 2 * j then (s - 3 * j, j - s) + else if s ≤ 3 * j then (2 * s - 5 * j, -j) + else if s ≤ 4 * j then (s - 2 * j, s - 4 * j) + else if s ≤ 5 * j then (6 * j - s, s - 4 * j) + else (11 * j - 2 * s, j) + +/-- Valid cell ring/index pairs. -/ +private def validC (j s : ℤ) : Prop := (j = 0 ∧ s = 0) ∨ (1 ≤ j ∧ 1 ≤ s ∧ s ≤ 6 * j) + +/-- `cpos` gives cell corners. -/ +private lemma cpos_even (j s : ℤ) : ((cpos j s).1 + (cpos j s).2) % 2 = 0 := by + unfold cpos; split_ifs <;> omega + +set_option maxHeartbeats 4000000 in +/-- Every cell is some `cpos j s`. -/ +private lemma cpos_surj (c : Pt) (hc : (c.1 + c.2) % 2 = 0) : ∃ j s, validC j s ∧ cpos j s = c := by + obtain ⟨x, y⟩ := c + simp only at hc + unfold validC + obtain ⟨q, hq⟩ : ∃ q, x = 2 * q + y := ⟨(x - y) / 2, by omega⟩ + subst hq + rcases (by omega : (q = 0 ∧ y = 0) ∨ (q < 0 ∧ 0 ≤ y ∧ y < -q) ∨ (y ≤ 0 ∧ q ≤ 0 ∧ q + y < 0) ∨ + (y < 0 ∧ 0 ≤ q ∧ q ≤ -y) ∨ (0 < q ∧ -q ≤ y ∧ y ≤ 0) ∨ (0 ≤ y ∧ 0 ≤ q ∧ 0 < q + y) ∨ + (0 < y ∧ -y ≤ q ∧ q ≤ 0)) with h | h | h | h | h | h | h + · obtain ⟨rfl, rfl⟩ := h + exact ⟨0, 0, by omega, by decide⟩ + · exact ⟨-q, -q - y, by omega, by unfold cpos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega⟩ + · exact ⟨-q - y, -q - 2 * y, by omega, by unfold cpos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega⟩ + · exact ⟨-y, q - 2 * y, by omega, by unfold cpos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega⟩ + · exact ⟨q, y + 4 * q, by omega, by unfold cpos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega⟩ + · exact ⟨q + y, 4 * q + 5 * y, by omega, by unfold cpos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega⟩ + · exact ⟨y, 5 * y - q, by omega, by unfold cpos; split_ifs <;> simp only [Prod.mk.injEq, and_true] <;> omega⟩ + +set_option maxHeartbeats 4000000 in +/-- `cpos` is injective on valid pairs. -/ +private lemma cpos_inj {j s j' s' : ℤ} (h : validC j s) (h' : validC j' s') (e : cpos j s = cpos j' s') : + j = j' ∧ s = s' := by + unfold validC at h h' + unfold cpos at e + split_ifs at e <;> simp only [Prod.mk.injEq] at e <;> omega + +/-- One more than the number of corners of the cell ring passed by cell `s` of ring `j`. -/ +private def cc (j s : ℤ) : ℤ := + if s < j then 1 else if s < 2 * j then 2 else if s < 3 * j then 3 + else if s < 4 * j then 4 else if s < 5 * j then 5 else 6 + +/-- The time at which cell `s` of cell ring `j` becomes ON. -/ +private def Tz (j s : ℤ) : ℤ := 6 * j * j - 1 + 2 * s + cc j s + +/-- Comparison of visit times through ring and offset. -/ +private lemma Q_le_lex (u : Pt) (mw kw : ℤ) (_hmw : 0 ≤ mw) (hkw : 0 ≤ kw) + (h : rg u < mw ∨ (rg u = mw ∧ off u ≤ kw)) : Q u ≤ bs mw + kw := by + have hu := D1 u; have h0 := rg_nonneg u + unfold Q + rcases h with h | ⟨h1, h2⟩ + · have := bs_mono h0 h; omega + · rw [h1]; omega + +/-- The vertices of the central cell are visited by time `5`. -/ +private lemma cv00 : ∀ u ∈ cellVerts (0, 0), rg u < 0 ∨ (rg u = 0 ∧ off u ≤ 5) := by decide + +set_option maxHeartbeats 4000000 in +/-- Vertex comparison for cells on side 0 of a cell ring. -/ +private lemma cv0 (j s : ℤ) (hj : 1 ≤ j) (h1 : 1 ≤ s) (h2 : s ≤ j - 1) : + ∀ u ∈ cellVerts (-j - s, j - s), + rg u < j - 1 ∨ (rg u = j - 1 ∧ off u ≤ 10 * j + 2 * s - 4) := by + intro u hu + simp only [cellVerts, List.mem_cons, List.not_mem_nil, or_false] at hu + rcases hu with rfl | rfl | rfl | rfl | rfl | rfl <;> (unfold off offm rg; simp only; omega) + +set_option maxHeartbeats 4000000 in +/-- Vertex comparison for cells on side 1 of a cell ring. -/ +private lemma cv1 (j s : ℤ) (hj : 1 ≤ j) (h1 : j ≤ s) (h2 : s ≤ 2 * j - 1) : + ∀ u ∈ cellVerts (s - 3 * j, j - s), rg u < j ∨ (rg u = j ∧ off u ≤ 2 * s - 2 * j + 1) := by + intro u hu + simp only [cellVerts, List.mem_cons, List.not_mem_nil, or_false] at hu + rcases hu with rfl | rfl | rfl | rfl | rfl | rfl <;> (unfold off offm rg; simp only; omega) + +set_option maxHeartbeats 4000000 in +/-- Vertex comparison for cells on side 2 of a cell ring. -/ +private lemma cv2 (j s : ℤ) (hj : 1 ≤ j) (h1 : 2 * j ≤ s) (h2 : s ≤ 3 * j - 1) : + ∀ u ∈ cellVerts (2 * s - 5 * j, -j), rg u < j ∨ (rg u = j ∧ off u ≤ 2 * s - 2 * j + 2) := by + intro u hu + simp only [cellVerts, List.mem_cons, List.not_mem_nil, or_false] at hu + rcases hu with rfl | rfl | rfl | rfl | rfl | rfl <;> (unfold off offm rg; simp only; omega) + +set_option maxHeartbeats 4000000 in +/-- Vertex comparison for cells on side 3 of a cell ring. -/ +private lemma cv3 (j s : ℤ) (hj : 1 ≤ j) (h1 : 3 * j ≤ s) (h2 : s ≤ 4 * j - 1) : + ∀ u ∈ cellVerts (s - 2 * j, s - 4 * j), rg u < j ∨ (rg u = j ∧ off u ≤ 2 * s - 2 * j + 3) := by + intro u hu + simp only [cellVerts, List.mem_cons, List.not_mem_nil, or_false] at hu + rcases hu with rfl | rfl | rfl | rfl | rfl | rfl <;> (unfold off offm rg; simp only; omega) + +set_option maxHeartbeats 4000000 in +/-- Vertex comparison for cells on side 4 of a cell ring. -/ +private lemma cv4 (j s : ℤ) (hj : 1 ≤ j) (h1 : 4 * j ≤ s) (h2 : s ≤ 5 * j - 1) : + ∀ u ∈ cellVerts (6 * j - s, s - 4 * j), rg u < j ∨ (rg u = j ∧ off u ≤ 2 * s - 2 * j + 4) := by + intro u hu + simp only [cellVerts, List.mem_cons, List.not_mem_nil, or_false] at hu + rcases hu with rfl | rfl | rfl | rfl | rfl | rfl <;> (unfold off offm rg; simp only; omega) + +set_option maxHeartbeats 4000000 in +/-- Vertex comparison for cells on side 5 of a cell ring. -/ +private lemma cv5 (j s : ℤ) (hj : 1 ≤ j) (h1 : 5 * j ≤ s) (h2 : s ≤ 6 * j) : + ∀ u ∈ cellVerts (11 * j - 2 * s, j), rg u < j ∨ (rg u = j ∧ off u ≤ 2 * s - 2 * j + 5) := by + intro u hu + simp only [cellVerts, List.mem_cons, List.not_mem_nil, or_false] at hu + rcases hu with rfl | rfl | rfl | rfl | rfl | rfl <;> (unfold off offm rg; simp only; omega) + +/-- All six vertices of cell `(j, s)` are covered by time `Tz j s`, and one of them exactly then. -/ +private lemma cell_complete (j s : ℤ) (hv : validC j s) : + (∀ u ∈ cellVerts (cpos j s), Q u ≤ Tz j s) ∧ (∃ u ∈ cellVerts (cpos j s), Q u = Tz j s) := by + unfold validC at hv + rcases hv with ⟨rfl, rfl⟩ | ⟨hj, hs1, hs2⟩ + · have e : cpos 0 0 = (0, 0) := by decide + have hT : Tz 0 0 = bs 0 + 5 := by decide + rw [e, hT] + refine ⟨fun u hu => Q_le_lex u 0 5 le_rfl (by norm_num) (cv00 u hu), (0, 1), + by simp [cellVerts], ?_⟩ + rw [show ((0 : ℤ), (1 : ℤ)) = pos 0 5 by decide, Q_pos 0 5 (by norm_num) (by norm_num) (by norm_num)] + · rcases (by omega : s ≤ j - 1 ∨ (j ≤ s ∧ s ≤ 2 * j - 1) ∨ (2 * j ≤ s ∧ s ≤ 3 * j - 1) ∨ + (3 * j ≤ s ∧ s ≤ 4 * j - 1) ∨ (4 * j ≤ s ∧ s ≤ 5 * j - 1) ∨ 5 * j ≤ s) with h | h | h | h | h | h + · have e : cpos j s = (-j - s, j - s) := by unfold cpos; rw [if_pos (by omega)] + have hT : Tz j s = bs (j - 1) + (10 * j + 2 * s - 4) := by + unfold Tz cc bs; rw [if_pos (by omega)]; ring + have hw : pos (j - 1) (10 * j + 2 * s - 4) = (-j - s, j - s) := by + rw [pos_F _ _ (by omega) (by omega)]; simp only [Prod.mk.injEq]; omega + rw [e, hT] + refine ⟨fun u hu => Q_le_lex u _ _ (by omega) (by omega) (cv0 j s hj hs1 h u hu), + (-j - s, j - s), by simp [cellVerts], ?_⟩ + rw [← hw, Q_pos _ _ (by omega) (by omega) (by omega)] + · have e : cpos j s = (s - 3 * j, j - s) := by + unfold cpos; split_ifs <;> simp only [Prod.mk.injEq, and_true] <;> omega + have hT : Tz j s = bs j + (2 * s - 2 * j + 1) := by + unfold Tz cc bs; rw [if_neg (by omega), if_pos (by omega)]; ring + have hw : pos j (2 * s - 2 * j + 1) = (s - 3 * j + 1, j - s) := by + rw [pos_A _ _ (by omega) (by omega) (by omega)]; simp only [Prod.mk.injEq]; omega + rw [e, hT] + refine ⟨fun u hu => Q_le_lex u _ _ (by omega) (by omega) (cv1 j s hj h.1 h.2 u hu), + (s - 3 * j + 1, j - s), by simp [cellVerts], ?_⟩ + rw [← hw, Q_pos _ _ (by omega) (by omega) (by omega)] + · have e : cpos j s = (2 * s - 5 * j, -j) := by + unfold cpos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega + have hT : Tz j s = bs j + (2 * s - 2 * j + 2) := by + unfold Tz cc bs; rw [if_neg (by omega), if_neg (by omega), if_pos (by omega)]; ring + have hw : pos j (2 * s - 2 * j + 2) = (2 * s - 5 * j + 2, -j) := by + rw [pos_B _ _ (by omega) (by omega) (by omega)]; simp only [Prod.mk.injEq, and_true]; omega + rw [e, hT] + refine ⟨fun u hu => Q_le_lex u _ _ (by omega) (by omega) (cv2 j s hj h.1 h.2 u hu), + (2 * s - 5 * j + 2, -j), by simp [cellVerts], ?_⟩ + rw [← hw, Q_pos _ _ (by omega) (by omega) (by omega)] + · have e : cpos j s = (s - 2 * j, s - 4 * j) := by + unfold cpos; split_ifs <;> simp only [Prod.mk.injEq, and_true] <;> omega + have hT : Tz j s = bs j + (2 * s - 2 * j + 3) := by + unfold Tz cc bs + rw [if_neg (by omega), if_neg (by omega), if_neg (by omega), if_pos (by omega)]; ring + have hw : pos j (2 * s - 2 * j + 3) = (s - 2 * j + 2, s - 4 * j + 1) := by + rw [pos_C _ _ (by omega) (by omega) (by omega)]; simp only [Prod.mk.injEq]; omega + rw [e, hT] + refine ⟨fun u hu => Q_le_lex u _ _ (by omega) (by omega) (cv3 j s hj h.1 h.2 u hu), + (s - 2 * j + 2, s - 4 * j + 1), by simp [cellVerts], ?_⟩ + rw [← hw, Q_pos _ _ (by omega) (by omega) (by omega)] + · have e : cpos j s = (6 * j - s, s - 4 * j) := by + unfold cpos; split_ifs <;> simp only [Prod.mk.injEq, and_true] <;> omega + have hT : Tz j s = bs j + (2 * s - 2 * j + 4) := by + unfold Tz cc bs + rw [if_neg (by omega), if_neg (by omega), if_neg (by omega), if_neg (by omega), + if_pos (by omega)]; ring + have hw : pos j (2 * s - 2 * j + 4) = (6 * j - s + 1, s - 4 * j + 1) := by + rw [pos_D _ _ (by omega) (by omega) (by omega)]; simp only [Prod.mk.injEq]; omega + rw [e, hT] + refine ⟨fun u hu => Q_le_lex u _ _ (by omega) (by omega) (cv4 j s hj h.1 h.2 u hu), + (6 * j - s + 1, s - 4 * j + 1), by simp [cellVerts], ?_⟩ + rw [← hw, Q_pos _ _ (by omega) (by omega) (by omega)] + · have e : cpos j s = (11 * j - 2 * s, j) := by + unfold cpos; split_ifs <;> simp only [Prod.mk.injEq] <;> omega + have hT : Tz j s = bs j + (2 * s - 2 * j + 5) := by + unfold Tz cc bs + rw [if_neg (by omega), if_neg (by omega), if_neg (by omega), if_neg (by omega), + if_neg (by omega)]; ring + have hw : pos j (2 * s - 2 * j + 5) = (11 * j - 2 * s, j + 1) := by + rw [pos_E _ _ (by omega) (by omega) (by omega)]; simp only [Prod.mk.injEq, and_true]; omega + rw [e, hT] + refine ⟨fun u hu => Q_le_lex u _ _ (by omega) (by omega) (cv5 j s hj h hs2 u hu), + (11 * j - 2 * s, j + 1), by simp [cellVerts], ?_⟩ + rw [← hw, Q_pos _ _ (by omega) (by omega) (by omega)] + +/-- The integer squeeze behind `⌈√(12 n - 3)⌉ = 6 j - 3 + cc j s`. -/ +private lemma cc_bounds (j s : ℤ) (hv : validC j s) : + (6 * j - 4 + cc j s) ^ 2 < 36 * j * j - 36 * j + 9 + 12 * s ∧ + 36 * j * j - 36 * j + 9 + 12 * s ≤ (6 * j - 3 + cc j s) ^ 2 ∧ 1 ≤ 6 * j - 4 + cc j s := by + unfold validC at hv + rcases hv with ⟨rfl, rfl⟩ | ⟨hj, hs1, hs2⟩ + · decide + · unfold cc + split_ifs with h1 h2 h3 h4 h5 + · refine ⟨by nlinarith, by nlinarith, by omega⟩ + · refine ⟨by nlinarith, by nlinarith, by omega⟩ + · refine ⟨by nlinarith, by nlinarith, by omega⟩ + · refine ⟨by nlinarith, by nlinarith, by omega⟩ + · refine ⟨by nlinarith, by nlinarith, by omega⟩ + · refine ⟨by nlinarith, by nlinarith, by omega⟩ + +/-- The conjectured value `2 n + ⌈√(12 n - 3)⌉`. -/ +private noncomputable def TT (n : ℕ) : ℕ := 2 * n + ⌈Real.sqrt (12 * (n : ℝ) - 3)⌉₊ + +/-- The conjectured value at the index of cell `(j, s)` is the time `Tz j s` at which that cell +turns ON. -/ +private lemma TT_eq (j s : ℤ) (hv : validC j s) (n : ℕ) (hn : (n : ℤ) = 3 * j * (j - 1) + 1 + s) : + (TT n : ℤ) = Tz j s := by + obtain ⟨h1, h2, h3⟩ := cc_bounds j s hv + obtain ⟨M, hM⟩ : ∃ M : ℕ, (M : ℤ) = 6 * j - 4 + cc j s := ⟨(6 * j - 4 + cc j s).toNat, by omega⟩ + have hX : (36 * j * j - 36 * j + 9 + 12 * s : ℤ) = 12 * (n : ℤ) - 3 := by rw [hn]; ring + rw [hX, ← hM] at h1 + rw [hX, show 6 * j - 3 + cc j s = (M : ℤ) + 1 by omega] at h2 + have r1 : ((M : ℝ)) ^ 2 < 12 * (n : ℝ) - 3 := by exact_mod_cast h1 + have r2 : 12 * (n : ℝ) - 3 ≤ ((M : ℝ) + 1) ^ 2 := by exact_mod_cast h2 + have hc : ⌈Real.sqrt (12 * (n : ℝ) - 3)⌉₊ = M + 1 := by + apply le_antisymm + · rw [Nat.ceil_le, Real.sqrt_le_left (by positivity)] + push_cast; exact r2 + · rw [Nat.succ_le_iff, Nat.lt_ceil, Real.lt_sqrt (by positivity)] + exact r1 + unfold TT Tz + rw [hc]; push_cast + rw [hn, hM]; ring + +/-- The conjectured value is strictly increasing. -/ +private lemma TT_mono {a b : ℕ} (h : a < b) : TT a < TT b := by + unfold TT + have : ⌈Real.sqrt (12 * (a : ℝ) - 3)⌉₊ ≤ ⌈Real.sqrt (12 * (b : ℝ) - 3)⌉₊ := by + apply Nat.ceil_mono + apply Real.sqrt_le_sqrt + have : (a : ℝ) ≤ b := by exact_mod_cast h.le + linarith + omega + +/-- The conjectured value is an order embedding. -/ +private lemma TT_le_iff {a b : ℕ} : TT a ≤ TT b ↔ a ≤ b := by + constructor + · intro h; by_contra h'; have := TT_mono (not_le.mp h'); omega + · intro h; rcases h.lt_or_eq with h | rfl + · exact (TT_mono h).le + · exact le_rfl + +/-- The cell ring/index pair of the `n`-th cell of the spiral. -/ +private def dec : ℕ → ℤ × ℤ + | 0 => (0, 0) + | 1 => (0, 0) + | n + 2 => if (dec (n + 1)).2 = 6 * (dec (n + 1)).1 then ((dec (n + 1)).1 + 1, 1) + else ((dec (n + 1)).1, (dec (n + 1)).2 + 1) + +/-- `dec n` is valid and has index `n`. -/ +private lemma dec_spec (a : ℕ) (ha : 1 ≤ a) : + validC (dec a).1 (dec a).2 ∧ 3 * (dec a).1 * ((dec a).1 - 1) + 1 + (dec a).2 = a := by + induction a, ha using Nat.le_induction with + | base => refine ⟨Or.inl ⟨rfl, rfl⟩, by simp [dec]⟩ + | succ b hb ih => + obtain ⟨c, rfl⟩ : ∃ c, b = c + 1 := ⟨b - 1, by omega⟩ + obtain ⟨hv, he⟩ := ih + have hd : dec (c + 1 + 1) = if (dec (c + 1)).2 = 6 * (dec (c + 1)).1 then ((dec (c + 1)).1 + 1, 1) + else ((dec (c + 1)).1, (dec (c + 1)).2 + 1) := rfl + rw [hd] + unfold validC at hv ⊢ + generalize dec (c + 1) = p at hv he ⊢ + obtain ⟨x, y⟩ := p + simp only at hv he ⊢ + split_ifs with h + · refine ⟨Or.inr ⟨by omega, le_rfl, by omega⟩, ?_⟩ + push_cast at he ⊢; linear_combination he - h + · refine ⟨Or.inr ⟨by omega, by omega, by omega⟩, ?_⟩ + push_cast at he ⊢; linear_combination he + +/-- Cell indices are positive. -/ +private lemma Nidx_pos {j s : ℤ} (h : validC j s) : 1 ≤ 3 * j * (j - 1) + 1 + s := by + unfold validC at h + rcases h with ⟨rfl, rfl⟩ | ⟨h1, h2, _⟩ + · norm_num + · nlinarith [mul_nonneg (show (0 : ℤ) ≤ j by omega) (show (0 : ℤ) ≤ j - 1 by omega)] + +/-- The cell index is injective on valid pairs. -/ +private lemma Nidx_inj {j s j' s' : ℤ} (h : validC j s) (h' : validC j' s') + (e : 3 * j * (j - 1) + 1 + s = 3 * j' * (j' - 1) + 1 + s') : j = j' ∧ s = s' := by + unfold validC at h h' + have key : ∀ a b a' b' : ℤ, ((a = 0 ∧ b = 0) ∨ (1 ≤ a ∧ 1 ≤ b ∧ b ≤ 6 * a)) → + ((a' = 0 ∧ b' = 0) ∨ (1 ≤ a' ∧ 1 ≤ b' ∧ b' ≤ 6 * a')) → a < a' → + 3 * a * (a - 1) + 1 + b < 3 * a' * (a' - 1) + 1 + b' := by + intro a b a' b' ha ha' hlt + have h0 : 0 ≤ a := by omega + have := mul_nonneg (show (0 : ℤ) ≤ a' - a - 1 by omega) (show (0 : ℤ) ≤ a' + a by omega) + rcases ha with ⟨rfl, rfl⟩ | ⟨_, _, hb⟩ <;> rcases ha' with ⟨rfl, rfl⟩ | ⟨_, hb', _⟩ <;> nlinarith + rcases lt_trichotomy j j' with hl | rfl | hl + · have := key _ _ _ _ h h' hl; omega + · omega + · have := key _ _ _ _ h' h hl; omega + +/-- `dec` inverts the cell index. -/ +private lemma dec_unique (j s : ℤ) (hv : validC j s) (a : ℕ) (ha : (a : ℤ) = 3 * j * (j - 1) + 1 + s) : + dec a = (j, s) := by + have ha1 : 1 ≤ a := by have := Nidx_pos hv; omega + obtain ⟨hv', he'⟩ := dec_spec a ha1 + obtain ⟨e1, e2⟩ := Nidx_inj hv' hv (by rw [he', ha]) + exact Prod.ext e1 e2 + +/-- The ON cells after `t` toothpicks are the cells whose ON time is at most `t`. -/ +private lemma mem_onCells (t : ℕ) (c : Pt) : + c ∈ onCells (walk t) ↔ ∃ j s, validC j s ∧ cpos j s = c ∧ Tz j s ≤ t := by + unfold onCells + rw [Finset.mem_filter, List.mem_toFinset] + constructor + · rintro ⟨_, heven, hall⟩ + obtain ⟨j, s, hv, rfl⟩ := cpos_surj c heven + obtain ⟨_, u, hu, hQ⟩ := cell_complete j s hv + refine ⟨j, s, hv, rfl, ?_⟩ + rw [← hQ, ← mem_walk] + exact hall u hu + · rintro ⟨j, s, hv, rfl, hT⟩ + obtain ⟨hle, _⟩ := cell_complete j s hv + refine ⟨?_, cpos_even j s, fun u hu => ?_⟩ + · rw [mem_walk] + exact (hle _ (by simp [cellVerts])).trans hT + · rw [mem_walk] + exact (hle u hu).trans hT + +/-- The ON time of the `a`-th cell is the conjectured value at `a`. -/ +private lemma Tz_dec (a : ℕ) (ha : 1 ≤ a) : Tz (dec a).1 (dec a).2 = TT a := + (TT_eq _ _ (dec_spec a ha).1 a (dec_spec a ha).2.symm).symm + +/-- Before the conjectured time, fewer than `n` cells are ON. -/ +private lemma upper (n : ℕ) (hn : 1 ≤ n) (t : ℕ) (ht : t < TT n) : onCount t ≤ n - 1 := by + unfold onCount + have hsub : onCells (walk t) ⊆ (Finset.Icc 1 (n - 1)).image (fun a => cpos (dec a).1 (dec a).2) := by + intro c hc + rw [mem_onCells] at hc + obtain ⟨j, s, hv, rfl, hT⟩ := hc + have hpos := Nidx_pos hv + obtain ⟨a, ha⟩ : ∃ a : ℕ, (a : ℤ) = 3 * j * (j - 1) + 1 + s := + ⟨(3 * j * (j - 1) + 1 + s).toNat, by omega⟩ + have hd := dec_unique j s hv a ha + have hTa := TT_eq j s hv a ha + have ha1 : 1 ≤ a := by omega + have hlt : TT a < TT n := by omega + have han : a < n := by + by_contra h'; have := TT_le_iff.mpr (not_lt.mp h'); omega + rw [Finset.mem_image] + exact ⟨a, Finset.mem_Icc.mpr ⟨ha1, by omega⟩, by rw [hd]⟩ + calc (onCells (walk t)).card ≤ ((Finset.Icc 1 (n - 1)).image _).card := Finset.card_le_card hsub + _ ≤ (Finset.Icc 1 (n - 1)).card := Finset.card_image_le + _ = n - 1 := by simp + +/-- At the conjectured time, at least `n` cells are ON. -/ +private lemma lower (n : ℕ) (_hn : 1 ≤ n) : n ≤ onCount (TT n) := by + unfold onCount + have hsub : (Finset.Icc 1 n).image (fun a => cpos (dec a).1 (dec a).2) ⊆ onCells (walk (TT n)) := by + intro c hc + rw [Finset.mem_image] at hc + obtain ⟨a, ha, rfl⟩ := hc + rw [Finset.mem_Icc] at ha + rw [mem_onCells] + refine ⟨_, _, (dec_spec a ha.1).1, rfl, ?_⟩ + rw [Tz_dec a ha.1] + exact_mod_cast TT_le_iff.mpr ha.2 + have hinj : Set.InjOn (fun a => cpos (dec a).1 (dec a).2) (Finset.Icc 1 n : Set ℕ) := by + intro a ha b hb e + simp only [Finset.coe_Icc, Set.mem_Icc] at ha hb + obtain ⟨hva, hea⟩ := dec_spec a ha.1 + obtain ⟨hvb, heb⟩ := dec_spec b hb.1 + obtain ⟨e1, e2⟩ := cpos_inj hva hvb e + have : (a : ℤ) = b := by rw [← hea, ← heb, e1, e2] + exact_mod_cast this + calc n = (Finset.Icc 1 n).card := by simp + _ = ((Finset.Icc 1 n).image _).card := (Finset.card_image_of_injOn hinj).symm + _ ≤ _ := Finset.card_le_card hsub + +/-- Librandi's conjecture holds: for every `n > 0`, `a(n) = 2n + ⌈√(12n - 3)⌉`. -/ +theorem result : statement := by + rw [statement_iff] + intro n hn + refine ⟨lower n hn, fun t ht => ?_⟩ + by_contra h + have := upper n hn t (not_le.mp h) + have ht' : n ≤ onCount t := ht + omega + +end Math0.Frontier.A182617 + +#math0_settles Math0.Frontier.A182617.result Math0.Statements.A182617.statement diff --git a/lean/Math0/Frontier/OEIS/A188474.lean b/lean/Math0/Frontier/OEIS/A188474.lean new file mode 100644 index 0000000..f16186e --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A188474.lean @@ -0,0 +1,702 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A188474 +import Math0.Audit + +/-! +# The row sums of the generalized Deutsch triangle A188474 are A137398 + +We prove Paul Barry's conjecture: for every `n`, `∑_{k=0}^{n} T(n,k) = A137398(n+2)`. + +**A137398 as lattice walks.** Encode a subsequence `p` of `S = [0, …, 2m-1]` by its indicator +word `c ∈ {U, D}^{2m}` (`U` at the positions in `p`), a walk with steps `±1`; `|p| = m` means it +ends at height `0`. Writing `cp(y) = |p ∩ [0, y)|`, `cq(y) = |q ∩ [0, y)|` (so `cp + cq = y`) +and using `p(k) < y ↔ k < cp(y)`, the exchange of `p(i)` and `q(i)` keeps both lists increasing +iff `2i ≤ p(i), q(i) ≤ 2i+1`, iff `cp(2i) = i` and `cp(2i+2) = i+1`, i.e. iff the walk has a +*hump* `0 → ±1 → 0` at steps `2i, 2i+1`. So `A137398(m)` counts the walks of length `2m` from +`0` to `0`, starting with `U`, without humps. A transfer-matrix count over the absolute height +(`Y`) evaluates this as `g(2m-2, 2)`, where `g(L, a) = ∑_j 2^j FP(L-2j, a+2j)` and `FP(L, a)` is +the number of first-passage walks from height `a` to `0` of length `L`; both satisfy local +Pascal-type recursions, so no generating functions are needed. + +**The row sums.** Swapping the two sums in `∑_k T(n,k)` and applying Vandermonde's identity +`∑_k C(N, n+1-k) C(N, k+1) = C(2N, n+2)` (for `N = n+2-j < n+2`) gives +`∑_k T(n,k) = ∑_{j≥1} 2^{j-1} (j/N) C(2N, N-j)`. The ballot formula +`(a+2d) FP(a+2d, a) = a C(a+2d, d)` identifies `(j/N) C(2N, N-j) = FP(2N, 2j)`, which is the +`j`-th term of `g(2n+2, 2)`. +-/ + +namespace Math0.Frontier.A188474 +open Math0.Statements.A188474 + +/-- All Boolean lists of length `n`. -/ +private def allLists : ℕ → List (List Bool) + | 0 => [[]] + | n + 1 => (allLists n).map (List.cons true) ++ (allLists n).map (List.cons false) + +/-- Every list in `allLists n` has length `n`. -/ +private lemma length_of_mem_allLists : ∀ {n : ℕ} {c : List Bool}, c ∈ allLists n → c.length = n + | 0, c, h => by simp [allLists] at h; simp [h] + | n + 1, c, h => by + simp only [allLists, List.mem_append, List.mem_map] at h + rcases h with ⟨d, hd, rfl⟩ | ⟨d, hd, rfl⟩ <;> simp [length_of_mem_allLists hd] + +/-- `decode a c` is the list of positions `a + x` with `c[x] = true`. -/ +private def decode : ℕ → List Bool → List ℕ + | _, [] => [] + | a, true :: c => a :: decode (a + 1) c + | a, false :: c => decode (a + 1) c + +/-- Counting over `allLists (n+1)` splits according to the first entry. -/ +private lemma countP_allLists_succ (n : ℕ) (P : List Bool → Bool) : + (allLists (n + 1)).countP P = + (allLists n).countP (fun c => P (true :: c)) + + (allLists n).countP (fun c => P (false :: c)) := by + simp only [allLists, List.countP_append, List.countP_map] + rfl + +/-- Sublists of `[a, …, a+n-1]` of length `k` correspond to indicator words with `k` trues. -/ +private lemma countP_sublistsLen : ∀ (n k a : ℕ) (P : List ℕ → Bool), + ((List.range' a n).sublistsLen k).countP P = + (allLists n).countP (fun c => decide (c.count true = k) && P (decode a c)) + | 0, 0, a, P => by simp [allLists, decode] + | 0, k + 1, a, P => by simp [allLists] + | n + 1, 0, a, P => by + rw [countP_allLists_succ] + have := countP_sublistsLen n 0 (a + 1) P + simp only [List.sublistsLen_zero] at this ⊢ + rw [this] + simp [decode] + | n + 1, k + 1, a, P => by + rw [countP_allLists_succ, List.range'_succ, List.sublistsLen_succ_cons, List.countP_append, + List.countP_map, countP_sublistsLen n (k + 1) (a + 1) P, + countP_sublistsLen n k (a + 1) (P ∘ List.cons a), Nat.add_comm] + congr 1 + apply List.countP_congr + intro c _ + simp [decode] + +/-- The entries of `decode a c` lie in `[a, a + |c|)`. -/ +private lemma mem_decode : + ∀ {a : ℕ} {c : List Bool} {x : ℕ}, x ∈ decode a c → a ≤ x ∧ x < a + c.length + | _, [], _, h => by simp [decode] at h + | a, true :: c, x, h => by + simp only [decode, List.mem_cons] at h + rcases h with rfl | h + · simp + · have := mem_decode h; simp only [List.length_cons]; omega + | a, false :: c, x, h => by + simp only [decode] at h + have := mem_decode h; simp only [List.length_cons]; omega + +/-- `decode a c` is strictly increasing. -/ +private lemma decode_pairwise : ∀ (a : ℕ) (c : List Bool), (decode a c).Pairwise (· < ·) + | _, [] => by simp [decode] + | a, true :: c => by + simp only [decode, List.pairwise_cons] + exact ⟨fun x hx => by have := mem_decode hx; omega, decode_pairwise (a + 1) c⟩ + | a, false :: c => by simpa [decode] using decode_pairwise (a + 1) c + +/-- `decode a c` has one entry per `true` of `c`. -/ +private lemma length_decode : ∀ (a : ℕ) (c : List Bool), (decode a c).length = c.count true + | _, [] => by simp [decode] + | a, true :: c => by simp [decode, length_decode (a + 1) c] + | a, false :: c => by simp [decode, length_decode (a + 1) c] + +/-- The complementary subsequence is decoded from the negated word. -/ +private lemma filter_decode : ∀ (a : ℕ) (c : List Bool), + (List.range' a c.length).filter (fun x => decide (x ∉ decode a c)) = decode a (c.map not) + | _, [] => by simp [decode] + | a, true :: c => by + have ha : a ∉ decode (a + 1) c := fun h => by have := mem_decode h; omega + have := filter_decode (a + 1) c + simp only [List.length_cons, List.range'_succ, List.filter_cons, decode, List.map_cons, + Bool.not_true, List.mem_cons, true_or, not_true_eq_false, decide_false] + simp only [Bool.false_eq_true, ↓reduceIte] + rw [← this] + apply List.filter_congr + intro x hx + have := List.mem_range'_1.1 hx + simp only [not_or, decide_eq_decide] + constructor + · intro h; exact h.2 + · intro h; exact ⟨by omega, h⟩ + | a, false :: c => by + have ha : a ∉ decode (a + 1) c := fun h => by have := mem_decode h; omega + have := filter_decode (a + 1) c + have e : decode a (false :: c) = decode (a + 1) c := rfl + have e2 : decode a ((false :: c).map not) = a :: decode (a + 1) (c.map not) := rfl + rw [e, e2, List.length_cons, List.range'_succ, List.filter_cons, ← this] + simp [ha] + +/-- The number of entries of `decode a c` below `a + y` is the number of trues among the +first `y` letters of `c`. -/ +private lemma countP_decode : ∀ (a : ℕ) (c : List Bool) (y : ℕ), + (decode a c).countP (fun x => decide (x < a + y)) = (c.take y).count true + | _, [], _ => by simp [decode] + | a, b :: c, 0 => by + simp only [Nat.add_zero, List.take_zero, List.count_nil] + rw [List.countP_eq_zero] + intro x hx + have := mem_decode hx + simp only [decide_eq_true_eq, not_lt] + omega + | a, true :: c, y + 1 => by + have := countP_decode (a + 1) c y + simp only [decode, List.take_succ_cons, List.count_cons_self] + rw [List.countP_cons, ← this] + simp only [show a + 1 + y = a + (y + 1) by omega] + simp + | a, false :: c, y + 1 => by + have := countP_decode (a + 1) c y + simp only [decode, List.take_succ_cons, List.count_cons] + rw [show a + (y + 1) = a + 1 + y by omega, this] + simp + +/-- In a strictly increasing list, `l[k] < y` iff `k` is below the number of entries `< y`. -/ +private lemma getElem_lt_iff : ∀ (l : List ℕ), l.Pairwise (· < ·) → ∀ (k : ℕ) (hk : k < l.length) + (y : ℕ), l[k] < y ↔ k < l.countP (fun x => decide (x < y)) + | [], _, k, hk, _ => by simp at hk + | a :: l, hl, k, hk, y => by + rw [List.pairwise_cons] at hl + rw [List.countP_cons] + by_cases hay : a < y + · rcases k with _ | k + · simp [hay] + · have ih := getElem_lt_iff l hl.2 k (by simpa using hk) y + simp [hay, ih] + · have h0 : l.countP (fun x => decide (x < y)) = 0 := by + rw [List.countP_eq_zero]; intro x hx; have := hl.1 x hx; simp; omega + rcases k with _ | k + · simp [hay, h0] + · have hk' : k < l.length := by simpa using hk + have : ¬ l[k] < y := by + have := hl.1 _ (List.getElem_mem hk'); omega + simp [hay, h0, this] + +/-- Entries of a strictly increasing list compare like their indices. -/ +private lemma getElem_lt_getElem_iff (l : List ℕ) (hl : l.Pairwise (· < ·)) (a b : ℕ) + (ha : a < l.length) (hb : b < l.length) : l[a] < l[b] ↔ a < b := by + rw [List.pairwise_iff_getElem] at hl + constructor + · intro h + by_contra h' + rcases Nat.lt_or_ge b a with h'' | h'' + · have := hl b a hb ha h''; omega + · have : a = b := by omega + subst this; omega + · intro h; exact hl a b ha hb h + +/-- When does changing one entry keep a strictly increasing list strictly increasing. -/ +private lemma pairwise_set_iff (l : List ℕ) (hl : l.Pairwise (· < ·)) (i : ℕ) (hi : i < l.length) + (x : ℕ) : (l.set i x).Pairwise (· < ·) ↔ + (∀ k (hk : k < l.length), k < i → l[k] < x) ∧ + (∀ k (hk : k < l.length), i < k → x < l[k]) := by + rw [List.pairwise_iff_getElem] at hl ⊢ + simp only [List.length_set, List.getElem_set] + constructor + · intro h + refine ⟨fun k hk hki => ?_, fun k hk hik => ?_⟩ + · have := h k i hk hi hki + rwa [if_neg (by omega), if_pos rfl] at this + · have := h i k hi hk hik + rwa [if_pos rfl, if_neg (by omega)] at this + · rintro ⟨h1, h2⟩ a b ha hb hab + split_ifs with h3 h4 h4 + · omega + · subst h3; exact h2 b hb hab + · subst h4; exact h1 a ha hab + · exact hl a b ha hb hab + +/-- Negating a word swaps the counts of `true` and `false`. -/ +private lemma count_map_not (c : List Bool) : (c.map not).count true = c.count false := by + induction c with + | nil => simp + | cons b c ih => cases b <;> simp [ih] + +/-- Two bounded naturals with the same initial segments below `m` are equal. -/ +private lemma eq_of_forall_lt_iff {a b m : ℕ} (ha : a ≤ m) (hb : b ≤ m) + (h : ∀ k < m, k < a ↔ k < b) : a = b := by + rcases Nat.lt_trichotomy a b with hab | hab | hab + · have := h a (by omega); omega + · exact hab + · have := h b (by omega); omega + +/-- The exchange of `p(i)` and `q(i)` keeps both lists increasing exactly when the path has a +"hump" `0 → ±1 → 0` at positions `2i, 2i+1`. -/ +private lemma swap_iff (m : ℕ) (c : List Bool) (hc : c.length = 2 * m) (hcnt : c.count true = m) + (i : ℕ) (hi : i < m) : + ((((decode 0 c).set i + (((List.range (2 * m)).filter (· ∉ decode 0 c)).getD i 0)).Pairwise (· < ·) ∧ + (((List.range (2 * m)).filter (· ∉ decode 0 c)).set i ((decode 0 c).getD i 0)).Pairwise + (· < ·)) + ↔ ((c.take (2 * i)).count true = i ∧ (c.take (2 * i + 2)).count true = i + 1)) := by + set p := decode 0 c with hp + set q := (List.range (2 * m)).filter (· ∉ p) with hq0 + have hq : q = decode 0 (c.map not) := by + rw [hq0, List.range_eq_range', ← hc, hp]; exact filter_decode 0 c + have hpP : p.Pairwise (· < ·) := decode_pairwise 0 c + have hqP : q.Pairwise (· < ·) := hq ▸ decode_pairwise 0 _ + have hpl : p.length = m := by rw [hp, length_decode, hcnt] + have hcf : c.count false = m := by + have := List.count_true_add_count_false c; omega + have hql : q.length = m := by rw [hq, length_decode, count_map_not, hcf] + have hcp : ∀ y, p.countP (fun x => decide (x < y)) = (c.take y).count true := by + intro y; have := countP_decode 0 c y; simpa using this + have hcq : ∀ y, q.countP (fun x => decide (x < y)) = (c.take y).count false := by + intro y; have := countP_decode 0 (c.map not) y + rw [← hq] at this; simp only [Nat.zero_add] at this + rw [this, ← List.map_take, count_map_not] + have hsum : ∀ y ≤ 2 * m, (c.take y).count true + (c.take y).count false = y := by + intro y hy; rw [List.count_true_add_count_false]; simp [hc]; omega + have hcpm : ∀ y, (c.take y).count true ≤ m := by + intro y; rw [← hcp, ← hpl]; exact List.countP_le_length + have hcqm : ∀ y, (c.take y).count false ≤ m := by + intro y; rw [← hcq, ← hql]; exact List.countP_le_length + have hgp : ∀ k (hk : k < p.length) y, p[k] < y ↔ k < (c.take y).count true := by + intro k hk y; rw [← hcp]; exact getElem_lt_iff p hpP k hk y + have hgq : ∀ k (hk : k < q.length) y, q[k] < y ↔ k < (c.take y).count false := by + intro k hk y; rw [← hcq]; exact getElem_lt_iff q hqP k hk y + have hpi : i < p.length := by omega + have hqi : i < q.length := by omega + have hP2 : p[i] < 2 * m := by + have := mem_decode (List.getElem_mem hpi); omega + have hQ2 : q[i] < 2 * m := by + have hmem : q[i] ∈ decode 0 (c.map not) := by rw [← hq]; exact List.getElem_mem hqi + have := mem_decode hmem; simp at this; omega + -- the ranks of `p[i]` and `q[i]` + have rP : (c.take p[i]).count true = i := by + apply eq_of_forall_lt_iff (hcpm _) (by omega) + intro k hk + rw [← hgp k (by omega), getElem_lt_getElem_iff p hpP k i (by omega) hpi] + have rP1 : (c.take (p[i] + 1)).count true = i + 1 := by + apply eq_of_forall_lt_iff (hcpm _) (by omega) + intro k hk + rw [← hgp k (by omega), Nat.lt_succ_iff, Nat.lt_succ_iff, ← not_lt, ← not_lt, + getElem_lt_getElem_iff p hpP i k hpi (by omega)] + have rQ : (c.take q[i]).count false = i := by + apply eq_of_forall_lt_iff (hcqm _) (by omega) + intro k hk + rw [← hgq k (by omega), getElem_lt_getElem_iff q hqP k i (by omega) hqi] + have rQ1 : (c.take (q[i] + 1)).count false = i + 1 := by + apply eq_of_forall_lt_iff (hcqm _) (by omega) + intro k hk + rw [← hgq k (by omega), Nat.lt_succ_iff, Nat.lt_succ_iff, ← not_lt, ← not_lt, + getElem_lt_getElem_iff q hqP i k hqi (by omega)] + rw [pairwise_set_iff p hpP i hpi, pairwise_set_iff q hqP i hqi, List.getD_eq_getElem _ _ hqi, + List.getD_eq_getElem _ _ hpi] + have c1 : (∀ k (hk : k < p.length), k < i → p[k] < q[i]) ↔ i ≤ (c.take q[i]).count true := by + constructor + · intro h + rcases Nat.eq_zero_or_pos i with h0 | h0 + · omega + · have := (hgp (i - 1) (by omega) q[i]).1 (h (i - 1) (by omega) (by omega)); omega + · intro h k hk hki; exact (hgp k hk q[i]).2 (by omega) + have c2 : (∀ k (hk : k < p.length), i < k → q[i] < p[k]) ↔ + (c.take (q[i] + 1)).count true ≤ i + 1 := by + constructor + · intro h + by_contra hc + have h1 := h (i + 1) (by have := hcpm (q[i] + 1); omega) (by omega) + have h2 := (hgp (i + 1) (by have := hcpm (q[i] + 1); omega) (q[i] + 1)).2 (by omega) + omega + · intro h k hk hik + by_contra hc + have := (hgp k hk (q[i] + 1)).1 (by omega) + omega + have c3 : (∀ k (hk : k < q.length), k < i → q[k] < p[i]) ↔ i ≤ (c.take p[i]).count false := by + constructor + · intro h + rcases Nat.eq_zero_or_pos i with h0 | h0 + · omega + · have := (hgq (i - 1) (by omega) p[i]).1 (h (i - 1) (by omega) (by omega)); omega + · intro h k hk hki; exact (hgq k hk p[i]).2 (by omega) + have c4 : (∀ k (hk : k < q.length), i < k → p[i] < q[k]) ↔ + (c.take (p[i] + 1)).count false ≤ i + 1 := by + constructor + · intro h + by_contra hc + have h1 := h (i + 1) (by have := hcqm (p[i] + 1); omega) (by omega) + have h2 := (hgq (i + 1) (by have := hcqm (p[i] + 1); omega) (p[i] + 1)).2 (by omega) + omega + · intro h k hk hik + by_contra hc + have := (hgq k hk (p[i] + 1)).1 (by omega) + omega + rw [c1, c2, c3, c4] + have s1 := hsum q[i] (by omega) + have s2 := hsum (q[i] + 1) (by omega) + have s3 := hsum p[i] (by omega) + have s4 := hsum (p[i] + 1) (by omega) + have s5 := hsum (2 * i) (by omega) + have s6 := hsum (2 * i + 2) (by omega) + have g1 := hgp i hpi (2 * i) + have g2 := hgp i hpi (2 * i + 2) + have g3 := hgq i hqi (2 * i) + have g4 := hgq i hqi (2 * i + 2) + omega + +/-- The step of the walk: `+1` for `true`, `-1` for `false`. -/ +private def stp (b : Bool) : ℤ := if b then 1 else -1 + +/-- `ok h f c`: the walk `c`, started at height `h` (with `f` recording that the height just +before was `0`), never makes a hump `0 → ±1 → 0` and ends at height `0`. -/ +private def ok : ℤ → Bool → List Bool → Bool + | h, _, [] => decide (h = 0) + | h, f, b :: c => !(f && decide (h + stp b = 0)) && ok (h + stp b) (decide (h = 0)) c + +/-- The height of the walk `c` after `x` steps. -/ +private def H (c : List Bool) (x : ℕ) : ℤ := 2 * ((c.take x).count true : ℤ) - x + +/-- The walk starts at height `0`. -/ +private lemma H_zero (c : List Bool) : H c 0 = 0 := by simp [H] + +/-- The height after `x+1` steps of `b :: c`. -/ +private lemma H_cons_succ (b : Bool) (c : List Bool) (x : ℕ) : + H (b :: c) (x + 1) = stp b + H c x := by + cases b <;> simp [H, stp] <;> ring + +/-- One step of the automaton `ok`. -/ +private lemma ok_cons (h : ℤ) (f b : Bool) (c : List Bool) : + ok h f (b :: c) = true ↔ + ¬ (f = true ∧ h + stp b = 0) ∧ ok (h + stp b) (decide (h = 0)) c = true := by + cases f <;> simp [ok] + +/-- What the automaton `ok` checks: final height `0`, no hump right at the start when `f` +holds, and no hump `0 → ±1 → 0` anywhere. -/ +private lemma ok_iff : ∀ (c : List Bool) (h : ℤ) (f : Bool), + ok h f c = true ↔ (h + H c c.length = 0 ∧ (f = true → 1 ≤ c.length → h + H c 1 ≠ 0) ∧ + ∀ x, x + 2 ≤ c.length → ¬ (h + H c x = 0 ∧ h + H c (x + 2) = 0)) + | [], h, f => by simp [ok, H] + | b :: c, h, f => by + rw [ok_cons, ok_iff c (h + stp b) (decide (h = 0))] + simp only [List.length_cons, H_cons_succ, H_zero, decide_eq_true_eq] + constructor + · rintro ⟨hf, h1, h2, h3⟩ + refine ⟨by linarith, fun hf' _ => by intro h0; exact hf ⟨hf', by linarith⟩, ?_⟩ + intro x hx + rcases x with _ | x + · rintro ⟨h0, h0'⟩ + rw [H_zero] at h0 + exact h2 (by linarith) (by omega) (by simpa using (by linarith : h + stp b + H c 1 = 0)) + · rintro ⟨h0, h0'⟩ + rw [show x + 1 + 1 = x + 2 from rfl] at h0' + rw [H_cons_succ] at h0 + exact h3 x (by omega) ⟨by linarith, by linarith⟩ + · rintro ⟨h1, h2, h3⟩ + refine ⟨fun ⟨hf, h0⟩ => h2 hf (by omega) (by linarith), by linarith, ?_, ?_⟩ + · intro h0 hc h0' + have := h3 0 (by omega) + rw [H_zero, Nat.zero_add] at this + exact this ⟨by linarith, by linarith⟩ + · intro x hx ⟨h0, h0'⟩ + have := h3 (x + 1) (by omega) + rw [show x + 1 + 1 = x + 2 from rfl, H_cons_succ] at this + exact this ⟨by linarith, by linarith⟩ + +/-- The least element `0` is in `p` iff the walk starts with an up-step. -/ +private lemma zero_mem_decode (c : List Bool) : 0 ∈ decode 0 c ↔ c.head? = some true := by + rcases c with _ | ⟨_ | _, c⟩ + · simp [decode] + · simp only [decode, List.head?_cons, Option.some.injEq, Bool.false_eq_true, iff_false] + intro h; have := mem_decode h; omega + · simp [decode] + +/-- Humps can only start at even positions `2i`, where the height is `2 cp(2i) - 2i`. -/ +private lemma hump_iff (M : ℕ) (c : List Bool) : + (∀ x, x + 2 ≤ 2 * M → ¬ (0 + H c x = 0 ∧ 0 + H c (x + 2) = 0)) ↔ + ∀ i < M, ¬ ((c.take (2 * i)).count true = i ∧ (c.take (2 * i + 2)).count true = i + 1) := by + simp only [H, zero_add] + constructor + · intro h i hi ⟨h1, h2⟩ + apply h (2 * i) (by omega) + push_cast + constructor <;> omega + · intro h x hx ⟨h1, h2⟩ + have e : x = 2 * (c.take x).count true := by omega + apply h ((c.take x).count true) (by omega) + rw [← e] + constructor <;> omega + +/-- The definition of A137398 as a count of walks: `A137398 (m+1)` counts the walks of length +`2m+1` from height `1` (just after an up-step from `0`) to height `0` with no hump. -/ +private lemma A137398_eq (m : ℕ) : + A137398 (m + 1) = (allLists (2 * m + 1)).countP (ok 1 true) := by + unfold A137398 + rw [show (List.range (2 * (m + 1))).sublistsLen (m + 1) = + (List.range' 0 (2 * (m + 1))).sublistsLen (m + 1) by rw [List.range_eq_range'], + countP_sublistsLen] + have key : ∀ c ∈ allLists (2 * (m + 1)), + (decide (c.count true = m + 1) && (fun p : List ℕ => + let q := (List.range (2 * (m + 1))).filter (· ∉ p) + decide (0 ∈ p ∧ ∀ i < m + 1, + ¬ ((p.set i (q.getD i 0)).Pairwise (· < ·) ∧ (q.set i (p.getD i 0)).Pairwise (· < ·)))) + (decode 0 c)) = true ↔ + (decide (c.head? = some true) && ok 0 false c) = true := by + intro c hc + have hl := length_of_mem_allLists hc + simp only [Bool.and_eq_true, decide_eq_true_eq] + rw [ok_iff, hl, zero_mem_decode] + constructor + · rintro ⟨hcnt, h0, hsw⟩ + refine ⟨h0, ?_, by simp, ?_⟩ + · simp only [H, zero_add, List.take_of_length_le (by omega : c.length ≤ 2 * (m + 1)), hcnt] + push_cast; ring + · rw [hump_iff] + intro i hi + rw [← swap_iff (m + 1) c hl hcnt i hi] + exact hsw i hi + · rintro ⟨h0, h1, -, h3⟩ + have hcnt : c.count true = m + 1 := by + simp only [H, zero_add, List.take_of_length_le (by omega : c.length ≤ 2 * (m + 1))] at h1 + omega + refine ⟨hcnt, h0, ?_⟩ + rw [hump_iff] at h3 + intro i hi + rw [swap_iff (m + 1) c hl hcnt i hi] + exact h3 i hi + rw [List.countP_congr key, show 2 * (m + 1) = 2 * m + 1 + 1 by ring, countP_allLists_succ] + simp [ok, stp] + +/-- The number of hump-free walks of length `L` from absolute height `a` to `0`; the flag `f` +(relevant only at height `1`) forbids an immediate step down to `0`. -/ +private def Y : ℕ → ℕ → Bool → ℕ + | 0, a, _ => if a = 0 then 1 else 0 + | L + 1, 0, _ => 2 * Y L 1 true + | L + 1, 1, f => Y L 2 false + (if f then 0 else Y L 0 false) + | L + 1, a + 2, _ => Y L (a + 3) false + Y L (a + 1) false + +/-- One step of the transfer-matrix count. -/ +private lemma countP_ok_cons (L : ℕ) (h : ℤ) (f b : Bool) : + (allLists L).countP (fun c => ok h f (b :: c)) = + if f = true ∧ h + stp b = 0 then 0 + else (allLists L).countP (ok (h + stp b) (decide (h = 0))) := by + split_ifs with hc + · rw [List.countP_eq_zero]; intro c _; simp [ok, hc.1, hc.2] + · apply List.countP_congr; intro c _ + have : (f && decide (h + stp b = 0)) = false := by + cases f <;> simp_all + simp [ok, this] + +/-- The automaton count depends only on the absolute height, and equals `Y`. -/ +private lemma countP_ok (L : ℕ) : + ∀ (h : ℤ) (f : Bool), (allLists L).countP (ok h f) = Y L h.natAbs f := by + induction L with + | zero => + intro h f + simp only [allLists, List.countP_cons, List.countP_nil, ok, Y, Int.natAbs_eq_zero] + split_ifs <;> simp_all + | succ L ih => + intro h f + rw [countP_allLists_succ, countP_ok_cons, countP_ok_cons, ih, ih] + simp only [stp, if_true, Bool.false_eq_true, if_false] + obtain ⟨a, rfl | rfl⟩ := Int.eq_nat_or_neg h + · rcases a with _ | _ | a + · simp [Y]; ring + · cases f <;> simp [Y] + · have e1 : ((((a + 2 : ℕ) : ℤ) + 1)).natAbs = a + 3 := by omega + have e2 : ((((a + 2 : ℕ) : ℤ) + -1)).natAbs = a + 1 := by omega + have e3 : (((a + 2 : ℕ) : ℤ)).natAbs = a + 2 := by omega + rw [e1, e2, e3] + have n1 : ¬ ((a : ℤ) + 1 + 1 + 1 = 0) := by omega + have n2 : ¬ ((a : ℤ) + 1 + 1 = 0) := by omega + have n3 : ¬ ((a : ℤ) + 1 = 0) := by omega + simp [Y, n1, n2, n3] + · rcases a with _ | _ | a + · simp [Y]; ring + · cases f <;> simp [Y, add_comm] + · have e1 : ((-((a + 2 : ℕ) : ℤ) + 1)).natAbs = a + 1 := by omega + have e2 : ((-((a + 2 : ℕ) : ℤ) + -1)).natAbs = a + 3 := by omega + have e3 : (-((a + 2 : ℕ) : ℤ)).natAbs = a + 2 := by omega + rw [e1, e2, e3] + rw [if_neg (show ¬ (f = true ∧ -((a + 2 : ℕ) : ℤ) + 1 = 0) from + fun h => absurd h.2 (by omega)), + if_neg (show ¬ (f = true ∧ -((a + 2 : ℕ) : ℤ) + -1 = 0) from + fun h => absurd h.2 (by omega)), + decide_eq_false (show ¬ (-((a + 2 : ℕ) : ℤ) = 0) by omega)] + simp only [Y, add_comm] + +/-- First-passage numbers: walks of length `L` from height `a` that reach `0` only at the end. -/ +private def FP : ℕ → ℕ → ℕ + | 0, a => if a = 0 then 1 else 0 + | _ + 1, 0 => 0 + | L + 1, a + 1 => FP L (a + 2) + FP L a + +/-- `g L a = ∑_j 2^j FP (L - 2j) (a + 2j)`, defined by its recursion. -/ +private def g : ℕ → ℕ → ℕ + | 0, a => FP 0 a + | 1, a => FP 1 a + | L + 2, a => FP (L + 2) a + 2 * g L (a + 2) + +/-- The Pascal-type recursion of `g` away from height `0`. -/ +private lemma g_succ : ∀ L a, g (L + 1) (a + 1) = g L (a + 2) + g L a + | 0, a => by simp [g, FP] + | 1, a => by simp [g, FP] + | L + 2, a => by + rw [g, g_succ L (a + 2), g, g, FP] + ring + +/-- Without the flag, `Y` is given by `g`. -/ +private lemma Y_eq_g (L : ℕ) : ∀ a, Y L a false = g L a := by + induction L using Nat.strong_induction_on with + | _ L ih => + intro a + rcases L with _ | L + · simp [Y, g, FP] + · rcases a with _ | _ | a + · rcases L with _ | L + · simp [Y, g, FP] + · rw [Y, Y, ih L (by omega), g, FP] + simp + · rw [Y, ih L (by omega), ih L (by omega), g_succ] + simp + · rw [Y, ih L (by omega), ih L (by omega), g_succ] + +/-- `g` as an explicit sum. -/ +private lemma g_two_mul : ∀ (t a : ℕ), + g (2 * t) a = ∑ i ∈ Finset.range (t + 1), 2 ^ i * FP (2 * t - 2 * i) (a + 2 * i) + | 0, a => by simp [g] + | t + 1, a => by + rw [show 2 * (t + 1) = 2 * t + 2 by ring, g, g_two_mul t (a + 2), + Finset.sum_range_succ' (fun i => 2 ^ i * FP (2 * t + 2 - 2 * i) (a + 2 * i)) (t + 1), + Finset.mul_sum] + simp only [pow_zero, one_mul, Nat.mul_zero, Nat.sub_zero, Nat.add_zero] + rw [add_comm] + congr 1 + apply Finset.sum_congr rfl + intro i hi + rw [show 2 * t + 2 - 2 * (i + 1) = 2 * t - 2 * i by omega, + show a + 2 * (i + 1) = a + 2 + 2 * i by ring, pow_succ] + ring + +/-- A first passage from height `a` needs at least `a` steps. -/ +private lemma FP_eq_zero : ∀ (L a : ℕ), L < a → FP L a = 0 + | 0, a, h => by simp [FP]; omega + | L + 1, 0, h => by omega + | L + 1, a + 1, h => by rw [FP, FP_eq_zero L (a + 2) (by omega), FP_eq_zero L a (by omega)] + +/-- The only first passage of length `a` from height `a` goes straight down. -/ +private lemma FP_self : ∀ a, FP a a = 1 + | 0 => by simp [FP] + | a + 1 => by rw [FP, FP_eq_zero a (a + 2) (by omega), FP_self a] + +/-- The ballot formula `(a + 2d) · FP (a + 2d) a = a · C(a + 2d, d)`. -/ +private lemma FP_mul : ∀ (d a : ℕ), FP (a + 2 * d) a * (a + 2 * d) = a * (a + 2 * d).choose d + | 0, a => by simp [FP_self] + | d + 1, 0 => by + rw [show 0 + 2 * (d + 1) = (2 * d + 1) + 1 by ring, FP]; simp + | d + 1, a + 1 => by + have hX := FP_mul d (a + 2) + have hY := FP_mul (d + 1) a + have hv := Nat.choose_succ_right_eq (a + 2 * d + 2) d + have hp := Nat.choose_succ_succ' (a + 2 * d + 2) d + rw [show a + 1 + 2 * (d + 1) = (a + 2 * d + 2) + 1 by ring, FP, + show a + 2 * d + 2 = a + 2 + 2 * d by ring] + rw [show a + 2 * d + 2 = a + 2 + 2 * d by ring] at hv hp + rw [show a + 2 * (d + 1) = a + 2 + 2 * d by ring] at hY + rw [show a + 2 + 2 * d - d = a + d + 2 by omega] at hv + rw [hp] + apply Nat.eq_of_mul_eq_mul_left (show 0 < a + 2 + 2 * d by omega) + zify at hX hY hv ⊢ + linear_combination ((a : ℤ) + 2 + 2 * d + 1) * hX + ((a : ℤ) + 2 + 2 * d + 1) * hY - 2 * hv + +/-- Vandermonde's identity in the form needed for the row sums. -/ +private lemma vandermonde_aux (n N : ℕ) (hN : N < n + 2) : + ∑ k ∈ Finset.range (n + 1), N.choose (n - k + 1) * N.choose (k + 1) = + (2 * N).choose (n + 2) := by + rw [two_mul, Nat.add_choose_eq, + Finset.Nat.sum_antidiagonal_eq_sum_range_succ (fun u v => N.choose u * N.choose v), + Finset.sum_range_succ (fun u => N.choose u * N.choose (n + 2 - u)) (n + 2), + Finset.sum_range_succ' (fun u => N.choose u * N.choose (n + 2 - u)) (n + 1)] + simp only [Nat.choose_eq_zero_of_lt hN, zero_mul, mul_zero, add_zero, Nat.sub_zero] + apply Finset.sum_congr rfl + intro k hk + rw [Finset.mem_range] at hk + rw [mul_comm, show n + 1 + 1 - (k + 1) = n - k + 1 by omega] + +/-- The row sum after swapping the sums and applying Vandermonde's identity. -/ +private lemma rowSum_eq (n : ℕ) : ∑ k ∈ Finset.range (n + 1), T n k = + ∑ j ∈ Finset.range (n + 2), (j : ℚ) / ((n : ℚ) + 2 - j) * (2 : ℚ) ^ ((j : ℤ) - 1) * + ((2 * (n + 2 - j)).choose (n + 2) : ℚ) := by + have h1 : ∀ k ∈ Finset.range (n + 1), T n k = ∑ j ∈ Finset.range (n + 2), + (j : ℚ) / ((n : ℚ) + 2 - j) * ((n + 2 - j).choose (n - k + 1) : ℚ) * + ((n + 2 - j).choose (k + 1) : ℚ) * (2 : ℚ) ^ ((j : ℤ) - 1) := by + intro k hk + rw [Finset.mem_range] at hk + unfold T + apply Finset.sum_subset + · intro j hj; simp only [Finset.mem_range] at hj ⊢; omega + · intro j hj hj' + simp only [Finset.mem_range, not_lt] at hj hj' + rw [Nat.choose_eq_zero_of_lt (show n + 2 - j < k + 1 by omega)] + simp + rw [Finset.sum_congr rfl h1, Finset.sum_comm] + apply Finset.sum_congr rfl + intro j hj + rw [Finset.mem_range] at hj + rcases Nat.eq_zero_or_pos j with rfl | hj0 + · simp + · rw [← vandermonde_aux n (n + 2 - j) (by omega), Nat.cast_sum, Finset.mul_sum] + apply Finset.sum_congr rfl + intro k _ + push_cast + ring + +/-- `A137398 (n + 2)` as an explicit sum of first-passage numbers. -/ +private lemma A137398_sum (n : ℕ) : A137398 (n + 2) = + ∑ i ∈ Finset.range (n + 2), 2 ^ i * FP (2 * (n + 1) - 2 * i) (2 + 2 * i) := by + rw [A137398_eq (n + 1), countP_ok, ← g_two_mul, ← Y_eq_g] + simp [Y] + +/-- The `i`-th terms agree. -/ +private lemma term_eq (n i : ℕ) (hi : i < n + 2) : + ((2 ^ i * FP (2 * (n + 1) - 2 * i) (2 + 2 * i) : ℕ) : ℚ) = + ((i + 1 : ℕ) : ℚ) / ((n : ℚ) + 2 - ((i + 1 : ℕ) : ℚ)) * + (2 : ℚ) ^ (((i + 1 : ℕ) : ℤ) - 1) * ((2 * (n + 2 - (i + 1))).choose (n + 2) : ℚ) := by + have hz : (((i + 1 : ℕ) : ℤ) - 1) = (i : ℤ) := by push_cast; ring + rw [hz, zpow_natCast] + rcases Nat.lt_or_ge (n + 1 - i) (i + 1) with hlt | hge + · -- the walk cannot reach `0` + rw [FP_eq_zero _ _ (by omega), Nat.choose_eq_zero_of_lt (by omega)] + simp + · obtain ⟨d, hd⟩ : ∃ d, n + 1 - i = i + 1 + d := ⟨n + 1 - i - (i + 1), by omega⟩ + have hF := FP_mul d (2 + 2 * i) + rw [show 2 + 2 * i + 2 * d = 2 * (n + 1) - 2 * i by omega] at hF + have hc : (2 * (n + 2 - (i + 1))).choose (n + 2) = (2 * (n + 1) - 2 * i).choose d := by + rw [show 2 * (n + 2 - (i + 1)) = 2 * (n + 1) - 2 * i by omega] + exact Nat.choose_symm_of_eq_add (by omega) + rw [hc] + have hN : ((n : ℚ) + 2 - ((i + 1 : ℕ) : ℚ)) = ((n + 1 - i : ℕ) : ℚ) := by + rw [Nat.cast_sub (by omega)]; push_cast; ring + rw [hN] + have hF' : (FP (2 * (n + 1) - 2 * i) (2 + 2 * i) : ℚ) * (2 * ((n + 1 - i : ℕ) : ℚ)) = + (2 + 2 * (i : ℚ)) * ((2 * (n + 1) - 2 * i).choose d : ℚ) := by + have := congrArg (fun x : ℕ => (x : ℚ)) hF + simp only [Nat.cast_mul, Nat.cast_add, Nat.cast_ofNat] at this + rw [← this, show 2 * (n + 1) - 2 * i = 2 * (n + 1 - i) by omega] + push_cast; ring + have hpos : ((n + 1 - i : ℕ) : ℚ) ≠ 0 := by + have : 0 < n + 1 - i := by omega + positivity + field_simp + push_cast + linear_combination ((2 : ℚ) ^ i / 2) * hF' + +/-- Paul Barry's conjecture: the row sums of A188474 are `A137398(n+2)`. -/ +theorem result : statement := by + intro n + rw [rowSum_eq, A137398_sum, Nat.cast_sum, + Finset.sum_range_succ + (fun i => ((2 ^ i * FP (2 * (n + 1) - 2 * i) (2 + 2 * i) : ℕ) : ℚ)) (n + 1), + Finset.sum_range_succ' _ (n + 1)] + have hlast : FP (2 * (n + 1) - 2 * (n + 1)) (2 + 2 * (n + 1)) = 0 := FP_eq_zero _ _ (by omega) + rw [hlast] + simp only [mul_zero, add_zero, CharP.cast_eq_zero, zero_div, zero_mul] + apply Finset.sum_congr rfl + intro i hi + rw [term_eq n i (by simp only [Finset.mem_range] at hi; omega)] + +end Math0.Frontier.A188474 + +#math0_settles Math0.Frontier.A188474.result Math0.Statements.A188474.statement diff --git a/lean/Math0/Frontier/OEIS/A195249.lean b/lean/Math0/Frontier/OEIS/A195249.lean new file mode 100644 index 0000000..f5842b2 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A195249.lean @@ -0,0 +1,169 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A195249 +import Math0.Audit + +/-! +# 3 × 3 lower triangles with neighbours differing by at most two (A195249) + +We prove Hardin's empirical formula `a(n) = 1047 n - 1459` for all `n > 2`. + +Split the count by the entry `x₀` at the apex: `a n = ∑_{c ≤ n} T n c`, where `T n c` counts the +valid triangles with entries in `0..n` and apex `c` (this is the inner part of the pruned copy +`aL` of the statement file, in which every entry is searched within distance two of an already +chosen neighbour, and every window is centred at `x₀`, `x₁` or `x₂`, all within two of `c`). + +* *Upper stability* (`T_up`): if `c + 4 ≤ n` then `T (n+1) c = T n c`, since all windows are + centred at values `≤ c + 2 ≤ n - 2` and so are not clipped by the upper bound. +* *Translation* (`T_shift`): if `4 ≤ c` then `T (n+1) (c+1) = T n c`, since all windows are + centred at values `≥ c - 2 ≥ 2` and so are not clipped at `0`; shifting every entry by one is + then a bijection, and `near` is translation invariant. + +Hence for `m ≥ 0`, splitting off the apices `c < 4` (unchanged by `T_up`) and shifting the +apices `c ≥ 5` down by one (`T_shift`), `a (m + 8) = a (m + 7) + T (m + 8) 4`, and +`T (m + 8) 4 = T 8 4 = 1047` by `T_up` and a kernel computation. With `a 7 = 5870` this gives +`a n = 1047 n - 1459` for `n ≥ 7`; the values `n = 3, …, 6` are kernel computations. +-/ + +namespace Math0.Frontier.A195249 +open Math0.Statements.A195249 Finset + +/-- `T n c`: the number of valid triangles with entries in `0..n` whose apex entry is `c`, +written as the inner part of the pruned sum `aL`. -/ +private def T (n x0 : ℕ) : ℕ := + lsum (win n x0) fun x1 => + lsum (win n x0) fun x2 => if near x1 x2 then + lsum (win n x1) fun x3 => if near x2 x3 then + lsum (win n x1) fun x4 => if near x2 x4 ∧ near x3 x4 then + lsum (win n x2) fun x5 => if near x4 x5 then 1 else 0 + else 0 else 0 else 0 + +/-- `a n` split according to the apex entry. -/ +private theorem a_eq_sum (n : ℕ) : a n = ∑ c ∈ range (n + 1), T n c := by + rw [a_eq_aL, sum_range_eq_lsum] + rfl + +/-- Congruence for `lsum` with membership hypotheses. -/ +private theorem lsum_congr {l : List ℕ} {f g : ℕ → ℕ} (h : ∀ x ∈ l, f x = g x) : + lsum l f = lsum l g := by + rw [lsum_eq, lsum_eq, List.map_congr_left h] + +/-- Summing over a list shifted by one. -/ +private theorem lsum_map_succ (l : List ℕ) (f : ℕ → ℕ) : + lsum (l.map (· + 1)) f = lsum l (fun x => f (x + 1)) := by + rw [lsum_eq, lsum_eq, List.map_map] + rfl + +/-- Elements of a window lie within two of its centre and in `0..n`. -/ +private theorem mem_win {n y x : ℕ} (h : x ∈ win n y) : y - 2 ≤ x ∧ x ≤ y + 2 ∧ x ≤ n := by + unfold win at h + rw [List.mem_range'_1] at h + omega + +/-- A window centred well below the upper bound does not see the upper bound. -/ +private theorem win_succ_up {n y : ℕ} (h : y + 2 ≤ n) : win (n + 1) y = win n y := by + unfold win + congr 1 + omega + +/-- A window centred at `≥ 2` is translated along with its centre and the upper bound. -/ +private theorem win_succ_shift {n y : ℕ} (h : 2 ≤ y) : + win (n + 1) (y + 1) = (win n y).map (· + 1) := by + unfold win + rw [show (fun x : ℕ => x + 1) = (1 + ·) from funext fun x => Nat.add_comm x 1, + List.map_add_range'] + congr 1 <;> omega + +/-- `near` is translation invariant. -/ +private theorem near_succ (x y : ℕ) : near (x + 1) (y + 1) ↔ near x y := by + unfold near + omega + +/-- Raising the upper bound does not change the count for apices far below it. -/ +private theorem T_up {n c : ℕ} (h : c + 4 ≤ n) : T (n + 1) c = T n c := by + unfold T + rw [win_succ_up (by omega)] + refine lsum_congr fun x1 h1 => ?_ + have h1' := mem_win h1 + refine lsum_congr fun x2 h2 => ?_ + have h2' := mem_win h2 + rw [win_succ_up (by omega : x1 + 2 ≤ n), win_succ_up (by omega : x2 + 2 ≤ n)] + +/-- Translating the apex and the upper bound together does not change the count, as long as +the apex is far above `0`. -/ +private theorem T_shift {n c : ℕ} (h : 4 ≤ c) : T (n + 1) (c + 1) = T n c := by + unfold T + rw [win_succ_shift (by omega : 2 ≤ c), lsum_map_succ] + refine lsum_congr fun x1 h1 => ?_ + have h1' := mem_win h1 + rw [lsum_map_succ] + refine lsum_congr fun x2 h2 => ?_ + have h2' := mem_win h2 + rw [win_succ_shift (by omega : 2 ≤ x1), win_succ_shift (by omega : 2 ≤ x2)] + simp only [lsum_map_succ, near_succ] + +/-- The number of valid triangles with apex `4` and entries in `0..8` (kernel computation). -/ +private theorem T_eight : T 8 4 = 1047 := by + decide +kernel + +/-- The apex-`4` count is `1047` as soon as the upper bound is at least `8`. -/ +private theorem T_four (m : ℕ) : T (m + 8) 4 = 1047 := by + induction m with + | zero => exact T_eight + | succ m ih => rw [show m + 1 + 8 = m + 8 + 1 by omega, T_up (by omega), ih] + +/-- Splitting off the first four terms of a sum over a range. -/ +private theorem split4 (n : ℕ) (f : ℕ → ℕ) : + ∑ c ∈ range (n + 4), f c = ∑ c ∈ range 4, f c + ∑ c ∈ range n, f (c + 4) := by + rw [add_comm n 4, sum_range_add] + exact congrArg _ (sum_congr rfl fun x _ => by rw [add_comm]) + +/-- The first differences are constant from `n = 7` on. -/ +private theorem step (m : ℕ) : a (m + 8) = a (m + 7) + 1047 := by + have e1 : a (m + 8) = ∑ c ∈ range ((m + 5) + 4), T (m + 8) c := a_eq_sum (m + 8) + have e2 : a (m + 7) = ∑ c ∈ range ((m + 4) + 4), T (m + 7) c := a_eq_sum (m + 7) + have h1 : ∑ x ∈ range 4, T (m + 8) x = ∑ x ∈ range 4, T (m + 7) x := + sum_congr rfl fun x hx => by + rw [mem_range] at hx + exact T_up (by omega) + have h2 : ∑ x ∈ range (m + 4), T (m + 8) (x + 1 + 4) = + ∑ x ∈ range (m + 4), T (m + 7) (x + 4) := + sum_congr rfl fun x _ => by + rw [show x + 1 + 4 = x + 4 + 1 by omega] + exact T_shift (by omega) + rw [e1, e2, split4 (m + 5) (T (m + 8)), split4 (m + 4) (T (m + 7)), + sum_range_succ' (fun c => T (m + 8) (c + 4)) (m + 4), h1, h2, zero_add, T_four] + ring + +/-- Small values, computed in the kernel. -/ +private theorem a_vals : a 3 = 1682 ∧ a 4 = 2729 ∧ a 5 = 3776 ∧ a 6 = 4823 ∧ a 7 = 5870 := by + simp only [a_eq_aL] + decide +kernel + +/-- The formula for `n ≥ 7`. -/ +private theorem formula (m : ℕ) : (a (m + 7) : ℤ) = 1047 * ((m + 7 : ℕ) : ℤ) - 1459 := by + induction m with + | zero => rw [a_vals.2.2.2.2]; norm_num + | succ m ih => + rw [show m + 1 + 7 = m + 8 by omega, step, Nat.cast_add, ih] + push_cast + ring + +/-- Hardin's formula: `a(n) = 1047 n - 1459` for every `n > 2`. -/ +theorem result : statement := by + intro n hn + obtain h | h := le_total n 7 + · obtain ⟨h3, h4, h5, h6, h7⟩ := a_vals + interval_cases n + · rw [h3]; norm_num + · rw [h4]; norm_num + · rw [h5]; norm_num + · rw [h6]; norm_num + · rw [h7]; norm_num + · obtain ⟨m, rfl⟩ := Nat.exists_eq_add_of_le' h + exact formula m + +end Math0.Frontier.A195249 + +#math0_settles Math0.Frontier.A195249.result Math0.Statements.A195249.statement diff --git a/lean/Math0/Frontier/OEIS/A201060.lean b/lean/Math0/Frontier/OEIS/A201060.lean new file mode 100644 index 0000000..ac671b9 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A201060.lean @@ -0,0 +1,162 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A201060 +import Math0.Audit + +/-! +# Repdigits with repdigit digital product are repunits from `a(16) = 1111` on (A201060) + +We prove Krizek's conjecture: `a(n)` is a repunit for every `n ≥ 16`. + +A term `m ≥ 1111` is a repdigit `ddd…d` with `k ≥ 4` digits and digital product `d ^ k`. If +`d = 1`, `m` is a repunit. Otherwise `2 ≤ d ≤ 9` and we show that `d ^ k` is never a repdigit. +Write a nonzero repdigit as `N = e · R_j` with `1 ≤ e ≤ 9` and the repunit `R_j` (odd). + +* `d` even: `16 ∣ d ^ k`, but `16 ∣ e · R_j` with `R_j` odd forces `16 ∣ e`, impossible. +* `d` odd: `d ^ k ≥ 81`, so `N` has at least two digits and `N mod 100 = 11 e`, a multiple + of `11`. But the powers of `3`, `7`, `9` modulo `100` lie in the subgroup generated by `3` + (20 residues), and the powers of `5` modulo `100` lie in `{1, 5, 25}`; none of these residues + is divisible by `11`. + +Finally `a(n) ≥ a(16) = 1111` for `n ≥ 16` (monotonicity of `Nat.nth` and the kernel-checked +data `a_data`), and `a(n)` is a term since the set of terms is infinite. +-/ + +namespace Math0.Frontier.A201060 +open Math0.Statements.A201060 + +/-- One more digit: `rep e (j + 1) = e + 10 · rep e j`. -/ +private lemma rep_succ (e j : ℕ) : rep e (j + 1) = e + 10 * rep e j := by + simp [rep, List.replicate_succ, Nat.ofDigits_cons] + +/-- A repdigit is its digit times a repunit. -/ +private lemma rep_eq_mul (e j : ℕ) : rep e j = e * rep 1 j := by + induction j with + | zero => simp [rep] + | succ j ih => rw [rep_succ, rep_succ, ih]; ring + +/-- A nonempty repunit is odd. -/ +private lemma odd_rep_one (j : ℕ) : Odd (rep 1 (j + 1)) := by + rw [rep_succ] + exact ⟨5 * rep 1 j, by ring⟩ + +/-- A positive repdigit is `rep (e + 1) (j + 1)` with `e < 9`. -/ +private lemma repdigit_eq {N : ℕ} (h : IsRepdigit N) (hN : 0 < N) : + ∃ j e, e < 9 ∧ rep (e + 1) (j + 1) = N := by + have hmem := (isRepdigit_iff_mem_repList (L := N) (Nat.lt_pow_self (by norm_num))).1 h + rcases mem_repList.1 hmem with h0 | ⟨j, -, e, he, hrep⟩ + · omega + · exact ⟨j, e, he, hrep⟩ + +/-- A positive repdigit is not divisible by `16`. -/ +private lemma repdigit_not_dvd_sixteen {N : ℕ} (h : IsRepdigit N) (hN : 0 < N) : ¬ 16 ∣ N := by + obtain ⟨j, e, he, rfl⟩ := repdigit_eq h hN + intro hdvd + rw [rep_eq_mul] at hdvd + have hcop : Nat.Coprime 16 (rep 1 (j + 1)) := by + have h2 : Nat.Coprime 2 (rep 1 (j + 1)) := Nat.coprime_two_left.2 (odd_rep_one j) + simpa using Nat.Coprime.pow_left 4 h2 + have := Nat.le_of_dvd (by omega) (hcop.dvd_of_dvd_mul_right hdvd) + omega + +/-- A repdigit `N ≥ 10` has `N mod 100 = 11 e`, a multiple of `11`. -/ +private lemma repdigit_mod_hundred {N : ℕ} (h : IsRepdigit N) (hN : 10 ≤ N) : + N % 100 % 11 = 0 := by + obtain ⟨j, e, he, rfl⟩ := repdigit_eq h (by omega) + rcases j with _ | j + · simp [rep] at hN + omega + · rw [rep_succ, rep_succ] + have h100 : (e + 1 + 10 * (e + 1 + 10 * rep (e + 1) j)) % 100 = 11 * (e + 1) := by omega + rw [h100, Nat.mul_mod_right] + +/-- If `1 ∈ T` and `T` is closed under multiplication by `D` modulo `100`, then all powers of +`D` lie in `T` modulo `100`. -/ +private lemma pow_mod_mem (D : ℕ) (T : List ℕ) (h1 : 1 ∈ T) (hT : ∀ t ∈ T, t * D % 100 ∈ T) + (K : ℕ) : D ^ K % 100 ∈ T := by + induction K with + | zero => simpa using h1 + | succ K ih => + rw [pow_succ, Nat.mul_mod] + have := hT _ ih + rwa [Nat.mul_mod, Nat.mod_mod] at this + +/-- The powers of `3` modulo `100`. -/ +private def T3 : List ℕ := + [1, 3, 9, 27, 81, 43, 29, 87, 61, 83, 49, 47, 41, 23, 69, 7, 21, 63, 89, 67] + +/-- The powers of `5` modulo `100`. -/ +private def T5 : List ℕ := [1, 5, 25] + +/-- Odd case: if all powers of `D` modulo `100` avoid the multiples of `11`, then `D ^ K ≥ 10` +is not a repdigit. -/ +private lemma not_repdigit_odd (D K : ℕ) (T : List ℕ) (h1 : 1 ∈ T) + (hT : ∀ t ∈ T, t * D % 100 ∈ T) (h11 : ∀ t ∈ T, t % 11 ≠ 0) (hK : 10 ≤ D ^ K) : + ¬ IsRepdigit (D ^ K) := fun h => + h11 _ (pow_mod_mem D T h1 hT K) (repdigit_mod_hundred h hK) + +/-- Even case: if `2 ∣ D` and `K ≥ 4` then `D ^ K` is not a repdigit. -/ +private lemma not_repdigit_even (D K : ℕ) (hD : 2 ∣ D) (hD0 : 0 < D) (hK : 4 ≤ K) : + ¬ IsRepdigit (D ^ K) := fun h => by + apply repdigit_not_dvd_sixteen h (pow_pos hD0 K) + have h16 : (16 : ℕ) = 2 ^ 4 := by norm_num + rw [h16] + exact (Nat.pow_dvd_pow 2 hK).trans (pow_dvd_pow_of_dvd hD K) + +/-- For `2 ≤ D ≤ 9` and `K ≥ 4`, `D ^ K` is not a repdigit. -/ +private lemma not_repdigit_pow (D K : ℕ) (hD2 : 2 ≤ D) (hD9 : D ≤ 9) (hK : 4 ≤ K) : + ¬ IsRepdigit (D ^ K) := by + have h10 : 10 ≤ D ^ K := by + calc 10 ≤ 2 ^ 4 := by norm_num + _ ≤ 2 ^ K := Nat.pow_le_pow_right (by norm_num) hK + _ ≤ D ^ K := Nat.pow_le_pow_left hD2 K + interval_cases D + · exact not_repdigit_even 2 K (by norm_num) (by norm_num) hK + · exact not_repdigit_odd 3 K T3 (by decide) (by decide) (by decide) h10 + · exact not_repdigit_even 4 K (by norm_num) (by norm_num) hK + · exact not_repdigit_odd 5 K T5 (by decide) (by decide) (by decide) h10 + · exact not_repdigit_even 6 K (by norm_num) (by norm_num) hK + · exact not_repdigit_odd 7 K T3 (by decide) (by decide) (by decide) h10 + · exact not_repdigit_even 8 K (by norm_num) (by norm_num) hK + · exact not_repdigit_odd 9 K T3 (by decide) (by decide) (by decide) h10 + +/-- Every term `m ≥ 1111` is a repunit. -/ +private lemma isRepunit_of_isTerm {m : ℕ} (hm : IsTerm m) (hge : 1111 ≤ m) : IsRepunit m := by + obtain ⟨h1, h2⟩ := hm + obtain ⟨k, d, hd, rfl⟩ := repdigit_eq h1 (by omega) + have hdig := digits_rep (d := d + 1) (by omega) (by omega) (k + 1) + have hk : 3 ≤ k := by + by_contra hk + have hlt := Nat.lt_base_pow_length_digits (b := 10) (m := rep (d + 1) (k + 1)) (by norm_num) + rw [hdig, List.length_replicate] at hlt + have : 10 ^ (k + 1) ≤ 10 ^ 3 := Nat.pow_le_pow_right (by norm_num) (by omega) + omega + rcases Nat.eq_zero_or_pos d with rfl | hdpos + · intro x hx + rw [hdig] at hx + exact List.eq_of_mem_replicate hx + · exfalso + have hprod : digitProd (rep (d + 1) (k + 1)) = (d + 1) ^ (k + 1) := by + unfold digitProd + rw [if_neg (by omega), hdig, List.prod_replicate] + rw [hprod] at h2 + exact not_repdigit_pow (d + 1) (k + 1) (by omega) (by omega) (by omega) h2 + +/-- `a 16 = 1111`. -/ +private lemma a_sixteen : a 16 = 1111 := by + have := congrArg (fun l => l[15]?) a_data + simpa using this + +/-- Krizek's conjecture (A201060): `a(n)` is a repunit for every `n ≥ 16`. -/ +theorem result : statement := by + intro n hn + have hterm : IsTerm (a n) := Nat.nth_mem_of_infinite infinite_isTerm (n - 1) + have hge : 1111 ≤ a n := by + rw [← a_sixteen] + exact Nat.nth_monotone infinite_isTerm (by omega) + exact isRepunit_of_isTerm hterm hge + +end Math0.Frontier.A201060 + +#math0_settles Math0.Frontier.A201060.result Math0.Statements.A201060.statement diff --git a/lean/Math0/Frontier/OEIS/A209802.lean b/lean/Math0/Frontier/OEIS/A209802.lean new file mode 100644 index 0000000..2cca497 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A209802.lean @@ -0,0 +1,173 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A209802 +import Math0.Audit + +/-! +# Positivity of the exponential Mertens function (A209802) + +We prove Zumkeller's conjecture `a(n) > 0` for all `n ≥ 1`, where `a(n) = ∑_{k=1}^{n} μ⁽ᵉ⁾(k)` +and `μ⁽ᵉ⁾` is the exponential Möbius function (multiplicative, `μ⁽ᵉ⁾(p^e) = μ(e)`). + +The idea: on a squarefree `k` all exponents are `1`, so `μ⁽ᵉ⁾(k) = 1`, and always +`|μ⁽ᵉ⁾(k)| ≤ 1`. A non-squarefree `k ≤ n` is divisible by `p^2` for a prime `p ≤ n`, and `p` is +`2`, `3` or an odd number `2j + 5` with `j < n`. Hence, with +`S(n, k) = [4 ∣ k] + [9 ∣ k] + ∑_{j 0`, +using the telescoping bound `1/(2j+5)^2 ≤ 1/(4j+8) - 1/(4j+12)`, which gives +`∑_{j ?_ + have h1 : k.factorization p ≤ 1 := hk.natFactorization_le_one p + have h2 : k.factorization p ≠ 0 := Finsupp.mem_support_iff.mp hp + have h3 : k.factorization p = 1 := by omega + rw [h3, moebius_apply_one] + +/-- `|μ⁽ᵉ⁾(k)| ≤ 1`, as a product of values of `μ`. -/ +private theorem abs_muE_le (k : ℕ) : |muE k| ≤ 1 := by + unfold muE + rw [Finsupp.prod, Finset.abs_prod] + exact Finset.prod_le_one (fun _ _ => abs_nonneg _) (fun _ _ => abs_moebius_le_one) + +/-- The indicator `[d ∣ k]`. -/ +private def ind (d k : ℕ) : ℤ := if d ∣ k then 1 else 0 + +/-- Indicators are nonnegative. -/ +private theorem ind_nonneg (d k : ℕ) : 0 ≤ ind d k := by + unfold ind; split_ifs <;> norm_num + +/-- The number of squares dividing `k` among `4`, `9`, `(2j+5)^2` (`j < n`). -/ +private def S (n k : ℕ) : ℤ := + ind 4 k + ind 9 k + ∑ j ∈ range n, ind ((2 * j + 5) ^ 2) k + +/-- `S(n, k) ≥ 0`. -/ +private theorem S_nonneg (n k : ℕ) : 0 ≤ S n k := by + unfold S + have := ind_nonneg 4 k + have := ind_nonneg 9 k + have := Finset.sum_nonneg fun j (_ : j ∈ range n) => ind_nonneg ((2 * j + 5) ^ 2) k + linarith + +/-- Pointwise: `1 - 2 S(n,k) ≤ μ⁽ᵉ⁾(k)` for `1 ≤ k ≤ n`. -/ +private theorem pointwise {n k : ℕ} (hk1 : 1 ≤ k) (hkn : k ≤ n) : 1 - 2 * S n k ≤ muE k := by + by_cases hsq : Squarefree k + · rw [muE_of_squarefree hsq] + have := S_nonneg n k + linarith + · have hm : -1 ≤ muE k := (abs_le.mp (abs_muE_le k)).1 + suffices h : 1 ≤ S n k by linarith + rw [Nat.squarefree_iff_prime_squarefree] at hsq + push Not at hsq + obtain ⟨p, hp, hpk⟩ := hsq + have hp' : p.Prime := hp + have hple : p ≤ k := (Nat.le_of_dvd (by omega) (dvd_trans (dvd_mul_right p p) hpk)) + have h4 := ind_nonneg 4 k + have h9 := ind_nonneg 9 k + have hs := Finset.sum_nonneg fun j (_ : j ∈ range n) => ind_nonneg ((2 * j + 5) ^ 2) k + unfold S + by_cases h2 : p = 2 + · subst h2 + have : ind 4 k = 1 := by unfold ind; rw [if_pos (by simpa using hpk)] + linarith + by_cases h3 : p = 3 + · subst h3 + have : ind 9 k = 1 := by unfold ind; rw [if_pos (by simpa using hpk)] + linarith + have hodd : Odd p := hp'.odd_of_ne_two h2 + have hp2 := hp'.two_le + have h4' : p ≠ 4 := by rintro rfl; exact absurd hp' (by decide) + obtain ⟨m, hm'⟩ := hodd + set j := (p - 5) / 2 with hj + have hjp : 2 * j + 5 = p := by omega + have hjn : j ∈ range n := by rw [mem_range]; omega + have hterm : ind ((2 * j + 5) ^ 2) k = 1 := by + unfold ind; rw [if_pos (by rw [hjp, sq]; exact hpk)] + have := Finset.single_le_sum (f := fun j => ind ((2 * j + 5) ^ 2) k) + (fun j (_ : j ∈ range n) => ind_nonneg ((2 * j + 5) ^ 2) k) hjn + linarith + +/-- `∑_{k=1}^{n} [d ∣ k] = ⌊n/d⌋`. -/ +private theorem sum_ind (n d : ℕ) : ∑ k ∈ Icc 1 n, ind d k = ((n / d : ℕ) : ℤ) := by + unfold ind + rw [Finset.sum_boole, ← Nat.Ioc_filter_dvd_card_eq_div n d] + rfl + +/-- Telescoping: `∑_{j norm_num + | succ N ih => + rw [sum_range_succ] + have hN : (0 : ℚ) ≤ N := Nat.cast_nonneg N + have key : (1 : ℚ) / ((2 * N + 5) ^ 2) ≤ 1 / (4 * N + 8) - 1 / (4 * ((N + 1 : ℕ) : ℚ) + 8) := by + push_cast + rw [div_sub_div _ _ (by positivity) (by positivity), div_le_div_iff₀ (by positivity) (by positivity)] + nlinarith + push_cast at key ⊢ + linarith + +/-- `∑_{j ?_ + rw [Int.cast_natCast, mul_one_div] + have := Nat.cast_div_le (α := ℚ) (m := n) (n := (2 * j + 5) ^ 2) + push_cast at this + exact this + _ = (n : ℚ) * ∑ j ∈ range n, (1 / ((2 * (j : ℚ) + 5) ^ 2)) := by rw [mul_sum] + _ ≤ (n : ℚ) * (1 / 8) := by + have := tele n + have : (0 : ℚ) < 1 / (4 * n + 8) := by positivity + apply mul_le_mul_of_nonneg_left _ (Nat.cast_nonneg n) + linarith + _ = (n : ℚ) / 8 := by ring + +/-- Zumkeller's conjecture (A209802): the partial sums `a(n) = ∑_{k=1}^{n} μ⁽ᵉ⁾(k)` of the +exponential Möbius function are positive for every `n ≥ 1`; the argument gives `a(n) ≥ n/36`. -/ +theorem result : statement := by + intro n hn + have hlow : ∑ k ∈ Icc 1 n, (1 - 2 * S n k) ≤ a n := by + unfold a + refine sum_le_sum fun k hk => ?_ + rw [mem_Icc] at hk + exact pointwise hk.1 hk.2 + have hsum : ∑ k ∈ Icc 1 n, (1 - 2 * S n k) = (n : ℤ) - 2 * (((n / 4 : ℕ) : ℤ) + ((n / 9 : ℕ) : ℤ) + + ∑ j ∈ range n, ((n / (2 * j + 5) ^ 2 : ℕ) : ℤ)) := by + rw [sum_sub_distrib, ← mul_sum] + unfold S + rw [sum_add_distrib, sum_add_distrib, sum_comm, sum_ind, sum_ind] + simp only [sum_ind, sum_const, Nat.card_Icc, nsmul_eq_mul, mul_one] + push_cast + ring + have hbound : 2 * (((n / 4 : ℕ) : ℤ) + ((n / 9 : ℕ) : ℤ) + + ∑ j ∈ range n, ((n / (2 * j + 5) ^ 2 : ℕ) : ℤ)) < (n : ℤ) := by + have h4 : (((n / 4 : ℕ) : ℤ) : ℚ) ≤ (n : ℚ) / 4 := by + rw [Int.cast_natCast]; exact_mod_cast Nat.cast_div_le + have h9 : (((n / 9 : ℕ) : ℤ) : ℚ) ≤ (n : ℚ) / 9 := by + rw [Int.cast_natCast]; exact_mod_cast Nat.cast_div_le + have ht := tail_le n + have hn' : (1 : ℚ) ≤ n := by exact_mod_cast hn + have : ((2 * (((n / 4 : ℕ) : ℤ) + ((n / 9 : ℕ) : ℤ) + + ∑ j ∈ range n, ((n / (2 * j + 5) ^ 2 : ℕ) : ℤ)) : ℤ) : ℚ) < ((n : ℤ) : ℚ) := by + rw [Int.cast_mul, Int.cast_add, Int.cast_add, Int.cast_sum, Int.cast_natCast (n := n)] + push_cast at h4 h9 ht ⊢ + linarith + exact_mod_cast this + linarith + +end Math0.Frontier.A209802 + +#math0_settles Math0.Frontier.A209802.result Math0.Statements.A209802.statement diff --git a/lean/Math0/Frontier/OEIS/A211343.lean b/lean/Math0/Frontier/OEIS/A211343.lean new file mode 100644 index 0000000..ceefdf4 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A211343.lean @@ -0,0 +1,132 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A211343 +import Math0.Audit + +/-! +# A211343: positive entries are smallest parts of consecutive-part partitions + +Both conjectures of Omar E. Pol on A211343 hold. Writing `S k = 0 + 1 + ⋯ + (k-1)`, column `k` +starts in row `k(k+1)/2 = S k + k` and has period `k`, so for `k ≥ 1` the entry `T(n,k)` is +positive exactly when `n = k * m + S k` for some `m ≥ 1`, and then `T(n,k) = m`. Since +`m + (m+1) + ⋯ + (m+k-1) = k * m + S k`, this says that `T(n,k) > 0` iff `n` is a sum of `k` +consecutive positive integers, the smallest of which is `T(n,k)`. Conjecture 1 follows (the +consecutive partition with `k` parts is determined by its sum), and Conjecture 2 follows from +`A109814_isGreatest`, since the set of columns of row `n` with positive entries is exactly +`{k | IsConsecSum n k}`. +-/ + +namespace Math0.Frontier.A211343 +open Math0.Statements.A211343 +open Finset + +/-- `k(k+1)/2 = (0 + 1 + ⋯ + (k-1)) + k`. -/ +private lemma tri_eq (k : ℕ) : k * (k + 1) / 2 = (∑ i ∈ range k, i) + k := by + have h := Finset.sum_range_id (k + 1) + rw [Finset.sum_range_succ] at h + rw [h, Nat.add_sub_cancel, Nat.mul_comm] + +/-- `m + (m+1) + ⋯ + (m+k-1) = k * m + (0 + 1 + ⋯ + (k-1))`. -/ +private lemma consec_sum (m k : ℕ) : + ∑ i ∈ range k, (m + i) = k * m + ∑ i ∈ range k, i := by + rw [Finset.sum_add_distrib, Finset.sum_const, Finset.card_range, smul_eq_mul] + +/-- The multiset sum of `m, m+1, …, m+k-1` is `k * m + (0 + 1 + ⋯ + (k-1))`. -/ +private lemma multiset_consec_sum (m k : ℕ) : + ((Multiset.range k).map (fun i => m + i)).sum = k * m + ∑ i ∈ range k, i := by + rw [← consec_sum] + rfl + +/-- A positive entry `T(n,k)` satisfies `n = k * T(n,k) + (0 + 1 + ⋯ + (k-1))`. -/ +private lemma eq_of_T_pos {n k : ℕ} (h : InRow n k) (hT : 0 < T n k) : + n = k * T n k + ∑ i ∈ range k, i := by + have hk := h.1 + have hle := h.2 + unfold T at hT ⊢ + rw [if_pos h] at hT ⊢ + unfold column at hT ⊢ + split_ifs at hT ⊢ with hd + · rw [tri_eq] at hle hd ⊢ + have hdiv : k ∣ n - ((∑ i ∈ range k, i) + k) := Nat.dvd_of_mod_eq_zero hd + have := Nat.mul_div_cancel' hdiv + rw [Nat.mul_add, this] + omega + · omega + +/-- Conversely, if `n = k * m + (0 + 1 + ⋯ + (k-1))` with `k, m ≥ 1`, then `(n, k)` is in the +triangle and `T(n,k) = m`. -/ +private lemma T_of_eq {n k m : ℕ} (hk : 1 ≤ k) (hm : 1 ≤ m) + (hn : n = k * m + ∑ i ∈ range k, i) : InRow n k ∧ T n k = m := by + have hrow : InRow n k := by + refine ⟨hk, ?_⟩ + rw [tri_eq, hn] + have : k ≤ k * m := Nat.le_mul_of_pos_right k hm + omega + refine ⟨hrow, ?_⟩ + unfold T + rw [if_pos hrow] + unfold column + have hj : n - k * (k + 1) / 2 = k * (m - 1) := by + rw [tri_eq, hn, Nat.mul_sub, Nat.mul_one] + have : k ≤ k * m := Nat.le_mul_of_pos_right k hm + omega + rw [hj, Nat.mul_mod_right, if_pos rfl, Nat.mul_div_cancel_left _ (by omega)] + omega + +/-- For `n ≥ 1`, the columns of row `n` with a positive entry are exactly the `k` such that `n` +is a sum of `k` consecutive positive integers. -/ +private lemma inRow_T_pos_iff {n k : ℕ} (hn : 1 ≤ n) : + (InRow n k ∧ 0 < T n k) ↔ IsConsecSum n k := by + constructor + · rintro ⟨h, hT⟩ + exact ⟨T n k, hT, by rw [consec_sum]; exact (eq_of_T_pos h hT).symm⟩ + · rintro ⟨m, hm, hs⟩ + rw [consec_sum] at hs + have hk : 1 ≤ k := by + rcases Nat.eq_zero_or_pos k with rfl | h + · simp at hs; omega + · exact h + obtain ⟨hrow, hT⟩ := T_of_eq hk hm hs.symm + exact ⟨hrow, by omega⟩ + +/-- Both conjectures hold: positive entries `T(n,k)` are the smallest parts of the (unique) +partition of `n` into `k` consecutive parts, and the last positive entry of row `n` is in +column `A109814(n)`. -/ +theorem result : statement := by + refine ⟨?_, ?_⟩ + · intro n k _ h hT + have hk : 1 ≤ k := h.1 + have hn := eq_of_T_pos h hT + refine ⟨?_, ?_⟩ + · refine ⟨⟨(Multiset.range k).map (fun i => T n k + i), ?_, ?_⟩, T n k, rfl⟩ + · intro i hi + obtain ⟨j, _, rfl⟩ := Multiset.mem_map.1 hi + omega + · rw [multiset_consec_sum] + exact hn.symm + · rintro p ⟨m', hp⟩ + have hsum := p.parts_sum + rw [hp, multiset_consec_sum] at hsum + have hmm : k * m' = k * T n k := by omega + have hm' : m' = T n k := Nat.eq_of_mul_eq_mul_left (by omega) hmm + subst hm' + refine ⟨?_, ?_⟩ + · show T n k ∈ p.parts + rw [hp] + exact Multiset.mem_map.2 ⟨0, Multiset.mem_range.2 (by omega), by simp⟩ + · intro x hx + have hx' : x ∈ p.parts := hx + rw [hp] at hx' + obtain ⟨j, _, rfl⟩ := Multiset.mem_map.1 hx' + omega + · intro n hn + have hset : {k | InRow n k ∧ 0 < T n k} = {k | IsConsecSum n k} := by + ext k + exact inRow_T_pos_iff hn + rw [hset] + exact A109814_isGreatest hn + +end Math0.Frontier.A211343 + +#math0_settles Math0.Frontier.A211343.result Math0.Statements.A211343.statement diff --git a/lean/Math0/Frontier/OEIS/A215010.lean b/lean/Math0/Frontier/OEIS/A215010.lean new file mode 100644 index 0000000..9cf21f2 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A215010.lean @@ -0,0 +1,82 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A215010 +import Math0.Audit + +/-! +# An equiangular decagon with sides in arithmetic progression (A215010) + +We refute Garcia's conjecture that hexagons are the only equiangular simple convex polygons whose +integer side lengths are the terms of an arithmetic progression in some order. + +Counterexample: `N = 10`, `t = d = 1`, with consecutive sides `(1, 4, 5, 8, 9, 2, 3, 6, 7, 10)`, +i.e. `σ = (0, 3, 4, 7, 8, 1, 2, 5, 6, 9)`. Let `ζ = exp (2πi/10)`, a primitive `10`th root of +unity, so `edgeDir 10 k = ζ ^ k`. Then `ζ ^ 5 = -1` and `ζ ≠ -1`, so from +`ζ ^ 5 + 1 = (ζ + 1) (ζ ^ 4 - ζ ^ 3 + ζ ^ 2 - ζ + 1)` we get `Φ₁₀(ζ) = ζ⁴ - ζ³ + ζ² - ζ + 1 = 0`. +Using `ζ ^ (k + 5) = -ζ ^ k`, the closing sum is +`∑_{k<5} (s k - s (k+5)) ζ ^ k = -1 + ζ - ζ² + ζ³ - ζ⁴ = -Φ₁₀(ζ) = 0`. +-/ + +namespace Math0.Frontier.A215010 +open Math0.Statements.A215010 + +/-- The ordering `σ = (0, 3, 4, 7, 8, 1, 2, 5, 6, 9)` of `Fin 10`, with its explicit inverse. -/ +private def σ10 : Equiv.Perm (Fin 10) where + toFun := ![0, 3, 4, 7, 8, 1, 2, 5, 6, 9] + invFun := ![0, 5, 6, 1, 2, 7, 8, 3, 4, 9] + left_inv := by decide + right_inv := by decide + +/-- `ζ = exp (2πi/10)` satisfies `Φ₁₀(ζ) = ζ⁴ - ζ³ + ζ² - ζ + 1 = 0` and `ζ ^ 5 = -1`. -/ +private theorem zeta_props : + edgeDir 10 1 ^ 4 - edgeDir 10 1 ^ 3 + edgeDir 10 1 ^ 2 - edgeDir 10 1 + 1 = 0 ∧ + edgeDir 10 1 ^ 5 = -1 := by + have hz : IsPrimitiveRoot (edgeDir 10 1) 10 := by + have := Complex.isPrimitiveRoot_exp 10 (by norm_num) + unfold edgeDir + convert this using 2 + push_cast; ring + set ζ := edgeDir 10 1 + have h5 : ζ ^ 5 = -1 := by + have h2 : IsPrimitiveRoot (ζ ^ 5) (10 / 5) := hz.pow_of_dvd (by norm_num) (by norm_num) + exact IsPrimitiveRoot.eq_neg_one_of_two_right h2 + have hne : ζ + 1 ≠ 0 := by + intro h + have : ζ = -1 := by linear_combination h + have h2 : ζ ^ 2 ≠ 1 := hz.pow_ne_one_of_pos_of_lt (by norm_num) (by norm_num) + exact h2 (by rw [this]; norm_num) + refine ⟨?_, h5⟩ + have hprod : (ζ + 1) * (ζ ^ 4 - ζ ^ 3 + ζ ^ 2 - ζ + 1) = 0 := by + linear_combination h5 + exact (mul_eq_zero.mp hprod).resolve_left hne + +/-- `edgeDir 10 k = ζ ^ k` with `ζ = edgeDir 10 1`. -/ +private theorem edgeDir_ten (k : ℕ) : edgeDir 10 k = edgeDir 10 1 ^ k := by + unfold edgeDir + rw [← Complex.exp_nat_mul]; congr 1; push_cast; ring + +/-- The decagon with sides `(1, 4, 5, 8, 9, 2, 3, 6, 7, 10)` is equiangular. -/ +private theorem decagon : IsEquiangularPolygon 10 (fun k => 1 + (σ10 k : ℕ) * 1) := by + refine ⟨by norm_num, fun _ => by positivity, ?_⟩ + obtain ⟨hΦ, h5⟩ := zeta_props + rw [Finset.sum_congr rfl fun k _ => by rw [edgeDir_ten]] + set ζ := edgeDir 10 1 + simp [Fin.sum_univ_succ, σ10] + have h6 : ζ ^ 6 = -ζ := by linear_combination ζ * h5 + have h7 : ζ ^ 7 = -ζ ^ 2 := by linear_combination ζ ^ 2 * h5 + have h8 : ζ ^ 8 = -ζ ^ 3 := by linear_combination ζ ^ 3 * h5 + have h9 : ζ ^ 9 = -ζ ^ 4 := by linear_combination ζ ^ 4 * h5 + norm_num + linear_combination (-1 : ℂ) * hΦ + 2 * h5 + 3 * h6 + 6 * h7 + 7 * h8 + 10 * h9 + +/-- Garcia's conjecture fails: the equiangular decagon with sides `1, …, 10` in the order +`(1, 4, 5, 8, 9, 2, 3, 6, 7, 10)` has `N = 10 ≠ 6`. -/ +theorem result : ¬ statement := by + intro h + have := h 10 1 1 le_rfl σ10 decagon + norm_num at this + +end Math0.Frontier.A215010 + +#math0_settles Math0.Frontier.A215010.result Math0.Statements.A215010.statement diff --git a/lean/Math0/Frontier/OEIS/A223395.lean b/lean/Math0/Frontier/OEIS/A223395.lean new file mode 100644 index 0000000..de688e9 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A223395.lean @@ -0,0 +1,141 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A223395 +import Math0.Audit + +/-! +# A223395: walks on the 4 × 4 grid graph satisfy a third-order recurrence + +We prove all three conjectures recorded in the entry: Hardin's recurrence +`a(n) = 3a(n-1) + 2a(n-2) - 4a(n-3)` (`n ≥ 4`), Barker's generating function and Barker's +closed form. + +Let `c n` be the vector `v ↦ cnt n v` (walks with `n + 1` vertices starting at `v`), so +`c (n+1) = A c n` for the adjacency matrix `A` of the grid graph, `c 0 = 1`, and +`a (n+1) = ∑ v, c n v`. The key fact is the vector identity `A³1 + 4·1 = 3A²1 + 2A1`, i.e. +`c 3 + 4 c 0 = 3 c 2 + 2 c 1`, which is checked in the kernel on the list computation `colsL`. +Applying `A` (linearity of `cnt_succ`) propagates it to `c (n+3) + 4 c n = 3 c (n+2) + 2 c (n+1)` +for all `n`, and summing over the top vertex gives `a(m+4) + 4a(m+1) = 3a(m+3) + 2a(m+2)`. +The generating function follows by comparing coefficients of +`(1 - 3X - 2X² + 4X³) ∑_{n≥1} a(n) Xⁿ`, and the closed form by induction, since `1`, `1 ± √5` +are the roots of `x³ - 3x² - 2x + 4 = (x - 1)(x² - 2x - 4)` and the formula matches +`a(1), a(2), a(3) = 16, 48, 152`. +-/ + +namespace Math0.Frontier.A223395 +open Math0.Statements.A223395 + +/-- `cnt n v` read off the fast list computation. -/ +private theorem cnt_eq_colsL (n : ℕ) (v : Fin 16) : cnt n v = (colsL n).getD v.val 0 := by + rw [colsL_eq, getD_map_finRange] + +/-- Base case of the vector recurrence (kernel-checked). -/ +private theorem cnt_base : ∀ v : Fin 16, cnt 3 v + 4 * cnt 0 v = 3 * cnt 2 v + 2 * cnt 1 v := by + simp only [cnt_eq_colsL] + decide +kernel + +/-- The vector recurrence `A^3 c = 3 A^2 c + 2 A c - 4 c`, propagated by linearity. -/ +private theorem cnt_rec (n : ℕ) : + ∀ v : Fin 16, cnt (n + 3) v + 4 * cnt n v = 3 * cnt (n + 2) v + 2 * cnt (n + 1) v := by + induction n with + | zero => exact cnt_base + | succ n ih => + intro v + rw [cnt_succ (n + 3) v, cnt_succ n v, cnt_succ (n + 2) v, cnt_succ (n + 1) v, + Finset.mul_sum, Finset.mul_sum, Finset.mul_sum, ← Finset.sum_add_distrib, + ← Finset.sum_add_distrib] + refine Finset.sum_congr rfl fun u _ => ?_ + by_cases h : Adj v u + · simp only [if_pos h] + exact ih u + · simp [h] + +/-- Hardin's recurrence in `ℕ`, without subtraction. -/ +private theorem a_rec (m : ℕ) : a (m + 4) + 4 * a (m + 1) = 3 * a (m + 3) + 2 * a (m + 2) := by + rw [a_succ (m + 3), a_succ m, a_succ (m + 2), a_succ (m + 1), Finset.mul_sum, Finset.mul_sum, + Finset.mul_sum, ← Finset.sum_add_distrib, ← Finset.sum_add_distrib] + exact Finset.sum_congr rfl fun v _ => cnt_rec m v + +/-- Hardin's recurrence. -/ +private theorem rec_part : statementRec := by + intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 4 := ⟨n - 4, by omega⟩ + have h := congrArg (Nat.cast : ℕ → ℤ) (a_rec m) + push_cast at h + rw [show m + 4 - 1 = m + 3 by omega, show m + 4 - 2 = m + 2 by omega, + show m + 4 - 3 = m + 1 by omega] + linarith + +/-- The first three terms. -/ +private theorem a_small : a 1 = 16 ∧ a 2 = 48 ∧ a 3 = 152 := by + simp only [a_eq_aL] + decide +kernel + +/-- Barker's generating function, by comparing coefficients. -/ +private theorem gf_part : statementGF := by + unfold statementGF + have hL : ∀ F : PowerSeries ℤ, + (1 - PowerSeries.X) * (1 - 2 * PowerSeries.X - 4 * PowerSeries.X ^ 2) * F = + F - PowerSeries.C (3 : ℤ) * (PowerSeries.X ^ 1 * F) + - PowerSeries.C (2 : ℤ) * (PowerSeries.X ^ 2 * F) + + PowerSeries.C (4 : ℤ) * (PowerSeries.X ^ 3 * F) := by + intro F + simp only [map_ofNat] + ring + have hR : (8 : PowerSeries ℤ) * PowerSeries.X * (2 - 3 * PowerSeries.X ^ 2) = + PowerSeries.C (16 : ℤ) * PowerSeries.X ^ 1 - PowerSeries.C (24 : ℤ) * PowerSeries.X ^ 3 := by + simp only [map_ofNat] + ring + rw [hL, hR] + ext k + simp only [map_add, map_sub, PowerSeries.coeff_C_mul, PowerSeries.coeff_X_pow_mul', + PowerSeries.coeff_X_pow, PowerSeries.coeff_mk] + rcases k with _ | _ | _ | _ | k + · simp + · simp [a_small.1] + · simp [a_small.1, a_small.2.1] + · simp [a_small.1, a_small.2.1, a_small.2.2] + · have h := congrArg (Nat.cast : ℕ → ℤ) (a_rec k) + push_cast at h + simp + linarith + +/-- Barker's closed form, by induction using the recurrence. -/ +private theorem cf_part : statementClosedForm := by + intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩ + set s := Real.sqrt 5 + have hs : s ^ 2 = 5 := Real.sq_sqrt (by norm_num) + have key : ∀ m : ℕ, + (a (m + 1) : ℝ) = (8 + (11 - 5 * s) * (1 - s) ^ (m + 1) + (1 + s) ^ (m + 1) * (11 + 5 * s)) / 5 ∧ + (a (m + 2) : ℝ) = (8 + (11 - 5 * s) * (1 - s) ^ (m + 2) + (1 + s) ^ (m + 2) * (11 + 5 * s)) / 5 ∧ + (a (m + 3) : ℝ) = (8 + (11 - 5 * s) * (1 - s) ^ (m + 3) + (1 + s) ^ (m + 3) * (11 + 5 * s)) / 5 := by + intro m + induction m with + | zero => + obtain ⟨h1, h2, h3⟩ := a_small + simp only [h1, h2, h3] + push_cast + refine ⟨?_, ?_, ?_⟩ + · linear_combination (-2 : ℝ) * hs + · linear_combination (-42 / 5 : ℝ) * hs + · linear_combination (-(2 * s ^ 2 + 146 / 5) : ℝ) * hs + | succ m ih => + obtain ⟨h1, h2, h3⟩ := ih + refine ⟨h2, h3, ?_⟩ + have h := congrArg (Nat.cast : ℕ → ℝ) (a_rec m) + push_cast at h + have e : (a (m + 1 + 3) : ℝ) = a (m + 4) := by rfl + rw [e] + linear_combination h - 4 * h1 + 3 * h3 + 2 * h2 + + (((11 - 5 * s) * (1 - s) ^ (m + 1) * s - (11 + 5 * s) * (1 + s) ^ (m + 1) * s) / 5) * hs + exact (key m).1 + +/-- All three conjectures of A223395 hold: Hardin's recurrence, Barker's generating function and +Barker's closed form. -/ +theorem result : statement := ⟨rec_part, gf_part, cf_part⟩ + +end Math0.Frontier.A223395 + +#math0_settles Math0.Frontier.A223395.result Math0.Statements.A223395.statement diff --git a/lean/Math0/Frontier/OEIS/A229159.lean b/lean/Math0/Frontier/OEIS/A229159.lean new file mode 100644 index 0000000..dcf2d4f --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A229159.lean @@ -0,0 +1,43 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A229159 +import Math0.Audit + +/-! +# Every odd prime is a side of a Heronian triangle (A229159) + +We prove Lagneau's conjecture: for every prime `p > 2` there is a non-degenerate integer-sided +triangle with integer area having a side of length `p`. + +The idea: every odd `p = 2m + 1` is a leg of the Pythagorean triple +`(p, (p² - 1)/2, (p² + 1)/2) = (2m + 1, 2m² + 2m, 2m² + 2m + 1)`. This right triangle has area +`p (p² - 1)/4 = m (m + 1) (2m + 1)`, an integer. The triangle inequalities hold since the two +long sides differ by `1 < p`, and Heron's formula is a polynomial identity in `m`. Primality is +not needed: the argument works for every odd `p ≥ 3`. +-/ + +namespace Math0.Frontier.A229159 +open Math0.Statements.A229159 + +/-- For every `m ≥ 1`, the right triangle `(2m + 1, 2m² + 2m, 2m² + 2m + 1)` is non-degenerate +and has integer area `m (m + 1) (2m + 1)`. -/ +private theorem isIntTriangle_odd (m : ℕ) (hm : 1 ≤ m) : + IsIntTriangle (2 * m + 1) (2 * m ^ 2 + 2 * m) (2 * m ^ 2 + 2 * m + 1) + (m * (m + 1) * (2 * m + 1)) := by + refine ⟨?_, by omega, ?_, ?_⟩ + · nlinarith + · omega + · push_cast + ring + +/-- Lagneau's conjecture (A229159) holds: every prime `p > 2` is a side of an integer-sided +triangle with integer area. -/ +theorem result : statement := by + intro p hp h2 + obtain ⟨m, rfl⟩ : Odd p := hp.odd_of_ne_two (by omega) + exact ⟨_, _, _, _, isIntTriangle_odd m (by omega), Or.inl rfl⟩ + +end Math0.Frontier.A229159 + +#math0_settles Math0.Frontier.A229159.result Math0.Statements.A229159.statement diff --git a/lean/Math0/Frontier/OEIS/A242396.lean b/lean/Math0/Frontier/OEIS/A242396.lean new file mode 100644 index 0000000..5a4015a --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A242396.lean @@ -0,0 +1,47 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A242396 +import Math0.Audit + +/-! +# Stephan's conjectured g.f. for A242396 is false + +We refute Ralf Stephan's conjectured rational generating function for A242396 (rows of the +unit triangular tiling meeting a circle of radius `n`). + +Clearing the denominator `1 - X - X¹³ + X¹⁴`, the conjecture says that the coefficient of `X⁹⁷` +in `(∑_{n ≥ 1} a(n) Xⁿ) · (X¹⁴ - X¹³ - X + 1)`, namely `a(97) - a(96) - a(84) + a(83)`, equals +the coefficient of `X⁹⁷` in the degree-14 numerator, which is `0`. But the kernel computes +`a 97 = 226`, `a 96 = 222`, `a 84 = 194`, `a 83 = 192`, so that coefficient is `2`. + +Geometrically, `a(n) = 2⌊2n/√3⌋ + 2`, a Beatty-type sequence with irrational slope, which cannot +satisfy the period-13 recurrence `a(n) = a(n-1) + a(n-13) - a(n-14)`; the first failure is at +`n = 97`, where `⌊194/√3⌋ = 112` (`3·112² = 37632 ≤ 37636 = 4·97² < 3·113²`). +-/ + +namespace Math0.Frontier.A242396 +open Math0.Statements.A242396 PowerSeries + +/-- The four values of `a` entering the coefficient of `X⁹⁷`, computed by the kernel. -/ +private lemma vals : a 97 = 226 ∧ a 96 = 222 ∧ a 84 = 194 ∧ a 83 = 192 := by + decide +kernel + +/-- Stephan's conjectured g.f. for A242396 fails: comparing coefficients of `X⁹⁷` gives +`a(83) - a(84) - a(96) + a(97) = 192 - 194 - 222 + 226 = 2 ≠ 0`. -/ +theorem result : ¬ statement := by + intro h + have e2 : (2 : ℤ⟦X⟧) = C 2 := (map_ofNat C 2).symm + have e4 : (4 : ℤ⟦X⟧) = C 4 := (map_ofNat C 4).symm + rw [statement, e2, e4] at h + have h97 := congrArg (coeff 97) h + simp only [mul_sub, mul_add, mul_one, neg_mul, map_add, map_sub, map_neg, coeff_C_mul, + coeff_X_pow, coeff_X] at h97 + simp [mul_comm _ (X ^ _), coeff_X_pow_mul'] at h97 + obtain ⟨h1, h2, h3, h4⟩ := vals + rw [h1, h2, h3, h4] at h97 + norm_num at h97 + +end Math0.Frontier.A242396 + +#math0_settles Math0.Frontier.A242396.result Math0.Statements.A242396.statement diff --git a/lean/Math0/Frontier/OEIS/A249434.lean b/lean/Math0/Frontier/OEIS/A249434.lean new file mode 100644 index 0000000..7ce92a4 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A249434.lean @@ -0,0 +1,449 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A249434 +import Math0.Audit + +/-! +# `A249151(k) = k` exactly when `k + 1` is prime + +We prove Karttunen's conjecture (A249434 / A249151): for every `k`, `k` is the largest `m` with +`m ! ∣ rowProd k` (the product of row `k` of Pascal's triangle) iff `k + 1` is prime. + +**Reduction.** The set `{m | m ! ∣ P}` is downward closed, so the claim is +`k ! ∣ P(k) ∧ ¬ (k+1)! ∣ P(k) ↔ (k+1).Prime`. Fix a prime `q`, put `n = k + 1`, +`g(m) = v_q(P(m))`, `L(m) = v_q(m!)`. From `P(n) n! = P(n-1) n^n` we get +`g(k) - L(k) = D := g(n) - (n-1) v_q(n)`, so `k ! ∣ P(k)` iff `D_q ≥ 0` for all `q`, and +`(k+1)! ∣ P(k)` iff `D_q ≥ v_q(n)` for all `q`. + +**Recursions.** By induction from the recurrence, `g(q m + r) = q g(m) + (q-1-r)(m + L(m))` for +`r < q`, and Legendre gives `L(q m + r) = m + L(m)`. Iterating, for `n = q^e u` with `q ∤ u` and +`S = u - (q-1) L(u)` (the base-`q` digit sum of `u`, `S ≥ 1`): +`(q-1) D = q^e ((q-1) g(u) - S) + S + (q-1) e`. + +**Key inequality.** If `g(u) ≥ 1` then `(q-1)(g(u) + L(u)) ≥ u`, i.e. `(q-1) g(u) ≥ S` +(strong induction on `u` via the recursion). Hence `D > e` when `g(u) ≥ 1`. When `g(u) = 0`, +`(q-1) D = (q-1) e - (q^e - 1) S < 0` unless `e = 1` and `S = 1`, i.e. `n = q`. + +**Conclusion.** If `n` is prime, `D_q ≥ 0` for all `q` and `D_n = 0 < 1 = v_n(n)`. If `n` is not +prime, every `q ∣ n` has `q ≠ n`, so `D_q < 0` or `D_q ≥ v_q(n)`; thus `k ! ∣ P(k)` forces +`(k+1)! ∣ P(k)`. +-/ + +namespace Math0.Frontier.A249434 +open Math0.Statements.A249434 +open Nat + +/-- The `q`-adic valuation of the row product `rowProd n`. -/ +private def g (q n : ℕ) : ℕ := padicValNat q (rowProd n) + +/-- The `q`-adic valuation of `n !`. -/ +private def L (q n : ℕ) : ℕ := padicValNat q (n !) + +/-- `rowProd 0 = 1`. -/ +private lemma g_zero (q : ℕ) : g q 0 = 0 := by simp [g, rowProd] + +/-- `rowProd 1 = 1`. -/ +private lemma g_one (q : ℕ) : g q 1 = 0 := by simp [g, rowProd, Finset.prod_range_succ] + +/-- `0 ! = 1`. -/ +private lemma L_zero (q : ℕ) : L q 0 = 0 := by simp [L] + +/-- `1 ! = 1`. -/ +private lemma L_one (q : ℕ) : L q 1 = 0 := by simp [L] + +/-- `q ∤ q m + r` for `0 < r < q`. -/ +private lemma v_eq_zero (q m r : ℕ) (h0 : 0 < r) (h : r < q) : + padicValNat q (q * m + r) = 0 := by + apply padicValNat.eq_zero_of_not_dvd + rw [Nat.dvd_add_right (dvd_mul_right q m)] + exact Nat.not_dvd_of_pos_of_lt h0 h + +section Val + +variable (q : ℕ) [hq : Fact q.Prime] + +/-- Valuation form of `rowProd (n+1) * (n+1)! = rowProd n * (n+1)^(n+1)`. -/ +private lemma rec_val (n : ℕ) : + g q (n + 1) + L q (n + 1) = g q n + (n + 1) * padicValNat q (n + 1) := by + have h := congrArg (padicValNat q) (rowProd_succ_mul n) + rw [padicValNat.mul (rowProd_pos _).ne' (factorial_ne_zero _), + padicValNat.mul (rowProd_pos _).ne' (pow_ne_zero _ (succ_ne_zero n)), padicValNat.pow] at h + exact h + +/-- Legendre recursion: `v_q((q m + r)!) = m + v_q(m!)` for `r < q`. -/ +private lemma L_mul_add (m r : ℕ) (hr : r < q) : L q (q * m + r) = m + L q m := by + unfold L + rw [padicValNat_factorial_mul_add m hr, padicValNat_factorial_mul, add_comm] + +/-- `v_q((q m)!) = m + v_q(m!)`. -/ +private lemma L_mul (m : ℕ) : L q (q * m) = m + L q m := by + simpa using L_mul_add q m 0 hq.out.pos + +/-- `v_q(q m) = 1 + v_q(m)`. -/ +private lemma v_mul (m : ℕ) (hm : m ≠ 0) : padicValNat q (q * m) = 1 + padicValNat q m := by + rw [padicValNat.mul hq.out.ne_zero hm, padicValNat_self] + +/-- One step inside a block `q m, …, q m + q - 1`. -/ +private lemma step_inner (m r : ℕ) (h : r + 1 < q) : + (g q (q * m + (r + 1)) : ℤ) = g q (q * m + r) - (m + L q m) := by + have h1 := rec_val q (q * m + r) + rw [add_assoc, v_eq_zero q m (r + 1) (succ_pos r) h, L_mul_add q m (r + 1) h] at h1 + have h2 : ((g q (q * m + (r + 1)) + (m + L q m) : ℕ) : ℤ) = (g q (q * m + r) : ℕ) := by + rw [h1]; simp + push_cast at h2 + linarith + +/-- Inside a block: `g(q m + r) = g(q m) - r (m + L m)`. -/ +private lemma block (m r : ℕ) (h : r < q) : + (g q (q * m + r) : ℤ) = g q (q * m) - r * (m + L q m) := by + induction r with + | zero => simp + | succ r ih => + rw [step_inner q m r h, ih (by omega)] + push_cast + ring + +/-- The basic recursion `g(q m) = q g(m) + (q - 1)(m + L m)`. -/ +private lemma g_mul (m : ℕ) : + (g q (q * m) : ℤ) = q * g q m + (q - 1) * (m + L q m) := by + have hq1 := hq.out.one_lt + induction m with + | zero => simp [g_zero q, L_zero q] + | succ m ih => + have e1 : q * m + (q - 1) + 1 = q * (m + 1) := by + rw [Nat.mul_succ]; omega + have hA := rec_val q (q * m + (q - 1)) + rw [e1, v_mul q (m + 1) (succ_ne_zero m), L_mul] at hA + have hB := block q m (q - 1) (by omega) + rw [ih] at hB + have hE := rec_val q m + have hc : (((q - 1 : ℕ)) : ℤ) = (q : ℤ) - 1 := by + rw [Nat.cast_sub hq1.le, Nat.cast_one] + rw [hc] at hB + have hA' : ((g q (q * (m + 1)) + (m + 1 + L q (m + 1)) : ℕ) : ℤ) = + ((g q (q * m + (q - 1)) + q * (m + 1) * (1 + padicValNat q (m + 1)) : ℕ) : ℤ) := by + rw [hA] + have hE' : ((g q (m + 1) + L q (m + 1) : ℕ) : ℤ) = + ((g q m + (m + 1) * padicValNat q (m + 1) : ℕ) : ℤ) := by + rw [hE] + simp only [Nat.cast_add, Nat.cast_mul, Nat.cast_one] at hA' hE' + simp only [Nat.cast_add, Nat.cast_one] + linear_combination hA' + hB - q * hE' + +/-- `g(q m + r) = q g(m) + (q - 1 - r)(m + L m)` for `r < q`. -/ +private lemma g_mul_add (m r : ℕ) (hr : r < q) : + (g q (q * m + r) : ℤ) = q * g q m + (q - 1 - r) * (m + L q m) := by + rw [block q m r hr, g_mul] + ring + +/-- `(q - 1) v_q(u!) < u` for `u ≠ 0`. -/ +private lemma S_pos (u : ℕ) (hu : u ≠ 0) : ((q : ℤ) - 1) * L q u + 1 ≤ u := by + have h := sub_one_mul_padicValNat_factorial_lt_of_ne_zero q hu + have hc : (((q - 1 : ℕ)) : ℤ) = (q : ℤ) - 1 := by + rw [Nat.cast_sub hq.out.one_lt.le, Nat.cast_one] + have h' : (((q - 1) * padicValNat q u ! : ℕ) : ℤ) < (u : ℤ) := by exact_mod_cast h + rw [Nat.cast_mul, hc] at h' + unfold L + linarith + +/-- The base-`q` digit sum `u - (q - 1) v_q(u!)` of `u ≥ 2` with `q ∤ u` is at least `2`. -/ +private lemma S_two (u : ℕ) (hu : 2 ≤ u) (hqu : ¬ q ∣ u) : ((q : ℤ) - 1) * L q u + 2 ≤ u := by + have hq0 := hq.out.pos + have hu' : u = q * (u / q) + u % q := (Nat.div_add_mod u q).symm + have hr : u % q < q := Nat.mod_lt _ hq0 + have hr0 : 0 < u % q := by + rcases Nat.eq_zero_or_pos (u % q) with h | h + · exact absurd (Nat.dvd_of_mod_eq_zero h) hqu + · exact h + have hL := L_mul_add q (u / q) (u % q) hr + rw [← hu'] at hL + rcases Nat.eq_zero_or_pos (u / q) with hm | hm + · rw [hm, L_zero q] at hL + rw [hL]; push_cast; linarith + · have h1 := S_pos q (u / q) hm.ne' + have hu'' : (u : ℤ) = q * (u / q : ℕ) + (u % q : ℕ) := by exact_mod_cast hu' + rw [hL, hu''] + push_cast + have : (1 : ℤ) ≤ ((u % q : ℕ) : ℤ) := by exact_mod_cast hr0 + nlinarith + +/-- Key lemma: if `g(u) ≥ 1` then `(q - 1)(g(u) + L(u)) ≥ u`. -/ +private lemma key_ineq (u : ℕ) (hg : 1 ≤ g q u) : + (u : ℤ) ≤ ((q : ℤ) - 1) * (g q u + L q u) := by + have hq1 := hq.out.one_lt + induction u using Nat.strong_induction_on with + | _ u ih => + have hu' : u = q * (u / q) + u % q := (Nat.div_add_mod u q).symm + have hr : u % q < q := Nat.mod_lt _ (by omega) + have hg' := g_mul_add q (u / q) (u % q) hr + have hL := L_mul_add q (u / q) (u % q) hr + rw [← hu'] at hg' hL + have hu'' : (u : ℤ) = q * (u / q : ℕ) + (u % q : ℕ) := by exact_mod_cast hu' + set m := u / q with hm + set r := u % q with hrdef + have hgm : (0 : ℤ) ≤ g q m := by positivity + have hLm : (0 : ℤ) ≤ L q m := by positivity + have hr0 : (0 : ℤ) ≤ r := by positivity + have hgu : (1 : ℤ) ≤ g q u := by exact_mod_cast hg + have hqZ : (2 : ℤ) ≤ q := by exact_mod_cast hq1 + rw [hL, hu''] + push_cast + rcases Nat.lt_or_ge (r + 1) q with hrq | hrq + · -- `r ≤ q - 2` + have hrqZ : (r : ℤ) + 2 ≤ q := by exact_mod_cast hrq + rcases Nat.eq_zero_or_pos m with hm0 | hm0 + · rw [hm0, g_zero q, L_zero q] at hg' + push_cast at hg' + linarith + · have hmZ : (1 : ℤ) ≤ m := by exact_mod_cast hm0 + rw [hg'] + nlinarith [mul_nonneg (mul_nonneg (by linarith : (0:ℤ) ≤ m) (by linarith : (0:ℤ) ≤ q)) + (by linarith : (0:ℤ) ≤ q - r - 2), mul_nonneg hr0 (by linarith : (0:ℤ) ≤ m - 1), + mul_nonneg (by linarith : (0:ℤ) ≤ q - 1) hgm, + mul_nonneg (mul_nonneg (by linarith : (0:ℤ) ≤ q - 1) (by linarith : (0:ℤ) ≤ q)) hgm, + mul_nonneg (mul_nonneg (by linarith : (0:ℤ) ≤ q - 1) (by linarith : (0:ℤ) ≤ q - r)) + hLm] + · -- `r = q - 1` + have hrq' : r + 1 = q := by omega + have hrZ : (r : ℤ) = q - 1 := by + have : ((r + 1 : ℕ) : ℤ) = q := by exact_mod_cast hrq' + push_cast at this; linarith + rw [hrZ] at hg' + have hg'' : (g q u : ℤ) = q * g q m := by rw [hg']; ring + have hgm1 : 1 ≤ g q m := by + by_contra hcon + have : g q m = 0 := by omega + rw [this] at hg'' + push_cast at hg'' + linarith + have hu0 : u ≠ 0 := by + rintro rfl + rw [g_zero q] at hg + omega + have hmu : m < u := Nat.div_lt_self (Nat.pos_of_ne_zero hu0) hq1 + have ih' := ih m hmu hgm1 + rw [hg'', hrZ] + have hgm1Z : (1 : ℤ) ≤ g q m := by exact_mod_cast hgm1 + nlinarith [mul_nonneg (mul_nonneg (by linarith : (0:ℤ) ≤ q - 1) + (by linarith : (0:ℤ) ≤ q - 1)) (by linarith : (0:ℤ) ≤ g q m - 1), + mul_nonneg (by linarith : (0:ℤ) ≤ q - 2) (by linarith : (0:ℤ) ≤ q - 1)] + +/-- `(q - 1) L(q^e u) = (q - 1) L(u) + (q^e - 1) u`. -/ +private lemma L_pow (e u : ℕ) : + ((q : ℤ) - 1) * L q (q ^ e * u) = (q - 1) * L q u + ((q : ℤ) ^ e - 1) * u := by + induction e with + | zero => simp + | succ e ih => + have h1 : q ^ (e + 1) * u = q * (q ^ e * u) := by ring + rw [h1, L_mul] + push_cast + linear_combination ih + +/-- Closed form of `g(q^e u)`, multiplied by `q - 1`. -/ +private lemma g_pow (e u : ℕ) : + ((q : ℤ) - 1) * g q (q ^ e * u) = (q : ℤ) ^ e * ((q - 1) * g q u - (u - (q - 1) * L q u)) + + (q - 1) * e * q ^ e * u + (u - (q - 1) * L q u) := by + induction e with + | zero => simp + | succ e ih => + have h1 : q ^ (e + 1) * u = q * (q ^ e * u) := by ring + rw [h1, g_mul] + have hL := L_pow q e u + push_cast + linear_combination q * ih + (q - 1) * hL + +/-- For `e ≥ 2`, `q^e - 1 > (q - 1) e`. -/ +private lemma pow_gt (e : ℕ) : ((q : ℤ) - 1) * (e + 2) + 1 < (q : ℤ) ^ (e + 2) := by + have hqZ : (2 : ℤ) ≤ q := by exact_mod_cast hq.out.one_lt + induction e with + | zero => push_cast; nlinarith + | succ e ih => + push_cast at ih ⊢ + rw [pow_succ] + have ih' : ((q : ℤ) - 1) * (e + 2) + 2 ≤ (q : ℤ) ^ (e + 2) := by linarith + have he : (0 : ℤ) ≤ e := by positivity + nlinarith [mul_le_mul_of_nonneg_right ih' (by linarith : (0 : ℤ) ≤ q), + mul_nonneg (by linarith : (0 : ℤ) ≤ q - 1) + (by nlinarith : (0 : ℤ) ≤ (e + 2) * (q - 1) + 1)] + +/-- `v_q(rowProd k) - v_q(k!) = g(k+1) - k v_q(k+1)`. -/ +private lemma key_rel (k : ℕ) : + (g q k : ℤ) - L q k = g q (k + 1) - k * padicValNat q (k + 1) := by + have h1 := rec_val q k + have h2 : L q (k + 1) = L q k + padicValNat q (k + 1) := by + unfold L + rw [factorial_succ, padicValNat.mul (succ_ne_zero k) (factorial_ne_zero k), add_comm] + have h1' : ((g q (k + 1) + L q (k + 1) : ℕ) : ℤ) = + ((g q k + (k + 1) * padicValNat q (k + 1) : ℕ) : ℤ) := by rw [h1] + have h2' : ((L q (k + 1) : ℕ) : ℤ) = ((L q k + padicValNat q (k + 1) : ℕ) : ℤ) := by rw [h2] + simp only [Nat.cast_add, Nat.cast_mul, Nat.cast_one] at h1' h2' + linear_combination h2' - h1' + +/-- `q`-part of `k ! ∣ rowProd k`. -/ +private lemma val_fact_iff (k : ℕ) : + padicValNat q (k !) ≤ padicValNat q (rowProd k) ↔ + (0 : ℤ) ≤ g q (k + 1) - k * padicValNat q (k + 1) := by + rw [← key_rel q k] + change L q k ≤ g q k ↔ _ + constructor + · intro h + have : (L q k : ℤ) ≤ g q k := by exact_mod_cast h + linarith + · intro h + have : (L q k : ℤ) ≤ g q k := by linarith + exact_mod_cast this + +/-- `q`-part of `(k + 1)! ∣ rowProd k`. -/ +private lemma val_fact_succ_iff (k : ℕ) : + padicValNat q ((k + 1)!) ≤ padicValNat q (rowProd k) ↔ + (padicValNat q (k + 1) : ℤ) ≤ g q (k + 1) - k * padicValNat q (k + 1) := by + rw [← key_rel q k, factorial_succ, padicValNat.mul (succ_ne_zero k) (factorial_ne_zero k)] + change padicValNat q (k + 1) + L q k ≤ g q k ↔ _ + constructor + · intro h + have : ((padicValNat q (k + 1) + L q k : ℕ) : ℤ) ≤ g q k := by exact_mod_cast h + rw [Nat.cast_add] at this + linarith + · intro h + have : ((padicValNat q (k + 1) + L q k : ℕ) : ℤ) ≤ g q k := by + rw [Nat.cast_add]; linarith + exact_mod_cast this + +/-- `g(q) = q - 1`. -/ +private lemma g_self : (g q q : ℤ) = q - 1 := by + have h := g_mul q 1 + rw [mul_one, g_one q, L_one q] at h + rw [h] + push_cast + ring + +/-- The dichotomy: if `q ∣ n` and `n ≠ q`, then with `D = g(n) - (n - 1) v_q(n)`, either +`D < 0` or `D ≥ v_q(n)`. -/ +private lemma dichotomy (n : ℕ) (hn : n ≠ 0) (hdvd : q ∣ n) (hne : n ≠ q) : + (g q n : ℤ) - ((n : ℤ) - 1) * padicValNat q n < 0 ∨ + (padicValNat q n : ℤ) ≤ (g q n : ℤ) - ((n : ℤ) - 1) * padicValNat q n := by + obtain ⟨e, u, hqu, rfl⟩ := Nat.exists_eq_pow_mul_and_not_dvd hn q hq.out.ne_one + have hu0 : u ≠ 0 := by rintro rfl; simp at hn + have hv : padicValNat q (q ^ e * u) = e := by + rw [padicValNat.mul (pow_ne_zero _ hq.out.ne_zero) hu0, padicValNat.prime_pow, + padicValNat.eq_zero_of_not_dvd hqu, add_zero] + have he : 1 ≤ e := by + rcases Nat.eq_zero_or_pos e with h | h + · subst h + rw [pow_zero, one_mul] at hdvd + exact absurd hdvd hqu + · exact h + rw [hv] + have hG := g_pow q e u + have hS1 := S_pos q u hu0 + have hqZ : (2 : ℤ) ≤ q := by exact_mod_cast hq.out.one_lt + have hcast : ((q ^ e * u : ℕ) : ℤ) = (q : ℤ) ^ e * u := by push_cast; ring + rw [hcast] + have hqe : (1 : ℤ) ≤ (q : ℤ) ^ e := one_le_pow₀ (by linarith) + set D := (g q (q ^ e * u) : ℤ) - ((q : ℤ) ^ e * u - 1) * e with hD + set S := (u : ℤ) - (q - 1) * L q u with hS + rcases Nat.eq_zero_or_pos (g q u) with hg0 | hg1 + · left + rw [hg0] at hG + have key : ((q : ℤ) - 1) * D = -(((q : ℤ) ^ e - 1) * S) + (q - 1) * e := by + rw [hD]; push_cast at hG; linear_combination hG + have hneg : ((q : ℤ) - 1) * D < 0 := by + rw [key] + rcases Nat.lt_or_ge e 2 with he2 | he2 + · have he1 : e = 1 := by omega + subst he1 + have hu2 : 2 ≤ u := by + rcases Nat.lt_or_ge u 2 with h | h + · have : u = 1 := by omega + subst this + simp at hne + · exact h + have hS2 := S_two q u hu2 hqu + push_cast + nlinarith + · obtain ⟨d, rfl⟩ : ∃ d, e = d + 2 := ⟨e - 2, by omega⟩ + have hpg := pow_gt q d + push_cast at hpg ⊢ + nlinarith [mul_le_mul_of_nonneg_left (by linarith : (1 : ℤ) ≤ S) + (by linarith : (0 : ℤ) ≤ (q : ℤ) ^ (d + 2) - 1)] + by_contra hcon + rw [not_lt] at hcon + nlinarith [mul_nonneg (by linarith : (0 : ℤ) ≤ q - 1) hcon] + · right + have hK := key_ineq q u hg1 + have hK' : (0 : ℤ) ≤ (q - 1) * g q u - S := by rw [hS]; linarith + have key : ((q : ℤ) - 1) * D = (q : ℤ) ^ e * ((q - 1) * g q u - S) + S + (q - 1) * e := by + rw [hD, hS]; rw [hS] at hK'; linear_combination hG + have hpos : ((q : ℤ) - 1) * (D - e) ≥ 1 := by + nlinarith [mul_nonneg (by linarith : (0 : ℤ) ≤ (q : ℤ) ^ e) hK'] + by_contra hcon + rw [not_le] at hcon + nlinarith [mul_nonneg (by linarith : (0 : ℤ) ≤ q - 1) (by linarith : (0 : ℤ) ≤ e - D)] + +end Val + +/-- `IsGreatest` reduces to `k ! ∣ P ∧ ¬ (k + 1)! ∣ P`, since the set is downward closed. -/ +private lemma isGreatest_iff (k P : ℕ) : + IsGreatest {m : ℕ | m ! ∣ P} k ↔ k ! ∣ P ∧ ¬ (k + 1)! ∣ P := by + constructor + · rintro ⟨h1, h2⟩ + exact ⟨h1, fun h => absurd (h2 h) (by omega)⟩ + · rintro ⟨h1, h2⟩ + refine ⟨h1, fun m hm => ?_⟩ + by_contra hlt + exact h2 ((factorial_dvd_factorial (by omega)).trans hm) + +/-- Divisibility of `rowProd k` via `p`-adic valuations. -/ +private lemma dvd_rowProd_iff (k d : ℕ) (hd : d ≠ 0) : + d ∣ rowProd k ↔ ∀ q, q.Prime → padicValNat q d ≤ padicValNat q (rowProd k) := by + rw [← Nat.factorization_prime_le_iff_dvd hd (rowProd_pos k).ne'] + refine forall_congr' fun q => forall_congr' fun hq => ?_ + rw [Nat.factorization_def _ hq, Nat.factorization_def _ hq] + +/-- Karttunen's conjecture: `A249151(k) = k` iff `k + 1` is prime. -/ +theorem result : statement := by + intro k + rw [isGreatest_iff] + by_cases hp : (k + 1).Prime + · simp only [hp, iff_true] + constructor + · refine (dvd_rowProd_iff k _ (factorial_ne_zero k)).2 fun q hq => ?_ + have := Fact.mk hq + rw [val_fact_iff] + by_cases hqn : q ∣ k + 1 + · have hqe : q = k + 1 := (Nat.prime_dvd_prime_iff_eq hq hp).1 hqn + have hg := g_self q + rw [← hqe, padicValNat_self, hg, hqe] + push_cast + linarith + · rw [padicValNat.eq_zero_of_not_dvd hqn] + push_cast + linarith [(Nat.cast_nonneg (g q (k + 1)) : (0 : ℤ) ≤ _)] + · intro h + have h' := (dvd_rowProd_iff k _ (factorial_ne_zero _)).1 h (k + 1) hp + have := Fact.mk hp + rw [val_fact_succ_iff, padicValNat_self, g_self] at h' + push_cast at h' + linarith + · simp only [hp, iff_false, not_and, not_not] + intro h1 + refine (dvd_rowProd_iff k _ (factorial_ne_zero _)).2 fun q hq => ?_ + have h1q := (dvd_rowProd_iff k _ (factorial_ne_zero k)).1 h1 q hq + have := Fact.mk hq + rw [val_fact_iff] at h1q + rw [val_fact_succ_iff] + by_cases hqn : q ∣ k + 1 + · have hne : k + 1 ≠ q := fun h => hp (h ▸ hq) + have hd := dichotomy q (k + 1) (succ_ne_zero k) hqn hne + simp only [Nat.cast_add, Nat.cast_one, add_sub_cancel_right] at hd + rcases hd with hd | hd + · linarith + · exact hd + · rw [padicValNat.eq_zero_of_not_dvd hqn] at h1q ⊢ + push_cast at h1q ⊢ + linarith + +end Math0.Frontier.A249434 + +#math0_settles Math0.Frontier.A249434.result Math0.Statements.A249434.statement diff --git a/lean/Math0/Frontier/OEIS/A262957.lean b/lean/Math0/Frontier/OEIS/A262957.lean new file mode 100644 index 0000000..5ca2971 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A262957.lean @@ -0,0 +1,199 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A262957 +import Math0.Audit + +/-! +# A262957: Israel's `b(n)` and `c(n)` are coprime, so `a(n) = b(n)` + +We prove Robert Israel's conjecture from OEIS A262957: the sequences `b`, `c` defined by +`b(1)=2, b(2)=3, c(1)=3, c(2)=5` and +`x(n+1) = (((-1)^n(n-1)+n(n+2)) x(n) - (1+(-1)^n(n+1)) x(n-1)) / (n-(-1)^n)` are coprime +integers, and `a(n) = b(n)`. + +**Convergents.** Let `p`, `q : ℕ → ℤ` satisfy `r(k+2) = (k+2) r(k+1) + (-1)^(k+1) r(k)` with +`p(0)=p(1)=1`, `q(0)=0`, `q(1)=1` (these are the shifted convergent numerators/denominators of +the continued fraction). By induction on `k`, for every `t ≥ 1` the fold of +`i, u ↦ i + (-1)^i/u` over `1, …, k+1` with innermost value `t` equals +`(p(k+1) t + (-1)^(k+1) p(k)) / (q(k+1) t + (-1)^(k+1) q(k))` (each step multiplies numerator +and denominator by `t ≠ 0`). With `t = 1`, `cf n = x(n)/y(n)` where +`x(n) = p(n+1) + (-1)^(n+1) p(n)`, `y(n) = q(n+1) + (-1)^(n+1) q(n)`. + +**Israel's recurrence.** Writing everything in terms of `r(m+1), r(m+2)` and splitting on the +parity of `m`, `x` and `y` satisfy Israel's recurrence (a polynomial identity), and their +initial values are `2, 3` and `3, 5`. Hence `b = x`, `c = y`. + +**Coprimality.** `x(n) q(n) - p(n) y(n) = p(n+1) q(n) - p(n) q(n+1) = ±1` (the determinant +changes by the factor `-(-1)^(k+1)` at each step and starts at `-1`), so `x(n)`, `y(n)` are +coprime. Both are positive for `n ≥ 1` (monotonicity of `p`, `q`), so the reduced numerator of +`cf n` is `x(n) = b(n)`. +-/ + +namespace Math0.Frontier.A262957 +open Math0.Statements.A262957 + +/-- Shifted convergent sequence: `r 0 = r₀`, `r 1 = r₁`, +`r (k+2) = (k+2) r (k+1) + (-1)^(k+1) r k`. -/ +private def seq (r₀ r₁ : ℤ) : ℕ → ℤ + | 0 => r₀ + | 1 => r₁ + | k + 2 => ((k : ℤ) + 2) * seq r₀ r₁ (k + 1) + (-1) ^ (k + 1) * seq r₀ r₁ k + +/-- The defining recurrence of `seq`. -/ +private lemma seq_succ_succ (r₀ r₁ : ℤ) (k : ℕ) : + seq r₀ r₁ (k + 2) = ((k : ℤ) + 2) * seq r₀ r₁ (k + 1) + (-1) ^ (k + 1) * seq r₀ r₁ k := by + rw [seq] + +/-- `z n = r (n+1) + (-1)^(n+1) r n`, the numerator/denominator candidate. -/ +private def z (r₀ r₁ : ℤ) (n : ℕ) : ℤ := seq r₀ r₁ (n + 1) + (-1) ^ (n + 1) * seq r₀ r₁ n + +/-- `z` satisfies Israel's recurrence. -/ +private lemma step_z (r₀ r₁ : ℤ) (m : ℕ) : + step (m + 2) (z r₀ r₁ (m + 1) : ℚ) (z r₀ r₁ (m + 2) : ℚ) = (z r₀ r₁ (m + 3) : ℚ) := by + have h4 := seq_succ_succ r₀ r₁ (m + 2) + have h3 := seq_succ_succ r₀ r₁ (m + 1) + simp only [step, z] + rw [show m + 3 + 1 = (m + 2) + 2 by ring, h4, show m + 2 + 1 = (m + 1) + 2 by ring, h3] + push_cast + rcases neg_one_pow_eq_or ℚ m with h | h <;> simp only [pow_succ, h] + · have hne : (m : ℚ) + 2 - 1 * (-1) * (-1) ≠ 0 := by + have : (0 : ℚ) ≤ m := Nat.cast_nonneg m + intro h'; linarith + rw [div_eq_iff hne]; ring + · have hne : (m : ℚ) + 2 - (-1) * (-1) * (-1) ≠ 0 := by + have : (0 : ℚ) ≤ m := Nat.cast_nonneg m + intro h'; linarith + rw [div_eq_iff hne]; ring + +/-- `israelPair` started from `z 1, z 2` runs through the values of `z`. -/ +private lemma israelPair_z (r₀ r₁ : ℤ) (m : ℕ) : + israelPair (z r₀ r₁ 1 : ℚ) (z r₀ r₁ 2 : ℚ) m = + ((z r₀ r₁ (m + 1) : ℚ), (z r₀ r₁ (m + 2) : ℚ)) := by + induction m with + | zero => rfl + | succ m ih => + rw [israelPair, ih] + simp only [Prod.mk.injEq, true_and] + exact step_z r₀ r₁ m + +/-- Monotonicity and nonnegativity of `seq` when `0 ≤ r₀ ≤ r₁`. -/ +private lemma seq_mono (r₀ r₁ : ℤ) (h0 : 0 ≤ r₀) (h1 : r₀ ≤ r₁) (k : ℕ) : + 0 ≤ seq r₀ r₁ k ∧ seq r₀ r₁ k ≤ seq r₀ r₁ (k + 1) := by + induction k with + | zero => exact ⟨h0, h1⟩ + | succ k ih => + obtain ⟨ha, hb⟩ := ih + refine ⟨le_trans ha hb, ?_⟩ + rw [seq_succ_succ] + have hk : (0 : ℤ) ≤ k := Int.natCast_nonneg k + have hs : -seq r₀ r₁ k ≤ (-1) ^ (k + 1) * seq r₀ r₁ k := by + rcases neg_one_pow_eq_or ℤ (k + 1) with h | h <;> rw [h] <;> linarith + nlinarith + +/-- Positivity of `z n` for `n ≥ 1`, given monotonicity and `r k ≥ 1` for `k ≥ 1`. -/ +private lemma z_pos (r₀ r₁ : ℤ) (h0 : 0 ≤ r₀) (h1 : r₀ ≤ r₁) (h11 : 1 ≤ r₁) (n : ℕ) + (hn : 1 ≤ n) : 0 < z r₀ r₁ n := by + obtain ⟨j, rfl⟩ : ∃ j, n = j + 1 := ⟨n - 1, by omega⟩ + have hmono : Monotone (seq r₀ r₁) := + monotone_nat_of_le_succ (fun k => (seq_mono r₀ r₁ h0 h1 k).2) + have hs1 : seq r₀ r₁ 1 = r₁ := by rw [seq] + have hge : 1 ≤ seq r₀ r₁ (j + 1) := le_trans h11 (hs1 ▸ hmono (show 1 ≤ j + 1 by omega)) + have hj0 := (seq_mono r₀ r₁ h0 h1 j).1 + have hj1 := (seq_mono r₀ r₁ h0 h1 j).2 + have hjn : (0 : ℤ) ≤ j := Int.natCast_nonneg j + simp only [z] + rw [seq_succ_succ] + rcases neg_one_pow_eq_or ℤ j with h | h <;> simp only [pow_succ, h] <;> nlinarith + +/-- The determinant `p(k+1) q(k) - p(k) q(k+1)` is `±1`. -/ +private lemma det_eq (k : ℕ) : + seq 1 1 (k + 1) * seq 0 1 k - seq 1 1 k * seq 0 1 (k + 1) = 1 ∨ + seq 1 1 (k + 1) * seq 0 1 k - seq 1 1 k * seq 0 1 (k + 1) = -1 := by + induction k with + | zero => right; decide + | succ k ih => + rw [seq_succ_succ 1 1 k, seq_succ_succ 0 1 k] + have e : (((k : ℤ) + 2) * seq 1 1 (k + 1) + (-1) ^ (k + 1) * seq 1 1 k) * seq 0 1 (k + 1) - + seq 1 1 (k + 1) * (((k : ℤ) + 2) * seq 0 1 (k + 1) + (-1) ^ (k + 1) * seq 0 1 k) = + -(-1) ^ (k + 1) * (seq 1 1 (k + 1) * seq 0 1 k - seq 1 1 k * seq 0 1 (k + 1)) := by ring + rw [e] + rcases neg_one_pow_eq_or ℤ (k + 1) with h | h <;> rw [h] <;> rcases ih with h' | h' <;> + rw [h'] <;> norm_num + +/-- The fold defining `cf`, over `1, …, k+1` with innermost value `t ≥ 1`, is the Möbius map +given by the convergents. -/ +private lemma fold_eq (k : ℕ) : ∀ t : ℚ, 1 ≤ t → + (List.range' 1 (k + 1)).foldr (fun (i : ℕ) (u : ℚ) => (i : ℚ) + (-1) ^ i / u) t = + ((seq 1 1 (k + 1) : ℚ) * t + (-1) ^ (k + 1) * (seq 1 1 k : ℚ)) / + ((seq 0 1 (k + 1) : ℚ) * t + (-1) ^ (k + 1) * (seq 0 1 k : ℚ)) := by + induction k with + | zero => + intro t ht + have ht0 : t ≠ 0 := by intro h; rw [h] at ht; norm_num at ht + simp [seq] + field_simp + | succ k ih => + intro t ht + have ht0 : t ≠ 0 := by intro h; rw [h] at ht; norm_num at ht + rw [List.range'_concat, List.foldr_append, show 1 + 1 * (k + 1) = k + 2 by ring] + simp only [List.foldr_cons, List.foldr_nil] + have ht' : 1 ≤ ((k + 2 : ℕ) : ℚ) + (-1) ^ (k + 2) / t := by + have hinv : 1 / t ≤ 1 := by rw [div_le_one (by linarith)]; exact ht + have hinv0 : 0 ≤ 1 / t := by positivity + have hk : (0 : ℚ) ≤ k := Nat.cast_nonneg k + push_cast + rcases neg_one_pow_eq_or ℚ (k + 2) with h | h <;> rw [h] <;> + [skip; rw [neg_div]] <;> linarith + rw [ih _ ht'] + rw [seq_succ_succ 1 1 k, seq_succ_succ 0 1 k] + have key : ∀ r₀ r₁ : ℤ, + (seq r₀ r₁ (k + 1) : ℚ) * (((k + 2 : ℕ) : ℚ) + (-1) ^ (k + 2) / t) + + (-1) ^ (k + 1) * (seq r₀ r₁ k : ℚ) = + ((((k : ℤ) + 2) * seq r₀ r₁ (k + 1) + (-1) ^ (k + 1) * seq r₀ r₁ k : ℤ) * t + + (-1) ^ (k + 1 + 1) * (seq r₀ r₁ (k + 1) : ℚ)) / t := by + intro r₀ r₁ + rw [eq_div_iff ht0] + push_cast + field_simp + ring + rw [key 1 1, key 0 1, div_div_div_cancel_right₀ ht0] + +/-- `cf n = z_p n / z_q n`. -/ +private lemma cf_eq (n : ℕ) : cf n = (z 1 1 n : ℚ) / (z 0 1 n : ℚ) := by + rw [cf, fold_eq n 1 le_rfl] + simp only [z] + push_cast + ring + +/-- Israel's conjecture holds: `b n`, `c n` are coprime integers and `a n = b n`. -/ +theorem result : statement := by + intro n hn + have hb : b n = (z 1 1 n : ℚ) := by + have h := israelPair_z 1 1 (n - 1) + have e1 : ((z 1 1 1 : ℤ) : ℚ) = 2 := by norm_num [z, seq] + have e2 : ((z 1 1 2 : ℤ) : ℚ) = 3 := by norm_num [z, seq] + rw [e1, e2] at h + rw [b, h, Nat.sub_add_cancel hn] + have hc : c n = (z 0 1 n : ℚ) := by + have h := israelPair_z 0 1 (n - 1) + have e1 : ((z 0 1 1 : ℤ) : ℚ) = 3 := by norm_num [z, seq] + have e2 : ((z 0 1 2 : ℤ) : ℚ) = 5 := by norm_num [z, seq] + rw [e1, e2] at h + rw [c, h, Nat.sub_add_cancel hn] + have hcop : IsCoprime (z 1 1 n) (z 0 1 n) := by + have hd := det_eq n + set d := seq 1 1 (n + 1) * seq 0 1 n - seq 1 1 n * seq 0 1 (n + 1) with hd_def + have hd2 : d * d = 1 := by rcases hd with h | h <;> rw [h] <;> norm_num + refine ⟨d * seq 0 1 n, -(d * seq 1 1 n), ?_⟩ + simp only [z] + linear_combination hd2 + have hxpos : 0 < z 1 1 n := z_pos 1 1 (by norm_num) le_rfl le_rfl n hn + have hypos : 0 < z 0 1 n := z_pos 0 1 le_rfl (by norm_num) le_rfl n hn + refine ⟨z 1 1 n, z 0 1 n, hb, hc, Int.isCoprime_iff_gcd_eq_one.mp hcop, ?_⟩ + rw [hb, a, cf_eq, Rat.num_div_eq_of_coprime hypos (Int.isCoprime_iff_gcd_eq_one.mp hcop)] + rw [Nat.cast_natAbs, Int.cast_abs, abs_of_pos (by exact_mod_cast hxpos)] + +end Math0.Frontier.A262957 + +#math0_settles Math0.Frontier.A262957.result Math0.Statements.A262957.statement diff --git a/lean/Math0/Frontier/OEIS/A265210.lean b/lean/Math0/Frontier/OEIS/A265210.lean new file mode 100644 index 0000000..130c4d1 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A265210.lean @@ -0,0 +1,308 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A265210 +import Math0.Audit + +/-! +# Columns of the reversed ternary digits of `2^n` + +We prove Conjecture 1 of OEIS A265210: column `k` of the triangle of reversed base-3 digits +of `2^n` has least period `p(k) = 2 * 3^(k-1)`, and for `k ≥ 2` each block of `p(k)` +consecutive entries contains each of the digits `0, 1, 2` exactly `2 * 3^(k-2)` times. + +The entry of row `n` in column `k` is `⌊2^n / 3^(k-1)⌋ mod 3`, which only depends on +`2^n mod 3^k`. For `k = j + 2` write `B = 3^(j+1)`, `M = 3^(j+2) = 3B`, `r = 2 * 3^j`. +An induction (`x^3 = (3^(j+1) t - 1)^3`) gives `2^(3^j) = 3^(j+1) t - 1` with `t ≡ 1 (mod 3)`. +Consequently +* `2^B ≡ -1 (mod M)` and `2^(2B) ≡ 1 (mod M)`: the column has period `p = 2B`, and `B` is not + a period (it maps the digit `0` of `2^(pB) ≡ 1` to the digit `2` of `-1`); +* `2^r ≡ 1 + B (mod M)`: shifting by `r` adds `2^n mod 3 ∈ {1, 2}` to the digit (mod 3), so + `r` is not a period, and the three shifts `n, n + r, n + 2r` see each digit exactly once, + which gives the equal frequencies in each window of length `3r = p`. +Any period `q < p` of the column would give the period `gcd q p`, a proper divisor of +`2 * 3^(j+1)`, hence a divisor of `B` or of `r`; both are excluded. Column `1` is +`1, 2, 1, 2, …` and is treated directly. +-/ + +namespace Math0.Frontier.A265210 +open Math0.Statements.A265210 + +/-- The entry of row `n` in column `k` is the base-3 digit of `2^n` at the place `3^(k-1)`. -/ +private lemma T_eq (n k : ℕ) : T n k = 2 ^ n / 3 ^ (k - 1) % 3 := by + unfold T row + exact Nat.getD_digits _ _ (by norm_num) + +/-- Column `j + 2` in closed form. -/ +private lemma T_eq' (n j : ℕ) : T n (j + 2) = 2 ^ n / 3 ^ (j + 1) % 3 := by + rw [T_eq] + rfl + +/-- Row `n` has an entry in column `k ≥ 1` iff `3^(k-1) ≤ 2^n`. -/ +private lemma len_iff (n k : ℕ) (hk : 1 ≤ k) : k ≤ (row n).length ↔ 3 ^ (k - 1) ≤ 2 ^ n := by + unfold row + constructor + · intro h + by_contra h' + have := (Nat.digits_length_le_iff (b := 3) (k := k - 1) (by norm_num) (2 ^ n)).2 (not_le.1 h') + omega + · intro h + by_contra h' + have := (Nat.digits_length_le_iff (b := 3) (k := k - 1) (by norm_num) (2 ^ n)).1 (by omega) + omega + +/-- Lifting the exponent for `2 ≡ -1 (mod 3)`: `2^(3^j) = 3^(j+1) t - 1` with `t ≡ 1 (mod 3)`. -/ +private lemma key (j : ℕ) : ∃ t : ℤ, (2 : ℤ) ^ (3 ^ j) = 3 ^ (j + 1) * t - 1 ∧ t % 3 = 1 := by + induction j with + | zero => exact ⟨1, by norm_num, by norm_num⟩ + | succ j ih => + obtain ⟨t, ht, ht3⟩ := ih + refine ⟨3 * (3 ^ (2 * j) * t ^ 3 - 3 ^ j * t ^ 2) + t, ?_, ?_⟩ + · rw [pow_succ (3 : ℕ) j, pow_mul, ht] + ring + · generalize 3 ^ (2 * j) * t ^ 3 - 3 ^ j * t ^ 2 = X + omega + +/-- `2^(2 * 3^(j+1)) ≡ 1 (mod 3^(j+2))`. -/ +private lemma E1 (j : ℕ) : 2 ^ (2 * 3 ^ (j + 1)) ≡ 1 [MOD 3 ^ (j + 2)] := by + obtain ⟨t, ht, -⟩ := key (j + 1) + rw [Nat.modEq_iff_dvd] + push_cast + rw [pow_mul', ht] + exact ⟨2 * t - 3 ^ (j + 2) * t ^ 2, by ring⟩ + +/-- `2^(3^(j+1)) ≡ -1 (mod 3^(j+2))`. -/ +private lemma E2 (j : ℕ) : 2 ^ (3 ^ (j + 1)) ≡ 3 ^ (j + 2) - 1 [MOD 3 ^ (j + 2)] := by + obtain ⟨t, ht, -⟩ := key (j + 1) + rw [Nat.modEq_iff_dvd, Nat.cast_sub (Nat.one_le_pow _ _ (by norm_num))] + push_cast + rw [ht] + exact ⟨1 - t, by ring⟩ + +/-- `2^(2 * 3^j) ≡ 1 + 3^(j+1) (mod 3^(j+2))`. -/ +private lemma E3 (j : ℕ) : 2 ^ (2 * 3 ^ j) ≡ 1 + 3 ^ (j + 1) [MOD 3 ^ (j + 2)] := by + obtain ⟨t, ht, ht3⟩ := key j + obtain ⟨s, rfl⟩ : ∃ s, t = 3 * s + 1 := ⟨t / 3, by omega⟩ + rw [Nat.modEq_iff_dvd] + push_cast + rw [pow_mul', ht] + exact ⟨1 + 2 * s - 3 ^ j * (3 * s + 1) ^ 2, by ring⟩ + +/-- The digit at the place `3^(j+1)` only depends on the residue mod `3^(j+2)`. -/ +private lemma dig_congr (j a b : ℕ) (h : a ≡ b [MOD 3 ^ (j + 2)]) : + a / 3 ^ (j + 1) % 3 = b / 3 ^ (j + 1) % 3 := by + have hM : 3 ^ (j + 2) = 3 ^ (j + 1) * 3 := pow_succ 3 (j + 1) + rw [← Nat.mod_mul_right_div_self, ← Nat.mod_mul_right_div_self, ← hM] + rw [h] + +/-- Column `j + 2` has period `2 * 3^(j+1)` (on all rows). -/ +private lemma per (j n : ℕ) : + 2 ^ (n + 2 * 3 ^ (j + 1)) / 3 ^ (j + 1) % 3 = 2 ^ n / 3 ^ (j + 1) % 3 := by + refine dig_congr j _ _ ?_ + rw [pow_add 2 n] + calc 2 ^ n * 2 ^ (2 * 3 ^ (j + 1)) ≡ 2 ^ n * 1 [MOD 3 ^ (j + 2)] := Nat.ModEq.mul_left _ (E1 j) + _ = 2 ^ n := mul_one _ + +/-- Shifting by `2 * 3^j` adds `2^n mod 3` to the digit of column `j + 2`. -/ +private lemma shift (j n : ℕ) : + 2 ^ (n + 2 * 3 ^ j) / 3 ^ (j + 1) % 3 = (2 ^ n / 3 ^ (j + 1) % 3 + 2 ^ n % 3) % 3 := by + have hM : 3 ^ (j + 2) = 3 * 3 ^ (j + 1) := by ring + have h2 : 2 ^ n * 3 ^ (j + 1) ≡ 2 ^ n % 3 * 3 ^ (j + 1) [MOD 3 ^ (j + 2)] := by + unfold Nat.ModEq + rw [hM, Nat.mul_mod_mul_right, Nat.mul_mod_mul_right, Nat.mod_mod] + have h1 : 2 ^ (n + 2 * 3 ^ j) ≡ 2 ^ n + 2 ^ n % 3 * 3 ^ (j + 1) [MOD 3 ^ (j + 2)] := by + rw [pow_add 2 n] + calc 2 ^ n * 2 ^ (2 * 3 ^ j) ≡ 2 ^ n * (1 + 3 ^ (j + 1)) [MOD 3 ^ (j + 2)] := + Nat.ModEq.mul_left _ (E3 j) + _ = 2 ^ n + 2 ^ n * 3 ^ (j + 1) := by ring + _ ≡ 2 ^ n + 2 ^ n % 3 * 3 ^ (j + 1) [MOD 3 ^ (j + 2)] := Nat.ModEq.add_left _ h2 + rw [dig_congr j _ _ h1, Nat.add_mul_div_right _ _ (by positivity)] + generalize 2 ^ n / 3 ^ (j + 1) = X + omega + +/-- `2^n mod 3` is `1` or `2`. -/ +private lemma two_pow_mod_three (n : ℕ) : 2 ^ n % 3 = 1 ∨ 2 ^ n % 3 = 2 := by + induction n with + | zero => left; rfl + | succ n ih => rw [pow_succ]; omega + +/-- Shifting by an even amount does not change `2^n mod 3`. -/ +private lemma mod_three_shift (j n : ℕ) : 2 ^ (n + 2 * 3 ^ j) % 3 = 2 ^ n % 3 := by + have h4 : 4 ^ 3 ^ j ≡ 1 [MOD 3] := by + calc 4 ^ 3 ^ j ≡ 1 ^ 3 ^ j [MOD 3] := Nat.ModEq.pow _ (show 4 % 3 = 1 % 3 from rfl) + _ = 1 := one_pow _ + have e : 2 ^ (n + 2 * 3 ^ j) = 2 ^ n * 4 ^ 3 ^ j := by rw [pow_add, pow_mul]; norm_num + rw [e] + have h := Nat.ModEq.mul_left (2 ^ n) h4 + rw [mul_one] at h + exact h + +/-- If `2^n ≡ 1 (mod 3^(j+2))`, then the digit of row `n` in column `j + 2` is `0`, while the +digit of row `n + 3^(j+1)` is `2`. -/ +private lemma digit_flip (j n : ℕ) (h : 2 ^ n ≡ 1 [MOD 3 ^ (j + 2)]) : + 2 ^ n / 3 ^ (j + 1) % 3 = 0 ∧ 2 ^ (n + 3 ^ (j + 1)) / 3 ^ (j + 1) % 3 = 2 := by + have hB : 3 ≤ 3 ^ (j + 1) := by + calc 3 = 3 ^ 1 := by norm_num + _ ≤ 3 ^ (j + 1) := Nat.pow_le_pow_right (by norm_num) (by omega) + have hM : 3 ^ (j + 2) = 3 ^ (j + 1) * 3 := pow_succ 3 (j + 1) + constructor + · rw [dig_congr j _ _ h, Nat.div_eq_of_lt (by omega)] + · have h' : 2 ^ (n + 3 ^ (j + 1)) ≡ 3 ^ (j + 2) - 1 [MOD 3 ^ (j + 2)] := by + rw [pow_add 2 n] + calc 2 ^ n * 2 ^ (3 ^ (j + 1)) ≡ 1 * (3 ^ (j + 2) - 1) [MOD 3 ^ (j + 2)] := + Nat.ModEq.mul h (E2 j) + _ = 3 ^ (j + 2) - 1 := one_mul _ + rw [dig_congr j _ _ h', hM] + generalize 3 ^ (j + 1) = B at hB ⊢ + rw [Nat.div_eq_of_lt_le (k := 2) (by omega) (by omega)] + +/-- A proper divisor of `2 * 3^(j+1)` divides `3^(j+1)` or `2 * 3^j`. -/ +private lemma proper_dvd (j g : ℕ) (h : g ∣ 2 * 3 ^ (j + 1)) (hlt : g < 2 * 3 ^ (j + 1)) : + g ∣ 3 ^ (j + 1) ∨ g ∣ 2 * 3 ^ j := by + obtain ⟨y, z, hy, hz, rfl⟩ := Nat.dvd_mul.1 h + obtain ⟨b, hb, rfl⟩ := (Nat.dvd_prime_pow Nat.prime_three).1 hz + rcases (Nat.dvd_prime Nat.prime_two).1 hy with rfl | rfl + · left + rw [one_mul] + exact pow_dvd_pow 3 hb + · right + have : b < j + 1 := by + by_contra hcon + have := Nat.pow_le_pow_right (by norm_num : 0 < 3) (not_lt.1 hcon) + omega + exact Nat.mul_dvd_mul_left 2 (pow_dvd_pow 3 (by omega)) + +/-- A window of length `3r` splits into three shifted windows of length `r`. -/ +private lemma count_three (f : ℕ → ℕ) (m r : ℕ) (h : ∀ x, f x + f (x + r) + f (x + r + r) = 1) : + ∑ x ∈ Finset.Ico m (m + (r + r + r)), f x = r := by + rw [Finset.sum_Ico_eq_sum_range, Nat.add_sub_cancel_left, Finset.sum_range_add, + Finset.sum_range_add, ← Finset.sum_add_distrib, ← Finset.sum_add_distrib] + rw [Finset.sum_congr rfl (g := fun _ => 1)] + · simp + · intro x _ + rw [show m + (r + x) = m + x + r by ring, show m + (r + r + x) = m + x + r + r by ring] + exact h (m + x) + +/-- The conjecture holds for column `1`. -/ +private lemma col_one : + (IsColPeriod 1 (p 1) ∧ ∀ q : ℕ, 0 < q → q < p 1 → ¬ IsColPeriod 1 q) := by + have hT : ∀ n, T n 1 = 2 ^ n % 3 := fun n => by rw [T_eq]; simp + refine ⟨fun n _ => ?_, fun q hq0 hq => ?_⟩ + · rw [hT, hT, show p 1 = 2 by rfl, pow_add] + omega + · have hq1 : q = 1 := by + have : p 1 = 2 := rfl + omega + subst hq1 + intro hper + have h0 := hper 0 (by decide) + rw [hT, hT] at h0 + norm_num at h0 + +/-- The digit of `2^n` at the place `3^(j+1)`, i.e. the entry of row `n` in column `j + 2`. -/ +private def dig (j n : ℕ) : ℕ := 2 ^ n / 3 ^ (j + 1) % 3 + +/-- `x` is a period of column `j + 2` on the rows that have an entry in that column. -/ +private def Per (j x : ℕ) : Prop := ∀ n, 3 ^ (j + 1) ≤ 2 ^ n → dig j (n + x) = dig j n + +/-- Multiples of periods are periods. -/ +private lemma Per_mul (j x : ℕ) (hx : Per j x) (t : ℕ) : Per j (x * t) := by + induction t with + | zero => intro n _; simp + | succ t ih => + intro n hn + have hn' : 3 ^ (j + 1) ≤ 2 ^ (n + x * t) := + le_trans hn (Nat.pow_le_pow_right (by norm_num) (by omega)) + rw [show n + x * (t + 1) = (n + x * t) + x by ring, hx _ hn', ih n hn] + +/-- If `q` and `P` are periods (with `gcd q P < P`), then so is `gcd q P`. -/ +private lemma Per_gcd (j q P : ℕ) (hq : Per j q) (hP : Per j P) (hlt : Nat.gcd q P < P) : + Per j (Nat.gcd q P) := by + obtain ⟨c, -, hc⟩ := Nat.exists_mul_mod_eq_gcd (k := P) (n := q) hlt + have hdm := Nat.div_add_mod (q * c) P + intro n hn + have hn' : 3 ^ (j + 1) ≤ 2 ^ (n + Nat.gcd q P) := + le_trans hn (Nat.pow_le_pow_right (by norm_num) (by omega)) + rw [← Per_mul j P hP (q * c / P) _ hn', + show n + Nat.gcd q P + P * (q * c / P) = n + q * c by omega] + exact Per_mul j q hq c n hn + +/-- The conjecture holds for column `j + 2`. -/ +private lemma col_ge_two (j : ℕ) : + (IsColPeriod (j + 2) (p (j + 2)) ∧ ∀ q : ℕ, 0 < q → q < p (j + 2) → + ¬ IsColPeriod (j + 2) q) ∧ + (∀ m : ℕ, ∀ d : ℕ, d < 3 → + ((Finset.Ico m (m + p (j + 2))).filter (fun n => T n (j + 2) = d)).card = 2 * 3 ^ j) := by + have hp : p (j + 2) = 2 * 3 ^ (j + 1) := rfl + have hTd : ∀ n, T n (j + 2) = dig j n := fun n => T_eq' n j + have hlen : ∀ n, j + 2 ≤ (row n).length ↔ 3 ^ (j + 1) ≤ 2 ^ n := + fun n => len_iff n (j + 2) (by omega) + refine ⟨⟨fun n _ => ?_, fun q hq0 hq => ?_⟩, fun m d hd => ?_⟩ + · rw [hTd, hTd, hp] + exact per j n + · intro hper + have hPq : Per j q := fun n hn => by + have := hper n ((hlen n).2 hn) + rwa [hTd, hTd] at this + have hPp : Per j (2 * 3 ^ (j + 1)) := fun n _ => per j n + have hgq : Nat.gcd q (2 * 3 ^ (j + 1)) ≤ q := Nat.le_of_dvd hq0 (Nat.gcd_dvd_left _ _) + have hPg : Per j (Nat.gcd q (2 * 3 ^ (j + 1))) := Per_gcd j _ _ hPq hPp (by omega) + rcases proper_dvd j (Nat.gcd q (2 * 3 ^ (j + 1))) (Nat.gcd_dvd_right _ _) (by omega) + with hd | hd + · -- `3^(j+1)` would be a period + obtain ⟨t, ht⟩ := hd + have hPB : Per j (3 ^ (j + 1)) := by rw [ht]; exact Per_mul j _ hPg t + have h1 : 2 ^ (2 * 3 ^ (j + 1) * 3 ^ (j + 1)) ≡ 1 [MOD 3 ^ (j + 2)] := by + rw [pow_mul] + calc (2 ^ (2 * 3 ^ (j + 1))) ^ 3 ^ (j + 1) ≡ 1 ^ 3 ^ (j + 1) [MOD 3 ^ (j + 2)] := + Nat.ModEq.pow _ (E1 j) + _ = 1 := one_pow _ + have hn : 3 ^ (j + 1) ≤ 2 ^ (2 * 3 ^ (j + 1) * 3 ^ (j + 1)) := + le_trans (Nat.lt_two_pow_self).le + (Nat.pow_le_pow_right (by norm_num) (Nat.le_mul_of_pos_left _ (by positivity))) + have := hPB _ hn + obtain ⟨ha, hb⟩ := digit_flip j _ h1 + unfold dig at this + omega + · -- `2 * 3^j` would be a period + obtain ⟨t, ht⟩ := hd + have hPr : Per j (2 * 3 ^ j) := by rw [ht]; exact Per_mul j _ hPg t + have hn : 3 ^ (j + 1) ≤ 2 ^ 3 ^ (j + 1) := (Nat.lt_two_pow_self).le + have := hPr _ hn + unfold dig at this + rw [shift j] at this + have h3 := two_pow_mod_three (3 ^ (j + 1)) + have h4 : 2 ^ 3 ^ (j + 1) / 3 ^ (j + 1) % 3 < 3 := Nat.mod_lt _ (by norm_num) + generalize 2 ^ 3 ^ (j + 1) / 3 ^ (j + 1) % 3 = a at this h4 + omega + · have hp3 : p (j + 2) = 2 * 3 ^ j + 2 * 3 ^ j + 2 * 3 ^ j := by rw [hp]; ring + rw [Finset.card_filter, hp3] + apply count_three + intro x + rw [hTd, hTd, hTd] + unfold dig + have e1 := shift j x + have e2 := shift j (x + 2 * 3 ^ j) + have e3 := mod_three_shift j x + have h3 := two_pow_mod_three x + rw [e2, e1, e3] + have h4 : 2 ^ x / 3 ^ (j + 1) % 3 < 3 := Nat.mod_lt _ (by norm_num) + generalize 2 ^ x / 3 ^ (j + 1) % 3 = a at h4 ⊢ + generalize 2 ^ x % 3 = s at h3 ⊢ + split_ifs <;> omega + +/-- Conjecture 1 of A265210 holds: column `k` has least period `2 * 3^(k-1)`, and for `k ≥ 2` +the digits `0, 1, 2` are equally frequent in every block of `2 * 3^(k-1)` consecutive entries. -/ +theorem result : statement := by + intro k hk + rcases Nat.lt_or_ge k 2 with hk2 | hk2 + · obtain rfl : k = 1 := by omega + exact ⟨col_one, fun h => absurd h (by norm_num)⟩ + · obtain ⟨j, rfl⟩ : ∃ j, k = j + 2 := ⟨k - 2, by omega⟩ + obtain ⟨h1, h2⟩ := col_ge_two j + refine ⟨h1, fun _ m _ d e hd he => ?_⟩ + rw [h2 m d hd, h2 m e he] + +end Math0.Frontier.A265210 + +#math0_settles Math0.Frontier.A265210.result Math0.Statements.A265210.statement diff --git a/lean/Math0/Frontier/OEIS/A265649.lean b/lean/Math0/Frontier/OEIS/A265649.lean new file mode 100644 index 0000000..4d4c376 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A265649.lean @@ -0,0 +1,350 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A265649 +import Math0.Audit + +/-! +# A265649: both closed forms of Werner Schulte hold + +We prove both conjectures of the entry for the triangle +`T(n,k) = T(n-1,k-1) + (2n-1+k)·T(n-1,k)`, `T(0,0) = 1`. + +**Method (factoring the triangle).** Suppose `A` and `D` are lower triangular arrays with +`A(n+1,i) = A(n,i-1) + α(n,i)·A(n,i)` and `D(i+1,k) = D(i,k-1) + β(i,k)·D(i,k)`, and +`α(n,i) + β(i,k) = γ(n,k)` does not depend on `i`. Then `S(n,k) = ∑_i A(n,i)·D(i,k)` satisfies +`S(n+1,k) = S(n,k-1) + γ(n,k)·S(n,k)`: expand `A(n+1,i)`, shift the index in the +`A(n,i-1)` part, and use the recurrence of `D`. So `S` agrees with any array obeying this +recurrence and the same row `0`. + +* *First form.* `A(n,i) = 2^(n-i)·n!·C(n,i)/i!` (`α = 2n+2+2i`) and + `D(i,k) = (-1/2)^(i-k)·(2i-k)!/((i-k)!·k!)` (`β = k-2i-1`). Then `γ = 2n+1+k`, as for `T`. + With `i = k+j` the summand `A(n,k+j)·D(k+j,k)` is exactly the `j`-th term of + `2^(n-k)·(n-k)!·C(n,k)·(-1/4)^j·C(2j+k,j)·C(n,j+k)`. +* *Second form.* `A = A001497` (Bessel, `α = 2N+1-j`) and `D(j,k) = (j+1)!·C(j+1,k)/k!` + (the unsigned Laguerre row `j+1`, `β = j+2+k`). Then `γ = 2N+3+k`, the recurrence of + `N ↦ T(N+1,k)`, and `(-1)^k·A021009(j+1,k) = D(j,k)`. + +Each recurrence of `A` and `D` is a one-line identity of factorials, or Pascal's rule together +with `C(n,i+1)·(i+1) = C(n,i)·(n-i)`. +-/ + +namespace Math0.Frontier.A265649 +open Math0.Statements.A265649 + +/-- Pushing one step of a two-term row recurrence of `A` across a sum `∑ A(n+1,i) X(i)`. -/ +private theorem shift_sum (A : ℕ → ℕ → ℚ) (α : ℕ → ℕ → ℚ) (n : ℕ) (X : ℕ → ℚ) + (hA0 : A (n+1) 0 = α n 0 * A n 0) + (hA : ∀ i, A (n+1) (i+1) = A n i + α n (i+1) * A n (i+1)) + (hz : A n (n+1) = 0) : + ∑ i ∈ Finset.range (n+2), A (n+1) i * X i = + ∑ i ∈ Finset.range (n+1), A n i * (X (i+1) + α n i * X i) := by + have h1 : ∑ i ∈ Finset.range (n+2), A (n+1) i * X i = + ∑ i ∈ Finset.range (n+1), A n i * X (i+1) + + ∑ i ∈ Finset.range (n+2), α n i * A n i * X i := by + rw [Finset.sum_range_succ' _ (n+1), Finset.sum_range_succ' (fun i => α n i * A n i * X i) (n+1)] + simp only [hA, hA0, add_mul, Finset.sum_add_distrib] + ring + rw [h1, Finset.sum_range_succ (fun i => α n i * A n i * X i), hz] + simp only [mul_zero, zero_mul, add_zero, mul_add, Finset.sum_add_distrib] + congr 1 + apply Finset.sum_congr rfl; intros; ring + +/-- If `A` and `D` satisfy two-term recurrences with coefficients `α(n,i)` and `β(i,k)` with +`α(n,i) + β(i,k) = γ(n,k)`, then `∑_i A(n,i) D(i,k)` satisfies the recurrence of `U` with +coefficient `γ`; so it equals `U` once the rows `n = 0` agree. -/ +private theorem matrix_induction (A D U α β γ : ℕ → ℕ → ℚ) + (hA0 : ∀ n, A (n+1) 0 = α n 0 * A n 0) + (hA : ∀ n i, A (n+1) (i+1) = A n i + α n (i+1) * A n (i+1)) + (hz : ∀ n, A n (n+1) = 0) + (hD0 : ∀ i, D (i+1) 0 = β i 0 * D i 0) + (hD : ∀ i k, D (i+1) (k+1) = D i k + β i (k+1) * D i (k+1)) + (hγ : ∀ n i k, α n i + β i k = γ n k) + (hU0 : ∀ n, U (n+1) 0 = γ n 0 * U n 0) + (hU : ∀ n k, U (n+1) (k+1) = U n k + γ n (k+1) * U n (k+1)) + (hbase : ∀ k, U 0 k = A 0 0 * D 0 k) : + ∀ n k, U n k = ∑ i ∈ Finset.range (n+1), A n i * D i k := by + intro n + induction n with + | zero => intro k; simp [hbase] + | succ n ih => + intro k + rw [shift_sum A α n _ (hA0 n) (hA n) (hz n)] + cases k with + | zero => + rw [hU0, ih 0, Finset.mul_sum] + apply Finset.sum_congr rfl; intro i _ + rw [hD0, ← hγ n i 0]; ring + | succ k => + rw [hU, ih k, ih (k+1), Finset.mul_sum, ← Finset.sum_add_distrib] + apply Finset.sum_congr rfl; intro i _ + rw [hD, ← hγ n i (k+1)]; ring + +/-- The unsigned Laguerre triangle `m!·C(m,k)/k!` (it vanishes for `k > m`). -/ +private def Lp (m k : ℕ) : ℚ := (m.factorial : ℚ) * (m.choose k : ℚ) / (k.factorial : ℚ) + +/-- `C(n,i+1)·(i+1) = C(n,i)·(n-i)` in `ℚ`, for all `n, i`. -/ +private theorem choose_rel (n i : ℕ) : + (n.choose (i+1) : ℚ) * (i+1) = n.choose i * ((n:ℚ) - i) := by + rcases Nat.lt_or_ge n i with h | h + · rw [Nat.choose_eq_zero_of_lt h, Nat.choose_eq_zero_of_lt (by omega)]; simp + · have := Nat.choose_succ_right_eq n i + rw [← Nat.cast_sub h] + exact_mod_cast this + +/-- Column `0` of `Lp`: `Lp(m+1,0) = (m+1)·Lp(m,0)`. -/ +private theorem Lp_succ_zero (m : ℕ) : Lp (m+1) 0 = (m+1) * Lp m 0 := by + simp [Lp, Nat.factorial_succ] + +/-- The Laguerre recurrence `Lp(m+1,k+1) = Lp(m,k) + (m+2+k)·Lp(m,k+1)`. -/ +private theorem Lp_succ_succ (m k : ℕ) : + Lp (m+1) (k+1) = Lp m k + (m + 2 + k) * Lp m (k+1) := by + have hr := choose_rel m k + simp only [Lp, Nat.choose_succ_succ', Nat.factorial_succ] + push_cast + field_simp + linear_combination -hr + +/-- `Lp(m,k) = 0` for `k > m`. -/ +private theorem Lp_eq_zero {m k : ℕ} (h : m < k) : Lp m k = 0 := by + simp [Lp, Nat.choose_eq_zero_of_lt h] + +/-! ### The first closed form -/ + +/-- The scaled Laguerre triangle `2^(n-i)·n!·C(n,i)/i!`. -/ +private def A₁ (n i : ℕ) : ℚ := (2:ℚ) ^ n / (2:ℚ) ^ i * Lp n i + +/-- The triangle `(-1/2)^(i-k)·(2i-k)!/((i-k)!·k!)` for `k ≤ i` (else `0`). -/ +private def D₁ (i k : ℕ) : ℚ := + if k ≤ i then (-1/2 : ℚ) ^ (i - k) * ((2 * i - k).factorial : ℚ) / + (((i - k).factorial : ℚ) * (k.factorial : ℚ)) else 0 + +/-- `A₁(n+1,0) = (2n+2)·A₁(n,0)`. -/ +private theorem A₁_succ_zero (n : ℕ) : + A₁ (n+1) 0 = (2 * (n:ℚ) + 2 + 2 * ((0:ℕ):ℚ)) * A₁ n 0 := by + simp only [A₁, Lp_succ_zero, pow_succ] + push_cast + ring + +/-- `A₁(n+1,i+1) = A₁(n,i) + (2n+2+2(i+1))·A₁(n,i+1)`. -/ +private theorem A₁_succ_succ (n i : ℕ) : + A₁ (n+1) (i+1) = A₁ n i + (2 * (n:ℚ) + 2 + 2 * ((i+1:ℕ):ℚ)) * A₁ n (i+1) := by + simp only [A₁, Lp_succ_succ, pow_succ] + push_cast + field_simp + ring + +/-- `A₁(n,n+1) = 0`. -/ +private theorem A₁_zero (n : ℕ) : A₁ n (n+1) = 0 := by + simp [A₁, Lp_eq_zero (Nat.lt_succ_self n)] + +/-- `D₁(i+1,0) = -(2i+1)·D₁(i,0)`. -/ +private theorem D₁_succ_zero (i : ℕ) : + D₁ (i+1) 0 = (((0:ℕ):ℚ) - 2 * (i:ℚ) - 1) * D₁ i 0 := by + unfold D₁ + rw [if_pos (Nat.zero_le _), if_pos (Nat.zero_le _)] + have e : 2 * (i+1) - 0 = (2*i+1)+1 := by omega + have e' : 2 * i - 0 = 2 * i := by omega + rw [e, e', Nat.sub_zero, Nat.sub_zero] + simp only [Nat.factorial_succ, Nat.factorial_zero] + push_cast + field_simp + ring + +/-- `D₁(i+1,k+1) = D₁(i,k) + ((k+1)-2i-1)·D₁(i,k+1)`. -/ +private theorem D₁_succ_succ (i k : ℕ) : + D₁ (i+1) (k+1) = D₁ i k + (((k+1:ℕ):ℚ) - 2 * (i:ℚ) - 1) * D₁ i (k+1) := by + rcases lt_trichotomy k i with h | rfl | h + · obtain ⟨m, rfl⟩ : ∃ m, i = k + m + 1 := ⟨i - k - 1, by omega⟩ + have h1 : k + 1 ≤ k + m + 1 + 1 := by omega + have h2 : k ≤ k + m + 1 := by omega + have h3 : k + 1 ≤ k + m + 1 := by omega + unfold D₁ + rw [if_pos h1, if_pos h2, if_pos h3] + have e1 : k + m + 1 + 1 - (k + 1) = m + 1 := by omega + have e2 : 2 * (k + m + 1 + 1) - (k + 1) = (2 * m + k + 1) + 1 + 1 := by omega + have e3 : k + m + 1 - k = m + 1 := by omega + have e4 : 2 * (k + m + 1) - k = (2 * m + k + 1) + 1 := by omega + have e5 : k + m + 1 - (k + 1) = m := by omega + have e6 : 2 * (k + m + 1) - (k + 1) = 2 * m + k + 1 := by omega + rw [e1, e2, e3, e4, e5, e6] + simp only [Nat.factorial_succ] + push_cast + field_simp + ring + · unfold D₁ + rw [if_pos (le_refl _), if_pos (le_refl _), if_neg (by omega : ¬ (k + 1 ≤ k))] + have e2 : 2 * (k + 1) - (k + 1) = k + 1 := by omega + have e4 : 2 * k - k = k := by omega + rw [e2, e4, Nat.sub_self, Nat.sub_self] + simp only [pow_zero, Nat.factorial_zero, Nat.cast_one, one_mul, mul_zero, add_zero] + rw [div_self (by positivity), div_self (by positivity)] + · unfold D₁ + rw [if_neg (by omega : ¬ (k + 1 ≤ i + 1)), if_neg (by omega : ¬ (k ≤ i)), + if_neg (by omega : ¬ (k + 1 ≤ i))] + ring + +/-- The defining recurrence of `T` in column `0`, cast to `ℚ`. -/ +private theorem T_cast_succ_zero (n : ℕ) : + (T (n+1) 0 : ℚ) = (2 * (n:ℚ) + 1 + ((0:ℕ):ℚ)) * T n 0 := by + have e : T (n+1) 0 = (2 * n + 1) * T n 0 := by + rw [T]; congr 1 + rw [e]; push_cast; ring + +/-- The defining recurrence of `T` in columns `k+1`, cast to `ℚ`. -/ +private theorem T_cast_succ_succ (n k : ℕ) : + (T (n+1) (k+1) : ℚ) = T n k + (2 * (n:ℚ) + 1 + ((k+1:ℕ):ℚ)) * T n (k+1) := by + have e : T (n+1) (k+1) = T n k + (2 * n + 1 + (k+1)) * T n (k+1) := by + rw [T_succ_succ]; congr 2 + rw [e]; push_cast; ring + +/-- `T = A₁ · D₁` as a product of lower triangular matrices. -/ +private theorem stmt1_sum (n k : ℕ) : + (T n k : ℚ) = ∑ i ∈ Finset.range (n+1), A₁ n i * D₁ i k := by + refine matrix_induction A₁ D₁ (fun n k => (T n k : ℚ)) + (fun n i => 2 * (n:ℚ) + 2 + 2 * (i:ℚ)) (fun i k => (k:ℚ) - 2 * (i:ℚ) - 1) + (fun n k => 2 * (n:ℚ) + 1 + (k:ℚ)) A₁_succ_zero A₁_succ_succ A₁_zero D₁_succ_zero + D₁_succ_succ (fun n i k => by ring) T_cast_succ_zero T_cast_succ_succ ?_ n k + intro k + cases k with + | zero => simp [A₁, D₁, Lp, T] + | succ k => simp [A₁, D₁, T] + +/-- The matrix product `A₁ · D₁` is the first closed form (reindex `i = k + j`). -/ +private theorem sum_eq_rhs₁ (n k : ℕ) (hk : k ≤ n) : + ∑ i ∈ Finset.range (n+1), A₁ n i * D₁ i k = + 2 ^ (n - k) * ((n - k).factorial : ℚ) * (n.choose k : ℚ) * + ∑ j ∈ Finset.range (n - k + 1), + (-1 / 4 : ℚ) ^ j * ((2 * j + k).choose j : ℚ) * (n.choose (j + k) : ℚ) := by + have e : n + 1 = k + (n - k + 1) := by omega + rw [e, Finset.sum_range_add, Finset.mul_sum] + have h0 : ∑ i ∈ Finset.range k, A₁ n i * D₁ i k = 0 := by + apply Finset.sum_eq_zero + intro i hi + have : ¬ k ≤ i := by simp at hi; omega + simp [D₁, this] + rw [h0, zero_add] + apply Finset.sum_congr rfl + intro j hj + have hj' : j ≤ n - k := by simp at hj; omega + obtain ⟨r, rfl⟩ : ∃ r, n = k + j + r := ⟨n - k - j, by omega⟩ + have hn : k + j + r - k = j + r := by omega + have hfac := Nat.choose_mul_factorial_mul_factorial hk + rw [hn] at hfac ⊢ + have hfacq : ((k + j + r).factorial : ℚ) = + ((k + j + r).choose k : ℚ) * (k.factorial : ℚ) * ((j + r).factorial : ℚ) := by + exact_mod_cast hfac.symm + have hc : ((2 * j + k).choose j : ℚ) = + ((2 * j + k).factorial : ℚ) / ((j.factorial : ℚ) * ((j + k).factorial : ℚ)) := by + have e : 2 * j + k - j = j + k := by omega + rw [Nat.cast_choose ℚ (by omega : j ≤ 2 * j + k), e] + have hD : D₁ (k + j) k = (-1/2 : ℚ) ^ j * ((2 * j + k).factorial : ℚ) / + ((j.factorial : ℚ) * (k.factorial : ℚ)) := by + unfold D₁ + rw [if_pos (by omega)] + have e1 : k + j - k = j := by omega + have e2 : 2 * (k + j) - k = 2 * j + k := by omega + rw [e1, e2] + have hpow : (-1/2 : ℚ) ^ j = 2 ^ j * (-1/4) ^ j := by + rw [← mul_pow]; norm_num + rw [hD, hc, hpow] + simp only [A₁, Lp] + rw [hfacq, add_comm j k, pow_add, pow_add, pow_add] + field_simp + + +/-! ### The second closed form -/ + +/-- `A001497(N+1,0) = (2N+1)·A001497(N,0)`. -/ +private theorem B_succ_zero (N : ℕ) : + A001497 (N+1) 0 = (2 * (N:ℚ) + 1 - ((0:ℕ):ℚ)) * A001497 N 0 := by + unfold A001497 + rw [if_pos (Nat.zero_le _), if_pos (Nat.zero_le _)] + have e1 : 2 * (N + 1) - 0 = (2 * N + 1) + 1 := by omega + have e2 : 2 * N - 0 = 2 * N := by omega + rw [e1, e2, Nat.sub_zero, Nat.sub_zero] + simp only [Nat.factorial_succ, Nat.factorial_zero, pow_succ] + push_cast + field_simp + ring + +/-- `A001497(N+1,j+1) = A001497(N,j) + (2N+1-(j+1))·A001497(N,j+1)`. -/ +private theorem B_succ_succ (N j : ℕ) : + A001497 (N+1) (j+1) = A001497 N j + (2 * (N:ℚ) + 1 - ((j+1:ℕ):ℚ)) * A001497 N (j+1) := by + rcases lt_trichotomy j N with h | rfl | h + · obtain ⟨m, rfl⟩ : ∃ m, N = j + m + 1 := ⟨N - j - 1, by omega⟩ + unfold A001497 + rw [if_pos (by omega), if_pos (by omega), if_pos (by omega)] + have e1 : 2 * (j + m + 1 + 1) - (j + 1) = (j + 2 * m + 1) + 1 + 1 := by omega + have e2 : j + m + 1 + 1 - (j + 1) = m + 1 := by omega + have e3 : 2 * (j + m + 1) - j = (j + 2 * m + 1) + 1 := by omega + have e4 : j + m + 1 - j = m + 1 := by omega + have e5 : 2 * (j + m + 1) - (j + 1) = j + 2 * m + 1 := by omega + have e6 : j + m + 1 - (j + 1) = m := by omega + rw [e1, e2, e3, e4, e5, e6] + simp only [Nat.factorial_succ, pow_succ] + push_cast + field_simp + ring + · unfold A001497 + rw [if_pos (le_refl _), if_pos (le_refl _), if_neg (by omega : ¬ (j + 1 ≤ j))] + have e1 : 2 * (j + 1) - (j + 1) = j + 1 := by omega + have e3 : 2 * j - j = j := by omega + rw [e1, e3, Nat.sub_self, Nat.sub_self] + simp only [pow_zero, Nat.factorial_zero, Nat.cast_one, mul_one, mul_zero, add_zero] + rw [div_self (by positivity), div_self (by positivity)] + · unfold A001497 + rw [if_neg (by omega : ¬ (j + 1 ≤ N + 1)), if_neg (by omega : ¬ (j ≤ N)), + if_neg (by omega : ¬ (j + 1 ≤ N))] + ring + +/-- `A001497(N,N+1) = 0`. -/ +private theorem B_zero (N : ℕ) : A001497 N (N+1) = 0 := by + unfold A001497 + rw [if_neg (by omega)] + +/-- `A021009(n,m) = (-1)^m·Lp(n,m)` for all `n, m`. -/ +private theorem A021009_eq (n m : ℕ) : A021009 n m = (-1) ^ m * Lp n m := by + unfold A021009 Lp + split_ifs with h + · ring + · rw [Nat.choose_eq_zero_of_lt (by omega)]; simp + +/-- `T(N+1,k) = ∑_j A001497(N,j)·Lp(j+1,k)`. -/ +private theorem stmt2_sum (N k : ℕ) : + (T (N+1) k : ℚ) = ∑ j ∈ Finset.range (N+1), A001497 N j * Lp (j+1) k := by + refine matrix_induction A001497 (fun j k => Lp (j+1) k) (fun N k => (T (N+1) k : ℚ)) + (fun N j => 2 * (N:ℚ) + 1 - (j:ℚ)) (fun j k => (j:ℚ) + 2 + (k:ℚ)) + (fun N k => 2 * (N:ℚ) + 3 + (k:ℚ)) B_succ_zero B_succ_succ B_zero ?_ ?_ + (fun N j k => by ring) ?_ ?_ ?_ N k + · intro j + rw [Lp_succ_zero (j+1)]; push_cast; ring + · intro j k + rw [Lp_succ_succ (j+1) k]; push_cast; ring + · intro N + rw [T_cast_succ_zero (N+1)]; push_cast; ring + · intro N k + rw [T_cast_succ_succ (N+1) k]; push_cast; ring + · intro k + match k with + | 0 => simp [A001497, Lp, T] + | 1 => simp [A001497, Lp, T] + | k + 2 => + rw [Lp_eq_zero (by omega)] + simp [T] + +/-- Both conjectures of Werner Schulte for A265649 hold. -/ +theorem result : statement := by + refine ⟨fun n k hk => ?_, fun n k hn hk => ?_⟩ + · rw [stmt1_sum n k, sum_eq_rhs₁ n k hk] + · obtain ⟨N, rfl⟩ : ∃ N, n = N + 1 := ⟨n - 1, by omega⟩ + rw [stmt2_sum N k, Nat.add_sub_cancel, Finset.mul_sum] + apply Finset.sum_congr rfl + intro j _ + rw [A021009_eq] + have h1 : ((-1 : ℚ) ^ k) * (-1) ^ k = 1 := by rw [← mul_pow]; norm_num + linear_combination (-(A001497 N j * Lp (j + 1) k)) * h1 + +end Math0.Frontier.A265649 + +#math0_settles Math0.Frontier.A265649.result Math0.Statements.A265649.statement diff --git a/lean/Math0/Frontier/OEIS/A267486.lean b/lean/Math0/Frontier/OEIS/A267486.lean new file mode 100644 index 0000000..d96a12e --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A267486.lean @@ -0,0 +1,348 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A267486 +import Math0.Audit + +/-! +# O'Sullivan's Gaussian-polynomial / Chebyshev representation (A267486) + +We prove the general conjecture stated in A267486: for all `m, n ≥ 0`, with +`N = n + ⌊m/2⌋` (so that `2n + m + 1 - (m mod 2) = 2N + 1`), the row polynomial +`G(m;n,x) = [t^m] (1+t) ∏_{k=1}^N (1 + t² + 2t T_k(x/2))` has degree at most `g(m;n)` and +`[2N+1, m]_q = ∑_{k ≤ g} [x^k]G(m;n,x) · (1+q²)^k q^(g-k)`. + +**Idea.** Substitute `x = q + q⁻¹` (the ring hom `φ : ℚ[x] → ℚ[q, q⁻¹]`). Then +`2 T_k(x/2) ↦ q^k + q^(-k)` (from the Chebyshev recursion), so each factor becomes +`(1 + q^k t)(1 + q^(-k) t)` and the whole product is `∏_{j=0}^{2N} (1 + q^(j-N) t)` +(`symProd`). The q-binomial theorem (`qbinom`, by induction from the q-Pascal rule that +defines `gaussBinom`) gives `[t^m] = q^(-Nm) q^(m(m-1)/2) [2N+1, m]_q`, i.e. +`φ(G) = q^(-g) [2N+1, m]_q` since `g = Nm - m(m-1)/2`. On the other side, for `deg P ≤ g`, +`∑_k [x^k]P (1+q²)^k q^(g-k) = q^g φ(P)` (`hom_eq`), and `Polynomial.toLaurent` is injective. + +The degree bound `deg G ≤ g` is proved separately by induction on `N` (`deg_F`): +`2 deg_x [t^m] F_N + m² ≤ m (2N+1)` for `m ≤ 2N+1`, where `F_N` is the product with `N` +Chebyshev factors and `deg 2T_k(x/2) ≤ k`. +-/ + +namespace Math0.Frontier.A267486 +open Math0.Statements.A267486 +open Polynomial +open scoped LaurentPolynomial + +/-- `2 T_0(x/2) = 2`. -/ +private theorem chebHalf_zero : 2 * chebHalf 0 = 2 := by + simp [chebHalf] + +/-- The Chebyshev recursion for `2 T_k(x/2)`: `a_{k+2} = x a_{k+1} - a_k`. -/ +private theorem chebHalf_add_two (k : ℕ) : + 2 * chebHalf (k + 2) = X * (2 * chebHalf (k + 1)) - 2 * chebHalf k := by + have h := Chebyshev.T_add_two ℚ (k : ℤ) + simp only [chebHalf] + push_cast + rw [h] + simp only [sub_comp, mul_comp, ofNat_comp, X_comp, Nat.cast_ofNat] + have hp : (2 : ℚ[X]) * (C (1 / 2 : ℚ) * X) = X := by + rw [← mul_assoc, ← C_ofNat, ← C_mul]; norm_num + linear_combination (2 * (Chebyshev.T ℚ ((k : ℤ) + 1)).comp (C (1 / 2 : ℚ) * X)) * hp + +/-- `deg 2 T_k(x/2) ≤ k` (stated for two consecutive indices, for the induction). -/ +private theorem natDegree_chebHalf (k : ℕ) : (2 * chebHalf k).natDegree ≤ k ∧ + (2 * chebHalf (k + 1)).natDegree ≤ k + 1 := by + induction k with + | zero => + refine ⟨?_, ?_⟩ + · rw [chebHalf_zero]; simp + · rw [two_chebHalf_one]; simp + | succ k ih => + refine ⟨ih.2, ?_⟩ + rw [chebHalf_add_two] + refine (natDegree_sub_le _ _).trans (max_le ?_ ?_) + · refine (natDegree_mul_le).trans ?_ + have := ih.2 + have h1 : (X : ℚ[X]).natDegree ≤ 1 := natDegree_X_le + omega + · have := ih.1; omega + +/-- The substitution `x ↦ q + q⁻¹`, as a ring hom `ℚ[x] → ℚ[q, q⁻¹]`. -/ +private noncomputable def φ : ℚ[X] →+* ℚ[T;T⁻¹] := + (aeval (LaurentPolynomial.T 1 + LaurentPolynomial.T (-1) : ℚ[T;T⁻¹])).toRingHom + +/-- `q · q⁻¹ = 1` in `ℚ[q, q⁻¹]`. -/ +private theorem T_mul_T : + (LaurentPolynomial.T 1 : ℚ[T;T⁻¹]) * LaurentPolynomial.T (-1) = 1 := by + rw [← LaurentPolynomial.T_add]; simp + +/-- `2 T_k((q + q⁻¹)/2) = q^k + q^(-k)`. -/ +private theorem φ_chebHalf (k : ℕ) : + φ (2 * chebHalf k) = LaurentPolynomial.T 1 ^ k + LaurentPolynomial.T (-1) ^ k ∧ + φ (2 * chebHalf (k + 1)) = + LaurentPolynomial.T 1 ^ (k + 1) + LaurentPolynomial.T (-1) ^ (k + 1) := by + induction k with + | zero => + refine ⟨?_, ?_⟩ + · rw [chebHalf_zero, map_ofNat]; norm_num + · rw [two_chebHalf_one]; simp [φ] + | succ k ih => + refine ⟨ih.2, ?_⟩ + rw [chebHalf_add_two, map_sub, map_mul, ih.1, ih.2] + have hX : φ X = LaurentPolynomial.T 1 + LaurentPolynomial.T (-1) := by simp [φ] + rw [hX] + linear_combination (LaurentPolynomial.T 1 ^ k + LaurentPolynomial.T (-1) ^ k) * T_mul_T + +/-- The q-binomial theorem: `[t^m] ∏_{j + intro m u + cases m with + | zero => simp [gaussBinom] + | succ m => simp [gaussBinom, coeff_one] + | succ M ih => + intro m u + rw [Finset.prod_range_succ'] + have hc : ∀ j ∈ Finset.range M, (1 + C (u * q ^ (j + 1)) * X : R[X]) = + 1 + C ((u * q) * q ^ j) * X := by + intro j _ + rw [show u * q ^ (j + 1) = (u * q) * q ^ j by ring] + rw [Finset.prod_congr rfl hc] + rw [pow_zero, mul_one, mul_add, mul_one, coeff_add, ← mul_assoc] + cases m with + | zero => + rw [coeff_mul_X_zero, add_zero, ih] + simp [gaussBinom] + | succ m => + rw [coeff_mul_X, coeff_mul_C, ih, ih] + simp only [gaussBinom, map_add, map_mul, map_pow, aeval_X] + rw [Nat.choose_succ_succ', Nat.choose_one_right] + ring + +/-- `(1+t) ∏_{k=1}^N (1 + t^2 + t (q^k + q^{-k})) = ∏_{j=0}^{2N} (1 + q^{j-N} t)`. -/ +private theorem symProd {R : Type*} [CommRing R] (q qi : R) (h : q * qi = 1) (N : ℕ) : + (1 + X) * ∏ k ∈ Finset.Icc 1 N, (1 + X ^ 2 + X * C (q ^ k + qi ^ k) : R[X]) = + ∏ j ∈ Finset.range (2 * N + 1), (1 + C (qi ^ N * q ^ j) * X) := by + induction N with + | zero => simp + | succ N ih => + rw [Finset.prod_Icc_succ_top (by omega), ← mul_assoc, ih, + show 2 * (N + 1) + 1 = 2 * N + 1 + 1 + 1 by ring, Finset.prod_range_succ _ (2 * N + 1 + 1), + Finset.prod_range_succ' _ (2 * N + 1)] + have hc : ∀ j ∈ Finset.range (2 * N + 1), (1 + C (qi ^ (N + 1) * q ^ (j + 1)) * X : R[X]) = + 1 + C (qi ^ N * q ^ j) * X := by + intro j _ + rw [show qi ^ (N + 1) * q ^ (j + 1) = qi ^ N * q ^ j by + linear_combination (qi ^ N * q ^ j) * h] + rw [Finset.prod_congr rfl hc, mul_assoc] + congr 1 + have h1 : qi ^ (N + 1) * q ^ (2 * N + 1 + 1) = q ^ (N + 1) := by + rw [show qi ^ (N + 1) * q ^ (2 * N + 1 + 1) = q ^ (N + 1) * (q * qi) ^ (N + 1) by ring, + h, one_pow, mul_one] + have h2 : (C (q ^ (N + 1)) * C (qi ^ (N + 1)) : R[X]) = 1 := by + rw [← map_mul, ← mul_pow, h, one_pow, map_one] + rw [h1, pow_zero, mul_one, map_add] + linear_combination (-X ^ 2 : R[X]) * h2 + +/-- `G(m;n,t,x)` with `N = n + ⌊m/2⌋` factors. -/ +private noncomputable def F (N : ℕ) : ℚ[X][X] := + (1 + X) * ∏ k ∈ Finset.Icc 1 N, (1 + X ^ 2 + 2 * X * C (chebHalf k)) + +/-- Adding the factor `k = N+1` to `F N`. -/ +private theorem F_succ (N : ℕ) : + F (N + 1) = F N * (1 + X ^ 2 + X * C (2 * chebHalf (N + 1))) := by + rw [F, F, Finset.prod_Icc_succ_top (by omega), mul_assoc, C_mul, C_ofNat] + ring + +/-- `F N` has `t`-degree at most `2N+1`. -/ +private theorem natDegree_F (N : ℕ) : (F N).natDegree ≤ 2 * N + 1 := by + induction N with + | zero => simp only [F, Finset.Icc_eq_empty_of_lt (show 0 < 1 by norm_num), + Finset.prod_empty, mul_one]; compute_degree! + | succ N ih => + rw [F_succ] + refine natDegree_mul_le.trans ?_ + have : (1 + X ^ 2 + X * C (2 * chebHalf (N + 1)) : ℚ[X][X]).natDegree ≤ 2 := by + compute_degree! + omega + +/-- The `t`-coefficients of `p · (1 + t² + t c)`. -/ +private theorem coeff_factor (p : ℚ[X][X]) (c : ℚ[X]) (m : ℕ) : + (p * (1 + X ^ 2 + X * C c)).coeff 0 = p.coeff 0 ∧ + (p * (1 + X ^ 2 + X * C c)).coeff 1 = p.coeff 1 + p.coeff 0 * c ∧ + (p * (1 + X ^ 2 + X * C c)).coeff (m + 2) = + p.coeff (m + 2) + p.coeff m + p.coeff (m + 1) * c := by + have e : p * (1 + X ^ 2 + X * C c) = p + p * X ^ 2 + p * C c * X := by ring + rw [e] + refine ⟨?_, ?_, ?_⟩ + · simp + · rw [coeff_add, coeff_add, coeff_mul_X, coeff_mul_C] + simp [coeff_mul_X_pow'] + · rw [coeff_add, coeff_add, coeff_mul_X, coeff_mul_C, coeff_mul_X_pow] + +/-- The `x`-degree bound `2 deg [t^m] F_N + m² ≤ m (2N+1)` for `m ≤ 2N+1`. -/ +private theorem deg_F (N : ℕ) : + ∀ m, m ≤ 2 * N + 1 → 2 * ((F N).coeff m).natDegree + m * m ≤ m * (2 * N + 1) := by + induction N with + | zero => + intro m hm + have hF : F 0 = 1 + X := by simp [F] + interval_cases m <;> simp [hF, coeff_one, coeff_X] + | succ N ih => + intro m hm + have hz : ∀ j, 2 * N + 1 < j → (F N).coeff j = 0 := fun j hj => + coeff_eq_zero_of_natDegree_lt ((natDegree_F N).trans_lt hj) + have ha := (natDegree_chebHalf (N + 1)).1 + rw [F_succ] + rcases m with _ | _ | m + · rw [(coeff_factor _ _ 0).1] + have := ih 0 (by omega) + omega + · rw [(coeff_factor _ _ 0).2.1] + have h1 := ih 1 (by omega) + have h0 := ih 0 (by omega) + have hd := (natDegree_add_le ((F N).coeff 1) ((F N).coeff 0 * (2 * chebHalf (N + 1)))).trans + (max_le_max le_rfl natDegree_mul_le) + have e1 : 1 * (2 * N + 1) = 2 * N + 1 := by ring + have e2 : 1 * (2 * (N + 1) + 1) = 2 * N + 3 := by ring + omega + · rw [(coeff_factor _ _ m).2.2] + have hB := ih m (by omega) + have hd := (natDegree_add_le _ _).trans (max_le_max (natDegree_add_le + ((F N).coeff (m + 2)) ((F N).coeff m)) (natDegree_mul_le (p := (F N).coeff (m + 1)) + (q := 2 * chebHalf (N + 1)))) + have hA : 2 * ((F N).coeff (m + 2)).natDegree + (m + 2) * (m + 2) ≤ (m + 2) * (2 * N + 1) + ∨ ((F N).coeff (m + 2)).natDegree = 0 := by + by_cases h : m + 2 ≤ 2 * N + 1 + · exact Or.inl (ih _ h) + · right; rw [hz _ (by omega)]; simp + have hC : 2 * ((F N).coeff (m + 1)).natDegree + (m + 1) * (m + 1) ≤ (m + 1) * (2 * N + 1) + ∨ m = 2 * N + 1 := by + by_cases h : m + 1 ≤ 2 * N + 1 + · exact Or.inl (ih _ h) + · right; omega + have e1 : (m + 2) * (m + 2) = m * m + 4 * m + 4 := by ring + have e2 : (m + 2) * (2 * (N + 1) + 1) = 2 * (m * N) + 3 * m + 4 * N + 6 := by ring + have e3 : m * (2 * N + 1) = 2 * (m * N) + m := by ring + have e4 : (m + 1) * (m + 1) = m * m + 2 * m + 1 := by ring + have e5 : (m + 1) * (2 * N + 1) = 2 * (m * N) + m + 2 * N + 1 := by ring + have e6 : (m + 2) * (2 * N + 1) = 2 * (m * N) + m + 4 * N + 2 := by ring + have e7 : (m + 1 + 1) * (m + 1 + 1) = m * m + 4 * m + 4 := by ring + have e8 : (m + 1 + 1) * (2 * (N + 1) + 1) = 2 * (m * N) + 3 * m + 4 * N + 6 := by ring + have hd' : ((F N).coeff (m + 2) + (F N).coeff m + (F N).coeff (m + 1) * + (2 * chebHalf (N + 1))).natDegree ≤ ((F N).coeff (m + 2)).natDegree ∨ + ((F N).coeff (m + 2) + (F N).coeff m + (F N).coeff (m + 1) * + (2 * chebHalf (N + 1))).natDegree ≤ ((F N).coeff m).natDegree ∨ + ((F N).coeff (m + 2) + (F N).coeff m + (F N).coeff (m + 1) * + (2 * chebHalf (N + 1))).natDegree ≤ ((F N).coeff (m + 1)).natDegree + + (2 * chebHalf (N + 1)).natDegree := by + rcases le_max_iff.mp hd with h | h + · rcases le_max_iff.mp h with h | h + · exact Or.inl h + · exact Or.inr (Or.inl h) + · exact Or.inr (Or.inr h) + rcases hC with hC | hC + · rcases hA with hA | hA <;> rcases hd' with hd' | hd' | hd' <;> omega + · subst hC + rw [hz (2 * N + 1 + 1) (by omega), zero_mul, add_zero] + have := (natDegree_add_le ((F N).coeff (2 * N + 1 + 2)) ((F N).coeff (2 * N + 1))) + omega + +/-- `toLaurent` of an integer polynomial is its evaluation at `q`. -/ +private theorem toLaurent_map_int (p : ℤ[X]) : + toLaurent (p.map (Int.castRingHom ℚ)) = aeval (LaurentPolynomial.T 1 : ℚ[T;T⁻¹]) p := by + have : (toLaurent : ℚ[X] →+* ℚ[T;T⁻¹]).comp (mapRingHom (Int.castRingHom ℚ)) = + (aeval (LaurentPolynomial.T 1 : ℚ[T;T⁻¹])).toRingHom := by + apply Polynomial.ringHom_ext + · intro a; simp + · simp + exact RingHom.congr_fun this p + +/-- For `deg P ≤ d`: `∑_{k ≤ d} [x^k]P (1+q²)^k q^(d-k) = q^d P(q + q⁻¹)`. -/ +private theorem hom_eq (P : ℚ[X]) (d : ℕ) (hP : P.natDegree ≤ d) : + toLaurent (∑ k ∈ Finset.range (d + 1), C (P.coeff k) * (1 + X ^ 2) ^ k * X ^ (d - k)) = + LaurentPolynomial.T 1 ^ d * φ P := by + have hφ : φ P = ∑ k ∈ Finset.range (d + 1), + P.coeff k • (LaurentPolynomial.T 1 + LaurentPolynomial.T (-1) : ℚ[T;T⁻¹]) ^ k := + aeval_eq_sum_range' (by omega) _ + rw [hφ, map_sum, Finset.mul_sum] + refine Finset.sum_congr rfl fun k hk => ?_ + have hk' : k ≤ d := by rw [Finset.mem_range] at hk; omega + obtain ⟨e, he⟩ := Nat.exists_eq_add_of_le hk' + rw [show d - k = e by omega, he] + simp only [map_mul, map_pow, map_add, map_one, toLaurent_C, toLaurent_X, Algebra.smul_def] + rw [← LaurentPolynomial.C_eq_algebraMap] + have h1 : (1 + LaurentPolynomial.T 1 ^ 2 : ℚ[T;T⁻¹]) = + LaurentPolynomial.T 1 * (LaurentPolynomial.T 1 + LaurentPolynomial.T (-1)) := by + linear_combination (-1 : ℚ[T;T⁻¹]) * T_mul_T + rw [h1, mul_pow] + ring + +/-- `G(m;n, q + q⁻¹) = q^(-Nm) q^(m choose 2) [2N+1, m]_q`. -/ +private theorem φ_G (m n : ℕ) : + φ (G m n) = (LaurentPolynomial.T (-1) ^ (n + (m - m % 2) / 2)) ^ m * + LaurentPolynomial.T 1 ^ (m.choose 2) * + aeval (LaurentPolynomial.T 1 : ℚ[T;T⁻¹]) + (gaussBinom (2 * (n + (m - m % 2) / 2) + 1) m) := by + have hGt : Gt m n = F (n + (m - m % 2) / 2) := rfl + rw [G_eq_coeff, hGt, ← coeff_map] + have hF : ∀ N, (F N).map φ = (1 + X) * ∏ k ∈ Finset.Icc 1 N, + (1 + X ^ 2 + X * C ((LaurentPolynomial.T 1 ^ k + LaurentPolynomial.T (-1) ^ k : + ℚ[T;T⁻¹]))) := by + intro N + have hfac : ∀ k, (1 + X ^ 2 + 2 * X * C (chebHalf k) : ℚ[X][X]) = + 1 + X ^ 2 + X * C (2 * chebHalf k) := fun k => by rw [C_mul, C_ofNat]; ring + unfold F + simp only [hfac] + rw [Polynomial.map_mul, Polynomial.map_prod] + simp only [Polynomial.map_add, Polynomial.map_one, Polynomial.map_X, Polynomial.map_mul, + Polynomial.map_pow, Polynomial.map_C, (φ_chebHalf _).1] + rw [hF, symProd _ _ T_mul_T, qbinom] + rfl + +/-- O'Sullivan's conjecture (A267486) holds. -/ +theorem result : statement := by + intro m n + set N := n + (m - m % 2) / 2 with hN + have hM : 2 * n + m + 1 - m % 2 = 2 * N + 1 := by omega + have hmN : m ≤ 2 * N + 1 := by omega + have hg : 2 * g m n + m * m = m * (2 * N + 1) := by + rcases Nat.even_or_odd' m with ⟨j, rfl | rfl⟩ + · have h1 : N = n + j := by omega + have h2 : g (2 * j) n = (2 * n + 1) * j := by + simp only [g, show 2 * j % 2 = 0 by omega] + simp only [zero_ne_one, if_false] + rw [show (2 * n + 1) * (2 * j) = 2 * ((2 * n + 1) * j) by ring, + Nat.mul_div_cancel_left _ (by norm_num)] + rw [h1, h2]; ring + · have h1 : N = n + j := by omega + have h2 : g (2 * j + 1) n = (2 * j + 1) * n := by + simp only [g, show (2 * j + 1) % 2 = 1 by omega, if_true] + rw [h1, h2]; ring + have hc : 2 * m.choose 2 + m = m * m := by + clear hg hmN hM hN + induction m with + | zero => rfl + | succ k ih => rw [Nat.choose_succ_succ', Nat.choose_one_right]; nlinarith + have hgc : g m n + m.choose 2 = N * m := by + have e : m * (2 * N + 1) = 2 * (N * m) + m := by ring + omega + have hdeg : (G m n).natDegree ≤ g m n := by + have hGt : Gt m n = F N := rfl + have := deg_F N m hmN + rw [G_eq_coeff, hGt] + omega + refine ⟨hdeg, ?_⟩ + rw [hM] + apply toLaurent_injective + rw [toLaurent_map_int, hom_eq _ _ hdeg, φ_G, ← hN] + have hTT : (LaurentPolynomial.T 1 : ℚ[T;T⁻¹]) ^ g m n * + ((LaurentPolynomial.T (-1)) ^ N) ^ m * LaurentPolynomial.T 1 ^ m.choose 2 = 1 := by + rw [← pow_mul, mul_right_comm, ← pow_add, hgc, mul_comm N m, ← mul_pow, mul_comm, + mul_comm (LaurentPolynomial.T (-1)), T_mul_T, one_pow] + rw [← mul_assoc, ← mul_assoc, hTT, one_mul] + +end Math0.Frontier.A267486 + +#math0_settles Math0.Frontier.A267486.result Math0.Statements.A267486.statement diff --git a/lean/Math0/Frontier/OEIS/A270668.lean b/lean/Math0/Frontier/OEIS/A270668.lean new file mode 100644 index 0000000..eed3965 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A270668.lean @@ -0,0 +1,593 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A270668 +import Math0.Audit + +/-! +# Mathar's generating function for column 3 of A270668 + +We prove Mathar's conjecture: `∑_{k ≥ 0} T(2k, 2) x^k = num / den`, where `T(2k, 2)` counts the +domino tilings of the `(4k+1) × 5` board with its central cell removed. + +The proof is a transfer-matrix argument on the 32 states (masks) of a width-5 row. + +* Using the broken-profile recursion for `cnt` from the statement file, the count from the start + of a row is obtained from the count at the start of the next row by a fixed row operator. There + are four kinds of rows: generic (`G0`), just above the hole (`G1`), the hole row (`G2`) and the + last row (`G3`). For `K ≥ 0` the `(4K+5) × 5` board is `G0^(2K+1) G1 G2 G0^(2K+1) G3` applied + to the all-ones vector, read at mask `0` (`vv_zero`). +* The row operators are linear and only use masks `< 32`, so they act through `32 × 32` integer + matrices (`rep`). With `A` the generic matrix, `P` the matrix of the two rows around the hole and + `e₀` the unit vector at mask `0`, the count is `e₀ᵀ A^(2K+1) P A^(2K+2) e₀`. `A` is symmetric + (kernel-checked), so the count is `∑ⱼ (A^(2K+1) e₀)ⱼ (P A^(2K+2) e₀)ⱼ` (`vv_formula`). +* A kernel computation shows `p(A²) e₀ = 0` for `p(t) = t⁴ - 15t³ + 32t² - 15t + 1`. Hence every + entry of `A^(2n+1) e₀` and of `P A^(2n+2) e₀` solves the order-4 recurrence `Rec4` with + characteristic polynomial `p`. +* If `a` and `b` solve `Rec4`, then `a · b` solves the order-9 recurrence `Rec9` whose + characteristic polynomial is the reversed denominator: its roots are `1` and the products + `ρᵢ ρⱼ` of roots of `p` (a polynomial identity, `rec9_mul`). So `T(2(K+1), 2)` solves `Rec9`. +* The coefficients of `x^n` in `(∑ T(2k, 2) x^k) · den` are the numerator coefficients for + `n ≤ 9`, using `T(2k, 2)` for `k ≤ 9` computed in the kernel. For `n ≥ 10` they are `0` by `Rec9`. +-/ + +namespace Math0.Frontier.A270668 +open Math0.Statements.A270668 +open Matrix + +/-- Vectors indexed by masks. -/ +private abbrev V := ℕ → ℤ + +/-- One cell step of the transfer matrix (width 5). -/ +private def cellF (s : ℕ) (a b d : Bool) (f : V) (M : ℕ) : ℤ := + if M.testBit s = true then f (M - 2 ^ s) + else if a = true then + (if s + 1 < 5 ∧ b = true ∧ M.testBit (s + 1) = false then f (M + 2 ^ (s + 1)) else 0) + + (if d = true then f (M + 2 ^ s) else 0) + else f M + +/-- One row of the transfer matrix. -/ +private def rowF (a b d : ℕ → Bool) (f : V) : V := + cellF 0 (a 0) (b 0) (d 0) (cellF 1 (a 1) (b 1) (d 1) (cellF 2 (a 2) (b 2) (d 2) + (cellF 3 (a 3) (b 3) (d 3) (cellF 4 (a 4) (b 4) (d 4) f)))) + +/-- Completion counts as an integer vector. -/ +private noncomputable def vv (N hx k : ℕ) : V := fun M => (cnt N 5 hx k M : ℤ) + +/-- One cell step of the broken-profile recursion for `cnt`, in the form of `cellF`. -/ +private theorem vv_cell (N hx k : ℕ) : + vv N hx k = cellF (k % 5) (inS N hx k) (inS N hx (k + 1)) (inS N hx (k + 5)) + (vv N hx (k + 1)) := by + funext M + unfold cellF + by_cases h1 : M.testBit (k % 5) = true + · rw [if_pos h1] + simp only [vv] + rw [cnt_of_set (by norm_num) h1] + · have h1' : M.testBit (k % 5) = false := by simpa using h1 + rw [if_neg h1] + by_cases h2 : inS N hx k = true + · rw [if_pos h2] + simp only [vv] + rw [cnt_of_free (c := 5) (by norm_num) h1' h2] + push_cast + rfl + · have h2' : inS N hx k = false := by simpa using h2 + rw [if_neg h2] + simp only [vv] + rw [cnt_of_notS (by norm_num) h1' h2'] + +/-- Five cell steps: the completion counts at the start of row `r` from those of row `r+1`. -/ +private theorem vv_row (N hx r : ℕ) : + vv N hx (5 * r) = rowF (fun j => inS N hx (5 * r + j)) (fun j => inS N hx (5 * r + j + 1)) + (fun j => inS N hx (5 * r + j + 5)) (vv N hx (5 * r + 5)) := by + rw [vv_cell N hx (5 * r), vv_cell N hx (5 * r + 1), vv_cell N hx (5 * r + 1 + 1), + vv_cell N hx (5 * r + 1 + 1 + 1), vv_cell N hx (5 * r + 1 + 1 + 1 + 1)] + rw [show (5 * r) % 5 = 0 by omega, show (5 * r + 1) % 5 = 1 by omega, + show (5 * r + 1 + 1) % 5 = 2 by omega, show (5 * r + 1 + 1 + 1) % 5 = 3 by omega, + show (5 * r + 1 + 1 + 1 + 1) % 5 = 4 by omega] + rfl + +/-- `rowF` only depends on the flags at the five columns `0, …, 4`. -/ +private theorem rowF_congr {a b d a' b' d' : ℕ → Bool} (ha : ∀ j < 5, a j = a' j) + (hb : ∀ j < 5, b j = b' j) (hd : ∀ j < 5, d j = d' j) (f : V) : + rowF a b d f = rowF a' b' d' f := by + simp only [rowF] + rw [ha 0 (by norm_num), ha 1 (by norm_num), ha 2 (by norm_num), ha 3 (by norm_num), + ha 4 (by norm_num), hb 0 (by norm_num), hb 1 (by norm_num), hb 2 (by norm_num), + hb 3 (by norm_num), hb 4 (by norm_num), hd 0 (by norm_num), hd 1 (by norm_num), + hd 2 (by norm_num), hd 3 (by norm_num), hd 4 (by norm_num)] + +/-- A generic row. -/ +private def G0 (f : V) : V := rowF (fun _ => true) (fun _ => true) (fun _ => true) f +/-- The row just above the hole. -/ +private def G1 (f : V) : V := rowF (fun _ => true) (fun _ => true) (fun j => decide (j ≠ 2)) f +/-- The row of the hole. -/ +private def G2 (f : V) : V := + rowF (fun j => decide (j ≠ 2)) (fun j => decide (j ≠ 1)) (fun _ => true) f +/-- The last row. -/ +private def G3 (f : V) : V := rowF (fun _ => true) (fun j => decide (j ≠ 4)) (fun _ => false) f + +section Rows +variable (K : ℕ) + +/-- A row away from the hole and from the bottom is the generic row `G0`. -/ +private theorem row_gen {r : ℕ} (h1 : r + 1 < 4 * K + 5) (h2 : r ≠ 2 * K + 2) + (h3 : r + 1 ≠ 2 * K + 2) : + vv (20 * K + 25) (10 * K + 12) (5 * r) = G0 (vv (20 * K + 25) (10 * K + 12) (5 * r + 5)) := by + rw [vv_row, G0] + apply rowF_congr <;> intro j hj <;> interval_cases j <;> simp [inS] <;> omega + +/-- The row just above the hole: no vertical domino into the hole. -/ +private theorem row_above : + vv (20 * K + 25) (10 * K + 12) (5 * (2 * K + 1)) = + G1 (vv (20 * K + 25) (10 * K + 12) (5 * (2 * K + 2))) := by + rw [vv_row, G1, show 5 * (2 * K + 1) + 5 = 5 * (2 * K + 2) by ring] + apply rowF_congr <;> intro j hj <;> interval_cases j <;> simp [inS] <;> omega + +/-- The row of the hole. -/ +private theorem row_hole : + vv (20 * K + 25) (10 * K + 12) (5 * (2 * K + 2)) = + G2 (vv (20 * K + 25) (10 * K + 12) (5 * (2 * K + 3))) := by + rw [vv_row, G2, show 5 * (2 * K + 2) + 5 = 5 * (2 * K + 3) by ring] + apply rowF_congr <;> intro j hj <;> interval_cases j <;> simp [inS] <;> omega + +/-- The last row: no vertical dominoes, and every final state completes in one way. -/ +private theorem row_last : + vv (20 * K + 25) (10 * K + 12) (5 * (4 * K + 4)) = G3 (fun _ => 1) := by + rw [vv_row, G3] + have : vv (20 * K + 25) (10 * K + 12) (5 * (4 * K + 4) + 5) = fun _ => 1 := by + funext M + simp only [vv] + rw [cnt_end (by omega)] + rfl + rw [this] + apply rowF_congr <;> intro j hj <;> interval_cases j <;> simp [inS] <;> omega + +/-- A stretch of `t` generic rows is `G0^[t]`. -/ +private theorem rows_gen : ∀ t s : ℕ, (∀ r, s ≤ r → r < s + t → + r + 1 < 4 * K + 5 ∧ r ≠ 2 * K + 2 ∧ r + 1 ≠ 2 * K + 2) → + vv (20 * K + 25) (10 * K + 12) (5 * s) = G0^[t] (vv (20 * K + 25) (10 * K + 12) (5 * (s + t))) + | 0, s, _ => by simp + | t + 1, s, h => by + obtain ⟨h1, h2, h3⟩ := h s le_rfl (by omega) + rw [row_gen K h1 h2 h3, show 5 * s + 5 = 5 * (s + 1) by ring, + rows_gen t (s + 1) (fun r hr1 hr2 => h r (by omega) (by omega)), + Function.iterate_succ_apply', show s + 1 + t = s + (t + 1) by ring] + +/-- The whole board, row by row. -/ +private theorem vv_zero : + vv (20 * K + 25) (10 * K + 12) 0 = + G0^[2 * K + 1] (G1 (G2 (G0^[2 * K + 1] (G3 (fun _ => 1))))) := by + have e1 := rows_gen K (2 * K + 1) 0 (fun r _ hr => by omega) + have e2 := rows_gen K (2 * K + 1) (2 * K + 3) (fun r hr1 hr2 => by omega) + rw [show 5 * 0 = 0 by rfl, show 0 + (2 * K + 1) = 2 * K + 1 by ring] at e1 + rw [show 2 * K + 3 + (2 * K + 1) = 4 * K + 4 by ring] at e2 + rw [e1, row_above, row_hole, e2, row_last] + +end Rows + +/-! ### Linearity and locality -/ + +/-- `F` only looks at masks `< 32` when evaluated at masks `< 32`. -/ +private def Loc (F : V → V) : Prop := + ∀ f g : V, (∀ M < 32, f M = g M) → ∀ M < 32, F f M = F g M + +/-- `cellF` is local (for the columns `s < 5`). -/ +private theorem cellF_loc {s : ℕ} (hs : s < 5) (a b d : Bool) : Loc (cellF s a b d) := by + intro f g hfg M hM + have hM' : M < 2 ^ 5 := hM + unfold cellF + by_cases h1 : M.testBit s = true + · rw [if_pos h1, if_pos h1] + exact hfg _ (lt_of_le_of_lt (Nat.sub_le _ _) hM) + · have h1' : M.testBit s = false := by simpa using h1 + rw [if_neg h1, if_neg h1] + split_ifs with h2 h3 h4 + · rw [hfg _ (add_two_pow_lt hM' h3.1 h3.2.2), hfg _ (add_two_pow_lt hM' hs h1')] + · rw [hfg _ (add_two_pow_lt hM' h3.1 h3.2.2)] + · rw [hfg _ (add_two_pow_lt hM' hs h1')] + · rfl + · exact hfg _ hM + +/-- `rowF` is local. -/ +private theorem rowF_loc (a b d : ℕ → Bool) : Loc (rowF a b d) := by + intro f g hfg + simp only [rowF] + exact cellF_loc (by norm_num) _ _ _ _ _ <| cellF_loc (by norm_num) _ _ _ _ _ <| + cellF_loc (by norm_num) _ _ _ _ _ <| cellF_loc (by norm_num) _ _ _ _ _ <| + cellF_loc (by norm_num) _ _ _ _ _ hfg + +/-- `cellF` as a linear map. -/ +private def cellL (s : ℕ) (a b d : Bool) : V →ₗ[ℤ] V where + toFun := cellF s a b d + map_add' f g := by + funext M + simp only [cellF, Pi.add_apply] + split_ifs <;> ring + map_smul' c f := by + funext M + simp only [cellF, Pi.smul_apply, smul_eq_mul, RingHom.id_apply] + split_ifs <;> ring + +/-- `rowF` as a linear map. -/ +private def rowL (a b d : ℕ → Bool) : V →ₗ[ℤ] V := + cellL 0 (a 0) (b 0) (d 0) ∘ₗ cellL 1 (a 1) (b 1) (d 1) ∘ₗ cellL 2 (a 2) (b 2) (d 2) ∘ₗ + cellL 3 (a 3) (b 3) (d 3) ∘ₗ cellL 4 (a 4) (b 4) (d 4) + +/-- `rowL` computes `rowF`. -/ +private theorem rowL_apply (a b d : ℕ → Bool) (f : V) : rowL a b d f = rowF a b d f := rfl + +/-- The unit vector at mask `j`. -/ +private def δn (j : ℕ) : V := fun x => if x = j then 1 else 0 + +/-- Restriction to the masks `< 32`. -/ +private def rest (f : V) : Fin 32 → ℤ := fun i => f i + +/-- The matrix of a linear map on the masks `< 32`. -/ +private def toMat (F : V →ₗ[ℤ] V) : Matrix (Fin 32) (Fin 32) ℤ := + Matrix.of fun i j => F (δn j) i + +/-- A local linear map acts on the masks `< 32` through its matrix. -/ +private theorem rep (F : V →ₗ[ℤ] V) (hF : Loc F) (f : V) : rest (F f) = toMat F *ᵥ rest f := by + funext i + have hf : ∀ M < 32, f M = (∑ j : Fin 32, f j • δn j) M := by + intro M hM + rw [Finset.sum_apply, Finset.sum_eq_single ⟨M, hM⟩] + · simp [δn] + · intro j _ hj + have : M ≠ (j : ℕ) := fun h => hj (Fin.ext h.symm) + simp [δn, this] + · simp + simp only [rest, Matrix.mulVec, dotProduct, toMat, Matrix.of_apply] + rw [hF f _ hf i i.2, map_sum, Finset.sum_apply] + refine Finset.sum_congr rfl fun j _ => ?_ + rw [map_smul, Pi.smul_apply, smul_eq_mul, mul_comm] + +/-! ### Kernel computations -/ + +/-- The last row applied to the all-ones vector is the generic row applied to `δ₀` +(kernel-checked on the 32 masks). -/ +private theorem last_row_eq : ∀ M < 32, G3 (fun _ => 1) M = G0 (δn 0) M := by decide +kernel + +/-- The generic row transfer matrix is symmetric (kernel-checked). -/ +private theorem G0_symm : ∀ i < 32, ∀ j < 32, G0 (δn j) i = G0 (δn i) j := by decide +kernel + +/-- Table lookup. -/ +private def tab (l : List ℤ) : V := fun M => l.getD M 0 + +/-- Materialize the first 32 entries of a vector. -/ +private def matz (g : V) : List ℤ := (List.range 32).map g + +/-- Reading back a materialized vector. -/ +private theorem tab_matz (g : V) {M : ℕ} (hM : M < 32) : tab (matz g) M = g M := by + simp [tab, matz, hM] + +/-- Materialized iterates `G0^n δ₀`. -/ +private def itG : ℕ → List ℤ + | 0 => matz (δn 0) + | n + 1 => matz (G0 (tab (itG n))) + +/-- `itG n` is `G0^[n] δ₀` on the masks `< 32`. -/ +private theorem itG_spec : ∀ n, ∀ M < 32, tab (itG n) M = G0^[n] (δn 0) M + | 0, M, hM => by rw [itG, tab_matz _ hM]; rfl + | n + 1, M, hM => by + rw [itG, tab_matz _ hM, Function.iterate_succ_apply'] + exact rowF_loc _ _ _ _ _ (itG_spec n) M hM + +/-- `δ₀` is annihilated by `p(G0²)` with `p(t) = t⁴ - 15t³ + 32t² - 15t + 1` +(kernel-checked on the 32 masks). -/ +private theorem krylov_check : ∀ M < 32, tab (itG 8) M - 15 * tab (itG 6) M + 32 * tab (itG 4) M - + 15 * tab (itG 2) M + tab (itG 0) M = 0 := by decide +kernel + +/-! ### Matrices -/ + +/-- The generic row as a linear map. -/ +private def G0L : V →ₗ[ℤ] V := rowL (fun _ => true) (fun _ => true) (fun _ => true) +/-- The row above the hole as a linear map. -/ +private def G1L : V →ₗ[ℤ] V := rowL (fun _ => true) (fun _ => true) (fun j => decide (j ≠ 2)) +/-- The hole row as a linear map. -/ +private def G2L : V →ₗ[ℤ] V := + rowL (fun j => decide (j ≠ 2)) (fun j => decide (j ≠ 1)) (fun _ => true) + +/-- The generic row transfer matrix. -/ +private def A : Matrix (Fin 32) (Fin 32) ℤ := toMat G0L +/-- The two rows around the hole. -/ +private def P : Matrix (Fin 32) (Fin 32) ℤ := toMat G1L * toMat G2L + +/-- The unit vector at mask `0`. -/ +private def e0 : Fin 32 → ℤ := rest (δn 0) + +/-- `A ^ n e₀`. -/ +private def x (n : ℕ) : Fin 32 → ℤ := A ^ n *ᵥ e0 + +/-- Locality of the generic row. -/ +private theorem G0L_loc : Loc G0L := rowF_loc (fun _ => true) (fun _ => true) (fun _ => true) +/-- Locality of the row above the hole. -/ +private theorem G1L_loc : Loc G1L := + rowF_loc (fun _ => true) (fun _ => true) (fun j => decide (j ≠ 2)) +/-- Locality of the hole row. -/ +private theorem G2L_loc : Loc G2L := + rowF_loc (fun j => decide (j ≠ 2)) (fun j => decide (j ≠ 1)) (fun _ => true) + +/-- The generic row acts by `A`. -/ +private theorem rest_G0 (f : V) : rest (G0 f) = A *ᵥ rest f := rep G0L G0L_loc f + +/-- `n` generic rows act by `A ^ n`. -/ +private theorem rest_G0_iter (n : ℕ) (f : V) : rest (G0^[n] f) = A ^ n *ᵥ rest f := by + induction n with + | zero => simp + | succ n ih => rw [Function.iterate_succ_apply', rest_G0, ih, mulVec_mulVec, pow_succ'] + +/-- The two rows around the hole act by `P`. -/ +private theorem rest_G12 (f : V) : rest (G1 (G2 f)) = P *ᵥ rest f := by + rw [P, ← mulVec_mulVec] + exact (rep G1L G1L_loc (G2 f)).trans (congrArg _ (rep G2L G2L_loc f)) + +/-- `A` is symmetric. -/ +private theorem A_symm : Aᵀ = A := by + ext i j + simp only [transpose_apply, A, toMat, of_apply, G0L, rowL_apply] + exact (G0_symm i i.2 j j.2).symm + +/-- `x n` is the column `0` of `A ^ n`. -/ +private theorem x_apply (n : ℕ) (j : Fin 32) : x n j = (A ^ n) j 0 := by + simp only [x, mulVec, dotProduct, e0, rest, δn] + rw [Finset.sum_eq_single 0] + · simp + · intro k _ hk + have : (k : ℕ) ≠ 0 := fun h => hk (Fin.ext h) + simp [this] + · simp + +/-- `x n` agrees with the materialized iterate. -/ +private theorem x_eq_tab (n : ℕ) (j : Fin 32) : x n j = tab (itG n) j := by + rw [itG_spec n j j.2, x, e0, ← rest_G0_iter] + rfl + +/-- The Krylov relation `p(A²) e₀ = 0`. -/ +private theorem x_base : x 8 = (15 : ℤ) • x 6 - (32 : ℤ) • x 4 + (15 : ℤ) • x 2 - x 0 := by + funext j + have := krylov_check j j.2 + simp only [Pi.sub_apply, Pi.add_apply, Pi.smul_apply, smul_eq_mul, x_eq_tab] + linarith + +/-- `x (m + k) = A ^ m x k`. -/ +private theorem x_add (m k : ℕ) : x (m + k) = A ^ m *ᵥ x k := by + rw [x, x, mulVec_mulVec, pow_add] + +/-- The vectors `x n` satisfy the recurrence `p` in steps of two. -/ +private theorem x_rec (m : ℕ) : + x (m + 8) = (15 : ℤ) • x (m + 6) - (32 : ℤ) • x (m + 4) + (15 : ℤ) • x (m + 2) - x m := by + rw [x_add, x_base, x_add, x_add, x_add, ← add_zero m, x_add m 0, add_zero] + simp only [mulVec_sub, mulVec_add, mulVec_smul] + +/-- The tiling count of the `(4K+5) × 5` board with central hole as a bilinear expression. -/ +private theorem vv_formula (K : ℕ) : + vv (20 * K + 25) (10 * K + 12) 0 0 = + ∑ j : Fin 32, x (2 * K + 1) j * (P *ᵥ x (2 * K + 2)) j := by + have h3 : rest (G3 (fun _ => 1)) = A *ᵥ e0 := by + rw [e0, ← rest_G0] + funext i + exact last_row_eq i i.2 + have h := congrArg (fun f => rest f (0 : Fin 32)) (vv_zero K) + have hx : A ^ (2 * K + 1) *ᵥ (A *ᵥ e0) = x (2 * K + 2) := by + rw [x, mulVec_mulVec, ← pow_succ] + rw [rest_G0_iter, rest_G12, rest_G0_iter, h3, hx] at h + rw [show vv (20 * K + 25) (10 * K + 12) 0 0 = rest (vv (20 * K + 25) (10 * K + 12) 0) 0 from rfl, + h] + simp only [mulVec, dotProduct] + refine Finset.sum_congr rfl fun j _ => ?_ + congr 1 + rw [x_apply, ← transpose_apply (A ^ (2 * K + 1)), transpose_pow, A_symm] + +/-! ### Linear recurrences -/ + +/-- The order-4 recurrence `s(n+4) = 15 s(n+3) - 32 s(n+2) + 15 s(n+1) - s(n)`. -/ +private def Rec4 (s : ℕ → ℤ) : Prop := + ∀ n, s (n + 4) = 15 * s (n + 3) - 32 * s (n + 2) + 15 * s (n + 1) - s n + +/-- The order-9 recurrence given by the denominator. -/ +private def Rec9 (s : ℕ → ℤ) : Prop := + ∀ n, s n - 192 * s (n + 1) + 5760 * s (n + 2) - 49283 * s (n + 3) + 147264 * s (n + 4) - + 147264 * s (n + 5) + 49283 * s (n + 6) - 5760 * s (n + 7) + 192 * s (n + 8) - s (n + 9) = 0 + +/-- The product of two solutions of `Rec4` solves `Rec9`. -/ +private theorem rec9_mul {a b : ℕ → ℤ} (ha : Rec4 a) (hb : Rec4 b) : + Rec9 (fun n => a n * b n) := by + intro n + have h0 := ha n + have h1 := ha (n + 1) + have h2 := ha (n + 2) + have h3 := ha (n + 3) + have h4 := ha (n + 4) + have h5 := ha (n + 5) + have g0 := hb n + have g1 := hb (n + 1) + have g2 := hb (n + 2) + have g3 := hb (n + 3) + have g4 := hb (n + 4) + have g5 := hb (n + 5) + simp only [Nat.add_assoc, Nat.reduceAdd] at h1 h2 h3 h4 h5 g1 g2 g3 g4 g5 + have a4 : a (n + 4) = + -a n + 15 * a (n + 1) - 32 * a (n + 2) + 15 * a (n + 3) := by + linear_combination h0 + have a5 : a (n + 5) = + -15 * a n + 224 * a (n + 1) - 465 * a (n + 2) + 193 * a (n + 3) := by + linear_combination h1 + 15 * a4 + have a6 : a (n + 6) = + -193 * a n + 2880 * a (n + 1) - 5952 * a (n + 2) + 2430 * a (n + 3) := by + linear_combination h2 + 15 * a5 - 32 * a4 + have a7 : a (n + 7) = + -2430 * a n + 36257 * a (n + 1) - 74880 * a (n + 2) + 30498 * a (n + 3) := by + linear_combination h3 + 15 * a6 - 32 * a5 + 15 * a4 + have a8 : a (n + 8) = + -30498 * a n + 455040 * a (n + 1) - 939679 * a (n + 2) + 382590 * a (n + 3) := by + linear_combination h4 + 15 * a7 - 32 * a6 + 15 * a5 - a4 + have a9 : a (n + 9) = + -382590 * a n + 5708352 * a (n + 1) - 11787840 * a (n + 2) + 4799171 * a (n + 3) := by + linear_combination h5 + 15 * a8 - 32 * a7 + 15 * a6 - a5 + have b4 : b (n + 4) = + -b n + 15 * b (n + 1) - 32 * b (n + 2) + 15 * b (n + 3) := by + linear_combination g0 + have b5 : b (n + 5) = + -15 * b n + 224 * b (n + 1) - 465 * b (n + 2) + 193 * b (n + 3) := by + linear_combination g1 + 15 * b4 + have b6 : b (n + 6) = + -193 * b n + 2880 * b (n + 1) - 5952 * b (n + 2) + 2430 * b (n + 3) := by + linear_combination g2 + 15 * b5 - 32 * b4 + have b7 : b (n + 7) = + -2430 * b n + 36257 * b (n + 1) - 74880 * b (n + 2) + 30498 * b (n + 3) := by + linear_combination g3 + 15 * b6 - 32 * b5 + 15 * b4 + have b8 : b (n + 8) = + -30498 * b n + 455040 * b (n + 1) - 939679 * b (n + 2) + 382590 * b (n + 3) := by + linear_combination g4 + 15 * b7 - 32 * b6 + 15 * b5 - b4 + have b9 : b (n + 9) = + -382590 * b n + 5708352 * b (n + 1) - 11787840 * b (n + 2) + 4799171 * b (n + 3) := by + linear_combination g5 + 15 * b8 - 32 * b7 + 15 * b6 - b5 + dsimp only + rw [a4, a5, a6, a7, a8, a9, b4, b5, b6, b7, b8, b9] + ring + +/-- `Rec9` is closed under finite sums. -/ +private theorem rec9_sum (S : Finset (Fin 32)) (f : Fin 32 → ℕ → ℤ) (h : ∀ i ∈ S, Rec9 (f i)) : + Rec9 (fun n => ∑ i ∈ S, f i n) := by + induction S using Finset.induction_on with + | empty => intro n; simp + | insert i S hi ih => + have h1 := h i (Finset.mem_insert_self i S) + have h2 := ih (fun j hj => h j (Finset.mem_insert_of_mem hj)) + intro n + have h1n := h1 n + have h2n := h2 n + dsimp only at h1n h2n ⊢ + simp only [Finset.sum_insert hi] + linear_combination h1n + h2n + +/-- The entries of `A^(2n+1) e₀` solve `Rec4`. -/ +private theorem rec4_x_odd (j : Fin 32) : Rec4 (fun n => x (2 * n + 1) j) := by + intro n + dsimp only + rw [show 2 * (n + 4) + 1 = 2 * n + 1 + 8 by ring, x_rec, + show 2 * (n + 3) + 1 = 2 * n + 1 + 6 by ring, + show 2 * (n + 2) + 1 = 2 * n + 1 + 4 by ring, show 2 * (n + 1) + 1 = 2 * n + 1 + 2 by ring] + simp only [Pi.sub_apply, Pi.add_apply, Pi.smul_apply, smul_eq_mul] + +/-- The entries of `P A^(2n+2) e₀` solve `Rec4`. -/ +private theorem rec4_Px_even (j : Fin 32) : Rec4 (fun n => (P *ᵥ x (2 * n + 2)) j) := by + intro n + dsimp only + rw [show 2 * (n + 4) + 2 = 2 * n + 2 + 8 by ring, x_rec, + show 2 * (n + 3) + 2 = 2 * n + 2 + 6 by ring, + show 2 * (n + 2) + 2 = 2 * n + 2 + 4 by ring, show 2 * (n + 1) + 2 = 2 * n + 2 + 2 by ring] + simp only [mulVec_sub, mulVec_add, mulVec_smul, Pi.sub_apply, Pi.add_apply, Pi.smul_apply, + smul_eq_mul] + +/-- `T(2(K+1), 2)` is the completion count of the initial state. -/ +private theorem T_eq_vv (K : ℕ) : (T (2 * (K + 1)) 2 : ℤ) = vv (20 * K + 25) (10 * K + 12) 0 0 := by + have h : T (2 * (K + 1)) 2 = cnt ((2 * (2 * (K + 1)) + 1) * (2 * 2 + 1)) (2 * 2 + 1) + (2 * (K + 1) * (2 * 2 + 1) + 2) 0 0 := by + rw [T, region_eq] + rfl + rw [h, show (2 * (2 * (K + 1)) + 1) * (2 * 2 + 1) = 20 * K + 25 by ring, + show 2 * (K + 1) * (2 * 2 + 1) + 2 = 10 * K + 12 by ring] + rfl + +/-- The column `T(2(K+1), 2)` solves `Rec9`. -/ +private theorem rec9_T : Rec9 (fun K => (T (2 * (K + 1)) 2 : ℤ)) := by + have : (fun K => (T (2 * (K + 1)) 2 : ℤ)) = + fun K => ∑ j : Fin 32, x (2 * K + 1) j * (P *ᵥ x (2 * K + 2)) j := by + funext K + rw [T_eq_vv, vv_formula] + rw [this] + exact rec9_sum _ _ fun j _ => rec9_mul (rec4_x_odd j) (rec4_Px_even j) + +/-! ### Initial values -/ + +/-- `T(0, 2)`, kernel-checked. -/ +private theorem Tc_val0 : Tc 0 2 = 1 := by decide +kernel +/-- `T(2, 2)`, kernel-checked. -/ +private theorem Tc_val1 : Tc 2 2 = 196 := by decide +kernel +/-- `T(4, 2)`, kernel-checked. -/ +private theorem Tc_val2 : Tc 4 2 = 31329 := by decide +kernel +/-- `T(6, 2)`, kernel-checked. -/ +private theorem Tc_val3 : Tc 6 2 = 4941729 := by decide +kernel +/-- `T(8, 2)`, kernel-checked. -/ +private theorem Tc_val4 : Tc 8 2 = 777852100 := by decide +kernel +/-- `T(10, 2)`, kernel-checked. -/ +private theorem Tc_val5 : Tc 10 2 = 122398521025 := by decide +kernel +/-- `T(12, 2)`, kernel-checked. -/ +private theorem Tc_val6 : Tc 12 2 = 19259046351169 := by decide +kernel +/-- `T(14, 2)`, kernel-checked. -/ +private theorem Tc_val7 : Tc 14 2 = 3030333168565444 := by decide +kernel +/-- `T(16, 2)`, kernel-checked. -/ +private theorem Tc_val8 : Tc 16 2 = 476810204277773601 := by decide +kernel +/-- `T(18, 2)`, kernel-checked. -/ +private theorem Tc_val9 : Tc 18 2 = 75024073162168851681 := by decide +kernel + +/-! ### The generating function -/ + +open PowerSeries + +/-- Coefficients of the denominator. -/ +private def dd (j : ℕ) : ℚ := + [-1, 192, -5760, 49283, -147264, 147264, -49283, 5760, -192, 1].getD j 0 + +/-- Coefficients of the numerator. -/ +private def nm (j : ℕ) : ℚ := [-1, -4, 543, -6238, 17032, -6238, 543, -4, -1].getD j 0 + +/-- The denominator as a sum of monomials. -/ +private theorem den_eq : den = ∑ j ∈ Finset.range 10, C (dd j) * X ^ j := by + simp [den, Finset.sum_range_succ, dd, map_ofNat C] + ring + +/-- The numerator as a sum of monomials. -/ +private theorem num_eq : num = ∑ j ∈ Finset.range 9, C (nm j) * X ^ j := by + simp [num, Finset.sum_range_succ, nm, map_ofNat C] + ring + +/-- Coefficients of a power series times the denominator. -/ +private theorem coeff_mul_den (c : ℕ → ℚ) (n : ℕ) : + coeff n (mk c * den) = ∑ j ∈ Finset.range 10, dd j * (if j ≤ n then c (n - j) else 0) := by + rw [den_eq, Finset.mul_sum, map_sum] + refine Finset.sum_congr rfl fun j _ => ?_ + rw [mul_left_comm, coeff_C_mul, coeff_mul_X_pow', coeff_mk] + +/-- Coefficients of the numerator. -/ +private theorem coeff_num (n : ℕ) : coeff n num = if n < 9 then nm n else 0 := by + rw [num_eq, map_sum] + simp only [coeff_C_mul_X_pow] + rw [Finset.sum_ite_eq] + simp + +/-- The column `T(2k, 2)` as rationals. -/ +private noncomputable def cq (k : ℕ) : ℚ := (T (2 * k) 2 : ℚ) + +/-- The recurrence of the denominator for `T(2k, 2)`, from `k = 1` on. -/ +private theorem cq_rec (K : ℕ) : + cq (K + 1) - 192 * cq (K + 2) + 5760 * cq (K + 3) - 49283 * cq (K + 4) + + 147264 * cq (K + 5) - 147264 * cq (K + 6) + 49283 * cq (K + 7) - 5760 * cq (K + 8) + + 192 * cq (K + 9) - cq (K + 10) = 0 := by + have h := rec9_T K + simp only [Nat.add_assoc, Nat.reduceAdd] at h + simp only [cq] + exact_mod_cast h + +/-- Mathar's conjectured generating function for column 3 (`m = 2`) of A270668 holds. -/ +theorem result : statement := by + rw [statement_iff] + change mk cq * den = num + ext n + rw [coeff_mul_den, coeff_num] + by_cases hn : n < 10 + · interval_cases n <;> + simp [Finset.sum_range_succ, dd, nm, cq, T_eq_Tc, Tc_val0, Tc_val1, Tc_val2, Tc_val3, + Tc_val4, Tc_val5, Tc_val6, Tc_val7, Tc_val8, Tc_val9] <;> norm_num + · obtain ⟨K, rfl⟩ : ∃ K, n = K + 10 := ⟨n - 10, by omega⟩ + rw [if_neg (by omega)] + simp [Finset.sum_range_succ, dd] + linarith [cq_rec K] + +end Math0.Frontier.A270668 + +#math0_settles Math0.Frontier.A270668.result Math0.Statements.A270668.statement diff --git a/lean/Math0/Frontier/OEIS/A275815.lean b/lean/Math0/Frontier/OEIS/A275815.lean new file mode 100644 index 0000000..d34446f --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A275815.lean @@ -0,0 +1,1224 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A275815 +import Math0.Audit + +/-! +# A275815: Jones's conjecture `a(n) = 8 (n - 2)²` for `n ≥ 6` holds + +The maximum total number of moves of same-colored queens on an `n × n` board is +`8 (n - 2)²` for every `n ≥ 6`. + +**Lower bound.** On the border placement (all `4n - 4` border squares occupied) every interior +square is empty and sees a queen in each of the eight directions, so the queens have +`8 (n - 2)²` moves. + +**Upper bound: a flow (linear programming dual) argument.** This part follows the proof of +A278212 in `Math0.Frontier.OEIS.A278212`, whose private lemmas are reproduced here for the +definitions of A275815. Fix a moving direction `d`. The moves in direction `d` are in bijection +with the empty squares `c` that "see" a queen behind them, i.e. `c - k • d` is a queen and +`c, c - d, …, c - (k-1) • d` are empty (`sum_ray_eq`). The indicator `Y c` of this satisfies +`Y c ≤ 1 - x c` and `Y c ≤ x (c - d) + Y (c - d)`, where `x` is the occupancy indicator. Let +`G c ≥ 0` be a "flow" from `c` to `c - d` (zero unless both are on the board) with +`α c := D + G (c + d) - G c ≥ 0`. Combining the two inequalities with weights `α c` and `G c` +and summing over the board, the flow terms telescope (`dir_ineq`). Summing over the directions +(`key`): `D · totalMoves ≤ ∑ c, (if c is occupied then B c else A c)` with +`A c = ∑_d α_d c` and `B c = ∑_d G_d (c + d)`, hence `≤ ∑ c, max (A c) (B c)`. + +For `n ≥ 7` one flow table (`LQ`, depending only on the position class of a square) gives +exactly `D · 8 (n - 2)²` (`queen_ge8` via a class-counting argument, `queen7` directly). +For `n = 6` the linear relaxation only gives `132.8`; a branch and bound tree on the five +squares `(0, 1), (1, 5), (4, 5), (5, 4), (4, 0)` has eight leaves, and at each leaf a flow +certificate (found by integer linear programming, checked by the kernel, `leaf`) bounds the +number of moves by a value `< 129`, hence by `128` (`queen6_le`). +-/ + +namespace Math0.Frontier.A275815 +open Math0.Statements.A275815 + +/-- The total number of moves of pieces of `S` moving in the directions `dirs`; for the queen +directions this is `totalMoves`. -/ +private def tm (dirs : List (ℤ × ℤ)) (n : ℕ) (S : Finset (ℕ × ℕ)) : ℕ := + ∑ p ∈ S, (dirs.map (rayMoves n S p)).sum + +/-- `totalMoves` is `tm` for the queen directions. -/ +private lemma totalMoves_eq (n : ℕ) (S : Finset (ℕ × ℕ)) : + totalMoves n S = tm queenDirs n S := rfl + +/-- The embedding of `ℕ × ℕ` into `ℤ × ℤ`. -/ +private def emb : ℕ × ℕ ↪ ℤ × ℤ := + ⟨fun p => ((p.1 : ℤ), (p.2 : ℤ)), fun a b h => by + simp only [Prod.mk.injEq, Nat.cast_inj] at h; exact Prod.ext h.1 h.2⟩ + +@[simp] private lemma emb_apply (p : ℕ × ℕ) : emb p = ((p.1 : ℤ), (p.2 : ℤ)) := rfl + +/-- The board as a set of integer points. -/ +private def BZ (n : ℕ) : Finset (ℤ × ℤ) := (board n).map emb + +/-- A placement as a set of integer points. -/ +private def SZ (S : Finset (ℕ × ℕ)) : Finset (ℤ × ℤ) := S.map emb + +/-- Membership in the integer board. -/ +private lemma mem_BZ {n : ℕ} {c : ℤ × ℤ} : + c ∈ BZ n ↔ 0 ≤ c.1 ∧ c.1 < n ∧ 0 ≤ c.2 ∧ c.2 < n := by + constructor + · intro h + simp only [BZ, Finset.mem_map, board, Finset.mem_product, Finset.mem_range] at h + obtain ⟨p, ⟨h1, h2⟩, rfl⟩ := h + simp only [emb_apply] + omega + · rintro ⟨h1, h2, h3, h4⟩ + simp only [BZ, Finset.mem_map, board, Finset.mem_product, Finset.mem_range] + refine ⟨(c.1.toNat, c.2.toNat), ⟨by omega, by omega⟩, ?_⟩ + simp only [emb_apply] + ext <;> simp <;> omega + +/-- Membership in the integer placement, for nonnegative points. -/ +private lemma mem_SZ {S : Finset (ℕ × ℕ)} {c : ℤ × ℤ} (h1 : 0 ≤ c.1) (h2 : 0 ≤ c.2) : + c ∈ SZ S ↔ (c.1.toNat, c.2.toNat) ∈ S := by + constructor + · intro h + simp only [SZ, Finset.mem_map] at h + obtain ⟨p, hp, rfl⟩ := h + simpa using hp + · intro h + simp only [SZ, Finset.mem_map] + refine ⟨_, h, ?_⟩ + simp only [emb_apply] + ext <;> simp <;> omega + +/-- A placement on the board stays on the board as a set of integer points. -/ +private lemma SZ_sub_BZ {n : ℕ} {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) : SZ S ⊆ BZ n := + Finset.map_subset_map.mpr hS + +/-- The empty squares of the board. -/ +private abbrev E (n : ℕ) (S : Finset (ℕ × ℕ)) (c : ℤ × ℤ) : Prop := c ∈ BZ n ∧ c ∉ SZ S + +/-- `isEmptySquare` in terms of `BZ` and `SZ`. -/ +private lemma isEmpty_iff {n : ℕ} {S : Finset (ℕ × ℕ)} {x y : ℤ} : + isEmptySquare n S x y = true ↔ E n S (x, y) := by + simp only [isEmptySquare, decide_eq_true_eq, E, mem_BZ] + constructor + · rintro ⟨h1, h2, h3, h4, h5⟩ + exact ⟨⟨h1, h2, h3, h4⟩, fun h => h5 ((mem_SZ h1 h3).mp h)⟩ + · rintro ⟨⟨h1, h2, h3, h4⟩, h5⟩ + exact ⟨h1, h2, h3, h4, fun h => h5 ((mem_SZ h1 h3).mpr h)⟩ + +/-- Length of `takeWhile` on `range'` as a count of good prefixes. -/ +private lemma tw_len (P : ℕ → Bool) (m s : ℕ) : + ((List.range' s m).takeWhile P).length = + ∑ k ∈ Finset.range m, if (∀ j < k + 1, P (s + j) = true) then 1 else 0 := by + induction m generalizing s with + | zero => simp + | succ m ih => + rw [List.range'_succ, List.takeWhile_cons, Finset.sum_range_succ'] + by_cases hs : P s = true + · have h0 : (∀ j < 0 + 1, P (s + j) = true) := by + intro j hj; obtain rfl : j = 0 := by omega + simpa using hs + rw [if_pos hs, List.length_cons, ih (s + 1), if_pos h0] + congr 1 + apply Finset.sum_congr rfl + intro k _ + apply if_congr _ rfl rfl + constructor + · intro h j hj + rcases j with _ | j + · simpa using hs + · have := h j (by omega); rwa [show s + 1 + j = s + (j + 1) by ring] at this + · intro h j hj; have := h (j + 1) (by omega); rwa [show s + (j + 1) = s + 1 + j by ring] at this + · have h0 : ¬ (∀ j < 0 + 1, P (s + j) = true) := fun h => hs (by simpa using h 0 (by omega)) + rw [if_neg hs, if_neg h0, List.length_nil, add_zero] + symm + apply Finset.sum_eq_zero + intro k _ + rw [if_neg] + intro h; exact hs (by simpa using h 0 (by omega)) + +/-- The point `c + t • d`. -/ +private def sh (c d : ℤ × ℤ) (t : ℤ) : ℤ × ℤ := (c.1 + t * d.1, c.2 + t * d.2) + +/-- The coercion of a list of naturals to a list of integers is a `map`. -/ +private lemma bind_pure_cast (l : List ℕ) : + (l >>= fun (a : ℕ) => (pure (a : ℤ) : List ℤ)) = l.map (fun a : ℕ => (a : ℤ)) := by + induction l with + | nil => rfl + | cons a l ih => simp_all + +/-- `rayMoves` counts the `k < n` such that the first `k + 1` squares of the ray are empty. -/ +private lemma rayMoves_eq (n : ℕ) (S : Finset (ℕ × ℕ)) (p : ℕ × ℕ) (d : ℤ × ℤ) : + rayMoves n S p d = ∑ k ∈ Finset.range n, + if (∀ j < k + 1, E n S (sh (emb p) d (1 + j))) then 1 else 0 := by + rw [rayMoves, bind_pure_cast, List.takeWhile_map, List.length_map, tw_len] + apply Finset.sum_congr rfl + intro k _ + apply if_congr _ rfl rfl + apply forall_congr'; intro j; apply imp_congr_right; intro _ + simp only [Function.comp_apply, isEmpty_iff, sh, emb_apply] + push_cast + rfl + +/-- `Y n S d c = 1` iff `c` is an empty square reached by a piece moving in direction `d`. -/ +private def Y (n : ℕ) (S : Finset (ℕ × ℕ)) (d c : ℤ × ℤ) : ℕ := + ∑ k ∈ Finset.range n, + if (sh c d (-(k + 1)) ∈ SZ S ∧ ∀ j < k + 1, E n S (sh c d (-j))) then 1 else 0 + +/-- Composition of shifts along `d`. -/ +private lemma sh_sh (c d : ℤ × ℤ) (s t : ℤ) : sh (sh c d s) d t = sh c d (s + t) := by + simp only [sh]; ext <;> simp <;> ring + +/-- The zero shift. -/ +private lemma sh_zero (c d : ℤ × ℤ) : sh c d 0 = c := by simp [sh] + +/-- Double counting: total moves in direction `d` = number of reached empty squares. -/ +private lemma sum_ray_eq (n : ℕ) (S : Finset (ℕ × ℕ)) (d : ℤ × ℤ) : + ∑ p ∈ S, rayMoves n S p d = ∑ c ∈ BZ n, Y n S d c := by + simp only [rayMoves_eq, Y] + rw [← Finset.sum_map S emb (fun q => ∑ k ∈ Finset.range n, + if (∀ j < k + 1, E n S (sh q d (1 + j))) then 1 else 0)] + rw [Finset.sum_comm, Finset.sum_comm (s := BZ n)] + apply Finset.sum_congr rfl + intro k _ + apply Finset.sum_bij_ne_zero (fun q _ _ => sh q d (k + 1)) + · intro q hq hne + have h := (by simpa using hne : ∀ j < k + 1, E n S (sh q d (1 + j))) + have := (h k (by omega)).1 + rwa [show (1 : ℤ) + (k : ℕ) = (k : ℤ) + 1 by ring] at this + · intro q1 _ _ q2 _ _ h + have := congrArg (fun c => sh c d (-(k + 1))) h + simpa [sh_sh, sh_zero] using this + · intro c hc hne + have h := (by simpa using hne : sh c d (-(k + 1)) ∈ SZ S ∧ + ∀ j < k + 1, E n S (sh c d (-j))) + refine ⟨sh c d (-(k + 1)), h.1, ?_, by simp [sh_sh, sh_zero]⟩ + rw [if_pos] + · exact one_ne_zero + intro j hj + have := h.2 (k - j) (by omega) + rw [sh_sh] + convert this using 2 + push_cast [Nat.cast_sub (by omega : j ≤ k)] + ring + · intro q hq _ + apply if_congr _ rfl rfl + rw [sh_sh, show ((k : ℤ) + 1 + -(k + 1)) = 0 by ring, sh_zero] + have hq' : q ∈ SZ S := hq + simp only [hq', true_and] + constructor + · intro h j hj + have := h (k - j) (by omega) + rw [sh_sh] + convert this using 2 + push_cast [Nat.cast_sub (by omega : j ≤ k)] + ring + · intro h j hj + have := h (k - j) (by omega) + rw [sh_sh] at this + convert this using 2 + push_cast [Nat.cast_sub (by omega : j ≤ k)] + ring + + +/-! ### The dual (flow) inequality -/ + +/-- Occupancy indicator. -/ +private def X (S : Finset (ℕ × ℕ)) (c : ℤ × ℤ) : ℤ := if c ∈ SZ S then 1 else 0 + +/-- At most one piece reaches a given square in a given direction. -/ +private lemma Y_le_one (n : ℕ) (S : Finset (ℕ × ℕ)) (d c : ℤ × ℤ) : Y n S d c ≤ 1 := by + unfold Y + rw [Finset.sum_boole] + apply Finset.card_le_one.mpr + intro a ha b hb + simp only [Finset.mem_filter, Finset.mem_range] at ha hb + by_contra hab + rcases Nat.lt_or_gt_of_ne hab with h | h + · exact (hb.2.2 (a + 1) (by omega)).2 (by simpa using ha.2.1) + · exact (ha.2.2 (b + 1) (by omega)).2 (by simpa using hb.2.1) + +/-- Only empty squares of the board are reached. -/ +private lemma Y_eq_zero_of_not_E {n : ℕ} {S : Finset (ℕ × ℕ)} {d c : ℤ × ℤ} (h : ¬ E n S c) : + Y n S d c = 0 := by + unfold Y + apply Finset.sum_eq_zero + intro k _ + rw [if_neg] + rintro ⟨_, h2⟩ + exact h (by simpa [sh_zero] using h2 0 (by omega)) + +/-- `Y c ≤ x (c - d) + Y (c - d)`: the square behind `c` is a piece or is itself reached. -/ +private lemma Y_rec (n : ℕ) (S : Finset (ℕ × ℕ)) (d c : ℤ × ℤ) : + (Y n S d c : ℤ) ≤ X S (sh c d (-1)) + Y n S d (sh c d (-1)) := by + rcases Nat.eq_zero_or_pos (Y n S d c) with h | h + · rw [h]; unfold X; split_ifs <;> positivity + have h1 : Y n S d c = 1 := le_antisymm (Y_le_one n S d c) h + rw [h1] + unfold Y at h + obtain ⟨k, hk, hk2⟩ := Finset.exists_ne_zero_of_sum_ne_zero (Nat.pos_iff_ne_zero.mp h) + rw [Finset.mem_range] at hk + have hk3 : sh c d (-(k + 1)) ∈ SZ S ∧ ∀ j < k + 1, E n S (sh c d (-j)) := by + by_contra hc; exact hk2 (if_neg hc) + rcases k with _ | k + · have : X S (sh c d (-1)) = 1 := by + unfold X; rw [if_pos]; simpa using hk3.1 + rw [this]; push_cast; omega + · have hY : 1 ≤ Y n S d (sh c d (-1)) := by + unfold Y + have hsub : ({k} : Finset ℕ) ⊆ Finset.range n := by + intro x hx; rw [Finset.mem_singleton] at hx; subst hx; rw [Finset.mem_range]; omega + calc 1 = ∑ k' ∈ ({k} : Finset ℕ), (if (sh (sh c d (-1)) d (-(k' + 1)) ∈ SZ S ∧ + ∀ j < k' + 1, E n S (sh (sh c d (-1)) d (-j))) then 1 else 0) := by + rw [Finset.sum_singleton, if_pos] + refine ⟨?_, ?_⟩ + · rw [sh_sh]; convert hk3.1 using 2; push_cast; ring + · intro j hj; rw [sh_sh] + convert hk3.2 (j + 1) (by omega) using 2; push_cast; ring + _ ≤ _ := Finset.sum_le_sum_of_subset hsub + have : 0 ≤ X S (sh c d (-1)) := by unfold X; split_ifs <;> norm_num + push_cast; omega + +/-- Squares whose predecessor in direction `d` is off the board are not reached. -/ +private lemma Y_first {n : ℕ} {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) {d c : ℤ × ℤ} (hd : sh c d (-1) ∉ BZ n) : Y n S d c = 0 := by + unfold Y + apply Finset.sum_eq_zero + intro k _ + rw [if_neg] + rintro ⟨h1, h2⟩ + rcases k with _ | k + · exact hd (SZ_sub_BZ hS (by simpa using h1)) + · exact hd (by simpa using (h2 1 (by omega)).1) + +/-- Shifting a sum along the direction `d`. -/ +private lemma shift_sum (n : ℕ) (d : ℤ × ℤ) (f g : ℤ × ℤ → ℤ) + (hf : ∀ c, f c ≠ 0 → c ∈ BZ n ∧ sh c d (-1) ∈ BZ n) : + ∑ c ∈ BZ n, f (sh c d 1) * g c = ∑ c ∈ BZ n, f c * g (sh c d (-1)) := by + apply Finset.sum_bij_ne_zero (fun c _ _ => sh c d 1) + · intro c _ h + exact (hf _ (left_ne_zero_of_mul h)).1 + · intro a _ _ b _ _ h + have := congrArg (fun c => sh c d (-1)) h + simpa [sh_sh, sh_zero] using this + · intro c _ h + have h2 := hf _ (left_ne_zero_of_mul h) + refine ⟨sh c d (-1), h2.2, ?_, by simp [sh_sh, sh_zero]⟩ + rw [sh_sh, show (-1 : ℤ) + 1 = 0 by ring, sh_zero] + exact h + · intro c _ _ + rw [sh_sh, show (1 : ℤ) + -1 = 0 by ring, sh_zero] + +/-- The flow inequality for one direction. -/ +private lemma dir_ineq {n : ℕ} {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) (D : ℤ) (d : ℤ × ℤ) + (G : ℤ × ℤ → ℤ) (h0 : ∀ c, 0 ≤ G c) + (hsupp : ∀ c, G c ≠ 0 → c ∈ BZ n ∧ sh c d (-1) ∈ BZ n) + (hα : ∀ c ∈ BZ n, sh c d (-1) ∈ BZ n → G c ≤ D + G (sh c d 1)) : + D * (∑ p ∈ S, rayMoves n S p d : ℕ) ≤ + ∑ c ∈ BZ n, ((if sh c d (-1) ∈ BZ n then D + G (sh c d 1) - G c else 0) * (1 - X S c) + + G (sh c d 1) * X S c) := by + rw [sum_ray_eq] + have hX0 : ∀ c, 0 ≤ X S c := fun c => by unfold X; split_ifs <;> norm_num + have hX1 : ∀ c, X S c ≤ 1 := fun c => by unfold X; split_ifs <;> norm_num + -- the per-cell inequality + have hcell : ∀ c ∈ BZ n, D * (Y n S d c : ℤ) + G (sh c d 1) * Y n S d c ≤ + (if sh c d (-1) ∈ BZ n then D + G (sh c d 1) - G c else 0) * (1 - X S c) + + G c * X S (sh c d (-1)) + G c * Y n S d (sh c d (-1)) := by + intro c hc + have hY1 := Y_le_one n S d c + have hYr := Y_rec n S d c + have hG := h0 c + have hX := hX0 (sh c d (-1)) + have hYc : (0 : ℤ) ≤ Y n S d (sh c d (-1)) := by positivity + by_cases hd : sh c d (-1) ∈ BZ n + · rw [if_pos hd] + have ha := hα c hc hd + rcases Nat.eq_zero_or_pos (Y n S d c) with h | h + · rw [h]; push_cast + have := hX1 c + nlinarith + · have h1 : Y n S d c = 1 := le_antisymm hY1 h + have hxc : X S c = 0 := by + unfold X; rw [if_neg]; intro hm + have := Y_eq_zero_of_not_E (n := n) (d := d) (fun hE => hE.2 hm) + omega + rw [h1, hxc] at *; push_cast at * + nlinarith + · rw [if_neg hd, Y_first hS hd] + push_cast + nlinarith + have hsum := Finset.sum_le_sum hcell + rw [Finset.sum_add_distrib, Finset.sum_add_distrib, Finset.sum_add_distrib] at hsum + have e1 := shift_sum n d G (fun c => (Y n S d c : ℤ)) hsupp + have e2 := shift_sum n d G (X S) hsupp + push_cast + rw [Finset.mul_sum, Finset.sum_add_distrib] + linarith + + +/-- The "empty" weight of a cell. -/ +private def Af (n : ℕ) (D : ℤ) (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) (c : ℤ × ℤ) : ℤ := + (dirs.map fun d => if sh c d (-1) ∈ BZ n then D + G d (sh c d 1) - G d c else 0).sum + +/-- The "occupied" weight of a cell. -/ +private def Bf (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) (c : ℤ × ℤ) : ℤ := + (dirs.map fun d => G d (sh c d 1)).sum + +/-- The main inequality: weighted total moves are bounded by the cell weights. -/ +private theorem key {n : ℕ} {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) (D : ℤ) + (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) (h0 : ∀ d c, 0 ≤ G d c) + (hsupp : ∀ d c, G d c ≠ 0 → c ∈ BZ n ∧ sh c d (-1) ∈ BZ n) + (hα : ∀ d ∈ dirs, ∀ c ∈ BZ n, sh c d (-1) ∈ BZ n → G d c ≤ D + G d (sh c d 1)) : + D * (tm dirs n S : ℤ) ≤ + ∑ c ∈ BZ n, (if c ∈ SZ S then Bf dirs G c else Af n D dirs G c) := by + have main : ∀ L : List (ℤ × ℤ), (∀ d ∈ L, ∀ c ∈ BZ n, sh c d (-1) ∈ BZ n → + G d c ≤ D + G d (sh c d 1)) → + D * (∑ p ∈ S, (L.map (rayMoves n S p)).sum : ℕ) ≤ + ∑ c ∈ BZ n, ((1 - X S c) * Af n D L G c + X S c * Bf L G c) := by + intro L + induction L with + | nil => intro _; simp [Af, Bf] + | cons d L ih => + intro hL + have h1 := dir_ineq hS D d (G d) (h0 d) (hsupp d) (hL d (by simp)) + have h2 := ih (fun d' hd' => hL d' (by simp [hd'])) + have e : ∀ p ∈ S, ((d :: L).map (rayMoves n S p)).sum = + rayMoves n S p d + (L.map (rayMoves n S p)).sum := by intro p _; simp + rw [Finset.sum_congr rfl e, Finset.sum_add_distrib] + have e2 : ∀ c ∈ BZ n, (1 - X S c) * Af n D (d :: L) G c + X S c * Bf (d :: L) G c = + ((if sh c d (-1) ∈ BZ n then D + G d (sh c d 1) - G d c else 0) * (1 - X S c) + + G d (sh c d 1) * X S c) + ((1 - X S c) * Af n D L G c + X S c * Bf L G c) := by + intro c _; simp only [Af, Bf, List.map_cons, List.sum_cons]; ring + rw [Finset.sum_congr rfl e2, Finset.sum_add_distrib] + push_cast at h1 h2 ⊢ + linarith + have hm := main dirs hα + have htot : tm dirs n S = ∑ p ∈ S, (dirs.map (rayMoves n S p)).sum := rfl + rw [htot] + refine hm.trans (le_of_eq (Finset.sum_congr rfl fun c _ => ?_)) + unfold X + split_ifs <;> ring + + +/-! ### Checking certificates by computation -/ + +/-- Board membership as a boolean. -/ +private def inB (n : ℕ) (c : ℤ × ℤ) : Bool := decide (0 ≤ c.1 ∧ c.1 < n ∧ 0 ≤ c.2 ∧ c.2 < n) + +/-- `inB` decides board membership. -/ +private lemma inB_iff {n : ℕ} {c : ℤ × ℤ} : inB n c = true ↔ c ∈ BZ n := by + simp [inB, mem_BZ] + +/-- A flow given by a table of natural numbers, cut off outside the board. -/ +private def Gt (n : ℕ) (T : ℤ × ℤ → ℤ × ℤ → ℕ) (d c : ℤ × ℤ) : ℤ := + if inB n c && inB n (sh c d (-1)) then (T d c : ℤ) else 0 + +/-- Table lookup: entries `(d₁, d₂, i, j, v)`. -/ +private def tab (L : List (ℤ × ℤ × ℤ × ℤ × ℕ)) (d c : ℤ × ℤ) : ℕ := + match L.find? (fun e => e.1 == d.1 && e.2.1 == d.2 && e.2.2.1 == c.1 && e.2.2.2.1 == c.2) with + | some e => e.2.2.2.2 + | none => 0 + +/-- Computable version of `Af`. -/ +private def Afc (n : ℕ) (D : ℤ) (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) (c : ℤ × ℤ) : ℤ := + (dirs.map fun d => if inB n (sh c d (-1)) then D + G d (sh c d 1) - G d c else 0).sum + +/-- `Af` agrees with its computable version. -/ +private lemma Af_eq (n : ℕ) (D : ℤ) (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) (c : ℤ × ℤ) : + Af n D dirs G c = Afc n D dirs G c := by + unfold Af Afc + congr 1 + apply List.map_congr_left + intro d _ + by_cases h : sh c d (-1) ∈ BZ n + · rw [if_pos h, if_pos (inB_iff.mpr h)] + · rw [if_neg h, if_neg (fun h' => h (inB_iff.mp h'))] + +/-- The `α ≥ 0` condition, checked cell by cell. -/ +private def checkA (n : ℕ) (D : ℤ) (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) : Bool := + dirs.all fun d => (List.range n).all fun i => (List.range n).all fun j => + !inB n (sh ((i : ℤ), (j : ℤ)) d (-1)) || decide (G d ((i : ℤ), (j : ℤ)) ≤ + D + G d (sh ((i : ℤ), (j : ℤ)) d 1)) + +/-- The bound for one cell, given cells known to be occupied (`In`) or empty (`Out`). -/ +private def bnd (n : ℕ) (D : ℤ) (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) + (In Out : List (ℕ × ℕ)) (i j : ℕ) : ℤ := + if (i, j) ∈ In then Bf dirs G ((i : ℤ), (j : ℤ)) + else if (i, j) ∈ Out then Afc n D dirs G ((i : ℤ), (j : ℤ)) + else max (Afc n D dirs G ((i : ℤ), (j : ℤ))) (Bf dirs G ((i : ℤ), (j : ℤ))) + +/-- The total of the cell bounds. -/ +private def bndSum (n : ℕ) (D : ℤ) (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) + (In Out : List (ℕ × ℕ)) : ℤ := + ∑ i ∈ Finset.range n, ∑ j ∈ Finset.range n, bnd n D dirs G In Out i j + +/-- Sums over the integer board as double sums over `range n`. -/ +private lemma sum_BZ (n : ℕ) (f : ℤ × ℤ → ℤ) : + ∑ c ∈ BZ n, f c = ∑ i ∈ Finset.range n, ∑ j ∈ Finset.range n, f ((i : ℤ), (j : ℤ)) := by + rw [BZ, Finset.sum_map, board, Finset.sum_product] + rfl + +/-- A leaf certificate bounds the total number of moves. -/ +private theorem leaf {n : ℕ} {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) (D : ℤ) (hD : 0 < D) + (dirs : List (ℤ × ℤ)) (T : ℤ × ℤ → ℤ × ℤ → ℕ) (In Out : List (ℕ × ℕ)) (target : ℕ) + (h1 : checkA n D dirs (Gt n T) = true) + (h2 : bndSum n D dirs (Gt n T) In Out < D * (target + 1)) + (hIn : ∀ p ∈ In, p ∈ S) (hOut : ∀ p ∈ Out, p ∉ S) : + tm dirs n S ≤ target := by + have hk := key hS D dirs (Gt n T) + (fun d c => by unfold Gt; split_ifs <;> positivity) + (fun d c h => by + unfold Gt at h + split_ifs at h with hc + · simp only [Bool.and_eq_true] at hc + exact ⟨inB_iff.mp hc.1, inB_iff.mp hc.2⟩ + · exact absurd rfl h) + (fun d hd c hc hc' => by + have h1' := h1 + unfold checkA at h1' + rw [List.all_eq_true] at h1' + have h3 := h1' d hd + rw [mem_BZ] at hc + obtain ⟨i, hi⟩ : ∃ i : ℕ, (i : ℤ) = c.1 := ⟨c.1.toNat, by omega⟩ + obtain ⟨j, hj⟩ : ∃ j : ℕ, (j : ℤ) = c.2 := ⟨c.2.toNat, by omega⟩ + rw [List.all_eq_true] at h3 + have h4 := h3 i (List.mem_range.mpr (by omega)) + rw [List.all_eq_true] at h4 + have h5 := h4 j (List.mem_range.mpr (by omega)) + have hc2 : c = ((i : ℤ), (j : ℤ)) := by ext <;> simp [hi, hj] + subst hc2 + simp only [Bool.or_eq_true, Bool.not_eq_true', decide_eq_true_eq] at h5 + rcases h5 with h5 | h5 + · exact absurd (inB_iff.mpr hc') (by simp [h5]) + · exact h5) + have hle : ∑ c ∈ BZ n, (if c ∈ SZ S then Bf dirs (Gt n T) c else Af n D dirs (Gt n T) c) ≤ + bndSum n D dirs (Gt n T) In Out := by + rw [sum_BZ, bndSum] + apply Finset.sum_le_sum; intro i _ + apply Finset.sum_le_sum; intro j _ + have hmem : ((i : ℤ), (j : ℤ)) ∈ SZ S ↔ (i, j) ∈ S := by + rw [mem_SZ (by simp) (by simp)]; simp + rw [Af_eq, bnd] + by_cases hI : (i, j) ∈ In + · rw [if_pos (hmem.mpr (hIn _ hI)), if_pos hI] + · rw [if_neg hI] + by_cases hO : (i, j) ∈ Out + · rw [if_neg (fun h => hOut _ hO (hmem.mp h)), if_pos hO] + · rw [if_neg hO] + split_ifs + · exact le_max_right _ _ + · exact le_max_left _ _ + have : D * (tm dirs n S : ℤ) < D * (target + 1) := by linarith + have := lt_of_mul_lt_mul_left this hD.le + omega + + +/-! ### The general case: flows depending only on the position class of a cell -/ + +/-- Position class of a coordinate, cut off at `3`: `0, 1, 2` near the start, `3` in the +middle, `4, 5, 6` near the end. -/ +private def cls3 (n : ℕ) (x : ℤ) : ℕ := + if x < 3 then x.toNat else if (n : ℤ) - 1 - x < 3 then (6 - ((n : ℤ) - 1 - x)).toNat else 3 + +/-- Position class of a coordinate, cut off at `4`: `0, …, 3` near the start, `4` in the +middle, `5, …, 8` near the end. -/ +private def cls4 (n : ℕ) (x : ℤ) : ℕ := + if x < 4 then x.toNat else if (n : ℤ) - 1 - x < 4 then (8 - ((n : ℤ) - 1 - x)).toNat else 4 + +/-- Whether a step `δ` from a coordinate of class `v` stays on the board. -/ +private def ok4 (v : ℕ) (δ : ℤ) : Bool := !(v == 0 && δ == -1) && !(v == 8 && δ == 1) + +/-- The `cls3` class after a step `δ` from a coordinate of `cls4` class `v`. -/ +private def sh3 (v : ℕ) (δ : ℤ) : ℕ := + if v ≤ 3 then (if (v : ℤ) + δ < 3 then ((v : ℤ) + δ).toNat else 3) + else if v = 4 then 3 + else (if 8 - (v : ℤ) - δ < 3 then ((v : ℤ) + δ - 2).toNat else 3) + +/-- Classes with cut-off `4` are at most `8`. -/ +private lemma cls4_le (n : ℕ) (x : ℤ) (hx : 0 ≤ x) (hxn : x < n) : cls4 n x ≤ 8 := by + unfold cls4; split_ifs <;> omega + +/-- `ok4` decides whether a step stays on the board (for `n ≥ 8`). -/ +private lemma ok4_iff {n : ℕ} (hn : 8 ≤ n) {x δ : ℤ} (hx : 0 ≤ x) (hxn : x < n) + (hδ : -1 ≤ δ ∧ δ ≤ 1) : ok4 (cls4 n x) δ = true ↔ 0 ≤ x + δ ∧ x + δ < n := by + unfold ok4 cls4 + split_ifs with h1 h2 <;> simp <;> omega + +/-- The `cls3` class after a step is determined by the `cls4` class before it (`n ≥ 8`). -/ +private lemma cls3_shift {n : ℕ} (hn : 8 ≤ n) {x δ : ℤ} (hx : 0 ≤ x) (hxn : x < n) + (hδ : -1 ≤ δ ∧ δ ≤ 1) (h1 : 0 ≤ x + δ) (h2 : x + δ < n) : + cls3 n (x + δ) = sh3 (cls4 n x) δ := by + unfold cls3 sh3 cls4 + split_ifs <;> omega + +/-- Lookup in a class table: entries `(u, w, d₁, d₂, v)`. -/ +private def tabC (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (u w : ℕ) (d : ℤ × ℤ) : ℕ := + match L.find? (fun e => e.1 == u && e.2.1 == w && e.2.2.1 == d.1 && e.2.2.2.1 == d.2) with + | some e => e.2.2.2.2 + | none => 0 + +/-- The flow defined by a class table. -/ +private def Gc (n : ℕ) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) : ℤ × ℤ → ℤ × ℤ → ℤ := + Gt n (fun d c => tabC L (cls3 n c.1) (cls3 n c.2) d) + +/-- Flow into the cell `c` from `c + d`, by classes. -/ +private def G1 (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (v w : ℕ) (d : ℤ × ℤ) : ℤ := + if ok4 v d.1 && ok4 w d.2 then (tabC L (sh3 v d.1) (sh3 w d.2) d : ℤ) else 0 + +/-- Flow out of the cell `c`, by classes. -/ +private def G0 (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (v w : ℕ) (d : ℤ × ℤ) : ℤ := + (tabC L (sh3 v 0) (sh3 w 0) d : ℤ) + +/-- `Af` by classes. -/ +private def Aty (D : ℤ) (dirs : List (ℤ × ℤ)) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (v w : ℕ) : ℤ := + (dirs.map fun d => if ok4 v (-d.1) && ok4 w (-d.2) then D + G1 L v w d - G0 L v w d + else 0).sum + +/-- `Bf` by classes. -/ +private def Bty (dirs : List (ℤ × ℤ)) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (v w : ℕ) : ℤ := + (dirs.map fun d => G1 L v w d).sum + +/-- The cell bound by classes. -/ +private def Mty (D : ℤ) (dirs : List (ℤ × ℤ)) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (v w : ℕ) : ℤ := + max (Aty D dirs L v w) (Bty dirs L v w) + +/-- Unit directions. -/ +private def unitDir (d : ℤ × ℤ) : Prop := -1 ≤ d.1 ∧ d.1 ≤ 1 ∧ -1 ≤ d.2 ∧ d.2 ≤ 1 + +/-- Board membership of a neighbour, by classes. -/ +private lemma memBZ_shift {n : ℕ} (hn : 8 ≤ n) {c d : ℤ × ℤ} (hc : c ∈ BZ n) (hd : unitDir d) + (s : ℤ) (hs : s = 1 ∨ s = -1) : + sh c d s ∈ BZ n ↔ (ok4 (cls4 n c.1) (s * d.1) && ok4 (cls4 n c.2) (s * d.2)) = true := by + rw [mem_BZ] at hc + obtain ⟨h1, h2, h3, h4⟩ := hc + obtain ⟨d1, d2, d3, d4⟩ := hd + have hδ1 : -1 ≤ s * d.1 ∧ s * d.1 ≤ 1 := by rcases hs with rfl | rfl <;> constructor <;> linarith + have hδ2 : -1 ≤ s * d.2 ∧ s * d.2 ≤ 1 := by rcases hs with rfl | rfl <;> constructor <;> linarith + rw [Bool.and_eq_true, ok4_iff hn h1 h2 hδ1, ok4_iff hn h3 h4 hδ2, mem_BZ] + simp only [sh] + constructor + · rintro ⟨a, b, c, e⟩; exact ⟨⟨by linarith, by linarith⟩, ⟨by linarith, by linarith⟩⟩ + · rintro ⟨⟨a, b⟩, ⟨c, e⟩⟩; exact ⟨by linarith, by linarith, by linarith, by linarith⟩ + +/-- The flow at `c + d`, by classes. -/ +private lemma Gc_one {n : ℕ} (hn : 8 ≤ n) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) {c d : ℤ × ℤ} + (hc : c ∈ BZ n) (hd : unitDir d) : + Gc n L d (sh c d 1) = G1 L (cls4 n c.1) (cls4 n c.2) d := by + have hm := memBZ_shift hn hc hd 1 (Or.inl rfl) + simp only [one_mul] at hm + unfold Gc Gt G1 + have hback : sh (sh c d 1) d (-1) = c := by + rw [sh_sh, show (1 : ℤ) + -1 = 0 by ring, sh_zero] + rw [hback, inB_iff.mpr hc, Bool.and_true] + by_cases h : sh c d 1 ∈ BZ n + · rw [if_pos (inB_iff.mpr h), if_pos (hm.mp h)] + rw [mem_BZ] at hc + obtain ⟨d1, d2, d3, d4⟩ := hd + have h' := mem_BZ.mp h + simp only [sh, one_mul] at h' ⊢ + rw [cls3_shift hn hc.1 hc.2.1 ⟨d1, d2⟩ (by linarith) (by linarith), + cls3_shift hn hc.2.2.1 hc.2.2.2 ⟨d3, d4⟩ (by linarith) (by linarith)] + · rw [if_neg (fun h' => h (inB_iff.mp h')), if_neg (fun h' => h (hm.mpr h'))] + +/-- The flow at `c` (when `c - d` is on the board), by classes. -/ +private lemma Gc_zero {n : ℕ} (hn : 8 ≤ n) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) {c d : ℤ × ℤ} + (hc : c ∈ BZ n) (hd' : sh c d (-1) ∈ BZ n) : + Gc n L d c = G0 L (cls4 n c.1) (cls4 n c.2) d := by + unfold Gc Gt G0 + rw [inB_iff.mpr hc, inB_iff.mpr hd', Bool.and_self, if_pos rfl] + rw [mem_BZ] at hc + have e1 := cls3_shift hn hc.1 hc.2.1 ⟨by norm_num, by norm_num⟩ (by linarith) (by linarith) + (δ := 0) + have e2 := cls3_shift hn hc.2.2.1 hc.2.2.2 ⟨by norm_num, by norm_num⟩ (by linarith) + (by linarith) (δ := 0) + simp only [add_zero] at e1 e2 + dsimp only + rw [e1, e2] + +/-- `Af` depends only on the classes of the coordinates. -/ +private lemma Af_ty {n : ℕ} (hn : 8 ≤ n) (D : ℤ) (dirs : List (ℤ × ℤ)) + (hdirs : ∀ d ∈ dirs, unitDir d) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) {c : ℤ × ℤ} + (hc : c ∈ BZ n) : Af n D dirs (Gc n L) c = Aty D dirs L (cls4 n c.1) (cls4 n c.2) := by + unfold Af Aty + congr 1 + apply List.map_congr_left + intro d hd + have hm := memBZ_shift hn hc (hdirs d hd) (-1) (Or.inr rfl) + simp only [neg_one_mul] at hm + by_cases h : sh c d (-1) ∈ BZ n + · rw [if_pos h, if_pos (hm.mp h), Gc_one hn L hc (hdirs d hd), Gc_zero hn L hc h] + · rw [if_neg h, if_neg (fun h' => h (hm.mpr h'))] + +/-- `Bf` depends only on the classes of the coordinates. -/ +private lemma Bf_ty {n : ℕ} (hn : 8 ≤ n) (dirs : List (ℤ × ℤ)) + (hdirs : ∀ d ∈ dirs, unitDir d) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) {c : ℤ × ℤ} + (hc : c ∈ BZ n) : Bf dirs (Gc n L) c = Bty dirs L (cls4 n c.1) (cls4 n c.2) := by + unfold Bf Bty + congr 1 + apply List.map_congr_left + intro d hd + rw [Gc_one hn L hc (hdirs d hd)] + +/-- The `α ≥ 0` condition by classes. -/ +private def checkTy (D : ℤ) (dirs : List (ℤ × ℤ)) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) : Bool := + dirs.all fun d => (List.range 9).all fun v => (List.range 9).all fun w => + !(ok4 v (-d.1) && ok4 w (-d.2)) || decide (G0 L v w d ≤ D + G1 L v w d) + +/-- The eight boundary classes. -/ +private def E8 : Finset ℕ := {0, 1, 2, 3, 5, 6, 7, 8} + +/-- Summing a function of the class over a coordinate, for `n ≥ 8`. -/ +private lemma sum_cls4 {n : ℕ} (hn : 8 ≤ n) (f : ℕ → ℤ) : + ∑ i ∈ Finset.range n, f (cls4 n i) = ∑ v ∈ E8, f v + ((n : ℤ) - 8) * f 4 := by + obtain ⟨m, rfl⟩ : ∃ m, n = 4 + m + 4 := ⟨n - 8, by omega⟩ + rw [Finset.sum_range_add, Finset.sum_range_add] + have hmid : ∀ x ∈ Finset.range m, f (cls4 (4 + m + 4) ((4 + x : ℕ) : ℤ)) = f 4 := by + intro x hx + rw [Finset.mem_range] at hx + congr 1 + unfold cls4; push_cast; split_ifs <;> omega + rw [Finset.sum_congr rfl hmid, Finset.sum_const, Finset.card_range] + have hv : ∀ k : ℕ, k < 4 → cls4 (4 + m + 4) (k : ℤ) = k := by + intro k hk; unfold cls4; push_cast; split_ifs <;> omega + have hw : ∀ k : ℕ, k < 4 → cls4 (4 + m + 4) ((4 + m + k : ℕ) : ℤ) = 5 + k := by + intro k hk; unfold cls4; push_cast; split_ifs <;> omega + simp only [Finset.sum_range_succ, Finset.sum_range_zero, zero_add] + rw [hv 0 (by norm_num), hv 1 (by norm_num), hv 2 (by norm_num), hv 3 (by norm_num), + hw 0 (by norm_num), hw 1 (by norm_num), hw 2 (by norm_num), hw 3 (by norm_num)] + simp only [E8] + norm_num + ring + +/-- The general bound for `n ≥ 8`. -/ +private theorem general {n : ℕ} (hn : 8 ≤ n) {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) (D : ℤ) + (hD : 0 < D) (dirs : List (ℤ × ℤ)) (hdirs : ∀ d ∈ dirs, unitDir d) + (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (hchk : checkTy D dirs L = true) (target : ℕ) + (htarget : ∑ v ∈ E8, ∑ w ∈ E8, Mty D dirs L v w + + ((n : ℤ) - 8) * (∑ v ∈ E8, Mty D dirs L v 4 + ∑ w ∈ E8, Mty D dirs L 4 w) + + ((n : ℤ) - 8) * ((n : ℤ) - 8) * Mty D dirs L 4 4 = D * target) : + tm dirs n S ≤ target := by + have hk := key hS D dirs (Gc n L) + (fun d c => by unfold Gc Gt; split_ifs <;> positivity) + (fun d c h => by + unfold Gc Gt at h + split_ifs at h with hc + · simp only [Bool.and_eq_true] at hc + exact ⟨inB_iff.mp hc.1, inB_iff.mp hc.2⟩ + · exact absurd rfl h) + (fun d hd c hc hc' => by + rw [Gc_one hn L hc (hdirs d hd), Gc_zero hn L hc hc'] + have h1 := hchk + unfold checkTy at h1 + rw [List.all_eq_true] at h1 + have h3 := h1 d hd + have hm := (memBZ_shift hn hc (hdirs d hd) (-1) (Or.inr rfl)).mp hc' + simp only [neg_one_mul] at hm + have hc2 := mem_BZ.mp hc + rw [List.all_eq_true] at h3 + have h4 := h3 (cls4 n c.1) (List.mem_range.mpr (by + have := cls4_le n c.1 hc2.1 hc2.2.1; omega)) + rw [List.all_eq_true] at h4 + have h5 := h4 (cls4 n c.2) (List.mem_range.mpr (by + have := cls4_le n c.2 hc2.2.2.1 hc2.2.2.2; omega)) + simp only [Bool.or_eq_true, Bool.not_eq_true', decide_eq_true_eq] at h5 + rcases h5 with h5 | h5 + · rw [hm] at h5; exact absurd h5 (by simp) + · exact h5) + have hle : ∑ c ∈ BZ n, (if c ∈ SZ S then Bf dirs (Gc n L) c else Af n D dirs (Gc n L) c) ≤ + ∑ c ∈ BZ n, Mty D dirs L (cls4 n c.1) (cls4 n c.2) := by + apply Finset.sum_le_sum + intro c hc + rw [Af_ty hn D dirs hdirs L hc, Bf_ty hn dirs hdirs L hc, Mty] + split_ifs + · exact le_max_right _ _ + · exact le_max_left _ _ + have hsum : ∑ i ∈ Finset.range n, ∑ j ∈ Finset.range n, + Mty D dirs L (cls4 n (i : ℤ)) (cls4 n (j : ℤ)) = D * target := by + have : ∀ i ∈ Finset.range n, ∑ j ∈ Finset.range n, Mty D dirs L (cls4 n (i : ℤ)) + (cls4 n (j : ℤ)) = ∑ w ∈ E8, Mty D dirs L (cls4 n (i : ℤ)) w + + ((n : ℤ) - 8) * Mty D dirs L (cls4 n (i : ℤ)) 4 := fun i _ => + sum_cls4 hn (fun w => Mty D dirs L (cls4 n (i : ℤ)) w) + rw [Finset.sum_congr rfl this, sum_cls4 hn (fun v => ∑ w ∈ E8, Mty D dirs L v w + + ((n : ℤ) - 8) * Mty D dirs L v 4), ← htarget, Finset.sum_add_distrib, ← Finset.mul_sum] + ring + have hsum2 : ∑ c ∈ BZ n, Mty D dirs L (cls4 n c.1) (cls4 n c.2) = D * target := by + rw [sum_BZ]; exact hsum + have : D * (tm dirs n S : ℤ) ≤ D * target := by linarith + have := le_of_mul_le_mul_left this hD + omega + + + +/-! ### The table for queens -/ + +/-- Flow table for queens (in half units), by position classes. -/ +private def LQ : List (ℕ × ℕ × ℤ × ℤ × ℕ) := + [(1, 1, -1, 1, 1), (1, 1, 0, 1, 4), (1, 1, 1, -1, 1), (1, 1, 1, 0, 4), (1, 1, 1, 1, 6), (1, 2, -1, 1, 1), (1, 2, 0, 1, 2), (1, 2, 1, -1, 3), (1, 2, 1, 0, 4), (1, 2, 1, 1, 6), (1, 3, -1, -1, 1), (1, 3, -1, 1, 1), (1, 3, 1, -1, 5), (1, 3, 1, 0, 4), (1, 3, 1, 1, 5), (1, 4, -1, -1, 1), (1, 4, 0, -1, 2), (1, 4, 1, -1, 6), (1, 4, 1, 0, 4), (1, 4, 1, 1, 3), (1, 5, -1, -1, 1), (1, 5, 0, -1, 4), (1, 5, 1, -1, 6), (1, 5, 1, 0, 4), (1, 5, 1, 1, 1), (2, 1, -1, 1, 3), (2, 1, 0, 1, 4), (2, 1, 1, -1, 1), (2, 1, 1, 0, 2), (2, 1, 1, 1, 6), (2, 2, -1, 1, 3), (2, 2, 0, 1, 2), (2, 2, 1, -1, 3), (2, 2, 1, 0, 2), (2, 2, 1, 1, 4), (2, 3, -1, -1, 2), (2, 3, -1, 1, 2), (2, 3, 1, -1, 4), (2, 3, 1, 0, 2), (2, 3, 1, 1, 4), (2, 4, -1, -1, 3), (2, 4, 0, -1, 2), (2, 4, 1, -1, 4), (2, 4, 1, 0, 2), (2, 4, 1, 1, 3), (2, 5, -1, -1, 3), (2, 5, 0, -1, 4), (2, 5, 1, -1, 6), (2, 5, 1, 0, 2), (2, 5, 1, 1, 1), (3, 1, -1, -1, 1), (3, 1, -1, 1, 5), (3, 1, 0, 1, 4), (3, 1, 1, -1, 1), (3, 1, 1, 1, 5), (3, 2, -1, -1, 2), (3, 2, -1, 1, 4), (3, 2, 0, 1, 2), (3, 2, 1, -1, 2), (3, 2, 1, 1, 4), (3, 3, -1, -1, 2), (3, 3, -1, 1, 2), (3, 3, 1, -1, 2), (3, 3, 1, 1, 2), (3, 4, -1, -1, 4), (3, 4, -1, 1, 2), (3, 4, 0, -1, 2), (3, 4, 1, -1, 4), (3, 4, 1, 1, 2), (3, 5, -1, -1, 5), (3, 5, -1, 1, 1), (3, 5, 0, -1, 4), (3, 5, 1, -1, 5), (3, 5, 1, 1, 1), (4, 1, -1, -1, 1), (4, 1, -1, 0, 2), (4, 1, -1, 1, 6), (4, 1, 0, 1, 4), (4, 1, 1, 1, 3), (4, 2, -1, -1, 3), (4, 2, -1, 0, 2), (4, 2, -1, 1, 4), (4, 2, 0, 1, 2), (4, 2, 1, 1, 3), (4, 3, -1, -1, 4), (4, 3, -1, 0, 2), (4, 3, -1, 1, 4), (4, 3, 1, -1, 2), (4, 3, 1, 1, 2), (4, 4, -1, -1, 4), (4, 4, -1, 0, 2), (4, 4, -1, 1, 3), (4, 4, 0, -1, 2), (4, 4, 1, -1, 3), (4, 5, -1, -1, 6), (4, 5, -1, 0, 2), (4, 5, -1, 1, 1), (4, 5, 0, -1, 4), (4, 5, 1, -1, 3), (5, 1, -1, -1, 1), (5, 1, -1, 0, 4), (5, 1, -1, 1, 6), (5, 1, 0, 1, 4), (5, 1, 1, 1, 1), (5, 2, -1, -1, 3), (5, 2, -1, 0, 4), (5, 2, -1, 1, 6), (5, 2, 0, 1, 2), (5, 2, 1, 1, 1), (5, 3, -1, -1, 5), (5, 3, -1, 0, 4), (5, 3, -1, 1, 5), (5, 3, 1, -1, 1), (5, 3, 1, 1, 1), (5, 4, -1, -1, 6), (5, 4, -1, 0, 4), (5, 4, -1, 1, 3), (5, 4, 0, -1, 2), (5, 4, 1, -1, 1), (5, 5, -1, -1, 6), (5, 5, -1, 0, 4), (5, 5, -1, 1, 1), (5, 5, 0, -1, 4), (5, 5, 1, -1, 1)] +/-- Queen directions are unit steps. -/ +private lemma queenDirs_unit : ∀ d ∈ queenDirs, unitDir d := by + simp [queenDirs, unitDir] + +/-- Casting the targets `k (n - 2)²` to `ℤ`. -/ +private lemma cast_target (n : ℕ) (hn : 2 ≤ n) (k : ℕ) : + ((k * (n - 2) ^ 2 : ℕ) : ℤ) = k * ((n : ℤ) - 8 + 6) ^ 2 := by + push_cast [Nat.cast_sub hn] + ring + +/-- Queens, `n ≥ 8`. -/ +private theorem queen_ge8 {n : ℕ} (hn : 8 ≤ n) {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) : + tm queenDirs n S ≤ 8 * (n - 2) ^ 2 := by + have c0 : ∑ v ∈ E8, ∑ w ∈ E8, Mty 2 queenDirs LQ v w = 576 := by decide +kernel + have c1 : ∑ v ∈ E8, Mty 2 queenDirs LQ v 4 + ∑ w ∈ E8, Mty 2 queenDirs LQ 4 w = 192 := by + decide +kernel + have c2 : Mty 2 queenDirs LQ 4 4 = 16 := by decide +kernel + refine general hn hS 2 (by norm_num) queenDirs queenDirs_unit LQ (by decide +kernel) _ ?_ + rw [c0, c1, c2, cast_target n (by omega)] + ring + +/-- Queens, `n = 7`, with the same table. -/ +private theorem queen7 {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 7) : + tm queenDirs 7 S ≤ 200 := + leaf hS 2 (by norm_num) queenDirs (fun d c => tabC LQ (cls3 7 c.1) (cls3 7 c.2) d) [] [] 200 + (by decide +kernel) (by decide +kernel) (by simp) (by simp) + + +/-! ### The border placement -/ + +/-- Membership in the border placement. -/ +private lemma mem_SZ_border {n : ℕ} {c : ℤ × ℤ} : + c ∈ SZ (border n) ↔ c ∈ BZ n ∧ (c.1 = 0 ∨ c.1 = n - 1 ∨ c.2 = 0 ∨ c.2 = n - 1) := by + constructor + · intro h + simp only [SZ, Finset.mem_map, border, Finset.mem_filter] at h + obtain ⟨p, ⟨hp, hb⟩, rfl⟩ := h + refine ⟨Finset.mem_map_of_mem emb hp, ?_⟩ + simp only [board, Finset.mem_product, Finset.mem_range] at hp + simp only [emb_apply] + omega + · rintro ⟨h1, h2⟩ + have h1' := mem_BZ.mp h1 + rw [mem_SZ h1'.1 h1'.2.2.1] + simp only [border, Finset.mem_filter, board, Finset.mem_product, Finset.mem_range] + omega + +/-- The interior squares. -/ +private def intr (n : ℕ) (c : ℤ × ℤ) : Prop := + 1 ≤ c.1 ∧ c.1 ≤ (n : ℤ) - 2 ∧ 1 ≤ c.2 ∧ c.2 ≤ (n : ℤ) - 2 + +/-- Interior squares are decidable. -/ +private instance (n : ℕ) : DecidablePred (intr n) := fun c => by unfold intr; infer_instance + +/-- For the border placement the empty squares are exactly the interior squares. -/ +private lemma E_border {n : ℕ} {c : ℤ × ℤ} : E n (border n) c ↔ intr n c := by + unfold E intr + rw [mem_SZ_border, mem_BZ] + omega + +/-- For the border placement every interior square is reached from every direction. -/ +private lemma Y_border {n : ℕ} {d c : ℤ × ℤ} (hd : unitDir d) (hd0 : d ≠ (0, 0)) : + Y n (border n) d c = if intr n c then 1 else 0 := by + split_ifs with hc + · apply le_antisymm (Y_le_one _ _ _ _) + obtain ⟨d1, d2, d3, d4⟩ := hd + have hc' := hc + obtain ⟨c1, c2, c3, c4⟩ := hc' + have hex : ∃ m : ℕ, ¬ intr n (sh c d (-((m : ℤ) + 1))) := by + refine ⟨n - 3, fun h => ?_⟩ + obtain ⟨e1, e2, e3, e4⟩ := h + simp only [sh] at e1 e2 e3 e4 + push_cast [Nat.cast_sub (show 3 ≤ n by omega)] at e1 e2 e3 e4 + have : d.1 ≠ 0 ∨ d.2 ≠ 0 := by + by_contra hh; push Not at hh; exact hd0 (Prod.ext hh.1 hh.2) + rcases this with h | h + · rcases (show d.1 = 1 ∨ d.1 = -1 by omega) with h' | h' <;> rw [h'] at e1 e2 <;> linarith + · rcases (show d.2 = 1 ∨ d.2 = -1 by omega) with h' | h' <;> rw [h'] at e3 e4 <;> linarith + classical + let k := Nat.find hex + have hk : ¬ intr n (sh c d (-((k : ℤ) + 1))) := Nat.find_spec hex + have hmin : ∀ j < k, intr n (sh c d (-((j : ℤ) + 1))) := fun j hj => by + have := Nat.find_min hex hj; push Not at this; simpa using this + have hkn : k ≤ n - 3 := Nat.find_min' hex (by + intro h + obtain ⟨e1, e2, e3, e4⟩ := h + simp only [sh] at e1 e2 e3 e4 + push_cast [Nat.cast_sub (show 3 ≤ n by omega)] at e1 e2 e3 e4 + have : d.1 ≠ 0 ∨ d.2 ≠ 0 := by + by_contra hh; push Not at hh; exact hd0 (Prod.ext hh.1 hh.2) + rcases this with h | h + · rcases (show d.1 = 1 ∨ d.1 = -1 by omega) with h' | h' <;> rw [h'] at e1 e2 <;> linarith + · rcases (show d.2 = 1 ∨ d.2 = -1 by omega) with h' | h' <;> rw [h'] at e3 e4 <;> linarith) + -- all squares before the stop are interior + have hall : ∀ j < k + 1, intr n (sh c d (-(j : ℤ))) := by + intro j hj + rcases j with _ | j + · simpa [sh_zero] using hc + · have := hmin j (by omega); push_cast; exact this + have hprev : intr n (sh c d (-(k : ℤ))) := hall k (by omega) + have hstop : sh c d (-((k : ℤ) + 1)) ∈ SZ (border n) := by + rw [mem_SZ_border, mem_BZ] + obtain ⟨f1, f2, f3, f4⟩ := hprev + simp only [intr, sh, not_and_or, not_le] at hk f1 f2 f3 f4 ⊢ + constructor + · constructor <;> [skip; constructor] <;> [skip; skip; constructor] <;> nlinarith + · rcases hk with h | h | h | h + · left; nlinarith + · right; left; nlinarith + · right; right; left; nlinarith + · right; right; right; nlinarith + unfold Y + calc 1 = (if (sh c d (-((k : ℤ) + 1)) ∈ SZ (border n) ∧ + ∀ j < k + 1, E n (border n) (sh c d (-(j : ℤ)))) then 1 else 0) := by + rw [if_pos ⟨hstop, fun j hj => E_border.mpr (hall j hj)⟩] + _ ≤ _ := Finset.single_le_sum (f := fun k : ℕ => if (sh c d (-((k : ℤ) + 1)) ∈ + SZ (border n) ∧ ∀ j < k + 1, E n (border n) (sh c d (-(j : ℤ)))) then 1 else 0) + (fun _ _ => Nat.zero_le _) (Finset.mem_range.mpr (by omega)) + · exact Y_eq_zero_of_not_E (fun h => hc (E_border.mp h)) + +/-- There are `(n - 2)²` interior squares. -/ +private lemma count_interior {n : ℕ} (hn : 2 ≤ n) : + ∑ c ∈ BZ n, (if intr n c then 1 else 0 : ℕ) = (n - 2) ^ 2 := by + rw [BZ, Finset.sum_map, board, Finset.sum_product] + have h1 : ∀ i ∈ Finset.range n, ∑ j ∈ Finset.range n, + (if intr n (emb (i, j)) then 1 else 0 : ℕ) = + if 1 ≤ i ∧ i ≤ n - 2 then n - 2 else 0 := by + intro i hi + rw [Finset.mem_range] at hi + have : ∀ j ∈ Finset.range n, (if intr n (emb (i, j)) then 1 else 0 : ℕ) = + if (1 ≤ i ∧ i ≤ n - 2) ∧ (1 ≤ j ∧ j ≤ n - 2) then 1 else 0 := by + intro j hj + rw [Finset.mem_range] at hj + apply if_congr _ rfl rfl + simp only [intr, emb_apply] + omega + rw [Finset.sum_congr rfl this] + split_ifs with h + · simp only [h, true_and] + rw [Finset.sum_boole] + have : (Finset.range n).filter (fun j => 1 ≤ j ∧ j ≤ n - 2) = Finset.Icc 1 (n - 2) := by + ext j; simp only [Finset.mem_filter, Finset.mem_range, Finset.mem_Icc]; omega + rw [this, Nat.card_Icc]; simp + · simp [h] + rw [Finset.sum_congr rfl h1, Finset.sum_ite, Finset.sum_const_zero, add_zero, + Finset.sum_const, smul_eq_mul] + have : (Finset.range n).filter (fun i => 1 ≤ i ∧ i ≤ n - 2) = Finset.Icc 1 (n - 2) := by + ext j; simp only [Finset.mem_filter, Finset.mem_range, Finset.mem_Icc]; omega + rw [this, Nat.card_Icc, Nat.add_sub_cancel, sq] + +/-- Exchanging a sum over the pieces with a sum over the list of directions. -/ +private lemma sum_swap_list (S : Finset (ℕ × ℕ)) (L : List (ℤ × ℤ)) (f : ℕ × ℕ → ℤ × ℤ → ℕ) : + ∑ p ∈ S, (L.map (f p)).sum = (L.map fun d => ∑ p ∈ S, f p d).sum := by + induction L with + | nil => simp + | cons d L ih => simp [Finset.sum_add_distrib, ih] + +/-- The border placement has `#dirs · (n - 2)²` moves. -/ +private lemma total_border {n : ℕ} (hn : 2 ≤ n) (dirs : List (ℤ × ℤ)) + (hdirs : ∀ d ∈ dirs, unitDir d ∧ d ≠ (0, 0)) : + tm dirs n (border n) = dirs.length * (n - 2) ^ 2 := by + unfold tm + rw [sum_swap_list] + have : ∀ d ∈ dirs, ∑ p ∈ border n, rayMoves n (border n) p d = (n - 2) ^ 2 := by + intro d hd + rw [sum_ray_eq, ← count_interior hn] + apply Finset.sum_congr rfl + intro c _ + exact Y_border (hdirs d hd).1 (hdirs d hd).2 + rw [List.map_congr_left this] + simp + +/-- The border placement lies on the board. -/ +private lemma border_sub (n : ℕ) : border n ⊆ board n := Finset.filter_subset _ _ + + +/-! ### The `6 × 6` board -/ + +/-- Flow certificate 0 for the `6 × 6` board (leaf `In = [(0, 1), (1, 5), (4, 5)]`, `Out = []`). -/ +private def q6_t0 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 9), (1, 1, 1, 3, 6), (1, 1, 1, 4, 3), (1, 1, 2, 1, 7), (1, 1, 2, 2, 6), (1, 1, + 2, 4, 3), (1, 1, 3, 1, 5), (1, 1, 3, 2, 4), (1, 1, 3, 3, 3), (1, 1, 4, 1, 2), (1, 1, 4, 2, + 2), (1, 1, 4, 3, 1), (1, -1, 1, 1, 3), (1, -1, 1, 2, 6), (1, -1, 1, 3, 6), (1, -1, 1, 4, + 9), (1, -1, 2, 1, 3), (1, -1, 2, 2, 3), (1, -1, 2, 3, 6), (1, -1, 3, 2, 3), (1, -1, 3, 3, + 1), (1, -1, 3, 4, 6), (1, -1, 4, 3, 3), (1, -1, 4, 4, 3), (-1, 1, 1, 1, 3), (-1, 1, 1, 2, + 3), (-1, 1, 1, 3, 2), (-1, 1, 2, 1, 6), (-1, 1, 2, 2, 5), (-1, 1, 2, 3, 2), (-1, 1, 2, 4, + 2), (-1, 1, 3, 1, 8), (-1, 1, 3, 2, 5), (-1, 1, 3, 3, 5), (-1, 1, 3, 4, 3), (-1, 1, 4, 1, + 8), (-1, 1, 4, 2, 8), (-1, 1, 4, 3, 6), (-1, 1, 4, 4, 3), (-1, -1, 1, 3, 2), (-1, -1, 1, + 4, 3), (-1, -1, 2, 1, 1), (-1, -1, 2, 2, 3), (-1, -1, 2, 4, 5), (-1, -1, 3, 1, 2), (-1, + -1, 3, 2, 4), (-1, -1, 3, 3, 6), (-1, -1, 4, 0, 1), (-1, -1, 4, 1, 3), (-1, -1, 4, 2, 5), + (-1, -1, 4, 3, 7), (-1, -1, 4, 4, 9), (1, 0, 1, 2, 6), (1, 0, 1, 3, 6), (1, 0, 1, 4, 9), + (1, 0, 2, 2, 3), (1, 0, 2, 3, 3), (1, 0, 2, 4, 6), (1, 0, 3, 4, 3), (-1, 0, 2, 3, 1), (-1, + 0, 2, 4, 2), (-1, 0, 3, 1, 2), (-1, 0, 3, 2, 3), (-1, 0, 3, 3, 4), (-1, 0, 3, 4, 5), (-1, + 0, 4, 1, 5), (-1, 0, 4, 2, 6), (-1, 0, 4, 3, 7), (-1, 0, 4, 4, 8), (0, 1, 1, 1, 8), (0, 1, + 1, 2, 5), (0, 1, 1, 3, 2), (0, 1, 2, 1, 7), (0, 1, 2, 2, 4), (0, 1, 2, 3, 1), (0, 1, 3, 1, + 7), (0, 1, 3, 2, 4), (0, 1, 3, 3, 1), (0, 1, 4, 1, 6), (0, 1, 4, 2, 3), (0, 1, 5, 1, 1), + (0, -1, 2, 3, 3), (0, -1, 2, 4, 6), (0, -1, 3, 2, 1), (0, -1, 3, 3, 4), (0, -1, 3, 4, 7)] + +/-- Flow certificate 1 for the `6 × 6` board (leaf `In = [(0, 1), (1, 5)]`, `Out = [(4, 5)]`). -/ +private def q6_t1 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 6), (1, 1, 1, 3, 4), (1, 1, 1, 4, 2), (1, 1, 2, 1, 4), (1, 1, 2, 2, 4), (1, 1, + 2, 4, 2), (1, 1, 3, 1, 3), (1, 1, 3, 2, 2), (1, 1, 3, 3, 2), (1, 1, 4, 1, 2), (1, 1, 4, 2, + 1), (1, 1, 4, 5, 2), (1, -1, 1, 1, 2), (1, -1, 1, 2, 4), (1, -1, 1, 3, 4), (1, -1, 1, 4, + 6), (1, -1, 2, 1, 2), (1, -1, 2, 2, 2), (1, -1, 2, 3, 4), (1, -1, 3, 2, 2), (1, -1, 3, 4, + 2), (1, -1, 4, 4, 2), (1, -1, 5, 4, 2), (-1, 1, 1, 1, 2), (-1, 1, 1, 2, 2), (-1, 1, 2, 1, + 4), (-1, 1, 2, 2, 2), (-1, 1, 2, 3, 1), (-1, 1, 3, 1, 4), (-1, 1, 3, 2, 3), (-1, 1, 3, 3, + 2), (-1, 1, 3, 4, 2), (-1, 1, 4, 1, 5), (-1, 1, 4, 2, 4), (-1, 1, 4, 3, 4), (-1, 1, 4, 4, + 2), (-1, 1, 4, 5, 2), (-1, -1, 1, 2, 2), (-1, -1, 1, 3, 2), (-1, -1, 1, 4, 2), (-1, -1, 2, + 3, 4), (-1, -1, 2, 4, 4), (-1, -1, 3, 1, 2), (-1, -1, 3, 2, 2), (-1, -1, 3, 3, 2), (-1, + -1, 3, 4, 6), (-1, -1, 4, 0, 2), (-1, -1, 4, 1, 2), (-1, -1, 4, 2, 4), (-1, -1, 4, 3, 4), + (-1, -1, 4, 4, 4), (1, 0, 1, 2, 4), (1, 0, 1, 3, 4), (1, 0, 1, 4, 6), (1, 0, 2, 2, 2), (1, + 0, 2, 3, 2), (1, 0, 2, 4, 4), (1, 0, 3, 4, 2), (-1, 0, 3, 1, 2), (-1, 0, 3, 2, 2), (-1, 0, + 3, 3, 2), (-1, 0, 4, 0, 1), (-1, 0, 4, 1, 4), (-1, 0, 4, 2, 4), (-1, 0, 4, 3, 4), (-1, 0, + 4, 4, 2), (-1, 0, 4, 5, 2), (0, 1, 1, 1, 6), (0, 1, 1, 2, 4), (0, 1, 1, 3, 2), (0, 1, 2, + 1, 5), (0, 1, 2, 2, 3), (0, 1, 2, 3, 1), (0, 1, 3, 1, 4), (0, 1, 3, 2, 2), (0, 1, 4, 1, + 3), (0, 1, 4, 2, 1), (0, 1, 4, 5, 2), (0, -1, 2, 2, 2), (0, -1, 2, 3, 4), (0, -1, 2, 4, + 6), (0, -1, 3, 3, 2), (0, -1, 3, 4, 4), (0, -1, 4, 2, 2), (0, -1, 4, 3, 4), (0, -1, 4, 4, + 6)] + +/-- Flow certificate 2 for the `6 × 6` board (leaf `In = [(0, 1), (5, 4)]`, `Out = [(1, 5)]`). -/ +private def q6_t2 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 6), (1, 1, 1, 3, 3), (1, 1, 1, 4, 2), (1, 1, 1, 5, 2), (1, 1, 2, 1, 6), (1, 1, + 2, 2, 4), (1, 1, 2, 4, 1), (1, 1, 3, 1, 4), (1, 1, 3, 2, 4), (1, 1, 3, 3, 2), (1, 1, 4, 1, + 2), (1, 1, 4, 2, 2), (1, 1, 4, 3, 2), (1, 1, 5, 1, 2), (1, -1, 1, 1, 2), (1, -1, 1, 2, 4), + (1, -1, 1, 3, 3), (1, -1, 1, 4, 4), (1, -1, 2, 1, 2), (1, -1, 2, 2, 1), (1, -1, 2, 3, 2), + (1, -1, 2, 4, 6), (1, -1, 3, 3, 4), (1, -1, 3, 4, 4), (1, -1, 4, 2, 2), (1, -1, 4, 3, 2), + (1, -1, 4, 4, 2), (-1, 1, 1, 1, 2), (-1, 1, 1, 2, 2), (-1, 1, 1, 5, 2), (-1, 1, 2, 1, 4), + (-1, 1, 2, 2, 2), (-1, 1, 2, 3, 2), (-1, 1, 3, 1, 4), (-1, 1, 3, 2, 4), (-1, 1, 3, 4, 2), + (-1, 1, 4, 1, 6), (-1, 1, 4, 2, 2), (-1, 1, 4, 3, 4), (-1, 1, 4, 4, 2), (-1, -1, 0, 4, 2), + (-1, -1, 2, 2, 2), (-1, -1, 2, 3, 2), (-1, -1, 2, 4, 2), (-1, -1, 3, 1, 2), (-1, -1, 3, 3, + 4), (-1, -1, 3, 4, 4), (-1, -1, 4, 0, 2), (-1, -1, 4, 1, 2), (-1, -1, 4, 2, 4), (-1, -1, + 4, 4, 6), (1, 0, 1, 2, 5), (1, 0, 1, 3, 4), (1, 0, 1, 4, 3), (1, 0, 1, 5, 2), (1, 0, 2, 2, + 3), (1, 0, 2, 3, 2), (1, 0, 2, 4, 1), (1, 0, 3, 2, 1), (-1, 0, 3, 1, 2), (-1, 0, 3, 2, 2), + (-1, 0, 3, 3, 2), (-1, 0, 4, 1, 4), (-1, 0, 4, 2, 4), (-1, 0, 4, 3, 4), (0, 1, 1, 1, 4), + (0, 1, 1, 2, 2), (0, 1, 1, 5, 2), (0, 1, 2, 1, 4), (0, 1, 2, 2, 2), (0, 1, 3, 1, 4), (0, + 1, 3, 2, 2), (0, 1, 4, 1, 2), (0, -1, 1, 1, 1), (0, -1, 1, 2, 3), (0, -1, 1, 3, 5), (0, + -1, 1, 4, 7), (0, -1, 2, 2, 2), (0, -1, 2, 3, 4), (0, -1, 2, 4, 6), (0, -1, 3, 2, 2), (0, + -1, 3, 3, 4), (0, -1, 3, 4, 6), (0, -1, 4, 2, 2), (0, -1, 4, 3, 4), (0, -1, 4, 4, 6)] + +/-- Flow certificate 3 for the `6 × 6` board (leaf `In = [(0, 1)]`, `Out = [(1, 5), (5, 4)]`). -/ +private def q6_t3 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 6), (1, 1, 1, 3, 2), (1, 1, 1, 4, 2), (1, 1, 1, 5, 2), (1, 1, 2, 1, 4), (1, 1, + 2, 2, 4), (1, 1, 3, 1, 4), (1, 1, 3, 2, 2), (1, 1, 3, 3, 2), (1, 1, 4, 1, 2), (1, 1, 4, 2, + 2), (1, 1, 5, 4, 2), (1, -1, 1, 1, 2), (1, -1, 1, 2, 4), (1, -1, 1, 3, 4), (1, -1, 1, 4, + 4), (1, -1, 2, 1, 2), (1, -1, 2, 2, 2), (1, -1, 2, 3, 2), (1, -1, 2, 4, 5), (1, -1, 3, 3, + 3), (1, -1, 3, 4, 2), (1, -1, 4, 2, 1), (1, -1, 4, 4, 2), (1, -1, 5, 4, 2), (-1, 1, 1, 1, + 2), (-1, 1, 1, 2, 1), (-1, 1, 1, 5, 2), (-1, 1, 2, 1, 3), (-1, 1, 2, 2, 2), (-1, 1, 3, 1, + 4), (-1, 1, 3, 2, 2), (-1, 1, 3, 3, 2), (-1, 1, 3, 4, 2), (-1, 1, 4, 1, 4), (-1, 1, 4, 2, + 4), (-1, 1, 4, 3, 4), (-1, 1, 4, 4, 2), (-1, 1, 4, 5, 2), (-1, -1, 0, 4, 2), (-1, -1, 1, + 0, 1), (-1, -1, 1, 3, 1), (-1, -1, 1, 4, 2), (-1, -1, 2, 1, 3), (-1, -1, 2, 3, 2), (-1, + -1, 2, 4, 3), (-1, -1, 3, 1, 1), (-1, -1, 3, 2, 5), (-1, -1, 3, 3, 2), (-1, -1, 3, 4, 4), + (-1, -1, 4, 0, 1), (-1, -1, 4, 1, 2), (-1, -1, 4, 2, 3), (-1, -1, 4, 3, 7), (-1, -1, 4, 4, + 4), (1, 0, 1, 2, 6), (1, 0, 1, 3, 4), (1, 0, 1, 4, 2), (1, 0, 1, 5, 2), (1, 0, 2, 2, 4), + (1, 0, 2, 3, 2), (1, 0, 3, 2, 2), (1, 0, 5, 4, 2), (-1, 0, 1, 5, 2), (-1, 0, 2, 3, 1), + (-1, 0, 2, 4, 2), (-1, 0, 3, 1, 2), (-1, 0, 3, 2, 2), (-1, 0, 3, 3, 3), (-1, 0, 3, 4, 4), + (-1, 0, 4, 0, 1), (-1, 0, 4, 1, 4), (-1, 0, 4, 2, 4), (-1, 0, 4, 3, 5), (-1, 0, 4, 4, 6), + (0, 1, 1, 1, 5), (0, 1, 1, 2, 3), (0, 1, 1, 3, 1), (0, 1, 1, 5, 2), (0, 1, 2, 1, 4), (0, + 1, 2, 2, 2), (0, 1, 3, 1, 5), (0, 1, 3, 2, 3), (0, 1, 3, 3, 1), (0, 1, 4, 1, 4), (0, 1, 4, + 2, 2), (0, 1, 5, 1, 1), (0, 1, 5, 4, 2), (0, -1, 1, 2, 2), (0, -1, 1, 3, 4), (0, -1, 1, 4, + 6), (0, -1, 2, 2, 2), (0, -1, 2, 3, 4), (0, -1, 2, 4, 6), (0, -1, 3, 3, 2), (0, -1, 3, 4, + 4), (0, -1, 4, 4, 2), (0, -1, 5, 4, 2)] + +/-- Flow certificate 4 for the `6 × 6` board (leaf `In = [(1, 5), (4, 0)]`, `Out = [(0, 1)]`). -/ +private def q6_t4 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 4), (1, 1, 1, 2, 6), (1, 1, 1, 3, 4), (1, 1, 1, 4, 2), (1, 1, 2, 1, 3), (1, 1, + 2, 2, 2), (1, 1, 2, 3, 4), (1, 1, 2, 4, 2), (1, 1, 3, 1, 4), (1, 1, 3, 2, 1), (1, 1, 3, 4, + 2), (1, 1, 4, 1, 2), (1, 1, 4, 2, 2), (1, -1, 1, 0, 2), (1, -1, 1, 2, 2), (1, -1, 1, 3, + 4), (1, -1, 1, 4, 6), (1, -1, 2, 2, 2), (1, -1, 2, 3, 4), (1, -1, 3, 2, 2), (1, -1, 3, 4, + 4), (1, -1, 4, 3, 2), (1, -1, 4, 4, 2), (1, -1, 5, 4, 2), (-1, 1, 0, 1, 2), (-1, 1, 1, 1, + 2), (-1, 1, 1, 2, 1), (-1, 1, 2, 1, 3), (-1, 1, 2, 3, 2), (-1, 1, 2, 4, 2), (-1, 1, 3, 2, + 4), (-1, 1, 3, 3, 4), (-1, 1, 3, 4, 2), (-1, 1, 4, 1, 6), (-1, 1, 4, 2, 6), (-1, 1, 4, 3, + 4), (-1, 1, 4, 4, 2), (-1, 1, 4, 5, 2), (-1, -1, 0, 1, 2), (-1, -1, 1, 3, 2), (-1, -1, 1, + 4, 2), (-1, -1, 2, 2, 2), (-1, -1, 2, 4, 4), (-1, -1, 3, 1, 2), (-1, -1, 3, 2, 2), (-1, + -1, 3, 3, 4), (-1, -1, 3, 4, 2), (-1, -1, 4, 1, 2), (-1, -1, 4, 2, 4), (-1, -1, 4, 3, 4), + (-1, -1, 4, 4, 6), (1, 0, 1, 1, 7), (1, 0, 1, 2, 6), (1, 0, 1, 3, 6), (1, 0, 1, 4, 6), (1, + 0, 2, 1, 5), (1, 0, 2, 2, 4), (1, 0, 2, 3, 4), (1, 0, 2, 4, 4), (1, 0, 3, 1, 3), (1, 0, 3, + 2, 2), (1, 0, 3, 3, 2), (1, 0, 3, 4, 2), (1, 0, 4, 1, 1), (-1, 0, 0, 1, 2), (-1, 0, 3, 1, + 2), (-1, 0, 3, 2, 2), (-1, 0, 3, 3, 2), (-1, 0, 4, 1, 4), (-1, 0, 4, 2, 4), (-1, 0, 4, 3, + 4), (-1, 0, 4, 4, 2), (0, 1, 0, 1, 2), (0, 1, 1, 1, 3), (0, 1, 1, 2, 1), (0, 1, 2, 1, 4), + (0, 1, 2, 2, 2), (0, 1, 3, 1, 5), (0, 1, 3, 2, 3), (0, 1, 3, 3, 1), (0, -1, 2, 3, 2), (0, + -1, 2, 4, 4), (0, -1, 3, 3, 2), (0, -1, 3, 4, 4), (0, -1, 4, 3, 2), (0, -1, 4, 4, 4)] + +/-- Flow certificate 5 for the `6 × 6` board (leaf `In = [(4, 0)]`, `Out = [(0, 1), (1, 5)]`). -/ +private def q6_t5 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 4), (1, 1, 1, 2, 6), (1, 1, 1, 3, 2), (1, 1, 1, 4, 2), (1, 1, 1, 5, 2), (1, 1, + 2, 1, 4), (1, 1, 2, 2, 2), (1, 1, 2, 3, 4), (1, 1, 3, 1, 4), (1, 1, 3, 2, 2), (1, 1, 3, 4, + 2), (1, 1, 4, 1, 2), (1, 1, 4, 2, 2), (1, -1, 1, 0, 2), (1, -1, 1, 1, 2), (1, -1, 1, 2, + 3), (1, -1, 1, 3, 3), (1, -1, 1, 4, 4), (1, -1, 2, 1, 1), (1, -1, 2, 2, 1), (1, -1, 2, 3, + 2), (1, -1, 2, 4, 6), (1, -1, 3, 3, 4), (1, -1, 3, 4, 3), (1, -1, 4, 2, 2), (1, -1, 4, 3, + 1), (1, -1, 4, 4, 2), (1, -1, 5, 4, 1), (-1, 1, 0, 1, 2), (-1, 1, 1, 1, 2), (-1, 1, 1, 5, + 2), (-1, 1, 2, 1, 2), (-1, 1, 2, 3, 1), (-1, 1, 3, 2, 3), (-1, 1, 3, 3, 2), (-1, 1, 3, 4, + 1), (-1, 1, 4, 1, 5), (-1, 1, 4, 2, 4), (-1, 1, 4, 3, 3), (-1, 1, 4, 4, 2), (-1, -1, 0, 1, + 2), (-1, -1, 0, 4, 2), (-1, -1, 1, 3, 2), (-1, -1, 1, 4, 2), (-1, -1, 2, 2, 2), (-1, -1, + 2, 3, 2), (-1, -1, 2, 4, 4), (-1, -1, 3, 1, 1), (-1, -1, 3, 2, 2), (-1, -1, 3, 3, 2), (-1, + -1, 3, 4, 4), (-1, -1, 4, 1, 2), (-1, -1, 4, 2, 3), (-1, -1, 4, 3, 4), (-1, -1, 4, 4, 4), + (1, 0, 1, 1, 6), (1, 0, 1, 2, 6), (1, 0, 1, 3, 5), (1, 0, 1, 4, 3), (1, 0, 1, 5, 2), (1, + 0, 2, 1, 4), (1, 0, 2, 2, 4), (1, 0, 2, 3, 3), (1, 0, 2, 4, 1), (1, 0, 3, 1, 2), (1, 0, 3, + 2, 2), (1, 0, 3, 3, 1), (-1, 0, 0, 1, 2), (-1, 0, 2, 1, 1), (-1, 0, 2, 2, 1), (-1, 0, 2, + 3, 1), (-1, 0, 3, 1, 3), (-1, 0, 3, 2, 3), (-1, 0, 3, 3, 3), (-1, 0, 3, 4, 2), (-1, 0, 4, + 1, 5), (-1, 0, 4, 2, 5), (-1, 0, 4, 3, 5), (-1, 0, 4, 4, 4), (-1, 0, 4, 5, 1), (0, 1, 0, + 1, 2), (0, 1, 1, 1, 2), (0, 1, 1, 5, 2), (0, 1, 2, 1, 4), (0, 1, 2, 2, 2), (0, 1, 3, 1, + 6), (0, 1, 3, 2, 4), (0, 1, 3, 3, 2), (0, 1, 5, 1, 1), (0, -1, 1, 2, 1), (0, -1, 1, 3, 3), + (0, -1, 1, 4, 5), (0, -1, 2, 2, 2), (0, -1, 2, 3, 3), (0, -1, 2, 4, 5), (0, -1, 3, 3, 2), + (0, -1, 3, 4, 4), (0, -1, 4, 3, 2), (0, -1, 4, 4, 4), (0, -1, 5, 4, 1)] + +/-- Flow certificate 6 for the `6 × 6` board (leaf `In = [(5, 4)]`, `Out = [(0, 1), (4, 0)]`). -/ +private def q6_t6 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 4), (1, 1, 1, 2, 6), (1, 1, 1, 3, 3), (1, 1, 1, 4, 2), (1, 1, 2, 1, 4), (1, 1, + 2, 2, 2), (1, 1, 2, 3, 4), (1, 1, 2, 4, 1), (1, 1, 3, 1, 3), (1, 1, 3, 2, 2), (1, 1, 3, 4, + 2), (1, 1, 4, 1, 2), (1, 1, 4, 2, 1), (1, 1, 5, 1, 2), (1, -1, 1, 0, 2), (1, -1, 1, 1, 2), + (1, -1, 1, 2, 4), (1, -1, 1, 3, 3), (1, -1, 1, 4, 3), (1, -1, 2, 1, 2), (1, -1, 2, 2, 1), + (1, -1, 2, 3, 1), (1, -1, 2, 4, 4), (1, -1, 3, 3, 2), (1, -1, 3, 4, 3), (1, -1, 4, 0, 2), + (1, -1, 4, 3, 1), (1, -1, 4, 4, 2), (-1, 1, 0, 1, 2), (-1, 1, 1, 1, 2), (-1, 1, 1, 3, 2), + (-1, 1, 2, 1, 2), (-1, 1, 2, 2, 4), (-1, 1, 3, 1, 6), (-1, 1, 3, 2, 2), (-1, 1, 3, 3, 2), + (-1, 1, 3, 4, 2), (-1, 1, 4, 1, 4), (-1, 1, 4, 2, 4), (-1, 1, 4, 3, 4), (-1, 1, 4, 4, 2), + (-1, -1, 0, 1, 2), (-1, -1, 0, 4, 1), (-1, -1, 1, 2, 1), (-1, -1, 1, 3, 2), (-1, -1, 1, 4, + 2), (-1, -1, 2, 2, 2), (-1, -1, 2, 3, 3), (-1, -1, 2, 4, 4), (-1, -1, 3, 3, 4), (-1, -1, + 3, 4, 5), (-1, -1, 4, 0, 2), (-1, -1, 4, 1, 2), (-1, -1, 4, 2, 2), (-1, -1, 4, 4, 6), (1, + 0, 1, 1, 5), (1, 0, 1, 2, 5), (1, 0, 1, 3, 4), (1, 0, 1, 4, 4), (1, 0, 1, 5, 1), (1, 0, 2, + 1, 3), (1, 0, 2, 2, 3), (1, 0, 2, 3, 2), (1, 0, 2, 4, 2), (1, 0, 3, 1, 1), (1, 0, 3, 2, + 2), (1, 0, 4, 0, 2), (-1, 0, 0, 1, 2), (-1, 0, 2, 3, 2), (-1, 0, 3, 2, 2), (-1, 0, 3, 3, + 4), (-1, 0, 4, 0, 2), (-1, 0, 4, 1, 2), (-1, 0, 4, 2, 4), (-1, 0, 4, 3, 6), (0, 1, 0, 1, + 2), (0, 1, 1, 1, 2), (0, 1, 2, 1, 5), (0, 1, 2, 2, 3), (0, 1, 2, 3, 1), (0, 1, 3, 1, 6), + (0, 1, 3, 2, 4), (0, 1, 3, 3, 2), (0, 1, 4, 1, 6), (0, 1, 4, 2, 4), (0, 1, 4, 3, 2), (0, + -1, 0, 4, 2), (0, -1, 1, 3, 2), (0, -1, 1, 4, 4), (0, -1, 2, 2, 1), (0, -1, 2, 3, 3), (0, + -1, 2, 4, 5), (0, -1, 3, 3, 2), (0, -1, 3, 4, 4), (0, -1, 4, 0, 2), (0, -1, 4, 2, 1), (0, + -1, 4, 3, 3), (0, -1, 4, 4, 5)] + +/-- Flow certificate 7 for the `6 × 6` board (leaf `In = []`, `Out = [(0, 1), (4, 0), (5, 4)]`). -/ +private def q6_t7 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 4), (1, 1, 1, 2, 6), (1, 1, 1, 3, 3), (1, 1, 1, 4, 2), (1, 1, 2, 1, 3), (1, 1, + 2, 2, 2), (1, 1, 2, 3, 4), (1, 1, 2, 4, 1), (1, 1, 3, 1, 4), (1, 1, 3, 2, 1), (1, 1, 3, 4, + 2), (1, 1, 4, 1, 2), (1, 1, 4, 2, 2), (1, 1, 5, 1, 2), (1, 1, 5, 4, 2), (1, -1, 1, 0, 2), + (1, -1, 1, 1, 2), (1, -1, 1, 2, 3), (1, -1, 1, 3, 4), (1, -1, 1, 4, 4), (1, -1, 2, 1, 1), + (1, -1, 2, 2, 2), (1, -1, 2, 3, 2), (1, -1, 2, 4, 4), (1, -1, 3, 2, 1), (1, -1, 3, 3, 2), + (1, -1, 3, 4, 2), (1, -1, 4, 0, 2), (1, -1, 4, 4, 2), (1, -1, 5, 4, 2), (-1, 1, 0, 1, 2), + (-1, 1, 1, 1, 2), (-1, 1, 1, 2, 1), (-1, 1, 1, 3, 2), (-1, 1, 2, 1, 3), (-1, 1, 2, 2, 4), + (-1, 1, 3, 1, 6), (-1, 1, 3, 2, 2), (-1, 1, 3, 3, 2), (-1, 1, 4, 1, 4), (-1, 1, 4, 2, 4), + (-1, 1, 4, 3, 2), (-1, 1, 4, 4, 2), (-1, 1, 4, 5, 2), (-1, -1, 0, 1, 2), (-1, -1, 0, 4, + 1), (-1, -1, 1, 4, 2), (-1, -1, 2, 1, 2), (-1, -1, 2, 3, 1), (-1, -1, 2, 4, 2), (-1, -1, + 3, 0, 1), (-1, -1, 3, 2, 4), (-1, -1, 3, 3, 2), (-1, -1, 3, 4, 3), (-1, -1, 4, 0, 2), (-1, + -1, 4, 1, 3), (-1, -1, 4, 2, 2), (-1, -1, 4, 3, 6), (-1, -1, 4, 4, 4), (1, 0, 1, 1, 5), + (1, 0, 1, 2, 5), (1, 0, 1, 3, 5), (1, 0, 1, 4, 4), (1, 0, 1, 5, 1), (1, 0, 2, 1, 3), (1, + 0, 2, 2, 3), (1, 0, 2, 3, 3), (1, 0, 2, 4, 2), (1, 0, 3, 1, 1), (1, 0, 3, 2, 1), (1, 0, 3, + 3, 1), (1, 0, 5, 4, 2), (-1, 0, 0, 1, 2), (-1, 0, 2, 2, 1), (-1, 0, 2, 3, 2), (-1, 0, 2, + 4, 1), (-1, 0, 3, 2, 3), (-1, 0, 3, 3, 4), (-1, 0, 3, 4, 3), (-1, 0, 4, 0, 2), (-1, 0, 4, + 1, 2), (-1, 0, 4, 2, 5), (-1, 0, 4, 3, 6), (-1, 0, 4, 4, 5), (0, 1, 0, 1, 2), (0, 1, 1, 1, + 3), (0, 1, 1, 2, 1), (0, 1, 2, 1, 4), (0, 1, 2, 2, 2), (0, 1, 3, 1, 4), (0, 1, 3, 2, 2), + (0, 1, 3, 3, 1), (0, 1, 4, 1, 5), (0, 1, 4, 2, 3), (0, 1, 4, 3, 1), (0, -1, 0, 4, 1), (0, + -1, 1, 3, 2), (0, -1, 1, 4, 4), (0, -1, 2, 2, 2), (0, -1, 2, 3, 4), (0, -1, 2, 4, 6), (0, + -1, 3, 2, 2), (0, -1, 3, 3, 4), (0, -1, 3, 4, 6), (0, -1, 4, 0, 2), (0, -1, 4, 3, 1), (0, + -1, 4, 4, 3), (0, -1, 5, 4, 2)] + +/-- Leaf 0 of the branch and bound tree for the `6 × 6` board. -/ +private lemma q6_leaf0 {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 6) + (hi0 : ((0, 1) : ℕ × ℕ) ∈ S) + (hi1 : ((1, 5) : ℕ × ℕ) ∈ S) + (hi2 : ((4, 5) : ℕ × ℕ) ∈ S) : + tm queenDirs 6 S ≤ 128 := + leaf hS 3 (by norm_num) queenDirs (tab q6_t0) [(0, 1), (1, 5), (4, 5)] [] 128 + (by decide +kernel) (by decide +kernel) (by simp [hi0, hi1, hi2]) (by simp) + +/-- Leaf 1 of the branch and bound tree for the `6 × 6` board. -/ +private lemma q6_leaf1 {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 6) + (hi0 : ((0, 1) : ℕ × ℕ) ∈ S) + (hi1 : ((1, 5) : ℕ × ℕ) ∈ S) + (ho0 : ((4, 5) : ℕ × ℕ) ∉ S) : + tm queenDirs 6 S ≤ 128 := + leaf hS 2 (by norm_num) queenDirs (tab q6_t1) [(0, 1), (1, 5)] [(4, 5)] 128 + (by decide +kernel) (by decide +kernel) (by simp [hi0, hi1]) (by simp [ho0]) + +/-- Leaf 2 of the branch and bound tree for the `6 × 6` board. -/ +private lemma q6_leaf2 {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 6) + (hi0 : ((0, 1) : ℕ × ℕ) ∈ S) + (hi1 : ((5, 4) : ℕ × ℕ) ∈ S) + (ho0 : ((1, 5) : ℕ × ℕ) ∉ S) : + tm queenDirs 6 S ≤ 128 := + leaf hS 2 (by norm_num) queenDirs (tab q6_t2) [(0, 1), (5, 4)] [(1, 5)] 128 + (by decide +kernel) (by decide +kernel) (by simp [hi0, hi1]) (by simp [ho0]) + +/-- Leaf 3 of the branch and bound tree for the `6 × 6` board. -/ +private lemma q6_leaf3 {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 6) + (hi0 : ((0, 1) : ℕ × ℕ) ∈ S) + (ho0 : ((1, 5) : ℕ × ℕ) ∉ S) + (ho1 : ((5, 4) : ℕ × ℕ) ∉ S) : + tm queenDirs 6 S ≤ 128 := + leaf hS 2 (by norm_num) queenDirs (tab q6_t3) [(0, 1)] [(1, 5), (5, 4)] 128 + (by decide +kernel) (by decide +kernel) (by simp [hi0]) (by simp [ho0, ho1]) + +/-- Leaf 4 of the branch and bound tree for the `6 × 6` board. -/ +private lemma q6_leaf4 {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 6) + (hi0 : ((1, 5) : ℕ × ℕ) ∈ S) + (hi1 : ((4, 0) : ℕ × ℕ) ∈ S) + (ho0 : ((0, 1) : ℕ × ℕ) ∉ S) : + tm queenDirs 6 S ≤ 128 := + leaf hS 2 (by norm_num) queenDirs (tab q6_t4) [(1, 5), (4, 0)] [(0, 1)] 128 + (by decide +kernel) (by decide +kernel) (by simp [hi0, hi1]) (by simp [ho0]) + +/-- Leaf 5 of the branch and bound tree for the `6 × 6` board. -/ +private lemma q6_leaf5 {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 6) + (hi0 : ((4, 0) : ℕ × ℕ) ∈ S) + (ho0 : ((0, 1) : ℕ × ℕ) ∉ S) + (ho1 : ((1, 5) : ℕ × ℕ) ∉ S) : + tm queenDirs 6 S ≤ 128 := + leaf hS 2 (by norm_num) queenDirs (tab q6_t5) [(4, 0)] [(0, 1), (1, 5)] 128 + (by decide +kernel) (by decide +kernel) (by simp [hi0]) (by simp [ho0, ho1]) + +/-- Leaf 6 of the branch and bound tree for the `6 × 6` board. -/ +private lemma q6_leaf6 {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 6) + (hi0 : ((5, 4) : ℕ × ℕ) ∈ S) + (ho0 : ((0, 1) : ℕ × ℕ) ∉ S) + (ho1 : ((4, 0) : ℕ × ℕ) ∉ S) : + tm queenDirs 6 S ≤ 128 := + leaf hS 2 (by norm_num) queenDirs (tab q6_t6) [(5, 4)] [(0, 1), (4, 0)] 128 + (by decide +kernel) (by decide +kernel) (by simp [hi0]) (by simp [ho0, ho1]) + +/-- Leaf 7 of the branch and bound tree for the `6 × 6` board. -/ +private lemma q6_leaf7 {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 6) + (ho0 : ((0, 1) : ℕ × ℕ) ∉ S) + (ho1 : ((4, 0) : ℕ × ℕ) ∉ S) + (ho2 : ((5, 4) : ℕ × ℕ) ∉ S) : + tm queenDirs 6 S ≤ 128 := + leaf hS 2 (by norm_num) queenDirs (tab q6_t7) [] [(0, 1), (4, 0), (5, 4)] 128 + (by decide +kernel) (by decide +kernel) (by simp) (by simp [ho0, ho1, ho2]) + +/-- Upper bound for queens on the `6 × 6` board: branch and bound on the squares `(0, 1)`, +`(1, 5)`, `(4, 5)`, `(5, 4)`, `(4, 0)`, with a flow certificate at each of the eight leaves. -/ +private theorem queen6_le {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 6) : + tm queenDirs 6 S ≤ 128 := by + by_cases h0 : ((0, 1) : ℕ × ℕ) ∈ S + · by_cases h1 : ((1, 5) : ℕ × ℕ) ∈ S + · by_cases h2 : ((4, 5) : ℕ × ℕ) ∈ S + · exact q6_leaf0 hS h0 h1 h2 + · exact q6_leaf1 hS h0 h1 h2 + · by_cases h2 : ((5, 4) : ℕ × ℕ) ∈ S + · exact q6_leaf2 hS h0 h2 h1 + · exact q6_leaf3 hS h0 h1 h2 + · by_cases h1 : ((4, 0) : ℕ × ℕ) ∈ S + · by_cases h2 : ((1, 5) : ℕ × ℕ) ∈ S + · exact q6_leaf4 hS h2 h1 h0 + · exact q6_leaf5 hS h1 h0 h2 + · by_cases h2 : ((5, 4) : ℕ × ℕ) ∈ S + · exact q6_leaf6 hS h2 h0 h1 + · exact q6_leaf7 hS h0 h1 h2 + +/-! ### Conclusion -/ + +/-- Upper bounds for `a`. -/ +private lemma a_le {n X : ℕ} (h : ∀ S ⊆ board n, tm queenDirs n S ≤ X) : a n ≤ X := + Finset.sup_le fun S hS => (totalMoves_eq n S).trans_le (h S (Finset.mem_powerset.mp hS)) + +/-- Lower bound for `a` from the border placement. -/ +private lemma a_border {n : ℕ} (hn : 2 ≤ n) : 8 * (n - 2) ^ 2 ≤ a n := by + have h := Finset.le_sup (f := totalMoves n) (Finset.mem_powerset.mpr (border_sub n)) + rw [totalMoves_eq, total_border hn queenDirs (by simp [queenDirs, unitDir])] at h + exact h + +/-- Jones's conjecture holds: `a(n) = 8 (n - 2)²` for every `n ≥ 6`. -/ +theorem result : statement := by + intro n hn + obtain rfl | rfl | h8 : n = 6 ∨ n = 7 ∨ 8 ≤ n := by omega + · exact le_antisymm ((a_le fun S hS => queen6_le hS).trans_eq (by norm_num)) + (a_border (by norm_num)) + · exact le_antisymm ((a_le fun S hS => queen7 hS).trans_eq (by norm_num)) + (a_border (by norm_num)) + · exact le_antisymm (a_le fun S hS => queen_ge8 h8 hS) (a_border (by omega)) + +end Math0.Frontier.A275815 + +#math0_settles Math0.Frontier.A275815.result Math0.Statements.A275815.statement diff --git a/lean/Math0/Frontier/OEIS/A278212.lean b/lean/Math0/Frontier/OEIS/A278212.lean new file mode 100644 index 0000000..0671ffb --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A278212.lean @@ -0,0 +1,1476 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A278212 +import Math0.Audit + +/-! +# A278212: Kagey's conjecture `a(n) = ⌊A275815(n) / 2⌋` holds + +We determine both maxima exactly, up to one unit for queens on the `6 × 6` board: + +* bishops: `a 4 = 20`, `a 5 = 38` and `a n = 4 (n - 2)²` for `n ≥ 6`; +* queens: `queenMax 4 ∈ {40, 41}`, `queenMax 5 ∈ {76, 77}`, `queenMax 6 ∈ {128, 129}` and + `queenMax n = 8 (n - 2)²` for `n ≥ 7` (this also proves Alec Jones's conjecture on A275815 + for `n ≥ 7`). + +Together with the listed values for `n ≤ 3` this gives `a n = queenMax n / 2` for all `n ≥ 1`. + +**Lower bounds.** On the border placement every interior square is empty and sees a piece in +each of the directions, so the number of moves is `#dirs · (n - 2)²`. + +**Upper bounds: a flow (linear programming dual) argument.** Fix a moving direction `d`. +The moves in direction `d` are in bijection with the empty squares `c` that "see" a piece +behind them, i.e. `c - k • d` is a piece and `c, c - d, …, c - (k-1) • d` are empty +(`sum_ray_eq`). The indicator `Y c` of this satisfies `Y c ≤ 1 - x c` and +`Y c ≤ x (c - d) + Y (c - d)`, where `x` is the occupancy indicator. Let `G c ≥ 0` be a +"flow" from `c` to `c - d` (zero unless both are on the board) with +`α c := D + G (c + d) - G c ≥ 0`. Combining the two inequalities with weights `α c` and `G c` +gives `D Y c + G (c + d) Y c ≤ α c (1 - x c) + G c x (c - d) + G c Y (c - d)`; summing over +the board, the flow terms telescope (`dir_ineq`). Summing over the directions (`key`): +`D · totalMoves ≤ ∑ c, (if c is occupied then B c else A c)` with +`A c = ∑_d α_d c` and `B c = ∑_d G_d (c + d)`, hence `≤ ∑ c, max (A c) (B c)`. + +The flows were found by linear programming. For `n ≥ 7` (queens, `D = 2`) and `n ≥ 6` +(bishops, `D = 1`) the flow of a square only depends on its position class (distance to each +side, cut off at `3`; tables `LQ`, `LB`). For `n ≥ 8`, `A c` and `B c` then only depend on the +position class with cut-off `4`; a kernel computation over the `9 × 9` classes checks +`α ≥ 0` and evaluates the constants, and a counting lemma (`sum_cls4`) gives +`∑ c, max (A c) (B c) = D · 8 (n - 2)²`, resp. `D · 4 (n - 2)²` (`general`). The boards with +`n = 6, 7` are checked directly. For the small boards (`n = 4, 5, 6` for queens, `n = 4, 5` for +bishops) the linear relaxation is not tight; there we split into cases on a few squares (a +branch and bound tree with at most ten leaves) and close every leaf by its own flow +certificate, again checked by the kernel (`leaf`). +-/ + +namespace Math0.Frontier.A278212 +open Math0.Statements.A278212 + +/-- The embedding of `ℕ × ℕ` into `ℤ × ℤ`. -/ +private def emb : ℕ × ℕ ↪ ℤ × ℤ := + ⟨fun p => ((p.1 : ℤ), (p.2 : ℤ)), fun a b h => by + simp only [Prod.mk.injEq, Nat.cast_inj] at h; exact Prod.ext h.1 h.2⟩ + +@[simp] private lemma emb_apply (p : ℕ × ℕ) : emb p = ((p.1 : ℤ), (p.2 : ℤ)) := rfl + +/-- The board as a set of integer points. -/ +private def BZ (n : ℕ) : Finset (ℤ × ℤ) := (board n).map emb + +/-- A placement as a set of integer points. -/ +private def SZ (S : Finset (ℕ × ℕ)) : Finset (ℤ × ℤ) := S.map emb + +/-- Membership in the integer board. -/ +private lemma mem_BZ {n : ℕ} {c : ℤ × ℤ} : + c ∈ BZ n ↔ 0 ≤ c.1 ∧ c.1 < n ∧ 0 ≤ c.2 ∧ c.2 < n := by + constructor + · intro h + simp only [BZ, Finset.mem_map, board, Finset.mem_product, Finset.mem_range] at h + obtain ⟨p, ⟨h1, h2⟩, rfl⟩ := h + simp only [emb_apply] + omega + · rintro ⟨h1, h2, h3, h4⟩ + simp only [BZ, Finset.mem_map, board, Finset.mem_product, Finset.mem_range] + refine ⟨(c.1.toNat, c.2.toNat), ⟨by omega, by omega⟩, ?_⟩ + simp only [emb_apply] + ext <;> simp <;> omega + +/-- Membership in the integer placement, for nonnegative points. -/ +private lemma mem_SZ {S : Finset (ℕ × ℕ)} {c : ℤ × ℤ} (h1 : 0 ≤ c.1) (h2 : 0 ≤ c.2) : + c ∈ SZ S ↔ (c.1.toNat, c.2.toNat) ∈ S := by + constructor + · intro h + simp only [SZ, Finset.mem_map] at h + obtain ⟨p, hp, rfl⟩ := h + simpa using hp + · intro h + simp only [SZ, Finset.mem_map] + refine ⟨_, h, ?_⟩ + simp only [emb_apply] + ext <;> simp <;> omega + +/-- A placement on the board stays on the board as a set of integer points. -/ +private lemma SZ_sub_BZ {n : ℕ} {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) : SZ S ⊆ BZ n := + Finset.map_subset_map.mpr hS + +/-- The empty squares of the board. -/ +private abbrev E (n : ℕ) (S : Finset (ℕ × ℕ)) (c : ℤ × ℤ) : Prop := c ∈ BZ n ∧ c ∉ SZ S + +/-- `isEmptySquare` in terms of `BZ` and `SZ`. -/ +private lemma isEmpty_iff {n : ℕ} {S : Finset (ℕ × ℕ)} {x y : ℤ} : + isEmptySquare n S x y = true ↔ E n S (x, y) := by + simp only [isEmptySquare, decide_eq_true_eq, E, mem_BZ] + constructor + · rintro ⟨h1, h2, h3, h4, h5⟩ + exact ⟨⟨h1, h2, h3, h4⟩, fun h => h5 ((mem_SZ h1 h3).mp h)⟩ + · rintro ⟨⟨h1, h2, h3, h4⟩, h5⟩ + exact ⟨h1, h2, h3, h4, fun h => h5 ((mem_SZ h1 h3).mpr h)⟩ + +/-- Length of `takeWhile` on `range'` as a count of good prefixes. -/ +private lemma tw_len (P : ℕ → Bool) (m s : ℕ) : + ((List.range' s m).takeWhile P).length = + ∑ k ∈ Finset.range m, if (∀ j < k + 1, P (s + j) = true) then 1 else 0 := by + induction m generalizing s with + | zero => simp + | succ m ih => + rw [List.range'_succ, List.takeWhile_cons, Finset.sum_range_succ'] + by_cases hs : P s = true + · have h0 : (∀ j < 0 + 1, P (s + j) = true) := by + intro j hj; obtain rfl : j = 0 := by omega + simpa using hs + rw [if_pos hs, List.length_cons, ih (s + 1), if_pos h0] + congr 1 + apply Finset.sum_congr rfl + intro k _ + apply if_congr _ rfl rfl + constructor + · intro h j hj + rcases j with _ | j + · simpa using hs + · have := h j (by omega); rwa [show s + 1 + j = s + (j + 1) by ring] at this + · intro h j hj; have := h (j + 1) (by omega); rwa [show s + (j + 1) = s + 1 + j by ring] at this + · have h0 : ¬ (∀ j < 0 + 1, P (s + j) = true) := fun h => hs (by simpa using h 0 (by omega)) + rw [if_neg hs, if_neg h0, List.length_nil, add_zero] + symm + apply Finset.sum_eq_zero + intro k _ + rw [if_neg] + intro h; exact hs (by simpa using h 0 (by omega)) + +/-- The point `c + t • d`. -/ +private def sh (c d : ℤ × ℤ) (t : ℤ) : ℤ × ℤ := (c.1 + t * d.1, c.2 + t * d.2) + +/-- The coercion of a list of naturals to a list of integers is a `map`. -/ +private lemma bind_pure_cast (l : List ℕ) : + (l >>= fun (a : ℕ) => (pure (a : ℤ) : List ℤ)) = l.map (fun a : ℕ => (a : ℤ)) := by + induction l with + | nil => rfl + | cons a l ih => simp_all + +/-- `rayMoves` counts the `k < n` such that the first `k + 1` squares of the ray are empty. -/ +private lemma rayMoves_eq (n : ℕ) (S : Finset (ℕ × ℕ)) (p : ℕ × ℕ) (d : ℤ × ℤ) : + rayMoves n S p d = ∑ k ∈ Finset.range n, + if (∀ j < k + 1, E n S (sh (emb p) d (1 + j))) then 1 else 0 := by + rw [rayMoves, bind_pure_cast, List.takeWhile_map, List.length_map, tw_len] + apply Finset.sum_congr rfl + intro k _ + apply if_congr _ rfl rfl + apply forall_congr'; intro j; apply imp_congr_right; intro _ + simp only [Function.comp_apply, isEmpty_iff, sh, emb_apply] + push_cast + rfl + +/-- `Y n S d c = 1` iff `c` is an empty square reached by a piece moving in direction `d`. -/ +private def Y (n : ℕ) (S : Finset (ℕ × ℕ)) (d c : ℤ × ℤ) : ℕ := + ∑ k ∈ Finset.range n, + if (sh c d (-(k + 1)) ∈ SZ S ∧ ∀ j < k + 1, E n S (sh c d (-j))) then 1 else 0 + +/-- Composition of shifts along `d`. -/ +private lemma sh_sh (c d : ℤ × ℤ) (s t : ℤ) : sh (sh c d s) d t = sh c d (s + t) := by + simp only [sh]; ext <;> simp <;> ring + +/-- The zero shift. -/ +private lemma sh_zero (c d : ℤ × ℤ) : sh c d 0 = c := by simp [sh] + +/-- Double counting: total moves in direction `d` = number of reached empty squares. -/ +private lemma sum_ray_eq (n : ℕ) (S : Finset (ℕ × ℕ)) (d : ℤ × ℤ) : + ∑ p ∈ S, rayMoves n S p d = ∑ c ∈ BZ n, Y n S d c := by + simp only [rayMoves_eq, Y] + rw [← Finset.sum_map S emb (fun q => ∑ k ∈ Finset.range n, + if (∀ j < k + 1, E n S (sh q d (1 + j))) then 1 else 0)] + rw [Finset.sum_comm, Finset.sum_comm (s := BZ n)] + apply Finset.sum_congr rfl + intro k _ + apply Finset.sum_bij_ne_zero (fun q _ _ => sh q d (k + 1)) + · intro q hq hne + have h := (by simpa using hne : ∀ j < k + 1, E n S (sh q d (1 + j))) + have := (h k (by omega)).1 + rwa [show (1 : ℤ) + (k : ℕ) = (k : ℤ) + 1 by ring] at this + · intro q1 _ _ q2 _ _ h + have := congrArg (fun c => sh c d (-(k + 1))) h + simpa [sh_sh, sh_zero] using this + · intro c hc hne + have h := (by simpa using hne : sh c d (-(k + 1)) ∈ SZ S ∧ + ∀ j < k + 1, E n S (sh c d (-j))) + refine ⟨sh c d (-(k + 1)), h.1, ?_, by simp [sh_sh, sh_zero]⟩ + rw [if_pos] + · exact one_ne_zero + intro j hj + have := h.2 (k - j) (by omega) + rw [sh_sh] + convert this using 2 + push_cast [Nat.cast_sub (by omega : j ≤ k)] + ring + · intro q hq _ + apply if_congr _ rfl rfl + rw [sh_sh, show ((k : ℤ) + 1 + -(k + 1)) = 0 by ring, sh_zero] + have hq' : q ∈ SZ S := hq + simp only [hq', true_and] + constructor + · intro h j hj + have := h (k - j) (by omega) + rw [sh_sh] + convert this using 2 + push_cast [Nat.cast_sub (by omega : j ≤ k)] + ring + · intro h j hj + have := h (k - j) (by omega) + rw [sh_sh] at this + convert this using 2 + push_cast [Nat.cast_sub (by omega : j ≤ k)] + ring + + +/-! ### The dual (flow) inequality -/ + +/-- Occupancy indicator. -/ +private def X (S : Finset (ℕ × ℕ)) (c : ℤ × ℤ) : ℤ := if c ∈ SZ S then 1 else 0 + +/-- At most one piece reaches a given square in a given direction. -/ +private lemma Y_le_one (n : ℕ) (S : Finset (ℕ × ℕ)) (d c : ℤ × ℤ) : Y n S d c ≤ 1 := by + unfold Y + rw [Finset.sum_boole] + apply Finset.card_le_one.mpr + intro a ha b hb + simp only [Finset.mem_filter, Finset.mem_range] at ha hb + by_contra hab + rcases Nat.lt_or_gt_of_ne hab with h | h + · exact (hb.2.2 (a + 1) (by omega)).2 (by simpa using ha.2.1) + · exact (ha.2.2 (b + 1) (by omega)).2 (by simpa using hb.2.1) + +/-- Only empty squares of the board are reached. -/ +private lemma Y_eq_zero_of_not_E {n : ℕ} {S : Finset (ℕ × ℕ)} {d c : ℤ × ℤ} (h : ¬ E n S c) : + Y n S d c = 0 := by + unfold Y + apply Finset.sum_eq_zero + intro k _ + rw [if_neg] + rintro ⟨_, h2⟩ + exact h (by simpa [sh_zero] using h2 0 (by omega)) + +/-- `Y c ≤ x (c - d) + Y (c - d)`: the square behind `c` is a piece or is itself reached. -/ +private lemma Y_rec (n : ℕ) (S : Finset (ℕ × ℕ)) (d c : ℤ × ℤ) : + (Y n S d c : ℤ) ≤ X S (sh c d (-1)) + Y n S d (sh c d (-1)) := by + rcases Nat.eq_zero_or_pos (Y n S d c) with h | h + · rw [h]; unfold X; split_ifs <;> positivity + have h1 : Y n S d c = 1 := le_antisymm (Y_le_one n S d c) h + rw [h1] + unfold Y at h + obtain ⟨k, hk, hk2⟩ := Finset.exists_ne_zero_of_sum_ne_zero (Nat.pos_iff_ne_zero.mp h) + rw [Finset.mem_range] at hk + have hk3 : sh c d (-(k + 1)) ∈ SZ S ∧ ∀ j < k + 1, E n S (sh c d (-j)) := by + by_contra hc; exact hk2 (if_neg hc) + rcases k with _ | k + · have : X S (sh c d (-1)) = 1 := by + unfold X; rw [if_pos]; simpa using hk3.1 + rw [this]; push_cast; omega + · have hY : 1 ≤ Y n S d (sh c d (-1)) := by + unfold Y + have hsub : ({k} : Finset ℕ) ⊆ Finset.range n := by + intro x hx; rw [Finset.mem_singleton] at hx; subst hx; rw [Finset.mem_range]; omega + calc 1 = ∑ k' ∈ ({k} : Finset ℕ), (if (sh (sh c d (-1)) d (-(k' + 1)) ∈ SZ S ∧ + ∀ j < k' + 1, E n S (sh (sh c d (-1)) d (-j))) then 1 else 0) := by + rw [Finset.sum_singleton, if_pos] + refine ⟨?_, ?_⟩ + · rw [sh_sh]; convert hk3.1 using 2; push_cast; ring + · intro j hj; rw [sh_sh] + convert hk3.2 (j + 1) (by omega) using 2; push_cast; ring + _ ≤ _ := Finset.sum_le_sum_of_subset hsub + have : 0 ≤ X S (sh c d (-1)) := by unfold X; split_ifs <;> norm_num + push_cast; omega + +/-- Squares whose predecessor in direction `d` is off the board are not reached. -/ +private lemma Y_first {n : ℕ} {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) {d c : ℤ × ℤ} (hd : sh c d (-1) ∉ BZ n) : Y n S d c = 0 := by + unfold Y + apply Finset.sum_eq_zero + intro k _ + rw [if_neg] + rintro ⟨h1, h2⟩ + rcases k with _ | k + · exact hd (SZ_sub_BZ hS (by simpa using h1)) + · exact hd (by simpa using (h2 1 (by omega)).1) + +/-- Shifting a sum along the direction `d`. -/ +private lemma shift_sum (n : ℕ) (d : ℤ × ℤ) (f g : ℤ × ℤ → ℤ) + (hf : ∀ c, f c ≠ 0 → c ∈ BZ n ∧ sh c d (-1) ∈ BZ n) : + ∑ c ∈ BZ n, f (sh c d 1) * g c = ∑ c ∈ BZ n, f c * g (sh c d (-1)) := by + apply Finset.sum_bij_ne_zero (fun c _ _ => sh c d 1) + · intro c _ h + exact (hf _ (left_ne_zero_of_mul h)).1 + · intro a _ _ b _ _ h + have := congrArg (fun c => sh c d (-1)) h + simpa [sh_sh, sh_zero] using this + · intro c _ h + have h2 := hf _ (left_ne_zero_of_mul h) + refine ⟨sh c d (-1), h2.2, ?_, by simp [sh_sh, sh_zero]⟩ + rw [sh_sh, show (-1 : ℤ) + 1 = 0 by ring, sh_zero] + exact h + · intro c _ _ + rw [sh_sh, show (1 : ℤ) + -1 = 0 by ring, sh_zero] + +/-- The flow inequality for one direction. -/ +private lemma dir_ineq {n : ℕ} {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) (D : ℤ) (d : ℤ × ℤ) + (G : ℤ × ℤ → ℤ) (h0 : ∀ c, 0 ≤ G c) + (hsupp : ∀ c, G c ≠ 0 → c ∈ BZ n ∧ sh c d (-1) ∈ BZ n) + (hα : ∀ c ∈ BZ n, sh c d (-1) ∈ BZ n → G c ≤ D + G (sh c d 1)) : + D * (∑ p ∈ S, rayMoves n S p d : ℕ) ≤ + ∑ c ∈ BZ n, ((if sh c d (-1) ∈ BZ n then D + G (sh c d 1) - G c else 0) * (1 - X S c) + + G (sh c d 1) * X S c) := by + rw [sum_ray_eq] + have hX0 : ∀ c, 0 ≤ X S c := fun c => by unfold X; split_ifs <;> norm_num + have hX1 : ∀ c, X S c ≤ 1 := fun c => by unfold X; split_ifs <;> norm_num + -- the per-cell inequality + have hcell : ∀ c ∈ BZ n, D * (Y n S d c : ℤ) + G (sh c d 1) * Y n S d c ≤ + (if sh c d (-1) ∈ BZ n then D + G (sh c d 1) - G c else 0) * (1 - X S c) + + G c * X S (sh c d (-1)) + G c * Y n S d (sh c d (-1)) := by + intro c hc + have hY1 := Y_le_one n S d c + have hYr := Y_rec n S d c + have hG := h0 c + have hX := hX0 (sh c d (-1)) + have hYc : (0 : ℤ) ≤ Y n S d (sh c d (-1)) := by positivity + by_cases hd : sh c d (-1) ∈ BZ n + · rw [if_pos hd] + have ha := hα c hc hd + rcases Nat.eq_zero_or_pos (Y n S d c) with h | h + · rw [h]; push_cast + have := hX1 c + nlinarith + · have h1 : Y n S d c = 1 := le_antisymm hY1 h + have hxc : X S c = 0 := by + unfold X; rw [if_neg]; intro hm + have := Y_eq_zero_of_not_E (n := n) (d := d) (fun hE => hE.2 hm) + omega + rw [h1, hxc] at *; push_cast at * + nlinarith + · rw [if_neg hd, Y_first hS hd] + push_cast + nlinarith + have hsum := Finset.sum_le_sum hcell + rw [Finset.sum_add_distrib, Finset.sum_add_distrib, Finset.sum_add_distrib] at hsum + have e1 := shift_sum n d G (fun c => (Y n S d c : ℤ)) hsupp + have e2 := shift_sum n d G (X S) hsupp + push_cast + rw [Finset.mul_sum, Finset.sum_add_distrib] + linarith + + +/-- The "empty" weight of a cell. -/ +private def Af (n : ℕ) (D : ℤ) (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) (c : ℤ × ℤ) : ℤ := + (dirs.map fun d => if sh c d (-1) ∈ BZ n then D + G d (sh c d 1) - G d c else 0).sum + +/-- The "occupied" weight of a cell. -/ +private def Bf (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) (c : ℤ × ℤ) : ℤ := + (dirs.map fun d => G d (sh c d 1)).sum + +/-- The main inequality: weighted total moves are bounded by the cell weights. -/ +private theorem key {n : ℕ} {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) (D : ℤ) + (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) (h0 : ∀ d c, 0 ≤ G d c) + (hsupp : ∀ d c, G d c ≠ 0 → c ∈ BZ n ∧ sh c d (-1) ∈ BZ n) + (hα : ∀ d ∈ dirs, ∀ c ∈ BZ n, sh c d (-1) ∈ BZ n → G d c ≤ D + G d (sh c d 1)) : + D * (totalMoves dirs n S : ℤ) ≤ + ∑ c ∈ BZ n, (if c ∈ SZ S then Bf dirs G c else Af n D dirs G c) := by + have main : ∀ L : List (ℤ × ℤ), (∀ d ∈ L, ∀ c ∈ BZ n, sh c d (-1) ∈ BZ n → + G d c ≤ D + G d (sh c d 1)) → + D * (∑ p ∈ S, (L.map (rayMoves n S p)).sum : ℕ) ≤ + ∑ c ∈ BZ n, ((1 - X S c) * Af n D L G c + X S c * Bf L G c) := by + intro L + induction L with + | nil => intro _; simp [Af, Bf] + | cons d L ih => + intro hL + have h1 := dir_ineq hS D d (G d) (h0 d) (hsupp d) (hL d (by simp)) + have h2 := ih (fun d' hd' => hL d' (by simp [hd'])) + have e : ∀ p ∈ S, ((d :: L).map (rayMoves n S p)).sum = + rayMoves n S p d + (L.map (rayMoves n S p)).sum := by intro p _; simp + rw [Finset.sum_congr rfl e, Finset.sum_add_distrib] + have e2 : ∀ c ∈ BZ n, (1 - X S c) * Af n D (d :: L) G c + X S c * Bf (d :: L) G c = + ((if sh c d (-1) ∈ BZ n then D + G d (sh c d 1) - G d c else 0) * (1 - X S c) + + G d (sh c d 1) * X S c) + ((1 - X S c) * Af n D L G c + X S c * Bf L G c) := by + intro c _; simp only [Af, Bf, List.map_cons, List.sum_cons]; ring + rw [Finset.sum_congr rfl e2, Finset.sum_add_distrib] + push_cast at h1 h2 ⊢ + linarith + have hm := main dirs hα + have htot : totalMoves dirs n S = ∑ p ∈ S, (dirs.map (rayMoves n S p)).sum := rfl + rw [htot] + refine hm.trans (le_of_eq (Finset.sum_congr rfl fun c _ => ?_)) + unfold X + split_ifs <;> ring + + +/-! ### Checking certificates by computation -/ + +/-- Board membership as a boolean. -/ +private def inB (n : ℕ) (c : ℤ × ℤ) : Bool := decide (0 ≤ c.1 ∧ c.1 < n ∧ 0 ≤ c.2 ∧ c.2 < n) + +/-- `inB` decides board membership. -/ +private lemma inB_iff {n : ℕ} {c : ℤ × ℤ} : inB n c = true ↔ c ∈ BZ n := by + simp [inB, mem_BZ] + +/-- A flow given by a table of natural numbers, cut off outside the board. -/ +private def Gt (n : ℕ) (T : ℤ × ℤ → ℤ × ℤ → ℕ) (d c : ℤ × ℤ) : ℤ := + if inB n c && inB n (sh c d (-1)) then (T d c : ℤ) else 0 + +/-- Table lookup: entries `(d₁, d₂, i, j, v)`. -/ +private def tab (L : List (ℤ × ℤ × ℤ × ℤ × ℕ)) (d c : ℤ × ℤ) : ℕ := + match L.find? (fun e => e.1 == d.1 && e.2.1 == d.2 && e.2.2.1 == c.1 && e.2.2.2.1 == c.2) with + | some e => e.2.2.2.2 + | none => 0 + +/-- Computable version of `Af`. -/ +private def Afc (n : ℕ) (D : ℤ) (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) (c : ℤ × ℤ) : ℤ := + (dirs.map fun d => if inB n (sh c d (-1)) then D + G d (sh c d 1) - G d c else 0).sum + +/-- `Af` agrees with its computable version. -/ +private lemma Af_eq (n : ℕ) (D : ℤ) (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) (c : ℤ × ℤ) : + Af n D dirs G c = Afc n D dirs G c := by + unfold Af Afc + congr 1 + apply List.map_congr_left + intro d _ + by_cases h : sh c d (-1) ∈ BZ n + · rw [if_pos h, if_pos (inB_iff.mpr h)] + · rw [if_neg h, if_neg (fun h' => h (inB_iff.mp h'))] + +/-- The `α ≥ 0` condition, checked cell by cell. -/ +private def checkA (n : ℕ) (D : ℤ) (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) : Bool := + dirs.all fun d => (List.range n).all fun i => (List.range n).all fun j => + !inB n (sh ((i : ℤ), (j : ℤ)) d (-1)) || decide (G d ((i : ℤ), (j : ℤ)) ≤ + D + G d (sh ((i : ℤ), (j : ℤ)) d 1)) + +/-- The bound for one cell, given cells known to be occupied (`In`) or empty (`Out`). -/ +private def bnd (n : ℕ) (D : ℤ) (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) + (In Out : List (ℕ × ℕ)) (i j : ℕ) : ℤ := + if (i, j) ∈ In then Bf dirs G ((i : ℤ), (j : ℤ)) + else if (i, j) ∈ Out then Afc n D dirs G ((i : ℤ), (j : ℤ)) + else max (Afc n D dirs G ((i : ℤ), (j : ℤ))) (Bf dirs G ((i : ℤ), (j : ℤ))) + +/-- The total of the cell bounds. -/ +private def bndSum (n : ℕ) (D : ℤ) (dirs : List (ℤ × ℤ)) (G : ℤ × ℤ → ℤ × ℤ → ℤ) + (In Out : List (ℕ × ℕ)) : ℤ := + ∑ i ∈ Finset.range n, ∑ j ∈ Finset.range n, bnd n D dirs G In Out i j + +/-- Sums over the integer board as double sums over `range n`. -/ +private lemma sum_BZ (n : ℕ) (f : ℤ × ℤ → ℤ) : + ∑ c ∈ BZ n, f c = ∑ i ∈ Finset.range n, ∑ j ∈ Finset.range n, f ((i : ℤ), (j : ℤ)) := by + rw [BZ, Finset.sum_map, board, Finset.sum_product] + rfl + +/-- A leaf certificate bounds the total number of moves. -/ +private theorem leaf {n : ℕ} {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) (D : ℤ) (hD : 0 < D) + (dirs : List (ℤ × ℤ)) (T : ℤ × ℤ → ℤ × ℤ → ℕ) (In Out : List (ℕ × ℕ)) (target : ℕ) + (h1 : checkA n D dirs (Gt n T) = true) + (h2 : bndSum n D dirs (Gt n T) In Out < D * (target + 1)) + (hIn : ∀ p ∈ In, p ∈ S) (hOut : ∀ p ∈ Out, p ∉ S) : + totalMoves dirs n S ≤ target := by + have hk := key hS D dirs (Gt n T) + (fun d c => by unfold Gt; split_ifs <;> positivity) + (fun d c h => by + unfold Gt at h + split_ifs at h with hc + · simp only [Bool.and_eq_true] at hc + exact ⟨inB_iff.mp hc.1, inB_iff.mp hc.2⟩ + · exact absurd rfl h) + (fun d hd c hc hc' => by + have h1' := h1 + unfold checkA at h1' + rw [List.all_eq_true] at h1' + have h3 := h1' d hd + rw [mem_BZ] at hc + obtain ⟨i, hi⟩ : ∃ i : ℕ, (i : ℤ) = c.1 := ⟨c.1.toNat, by omega⟩ + obtain ⟨j, hj⟩ : ∃ j : ℕ, (j : ℤ) = c.2 := ⟨c.2.toNat, by omega⟩ + rw [List.all_eq_true] at h3 + have h4 := h3 i (List.mem_range.mpr (by omega)) + rw [List.all_eq_true] at h4 + have h5 := h4 j (List.mem_range.mpr (by omega)) + have hc2 : c = ((i : ℤ), (j : ℤ)) := by ext <;> simp [hi, hj] + subst hc2 + simp only [Bool.or_eq_true, Bool.not_eq_true', decide_eq_true_eq] at h5 + rcases h5 with h5 | h5 + · exact absurd (inB_iff.mpr hc') (by simp [h5]) + · exact h5) + have hle : ∑ c ∈ BZ n, (if c ∈ SZ S then Bf dirs (Gt n T) c else Af n D dirs (Gt n T) c) ≤ + bndSum n D dirs (Gt n T) In Out := by + rw [sum_BZ, bndSum] + apply Finset.sum_le_sum; intro i _ + apply Finset.sum_le_sum; intro j _ + have hmem : ((i : ℤ), (j : ℤ)) ∈ SZ S ↔ (i, j) ∈ S := by + rw [mem_SZ (by simp) (by simp)]; simp + rw [Af_eq, bnd] + by_cases hI : (i, j) ∈ In + · rw [if_pos (hmem.mpr (hIn _ hI)), if_pos hI] + · rw [if_neg hI] + by_cases hO : (i, j) ∈ Out + · rw [if_neg (fun h => hOut _ hO (hmem.mp h)), if_pos hO] + · rw [if_neg hO] + split_ifs + · exact le_max_right _ _ + · exact le_max_left _ _ + have : D * (totalMoves dirs n S : ℤ) < D * (target + 1) := by linarith + have := lt_of_mul_lt_mul_left this hD.le + omega + + +/-! ### The general case: flows depending only on the position class of a cell -/ + +/-- Position class of a coordinate, cut off at `3`: `0, 1, 2` near the start, `3` in the +middle, `4, 5, 6` near the end. -/ +private def cls3 (n : ℕ) (x : ℤ) : ℕ := + if x < 3 then x.toNat else if (n : ℤ) - 1 - x < 3 then (6 - ((n : ℤ) - 1 - x)).toNat else 3 + +/-- Position class of a coordinate, cut off at `4`: `0, …, 3` near the start, `4` in the +middle, `5, …, 8` near the end. -/ +private def cls4 (n : ℕ) (x : ℤ) : ℕ := + if x < 4 then x.toNat else if (n : ℤ) - 1 - x < 4 then (8 - ((n : ℤ) - 1 - x)).toNat else 4 + +/-- Whether a step `δ` from a coordinate of class `v` stays on the board. -/ +private def ok4 (v : ℕ) (δ : ℤ) : Bool := !(v == 0 && δ == -1) && !(v == 8 && δ == 1) + +/-- The `cls3` class after a step `δ` from a coordinate of `cls4` class `v`. -/ +private def sh3 (v : ℕ) (δ : ℤ) : ℕ := + if v ≤ 3 then (if (v : ℤ) + δ < 3 then ((v : ℤ) + δ).toNat else 3) + else if v = 4 then 3 + else (if 8 - (v : ℤ) - δ < 3 then ((v : ℤ) + δ - 2).toNat else 3) + +/-- Classes with cut-off `4` are at most `8`. -/ +private lemma cls4_le (n : ℕ) (x : ℤ) (hx : 0 ≤ x) (hxn : x < n) : cls4 n x ≤ 8 := by + unfold cls4; split_ifs <;> omega + +/-- `ok4` decides whether a step stays on the board (for `n ≥ 8`). -/ +private lemma ok4_iff {n : ℕ} (hn : 8 ≤ n) {x δ : ℤ} (hx : 0 ≤ x) (hxn : x < n) + (hδ : -1 ≤ δ ∧ δ ≤ 1) : ok4 (cls4 n x) δ = true ↔ 0 ≤ x + δ ∧ x + δ < n := by + unfold ok4 cls4 + split_ifs with h1 h2 <;> simp <;> omega + +/-- The `cls3` class after a step is determined by the `cls4` class before it (`n ≥ 8`). -/ +private lemma cls3_shift {n : ℕ} (hn : 8 ≤ n) {x δ : ℤ} (hx : 0 ≤ x) (hxn : x < n) + (hδ : -1 ≤ δ ∧ δ ≤ 1) (h1 : 0 ≤ x + δ) (h2 : x + δ < n) : + cls3 n (x + δ) = sh3 (cls4 n x) δ := by + unfold cls3 sh3 cls4 + split_ifs <;> omega + +/-- Lookup in a class table: entries `(u, w, d₁, d₂, v)`. -/ +private def tabC (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (u w : ℕ) (d : ℤ × ℤ) : ℕ := + match L.find? (fun e => e.1 == u && e.2.1 == w && e.2.2.1 == d.1 && e.2.2.2.1 == d.2) with + | some e => e.2.2.2.2 + | none => 0 + +/-- The flow defined by a class table. -/ +private def Gc (n : ℕ) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) : ℤ × ℤ → ℤ × ℤ → ℤ := + Gt n (fun d c => tabC L (cls3 n c.1) (cls3 n c.2) d) + +/-- Flow into the cell `c` from `c + d`, by classes. -/ +private def G1 (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (v w : ℕ) (d : ℤ × ℤ) : ℤ := + if ok4 v d.1 && ok4 w d.2 then (tabC L (sh3 v d.1) (sh3 w d.2) d : ℤ) else 0 + +/-- Flow out of the cell `c`, by classes. -/ +private def G0 (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (v w : ℕ) (d : ℤ × ℤ) : ℤ := + (tabC L (sh3 v 0) (sh3 w 0) d : ℤ) + +/-- `Af` by classes. -/ +private def Aty (D : ℤ) (dirs : List (ℤ × ℤ)) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (v w : ℕ) : ℤ := + (dirs.map fun d => if ok4 v (-d.1) && ok4 w (-d.2) then D + G1 L v w d - G0 L v w d + else 0).sum + +/-- `Bf` by classes. -/ +private def Bty (dirs : List (ℤ × ℤ)) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (v w : ℕ) : ℤ := + (dirs.map fun d => G1 L v w d).sum + +/-- The cell bound by classes. -/ +private def Mty (D : ℤ) (dirs : List (ℤ × ℤ)) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (v w : ℕ) : ℤ := + max (Aty D dirs L v w) (Bty dirs L v w) + +/-- Unit directions. -/ +private def unitDir (d : ℤ × ℤ) : Prop := -1 ≤ d.1 ∧ d.1 ≤ 1 ∧ -1 ≤ d.2 ∧ d.2 ≤ 1 + +/-- Board membership of a neighbour, by classes. -/ +private lemma memBZ_shift {n : ℕ} (hn : 8 ≤ n) {c d : ℤ × ℤ} (hc : c ∈ BZ n) (hd : unitDir d) + (s : ℤ) (hs : s = 1 ∨ s = -1) : + sh c d s ∈ BZ n ↔ (ok4 (cls4 n c.1) (s * d.1) && ok4 (cls4 n c.2) (s * d.2)) = true := by + rw [mem_BZ] at hc + obtain ⟨h1, h2, h3, h4⟩ := hc + obtain ⟨d1, d2, d3, d4⟩ := hd + have hδ1 : -1 ≤ s * d.1 ∧ s * d.1 ≤ 1 := by rcases hs with rfl | rfl <;> constructor <;> linarith + have hδ2 : -1 ≤ s * d.2 ∧ s * d.2 ≤ 1 := by rcases hs with rfl | rfl <;> constructor <;> linarith + rw [Bool.and_eq_true, ok4_iff hn h1 h2 hδ1, ok4_iff hn h3 h4 hδ2, mem_BZ] + simp only [sh] + constructor + · rintro ⟨a, b, c, e⟩; exact ⟨⟨by linarith, by linarith⟩, ⟨by linarith, by linarith⟩⟩ + · rintro ⟨⟨a, b⟩, ⟨c, e⟩⟩; exact ⟨by linarith, by linarith, by linarith, by linarith⟩ + +/-- The flow at `c + d`, by classes. -/ +private lemma Gc_one {n : ℕ} (hn : 8 ≤ n) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) {c d : ℤ × ℤ} + (hc : c ∈ BZ n) (hd : unitDir d) : + Gc n L d (sh c d 1) = G1 L (cls4 n c.1) (cls4 n c.2) d := by + have hm := memBZ_shift hn hc hd 1 (Or.inl rfl) + simp only [one_mul] at hm + unfold Gc Gt G1 + have hback : sh (sh c d 1) d (-1) = c := by + rw [sh_sh, show (1 : ℤ) + -1 = 0 by ring, sh_zero] + rw [hback, inB_iff.mpr hc, Bool.and_true] + by_cases h : sh c d 1 ∈ BZ n + · rw [if_pos (inB_iff.mpr h), if_pos (hm.mp h)] + rw [mem_BZ] at hc + obtain ⟨d1, d2, d3, d4⟩ := hd + have h' := mem_BZ.mp h + simp only [sh, one_mul] at h' ⊢ + rw [cls3_shift hn hc.1 hc.2.1 ⟨d1, d2⟩ (by linarith) (by linarith), + cls3_shift hn hc.2.2.1 hc.2.2.2 ⟨d3, d4⟩ (by linarith) (by linarith)] + · rw [if_neg (fun h' => h (inB_iff.mp h')), if_neg (fun h' => h (hm.mpr h'))] + +/-- The flow at `c` (when `c - d` is on the board), by classes. -/ +private lemma Gc_zero {n : ℕ} (hn : 8 ≤ n) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) {c d : ℤ × ℤ} + (hc : c ∈ BZ n) (hd' : sh c d (-1) ∈ BZ n) : + Gc n L d c = G0 L (cls4 n c.1) (cls4 n c.2) d := by + unfold Gc Gt G0 + rw [inB_iff.mpr hc, inB_iff.mpr hd', Bool.and_self, if_pos rfl] + rw [mem_BZ] at hc + have e1 := cls3_shift hn hc.1 hc.2.1 ⟨by norm_num, by norm_num⟩ (by linarith) (by linarith) + (δ := 0) + have e2 := cls3_shift hn hc.2.2.1 hc.2.2.2 ⟨by norm_num, by norm_num⟩ (by linarith) + (by linarith) (δ := 0) + simp only [add_zero] at e1 e2 + dsimp only + rw [e1, e2] + +/-- `Af` depends only on the classes of the coordinates. -/ +private lemma Af_ty {n : ℕ} (hn : 8 ≤ n) (D : ℤ) (dirs : List (ℤ × ℤ)) + (hdirs : ∀ d ∈ dirs, unitDir d) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) {c : ℤ × ℤ} + (hc : c ∈ BZ n) : Af n D dirs (Gc n L) c = Aty D dirs L (cls4 n c.1) (cls4 n c.2) := by + unfold Af Aty + congr 1 + apply List.map_congr_left + intro d hd + have hm := memBZ_shift hn hc (hdirs d hd) (-1) (Or.inr rfl) + simp only [neg_one_mul] at hm + by_cases h : sh c d (-1) ∈ BZ n + · rw [if_pos h, if_pos (hm.mp h), Gc_one hn L hc (hdirs d hd), Gc_zero hn L hc h] + · rw [if_neg h, if_neg (fun h' => h (hm.mpr h'))] + +/-- `Bf` depends only on the classes of the coordinates. -/ +private lemma Bf_ty {n : ℕ} (hn : 8 ≤ n) (dirs : List (ℤ × ℤ)) + (hdirs : ∀ d ∈ dirs, unitDir d) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) {c : ℤ × ℤ} + (hc : c ∈ BZ n) : Bf dirs (Gc n L) c = Bty dirs L (cls4 n c.1) (cls4 n c.2) := by + unfold Bf Bty + congr 1 + apply List.map_congr_left + intro d hd + rw [Gc_one hn L hc (hdirs d hd)] + +/-- The `α ≥ 0` condition by classes. -/ +private def checkTy (D : ℤ) (dirs : List (ℤ × ℤ)) (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) : Bool := + dirs.all fun d => (List.range 9).all fun v => (List.range 9).all fun w => + !(ok4 v (-d.1) && ok4 w (-d.2)) || decide (G0 L v w d ≤ D + G1 L v w d) + +/-- The eight boundary classes. -/ +private def E8 : Finset ℕ := {0, 1, 2, 3, 5, 6, 7, 8} + +/-- Summing a function of the class over a coordinate, for `n ≥ 8`. -/ +private lemma sum_cls4 {n : ℕ} (hn : 8 ≤ n) (f : ℕ → ℤ) : + ∑ i ∈ Finset.range n, f (cls4 n i) = ∑ v ∈ E8, f v + ((n : ℤ) - 8) * f 4 := by + obtain ⟨m, rfl⟩ : ∃ m, n = 4 + m + 4 := ⟨n - 8, by omega⟩ + rw [Finset.sum_range_add, Finset.sum_range_add] + have hmid : ∀ x ∈ Finset.range m, f (cls4 (4 + m + 4) ((4 + x : ℕ) : ℤ)) = f 4 := by + intro x hx + rw [Finset.mem_range] at hx + congr 1 + unfold cls4; push_cast; split_ifs <;> omega + rw [Finset.sum_congr rfl hmid, Finset.sum_const, Finset.card_range] + have hv : ∀ k : ℕ, k < 4 → cls4 (4 + m + 4) (k : ℤ) = k := by + intro k hk; unfold cls4; push_cast; split_ifs <;> omega + have hw : ∀ k : ℕ, k < 4 → cls4 (4 + m + 4) ((4 + m + k : ℕ) : ℤ) = 5 + k := by + intro k hk; unfold cls4; push_cast; split_ifs <;> omega + simp only [Finset.sum_range_succ, Finset.sum_range_zero, zero_add] + rw [hv 0 (by norm_num), hv 1 (by norm_num), hv 2 (by norm_num), hv 3 (by norm_num), + hw 0 (by norm_num), hw 1 (by norm_num), hw 2 (by norm_num), hw 3 (by norm_num)] + simp only [E8] + norm_num + ring + +/-- The general bound for `n ≥ 8`. -/ +private theorem general {n : ℕ} (hn : 8 ≤ n) {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) (D : ℤ) + (hD : 0 < D) (dirs : List (ℤ × ℤ)) (hdirs : ∀ d ∈ dirs, unitDir d) + (L : List (ℕ × ℕ × ℤ × ℤ × ℕ)) (hchk : checkTy D dirs L = true) (target : ℕ) + (htarget : ∑ v ∈ E8, ∑ w ∈ E8, Mty D dirs L v w + + ((n : ℤ) - 8) * (∑ v ∈ E8, Mty D dirs L v 4 + ∑ w ∈ E8, Mty D dirs L 4 w) + + ((n : ℤ) - 8) * ((n : ℤ) - 8) * Mty D dirs L 4 4 = D * target) : + totalMoves dirs n S ≤ target := by + have hk := key hS D dirs (Gc n L) + (fun d c => by unfold Gc Gt; split_ifs <;> positivity) + (fun d c h => by + unfold Gc Gt at h + split_ifs at h with hc + · simp only [Bool.and_eq_true] at hc + exact ⟨inB_iff.mp hc.1, inB_iff.mp hc.2⟩ + · exact absurd rfl h) + (fun d hd c hc hc' => by + rw [Gc_one hn L hc (hdirs d hd), Gc_zero hn L hc hc'] + have h1 := hchk + unfold checkTy at h1 + rw [List.all_eq_true] at h1 + have h3 := h1 d hd + have hm := (memBZ_shift hn hc (hdirs d hd) (-1) (Or.inr rfl)).mp hc' + simp only [neg_one_mul] at hm + have hc2 := mem_BZ.mp hc + rw [List.all_eq_true] at h3 + have h4 := h3 (cls4 n c.1) (List.mem_range.mpr (by + have := cls4_le n c.1 hc2.1 hc2.2.1; omega)) + rw [List.all_eq_true] at h4 + have h5 := h4 (cls4 n c.2) (List.mem_range.mpr (by + have := cls4_le n c.2 hc2.2.2.1 hc2.2.2.2; omega)) + simp only [Bool.or_eq_true, Bool.not_eq_true', decide_eq_true_eq] at h5 + rcases h5 with h5 | h5 + · rw [hm] at h5; exact absurd h5 (by simp) + · exact h5) + have hle : ∑ c ∈ BZ n, (if c ∈ SZ S then Bf dirs (Gc n L) c else Af n D dirs (Gc n L) c) ≤ + ∑ c ∈ BZ n, Mty D dirs L (cls4 n c.1) (cls4 n c.2) := by + apply Finset.sum_le_sum + intro c hc + rw [Af_ty hn D dirs hdirs L hc, Bf_ty hn dirs hdirs L hc, Mty] + split_ifs + · exact le_max_right _ _ + · exact le_max_left _ _ + have hsum : ∑ i ∈ Finset.range n, ∑ j ∈ Finset.range n, + Mty D dirs L (cls4 n (i : ℤ)) (cls4 n (j : ℤ)) = D * target := by + have : ∀ i ∈ Finset.range n, ∑ j ∈ Finset.range n, Mty D dirs L (cls4 n (i : ℤ)) + (cls4 n (j : ℤ)) = ∑ w ∈ E8, Mty D dirs L (cls4 n (i : ℤ)) w + + ((n : ℤ) - 8) * Mty D dirs L (cls4 n (i : ℤ)) 4 := fun i _ => + sum_cls4 hn (fun w => Mty D dirs L (cls4 n (i : ℤ)) w) + rw [Finset.sum_congr rfl this, sum_cls4 hn (fun v => ∑ w ∈ E8, Mty D dirs L v w + + ((n : ℤ) - 8) * Mty D dirs L v 4), ← htarget, Finset.sum_add_distrib, ← Finset.mul_sum] + ring + have hsum2 : ∑ c ∈ BZ n, Mty D dirs L (cls4 n c.1) (cls4 n c.2) = D * target := by + rw [sum_BZ]; exact hsum + have : D * (totalMoves dirs n S : ℤ) ≤ D * target := by linarith + have := le_of_mul_le_mul_left this hD + omega + + +/-! ### The tables for queens and bishops -/ + +/-- Flow table for queens (in half units), by position classes. -/ +private def LQ : List (ℕ × ℕ × ℤ × ℤ × ℕ) := + [(1, 1, -1, 1, 1), (1, 1, 0, 1, 4), (1, 1, 1, -1, 1), (1, 1, 1, 0, 4), (1, 1, 1, 1, 6), (1, 2, -1, 1, 1), (1, 2, 0, 1, 2), (1, 2, 1, -1, 3), (1, 2, 1, 0, 4), (1, 2, 1, 1, 6), (1, 3, -1, -1, 1), (1, 3, -1, 1, 1), (1, 3, 1, -1, 5), (1, 3, 1, 0, 4), (1, 3, 1, 1, 5), (1, 4, -1, -1, 1), (1, 4, 0, -1, 2), (1, 4, 1, -1, 6), (1, 4, 1, 0, 4), (1, 4, 1, 1, 3), (1, 5, -1, -1, 1), (1, 5, 0, -1, 4), (1, 5, 1, -1, 6), (1, 5, 1, 0, 4), (1, 5, 1, 1, 1), (2, 1, -1, 1, 3), (2, 1, 0, 1, 4), (2, 1, 1, -1, 1), (2, 1, 1, 0, 2), (2, 1, 1, 1, 6), (2, 2, -1, 1, 3), (2, 2, 0, 1, 2), (2, 2, 1, -1, 3), (2, 2, 1, 0, 2), (2, 2, 1, 1, 4), (2, 3, -1, -1, 2), (2, 3, -1, 1, 2), (2, 3, 1, -1, 4), (2, 3, 1, 0, 2), (2, 3, 1, 1, 4), (2, 4, -1, -1, 3), (2, 4, 0, -1, 2), (2, 4, 1, -1, 4), (2, 4, 1, 0, 2), (2, 4, 1, 1, 3), (2, 5, -1, -1, 3), (2, 5, 0, -1, 4), (2, 5, 1, -1, 6), (2, 5, 1, 0, 2), (2, 5, 1, 1, 1), (3, 1, -1, -1, 1), (3, 1, -1, 1, 5), (3, 1, 0, 1, 4), (3, 1, 1, -1, 1), (3, 1, 1, 1, 5), (3, 2, -1, -1, 2), (3, 2, -1, 1, 4), (3, 2, 0, 1, 2), (3, 2, 1, -1, 2), (3, 2, 1, 1, 4), (3, 3, -1, -1, 2), (3, 3, -1, 1, 2), (3, 3, 1, -1, 2), (3, 3, 1, 1, 2), (3, 4, -1, -1, 4), (3, 4, -1, 1, 2), (3, 4, 0, -1, 2), (3, 4, 1, -1, 4), (3, 4, 1, 1, 2), (3, 5, -1, -1, 5), (3, 5, -1, 1, 1), (3, 5, 0, -1, 4), (3, 5, 1, -1, 5), (3, 5, 1, 1, 1), (4, 1, -1, -1, 1), (4, 1, -1, 0, 2), (4, 1, -1, 1, 6), (4, 1, 0, 1, 4), (4, 1, 1, 1, 3), (4, 2, -1, -1, 3), (4, 2, -1, 0, 2), (4, 2, -1, 1, 4), (4, 2, 0, 1, 2), (4, 2, 1, 1, 3), (4, 3, -1, -1, 4), (4, 3, -1, 0, 2), (4, 3, -1, 1, 4), (4, 3, 1, -1, 2), (4, 3, 1, 1, 2), (4, 4, -1, -1, 4), (4, 4, -1, 0, 2), (4, 4, -1, 1, 3), (4, 4, 0, -1, 2), (4, 4, 1, -1, 3), (4, 5, -1, -1, 6), (4, 5, -1, 0, 2), (4, 5, -1, 1, 1), (4, 5, 0, -1, 4), (4, 5, 1, -1, 3), (5, 1, -1, -1, 1), (5, 1, -1, 0, 4), (5, 1, -1, 1, 6), (5, 1, 0, 1, 4), (5, 1, 1, 1, 1), (5, 2, -1, -1, 3), (5, 2, -1, 0, 4), (5, 2, -1, 1, 6), (5, 2, 0, 1, 2), (5, 2, 1, 1, 1), (5, 3, -1, -1, 5), (5, 3, -1, 0, 4), (5, 3, -1, 1, 5), (5, 3, 1, -1, 1), (5, 3, 1, 1, 1), (5, 4, -1, -1, 6), (5, 4, -1, 0, 4), (5, 4, -1, 1, 3), (5, 4, 0, -1, 2), (5, 4, 1, -1, 1), (5, 5, -1, -1, 6), (5, 5, -1, 0, 4), (5, 5, -1, 1, 1), (5, 5, 0, -1, 4), (5, 5, 1, -1, 1)] + +/-- Flow table for bishops, by position classes. -/ +private def LB : List (ℕ × ℕ × ℤ × ℤ × ℕ) := + [(1, 1, -1, 1, 1), (1, 1, 1, -1, 1), (1, 1, 1, 1, 1), (1, 2, 1, -1, 1), (1, 2, 1, 1, 2), (1, 3, 1, -1, 1), (1, 3, 1, 1, 1), (1, 4, 1, -1, 2), (1, 4, 1, 1, 1), (1, 5, -1, -1, 1), (1, 5, 1, -1, 1), (1, 5, 1, 1, 1), (2, 1, -1, 1, 1), (2, 1, 1, 1, 2), (2, 2, -1, 1, 1), (2, 2, 1, -1, 1), (2, 3, 1, -1, 1), (2, 3, 1, 1, 1), (2, 4, -1, -1, 1), (2, 4, 1, 1, 1), (2, 5, -1, -1, 1), (2, 5, 1, -1, 2), (3, 1, -1, 1, 1), (3, 1, 1, 1, 1), (3, 2, -1, 1, 1), (3, 2, 1, 1, 1), (3, 4, -1, -1, 1), (3, 4, 1, -1, 1), (3, 5, -1, -1, 1), (3, 5, 1, -1, 1), (4, 1, -1, 1, 2), (4, 1, 1, 1, 1), (4, 2, -1, -1, 1), (4, 2, 1, 1, 1), (4, 3, -1, -1, 1), (4, 3, -1, 1, 1), (4, 4, -1, 1, 1), (4, 4, 1, -1, 1), (4, 5, -1, -1, 2), (4, 5, 1, -1, 1), (5, 1, -1, -1, 1), (5, 1, -1, 1, 1), (5, 1, 1, 1, 1), (5, 2, -1, -1, 1), (5, 2, -1, 1, 2), (5, 3, -1, -1, 1), (5, 3, -1, 1, 1), (5, 4, -1, -1, 2), (5, 4, -1, 1, 1), (5, 5, -1, -1, 1), (5, 5, -1, 1, 1), (5, 5, 1, -1, 1)] + +/-- Queen directions are unit steps. -/ +private lemma queenDirs_unit : ∀ d ∈ queenDirs, unitDir d := by + simp [queenDirs, unitDir] + +/-- Bishop directions are unit steps. -/ +private lemma bishopDirs_unit : ∀ d ∈ bishopDirs, unitDir d := by + simp [bishopDirs, unitDir] + +/-- Casting the targets `k (n - 2)²` to `ℤ`. -/ +private lemma cast_target (n : ℕ) (hn : 2 ≤ n) (k : ℕ) : + ((k * (n - 2) ^ 2 : ℕ) : ℤ) = k * ((n : ℤ) - 8 + 6) ^ 2 := by + push_cast [Nat.cast_sub hn] + ring + +/-- Queens, `n ≥ 8`. -/ +private theorem queen_ge8 {n : ℕ} (hn : 8 ≤ n) {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) : + totalMoves queenDirs n S ≤ 8 * (n - 2) ^ 2 := by + have c0 : ∑ v ∈ E8, ∑ w ∈ E8, Mty 2 queenDirs LQ v w = 576 := by decide +kernel + have c1 : ∑ v ∈ E8, Mty 2 queenDirs LQ v 4 + ∑ w ∈ E8, Mty 2 queenDirs LQ 4 w = 192 := by + decide +kernel + have c2 : Mty 2 queenDirs LQ 4 4 = 16 := by decide +kernel + refine general hn hS 2 (by norm_num) queenDirs queenDirs_unit LQ (by decide +kernel) _ ?_ + rw [c0, c1, c2, cast_target n (by omega)] + ring + +/-- Bishops, `n ≥ 8`. -/ +private theorem bishop_ge8 {n : ℕ} (hn : 8 ≤ n) {S : Finset (ℕ × ℕ)} (hS : S ⊆ board n) : + totalMoves bishopDirs n S ≤ 4 * (n - 2) ^ 2 := by + have c0 : ∑ v ∈ E8, ∑ w ∈ E8, Mty 1 bishopDirs LB v w = 144 := by decide +kernel + have c1 : ∑ v ∈ E8, Mty 1 bishopDirs LB v 4 + ∑ w ∈ E8, Mty 1 bishopDirs LB 4 w = 48 := by + decide +kernel + have c2 : Mty 1 bishopDirs LB 4 4 = 4 := by decide +kernel + refine general hn hS 1 (by norm_num) bishopDirs bishopDirs_unit LB (by decide +kernel) _ ?_ + rw [c0, c1, c2, cast_target n (by omega)] + ring + +/-- Queens, `n = 7`, with the same table. -/ +private theorem queen7 {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 7) : + totalMoves queenDirs 7 S ≤ 200 := + leaf hS 2 (by norm_num) queenDirs (fun d c => tabC LQ (cls3 7 c.1) (cls3 7 c.2) d) [] [] 200 + (by decide +kernel) (by decide +kernel) (by simp) (by simp) + +/-- Bishops, `n = 6`, with the same table. -/ +private theorem bishop6 {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 6) : + totalMoves bishopDirs 6 S ≤ 64 := + leaf hS 1 (by norm_num) bishopDirs (fun d c => tabC LB (cls3 6 c.1) (cls3 6 c.2) d) [] [] 64 + (by decide +kernel) (by decide +kernel) (by simp) (by simp) + +/-- Bishops, `n = 7`, with the same table. -/ +private theorem bishop7 {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 7) : + totalMoves bishopDirs 7 S ≤ 100 := + leaf hS 1 (by norm_num) bishopDirs (fun d c => tabC LB (cls3 7 c.1) (cls3 7 c.2) d) [] [] 100 + (by decide +kernel) (by decide +kernel) (by simp) (by simp) + + +/-! ### The border placement -/ + +/-- Membership in the border placement. -/ +private lemma mem_SZ_border {n : ℕ} {c : ℤ × ℤ} : + c ∈ SZ (border n) ↔ c ∈ BZ n ∧ (c.1 = 0 ∨ c.1 = n - 1 ∨ c.2 = 0 ∨ c.2 = n - 1) := by + constructor + · intro h + simp only [SZ, Finset.mem_map, border, Finset.mem_filter] at h + obtain ⟨p, ⟨hp, hb⟩, rfl⟩ := h + refine ⟨Finset.mem_map_of_mem emb hp, ?_⟩ + simp only [board, Finset.mem_product, Finset.mem_range] at hp + simp only [emb_apply] + omega + · rintro ⟨h1, h2⟩ + have h1' := mem_BZ.mp h1 + rw [mem_SZ h1'.1 h1'.2.2.1] + simp only [border, Finset.mem_filter, board, Finset.mem_product, Finset.mem_range] + omega + +/-- The interior squares. -/ +private def intr (n : ℕ) (c : ℤ × ℤ) : Prop := + 1 ≤ c.1 ∧ c.1 ≤ (n : ℤ) - 2 ∧ 1 ≤ c.2 ∧ c.2 ≤ (n : ℤ) - 2 + +/-- Interior squares are decidable. -/ +private instance (n : ℕ) : DecidablePred (intr n) := fun c => by unfold intr; infer_instance + +/-- For the border placement the empty squares are exactly the interior squares. -/ +private lemma E_border {n : ℕ} {c : ℤ × ℤ} : E n (border n) c ↔ intr n c := by + unfold E intr + rw [mem_SZ_border, mem_BZ] + omega + +/-- For the border placement every interior square is reached from every direction. -/ +private lemma Y_border {n : ℕ} {d c : ℤ × ℤ} (hd : unitDir d) (hd0 : d ≠ (0, 0)) : + Y n (border n) d c = if intr n c then 1 else 0 := by + split_ifs with hc + · apply le_antisymm (Y_le_one _ _ _ _) + obtain ⟨d1, d2, d3, d4⟩ := hd + have hc' := hc + obtain ⟨c1, c2, c3, c4⟩ := hc' + have hex : ∃ m : ℕ, ¬ intr n (sh c d (-((m : ℤ) + 1))) := by + refine ⟨n - 3, fun h => ?_⟩ + obtain ⟨e1, e2, e3, e4⟩ := h + simp only [sh] at e1 e2 e3 e4 + push_cast [Nat.cast_sub (show 3 ≤ n by omega)] at e1 e2 e3 e4 + have : d.1 ≠ 0 ∨ d.2 ≠ 0 := by + by_contra hh; push Not at hh; exact hd0 (Prod.ext hh.1 hh.2) + rcases this with h | h + · rcases (show d.1 = 1 ∨ d.1 = -1 by omega) with h' | h' <;> rw [h'] at e1 e2 <;> linarith + · rcases (show d.2 = 1 ∨ d.2 = -1 by omega) with h' | h' <;> rw [h'] at e3 e4 <;> linarith + classical + let k := Nat.find hex + have hk : ¬ intr n (sh c d (-((k : ℤ) + 1))) := Nat.find_spec hex + have hmin : ∀ j < k, intr n (sh c d (-((j : ℤ) + 1))) := fun j hj => by + have := Nat.find_min hex hj; push Not at this; simpa using this + have hkn : k ≤ n - 3 := Nat.find_min' hex (by + intro h + obtain ⟨e1, e2, e3, e4⟩ := h + simp only [sh] at e1 e2 e3 e4 + push_cast [Nat.cast_sub (show 3 ≤ n by omega)] at e1 e2 e3 e4 + have : d.1 ≠ 0 ∨ d.2 ≠ 0 := by + by_contra hh; push Not at hh; exact hd0 (Prod.ext hh.1 hh.2) + rcases this with h | h + · rcases (show d.1 = 1 ∨ d.1 = -1 by omega) with h' | h' <;> rw [h'] at e1 e2 <;> linarith + · rcases (show d.2 = 1 ∨ d.2 = -1 by omega) with h' | h' <;> rw [h'] at e3 e4 <;> linarith) + -- all squares before the stop are interior + have hall : ∀ j < k + 1, intr n (sh c d (-(j : ℤ))) := by + intro j hj + rcases j with _ | j + · simpa [sh_zero] using hc + · have := hmin j (by omega); push_cast; exact this + have hprev : intr n (sh c d (-(k : ℤ))) := hall k (by omega) + have hstop : sh c d (-((k : ℤ) + 1)) ∈ SZ (border n) := by + rw [mem_SZ_border, mem_BZ] + obtain ⟨f1, f2, f3, f4⟩ := hprev + simp only [intr, sh, not_and_or, not_le] at hk f1 f2 f3 f4 ⊢ + constructor + · constructor <;> [skip; constructor] <;> [skip; skip; constructor] <;> nlinarith + · rcases hk with h | h | h | h + · left; nlinarith + · right; left; nlinarith + · right; right; left; nlinarith + · right; right; right; nlinarith + unfold Y + calc 1 = (if (sh c d (-((k : ℤ) + 1)) ∈ SZ (border n) ∧ + ∀ j < k + 1, E n (border n) (sh c d (-(j : ℤ)))) then 1 else 0) := by + rw [if_pos ⟨hstop, fun j hj => E_border.mpr (hall j hj)⟩] + _ ≤ _ := Finset.single_le_sum (f := fun k : ℕ => if (sh c d (-((k : ℤ) + 1)) ∈ + SZ (border n) ∧ ∀ j < k + 1, E n (border n) (sh c d (-(j : ℤ)))) then 1 else 0) + (fun _ _ => Nat.zero_le _) (Finset.mem_range.mpr (by omega)) + · exact Y_eq_zero_of_not_E (fun h => hc (E_border.mp h)) + +/-- There are `(n - 2)²` interior squares. -/ +private lemma count_interior {n : ℕ} (hn : 2 ≤ n) : + ∑ c ∈ BZ n, (if intr n c then 1 else 0 : ℕ) = (n - 2) ^ 2 := by + rw [BZ, Finset.sum_map, board, Finset.sum_product] + have h1 : ∀ i ∈ Finset.range n, ∑ j ∈ Finset.range n, + (if intr n (emb (i, j)) then 1 else 0 : ℕ) = + if 1 ≤ i ∧ i ≤ n - 2 then n - 2 else 0 := by + intro i hi + rw [Finset.mem_range] at hi + have : ∀ j ∈ Finset.range n, (if intr n (emb (i, j)) then 1 else 0 : ℕ) = + if (1 ≤ i ∧ i ≤ n - 2) ∧ (1 ≤ j ∧ j ≤ n - 2) then 1 else 0 := by + intro j hj + rw [Finset.mem_range] at hj + apply if_congr _ rfl rfl + simp only [intr, emb_apply] + omega + rw [Finset.sum_congr rfl this] + split_ifs with h + · simp only [h, true_and] + rw [Finset.sum_boole] + have : (Finset.range n).filter (fun j => 1 ≤ j ∧ j ≤ n - 2) = Finset.Icc 1 (n - 2) := by + ext j; simp only [Finset.mem_filter, Finset.mem_range, Finset.mem_Icc]; omega + rw [this, Nat.card_Icc]; simp + · simp [h] + rw [Finset.sum_congr rfl h1, Finset.sum_ite, Finset.sum_const_zero, add_zero, + Finset.sum_const, smul_eq_mul] + have : (Finset.range n).filter (fun i => 1 ≤ i ∧ i ≤ n - 2) = Finset.Icc 1 (n - 2) := by + ext j; simp only [Finset.mem_filter, Finset.mem_range, Finset.mem_Icc]; omega + rw [this, Nat.card_Icc, Nat.add_sub_cancel, sq] + +/-- Exchanging a sum over the pieces with a sum over the list of directions. -/ +private lemma sum_swap_list (S : Finset (ℕ × ℕ)) (L : List (ℤ × ℤ)) (f : ℕ × ℕ → ℤ × ℤ → ℕ) : + ∑ p ∈ S, (L.map (f p)).sum = (L.map fun d => ∑ p ∈ S, f p d).sum := by + induction L with + | nil => simp + | cons d L ih => simp [Finset.sum_add_distrib, ih] + +/-- The border placement has `#dirs · (n - 2)²` moves. -/ +private lemma total_border {n : ℕ} (hn : 2 ≤ n) (dirs : List (ℤ × ℤ)) + (hdirs : ∀ d ∈ dirs, unitDir d ∧ d ≠ (0, 0)) : + totalMoves dirs n (border n) = dirs.length * (n - 2) ^ 2 := by + unfold totalMoves + rw [sum_swap_list] + have : ∀ d ∈ dirs, ∑ p ∈ border n, rayMoves n (border n) p d = (n - 2) ^ 2 := by + intro d hd + rw [sum_ray_eq, ← count_interior hn] + apply Finset.sum_congr rfl + intro c _ + exact Y_border (hdirs d hd).1 (hdirs d hd).2 + rw [List.map_congr_left this] + simp + +/-- The border placement lies on the board. -/ +private lemma border_sub (n : ℕ) : border n ⊆ board n := Finset.filter_subset _ _ + + +/-! ### Small boards -/ + +/-- Flow certificate 0 for bishop4. -/ +private def bishop4_t0 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 1), (1, 1, 1, 2, 1), (1, 1, 1, 3, 1), (1, 1, 2, 1, 1), (1, -1, 1, 1, 1), + (1, -1, 1, 2, 1), (1, -1, 2, 2, 1), (-1, 1, 0, 1, 1), (-1, 1, 1, 1, 1), (-1, 1, 2, 1, 1), + (-1, 1, 2, 2, 1), (-1, 1, 2, 3, 1), (-1, -1, 1, 2, 1), (-1, -1, 2, 0, 1), (-1, -1, 2, 1, 1), + (-1, -1, 2, 2, 1)] + +/-- Upper bound for bishops on the 4 × 4 board (branch and bound with flow certificates). -/ +private theorem bishop4_le {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 4) : + totalMoves bishopDirs 4 S ≤ 20 := by + exact leaf hS 1 (by norm_num) bishopDirs (tab bishop4_t0) [] [] 20 + (by decide +kernel) (by decide +kernel) (by simp) (by simp) + +/-- Flow certificate 0 for queen4. -/ +private def queen4_t0 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 6), (1, 1, 1, 3, 3), (1, 1, 2, 1, 3), (1, 1, 2, 2, 3), (1, -1, 1, 1, 3), + (1, -1, 1, 2, 6), (1, -1, 2, 1, 3), (1, -1, 2, 2, 3), (1, -1, 3, 2, 3), (-1, 1, 1, 2, 3), + (-1, 1, 1, 3, 2), (-1, 1, 2, 1, 6), (-1, 1, 2, 2, 5), (-1, 1, 2, 3, 3), (-1, -1, 0, 2, 2), + (-1, -1, 1, 0, 3), (-1, -1, 1, 1, 3), (-1, -1, 1, 2, 3), (-1, -1, 2, 1, 6), + (-1, -1, 2, 2, 6), (1, 0, 1, 0, 3), (1, 0, 1, 2, 4), (1, 0, 2, 2, 1), (-1, 0, 1, 1, 3), + (-1, 0, 2, 1, 6), (-1, 0, 2, 2, 3), (-1, 0, 2, 3, 3), (0, 1, 1, 1, 6), (0, 1, 1, 2, 3), + (0, 1, 3, 1, 3), (0, -1, 0, 2, 3), (0, -1, 1, 1, 2), (0, -1, 1, 2, 5), (0, -1, 2, 2, 3)] + +/-- Flow certificate 1 for queen4. -/ +private def queen4_t1 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 4), (1, 1, 2, 1, 2), (1, 1, 2, 2, 2), (1, 1, 3, 1, 2), (1, -1, 1, 2, 4), + (1, -1, 2, 0, 2), (1, -1, 2, 1, 2), (1, -1, 2, 2, 2), (1, -1, 3, 2, 2), (-1, 1, 1, 1, 2), + (-1, 1, 1, 2, 1), (-1, 1, 2, 1, 3), (-1, 1, 2, 2, 2), (-1, 1, 2, 3, 2), (-1, -1, 1, 1, 1), + (-1, -1, 1, 2, 2), (-1, -1, 2, 0, 2), (-1, -1, 2, 1, 2), (-1, -1, 2, 2, 3), (1, 0, 1, 0, 2), + (1, 0, 1, 3, 2), (-1, 0, 1, 1, 1), (-1, 0, 1, 2, 1), (-1, 0, 2, 0, 2), (-1, 0, 2, 1, 3), + (-1, 0, 2, 2, 3), (-1, 0, 2, 3, 2), (0, 1, 1, 1, 4), (0, 1, 1, 2, 2), (0, 1, 2, 1, 4), + (0, 1, 2, 2, 2), (0, 1, 3, 1, 1), (0, -1, 1, 0, 2), (0, -1, 1, 1, 4), (0, -1, 1, 2, 6), + (0, -1, 2, 0, 2), (0, -1, 2, 2, 2), (0, -1, 3, 2, 1)] + +/-- Flow certificate 2 for queen4. -/ +private def queen4_t2 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 1), (1, 1, 1, 3, 1), (1, 1, 2, 1, 1), (1, 1, 3, 1, 1), (1, -1, 1, 1, 2), + (1, -1, 1, 2, 2), (1, -1, 2, 0, 1), (1, -1, 2, 1, 1), (1, -1, 2, 2, 1), (1, -1, 3, 2, 1), + (-1, 1, 0, 2, 1), (-1, 1, 1, 1, 2), (-1, 1, 2, 1, 1), (-1, 1, 2, 2, 1), (-1, 1, 2, 3, 1), + (-1, -1, 0, 2, 1), (-1, -1, 1, 2, 1), (-1, -1, 2, 0, 1), (-1, -1, 2, 1, 1), + (-1, -1, 2, 2, 1), (1, 0, 1, 0, 2), (1, 0, 1, 2, 2), (1, 0, 2, 0, 1), (1, 0, 2, 1, 1), + (1, 0, 2, 2, 1), (-1, 0, 0, 2, 1), (-1, 0, 2, 0, 1), (-1, 0, 2, 1, 1), (-1, 0, 2, 2, 1), + (-1, 0, 2, 3, 1), (0, 1, 1, 1, 2), (0, 1, 1, 2, 1), (0, 1, 2, 1, 2), (0, 1, 2, 2, 1), + (0, 1, 3, 1, 1), (0, -1, 0, 2, 1), (0, -1, 1, 1, 1), (0, -1, 1, 2, 2), (0, -1, 2, 0, 1), + (0, -1, 2, 2, 1), (0, -1, 3, 2, 1)] + +/-- Flow certificate 3 for queen4. -/ +private def queen4_t3 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 4), (1, 1, 1, 2, 3), (1, 1, 2, 1, 2), (1, 1, 2, 2, 2), (1, 1, 2, 3, 1), + (1, -1, 1, 0, 2), (1, -1, 1, 2, 4), (1, -1, 2, 1, 2), (1, -1, 2, 2, 2), (1, -1, 3, 2, 2), + (-1, 1, 0, 1, 2), (-1, 1, 1, 1, 2), (-1, 1, 1, 2, 1), (-1, 1, 2, 1, 3), (-1, 1, 2, 3, 1), + (-1, -1, 0, 1, 2), (-1, -1, 1, 1, 2), (-1, -1, 1, 2, 3), (-1, -1, 2, 1, 2), + (-1, -1, 2, 2, 4), (1, 0, 1, 1, 4), (1, 0, 1, 3, 2), (1, 0, 2, 1, 2), (-1, 0, 0, 1, 2), + (-1, 0, 1, 0, 1), (-1, 0, 1, 2, 1), (-1, 0, 2, 0, 3), (-1, 0, 2, 2, 3), (0, 1, 0, 1, 2), + (0, 1, 1, 1, 2), (0, 1, 2, 1, 4), (0, 1, 2, 2, 2), (0, -1, 0, 1, 2), (0, -1, 1, 1, 2), + (0, -1, 1, 2, 4), (0, -1, 2, 1, 1), (0, -1, 2, 2, 3), (0, -1, 3, 2, 2)] + +/-- Flow certificate 4 for queen4. -/ +private def queen4_t4 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 1), (1, 1, 1, 2, 2), (1, 1, 1, 3, 1), (1, 1, 2, 1, 2), (1, 1, 2, 3, 1), + (1, 1, 3, 2, 1), (1, -1, 1, 0, 1), (1, -1, 1, 1, 1), (1, -1, 2, 2, 1), (1, -1, 3, 2, 1), + (-1, 1, 0, 1, 1), (-1, 1, 0, 2, 1), (-1, 1, 1, 1, 2), (-1, 1, 1, 2, 1), (-1, 1, 2, 1, 2), + (-1, -1, 0, 1, 1), (-1, -1, 0, 2, 1), (-1, -1, 1, 1, 1), (-1, -1, 1, 2, 2), + (-1, -1, 2, 1, 1), (-1, -1, 2, 2, 2), (1, 0, 1, 1, 2), (1, 0, 1, 2, 2), (1, 0, 1, 3, 1), + (1, 0, 2, 1, 1), (1, 0, 2, 2, 1), (-1, 0, 0, 1, 1), (-1, 0, 0, 2, 1), (-1, 0, 2, 0, 1), + (-1, 0, 2, 2, 1), (0, 1, 0, 1, 2), (0, 1, 0, 2, 1), (0, 1, 1, 1, 1), (0, 1, 2, 1, 2), + (0, 1, 2, 2, 1), (0, -1, 0, 1, 1), (0, -1, 0, 2, 2), (0, -1, 1, 2, 1), (0, -1, 2, 2, 1), + (0, -1, 3, 2, 1)] + +/-- Flow certificate 5 for queen4. -/ +private def queen4_t5 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 1), (1, 1, 1, 2, 2), (1, 1, 2, 1, 1), (1, 1, 2, 3, 1), (1, 1, 3, 1, 1), + (1, -1, 1, 0, 1), (1, -1, 1, 2, 2), (1, -1, 2, 1, 1), (1, -1, 2, 2, 2), (1, -1, 3, 1, 1), + (-1, 1, 0, 1, 1), (-1, 1, 1, 1, 1), (-1, 1, 1, 3, 1), (-1, 1, 2, 2, 2), (-1, -1, 0, 1, 1), + (-1, -1, 1, 2, 2), (-1, -1, 2, 0, 1), (-1, -1, 2, 1, 1), (-1, -1, 2, 2, 1), (1, 0, 1, 0, 1), + (1, 0, 1, 1, 3), (1, 0, 1, 3, 1), (1, 0, 2, 1, 2), (1, 0, 3, 1, 1), (-1, 0, 0, 1, 1), + (-1, 0, 1, 1, 2), (-1, 0, 1, 2, 1), (-1, 0, 2, 0, 1), (-1, 0, 2, 1, 2), (-1, 0, 2, 2, 2), + (-1, 0, 2, 3, 1), (0, 1, 0, 1, 1), (0, 1, 1, 1, 1), (0, 1, 2, 1, 1), (0, 1, 3, 1, 2), + (0, 1, 3, 2, 1), (0, -1, 0, 1, 1), (0, -1, 1, 2, 1), (0, -1, 2, 2, 1), (0, -1, 3, 1, 1), + (0, -1, 3, 2, 1)] + +/-- Flow certificate 6 for queen4. -/ +private def queen4_t6 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 2, 4), (1, 1, 1, 3, 2), (1, 1, 2, 1, 2), (1, 1, 2, 3, 2), (1, 1, 3, 1, 2), + (1, -1, 1, 0, 2), (1, -1, 1, 1, 2), (1, -1, 1, 2, 2), (1, -1, 2, 2, 4), (1, -1, 3, 1, 2), + (-1, 1, 0, 1, 2), (-1, 1, 0, 2, 2), (-1, 1, 1, 1, 4), (-1, 1, 1, 3, 1), (-1, 1, 2, 1, 2), + (-1, 1, 2, 2, 3), (-1, -1, 0, 1, 2), (-1, -1, 0, 2, 2), (-1, -1, 1, 2, 4), (-1, -1, 2, 0, 2), + (-1, -1, 2, 1, 2), (-1, -1, 2, 2, 2), (1, 0, 1, 0, 2), (1, 0, 1, 1, 6), (1, 0, 1, 2, 4), + (1, 0, 2, 1, 4), (1, 0, 2, 2, 2), (1, 0, 3, 1, 2), (-1, 0, 0, 1, 2), (-1, 0, 0, 2, 2), + (-1, 0, 1, 1, 2), (-1, 0, 1, 2, 1), (-1, 0, 2, 1, 4), (-1, 0, 2, 2, 3), (-1, 0, 2, 3, 2), + (0, 1, 0, 1, 4), (0, 1, 0, 2, 2), (0, 1, 1, 1, 2), (0, 1, 2, 1, 2), (0, 1, 3, 1, 4), + (0, 1, 3, 2, 2), (0, -1, 0, 1, 2), (0, -1, 0, 2, 4), (0, -1, 1, 2, 1), (0, -1, 2, 2, 2), + (0, -1, 3, 1, 2), (0, -1, 3, 2, 3)] + +/-- Upper bound for queens on the 4 × 4 board (branch and bound with flow certificates). -/ +private theorem queen4_le {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 4) : + totalMoves queenDirs 4 S ≤ 41 := by + by_cases h0 : ((0, 1) : ℕ × ℕ) ∈ S + · by_cases h1 : ((2, 0) : ℕ × ℕ) ∈ S + · exact leaf hS 3 (by norm_num) queenDirs (tab queen4_t0) [(0, 1), (2, 0)] [] 41 + (by decide +kernel) (by decide +kernel) (by simp [h0, h1]) (by simp) + · by_cases h2 : ((0, 2) : ℕ × ℕ) ∈ S + · exact leaf hS 2 (by norm_num) queenDirs (tab queen4_t1) [(0, 1), (0, 2)] [(2, 0)] 41 + (by decide +kernel) (by decide +kernel) (by simp [h0, h2]) (by simp [h1]) + · exact leaf hS 1 (by norm_num) queenDirs (tab queen4_t2) [(0, 1)] [(0, 2), (2, 0)] 41 + (by decide +kernel) (by decide +kernel) (by simp [h0]) (by simp [h1, h2]) + · by_cases h1 : ((3, 1) : ℕ × ℕ) ∈ S + · by_cases h2 : ((0, 2) : ℕ × ℕ) ∈ S + · exact leaf hS 2 (by norm_num) queenDirs (tab queen4_t3) [(0, 2), (3, 1)] [(0, 1)] 41 + (by decide +kernel) (by decide +kernel) (by simp [h1, h2]) (by simp [h0]) + · exact leaf hS 1 (by norm_num) queenDirs (tab queen4_t4) [(3, 1)] [(0, 1), (0, 2)] 41 + (by decide +kernel) (by decide +kernel) (by simp [h1]) (by simp [h0, h2]) + · by_cases h2 : ((0, 2) : ℕ × ℕ) ∈ S + · exact leaf hS 1 (by norm_num) queenDirs (tab queen4_t5) [(0, 2)] [(0, 1), (3, 1)] 41 + (by decide +kernel) (by decide +kernel) (by simp [h2]) (by simp [h0, h1]) + · exact leaf hS 2 (by norm_num) queenDirs (tab queen4_t6) [] [(0, 1), (0, 2), (3, 1)] 41 + (by decide +kernel) (by decide +kernel) (by simp) (by simp [h0, h1, h2]) + +/-- Flow certificate 0 for bishop5. -/ +private def bishop5_t0 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 1), (1, 1, 1, 2, 2), (1, 1, 1, 3, 1), (1, 1, 2, 1, 2), (1, 1, 2, 3, 1), + (1, 1, 3, 1, 1), (1, 1, 3, 2, 1), (1, -1, 1, 1, 1), (1, -1, 1, 2, 1), (1, -1, 1, 3, 1), + (1, -1, 2, 3, 1), (1, -1, 3, 3, 1), (1, -1, 4, 3, 1), (-1, 1, 1, 1, 1), (-1, 1, 1, 2, 1), + (-1, 1, 2, 1, 2), (-1, 1, 2, 3, 1), (-1, 1, 3, 1, 1), (-1, 1, 3, 2, 2), (-1, 1, 3, 3, 1), + (-1, -1, 0, 3, 1), (-1, -1, 1, 1, 1), (-1, -1, 1, 3, 1), (-1, -1, 2, 3, 1), + (-1, -1, 3, 1, 1), (-1, -1, 3, 2, 1), (-1, -1, 3, 3, 1)] + +/-- Upper bound for bishops on the 5 × 5 board (branch and bound with flow certificates). -/ +private theorem bishop5_le {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 5) : + totalMoves bishopDirs 5 S ≤ 38 := by + exact leaf hS 1 (by norm_num) bishopDirs (tab bishop5_t0) [] [] 38 + (by decide +kernel) (by decide +kernel) (by simp) (by simp) + +/-- Flow certificate 0 for queen5. -/ +private def queen5_t0 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 20), (1, 1, 1, 2, 16), (1, 1, 1, 3, 9), (1, 1, 2, 2, 12), (1, 1, 2, 3, 8), + (1, 1, 2, 4, 1), (1, 1, 3, 1, 10), (1, 1, 3, 3, 4), (1, 1, 4, 2, 2), (1, -1, 1, 1, 16), + (1, -1, 1, 2, 16), (1, -1, 1, 3, 9), (1, -1, 2, 0, 8), (1, -1, 2, 1, 8), (1, -1, 2, 2, 1), + (1, -1, 2, 3, 16), (1, -1, 3, 2, 8), (1, -1, 3, 3, 14), (1, -1, 4, 2, 6), (-1, 1, 1, 1, 8), + (-1, 1, 1, 2, 8), (-1, 1, 1, 3, 5), (-1, 1, 2, 1, 16), (-1, 1, 2, 2, 13), (-1, 1, 3, 1, 21), + (-1, 1, 3, 3, 8), (-1, -1, 1, 3, 8), (-1, -1, 2, 1, 8), (-1, -1, 2, 2, 8), (-1, -1, 3, 1, 8), + (-1, -1, 3, 2, 16), (-1, -1, 3, 3, 16), (1, 0, 1, 1, 20), (1, 0, 1, 2, 15), (1, 0, 1, 3, 17), + (1, 0, 1, 4, 8), (1, 0, 2, 1, 12), (1, 0, 2, 2, 7), (1, 0, 2, 3, 9), (1, 0, 3, 1, 4), + (1, 0, 3, 3, 1), (-1, 0, 2, 2, 8), (-1, 0, 2, 3, 8), (-1, 0, 3, 0, 3), (-1, 0, 3, 2, 16), + (-1, 0, 3, 3, 16), (0, 1, 0, 1, 4), (0, 1, 2, 1, 14), (0, 1, 2, 2, 6), (0, 1, 3, 1, 21), + (0, 1, 3, 2, 13), (0, 1, 3, 3, 5), (0, -1, 0, 3, 7), (0, -1, 1, 2, 8), (0, -1, 1, 3, 16), + (0, -1, 2, 1, 1), (0, -1, 2, 2, 9), (0, -1, 2, 3, 17), (0, -1, 3, 2, 8), (0, -1, 4, 3, 8)] + +/-- Flow certificate 1 for queen5. -/ +private def queen5_t1 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 12), (1, 1, 1, 2, 6), (1, 1, 1, 3, 6), (1, 1, 1, 4, 3), (1, 1, 2, 2, 6), + (1, 1, 3, 1, 6), (1, 1, 3, 4, 6), (1, -1, 1, 1, 12), (1, -1, 1, 2, 12), (1, -1, 1, 3, 12), + (1, -1, 2, 0, 6), (1, -1, 2, 1, 6), (1, -1, 2, 2, 6), (1, -1, 2, 3, 12), (1, -1, 3, 2, 6), + (1, -1, 3, 3, 6), (1, -1, 4, 3, 6), (-1, 1, 1, 1, 6), (-1, 1, 1, 2, 6), (-1, 1, 2, 1, 12), + (-1, 1, 2, 2, 6), (-1, 1, 3, 1, 12), (-1, 1, 3, 3, 6), (-1, 1, 3, 4, 6), (-1, -1, 1, 2, 6), + (-1, -1, 1, 3, 6), (-1, -1, 2, 1, 4), (-1, -1, 2, 2, 2), (-1, -1, 2, 3, 12), + (-1, -1, 3, 1, 6), (-1, -1, 3, 2, 10), (-1, -1, 3, 3, 8), (1, 0, 1, 1, 18), (1, 0, 1, 2, 12), + (1, 0, 1, 3, 14), (1, 0, 1, 4, 5), (1, 0, 2, 1, 12), (1, 0, 2, 2, 6), (1, 0, 2, 3, 8), + (1, 0, 3, 1, 6), (1, 0, 3, 3, 2), (1, 0, 3, 4, 6), (-1, 0, 1, 2, 2), (-1, 0, 2, 2, 8), + (-1, 0, 2, 3, 2), (-1, 0, 2, 4, 4), (-1, 0, 3, 0, 6), (-1, 0, 3, 2, 14), (-1, 0, 3, 3, 8), + (-1, 0, 3, 4, 10), (0, 1, 0, 1, 6), (0, 1, 2, 1, 12), (0, 1, 2, 2, 6), (0, 1, 3, 1, 12), + (0, 1, 3, 2, 6), (0, 1, 3, 4, 6), (0, -1, 0, 3, 1), (0, -1, 1, 2, 4), (0, -1, 1, 3, 10), + (0, -1, 2, 1, 2), (0, -1, 2, 2, 8), (0, -1, 2, 3, 14), (0, -1, 3, 1, 6), (0, -1, 3, 2, 12), + (0, -1, 3, 3, 18)] + +/-- Flow certificate 2 for queen5. -/ +private def queen5_t2 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 32), (1, 1, 1, 2, 32), (1, 1, 1, 3, 32), (1, 1, 2, 2, 16), (1, 1, 2, 3, 16), + (1, 1, 2, 4, 16), (1, 1, 3, 1, 16), (1, 1, 4, 1, 16), (1, -1, 1, 1, 30), (1, -1, 1, 2, 32), + (1, -1, 1, 3, 32), (1, -1, 2, 0, 14), (1, -1, 2, 1, 16), (1, -1, 2, 2, 16), + (1, -1, 3, 3, 16), (1, -1, 4, 1, 16), (-1, 1, 1, 1, 16), (-1, 1, 1, 2, 4), (-1, 1, 2, 1, 20), + (-1, 1, 2, 2, 10), (-1, 1, 2, 3, 16), (-1, 1, 3, 1, 26), (-1, 1, 3, 2, 32), + (-1, 1, 3, 3, 16), (-1, 1, 3, 4, 13), (-1, -1, 1, 1, 2), (-1, -1, 1, 2, 16), + (-1, -1, 1, 3, 16), (-1, -1, 2, 1, 10), (-1, -1, 2, 2, 18), (-1, -1, 2, 3, 32), + (-1, -1, 3, 0, 16), (-1, -1, 3, 1, 16), (-1, -1, 3, 2, 26), (-1, -1, 3, 3, 34), + (1, 0, 1, 1, 32), (1, 0, 1, 2, 18), (1, 0, 1, 3, 32), (1, 0, 2, 1, 16), (1, 0, 2, 2, 2), + (1, 0, 2, 3, 16), (1, 0, 4, 1, 16), (-1, 0, 1, 1, 16), (-1, 0, 1, 2, 16), (-1, 0, 2, 1, 32), + (-1, 0, 2, 2, 32), (-1, 0, 2, 3, 14), (-1, 0, 3, 0, 6), (-1, 0, 3, 1, 48), (-1, 0, 3, 2, 48), + (-1, 0, 3, 3, 30), (-1, 0, 3, 4, 3), (0, 1, 0, 1, 16), (0, 1, 2, 1, 34), (0, 1, 2, 2, 18), + (0, 1, 2, 3, 2), (0, 1, 3, 1, 22), (0, 1, 3, 2, 6), (0, 1, 4, 1, 16), (0, -1, 0, 3, 16), + (0, -1, 2, 2, 16), (0, -1, 2, 3, 32), (0, -1, 3, 2, 16), (0, -1, 3, 3, 32), + (0, -1, 4, 1, 16), (0, -1, 4, 3, 11)] + +/-- Flow certificate 3 for queen5. -/ +private def queen5_t3 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 16), (1, 1, 1, 2, 15), (1, 1, 1, 3, 11), (1, 1, 1, 4, 8), (1, 1, 2, 2, 8), + (1, 1, 2, 3, 7), (1, 1, 2, 4, 3), (1, 1, 3, 1, 8), (1, 1, 4, 1, 8), (1, -1, 1, 1, 13), + (1, -1, 1, 2, 14), (1, -1, 1, 3, 16), (1, -1, 2, 0, 5), (1, -1, 2, 1, 6), (1, -1, 2, 2, 8), + (1, -1, 2, 3, 16), (1, -1, 3, 2, 8), (1, -1, 3, 3, 8), (1, -1, 4, 1, 8), (1, -1, 4, 3, 8), + (-1, 1, 1, 1, 8), (-1, 1, 1, 2, 8), (-1, 1, 1, 4, 8), (-1, 1, 2, 1, 16), (-1, 1, 2, 2, 8), + (-1, 1, 2, 3, 16), (-1, 1, 2, 4, 8), (-1, 1, 3, 1, 16), (-1, 1, 3, 2, 24), (-1, 1, 3, 3, 16), + (-1, 1, 3, 4, 8), (-1, -1, 0, 3, 8), (-1, -1, 1, 3, 8), (-1, -1, 2, 2, 8), (-1, -1, 2, 3, 8), + (-1, -1, 3, 0, 8), (-1, -1, 3, 1, 8), (-1, -1, 3, 2, 8), (-1, -1, 3, 3, 16), + (1, 0, 1, 1, 16), (1, 0, 1, 2, 16), (1, 0, 1, 3, 10), (1, 0, 1, 4, 8), (1, 0, 2, 1, 8), + (1, 0, 2, 2, 8), (1, 0, 2, 3, 2), (1, 0, 4, 1, 8), (-1, 0, 1, 1, 8), (-1, 0, 2, 1, 16), + (-1, 0, 2, 2, 8), (-1, 0, 3, 1, 24), (-1, 0, 3, 2, 16), (-1, 0, 3, 3, 8), (0, 1, 0, 1, 8), + (0, 1, 1, 4, 8), (0, 1, 2, 1, 18), (0, 1, 2, 2, 10), (0, 1, 2, 3, 2), (0, 1, 3, 1, 8), + (0, 1, 4, 1, 8), (0, -1, 1, 1, 3), (0, -1, 1, 2, 11), (0, -1, 1, 3, 19), (0, -1, 2, 2, 5), + (0, -1, 2, 3, 13), (0, -1, 3, 2, 8), (0, -1, 3, 3, 16), (0, -1, 4, 1, 8), (0, -1, 4, 3, 8)] + +/-- Flow certificate 4 for queen5. -/ +private def queen5_t4 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 26), (1, 1, 1, 2, 20), (1, 1, 1, 3, 30), (1, 1, 2, 1, 32), (1, 1, 2, 2, 10), + (1, 1, 2, 3, 4), (1, 1, 2, 4, 14), (1, 1, 3, 1, 16), (1, 1, 3, 2, 16), (1, 1, 4, 1, 13), + (1, -1, 1, 0, 16), (1, -1, 1, 1, 16), (1, -1, 1, 3, 32), (1, -1, 2, 2, 16), + (1, -1, 2, 3, 32), (1, -1, 3, 2, 16), (1, -1, 3, 3, 16), (-1, 1, 0, 1, 16), + (-1, 1, 1, 1, 16), (-1, 1, 1, 2, 10), (-1, 1, 1, 3, 2), (-1, 1, 2, 1, 26), (-1, 1, 2, 2, 18), + (-1, 1, 2, 3, 16), (-1, 1, 2, 4, 16), (-1, 1, 3, 1, 34), (-1, 1, 3, 2, 32), + (-1, 1, 3, 3, 32), (-1, -1, 1, 0, 16), (-1, -1, 1, 2, 16), (-1, -1, 1, 3, 16), + (-1, -1, 2, 2, 16), (-1, -1, 2, 3, 32), (-1, -1, 3, 1, 16), (-1, -1, 3, 3, 32), + (1, 0, 1, 0, 16), (1, 0, 1, 1, 22), (1, 0, 1, 2, 34), (1, 0, 1, 4, 16), (1, 0, 2, 1, 6), + (1, 0, 2, 2, 18), (1, 0, 3, 2, 2), (-1, 0, 2, 1, 16), (-1, 0, 2, 2, 16), (-1, 0, 3, 0, 11), + (-1, 0, 3, 1, 32), (-1, 0, 3, 2, 32), (-1, 0, 3, 4, 16), (0, 1, 0, 1, 6), (0, 1, 1, 1, 48), + (0, 1, 1, 2, 32), (0, 1, 1, 3, 16), (0, 1, 2, 1, 48), (0, 1, 2, 2, 32), (0, 1, 2, 3, 16), + (0, 1, 3, 1, 30), (0, 1, 3, 2, 14), (0, 1, 4, 1, 3), (0, -1, 1, 0, 16), (0, -1, 1, 2, 16), + (0, -1, 1, 3, 32), (0, -1, 2, 2, 2), (0, -1, 2, 3, 18), (0, -1, 3, 2, 16), (0, -1, 3, 3, 32)] + +/-- Flow certificate 5 for queen5. -/ +private def queen5_t5 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 1), (1, 1, 1, 2, 1), (1, 1, 1, 3, 1), (1, 1, 1, 4, 1), (1, 1, 2, 1, 2), + (1, 1, 3, 1, 1), (1, 1, 3, 2, 1), (1, -1, 1, 0, 1), (1, -1, 1, 1, 1), (1, -1, 1, 2, 2), + (1, -1, 1, 3, 1), (1, -1, 2, 1, 1), (1, -1, 2, 3, 1), (1, -1, 3, 3, 1), (-1, 1, 0, 1, 1), + (-1, 1, 0, 3, 1), (-1, 1, 1, 1, 1), (-1, 1, 2, 2, 1), (-1, 1, 2, 3, 1), (-1, 1, 3, 1, 2), + (-1, 1, 3, 2, 2), (-1, 1, 3, 3, 1), (-1, -1, 0, 3, 1), (-1, -1, 1, 0, 1), (-1, -1, 1, 3, 1), + (-1, -1, 2, 0, 1), (-1, -1, 2, 2, 1), (-1, -1, 2, 3, 1), (-1, -1, 3, 1, 2), + (-1, -1, 3, 3, 2), (1, 0, 1, 0, 2), (1, 0, 1, 1, 2), (1, 0, 1, 2, 3), (1, 0, 1, 3, 3), + (1, 0, 1, 4, 1), (1, 0, 2, 0, 1), (1, 0, 2, 1, 1), (1, 0, 2, 2, 2), (1, 0, 2, 3, 2), + (1, 0, 3, 2, 1), (1, 0, 3, 3, 1), (-1, 0, 0, 3, 1), (-1, 0, 2, 1, 1), (-1, 0, 2, 2, 1), + (-1, 0, 3, 1, 2), (-1, 0, 3, 2, 2), (-1, 0, 3, 4, 1), (0, 1, 0, 3, 1), (0, 1, 1, 1, 3), + (0, 1, 1, 2, 2), (0, 1, 1, 3, 1), (0, 1, 2, 1, 1), (0, 1, 4, 1, 1), (0, -1, 0, 3, 1), + (0, -1, 1, 0, 1), (0, -1, 1, 3, 1), (0, -1, 2, 1, 1), (0, -1, 2, 2, 2), (0, -1, 2, 3, 3), + (0, -1, 3, 1, 1), (0, -1, 3, 2, 2), (0, -1, 3, 3, 3)] + +/-- Flow certificate 6 for queen5. -/ +private def queen5_t6 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 4), (1, 1, 1, 2, 2), (1, 1, 1, 3, 2), (1, 1, 1, 4, 2), (1, 1, 2, 1, 4), + (1, 1, 2, 2, 2), (1, 1, 3, 1, 2), (1, 1, 3, 2, 2), (1, 1, 4, 1, 2), (1, -1, 1, 0, 2), + (1, -1, 1, 1, 2), (1, -1, 1, 2, 2), (1, -1, 1, 3, 3), (1, -1, 2, 2, 1), (1, -1, 2, 3, 4), + (1, -1, 3, 0, 2), (1, -1, 3, 2, 2), (1, -1, 3, 3, 2), (-1, 1, 0, 1, 2), (-1, 1, 0, 3, 2), + (-1, 1, 1, 1, 2), (-1, 1, 1, 2, 4), (-1, 1, 2, 1, 6), (-1, 1, 3, 1, 2), (-1, 1, 3, 2, 2), + (-1, 1, 3, 3, 2), (-1, -1, 0, 2, 1), (-1, -1, 0, 3, 2), (-1, -1, 1, 0, 2), (-1, -1, 1, 2, 2), + (-1, -1, 1, 3, 3), (-1, -1, 2, 0, 2), (-1, -1, 2, 2, 2), (-1, -1, 2, 3, 4), + (-1, -1, 3, 0, 2), (-1, -1, 3, 1, 4), (-1, -1, 3, 3, 4), (1, 0, 1, 0, 2), (1, 0, 1, 1, 4), + (1, 0, 1, 2, 4), (1, 0, 1, 3, 6), (1, 0, 2, 1, 2), (1, 0, 2, 2, 2), (1, 0, 2, 3, 4), + (1, 0, 3, 3, 2), (-1, 0, 0, 3, 2), (-1, 0, 1, 0, 2), (-1, 0, 2, 2, 2), (-1, 0, 3, 0, 2), + (-1, 0, 3, 1, 2), (-1, 0, 3, 2, 4), (-1, 0, 3, 4, 2), (0, 1, 0, 3, 2), (0, 1, 1, 1, 4), + (0, 1, 1, 2, 2), (0, 1, 2, 1, 4), (0, 1, 2, 2, 2), (0, 1, 3, 1, 6), (0, 1, 3, 2, 4), + (0, 1, 3, 3, 2), (0, 1, 4, 1, 2), (0, -1, 0, 2, 1), (0, -1, 0, 3, 3), (0, -1, 1, 0, 2), + (0, -1, 1, 3, 2), (0, -1, 2, 2, 2), (0, -1, 2, 3, 4), (0, -1, 3, 0, 2), (0, -1, 3, 2, 2), + (0, -1, 3, 3, 4)] + +/-- Flow certificate 7 for queen5. -/ +private def queen5_t7 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 2), (1, 1, 1, 2, 4), (1, 1, 1, 4, 2), (1, 1, 2, 3, 2), (1, 1, 3, 1, 4), + (1, 1, 4, 1, 2), (1, 1, 4, 2, 2), (1, 1, 4, 3, 2), (1, -1, 1, 0, 2), (1, -1, 1, 1, 2), + (1, -1, 1, 2, 2), (1, -1, 1, 3, 4), (1, -1, 2, 2, 2), (1, -1, 2, 3, 3), (1, -1, 3, 2, 1), + (1, -1, 3, 3, 2), (1, -1, 4, 3, 2), (-1, 1, 0, 1, 2), (-1, 1, 0, 2, 2), (-1, 1, 1, 1, 4), + (-1, 1, 2, 2, 2), (-1, 1, 2, 3, 2), (-1, 1, 3, 1, 4), (-1, 1, 3, 2, 4), (-1, 1, 3, 3, 1), + (-1, 1, 3, 4, 2), (-1, -1, 0, 2, 2), (-1, -1, 0, 3, 2), (-1, -1, 1, 0, 2), (-1, -1, 1, 3, 4), + (-1, -1, 2, 2, 2), (-1, -1, 2, 3, 2), (-1, -1, 3, 0, 2), (-1, -1, 3, 1, 2), + (-1, -1, 3, 2, 2), (-1, -1, 3, 3, 4), (1, 0, 1, 0, 4), (1, 0, 1, 1, 2), (1, 0, 1, 2, 4), + (1, 0, 1, 3, 2), (1, 0, 2, 0, 2), (1, 0, 2, 2, 2), (1, 0, 4, 3, 2), (-1, 0, 1, 0, 2), + (-1, 0, 1, 2, 1), (-1, 0, 1, 3, 1), (-1, 0, 2, 2, 3), (-1, 0, 2, 3, 3), (-1, 0, 3, 0, 2), + (-1, 0, 3, 1, 2), (-1, 0, 3, 2, 5), (-1, 0, 3, 3, 5), (0, 1, 1, 1, 6), (0, 1, 1, 2, 4), + (0, 1, 1, 3, 2), (0, 1, 3, 1, 4), (0, 1, 3, 2, 2), (0, -1, 0, 3, 2), (0, -1, 1, 0, 2), + (0, -1, 1, 2, 1), (0, -1, 1, 3, 3), (0, -1, 2, 2, 2), (0, -1, 2, 3, 4), (0, -1, 3, 2, 2), + (0, -1, 3, 3, 4), (0, -1, 4, 3, 2)] + +/-- Flow certificate 8 for queen5. -/ +private def queen5_t8 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 2), (1, 1, 1, 2, 1), (1, 1, 1, 3, 1), (1, 1, 2, 1, 3), (1, 1, 2, 2, 1), + (1, 1, 3, 1, 2), (1, 1, 3, 2, 2), (1, 1, 4, 1, 1), (1, 1, 4, 2, 1), (1, 1, 4, 3, 1), + (1, -1, 1, 0, 1), (1, -1, 1, 1, 1), (1, -1, 1, 3, 2), (1, -1, 2, 2, 1), (1, -1, 2, 3, 2), + (1, -1, 3, 2, 1), (1, -1, 3, 3, 1), (1, -1, 4, 3, 1), (-1, 1, 0, 1, 1), (-1, 1, 1, 1, 1), + (-1, 1, 1, 2, 1), (-1, 1, 2, 1, 2), (-1, 1, 2, 2, 1), (-1, 1, 3, 1, 2), (-1, 1, 3, 3, 1), + (-1, 1, 3, 4, 1), (-1, -1, 0, 2, 1), (-1, -1, 1, 0, 1), (-1, -1, 1, 2, 1), (-1, -1, 1, 3, 2), + (-1, -1, 2, 1, 2), (-1, -1, 2, 2, 1), (-1, -1, 2, 3, 2), (-1, -1, 3, 0, 1), + (-1, -1, 3, 1, 1), (-1, -1, 3, 2, 3), (-1, -1, 3, 3, 2), (1, 0, 1, 0, 1), (1, 0, 1, 1, 2), + (1, 0, 1, 2, 2), (1, 0, 1, 4, 1), (1, 0, 2, 1, 1), (1, 0, 2, 2, 1), (1, 0, 4, 3, 1), + (-1, 0, 1, 0, 1), (-1, 0, 1, 3, 1), (-1, 0, 2, 1, 1), (-1, 0, 2, 2, 1), (-1, 0, 2, 3, 2), + (-1, 0, 3, 1, 2), (-1, 0, 3, 2, 2), (-1, 0, 3, 3, 3), (0, 1, 1, 1, 2), (0, 1, 1, 2, 1), + (0, 1, 2, 1, 2), (0, 1, 2, 2, 1), (0, 1, 3, 1, 1), (0, 1, 4, 1, 1), (0, -1, 1, 0, 1), + (0, -1, 1, 2, 1), (0, -1, 1, 3, 2), (0, -1, 2, 2, 1), (0, -1, 2, 3, 2), (0, -1, 3, 3, 1), + (0, -1, 4, 3, 1)] + +/-- Flow certificate 9 for queen5. -/ +private def queen5_t9 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 4), (1, 1, 1, 2, 2), (1, 1, 1, 3, 2), (1, 1, 1, 4, 2), (1, 1, 2, 1, 6), + (1, 1, 2, 2, 2), (1, 1, 3, 1, 4), (1, 1, 3, 2, 4), (1, 1, 4, 1, 1), (1, 1, 4, 2, 2), + (1, 1, 4, 3, 2), (1, -1, 1, 0, 2), (1, -1, 1, 1, 2), (1, -1, 1, 2, 4), (1, -1, 1, 3, 2), + (1, -1, 2, 1, 2), (1, -1, 2, 3, 2), (1, -1, 3, 3, 1), (1, -1, 4, 3, 2), (-1, 1, 0, 1, 2), + (-1, 1, 0, 3, 2), (-1, 1, 1, 1, 2), (-1, 1, 1, 2, 3), (-1, 1, 2, 1, 5), (-1, 1, 2, 2, 2), + (-1, 1, 3, 1, 4), (-1, 1, 3, 2, 1), (-1, 1, 3, 3, 2), (-1, 1, 3, 4, 2), (-1, -1, 0, 2, 1), + (-1, -1, 0, 3, 2), (-1, -1, 1, 0, 2), (-1, -1, 1, 3, 3), (-1, -1, 2, 1, 4), + (-1, -1, 2, 2, 1), (-1, -1, 2, 3, 2), (-1, -1, 3, 0, 2), (-1, -1, 3, 1, 2), + (-1, -1, 3, 2, 6), (-1, -1, 3, 3, 3), (1, 0, 1, 0, 2), (1, 0, 1, 1, 4), (1, 0, 1, 2, 4), + (1, 0, 1, 3, 3), (1, 0, 1, 4, 1), (1, 0, 2, 1, 2), (1, 0, 2, 2, 2), (1, 0, 2, 3, 1), + (1, 0, 4, 3, 2), (-1, 0, 0, 3, 2), (-1, 0, 1, 3, 3), (-1, 0, 2, 1, 2), (-1, 0, 2, 2, 2), + (-1, 0, 2, 3, 5), (-1, 0, 3, 1, 4), (-1, 0, 3, 2, 4), (-1, 0, 3, 3, 7), (-1, 0, 3, 4, 1), + (0, 1, 0, 3, 2), (0, 1, 1, 1, 4), (0, 1, 1, 2, 2), (0, 1, 2, 1, 4), (0, 1, 2, 2, 2), + (0, 1, 3, 1, 2), (0, 1, 4, 1, 2), (0, -1, 0, 2, 1), (0, -1, 0, 3, 3), (0, -1, 1, 0, 2), + (0, -1, 1, 2, 1), (0, -1, 1, 3, 3), (0, -1, 2, 1, 2), (0, -1, 2, 2, 4), (0, -1, 2, 3, 6), + (0, -1, 3, 2, 1), (0, -1, 3, 3, 3), (0, -1, 4, 3, 2)] + +/-- Upper bound for queens on the 5 × 5 board (branch and bound with flow certificates). -/ +private theorem queen5_le {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 5) : + totalMoves queenDirs 5 S ≤ 77 := by + by_cases h0 : ((1, 0) : ℕ × ℕ) ∈ S + · by_cases h1 : ((4, 1) : ℕ × ℕ) ∈ S + · by_cases h2 : ((3, 4) : ℕ × ℕ) ∈ S + · exact leaf hS 8 (by norm_num) queenDirs (tab queen5_t0) [(1, 0), (3, 4), (4, 1)] [] 77 + (by decide +kernel) (by decide +kernel) (by simp [h0, h1, h2]) (by simp) + · exact leaf hS 6 (by norm_num) queenDirs (tab queen5_t1) [(1, 0), (4, 1)] [(3, 4)] 77 + (by decide +kernel) (by decide +kernel) (by simp [h0, h1]) (by simp [h2]) + · by_cases h2 : ((1, 4) : ℕ × ℕ) ∈ S + · exact leaf hS 16 (by norm_num) queenDirs (tab queen5_t2) [(1, 0), (1, 4)] [(4, 1)] 77 + (by decide +kernel) (by decide +kernel) (by simp [h0, h2]) (by simp [h1]) + · exact leaf hS 8 (by norm_num) queenDirs (tab queen5_t3) [(1, 0)] [(1, 4), (4, 1)] 77 + (by decide +kernel) (by decide +kernel) (by simp [h0]) (by simp [h1, h2]) + · by_cases h1 : ((4, 3) : ℕ × ℕ) ∈ S + · by_cases h2 : ((0, 3) : ℕ × ℕ) ∈ S + · exact leaf hS 16 (by norm_num) queenDirs (tab queen5_t4) [(0, 3), (4, 3)] [(1, 0)] 77 + (by decide +kernel) (by decide +kernel) (by simp [h1, h2]) (by simp [h0]) + · by_cases h3 : ((3, 0) : ℕ × ℕ) ∈ S + · exact leaf hS 1 (by norm_num) queenDirs (tab queen5_t5) [(3, 0), (4, 3)] [(0, 3), (1, 0)] 77 + (by decide +kernel) (by decide +kernel) (by simp [h1, h3]) (by simp [h0, h2]) + · exact leaf hS 2 (by norm_num) queenDirs (tab queen5_t6) [(4, 3)] [(0, 3), (1, 0), (3, 0)] 77 + (by decide +kernel) (by decide +kernel) (by simp [h1]) (by simp [h0, h2, h3]) + · by_cases h2 : ((2, 1) : ℕ × ℕ) ∈ S + · exact leaf hS 2 (by norm_num) queenDirs (tab queen5_t7) [(2, 1)] [(1, 0), (4, 3)] 77 + (by decide +kernel) (by decide +kernel) (by simp [h2]) (by simp [h0, h1]) + · by_cases h3 : ((0, 3) : ℕ × ℕ) ∈ S + · exact leaf hS 1 (by norm_num) queenDirs (tab queen5_t8) [(0, 3)] [(1, 0), (2, 1), (4, 3)] 77 + (by decide +kernel) (by decide +kernel) (by simp [h3]) (by simp [h0, h1, h2]) + · exact leaf hS 2 (by norm_num) queenDirs (tab queen5_t9) [] [(0, 3), (1, 0), (2, 1), (4, 3)] 77 + (by decide +kernel) (by decide +kernel) (by simp) (by simp [h0, h1, h2, h3]) + +/-- Flow certificate 0 for queen6. -/ +private def queen6_t0 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 24), (1, 1, 1, 3, 15), (1, 1, 1, 4, 8), (1, 1, 2, 1, 16), (1, 1, 2, 2, 16), + (1, 1, 2, 4, 7), (1, 1, 3, 1, 16), (1, 1, 3, 2, 8), (1, 1, 3, 3, 8), (1, 1, 4, 1, 5), + (1, 1, 4, 2, 8), (1, 1, 5, 1, 5), (1, -1, 1, 1, 8), (1, -1, 1, 2, 16), (1, -1, 1, 3, 17), + (1, -1, 1, 4, 24), (1, -1, 2, 1, 8), (1, -1, 2, 2, 9), (1, -1, 2, 3, 16), (1, -1, 3, 1, 1), + (1, -1, 3, 2, 8), (1, -1, 3, 4, 8), (1, -1, 4, 4, 8), (1, -1, 5, 4, 2), (-1, 1, 1, 1, 8), + (-1, 1, 1, 2, 8), (-1, 1, 2, 1, 16), (-1, 1, 2, 2, 7), (-1, 1, 2, 3, 3), (-1, 1, 2, 4, 2), + (-1, 1, 3, 1, 15), (-1, 1, 3, 2, 11), (-1, 1, 3, 3, 10), (-1, 1, 3, 4, 6), (-1, 1, 4, 1, 19), + (-1, 1, 4, 2, 18), (-1, 1, 4, 3, 14), (-1, 1, 4, 4, 8), (-1, -1, 1, 2, 7), (-1, -1, 1, 3, 8), + (-1, -1, 1, 4, 8), (-1, -1, 2, 1, 8), (-1, -1, 2, 2, 5), (-1, -1, 2, 3, 15), + (-1, -1, 2, 4, 16), (-1, -1, 3, 1, 5), (-1, -1, 3, 2, 15), (-1, -1, 3, 3, 13), + (-1, -1, 3, 4, 23), (-1, -1, 4, 1, 8), (-1, -1, 4, 2, 12), (-1, -1, 4, 3, 23), + (-1, -1, 4, 4, 21), (1, 0, 1, 2, 17), (1, 0, 1, 3, 16), (1, 0, 1, 4, 23), (1, 0, 2, 2, 9), + (1, 0, 2, 3, 8), (1, 0, 2, 4, 15), (1, 0, 3, 2, 1), (1, 0, 3, 4, 7), (-1, 0, 2, 2, 2), + (-1, 0, 2, 3, 4), (-1, 0, 3, 1, 8), (-1, 0, 3, 2, 10), (-1, 0, 3, 3, 12), (-1, 0, 3, 4, 4), + (-1, 0, 4, 0, 4), (-1, 0, 4, 1, 16), (-1, 0, 4, 2, 18), (-1, 0, 4, 3, 20), (-1, 0, 4, 4, 12), + (0, 1, 1, 1, 24), (0, 1, 1, 2, 16), (0, 1, 1, 3, 8), (0, 1, 2, 1, 16), (0, 1, 2, 2, 8), + (0, 1, 3, 1, 19), (0, 1, 3, 2, 11), (0, 1, 3, 3, 3), (0, 1, 4, 1, 16), (0, 1, 4, 2, 8), + (0, 1, 5, 1, 1), (0, -1, 2, 2, 8), (0, -1, 2, 3, 16), (0, -1, 2, 4, 24), (0, -1, 3, 3, 8), + (0, -1, 3, 4, 16), (0, -1, 4, 3, 7), (0, -1, 4, 4, 15), (0, -1, 5, 4, 3)] + +/-- Flow certificate 1 for queen6. -/ +private def queen6_t1 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 12), (1, 1, 1, 3, 6), (1, 1, 1, 4, 4), (1, 1, 1, 5, 4), (1, 1, 2, 1, 12), + (1, 1, 2, 2, 8), (1, 1, 2, 4, 2), (1, 1, 3, 1, 6), (1, 1, 3, 2, 8), (1, 1, 3, 3, 4), + (1, 1, 4, 1, 4), (1, 1, 4, 2, 2), (1, 1, 4, 3, 4), (1, 1, 5, 1, 4), (1, -1, 1, 1, 4), + (1, -1, 1, 2, 8), (1, -1, 1, 3, 7), (1, -1, 1, 4, 7), (1, -1, 2, 1, 4), (1, -1, 2, 2, 3), + (1, -1, 2, 3, 4), (1, -1, 2, 4, 12), (1, -1, 3, 3, 8), (1, -1, 3, 4, 4), (1, -1, 4, 2, 4), + (1, -1, 4, 4, 4), (-1, 1, 1, 1, 4), (-1, 1, 1, 2, 2), (-1, 1, 1, 5, 4), (-1, 1, 2, 1, 6), + (-1, 1, 2, 2, 4), (-1, 1, 2, 3, 2), (-1, 1, 3, 1, 8), (-1, 1, 3, 2, 6), (-1, 1, 3, 3, 4), + (-1, 1, 3, 4, 4), (-1, 1, 4, 1, 10), (-1, 1, 4, 2, 8), (-1, 1, 4, 3, 8), (-1, 1, 4, 4, 4), + (-1, 1, 4, 5, 1), (-1, -1, 0, 4, 4), (-1, -1, 1, 2, 3), (-1, -1, 1, 3, 2), (-1, -1, 1, 4, 4), + (-1, -1, 2, 3, 6), (-1, -1, 2, 4, 6), (-1, -1, 3, 1, 4), (-1, -1, 3, 2, 4), + (-1, -1, 3, 3, 4), (-1, -1, 3, 4, 10), (-1, -1, 4, 1, 4), (-1, -1, 4, 2, 8), + (-1, -1, 4, 3, 8), (-1, -1, 4, 4, 8), (1, 0, 1, 2, 10), (1, 0, 1, 3, 8), (1, 0, 1, 4, 4), + (1, 0, 1, 5, 4), (1, 0, 2, 2, 6), (1, 0, 2, 3, 4), (1, 0, 3, 2, 2), (-1, 0, 1, 5, 4), + (-1, 0, 3, 1, 4), (-1, 0, 3, 2, 4), (-1, 0, 3, 3, 4), (-1, 0, 3, 4, 4), (-1, 0, 4, 0, 2), + (-1, 0, 4, 1, 8), (-1, 0, 4, 2, 8), (-1, 0, 4, 3, 8), (-1, 0, 4, 4, 8), (-1, 0, 4, 5, 1), + (0, 1, 1, 1, 8), (0, 1, 1, 2, 4), (0, 1, 1, 5, 4), (0, 1, 2, 1, 10), (0, 1, 2, 2, 6), + (0, 1, 2, 3, 2), (0, 1, 3, 1, 10), (0, 1, 3, 2, 6), (0, 1, 3, 3, 2), (0, 1, 4, 1, 6), + (0, 1, 4, 2, 2), (0, -1, 0, 4, 1), (0, -1, 1, 1, 1), (0, -1, 1, 2, 5), (0, -1, 1, 3, 9), + (0, -1, 1, 4, 13), (0, -1, 2, 2, 4), (0, -1, 2, 3, 8), (0, -1, 2, 4, 12), (0, -1, 3, 2, 2), + (0, -1, 3, 3, 6), (0, -1, 3, 4, 10), (0, -1, 4, 3, 4), (0, -1, 4, 4, 8), (0, -1, 5, 4, 3)] + +/-- Flow certificate 2 for queen6. -/ +private def queen6_t2 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 8), (1, 1, 1, 2, 12), (1, 1, 1, 3, 4), (1, 1, 1, 4, 4), (1, 1, 2, 1, 8), + (1, 1, 2, 2, 4), (1, 1, 2, 3, 8), (1, 1, 3, 1, 8), (1, 1, 3, 2, 4), (1, 1, 3, 4, 4), + (1, 1, 4, 1, 4), (1, 1, 4, 2, 4), (1, -1, 1, 0, 4), (1, -1, 1, 1, 4), (1, -1, 1, 2, 6), + (1, -1, 1, 3, 10), (1, -1, 1, 4, 9), (1, -1, 2, 1, 2), (1, -1, 2, 2, 6), (1, -1, 2, 3, 5), + (1, -1, 2, 4, 8), (1, -1, 3, 1, 2), (1, -1, 3, 2, 2), (1, -1, 3, 3, 4), (1, -1, 3, 4, 7), + (1, -1, 4, 3, 3), (1, -1, 4, 4, 4), (1, -1, 5, 4, 1), (-1, 1, 0, 1, 4), (-1, 1, 1, 1, 4), + (-1, 1, 1, 2, 2), (-1, 1, 2, 1, 6), (-1, 1, 2, 3, 4), (-1, 1, 2, 4, 4), (-1, 1, 3, 2, 8), + (-1, 1, 3, 3, 8), (-1, 1, 3, 4, 4), (-1, 1, 4, 1, 12), (-1, 1, 4, 2, 12), (-1, 1, 4, 3, 8), + (-1, 1, 4, 4, 3), (-1, 1, 4, 5, 4), (-1, -1, 0, 1, 4), (-1, -1, 0, 4, 2), (-1, -1, 1, 3, 4), + (-1, -1, 1, 4, 4), (-1, -1, 2, 2, 3), (-1, -1, 2, 3, 3), (-1, -1, 2, 4, 8), + (-1, -1, 3, 1, 4), (-1, -1, 3, 2, 4), (-1, -1, 3, 3, 7), (-1, -1, 3, 4, 7), + (-1, -1, 4, 1, 4), (-1, -1, 4, 2, 8), (-1, -1, 4, 3, 8), (-1, -1, 4, 4, 11), + (1, 0, 1, 1, 12), (1, 0, 1, 2, 12), (1, 0, 1, 3, 10), (1, 0, 1, 4, 7), (1, 0, 1, 5, 2), + (1, 0, 2, 1, 8), (1, 0, 2, 2, 8), (1, 0, 2, 3, 6), (1, 0, 2, 4, 3), (1, 0, 3, 1, 4), + (1, 0, 3, 2, 4), (1, 0, 3, 3, 2), (-1, 0, 0, 1, 4), (-1, 0, 2, 3, 1), (-1, 0, 3, 1, 4), + (-1, 0, 3, 2, 4), (-1, 0, 3, 3, 5), (-1, 0, 3, 4, 2), (-1, 0, 4, 1, 8), (-1, 0, 4, 2, 8), + (-1, 0, 4, 3, 9), (-1, 0, 4, 4, 6), (0, 1, 0, 1, 4), (0, 1, 1, 1, 4), (0, 1, 2, 1, 8), + (0, 1, 2, 2, 4), (0, 1, 3, 1, 10), (0, 1, 3, 2, 6), (0, 1, 3, 3, 2), (0, -1, 0, 1, 4), + (0, -1, 0, 4, 1), (0, -1, 1, 3, 4), (0, -1, 1, 4, 8), (0, -1, 2, 2, 1), (0, -1, 2, 3, 5), + (0, -1, 2, 4, 9), (0, -1, 3, 3, 4), (0, -1, 3, 4, 8), (0, -1, 4, 3, 4), (0, -1, 4, 4, 8), + (0, -1, 5, 4, 1)] + +/-- Flow certificate 3 for queen6. -/ +private def queen6_t3 : List (ℤ × ℤ × ℤ × ℤ × ℕ) := + [(1, 1, 1, 1, 8), (1, 1, 1, 2, 12), (1, 1, 1, 3, 7), (1, 1, 1, 4, 4), (1, 1, 1, 5, 3), + (1, 1, 2, 1, 7), (1, 1, 2, 2, 4), (1, 1, 2, 3, 8), (1, 1, 2, 4, 3), (1, 1, 3, 1, 8), + (1, 1, 3, 2, 4), (1, 1, 3, 4, 4), (1, 1, 4, 1, 4), (1, 1, 4, 2, 4), (1, 1, 5, 1, 4), + (1, -1, 1, 0, 4), (1, -1, 1, 1, 4), (1, -1, 1, 2, 8), (1, -1, 1, 3, 8), (1, -1, 1, 4, 9), + (1, -1, 2, 1, 4), (1, -1, 2, 2, 4), (1, -1, 2, 3, 5), (1, -1, 2, 4, 8), (1, -1, 3, 2, 1), + (1, -1, 3, 3, 4), (1, -1, 3, 4, 5), (1, -1, 4, 0, 4), (1, -1, 4, 3, 1), (1, -1, 4, 4, 4), + (1, -1, 5, 4, 4), (-1, 1, 0, 1, 4), (-1, 1, 1, 1, 4), (-1, 1, 1, 2, 2), (-1, 1, 1, 3, 4), + (-1, 1, 2, 1, 6), (-1, 1, 2, 2, 8), (-1, 1, 3, 1, 12), (-1, 1, 3, 2, 4), (-1, 1, 3, 3, 4), + (-1, 1, 3, 4, 2), (-1, 1, 4, 1, 8), (-1, 1, 4, 2, 8), (-1, 1, 4, 3, 6), (-1, 1, 4, 4, 4), + (-1, 1, 4, 5, 1), (-1, -1, 0, 1, 4), (-1, -1, 1, 3, 2), (-1, -1, 1, 4, 4), (-1, -1, 2, 2, 3), + (-1, -1, 2, 3, 4), (-1, -1, 2, 4, 6), (-1, -1, 3, 0, 1), (-1, -1, 3, 2, 4), + (-1, -1, 3, 3, 7), (-1, -1, 3, 4, 8), (-1, -1, 4, 0, 4), (-1, -1, 4, 1, 5), + (-1, -1, 4, 2, 4), (-1, -1, 4, 3, 8), (-1, -1, 4, 4, 11), (1, 0, 1, 1, 11), (1, 0, 1, 2, 9), + (1, 0, 1, 3, 8), (1, 0, 1, 4, 8), (1, 0, 1, 5, 2), (1, 0, 2, 1, 7), (1, 0, 2, 2, 5), + (1, 0, 2, 3, 4), (1, 0, 2, 4, 4), (1, 0, 3, 1, 3), (1, 0, 3, 2, 1), (-1, 0, 0, 1, 4), + (-1, 0, 2, 2, 1), (-1, 0, 2, 3, 4), (-1, 0, 3, 2, 5), (-1, 0, 3, 3, 8), (-1, 0, 3, 4, 3), + (-1, 0, 4, 0, 4), (-1, 0, 4, 1, 4), (-1, 0, 4, 2, 9), (-1, 0, 4, 3, 12), (-1, 0, 4, 4, 7), + (-1, 0, 4, 5, 1), (0, 1, 0, 1, 4), (0, 1, 1, 1, 5), (0, 1, 1, 2, 1), (0, 1, 2, 1, 8), + (0, 1, 2, 2, 4), (0, 1, 3, 1, 9), (0, 1, 3, 2, 5), (0, 1, 3, 3, 1), (0, 1, 4, 1, 11), + (0, 1, 4, 2, 7), (0, 1, 4, 3, 3), (0, -1, 0, 4, 1), (0, -1, 1, 3, 3), (0, -1, 1, 4, 7), + (0, -1, 2, 2, 3), (0, -1, 2, 3, 7), (0, -1, 2, 4, 11), (0, -1, 3, 2, 2), (0, -1, 3, 3, 6), + (0, -1, 3, 4, 10), (0, -1, 4, 0, 4), (0, -1, 4, 3, 2), (0, -1, 4, 4, 6)] + +/-- Upper bound for queens on the 6 × 6 board (branch and bound with flow certificates). -/ +private theorem queen6_le {S : Finset (ℕ × ℕ)} (hS : S ⊆ board 6) : + totalMoves queenDirs 6 S ≤ 129 := by + by_cases h0 : ((0, 1) : ℕ × ℕ) ∈ S + · by_cases h1 : ((1, 5) : ℕ × ℕ) ∈ S + · exact leaf hS 8 (by norm_num) queenDirs (tab queen6_t0) [(0, 1), (1, 5)] [] 129 + (by decide +kernel) (by decide +kernel) (by simp [h0, h1]) (by simp) + · exact leaf hS 4 (by norm_num) queenDirs (tab queen6_t1) [(0, 1)] [(1, 5)] 129 + (by decide +kernel) (by decide +kernel) (by simp [h0]) (by simp [h1]) + · by_cases h1 : ((4, 0) : ℕ × ℕ) ∈ S + · exact leaf hS 4 (by norm_num) queenDirs (tab queen6_t2) [(4, 0)] [(0, 1)] 129 + (by decide +kernel) (by decide +kernel) (by simp [h1]) (by simp [h0]) + · exact leaf hS 4 (by norm_num) queenDirs (tab queen6_t3) [] [(0, 1), (4, 0)] 129 + (by decide +kernel) (by decide +kernel) (by simp) (by simp [h0, h1]) + + +/-! ### Conclusion -/ + +/-- Upper bounds for `a`. -/ +private lemma a_le {n X : ℕ} (h : ∀ S ⊆ board n, totalMoves bishopDirs n S ≤ X) : a n ≤ X := + Finset.sup_le fun S hS => h S (Finset.mem_powerset.mp hS) + +/-- Upper bounds for `queenMax`. -/ +private lemma q_le {n X : ℕ} (h : ∀ S ⊆ board n, totalMoves queenDirs n S ≤ X) : + queenMax n ≤ X := + Finset.sup_le fun S hS => h S (Finset.mem_powerset.mp hS) + +/-- Lower bound for `a` from the border placement. -/ +private lemma a_border {n : ℕ} (hn : 2 ≤ n) : 4 * (n - 2) ^ 2 ≤ a n := by + have h := Finset.le_sup (f := totalMoves bishopDirs n) (Finset.mem_powerset.mpr (border_sub n)) + rw [total_border hn bishopDirs (by simp [bishopDirs, unitDir])] at h + exact h + +/-- Lower bound for `queenMax` from the border placement. -/ +private lemma q_border {n : ℕ} (hn : 2 ≤ n) : 8 * (n - 2) ^ 2 ≤ queenMax n := by + have h := Finset.le_sup (f := totalMoves queenDirs n) (Finset.mem_powerset.mpr (border_sub n)) + rw [total_border hn queenDirs (by simp [queenDirs, unitDir])] at h + exact h + +/-- Kagey's conjecture holds: `a(n) = ⌊A275815(n) / 2⌋` for all `n ≥ 1`. -/ +theorem result : statement := by + intro n hn + have hA : [a 1, a 2, a 3] = [0, 2, 8] := a_data + have hQ : [queenMax 1, queenMax 2, queenMax 3] = [0, 4, 17] := queenMax_data + simp only [List.cons.injEq, and_true] at hA hQ + obtain rfl | rfl | rfl | rfl | rfl | rfl | rfl | h8 : + n = 1 ∨ n = 2 ∨ n = 3 ∨ n = 4 ∨ n = 5 ∨ n = 6 ∨ n = 7 ∨ 8 ≤ n := by omega + · rw [hA.1, hQ.1] + · rw [hA.2.1, hQ.2.1] + · rw [hA.2.2, hQ.2.2] + · have h1 := a_le fun S hS => bishop4_le hS + have h2 : 20 ≤ a 4 := by simpa using a_ge_data 0 (by norm_num) + have h3 := q_le fun S hS => queen4_le hS + have h4 : 40 ≤ queenMax 4 := by simpa using queenMax_ge_data 0 (by norm_num) + omega + · have h1 := a_le fun S hS => bishop5_le hS + have h2 : 38 ≤ a 5 := by simpa using a_ge_data 1 (by norm_num) + have h3 := q_le fun S hS => queen5_le hS + have h4 : 76 ≤ queenMax 5 := by simpa using queenMax_ge_data 1 (by norm_num) + omega + · have h1 := a_le fun S hS => bishop6 hS + have h2 := a_border (n := 6) (by norm_num) + have h3 := q_le fun S hS => queen6_le hS + have h4 := q_border (n := 6) (by norm_num) + norm_num at h2 h4 + omega + · have h1 := a_le fun S hS => bishop7 hS + have h2 := a_border (n := 7) (by norm_num) + have h3 := q_le fun S hS => queen7 hS + have h4 := q_border (n := 7) (by norm_num) + norm_num at h2 h4 + omega + · have h1 := a_le fun S hS => bishop_ge8 h8 hS + have h2 := a_border (n := n) (by omega) + have h3 := q_le fun S hS => queen_ge8 h8 hS + have h4 := q_border (n := n) (by omega) + generalize (n - 2) ^ 2 = x at h1 h2 h3 h4 + omega + +end Math0.Frontier.A278212 + +#math0_settles Math0.Frontier.A278212.result Math0.Statements.A278212.statement diff --git a/lean/Math0/Frontier/OEIS/A281000.lean b/lean/Math0/Frontier/OEIS/A281000.lean new file mode 100644 index 0000000..7e29eee --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A281000.lean @@ -0,0 +1,370 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A281000 +import Math0.Audit + +/-! +# Schulte's conjectures on A281000, `T(n,k) = C(2n+1,2k+1)·Cat(n-k)` + +We prove all three conjectures of Werner Schulte (Jan 12 2017) as encoded in the statement file: +(1) the antidiagonal sums are the little Schröder numbers A001003(n+1); (2) (corrected reading) +`Σ_k T(n,k)(2k+1)Cat(k)·A103365(k+1) = 0^n`; (3) the inverse of `T` is +`T(n,k)·A103365(n+1-k)`. + +**Inverse (3), (2).** In factorial form `T(k+p,k) = (2(k+p)+1)!/((2k+1)!·p!·(p+1)!)` and +`N(i+j+1,j+1) = (i+j+1)!(i+j)!/((j+1)!·j!·i!·(i+1)!)` (Narayana). Hence for `j ≤ p` +`T(k+p,k+j)·T(k+j,k) = F(k,p)·N(p+1,j+1)` with `F` independent of `j`, so the `(k+p,k)` entry +of `T·U` is `F(k,p)·Σ_j N(p+1,j+1)·A103365(j+1) = F(k,p)·[p = 0] = [p = 0]`, the middle sum being +the defining property of A103365 (first column of the inverse Narayana matrix, obtained from the +forward-substitution recursion). Thus `T·U = I` on every leading block, and `T⁻¹ = U`. +Conjecture (2) is the column `k = 0`, since `T(k,0) = (2k+1)·Cat(k)`. + +**Antidiagonals (1).** Using `N(M+1,i+1)(i+1) = C(M,i)C(M+1,i)`, +`C(M,i)C(i,2k) = C(M,2k)C(M-2k,i-2k)` and Vandermonde one gets, for `M = 2k+p`, +`Σ_i N(M+1,i+1)·C(i+1,2k+1) = C(2k+p,2k)·C(2k+2p+1,p+1)/(2k+1) = T(k+p,k)`. +Summing over `k ≤ n/2` (with `M = n`) and exchanging sums gives +`Σ_i N(n+1,i+1)·Σ_k C(i+1,2k+1) = Σ_i N(n+1,i+1)·2^i = A001003(n+1)`. +-/ + +namespace Math0.Frontier.A281000 +open Math0.Statements.A281000 +open Finset +open scoped Nat + +/-- `T` vanishes above the diagonal: `C(2n+1, 2k+1) = 0` for `k > n`. -/ +private theorem T_eq_zero {n k : ℕ} (h : n < k) : T n k = 0 := by + unfold T + rw [Nat.choose_eq_zero_of_lt (by omega)] + simp + +/-- On and below the diagonal the division in `T` is exact: +`T(k+p, k) = C(2(k+p)+1, 2k+1)·Cat(p)`. -/ +private theorem T_add (k p : ℕ) : + T (k + p) k = (2 * (k + p) + 1).choose (2 * k + 1) * catalan p := by + unfold T + have h1 : 2 * (k + p) - 2 * k = 2 * p := by omega + have h2 : k + p - k = p := by omega + have h3 : k + p + 1 - k = p + 1 := by omega + rw [h1, h2, h3, ← Nat.centralBinom_eq_two_mul_choose, ← succ_mul_catalan_eq_centralBinom, + Nat.mul_left_comm, Nat.mul_div_cancel_left _ (Nat.succ_pos p)] + +/-- `Cat(p)·p!·(p+1)! = (2p)!`. -/ +private theorem catalan_mul_fact (p : ℕ) : catalan p * p ! * (p + 1)! = (2 * p)! := by + have h := Nat.add_choose_mul_factorial_mul_factorial p p + rw [← two_mul, ← Nat.centralBinom_eq_two_mul_choose, ← succ_mul_catalan_eq_centralBinom] + at h + rw [← h, Nat.factorial_succ] + ring + +/-- Factorial form of `T`: `T(k+p, k)·(2k+1)!·p!·(p+1)! = (2(k+p)+1)!`. -/ +private theorem T_mul_fact (k p : ℕ) : + T (k + p) k * ((2 * k + 1)! * p ! * (p + 1)!) = (2 * (k + p) + 1)! := by + rw [T_add] + have h := Nat.add_choose_mul_factorial_mul_factorial (2 * p) (2 * k + 1) + have e : 2 * p + (2 * k + 1) = 2 * (k + p) + 1 := by ring + rw [e] at h + rw [← h, ← catalan_mul_fact] + ring + +/-- Rational closed form `T(k+p, k) = (2(k+p)+1)! / ((2k+1)!·p!·(p+1)!)`. -/ +private theorem T_q (k p : ℕ) : + (T (k + p) k : ℚ) = (2 * (k + p) + 1)! / ((2 * k + 1)! * p ! * (p + 1)!) := by + rw [eq_div_iff (by positivity)] + exact_mod_cast T_mul_fact k p + +/-- `(i+1) ∣ C(M,i)·C(M+1,i)`, so the Narayana division is exact. -/ +private theorem nar_dvd (M i : ℕ) : i + 1 ∣ M.choose i * (M + 1).choose i := by + have h1 : i + 1 ∣ (M + 1) * (M.choose i * (M + 1).choose i) := by + have := Nat.add_one_mul_choose_eq M i + exact ⟨(M + 1).choose (i + 1) * (M + 1).choose i, by rw [← Nat.mul_assoc, this]; ring⟩ + have h2 : i + 1 ∣ (M + 2) * (M.choose i * (M + 1).choose i) := by + have := Nat.add_one_mul_choose_eq (M + 1) i + exact ⟨(M + 2).choose (i + 1) * M.choose i, by + rw [show (M + 2) * (M.choose i * (M + 1).choose i) + = ((M + 1 + 1) * (M + 1).choose i) * M.choose i by ring, this]; ring⟩ + have h3 := Nat.dvd_sub h2 h1 + rwa [show (M + 2) * (M.choose i * (M + 1).choose i) = + (M + 1) * (M.choose i * (M + 1).choose i) + M.choose i * (M + 1).choose i by ring, + Nat.add_sub_cancel_left] at h3 + +/-- The Narayana division is exact: `N(M+1, i+1)·(i+1) = C(M,i)·C(M+1,i)`. -/ +private theorem nar_mul (M i : ℕ) : + narayana (M + 1) (i + 1) * (i + 1) = M.choose i * (M + 1).choose i := by + unfold narayana + simp only [Nat.add_sub_cancel] + exact Nat.div_mul_cancel (nar_dvd M i) + +/-- Factorial form of Narayana numbers: +`N(i+j+1, j+1)·(j+1)!·j!·i!·(i+1)! = (i+j+1)!·(i+j)!`. -/ +private theorem nar_mul_fact (j i : ℕ) : + narayana (i + j + 1) (j + 1) * ((j + 1)! * j ! * i ! * (i + 1)!) = (i + j + 1)! * (i + j)! := by + have h := nar_mul (i + j) j + have h1 := Nat.add_choose_mul_factorial_mul_factorial i j + have h2 := Nat.add_choose_mul_factorial_mul_factorial (i + 1) j + rw [show i + 1 + j = i + j + 1 by ring] at h2 + rw [← h1, ← h2, Nat.factorial_succ j] + calc narayana (i + j + 1) (j + 1) * ((j + 1) * j ! * j ! * i ! * (i + 1)!) + = (narayana (i + j + 1) (j + 1) * (j + 1)) * j ! * j ! * i ! * (i + 1)! := by ring + _ = _ := by rw [h]; ring + +/-- The list `invNarayanaCol m` has length `m`. -/ +private theorem invNarayanaCol_length (m : ℕ) : (invNarayanaCol m).length = m := by + induction m with + | zero => rfl + | succ m ih => simp [invNarayanaCol, ih] + +/-- Entry `j < m` of `invNarayanaCol m` is `A103365 (j+1)` (the lists are prefixes of each +other). -/ +private theorem invNarayanaCol_getD (m j : ℕ) (h : j < m) : + (invNarayanaCol m).getD j 0 = A103365 (j + 1) := by + induction m with + | zero => omega + | succ m ih => + rcases Nat.lt_succ_iff_lt_or_eq.1 h with h | h + · rw [invNarayanaCol, List.getD_append _ _ _ _ (by rw [invNarayanaCol_length]; exact h)] + exact ih h + · subst h; simp [A103365] + +/-- A `List.range` sum is a `Finset.range` sum. -/ +private theorem list_sum_range {M : Type*} [AddCommMonoid M] (f : ℕ → M) (m : ℕ) : + ((List.range m).map f).sum = ∑ j ∈ range m, f j := by + induction m with + | zero => simp + | succ m ih => rw [List.range_succ, List.map_append, List.sum_append, ih, sum_range_succ]; simp + +/-- The forward-substitution recursion +`A103365(m+1) = [m = 0] - Σ_{j ?_ + rw [invNarayanaCol_getD m j (mem_range.1 hj)] + +/-- `A103365` is the first column of the inverse Narayana matrix: +`Σ_{j≤m} N(m+1, j+1)·A103365(j+1) = [m = 0]`. -/ +private theorem nar_sum (m : ℕ) : + ∑ j ∈ range (m + 1), (narayana (m + 1) (j + 1) : ℤ) * A103365 (j + 1) = + if m = 0 then 1 else 0 := by + rw [sum_range_succ] + have h : narayana (m + 1) (m + 1) = 1 := by + have := nar_mul m m + simp only [Nat.choose_self, Nat.choose_succ_self_right, one_mul] at this + exact (Nat.mul_eq_right (Nat.succ_ne_zero m)).1 this + rw [h, A103365_succ m] + push_cast + ring + +/-- The key factorisation: for `j ≤ p`, +`T(k+p, k+j)·T(k+j, k) = F(k,p)·N(p+1, j+1)` with +`F(k,p) = (2(k+p)+1)! / ((2k+1)!·(p+1)!·p!)` independent of `j`. -/ +private theorem term_eq (k p j : ℕ) (hj : j ≤ p) : + (T (k + p) (k + j) : ℚ) * T (k + j) k = + (2 * (k + p) + 1)! / ((2 * k + 1)! * (p + 1)! * p !) * narayana (p + 1) (j + 1) := by + obtain ⟨i, rfl⟩ := Nat.exists_eq_add_of_le hj + have e1 : k + (j + i) = k + j + i := by ring + have e2 : j + i = i + j := by ring + rw [e1, T_q, T_q, e2] + have hN : (narayana (i + j + 1) (j + 1) : ℚ) = + (i + j + 1)! * (i + j)! / ((j + 1)! * j ! * i ! * (i + 1)!) := by + rw [eq_div_iff (by positivity)]; exact_mod_cast nar_mul_fact j i + rw [hN] + field_simp + +/-- The `(k+p, k)` entry of `T·U` is `[p = 0]`. -/ +private theorem main (k p : ℕ) : + ∑ l ∈ range (k + p + 1), (T (k + p) l : ℚ) * ((T l k : ℚ) * (A103365 (l + 1 - k) : ℚ)) = + if p = 0 then 1 else 0 := by + rw [show range (k + p + 1) = range (k + (p + 1)) from rfl, sum_range_add] + have h0 : ∑ l ∈ range k, (T (k + p) l : ℚ) * ((T l k : ℚ) * (A103365 (l + 1 - k) : ℚ)) = 0 := by + refine sum_eq_zero fun l hl => ?_ + rw [T_eq_zero (mem_range.1 hl)]; simp + rw [h0, zero_add] + have h1 : ∀ j ∈ range (p + 1), (T (k + p) (k + j) : ℚ) * + ((T (k + j) k : ℚ) * (A103365 (k + j + 1 - k) : ℚ)) = + (2 * (k + p) + 1)! / ((2 * k + 1)! * (p + 1)! * p !) * + (((narayana (p + 1) (j + 1) : ℤ) * A103365 (j + 1) : ℤ) : ℚ) := by + intro j hj + rw [show k + j + 1 - k = j + 1 by omega, ← mul_assoc, + term_eq k p j (Nat.lt_succ_iff.1 (mem_range.1 hj))] + push_cast; ring + rw [sum_congr rfl h1, ← mul_sum, ← Int.cast_sum, nar_sum] + split_ifs with hp + · subst hp; simp [Nat.factorial_ne_zero] + · simp + +/-- Row `n` of `T` against column `k` of `U = T(·,·)·A103365(·+1-·)`, summed over any range +longer than `n`, gives `[n = k]`. -/ +private theorem main' (n k N : ℕ) (hn : n < N) : + ∑ l ∈ range N, (T n l : ℚ) * ((T l k : ℚ) * (A103365 (l + 1 - k) : ℚ)) = + if n = k then 1 else 0 := by + rcases le_or_gt k n with h | h + · obtain ⟨p, rfl⟩ := Nat.exists_eq_add_of_le h + rw [← sum_subset (range_subset_range.2 (show k + p + 1 ≤ N by omega)), main] + · simp + · intro l hl hl' + rw [T_eq_zero (by simp at hl hl'; omega)]; simp + · rw [if_neg (by omega)] + refine sum_eq_zero fun l _ => ?_ + rcases le_or_gt l n with h' | h' + · rw [T_eq_zero (show l < k by omega)]; simp + · rw [T_eq_zero h']; simp + +/-- Conjecture (3). -/ +private theorem conj3_proof : conj3 := by + intro N + apply Matrix.inv_eq_right_inv + ext i j + rw [Matrix.mul_apply, Matrix.one_apply] + simp only [Matrix.of_apply] + rw [Fin.sum_univ_eq_sum_range + (fun l => (T i l : ℚ) * ((T l j : ℚ) * (A103365 (l + 1 - j) : ℚ))) N, main' _ _ _ i.isLt] + simp [Fin.ext_iff] + +/-- First column: `T(k, 0) = (2k+1)·Cat(k)`. -/ +private theorem T_zero (k : ℕ) : T k 0 = (2 * k + 1) * catalan k := by + have := T_add 0 k + simpa using this + +/-- Conjecture (2) (corrected reading): it is the `k = 0` column of `T·U = I`. -/ +private theorem conj2_proof : conj2 := by + intro n + have h := main' n 0 (n + 1) (Nat.lt_succ_self n) + have h' : ∑ k ∈ range (n + 1), + ((T n k : ℤ) * (2 * k + 1) * (catalan k : ℤ) * A103365 (k + 1) : ℤ) = + if n = 0 then 1 else 0 := by + have h'' : ((∑ k ∈ range (n + 1), + ((T n k : ℤ) * (2 * k + 1) * (catalan k : ℤ) * A103365 (k + 1) : ℤ) : ℤ) : ℚ) = + ((if n = 0 then 1 else 0 : ℤ) : ℚ) := by + have e : ((if n = 0 then 1 else 0 : ℤ) : ℚ) = if n = 0 then 1 else 0 := by + split_ifs <;> simp + rw [e, ← h] + push_cast + refine sum_congr rfl fun k _ => ?_ + rw [T_zero]; push_cast + ring + exact_mod_cast h'' + rw [h'] + rcases n with _ | n <;> simp + +/-! ### Conjecture (1) -/ + +/-- Grouping a sum over `range (2M)` into consecutive pairs. -/ +private theorem sum_pairs (f : ℕ → ℕ) (M : ℕ) : + ∑ k ∈ range M, (f (2 * k) + f (2 * k + 1)) = ∑ t ∈ range (2 * M), f t := by + induction M with + | zero => simp + | succ M ih => + rw [sum_range_succ, ih, show 2 * (M + 1) = 2 * M + 1 + 1 by ring, sum_range_succ, + sum_range_succ] + ring + +/-- `Σ_{k i.choose t) M + rw [this, ← Nat.sum_range_choose i] + symm + apply sum_subset (range_subset_range.2 (by omega)) + intro t ht ht' + exact Nat.choose_eq_zero_of_lt (by simp at ht ht'; omega) + +/-- By `C(M,i)·C(i,2k) = C(M,2k)·C(M-2k, i-2k)` and Vandermonde: +`Σ_i C(2k+p, i)·C(2k+p+1, i)·C(i, 2k) = C(2k+p, 2k)·C(2k+2p+1, p+1)`. -/ +private theorem vandermonde_step (k p : ℕ) : + ∑ i ∈ range (2 * k + p + 1), + (2 * k + p).choose i * (2 * k + p + 1).choose i * i.choose (2 * k) = + (2 * k + p).choose (2 * k) * (2 * k + 2 * p + 1).choose (p + 1) := by + rw [show range (2 * k + p + 1) = range (2 * k + (p + 1)) from rfl, sum_range_add] + have h0 : ∑ i ∈ range (2 * k), + (2 * k + p).choose i * (2 * k + p + 1).choose i * i.choose (2 * k) = 0 := by + refine sum_eq_zero fun i hi => ?_ + rw [Nat.choose_eq_zero_of_lt (mem_range.1 hi)]; simp + rw [h0, zero_add] + have h1 : ∀ t ∈ range (p + 1), + (2 * k + p).choose (2 * k + t) * (2 * k + p + 1).choose (2 * k + t) * + (2 * k + t).choose (2 * k) = + (2 * k + p).choose (2 * k) * (p.choose t * (2 * k + p + 1).choose (p + 1 - t)) := by + intro t ht + have ht' : t ≤ p := Nat.lt_succ_iff.1 (mem_range.1 ht) + have e1 := Nat.choose_mul (n := 2 * k + p) (k := 2 * k + t) (s := 2 * k) (by omega) + rw [show 2 * k + p - 2 * k = p by omega, show 2 * k + t - 2 * k = t by omega] at e1 + rw [Nat.choose_symm_of_eq_add (show 2 * k + p + 1 = (2 * k + t) + (p + 1 - t) by omega)] + calc (2 * k + p).choose (2 * k + t) * (2 * k + p + 1).choose (p + 1 - t) * + (2 * k + t).choose (2 * k) + = (2 * k + p).choose (2 * k + t) * (2 * k + t).choose (2 * k) * + (2 * k + p + 1).choose (p + 1 - t) := by ring + _ = _ := by rw [e1]; ring + rw [sum_congr rfl h1, ← mul_sum] + congr 1 + have hv := Nat.add_choose_eq p (2 * k + p + 1) (p + 1) + rw [Finset.Nat.sum_antidiagonal_eq_sum_range_succ_mk, sum_range_succ, + Nat.choose_eq_zero_of_lt (Nat.lt_succ_self p), zero_mul, add_zero, + show p + (2 * k + p + 1) = 2 * k + 2 * p + 1 by ring] at hv + exact hv.symm + +/-- `C(2k+p, 2k)·C(2k+2p+1, p+1) = (2k+1)·T(k+p, k)` (factorial identity). -/ +private theorem claimC (k p : ℕ) : + (2 * k + p).choose (2 * k) * (2 * k + 2 * p + 1).choose (p + 1) = + (2 * k + 1) * T (k + p) k := by + have hX : 0 < (2 * k)! * p ! * (p + 1)! := by positivity + apply Nat.eq_of_mul_eq_mul_right hX + have h1 := Nat.choose_mul_factorial_mul_factorial (show 2 * k ≤ 2 * k + p by omega) + have h2 := Nat.choose_mul_factorial_mul_factorial (show p + 1 ≤ 2 * k + 2 * p + 1 by omega) + rw [show 2 * k + p - 2 * k = p by omega] at h1 + rw [show 2 * k + 2 * p + 1 - (p + 1) = 2 * k + p by omega] at h2 + have h3 := T_mul_fact k p + rw [Nat.factorial_succ (2 * k), show 2 * (k + p) + 1 = 2 * k + 2 * p + 1 by ring] at h3 + calc (2 * k + p).choose (2 * k) * (2 * k + 2 * p + 1).choose (p + 1) * + ((2 * k)! * p ! * (p + 1)!) + = (2 * k + 2 * p + 1).choose (p + 1) * (p + 1)! * + ((2 * k + p).choose (2 * k) * (2 * k)! * p !) := by ring + _ = (2 * k + 2 * p + 1)! := by rw [h1, h2] + _ = _ := by rw [← h3]; ring + +/-- `T(k+p, k) = Σ_{i} N(2k+p+1, i+1)·C(i+1, 2k+1)`. -/ +private theorem claimA (k p : ℕ) : + T (k + p) k = ∑ i ∈ range (2 * k + p + 1), + narayana (2 * k + p + 1) (i + 1) * (i + 1).choose (2 * k + 1) := by + apply Nat.eq_of_mul_eq_mul_left (show 0 < 2 * k + 1 by omega) + rw [← claimC, mul_sum, ← vandermonde_step] + refine sum_congr rfl fun i _ => ?_ + symm + apply Nat.eq_of_mul_eq_mul_right (show 0 < i + 1 by omega) + have h1 := nar_mul (2 * k + p) i + have h2 := Nat.add_one_mul_choose_eq i (2 * k) + calc (2 * k + 1) * (narayana (2 * k + p + 1) (i + 1) * (i + 1).choose (2 * k + 1)) * (i + 1) + = (narayana (2 * k + p + 1) (i + 1) * (i + 1)) * + ((i + 1).choose (2 * k + 1) * (2 * k + 1)) := by ring + _ = _ := by rw [h1, ← h2]; ring + +/-- Conjecture (1). -/ +private theorem conj1_proof : conj1 := by + intro n + have hL : ∀ k ∈ range (n / 2 + 1), T (n - k) k = + ∑ i ∈ range (n + 1), narayana (n + 1) (i + 1) * (i + 1).choose (2 * k + 1) := by + intro k hk + have hk' : 2 * k ≤ n := by simp at hk; omega + have := claimA k (n - 2 * k) + rw [show k + (n - 2 * k) = n - k by omega, show 2 * k + (n - 2 * k) = n by omega] at this + exact this + rw [sum_congr rfl hL, sum_comm] + simp_rw [← mul_sum] + rw [A001003, if_neg (Nat.succ_ne_zero n), ← Finset.Ico_add_one_right_eq_Icc, + sum_Ico_eq_sum_range] + rw [show n + 1 + 1 - 1 = n + 1 by omega] + refine sum_congr rfl fun i hi => ?_ + rw [odd_sum i _ (by simp at hi; omega), add_comm 1 i, Nat.add_sub_cancel, mul_comm] + +/-- Werner Schulte's conjectures (1), (2) (corrected reading) and (3) on A281000 all hold. -/ +theorem result : statement := ⟨conj1_proof, conj2_proof, conj3_proof⟩ + +end Math0.Frontier.A281000 + +#math0_settles Math0.Frontier.A281000.result Math0.Statements.A281000.statement diff --git a/lean/Math0/Frontier/OEIS/A294512.lean b/lean/Math0/Frontier/OEIS/A294512.lean new file mode 100644 index 0000000..d9e348e --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A294512.lean @@ -0,0 +1,47 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A294512 +import Math0.Audit + +/-! +# Lang's conjecture for A294512 fails at n = 164 + +The OEIS entry A294512 (denominators of `V n = ∑_{k=0}^{n} 1/((k+1)(3k+1))`) carries the +conjecture `a(n) = A250400(n+1)/(n+1)`, where `A250400(m)` is the numerator of the harmonic mean +of the first `m` octagonal numbers. We refute it with the explicit counterexample `n = 164`. + +Since `∑_{j=1}^{n+1} 1/(j(3j-2)) = V n`, writing `V n = p/q` in lowest terms gives +`A250400(n+1) = (n+1) q / gcd(n+1, p)`, so the conjecture is equivalent to +`gcd(n+1, p) = 1`. At `n = 164` we have `11 ∣ 165` and `11 ∣ p`, and in fact +`A250400(165) * 11 = 165 * a(164)` exactly. This identity between two natural numbers of about +160 digits is checked by the kernel (`decide +kernel`). It shows `A250400(165)/165 = a(164)/11`, +which is not `a(164)` because `a(164)` is a positive denominator. +-/ + +namespace Math0.Frontier.A294512 +open Math0.Statements.A294512 + +set_option maxHeartbeats 4000000 in +/-- The kernel-checked key identity `A250400(165) * 11 = 165 * a(164)`: the harmonic-mean +numerator at `m = 165` is only `165/11 = 15` times the denominator of `V 164`. -/ +private theorem key : A250400 165 * 11 = 165 * a 164 := by + decide +kernel + +/-- Lang's conjecture `a(n) = A250400(n+1)/(n+1)` (A294512) is false: it fails at `n = 164`, +where `A250400(165)/165 = a(164)/11`. -/ +theorem result : ¬ statement := by + intro h + have h1 := h 164 + have hk := key + have hpos : 0 < a 164 := (V 164).den_pos + have h2 : (A250400 165 : ℚ) = 165 * (a 164 : ℚ) := by + rw [div_eq_iff (by norm_num)] at h1 + push_cast at h1 ⊢ + linarith + have h3 : A250400 165 = 165 * a 164 := by exact_mod_cast h2 + omega + +end Math0.Frontier.A294512 + +#math0_settles Math0.Frontier.A294512.result Math0.Statements.A294512.statement diff --git a/lean/Math0/Frontier/OEIS/A300789.lean b/lean/Math0/Frontier/OEIS/A300789.lean new file mode 100644 index 0000000..12a59a3 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A300789.lean @@ -0,0 +1,341 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A300789 +import Math0.Audit + +/-! +# Domino-tileable Young diagrams are exactly the colour-balanced ones (A300789) + +We prove Wiseman's conjecture from OEIS A300789: the Heinz numbers of partitions whose Young +diagram can be tiled by dominoes are exactly the Heinz numbers of partitions whose odd parts +occur as often in even as in odd positions. Hence `a n = b n` for all `n ≥ 1`. + +Colour the cell `(i, j)` with the weight `(-1)^(i+j)`. A row `i` of length `y_i` has total +weight `(-1)^i [y_i odd]`, so the parity condition says that the diagram has total weight zero +(the "imbalance" `∑ (-1)^i [y_i odd]` vanishes). + +* (tileable → balanced) Every domino covers two cells of opposite colour. We run this along the + verified search `tileL` of the statement file: each step removes a cell and a neighbour. +* (balanced → tileable) Strong induction on the number of cells, with the row lengths as an + antitone function `Y : ℕ → ℕ`. If some row has `Y i ≥ Y (i+1) + 2`, remove the horizontal + domino at its end. If `Y i = Y (i+1) > Y (i+2)`, remove the vertical domino at the ends of + rows `i, i+1`. Both moves keep the shape a partition and keep the imbalance. If neither move + applies, the shape is a staircase `Y r = k - r`. All its odd rows have the same sign + `(-1)^(k+1)`, so its imbalance is nonzero unless `k = 0`, the empty diagram. +-/ + +namespace Math0.Frontier.A300789 +open Math0.Statements.A300789 + +/-- The chessboard weight `(-1)^(i+j)` of a cell `(i, j)`. -/ +private def wt (c : ℕ × ℕ) : ℤ := (-1) ^ (c.1 + c.2) + +/-- A list of cells accepted by `tileL` has total chessboard weight zero: each domino covers one +cell of each colour. -/ +private theorem sum_wt_of_tileL : ∀ (fuel : ℕ) (l : List (ℕ × ℕ)), tileL fuel l = true → + (l.map wt).sum = 0 + | _, [], _ => by simp + | 0, _ :: _, h => by simp [tileL] at h + | fuel + 1, c :: rest, h => by + simp only [tileL, Bool.or_eq_true, Bool.and_eq_true, decide_eq_true_eq] at h + rcases h with ⟨hx, ht⟩ | ⟨hx, ht⟩ + · have ih := sum_wt_of_tileL fuel _ ht + have hp := ((List.perm_cons_erase hx).map wt).sum_eq + simp only [List.map_cons, List.sum_cons] at hp ⊢ + rw [hp, ih, wt, wt] + ring + · have ih := sum_wt_of_tileL fuel _ ht + have hp := ((List.perm_cons_erase hx).map wt).sum_eq + simp only [List.map_cons, List.sum_cons] at hp ⊢ + rw [hp, ih, wt, wt] + ring + +/-- The weight of a row of length `n` in row `i`. -/ +private theorem sum_row (i n : ℕ) : + (((List.range n).map fun j => (i, j)).map wt).sum = (-1) ^ i * ((n % 2 : ℕ) : ℤ) := by + induction n with + | zero => simp + | succ n ih => + rw [List.range_succ, List.map_append, List.map_append, List.sum_append, ih] + simp only [List.map_cons, List.map_nil, List.sum_cons, List.sum_nil, wt, add_zero, pow_add] + rcases Nat.even_or_odd n with hn | hn + · have h := Nat.even_iff.1 hn + rw [hn.neg_one_pow, h, show (n + 1) % 2 = 1 by omega] + push_cast; ring + · have h := Nat.odd_iff.1 hn + rw [hn.neg_one_pow, h, show (n + 1) % 2 = 0 by omega] + push_cast; ring + +/-- The imbalance `∑_{i < N} (-1)^i [Y i odd]` of the rows `Y 0, …, Y (N-1)`. -/ +private def imb (Y : ℕ → ℕ) (N : ℕ) : ℤ := ∑ i ∈ Finset.range N, (-1) ^ i * ((Y i % 2 : ℕ) : ℤ) + +/-- The total weight of the Young diagram of `y` is its imbalance. -/ +private theorem sum_cellsList (y : List ℕ) : + ((cellsList y).map wt).sum = imb (fun i => y.getD i 0) y.length := by + unfold cellsList imb + generalize y.length = m + induction m with + | zero => simp + | succ m ih => + rw [List.range_succ, List.flatMap_append, List.map_append, List.sum_append, ih, + Finset.sum_range_succ, List.flatMap_cons, List.flatMap_nil, List.append_nil, sum_row] + +/-- The sign of a row: `(-1)^i [v odd]` as a difference of two indicators. -/ +private theorem term_eq (i v : ℕ) : (-1 : ℤ) ^ i * ((v % 2 : ℕ) : ℤ) = + (if Odd (i + 1) ∧ Odd v then 1 else 0) - (if Even (i + 1) ∧ Odd v then 1 else 0) := by + rcases Nat.even_or_odd i with hi | hi <;> rcases Nat.even_or_odd v with hy | hy + · have h1 : ¬ Odd v := Nat.not_odd_iff_even.2 hy + rw [Nat.even_iff.1 hy]; simp [h1] + · have h1 : Odd (i + 1) := hi.add_one + have h2 : ¬ Even (i + 1) := Nat.not_even_iff_odd.2 h1 + rw [Nat.odd_iff.1 hy, hi.neg_one_pow]; simp [h1, h2, hy] + · have h1 : ¬ Odd v := Nat.not_odd_iff_even.2 hy + rw [Nat.even_iff.1 hy]; simp [h1] + · have h1 : Even (i + 1) := hi.add_one + have h2 : ¬ Odd (i + 1) := Nat.not_odd_iff_even.2 h1 + rw [Nat.odd_iff.1 hy, hi.neg_one_pow]; simp [h1, h2, hy] + +/-- The parity condition of the conjecture is the vanishing of the imbalance. -/ +private theorem balanced_iff (y : List ℕ) : + OddPartsBalanced y ↔ imb (fun i => y.getD i 0) y.length = 0 := by + unfold OddPartsBalanced imb + simp only [term_eq, Finset.sum_sub_distrib, Finset.sum_boole] + rw [sub_eq_zero, Nat.cast_inj, eq_comm] + +/-- The diagram `{(i, j) | j < Y i}` of a row-length function `Y`. -/ +private def shape (Y : ℕ → ℕ) : Set (ℕ × ℕ) := {c | c.2 < Y c.1} + +/-- A nonempty staircase `Y r = k - r` has nonzero imbalance: every odd row has the sign +`(-1)^(k+1)`. -/ +private theorem imb_staircase_ne (Y : ℕ → ℕ) (N : ℕ) (hN : ∀ i, N ≤ i → Y i = 0) + (hst : ∀ r, Y r = Y 0 - r) (h0 : 0 < Y 0) : imb Y N ≠ 0 := by + have hkN : Y 0 ≤ N := by have := hN N le_rfl; rw [hst N] at this; omega + have hterm : ∀ i ∈ Finset.range N, (-1 : ℤ) ^ i * ((Y i % 2 : ℕ) : ℤ) = + (-1) ^ (Y 0 + 1) * ((Y i % 2 : ℕ) : ℤ) := by + intro i _ + rcases Nat.mod_two_eq_zero_or_one (Y i) with h | h + · rw [h]; simp + · obtain ⟨m, hm⟩ : ∃ m, Y 0 + 1 = i + 2 * m := ⟨(Y 0 + 1 - i) / 2, by rw [hst i] at h; omega⟩ + rw [hm, pow_add, pow_mul]; simp + unfold imb + rw [Finset.sum_congr rfl hterm, ← Finset.mul_sum] + refine mul_ne_zero (pow_ne_zero _ (by norm_num)) ?_ + have h1 : Y (Y 0 - 1) % 2 = 1 := by rw [hst (Y 0 - 1)]; omega + apply ne_of_gt + calc (0 : ℤ) < 1 := one_pos + _ = ((Y (Y 0 - 1) % 2 : ℕ) : ℤ) := by rw [h1]; norm_num + _ ≤ _ := Finset.single_le_sum (f := fun i => ((Y i % 2 : ℕ) : ℤ)) + (fun i _ => by positivity) (Finset.mem_range.2 (by omega)) + +/-- The main lemma: an antitone row-length function with zero imbalance has a domino-tileable +diagram. By strong induction on the number of cells, removing a rim domino. -/ +private theorem tileable_shape (N : ℕ) : ∀ (s : ℕ) (Y : ℕ → ℕ), ∑ i ∈ Finset.range N, Y i = s → + Antitone Y → (∀ i, N ≤ i → Y i = 0) → imb Y N = 0 → DominoTileable (shape Y) := by + intro s + induction s using Nat.strong_induction_on with + | _ s ih => + intro Y hs hY hN himb + by_cases h0 : Y 0 = 0 + · have : shape Y = ∅ := by + ext ⟨r, c⟩ + simp only [shape, Set.mem_ofPred_eq, Set.mem_empty_iff_false, iff_false, not_lt] + have := hY (Nat.zero_le r); omega + rw [this]; exact tileable_empty + by_cases hh : ∃ i, Y (i + 1) + 2 ≤ Y i + · -- a horizontal rim domino at the end of row `i` + obtain ⟨i, hi⟩ := hh + have hiN : i < N := by + by_contra h + have := hN i (by omega); omega + have hdom : IsDomino {(i, Y i - 2), (i, Y i - 2 + 1)} := ⟨i, Y i - 2, Or.inr rfl⟩ + have hsub : ({(i, Y i - 2), (i, Y i - 2 + 1)} : Set (ℕ × ℕ)) ⊆ shape Y := by + intro c hc + simp only [Set.mem_insert_iff, Set.mem_singleton_iff] at hc + rcases hc with rfl | rfl <;> simp only [shape, Set.mem_ofPred_eq] <;> omega + have hdiff : shape Y \ {(i, Y i - 2), (i, Y i - 2 + 1)} = + shape (fun r => if r = i then Y r - 2 else Y r) := by + ext ⟨r, c⟩ + simp only [shape, Set.mem_sdiff, Set.mem_ofPred_eq, Set.mem_insert_iff, + Set.mem_singleton_iff, Prod.mk.injEq] + split_ifs with h + · subst h; omega + · omega + refine tileable_of_diff hdom hsub ?_ + rw [hdiff] + refine ih _ ?_ _ rfl ?_ ?_ ?_ + · rw [← hs] + apply Finset.sum_lt_sum + · intro r _; split_ifs <;> omega + · refine ⟨i, Finset.mem_range.2 hiN, ?_⟩ + show (if i = i then Y i - 2 else Y i) < Y i + rw [if_pos rfl]; omega + · intro a b hab + have h1 := hY hab + have h2 : Y b ≤ Y (i + 1) ∨ b ≤ i := by + rcases Nat.lt_or_ge i b with h | h + · exact Or.inl (hY h) + · exact Or.inr h + simp only + split_ifs with ha hb hb <;> subst_vars <;> omega + · intro r hr + have := hN r hr + split_ifs <;> omega + · rw [← himb]; unfold imb + apply Finset.sum_congr rfl + intro r _ + beta_reduce + split_ifs with h + · subst h + rw [show (Y r - 2) % 2 = Y r % 2 by omega] + · rfl + by_cases hv : ∃ i, Y (i + 1) = Y i ∧ Y (i + 2) < Y (i + 1) + · -- a vertical rim domino at the ends of rows `i` and `i + 1` + obtain ⟨i, heq, hlt⟩ := hv + have hiN : i + 1 < N := by + by_contra h + have := hN (i + 1) (by omega); omega + have hdom : IsDomino {(i, Y i - 1), (i + 1, Y i - 1)} := ⟨i, Y i - 1, Or.inl rfl⟩ + have hsub : ({(i, Y i - 1), (i + 1, Y i - 1)} : Set (ℕ × ℕ)) ⊆ shape Y := by + intro c hc + simp only [Set.mem_insert_iff, Set.mem_singleton_iff] at hc + rcases hc with rfl | rfl <;> simp only [shape, Set.mem_ofPred_eq] <;> omega + have hdiff : shape Y \ {(i, Y i - 1), (i + 1, Y i - 1)} = + shape (fun r => if r = i ∨ r = i + 1 then Y r - 1 else Y r) := by + ext ⟨r, c⟩ + simp only [shape, Set.mem_sdiff, Set.mem_ofPred_eq, Set.mem_insert_iff, + Set.mem_singleton_iff, Prod.mk.injEq] + split_ifs with h + · rcases h with rfl | rfl <;> omega + · omega + refine tileable_of_diff hdom hsub ?_ + rw [hdiff] + refine ih _ ?_ _ rfl ?_ ?_ ?_ + · rw [← hs] + apply Finset.sum_lt_sum + · intro r _; split_ifs <;> omega + · exact ⟨i, Finset.mem_range.2 (by omega), by simp only [true_or, if_true]; omega⟩ + · intro a b hab + have h1 := hY hab + have h2 : Y b ≤ Y (i + 2) ∨ b ≤ i + 1 := by + rcases Nat.lt_or_ge (i + 1) b with h | h + · exact Or.inl (hY h) + · exact Or.inr h + have h3 : Y (i + 1) ≤ Y a ∨ i + 1 < a := by + rcases Nat.lt_or_ge (i + 1) a with h | h + · exact Or.inr h + · exact Or.inl (hY h) + simp only + split_ifs with ha hb hb <;> omega + · intro r hr + have := hN r hr + split_ifs <;> omega + · rw [← himb]; unfold imb + obtain ⟨t, rfl⟩ : ∃ t, N = i + 1 + 1 + t := ⟨N - (i + 2), by omega⟩ + simp only + rw [Finset.sum_range_add _ (i + 1 + 1) t, Finset.sum_range_add _ (i + 1 + 1) t, + Finset.sum_range_succ _ (i + 1), Finset.sum_range_succ _ (i + 1), + Finset.sum_range_succ _ i, Finset.sum_range_succ _ i] + have hA : ∑ x ∈ Finset.range i, (-1 : ℤ) ^ x * + (((if x = i ∨ x = i + 1 then Y x - 1 else Y x) % 2 : ℕ) : ℤ) = + ∑ x ∈ Finset.range i, (-1 : ℤ) ^ x * ((Y x % 2 : ℕ) : ℤ) := by + apply Finset.sum_congr rfl + intro x hx + have := Finset.mem_range.1 hx + rw [if_neg (by omega)] + have hB : ∑ x ∈ Finset.range t, (-1 : ℤ) ^ (i + 1 + 1 + x) * + (((if i + 1 + 1 + x = i ∨ i + 1 + 1 + x = i + 1 then Y (i + 1 + 1 + x) - 1 + else Y (i + 1 + 1 + x)) % 2 : ℕ) : ℤ) = + ∑ x ∈ Finset.range t, (-1 : ℤ) ^ (i + 1 + 1 + x) * ((Y (i + 1 + 1 + x) % 2 : ℕ) : ℤ) := by + apply Finset.sum_congr rfl + intro x _ + rw [if_neg (by omega)] + rw [hA, hB, if_pos (Or.inl rfl), if_pos (Or.inr rfl), heq, pow_succ] + ring + · -- no rim domino: the diagram is a staircase, which has nonzero imbalance + push Not at hh hv + have hflat : ∀ r, Y (r + 1) = Y r → Y r = 0 := by + intro r hr + have hc1 : ∀ t, Y (r + t + 1) = Y (r + t) := by + intro t + induction t with + | zero => simpa using hr + | succ t iht => + have h1 := hv (r + t) iht + have h2 := hY (show r + t + 1 ≤ r + t + 2 by omega) + rw [show r + (t + 1) + 1 = r + t + 2 by omega, show r + (t + 1) = r + t + 1 by omega] + omega + have hc : ∀ t, Y (r + t) = Y r := by + intro t + induction t with + | zero => rfl + | succ t iht => rw [← add_assoc, hc1 t, iht] + rw [← hc N] + exact hN _ (by omega) + have hst : ∀ r, Y r = Y 0 - r := by + intro r + induction r with + | zero => simp + | succ r ihr => + have h1 := hY (show r ≤ r + 1 by omega) + have h2 := hh r + by_cases he : Y (r + 1) = Y r + · have := hflat r he; omega + · omega + exact absurd himb (imb_staircase_ne Y N hN hst (Nat.pos_of_ne_zero h0)) + +/-- `y.getD · 0` is antitone for a weakly decreasing list `y`. -/ +private theorem antitone_getD {l : List ℕ} (hl : l.Pairwise (· ≥ ·)) : + Antitone (fun i => l.getD i 0) := by + intro a b hab + simp only + by_cases hb : b < l.length + · rw [List.getD_eq_getElem _ _ hb, List.getD_eq_getElem _ _ (show a < l.length by omega)] + rcases Nat.lt_or_eq_of_le hab with h | rfl + · exact List.pairwise_iff_getElem.1 hl a b (by omega) hb h + · exact le_refl _ + · rw [List.getD_eq_default _ _ (show l.length ≤ b by omega)]; exact Nat.zero_le _ + +/-- The parts of `k` are weakly decreasing. -/ +private theorem parts_pairwise (k : ℕ) : (parts k).Pairwise (· ≥ ·) := by + unfold parts + rw [List.pairwise_reverse] + exact (Nat.primeFactorsList_sorted k).pairwise.map _ (fun a b h => Nat.monotone_primeCounting h) + +/-- The Young diagram of `y` is the diagram of its row-length function. -/ +private theorem youngDiagram_eq (y : List ℕ) : youngDiagram y = shape (fun i => y.getD i 0) := by + ext ⟨r, c⟩ + simp only [youngDiagram, shape, Set.mem_ofPred_eq] + constructor + · exact fun h => h.2 + · intro h + refine ⟨?_, h⟩ + by_contra hr + rw [List.getD_eq_default _ _ (show y.length ≤ r by omega)] at h + omega + +/-- Domino tileability is exactly the conjectured parity condition. -/ +private theorem isTerm_iff (k : ℕ) : IsTerm k ↔ IsConjTerm k := by + unfold IsTerm IsConjTerm + refine and_congr_right fun _ => ?_ + rw [balanced_iff] + constructor + · intro h + have ht := (tileL_iff _ _ (pairwise_cellsList (parts k)) le_rfl).2 + (by rw [setOf_mem_cellsList]; exact h) + have := sum_wt_of_tileL _ _ ht + rwa [sum_cellsList] at this + · intro h + rw [youngDiagram_eq] + exact tileable_shape _ _ _ rfl (antitone_getD (parts_pairwise k)) + (fun i hi => List.getD_eq_default _ _ hi) h + +/-- Wiseman's conjecture holds: `a n = b n` for all `n ≥ 1`. -/ +theorem result : statement := by + intro n _ + have h : IsTerm = IsConjTerm := funext fun k => propext (isTerm_iff k) + simp only [a, b, h] + +end Math0.Frontier.A300789 + +#math0_settles Math0.Frontier.A300789.result Math0.Statements.A300789.statement diff --git a/lean/Math0/Frontier/OEIS/A308107.lean b/lean/Math0/Frontier/OEIS/A308107.lean new file mode 100644 index 0000000..e7f8138 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A308107.lean @@ -0,0 +1,325 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A308107 +import Math0.Audit + +/-! +# A308107: Barker's generating function for smallest sides of scalene triangles + +We prove both of Barker's conjectures (the rational generating function and the order-15 +recurrence). + +*Idea.* A scalene triangle `k < i < j < k + i` with middle side `i ≥ k + 2` is obtained from the +triangle `(k, i - 1, j - 1)` of perimeter `n - 2` with the same smallest side; the ones with +`i = k + 1` are parametrized by `v = j - i ≥ 1`, `w = k - v ≥ 1`, i.e. `(k, i, j) = +(v + w, v + w + 1, 2v + w + 1)`, of perimeter `4v + 3w + 2` and weight `k = v + w`. Shifting +`v ↦ v + 1` and `w ↦ w + 1` in the set `U n` of such pairs gives the relations + +* `a(n+2) = a(n) + bv(n+2) + bw(n+2)` with `bv n = ∑_{U n} v`, `bw n = ∑_{U n} w`; +* `bv(n+4) = bv(n) + c(n+4)`, `bw(n+3) = bw(n) + c(n+3)` with `c n = #U n`; +* `c(n+4) = c(n) + e(n+4)` with `e n = #{(v, w) ∈ U n | v = 1}`, and + `e(n+3) = e(n) + [n + 3 = 9]`. + +As power series these say `(1 - X²) A = Bv + Bw`, `(1 - X⁴) Bv = C`, `(1 - X³) Bw = C`, +`(1 - X⁴) C = E`, `(1 - X³) E = X⁹`, so +`(1 - X²)(1 - X³)²(1 - X⁴)² A = X⁹ (2 - X³ - X⁴)`. Since +`(1 - X²)(1 - X³)²(1 - X⁴)² = (1 - X) · den` and `2 - X³ - X⁴ = (1 - X)(2 + 2X + 2X² + X³)`, +cancelling `1 - X` gives `A · den = X⁹ (2 + 2X + 2X² + X³)`, i.e. the generating function, and +comparing coefficients of index `n > 15` gives the recurrence. +-/ + +namespace Math0.Frontier.A308107 +open Math0.Statements.A308107 PowerSeries + +/-- The triples `(k, i, j)` with `k < i < j < k + i` and `k + i + j = n` summed in `a n`. -/ +private def T (n : ℕ) : Finset (ℕ × ℕ × ℕ) := + (Finset.range (n + 1) ×ˢ Finset.range (n + 1) ×ˢ Finset.range (n + 1)).filter + (fun t : ℕ × ℕ × ℕ => t.1 < t.2.1 ∧ t.2.1 < t.2.2 ∧ t.2.2 < t.1 + t.2.1 ∧ + t.1 + t.2.1 + t.2.2 = n) + +/-- The pairs `(v, w)` with `v, w ≥ 1` and `4v + 3w + 2 = n`: the scalene triangles +`(v + w, v + w + 1, 2v + w + 1)` of perimeter `n` whose middle side is one more than the +smallest. -/ +private def U (n : ℕ) : Finset (ℕ × ℕ) := + (Finset.range (n + 1) ×ˢ Finset.range (n + 1)).filter + (fun p : ℕ × ℕ => 1 ≤ p.1 ∧ 1 ≤ p.2 ∧ 4 * p.1 + 3 * p.2 + 2 = n) + +/-- `a n` as a sum over `T n`. -/ +private theorem a_eq_T (n : ℕ) : a n = ∑ t ∈ T n, t.1 := rfl + +/-- Triangles with middle side one more than the smallest side, reparametrized by `U`. -/ +private theorem sum_T_filter (n : ℕ) : + ∑ t ∈ (T n).filter (fun t => t.2.1 = t.1 + 1), t.1 = ∑ p ∈ U n, (p.1 + p.2) := by + symm + apply Finset.sum_nbij' (fun p => (p.1 + p.2, p.1 + p.2 + 1, 2 * p.1 + p.2 + 1)) + (fun t => (t.2.2 - t.1 - 1, 2 * t.1 + 1 - t.2.2)) + · rintro ⟨v, w⟩ h + simp only [U, T, Finset.mem_filter, Finset.mem_product, Finset.mem_range, and_true] at h ⊢ + omega + · rintro ⟨k, i, j⟩ h + simp only [U, T, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h ⊢ + omega + · rintro ⟨v, w⟩ h + simp only [U, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h + simp only [Prod.mk.injEq] + omega + · rintro ⟨k, i, j⟩ h + simp only [T, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h + simp only [Prod.mk.injEq] + omega + · rintro ⟨v, w⟩ _ + rfl + +/-- Triangles with middle side at least two more than the smallest side come from perimeter +`n` by adding `1` to the two larger sides. -/ +private theorem sum_T_filter_not (n : ℕ) : + ∑ t ∈ (T (n + 2)).filter (fun t => ¬ t.2.1 = t.1 + 1), t.1 = ∑ t ∈ T n, t.1 := by + symm + apply Finset.sum_nbij' (fun t => (t.1, t.2.1 + 1, t.2.2 + 1)) + (fun t => (t.1, t.2.1 - 1, t.2.2 - 1)) + · rintro ⟨k, i, j⟩ h + simp only [T, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h ⊢ + omega + · rintro ⟨k, i, j⟩ h + simp only [T, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h ⊢ + omega + · rintro ⟨k, i, j⟩ h + simp only [T, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h + simp only [Prod.mk.injEq, true_and] + omega + · rintro ⟨k, i, j⟩ h + simp only [T, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h + simp only [Prod.mk.injEq, true_and] + omega + · rintro ⟨k, i, j⟩ _ + rfl + +/-- `a(n+2) = a(n) + ∑_{U(n+2)} (v + w)`. -/ +private theorem a_shift (n : ℕ) : + a (n + 2) = a n + (∑ p ∈ U (n + 2), p.1 + ∑ p ∈ U (n + 2), p.2) := by + rw [a_eq_T, a_eq_T, ← Finset.sum_filter_add_sum_filter_not (T (n + 2)) + (fun t => t.2.1 = t.1 + 1), sum_T_filter, sum_T_filter_not, Finset.sum_add_distrib, add_comm] + +/-- Shifting `v ↦ v + 1` in `U`. -/ +private theorem U_shift_v (n : ℕ) (g : ℕ × ℕ → ℕ) : + ∑ p ∈ U (n + 4), g p = + ∑ p ∈ U n, g (p.1 + 1, p.2) + ∑ p ∈ U (n + 4), if p.1 = 1 then g p else 0 := by + have h1 : + ∑ p ∈ (U (n + 4)).filter (fun p => ¬ p.1 = 1), g p = ∑ p ∈ U n, g (p.1 + 1, p.2) := by + symm + apply Finset.sum_nbij' (fun p => (p.1 + 1, p.2)) (fun p => (p.1 - 1, p.2)) + · rintro ⟨v, w⟩ h + simp only [U, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h ⊢ + omega + · rintro ⟨v, w⟩ h + simp only [U, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h ⊢ + omega + · rintro ⟨v, w⟩ _ + simp + · rintro ⟨v, w⟩ h + simp only [U, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h + simp only [Prod.mk.injEq, and_true] + omega + · rintro ⟨v, w⟩ _ + rfl + rw [← Finset.sum_filter_add_sum_filter_not (U (n + 4)) (fun p => p.1 = 1), h1, + Finset.sum_filter, add_comm] + +/-- Shifting `w ↦ w + 1` in `U`. -/ +private theorem U_shift_w (n : ℕ) (g : ℕ × ℕ → ℕ) : + ∑ p ∈ U (n + 3), g p = + ∑ p ∈ U n, g (p.1, p.2 + 1) + ∑ p ∈ U (n + 3), if p.2 = 1 then g p else 0 := by + have h1 : + ∑ p ∈ (U (n + 3)).filter (fun p => ¬ p.2 = 1), g p = ∑ p ∈ U n, g (p.1, p.2 + 1) := by + symm + apply Finset.sum_nbij' (fun p => (p.1, p.2 + 1)) (fun p => (p.1, p.2 - 1)) + · rintro ⟨v, w⟩ h + simp only [U, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h ⊢ + omega + · rintro ⟨v, w⟩ h + simp only [U, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h ⊢ + omega + · rintro ⟨v, w⟩ _ + simp + · rintro ⟨v, w⟩ h + simp only [U, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h + simp only [Prod.mk.injEq, true_and] + omega + · rintro ⟨v, w⟩ _ + rfl + rw [← Finset.sum_filter_add_sum_filter_not (U (n + 3)) (fun p => p.2 = 1), h1, + Finset.sum_filter, add_comm] + +/-- `U n` is empty for `n < 9`, so every sum over it vanishes. -/ +private theorem sum_U_small (n : ℕ) (hn : n < 9) (g : ℕ × ℕ → ℕ) : + ∑ p ∈ U n, g p = 0 := by + apply Finset.sum_eq_zero + rintro ⟨v, w⟩ h + simp only [U, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at h + omega + +/-- `∑_{U n} v`. -/ +private def bv (n : ℕ) : ℕ := ∑ p ∈ U n, p.1 +/-- `∑_{U n} w`. -/ +private def bw (n : ℕ) : ℕ := ∑ p ∈ U n, p.2 +/-- `#U n`. -/ +private def c (n : ℕ) : ℕ := ∑ _p ∈ U n, 1 +/-- `#{(v, w) ∈ U n | v = 1}`. -/ +private def e (n : ℕ) : ℕ := ∑ p ∈ U n, if p.1 = 1 then 1 else 0 + +/-- `bv(n+4) = bv(n) + c(n+4)`. -/ +private theorem bv_shift (n : ℕ) : bv (n + 4) = bv n + c (n + 4) := by + unfold bv c + rw [U_shift_v n Prod.fst, U_shift_v n (fun _ => 1), Finset.sum_add_distrib] + have : ∀ p : ℕ × ℕ, (if p.1 = 1 then p.1 else 0) = if p.1 = 1 then 1 else 0 := by + rintro ⟨v, w⟩; dsimp only; split_ifs with h <;> simp [h] + simp only [this] + ring + +/-- `bw(n+3) = bw(n) + c(n+3)`. -/ +private theorem bw_shift (n : ℕ) : bw (n + 3) = bw n + c (n + 3) := by + unfold bw c + rw [U_shift_w n Prod.snd, U_shift_w n (fun _ => 1), Finset.sum_add_distrib] + have : ∀ p : ℕ × ℕ, (if p.2 = 1 then p.2 else 0) = if p.2 = 1 then 1 else 0 := by + rintro ⟨v, w⟩; dsimp only; split_ifs with h <;> simp [h] + simp only [this] + ring + +/-- `c(n+4) = c(n) + e(n+4)`. -/ +private theorem c_shift (n : ℕ) : c (n + 4) = c n + e (n + 4) := by + unfold c e + rw [U_shift_v n (fun _ => 1)] + +/-- `e(n+3) = e(n) + [n + 3 = 9]`: the only pair with `v = w = 1` is at perimeter `9`. -/ +private theorem e_shift (n : ℕ) : e (n + 3) = e n + if n + 3 = 9 then 1 else 0 := by + unfold e + rw [U_shift_w n (fun p => if p.1 = 1 then 1 else 0)] + congr 1 + have : ∀ p : ℕ × ℕ, (if p.2 = 1 then (if p.1 = 1 then 1 else 0) else 0) = + if ((1, 1) : ℕ × ℕ) = p then 1 else 0 := by + rintro ⟨v, w⟩ + simp only [Prod.mk.injEq] + split_ifs <;> omega + simp only [this] + rw [Finset.sum_ite_eq] + congr 1 + simp only [U, Finset.mem_filter, Finset.mem_product, Finset.mem_range, eq_iff_iff] + omega + +/-- A one-step shift relation is a power series identity. -/ +private theorem ps_shift (d : ℕ) (f g : ℕ → ℚ) (h : ∀ n, f (n + d) = f n + g (n + d)) + (h0 : ∀ n < d, f n = g n) : (1 - X ^ d) * mk f = mk g := by + ext n + rw [sub_mul, one_mul, map_sub, coeff_X_pow_mul'] + simp only [coeff_mk] + split_ifs with hd + · obtain ⟨m, rfl⟩ : ∃ m, n = m + d := ⟨n - d, by omega⟩ + rw [Nat.add_sub_cancel, h m] + ring + · rw [h0 n (by omega)] + ring + +/-- The first two terms vanish. -/ +private theorem a_zero_one : a 0 = 0 ∧ a 1 = 0 := by decide + +/-- The shift relations as power series identities, combined: +`A · den = X⁹ (2 + 2X + 2X² + X³)`. -/ +private theorem gf_mul : + mk (fun n => (a n : ℚ)) * den = X ^ 9 * (2 + 2 * X + 2 * X ^ 2 + X ^ 3) := by + have h1 : + (1 - X ^ 2) * mk (fun n => (a n : ℚ)) = mk (fun n => ((bv n + bw n : ℕ) : ℚ)) := by + apply ps_shift + · intro n + exact_mod_cast a_shift n + · intro n hn + have ha : a n = 0 := by + interval_cases n + · exact a_zero_one.1 + · exact a_zero_one.2 + simp only [ha, bv, bw, sum_U_small n (by omega), Nat.cast_zero, add_zero] + have h2 : mk (fun n => ((bv n + bw n : ℕ) : ℚ)) = + mk (fun n => (bv n : ℚ)) + mk (fun n => (bw n : ℚ)) := by + ext n + simp + have h3 : (1 - X ^ 4) * mk (fun n => (bv n : ℚ)) = mk (fun n => (c n : ℚ)) := by + apply ps_shift + · intro n + exact_mod_cast bv_shift n + · intro n hn + simp only [bv, c, sum_U_small n (by omega)] + have h4 : (1 - X ^ 3) * mk (fun n => (bw n : ℚ)) = mk (fun n => (c n : ℚ)) := by + apply ps_shift + · intro n + exact_mod_cast bw_shift n + · intro n hn + simp only [bw, c, sum_U_small n (by omega)] + have h5 : (1 - X ^ 4) * mk (fun n => (c n : ℚ)) = mk (fun n => (e n : ℚ)) := by + apply ps_shift + · intro n + exact_mod_cast c_shift n + · intro n hn + simp only [c, e, sum_U_small n (by omega)] + have h6 : (1 - X ^ 3) * mk (fun n => (e n : ℚ)) = X ^ 9 := by + have : (X ^ 9 : ℚ⟦X⟧) = mk (fun n => ((if n = 9 then 1 else 0 : ℕ) : ℚ)) := by + ext n + simp only [coeff_X_pow, coeff_mk] + split_ifs <;> simp + rw [this] + apply ps_shift + · intro n + exact_mod_cast e_shift n + · intro n hn + simp only [e, sum_U_small n (by omega)] + rw [if_neg (by omega)] + have hX : (1 - X : ℚ⟦X⟧) ≠ 0 := by + intro h + have := congrArg (coeff 0) h + simp at this + apply mul_left_cancel₀ hX + unfold den + linear_combination (1 - X ^ 3) ^ 2 * (1 - X ^ 4) ^ 2 * h1 + (1 - X ^ 3) ^ 2 * (1 - X ^ 4) ^ 2 * h2 + + (1 - X ^ 3) ^ 2 * (1 - X ^ 4) * h3 + (1 - X ^ 3) * (1 - X ^ 4) ^ 2 * h4 + + (1 - X ^ 3) * (2 - X ^ 3 - X ^ 4) * h5 + (2 - X ^ 3 - X ^ 4) * h6 + +/-- The `n`-th coefficient of `X^k · mk f` for `k ≤ n`. -/ +private theorem coeff_shift (f : ℕ → ℚ) {n k : ℕ} (hk : k ≤ n) : + coeff n (X ^ k * mk f) = f (n - k) := by + rw [coeff_X_pow_mul', if_pos hk, coeff_mk] + +/-- Barker's generating function and recurrence. -/ +theorem result : statement := by + refine ⟨genFun_iff.2 gf_mul, ?_⟩ + intro n hn + set f : ℕ → ℚ := fun n => (a n : ℚ) with hf + have hden : mk f * den = X ^ 0 * mk f + X ^ 1 * mk f - C 2 * (X ^ 3 * mk f) - + C 4 * (X ^ 4 * mk f) - C 2 * (X ^ 5 * mk f) + X ^ 6 * mk f + C 5 * (X ^ 7 * mk f) + + C 5 * (X ^ 8 * mk f) + X ^ 9 * mk f - C 2 * (X ^ 10 * mk f) - C 4 * (X ^ 11 * mk f) - + C 2 * (X ^ 12 * mk f) + X ^ 14 * mk f + X ^ 15 * mk f := by + rw [den_eq] + simp only [map_ofNat] + ring + have hrhs : (X ^ 9 * (2 + 2 * X + 2 * X ^ 2 + X ^ 3) : ℚ⟦X⟧) = + C 2 * X ^ 9 + C 2 * X ^ 10 + C 2 * X ^ 11 + X ^ 12 := by + simp only [map_ofNat] + ring + have h := congrArg (coeff n) gf_mul + rw [hden, hrhs] at h + simp only [map_add, map_sub, coeff_C_mul, coeff_X_pow] at h + rw [coeff_shift f (by omega : 0 ≤ n), coeff_shift f (by omega : 1 ≤ n), + coeff_shift f (by omega : 3 ≤ n), coeff_shift f (by omega : 4 ≤ n), + coeff_shift f (by omega : 5 ≤ n), coeff_shift f (by omega : 6 ≤ n), + coeff_shift f (by omega : 7 ≤ n), coeff_shift f (by omega : 8 ≤ n), + coeff_shift f (by omega : 9 ≤ n), coeff_shift f (by omega : 10 ≤ n), + coeff_shift f (by omega : 11 ≤ n), coeff_shift f (by omega : 12 ≤ n), + coeff_shift f (by omega : 14 ≤ n), coeff_shift f (by omega : 15 ≤ n), + if_neg (by omega : n ≠ 9), if_neg (by omega : n ≠ 10), if_neg (by omega : n ≠ 11), + if_neg (by omega : n ≠ 12)] at h + simp only [hf, Nat.sub_zero] at h + apply Int.cast_injective (α := ℚ) + push_cast + linarith + +end Math0.Frontier.A308107 + +#math0_settles Math0.Frontier.A308107.result Math0.Statements.A308107.statement diff --git a/lean/Math0/Frontier/OEIS/A308121.lean b/lean/Math0/Frontier/OEIS/A308121.lean new file mode 100644 index 0000000..51df9ba --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A308121.lean @@ -0,0 +1,283 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A308121 +import Math0.Audit + +/-! +# A308121: for odd `n`, row `2n` is row `n` with its halves swapped + +We prove Charlie Neder's conjecture (2019) on the irregular triangle +`T(n,k) = A109395(n)·k - A076512(n)·r_k`, where `r_1 < ⋯ < r_φ(n)` are the totatives of `n` +and `A076512(n)/A109395(n)` is `φ(n)/n` in lowest terms. + +Let `n = 2t+1 ≥ 3`, `m = φ(n) = 2h`, and `φ(n)/n = a/b` in lowest terms. + +* **Totatives.** By the reflection `r ↦ n - r`, exactly `h` totatives of `n` lie in `[1, t]` + (list `L`) and `h` in `[t+1, 2t]` (list `H`); `totatives n = L ++ H`. The totatives of `2n` + are the odd numbers coprime to `n`: those below `n` are `2r - n` for `r ∈ H`, those above `n` + are `n + 2r` for `r ∈ L`, so `totatives (2n) = H.map (2·-n) ++ L.map (n+2·)`. +* **Fractions.** `φ(2n) = φ(n)`, so `φ(2n)/(2n) = (a/b)/2`. From `a n = b m` with `m` even + and `n` odd, `a` is even, so `(a/2)/b` is already in lowest terms: `A109395(2n) = b`, + `A076512(2n) = a/2`. +* **Algebra.** For `k ≤ h`: `T(2n,k) = b k - (a/2)(2 H_k - n) = b(k+h) - a H_k = T(n, k+h)`, using + `(a/2) n = b h`. For `k > h`: `T(2n,k) = b k - (a/2)(n + 2 L_{k-h}) = T(n, k-h)`. +-/ + +namespace Math0.Frontier.A308121 +open Math0.Statements.A308121 + +/-- Among `a, a+1, …, a+2k-1` with `a` odd, the numbers coprime to `2n` are exactly the odd +ones `a, a+2, …, a+2k-2` that are coprime to `n`. -/ +private lemma filter_pair (n : ℕ) : ∀ (k a : ℕ), Odd a → + (List.range' a (2 * k)).filter (fun s => Nat.Coprime s (2 * n)) = + (List.range' a k 2).filter (fun s => Nat.Coprime s n) := by + intro k + induction k with + | zero => intro a _; simp + | succ k ih => + intro a ha + have h2 : 2 * (k + 1) = (2 * k) + 1 + 1 := by ring + have c1 : Nat.Coprime a (2 * n) ↔ Nat.Coprime a n := by + rw [Nat.coprime_mul_iff_right]; simp [ha] + have c2 : ¬ Nat.Coprime (a + 1) (2 * n) := by + intro h + have := Nat.coprime_two_right.mp (Nat.Coprime.coprime_dvd_right (dvd_mul_right 2 n) h) + rw [Nat.odd_add_one] at this + exact this ha + have ha2 : Odd (a + 1 + 1) := by rw [Nat.odd_add_one, Nat.odd_add_one, not_not]; exact ha + rw [h2, List.range'_succ, List.range'_succ, List.range'_succ, List.filter_cons, + List.filter_cons, List.filter_cons, ih _ ha2] + simp [c1, c2] + +/-- An arithmetic progression of step `2` is the image of a step-`1` range under any `f` that +increases by `2` at each step. -/ +private lemma range'_two_eq_map (f : ℕ → ℕ) : ∀ (k r0 : ℕ), + (∀ r, r0 ≤ r → f (r + 1) = f r + 2) → + List.range' (f r0) k 2 = (List.range' r0 k).map f := by + intro k + induction k with + | zero => intro r0 _; simp + | succ k ih => + intro r0 hf + rw [List.range'_succ, List.range'_succ, List.map_cons, ← hf r0 le_rfl, + ih (r0 + 1) (fun r hr => hf r (by omega))] + +/-- Reflection `r ↦ N - r` sends `[1, t]` onto `[N - t, N - 1]`, reversed. -/ +private lemma map_sub_range' (N : ℕ) : ∀ t, t < N → + (List.range' 1 t).map (fun r => N - r) = (List.range' (N - t) t).reverse := by + intro t + induction t with + | zero => intro _; simp + | succ t ih => + intro ht + rw [List.range'_concat, List.map_append, ih (by omega)] + have : N - (t + 1) + 1 = N - t := by omega + rw [List.range'_succ, this] + simp + omega + +/-- `totatives n` has `φ(n)` elements. -/ +private lemma len_tot (n : ℕ) : (totatives n).length = Nat.totient n := by + rw [← Nat.filter_coprime_Ico_eq_totient n 1, Nat.Ico_eq_range'] + simp [totatives, Finset.card, Finset.filter, Nat.coprime_comm] + +/-- For odd `n` and `2r ≥ n`: `2r - n` is coprime to `n` iff `r` is. -/ +private lemma cop_hi {n r : ℕ} (hn : Odd n) (hr : n ≤ 2 * r) : + Nat.Coprime (2 * r - n) n ↔ Nat.Coprime r n := by + rw [Nat.coprime_sub_self_left hr, Nat.coprime_mul_iff_left]; simp [hn] + +/-- For odd `n`: `n + 2r` is coprime to `n` iff `r` is. -/ +private lemma cop_lo {n r : ℕ} (hn : Odd n) : + Nat.Coprime (n + 2 * r) n ↔ Nat.Coprime r n := by + rw [add_comm, Nat.coprime_add_self_left, Nat.coprime_mul_iff_left]; simp [hn] + +/-- The totatives of `n = 2t+1` are those in `[1, t]` followed by those in `[t+1, 2t]`. -/ +private lemma tot_split (t : ℕ) (ht : 1 ≤ t) : + totatives (2 * t + 1) = + (List.range' 1 t).filter (fun r => Nat.Coprime r (2 * t + 1)) ++ + (List.range' (t + 1) t).filter (fun r => Nat.Coprime r (2 * t + 1)) := by + have e : List.range' 1 (2 * t + 1) = + List.range' 1 t ++ List.range' (t + 1) t ++ [2 * t + 1] := by + rw [show [2 * t + 1] = List.range' (1 + (t + t)) 1 by simp; omega, + show t + 1 = 1 + t by omega, List.range'_append_1, List.range'_append_1] + congr 1; omega + have hc : ¬ Nat.Coprime (2 * t + 1) (2 * t + 1) := by + rw [Nat.coprime_self]; omega + rw [totatives, e, List.filter_append, List.filter_append] + simp [hc] + +/-- The totatives of `2n`, `n = 2t+1`: first `2r - n` for the totatives `r > n/2` of `n`, then +`n + 2r` for the totatives `r < n/2`, each in increasing order. -/ +private lemma tot2_split (t : ℕ) (ht : 1 ≤ t) : + totatives (2 * (2 * t + 1)) = + ((List.range' (t + 1) t).filter (fun r => Nat.Coprime r (2 * t + 1))).map + (fun r => 2 * r - (2 * t + 1)) ++ + ((List.range' 1 t).filter (fun r => Nat.Coprime r (2 * t + 1))).map + (fun r => (2 * t + 1) + 2 * r) := by + have hn : Odd (2 * t + 1) := odd_two_mul_add_one t + have e : List.range' 1 (2 * (2 * t + 1)) = + List.range' 1 (2 * t) ++ List.range' (2 * t + 1) 2 ++ List.range' (2 * t + 3) (2 * t) := by + rw [show 2 * t + 1 = 1 + 2 * t by omega, List.range'_append_1, + show 2 * t + 3 = 1 + (2 * t + 2) by omega, List.range'_append_1] + congr 1; omega + have hmid : (List.range' (2 * t + 1) 2).filter + (fun s => Nat.Coprime s (2 * (2 * t + 1))) = [] := by + have c1 : ¬ Nat.Coprime (2 * t + 1) (2 * (2 * t + 1)) := by + intro h + have := Nat.Coprime.coprime_dvd_right (dvd_mul_left (2 * t + 1) 2) h + rw [Nat.coprime_self] at this; omega + have c2 : ¬ Nat.Coprime (2 * t + 1 + 1) (2 * (2 * t + 1)) := by + intro h + have := Nat.coprime_two_right.mp + (Nat.Coprime.coprime_dvd_right (dvd_mul_right 2 (2 * t + 1)) h) + rw [Nat.odd_add_one] at this + exact this hn + simp [List.range'_succ, c1, c2] + rw [totatives, e, List.filter_append, List.filter_append, hmid, List.append_nil, + filter_pair _ t 1 (by simp), filter_pair _ t (2 * t + 3) (by + rw [show 2 * t + 3 = 2 * (t + 1) + 1 by ring]; exact odd_two_mul_add_one _)] + have m1 : List.range' 1 t 2 = (List.range' (t + 1) t).map (fun r => 2 * r - (2 * t + 1)) := by + have := range'_two_eq_map (fun r => 2 * r - (2 * t + 1)) t (t + 1) + (fun r hr => by omega) + convert this using 2; omega + have m2 : List.range' (2 * t + 3) t 2 = (List.range' 1 t).map (fun r => (2 * t + 1) + 2 * r) := by + have := range'_two_eq_map (fun r => (2 * t + 1) + 2 * r) t 1 + (fun r hr => by omega) + convert this using 2 + rw [m1, m2, List.filter_map, List.filter_map] + congr 2 + · apply List.filter_congr + intro x hx + simp only [List.mem_range'_1] at hx + simp only [Function.comp, decide_eq_decide] + exact cop_hi hn (by omega) + · apply List.filter_congr + intro x hx + simp only [Function.comp, decide_eq_decide] + exact cop_lo hn + +/-- The reflection `r ↦ n - r` shows that equally many totatives of `n = 2t+1` lie below and +above `n/2`. -/ +private lemma len_eq (t : ℕ) : + ((List.range' 1 t).filter (fun r => Nat.Coprime r (2 * t + 1))).length = + ((List.range' (t + 1) t).filter (fun r => Nat.Coprime r (2 * t + 1))).length := by + have hm := map_sub_range' (2 * t + 1) t (by omega) + rw [show 2 * t + 1 - t = t + 1 by omega] at hm + rw [← List.length_reverse (as := List.filter _ (List.range' (t + 1) t)), + ← List.filter_reverse, ← hm, List.filter_map, List.length_map] + congr 1 + apply List.filter_congr + intro x hx + simp only [List.mem_range'_1] at hx + simp only [Function.comp, decide_eq_decide] + exact (Nat.coprime_self_sub_left (by omega)).symm + +/-- For odd `n > 1`, writing `φ(n)/n = a/b` in lowest terms: `φ(2n)/(2n) = (a/2)/b` in lowest +terms (since `a` is even), and `a n = b φ(n)`. -/ +private lemma rat_facts (n : ℕ) (hn : Odd n) (h1 : 1 < n) : + A109395 (2 * n) = A109395 n ∧ A076512 (2 * n) * 2 = A076512 n ∧ + A076512 n * n = A109395 n * Nat.totient n := by + set q : ℚ := (Nat.totient n : ℚ) / n with hqdef + have hn0 : (n : ℚ) ≠ 0 := by exact_mod_cast (show n ≠ 0 by omega) + have hq2 : (Nat.totient (2 * n) : ℚ) / ((2 * n : ℕ) : ℚ) = q / 2 := by + rw [Nat.totient_mul (Nat.coprime_two_left.mpr hn), Nat.totient_two, hqdef] + push_cast; ring + have key : (q.num : ℚ) * n = q.den * Nat.totient n := by + rw [← Rat.mul_den_eq_num q, hqdef]; field_simp + have keyZ : q.num * n = q.den * Nat.totient n := by exact_mod_cast key + have hev : Even q.num := by + have h2 : Even ((q.den : ℤ) * Nat.totient n) := by + apply Even.mul_left + exact_mod_cast Nat.totient_even (n := n) (by obtain ⟨k, hk⟩ := hn; omega) + rw [← keyZ, Int.even_mul] at h2 + rcases h2 with h2 | h2 + · exact h2 + · exact absurd (by exact_mod_cast h2 : Even n) (Nat.not_even_iff_odd.mpr hn) + obtain ⟨c, hc⟩ := hev + have hcop : Nat.Coprime c.natAbs (q.den : ℤ).natAbs := by + have := q.reduced + rw [hc, show c + c = 2 * c by ring, Int.natAbs_mul] at this + simpa using Nat.Coprime.coprime_mul_left this + have hdpos : (0 : ℤ) < q.den := by exact_mod_cast q.den_pos + have hq2' : q / 2 = (c : ℚ) / ((q.den : ℤ) : ℚ) := by + conv_lhs => rw [← Rat.num_div_den q, hc] + push_cast; ring + have hden := Rat.den_div_eq_of_coprime hdpos hcop + have hnum := Rat.num_div_eq_of_coprime hdpos hcop + rw [← hq2', ← hq2] at hden hnum + refine ⟨?_, ?_, keyZ⟩ + · show ((Nat.totient (2 * n) : ℚ) / ((2 * n : ℕ) : ℚ)).den = q.den + exact_mod_cast hden + · show ((Nat.totient (2 * n) : ℚ) / ((2 * n : ℕ) : ℚ)).num * 2 = q.num + rw [hnum, hc]; ring + +/-- `getD` at a valid index is `getElem`. -/ +private lemma getD_lt {l : List ℕ} {i : ℕ} (h : i < l.length) : l.getD i 0 = l[i] := by + simp [List.getD_eq_getElem?_getD, h] + +/-- If `φ(n) = h + h`, row `n` is the concatenation of its first `h` and last `h` entries. -/ +private lemma row_split (n h : ℕ) (hφ : Nat.totient n = h + h) : + row n = (List.range h).map (fun i => T n (i + 1)) ++ + (List.range h).map (fun i => T n (h + i + 1)) := by + rw [row, hφ, List.range_add, List.map_append, List.map_map] + rfl + +/-- Charlie Neder's conjecture on A308121 holds: for odd `n > 1`, row `2n` is row `n` with its +two halves interchanged. -/ +theorem result : statement := by + intro n hn h1 + obtain ⟨t, rfl⟩ := hn + have ht : 1 ≤ t := by omega + have hNodd : Odd (2 * t + 1) := odd_two_mul_add_one t + have htot := tot_split t ht + have htot2 := tot2_split t ht + have hlen := len_eq t + set N := 2 * t + 1 with hN + set L := (List.range' 1 t).filter (fun r => Nat.Coprime r N) with hL + set H := (List.range' (t + 1) t).filter (fun r => Nat.Coprime r N) with hH + set h := L.length with hh + have hφ : Nat.totient N = h + h := by + rw [← len_tot, htot, List.length_append]; omega + have hφ2 : Nat.totient (2 * N) = h + h := by + rw [← len_tot, htot2, List.length_append, List.length_map, List.length_map]; omega + obtain ⟨e1, e2, e3⟩ := rat_facts N hNodd (by omega) + rw [hφ] at e3 + have key : A076512 (2 * N) * N = (A109395 N : ℤ) * h := by + have : 2 * (A076512 (2 * N) * N) = 2 * ((A109395 N : ℤ) * h) := by + push_cast at e3 + linear_combination (N : ℤ) * e2 + e3 + exact Int.eq_of_mul_eq_mul_left (by norm_num) this + refine ⟨_, _, row_split N h hφ, by simp, ?_⟩ + rw [row_split (2 * N) h hφ2] + congr 1 + · apply List.map_congr_left + intro i hi + rw [List.mem_range] at hi + have hiH : i < H.length := by omega + have hmem : H[i] ∈ List.range' (t + 1) t := List.mem_of_mem_filter (List.getElem_mem hiH) + rw [List.mem_range'_1] at hmem + simp only [T, Nat.add_sub_cancel] + rw [htot2, htot, getD_lt (by simp; omega), getD_lt (by simp; omega), + List.getElem_append_left (by simp; omega), List.getElem_append_right (by omega), + List.getElem_map, e1] + have hsub : h + i - L.length = i := by omega + simp only [hsub] + push_cast [Nat.cast_sub (show N ≤ 2 * H[i] by omega)] + linear_combination (-(H[i] : ℤ)) * e2 + key + · apply List.map_congr_left + intro i hi + rw [List.mem_range] at hi + simp only [T, Nat.add_sub_cancel] + rw [htot2, htot, getD_lt (by simp; omega), getD_lt (by simp; omega), + List.getElem_append_right (by simp; omega), List.getElem_append_left (by omega), + List.getElem_map, e1] + have hsub : h + i - (List.map (fun r => 2 * r - N) H).length = i := by + rw [List.length_map]; omega + simp only [hsub] + push_cast + linear_combination (-(L[i] : ℤ)) * e2 - key + +end Math0.Frontier.A308121 + +#math0_settles Math0.Frontier.A308121.result Math0.Statements.A308121.statement diff --git a/lean/Math0/Frontier/OEIS/A308222.lean b/lean/Math0/Frontier/OEIS/A308222.lean new file mode 100644 index 0000000..b77ac45 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A308222.lean @@ -0,0 +1,172 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A308222 +import Math0.Audit + +/-! +# Perimeters of primitive Heronian isosceles triangles: A308222(n) = 2 · A096033(n + 2) + +We prove Kagey's conjecture. Write a primitive Heronian isosceles triangle with perimeter `2m` +as legs `s, s` and base `2(m - s)` (the statement file's `LegOK m s`: `m/2 < s < m`, `s` odd, +`gcd(s, m) = 1`, `m (2s - m)` a square). We show that for `m ≥ 3` such an `s` exists iff `m` is +an odd square or twice a square, i.e. iff `m` lies in A096033 (`IsLegHypDiff`): + +* If `m` is odd, then `gcd(m, 2s - m) = gcd(m, 2s) = 1`, so the square `m (2s - m)` forces `m` to + be a square. If `m = 2m'` is even, then `2s - m = 2f` with `s = m' + f`, `gcd(m', f) = 1`, and + `m' f` is a square, so `m'` is a square. +* Conversely, for `m = (2u+3)²` take `s = 4(u+1)² + 1` (then `2s - m = (2u+1)²`), and for + `m = 2(v+2)²` take `s = (v+2)² + (v+1)²` (then `2s - m = 2(v+1)²`); coprimality comes from + explicit Bezout identities. + +Odd numbers are never perimeters, and the differences `1, 2` (the only ones below `3`) give no +triangle. Hence `count IsPerimeter (2n) + 2 = count IsLegHypDiff n` for `n ≥ 3`, and the +`(k+2)`-th difference `d` satisfies `nth IsPerimeter k = 2d` via `Nat.nth_count`. +-/ + +namespace Math0.Frontier.A308222 +open Math0.Statements.A308222 + +/-- If coprime `a, b` have a square product, then `a` is a square. -/ +private theorem sq_of_coprime_mul {a b c : ℕ} (hab : Nat.Coprime a b) (h : a * b = c * c) : + ∃ k, k * k = a := by + obtain ⟨d, hd⟩ := exists_eq_pow_of_mul_eq_pow (a := a) (b := b) (c := c) (k := 2) + (Nat.isUnit_iff.2 hab) (by rw [h, sq]) + exact ⟨d, by rw [hd, sq]⟩ + +/-- A valid leg for half-perimeter `m` forces `m` to be a leg-hypotenuse difference. -/ +private theorem isLegHypDiff_of_legOK {m s : ℕ} (hl : LegOK m s) : IsLegHypDiff m := by + obtain ⟨h1, h2, hodd, hg, h, hh⟩ := hl + rw [isLegHypDiff_iff] + obtain ⟨e, he⟩ : ∃ e, 2 * s = m + e := ⟨2 * s - m, by omega⟩ + rw [show 2 * s - m = e by omega] at hh + rcases Nat.even_or_odd m with ⟨m', rfl⟩ | hmo + · right + obtain ⟨f, rfl⟩ : ∃ f, e = 2 * f := ⟨e / 2, by omega⟩ + obtain ⟨f', rfl⟩ : ∃ f', s = f' + m' := ⟨s - m', by omega⟩ + have hf : f' = f := by omega + subst hf + have hcs : Nat.Coprime m' (f' + m') := + Nat.Coprime.coprime_dvd_left (show m' ∣ m' + m' from ⟨2, by ring⟩) (Nat.Coprime.symm hg) + have hcop : Nat.Coprime m' f' := Nat.coprime_add_self_right.1 hcs + have hev : Even (h * h) := ⟨2 * (m' * f'), by rw [hh]; ring⟩ + have hh2 : Even h := by + rcases Nat.even_mul.1 hev with h' | h' <;> exact h' + obtain ⟨r, rfl⟩ := hh2 + have hr : m' * f' = r * r := by + have e1 : (r + r) * (r + r) = 4 * (r * r) := by ring + have e2 : (m' + m') * (2 * f') = 4 * (m' * f') := by ring + omega + obtain ⟨k, hk⟩ := sq_of_coprime_mul hcop hr + refine ⟨by omega, by omega, k, by omega⟩ + · left + have hc2 : Nat.Coprime m (2 * s) := + Nat.Coprime.mul_right (Nat.coprime_two_right.2 hmo) (Nat.Coprime.symm hg) + rw [he, add_comm] at hc2 + have hcop : Nat.Coprime m e := Nat.coprime_add_self_right.1 hc2 + obtain ⟨k, hk⟩ := sq_of_coprime_mul hcop hh.symm + exact ⟨Nat.odd_iff.1 hmo, k, hk⟩ + +/-- Conversely, every leg-hypotenuse difference `m ≥ 3` has a valid leg. -/ +private theorem legOK_of_isLegHypDiff {m : ℕ} (hm : 3 ≤ m) (hL : IsLegHypDiff m) : + ∃ s, LegOK m s := by + rw [isLegHypDiff_iff] at hL + rcases hL with ⟨hmo, k, rfl⟩ | ⟨hme, -, j, hj⟩ + · obtain ⟨u, rfl⟩ : ∃ u, k = 2 * u + 3 := by + rcases Nat.even_or_odd k with ⟨r, rfl⟩ | ⟨r, rfl⟩ + · exfalso + have : (r + r) * (r + r) = 2 * (2 * r * r) := by ring + omega + · rcases r with _ | r + · simp at hm + · exact ⟨r, by ring⟩ + refine ⟨4 * (u + 1) * (u + 1) + 1, by nlinarith, by nlinarith, ?_, ?_, ?_⟩ + · have : 4 * (u + 1) * (u + 1) + 1 = 2 * (2 * (u + 1) * (u + 1)) + 1 := by ring + omega + · apply Nat.isCoprime_iff_coprime.1 + exact ⟨(u + 2 : ℤ), -(u + 1 : ℤ), by push_cast; ring⟩ + · refine ⟨(2 * u + 3) * (2 * u + 1), ?_⟩ + rw [show 2 * (4 * (u + 1) * (u + 1) + 1) - (2 * u + 3) * (2 * u + 3) = + (2 * u + 1) * (2 * u + 1) from Nat.sub_eq_of_eq_add (by ring)] + ring + · obtain ⟨v, rfl⟩ : ∃ v, j = v + 2 := by + rcases j with _ | _ | v + · omega + · omega + · exact ⟨v, rfl⟩ + have hm2 : m = 2 * ((v + 2) * (v + 2)) := by omega + subst hm2 + refine ⟨(v + 2) * (v + 2) + (v + 1) * (v + 1), by nlinarith, by nlinarith, ?_, ?_, ?_⟩ + · have : (v + 2) * (v + 2) + (v + 1) * (v + 1) = 2 * (v * v + 3 * v + 2) + 1 := by ring + omega + · apply Nat.isCoprime_iff_coprime.1 + exact ⟨(2 * v + 5 : ℤ), -(2 * v + 3 : ℤ), by push_cast; ring⟩ + · refine ⟨2 * (v + 1) * (v + 2), ?_⟩ + rw [show 2 * ((v + 2) * (v + 2) + (v + 1) * (v + 1)) - 2 * ((v + 2) * (v + 2)) = + 2 * ((v + 1) * (v + 1)) from Nat.sub_eq_of_eq_add (by ring)] + ring + +/-- For `n ≥ 3`, `2n` is a perimeter iff `n` is a leg-hypotenuse difference. -/ +private theorem isPerimeter_two_mul {n : ℕ} (hn : 3 ≤ n) : + IsPerimeter (2 * n) ↔ IsLegHypDiff n := by + rw [isPerimeter_iff_legOK, show 2 * n / 2 = n by omega] + constructor + · rintro ⟨-, s, hs⟩ + exact isLegHypDiff_of_legOK hs + · intro h + exact ⟨by omega, legOK_of_isLegHypDiff hn h⟩ + +/-- Odd numbers are never perimeters. -/ +private theorem not_isPerimeter_odd (n : ℕ) : ¬ IsPerimeter (2 * n + 1) := by + rw [isPerimeter_iff_legOK] + rintro ⟨h, -⟩ + omega + +/-- Counting relation: below `2n` there are two fewer perimeters than there are differences +below `n` (the differences `1, 2` have no triangle). -/ +private theorem count_rel (n : ℕ) (hn : 3 ≤ n) : + Nat.count IsPerimeter (2 * n) + 2 = Nat.count IsLegHypDiff n := by + induction n, hn using Nat.le_induction with + | base => decide + | succ n hn ih => + rw [show 2 * (n + 1) = 2 * n + 1 + 1 by ring] + simp only [Nat.count_succ] + rw [if_neg (not_isPerimeter_odd n), ← ih] + by_cases h : IsLegHypDiff n + · rw [if_pos h, if_pos ((isPerimeter_two_mul hn).2 h)] + · rw [if_neg h, if_neg (fun h' => h ((isPerimeter_two_mul hn).1 h'))] + +/-- There are infinitely many leg-hypotenuse differences (all `2 j²`). -/ +private theorem infinite_L : (Set.ofPred IsLegHypDiff).Infinite := by + refine Set.infinite_of_forall_exists_gt fun N => ⟨2 * ((N + 1) * (N + 1)), ?_, ?_⟩ + · show IsLegHypDiff _ + rw [isLegHypDiff_iff] + right + exact ⟨by omega, by positivity, N + 1, by omega⟩ + · nlinarith + +/-- Kagey's conjecture: `a(n) = 2 · A096033(n + 2)`. -/ +theorem result : statement := by + intro n hn + obtain ⟨k, rfl⟩ : ∃ k, n = k + 1 := ⟨n - 1, by omega⟩ + unfold a A096033 + rw [show k + 1 + 2 - 1 = k + 2 by omega, show k + 1 - 1 = k by omega] + have hd : IsLegHypDiff (Nat.nth IsLegHypDiff (k + 2)) := Nat.nth_mem_of_infinite infinite_L _ + have hc : Nat.count IsLegHypDiff (Nat.nth IsLegHypDiff (k + 2)) = k + 2 := + Nat.count_nth_of_infinite infinite_L _ + generalize Nat.nth IsLegHypDiff (k + 2) = d at hd hc + have h3 : 3 ≤ d := by + by_contra h + have : Nat.count IsLegHypDiff d ≤ Nat.count IsLegHypDiff 2 := + Nat.count_monotone _ (by omega) + have h2 : Nat.count IsLegHypDiff 2 = 1 := by decide + omega + have hcr := count_rel d h3 + have hP : IsPerimeter (2 * d) := (isPerimeter_two_mul h3).2 hd + rw [← Nat.nth_count hP] + congr 1 + omega + +end Math0.Frontier.A308222 + +#math0_settles Math0.Frontier.A308222.result Math0.Statements.A308222.statement diff --git a/lean/Math0/Frontier/OEIS/A308359.lean b/lean/Math0/Frontier/OEIS/A308359.lean new file mode 100644 index 0000000..ff89436 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A308359.lean @@ -0,0 +1,757 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A308359 +import Math0.Audit + +/-! +# Fixed polyominoes with `n` cells and width `n - 2` (A308359) + +We prove R. J. Mathar's conjecture `T(n, n - 2) = 8n² - 51n + 86` for all `n ≥ 5`. + +Write `w = n - 2 ≥ 3`. A fixed polyomino `S` with `w + 2` cells and width `w` has every column +`0, …, w - 1` nonempty, so the column sizes exceed `1` by `2` in total, and it has at most `3` +rows (`cols_add_rows_le`), i.e. it lies in `[0, w) × [0, 3)`. + +* *Structure.* Consecutive columns share a row (otherwise no edge crosses between them), and no + column is `{0, 2}`: a chain joining its two cells passes a vertical edge between rows `0, 1` and + one between rows `1, 2`, in columns other than the gapped one, which forces at least `w + 3` + cells. So every column is a vertical interval. Conversely such "good" configurations (column + intervals, consecutive overlap) are connected. Hence the polyominoes are exactly the good + configurations with `w + 2` cells meeting row `0`. +* *Transfer matrix.* Classify good configurations of width `w` by the state `(e, a, b, z)`: + excess `e = |S| - w ≤ 2`, last column `a, …, b`, and whether row `0` is used. Removing the last + column is a bijection onto the configurations of width `w - 1` in compatible states, so the + counts satisfy a linear recursion `D` over 36 states. +* *Closed form.* For `w ≥ 3` each `D w s` is a quadratic `A w² + B w + C`; this is checked at + `w = 3` and propagated by three coefficient identities of the transfer matrix (all verified by + `decide`). Summing over the final states (`e = 2`, row `0` used) gives `8w² - 19w + 16`, which is + `8n² - 51n + 86`. +-/ + +namespace Math0.Frontier.A308359 +open Math0.Statements.A308359 + +/-- Column `x` of `S` consists exactly of the rows `a, …, b`. -/ +private def ColIs (S : Finset (ℕ × ℕ)) (x a b : ℕ) : Prop := ∀ y, (x, y) ∈ S ↔ a ≤ y ∧ y ≤ b + +/-- `S` is a good configuration of width `w`: its cells lie in the columns `0, …, w - 1`, each of +these columns is a nonempty vertical interval of rows inside `0, 1, 2`, and any two consecutive +columns share a row. -/ +private def Good (w : ℕ) (S : Finset (ℕ × ℕ)) : Prop := + (∀ p ∈ S, p.1 < w) ∧ (∀ x < w, ∃ a b, a ≤ b ∧ b ≤ 2 ∧ ColIs S x a b) ∧ + (∀ x, x + 1 < w → ∃ y, (x, y) ∈ S ∧ (x + 1, y) ∈ S) + +/-- Reachability inside `S` along edge-adjacent cells. -/ +private abbrev Reach (S : Finset (ℕ × ℕ)) := Relation.ReflTransGen (Step S) + +/-- A nonempty column interval determines its endpoints. -/ +private lemma colIs_unique {S : Finset (ℕ × ℕ)} {x a b a' b' : ℕ} (h : ColIs S x a b) + (h' : ColIs S x a' b') (hab : a ≤ b) (hab' : a' ≤ b') : a = a' ∧ b = b' := by + have h1 := (h' a).1 ((h a).2 ⟨le_rfl, hab⟩) + have h2 := (h a').1 ((h' a').2 ⟨le_rfl, hab'⟩) + have h3 := (h' b).1 ((h b).2 ⟨hab, le_rfl⟩) + have h4 := (h b').1 ((h' b').2 ⟨hab', le_rfl⟩) + omega + +/-- The cells of a good configuration lie in the box `[0, w) × [0, 3)`. -/ +private lemma good_row {w : ℕ} {S : Finset (ℕ × ℕ)} (hS : Good w S) {p : ℕ × ℕ} (hp : p ∈ S) : + p.1 < w ∧ p.2 ≤ 2 := by + have h1 := hS.1 p hp + obtain ⟨a, b, -, hb, hc⟩ := hS.2.1 p.1 h1 + have := (hc p.2).1 hp + exact ⟨h1, by omega⟩ + +/-- A good configuration of width `w` has at least `w` cells (every column is nonempty). -/ +private lemma good_le_card {w : ℕ} {S : Finset (ℕ × ℕ)} (hS : Good w S) : w ≤ S.card := by + have hsub : Finset.range w ⊆ S.image Prod.fst := by + intro x hx + rw [Finset.mem_range] at hx + obtain ⟨a, b, hab, -, hc⟩ := hS.2.1 x hx + exact Finset.mem_image.2 ⟨(x, a), (hc a).2 ⟨le_rfl, hab⟩, rfl⟩ + have := Finset.card_le_card hsub + rw [Finset.card_range] at this + exact this.trans Finset.card_image_le + +/-- Inside a column interval `a, …, b`, the cell in row `a + k` is reachable from row `a`. -/ +private lemma vert {S : Finset (ℕ × ℕ)} {x a b : ℕ} (h : ColIs S x a b) : + ∀ k, a + k ≤ b → Reach S (x, a) (x, a + k) + | 0, _ => Relation.ReflTransGen.refl + | k + 1, hk => by + refine (vert h k (by omega)).tail ⟨(h _).2 ⟨by omega, by omega⟩, (h _).2 ⟨by omega, hk⟩, ?_⟩ + unfold Adj + omega + +/-- Any two cells of a column that is an interval are joined inside that column. -/ +private lemma vert' {S : Finset (ℕ × ℕ)} {x a b y y' : ℕ} (h : ColIs S x a b) (hy : (x, y) ∈ S) + (hy' : (x, y') ∈ S) : Reach S (x, y) (x, y') := by + have h1 := (h y).1 hy + have h2 := (h y').1 hy' + have e1 := vert h (y - a) (by omega) + have e2 := vert h (y' - a) (by omega) + rw [show a + (y - a) = y by omega] at e1 + rw [show a + (y' - a) = y' by omega] at e2 + exact (reach_symm e1).trans e2 + +/-- A good configuration is edge-connected: walk up and down inside the column intervals and +step right through a shared row. -/ +private lemma good_conn {w : ℕ} {S : Finset (ℕ × ℕ)} (hS : Good w S) : IsConnected S := by + rcases Nat.eq_zero_or_pos w with rfl | hw + · intro p hp + exact absurd (hS.1 p hp) (Nat.not_lt_zero _) + obtain ⟨a0, b0, hab0, -, hc0⟩ := hS.2.1 0 hw + have h0 : (0, a0) ∈ S := (hc0 a0).2 ⟨le_rfl, hab0⟩ + have key : ∀ x, x < w → ∀ y, (x, y) ∈ S → Reach S (0, a0) (x, y) := by + intro x + induction x with + | zero => intro _ y hy; exact vert' hc0 h0 hy + | succ x ih => + intro hx y hy + obtain ⟨r, hr, hr'⟩ := hS.2.2 x hx + obtain ⟨a1, b1, -, -, hc1⟩ := hS.2.1 (x + 1) hx + refine ((ih (by omega) r hr).tail ⟨hr, hr', ?_⟩).trans (vert' hc1 hr' hy) + unfold Adj + omega + intro p hp q hq + exact (reach_symm (key p.1 (hS.1 p hp) p.2 hp)).trans (key q.1 (hS.1 q hq) q.2 hq) + +/-- A chain from row `≤ k` to row `> k` uses a vertical edge between rows `k` and `k + 1`. -/ +private lemma cross {S : Finset (ℕ × ℕ)} {p q : ℕ × ℕ} (h : Reach S p q) : + ∀ k, p.2 ≤ k → k < q.2 → ∃ c, (c, k) ∈ S ∧ (c, k + 1) ∈ S := by + induction h with + | refl => intro k h1 h2; omega + | @tail b c _ hbc ih => + intro k h1 h2 + by_cases hk : k < b.2 + · exact ih k h1 hk + · obtain ⟨hb, hc, hadj⟩ := hbc + unfold Adj at hadj + have e1 : b.1 = c.1 := by omega + have e2 : b.2 = k := by omega + have e3 : c.2 = k + 1 := by omega + refine ⟨b.1, ?_, ?_⟩ + · rw [← e2]; exact hb + · rw [← e3, e1]; exact hc + +/-- In a connected set with `w + 2` cells, `w` nonempty columns, no column is `{0, 2}`: joining its +two cells needs a column containing rows `0, 1` and one containing rows `1, 2`, both different from +it, and then the columns carry at least `w + 3` cells. -/ +private lemma no_gap {w : ℕ} {S : Finset (ℕ × ℕ)} (hcard : S.card = w + 2) + (hS : ∀ p ∈ S, p.1 < w) (hcol : ∀ x < w, ∃ y, (x, y) ∈ S) (hconn : IsConnected S) + {x : ℕ} (h0 : (x, 0) ∈ S) (h1 : (x, 1) ∉ S) (h2 : (x, 2) ∈ S) : False := by + obtain ⟨c1, hc10, hc11⟩ := cross (hconn _ h0 _ h2) 0 (by simp) (by simp) + obtain ⟨c2, hc21, hc22⟩ := cross (hconn _ h0 _ h2) 1 (by simp) (by simp) + have hc1x : c1 ≠ x := by rintro rfl; exact h1 hc11 + have hc2x : c2 ≠ x := by rintro rfl; exact h1 hc21 + set g : ℕ → ℕ := fun x' => (S.filter (fun p => p.1 = x')).card with hg + have hsum : S.card = ∑ x' ∈ Finset.range w, g x' := + Finset.card_eq_sum_card_fiberwise (fun p hp => Finset.mem_range.2 (hS p hp)) + have hlow : ∀ x' (T : Finset (ℕ × ℕ)), T ⊆ S → (∀ p ∈ T, p.1 = x') → T.card ≤ g x' := by + intro x' T hT hT' + exact Finset.card_le_card fun p hp => Finset.mem_filter.2 ⟨hT hp, hT' p hp⟩ + have hg1 : ∀ x' ∈ Finset.range w, 1 ≤ g x' := by + intro x' hx' + obtain ⟨y, hy⟩ := hcol x' (Finset.mem_range.1 hx') + simpa using hlow x' {(x', y)} (by simpa using hy) (by simp) + have hgx : 2 ≤ g x := by + have := hlow x {(x, 0), (x, 2)} (by simp [Finset.insert_subset_iff, h0, h2]) (by simp) + simpa using this + have hxw : x < w := hS _ h0 + have hc1w : c1 < w := hS _ hc10 + have hc2w : c2 < w := hS _ hc21 + have hsplit : ∑ x' ∈ Finset.range w, g x' = + ∑ x' ∈ Finset.range w, 1 + ∑ x' ∈ Finset.range w, (g x' - 1) := by + rw [← Finset.sum_add_distrib] + exact Finset.sum_congr rfl fun x' hx' => by have := hg1 x' hx'; omega + rw [Finset.sum_const, Finset.card_range, smul_eq_mul, mul_one] at hsplit + by_cases hc12 : c1 = c2 + · subst hc12 + have hgc : 3 ≤ g c1 := by + have := hlow c1 {(c1, 0), (c1, 1), (c1, 2)} + (by simp [Finset.insert_subset_iff, hc10, hc11, hc22]) (by simp) + simpa using this + have hT : ({x, c1} : Finset ℕ) ⊆ Finset.range w := by + simp [Finset.insert_subset_iff, hxw, hc1w] + have := Finset.sum_le_sum_of_subset (f := fun x' => g x' - 1) hT + rw [Finset.sum_pair (Ne.symm hc1x)] at this + omega + · have hgc1 : 2 ≤ g c1 := by + have := hlow c1 {(c1, 0), (c1, 1)} (by simp [Finset.insert_subset_iff, hc10, hc11]) + (by simp) + simpa using this + have hgc2 : 2 ≤ g c2 := by + have := hlow c2 {(c2, 1), (c2, 2)} (by simp [Finset.insert_subset_iff, hc21, hc22]) + (by simp) + simpa using this + have hT : ({x, c1, c2} : Finset ℕ) ⊆ Finset.range w := by + simp [Finset.insert_subset_iff, hxw, hc1w, hc2w] + have := Finset.sum_le_sum_of_subset (f := fun x' => g x' - 1) hT + rw [Finset.sum_insert (by simp [Ne.symm hc1x, Ne.symm hc2x]), Finset.sum_pair hc12] at this + omega + +/-- Checking a column interval inside the rows `0, 1, 2`. -/ +private lemma colIs_of {S : Finset (ℕ × ℕ)} {x a b : ℕ} (hb : b ≤ 2) + (hS : ∀ y, (x, y) ∈ S → y < 3) (h : ∀ y < 3, ((x, y) ∈ S ↔ a ≤ y ∧ y ≤ b)) : + ColIs S x a b := by + intro y + by_cases hy : y < 3 + · exact h y hy + · constructor + · intro hm; exact absurd (hS y hm) hy + · intro hm; omega + +/-- Every fixed polyomino with `w + 2` cells and width `w` is a good configuration. -/ +private lemma struct {w : ℕ} {S : Finset (ℕ × ℕ)} (h : IsPoly (w + 2) w S) : Good w S := by + have hbox := subset_box h + obtain ⟨hcard, ⟨p0, hp0S, hp0⟩, -, hsup, hconn⟩ := h + have hb : ∀ p ∈ S, p.1 < w ∧ p.2 < 3 := by + intro p hp + have := hbox hp + simp only [box, Finset.mem_product, Finset.mem_range] at this + omega + have hne : S.Nonempty := ⟨p0, hp0S⟩ + obtain ⟨m, hmS, hm⟩ := Finset.exists_mem_eq_sup S hne Prod.fst + have hfst : ∀ p q : ℕ × ℕ, Adj p q → q.1 ≤ p.1 + 1 := by + intro p q h + unfold Adj at h + omega + have hcol : ∀ x < w, ∃ y, (x, y) ∈ S := by + intro x hx + obtain ⟨c, hc, hcx⟩ := + exists_coord Prod.fst hfst hp0S (hconn p0 hp0S m hmS) x (by omega) (by omega) + exact ⟨c.2, by rw [← hcx]; exact hc⟩ + refine ⟨fun p hp => (hb p hp).1, ?_, ?_⟩ + · intro x hx + have hS3 : ∀ y, (x, y) ∈ S → y < 3 := fun y hy => (hb _ hy).2 + by_cases h0 : (x, 0) ∈ S <;> by_cases h1 : (x, 1) ∈ S <;> by_cases h2 : (x, 2) ∈ S + · exact ⟨0, 2, by omega, le_rfl, colIs_of le_rfl hS3 fun y hy => by + interval_cases y <;> simp [h0, h1, h2]⟩ + · exact ⟨0, 1, by omega, by omega, colIs_of (by omega) hS3 fun y hy => by + interval_cases y <;> simp [h0, h1, h2]⟩ + · exact (no_gap hcard (fun p hp => (hb p hp).1) hcol hconn h0 h1 h2).elim + · exact ⟨0, 0, le_rfl, by omega, colIs_of (by omega) hS3 fun y hy => by + interval_cases y <;> simp [h0, h1, h2]⟩ + · exact ⟨1, 2, by omega, le_rfl, colIs_of le_rfl hS3 fun y hy => by + interval_cases y <;> simp [h0, h1, h2]⟩ + · exact ⟨1, 1, le_rfl, by omega, colIs_of (by omega) hS3 fun y hy => by + interval_cases y <;> simp [h0, h1, h2]⟩ + · exact ⟨2, 2, le_rfl, le_rfl, colIs_of le_rfl hS3 fun y hy => by + interval_cases y <;> simp [h0, h1, h2]⟩ + · exfalso + obtain ⟨y, hy⟩ := hcol x hx + have := hS3 y hy + interval_cases y <;> contradiction + · intro x hx + by_contra hno + obtain ⟨y0, hy0⟩ := hcol x (by omega) + obtain ⟨y1, hy1⟩ := hcol (x + 1) hx + obtain ⟨b, hbA, c, hcS, hcA, hbc⟩ := + Math0.Statements.A308359.frontier (A := S.filter (fun p => p.1 ≤ x)) + (Finset.mem_filter.2 ⟨hy0, le_rfl⟩) (by simp) (hconn _ hy0 _ hy1) + rw [Finset.mem_filter] at hbA hcA + have hcx : x < c.1 := by + by_contra hh + exact hcA ⟨hcS, by omega⟩ + unfold Adj at hbc + have e1 : b.1 = x := by omega + have e2 : c.1 = x + 1 := by omega + have e3 : b.2 = c.2 := by omega + refine hno ⟨b.2, ?_, ?_⟩ + · rw [← e1]; exact hbA.1 + · rw [e3, ← e2]; exact hcS + +/-- The fixed polyominoes with `w + 2` cells and width `w` are exactly the good configurations +with `w + 2` cells meeting row `0`. -/ +private lemma poly_iff {w : ℕ} (hw : 1 ≤ w) (S : Finset (ℕ × ℕ)) : + IsPoly (w + 2) w S ↔ Good w S ∧ S.card = w + 2 ∧ ∃ p ∈ S, p.2 = 0 := by + constructor + · intro h + exact ⟨struct h, h.1, h.2.2.1⟩ + · rintro ⟨hS, hcard, hrow⟩ + obtain ⟨a0, b0, hab0, -, hc0⟩ := hS.2.1 0 (by omega) + obtain ⟨a1, b1, hab1, -, hc1⟩ := hS.2.1 (w - 1) (by omega) + have hm := (hc1 a1).2 ⟨le_rfl, hab1⟩ + refine ⟨hcard, ⟨(0, a0), (hc0 a0).2 ⟨le_rfl, hab0⟩, rfl⟩, hrow, ?_, good_conn hS⟩ + have h1 : S.sup Prod.fst ≤ w - 1 := Finset.sup_le fun p hp => by have := hS.1 p hp; omega + have h2 := Finset.le_sup (f := Prod.fst) hm + simp only at h2 + omega + +/-- A state `(e, a, b, z)`: the excess `e` (cells minus columns), the last column `a, …, b`, and +whether row `0` is used. -/ +private abbrev State := ℕ × ℕ × ℕ × Bool + +/-- The 36 states with `e ≤ 2` and `a ≤ b ≤ 2`. -/ +private def states : Finset State := + (Finset.range 3 ×ˢ Finset.range 3 ×ˢ Finset.range 3 ×ˢ (Finset.univ : Finset Bool)).filter + (fun s => s.2.1 ≤ s.2.2.1) + +/-- A configuration in state `t` extended by the column `a, …, b` (of state `s = (e, a, b, z)`) +is in state `s`: excesses add up, the two columns overlap, and the row-`0` flag is updated. -/ +private def Compat (s t : State) : Prop := + s.1 = t.1 + (s.2.2.1 - s.2.1) ∧ s.2.1 ≤ t.2.2.1 ∧ t.2.1 ≤ s.2.2.1 ∧ + s.2.2.2 = (t.2.2.2 || decide (s.2.1 = 0)) + +/-- `Compat` is decidable. -/ +private instance (s t : State) : Decidable (Compat s t) := + inferInstanceAs (Decidable (s.1 = t.1 + (s.2.2.1 - s.2.1) ∧ s.2.1 ≤ t.2.2.1 ∧ + t.2.1 ≤ s.2.2.1 ∧ s.2.2.2 = (t.2.2.2 || decide (s.2.1 = 0)))) + +/-- The transfer-matrix count: `D w s` configurations of width `w` in state `s`. -/ +private def D : ℕ → State → ℕ + | 0, _ => 0 + | 1, s => if s.1 = s.2.2.1 - s.2.1 ∧ s.2.2.2 = decide (s.2.1 = 0) then 1 else 0 + | w + 2, s => ∑ t ∈ states.filter (Compat s), D (w + 1) t + +/-- The coefficients `(A, B, C)` of the closed form `D w s = A w² + B w + C` (`w ≥ 3`). -/ +private def coef : State → ℤ × ℤ × ℤ + | (0, 0, 0, true) => (0, 0, 1) + | (0, 1, 1, false) => (0, 0, 1) + | (0, 2, 2, false) => (0, 0, 1) + | (1, 0, 0, true) => (0, 2, -3) + | (1, 0, 1, true) => (0, 0, 2) + | (1, 1, 1, false) => (0, 2, -3) + | (1, 1, 1, true) => (0, 2, -3) + | (1, 1, 2, false) => (0, 0, 2) + | (1, 2, 2, false) => (0, 2, -3) + | (2, 0, 0, true) => (3, -11, 12) + | (2, 0, 1, true) => (0, 6, -11) + | (2, 0, 2, true) => (0, 0, 3) + | (2, 1, 1, false) => (2, -10, 13) + | (2, 1, 1, true) => (4, -15, 16) + | (2, 1, 2, false) => (0, 4, -8) + | (2, 1, 2, true) => (0, 2, -3) + | (2, 2, 2, false) => (2, -10, 13) + | (2, 2, 2, true) => (1, -1, -1) + | _ => (0, 0, 0) + +/-- The final states: excess `2`, row `0` used. -/ +private def final : Finset State := states.filter (fun s => s.1 = 2 ∧ s.2.2.2 = true) + +set_option maxHeartbeats 4000000 in +/-- The quadratic coefficients are invariant under the transfer step. -/ +private lemma coefA : ∀ s ∈ states, ∑ t ∈ states.filter (Compat s), (coef t).1 = (coef s).1 := by + decide +kernel + +set_option maxHeartbeats 4000000 in +/-- The transfer step on the linear coefficients. -/ +private lemma coefB : ∀ s ∈ states, + ∑ t ∈ states.filter (Compat s), (coef t).2.1 = 2 * (coef s).1 + (coef s).2.1 := by + decide +kernel + +set_option maxHeartbeats 4000000 in +/-- The transfer step on the constant coefficients. -/ +private lemma coefC : ∀ s ∈ states, + ∑ t ∈ states.filter (Compat s), (coef t).2.2 = (coef s).1 + (coef s).2.1 + (coef s).2.2 := by + decide +kernel + +set_option maxHeartbeats 4000000 in +/-- The closed form at `w = 3`. -/ +private lemma D_three : ∀ s ∈ states, + (D 3 s : ℤ) = (coef s).1 * 3 ^ 2 + (coef s).2.1 * 3 + (coef s).2.2 := by + decide +kernel + +/-- Summing the closed forms over the final states gives `8w² - 19w + 16`. -/ +private lemma final_sum : (∑ s ∈ final, (coef s).1 = 8) ∧ (∑ s ∈ final, (coef s).2.1 = -19) ∧ + (∑ s ∈ final, (coef s).2.2 = 16) := by + decide +kernel + +/-- Membership in `states`. -/ +private lemma mem_states {s : State} : + s ∈ states ↔ s.1 < 3 ∧ s.2.1 < 3 ∧ s.2.2.1 < 3 ∧ s.2.1 ≤ s.2.2.1 := by + obtain ⟨e, a, b, z⟩ := s + simp [states, and_assoc] + +/-- The column `{x} × [a, b]`. -/ +private def colSet (x a b : ℕ) : Finset (ℕ × ℕ) := {x} ×ˢ Finset.Icc a b + +/-- Membership in a column. -/ +private lemma mem_colSet {x a b x' y : ℕ} : (x', y) ∈ colSet x a b ↔ x' = x ∧ a ≤ y ∧ y ≤ b := by + simp only [colSet, Finset.mem_product, Finset.mem_singleton, Finset.mem_Icc] + +/-- The size of a column. -/ +private lemma card_colSet (x a b : ℕ) : (colSet x a b).card = b + 1 - a := by + simp [colSet] + +/-- Adding the column `{x} × [a, b]` uses row `0` iff it was used or `a = 0`. -/ +private lemma row0_union {S' : Finset (ℕ × ℕ)} {x a b : ℕ} : + (∃ p ∈ S' ∪ colSet x a b, p.2 = 0) ↔ (∃ p ∈ S', p.2 = 0) ∨ a = 0 := by + constructor + · rintro ⟨⟨x', y⟩, hp, hp0⟩ + rcases Finset.mem_union.1 hp with hp | hp + · exact Or.inl ⟨_, hp, hp0⟩ + · right + rw [mem_colSet] at hp + simp only at hp0 + omega + · rintro (⟨p, hp, hp0⟩ | ha) + · exact ⟨p, Finset.mem_union_left _ hp, hp0⟩ + · exact ⟨(x, 0), Finset.mem_union_right _ (mem_colSet.2 ⟨rfl, by omega, by omega⟩), rfl⟩ + +/-- `S` is a good configuration of width `w` in state `s`. -/ +private def InP (w : ℕ) (s : State) (S : Finset (ℕ × ℕ)) : Prop := + Good w S ∧ S.card = w + s.1 ∧ ColIs S (w - 1) s.2.1 s.2.2.1 ∧ + ((∃ p ∈ S, p.2 = 0) ↔ s.2.2.2 = true) + +open scoped Classical in +/-- The finite set of good configurations of width `w` in state `s`. -/ +private noncomputable def Pset (w : ℕ) (s : State) : Finset (Finset (ℕ × ℕ)) := + (Finset.range w ×ˢ Finset.range 3).powerset.filter (InP w s) + +/-- Membership in `Pset`. -/ +private lemma mem_Pset {w : ℕ} {s : State} {S : Finset (ℕ × ℕ)} : + S ∈ Pset w s ↔ InP w s S := by + classical + unfold Pset + rw [Finset.mem_filter, Finset.mem_powerset] + constructor + · exact fun h => h.2 + · intro h + refine ⟨fun p hp => ?_, h⟩ + have := good_row h.1 hp + simp only [Finset.mem_product, Finset.mem_range] + omega + +/-- A configuration has only one state. -/ +private lemma Pset_unique {w : ℕ} {s t : State} (hs : s ∈ states) (ht : t ∈ states) + {S : Finset (ℕ × ℕ)} (h1 : S ∈ Pset w s) (h2 : S ∈ Pset w t) : s = t := by + obtain ⟨e, a, b, z⟩ := s + obtain ⟨e', a', b', z'⟩ := t + rw [mem_Pset] at h1 h2 + rw [mem_states] at hs ht + obtain ⟨-, hc1, hcol1, hz1⟩ := h1 + obtain ⟨-, hc2, hcol2, hz2⟩ := h2 + simp only at hs ht hc1 hcol1 hz1 hc2 hcol2 hz2 + obtain ⟨rfl, rfl⟩ := colIs_unique hcol1 hcol2 hs.2.2.2 ht.2.2.2 + have : z = z' := Bool.eq_iff_iff.2 (hz1.symm.trans hz2) + subst this + have : e = e' := by omega + subst this + rfl + +/-- Width one: the only configuration is the column itself. -/ +private lemma Pset_one {s : State} (hs : s ∈ states) : (Pset 1 s).card = D 1 s := by + obtain ⟨e, a, b, z⟩ := s + rw [mem_states] at hs + simp only at hs + have hsub : ∀ S ∈ Pset 1 (e, a, b, z), S = colSet 0 a b := by + intro S hS + rw [mem_Pset] at hS + obtain ⟨hG, -, hcol, -⟩ := hS + simp only [Nat.sub_self] at hcol + ext ⟨x, y⟩ + rw [mem_colSet] + constructor + · intro hp + have h1 : x = 0 := by have := hG.1 _ hp; simp only at this; omega + subst h1 + exact ⟨rfl, (hcol y).1 hp⟩ + · rintro ⟨rfl, h⟩ + exact (hcol y).2 h + have hrow : (∃ p ∈ colSet 0 a b, p.2 = 0) ↔ a = 0 := by + have := row0_union (S' := ∅) (x := 0) (a := a) (b := b) + simpa using this + rw [show D 1 (e, a, b, z) = if e = b - a ∧ z = decide (a = 0) then 1 else 0 from rfl] + split_ifs with hcond + · obtain ⟨rfl, rfl⟩ := hcond + rw [Finset.card_eq_one] + refine ⟨colSet 0 a b, Finset.eq_singleton_iff_unique_mem.2 ⟨?_, hsub⟩⟩ + rw [mem_Pset] + refine ⟨⟨?_, ?_, ?_⟩, ?_, ?_, ?_⟩ + · rintro ⟨x, y⟩ hp + rw [mem_colSet] at hp + simp only + omega + · intro x hx + refine ⟨a, b, hs.2.2.2, by omega, ?_⟩ + intro y + rw [mem_colSet] + omega + · intro x hx + omega + · simp only + rw [card_colSet] + omega + · intro y + rw [mem_colSet] + simp + · simp only [decide_eq_true_eq] + exact hrow + · rw [Finset.card_eq_zero, Finset.eq_empty_iff_forall_notMem] + intro S hS + have hSC := hsub S hS + rw [mem_Pset] at hS + obtain ⟨-, hcard, -, hz⟩ := hS + subst hSC + apply hcond + rw [card_colSet] at hcard + simp only at hcard hz + have he : e = b - a := by clear hrow hz hsub hcond; omega + refine ⟨he, Bool.eq_iff_iff.2 ?_⟩ + rw [← hz, hrow, decide_eq_true_eq] + +/-- The transfer step: removing the last column is a bijection from the configurations of width +`w + 1` in state `s` onto the configurations of width `w` in states compatible with `s`. -/ +private lemma Pset_succ {w : ℕ} (hw : 1 ≤ w) {s : State} (hs : s ∈ states) : + (Pset (w + 1) s).card = ∑ t ∈ states.filter (Compat s), (Pset w t).card := by + classical + rw [← Finset.card_biUnion (s := states.filter (Compat s)) (t := Pset w) ?_] + swap + · intro t ht t' ht' htt' + simp only [Finset.coe_filter, Set.mem_ofPred_eq] at ht ht' + rw [Function.onFun, Finset.disjoint_left] + intro S h1 h2 + exact htt' (Pset_unique ht.1 ht'.1 h1 h2) + obtain ⟨e, a, b, z⟩ := s + rw [mem_states] at hs + simp only at hs + refine Finset.card_nbij' (fun S => S.filter (fun p => p.1 < w)) (fun S' => S' ∪ colSet w a b) + ?_ ?_ ?_ ?_ + · intro S hS + simp only [Finset.mem_coe] at hS ⊢ + rw [mem_Pset] at hS + obtain ⟨hG, hcard, hcol, hz⟩ := hS + simp only [Nat.add_sub_cancel] at hcard hcol hz + obtain ⟨a', b', hab', hb', hcol'⟩ := hG.2.1 (w - 1) (by omega) + have hmem : ∀ x y, x < w → ((x, y) ∈ S.filter (fun p => p.1 < w) ↔ (x, y) ∈ S) := by + intro x y hx + simp [Finset.mem_filter, hx] + have hSu : S = S.filter (fun p => p.1 < w) ∪ colSet w a b := by + ext ⟨x, y⟩ + rw [Finset.mem_union, mem_colSet, Finset.mem_filter] + constructor + · intro hp + by_cases hx : x < w + · exact Or.inl ⟨hp, hx⟩ + · have := hG.1 _ hp + simp only at this + have hxw : x = w := by omega + subst hxw + exact Or.inr ⟨rfl, (hcol y).1 hp⟩ + · rintro (⟨hp, -⟩ | ⟨rfl, h⟩) + · exact hp + · exact (hcol y).2 h + have hdisj : Disjoint (S.filter (fun p => p.1 < w)) (colSet w a b) := by + rw [Finset.disjoint_left] + rintro ⟨x, y⟩ hp hpC + rw [mem_colSet] at hpC + have := (Finset.mem_filter.1 hp).2 + simp only at this + omega + have hG' : Good w (S.filter (fun p => p.1 < w)) := by + refine ⟨fun p hp => (Finset.mem_filter.1 hp).2, ?_, ?_⟩ + · intro x hx + obtain ⟨a1, b1, h1, h2, h3⟩ := hG.2.1 x (by omega) + exact ⟨a1, b1, h1, h2, fun y => (hmem x y hx).trans (h3 y)⟩ + · intro x hx + obtain ⟨y, hy1, hy2⟩ := hG.2.2 x (by omega) + exact ⟨y, (hmem x y (by omega)).2 hy1, (hmem (x + 1) y hx).2 hy2⟩ + have hle := good_le_card hG' + have hcardS : S.card = (S.filter (fun p => p.1 < w)).card + (b + 1 - a) := by + conv_lhs => rw [hSu] + rw [Finset.card_union_of_disjoint hdisj, card_colSet] + obtain ⟨y, hy1, hy2⟩ := hG.2.2 (w - 1) (by omega) + rw [Nat.sub_add_cancel hw] at hy2 + have hy1' := (hcol' y).1 hy1 + have hy2' := (hcol y).1 hy2 + have hrowS : (∃ p ∈ S, p.2 = 0) ↔ + (∃ p ∈ S.filter (fun p => p.1 < w), p.2 = 0) ∨ a = 0 := by + conv_lhs => rw [hSu] + exact row0_union + have hnum : (S.filter (fun p => p.1 < w)).card - w < 3 ∧ + e = (S.filter (fun p => p.1 < w)).card - w + (b - a) ∧ a ≤ b' ∧ a' ≤ b ∧ + (S.filter (fun p => p.1 < w)).card = w + ((S.filter (fun p => p.1 < w)).card - w) := by + clear hz hrowS hSu hmem hcol hcol' hG hG' hdisj + omega + rw [Finset.mem_biUnion] + refine ⟨((S.filter (fun p => p.1 < w)).card - w, a', b', + decide (∃ p ∈ S.filter (fun p => p.1 < w), p.2 = 0)), ?_, ?_⟩ + · rw [Finset.mem_filter, mem_states, Compat] + simp only + refine ⟨⟨hnum.1, by omega, by omega, hab'⟩, hnum.2.1, hnum.2.2.1, hnum.2.2.2.1, ?_⟩ + apply Bool.eq_iff_iff.2 + rw [← hz, hrowS] + simp + · rw [mem_Pset] + refine ⟨hG', hnum.2.2.2.2, ?_, ?_⟩ + · intro y' + exact (hmem _ y' (by omega)).trans (hcol' y') + · simp + · intro S' hS' + simp only [Finset.mem_coe, Finset.mem_biUnion, Finset.mem_filter] at hS' ⊢ + obtain ⟨⟨e', a', b', z'⟩, ⟨ht, hcomp⟩, hS'⟩ := hS' + rw [mem_states] at ht + rw [mem_Pset] at hS' ⊢ + obtain ⟨hG, hcard, hcol, hz⟩ := hS' + rw [Compat] at hcomp + obtain ⟨he, h1, h2, hzz⟩ := hcomp + simp only at ht hcard hcol hz he h1 h2 hzz ⊢ + have hdisj : Disjoint S' (colSet w a b) := by + rw [Finset.disjoint_left] + rintro ⟨x, y⟩ hp hpC + rw [mem_colSet] at hpC + have := hG.1 _ hp + simp only at this + omega + have hmemU : ∀ x y, x < w → ((x, y) ∈ S' ∪ colSet w a b ↔ (x, y) ∈ S') := by + intro x y hx + rw [Finset.mem_union, mem_colSet] + constructor + · rintro (h | ⟨rfl, -⟩) + · exact h + · omega + · exact Or.inl + have hcolw : ColIs (S' ∪ colSet w a b) w a b := by + intro y + rw [Finset.mem_union, mem_colSet] + constructor + · rintro (h | ⟨-, h⟩) + · have := hG.1 _ h + simp at this + · exact h + · intro h + exact Or.inr ⟨rfl, h⟩ + refine ⟨⟨?_, ?_, ?_⟩, ?_, ?_, ?_⟩ + · rintro ⟨x, y⟩ hp + rcases Finset.mem_union.1 hp with hp | hp + · have := hG.1 _ hp + simp only at this ⊢ + omega + · rw [mem_colSet] at hp + simp only + omega + · intro x hx + by_cases hx' : x < w + · obtain ⟨a1, b1, h1, h2, h3⟩ := hG.2.1 x hx' + exact ⟨a1, b1, h1, h2, fun y => (hmemU x y hx').trans (h3 y)⟩ + · have hxw : x = w := by omega + subst hxw + exact ⟨a, b, hs.2.2.2, by omega, hcolw⟩ + · intro x hx + by_cases hx' : x + 1 < w + · obtain ⟨y, hy1, hy2⟩ := hG.2.2 x hx' + exact ⟨y, (hmemU x y (by omega)).2 hy1, (hmemU (x + 1) y hx').2 hy2⟩ + · have hxw : x = w - 1 := by omega + subst hxw + refine ⟨max a a', (hmemU _ _ (by omega)).2 ((hcol _).2 ⟨le_max_right _ _, by omega⟩), ?_⟩ + rw [Nat.sub_add_cancel hw] + exact (hcolw _).2 ⟨le_max_left _ _, by omega⟩ + · rw [Finset.card_union_of_disjoint hdisj, hcard, card_colSet] + omega + · rw [Nat.add_sub_cancel] + exact hcolw + · rw [row0_union, hz, hzz] + simp + · intro S hS + simp only [Finset.mem_coe] at hS + rw [mem_Pset] at hS + obtain ⟨hG, -, hcol, -⟩ := hS + simp only [Nat.add_sub_cancel] at hcol + ext ⟨x, y⟩ + rw [Finset.mem_union, mem_colSet, Finset.mem_filter] + constructor + · rintro (⟨h, -⟩ | ⟨rfl, h⟩) + · exact h + · exact (hcol y).2 h + · intro h + by_cases hx : x < w + · exact Or.inl ⟨h, hx⟩ + · have := hG.1 _ h + simp only at this + have hxw : x = w := by omega + subst hxw + exact Or.inr ⟨rfl, (hcol y).1 h⟩ + · intro S' hS' + simp only [Finset.mem_coe, Finset.mem_biUnion] at hS' + obtain ⟨t, -, hS'⟩ := hS' + rw [mem_Pset] at hS' + ext ⟨x, y⟩ + rw [Finset.mem_filter, Finset.mem_union, mem_colSet] + constructor + · rintro ⟨h | ⟨rfl, -⟩, hx⟩ + · exact h + · simp at hx + · intro h + exact ⟨Or.inl h, hS'.1.1 _ h⟩ + +/-- The configurations are counted by `D`. -/ +private lemma card_Pset : ∀ w, 1 ≤ w → ∀ s ∈ states, (Pset w s).card = D w s := by + intro w hw + induction w, hw using Nat.le_induction with + | base => exact fun s hs => Pset_one hs + | succ w hw ih => + intro s hs + rw [Pset_succ hw hs] + obtain ⟨k, rfl⟩ : ∃ k, w = k + 1 := ⟨w - 1, by omega⟩ + show _ = ∑ t ∈ states.filter (Compat s), D (k + 1) t + exact Finset.sum_congr rfl fun t ht => ih t (Finset.mem_filter.1 ht).1 + +/-- The closed form of `D w s` for `w ≥ 3`, by induction using the coefficient identities. -/ +private lemma D_poly : ∀ w, 3 ≤ w → ∀ s ∈ states, + (D w s : ℤ) = (coef s).1 * (w : ℤ) ^ 2 + (coef s).2.1 * w + (coef s).2.2 := by + intro w hw + induction w, hw using Nat.le_induction with + | base => + intro s hs + have := D_three s hs + push_cast + exact this + | succ w hw ih => + intro s hs + obtain ⟨k, rfl⟩ : ∃ k, w = k + 1 := ⟨w - 1, by omega⟩ + have hD : D (k + 1 + 1) s = ∑ t ∈ states.filter (Compat s), D (k + 1) t := rfl + rw [hD, Nat.cast_sum, Finset.sum_congr rfl fun t ht => ih t (Finset.mem_filter.1 ht).1, + Finset.sum_add_distrib, Finset.sum_add_distrib, ← Finset.sum_mul, ← Finset.sum_mul, + coefA s hs, coefB s hs, coefC s hs] + push_cast + ring + +/-- Final states are states. -/ +private lemma mem_final {s : State} (h : s ∈ final) : s ∈ states := (Finset.mem_filter.1 h).1 + +/-- `T(w + 2, w)` is the number of good configurations in the final states. -/ +private lemma T_eq {w : ℕ} (hw : 1 ≤ w) : T (w + 2) w = ∑ s ∈ final, (Pset w s).card := by + classical + rw [T, ← Finset.card_biUnion (s := final) (t := Pset w) ?_] + · rw [← Set.ncard_coe_finset] + congr 1 + ext S + simp only [Set.mem_ofPred_eq, Finset.coe_biUnion, Finset.mem_coe, Set.mem_iUnion, exists_prop] + rw [poly_iff hw] + constructor + · rintro ⟨hG, hcard, hrow⟩ + obtain ⟨a, b, hab, hb, hcol⟩ := hG.2.1 (w - 1) (by omega) + refine ⟨(2, a, b, true), ?_, ?_⟩ + · rw [final, Finset.mem_filter, mem_states] + exact ⟨⟨by norm_num, show a < 3 by omega, show b < 3 by omega, hab⟩, rfl, rfl⟩ + · rw [mem_Pset] + exact ⟨hG, hcard, hcol, by simp [hrow]⟩ + · rintro ⟨s, hs, hS⟩ + rw [final, Finset.mem_filter] at hs + rw [mem_Pset] at hS + obtain ⟨hG, hcard, -, hz⟩ := hS + rw [hs.2.1] at hcard + exact ⟨hG, hcard, hz.2 hs.2.2⟩ + · intro t ht t' ht' htt' + simp only [final, Finset.coe_filter, Set.mem_ofPred_eq] at ht ht' + rw [Function.onFun, Finset.disjoint_left] + intro S h1 h2 + exact htt' (Pset_unique ht.1 ht'.1 h1 h2) + +/-- **Mathar's conjecture for A308359.** For every `n ≥ 5` the number of fixed polyominoes with +`n` cells and width `n - 2` is `8n² - 51n + 86`. -/ +theorem result : statement := by + intro n hn + obtain ⟨w, rfl⟩ : ∃ w, n = w + 2 := ⟨n - 2, by omega⟩ + rw [Nat.add_sub_cancel, T_eq (by omega), + Finset.sum_congr rfl fun s hs => card_Pset w (by omega) s (mem_final hs), + Nat.cast_sum, + Finset.sum_congr rfl fun s hs => D_poly w (by omega) s (mem_final hs), + Finset.sum_add_distrib, Finset.sum_add_distrib, ← Finset.sum_mul, ← Finset.sum_mul, + final_sum.1, final_sum.2.1, final_sum.2.2] + push_cast + ring + +end Math0.Frontier.A308359 + +#math0_settles Math0.Frontier.A308359.result Math0.Statements.A308359.statement diff --git a/lean/Math0/Frontier/OEIS/A320099.lean b/lean/Math0/Frontier/OEIS/A320099.lean new file mode 100644 index 0000000..c234a61 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A320099.lean @@ -0,0 +1,86 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A320099 +import Math0.Audit + +/-! +# Kagey's order-10 recurrence for no-leaf subgraphs of the `5 × n` grid holds + +We prove Peter Kagey's conjecture (A320099): for every `n > 10`, +`a(n) = 103 a(n-1) + 1063 a(n-2) - 1873 a(n-3) - 20274 a(n-4) + 44071 a(n-5) - 10365 a(n-6) +- 20208 a(n-7) + 5959 a(n-8) + 2300 a(n-9) - 500 a(n-10)`. + +**Idea.** The statement file proves `a n = (T ^ n) noH noH` for the `32 × 32` column transfer +matrix `T`, and that `fastRow k` is the row `noH` of `T ^ k`. Put `x P(x)` for the polynomial +`x^11 - 103 x^10 - 1063 x^9 + 1873 x^8 + 20274 x^7 - 44071 x^6 + 10365 x^5 + 20208 x^4 +- 5959 x^3 - 2300 x^2 + 500 x`. The row vector `e_noH` is annihilated on the left by it: +`e_noH · (x P)(T) = 0`, i.e. the rows `fastRow 1, …, fastRow 11` satisfy one linear relation +(the left Krylov space of `e_noH` has dimension exactly `11`). This finite vector identity is +checked by the kernel on the explicit rows (`row_identity`, written without subtractions). +Multiplying it on the right by `T ^ m` and reading the entry at `noH` gives the recurrence for +`a (m + 11)`, for every `m` (`nat_identity`), with no induction needed. +-/ + +namespace Math0.Frontier.A320099 +open Math0.Statements.A320099 Finset + +/-- Mapping over `states` turns a pointwise sum into `zipWith (+)`. -/ +private theorem map_add (f g : St → ℕ) : + states.map (fun R => f R + g R) = List.zipWith (· + ·) (states.map f) (states.map g) := by + rw [List.zipWith_map, List.zipWith_self] + +/-- Mapping over `states` turns a pointwise scalar multiple into a mapped scalar multiple. -/ +private theorem map_mul (c : ℕ) (f : St → ℕ) : + states.map (fun R => c * f R) = (states.map f).map (c * ·) := by + rw [List.map_map]; rfl + +/-- The row `noH` of `T ^ k`, listed along `states`, is `fastRow k`. -/ +private theorem map_row (k : ℕ) : states.map (fun R => (T ^ k) noH R) = fastRow k := + (fastRow_eq k).symm + +/-- The left annihilation `e_noH · T P(T) = 0`, entry by entry (kernel-checked on the rows). -/ +private theorem row_identity (R : St) : + (T ^ 11) noH R + 1873 * (T ^ 8) noH R + 20274 * (T ^ 7) noH R + 10365 * (T ^ 5) noH R + + 20208 * (T ^ 4) noH R + 500 * (T ^ 1) noH R = + 103 * (T ^ 10) noH R + 1063 * (T ^ 9) noH R + 44071 * (T ^ 6) noH R + + 5959 * (T ^ 3) noH R + 2300 * (T ^ 2) noH R := by + have h : states.map (fun R => (T ^ 11) noH R + 1873 * (T ^ 8) noH R + 20274 * (T ^ 7) noH R + + 10365 * (T ^ 5) noH R + 20208 * (T ^ 4) noH R + 500 * (T ^ 1) noH R) = + states.map (fun R => 103 * (T ^ 10) noH R + 1063 * (T ^ 9) noH R + + 44071 * (T ^ 6) noH R + 5959 * (T ^ 3) noH R + 2300 * (T ^ 2) noH R) := by + simp only [map_add, map_mul, map_row] + decide +kernel + exact (List.map_inj_left.1 h) R (mem_states R) + +/-- The recurrence for the entries `(T ^ (k + m)) noH noH`, for every `m`. -/ +private theorem nat_identity (m : ℕ) : + (T ^ (11 + m)) noH noH + 1873 * (T ^ (8 + m)) noH noH + 20274 * (T ^ (7 + m)) noH noH + + 10365 * (T ^ (5 + m)) noH noH + 20208 * (T ^ (4 + m)) noH noH + + 500 * (T ^ (1 + m)) noH noH = + 103 * (T ^ (10 + m)) noH noH + 1063 * (T ^ (9 + m)) noH noH + + 44071 * (T ^ (6 + m)) noH noH + 5959 * (T ^ (3 + m)) noH noH + + 2300 * (T ^ (2 + m)) noH noH := by + simp only [pow_add, Matrix.mul_apply, Finset.mul_sum, ← Finset.sum_add_distrib] + refine Finset.sum_congr rfl fun R _ => ?_ + have h := congrArg (· * (T ^ m) R noH) (row_identity R) + simp only [add_mul, mul_assoc] at h + exact h + +/-- Kagey's recurrence holds for every `n > 10`. -/ +theorem result : statement := by + intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = 11 + m := ⟨n - 11, by omega⟩ + rw [show 11 + m - 1 = 10 + m by omega, show 11 + m - 2 = 9 + m by omega, + show 11 + m - 3 = 8 + m by omega, show 11 + m - 4 = 7 + m by omega, + show 11 + m - 5 = 6 + m by omega, show 11 + m - 6 = 5 + m by omega, + show 11 + m - 7 = 4 + m by omega, show 11 + m - 8 = 3 + m by omega, + show 11 + m - 9 = 2 + m by omega, show 11 + m - 10 = 1 + m by omega] + simp only [a_eq_T] + have h := nat_identity m + zify at h + linarith + +end Math0.Frontier.A320099 + +#math0_settles Math0.Frontier.A320099.result Math0.Statements.A320099.statement diff --git a/lean/Math0/Frontier/OEIS/A323695.lean b/lean/Math0/Frontier/OEIS/A323695.lean new file mode 100644 index 0000000..bb91758 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A323695.lean @@ -0,0 +1,138 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A323695 +import Math0.Audit + +/-! +# Odd terms of A323695 occur only at `n = k*(k+2)` + +We prove Hanna's conjecture: if `a n` is odd then `n + 1` is a perfect square, i.e. +`n = k * (k + 2)`. + +Idea: reduce mod 2. In `(ZMod 2)⟦X⟧` we have `1 - X^(m+1) = 1 + X^(m+1)`, so the `m`-th summand +`X^m (1 - X^(m+1))^m / (1 + X^(m+1))^(m+1)` becomes `X^m / (1 + X^(m+1)) = ∑_j X^((m+1)(j+1) - 1)` +(we use `-1 = 1` once more on the coefficients of `1/(1 + X^(m+1))`). Its coefficient of `x^N` +is `1` exactly when `m + 1 ∣ N + 1`, so `a N ≡ #{divisors of N + 1} (mod 2)`. If `N + 1` is not +a square, the involution `d ↦ (N + 1)/d` on the divisors has no fixed point, so the number of +divisors is even and `a N` is even. +-/ + +namespace Math0.Frontier.A323695 +open Math0.Statements.A323695 PowerSeries + +/-- In `(ZMod 2)⟦X⟧`, `-1 = 1`. -/ +private theorem neg_one_eq : (-1 : PowerSeries (ZMod 2)) = 1 := by + ext n + rw [map_neg, coeff_one] + split_ifs <;> decide + +/-- `E b hb = ∑_j (-1)^j X^(b j)`, the inverse of `1 + X^b` in `ℤ⟦X⟧` (the case `d = 0` of +`one_add_X_pow_pow_mul` in the statement file). -/ +private noncomputable def E (b : ℕ) (hb : b ≠ 0) : PowerSeries ℤ := + expand b hb (evalNegHom (mk fun j => (Nat.choose (0 + j) 0 : ℤ))) + +/-- Mod 2, `summand m = X^m / (1 + X^(m+1)) = X^m * E (m+1)`: since `-1 = 1` mod 2, the factor +`(1 - X^(m+1))^m` cancels against `(1 + X^(m+1))^(m+1)` up to one factor. -/ +private theorem map_summand (m : ℕ) : + map (Int.castRingHom (ZMod 2)) (summand m) = + X ^ m * map (Int.castRingHom (ZMod 2)) (E (m + 1) (by omega)) := by + have h1 := congrArg (map (Int.castRingHom (ZMod 2))) (summand_spec m) + have h2 := congrArg (map (Int.castRingHom (ZMod 2))) (one_add_X_pow_pow_mul (m + 1) 0 (by omega)) + rw [← E] at h2 + simp only [map_mul, map_pow, map_add, map_sub, map_one, map_X, zero_add, pow_one] at h1 h2 + rw [sub_eq_add_neg, ← neg_one_mul (X ^ (m + 1)), neg_one_eq, one_mul] at h1 + generalize map (Int.castRingHom (ZMod 2)) (summand m) = s at h1 ⊢ + generalize map (Int.castRingHom (ZMod 2)) (E (m + 1) (by omega)) = e at h2 ⊢ + generalize (1 + X ^ (m + 1) : PowerSeries (ZMod 2)) = u at h1 h2 + calc s = (u * e) ^ (m + 1) * s := by rw [h2, one_pow, one_mul] + _ = e ^ (m + 1) * (u ^ (m + 1) * s) := by ring + _ = e ^ (m + 1) * (X ^ m * u ^ m) := by rw [h1] + _ = X ^ m * e * (u * e) ^ m := by ring + _ = X ^ m * e := by rw [h2, one_pow, mul_one] + +/-- Mod 2, the coefficient of `x^N` in `summand m` is `1` if `m + 1 ∣ N + 1` (and `m ≤ N`), +and `0` otherwise. -/ +private theorem coeff_map_summand (N m : ℕ) : + coeff N (map (Int.castRingHom (ZMod 2)) (summand m)) = + if m + 1 ∣ N + 1 ∧ m ≤ N then 1 else 0 := by + rw [map_summand, coeff_X_pow_mul', E] + split_ifs with h1 h2 h2 + · rw [coeff_map, coeff_E _ _ _ (by omega)] + rw [if_pos] + · simp + · apply Nat.mod_eq_zero_of_dvd + have h3 : N - m = (N + 1) - (m + 1) := by omega + rw [h3] + exact Nat.dvd_sub h2.1 (dvd_refl _) + · rw [coeff_map, coeff_E _ _ _ (by omega), if_neg] + · rfl + · intro h3 + apply h2 + refine ⟨?_, h1⟩ + have h4 : N + 1 = (N - m) + (m + 1) := by omega + rw [h4] + exact dvd_add (Nat.dvd_of_mod_eq_zero h3) (dvd_refl _) + · exact absurd h2.2 h1 + · rfl + +/-- Mod 2, `a N` counts the `m ≤ N` with `m + 1 ∣ N + 1`. -/ +private theorem cast_a (N : ℕ) : + ((a N : ℤ) : ZMod 2) = + ∑ m ∈ Finset.range (N + 1), if m + 1 ∣ N + 1 ∧ m ≤ N then (1 : ZMod 2) else 0 := by + rw [a_eq_coeff, A, coeff_mk, Int.cast_sum] + refine Finset.sum_congr rfl fun m _ => ?_ + rw [← coeff_map_summand, coeff_map] + rfl + +/-- If `N + 1` is not a square, the number of divisors of `N + 1` is even. -/ +private theorem sum_eq_zero (N : ℕ) (hN : ∀ k : ℕ, N ≠ k * (k + 2)) : + ∑ m ∈ Finset.range (N + 1), (if m + 1 ∣ N + 1 ∧ m ≤ N then (1 : ZMod 2) else 0) = 0 := by + rw [← Finset.sum_filter] + have key : ∀ m ∈ Finset.filter (fun m => m + 1 ∣ N + 1 ∧ m ≤ N) (Finset.range (N + 1)), + ∃ c, N + 1 = (m + 1) * c ∧ 1 ≤ c ∧ (N + 1) / (m + 1) = c ∧ m ≤ N := by + intro m hm + rw [Finset.mem_filter] at hm + obtain ⟨c, hc⟩ := hm.2.1 + refine ⟨c, hc, ?_, ?_, hm.2.2⟩ + · rcases Nat.eq_zero_or_pos c with h | h + · rw [h, mul_zero] at hc; omega + · exact h + · rw [hc, Nat.mul_div_cancel_left _ (by omega)] + refine Finset.sum_involution (fun m _ => (N + 1) / (m + 1) - 1) ?_ ?_ ?_ ?_ + · intro _ _ + decide + · intro m hm _ heq + obtain ⟨c, hc, hc1, hdiv, _⟩ := key m hm + rw [hdiv] at heq + apply hN m + have hcm : c = m + 1 := by omega + rw [hcm] at hc + have : N + 1 = m * (m + 2) + 1 := by rw [hc]; ring + omega + · intro m hm + obtain ⟨c, hc, hc1, hdiv, hmN⟩ := key m hm + rw [hdiv, Finset.mem_filter, Finset.mem_range] + have hcdvd : c ∣ N + 1 := ⟨m + 1, by rw [hc, mul_comm]⟩ + have hcle : c ≤ N + 1 := Nat.le_of_dvd (by omega) hcdvd + refine ⟨by omega, ?_, by omega⟩ + rw [Nat.sub_add_cancel hc1] + exact hcdvd + · intro m hm + obtain ⟨c, hc, hc1, hdiv, hmN⟩ := key m hm + show (N + 1) / ((N + 1) / (m + 1) - 1 + 1) - 1 = m + rw [hdiv, Nat.sub_add_cancel hc1, hc, Nat.mul_div_cancel _ (by omega)] + omega + +/-- Hanna's conjecture for A323695: odd terms `a n` occur only at `n = k * (k + 2)`. -/ +theorem result : statement := by + intro n hodd + by_contra hne' + have hne : ∀ k : ℕ, n ≠ k * (k + 2) := fun k hk => hne' ⟨k, hk⟩ + have h1 : ((a n : ℤ) : ZMod 2) = 1 := ZMod.intCast_eq_one_iff_odd.mpr hodd + rw [cast_a, sum_eq_zero n hne] at h1 + exact absurd h1 (by decide) + +end Math0.Frontier.A323695 + +#math0_settles Math0.Frontier.A323695.result Math0.Statements.A323695.statement diff --git a/lean/Math0/Frontier/OEIS/A326407.lean b/lean/Math0/Frontier/OEIS/A326407.lean new file mode 100644 index 0000000..c0930d1 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A326407.lean @@ -0,0 +1,152 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A326407 +import Math0.Audit + +/-! +# Prime-Minesweeper on the A060734 array: `a(n) < 6`, and `a(n) = 5` only at `n = 6` + +We prove Tatkiewicz's two conjectures from A326407: for every `n ≥ 1`, `a(n) ≤ 4` unless +`n = 6`, and `a(6) = 5`. + +**Checkerboard parity.** `val r c ≡ r + c + 1 (mod 2)`: on and above the diagonal +`(c+1)^2 - r ≡ c + 1 + r`, below it `r^2 + 1 + c ≡ r + 1 + c`. So the cells with `r + c` odd hold +even numbers, and the only even prime `2` sits in the single cell `(1, 0)` (as `pos 2 = (1, 0)` +and `val` is injective). Hence an even-valued cell other than `(1, 0)` is never prime. + +**Counting.** For an interior cell `(s+1, t+1)` the 4 diagonal neighbours have one parity of +`i + j` and the 4 orthogonal neighbours the other. If `s + t` is odd the diagonal neighbours are +even-valued, and none of them is `(1, 0)` unless `(s, t) = (1, 0)`, i.e. the cell is `(2, 1)` +holding `6`; if `s + t` is even the orthogonal ones are even-valued and avoid `(1, 0)` unless +the cell is `(1, 1)` (checked directly). Either way at least 4 of the 8 neighbours are not +prime. In row `0` (5 neighbours) and column `0` (5 neighbours) the same parity bookkeeping +excludes at least one neighbour, and the corner `(0, 0)` has only 3 neighbours. So every cell +except `(2, 1)` has at most 4 prime neighbours, while the cell `(2, 1)` of `6` has exactly 5 +(namely `2, 3, 5, 7, 11`). Since `6` is not prime, `a(6) = 5`. +-/ + +namespace Math0.Frontier.A326407 +open Math0.Statements.A326407 + +/-- The numbers in the cells adjacent to the cell `(r, c)` (same shape as `neighbours`). -/ +private def nb (r c : ℕ) : List ℕ := + (near r).flatMap fun i => + (near c).filterMap fun j => if (i, j) = (r, c) then none else some (val i j) + +/-- `neighbours n` is `nb` at the cell of `n`. -/ +private theorem neighbours_eq (n : ℕ) : neighbours n = nb (pos n).1 (pos n).2 := rfl + +/-- `c * c` has the parity of `c`. -/ +private theorem mul_self_mod_two (c : ℕ) : c * c % 2 = c % 2 := by + rcases Nat.mod_two_eq_zero_or_one c with h | h <;> simp [Nat.mul_mod, h] + +/-- Checkerboard parity of the array: `val i j ≡ i + j + 1 (mod 2)`. -/ +private theorem val_mod_two (i j : ℕ) : val i j % 2 = (i + j + 1) % 2 := by + unfold val + split_ifs with h + · have e : (j + 1) ^ 2 = j * j + 2 * j + 1 := by ring + rw [e] + have := mul_self_mod_two j + omega + · have e : i ^ 2 = i * i := by ring + rw [e] + have := mul_self_mod_two i + omega + +/-- The only cell holding `2` is `(1, 0)`. -/ +private theorem val_eq_two {i j : ℕ} (h : val i j = 2) : i = 1 ∧ j = 0 := by + have := pos_val i j + rw [h, show pos 2 = (1, 0) by decide +kernel] at this + simp only [Prod.mk.injEq] at this + omega + +/-- An even-valued cell (`i + j` odd) other than `(1, 0)` does not hold a prime. -/ +private theorem not_prime_val {i j : ℕ} (h1 : (i + j) % 2 = 1) (h2 : ¬ (i = 1 ∧ j = 0)) : + ¬ (val i j).Prime := by + intro hp + rcases hp.eq_two_or_odd with h | h + · exact h2 (val_eq_two h) + · have := val_mod_two i j + omega + +/-- Counting primes in a list one element at a time. -/ +private theorem len_filter_cons (a : ℕ) (l : List ℕ) : + ((a :: l).filter fun m => m.Prime).length = + (l.filter fun m => m.Prime).length + (if a.Prime then 1 else 0) := by + by_cases h : a.Prime <;> simp [h] + +/-- Every cell other than `(2, 1)` has at most 4 prime neighbours. -/ +private theorem count_le (r c : ℕ) (h : ¬ (r = 2 ∧ c = 1)) : + ((nb r c).filter fun m => m.Prime).length ≤ 4 := by + rcases r with _ | s <;> rcases c with _ | t + · decide +kernel + · simp [nb, near] + simp only [len_filter_cons, List.filter_nil, List.length_nil] + rcases Nat.mod_two_eq_zero_or_one t with ht | ht + · have h1 : ¬ (val 1 (t + 1 + 1)).Prime := not_prime_val (by omega) (by omega) + simp only [h1, if_false] + split_ifs <;> omega + · have h1 : ¬ (val 0 t).Prime := not_prime_val (by omega) (by omega) + have h2 : ¬ (val 0 (t + 1 + 1)).Prime := not_prime_val (by omega) (by omega) + simp only [h1, h2, if_false] + split_ifs <;> omega + · simp [nb, near] + simp only [len_filter_cons, List.filter_nil, List.length_nil] + rcases Nat.mod_two_eq_zero_or_one s with hs | hs + · have h1 : ¬ (val s 1).Prime := not_prime_val (by omega) (by omega) + simp only [h1, if_false] + split_ifs <;> omega + · have h1 : ¬ (val (s + 1) 1).Prime := not_prime_val (by omega) (by omega) + have h2 : ¬ (val (s + 1 + 1) 0).Prime := not_prime_val (by omega) (by omega) + simp only [h1, h2, if_false] + split_ifs <;> omega + · by_cases h0 : s = 0 ∧ t = 0 + · obtain ⟨rfl, rfl⟩ := h0 + decide +kernel + simp [nb, near] + simp only [len_filter_cons, List.filter_nil, List.length_nil] + rcases Nat.mod_two_eq_zero_or_one (s + t) with hst | hst + · have h1 : ¬ (val s (t + 1)).Prime := not_prime_val (by omega) (by omega) + have h2 : ¬ (val (s + 1) t).Prime := not_prime_val (by omega) (by omega) + have h3 : ¬ (val (s + 1) (t + 1 + 1)).Prime := not_prime_val (by omega) (by omega) + have h4 : ¬ (val (s + 1 + 1) (t + 1)).Prime := not_prime_val (by omega) (by omega) + simp only [h1, h2, h3, h4, if_false] + split_ifs <;> omega + · have h1 : ¬ (val s t).Prime := not_prime_val (by omega) (by omega) + have h2 : ¬ (val s (t + 1 + 1)).Prime := not_prime_val (by omega) (by omega) + have h3 : ¬ (val (s + 1 + 1) t).Prime := not_prime_val (by omega) (by omega) + have h4 : ¬ (val (s + 1 + 1) (t + 1 + 1)).Prime := not_prime_val (by omega) (by omega) + simp only [h1, h2, h3, h4, if_false] + split_ifs <;> omega + +/-- `a(6) = 5` (kernel-checked). -/ +private theorem a_six : a 6 = 5 := by + decide +kernel + +/-- For `n ≥ 1`, `n ≠ 6`, we have `a(n) ≤ 4`. -/ +private theorem a_le_four {n : ℕ} (hn : 1 ≤ n) (h6 : n ≠ 6) : a n ≤ 4 := by + unfold a + split_ifs with hp + · norm_num + · rw [neighbours_eq] + have hc : ¬ ((pos n).1 = 2 ∧ (pos n).2 = 1) := by + rintro ⟨h1, h2⟩ + have := val_pos hn + rw [h1, h2, show val 2 1 = 6 by decide] at this + exact h6 this.symm + exact_mod_cast count_le _ _ hc + +/-- Both conjectures of A326407: `a(n) < 6` for `n ≥ 1`, and `a(n) = 5 ↔ n = 6`. -/ +theorem result : statement := by + refine ⟨fun n hn => ?_, fun n hn => ⟨fun h5 => ?_, fun h => ?_⟩⟩ + · by_cases h6 : n = 6 + · subst h6; rw [a_six]; norm_num + · have := a_le_four hn h6; omega + · by_contra h6 + have := a_le_four hn h6; omega + · subst h; exact a_six + +end Math0.Frontier.A326407 + +#math0_settles Math0.Frontier.A326407.result Math0.Statements.A326407.statement diff --git a/lean/Math0/Frontier/OEIS/A326602.lean b/lean/Math0/Frontier/OEIS/A326602.lean new file mode 100644 index 0000000..02bb626 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A326602.lean @@ -0,0 +1,226 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A326602 +import Math0.Audit + +/-! +# A326602: `a n` is odd iff `n` is a square + +We prove Hanna's conjecture: the coefficient `a n` of `x^(2n)` in +`∑_{n ≥ 0} (x^(2n-1) + 1)^n x^n / (1 + x^(2n+1))^(n+1)` is odd iff `n` is a perfect square. + +Idea. Write `p = x`, `s = x^(2n)`, so the `n`-th summand is `(p + s)^n / (1 + p s)^(n+1)`. +Expanding, the coefficient of `x^N` in the `n`-th summand is the sum, over `i ≤ n` and `j ≥ 0` +with `n + (2n-1) i + (2n+1) j = N`, of `(-1)^j C(n,i) C(n+j,j)`. Put `m = i + j`: the exponent +becomes `n + m + 2nm - 2i` and (up to sign) the weight becomes the trinomial coefficient +`T n m i = C(n+m-i, i) C(n+m-2i, n-i) = (n+m-i)! / (i! (n-i)! (m-i)!)`. Both are symmetric in +`n, m`. Hence, mod 2, `coeff N A` is the sum of `T n m i` over the finite set of triples +`(n, i, m)` with `i ≤ n`, `i ≤ m`, `n + m + 2nm = N + 2i`, and the involution `n ↔ m` cancels all +off-diagonal triples. On the diagonal `n = m`, `T n n i = C(2n-i, i) C(2(n-i), n-i)` is even +unless `i = n` (central binomial coefficients are even), and the triple `(n, n, n)` has exponent +`2n²` and weight `1`. So `A ≡ ∑_k x^(2k²) (mod 2)`. +-/ + +namespace Math0.Frontier.A326602 +open Math0.Statements.A326602 + +/-- The symmetric weight `T n m i = C(n+m-i, i) C(n+m-2i, n-i)`. -/ +private def T (n m i : ℕ) : ℕ := (n + m - i).choose i * (n + m - 2 * i).choose (n - i) + +/-- `T` is symmetric in its first two arguments. -/ +private theorem T_symm {n m i : ℕ} (hn : i ≤ n) (hm : i ≤ m) : T n m i = T m n i := by + unfold T + rw [add_comm m n] + congr 1 + exact Nat.choose_symm_of_eq_add (by omega) + +/-- `C(n,i) C(n+j,j) = T n (i+j) i`. -/ +private theorem T_eq {n i j : ℕ} (hi : i ≤ n) : + n.choose i * (n + j).choose j = T n (i + j) i := by + unfold T + have h1 : n + (i + j) - i = n + j := by omega + have h2 : n + (i + j) - 2 * i = n + j - i := by omega + rw [h1, h2, ← Nat.choose_mul (n := n + j) hi, ← Nat.choose_symm_add, Nat.mul_comm] + +/-- The exponent identity `((2n-1) i + n) + (2n+1) j + 2i = n + m + 2nm` with `m = i + j`. -/ +private theorem key_arith {n i j : ℕ} (hi : i ≤ n) : + (2 * n - 1) * i + n + (2 * n + 1) * j + 2 * i = n + (i + j) + 2 * (n * (i + j)) := by + rcases Nat.eq_zero_or_pos n with rfl | hn + · obtain rfl : i = 0 := by omega + ring + · obtain ⟨k, rfl⟩ : ∃ k, n = k + 1 := ⟨n - 1, by omega⟩ + rw [show 2 * (k + 1) - 1 = 2 * k + 1 by omega] + ring + +/-- `m ↦ n + m + 2nm` is injective. -/ +private theorem inj_aux {n m m' : ℕ} (h : n + m + 2 * (n * m) = n + m' + 2 * (n * m')) : + m = m' := by + have e1 : (2 * n + 1) * m = m + 2 * (n * m) := by ring + have e2 : (2 * n + 1) * m' = m' + 2 * (n * m') := by ring + exact Nat.eq_of_mul_eq_mul_left (by omega : 0 < 2 * n + 1) (by omega) + +/-- `-1 = 1` in `ZMod 2`. -/ +private theorem neg_one_zmod2 : (-1 : ZMod 2) = 1 := by decide + +/-- Mod 2, `term N n i` (for `i ≤ n`) is the sum of `T n m i` over the (at most one) `m` with +`i ≤ m` and `n + m + 2nm = N + 2i`. -/ +private theorem term_cast {N n i : ℕ} (hi : i ≤ n) : + ((term N n i : ℤ) : ZMod 2) = ∑ m ∈ Finset.range (N + 1), + if i ≤ m ∧ n + m + 2 * (n * m) = N + 2 * i then (T n m i : ZMod 2) else 0 := by + unfold term + split_ifs with h + · obtain ⟨h1, h2⟩ := h + have hNq : N = (2 * n - 1) * i + n + + (2 * n + 1) * ((N - ((2 * n - 1) * i + n)) / (2 * n + 1)) := by + have := Nat.div_add_mod (N - ((2 * n - 1) * i + n)) (2 * n + 1) + rw [h2] at this + omega + generalize (N - ((2 * n - 1) * i + n)) / (2 * n + 1) = q at hNq ⊢ + have hk := key_arith (j := q) hi + have hq' : q ≤ (2 * n + 1) * q := Nat.le_mul_of_pos_left q (by omega) + rw [Finset.sum_eq_single (i + q)] + · rw [if_pos ⟨by omega, by omega⟩] + push_cast + rw [neg_one_zmod2, one_pow, one_mul, binom_eq_choose, binom_eq_choose, ← Nat.cast_mul, + T_eq hi] + · intro m _ hne + rw [if_neg] + rintro ⟨_, heq⟩ + exact hne (inj_aux (n := n) (by omega)).symm + · intro hmem + exfalso + apply hmem + rw [Finset.mem_range] + omega + · symm + apply Finset.sum_eq_zero + intro m _ + rw [if_neg] + rintro ⟨him, heq⟩ + apply h + obtain ⟨j, rfl⟩ : ∃ j, m = i + j := ⟨m - i, by omega⟩ + have := key_arith (j := j) hi + refine ⟨by omega, ?_⟩ + have : N - ((2 * n - 1) * i + n) = (2 * n + 1) * j := by omega + rw [this, Nat.mul_mod_right] + +/-- The finite set of triples `(n, i, m)` with `i ≤ n`, `i ≤ m` and `n + m + 2nm = N + 2i` +(all coordinates are automatically `≤ N`). -/ +private def S (N : ℕ) : Finset (ℕ × ℕ × ℕ) := + (Finset.range (N + 1) ×ˢ Finset.range (N + 1) ×ˢ Finset.range (N + 1)).filter + fun x => x.2.1 ≤ x.1 ∧ x.2.1 ≤ x.2.2 ∧ x.1 + x.2.2 + 2 * (x.1 * x.2.2) = N + 2 * x.2.1 + +/-- The contribution of the `n`-th summand, mod 2. -/ +private theorem summand_cast {N n : ℕ} (hn : n ≤ N) : + ∑ i ∈ Finset.range (n + 1), ((term N n i : ℤ) : ZMod 2) = + ∑ i ∈ Finset.range (N + 1), ∑ m ∈ Finset.range (N + 1), + if i ≤ n ∧ i ≤ m ∧ n + m + 2 * (n * m) = N + 2 * i then (T n m i : ZMod 2) else 0 := by + rw [← Finset.sum_subset (s₁ := Finset.range (n + 1)) (s₂ := Finset.range (N + 1)) + (Finset.range_subset_range.2 (by omega))] + · refine Finset.sum_congr rfl fun i hi => ?_ + have hi' : i ≤ n := by rw [Finset.mem_range] at hi; omega + rw [term_cast hi'] + refine Finset.sum_congr rfl fun m _ => ?_ + simp only [hi', true_and] + · intro i _ hi + apply Finset.sum_eq_zero + intro m _ + rw [if_neg] + rintro ⟨h, -⟩ + rw [Finset.mem_range] at hi + omega + +/-- `coeffA N` mod 2 is the sum of `T` over `S N`. -/ +private theorem coeffA_cast (N : ℕ) : + ((coeffA N : ℤ) : ZMod 2) = ∑ x ∈ S N, (T x.1 x.2.2 x.2.1 : ZMod 2) := by + rw [coeffA_eq, Int.cast_sum, S, Finset.sum_filter, Finset.sum_product] + refine Finset.sum_congr rfl fun n hn => ?_ + rw [Int.cast_sum, Finset.sum_product, summand_cast (by rw [Finset.mem_range] at hn; omega)] + +/-- The off-diagonal triples cancel mod 2 (involution `n ↔ m`). -/ +private theorem sum_S_eq_diag (N : ℕ) : + ∑ x ∈ S N, (T x.1 x.2.2 x.2.1 : ZMod 2) = + ∑ x ∈ (S N).filter (fun x => x.1 = x.2.2), (T x.1 x.2.2 x.2.1 : ZMod 2) := by + rw [← Finset.sum_filter_add_sum_filter_not (S N) (fun x => x.1 = x.2.2), add_eq_left] + refine Finset.sum_involution (fun x _ => (x.2.2, x.2.1, x.1)) ?_ ?_ ?_ ?_ + · intro x hx + simp only [S, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at hx + rw [T_symm hx.1.2.1 hx.1.2.2.1, CharTwo.add_self_eq_zero] + · rintro ⟨n, i, m⟩ hx _ h + simp only [S, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at hx + apply hx.2 + simp only [Prod.mk.injEq] at h + omega + · rintro ⟨n, i, m⟩ hx + simp only [S, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at hx ⊢ + obtain ⟨⟨⟨h1, h2, h3⟩, h4, h5, h6⟩, h7⟩ := hx + refine ⟨⟨⟨h3, h2, h1⟩, h5, h4, ?_⟩, fun h => h7 h.symm⟩ + have := Nat.mul_comm m n + omega + · intro x _ + rfl + +/-- On the diagonal, `T n n i` is even unless `i = n`. -/ +private theorem T_diag_even {n i : ℕ} (h : i < n) : ((T n n i : ℕ) : ZMod 2) = 0 := by + rw [ZMod.natCast_eq_zero_iff] + unfold T + apply Dvd.dvd.mul_left + have : n + n - 2 * i = 2 * (n - i) := by omega + rw [this, ← Nat.centralBinom_eq_two_mul_choose] + exact Nat.two_dvd_centralBinom_of_one_le (by omega) + +/-- On a diagonal triple `(n, i, n)` of `S N`, `T n n i` is `0` mod 2 unless `i = n`, in which case +`N = 2 n²`. -/ +private theorem diag_cases {N n i : ℕ} (h6 : n + n + 2 * (n * n) = N + 2 * i) (h4 : i ≤ n) : + ((T n n i : ℕ) : ZMod 2) = 0 ∨ (i = n ∧ N = 2 * (n * n)) := by + rcases Nat.lt_or_ge i n with h | h + · exact Or.inl (T_diag_even h) + · exact Or.inr ⟨by omega, by omega⟩ + +/-- `a K` mod 2 is `1` if `K` is a square and `0` otherwise. -/ +private theorem a_cast (K : ℕ) : ((a K : ℤ) : ZMod 2) = if IsSquare K then 1 else 0 := by + rw [a, coeffA_cast, sum_S_eq_diag] + split_ifs with hK + · obtain ⟨k, rfl⟩ := hK + rw [Finset.sum_eq_single (k, k, k)] + · simp [T] + · rintro ⟨n, i, m⟩ hx hne + simp only [S, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at hx + obtain ⟨⟨⟨-, -, -⟩, h4, -, h6⟩, hnm⟩ := hx + dsimp only + rw [← hnm] at h6 ⊢ + rcases diag_cases h6 h4 with h | ⟨hin, hN⟩ + · exact h + · exfalso + apply hne + have hsq : n * n = k * k := by omega + have hnk : n = k := Nat.mul_self_inj.1 hsq + rw [← hnm, hin, hnk] + · intro hmem + exfalso + apply hmem + simp only [S, Finset.mem_filter, Finset.mem_product, Finset.mem_range] + have : k ≤ k * k := Nat.le_mul_self k + refine ⟨⟨⟨by omega, by omega, by omega⟩, le_rfl, le_rfl, by omega⟩, trivial⟩ + · apply Finset.sum_eq_zero + rintro ⟨n, i, m⟩ hx + simp only [S, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at hx + obtain ⟨⟨⟨-, -, -⟩, h4, -, h6⟩, hnm⟩ := hx + dsimp only + rw [← hnm] at h6 ⊢ + rcases diag_cases h6 h4 with h | ⟨-, hN⟩ + · exact h + · exact absurd ⟨n, by omega⟩ hK + +/-- Hanna's conjecture A326602: `a n` is odd iff `n` is a square. -/ +theorem result : statement := by + intro n + rw [← ZMod.intCast_eq_one_iff_odd, a_cast] + split_ifs with h + · simp [h] + · simp [h] + +end Math0.Frontier.A326602 + +#math0_settles Math0.Frontier.A326602.result Math0.Statements.A326602.statement diff --git a/lean/Math0/Frontier/OEIS/A328202.lean b/lean/Math0/Frontier/OEIS/A328202.lean new file mode 100644 index 0000000..955e382 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A328202.lean @@ -0,0 +1,246 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A328202 +import Math0.Audit + +/-! +# The gcd of the interior binomial coefficients is `Λ-exp(n) · Λ-exp(n - 1)` + +We prove Jon Maiga's conjecture (A328202): for `n ≥ 4`, +`gcd {C(n, k) : 2 ≤ k ≤ n - 2} = L(n) · L(n - 1)`, where `L(m) = p` if `m = p ^ t` is a prime +power (`t ≥ 1`) and `L(m) = 1` otherwise (A014963). + +**`L(n) · L(n-1)` divides the gcd.** If `n = p ^ t` then `p ∣ C(n, k)` for `0 < k < n`. If +`n - 1 = p ^ t` then `C(n, k) = C(n-1, k-1) + C(n-1, k)` and both terms are divisible by `p` for +`2 ≤ k ≤ n - 2`. Since `L(m) ∣ m` and `n`, `n - 1` are coprime, the product divides each +`C(n, k)`. + +**The gcd `g` divides `L(n) · L(n-1)`.** Let `p ^ e ∣ g` with `e ≥ 1`. As `g ∣ C(n, 2)` and +`2 · C(n, 2) = n (n - 1)`, `p` divides `n` or `n - 1`. +* `n = p ^ t · m`, `p ∤ m`, `t ≥ 1`. If `m ≥ 2`, Lucas gives `C(p^t m, p^t) ≡ m (mod p)`, so + `p ∤ g`. If `m = 1`, Kummer for prime powers (`v_p C(p^t, k) = t - v_p k`) gives + `p² ∤ C(p^t, k₀)` with `k₀ = p^(t-1)` (or `k₀ = 2` when `t = 1`), so `e = 1` and `p = L(n)`. +* `n - 1 = p ^ t · m`, `p ∤ m`, `t ≥ 1`. Use `(N+1) C(N, j) = C(N+1, j+1) (j+1)` with + `N = n - 1`. If `m ≥ 2`, take `j = p^t`: `p ∤ (N+1) C(N, p^t)`, so `p ∤ C(n, p^t + 1)`. + If `m = 1`, take `j = p^(t-1)`: `p² ∤ (p^t+1) C(p^t, p^(t-1))`, so `p² ∤ C(n, p^(t-1)+1)`, + hence `e = 1` and `p = L(n - 1)`. +-/ + +namespace Math0.Frontier.A328202 +open Math0.Statements.A328202 + +/-- `L(m) ∣ m`. -/ +private lemma expMangoldt_dvd_self (m : ℕ) : expMangoldt m ∣ m := by + unfold expMangoldt + split_ifs + · exact Nat.minFac_dvd m + · exact one_dvd m + +/-- `L(p ^ t) = p` for `p` prime and `t ≥ 1`. -/ +private lemma expMangoldt_prime_pow {p t : ℕ} (hp : p.Prime) (ht : t ≠ 0) : + expMangoldt (p ^ t) = p := by + unfold expMangoldt + rw [if_pos ((isPrimePow_pow_iff ht).mpr hp.isPrimePow), hp.pow_minFac ht] + +/-- `L(n) ∣ C(n, k)` for `0 < k < n`. -/ +private lemma expMangoldt_dvd_choose (n k : ℕ) (hk0 : k ≠ 0) (hkn : k ≠ n) : + expMangoldt n ∣ n.choose k := by + unfold expMangoldt + split_ifs with h + · obtain ⟨p, t, hp, ht, rfl⟩ := (isPrimePow_nat_iff _).mp h + rw [hp.pow_minFac ht.ne'] + exact hp.dvd_choose_pow hk0 hkn + · exact one_dvd _ + +/-- `L(n - 1) ∣ C(n, k)` for `2 ≤ k ≤ n - 2`. -/ +private lemma expMangoldt_pred_dvd_choose (n k : ℕ) (hk : 2 ≤ k) (hkn : k + 2 ≤ n) : + expMangoldt (n - 1) ∣ n.choose k := by + obtain ⟨N, rfl⟩ : ∃ N, n = N + 1 := ⟨n - 1, by omega⟩ + obtain ⟨j, rfl⟩ : ∃ j, k = j + 1 := ⟨k - 1, by omega⟩ + rw [Nat.choose_succ_succ, Nat.add_sub_cancel] + exact dvd_add (expMangoldt_dvd_choose N j (by omega) (by omega)) + (expMangoldt_dvd_choose N (j + 1) (by omega) (by omega)) + +/-- Kummer for prime powers: if `v_p(k) ≥ t - 1` then `p² ∤ C(p^t, k)`. -/ +private lemma not_sq_dvd_choose {p t k : ℕ} (hp : p.Prime) (hk0 : k ≠ 0) (hk : k ≤ p ^ t) + (hf : t - 1 ≤ k.factorization p) : ¬ p ^ 2 ∣ (p ^ t).choose k := by + intro h + have hc : (p ^ t).choose k ≠ 0 := (Nat.choose_pos hk).ne' + rw [hp.pow_dvd_iff_le_factorization hc, Nat.factorization_choose_prime_pow hp hk hk0] at h + omega + +/-- Lucas: `C(p^t m, p^t) ≡ m (mod p)`. -/ +private lemma choose_pow_mul_modEq {p m : ℕ} (hp : p.Prime) : + ∀ t : ℕ, (p ^ t * m).choose (p ^ t) ≡ m [MOD p] + | 0 => by simp [Nat.ModEq] + | t + 1 => by + have : Fact p.Prime := ⟨hp⟩ + have h := @Choose.choose_modEq_choose_mod_mul_choose_div_nat (p ^ (t + 1) * m) (p ^ (t + 1)) + p _ + have hp0 : 0 < p := hp.pos + have e1 : p ^ (t + 1) * m % p = 0 := by + exact Nat.mod_eq_zero_of_dvd (Dvd.dvd.mul_right (dvd_pow_self p (by omega)) _) + have e2 : p ^ (t + 1) % p = 0 := by + exact Nat.mod_eq_zero_of_dvd (dvd_pow_self p (by omega)) + have e3 : p ^ (t + 1) * m / p = p ^ t * m := by + rw [pow_succ, mul_comm (p ^ t) p, mul_assoc, Nat.mul_div_cancel_left _ hp0] + have e4 : p ^ (t + 1) / p = p ^ t := by + rw [pow_succ, Nat.mul_div_cancel _ hp0] + rw [e1, e2, e3, e4, Nat.choose_zero_right, one_mul] at h + exact h.trans (choose_pow_mul_modEq hp t) + +/-- `p ∤ C(p^t m, p^t)` when `p ∤ m`. -/ +private lemma not_dvd_choose_pow_mul {p m t : ℕ} (hp : p.Prime) (hm : ¬ p ∣ m) : + ¬ p ∣ (p ^ t * m).choose (p ^ t) := by + intro h + exact hm (((choose_pow_mul_modEq hp t).dvd_iff (dvd_refl p)).mp h) + +/-- The main theorem: Maiga's conjecture holds for every `n ≥ 4`. -/ +theorem result : statement := by + intro n hn + set L := expMangoldt n * expMangoldt (n - 1) with hL + have hcop : Nat.Coprime (expMangoldt n) (expMangoldt (n - 1)) := by + have h : Nat.Coprime n (n - 1) := + (Nat.coprime_self_sub_right (by omega : 1 ≤ n)).mpr (Nat.coprime_one_right n) + exact (h.coprime_dvd_left (expMangoldt_dvd_self n)).coprime_dvd_right + (expMangoldt_dvd_self (n - 1)) + have hg : ∀ k, 2 ≤ k → k + 2 ≤ n → a n ∣ n.choose k := fun k h1 h2 => + Finset.gcd_dvd (Finset.mem_Icc.mpr ⟨h1, by omega⟩) + apply Nat.dvd_antisymm + · -- the gcd divides `L` + refine (Nat.dvd_iff_prime_pow_dvd_dvd L (a n)).mpr ?_ + intro p e hp hpe + rcases Nat.eq_zero_or_pos e with rfl | he + · simp + have hpg : p ∣ a n := (dvd_pow_self p he.ne').trans hpe + have hp2 : 2 ≤ p := hp.two_le + -- `p ^ e ∣ p` as soon as `p² ∤ g` + have key : ¬ p ^ 2 ∣ a n → p ^ e ∣ p := by + intro h + have : e ≤ 1 := by + by_contra hc + exact h ((pow_dvd_pow p (by omega)).trans hpe) + exact (pow_dvd_pow p this).trans (by rw [pow_one]) + have hn2 : p ∣ n * (n - 1) := by + have h := Nat.add_one_mul_choose_eq (n - 1) 1 + rw [Nat.sub_add_cancel (by omega : 1 ≤ n), Nat.choose_one_right] at h + rw [h] + exact Dvd.dvd.mul_right (hpg.trans (hg 2 le_rfl (by omega))) _ + rcases (Nat.Prime.dvd_mul hp).mp hn2 with hdn | hdn + · -- `p ∣ n` + obtain ⟨t, m, hm, hnm⟩ := Nat.exists_eq_pow_mul_and_not_dvd (by omega : n ≠ 0) p + (by omega) + have ht : t ≠ 0 := by + rintro rfl + rw [pow_zero, one_mul] at hnm + exact hm (hnm ▸ hdn) + have hpt : p ≤ p ^ t := Nat.le_self_pow ht p + have hm0 : m ≠ 0 := by rintro rfl; simp at hnm; omega + by_cases hm1 : m = 1 + · subst hm1 + rw [mul_one] at hnm + have hLp : p ∣ L := by + rw [hL, hnm, expMangoldt_prime_pow hp ht] + exact dvd_mul_right _ _ + refine (key ?_).trans hLp + intro h2 + by_cases ht1 : t = 1 + · subst ht1 + rw [pow_one] at hnm + refine not_sq_dvd_choose hp (by omega : (2 : ℕ) ≠ 0) (by rw [pow_one]; omega) + (by omega) ?_ + rw [pow_one] + have := h2.trans (hg 2 le_rfl (by omega)) + rwa [hnm] at this + · have hk : p ^ (t - 1) * p = p ^ t := by + rw [← pow_succ, Nat.sub_add_cancel (by omega)] + have hk2 : 2 ≤ p ^ (t - 1) := by + calc 2 ≤ p := hp2 + _ ≤ p ^ (t - 1) := Nat.le_self_pow (by omega) p + refine not_sq_dvd_choose hp (t := t) (k := p ^ (t - 1)) (by omega) + (Nat.pow_le_pow_right hp.pos (by omega)) ?_ ?_ + · rw [hp.factorization_pow, Finsupp.single_eq_same] + · rw [← hnm] + refine h2.trans (hg _ hk2 ?_) + rw [hnm, ← hk] + nlinarith + · exfalso + have hm2 : 2 ≤ m := by omega + apply not_dvd_choose_pow_mul (t := t) hp hm + rw [← hnm] + refine hpg.trans (hg _ (by omega) ?_) + rw [hnm] + nlinarith + · -- `p ∣ n - 1` + obtain ⟨t, m, hm, hnm⟩ := Nat.exists_eq_pow_mul_and_not_dvd (by omega : n - 1 ≠ 0) p + (by omega) + have ht : t ≠ 0 := by + rintro rfl + rw [pow_zero, one_mul] at hnm + exact hm (hnm ▸ hdn) + have hpt : p ≤ p ^ t := Nat.le_self_pow ht p + have hpdt : p ∣ p ^ t := dvd_pow_self p ht + have hm0 : m ≠ 0 := by rintro rfl; simp at hnm; omega + have hn1 : n = (n - 1) + 1 := by omega + by_cases hm1 : m = 1 + · subst hm1 + rw [mul_one] at hnm + have hLp : p ∣ L := by + rw [hL, hnm, expMangoldt_prime_pow hp ht] + exact dvd_mul_left _ _ + refine (key ?_).trans hLp + intro h2 + have hk : p ^ (t - 1) * p = p ^ t := by + rw [← pow_succ, Nat.sub_add_cancel (by omega)] + have hk1 : 1 ≤ p ^ (t - 1) := Nat.one_le_pow _ _ hp.pos + have hrange : p ^ (t - 1) + 1 + 2 ≤ n := by + rcases Nat.lt_or_ge t 2 with ht2 | ht2 + · have : t = 1 := by omega + subst this + simp only [Nat.sub_self, pow_zero, pow_one] at hnm ⊢ + omega + · have : 2 ≤ p ^ (t - 1) := by + calc 2 ≤ p := hp2 + _ ≤ p ^ (t - 1) := Nat.le_self_pow (by omega) p + have : p ^ (t - 1) * 2 ≤ p ^ t := by rw [← hk]; exact Nat.mul_le_mul_left _ hp2 + omega + have hid := Nat.add_one_mul_choose_eq (p ^ t) (p ^ (t - 1)) + have hc : p ^ 2 ∣ (p ^ t + 1) * (p ^ t).choose (p ^ (t - 1)) := by + rw [hid] + refine Dvd.dvd.mul_right ?_ _ + have := h2.trans (hg _ (by omega) hrange) + rwa [hn1, hnm] at this + have hcp : Nat.Coprime (p ^ 2) (p ^ t + 1) := by + refine Nat.Coprime.pow_left 2 ((Nat.Prime.coprime_iff_not_dvd hp).mpr ?_) + intro hd + have := (Nat.dvd_add_right hpdt).mp hd + exact hp.one_lt.ne' (Nat.dvd_one.mp this) + refine not_sq_dvd_choose hp (t := t) (k := p ^ (t - 1)) (by omega) + (Nat.pow_le_pow_right hp.pos (by omega)) ?_ (hcp.dvd_of_dvd_mul_left hc) + rw [hp.factorization_pow, Finsupp.single_eq_same] + · exfalso + have hm2 : 2 ≤ m := by omega + have hrange : p ^ t + 1 + 2 ≤ n := by + rw [hn1, hnm] + nlinarith + have hid := Nat.add_one_mul_choose_eq (p ^ t * m) (p ^ t) + have hc : p ∣ (p ^ t * m + 1) * (p ^ t * m).choose (p ^ t) := by + rw [hid] + refine Dvd.dvd.mul_right ?_ _ + have := hpg.trans (hg _ (by omega) hrange) + rwa [hn1, hnm] at this + rcases (Nat.Prime.dvd_mul hp).mp hc with hd | hd + · have := (Nat.dvd_add_right (Dvd.dvd.mul_right hpdt m)).mp hd + exact hp.one_lt.ne' (Nat.dvd_one.mp this) + · exact not_dvd_choose_pow_mul hp hm hd + · -- `L` divides the gcd + refine Finset.dvd_gcd ?_ + intro k hk + rw [Finset.mem_Icc] at hk + exact hcop.mul_dvd_of_dvd_of_dvd (expMangoldt_dvd_choose n k (by omega) (by omega)) + (expMangoldt_pred_dvd_choose n k hk.1 (by omega)) + +end Math0.Frontier.A328202 + +#math0_settles Math0.Frontier.A328202.result Math0.Statements.A328202.statement diff --git a/lean/Math0/Frontier/OEIS/A332010.lean b/lean/Math0/Frontier/OEIS/A332010.lean new file mode 100644 index 0000000..682ad8b --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A332010.lean @@ -0,0 +1,438 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A332010 +import Math0.Audit + +/-! +# A332010: the one-descent derangements and their average first letter + +We prove Kagey's conjecture `T(n, 1) = 2^(n-2)` for every `n ≥ 2`: the average first letter of +the derangements of `{1, …, n}` with exactly one descent has reduced denominator `2^(n-2)`. + +**Structure.** Write `n = m + 2`. A word with distinct letters and exactly one descent is the +concatenation `P ++ Q` of two increasing runs (`split_of_desB`). For a permutation of +`{1, …, n}`, an increasing run `P` at positions `1, 2, …` has `P[i] ≥ i + 1`, with a fixed point +iff its first letter is `1`; an increasing run `Q` ending at position `n` has a fixed point iff it +contains `n` (`lower_of_derB`, `upper_of_derB`). So for a derangement, `1` is in the second run +and `n` in the first: the word is `s ++ [n] ++ [1] ++ (the rest of {2, …, n-1}, increasing)` +where `s` is an increasing list from `{2, …, n-1}`, i.e. a sublist of `[2, …, n-1]`. +Conversely each such word is a one-descent derangement (`word_mem_ders`), and distinct `s` give +distinct words. Hence the one-descent derangements are a permutation of the `2^m` words +`word m s`, `s` a sublist of `[2, …, m+1]` (`ders_perm_words`). + +**Counting.** The first letter of `word m s` is the head of `s`, or `m + 2` when `s = []`. +Summing over the sublists of `[a, …, a+k-1]` with default `a + k` gives `(a+1)·2^k - 1` +(`sum_heads`, by induction using `sublists'_cons`), so the sum of first letters is +`N = 3·2^m - 1`. The average is `N / 2^m`, and `N` is coprime to `2^m` (it is odd when `m ≥ 1`), +so its reduced denominator is `2^m = 2^(n-2)`. +-/ + +namespace Math0.Frontier.A332010 +open Math0.Statements.A332010 + +/-! ### The derangement test on pieces -/ + +/-- `derB` of a concatenation. -/ +private theorem derB_append (l₁ l₂ : List ℕ) (i : ℕ) : + derB (l₁ ++ l₂) i = (derB l₁ i && derB l₂ (i + l₁.length)) := by + induction l₁ generalizing i with + | nil => simp [derB] + | cons x xs ih => + simp only [List.cons_append, derB, ih, List.length_cons, Bool.and_assoc] + rw [show i + 1 + xs.length = i + (xs.length + 1) by omega] + +/-- An increasing list whose letters all exceed `i` passes `derB _ i`. -/ +private theorem derB_of_lower : ∀ (l : List ℕ) (i : ℕ), l.Pairwise (· < ·) → + (∀ x ∈ l, i < x) → derB l i = true + | [], _, _, _ => rfl + | x :: xs, i, hp, hb => by + rw [List.pairwise_cons] at hp + simp only [derB, Bool.and_eq_true, bne_iff_ne, ne_eq] + refine ⟨by have := hb x (by simp); omega, derB_of_lower xs (i + 1) hp.2 fun y hy => ?_⟩ + have h1 := hp.1 y hy + have h2 := hb x (by simp) + omega + +/-- In an increasing list `x :: xs` bounded by `B`, the head satisfies `x + |xs| < B`. -/ +private theorem head_add_length_lt : ∀ (x : ℕ) (xs : List ℕ) (B : ℕ), + (x :: xs).Pairwise (· < ·) → (∀ y ∈ x :: xs, y < B) → x + xs.length < B + | x, [], B, _, hb => by simpa using hb x (by simp) + | x, z :: zs, B, hp, hb => by + have h1 := head_add_length_lt z zs B (List.pairwise_cons.mp hp).2 + (fun y hy => hb y (List.mem_cons_of_mem _ hy)) + have h2 := (List.pairwise_cons.mp hp).1 z (by simp) + simp only [List.length_cons] + omega + +/-- An increasing list placed at positions `i, i+1, …` whose letters all lie below its last +position passes `derB _ i`. -/ +private theorem derB_of_upper : ∀ (l : List ℕ) (i : ℕ), l.Pairwise (· < ·) → + (∀ x ∈ l, x + 1 < i + l.length) → derB l i = true + | [], _, _, _ => rfl + | x :: xs, i, hp, hb => by + have h1 := head_add_length_lt x xs (i + xs.length) hp + (fun y hy => by have := hb y hy; simp only [List.length_cons] at this; omega) + rw [List.pairwise_cons] at hp + simp only [derB, Bool.and_eq_true, bne_iff_ne, ne_eq] + refine ⟨by omega, derB_of_upper xs (i + 1) hp.2 fun y hy => ?_⟩ + have := hb y (List.mem_cons_of_mem _ hy) + simp only [List.length_cons] at this + omega + +/-- Converse direction at the start: an increasing list with letters `≥ i` passing `derB _ i` +has all letters `> i`. -/ +private theorem lower_of_derB : ∀ (l : List ℕ) (i : ℕ), l.Pairwise (· < ·) → + (∀ x ∈ l, i ≤ x) → derB l i = true → ∀ x ∈ l, i < x + | [], _, _, _, _ => by simp + | x :: xs, i, hp, hb, hd => by + simp only [derB, Bool.and_eq_true, bne_iff_ne, ne_eq] at hd + rw [List.pairwise_cons] at hp + have hx : i < x := by have := hb x (by simp); omega + have ih := lower_of_derB xs (i + 1) hp.2 (fun y hy => by have := hp.1 y hy; omega) hd.2 + intro y hy + rcases List.mem_cons.mp hy with rfl | hy + · exact hx + · have := ih y hy; omega + +/-- Converse direction at the end: an increasing list at positions `i, i+1, …` with letters +below `i + |l|` passing `derB _ i` has all letters below its last position. -/ +private theorem upper_of_derB : ∀ (l : List ℕ) (i : ℕ), l.Pairwise (· < ·) → + (∀ x ∈ l, x < i + l.length) → derB l i = true → ∀ x ∈ l, x + 1 < i + l.length + | [], _, _, _, _ => by simp + | x :: xs, i, hp, hb, hd => by + simp only [derB, Bool.and_eq_true, bne_iff_ne, ne_eq] at hd + rw [List.pairwise_cons] at hp + have ih := upper_of_derB xs (i + 1) hp.2 (fun y hy => by + have := hb y (List.mem_cons_of_mem _ hy); simp only [List.length_cons] at this; omega) hd.2 + intro y hy + simp only [List.length_cons] + rcases List.mem_cons.mp hy with rfl | hy + · cases xs with + | nil => have := hb y (by simp); simp at this; omega + | cons z zs => + have h1 := hp.1 z (by simp) + have h2 := ih z (by simp) + simp only [List.length_cons] at h2 ⊢ + omega + · have := ih y hy; omega + +/-! ### The descent count on pieces -/ + +/-- One unfolding step of `desB`. -/ +private theorem desB_cons_cons (x y : ℕ) (l : List ℕ) : + desB (x :: y :: l) = (if y < x then 1 else 0) + desB (y :: l) := by + rw [desB] + +/-- An increasing word has no descent. -/ +private theorem desB_of_pairwise : ∀ l : List ℕ, l.Pairwise (· < ·) → desB l = 0 + | [], _ => rfl + | [_], _ => rfl + | x :: y :: l, hp => by + rw [desB_cons_cons, desB_of_pairwise (y :: l) (List.pairwise_cons.mp hp).2] + have := (List.pairwise_cons.mp hp).1 y (by simp) + rw [if_neg (by omega)] + +/-- A word with distinct letters and no descent is increasing. -/ +private theorem pairwise_of_desB : ∀ l : List ℕ, l.Nodup → desB l = 0 → l.Pairwise (· < ·) + | [], _, _ => List.Pairwise.nil + | [_], _, _ => List.pairwise_singleton _ _ + | x :: y :: l, hn, hd => by + rw [desB_cons_cons] at hd + have hyx : ¬ y < x := by intro h; rw [if_pos h] at hd; omega + rw [if_neg hyx, Nat.zero_add] at hd + have ih := pairwise_of_desB (y :: l) (List.nodup_cons.mp hn).2 hd + have hxy : x ≠ y := fun h => (List.nodup_cons.mp hn).1 (h ▸ List.mem_cons_self ..) + refine List.Pairwise.cons (fun z hz => ?_) ih + rcases List.mem_cons.mp hz with rfl | hz + · omega + · have := (List.pairwise_cons.mp ih).1 z hz; omega + +/-- Descents of `l ++ a :: b :: m`, split at the step `a, b`. -/ +private theorem desB_split : ∀ (l : List ℕ) (a b : ℕ) (m : List ℕ), + desB (l ++ a :: b :: m) = desB (l ++ [a]) + (if b < a then 1 else 0) + desB (b :: m) + | [], a, b, m => by simp [desB_cons_cons, desB] + | [x], a, b, m => by simp [desB_cons_cons, desB]; omega + | x :: y :: l, a, b, m => by + have ih := desB_split (y :: l) a b m + simp only [List.cons_append] at ih ⊢ + rw [desB_cons_cons, ih, desB_cons_cons] + omega + +/-- A word with distinct letters and exactly one descent is the concatenation of two increasing +runs. -/ +private theorem split_of_desB : ∀ l : List ℕ, l.Nodup → desB l = 1 → + ∃ u a b v, l = u ++ a :: b :: v ∧ (u ++ [a]).Pairwise (· < ·) ∧ (b :: v).Pairwise (· < ·) + | [], _, h => by simp [desB] at h + | [_], _, h => by simp [desB] at h + | x :: y :: l, hn, hd => by + rw [desB_cons_cons] at hd + by_cases hyx : y < x + · rw [if_pos hyx] at hd + exact ⟨[], x, y, l, rfl, by simp, + pairwise_of_desB (y :: l) (List.nodup_cons.mp hn).2 (by omega)⟩ + · rw [if_neg hyx] at hd + obtain ⟨u, a, b, v, he, hu, hv⟩ := + split_of_desB (y :: l) (List.nodup_cons.mp hn).2 (by omega) + have hxy : x ≠ y := fun h => (List.nodup_cons.mp hn).1 (h ▸ List.mem_cons_self ..) + refine ⟨x :: u, a, b, v, by rw [he]; rfl, ?_, hv⟩ + rw [List.cons_append, List.pairwise_cons] + refine ⟨fun z hz => ?_, hu⟩ + have hy : ∀ z ∈ u ++ [a], y ≤ z := by + cases u with + | nil => + simp only [List.nil_append, List.cons.injEq] at he + simp [he.1] + | cons c u' => + simp only [List.cons_append, List.cons.injEq] at he + obtain ⟨rfl, -⟩ := he + intro z hz + rw [List.cons_append] at hz + rcases List.mem_cons.mp hz with rfl | hz + · exact le_refl _ + · exact le_of_lt ((List.pairwise_cons.mp hu).1 z hz) + have := hy z hz + omega + +/-! ### The explicit list of one-descent derangements -/ + +/-- The word attached to an increasing list `s` of letters from `{2, …, m+1}`: the first run is +`s` followed by `m+2`, the second run is `1` followed by the remaining letters of +`{2, …, m+1}`. -/ +private def word (m : ℕ) (s : List ℕ) : List ℕ := + s ++ (m + 2) :: 1 :: (List.range' 2 m).filter (fun x => decide (x ∉ s)) + +/-- All the words `word m s`, for `s` running over the sublists of `[2, …, m+1]`. -/ +private def words (m : ℕ) : List (List ℕ) := (List.range' 2 m).sublists'.map (word m) + + +/-- Membership in `range' a k`. -/ +private theorem mem_range'_iff {x a k : ℕ} : x ∈ List.range' a k ↔ a ≤ x ∧ x < a + k := + List.mem_range'_1 + +/-- Every word `word m s` (with `s` a sublist of `[2, …, m+1]`) is a derangement of +`{1, …, m+2}` with exactly one descent. -/ +private theorem word_mem_ders {m : ℕ} {s : List ℕ} (hsub : s.Sublist (List.range' 2 m)) : + word m s ∈ ders (m + 2) 1 := by + have hs : s.Pairwise (· < ·) := List.Pairwise.sublist hsub List.pairwise_lt_range' + have hsn : s.Nodup := List.Nodup.sublist hsub List.nodup_range' + have hsm : ∀ x ∈ s, 2 ≤ x ∧ x < 2 + m := fun x hx => mem_range'_iff.mp (hsub.subset hx) + have hslen : s.length ≤ m := by simpa using hsub.length_le + set v := (List.range' 2 m).filter (fun x => decide (x ∉ s)) with hvdef + have hv : v.Pairwise (· < ·) := List.Pairwise.filter _ List.pairwise_lt_range' + have hvn : v.Nodup := List.Nodup.filter _ List.nodup_range' + have memv : ∀ x, x ∈ v ↔ (2 ≤ x ∧ x < 2 + m) ∧ x ∉ s := by + intro x; simp [hvdef, List.mem_filter] + have hw : word m s = s ++ (m + 2) :: 1 :: v := rfl + have hnod : (word m s).Nodup := by + rw [hw, List.nodup_append, List.nodup_cons, List.nodup_cons] + refine ⟨hsn, ⟨?_, ?_, hvn⟩, ?_⟩ + · simp only [List.mem_cons, not_or] + refine ⟨by omega, fun h => ?_⟩ + have := ((memv _).mp h).1; omega + · intro h; have := ((memv _).mp h).1; omega + · intro x hx y hy + have hx' := hsm x hx + simp only [List.mem_cons] at hy + rcases hy with rfl | rfl | hy + · omega + · omega + · rintro rfl; exact ((memv _).mp hy).2 hx + have hperm : (word m s).Perm (List.range' 1 (m + 2)) := by + rw [List.perm_ext_iff_of_nodup hnod List.nodup_range'] + intro x + rw [hw, mem_range'_iff] + simp only [List.mem_append, List.mem_cons, memv] + constructor + · rintro (h | rfl | rfl | ⟨h, -⟩) + · have := hsm x h; omega + · omega + · omega + · omega + · intro h + by_cases hxs : x ∈ s + · exact Or.inl hxs + · right + by_cases h1 : x = m + 2 + · exact Or.inl h1 + · right + by_cases h2 : x = 1 + · exact Or.inl h2 + · exact Or.inr ⟨by omega, hxs⟩ + have hlen : s.length + v.length = m := by + have := hperm.length_eq + rw [hw] at this + simp only [List.length_append, List.length_cons, List.length_range'] at this + omega + rw [mem_ders] + refine ⟨hperm, ?_, ?_⟩ + · have hder : derB (word m s) 1 = true := by + rw [hw, derB_append] + simp only [derB, Bool.and_eq_true, bne_iff_ne, ne_eq] + refine ⟨derB_of_lower s 1 hs (fun x hx => by have := hsm x hx; omega), by omega, by omega, + derB_of_upper v _ hv (fun x hx => ?_)⟩ + have := ((memv x).mp hx).1 + omega + rw [derB_one] at hder + exact of_decide_eq_true hder + · rw [← desB_eq, hw, desB_split, desB_of_pairwise (s ++ [m + 2]), desB_of_pairwise (1 :: v), + if_pos (by omega)] + · rw [List.pairwise_cons] + exact ⟨fun x hx => by have := ((memv x).mp hx).1; omega, hv⟩ + · rw [List.pairwise_append] + refine ⟨hs, List.pairwise_singleton _ _, fun x hx y hy => ?_⟩ + have := hsm x hx + simp only [List.mem_singleton] at hy + omega + +/-- Every derangement of `{1, …, m+2}` with exactly one descent is a word `word m s`. -/ +private theorem mem_words_of_mem_ders {m : ℕ} {w : List ℕ} (h : w ∈ ders (m + 2) 1) : + w ∈ words m := by + rw [mem_ders] at h + obtain ⟨hp, hd, hdes⟩ := h + have hn : w.Nodup := hp.nodup_iff.mpr List.nodup_range' + have hmem : ∀ x, x ∈ w ↔ 1 ≤ x ∧ x < 1 + (m + 2) := fun x => hp.mem_iff.trans mem_range'_iff + have hlen : w.length = m + 2 := hp.length_eq.trans List.length_range' + have hD : derB w 1 = true := by rw [derB_one]; simpa using hd + obtain ⟨u, a, b, v, rfl, hP, hQ⟩ := split_of_desB w hn (by rw [desB_eq]; exact hdes) + have hsplit : u ++ a :: b :: v = (u ++ [a]) ++ (b :: v) := by simp + rw [hsplit] at hD hmem hlen hn + rw [derB_append, Bool.and_eq_true] at hD + have hlo := lower_of_derB _ 1 hP (fun x hx => ((hmem x).mp (List.mem_append_left _ hx)).1) hD.1 + have hup := upper_of_derB _ _ hQ (fun x hx => by + have := ((hmem x).mp (List.mem_append_right _ hx)).2 + rw [List.length_append] at hlen; omega) hD.2 + rw [List.length_append] at hlen + replace hup : ∀ x ∈ b :: v, x + 1 < 1 + (m + 2) := fun x hx => by have := hup x hx; omega + -- `1` lies in the second run, so `b = 1` + have hb : b = 1 := by + have h1 : 1 ∈ (u ++ [a]) ++ (b :: v) := (hmem 1).mpr (by omega) + rcases List.mem_append.mp h1 with h1 | h1 + · have := hlo 1 h1; omega + · have hb1 := ((hmem b).mp (List.mem_append_right _ (List.mem_cons_self ..))).1 + rcases List.mem_cons.mp h1 with h1 | h1 + · exact h1.symm + · have := (List.pairwise_cons.mp hQ).1 1 h1; omega + -- `m + 2` lies in the first run, so `a = m + 2` + have hPa : ∀ x ∈ u, x < a := fun x hx => + (List.pairwise_append.mp hP).2.2 x hx a (List.mem_singleton_self _) + have ha : a = m + 2 := by + have h1 : m + 2 ∈ (u ++ [a]) ++ (b :: v) := (hmem _).mpr (by omega) + have ha2 := ((hmem a).mp (List.mem_append_left _ (by simp))).2 + rcases List.mem_append.mp h1 with h1 | h1 + · rcases List.mem_append.mp h1 with h1 | h1 + · have := hPa _ h1; omega + · simp only [List.mem_singleton] at h1; omega + · have := hup _ h1; omega + subst hb ha + have hun : u.Nodup := (List.nodup_append.mp (List.nodup_append.mp hn).1).1 + have hu : u.Pairwise (· < ·) := (List.pairwise_append.mp hP).1 + have hv : v.Pairwise (· < ·) := (List.pairwise_cons.mp hQ).2 + have hv1 : ∀ x ∈ v, 1 < x := (List.pairwise_cons.mp hQ).1 + have hdisj : ∀ x ∈ u, x ∉ v := by + intro x hx hxv + have := (List.nodup_append.mp hn).2.2 x (List.mem_append_left _ hx) x + (List.mem_cons_of_mem _ hxv) + exact this rfl + have husub : u ⊆ List.range' 2 m := by + intro x hx + rw [mem_range'_iff] + have h1 := hlo x (List.mem_append_left _ hx) + have h2 := hPa x hx + omega + have hsub : u.Sublist (List.range' 2 m) := + List.sublist_of_subperm_of_pairwise (List.subperm_of_subset hun husub) hu + List.pairwise_lt_range' + have hveq : v = (List.range' 2 m).filter (fun x => decide (x ∉ u)) := by + apply List.Pairwise.eq_of_mem_iff hv (List.Pairwise.filter _ List.pairwise_lt_range') + intro x + simp only [List.mem_filter, mem_range'_iff, decide_eq_true_eq] + constructor + · intro hx + have h1 := hv1 x hx + have h2 := hup x (List.mem_cons_of_mem _ hx) + exact ⟨⟨by omega, by omega⟩, fun hu' => hdisj x hu' hx⟩ + · rintro ⟨⟨h1, h2⟩, h3⟩ + have hx := (hmem x).mpr (by omega) + rcases List.mem_append.mp hx with hx | hx + · rcases List.mem_append.mp hx with hx | hx + · exact absurd hx h3 + · simp only [List.mem_singleton] at hx; omega + · rcases List.mem_cons.mp hx with hx | hx + · omega + · exact hx + rw [words, List.mem_map] + refine ⟨u, List.mem_sublists'.mpr hsub, ?_⟩ + rw [word, ← hveq] + +/-- The words `word m s` are pairwise distinct. -/ +private theorem words_nodup (m : ℕ) : (words m).Nodup := by + refine List.Nodup.map_on ?_ (List.nodup_sublists'.mpr List.nodup_range') + intro s hs t ht hst + have hs' := List.mem_sublists'.mp hs + have ht' := List.mem_sublists'.mp ht + have hns : m + 2 ∉ s := fun h => by have := mem_range'_iff.mp (hs'.subset h); omega + have hnz : m + 2 ∉ 1 :: (List.range' 2 m).filter (fun x => decide (x ∉ s)) := by + simp only [List.mem_cons, List.mem_filter, mem_range'_iff, not_or] + omega + exact ((List.append_cons_inj_of_notMem hns hnz).mp hst).1 + +/-- The one-descent derangements of `{1, …, m+2}` are, up to order, the words `word m s`. -/ +private theorem ders_perm_words (m : ℕ) : (ders (m + 2) 1).Perm (words m) := by + rw [List.perm_ext_iff_of_nodup (nodup_ders _ _) (words_nodup m)] + intro w + constructor + · exact mem_words_of_mem_ders + · intro h + obtain ⟨s, hs, rfl⟩ := List.mem_map.mp h + exact word_mem_ders (List.mem_sublists'.mp hs) + +/-- The sum, over the sublists `s` of `[a, …, a+k-1]`, of the first letter of `s` (or `a + k` +for the empty sublist) is `(a + 1) 2^k - 1`. -/ +private theorem sum_heads : ∀ k a : ℕ, + ((List.range' a k).sublists'.map fun s => s.headD (a + k)).sum + 1 = (a + 1) * 2 ^ k + | 0, a => by simp + | k + 1, a => by + have ih := sum_heads k (a + 1) + rw [show a + 1 + k = a + (k + 1) by omega] at ih + rw [List.range'_succ, List.sublists'_cons, List.map_append, List.sum_append, List.map_map] + have h2 : ((List.range' (a + 1) k).sublists'.map + ((fun s => s.headD (a + (k + 1))) ∘ List.cons a)).sum = a * 2 ^ k := by + simp [Function.comp_def, List.length_sublists', Nat.mul_comm] + rw [h2, pow_succ] + nlinarith + +/-- Kagey's conjecture: `T(n, 1) = 2^(n-2)` for every `n ≥ 2`. -/ +theorem result : statement := by + intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 2 := ⟨n - 2, by omega⟩ + have hlen : (words m).length = 2 ^ m := by + simp [words, List.length_sublists'] + have hsum : ((words m).map fun w => w.headD 0).sum + 1 = 3 * 2 ^ m := by + have h := sum_heads m 2 + rw [show 2 + m = m + 2 by omega] at h + have : ((words m).map fun w => w.headD 0) = + (List.range' 2 m).sublists'.map fun s => s.headD (m + 2) := by + rw [words, List.map_map] + congr 1 + funext s + cases s <;> rfl + rw [this, h] + rw [T, avgFirst, avgFirstLetter_perm (ders_perm_words m), avgFirstLetter, hlen, + Nat.add_sub_cancel] + set N := ((words m).map fun w => w.headD 0).sum + have hcop : Nat.Coprime N (2 ^ m) := by + rcases m with _ | k + · simp + · apply Nat.Coprime.pow_right + rw [Nat.coprime_two_right] + rw [pow_succ] at hsum + exact ⟨3 * 2 ^ k - 1, by have := Nat.one_le_two_pow (n := k); omega⟩ + have key := Rat.den_div_eq_of_coprime (a := (N : ℤ)) (b := ((2 ^ m : ℕ) : ℤ)) + (by positivity) (by simpa using hcop) + rw [Int.cast_natCast, Int.cast_natCast] at key + exact_mod_cast key + +end Math0.Frontier.A332010 + +#math0_settles Math0.Frontier.A332010.result Math0.Statements.A332010.statement diff --git a/lean/Math0/Frontier/OEIS/A333650.lean b/lean/Math0/Frontier/OEIS/A333650.lean new file mode 100644 index 0000000..afc3d76 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A333650.lean @@ -0,0 +1,394 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A333650 +import Math0.Audit + +/-! +# Domino towers of height 2 and of height `n - 1`, `n - 2`, `n - 3` (A333650) + +We prove all four conjectures of A333650: `T(n,2) = A000071(n+2)` for `n > 1`, and +`T(n,n-1) = A339252(n-2)`, `T(n,n-2) = A339254(n-3)`, `T(n,n-3) = A339029(n-4)`. + +*Height 2.* A tower of height 2 with base `b` has a top layer that is any `n - b ≥ 1` element +subset of the `b + 1` positions `-1, 1, …, 2b - 1` supported by the base, so +`T(n,2) = ∑_{b=1}^{n-1} C(b+1, n-b)`, which is `F(n+2) - 1` by `F(N+1) = ∑_k C(N-k, k)`. + +*Near-diagonals.* `ways L h m` (the number of stacks of `h` layers with `m` bricks on a layer +`L`) is invariant under translating `L`. A tower with `n` bricks and height `n - e` has +"excess" `e` (bricks beyond one per layer). Writing `V(S, e, h) = ways S h (h + e)` and +normalising each layer by translation (`nrm`), the recursion of `ways` closes up on just +thirteen states `(S, e)` with `e ≤ 3` (the bases `{0}`, `{0,2}`, `{0,2,4}`, `{0,2,4,6}` and the +gapped pairs `{0,4}`, `{0,6}`). For each state `128 · V(S, e, h) = 2^h · p_{S,e}(h)` for an +explicit integer cubic `p_{S,e}` once `h ≥ 3`: the base case `h = 3` and the fact that the +recursion maps the tuple of polynomials `p` to `2 p(h + 1)` are finite checks done by +`decide +kernel`, and the general statement follows by induction on `h`. Summing over the base +size gives `128 · T(n, n-e) = 2^h · P_e(h)` with `h = n - e - 1` and +`P_1 = 160 + 96h`, `P_2 = 280 + 172h + 36h^2`, `P_3 = 588 + 367h + 84h^2 + 9h^3`, and the same +closed forms are obtained for A339252, A339254, A339029 from their linear recurrences. The +rows `n ≤ 10` come from `statement_check`. +-/ + +namespace Math0.Frontier.A333650 +open Math0.Statements.A333650 Finset + +/-- Translating a layer translates the positions it supports. -/ +private theorem supported_map (L : Finset ℤ) (c : ℤ) : + supported (L.map (addRightEmbedding c)) = (supported L).map (addRightEmbedding c) := by + ext x + simp only [mem_supported, mem_map, addRightEmbedding_apply] + constructor + · rintro (⟨a, ha, hax⟩ | ⟨a, ha, hax⟩) + · exact ⟨x - c, Or.inl (by rw [show x - c + 1 = a by omega]; exact ha), by ring⟩ + · exact ⟨x - c, Or.inr (by rw [show x - c - 1 = a by omega]; exact ha), by ring⟩ + · rintro ⟨y, hy | hy, rfl⟩ + · exact Or.inl ⟨y + 1, hy, by ring⟩ + · exact Or.inr ⟨y - 1, hy, by ring⟩ + +/-- `ways` is invariant under translating the bottom layer. -/ +private theorem ways_map (c : ℤ) (h : ℕ) : ∀ (L : Finset ℤ) (m : ℕ), + ways (L.map (addRightEmbedding c)) h m = ways L h m := by + induction h with + | zero => intro L m; rfl + | succ h ih => + intro L m + simp only [ways] + refine sum_congr rfl fun j _ => ?_ + rw [supported_map, powersetCard_map, sum_map] + refine sum_congr rfl fun L' _ => ?_ + exact ih L' _ + +/-- Normal form of a layer up to translation: shifted so that its leftmost brick is at `0`. -/ +private def nrm (L : Finset ℤ) : Finset ℤ := + if hL : L.Nonempty then L.map (addRightEmbedding (-L.min' hL)) else L + +/-- `ways` only depends on the normal form of the bottom layer. -/ +private theorem ways_nrm (L : Finset ℤ) (h m : ℕ) : ways (nrm L) h m = ways L h m := by + unfold nrm + split_ifs + · exact ways_map _ _ _ _ + · rfl + +/-- One step of the recursion of `ways`, written with the excess `e` and normalised layers. -/ +private theorem ways_succ (L : Finset ℤ) (h e : ℕ) : + ways L (h + 1) (h + 1 + e) = ∑ j ∈ range (e + 1), + ∑ L' ∈ (supported L).powersetCard (j + 1), ways (nrm L') h (h + (e - j)) := by + rw [ways, show h + 1 + e - h = e + 1 by omega] + have hI : Icc 1 (e + 1) = (range (e + 1)).map (addRightEmbedding 1) := by + ext x; simp only [mem_Icc, mem_map, mem_range, addRightEmbedding_apply] + constructor + · intro hx; exact ⟨x - 1, by omega, by omega⟩ + · rintro ⟨a, ha, rfl⟩; omega + rw [hI, sum_map] + refine sum_congr rfl fun j hj => sum_congr rfl fun L' _ => ?_ + rw [mem_range] at hj + rw [ways_nrm, addRightEmbedding_apply, show h + 1 + e - (j + 1) = h + (e - j) by omega] + +/-- Fewer bricks than layers: no stacks. -/ +private theorem ways_eq_zero (L : Finset ℤ) (h m : ℕ) (hm : m < h) : ways L h m = 0 := by + obtain ⟨h, rfl⟩ : ∃ h', h = h' + 1 := ⟨h - 1, by omega⟩ + rw [ways, show m - h = 0 by omega] + simp + +/-- The thirteen states `(layer shape, remaining excess)`, with the coefficients (scaled by +`128`) of the polynomial `p` such that the number of stacks is `2^h * p(h) / 128`. -/ +private def tab : List ((Finset ℤ × ℕ) × List ℤ) := + [(({0}, 0), [128, 0, 0, 0]), + (({0}, 1), [-32, 96, 0, 0]), + (({0, 2}, 0), [192, 0, 0, 0]), + (({0}, 2), [-104, 28, 36, 0]), + (({0, 2}, 1), [128, 144, 0, 0]), + (({0, 2, 4}, 0), [256, 0, 0, 0]), + (({0}, 3), [-228, 1, 30, 9]), + (({0, 2}, 2), [80, 174, 54, 0]), + (({0, 2, 4}, 1), [416, 192, 0, 0]), + (({0, 2, 4, 6}, 0), [320, 0, 0, 0]), + (({0, 4}, 0), [256, 0, 0, 0]), + (({0, 4}, 1), [416, 192, 0, 0]), + (({0, 6}, 0), [256, 0, 0, 0])] + +/-- The states of `tab`. -/ +private def states : List (Finset ℤ × ℕ) := tab.map Prod.fst + +/-- The (scaled) coefficient of `h^d` in the polynomial of a state, `0` if absent. -/ +private def coef (s : Finset ℤ × ℕ) (d : ℕ) : ℤ := ((tab.lookup s).getD []).getD d 0 + +/-- Evaluation of the cubic with coefficients `c 0, …, c 3`. -/ +private def pe (c : ℕ → ℤ) (x : ℤ) : ℤ := c 0 + c 1 * x + c 2 * x ^ 2 + c 3 * x ^ 3 + +/-- Coefficients of `2 · p(x + 1)` from those of `p`. -/ +private def nx (c : ℕ → ℤ) : ℕ → ℤ + | 0 => 2 * (c 0 + c 1 + c 2 + c 3) + | 1 => 2 * (c 1 + 2 * c 2 + 3 * c 3) + | 2 => 2 * (c 2 + 3 * c 3) + | _ => 2 * c 3 + +/-- The recursion from a state only reaches states (kernel check). -/ +private theorem closure_check : ∀ s ∈ states, ∀ j ∈ range (s.2 + 1), + ∀ L' ∈ (supported s.1).powersetCard (j + 1), (nrm L', s.2 - j) ∈ states := by + decide +kernel + +/-- The recursion maps the polynomial of each state to `2 p(h + 1)` (kernel check). -/ +private theorem coef_check : ∀ s ∈ states, ∀ d ∈ range 4, + ∑ j ∈ range (s.2 + 1), ∑ L' ∈ (supported s.1).powersetCard (j + 1), + coef (nrm L', s.2 - j) d = nx (coef s) d := by + decide +kernel + +/-- The closed forms at `h = 3` (kernel check). -/ +private theorem base_check : ∀ s ∈ states, + 128 * (ways s.1 3 (3 + s.2) : ℤ) = 2 ^ 3 * pe (coef s) 3 := by + decide +kernel + +/-- `pe` is linear in the coefficients. -/ +private theorem pe_sum {ι : Type*} (I : Finset ι) (c : ι → ℕ → ℤ) (x : ℤ) : + ∑ i ∈ I, pe (c i) x = pe (fun d => ∑ i ∈ I, c i d) x := by + simp only [pe, sum_add_distrib, sum_mul] + +/-- `pe` only depends on the first four coefficients. -/ +private theorem pe_congr {c c' : ℕ → ℤ} (x : ℤ) (h : ∀ d ∈ range 4, c d = c' d) : + pe c x = pe c' x := by + simp only [pe, h 0 (by simp), h 1 (by simp), h 2 (by simp), h 3 (by simp)] + +/-- `nx` realises `p ↦ 2 p(x + 1)`. -/ +private theorem pe_nx (c : ℕ → ℤ) (x : ℤ) : pe (nx c) x = 2 * pe c (x + 1) := by + simp only [pe, nx]; ring + +/-- Closed form of every state: `128 · ways S h (h + e) = 2^h · p_{S,e}(h)` for `h ≥ 3`. -/ +private theorem main (h : ℕ) (hh : 3 ≤ h) : ∀ s ∈ states, + 128 * (ways s.1 h (h + s.2) : ℤ) = 2 ^ h * pe (coef s) h := by + induction h, hh using Nat.le_induction with + | base => exact base_check + | succ h hh ih => + intro s hs + rw [ways_succ] + push_cast + rw [mul_sum] + have step : ∀ j ∈ range (s.2 + 1), 128 * ∑ L' ∈ (supported s.1).powersetCard (j + 1), + (ways (nrm L') h (h + (s.2 - j)) : ℤ) = + 2 ^ h * ∑ L' ∈ (supported s.1).powersetCard (j + 1), pe (coef (nrm L', s.2 - j)) h := by + intro j hj + rw [mul_sum, mul_sum] + refine sum_congr rfl fun L' hL' => ?_ + exact ih (nrm L', s.2 - j) (closure_check s hs j hj L' hL') + rw [sum_congr rfl step, ← mul_sum] + simp only [pe_sum] + rw [pe_congr _ (coef_check s hs), pe_nx] + ring + +/-- `T(n, n - e)` as a sum over the base size `b + 1 ≤ e + 1`. -/ +private theorem Tc_diag (n e : ℕ) (hn : e + 1 ≤ n) : + Tc n (n - e) = ∑ b ∈ range (e + 1), + ways (base (b + 1)) (n - e - 1) (n - e - 1 + (e - b)) := by + rw [Tc, if_neg (by omega)] + have hsub : (range (e + 1)).map (addRightEmbedding 1) ⊆ Icc 1 n := by + intro x hx + simp only [mem_map, mem_range, addRightEmbedding_apply] at hx + obtain ⟨a, ha, rfl⟩ := hx + simp only [mem_Icc]; omega + rw [← sum_subset hsub, sum_map] + · refine sum_congr rfl fun b hb => ?_ + rw [mem_range] at hb + simp only [addRightEmbedding_apply] + congr 1; omega + · intro b hb hb' + apply ways_eq_zero + simp only [mem_map, mem_range, addRightEmbedding_apply, not_exists, not_and] at hb' + simp only [mem_Icc] at hb + have : e + 2 ≤ b := by + by_contra hc + exact hb' (b - 1) (by omega) (by omega) + omega + +/-- Coefficients of the polynomial for the diagonal `T(n, n - e)`. -/ +private def R (e d : ℕ) : ℤ := ∑ b ∈ range (e + 1), coef (base (b + 1), e - b) d + +/-- The bases with their remaining excess are states (kernel check). -/ +private theorem base_mem : + ∀ e ∈ range 4, ∀ b ∈ range (e + 1), (base (b + 1), e - b) ∈ states := by + decide +kernel + +/-- `128 · T(n, n - e) = 2^h · P_e(h)` with `h = n - e - 1`, for `e ≤ 3` and `n ≥ e + 4`. -/ +private theorem diag (n e : ℕ) (he : e < 4) (hn : e + 4 ≤ n) : + 128 * (T n (n - e) : ℤ) = 2 ^ (n - e - 1) * pe (R e) (n - e - 1 : ℕ) := by + rw [T_eq_Tc, Tc_diag n e (by omega)] + push_cast + rw [mul_sum] + have key : ∀ b ∈ range (e + 1), + 128 * (ways (base (b + 1)) (n - e - 1) (n - e - 1 + (e - b)) : ℤ) = + 2 ^ (n - e - 1) * pe (coef (base (b + 1), e - b)) (n - e - 1 : ℕ) := by + intro b hb + exact main (n - e - 1) (by omega) _ (base_mem e (by simpa using he) b hb) + rw [sum_congr rfl key, ← mul_sum, pe_sum] + rfl + +/-- The coefficients of `P_1`. -/ +private theorem R1 : R 1 0 = 160 ∧ R 1 1 = 96 ∧ R 1 2 = 0 ∧ R 1 3 = 0 := by decide +kernel +/-- The coefficients of `P_2`. -/ +private theorem R2 : R 2 0 = 280 ∧ R 2 1 = 172 ∧ R 2 2 = 36 ∧ R 2 3 = 0 := by decide +kernel +/-- The coefficients of `P_3`. -/ +private theorem R3 : R 3 0 = 588 ∧ R 3 1 = 367 ∧ R 3 2 = 84 ∧ R 3 3 = 9 := by decide +kernel + +/-- `128 · A339252(h) = 2^h (160 + 96 h)` for `h ≥ 1`. -/ +private theorem A339252_closed (k : ℕ) : + 128 * A339252 (k + 1) = 2 ^ (k + 1) * (160 + 96 * ((k + 1 : ℕ) : ℤ)) ∧ + 128 * A339252 (k + 2) = 2 ^ (k + 2) * (160 + 96 * ((k + 2 : ℕ) : ℤ)) := by + induction k with + | zero => norm_num [A339252] + | succ k ih => + obtain ⟨h1, h2⟩ := ih + refine ⟨h2, ?_⟩ + rw [show k + 1 + 2 = k + 3 from rfl, A339252] + push_cast at h1 h2 ⊢ + linear_combination 4 * h2 - 4 * h1 + +/-- `128 · A339254(h) = 2^h (280 + 172 h + 36 h^2)` for `h ≥ 2`. -/ +private theorem A339254_closed (k : ℕ) : + 128 * A339254 (k + 2) = 2 ^ (k + 2) * (280 + 172 * ((k + 2 : ℕ) : ℤ) + + 36 * ((k + 2 : ℕ) : ℤ) ^ 2) ∧ + 128 * A339254 (k + 3) = 2 ^ (k + 3) * (280 + 172 * ((k + 3 : ℕ) : ℤ) + + 36 * ((k + 3 : ℕ) : ℤ) ^ 2) ∧ + 128 * A339254 (k + 4) = 2 ^ (k + 4) * (280 + 172 * ((k + 4 : ℕ) : ℤ) + + 36 * ((k + 4 : ℕ) : ℤ) ^ 2) := by + induction k with + | zero => norm_num [A339254] + | succ k ih => + obtain ⟨h1, h2, h3⟩ := ih + refine ⟨h2, h3, ?_⟩ + rw [show k + 1 + 4 = k + 5 from rfl, A339254] + push_cast at h1 h2 h3 ⊢ + linear_combination 6 * h3 - 12 * h2 + 8 * h1 + +/-- `128 · A339029(h) = 2^h (588 + 367 h + 84 h^2 + 9 h^3)` for `h ≥ 3`. -/ +private theorem A339029_closed (k : ℕ) : + 128 * A339029rec (k + 3) = 2 ^ (k + 3) * (588 + 367 * ((k + 3 : ℕ) : ℤ) + + 84 * ((k + 3 : ℕ) : ℤ) ^ 2 + 9 * ((k + 3 : ℕ) : ℤ) ^ 3) ∧ + 128 * A339029rec (k + 4) = 2 ^ (k + 4) * (588 + 367 * ((k + 4 : ℕ) : ℤ) + + 84 * ((k + 4 : ℕ) : ℤ) ^ 2 + 9 * ((k + 4 : ℕ) : ℤ) ^ 3) ∧ + 128 * A339029rec (k + 5) = 2 ^ (k + 5) * (588 + 367 * ((k + 5 : ℕ) : ℤ) + + 84 * ((k + 5 : ℕ) : ℤ) ^ 2 + 9 * ((k + 5 : ℕ) : ℤ) ^ 3) ∧ + 128 * A339029rec (k + 6) = 2 ^ (k + 6) * (588 + 367 * ((k + 6 : ℕ) : ℤ) + + 84 * ((k + 6 : ℕ) : ℤ) ^ 2 + 9 * ((k + 6 : ℕ) : ℤ) ^ 3) := by + induction k with + | zero => norm_num [A339029rec] + | succ k ih => + obtain ⟨h1, h2, h3, h4⟩ := ih + refine ⟨h2, h3, h4, ?_⟩ + rw [show k + 1 + 6 = k + 7 from rfl, A339029rec] + push_cast at h1 h2 h3 h4 ⊢ + linear_combination 8 * h4 - 24 * h3 + 32 * h2 - 16 * h1 + +/-- One layer of `m ≥ 1` bricks on `L`: any `m`-subset of the supported positions. -/ +private theorem ways_one (L : Finset ℤ) (m : ℕ) (hm : 1 ≤ m) : + ways L 1 m = (supported L).card.choose m := by + simp only [ways, Nat.sub_zero] + rw [sum_eq_single m] + · simp [card_powersetCard] + · intro j hj hjm + simp only [mem_Icc] at hj + refine sum_eq_zero fun L' _ => ?_ + rw [if_neg (by omega)] + · intro hm' + simp only [mem_Icc] at hm' + omega + +/-- A base of `b` bricks supports `b + 1` positions. -/ +private theorem card_supported_base (b : ℕ) (hb : 1 ≤ b) : + (supported (base b)).card = b + 1 := by + have : supported (base b) = (range (b + 1)).image fun i : ℕ => 2 * (i : ℤ) - 1 := by + ext x + simp only [mem_supported, base, mem_image, mem_range] + constructor + · rintro (⟨j, hj, hjx⟩ | ⟨j, hj, hjx⟩) + · exact ⟨j, by omega, by omega⟩ + · exact ⟨j + 1, by omega, by push_cast; omega⟩ + · rintro ⟨i, hi, rfl⟩ + by_cases hib : i < b + · exact Or.inl ⟨i, hib, by ring⟩ + · exact Or.inr ⟨i - 1, by omega, by + rw [Nat.cast_sub (by omega)]; push_cast; ring⟩ + rw [this, card_image_of_injective (f := fun i : ℕ => 2 * (i : ℤ) - 1) _ + (fun i j hij => by simp only at hij; omega), card_range] + +/-- Kagey: `T(n,2) = F(n+2) - 1` for `n > 1`. -/ +private theorem col2 : statement_col2 := by + intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 2 := ⟨n - 2, by omega⟩ + have hT : T (m + 2) 2 = ∑ b ∈ range (m + 1), (b + 2).choose (m + 1 - b) := by + rw [T_eq_Tc, Tc, if_neg (by norm_num)] + have hI : Icc 1 (m + 2) = (range (m + 2)).map (addRightEmbedding 1) := by + ext x; simp only [mem_Icc, mem_map, mem_range, addRightEmbedding_apply] + constructor + · intro hx; exact ⟨x - 1, by omega, by omega⟩ + · rintro ⟨a, ha, rfl⟩; omega + rw [hI, sum_map, sum_range_succ] + simp only [addRightEmbedding_apply] + rw [ways_eq_zero _ _ _ (by omega), add_zero] + refine sum_congr rfl fun b hb => ?_ + rw [mem_range] at hb + rw [show 2 - 1 = 1 from rfl, show m + 2 - (b + 1) = m + 1 - b by omega, + ways_one _ _ (by omega), card_supported_base _ (by omega)] + have hF : Nat.fib (m + 2 + 2) = (∑ b ∈ range (m + 1), (b + 2).choose (m + 1 - b)) + 1 := by + rw [show m + 2 + 2 = (m + 3) + 1 by ring, Nat.fib_succ_eq_sum_choose, + Finset.Nat.sum_antidiagonal_eq_sum_range_succ (fun i j => i.choose j), + Nat.succ_eq_add_one, sum_range_succ', sum_range_succ', sum_range_succ] + have h1 : (0 + 1).choose (m + 3 - (0 + 1)) = 0 := Nat.choose_eq_zero_of_lt (by omega) + have h2 : (m + 1 + 1 + 1).choose (m + 3 - (m + 1 + 1 + 1)) = 1 := by + rw [show m + 3 - (m + 1 + 1 + 1) = 0 by omega, Nat.choose_zero_right] + have h0 : Nat.choose 0 (m + 3 - 0) = 0 := Nat.choose_eq_zero_of_lt (by omega) + rw [h1, h2, h0] + have h3 : ∀ k ∈ range (m + 1), (k + 1 + 1).choose (m + 3 - (k + 1 + 1)) = + (k + 2).choose (m + 1 - k) := fun k _ => by + rw [show m + 3 - (k + 1 + 1) = m + 1 - k by omega] + rw [sum_congr rfl h3] + rw [A000071, hT, hF] + push_cast + ring + +/-- Kagey: `T(n,n-1) = A339252(n-2)`. -/ +private theorem diag1 : statement_diag1 := by + intro n hn + by_cases hsmall : n < 11 + · exact statement_check.2.1 n hsmall hn + have h1 := diag n 1 (by norm_num) (by omega) + obtain ⟨r0, r1, r2, r3⟩ := R1 + have h2 := (A339252_closed (n - 3)).1 + rw [show n - 3 + 1 = n - 1 - 1 by omega] at h2 + rw [show n - 2 = n - 1 - 1 by omega] + simp only [pe, r0, r1, r2, r3] at h1 + have : 128 * (T n (n - 1) : ℤ) = 128 * A339252 (n - 1 - 1) := by linear_combination h1 - h2 + linarith + +/-- Luschny: `T(n,n-2) = A339254(n-3)`. -/ +private theorem diag2 : statement_diag2 := by + intro n hn + by_cases hsmall : n < 11 + · exact statement_check.2.2.1 n hsmall hn + have h1 := diag n 2 (by norm_num) (by omega) + obtain ⟨r0, r1, r2, r3⟩ := R2 + have h2 := (A339254_closed (n - 5)).1 + rw [show n - 5 + 2 = n - 2 - 1 by omega] at h2 + rw [show n - 3 = n - 2 - 1 by omega] + simp only [pe, r0, r1, r2, r3] at h1 + have : 128 * (T n (n - 2) : ℤ) = 128 * A339254 (n - 2 - 1) := by linear_combination h1 - h2 + linarith + +/-- Luschny: `T(n,n-3) = A339029(n-4)`. -/ +private theorem diag3 : statement_diag3 := by + intro n hn + by_cases hsmall : n < 11 + · exact statement_check.2.2.2 n hsmall hn + have h1 := diag n 3 (by norm_num) (by omega) + obtain ⟨r0, r1, r2, r3⟩ := R3 + have h2 := (A339029_closed (n - 7)).1 + rw [show n - 7 + 3 = n - 3 - 1 by omega] at h2 + rw [show n - 4 = n - 3 - 1 by omega, A339029_eq] + simp only [pe, r0, r1, r2, r3] at h1 + have : 128 * (T n (n - 3) : ℤ) = 128 * A339029rec (n - 3 - 1) := by linear_combination h1 - h2 + linarith + +/-- The four conjectures of A333650 hold. -/ +theorem result : statement := ⟨col2, diag1, diag2, diag3⟩ + +end Math0.Frontier.A333650 + +#math0_settles Math0.Frontier.A333650.result Math0.Statements.A333650.statement diff --git a/lean/Math0/Frontier/OEIS/A334592.lean b/lean/Math0/Frontier/OEIS/A334592.lean new file mode 100644 index 0000000..2b336ca --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A334592.lean @@ -0,0 +1,265 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A334592 +import Math0.Audit + +/-! +# Records of the XOR-triangle zero count A334592 are exactly the powers of two + +We prove Peter Kagey's conjecture: `n ≥ 1` is a record position of `a` (the number of zeros in +the XOR-triangle of the binary expansion of `n`) if and only if `n` is a power of two. + +**Ones bound.** Let `ones r` be the number of `true` entries in the XOR-triangle with top row +`r`. For every split `r = p ++ true :: s` we show +`count true p + |s| + 1 ≤ ones r`, by induction on `|s|` (generalizing `p`): +* `s = []`: the top row alone has `count true p + 1` ones; +* `s = true :: s'`: apply the induction hypothesis to the split `(p ++ [true]) ++ true :: s'`; +* `s = false :: s'`: the next row is `q ++ true :: xorRow (false :: s')` (as `true ⊕ false = true`), + with `|xorRow (false :: s')| = |s'|`; the induction hypothesis bounds the ones below the top row + by `|s'| + 1`, and the top row has at least `count true p + 1` ones. +With `p = []`: a top row of length `L` starting with `true` gives at least `L` ones. + +**Zeros.** The triangle of a row of length `L` has `tri L = L(L+1)/2` entries, so +`a n + L ≤ tri L`, i.e. `a n ≤ tri (L - 1)`, where `L` is the bit length of `n ≥ 1` (the leading +bit is `1`). For `n = 2^k` the rows are `10…0` of lengths `k+1, k, …, 1`, so `a (2^k) = tri k`. + +**Records.** If `1 ≤ m < 2^k` then `m` has bit length `L ≤ k`, so `a m ≤ tri (L-1) < tri k`. +If `n ≥ 1` is not a power of two, with bit length `k + 1`, then `2^k < n` and +`a n ≤ tri k = a (2^k)`, so `n` is not a record. +-/ + +namespace Math0.Frontier.A334592 +open Math0.Statements.A334592 + +/-- Number of `true` entries in the XOR-triangle with top row `r`. -/ +private def ones (r : List Bool) : ℕ := ((xorTriangle r).map (List.count true)).sum + +/-- Number of `false` entries in the XOR-triangle with top row `r`. -/ +private def zeros (r : List Bool) : ℕ := ((xorTriangle r).map (List.count false)).sum + +/-- Triangular numbers: `tri k = 0 + 1 + ⋯ + k`. -/ +private def tri : ℕ → ℕ + | 0 => 0 + | k + 1 => tri k + (k + 1) + +/-- `tri` is strictly increasing. -/ +private lemma tri_lt {a b : ℕ} (h : a < b) : tri a < tri b := by + induction b with + | zero => omega + | succ b ih => + rcases Nat.lt_succ_iff_lt_or_eq.1 h with h' | rfl + · have := ih h' + simp only [tri] + omega + · simp only [tri] + omega + +/-- The next row is one shorter. -/ +private lemma xorRow_length (r : List Bool) : (xorRow r).length = r.length - 1 := by + simp [xorRow] + +/-- `xorRow` on a list with two leading entries. -/ +private lemma xorRow_cons_cons (a b : Bool) (s : List Bool) : + xorRow (a :: b :: s) = (a ^^ b) :: xorRow (b :: s) := rfl + +/-- The XOR-triangle of a nonempty row: the row followed by the triangle of the next row. -/ +private lemma xorTriangle_cons (x : Bool) (s : List Bool) : + xorTriangle (x :: s) = (x :: s) :: xorTriangle (xorRow (x :: s)) := by + have h : (xorRow (x :: s)).length = s.length := by + rw [xorRow_length] + simp + show rows (s.length + 1) (x :: s) = (x :: s) :: rows (xorRow (x :: s)).length (xorRow (x :: s)) + rw [h] + rfl + +/-- Recursion for `ones` on a nonempty row. -/ +private lemma ones_of_ne_nil (r : List Bool) (hr : r ≠ []) : + ones r = r.count true + ones (xorRow r) := by + obtain ⟨x, s, rfl⟩ := List.exists_cons_of_ne_nil hr + simp only [ones, xorTriangle_cons, List.map_cons, List.sum_cons] + +/-- Recursion for `zeros` on a nonempty row. -/ +private lemma zeros_of_ne_nil (r : List Bool) (hr : r ≠ []) : + zeros r = r.count false + zeros (xorRow r) := by + obtain ⟨x, s, rfl⟩ := List.exists_cons_of_ne_nil hr + simp only [zeros, xorTriangle_cons, List.map_cons, List.sum_cons] + +/-- The triangle of a row of length `n` has `tri n` entries. -/ +private lemma zeros_add_ones : ∀ (n : ℕ) (r : List Bool), r.length = n → + zeros r + ones r = tri n + | 0, r, h => by + have : r = [] := List.eq_nil_of_length_eq_zero h + subst this + rfl + | n + 1, r, h => by + have hr : r ≠ [] := by + intro h' + subst h' + simp at h + have ih := zeros_add_ones n (xorRow r) (by rw [xorRow_length]; omega) + rw [zeros_of_ne_nil r hr, ones_of_ne_nil r hr] + have := List.count_false_add_count_true r + simp only [tri] + omega + +/-- Prepending a prefix to a nonempty row changes only a prefix of the next row. -/ +private lemma xorRow_append (p l : List Bool) (hl : l ≠ []) : + ∃ q, xorRow (p ++ l) = q ++ xorRow l := by + induction p with + | nil => exact ⟨[], rfl⟩ + | cons a p ih => + obtain ⟨q, hq⟩ := ih + obtain ⟨b, t, hbt⟩ : ∃ b t, p ++ l = b :: t := by + cases p with + | nil => + obtain ⟨b, t, rfl⟩ := List.exists_cons_of_ne_nil hl + exact ⟨b, t, rfl⟩ + | cons b t => exact ⟨b, t ++ l, rfl⟩ + refine ⟨(a ^^ b) :: q, ?_⟩ + rw [List.cons_append, hbt, xorRow_cons_cons, ← hbt, hq] + rfl + +/-- The key bound: for a top row `p ++ true :: s` the triangle has at least +`count true p + |s| + 1` ones (one on each antidiagonal from that `true` onward). -/ +private lemma ones_ge : ∀ (n : ℕ) (p s : List Bool), s.length = n → + p.count true + s.length + 1 ≤ ones (p ++ true :: s) + | 0, p, s, h => by + have : s = [] := List.eq_nil_of_length_eq_zero h + subst this + rw [ones_of_ne_nil _ (by simp)] + simp only [List.count_append, List.count_singleton_self, List.length_nil] + omega + | n + 1, p, s, h => by + obtain ⟨b, s', rfl⟩ := List.exists_cons_of_length_eq_add_one h + have hs' : s'.length = n := by simpa using h + cases b with + | true => + have ih := ones_ge n (p ++ [true]) s' hs' + have e : p ++ [true] ++ true :: s' = p ++ true :: true :: s' := by simp + rw [e, List.count_append] at ih + simp only [List.count_singleton_self, List.length_cons] at ih ⊢ + omega + | false => + obtain ⟨q, hq⟩ := xorRow_append p (true :: false :: s') (by simp) + have e : xorRow (true :: false :: s') = true :: xorRow (false :: s') := rfl + have hl : (xorRow (false :: s')).length = n := by + rw [xorRow_length] + simp [hs'] + have ih := ones_ge n q (xorRow (false :: s')) hl + rw [ones_of_ne_nil _ (by simp), hq, e] + have hc : p.count true + 1 ≤ (p ++ true :: false :: s').count true := by + simp [List.count_append] + simp only [List.length_cons, hs'] + omega + +/-- A row of length `L` starting with `true` has at least `L` ones in its triangle. -/ +private lemma ones_ge_length (s : List Bool) : (true :: s).length ≤ ones (true :: s) := by + have := ones_ge s.length [] s rfl + simpa using this + +/-- `xorRow` of an all-zero row. -/ +private lemma xorRow_replicate_false (k : ℕ) : + xorRow (List.replicate k false) = List.replicate (k - 1) false := by + induction k with + | zero => rfl + | succ k ih => + cases k with + | zero => rfl + | succ k => + rw [List.replicate_succ, List.replicate_succ, xorRow_cons_cons, ← List.replicate_succ, ih] + simp [List.replicate_succ] + +/-- The triangle of `10…0` (with `k` zeros) has `tri k` zeros. -/ +private lemma zeros_pow (k : ℕ) : zeros (true :: List.replicate k false) = tri k := by + induction k with + | zero => rfl + | succ k ih => + rw [zeros_of_ne_nil _ (by simp), List.replicate_succ, xorRow_cons_cons, + ← List.replicate_succ, xorRow_replicate_false] + simp only [Bool.true_xor, Bool.not_false, Nat.add_sub_cancel] at ih ⊢ + rw [ih] + simp only [tri, List.count_cons_of_ne (by decide : true ≠ false), List.count_replicate_self] + omega + +/-- The binary expansion of a positive number starts with `1`. -/ +private lemma binary_cons (n : ℕ) (hn : n ≠ 0) : ∃ s, binary n = true :: s := by + rw [binary_eq_digits] + have hne : Nat.digits 2 n ≠ [] := Nat.digits_ne_nil_iff_ne_zero.mpr hn + obtain ⟨L, d, hLd⟩ := (List.eq_nil_or_concat (Nat.digits 2 n)).resolve_left hne + have hlast := Nat.getLast_digit_ne_zero 2 hn + have hd : (Nat.digits 2 n).getLast hne = d := by simp [hLd] + have hmem : d ∈ Nat.digits 2 n := by rw [hLd]; simp + have hlt : d < 2 := Nat.digits_lt_base (by norm_num) hmem + have h1 : d = 1 := by omega + rw [hLd, h1] + simp + +/-- The length of the binary expansion is the number of base-2 digits. -/ +private lemma binary_length (n : ℕ) : (binary n).length = (Nat.digits 2 n).length := by + simp [binary_eq_digits] + +/-- The binary expansion of `2^k` is `10…0`. -/ +private lemma binary_pow (k : ℕ) : binary (2 ^ k) = true :: List.replicate k false := by + rw [binary_eq_digits] + induction k with + | zero => simp + | succ k ih => + rw [Nat.digits_def' (by norm_num) (by positivity)] + have h1 : 2 ^ (k + 1) % 2 = 0 := by simp [Nat.pow_succ] + have h2 : 2 ^ (k + 1) / 2 = 2 ^ k := by simp [Nat.pow_succ] + rw [h1, h2, List.map_cons, List.reverse_cons, ih, List.replicate_succ'] + rfl + +/-- `a (2^k) = tri k`. -/ +private lemma a_pow (k : ℕ) : a (2 ^ k) = tri k := by + show zeros (binary (2 ^ k)) = tri k + rw [binary_pow, zeros_pow] + +/-- For `n ≥ 1` with `L` binary digits, `a n ≤ tri (L - 1)`. -/ +private lemma a_le (n : ℕ) (hn : n ≠ 0) : a n ≤ tri ((Nat.digits 2 n).length - 1) := by + obtain ⟨s, hs⟩ := binary_cons n hn + have hlen := binary_length n + rw [hs] at hlen + have h1 := ones_ge_length s + have h2 := zeros_add_ones _ (true :: s) rfl + have ha : a n = zeros (true :: s) := by + show zeros (binary n) = _ + rw [hs] + rw [ha, ← hlen] + simp only [List.length_cons, Nat.add_sub_cancel] at h1 h2 ⊢ + simp only [tri] at h2 + omega + +/-- Kagey's conjecture: the record positions of A334592 are exactly the powers of two. -/ +theorem result : statement := by + intro n + constructor + · rintro ⟨hn1, hrec⟩ + by_contra hne + simp only [not_exists] at hne + have hn0 : n ≠ 0 := by omega + have hpos : 0 < (Nat.digits 2 n).length := + List.length_pos_iff.mpr (Nat.digits_ne_nil_iff_ne_zero.mpr hn0) + have hL : 2 ^ ((Nat.digits 2 n).length - 1) ≤ n := + (Nat.lt_digits_length_iff (by norm_num) n).1 (by omega) + have hlt : 2 ^ ((Nat.digits 2 n).length - 1) < n := + lt_of_le_of_ne hL (fun h => hne _ h.symm) + have h1 := hrec _ Nat.one_le_two_pow hlt + have h2 := a_le n hn0 + rw [a_pow] at h1 + omega + · rintro ⟨k, rfl⟩ + refine ⟨Nat.one_le_two_pow, fun m hm1 hmk => ?_⟩ + have hm0 : m ≠ 0 := by omega + have hLk : (Nat.digits 2 m).length ≤ k := (Nat.digits_length_le_iff (by norm_num) m).2 hmk + have hpos : 0 < (Nat.digits 2 m).length := + List.length_pos_iff.mpr (Nat.digits_ne_nil_iff_ne_zero.mpr hm0) + have h1 := a_le m hm0 + have h2 : tri ((Nat.digits 2 m).length - 1) < tri k := tri_lt (by omega) + rw [a_pow] + omega + +end Math0.Frontier.A334592 + +#math0_settles Math0.Frontier.A334592.result Math0.Statements.A334592.statement diff --git a/lean/Math0/Frontier/OEIS/A334595.lean b/lean/Math0/Frontier/OEIS/A334595.lean new file mode 100644 index 0000000..fe26e47 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A334595.lean @@ -0,0 +1,419 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A334595 +import Math0.Audit + +/-! +# A334595: `a(n) = 1` iff `n` is a power of two, and records occur at `1` and `2^k + 1` + +We prove both conjectures of Peter Kagey on the right diagonal of the XOR-triangle. + +**Reversal.** XOR is commutative, so `xorRow` commutes with list reversal; hence the right +diagonal of the triangle of `binExp n = (digits 2 n).reverse` is the *head column* +`D c = [head c, head (xorRow c), head (xorRow² c), …]` of the least-significant-first digit list +`c = digits 2 n`, and `a n = ofDigits 2 (D c).reverse`. + +**Involution.** `D (x :: r) = x :: D (xorRow (x :: r))` and, by induction on the length, +`xorRow (D c) = D c.tail` (the only algebra used is `x ^^^ (x ^^^ y) = y`). Consequently +`D (D c) = c` (Newton's forward-difference formula over `GF(2)`). Together with injectivity of +`ofDigits 2` on `0`/`1` lists of a fixed length, `a` is injective on numbers with `L` binary +digits, and `a n` is determined by solving `D c = d`, i.e. `c = D d`. + +**Explicit values.** `D` fixes `(0,…,0,1)` (the digits of `2^k`), so `a(2^k) = 1`, and +`a n = 1` forces the digits of `n` to be `(0,…,0,1)`. `D (1,0,…,0,1) = (1,…,1,0)`, so +`a(2^(j+1)+1) = 2^(j+2) - 2`. `D (1,0,…,0) = (1,…,1)`, so `a n = 2^L - 1` forces `n = 1`. +Since `a n < 2^L` for an `L`-digit `n`, every `L`-digit `n ≥ 2` other than `2^(L-1)` and +`2^(L-1) + 1` has `a n ≤ 2^L - 2 = a(2^(L-1)+1)`, while `a(2^(L-1)) = 1 = a 1` and all shorter +`m` have `a m < 2^(L-1)`. This gives exactly the record positions `1, 3, 5, 9, 17, …`. +-/ + +namespace Math0.Frontier.A334595 +open Math0.Statements.A334595 + +/-- The head column of a row: entry `r` is the head of the `r`-th iterated XOR-row. -/ +private def D (c : List ℕ) : List ℕ := + (List.range c.length).map (fun r => (xorRow^[r] c).headD 0) + +/-- `xorRow` of a one-entry row is empty. -/ +private lemma xorRow_single (x : ℕ) : xorRow [x] = [] := rfl + +/-- Unfolding `xorRow` on a row with at least two entries. -/ +private lemma xorRow_cons_cons (x y : ℕ) (r : List ℕ) : + xorRow (x :: y :: r) = (x ^^^ y) :: xorRow (y :: r) := rfl + +/-- `xorRow` shortens a row by one. -/ +private lemma length_xorRow (l : List ℕ) : (xorRow l).length = l.length - 1 := by + simp [xorRow, List.length_zipWith] + +/-- Entry `i` of `xorRow l` is `l[i] ^^^ l[i+1]`. -/ +private lemma getElem_xorRow (l : List ℕ) (i : ℕ) (h : i < (xorRow l).length) : + (xorRow l)[i] = l[i]'(by rw [length_xorRow] at h; omega) ^^^ + l[i + 1]'(by rw [length_xorRow] at h; omega) := by + simp [xorRow, List.getElem_zipWith, List.getElem_tail] + +/-- `xorRow` commutes with reversal (XOR is commutative). -/ +private lemma xorRow_reverse (l : List ℕ) : xorRow l.reverse = (xorRow l).reverse := by + apply List.ext_getElem + · simp [length_xorRow] + · intro i h1 h2 + rw [getElem_xorRow, List.getElem_reverse, List.getElem_reverse, List.getElem_reverse, + getElem_xorRow] + simp only [length_xorRow, List.length_reverse] at h1 h2 ⊢ + rw [Nat.xor_comm] + congr 2 <;> omega + +/-- Iterated `xorRow` commutes with reversal. -/ +private lemma iterate_xorRow_reverse (l : List ℕ) (r : ℕ) : + xorRow^[r] l.reverse = (xorRow^[r] l).reverse := by + induction r with + | zero => rfl + | succ r ih => rw [Function.iterate_succ_apply', Function.iterate_succ_apply', ih, + xorRow_reverse] + +/-- The right diagonal of the triangle of `c.reverse` is the head column `D c` of `c`. -/ +private lemma rightDiag_reverse (c : List ℕ) : rightDiag c.reverse = D c := by + simp only [rightDiag, triangle, D, List.length_reverse, List.map_map] + congr 1 + funext r + simp [iterate_xorRow_reverse] + +/-- `a n` read through the least-significant-first digit list of `n`. -/ +private lemma a_eq (n : ℕ) : a n = Nat.ofDigits 2 (D (Nat.digits 2 n)).reverse := by + rw [a, binExp, rightDiag_reverse] + +/-- `D` preserves length. -/ +private lemma length_D (c : List ℕ) : (D c).length = c.length := by + simp [D] + +/-- `D [] = []`. -/ +private lemma D_nil : D [] = [] := rfl + +/-- Recursion for `D`: the head column of `x :: r` is `x` followed by the head column of the +next row. -/ +private lemma D_cons (x : ℕ) (r : List ℕ) : D (x :: r) = x :: D (xorRow (x :: r)) := by + unfold D + rw [length_xorRow, List.length_cons, Nat.add_sub_cancel, List.range_succ_eq_map, + List.map_cons, List.map_map] + congr 1 + +/-- `xorRow` commutes with `tail`. -/ +private lemma tail_xorRow (l : List ℕ) : (xorRow l).tail = xorRow l.tail := by + match l with + | [] => rfl + | [_] => rfl + | x :: y :: r => rfl + +/-- Key identity `xorRow (D c) = D c.tail`, by induction on the length of `c`. -/ +private lemma xorRow_D_aux (n : ℕ) : + ∀ c : List ℕ, c.length = n → xorRow (D c) = D c.tail := by + induction n with + | zero => + intro c hc + rw [List.length_eq_zero_iff.mp hc] + rfl + | succ n ih => + intro c hc + match c, hc with + | [x], _ => + rw [D_cons, xorRow_single, D_nil, xorRow_single] + rfl + | x :: y :: r, hc => + have h1 : D (x :: y :: r) = x :: D (xorRow (x :: y :: r)) := D_cons x (y :: r) + have h2 : D (xorRow (x :: y :: r)) = + (x ^^^ y) :: D (xorRow (xorRow (x :: y :: r))) := by + rw [xorRow_cons_cons x y r, D_cons] + have h3 : xorRow (D (xorRow (x :: y :: r))) = D (xorRow (y :: r)) := by + rw [ih _ (by rw [length_xorRow]; simp only [List.length_cons] at hc ⊢; omega), + tail_xorRow] + rfl + rw [h1, h2, xorRow_cons_cons x (x ^^^ y) (D (xorRow (xorRow (x :: y :: r)))), ← h2, h3, + ← Nat.xor_assoc, Nat.xor_self, Nat.zero_xor, List.tail_cons, D_cons y r] + +/-- Key identity: the XOR-row of the head column of `c` is the head column of `c.tail`. -/ +private lemma xorRow_D (c : List ℕ) : xorRow (D c) = D c.tail := + xorRow_D_aux c.length c rfl + +/-- `D` is an involution, by induction on the length. -/ +private lemma D_D_aux (n : ℕ) : ∀ c : List ℕ, c.length = n → D (D c) = c := by + induction n with + | zero => + intro c hc + rw [List.length_eq_zero_iff.mp hc] + rfl + | succ n ih => + intro c hc + match c, hc with + | x :: r, hc => + calc D (D (x :: r)) = D (x :: D (xorRow (x :: r))) := by rw [D_cons x r] + _ = x :: D (xorRow (x :: D (xorRow (x :: r)))) := D_cons _ _ + _ = x :: D (xorRow (D (x :: r))) := by rw [D_cons x r] + _ = x :: D (D r) := by rw [xorRow_D]; rfl + _ = x :: r := by rw [ih r (by simpa using hc)] + +/-- `D` is an involution (Newton's forward-difference formula over `GF(2)`). -/ +private lemma D_D (c : List ℕ) : D (D c) = c := + D_D_aux c.length c rfl + +/-- `xorRow` keeps a `0`/`1` row a `0`/`1` row. -/ +private lemma xorRow_lt_two (l : List ℕ) (h : ∀ x ∈ l, x < 2) : + ∀ x ∈ xorRow l, x < 2 := by + intro z hz + obtain ⟨i, hi, rfl⟩ := List.getElem_of_mem hz + rw [getElem_xorRow] + have hi' : i + 1 < l.length := by rw [length_xorRow] at hi; omega + have h1 := h _ (List.getElem_mem (show i < l.length by omega)) + have h2 := h _ (List.getElem_mem hi') + have := Nat.xor_lt_two_pow (n := 1) (by simpa using h1) (by simpa using h2) + simpa using this + +/-- Iterated `xorRow` keeps a `0`/`1` row a `0`/`1` row. -/ +private lemma iterate_xorRow_lt_two (l : List ℕ) (h : ∀ x ∈ l, x < 2) (r : ℕ) : + ∀ x ∈ xorRow^[r] l, x < 2 := by + induction r with + | zero => exact h + | succ r ih => + rw [Function.iterate_succ_apply'] + exact xorRow_lt_two _ ih + +/-- The head column of a `0`/`1` row is a `0`/`1` row. -/ +private lemma D_lt_two (c : List ℕ) (h : ∀ x ∈ c, x < 2) : ∀ x ∈ D c, x < 2 := by + intro z hz + simp only [D, List.mem_map, List.mem_range] at hz + obtain ⟨r, _, rfl⟩ := hz + have := iterate_xorRow_lt_two c h r + cases hl : xorRow^[r] c with + | nil => simp + | cons y t => + rw [hl] at this + simpa using this y (by simp) + +/-- `xorRow (0,…,0,1) = (0,…,0,1)` with one zero fewer. -/ +private lemma xorRow_e (k : ℕ) : + xorRow (List.replicate (k + 1) 0 ++ [1]) = List.replicate k 0 ++ [1] := by + induction k with + | zero => rfl + | succ k ih => + have ih' : xorRow (0 :: (List.replicate k 0 ++ [1])) = List.replicate k 0 ++ [1] := ih + show xorRow (0 :: 0 :: (List.replicate k 0 ++ [1])) = 0 :: (List.replicate k 0 ++ [1]) + rw [xorRow_cons_cons, ih', Nat.xor_self] + +/-- `D` fixes `e_k = (0,…,0,1)` (`k` zeros), the digits of `2^k`. -/ +private lemma D_e (k : ℕ) : D (List.replicate k 0 ++ [1]) = List.replicate k 0 ++ [1] := by + induction k with + | zero => + show D [1] = [1] + rw [D_cons, xorRow_single, D_nil] + | succ k ih => + show D (0 :: (List.replicate k 0 ++ [1])) = 0 :: (List.replicate k 0 ++ [1]) + rw [D_cons] + have h : xorRow (0 :: (List.replicate k 0 ++ [1])) = List.replicate k 0 ++ [1] := xorRow_e k + rw [h, ih] + +/-- `xorRow` of a constant row is a zero row. -/ +private lemma xorRow_rep (m x : ℕ) : xorRow (List.replicate (m + 1) x) = List.replicate m 0 := by + induction m with + | zero => rfl + | succ m ih => + show xorRow (x :: x :: List.replicate m x) = 0 :: List.replicate m 0 + rw [xorRow_cons_cons, Nat.xor_self] + exact congrArg (0 :: ·) ih + +/-- `D` fixes zero rows. -/ +private lemma D_rep0 (m : ℕ) : D (List.replicate m 0) = List.replicate m 0 := by + induction m with + | zero => rfl + | succ m ih => + show D (0 :: List.replicate m 0) = 0 :: List.replicate m 0 + rw [D_cons] + have h : xorRow (0 :: List.replicate m 0) = List.replicate m 0 := xorRow_rep m 0 + rw [h, ih] + +/-- `D (1,…,1) = (1,0,…,0)`. -/ +private lemma D_rep1 (m : ℕ) : D (List.replicate (m + 1) 1) = 1 :: List.replicate m 0 := by + show D (1 :: List.replicate m 1) = 1 :: List.replicate m 0 + rw [D_cons] + have h : xorRow (1 :: List.replicate m 1) = List.replicate m 0 := xorRow_rep m 1 + rw [h, D_rep0] + +/-- `xorRow (1,0,…,0,1) = (1,0,…,0,1)` with one zero fewer. -/ +private lemma xorRow_f (j : ℕ) : + xorRow (1 :: (List.replicate (j + 1) 0 ++ [1])) = 1 :: (List.replicate j 0 ++ [1]) := by + show xorRow (1 :: 0 :: (List.replicate j 0 ++ [1])) = 1 :: (List.replicate j 0 ++ [1]) + rw [xorRow_cons_cons] + have h : xorRow (0 :: (List.replicate j 0 ++ [1])) = List.replicate j 0 ++ [1] := xorRow_e j + rw [h] + rfl + +/-- `D (1,0,…,0,1) = (1,…,1,0)`; here `(1,0,…,0,1)` (`j` zeros) is the digit list of +`2^(j+1)+1`. -/ +private lemma D_f (j : ℕ) : + D (1 :: (List.replicate j 0 ++ [1])) = List.replicate (j + 1) 1 ++ [0] := by + induction j with + | zero => + show D [1, 1] = [1, 0] + rw [D_cons, xorRow_cons_cons, xorRow_single, Nat.xor_self, D_cons, xorRow_single, D_nil] + | succ j ih => + rw [D_cons, xorRow_f, ih] + rfl + +/-- The value of `e_k` is `2^k`. -/ +private lemma ofDigits_e (k : ℕ) : Nat.ofDigits 2 (List.replicate k 0 ++ [1]) = 2 ^ k := by + simp [Nat.ofDigits_append, Nat.ofDigits_replicate_zero, Nat.ofDigits_singleton] + +/-- The value of `e_k` reversed is `1`. -/ +private lemma ofDigits_e_rev (k : ℕ) : + Nat.ofDigits 2 (List.replicate k 0 ++ [1]).reverse = 1 := by + simp [List.reverse_append, List.reverse_replicate, Nat.ofDigits_cons, + Nat.ofDigits_replicate_zero] + +/-- `ofDigits 2 (1,…,1) + 1 = 2^m` (`m` ones). -/ +private lemma ofDigits_rep1 (m : ℕ) : Nat.ofDigits 2 (List.replicate m 1) + 1 = 2 ^ m := by + induction m with + | zero => rfl + | succ m ih => + rw [List.replicate_succ, Nat.ofDigits_cons, pow_succ] + omega + +/-- `e_k` is a `0`/`1` row. -/ +private lemma e_lt (k : ℕ) : ∀ x ∈ List.replicate k 0 ++ [1], x < 2 := by + intro x hx + simp only [List.mem_append, List.mem_replicate, List.mem_singleton] at hx + omega + +/-- `(1,0,…,0,1)` is a `0`/`1` row. -/ +private lemma f_lt (j : ℕ) : ∀ x ∈ 1 :: (List.replicate j 0 ++ [1]), x < 2 := by + intro x hx + simp at hx + omega + +/-- `a` of the number with (least-significant-first) binary digits `l`. -/ +private lemma a_ofDigits (l : List ℕ) (hl : ∀ x ∈ l, x < 2) + (hlast : ∀ h : l ≠ [], l.getLast h ≠ 0) : + a (Nat.ofDigits 2 l) = Nat.ofDigits 2 (D l).reverse := by + rw [a_eq, Nat.digits_ofDigits 2 (by norm_num) l hl hlast] + +/-- `a n < 2^L` where `L` is the number of binary digits of `n`. -/ +private lemma a_lt (n : ℕ) : a n < 2 ^ (Nat.digits 2 n).length := by + have hc : ∀ x ∈ Nat.digits 2 n, x < 2 := fun x hx => Nat.digits_lt_base (by norm_num) hx + rw [a_eq] + have := Nat.ofDigits_lt_base_pow_length (b := 2) (by norm_num) + (l := (D (Nat.digits 2 n)).reverse) (fun x hx => D_lt_two _ hc x (List.mem_reverse.mp hx)) + simpa [length_D] using this + +/-- Injectivity: if `a n` equals the value attached to a `0`/`1` row `l` of the same length as +the digits of `n`, then `l` is the digit list of `n`. -/ +private lemma eq_ofDigits_of_a_eq (n : ℕ) (l : List ℕ) (hl : ∀ x ∈ l, x < 2) + (hlen : l.length = (Nat.digits 2 n).length) (h : a n = Nat.ofDigits 2 (D l).reverse) : + n = Nat.ofDigits 2 l := by + have hc : ∀ x ∈ Nat.digits 2 n, x < 2 := fun x hx => Nat.digits_lt_base (by norm_num) hx + rw [a_eq] at h + have h1 := Nat.ofDigits_inj_of_len_eq (b := 2) (by norm_num) + (by simp [length_D, hlen]) (fun x hx => D_lt_two _ hc x (List.mem_reverse.mp hx)) + (fun x hx => D_lt_two _ hl x (List.mem_reverse.mp hx)) h + rw [List.reverse_inj] at h1 + have h2 : Nat.digits 2 n = l := by rw [← D_D (Nat.digits 2 n), h1, D_D] + rw [← h2, Nat.ofDigits_digits] + +/-- `a (2^k) = 1`. -/ +private lemma a_two_pow (k : ℕ) : a (2 ^ k) = 1 := by + rw [← ofDigits_e k, a_ofDigits _ (e_lt k) (by simp), D_e, ofDigits_e_rev] + +/-- `a (2^(j+1)+1) = 2^(j+2) - 2`. -/ +private lemma a_two_pow_add_one (j : ℕ) : a (2 ^ (j + 1) + 1) + 2 = 2 ^ (j + 2) := by + have h1 : Nat.ofDigits 2 (1 :: (List.replicate j 0 ++ [1])) = 2 ^ (j + 1) + 1 := by + rw [Nat.ofDigits_cons, ofDigits_e, pow_succ] + ring + rw [← h1, a_ofDigits _ (f_lt j) (by simp), D_f, List.reverse_append, List.reverse_replicate] + simp only [List.reverse_singleton, List.singleton_append, Nat.ofDigits_cons] + have := ofDigits_rep1 (j + 1) + rw [pow_succ 2 (j + 1)] + omega + +/-- For `n ≥ 2` with `L` binary digits, `a n ≠ 2^L - 1`. -/ +private lemma a_ne_all_ones (n : ℕ) (hn : 2 ≤ n) : a n + 1 ≠ 2 ^ (Nat.digits 2 n).length := by + intro h + obtain ⟨m, hm⟩ : ∃ m, (Nat.digits 2 n).length = m + 1 := ⟨(Nat.digits 2 n).length - 1, by + have := (Nat.lt_digits_length_iff (b := 2) (k := 0) (by norm_num) n).mpr (by simp; omega) + omega⟩ + rw [hm] at h + have hD : D (1 :: List.replicate m 0) = List.replicate (m + 1) 1 := by + rw [← D_rep1, D_D] + have h' := eq_ofDigits_of_a_eq n (1 :: List.replicate m 0) + (by + intro x hx + simp only [List.mem_cons, List.mem_replicate] at hx + omega) + (by simp [hm]) + (by + rw [hD, List.reverse_replicate] + have := ofDigits_rep1 (m + 1) + omega) + rw [Nat.ofDigits_cons, Nat.ofDigits_replicate_zero] at h' + omega + +/-- If `a n = 1` (`n ≥ 1`) then `n` is a power of two. -/ +private lemma pow_of_a_eq_one (n : ℕ) (hn : 1 ≤ n) (h : a n = 1) : ∃ k, n = 2 ^ k := by + obtain ⟨k, hk⟩ : ∃ k, (Nat.digits 2 n).length = k + 1 := ⟨(Nat.digits 2 n).length - 1, by + have := (Nat.lt_digits_length_iff (b := 2) (k := 0) (by norm_num) n).mpr (by simpa using hn) + omega⟩ + refine ⟨k, ?_⟩ + rw [eq_ofDigits_of_a_eq n (List.replicate k 0 ++ [1]) (e_lt k) (by simp [hk]) + (by rw [D_e, ofDigits_e_rev, h]), ofDigits_e] + +/-- The record conjecture. -/ +private lemma records : statement_records := by + have ha1 : a 1 = 1 := by simpa using a_two_pow 0 + intro n + constructor + · rintro ⟨hn1, hrec⟩ + by_cases h1 : n = 1 + · exact Or.inl h1 + right + have hn2 : 2 ≤ n := by omega + have hL : 1 < (Nat.digits 2 n).length := + (Nat.lt_digits_length_iff (by norm_num) n).mpr (by simpa using hn2) + obtain ⟨j, hj⟩ : ∃ j, (Nat.digits 2 n).length = j + 2 := + ⟨(Nat.digits 2 n).length - 2, by omega⟩ + have hlow : 2 ^ (j + 1) ≤ n := (Nat.lt_digits_length_iff (by norm_num) n).mp (by omega) + refine ⟨j + 1, by omega, ?_⟩ + rcases Nat.lt_trichotomy n (2 ^ (j + 1) + 1) with hlt | heq | hgt + · have hn' : n = 2 ^ (j + 1) := by omega + have := hrec 1 le_rfl (by omega) + rw [hn', a_two_pow, ha1] at this + exact absurd this (lt_irrefl _) + · exact heq + · have h1 := hrec (2 ^ (j + 1) + 1) (Nat.le_add_left _ _) hgt + have h2 := a_two_pow_add_one j + have h3 := a_lt n + have h4 := a_ne_all_ones n hn2 + rw [hj] at h3 h4 + omega + · rintro (rfl | ⟨k, hk, rfl⟩) + · exact ⟨le_rfl, fun m hm1 hm2 => absurd hm2 (by omega)⟩ + · obtain ⟨j, rfl⟩ : ∃ j, k = j + 1 := ⟨k - 1, by omega⟩ + refine ⟨Nat.le_add_left _ _, fun m hm1 hm2 => ?_⟩ + have h2 := a_two_pow_add_one j + have hp : 2 ^ (j + 2) = 2 * 2 ^ (j + 1) := by ring + have hp2 : 2 ≤ 2 ^ (j + 1) := by + have := Nat.two_pow_pos j + rw [pow_succ] + omega + rcases Nat.lt_or_ge m (2 ^ (j + 1)) with hlt | hge + · have hlen : (Nat.digits 2 m).length ≤ j + 1 := + (Nat.digits_length_le_iff (by norm_num) m).mpr hlt + have h3 := a_lt m + have h4 : 2 ^ (Nat.digits 2 m).length ≤ 2 ^ (j + 1) := + Nat.pow_le_pow_right (by norm_num) hlen + omega + · have hm : m = 2 ^ (j + 1) := by omega + rw [hm, a_two_pow] + omega + +/-- Both conjectures of A334595 hold. -/ +theorem result : statement := + ⟨records, fun n hn => ⟨pow_of_a_eq_one n hn, fun ⟨k, hk⟩ => hk ▸ a_two_pow k⟩⟩ + +end Math0.Frontier.A334595 + +#math0_settles Math0.Frontier.A334595.result Math0.Statements.A334595.statement diff --git a/lean/Math0/Frontier/OEIS/A334603.lean b/lean/Math0/Frontier/OEIS/A334603.lean new file mode 100644 index 0000000..d4c7e80 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A334603.lean @@ -0,0 +1,72 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A334603 +import Math0.Audit + +/-! +# The period of `1/11^n` is `2 * 11^(n-1)` + +We prove the FORMULA conjecture of OEIS A334603: for every `n ≥ 1`, the multiplicative order of +`10` modulo `11^n` (the period of the decimal expansion of `1/11^n`) is `2 * 11^(n-1)`. + +Write `n = k + 1`. In `ZMod (11^(k+1))` we have `10^2 = 100 = 1 + 11 * 9` with `11 ∤ 9`, so by +Mathlib's `ZMod.orderOf_one_add_mul_prime` the element `10^2` has order exactly `11^k`. Hence +`10^(2 * 11^k) = 1`. The prime divisors of `2 * 11^k` are `2` and (for `k ≥ 1`) `11`: +* `10^(11^k) ≠ 1`, because reducing modulo `11` gives `(-1)^(11^k) = -1 ≠ 1`; +* `10^(2 * 11^(k-1)) = (10^2)^(11^(k-1)) ≠ 1`, since `0 < 11^(k-1) < 11^k = orderOf (10^2)`. +The order criterion `orderOf_eq_of_pow_and_pow_div_prime` then gives `orderOf 10 = 2 * 11^k`. +-/ + +namespace Math0.Frontier.A334603 +open Math0.Statements.A334603 + +/-- In `ZMod (11 ^ (k + 1))`, the element `10 ^ 2 = 100 = 1 + 11 * 9` has order `11 ^ k`. -/ +private theorem orderOf_hundred (k : ℕ) : + orderOf ((10 : ZMod (11 ^ (k + 1))) ^ 2) = 11 ^ k := by + have h := ZMod.orderOf_one_add_mul_prime (p := 11) (by norm_num) (by norm_num) 9 + (by decide) k + have e : ((10 : ZMod (11 ^ (k + 1))) ^ 2) = + 1 + ((11 : ℕ) : ZMod (11 ^ (k + 1))) * ((9 : ℤ) : ZMod (11 ^ (k + 1))) := by + push_cast + norm_num + rw [e] + exact h + +/-- An odd power of `10` is never `1` modulo `11 ^ (k + 1)`, since `10 ≡ -1 (mod 11)`. -/ +private theorem ten_pow_odd_ne_one (k j : ℕ) (hj : Odd j) : + (10 : ZMod (11 ^ (k + 1))) ^ j ≠ 1 := by + intro h + have h2 := congrArg (ZMod.castHom (dvd_pow_self 11 (Nat.succ_ne_zero k)) (ZMod 11)) h + rw [map_pow, map_one, map_ofNat] at h2 + have h10 : (10 : ZMod 11) = -1 := by decide + rw [h10, hj.neg_one_pow] at h2 + exact absurd h2 (by decide) + +/-- The multiplicative order of `10` modulo `11 ^ (k + 1)` is `2 * 11 ^ k`. -/ +private theorem orderOf_ten (k : ℕ) : orderOf (10 : ZMod (11 ^ (k + 1))) = 2 * 11 ^ k := by + apply orderOf_eq_of_pow_and_pow_div_prime (by positivity) + · rw [pow_mul, ← orderOf_hundred k, pow_orderOf_eq_one] + · intro q hq hqL + rcases prime_dvd_two_mul_pow hq hqL with rfl | rfl + · rw [Nat.mul_div_cancel_left _ (by norm_num)] + exact ten_pow_odd_ne_one k _ (Odd.pow (by decide)) + · cases k with + | zero => norm_num at hqL + | succ k => + rw [show 2 * 11 ^ (k + 1) / 11 = 2 * 11 ^ k by rw [pow_succ]; omega, pow_mul] + apply pow_ne_one_of_lt_orderOf (by positivity) + rw [orderOf_hundred] + exact Nat.pow_lt_pow_right (by norm_num) (Nat.lt_succ_self k) + +/-- OEIS A334603 (FORMULA conjecture): for every `n ≥ 1`, the period of the decimal expansion of +`1/11^n` is `2 * 11^(n-1)`. -/ +theorem result : statement := by + intro n hn + obtain ⟨k, rfl⟩ : ∃ k, n = k + 1 := ⟨n - 1, by omega⟩ + rw [a, period_eq_orderOf (Nat.Coprime.pow_right _ (by norm_num)), orderOf_ten, + Nat.add_sub_cancel] + +end Math0.Frontier.A334603 + +#math0_settles Math0.Frontier.A334603.result Math0.Statements.A334603.statement diff --git a/lean/Math0/Frontier/OEIS/A335012.lean b/lean/Math0/Frontier/OEIS/A335012.lean new file mode 100644 index 0000000..a435537 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A335012.lean @@ -0,0 +1,291 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A335012 +import Math0.Audit + +/-! +# Repunit residues: `a(n) = n - 1` exactly for long period primes + +We prove Eu's conjecture on A335012: for `n ≥ 1`, the repunits `R_1, ..., R_n` take exactly +`n - 1` distinct residues modulo `n` iff `n` is a long period prime (A006883). + +Write `R_k = (10^k - 1)/9`, so `R_{k+1} = 10 R_k + 1`, `9 R_k + 1 = 10^k` and +`R_{m+k} = 10^k R_m + R_k`. + +* **Periodicity.** If `n ∣ R_m` with `m ≥ 1`, then `R_{m+k} ≡ R_k (mod n)`, so every residue is + already attained by some `R_j` with `1 ≤ j ≤ m`; hence `a(n) ≤ m`. +* **Cancellation.** If `gcd(n, 10) = 1` and `R_i ≡ R_j (mod n)` with `i < j`, then + `n ∣ 10^i R_{j-i}`, so `n ∣ R_{j-i}`. +* **Small factors.** If `2 ∣ n` (`n ≥ 4`) all residues are odd, if `5 ∣ n` all are `≡ 1 (mod 5)`; + either way `0` and `2` are missed and `a(n) ≤ n - 2`. +* **Three.** `R_k ≡ k (mod 3)`. If `3 ∣ n`, `gcd(n,10) = 1` and `a(n) = n - 1 < n`, pigeonhole and + cancellation give `n ∣ R_m` with `1 ≤ m ≤ n - 1`, periodicity forces `m = n - 1`, and then + `3 ∣ R_{n-1}` gives `3 ∣ n - 1`, impossible. +* **The main case.** If `gcd(n, 30) = 1`, then `n ∣ R_m ↔ 10^m ≡ 1 (mod n)`. Euler gives + `n ∣ R_{φ(n)}`, so `n - 1 = a(n) ≤ φ(n)`, hence `n` is prime; then with `d = ord_n(10)`, + `n - 1 ≤ d ∣ n - 1`. Conversely for a long period prime `p ≥ 7`, `R_1, ..., R_{p-1}` are + pairwise distinct modulo `p` (cancellation and minimality of the order) and `p ∣ R_{p-1}`. +-/ + +namespace Math0.Frontier.A335012 +open Math0.Statements.A335012 + +/-- The repunit `R_k = 11...1` (`k` ones), defined by `R_0 = 0`, `R_{k+1} = 10 R_k + 1`. -/ +private def rep : ℕ → ℕ + | 0 => 0 + | k + 1 => 10 * rep k + 1 + +/-- `9 R_k + 1 = 10^k`. -/ +private lemma nine_rep (k : ℕ) : 9 * rep k + 1 = 10 ^ k := by + induction k with + | zero => rfl + | succ k ih => rw [rep, pow_succ, ← ih]; ring + +/-- The closed form used in the statement agrees with `rep`. -/ +private lemma rep_eq (k : ℕ) : (10 ^ k - 1) / 9 = rep k := by + rw [← nine_rep k]; omega + +/-- `R_{m+k} = 10^k R_m + R_k`. -/ +private lemma rep_add (m k : ℕ) : rep (m + k) = 10 ^ k * rep m + rep k := by + induction k with + | zero => simp [rep] + | succ k ih => rw [← add_assoc, rep, ih, rep, pow_succ]; ring + +/-- `R_k ≡ k (mod 3)`. -/ +private lemma rep_mod_three (k : ℕ) : rep k % 3 = k % 3 := by + induction k with + | zero => rfl + | succ k ih => rw [rep]; omega + +/-- Repunits are odd. -/ +private lemma rep_mod_two (k : ℕ) (hk : 1 ≤ k) : rep k % 2 = 1 := by + obtain ⟨k, rfl⟩ : ∃ j, k = j + 1 := ⟨k - 1, by omega⟩ + rw [rep]; omega + +/-- Repunits are `≡ 1 (mod 5)`. -/ +private lemma rep_mod_five (k : ℕ) (hk : 1 ≤ k) : rep k % 5 = 1 := by + obtain ⟨k, rfl⟩ : ∃ j, k = j + 1 := ⟨k - 1, by omega⟩ + rw [rep]; omega + +/-- `a` in terms of `rep`. -/ +private lemma a_eq (n : ℕ) : a n = ((Finset.Icc 1 n).image (fun k => rep k % n)).card := by + unfold a + congr 2 + funext k + rw [rep_eq] + +/-- `10^m = 1` in `ZMod n` iff `10^m ≡ 1 (mod n)`. -/ +private lemma zmod_pow_iff (n m : ℕ) : (10 : ZMod n) ^ m = 1 ↔ 10 ^ m ≡ 1 [MOD n] := by + rw [← ZMod.natCast_eq_natCast_iff] + push_cast + rfl + +/-- If `n` is prime to `3` and `10^m ≡ 1 (mod n)`, then `n ∣ R_m`. -/ +private lemma dvd_rep_of_modEq {n m : ℕ} (h3 : Nat.Coprime n 3) (h : 10 ^ m ≡ 1 [MOD n]) : + n ∣ rep m := by + rw [← nine_rep] at h + have h0 : 9 * rep m ≡ 0 [MOD n] := Nat.ModEq.add_right_cancel' 1 (by simpa using h) + have h9 : Nat.Coprime n 9 := by + have := Nat.Coprime.pow_right 2 h3 + simpa using this + exact h9.dvd_of_dvd_mul_left ((Nat.modEq_zero_iff_dvd).1 h0) + +/-- If `n ∣ R_m`, then `10^m ≡ 1 (mod n)`. -/ +private lemma modEq_of_dvd_rep {n m : ℕ} (h : n ∣ rep m) : 10 ^ m ≡ 1 [MOD n] := by + rw [← nine_rep] + have h0 : 9 * rep m ≡ 0 [MOD n] := (Nat.modEq_zero_iff_dvd).2 (dvd_mul_of_dvd_right h 9) + simpa using h0.add_right 1 + +/-- Periodicity: if `n ∣ R_m` then every `R_k % n` (`k ≥ 1`) equals some `R_j % n`, `1 ≤ j ≤ m`. -/ +private lemma exists_small {n m : ℕ} (hm : 1 ≤ m) (h : n ∣ rep m) : + ∀ k, 1 ≤ k → ∃ j, 1 ≤ j ∧ j ≤ m ∧ rep j % n = rep k % n := by + intro k + induction k using Nat.strong_induction_on with + | _ k ih => + intro hk + by_cases hkm : k ≤ m + · exact ⟨k, hk, hkm, rfl⟩ + · obtain ⟨j, hj1, hjm, hj⟩ := ih (k - m) (by omega) (by omega) + refine ⟨j, hj1, hjm, ?_⟩ + have hk' : k = m + (k - m) := by omega + rw [hj, hk', rep_add, Nat.add_sub_cancel_left] + obtain ⟨c, hc⟩ := h + rw [hc] + rw [show 10 ^ (k - m) * (n * c) = n * (10 ^ (k - m) * c) by ring, Nat.mul_add_mod] + +/-- Periodicity bound: if `n ∣ R_m` with `m ≥ 1` then `a(n) ≤ m`. -/ +private lemma a_le_of_dvd {n m : ℕ} (hm : 1 ≤ m) (h : n ∣ rep m) : a n ≤ m := by + rw [a_eq] + calc ((Finset.Icc 1 n).image (fun k => rep k % n)).card + ≤ ((Finset.Icc 1 m).image (fun k => rep k % n)).card := by + apply Finset.card_le_card + intro x hx + simp only [Finset.mem_image, Finset.mem_Icc] at hx ⊢ + obtain ⟨k, ⟨hk1, -⟩, rfl⟩ := hx + obtain ⟨j, hj1, hjm, hj⟩ := exists_small hm h k hk1 + exact ⟨j, ⟨hj1, hjm⟩, hj⟩ + _ ≤ (Finset.Icc 1 m).card := Finset.card_image_le + _ = m := by simp + +/-- If no residue `R_k % n` is `0` or `2` (and `n ≥ 3`), then `a(n) ≤ n - 2`. -/ +private lemma a_le_sub_two {n : ℕ} (hn : 3 ≤ n) + (h : ∀ k, 1 ≤ k → rep k % n ≠ 0 ∧ rep k % n ≠ 2) : a n ≤ n - 2 := by + rw [a_eq] + calc ((Finset.Icc 1 n).image (fun k => rep k % n)).card + ≤ (((Finset.range n).erase 0).erase 2).card := by + apply Finset.card_le_card + intro x hx + simp only [Finset.mem_image, Finset.mem_Icc] at hx + obtain ⟨k, ⟨hk1, -⟩, rfl⟩ := hx + obtain ⟨h0, h2⟩ := h k hk1 + simp only [Finset.mem_erase, Finset.mem_range] + exact ⟨h2, h0, Nat.mod_lt _ (by omega)⟩ + _ = n - 2 := by + rw [Finset.card_erase_of_mem (by simp; omega), Finset.card_erase_of_mem (by simp; omega)] + simp; omega + +/-- Cancellation: for `n` prime to `10`, `R_i ≡ R_j (mod n)` with `i < j` gives `n ∣ R_{j-i}`. -/ +private lemma dvd_rep_sub {n i j : ℕ} (hn : Nat.Coprime n 10) (hij : i < j) + (h : rep i % n = rep j % n) : n ∣ rep (j - i) := by + have hj : j = (j - i) + i := by omega + rw [hj, rep_add] at h + have h' : 0 + rep i ≡ 10 ^ i * rep (j - i) + rep i [MOD n] := by + simpa [Nat.ModEq] using h + have h0 := Nat.ModEq.add_right_cancel' (rep i) h' + have hd : n ∣ 10 ^ i * rep (j - i) := (Nat.modEq_zero_iff_dvd).1 h0.symm + exact (Nat.Coprime.pow_right i hn).dvd_of_dvd_mul_left hd + +/-- Pigeonhole: if `a(n) < n`, two of `R_1, ..., R_n` agree modulo `n`. -/ +private lemma exists_collision {n : ℕ} (h : a n < n) : + ∃ i j, 1 ≤ i ∧ i < j ∧ j ≤ n ∧ rep i % n = rep j % n := by + rw [a_eq] at h + have hninj : ¬ Set.InjOn (fun k => rep k % n) (Finset.Icc 1 n : Set ℕ) := by + intro hinj + rw [Finset.card_image_of_injOn hinj] at h + simp at h + simp only [Set.InjOn, Finset.coe_Icc, Set.mem_Icc, not_forall] at hninj + obtain ⟨i, ⟨hi1, hin⟩, j, ⟨hj1, hjn⟩, hij, hne⟩ := hninj + rcases lt_or_gt_of_ne hne with hlt | hlt + · exact ⟨i, j, hi1, hlt, hjn, hij⟩ + · exact ⟨j, i, hj1, hlt, hin, hij.symm⟩ + +/-- `a(1) = 1`. -/ +private lemma a_one : a 1 = 1 := by decide +kernel + +/-- `a(2) = 1`. -/ +private lemma a_two : a 2 = 1 := by decide +kernel + +/-- Forward direction: `a(n) = n - 1` forces `n` to be a long period prime. -/ +private lemma forward {n : ℕ} (hn : 1 ≤ n) (ha : a n = n - 1) : IsLongPeriodPrime n := by + rcases Nat.lt_or_ge n 2 with hn2 | hn2 + · have : n = 1 := by omega + subst this + rw [a_one] at ha + simp at ha + by_cases h2 : 2 ∣ n + · by_cases hn4 : n = 2 + · subst hn4; exact ⟨Nat.prime_two, Or.inl rfl⟩ + · exfalso + have hn4' : 4 ≤ n := by obtain ⟨c, hc⟩ := h2; omega + have := a_le_sub_two (n := n) (by omega) (fun k hk => by + have hm : rep k % n % 2 = 1 := by rw [Nat.mod_mod_of_dvd _ h2]; exact rep_mod_two k hk + constructor <;> intro hc <;> rw [hc] at hm <;> simp at hm) + omega + by_cases h5 : 5 ∣ n + · exfalso + have hn5 : 5 ≤ n := Nat.le_of_dvd (by omega) h5 + have := a_le_sub_two (n := n) (by omega) (fun k hk => by + have hm : rep k % n % 5 = 1 := by rw [Nat.mod_mod_of_dvd _ h5]; exact rep_mod_five k hk + constructor <;> intro hc <;> rw [hc] at hm <;> simp at hm) + omega + have hc2 : Nat.Coprime n 2 := (Nat.coprime_comm.1 ((Nat.Prime.coprime_iff_not_dvd + Nat.prime_two).2 h2)) + have hc5 : Nat.Coprime n 5 := (Nat.coprime_comm.1 ((Nat.Prime.coprime_iff_not_dvd + (by norm_num : Nat.Prime 5)).2 h5)) + have hc10 : Nat.Coprime n 10 := by + have := Nat.Coprime.mul_right hc2 hc5 + simpa using this + by_cases h3 : 3 ∣ n + · exfalso + obtain ⟨i, j, hi1, hij, hjn, hr⟩ := exists_collision (n := n) (by omega) + have hd := dvd_rep_sub hc10 hij hr + have hle := a_le_of_dvd (by omega) hd + have hm : j - i = n - 1 := by omega + rw [hm] at hd + have h3r : 3 ∣ rep (n - 1) := dvd_trans h3 hd + have := rep_mod_three (n - 1) + omega + have hc3 : Nat.Coprime n 3 := (Nat.coprime_comm.1 ((Nat.Prime.coprime_iff_not_dvd + Nat.prime_three).2 h3)) + -- Euler: `n ∣ R_{φ(n)}`, so `n - 1 ≤ φ(n) < n`. + have heul : 10 ^ n.totient ≡ 1 [MOD n] := Nat.ModEq.pow_totient hc10.symm + have htpos : 1 ≤ n.totient := Nat.totient_pos.2 (by omega) + have hle := a_le_of_dvd htpos (dvd_rep_of_modEq hc3 heul) + have hlt := Nat.totient_lt n (by omega) + have htot : n.totient = n - 1 := by omega + have hp : n.Prime := (Nat.totient_eq_iff_prime (by omega)).1 htot + refine ⟨hp, Or.inr ?_⟩ + rw [htot] at heul + have hpow : (10 : ZMod n) ^ (n - 1) = 1 := (zmod_pow_iff n (n - 1)).2 heul + have hdvd : orderOf (10 : ZMod n) ∣ n - 1 := orderOf_dvd_of_pow_eq_one hpow + have hpos : 0 < orderOf (10 : ZMod n) := Nat.pos_of_dvd_of_pos hdvd (by omega) + have hd : n ∣ rep (orderOf (10 : ZMod n)) := + dvd_rep_of_modEq hc3 ((zmod_pow_iff _ _).1 (pow_orderOf_eq_one _)) + have h1 := a_le_of_dvd hpos hd + have h2 := Nat.le_of_dvd (by omega) hdvd + omega + +/-- Backward direction: a long period prime `p` has `a(p) = p - 1`. -/ +private lemma backward {p : ℕ} (hp : IsLongPeriodPrime p) : a p = p - 1 := by + obtain ⟨hpr, h2 | hord⟩ := hp + · subst h2; exact a_two + by_cases hp2 : p = 2 + · subst hp2; exact a_two + have hp3 : 3 ≤ p := by have := hpr.two_le; omega + have hpow : (10 : ZMod p) ^ (p - 1) = 1 := by rw [← hord]; exact pow_orderOf_eq_one _ + have hmod : 10 ^ (p - 1) ≡ 1 [MOD p] := (zmod_pow_iff _ _).1 hpow + -- `p` is prime to `10`. + have hc10 : Nat.Coprime p 10 := by + have hg := Nat.ModEq.gcd_eq hmod + have hcop : Nat.Coprime (10 ^ (p - 1)) p := by + unfold Nat.Coprime; rw [hg]; simp + exact ((Nat.coprime_pow_left_iff (by omega) _ _).1 hcop).symm + -- `p ≠ 3`. + have hne3 : p ≠ 3 := by + intro h3 + subst h3 + have : (10 : ZMod 3) ^ 1 ≠ 1 := pow_ne_one_of_lt_orderOf one_ne_zero (by rw [hord]; norm_num) + exact this (by decide) + have hc3 : Nat.Coprime p 3 := (Nat.coprime_primes hpr Nat.prime_three).2 hne3 + apply le_antisymm + · exact a_le_of_dvd (by omega) (dvd_rep_of_modEq hc3 hmod) + · -- `R_1, ..., R_{p-1}` are distinct modulo `p`. + have hinj : Set.InjOn (fun k => rep k % p) (Finset.Icc 1 (p - 1) : Set ℕ) := by + have key : ∀ i j, 1 ≤ i → i < j → j ≤ p - 1 → rep i % p ≠ rep j % p := by + intro i j hi hij hj hr + have hd := dvd_rep_sub hc10 hij hr + have hz := (zmod_pow_iff p (j - i)).2 (modEq_of_dvd_rep hd) + exact pow_ne_one_of_lt_orderOf (by omega) (by rw [hord]; omega) hz + intro i hi j hj hr + simp only [Finset.coe_Icc, Set.mem_Icc] at hi hj + rcases lt_trichotomy i j with hlt | heq | hlt + · exact absurd hr (key i j hi.1 hlt hj.2) + · exact heq + · exact absurd hr.symm (key j i hj.1 hlt hi.2) + rw [a_eq] + calc p - 1 = (Finset.Icc 1 (p - 1)).card := by simp + _ = ((Finset.Icc 1 (p - 1)).image (fun k => rep k % p)).card := + (Finset.card_image_of_injOn hinj).symm + _ ≤ ((Finset.Icc 1 p).image (fun k => rep k % p)).card := by + apply Finset.card_le_card + apply Finset.image_subset_image + exact Finset.Icc_subset_Icc le_rfl (by omega) + +/-- **Eu's conjecture (A335012).** For every `n ≥ 1`, the repunits `R_1, ..., R_n` leave exactly +`n - 1` distinct remainders modulo `n` iff `n` is a long period prime. -/ +theorem result : statement := fun _ hn => ⟨forward hn, backward⟩ + +end Math0.Frontier.A335012 + +#math0_settles Math0.Frontier.A335012.result Math0.Statements.A335012.statement diff --git a/lean/Math0/Frontier/OEIS/A338885.lean b/lean/Math0/Frontier/OEIS/A338885.lean new file mode 100644 index 0000000..0999b26 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A338885.lean @@ -0,0 +1,65 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A338885 +import Math0.Audit + +/-! +# A338885: the smallest number in row 655 is not A228286(655) + +Kagey's conjecture says that the smallest `k` for which a diagonal lattice rectangle touches all +four sides of an `n X k` box is `A228286 n`. It fails at `n = 655`. + +* `104` is in row `655`: the rectangle with vertices `(4, 0)`, `(655, 42)`, `(651, 104)`, + `(0, 62)` has side vectors `u = (651, 42)` and `v = (-4, 62)`, which are perpendicular since + `651 * (-4) + 42 * 62 = -2604 + 2604 = 0`; it lies in `[0, 655] × [0, 104]`, touches all four + sides, and has no horizontal side. +* Every value `x + y * z` with `x, y, z ≥ 1` and `x * y + z = 655` is at least `105` (in fact + the minimum `A228286 655` is `115`). If `x + y * z ≤ 104` then `x ≤ 104` and + `y ≤ y * z ≤ 104`, and a kernel-checked search over the `104 × 104` pairs `(x, y)` (with + `z = 655 - x * y`) shows that this never happens. + +Hence `A228286 655 ≥ 105 > 104`, so `A228286 655` is not a lower bound of row `655`. +-/ + +namespace Math0.Frontier.A338885 +open Math0.Statements.A338885 + +/-- Finite search: for `1 ≤ x, y ≤ 104` with `x * y < 655`, the value +`x + y * (655 - x * y)` is at least `105` (kernel-checked). -/ +private theorem search : ∀ x < 105, ∀ y < 105, 0 < x → 0 < y → x * y < 655 → + 105 ≤ x + y * (655 - x * y) := by + decide +kernel + +/-- Every element of `A228286Set 655` is at least `105`. -/ +private theorem ge_of_mem {m : ℕ} (hm : m ∈ A228286Set 655) : 105 ≤ m := by + obtain ⟨x, y, z, hx, hy, hz, hsum, rfl⟩ := hm + by_contra hlt + have hyz : y ≤ y * z := Nat.le_mul_of_pos_right y hz + have hz' : z = 655 - x * y := by omega + have h := search x (by omega) y (by omega) hx hy (by omega) + rw [← hz'] at h + omega + +/-- The explicit diagonal lattice rectangle with vertices `(4, 0)`, `(655, 42)`, `(651, 104)`, +`(0, 62)` shows that `104` is in row `655`. -/ +private theorem inRow_655_104 : InRow 655 104 := by + refine ⟨4, 0, 651, 42, -4, 62, by norm_num, by norm_num, by norm_num, ?_, ?_, ?_, ?_, ?_⟩ + · simp only [vertices, InBox, List.mem_cons, List.not_mem_nil, or_false, forall_eq_or_imp, + forall_eq] + norm_num + · exact ⟨(0, 62), by simp [vertices], by norm_num⟩ + · exact ⟨(655, 42), by simp [vertices], by norm_num⟩ + · exact ⟨(4, 0), by simp [vertices], by norm_num⟩ + · exact ⟨(651, 104), by simp [vertices], by norm_num⟩ + +/-- Kagey's conjecture fails at `n = 655`: `104` is in row `655` but `A228286 655 ≥ 105`. -/ +theorem result : ¬ statement := by + intro h + have hle : A228286 655 ≤ 104 := (h 655 (by norm_num)).2 inRow_655_104 + have hge : 105 ≤ A228286 655 := ge_of_mem (isLeast_A228286 (by norm_num)).1 + omega + +end Math0.Frontier.A338885 + +#math0_settles Math0.Frontier.A338885.result Math0.Statements.A338885.statement diff --git a/lean/Math0/Frontier/OEIS/A341761.lean b/lean/Math0/Frontier/OEIS/A341761.lean new file mode 100644 index 0000000..2aa2161 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A341761.lean @@ -0,0 +1,274 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A341761 +import Math0.Audit + +/-! +# The subword complexity polynomial `S(n, x)` has leading coefficient `n(n+1)/2` + +We prove Shiyao Guo's conjecture from OEIS A341761: `S(n, x)`, the sum of the subword +complexities of all words of length `n` over an `x`-letter alphabet, is a polynomial in `x` +whose coefficient of `x^n` is `n(n+1)/2`. + +**Patterns.** For a word `w : Fin n → α`, let `pat w i` be the first position carrying the same +letter as position `i`. Then `pat w i = pat w j ↔ w i = w j`, so `pat (pat w) = pat w`, and +`w = w ∘ pat w` with `w` injective on the letters of `pat w`. Since an injective relabelling of the +letters does not change the set of factors up to a bijection, `complexity w = complexity (pat w)`. + +**Counting fibres.** For a pattern `p` (a fixed point `pat p = p`) with `k` fixed points +(first occurrences), the words `w : Fin n → Fin x` with `pat w = p` are in bijection with the +injections from the `k` first-occurrence positions into `Fin x`, so there are +`x(x-1)⋯(x-k+1)` of them. Hence +`S(n, x) = ∑_{p = pat p} complexity(p) · x.descFactorial (#fix p)`, which is the value at `x` of +the polynomial `P = ∑_{p = pat p} complexity(p) · descPochhammer ℚ (#fix p)`. + +**Leading coefficient.** `descPochhammer ℚ k` is monic of degree `k ≤ n`; `k = n` only for the +identity pattern. Its word `0 1 ⋯ (n-1)` has pairwise distinct letters, so its `n(n+1)/2` +nonempty factors are pairwise distinct (by induction: the nonempty prefixes of `a :: l` start with +`a ∉ l` and are disjoint from the factors of `l`). So `P.coeff n = n(n+1)/2`. +-/ + +namespace Math0.Frontier.A341761 +open Math0.Statements.A341761 +open Polynomial Finset + +/-- The canonical pattern of a word: each position is sent to the first position carrying the +same letter. -/ +private def pat {n : ℕ} {α : Type*} [DecidableEq α] (w : Fin n → α) (i : Fin n) : Fin n := + (univ.filter fun j => w j = w i).min' ⟨i, by simp⟩ + +/-- Position `pat w i` carries the same letter as position `i`. -/ +private lemma pat_spec {n : ℕ} {α : Type*} [DecidableEq α] (w : Fin n → α) (i : Fin n) : + w (pat w i) = w i := by + have := Finset.min'_mem (univ.filter fun j => w j = w i) ⟨i, by simp⟩ + exact (Finset.mem_filter.1 this).2 + +/-- `pat w` depends only on which positions of `w` carry equal letters. -/ +private lemma pat_congr {n : ℕ} {α β : Type*} [DecidableEq α] [DecidableEq β] + (w : Fin n → α) (v : Fin n → β) (h : ∀ i j, w i = w j ↔ v i = v j) : pat w = pat v := by + funext i + unfold pat + congr 1 + ext j + simp [h] + +/-- Two positions have the same first occurrence iff they carry the same letter. -/ +private lemma pat_eq_iff {n : ℕ} {α : Type*} [DecidableEq α] (w : Fin n → α) (i j : Fin n) : + pat w i = pat w j ↔ w i = w j := by + constructor + · intro hij + rw [← pat_spec w i, hij, pat_spec w j] + · intro hij + unfold pat + congr 1 + ext k + simp [hij] + +/-- `pat` is idempotent. -/ +private lemma pat_pat {n : ℕ} {α : Type*} [DecidableEq α] (w : Fin n → α) : + pat (pat w) = pat w := + pat_congr _ _ (fun i j => pat_eq_iff w i j) + +/-- The identity word is its own pattern. -/ +private lemma pat_id (n : ℕ) : pat (id : Fin n → Fin n) = id := by + funext i + exact pat_spec id i + +/-- Mapping by a function injective on a set `s` is injective on lists with letters in `s`. -/ +private lemma map_injOn_lists {α β : Type*} (f : α → β) (s : Set α) (hf : Set.InjOn f s) : + ∀ u v : List α, (∀ a ∈ u, a ∈ s) → (∀ a ∈ v, a ∈ s) → u.map f = v.map f → u = v + | [], [], _, _, _ => rfl + | [], b :: v, _, _, h => by simp at h + | a :: u, [], _, _, h => by simp at h + | a :: u, b :: v, hu, hv, h => by + simp only [List.map_cons, List.cons.injEq] at h + rw [hf (hu a (by simp)) (hv b (by simp)) h.1, + map_injOn_lists f s hf u v (fun c hc => hu c (by simp [hc])) + (fun c hc => hv c (by simp [hc])) h.2] + +/-- Relabelling the letters of a word injectively does not change its subword complexity. -/ +private lemma complexity_map {α β : Type*} [DecidableEq α] [DecidableEq β] (f : α → β) + (l : List α) (hf : Set.InjOn f {a | a ∈ l}) : complexity (l.map f) = complexity l := by + unfold complexity + have : factors (l.map f) = (factors l).image (List.map f) := by + ext u + simp only [mem_factors, Finset.mem_image] + constructor + · rintro ⟨hu, hinf⟩ + obtain ⟨v, hv, rfl⟩ := List.infix_map_iff.1 hinf + exact ⟨v, ⟨by simpa using hu, hv⟩, rfl⟩ + · rintro ⟨v, ⟨hv, hinf⟩, rfl⟩ + exact ⟨by simpa using hv, hinf.map f⟩ + rw [this, Finset.card_image_of_injOn] + intro u hu v hv huv + rw [Finset.mem_coe, mem_factors] at hu hv + exact map_injOn_lists f _ hf u v (fun a ha => hu.2.subset ha) (fun a ha => hv.2.subset ha) huv + +/-- A word has the same subword complexity as its pattern. -/ +private lemma complexity_pat {n x : ℕ} (w : Fin n → Fin x) : + complexity (List.ofFn w) = complexity (List.ofFn (pat w)) := by + have h1 : List.ofFn w = (List.ofFn (pat w)).map w := by + rw [List.map_ofFn] + congr 1 + funext i + exact (pat_spec w i).symm + rw [h1, complexity_map] + intro a ha b hb hab + simp only [Set.mem_ofPred_eq, List.mem_ofFn] at ha hb + obtain ⟨i, rfl⟩ := ha + obtain ⟨j, rfl⟩ := hb + rw [pat_spec w i, pat_spec w j] at hab + exact (pat_eq_iff w i j).2 hab + +/-- For a pattern `p`, `p (p i) = p i`. -/ +private lemma pat_idem_apply {n : ℕ} (p : Fin n → Fin n) (hp : pat p = p) (i : Fin n) : + p (p i) = p i := by + have := pat_spec p i + rwa [hp] at this + +/-- Words with pattern `p` correspond to injections of the first-occurrence positions of `p` +into the alphabet. -/ +private def fiberEquiv {n x : ℕ} (p : Fin n → Fin n) (hp : pat p = p) : + {w : Fin n → Fin x // pat w = p} ≃ ({i : Fin n // p i = i} ↪ Fin x) where + toFun w := ⟨fun i => w.1 i.1, by + rintro ⟨i, hi⟩ ⟨j, hj⟩ h + apply Subtype.ext + have := (pat_eq_iff w.1 i j).2 h + rw [w.2] at this + exact hi.symm.trans (this.trans hj)⟩ + invFun e := ⟨fun i => e ⟨p i, pat_idem_apply p hp i⟩, by + calc pat (fun i => e ⟨p i, pat_idem_apply p hp i⟩) = pat p := + pat_congr _ _ (fun i j => by rw [e.injective.eq_iff, Subtype.mk.injEq]) + _ = p := hp⟩ + left_inv w := by + apply Subtype.ext + funext i + have := pat_spec w.1 i + rw [w.2] at this + exact this + right_inv e := by + refine Function.Embedding.ext fun ⟨i, hi⟩ => ?_ + show e ⟨p i, _⟩ = e ⟨i, hi⟩ + exact congrArg e (Subtype.ext hi) + +/-- There are `x.descFactorial k` words over `Fin x` with pattern `p`, where `k` is the number +of first-occurrence positions of `p`. -/ +private lemma card_fiber {n x : ℕ} (p : Fin n → Fin n) (hp : pat p = p) : + (univ.filter fun w : Fin n → Fin x => pat w = p).card = + x.descFactorial (univ.filter fun i => p i = i).card := by + rw [← Fintype.card_subtype, Fintype.card_congr (fiberEquiv p hp), Fintype.card_embedding_eq, + Fintype.card_fin, Fintype.card_subtype] + +/-- `S(n, x)` as a sum over patterns of complexity times a falling factorial in `x`. -/ +private lemma S_eq (n x : ℕ) : S n x = ∑ p : Fin n → Fin n, + if pat p = p then complexity (List.ofFn p) * x.descFactorial (univ.filter fun i => p i = i).card + else 0 := by + unfold S + rw [← Finset.sum_fiberwise (univ : Finset (Fin n → Fin x)) pat] + refine Finset.sum_congr rfl fun p _ => ?_ + rw [Finset.sum_congr rfl (g := fun _ => complexity (List.ofFn p)) (fun w hw => by + rw [complexity_pat w, (Finset.mem_filter.1 hw).2])] + rw [Finset.sum_const, smul_eq_mul] + split_ifs with hp + · rw [card_fiber p hp, mul_comm] + · have : (univ.filter fun w : Fin n → Fin x => pat w = p) = ∅ := by + ext w + simp only [Finset.mem_filter, Finset.mem_univ, true_and, Finset.notMem_empty, iff_false] + intro hw + apply hp + rw [← hw, pat_pat] + rw [this, Finset.card_empty, zero_mul] + +/-- `toFinset` of a mapped list is the image of the `toFinset`. -/ +private lemma toFinset_map' {α β : Type*} [DecidableEq α] [DecidableEq β] (f : α → β) + (L : List α) : (L.map f).toFinset = L.toFinset.image f := by + ext; simp + +/-- A list of length `m` has `m + 1` distinct prefixes. -/ +private lemma card_inits {α : Type*} [DecidableEq α] : + ∀ l : List α, l.inits.toFinset.card = l.length + 1 + | [] => by simp + | a :: l => by + rw [List.inits_cons, List.toFinset_cons, toFinset_map', Finset.card_insert_of_notMem, + Finset.card_image_of_injective _ List.cons_injective, card_inits l, List.length_cons] + simp + +/-- A list of length `m` has `m` distinct nonempty prefixes. -/ +private lemma card_inits_tail {α : Type*} [DecidableEq α] : + ∀ l : List α, l.inits.tail.toFinset.card = l.length + | [] => by simp + | a :: l => by + rw [List.inits_cons, List.tail_cons, toFinset_map', + Finset.card_image_of_injective _ List.cons_injective, card_inits l, List.length_cons] + +/-- A word of length `m` with pairwise distinct letters has `m(m+1)/2` distinct nonempty +factors. -/ +private lemma complexity_nodup {α : Type*} [DecidableEq α] : + ∀ l : List α, l.Nodup → 2 * complexity l = l.length * (l.length + 1) + | [], _ => by simp [complexity, factors] + | a :: l, h => by + have hfac : factors (a :: l) = (a :: l).inits.tail.toFinset ∪ factors l := by + simp only [factors, List.tails_cons, List.flatMap_cons, List.toFinset_append] + have hdisj : Disjoint (a :: l).inits.tail.toFinset (factors l) := by + rw [Finset.disjoint_left] + intro u hu hu' + rw [List.mem_toFinset, mem_inits_tail] at hu + rw [mem_factors] at hu' + obtain ⟨hne, hpre⟩ := hu + rcases u with _ | ⟨b, v⟩ + · exact hne rfl + · obtain ⟨rfl, _⟩ := List.cons_prefix_cons.1 hpre + exact (List.nodup_cons.1 h).1 (hu'.2.subset (List.mem_cons_self ..)) + have ih := complexity_nodup l (List.nodup_cons.1 h).2 + unfold complexity at ih ⊢ + rw [hfac, Finset.card_union_of_disjoint hdisj, card_inits_tail, mul_add, ih, List.length_cons] + ring + +/-- The number of first-occurrence positions (fixed points) of a pattern. -/ +private def nfix {n : ℕ} (p : Fin n → Fin n) : ℕ := (univ.filter fun i => p i = i).card + +/-- **Guo's conjecture (A341761).** For every `n`, `S(n, x)` is given by a polynomial in `x` +whose coefficient of `x^n` is `n(n+1)/2`. -/ +theorem result : statement := by + intro n + refine ⟨∑ p : Fin n → Fin n, if pat p = p then + C (complexity (List.ofFn p) : ℚ) * descPochhammer ℚ (nfix p) else 0, ?_, ?_⟩ + · intro x + rw [S_eq, eval_finsetSum] + push_cast + refine Finset.sum_congr rfl fun p _ => ?_ + split_ifs + · rw [eval_mul, eval_C, descPochhammer_eval_eq_descFactorial] + rfl + · simp + · rw [finsetSum_coeff, Finset.sum_eq_single (id : Fin n → Fin n)] + · rw [if_pos (pat_id n), coeff_C_mul] + have hk : nfix (id : Fin n → Fin n) = n := by simp [nfix] + have h1 : (descPochhammer ℚ n).coeff n = 1 := by + have := (monic_descPochhammer ℚ n).coeff_natDegree + rwa [descPochhammer_natDegree] at this + rw [hk, h1, mul_one] + have h2 := complexity_nodup (List.ofFn (id : Fin n → Fin n)) + (List.nodup_ofFn.2 Function.injective_id) + rw [List.length_ofFn] at h2 + have h3 : (2 : ℚ) * (complexity (List.ofFn (id : Fin n → Fin n)) : ℚ) = n * (n + 1) := by + exact_mod_cast h2 + linarith + · intro p _ hp + split_ifs with hpp + · rw [coeff_C_mul] + obtain ⟨i, hi⟩ := Function.ne_iff.1 hp + have hlt : nfix p < n := by + have hss : (univ.filter fun j => p j = j) ⊂ univ := + Finset.filter_ssubset.2 ⟨i, Finset.mem_univ i, hi⟩ + have := Finset.card_lt_card hss + simpa [nfix] using this + rw [coeff_eq_zero_of_natDegree_lt (by rwa [descPochhammer_natDegree]), mul_zero] + · simp + · intro h + exact absurd (Finset.mem_univ _) h + +end Math0.Frontier.A341761 + +#math0_settles Math0.Frontier.A341761.result Math0.Statements.A341761.statement diff --git a/lean/Math0/Frontier/OEIS/A342645.lean b/lean/Math0/Frontier/OEIS/A342645.lean new file mode 100644 index 0000000..b612002 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A342645.lean @@ -0,0 +1,2507 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A342645 +import Math0.Audit + +/-! +# A342645: the diagonals of the eventual Mahonian-column polynomials + +We prove both conjectures of A342645 (Kagey). + +*Diagonals.* For `x ≥ n` the Mahonian number `mahonian x n` equals +`P_n(x) = ∑_{a ≤ n} e_a binom(x+n-a-1, n-a)`, where `∏_{i ≥ 1} (1 - q^i) = ∑ e_a q^a` +(from `∏_{i q.Prime ∧ (q - 1) ∣ 2 * k) with hS + have hsplit : (∑ q ∈ S, (1 : ℚ) / q) = + (if (p - 1) ∣ 2 * k then 1 / (p : ℚ) else 0) + ∑ q ∈ S.erase p, (1 : ℚ) / q := by + by_cases hd : (p - 1) ∣ 2 * k + · have hpS : p ∈ S := by + rw [hS, mem_filter, mem_range] + refine ⟨?_, hp.out, hd⟩ + have := Nat.le_of_dvd (by omega) hd + omega + rw [if_pos hd, ← add_sum_erase _ _ hpS] + · have hpS : p ∉ S := by + rw [hS, mem_filter]; tauto + rw [if_neg hd, erase_eq_of_notMem hpS, zero_add] + refine ⟨(m : ℚ) - ∑ q ∈ S.erase p, (1 : ℚ) / q, ?_, ?_⟩ + · refine le_trans (padicNorm.sub) (max_le (padicNorm.of_int m) ?_) + refine padicNorm.sum_le' (fun q hq => ?_) zero_le_one + rw [mem_erase, hS, mem_filter] at hq + rw [padicNorm_one_div_prime hq.2.2.1 hq.1] + · have : bernoulli (2 * k) = (m : ℚ) - ∑ q ∈ S, (1 : ℚ) / q := by + rw [hm]; ring + rw [this, hsplit]; ring + +/-- `|B_n|_p ≤ p` for every `n` (von Staudt–Clausen). -/ +private lemma bern_norm_le_p (n : ℕ) : padicNorm p (bernoulli n) ≤ p := by + have hp1 : (1 : ℚ) ≤ p := by exact_mod_cast hp.out.one_lt.le + rcases Nat.even_or_odd n with ⟨k, hk⟩ | hodd + · rcases Nat.eq_zero_or_pos k with rfl | hkpos + · simp at hk; subst hk; simp [bernoulli_zero, hp1] + · obtain ⟨z, hz, hb⟩ := vsc_decomp (p := p) k hkpos + rw [show n = 2 * k by omega, hb] + refine le_trans padicNorm.sub (max_le (hz.trans hp1) ?_) + split_ifs + · rw [padicNorm.div, padicNorm.one, padicNorm.padicNorm_p_of_prime]; simp + · simp + · rcases Nat.eq_or_lt_of_le hodd.pos with h1 | h1 + · subst h1; rw [bernoulli_one, show (-1 / 2 : ℚ) = -(2 : ℚ)⁻¹ by ring, padicNorm.neg] + exact padicNorm_two_inv_le + · rw [bernoulli_eq_zero_of_odd hodd h1]; simp + +/-- If `p - 1 ∤ n` then `B_n` is `p`-integral (von Staudt–Clausen). -/ +private lemma bern_norm_le_one (n : ℕ) (h : ¬ (p - 1) ∣ n) : padicNorm p (bernoulli n) ≤ 1 := by + rcases Nat.even_or_odd n with ⟨k, hk⟩ | hodd + · rcases Nat.eq_zero_or_pos k with rfl | hkpos + · simp at hk; subst hk; exact absurd (dvd_zero _) h + · obtain ⟨z, hz, hb⟩ := vsc_decomp (p := p) k hkpos + rw [show n = 2 * k by omega] at h ⊢ + rw [hb, if_neg h, sub_zero]; exact hz + · rcases Nat.eq_or_lt_of_le hodd.pos with h1 | h1 + · subst h1 + have h2 : p ≠ 2 := by rintro rfl; exact h (by simp) + rw [bernoulli_one, show (-1 / 2 : ℚ) = -(2 : ℚ)⁻¹ by ring, padicNorm.neg, + padicNorm_two_inv_odd h2] + · rw [bernoulli_eq_zero_of_odd hodd h1]; simp + +/-- If `p - 1 ∣ n` with `n > 0` even, then `|B_n|_p = p` (von Staudt–Clausen). -/ +private lemma bern_norm_eq_p (n : ℕ) (h : (p - 1) ∣ n) (he : Even n) (hn : 0 < n) : + padicNorm p (bernoulli n) = p := by + obtain ⟨k, hk⟩ := he + have hkpos : 0 < k := by omega + obtain ⟨z, hz, hb⟩ := vsc_decomp (p := p) k hkpos + rw [show n = 2 * k by omega] at h ⊢ + rw [hb, if_pos h] + have h1p : padicNorm p (1 / (p : ℚ)) = p := by + rw [padicNorm.div, padicNorm.one, padicNorm.padicNorm_p_of_prime]; simp + have hlt : padicNorm p z < padicNorm p (1 / (p : ℚ)) := by + rw [h1p]; exact lt_of_le_of_lt hz (by exact_mod_cast hp.out.one_lt) + rw [sub_eq_add_neg, padicNorm.add_eq_max_of_ne, padicNorm.neg, h1p, max_eq_right] + · rw [← h1p]; exact hlt.le + · rw [padicNorm.neg]; exact hlt.ne + +end VonStaudt + +section PowerSums +open Finset + +variable {p : ℕ} [hp : Fact p.Prime] + +/-- A primitive root modulo `p`: `a^n ≡ 1 (mod p)` forces `p - 1 ∣ n`. -/ +private lemma exists_prim_root : ∃ a : ℕ, ¬ p ∣ a ∧ + ∀ n : ℕ, (p : ℤ) ∣ (a : ℤ) ^ n - 1 → (p - 1) ∣ n := by + obtain ⟨g, hg⟩ := IsCyclic.exists_generator (α := (ZMod p)ˣ) + have hord : orderOf g = p - 1 := by + rw [orderOf_eq_card_of_forall_mem_zpowers hg, Nat.card_eq_fintype_card, + ZMod.card_units_eq_totient, Nat.totient_prime hp.out] + refine ⟨(g : ZMod p).val, ?_, ?_⟩ + · intro hd + have : (((g : ZMod p).val : ℕ) : ZMod p) = 0 := (ZMod.natCast_eq_zero_iff _ _).2 hd + rw [ZMod.natCast_zmod_val] at this + exact g.ne_zero this + · intro n hn + have h1 : (g : ZMod p) ^ n = 1 := by + have := (ZMod.intCast_zmod_eq_zero_iff_dvd _ p).2 hn + push_cast at this + rw [ZMod.natCast_zmod_val] at this + exact sub_eq_zero.1 this + have : g ^ n = 1 := Units.ext (by simpa using h1) + rw [← hord]; exact orderOf_dvd_of_pow_eq_one this + +/-- The power sum `∑ j^n` over `0 ≤ j < p^e` with `p ∤ j`. -/ +private def psT (n e : ℕ) : ℤ := ∑ j ∈ (range (p ^ e)).filter (fun j => ¬ p ∣ j), (j : ℤ) ^ n + +/-- The power sum `∑ j^n` over `0 ≤ j < p^e`. -/ +private def psS (n e : ℕ) : ℤ := ∑ j ∈ range (p ^ e), (j : ℤ) ^ n + +/-- Multiplication by `a` with `p ∤ a` permutes the residues prime to `p` modulo `p^e`. -/ +private lemma psT_perm (a n e : ℕ) (ha : ¬ p ∣ a) : + ∑ j ∈ (range (p ^ e)).filter (fun j => ¬ p ∣ j), (((a * j) % p ^ e : ℕ) : ℤ) ^ n = + psT (p := p) n e := by + set U := (range (p ^ e)).filter (fun j => ¬ p ∣ j) + have hN : 0 < p ^ e := pow_pos hp.out.pos e + have hcop : Nat.gcd (p ^ e) a = 1 := by + apply Nat.Coprime.pow_left + exact (Nat.Prime.coprime_iff_not_dvd hp.out).2 ha + have hmaps : Set.MapsTo (fun j => (a * j) % p ^ e) (U : Set ℕ) (U : Set ℕ) := by + intro j hj + simp only [U, coe_filter, mem_range, Set.mem_ofPred_eq] at hj ⊢ + refine ⟨Nat.mod_lt _ hN, ?_⟩ + intro hd + rcases Nat.eq_zero_or_pos e with he | he + · subst he; rw [pow_zero] at hj + have : j = 0 := by omega + subst this; exact absurd (dvd_zero p) hj.2 + have h1 : p ∣ p ^ e := dvd_pow_self p he.ne' + have h2 : p ∣ a * j := by + have := Nat.mod_add_div (a * j) (p ^ e) + rw [← this]; exact dvd_add hd (dvd_mul_of_dvd_left h1 _) + rcases (Nat.Prime.dvd_mul hp.out).1 h2 with h | h + · exact ha h + · exact hj.2 h + have hinj : Set.InjOn (fun j => (a * j) % p ^ e) (U : Set ℕ) := by + intro j hj k hk hjk + simp only [U, coe_filter, mem_range, Set.mem_ofPred_eq] at hj hk + have := Nat.ModEq.cancel_left_of_coprime hcop hjk + unfold Nat.ModEq at this + rwa [Nat.mod_eq_of_lt hj.1, Nat.mod_eq_of_lt hk.1] at this + have hsurj := Finset.surjOn_of_injOn_of_card_le _ hmaps hinj le_rfl + unfold psT + exact Finset.sum_nbij _ (fun j hj => hmaps hj) hinj hsurj (fun _ _ => rfl) + +/-- Voronoi-type congruence: `p^(e + min(v_p(n), e))` divides the reduced power sum when `a^n ≢ 1 (mod p)`. -/ +private lemma psT_dvd (a n e : ℕ) (ha : ¬ p ∣ a) (hprim : ¬ (p : ℤ) ∣ (a : ℤ) ^ n - 1) : + (p : ℤ) ^ (e + min (padicValNat p n) e) ∣ psT (p := p) n e := by + set D : ℤ := (p : ℤ) ^ (e + min (padicValNat p n) e) + set N : ℕ := p ^ e + have hDN : D ∣ (N : ℤ) * n := by + simp only [D, N, pow_add, Nat.cast_pow] + apply mul_dvd_mul_left + have : (p : ℤ) ^ (padicValNat p n) ∣ (n : ℤ) := by exact_mod_cast pow_padicValNat_dvd + exact (pow_dvd_pow _ (min_le_left _ _)).trans this + have hDN2 : D ∣ (N : ℤ) ^ 2 := by + simp only [D, N, Nat.cast_pow, ← pow_mul] + apply pow_dvd_pow; omega + have key : D ∣ ((a : ℤ) ^ n - 1) * psT (p := p) n e := by + have hsum : ((a : ℤ) ^ n - 1) * psT (p := p) n e = + ∑ j ∈ (range (p ^ e)).filter (fun j => ¬ p ∣ j), + (((a * j : ℕ) : ℤ) ^ n - (((a * j) % p ^ e : ℕ) : ℤ) ^ n) := by + rw [sum_sub_distrib, psT_perm a n e ha, sub_mul, one_mul, psT, mul_sum] + congr 1 + refine sum_congr rfl (fun j _ => ?_) + push_cast; ring + rw [hsum] + refine dvd_sum (fun j _ => ?_) + set r : ℤ := (((a * j) % p ^ e : ℕ) : ℤ) + set q : ℤ := (((a * j) / p ^ e : ℕ) : ℤ) + have hdecomp : ((a * j : ℕ) : ℤ) = r + (N : ℤ) * q := by + simp only [r, q, N] + exact_mod_cast (Nat.mod_add_div (a * j) (p ^ e)).symm + rw [hdecomp] + have h2 := sq_dvd_add_pow_sub_sub ((N : ℤ) * q) r n + have : (r + N * q) ^ n - r ^ n = + ((r + N * q) ^ n - r ^ (n - 1) * (N * q) * n - r ^ n) + r ^ (n - 1) * (N * q) * n := by + ring + rw [this] + refine dvd_add ?_ ?_ + · exact hDN2.trans ((pow_dvd_pow_of_dvd (dvd_mul_right _ _) 2).trans h2) + · have : r ^ (n - 1) * (N * q) * n = ((N : ℤ) * n) * (r ^ (n - 1) * q) := by ring + rw [this]; exact dvd_mul_of_dvd_left hDN _ + have hcop : IsCoprime D ((a : ℤ) ^ n - 1) := by + apply IsCoprime.pow_left + exact (Irreducible.coprime_iff_not_dvd (Nat.prime_iff_prime_int.1 hp.out).irreducible).2 hprim + exact hcop.dvd_of_dvd_mul_left key + +/-- Splitting the full power sum according to divisibility by `p`. -/ +private lemma psS_succ (n e : ℕ) (_hn : 0 < n) : + psS (p := p) n (e + 1) = psT (p := p) n (e + 1) + (p : ℤ) ^ n * psS (p := p) n e := by + unfold psS psT + rw [← sum_filter_add_sum_filter_not (range (p ^ (e + 1))) (fun j => p ∣ j), add_comm] + congr 1 + rw [mul_sum] + have : (range (p ^ (e + 1))).filter (fun j => p ∣ j) = (range (p ^ e)).map + ⟨fun i => p * i, fun x y h => Nat.eq_of_mul_eq_mul_left hp.out.pos h⟩ := by + ext j + simp only [mem_filter, mem_range, mem_map] + constructor + · rintro ⟨hj, ⟨i, rfl⟩⟩ + refine ⟨i, ?_, rfl⟩ + rw [pow_succ'] at hj + exact Nat.lt_of_mul_lt_mul_left hj + · rintro ⟨i, hi, rfl⟩ + refine ⟨?_, dvd_mul_right _ _⟩ + rw [pow_succ'] + exact Nat.mul_lt_mul_of_pos_left hi hp.out.pos + rw [this, sum_map] + refine sum_congr rfl (fun i _ => ?_) + show (((p * i : ℕ) : ℤ)) ^ n = _ + push_cast; ring + +/-- `p^(e + min(v_p(n), e))` divides `∑_{j < p^e} j^n` when `a^n ≢ 1 (mod p)`. -/ +private lemma psS_dvd (a n : ℕ) (hn : 0 < n) (ha : ¬ p ∣ a) (hprim : ¬ (p : ℤ) ∣ (a : ℤ) ^ n - 1) (e : ℕ) : + (p : ℤ) ^ (e + min (padicValNat p n) e) ∣ psS (p := p) n e := by + induction e with + | zero => simp [psS, zero_pow hn.ne'] + | succ e ih => + rw [psS_succ n e hn] + refine dvd_add (psT_dvd a n (e + 1) ha hprim) ?_ + have hle : e + 1 + min (padicValNat p n) (e + 1) ≤ n + (e + min (padicValNat p n) e) := by + rcases le_or_gt (padicValNat p n) e with h | h + · rw [min_eq_left h, min_eq_left (by omega)]; omega + · rw [min_eq_right h.le, min_eq_right (by omega)] + have : 2 ≤ n := by + have h1 : 1 ≤ padicValNat p n := by omega + have h2 : p ∣ n := dvd_of_one_le_padicValNat h1 + have := Nat.le_of_dvd hn h2 + have := hp.out.two_le + omega + omega + exact (pow_dvd_pow _ hle).trans (by rw [pow_add]; exact mul_dvd_mul_left _ ih) + +end PowerSums + +section Adams +open Finset + +variable {p : ℕ} [hp : Fact p.Prime] + +omit hp in +/-- `|m|_p = p^(-v_p(m))` for `m > 0`. -/ +private lemma padicNorm_natCast_eq (m : ℕ) (hm : 0 < m) : + padicNorm p (m : ℚ) = ((p : ℚ) ^ (padicValNat p m))⁻¹ := by + rw [padicNorm.eq_zpow_of_nonzero (by exact_mod_cast hm.ne'), padicValRat.of_nat, zpow_neg, + zpow_natCast] + +/-- `|p^e|_p = p^(-e)`. -/ +private lemma padicNorm_prime_pow (e : ℕ) : padicNorm p ((p : ℚ) ^ e) = ((p : ℚ) ^ e)⁻¹ := by + have := padicNorm_natCast_eq (p := p) (p ^ e) (pow_pos hp.out.pos e) + rw [padicValNat.prime_pow] at this + exact_mod_cast this + +/-- `|1/m|_p ≤ m` for `m > 0`. -/ +private lemma padicNorm_one_div_nat_le (m : ℕ) (hm : 0 < m) : padicNorm p (1 / (m : ℚ)) ≤ m := by + rw [padicNorm.div, padicNorm.one, padicNorm_natCast_eq m hm, one_div, inv_inv] + exact_mod_cast Nat.le_of_dvd hm pow_padicValNat_dvd + +/-- If `p^k ∣ z` then `|z|_p ≤ p^(-k)`. -/ +private lemma padicNorm_int_le_of_dvd (z : ℤ) (k : ℕ) (h : (p : ℤ) ^ k ∣ z) : + padicNorm p (z : ℚ) ≤ ((p : ℚ) ^ k)⁻¹ := by + have := (padicNorm.dvd_iff_norm_le (p := p) (n := k) (z := z)).1 (by exact_mod_cast h) + rwa [zpow_neg, zpow_natCast] at this + +/-- An elementary size estimate used in the proof of Adams' theorem. -/ +private lemma aux_big (n q : ℕ) (hq : 2 ≤ q) : n * (n + 1) * q ≤ q ^ (n * (n + 1) + 1) := by + rw [pow_succ] + apply Nat.mul_le_mul_right + have h2 : n * (n + 1) < 2 ^ (n * (n + 1)) := Nat.lt_two_pow_self + have h3 : 2 ^ (n * (n + 1)) ≤ q ^ (n * (n + 1)) := Nat.pow_le_pow_left hq _ + omega + +/-- **Adams' theorem** (the case needed here): if `p - 1 ∤ n` then `B_n / n` is `p`-integral. Proof: a Voronoi-type congruence for power sums modulo `p^e` and Faulhaber's formula. -/ +private theorem adams (n : ℕ) (h : ¬ (p - 1) ∣ n) : padicNorm p (bernoulli n / n) ≤ 1 := by + have hn : 0 < n := by + rcases Nat.eq_zero_or_pos n with rfl | h' + · exact absurd (dvd_zero _) h + · exact h' + obtain ⟨a, ha, hprim⟩ := exists_prim_root (p := p) + have hprim' : ¬ (p : ℤ) ∣ (a : ℤ) ^ n - 1 := fun hd => h (hprim n hd) + set e := n * (n + 1) + 1 with he + set ν := padicValNat p n with hν + have hνe : ν ≤ e := by + have h1 := padicValNat_le_nat_log (p := p) n + have h2 : Nat.log p n ≤ n := (Nat.log_lt_self p hn.ne').le + have : n ≤ e := by rw [he]; nlinarith + omega + have hS := psS_dvd (p := p) a n hn ha hprim' e + rw [min_eq_left hνe] at hS + have hp0 : (0 : ℚ) < p := by exact_mod_cast hp.out.pos + set N : ℚ := (p : ℚ) ^ e with hN + have hN0 : N ≠ 0 := by positivity + have hn0 : (n : ℚ) ≠ 0 := by exact_mod_cast hn.ne' + have hn1 : (n : ℚ) + 1 ≠ 0 := by positivity + have hSQ : ((psS (p := p) n e : ℤ) : ℚ) = ∑ k ∈ range (p ^ e), (k : ℚ) ^ n := by + unfold psS; push_cast; rfl + have hF := sum_range_pow (p ^ e) n + rw [← hSQ, sum_range_succ, Nat.choose_succ_self_right, Nat.add_sub_cancel_left] at hF + push_cast at hF + have key : bernoulli n / n = (psS (p := p) n e : ℚ) / (n * N) - + ∑ i ∈ range n, bernoulli i * ((n + 1).choose i : ℚ) * N ^ (n - i) * (1 / (n * (n + 1))) := by + rw [hF, add_div, sum_div] + have hsum : ∑ i ∈ range n, + bernoulli i * ((n + 1).choose i : ℚ) * N ^ (n + 1 - i) / (n + 1) / (n * N) = + ∑ i ∈ range n, bernoulli i * ((n + 1).choose i : ℚ) * N ^ (n - i) * (1 / (n * (n + 1))) := by + refine sum_congr rfl (fun i hi => ?_) + have hi' : i < n := mem_range.1 hi + rw [show n + 1 - i = (n - i) + 1 by omega, pow_succ] + field_simp + rw [hsum] + field_simp + ring + rw [key] + refine le_trans padicNorm.sub (max_le ?_ ?_) + · rw [padicNorm.div, padicNorm.mul, padicNorm_natCast_eq n hn, hN, padicNorm_prime_pow] + have h1 := padicNorm_int_le_of_dvd (p := p) _ _ hS + rw [div_le_one (by positivity)] + calc padicNorm p (psS (p := p) n e : ℚ) ≤ ((p : ℚ) ^ (e + ν))⁻¹ := h1 + _ = ((p : ℚ) ^ ν)⁻¹ * ((p : ℚ) ^ e)⁻¹ := by rw [pow_add, mul_inv, mul_comm] + · refine padicNorm.sum_le' (fun i hi => ?_) zero_le_one + have hi' : i < n := mem_range.1 hi + rw [padicNorm.mul, padicNorm.mul, padicNorm.mul] + have hB := bern_norm_le_p (p := p) i + have hC := padicNorm.of_nat (p := p) ((n + 1).choose i) + have hNp : padicNorm p (N ^ (n - i)) ≤ ((p : ℚ) ^ e)⁻¹ := by + rw [hN, ← pow_mul, padicNorm_prime_pow] + apply inv_anti₀ (by positivity) + apply pow_le_pow_right₀ (by exact_mod_cast hp.out.one_lt.le) + have : 1 ≤ n - i := by omega + nlinarith + have hD : padicNorm p (1 / ((n : ℚ) * (n + 1))) ≤ (n * (n + 1) : ℕ) := by + have := padicNorm_one_div_nat_le (p := p) (n * (n + 1)) (by positivity) + push_cast at this ⊢; exact this + have hbig : ((n * (n + 1) : ℕ) : ℚ) * p ≤ (p : ℚ) ^ e := by + have := aux_big n p hp.out.two_le + rw [← he] at this + exact_mod_cast this + have hpe : (0 : ℚ) < (p : ℚ) ^ e := by positivity + calc padicNorm p (bernoulli i) * padicNorm p ((n + 1).choose i : ℚ) * + padicNorm p (N ^ (n - i)) * padicNorm p (1 / ((n : ℚ) * (n + 1))) + ≤ (p : ℚ) * 1 * ((p : ℚ) ^ e)⁻¹ * ((n * (n + 1) : ℕ) : ℚ) := by + have hp0' : (0 : ℚ) ≤ p := hp0.le + refine mul_le_mul (mul_le_mul (mul_le_mul hB hC (padicNorm.nonneg _) hp0') hNp + (padicNorm.nonneg _) (by positivity)) hD (padicNorm.nonneg _) (by positivity) + _ ≤ 1 := by + rw [mul_one, mul_comm _ (((n * (n + 1) : ℕ) : ℚ)), ← mul_assoc, + ← div_eq_mul_inv, div_le_one hpe] + exact hbig + +end Adams + +section Series +open PowerSeries Finset + +/-- `G k = B_k / k!`, the coefficients of `t / (e^t - 1)`. -/ +private noncomputable def G (k : ℕ) : ℚ := bernoulli k / k.factorial +/-- The power series `G = t/(e^t - 1) = ∑ B_k t^k / k!`. -/ +private noncomputable def Gs : ℚ⟦X⟧ := PowerSeries.mk G +/-- The power series `(e^t - 1)/t = ∑ t^k/(k+1)!`. -/ +private noncomputable def Es : ℚ⟦X⟧ := PowerSeries.mk (fun k => 1 / ((k + 1).factorial : ℚ)) +/-- The coefficients `h_k` of `h = log(t/(e^t - 1))`: `h_1 = -1/2` and `h_k = -B_k/(k·k!)` otherwise. -/ +private noncomputable def hcoef (k : ℕ) : ℚ := if k = 1 then -1 / 2 else -G k / k +/-- The power series `h = log(t/(e^t - 1))`. -/ +private noncomputable def hs : ℚ⟦X⟧ := PowerSeries.mk hcoef + +/-- `Gs` is Mathlib's `bernoulliPowerSeries`. -/ +private lemma Gs_eq : Gs = bernoulliPowerSeries ℚ := by + ext n; simp [Gs, bernoulliPowerSeries, G] + +/-- `e^t - 1 = t · Es`. -/ +private lemma exp_sub_one_eq : exp ℚ - 1 = X * Es := by + ext n + cases n with + | zero => simp [Es] + | succ n => + rw [coeff_succ_X_mul] + simp [Es, coeff_exp] + +/-- `G · Es = 1`. -/ +private lemma Gs_mul_Es : Gs * Es = 1 := by + have h := bernoulliPowerSeries_mul_exp_sub_one ℚ + rw [← Gs_eq, exp_sub_one_eq] at h + have hX : (X : ℚ⟦X⟧) ≠ 0 := X_ne_zero + apply mul_left_cancel₀ hX + calc X * (Gs * Es) = Gs * (X * Es) := by ring + _ = X := h + _ = X * 1 := (mul_one _).symm + +/-- `t Es' = 1 + t Es - Es`. -/ +private lemma X_Es' : X * d⁄dX ℚ Es = 1 + X * Es - Es := by + ext n + rcases n with _ | n + · simp [Es] + · rw [coeff_succ_X_mul, coeff_derivative, map_sub, map_add, coeff_succ_X_mul] + simp only [Es, coeff_mk, coeff_one, Nat.succ_ne_zero, if_false, zero_add] + rw [Nat.factorial_succ (n + 1)] + have h1 : ((n + 1).factorial : ℚ) ≠ 0 := by positivity + push_cast + field_simp + ring + +/-- `t G' = G - t G - G²` for `G = t/(e^t - 1)`. -/ +private lemma X_Gs' : X * d⁄dX ℚ Gs = Gs - X * Gs - Gs ^ 2 := by + have h1 := Gs_mul_Es + have h2 : Gs * d⁄dX ℚ Es + Es * d⁄dX ℚ Gs = 0 := by + have := (d⁄dX ℚ).leibniz Gs Es + rw [h1, derivative_one] at this + simpa [smul_eq_mul] using this.symm + have h3 := X_Es' + linear_combination (-(X * d⁄dX ℚ Gs - Gs + X * Gs)) * h1 + (X * Gs) * h2 + (-Gs ^ 2) * h3 + +/-- `G_0 = 1`. -/ +private lemma G_zero : G 0 = 1 := by simp [G] +/-- `G_1 = -1/2`. -/ +private lemma G_one : G 1 = -1 / 2 := by simp [G, bernoulli_one] + +/-- `t h' = 1 - t - G`. -/ +private lemma X_hs' : X * d⁄dX ℚ hs = 1 - X - Gs := by + ext n + rcases n with _ | n + · simp [Gs, G_zero] + · rw [coeff_succ_X_mul, coeff_derivative] + rcases n with _ | n + · simp [hs, hcoef, Gs, G_one, coeff_X]; norm_num + · simp only [hs, Gs, coeff_mk, map_sub, coeff_one, coeff_X, hcoef] + simp only [Nat.add_eq_zero_iff, one_ne_zero, and_false, if_false, + show n + 1 + 1 ≠ 1 by omega, zero_sub] + have : ((n + 1 + 1 : ℕ) : ℚ) ≠ 0 := by positivity + push_cast at this ⊢ + field_simp + ring + +/-- `G' = h' G`, i.e. `h = log G`. -/ +private lemma Gs'_eq : d⁄dX ℚ Gs = d⁄dX ℚ hs * Gs := by + have hX : (X : ℚ⟦X⟧) ≠ 0 := X_ne_zero + apply mul_left_cancel₀ hX + rw [X_Gs', ← mul_assoc, X_hs']; ring + +/-- `(G^N)' = N h' G^N`. -/ +private lemma Gs_pow_deriv (N : ℕ) : d⁄dX ℚ (Gs ^ N) = (N : ℚ⟦X⟧) * d⁄dX ℚ hs * Gs ^ N := by + rw [derivative_pow, Gs'_eq] + rcases N with _ | N + · simp + · simp only [Nat.add_sub_cancel, pow_succ]; push_cast; ring + +/-- Uniqueness for the linear differential equation `Y' = c Y` over `ℚ`. -/ +private lemma ode_unique (A B c : ℚ⟦X⟧) (h0 : constantCoeff A = constantCoeff B) + (hA : d⁄dX ℚ A = c * A) (hB : d⁄dX ℚ B = c * B) : A = B := by + ext n + induction n using Nat.strong_induction_on with + | _ n ih => + rcases n with _ | n + · simpa using h0 + · have eA := coeff_derivative A n + have eB := coeff_derivative B n + rw [hA, coeff_mul] at eA + rw [hB, coeff_mul] at eB + have hsum : ∑ x ∈ antidiagonal n, coeff x.1 c * coeff x.2 A = + ∑ x ∈ antidiagonal n, coeff x.1 c * coeff x.2 B := by + refine sum_congr rfl (fun x hx => ?_) + rw [ih x.2 (by have := mem_antidiagonal.1 hx; omega)] + have hn : ((n : ℚ) + 1) ≠ 0 := by positivity + have := eA.symm.trans (hsum.trans eB) + exact mul_right_cancel₀ hn this + +/-- `h(0) = 0`. -/ +private lemma constantCoeff_hs : constantCoeff hs = 0 := by + simp [hs, hcoef, G_zero] + +/-- `[t^n] h^k = 0` for `n < k`. -/ +private lemma coeff_hs_pow_eq_zero (k n : ℕ) (h : n < k) : coeff n (hs ^ k) = 0 := by + have h1 : (X : ℚ⟦X⟧) ∣ hs := X_dvd_iff.2 constantCoeff_hs + have h2 : (X : ℚ⟦X⟧) ^ k ∣ hs ^ k := pow_dvd_pow_of_dvd h1 k + exact X_pow_dvd_iff.1 h2 n h + +/-- The power series `exp(c h) = ∑_k c^k h^k / k!`. -/ +private noncomputable def Ys (c : ℚ) : ℚ⟦X⟧ := + PowerSeries.mk (fun n => ∑ k ∈ range (n + 1), c ^ k * coeff n (hs ^ k) / k.factorial) + +/-- The truncation `∑_{k ≤ M} c^k h^k / k!` of `exp(c h)`. -/ +private noncomputable def Zs (c : ℚ) (M : ℕ) : ℚ⟦X⟧ := + ∑ k ∈ range (M + 1), PowerSeries.C (c ^ k / k.factorial) * hs ^ k + +/-- The truncations of `exp(c h)` agree with `exp(c h)` in low degree. -/ +private lemma coeff_Zs (c : ℚ) (M n : ℕ) (h : n ≤ M) : coeff n (Zs c M) = coeff n (Ys c) := by + simp only [Zs, Ys, map_sum, coeff_C_mul, coeff_mk] + have : range (M + 1) = range (n + 1) ∪ Ico (n + 1) (M + 1) := by + ext k; simp only [mem_range, mem_union, mem_Ico]; omega + rw [this, sum_union (by + rw [range_eq_Ico]; exact Ico_disjoint_Ico_consecutive _ _ _)] + rw [sum_eq_zero (s := Ico (n + 1) (M + 1)), add_zero] + · refine sum_congr rfl (fun k _ => by ring) + · intro k hk + rw [coeff_hs_pow_eq_zero k n (by simp at hk; omega), mul_zero] + +/-- Derivative of the truncated exponential. -/ +private lemma Zs_deriv (c : ℚ) (M : ℕ) : + d⁄dX ℚ (Zs c (M + 1)) = PowerSeries.C c * d⁄dX ℚ hs * Zs c M := by + simp only [Zs, map_sum, Derivation.leibniz, derivative_C, smul_eq_mul, derivative_pow] + rw [sum_range_succ', mul_sum] + simp only [Nat.cast_zero, zero_mul, mul_zero, add_zero, Nat.add_sub_cancel] + refine sum_congr rfl (fun k _ => ?_) + have hk : ((k + 1).factorial : ℚ) = (k + 1) * k.factorial := by + push_cast [Nat.factorial_succ]; ring + rw [hk] + have : PowerSeries.C (c ^ (k + 1) / ((k + 1) * (k.factorial : ℚ))) * ((k + 1 : ℕ) : ℚ⟦X⟧) = + PowerSeries.C c * PowerSeries.C (c ^ k / k.factorial) := by + rw [← map_mul, ← map_natCast (PowerSeries.C (R := ℚ)), ← map_mul] + congr 1 + have : (k.factorial : ℚ) ≠ 0 := by positivity + push_cast + field_simp + ring + calc PowerSeries.C (c ^ (k + 1) / ((k + 1) * (k.factorial : ℚ))) * + (((k + 1 : ℕ) : ℚ⟦X⟧) * hs ^ k * d⁄dX ℚ hs) + = (PowerSeries.C (c ^ (k + 1) / ((k + 1) * (k.factorial : ℚ))) * ((k + 1 : ℕ) : ℚ⟦X⟧)) * + hs ^ k * d⁄dX ℚ hs := by ring + _ = _ := by rw [this]; ring + +/-- `exp(c h)' = c h' exp(c h)`. -/ +private lemma Ys_deriv (c : ℚ) : d⁄dX ℚ (Ys c) = PowerSeries.C c * d⁄dX ℚ hs * Ys c := by + ext n + rw [coeff_derivative, ← coeff_Zs c (n + 1) (n + 1) le_rfl, ← coeff_derivative, Zs_deriv, + coeff_mul, coeff_mul] + refine sum_congr rfl (fun x hx => ?_) + rw [coeff_Zs c n x.2 (by have := mem_antidiagonal.1 hx; omega)] + +/-- `exp(c h)(0) = 1`. -/ +private lemma constantCoeff_Ys (c : ℚ) : constantCoeff (Ys c) = 1 := by + simp [Ys] + +/-- `exp(N h) = G^N` for natural `N`. -/ +private lemma Ys_nat (N : ℕ) : Ys N = Gs ^ N := by + apply ode_unique _ _ (PowerSeries.C (N : ℚ) * d⁄dX ℚ hs) + · rw [constantCoeff_Ys, map_pow]; simp [Gs, G_zero] + · exact Ys_deriv N + · rw [Gs_pow_deriv]; simp + +end Series + +section Valuations +open Finset + +/-- `V_p(n) = q + v_p(q!)` with `q = ⌊n/(p-1)⌋`: the exponent of `p` in `A053657(n+1)`. -/ +private def Vp (p n : ℕ) : ℕ := n / (p - 1) + padicValNat p (n / (p - 1)).factorial + +/-- The bound `w_p(i) = v_p(i!) + [p-1 ∣ i](1 + v_p(i))` for `-v_p(h_i)`. -/ +private def wp (p i : ℕ) : ℕ := padicValNat p i.factorial + if (p - 1) ∣ i then 1 + padicValNat p i else 0 + +variable {p : ℕ} [hp : Fact p.Prime] + +/-- `v_p` is monotone along divisibility. -/ +private lemma padicValNat_mono {a b : ℕ} (hab : a ∣ b) (hb : b ≠ 0) : padicValNat p a ≤ padicValNat p b := + (padicValNat_dvd_iff_le hb).1 ((pow_padicValNat_dvd).trans hab) + +/-- `v_p(a!) ≤ v_p(b!)` for `a ≤ b`. -/ +private lemma padicValNat_fact_mono {a b : ℕ} (hab : a ≤ b) : + padicValNat p a.factorial ≤ padicValNat p b.factorial := + padicValNat_mono (Nat.factorial_dvd_factorial hab) (Nat.factorial_ne_zero _) + +/-- `v_p(a!) + v_p(b!) ≤ v_p((a+b)!)`. -/ +private lemma padicValNat_fact_add (a b : ℕ) : + padicValNat p a.factorial + padicValNat p b.factorial ≤ padicValNat p (a + b).factorial := by + rw [← padicValNat.mul (Nat.factorial_ne_zero _) (Nat.factorial_ne_zero _)] + exact padicValNat_mono (Nat.factorial_mul_factorial_dvd_factorial_add a b) (Nat.factorial_ne_zero _) + +/-- `V_p` is monotone. -/ +private lemma Vp_mono {a b : ℕ} (h : a ≤ b) : Vp p a ≤ Vp p b := by + unfold Vp + have : a / (p - 1) ≤ b / (p - 1) := Nat.div_le_div_right h + have := padicValNat_fact_mono (p := p) this + omega + +/-- `V_p` is superadditive. -/ +private lemma Vp_add (a b : ℕ) : Vp p a + Vp p b ≤ Vp p (a + b) := by + unfold Vp + have h1 := (Nat.div_add_div_le_add_div (x := a) (y := b) (z := p - 1)) + have h2 := padicValNat_fact_add (p := p) (a / (p - 1)) (b / (p - 1)) + have h3 := padicValNat_fact_mono (p := p) h1 + omega + +/-- `(Q!)^m m! ∣ (mQ)!` for `Q > 0`. -/ +private lemma fact_pow_mul_dvd (Q m : ℕ) (hQ : 0 < Q) : + Q.factorial ^ m * m.factorial ∣ (m * Q).factorial := by + induction m with + | zero => simp + | succ m ih => + have h1 : (m * Q).factorial * Q.factorial * ((m + 1) * Q).choose Q = ((m + 1) * Q).factorial := by + have := Nat.choose_mul_factorial_mul_factorial (n := (m + 1) * Q) (k := Q) (by nlinarith) + rw [show (m + 1) * Q - Q = m * Q by rw [add_mul, one_mul, Nat.add_sub_cancel]] at this + rw [← this]; ring + have h2 : (m + 1) ∣ ((m + 1) * Q).choose Q := by + have := Nat.add_one_mul_choose_eq ((m + 1) * Q - 1) (Q - 1) + rw [show (m + 1) * Q - 1 + 1 = (m + 1) * Q by + have : 1 ≤ (m + 1) * Q := by nlinarith + omega, show Q - 1 + 1 = Q by omega] at this + -- this : (m+1)*Q * choose ((m+1)Q-1) (Q-1) = choose ((m+1)Q) Q * Q + have h3 : (m + 1) * (((m + 1) * Q - 1).choose (Q - 1)) * Q = ((m + 1) * Q).choose Q * Q := by + rw [← this]; ring + exact ⟨_, (Nat.eq_of_mul_eq_mul_right hQ h3).symm⟩ + obtain ⟨c, hc⟩ := h2 + rw [← h1, hc, Nat.factorial_succ, pow_succ] + obtain ⟨d, hd⟩ := ih + rw [hd] + exact ⟨d * c, by ring⟩ + +/-- `m V_p(i) + v_p(m!) ≤ V_p(i m)`. -/ +private lemma Vp_mul (i m : ℕ) (hi : 0 < i) : + m * Vp p i + padicValNat p m.factorial ≤ Vp p (i * m) := by + unfold Vp + set Q := i / (p - 1) + rcases Nat.eq_zero_or_pos Q with hQ0 | hQ + · rw [hQ0] + simp only [Nat.factorial_zero, padicValNat_one_right, add_zero, mul_zero, zero_add] + have hp1 : 0 < p - 1 := by have := hp.out.two_le; omega + have h1 := sub_one_mul_padicValNat_factorial (p := p) m + have h2 : padicValNat p m.factorial ≤ i * m / (p - 1) := by + rw [Nat.le_div_iff_mul_le hp1, mul_comm, h1] + have : m ≤ i * m := Nat.le_mul_of_pos_left m hi + omega + omega + have h1 : m * Q ≤ i * m / (p - 1) := by + rcases Nat.eq_zero_or_pos (p - 1) with h0 | h0 + · simp [Q, h0] + rw [Nat.le_div_iff_mul_le h0] + have : Q * (p - 1) ≤ i := Nat.div_mul_le_self i (p - 1) + nlinarith + have h2 : m * padicValNat p Q.factorial + padicValNat p m.factorial ≤ + padicValNat p (m * Q).factorial := by + have := padicValNat_mono (p := p) (fact_pow_mul_dvd Q m hQ) (Nat.factorial_ne_zero _) + rw [padicValNat.mul (pow_ne_zero _ (Nat.factorial_ne_zero _)) (Nat.factorial_ne_zero _), + padicValNat.pow] at this + exact this + have h3 := padicValNat_fact_mono (p := p) h1 + nlinarith + +/-- The base-`p` digit sum of a positive number is positive. -/ +private lemma digits_sum_pos {i : ℕ} (hi : i ≠ 0) : 0 < (p.digits i).sum := by + have h1 := sub_one_mul_padicValNat_factorial (p := p) i + have h2 := sub_one_mul_padicValNat_factorial_lt_of_ne_zero p hi + omega + +/-- If `p - 1 ∣ i > 0` then the base-`p` digit sum of `i` is at least `p - 1`. -/ +private lemma digits_sum_ge {i : ℕ} (hi : i ≠ 0) (hd : (p - 1) ∣ i) : p - 1 ≤ (p.digits i).sum := by + have hpos := digits_sum_pos (p := p) hi + rcases Nat.lt_or_ge p 3 with h3 | h3 + · have := hp.out.two_le; omega + · have hmod : i ≡ (p.digits i).sum [MOD (p - 1)] := + Nat.modEq_digits_sum (p - 1) p (by + have h1 : 1 ≡ p [MOD p - 1] := (Nat.modEq_iff_dvd' (by omega)).2 (by + rw [show p - 1 = p - 1 from rfl]) + unfold Nat.ModEq at h1 + rw [← h1]; exact Nat.mod_eq_of_lt (by omega)) i + have : (p - 1) ∣ (p.digits i).sum := (Nat.modEq_zero_iff_dvd.1 (hmod.symm.trans + (Nat.modEq_zero_iff_dvd.2 hd))) + exact Nat.le_of_dvd hpos this + +/-- `v_p(((p-1)Q)!) ≤ Q - 1` for `Q > 0`. -/ +private lemma padicValNat_fact_mul_le (Q : ℕ) (hQ : 0 < Q) : + padicValNat p ((p - 1) * Q).factorial + 1 ≤ Q := by + have hp1 : 0 < p - 1 := by have := hp.out.two_le; omega + have h1 := sub_one_mul_padicValNat_factorial (p := p) ((p - 1) * Q) + have h2 := digits_sum_ge (p := p) (i := (p - 1) * Q) (by positivity) (dvd_mul_right _ _) + have h3 : (p - 1) * padicValNat p ((p - 1) * Q).factorial ≤ (p - 1) * (Q - 1) := by + rw [h1, Nat.mul_sub, mul_one]; omega + have := Nat.le_of_mul_le_mul_left h3 hp1 + omega + +/-- `v_p((p-1)Q) = v_p(Q)`. -/ +private lemma padicValNat_sub_one_mul (Q : ℕ) (hQ : 0 < Q) : + padicValNat p ((p - 1) * Q) = padicValNat p Q := by + have hp1 : p - 1 ≠ 0 := by have := hp.out.two_le; omega + rw [padicValNat.mul hp1 hQ.ne', padicValNat.eq_zero_of_not_dvd, zero_add] + intro hd + have := Nat.le_of_dvd (by omega) hd + omega + +/-- `w_p(i) ≤ V_p(i)`. -/ +private lemma wp_le_Vp (i : ℕ) (hi : 0 < i) : wp p i ≤ Vp p i := by + unfold wp Vp + have hp1 : 0 < p - 1 := by have := hp.out.two_le; omega + split_ifs with hd + · obtain ⟨Q, rfl⟩ := hd + have hQ : 0 < Q := by + rcases Nat.eq_zero_or_pos Q with h | h + · simp [h] at hi + · exact h + rw [Nat.mul_div_cancel_left _ hp1, padicValNat_sub_one_mul Q hQ] + have h1 := padicValNat_fact_mul_le (p := p) Q hQ + have h2 : padicValNat p Q ≤ padicValNat p Q.factorial := + padicValNat_mono (Nat.dvd_factorial hQ le_rfl) (Nat.factorial_ne_zero _) + omega + · have h1 := sub_one_mul_padicValNat_factorial (p := p) i + have : padicValNat p i.factorial ≤ i / (p - 1) := by + rw [Nat.le_div_iff_mul_le hp1, mul_comm, h1]; omega + omega + +/-- `w_p(1) = 0` for odd `p`. -/ +private lemma wp_one (h2 : p ≠ 2) : wp p 1 = 0 := by + unfold wp + have : ¬ (p - 1) ∣ 1 := by + intro hd + have := Nat.le_of_dvd one_pos hd + have := hp.out.two_le + omega + simp [this] + +/-- `w_p(p-1) = 1` for odd `p`. -/ +private lemma wp_sub_one (h2 : p ≠ 2) : wp p (p - 1) = 1 := by + unfold wp + have h3 : 3 ≤ p := by have := hp.out.two_le; omega + rw [if_pos dvd_rfl, padicValNat.eq_zero_of_not_dvd (n := p - 1), padicValNat.eq_zero_of_not_dvd] + · intro hd + exact (Nat.Prime.dvd_factorial hp.out).not.mpr (by omega) hd + · intro hd + have := Nat.le_of_dvd (by omega) hd + omega + +omit hp in +/-- `(p-2) v < p^v - 1` for `v > 0` and `p ≥ 3`. -/ +private lemma pow_bound (v : ℕ) (hv : 0 < v) (hp3 : 3 ≤ p) : (p - 2) * v < p ^ v - 1 := by + have := one_add_mul_le_pow (a := ((p : ℤ) - 1)) (by omega) v + have h : (1 : ℤ) + v * ((p : ℤ) - 1) ≤ (p : ℤ) ^ v := by simpa using this + have h2 : (p - 2) * v + 1 < p ^ v := by + zify [show 2 ≤ p by omega] + nlinarith + omega + +/-- For odd `p` and `i ≥ 2`, `i ≠ p - 1`: `(p-2) w_p(i) < i - 1` (strictness for the lower bound). -/ +private lemma wp_strict (h2 : p ≠ 2) (i : ℕ) (hi : 2 ≤ i) (hne : i ≠ p - 1) : + (p - 2) * wp p i < i - 1 := by + have hp3 : 3 ≤ p := by have := hp.out.two_le; omega + have hp1 : 0 < p - 1 := by omega + unfold wp + split_ifs with hd + · obtain ⟨Q, rfl⟩ := hd + have hQ : 2 ≤ Q := by + rcases Nat.lt_or_ge Q 2 with h | h + · interval_cases Q + · simp at hi + · simp at hne + · exact h + rw [padicValNat_sub_one_mul Q (by omega)] + have h1 := padicValNat_fact_mul_le (p := p) Q (by omega) + -- need (p-2) * (v + 1 + vQ) < (p-1)Q - 1 where v + 1 ≤ Q + have h3 : (p - 2) * padicValNat p Q < Q - 1 := by + rcases Nat.eq_zero_or_pos (padicValNat p Q) with h0 | h0 + · rw [h0]; omega + · have h4 := pow_bound (p := p) _ h0 hp3 + have h5 : p ^ padicValNat p Q ≤ Q := Nat.le_of_dvd (by omega) pow_padicValNat_dvd + omega + have e1 : (p - 2) * (padicValNat p ((p - 1) * Q).factorial + (1 + padicValNat p Q)) ≤ + (p - 2) * (Q + padicValNat p Q) := Nat.mul_le_mul_left _ (by omega) + have e2 : (p - 2) * (Q + padicValNat p Q) = (p - 2) * Q + (p - 2) * padicValNat p Q := by ring + have e3 : (p - 1) * Q = (p - 2) * Q + Q := by + rw [show p - 1 = (p - 2) + 1 by omega]; ring + omega + · have h1 := sub_one_mul_padicValNat_factorial (p := p) i + have h2' := sub_one_mul_padicValNat_factorial_lt_of_ne_zero p (by omega : i ≠ 0) + simp only [add_zero] + set v := padicValNat p i.factorial + rcases Nat.eq_zero_or_pos v with h0 | h0 + · rw [h0]; omega + · have e3 : (p - 1) * v = (p - 2) * v + v := by + rw [show p - 1 = (p - 2) + 1 by omega]; ring + omega + +end Valuations + +section UpperBound +open PowerSeries Finset + +variable {p : ℕ} [hp : Fact p.Prime] + +/-- `|1/m!|_p = p^(v_p(m!))`. -/ +private lemma padicNorm_one_div_fact (m : ℕ) : + padicNorm p (1 / (m.factorial : ℚ)) = (p : ℚ) ^ padicValNat p m.factorial := by + rw [padicNorm.div, padicNorm.one, padicNorm_natCast_eq _ (Nat.factorial_pos m), one_div, inv_inv] + +/-- `|1/m|_p = p^(v_p(m))`. -/ +private lemma padicNorm_one_div_nat (m : ℕ) (hm : 0 < m) : + padicNorm p (1 / (m : ℚ)) = (p : ℚ) ^ padicValNat p m := by + rw [padicNorm.div, padicNorm.one, padicNorm_natCast_eq _ hm, one_div, inv_inv] + +/-- `|a^n|_p = |a|_p^n`. -/ +private lemma padicNorm_pow (a : ℚ) (n : ℕ) : padicNorm p (a ^ n) = padicNorm p a ^ n := by + induction n with + | zero => simp + | succ n ih => rw [pow_succ, padicNorm.mul, ih, pow_succ] + +/-- `|h_i|_p ≤ p^(w_p(i))`, from von Staudt–Clausen and Adams' theorem. -/ +private lemma hcoef_norm_le (i : ℕ) (hi : 0 < i) : padicNorm p (hcoef i) ≤ (p : ℚ) ^ wp p i := by + have hp1 : (1 : ℚ) ≤ p := by exact_mod_cast hp.out.one_lt.le + rcases Nat.eq_or_lt_of_le hi with h1 | h2 + · subst h1 + simp only [hcoef, if_true] + rw [show (-1 / 2 : ℚ) = -(2 : ℚ)⁻¹ by ring, padicNorm.neg] + by_cases hp2 : p = 2 + · subst hp2 + have : wp 2 1 = 1 := by simp [wp] + rw [this, pow_one]; exact padicNorm_two_inv_le + · rw [padicNorm_two_inv_odd hp2]; exact one_le_pow₀ hp1 + · have hne : i ≠ 1 := by omega + have heq : hcoef i = -(bernoulli i / i) * (1 / (i.factorial : ℚ)) := by + simp only [hcoef, hne, if_false, G]; ring + rw [heq, padicNorm.mul, padicNorm.neg, padicNorm_one_div_fact] + unfold wp + split_ifs with hd + · rw [div_eq_mul_one_div, padicNorm.mul, padicNorm_one_div_nat i hi, pow_add, pow_add, + pow_one] + have hB := bern_norm_le_p (p := p) i + have : padicNorm p (bernoulli i) * (p : ℚ) ^ padicValNat p i * (p : ℚ) ^ padicValNat p i.factorial + ≤ (p : ℚ) * (p : ℚ) ^ padicValNat p i * (p : ℚ) ^ padicValNat p i.factorial := by + gcongr + linarith + · have hA := adams (p := p) i hd + rw [add_zero] + calc padicNorm p (bernoulli i / i) * (p : ℚ) ^ padicValNat p i.factorial + ≤ 1 * (p : ℚ) ^ padicValNat p i.factorial := by gcongr + _ = _ := one_mul _ + +/-- `|h_{p-1}|_p = p` for odd `p`. -/ +private lemma hcoef_norm_pm1 (h2 : p ≠ 2) : padicNorm p (hcoef (p - 1)) = p := by + have hp3 : 3 ≤ p := by have := hp.out.two_le; omega + have hne : p - 1 ≠ 1 := by omega + have heq : hcoef (p - 1) = -(bernoulli (p - 1)) * (1 / ((p - 1 : ℕ) : ℚ)) * + (1 / ((p - 1).factorial : ℚ)) := by + simp only [hcoef, hne, if_false, G]; ring + have hev : Even (p - 1) := by + rcases hp.out.eq_two_or_odd' with h | h + · exact absurd h h2 + · exact Nat.Odd.sub_odd h odd_one + rw [heq, padicNorm.mul, padicNorm.mul, padicNorm.neg, + bern_norm_eq_p (p - 1) dvd_rfl hev (by omega), padicNorm_one_div_fact, + padicNorm_one_div_nat _ (by omega)] + rw [padicValNat.eq_zero_of_not_dvd (n := p - 1), padicValNat.eq_zero_of_not_dvd] + · simp + · intro hd + exact (Nat.Prime.dvd_factorial hp.out).not.mpr (by omega) hd + · intro hd + have := Nat.le_of_dvd (by omega) hd + omega + +/-- The truncation `∑_{i ≤ j} h_i t^i`. -/ +private noncomputable def hsT (j : ℕ) : ℚ⟦X⟧ := PowerSeries.mk (fun i => if i ≤ j then hcoef i else 0) + +/-- `h_0 = 0`. -/ +private lemma hcoef_zero : hcoef 0 = 0 := by simp [hcoef] + +/-- The truncation `h_{≤ 0}` is `0`. -/ +private lemma hsT_zero : hsT 0 = 0 := by + ext i; simp only [hsT, coeff_mk, map_zero] + split_ifs with h + · have : i = 0 := by omega + subst this; exact hcoef_zero + · rfl + +/-- Adding one more term to the truncation. -/ +private lemma hsT_succ (j : ℕ) : + hsT (j + 1) = hsT j + PowerSeries.C (hcoef (j + 1)) * X ^ (j + 1) := by + ext i + simp only [hsT, coeff_mk, map_add, coeff_C_mul_X_pow] + split_ifs <;> first | omega | simp_all + +/-- Upper bound `|[t^n] (h_{≤ j})^k / k!|_p ≤ p^(V_p(n))`, by induction on the largest part `j` (multinomial expansion). -/ +private lemma upper_hsT (j : ℕ) : ∀ n k : ℕ, + padicNorm p (coeff n (hsT j ^ k) / k.factorial) ≤ (p : ℚ) ^ Vp p n := by + have hp1 : (1 : ℚ) ≤ p := by exact_mod_cast hp.out.one_lt.le + induction j with + | zero => + intro n k + rw [hsT_zero] + rcases Nat.eq_zero_or_pos k with rfl | hk + · simp only [pow_zero, Nat.factorial_zero, Nat.cast_one, div_one, coeff_one] + split_ifs + · rw [padicNorm.one]; exact one_le_pow₀ hp1 + · rw [padicNorm.zero]; positivity + · rw [zero_pow hk.ne']; simp + | succ j ih => + intro n k + rw [hsT_succ, add_pow, map_sum, sum_div] + refine padicNorm.sum_le' (fun m hm => ?_) (by positivity) + have hm' : m ≤ k := Nat.lt_succ_iff.1 (mem_range.1 hm) + set J := (j + 1) * (k - m) + have hy : (PowerSeries.C (hcoef (j + 1)) * X ^ (j + 1)) ^ (k - m) = + PowerSeries.C (hcoef (j + 1) ^ (k - m)) * X ^ J := by + rw [mul_pow, ← map_pow, ← pow_mul] + rw [hy] + have hcho : ((k.choose m : ℕ) : ℚ) / k.factorial = 1 / (m.factorial * (k - m).factorial) := by + rw [Nat.choose_eq_factorial_div_factorial hm', Nat.cast_div (Nat.factorial_mul_factorial_dvd_factorial hm') + (by positivity)] + push_cast + field_simp + have hcoeff : coeff n (hsT j ^ m * (PowerSeries.C (hcoef (j + 1) ^ (k - m)) * X ^ J) * + ((k.choose m : ℕ) : ℚ⟦X⟧)) / k.factorial = + (if J ≤ n then (coeff (n - J) (hsT j ^ m) / m.factorial) * + (hcoef (j + 1) ^ (k - m) * (1 / ((k - m).factorial : ℚ))) else 0) := by + rw [show ((k.choose m : ℕ) : ℚ⟦X⟧) = PowerSeries.C ((k.choose m : ℕ) : ℚ) by simp, + mul_comm _ (PowerSeries.C _), coeff_C_mul, ← mul_assoc, mul_comm (hsT j ^ m), + mul_assoc, coeff_C_mul, coeff_mul_X_pow'] + split_ifs + · calc ((k.choose m : ℕ) : ℚ) * (hcoef (j + 1) ^ (k - m) * coeff (n - J) (hsT j ^ m)) / + k.factorial + = (hcoef (j + 1) ^ (k - m) * coeff (n - J) (hsT j ^ m)) * + (((k.choose m : ℕ) : ℚ) / k.factorial) := by ring + _ = _ := by rw [hcho]; ring + · simp + rw [hcoeff] + split_ifs with hJ + · rw [padicNorm.mul, padicNorm.mul, padicNorm_one_div_fact] + have h1 := ih (n - J) m + have h2 : padicNorm p (hcoef (j + 1) ^ (k - m)) ≤ (p : ℚ) ^ ((k - m) * wp p (j + 1)) := by + rw [padicNorm_pow, mul_comm, pow_mul] + exact pow_le_pow_left₀ (padicNorm.nonneg _) (hcoef_norm_le (j + 1) (by omega)) _ + have h3 : (k - m) * wp p (j + 1) + padicValNat p (k - m).factorial ≤ Vp p J := by + have hJdef : J = (j + 1) * (k - m) := rfl + have := Vp_mul (p := p) (j + 1) (k - m) (by omega) + rw [← hJdef] at this + have := wp_le_Vp (p := p) (j + 1) (by omega) + have : (k - m) * wp p (j + 1) ≤ (k - m) * Vp p (j + 1) := Nat.mul_le_mul_left _ this + omega + have h4 : Vp p (n - J) + Vp p J ≤ Vp p n := by + have := Vp_add (p := p) (n - J) J + rwa [Nat.sub_add_cancel hJ] at this + calc padicNorm p (coeff (n - J) (hsT j ^ m) / m.factorial) * + (padicNorm p (hcoef (j + 1) ^ (k - m)) * (p : ℚ) ^ padicValNat p (k - m).factorial) + ≤ (p : ℚ) ^ Vp p (n - J) * ((p : ℚ) ^ ((k - m) * wp p (j + 1)) * + (p : ℚ) ^ padicValNat p (k - m).factorial) := by + gcongr + exact mul_nonneg (padicNorm.nonneg _) (by positivity) + _ = (p : ℚ) ^ (Vp p (n - J) + ((k - m) * wp p (j + 1) + padicValNat p (k - m).factorial)) := by + rw [pow_add, pow_add] + _ ≤ (p : ℚ) ^ Vp p n := pow_le_pow_right₀ hp1 (by omega) + · rw [padicNorm.zero]; positivity + +end UpperBound + +section Content +open PowerSeries Finset + +/-- `a(n,k) = [t^n] h^k / k!`, the coefficient of `x^k` in `f_n(x) = [t^n] (t/(e^t-1))^x`. -/ +private noncomputable def aco (n k : ℕ) : ℚ := coeff n (hs ^ k) / k.factorial + +/-- `[t^n] h^k` only depends on `h_{≤ n}`. -/ +private lemma coeff_hs_pow_eq_hsT (n k : ℕ) : coeff n (hs ^ k) = coeff n (hsT n ^ k) := by + have h1 : (X : ℚ⟦X⟧) ^ (n + 1) ∣ hs - hsT n := by + rw [X_pow_dvd_iff] + intro m hm + simp [hs, hsT, show m ≤ n by omega] + have h2 : (X : ℚ⟦X⟧) ^ (n + 1) ∣ hs ^ k - hsT n ^ k := h1.trans (sub_dvd_pow_sub_pow _ _ _) + have := X_pow_dvd_iff.1 h2 n (by omega) + rw [map_sub] at this + exact sub_eq_zero.1 this + +variable {p : ℕ} [hp : Fact p.Prime] + +/-- Upper bound `|a(n,k)|_p ≤ p^(V_p(n))`. -/ +private theorem aco_upper (n k : ℕ) : padicNorm p (aco n k) ≤ (p : ℚ) ^ Vp p n := by + unfold aco; rw [coeff_hs_pow_eq_hsT]; exact upper_hsT n n k + +/-- The power series `g = h / t`. -/ +private noncomputable def gs : ℚ⟦X⟧ := PowerSeries.mk (fun i => hcoef (i + 1)) + +/-- `h = t g`. -/ +private lemma hs_eq : hs = X * gs := by + ext i + rcases i with _ | i + · simp [hs, hcoef_zero] + · rw [coeff_succ_X_mul]; simp [hs, gs] + +/-- `[t^n] h^n = h_1^n`. -/ +private lemma coeff_hs_pow_self (n : ℕ) : coeff n (hs ^ n) = hcoef 1 ^ n := by + rw [hs_eq, mul_pow, coeff_X_pow_mul', if_pos le_rfl, Nat.sub_self, coeff_zero_eq_constantCoeff, + map_pow] + simp [gs] + +/-- The top coefficient `a(n,n) = (-1/2)^n / n!`. -/ +private lemma aco_self (n : ℕ) : aco n n = (-1 / 2 : ℚ) ^ n / n.factorial := by + rw [aco, coeff_hs_pow_self]; simp [hcoef] + +/-- `|a(n,n)|_2 = 2^(V_2(n))`. -/ +private lemma aco_lower_two (n : ℕ) : padicNorm 2 (aco n n) = (2 : ℚ) ^ Vp 2 n := by + have : Fact (Nat.Prime 2) := ⟨Nat.prime_two⟩ + rw [aco_self, div_eq_mul_one_div, padicNorm.mul, padicNorm_one_div_fact, padicNorm_pow, + show (-1 / 2 : ℚ) = -(2 : ℚ)⁻¹ by ring, padicNorm.neg, inv_eq_one_div, padicNorm.div, + padicNorm.one] + have h2 : padicNorm 2 (2 : ℚ) = (2 : ℚ)⁻¹ := by + have := @padicNorm.padicNorm_p_of_prime 2 _ + simpa using this + rw [h2] + simp [Vp, pow_add] + +end Content + +section LowerBoundOdd +open PowerSeries Finset + +variable {p : ℕ} [hp : Fact p.Prime] + +/-- Ultrametric bound for `|∑ F|_p^d`. -/ +private lemma norm_sum_pow_le {ι : Type*} (s : Finset ι) (F : ι → ℚ) (d : ℕ) (C : ℚ) (hC : 0 ≤ C) + (hd : 0 < d) (h : ∀ x ∈ s, padicNorm p (F x) ^ d ≤ C) : + padicNorm p (∑ x ∈ s, F x) ^ d ≤ C := by + rcases s.eq_empty_or_nonempty with rfl | hne + · simp [zero_pow hd.ne', hC] + · obtain ⟨y, hy, hmax⟩ := Finset.exists_max_image s (fun x => padicNorm p (F x)) hne + have h1 : padicNorm p (∑ x ∈ s, F x) ≤ padicNorm p (F y) := + padicNorm.sum_le hne (fun i hi => hmax i hi) + exact (pow_le_pow_left₀ (padicNorm.nonneg _) h1 d).trans (h y hy) + +/-- Strict ultrametric bound for `|∑ F|_p^d`. -/ +private lemma norm_sum_pow_lt {ι : Type*} (s : Finset ι) (F : ι → ℚ) (d : ℕ) (C : ℚ) (hC : 0 < C) + (hd : 0 < d) (h : ∀ x ∈ s, padicNorm p (F x) ^ d < C) : + padicNorm p (∑ x ∈ s, F x) ^ d < C := by + rcases s.eq_empty_or_nonempty with rfl | hne + · simp [zero_pow hd.ne', hC] + · obtain ⟨y, hy, hmax⟩ := Finset.exists_max_image s (fun x => padicNorm p (F x)) hne + have h1 : padicNorm p (∑ x ∈ s, F x) ≤ padicNorm p (F y) := + padicNorm.sum_le hne (fun i hi => hmax i hi) + exact lt_of_le_of_lt (pow_le_pow_left₀ (padicNorm.nonneg _) h1 d) (h y hy) + +/-- Strict ultrametric bound for `|a + b|_p^d`. -/ +private lemma norm_add_pow_lt (a b : ℚ) (d : ℕ) (C : ℚ) (_hd : 0 < d) + (ha : padicNorm p a ^ d < C) (hb : padicNorm p b ^ d < C) : + padicNorm p (a + b) ^ d < C := by + have h1 := padicNorm.nonarchimedean (p := p) (q := a) (r := b) + rcases le_total (padicNorm p a) (padicNorm p b) with h | h + · rw [max_eq_right h] at h1 + exact lt_of_le_of_lt (pow_le_pow_left₀ (padicNorm.nonneg _) h1 d) hb + · rw [max_eq_left h] at h1 + exact lt_of_le_of_lt (pow_le_pow_left₀ (padicNorm.nonneg _) h1 d) ha + +section odd + +variable (h2 : p ≠ 2) +include h2 + +/-- An odd prime is at least `3`. -/ +private lemma p3 : 3 ≤ p := by have := hp.out.two_le; omega + +/-- `|g_i|_p^(p-2) ≤ p^i`. -/ +private lemma gs_bound (i : ℕ) : padicNorm p (coeff i gs) ^ (p - 2) ≤ (p : ℚ) ^ i := by + have hp1 : (1 : ℚ) ≤ p := by exact_mod_cast hp.out.one_lt.le + have h := hcoef_norm_le (p := p) (i + 1) (by omega) + simp only [gs, coeff_mk] + have hw : (p - 2) * wp p (i + 1) ≤ i := by + rcases Nat.eq_zero_or_pos i with rfl | hi + · rw [wp_one h2]; simp + by_cases he : i + 1 = p - 1 + · rw [he, wp_sub_one h2]; omega + · have := wp_strict h2 (i + 1) (by omega) he; omega + calc padicNorm p (hcoef (i + 1)) ^ (p - 2) ≤ ((p : ℚ) ^ wp p (i + 1)) ^ (p - 2) := + pow_le_pow_left₀ (padicNorm.nonneg _) h _ + _ = (p : ℚ) ^ ((p - 2) * wp p (i + 1)) := by rw [← pow_mul, mul_comm] + _ ≤ (p : ℚ) ^ i := pow_le_pow_right₀ hp1 hw + +/-- `|g_i|_p^(p-2) < p^i` unless `i ∈ {0, p-2}`. -/ +private lemma gs_strict (i : ℕ) (hi0 : i ≠ 0) (hid : i ≠ p - 2) : + padicNorm p (coeff i gs) ^ (p - 2) < (p : ℚ) ^ i := by + have hp1 : (1 : ℚ) < p := by exact_mod_cast hp.out.one_lt + have h := hcoef_norm_le (p := p) (i + 1) (by omega) + simp only [gs, coeff_mk] + have hw : (p - 2) * wp p (i + 1) < i := by + have := wp_strict h2 (i + 1) (by omega) (by have := p3 h2; omega); omega + calc padicNorm p (hcoef (i + 1)) ^ (p - 2) ≤ ((p : ℚ) ^ wp p (i + 1)) ^ (p - 2) := + pow_le_pow_left₀ (padicNorm.nonneg _) h _ + _ = (p : ℚ) ^ ((p - 2) * wp p (i + 1)) := by rw [← pow_mul, mul_comm] + _ < (p : ℚ) ^ i := pow_lt_pow_right₀ hp1 hw + +/-- `|g_0|_p ≤ 1` for odd `p`. -/ +private lemma gs_zero : padicNorm p (coeff 0 gs) ≤ 1 := by + simp only [gs, coeff_mk, zero_add, hcoef, if_true] + rw [show (-1 / 2 : ℚ) = -(2 : ℚ)⁻¹ by ring, padicNorm.neg, padicNorm_two_inv_odd h2] + +/-- `|g_{p-2}|_p = p` for odd `p`. -/ +private lemma gs_d : padicNorm p (coeff (p - 2) gs) = p := by + simp only [gs, coeff_mk] + rw [show p - 2 + 1 = p - 1 by have := p3 h2; omega] + exact hcoef_norm_pm1 h2 + +/-- Weighted `p`-adic bounds for the powers `g^q`, with the dominant term `g_{p-2}^q` of `[t^((p-2)q)] g^q` isolated. -/ +private lemma gs_pow_props (q : ℕ) : + (∀ i, padicNorm p (coeff i (gs ^ q)) ^ (p - 2) ≤ (p : ℚ) ^ i) ∧ + (∀ i, (p - 2) * q < i → padicNorm p (coeff i (gs ^ q)) ^ (p - 2) < (p : ℚ) ^ i) ∧ + padicNorm p (coeff ((p - 2) * q) (gs ^ q) - coeff (p - 2) gs ^ q) ^ (p - 2) < + (p : ℚ) ^ ((p - 2) * q) := by + have hp3 := p3 h2 + have hd : 0 < p - 2 := by omega + have hp0 : (0 : ℚ) < p := by exact_mod_cast hp.out.pos + induction q with + | zero => + refine ⟨fun i => ?_, fun i hi => ?_, ?_⟩ + · rw [pow_zero, coeff_one] + split_ifs with h + · subst h; simp + · simp [zero_pow hd.ne'] + · rw [pow_zero, coeff_one, if_neg (by omega)]; simp [zero_pow hd.ne']; positivity + · simp [zero_pow hd.ne'] + | succ q ih => + obtain ⟨P1, P2, P3⟩ := ih + have hterm : ∀ (a b : ℕ), padicNorm p (coeff a gs * coeff b (gs ^ q)) ^ (p - 2) ≤ + (p : ℚ) ^ (a + b) := by + intro a b + rw [padicNorm.mul, mul_pow, pow_add] + exact mul_le_mul (gs_bound h2 a) (P1 b) (pow_nonneg (padicNorm.nonneg _) _) (by positivity) + have hterm_lt : ∀ (a b : ℕ), (a ≠ 0 ∧ a ≠ p - 2) ∨ (p - 2) * q < b → + padicNorm p (coeff a gs * coeff b (gs ^ q)) ^ (p - 2) < (p : ℚ) ^ (a + b) := by + intro a b hab + rw [padicNorm.mul, mul_pow, pow_add] + rcases hab with ⟨ha0, had⟩ | hb + · calc padicNorm p (coeff a gs) ^ (p - 2) * padicNorm p (coeff b (gs ^ q)) ^ (p - 2) + ≤ padicNorm p (coeff a gs) ^ (p - 2) * (p : ℚ) ^ b := + mul_le_mul_of_nonneg_left (P1 b) (pow_nonneg (padicNorm.nonneg _) _) + _ < (p : ℚ) ^ a * (p : ℚ) ^ b := + mul_lt_mul_of_pos_right (gs_strict h2 a ha0 had) (by positivity) + · calc padicNorm p (coeff a gs) ^ (p - 2) * padicNorm p (coeff b (gs ^ q)) ^ (p - 2) + ≤ (p : ℚ) ^ a * padicNorm p (coeff b (gs ^ q)) ^ (p - 2) := + mul_le_mul_of_nonneg_right (gs_bound h2 a) (pow_nonneg (padicNorm.nonneg _) _) + _ < (p : ℚ) ^ a * (p : ℚ) ^ b := + mul_lt_mul_of_pos_left (P2 b hb) (by positivity) + refine ⟨fun i => ?_, fun i hi => ?_, ?_⟩ + · rw [pow_succ', coeff_mul] + refine norm_sum_pow_le _ _ _ _ (by positivity) hd (fun x hx => ?_) + have := hterm x.1 x.2 + rwa [(HasAntidiagonal.mem_antidiagonal.1 hx)] at this + · rw [pow_succ', coeff_mul] + refine norm_sum_pow_lt _ _ _ _ (by positivity) hd (fun x hx => ?_) + have hx' := HasAntidiagonal.mem_antidiagonal.1 hx + have := hterm_lt x.1 x.2 (by + by_cases ha0 : x.1 = 0 + · right; rw [mul_add, mul_one] at hi; omega + · by_cases had : x.1 = p - 2 + · right; rw [mul_add, mul_one] at hi; omega + · left; exact ⟨ha0, had⟩) + rwa [hx'] at this + · rw [pow_succ', coeff_mul] + have hmem : (p - 2, (p - 2) * q) ∈ antidiagonal ((p - 2) * (q + 1)) := by + rw [HasAntidiagonal.mem_antidiagonal]; ring + rw [← add_sum_erase _ _ hmem] + have : coeff (p - 2) gs * coeff ((p - 2) * q) (gs ^ q) + + ∑ x ∈ (antidiagonal ((p - 2) * (q + 1))).erase (p - 2, (p - 2) * q), + coeff x.1 gs * coeff x.2 (gs ^ q) - coeff (p - 2) gs ^ (q + 1) = + coeff (p - 2) gs * (coeff ((p - 2) * q) (gs ^ q) - coeff (p - 2) gs ^ q) + + ∑ x ∈ (antidiagonal ((p - 2) * (q + 1))).erase (p - 2, (p - 2) * q), + coeff x.1 gs * coeff x.2 (gs ^ q) := by ring + rw [this] + apply norm_add_pow_lt _ _ _ _ hd + · rw [padicNorm.mul, mul_pow, gs_d h2] + rw [show (p - 2) * (q + 1) = (p - 2) + (p - 2) * q by ring, pow_add] + exact mul_lt_mul_of_pos_left P3 (by positivity) + · refine norm_sum_pow_lt _ _ _ _ (by positivity) hd (fun x hx => ?_) + have hne := Finset.ne_of_mem_erase hx + have hx' := HasAntidiagonal.mem_antidiagonal.1 (Finset.mem_of_mem_erase hx) + have := hterm_lt x.1 x.2 (by + by_cases ha0 : x.1 = 0 + · right; rw [mul_add, mul_one] at hx'; omega + · by_cases had : x.1 = p - 2 + · exfalso; apply hne + ext + · exact had + · simp only; rw [mul_add, mul_one] at hx'; omega + · left; exact ⟨ha0, had⟩) + rwa [hx'] at this + +/-- `|[t^((p-2)q)] g^q|_p = p^q` for odd `p`. -/ +private lemma coeff_gs_pow_norm (q : ℕ) : + padicNorm p (coeff ((p - 2) * q) (gs ^ q)) = (p : ℚ) ^ q := by + have hp3 := p3 h2 + have hd : 0 < p - 2 := by omega + have P3 := (gs_pow_props h2 q).2.2 + set err := coeff ((p - 2) * q) (gs ^ q) - coeff (p - 2) gs ^ q + have hmain : padicNorm p (coeff (p - 2) gs ^ q) = (p : ℚ) ^ q := by + rw [padicNorm_pow, gs_d h2] + have herr : padicNorm p err < (p : ℚ) ^ q := by + rw [mul_comm, pow_mul] at P3 + exact lt_of_pow_lt_pow_left₀ _ (by positivity) P3 + have : coeff ((p - 2) * q) (gs ^ q) = coeff (p - 2) gs ^ q + err := by simp [err] + rw [this, padicNorm.add_eq_max_of_ne, hmain, max_eq_left (by rw [← hmain] at herr; linarith)] + rw [hmain]; exact herr.ne' + +/-- `|a((p-1)q, q)|_p = p^(V_p((p-1)q))` for odd `p`. -/ +private theorem aco_lower_odd (q : ℕ) : + padicNorm p (aco ((p - 1) * q) q) = (p : ℚ) ^ Vp p ((p - 1) * q) := by + have hp3 := p3 h2 + have hcoeff : coeff ((p - 1) * q) (hs ^ q) = coeff ((p - 2) * q) (gs ^ q) := by + rw [hs_eq, mul_pow, coeff_X_pow_mul', if_pos (Nat.le_mul_of_pos_left q (by omega))] + congr 1 + rw [show p - 1 = (p - 2) + 1 by omega, add_mul, one_mul, Nat.add_sub_cancel] + rw [aco, hcoeff, div_eq_mul_one_div, padicNorm.mul, coeff_gs_pow_norm h2, + padicNorm_one_div_fact, ← pow_add] + unfold Vp + rw [Nat.mul_div_cancel_left _ (by omega)] + +end odd + +end LowerBoundOdd + +section Monotone +open PowerSeries Finset + +/-- The polynomial `f_n(x) = [t^n] (t/(e^t-1))^x = B_n^(x) / n!`. -/ +private noncomputable def fpoly (n : ℕ) : Polynomial ℚ := + ∑ k ∈ range (n + 1), Polynomial.C (aco n k) * Polynomial.X ^ k + +/-- `a(n,k) = 0` for `k > n`. -/ +private lemma aco_eq_zero (n k : ℕ) (h : n < k) : aco n k = 0 := by + rw [aco, coeff_hs_pow_eq_zero k n h, zero_div] + +/-- The coefficients of `f_n` are the `a(n,k)`. -/ +private lemma coeff_fpoly (n k : ℕ) : (fpoly n).coeff k = aco n k := by + simp only [fpoly, Polynomial.finsetSum_coeff, Polynomial.coeff_C_mul_X_pow] + rw [sum_eq_single k] + · simp + · intro b _ hb; simp [Ne.symm hb] + · intro hk; simp at hk; simp [aco_eq_zero n k (by omega)] + +/-- `f_n(N) = [t^n] G^N` for natural `N`. -/ +private lemma eval_fpoly (n N : ℕ) : (fpoly n).eval (N : ℚ) = coeff n (Gs ^ N) := by + rw [← Ys_nat] + simp only [fpoly, Polynomial.eval_finsetSum, Polynomial.eval_mul, Polynomial.eval_C, + Polynomial.eval_pow, Polynomial.eval_X, Ys, coeff_mk, aco] + refine sum_congr rfl (fun k _ => by ring) + +/-- `t (G^N)' = N (G^N - t G^N - G^(N+1))`. -/ +private lemma X_Gs_pow_deriv (N : ℕ) : + X * d⁄dX ℚ (Gs ^ N) = (N : ℚ⟦X⟧) * (Gs ^ N - X * Gs ^ N - Gs ^ (N + 1)) := by + rw [Gs_pow_deriv] + have := X_hs' + calc X * ((N : ℚ⟦X⟧) * d⁄dX ℚ hs * Gs ^ N) = (N : ℚ⟦X⟧) * (X * d⁄dX ℚ hs) * Gs ^ N := by ring + _ = _ := by rw [this]; ring + +/-- Coefficient form of `X_Gs_pow_deriv`. -/ +private lemma f_rel (n N : ℕ) : + coeff (n + 1) (Gs ^ N) * (n + 1) = + N * (coeff (n + 1) (Gs ^ N) - coeff n (Gs ^ N) - coeff (n + 1) (Gs ^ (N + 1))) := by + have h := congrArg (coeff (n + 1)) (X_Gs_pow_deriv N) + rw [coeff_succ_X_mul, coeff_derivative] at h + rw [h] + rw [show ((N : ℚ⟦X⟧)) = PowerSeries.C (N : ℚ) by simp, coeff_C_mul, map_sub, map_sub, + coeff_succ_X_mul] + +/-- `x f_n(x) = (x - n - 1) f_{n+1}(x) - x f_{n+1}(x+1)`. -/ +private lemma fpoly_rel (n : ℕ) : + Polynomial.X * fpoly n = (Polynomial.X - Polynomial.C ((n : ℚ) + 1)) * fpoly (n + 1) - + Polynomial.X * (fpoly (n + 1)).comp (Polynomial.X + 1) := by + apply Polynomial.eq_of_infinite_eval_eq + apply Set.Infinite.mono (s := Set.range (fun N : ℕ => (N : ℚ))) + · rintro _ ⟨N, rfl⟩ + simp only [Set.mem_ofPred_eq, Polynomial.eval_mul, Polynomial.eval_X, Polynomial.eval_sub, + Polynomial.eval_C, Polynomial.eval_comp, Polynomial.eval_add, Polynomial.eval_one] + rw [show (N : ℚ) + 1 = ((N + 1 : ℕ) : ℚ) by push_cast; ring, eval_fpoly, eval_fpoly, + eval_fpoly] + linear_combination (f_rel n N) + · exact Set.infinite_range_of_injective Nat.cast_injective + +variable {p : ℕ} [hp : Fact p.Prime] + +/-- Substituting `x ↦ x + 1` preserves strict `p`-adic bounds on all coefficients. -/ +private lemma comp_coeff_lt (P : Polynomial ℚ) (C : ℚ) (hC : 0 < C) + (h : ∀ j, padicNorm p (P.coeff j) < C) (k : ℕ) : + padicNorm p ((P.comp (Polynomial.X + 1)).coeff k) < C := by + rw [Polynomial.comp_eq_sum_left, Polynomial.sum_def, Polynomial.finsetSum_coeff] + refine padicNorm.sum_lt' (fun j _ => ?_) hC + rw [Polynomial.coeff_C_mul, Polynomial.coeff_X_add_one_pow, padicNorm.mul] + calc padicNorm p (P.coeff j) * padicNorm p ((j.choose k : ℕ) : ℚ) + ≤ padicNorm p (P.coeff j) * 1 := + mul_le_mul_of_nonneg_left (padicNorm.of_nat _) (padicNorm.nonneg _) + _ < C := by rw [mul_one]; exact h j + +/-- If all coefficients of `f_{n+1}` have `p`-adic norm `< C`, so do those of `f_n`. -/ +private lemma aco_mono (n : ℕ) (C : ℚ) (hC : 0 < C) (h : ∀ k, padicNorm p (aco (n + 1) k) < C) (k : ℕ) : + padicNorm p (aco n k) < C := by + have hrel := congrArg (fun P => Polynomial.coeff P (k + 1)) (fpoly_rel n) + rw [Polynomial.coeff_X_mul, Polynomial.coeff_sub, Polynomial.coeff_X_mul, sub_mul, + Polynomial.coeff_sub, Polynomial.coeff_X_mul, Polynomial.coeff_C_mul, coeff_fpoly, + coeff_fpoly, coeff_fpoly] at hrel + rw [hrel] + have h3 := comp_coeff_lt (p := p) (fpoly (n + 1)) C hC (fun j => by rw [coeff_fpoly]; exact h j) k + refine lt_of_le_of_lt padicNorm.sub (max_lt (lt_of_le_of_lt padicNorm.sub (max_lt (h k) ?_)) h3) + rw [padicNorm.mul] + calc padicNorm p ((n : ℚ) + 1) * padicNorm p (aco (n + 1) (k + 1)) + ≤ 1 * padicNorm p (aco (n + 1) (k + 1)) := + mul_le_mul_of_nonneg_right (by exact_mod_cast padicNorm.of_nat (p := p) (n + 1)) + (padicNorm.nonneg _) + _ < C := by rw [one_mul]; exact h (k + 1) + +/-- The `p`-content of `f_n` is exactly `p^(V_p(n))`. -/ +private theorem aco_content (n : ℕ) : + (∀ k, padicNorm p (aco n k) ≤ (p : ℚ) ^ Vp p n) ∧ + ∃ k, (p : ℚ) ^ Vp p n ≤ padicNorm p (aco n k) := by + refine ⟨fun k => aco_upper n k, ?_⟩ + by_cases h2 : p = 2 + · subst h2; exact ⟨n, (aco_lower_two n).ge⟩ + by_contra hcon + push Not at hcon + have hp3 : 3 ≤ p := by have := hp.out.two_le; omega + set q := n / (p - 1) + set m := (p - 1) * q + have hm : m ≤ n := by simp only [m, q]; exact Nat.mul_div_le n (p - 1) + have hV : Vp p m = Vp p n := by + simp only [Vp, m, q] + rw [Nat.mul_div_cancel_left _ (by omega)] + have hdown : ∀ j, j ≤ n - m → ∀ k, padicNorm p (aco (n - j) k) < (p : ℚ) ^ Vp p n := by + intro j + induction j with + | zero => intro _ k; simpa using hcon k + | succ j ih => + intro hj k + have := ih (by omega) + have e : n - j = (n - (j + 1)) + 1 := by omega + rw [e] at this + exact aco_mono _ _ (by positivity) this k + have := hdown (n - m) le_rfl q + rw [show n - (n - m) = m by omega, aco_lower_odd h2 q, hV] at this + exact lt_irrefl _ this + +end Monotone + +section NorlundLists +open Finset Math0.Statements.A342645 + +/-- The polynomial with rational coefficient list `l` (lowest degree first). -/ +private noncomputable def toPolyQ : List ℚ → Polynomial ℚ + | [] => 0 + | a :: l => Polynomial.C a + Polynomial.X * toPolyQ l + +/-- Coefficients of `toPolyQ`. -/ +private lemma coeff_toPolyQ (l : List ℚ) (k : ℕ) : (toPolyQ l).coeff k = l.getD k 0 := by + induction l generalizing k with + | nil => simp [toPolyQ] + | cons a l ih => + cases k with + | zero => simp [toPolyQ] + | succ k => simp [toPolyQ, Polynomial.coeff_X_mul, ih] + +/-- `addQ` is polynomial addition. -/ +private lemma toPolyQ_addQ (a b : List ℚ) : toPolyQ (addQ a b) = toPolyQ a + toPolyQ b := by + induction a generalizing b with + | nil => simp [addQ, toPolyQ] + | cons x a ih => + cases b with + | nil => simp [addQ, toPolyQ] + | cons y b => simp only [addQ, toPolyQ, ih, map_add]; ring + +/-- Scaling a coefficient list. -/ +private lemma toPolyQ_map_mul (c : ℚ) (l : List ℚ) : + toPolyQ (l.map (fun a => c * a)) = Polynomial.C c * toPolyQ l := by + induction l with + | nil => simp [toPolyQ] + | cons x l ih => simp only [List.map_cons, toPolyQ, ih, map_mul]; ring + +/-- `mulQ` is polynomial multiplication. -/ +private lemma toPolyQ_mulQ (a b : List ℚ) : toPolyQ (mulQ a b) = toPolyQ a * toPolyQ b := by + induction a with + | nil => simp [mulQ, toPolyQ] + | cons x a ih => + have : mulQ (x :: a) b = addQ (b.map (x * ·)) (0 :: mulQ a b) := rfl + rw [this, toPolyQ_addQ, toPolyQ_map_mul, toPolyQ, toPolyQ, ih, map_zero] + ring + +/-- Entries of a truncated list. -/ +private lemma getD_take (l : List ℚ) (m i : ℕ) : + (l.take m).getD i 0 = if i < m then l.getD i 0 else 0 := by + induction l generalizing m i with + | nil => simp + | cons a l ih => + cases m with + | zero => simp + | succ m => + cases i with + | zero => simp + | succ i => simp only [List.take_succ_cons, List.getD_cons_succ, ih]; split_ifs <;> first | rfl | omega + +/-- Truncating above degree `n` does not change the degree-`n` coefficient of a product. -/ +private lemma coeff_take_mul (l : List ℚ) (B : Polynomial ℚ) (n : ℕ) : + (toPolyQ (l.take (n + 1)) * B).coeff n = (toPolyQ l * B).coeff n := by + rw [Polynomial.coeff_mul, Polynomial.coeff_mul] + refine sum_congr rfl (fun x hx => ?_) + have := HasAntidiagonal.mem_antidiagonal.1 hx + rw [coeff_toPolyQ, coeff_toPolyQ, getD_take, if_pos (by omega)] + +/-- Length of `powsH`. -/ +private lemma powsH_length (n : ℕ) (H : List ℚ) (k : ℕ) (P : List ℚ) : (powsH n H k P).length = k := by + induction k generalizing P with + | zero => rfl + | succ k ih => simp [powsH, ih] + +/-- `powsH` lists the coefficients `[t^n] P H^j`. -/ +private lemma powsH_getD (n : ℕ) (H : List ℚ) (k : ℕ) (P : List ℚ) (j : ℕ) : + (powsH n H k P).getD j 0 = + if j < k then (toPolyQ P * toPolyQ H ^ j).coeff n else 0 := by + induction k generalizing P j with + | zero => simp [powsH] + | succ k ih => + cases j with + | zero => simp [powsH, coeff_toPolyQ] + | succ j => + simp only [powsH, List.getD_cons_succ, ih] + split_ifs with h1 h2 h2 + · rw [coeff_take_mul, toPolyQ_mulQ, pow_succ]; ring_nf + · omega + · omega + · rfl + +/-- `descQ j` is the falling factorial `x(x-1)⋯(x-j+1)`. -/ +private lemma toPolyQ_descQ (j : ℕ) : toPolyQ (descQ j) = descPochhammer ℚ j := by + induction j with + | zero => simp [descQ, toPolyQ] + | succ j ih => + simp only [descQ] + rw [toPolyQ_addQ, toPolyQ, toPolyQ_map_mul, ih, descPochhammer_succ_right, map_zero, zero_add] + rw [show ((j : Polynomial ℚ)) = Polynomial.C (j : ℚ) by simp] + rw [map_neg]; ring + +/-- The polynomial computed by `norlundAux`. -/ +private lemma toPolyQ_norlundAux (n j : ℕ) (cs : List ℚ) : + toPolyQ (norlundAux n j cs) = ∑ i ∈ range cs.length, + Polynomial.C ((n.factorial : ℚ) * cs.getD i 0 / ((j + i).factorial : ℚ)) * + descPochhammer ℚ (j + i) := by + induction cs generalizing j with + | nil => simp [norlundAux, toPolyQ] + | cons c cs ih => + simp only [norlundAux] + rw [toPolyQ_addQ, toPolyQ_map_mul, toPolyQ_descQ, ih, List.length_cons, sum_range_succ'] + simp only [List.getD_cons_zero, List.getD_cons_succ, add_zero] + rw [add_comm] + congr 1 + refine sum_congr rfl (fun i _ => ?_) + rw [show j + 1 + i = j + (i + 1) by ring] + +end NorlundLists + +section BernoulliLists +open Finset Math0.Statements.A342645 PowerSeries + +/-- List sums over `List.range` are `Finset` sums. -/ +private lemma list_sum_map_range (f : ℕ → ℚ) (n : ℕ) : + ((List.range n).map f).sum = ∑ i ∈ range n, f i := by + induction n with + | zero => simp + | succ n ih => rw [List.range_succ, List.map_append, List.sum_append, ih, sum_range_succ]; simp + +/-- The recursion defining `revG`, satisfied by `G_k = B_k/k!`. -/ +private lemma G_rec (k : ℕ) : + G (k + 1) = -∑ i ∈ range (k + 1), G (k - i) / ((i + 2).factorial : ℚ) := by + have h := congrArg (coeff (k + 1)) Gs_mul_Es + rw [coeff_mul, coeff_one, if_neg (by omega), ← Finset.Nat.sum_antidiagonal_swap] at h + simp only [Prod.fst_swap, Prod.snd_swap] at h + rw [Finset.Nat.sum_antidiagonal_eq_sum_range_succ (fun b a => coeff a Gs * coeff b Es), + sum_range_succ'] at h + simp only [Gs, Es, coeff_mk, Nat.sub_zero, zero_add, Nat.factorial_one, Nat.cast_one, + div_one, mul_one] at h + have h2 : ∑ i ∈ range (k + 1), G (k + 1 - (i + 1)) * (1 / ((i + 1 + 1).factorial : ℚ)) = + ∑ i ∈ range (k + 1), G (k - i) / ((i + 2).factorial : ℚ) := by + refine sum_congr rfl (fun i _ => ?_) + rw [show k + 1 - (i + 1) = k - i by omega]; ring + rw [h2] at h + linarith + +/-- `revG k = [G_k, …, G_0]`. -/ +private lemma revG_eq (k : ℕ) : revG k = (List.range (k + 1)).map (fun i => G (k - i)) := by + induction k with + | zero => simp [revG, G_zero] + | succ k ih => + rw [revG, ih, List.zipWith_map_left, List.zipWith_self, list_sum_map_range, + List.range_succ_eq_map (n := k + 1), List.map_cons, List.map_map] + congr 1 + · rw [Nat.sub_zero, G_rec] + · refine List.map_congr_left (fun i _ => ?_) + simp + +/-- `bernG n = [G_0, …, G_n]`. -/ +private lemma bernG_getD (n i : ℕ) : (bernG n).getD i 0 = if i ≤ n then G i else 0 := by + rw [bernG, revG_eq, List.getD_eq_getElem?_getD] + split_ifs with h + · rw [List.getElem?_reverse (by simp; omega)] + simp only [List.length_map, List.length_range, List.getElem?_map] + rw [List.getElem?_range (by omega)] + simp only [Option.map_some, Option.getD_some] + congr 1; omega + · rw [List.getElem?_eq_none (by simp; omega)]; rfl + +/-- `Hser n = [0, G_1, …, G_n]`. -/ +private lemma Hser_getD (n i : ℕ) : (Hser n).getD i 0 = if 1 ≤ i ∧ i ≤ n then G i else 0 := by + rcases i with _ | i + · simp [Hser] + · simp only [Hser, List.getD_cons_succ] + rw [show (bernG n).tail.getD i 0 = (bernG n).getD (i + 1) 0 by + rcases h : bernG n with _ | ⟨a, l⟩ + · simp + · simp] + rw [bernG_getD] + split_ifs <;> first | rfl | omega + +end BernoulliLists + +section NorlundPoly +open Finset Math0.Statements.A342645 PowerSeries + +/-- `G - 1` has no constant term. -/ +private lemma constantCoeff_Gs_sub_one : constantCoeff (Gs - 1) = 0 := by + simp [Gs, G_zero] + +/-- `[t^n] (G-1)^i = 0` for `n < i`. -/ +private lemma coeff_Gs_sub_one_pow_eq_zero (i n : ℕ) (h : n < i) : coeff n ((Gs - 1) ^ i) = 0 := by + have h1 : (X : ℚ⟦X⟧) ∣ Gs - 1 := X_dvd_iff.2 constantCoeff_Gs_sub_one + exact X_pow_dvd_iff.1 (pow_dvd_pow_of_dvd h1 i) n h + +/-- Degree-`n` coefficients of powers of the truncation `Hser n` agree with those of `G - 1`. -/ +private lemma coeff_Hpoly_pow (n j : ℕ) : + (toPolyQ (Hser n) ^ j).coeff n = coeff n ((Gs - 1) ^ j) := by + have h1 : (X : ℚ⟦X⟧) ^ (n + 1) ∣ (toPolyQ (Hser n) : ℚ⟦X⟧) - (Gs - 1) := by + rw [X_pow_dvd_iff] + intro m hm + rw [map_sub, Polynomial.coeff_coe, coeff_toPolyQ, Hser_getD, map_sub, coeff_one] + simp only [Gs, coeff_mk] + rcases m with _ | m + · simp [G_zero] + · rw [if_pos ⟨by omega, by omega⟩, if_neg (by omega)]; ring + have h2 := X_pow_dvd_iff.1 (h1.trans (sub_dvd_pow_sub_pow _ _ j)) n (by omega) + rw [map_sub, ← Polynomial.coe_pow, Polynomial.coeff_coe] at h2 + exact sub_eq_zero.1 h2 + +/-- The list `powsH n (Hser n) (n+1) [1]` is `[t^n] (G-1)^j`, `j ≤ n`. -/ +private lemma norlund_cs (n i : ℕ) : + (powsH n (Hser n) (n + 1) [1]).getD i 0 = + if i < n + 1 then coeff n ((Gs - 1) ^ i) else 0 := by + rw [powsH_getD] + split_ifs + · rw [show toPolyQ [1] = 1 by simp [toPolyQ], one_mul, coeff_Hpoly_pow] + · rfl + +/-- `norlund n = ∑_j (n!/j!) [t^n](G-1)^j x(x-1)⋯(x-j+1)`. -/ +private lemma toPolyQ_norlund (n : ℕ) : toPolyQ (norlund n) = ∑ i ∈ range (n + 1), + Polynomial.C ((n.factorial : ℚ) * coeff n ((Gs - 1) ^ i) / (i.factorial : ℚ)) * + descPochhammer ℚ i := by + rw [norlund, toPolyQ_norlundAux, powsH_length] + refine sum_congr rfl (fun i hi => ?_) + rw [norlund_cs, if_pos (mem_range.1 hi), zero_add] + +/-- `norlund n` evaluated at `N` is `n! [t^n] G^N`. -/ +private lemma eval_norlund (n N : ℕ) : + (toPolyQ (norlund n)).eval (N : ℚ) = n.factorial * coeff n (Gs ^ N) := by + rw [toPolyQ_norlund, Polynomial.eval_finsetSum] + simp only [Polynomial.eval_mul, Polynomial.eval_C, descPochhammer_eval_eq_descFactorial, + Nat.descFactorial_eq_factorial_mul_choose] + have hpow : Gs ^ N = ∑ i ∈ range (N + 1), (Gs - 1) ^ i * (N.choose i : ℚ⟦X⟧) := by + have := add_pow (Gs - 1) 1 N + simp only [one_pow, mul_one] at this + rw [← this]; ring + rw [hpow, map_sum, mul_sum] + have e1 : ∀ i ∈ range (n + 1), (n.factorial : ℚ) * coeff n ((Gs - 1) ^ i) / (i.factorial : ℚ) * + (((i.factorial * N.choose i : ℕ)) : ℚ) = + n.factorial * (coeff n ((Gs - 1) ^ i) * (N.choose i : ℚ)) := by + intro i _ + have : (i.factorial : ℚ) ≠ 0 := by positivity + push_cast; field_simp + have e2 : ∀ i ∈ range (N + 1), (n.factorial : ℚ) * coeff n ((Gs - 1) ^ i * (N.choose i : ℚ⟦X⟧)) = + n.factorial * (coeff n ((Gs - 1) ^ i) * (N.choose i : ℚ)) := by + intro i _ + rw [show ((N.choose i : ℕ) : ℚ⟦X⟧) = PowerSeries.C ((N.choose i : ℕ) : ℚ) by simp, + coeff_mul_C] + rw [sum_congr rfl e1, sum_congr rfl e2, ← mul_sum, ← mul_sum] + congr 1 + have hsub1 : range (n + 1) ⊆ range (n + N + 1) := range_subset_range.2 (by omega) + have hsub2 : range (N + 1) ⊆ range (n + N + 1) := range_subset_range.2 (by omega) + rw [sum_subset hsub1, sum_subset hsub2] + · intro i hi hi' + simp only [mem_range] at hi hi' + rw [Nat.choose_eq_zero_of_lt (by omega)]; simp + · intro i hi hi' + simp only [mem_range] at hi hi' + rw [coeff_Gs_sub_one_pow_eq_zero i n (by omega)]; simp + +/-- `norlund n` is the coefficient list of `n! f_n`. -/ +private lemma toPolyQ_norlund_eq (n : ℕ) : + toPolyQ (norlund n) = Polynomial.C (n.factorial : ℚ) * fpoly n := by + apply Polynomial.eq_of_infinite_eval_eq + apply Set.Infinite.mono (s := Set.range (fun N : ℕ => (N : ℚ))) + · rintro _ ⟨N, rfl⟩ + simp only [Set.mem_ofPred_eq, Polynomial.eval_mul, Polynomial.eval_C] + rw [eval_norlund, eval_fpoly] + · exact Set.infinite_range_of_injective Nat.cast_injective + +/-- The `k`-th entry of `norlund n` is `n! a(n,k)`. -/ +private theorem norlund_getD (n k : ℕ) : (norlund n).getD k 0 = n.factorial * aco n k := by + rw [← coeff_toPolyQ, toPolyQ_norlund_eq, Polynomial.coeff_C_mul, coeff_fpoly] + +end NorlundPoly + +section LcmDen +open Finset Math0.Statements.A342645 PowerSeries + +variable {p : ℕ} [hp : Fact p.Prime] + +/-- `v_p(den c) ≤ e ↔ |c|_p ≤ p^e`. -/ +private lemma den_val_le_iff (c : ℚ) (e : ℕ) : + padicValNat p c.den ≤ e ↔ padicNorm p c ≤ (p : ℚ) ^ e := by + have hp1 : (1 : ℚ) < p := by exact_mod_cast hp.out.one_lt + by_cases hc : c = 0 + · subst hc; simp + rw [padicNorm.eq_zpow_of_nonzero hc, padicValRat_def] + by_cases hd : p ∣ c.den + · have hnum : padicValInt p c.num = 0 := by + apply padicValInt.eq_zero_of_not_dvd + intro hn + have hcop := c.reduced + have h1 : p ∣ c.num.natAbs := by + rw [← Int.natCast_dvd_natCast, Int.natCast_natAbs]; exact (dvd_abs _ _).2 hn + exact hp.out.one_lt.ne' (Nat.dvd_one.1 ((Nat.dvd_gcd h1 hd).trans + (by rw [hcop.gcd_eq_one]))) + rw [hnum] + simp only [Nat.cast_zero, zero_sub, neg_neg, zpow_natCast] + exact (pow_le_pow_iff_right₀ hp1).symm + · rw [padicValNat.eq_zero_of_not_dvd hd] + simp only [Nat.cast_zero, sub_zero, zero_le, true_iff] + refine le_trans (zpow_le_one_of_nonpos₀ hp1.le ?_) (one_le_pow₀ hp1.le) + simp + +/-- `lcmDen` is positive. -/ +private lemma lcmDen_ne_zero (l : List ℚ) : lcmDen l ≠ 0 := by + induction l with + | nil => simp [lcmDen] + | cons c l ih => + simp only [lcmDen, List.map_cons, List.foldr_cons] at ih ⊢ + exact Nat.lcm_ne_zero c.den_nz ih + +/-- `v_p(lcmDen l) ≤ e` iff every entry `c` has `v_p(den c) ≤ e`. -/ +private lemma val_lcmDen_le_iff (l : List ℚ) (e : ℕ) : + padicValNat p (lcmDen l) ≤ e ↔ ∀ c ∈ l, padicValNat p c.den ≤ e := by + induction l with + | nil => simp [lcmDen] + | cons c l ih => + have hne := lcmDen_ne_zero l + simp only [lcmDen, List.map_cons, List.foldr_cons] at ih hne ⊢ + rw [← Nat.factorization_def _ hp.out, Nat.factorization_lcm c.den_nz hne, + Finsupp.sup_apply, Nat.factorization_def _ hp.out, Nat.factorization_def _ hp.out, + sup_le_iff, ih] + simp + +/-- Each denominator divides `lcmDen`. -/ +private lemma den_dvd_lcmDen (l : List ℚ) (c : ℚ) (hc : c ∈ l) : c.den ∣ lcmDen l := by + induction l with + | nil => simp at hc + | cons a l ih => + simp only [lcmDen, List.map_cons, List.foldr_cons] at ih ⊢ + rcases List.mem_cons.1 hc with rfl | h + · exact Nat.dvd_lcm_left _ _ + · exact (ih h).trans (Nat.dvd_lcm_right _ _) + +/-- A nonzero `getD` entry belongs to the list. -/ +private lemma mem_of_getD_ne_zero (l : List ℚ) (k : ℕ) (h : l.getD k 0 ≠ 0) : l.getD k 0 ∈ l := by + rw [List.getD_eq_getElem?_getD] at h ⊢ + rcases hk : l[k]? with _ | c + · rw [hk] at h; simp at h + · simp only [Option.getD_some] + exact List.mem_of_getElem? hk + +/-- Every element of a list is a `getD` entry. -/ +private lemma getD_of_mem (l : List ℚ) (c : ℚ) (hc : c ∈ l) : ∃ k, l.getD k 0 = c := by + obtain ⟨k, hk, rfl⟩ := List.getElem_of_mem hc + exact ⟨k, by rw [List.getD_eq_getElem?_getD, List.getElem?_eq_getElem hk]; rfl⟩ + +/-- `v_p(n!) ≤ V_p(n)`. -/ +private lemma fact_val_le_Vp (n : ℕ) : padicValNat p n.factorial ≤ Vp p n := by + unfold Vp + have hp1 : 0 < p - 1 := by have := hp.out.two_le; omega + have h1 := sub_one_mul_padicValNat_factorial (p := p) n + have : padicValNat p n.factorial ≤ n / (p - 1) := by + rw [Nat.le_div_iff_mul_le hp1, mul_comm, h1]; omega + omega + +omit hp in +/-- `|n!|_p = p^(-v_p(n!))`. -/ +private lemma padicNorm_fact (n : ℕ) : + padicNorm p (n.factorial : ℚ) = ((p : ℚ) ^ padicValNat p n.factorial)⁻¹ := + padicNorm_natCast_eq _ (Nat.factorial_pos n) + +/-- `v_p(lcmDen (norlund n)) = V_p(n) - v_p(n!)`. -/ +private theorem val_lcmDen_norlund (n : ℕ) : + padicValNat p (lcmDen (norlund n)) = Vp p n - padicValNat p n.factorial := by + have hp1 : (1 : ℚ) < p := by exact_mod_cast hp.out.one_lt + have hp0 : (0 : ℚ) < p := by positivity + obtain ⟨hup, k, hlow⟩ := aco_content (p := p) n + have hF := fact_val_le_Vp (p := p) n + set e := Vp p n - padicValNat p n.factorial + have hnorm : ∀ k, padicNorm p ((norlund n).getD k 0) = + ((p : ℚ) ^ padicValNat p n.factorial)⁻¹ * padicNorm p (aco n k) := by + intro k; rw [norlund_getD, padicNorm.mul, padicNorm_fact] + have hsplit : (p : ℚ) ^ Vp p n = (p : ℚ) ^ padicValNat p n.factorial * (p : ℚ) ^ e := by + rw [← pow_add]; congr 1; omega + apply le_antisymm + · rw [val_lcmDen_le_iff] + intro c hc + obtain ⟨j, rfl⟩ := getD_of_mem _ c hc + rw [den_val_le_iff, hnorm, inv_mul_le_iff₀ (by positivity), ← hsplit] + exact hup j + · by_contra hlt + push Not at hlt + have hc : padicNorm p ((norlund n).getD k 0) ≥ (p : ℚ) ^ e := by + rw [hnorm, ge_iff_le, le_inv_mul_iff₀ (by positivity), ← hsplit]; exact hlow + have hne : (norlund n).getD k 0 ≠ 0 := by + intro h0; rw [h0, padicNorm.zero] at hc + exact absurd hc (not_le.2 (by positivity)) + have hmem := mem_of_getD_ne_zero _ k hne + have h1 := (val_lcmDen_le_iff (p := p) (norlund n) (e - 1)).1 (by omega) _ hmem + rw [den_val_le_iff] at h1 + have : (p : ℚ) ^ e ≤ (p : ℚ) ^ (e - 1) := le_trans hc h1 + have := (pow_le_pow_iff_right₀ hp1).1 this + omega + +end LcmDen + +section LeadingCoefficient +open Finset Math0.Statements.A342645 PowerSeries + +/-- The exponent of `p` in the product defining `A053657(n+1)` is `V_p(n)`. -/ +private lemma exp_eq_Vp (p n : ℕ) [hp : Fact p.Prime] : + ∑ k ∈ range (n + 1), n / ((p - 1) * p ^ k) = Vp p n := by + have h1 : ∀ k, n / ((p - 1) * p ^ k) = n / (p - 1) / p ^ k := fun k => + (Nat.div_div_eq_div_mul n (p - 1) (p ^ k)).symm + simp only [h1] + rw [sum_range_succ', pow_zero, Nat.div_one, Vp, add_comm] + congr 1 + rw [padicValNat_factorial (b := n + 1)] + · rw [sum_Ico_eq_sum_range] + refine sum_congr (by simp) (fun k _ => ?_) + rw [add_comm] + · have : n / (p - 1) ≤ n := Nat.div_le_self _ _ + have := Nat.log_le_self p (n / (p - 1)) + omega + +/-- `v_p(A053657(n+1)) = V_p(n)`. -/ +private lemma factorization_A053657 (n p : ℕ) (hp : p.Prime) : + (A053657 (n + 1)).factorization p = Vp p n := by + have : Fact p.Prime := ⟨hp⟩ + unfold A053657 + rw [Nat.factorization_prod (fun q hq => pow_ne_zero _ (Nat.Prime.ne_zero (mem_filter.1 hq).2))] + rw [Finset.sum_apply'] + simp only [Nat.factorization_pow, Finsupp.smul_apply, smul_eq_mul, Nat.add_sub_cancel] + by_cases hpS : p ∈ (range (n + 1 + 1)).filter Nat.Prime + · rw [sum_eq_single p] + · rw [hp.factorization_self, mul_one, exp_eq_Vp] + · intro q hq hqp + rw [(mem_filter.1 hq).2.factorization, Finsupp.single_eq_of_ne hqp.symm, mul_zero] + · intro h; exact absurd hpS h + · rw [sum_eq_zero] + · have : n + 1 < p := by + simp only [mem_filter, mem_range, not_and] at hpS + by_contra h; exact hpS (by omega) hp + simp [Vp, Nat.div_eq_of_lt (show n < p - 1 by omega)] + · intro q hq + have hqp : q ≠ p := fun h => hpS (h ▸ hq) + rw [(mem_filter.1 hq).2.factorization, Finsupp.single_eq_of_ne hqp.symm, mul_zero] + +/-- `lcmDen (norlund n) · n! = A053657(n+1)`. -/ +private theorem lcmDen_mul_fact (n : ℕ) : lcmDen (norlund n) * n.factorial = A053657 (n + 1) := by + have hA : A053657 (n + 1) ≠ 0 := by + unfold A053657 + exact prod_ne_zero_iff.2 (fun q hq => pow_ne_zero _ (Nat.Prime.ne_zero (mem_filter.1 hq).2)) + apply Nat.eq_of_factorization_eq (mul_ne_zero (lcmDen_ne_zero _) (Nat.factorial_ne_zero _)) hA + intro p + by_cases hp : p.Prime + · have : Fact p.Prime := ⟨hp⟩ + rw [factorization_A053657 n p hp, Nat.factorization_mul (lcmDen_ne_zero _) + (Nat.factorial_ne_zero _), Finsupp.add_apply, Nat.factorization_def _ hp, + Nat.factorization_def _ hp, val_lcmDen_norlund] + have := fact_val_le_Vp (p := p) n + omega + · rw [Nat.factorization_eq_zero_of_not_prime _ hp, Nat.factorization_eq_zero_of_not_prime _ hp] + +/-- The leading coefficient of `B_n^(x)` is `(-1/2)^n`. -/ +private lemma norlund_getD_self (n : ℕ) : (norlund n).getD n 0 = (-1 / 2 : ℚ) ^ n := by + rw [norlund_getD, aco_self] + have : (n.factorial : ℚ) ≠ 0 := by positivity + field_simp + +/-- `|A290030(n) / A053657(n+1)| = 1/(2^n n!)`. -/ +private theorem A290030_ratio (n : ℕ) : + |(A290030 n : ℚ) / (A053657 (n + 1) : ℚ)| = 1 / (2 ^ n * (n.factorial : ℚ)) := by + set L := lcmDen (norlund n) with hL + have hmem : (-1 / 2 : ℚ) ^ n ∈ norlund n := by + rw [← norlund_getD_self] + exact mem_of_getD_ne_zero _ _ (by rw [norlund_getD_self]; positivity) + have hden : ((-1 / 2 : ℚ) ^ n).den = 2 ^ n := by + rw [Rat.den_pow]; congr 1; norm_num + have hdvd : 2 ^ n ∣ L := hden ▸ den_dvd_lcmDen _ _ hmem + obtain ⟨M, hM⟩ := hdvd + have hL0 : L ≠ 0 := lcmDen_ne_zero _ + have hM0 : M ≠ 0 := by rintro rfl; simp at hM; exact hL0 hM + have hA : A290030 n = (-1) ^ n * (M : ℤ) := by + unfold A290030 + rw [← hL, norlund_getD_self, hM] + have : ((2 ^ n * M : ℕ) : ℚ) * (-1 / 2 : ℚ) ^ n = (((-1) ^ n * (M : ℤ) : ℤ) : ℚ) := by + push_cast + rw [div_pow, mul_div_assoc'] + field_simp + rw [this, Rat.num_intCast] + rw [hA, ← lcmDen_mul_fact, ← hL, hM] + push_cast + rw [abs_div, abs_mul, abs_pow, abs_neg, abs_one, one_pow, one_mul] + have hM' : (0 : ℚ) < M := by exact_mod_cast Nat.pos_of_ne_zero hM0 + rw [abs_of_pos hM', abs_of_pos (by positivity)] + have : (n.factorial : ℚ) ≠ 0 := by positivity + field_simp + +end LeadingCoefficient + +section TriangleLists +open Finset Math0.Statements.A342645 + +/-- The rational polynomial with integer coefficient list `l` (lowest degree first). -/ +private noncomputable def toPolyZ : List ℤ → Polynomial ℚ + | [] => 0 + | a :: l => Polynomial.C (a : ℚ) + Polynomial.X * toPolyZ l + +/-- Coefficients of `toPolyZ`. -/ +private lemma coeff_toPolyZ (l : List ℤ) (k : ℕ) : (toPolyZ l).coeff k = ((l.getD k 0 : ℤ) : ℚ) := by + induction l generalizing k with + | nil => simp [toPolyZ] + | cons a l ih => + cases k with + | zero => simp [toPolyZ] + | succ k => + simp only [toPolyZ, Polynomial.coeff_add, Polynomial.coeff_C, Polynomial.coeff_X_mul, ih, + List.getD_cons_succ] + simp + +/-- `addZ` is polynomial addition. -/ +private lemma toPolyZ_addZ (a b : List ℤ) : toPolyZ (addZ a b) = toPolyZ a + toPolyZ b := by + induction a generalizing b with + | nil => simp [addZ, toPolyZ] + | cons x a ih => + cases b with + | nil => simp [addZ, toPolyZ] + | cons y b => simp only [addZ, toPolyZ, ih, Int.cast_add, map_add]; ring + +/-- Scaling a coefficient list. -/ +private lemma toPolyZ_map_mul (c : ℤ) (l : List ℤ) : + toPolyZ (l.map (fun a => c * a)) = Polynomial.C (c : ℚ) * toPolyZ l := by + induction l with + | nil => simp [toPolyZ] + | cons x l ih => simp only [List.map_cons, toPolyZ, ih, Int.cast_mul, map_mul]; ring + +/-- `mulXsub c` multiplies by `x - c`. -/ +private lemma toPolyZ_mulXsub (c : ℤ) (l : List ℤ) : + toPolyZ (mulXsub c l) = (Polynomial.X - Polynomial.C (c : ℚ)) * toPolyZ l := by + unfold mulXsub + rw [toPolyZ_addZ, toPolyZ, toPolyZ_map_mul] + simp only [Int.cast_zero, map_zero, zero_add, Int.cast_neg, map_neg] + ring + +/-- `fallingFrom c j` is `(x-c)(x-c-1)⋯(x-c-j+1)`. -/ +private lemma toPolyZ_fallingFrom (c j : ℕ) : + toPolyZ (fallingFrom c j) = + (descPochhammer ℚ j).comp (Polynomial.X - Polynomial.C (c : ℚ)) := by + induction j with + | zero => simp [fallingFrom, toPolyZ] + | succ j ih => + rw [fallingFrom, toPolyZ_mulXsub, ih, descPochhammer_succ_right, Polynomial.mul_comp, + Polynomial.sub_comp, Polynomial.X_comp] + rw [show ((j : Polynomial ℚ)) = Polynomial.C (j : ℚ) by simp, Polynomial.C_comp] + push_cast + rw [map_add]; ring + +/-- The polynomial computed by `newton`. -/ +private lemma toPolyZ_newton (n j : ℕ) (ds : List ℤ) : + toPolyZ (newton n j ds) = ∑ i ∈ range ds.length, + Polynomial.C (((ds.getD i 0 : ℤ) : ℚ) * ((n.factorial / (j + i).factorial : ℕ) : ℚ)) * + (descPochhammer ℚ (j + i)).comp (Polynomial.X - Polynomial.C (n : ℚ)) := by + induction ds generalizing j with + | nil => simp [newton, toPolyZ] + | cons d ds ih => + rw [newton, toPolyZ_addZ, toPolyZ_map_mul, toPolyZ_fallingFrom, ih, List.length_cons, + sum_range_succ'] + simp only [List.getD_cons_zero, List.getD_cons_succ, add_zero] + rw [add_comm] + congr 1 + · refine sum_congr rfl (fun i _ => ?_) + rw [show j + 1 + i = j + (i + 1) by ring] + · rw [mul_comm, Int.cast_mul, Int.cast_natCast]; ring + +/-- Length of `diffHeads`. -/ +private lemma diffHeads_length (k : ℕ) (v : List ℤ) : (diffHeads k v).length = k := by + induction k generalizing v with + | zero => rfl + | succ k ih => simp [diffHeads, ih] + +/-- Entries of the difference list. -/ +private lemma getD_zipWith_sub (v : List ℤ) (m : ℕ) (hm : m + 1 < v.length) : + (List.zipWith (· - ·) v.tail v).getD m 0 = v.getD (m + 1) 0 - v.getD m 0 := by + rw [List.getD_eq_getElem?_getD, List.getD_eq_getElem?_getD, List.getD_eq_getElem?_getD, + List.getElem?_zipWith, List.getElem?_tail, List.getElem?_eq_getElem hm, + List.getElem?_eq_getElem (by omega)] + rfl + +/-- `diffHeads` lists the iterated forward differences at `0`. -/ +private lemma diffHeads_getD (k : ℕ) (v : List ℤ) (i : ℕ) (hi : i < k) (hk : k ≤ v.length) : + (diffHeads k v).getD i 0 = (fwdDiff 1)^[i] (fun m : ℕ => v.getD m 0) 0 := by + induction k generalizing v i with + | zero => omega + | succ k ih => + rcases i with _ | i + · simp only [diffHeads, List.getD_cons_zero, Function.iterate_zero, id] + cases v <;> simp + · simp only [diffHeads, List.getD_cons_succ] + have hlen : k ≤ (List.zipWith (· - ·) v.tail v).length := by + simp [List.length_zipWith, List.length_tail]; omega + rw [ih _ i (by omega) hlen, Function.iterate_succ_apply, fwdDiff_iter_eq_sum_shift, + fwdDiff_iter_eq_sum_shift] + refine sum_congr rfl (fun m hm => ?_) + have hm' := mem_range.1 hm + congr 1 + simp only [smul_eq_mul, mul_one, zero_add, fwdDiff] + rw [getD_zipWith_sub v m (by omega)] + +end TriangleLists + +section Mahonian +open Finset Math0.Statements.A342645 + +/-- `∏_{i=1}^{x} (1 - q^i)`. -/ +private noncomputable def Pprod (x : ℕ) : Polynomial ℤ := + ∏ i ∈ range x, (1 - Polynomial.X ^ (i + 1)) + +/-- `e_a = [q^a] ∏_{i ≥ 1} (1 - q^i)`. -/ +private noncomputable def ecoef (a : ℕ) : ℤ := (Pprod a).coeff a + +/-- `binom(x + m - 1, m) = x(x+1)⋯(x+m-1)/m!` as a polynomial in `x`. -/ +private noncomputable def Rpoly (m : ℕ) : Polynomial ℚ := + Polynomial.C (1 / (m.factorial : ℚ)) * ascPochhammer ℚ m + +/-- The column polynomial `P_n(x) = ∑_{a ≤ n} e_a binom(x+n-a-1, n-a)`. -/ +private noncomputable def Mcol (n : ℕ) : Polynomial ℚ := + ∑ a ∈ range (n + 1), Polynomial.C (ecoef a : ℚ) * Rpoly (n - a) + +/-- `[q^a] ∏_{i ≤ x} (1 - q^i) = e_a` once `x ≥ a`. -/ +private lemma Pprod_coeff_stable (a x : ℕ) (h : a ≤ x) : (Pprod x).coeff a = ecoef a := by + induction x, h using Nat.le_induction with + | base => rfl + | succ x hx ih => + rw [Pprod, prod_range_succ, ← Pprod, mul_sub, mul_one, Polynomial.coeff_sub, + Polynomial.coeff_mul_X_pow', if_neg (by omega), sub_zero, ih] + +/-- `(∏_{i ?_) + rw [Polynomial.map_sum] + simp only [Polynomial.map_pow, Polynomial.map_X] + exact geom_sum_mul_neg _ _ + +/-- `[q^b] (1-q)^(-x) = x(x+1)⋯(x+b-1)/b!`. -/ +private lemma coeff_invOneSubPow (x b : ℕ) : + ((PowerSeries.coeff b (PowerSeries.invOneSubPow ℤ x).val : ℤ) : ℚ) = + (ascPochhammer ℚ b).eval (x : ℚ) / (b.factorial : ℚ) := by + rcases x with _ | d + · rw [PowerSeries.invOneSubPow_zero, Units.val_one, PowerSeries.coeff_one, Nat.cast_zero, + ascPochhammer_eval_zero] + split_ifs <;> simp_all + · rw [PowerSeries.invOneSubPow_val_succ_eq_mk_add_choose, PowerSeries.coeff_mk, + ← ascPochhammer_eval_cast, ascPochhammer_nat_eq_ascFactorial, + Nat.ascFactorial_eq_factorial_mul_choose, Nat.choose_symm_add] + have : (b.factorial : ℚ) ≠ 0 := by positivity + push_cast + field_simp + +/-- For `x ≥ n`, the Mahonian number `mahonian x n` equals `P_n(x)`. -/ +private theorem mahonian_eq_Mcol (x n : ℕ) (h : n ≤ x) : + (mahonian x n : ℚ) = (Mcol n).eval (x : ℚ) := by + -- power series identity + set u := PowerSeries.invOneSubPow ℤ x + have hP : (((mahonianPoly x).map (Nat.castRingHom ℤ) : Polynomial ℤ) : PowerSeries ℤ) = + (Pprod x : PowerSeries ℤ) * u.val := by + have h1 : (((mahonianPoly x).map (Nat.castRingHom ℤ) : Polynomial ℤ) : PowerSeries ℤ) * + (1 - PowerSeries.X) ^ x = (Pprod x : PowerSeries ℤ) := by + rw [← mahonianPoly_map_mul x, Polynomial.coe_mul, Polynomial.coe_pow, Polynomial.coe_sub, + Polynomial.coe_one, Polynomial.coe_X] + have h2 : (1 - PowerSeries.X : PowerSeries ℤ) ^ x * u.val = 1 := by + rw [← PowerSeries.invOneSubPow_inv_eq_one_sub_pow]; exact u.inv_val + rw [← h1, mul_assoc, h2, mul_one] + have hc := congrArg (PowerSeries.coeff n) hP + rw [Polynomial.coeff_coe, Polynomial.coeff_map, coeff_mahonianPoly, PowerSeries.coeff_mul, + Finset.Nat.sum_antidiagonal_eq_sum_range_succ (fun a b => PowerSeries.coeff a (Pprod x : PowerSeries ℤ) * + PowerSeries.coeff b u.val)] at hc + have hc' : (mahonian x n : ℚ) = ((∑ a ∈ range (n + 1), PowerSeries.coeff a (Pprod x : PowerSeries ℤ) * + PowerSeries.coeff (n - a) u.val : ℤ) : ℚ) := by + rw [← hc]; simp + rw [hc', Mcol, Polynomial.eval_finsetSum] + push_cast + refine sum_congr rfl (fun a ha => ?_) + have ha' := mem_range.1 ha + rw [Pprod_coeff_stable a x (by omega), coeff_invOneSubPow, Rpoly] + simp only [Polynomial.eval_mul, Polynomial.eval_C] + ring + +end Mahonian + +section Interpolation +open Finset Math0.Statements.A342645 + +/-- `deg binom(x+m-1, m) ≤ m`. -/ +private lemma natDegree_Rpoly_le (m : ℕ) : (Rpoly m).natDegree ≤ m := by + unfold Rpoly + exact (Polynomial.natDegree_C_mul_le _ _).trans (ascPochhammer_natDegree ℚ m).le + +/-- `deg P_n ≤ n`. -/ +private lemma natDegree_Mcol_le (n : ℕ) : (Mcol n).natDegree ≤ n := by + unfold Mcol + apply Polynomial.natDegree_sum_le_of_forall_le + intro a _ + exact (Polynomial.natDegree_C_mul_le _ _).trans ((natDegree_Rpoly_le _).trans (Nat.sub_le _ _)) + +/-- The interpolation data has `n + 1` entries. -/ +private lemma column_length (n : ℕ) : (column n).length = n + 1 := by simp [column] + +/-- The interpolation data are Mahonian numbers. -/ +private lemma column_getD (n m : ℕ) (hm : m ≤ n) : (column n).getD m 0 = (mahonian (n + m) n : ℤ) := by + rw [column, List.getD_eq_getElem?_getD, List.getElem?_map, List.getElem?_range (by omega)] + rfl + +/-- The forward differences of the interpolation data are those of `P_n` at `x = n`. -/ +private lemma diff_eq (n i : ℕ) (hi : i ≤ n) : + (((diffHeads (n + 1) (column n)).getD i 0 : ℤ) : ℚ) = + (fwdDiff 1)^[i] (fun x : ℚ => (Mcol n).eval x) (n : ℚ) := by + rw [diffHeads_getD (n + 1) (column n) i (by omega) (by rw [column_length]), + fwdDiff_iter_eq_sum_shift, fwdDiff_iter_eq_sum_shift] + push_cast + refine sum_congr rfl (fun k hk => ?_) + have hk' := mem_range.1 hk + simp only [zsmul_eq_mul, smul_eq_mul, mul_one, zero_add, Int.cast_mul, Int.cast_pow, + Int.cast_neg, Int.cast_one, Int.cast_natCast] + congr 1 + rw [column_getD n k (by omega), Int.cast_natCast, mahonian_eq_Mcol (n + k) n (by omega)] + push_cast; ring_nf + +/-- Row `n` of the triangle is the coefficient list of `n! P_n(x)` (Newton interpolation of a polynomial of degree `≤ n`). -/ +private lemma Trow_poly (n : ℕ) : + toPolyZ (Trow n) = Polynomial.C (n.factorial : ℚ) * Mcol n := by + apply Polynomial.eq_of_infinite_eval_eq + apply Set.Infinite.mono (s := Set.range (fun y : ℕ => (n : ℚ) + y)) + · rintro _ ⟨y, rfl⟩ + simp only [Set.mem_ofPred_eq] + rw [Trow, toPolyZ_newton, diffHeads_length, Polynomial.eval_finsetSum, + Polynomial.eval_mul, Polynomial.eval_C] + have hnewton := shift_eq_sum_fwdDiff_iter (h := (1 : ℚ)) (fun x : ℚ => (Mcol n).eval x) y (n : ℚ) + simp only [nsmul_eq_mul, mul_one] at hnewton + rw [hnewton, mul_sum] + have hsub1 : range (n + 1) ⊆ range (n + y + 1) := range_subset_range.2 (by omega) + have hsub2 : range (y + 1) ⊆ range (n + y + 1) := range_subset_range.2 (by omega) + rw [sum_subset hsub1, sum_subset hsub2] + · refine sum_congr rfl (fun i hi => ?_) + by_cases hin : i ≤ n + · simp only [zero_add, Polynomial.eval_mul, Polynomial.eval_C, Polynomial.eval_comp, + Polynomial.eval_sub, Polynomial.eval_X, add_sub_cancel_left, + descPochhammer_eval_eq_descFactorial, Nat.descFactorial_eq_factorial_mul_choose] + rw [diff_eq n i hin, Nat.cast_div (Nat.factorial_dvd_factorial hin) (by positivity)] + have : (i.factorial : ℚ) ≠ 0 := by positivity + push_cast + field_simp + · have hz : (fwdDiff 1)^[i] (fun x : ℚ => (Mcol n).eval x) = 0 := + Polynomial.fwdDiff_iter_eq_zero_of_degree_lt (lt_of_le_of_lt (natDegree_Mcol_le n) (by omega)) + rw [hz] + have hz2 : (diffHeads (n + 1) (column n)).getD i 0 = 0 := by + rw [List.getD_eq_getElem?_getD, List.getElem?_eq_none (by rw [diffHeads_length]; omega)] + rfl + rw [hz2]; simp + · intro i hi hi' + simp only [mem_range] at hi hi' + rw [Nat.choose_eq_zero_of_lt (by omega)]; simp + · intro i hi hi' + simp only [mem_range] at hi hi' + have hz2 : (diffHeads (n + 1) (column n)).getD i 0 = 0 := by + rw [List.getD_eq_getElem?_getD, List.getElem?_eq_none (by rw [diffHeads_length]; omega)] + rfl + rw [hz2]; simp + · exact Set.infinite_range_of_injective (fun a b h => by simpa using h) + +/-- `T(n,k) = n! [x^k] P_n(x)`. -/ +private theorem T_eq (n k : ℕ) : (T n k : ℚ) = (n.factorial : ℚ) * (Mcol n).coeff k := by + rw [T, ← coeff_toPolyZ, Trow_poly, Polynomial.coeff_C_mul] + +end Interpolation + +section Stirling +open Finset Math0.Statements.A342645 Polynomial + +/-- Unsigned Stirling numbers of the first kind: `x(x+1)⋯(x+m-1) = ∑_k c(m,k) x^k`. -/ +private noncomputable def cst (m k : ℕ) : ℕ := (ascPochhammer ℕ m).coeff k + +/-- `c(m+1,k+1) = c(m,k) + m c(m,k+1)`. -/ +private lemma cst_succ_succ (m k : ℕ) : cst (m + 1) (k + 1) = cst m k + m * cst m (k + 1) := by + unfold cst + rw [ascPochhammer_succ_right, mul_add, coeff_add, coeff_mul_X, + show ((m : ℕ[X])) = C m by simp, coeff_mul_C] + ring + +/-- `c(m,k) = 0` for `k > m`. -/ +private lemma cst_eq_zero (m k : ℕ) (h : m < k) : cst m k = 0 := by + unfold cst + apply coeff_eq_zero_of_natDegree_lt + rw [ascPochhammer_natDegree]; exact h + +/-- `c(m,m) = 1`. -/ +private lemma cst_self (m : ℕ) : cst m m = 1 := by + unfold cst + have := monic_ascPochhammer ℕ m + rw [Monic, leadingCoeff, ascPochhammer_natDegree] at this + exact this + +/-- `c(m,0) = 0` for `m > 0`. -/ +private lemma cst_zero_right (m : ℕ) (hm : 0 < m) : cst m 0 = 0 := by + unfold cst + rw [coeff_zero_eq_eval_zero, ascPochhammer_eval_zero, if_neg (by omega)] + +/-- Coefficients of `binom(x+m-1, m)`. -/ +private lemma coeff_Rpoly (m k : ℕ) : (Rpoly m).coeff k = (cst m k : ℚ) / (m.factorial : ℚ) := by + unfold Rpoly cst + rw [coeff_C_mul, ← ascPochhammer_map (Nat.castRingHom ℚ), coeff_map] + simp; ring + +/-- `e_0 = 1`. -/ +private lemma ecoef_zero : ecoef 0 = 1 := by simp [ecoef, Pprod] + +/-- `T(n,k) = ∑_a e_a n(n-1)⋯(n-a+1) c(n-a,k)`. -/ +private theorem T_formula (n k : ℕ) : (T n k : ℚ) = + ∑ a ∈ range (n + 1), (ecoef a : ℚ) * (n.descFactorial a : ℚ) * (cst (n - a) k : ℚ) := by + rw [T_eq, Mcol, finsetSum_coeff, mul_sum] + refine sum_congr rfl (fun a ha => ?_) + have ha' : a ≤ n := Nat.lt_succ_iff.1 (mem_range.1 ha) + rw [coeff_C_mul, coeff_Rpoly] + have h1 := Nat.factorial_mul_descFactorial ha' + have h2 : ((n - a).factorial : ℚ) ≠ 0 := by positivity + have h3 : (n.factorial : ℚ) = (n - a).factorial * n.descFactorial a := by exact_mod_cast h1.symm + rw [h3] + field_simp + +/-- Discrete antiderivative: for `deg P ≤ d` there is `Q` with `Q(x+1) - Q(x) = P(x)`, `deg Q ≤ d + 1` and `[x^(d+1)] Q = [x^d] P / (d+1)`. -/ +private lemma antidiff (d : ℕ) : ∀ P : ℚ[X], P.natDegree ≤ d → + ∃ Q : ℚ[X], Q.comp (X + 1) - Q = P ∧ Q.natDegree ≤ d + 1 ∧ + Q.coeff (d + 1) = P.coeff d / (d + 1) := by + induction d with + | zero => + intro P hP + rw [Nat.le_zero, natDegree_eq_zero] at hP + obtain ⟨c, rfl⟩ := hP + refine ⟨C c * X, ?_, ?_, ?_⟩ + · simp [mul_add] + · exact (natDegree_C_mul_le _ _).trans (by simp) + · simp + | succ d ih => + intro P hP + set a := P.coeff (d + 1) + set Q0 : ℚ[X] := C (a / (d + 2)) * X ^ (d + 2) + set R := Q0.comp (X + 1) - Q0 + have hR : ∀ j, R.coeff j = a / (d + 2) * (((d + 2).choose j : ℚ) - if j = d + 2 then 1 else 0) := by + intro j + simp only [R, Q0, mul_comp, C_comp, X_pow_comp, coeff_sub, coeff_C_mul, coeff_X_add_one_pow, + coeff_X_pow] + ring + have hP' : (P - R).natDegree ≤ d := by + rw [natDegree_le_iff_coeff_eq_zero] + intro j hj + rw [coeff_sub, hR] + have hj' : d < j := by exact_mod_cast hj + rcases Nat.lt_trichotomy j (d + 2) with h | h | h + · have : j = d + 1 := by omega + subst this + rw [Nat.choose_succ_self_right, if_neg (by omega)] + have : (d : ℚ) + 2 ≠ 0 := by positivity + push_cast; field_simp; ring + · subst h; rw [Nat.choose_self, if_pos rfl, coeff_eq_zero_of_natDegree_lt (by omega)]; simp + · rw [Nat.choose_eq_zero_of_lt h, if_neg (by omega), coeff_eq_zero_of_natDegree_lt (by omega)] + simp + obtain ⟨Q', hQ'1, hQ'2, _⟩ := ih (P - R) hP' + refine ⟨Q0 + Q', ?_, ?_, ?_⟩ + · rw [add_comp] + have : R = Q0.comp (X + 1) - Q0 := rfl + linear_combination hQ'1 - this + · refine (natDegree_add_le _ _).trans (max_le ?_ (by omega)) + exact (natDegree_C_mul_le _ _).trans (by simp) + · rw [coeff_add, coeff_eq_zero_of_natDegree_lt (show Q'.natDegree < d + 1 + 1 by omega)] + simp only [Q0, coeff_C_mul, coeff_X_pow] + push_cast; ring + +end Stirling + +section Diagonals +open Finset Math0.Statements.A342645 Polynomial + +/-- `c(N, N-r)` is a polynomial in `N ≥ r` of degree `2r` with leading coefficient `1/(2^r r!)`. -/ +private lemma Ddiag (r : ℕ) : ∃ D : ℚ[X], (∀ N : ℕ, r ≤ N → D.eval (N : ℚ) = (cst N (N - r) : ℚ)) ∧ + D.natDegree = 2 * r ∧ D.leadingCoeff = 1 / (2 ^ r * (r.factorial : ℚ)) := by + induction r with + | zero => + refine ⟨1, fun N _ => ?_, by simp, by simp⟩ + simp [cst_self] + | succ r ih => + obtain ⟨D', hD'1, hD'2, hD'3⟩ := ih + have hD'0 : D' ≠ 0 := by + intro h; rw [h, leadingCoeff_zero] at hD'3 + have : (0 : ℚ) < 1 / (2 ^ r * (r.factorial : ℚ)) := by positivity + linarith + set P := X * D' + have hPdeg : P.natDegree = 2 * r + 1 := by + simp only [P]; rw [natDegree_X_mul hD'0, hD'2] + have hPc : P.coeff (2 * r + 1) = 1 / (2 ^ r * (r.factorial : ℚ)) := by + simp only [P]; rw [coeff_X_mul, ← hD'2]; exact hD'3 + obtain ⟨Q, hQ1, hQ2, hQ3⟩ := antidiff (2 * r + 1) P hPdeg.le + set D := Q - C (Q.eval ((r + 1 : ℕ) : ℚ)) + have hstep : ∀ x : ℚ, Q.eval (x + 1) - Q.eval x = x * D'.eval x := by + intro x + have := congrArg (eval x) hQ1 + simpa [eval_comp, P] using this + have hcoef : Q.coeff (2 * r + 1 + 1) ≠ 0 := by + rw [hQ3, hPc]; positivity + have hQdeg : Q.natDegree = 2 * (r + 1) := by + have := natDegree_eq_of_le_of_coeff_ne_zero hQ2 hcoef + rw [this]; ring + refine ⟨D, ?_, ?_, ?_⟩ + · intro N hN + induction N, hN using Nat.le_induction with + | base => + simp only [D, eval_sub, eval_C, sub_self, Nat.sub_self] + rw [cst_zero_right _ (by omega)]; simp + | succ N hN ihN => + have h1 : D.eval ((N + 1 : ℕ) : ℚ) = D.eval (N : ℚ) + N * D'.eval (N : ℚ) := by + simp only [D, eval_sub, eval_C] + have := hstep (N : ℚ) + push_cast + linarith + rw [h1, ihN, hD'1 N (by omega)] + have h2 := cst_succ_succ N (N - (r + 1)) + rw [show N - (r + 1) + 1 = N - r by omega] at h2 + rw [show N + 1 - (r + 1) = N - (r + 1) + 1 by omega, show N - (r + 1) + 1 = N - r by omega, + h2] + push_cast; ring + · simp only [D]; rw [natDegree_sub_C, hQdeg] + · rw [leadingCoeff, show D.natDegree = 2 * (r + 1) by simp only [D]; rw [natDegree_sub_C, hQdeg]] + simp only [D, coeff_sub, coeff_C, if_neg (show 2 * (r + 1) ≠ 0 by omega), sub_zero] + rw [show 2 * (r + 1) = 2 * r + 1 + 1 by ring, hQ3, hPc] + push_cast [Nat.factorial_succ] + have : (r.factorial : ℚ) ≠ 0 := by positivity + field_simp + ring + +/-- `T(n, n-m)` is a polynomial in `n ≥ m` of degree `2m` with leading coefficient `1/(2^m m!)`. -/ +private theorem diag (m : ℕ) : ∃ Q : ℚ[X], Q.natDegree = 2 * m ∧ + Q.leadingCoeff = 1 / (2 ^ m * (m.factorial : ℚ)) ∧ + ∀ n : ℕ, m ≤ n → (T n (n - m) : ℚ) = Q.eval (n : ℚ) := by + choose D hD using Ddiag + set f : ℕ → ℚ[X] := fun j => C (ecoef j : ℚ) * descPochhammer ℚ j * + (D (m - j)).comp (X - C (j : ℚ)) + set Q := ∑ j ∈ range (m + 1), f j + have hf0 : f 0 = D m := by + simp [f, ecoef_zero] + have hrest : ∀ j ∈ range m, (f (j + 1)).natDegree ≤ 2 * m - 1 := by + intro j hj + have hj' := mem_range.1 hj + simp only [f] + refine (natDegree_mul_le).trans ?_ + have h1 : (C (ecoef (j + 1) : ℚ) * descPochhammer ℚ (j + 1)).natDegree ≤ j + 1 := + (natDegree_C_mul_le _ _).trans (descPochhammer_natDegree ℚ (j + 1)).le + have h2 : ((D (m - (j + 1))).comp (X - C ((j + 1 : ℕ) : ℚ))).natDegree ≤ 2 * (m - (j + 1)) := by + rw [natDegree_comp, (hD _).2.1, natDegree_X_sub_C, mul_one] + omega + have hQ : Q = D m + ∑ j ∈ range m, f (j + 1) := by + simp only [Q]; rw [sum_range_succ', hf0, add_comm] + have hDm := hD m + have hdeg : Q.natDegree = 2 * m ∧ Q.leadingCoeff = 1 / (2 ^ m * (m.factorial : ℚ)) := by + rcases Nat.eq_zero_or_pos m with h0 | hpos + · rw [hQ, h0, range_zero, sum_empty, add_zero] + exact ⟨by rw [(hD 0).2.1], by rw [(hD 0).2.2]⟩ + · have hlt : (∑ j ∈ range m, f (j + 1)).natDegree < (D m).natDegree := by + rw [hDm.2.1] + exact lt_of_le_of_lt (natDegree_sum_le_of_forall_le _ _ hrest) (by omega) + refine ⟨?_, ?_⟩ + · rw [hQ, natDegree_add_eq_left_of_natDegree_lt hlt, hDm.2.1] + · rw [hQ, leadingCoeff_add_of_degree_lt' (degree_lt_degree hlt), hDm.2.2] + refine ⟨Q, hdeg.1, hdeg.2, ?_⟩ + · intro n hn + rw [T_formula] + simp only [Q, f, eval_finsetSum, eval_mul, eval_C, eval_comp, eval_sub, eval_X, + descPochhammer_eval_eq_descFactorial] + have hsub : range (m + 1) ⊆ range (n + 1) := range_subset_range.2 (by omega) + rw [← sum_subset hsub] + · refine sum_congr rfl (fun j hj => ?_) + have hj' := Nat.lt_succ_iff.1 (mem_range.1 hj) + rw [show (n : ℚ) - (j : ℚ) = ((n - j : ℕ) : ℚ) by push_cast [Nat.cast_sub (by omega : j ≤ n)]; ring, + (hD (m - j)).1 (n - j) (by omega), show n - j - (m - j) = n - m by omega] + · intro a ha ha' + simp only [mem_range] at ha ha' + rw [cst_eq_zero (n - a) (n - m) (by omega)]; simp + +end Diagonals + +section Formulas +open Finset Math0.Statements.A342645 Polynomial + +/-- `T(n, n-m) = ∑_{a ≤ m} e_a n(n-1)⋯(n-a+1) c(n-a, n-m)`. -/ +private lemma T_diag_sum (n m : ℕ) (h : m ≤ n) : (T n (n - m) : ℚ) = + ∑ a ∈ range (m + 1), (ecoef a : ℚ) * (n.descFactorial a : ℚ) * (cst (n - a) (n - m) : ℚ) := by + rw [T_formula] + symm + apply sum_subset (range_subset_range.2 (by omega)) + intro a ha ha' + simp only [mem_range] at ha ha' + rw [cst_eq_zero (n - a) (n - m) (by omega)]; simp + +/-- `e_1 = -1`. -/ +private lemma ecoef_one : ecoef 1 = -1 := by + simp [ecoef, Pprod, coeff_one] + +/-- `e_2 = -1`. -/ +private lemma ecoef_two : ecoef 2 = -1 := by + have : Pprod 2 = 1 - X - X ^ 2 + X ^ 3 := by + simp [Pprod, prod_range_succ]; ring + rw [ecoef, this] + simp [coeff_X_pow, coeff_one, coeff_X] + +/-- `e_3 = 0`. -/ +private lemma ecoef_three : ecoef 3 = 0 := by + have : Pprod 3 = 1 - X - X ^ 2 + X ^ 4 + X ^ 5 - X ^ 6 := by + simp [Pprod, prod_range_succ]; ring + rw [ecoef, this] + simp [coeff_X_pow, coeff_one, coeff_X] + +/-- `c(k+1, k) = (k+1)k/2`. -/ +private lemma cst1 (k : ℕ) : (cst (k + 1) k : ℚ) = (k + 1) * k / 2 := by + induction k with + | zero => simp [cst_zero_right] + | succ k ih => + rw [cst_succ_succ, cst_self]; push_cast; rw [ih]; ring + +/-- `c(k+2, k) = (k+2)(k+1)k(3k+5)/24`. -/ +private lemma cst2 (k : ℕ) : (cst (k + 2) k : ℚ) = (k + 2) * (k + 1) * k * (3 * k + 5) / 24 := by + induction k with + | zero => simp [cst_zero_right] + | succ k ih => + rw [show k + 1 + 2 = (k + 2) + 1 by ring, cst_succ_succ] + push_cast + rw [ih, show k + 2 = (k + 1) + 1 by ring, cst1] + push_cast; ring + +/-- `c(k+3, k) = (k+3)²(k+2)²(k+1)k/48`. -/ +private lemma cst3 (k : ℕ) : + (cst (k + 3) k : ℚ) = (k + 3) ^ 2 * (k + 2) ^ 2 * (k + 1) * k / 48 := by + induction k with + | zero => simp [cst_zero_right] + | succ k ih => + rw [show k + 1 + 3 = (k + 3) + 1 by ring, cst_succ_succ] + push_cast + rw [ih, show k + 3 = (k + 1) + 2 by ring, cst2] + push_cast; ring + +/-- `T(n,n) = 1`. -/ +private theorem formula0 (n : ℕ) : T n n = 1 := by + have h := T_diag_sum n 0 (Nat.zero_le n) + simp only [Nat.sub_zero, zero_add, range_one, sum_singleton, ecoef_zero, + Nat.descFactorial_zero, cst_self] at h + have h' : (T n n : ℚ) = 1 := by rw [h]; norm_num + exact_mod_cast h' + +/-- `T(n,n-1) = (n² - 3n)/2`. -/ +private theorem formula1 (n : ℕ) (hn : 1 ≤ n) : + (T n (n - 1) : ℚ) = (-3 * (n : ℚ) + (n : ℚ) ^ 2) / 2 := by + obtain ⟨k, rfl⟩ : ∃ k, n = k + 1 := ⟨n - 1, by omega⟩ + rw [T_diag_sum _ 1 hn] + simp only [sum_range_succ, range_zero, sum_empty, zero_add, Nat.add_sub_cancel, + Nat.sub_zero, ecoef_zero, ecoef_one, Nat.descFactorial_zero, Nat.descFactorial_one, cst_self] + rw [cst1] + push_cast; ring + +/-- `T(n,n-2) = (3n⁴ - 22n³ + 21n² - 2n)/24`. -/ +private theorem formula2 (n : ℕ) (hn : 2 ≤ n) : + (T n (n - 2) : ℚ) = + (-2 * (n : ℚ) + 21 * (n : ℚ) ^ 2 - 22 * (n : ℚ) ^ 3 + 3 * (n : ℚ) ^ 4) / 24 := by + obtain ⟨k, rfl⟩ : ∃ k, n = k + 2 := ⟨n - 2, by omega⟩ + rw [T_diag_sum _ 2 hn] + simp only [sum_range_succ, range_zero, sum_empty, zero_add, Nat.add_sub_cancel, + Nat.sub_zero, ecoef_zero, ecoef_one, ecoef_two, Nat.descFactorial_zero, Nat.descFactorial_one, + cst_self] + rw [show k + 2 - 1 = k + 1 by omega, cst2, cst1] + simp only [Nat.descFactorial_succ, Nat.descFactorial_zero] + push_cast + ring + +/-- `T(n,n-3) = (n⁶ - 13n⁵ + 37n⁴ + 13n³ - 134n² + 96n)/48`. -/ +private theorem formula3 (n : ℕ) (hn : 3 ≤ n) : + (T n (n - 3) : ℚ) = + (96 * (n : ℚ) - 134 * (n : ℚ) ^ 2 + 13 * (n : ℚ) ^ 3 + 37 * (n : ℚ) ^ 4 + - 13 * (n : ℚ) ^ 5 + (n : ℚ) ^ 6) / 48 := by + obtain ⟨k, rfl⟩ : ∃ k, n = k + 3 := ⟨n - 3, by omega⟩ + rw [T_diag_sum _ 3 hn] + simp only [sum_range_succ, range_zero, sum_empty, zero_add, Nat.add_sub_cancel, + Nat.sub_zero, ecoef_zero, ecoef_one, ecoef_two, ecoef_three, Nat.descFactorial_zero, + Nat.descFactorial_one, cst_self] + rw [show k + 3 - 1 = k + 2 by omega, show k + 3 - 2 = k + 1 by omega, cst3, cst2, cst1] + simp only [Nat.descFactorial_succ, Nat.descFactorial_zero] + push_cast + ring + +end Formulas + +/-- Both conjectures of A342645 hold: every diagonal `n ↦ T(n, n-m)` is a polynomial of degree `2m` +with leading coefficient `|A290030(m)/A053657(m+1)| = 1/(2^m m!)`, and the four FORMULA identities +hold. -/ +theorem result : statement := by + refine ⟨fun m => ?_, formula0, formula1, formula2, formula3⟩ + obtain ⟨Q, hdeg, hlc, hT⟩ := diag m + refine ⟨Q, ?_, ?_, hT⟩ + · have hQ0 : Q ≠ 0 := by + intro h + rw [h, Polynomial.leadingCoeff_zero] at hlc + have : (0 : ℚ) < 1 / (2 ^ m * (m.factorial : ℚ)) := by positivity + linarith + rw [Polynomial.degree_eq_natDegree hQ0, hdeg] + · rw [hlc, A290030_ratio] + +end Math0.Frontier.A342645 + +#math0_settles Math0.Frontier.A342645.result Math0.Statements.A342645.statement diff --git a/lean/Math0/Frontier/OEIS/A342992.lean b/lean/Math0/Frontier/OEIS/A342992.lean new file mode 100644 index 0000000..01f13ff --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A342992.lean @@ -0,0 +1,131 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A342992 +import Math0.Audit + +/-! +# Every `n` not divisible by `5` has a multiple with only prime digits (A342992) + +We prove Sariyar's conjecture: if `n ≥ 1` and `5 ∤ n`, then some positive multiple of `n` has +only the decimal digits `2` and `3`; in particular `a(n) > 0`. + +Write `n = 2^e * m` with `m` odd, so `gcd(m, 10) = 1`. Put `L = φ(m) * (e + 1)`. + +* *Block.* By induction on `j` there is a `j`-digit number `N_j` with digits in `{2, 3}` and + `2^j ∣ N_j`: given `N_j = 2^j q`, append the leading digit `d ∈ {2, 3}` with `q + 5^j d` + even; then `N_j + 10^j d = 2^j (q + 5^j d)` is divisible by `2^(j+1)`. +* *Repetition.* Let `X_t` be the block `N = N_L` written `t` times in a row, so + `X_{t+1} = N + 10^L X_t`. Since `10^L ≡ 1 [MOD m]` (Euler), `X_t ≡ t N [MOD m]`, and + `2^e ∣ 2^L ∣ N` gives `2^e ∣ X_t`. Hence `m ∣ X_m` and `2^e ∣ X_m`; by coprimality + `n ∣ X_m`. The digits of `X_m` are those of the repeated block, all in `{2, 3}`. +-/ + +namespace Math0.Frontier.A342992 +open Math0.Statements.A342992 + +/-- For every `j` there is a little-endian digit list of length `j` with entries in `{2, 3}` +whose value is divisible by `2^j`. -/ +private lemma exists_block (j : ℕ) : ∃ l : List ℕ, l.length = j ∧ (∀ d ∈ l, d = 2 ∨ d = 3) ∧ + 2 ^ j ∣ Nat.ofDigits 10 l := by + induction j with + | zero => exact ⟨[], rfl, by simp, by simp⟩ + | succ j ih => + obtain ⟨l, hlen, hdig, q, hq⟩ := ih + have h10 : (10 : ℕ) ^ j = 2 ^ j * 5 ^ j := by rw [← mul_pow]; norm_num + rcases Nat.even_or_odd q with ⟨r, hr⟩ | ⟨r, hr⟩ + · refine ⟨l ++ [2], by simp [hlen], ?_, ?_⟩ + · intro d hd + rcases List.mem_append.1 hd with hd | hd + · exact hdig d hd + · simp at hd; omega + · refine ⟨r + 5 ^ j, ?_⟩ + rw [Nat.ofDigits_append, Nat.ofDigits_singleton, hq, hlen, h10, hr] + ring + · obtain ⟨s, hs⟩ : Odd (5 ^ j) := Odd.pow (by decide) + refine ⟨l ++ [3], by simp [hlen], ?_, ?_⟩ + · intro d hd + rcases List.mem_append.1 hd with hd | hd + · exact hdig d hd + · simp at hd; omega + · refine ⟨r + 3 * s + 2, ?_⟩ + rw [Nat.ofDigits_append, Nat.ofDigits_singleton, hq, hlen, h10, hr, hs] + ring + +/-- Repeating a block `t` times: the value is `t * N` modulo `m` when `10^L ≡ 1 [MOD m]`, and +it stays divisible by any `D` dividing the block's value. -/ +private lemma rep_props (l : List ℕ) (m D : ℕ) (hm : 10 ^ l.length ≡ 1 [MOD m]) + (hD : D ∣ Nat.ofDigits 10 l) (t : ℕ) : + Nat.ofDigits 10 (List.replicate t l).flatten ≡ t * Nat.ofDigits 10 l [MOD m] ∧ + D ∣ Nat.ofDigits 10 (List.replicate t l).flatten := by + induction t with + | zero => simp; rfl + | succ t ih => + rw [List.replicate_succ, List.flatten_cons, Nat.ofDigits_append] + refine ⟨?_, dvd_add hD (dvd_mul_of_dvd_right ih.2 _)⟩ + have h1 := (hm.mul ih.1).add_left (Nat.ofDigits 10 l) + rw [one_mul] at h1 + refine h1.trans ?_ + rw [add_mul, one_mul, add_comm] + +/-- The conjecture holds: every `n ≥ 1` with `5 ∤ n` has a multiple with only prime digits. -/ +theorem result : statement := by + intro n hn h5 + rw [a_pos_iff] + obtain ⟨e, m, hm2, rfl⟩ := Nat.exists_eq_pow_mul_and_not_dvd (by omega : n ≠ 0) 2 (by decide) + have hm0 : 0 < m := by + rcases Nat.eq_zero_or_pos m with h | h + · subst h; simp at hn + · exact h + have hm5 : ¬ 5 ∣ m := fun h => h5 (dvd_mul_of_dvd_right h _) + have hcop : Nat.Coprime 10 m := by + rw [show (10 : ℕ) = 2 * 5 by rfl, Nat.coprime_mul_iff_left] + exact ⟨(Nat.Prime.coprime_iff_not_dvd Nat.prime_two).2 hm2, + (Nat.Prime.coprime_iff_not_dvd (by norm_num)).2 hm5⟩ + have hphi : 0 < Nat.totient m := Nat.totient_pos.2 hm0 + obtain ⟨l, hlen, hdig, hdvd⟩ := exists_block (Nat.totient m * (e + 1)) + have hmod : 10 ^ l.length ≡ 1 [MOD m] := by + rw [hlen, pow_mul] + simpa using (Nat.ModEq.pow_totient hcop).pow (e + 1) + have hle : e ≤ Nat.totient m * (e + 1) := by nlinarith + have hD : 2 ^ e ∣ Nat.ofDigits 10 l := (pow_dvd_pow 2 hle).trans hdvd + obtain ⟨hX1, hX2⟩ := rep_props l m (2 ^ e) hmod hD m + set X := Nat.ofDigits 10 (List.replicate m l).flatten with hX + have hmX : m ∣ X := by + have := hX1.trans (Nat.modEq_zero_iff_dvd.2 (dvd_mul_right m _)) + exact Nat.modEq_zero_iff_dvd.1 this + have hnX : 2 ^ e * m ∣ X := + Nat.Coprime.mul_dvd_of_dvd_of_dvd + (Nat.Coprime.pow_left _ ((Nat.Prime.coprime_iff_not_dvd Nat.prime_two).2 hm2)) hX2 hmX + have hmem : ∀ d ∈ (List.replicate m l).flatten, d = 2 ∨ d = 3 := by + intro d hd + rw [List.mem_flatten] at hd + obtain ⟨l', hl', hd⟩ := hd + rw [List.eq_of_mem_replicate hl'] at hd + exact hdig d hd + have hdigits : Nat.digits 10 X = (List.replicate m l).flatten := by + apply Nat.digits_ofDigits 10 (by norm_num) + · intro d hd + rcases hmem d hd with h | h <;> omega + · intro h + rcases hmem _ (List.getLast_mem h) with h' | h' <;> omega + have hne : (List.replicate m l).flatten ≠ [] := by + obtain ⟨m', rfl⟩ : ∃ m', m = m' + 1 := ⟨m - 1, by omega⟩ + rw [List.replicate_succ, List.flatten_cons] + intro h + have := congrArg List.length h + simp [hlen] at this + have hXpos : 0 < X := by + rcases Nat.eq_zero_or_pos X with h | h + · rw [h, Nat.digits_zero] at hdigits + exact absurd hdigits.symm hne + · exact h + refine ⟨X / (2 ^ e * m), ?_⟩ + rw [Nat.div_mul_cancel hnX] + refine ⟨hXpos, fun d hd => ?_⟩ + rw [hdigits] at hd + rcases hmem d hd with h | h <;> subst h <;> norm_num + +end Math0.Frontier.A342992 + +#math0_settles Math0.Frontier.A342992.result Math0.Statements.A342992.statement diff --git a/lean/Math0/Frontier/OEIS/A344710.lean b/lean/Math0/Frontier/OEIS/A344710.lean new file mode 100644 index 0000000..782c0d6 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A344710.lean @@ -0,0 +1,110 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A344710 +import Math0.Audit + +/-! +# A344710: every non-obtuse lattice triangle with sides `≥ √n` has `|det| > (√3/2) n` + +We prove Waldmann's conjectured inequality `a(n) > √(3/4) · n` for all `n ≥ 1`. + +Let `X, Y, Z` be the squared side lengths of an admissible triangle and `D = det2 A B C`. Then +`4 D² = 2XY + 2YZ + 2ZX - X² - Y² - Z²` (Heron / Lagrange identity). If `Z` is the largest of +the three, this equals `4XY - (X + Y - Z)²`, and non-obtuseness gives `0 ≤ X + Y - Z ≤ min(X, Y)`, +so `(X + Y - Z)² ≤ XY` and `4 D² ≥ 3XY ≥ 3n²`. Equality `4D² = 3n²` with `n ≥ 1` is impossible +because `√3` is irrational. Hence `4 a(n)² > 3 n²`, i.e. `a(n) > √(3/4) · n`. +-/ + +namespace Math0.Frontier.A344710 +open Math0.Statements.A344710 + +/-- The key inequality in the case where `Z` is the largest squared side. -/ +private lemma heron_bound_of_max (X Y Z n : ℤ) (hn : 0 ≤ n) (hX : n ≤ X) (hY : n ≤ Y) + (h0 : 0 ≤ X + Y - Z) (hZX : X ≤ Z) (hZY : Y ≤ Z) : + 3 * n ^ 2 ≤ 2 * X * Y + 2 * Y * Z + 2 * Z * X - X ^ 2 - Y ^ 2 - Z ^ 2 := by + have h1 : (X + Y - Z) * (X + Y - Z) ≤ X * Y := + mul_le_mul (by linarith) (by linarith) h0 (by linarith) + have h2 : n * n ≤ X * Y := mul_le_mul hX hY hn (by linarith) + nlinarith + +/-- Heron-type lower bound: for squared side lengths `X, Y, Z ≥ n ≥ 0` of a non-obtuse triangle, +`16 · area² = 2XY + 2YZ + 2ZX - X² - Y² - Z² ≥ 3 n²`. -/ +private lemma heron_bound (X Y Z n : ℤ) (hn : 0 ≤ n) (hX : n ≤ X) (hY : n ≤ Y) (hZ : n ≤ Z) + (h1 : 0 ≤ X + Y - Z) (h2 : 0 ≤ X + Z - Y) (h3 : 0 ≤ Y + Z - X) : + 3 * n ^ 2 ≤ 2 * X * Y + 2 * Y * Z + 2 * Z * X - X ^ 2 - Y ^ 2 - Z ^ 2 := by + rcases le_total X Z with hXZ | hZX + · rcases le_total Y Z with hYZ | hZY + · exact heron_bound_of_max X Y Z n hn hX hY h1 hXZ hYZ + · -- `Y` is the largest + have := heron_bound_of_max X Z Y n hn hX hZ h2 (by linarith) hZY + linarith + · rcases le_total Y X with hYX | hXY + · -- `X` is the largest + have := heron_bound_of_max Y Z X n hn hY hZ h3 hYX hZX + linarith + · -- `Y` is the largest + have := heron_bound_of_max X Z Y n hn hX hZ h2 hXY (by linarith) + linarith + +/-- `4 det² ≥ 3 n²` for every admissible triangle. -/ +private lemma det_sq_ge {n : ℕ} {A B C : ℤ × ℤ} (h : IsValid n A B C) : + 3 * (n : ℤ) ^ 2 ≤ 4 * (det2 A B C) ^ 2 := by + obtain ⟨-, hAB, hBC, hCA, hdA, hdB, hdC⟩ := h + have hA : 2 * dotAt A B C = dist2 A B + dist2 C A - dist2 B C := by + simp only [dotAt, dist2]; ring + have hB : 2 * dotAt B C A = dist2 A B + dist2 B C - dist2 C A := by + simp only [dotAt, dist2]; ring + have hC : 2 * dotAt C A B = dist2 B C + dist2 C A - dist2 A B := by + simp only [dotAt, dist2]; ring + have hid : 4 * (det2 A B C) ^ 2 = + 2 * dist2 A B * dist2 C A + 2 * dist2 C A * dist2 B C + 2 * dist2 B C * dist2 A B + - dist2 A B ^ 2 - dist2 C A ^ 2 - dist2 B C ^ 2 := by + simp only [det2, dist2]; ring + rw [hid] + exact heron_bound _ _ _ _ (Int.natCast_nonneg n) hAB hCA hBC (by linarith) (by linarith) + (by linarith) + +/-- `4 m² = 3 n²` has no solution in natural numbers with `n ≥ 1`, since `√3` is irrational. -/ +private lemma four_sq_ne_three_sq (m n : ℕ) (hn : 1 ≤ n) : 4 * m ^ 2 ≠ 3 * n ^ 2 := by + intro h + have hirr : Irrational (√((3 : ℕ) : ℝ)) := Nat.prime_three.irrational_sqrt + have hnR : (0 : ℝ) < n := by exact_mod_cast hn + have hR : ((2 * m : ℕ) : ℝ) ^ 2 = (3 : ℝ) * (n : ℝ) ^ 2 := by + have : ((4 * m ^ 2 : ℕ) : ℝ) = ((3 * n ^ 2 : ℕ) : ℝ) := by rw [h] + push_cast at this ⊢ + linarith + have hs : √((3 : ℕ) : ℝ) * n = ((2 * m : ℕ) : ℝ) := by + rw [← Real.sqrt_sq hnR.le, ← Real.sqrt_mul (by norm_num), Nat.cast_ofNat, ← hR, + Real.sqrt_sq (by positivity)] + have hq : √((3 : ℕ) : ℝ) = ((2 * m : ℕ) : ℤ) / ((n : ℕ) : ℤ) := by + have hn' : ((n : ℤ) : ℝ) ≠ 0 := by exact_mod_cast hnR.ne' + push_cast at hs hn' ⊢ + rw [eq_div_iff hn'] + exact hs + exact (irrational_iff_ne_rational _).mp hirr _ _ (by exact_mod_cast (by omega : n ≠ 0)) hq + +/-- Waldmann's conjecture A344710: `a(n) > √(3/4) · n` for every `n ≥ 1`. -/ +theorem result : statement := by + intro n hn + obtain ⟨⟨A, B, C, hv, hk⟩, -⟩ := isLeast_a n + have hge := det_sq_ge hv + have hsq : (det2 A B C) ^ 2 = ((a n : ℕ) : ℤ) ^ 2 := by + rw [← hk, Int.natCast_natAbs, sq_abs] + rw [hsq] at hge + have hgeN : 3 * n ^ 2 ≤ 4 * (a n) ^ 2 := by exact_mod_cast hge + have hlt : 3 * n ^ 2 < 4 * (a n) ^ 2 := + lt_of_le_of_ne hgeN (fun h => four_sq_ne_three_sq (a n) n hn h.symm) + have hltR : (3 : ℝ) * (n : ℝ) ^ 2 < 4 * ((a n : ℕ) : ℝ) ^ 2 := by exact_mod_cast hlt + have hapos : (0 : ℝ) < (a n : ℝ) := by + rcases Nat.eq_zero_or_pos (a n) with h0 | h0 + · rw [h0] at hltR + have : (0 : ℝ) < (n : ℝ) := by exact_mod_cast hn + nlinarith + · exact_mod_cast h0 + have hnR : (0 : ℝ) ≤ (n : ℝ) := Nat.cast_nonneg n + rw [← Real.sqrt_sq hnR, ← Real.sqrt_mul (by norm_num), Real.sqrt_lt' hapos] + linarith +end Math0.Frontier.A344710 + +#math0_settles Math0.Frontier.A344710.result Math0.Statements.A344710.statement diff --git a/lean/Math0/Frontier/OEIS/A348484.lean b/lean/Math0/Frontier/OEIS/A348484.lean new file mode 100644 index 0000000..84a2b8a --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A348484.lean @@ -0,0 +1,245 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A348484 +import Math0.Audit + +/-! +# A348484: no two squares two steps apart — the conjectured formula holds + +We prove Yang Hong's conjecture: the maximum number of squares of an `n × n` board with no two +exactly two steps apart in a row or column is `n²/2`, `(n²+1)/2` or `n²/2 + 2` according as +`n ≡ 0`, `n` odd, or `n ≡ 2 (mod 4)`. + +The idea. Let `f` be the involution `j ↦ j xor 2` of `ℕ` (`j + 2` if `j mod 4 < 2`, else +`j - 2`). Pair each square `(i, j)` with `(i, f j)` when `f j < n`, otherwise with `(f i, j)` when +`f i < n`, otherwise leave it unpaired. This is an involution `sig` of the board whose non-trivial +orbits are pairs of squares two steps apart, and whose fixed points are `A × A` with +`A = {j < n | f j ≥ n}`, a set of size `0, 1, 2, 1` for `n ≡ 0, 1, 2, 3 (mod 4)`. + +* Upper bound: an admissible `T` meets each pair at most once, so `T ∩ sig T` consists of fixed + points and `2|T| = |T ∪ sig T| + |T ∩ sig T| ≤ n² + |Fix|`. +* Lower bound: colour `(i, j)` by the parity of `i/2 + j/2`. Two squares two steps apart get + different colours, so the colour-`0` class `S₀` is admissible; every fixed point has colour `0`, + and `sig` maps the colour-`1` squares injectively into `S₀ \ Fix`. Hence + `n² - |S₀| ≤ |S₀| - |Fix|`. + +Together, `a n = |S₀|` and `2 a(n) = n² + |A|²`, which is the conjectured formula in each case. +-/ + +namespace Math0.Frontier.A348484 +open Math0.Statements.A348484 + +/-- The involution `j ↦ j xor 2` of `ℕ`. -/ +private def f (j : ℕ) : ℕ := if j % 4 < 2 then j + 2 else j - 2 + +/-- `f` is an involution. -/ +private lemma f_f (j : ℕ) : f (f j) = j := by + unfold f; split_ifs <;> omega + +/-- `f` moves every number by exactly two. -/ +private lemma f_cases (j : ℕ) : f j = j + 2 ∨ j = f j + 2 := by + unfold f; split_ifs <;> omega + +/-- The pairing involution of the board: move two steps within the row (by `f` on the column) +if that stays on the board, else two steps within the column, else stay put. -/ +private def sig {n : ℕ} (c : Fin n × Fin n) : Fin n × Fin n := + if h : f c.2 < n then (c.1, ⟨f c.2, h⟩) + else if h' : f c.1 < n then (⟨f c.1, h'⟩, c.2) else c + +/-- `sig` is an involution. -/ +private lemma sig_sig {n : ℕ} (c : Fin n × Fin n) : sig (sig c) = c := by + obtain ⟨i, j⟩ := c + unfold sig + by_cases h1 : f j < n + · simp [h1, f_f] + · by_cases h3 : f i < n + · simp [h1, h3, f_f] + · simp [h1, h3] + +/-- The fixed points of `sig` are the squares whose row and column both satisfy `f · ≥ n`. -/ +private lemma sig_eq_iff {n : ℕ} (c : Fin n × Fin n) : + sig c = c ↔ n ≤ f c.1 ∧ n ≤ f c.2 := by + obtain ⟨i, j⟩ := c + unfold sig + by_cases h1 : f j < n + · simp only [h1, dite_true, Prod.mk.injEq, true_and, Fin.ext_iff] + have := f_cases j.val + constructor + · intro h; omega + · intro h; omega + · by_cases h3 : f i < n + · simp only [h1, h3, dite_true, dite_false, Prod.mk.injEq, and_true, Fin.ext_iff] + have := f_cases i.val + constructor + · intro h; omega + · intro h; omega + · simp only [h1, h3, dite_false] + exact ⟨fun _ => by omega, fun _ => trivial⟩ + +/-- A square not fixed by `sig` is two steps apart from its image. -/ +private lemma sig_adj {n : ℕ} (c : Fin n × Fin n) (h : sig c ≠ c) : TwoApart c (sig c) := by + obtain ⟨i, j⟩ := c + unfold sig at h ⊢ + by_cases h1 : f j < n + · simp only [h1, dite_true] + left + exact ⟨rfl, by have := f_cases j.val; simp only; omega⟩ + · by_cases h3 : f i < n + · simp only [h1, h3, dite_true, dite_false] + right + exact ⟨rfl, by have := f_cases i.val; simp only; omega⟩ + · simp [h1, h3] at h + +/-- The colour of a square: the checkerboard colour of its position in its parity class. -/ +private def P {n : ℕ} (c : Fin n × Fin n) : Prop := (c.1.val / 2 + c.2.val / 2) % 2 = 0 + +/-- Decidability of the colour predicate. -/ +private instance {n : ℕ} : DecidablePred (P (n := n)) := fun c => + inferInstanceAs (Decidable ((c.1.val / 2 + c.2.val / 2) % 2 = 0)) + +/-- Squares two steps apart have different colours. -/ +private lemma P_flip {n : ℕ} (c d : Fin n × Fin n) (h : TwoApart c d) : (P c ↔ ¬ P d) := by + unfold P + rcases h with ⟨h1, h2⟩ | ⟨h1, h2⟩ + · rw [h1]; omega + · rw [h1]; omega + +/-- Every fixed point of `sig` has colour `0` (its coordinates are `≡ 0, 1 (mod 4)`). -/ +private lemma P_of_fix {n : ℕ} (c : Fin n × Fin n) (h : sig c = c) : P c := by + rw [sig_eq_iff] at h + have hi := c.1.isLt + have hj := c.2.isLt + unfold P + unfold f at h + split_ifs at h <;> omega + +/-- The colour-`0` class is a maximum admissible set, and twice its size is `n²` plus the +number of fixed points of `sig`. -/ +private lemma key {n : ℕ} : + a n = (Finset.univ.filter (P (n := n))).card ∧ + 2 * (Finset.univ.filter (P (n := n))).card = + n * n + (Finset.univ.filter (fun c : Fin n × Fin n => sig c = c)).card := by + classical + set S0 := Finset.univ.filter (P (n := n)) with hS0 + set C := Finset.univ.filter (fun c : Fin n × Fin n => ¬ P c) with hC + set Fx := Finset.univ.filter (fun c : Fin n × Fin n => sig c = c) with hFx + have hinj : Function.Injective (sig (n := n)) := + Function.Involutive.injective sig_sig + have huniv : (Finset.univ : Finset (Fin n × Fin n)).card = n * n := by + simp + -- upper bound for any admissible set + have hub : ∀ T : Finset (Fin n × Fin n), Admissible T → 2 * T.card ≤ n * n + Fx.card := by + intro T hT + have h1 : (T.image sig).card = T.card := Finset.card_image_of_injective _ hinj + have h2 : (T ∪ T.image sig).card ≤ n * n := huniv ▸ Finset.card_le_univ _ + have h3 : T ∩ T.image sig ⊆ Fx := by + intro c hc + rw [Finset.mem_inter, Finset.mem_image] at hc + obtain ⟨hcT, d, hdT, rfl⟩ := hc + rw [hFx, Finset.mem_filter] + refine ⟨Finset.mem_univ _, ?_⟩ + rw [sig_sig] + by_contra hne + have := sig_adj d (Ne.symm hne) + exact hT d hdT (sig d) hcT this + have h4 := Finset.card_le_card h3 + have h5 := Finset.card_union_add_card_inter T (T.image sig) + omega + -- lower bound for S0 + have hlb : n * n + Fx.card ≤ 2 * S0.card := by + have h1 : (C.image sig).card = C.card := Finset.card_image_of_injective _ hinj + have h2 : S0.card + C.card = n * n := by + rw [← huniv]; exact Finset.card_filter_add_card_filter_not _ + have hdisj : Disjoint (C.image sig) Fx := by + rw [Finset.disjoint_left] + intro x hx hxF + rw [Finset.mem_image] at hx + obtain ⟨c, hcC, rfl⟩ := hx + rw [hFx, Finset.mem_filter, sig_sig] at hxF + rw [hC, Finset.mem_filter] at hcC + exact hcC.2 (P_of_fix c hxF.2.symm) + have hsub : C.image sig ∪ Fx ⊆ S0 := by + intro x hx + rw [Finset.mem_union] at hx + rw [hS0, Finset.mem_filter] + refine ⟨Finset.mem_univ _, ?_⟩ + rcases hx with hx | hx + · rw [Finset.mem_image] at hx + obtain ⟨c, hcC, rfl⟩ := hx + rw [hC, Finset.mem_filter] at hcC + have hne : sig c ≠ c := fun h => hcC.2 (P_of_fix c h) + have := (P_flip c (sig c) (sig_adj c hne)).not + tauto + · rw [hFx, Finset.mem_filter] at hx + exact P_of_fix _ hx.2 + have h3 := Finset.card_le_card hsub + rw [Finset.card_union_of_disjoint hdisj] at h3 + omega + have hS0adm : Admissible S0 := by + intro c hc d hd hcd + rw [hS0, Finset.mem_filter] at hc hd + exact (P_flip c d hcd).1 hc.2 hd.2 + refine ⟨le_antisymm ?_ ?_, ?_⟩ + · apply Finset.sup_le + intro T hT + have := hub T (Finset.mem_filter.1 hT).2 + omega + · exact Finset.le_sup (f := Finset.card) (Finset.mem_filter.2 ⟨Finset.mem_univ _, hS0adm⟩) + · have := hub S0 hS0adm + omega + +/-- The fixed points of `sig` are the squares both of whose coordinates lie in `A`. -/ +private lemma card_fix {n : ℕ} : + (Finset.univ.filter (fun c : Fin n × Fin n => sig c = c)).card = + (Finset.univ.filter (fun j : Fin n => n ≤ f j)).card * + (Finset.univ.filter (fun j : Fin n => n ≤ f j)).card := by + rw [← Finset.card_product] + congr 1 + ext c + simp only [Finset.mem_filter, Finset.mem_univ, true_and, Finset.mem_product, sig_eq_iff] + +/-- The number of `j < n` with `f j ≥ n`, by the residue of `n` mod `4`. -/ +private lemma card_A (n : ℕ) : + (Finset.univ.filter (fun j : Fin n => n ≤ f j)).card = + if n % 4 = 0 then 0 else if n % 4 = 2 then 2 else 1 := by + split_ifs with h0 h2 + · rw [Finset.card_eq_zero, Finset.filter_eq_empty_iff] + intro j _ + have := j.isLt + unfold f; split_ifs <;> omega + · rw [Finset.card_eq_two] + refine ⟨⟨n - 2, by omega⟩, ⟨n - 1, by omega⟩, by simp [Fin.ext_iff]; omega, ?_⟩ + ext j + have := j.isLt + simp only [Finset.mem_filter, Finset.mem_univ, true_and, Finset.mem_insert, + Finset.mem_singleton, Fin.ext_iff] + unfold f; split_ifs <;> omega + · rw [Finset.card_eq_one] + refine ⟨⟨if n % 4 = 1 then n - 1 else n - 2, by split_ifs <;> omega⟩, ?_⟩ + ext j + have := j.isLt + simp only [Finset.mem_filter, Finset.mem_univ, true_and, Finset.mem_singleton, Fin.ext_iff] + unfold f; split_ifs <;> omega + +/-- `2 a(n) = n² + s`, where `s = 0, 1, 4, 1` according as `n ≡ 0, 1, 2, 3 (mod 4)`. -/ +private lemma two_a (n : ℕ) : + 2 * a n = n * n + (if n % 4 = 0 then 0 else if n % 4 = 2 then 4 else 1) := by + obtain ⟨h1, h2⟩ := key (n := n) + rw [h1, h2, card_fix, card_A] + split_ifs <;> rfl + +/-- Yang Hong's conjectured formula for A348484 holds for every `n ≥ 1`. -/ +theorem result : statement := by + intro n _ + have h := two_a n + have hsq : n ^ 2 = n * n := sq n + rw [← hsq] at h + refine ⟨fun h0 => ?_, fun h13 => ?_, fun h2 => ?_⟩ + · rw [if_pos h0] at h; omega + · rw [if_neg (by omega), if_neg (by omega)] at h; omega + · rw [if_neg (by omega), if_pos h2] at h; omega + +end Math0.Frontier.A348484 + +#math0_settles Math0.Frontier.A348484.result Math0.Statements.A348484.statement diff --git a/lean/Math0/Frontier/OEIS/A350499.lean b/lean/Math0/Frontier/OEIS/A350499.lean new file mode 100644 index 0000000..3f5f15a --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A350499.lean @@ -0,0 +1,135 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A350499 +import Math0.Audit + +/-! +# Kurkov's recursion computes the free cumulants (A350499) + +We prove Mikhail Kurkov's conjecture: with `R(1, k) = m_k` and +`R(n, k) = R(n-1, k+1) - ∑_{j=1}^{n-1} R(j, k) R(n-j, 1)` for `n > 1`, one has `R(n, 1) = c_n` +(the `n`-th free cumulant) for every `n > 0`, as polynomials in the indeterminate moments. + +**Idea.** Let `W = M^⟨-1⟩` and `C = x / W` (`Cgf`). For each `k` put +`T_k(x) = ∑_{j ≥ 0} m_{k+j} x^{j+1}` and `F_k = T_k ∘ W`. Then: + +* `T_k = x (m_k + T_{k+1})`, so, substituting `W`, `F_k = W (m_k + F_{k+1})`; multiplying by `C` + and using `C W = x` gives `F_k · C = x (m_k + F_{k+1})`. +* `T_1 = P - 1` and `P ∘ W = (C ∘ M) ∘ W = C ∘ (M ∘ W) = C`, so `F_1 = C - 1`. +* `F_k` has constant term `0` and `C` has constant term `1`. + +Comparing coefficients of `x^n` (`n ≥ 1`) in `F_k · (1 + F_1) = x (m_k + F_{k+1})` gives exactly +`[x^1] F_k = m_k` and `[x^n] F_k = [x^{n-1}] F_{k+1} - ∑_{j=1}^{n-1} [x^j] F_k · [x^{n-j}] F_1`, +i.e. Kurkov's recursion. By strong induction on `n`, `R(n, k) = [x^n] F_k` for all `n ≥ 1` and all +`k`; in particular `R(n, 1) = [x^n] (C - 1) = c_n`. +-/ + +namespace Math0.Frontier.A350499 +open Math0.Statements.A350499 PowerSeries + +/-- The tail series `T_k(x) = ∑_{j ≥ 0} m_{k+j} x^{j+1}`. -/ +private noncomputable def Tk (k : ℕ) : PowerSeries (MvPolynomial ℕ ℤ) := + PowerSeries.mk fun n => if n = 0 then 0 else MvPolynomial.X (k + n - 1) + +/-- `T_k(x) = x (m_k + T_{k+1}(x))`. -/ +private theorem Tk_eq (k : ℕ) : + Tk k = X * (C (MvPolynomial.X k) + Tk (k + 1)) := by + ext n + rcases n with _ | n + · simp [Tk] + · rw [coeff_succ_X_mul] + rcases n with _ | n <;> simp [Tk] + +/-- `T_1(x) = P(x) - 1`. -/ +private theorem Tk_one : Tk 1 = P - 1 := by + ext n + rcases n with _ | n + · simp [Tk, P, mom] + · simp [Tk, P, mom, coeff_one] + +/-- `M^⟨-1⟩` can be substituted (its constant term is `0`). -/ +private theorem hasSubst_Minv : HasSubst Minv := + HasSubst.of_constantCoeff_zero' constantCoeff_Minv + +/-- `F_k = T_k(M^⟨-1⟩(x))`. -/ +private noncomputable def F (k : ℕ) : PowerSeries (MvPolynomial ℕ ℤ) := (Tk k).subst Minv + +/-- `F_k = M^⟨-1⟩ · (m_k + F_{k+1})`, by substituting `M^⟨-1⟩` into `Tk_eq`. -/ +private theorem F_eq (k : ℕ) : F k = Minv * (C (MvPolynomial.X k) + F (k + 1)) := by + rw [F, Tk_eq, subst_mul hasSubst_Minv, subst_X hasSubst_Minv, subst_add hasSubst_Minv, + subst_C] + rfl + +/-- `P(M^⟨-1⟩(x)) = C(x)`, from `C(M(x)) = P(x)` and `M(M^⟨-1⟩(x)) = x`. -/ +private theorem P_subst_Minv : P.subst Minv = Cgf := by + rw [← Cgf_subst_M, subst_comp_subst_apply hasSubst_M hasSubst_Minv, M_subst_Minv, X_subst] + +/-- `F_1 = C - 1`. -/ +private theorem F_one : F 1 = Cgf - 1 := by + rw [F, Tk_one, subst_sub hasSubst_Minv, P_subst_Minv, ← coe_substAlgHom hasSubst_Minv, map_one] + +/-- Each `F_k` has constant term `0`. -/ +private theorem constantCoeff_F (k : ℕ) : constantCoeff (F k) = 0 := by + rw [F_eq, map_mul, constantCoeff_Minv, zero_mul] + +/-- `C` has constant term `c_0 = 1`. -/ +private theorem coeff_zero_Cgf : coeff 0 Cgf = 1 := freeCumulant_zero + +/-- `F_k · C = x (m_k + F_{k+1})`. -/ +private theorem F_mul_Cgf (k : ℕ) : F k * Cgf = X * (C (MvPolynomial.X k) + F (k + 1)) := by + conv_lhs => rw [F_eq k] + rw [mul_comm, ← mul_assoc, Cgf_mul_Minv] + +/-- Coefficient of `x^(n+1)` in `F_mul_Cgf`: +`[x^(n+1)] F_k + ∑_{i coeff i (F k) * coeff j Cgf), Finset.sum_range_succ', Finset.sum_range_succ] + at h + rw [← h, coeff_zero_eq_constantCoeff_apply (F k), constantCoeff_F, zero_mul, add_zero, + Nat.sub_self, coeff_zero_Cgf, mul_one, add_comm] + congr 1 + refine Finset.sum_congr rfl fun i _ => ?_ + rw [Nat.add_sub_add_right] + +/-- `R(n+1, k) = [x^(n+1)] F_k` for all `n` and `k` (strong induction on `n`). -/ +private theorem R_eq_coeff (n : ℕ) : ∀ k, + R (fun k => (MvPolynomial.X k : MvPolynomial ℕ ℤ)) (n + 1) k = coeff (n + 1) (F k) := by + induction n using Nat.strong_induction_on with + | _ n ih => + intro k + have hk := key k n + rcases n with _ | n + · simp at hk + rw [R_one, hk, constantCoeff_F, add_zero] + · rw [R, Fin.sum_univ_eq_sum_range + (fun j => R (fun k => (MvPolynomial.X k : MvPolynomial ℕ ℤ)) (j + 1) k * + R (fun k => (MvPolynomial.X k : MvPolynomial ℕ ℤ)) (n + 1 - j) 1) (n + 1), + ih n (by omega) (k + 1)] + have hs : ∀ j ∈ Finset.range (n + 1), + R (fun k => (MvPolynomial.X k : MvPolynomial ℕ ℤ)) (j + 1) k * + R (fun k => (MvPolynomial.X k : MvPolynomial ℕ ℤ)) (n + 1 - j) 1 = + coeff (j + 1) (F k) * coeff (n + 1 - j) Cgf := by + intro j hj + rw [Finset.mem_range] at hj + rw [ih j (by omega) k, show n + 1 - j = (n - j) + 1 by omega, ih (n - j) (by omega) 1, + F_one, map_sub, coeff_one, if_neg (Nat.succ_ne_zero _), sub_zero] + rw [Finset.sum_congr rfl hs] + rw [map_add, coeff_C, if_neg (Nat.succ_ne_zero _), zero_add] at hk + rw [← hk] + ring + +/-- Kurkov's conjecture holds: `R(n, 1) = c_n` for every `n > 0`. -/ +theorem result : statement := by + intro n hn + obtain ⟨n, rfl⟩ : ∃ n', n = n' + 1 := ⟨n - 1, by omega⟩ + rw [R_eq_coeff, F_one, map_sub, coeff_one, if_neg (Nat.succ_ne_zero n), sub_zero] + rfl + +end Math0.Frontier.A350499 + +#math0_settles Math0.Frontier.A350499.result Math0.Statements.A350499.statement diff --git a/lean/Math0/Frontier/OEIS/A350557.lean b/lean/Math0/Frontier/OEIS/A350557.lean new file mode 100644 index 0000000..c3d5bec --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A350557.lean @@ -0,0 +1,262 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A350557 +import Math0.Audit + +/-! +# OEIS A350557: the signed triangle is the inverse of A350512 + +We prove Werner Schulte's conjecture: `M(n,k) = (-1)^(n-k) T(n,k)` is the matrix inverse of the +lower-triangular matrix `L` of A350512, i.e. `L * M = I` and `M * L = I`. + +Idea. Introduce two auxiliary lower-triangular matrices: the bidiagonal `A` with `A(n,n) = 1`, +`A(n,n-1) = 2n-1`, and `B` with `B(0,0) = 1`, `B(n,k) = (-1)^(n-k) C(n-1,k-1)` for `n, k ≥ 1`. +* `A * M = B`: this is the recurrence `T(n+1,j) = (2n+1) T(n,j) + [j ≥ 1] C(n,j-1)`, which + follows from the definition of `T` by splitting off the top term of the sum. +* `B * L = A`: using `L(k+1,j) = (2j+1) C(k,j) + [j ≥ 1] C(k,j-1)`, this reduces to binomial + inversion `∑_k (-1)^(m-k) C(m,k) C(k,i) = [m = i]` (coefficient of `X^i` in + `((X+1) - 1)^m`). +Hence, on every `N × N` upper-left block, `A (M L) = (A M) L = B L = A`; `A` has determinant `1`, +so `M L = I`, and then `L M = I` because these are square matrices over a field. +-/ + +namespace Math0.Frontier.A350557 +open Math0.Statements.A350557 + +/-- The bidiagonal matrix with `1` on the diagonal and `2n-1` at `(n, n-1)`. -/ +private def A (n k : ℕ) : ℚ := if n = k then 1 else if n = k + 1 then 2 * (n : ℚ) - 1 else 0 + +/-- `B(0,0) = 1`, `B(n,k) = (-1)^(n-k) C(n-1,k-1)` for `n, k ≥ 1`, and `0` otherwise. -/ +private def B (n k : ℕ) : ℚ := + if n = 0 then (if k = 0 then 1 else 0) + else if k = 0 then 0 else (-1) ^ (n - k) * ((n - 1).choose (k - 1) : ℚ) + +/-- Upper-left `N × N` block of an `ℕ`-indexed matrix. -/ +private def toMat (N : ℕ) (X : ℕ → ℕ → ℚ) : Matrix (Fin N) (Fin N) ℚ := + Matrix.of fun i j => X i j + +/-- Entries of the product of two blocks, when the left factor is lower triangular. -/ +private lemma toMat_mul_apply (X Y : ℕ → ℕ → ℚ) (hX : ∀ n k, n < k → X n k = 0) (N : ℕ) + (i j : Fin N) : + (toMat N X * toMat N Y) i j = ∑ k ∈ Finset.range (i + 1), X i k * Y k j := by + rw [Matrix.mul_apply] + simp only [toMat, Matrix.of_apply] + rw [Fin.sum_univ_eq_sum_range (fun k => X i k * Y k j) N] + symm + apply Finset.sum_subset + · intro k hk + simp only [Finset.mem_range] at hk ⊢ + omega + · intro k _ hk + simp only [Finset.mem_range, not_lt] at hk + rw [hX _ _ (by omega), zero_mul] + +/-- `L` is lower triangular. -/ +private lemma L_lower : ∀ n k, n < k → L n k = 0 := by + intro n k h; simp [L, h] + +/-- `M` is lower triangular. -/ +private lemma M_lower : ∀ n k, n < k → M n k = 0 := by + intro n k h; simp [M, T, h] + +/-- `A` is lower triangular. -/ +private lemma A_lower : ∀ n k, n < k → A n k = 0 := by + intro n k h; unfold A; rw [if_neg (by omega), if_neg (by omega)] + +/-- `B` is lower triangular. -/ +private lemma B_lower : ∀ n k, n < k → B n k = 0 := by + intro n k h + unfold B + by_cases hn : n = 0 + · rw [if_pos hn, if_neg (by omega)] + · rw [if_neg hn, if_neg (by omega), Nat.choose_eq_zero_of_lt (by omega)] + simp + +/-- Binomial inversion: `∑_k (-1)^(m-k) C(m,k) C(k,i) = [m = i]`. -/ +private lemma inv_pascal (m i : ℕ) : + ∑ k ∈ Finset.range (m + 1), (-1 : ℚ) ^ (m - k) * (m.choose k : ℚ) * (k.choose i : ℚ) = + if m = i then 1 else 0 := by + have h : ((Polynomial.X + 1 : Polynomial ℚ) + Polynomial.C (-1)) ^ m = + ∑ k ∈ Finset.range (m + 1), (Polynomial.X + 1) ^ k * + Polynomial.C ((-1 : ℚ) ^ (m - k) * (m.choose k : ℚ)) := by + rw [add_pow] + refine Finset.sum_congr rfl fun k _ => ?_ + simp only [map_mul, map_pow, map_natCast] + ring + have h2 := congrArg (fun p => Polynomial.coeff p i) h + simp only [Polynomial.finsetSum_coeff, Polynomial.coeff_mul_C, + Polynomial.coeff_X_add_one_pow] at h2 + rw [show (Polynomial.X + 1 : Polynomial ℚ) + Polynomial.C (-1) = Polynomial.X by + simp [map_neg, map_one]] at h2 + rw [Polynomial.coeff_X_pow] at h2 + rw [Finset.sum_congr rfl (fun k _ => by ring : + ∀ k ∈ Finset.range (m + 1), (-1 : ℚ) ^ (m - k) * (m.choose k : ℚ) * (k.choose i : ℚ) = + (k.choose i : ℚ) * ((-1) ^ (m - k) * (m.choose k : ℚ))), ← h2] + split_ifs <;> first | rfl | omega + +/-- For `k ≥ 1` the summation formula for `T n k` holds for all `n` +(the sum is empty if `n < k`). -/ +private lemma T_pos (n k : ℕ) (hk : k ≠ 0) : + T n k = (∑ i ∈ Finset.Icc k n, + ((i - 1).choose (k - 1) : ℚ) * 2 ^ i * i.factorial / (2 * i).factorial) * + (2 * n).factorial / (2 ^ n * n.factorial) := by + simp only [T, hk, if_false] + split_ifs with h + · rw [Finset.Icc_eq_empty (by omega)]; simp + · rfl + +/-- `(2m+2)! = (2m+2)(2m+1)(2m)!`. -/ +private lemma fact_two_succ (m : ℕ) : + ((2 * (m + 1)).factorial : ℚ) = (2 * m + 2) * (2 * m + 1) * (2 * m).factorial := by + rw [show 2 * (m + 1) = (2 * m + 1) + 1 by ring, Nat.factorial_succ, Nat.factorial_succ] + push_cast; ring + +/-- The recurrence `T(m+1,j) = (2m+1) T(m,j) + [j ≥ 1] C(m,j-1)`. -/ +private lemma T_succ (m j : ℕ) : + T (m + 1) j = (2 * m + 1) * T m j + (if j = 0 then 0 else ((m.choose (j - 1) : ℕ) : ℚ)) := by + have hf := fact_two_succ m + have h1 : ((2 * m).factorial : ℚ) ≠ 0 := by positivity + have h2 : (m.factorial : ℚ) ≠ 0 := by positivity + have h3 : (2 * (m : ℚ) + 2) ≠ 0 := by positivity + have h4 : (2 * (m : ℚ) + 1) ≠ 0 := by positivity + have h5 : ((m : ℚ) + 1) ≠ 0 := by positivity + rcases Nat.eq_zero_or_pos j with rfl | hj + · simp only [T, Nat.not_lt_zero, if_false, if_true] + rw [hf, Nat.factorial_succ]; push_cast; field_simp; ring + · rw [if_neg (by omega), T_pos _ _ (by omega), T_pos _ _ (by omega)] + rcases le_or_gt j (m + 1) with hjm | hjm + · rw [Finset.sum_Icc_succ_top hjm, hf, Nat.factorial_succ] + simp only [Nat.add_sub_cancel] + push_cast + field_simp + ring + · rw [Finset.Icc_eq_empty (by omega), Finset.Icc_eq_empty (by omega), + Nat.choose_eq_zero_of_lt (by omega)] + simp + +/-- The signed recurrence `M(m+1,j) + (2m+1) M(m,j) = B(m+1,j)`. -/ +private lemma M_succ (m j : ℕ) : M (m + 1) j + (2 * m + 1) * M m j = B (m + 1) j := by + unfold M + rw [T_succ] + unfold B + rw [if_neg (Nat.succ_ne_zero m)] + rcases le_or_gt j m with hjm | hjm + · rw [show m + 1 - j = (m - j) + 1 by omega, pow_succ] + split_ifs with hj + · ring + · simp only [Nat.add_sub_cancel]; ring + · have hT : T m j = 0 := by simp [T, hjm] + simp [hT, show j ≠ 0 by omega] + +/-- `A * M = B`, entrywise. -/ +private lemma AM_entry (n j : ℕ) : ∑ k ∈ Finset.range (n + 1), A n k * M k j = B n j := by + cases n with + | zero => + rcases Nat.eq_zero_or_pos j with rfl | hj + · simp [A, M, B, T] + · simp [A, M, B, T, hj, hj.ne'] + | succ m => + rw [Finset.sum_range_succ, Finset.sum_range_succ, Finset.sum_eq_zero, ← M_succ] + · simp [A]; ring + · intro k hk + simp only [Finset.mem_range] at hk + simp only [A] + rw [if_neg (by omega), if_neg (by omega), zero_mul] + +/-- `L(k+1,j) = (2j+1) C(k,j) + [j ≥ 1] C(k,j-1)`. -/ +private lemma L_succ (k j : ℕ) : + L (k + 1) j = (2 * j + 1) * (k.choose j : ℚ) + + (if j = 0 then 0 else (k.choose (j - 1) : ℚ)) := by + rcases Nat.eq_zero_or_pos j with rfl | hj + · simp [L] + · obtain ⟨i, rfl⟩ : ∃ i, j = i + 1 := ⟨j - 1, by omega⟩ + rw [if_neg (Nat.succ_ne_zero i)] + simp only [Nat.add_sub_cancel] + rcases le_or_gt i k with hik | hik + · have hc := Nat.choose_succ_right_eq k i + have hc' : (k.choose (i + 1) : ℚ) * (i + 1) = (k.choose i : ℚ) * ((k : ℚ) - i) := by + rw [← Nat.cast_sub hik]; exact_mod_cast hc + unfold L + rw [if_neg (by omega), if_neg (Nat.succ_ne_zero i)] + simp only [Nat.add_sub_cancel, Nat.add_sub_add_right] + rw [Nat.cast_sub hik, div_eq_iff (by positivity)] + push_cast + linear_combination (-(2 * (i : ℚ) + 3)) * hc' + · unfold L + rw [if_pos (by omega), Nat.choose_eq_zero_of_lt (by omega), Nat.choose_eq_zero_of_lt hik] + simp + +/-- `B * L = A`, entrywise. -/ +private lemma BL_entry (n j : ℕ) : ∑ k ∈ Finset.range (n + 1), B n k * L k j = A n j := by + cases n with + | zero => + rcases Nat.eq_zero_or_pos j with rfl | hj + · simp [A, B, L] + · simp [A, B, L, hj, hj.ne, hj.ne'] + | succ m => + rw [Finset.sum_range_succ'] + have hB : ∀ k, B (m + 1) (k + 1) = (-1) ^ (m - k) * (m.choose k : ℚ) := by + intro k; simp [B] + simp only [hB, L_succ] + have e : ∀ k ∈ Finset.range (m + 1), (-1 : ℚ) ^ (m - k) * (m.choose k : ℚ) * + ((2 * j + 1) * (k.choose j : ℚ) + (if j = 0 then 0 else (k.choose (j - 1) : ℚ))) = + (2 * j + 1) * ((-1 : ℚ) ^ (m - k) * (m.choose k : ℚ) * (k.choose j : ℚ)) + + (if j = 0 then 0 else 1) * ((-1 : ℚ) ^ (m - k) * (m.choose k : ℚ) * + (k.choose (j - 1) : ℚ)) := by + intro k _; split_ifs <;> ring + rw [Finset.sum_congr rfl e, Finset.sum_add_distrib, ← Finset.mul_sum, ← Finset.mul_sum, + inv_pascal, inv_pascal, show B (m + 1) 0 = 0 by simp [B]] + unfold A + split_ifs <;> (try subst_vars) <;> first | omega | (push_cast; ring) + +/-- `A * M = B` on `N × N` blocks. -/ +private lemma mat_AM (N : ℕ) : toMat N A * toMat N M = toMat N B := by + ext i j + rw [toMat_mul_apply _ _ A_lower, AM_entry] + rfl + +/-- `B * L = A` on `N × N` blocks. -/ +private lemma mat_BL (N : ℕ) : toMat N B * toMat N L = toMat N A := by + ext i j + rw [toMat_mul_apply _ _ B_lower, BL_entry] + rfl + +/-- The block of `A` is unitriangular, so its determinant is `1`. -/ +private lemma det_A (N : ℕ) : (toMat N A).det = 1 := by + have h : (toMat N A).IsLowerTriangular := by + intro i j hij + have hij' : i < j := OrderDual.toDual_lt_toDual.mp hij + simp only [toMat, Matrix.of_apply] + exact A_lower _ _ hij' + rw [Matrix.det_of_isLowerTriangular _ h] + simp [toMat, A] + +/-- `M * L = 1` on `N × N` blocks. -/ +private lemma mat_ML (N : ℕ) : toMat N M * toMat N L = 1 := by + have hu : IsUnit (toMat N A) := by + rw [Matrix.isUnit_iff_isUnit_det, det_A]; exact isUnit_one + apply hu.mul_left_cancel + rw [← mul_assoc, mat_AM, mat_BL, mul_one] + +/-- `L * M = 1` on `N × N` blocks. -/ +private lemma mat_LM (N : ℕ) : toMat N L * toMat N M = 1 := mul_eq_one_comm.mp (mat_ML N) + +/-- Schulte's conjecture holds: `M(n,k) = (-1)^(n-k) T(n,k)` is the two-sided matrix inverse of +the triangle `L` of A350512. -/ +theorem result : statement := by + refine ⟨fun n j => ?_, fun n j => ?_⟩ + · have h : (toMat (n + j + 1) L * toMat (n + j + 1) M) ⟨n, by omega⟩ ⟨j, by omega⟩ = + (1 : Matrix (Fin (n + j + 1)) (Fin (n + j + 1)) ℚ) ⟨n, by omega⟩ ⟨j, by omega⟩ := by + rw [mat_LM] + rw [toMat_mul_apply _ _ L_lower, Matrix.one_apply] at h + simpa [Fin.ext_iff] using h + · have h : (toMat (n + j + 1) M * toMat (n + j + 1) L) ⟨n, by omega⟩ ⟨j, by omega⟩ = + (1 : Matrix (Fin (n + j + 1)) (Fin (n + j + 1)) ℚ) ⟨n, by omega⟩ ⟨j, by omega⟩ := by + rw [mat_ML] + rw [toMat_mul_apply _ _ M_lower, Matrix.one_apply] at h + simpa [Fin.ext_iff] using h + +end Math0.Frontier.A350557 + +#math0_settles Math0.Frontier.A350557.result Math0.Statements.A350557.statement diff --git a/lean/Math0/Frontier/OEIS/A350900.lean b/lean/Math0/Frontier/OEIS/A350900.lean new file mode 100644 index 0000000..d753f7b --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A350900.lean @@ -0,0 +1,163 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A350900 +import Math0.Audit + +/-! +# OEIS A350900: Schulte's gcd-ratio double sum is a Dirichlet convolution + +We prove all four parts of Werner Schulte's conjecture (Jan 21 2022) in A350900: for every +arithmetic function `f` and `n > 0`, +`a(f; n) = ∑_{i,k=1}^{n} f(gcd(i,n)/gcd(gcd(i,k),n)) = ((f·φ) * A057660)(n)`; +`a(f; ·)` is multiplicative when `f` is; the row sums of the triangle are `a(id; n)`; and the +row sums equal `(A002618 * A057660)(n)`. + +Idea. Since `gcd(gcd(i,k),n) = gcd(g,k)` with `g = gcd(i,n)`, and both indices may be taken +modulo `n`, the sum over `k` is `(n/g)` copies of a full period `∑_{k simp + | succ n ih => rw [Finset.sum_Icc_succ_top (by omega), ih, Finset.sum_range_succ] + +/-- For `F 0 = F n`, summing over `1, …, n` is the same as summing over `0, …, n-1`. -/ +private lemma sum_Icc_eq_sum_range {M : Type*} [AddCommMonoid M] (F : ℕ → M) (n : ℕ) + (h : F 0 = F n) : ∑ k ∈ Icc 1 n, F k = ∑ k ∈ range n, F k := by + rw [sum_Icc_eq_sum_range_succ] + cases n with + | zero => simp + | succ m => rw [sum_range_succ, sum_range_succ' F, h] + +/-- Grouping `0 ≤ i < n` by `gcd(n, i)`: each divisor `d` occurs `φ(n/d)` times. -/ +private lemma sum_range_gcd {M : Type*} [AddCommMonoid M] (n : ℕ) (hn : 0 < n) (G : ℕ → M) : + ∑ i ∈ range n, G (Nat.gcd n i) = ∑ d ∈ n.divisors, Nat.totient (n / d) • G d := by + rw [← Finset.sum_fiberwise_of_maps_to (g := fun i => Nat.gcd n i) (t := n.divisors)] + · refine sum_congr rfl fun d hd => ?_ + rw [Nat.totient_div_of_dvd (Nat.dvd_of_mem_divisors hd), ← sum_const] + refine sum_congr rfl fun i hi => ?_ + rw [(mem_filter.1 hi).2] + · intro i _ + simp [Nat.mem_divisors, Nat.gcd_dvd_left, hn.ne'] + +/-- Periodicity of `k ↦ gcd(g, k)`: a sum over `g * m` consecutive values is `m` full periods. -/ +private lemma sum_range_mul_gcd {M : Type*} [AddCommMonoid M] (g m : ℕ) (F : ℕ → M) : + ∑ k ∈ range (g * m), F (Nat.gcd g k) = m • ∑ k ∈ range g, F (Nat.gcd g k) := by + induction m with + | zero => simp + | succ m ih => + rw [Nat.mul_succ, sum_range_add, ih, succ_nsmul] + congr 1 + refine sum_congr rfl fun k _ => ?_ + rw [Nat.gcd_mul_left_add_right] + +/-- `phi` evaluates to Euler's totient. -/ +private lemma phi_apply (n : ℕ) : phi n = Nat.totient n := rfl + +/-- Euler's totient is multiplicative. -/ +private lemma phi_mult : phi.IsMultiplicative := + ⟨Nat.totient_one, fun h => Nat.totient_mul h⟩ + +/-- `∑_{k=1}^{m} m / gcd(m,k) = ∑_{d ∣ m} d φ(d)`, i.e. `A057660 = ζ * (id · φ)`. -/ +private lemma A057660Fn_eq : + A057660Fn = (ζ : ArithmeticFunction ℕ) * (ArithmeticFunction.id.pmul phi) := by + ext m + rcases Nat.eq_zero_or_pos m with rfl | hm + · simp + rw [zeta_mul_apply] + show A057660 m = _ + unfold A057660 + rw [sum_Icc_eq_sum_range (fun k => m / Nat.gcd m k) m (by simp), + sum_range_gcd m hm (fun d => m / d)] + have := Nat.sum_div_divisors m (fun x => Nat.totient x • x) + rw [this] + refine sum_congr rfl fun d _ => ?_ + simp [pmul_apply, phi_apply, mul_comm] + +/-- `A057660` is multiplicative, being `ζ * (id · φ)`. -/ +private lemma A057660Fn_mult : A057660Fn.IsMultiplicative := by + rw [A057660Fn_eq] + exact isMultiplicative_zeta.mul (isMultiplicative_id.pmul phi_mult) + +/-- The core computation: `a(f; n) = ∑_{g ∣ n} φ(n/g) (n/g) ∑_{e ∣ g} φ(e) f(e)`. -/ +private lemma aF_eq {R : Type*} [CommSemiring R] (f : ArithmeticFunction R) (n : ℕ) + (hn : 0 < n) : + aF f n = ∑ g ∈ n.divisors, + Nat.totient (n / g) • ((n / g) • ∑ e ∈ g.divisors, Nat.totient e • f e) := by + have h1 : aF f n = ∑ i ∈ range n, ∑ k ∈ range n, + f (Nat.gcd n i / Nat.gcd (Nat.gcd n i) k) := by + unfold aF + rw [sum_Icc_eq_sum_range _ n (by simp [Nat.gcd_comm])] + refine sum_congr rfl fun i _ => ?_ + rw [sum_Icc_eq_sum_range _ n (by simp)] + refine sum_congr rfl fun k _ => ?_ + rw [Nat.gcd_right_comm, Nat.gcd_comm i n] + rw [h1, sum_range_gcd n hn + (fun g => ∑ k ∈ range n, f (g / Nat.gcd g k))] + refine sum_congr rfl fun g hg => ?_ + have hgn : g ∣ n := Nat.dvd_of_mem_divisors hg + have hg0 : 0 < g := Nat.pos_of_mem_divisors hg + congr 1 + conv_lhs => rw [← Nat.mul_div_cancel' hgn] + rw [sum_range_mul_gcd g (n / g) (fun d => f (g / d)), sum_range_gcd g hg0 (fun d => f (g / d))] + congr 1 + exact Nat.sum_div_divisors g (fun x => Nat.totient x • f x) + +/-- Part 1 over an arbitrary commutative semiring. -/ +private lemma main {R : Type*} [CommSemiring R] (f : ArithmeticFunction R) (n : ℕ) + (hn : 0 < n) : + aF f n = (f.pmul (phi : ArithmeticFunction R) * (A057660Fn : ArithmeticFunction R)) n := by + rw [aF_eq f n hn, A057660Fn_eq, natCoe_mul, ← mul_assoc, mul_apply, + Nat.sum_divisorsAntidiagonal (fun a b => ((f.pmul (phi : ArithmeticFunction R)) * + (ζ : ArithmeticFunction R)) a * + (↑(ArithmeticFunction.id.pmul phi) : ArithmeticFunction R) b)] + refine sum_congr rfl fun g _ => ?_ + rw [coe_mul_zeta_apply] + simp only [pmul_apply, natCoe_apply, phi_apply, id_apply, nsmul_eq_mul] + push_cast + rw [show ∑ e ∈ g.divisors, f e * (Nat.totient e : R) = + ∑ e ∈ g.divisors, (Nat.totient e : R) * f e from sum_congr rfl fun _ _ => mul_comm _ _] + ring + +/-- The row sums of the triangle are `a(id; n)`. -/ +private lemma rowsum_eq (n : ℕ) : + ∑ k ∈ Icc 1 n, T n k = aF (ArithmeticFunction.id : ArithmeticFunction ℕ) n := by + unfold T aF + rw [Finset.sum_comm] + rfl + +/-- Schulte's conjecture (all four parts) holds. -/ +theorem result : statement := by + refine ⟨fun f n hn => main f n hn, fun f hf => ?_, fun n _ => ?_, fun n hn => ?_⟩ + · have : aFun f = + f.pmul (phi : ArithmeticFunction ℂ) * (A057660Fn : ArithmeticFunction ℂ) := by + ext n + rcases Nat.eq_zero_or_pos n with rfl | hn + · simp + · exact main f n hn + rw [this] + exact (hf.pmul phi_mult.natCast).mul A057660Fn_mult.natCast + · rw [rowsum_eq] + simp only [aF, natCoe_apply, id_apply, Nat.cast_sum] + · have hA : (ArithmeticFunction.id : ArithmeticFunction ℕ).pmul phi = A002618Fn := by + ext x + simp [pmul_apply, phi_apply, A002618Fn, A002618] + rw [rowsum_eq, main _ n hn, natCoe_nat, natCoe_nat, hA] + +end Math0.Frontier.A350900 + +#math0_settles Math0.Frontier.A350900.result Math0.Statements.A350900.statement diff --git a/lean/Math0/Frontier/OEIS/A351743.lean b/lean/Math0/Frontier/OEIS/A351743.lean new file mode 100644 index 0000000..083ab19 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A351743.lean @@ -0,0 +1,407 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A351743 +import Math0.Audit + +/-! +# A351743: the eventual affine 42-block structure + +We prove all four conjectures in `Math0.Statements.A351743.statement`: Sycamore's conjecture that +`1` and `2` occur infinitely often in A351743, Sigrist's two conjectures on the odd- and +even-indexed terms, and the A355149 conjecture on the partial sums. + +The idea. Put `Y 0 = 0`, `Y (m + 1) = 3645 * Y m + 1` (so `Y m = (3645^m - 1)/3644`). For each +`i < 42` there are explicit naturals `(P_i, Q_i, R_i, U_i)` (the table `rows`) such that for all +`m`, `a(139 + 42 m + i) = P_i * Y m + Q_i` and `s(139 + 42 m + i) = R_i * Y m + U_i`. +This is proved by induction: the base `m = 0, i = 0` is a kernel computation, and each step of +the recursion maps the affine pair of row `i` to the affine pair of row `i + 1` *for every value* +`W` of the parameter (row `41` maps to row `0` evaluated at `3645 W + 1`). Such a step is a +statement `coprimePart (R W + U) (P W + Q) = P' W + Q'`, which follows from a factorisation +`R W + U = d * e` with `d` prime to `P W + Q` and `e ∣ (P W + Q)^k` (`cp_eq`). There are two +shapes: +* when `P = 0` (so `a(n) = Q ∈ {1, …, 5}` is constant), `e` is a constant dividing `Q^k` and + `d = P' W + Q'` is prime to `Q` because some `g` with `Q ∣ g^k` divides `P'` and is prime to + `Q'`; +* when `P' = 0` (then `s(n) = c * a(n)` with `c ∈ {2, 4, 5, 6, 9}`), `d = Q'` is a constant and + `e = f * (P W + Q)`, where `f ∣ h^k` for a common divisor `h` of `P` and `Q`. +All the finitely many arithmetic side conditions on the table (`Good`) are checked by the kernel. +The conjectures then follow: rows `4` and `8` are `a = 1` and `a = 2`, the rows of odd index +`139 + i` are constant, and since `Y (m + 1) = 3645 * Y m + 1`, the quantities +`a(n + 42) - 3645 a(n)` and `s(n + 42) - 3645 s(n)` only depend on `i`. +-/ + +namespace Math0.Frontier.A351743 +open Math0.Statements.A351743 + +/-- The block parameter: `Y 0 = 0`, `Y (m + 1) = 3645 * Y m + 1`, +i.e. `Y m = (3645^m - 1)/3644`. -/ +private def Y : ℕ → ℕ + | 0 => 0 + | m + 1 => 3645 * Y m + 1 + +/-- The pair `(P * W + Q, R * W + U)` described by a row `(P, Q, R, U)` at parameter `W`. -/ +private def F (r : ℕ × ℕ × ℕ × ℕ) (W : ℕ) : ℕ × ℕ := + (r.1 * W + r.2.1, r.2.2.1 * W + r.2.2.2) + +/-- The rows `(P_i, Q_i, R_i, U_i)`, `i < 42`: `a(139 + 42 m + i) = P_i * Y m + Q_i` and +`s(139 + 42 m + i) = R_i * Y m + U_i`. -/ +private def rows : List (ℕ × ℕ × ℕ × ℕ) := + [(0, 3, 1150034580, 315591), + (383344860, 105197, 1533379440, 420788), + (0, 4, 1533379440, 420792), + (191672430, 52599, 1725051870, 473391), + (0, 1, 1725051870, 473392), + (1725051870, 473392, 3450103740, 946784), + (0, 1, 3450103740, 946785), + (3450103740, 946785, 6900207480, 1893570), + (0, 2, 6900207480, 1893572), + (1725051870, 473393, 8625259350, 2366965), + (0, 5, 8625259350, 2366970), + (1725051870, 473394, 10350311220, 2840364), + (0, 1, 10350311220, 2840365), + (10350311220, 2840365, 20700622440, 5680730), + (0, 2, 20700622440, 5680732), + (5175155610, 1420183, 25875778050, 7100915), + (0, 5, 25875778050, 7100920), + (5175155610, 1420184, 31050933660, 8521104), + (0, 3, 31050933660, 8521107), + (10350311220, 2840369, 41401244880, 11361476), + (0, 4, 41401244880, 11361480), + (5175155610, 1420185, 46576400490, 12781665), + (0, 1, 46576400490, 12781666), + (46576400490, 12781666, 93152800980, 25563332), + (0, 1, 93152800980, 25563333), + (93152800980, 25563333, 186305601960, 51126666), + (0, 2, 186305601960, 51126668), + (46576400490, 12781667, 232882002450, 63908335), + (0, 5, 232882002450, 63908340), + (46576400490, 12781668, 279458402940, 76690008), + (0, 1, 279458402940, 76690009), + (279458402940, 76690009, 558916805880, 153380018), + (0, 2, 558916805880, 153380020), + (139729201470, 38345005, 698646007350, 191725025), + (0, 1, 698646007350, 191725026), + (698646007350, 191725026, 1397292014700, 383450052), + (0, 1, 1397292014700, 383450053), + (1397292014700, 383450053, 2794584029400, 766900106), + (0, 2, 2794584029400, 766900108), + (698646007350, 191725027, 3493230036750, 958625135), + (0, 5, 3493230036750, 958625140), + (698646007350, 191725028, 4191876044100, 1150350168)] + +/-- Row `i` of the table. -/ +private def row (i : ℕ) : ℕ × ℕ × ℕ × ℕ := rows.getD i (0, 0, 0, 0) + +/-- Certificates for the steps: `(e, g, k, 0, 0)` for a step of the first shape (`GoodSmall`), +`(c, f, g, h, k)` for a step of the second shape (`GoodBig`). -/ +private def certs : List (ℕ × ℕ × ℕ × ℕ × ℕ) := + [(3, 3, 4, 0, 0), + (4, 1, 2, 1, 4), + (8, 2, 4, 0, 0), + (9, 9, 1, 3, 4), + (1, 1, 4, 0, 0), + (2, 2, 1, 2, 4), + (1, 1, 4, 0, 0), + (2, 1, 2, 15, 4), + (4, 2, 4, 0, 0), + (5, 1, 5, 1, 4), + (5, 5, 4, 0, 0), + (6, 6, 1, 6, 4), + (1, 1, 4, 0, 0), + (2, 1, 2, 5, 4), + (4, 2, 4, 0, 0), + (5, 1, 5, 1, 4), + (5, 5, 4, 0, 0), + (6, 2, 3, 2, 4), + (3, 3, 4, 0, 0), + (4, 1, 2, 1, 4), + (8, 2, 4, 0, 0), + (9, 9, 1, 15, 4), + (1, 1, 4, 0, 0), + (2, 2, 1, 2, 4), + (1, 1, 4, 0, 0), + (2, 1, 2, 3, 4), + (4, 2, 4, 0, 0), + (5, 1, 5, 1, 4), + (5, 5, 4, 0, 0), + (6, 6, 1, 6, 4), + (1, 1, 4, 0, 0), + (2, 1, 2, 1, 4), + (4, 2, 4, 0, 0), + (5, 5, 1, 5, 4), + (1, 1, 4, 0, 0), + (2, 2, 1, 6, 4), + (1, 1, 4, 0, 0), + (2, 1, 2, 1, 4), + (4, 2, 4, 0, 0), + (5, 1, 5, 1, 4), + (5, 5, 4, 0, 0), + (6, 2, 3, 2, 4)] + +/-- Certificate `i`. -/ +private def cert (i : ℕ) : ℕ × ℕ × ℕ × ℕ × ℕ := certs.getD i (0, 0, 0, 0, 0) + +/-- The row describing block `m + 1` in terms of the parameter `Y m` of block `m` +(see `F_shift`). -/ +private def shift (r : ℕ × ℕ × ℕ × ℕ) : ℕ × ℕ × ℕ × ℕ := + (3645 * r.1, r.1 + r.2.1, 3645 * r.2.2.1, r.2.2.1 + r.2.2.2) + +/-- The row following row `i`: row `i + 1`, or the shifted row `0` after row `41`. -/ +private def nextRow (i : ℕ) : ℕ × ℕ × ℕ × ℕ := if i = 41 then shift (row 0) else row (i + 1) + +/-- Side conditions for a step from `r` to `r'` when `a(n) = Q` is constant (`P = 0`): +`R W + U = e * (P' W + Q')` with `e ∣ Q^k`, and `P' W + Q'` prime to `Q`. -/ +private abbrev GoodSmall (r r' : ℕ × ℕ × ℕ × ℕ) (e g k : ℕ) : Prop := + r.1 = 0 ∧ r.2.2.1 = e * r'.1 ∧ r.2.2.2 = e * r'.2.1 ∧ e ∣ r.2.1 ^ k ∧ g ∣ r'.1 ∧ + Nat.Coprime r'.2.1 g ∧ r.2.1 ∣ g ^ k ∧ 0 < e ∧ 0 < r'.2.1 ∧ + r'.2.2.1 = r.2.2.1 + r'.1 ∧ r'.2.2.2 = r.2.2.2 + r'.2.1 + +/-- Side conditions for a step from `r` to `r'` when `s(n) = c * a(n)` and `a(n + 1) = Q'` is +constant (`P' = 0`): `c = Q' * f` with `f ∣ (P W + Q)^k` and `Q'` prime to `P W + Q`. -/ +private abbrev GoodBig (r r' : ℕ × ℕ × ℕ × ℕ) (c f g h k : ℕ) : Prop := + r'.1 = 0 ∧ r.2.2.1 = c * r.1 ∧ r.2.2.2 = c * r.2.1 ∧ c = r'.2.1 * f ∧ h ∣ r.1 ∧ h ∣ r.2.1 ∧ + f ∣ h ^ k ∧ g ∣ r.1 ∧ Nat.Coprime r.2.1 g ∧ r'.2.1 ∣ g ^ k ∧ 0 < r'.2.1 ∧ 0 < r.2.1 ∧ + 0 < f ∧ r'.2.2.1 = r.2.2.1 ∧ r'.2.2.2 = r.2.2.2 + r'.2.1 + +/-- A certified step from row `r` to row `r'`. -/ +private abbrev Good (r r' : ℕ × ℕ × ℕ × ℕ) (x : ℕ × ℕ × ℕ × ℕ × ℕ) : Prop := + GoodSmall r r' x.1 x.2.1 x.2.2.1 ∨ GoodBig r r' x.1 x.2.1 x.2.2.1 x.2.2.2.1 x.2.2.2.2 + +/-- If `w = d * e` with `d` prime to `v` and `e ∣ v^k`, then the greatest divisor of `w` prime +to `v` is `d`. -/ +private theorem cp_eq (d e v k : ℕ) (hd : 0 < d) (he : 0 < e) (hc : Nat.Coprime d v) + (hk : e ∣ v ^ k) : coprimePart (d * e) v = d := by + have h1 := coprimePart_isGreatest (d * e) v (Nat.mul_pos hd he) + have h2 : IsGreatest {x | x ∣ d * e ∧ Nat.Coprime x v} d := by + refine ⟨⟨dvd_mul_right d e, hc⟩, ?_⟩ + rintro x ⟨hx, hxv⟩ + have hxe : Nat.Coprime x e := Nat.Coprime.coprime_dvd_right hk (Nat.Coprime.pow_right k hxv) + exact Nat.le_of_dvd hd (hxe.dvd_of_dvd_mul_right hx) + exact h1.unique h2 + +/-- `L W + M` is prime to `K` as soon as some `g ∣ L` is prime to `M` and `K ∣ g^k`. -/ +private theorem cop_lin (L M g K k W : ℕ) (hg : g ∣ L) (hM : Nat.Coprime M g) + (hK : K ∣ g ^ k) : Nat.Coprime (L * W + M) K := by + obtain ⟨t, rfl⟩ := hg + have h1 : Nat.Coprime (M + (t * W) * g) g := (Nat.coprime_add_mul_right_left M g (t * W)).2 hM + have h2 : g * t * W + M = M + (t * W) * g := by ring + rw [h2] + exact Nat.Coprime.coprime_dvd_right hK (Nat.Coprime.pow_right k h1) + +/-- One step of the recursion on an explicit pair. -/ +private theorem step_F (P Q R U W : ℕ) : + step (F (P, Q, R, U) W) = + (coprimePart (R * W + U) (P * W + Q), R * W + U + coprimePart (R * W + U) (P * W + Q)) := + rfl + +/-- Soundness of the first shape of step. -/ +private theorem step_small (P Q R U P' Q' R' U' e g k W : ℕ) + (H : GoodSmall (P, Q, R, U) (P', Q', R', U') e g k) : + step (F (P, Q, R, U) W) = F (P', Q', R', U') W := by + obtain ⟨hP, hR, hU, he, hg, hQ', hQg, he0, hQ'0, hR', hU'⟩ := H + dsimp only at hP hR hU he hg hQ' hQg he0 hQ'0 hR' hU' + have hw : R * W + U = (P' * W + Q') * e := by rw [hR, hU]; ring + have hv : P * W + Q = Q := by rw [hP]; ring + have hpos : 0 < P' * W + Q' := Nat.lt_of_lt_of_le hQ'0 (Nat.le_add_left _ _) + have hcp : coprimePart (R * W + U) (P * W + Q) = P' * W + Q' := by + rw [hw, hv] + exact cp_eq _ _ _ k hpos he0 (cop_lin P' Q' g Q k W hg hQ' hQg) he + rw [step_F, hcp, hw] + simp only [F, Prod.mk.injEq] + refine ⟨trivial, ?_⟩ + rw [hR', hU', hR, hU] + ring + +/-- Soundness of the second shape of step. -/ +private theorem step_big (P Q R U P' Q' R' U' c f g h k W : ℕ) + (H : GoodBig (P, Q, R, U) (P', Q', R', U') c f g h k) : + step (F (P, Q, R, U) W) = F (P', Q', R', U') W := by + obtain ⟨hP', hR, hU, hc, hhP, hhQ, hf, hgP, hQg, hQ'g, hQ'0, hQ0, hf0, hR', hU'⟩ := H + dsimp only at hP' hR hU hc hhP hhQ hf hgP hQg hQ'g hQ'0 hQ0 hf0 hR' hU' + have hw : R * W + U = Q' * (f * (P * W + Q)) := by rw [hR, hU, hc]; ring + have hvpos : 0 < P * W + Q := Nat.lt_of_lt_of_le hQ0 (Nat.le_add_left _ _) + have hhv : h ∣ P * W + Q := Dvd.dvd.add (Dvd.dvd.mul_right hhP W) hhQ + have hcp : coprimePart (R * W + U) (P * W + Q) = Q' := by + rw [hw] + refine cp_eq _ _ _ (k + 1) hQ'0 (Nat.mul_pos hf0 hvpos) + (cop_lin P Q g Q' k W hgP hQg hQ'g).symm ?_ + rw [pow_succ] + exact mul_dvd_mul_right (dvd_trans hf (pow_dvd_pow_of_dvd hhv k)) _ + rw [step_F, hcp] + simp only [F, Prod.mk.injEq] + refine ⟨by rw [hP']; ring, ?_⟩ + rw [hR', hU'] + ring + +/-- Soundness of a certified step: it holds for every value `W` of the parameter. -/ +private theorem step_good (r r' : ℕ × ℕ × ℕ × ℕ) (x : ℕ × ℕ × ℕ × ℕ × ℕ) (H : Good r r' x) + (W : ℕ) : step (F r W) = F r' W := by + obtain ⟨P, Q, R, U⟩ := r + obtain ⟨P', Q', R', U'⟩ := r' + obtain ⟨x1, x2, x3, x4, x5⟩ := x + rcases H with H | H + · exact step_small P Q R U P' Q' R' U' x1 x2 x3 W H + · exact step_big P Q R U P' Q' R' U' x1 x2 x3 x4 x5 W H + +/-- All 42 steps of the table are certified (kernel computation). -/ +private theorem good_all : ∀ i, i < 42 → Good (row i) (nextRow i) (cert i) := by + decide +kernel + +/-- Each row steps to the next row, for every value of the parameter. -/ +private theorem step_row (i : ℕ) (hi : i < 42) (W : ℕ) : step (F (row i) W) = F (nextRow i) W := + step_good _ _ _ (good_all i hi) W + +/-- The shifted row at `W` is the row at `3645 W + 1`. -/ +private theorem F_shift (r : ℕ × ℕ × ℕ × ℕ) (W : ℕ) : F (shift r) W = F r (3645 * W + 1) := by + obtain ⟨P, Q, R, U⟩ := r + simp only [F, shift, Prod.mk.injEq] + constructor <;> ring + +private theorem state_succ' (n : ℕ) : state (n + 1) = step (state n) := by + unfold state + rw [Function.iterate_succ_apply'] + +/-- The base of the induction: `(a 139, s 139) = (3, 315591)` (kernel computation). -/ +private theorem state_base : state 138 = F (row 0) (Y 0) := by + decide +kernel + +/-- The block structure: `state (138 + 42 m + i) = F (row i) (Y m)` for `i < 42`. -/ +private theorem key (m : ℕ) : ∀ i, i < 42 → state (138 + 42 * m + i) = F (row i) (Y m) := by + induction m with + | zero => + intro i hi + induction i with + | zero => exact state_base + | succ i ih => + rw [show 138 + 42 * 0 + (i + 1) = (138 + 42 * 0 + i) + 1 by ring, state_succ', + ih (by omega), step_row i (by omega), nextRow, if_neg (by omega)] + | succ m ihm => + intro i hi + induction i with + | zero => + rw [show 138 + 42 * (m + 1) + 0 = (138 + 42 * m + 41) + 1 by ring, state_succ', + ihm 41 (by norm_num), step_row 41 (by norm_num), nextRow, if_pos rfl, F_shift] + rfl + | succ i ih => + rw [show 138 + 42 * (m + 1) + (i + 1) = (138 + 42 * (m + 1) + i) + 1 by ring, state_succ', + ih (by omega), step_row i (by omega), nextRow, if_neg (by omega)] + +/-- `a(139 + 42 m + i) = P_i * Y m + Q_i`. -/ +private theorem a_form (m i : ℕ) (hi : i < 42) : + a (139 + 42 * m + i) = (row i).1 * Y m + (row i).2.1 := by + rw [show 139 + 42 * m + i = (138 + 42 * m + i) + 1 by ring] + show (state _).1 = _ + rw [key m i hi] + rfl + +/-- `s(139 + 42 m + i) = R_i * Y m + U_i`. -/ +private theorem s_form (m i : ℕ) (hi : i < 42) : + s (139 + 42 * m + i) = (row i).2.2.1 * Y m + (row i).2.2.2 := by + rw [show 139 + 42 * m + i = (138 + 42 * m + i) + 1 by ring, ← state_snd, key m i hi] + rfl + +/-- `1` occurs infinitely often: `a(143 + 42 m) = 1`. -/ +private theorem one_inf : {n : ℕ | a n = 1}.Infinite := by + refine Set.infinite_of_injective_forall_mem (f := fun m : ℕ => 139 + 42 * m + 4) ?_ ?_ + · intro x y hxy + simp only at hxy + omega + · intro m + show a (139 + 42 * m + 4) = 1 + rw [a_form m 4 (by norm_num), show row 4 = (0, 1, 1725051870, 473392) from rfl] + simp + +/-- `2` occurs infinitely often: `a(147 + 42 m) = 2`. -/ +private theorem two_inf : {n : ℕ | a n = 2}.Infinite := by + refine Set.infinite_of_injective_forall_mem (f := fun m : ℕ => 139 + 42 * m + 8) ?_ ?_ + · intro x y hxy + simp only at hxy + omega + · intro m + show a (139 + 42 * m + 8) = 2 + rw [a_form m 8 (by norm_num), show row 8 = (0, 2, 6900207480, 1893572) from rfl] + simp + +/-- The rows at odd indices `139 + i` are constant. -/ +private theorem row_even_const : ∀ i, i < 42 → i % 2 = 0 → (row i).1 = 0 := by + decide + +/-- Sigrist's first conjecture. -/ +private theorem odd_part : sigristOdd := by + unfold sigristOdd + intro n hn + obtain ⟨m, i, hi, hk⟩ : ∃ m i, i < 42 ∧ 2 * n - 1 = 139 + 42 * m + i := + ⟨(2 * n - 1 - 139) / 42, (2 * n - 1 - 139) % 42, Nat.mod_lt _ (by norm_num), by omega⟩ + have hk' : 2 * (n + 21) - 1 = 139 + 42 * (m + 1) + i := by omega + have hev : i % 2 = 0 := by omega + rw [hk, hk', a_form _ _ hi, a_form _ _ hi, row_even_const i hi hev] + simp + +/-- `a(n + 42) - 3645 a(n)` for `n = 139 + 42 m + i`. -/ +private def dA (j : ℕ) : ℤ := ((row j).1 : ℤ) + (row j).2.1 - 3645 * (row j).2.1 + +/-- Sigrist's second conjecture. -/ +private theorem even_part : sigristEven := by + unfold sigristEven + refine ⟨fun n => dA ((2 * (n % 21) + 29) % 42), ?_, ?_⟩ + · intro n + simp only [Nat.add_mod_right] + · intro n hn + obtain ⟨m, i, hi, hk⟩ : ∃ m i, i < 42 ∧ 2 * n = 139 + 42 * m + i := + ⟨(2 * n - 139) / 42, (2 * n - 139) % 42, Nat.mod_lt _ (by norm_num), by omega⟩ + have hk' : 2 * (n + 21) = 139 + 42 * (m + 1) + i := by omega + have hj : (2 * (n % 21) + 29) % 42 = i := by omega + simp only + rw [hj, hk', hk, a_form _ _ hi, a_form _ _ hi] + simp only [Y, dA] + push_cast + ring + +/-- `s(n + 42) - 3645 s(n)` for `n = 139 + 42 m + i`. -/ +private def dS (j : ℕ) : ℤ := ((row j).2.2.1 : ℤ) + (row j).2.2.2 - 3645 * (row j).2.2.2 + +/-- The A355149 conjecture. -/ +private theorem sums_part : partialSums := by + unfold partialSums + refine ⟨fun n => dS ((n + 29) % 42), ?_, ?_⟩ + · intro n + simp only [show n + 42 + 29 = (n + 29) + 42 by ring, Nat.add_mod_right] + · intro n hn + rcases Nat.eq_or_lt_of_le hn with h | h + · subst h + have h1 : s 180 = 1150350168 := by + rw [show 180 = 139 + 42 * 0 + 41 by rfl, s_form 0 41 (by norm_num)] + rfl + have h2 : s 139 = 315591 := by + rw [show 139 = 139 + 42 * 0 + 0 by rfl, s_form 0 0 (by norm_num)] + rfl + have h3 : a 139 = 3 := by + rw [show 139 = 139 + 42 * 0 + 0 by rfl, a_form 0 0 (by norm_num)] + rfl + have h4 : s 138 = 315588 := by + have := s_succ 138 + rw [show (138 + 1 : ℕ) = 139 from rfl, h2, h3] at this + omega + simp only + rw [show 138 + 42 = 180 by rfl, h1, h4] + decide + · obtain ⟨m, i, hi, hk⟩ : ∃ m i, i < 42 ∧ n = 139 + 42 * m + i := + ⟨(n - 139) / 42, (n - 139) % 42, Nat.mod_lt _ (by norm_num), by omega⟩ + have hj : (n + 29) % 42 = i := by omega + simp only + rw [hj] + subst hk + rw [show 139 + 42 * m + i + 42 = 139 + 42 * (m + 1) + i by ring, s_form _ _ hi, + s_form _ _ hi] + simp only [Y, dS] + push_cast + ring + +/-- All four conjectures on A351743 and A355149 hold. -/ +theorem result : statement := + And.intro (And.intro one_inf two_inf) (And.intro odd_part (And.intro even_part sums_part)) + +end Math0.Frontier.A351743 + +#math0_settles Math0.Frontier.A351743.result Math0.Statements.A351743.statement diff --git a/lean/Math0/Frontier/OEIS/A354571.lean b/lean/Math0/Frontier/OEIS/A354571.lean new file mode 100644 index 0000000..217d61f --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A354571.lean @@ -0,0 +1,2285 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A354571 +import Math0.Audit + +/-! +# Even and odd legs with odd prime factors `≡ 3 (mod 4)`: `a(n)/n → π` (A354571, A354570) + +We prove Selle's conjecture (A354571, A354570): `a(n)/n → π` for the ordered even legs and for +the ordered odd legs (with multiplicity) of the primitive Pythagorean triangles whose odd prime +factors are all `≡ 3 (mod 4)`. + +* **Counting.** Let `g(m) = 2^ω(m)` if `m` is odd with all prime factors `≡ 3 (mod 4)`, else + `g(m) = 0`. Primitive triangles `(b, k, c)` with odd leg `k` correspond to coprime + factorizations `k² = d e`, `d < e` (via `(b, c) ↦ (c - b, c + b)`); those with leg `2n`, `n` + even, to coprime factorizations `n² = d e`, `d < e` (via `(b, c) ↦ ((c - b)/2, (c + b)/2)`); + legs `≡ 2 (mod 4)` do not occur. Counting coprime factorizations (`2^ω(N)` ordered ones) gives + `2 wO(k) + [k = 1] = g(k)`, `wE(4j) + [j = 1] = g(j)` for odd `j`, `wE(8i) = wE(4i)`, and + `wE(k) = 0` unless `4 ∣ k`. +* **Dirichlet series.** `g` is multiplicative and `g * χ₄ = 1_odd` (checked on prime powers), so + `L(g, s) L(s, χ₄) = L(s, χ₀)` for the trivial character `χ₀` mod `4`. Summing the identity and + using that the partial sums of `χ₄` are `0` or `1` gives `∑_{N/2 < n ≤ N} g(n) ≤ N`, hence + `∑_{n ≤ N} g(n) ≤ 2N`. Since `L(s, χ₄) ≠ 0` on `re s ≥ 1` (Mathlib) and `(s - 1) L(s, χ₀)` is + entire with value `1/2` at `1`, the function `L(g, s)/s - c/(s - 1)` with + `c = (1/2)/L(1, χ₄)` extends continuously to `re s ≥ 1` (a `dslope`). Pairing the terms of + `L(σ, χ₄)` and using Leibniz' series with dominated convergence as `σ → 1⁺` gives + `L(1, χ₄) = π/4`, so `c = 2/π`. +* **Tauberian theorem.** A Wiener–Ikehara theorem for nonnegative coefficients with linearly + bounded partial sums, proved with the Fejér kernel. With `B(v) = e^{-v} ∑_{n ≤ e^v} g(n)`, the + triangle `φ_L` and its Fourier transform `Φ_L(u) = 2 (1 - cos (L u))/(L u²) ≥ 0`, Fubini and + `ε → 0⁺` give `∫ φ_L(t) G(1 + it) e^{iyt} dt = ∫_{v > 0} (B(v) - c) Φ_L(y - v) dv`, which tends + to `0` as `y → ∞` by the Riemann–Lebesgue lemma. Monotonicity of the partial sums and the + concentration of `Φ_L` as `L → ∞` then squeeze `B(y) → c`, i.e. `∑_{n ≤ N} g(n) ~ (2/π) N`. +* **Conclusion.** `numLE wO N = (S(N) - 1)/2 ~ N/π` with `S(N) = ∑_{n ≤ N} g(n)`, and + `numLE wE N = E(⌊N/4⌋)` where `E(J) = ∑_i R(⌊J/2^i⌋) ~ (4/π) J` (dominated convergence, + `R(M) = S(M) - [M ≥ 1]`), so also `numLE wE N ~ N/π`. Inverting the counting functions gives + `a(n)/n → π` for both sequences. +-/ + +namespace Math0.Frontier.A354571 + +namespace Tauber + +open MeasureTheory Filter Topology Complex Set + +noncomputable section + +/-- The triangle function `phi L t = max 0 (1 - |t| / L)`, supported on `[-L, L]`. -/ +private def phi (L t : ℝ) : ℝ := max 0 (1 - |t| / L) + +/-- The Fourier transform `Φ_L(u) = 2 (1 - cos (L u)) / (L u²)` of `phi L` (the Fejér kernel), with value `L` at `u = 0`. -/ +private def Phi (L u : ℝ) : ℝ := if u = 0 then L else 2 * (1 - Real.cos (L * u)) / (L * u ^ 2) + +/-- `phi L` is nonnegative. -/ +private theorem phi_nonneg (L t : ℝ) : 0 ≤ phi L t := le_max_left _ _ + +/-- `phi L t = 0` for `|t| ≥ L`. -/ +private theorem phi_eq_zero {L t : ℝ} (hL : 0 < L) (ht : L ≤ |t|) : phi L t = 0 := by + unfold phi; apply max_eq_left; rw [sub_nonpos, le_div_iff₀ hL]; linarith + +/-- `phi L` is at most `1`. -/ +private theorem phi_le_one {L : ℝ} (hL : 0 < L) (t : ℝ) : phi L t ≤ 1 := by + unfold phi; apply max_le zero_le_one + have : 0 ≤ |t| / L := div_nonneg (abs_nonneg t) hL.le + linarith + +/-- `phi L` is continuous. -/ +private theorem continuous_phi (L : ℝ) : Continuous (phi L) := by unfold phi; fun_prop + +/-- `phi L` has compact support (contained in `[-L, L]`). -/ +private theorem hasCompactSupport_phi {L : ℝ} (hL : 0 < L) : HasCompactSupport (phi L) := by + apply HasCompactSupport.intro (isCompact_Icc (a := -L) (b := L)) + intro t ht + apply phi_eq_zero hL + rw [mem_Icc, not_and_or, not_le, not_le] at ht + rcases ht with h | h + · rw [abs_of_neg (by linarith)]; linarith + · rw [abs_of_pos (by linarith)]; linarith + +/-- `phi L` is integrable. -/ +private theorem integrable_phi {L : ℝ} (hL : 0 < L) : Integrable (phi L) := + (continuous_phi L).integrable_of_hasCompactSupport (hasCompactSupport_phi hL) + +/-- On `[0, L]`, `phi L t = 1 - t / L`. -/ +private theorem phi_of_nonneg {L t : ℝ} (hL : 0 < L) (h0 : 0 ≤ t) (h1 : t ≤ L) : phi L t = 1 - t / L := by + unfold phi; rw [abs_of_nonneg h0]; apply max_eq_right + rw [sub_nonneg, div_le_one hL]; exact h1 + +/-- On `[-L, 0]`, `phi L t = 1 + t / L`. -/ +private theorem phi_of_nonpos {L t : ℝ} (hL : 0 < L) (h0 : t ≤ 0) (h1 : -L ≤ t) : phi L t = 1 + t / L := by + unfold phi; rw [abs_of_nonpos h0, neg_div, sub_neg_eq_add]; rw [max_eq_right] + have : -1 ≤ t / L := by rw [le_div_iff₀ hL]; linarith + linarith + +/-- Derivative of `t ↦ (p + q t) e^{w t}`. -/ +private theorem hasDerivAt_aux (p q w : ℂ) (t : ℝ) : + HasDerivAt (fun t : ℝ => (p + q * (t : ℂ)) * cexp (w * t)) + ((q + w * (p + q * t)) * cexp (w * t)) t := by + have h1 : HasDerivAt (fun t : ℝ => (t : ℂ)) 1 t := hasDerivAt_id t |>.ofReal_comp + have h2 : HasDerivAt (fun t : ℝ => p + q * (t : ℂ)) q t := by + simpa using (h1.const_mul q).const_add p + have h3 : HasDerivAt (fun t : ℝ => cexp (w * t)) (cexp (w * t) * w) t := by + have := (h1.const_mul w).cexp + simpa using this + exact (h2.mul h3).congr_deriv (by ring) + +/-- `∫₀^L phi L t e^{iut} dt` for `u ≠ 0`. -/ +private theorem integral_right_half {L : ℝ} (hL : 0 < L) {u : ℝ} (hu : u ≠ 0) : + ∫ t in (0:ℝ)..L, (phi L t : ℂ) * cexp (I * u * t) = + (1 - cexp (I * u * L)) / (L * u ^ 2) + I / u := by + have hL' : (L : ℂ) ≠ 0 := by exact_mod_cast hL.ne' + have hu' : (u : ℂ) ≠ 0 := by exact_mod_cast hu + set p : ℂ := -I / u - 1 / (u ^ 2 * L) + set q : ℂ := I / (u * L) + have hcongr : ∀ t ∈ Set.uIcc (0:ℝ) L, (phi L t : ℂ) * cexp (I * u * t) = + (q + (I * u) * (p + q * t)) * cexp ((I * u) * t) := by + intro t ht + rw [Set.uIcc_of_le hL.le] at ht + rw [phi_of_nonneg hL ht.1 ht.2] + congr 1 + simp only [p, q] + push_cast + field_simp + ring_nf + rw [I_sq] + ring + rw [intervalIntegral.integral_congr hcongr] + rw [intervalIntegral.integral_eq_sub_of_hasDerivAt (fun t _ => hasDerivAt_aux p q (I * u) t)] + · simp only [p, q] + push_cast + simp only [mul_zero, Complex.exp_zero, add_zero, mul_one] + field_simp + ring + · exact (Continuous.intervalIntegrable (by fun_prop) _ _) + +/-- `∫_{-L}^0 phi L t e^{iut} dt` for `u ≠ 0`. -/ +private theorem integral_left_half {L : ℝ} (hL : 0 < L) {u : ℝ} (hu : u ≠ 0) : + ∫ t in (-L)..0, (phi L t : ℂ) * cexp (I * u * t) = + (1 - cexp (-(I * u * L))) / (L * u ^ 2) - I / u := by + have hL' : (L : ℂ) ≠ 0 := by exact_mod_cast hL.ne' + have hu' : (u : ℂ) ≠ 0 := by exact_mod_cast hu + set p : ℂ := -I / u + 1 / (u ^ 2 * L) + set q : ℂ := -I / (u * L) + have hcongr : ∀ t ∈ Set.uIcc (-L) 0, (phi L t : ℂ) * cexp (I * u * t) = + (q + (I * u) * (p + q * t)) * cexp ((I * u) * t) := by + intro t ht + rw [Set.uIcc_of_le (by linarith)] at ht + rw [phi_of_nonpos hL ht.2 ht.1] + congr 1 + simp only [p, q] + push_cast + field_simp + ring_nf + rw [I_sq] + ring + rw [intervalIntegral.integral_congr hcongr] + rw [intervalIntegral.integral_eq_sub_of_hasDerivAt (fun t _ => hasDerivAt_aux p q (I * u) t)] + · simp only [p, q] + push_cast + simp only [mul_zero, Complex.exp_zero, add_zero, mul_one] + field_simp + ring_nf + · exact (Continuous.intervalIntegrable (by fun_prop) _ _) + +/-- `∫₀^L phi L = L / 2`. -/ +private theorem integral_right_half_zero {L : ℝ} (hL : 0 < L) : + ∫ t in (0:ℝ)..L, (phi L t : ℂ) = L / 2 := by + have hL' : (L : ℂ) ≠ 0 := by exact_mod_cast hL.ne' + have hcongr : ∀ t ∈ Set.uIcc (0:ℝ) L, (phi L t : ℂ) = 1 - (t : ℂ) / L := by + intro t ht + rw [Set.uIcc_of_le hL.le] at ht + rw [phi_of_nonneg hL ht.1 ht.2]; push_cast; ring + rw [intervalIntegral.integral_congr hcongr, intervalIntegral.integral_sub, intervalIntegral.integral_div, + intervalIntegral.integral_ofReal (f := fun x => x), integral_id] + · simp; field_simp; ring + · exact intervalIntegrable_const + · exact (Continuous.intervalIntegrable (by fun_prop) _ _) + +/-- `∫_{-L}^0 phi L = L / 2`. -/ +private theorem integral_left_half_zero {L : ℝ} (hL : 0 < L) : + ∫ t in (-L)..0, (phi L t : ℂ) = L / 2 := by + have hL' : (L : ℂ) ≠ 0 := by exact_mod_cast hL.ne' + have hcongr : ∀ t ∈ Set.uIcc (-L) 0, (phi L t : ℂ) = 1 + (t : ℂ) / L := by + intro t ht + rw [Set.uIcc_of_le (by linarith)] at ht + rw [phi_of_nonpos hL ht.2 ht.1]; push_cast; ring + rw [intervalIntegral.integral_congr hcongr, intervalIntegral.integral_add, intervalIntegral.integral_div, + intervalIntegral.integral_ofReal (f := fun x => x), integral_id] + · simp; field_simp; ring + · exact intervalIntegrable_const + · exact (Continuous.intervalIntegrable (by fun_prop) _ _) + +/-- The Fourier transform of the triangle: `∫ phi L t e^{iut} dt = Φ_L(u)`. -/ +private theorem fourier_phi {L : ℝ} (hL : 0 < L) (u : ℝ) : + ∫ t, (phi L t : ℂ) * cexp (I * u * t) = (Phi L u : ℂ) := by + have hzero : ∀ t ∉ Ioc (-L) L, (phi L t : ℂ) * cexp (I * u * t) = 0 := by + intro t ht + rw [mem_Ioc, not_and_or, not_lt, not_le] at ht + rw [phi_eq_zero hL] + · simp + rcases ht with h | h + · rw [abs_of_nonpos (by linarith)]; linarith + · rw [abs_of_pos (by linarith)]; linarith + rw [← setIntegral_eq_integral_of_forall_compl_eq_zero hzero, + ← intervalIntegral.integral_of_le (by linarith), + ← intervalIntegral.integral_add_adjacent_intervals (b := 0) + (Continuous.intervalIntegrable (by have := continuous_phi L; fun_prop) _ _) + (Continuous.intervalIntegrable (by have := continuous_phi L; fun_prop) _ _)] + have hL' : (L : ℂ) ≠ 0 := by exact_mod_cast hL.ne' + by_cases hu : u = 0 + · subst hu + simp only [ofReal_zero, mul_zero, zero_mul, Complex.exp_zero, mul_one] + rw [integral_left_half_zero hL, integral_right_half_zero hL, Phi, if_pos rfl] + ring + · rw [integral_left_half hL hu, integral_right_half hL hu, Phi, if_neg hu] + have hu' : (u : ℂ) ≠ 0 := by exact_mod_cast hu + push_cast + rw [Complex.cos, show (L : ℂ) * u * I = I * u * L by ring, + show -((L : ℂ) * u) * I = -(I * u * L) by ring] + field_simp + ring + +/-- The Fejér kernel is nonnegative. -/ +private theorem Phi_nonneg {L : ℝ} (hL : 0 < L) (u : ℝ) : 0 ≤ Phi L u := by + unfold Phi; split_ifs with hu + · exact hL.le + · have := Real.cos_le_one (L * u) + have : 0 < L * u ^ 2 := by positivity + positivity + +/-- Tail bound `Φ_L(u) ≤ 4 / (L u²)`. -/ +private theorem Phi_le_tail {L : ℝ} (hL : 0 < L) {u : ℝ} (hu : u ≠ 0) : Phi L u ≤ 4 / (L * u ^ 2) := by + unfold Phi; rw [if_neg hu] + have := Real.neg_one_le_cos (L * u) + have : 0 < L * u ^ 2 := by positivity + apply div_le_div_of_nonneg_right _ this.le + linarith + +/-- `Φ_L(u) ≤ L`. -/ +private theorem Phi_le_L {L : ℝ} (hL : 0 < L) (u : ℝ) : Phi L u ≤ L := by + unfold Phi; split_ifs with hu + · exact le_rfl + · have h := Real.one_sub_sq_div_two_le_cos (x := L * u) + have : 0 < L * u ^ 2 := by positivity + rw [div_le_iff₀ this] + nlinarith + +/-- `Φ_L(u) ≥ L / 2` for `|u| ≤ 1 / L`. -/ +private theorem Phi_ge {L : ℝ} (hL : 0 < L) {u : ℝ} (hu : |u| ≤ 1 / L) : L / 2 ≤ Phi L u := by + unfold Phi; split_ifs with h0 + · linarith + · have hx : |L * u| ≤ 1 := by + rw [abs_mul, abs_of_pos hL]; rw [le_div_iff₀ hL] at hu; linarith + have hb := Real.cos_bound hx + have h1 : Real.cos (L * u) ≤ 1 - (L * u) ^ 2 / 2 + |L * u| ^ 4 * (5 / 96) := by + have := (abs_le.mp hb).2; linarith + have h2 : |L * u| ^ 4 ≤ (L * u) ^ 2 := by + rw [show |L * u| ^ 4 = (L * u) ^ 2 * |L * u| ^ 2 by rw [← sq_abs (L * u)]; ring] + have : |L * u| ^ 2 ≤ 1 := by nlinarith [abs_nonneg (L * u)] + have : 0 ≤ (L * u) ^ 2 := sq_nonneg _ + nlinarith + have hpos : 0 < L * u ^ 2 := by positivity + rw [le_div_iff₀ hpos] + nlinarith + +/-- The Fejér kernel is measurable. -/ +private theorem measurable_Phi (L : ℝ) : Measurable (Phi L) := by + unfold Phi + refine Measurable.ite (measurableSet_singleton 0) measurable_const ?_ + fun_prop + +/-- `Φ_L(u) ≤ (2 L + 8 / L) / (1 + u²)`. -/ +private theorem Phi_le_bound {L : ℝ} (hL : 0 < L) (u : ℝ) : Phi L u ≤ (2 * L + 8 / L) * (1 + u ^ 2)⁻¹ := by + have h1 : 0 < 1 + u ^ 2 := by positivity + rw [← div_eq_mul_inv, le_div_iff₀ h1] + rcases le_or_gt (|u|) 1 with hu | hu + · have := Phi_le_L hL u + have := Phi_nonneg hL u + have : u ^ 2 ≤ 1 := by nlinarith [abs_nonneg u, sq_abs u] + have : 0 < 8 / L := by positivity + nlinarith + · have hu0 : u ≠ 0 := by intro h; rw [h] at hu; norm_num at hu + have h2 := Phi_le_tail hL hu0 + have hu2 : 1 < u ^ 2 := by nlinarith [abs_nonneg u, sq_abs u] + have : 4 / (L * u ^ 2) * (1 + u ^ 2) ≤ 8 / L := by + rw [div_mul_eq_mul_div, div_le_div_iff₀ (by positivity) hL] + nlinarith + have := Phi_nonneg hL u + nlinarith + +/-- The Fejér kernel is integrable. -/ +private theorem integrable_Phi {L : ℝ} (hL : 0 < L) : Integrable (Phi L) := by + refine Integrable.mono' (integrable_inv_one_add_sq.const_mul (2 * L + 8 / L)) + (measurable_Phi L).aestronglyMeasurable (Eventually.of_forall fun u => ?_) + rw [Real.norm_eq_abs, abs_of_nonneg (Phi_nonneg hL u)] + exact Phi_le_bound hL u + +/-- `∫ du / (δ² + u²) = π / δ`. -/ +private theorem integral_inv_sq_add_sq {δ : ℝ} (hδ : 0 < δ) : ∫ u : ℝ, (δ ^ 2 + u ^ 2)⁻¹ = Real.pi / δ := by + have h1 : ∀ u : ℝ, (δ ^ 2 + u ^ 2)⁻¹ = δ⁻¹ ^ 2 * (1 + (u / δ) ^ 2)⁻¹ := by + intro u; field_simp + simp_rw [h1] + rw [integral_const_mul, Measure.integral_comp_div (fun w => (1 + w ^ 2)⁻¹) δ, + integral_univ_inv_one_add_sq, abs_of_pos hδ, smul_eq_mul] + field_simp + +/-- `u ↦ 1 / (δ² + u²)` is integrable. -/ +private theorem integrable_inv_sq_add_sq {δ : ℝ} (hδ : 0 < δ) : Integrable (fun u : ℝ => (δ ^ 2 + u ^ 2)⁻¹) := by + have h1 : (fun u : ℝ => (δ ^ 2 + u ^ 2)⁻¹) = fun u => δ⁻¹ ^ 2 * (1 + (u / δ) ^ 2)⁻¹ := by + ext u; field_simp + rw [h1] + refine Integrable.const_mul ?_ _ + exact (integrable_inv_one_add_sq).comp_div hδ.ne' + +/-- tail of the kernel -/ +private theorem tail_le {L δ : ℝ} (hL : 0 < L) (hδ : 0 < δ) : + ∫ u, Set.indicator {u | δ < |u|} (Phi L) u ≤ 8 * Real.pi / (L * δ) := by + have hb : ∀ u, Set.indicator {u | δ < |u|} (Phi L) u ≤ (8 / L) * (δ ^ 2 + u ^ 2)⁻¹ := by + intro u + by_cases hu : δ < |u| + · rw [Set.indicator_of_mem (by exact hu)] + have hu0 : u ≠ 0 := by intro h; rw [h] at hu; simp at hu; linarith + refine (Phi_le_tail hL hu0).trans ?_ + have hu2 : δ ^ 2 < u ^ 2 := by + rw [← sq_abs u]; exact pow_lt_pow_left₀ hu hδ.le (by norm_num) + have hu2' : 0 < u ^ 2 := by positivity + rw [← div_eq_mul_inv, div_le_div_iff₀ (by positivity) (by positivity)] + have : 8 / L * (L * u ^ 2) = 8 * u ^ 2 := by field_simp + rw [this]; linarith + · rw [Set.indicator_of_notMem (by exact hu)] + positivity + calc ∫ u, Set.indicator {u | δ < |u|} (Phi L) u + ≤ ∫ u, (8 / L) * (δ ^ 2 + u ^ 2)⁻¹ := by + apply integral_mono_of_nonneg + · exact Eventually.of_forall fun u => Set.indicator_nonneg (fun u _ => Phi_nonneg hL u) u + · exact (integrable_inv_sq_add_sq hδ).const_mul _ + · exact Eventually.of_forall hb + _ = 8 * Real.pi / (L * δ) := by + rw [integral_const_mul, integral_inv_sq_add_sq hδ]; field_simp + +/-- The total mass of the Fejér kernel is at least `1`. -/ +private theorem one_le_integral_Phi {L : ℝ} (hL : 0 < L) : 1 ≤ ∫ u, Phi L u := by + have hb : ∀ u, Set.indicator (Icc (-(1 / L)) (1 / L)) (fun _ => L / 2) u ≤ Phi L u := by + intro u + by_cases hu : u ∈ Icc (-(1 / L)) (1 / L) + · rw [Set.indicator_of_mem hu]; exact Phi_ge hL (abs_le.mpr hu) + · rw [Set.indicator_of_notMem hu]; exact Phi_nonneg hL u + calc (1 : ℝ) = ∫ u, Set.indicator (Icc (-(1 / L)) (1 / L)) (fun _ => L / 2) u := by + rw [integral_indicator_const _ measurableSet_Icc, Real.volume_real_Icc] + rw [smul_eq_mul, max_eq_left (by have : 0 < 1 / L := by positivity + linarith)] + field_simp; ring + _ ≤ ∫ u, Phi L u := by + apply integral_mono_of_nonneg + · exact Eventually.of_forall fun u => Set.indicator_nonneg (fun u _ => by positivity) u + · exact integrable_Phi hL + · exact Eventually.of_forall hb + +section Tauberian + +variable (a : ℕ → ℝ) + +/-- partial sums -/ +private def Asum (x : ℝ) : ℝ := ∑ n ∈ Finset.Icc 1 ⌊x⌋₊, a n + +/-- normalized partial sums in logarithmic variable -/ +private def Bf (v : ℝ) : ℝ := Asum a (Real.exp v) * Real.exp (-v) + +variable {a} + +/-- The partial sums of a nonnegative sequence are monotone. -/ +private theorem Asum_mono (ha : ∀ n, 0 ≤ a n) : Monotone (Asum a) := by + intro x y hxy + unfold Asum + apply Finset.sum_le_sum_of_subset_of_nonneg + · exact Finset.Icc_subset_Icc le_rfl (Nat.floor_le_floor hxy) + · intro i _ _; exact ha i + +/-- The partial sums of a nonnegative sequence are nonnegative. -/ +private theorem Asum_nonneg (ha : ∀ n, 0 ≤ a n) (x : ℝ) : 0 ≤ Asum a x := + Finset.sum_nonneg fun i _ => ha i + +/-- Linear bound on the partial sums. -/ +private theorem Asum_le {M : ℝ} (hM0 : 0 ≤ M) (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) + {x : ℝ} (hx : 0 ≤ x) : Asum a x ≤ M * x := + (hM _).trans (mul_le_mul_of_nonneg_left (Nat.floor_le hx) hM0) + +/-- `B` is nonnegative. -/ +private theorem Bf_nonneg (ha : ∀ n, 0 ≤ a n) (v : ℝ) : 0 ≤ Bf a v := + mul_nonneg (Asum_nonneg ha _) (Real.exp_pos _).le + +/-- `B` is bounded by `M`. -/ +private theorem Bf_le {M : ℝ} (hM0 : 0 ≤ M) (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) + (v : ℝ) : Bf a v ≤ M := by + unfold Bf + calc Asum a (Real.exp v) * Real.exp (-v) ≤ (M * Real.exp v) * Real.exp (-v) := + mul_le_mul_of_nonneg_right (Asum_le hM0 hM (Real.exp_pos v).le) (Real.exp_pos _).le + _ = M := by rw [mul_assoc, ← Real.exp_add, add_neg_cancel, Real.exp_zero, mul_one] + +/-- Monotonicity of `A` gives `B(v) ≥ B(y) e^{-2δ}` for `v ∈ [y, y + 2δ]`. -/ +private theorem Bf_ge_of_ge (ha : ∀ n, 0 ≤ a n) {y v δ : ℝ} (h1 : y ≤ v) (h2 : v ≤ y + 2 * δ) : + Bf a y * Real.exp (-(2 * δ)) ≤ Bf a v := by + unfold Bf + rw [mul_assoc, ← Real.exp_add] + have hA : Asum a (Real.exp y) ≤ Asum a (Real.exp v) := + Asum_mono ha (Real.exp_le_exp.mpr h1) + have hE : Real.exp (-y + -(2 * δ)) ≤ Real.exp (-v) := Real.exp_le_exp.mpr (by linarith) + exact mul_le_mul hA hE (Real.exp_pos _).le (Asum_nonneg ha _) + +/-- Monotonicity of `A` gives `B(v) ≤ B(y) e^{2δ}` for `v ∈ [y - 2δ, y]`. -/ +private theorem Bf_le_of_le (ha : ∀ n, 0 ≤ a n) {y v δ : ℝ} (h1 : y - 2 * δ ≤ v) (h2 : v ≤ y) : + Bf a v ≤ Bf a y * Real.exp (2 * δ) := by + unfold Bf + rw [mul_assoc, ← Real.exp_add] + have hA : Asum a (Real.exp v) ≤ Asum a (Real.exp y) := + Asum_mono ha (Real.exp_le_exp.mpr h2) + have hE : Real.exp (-v) ≤ Real.exp (-y + 2 * δ) := Real.exp_le_exp.mpr (by linarith) + exact mul_le_mul hA hE (Real.exp_pos _).le (Asum_nonneg ha _) + +/-- The partial sum function is measurable. -/ +private theorem measurable_Asum : Measurable (Asum a) := by + unfold Asum + exact (measurable_from_nat (f := fun N => ∑ n ∈ Finset.Icc 1 N, a n)).comp Nat.measurable_floor + +/-- `B` is measurable. -/ +private theorem measurable_Bf : Measurable (Bf a) := by + unfold Bf + exact (measurable_Asum.comp Real.measurable_exp).mul (by fun_prop) + +/-- `v ↦ B(v) e^{-wv}` is integrable on `(0, ∞)` for `re w > 0`. -/ +private theorem integrableOn_Bf_exp {M : ℝ} (hM0 : 0 ≤ M) (ha : ∀ n, 0 ≤ a n) + (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) {w : ℂ} (hw : 0 < w.re) : + IntegrableOn (fun v : ℝ => (Bf a v : ℂ) * cexp (-w * v)) (Ioi 0) := by + refine Integrable.mono' ((exp_neg_integrableOn_Ioi 0 hw).const_mul M) ?_ ?_ + · exact ((measurable_Bf.complex_ofReal).mul (by fun_prop)).aestronglyMeasurable + · refine Eventually.of_forall fun v => ?_ + rw [norm_mul, Complex.norm_exp, Complex.norm_real, Real.norm_eq_abs, + abs_of_nonneg (Bf_nonneg ha v)] + have : (-w * (v : ℂ)).re = -w.re * v := by simp + rw [this] + exact mul_le_mul_of_nonneg_right (Bf_le hM0 hM v) (Real.exp_pos _).le + +/-- Laplace transform representation -/ +private theorem laplace_repr {M : ℝ} (hM0 : 0 ≤ M) (ha : ∀ n, 0 ≤ a n) + (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) (c : ℝ) {s : ℂ} (hs : 1 < s.re) : + LSeries (fun n => (a n : ℂ)) s / s - c / (s - 1) = + ∫ v in Ioi 0, ((Bf a v : ℂ) - c) * cexp (-(s - 1) * v) := by + have hs0 : s ≠ 0 := by intro h; rw [h] at hs; simp at hs; linarith + have hs1 : s - 1 ≠ 0 := by intro h; rw [sub_eq_zero] at h; rw [h] at hs; simp at hs + have hw : 0 < (s - 1).re := by simp; linarith + have hO : (fun n ↦ ∑ k ∈ Finset.Icc 1 n, a k) =O[atTop] fun n ↦ (n : ℝ) ^ (1 : ℝ) := by + refine Asymptotics.IsBigO.of_bound M (Eventually.of_forall fun n => ?_) + rw [Real.rpow_one, Real.norm_eq_abs, Real.norm_eq_abs, abs_of_nonneg (Finset.sum_nonneg fun i _ => ha i), + abs_of_nonneg (Nat.cast_nonneg n)] + exact hM n + have h1 := LSeries_eq_mul_integral_of_nonneg a zero_le_one (by simpa using hs) hO ha + rw [h1, mul_div_cancel_left₀ _ hs0] + have hcv := integral_comp_exp_Ioi (fun t : ℝ => (∑ k ∈ Finset.Icc 1 ⌊t⌋₊, (a k : ℂ)) * + (t : ℂ) ^ (-(s + 1))) 0 + rw [Real.exp_zero] at hcv + rw [← hcv] + have h2 : ∀ v : ℝ, Real.exp v • ((∑ k ∈ Finset.Icc 1 ⌊Real.exp v⌋₊, (a k : ℂ)) * + ((Real.exp v : ℝ) : ℂ) ^ (-(s + 1))) = (Bf a v : ℂ) * cexp (-(s - 1) * v) := by + intro v + rw [Complex.real_smul, cpow_def_of_ne_zero (by exact_mod_cast (Real.exp_pos v).ne'), + ← Complex.ofReal_log (Real.exp_pos v).le, Real.log_exp] + unfold Bf Asum + push_cast + have he : cexp ↑v * cexp (↑v * -(s + 1)) = cexp (-↑v) * cexp (-(s - 1) * ↑v) := by + rw [← Complex.exp_add, ← Complex.exp_add]; ring_nf + linear_combination (∑ k ∈ Finset.Icc 1 ⌊Real.exp v⌋₊, (a k : ℂ)) * he + simp_rw [h2] + have h3 : (c : ℂ) / (s - 1) = ∫ v in Ioi (0:ℝ), (c : ℂ) * cexp (-(s - 1) * v) := by + rw [integral_const_mul, integral_exp_mul_complex_Ioi (by simpa using hw) 0] + simp only [ofReal_zero, mul_zero, Complex.exp_zero] + field_simp + rw [h3, ← integral_sub (integrableOn_Bf_exp hM0 ha hM hw) + ((integrableOn_exp_mul_complex_Ioi (by simpa using hw) 0).const_mul _)] + congr 1; ext v; ring + +/-- For `ε > 0`: `∫ phi(t) G(1 + ε + it) e^{iyt} dt = ∫_{v > 0} (B(v) - c) e^{-εv} Φ(y - v) dv` (Fubini). -/ +private theorem fubini_identity {M : ℝ} (hM0 : 0 ≤ M) (ha : ∀ n, 0 ≤ a n) + (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) (c : ℝ) (G : ℂ → ℂ) + (hG : ∀ s : ℂ, 1 < s.re → LSeries (fun n => (a n : ℂ)) s / s - c / (s - 1) = G s) + {L : ℝ} (hL : 0 < L) (y : ℝ) {ε : ℝ} (hε : 0 < ε) : + ∫ t, (phi L t : ℂ) * G (1 + ε + t * I) * cexp (I * y * t) = + ∫ v in Ioi 0, ((Bf a v : ℂ) - c) * cexp (-ε * v) * (Phi L (y - v) : ℂ) := by + set F : ℝ → ℝ → ℂ := fun t v => (phi L t : ℂ) * (((Bf a v : ℂ) - c) * + cexp (-(ε + t * I) * v)) * cexp (I * y * t) with hF + have hL1 : ∀ t : ℝ, (phi L t : ℂ) * G (1 + ε + t * I) * cexp (I * y * t) = + ∫ v in Ioi 0, F t v := by + intro t + have hs : 1 < (1 + ε + t * I : ℂ).re := by simp; linarith + rw [← hG _ hs, laplace_repr hM0 ha hM c hs, hF] + simp only + rw [← integral_const_mul, ← integral_mul_const] + congr 1; ext v; ring_nf + have hR1 : ∀ v : ℝ, ∫ t, F t v = ((Bf a v : ℂ) - c) * cexp (-ε * v) * (Phi L (y - v) : ℂ) := by + intro v + rw [← fourier_phi hL (y - v), ← integral_const_mul] + congr 1; ext t + rw [hF]; simp only + have : cexp (-(ε + t * I) * v) * cexp (I * y * t) = cexp (-ε * v) * cexp (I * ↑(y - v) * t) := by + rw [← Complex.exp_add, ← Complex.exp_add]; push_cast; ring_nf + linear_combination ((phi L t : ℂ) * ((Bf a v : ℂ) - c)) * this + simp_rw [hL1] + have hint : Integrable (Function.uncurry F) (volume.prod (volume.restrict (Ioi 0))) := by + have hprod : Integrable (fun z : ℝ × ℝ => phi L z.1 * ((M + |c|) * Real.exp (-ε * z.2))) + (volume.prod (volume.restrict (Ioi 0))) := + (integrable_phi hL).mul_prod ((exp_neg_integrableOn_Ioi 0 hε).const_mul (M + |c|)) + refine hprod.mono' ?_ (Eventually.of_forall fun z => ?_) + · have hB := (measurable_Bf (a := a)) + have : Measurable (Function.uncurry F) := by + rw [hF] + unfold Function.uncurry + have := continuous_phi L + fun_prop + exact this.aestronglyMeasurable + · obtain ⟨t, v⟩ := z + simp only [Function.uncurry, hF] + rw [norm_mul, norm_mul, norm_mul, Complex.norm_real, Real.norm_eq_abs, + abs_of_nonneg (phi_nonneg L t), Complex.norm_exp, Complex.norm_exp] + have h1 : (-(↑ε + ↑t * I) * (v : ℂ)).re = -ε * v := by simp + have h2 : (I * ↑y * (t : ℂ)).re = 0 := by simp + rw [h1, h2, Real.exp_zero, mul_one] + have h3 : ‖(Bf a v : ℂ) - c‖ ≤ M + |c| := by + rw [← Complex.ofReal_sub, Complex.norm_real, Real.norm_eq_abs] + refine (abs_sub _ _).trans ?_ + rw [abs_of_nonneg (Bf_nonneg ha v)] + linarith [Bf_le hM0 hM v] + apply mul_le_mul_of_nonneg_left _ (phi_nonneg L t) + exact mul_le_mul_of_nonneg_right h3 (Real.exp_pos _).le + rw [integral_integral_swap hint] + simp_rw [hR1] + +/-- Letting `ε → 0`: `∫ phi(t) G(1 + it) e^{iyt} dt = ∫_{v > 0} (B(v) - c) Φ(y - v) dv`. -/ +private theorem limit_identity {M : ℝ} (hM0 : 0 ≤ M) (ha : ∀ n, 0 ≤ a n) + (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) (c : ℝ) (G : ℂ → ℂ) + (hGc : ContinuousOn G {s | 1 ≤ s.re}) + (hG : ∀ s : ℂ, 1 < s.re → LSeries (fun n => (a n : ℂ)) s / s - c / (s - 1) = G s) + {L : ℝ} (hL : 0 < L) (y : ℝ) : + ∫ t, (phi L t : ℂ) * G (1 + t * I) * cexp (I * y * t) = + ∫ v in Ioi 0, ((Bf a v : ℂ) - c) * (Phi L (y - v) : ℂ) := by + -- the path + have hpath : ∀ (ε : ℝ), 0 ≤ ε → Continuous (fun t : ℝ => G (1 + ε + t * I)) := by + intro ε hε + refine hGc.comp_continuous (by fun_prop) (fun t => ?_) + simp only [Set.mem_ofPred_eq, add_re, one_re, ofReal_re, mul_re, I_re, mul_zero, ofReal_im, I_im, + mul_one, sub_self, add_zero] + linarith + -- left limit + have hK : IsCompact ((Icc (1:ℝ) 2) ×ℂ (Icc (-L) L)) := isCompact_Icc.reProdIm isCompact_Icc + obtain ⟨C, hC⟩ := hK.exists_bound_of_continuousOn (hGc.mono (fun s hs => by + simp only [mem_reProdIm, mem_Icc] at hs; exact hs.1.1)) + have hLlim : Tendsto (fun ε : ℝ => ∫ t, (phi L t : ℂ) * G (1 + ε + t * I) * cexp (I * y * t)) + (𝓝[>] 0) (𝓝 (∫ t, (phi L t : ℂ) * G (1 + t * I) * cexp (I * y * t))) := by + refine tendsto_integral_filter_of_dominated_convergence (fun t => C * phi L t) ?_ ?_ ?_ ?_ + · filter_upwards [self_mem_nhdsWithin] with ε hε + have h1 := hpath ε (le_of_lt hε) + have h2 : Continuous fun t : ℝ => (phi L t : ℂ) := by have := continuous_phi L; fun_prop + have h3 : Continuous fun t : ℝ => cexp (I * y * t) := by fun_prop + exact ((h2.mul h1).mul h3).aestronglyMeasurable + · have h1 : Ioo (0:ℝ) 1 ∈ 𝓝[>] (0:ℝ) := Ioo_mem_nhdsGT (by norm_num) + filter_upwards [h1] with ε hε + refine Eventually.of_forall fun t => ?_ + rw [norm_mul, norm_mul, Complex.norm_real, Real.norm_eq_abs, abs_of_nonneg (phi_nonneg L t)] + have he : ‖cexp (I * y * t)‖ = 1 := by + rw [Complex.norm_exp]; simp + rw [he, mul_one] + by_cases ht : L ≤ |t| + · rw [phi_eq_zero hL ht]; simp + · rw [mul_comm] + apply mul_le_mul_of_nonneg_right _ (phi_nonneg L t) + apply hC + rw [not_le, abs_lt] at ht + simp only [mem_reProdIm, mem_Icc, add_re, one_re, ofReal_re, mul_re, I_re, mul_zero, + ofReal_im, I_im, mul_one, sub_self, add_zero, add_im, one_im, zero_add, mul_im] + exact ⟨⟨by linarith [hε.1], by linarith [hε.2]⟩, ht.1.le, ht.2.le⟩ + · exact (integrable_phi hL).const_mul C + · refine Eventually.of_forall fun t => ?_ + have hmem : (1 + t * I : ℂ) ∈ {s : ℂ | 1 ≤ s.re} := by simp + have hcw := (hGc _ hmem).tendsto + have hpth : Tendsto (fun ε : ℝ => (1 + ε + t * I : ℂ)) (𝓝[>] 0) (𝓝[{s | 1 ≤ s.re}] (1 + t * I)) := by + apply tendsto_nhdsWithin_iff.mpr + constructor + · have : Tendsto (fun ε : ℝ => (1 + ε + t * I : ℂ)) (𝓝 0) (𝓝 (1 + (0:ℝ) + t * I)) := + (by fun_prop : Continuous fun ε : ℝ => (1 + ε + t * I : ℂ)).tendsto 0 + simpa using this.mono_left nhdsWithin_le_nhds + · filter_upwards [self_mem_nhdsWithin] with ε hε + simp only [add_re, one_re, ofReal_re, mul_re, I_re, mul_zero, ofReal_im, + I_im, mul_one, sub_self, add_zero] + linarith [mem_Ioi.mp hε] + exact ((hcw.comp hpth).const_mul _).mul_const _ + -- right limit + have hRlim : Tendsto (fun ε : ℝ => ∫ v in Ioi 0, ((Bf a v : ℂ) - c) * cexp (-ε * v) * + (Phi L (y - v) : ℂ)) (𝓝[>] 0) (𝓝 (∫ v in Ioi 0, ((Bf a v : ℂ) - c) * (Phi L (y - v) : ℂ))) := by + refine tendsto_integral_filter_of_dominated_convergence (fun v => (M + |c|) * Phi L (y - v)) + ?_ ?_ ?_ ?_ + · refine Eventually.of_forall fun ε => ?_ + have hB := (measurable_Bf (a := a)) + have hP := measurable_Phi L + exact (by fun_prop : Measurable fun v : ℝ => ((Bf a v : ℂ) - c) * cexp (-ε * v) * + (Phi L (y - v) : ℂ)).aestronglyMeasurable + · filter_upwards [self_mem_nhdsWithin] with ε hε + refine (ae_restrict_iff' measurableSet_Ioi).mpr (Eventually.of_forall fun v hv => ?_) + rw [norm_mul, norm_mul, Complex.norm_real, Real.norm_eq_abs, + abs_of_nonneg (Phi_nonneg hL _), Complex.norm_exp] + have h1 : (-(ε : ℂ) * v).re = -ε * v := by simp + rw [h1] + have h2 : Real.exp (-ε * v) ≤ 1 := by + rw [Real.exp_le_one_iff] + have := mem_Ioi.mp hε; have := mem_Ioi.mp hv; nlinarith + have h3 : ‖(Bf a v : ℂ) - c‖ ≤ M + |c| := by + rw [← Complex.ofReal_sub, Complex.norm_real, Real.norm_eq_abs] + refine (abs_sub _ _).trans ?_ + rw [abs_of_nonneg (Bf_nonneg ha v)] + linarith [Bf_le hM0 hM v] + have h4 : 0 ≤ ‖(Bf a v : ℂ) - c‖ := norm_nonneg _ + apply mul_le_mul_of_nonneg_right _ (Phi_nonneg hL _) + calc ‖(Bf a v : ℂ) - c‖ * Real.exp (-ε * v) ≤ ‖(Bf a v : ℂ) - c‖ * 1 := + mul_le_mul_of_nonneg_left h2 h4 + _ ≤ M + |c| := by rw [mul_one]; exact h3 + · exact ((integrable_Phi hL).comp_sub_left y).integrableOn.const_mul _ + · refine Eventually.of_forall fun v => ?_ + have : Tendsto (fun ε : ℝ => cexp (-ε * v)) (𝓝[>] 0) (𝓝 (cexp (-(0:ℝ) * v))) := + ((by fun_prop : Continuous fun ε : ℝ => cexp (-ε * v)).tendsto 0).mono_left + nhdsWithin_le_nhds + simp only [ofReal_zero, neg_zero, zero_mul, Complex.exp_zero] at this + simpa using (this.const_mul ((Bf a v : ℂ) - c)).mul_const (Phi L (y - v) : ℂ) + have heq : (fun ε : ℝ => ∫ t, (phi L t : ℂ) * G (1 + ε + t * I) * cexp (I * y * t)) =ᶠ[𝓝[>] 0] + (fun ε : ℝ => ∫ v in Ioi 0, ((Bf a v : ℂ) - c) * cexp (-ε * v) * (Phi L (y - v) : ℂ)) := by + filter_upwards [self_mem_nhdsWithin] with ε hε + exact fubini_identity hM0 ha hM c G hG hL y hε + exact tendsto_nhds_unique (hLlim.congr' heq) hRlim + +/-- By the Riemann–Lebesgue lemma, `∫_{v > 0} (B(v) - c) Φ(y - v) dv → 0` as `y → ∞`. -/ +private theorem J_tendsto {M : ℝ} (hM0 : 0 ≤ M) (ha : ∀ n, 0 ≤ a n) + (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) (c : ℝ) (G : ℂ → ℂ) + (hGc : ContinuousOn G {s | 1 ≤ s.re}) + (hG : ∀ s : ℂ, 1 < s.re → LSeries (fun n => (a n : ℂ)) s / s - c / (s - 1) = G s) + {L : ℝ} (hL : 0 < L) : + Tendsto (fun y : ℝ => ∫ v in Ioi 0, (Bf a v - c) * Phi L (y - v)) atTop (𝓝 0) := by + have hRL := Real.tendsto_integral_exp_smul_cocompact (fun t : ℝ => (phi L t : ℂ) * G (1 + t * I)) + have hw : Tendsto (fun y : ℝ => -y / (2 * Real.pi)) atTop (cocompact ℝ) := by + refine Tendsto.mono_right ?_ atBot_le_cocompact + have : Tendsto (fun y : ℝ => -y) atTop atBot := tendsto_neg_atTop_atBot + exact this.atBot_div_const (by positivity) + have hC := hRL.comp hw + have heq : ∀ y : ℝ, ((fun w : ℝ => ∫ v : ℝ, Real.fourierChar (-(v * w)) • + ((fun t : ℝ => (phi L t : ℂ) * G (1 + t * I)) v)) ∘ (fun y : ℝ => -y / (2 * Real.pi))) y = + ((∫ v in Ioi 0, (Bf a v - c) * Phi L (y - v) : ℝ) : ℂ) := by + intro y + simp only [Function.comp] + rw [← integral_complex_ofReal] + push_cast + rw [← limit_identity hM0 ha hM c G hGc hG hL y] + congr 1; ext t + rw [Circle.smul_def, Real.fourierChar_apply] + simp only [smul_eq_mul] + have : (↑(2 * Real.pi * -(t * (-y / (2 * Real.pi)))) * I : ℂ) = I * y * t := by + push_cast + field_simp + rw [this]; ring + have hC' : Tendsto (fun y : ℝ => ((∫ v in Ioi 0, (Bf a v - c) * Phi L (y - v) : ℝ) : ℂ)) + atTop (𝓝 0) := by + refine hC.congr (fun y => heq y) + have := (Complex.continuous_re.tendsto 0).comp hC' + refine this.congr (fun y => ?_) + simp only [Function.comp, Complex.ofReal_re] + +/-- Translates of the Fejér kernel are integrable. -/ +private theorem integrable_Phi_sub {L : ℝ} (hL : 0 < L) (y : ℝ) : Integrable (fun v => Phi L (y - v)) := + (integrable_Phi hL).comp_sub_left y + +/-- `v ↦ B(v) Φ(y - v)` is integrable on every set. -/ +private theorem integrableOn_Bf_Phi {M : ℝ} (hM0 : 0 ≤ M) (ha : ∀ n, 0 ≤ a n) + (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) {L : ℝ} (hL : 0 < L) (y : ℝ) + (s : Set ℝ) : IntegrableOn (fun v => Bf a v * Phi L (y - v)) s := by + refine Integrable.mono' ((integrable_Phi_sub hL y).integrableOn.const_mul M) ?_ ?_ + · have := measurable_Bf (a := a); have := measurable_Phi L + exact (by fun_prop : Measurable fun v => Bf a v * Phi L (y - v)).aestronglyMeasurable + · refine Eventually.of_forall fun v => ?_ + rw [Real.norm_eq_abs, abs_of_nonneg (mul_nonneg (Bf_nonneg ha v) (Phi_nonneg hL _))] + exact mul_le_mul_of_nonneg_right (Bf_le hM0 hM v) (Phi_nonneg hL _) + +/-- `∫_{v > 0} Φ(y - v) dv → ∫ Φ` as `y → ∞`. -/ +private theorem tail_tendsto {L : ℝ} (hL : 0 < L) : + Tendsto (fun y : ℝ => ∫ v in Ioi 0, Phi L (y - v)) atTop (𝓝 (∫ u, Phi L u)) := by + have hsplit : ∀ y, ∫ v in Ioi 0, Phi L (y - v) = (∫ u, Phi L u) - ∫ v in Iic 0, Phi L (y - v) := by + intro y + have := integral_add_compl (measurableSet_Ioi (a := (0:ℝ))) (integrable_Phi_sub hL y) + have h2 : ∫ v, Phi L (y - v) = ∫ u, Phi L u := + integral_sub_left_eq_self (fun u => Phi L u) volume y + rw [compl_Ioi, h2] at this + linarith + simp_rw [hsplit] + have hE : Tendsto (fun y : ℝ => ∫ v in Iic 0, Phi L (y - v)) atTop (𝓝 0) := by + have hub : Tendsto (fun y : ℝ => 16 * Real.pi / L * y⁻¹) atTop (𝓝 0) := by + simpa using tendsto_inv_atTop_zero.const_mul (16 * Real.pi / L) + refine tendsto_of_tendsto_of_tendsto_of_le_of_le' tendsto_const_nhds hub ?_ ?_ + · exact Eventually.of_forall fun y => setIntegral_nonneg measurableSet_Iic + (fun v _ => Phi_nonneg hL _) + · filter_upwards [eventually_gt_atTop 0] with y hy + rw [← integral_indicator measurableSet_Iic] + calc ∫ v, Set.indicator (Iic 0) (fun v => Phi L (y - v)) v + ≤ ∫ v, Set.indicator {u | y / 2 < |u|} (Phi L) (y - v) := by + apply integral_mono_of_nonneg + · exact Eventually.of_forall fun v => + Set.indicator_nonneg (fun v _ => Phi_nonneg hL _) v + · have : Integrable (Set.indicator {u | y / 2 < |u|} (Phi L)) := + (integrable_Phi hL).indicator (measurableSet_lt measurable_const measurable_abs) + exact this.comp_sub_left y + · refine Eventually.of_forall fun v => ?_ + by_cases hv : v ∈ Iic 0 + · simp only [mem_Iic] at hv + have hmem : y - v ∈ {u : ℝ | y / 2 < |u|} := by + show y / 2 < |y - v| + rw [abs_of_pos (by linarith)]; linarith + rw [Set.indicator_of_mem (show v ∈ Iic 0 from hv)] + dsimp only + rw [Set.indicator_of_mem hmem] + · rw [Set.indicator_of_notMem hv] + exact Set.indicator_nonneg (fun u _ => Phi_nonneg hL u) _ + _ = ∫ u, Set.indicator {u | y / 2 < |u|} (Phi L) u := + integral_sub_left_eq_self (Set.indicator {u | y / 2 < |u|} (Phi L)) volume y + _ ≤ 8 * Real.pi / (L * (y / 2)) := tail_le hL (by linarith) + _ = 16 * Real.pi / L * y⁻¹ := by field_simp; ring + simpa using (tendsto_const_nhds (x := ∫ u, Phi L u)).sub hE + +/-- `∫_{v > 0} B(v) Φ(y - v) dv → c ∫ Φ` as `y → ∞`. -/ +private theorem I_tendsto {M : ℝ} (hM0 : 0 ≤ M) (ha : ∀ n, 0 ≤ a n) + (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) (c : ℝ) (G : ℂ → ℂ) + (hGc : ContinuousOn G {s | 1 ≤ s.re}) + (hG : ∀ s : ℂ, 1 < s.re → LSeries (fun n => (a n : ℂ)) s / s - c / (s - 1) = G s) + {L : ℝ} (hL : 0 < L) : + Tendsto (fun y : ℝ => ∫ v in Ioi 0, Bf a v * Phi L (y - v)) atTop + (𝓝 (c * ∫ u, Phi L u)) := by + have hsplit : ∀ y : ℝ, ∫ v in Ioi 0, Bf a v * Phi L (y - v) = + (∫ v in Ioi 0, (Bf a v - c) * Phi L (y - v)) + c * ∫ v in Ioi 0, Phi L (y - v) := by + intro y + rw [← integral_const_mul, ← integral_add] + · congr 1; ext v; ring + · simp_rw [sub_mul] + exact (integrableOn_Bf_Phi hM0 ha hM hL y _).sub + ((integrable_Phi_sub hL y).integrableOn.const_mul c) + · exact (integrable_Phi_sub hL y).integrableOn.const_mul c + simp_rw [hsplit] + simpa using (J_tendsto hM0 ha hM c G hGc hG hL).add ((tail_tendsto hL).const_mul c) + +/-- `{u | δ < |u|}` is measurable. -/ +private theorem measurableSet_far (δ : ℝ) : MeasurableSet {u : ℝ | δ < |u|} := + measurableSet_lt measurable_const measurable_abs + +/-- `{u | |u| ≤ δ}` is measurable. -/ +private theorem measurableSet_near (δ : ℝ) : MeasurableSet {u : ℝ | |u| ≤ δ} := + measurableSet_le measurable_abs measurable_const + +/-- Mass of the kernel near `0` equals total mass minus the tail. -/ +private theorem near_eq {L : ℝ} (hL : 0 < L) (δ : ℝ) : + ∫ u, Set.indicator {u | |u| ≤ δ} (Phi L) u = + (∫ u, Phi L u) - ∫ u, Set.indicator {u | δ < |u|} (Phi L) u := by + rw [eq_sub_iff_add_eq, ← integral_add ((integrable_Phi hL).indicator (measurableSet_near δ)) + ((integrable_Phi hL).indicator (measurableSet_far δ))] + congr 1; ext u + by_cases hu : |u| ≤ δ + · rw [Set.indicator_of_mem (show u ∈ {u : ℝ | |u| ≤ δ} from hu), + Set.indicator_of_notMem (show u ∉ {u : ℝ | δ < |u|} from not_lt.mpr hu), add_zero] + · rw [Set.indicator_of_notMem (show u ∉ {u : ℝ | |u| ≤ δ} from hu), + Set.indicator_of_mem (show u ∈ {u : ℝ | δ < |u|} from not_le.mp hu), zero_add] + +/-- Tauberian upper estimate: `B(y) e^{-2δ} (∫ Φ - tail) ≤ ∫_{v > 0} B(v) Φ(y + δ - v) dv`. -/ +private theorem upper_bound {M : ℝ} (hM0 : 0 ≤ M) (ha : ∀ n, 0 ≤ a n) + (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) {L : ℝ} (hL : 0 < L) {y δ : ℝ} + (hy : 0 < y) : + Bf a y * Real.exp (-(2 * δ)) * ((∫ u, Phi L u) - ∫ u, Set.indicator {u | δ < |u|} (Phi L) u) + ≤ ∫ v in Ioi 0, Bf a v * Phi L (y + δ - v) := by + rw [← near_eq hL δ, ← integral_sub_left_eq_self _ volume (y + δ), ← integral_const_mul, + ← integral_indicator measurableSet_Ioi] + apply integral_mono + · exact (((integrable_Phi hL).indicator (measurableSet_near δ)).comp_sub_left (y + δ)).const_mul _ + · exact (integrableOn_Bf_Phi hM0 ha hM hL (y + δ) (Ioi 0)).integrable_indicator measurableSet_Ioi + · intro v + dsimp only + have hc : 0 ≤ Bf a y * Real.exp (-(2 * δ)) := + mul_nonneg (Bf_nonneg ha y) (Real.exp_pos _).le + by_cases hv : |y + δ - v| ≤ δ + · rw [Set.indicator_of_mem (show y + δ - v ∈ {u : ℝ | |u| ≤ δ} from hv)] + rw [abs_le] at hv + have hv0 : v ∈ Ioi 0 := by simp only [mem_Ioi]; linarith + rw [Set.indicator_of_mem hv0] + exact mul_le_mul_of_nonneg_right (Bf_ge_of_ge ha (by linarith) (by linarith)) + (Phi_nonneg hL _) + · rw [Set.indicator_of_notMem (show y + δ - v ∉ {u : ℝ | |u| ≤ δ} from hv), mul_zero] + exact Set.indicator_nonneg (fun v _ => mul_nonneg (Bf_nonneg ha v) (Phi_nonneg hL _)) v + +/-- Tauberian lower estimate: `∫_{v > 0} B(v) Φ(y - δ - v) dv ≤ B(y) e^{2δ} ∫ Φ + M · tail`. -/ +private theorem lower_bound {M : ℝ} (hM0 : 0 ≤ M) (ha : ∀ n, 0 ≤ a n) + (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) {L : ℝ} (hL : 0 < L) (y δ : ℝ) : + ∫ v in Ioi 0, Bf a v * Phi L (y - δ - v) ≤ + Bf a y * Real.exp (2 * δ) * (∫ u, Phi L u) + + M * ∫ u, Set.indicator {u | δ < |u|} (Phi L) u := by + rw [← integral_sub_left_eq_self (Phi L) volume (y - δ), + ← integral_sub_left_eq_self (Set.indicator {u | δ < |u|} (Phi L)) volume (y - δ), + ← integral_const_mul, ← integral_const_mul, ← integral_add, + ← integral_indicator measurableSet_Ioi] + · apply integral_mono + · exact (integrableOn_Bf_Phi hM0 ha hM hL (y - δ) (Ioi 0)).integrable_indicator measurableSet_Ioi + · exact ((integrable_Phi_sub hL (y - δ)).const_mul _).add + ((((integrable_Phi hL).indicator (measurableSet_far δ)).comp_sub_left (y - δ)).const_mul _) + · intro v + dsimp only + have hfar : 0 ≤ M * Set.indicator {u | δ < |u|} (Phi L) (y - δ - v) := + mul_nonneg hM0 (Set.indicator_nonneg (fun u _ => Phi_nonneg hL u) _) + have hnear : 0 ≤ Bf a y * Real.exp (2 * δ) * Phi L (y - δ - v) := + mul_nonneg (mul_nonneg (Bf_nonneg ha y) (Real.exp_pos _).le) (Phi_nonneg hL _) + by_cases hv0 : v ∈ Ioi 0 + · rw [Set.indicator_of_mem hv0] + by_cases hv : |y - δ - v| ≤ δ + · rw [abs_le] at hv + have := mul_le_mul_of_nonneg_right (Bf_le_of_le ha (y := y) (v := v) (δ := δ) + (by linarith) (by linarith)) (Phi_nonneg hL (y - δ - v)) + linarith + · rw [Set.indicator_of_mem (show y - δ - v ∈ {u : ℝ | δ < |u|} from not_le.mp hv)] + have := mul_le_mul_of_nonneg_right (Bf_le hM0 hM v) (Phi_nonneg hL (y - δ - v)) + linarith + · rw [Set.indicator_of_notMem hv0] + linarith + · exact (integrable_Phi_sub hL (y - δ)).const_mul _ + · exact (((integrable_Phi hL).indicator (measurableSet_far δ)).comp_sub_left (y - δ)).const_mul _ + +/-- The tail of the kernel is nonnegative. -/ +private theorem tail_nonneg {L : ℝ} (hL : 0 < L) (δ : ℝ) : + 0 ≤ ∫ u, Set.indicator {u | δ < |u|} (Phi L) u := + integral_nonneg fun u => Set.indicator_nonneg (fun u _ => Phi_nonneg hL u) u + +/-- `B(y) → c` as `y → ∞`. -/ +private theorem tendsto_Bf {M : ℝ} (hM0 : 0 ≤ M) (ha : ∀ n, 0 ≤ a n) + (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) (c : ℝ) (hc : 0 ≤ c) (G : ℂ → ℂ) + (hGc : ContinuousOn G {s | 1 ≤ s.re}) + (hG : ∀ s : ℂ, 1 < s.re → LSeries (fun n => (a n : ℂ)) s / s - c / (s - 1) = G s) : + Tendsto (Bf a) atTop (𝓝 c) := by + rw [tendsto_order] + constructor + · intro c' hc' + rcases lt_or_ge c' 0 with h0 | h0 + · exact Eventually.of_forall fun y => h0.trans_le (Bf_nonneg ha y) + -- choose δ + have hδlim : Tendsto (fun δ : ℝ => Real.exp (-(2 * δ)) * c) (𝓝[>] 0) (𝓝 c) := by + have : Tendsto (fun δ : ℝ => Real.exp (-(2 * δ)) * c) (𝓝 0) (𝓝 (Real.exp (-(2 * 0)) * c)) := + ((by fun_prop : Continuous fun δ : ℝ => Real.exp (-(2 * δ)) * c).tendsto 0) + simpa using this.mono_left nhdsWithin_le_nhds + obtain ⟨δ, hδc, hδ⟩ := ((hδlim.eventually (lt_mem_nhds hc')).and self_mem_nhdsWithin).exists + have hδ : 0 < δ := hδ + -- choose L + have hLlim : Tendsto (fun L : ℝ => Real.exp (-(2 * δ)) * (c - M * (8 * Real.pi / δ * L⁻¹))) + atTop (𝓝 (Real.exp (-(2 * δ)) * c)) := by + have := ((tendsto_inv_atTop_zero.const_mul (8 * Real.pi / δ)).const_mul M).const_sub c + simpa using this.const_mul (Real.exp (-(2 * δ))) + obtain ⟨L, hLc, hL⟩ := ((hLlim.eventually (lt_mem_nhds hδc)).and + (eventually_gt_atTop 0)).exists + set K := ∫ u, Phi L u with hK + set τ := ∫ u, Set.indicator {u | δ < |u|} (Phi L) u with hτ + have hK1 : 1 ≤ K := one_le_integral_Phi hL + have hτ0 : 0 ≤ τ := tail_nonneg hL δ + have hτ1 : τ ≤ 8 * Real.pi / δ * L⁻¹ := by + have := tail_le hL hδ; rw [← hτ] at this + calc τ ≤ 8 * Real.pi / (L * δ) := this + _ = 8 * Real.pi / δ * L⁻¹ := by field_simp + have hE : 0 < Real.exp (2 * δ) * K := by positivity + have hlim : Tendsto (fun y : ℝ => ((∫ v in Ioi 0, Bf a v * Phi L (y - δ - v)) - M * τ) / + (Real.exp (2 * δ) * K)) atTop (𝓝 ((c * K - M * τ) / (Real.exp (2 * δ) * K))) := by + have h1 := (I_tendsto hM0 ha hM c G hGc hG hL).comp + (tendsto_atTop_add_const_right _ (-δ) tendsto_id) + have h2 : Tendsto (fun y : ℝ => ∫ v in Ioi 0, Bf a v * Phi L (y - δ - v)) atTop + (𝓝 (c * K)) := by + refine h1.congr (fun y => ?_) + simp only [Function.comp, id, ← sub_eq_add_neg] + exact (h2.sub_const _).div_const _ + have hval : c' < (c * K - M * τ) / (Real.exp (2 * δ) * K) := by + rw [lt_div_iff₀ hE] + have e1 : Real.exp (-(2 * δ)) * Real.exp (2 * δ) = 1 := by + rw [← Real.exp_add]; simp + have hMτ : M * τ ≤ M * (8 * Real.pi / δ * L⁻¹) := mul_le_mul_of_nonneg_left hτ1 hM0 + have hMτK : M * τ ≤ M * τ * K := le_mul_of_one_le_right (mul_nonneg hM0 hτ0) hK1 + -- c' * exp(2δ) < c - M*bound ≤ c - M τ + have h3 : c' * Real.exp (2 * δ) < c - M * (8 * Real.pi / δ * L⁻¹) := by + have := mul_lt_mul_of_pos_right hLc (Real.exp_pos (2 * δ)) + calc c' * Real.exp (2 * δ) < Real.exp (-(2 * δ)) * (c - M * (8 * Real.pi / δ * L⁻¹)) * + Real.exp (2 * δ) := this + _ = c - M * (8 * Real.pi / δ * L⁻¹) := by + rw [mul_comm, ← mul_assoc, mul_comm (Real.exp (2 * δ)), e1, one_mul] + have h4 : c' * Real.exp (2 * δ) * K ≤ (c - M * τ) * K := by + apply mul_le_mul_of_nonneg_right _ (by linarith) + linarith + nlinarith + filter_upwards [hlim.eventually (lt_mem_nhds hval)] with y hy + refine hy.trans_le ?_ + rw [div_le_iff₀ hE] + have := lower_bound hM0 ha hM hL y δ + rw [← hK, ← hτ] at this + linarith + · intro c' hc' + have hδlim : Tendsto (fun δ : ℝ => Real.exp (2 * δ) * c) (𝓝[>] 0) (𝓝 c) := by + have : Tendsto (fun δ : ℝ => Real.exp (2 * δ) * c) (𝓝 0) (𝓝 (Real.exp (2 * 0) * c)) := + ((by fun_prop : Continuous fun δ : ℝ => Real.exp (2 * δ) * c).tendsto 0) + simpa using this.mono_left nhdsWithin_le_nhds + obtain ⟨δ, hδc, hδ⟩ := ((hδlim.eventually (gt_mem_nhds hc')).and self_mem_nhdsWithin).exists + have hδ : 0 < δ := hδ + have hLlim : Tendsto (fun L : ℝ => Real.exp (2 * δ) * c / (1 - 8 * Real.pi / δ * L⁻¹)) + atTop (𝓝 (Real.exp (2 * δ) * c)) := by + have := (tendsto_inv_atTop_zero.const_mul (8 * Real.pi / δ)).const_sub 1 + have h := (tendsto_const_nhds (x := Real.exp (2 * δ) * c)).div this (by simp) + simp only [mul_zero, sub_zero, div_one] at h + exact h + have hsmall : Tendsto (fun L : ℝ => 8 * Real.pi / δ * L⁻¹) atTop (𝓝 0) := by + simpa using tendsto_inv_atTop_zero.const_mul (8 * Real.pi / δ) + obtain ⟨L, ⟨hLc, hL1⟩, hL⟩ := (((hLlim.eventually (gt_mem_nhds hδc)).and + (hsmall.eventually (gt_mem_nhds (by norm_num : (0:ℝ) < 1)))).and + (eventually_gt_atTop 0)).exists + set t₀ := 8 * Real.pi / δ * L⁻¹ with ht₀ + set K := ∫ u, Phi L u with hK + set τ := ∫ u, Set.indicator {u | δ < |u|} (Phi L) u with hτ + have hK1 : 1 ≤ K := one_le_integral_Phi hL + have hτ0 : 0 ≤ τ := tail_nonneg hL δ + have hτ1 : τ ≤ t₀ := by + have := tail_le hL hδ; rw [← hτ] at this + calc τ ≤ 8 * Real.pi / (L * δ) := this + _ = t₀ := by rw [ht₀]; field_simp + have hKτ : 0 < K - τ := by linarith + have hlim : Tendsto (fun y : ℝ => (∫ v in Ioi 0, Bf a v * Phi L (y + δ - v)) * + Real.exp (2 * δ) / (K - τ)) atTop (𝓝 (c * K * Real.exp (2 * δ) / (K - τ))) := by + have h1 := (I_tendsto hM0 ha hM c G hGc hG hL).comp + (tendsto_atTop_add_const_right _ δ tendsto_id) + have h2 : Tendsto (fun y : ℝ => ∫ v in Ioi 0, Bf a v * Phi L (y + δ - v)) atTop + (𝓝 (c * K)) := by + refine h1.congr (fun y => ?_) + simp only [Function.comp, id] + exact (h2.mul_const _).div_const _ + have hval : c * K * Real.exp (2 * δ) / (K - τ) < c' := by + rw [div_lt_iff₀ hKτ] + have ht1 : 0 < 1 - t₀ := by linarith + rw [div_lt_iff₀ ht1] at hLc + -- c K e (1 - t0) ≤ e c (K - τ) and e c < c' (1 - t0) ... combine + have hE := Real.exp_pos (2 * δ) + have k1 : c * K * Real.exp (2 * δ) * (1 - t₀) ≤ Real.exp (2 * δ) * c * (K - τ) := by + have : c * τ ≤ c * K * t₀ := by + have : τ ≤ K * t₀ := hτ1.trans (le_mul_of_one_le_left (by linarith) hK1) + calc c * τ ≤ c * (K * t₀) := mul_le_mul_of_nonneg_left this hc + _ = c * K * t₀ := by ring + nlinarith + have k2 : Real.exp (2 * δ) * c * (K - τ) < c' * (1 - t₀) * (K - τ) := + mul_lt_mul_of_pos_right hLc hKτ + have k3 : c' * (1 - t₀) * (K - τ) ≤ c' * (K - τ) * (1 - t₀) := le_of_eq (by ring) + have k4 : c * K * Real.exp (2 * δ) * (1 - t₀) < c' * (K - τ) * (1 - t₀) := by linarith + exact lt_of_mul_lt_mul_right k4 ht1.le + filter_upwards [hlim.eventually (gt_mem_nhds hval), eventually_gt_atTop 0] with y hy hy0 + refine lt_of_le_of_lt ?_ hy + rw [le_div_iff₀ hKτ] + have := upper_bound hM0 ha hM hL (δ := δ) hy0 + rw [← hK, ← hτ] at this + have e1 : Real.exp (-(2 * δ)) * Real.exp (2 * δ) = 1 := by + rw [← Real.exp_add]; simp + have := mul_le_mul_of_nonneg_right this (Real.exp_pos (2 * δ)).le + calc Bf a y * (K - τ) = Bf a y * Real.exp (-(2 * δ)) * (K - τ) * Real.exp (2 * δ) := by + linear_combination (-(Bf a y * (K - τ))) * e1 + _ ≤ _ := this + +/-- A Wiener–Ikehara type Tauberian theorem for nonnegative coefficients with linearly bounded +partial sums. -/ +private theorem tauberian {M : ℝ} (hM0 : 0 ≤ M) (ha : ∀ n, 0 ≤ a n) + (hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, a n ≤ M * N) (c : ℝ) (hc : 0 ≤ c) (G : ℂ → ℂ) + (hGc : ContinuousOn G {s | 1 ≤ s.re}) + (hG : ∀ s : ℂ, 1 < s.re → LSeries (fun n => (a n : ℂ)) s / s - c / (s - 1) = G s) : + Tendsto (fun N : ℕ => (∑ n ∈ Finset.Icc 1 N, a n) / N) atTop (𝓝 c) := by + have h := (tendsto_Bf hM0 ha hM c hc G hGc hG).comp + (Real.tendsto_log_atTop.comp tendsto_natCast_atTop_atTop) + refine h.congr' ?_ + filter_upwards [eventually_gt_atTop 0] with N hN + have hN' : (0 : ℝ) < N := by exact_mod_cast hN + simp only [Function.comp, Bf, Asum] + rw [Real.exp_log hN', Real.exp_neg, Real.exp_log hN', Nat.floor_natCast, div_eq_mul_inv] + +end Tauberian + +end + +end Tauber + +namespace Arith + +open ArithmeticFunction +open scoped LSeries.notation + +/-- the weight `2^ω(m)` on odd `m` all of whose prime factors are `3 mod 4` -/ +private def gN (m : ℕ) : ℕ := + if Odd m ∧ (∀ p ∈ m.primeFactors, p % 4 = 3) then 2 ^ m.primeFactors.card else 0 + +/-- `g 0 = 0`. -/ +private theorem gN_zero : gN 0 = 0 := by simp [gN] + +/-- `g 1 = 1`. -/ +private theorem gN_one : gN 1 = 1 := by simp [gN] + +/-- `g` is multiplicative. -/ +private theorem gN_mul {m n : ℕ} (hm : m ≠ 0) (hn : n ≠ 0) (h : m.Coprime n) : + gN (m * n) = gN m * gN n := by + unfold gN + rw [Nat.primeFactors_mul hm hn, Finset.card_union_of_disjoint h.disjoint_primeFactors] + simp only [Nat.odd_mul] + by_cases h1 : Odd m ∧ ∀ p ∈ m.primeFactors, p % 4 = 3 + · by_cases h2 : Odd n ∧ ∀ p ∈ n.primeFactors, p % 4 = 3 + · rw [if_pos h1, if_pos h2, if_pos, pow_add] + refine ⟨⟨h1.1, h2.1⟩, fun p hp => ?_⟩ + rcases Finset.mem_union.mp hp with hp | hp + · exact h1.2 p hp + · exact h2.2 p hp + · rw [if_neg h2, if_neg, mul_zero] + rintro ⟨⟨_, ho⟩, hp⟩ + exact h2 ⟨ho, fun p h => hp p (Finset.mem_union_right _ h)⟩ + · rw [if_neg h1, if_neg, zero_mul] + rintro ⟨⟨ho, _⟩, hp⟩ + exact h1 ⟨ho, fun p h => hp p (Finset.mem_union_left _ h)⟩ + +/-- Values of `g` at prime powers. -/ +private theorem gN_prime_pow {p : ℕ} (hp : p.Prime) {j : ℕ} (hj : j ≠ 0) : + gN (p ^ j) = if p % 4 = 3 then 2 else 0 := by + unfold gN + rw [Nat.primeFactors_prime_pow hj hp, Finset.card_singleton, pow_one] + simp only [Finset.mem_singleton, forall_eq] + by_cases h3 : p % 4 = 3 + · rw [if_pos h3, if_pos] + refine ⟨Odd.pow ?_, h3⟩ + rw [Nat.odd_iff]; omega + · rw [if_neg h3, if_neg] + exact fun h => h3 h.2 + +/-- `g` as an arithmetic function -/ +private def gA : ArithmeticFunction ℤ := ⟨fun m => (gN m : ℤ), by simp [gN_zero]⟩ + +/-- Values of `gA`. -/ +private theorem gA_apply (m : ℕ) : gA m = (gN m : ℤ) := rfl + +/-- `gA` is multiplicative. -/ +private theorem gA_mult : gA.IsMultiplicative := by + refine IsMultiplicative.iff_ne_zero.mpr ⟨by simp [gA_apply, gN_one], fun {m n} hm hn h => ?_⟩ + simp only [gA_apply, gN_mul hm hn h, Nat.cast_mul] + +/-- `χ₄` as an arithmetic function -/ +private def χA : ArithmeticFunction ℤ := toArithmeticFunction (fun n : ℕ => ZMod.χ₄ (n : ZMod 4)) + +/-- Values of `χA`. -/ +private theorem χA_apply {n : ℕ} (hn : n ≠ 0) : χA n = ZMod.χ₄ (n : ZMod 4) := by + simp [χA, toArithmeticFunction, hn] + +/-- `χA` is multiplicative. -/ +private theorem χA_mult : χA.IsMultiplicative := + DirichletCharacter.isMultiplicative_toArithmeticFunction (N := 4) ZMod.χ₄ + +/-- indicator of odd numbers -/ +private def oA : ArithmeticFunction ℤ := ⟨fun n => if Odd n then 1 else 0, by simp⟩ + +/-- Values of `oA`. -/ +private theorem oA_apply (n : ℕ) : oA n = if Odd n then 1 else 0 := rfl + +/-- `oA` is multiplicative. -/ +private theorem oA_mult : oA.IsMultiplicative := by + refine IsMultiplicative.iff_ne_zero.mpr ⟨by simp [oA_apply], fun {m n} _ _ _ => ?_⟩ + simp only [oA_apply, Nat.odd_mul] + by_cases h1 : Odd m <;> by_cases h2 : Odd n <;> simp [h1, h2] + +/-- Dirichlet convolution at a prime power. -/ +private theorem mul_prime_pow (f g : ArithmeticFunction ℤ) {p : ℕ} (hp : p.Prime) (i : ℕ) : + (f * g) (p ^ i) = ∑ j ∈ Finset.range (i + 1), f (p ^ j) * g (p ^ (i - j)) := by + rw [mul_apply, Nat.sum_divisorsAntidiagonal (fun x y => f x * g y), Nat.divisors_prime_pow hp, + Finset.sum_map] + refine Finset.sum_congr rfl fun j hj => ?_ + simp only [Function.Embedding.coeFn_mk] + rw [Nat.pow_div (by simpa [Nat.lt_succ_iff] using hj) hp.pos] + +/-- `χ₄` is completely multiplicative on powers. -/ +private theorem χ₄_pow (p j : ℕ) : ZMod.χ₄ ((p ^ j : ℕ) : ZMod 4) = ZMod.χ₄ (p : ZMod 4) ^ j := by + rw [Nat.cast_pow, map_pow] + +/-- `(-1)^i + 2 ∑_{1 ≤ j ≤ i} (-1)^{i-j} = 1`. -/ +private theorem sum_alt (i : ℕ) : + ∑ j ∈ Finset.range (i + 1), ((if j = 0 then 1 else 2 : ℤ)) * (-1) ^ (i - j) = 1 := by + induction i with + | zero => simp + | succ i ih => + rw [Finset.sum_range_succ, Nat.sub_self, pow_zero, if_neg (by omega), mul_one] + have : ∑ j ∈ Finset.range (i + 1), ((if j = 0 then 1 else 2 : ℤ)) * (-1) ^ (i + 1 - j) = + -∑ j ∈ Finset.range (i + 1), ((if j = 0 then 1 else 2 : ℤ)) * (-1) ^ (i - j) := by + rw [← Finset.sum_neg_distrib] + refine Finset.sum_congr rfl fun j hj => ?_ + have hj' : j ≤ i := Nat.lt_succ_iff.mp (Finset.mem_range.mp hj) + rw [show i + 1 - j = (i - j) + 1 by omega, pow_succ] + ring + rw [this, ih]; norm_num + +/-- The key identity `g * χ₄ = 1_odd`. -/ +private theorem gA_mul_χA : gA * χA = oA := by + rw [IsMultiplicative.eq_iff_eq_on_prime_powers _ (gA_mult.mul χA_mult) _ oA_mult] + intro p i hp + rw [mul_prime_pow _ _ hp] + rcases Nat.Prime.eq_two_or_odd hp with h2 | hodd + · -- p = 2 + subst h2 + rcases Nat.eq_zero_or_pos i with hi | hi + · subst hi; simp [gA_apply, gN_one, χA_apply, oA_apply] + · rw [oA_apply, if_neg (by rw [Nat.not_odd_iff_even]; exact (Nat.even_pow' hi.ne').mpr even_two)] + refine Finset.sum_eq_zero fun j hj => ?_ + have hj' : j ≤ i := Nat.lt_succ_iff.mp (Finset.mem_range.mp hj) + rcases Nat.eq_zero_or_pos j with hj0 | hj0 + · subst hj0 + rw [Nat.sub_zero, χA_apply (by positivity), χ₄_pow, ZMod.χ₄_nat_eq_if_mod_four 2] + simp [hi.ne'] + · rw [gA_apply, gN_prime_pow Nat.prime_two hj0.ne']; simp + · have hpo : Odd p := Nat.odd_iff.mpr hodd + rw [oA_apply, if_pos (hpo.pow)] + have hmod : p % 4 = 1 ∨ p % 4 = 3 := by omega + rcases hmod with h1 | h3 + · rw [Finset.sum_eq_single 0] + · rw [pow_zero, gA_apply, gN_one, Nat.sub_zero, χA_apply (pow_pos hp.pos _).ne', χ₄_pow, + ZMod.χ₄_nat_one_mod_four h1] + simp + · intro j _ hj0 + rw [gA_apply, gN_prime_pow hp hj0, if_neg (by omega)]; simp + · intro h; simp at h + · have : ∀ j ∈ Finset.range (i + 1), gA (p ^ j) * χA (p ^ (i - j)) = + ((if j = 0 then 1 else 2 : ℤ)) * (-1) ^ (i - j) := by + intro j _ + rw [χA_apply (pow_pos hp.pos _).ne', χ₄_pow, ZMod.χ₄_nat_three_mod_four h3, gA_apply] + by_cases hj0 : j = 0 + · subst hj0; simp [gN_one] + · rw [gN_prime_pow hp hj0, if_pos h3, if_neg hj0]; simp + rw [Finset.sum_congr rfl this, sum_alt] + +/-- partial sums of `χ₄` -/ +private theorem χA_partial (k : ℕ) : + ∑ m ∈ Finset.Ioc 0 k, χA m = if k % 4 = 1 ∨ k % 4 = 2 then 1 else 0 := by + induction k with + | zero => simp + | succ k ih => + rw [Finset.sum_Ioc_succ_top (Nat.zero_le k), ih, χA_apply (by omega), + ZMod.χ₄_nat_eq_if_mod_four (k + 1)] + split_ifs <;> omega + +/-- Partial sums of `χ₄` are nonnegative. -/ +private theorem χA_partial_nonneg (k : ℕ) : 0 ≤ ∑ m ∈ Finset.Ioc 0 k, χA m := by + rw [χA_partial]; split_ifs <;> norm_num + +/-- `∑_{N/2 < n ≤ N} g(n) ≤ N`, from `g * χ₄ = 1_odd`. -/ +private theorem window_le (N : ℕ) : ∑ n ∈ Finset.Ioc (N / 2) N, (gN n : ℤ) ≤ N := by + have key := sum_Ioc_mul_eq_sum_sum gA χA N + rw [gA_mul_χA] at key + have hL : ∑ n ∈ Finset.Ioc 0 N, oA n ≤ N := by + calc ∑ n ∈ Finset.Ioc 0 N, oA n ≤ ∑ n ∈ Finset.Ioc 0 N, (1 : ℤ) := by + apply Finset.sum_le_sum; intro n _; rw [oA_apply]; split_ifs <;> norm_num + _ = N := by simp + have hR : ∑ n ∈ Finset.Ioc (N / 2) N, (gN n : ℤ) ≤ + ∑ n ∈ Finset.Ioc 0 N, gA n * ∑ m ∈ Finset.Ioc 0 (N / n), χA m := by + calc ∑ n ∈ Finset.Ioc (N / 2) N, (gN n : ℤ) + = ∑ n ∈ Finset.Ioc (N / 2) N, gA n * ∑ m ∈ Finset.Ioc 0 (N / n), χA m := by + refine Finset.sum_congr rfl fun n hn => ?_ + rw [Finset.mem_Ioc] at hn + have hdiv : N / n = 1 := by + apply Nat.div_eq_of_lt_le + · omega + · have := (Nat.div_lt_iff_lt_mul (by norm_num : 0 < 2)).mp hn.1; omega + rw [hdiv, χA_partial, gA_apply]; norm_num + _ ≤ ∑ n ∈ Finset.Ioc 0 N, gA n * ∑ m ∈ Finset.Ioc 0 (N / n), χA m := by + apply Finset.sum_le_sum_of_subset_of_nonneg + · exact Finset.Ioc_subset_Ioc (Nat.zero_le _) le_rfl + · intro n _ _ + exact mul_nonneg (by rw [gA_apply]; positivity) (χA_partial_nonneg _) + linarith + +/-- `∑_{n ≤ N} g(n) ≤ 2 N`. -/ +private theorem partial_le (N : ℕ) : ∑ n ∈ Finset.Ioc 0 N, gN n ≤ 2 * N := by + induction N using Nat.strong_induction_on with + | _ N ih => + rcases Nat.eq_zero_or_pos N with h0 | hpos + · subst h0; simp + · have h1 := ih (N / 2) (Nat.div_lt_self hpos (by norm_num)) + have h2 := window_le N + have h3 : ∑ n ∈ Finset.Ioc (N / 2) N, gN n ≤ N := by exact_mod_cast h2 + rw [← Finset.sum_Ioc_consecutive _ (Nat.zero_le (N / 2)) (Nat.div_le_self N 2)] + have : 2 * (N / 2) ≤ N := Nat.mul_div_le N 2 + omega + +/-- `Icc 1 N = Ioc 0 N`. -/ +private theorem Icc_eq_Ioc (N : ℕ) : Finset.Icc 1 N = Finset.Ioc 0 N := by + ext n; simp; omega + +/-- `χ₄` as a complex Dirichlet character -/ +private noncomputable def χC : DirichletCharacter ℂ 4 := ZMod.χ₄.ringHomComp (Int.castRingHom ℂ) + +/-- Values of `χC`. -/ +private theorem χC_apply (n : ℕ) : χC (n : ZMod 4) = ((ZMod.χ₄ (n : ZMod 4) : ℤ) : ℂ) := by + simp [χC, MulChar.ringHomComp_apply] + +/-- `χ₄` is not the trivial character. -/ +private theorem χC_ne_one : χC ≠ 1 := by + intro h + have h3 : χC ((3 : ℕ) : ZMod 4) = 1 := by + rw [h]; apply MulChar.one_apply + rw [ZMod.isUnit_iff_coprime]; norm_num + rw [χC_apply, ZMod.χ₄_nat_three_mod_four (by norm_num)] at h3 + norm_num at h3 + +/-- The trivial character mod `4` is the indicator of odd numbers. -/ +private theorem one_char_apply (n : ℕ) : (1 : DirichletCharacter ℂ 4) (n : ZMod 4) = if Odd n then 1 else 0 := by + have hu : IsUnit (n : ZMod 4) ↔ Odd n := by + rw [ZMod.isUnit_iff_coprime, show (4 : ℕ) = 2 ^ 2 by norm_num, + Nat.coprime_pow_right_iff (by norm_num), Nat.coprime_two_right] + by_cases h : Odd n + · rw [if_pos h, MulChar.one_apply (hu.mpr h)] + · rw [if_neg h, MulChar.map_nonunit _ (fun h' => h (hu.mp h'))] + +/-- The L-series of `g` converges absolutely for `re s > 1`. -/ +private theorem LSeriesSummable_g {s : ℂ} (hs : 1 < s.re) : LSeriesSummable (fun n => (gN n : ℂ)) s := by + refine LSeriesSummable_of_sum_norm_bigO (r := 1) ?_ zero_le_one (by simpa using hs) + refine Asymptotics.IsBigO.of_bound 2 (Filter.Eventually.of_forall fun n => ?_) + simp only [Complex.norm_natCast, Real.rpow_one, Real.norm_eq_abs] + rw [abs_of_nonneg (Finset.sum_nonneg fun _ _ => by positivity), abs_of_nonneg (by positivity), + Icc_eq_Ioc] + exact_mod_cast partial_le n + +/-- `L(g, s) L(s, χ₄) = L(s, χ₀)` for `re s > 1`. -/ +private theorem LSeries_identity {s : ℂ} (hs : 1 < s.re) : + LSeries (fun n => (gN n : ℂ)) s * DirichletCharacter.LFunction χC s = + DirichletCharacter.LFunction (1 : DirichletCharacter ℂ 4) s := by + rw [DirichletCharacter.LFunction_eq_LSeries _ hs, DirichletCharacter.LFunction_eq_LSeries _ hs] + have hg : LSeries (fun n => (gN n : ℂ)) s = LSeries ↗(gA : ArithmeticFunction ℂ) s := + LSeries_congr (fun {n} _ => by simp [intCoe_apply, gA_apply]) s + have hχ : LSeries (fun n => χC n) s = LSeries ↗(χA : ArithmeticFunction ℂ) s := + LSeries_congr (fun {n} hn => by simp [intCoe_apply, χA_apply hn, χC_apply]) s + have ho : LSeries (fun n => (1 : DirichletCharacter ℂ 4) n) s = + LSeries ↗(oA : ArithmeticFunction ℂ) s := + LSeries_congr (fun {n} _ => by + rw [one_char_apply, intCoe_apply, oA_apply]; split_ifs <;> simp) s + have hsg : LSeriesSummable ↗(gA : ArithmeticFunction ℂ) s := + (LSeriesSummable_congr s (fun {n} _ => by simp [intCoe_apply, gA_apply])).mp + (LSeriesSummable_g hs) + have hsχ : LSeriesSummable ↗(χA : ArithmeticFunction ℂ) s := + (LSeriesSummable_congr s (fun {n} hn => by simp [intCoe_apply, χA_apply hn, χC_apply])).mp + (DirichletCharacter.LSeriesSummable_of_one_lt_re χC hs) + rw [hg, hχ, ho, ← ArithmeticFunction.LSeries_mul' hsg hsχ, ← intCoe_mul, gA_mul_χA] + +/-- the paired terms of the L-series of `χ₄` -/ +private noncomputable def uu (σ : ℝ) (m : ℕ) : ℝ := ((4 * m + 1 : ℝ) ^ σ)⁻¹ - ((4 * m + 3 : ℝ) ^ σ)⁻¹ + +/-- `∑ (4m + k)^{-σ}` converges for `σ > 1`. -/ +private theorem summable_shift {σ : ℝ} (hσ : 1 < σ) (k : ℝ) (hk : 1 ≤ k) : + Summable (fun m : ℕ => ((4 * m + k : ℝ) ^ σ)⁻¹) := by + have h1 : Summable (fun m : ℕ => (((m + 1 : ℕ) : ℝ) ^ σ)⁻¹) := + (summable_nat_add_iff 1).mpr (Real.summable_nat_rpow_inv.mpr hσ) + refine Summable.of_nonneg_of_le (fun m => by positivity) (fun m => ?_) h1 + apply inv_anti₀ (by positivity) + apply Real.rpow_le_rpow (by positivity) _ (by linarith) + push_cast; linarith [(Nat.cast_nonneg m : (0:ℝ) ≤ m)] + +/-- For real `σ > 1`, `L(σ, χ₄) = ∑ ((4m+1)^{-σ} - (4m+3)^{-σ})`. -/ +private theorem LSeries_χC_real {σ : ℝ} (hσ : 1 < σ) : + LSeries (fun n => χC n) σ = ((∑' m, uu σ m : ℝ) : ℂ) := by + have hsum : Summable (LSeries.term (fun n => χC n) σ) := + DirichletCharacter.LSeriesSummable_of_one_lt_re χC (by simpa using hσ) + rw [LSeries, Nat.sumByResidueClasses hsum 4] + rw [show (∑ j : ZMod 4, ∑' m, LSeries.term (fun n => χC n) σ (j.val + 4 * m)) = + ∑' m, LSeries.term (fun n => χC n) σ (0 + 4 * m) + ∑' m, LSeries.term (fun n => χC n) σ (1 + 4 * m) + + ∑' m, LSeries.term (fun n => χC n) σ (2 + 4 * m) + ∑' m, LSeries.term (fun n => χC n) σ (3 + 4 * m) + from Fin.sum_univ_four (fun j : Fin 4 => ∑' m, LSeries.term (fun n => χC n) σ (j.val + 4 * m))] + have hcp : ∀ n : ℕ, (n : ℂ) ^ (σ : ℂ) = (((n : ℝ) ^ σ : ℝ) : ℂ) := by + intro n; rw [Complex.ofReal_cpow (Nat.cast_nonneg n)]; simp + have h0 : ∀ m : ℕ, LSeries.term (fun n => χC n) σ (0 + 4 * m) = 0 := by + intro m + rw [LSeries.term_def]; split_ifs with h + · rfl + · rw [χC_apply, ZMod.χ₄_nat_eq_if_mod_four, if_pos (by omega)]; simp + have h2 : ∀ m : ℕ, LSeries.term (fun n => χC n) σ (2 + 4 * m) = 0 := by + intro m + rw [LSeries.term_def]; split_ifs with h + · rfl + · rw [χC_apply, ZMod.χ₄_nat_eq_if_mod_four, if_pos (by omega)]; simp + have h1 : ∀ m : ℕ, LSeries.term (fun n => χC n) σ (1 + 4 * m) = + ((((4 * m + 1 : ℝ) ^ σ)⁻¹ : ℝ) : ℂ) := by + intro m + rw [LSeries.term_def, if_neg (by omega), χC_apply, ZMod.χ₄_nat_one_mod_four (by omega), hcp] + push_cast; ring_nf + have h3 : ∀ m : ℕ, LSeries.term (fun n => χC n) σ (3 + 4 * m) = + -((((4 * m + 3 : ℝ) ^ σ)⁻¹ : ℝ) : ℂ) := by + intro m + rw [LSeries.term_def, if_neg (by omega), χC_apply, ZMod.χ₄_nat_three_mod_four (by omega), hcp] + push_cast; ring_nf + simp_rw [h0, h1, h2, h3, tsum_zero, zero_add, add_zero, tsum_neg, ← Complex.ofReal_tsum] + rw [← Complex.ofReal_neg, ← Complex.ofReal_add, ← sub_eq_add_neg, + ← (summable_shift hσ 1 le_rfl).tsum_sub (summable_shift hσ 3 (by norm_num))] + rfl + +/-- The paired terms are nonnegative. -/ +private theorem uu_nonneg {σ : ℝ} (hσ : 0 ≤ σ) (m : ℕ) : 0 ≤ uu σ m := by + unfold uu + rw [sub_nonneg] + apply inv_anti₀ (by positivity) + exact Real.rpow_le_rpow (by positivity) (by linarith) hσ + +/-- Uniform bound `0 ≤ uu σ m ≤ 4 / (m + 1)²` for `1 ≤ σ ≤ 2`. -/ +private theorem uu_le {σ : ℝ} (h1 : 1 ≤ σ) (h2 : σ ≤ 2) (m : ℕ) : uu σ m ≤ 4 * (((m + 1 : ℕ) : ℝ) ^ 2)⁻¹ := by + unfold uu + set a : ℝ := 4 * m + 1 with ha + set b : ℝ := 4 * m + 3 with hb + have ha1 : 1 ≤ a := by rw [ha]; linarith [(Nat.cast_nonneg m : (0:ℝ) ≤ m)] + have hb1 : 0 < b := by rw [hb]; linarith [(Nat.cast_nonneg m : (0:ℝ) ≤ m)] + have hab : b = a + 2 := by rw [ha, hb]; ring + -- Bernoulli + have hbern : 1 + σ * (a / b - 1) ≤ (a / b) ^ σ := by + have := one_add_mul_self_le_rpow_one_add (s := a / b - 1) (by + have : 0 ≤ a / b := by positivity + linarith) h1 + simpa using this + rw [Real.div_rpow (by linarith) hb1.le] at hbern + have haσ : 0 < a ^ σ := by positivity + have hbσ : 0 < b ^ σ := by positivity + have hkey : (a ^ σ)⁻¹ - (b ^ σ)⁻¹ = (a ^ σ)⁻¹ * (1 - a ^ σ / b ^ σ) := by + field_simp + rw [hkey] + have hinv : (a ^ σ)⁻¹ ≤ a⁻¹ := by + apply inv_anti₀ (by linarith) + calc a = a ^ (1:ℝ) := (Real.rpow_one a).symm + _ ≤ a ^ σ := Real.rpow_le_rpow_of_exponent_le ha1 h1 + have hfac : 1 - a ^ σ / b ^ σ ≤ σ * (2 / b) := by + have : a / b - 1 = -(2 / b) := by rw [hab]; field_simp; ring + rw [this] at hbern; linarith + have hfac0 : 0 ≤ 1 - a ^ σ / b ^ σ := by + rw [sub_nonneg, div_le_one hbσ] + exact Real.rpow_le_rpow (by linarith) (by linarith) (by linarith) + calc (a ^ σ)⁻¹ * (1 - a ^ σ / b ^ σ) ≤ a⁻¹ * (σ * (2 / b)) := + mul_le_mul hinv hfac hfac0 (by positivity) + _ ≤ a⁻¹ * (2 * (2 / a)) := by + apply mul_le_mul_of_nonneg_left _ (by positivity) + apply mul_le_mul h2 _ (by positivity) (by norm_num) + apply div_le_div_of_nonneg_left (by norm_num) (by linarith) (by linarith) + _ = 4 * (a ^ 2)⁻¹ := by field_simp; ring + _ ≤ 4 * (((m + 1 : ℕ) : ℝ) ^ 2)⁻¹ := by + apply mul_le_mul_of_nonneg_left _ (by norm_num) + apply inv_anti₀ (by positivity) + apply pow_le_pow_left₀ (by positivity) + rw [ha]; push_cast; linarith [(Nat.cast_nonneg m : (0:ℝ) ≤ m)] + +/-- The paired terms at `σ = 1`. -/ +private theorem uu_one (m : ℕ) : uu 1 m = 1 / (4 * m + 1) - 1 / (4 * m + 3) := by + simp [uu, Real.rpow_one] + +/-- Partial sums of the paired terms are partial sums of the Leibniz series. -/ +private theorem partial_uu (K : ℕ) : ∑ m ∈ Finset.range K, uu 1 m = + ∑ i ∈ Finset.range (2 * K), (-1 : ℝ) ^ i / (2 * i + 1) := by + induction K with + | zero => simp + | succ K ih => + rw [Finset.sum_range_succ, ih, show 2 * (K + 1) = 2 * K + 1 + 1 by ring, + Finset.sum_range_succ, Finset.sum_range_succ, uu_one] + rw [pow_succ, pow_mul] + push_cast + ring + +/-- `∑ (1/(4m+1) - 1/(4m+3)) = π / 4`. -/ +private theorem tsum_uu_one : ∑' m, uu 1 m = Real.pi / 4 := by + apply HasSum.tsum_eq + rw [hasSum_iff_tendsto_nat_of_nonneg (uu_nonneg zero_le_one)] + simp_rw [partial_uu] + exact Real.tendsto_sum_pi_div_four.comp + (Filter.tendsto_id.const_mul_atTop' (by norm_num : 0 < 2)) + +/-- `∑ uu σ m → π / 4` as `σ → 1⁺` (dominated convergence). -/ +private theorem tendsto_tsum_uu : + Filter.Tendsto (fun σ : ℝ => ∑' m, uu σ m) (nhdsWithin 1 (Set.Ioi 1)) + (nhds (Real.pi / 4)) := by + rw [← tsum_uu_one] + refine tendsto_tsum_of_dominated_convergence (bound := fun m => 4 * (((m + 1 : ℕ) : ℝ) ^ 2)⁻¹) + ?_ ?_ ?_ + · refine Summable.mul_left 4 ?_ + have := (summable_nat_add_iff 1).mpr (Real.summable_nat_pow_inv.mpr (by norm_num : 1 < 2)) + exact this + · intro m + have hc : ContinuousAt (fun σ : ℝ => uu σ m) 1 := by + unfold uu + apply ContinuousAt.sub + · exact ((continuousAt_const.rpow continuousAt_id (Or.inl (by positivity))).inv₀ + (by positivity)) + · exact ((continuousAt_const.rpow continuousAt_id (Or.inl (by positivity))).inv₀ + (by positivity)) + exact hc.tendsto.mono_left nhdsWithin_le_nhds + · have : Set.Ioo (1:ℝ) 2 ∈ nhdsWithin (1:ℝ) (Set.Ioi 1) := Ioo_mem_nhdsGT (by norm_num) + filter_upwards [this] with σ hσ + intro m + rw [Real.norm_eq_abs, abs_of_nonneg (uu_nonneg (by linarith [hσ.1]) m)] + exact uu_le hσ.1.le hσ.2.le m + +/-- `L(1, χ₄) = π / 4`. -/ +private theorem LFunction_χC_one : DirichletCharacter.LFunction χC 1 = (Real.pi / 4 : ℝ) := by + have hcont : ContinuousAt (DirichletCharacter.LFunction χC) 1 := + (DirichletCharacter.differentiableAt_LFunction χC 1 (Or.inr χC_ne_one)).continuousAt + have h1 : Filter.Tendsto (fun σ : ℝ => DirichletCharacter.LFunction χC σ) + (nhdsWithin 1 (Set.Ioi 1)) (nhds (DirichletCharacter.LFunction χC 1)) := by + have : Filter.Tendsto (fun σ : ℝ => (σ : ℂ)) (nhdsWithin 1 (Set.Ioi 1)) (nhds ((1:ℝ) : ℂ)) := + (Complex.continuous_ofReal.tendsto 1).mono_left nhdsWithin_le_nhds + rw [Complex.ofReal_one] at this + exact hcont.tendsto.comp this + have h2 : Filter.Tendsto (fun σ : ℝ => DirichletCharacter.LFunction χC σ) + (nhdsWithin 1 (Set.Ioi 1)) (nhds ((Real.pi / 4 : ℝ) : ℂ)) := by + have := (Complex.continuous_ofReal.tendsto _).comp tendsto_tsum_uu + refine this.congr' ?_ + filter_upwards [self_mem_nhdsWithin] with σ hσ + simp only [Function.comp] + rw [DirichletCharacter.LFunction_eq_LSeries _ (by simpa using hσ), LSeries_χC_real hσ] + exact tendsto_nhds_unique h1 h2 + +/-- the holomorphic function `T(s) / (s L(s, χ₄))`, where `T(s) = (s - 1) L(s, χ₀)` -/ +private noncomputable def HH (s : ℂ) : ℂ := + DirichletCharacter.LFunctionTrivChar₁ 4 s / (s * DirichletCharacter.LFunction χC s) + +/-- `(s - 1) L(s, χ₀)` at `s = 1` equals `1 / 2`. -/ +private theorem T_one : DirichletCharacter.LFunctionTrivChar₁ 4 1 = 1 / 2 := by + simp only [DirichletCharacter.LFunctionTrivChar₁, Function.update_self] + rw [show (4 : ℕ) = 2 ^ 2 by norm_num, Nat.primeFactors_prime_pow (by norm_num) Nat.prime_two] + norm_num + +/-- `HH 1 = 2 / π`. -/ +private theorem HH_one : HH 1 = ((2 / Real.pi : ℝ) : ℂ) := by + rw [HH, T_one, LFunction_χC_one, one_mul] + have : (Real.pi : ℂ) ≠ 0 := by exact_mod_cast Real.pi_ne_zero + push_cast + field_simp + norm_num + +/-- The set where `s ≠ 0` and `L(s, χ₄) ≠ 0` is open. -/ +private theorem open_U : IsOpen {s : ℂ | s ≠ 0 ∧ DirichletCharacter.LFunction χC s ≠ 0} := by + apply IsOpen.inter (isOpen_ne) + exact isOpen_ne_fun (DirichletCharacter.differentiable_LFunction χC_ne_one).continuous + continuous_const + +/-- The closed half plane `re s ≥ 1` lies in that open set. -/ +private theorem half_plane_sub_U : {s : ℂ | 1 ≤ s.re} ⊆ {s : ℂ | s ≠ 0 ∧ DirichletCharacter.LFunction χC s ≠ 0} := by + intro s hs + refine ⟨fun h => ?_, DirichletCharacter.LFunction_ne_zero_of_one_le_re χC (Or.inl χC_ne_one) hs⟩ + rw [h] at hs; simp at hs; linarith + +/-- `HH` is holomorphic on that open set. -/ +private theorem differentiableOn_HH : + DifferentiableOn ℂ HH {s : ℂ | s ≠ 0 ∧ DirichletCharacter.LFunction χC s ≠ 0} := by + intro s hs + apply DifferentiableAt.differentiableWithinAt + apply DifferentiableAt.div + · exact DirichletCharacter.differentiable_LFunctionTrivChar₁ 4 s + · exact differentiableAt_id.mul (DirichletCharacter.differentiable_LFunction χC_ne_one s) + · exact mul_ne_zero hs.1 hs.2 + +/-- `dslope HH 1` is continuous on `re s ≥ 1`. -/ +private theorem continuousOn_G : ContinuousOn (dslope HH 1) {s : ℂ | 1 ≤ s.re} := by + have hU : {s : ℂ | s ≠ 0 ∧ DirichletCharacter.LFunction χC s ≠ 0} ∈ nhds (1 : ℂ) := + open_U.mem_nhds (half_plane_sub_U (by simp)) + have := (Complex.differentiableOn_dslope hU).mpr differentiableOn_HH + exact this.continuousOn.mono half_plane_sub_U + +/-- `L(g, s) / s - (2/π) / (s - 1) = dslope HH 1 s` for `re s > 1`. -/ +private theorem G_eq {s : ℂ} (hs : 1 < s.re) : + LSeries (fun n => ((gN n : ℝ) : ℂ)) s / s - ((2 / Real.pi : ℝ) : ℂ) / (s - 1) = dslope HH 1 s := by + have hs1 : s ≠ 1 := by intro h; rw [h] at hs; simp at hs + have hs0 : s ≠ 0 := by intro h; rw [h] at hs; simp at hs; linarith + have hs1' : s - 1 ≠ 0 := sub_ne_zero.mpr hs1 + have hL : DirichletCharacter.LFunction χC s ≠ 0 := + DirichletCharacter.LFunction_ne_zero_of_one_le_re χC (Or.inl χC_ne_one) hs.le + have hid := LSeries_identity hs + have hT : DirichletCharacter.LFunctionTrivChar₁ 4 s = + (s - 1) * DirichletCharacter.LFunction (1 : DirichletCharacter ℂ 4) s := by + simp only [DirichletCharacter.LFunctionTrivChar₁, Function.update_of_ne hs1] + have hg : LSeries (fun n => ((gN n : ℝ) : ℂ)) s = LSeries (fun n => (gN n : ℂ)) s := by + congr 1 + rw [dslope_of_ne _ hs1, slope_def_field, ← HH_one, hg] + unfold HH + rw [hT, ← hid] + field_simp + +end Arith + +namespace Fin1 + +open Filter Topology + +/-- `⌊J / k⌋ / J → 1 / k` -/ +private theorem tendsto_div_nat_div (k : ℕ) (hk : 0 < k) : + Tendsto (fun J : ℕ => ((J / k : ℕ) : ℝ) / J) atTop (𝓝 (1 / k)) := by + have hk' : (0 : ℝ) < k := by exact_mod_cast hk + have hup : ∀ J : ℕ, ((J / k : ℕ) : ℝ) / J ≤ 1 / k := by + intro J + rcases Nat.eq_zero_or_pos J with rfl | hJ + · simp + · have hJ' : (0 : ℝ) < J := by exact_mod_cast hJ + rw [div_le_div_iff₀ hJ' hk', one_mul] + have := Nat.cast_div_le (m := J) (n := k) (α := ℝ) + rw [le_div_iff₀ hk'] at this + linarith + have hlow : ∀ J : ℕ, 0 < J → 1 / k - 1 / J ≤ ((J / k : ℕ) : ℝ) / J := by + intro J hJ + have hJ' : (0 : ℝ) < J := by exact_mod_cast hJ + have h1 : (J : ℝ) < ((J / k : ℕ) + 1) * k := by + have := Nat.lt_div_mul_add (a := J) hk + exact_mod_cast (by linarith [this] : J < (J / k + 1) * k) + rw [div_sub_div _ _ hk'.ne' hJ'.ne', div_le_div_iff₀ (by positivity) hJ'] + nlinarith + have hlim : Tendsto (fun J : ℕ => 1 / (k : ℝ) - 1 / J) atTop (𝓝 (1 / k)) := by + have := tendsto_one_div_atTop_nhds_zero_nat (𝕜 := ℝ) + simpa using (tendsto_const_nhds (x := 1 / (k : ℝ))).sub this + refine tendsto_of_tendsto_of_tendsto_of_le_of_le' hlim tendsto_const_nhds ?_ + (Eventually.of_forall hup) + filter_upwards [eventually_gt_atTop 0] with J hJ using hlow J hJ + +/-- `J / k → ∞`. -/ +private theorem tendsto_div_nat_atTop (k : ℕ) (hk : 0 < k) : Tendsto (fun J : ℕ => J / k) atTop atTop := by + rw [tendsto_atTop_atTop] + intro b + refine ⟨b * k, fun J hJ => ?_⟩ + exact (Nat.le_div_iff_mul_le hk).mpr hJ + +/-- composition: if `R M / M → c` then `R (J / k) / J → c / k` -/ +private theorem tendsto_comp_div (R : ℕ → ℝ) (hR0 : R 0 = 0) {c : ℝ} + (hRlim : Tendsto (fun M : ℕ => R M / M) atTop (𝓝 c)) (k : ℕ) (hk : 0 < k) : + Tendsto (fun J : ℕ => R (J / k) / J) atTop (𝓝 (c * (1 / k))) := by + have h1 := (hRlim.comp (tendsto_div_nat_atTop k hk)).mul (tendsto_div_nat_div k hk) + refine h1.congr (fun J => ?_) + simp only [Function.comp] + by_cases hM : J / k = 0 + · rw [hM, hR0]; simp + · have hM' : ((J / k : ℕ) : ℝ) ≠ 0 := by exact_mod_cast hM + field_simp + +/-- If `R(M)/M → c` with `0 ≤ R(M) ≤ C M`, then `(∑ᵢ R(J / 2^i)) / J → 2 c`. -/ +private theorem dyadic (R : ℕ → ℝ) (C c : ℝ) (hR0 : R 0 = 0) (hRnn : ∀ M, 0 ≤ R M) + (hRle : ∀ M, R M ≤ C * M) (hRlim : Tendsto (fun M : ℕ => R M / M) atTop (𝓝 c)) : + Tendsto (fun J : ℕ => (∑' i : ℕ, R (J / 2 ^ i)) / J) atTop (𝓝 (2 * c)) := by + have hC : 0 ≤ C := by have := hRle 1; have := hRnn 1; simp at *; linarith + have hsum : Summable (fun i : ℕ => C * (1 / 2 : ℝ) ^ i) := + (summable_geometric_two).mul_left C + have hlim : Tendsto (fun J : ℕ => ∑' i : ℕ, R (J / 2 ^ i) / J) atTop + (𝓝 (∑' i : ℕ, c * (1 / 2 : ℝ) ^ i)) := by + refine tendsto_tsum_of_dominated_convergence hsum (fun i => ?_) ?_ + · have := tendsto_comp_div R hR0 hRlim (2 ^ i) (pow_pos (by norm_num) i) + simpa [one_div, inv_pow] using this + · refine Eventually.of_forall fun J i => ?_ + rw [Real.norm_eq_abs, abs_of_nonneg (div_nonneg (hRnn _) (Nat.cast_nonneg _))] + rcases Nat.eq_zero_or_pos J with rfl | hJ + · simp; positivity + have hJ' : (0 : ℝ) < J := by exact_mod_cast hJ + rw [div_le_iff₀ hJ'] + calc R (J / 2 ^ i) ≤ C * ((J / 2 ^ i : ℕ) : ℝ) := hRle _ + _ ≤ C * ((J : ℝ) / 2 ^ i) := by + apply mul_le_mul_of_nonneg_left _ hC + have := Nat.cast_div_le (m := J) (n := 2 ^ i) (α := ℝ) + simpa using this + _ = C * (1 / 2) ^ i * J := by rw [one_div, inv_pow]; field_simp + rw [tsum_mul_left, tsum_geometric_two, mul_comm] at hlim + refine hlim.congr (fun J => ?_) + rw [tsum_div_const] + +end Fin1 + +namespace Comb + +open Math0.Statements.A354571 + +/-- number of coprime ordered factorizations `N = x * y` -/ +private def UU (N : ℕ) : ℕ := ((Nat.divisorsAntidiagonal N).filter (fun p => Nat.Coprime p.1 p.2)).card + +/-- number of coprime factorizations `N = x * y` with `x < y` -/ +private def UC (N : ℕ) : ℕ := + ((Nat.divisorsAntidiagonal N).filter (fun p => Nat.Coprime p.1 p.2 ∧ p.1 < p.2)).card + +/-- `UU 1 = 1`. -/ +private theorem UU_one : UU 1 = 1 := by decide + +/-- `UU (p^n a) = 2 UU a` for `p ∤ a`. -/ +private theorem UU_prime_pow_mul {p a n : ℕ} (hp : p.Prime) (hpa : ¬ p ∣ a) (hn : 0 < n) : + UU (p ^ n * a) = 2 * UU a := by + classical + have ha0 : a ≠ 0 := by rintro rfl; exact hpa (dvd_zero p) + have hpn : 0 < p ^ n := pow_pos hp.pos n + have hpa0 : p ^ n * a ≠ 0 := Nat.mul_ne_zero hpn.ne' ha0 + set A := (Nat.divisorsAntidiagonal a).filter (fun q => Nat.Coprime q.1 q.2) with hA + set f₁ : ℕ × ℕ → ℕ × ℕ := fun q => (p ^ n * q.1, q.2) with hf₁ + set f₂ : ℕ × ℕ → ℕ × ℕ := fun q => (q.1, p ^ n * q.2) with hf₂ + have hinj₁ : Function.Injective f₁ := by + intro x y h + simp only [hf₁, Prod.mk.injEq] at h + exact Prod.ext (Nat.eq_of_mul_eq_mul_left hpn h.1) h.2 + have hinj₂ : Function.Injective f₂ := by + intro x y h + simp only [hf₂, Prod.mk.injEq] at h + exact Prod.ext h.1 (Nat.eq_of_mul_eq_mul_left hpn h.2) + have hcopn : ∀ y, y ∣ a → Nat.Coprime (p ^ n) y := by + intro y hy + apply Nat.Coprime.pow_left + exact (Nat.Prime.coprime_iff_not_dvd hp).mpr (fun h => hpa (h.trans hy)) + have hS : (Nat.divisorsAntidiagonal (p ^ n * a)).filter (fun q => Nat.Coprime q.1 q.2) = + A.image f₁ ∪ A.image f₂ := by + ext ⟨u, v⟩ + simp only [Finset.mem_filter, Nat.mem_divisorsAntidiagonal, Finset.mem_union, + Finset.mem_image, hA, hf₁, hf₂, Prod.mk.injEq, Prod.exists] + constructor + · rintro ⟨⟨huv, -⟩, hcop⟩ + have hpuv : p ∣ u * v := by rw [huv]; exact Dvd.dvd.mul_right (dvd_pow_self p hn.ne') a + rcases (Nat.Prime.dvd_mul hp).mp hpuv with hpu | hpv + · have hpv : ¬ p ∣ v := fun h => + (Nat.Prime.coprime_iff_not_dvd hp).mp (Nat.Coprime.coprime_dvd_left hpu hcop) h + have hcv : Nat.Coprime (p ^ n) v := + Nat.Coprime.pow_left n ((Nat.Prime.coprime_iff_not_dvd hp).mpr hpv) + have hdvd : p ^ n ∣ u := hcv.dvd_of_dvd_mul_right (by rw [huv]; exact dvd_mul_right _ _) + obtain ⟨x, rfl⟩ := hdvd + have hxv : x * v = a := by + apply Nat.eq_of_mul_eq_mul_left hpn; rw [← huv]; ring + left + exact ⟨x, v, ⟨⟨hxv, ha0⟩, Nat.Coprime.coprime_mul_left hcop⟩, rfl, rfl⟩ + · have hpu : ¬ p ∣ u := fun h => + (Nat.Prime.coprime_iff_not_dvd hp).mp (Nat.Coprime.coprime_dvd_right hpv hcop).symm h + have hcu : Nat.Coprime (p ^ n) u := + Nat.Coprime.pow_left n ((Nat.Prime.coprime_iff_not_dvd hp).mpr hpu) + have hdvd : p ^ n ∣ v := hcu.dvd_of_dvd_mul_left (by rw [huv]; exact dvd_mul_right _ _) + obtain ⟨y, rfl⟩ := hdvd + have huy : u * y = a := by + apply Nat.eq_of_mul_eq_mul_left hpn; rw [← huv]; ring + right + exact ⟨u, y, ⟨⟨huy, ha0⟩, Nat.Coprime.coprime_mul_left_right hcop⟩, rfl, rfl⟩ + · rintro (⟨x, y, ⟨⟨hxy, -⟩, hcop⟩, rfl, rfl⟩ | ⟨x, y, ⟨⟨hxy, -⟩, hcop⟩, rfl, rfl⟩) + · refine ⟨⟨by rw [← hxy]; ring, hpa0⟩, ?_⟩ + exact Nat.Coprime.mul_left (hcopn y (Dvd.intro_left x hxy)) hcop + · refine ⟨⟨by rw [← hxy]; ring, hpa0⟩, ?_⟩ + exact Nat.Coprime.mul_right (hcopn x (Dvd.intro y hxy)).symm hcop + have hdisj : Disjoint (A.image f₁) (A.image f₂) := by + rw [Finset.disjoint_left] + rintro q h1 h2 + simp only [Finset.mem_image, hA, Finset.mem_filter, Nat.mem_divisorsAntidiagonal, + hf₁, hf₂, Prod.exists] at h1 h2 + obtain ⟨x, y, ⟨⟨hxy, -⟩, -⟩, rfl⟩ := h1 + obtain ⟨x', y', ⟨⟨hxy', -⟩, -⟩, h⟩ := h2 + simp only [Prod.mk.injEq] at h + apply hpa + rw [← hxy', h.1] + exact Dvd.dvd.mul_right (Dvd.dvd.mul_right (dvd_pow_self p hn.ne') x) y' + unfold UU + rw [hS, Finset.card_union_of_disjoint hdisj, Finset.card_image_of_injective _ hinj₁, + Finset.card_image_of_injective _ hinj₂, ← hA] + ring + +/-- `UU N = 2^{ω(N)}`. -/ +private theorem UU_eq (N : ℕ) (hN : N ≠ 0) : UU N = 2 ^ N.primeFactors.card := by + induction N using Nat.recOnPrimePow with + | zero => exact absurd rfl hN + | one => simp [UU_one] + | prime_pow_mul a p n hp hpa hn ih => + have ha0 : a ≠ 0 := by rintro rfl; exact hpa (dvd_zero p) + rw [UU_prime_pow_mul hp hpa hn, ih ha0, Nat.primeFactors_mul (pow_pos hp.pos n).ne' ha0, + Nat.primeFactors_prime_pow hn.ne' hp, Finset.card_union_of_disjoint, Finset.card_singleton, + pow_add, pow_one, mul_comm] + rw [Finset.disjoint_singleton_left] + exact fun h => hpa (Nat.dvd_of_mem_primeFactors h) + +/-- `UU N = 2 UC N + [N = 1]`. -/ +private theorem UU_eq_UC (N : ℕ) : UU N = 2 * UC N + (if N = 1 then 1 else 0) := by + classical + by_cases hN1 : N = 1 + · subst hN1; decide + rw [if_neg hN1, add_zero] + set S := (Nat.divisorsAntidiagonal N).filter (fun p => Nat.Coprime p.1 p.2) with hS + have hUC : UC N = (S.filter (fun q => q.1 < q.2)).card := by + rw [UC, hS, Finset.filter_filter] + have h1 : S.filter (fun q => ¬ q.1 < q.2) = S.filter (fun q => q.2 < q.1) := by + ext ⟨x, y⟩ + simp only [hS, Finset.mem_filter, Nat.mem_divisorsAntidiagonal, not_lt] + constructor + · rintro ⟨⟨⟨hxy, hN0⟩, hcop⟩, hle⟩ + refine ⟨⟨⟨hxy, hN0⟩, hcop⟩, lt_of_le_of_ne hle ?_⟩ + rintro rfl + have : y = 1 := by rwa [Nat.Coprime, Nat.gcd_self] at hcop + subst this; exact hN1 (by rw [← hxy]) + · rintro ⟨h, hlt⟩; exact ⟨h, hlt.le⟩ + have h2 : (S.filter (fun q => q.2 < q.1)).card = (S.filter (fun q => q.1 < q.2)).card := by + apply Finset.card_nbij' Prod.swap Prod.swap + · rintro ⟨x, y⟩ h + rw [Finset.mem_coe] at h ⊢ + simp only [hS, Finset.mem_filter, Nat.mem_divisorsAntidiagonal, Prod.swap_prod_mk] at h ⊢ + exact ⟨⟨⟨by rw [mul_comm]; exact h.1.1.1, h.1.1.2⟩, h.1.2.symm⟩, h.2⟩ + · rintro ⟨x, y⟩ h + rw [Finset.mem_coe] at h ⊢ + simp only [hS, Finset.mem_filter, Nat.mem_divisorsAntidiagonal, Prod.swap_prod_mk] at h ⊢ + exact ⟨⟨⟨by rw [mul_comm]; exact h.1.1.1, h.1.1.2⟩, h.1.2.symm⟩, h.2⟩ + · intro q _; rfl + · intro q _; rfl + have h3 := Finset.card_filter_add_card_filter_not (s := S) (fun q => q.1 < q.2) + rw [h1, h2] at h3 + rw [UU, ← hS, ← h3, hUC]; ring + +/-- In a primitive triple, the leg `b` and the hypotenuse `c` are coprime. -/ +private theorem ppt_coprime {b k c : ℕ} (h : IsPPT b k c) : Nat.Coprime b c := by + obtain ⟨hb, hk, heq, hg⟩ := h + set g := Nat.gcd b c with hgdef + have hgb : g ∣ b := Nat.gcd_dvd_left b c + have hgc : g ∣ c := Nat.gcd_dvd_right b c + have hg2 : g ^ 2 ∣ k ^ 2 := by + have h1 : g ^ 2 ∣ c ^ 2 := pow_dvd_pow_of_dvd hgc 2 + have h2 : g ^ 2 ∣ b ^ 2 := pow_dvd_pow_of_dvd hgb 2 + have : k ^ 2 = c ^ 2 - b ^ 2 := by omega + rw [this]; exact Nat.dvd_sub h1 h2 + have hgk : g ∣ k := (Nat.pow_dvd_pow_iff two_ne_zero).mp hg2 + have : g ∣ Nat.gcd (Nat.gcd b k) c := Nat.dvd_gcd (Nat.dvd_gcd hgb hgk) hgc + rw [hg] at this + exact Nat.dvd_one.mp this + +/-- A coprime leg/hypotenuse pair gives a primitive triple. -/ +private theorem ppt_of {b k c : ℕ} (hb : 0 < b) (hk : 0 < k) (heq : b ^ 2 + k ^ 2 = c ^ 2) + (hcop : Nat.Coprime b c) : IsPPT b k c := by + refine ⟨hb, hk, heq, ?_⟩ + exact Nat.Coprime.coprime_dvd_left (Nat.gcd_dvd_left b k) hcop + +/-- The leg is smaller than the hypotenuse. -/ +private theorem ppt_lt {b k c : ℕ} (h : IsPPT b k c) : b < c := by + obtain ⟨hb, hk, heq, -⟩ := h + have : b ^ 2 < c ^ 2 := by have : 0 < k ^ 2 := by positivity + omega + exact lt_of_pow_lt_pow_left₀ 2 (Nat.zero_le _) this + +/-- If the given leg is even, the other leg and the hypotenuse are odd. -/ +private theorem ppt_even_leg_odd {b n c : ℕ} (h : IsPPT b (2 * n) c) : Odd b ∧ Odd c := by + have hcop := ppt_coprime h + obtain ⟨hb, hk, heq, -⟩ := h + have hk2 : Even ((2 * n) ^ 2) := (Nat.even_pow' two_ne_zero).mpr (even_two_mul n) + have hbo : Odd b := by + rw [← Nat.not_even_iff_odd] + intro hbe + have hce : Even c := by + have : Even (c ^ 2) := by + rw [← heq]; exact Even.add ((Nat.even_pow' two_ne_zero).mpr hbe) hk2 + exact (Nat.even_pow' two_ne_zero).mp this + have h2 : 2 ∣ Nat.gcd b c := Nat.dvd_gcd (even_iff_two_dvd.mp hbe) (even_iff_two_dvd.mp hce) + rw [hcop] at h2 + omega + refine ⟨hbo, ?_⟩ + have : Odd (c ^ 2) := by rw [← heq]; exact Odd.add_even (hbo.pow) hk2 + exact (Nat.odd_pow_iff two_ne_zero).mp this + +/-- For odd `k`, the triangles with leg `k` correspond to `k² = d e`, `d < e` coprime. -/ +private theorem card_leg_odd {k : ℕ} (hk : Odd k) : (legTriangles k).card = UC (k ^ 2) := by + unfold UC + apply Finset.card_nbij' (fun q => (q.2 - q.1, q.2 + q.1)) (fun q => ((q.2 - q.1) / 2, (q.2 + q.1) / 2)) + · rintro ⟨b, c⟩ h + rw [Finset.mem_coe, mem_legTriangles] at h + rw [Finset.mem_coe] + have hbc := ppt_lt h + have hcop := ppt_coprime h + obtain ⟨hb, hk0, heq, -⟩ := h + simp only [Finset.mem_filter, Nat.mem_divisorsAntidiagonal] + have hprod : (c - b) * (c + b) = k ^ 2 := by + zify [hbc.le] at heq ⊢ + linear_combination (-1 : ℤ) * heq + refine ⟨⟨hprod, by positivity⟩, ?_, by omega⟩ + set g := Nat.gcd (c - b) (c + b) with hg + have h1 : g ∣ 2 * c := by + have := Nat.dvd_add (Nat.gcd_dvd_left (c - b) (c + b)) (Nat.gcd_dvd_right (c - b) (c + b)) + rwa [show c - b + (c + b) = 2 * c by omega] at this + have h2 : g ∣ 2 * b := by + have := Nat.dvd_sub (Nat.gcd_dvd_right (c - b) (c + b)) (Nat.gcd_dvd_left (c - b) (c + b)) + rwa [show c + b - (c - b) = 2 * b by omega] at this + have h3 : g ∣ 2 := by + have := Nat.dvd_gcd h2 h1 + rwa [Nat.gcd_mul_left, hcop, mul_one] at this + rcases (Nat.dvd_prime Nat.prime_two).mp h3 with h | h + · exact h + · exfalso + have h4 : 2 ∣ k ^ 2 := by + rw [← hprod]; exact Dvd.dvd.mul_right (h ▸ Nat.gcd_dvd_left (c - b) (c + b)) _ + have := Nat.Prime.dvd_of_dvd_pow Nat.prime_two h4 + rw [← even_iff_two_dvd] at this + exact (Nat.not_even_iff_odd.mpr hk) this + · rintro ⟨d, e⟩ h + rw [Finset.mem_coe] at h + rw [Finset.mem_coe] + show ((e - d) / 2, (e + d) / 2) ∈ legTriangles k + rw [mem_legTriangles] + simp only [Finset.mem_filter, Nat.mem_divisorsAntidiagonal] at h + obtain ⟨⟨hde, -⟩, hcop, hlt⟩ := h + have hodd : Odd (d * e) := by rw [hde]; exact hk.pow + obtain ⟨hdo, heo⟩ := Nat.odd_mul.mp hodd + rw [Nat.odd_iff] at hdo heo + obtain ⟨b, rfl⟩ : ∃ b, e = d + 2 * b := ⟨(e - d) / 2, by omega⟩ + rw [show (d + 2 * b - d) / 2 = b by omega, show (d + 2 * b + d) / 2 = d + b by omega] + have hcbd : Nat.Coprime d b := (Nat.coprime_self_add_right.mp hcop).coprime_mul_left_right + refine ppt_of (by omega) hk.pos ?_ (Nat.coprime_add_self_right.mpr hcbd.symm) + rw [← hde]; ring + · rintro ⟨b, c⟩ h + rw [Finset.mem_coe, mem_legTriangles] at h + have := ppt_lt h + simp only [Prod.mk.injEq] + omega + · rintro ⟨d, e⟩ h + rw [Finset.mem_coe] at h + simp only [Finset.mem_filter, Nat.mem_divisorsAntidiagonal] at h + obtain ⟨⟨hde, -⟩, hcop, hlt⟩ := h + have hodd : Odd (d * e) := by rw [hde]; exact hk.pow + obtain ⟨hdo, heo⟩ := Nat.odd_mul.mp hodd + rw [Nat.odd_iff] at hdo heo + simp only [Prod.mk.injEq] + omega + +/-- No primitive triangle has a leg `≡ 2 (mod 4)`. -/ +private theorem leg_two_mul_odd {n : ℕ} (hn : Odd n) : legTriangles (2 * n) = ∅ := by + rw [Finset.eq_empty_iff_forall_notMem] + rintro ⟨b, c⟩ h + rw [mem_legTriangles] at h + obtain ⟨hbo, hco⟩ := ppt_even_leg_odd h + obtain ⟨-, -, heq, -⟩ := h + obtain ⟨u, rfl⟩ := hbo + obtain ⟨w, rfl⟩ := hco + have h1 : u * (u + 1) + n * n = w * (w + 1) := by nlinarith + have hu := Nat.even_mul_succ_self u + have hw := Nat.even_mul_succ_self w + have hnn : Even (n * n) := by + rw [← h1] at hw + exact (Nat.even_add.mp hw).mp hu + rcases Nat.even_mul.mp hnn with h | h <;> exact (Nat.not_even_iff_odd.mpr hn) h + +/-- For even `n`, the triangles with leg `2n` correspond to `n² = d e`, `d < e` coprime. -/ +private theorem card_leg_even {n : ℕ} (hn : Even n) (hn0 : n ≠ 0) : + (legTriangles (2 * n)).card = UC (n ^ 2) := by + unfold UC + apply Finset.card_nbij' (fun q => ((q.2 - q.1) / 2, (q.2 + q.1) / 2)) (fun q => (q.2 - q.1, q.2 + q.1)) + · rintro ⟨b, c⟩ h + rw [Finset.mem_coe, mem_legTriangles] at h + rw [Finset.mem_coe] + have hbc := ppt_lt h + have hcop := ppt_coprime h + obtain ⟨hbo, hco⟩ := ppt_even_leg_odd h + obtain ⟨hb, hk0, heq, -⟩ := h + rw [Nat.odd_iff] at hbo hco + simp only [Finset.mem_filter, Nat.mem_divisorsAntidiagonal] + obtain ⟨d, hd⟩ : ∃ d, c = b + 2 * d := ⟨(c - b) / 2, by omega⟩ + subst hd + rw [show (b + 2 * d - b) / 2 = d by omega, show (b + 2 * d + b) / 2 = b + d by omega] + have hprod : d * (b + d) = n ^ 2 := by nlinarith + refine ⟨⟨hprod, by positivity⟩, ?_, by omega⟩ + -- coprime d (b + d) + have h1 : Nat.Coprime b (b + 2 * d) := hcop + have h2 : Nat.Coprime b (2 * d) := Nat.coprime_self_add_right.mp h1 + have h3 : Nat.Coprime b d := h2.coprime_mul_left_right + exact Nat.coprime_add_self_right.mpr h3.symm + · rintro ⟨d, e⟩ h + rw [Finset.mem_coe] at h + rw [Finset.mem_coe] + show (e - d, e + d) ∈ legTriangles (2 * n) + rw [mem_legTriangles] + simp only [Finset.mem_filter, Nat.mem_divisorsAntidiagonal] at h + obtain ⟨⟨hde, -⟩, hcop, hlt⟩ := h + have hev : Even (d * e) := by rw [hde]; exact (Nat.even_pow' two_ne_zero).mpr hn + have hpar : d % 2 + e % 2 = 1 := by + rcases Nat.even_mul.mp hev with h | h + · have : ¬ Even e := fun h' => by + have h2 : 2 ∣ Nat.gcd d e := Nat.dvd_gcd (even_iff_two_dvd.mp h) (even_iff_two_dvd.mp h') + rw [hcop] at h2; omega + rw [Nat.not_even_iff_odd, Nat.odd_iff] at this + rw [Nat.even_iff] at h; omega + · have : ¬ Even d := fun h' => by + have h2 : 2 ∣ Nat.gcd d e := Nat.dvd_gcd (even_iff_two_dvd.mp h') (even_iff_two_dvd.mp h) + rw [hcop] at h2; omega + rw [Nat.not_even_iff_odd, Nat.odd_iff] at this + rw [Nat.even_iff] at h; omega + refine ppt_of (by omega) (by omega) ?_ ?_ + · zify [hlt.le] + have : ((d : ℤ) * e) = (n : ℤ) ^ 2 := by exact_mod_cast hde + linear_combination (-4) * this + · set g := Nat.gcd (e - d) (e + d) with hg + have h1 : g ∣ 2 * e := by + have := Nat.dvd_add (Nat.gcd_dvd_left (e - d) (e + d)) (Nat.gcd_dvd_right (e - d) (e + d)) + rwa [show e - d + (e + d) = 2 * e by omega] at this + have h2 : g ∣ 2 * d := by + have := Nat.dvd_sub (Nat.gcd_dvd_right (e - d) (e + d)) (Nat.gcd_dvd_left (e - d) (e + d)) + rwa [show e + d - (e - d) = 2 * d by omega] at this + have h3 : g ∣ 2 := by + have := Nat.dvd_gcd h2 h1 + rwa [Nat.gcd_mul_left, hcop, mul_one] at this + rcases (Nat.dvd_prime Nat.prime_two).mp h3 with h | h + · exact h + · exfalso + have h4 : 2 ∣ e - d := h ▸ Nat.gcd_dvd_left (e - d) (e + d) + omega + · rintro ⟨b, c⟩ h + rw [Finset.mem_coe, mem_legTriangles] at h + have := ppt_lt h + obtain ⟨hbo, hco⟩ := ppt_even_leg_odd h + rw [Nat.odd_iff] at hbo hco + simp only [Prod.mk.injEq] + omega + · rintro ⟨d, e⟩ h + rw [Finset.mem_coe] at h + simp only [Finset.mem_filter, Nat.mem_divisorsAntidiagonal] at h + obtain ⟨⟨hde, -⟩, hcop, hlt⟩ := h + simp only [Prod.mk.injEq] + omega + +/-- `2 UC (k²) + [k = 1] = 2^{ω(k)}`. -/ +private theorem two_UC_sq {k : ℕ} (hk : k ≠ 0) : + 2 * UC (k ^ 2) + (if k = 1 then 1 else 0) = 2 ^ k.primeFactors.card := by + have h1 := UU_eq_UC (k ^ 2) + rw [UU_eq _ (pow_ne_zero 2 hk), Nat.primeFactors_pow _ two_ne_zero] at h1 + rw [h1] + congr 1 + simp only [sq_eq_one] + +/-- `2 wO(k) + [k = 1] = g(k)`. -/ +private theorem wO_eq (k : ℕ) : 2 * wO k + (if k = 1 then 1 else 0) = Arith.gN k := by + unfold wO Arith.gN + by_cases h : Odd k ∧ CondO k + · rw [if_pos h, if_pos (show Odd k ∧ ∀ p ∈ k.primeFactors, p % 4 = 3 from h), card_leg_odd h.1] + exact two_UC_sq (by rintro rfl; exact (Nat.not_odd_zero h.1)) + · rw [if_neg h, if_neg (show ¬ (Odd k ∧ ∀ p ∈ k.primeFactors, p % 4 = 3) from h), if_neg] + rintro rfl + exact h ⟨odd_one, by simp [CondO]⟩ + +/-- `wE k = 0` unless `4 ∣ k`. -/ +private theorem wE_of_mod {k : ℕ} (hk : k % 4 ≠ 0) : wE k = 0 := by + unfold wE + split_ifs with h + · obtain ⟨⟨r, hr⟩, -⟩ := h + have hn : Odd r := by rw [Nat.odd_iff]; omega + rw [show k = 2 * r by omega, leg_two_mul_odd hn, Finset.card_empty] + · rfl + +/-- Prime factors of `2 m` for even `m`. -/ +private theorem primeFactors_two_mul_of_even {m : ℕ} (hm : Even m) (hm0 : m ≠ 0) : + (2 * m).primeFactors = m.primeFactors := by + rw [Nat.primeFactors_mul two_ne_zero hm0, Nat.Prime.primeFactors Nat.prime_two] + apply Finset.union_eq_right.mpr + rw [Finset.singleton_subset_iff, Nat.mem_primeFactors] + exact ⟨Nat.prime_two, even_iff_two_dvd.mp hm, hm0⟩ + +/-- Prime factors of `2 m` for odd `m`. -/ +private theorem primeFactors_two_mul_of_odd {m : ℕ} (hm : Odd m) : + (2 * m).primeFactors = {2} ∪ m.primeFactors := by + rw [Nat.primeFactors_mul two_ne_zero (by rintro rfl; exact Nat.not_odd_zero hm), + Nat.Prime.primeFactors Nat.prime_two] + +/-- `wE (8 i) = wE (4 i)`. -/ +private theorem wE_eight (i : ℕ) : wE (8 * i) = wE (4 * i) := by + rcases Nat.eq_zero_or_pos i with rfl | hi + · rfl + have hpf : (8 * i).primeFactors = (4 * i).primeFactors := by + rw [show 8 * i = 2 * (4 * i) by ring] + exact primeFactors_two_mul_of_even ⟨2 * i, by ring⟩ (by omega) + have hpf2 : (4 * i).primeFactors = (2 * i).primeFactors := by + rw [show 4 * i = 2 * (2 * i) by ring] + exact primeFactors_two_mul_of_even ⟨i, by ring⟩ (by omega) + have hc8 : (legTriangles (8 * i)).card = (legTriangles (4 * i)).card := by + rw [show 8 * i = 2 * (4 * i) by ring, card_leg_even ⟨2 * i, by ring⟩ (by omega), + show 4 * i = 2 * (2 * i) by ring, card_leg_even ⟨i, by ring⟩ (by omega)] + have h1 := two_UC_sq (k := 4 * i) (by omega) + have h2 := two_UC_sq (k := 2 * i) (by omega) + rw [if_neg (by omega)] at h1 h2 + rw [show 2 * (2 * i) = 4 * i by ring] at * + rw [hpf2] at h1 + omega + have hiff : (Even (8 * i) ∧ CondE (8 * i)) ↔ (Even (4 * i) ∧ CondE (4 * i)) := by + unfold CondE + rw [hpf] + constructor + · rintro ⟨-, h⟩; exact ⟨⟨2 * i, by ring⟩, h⟩ + · rintro ⟨-, h⟩; exact ⟨⟨4 * i, by ring⟩, h⟩ + unfold wE + by_cases h : Even (4 * i) ∧ CondE (4 * i) + · rw [if_pos (hiff.mpr h), if_pos h, hc8] + · rw [if_neg (mt hiff.mp h), if_neg h] + +/-- `wE (4 j) + [j = 1] = g(j)` for odd `j`. -/ +private theorem wE_odd {j : ℕ} (hj : Odd j) : wE (4 * j) + (if j = 1 then 1 else 0) = Arith.gN j := by + have hj0 : j ≠ 0 := by rintro rfl; exact Nat.not_odd_zero hj + have hpf4 : (4 * j).primeFactors = {2} ∪ j.primeFactors := by + rw [show 4 * j = 2 * (2 * j) by ring, primeFactors_two_mul_of_even ⟨j, by ring⟩ (by omega), + primeFactors_two_mul_of_odd hj] + have hcard : (legTriangles (4 * j)).card = 2 ^ j.primeFactors.card := by + rw [show 4 * j = 2 * (2 * j) by ring, card_leg_even ⟨j, by ring⟩ (by omega)] + have h1 := two_UC_sq (k := 2 * j) (by omega) + rw [if_neg (by omega), primeFactors_two_mul_of_odd hj, Finset.card_union_of_disjoint, Finset.card_singleton] at h1 + · rw [pow_add] at h1; omega + · rw [Finset.disjoint_singleton_left, Nat.mem_primeFactors] + rintro ⟨-, h2, -⟩ + exact (Nat.not_even_iff_odd.mpr hj) (even_iff_two_dvd.mpr h2) + have hodd_pf : ∀ p ∈ j.primeFactors, Odd p := by + intro p hp + rw [Nat.mem_primeFactors] at hp + exact Odd.of_dvd_nat hj hp.2.1 + have hcond : CondE (4 * j) ↔ (∀ p ∈ j.primeFactors, p % 4 = 3) ∧ j ≠ 1 := by + unfold CondE + rw [hpf4] + constructor + · rintro ⟨h1, ⟨p, hp, hpo⟩⟩ + refine ⟨fun q hq => h1 q (Finset.mem_union_right _ hq) (hodd_pf q hq), ?_⟩ + rintro rfl + simp at hp + rw [hp] at hpo + exact (Nat.not_odd_iff_even.mpr even_two) hpo + · rintro ⟨h1, hne⟩ + refine ⟨fun q hq hqo => ?_, ?_⟩ + · rcases Finset.mem_union.mp hq with hq | hq + · rw [Finset.mem_singleton] at hq; rw [hq] at hqo + exact absurd hqo (Nat.not_odd_iff_even.mpr even_two) + · exact h1 q hq + · obtain ⟨p, hp⟩ : (j.primeFactors).Nonempty := by + rw [Finset.nonempty_iff_ne_empty, Ne, Nat.primeFactors_eq_empty]; omega + exact ⟨p, Finset.mem_union_right _ hp, hodd_pf p hp⟩ + unfold wE Arith.gN + by_cases h : (∀ p ∈ j.primeFactors, p % 4 = 3) ∧ j ≠ 1 + · rw [if_pos (show Even (4 * j) ∧ CondE (4 * j) from ⟨⟨2 * j, by ring⟩, hcond.mpr h⟩), + if_pos (show Odd j ∧ ∀ p ∈ j.primeFactors, p % 4 = 3 from ⟨hj, h.1⟩), if_neg h.2, hcard, + add_zero] + · rw [if_neg (show ¬ (Even (4 * j) ∧ CondE (4 * j)) from fun h' => h (hcond.mp h'.2)), zero_add] + by_cases h1 : j = 1 + · subst h1; simp + · rw [if_neg h1, if_neg (show ¬ (Odd j ∧ ∀ p ∈ j.primeFactors, p % 4 = 3) from + fun h' => h ⟨h'.2, h1⟩)] + +/-- partial sums of `Arith.gN` -/ +private def SN (N : ℕ) : ℕ := ∑ k ∈ Finset.range (N + 1), Arith.gN k + +/-- partial sums of `wE (4 j)` -/ +private def EE (J : ℕ) : ℕ := ∑ j ∈ Finset.range (J + 1), wE (4 * j) + +/-- Recursion step for `EE`. -/ +private theorem EE_succ (J : ℕ) : EE (J + 1) = EE J + wE (4 * (J + 1)) := Finset.sum_range_succ _ _ + +/-- Recursion step for `SN`. -/ +private theorem SN_succ (J : ℕ) : SN (J + 1) = SN J + Arith.gN (J + 1) := Finset.sum_range_succ _ _ + +/-- `wE 0 = 0`. -/ +private theorem wE_zero : wE 0 = 0 := by + simp [wE, CondE] + +/-- `g` vanishes on even numbers. -/ +private theorem gN_of_even {k : ℕ} (hk : Even k) : Arith.gN k = 0 := by + unfold Arith.gN + rw [if_neg] + rintro ⟨h, -⟩ + exact (Nat.not_odd_iff_even.mpr hk) h + +/-- `2 numLE wO N + [N ≥ 1] = SN N`. -/ +private theorem numLE_wO (N : ℕ) : 2 * numLE wO N + (if 1 ≤ N then 1 else 0) = SN N := by + unfold numLE SN + rw [Finset.mul_sum] + have : (if 1 ≤ N then 1 else 0) = ∑ k ∈ Finset.range (N + 1), (if k = 1 then 1 else 0) := by + rw [Finset.sum_ite_eq'] + simp only [Finset.mem_range] + split_ifs <;> omega + rw [this, ← Finset.sum_add_distrib] + exact Finset.sum_congr rfl fun k _ => wO_eq k + +/-- `numLE wE N = EE (N / 4)`. -/ +private theorem numLE_wE (N : ℕ) : numLE wE N = EE (N / 4) := by + induction N with + | zero => simp [numLE, EE, wE_zero] + | succ N ih => + rw [numLE, Finset.sum_range_succ, ← numLE, ih] + by_cases h : (N + 1) % 4 = 0 + · rw [show (N + 1) / 4 = N / 4 + 1 by omega, EE_succ, + show 4 * (N / 4 + 1) = N + 1 by omega] + · rw [wE_of_mod h, add_zero, show (N + 1) / 4 = N / 4 by omega] + +/-- `EE J + [J ≥ 1] = SN J + EE (J / 2)`. -/ +private theorem EE_rec (J : ℕ) : EE J + (if 1 ≤ J then 1 else 0) = SN J + EE (J / 2) := by + induction J with + | zero => simp [EE, SN, wE_zero, Arith.gN] + | succ J ih => + rw [EE_succ, SN_succ] + rcases Nat.even_or_odd (J + 1) with he | ho + · rw [gN_of_even he] + obtain ⟨r, hr⟩ := he + have h1 : (J + 1) / 2 = J / 2 + 1 := by omega + rw [h1, EE_succ, show 4 * (J + 1) = 8 * (J / 2 + 1) by omega, wE_eight] + rw [if_pos (by omega)] at ih ⊢ + omega + · have h1 := wE_odd ho + have h2 : (J + 1) / 2 = J / 2 := by obtain ⟨r, hr⟩ := ho; omega + rw [h2] + split_ifs at ih h1 ⊢ <;> omega + +/-- inverting the counting function -/ +private theorem nth_limit (w : ℕ → ℕ) {L : ℝ} (hL : 0 < L) + (hlim : Filter.Tendsto (fun N : ℕ => (numLE w N : ℝ) / N) Filter.atTop (nhds L)) + (hex : ∀ n, ∃ k, n ≤ numLE w k) : + Filter.Tendsto (fun n : ℕ => (nthTerm w n : ℝ) / n) Filter.atTop (nhds L⁻¹) := by + have hspec := fun n => nthTerm_spec w (hex n) + -- nthTerm → ∞ + have hinf : Filter.Tendsto (nthTerm w) Filter.atTop Filter.atTop := by + rw [Filter.tendsto_atTop_atTop] + intro K + refine ⟨numLE w K + 1, fun n hn => ?_⟩ + by_contra hlt + rw [not_le] at hlt + have h1 := (hspec n).1 + have h2 := numLE_mono w hlt.le + omega + have hup : Filter.Tendsto (fun n : ℕ => (numLE w (nthTerm w n) : ℝ) / (nthTerm w n)) + Filter.atTop (nhds L) := hlim.comp hinf + have hsub : Filter.Tendsto (fun n : ℕ => nthTerm w n - 1) Filter.atTop Filter.atTop := + Filter.tendsto_sub_atTop_nat 1 |>.comp hinf + have hratio : Filter.Tendsto (fun n : ℕ => ((nthTerm w n - 1 : ℕ) : ℝ) / (nthTerm w n)) + Filter.atTop (nhds 1) := by + have h0 : Filter.Tendsto (fun n : ℕ => (1 : ℝ) - 1 / (nthTerm w n)) Filter.atTop (nhds 1) := by + have := (tendsto_one_div_atTop_nhds_zero_nat (𝕜 := ℝ)).comp hinf + simpa using (tendsto_const_nhds (x := (1:ℝ))).sub this + refine h0.congr' ?_ + filter_upwards [hinf.eventually (Filter.eventually_ge_atTop 1)] with n hn + have : (0 : ℝ) < nthTerm w n := by exact_mod_cast hn + rw [Nat.cast_sub hn, Nat.cast_one] + field_simp + have hlow : Filter.Tendsto (fun n : ℕ => (numLE w (nthTerm w n - 1) : ℝ) / (nthTerm w n)) + Filter.atTop (nhds L) := by + have := (hlim.comp hsub).mul hratio + rw [mul_one] at this + refine this.congr' ?_ + filter_upwards [hinf.eventually (Filter.eventually_ge_atTop 2)] with n hn + simp only [Function.comp] + have : ((nthTerm w n - 1 : ℕ) : ℝ) ≠ 0 := by + have : 1 ≤ nthTerm w n - 1 := by omega + exact_mod_cast (by omega : nthTerm w n - 1 ≠ 0) + field_simp + have hmain : Filter.Tendsto (fun n : ℕ => (n : ℝ) / (nthTerm w n)) Filter.atTop (nhds L) := by + refine tendsto_of_tendsto_of_tendsto_of_le_of_le' hlow hup ?_ ?_ + · filter_upwards [hinf.eventually (Filter.eventually_ge_atTop 1)] with n hn + have hpos : (0 : ℝ) < nthTerm w n := by exact_mod_cast hn + apply div_le_div_of_nonneg_right _ hpos.le + have := (hspec n).2 (nthTerm w n - 1) (by omega) + exact_mod_cast this.le + · filter_upwards [hinf.eventually (Filter.eventually_ge_atTop 1)] with n hn + have hpos : (0 : ℝ) < nthTerm w n := by exact_mod_cast hn + apply div_le_div_of_nonneg_right _ hpos.le + exact_mod_cast (hspec n).1 + have := hmain.inv₀ hL.ne' + refine this.congr' ?_ + filter_upwards [Filter.eventually_gt_atTop 0] with n hn + simp only [inv_div] + +end Comb + +namespace Final + +open Filter Topology Math0.Statements.A354571 + +/-- The partial sums `SN N` agree with the sums used in the Tauberian theorem. -/ +private theorem SN_eq_Ioc (N : ℕ) : Comb.SN N = ∑ n ∈ Finset.Ioc 0 N, Arith.gN n := by + induction N with + | zero => simp [Comb.SN, Arith.gN_zero] + | succ N ih => rw [Comb.SN_succ, ih, Finset.sum_Ioc_succ_top (Nat.zero_le N)] + +/-- `SN N ≤ 2 N`. -/ +private theorem SN_le (N : ℕ) : Comb.SN N ≤ 2 * N := by + rw [SN_eq_Ioc]; exact Arith.partial_le N + +/-- The main asymptotic `SN N / N → 2 / π`, from the Tauberian theorem. -/ +private theorem SN_tendsto : Tendsto (fun N : ℕ => (Comb.SN N : ℝ) / N) atTop (𝓝 (2 / Real.pi)) := by + have hM : ∀ N : ℕ, ∑ n ∈ Finset.Icc 1 N, (Arith.gN n : ℝ) ≤ 2 * N := by + intro N + rw [Arith.Icc_eq_Ioc] + exact_mod_cast Arith.partial_le N + have h := Tauber.tauberian (a := fun n => (Arith.gN n : ℝ)) (M := 2) (by norm_num) + (fun n => Nat.cast_nonneg _) hM (2 / Real.pi) (by positivity) (dslope Arith.HH 1) + Arith.continuousOn_G (fun s hs => Arith.G_eq hs) + refine h.congr (fun N => ?_) + rw [SN_eq_Ioc, Arith.Icc_eq_Ioc] + push_cast + rfl + +/-- `numLE wO N / N → 1 / π`. -/ +private theorem wO_tendsto : Tendsto (fun N : ℕ => (numLE wO N : ℝ) / N) atTop (𝓝 (1 / Real.pi)) := by + have h1 : Tendsto (fun N : ℕ => ((Comb.SN N : ℝ) / N - 1 / N) / 2) atTop + (𝓝 ((2 / Real.pi - 0) / 2)) := + (SN_tendsto.sub tendsto_one_div_atTop_nhds_zero_nat).div_const 2 + rw [show (2 / Real.pi - 0) / 2 = 1 / Real.pi by ring] at h1 + refine h1.congr' ?_ + filter_upwards [eventually_ge_atTop 1] with N hN + have h := Comb.numLE_wO N + rw [if_pos hN] at h + have hN' : (0 : ℝ) < N := by exact_mod_cast hN + have : (Comb.SN N : ℝ) = 2 * numLE wO N + 1 := by exact_mod_cast h.symm + rw [this]; field_simp; ring + +/-- The summand of the dyadic decomposition of `EE`. -/ +private noncomputable def RR (M : ℕ) : ℝ := (Comb.SN M : ℝ) - (if 1 ≤ M then 1 else 0) + +/-- `RR 0 = 0`. -/ +private theorem RR_zero : RR 0 = 0 := by + simp [RR, Comb.SN, Arith.gN_zero] + +/-- `RR` is nonnegative. -/ +private theorem RR_nonneg (M : ℕ) : 0 ≤ RR M := by + unfold RR + split_ifs with h + · have : 1 ≤ Comb.SN M := by + unfold Comb.SN + calc 1 = Arith.gN 1 := Arith.gN_one.symm + _ ≤ ∑ k ∈ Finset.range (M + 1), Arith.gN k := + Finset.single_le_sum (fun k _ => Nat.zero_le _) (Finset.mem_range.mpr (by omega)) + have : (1 : ℝ) ≤ Comb.SN M := by exact_mod_cast this + linarith + · simp + +/-- `RR M ≤ 2 M`. -/ +private theorem RR_le (M : ℕ) : RR M ≤ 2 * M := by + unfold RR + have : (Comb.SN M : ℝ) ≤ 2 * M := by exact_mod_cast SN_le M + split_ifs <;> linarith + +/-- `RR M / M → 2 / π`. -/ +private theorem RR_tendsto : Tendsto (fun M : ℕ => RR M / M) atTop (𝓝 (2 / Real.pi)) := by + have h := SN_tendsto.sub tendsto_one_div_atTop_nhds_zero_nat + rw [sub_zero] at h + refine h.congr' ?_ + filter_upwards [eventually_ge_atTop 1] with M hM + unfold RR + rw [if_pos hM, sub_div] + +/-- The recursion for `EE` over the reals. -/ +private theorem EE_real (J : ℕ) : (Comb.EE J : ℝ) = RR J + Comb.EE (J / 2) := by + have h := Comb.EE_rec J + have h' : (Comb.EE J : ℝ) + (if 1 ≤ J then 1 else 0) = Comb.SN J + Comb.EE (J / 2) := by + have := congrArg (fun x : ℕ => (x : ℝ)) h + push_cast at this + split_ifs at this ⊢ <;> simpa using this + unfold RR + linarith + +/-- The dyadic decomposition `EE J = ∑ᵢ RR (J / 2^i)`. -/ +private theorem EE_tsum (J : ℕ) : (Comb.EE J : ℝ) = ∑' i : ℕ, RR (J / 2 ^ i) := by + induction J using Nat.strong_induction_on with + | _ J ih => + have hsum : Summable (fun i : ℕ => RR (J / 2 ^ i)) := by + apply summable_of_ne_finset_zero (s := Finset.range (J + 1)) + intro i hi + rw [Finset.mem_range, not_lt] at hi + have : J < 2 ^ i := lt_of_lt_of_le (Nat.lt_two_pow_self) (Nat.pow_le_pow_right (by norm_num) (by omega)) + rw [Nat.div_eq_of_lt this, RR_zero] + rcases Nat.eq_zero_or_pos J with rfl | hJ + · simp [Comb.EE, Comb.wE_zero, RR_zero] + rw [hsum.tsum_eq_zero_add, EE_real, ih (J / 2) (Nat.div_lt_self hJ (by norm_num))] + simp only [pow_zero, Nat.div_one] + congr 1 + refine tsum_congr fun i => ?_ + rw [Nat.div_div_eq_div_mul, pow_succ'] + +/-- `EE J / J → 4 / π`. -/ +private theorem EE_tendsto : Tendsto (fun J : ℕ => (Comb.EE J : ℝ) / J) atTop (𝓝 (2 * (2 / Real.pi))) := by + have := Fin1.dyadic RR 2 (2 / Real.pi) RR_zero RR_nonneg RR_le RR_tendsto + refine this.congr (fun J => ?_) + rw [EE_tsum] + +/-- `numLE wE N / N → 1 / π`. -/ +private theorem wE_tendsto : Tendsto (fun N : ℕ => (numLE wE N : ℝ) / N) atTop (𝓝 (1 / Real.pi)) := by + have h := Fin1.tendsto_comp_div (fun J => (Comb.EE J : ℝ)) + (by simp [Comb.EE, Comb.wE_zero]) EE_tendsto 4 (by norm_num) + rw [show 2 * (2 / Real.pi) * (1 / ((4 : ℕ) : ℝ)) = 1 / Real.pi by push_cast; ring] at h + refine h.congr (fun N => ?_) + rw [Comb.numLE_wE] + +end Final + +open Math0.Statements.A354571 in +/-- Selle's conjecture holds: `a(n)/n → π` for A354571 and A354570. -/ +theorem result : statement := by + have hpi : (1 / Real.pi)⁻¹ = Real.pi := by rw [one_div, inv_inv] + have hL : (0 : ℝ) < 1 / Real.pi := by positivity + refine ⟨?_, ?_⟩ + · have h := Comb.nth_limit wE hL Final.wE_tendsto exists_le_numLE_wE + rw [hpi] at h + exact h + · have h := Comb.nth_limit wO hL Final.wO_tendsto exists_le_numLE_wO + rw [hpi] at h + exact h + +end Math0.Frontier.A354571 + +#math0_settles Math0.Frontier.A354571.result Math0.Statements.A354571.statement diff --git a/lean/Math0/Frontier/OEIS/A355076.lean b/lean/Math0/Frontier/OEIS/A355076.lean new file mode 100644 index 0000000..178df17 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A355076.lean @@ -0,0 +1,192 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A355076 +import Math0.Audit + +/-! +# Integer partial sums of the Calkin-Wilf ratios `fusc(k)/fusc(k+1)` (A355076) + +We prove Rémy Sigrist's conjecture: `∑_{k=0}^{n} fusc(k)/fusc(k+1)` is an integer whenever +`n = 2*4^k - 1` or `n = 2*4^k - 2`. + +Write `x_j = fusc(j)/fusc(j+1)` (the Calkin-Wilf sequence). The children of `x_j` are +`x_{2j} = x_j/(1+x_j)` and `x_{2j+1} = 1 + x_j`. By the symmetry +`fusc(2^m + i) = fusc(2^m + j)` for `i + j = 2^m`, the row `{x_j : 2^m ≤ j < 2^(m+1)}` is closed +under `x ↦ 1/x` (reflected order), so `∑_row x/(1+x) = ∑_row 1/(1+x)`, and both equal `2^m/2`. +Hence the row sums satisfy `T(m+1) = T(m) + 2^m + 2^m/2`, `T(0) = 1`, so +`T(m) = (3*2^m - 1)/2`, and `∑_{k < 2^M} x_k = (3*2^M - 3 - M)/2`. For `M = 2k+1` this is the +integer `3*4^k - k - 2`; removing the last term `x_{2^M-1} = M/1` gives the other integer. +-/ + +namespace Math0.Frontier.A355076 +open Math0.Statements.A355076 + +/-- `fusc n > 0` for `n ≥ 1`. -/ +private lemma fusc_pos : ∀ n, 1 ≤ n → 0 < fusc n := by + intro n + induction n using Nat.strong_induction_on with + | _ n ih => + intro hn + rcases Nat.even_or_odd' n with ⟨k, rfl | rfl⟩ + · rw [fusc_even]; exact ih k (by omega) (by omega) + · rcases Nat.eq_zero_or_pos k with rfl | hk + · simp [fusc_one] + · rw [fusc_odd]; have := ih k (by omega) hk; omega + +/-- Symmetry of each row of Stern's diatomic sequence: `fusc(2^m + i) = fusc(2^m + j)` when +`i + j = 2^m`. -/ +private lemma fusc_symm : ∀ m i j, i + j = 2 ^ m → fusc (2 ^ m + i) = fusc (2 ^ m + j) := by + intro m + induction m with + | zero => + intro i j h + have : (i = 0 ∧ j = 1) ∨ (i = 1 ∧ j = 0) := by simp at h; omega + rcases this with ⟨rfl, rfl⟩ | ⟨rfl, rfl⟩ <;> decide +kernel + | succ m ih => + intro i j h + have hp : 2 ^ (m + 1) = 2 * 2 ^ m := by ring + rw [hp] at h ⊢ + rcases Nat.even_or_odd' i with ⟨i', rfl | rfl⟩ <;> + rcases Nat.even_or_odd' j with ⟨j', rfl | rfl⟩ + · rw [show 2 * 2 ^ m + 2 * i' = 2 * (2 ^ m + i') by ring, + show 2 * 2 ^ m + 2 * j' = 2 * (2 ^ m + j') by ring, fusc_even, fusc_even] + exact ih i' j' (by omega) + · omega + · omega + · rw [show 2 * 2 ^ m + (2 * i' + 1) = 2 * (2 ^ m + i') + 1 by ring, + show 2 * 2 ^ m + (2 * j' + 1) = 2 * (2 ^ m + j') + 1 by ring, fusc_odd, fusc_odd] + have e1 := ih i' (j' + 1) (by omega) + have e2 := ih (i' + 1) j' (by omega) + rw [← add_assoc] at e1 e2 + rw [e1, e2, Nat.add_comm] + +/-- `fusc (2^M) = 1`. -/ +private lemma fusc_two_pow (M : ℕ) : fusc (2 ^ M) = 1 := by + induction M with + | zero => decide +kernel + | succ M ih => rw [pow_succ, mul_comm, fusc_even, ih] + +/-- `fusc (2^M - 1) = M`. -/ +private lemma fusc_two_pow_sub_one (M : ℕ) : fusc (2 ^ M - 1) = M := by + induction M with + | zero => decide +kernel + | succ M ih => + have h1 := Nat.one_le_two_pow (n := M) + rw [show 2 ^ (M + 1) - 1 = 2 * (2 ^ M - 1) + 1 by rw [pow_succ]; omega, fusc_odd, ih, + Nat.sub_add_cancel h1, fusc_two_pow] + +/-- Splitting a sum over `range (2n)` into even and odd indices. -/ +private lemma sum_range_double (h : ℕ → ℚ) (n : ℕ) : + ∑ i ∈ Finset.range (2 * n), h i = ∑ i ∈ Finset.range n, (h (2 * i) + h (2 * i + 1)) := by + induction n with + | zero => simp + | succ n ih => + rw [show 2 * (n + 1) = 2 * n + 1 + 1 by ring, Finset.sum_range_succ, Finset.sum_range_succ, + ih, Finset.sum_range_succ] + ring + +/-- The left child: `x_{2j} = fusc j / (fusc j + fusc (j+1))`. -/ +private lemma ratio_even (j : ℕ) : + (fusc (2 * j) : ℚ) / fusc (2 * j + 1) = fusc j / (fusc j + fusc (j + 1)) := by + rw [fusc_even, fusc_odd]; push_cast; ring + +/-- The right child: `x_{2j+1} = x_j + 1`. -/ +private lemma ratio_odd (j : ℕ) : + (fusc (2 * j + 1) : ℚ) / fusc (2 * j + 1 + 1) = fusc j / fusc (j + 1) + 1 := by + have hpos : (0 : ℚ) < fusc (j + 1) := by exact_mod_cast fusc_pos (j + 1) (by omega) + rw [show 2 * j + 1 + 1 = 2 * (j + 1) by ring, fusc_even, fusc_odd] + push_cast + field_simp + +/-- Over a row, `∑ x/(1+x) = 2^m/2`, proved by pairing `x` with `1/x` via the row symmetry. -/ +private lemma row_left_sum (m : ℕ) : + ∑ i ∈ Finset.range (2 ^ m), + (fusc (2 ^ m + i) : ℚ) / (fusc (2 ^ m + i) + fusc (2 ^ m + i + 1)) = 2 ^ m / 2 := by + set N := 2 ^ m with hN + have hpos : ∀ i, (0 : ℚ) < fusc (N + i) + fusc (N + i + 1) := by + intro i + have : 0 < fusc (N + i + 1) := fusc_pos _ (Nat.le_add_left _ _) + have : (0 : ℚ) < fusc (N + i + 1) := by exact_mod_cast this + positivity + have hsum : ∑ i ∈ Finset.range N, + ((fusc (N + i) : ℚ) / (fusc (N + i) + fusc (N + i + 1)) + + (fusc (N + i + 1) : ℚ) / (fusc (N + i) + fusc (N + i + 1))) = N := by + rw [Finset.sum_congr rfl (g := fun _ => (1 : ℚ))] + · simp + · intro i _ + rw [← add_div, div_self (hpos i).ne'] + have hrefl : ∑ i ∈ Finset.range N, + (fusc (N + i) : ℚ) / (fusc (N + i) + fusc (N + i + 1)) = + ∑ i ∈ Finset.range N, (fusc (N + i + 1) : ℚ) / (fusc (N + i) + fusc (N + i + 1)) := by + rw [← Finset.sum_range_reflect] + apply Finset.sum_congr rfl + intro i hi + rw [Finset.mem_range] at hi + have e1 : fusc (N + (N - 1 - i)) = fusc (N + i + 1) := by + rw [fusc_symm m (N - 1 - i) (i + 1) (by omega), add_assoc] + have e2 : fusc (N + (N - 1 - i) + 1) = fusc (N + i) := by + rw [show N + (N - 1 - i) + 1 = N + (N - i) by omega, fusc_symm m (N - i) i (by omega)] + rw [e1, e2, add_comm ((fusc (N + i + 1) : ℚ))] + rw [Finset.sum_add_distrib, ← hrefl] at hsum + have hNq : (N : ℚ) = 2 ^ m := by rw [hN]; push_cast; ring + rw [hNq] at hsum + linarith + +/-- The row sum `T(m) = ∑_{2^m ≤ j < 2^(m+1)} x_j = (3*2^m - 1)/2`. -/ +private lemma row_sum (m : ℕ) : + ∑ i ∈ Finset.range (2 ^ m), (fusc (2 ^ m + i) : ℚ) / fusc (2 ^ m + i + 1) = + (3 * 2 ^ m - 1) / 2 := by + induction m with + | zero => norm_num [fusc_one, show fusc 2 = 1 from by decide +kernel] + | succ m ih => + rw [show 2 ^ (m + 1) = 2 * 2 ^ m by ring, sum_range_double] + rw [Finset.sum_congr rfl (g := fun i => + ((fusc (2 ^ m + i) : ℚ) / (fusc (2 ^ m + i) + fusc (2 ^ m + i + 1)) + + ((fusc (2 ^ m + i) : ℚ) / fusc (2 ^ m + i + 1) + 1)))] + · rw [Finset.sum_add_distrib, Finset.sum_add_distrib, row_left_sum, ih] + simp + ring + · intro i _ + rw [show 2 * 2 ^ m + 2 * i = 2 * (2 ^ m + i) by ring, + show 2 * 2 ^ m + (2 * i + 1) = 2 * (2 ^ m + i) + 1 by ring, ratio_even, ratio_odd] + +/-- `∑_{k < 2^M} x_k = (3*2^M - 3 - M)/2`. -/ +private lemma prefix_sum (M : ℕ) : + ∑ k ∈ Finset.range (2 ^ M), (fusc k : ℚ) / fusc (k + 1) = (3 * 2 ^ M - 3 - M) / 2 := by + induction M with + | zero => simp [fusc_zero] + | succ M ih => + rw [show 2 ^ (M + 1) = 2 ^ M + 2 ^ M by ring, Finset.sum_range_add, ih, row_sum] + push_cast + ring + +/-- Sigrist's conjecture for A355076 holds. -/ +theorem result : statement := by + intro n ⟨k, hk⟩ + have hpow : 2 * 4 ^ k = 2 ^ (2 * k + 1) := by + rw [pow_succ, pow_mul]; norm_num; ring + have h1 := Nat.one_le_two_pow (n := 2 * k + 1) + have hS : ∑ j ∈ Finset.range (2 ^ (2 * k + 1)), (fusc j : ℚ) / fusc (j + 1) = + ((3 * 4 ^ k - k - 2 : ℤ) : ℚ) := by + rw [prefix_sum] + push_cast + rw [pow_succ, pow_mul] + norm_num + ring + rcases hk with rfl | rfl + · unfold a + rw [show 2 * 4 ^ k - 1 + 1 = 2 ^ (2 * k + 1) by omega, hS] + exact Rat.den_intCast _ + · unfold a + have hsplit := + Finset.sum_range_succ (fun j => (fusc j : ℚ) / fusc (j + 1)) (2 ^ (2 * k + 1) - 1) + rw [Nat.sub_add_cancel h1, hS, fusc_two_pow_sub_one, fusc_two_pow] at hsplit + rw [show 2 * 4 ^ k - 2 + 1 = 2 ^ (2 * k + 1) - 1 by omega] + rw [show ∑ j ∈ Finset.range (2 ^ (2 * k + 1) - 1), (fusc j : ℚ) / fusc (j + 1) = + ((3 * 4 ^ k - k - 2 - (2 * k + 1) : ℤ) : ℚ) by push_cast at hsplit ⊢; linarith] + exact Rat.den_intCast _ + +end Math0.Frontier.A355076 + +#math0_settles Math0.Frontier.A355076.result Math0.Statements.A355076.statement diff --git a/lean/Math0/Frontier/OEIS/A355339.lean b/lean/Math0/Frontier/OEIS/A355339.lean new file mode 100644 index 0000000..938fbd1 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A355339.lean @@ -0,0 +1,405 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A355339 +import Math0.Audit + +/-! +# A355339: the central even run of the knight-move triangle has length 1 iff `n = 2^m - 2` + +We prove Rémy Sigrist's conjecture: `a(n) = 1` iff `n > 0` and `n = 2^m - 2`. + +**Reduction.** For `n ≥ 1` the central entry `T(n,0)` is even, and the row is symmetric +(`T(n,-k) = T(n,k)`, by induction from the recurrence). So the central even block has length +`2·right - 1` with `right ≥ 1`, and `a(n) = 1` iff `T(n,1)` is odd. + +**Parity via polynomials.** Over `𝔽₂` let `F_n` be the row polynomial +`∑_i T(n, i - 2n) X^i`; it satisfies `F_{n+2} = (1+X⁴) F_{n+1} + (X³+X⁵) F_n`. With +`v = 1 + X²` we have `1 + X⁴ = v²` and `X³ + X⁵ = X³ v`, so `G_n = F_n v^n` satisfies +`G_{n+2} = v³ G_{n+1} + v³ X³ G_n`, whose solution is the Fibonacci-type sum +`G_n = ∑_{p+q=n} C(p,q) (v³)^p (X³)^q`. Cancelling `v^n` gives +`F_n = ∑_{p+q=n} C(p,q) X^{3q} v^{2p-q}`, and `[X^j] v^e = C(e, j/2)` for even `j`. + +* `[X^{2n}] F_n`: each term is `C(p,q) C(2c, c)` with `2c = 2p - q ≥ 1`, which is even. +* `[X^{2n+1}] F_n`: the term `(p,q)` is `C(p,q) C(2c+1, c)` with `2p - q = 2c + 1`. + By Lucas' theorem `C(2c+1, c)` is odd iff `c + 1 = 2^t`. If moreover `C(p,q)` is odd, then + with `D = p - q` we have `C(D+q, q)` odd and `2D + q + 1 = 2^{t+1}`, and Lucas' theorem + forces `D = 0` (induction on `t`). So only the diagonal term `p = q = n/2` survives, and it + is odd iff `n/2 = 2c+1` with `c + 1 = 2^t`, i.e. iff `n + 2 = 2^{t+2}`. +-/ + +namespace Math0.Frontier.A355339 +open Math0.Statements.A355339 +open Polynomial Finset + +/-! ### Binomial parities (Lucas' theorem at `p = 2`) -/ + +/-- Lucas' theorem at the prime `2`. -/ +private lemma lucas2 (n k : ℕ) : + n.choose k % 2 = ((n % 2).choose (k % 2) * (n / 2).choose (k / 2)) % 2 := + @Choose.choose_modEq_choose_mod_mul_choose_div_nat n k 2 ⟨Nat.prime_two⟩ + +/-- `C(2b+1, b)` is odd iff `b + 1` is a power of two. -/ +private lemma oddC : ∀ b : ℕ, (2 * b + 1).choose b % 2 = 1 ↔ ∃ t, b + 1 = 2 ^ t := by + intro b + induction b using Nat.strong_induction_on with + | _ b ih => + rw [lucas2] + have h1 : (2 * b + 1) % 2 = 1 := by omega + have h2 : (2 * b + 1) / 2 = b := by omega + have h3 : (1 : ℕ).choose (b % 2) = 1 := by + rcases Nat.mod_two_eq_zero_or_one b with h | h <;> rw [h] <;> rfl + rw [h1, h2, h3, one_mul] + rcases Nat.even_or_odd' b with ⟨c, rfl | rfl⟩ + · rcases Nat.eq_zero_or_pos c with rfl | hc + · simp only [Nat.mul_zero, Nat.zero_div, Nat.choose_zero_right, Nat.zero_add] + exact ⟨fun _ => ⟨0, rfl⟩, fun _ => trivial⟩ + · have hd := Nat.two_dvd_centralBinom_of_one_le hc + rw [Nat.centralBinom_eq_two_mul_choose] at hd + have : 2 * c / 2 = c := by omega + rw [this, Nat.mod_eq_zero_of_dvd hd] + constructor + · intro h; omega + · rintro ⟨t, ht⟩ + rcases t with _ | t + · simp at ht; omega + · rw [pow_succ] at ht; omega + · have : (2 * c + 1) / 2 = c := by omega + rw [this, ih c (by omega)] + constructor + · rintro ⟨t, ht⟩; exact ⟨t + 1, by rw [pow_succ]; omega⟩ + · rintro ⟨t, ht⟩ + rcases t with _ | t + · simp at ht + · exact ⟨t, by rw [pow_succ] at ht; omega⟩ + +/-- If `C(D+q, q)` is odd and `2D + q + 1` is a power of two, then `D = 0` +(no carries in `2D + q`, and `D ⊆ q` bitwise, force `D = 0`). -/ +private lemma dzero : ∀ (t D q : ℕ), (D + q).choose q % 2 = 1 → 2 * D + q + 1 = 2 ^ t → D = 0 := by + intro t + induction t with + | zero => intro D q _ h; simp at h; omega + | succ t ih => + intro D q hc h + rw [pow_succ] at h + obtain ⟨q', rfl⟩ : ∃ q', q = 2 * q' + 1 := ⟨q / 2, by omega⟩ + rw [lucas2] at hc + rcases Nat.even_or_odd' D with ⟨D', rfl | rfl⟩ + · have e1 : (2 * D' + (2 * q' + 1)) % 2 = 1 := by omega + have e2 : (2 * q' + 1) % 2 = 1 := by omega + have e3 : (2 * D' + (2 * q' + 1)) / 2 = D' + q' := by omega + have e4 : (2 * q' + 1) / 2 = q' := by omega + rw [e1, e2, e3, e4, Nat.choose_self, one_mul] at hc + have := ih D' q' hc (by omega) + omega + · have e1 : (2 * D' + 1 + (2 * q' + 1)) % 2 = 0 := by omega + have e2 : (2 * q' + 1) % 2 = 1 := by omega + rw [e1, e2] at hc + simp at hc + +/-- A natural number in `ZMod 2` is its parity bit. -/ +private lemma cast_mod2 (x : ℕ) : (x : ZMod 2) = if x % 2 = 1 then 1 else 0 := by + rw [← ZMod.natCast_mod] + rcases Nat.mod_two_eq_zero_or_one x with h | h <;> simp [h] + +/-! ### The row polynomials over `𝔽₂` -/ + +/-- The row polynomial `∑_i T(n, i - 2n) X^i`, reduced mod `2`, via the knight-move recurrence. -/ +private noncomputable def Fp : ℕ → (ZMod 2)[X] + | 0 => 1 + | 1 => 1 + X ^ 4 + | n + 2 => (1 + X ^ 4) * Fp (n + 1) + (X ^ 3 + X ^ 5) * Fp n + +/-- Row `0` of the triangle. -/ +private lemma T0 (k : ℤ) : T 0 k = if k = 0 then 1 else 0 := by + split_ifs with h + · subst h; exact T_zero_zero + · exact T_eq_zero 0 k (by have := abs_pos.mpr h; simpa using this) + +/-- Shifting the position by `j` to the left, with zero extension. -/ +private lemma T_shift (n j m : ℕ) : + (T n ((m : ℤ) - 2 * n - j) : ZMod 2) = + if j ≤ m then (T n (((m - j : ℕ) : ℤ) - 2 * n) : ZMod 2) else 0 := by + split_ifs with h + · congr 2; push_cast [h]; ring + · rw [T_eq_zero n _ (by rw [abs_of_neg (by omega)]; omega), Nat.cast_zero] + +/-- The coefficients of `Fp n` are the entries of row `n` mod `2`. -/ +private theorem T_coeff : ∀ (n m : ℕ), (T n ((m : ℤ) - 2 * n) : ZMod 2) = (Fp n).coeff m + | 0, m => by + rw [T0, Fp, coeff_one] + split_ifs <;> first | omega | simp + | 1, m => by + rw [T_one, T0, T0, Fp, coeff_add, coeff_one, coeff_X_pow] + split_ifs <;> first | omega | simp + | n + 2, m => by + rw [T_add_two, Fp, coeff_add, add_mul, add_mul, coeff_add, coeff_add, one_mul, + coeff_X_pow_mul', coeff_X_pow_mul', coeff_X_pow_mul', ← T_coeff (n + 1), ← T_coeff (n + 1), + ← T_coeff n, ← T_coeff n] + have e1 := T_shift (n + 1) 4 m + have e3 := T_shift n 5 m + have e4 := T_shift n 3 m + push_cast at e1 e3 e4 ⊢ + rw [show (m : ℤ) - 2 * (n + 2) - 2 = m - 2 * (n + 1) - 4 by ring, + show (m : ℤ) - 2 * (n + 2) + 2 = m - 2 * (n + 1) by ring, + show (m : ℤ) - 2 * (n + 2) - 1 = m - 2 * n - 5 by ring, + show (m : ℤ) - 2 * (n + 2) + 1 = m - 2 * n - 3 by ring, e1, e3, e4] + split_ifs <;> ring + +/-- The Fibonacci-type sum `∑_{p+q=n} C(p,q) A^p B^q`. -/ +private noncomputable def hsum {R : Type*} [CommSemiring R] (A B : R) (n : ℕ) : R := + ∑ p ∈ antidiagonal n, (p.1.choose p.2 : R) * A ^ p.1 * B ^ p.2 + +/-- `hsum` satisfies `h(n+2) = A h(n+1) + A B h(n)` (Pascal's rule). -/ +private lemma hsum_rec {R : Type*} [CommSemiring R] (A B : R) (n : ℕ) : + hsum A B (n + 2) = A * hsum A B (n + 1) + A * B * hsum A B n := by + unfold hsum + rw [Nat.sum_antidiagonal_succ, Nat.sum_antidiagonal_succ'] + rw [Nat.sum_antidiagonal_succ' (n := n)] + simp only [Nat.choose_succ_succ, Nat.choose_zero_succ, Nat.choose_zero_right, Nat.cast_add, + Nat.cast_zero, Nat.cast_one, zero_mul, zero_add, Finset.mul_sum] + rw [mul_add, Finset.mul_sum, add_assoc (A * _), ← Finset.sum_add_distrib] + congr 1 + · ring + · refine Finset.sum_congr rfl fun x _ => ?_ + rw [Nat.succ_eq_add_one] + ring + +/-- `2 = 0` in `𝔽₂[X]`. -/ +private lemma two_eq_zero : (2 : (ZMod 2)[X]) = 0 := by + exact_mod_cast CharP.cast_eq_zero (ZMod 2)[X] 2 + +/-- `1 + X⁴ = (1 + X²)²` in `𝔽₂[X]`. -/ +private lemma one_add_X4 : (1 + X ^ 4 : (ZMod 2)[X]) = (1 + X ^ 2) ^ 2 := by + linear_combination (-(X : (ZMod 2)[X]) ^ 2) * two_eq_zero + +/-- `Fp n · v^n = ∑_{p+q=n} C(p,q) (v³)^p (X³)^q` with `v = 1 + X²`. -/ +private lemma Fp_mul (n : ℕ) : + Fp n * (1 + X ^ 2) ^ n = hsum ((1 + X ^ 2 : (ZMod 2)[X]) ^ 3) (X ^ 3) n := by + induction n using Nat.twoStepInduction with + | zero => simp [Fp, hsum] + | one => + rw [Fp, one_add_X4] + simp [hsum, Nat.sum_antidiagonal_succ] + ring + | more n ih0 ih1 => + rw [hsum_rec, ← ih0, ← ih1, Fp, one_add_X4] + ring + +/-- `1 + X² ≠ 0`. -/ +private lemma vne : (1 + X ^ 2 : (ZMod 2)[X]) ≠ 0 := by + intro h + have := congrArg (Polynomial.eval 0) h + simp at this + +/-- Closed form `Fp n = ∑_{p+q=n} C(p,q) X^{3q} (1+X²)^{2p-q}`. -/ +private lemma Fp_closed (n : ℕ) : + Fp n = ∑ p ∈ antidiagonal n, + (p.1.choose p.2 : (ZMod 2)[X]) * (X ^ (3 * p.2) * (1 + X ^ 2) ^ (2 * p.1 - p.2)) := by + apply mul_right_cancel₀ (pow_ne_zero n vne) + rw [Fp_mul, hsum, Finset.sum_mul] + refine Finset.sum_congr rfl fun p hp => ?_ + rw [HasAntidiagonal.mem_antidiagonal] at hp + rcases le_or_gt p.2 p.1 with h | h + · rw [← pow_mul, ← pow_mul, mul_comm 3 p.2, show 3 * p.1 = 2 * p.1 - p.2 + n by omega, pow_add] + ring + · rw [Nat.choose_eq_zero_of_lt h] + simp + +/-- `[X^j] (1 + X²)^e = C(e, j/2)` for even `j`, and `0` for odd `j`. -/ +private lemma vpow_coeff (e j : ℕ) : + ((1 + X ^ 2 : (ZMod 2)[X]) ^ e).coeff j = + if 2 ∣ j then ((e.choose (j / 2) : ℕ) : ZMod 2) else 0 := by + have : (1 + X ^ 2 : (ZMod 2)[X]) ^ e = expand (ZMod 2) 2 ((1 + X) ^ e) := by + simp [map_pow, map_add, expand_X] + rw [this, coeff_expand two_pos, coeff_one_add_X_pow] + +/-- Coefficient formula for `Fp n`. -/ +private lemma Fp_coeff (n m : ℕ) : + (Fp n).coeff m = ∑ p ∈ antidiagonal n, (p.1.choose p.2 : ZMod 2) * + (if 3 * p.2 ≤ m then (if 2 ∣ (m - 3 * p.2) then + (((2 * p.1 - p.2).choose ((m - 3 * p.2) / 2) : ℕ) : ZMod 2) else 0) else 0) := by + rw [Fp_closed, finsetSum_coeff] + refine Finset.sum_congr rfl fun p _ => ?_ + rw [coeff_natCast_mul, coeff_X_pow_mul'] + split_ifs <;> simp [vpow_coeff, *] + +/-! ### The central coefficients -/ + +/-- Every term of `[X^{2n}] Fp n` vanishes for `n ≥ 1`. -/ +private lemma term_even (n : ℕ) (hn : 1 ≤ n) (p : ℕ × ℕ) (hp : p.1 + p.2 = n) : + (p.1.choose p.2 : ZMod 2) * + (if 3 * p.2 ≤ 2 * n then (if 2 ∣ (2 * n - 3 * p.2) then + (((2 * p.1 - p.2).choose ((2 * n - 3 * p.2) / 2) : ℕ) : ZMod 2) else 0) else 0) = 0 := by + obtain ⟨a, b⟩ := p + simp only at hp ⊢ + rcases lt_or_ge a b with hab | hab + · rw [Nat.choose_eq_zero_of_lt hab, Nat.cast_zero, zero_mul] + · split_ifs with h1 h2 + · obtain ⟨c, hc⟩ : ∃ c, 2 * a - b = 2 * c := ⟨(2 * a - b) / 2, by omega⟩ + have e1 : (2 * n - 3 * b) / 2 = c := by omega + have hd := Nat.two_dvd_centralBinom_of_one_le (show 0 < c by omega) + rw [Nat.centralBinom_eq_two_mul_choose] at hd + rw [hc, e1, (ZMod.natCast_eq_zero_iff _ 2).mpr hd, mul_zero] + · rw [mul_zero] + · rw [mul_zero] + +/-- Every off-diagonal term (`p ≠ q`) of `[X^{2n+1}] Fp n` vanishes. -/ +private lemma term_off (n : ℕ) (p : ℕ × ℕ) (hp : p.1 + p.2 = n) (hne : p.1 ≠ p.2) : + (p.1.choose p.2 : ZMod 2) * + (if 3 * p.2 ≤ 2 * n + 1 then (if 2 ∣ (2 * n + 1 - 3 * p.2) then + (((2 * p.1 - p.2).choose ((2 * n + 1 - 3 * p.2) / 2) : ℕ) : ZMod 2) else 0) else 0) = + 0 := by + obtain ⟨a, b⟩ := p + simp only at hp hne ⊢ + rcases lt_or_ge a b with hab | hab + · rw [Nat.choose_eq_zero_of_lt hab, Nat.cast_zero, zero_mul] + · rw [if_pos (by omega)] + by_cases h2 : 2 ∣ (2 * n + 1 - 3 * b) + · rw [if_pos h2] + obtain ⟨c, hc⟩ : ∃ c, 2 * a - b = 2 * c + 1 := ⟨(2 * a - b) / 2, by omega⟩ + have e1 : (2 * n + 1 - 3 * b) / 2 = c + 1 := by omega + rw [hc, e1, Nat.choose_symm_half, cast_mod2, cast_mod2] + by_cases hc1 : (2 * c + 1).choose c % 2 = 1 + · obtain ⟨t, ht⟩ := (oddC c).mp hc1 + by_cases hc2 : a.choose b % 2 = 1 + · exfalso + have h3 : (a - b + b).choose b % 2 = 1 := by rwa [Nat.sub_add_cancel hab] + have h4 : 2 * (a - b) + b + 1 = 2 ^ (t + 1) := by rw [pow_succ]; omega + have := dzero (t + 1) (a - b) b h3 h4 + omega + · rw [if_neg hc2, zero_mul] + · rw [if_neg hc1, mul_zero] + · rw [if_neg h2, mul_zero] + +/-- For `n ≥ 1`, the central entry `T(n,0)` is even. -/ +private lemma T0_even (n : ℕ) (hn : 1 ≤ n) : T n 0 % 2 = 0 := by + have hT : (T n 0 : ZMod 2) = (Fp n).coeff (2 * n) := by + rw [← T_coeff]; congr 2; push_cast; ring + rw [Fp_coeff, Finset.sum_eq_zero + (fun p hp => term_even n hn p (HasAntidiagonal.mem_antidiagonal.mp hp))] at hT + have := (ZMod.natCast_eq_zero_iff _ 2).mp hT + omega + +/-- `T(n,1)` is odd iff `n + 2` is a power of two that is at least `4`. -/ +private lemma T1_parity (n : ℕ) : T n 1 % 2 = 1 ↔ ∃ t, n + 2 = 2 ^ (t + 2) := by + have hT : (T n 1 : ZMod 2) = (Fp n).coeff (2 * n + 1) := by + rw [← T_coeff]; congr 2; push_cast; ring + rw [Fp_coeff] at hT + rcases Nat.even_or_odd' n with ⟨q, rfl | rfl⟩ + · rw [Finset.sum_eq_single (q, q)] at hT + · simp only at hT + rw [Nat.choose_self, Nat.cast_one, one_mul, if_pos (by omega)] at hT + rcases Nat.even_or_odd' q with ⟨c, rfl | rfl⟩ + · rw [if_neg (by omega)] at hT + have := (ZMod.natCast_eq_zero_iff _ 2).mp hT + constructor + · intro h; omega + · rintro ⟨t, ht⟩; rw [pow_add] at ht; omega + · rw [if_pos (by omega)] at hT + have e1 : (2 * (2 * (2 * c + 1)) + 1 - 3 * (2 * c + 1)) / 2 = c + 1 := by omega + have e2 : 2 * (2 * c + 1) - (2 * c + 1) = 2 * c + 1 := by omega + rw [e1, e2, Nat.choose_symm_half, ZMod.natCast_eq_natCast_iff'] at hT + rw [hT, oddC] + constructor + · rintro ⟨t, ht⟩; exact ⟨t, by rw [pow_add]; omega⟩ + · rintro ⟨t, ht⟩; exact ⟨t, by rw [pow_add] at ht; omega⟩ + · intro p hp hne + apply term_off _ p (HasAntidiagonal.mem_antidiagonal.mp hp) + intro h + have := HasAntidiagonal.mem_antidiagonal.mp hp + exact hne (Prod.ext (by omega) (by omega)) + · intro h + exact absurd (HasAntidiagonal.mem_antidiagonal.mpr (by simp; omega)) h + · rw [Finset.sum_eq_zero + (fun p hp => term_off _ p (HasAntidiagonal.mem_antidiagonal.mp hp) (by + have := HasAntidiagonal.mem_antidiagonal.mp hp; omega))] at hT + have := (ZMod.natCast_eq_zero_iff _ 2).mp hT + constructor + · intro h; omega + · rintro ⟨t, ht⟩; rw [pow_add] at ht; omega + +/-! ### Symmetry and the run length -/ + +/-- The rows are symmetric: `T(n,-k) = T(n,k)`. -/ +private theorem T_symm : ∀ (n : ℕ) (k : ℤ), T n (-k) = T n k + | 0, k => by rw [T0, T0]; simp [neg_eq_zero] + | 1, k => by + rw [T_one, T_one, T0, T0, T0, T0] + split_ifs <;> omega + | n + 2, k => by + rw [T_add_two, T_add_two, show -k - 2 = -(k + 2) by ring, show -k + 2 = -(k - 2) by ring, + show -k - 1 = -(k + 1) by ring, show -k + 1 = -(k - 1) by ring, T_symm (n + 1), + T_symm (n + 1), T_symm n, T_symm n] + ring + +/-- The first two entries of `(range (2n+1)).map f` for `n ≥ 1`. -/ +private lemma range_map (n : ℕ) (hn : 1 ≤ n) (f : ℕ → ℕ) : + ∃ rest, (List.range (2 * n + 1)).map f = f 0 :: f 1 :: rest := by + obtain ⟨k, hk⟩ : ∃ k, 2 * n + 1 = k + 1 + 1 := ⟨2 * n - 1, by omega⟩ + rw [hk, List.range_succ_eq_map, List.range_succ_eq_map] + exact ⟨(List.range k).map (f ∘ Nat.succ ∘ Nat.succ), by simp⟩ + +/-- The even prefix of `x :: y :: rest` with `x` even has length `≥ 1`, and length `1` iff +`y` is odd. -/ +private lemma tw (x y : ℕ) (rest : List ℕ) (hx : x % 2 = 0) : + 1 ≤ ((x :: y :: rest).takeWhile (fun z => z % 2 == 0)).length ∧ + (((x :: y :: rest).takeWhile (fun z => z % 2 == 0)).length = 1 ↔ y % 2 = 1) := by + rw [List.takeWhile_cons, List.takeWhile_cons] + simp only [hx, beq_self_eq_true, if_true, List.length_cons] + split_ifs with h + · simp only [beq_iff_eq] at h + simp only [List.length_cons] + omega + · simp at h; simp [h] + +/-- The run-length expression of `a` equals `1` iff the entry next to the (even) centre is odd. -/ +private lemma run_one (x x' y y' : ℕ) (r r' : List ℕ) (hx : x % 2 = 0) (hx' : x' % 2 = 0) + (hy : y' % 2 = y % 2) : + (if ((x :: y :: r).takeWhile (fun z => z % 2 == 0)).length = 0 then 0 else + ((x' :: y' :: r').takeWhile (fun z => z % 2 == 0)).length + + ((x :: y :: r).takeWhile (fun z => z % 2 == 0)).length - 1) = 1 ↔ y % 2 = 1 := by + obtain ⟨hR1, hR2⟩ := tw x y r hx + obtain ⟨hL1, hL2⟩ := tw x' y' r' hx' + rw [if_neg (by omega)] + constructor + · intro h + exact hR2.mp (by omega) + · intro h + have := hR2.mpr h + have := hL2.mpr (by omega) + omega + +/-- For `n ≥ 1`, `a(n) = 1` iff `T(n,1)` is odd. -/ +private lemma a_one_iff (n : ℕ) (hn : 1 ≤ n) : a n = 1 ↔ T n 1 % 2 = 1 := by + rw [a_eq, if_neg (by omega)] + dsimp only + obtain ⟨r1, h1⟩ := range_map n hn (fun k : ℕ => T n k) + obtain ⟨r2, h2⟩ := range_map n hn (fun k : ℕ => T n (-k)) + rw [h1, h2] + have h0 := T0_even n hn + exact run_one _ _ _ _ _ _ (by simpa using h0) (by simpa using h0) (by simp [T_symm]) + +/-- Sigrist's conjecture holds: `a(n) = 1` iff `n > 0` and `n = 2^m - 2`. -/ +theorem result : statement := by + intro n + rcases Nat.eq_zero_or_pos n with rfl | hn + · simp [a] + · rw [a_one_iff n hn, T1_parity] + constructor + · rintro ⟨t, ht⟩ + refine ⟨hn, t + 2, ?_⟩ + have := congrArg (Nat.cast : ℕ → ℤ) ht + push_cast at this + linarith + · rintro ⟨-, m, hm⟩ + rcases m with _ | _ | t + · norm_num at hm; omega + · norm_num at hm; omega + · refine ⟨t, ?_⟩ + have : ((n + 2 : ℕ) : ℤ) = ((2 ^ (t + 2) : ℕ) : ℤ) := by push_cast; linarith + exact_mod_cast this + +end Math0.Frontier.A355339 + +#math0_settles Math0.Frontier.A355339.result Math0.Statements.A355339.statement diff --git a/lean/Math0/Frontier/OEIS/A355360.lean b/lean/Math0/Frontier/OEIS/A355360.lean new file mode 100644 index 0000000..41dc81a --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A355360.lean @@ -0,0 +1,1040 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A355360 +import Math0.Audit + +/-! +# Columns 1 and 2 of the theta-series triangle A355360 are `P(x)^3` and `2 P(x)^6` + +We prove both conjectures of Paul D. Hanna in A355360: `T(n+1, 1) = A000716(n)` (partitions +into parts of 3 kinds) and `T(n+2, 2) = 2 · A023005(n)` (partitions into parts of 6 kinds). + +**Mathematics.** Let `F(B) = ∑_{n ∈ ℤ} (-1)^n x^{T(n)} B^n` with `T(n) = n(n+1)/2`; grouping `n` +and `-1-n`, `F(B) = ∑_{n ≥ 0} (-1)^n x^{T(n)} (B^n - B^{-(n+1)})`. Work modulo `y^3`. Put +`u = x P^3`, `w = y u + 2 y^2 u^2` and `E = 1 + w`. Since `w^3 = 0`, +`E^n - E^{-(n+1)} = (1+w)^n - (1-w+w^2)^{n+1} = (2n+1)(w - w^2) = (2n+1)(y u + y^2 u^2)`, so +`F(E) = S · (y u + y^2 u^2)` with `S = ∑_{n ≥ 0} (-1)^n (2n+1) x^{T(n)}`. **Jacobi's identity** +`∏ (1 - x^k)^3 = S` gives `S P^3 = 1`, hence `S u = x` and `F(E) = x y (1 + y u) = x y E` +modulo `y^3`. The recursion of the entry (`coeffs`) is `a_{m+1} = y a_m - [x^{m+1}] F(A_{≤m})`, +and `[x^{m+1}] F(A_{≤m}) = [x^{m+1}] F(E) - e_{m+1}` when `A_{≤m}` is the truncation of `E` (only +the `n = 0` term `-B^{-1}` sees the missing coefficient). By induction `a_m ≡ e_m (mod y^3)`, so +column 1 is `u = x P^3` and column 2 is `2 u^2 = 2 x^2 P^6`. + +**Jacobi's identity** is proved in the truncated form `(q;q)_n^3 ≡ ∑_{k ≤ n} (-1)^k (2k+1) q^{T(k)} +(mod q^{n+1})`. With Gaussian binomials `G(j,k) = (q;q)_{j+k} / ((q;q)_j (q;q)_k)` (in `ℤ⟦q⟧`), the +`q`-binomial theorem (two `q`-Pascal rules, induction) expands +`Φ(u) = ∏_{i exact Cg.rfl' + | succ k ih => rw [pow_succ, pow_succ]; exact ih.mul h + +/-- Congruences modulo `X ^ N` can be summed over a finset. -/ +private theorem Cg.sum {ι : Type*} {N : ℕ} (s : Finset ι) {f g : ι → R⟦X⟧} + (h : ∀ i ∈ s, Cg N (f i) (g i)) : + Cg N (∑ i ∈ s, f i) (∑ i ∈ s, g i) := by + unfold Cg at *; rw [← Finset.sum_sub_distrib]; exact Finset.dvd_sum h + +/-- A congruence modulo `X ^ N'` implies one modulo `X ^ N` for `N ≤ N'`. -/ +private theorem Cg.mono {N N' : ℕ} {f g : R⟦X⟧} (hN : N ≤ N') (h : Cg N' f g) : Cg N f g := + (pow_dvd_pow _ hN).trans h + +/-- Congruent power series modulo `X ^ N` have the same coefficients below `N`. -/ +private theorem Cg.coeff_eq {N : ℕ} {f g : R⟦X⟧} (h : Cg N f g) {i : ℕ} (hi : i < N) : + coeff i f = coeff i g := by + have := (X_pow_dvd_iff.1 h) i hi + rwa [map_sub, sub_eq_zero] at this + +/-- Power series with the same coefficients below `N` are congruent modulo `X ^ N`. -/ +private theorem cg_of_coeff {N : ℕ} {f g : R⟦X⟧} (h : ∀ i < N, coeff i f = coeff i g) : Cg N f g := + X_pow_dvd_iff.2 fun i hi => by rw [map_sub, h i hi, sub_self] + +/-- Multiplying a congruence modulo `X ^ N` by `X ^ e` gives one modulo `X ^ (N + e)`. -/ +private theorem Cg.X_pow_mul {N : ℕ} (e : ℕ) {f g : R⟦X⟧} (h : Cg N f g) : + Cg (N + e) (X ^ e * f) (X ^ e * g) := by + unfold Cg at *; rw [← mul_sub, pow_add, mul_comm ((X : R⟦X⟧) ^ N)]; exact mul_dvd_mul_left _ h + +/-- Triangular numbers. -/ +private def tri (k : ℕ) : ℕ := k * (k + 1) / 2 + +/-- `T(k+1) = T(k) + (k+1)`. -/ +private theorem tri_succ (k : ℕ) : tri (k + 1) = tri k + (k + 1) := by + unfold tri + rw [show (k + 1) * (k + 1 + 1) = k * (k + 1) + 2 * (k + 1) by ring, + Nat.add_mul_div_left _ _ (by norm_num)] + +/-- `k ≤ T(k)`. -/ +private theorem le_tri (k : ℕ) : k ≤ tri k := by + induction k with + | zero => simp + | succ k ih => rw [tri_succ]; omega + +/-- `T(0) = 0`. -/ +private theorem tri_zero : tri 0 = 0 := rfl + +/-- `(q;q)_a`. -/ +private noncomputable def qp (a : ℕ) : R⟦X⟧ := ∏ j ∈ range a, (1 - X ^ (j + 1)) + +/-- `(q;q)_{a+1} = (q;q)_a (1 - q^{a+1})`. -/ +private theorem qp_succ (a : ℕ) : (qp (a + 1) : R⟦X⟧) = qp a * (1 - X ^ (a + 1)) := + prod_range_succ _ _ + +/-- `(q;q)_0 = 1`. -/ +private theorem qp_zero : (qp 0 : R⟦X⟧) = 1 := prod_range_zero _ + +/-- `(q;q)_a` has constant coefficient `1`. -/ +private theorem constantCoeff_qp (a : ℕ) : constantCoeff (qp a : R⟦X⟧) = 1 := by + simp [qp, map_prod] + +/-- The inverse `1/(q;q)_a` in `R⟦q⟧`. -/ +private noncomputable def qpi (a : ℕ) : R⟦X⟧ := invOfUnit (qp a) 1 + +/-- `qpi a` is the inverse of `(q;q)_a`. -/ +private theorem qp_mul_qpi (a : ℕ) : (qp a : R⟦X⟧) * qpi a = 1 := + mul_invOfUnit _ _ (by simp [constantCoeff_qp]) + +/-- `1/(q;q)_0 = 1`. -/ +private theorem qpi_zero : (qpi 0 : R⟦X⟧) = 1 := by + have := qp_mul_qpi (R := R) 0; rwa [qp_zero, one_mul] at this + +/-- `1/(q;q)_a = (1 - q^{a+1}) / (q;q)_{a+1}`. -/ +private theorem qpi_succ (a : ℕ) : (qpi a : R⟦X⟧) = (1 - X ^ (a + 1)) * qpi (a + 1) := by + have h1 := qp_mul_qpi (R := R) a + have h2 := qp_mul_qpi (R := R) (a + 1) + rw [qp_succ] at h2 + linear_combination ((1 - X ^ (a + 1)) * qpi (a + 1)) * h1 - qpi a * h2 + +/-- Gaussian binomial `[j+k choose j]_q`. -/ +private noncomputable def gb (j k : ℕ) : R⟦X⟧ := qp (j + k) * qpi j * qpi k + +/-- Symmetry of the Gaussian binomial. -/ +private theorem gb_comm (j k : ℕ) : (gb j k : R⟦X⟧) = gb k j := by + unfold gb; rw [add_comm]; ring + +/-- `[k choose 0]_q = 1`. -/ +private theorem gb_zero_left (k : ℕ) : (gb 0 k : R⟦X⟧) = 1 := by + unfold gb; rw [zero_add, qpi_zero, mul_one, qp_mul_qpi] + +/-- `[j choose j]_q = 1`. -/ +private theorem gb_zero_right (j : ℕ) : (gb j 0 : R⟦X⟧) = 1 := by + rw [gb_comm, gb_zero_left] + +/-- The `q`-Pascal rule `G(j+1,k+1) = G(j,k+1) + q^{j+1} G(j+1,k)`. -/ +private theorem gb_pascalA (j k : ℕ) : + (gb (j + 1) (k + 1) : R⟦X⟧) = gb j (k + 1) + X ^ (j + 1) * gb (j + 1) k := by + unfold gb + rw [qpi_succ j, qpi_succ k, show j + 1 + (k + 1) = (j + k + 1) + 1 by ring, + show j + (k + 1) = j + k + 1 by ring, show j + 1 + k = j + k + 1 by ring, qp_succ (j + k + 1)] + ring + +/-- The `q`-Pascal rule `G(j+1,k+1) = q^{k+1} G(j,k+1) + G(j+1,k)`. -/ +private theorem gb_pascalB (j k : ℕ) : + (gb (j + 1) (k + 1) : R⟦X⟧) = X ^ (k + 1) * gb j (k + 1) + gb (j + 1) k := by + rw [gb_comm, gb_pascalA, gb_comm k, gb_comm (k + 1)]; ring + + +/-- Exponent of `q` in the coefficient of `u^i` in `∏_{i exact coeff_Φ_zero_zero + | succ a ih => + intro i + rw [Φ_succ_left] + cases i with + | zero => rw [coeff_mul_lin_zero, ih, cf_succ_left_zero] + | succ i => rw [coeff_mul_lin, ih, ih, cf_succ_left] + +/-- The `q`-binomial expansion: the coefficients of `Φ a b` are `cf a b i`. -/ +private theorem coeff_Φ (a b : ℕ) : ∀ i, (Φ a b : Polynomial R⟦X⟧).coeff i = cf a b i := by + induction b with + | zero => exact coeff_Φ_left a + | succ b ih => + intro i + rw [Φ_succ_right] + cases i with + | zero => rw [coeff_mul_lin_zero, ih, cf_succ_right_zero] + | succ i => rw [coeff_mul_lin, ih, ih, cf_succ_right] + + +/-- `Ψ n`, with `Φ n (n+1) = (1 - u) Ψ n`. -/ +private noncomputable def Ψ (n : ℕ) : Polynomial R⟦X⟧ := + (∏ i ∈ range n, (Polynomial.C ((X : R⟦X⟧) ^ (i + 1)) - Polynomial.X)) * + ∏ j ∈ range n, (1 - Polynomial.C ((X : R⟦X⟧) ^ (j + 1)) * Polynomial.X) + +/-- The factor `j = 0` of the second product of `Φ n (n+1)` is `1 - u`. -/ +private theorem Φ_eq (n : ℕ) : (Φ n (n + 1) : Polynomial R⟦X⟧) = (1 - Polynomial.X) * Ψ n := by + simp only [Φ, Ψ, prod_range_succ' (fun j => (1 - Polynomial.C ((X : R⟦X⟧) ^ j) * Polynomial.X)), + pow_zero, map_one, one_mul] + ring + +/-- `Ψ n (1) = (-1)^n (q;q)_n^2`. -/ +private theorem eval_Ψ (n : ℕ) : (Ψ n : Polynomial R⟦X⟧).eval 1 = (-1) ^ n * qp n * qp n := by + simp only [Ψ, Polynomial.eval_mul, Polynomial.eval_prod, Polynomial.eval_sub, Polynomial.eval_C, + Polynomial.eval_X, Polynomial.eval_one, mul_one, qp] + rw [show (∏ i ∈ range n, ((X : R⟦X⟧) ^ (i + 1) - 1)) = + ∏ i ∈ range n, ((-1) * (1 - X ^ (i + 1))) from prod_congr rfl (fun _ _ => by ring), + prod_mul_distrib, prod_const, card_range] + +/-- `Φ n (n+1)` has degree at most `2n+1`. -/ +private theorem natDegree_Φ (n : ℕ) : (Φ n (n + 1) : Polynomial R⟦X⟧).natDegree < 2 * n + 2 := by + have : (Φ n (n + 1) : Polynomial R⟦X⟧).natDegree ≤ 2 * n + 1 := by + rw [Polynomial.natDegree_le_iff_coeff_eq_zero] + intro N hN + rw [coeff_Φ, cf, if_neg (by omega)] + omega + +/-- Differentiating `Φ n (n+1) = (1-u) Ψ n` at `u = 1`: +`-(-1)^n (q;q)_n^2 = ∑_i i · cf n (n+1) i`. -/ +private theorem deriv_identity (n : ℕ) : + -((-1) ^ n * qp n * qp n : R⟦X⟧) = + ∑ i ∈ range (2 * n + 2), cf n (n + 1) i * (i : R⟦X⟧) := by + have h1 : (Polynomial.derivative (Φ n (n + 1) : Polynomial R⟦X⟧)).eval 1 = + -((-1) ^ n * qp n * qp n) := by + rw [Φ_eq, Polynomial.derivative_mul, Polynomial.eval_add, Polynomial.eval_mul, + Polynomial.eval_mul, eval_Ψ] + simp + have h2 : (Polynomial.derivative (Φ n (n + 1) : Polynomial R⟦X⟧)).eval 1 = + ∑ i ∈ range (2 * n + 2), cf n (n + 1) i * (i : R⟦X⟧) := by + rw [Polynomial.derivative_eval, Polynomial.sum_over_range' _ (by simp) _ (natDegree_Φ n)] + simp [coeff_Φ] + rw [← h1, h2] + +/-- `(q;q)_m ≡ (q;q)_k` modulo `q^{k+1}` for `k ≤ m`. -/ +private theorem qp_cg {k m : ℕ} (h : k ≤ m) : Cg (k + 1) (qp m : R⟦X⟧) (qp k) := by + induction m, h using Nat.le_induction with + | base => exact Cg.rfl' + | succ m hkm ih => + rw [qp_succ] + have : Cg (k + 1) ((1 : R⟦X⟧) - X ^ (m + 1)) 1 := by + unfold Cg; rw [sub_sub_cancel_left]; exact (dvd_neg).2 (pow_dvd_pow _ (by omega)) + have := ih.mul this; rwa [mul_one] at this + +/-- `(q;q)_m / (q;q)_k ≡ 1` modulo `q^{k+1}` for `k ≤ m`. -/ +private theorem qp_qpi_cg {k m : ℕ} (h : k ≤ m) : Cg (k + 1) ((qp m : R⟦X⟧) * qpi k) 1 := by + have := (qp_cg (R := R) h).mul (Cg.rfl' (f := qpi k)); rwa [qp_mul_qpi] at this + +/-- If `s + l = 2n+1`, `s ≤ n` and `n ≤ e + s`, then `q^e G(s,l) (q;q)_n ≡ q^e` modulo `q^{n+1}`. -/ +private theorem key_cg {s l n e : ℕ} (hsl : s + l = 2 * n + 1) (hs : s ≤ n) (he : n ≤ e + s) : + Cg (n + 1) ((X : R⟦X⟧) ^ e * (gb s l * qp n)) (X ^ e) := by + have h1 : Cg (s + 1) ((qp (s + l) : R⟦X⟧) * qpi l) 1 := (qp_qpi_cg (by omega)).mono (by omega) + have h2 : Cg (s + 1) ((qp n : R⟦X⟧) * qpi s) 1 := qp_qpi_cg hs + have h3 := (h1.mul h2).X_pow_mul e + rw [mul_one, mul_one] at h3 + have : (gb s l : R⟦X⟧) * qp n = qp (s + l) * qpi l * (qp n * qpi s) := by unfold gb; ring + rw [this] + exact h3.mono (by omega) + +/-- Each term of `deriv_identity`, multiplied by `(q;q)_n`, is `(-1)^i i q^{ex n i}` modulo +`q^{n+1}`. -/ +private theorem term_cg (n i : ℕ) (hi : i < 2 * n + 2) : + Cg (n + 1) (cf n (n + 1) i * (i : R⟦X⟧) * qp n) ((-1) ^ i * (i : R⟦X⟧) * X ^ (ex n i)) := by + have hc : cf n (n + 1) i * (i : R⟦X⟧) * qp n = + (-1) ^ i * (i : R⟦X⟧) * (X ^ (ex n i) * (gb i (n + (n + 1) - i) * qp n)) := by + rw [cf, if_pos (by omega)]; ring + rw [hc] + refine Cg.rfl'.mul ?_ + by_cases hin : i ≤ n + · refine key_cg (by omega) hin ?_ + have : ex n i = tri (n - i) := by rw [ex, if_neg (by omega)] + rw [this]; have := le_tri (n - i); omega + · rw [gb_comm] + refine key_cg (by omega) (by omega) ?_ + have : ex n i = tri (i - n - 1) := by rw [ex, if_pos (by omega)] + rw [this]; have := le_tri (i - n - 1); omega + +/-- The truncated Jacobi series `∑_{k ≤ n} (-1)^k (2k+1) q^{k(k+1)/2}`. -/ +private noncomputable def J (n : ℕ) : R⟦X⟧ := + ∑ k ∈ range (n + 1), (-1) ^ k * (2 * (k : R⟦X⟧) + 1) * X ^ (tri k) + +/-- Pairing the terms `i = n - k` and `i = n + 1 + k`. -/ +private theorem pairing (n : ℕ) : + ∑ i ∈ range (2 * n + 2), (-1) ^ i * (i : R⟦X⟧) * X ^ (ex n i) = (-1) ^ (n + 1) * J n := by + rw [show 2 * n + 2 = (n + 1) + (n + 1) by ring, sum_range_add, + ← sum_range_reflect (fun i => (-1) ^ i * (i : R⟦X⟧) * X ^ (ex n i)) (n + 1), J, mul_sum, + ← sum_add_distrib] + refine sum_congr rfl fun k hk => ?_ + have hk' : k ≤ n := by rw [mem_range] at hk; omega + obtain ⟨d, rfl⟩ : ∃ d, n = k + d := ⟨n - k, by omega⟩ + have e1 : ex (k + d) (k + d + 1 - 1 - k) = tri k := by + rw [ex, if_neg (by omega)]; congr 1; omega + have e2 : ex (k + d) (k + d + 1 + k) = tri k := by + rw [ex, if_pos (by omega)]; congr 1; omega + rw [e1, e2, show k + d + 1 - 1 - k = d by omega] + have s1 : (-1 : R⟦X⟧) ^ (k + d + 1 + k) = (-1) ^ (d + 1) := by + rw [show k + d + 1 + k = (d + 1) + 2 * k by ring, pow_add, pow_mul, neg_one_sq, one_pow, + mul_one] + have s2 : (-1 : R⟦X⟧) ^ (k + d + 1) * (-1) ^ k = (-1) ^ (d + 1) := by + rw [← pow_add, show k + d + 1 + k = (d + 1) + 2 * k by ring, pow_add, pow_mul, neg_one_sq, + one_pow, mul_one] + rw [s1] + push_cast + linear_combination (-(2 * (k : R⟦X⟧) + 1) * X ^ tri k) * s2 + +/-- **Jacobi's identity, truncated**: `(q;q)_n^3 ≡ ∑_{k ≤ n} (-1)^k (2k+1) q^{T(k)}` modulo +`q^{n+1}`. -/ +private theorem jacobi_cg (n : ℕ) : Cg (n + 1) ((qp n : R⟦X⟧) ^ 3) (J n) := by + have hsum : Cg (n + 1) ((∑ i ∈ range (2 * n + 2), cf n (n + 1) i * (i : R⟦X⟧)) * qp n) + (∑ i ∈ range (2 * n + 2), (-1) ^ i * (i : R⟦X⟧) * X ^ (ex n i)) := by + rw [sum_mul] + exact Cg.sum _ fun i hi => term_cg n i (mem_range.1 hi) + rw [← deriv_identity, pairing] at hsum + have h := (Cg.rfl' (f := (-1 : R⟦X⟧) ^ (n + 1))).mul hsum + have hsq : ((-1 : R⟦X⟧) ^ n) ^ 2 = 1 := by + rw [← pow_mul, mul_comm, pow_mul, neg_one_sq, one_pow] + have e1 : (-1 : R⟦X⟧) ^ (n + 1) * (-((-1) ^ n * qp n * qp n) * qp n) = qp n ^ 3 := by + rw [pow_succ]; linear_combination (qp n ^ 3) * hsq + have e2 : (-1 : R⟦X⟧) ^ (n + 1) * ((-1) ^ (n + 1) * J n) = J n := by + rw [pow_succ]; linear_combination (J n) * hsq + rwa [e1, e2] at h + + + +/-- The partition generating function `∑ p(n) q^n`. -/ +private noncomputable def Pgf : R⟦X⟧ := PowerSeries.mk fun n => ((p n : ℕ) : R) + +/-- `∑ pb(n, m) q^n = ∏_{j ≤ m} 1/(1 - q^j)`. -/ +private noncomputable def pbS (m : ℕ) : R⟦X⟧ := PowerSeries.mk fun n => ((pb n m : ℕ) : R) + +/-- `∑ pb(n,0) q^n = 1`. -/ +private theorem pbS_zero : (pbS 0 : R⟦X⟧) = 1 := by + ext n; rw [pbS, coeff_mk, pb_zero_right, coeff_one]; split_ifs <;> simp + +/-- `(1 - q^{m+1}) ∑ pb(n,m+1) q^n = ∑ pb(n,m) q^n`, from `pb_succ`. -/ +private theorem pbS_succ (m : ℕ) : (pbS (m + 1) : R⟦X⟧) * (1 - X ^ (m + 1)) = pbS m := by + ext n + rw [mul_sub, mul_one, map_sub, mul_comm, coeff_X_pow_mul'] + simp only [pbS, coeff_mk] + rw [pb_succ n m] + split_ifs <;> push_cast <;> ring + +/-- `(∑ pb(n,m) q^n) (q;q)_m = 1`. -/ +private theorem pbS_mul_qp (m : ℕ) : (pbS m : R⟦X⟧) * qp m = 1 := by + induction m with + | zero => rw [pbS_zero, qp_zero, one_mul] + | succ m ih => + calc (pbS (m + 1) : R⟦X⟧) * qp (m + 1) = (pbS (m + 1) * (1 - X ^ (m + 1))) * qp m := by + rw [qp_succ]; ring + _ = 1 := by rw [pbS_succ, ih] + +/-- `pb n m = pb n n` for `m ≥ n`. -/ +private theorem pb_stable {n m : ℕ} (h : n ≤ m) : pb n m = pb n n := by + induction m, h using Nat.le_induction with + | base => rfl + | succ m hnm ih => rw [pb_succ, if_neg (by omega), add_zero, ih] + +/-- `P ≡ ∑ pb(n,N) q^n` modulo `q^{N+1}`. -/ +private theorem Pgf_cg (N : ℕ) : Cg (N + 1) (Pgf : R⟦X⟧) (pbS N) := + cg_of_coeff fun i hi => by + simp only [Pgf, pbS, coeff_mk, p_eq_pb, pb_stable (show i ≤ N by omega)] + +/-- `P (q;q)_N ≡ 1` modulo `q^{N+1}`. -/ +private theorem Pgf_qp_cg (N : ℕ) : Cg (N + 1) ((Pgf : R⟦X⟧) * qp N) 1 := by + have := (Pgf_cg (R := R) N).mul (Cg.rfl' (f := qp N)); rwa [pbS_mul_qp] at this + +/-- `J_N P^3 ≡ 1` modulo `q^{N+1}` (Jacobi's identity and the partition generating function). -/ +private theorem J_Pgf_cg (N : ℕ) : Cg (N + 1) (J N * (Pgf : R⟦X⟧) ^ 3) 1 := by + have h1 := ((jacobi_cg (R := R) N).symm).mul (Cg.rfl' (f := (Pgf : R⟦X⟧) ^ 3)) + have h2 := (Pgf_qp_cg (R := R) N).pow 3 + rw [one_pow] at h2 + refine h1.trans ?_ + rw [← mul_pow, mul_comm]; exact h2 + +/-- The coefficient of `q^n` in `F^k` as a sum over `k`-tuples summing to `n`. -/ +private theorem coeff_pow_tuple (F : R⟦X⟧) (k n : ℕ) : + coeff n (F ^ k) = ∑ f ∈ Finset.Nat.antidiagonalTuple k n, ∏ i, coeff (f i) F := by + have : F ^ k = ∏ _i : Fin k, F := by simp + rw [this, coeff_prod, ← Finset.piAntidiag_univ_fin_eq_antidiagonalTuple, finsuppAntidiag, + sum_map] + exact sum_attach (univ.piAntidiag n) (fun f => ∏ i, coeff (f i) F) + + +/-- Evaluate a coefficient list at `y`. -/ +private def ev (y : R) : Poly → R + | [] => 0 + | a :: l => (a : R) + y * ev y l + +/-- Evaluation of the empty list. -/ +@[simp] private theorem ev_nil (y : R) : ev y [] = 0 := rfl +/-- Evaluation of a cons. -/ +@[simp] private theorem ev_cons (y : R) (a : ℤ) (l : Poly) : ev y (a :: l) = a + y * ev y l := rfl + +/-- `padd` is addition of polynomials. -/ +private theorem ev_padd (y : R) : ∀ p q : Poly, ev y (padd p q) = ev y p + ev y q + | [], q => by simp [padd] + | a :: p, [] => by simp [padd] + | a :: p, b :: q => by simp only [padd, ev_cons, ev_padd y p q]; push_cast; ring + +/-- `pscale` is multiplication by a constant. -/ +private theorem ev_pscale (y : R) (c : ℤ) : ∀ p : Poly, ev y (pscale c p) = c * ev y p + | [] => by simp [pscale] + | a :: p => by + have := ev_pscale y c p + simp only [pscale, List.map_cons] at this ⊢ + rw [ev_cons, ev_cons, this]; push_cast; ring + +/-- `pmul` is multiplication of polynomials. -/ +private theorem ev_pmul (y : R) : ∀ p q : Poly, ev y (pmul p q) = ev y p * ev y q + | [], q => by simp [pmul] + | a :: p, q => by + rw [pmul, ev_padd, ev_pscale, ev_cons, ev_cons, ev_pmul y p q]; push_cast; ring + +/-- A `foldl` of `padd` is a sum. -/ +private theorem ev_foldl_padd (y : R) (f : ℕ → Poly) : ∀ (l : List ℕ) (s : Poly), + ev y (l.foldl (fun s j => padd s (f j)) s) = ev y s + (l.map fun j => ev y (f j)).sum + | [], s => by simp + | j :: l, s => by + rw [List.foldl_cons, ev_foldl_padd y f l, ev_padd, List.map_cons, List.sum_cons]; ring + +/-- A sum over `List.range` is a `Finset.range` sum. -/ +private theorem list_range_sum (g : ℕ → R) (n : ℕ) : + ((List.range n).map g).sum = ∑ j ∈ range n, g j := by + induction n with + | zero => simp + | succ n ih => + rw [List.range_succ, List.map_append, List.sum_append, ih, sum_range_succ]; simp + +/-- The power series whose coefficients are the evaluated entries of a list. -/ +private noncomputable def evS (y : R) (A : Ser) : R⟦X⟧ := PowerSeries.mk fun i => ev y (A.getD i []) + +/-- Coefficients of `evS`. -/ +@[simp] private theorem coeff_evS (y : R) (A : Ser) (i : ℕ) : + coeff i (evS y A) = ev y (A.getD i []) := coeff_mk _ _ + +/-- `mulCoeff A B i` is the coefficient of `x^i` in the product. -/ +private theorem ev_mulCoeff (y : R) (A B : Ser) (i : ℕ) : + ev y (mulCoeff A B i) = coeff i (evS y A * evS y B) := by + rw [mulCoeff, ev_foldl_padd y (fun j => pmul (A.getD j []) (B.getD (i - j) [])), ev_nil, + zero_add, list_range_sum, coeff_mul, + Finset.Nat.sum_antidiagonal_eq_sum_range_succ + (fun j k => coeff j (evS y A) * coeff k (evS y B))] + simp [ev_pmul] + +/-- The entries of `smul L A B`. -/ +private theorem getD_smul (L : ℕ) (A B : Ser) (i : ℕ) : + (smul L A B).getD i [] = if i < L then mulCoeff A B i else [] := by + rw [smul, List.getD_eq_getElem?_getD, List.getElem?_map] + split_ifs with h + · rw [List.getElem?_range h]; rfl + · rw [List.getElem?_eq_none (by simp; omega)]; rfl + +/-- `smul L` is the product modulo `x^L`. -/ +private theorem cg_smul (y : R) (L : ℕ) (A B : Ser) : + Cg L (evS y (smul L A B)) (evS y A * evS y B) := + cg_of_coeff fun i hi => by rw [coeff_evS, getD_smul, if_pos hi, ev_mulCoeff] + +/-- One more step of the loop in `sinv`. -/ +private theorem sinv_succ (L : ℕ) (A : Ser) : sinv (L + 1) A = sinv L A ++ [if L = 0 then [1] else + pscale (-1) ((List.range L).foldl + (fun s j => padd s (pmul (A.getD (j + 1) []) ((sinv L A).getD (L - 1 - j) []))) [])] := by + simp only [sinv, List.range_succ, List.foldl_append, List.foldl_cons, List.foldl_nil] + +/-- `sinv L A` has length `L`. -/ +private theorem length_sinv (L : ℕ) (A : Ser) : (sinv L A).length = L := by + induction L with + | zero => rfl + | succ L ih => rw [sinv_succ, List.length_append, ih]; rfl + +/-- The entries of `sinv` are stable once computed. -/ +private theorem getD_sinv_of_lt {L M : ℕ} (h : L ≤ M) (A : Ser) {i : ℕ} (hi : i < L) : + (sinv M A).getD i [] = (sinv L A).getD i [] := by + induction M, h using Nat.le_induction with + | base => rfl + | succ M hLM ih => + rw [sinv_succ, List.getD_append _ _ _ _ (by rw [length_sinv]; omega), ih] + +/-- The recursion satisfied by the entries of `sinv L A`. -/ +private theorem ev_sinv (y : R) (A : Ser) {L i : ℕ} (hi : i < L) : + ev y ((sinv L A).getD i []) = if i = 0 then 1 else + -∑ j ∈ range i, ev y (A.getD (j + 1) []) * ev y ((sinv L A).getD (i - 1 - j) []) := by + rw [getD_sinv_of_lt (show i + 1 ≤ L by omega) A (Nat.lt_succ_self i), sinv_succ, + List.getD_append_right _ _ _ _ (by rw [length_sinv]), length_sinv, Nat.sub_self] + split_ifs with h0 + · simp + · simp only [List.getD_cons_zero] + rw [ev_pscale, + ev_foldl_padd y (fun j => pmul (A.getD (j + 1) []) ((sinv i A).getD (i - 1 - j) [])), + ev_nil, zero_add, list_range_sum, Int.cast_neg, Int.cast_one, neg_one_mul] + congr 1 + refine sum_congr rfl fun j hj => ?_ + rw [mem_range] at hj + rw [ev_pmul, getD_sinv_of_lt (show i ≤ L by omega) A (show i - 1 - j < i by omega)] + +/-- `A · sinv L A ≡ 1` modulo `x^L` when `A` has constant term `1`. -/ +private theorem sinv_spec (y : R) (A : Ser) (hA : ev y (A.getD 0 []) = 1) (L : ℕ) : + Cg L (evS y A * evS y (sinv L A)) 1 := by + refine cg_of_coeff fun i hi => ?_ + rw [coeff_mul, Finset.Nat.sum_antidiagonal_eq_sum_range_succ + (fun j k => coeff j (evS y A) * coeff k (evS y (sinv L A))), sum_range_succ', coeff_one] + simp only [coeff_evS, Nat.sub_zero, hA, one_mul] + rw [ev_sinv y A hi] + split_ifs with h0 + · subst h0; simp + · rw [add_neg_eq_zero] + refine sum_congr rfl fun j hj => ?_ + rw [show i - (j + 1) = i - 1 - j by omega] + +/-- `sinv L A` agrees with any inverse of `A` modulo `x^L`. -/ +private theorem sinv_inv (y : R) (A : Ser) (hA : ev y (A.getD 0 []) = 1) (L : ℕ) (W : R⟦X⟧) + (hW : evS y A * W = 1) : Cg L (evS y (sinv L A)) W := by + have h := (sinv_spec y A hA L).mul (Cg.rfl' (f := W)) + rw [one_mul, mul_comm (evS y A), mul_assoc, hW, mul_one] at h + exact h + + +/-- One step of the loop in `thetaCoeff`. -/ +private def thStep (B : Ser) (m : ℕ) (st : Poly × Ser × Ser) (n : ℕ) : Poly × Ser × Ser := + if n * (n + 1) / 2 ≤ m then + (padd st.1 (pscale ((-1) ^ n) + (padd (st.2.1.getD (m - n * (n + 1) / 2) []) + (pscale (-1) (st.2.2.getD (m - n * (n + 1) / 2) [])))), + smul (m + 1) st.2.1 B, smul (m + 1) st.2.2 (sinv (m + 1) B)) + else st + +/-- The state of the loop in `thetaCoeff` after `k` steps. -/ +private def thSt (B : Ser) (m k : ℕ) : Poly × Ser × Ser := + (List.range k).foldl (thStep B m) ([], [[1]], sinv (m + 1) B) + +/-- `thetaCoeff` in terms of `thSt`. -/ +private theorem thetaCoeff_eq (B : Ser) (m : ℕ) : thetaCoeff B m = (thSt B m (m + 1)).1 := rfl + +/-- One more step of the loop in `thetaCoeff`. -/ +private theorem thSt_succ (B : Ser) (m k : ℕ) : thSt B m (k + 1) = thStep B m (thSt B m k) k := by + simp only [thSt, List.range_succ, List.foldl_append, List.foldl_cons, List.foldl_nil] + +/-- The list `[[1]]` is the series `1`. -/ +private theorem evS_one (y : R) : evS y [[1]] = 1 := by + ext i + rw [coeff_evS, coeff_one] + rcases i with _ | i + · simp + · simp + +/-- `T(k-1) ≤ T(k)`. -/ +private theorem tri_mono_aux (k : ℕ) : (k - 1) * k / 2 ≤ tri k := + Nat.div_le_div_right (Nat.mul_le_mul (Nat.sub_le k 1) (Nat.le_succ k)) + +/-- The loop invariant of `thetaCoeff`: the partial sum, and (while the loop is active) the powers +`B^k` and `B^{-(k+1)}` modulo `x^{m+1}`. -/ +private theorem th_inv (y : R) (B : Ser) (m : ℕ) (W : R⟦X⟧) + (hW : Cg (m + 1) (evS y (sinv (m + 1) B)) W) (k : ℕ) : + ev y (thSt B m k).1 = ∑ n ∈ range k, (if tri n ≤ m then + (-1) ^ n * (coeff (m - tri n) (evS y B ^ n) - coeff (m - tri n) (W ^ (n + 1))) else 0) ∧ + ((k - 1) * k / 2 ≤ m → Cg (m + 1) (evS y (thSt B m k).2.1) (evS y B ^ k) ∧ + Cg (m + 1) (evS y (thSt B m k).2.2) (W ^ (k + 1))) := by + induction k with + | zero => + refine ⟨by simp [thSt], fun _ => ⟨?_, ?_⟩⟩ + · simp only [thSt, List.range_zero, List.foldl_nil, pow_zero, evS_one]; exact Cg.rfl' + · simpa [thSt] using hW + | succ k ih => + obtain ⟨ih1, ih2⟩ := ih + rw [thSt_succ, thStep, sum_range_succ] + by_cases h : tri k ≤ m + · have h' : k * (k + 1) / 2 ≤ m := h + rw [if_pos h', if_pos h] + obtain ⟨c1, c2⟩ := ih2 ((tri_mono_aux k).trans h) + refine ⟨?_, fun _ => ⟨?_, ?_⟩⟩ + · simp only + rw [ev_padd, ev_pscale, ev_padd, ev_pscale, ih1, ← coeff_evS, ← coeff_evS, + show k * (k + 1) / 2 = tri k from rfl, c1.coeff_eq (show m - tri k < m + 1 by omega), + c2.coeff_eq (show m - tri k < m + 1 by omega)] + push_cast + ring + · rw [pow_succ]; exact (cg_smul y _ _ _).trans (c1.mul Cg.rfl') + · rw [pow_succ]; exact (cg_smul y _ _ _).trans (c2.mul hW) + · have h' : ¬ k * (k + 1) / 2 ≤ m := h + rw [if_neg h', if_neg h, add_zero] + refine ⟨ih1, fun hk => absurd ?_ h⟩ + have : (k + 1 - 1) * (k + 1) / 2 = tri k := by simp [tri] + omega + +/-- `∑_{n ≤ m} (-1)^n q^{n(n+1)/2} (V^n - W^{n+1})`. -/ +private noncomputable def Θ (V W : R⟦X⟧) (m : ℕ) : R⟦X⟧ := + ∑ n ∈ range (m + 1), (-1) ^ n * X ^ (tri n) * (V ^ n - W ^ (n + 1)) + +/-- Semantics of `thetaCoeff`: it is the coefficient of `x^m` in `Θ B B⁻¹ m`. -/ +private theorem ev_thetaCoeff (y : R) (B : Ser) (m : ℕ) (W : R⟦X⟧) (hB : ev y (B.getD 0 []) = 1) + (hW : evS y B * W = 1) : ev y (thetaCoeff B m) = coeff m (Θ (evS y B) W m) := by + rw [thetaCoeff_eq, (th_inv y B m W (sinv_inv y B hB (m + 1) W hW) (m + 1)).1, Θ, map_sum] + refine sum_congr rfl fun n _ => ?_ + rw [show ((-1 : R⟦X⟧)) ^ n = C ((-1 : R) ^ n) by simp, mul_assoc, coeff_C_mul, + coeff_X_pow_mul', map_sub] + split_ifs <;> simp + +/-- Unfolding `coeffs`. -/ +private theorem coeffs_succ (m : ℕ) : coeffs (m + 1) = coeffs m ++ + [padd (0 :: (coeffs m).getD m []) (pscale (-1) (thetaCoeff (coeffs m) (m + 1)))] := rfl + +/-- `coeffs m` has length `m + 1`. -/ +private theorem length_coeffs (m : ℕ) : (coeffs m).length = m + 1 := by + induction m with + | zero => rfl + | succ m ih => rw [coeffs_succ, List.length_append, ih]; rfl + +/-- The entries of `coeffs` are stable once computed. -/ +private theorem getD_coeffs_of_le {j M : ℕ} (h : j ≤ M) : + (coeffs M).getD j [] = (coeffs j).getD j [] := by + induction M, h using Nat.le_induction with + | base => rfl + | succ M hjM ih => + rw [coeffs_succ, List.getD_append _ _ _ _ (by rw [length_coeffs]; omega), ih] + +/-- Entries of `coeffs m` beyond `m` are empty. -/ +private theorem getD_coeffs_of_gt {j m : ℕ} (h : m < j) : (coeffs m).getD j [] = [] := + List.getD_eq_default _ _ (by rw [length_coeffs]; omega) + +/-- `a_j`, the coefficient of `x^j` of the computed series, evaluated at `y`. -/ +private def aco (y : R) (j : ℕ) : R := ev y ((coeffs j).getD j []) + +/-- The series of `coeffs m` is the truncation of the computed series. -/ +private theorem coeff_evS_coeffs (y : R) (m j : ℕ) : + coeff j (evS y (coeffs m)) = if j ≤ m then aco y j else 0 := by + rw [coeff_evS] + split_ifs with h + · rw [getD_coeffs_of_le h]; rfl + · rw [getD_coeffs_of_gt (by omega)]; rfl + +/-- `a_0 = 1`. -/ +private theorem aco_zero (y : R) : aco y 0 = 1 := by simp [aco, coeffs] + +/-- The recursion `a_{m+1} = y a_m - [x^{m+1}] F(a_0 + ⋯ + a_m x^m)`. -/ +private theorem aco_succ (y : R) (m : ℕ) : + aco y (m + 1) = y * aco y m - ev y (thetaCoeff (coeffs m) (m + 1)) := by + rw [aco, coeffs_succ, List.getD_append_right _ _ _ _ (by rw [length_coeffs]), length_coeffs, + Nat.sub_self, List.getD_cons_zero, ev_padd, ev_cons, ev_pscale, aco] + push_cast; ring + + +/-- If `X^M ∣ D` then `[x^M] (F D) = F(0) · [x^M] D`. -/ +private theorem coeff_mul_of_dvd {M : ℕ} (F : R⟦X⟧) {D : R⟦X⟧} (h : (X : R⟦X⟧) ^ M ∣ D) : + coeff M (F * D) = constantCoeff F * coeff M D := by + obtain ⟨D', rfl⟩ := h + rw [mul_left_comm, coeff_X_pow_mul', if_pos le_rfl, coeff_X_pow_mul', if_pos le_rfl, + Nat.sub_self, coeff_zero_eq_constantCoeff_apply, coeff_zero_eq_constantCoeff_apply, map_mul] + +/-- Replacing the full solution `E` by its truncation `V` (agreeing below `x^M`, zero at `x^M`) +changes `[x^M] Θ` by `-[x^M] E`. -/ +private theorem pert {V E W Eb : R⟦X⟧} {M : ℕ} (hVW : V * W = 1) (hEEb : E * Eb = 1) + (hV0 : constantCoeff V = 1) (hEb0 : constantCoeff Eb = 1) (hVE : Cg M V E) + (hVM : coeff M V = 0) : + coeff M (Θ V W M) = coeff M (Θ E Eb M) - coeff M E := by + have hWEb : Cg M W Eb := by + have h := (Cg.rfl' (f := W)).mul (hVE.symm.mul (Cg.rfl' (f := Eb))) + rw [hEEb, mul_one, ← mul_assoc, mul_comm W V, hVW, one_mul] at h + exact h + have hdiff : Θ V W M - Θ E Eb M = ∑ n ∈ range M, (-1) ^ (n + 1) * X ^ (tri (n + 1)) * + ((V ^ (n + 1) - E ^ (n + 1)) - (W ^ (n + 1 + 1) - Eb ^ (n + 1 + 1))) + (Eb - W) := by + rw [Θ, Θ, ← sum_sub_distrib, sum_range_succ'] + congr 1 + · exact sum_congr rfl fun n _ => by ring + · simp [tri] + have hzero : Cg (M + 1) (∑ n ∈ range M, (-1) ^ (n + 1) * X ^ (tri (n + 1)) * + ((V ^ (n + 1) - E ^ (n + 1)) - (W ^ (n + 1 + 1) - Eb ^ (n + 1 + 1)))) 0 := by + rw [← sum_const_zero (s := range M)] + refine Cg.sum _ fun n _ => ?_ + have h1 : Cg M ((V ^ (n + 1) - E ^ (n + 1)) - (W ^ (n + 1 + 1) - Eb ^ (n + 1 + 1))) 0 := by + have := ((hVE.pow (n + 1)).sub (Cg.rfl' (f := E ^ (n + 1)))).sub + ((hWEb.pow (n + 1 + 1)).sub (Cg.rfl' (f := Eb ^ (n + 1 + 1)))) + simpa using this + have h2 := h1.X_pow_mul (tri (n + 1)) + rw [mul_zero] at h2 + have h3 := (Cg.rfl' (f := ((-1 : R⟦X⟧)) ^ (n + 1))).mul + (h2.mono (show M + 1 ≤ M + tri (n + 1) by have := le_tri (n + 1); omega)) + rw [mul_zero, ← mul_assoc] at h3 + exact h3 + have hc1 : coeff M (Θ V W M) - coeff M (Θ E Eb M) = coeff M (Eb - W) := by + rw [← map_sub, hdiff, map_add, hzero.coeff_eq (Nat.lt_succ_self M), map_zero, zero_add] + have hc2 : coeff M (W - Eb) = coeff M E := by + have h0 : V * (W - Eb) + (V - E) * Eb = 0 := by linear_combination hVW - hEEb + have h1 := congrArg (coeff M) h0 + rw [map_add, coeff_mul_of_dvd V hWEb, mul_comm (V - E), coeff_mul_of_dvd Eb hVE, hV0, hEb0, + map_sub, map_sub, hVM, map_zero] at h1 + rw [map_sub] + linear_combination h1 + rw [map_sub] at hc1 hc2 + linear_combination hc1 - hc2 + +/-- If `w^3 = 0` then `(1+w)^n - (1-w+w^2)^{n+1} = (2n+1)(w - w^2)`. -/ +private theorem pow_sub_pow_of_cube {S : Type*} [CommRing S] (w : S) (hw : w ^ 3 = 0) (n : ℕ) : + (1 + w) ^ n - (1 - w + w ^ 2) ^ (n + 1) = (2 * (n : S) + 1) * (w - w ^ 2) := by + have h1 : ∀ n : ℕ, (1 + w) ^ n = 1 + n * w + (n.choose 2 : S) * w ^ 2 := by + intro n + induction n with + | zero => simp + | succ n ih => + rw [pow_succ, ih, Nat.choose_succ_succ', Nat.choose_one_right] + push_cast + linear_combination (n.choose 2 : S) * hw + have h2 : ∀ n : ℕ, (1 - w + w ^ 2) ^ n = 1 - n * w + (n + n.choose 2 : S) * w ^ 2 := by + intro n + induction n with + | zero => simp + | succ n ih => + rw [pow_succ, ih, Nat.choose_succ_succ', Nat.choose_one_right] + push_cast + linear_combination (-(n : S) - (n + n.choose 2 : S) + (n + n.choose 2 : S) * w) * hw + rw [h1, h2, Nat.choose_succ_succ', Nat.choose_one_right] + push_cast + ring + +section Solution +variable (y : R) + +/-- `u = x P(x)^3`. -/ +private noncomputable def U : R⟦X⟧ := X * Pgf ^ 3 + +/-- `w = y u + 2 y^2 u^2`. -/ +private noncomputable def wS : R⟦X⟧ := C y * U + C (2 * y ^ 2) * U ^ 2 + +/-- The solution mod `y^3`: `E = 1 + y u + 2 y^2 u^2`. -/ +private noncomputable def Ecal : R⟦X⟧ := 1 + wS y + +/-- Its inverse mod `y^3`. -/ +private noncomputable def Ebar : R⟦X⟧ := 1 - wS y + wS y ^ 2 + +variable {y} + +/-- `w^3 = 0` since `y^3 = 0`. -/ +private theorem wS_cube (hy : y ^ 3 = 0) : wS y ^ 3 = 0 := by + have : wS y = C y * (U + C (2 * y) * U ^ 2) := by simp only [wS, map_mul, map_pow]; ring + rw [this, mul_pow, ← map_pow, hy, map_zero, zero_mul] + +/-- `E · E⁻¹ = 1`. -/ +private theorem Ecal_mul_Ebar (hy : y ^ 3 = 0) : Ecal y * Ebar y = 1 := by + simp only [Ecal, Ebar]; linear_combination wS_cube hy + +/-- `w` has constant coefficient `0`. -/ +private theorem constantCoeff_wS : constantCoeff (wS y) = 0 := by + simp [wS, U] + +/-- `E⁻¹` has constant coefficient `1`. -/ +private theorem constantCoeff_Ebar : constantCoeff (Ebar y) = 1 := by + simp [Ebar, constantCoeff_wS] + +/-- `w - w^2 = y u + y^2 u^2` since `y^3 = 0`. -/ +private theorem wS_sub_sq (hy : y ^ 3 = 0) : wS y - wS y ^ 2 = C y * U + C (y ^ 2) * U ^ 2 := by + have hy4 : y ^ 4 = 0 := by rw [pow_succ, hy, zero_mul] + have e3 : (C (y ^ 3) : R⟦X⟧) = 0 := by rw [hy, map_zero] + have e4 : (C (y ^ 4) : R⟦X⟧) = 0 := by rw [hy4, map_zero] + simp only [wS, map_mul, map_pow, map_ofNat] at e3 e4 ⊢ + linear_combination (-4 * U ^ 3 : R⟦X⟧) * e3 + (-4 * U ^ 4 : R⟦X⟧) * e4 + +/-- For `E`, `Θ E E⁻¹ M = J_M (y u + y^2 u^2)`. -/ +private theorem Θ_E (hy : y ^ 3 = 0) (M : ℕ) : + Θ (Ecal y) (Ebar y) M = J M * (C y * U + C (y ^ 2) * U ^ 2) := by + rw [Θ, J, sum_mul, ← wS_sub_sq hy] + refine sum_congr rfl fun n _ => ?_ + rw [Ecal, Ebar, pow_sub_pow_of_cube _ (wS_cube hy)] + ring + +/-- The functional equation for `E` at order `x^{m+1}`: `[x^{m+1}] F(E) = y [x^m] E`. -/ +private theorem fe (hy : y ^ 3 = 0) (m : ℕ) : + coeff (m + 1) (Θ (Ecal y) (Ebar y) (m + 1)) = y * coeff m (Ecal y) := by + have h1 : Θ (Ecal y) (Ebar y) (m + 1) = (J (m + 1) * Pgf ^ 3) * (X * (C y + C (y ^ 2) * U)) := by + rw [Θ_E hy, U]; ring + have h2 : X * (C y + C (y ^ 2) * U) = X * (C y * Ecal y) := by + have e3 : (C (y ^ 3) : R⟦X⟧) = 0 := by rw [hy, map_zero] + simp only [Ecal, wS, map_mul, map_pow, map_ofNat] at e3 ⊢ + linear_combination (-2 * X * U ^ 2 : R⟦X⟧) * e3 + have h3 := (J_Pgf_cg (R := R) (m + 1)).mul (Cg.rfl' (f := X * (C y + C (y ^ 2) * U))) + rw [one_mul, ← h1, h2] at h3 + rw [h3.coeff_eq (Nat.lt_succ_self (m + 1)), coeff_succ_X_mul, coeff_C_mul] + +/-- Modulo `y^3`, the computed coefficients are those of `E = 1 + y u + 2 y^2 u^2`. -/ +private theorem aco_eq (hy : y ^ 3 = 0) : ∀ m, aco y m = coeff m (Ecal y) := by + intro m + induction m using Nat.strong_induction_on with + | _ m ih => + rcases m with _ | m + · rw [aco_zero, coeff_zero_eq_constantCoeff_apply, Ecal, map_add, constantCoeff_wS, map_one, + add_zero] + · have hB0 : ev y ((coeffs m).getD 0 []) = 1 := by + rw [getD_coeffs_of_le (Nat.zero_le m)]; exact aco_zero y + have hV0 : constantCoeff (evS y (coeffs m)) = 1 := by + rw [← coeff_zero_eq_constantCoeff_apply, coeff_evS, hB0] + have hVW := mul_invOfUnit (evS y (coeffs m)) 1 (by rw [hV0]; rfl) + have hVE : Cg (m + 1) (evS y (coeffs m)) (Ecal y) := cg_of_coeff fun i hi => by + rw [coeff_evS_coeffs, if_pos (by omega), ih i (by omega)] + have hVM : coeff (m + 1) (evS y (coeffs m)) = 0 := by + rw [coeff_evS_coeffs, if_neg (by omega)] + rw [aco_succ, ev_thetaCoeff y (coeffs m) (m + 1) _ hB0 hVW, + pert hVW (Ecal_mul_Ebar hy) hV0 constantCoeff_Ebar hVE hVM, fe hy, + ih m (by omega)] + ring + +end Solution + + +/-- `ℤ[y]/(y^3)`. -/ +private abbrev R3 := Polynomial ℤ ⧸ Ideal.span {(Polynomial.X : Polynomial ℤ) ^ 3} + +/-- The quotient map `ℤ[y] → ℤ[y]/(y^3)`. -/ +private noncomputable def π3 : Polynomial ℤ →+* R3 := Ideal.Quotient.mk _ + +/-- `y^3 = 0` in `ℤ[y]/(y^3)`. -/ +private theorem y3_cube : (π3 Polynomial.X) ^ 3 = 0 := by + rw [← map_pow, π3, Ideal.Quotient.eq_zero_iff_mem] + exact Ideal.subset_span rfl + +/-- Evaluation commutes with ring homomorphisms. -/ +private theorem ev_map {S : Type*} [CommRing S] (f : R →+* S) (y : R) : + ∀ l : Poly, f (ev y l) = ev (f y) l + | [] => by simp + | a :: l => by simp [ev_map f y l] + +/-- Evaluating a list at the variable `y` of `ℤ[y]` gives the polynomial with these coefficients. -/ +private theorem coeff_evX : ∀ (l : Poly) (k : ℕ), + (ev (Polynomial.X : Polynomial ℤ) l).coeff k = l.getD k 0 + | [], k => by simp + | a :: l, 0 => by + rw [ev_cons, Polynomial.coeff_add, Polynomial.intCast_coeff_zero, Polynomial.coeff_X_mul_zero, + add_zero]; rfl + | a :: l, k + 1 => by + rw [ev_cons, Polynomial.coeff_add, ← Polynomial.C_eq_intCast, Polynomial.coeff_C, + if_neg (Nat.succ_ne_zero k), Polynomial.coeff_X_mul, coeff_evX l k, zero_add]; rfl + +/-- `P` over `ℤ[y]/(y^3)` is the image of `P` over `ℤ`. -/ +private theorem Pgf_map : (Pgf : R3⟦X⟧) = map (Int.castRingHom R3) (Pgf : ℤ⟦X⟧) := by + ext n; simp [Pgf] + +/-- `u` over `ℤ[y]/(y^3)` is the image of `u` over `ℤ`. -/ +private theorem U_map : (U : R3⟦X⟧) = map (Int.castRingHom R3) (U : ℤ⟦X⟧) := by + simp [U, Pgf_map] + +/-- Columns `1` and `2` of the triangle are the coefficients of `u = x P^3` and `2u^2`. -/ +private theorem T_cols (n : ℕ) : + T n 1 = coeff n (U : ℤ⟦X⟧) ∧ T n 2 = 2 * coeff n ((U : ℤ⟦X⟧) ^ 2) := by + have h := aco_eq (R := R3) (y := π3 Polynomial.X) y3_cube n + have hC : ∀ z : ℤ, π3 (Polynomial.C z) = (z : R3) := fun z => eq_intCast (π3.comp Polynomial.C) z + set u := coeff n (U : ℤ⟦X⟧) + set v := coeff n ((U : ℤ⟦X⟧) ^ 2) + set Q : Polynomial ℤ := Polynomial.C (if n = 0 then 1 else 0) + Polynomial.C u * Polynomial.X + + Polynomial.C (2 * v) * Polynomial.X ^ 2 with hQdef + have e1 : coeff n (Ecal (π3 Polynomial.X)) = ((if n = 0 then 1 else 0 : ℤ) : R3) + + π3 Polynomial.X * (u : R3) + 2 * (π3 Polynomial.X) ^ 2 * (v : R3) := by + rw [Ecal, wS, map_add, map_add, coeff_one, coeff_C_mul, coeff_C_mul, U_map, + ← map_pow (PowerSeries.map (Int.castRingHom R3)), coeff_map, coeff_map] + simp only [Int.coe_castRingHom] + split_ifs <;> simp <;> ring + have e2 : π3 Q = ((if n = 0 then 1 else 0 : ℤ) : R3) + + π3 Polynomial.X * (u : R3) + 2 * (π3 Polynomial.X) ^ 2 * (v : R3) := by + rw [hQdef, map_add, map_add, map_mul, map_mul, hC, hC, hC, map_pow] + push_cast; ring + have hQ : π3 (ev Polynomial.X ((coeffs n).getD n [])) = π3 Q := by + rw [ev_map, ← aco, h, e1, e2] + have hdvd : (Polynomial.X : Polynomial ℤ) ^ 3 ∣ ev Polynomial.X ((coeffs n).getD n []) - Q := by + rw [← Ideal.mem_span_singleton, ← Ideal.Quotient.eq]; exact hQ + obtain ⟨r, hr⟩ := hdvd + have hQ1 : Q.coeff 1 = u := by + rw [hQdef, Polynomial.coeff_add, Polynomial.coeff_add, Polynomial.coeff_C, + Polynomial.coeff_C_mul_X, Polynomial.coeff_C_mul_X_pow] + simp + have hQ2 : Q.coeff 2 = 2 * v := by + rw [hQdef, Polynomial.coeff_add, Polynomial.coeff_add, Polynomial.coeff_C, + Polynomial.coeff_C_mul_X, Polynomial.coeff_C_mul_X_pow] + simp + have c1 := congrArg (fun f => Polynomial.coeff f 1) hr + have c2 := congrArg (fun f => Polynomial.coeff f 2) hr + simp only [Polynomial.coeff_sub, Polynomial.coeff_X_pow_mul', hQ1, hQ2] at c1 c2 + rw [if_neg (by norm_num)] at c1 c2 + rw [T, T, ← coeff_evX, ← coeff_evX] + exact ⟨by linear_combination c1, by linear_combination c2⟩ + + +/-- The coefficients of `P^j` count partitions into parts of `j` kinds. -/ +private theorem coeff_Pgf_pow (j n : ℕ) : + coeff n ((Pgf : ℤ⟦X⟧) ^ j) = (partitionsOfKinds j n : ℤ) := by + rw [coeff_pow_tuple, partitionsOfKinds] + push_cast + simp [Pgf] + +/-- **Hanna's conjectures (C.1) and (C.2) hold.** Column 1 of the triangle is A000716 and +column 2 is twice A023005. -/ +theorem result : statement := by + refine ⟨fun n => ?_, fun n => ?_⟩ + · rw [(T_cols (n + 1)).1, U, coeff_succ_X_mul, coeff_Pgf_pow, A000716] + · rw [(T_cols (n + 2)).2, U, show ((X : ℤ⟦X⟧) * Pgf ^ 3) ^ 2 = X ^ 2 * Pgf ^ 6 by ring, + coeff_X_pow_mul', if_pos (by omega), show n + 2 - 2 = n by omega, coeff_Pgf_pow, A023005] + +end Math0.Frontier.A355360 + +#math0_settles Math0.Frontier.A355360.result Math0.Statements.A355360.statement diff --git a/lean/Math0/Frontier/OEIS/A356360.lean b/lean/Math0/Frontier/OEIS/A356360.lean new file mode 100644 index 0000000..cefcf98 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A356360.lean @@ -0,0 +1,193 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A356360 +import Math0.Audit + +/-! +# A356360: the continued-fraction denominators are 1 or prime + +We prove Mohammed Bouras's conjecture: the denominator `a n` of +`1/(2-3/(3-4/(...(n-1)-n/(n+1))))` is `1` or a prime for every `n ≥ 3`. + +**Closed form.** Write `n = m + 2` and `H m x = step 2 (step 3 (… (step (m+1) x)))`, so that +`cf n = 1 / H m (n+1)`. With `S m = 0! + 1! + ⋯ + (m-1)!` and `M = (m+1)x - m(m+2)`, +induction on `m` (peeling off the innermost step, `H (m+1) x = H m (step (m+2) x)`) gives +`H m x = 2M / (S m · M + (m+2)·m!)` whenever `M > 0`; the positivity of `M` is inherited by the +inner argument because `M_m(step (m+2) x) = M_{m+1}(x) / x`. For `x = n + 1` we get `M = 2m+3 = +2n-1`, hence `cf n = (S m (2m+3) + (m+2) m!) / (2 (2m+3))`. + +**Arithmetic.** For `m ≥ 2` both `S m` and `m!` are even, so `cf n = K / (2m+3)` with `K ∈ ℕ`. +If `2m+3` is prime, the denominator divides it, so it is `1` or `2m+3`. If `2m+3` is composite +and `m ≥ 4`, then `2m+3 ∣ m!` (write `2m+3 = p·b` with `p` its least prime factor, `3 ≤ p ≤ b ≤ m`; +if `p < b` then `p·b ∣ m!`, and if `p = b` then `p ≥ 5`, `2p ≤ m` and `p·2p ∣ m!`), so `2m+3` +divides `2K` and, being odd, divides `K`: the denominator is `1`. The cases `n = 3, 4, 5` +(`a = 5, 7, 3`) are checked by the kernel. +-/ + +namespace Math0.Frontier.A356360 +open Math0.Statements.A356360 + +/-- `S m = 0! + 1! + ⋯ + (m-1)!`. -/ +private def S (m : ℕ) : ℕ := ∑ k ∈ Finset.range m, k.factorial + +/-- Closed form of the continued-fraction tail `H m x = foldr step x [2, …, m+1]`, valid when +`M = (m+1)x - m(m+2) > 0`: `H m x = 2M / (S m · M + (m+2)·m!)`. -/ +private lemma closed (m : ℕ) : ∀ x : ℚ, 0 < ((m : ℚ) + 1) * x - m * (m + 2) → + (List.range' 2 m).foldr step x = + 2 * (((m : ℚ) + 1) * x - m * (m + 2)) / + ((S m : ℚ) * (((m : ℚ) + 1) * x - m * (m + 2)) + ((m : ℚ) + 2) * m.factorial) := by + induction m with + | zero => + intro x _ + simp [S] + | succ m ih => + intro x hx + push_cast at hx + have hxpos : 0 < x := by + by_contra h + push Not at h + nlinarith + have hxne : x ≠ 0 := hxpos.ne' + rw [List.range'_concat, List.foldr_append] + simp only [List.foldr_cons, List.foldr_nil] + have key : ((m : ℚ) + 1) * step (2 + 1 * m) x - m * (m + 2) = + (((m : ℚ) + 2) * x - (m + 1) * (m + 3)) / x := by + simp only [step] + push_cast + field_simp + ring + have hpos : 0 < ((m : ℚ) + 1) * step (2 + 1 * m) x - m * (m + 2) := by + rw [key] + apply div_pos _ hxpos + linarith + rw [ih _ hpos, key] + have hS : (S (m + 1) : ℚ) = S m + m.factorial := by + simp [S, Finset.sum_range_succ] + have hf : ((m + 1).factorial : ℚ) = (m + 1) * m.factorial := by + push_cast [Nat.factorial_succ] + ring + rw [hS, hf] + push_cast + have hfpos : (0 : ℚ) < m.factorial := by exact_mod_cast Nat.factorial_pos m + have hS0 : (0 : ℚ) ≤ S m := by positivity + set M := ((m : ℚ) + 2) * x - (m + 1) * (m + 3) with hM + have hMpos : 0 < M := by rw [hM]; linarith + rw [div_eq_div_iff] + · field_simp + ring + · have : 0 < (S m : ℚ) * (M / x) + ((m : ℚ) + 2) * m.factorial := by positivity + exact this.ne' + · have e : ((m : ℚ) + 1 + 1) * x - (m + 1) * (m + 1 + 2) = M := by rw [hM]; ring + rw [e] + positivity + +/-- `cf (m+2) = (S m (2m+3) + (m+2) m!) / (2 (2m+3))`. -/ +private lemma cf_eq (m : ℕ) : cf (m + 2) = + ((S m * (2 * m + 3) + (m + 2) * m.factorial : ℕ) : ℚ) / (2 * ((2 * m + 3 : ℕ) : ℚ)) := by + unfold cf + rw [show m + 2 - 2 = m by omega] + have hM : ((m : ℚ) + 1) * (((m + 2 : ℕ) : ℚ) + 1) - m * (m + 2) = 2 * m + 3 := by + push_cast; ring + rw [closed m _ (by rw [hM]; positivity), hM, one_div_div] + push_cast + ring + +/-- `S m = 0! + ⋯ + (m-1)!` is even for `m ≥ 2`. -/ +private lemma two_dvd_S (m : ℕ) (hm : 2 ≤ m) : 2 ∣ S m := by + induction m with + | zero => omega + | succ m ih => + rcases (show m = 1 ∨ 2 ≤ m by omega) with h | h + · subst h; decide + · have : S (m + 1) = S m + m.factorial := by simp [S, Finset.sum_range_succ] + rw [this] + exact dvd_add (ih h) (Nat.dvd_factorial (by norm_num) h) + +/-- If `0 < a < b ≤ m` then `a * b ∣ m!`. -/ +private lemma mul_dvd_factorial {a b m : ℕ} (ha : 0 < a) (hab : a < b) (hbm : b ≤ m) : + a * b ∣ m.factorial := by + have h1 : a ∣ (b - 1).factorial := Nat.dvd_factorial ha (by omega) + have h2 : (b - 1).factorial * b = b.factorial := by + rw [mul_comm, Nat.mul_factorial_pred (by omega)] + have h3 : a * b ∣ b.factorial := by + rw [← h2]; exact Nat.mul_dvd_mul_right h1 b + exact h3.trans (Nat.factorial_dvd_factorial hbm) + +/-- A composite `2m+3` with `m ≥ 4` divides `m!`. -/ +private lemma composite_dvd (m : ℕ) (hm : 4 ≤ m) (hp : ¬ (2 * m + 3).Prime) : + 2 * m + 3 ∣ m.factorial := by + set c := 2 * m + 3 with hc + set a := c.minFac with ha + have hc1 : c ≠ 1 := by omega + have hap : a.Prime := Nat.minFac_prime hc1 + have hadvd : a ∣ c := Nat.minFac_dvd c + have ha2 : a ≠ 2 := by + intro h + rw [h] at hadvd + omega + have ha3 : 3 ≤ a := by + have := hap.two_le + omega + have hsq : a ^ 2 ≤ c := Nat.minFac_sq_le_self (by omega) hp + obtain ⟨b, hb⟩ := hadvd + have hab : a ≤ b := by + rw [hb, pow_two] at hsq + exact Nat.le_of_mul_le_mul_left hsq (by omega) + have hbm : b ≤ m := by nlinarith + rcases lt_or_eq_of_le hab with h | h + · rw [hb]; exact mul_dvd_factorial (by omega) h hbm + · subst h + have ha5 : 5 ≤ a := by + by_contra h5 + have : a = 3 ∨ a = 4 := by omega + rcases this with h' | h' <;> rw [h'] at hb <;> omega + have h2a : 2 * a ≤ m := by nlinarith + rw [hb] + have : a * (2 * a) ∣ m.factorial := mul_dvd_factorial (by omega) (by omega) h2a + exact dvd_trans (Dvd.intro 2 (by ring)) this + +/-- The conjecture for `n = m + 2 ≥ 6`. -/ +private lemma main (m : ℕ) (hm : 4 ≤ m) : a (m + 2) = 1 ∨ (a (m + 2)).Prime := by + have hev : 2 ∣ S m * (2 * m + 3) + (m + 2) * m.factorial := + dvd_add (dvd_mul_of_dvd_left (two_dvd_S m (by omega)) _) + (dvd_mul_of_dvd_right (Nat.dvd_factorial (by norm_num) (by omega)) _) + obtain ⟨K, hK⟩ := hev + have hcf : cf (m + 2) = (K : ℚ) / ((2 * m + 3 : ℕ) : ℚ) := by + rw [cf_eq, hK] + push_cast + field_simp + unfold a + rw [hcf] + by_cases hp : (2 * m + 3).Prime + · have hd : (((K : ℚ) / ((2 * m + 3 : ℕ) : ℚ)).den : ℤ) ∣ ((2 * m + 3 : ℕ) : ℤ) := by + have := Rat.den_dvd (K : ℤ) ((2 * m + 3 : ℕ) : ℤ) + rw [Rat.divInt_eq_div] at this + push_cast at this ⊢ + exact this + have hd' : ((K : ℚ) / ((2 * m + 3 : ℕ) : ℚ)).den ∣ 2 * m + 3 := by exact_mod_cast hd + rcases hp.eq_one_or_self_of_dvd _ hd' with h | h + · left; exact h + · right; rw [h]; exact hp + · left + rw [Rat.den_div_natCast_eq_one_iff _ _ (by omega)] + have h1 : 2 * m + 3 ∣ m.factorial := composite_dvd m hm hp + have h2 : 2 * m + 3 ∣ 2 * K := by + rw [← hK] + exact dvd_add (dvd_mul_left _ _) (dvd_mul_of_dvd_right h1 _) + exact (Nat.Coprime.dvd_of_dvd_mul_left (Nat.Coprime.symm + (Nat.prime_two.coprime_iff_not_dvd.2 (by omega))) h2) + +/-- Every term `a n` (`n ≥ 3`) of A356360 is `1` or a prime. -/ +theorem result : statement := by + intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 2 := ⟨n - 2, by omega⟩ + rcases (show m = 1 ∨ m = 2 ∨ m = 3 ∨ 4 ≤ m by omega) with h | h | h | h + · subst h; right; rw [show a (1 + 2) = 5 by decide +kernel]; norm_num + · subst h; right; rw [show a (2 + 2) = 7 by decide +kernel]; norm_num + · subst h; right; rw [show a (3 + 2) = 3 by decide +kernel]; norm_num + · exact main m h + +end Math0.Frontier.A356360 + +#math0_settles Math0.Frontier.A356360.result Math0.Statements.A356360.statement diff --git a/lean/Math0/Frontier/OEIS/A357216.lean b/lean/Math0/Frontier/OEIS/A357216.lean new file mode 100644 index 0000000..69f8bd4 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A357216.lean @@ -0,0 +1,1982 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A357216 +import Math0.Audit + +/-! +# Internal `n`-gons in a regular `n`-gon: Shannon's conjecture (OEIS A357216) + +We prove both parts of `statement`: for `n ≥ 3` some `k` gives a point on three of the drawn +sides iff `n ∈ {3, 4, 6}`, and for `n = 5` and every `n ≥ 7` the `k` internal `n`-gons cut the +regular `n`-gon into exactly `n k² + 1` regions. + +**Frames.** At the corner `V_C` of the polygon write `z = V_C + x (V_{C-1} - V_C) + y (V_{C+1} - V_C)` +(`fx`, `fy`; real-affine in `z`). The vertex `V_{C+a}` has frame coordinates +`X(a) = sin(aφ) sin((a-1)φ) / (sin φ sin 2φ)`, `Y(a) = sin(aφ) sin((a+1)φ) / (sin φ sin 2φ)` +with `φ = π/n` (`Xr`, `Yr`). In particular `V_{C±1}, V_{C±2}` are `(1,0), (0,1), (1+u,1), (1,1+u)` +with `W = 1 + u = 1 + 2 cos(2π/n)`, and every vertex other than `V_C` has `x, y ≥ 0`, `x + y ≥ 1`. +So the polygon lies in each corner angle, and the open corner triangle lies in its interior. + +**Chords and lines.** The side `(j, m)` of the internal polygon number `m+1` is the chord at the +corner `V_{j+1}` from `(1-t, 0)` to `(0, t)`, `t = (m+1)/(k+1)`, on the line +`Fl = t x + (1-t) y - t(1-t) = 0`. The line meets the open polygon exactly in the open chord. +Along chord `(j, m)` (parameter `r`) the line of chord `(j', m')` (parameter `s`) is the affine +function `(1-r) a + r b`, computed from the frame values: same corner: `(t - s)(r - s)`; next +corner: a root in `(0,1)` iff `s < t`; previous corner: iff `s > t`; other corners: none. + +**No triple points (`n = 5`, `n ≥ 7`).** Three concurrent lines would give two at one corner and +one at an adjacent corner, and then an equation `α W + β = 0` with rational `α ≠ 0`, `β`. But `W` +is irrational by Niven's theorem (`niven`). + +**Counting.** A general theorem (`count_general`): if lines `f_i = 0`, added in order, each meet an +open convex set `U` in an open segment, then the components of `U` minus the lines are the +realised sign vectors, and their number is `1 + ∑_i (1 + #distinct points of segment i on earlier +lines)`. Adding the chords in order of `m`, the chord `(j, m)` meets `2m` earlier lines in distinct +points (the `m` earlier chords at its corner and the `m` at the next corner), so the count is +`1 + ∑_{m 0 < f i z) + +/-- Membership in a sign vector. -/ +private lemma mem_sgn {f : ℕ → ℂ → ℝ} {N : ℕ} {z : ℂ} {i : ℕ} : i ∈ sgn f N z ↔ i < N ∧ 0 < f i z := by + simp [sgn] + +section general + +variable {U : Set ℂ} {f : ℕ → ℂ → ℝ} + (hUo : IsOpen U) (hUc : Convex ℝ U) + (hfa : ∀ i (z w : ℂ) (r : ℝ), f i (z + r * (w - z)) = f i z + r * (f i w - f i z)) + (hfc : ∀ i, Continuous (f i)) + +include hUc hfa in +/-- Cells are convex. -/ +private lemma cell_convex_step {N : ℕ} {z₁ z₂ : ℂ} (h₁ : z₁ ∈ cellSet U f N) (h₂ : z₂ ∈ cellSet U f N) + (hs : sgn f N z₁ = sgn f N z₂) {r : ℝ} (hr0 : 0 ≤ r) (hr1 : r ≤ 1) : + z₁ + r * (z₂ - z₁) ∈ cellSet U f N ∧ sgn f N (z₁ + r * (z₂ - z₁)) = sgn f N z₁ := by + have hmemU : z₁ + r * (z₂ - z₁) ∈ U := by + have := hUc.add_smul_sub_mem h₁.1 h₂.1 ⟨hr0, hr1⟩ + simpa [Complex.real_smul] using this + have key : ∀ i < N, (0 < f i (z₁ + r * (z₂ - z₁)) ∧ 0 < f i z₁) ∨ + (f i (z₁ + r * (z₂ - z₁)) < 0 ∧ f i z₁ < 0) := by + intro i hi + rw [hfa] + have e1 := h₁.2 i hi + have e2 := h₂.2 i hi + have hiff : 0 < f i z₁ ↔ 0 < f i z₂ := by + have := congrArg (fun s => i ∈ s) hs + simp only [mem_sgn, eq_iff_iff] at this + constructor + · intro h; exact (this.mp ⟨hi, h⟩).2 + · intro h; exact (this.mpr ⟨hi, h⟩).2 + rcases lt_or_gt_of_ne e1 with h | h + · right + have h2' : f i z₂ < 0 := by + rcases lt_or_gt_of_ne e2 with h' | h' + · exact h' + · exact absurd (hiff.mpr h') (not_lt.mpr h.le) + refine ⟨?_, h⟩ + rcases le_total (f i z₁) (f i z₂) with hh | hh + · nlinarith [mul_nonneg (sub_nonneg.mpr hr1) (sub_nonneg.mpr hh)] + · nlinarith [mul_nonneg hr0 (sub_nonneg.mpr hh)] + · left + have h2' : 0 < f i z₂ := hiff.mp h + refine ⟨?_, h⟩ + rcases le_total (f i z₁) (f i z₂) with hh | hh + · nlinarith [mul_nonneg hr0 (sub_nonneg.mpr hh)] + · nlinarith [mul_nonneg (sub_nonneg.mpr hr1) (sub_nonneg.mpr hh)] + refine ⟨⟨hmemU, fun i hi => ?_⟩, ?_⟩ + · rcases key i hi with ⟨h, _⟩ | ⟨h, _⟩ + · exact h.ne' + · exact h.ne + · ext i + simp only [mem_sgn] + constructor + · rintro ⟨hi, h⟩ + refine ⟨hi, ?_⟩ + rcases key i hi with ⟨_, h'⟩ | ⟨h', _⟩ + · exact h' + · exact absurd h (not_lt.mpr h'.le) + · rintro ⟨hi, h⟩ + refine ⟨hi, ?_⟩ + rcases key i hi with ⟨h', _⟩ | ⟨_, h'⟩ + · exact h' + · exact absurd h (not_lt.mpr h'.le) + +include hUo hfc in +/-- Each point of `cellSet` has an open neighbourhood inside its cell. -/ +private lemma cell_open_nhd {N : ℕ} {z : ℂ} (hz : z ∈ cellSet U f N) : + ∃ O : Set ℂ, IsOpen O ∧ z ∈ O ∧ ∀ y ∈ O, y ∈ cellSet U f N ∧ sgn f N y = sgn f N z := by + refine ⟨U ∩ ⋂ i ∈ Finset.range N, {y | 0 < f i y * f i z}, ?_, ?_, ?_⟩ + · refine hUo.inter ?_ + refine isOpen_biInter_finset fun i _ => ?_ + exact isOpen_lt continuous_const ((hfc i).mul continuous_const) + · refine ⟨hz.1, ?_⟩ + simp only [mem_iInter, Finset.mem_range, mem_ofPred_eq] + intro i hi + have := hz.2 i hi + exact mul_self_pos.mpr this + · intro y hy + simp only [mem_inter_iff, mem_iInter, Finset.mem_range, mem_ofPred_eq] at hy + refine ⟨⟨hy.1, fun i hi h => ?_⟩, ?_⟩ + · have := hy.2 i hi + rw [h, zero_mul] at this + exact lt_irrefl _ this + · ext i + simp only [mem_sgn] + constructor + · rintro ⟨hi, h⟩ + refine ⟨hi, ?_⟩ + have := hy.2 i hi + exact (pos_and_pos_or_neg_and_neg_of_mul_pos this).elim (fun h => h.2) + (fun h' => absurd h (not_lt.mpr h'.1.le)) + · rintro ⟨hi, h⟩ + refine ⟨hi, ?_⟩ + have := hy.2 i hi + exact (pos_and_pos_or_neg_and_neg_of_mul_pos this).elim (fun h => h.1) + (fun h' => absurd h (not_lt.mpr h'.2.le)) + +include hUo hUc hfa hfc in +/-- Connected components of the complement of the lines are the realized sign vectors. -/ +private theorem card_cc_eq (N : ℕ) : + Nat.card (ConnectedComponents (cellSet U f N)) = (sgn f N '' cellSet U f N).ncard := by + set X := cellSet U f N + let g : X → Finset ℕ := fun x => sgn f N x + have hg : IsLocallyConstant g := by + rw [IsLocallyConstant.iff_exists_open] + intro x + obtain ⟨O, hO, hxO, hOs⟩ := cell_open_nhd hUo hfc x.2 + refine ⟨Subtype.val ⁻¹' O, hO.preimage continuous_subtype_val, hxO, fun y hy => ?_⟩ + exact (hOs y hy).2 + have hfib : ∀ x : X, IsPreconnected {y : X | g y = g x} := by + intro x + rw [← Topology.IsInducing.subtypeVal.isPreconnected_image] + apply Convex.isPreconnected + intro a ha b hb s t hs ht hst + obtain ⟨a', ha', rfl⟩ := ha + obtain ⟨b', hb', rfl⟩ := hb + simp only [mem_ofPred_eq, g] at ha' hb' + have hst' : s = 1 - t := by linarith + have := cell_convex_step hUc hfa a'.2 b'.2 (ha'.trans hb'.symm) ht (by linarith) + have e : s • (a' : ℂ) + t • (b' : ℂ) = (a' : ℂ) + t * ((b' : ℂ) - a') := by + rw [hst', Complex.real_smul, Complex.real_smul]; push_cast; ring + rw [e] + refine ⟨⟨_, this.1⟩, ?_, rfl⟩ + simp only [mem_ofPred_eq, g] + rw [this.2] + exact ha' + have hinj : ∀ x y : X, g x = g y → (ConnectedComponents.mk x = ConnectedComponents.mk y) := by + intro x y h + rw [ConnectedComponents.coe_eq_coe'] + have hsub := (hfib y).subset_connectedComponent (show y ∈ {z : X | g z = g y} from rfl) + exact hsub h + have hconst : ∀ x y : X, ConnectedComponents.mk x = ConnectedComponents.mk y → g x = g y := by + intro x y h + rw [ConnectedComponents.coe_eq_coe'] at h + exact hg.apply_eq_of_isPreconnected isPreconnected_connectedComponent h mem_connectedComponent + let F : ConnectedComponents X → Set.range g := + Quotient.lift (fun x => (⟨g x, x, rfl⟩ : Set.range g)) (fun a b hab => by + apply Subtype.ext + exact hconst a b (Quotient.sound hab)) + have hF : Function.Bijective F := by + constructor + · intro p q hpq + obtain ⟨x, rfl⟩ := ConnectedComponents.surjective_coe p + obtain ⟨y, rfl⟩ := ConnectedComponents.surjective_coe q + apply hinj + have := congrArg Subtype.val hpq + exact this + · rintro ⟨_, x, rfl⟩ + exact ⟨ConnectedComponents.mk x, rfl⟩ + rw [Nat.card_congr (Equiv.ofBijective F hF), Nat.card_coe_set_eq] + congr 1 + ext σ + simp only [mem_range, mem_image, g] + constructor + · rintro ⟨x, rfl⟩; exact ⟨x, x.2, rfl⟩ + · rintro ⟨z, hz, rfl⟩; exact ⟨⟨z, hz⟩, rfl⟩ + +/-- Sign vector with one more line. -/ +private lemma sgn_succ (N : ℕ) (z : ℂ) : + sgn f (N + 1) z = if 0 < f N z then insert N (sgn f N z) else sgn f N z := by + unfold sgn + rw [Finset.range_add_one, Finset.filter_insert] + +/-- Sign vectors are subsets of `range N`. -/ +private lemma sgn_subset (N : ℕ) (z : ℂ) : sgn f N z ⊆ Finset.range N := Finset.filter_subset _ _ + +/-- There are finitely many sign vectors. -/ +private lemma finite_sgn_image (N : ℕ) (S : Set ℂ) : (sgn f N '' S).Finite := by + refine Set.Finite.subset (Finset.finite_toSet (Finset.range N).powerset) ?_ + rintro σ ⟨z, _, rfl⟩ + simp only [Finset.coe_powerset, Set.mem_preimage, Set.mem_powerset_iff, Finset.coe_subset] + exact sgn_subset (f := f) N z + +include hUo hfa hfc in +/-- A cell meeting the next line contains points on both of its sides. -/ +private lemma perturb {N : ℕ} (hne : ∃ w, f N w ≠ 0) {z : ℂ} (hz : z ∈ cellSet U f N) (hz0 : f N z = 0) : + (∃ y ∈ cellSet U f N, sgn f N y = sgn f N z ∧ 0 < f N y) ∧ + (∃ y ∈ cellSet U f N, sgn f N y = sgn f N z ∧ f N y < 0) := by + obtain ⟨w, hw⟩ := hne + obtain ⟨O, hO, hzO, hOs⟩ := cell_open_nhd hUo hfc hz + let p : ℝ → ℂ := fun e => z + e * (w - z) + have hp : Continuous p := by fun_prop + have hpO : IsOpen (p ⁻¹' O) := hO.preimage hp + have h0 : (0 : ℝ) ∈ p ⁻¹' O := by simp [p, hzO] + obtain ⟨δ, hδ, hball⟩ := Metric.isOpen_iff.mp hpO 0 h0 + have hin : ∀ e : ℝ, |e| < δ → p e ∈ O := by + intro e he + apply hball + simpa [Metric.mem_ball, Real.dist_eq] using he + have hval : ∀ e : ℝ, f N (p e) = e * f N w := by + intro e + simp only [p] + rw [hfa, hz0]; ring + have h1 := hOs _ (hin (δ / 2) (by rw [abs_of_pos (by positivity)]; linarith)) + have h2 := hOs _ (hin (-(δ / 2)) (by rw [abs_neg, abs_of_pos (by positivity)]; linarith)) + rcases lt_or_gt_of_ne hw with hw' | hw' + · refine ⟨⟨_, h2.1, h2.2, ?_⟩, ⟨_, h1.1, h1.2, ?_⟩⟩ + · rw [hval]; nlinarith + · rw [hval]; nlinarith + · refine ⟨⟨_, h1.1, h1.2, ?_⟩, ⟨_, h2.1, h2.2, ?_⟩⟩ + · rw [hval]; nlinarith + · rw [hval]; nlinarith + +include hUo hUc hfa hfc in +/-- Adding one line adds as many cells as there are cells it meets. -/ +private theorem ncard_step (N : ℕ) (hne : ∃ w, f N w ≠ 0) : + (sgn f (N + 1) '' cellSet U f (N + 1)).ncard = + (sgn f N '' cellSet U f N).ncard + (sgn f N '' (cellSet U f N ∩ {z | f N z = 0})).ncard := by + set Rp := sgn f N '' {z | z ∈ cellSet U f N ∧ 0 < f N z} with hRp + set Rm := sgn f N '' {z | z ∈ cellSet U f N ∧ f N z < 0} with hRm + have e1 : sgn f (N + 1) '' cellSet U f (N + 1) = (insert N) '' Rp ∪ Rm := by + ext σ + constructor + · rintro ⟨z, hz, rfl⟩ + have hzN : z ∈ cellSet U f N := ⟨hz.1, fun i hi => hz.2 i (by omega)⟩ + have hne' : f N z ≠ 0 := hz.2 N (by omega) + rw [sgn_succ] + split_ifs with h + · left; exact ⟨_, ⟨z, ⟨hzN, h⟩, rfl⟩, rfl⟩ + · right; exact ⟨z, ⟨hzN, lt_of_le_of_ne (not_lt.mp h) hne'⟩, rfl⟩ + · rintro (⟨_, ⟨z, ⟨hz, h⟩, rfl⟩, rfl⟩ | ⟨z, ⟨hz, h⟩, rfl⟩) + · refine ⟨z, ⟨hz.1, fun i hi => ?_⟩, ?_⟩ + · rcases Nat.lt_succ_iff_lt_or_eq.mp hi with hi | rfl + · exact hz.2 i hi + · exact h.ne' + · rw [sgn_succ, if_pos h] + · refine ⟨z, ⟨hz.1, fun i hi => ?_⟩, ?_⟩ + · rcases Nat.lt_succ_iff_lt_or_eq.mp hi with hi | rfl + · exact hz.2 i hi + · exact h.ne + · rw [sgn_succ, if_neg (not_lt.mpr h.le)] + have hdisj : Disjoint ((insert N) '' Rp) Rm := by + rw [Set.disjoint_left] + rintro σ ⟨_, ⟨z, _, rfl⟩, rfl⟩ ⟨y, _, hy⟩ + have : N ∈ sgn f N y := by rw [hy]; exact Finset.mem_insert_self _ _ + have := sgn_subset N y this + simp at this + have hinj : Set.InjOn (insert N) Rp := by + rintro σ ⟨z, _, rfl⟩ τ ⟨y, _, rfl⟩ h + have hz : N ∉ sgn f N z := fun hh => by simpa using sgn_subset N z hh + have hy : N ∉ sgn f N y := fun hh => by simpa using sgn_subset N y hh + have := congrArg (fun s => Finset.erase s N) h + simpa [Finset.erase_insert hz, Finset.erase_insert hy] using this + have hunion : Rp ∪ Rm = sgn f N '' cellSet U f N := by + ext σ + constructor + · rintro (⟨z, ⟨hz, _⟩, rfl⟩ | ⟨z, ⟨hz, _⟩, rfl⟩) <;> exact ⟨z, hz, rfl⟩ + · rintro ⟨z, hz, rfl⟩ + rcases lt_trichotomy (f N z) 0 with h | h | h + · right; exact ⟨z, ⟨hz, h⟩, rfl⟩ + · obtain ⟨⟨y, hy, hys, hyp⟩, _⟩ := perturb hUo hfa hfc hne hz h + left; exact ⟨y, ⟨hy, hyp⟩, hys⟩ + · left; exact ⟨z, ⟨hz, h⟩, rfl⟩ + have hinter : Rp ∩ Rm = sgn f N '' (cellSet U f N ∩ {z | f N z = 0}) := by + ext σ + constructor + · rintro ⟨⟨z₁, ⟨h₁, hp⟩, rfl⟩, ⟨z₂, ⟨h₂, hm⟩, hs⟩⟩ + set r : ℝ := f N z₁ / (f N z₁ - f N z₂) + have hd : 0 < f N z₁ - f N z₂ := by linarith + have hr0 : 0 ≤ r := div_nonneg hp.le hd.le + have hr1 : r ≤ 1 := by rw [div_le_one hd]; linarith + have hc := cell_convex_step hUc hfa h₁ h₂ hs.symm hr0 hr1 + refine ⟨_, ⟨hc.1, ?_⟩, hc.2⟩ + show f N (z₁ + r * (z₂ - z₁)) = 0 + rw [hfa] + simp only [r] + field_simp + ring + · rintro ⟨z, ⟨hz, h0⟩, rfl⟩ + obtain ⟨⟨y, hy, hys, hyp⟩, ⟨y', hy', hys', hym⟩⟩ := perturb hUo hfa hfc hne hz h0 + exact ⟨⟨y, ⟨hy, hyp⟩, hys⟩, ⟨y', ⟨hy', hym⟩, hys'⟩⟩ + have fRp : Rp.Finite := finite_sgn_image N _ + have fRm : Rm.Finite := finite_sgn_image N _ + rw [e1, Set.ncard_union_eq hdisj (fRp.image _) fRm, hinj.ncard_image, ← hunion, ← hinter, + Set.ncard_union_add_ncard_inter _ _ fRp fRm] + +/-! One-dimensional count: sign vectors of affine functions along an interval. -/ + +/-- Sign vector along a line. -/ +private noncomputable def sgn1 (N : ℕ) (c d : ℕ → ℝ) (x : ℝ) : Finset ℕ := + (Finset.range N).filter (fun j => 0 < c j + x * d j) + +/-- The sign vector is constant on an interval without roots. -/ +private lemma sgn1_const {N : ℕ} {c d : ℕ → ℝ} {x y : ℝ} (hxy : x ≤ y) + (h : ∀ z, x ≤ z → z ≤ y → ∀ j < N, c j + z * d j ≠ 0) : sgn1 N c d x = sgn1 N c d y := by + ext j + simp only [sgn1, Finset.mem_filter, Finset.mem_range] + constructor + · rintro ⟨hj, hx⟩ + refine ⟨hj, ?_⟩ + by_contra hy + replace hy := not_lt.mp hy + have hcont : ContinuousOn (fun z => c j + z * d j) (Set.Icc x y) := by fun_prop + obtain ⟨z, hz, hz0⟩ := intermediate_value_Icc' hxy hcont ⟨hy, hx.le⟩ + exact h z hz.1 hz.2 j hj hz0 + · rintro ⟨hj, hy⟩ + refine ⟨hj, ?_⟩ + by_contra hx + replace hx := not_lt.mp hx + have hcont : ContinuousOn (fun z => c j + z * d j) (Set.Icc x y) := by fun_prop + obtain ⟨z, hz, hz0⟩ := intermediate_value_Icc hxy hcont ⟨hx, hy.le⟩ + exact h z hz.1 hz.2 j hj hz0 + +/-- The sign vector changes across a root. -/ +private lemma sgn1_sep {N : ℕ} {c d : ℕ → ℝ} {x y r : ℝ} (hxr : x < r) (hry : r < y) {j : ℕ} (hj : j < N) + (hr : c j + r * d j = 0) (hx : c j + x * d j ≠ 0) (_hy : c j + y * d j ≠ 0) : + sgn1 N c d x ≠ sgn1 N c d y := by + have hc : c j = - r * d j := by linarith + have hd : d j ≠ 0 := by + intro h; apply hx; rw [hc, h]; ring + intro heq + have := congrArg (fun s => j ∈ s) heq + simp only [sgn1, Finset.mem_filter, Finset.mem_range, eq_iff_iff] at this + rw [hc] at this + rcases lt_or_gt_of_ne hd with h | h + · have h1 : 0 < -r * d j + x * d j := by nlinarith + have h2 : -r * d j + y * d j < 0 := by nlinarith + exact absurd (this.mp ⟨hj, h1⟩).2 (not_lt.mpr h2.le) + · have h1 : -r * d j + x * d j < 0 := by nlinarith + have h2 : 0 < -r * d j + y * d j := by nlinarith + exact absurd (this.mpr ⟨hj, h2⟩).2 (not_lt.mpr h1.le) + +/-- There are finitely many one-dimensional sign vectors. -/ +private lemma finite_sgn1_image (N : ℕ) (c d : ℕ → ℝ) (S : Set ℝ) : (sgn1 N c d '' S).Finite := by + refine Set.Finite.subset (Finset.finite_toSet (Finset.range N).powerset) ?_ + rintro σ ⟨z, _, rfl⟩ + simp only [Finset.coe_powerset, Set.mem_preimage, Set.mem_powerset_iff, Finset.coe_subset] + exact Finset.filter_subset _ _ + +/-- On a root-free open interval there is exactly one sign vector. -/ +private lemma sgn1_image_Ioo {N : ℕ} {c d : ℕ → ℝ} {a b : ℝ} (hab : a < b) + (h : ∀ z, a < z → z < b → ∀ j < N, c j + z * d j ≠ 0) : + sgn1 N c d '' {x | a < x ∧ x < b ∧ ∀ j < N, c j + x * d j ≠ 0} = {sgn1 N c d ((a + b) / 2)} := by + ext σ + simp only [Set.mem_image, Set.mem_ofPred_eq, Set.mem_singleton_iff] + constructor + · rintro ⟨x, ⟨hax, hxb, _⟩, rfl⟩ + rcases le_total x ((a + b) / 2) with hx | hx + · exact sgn1_const hx (fun z h1 h2 => h z (by linarith) (by linarith)) + · exact (sgn1_const hx (fun z h1 h2 => h z (by linarith) (by linarith))).symm + · rintro rfl + exact ⟨(a + b) / 2, ⟨by linarith, by linarith, h _ (by linarith) (by linarith)⟩, rfl⟩ + +/-- The number of sign vectors along an interval is one more than the number of roots. -/ +private theorem sgn1_count (N : ℕ) (c d : ℕ → ℝ) (a : ℝ) (Rt : Finset ℝ) : + ∀ b, a < b → (∀ x, x ∈ Rt ↔ (a < x ∧ x < b ∧ ∃ j < N, c j + x * d j = 0)) → + (sgn1 N c d '' {x | a < x ∧ x < b ∧ ∀ j < N, c j + x * d j ≠ 0}).ncard = Rt.card + 1 := by + induction Rt using Finset.induction_on_max with + | empty => + intro b hab hR + have h : ∀ z, a < z → z < b → ∀ j < N, c j + z * d j ≠ 0 := by + intro z h1 h2 j hj h0 + have := (hR z).mpr ⟨h1, h2, j, hj, h0⟩ + simp at this + rw [sgn1_image_Ioo hab h, Set.ncard_singleton] + simp + | insert r s hs ih => + intro b hab hR + have hr := (hR r).mp (Finset.mem_insert_self r s) + obtain ⟨har, hrb, j₀, hj₀, hr0⟩ := hr + have hrs : r ∉ s := fun h => lt_irrefl r (hs r h) + have ih' := ih r har (by + intro x + constructor + · intro hx + obtain ⟨h1, _, h3⟩ := (hR x).mp (Finset.mem_insert_of_mem hx) + exact ⟨h1, hs x hx, h3⟩ + · rintro ⟨h1, h2, h3⟩ + have := (hR x).mpr ⟨h1, by linarith, h3⟩ + rcases Finset.mem_insert.mp this with h | h + · exact absurd h h2.ne + · exact h) + have hno : ∀ z, r < z → z < b → ∀ j < N, c j + z * d j ≠ 0 := by + intro z h1 h2 j hj h0 + have := (hR z).mpr ⟨by linarith, h2, j, hj, h0⟩ + rcases Finset.mem_insert.mp this with h | h + · exact absurd h h1.ne' + · exact absurd (hs z h) (not_lt.mpr h1.le) + have hsplit : {x | a < x ∧ x < b ∧ ∀ j < N, c j + x * d j ≠ 0} = + {x | a < x ∧ x < r ∧ ∀ j < N, c j + x * d j ≠ 0} ∪ + {x | r < x ∧ x < b ∧ ∀ j < N, c j + x * d j ≠ 0} := by + ext x + simp only [Set.mem_ofPred_eq, Set.mem_union] + constructor + · rintro ⟨h1, h2, h3⟩ + rcases lt_trichotomy x r with h | rfl | h + · left; exact ⟨h1, h, h3⟩ + · exact absurd hr0 (h3 j₀ hj₀) + · right; exact ⟨h, h2, h3⟩ + · rintro (⟨h1, h2, h3⟩ | ⟨h1, h2, h3⟩) + · exact ⟨h1, by linarith, h3⟩ + · exact ⟨by linarith, h2, h3⟩ + rw [hsplit, Set.image_union, sgn1_image_Ioo hrb hno, Set.union_singleton, + Set.ncard_insert_of_notMem _ (finite_sgn1_image N c d _), ih', Finset.card_insert_of_notMem hrs] + rintro ⟨x, ⟨h1, h2, h3⟩, hx⟩ + apply sgn1_sep h2 (show r < (r + b) / 2 by linarith) hj₀ hr0 (h3 j₀ hj₀) + (hno _ (by linarith) (by linarith) j₀ hj₀) hx + +include hUo hUc hfa hfc in +/-- **Counting regions.** Lines `f i = 0` (in a fixed order) each meet the open convex set `U` +in an open segment `A i + r (B i - A i)`, `0 < r < 1`; then the number of regions is +`1 + ∑ (1 + number of distinct points of segment `i` on earlier lines)`. -/ +private theorem count_general (hne : U.Nonempty) (A B : ℕ → ℂ) (N : ℕ) + (hline : ∀ i < N, ∀ z, z ∈ U → f i z = 0 → ∃ r : ℝ, 0 < r ∧ r < 1 ∧ z = A i + r * (B i - A i)) + (hseg : ∀ i < N, ∀ (r : ℝ), 0 < r → r < 1 → + A i + r * (B i - A i) ∈ U ∧ f i (A i + r * (B i - A i)) = 0) + (hnz : ∀ i < N, ∃ w, f i w ≠ 0) + (hnc : ∀ i < N, ∀ j < i, ∃ r : ℝ, f j (A i + r * (B i - A i)) ≠ 0) : + Nat.card (ConnectedComponents (cellSet U f N)) = + 1 + ∑ i ∈ Finset.range N, + (1 + {r : ℝ | 0 < r ∧ r < 1 ∧ ∃ j < i, f j (A i + r * (B i - A i)) = 0}.ncard) := by + rw [card_cc_eq hUo hUc hfa hfc] + suffices H : ∀ M ≤ N, (sgn f M '' cellSet U f M).ncard = 1 + ∑ i ∈ Finset.range M, + (1 + {r : ℝ | 0 < r ∧ r < 1 ∧ ∃ j < i, f j (A i + r * (B i - A i)) = 0}.ncard) from + H N le_rfl + intro M hM + induction M with + | zero => + obtain ⟨z₀, hz₀⟩ := hne + have : sgn f 0 '' cellSet U f 0 = {∅} := by + ext σ + simp only [Set.mem_image, Set.mem_singleton_iff] + constructor + · rintro ⟨z, _, rfl⟩; simp [sgn] + · rintro rfl; exact ⟨z₀, ⟨hz₀, fun i hi => absurd hi (Nat.not_lt_zero _)⟩, by simp [sgn]⟩ + rw [this, Set.ncard_singleton] + simp + | succ N ih => + rw [ncard_step hUo hUc hfa hfc N (hnz N (by omega)), ih (by omega), Finset.sum_range_succ] + set c : ℕ → ℝ := fun j => f j (A N) + set d : ℕ → ℝ := fun j => f j (B N) - f j (A N) + have hγ : ∀ j (r : ℝ), f j (A N + r * (B N - A N)) = c j + r * d j := fun j r => hfa j _ _ r + have hM : sgn f N '' (cellSet U f N ∩ {z | f N z = 0}) = + sgn1 N c d '' {x | 0 < x ∧ x < 1 ∧ ∀ j < N, c j + x * d j ≠ 0} := by + ext σ + constructor + · rintro ⟨z, ⟨⟨hzU, hz⟩, hz0⟩, rfl⟩ + obtain ⟨r, hr0, hr1, rfl⟩ := hline N (by omega) z hzU hz0 + refine ⟨r, ⟨hr0, hr1, fun j hj => ?_⟩, ?_⟩ + · rw [← hγ]; exact hz j hj + · ext j; simp [sgn, sgn1, hγ] + · rintro ⟨r, ⟨hr0, hr1, hr⟩, rfl⟩ + obtain ⟨hU, h0⟩ := hseg N (by omega) r hr0 hr1 + refine ⟨A N + r * (B N - A N), ⟨⟨hU, fun j hj => ?_⟩, h0⟩, ?_⟩ + · rw [hγ]; exact hr j hj + · ext j; simp [sgn, sgn1, hγ] + have hfin : {r : ℝ | 0 < r ∧ r < 1 ∧ ∃ j < N, f j (A N + r * (B N - A N)) = 0}.Finite := by + refine Set.Finite.subset ((Finset.range N).finite_toSet.biUnion + (fun j _ => Set.finite_singleton (-(c j) / d j))) ?_ + rintro x ⟨_, _, j, hj, hx⟩ + simp only [Set.mem_iUnion, Finset.coe_range, Set.mem_Iio, Set.mem_singleton_iff] + refine ⟨j, hj, ?_⟩ + rw [hγ] at hx + obtain ⟨r, hr⟩ := hnc N (by omega) j hj + rw [hγ] at hr + have hd : d j ≠ 0 := by + intro h + apply hr + have : c j = 0 := by rw [h] at hx; linarith + rw [this, h]; ring + field_simp + linarith + rw [hM, sgn1_count N c d 0 hfin.toFinset 1 one_pos (by + intro x + simp only [Set.Finite.mem_toFinset, Set.mem_ofPred_eq, hγ]), Set.ncard_eq_toFinset_card _ hfin] + ring + +end general + +/-! ### Trigonometric layer -/ + +/-- `E α = exp (α i)`. -/ +private noncomputable def E (α : ℝ) : ℂ := Complex.exp (α * Complex.I) + +/-- Real part of `E α`. -/ +private lemma E_re (α : ℝ) : (E α).re = Real.cos α := Complex.exp_ofReal_mul_I_re α +/-- Imaginary part of `E α`. -/ +private lemma E_im (α : ℝ) : (E α).im = Real.sin α := Complex.exp_ofReal_mul_I_im α + +/-- `E α E β = E (α + β)`. -/ +private lemma E_mul (α β : ℝ) : E α * E β = E (α + β) := by + unfold E; rw [← Complex.exp_add]; congr 1; push_cast; ring + +/-- Conjugate of `E α`. -/ +private lemma E_conj (α : ℝ) : (starRingEnd ℂ) (E α) = E (-α) := by + unfold E; rw [← Complex.exp_conj]; congr 1 + simp [map_mul, Complex.conj_ofReal, Complex.conj_I] + +/-- `E 0 = 1`. -/ +private lemma E_zero : E 0 = 1 := by simp [E] + +/-- Half the central angle, `π / n`. -/ +private noncomputable def ph (n : ℕ) : ℝ := Real.pi / n + +/-- The vertices in terms of `E`. -/ +private lemma vertex_eq (n j : ℕ) : vertex n j = E (j * (2 * ph n)) := by + unfold vertex E ph; congr 1; push_cast; ring + +section basic +variable {n : ℕ} (hn : 3 ≤ n) +include hn + +/-- `n > 0` as a real number. -/ +private lemma n_pos : (0 : ℝ) < n := by + have : (3 : ℝ) ≤ n := by exact_mod_cast hn + linarith + +/-- `π / n > 0`. -/ +private lemma ph_pos : 0 < ph n := div_pos Real.pi_pos (n_pos hn) + +/-- `π / n ≤ π / 3` for `n ≥ 3`. -/ +private lemma ph_le : ph n ≤ Real.pi / 3 := by + unfold ph + apply div_le_div_of_nonneg_left Real.pi_pos.le (by norm_num) + exact_mod_cast hn + +/-- `n (π / n) = π`. -/ +private lemma n_mul_ph : (n : ℝ) * ph n = Real.pi := by + unfold ph; field_simp [(n_pos hn).ne'] + +/-- `sin (π/n) > 0`. -/ +private lemma sin_ph_pos : 0 < Real.sin (ph n) := + Real.sin_pos_of_pos_of_lt_pi (ph_pos hn) (by linarith [ph_le hn, Real.pi_pos]) + +/-- `cos (π/n) > 0`. -/ +private lemma cos_ph_pos : 0 < Real.cos (ph n) := + Real.cos_pos_of_mem_Ioo ⟨by linarith [ph_pos hn, Real.pi_pos], by linarith [ph_le hn, Real.pi_pos]⟩ + +/-- `sin (2π/n) > 0`. -/ +private lemma sin_two_ph_pos : 0 < Real.sin (2 * ph n) := by + rw [Real.sin_two_mul] + have := sin_ph_pos hn + have := cos_ph_pos hn + positivity + +/-- `1 - cos (2π/n) > 0`. -/ +private lemma one_sub_cos_pos : 0 < 1 - Real.cos (2 * ph n) := by + rw [Real.cos_two_mul_eq_one_sub] + have := sin_ph_pos hn + nlinarith + +end basic + +/-- Frame `x`-coordinate relative to the corner `1` of the rotated polygon. -/ +private noncomputable def x0 (n : ℕ) (w : ℂ) : ℝ := + ((1 - w.re) / (1 - Real.cos (2 * ph n)) - w.im / Real.sin (2 * ph n)) / 2 + +/-- Frame `y`-coordinate relative to the corner `1` of the rotated polygon. -/ +private noncomputable def y0 (n : ℕ) (w : ℂ) : ℝ := + ((1 - w.re) / (1 - Real.cos (2 * ph n)) + w.im / Real.sin (2 * ph n)) / 2 + +/-- Frame `x`-coordinate at corner `C`: `z = V_C + x (V_{C-1} - V_C) + y (V_{C+1} - V_C)`. -/ +private noncomputable def fx (n C : ℕ) (z : ℂ) : ℝ := x0 n ((starRingEnd ℂ) (vertex n C) * z) + +/-- Frame `y`-coordinate at corner `C`. -/ +private noncomputable def fy (n C : ℕ) (z : ℂ) : ℝ := y0 n ((starRingEnd ℂ) (vertex n C) * z) + +/-- Closed form of the frame `x`-coordinate of the vertex at relative position `a`. -/ +private noncomputable def Xr (n : ℕ) (a : ℝ) : ℝ := + Real.sin (a * ph n) * Real.sin ((a - 1) * ph n) / (Real.sin (ph n) * Real.sin (2 * ph n)) + +/-- Closed form of the frame `y`-coordinate of the vertex at relative position `a`. -/ +private noncomputable def Yr (n : ℕ) (a : ℝ) : ℝ := + Real.sin (a * ph n) * Real.sin ((a + 1) * ph n) / (Real.sin (ph n) * Real.sin (2 * ph n)) + +section frames +variable {n : ℕ} (hn : 3 ≤ n) +include hn + +/-- Frame `x`-coordinate of the unit vector at angle `2πa/n` (closed form). -/ +private lemma x0_E (a : ℝ) : x0 n (E (a * (2 * ph n))) = Xr n a := by + have hs := sin_ph_pos hn + have hc := cos_ph_pos hn + unfold x0 Xr + rw [E_re, E_im, show a * (2 * ph n) = 2 * (a * ph n) by ring, Real.cos_two_mul_eq_one_sub, + Real.cos_two_mul_eq_one_sub, Real.sin_two_mul, Real.sin_two_mul, + show (a - 1) * ph n = a * ph n - ph n by ring, Real.sin_sub] + field_simp + ring + +/-- Frame `y`-coordinate of the unit vector at angle `2πa/n` (closed form). -/ +private lemma y0_E (a : ℝ) : y0 n (E (a * (2 * ph n))) = Yr n a := by + have hs := sin_ph_pos hn + have hc := cos_ph_pos hn + unfold y0 Yr + rw [E_re, E_im, show a * (2 * ph n) = 2 * (a * ph n) by ring, Real.cos_two_mul_eq_one_sub, + Real.cos_two_mul_eq_one_sub, Real.sin_two_mul, Real.sin_two_mul, + show (a + 1) * ph n = a * ph n + ph n by ring, Real.sin_add] + field_simp + ring + +omit hn in +/-- Rotating vertex `i` back by vertex `C`. -/ +private lemma conj_vertex_mul (C i : ℕ) : + (starRingEnd ℂ) (vertex n C) * vertex n i = E (((i : ℝ) - C) * (2 * ph n)) := by + rw [vertex_eq, vertex_eq, E_conj, E_mul]; congr 1; ring + +/-- Frame `x`-coordinate of a vertex. -/ +private lemma fx_vertex (C i : ℕ) : fx n C (vertex n i) = Xr n ((i : ℝ) - C) := by + unfold fx; rw [conj_vertex_mul, x0_E hn] + +/-- Frame `y`-coordinate of a vertex. -/ +private lemma fy_vertex (C i : ℕ) : fy n C (vertex n i) = Yr n ((i : ℝ) - C) := by + unfold fy; rw [conj_vertex_mul, y0_E hn] + +end frames + +/-- The frame `x`-coordinate is real-affine. -/ +private lemma fx_aff (n C : ℕ) (z p q : ℂ) (r : ℝ) : + fx n C (z + r * (q - p)) = fx n C z + r * (fx n C q - fx n C p) := by + unfold fx x0 + rw [show (starRingEnd ℂ) (vertex n C) * (z + r * (q - p)) = + (starRingEnd ℂ) (vertex n C) * z + (r : ℂ) * ((starRingEnd ℂ) (vertex n C) * q - + (starRingEnd ℂ) (vertex n C) * p) by ring] + simp only [Complex.add_re, Complex.re_ofReal_mul, Complex.sub_re, Complex.add_im, + Complex.im_ofReal_mul, Complex.sub_im] + ring + +/-- The frame `y`-coordinate is real-affine. -/ +private lemma fy_aff (n C : ℕ) (z p q : ℂ) (r : ℝ) : + fy n C (z + r * (q - p)) = fy n C z + r * (fy n C q - fy n C p) := by + unfold fy y0 + rw [show (starRingEnd ℂ) (vertex n C) * (z + r * (q - p)) = + (starRingEnd ℂ) (vertex n C) * z + (r : ℂ) * ((starRingEnd ℂ) (vertex n C) * q - + (starRingEnd ℂ) (vertex n C) * p) by ring] + simp only [Complex.add_re, Complex.re_ofReal_mul, Complex.sub_re, Complex.add_im, + Complex.im_ofReal_mul, Complex.sub_im] + ring + +/-- The frame `x`-coordinate is continuous. -/ +private lemma fx_cont (n C : ℕ) : Continuous (fx n C) := by + unfold fx x0; fun_prop + +/-- The frame `y`-coordinate is continuous. -/ +private lemma fy_cont (n C : ℕ) : Continuous (fy n C) := by + unfold fy y0; fun_prop + +/-- Reconstruction of a point from its frame coordinates at corner `j+1`. -/ +private lemma recon {n : ℕ} (hn : 3 ≤ n) (j : ℕ) (z : ℂ) : + z = vertex n (j + 1) + (fx n (j + 1) z : ℂ) * (vertex n j - vertex n (j + 1)) + + (fy n (j + 1) z : ℂ) * (vertex n (j + 2) - vertex n (j + 1)) := by + set V := vertex n (j + 1) + set w := (starRingEnd ℂ) V * z + have hVV : V * (starRingEnd ℂ) V = 1 := by + simp only [V]; rw [vertex_eq, E_conj, E_mul]; simp [E] + have hz : z = V * w := by simp only [w]; rw [← mul_assoc, hVV, one_mul] + have hVj : vertex n j = V * E (-(2 * ph n)) := by + simp only [V]; rw [vertex_eq, vertex_eq, E_mul]; congr 1; push_cast; ring + have hVj2 : vertex n (j + 2) = V * E (2 * ph n) := by + simp only [V]; rw [vertex_eq, vertex_eq, E_mul]; congr 1; push_cast; ring + have hw : w = 1 + (x0 n w : ℂ) * (E (-(2 * ph n)) - 1) + (y0 n w : ℂ) * (E (2 * ph n) - 1) := by + have h1 := one_sub_cos_pos hn + have h2 := sin_two_ph_pos hn + apply Complex.ext + · simp only [Complex.add_re, Complex.one_re, Complex.re_ofReal_mul, Complex.sub_re, E_re, + Real.cos_neg] + unfold x0 y0 + field_simp + ring + · simp only [Complex.add_im, Complex.one_im, Complex.im_ofReal_mul, Complex.sub_im, E_im, + Real.sin_neg] + unfold x0 y0 + field_simp + ring + show z = V + (x0 n w : ℂ) * (vertex n j - V) + (y0 n w : ℂ) * (vertex n (j + 2) - V) + rw [hVj, hVj2] + conv_lhs => rw [hz, hw] + ring + +/-! ### Values and inequalities of the closed forms -/ + +section values +variable {n : ℕ} (hn : 3 ≤ n) +include hn + +/-- `Xr` has period `n`. -/ +private lemma Xr_periodic : Function.Periodic (Xr n) n := by + intro a + unfold Xr + rw [show (a + n) * ph n = a * ph n + Real.pi by rw [add_mul, n_mul_ph hn], + show (a + n - 1) * ph n = (a - 1) * ph n + Real.pi by rw [sub_mul, add_mul, n_mul_ph hn]; ring, + Real.sin_add_pi, Real.sin_add_pi] + ring + +/-- `Yr` has period `n`. -/ +private lemma Yr_periodic : Function.Periodic (Yr n) n := by + intro a + unfold Yr + rw [show (a + n) * ph n = a * ph n + Real.pi by rw [add_mul, n_mul_ph hn], + show (a + n + 1) * ph n = (a + 1) * ph n + Real.pi by rw [add_mul, add_mul, n_mul_ph hn]; ring, + Real.sin_add_pi, Real.sin_add_pi] + ring + +/-- `Xr` is invariant under integer multiples of `n`. -/ +private lemma Xr_shift (a : ℝ) (q : ℤ) : Xr n (a + q * n) = Xr n a := + (Xr_periodic hn).int_mul q a + +/-- `Yr` is invariant under integer multiples of `n`. -/ +private lemma Yr_shift (a : ℝ) (q : ℤ) : Yr n (a + q * n) = Yr n a := + (Yr_periodic hn).int_mul q a + +omit hn in +/-- The corner itself: `x = 0`. -/ +private lemma Xr_zero : Xr n 0 = 0 := by simp [Xr] +omit hn in +/-- The corner itself: `y = 0`. -/ +private lemma Yr_zero : Yr n 0 = 0 := by simp [Yr] +omit hn in +/-- The next vertex: `x = 0`. -/ +private lemma Xr_one : Xr n 1 = 0 := by simp [Xr] +/-- The next vertex: `y = 1`. -/ +private lemma Yr_one : Yr n 1 = 1 := by + have := sin_ph_pos hn; have := sin_two_ph_pos hn + unfold Yr; rw [show ((1 : ℝ) + 1) * ph n = 2 * ph n by ring, one_mul]; field_simp +/-- The previous vertex: `x = 1`. -/ +private lemma Xr_neg_one : Xr n (-1) = 1 := by + have := sin_ph_pos hn; have := sin_two_ph_pos hn + unfold Xr + rw [show ((-1 : ℝ) - 1) * ph n = -(2 * ph n) by ring, show (-1 : ℝ) * ph n = -(ph n) by ring, + Real.sin_neg, Real.sin_neg] + field_simp +omit hn in +/-- The previous vertex: `y = 0`. -/ +private lemma Yr_neg_one : Yr n (-1) = 0 := by simp [Yr] +/-- The vertex two steps ahead: `x = 1`. -/ +private lemma Xr_two : Xr n 2 = 1 := by + have := sin_ph_pos hn; have := sin_two_ph_pos hn + unfold Xr; rw [show ((2 : ℝ) - 1) * ph n = ph n by ring]; field_simp +/-- The vertex two steps back: `y = 1`. -/ +private lemma Yr_neg_two : Yr n (-2) = 1 := by + have := sin_ph_pos hn; have := sin_two_ph_pos hn + unfold Yr + rw [show ((-2 : ℝ) + 1) * ph n = -(ph n) by ring, show (-2 : ℝ) * ph n = -(2 * ph n) by ring, + Real.sin_neg, Real.sin_neg] + field_simp +omit hn in +/-- The vertex two steps ahead: `y = W`. -/ +private lemma Yr_two_eq : Yr n 2 = Xr n (-2) := by + unfold Xr Yr + rw [show ((-2 : ℝ) - 1) * ph n = -((2 + 1) * ph n) by ring, + show (-2 : ℝ) * ph n = -(2 * ph n) by ring, Real.sin_neg, Real.sin_neg] + ring + +/-- `W = Xr (-2) = 1 + 2 cos (2π/n)`. -/ +private lemma Xr_neg_two : Xr n (-2) = 1 + 2 * Real.cos (2 * ph n) := by + have hs := sin_ph_pos hn; have := sin_two_ph_pos hn + unfold Xr + rw [show ((-2 : ℝ) - 1) * ph n = -(3 * ph n) by ring, + show (-2 : ℝ) * ph n = -(2 * ph n) by ring, Real.sin_neg, Real.sin_neg, Real.sin_three_mul, + Real.cos_two_mul_eq_one_sub] + field_simp + ring + +/-- Basic inequalities at relative positions `1 ≤ b ≤ n - 1`. -/ +private lemma XY_basic (b : ℝ) (hb1 : 1 ≤ b) (hb2 : b ≤ n - 1) : + 0 ≤ Xr n b ∧ 0 ≤ Yr n b ∧ 1 ≤ Xr n b + Yr n b ∧ (b ≤ n - 2 → 0 < Yr n b) := by + have hs := sin_ph_pos hn + have hc := cos_ph_pos hn + have hs2 := sin_two_ph_pos hn + have hp := ph_pos hn + have hnp := n_mul_ph hn + have hD : 0 < Real.sin (ph n) * Real.sin (2 * ph n) := mul_pos hs hs2 + have h1 : 0 < Real.sin (b * ph n) := by + apply Real.sin_pos_of_pos_of_lt_pi (by nlinarith) + nlinarith + have h2 : 0 ≤ Real.sin ((b - 1) * ph n) := by + apply Real.sin_nonneg_of_nonneg_of_le_pi (by nlinarith) + nlinarith + have h3 : 0 ≤ Real.sin ((b + 1) * ph n) := by + apply Real.sin_nonneg_of_nonneg_of_le_pi (by nlinarith) + nlinarith + have hge : Real.sin (ph n) ≤ Real.sin (b * ph n) := by + have := Real.sin_sub_sin (b * ph n) (ph n) + have e1 : 0 ≤ Real.sin ((b * ph n - ph n) / 2) := by + apply Real.sin_nonneg_of_nonneg_of_le_pi (by nlinarith) + nlinarith + have e2 : 0 ≤ Real.cos ((b * ph n + ph n) / 2) := by + apply Real.cos_nonneg_of_mem_Icc + constructor <;> nlinarith + nlinarith + refine ⟨div_nonneg (mul_nonneg h1.le h2) hD.le, div_nonneg (mul_nonneg h1.le h3) hD.le, ?_, ?_⟩ + · unfold Xr Yr + rw [← add_div, le_div_iff₀ hD, one_mul, ← mul_add, + show (b - 1) * ph n = b * ph n - ph n by ring, show (b + 1) * ph n = b * ph n + ph n by ring, + Real.sin_sub, Real.sin_add, Real.sin_two_mul] + nlinarith [mul_le_mul hge hge hs.le h1.le] + · intro hb3 + apply div_pos _ hD + apply mul_pos h1 + apply Real.sin_pos_of_pos_of_lt_pi (by nlinarith) + nlinarith + +end values + +/-! ### Integer relative positions -/ + +section intpos +variable {n : ℕ} (hn : 3 ≤ n) +include hn + +/-- Shifting a relative position by `n`. -/ +private lemma XY_shift1 (ρ : ℤ) : Xr n ρ = Xr n ((ρ + n : ℤ) : ℝ) ∧ Yr n ρ = Yr n ((ρ + n : ℤ) : ℝ) := by + rw [show ((ρ + n : ℤ) : ℝ) = (ρ : ℝ) + ((1 : ℤ) : ℝ) * n by push_cast; ring, Xr_shift hn, + Yr_shift hn] + exact ⟨rfl, rfl⟩ + +/-- Frame coordinates of the other vertices: `x, y ≥ 0` and `x + y ≥ 1`. -/ +private lemma XY_range (ρ : ℤ) (h1 : -(n : ℤ) ≤ ρ) (h2 : ρ ≤ n) (h0 : ρ ≠ 0) (h3 : ρ ≠ n) + (h4 : ρ ≠ -n) : 0 ≤ Xr n ρ ∧ 0 ≤ Yr n ρ ∧ 1 ≤ Xr n ρ + Yr n ρ := by + rcases lt_or_gt_of_ne h0 with hneg | hpos + · obtain ⟨e1, e2⟩ := XY_shift1 hn ρ + rw [e1, e2] + have hb1 : (1 : ℝ) ≤ ((ρ + n : ℤ) : ℝ) := by exact_mod_cast (show (1 : ℤ) ≤ ρ + n by omega) + have hb2 : ((ρ + n : ℤ) : ℝ) ≤ (n : ℝ) - 1 := by + have : ((ρ + n : ℤ) : ℝ) ≤ ((n - 1 : ℤ) : ℝ) := by exact_mod_cast (show ρ + n ≤ n - 1 by omega) + simpa using this + have h := XY_basic hn _ hb1 hb2 + exact ⟨h.1, h.2.1, h.2.2.1⟩ + · have hb1 : (1 : ℝ) ≤ (ρ : ℝ) := by exact_mod_cast (show (1 : ℤ) ≤ ρ by omega) + have hb2 : (ρ : ℝ) ≤ (n : ℝ) - 1 := by + have : (ρ : ℝ) ≤ ((n - 1 : ℤ) : ℝ) := by exact_mod_cast (show ρ ≤ n - 1 by omega) + simpa using this + have h := XY_basic hn _ hb1 hb2 + exact ⟨h.1, h.2.1, h.2.2.1⟩ + +/-- The frame `y`-coordinate vanishes only on the two vertices of the previous side. -/ +private lemma Y_pos_range (ρ : ℤ) (h1 : -(n : ℤ) ≤ ρ) (h2 : ρ ≤ n) (h0 : ρ ≠ 0) (h3 : ρ ≠ n) + (h4 : ρ ≠ -n) (h5 : ρ ≠ -1) (h6 : ρ ≠ n - 1) : 0 < Yr n ρ := by + rcases lt_or_gt_of_ne h0 with hneg | hpos + · obtain ⟨_, e2⟩ := XY_shift1 hn ρ + rw [e2] + have hb1 : (1 : ℝ) ≤ ((ρ + n : ℤ) : ℝ) := by exact_mod_cast (show (1 : ℤ) ≤ ρ + n by omega) + have hb2 : ((ρ + n : ℤ) : ℝ) ≤ (n : ℝ) - 1 := by + have : ((ρ + n : ℤ) : ℝ) ≤ ((n - 1 : ℤ) : ℝ) := by exact_mod_cast (show ρ + n ≤ n - 1 by omega) + simpa using this + have hb3 : ((ρ + n : ℤ) : ℝ) ≤ (n : ℝ) - 2 := by + have : ((ρ + n : ℤ) : ℝ) ≤ ((n - 2 : ℤ) : ℝ) := by exact_mod_cast (show ρ + n ≤ n - 2 by omega) + simpa using this + exact (XY_basic hn _ hb1 hb2).2.2.2 hb3 + · have hb1 : (1 : ℝ) ≤ (ρ : ℝ) := by exact_mod_cast (show (1 : ℤ) ≤ ρ by omega) + have hb2 : (ρ : ℝ) ≤ (n : ℝ) - 1 := by + have : (ρ : ℝ) ≤ ((n - 1 : ℤ) : ℝ) := by exact_mod_cast (show ρ ≤ n - 1 by omega) + simpa using this + have hb3 : (ρ : ℝ) ≤ (n : ℝ) - 2 := by + have : (ρ : ℝ) ≤ ((n - 2 : ℤ) : ℝ) := by exact_mod_cast (show ρ ≤ n - 2 by omega) + simpa using this + exact (XY_basic hn _ hb1 hb2).2.2.2 hb3 + +/-- All vertices have nonnegative frame coordinates. -/ +private lemma XY_nonneg (ρ : ℤ) (h1 : -(n : ℤ) ≤ ρ) (h2 : ρ ≤ n) : 0 ≤ Xr n ρ ∧ 0 ≤ Yr n ρ := by + by_cases h0 : ρ = 0 + · subst h0; simp [Xr_zero, Yr_zero] + by_cases h3 : ρ = n + · subst h3 + rw [show ((n : ℤ) : ℝ) = (0 : ℝ) + ((1 : ℤ) : ℝ) * n by push_cast; ring, Xr_shift hn, + Yr_shift hn, Xr_zero, Yr_zero] + simp + by_cases h4 : ρ = -n + · subst h4 + rw [show ((-(n : ℤ) : ℤ) : ℝ) = (0 : ℝ) + ((-1 : ℤ) : ℝ) * n by push_cast; ring, Xr_shift hn, + Yr_shift hn, Xr_zero, Yr_zero] + simp + have h := XY_range hn ρ h1 h2 h0 h3 h4 + exact ⟨h.1, h.2.1⟩ + +/-- Frame `x`-coordinate of a vertex, as an integer relative position. -/ +private lemma fx_vertex_int (C i : ℕ) : fx n C (vertex n i) = Xr n (((i : ℤ) - C : ℤ) : ℝ) := by + rw [fx_vertex hn]; push_cast; rfl + +/-- Frame `y`-coordinate of a vertex, with an integer relative position. -/ +private lemma fy_vertex_int (C i : ℕ) : fy n C (vertex n i) = Yr n (((i : ℤ) - C : ℤ) : ℝ) := by + rw [fy_vertex hn]; push_cast; rfl + +/-- `W = 1 + 2 cos (2π/n) ≥ 0`. -/ +private lemma W_nonneg : 0 ≤ Xr n (-2) := by + have := XY_range hn (-2) (by omega) (by omega) (by omega) (by omega) (by omega) + simpa using this.1 + +end intpos + +/-- Vertices are periodic with period `n`. -/ +private lemma vertex_add_n (n i : ℕ) (hn : 0 < n) : vertex n (i + n) = vertex n i := by + unfold vertex + rw [show 2 * (Real.pi : ℂ) * Complex.I * ((i + n : ℕ) : ℂ) / (n : ℂ) = + 2 * Real.pi * Complex.I * (i : ℂ) / n + (1 : ℕ) * (2 * Real.pi * Complex.I) by + have : (n : ℂ) ≠ 0 := by exact_mod_cast hn.ne' + push_cast; field_simp] + rw [Complex.exp_add, Complex.exp_nat_mul_two_pi_mul_I, mul_one] + +/-- Every vertex lies in the polygon. -/ +private lemma vertex_mem_polygon (n i : ℕ) (hn : 0 < n) : vertex n i ∈ polygon n := by + apply subset_convexHull + refine ⟨⟨i % n, Nat.mod_lt _ hn⟩, ?_⟩ + simp only + conv_rhs => rw [← Nat.mod_add_div i n] + induction (i / n) with + | zero => simp + | succ q ih => rw [Nat.mul_succ, ← add_assoc, vertex_add_n n _ hn, ih] + +/-! ### The polygon in the frames -/ + +section polygon +variable {n : ℕ} (hn : 3 ≤ n) +include hn + +/-- The polygon lies in the angle of each corner. -/ +private lemma polygon_sub (j : ℕ) (hj : j < n) : + polygon n ⊆ {z | 0 ≤ fx n (j + 1) z ∧ 0 ≤ fy n (j + 1) z} := by + apply convexHull_min + · rintro _ ⟨i, rfl⟩ + simp only [mem_ofPred_eq] + rw [fx_vertex_int hn, fy_vertex_int hn] + exact XY_nonneg hn _ (by omega) (by omega) + · intro x hx y hy a b ha hb hab + simp only [mem_ofPred_eq] at hx hy ⊢ + have e : a • x + b • y = x + (b : ℂ) * (y - x) := by + rw [Complex.real_smul, Complex.real_smul, show (a : ℂ) = 1 - b by + rw [show a = 1 - b by linarith]; push_cast; ring] + ring + rw [e, fx_aff, fy_aff] + constructor <;> nlinarith + +/-- Interior points have positive frame coordinates at every corner. -/ +private lemma interior_pos (j : ℕ) (hj : j < n) {z : ℂ} (hz : z ∈ interior (polygon n)) : + 0 < fx n (j + 1) z ∧ 0 < fy n (j + 1) z := by + have key : ∀ (v : ℂ) (g : ℂ → ℝ), Continuous g → + (∀ e : ℝ, g (z + e * v) = g z - e) → (∀ w ∈ polygon n, 0 ≤ g w) → 0 < g z := by + intro v g _ hg hP + let p : ℝ → ℂ := fun e => z + e * v + have hp : Continuous p := by fun_prop + have hO : IsOpen (p ⁻¹' interior (polygon n)) := isOpen_interior.preimage hp + have h0 : (0 : ℝ) ∈ p ⁻¹' interior (polygon n) := by simp [p, hz] + obtain ⟨δ, hδ, hball⟩ := Metric.isOpen_iff.mp hO 0 h0 + have hmem : p (δ / 2) ∈ interior (polygon n) := by + apply hball + rw [Metric.mem_ball, Real.dist_eq, sub_zero, abs_of_pos (by positivity)] + linarith + have := hP _ (interior_subset hmem) + simp only [p] at this + rw [hg] at this + linarith + constructor + · apply key (vertex n (j + 1) - vertex n j) (fx n (j + 1)) (fx_cont n (j + 1)) + · intro e + rw [show z + (e : ℂ) * (vertex n (j + 1) - vertex n j) = + z + (e : ℂ) * (vertex n (j + 1) - vertex n j) from rfl, fx_aff, fx_vertex hn, fx_vertex hn, + show ((j + 1 : ℕ) : ℝ) - ((j + 1 : ℕ) : ℝ) = 0 by ring, + show ((j : ℕ) : ℝ) - ((j + 1 : ℕ) : ℝ) = -1 by push_cast; ring, Xr_zero, Xr_neg_one hn] + ring + · intro w hw; exact (polygon_sub hn j hj hw).1 + · apply key (vertex n (j + 1) - vertex n (j + 2)) (fy n (j + 1)) (fy_cont n (j + 1)) + · intro e + rw [fy_aff, fy_vertex hn, fy_vertex hn, + show ((j + 1 : ℕ) : ℝ) - ((j + 1 : ℕ) : ℝ) = 0 by ring, + show ((j + 2 : ℕ) : ℝ) - ((j + 1 : ℕ) : ℝ) = 1 by push_cast; ring, Yr_zero, Yr_one hn] + ring + · intro w hw; exact (polygon_sub hn j hj hw).2 + +/-- The open corner triangle lies in the interior of the polygon. -/ +private lemma tri_interior (j : ℕ) {z : ℂ} (hx : 0 < fx n (j + 1) z) (hy : 0 < fy n (j + 1) z) + (hxy : fx n (j + 1) z + fy n (j + 1) z < 1) : z ∈ interior (polygon n) := by + have hO : IsOpen {w | 0 < fx n (j + 1) w ∧ 0 < fy n (j + 1) w ∧ + fx n (j + 1) w + fy n (j + 1) w < 1} := by + have c1 := fx_cont n (j + 1) + have c2 := fy_cont n (j + 1) + refine (isOpen_lt continuous_const c1).inter ((isOpen_lt continuous_const c2).inter + (isOpen_lt (c1.add c2) continuous_const)) + refine interior_maximal ?_ hO ⟨hx, hy, hxy⟩ + rintro w ⟨hwx, hwy, hwxy⟩ + have hn0 : 0 < n := by omega + have hconv : Convex ℝ (polygon n) := convex_convexHull ℝ _ + have hmem := hconv.sum_mem (t := Finset.univ) (w := ![1 - fx n (j + 1) w - fy n (j + 1) w, + fx n (j + 1) w, fy n (j + 1) w]) (z := ![vertex n (j + 1), vertex n j, vertex n (j + 2)]) + (by intro i _; fin_cases i <;> simp <;> linarith) + (by simp [Fin.sum_univ_three]; ring) + (by intro i _; fin_cases i <;> simp <;> exact vertex_mem_polygon n _ hn0) + rw [Fin.sum_univ_three] at hmem + simp only [Matrix.cons_val_zero, Matrix.cons_val_one, Matrix.cons_val_two, Matrix.head_cons, + Matrix.tail_cons, Complex.real_smul] at hmem + convert hmem using 1 + conv_lhs => rw [recon hn j w] + push_cast + ring + +/-- The open polygon is nonempty. -/ +private lemma interior_nonempty : (interior (polygon n)).Nonempty := by + have hs := sin_two_ph_pos hn + have h1 := one_sub_cos_pos hn + -- the point with frame coordinates (1/3, 1/3) at corner 1 + let z : ℂ := vertex n 1 + ((1 / 3 : ℝ) : ℂ) * (vertex n 0 - vertex n 1) + + ((1 / 3 : ℝ) : ℂ) * (vertex n 2 - vertex n 1) + have hx : fx n (0 + 1) z = 1 / 3 := by + simp only [z] + rw [show vertex n 1 + ((1 / 3 : ℝ) : ℂ) * (vertex n 0 - vertex n 1) + + ((1 / 3 : ℝ) : ℂ) * (vertex n 2 - vertex n 1) = (vertex n 1 + ((1 / 3 : ℝ) : ℂ) * + (vertex n 0 - vertex n 1)) + ((1 / 3 : ℝ) : ℂ) * (vertex n 2 - vertex n 1) from rfl, + fx_aff, fx_aff, fx_vertex hn, fx_vertex hn, fx_vertex hn] + norm_num [Xr_zero, Xr_one, Xr_neg_one hn] + have hy : fy n (0 + 1) z = 1 / 3 := by + simp only [z] + rw [fy_aff, fy_aff, fy_vertex hn, fy_vertex hn, fy_vertex hn] + norm_num [Yr_zero, Yr_one hn, Yr_neg_one] + exact ⟨z, tri_interior hn 0 (by rw [hx]; norm_num) (by rw [hy]; norm_num) + (by rw [hx, hy]; norm_num)⟩ + +end polygon + +/-! ### Chords -/ + +/-- The parameter `t = (m+1)/(k+1)` of the internal polygon number `m+1`. -/ +private noncomputable def tt (k m : ℕ) : ℝ := ((m : ℝ) + 1) / ((k : ℝ) + 1) + +/-- The rational version of `tt`. -/ +private def ttq (k m : ℕ) : ℚ := ((m : ℚ) + 1) / ((k : ℚ) + 1) + +/-- `tt` is a rational number. -/ +private lemma tt_eq_cast (k m : ℕ) : tt k m = ((ttq k m : ℚ) : ℝ) := by + unfold tt ttq; push_cast; rfl + +/-- `tt > 0`. -/ +private lemma tt_pos (k m : ℕ) : 0 < tt k m := by unfold tt; positivity + +/-- `tt < 1`. -/ +private lemma tt_lt_one {k m : ℕ} (hm : m < k) : tt k m < 1 := by + unfold tt + rw [div_lt_one (by positivity)] + have : (m : ℝ) < k := by exact_mod_cast hm + linarith + +/-- `tt` is strictly increasing. -/ +private lemma tt_lt_iff (k m m' : ℕ) : tt k m < tt k m' ↔ m < m' := by + unfold tt + rw [div_lt_div_iff_of_pos_right (by positivity)] + constructor + · intro h; exact_mod_cast (show (m : ℝ) < m' by linarith) + · intro h; have : (m : ℝ) < m' := by exact_mod_cast h + linarith + +/-- `tt` is injective. -/ +private lemma tt_inj (k m m' : ℕ) : tt k m = tt k m' ↔ m = m' := by + constructor + · intro h + rcases lt_trichotomy m m' with h' | h' | h' + · exact absurd h ((tt_lt_iff k m m').mpr h').ne + · exact h' + · exact absurd h ((tt_lt_iff k m' m).mpr h').ne' + · rintro rfl; rfl + +/-- The line functional of chord `(j, m)` (zero exactly on the line of the chord). -/ +private noncomputable def Fl (n k j m : ℕ) (z : ℂ) : ℝ := + tt k m * fx n (j + 1) z + (1 - tt k m) * fy n (j + 1) z - tt k m * (1 - tt k m) + +/-- Parametrisation of chord `(j, m)`: `r = 0` and `r = 1` give its endpoints. -/ +private noncomputable def gam (n k j m : ℕ) (r : ℝ) : ℂ := + divPt n k j (m + 1) + (r : ℂ) * (divPt n k (j + 1) (m + 1) - divPt n k j (m + 1)) + +/-- The division points in terms of `tt`. -/ +private lemma divPt_eq (n k j m : ℕ) : + divPt n k j (m + 1) = vertex n j + (tt k m : ℂ) * (vertex n (j + 1) - vertex n j) := by + unfold divPt tt; push_cast; ring + +/-- The line functional is real-affine. -/ +private lemma Fl_aff (n k j m : ℕ) (z p q : ℂ) (r : ℝ) : + Fl n k j m (z + r * (q - p)) = Fl n k j m z + r * (Fl n k j m q - Fl n k j m p) := by + unfold Fl; rw [fx_aff, fy_aff]; ring + +/-- The line functional is continuous. -/ +private lemma Fl_cont (n k j m : ℕ) : Continuous (Fl n k j m) := by + unfold Fl + have := fx_cont n (j + 1) + have := fy_cont n (j + 1) + fun_prop + +/-- The "next vertex index" `j + 1` reduced modulo `n` (for `j < n`). -/ +private def nx (n j : ℕ) : ℕ := if j + 1 = n then 0 else j + 1 + +/-- `nx n j < n`. -/ +private lemma nx_lt {n j : ℕ} (hj : j < n) : nx n j < n := by unfold nx; split_ifs <;> omega + +section chords +variable {n : ℕ} (hn : 3 ≤ n) +include hn + +/-- Frame `x`-coordinate of a vertex at a given relative position. -/ +private lemma fxv (C i : ℕ) (ρ : ℝ) (h : (i : ℝ) - (C : ℝ) = ρ) : fx n C (vertex n i) = Xr n ρ := by + rw [fx_vertex hn, h] + +/-- Frame `y`-coordinate of a vertex at a given relative position. -/ +private lemma fyv (C i : ℕ) (ρ : ℝ) (h : (i : ℝ) - (C : ℝ) = ρ) : fy n C (vertex n i) = Yr n ρ := by + rw [fy_vertex hn, h] + +/-- Frame `x`-coordinate along the chord. -/ +private lemma fx_gam (k j m : ℕ) (r : ℝ) : fx n (j + 1) (gam n k j m r) = (1 - tt k m) * (1 - r) := by + unfold gam + rw [fx_aff, divPt_eq, divPt_eq, fx_aff, fx_aff, fxv hn _ j (-1) (by push_cast; ring), + fxv hn _ (j + 1) 0 (by push_cast; ring), fxv hn _ (j + 1 + 1) 1 (by push_cast; ring), + Xr_neg_one hn, Xr_zero, Xr_one] + ring + +/-- Frame `y`-coordinate along the chord. -/ +private lemma fy_gam (k j m : ℕ) (r : ℝ) : fy n (j + 1) (gam n k j m r) = tt k m * r := by + unfold gam + rw [fy_aff, divPt_eq, divPt_eq, fy_aff, fy_aff, fyv hn _ j (-1) (by push_cast; ring), + fyv hn _ (j + 1) 0 (by push_cast; ring), fyv hn _ (j + 1 + 1) 1 (by push_cast; ring), + Yr_neg_one, Yr_zero, Yr_one hn] + ring + +/-- The chord lies on its line. -/ +private lemma Fl_gam (k j m : ℕ) (r : ℝ) : Fl n k j m (gam n k j m r) = 0 := by + unfold Fl; rw [fx_gam hn, fy_gam hn]; ring + +/-- The open chord lies in the open polygon. -/ +private lemma gam_interior {k j m : ℕ} (hm : m < k) {r : ℝ} (hr0 : 0 < r) (hr1 : r < 1) : + gam n k j m r ∈ interior (polygon n) := by + have ht0 := tt_pos k m + have ht1 := tt_lt_one hm + apply tri_interior hn j + · rw [fx_gam hn]; nlinarith + · rw [fy_gam hn]; nlinarith + · rw [fx_gam hn, fy_gam hn]; nlinarith + +/-- The line of a chord meets the open polygon exactly in the open chord. -/ +private lemma line_inter {k j m : ℕ} (hj : j < n) (hm : m < k) {z : ℂ} (hz : z ∈ interior (polygon n)) + (h0 : Fl n k j m z = 0) : ∃ r : ℝ, 0 < r ∧ r < 1 ∧ z = gam n k j m r := by + obtain ⟨hx, hy⟩ := interior_pos hn j hj hz + have ht0 := tt_pos k m + have ht1 := tt_lt_one hm + have hlin : tt k m * fx n (j + 1) z + (1 - tt k m) * fy n (j + 1) z = + tt k m * (1 - tt k m) := by + unfold Fl at h0; linarith + obtain ⟨r, hr⟩ : ∃ r : ℝ, r = fy n (j + 1) z / tt k m := ⟨_, rfl⟩ + have hy' : fy n (j + 1) z = tt k m * r := by rw [hr]; field_simp + have hx' : fx n (j + 1) z = (1 - tt k m) * (1 - r) := by + have : tt k m * fx n (j + 1) z = tt k m * ((1 - tt k m) * (1 - r)) := by + rw [hy'] at hlin; linear_combination hlin + exact mul_left_cancel₀ ht0.ne' this + refine ⟨r, ?_, ?_, ?_⟩ + · rw [hr]; exact div_pos hy ht0 + · have : 0 < (1 - tt k m) * (1 - r) := hx' ▸ hx + nlinarith + · conv_lhs => rw [recon hn j z] + rw [hx', hy'] + unfold gam + rw [divPt_eq, divPt_eq] + push_cast + ring + +omit hn in +/-- The chord as the image of `gam` on `[0, 1]`. -/ +private lemma chord_eq (k : ℕ) (c : Fin n × Fin k) : + chord n k c = gam n k c.1 c.2 '' Icc 0 1 := by + unfold chord gam + rw [segment_eq_image'] + ext z + simp only [mem_image, Complex.real_smul] + +/-- Inside the open polygon, a point is on a chord iff it is on its line. -/ +private lemma mem_chord_iff {k : ℕ} (c : Fin n × Fin k) {z : ℂ} (hz : z ∈ interior (polygon n)) : + z ∈ chord n k c ↔ Fl n k c.1 c.2 z = 0 := by + rw [chord_eq] + constructor + · rintro ⟨r, _, rfl⟩; exact Fl_gam hn _ _ _ _ + · intro h + obtain ⟨r, hr0, hr1, rfl⟩ := line_inter hn c.1.2 c.2.2 hz h + exact ⟨r, ⟨hr0.le, hr1.le⟩, rfl⟩ + +end chords + +/-! ### Meeting points of a chord with the other lines -/ + +/-- Value of the line functional of a chord with parameter `s` at the vertex at relative +position `ρ` from its corner. -/ +private noncomputable def Fv (n : ℕ) (s ρ : ℝ) : ℝ := s * Xr n ρ + (1 - s) * Yr n ρ - s * (1 - s) + +/-- Coefficient for the line at the next corner. -/ +private noncomputable def aP (s t W : ℝ) : ℝ := (1 - t) * (s * W + (1 - s) ^ 2) + t * s ^ 2 + +/-- Coefficient for the line at the previous corner. -/ +private noncomputable def bM (s t W : ℝ) : ℝ := (1 - t) * (1 - s) ^ 2 + t * (s ^ 2 + (1 - s) * W) + +section pairs +variable {n : ℕ} (hn : 3 ≤ n) +include hn + +/-- The line functional at a vertex. -/ +private lemma Fl_vertex (k j' m' i : ℕ) : + Fl n k j' m' (vertex n i) = Fv n (tt k m') ((i : ℝ) - ((j' + 1 : ℕ) : ℝ)) := by + unfold Fl Fv; rw [fx_vertex hn, fy_vertex hn] + +/-- The line functional of chord `(j', m')` along chord `(j, m)`. -/ +private lemma Fl_gam_master (k j m j' m' : ℕ) (r : ℝ) : + Fl n k j' m' (gam n k j m r) = + (1 - r) * ((1 - tt k m) * Fv n (tt k m') ((j : ℝ) - (j' + 1)) + + tt k m * Fv n (tt k m') ((j : ℝ) - j')) + + r * ((1 - tt k m) * Fv n (tt k m') ((j : ℝ) - j') + + tt k m * Fv n (tt k m') ((j : ℝ) + 1 - j')) := by + unfold gam + rw [Fl_aff, divPt_eq, divPt_eq, Fl_aff, Fl_aff, Fl_vertex hn, Fl_vertex hn, Fl_vertex hn] + have e0 : ((j : ℕ) : ℝ) - ((j' + 1 : ℕ) : ℝ) = (j : ℝ) - (j' + 1) := by push_cast; ring + have e1 : ((j + 1 : ℕ) : ℝ) - ((j' + 1 : ℕ) : ℝ) = (j : ℝ) - j' := by push_cast; ring + have e2 : ((j + 1 + 1 : ℕ) : ℝ) - ((j' + 1 : ℕ) : ℝ) = (j : ℝ) + 1 - j' := by push_cast; ring + rw [e0, e1, e2]; ring + +/-- `Fv` is invariant under integer multiples of `n`. -/ +private lemma Fv_shift (s ρ : ℝ) (q : ℤ) : Fv n s (ρ + q * n) = Fv n s ρ := by + unfold Fv; rw [Xr_shift hn, Yr_shift hn] + +/-- `Fv` two steps back. -/ +private lemma Fv_m2 (s : ℝ) : Fv n s (-2) = s * Xr n (-2) + (1 - s) ^ 2 := by + unfold Fv; rw [Yr_neg_two hn]; ring +/-- `Fv` one step back. -/ +private lemma Fv_m1 (s : ℝ) : Fv n s (-1) = s ^ 2 := by + unfold Fv; rw [Xr_neg_one hn, Yr_neg_one]; ring +omit hn in +/-- `Fv` at the corner. -/ +private lemma Fv_0 (s : ℝ) : Fv n s 0 = -(s * (1 - s)) := by + unfold Fv; rw [Xr_zero, Yr_zero]; ring +/-- `Fv` one step ahead. -/ +private lemma Fv_1 (s : ℝ) : Fv n s 1 = (1 - s) ^ 2 := by + unfold Fv; rw [Xr_one, Yr_one hn]; ring +/-- `Fv` two steps ahead. -/ +private lemma Fv_2 (s : ℝ) : Fv n s 2 = s ^ 2 + (1 - s) * Xr n (-2) := by + unfold Fv; rw [Xr_two hn, Yr_two_eq]; ring + +/-- Every vertex other than the corner lies strictly on the far side of the line. -/ +private lemma Fv_pos_int (s : ℝ) (hs0 : 0 < s) (hs1 : s < 1) (ρ : ℤ) (h1 : -(n : ℤ) ≤ ρ) (h2 : ρ ≤ n) + (h0 : ρ ≠ 0) (h3 : ρ ≠ n) (h4 : ρ ≠ -n) : 0 < Fv n s ρ := by + obtain ⟨hX, hY, hXY⟩ := XY_range hn ρ h1 h2 h0 h3 h4 + unfold Fv + rcases le_total s (1 / 2) with h | h + · nlinarith [mul_nonneg hs0.le (sub_nonneg.mpr hXY), mul_nonneg (sub_nonneg.mpr h) hY] + · nlinarith [mul_nonneg (sub_nonneg.mpr hs1.le) (sub_nonneg.mpr hXY), + mul_nonneg (sub_nonneg.mpr h) hX] + +/-- Two chords at the same corner: they meet at parameter `s` along the first. -/ +private lemma pair_same (k j m m' : ℕ) (r : ℝ) : + Fl n k j m' (gam n k j m r) = (tt k m - tt k m') * (r - tt k m') := by + rw [Fl_gam_master hn, show (j : ℝ) - (j + 1) = -1 by ring, sub_self, + show (j : ℝ) + 1 - j = 1 by ring, Fv_m1 hn, Fv_0, Fv_1 hn] + ring + +/-- A chord and a line at the next corner. -/ +private lemma pair_next (k j m m' : ℕ) (_hj : j < n) (r : ℝ) : + Fl n k (nx n j) m' (gam n k j m r) = + (1 - r) * aP (tt k m') (tt k m) (Xr n (-2)) + r * (tt k m' * (tt k m' - tt k m)) := by + rw [Fl_gam_master hn] + unfold nx + split_ifs with h + · have hjn : (j : ℝ) + 1 = n := by exact_mod_cast h + rw [show (j : ℝ) - (((0 : ℕ) : ℝ) + 1) = -2 + ((1 : ℤ) : ℝ) * n by push_cast; linarith, + show (j : ℝ) - ((0 : ℕ) : ℝ) = -1 + ((1 : ℤ) : ℝ) * n by push_cast; linarith, + show (j : ℝ) + 1 - ((0 : ℕ) : ℝ) = 0 + ((1 : ℤ) : ℝ) * n by push_cast; linarith, + Fv_shift hn, Fv_shift hn, Fv_shift hn, Fv_m2 hn, Fv_m1 hn, Fv_0] + unfold aP; ring + · rw [show (j : ℝ) - (((j + 1 : ℕ) : ℝ) + 1) = -2 by push_cast; ring, + show (j : ℝ) - ((j + 1 : ℕ) : ℝ) = -1 by push_cast; ring, + show (j : ℝ) + 1 - ((j + 1 : ℕ) : ℝ) = 0 by push_cast; ring, Fv_m2 hn, Fv_m1 hn, Fv_0] + unfold aP; ring + +/-- A chord and a line at the previous corner. -/ +private lemma pair_prev (k j' m m' : ℕ) (_hj' : j' < n) (r : ℝ) : + Fl n k j' m' (gam n k (nx n j') m r) = + (1 - r) * ((1 - tt k m') * (tt k m - tt k m')) + r * bM (tt k m') (tt k m) (Xr n (-2)) := by + rw [Fl_gam_master hn] + unfold nx + split_ifs with h + · have hjn : (j' : ℝ) + 1 = n := by exact_mod_cast h + rw [show ((0 : ℕ) : ℝ) - ((j' : ℝ) + 1) = 0 + ((-1 : ℤ) : ℝ) * n by push_cast; linarith, + show ((0 : ℕ) : ℝ) - (j' : ℝ) = 1 + ((-1 : ℤ) : ℝ) * n by push_cast; linarith, + show ((0 : ℕ) : ℝ) + 1 - (j' : ℝ) = 2 + ((-1 : ℤ) : ℝ) * n by push_cast; linarith, + Fv_shift hn, Fv_shift hn, Fv_shift hn, Fv_0, Fv_1 hn, Fv_2 hn] + unfold bM; ring + · rw [show ((j' + 1 : ℕ) : ℝ) - ((j' : ℝ) + 1) = 0 by push_cast; ring, + show ((j' + 1 : ℕ) : ℝ) - (j' : ℝ) = 1 by push_cast; ring, + show ((j' + 1 : ℕ) : ℝ) + 1 - (j' : ℝ) = 2 by push_cast; ring, Fv_0, Fv_1 hn, Fv_2 hn] + unfold bM; ring + +/-- Lines at corners two or more steps away do not meet the closed chord. -/ +private lemma pair_far {k j m j' m' : ℕ} (hj : j < n) (hj' : j' < n) (hm' : m' < k) + (h1 : j' ≠ j) (h2 : j' ≠ nx n j) (h3 : j ≠ nx n j') {r : ℝ} (hr0 : 0 ≤ r) (hr1 : r ≤ 1) + (hm : m < k) : 0 < Fl n k j' m' (gam n k j m r) := by + have hs0 := tt_pos k m' + have hs1 := tt_lt_one hm' + have ht0 := tt_pos k m + have ht1 := tt_lt_one hm + unfold nx at h2 h3 + have p0 : 0 < Fv n (tt k m') ((j : ℝ) - (j' + 1)) := by + have := Fv_pos_int hn _ hs0 hs1 ((j : ℤ) - j' - 1) (by split_ifs at * <;> omega) + (by split_ifs at * <;> omega) (by split_ifs at * <;> omega) (by split_ifs at * <;> omega) + (by split_ifs at * <;> omega) + push_cast at this; convert this using 2; ring + have p1 : 0 < Fv n (tt k m') ((j : ℝ) - j') := by + have := Fv_pos_int hn _ hs0 hs1 ((j : ℤ) - j') (by split_ifs at * <;> omega) + (by split_ifs at * <;> omega) (by split_ifs at * <;> omega) (by split_ifs at * <;> omega) + (by split_ifs at * <;> omega) + push_cast at this; exact this + have p2 : 0 < Fv n (tt k m') ((j : ℝ) + 1 - j') := by + have := Fv_pos_int hn _ hs0 hs1 ((j : ℤ) - j' + 1) (by split_ifs at * <;> omega) + (by split_ifs at * <;> omega) (by split_ifs at * <;> omega) (by split_ifs at * <;> omega) + (by split_ifs at * <;> omega) + push_cast at this; convert this using 2; ring + rw [Fl_gam_master hn] + have hA : 0 < (1 - tt k m) * Fv n (tt k m') ((j : ℝ) - (j' + 1)) + + tt k m * Fv n (tt k m') ((j : ℝ) - j') := by + have := mul_pos (sub_pos.mpr ht1) p0; have := mul_pos ht0 p1; linarith + have hB : 0 < (1 - tt k m) * Fv n (tt k m') ((j : ℝ) - j') + + tt k m * Fv n (tt k m') ((j : ℝ) + 1 - j') := by + have := mul_pos (sub_pos.mpr ht1) p1; have := mul_pos ht0 p2; linarith + rcases eq_or_lt_of_le hr1 with h | h + · subst h; simp [hB] + · have := mul_pos (sub_pos.mpr h) hA + have := mul_nonneg hr0 hB.le + linarith + +/-- `aP > 0`. -/ +private lemma aP_pos {s t : ℝ} (hs1 : s < 1) (ht0 : 0 < t) (ht1 : t < 1) (hs0 : 0 < s) : + 0 < aP s t (Xr n (-2)) := by + have hW := W_nonneg hn + unfold aP + have : 0 < (1 - t) * (1 - s) ^ 2 := mul_pos (by linarith) (by nlinarith) + have : 0 ≤ (1 - t) * (s * Xr n (-2)) := mul_nonneg (by linarith) (mul_nonneg hs0.le hW) + nlinarith + +/-- `bM > 0`. -/ +private lemma bM_pos {s t : ℝ} (hs1 : s < 1) (ht0 : 0 < t) (ht1 : t < 1) : + 0 < bM s t (Xr n (-2)) := by + have hW := W_nonneg hn + unfold bM + have : 0 < (1 - t) * (1 - s) ^ 2 := mul_pos (by linarith) (by nlinarith) + have : 0 ≤ t * (s ^ 2 + (1 - s) * Xr n (-2)) := + mul_nonneg ht0.le (add_nonneg (sq_nonneg _) (mul_nonneg (by linarith) hW)) + linarith + +/-- Classification of the points where a line meets the open chord `(j, m)`. -/ +private lemma cls {k j m j' m' : ℕ} (hj : j < n) (hj' : j' < n) (hm : m < k) (hm' : m' < k) + (hne : ¬ (j' = j ∧ m' = m)) {r : ℝ} (hr0 : 0 < r) (hr1 : r < 1) + (h : Fl n k j' m' (gam n k j m r) = 0) : + (j' = j ∧ r = tt k m') ∨ + (j' = nx n j ∧ tt k m' < tt k m ∧ + (1 - r) * aP (tt k m') (tt k m) (Xr n (-2)) + r * (tt k m' * (tt k m' - tt k m)) = 0) ∨ + (j = nx n j' ∧ tt k m < tt k m' ∧ + (1 - r) * ((1 - tt k m') * (tt k m - tt k m')) + r * bM (tt k m') (tt k m) (Xr n (-2)) = 0) := by + have hs0 := tt_pos k m' + have hs1 := tt_lt_one hm' + have ht0 := tt_pos k m + have ht1 := tt_lt_one hm + by_cases h1 : j' = j + · subst h1 + left + refine ⟨rfl, ?_⟩ + rw [pair_same hn] at h + have hne' : tt k m - tt k m' ≠ 0 := by + intro h' + apply hne + exact ⟨rfl, ((tt_inj k m' m).mp (by linarith))⟩ + have := (mul_eq_zero.mp h).resolve_left hne' + linarith + by_cases h2 : j' = nx n j + · subst h2 + right; left + rw [pair_next hn k j m m' hj] at h + refine ⟨rfl, ?_, h⟩ + by_contra hlt + replace hlt := not_lt.mp hlt + have := aP_pos hn hs1 ht0 ht1 hs0 + have : 0 < (1 - r) * aP (tt k m') (tt k m) (Xr n (-2)) := mul_pos (by linarith) this + have : 0 ≤ r * (tt k m' * (tt k m' - tt k m)) := + mul_nonneg hr0.le (mul_nonneg hs0.le (by linarith)) + linarith + by_cases h3 : j = nx n j' + · subst h3 + right; right + rw [pair_prev hn k j' m m' hj'] at h + refine ⟨rfl, ?_, h⟩ + by_contra hlt + replace hlt := not_lt.mp hlt + have := bM_pos hn hs1 ht0 ht1 + have : 0 < r * bM (tt k m') (tt k m) (Xr n (-2)) := mul_pos hr0 this + have : 0 ≤ (1 - r) * ((1 - tt k m') * (tt k m - tt k m')) := + mul_nonneg (by linarith) (mul_nonneg (by linarith) (by linarith)) + linarith + exfalso + have := pair_far hn hj hj' hm' h1 h2 h3 hr0.le hr1.le hm + linarith + +end pairs + +/-! ### No three lines through one point (`n = 5`, `n ≥ 7`) -/ + +/-- `W = 1 + 2 cos (2π/n)` is irrational for `n = 5` and `n ≥ 7` (Niven). -/ +private lemma W_irr {n : ℕ} (hn5 : n = 5 ∨ 7 ≤ n) (q : ℚ) : Xr n (-2) ≠ q := by + have hn : 3 ≤ n := by omega + rw [Xr_neg_two hn] + intro h + have hcos : Real.cos (2 * ph n) = ((q - 1) / 2 : ℚ) := by push_cast; linarith + have hθ : ∃ r : ℚ, 2 * ph n = r * Real.pi := ⟨2 / n, by unfold ph; push_cast; ring⟩ + have hmem := niven hθ ⟨_, hcos⟩ + have hpi := Real.pi_pos + have hnpos : (0 : ℝ) < n := n_pos hn + have hbounds : (0 < Real.cos (2 * ph n) ∧ Real.cos (2 * ph n) < 1 / 2) ∨ + (1 / 2 < Real.cos (2 * ph n) ∧ Real.cos (2 * ph n) < 1) := by + rcases hn5 with rfl | h7 + · left + have e : 2 * ph 5 = 2 * Real.pi / 5 := by unfold ph; push_cast; ring + rw [e] + constructor + · rw [← Real.cos_pi_div_two] + exact Real.cos_lt_cos_of_nonneg_of_le_pi (by positivity) (by linarith) (by linarith) + · rw [← Real.cos_pi_div_three] + exact Real.cos_lt_cos_of_nonneg_of_le_pi (by positivity) (by linarith) (by linarith) + · right + have h7' : (7 : ℝ) ≤ n := by exact_mod_cast h7 + have hlt : 2 * ph n < Real.pi / 3 := by + unfold ph + rw [mul_div_assoc', div_lt_div_iff₀ hnpos (by norm_num)] + nlinarith + have hpos : 0 < 2 * ph n := by have := ph_pos hn; linarith + constructor + · rw [← Real.cos_pi_div_three] + exact Real.cos_lt_cos_of_nonneg_of_le_pi (by positivity) (by linarith) hlt + · rw [← Real.cos_zero] + exact Real.cos_lt_cos_of_nonneg_of_le_pi le_rfl (by linarith) hpos + simp only [Set.mem_insert_iff, Set.mem_singleton_iff] at hmem + rcases hmem with e | e | e | e | e <;> rw [e] at hbounds <;> norm_num at hbounds + +/-- A concurrency at the next corner would make `W` rational. -/ +private lemma I1 {n : ℕ} (hn5 : n = 5 ∨ 7 ≤ n) {k a b c : ℕ} (ha : a < k) (hc : c < k) + (h : (1 - tt k a) * aP (tt k b) (tt k c) (Xr n (-2)) + tt k a * (tt k b * (tt k b - tt k c)) = 0) : + False := by + have h1 := tt_lt_one ha + have h2 := tt_lt_one hc + have h3 := tt_pos k b + have hα : (1 - tt k a) * (1 - tt k c) * tt k b ≠ 0 := by + apply mul_ne_zero (mul_ne_zero (by linarith) (by linarith)) h3.ne' + have key : Xr n (-2) = -((1 - tt k a) * ((1 - tt k c) * (1 - tt k b) ^ 2 + tt k c * tt k b ^ 2) + + tt k a * (tt k b * (tt k b - tt k c))) / ((1 - tt k a) * (1 - tt k c) * tt k b) := by + rw [eq_div_iff hα]; unfold aP at h; linear_combination h + apply W_irr hn5 (-((1 - ttq k a) * ((1 - ttq k c) * (1 - ttq k b) ^ 2 + ttq k c * ttq k b ^ 2) + + ttq k a * (ttq k b * (ttq k b - ttq k c))) / ((1 - ttq k a) * (1 - ttq k c) * ttq k b)) + rw [key] + simp only [tt_eq_cast] + push_cast + ring + +/-- A concurrency at the previous corner would make `W` rational. -/ +private lemma I2 {n : ℕ} (hn5 : n = 5 ∨ 7 ≤ n) {k a b c : ℕ} (hb : b < k) + (h : (1 - tt k a) * ((1 - tt k b) * (tt k c - tt k b)) + tt k a * bM (tt k b) (tt k c) (Xr n (-2)) = 0) : + False := by + have h1 := tt_pos k a + have h2 := tt_lt_one hb + have h3 := tt_pos k c + have hα : tt k a * tt k c * (1 - tt k b) ≠ 0 := by + apply mul_ne_zero (mul_ne_zero h1.ne' h3.ne') (by linarith) + have key : Xr n (-2) = -((1 - tt k a) * ((1 - tt k b) * (tt k c - tt k b)) + + tt k a * ((1 - tt k c) * (1 - tt k b) ^ 2 + tt k c * tt k b ^ 2)) / + (tt k a * tt k c * (1 - tt k b)) := by + rw [eq_div_iff hα]; unfold bM at h; linear_combination h + apply W_irr hn5 (-((1 - ttq k a) * ((1 - ttq k b) * (ttq k c - ttq k b)) + + ttq k a * ((1 - ttq k c) * (1 - ttq k b) ^ 2 + ttq k c * ttq k b ^ 2)) / + (ttq k a * ttq k c * (1 - ttq k b))) + rw [key] + simp only [tt_eq_cast] + push_cast + ring + +/-- **No triple points.** For `n = 5` and `n ≥ 7`, no point of the open polygon lies on the +lines of three distinct chords. -/ +private theorem no_triple {n : ℕ} (hn5 : n = 5 ∨ 7 ≤ n) {k j₁ m₁ j₂ m₂ j₃ m₃ : ℕ} + (hj₁ : j₁ < n) (hj₂ : j₂ < n) (hj₃ : j₃ < n) (hm₁ : m₁ < k) (hm₂ : m₂ < k) (hm₃ : m₃ < k) + (h12 : ¬ (j₂ = j₁ ∧ m₂ = m₁)) (h13 : ¬ (j₃ = j₁ ∧ m₃ = m₁)) (h23 : ¬ (j₃ = j₂ ∧ m₃ = m₂)) + {p : ℂ} (hp : p ∈ interior (polygon n)) (e₁ : Fl n k j₁ m₁ p = 0) (e₂ : Fl n k j₂ m₂ p = 0) + (e₃ : Fl n k j₃ m₃ p = 0) : False := by + have hn : 3 ≤ n := by omega + obtain ⟨r₁, hr₁0, hr₁1, hp₁⟩ := line_inter hn hj₁ hm₁ hp e₁ + obtain ⟨r₂, hr₂0, hr₂1, hp₂⟩ := line_inter hn hj₂ hm₂ hp e₂ + have c12 := cls hn hj₁ hj₂ hm₁ hm₂ h12 hr₁0 hr₁1 (hp₁ ▸ e₂) + have c13 := cls hn hj₁ hj₃ hm₁ hm₃ h13 hr₁0 hr₁1 (hp₁ ▸ e₃) + have c21 := cls hn hj₂ hj₁ hm₂ hm₁ (fun h => h12 ⟨h.1.symm, h.2.symm⟩) hr₂0 hr₂1 (hp₂ ▸ e₁) + have c23 := cls hn hj₂ hj₃ hm₂ hm₃ h23 hr₂0 hr₂1 (hp₂ ▸ e₃) + have hn5' : 5 ≤ n := by omega + rcases c12 with ⟨a1, a2⟩ | ⟨a1, _, a3⟩ | ⟨a1, _, a3⟩ <;> + rcases c13 with ⟨b1, b2⟩ | ⟨b1, _, b3⟩ | ⟨b1, _, b3⟩ + · exact h23 ⟨by omega, (tt_inj k m₃ m₂).mp (b2 ▸ a2)⟩ + · rw [a2] at b3; exact I1 hn5 hm₂ hm₁ b3 + · rw [a2] at b3; exact I2 hn5 hm₃ b3 + · rw [b2] at a3; exact I1 hn5 hm₃ hm₁ a3 + · -- next / next + rcases c23 with ⟨d1, d2⟩ | ⟨d1, _, _⟩ | ⟨d1, _, _⟩ + · rcases c21 with ⟨f1, _⟩ | ⟨f1, _, _⟩ | ⟨f1, _, f3⟩ + · unfold nx at *; split_ifs at * <;> omega + · unfold nx at *; split_ifs at * <;> omega + · rw [d2] at f3; exact I2 hn5 hm₁ f3 + · unfold nx at *; split_ifs at * <;> omega + · unfold nx at *; split_ifs at * <;> omega + · -- next / prev + rcases c23 with ⟨d1, _⟩ | ⟨d1, _, _⟩ | ⟨d1, _, _⟩ <;> (unfold nx at *; split_ifs at * <;> omega) + · rw [b2] at a3; exact I2 hn5 hm₂ a3 + · -- prev / next + rcases c23 with ⟨d1, _⟩ | ⟨d1, _, _⟩ | ⟨d1, _, _⟩ <;> (unfold nx at *; split_ifs at * <;> omega) + · -- prev / prev + rcases c23 with ⟨d1, d2⟩ | ⟨d1, _, _⟩ | ⟨d1, _, _⟩ + · rcases c21 with ⟨f1, _⟩ | ⟨f1, _, f3⟩ | ⟨f1, _, _⟩ + · unfold nx at *; split_ifs at * <;> omega + · rw [d2] at f3; exact I1 hn5 hm₃ hm₂ f3 + · unfold nx at *; split_ifs at * <;> omega + · unfold nx at *; split_ifs at * <;> omega + · unfold nx at *; split_ifs at * <;> omega + +/-! ### Endpoints of the chords -/ + +section endpoints +variable {n : ℕ} (hn : 3 ≤ n) +include hn + +/-- Frame `y`-coordinate of a vertex at an integer relative position. -/ +private lemma fyvi (C i : ℕ) (ρ : ℤ) (h : (i : ℤ) - C = ρ) : fy n C (vertex n i) = Yr n ρ := by + rw [fy_vertex hn, ← h]; push_cast; ring_nf + +omit hn in +/-- The division points with a general index. -/ +private lemma divPt_eq' (k σ μ : ℕ) : + divPt n k σ μ = vertex n σ + + (((μ : ℝ) / ((k : ℝ) + 1) : ℝ) : ℂ) * (vertex n (σ + 1) - vertex n σ) := by + unfold divPt; push_cast; ring + +/-- Distinct division points are distinct points of the plane. -/ +private lemma divPt_inj {k σ σ' μ μ' : ℕ} (hσ : σ < n) (hσ' : σ' < n) (hμ1 : 1 ≤ μ') (hμ2 : μ' ≤ k) + (h : divPt n k σ μ = divPt n k σ' μ') : σ = σ' ∧ μ = μ' := by + have hk : (0 : ℝ) < (k : ℝ) + 1 := by positivity + have hτ0 : 0 < (μ' : ℝ) / ((k : ℝ) + 1) := + div_pos (by exact_mod_cast (show 0 < μ' by omega)) hk + have hτ1 : (μ' : ℝ) / ((k : ℝ) + 1) < 1 := by + rw [div_lt_one hk]; have : (μ' : ℝ) ≤ k := by exact_mod_cast hμ2 + linarith + have hfy : fy n (σ + 1) (divPt n k σ μ) = 0 := by + rw [divPt_eq', fy_aff, fyv hn _ σ (-1) (by push_cast; ring), + fyv hn _ (σ + 1) 0 (by push_cast; ring), Yr_neg_one, Yr_zero] + ring + have hσeq : σ = σ' := by + by_contra hne + obtain ⟨ρ, hρ⟩ : ∃ ρ : ℤ, ρ = (σ' : ℤ) - σ := ⟨_, rfl⟩ + have e : fy n (σ + 1) (divPt n k σ' μ') = + (1 - (μ' : ℝ) / ((k : ℝ) + 1)) * Yr n ((ρ - 1 : ℤ) : ℝ) + + (μ' : ℝ) / ((k : ℝ) + 1) * Yr n (ρ : ℝ) := by + rw [divPt_eq', fy_aff, fyvi hn _ σ' (ρ - 1) (by push_cast; omega), + fyvi hn _ (σ' + 1) ρ (by push_cast; omega)] + ring + have hY0 := (XY_nonneg hn (ρ - 1) (by omega) (by omega)).2 + have hY1 := (XY_nonneg hn ρ (by omega) (by omega)).2 + have hpos : 0 < (1 - (μ' : ℝ) / ((k : ℝ) + 1)) * Yr n ((ρ - 1 : ℤ) : ℝ) + + (μ' : ℝ) / ((k : ℝ) + 1) * Yr n (ρ : ℝ) := by + by_cases hc : ρ = -1 ∨ ρ = n - 1 + · have := Y_pos_range hn (ρ - 1) (by omega) (by omega) (by omega) (by omega) (by omega) + (by omega) (by omega) + nlinarith [mul_pos (sub_pos.mpr hτ1) this, mul_nonneg hτ0.le hY1] + · have := Y_pos_range hn ρ (by omega) (by omega) (by omega) (by omega) (by omega) + (by omega) (by omega) + nlinarith [mul_nonneg (sub_pos.mpr hτ1).le hY0, mul_pos hτ0 this] + rw [← e, ← h, hfy] at hpos + exact lt_irrefl _ hpos + subst hσeq + refine ⟨rfl, ?_⟩ + have hfx : ∀ μ'' : ℕ, fx n (σ + 1) (divPt n k σ μ'') = 1 - (μ'' : ℝ) / ((k : ℝ) + 1) := by + intro μ'' + rw [divPt_eq', fx_aff, fxv hn _ σ (-1) (by push_cast; ring), + fxv hn _ (σ + 1) 0 (by push_cast; ring), Xr_neg_one hn, Xr_zero] + ring + have h1 := congrArg (fx n (σ + 1)) h + rw [hfx, hfx] at h1 + have h2 : (μ : ℝ) / ((k : ℝ) + 1) = (μ' : ℝ) / ((k : ℝ) + 1) := by linarith + rw [div_left_inj' hk.ne'] at h2 + exact_mod_cast h2 + +/-- Division points on side `n` are those on side `0`. -/ +private lemma divPt_succ_nx {k j μ : ℕ} (_hj : j < n) : divPt n k (j + 1) μ = divPt n k (nx n j) μ := by + unfold nx + split_ifs with h + · have h0 : vertex n n = vertex n 0 := by simpa using vertex_add_n n 0 (by omega) + have h1 : vertex n (n + 1) = vertex n (0 + 1) := by + rw [show n + 1 = 1 + n by ring, vertex_add_n n 1 (by omega)] + unfold divPt + rw [h, h0, h1] + · rfl + +end endpoints + +/-! ### The conjecture about non-simple intersections -/ + +/-- For `n = 5` and `n ≥ 7` there is never a point on three of the drawn sides. -/ +private theorem no_nonsimple {n : ℕ} (hn5 : n = 5 ∨ 7 ≤ n) (k : ℕ) : ¬ HasNonSimpleIntersection n k := by + have hn : 3 ≤ n := by omega + rintro ⟨p, c₁, c₂, c₃, h12, h13, h23, hp1, hp2, hp3⟩ + have d : ∀ c c' : Fin n × Fin k, c ≠ c' → ¬ ((c'.1 : ℕ) = c.1 ∧ (c'.2 : ℕ) = c.2) := by + intro c c' hcc' h + exact hcc' (Prod.ext (Fin.ext h.1.symm) (Fin.ext h.2.symm)) + have D12 := d _ _ h12 + have D13 := d _ _ h13 + have D23 := d _ _ h23 + by_cases hpi : p ∈ interior (polygon n) + · rw [mem_chord_iff hn _ hpi] at hp1 hp2 hp3 + exact no_triple hn5 c₁.1.2 c₂.1.2 c₃.1.2 c₁.2.2 c₂.2.2 c₃.2.2 D12 D13 D23 hpi hp1 hp2 hp3 + · have endpt : ∀ c : Fin n × Fin k, p ∈ chord n k c → + p = divPt n k c.1 ((c.2 : ℕ) + 1) ∨ p = divPt n k (nx n c.1) ((c.2 : ℕ) + 1) := by + intro c hc + rw [chord_eq] at hc + obtain ⟨r, ⟨hr0, hr1⟩, rfl⟩ := hc + rcases eq_or_lt_of_le hr0 with rfl | hr0' + · left; simp [gam] + rcases eq_or_lt_of_le hr1 with rfl | hr1' + · right; simp only [gam]; rw [← divPt_succ_nx hn c.1.2]; push_cast; ring + exact absurd (gam_interior hn c.2.2 hr0' hr1') hpi + have key : ∀ (σ σ' : ℕ) (c c' : Fin n × Fin k), σ < n → σ' < n → + divPt n k σ ((c.2 : ℕ) + 1) = divPt n k σ' ((c'.2 : ℕ) + 1) → σ = σ' ∧ (c.2 : ℕ) = c'.2 := by + intro σ σ' c c' hσ hσ' h + obtain ⟨h1, h2⟩ := divPt_inj hn hσ hσ' (by omega) (by have := c'.2.2; omega) h + exact ⟨h1, by omega⟩ + have b1 := c₁.1.2 + have b2 := c₂.1.2 + have b3 := c₃.1.2 + have n1 := nx_lt c₁.1.2 + have n2 := nx_lt c₂.1.2 + have n3 := nx_lt c₃.1.2 + rcases endpt c₁ hp1 with e1 | e1 <;> rcases endpt c₂ hp2 with e2 | e2 <;> + rcases endpt c₃ hp3 with e3 | e3 <;> + · obtain ⟨s12, u12⟩ := key _ _ c₁ c₂ (by assumption) (by assumption) (e1.symm.trans e2) + obtain ⟨s13, u13⟩ := key _ _ c₁ c₃ (by assumption) (by assumption) (e1.symm.trans e3) + clear e1 e2 e3 endpt key d hp1 hp2 hp3 + simp only [nx] at s12 s13 n1 n2 n3 + (try split_ifs at s12 s13) <;> omega + +/-- `W = 0` for the triangle. -/ +private lemma W3 : Xr 3 (-2) = 0 := by + rw [Xr_neg_two (by norm_num)] + have : 2 * ph 3 = Real.pi - Real.pi / 3 := by unfold ph; push_cast; ring + rw [this, Real.cos_pi_sub, Real.cos_pi_div_three]; norm_num + +/-- `W = 1` for the square. -/ +private lemma W4 : Xr 4 (-2) = 1 := by + rw [Xr_neg_two (by norm_num)] + have : 2 * ph 4 = Real.pi / 2 := by unfold ph; push_cast; ring + rw [this, Real.cos_pi_div_two]; norm_num + +/-- `W = 2` for the hexagon. -/ +private lemma W6 : Xr 6 (-2) = 2 := by + rw [Xr_neg_two (by norm_num)] + have : 2 * ph 6 = Real.pi / 3 := by unfold ph; push_cast; ring + rw [this, Real.cos_pi_div_three]; norm_num + +/-- A triple point from chords `(0, m₁)`, `(0, m₂)` and `(1, m₃)`. -/ +private lemma triple_exists {n k m₁ m₂ m₃ : ℕ} (hn : 3 ≤ n) (h1 : m₁ < k) (h2 : m₂ < k) (h3 : m₃ < k) + (hne : m₁ ≠ m₂) + (heq : (1 - tt k m₂) * aP (tt k m₃) (tt k m₁) (Xr n (-2)) + + tt k m₂ * (tt k m₃ * (tt k m₃ - tt k m₁)) = 0) : + HasNonSimpleIntersection n k := by + have hpi : gam n k 0 m₁ (tt k m₂) ∈ interior (polygon n) := + gam_interior hn h1 (tt_pos k m₂) (tt_lt_one h2) + let c₁ : Fin n × Fin k := (⟨0, by omega⟩, ⟨m₁, h1⟩) + let c₂ : Fin n × Fin k := (⟨0, by omega⟩, ⟨m₂, h2⟩) + let c₃ : Fin n × Fin k := (⟨1, by omega⟩, ⟨m₃, h3⟩) + refine ⟨gam n k 0 m₁ (tt k m₂), c₁, c₂, c₃, ?_, ?_, ?_, ?_, ?_, ?_⟩ + · intro h; apply hne; have := congrArg (fun c => (c.2 : ℕ)) h; simpa [c₁, c₂] using this + · intro h; have := congrArg (fun c => (c.1 : ℕ)) h; simp [c₁, c₃] at this + · intro h; have := congrArg (fun c => (c.1 : ℕ)) h; simp [c₂, c₃] at this + · rw [chord_eq]; exact ⟨tt k m₂, ⟨(tt_pos k m₂).le, (tt_lt_one h2).le⟩, rfl⟩ + · rw [mem_chord_iff hn _ hpi]; show Fl n k 0 m₂ (gam n k 0 m₁ (tt k m₂)) = 0 + rw [pair_same hn]; ring + · rw [mem_chord_iff hn _ hpi] + show Fl n k 1 m₃ (gam n k 0 m₁ (tt k m₂)) = 0 + have hnx : nx n 0 = 1 := by unfold nx; split_ifs <;> omega + have := pair_next hn k 0 m₁ m₃ (by omega) (tt k m₂) + rw [hnx] at this + rw [this]; exact heq + +/-- A triple point for the triangle (`k = 5`). -/ +private lemma triple3 : HasNonSimpleIntersection 3 5 := + triple_exists (m₁ := 2) (m₂ := 4) (m₃ := 1) (by norm_num) (by norm_num) (by norm_num) + (by norm_num) (by norm_num) (by rw [W3]; unfold aP tt; norm_num) + +/-- A triple point for the square (`k = 5`). -/ +private lemma triple4 : HasNonSimpleIntersection 4 5 := + triple_exists (m₁ := 3) (m₂ := 4) (m₃ := 2) (by norm_num) (by norm_num) (by norm_num) + (by norm_num) (by norm_num) (by rw [W4]; unfold aP tt; norm_num) + +/-- A triple point for the hexagon (`k = 9`). -/ +private lemma triple6 : HasNonSimpleIntersection 6 9 := + triple_exists (m₁ := 4) (m₂ := 8) (m₃ := 1) (by norm_num) (by norm_num) (by norm_num) + (by norm_num) (by norm_num) (by rw [W6]; unfold aP tt; norm_num) + +/-! ### Counting the regions -/ + +/-- The line functionals, indexed by `i = n m + j`. -/ +private noncomputable def fL (n k i : ℕ) (z : ℂ) : ℝ := Fl n k (i % n) (i / n) z + +/-- The region set is the complement of the `n k` lines in the open polygon. -/ +private lemma regionSet_eq {n : ℕ} (hn : 3 ≤ n) (k : ℕ) : + regionSet n k = cellSet (interior (polygon n)) (fL n k) (n * k) := by + ext z + simp only [regionSet, cellSet, mem_sdiff, mem_iUnion, not_exists, mem_ofPred_eq, fL] + constructor + · rintro ⟨hz, hno⟩ + refine ⟨hz, fun i hi h0 => ?_⟩ + have hj : i % n < n := Nat.mod_lt _ (by omega) + have hm : i / n < k := by + rw [Nat.div_lt_iff_lt_mul (by omega)]; rw [mul_comm] at hi; exact hi + apply hno (⟨i % n, hj⟩, ⟨i / n, hm⟩) + rw [mem_chord_iff hn _ hz] + exact h0 + · rintro ⟨hz, hno⟩ + refine ⟨hz, fun c hc => ?_⟩ + rw [mem_chord_iff hn _ hz] at hc + have hi : n * (c.2 : ℕ) + c.1 < n * k := by + have h1 := c.1.2 + have h2 : n * ((c.2 : ℕ) + 1) ≤ n * k := Nat.mul_le_mul_left _ c.2.2 + rw [Nat.mul_succ] at h2 + omega + apply hno _ hi + rw [Nat.mul_add_mod, Nat.mod_eq_of_lt c.1.2, Nat.mul_add_div (by omega), + Nat.div_eq_of_lt c.1.2, add_zero] + exact hc + +/-- `nx n j ≠ j`. -/ +private lemma nx_ne {n j : ℕ} (hn : 3 ≤ n) (_hj : j < n) : nx n j ≠ j := by + unfold nx; split_ifs <;> omega + +/-- The number of distinct points of the open chord `(j, m)` on earlier lines is `2m`. -/ +private lemma roots_count {n k j m : ℕ} (hn5 : n = 5 ∨ 7 ≤ n) (hj : j < n) (hm : m < k) : + {r : ℝ | 0 < r ∧ r < 1 ∧ ∃ i' < n * m + j, fL n k i' (gam n k j m r) = 0}.ncard = 2 * m := by + have hn : 3 ≤ n := by omega + have hn0 : 0 < n := by omega + have ht0 := tt_pos k m + have ht1 := tt_lt_one hm + let ρP : ℕ → ℝ := fun m' => aP (tt k m') (tt k m) (Xr n (-2)) / + (aP (tt k m') (tt k m) (Xr n (-2)) + tt k m' * (tt k m - tt k m')) + have hρP : ∀ m' < m, 0 < ρP m' ∧ ρP m' < 1 ∧ + Fl n k (nx n j) m' (gam n k j m (ρP m')) = 0 := by + intro m' hm' + have hs0 := tt_pos k m' + have hs1 := tt_lt_one (show m' < k by omega) + have hst := (tt_lt_iff k m' m).mpr hm' + have ha := aP_pos hn hs1 ht0 ht1 hs0 + have hb : 0 < tt k m' * (tt k m - tt k m') := mul_pos hs0 (by linarith) + refine ⟨div_pos ha (by linarith), (div_lt_one (by linarith)).mpr (by linarith), ?_⟩ + rw [pair_next hn k j m m' hj] + simp only [ρP] + field_simp + ring + have hset : {r : ℝ | 0 < r ∧ r < 1 ∧ ∃ i' < n * m + j, fL n k i' (gam n k j m r) = 0} = + (tt k '' Iio m) ∪ (ρP '' Iio m) := by + ext r + simp only [mem_ofPred_eq, mem_union, mem_image, mem_Iio, fL] + constructor + · rintro ⟨hr0, hr1, i', hi', h0⟩ + have hj' : i' % n < n := Nat.mod_lt _ hn0 + have hdm := Nat.div_add_mod i' n + have hm'le : i' / n ≤ m := by + have : i' / n ≤ (n * m + j) / n := Nat.div_le_div_right hi'.le + rwa [Nat.mul_add_div hn0, Nat.div_eq_of_lt hj, add_zero] at this + have hm'k : i' / n < k := by omega + have hne : ¬ (i' % n = j ∧ i' / n = m) := by + rintro ⟨h1, h2⟩ + rw [h1, h2] at hdm + omega + rcases cls hn hj hj' hm hm'k hne hr0 hr1 h0 with ⟨h1, h2⟩ | ⟨h1, h2, h3⟩ | ⟨h1, h2, h3⟩ + · left + refine ⟨i' / n, ?_, h2.symm⟩ + rcases eq_or_lt_of_le hm'le with h | h + · exact absurd ⟨h1, h⟩ hne + · exact h + · right + have hlt := (tt_lt_iff k _ m).mp h2 + refine ⟨i' / n, hlt, ?_⟩ + have hs0 := tt_pos k (i' / n) + have hs1 := tt_lt_one hm'k + have ha := aP_pos hn hs1 ht0 ht1 hs0 + have hb : 0 < tt k (i' / n) * (tt k m - tt k (i' / n)) := mul_pos hs0 (by linarith) + simp only [ρP] + rw [div_eq_iff (by linarith)] + linear_combination h3 + · exfalso + have := (tt_lt_iff k m _).mp h2 + omega + · rintro (⟨m', hm', rfl⟩ | ⟨m', hm', rfl⟩) + · refine ⟨tt_pos k m', tt_lt_one (by omega), n * m' + j, ?_, ?_⟩ + · have h2 : n * (m' + 1) ≤ n * m := Nat.mul_le_mul_left _ hm' + rw [Nat.mul_succ] at h2 + omega + · rw [Nat.mul_add_mod, Nat.mod_eq_of_lt hj, Nat.mul_add_div hn0, Nat.div_eq_of_lt hj, + add_zero, pair_same hn] + ring + · obtain ⟨h0, h1, h2⟩ := hρP m' hm' + refine ⟨h0, h1, n * m' + nx n j, ?_, ?_⟩ + · have := nx_lt hj + have h3 : n * (m' + 1) ≤ n * m := Nat.mul_le_mul_left _ hm' + rw [Nat.mul_succ] at h3 + omega + · rw [Nat.mul_add_mod, Nat.mod_eq_of_lt (nx_lt hj), Nat.mul_add_div hn0, + Nat.div_eq_of_lt (nx_lt hj), add_zero] + exact h2 + have hinj1 : InjOn (tt k) (Iio m) := fun a _ b _ h => (tt_inj k a b).mp h + have hinj2 : InjOn ρP (Iio m) := by + intro a ha b hb hab + by_contra hne + simp only [mem_Iio] at ha hb + obtain ⟨h0, h1, e2⟩ := hρP a ha + obtain ⟨_, _, e3⟩ := hρP b hb + rw [← hab] at e3 + exact no_triple hn5 hj (nx_lt hj) (nx_lt hj) hm (show a < k by omega) (show b < k by omega) + (fun h => nx_ne hn hj h.1) (fun h => nx_ne hn hj h.1) (fun h => hne h.2.symm) + (gam_interior hn hm h0 h1) (Fl_gam hn k j m _) e2 e3 + have hdisj : Disjoint (tt k '' Iio m) (ρP '' Iio m) := by + rw [Set.disjoint_left] + rintro r ⟨a, ha, rfl⟩ ⟨b, hb, hab⟩ + simp only [mem_Iio] at ha hb + obtain ⟨_, _, e3⟩ := hρP b hb + rw [hab] at e3 + have e2 : Fl n k j a (gam n k j m (tt k a)) = 0 := by rw [pair_same hn]; ring + exact no_triple hn5 hj hj (nx_lt hj) hm (show a < k by omega) (show b < k by omega) + (fun h => by omega) (fun h => nx_ne hn hj h.1) (fun h => nx_ne hn hj h.1) + (gam_interior hn hm (tt_pos k a) (tt_lt_one (by omega))) (Fl_gam hn k j m _) e2 e3 + rw [hset, Set.ncard_union_eq hdisj ((Set.finite_Iio m).image _) ((Set.finite_Iio m).image _), + hinj1.ncard_image, hinj2.ncard_image, Set.ncard_Iio_nat] + ring + +/-- `∑_{i < nk} (1 + 2 ⌊i/n⌋) = n k²`. -/ +private lemma sum_formula (n k : ℕ) (hn : 0 < n) : + ∑ i ∈ Finset.range (n * k), (1 + 2 * (i / n)) = n * k ^ 2 := by + induction k with + | zero => simp + | succ k ih => + rw [Nat.mul_succ, Finset.sum_range_add, ih] + have : ∀ x ∈ Finset.range n, 1 + 2 * ((n * k + x) / n) = 1 + 2 * k := by + intro x hx + rw [Nat.mul_add_div hn, Nat.div_eq_of_lt (Finset.mem_range.mp hx), add_zero] + rw [Finset.sum_congr rfl this, Finset.sum_const, Finset.card_range, smul_eq_mul] + ring + +/-- **The region count.** For `n = 5` and `n ≥ 7` the `k` internal `n`-gons cut the `n`-gon +into `n k² + 1` regions. -/ +private theorem regions_formula {n : ℕ} (hn5 : n = 5 ∨ 7 ≤ n) (k : ℕ) : regions n k = n * k ^ 2 + 1 := by + have hn : 3 ≤ n := by omega + have hn0 : 0 < n := by omega + unfold regions + rw [regionSet_eq hn k] + have hU : IsOpen (interior (polygon n)) := isOpen_interior + have hUc : Convex ℝ (interior (polygon n)) := (convex_convexHull ℝ _).interior + have hfa : ∀ i (z w : ℂ) (r : ℝ), fL n k i (z + r * (w - z)) = + fL n k i z + r * (fL n k i w - fL n k i z) := fun i z w r => Fl_aff _ _ _ _ z z w r + have hfc : ∀ i, Continuous (fL n k i) := fun i => Fl_cont _ _ _ _ + rw [count_general hU hUc hfa hfc (interior_nonempty hn) + (fun i => divPt n k (i % n) (i / n + 1)) (fun i => divPt n k (i % n + 1) (i / n + 1)) (n * k)] + · rw [Finset.sum_congr rfl (g := fun i => 1 + 2 * (i / n)), sum_formula n k hn0] + · ring + intro i hi + have hi' := Finset.mem_range.mp hi + have hj : i % n < n := Nat.mod_lt _ hn0 + have hm : i / n < k := by rw [Nat.div_lt_iff_lt_mul hn0]; rw [mul_comm] at hi'; exact hi' + have := roots_count hn5 hj hm + rw [Nat.div_add_mod] at this + rw [← this] + rfl + · intro i hi z hz h0 + have hj : i % n < n := Nat.mod_lt _ hn0 + have hm : i / n < k := by rw [Nat.div_lt_iff_lt_mul hn0]; rw [mul_comm] at hi; exact hi + exact line_inter hn hj hm hz h0 + · intro i hi r hr0 hr1 + have hm : i / n < k := by rw [Nat.div_lt_iff_lt_mul hn0]; rw [mul_comm] at hi; exact hi + exact ⟨gam_interior hn hm hr0 hr1, Fl_gam hn k _ _ r⟩ + · intro i hi + have hm : i / n < k := by rw [Nat.div_lt_iff_lt_mul hn0]; rw [mul_comm] at hi; exact hi + refine ⟨vertex n (i % n + 1), ?_⟩ + show Fl n k (i % n) (i / n) (vertex n (i % n + 1)) ≠ 0 + unfold Fl + rw [fxv hn _ _ 0 (by ring), fyv hn _ _ 0 (by ring), Xr_zero, Yr_zero] + have := tt_pos k (i / n) + have := tt_lt_one hm + nlinarith + · intro i hi i' hi' + have hj : i % n < n := Nat.mod_lt _ hn0 + have hm : i / n < k := by rw [Nat.div_lt_iff_lt_mul hn0]; rw [mul_comm] at hi; exact hi + have hj' : i' % n < n := Nat.mod_lt _ hn0 + have hm' : i' / n < k := by + rw [Nat.div_lt_iff_lt_mul hn0]; rw [mul_comm] at hi; exact lt_trans hi' hi + have hne : ¬ (i' % n = i % n ∧ i' / n = i / n) := by + rintro ⟨h1, h2⟩ + have e1 := Nat.div_add_mod i n + have e2 := Nat.div_add_mod i' n + rw [h1, h2] at e2 + omega + show ∃ r : ℝ, Fl n k (i' % n) (i' / n) (gam n k (i % n) (i / n) r) ≠ 0 + have hs0 := tt_pos k (i' / n) + have hs1 := tt_lt_one hm' + have ht0 := tt_pos k (i / n) + have ht1 := tt_lt_one hm + by_cases h1 : i' % n = i % n + · refine ⟨0, ?_⟩ + rw [h1, pair_same hn] + have : tt k (i / n) ≠ tt k (i' / n) := fun h => hne ⟨h1, ((tt_inj k _ _).mp h).symm⟩ + have : tt k (i / n) - tt k (i' / n) ≠ 0 := sub_ne_zero.mpr this + have : (0 : ℝ) - tt k (i' / n) ≠ 0 := by linarith + exact mul_ne_zero (by assumption) this + by_cases h2 : i' % n = nx n (i % n) + · refine ⟨0, ?_⟩ + rw [h2, pair_next hn k _ _ _ hj] + have := aP_pos hn hs1 ht0 ht1 hs0 + simp only [sub_zero, one_mul, zero_mul, add_zero] + exact this.ne' + by_cases h3 : i % n = nx n (i' % n) + · refine ⟨1, ?_⟩ + rw [h3, pair_prev hn k _ _ _ hj'] + have := bM_pos hn hs1 ht0 ht1 + simp only [sub_self, zero_mul, one_mul, zero_add] + exact this.ne' + · refine ⟨0, ?_⟩ + exact (pair_far hn hj hj' hm' h1 h2 h3 le_rfl zero_le_one hm).ne' + +/-- The conjecture of A357216: non-simple intersections occur exactly for the triangle, the +square and the hexagon, and otherwise there are `n k² + 1` regions. -/ +theorem result : statement := by + refine ⟨fun n hn => ⟨fun ⟨k, hk⟩ => ?_, fun h => ?_⟩, fun n k hn => regions_formula hn k⟩ + · by_contra hc + exact no_nonsimple (show n = 5 ∨ 7 ≤ n by omega) k hk + · rcases h with rfl | rfl | rfl + · exact ⟨5, triple3⟩ + · exact ⟨5, triple4⟩ + · exact ⟨9, triple6⟩ + +end Math0.Frontier.A357216 + +#math0_settles Math0.Frontier.A357216.result Math0.Statements.A357216.statement diff --git a/lean/Math0/Frontier/OEIS/A357583.lean b/lean/Math0/Frontier/OEIS/A357583.lean new file mode 100644 index 0000000..e44c643 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A357583.lean @@ -0,0 +1,144 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A357583 +import Math0.Audit + +/-! +# Kurkov's recursion for the row polynomials of convolution triangles holds + +We prove both parts of Mikhail Kurkov's conjecture: for every integer sequence `s` and every +`n > 0`, the row polynomial `E(n) = ∑_k T_s(n,k) x^k` of the convolution triangle of `s` equals +`x * R(n,1)`, where `R(1,k) = s(k)` and `R(n,k) = R(n-1,k+1) + x R(n-1,1) R(1,k)`; the Bell case +(A357583) is the instance `s = Bell`, after casting the natural-number triangle to `ℤ`. + +**Row-polynomial recursion.** Since `T_s(n,k) = 0` for `k > n` and `T_s(n,0) = [n = 0]`, +the column recursion `T_s(n+1,k+1) = ∑_{j=0}^{n} s(j+1) T_s(n-j,k)` gives +`E(0) = 1` and `E(n+1) = x ∑_{j=0}^{n} s(j+1) E(n-j)` (i.e. `E = 1/(1 - x A(z))`). + +**Closed form.** By induction on `m`, `R(m+1,k) = ∑_{j=0}^{m} s(k+j) E(m-j)`: the step splits off +the `j = 0` term `s(k) E(m+1)`, and `E(m+1) = x R(m+1,1)` by the recursion above and the +induction hypothesis at `k = 1`, while the remaining terms are `R(m+1,k+1)`. + +**Conclusion.** `x R(m+1,1) = x ∑_{j=0}^{m} s(j+1) E(m-j) = E(m+1)`. +-/ + +namespace Math0.Frontier.A357583 +open Math0.Statements.A357583 +open Polynomial + +/-- Entries above the diagonal of a convolution triangle vanish. -/ +private lemma convT_eq_zero (s : ℕ → ℤ) : ∀ k n : ℕ, n < k → convT s n k = 0 + | 0, n, h => absurd h (Nat.not_lt_zero n) + | k + 1, n, h => by + rw [convT] + refine Finset.sum_eq_zero fun p hp => ?_ + rw [Finset.HasAntidiagonal.mem_antidiagonal] at hp + rcases Nat.eq_zero_or_pos p.1 with h1 | h1 + · simp [pad, h1] + · rw [convT_eq_zero s k p.2 (by omega), mul_zero] + +/-- Extending the range of the row polynomial sum by vanishing terms. -/ +private lemma rowPoly_eq_sum (s : ℕ → ℤ) (m : ℕ) : ∀ M : ℕ, m + 1 ≤ M → + ∑ k ∈ Finset.range M, C (convT s m k) * X ^ k = rowPoly s m + | 0, h => absurd h (by omega) + | M + 1, h => by + rcases Nat.eq_or_lt_of_le h with h' | h' + · rw [← h']; rfl + · rw [Finset.sum_range_succ, rowPoly_eq_sum s m M (by omega), + convT_eq_zero s M m (by omega)] + simp + +/-- `rowPoly s 0 = 1`. -/ +private lemma rowPoly_zero (s : ℕ → ℤ) : rowPoly s 0 = 1 := by + simp [rowPoly, convT] + +/-- The column recursion, with the antidiagonal written as a range sum (the term `pad s 0` +vanishes). -/ +private lemma convT_succ_succ (s : ℕ → ℤ) (n k : ℕ) : + convT s (n + 1) (k + 1) = ∑ j ∈ Finset.range (n + 1), s (j + 1) * convT s (n - j) k := by + rw [convT, Finset.Nat.sum_antidiagonal_succ, + Finset.Nat.sum_antidiagonal_eq_sum_range_succ (fun i j => pad s (i + 1) * convT s j k) n] + simp [pad] + +/-- The recursion `E(n+1) = x * ∑_{j=0}^{n} s(j+1) E(n-j)` for the row polynomials. -/ +private lemma rowPoly_succ (s : ℕ → ℤ) (n : ℕ) : + rowPoly s (n + 1) = + X * ∑ j ∈ Finset.range (n + 1), C (s (j + 1)) * rowPoly s (n - j) := by + calc rowPoly s (n + 1) + = ∑ k ∈ Finset.range (n + 1), C (convT s (n + 1) (k + 1)) * X ^ (k + 1) := by + unfold rowPoly + rw [Finset.sum_range_succ'] + simp [convT] + _ = ∑ k ∈ Finset.range (n + 1), ∑ j ∈ Finset.range (n + 1), + X * (C (s (j + 1)) * (C (convT s (n - j) k) * X ^ k)) := by + refine Finset.sum_congr rfl fun k _ => ?_ + rw [convT_succ_succ, map_sum, Finset.sum_mul] + refine Finset.sum_congr rfl fun j _ => ?_ + rw [map_mul] + ring + _ = X * ∑ j ∈ Finset.range (n + 1), + C (s (j + 1)) * ∑ k ∈ Finset.range (n + 1), C (convT s (n - j) k) * X ^ k := by + rw [Finset.sum_comm, Finset.mul_sum] + refine Finset.sum_congr rfl fun j _ => ?_ + rw [Finset.mul_sum, Finset.mul_sum] + _ = X * ∑ j ∈ Finset.range (n + 1), C (s (j + 1)) * rowPoly s (n - j) := by + congr 1 + refine Finset.sum_congr rfl fun j _ => ?_ + rw [rowPoly_eq_sum s (n - j) (n + 1) (by omega)] + +/-- Closed form of Kurkov's polynomials: +`R(m+1, k) = ∑_{j=0}^{m} s(k+j) E(m-j)` with `E` the row polynomials. -/ +private lemma R_closed (s : ℕ → ℤ) : ∀ m k : ℕ, + R s (m + 1) k = ∑ j ∈ Finset.range (m + 1), C (s (k + j)) * rowPoly s (m - j) + | 0, k => by simp [R, rowPoly_zero] + | m + 1, k => by + rw [R, R_closed s m (k + 1), R_closed s m 1, Finset.sum_range_succ' _ (m + 1)] + have hE : X * ∑ j ∈ Finset.range (m + 1), C (s (1 + j)) * rowPoly s (m - j) = + rowPoly s (m + 1) := by + rw [rowPoly_succ] + congr 1 + refine Finset.sum_congr rfl fun j _ => ?_ + rw [Nat.add_comm 1 j] + rw [hE, R] + simp only [Nat.add_zero, Nat.sub_zero] + rw [mul_comm (rowPoly s (m + 1))] + congr 1 + refine Finset.sum_congr rfl fun j _ => ?_ + rw [Nat.add_sub_add_right, show k + 1 + j = k + (j + 1) by omega] + +/-- Part (2) of the conjecture, for every sequence `s`. -/ +private lemma part_two (s : ℕ → ℤ) (n : ℕ) (hn : 0 < n) : rowPoly s n = X * R s n 1 := by + obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩ + rw [R_closed, rowPoly_succ] + congr 1 + refine Finset.sum_congr rfl fun j _ => ?_ + rw [Nat.add_comm 1 j] + +/-- Casting the convolution triangle along a ring homomorphism. -/ +private lemma map_convT {S₁ S₂ : Type*} [CommSemiring S₁] [CommSemiring S₂] (f : S₁ →+* S₂) + (s : ℕ → S₁) : ∀ k n : ℕ, f (convT s n k) = convT (fun j => f (s j)) n k + | 0, n => by + simp only [convT] + split_ifs <;> simp + | k + 1, n => by + simp only [convT, map_sum, map_mul] + refine Finset.sum_congr rfl fun p _ => ?_ + rw [map_convT f s k p.2] + congr 1 + unfold pad + split_ifs <;> simp + +/-- Kurkov's conjecture holds: the row polynomials of every integer convolution triangle, and in +particular of A357583, are `x * R(n, 1)`. -/ +theorem result : statement := by + refine ⟨fun n hn => ?_, part_two⟩ + rw [← part_two bellZ n hn] + unfold rowPoly + refine Finset.sum_congr rfl fun k _ => ?_ + congr 2 + exact map_convT (Nat.castRingHom ℤ) Nat.bell k n + +end Math0.Frontier.A357583 + +#math0_settles Math0.Frontier.A357583.result Math0.Statements.A357583.statement diff --git a/lean/Math0/Frontier/OEIS/A362086.lean b/lean/Math0/Frontier/OEIS/A362086.lean new file mode 100644 index 0000000..2518234 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A362086.lean @@ -0,0 +1,374 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A362086 +import Math0.Audit + +/-! +# OEIS A362086: every denominator except 9 is 1 or a prime + +We prove Bouras' conjecture: for every `n ≥ 3`, the denominator `a n` of +`1/(2-3/(3-4/(…(n-1)-n/(-3))))` is `1` or a prime, unless it equals `9` (which happens at `n = 5`). + +*Closed form.* The convergents of the continued fraction have numerators `k+1` and denominators +`(k+1)·!k/2`, where `!k = 0! + ⋯ + (k-1)!` is the left factorial. Feeding in `-3` gives, with +`x = n-3` and `N = n^2+n-3 = x^2+7x+9`, +`cf n = (N·!x + 3(x+2)·x!) / (2N)`. Every intermediate tail is positive (each tail `t_k` with +`k ≤ n-1` is at least `k-2`), so Lean's `x/0 = 0` convention never intervenes. Since `N` is odd +and `N·!x + 3(x+2)·x!` is even, `a n = N / gcd(N, M)` with `M = 3(x+2)·x!`. + +*Number theory* (for `x ≥ 33`). Let `d = N / gcd(N, M)` and let `p` be its least prime factor +(odd, as `N` is odd). If `p ∣ d` then `p^(j+1) ∣ N` whenever `p^j ∣ M`. Note +`(x+3)^2 < N < (x+4)^2`. +* `2p ≤ x`: then `p^(x/p) ∣ x! ∣ M`, so `p^(x/p+1) ≤ N < (x+4)^2 ≤ (p(x/p+1)+4)^2 < p^(x/p+1)`, + which is impossible. +* `x < 2p ≤ 2x`: then `p ∣ M`, so `N = m p^2` with `m < 5`; parity and `(x+3)^2 < N < (x+4)^2` + force `N = 3p^2`, and then `3p ∣ gcd(N, M)`, so `d ∣ p`. +* `p > x`: `N` is not divisible by `x+1, x+2, x+3` (as `N = (x+1)(x+6)+3 = (x+2)(x+5)-1 = + (x+3)(x+4)-3`), so every prime factor of `d` is at least `x+4`; two of them would give + `d ≥ (x+4)^2 > N`, so `d = p`. +The cases `n < 36` are read off from the kernel-checked data `a_data`. +-/ + +namespace Math0.Frontier.A362086 +open Math0.Statements.A362086 + +/-- Left factorial `!m = 0! + 1! + ⋯ + (m-1)!`. -/ +private def lf (m : ℕ) : ℕ := ∑ i ∈ Finset.range m, i.factorial + +/-- Recursion for the left factorial: `!(m+1) = !m + m!`. -/ +private lemma lf_succ (m : ℕ) : lf (m+1) = lf m + m.factorial := by + simp [lf, Finset.sum_range_succ] + +/-- Peeling off the innermost level of the continued fraction: the fold over +`[2, …, m+2]` starting from `t` is the fold over `[2, …, m+1]` starting from `step (m+2) t`. -/ +private lemma fold_concat (m : ℕ) (t : ℚ) : + (List.range' 2 (m+1)).foldr step t = (List.range' 2 m).foldr step (step (m+2) t) := by + rw [List.range'_concat, List.foldr_append] + simp [add_comm] + +/-- The value of `step 2 (step 3 (… (step (m+2) t)))` predicted by the convergents of the +continued fraction: numerators `k+1` and denominators `(k+1)·!k/2`. -/ +private def F (m : ℕ) (t : ℚ) : ℚ := + 2 * ((m+2) * t - (m+3) * (m+1)) / ((m+2) * (lf (m+1) : ℚ) * t - (m+3) * (m+1) * (lf m : ℚ)) + +/-- One more level of the continued fraction moves the convergent formula from `m` to `m+1` +(valid for every nonzero innermost value `t`). -/ +private lemma F_step (m : ℕ) (t : ℚ) (ht : t ≠ 0) : F m (step (m+3) t) = F (m+1) t := by + have h1 : (lf (m+1) : ℚ) = lf m + m.factorial := by rw [lf_succ]; push_cast; ring + have h2 : (lf (m+1+1) : ℚ) = lf m + m.factorial + (m+1) * m.factorial := by + rw [lf_succ, lf_succ, Nat.factorial_succ]; push_cast; ring + calc F m (step (m+3) t) + = (2 * ((m+3) * t - (m+4) * (m+2)) / t) / + (((m+3) * (lf m + m.factorial + (m+1) * m.factorial) * t + - (m+4) * (m+2) * (lf m + m.factorial)) / t) := by + simp only [F, step, h1] + push_cast + congr 1 + · field_simp; ring + · field_simp; ring + _ = (2 * ((m+3) * t - (m+4) * (m+2))) / + ((m+3) * (lf m + m.factorial + (m+1) * m.factorial) * t + - (m+4) * (m+2) * (lf m + m.factorial)) := div_div_div_cancel_right₀ ht _ _ + _ = F (m+1) t := by + simp only [F, h1, h2] + push_cast + ring_nf + +/-- The fold equals the convergent formula as long as the innermost value is large enough; +this keeps every intermediate tail positive, so no division by zero ever occurs. -/ +private lemma fold_eq_F (m : ℕ) : ∀ t : ℚ, (m + 1 : ℚ) ≤ t → + (List.range' 2 (m+1)).foldr step t = F m t := by + induction m with + | zero => + intro t ht + have ht0 : t ≠ 0 := by intro h; rw [h] at ht; norm_num at ht + simp [F, step, lf] + field_simp + ring + | succ m ih => + intro t ht + push_cast at ht + have htpos : 0 < t := by linarith + rw [fold_concat] + have hs : ((m + 1 : ℕ) : ℚ) + 0 ≤ step (m+3) t := by + unfold step; push_cast + have : ((m:ℚ)+3+1)/t ≤ 2 := by rw [div_le_iff₀ htpos]; linarith + linarith + rw [show m + 1 + 2 = m + 3 from rfl, ih _ (by simpa using hs)] + exact F_step m t htpos.ne' + +/-- Closed form: with `x = y+1`, `N = x^2+7x+9` (that is `n^2+n-3` for `n = x+3`), +`cf (x+3) = (N·!x + 3(x+2)·x!) / (2N)`. -/ +private lemma cf_closed (y : ℕ) : + cf (y+4) = (((y+1)^2+7*(y+1)+9) * lf (y+1) + 3*(y+3)*(y+1).factorial : ℕ) / + (2*((y+1)^2+7*(y+1)+9) : ℕ) := by + have hs : ((y + 1 : ℕ) : ℚ) ≤ step (y+3) (-3) := by + unfold step; push_cast + have : ((y:ℚ)+3+1)/(-3) = -(((y:ℚ)+4)/3) := by ring + rw [this] + have : (0:ℚ) ≤ ((y:ℚ)+4)/3 := by positivity + linarith + have hfold : (List.range' 2 (y+4-2)).foldr step (-3) = F (y+1) (-3) := by + rw [show y+4-2 = (y+1)+1 by omega, fold_concat, show y+1+2 = y+3 from rfl, + fold_eq_F y _ (by simpa using hs), F_step y (-3) (by norm_num)] + unfold cf + rw [hfold] + unfold F + rw [one_div_div] + have hN : (0:ℚ) < (y:ℚ)^2 + 9*y + 17 := by positivity + rw [div_eq_div_iff] + · rw [lf_succ (y+1), lf_succ y, Nat.factorial_succ] + push_cast + ring + · push_cast; nlinarith + · push_cast; nlinarith + +/-- `!x = 0! + 1! + ⋯ + (x-1)!` is even for `x ≥ 2`. -/ +private lemma two_dvd_lf (x : ℕ) (hx : 2 ≤ x) : 2 ∣ lf x := by + induction x, hx using Nat.le_induction with + | base => decide + | succ x hx ih => + rw [lf_succ] + exact dvd_add ih (Nat.dvd_factorial (by norm_num) hx) + +/-- `N = x^2+7x+9` is odd. -/ +private lemma N_odd (x : ℕ) : ¬ 2 ∣ x^2 + 7*x + 9 := by + intro h + rcases Nat.mod_two_eq_zero_or_one x with h0 | h0 <;> + simp [Nat.dvd_iff_mod_eq_zero, Nat.add_mod, Nat.mul_mod, Nat.pow_mod, h0] at h + +/-- The sequence in closed form: `a (x+3) = N / gcd(N, 3(x+2)·x!)` with `N = x^2+7x+9`. -/ +private lemma a_eq (x : ℕ) (hx : 3 ≤ x) : + a (x+3) = (x^2+7*x+9) / Nat.gcd (x^2+7*x+9) (3*(x+2)*x.factorial) := by + obtain ⟨y, rfl⟩ : ∃ y, x = y + 1 := ⟨x - 1, by omega⟩ + set N := (y+1)^2+7*(y+1)+9 with hN + set M := 3*((y+1)+2)*(y+1).factorial with hM + have hW : 2 ∣ N * lf (y+1) + M := by + refine dvd_add (dvd_mul_of_dvd_right (two_dvd_lf _ (by omega)) _) ?_ + exact dvd_mul_of_dvd_right (Nat.dvd_factorial (by norm_num) (by omega)) _ + obtain ⟨X, hX⟩ := hW + have hcf : cf (y+1+3) = (X : ℚ) / (N : ℚ) := by + rw [show y+1+3 = y+4 from rfl, cf_closed y] + have : N * lf (y+1) + 3*(y+3)*(y+1).factorial = 2 * X := by rw [← hX] + rw [this, show (2*((y+1)^2+7*(y+1)+9) : ℕ) = 2 * N from rfl] + push_cast + have hN0 : (N:ℚ) ≠ 0 := by positivity + field_simp + have hden : a (y+1+3) = N / Nat.gcd N X := by + unfold a + rw [hcf, show (X : ℚ) / (N : ℚ) = ((X : ℤ) : ℚ) / ((N : ℤ) : ℚ) by push_cast; rfl, + ← Rat.divInt_eq_div, Rat.den_divInt] + have hN0 : (N : ℤ) ≠ 0 := by positivity + rw [if_neg hN0] + simp [Int.gcd] + rw [hden] + congr 1 + have hcop : Nat.Coprime 2 N := (Nat.Prime.coprime_iff_not_dvd Nat.prime_two).mpr (N_odd _) + rw [← Nat.gcd_add_mul_right_right N M (lf (y+1)), show M + lf (y+1) * N = 2 * X by rw [← hX]; ring, + Nat.gcd_comm N (2 * X), Nat.Coprime.gcd_mul_left_cancel X hcop, Nat.gcd_comm] + +/-- `q^k ∣ (qk)!`, since `q, 2q, …, kq` all occur in the product. -/ +private lemma pow_dvd_fact (q k : ℕ) (hq : 0 < q) : q^k ∣ (q*k).factorial := by + induction k with + | zero => simp + | succ k ih => + have h : q * (k+1) = (q*k + (q-1)) + 1 := by rw [Nat.mul_succ]; omega + rw [h, Nat.factorial_succ, pow_succ, mul_comm (q^k)] + apply mul_dvd_mul + · rw [← h]; exact Dvd.intro (k+1) rfl + · exact ih.trans (Nat.factorial_dvd_factorial (by omega)) + +/-- If `q` divides `N / gcd(N, M)`, then `q^(j+1) ∣ N` whenever `q^j ∣ M`. -/ +private lemma pow_step {N M q : ℕ} (hq : q ∣ N / Nat.gcd N M) : + ∀ j, q^j ∣ M → q^(j+1) ∣ N := by + have hg : Nat.gcd N M ∣ N := Nat.gcd_dvd_left N M + have hNe : N = Nat.gcd N M * (N / Nat.gcd N M) := (Nat.mul_div_cancel' hg).symm + intro j + induction j with + | zero => intro _; simpa using hq.trans (Nat.div_dvd_of_dvd hg) + | succ j ih => + intro hj + have h1 : q^j ∣ M := (pow_dvd_pow q (Nat.le_succ j)).trans hj + have h2 : q^(j+1) ∣ Nat.gcd N M := Nat.dvd_gcd (ih h1) hj + rw [hNe, pow_succ] + exact mul_dvd_mul h2 hq + +/-- `(qj+4)^2 < q^j` for `q ≥ 3`, `j ≥ 6`. -/ +private lemma bound6 (q : ℕ) (hq : 3 ≤ q) : ∀ j, 6 ≤ j → (q*j+4)^2 < q^j := by + intro j hj + induction j, hj using Nat.le_induction with + | base => + have h1 : q^6 = q^4 * q^2 := by ring + have h2 : 81 ≤ q^4 := by + calc 81 = 3^4 := by norm_num + _ ≤ q^4 := Nat.pow_le_pow_left hq 4 + rw [h1]; nlinarith + | succ j hj ih => + rw [pow_succ] + have h3 : (q*(j+1)+4)^2 ≤ 3*(q*j+4)^2 := by nlinarith + calc (q*(j+1)+4)^2 ≤ 3*(q*j+4)^2 := h3 + _ < 3 * q^j := by omega + _ ≤ q^j * q := by rw [mul_comm]; exact Nat.mul_le_mul_left _ hq + +/-- `(qj+4)^2 < q^j` for `q, j ≥ 3` and `qj ≥ 34`. -/ +private lemma bound (q j : ℕ) (hq : 3 ≤ q) (hj : 3 ≤ j) (hqj : 34 ≤ q*j) : + (q*j+4)^2 < q^j := by + rcases (show j = 3 ∨ j = 4 ∨ j = 5 ∨ 6 ≤ j by omega) with rfl | rfl | rfl | h6 + · have : 12 ≤ q := by omega + nlinarith + · have : 9 ≤ q := by omega + have h1 : q^4 = q^2 * q^2 := by ring + have h2 : 81 ≤ q^2 := by nlinarith + rw [h1]; nlinarith + · have : 7 ≤ q := by omega + have h1 : q^5 = q^3 * q^2 := by ring + have h2 : 343 ≤ q^3 := by + calc 343 = 7^3 := by norm_num + _ ≤ q^3 := Nat.pow_le_pow_left this 3 + rw [h1]; nlinarith + · exact bound6 q hq j h6 + +/-- `x + k` divides `N + c` for small shifts, so it cannot divide `N` when `x` is large. -/ +private lemma not_dvd_aux (x k c : ℕ) (hk : x + k ∣ x^2 + 7*x + 9 + c) (hc : c < x + k) + (hc' : 0 < c) : ¬ x + k ∣ x^2 + 7*x + 9 := by + intro h + have := (Nat.dvd_add_right h).mp hk + have := Nat.le_of_dvd hc' this + omega + +/-- The number-theoretic core: for `x ≥ 33`, `N / gcd(N, 3(x+2)·x!)` is `1` or a prime, +where `N = x^2+7x+9`. -/ +private lemma main (x : ℕ) (hx : 33 ≤ x) : + (x^2+7*x+9) / Nat.gcd (x^2+7*x+9) (3*(x+2)*x.factorial) = 1 ∨ + ((x^2+7*x+9) / Nat.gcd (x^2+7*x+9) (3*(x+2)*x.factorial)).Prime := by + set N := x^2+7*x+9 with hN + set M := 3*(x+2)*x.factorial with hM + set g := Nat.gcd N M with hg + set d := N / g with hd + have hNpos : 0 < N := by positivity + have hgN : g ∣ N := Nat.gcd_dvd_left N M + have hdN : d ∣ N := Nat.div_dvd_of_dvd hgN + have hNgd : N = g * d := (Nat.mul_div_cancel' hgN).symm + have hodd : ¬ 2 ∣ N := N_odd x + have hfM : x.factorial ∣ M := Dvd.intro_left _ rfl + have hN4 : N < (x+4)^2 := by rw [hN]; nlinarith + by_cases hd1 : d = 1 + · left; exact hd1 + have hpp : d.minFac.Prime := Nat.minFac_prime hd1 + set p := d.minFac with hp + have hpd : p ∣ d := Nat.minFac_dvd d + have hpN : p ∣ N := hpd.trans hdN + have hp3 : 3 ≤ p := by + have := hpp.two_le + rcases (show p = 2 ∨ 3 ≤ p by omega) with h | h + · rw [h] at hpN; exact absurd hpN hodd + · exact h + by_cases hpx : p ≤ x + · by_cases h2p : 2*p ≤ x + · exfalso + have hk2 : 2 ≤ x / p := (Nat.le_div_iff_mul_le hpp.pos).mpr (by linarith) + have hdvdM : p^(x/p) ∣ M := + (pow_dvd_fact p (x/p) hpp.pos).trans + ((Nat.factorial_dvd_factorial (Nat.mul_div_le x p)).trans hfM) + have h1 := pow_step hpd (x/p) hdvdM + have h2 : p^(x/p+1) ≤ N := Nat.le_of_dvd hNpos h1 + have h3 : x < p*(x/p+1) := Nat.lt_mul_div_succ x hpp.pos + have h4 := bound p (x/p+1) hp3 (by omega) (by omega) + have h6 : (x+4)^2 ≤ (p*(x/p+1)+4)^2 := Nat.pow_le_pow_left (by omega) 2 + omega + · push Not at h2p + have hpM : p ∣ M := (Nat.dvd_factorial hpp.pos hpx).trans hfM + have hp2 : p^2 ∣ N := pow_step hpd 1 (by simpa using hpM) + obtain ⟨m, hm⟩ := hp2 + have hm5 : m < 5 := by + by_contra hcon + push Not at hcon + have h1 : (x+1)^2 ≤ (2*p)^2 := Nat.pow_le_pow_left (by omega) 2 + have h2 : 5 * p^2 ≤ p^2 * m := by rw [mul_comm]; exact Nat.mul_le_mul_left _ hcon + nlinarith + interval_cases m + · omega + · exfalso + rw [mul_one] at hm + have h1 : x + 3 < p := by + by_contra hc; push Not at hc + have : p^2 ≤ (x+3)^2 := Nat.pow_le_pow_left hc 2 + nlinarith + have h2 : p < x + 4 := by + by_contra hc; push Not at hc + have : (x+4)^2 ≤ p^2 := Nat.pow_le_pow_left hc 2 + omega + omega + · exfalso; exact hodd ⟨p^2, by rw [hm]; ring⟩ + · have hp_ne3 : p ≠ 3 := by omega + have h3M : 3 ∣ M := ⟨(x+2)*x.factorial, by rw [hM]; ring⟩ + have hcop : Nat.Coprime 3 p := (Nat.coprime_primes Nat.prime_three hpp).mpr (Ne.symm hp_ne3) + have h3pM : 3*p ∣ M := hcop.mul_dvd_of_dvd_of_dvd h3M hpM + have h3pN : 3*p ∣ N := ⟨p, by rw [hm]; ring⟩ + have h3pg : 3*p ∣ g := Nat.dvd_gcd h3pN h3pM + obtain ⟨h, hh⟩ := h3pg + have hpe : p = h * d := by + have : 3*p*p = 3*p*(h*d) := by rw [← mul_assoc, ← hh, ← hNgd, hm]; ring + exact Nat.eq_of_mul_eq_mul_left (by positivity) this + rcases hpp.eq_one_or_self_of_dvd d ⟨h, by rw [hpe, mul_comm]⟩ with h' | h' + · left; exact h' + · right; rw [h']; exact hpp + · exfalso; exact hodd ⟨2*p^2, by rw [hm]; ring⟩ + · push Not at hpx + have h1 : ¬ x + 1 ∣ N := by + intro h + have h' : x + 1 ∣ (x+1)*(x+6) + 3 := by + rw [show (x+1)*(x+6) + 3 = N by rw [hN]; ring]; exact h + have := Nat.le_of_dvd (by norm_num) ((Nat.dvd_add_right (dvd_mul_right _ _)).mp h') + omega + have h2 : ¬ x + 2 ∣ N := not_dvd_aux x 2 1 ⟨x+5, by ring⟩ (by omega) (by norm_num) + have h3 : ¬ x + 3 ∣ N := not_dvd_aux x 3 3 ⟨x+4, by ring⟩ (by omega) (by norm_num) + have hB : ∀ q, q ∣ N → x < q → x + 4 ≤ q := by + intro q hq hxq + by_contra hcon + push Not at hcon + rcases (show q = x+1 ∨ q = x+2 ∨ q = x+3 by omega) with rfl | rfl | rfl + · exact h1 hq + · exact h2 hq + · exact h3 hq + have hp4 : x + 4 ≤ p := hB p hpN hpx + by_cases hdp : d = p + · right; rw [hdp]; exact hpp + exfalso + have hdr : d = p * (d / p) := (Nat.mul_div_cancel' hpd).symm + have hr1 : d / p ≠ 1 := by intro h; apply hdp; rw [hdr, h, mul_one] + have hr0 : d / p ≠ 0 := by + intro h; rw [h, mul_zero] at hdr; rw [hdr] at hNgd; omega + have hrp : (d / p).minFac.Prime := Nat.minFac_prime hr1 + have hrd : (d / p).minFac ∣ d := (Nat.minFac_dvd _).trans (Dvd.intro_left p hdr.symm) + have hpr : p ≤ (d / p).minFac := Nat.minFac_le_of_dvd hrp.two_le hrd + have hr4 : x + 4 ≤ d / p := le_trans hp4 (hpr.trans (Nat.minFac_le (Nat.pos_of_ne_zero hr0))) + have hdle : d ≤ N := Nat.le_of_dvd hNpos hdN + have : (x+4)^2 ≤ d := by rw [hdr, sq]; exact Nat.mul_le_mul hp4 hr4 + omega + +/-- The cases `3 ≤ n < 60`, read off from the 57 kernel-checked terms `a_data`. -/ +private lemma small (n : ℕ) (hn : 3 ≤ n) (hn' : n < 60) (h9 : a n ≠ 9) : + a n = 1 ∨ (a n).Prime := by + have key : ∀ v ∈ (List.range 57).map (fun i => a (i + 3)), v ≠ 9 → v = 1 ∨ v.Prime := by + rw [a_data] + simp only [List.forall_mem_cons, List.not_mem_nil, IsEmpty.forall_iff, implies_true, and_true] + norm_num + refine key (a n) (List.mem_map.mpr ⟨n - 3, List.mem_range.mpr (by omega), ?_⟩) h9 + show a (n - 3 + 3) = a n + congr 1 + omega + +/-- Bouras' conjecture for A362086: except for `9`, every term `a n` (`n ≥ 3`) is `1` or a prime. -/ +theorem result : statement := by + intro n hn h9 + by_cases hsmall : n < 36 + · exact small n hn (by omega) h9 + · obtain ⟨x, rfl⟩ : ∃ x, n = x + 3 := ⟨n - 3, by omega⟩ + rw [a_eq x (by omega)] + exact main x (by omega) + +end Math0.Frontier.A362086 + +#math0_settles Math0.Frontier.A362086.result Math0.Statements.A362086.statement diff --git a/lean/Math0/Frontier/OEIS/A363482.lean b/lean/Math0/Frontier/OEIS/A363482.lean new file mode 100644 index 0000000..0e347bc --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A363482.lean @@ -0,0 +1,374 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A363482 +import Math0.Audit + +/-! +# OEIS A363482: every denominator except 49 is 1 or a prime + +We prove Bouras' conjecture: for every `n ≥ 3`, the denominator `a n` of +`1/(2-3/(3-4/(…(n-1)-n/(-5))))` is `1` or a prime, unless it equals `49` (which happens at `n = 6`). + +*Closed form.* The convergents of the continued fraction have numerators `k+1` and denominators +`(k+1)·!k/2`, where `!k = 0! + ⋯ + (k-1)!` is the left factorial. Feeding in `-5` gives, with +`x = n-3` and `N = n^2+3n-5 = x^2+9x+13`, +`cf n = (N·!x + 5(x+2)·x!) / (2N)`. Every intermediate tail is positive (each tail `t_k` with +`k ≤ n-1` is at least `k-2`), so Lean's `x/0 = 0` convention never intervenes. Since `N` is odd +and `N·!x + 5(x+2)·x!` is even, `a n = N / gcd(N, M)` with `M = 5(x+2)·x!`. + +*Number theory* (for `x ≥ 33`). Let `d = N / gcd(N, M)` and let `p` be its least prime factor. +If `p ∣ d` then `p^(j+1) ∣ N` whenever `p^j ∣ M`. +* `2p ≤ x`: then `p^(x/p) ∣ x! ∣ M`, so `p^(x/p+1) ≤ N < (x+5)^2 ≤ (p(x/p+1)+4)^2 < p^(x/p+1)`, + which is impossible. +* `x < 2p ≤ 2x`: then `p ∣ M`, so `N = m p^2` with `m < 5`; parity and `(x+4)^2 < N < (x+5)^2` + force `N = 3p^2`, and then `3p ∣ gcd(N, M)`, so `d ∣ p`. +* `p > x`: `N` is not divisible by `x+1, …, x+4`, so every prime factor of `d` is at least `x+5`; + two of them would give `d ≥ (x+5)^2 > N`, so `d = p`. +The cases `n < 36` are read off from the kernel-checked data `a_data`. +-/ + +namespace Math0.Frontier.A363482 +open Math0.Statements.A363482 + +/-- Left factorial `!m = 0! + 1! + ⋯ + (m-1)!`. -/ +private def lf (m : ℕ) : ℕ := ∑ i ∈ Finset.range m, i.factorial + +/-- Recursion for the left factorial: `!(m+1) = !m + m!`. -/ +private lemma lf_succ (m : ℕ) : lf (m+1) = lf m + m.factorial := by + simp [lf, Finset.sum_range_succ] + +/-- Peeling off the innermost level of the continued fraction: the fold over +`[2, …, m+2]` starting from `t` is the fold over `[2, …, m+1]` starting from `step (m+2) t`. -/ +private lemma fold_concat (m : ℕ) (t : ℚ) : + (List.range' 2 (m+1)).foldr step t = (List.range' 2 m).foldr step (step (m+2) t) := by + rw [List.range'_concat, List.foldr_append] + simp [add_comm] + +/-- The value of `step 2 (step 3 (… (step (m+2) t)))` predicted by the convergents of the +continued fraction: numerators `k+1` and denominators `(k+1)·!k/2`. -/ +private def F (m : ℕ) (t : ℚ) : ℚ := + 2 * ((m+2) * t - (m+3) * (m+1)) / ((m+2) * (lf (m+1) : ℚ) * t - (m+3) * (m+1) * (lf m : ℚ)) + +/-- One more level of the continued fraction moves the convergent formula from `m` to `m+1` +(valid for every nonzero innermost value `t`). -/ +private lemma F_step (m : ℕ) (t : ℚ) (ht : t ≠ 0) : F m (step (m+3) t) = F (m+1) t := by + have h1 : (lf (m+1) : ℚ) = lf m + m.factorial := by rw [lf_succ]; push_cast; ring + have h2 : (lf (m+1+1) : ℚ) = lf m + m.factorial + (m+1) * m.factorial := by + rw [lf_succ, lf_succ, Nat.factorial_succ]; push_cast; ring + calc F m (step (m+3) t) + = (2 * ((m+3) * t - (m+4) * (m+2)) / t) / + (((m+3) * (lf m + m.factorial + (m+1) * m.factorial) * t + - (m+4) * (m+2) * (lf m + m.factorial)) / t) := by + simp only [F, step, h1] + push_cast + congr 1 + · field_simp; ring + · field_simp; ring + _ = (2 * ((m+3) * t - (m+4) * (m+2))) / + ((m+3) * (lf m + m.factorial + (m+1) * m.factorial) * t + - (m+4) * (m+2) * (lf m + m.factorial)) := div_div_div_cancel_right₀ ht _ _ + _ = F (m+1) t := by + simp only [F, h1, h2] + push_cast + ring_nf + +/-- The fold equals the convergent formula as long as the innermost value is large enough; +this keeps every intermediate tail positive, so no division by zero ever occurs. -/ +private lemma fold_eq_F (m : ℕ) : ∀ t : ℚ, (m + 1 : ℚ) ≤ t → + (List.range' 2 (m+1)).foldr step t = F m t := by + induction m with + | zero => + intro t ht + have ht0 : t ≠ 0 := by intro h; rw [h] at ht; norm_num at ht + simp [F, step, lf] + field_simp + ring + | succ m ih => + intro t ht + push_cast at ht + have htpos : 0 < t := by linarith + rw [fold_concat] + have hs : ((m + 1 : ℕ) : ℚ) + 0 ≤ step (m+3) t := by + unfold step; push_cast + have : ((m:ℚ)+3+1)/t ≤ 2 := by rw [div_le_iff₀ htpos]; linarith + linarith + rw [show m + 1 + 2 = m + 3 from rfl, ih _ (by simpa using hs)] + exact F_step m t htpos.ne' + +/-- Closed form: with `x = y+1`, `N = x^2+9x+13` (that is `n^2+3n-5` for `n = x+3`), +`cf (x+3) = (N·!x + 5(x+2)·x!) / (2N)`. -/ +private lemma cf_closed (y : ℕ) : + cf (y+4) = (((y+1)^2+9*(y+1)+13) * lf (y+1) + 5*(y+3)*(y+1).factorial : ℕ) / + (2*((y+1)^2+9*(y+1)+13) : ℕ) := by + have hs : ((y + 1 : ℕ) : ℚ) ≤ step (y+3) (-5) := by + unfold step; push_cast + have : ((y:ℚ)+3+1)/(-5) = -(((y:ℚ)+4)/5) := by ring + rw [this] + have : (0:ℚ) ≤ ((y:ℚ)+4)/5 := by positivity + linarith + have hfold : (List.range' 2 (y+4-2)).foldr step (-5) = F (y+1) (-5) := by + rw [show y+4-2 = (y+1)+1 by omega, fold_concat, show y+1+2 = y+3 from rfl, + fold_eq_F y _ (by simpa using hs), F_step y (-5) (by norm_num)] + unfold cf + rw [hfold] + unfold F + rw [one_div_div] + have hN : (0:ℚ) < (y:ℚ)^2 + 11*y + 23 := by positivity + rw [div_eq_div_iff] + · rw [lf_succ (y+1), lf_succ y, Nat.factorial_succ] + push_cast + ring + · push_cast; nlinarith + · push_cast; nlinarith + +/-- `!x = 0! + 1! + ⋯ + (x-1)!` is even for `x ≥ 2`. -/ +private lemma two_dvd_lf (x : ℕ) (hx : 2 ≤ x) : 2 ∣ lf x := by + induction x, hx using Nat.le_induction with + | base => decide + | succ x hx ih => + rw [lf_succ] + exact dvd_add ih (Nat.dvd_factorial (by norm_num) hx) + +/-- `N = x^2+9x+13` is odd. -/ +private lemma N_odd (x : ℕ) : ¬ 2 ∣ x^2 + 9*x + 13 := by + intro h + rcases Nat.mod_two_eq_zero_or_one x with h0 | h0 <;> + simp [Nat.dvd_iff_mod_eq_zero, Nat.add_mod, Nat.mul_mod, Nat.pow_mod, h0] at h + +/-- The sequence in closed form: `a (x+3) = N / gcd(N, 5(x+2)·x!)` with `N = x^2+9x+13`. -/ +private lemma a_eq (x : ℕ) (hx : 3 ≤ x) : + a (x+3) = (x^2+9*x+13) / Nat.gcd (x^2+9*x+13) (5*(x+2)*x.factorial) := by + obtain ⟨y, rfl⟩ : ∃ y, x = y + 1 := ⟨x - 1, by omega⟩ + set N := (y+1)^2+9*(y+1)+13 with hN + set M := 5*((y+1)+2)*(y+1).factorial with hM + have hW : 2 ∣ N * lf (y+1) + M := by + refine dvd_add (dvd_mul_of_dvd_right (two_dvd_lf _ (by omega)) _) ?_ + exact dvd_mul_of_dvd_right (Nat.dvd_factorial (by norm_num) (by omega)) _ + obtain ⟨X, hX⟩ := hW + have hcf : cf (y+1+3) = (X : ℚ) / (N : ℚ) := by + rw [show y+1+3 = y+4 from rfl, cf_closed y] + have : N * lf (y+1) + 5*(y+3)*(y+1).factorial = 2 * X := by rw [← hX] + rw [this, show (2*((y+1)^2+9*(y+1)+13) : ℕ) = 2 * N from rfl] + push_cast + have hN0 : (N:ℚ) ≠ 0 := by positivity + field_simp + have hden : a (y+1+3) = N / Nat.gcd N X := by + unfold a + rw [hcf, show (X : ℚ) / (N : ℚ) = ((X : ℤ) : ℚ) / ((N : ℤ) : ℚ) by push_cast; rfl, + ← Rat.divInt_eq_div, Rat.den_divInt] + have hN0 : (N : ℤ) ≠ 0 := by positivity + rw [if_neg hN0] + simp [Int.gcd] + rw [hden] + congr 1 + have hcop : Nat.Coprime 2 N := (Nat.Prime.coprime_iff_not_dvd Nat.prime_two).mpr (N_odd _) + rw [← Nat.gcd_add_mul_right_right N M (lf (y+1)), show M + lf (y+1) * N = 2 * X by rw [← hX]; ring, + Nat.gcd_comm N (2 * X), Nat.Coprime.gcd_mul_left_cancel X hcop, Nat.gcd_comm] + +/-- `q^k ∣ (qk)!`, since `q, 2q, …, kq` all occur in the product. -/ +private lemma pow_dvd_fact (q k : ℕ) (hq : 0 < q) : q^k ∣ (q*k).factorial := by + induction k with + | zero => simp + | succ k ih => + have h : q * (k+1) = (q*k + (q-1)) + 1 := by rw [Nat.mul_succ]; omega + rw [h, Nat.factorial_succ, pow_succ, mul_comm (q^k)] + apply mul_dvd_mul + · rw [← h]; exact Dvd.intro (k+1) rfl + · exact ih.trans (Nat.factorial_dvd_factorial (by omega)) + +/-- If `q` divides `N / gcd(N, M)`, then `q^(j+1) ∣ N` whenever `q^j ∣ M`. -/ +private lemma pow_step {N M q : ℕ} (hq : q ∣ N / Nat.gcd N M) : + ∀ j, q^j ∣ M → q^(j+1) ∣ N := by + have hg : Nat.gcd N M ∣ N := Nat.gcd_dvd_left N M + have hNe : N = Nat.gcd N M * (N / Nat.gcd N M) := (Nat.mul_div_cancel' hg).symm + intro j + induction j with + | zero => intro _; simpa using hq.trans (Nat.div_dvd_of_dvd hg) + | succ j ih => + intro hj + have h1 : q^j ∣ M := (pow_dvd_pow q (Nat.le_succ j)).trans hj + have h2 : q^(j+1) ∣ Nat.gcd N M := Nat.dvd_gcd (ih h1) hj + rw [hNe, pow_succ] + exact mul_dvd_mul h2 hq + +/-- `(qj+4)^2 < q^j` for `q ≥ 3`, `j ≥ 6`. -/ +private lemma bound6 (q : ℕ) (hq : 3 ≤ q) : ∀ j, 6 ≤ j → (q*j+4)^2 < q^j := by + intro j hj + induction j, hj using Nat.le_induction with + | base => + have h1 : q^6 = q^4 * q^2 := by ring + have h2 : 81 ≤ q^4 := by + calc 81 = 3^4 := by norm_num + _ ≤ q^4 := Nat.pow_le_pow_left hq 4 + rw [h1]; nlinarith + | succ j hj ih => + rw [pow_succ] + have h3 : (q*(j+1)+4)^2 ≤ 3*(q*j+4)^2 := by nlinarith + calc (q*(j+1)+4)^2 ≤ 3*(q*j+4)^2 := h3 + _ < 3 * q^j := by omega + _ ≤ q^j * q := by rw [mul_comm]; exact Nat.mul_le_mul_left _ hq + +/-- `(qj+4)^2 < q^j` for `q, j ≥ 3` and `qj ≥ 34`. -/ +private lemma bound (q j : ℕ) (hq : 3 ≤ q) (hj : 3 ≤ j) (hqj : 34 ≤ q*j) : + (q*j+4)^2 < q^j := by + rcases (show j = 3 ∨ j = 4 ∨ j = 5 ∨ 6 ≤ j by omega) with rfl | rfl | rfl | h6 + · have : 12 ≤ q := by omega + nlinarith + · have : 9 ≤ q := by omega + have h1 : q^4 = q^2 * q^2 := by ring + have h2 : 81 ≤ q^2 := by nlinarith + rw [h1]; nlinarith + · have : 7 ≤ q := by omega + have h1 : q^5 = q^3 * q^2 := by ring + have h2 : 343 ≤ q^3 := by + calc 343 = 7^3 := by norm_num + _ ≤ q^3 := Nat.pow_le_pow_left this 3 + rw [h1]; nlinarith + · exact bound6 q hq j h6 + +/-- `x + k` divides `N + c` for small shifts, so it cannot divide `N` when `x` is large. -/ +private lemma not_dvd_aux (x k c : ℕ) (hk : x + k ∣ x^2 + 9*x + 13 + c) (hc : c < x + k) + (hc' : 0 < c) : ¬ x + k ∣ x^2 + 9*x + 13 := by + intro h + have := (Nat.dvd_add_right h).mp hk + have := Nat.le_of_dvd hc' this + omega + +/-- The number-theoretic core: for `x ≥ 33`, `N / gcd(N, 5(x+2)·x!)` is `1` or a prime, +where `N = x^2+9x+13`. -/ +private lemma main (x : ℕ) (hx : 33 ≤ x) : + (x^2+9*x+13) / Nat.gcd (x^2+9*x+13) (5*(x+2)*x.factorial) = 1 ∨ + ((x^2+9*x+13) / Nat.gcd (x^2+9*x+13) (5*(x+2)*x.factorial)).Prime := by + set N := x^2+9*x+13 with hN + set M := 5*(x+2)*x.factorial with hM + set g := Nat.gcd N M with hg + set d := N / g with hd + have hNpos : 0 < N := by positivity + have hgN : g ∣ N := Nat.gcd_dvd_left N M + have hdN : d ∣ N := Nat.div_dvd_of_dvd hgN + have hNgd : N = g * d := (Nat.mul_div_cancel' hgN).symm + have hodd : ¬ 2 ∣ N := N_odd x + have hfM : x.factorial ∣ M := Dvd.intro_left _ rfl + have hN5 : N < (x+5)^2 := by rw [hN]; nlinarith + by_cases hd1 : d = 1 + · left; exact hd1 + have hpp : d.minFac.Prime := Nat.minFac_prime hd1 + set p := d.minFac with hp + have hpd : p ∣ d := Nat.minFac_dvd d + have hpN : p ∣ N := hpd.trans hdN + have hp3 : 3 ≤ p := by + have := hpp.two_le + rcases (show p = 2 ∨ 3 ≤ p by omega) with h | h + · rw [h] at hpN; exact absurd hpN hodd + · exact h + by_cases hpx : p ≤ x + · by_cases h2p : 2*p ≤ x + · exfalso + have hk2 : 2 ≤ x / p := (Nat.le_div_iff_mul_le hpp.pos).mpr (by linarith) + have hdvdM : p^(x/p) ∣ M := + (pow_dvd_fact p (x/p) hpp.pos).trans + ((Nat.factorial_dvd_factorial (Nat.mul_div_le x p)).trans hfM) + have h1 := pow_step hpd (x/p) hdvdM + have h2 : p^(x/p+1) ≤ N := Nat.le_of_dvd hNpos h1 + have h3 : x < p*(x/p+1) := Nat.lt_mul_div_succ x hpp.pos + have h4 := bound p (x/p+1) hp3 (by omega) (by omega) + have h6 : (x+5)^2 ≤ (p*(x/p+1)+4)^2 := Nat.pow_le_pow_left (by omega) 2 + omega + · push Not at h2p + have hpM : p ∣ M := (Nat.dvd_factorial hpp.pos hpx).trans hfM + have hp2 : p^2 ∣ N := pow_step hpd 1 (by simpa using hpM) + obtain ⟨m, hm⟩ := hp2 + have hm5 : m < 5 := by + by_contra hcon + push Not at hcon + have h1 : (x+1)^2 ≤ (2*p)^2 := Nat.pow_le_pow_left (by omega) 2 + have h2 : 5 * p^2 ≤ p^2 * m := by rw [mul_comm]; exact Nat.mul_le_mul_left _ hcon + nlinarith + interval_cases m + · omega + · exfalso + rw [mul_one] at hm + have h1 : x + 4 < p := by + by_contra hc; push Not at hc + have : p^2 ≤ (x+4)^2 := Nat.pow_le_pow_left hc 2 + nlinarith + have h2 : p < x + 5 := by + by_contra hc; push Not at hc + have : (x+5)^2 ≤ p^2 := Nat.pow_le_pow_left hc 2 + omega + omega + · exfalso; exact hodd ⟨p^2, by rw [hm]; ring⟩ + · have hp_ne3 : p ≠ 3 := by omega + have h3M : 3 ∣ M := (Nat.dvd_factorial (by norm_num) (by omega)).trans hfM + have hcop : Nat.Coprime 3 p := (Nat.coprime_primes Nat.prime_three hpp).mpr (Ne.symm hp_ne3) + have h3pM : 3*p ∣ M := hcop.mul_dvd_of_dvd_of_dvd h3M hpM + have h3pN : 3*p ∣ N := ⟨p, by rw [hm]; ring⟩ + have h3pg : 3*p ∣ g := Nat.dvd_gcd h3pN h3pM + obtain ⟨h, hh⟩ := h3pg + have hpe : p = h * d := by + have : 3*p*p = 3*p*(h*d) := by rw [← mul_assoc, ← hh, ← hNgd, hm]; ring + exact Nat.eq_of_mul_eq_mul_left (by positivity) this + rcases hpp.eq_one_or_self_of_dvd d ⟨h, by rw [hpe, mul_comm]⟩ with h' | h' + · left; exact h' + · right; rw [h']; exact hpp + · exfalso; exact hodd ⟨2*p^2, by rw [hm]; ring⟩ + · push Not at hpx + have h1 : ¬ x + 1 ∣ N := by + intro h + have h' : x + 1 ∣ (x+1)*(x+8) + 5 := by + rw [show (x+1)*(x+8) + 5 = N by rw [hN]; ring]; exact h + have := Nat.le_of_dvd (by norm_num) ((Nat.dvd_add_right (dvd_mul_right _ _)).mp h') + omega + have h2 : ¬ x + 2 ∣ N := not_dvd_aux x 2 1 ⟨x+7, by ring⟩ (by omega) (by norm_num) + have h3 : ¬ x + 3 ∣ N := not_dvd_aux x 3 5 ⟨x+6, by ring⟩ (by omega) (by norm_num) + have h4 : ¬ x + 4 ∣ N := not_dvd_aux x 4 7 ⟨x+5, by ring⟩ (by omega) (by norm_num) + have hB : ∀ q, q ∣ N → x < q → x + 5 ≤ q := by + intro q hq hxq + by_contra hcon + push Not at hcon + rcases (show q = x+1 ∨ q = x+2 ∨ q = x+3 ∨ q = x+4 by omega) with rfl | rfl | rfl | rfl + · exact h1 hq + · exact h2 hq + · exact h3 hq + · exact h4 hq + have hp5 : x + 5 ≤ p := hB p hpN hpx + by_cases hdp : d = p + · right; rw [hdp]; exact hpp + exfalso + have hdr : d = p * (d / p) := (Nat.mul_div_cancel' hpd).symm + have hr1 : d / p ≠ 1 := by intro h; apply hdp; rw [hdr, h, mul_one] + have hr0 : d / p ≠ 0 := by + intro h; rw [h, mul_zero] at hdr; rw [hdr] at hNgd; omega + have hrp : (d / p).minFac.Prime := Nat.minFac_prime hr1 + have hrd : (d / p).minFac ∣ d := (Nat.minFac_dvd _).trans (Dvd.intro_left p hdr.symm) + have hpr : p ≤ (d / p).minFac := Nat.minFac_le_of_dvd hrp.two_le hrd + have hr5 : x + 5 ≤ d / p := le_trans hp5 (hpr.trans (Nat.minFac_le (Nat.pos_of_ne_zero hr0))) + have hdle : d ≤ N := Nat.le_of_dvd hNpos hdN + have : (x+5)^2 ≤ d := by rw [hdr, sq]; exact Nat.mul_le_mul hp5 hr5 + omega + +/-- The cases `3 ≤ n < 64`, read off from the 61 kernel-checked terms `a_data`. -/ +private lemma small (n : ℕ) (hn : 3 ≤ n) (hn' : n < 64) (h49 : a n ≠ 49) : + a n = 1 ∨ (a n).Prime := by + have key : ∀ v ∈ (List.range 61).map (fun i => a (i + 3)), v ≠ 49 → v = 1 ∨ v.Prime := by + rw [a_data] + simp only [List.forall_mem_cons, List.not_mem_nil, IsEmpty.forall_iff, implies_true, and_true] + norm_num + refine key (a n) (List.mem_map.mpr ⟨n - 3, List.mem_range.mpr (by omega), ?_⟩) h49 + show a (n - 3 + 3) = a n + congr 1 + omega + +/-- Bouras' conjecture for A363482: except for `49`, every term `a n` (`n ≥ 3`) is `1` or a prime. -/ +theorem result : statement := by + intro n hn h49 + by_cases hsmall : n < 36 + · exact small n hn (by omega) h49 + · obtain ⟨x, rfl⟩ : ∃ x, n = x + 3 := ⟨n - 3, by omega⟩ + rw [a_eq x (by omega)] + exact main x (by omega) + +end Math0.Frontier.A363482 + +#math0_settles Math0.Frontier.A363482.result Math0.Statements.A363482.statement diff --git a/lean/Math0/Frontier/OEIS/A363609.lean b/lean/Math0/Frontier/OEIS/A363609.lean new file mode 100644 index 0000000..a4aa2a2 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A363609.lean @@ -0,0 +1,436 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A363609 +import Math0.Audit + +/-! +# A363609: the `k × k × k` cube of dice shows at least `6k(k + 2)` pips + +We prove the conjecture `a(k³) = 6 (k + 2) k` for `k > 1`: no polycube of `k³` dice shows fewer +than `6k² + 12k` pips, and the `k × k × k` cube shows exactly that many. + +**Per die.** Since the dice are oriented independently, the minimum for a fixed polycube `P` is +`LB P = ∑ c ∈ P, fmin (exposed P c)`. A check of the `64` cases of the table `tabF` shows +`fmin E ≥ |E| + (number of perpendicular pairs of faces in E)`. + +**Faces.** For every axis direction `d`, the cells of `P` whose `d`-face is exposed project onto +the whole projection of `P` along that axis (the last cell of each line along `d` is exposed). So +the number of exposed faces is at least `2 (A + B + C)`, where `A, B, C` are the sizes of the three +coordinate projections of `P`. + +**Edges.** For two perpendicular directions `d, e`, the lexicographically last cell (first along +`d`, then along `e`) of each slice of `P` orthogonal to the third axis has both its `d`- and its +`e`-face exposed. Summing over the `12` perpendicular pairs, the number of exposed perpendicular +face pairs is at least `4 (a + b + c)`, where `a, b, c` count the occupied slices in the three +axis directions. + +**Inequalities.** `|P| ≤ a b c`, so AM-GM gives `a + b + c ≥ 3k`. Slicing along `z`, the slice +`P_z` has at most `C` cells and at most `α_z β_z` cells, where `α_z, β_z` are the sizes of its two +projections and `∑ α_z = B`, `∑ β_z = A`. Hence `4 k |P_z| ≤ (C + k²)(α_z + β_z)`, and summing gives +`4 k⁴ ≤ (C + k²)(A + B)`, so `(C + k²) + (A + B) ≥ 4k²`, i.e. `A + B + C ≥ 3k²` (a discrete +Loomis–Whitney inequality). Altogether `LB P ≥ 2 · 3k² + 4 · 3k = 6k(k + 2)`. + +**The cube.** In `[0, k)³` a die with `m` exposed faces (`m ≤ 3`, no two opposite) contributes +`m (m + 1) / 2`. Writing `u(x) = [x = k - 1] + [x = 0]`, a die contributes +`(1 + u x)(1 + u y)(1 + u z) - 1 - u x u y u z`, and summing gives `(k + 2)³ - k³ - 8 = 6k² + 12k`. +-/ + +namespace Math0.Frontier.A363609 +open Math0.Statements.A363609 + +/-- Per-die bound (all `64` cases): a die shows at least as many pips as it has exposed faces +plus exposed pairs of perpendicular faces. The arguments of `tabF` are the exposure flags of +`+x, -x, +y, -y, +z, -z`. -/ +private theorem tabF_lower : ∀ b0 b1 b2 b3 b4 b5 : Bool, + ((if b0 then 1 else 0) + (if b1 then 1 else 0) + (if b2 then 1 else 0) + + (if b3 then 1 else 0) + (if b4 then 1 else 0) + (if b5 then 1 else 0)) + + ((if b0 && b2 then 1 else 0) + (if b0 && b3 then 1 else 0) + (if b1 && b2 then 1 else 0) + + (if b1 && b3 then 1 else 0)) + + ((if b0 && b4 then 1 else 0) + (if b0 && b5 then 1 else 0) + (if b1 && b4 then 1 else 0) + + (if b1 && b5 then 1 else 0)) + + ((if b2 && b4 then 1 else 0) + (if b2 && b5 then 1 else 0) + (if b3 && b4 then 1 else 0) + + (if b3 && b5 then 1 else 0)) ≤ tabF b0 b1 b2 b3 b4 b5 := by + decide + +/-- Number of cells of `P` whose face with normal `d` is exposed. -/ +private def E1 (P : Finset Cell) (d : Cell) : ℕ := (P.filter fun c => c + d ∉ P).card + +/-- Number of cells of `P` whose faces with normals `d` and `e` are both exposed. -/ +private def E2 (P : Finset Cell) (d e : Cell) : ℕ := + (P.filter fun c => c + d ∉ P ∧ c + e ∉ P).card + +/-- Summing the per-die bound: exposed faces plus exposed perpendicular face pairs (counted per +direction and per pair of directions) are at most `LB P`. -/ +private theorem LB_ge_E (P : Finset Cell) : + (E1 P (1, 0, 0) + E1 P (-1, 0, 0) + E1 P (0, 1, 0) + E1 P (0, -1, 0) + E1 P (0, 0, 1) + + E1 P (0, 0, -1)) + + (E2 P (1, 0, 0) (0, 1, 0) + E2 P (1, 0, 0) (0, -1, 0) + E2 P (-1, 0, 0) (0, 1, 0) + + E2 P (-1, 0, 0) (0, -1, 0)) + + (E2 P (1, 0, 0) (0, 0, 1) + E2 P (1, 0, 0) (0, 0, -1) + E2 P (-1, 0, 0) (0, 0, 1) + + E2 P (-1, 0, 0) (0, 0, -1)) + + (E2 P (0, 1, 0) (0, 0, 1) + E2 P (0, 1, 0) (0, 0, -1) + E2 P (0, -1, 0) (0, 0, 1) + + E2 P (0, -1, 0) (0, 0, -1)) ≤ LB P := by + unfold LB E1 E2 + simp only [Finset.card_filter, ← Finset.sum_add_distrib] + refine Finset.sum_le_sum fun c _ => ?_ + rw [fmin_exposed] + have := tabF_lower (decide (c + (1, 0, 0) ∉ P)) (decide (c + (-1, 0, 0) ∉ P)) + (decide (c + (0, 1, 0) ∉ P)) (decide (c + (0, -1, 0) ∉ P)) (decide (c + (0, 0, 1) ∉ P)) + (decide (c + (0, 0, -1) ∉ P)) + simpa only [decide_eq_true_eq, Bool.and_eq_true] using this + +/-- Projection bound for one exposed direction. -/ +private theorem card_image_le_E1 {β : Type} [DecidableEq β] (P : Finset Cell) (d : Cell) + (π : Cell → β) (h : Cell → ℤ) (hπ : ∀ c, π (c + d) = π c) (hh : ∀ c, h (c + d) = h c + 1) : + (P.image π).card ≤ E1 P d := by + unfold E1 + calc (P.image π).card ≤ ((P.filter fun c => c + d ∉ P).image π).card := by + apply Finset.card_le_card + intro p hp + obtain ⟨c, hc, rfl⟩ := Finset.mem_image.1 hp + obtain ⟨m, hm, hmax⟩ := Finset.exists_max_image (P.filter fun c' => π c' = π c) h + ⟨c, Finset.mem_filter.2 ⟨hc, rfl⟩⟩ + rw [Finset.mem_filter] at hm + refine Finset.mem_image.2 ⟨m, Finset.mem_filter.2 ⟨hm.1, fun hd => ?_⟩, hm.2⟩ + have := hmax (m + d) (Finset.mem_filter.2 ⟨hd, by rw [hπ, hm.2]⟩) + rw [hh] at this + omega + _ ≤ _ := Finset.card_image_le + +/-- Projection bound for two perpendicular exposed directions. -/ +private theorem card_image_le_E2 {β : Type} [DecidableEq β] (P : Finset Cell) (d e : Cell) + (π : Cell → β) (h1 h2 : Cell → ℤ) (hπ1 : ∀ c, π (c + d) = π c) (hπ2 : ∀ c, π (c + e) = π c) + (h11 : ∀ c, h1 (c + d) = h1 c + 1) (h12 : ∀ c, h1 (c + e) = h1 c) + (h22 : ∀ c, h2 (c + e) = h2 c + 1) : + (P.image π).card ≤ E2 P d e := by + unfold E2 + calc (P.image π).card ≤ ((P.filter fun c => c + d ∉ P ∧ c + e ∉ P).image π).card := by + apply Finset.card_le_card + intro p hp + obtain ⟨c, hc, rfl⟩ := Finset.mem_image.1 hp + obtain ⟨m, hm, hmax⟩ := Finset.exists_max_image (P.filter fun c' => π c' = π c) + (fun c' => toLex (h1 c', h2 c')) ⟨c, Finset.mem_filter.2 ⟨hc, rfl⟩⟩ + rw [Finset.mem_filter] at hm + refine Finset.mem_image.2 ⟨m, Finset.mem_filter.2 ⟨hm.1, fun hd => ?_, fun he => ?_⟩, + hm.2⟩ + · have := hmax (m + d) (Finset.mem_filter.2 ⟨hd, by rw [hπ1, hm.2]⟩) + rw [Prod.Lex.toLex_le_toLex, h11] at this + dsimp only at this + omega + · have := hmax (m + e) (Finset.mem_filter.2 ⟨he, by rw [hπ2, hm.2]⟩) + rw [Prod.Lex.toLex_le_toLex, h12, h22] at this + dsimp only at this + omega + _ ≤ _ := Finset.card_image_le + +/-- Surface and edge counts dominate the projection sizes. -/ +private theorem LB_ge_proj (P : Finset Cell) : + 2 * ((P.image fun c => c.2).card + (P.image fun c => (c.1, c.2.2)).card + + (P.image fun c => (c.1, c.2.1)).card) + + 4 * ((P.image fun c => c.1).card + (P.image fun c => c.2.1).card + + (P.image fun c => c.2.2).card) ≤ LB P := by + refine le_trans ?_ (LB_ge_E P) + have hx : ∀ s : ℤ, s * s = 1 → (P.image fun c => c.2).card ≤ E1 P (s, 0, 0) := by + intro s hs + refine card_image_le_E1 P _ (fun c => c.2) (fun c => s * c.1) ?_ ?_ + · intro c; obtain ⟨x, y, z⟩ := c; simp only [Prod.mk_add_mk, add_zero] + · intro c; obtain ⟨x, y, z⟩ := c; simp only [Prod.mk_add_mk]; linear_combination hs + have hy : ∀ s : ℤ, s * s = 1 → (P.image fun c => (c.1, c.2.2)).card ≤ E1 P (0, s, 0) := by + intro s hs + refine card_image_le_E1 P _ (fun c => (c.1, c.2.2)) (fun c => s * c.2.1) ?_ ?_ + · intro c; obtain ⟨x, y, z⟩ := c; simp only [Prod.mk_add_mk, add_zero] + · intro c; obtain ⟨x, y, z⟩ := c; simp only [Prod.mk_add_mk]; linear_combination hs + have hz : ∀ s : ℤ, s * s = 1 → (P.image fun c => (c.1, c.2.1)).card ≤ E1 P (0, 0, s) := by + intro s hs + refine card_image_le_E1 P _ (fun c => (c.1, c.2.1)) (fun c => s * c.2.2) ?_ ?_ + · intro c; obtain ⟨x, y, z⟩ := c; simp only [Prod.mk_add_mk, add_zero] + · intro c; obtain ⟨x, y, z⟩ := c; simp only [Prod.mk_add_mk]; linear_combination hs + have hxy : ∀ s t : ℤ, s * s = 1 → t * t = 1 → + (P.image fun c => c.2.2).card ≤ E2 P (s, 0, 0) (0, t, 0) := by + intro s t hs ht + refine card_image_le_E2 P _ _ (fun c => c.2.2) (fun c => s * c.1) (fun c => t * c.2.1) + ?_ ?_ ?_ ?_ ?_ <;> + · intro c; obtain ⟨x, y, z⟩ := c; simp only [Prod.mk_add_mk] + first | linear_combination | linear_combination hs | linear_combination ht + have hxz : ∀ s t : ℤ, s * s = 1 → t * t = 1 → + (P.image fun c => c.2.1).card ≤ E2 P (s, 0, 0) (0, 0, t) := by + intro s t hs ht + refine card_image_le_E2 P _ _ (fun c => c.2.1) (fun c => s * c.1) (fun c => t * c.2.2) + ?_ ?_ ?_ ?_ ?_ <;> + · intro c; obtain ⟨x, y, z⟩ := c; simp only [Prod.mk_add_mk] + first | linear_combination | linear_combination hs | linear_combination ht + have hyz : ∀ s t : ℤ, s * s = 1 → t * t = 1 → + (P.image fun c => c.1).card ≤ E2 P (0, s, 0) (0, 0, t) := by + intro s t hs ht + refine card_image_le_E2 P _ _ (fun c => c.1) (fun c => s * c.2.1) (fun c => t * c.2.2) + ?_ ?_ ?_ ?_ ?_ <;> + · intro c; obtain ⟨x, y, z⟩ := c; simp only [Prod.mk_add_mk] + first | linear_combination | linear_combination hs | linear_combination ht + have p1 : (1 : ℤ) * 1 = 1 := by norm_num + have m1 : (-1 : ℤ) * -1 = 1 := by norm_num + have := hx 1 p1 + have := hx (-1) m1 + have := hy 1 p1 + have := hy (-1) m1 + have := hz 1 p1 + have := hz (-1) m1 + have := hxy 1 1 p1 p1 + have := hxy 1 (-1) p1 m1 + have := hxy (-1) 1 m1 p1 + have := hxy (-1) (-1) m1 m1 + have := hxz 1 1 p1 p1 + have := hxz 1 (-1) p1 m1 + have := hxz (-1) 1 m1 p1 + have := hxz (-1) (-1) m1 m1 + have := hyz 1 1 p1 p1 + have := hyz 1 (-1) p1 m1 + have := hyz (-1) 1 m1 p1 + have := hyz (-1) (-1) m1 m1 + omega + +/-- The per-slice inequality: from `m ≤ C` and `m ≤ α β`, `4 k m ≤ (C + k²)(α + β)` (two AM-GM +steps, `4 C k² ≤ (C + k²)²` and `4 α β ≤ (α + β)²`). -/ +private theorem slice_arith (k m C α β : ℕ) (hC : m ≤ C) (hαβ : m ≤ α * β) : + 4 * k * m ≤ (C + k ^ 2) * (α + β) := by + have h1 : m * m ≤ C * (α * β) := Nat.mul_le_mul hC hαβ + have h2 : 4 * (C * k ^ 2) ≤ (C + k ^ 2) ^ 2 := by + have : (0 : ℤ) ≤ ((C : ℤ) - k ^ 2) ^ 2 := sq_nonneg _ + have : (4 * (C * k ^ 2) : ℤ) ≤ ((C : ℤ) + k ^ 2) ^ 2 := by nlinarith + exact_mod_cast this + have h3 : 4 * (α * β) ≤ (α + β) ^ 2 := by + have : (0 : ℤ) ≤ ((α : ℤ) - β) ^ 2 := sq_nonneg _ + have : (4 * (α * β) : ℤ) ≤ ((α : ℤ) + β) ^ 2 := by nlinarith + exact_mod_cast this + have h4 : (4 * k * m) ^ 2 ≤ ((C + k ^ 2) * (α + β)) ^ 2 := by + calc (4 * k * m) ^ 2 = 4 * k ^ 2 * (4 * (m * m)) := by ring + _ ≤ 4 * k ^ 2 * (4 * (C * (α * β))) := by gcongr + _ = (4 * (C * k ^ 2)) * (4 * (α * β)) := by ring + _ ≤ (C + k ^ 2) ^ 2 * (α + β) ^ 2 := Nat.mul_le_mul h2 h3 + _ = ((C + k ^ 2) * (α + β)) ^ 2 := by ring + exact (Nat.pow_le_pow_iff_left (by norm_num)).1 h4 + +/-- A discrete Loomis–Whitney type estimate, slicing along the third coordinate. -/ +private theorem loomis (P : Finset Cell) (k : ℕ) : + 4 * k * P.card ≤ ((P.image fun c => (c.1, c.2.1)).card + k ^ 2) * + ((P.image fun c => c.2).card + (P.image fun c => (c.1, c.2.2)).card) := by + set C := (P.image fun c => (c.1, c.2.1)).card + set Z := P.image fun c => c.2.2 + have hP : P.card = ∑ z ∈ Z, (P.filter fun c => c.2.2 = z).card := + Finset.card_eq_sum_card_image _ _ + have hfib : ∀ (f : Cell → ℤ × ℤ), (∀ c, (f c).2 = c.2.2) → + (P.image f).card = ∑ z ∈ Z, ((P.filter fun c => c.2.2 = z).image f).card := by + intro f hf + rw [Finset.card_eq_sum_card_image Prod.snd (P.image f), Finset.image_image] + have e : Prod.snd ∘ f = fun c => c.2.2 := funext hf + rw [e] + refine Finset.sum_congr rfl fun z _ => ?_ + rw [Finset.filter_image] + simp only [hf] + rw [hfib (fun c => c.2) (fun _ => rfl), hfib (fun c => (c.1, c.2.2)) (fun _ => rfl), hP, + Finset.mul_sum, ← Finset.sum_add_distrib, Finset.mul_sum] + refine Finset.sum_le_sum fun z _ => ?_ + set F := P.filter fun c => c.2.2 = z + apply slice_arith + · calc F.card = (F.image fun c => (c.1, c.2.1)).card := by + refine (Finset.card_image_of_injOn ?_).symm + intro u hu v hv huv + simp only [F, Finset.mem_coe, Finset.mem_filter] at hu hv + simp only [Prod.mk.injEq] at huv + exact Prod.ext huv.1 (Prod.ext huv.2 (hu.2.trans hv.2.symm)) + _ ≤ C := Finset.card_le_card (Finset.image_subset_image (Finset.filter_subset _ _)) + · rw [mul_comm, ← Finset.card_product] + refine Finset.card_le_card_of_injOn (fun c => ((c.1, c.2.2), c.2)) ?_ ?_ + · intro c hc + simp only [Finset.coe_product, Set.mem_prod, Finset.mem_coe] + exact ⟨Finset.mem_image_of_mem _ hc, Finset.mem_image_of_mem _ hc⟩ + · intro u _ v _ huv + simp only [Prod.mk.injEq] at huv + exact Prod.ext huv.1.1 huv.2 + +/-- AM-GM for three natural numbers, in cubed form. -/ +private theorem amgm3 (a b c : ℕ) : 27 * (a * b * c) ≤ (a + b + c) ^ 3 := by + have ha : (0 : ℤ) ≤ a := by positivity + have hb : (0 : ℤ) ≤ b := by positivity + have hc : (0 : ℤ) ≤ c := by positivity + have : (27 * (a * b * c) : ℤ) ≤ ((a : ℤ) + b + c) ^ 3 := by + nlinarith [mul_nonneg (add_nonneg (add_nonneg ha hb) hc) (sq_nonneg ((a : ℤ) - b)), + mul_nonneg (add_nonneg (add_nonneg ha hb) hc) (sq_nonneg ((b : ℤ) - c)), + mul_nonneg (add_nonneg (add_nonneg ha hb) hc) (sq_nonneg ((a : ℤ) - c)), + mul_nonneg ha (sq_nonneg ((b : ℤ) - c)), mul_nonneg hb (sq_nonneg ((a : ℤ) - c)), + mul_nonneg hc (sq_nonneg ((a : ℤ) - b))] + exact_mod_cast this + +/-- If `k³ ≤ a b c` then `3 k ≤ a + b + c`. -/ +private theorem sum3_ge (k a b c : ℕ) (h : k ^ 3 ≤ a * (b * c)) : 3 * k ≤ a + b + c := by + have h1 : (3 * k) ^ 3 ≤ (a + b + c) ^ 3 := by + calc (3 * k) ^ 3 = 27 * k ^ 3 := by ring + _ ≤ 27 * (a * b * c) := by rw [mul_assoc a]; omega + _ ≤ _ := amgm3 a b c + exact (Nat.pow_le_pow_iff_left (by norm_num)).1 h1 + +/-- If `4 k⁴ ≤ u v` then `4 k² ≤ u + v`. -/ +private theorem sum2_ge (k u v : ℕ) (h : 4 * k ^ 4 ≤ u * v) : 4 * k ^ 2 ≤ u + v := by + have h1 : (4 * k ^ 2) ^ 2 ≤ (u + v) ^ 2 := by + have : (0 : ℤ) ≤ ((u : ℤ) - v) ^ 2 := sq_nonneg _ + have : (4 * (u * v) : ℤ) ≤ ((u : ℤ) + v) ^ 2 := by nlinarith + have h' : 4 * (u * v) ≤ (u + v) ^ 2 := by exact_mod_cast this + calc (4 * k ^ 2) ^ 2 = 4 * (4 * k ^ 4) := by ring + _ ≤ 4 * (u * v) := by omega + _ ≤ _ := h' + exact (Nat.pow_le_pow_iff_left (by norm_num)).1 h1 + +/-- The `k × k × k` cube `[0, k)³`. -/ +private noncomputable def cube (k : ℕ) : Finset Cell := + Finset.Ico (0 : ℤ) k ×ˢ Finset.Ico (0 : ℤ) k ×ˢ Finset.Ico (0 : ℤ) k + +/-- The cube has `k³` cells. -/ +private theorem card_cube (k : ℕ) : (cube k).card = k ^ 3 := by + simp only [cube, Finset.card_product, Int.card_Ico, sub_zero, Int.toNat_natCast] + ring + +/-- Membership in the cube, coordinatewise. -/ +private theorem mem_cube {k : ℕ} {x y z : ℤ} : + (x, y, z) ∈ cube k ↔ (0 ≤ x ∧ x < k) ∧ (0 ≤ y ∧ y < k) ∧ (0 ≤ z ∧ z < k) := by + simp only [cube, Finset.mem_product, Finset.mem_Ico] + +/-- Cells along a line inside `P` are connected to its starting cell, in both directions. -/ +private theorem line {P : Finset Cell} (f : ℤ → Cell) (k : ℕ) + (hf : ∀ i : ℤ, 0 ≤ i → i < k → f i ∈ P) (hd : ∀ i, f i - f (i + 1) ∈ dirs) + (hd' : ∀ i, f (i + 1) - f i ∈ dirs) : + ∀ n : ℕ, (n : ℤ) < k → Relation.ReflTransGen (Adj P) (f n) (f 0) ∧ + Relation.ReflTransGen (Adj P) (f 0) (f n) := by + intro n + induction n with + | zero => intro _; exact ⟨by simpa using Relation.ReflTransGen.refl, + by simpa using Relation.ReflTransGen.refl⟩ + | succ n ih => + intro hn + push_cast at hn ⊢ + obtain ⟨h1, h2⟩ := ih (by omega) + have m1 : f (n + 1) ∈ P := hf _ (by omega) hn + have m0 : f n ∈ P := hf _ (by omega) (by omega) + exact ⟨Relation.ReflTransGen.head ⟨m1, m0, hd n⟩ h1, h2.tail ⟨m0, m1, hd' n⟩⟩ + +/-- The cube is face-connected: every cell is joined to the origin along the three axes. -/ +private theorem cube_conn (k : ℕ) : FaceConnected (cube k) := by + have key : ∀ c ∈ cube k, Relation.ReflTransGen (Adj (cube k)) c (0, 0, 0) ∧ + Relation.ReflTransGen (Adj (cube k)) (0, 0, 0) c := by + rintro ⟨x, y, z⟩ hc + rw [mem_cube] at hc + obtain ⟨⟨hx0, hxk⟩, ⟨hy0, hyk⟩, ⟨hz0, hzk⟩⟩ := hc + obtain ⟨a, rfl⟩ := Int.eq_ofNat_of_zero_le hx0 + obtain ⟨b, rfl⟩ := Int.eq_ofNat_of_zero_le hy0 + obtain ⟨c, rfl⟩ := Int.eq_ofNat_of_zero_le hz0 + have l1 := line (P := cube k) (fun i => (i, (b : ℤ), (c : ℤ))) k + (fun i h0 h1 => mem_cube.2 ⟨⟨h0, h1⟩, ⟨hy0, hyk⟩, ⟨hz0, hzk⟩⟩) + (fun i => by simp [dirs, Prod.ext_iff]) (fun i => by simp [dirs, Prod.ext_iff]) a hxk + have l2 := line (P := cube k) (fun i => ((0 : ℤ), i, (c : ℤ))) k + (fun i h0 h1 => mem_cube.2 ⟨⟨le_rfl, by omega⟩, ⟨h0, h1⟩, ⟨hz0, hzk⟩⟩) + (fun i => by simp [dirs, Prod.ext_iff]) (fun i => by simp [dirs, Prod.ext_iff]) b hyk + have l3 := line (P := cube k) (fun i => ((0 : ℤ), (0 : ℤ), i)) k + (fun i h0 h1 => mem_cube.2 ⟨⟨le_rfl, by omega⟩, ⟨le_rfl, by omega⟩, ⟨h0, h1⟩⟩) + (fun i => by simp [dirs, Prod.ext_iff]) (fun i => by simp [dirs, Prod.ext_iff]) c hzk + exact ⟨(l1.1.trans l2.1).trans l3.1, (l3.2.trans l2.2).trans l1.2⟩ + intro u hu v hv + exact (key u hu).1.trans (key v hv).2 + +/-- When no two opposite faces are exposed, a die with exposure counts `X, Y, Z ∈ {0, 1}` per axis +has `fmin = X + Y + Z + XY + XZ + YZ`, written as `fmin + 1 + XYZ = (1 + X)(1 + Y)(1 + Z)`. -/ +private theorem tabF_upper : ∀ b0 b1 b2 b3 b4 b5 : Bool, + (b0 && b1) = false → (b2 && b3) = false → (b4 && b5) = false → + tabF b0 b1 b2 b3 b4 b5 + 1 + + ((if b0 then 1 else 0) + (if b1 then 1 else 0)) * + ((if b2 then 1 else 0) + (if b3 then 1 else 0)) * + ((if b4 then 1 else 0) + (if b5 then 1 else 0)) = + (1 + ((if b0 then 1 else 0) + (if b1 then 1 else 0))) * + (1 + ((if b2 then 1 else 0) + (if b3 then 1 else 0))) * + (1 + ((if b4 then 1 else 0) + (if b5 then 1 else 0))) := by + decide + +/-- A product of one-variable functions sums over the cube to the product of the sums. -/ +private theorem sum_cube_mul (k : ℕ) (f g h : ℤ → ℕ) : + ∑ c ∈ cube k, f c.1 * g c.2.1 * h c.2.2 = + (∑ x ∈ Finset.Ico (0 : ℤ) k, f x) * (∑ x ∈ Finset.Ico (0 : ℤ) k, g x) * + (∑ x ∈ Finset.Ico (0 : ℤ) k, h x) := by + rw [mul_assoc, Finset.sum_mul_sum, Finset.sum_mul] + simp only [cube, Finset.sum_product, Finset.mul_sum, mul_assoc] + +/-- The cube attains the bound: `LB (cube k) = 6 (k + 2) k` for `k ≥ 2`. -/ +private theorem LB_cube (k : ℕ) (hk : 2 ≤ k) : LB (cube k) = 6 * (k + 2) * k := by + set u : ℤ → ℕ := fun x => (if x = k - 1 then 1 else 0) + (if x = 0 then 1 else 0) with hu + have hcell : ∀ c ∈ cube k, fmin (exposed (cube k) c) + 1 + u c.1 * u c.2.1 * u c.2.2 = + (1 + u c.1) * (1 + u c.2.1) * (1 + u c.2.2) := by + rintro ⟨x, y, z⟩ hc + rw [mem_cube] at hc + rw [fmin_exposed] + have e0 : decide ((x, y, z) + (1, 0, 0) ∉ cube k) = decide (x = k - 1) := by + simp only [Prod.mk_add_mk, mem_cube, decide_eq_decide]; omega + have e1 : decide ((x, y, z) + (-1, 0, 0) ∉ cube k) = decide (x = 0) := by + simp only [Prod.mk_add_mk, mem_cube, decide_eq_decide]; omega + have e2 : decide ((x, y, z) + (0, 1, 0) ∉ cube k) = decide (y = k - 1) := by + simp only [Prod.mk_add_mk, mem_cube, decide_eq_decide]; omega + have e3 : decide ((x, y, z) + (0, -1, 0) ∉ cube k) = decide (y = 0) := by + simp only [Prod.mk_add_mk, mem_cube, decide_eq_decide]; omega + have e4 : decide ((x, y, z) + (0, 0, 1) ∉ cube k) = decide (z = k - 1) := by + simp only [Prod.mk_add_mk, mem_cube, decide_eq_decide]; omega + have e5 : decide ((x, y, z) + (0, 0, -1) ∉ cube k) = decide (z = 0) := by + simp only [Prod.mk_add_mk, mem_cube, decide_eq_decide]; omega + rw [e0, e1, e2, e3, e4, e5] + have hx : (decide (x = k - 1) && decide (x = 0)) = false := by + simp only [Bool.and_eq_false_iff, decide_eq_false_iff_not]; omega + have hy : (decide (y = k - 1) && decide (y = 0)) = false := by + simp only [Bool.and_eq_false_iff, decide_eq_false_iff_not]; omega + have hz : (decide (z = k - 1) && decide (z = 0)) = false := by + simp only [Bool.and_eq_false_iff, decide_eq_false_iff_not]; omega + have := tabF_upper _ _ _ _ _ _ hx hy hz + simpa only [decide_eq_true_eq, hu] using this + have hsum : ∑ x ∈ Finset.Ico (0 : ℤ) k, u x = 2 := by + simp only [hu, Finset.sum_add_distrib, Finset.sum_ite_eq', Finset.mem_Ico] + split_ifs <;> omega + clear_value u + have hsum1 : ∑ x ∈ Finset.Ico (0 : ℤ) k, (1 + u x) = k + 2 := by + rw [Finset.sum_add_distrib, hsum] + simp + have key := Finset.sum_congr rfl hcell + have key2 := sum_cube_mul k (fun x => 1 + u x) (fun x => 1 + u x) (fun x => 1 + u x) + rw [key2, Finset.sum_add_distrib, Finset.sum_add_distrib, sum_cube_mul k u u u, hsum, + hsum1] at key + simp only [Finset.sum_const, card_cube, smul_eq_mul, mul_one] at key + unfold LB + nlinarith [key] + +/-- The lower bound: every polycube of `k³` dice has `LB ≥ 6 (k + 2) k` (connectivity is not +needed). -/ +private theorem LB_lower (k : ℕ) (P : Finset Cell) (hc : P.card = k ^ 3) : + 6 * (k + 2) * k ≤ LB P := by + have h1 := LB_ge_proj P + have h2 := loomis P k + rw [hc] at h2 + have h3 := sum2_ge k _ _ (by + calc 4 * k ^ 4 = 4 * k * k ^ 3 := by ring + _ ≤ _ := h2) + have h4 : P.card ≤ (P.image fun c => c.1).card * + ((P.image fun c => c.2.1).card * (P.image fun c => c.2.2).card) := by + rw [← Finset.card_product, ← Finset.card_product] + apply Finset.card_le_card + intro c hc + simp only [Finset.mem_product] + exact ⟨Finset.mem_image_of_mem _ hc, Finset.mem_image_of_mem _ hc, + Finset.mem_image_of_mem _ hc⟩ + rw [hc] at h4 + have h5 := sum3_ge k _ _ _ h4 + nlinarith + +/-- The conjecture of A363609: `a (k ^ 3) = 6 (k + 2) k` for every `k > 1`. -/ +theorem result : statement := by + intro k hk + have hLB : LB (cube k) = 6 * (k + 2) * k := LB_cube k hk + rw [← hLB] + exact a_eq_of (LB_mem_totals (card_cube k) (cube_conn k)) fun P hc _ => by + rw [hLB] + exact LB_lower k P hc + +end Math0.Frontier.A363609 + +#math0_settles Math0.Frontier.A363609.result Math0.Statements.A363609.statement diff --git a/lean/Math0/Frontier/OEIS/A367119.lean b/lean/Math0/Frontier/OEIS/A367119.lean new file mode 100644 index 0000000..322c68a --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A367119.lean @@ -0,0 +1,2361 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A367119 +import Math0.Audit + +/-! +# Edges of the all-chords graph of a triangle with `n` general points per side (A367119) + +We prove the conjecture of Shannon and Sloane in the form of `statement`: for every `n` and every +placement `B` of `n` points on each side of the equilateral triangle in general position, the +planar graph has `(3/2)(3n^4 + 4n^3 + 3n^2 + 4n + 2)` edges. + +*Parameters.* The boundary is parametrized by `P : [0, 3) → ℂ` (side `j` is the parameter range +`[j, j + 1]`, the corner `0` being the parameter `0`), with left inverse `θ`. The boundary points +are `B = P '' T` for a set `T ⊆ [0, 3)` of `3n + 3` parameters, `n + 2` on each closed side +(`exists_T`). For parameters `a < b < c` not all on one side, the signed area +`D (P a) (P b) (P c)` is positive (`E_pos`, a short computation on each pattern of sides). Hence +a chord `[P a, P b]` (`a < b` not on a common side) has the boundary points with parameters in +`(a, b)` strictly on one side and the others strictly on the other side; its relative interior +lies in the interior of the triangle; two chords meet in the interior iff their parameters +interleave (`X_mem`, `crossR_of_mem`), and then in exactly one point. + +*Vertices and edges.* Using general position, the vertices on a chord `c` are its two endpoints +and one crossing point for each chord crossing `c`, all distinct (`V_chord`, `VC_card`); the +vertices on a side are the points of `B` on it (`V_side`, which also uses that two pieces of a +side meeting in a single point meet at a point of `B`, `oneD`). The edges are the consecutive +pairs of vertices on the three sides and on the chords, and these families are disjoint +(`edgeSet_eq`, `EF_card`). So the number of edges is +`3(n + 1) + #chords + ∑_c #(chords crossing c)` (`edges_eq`). + +*Counting.* There are `3n(n + 1)` chords (`chords_card`). Crossing pairs of chords correspond to +the 4-subsets of `T` with no three points on a side (the two diagonals of the sorted quadruple, +`crossH_card`, `diag_iff`), and inclusion-exclusion gives +`C(3n+3, 4) - 3((2n+1) C(n+2, 3) + C(n+2, 4)) = (3/4) n^2 (n+1)(3n+1)` of them +(`crossings_formula`). Adding up gives the formula. +-/ + +namespace Math0.Frontier.A367119 +open Math0.Statements.A367119 + +/-- Twice the signed area of the triangle `a b c`. -/ +private noncomputable def D (a b c : ℂ) : ℝ := (b - a).re * (c - a).im - (b - a).im * (c - a).re + +/-- The signed area vanishes when the third point is the first. -/ +private lemma D_left (a b : ℂ) : D a b a = 0 := by simp [D] + +/-- The signed area vanishes when the third point is the second. -/ +private lemma D_right (a b : ℂ) : D a b b = 0 := by simp only [D]; ring + +/-- `D a b` is affine in its third argument. -/ +private lemma D_comb (a b p q : ℂ) (s t : ℝ) (h : s + t = 1) : + D a b (s • p + t • q) = s * D a b p + t * D a b q := by + have hs : s = 1 - t := by linarith + subst hs + simp only [D, Complex.sub_re, Complex.sub_im, Complex.add_re, Complex.add_im, + Complex.smul_re, Complex.smul_im, smul_eq_mul] + ring + +/-- A point of the segment `[a, b]` lies on the line `ab`. -/ +private lemma D_of_mem_segment {a b z : ℂ} (h : z ∈ segment ℝ a b) : D a b z = 0 := by + obtain ⟨s, t, -, -, hst, rfl⟩ := h + rw [D_comb _ _ _ _ _ _ hst, D_left, D_right]; ring + +/-- If `c` is not on the line `ab`, the segments `[a, b]` and `[c, d]` meet in at most one point. -/ +private lemma seg_inter_sub {a b c d z z' : ℂ} (hc : D a b c ≠ 0) (hz1 : z ∈ segment ℝ a b) + (hz2 : z ∈ segment ℝ c d) (hz1' : z' ∈ segment ℝ a b) (hz2' : z' ∈ segment ℝ c d) : + z = z' := by + have e1 := D_of_mem_segment hz1 + have e2 := D_of_mem_segment hz1' + obtain ⟨s, t, -, -, hst, rfl⟩ := hz2 + obtain ⟨s', t', -, -, hst', rfl⟩ := hz2' + rw [D_comb _ _ _ _ _ _ hst] at e1 + rw [D_comb _ _ _ _ _ _ hst'] at e2 + have htt : t = t' := by + by_contra hne + have hm : (t - t') * (D a b d - D a b c) = 0 := by + have hs : s = 1 - t := by linarith + have hs' : s' = 1 - t' := by linarith + subst hs hs' + linear_combination e1 - e2 + rcases mul_eq_zero.1 hm with h | h + · exact hne (by linarith) + · apply hc + have hs : s = 1 - t := by linarith + subst hs + have : D a b d = D a b c := by linarith + rw [this] at e1 + linarith + have hss : s = s' := by linarith + rw [htt, hss] + +/-- `D a b` is positive on an open segment whose endpoints have nonnegative values, not both +zero. -/ +private lemma openSeg_pos {a b c d z : ℂ} (hc : 0 ≤ D a b c) (hd : 0 ≤ D a b d) + (h : 0 < D a b c ∨ 0 < D a b d) (hz : z ∈ openSegment ℝ c d) : 0 < D a b z := by + obtain ⟨s, t, hs, ht, hst, rfl⟩ := hz + rw [D_comb _ _ _ _ _ _ hst] + rcases h with h | h + · have := mul_pos hs h + have := mul_nonneg ht.le hd + linarith + · have := mul_pos ht h + have := mul_nonneg hs.le hc + linarith + +/-- `D a b` is positive on a segment whose endpoints have positive values. -/ +private lemma seg_pos {a b c d z : ℂ} (hc : 0 < D a b c) (hd : 0 < D a b d) + (hz : z ∈ segment ℝ c d) : 0 < D a b z := by + obtain ⟨s, t, hs, ht, hst, rfl⟩ := hz + rw [D_comb _ _ _ _ _ _ hst] + rcases eq_or_lt_of_le hs with h | h + · subst h + have : t = 1 := by linarith + subst this; linarith + · have := mul_pos h hc + have := mul_nonneg ht hd.le + linarith + +/-- `D a b` is negative on a segment whose endpoints have negative values. -/ +private lemma seg_neg {a b c d z : ℂ} (hc : D a b c < 0) (hd : D a b d < 0) + (hz : z ∈ segment ℝ c d) : D a b z < 0 := by + obtain ⟨s, t, hs, ht, hst, rfl⟩ := hz + rw [D_comb _ _ _ _ _ _ hst] + rcases eq_or_lt_of_le hs with h | h + · subst h + have : t = 1 := by linarith + subst this; linarith + · have := mul_neg_of_pos_of_neg h hc + have := mul_nonpos_of_nonneg_of_nonpos ht hd.le + linarith + +/-- The intersection point of the lines `ab` and `cd`. -/ +private noncomputable def crossPt (a b c d : ℂ) : ℂ := + (1 / (D a b c - D a b d)) • ((D a b c) • d - (D a b d) • c) + +/-- Coefficients of the intersection point of two crossing segments. -/ +private lemma opp_coeffs {x y : ℝ} (h : x * y < 0) : 0 < x / (x - y) ∧ 0 < -y / (x - y) := by + rcases lt_or_gt_of_ne (show x ≠ 0 by rintro rfl; simp at h) with hx | hx + · have hy : 0 < y := by nlinarith + have : x - y < 0 := by linarith + exact ⟨div_pos_of_neg_of_neg hx this, div_pos_of_neg_of_neg (by linarith) this⟩ + · have hy : y < 0 := by nlinarith + have : 0 < x - y := by linarith + exact ⟨div_pos hx this, div_pos (by linarith) this⟩ + +/-- If `c, d` are strictly on opposite sides of the line `ab` and vice versa, the two open +segments meet at `crossPt a b c d`. -/ +private lemma crossPt_mem {a b c d : ℂ} (h1 : D a b c * D a b d < 0) (h2 : D c d a * D c d b < 0) : + crossPt a b c d ∈ openSegment ℝ a b ∧ crossPt a b c d ∈ openSegment ℝ c d := by + have hne : D a b c - D a b d ≠ 0 := by + intro h; have : D a b c = D a b d := by linarith + rw [this] at h1; nlinarith + have hid : D c d b - D c d a = D a b c - D a b d := by + simp only [D, Complex.sub_re, Complex.sub_im]; ring + have hne' : D c d b - D c d a ≠ 0 := by rw [hid]; exact hne + constructor + · obtain ⟨p1, p2⟩ := opp_coeffs (show D c d b * D c d a < 0 by linarith) + refine ⟨D c d b / (D c d b - D c d a), -D c d a / (D c d b - D c d a), p1, p2, ?_, ?_⟩ + · field_simp; ring + · rw [hid] + simp only [D, Complex.sub_re, Complex.sub_im] at hne + apply Complex.ext <;> + · simp only [crossPt, D, Complex.add_re, Complex.add_im, Complex.smul_re, Complex.smul_im, + Complex.sub_re, Complex.sub_im, smul_eq_mul] + field_simp + ring + · obtain ⟨p1, p2⟩ := opp_coeffs h1 + refine ⟨-D a b d / (D a b c - D a b d), D a b c / (D a b c - D a b d), p2, p1, ?_, ?_⟩ + · field_simp; ring + · apply Complex.ext <;> + · simp only [crossPt, Complex.add_re, Complex.add_im, Complex.smul_re, Complex.smul_im, + Complex.sub_re, Complex.sub_im, smul_eq_mul] + field_simp + ring + +/-! ### The boundary parametrization -/ + +/-- The real part of the boundary point with parameter `t`. -/ +private noncomputable def xP (t : ℝ) : ℝ := if t ≤ 1 then t else (3 - t) / 2 +/-- The imaginary part, divided by `√3`, of the boundary point with parameter `t`. -/ +private noncomputable def yP (t : ℝ) : ℝ := + if t ≤ 1 then 0 else if t ≤ 2 then (t - 1) / 2 else (3 - t) / 2 + +/-- The boundary point with parameter `t ∈ [0, 3)`. -/ +private noncomputable def P (t : ℝ) : ℂ := ⟨xP t, Real.sqrt 3 * yP t⟩ + +/-- `D (P a) (P b) (P c) / √3`. -/ +private noncomputable def E (a b c : ℝ) : ℝ := + (xP b - xP a) * (yP c - yP a) - (yP b - yP a) * (xP c - xP a) + +/-- The signed area of three boundary points. -/ +private lemma D_P (a b c : ℝ) : D (P a) (P b) (P c) = Real.sqrt 3 * E a b c := by + simp only [D, P, E, Complex.sub_re, Complex.sub_im]; ring + +/-- `E` is invariant under cyclic permutation. -/ +private lemma E_cyc (a b c : ℝ) : E a b c = E b c a := by simp only [E]; ring +/-- `E` changes sign when the last two arguments are swapped. -/ +private lemma E_swap (a b c : ℝ) : E a b c = - E a c b := by simp only [E]; ring + +/-- `xP` on the parameter range of side 0. -/ +private lemma xP_A {t : ℝ} (h : t ≤ 1) : xP t = t := by simp [xP, h] +/-- `yP` on the parameter range of side 0. -/ +private lemma yP_A {t : ℝ} (h : t ≤ 1) : yP t = 0 := by simp [yP, h] +/-- `xP` on the parameter range of sides 1 and 2. -/ +private lemma xP_B {t : ℝ} (h : 1 < t) : xP t = (3 - t) / 2 := by simp [xP, not_le.2 h] +/-- `yP` on the parameter range of side 1. -/ +private lemma yP_B {t : ℝ} (h : 1 < t) (h' : t ≤ 2) : yP t = (t - 1) / 2 := by + simp [yP, not_le.2 h, h'] +/-- `yP` on the parameter range of side 2. -/ +private lemma yP_C {t : ℝ} (h : 2 < t) : yP t = (3 - t) / 2 := by + simp [yP, not_le.2 h, not_le.2 (by linarith : (1:ℝ) < t)] + +/-- The parameter `t ∈ [0, 3)` belongs to the closed side 0. -/ +private def S0 (t : ℝ) : Prop := t ≤ 1 +/-- The parameter `t ∈ [0, 3)` belongs to the closed side 1. -/ +private def S1 (t : ℝ) : Prop := 1 ≤ t ∧ t ≤ 2 +/-- The parameter `t ∈ [0, 3)` belongs to the closed side 2 (which contains the corner `0`). -/ +private def S2 (t : ℝ) : Prop := 2 ≤ t ∨ t = 0 + +/-- Decidability of `S0`. -/ +private noncomputable instance : DecidablePred S0 := fun t => by unfold S0; infer_instance +/-- Decidability of `S1`. -/ +private noncomputable instance : DecidablePred S1 := fun t => by unfold S1; infer_instance +/-- Decidability of `S2`. -/ +private noncomputable instance : DecidablePred S2 := fun t => by unfold S2; infer_instance + +/-- Two parameters lie on a common closed side. -/ +private def coSide (a b : ℝ) : Prop := (S0 a ∧ S0 b) ∨ (S1 a ∧ S1 b) ∨ (S2 a ∧ S2 b) +/-- Three parameters lie on a common closed side. -/ +private def coSide3 (a b c : ℝ) : Prop := + (S0 a ∧ S0 b ∧ S0 c) ∨ (S1 a ∧ S1 b ∧ S1 c) ∨ (S2 a ∧ S2 b ∧ S2 c) + +/-- Orientation of three boundary points in increasing parameter order. -/ +private lemma E_pos {a b c : ℝ} (ha : 0 ≤ a) (hab : a < b) (hbc : b < c) (hc : c < 3) + (h : ¬ coSide3 a b c) : 0 < E a b c := by + unfold coSide3 S0 S1 S2 at h + unfold E + rcases le_or_gt c 1 with hc1 | hc1 + · exact absurd (Or.inl ⟨by linarith, by linarith, hc1⟩) h + rcases le_or_gt c 2 with hc2 | hc2 + · rw [xP_B hc1, yP_B hc1 hc2] + rcases le_or_gt b 1 with hb1 | hb1 + · rw [xP_A hb1, yP_A hb1, xP_A (by linarith : a ≤ 1), yP_A (by linarith : a ≤ 1)] + nlinarith [mul_pos (sub_pos.2 hab) (sub_pos.2 hc1)] + · rw [xP_B hb1, yP_B hb1 (by linarith)] + rcases le_or_gt a 1 with ha1 | ha1 + · rw [xP_A ha1, yP_A ha1] + have ha1' : a < 1 := by + rcases lt_or_eq_of_le ha1 with h1 | h1 + · exact h1 + · exact absurd (Or.inr (Or.inl ⟨⟨h1.ge, by linarith⟩, ⟨by linarith, by linarith⟩, + ⟨by linarith, hc2⟩⟩)) h + nlinarith [mul_pos (sub_pos.2 hbc) (sub_pos.2 ha1')] + · exact absurd (Or.inr (Or.inl ⟨⟨ha1.le, by linarith⟩, ⟨by linarith, by linarith⟩, + ⟨by linarith, hc2⟩⟩)) h + · rw [xP_B hc1, yP_C hc2] + rcases le_or_gt b 1 with hb1 | hb1 + · rw [xP_A hb1, yP_A hb1, xP_A (by linarith : a ≤ 1), yP_A (by linarith : a ≤ 1)] + nlinarith [mul_pos (sub_pos.2 hab) (sub_pos.2 hc)] + rcases le_or_gt b 2 with hb2 | hb2 + · rw [xP_B hb1, yP_B hb1 hb2] + rcases le_or_gt a 1 with ha1 | ha1 + · rw [xP_A ha1, yP_A ha1] + rcases eq_or_lt_of_le ha with h0 | h0 + · have hb2' : b < 2 := by + rcases lt_or_eq_of_le hb2 with h2 | h2 + · exact h2 + · exact absurd (Or.inr (Or.inr ⟨Or.inr h0.symm, Or.inl h2.ge, Or.inl hc2.le⟩)) h + rw [← h0] + nlinarith [mul_pos (sub_pos.2 hb2') (sub_pos.2 hc)] + · nlinarith [mul_pos (mul_pos h0 (sub_pos.2 hb1)) (sub_pos.2 hc2), + mul_nonneg (mul_nonneg (sub_nonneg.2 hb2) (sub_nonneg.2 hc.le)) (sub_nonneg.2 ha1)] + · rw [xP_B ha1, yP_B ha1 (by linarith)] + nlinarith [mul_pos (sub_pos.2 hab) (sub_pos.2 hc2)] + · rw [xP_B hb1, yP_C hb2] + rcases le_or_gt a 1 with ha1 | ha1 + · rw [xP_A ha1, yP_A ha1] + have h0 : 0 < a := by + rcases eq_or_lt_of_le ha with h0 | h0 + · exact absurd (Or.inr (Or.inr ⟨Or.inr h0.symm, Or.inl hb2.le, Or.inl hc2.le⟩)) h + · exact h0 + nlinarith [mul_pos h0 (sub_pos.2 hbc)] + rcases le_or_gt a 2 with ha2 | ha2 + · rw [xP_B ha1, yP_B ha1 ha2] + have ha2' : a < 2 := by + rcases lt_or_eq_of_le ha2 with h2 | h2 + · exact h2 + · exact absurd (Or.inr (Or.inr ⟨Or.inl h2.ge, Or.inl hb2.le, Or.inl hc2.le⟩)) h + nlinarith [mul_pos (sub_pos.2 hbc) (sub_pos.2 ha2')] + · exact absurd (Or.inr (Or.inr ⟨Or.inl ha2.le, Or.inl hb2.le, Or.inl hc2.le⟩)) h + +/-- The corner `0`. -/ +private lemma corner_zero : corner 0 = 0 := by simp [corner] +/-- The corner `1`. -/ +private lemma corner_one : corner 1 = 1 := by simp [corner] +/-- The corner `1/2 + (√3/2) i`. -/ +private lemma corner_two : corner 2 = ⟨1 / 2, Real.sqrt 3 / 2⟩ := by simp [corner] + +/-- The parameter `0` gives the corner `0`. -/ +private lemma P_zero : P 0 = corner 0 := by + rw [corner_zero]; apply Complex.ext <;> simp [P, xP, yP] +/-- The parameter `1` gives the corner `1`. -/ +private lemma P_one : P 1 = corner 1 := by + rw [corner_one]; apply Complex.ext <;> simp [P, xP, yP] +/-- The parameter `2` gives the corner `2`. -/ +private lemma P_two : P 2 = corner 2 := by + rw [corner_two]; apply Complex.ext <;> norm_num [P, xP, yP] + ring + +/-- `√3 > 0`. -/ +private lemma sqrt3_pos : 0 < Real.sqrt 3 := Real.sqrt_pos.2 (by norm_num) + +/-- The parameter of a boundary point. -/ +private noncomputable def θ (z : ℂ) : ℝ := if z.im = 0 then z.re else 3 - 2 * z.re + +/-- `yP` is positive off side 0. -/ +private lemma yP_pos {t : ℝ} (h1 : 1 < t) (h3 : t < 3) : 0 < yP t := by + rcases le_or_gt t 2 with h2 | h2 + · rw [yP_B h1 h2]; linarith + · rw [yP_C h2]; linarith + +/-- `yP` is nonnegative. -/ +private lemma yP_nonneg {t : ℝ} (h3 : t < 3) : 0 ≤ yP t := by + rcases le_or_gt t 1 with h1 | h1 + · rw [yP_A h1] + · exact (yP_pos h1 h3).le + +/-- `θ` inverts `P` on `[0, 3)`. -/ +private lemma θ_P {t : ℝ} (_h0 : 0 ≤ t) (h3 : t < 3) : θ (P t) = t := by + unfold θ + rcases le_or_gt t 1 with h1 | h1 + · have : (P t).im = 0 := by simp [P, yP_A h1] + rw [if_pos this]; simp [P, xP_A h1] + · have : (P t).im ≠ 0 := by + simp only [P] + exact (mul_pos sqrt3_pos (yP_pos h1 h3)).ne' + rw [if_neg this]; simp only [P, xP_B h1]; ring + +/-- `P` is injective on `[0, 3)`. -/ +private lemma P_inj {s t : ℝ} (hs0 : 0 ≤ s) (hs3 : s < 3) (ht0 : 0 ≤ t) (ht3 : t < 3) + (h : P s = P t) : s = t := by + rw [← θ_P hs0 hs3, ← θ_P ht0 ht3, h] + +/-! ### Corner lines -/ + +/-- The line through the corners `0` and `1` at a boundary point. -/ +private lemma D01 (t : ℝ) : D (corner 0) (corner 1) (P t) = Real.sqrt 3 * yP t := by + rw [← P_zero, ← P_one, D_P] + congr 1 + simp only [E, xP_A (show (0:ℝ) ≤ 1 by norm_num), yP_A (show (0:ℝ) ≤ 1 by norm_num), + xP_A (show (1:ℝ) ≤ 1 by norm_num), yP_A (show (1:ℝ) ≤ 1 by norm_num)] + ring + +/-- The line through the corners `1` and `2` at a boundary point. -/ +private lemma D12 (t : ℝ) : + D (corner 1) (corner 2) (P t) = Real.sqrt 3 * ((1 - xP t - yP t) / 2) := by + rw [← P_one, ← P_two, D_P] + congr 1 + simp only [E, xP_A (show (1:ℝ) ≤ 1 by norm_num), yP_A (show (1:ℝ) ≤ 1 by norm_num), + xP_B (show (1:ℝ) < 2 by norm_num), yP_B (show (1:ℝ) < 2 by norm_num) (le_refl _)] + ring + +/-- The line through the corners `2` and `0` at a boundary point. -/ +private lemma D20 (t : ℝ) : D (corner 2) (corner 0) (P t) = Real.sqrt 3 * ((xP t - yP t) / 2) := by + rw [← P_zero, ← P_two, D_P] + congr 1 + simp only [E, xP_A (show (0:ℝ) ≤ 1 by norm_num), yP_A (show (0:ℝ) ≤ 1 by norm_num), + xP_B (show (1:ℝ) < 2 by norm_num), yP_B (show (1:ℝ) < 2 by norm_num) (le_refl _)] + ring + +/-- Boundary points are on the inner side of side 0. -/ +private lemma L0_nonneg {t : ℝ} (_h0 : 0 ≤ t) (h3 : t < 3) : 0 ≤ yP t := yP_nonneg h3 + +/-- Boundary points off side 0 are strictly on its inner side. -/ +private lemma L0_pos_iff {t : ℝ} (_h0 : 0 ≤ t) (h3 : t < 3) : 0 < yP t ↔ ¬ S0 t := by + unfold S0 + constructor + · intro h h1; rw [yP_A h1] at h; exact lt_irrefl _ h + · intro h; exact yP_pos (not_le.1 h) h3 + +/-- Boundary points are on the inner side of side 1. -/ +private lemma L1_nonneg {t : ℝ} (_h0 : 0 ≤ t) (_h3 : t < 3) : 0 ≤ (1 - xP t - yP t) / 2 := by + rcases le_or_gt t 1 with h1 | h1 + · rw [xP_A h1, yP_A h1]; linarith + rcases le_or_gt t 2 with h2 | h2 + · rw [xP_B h1, yP_B h1 h2]; linarith + · rw [xP_B h1, yP_C h2]; linarith + +/-- Boundary points off side 1 are strictly on its inner side. -/ +private lemma L1_pos_iff {t : ℝ} (_h0 : 0 ≤ t) (h3 : t < 3) : + 0 < (1 - xP t - yP t) / 2 ↔ ¬ S1 t := by + unfold S1 + rcases le_or_gt t 1 with h1 | h1 + · rw [xP_A h1, yP_A h1] + constructor + · rintro h ⟨h1', -⟩; linarith + · intro h + have : t < 1 := by + rcases lt_or_eq_of_le h1 with h' | h' + · exact h' + · exact absurd ⟨h'.ge, by linarith⟩ h + linarith + rcases le_or_gt t 2 with h2 | h2 + · rw [xP_B h1, yP_B h1 h2] + constructor + · intro h; linarith + · intro h; exact absurd ⟨h1.le, h2⟩ h + · rw [xP_B h1, yP_C h2] + constructor + · rintro h ⟨-, h'⟩; linarith + · intro _; linarith + +/-- Boundary points are on the inner side of side 2. -/ +private lemma L2_nonneg {t : ℝ} (h0 : 0 ≤ t) (_h3 : t < 3) : 0 ≤ (xP t - yP t) / 2 := by + rcases le_or_gt t 1 with h1 | h1 + · rw [xP_A h1, yP_A h1]; linarith + rcases le_or_gt t 2 with h2 | h2 + · rw [xP_B h1, yP_B h1 h2]; linarith + · rw [xP_B h1, yP_C h2]; linarith + +/-- Boundary points off side 2 are strictly on its inner side. -/ +private lemma L2_pos_iff {t : ℝ} (h0 : 0 ≤ t) (_h3 : t < 3) : 0 < (xP t - yP t) / 2 ↔ ¬ S2 t := by + unfold S2 + rcases le_or_gt t 1 with h1 | h1 + · rw [xP_A h1, yP_A h1] + constructor + · rintro h (h' | h') <;> linarith + · intro h + have : t ≠ 0 := fun h' => h (Or.inr h') + have : 0 < t := lt_of_le_of_ne h0 (Ne.symm this) + linarith + rcases le_or_gt t 2 with h2 | h2 + · rw [xP_B h1, yP_B h1 h2] + constructor + · rintro h (h' | h') <;> linarith + · intro h + have : t < 2 := by + rcases lt_or_eq_of_le h2 with h' | h' + · exact h' + · exact absurd (Or.inl h'.ge) h + linarith + · rw [xP_B h1, yP_C h2] + constructor + · intro h; linarith + · intro h; exact absurd (Or.inl h2.le) h + +/-- The three corner-line functionals at boundary points. -/ +private lemma Dline_nonneg (j : Fin 3) {t : ℝ} (h0 : 0 ≤ t) (h3 : t < 3) : + 0 ≤ D (corner j) (corner (j + 1)) (P t) := by + fin_cases j + · show 0 ≤ D (corner 0) (corner 1) (P t) + rw [D01]; exact mul_nonneg sqrt3_pos.le (L0_nonneg h0 h3) + · show 0 ≤ D (corner 1) (corner 2) (P t) + rw [D12]; exact mul_nonneg sqrt3_pos.le (L1_nonneg h0 h3) + · show 0 ≤ D (corner 2) (corner 0) (P t) + rw [D20]; exact mul_nonneg sqrt3_pos.le (L2_nonneg h0 h3) + +/-- Side membership of a parameter. -/ +private def Sd : Fin 3 → ℝ → Prop + | ⟨0, _⟩, t => S0 t + | ⟨1, _⟩, t => S1 t + | ⟨2, _⟩, t => S2 t + +/-- Decidability of `Sd j`. -/ +private noncomputable instance (j : Fin 3) : DecidablePred (Sd j) := Classical.decPred _ + +/-- A boundary point is strictly inside the line of side `j` iff it is not on side `j`. -/ +private lemma Dline_pos_iff (j : Fin 3) {t : ℝ} (h0 : 0 ≤ t) (h3 : t < 3) : + 0 < D (corner j) (corner (j + 1)) (P t) ↔ ¬ Sd j t := by + fin_cases j + · show 0 < D (corner 0) (corner 1) (P t) ↔ ¬ S0 t + rw [D01, ← L0_pos_iff h0 h3] + exact ⟨fun h => pos_of_mul_pos_right h sqrt3_pos.le, fun h => mul_pos sqrt3_pos h⟩ + · show 0 < D (corner 1) (corner 2) (P t) ↔ ¬ S1 t + rw [D12, ← L1_pos_iff h0 h3] + exact ⟨fun h => pos_of_mul_pos_right h sqrt3_pos.le, fun h => mul_pos sqrt3_pos h⟩ + · show 0 < D (corner 2) (corner 0) (P t) ↔ ¬ S2 t + rw [D20, ← L2_pos_iff h0 h3] + exact ⟨fun h => pos_of_mul_pos_right h sqrt3_pos.le, fun h => mul_pos sqrt3_pos h⟩ + +/-- `coSide` in terms of the indexed side predicate. -/ +private lemma coSide_iff (a b : ℝ) : coSide a b ↔ ∃ j : Fin 3, Sd j a ∧ Sd j b := by + unfold coSide + constructor + · rintro (h | h | h) + · exact ⟨0, h⟩ + · exact ⟨1, h⟩ + · exact ⟨2, h⟩ + · rintro ⟨j, h⟩ + fin_cases j + · exact Or.inl h + · exact Or.inr (Or.inl h) + · exact Or.inr (Or.inr h) + +/-! ### Sides -/ + +/-- The closed side `j`. -/ +private def side (j : Fin 3) : Set ℂ := segment ℝ (corner j) (corner (j + 1)) + +/-- A parameter of side `j` gives a point of side `j`. -/ +private lemma P_mem_side {j : Fin 3} {t : ℝ} (h0 : 0 ≤ t) (h3 : t < 3) (h : Sd j t) : + P t ∈ side j := by + fin_cases j + · change S0 t at h; unfold S0 at h + change P t ∈ segment ℝ (corner 0) (corner 1) + rw [corner_zero, corner_one] + refine ⟨1 - t, t, by linarith, h0, by ring, ?_⟩ + apply Complex.ext <;> simp [P, xP_A h, yP_A h] + · change S1 t at h; unfold S1 at h + change P t ∈ segment ℝ (corner 1) (corner 2) + rw [corner_one, corner_two] + rcases eq_or_lt_of_le h.1 with h1 | h1 + · subst h1 + refine ⟨1, 0, by norm_num, le_refl _, by ring, ?_⟩ + apply Complex.ext <;> simp [P, xP, yP] + · refine ⟨2 - t, t - 1, by linarith, by linarith, by ring, ?_⟩ + apply Complex.ext <;> simp [P, xP_B h1, yP_B h1 h.2] <;> ring + · change S2 t at h; unfold S2 at h + change P t ∈ segment ℝ (corner 2) (corner 0) + rw [corner_two, corner_zero] + rcases h with h | h + · rcases eq_or_lt_of_le h with h2 | h2 + · subst h2 + refine ⟨1, 0, by norm_num, le_refl _, by ring, ?_⟩ + apply Complex.ext <;> norm_num [P, xP, yP] + ring + · refine ⟨3 - t, t - 2, by linarith, by linarith, by ring, ?_⟩ + apply Complex.ext <;> simp [P, xP_B (by linarith : (1:ℝ) < t), yP_C h2] <;> ring + · subst h + refine ⟨0, 1, le_refl _, by norm_num, by ring, ?_⟩ + apply Complex.ext <;> simp [P, xP, yP] + +/-- Every point of side `j` is `P t` for a parameter `t ∈ [0, 3)` of side `j`. -/ +private lemma exists_P_of_mem_side {j : Fin 3} {z : ℂ} (hz : z ∈ side j) : + ∃ t, 0 ≤ t ∧ t < 3 ∧ Sd j t ∧ P t = z := by + fin_cases j + · change z ∈ segment ℝ (corner 0) (corner 1) at hz + change ∃ t, 0 ≤ t ∧ t < 3 ∧ S0 t ∧ P t = z + rw [corner_zero, corner_one] at hz + obtain ⟨a, b, ha, hb, hab, rfl⟩ := hz + have hb1 : b ≤ 1 := by linarith + refine ⟨b, hb, by linarith, hb1, ?_⟩ + apply Complex.ext <;> simp [P, xP_A hb1, yP_A hb1] + · change z ∈ segment ℝ (corner 1) (corner 2) at hz + change ∃ t, 0 ≤ t ∧ t < 3 ∧ S1 t ∧ P t = z + rw [corner_one, corner_two] at hz + obtain ⟨a, b, ha, hb, hab, rfl⟩ := hz + refine ⟨1 + b, by linarith, by linarith, ⟨by linarith, by linarith⟩, ?_⟩ + rcases eq_or_lt_of_le hb with h0 | h0 + · subst h0 + have : a = 1 := by linarith + subst this + apply Complex.ext <;> simp [P, xP, yP] + · apply Complex.ext <;> + simp [P, xP_B (by linarith : (1:ℝ) < 1 + b), yP_B (by linarith : (1:ℝ) < 1 + b) + (by linarith : 1 + b ≤ 2)] <;> linarith + · change z ∈ segment ℝ (corner 2) (corner 0) at hz + change ∃ t, 0 ≤ t ∧ t < 3 ∧ S2 t ∧ P t = z + rw [corner_two, corner_zero] at hz + obtain ⟨a, b, ha, hb, hab, rfl⟩ := hz + rcases eq_or_lt_of_le ha with h0 | h0 + · subst h0 + have : b = 1 := by linarith + subst this + refine ⟨0, le_refl _, by norm_num, Or.inr rfl, ?_⟩ + apply Complex.ext <;> simp [P, xP, yP] + · refine ⟨3 - a, by linarith, by linarith, Or.inl (by linarith), ?_⟩ + rcases eq_or_lt_of_le (show a ≤ 1 by linarith) with h1 | h1 + · subst h1 + apply Complex.ext <;> norm_num [P, xP, yP] + ring + · apply Complex.ext <;> + simp [P, xP_B (by linarith : (1:ℝ) < 3 - a), yP_C (by linarith : (2:ℝ) < 3 - a)] <;> + ring + +/-- Points of side `j` lie on its line. -/ +private lemma Dline_zero_of_mem_side (j : Fin 3) {z : ℂ} (hz : z ∈ side j) : + D (corner j) (corner (j + 1)) z = 0 := D_of_mem_segment hz + +/-- `P t` lies on side `j` iff `t` is a parameter of side `j`. -/ +private lemma P_mem_side_iff {j : Fin 3} {t : ℝ} (h0 : 0 ≤ t) (h3 : t < 3) : + P t ∈ side j ↔ Sd j t := by + constructor + · intro h + by_contra hn + have := (Dline_pos_iff j h0 h3).2 hn + rw [Dline_zero_of_mem_side j h] at this + exact lt_irrefl _ this + · exact P_mem_side h0 h3 + +/-- Consecutive corners are distinct. -/ +private lemma corner_ne (j : Fin 3) : corner j ≠ corner (j + 1) := by + fin_cases j + · show corner 0 ≠ corner 1 + rw [corner_zero, corner_one]; exact zero_ne_one + · show corner 1 ≠ corner 2 + rw [corner_one, corner_two]; intro h + have := congrArg Complex.im h + simp at this; linarith [sqrt3_pos] + · show corner 2 ≠ corner 0 + rw [corner_two, corner_zero]; intro h + have := congrArg Complex.im h + simp at this + +/-- Points of the open side `j`. -/ +private def Od : Fin 3 → ℝ → Prop + | ⟨0, _⟩, t => 0 < t ∧ t < 1 + | ⟨1, _⟩, t => 1 < t ∧ t < 2 + | ⟨2, _⟩, t => 2 < t + +/-- Decidability of `Od j`. -/ +private noncomputable instance (j : Fin 3) : DecidablePred (Od j) := Classical.decPred _ + +/-- `P t` lies in the relative interior of side `j` iff `t` is in the open parameter interval of +side `j`. -/ +private lemma P_mem_openSide_iff {j : Fin 3} {t : ℝ} (h0 : 0 ≤ t) (h3 : t < 3) : + P t ∈ openSegment ℝ (corner j) (corner (j + 1)) ↔ Od j t := by + have hne := corner_ne j + constructor + · intro h + have hs : P t ∈ side j := openSegment_subset_segment _ _ _ h + rw [P_mem_side_iff h0 h3] at hs + have h1 : P t ≠ corner j := by + intro e; rw [e, left_mem_openSegment_iff] at h; exact hne h + have h2 : P t ≠ corner (j + 1) := by + intro e; rw [e, right_mem_openSegment_iff] at h; exact hne h + fin_cases j + · change S0 t at hs; unfold S0 at hs + change P t ≠ corner 0 at h1; change P t ≠ corner 1 at h2 + rw [← P_zero] at h1; rw [← P_one] at h2 + refine ⟨lt_of_le_of_ne h0 (fun e => h1 (by rw [← e])), lt_of_le_of_ne hs + (fun e => h2 (by rw [e]))⟩ + · change S1 t at hs; unfold S1 at hs + change P t ≠ corner 1 at h1; change P t ≠ corner 2 at h2 + rw [← P_one] at h1; rw [← P_two] at h2 + exact ⟨lt_of_le_of_ne hs.1 (fun e => h1 (by rw [← e])), lt_of_le_of_ne hs.2 + (fun e => h2 (by rw [e]))⟩ + · change S2 t at hs; unfold S2 at hs + change P t ≠ corner 2 at h1; change P t ≠ corner 0 at h2 + rw [← P_two] at h1; rw [← P_zero] at h2 + rcases hs with hs | hs + · exact lt_of_le_of_ne hs (fun e => h1 (by rw [← e])) + · exact absurd (by rw [hs]) h2 + · intro h + have hs : P t ∈ side j := by + apply P_mem_side h0 h3 + fin_cases j + · change 0 < t ∧ t < 1 at h; exact h.2.le + · change 1 < t ∧ t < 2 at h; exact ⟨h.1.le, h.2.le⟩ + · change 2 < t at h; exact Or.inl h.le + have hne1 : P t ≠ corner j := by + fin_cases j + · change 0 < t ∧ t < 1 at h; change P t ≠ corner 0 + rw [← P_zero]; intro e + exact absurd (P_inj h0 h3 (le_refl _) (by norm_num) e) (ne_of_gt h.1) + · change 1 < t ∧ t < 2 at h; change P t ≠ corner 1 + rw [← P_one]; intro e + exact absurd (P_inj h0 h3 (by norm_num) (by norm_num) e) (ne_of_gt h.1) + · change 2 < t at h; change P t ≠ corner 2 + rw [← P_two]; intro e + exact absurd (P_inj h0 h3 (by norm_num) (by norm_num) e) (ne_of_gt h) + have hne2 : P t ≠ corner (j + 1) := by + fin_cases j + · change 0 < t ∧ t < 1 at h; change P t ≠ corner 1 + rw [← P_one]; intro e + exact absurd (P_inj h0 h3 (by norm_num) (by norm_num) e) (ne_of_lt h.2) + · change 1 < t ∧ t < 2 at h; change P t ≠ corner 2 + rw [← P_two]; intro e + exact absurd (P_inj h0 h3 (by norm_num) (by norm_num) e) (ne_of_lt h.2) + · change 2 < t at h; change P t ≠ corner 0 + rw [← P_zero]; intro e + have := P_inj h0 h3 (le_refl _) (by norm_num) e + linarith + rw [side, ← insert_endpoints_openSegment] at hs + rcases hs with hs | hs | hs + · exact absurd hs hne1 + · exact absurd hs hne2 + · exact hs + +/-- Decidability of `coSide`. -/ +private noncomputable instance : DecidableRel coSide := fun a b => by unfold coSide; infer_instance + +/-- Two chords `(a, b)`, `(c, d)` (`a < b`, `c < d`) have interleaving endpoints. -/ +private def crossR (c d : ℝ × ℝ) : Prop := + (c.1 < d.1 ∧ d.1 < c.2 ∧ c.2 < d.2) ∨ (d.1 < c.1 ∧ c.1 < d.2 ∧ d.2 < c.2) + +/-- Decidability of `crossR c`. -/ +private noncomputable instance (c : ℝ × ℝ) : DecidablePred (crossR c) := fun d => by + unfold crossR; infer_instance + +/-- The chords: pairs of parameters `a < b` of `T` not on a common side. -/ +private noncomputable def Ch (T : Finset ℝ) : Finset (ℝ × ℝ) := + (T ×ˢ T).filter (fun p => p.1 < p.2 ∧ ¬ coSide p.1 p.2) + +/-- Membership in `Ch T`. -/ +private lemma mem_Ch {T : Finset ℝ} {c : ℝ × ℝ} : + c ∈ Ch T ↔ c.1 ∈ T ∧ c.2 ∈ T ∧ c.1 < c.2 ∧ ¬ coSide c.1 c.2 := by + simp only [Ch, Finset.mem_filter, Finset.mem_product, and_assoc] + +/-! ### The region index -/ + +/-- The region index of a parameter: `0`, `(0,1)`, `1`, `(1,2)`, `2`, `(2,3)` give `0, …, 5`. -/ +private noncomputable def ρ (t : ℝ) : ℕ := + if t ≤ 0 then 0 else if t < 1 then 1 else if t ≤ 1 then 2 else if t < 2 then 3 + else if t ≤ 2 then 4 else 5 + +/-- `S0` through the region index. -/ +private lemma ρ_S0 {t : ℝ} (_h : 0 ≤ t) : S0 t ↔ ρ t ≤ 2 := by + unfold S0 ρ + split_ifs <;> constructor <;> intro hh <;> + first | decide | (exfalso; linarith) | linarith + +/-- `S1` through the region index. -/ +private lemma ρ_S1 {t : ℝ} (_h : 0 ≤ t) : S1 t ↔ 2 ≤ ρ t ∧ ρ t ≤ 4 := by + unfold S1 ρ + split_ifs <;> constructor <;> intro hh <;> + first | decide | (exfalso; linarith [hh.1, hh.2]) | (constructor <;> linarith) + +/-- `S2` through the region index. -/ +private lemma ρ_S2 {t : ℝ} (h : 0 ≤ t) : S2 t ↔ 4 ≤ ρ t ∨ ρ t = 0 := by + unfold S2 ρ + split_ifs <;> constructor <;> intro hh <;> + first | decide | (exfalso; rcases hh with hh | hh <;> linarith) | (left; linarith) | + (right; linarith) | omega | simp_all + +/-- The region index is monotone, and constant only on open regions. -/ +private lemma ρ_mono {s t : ℝ} (hs : 0 ≤ s) (h : s < t) : + ρ s ≤ ρ t ∧ (ρ s = ρ t → ρ s = 1 ∨ ρ s = 3 ∨ ρ s = 5) := by + unfold ρ + split_ifs <;> first | decide | (exfalso; linarith) + +/-- Three of four elements satisfy `p`. -/ +private def three (p : ℝ → Prop) (w x y z : ℝ) : Prop := + (p w ∧ p x ∧ p y) ∨ (p w ∧ p x ∧ p z) ∨ (p w ∧ p y ∧ p z) ∨ (p x ∧ p y ∧ p z) + +/-- At least three of four sorted points satisfy `p` iff `three p` holds. -/ +private lemma three_le_card_filter (p : ℝ → Prop) [DecidablePred p] {w x y z : ℝ} + (h1 : w < x) (h2 : x < y) (h3 : y < z) : + 3 ≤ (({w, x, y, z} : Finset ℝ).filter p).card ↔ three p w x y z := by + have hwx : w ≠ x := ne_of_lt h1 + have hwy : w ≠ y := ne_of_lt (h1.trans h2) + have hwz : w ≠ z := ne_of_lt (h1.trans (h2.trans h3)) + have hxy : x ≠ y := ne_of_lt h2 + have hxz : x ≠ z := ne_of_lt (h2.trans h3) + have hyz : y ≠ z := ne_of_lt h3 + by_cases pw : p w <;> by_cases px : p x <;> by_cases py : p y <;> by_cases pz : p z <;> + simp [three, Finset.filter_insert, Finset.filter_singleton, pw, px, py, pz, hwx, hwy, hwz, + hxy, hxz, hyz] + +/-- Reduction of `three` to a statement about region indices. -/ +private lemma three_iff {w x y z : ℝ} (h0 : 0 ≤ w) (h1 : w < x) (h2 : x < y) (h3 : y < z) + (p : ℝ → Prop) (q : ℕ → Prop) (hpq : ∀ t, 0 ≤ t → (p t ↔ q (ρ t))) + (hq : ∀ a b c d : ℕ, a ≤ b → b ≤ c → c ≤ d → (a = b → a = 1 ∨ a = 3 ∨ a = 5) → + (b = c → b = 1 ∨ b = 3 ∨ b = 5) → (c = d → c = 1 ∨ c = 3 ∨ c = 5) → + (((q a ∧ q b ∧ q c) ∨ (q a ∧ q b ∧ q d) ∨ (q a ∧ q c ∧ q d) ∨ (q b ∧ q c ∧ q d)) ↔ + ((q a ∧ q c) ∨ (q b ∧ q d)))) : + three p w x y z ↔ (p w ∧ p y) ∨ (p x ∧ p z) := by + have hx : 0 ≤ x := by linarith + have hy : 0 ≤ y := by linarith + have hz : 0 ≤ z := by linarith + have m1 := ρ_mono h0 h1 + have m2 := ρ_mono hx h2 + have m3 := ρ_mono hy h3 + unfold three + rw [hpq w h0, hpq x hx, hpq y hy, hpq z hz] + exact hq _ _ _ _ m1.1 m2.1 m3.1 m1.2 m2.2 m3.2 + +/-- For a sorted quadruple, three points lie on side 0 iff one of the diagonals does. -/ +private lemma three_S0 {w x y z : ℝ} (h0 : 0 ≤ w) (h1 : w < x) (h2 : x < y) (h3 : y < z) : + three S0 w x y z ↔ (S0 w ∧ S0 y) ∨ (S0 x ∧ S0 z) := + three_iff h0 h1 h2 h3 S0 (fun r => r ≤ 2) (fun t ht => ρ_S0 ht) (by intros; omega) + +/-- For a sorted quadruple, three points lie on side 1 iff one of the diagonals does. -/ +private lemma three_S1 {w x y z : ℝ} (h0 : 0 ≤ w) (h1 : w < x) (h2 : x < y) (h3 : y < z) : + three S1 w x y z ↔ (S1 w ∧ S1 y) ∨ (S1 x ∧ S1 z) := + three_iff h0 h1 h2 h3 S1 (fun r => 2 ≤ r ∧ r ≤ 4) (fun t ht => ρ_S1 ht) (by intros; omega) + +/-- For a sorted quadruple, three points lie on side 2 iff one of the diagonals does. -/ +private lemma three_S2 {w x y z : ℝ} (h0 : 0 ≤ w) (h1 : w < x) (h2 : x < y) (h3 : y < z) : + three S2 w x y z ↔ (S2 w ∧ S2 y) ∨ (S2 x ∧ S2 z) := + three_iff h0 h1 h2 h3 S2 (fun r => 4 ≤ r ∨ r = 0) (fun t ht => ρ_S2 ht) (by intros; omega) + +/-- For a sorted quadruple, both diagonals are chords iff no three points share a side. -/ +private lemma diag_iff {w x y z : ℝ} (h0 : 0 ≤ w) (h1 : w < x) (h2 : x < y) (h3 : y < z) : + (¬ coSide w y ∧ ¬ coSide x z) ↔ + ¬ three S0 w x y z ∧ ¬ three S1 w x y z ∧ ¬ three S2 w x y z := by + rw [three_S0 h0 h1 h2 h3, three_S1 h0 h1 h2 h3, three_S2 h0 h1 h2 h3] + unfold coSide + tauto + +/-- Generalized Vandermonde count. -/ +private lemma card_filter_card_eq {α : Type*} [DecidableEq α] (U : Finset α) (p : α → Prop) + [DecidablePred p] (k m : ℕ) (hm : m ≤ k) : + ((U.powersetCard k).filter (fun Q => (Q.filter p).card = m)).card = + (U.filter p).card.choose m * (U.filter (fun x => ¬ p x)).card.choose (k - m) := by + rw [← Finset.card_powersetCard m (U.filter p), + ← Finset.card_powersetCard (k - m) (U.filter (fun x => ¬ p x)), ← Finset.card_product] + symm + apply Finset.card_nbij' (fun AR => AR.1 ∪ AR.2) + (fun Q => (Q.filter p, Q.filter (fun x => ¬ p x))) + · rintro ⟨A, R⟩ h + simp only [Finset.coe_product, Set.mem_prod, Finset.mem_coe, Finset.mem_powersetCard, + Finset.subset_iff, Finset.mem_filter] at h + obtain ⟨⟨hA, hAc⟩, ⟨hR, hRc⟩⟩ := h + have hdis : Disjoint A R := by + rw [Finset.disjoint_left]; intro x hx hx'; exact (hR hx').2 (hA hx).2 + have hfA : (A ∪ R).filter p = A := by + ext x; simp only [Finset.mem_filter, Finset.mem_union] + constructor + · rintro ⟨hx | hx, hp⟩ + · exact hx + · exact absurd hp (hR hx).2 + · intro hx; exact ⟨Or.inl hx, (hA hx).2⟩ + simp only [Finset.coe_filter, Set.mem_ofPred_eq, Finset.mem_powersetCard, Finset.subset_iff, + Finset.mem_union, hfA, hAc, and_true] + refine ⟨?_, ?_⟩ + · rintro x (hx | hx) + · exact (hA hx).1 + · exact (hR hx).1 + · rw [Finset.card_union_of_disjoint hdis, hAc, hRc]; omega + · intro Q hQ + simp only [Finset.coe_filter, Set.mem_ofPred_eq, Finset.mem_powersetCard] at hQ + obtain ⟨⟨hQU, hQc⟩, hQm⟩ := hQ + have := Finset.card_filter_add_card_filter_not (s := Q) p + simp only [Finset.coe_product, Set.mem_prod, Finset.mem_coe, Finset.mem_powersetCard] + refine ⟨⟨Finset.filter_subset_filter _ hQU, hQm⟩, Finset.filter_subset_filter _ hQU, ?_⟩ + omega + · rintro ⟨A, R⟩ h + simp only [Finset.coe_product, Set.mem_prod, Finset.mem_coe, Finset.mem_powersetCard, + Finset.subset_iff, Finset.mem_filter] at h + obtain ⟨⟨hA, -⟩, ⟨hR, -⟩⟩ := h + simp only [Prod.mk.injEq] + constructor + · ext x; simp only [Finset.mem_filter, Finset.mem_union] + constructor + · rintro ⟨hx | hx, hp⟩ + · exact hx + · exact absurd hp (hR hx).2 + · intro hx; exact ⟨Or.inl hx, (hA hx).2⟩ + · ext x; simp only [Finset.mem_filter, Finset.mem_union] + constructor + · rintro ⟨hx | hx, hp⟩ + · exact absurd (hA hx).2 hp + · exact hx + · intro hx; exact ⟨Or.inr hx, (hR hx).2⟩ + · intro Q _ + exact Finset.filter_union_filter_not_eq _ _ + +/-- The 4-subsets of `T` with no three points on a common side. -/ +private noncomputable def good4 (T : Finset ℝ) : Finset (Finset ℝ) := + (((T.powersetCard 4).filter (fun Q => ¬ 3 ≤ (Q.filter S0).card)).filter + (fun Q => ¬ 3 ≤ (Q.filter S1).card)).filter (fun Q => ¬ 3 ≤ (Q.filter S2).card) + +/-- Pairs of chords `(w, y)`, `(x, z)` with `w < x < y < z`. -/ +private noncomputable def crossH (T : Finset ℝ) : Finset ((ℝ × ℝ) × (ℝ × ℝ)) := + ((Ch T) ×ˢ (Ch T)).filter (fun p => p.1.1 < p.2.1 ∧ p.2.1 < p.1.2 ∧ p.1.2 < p.2.2) + +/-- Four sorted reals form a 4-set. -/ +private lemma card_four {w x y z : ℝ} (h1 : w < x) (h2 : x < y) (h3 : y < z) : + ({w, x, y, z} : Finset ℝ).card = 4 := by + have hwx : w ≠ x := ne_of_lt h1 + have hwy : w ≠ y := ne_of_lt (h1.trans h2) + have hwz : w ≠ z := ne_of_lt (h1.trans (h2.trans h3)) + have hxy : x ≠ y := ne_of_lt h2 + have hxz : x ≠ z := ne_of_lt (h2.trans h3) + have hyz : y ≠ z := ne_of_lt h3 + simp [hwx, hwy, hwz, hxy, hxz, hyz] + +/-- Crossing pairs of chords correspond to 4-subsets with no three points on a side. -/ +private lemma crossH_card (T : Finset ℝ) (hT : ∀ t ∈ T, 0 ≤ t) : + (crossH T).card = (good4 T).card := by + classical + apply Finset.card_nbij' (fun p => ({p.1.1, p.2.1, p.1.2, p.2.2} : Finset ℝ)) + (fun Q => if h : Q.card = 4 then ((Q.orderEmbOfFin h 0, Q.orderEmbOfFin h 2), + (Q.orderEmbOfFin h 1, Q.orderEmbOfFin h 3)) else ((0, 0), (0, 0))) + · rintro ⟨⟨w, y⟩, ⟨x, z⟩⟩ hp + simp only [crossH, Finset.coe_filter, Finset.mem_product, mem_Ch, + Set.mem_ofPred_eq] at hp + obtain ⟨⟨⟨hw, hy, -, hwy⟩, ⟨hx, hz, -, hxz⟩⟩, h1, h2, h3⟩ := hp + have hd := (diag_iff (hT w hw) h1 h2 h3).1 ⟨hwy, hxz⟩ + simp only [good4, Finset.coe_filter, Finset.mem_filter, Finset.mem_powersetCard, + Set.mem_ofPred_eq] + rw [three_le_card_filter _ h1 h2 h3, three_le_card_filter _ h1 h2 h3, + three_le_card_filter _ h1 h2 h3, card_four h1 h2 h3] + refine ⟨⟨⟨⟨?_, rfl⟩, hd.1⟩, hd.2.1⟩, hd.2.2⟩ + intro a ha + simp only [Finset.mem_insert, Finset.mem_singleton] at ha + rcases ha with rfl | rfl | rfl | rfl <;> assumption + · intro Q hQ + simp only [good4, Finset.coe_filter, Finset.mem_filter, Finset.mem_powersetCard, + Set.mem_ofPred_eq] at hQ + obtain ⟨⟨⟨⟨hQU, hc⟩, g0⟩, g1⟩, g2⟩ := hQ + simp only [hc, dite_true] + set f := Q.orderEmbOfFin hc + have m01 : f 0 < f 1 := f.strictMono (by decide) + have m12 : f 1 < f 2 := f.strictMono (by decide) + have m23 : f 2 < f 3 := f.strictMono (by decide) + have hmem : ∀ i, f i ∈ T := fun i => hQU (Finset.orderEmbOfFin_mem Q hc i) + have hQ : Q = {f 0, f 1, f 2, f 3} := by + symm + apply Finset.eq_of_subset_of_card_le + · intro a ha + simp only [Finset.mem_insert, Finset.mem_singleton] at ha + rcases ha with rfl | rfl | rfl | rfl <;> exact Finset.orderEmbOfFin_mem Q hc _ + · rw [hc, card_four m01 m12 m23] + rw [hQ, three_le_card_filter _ m01 m12 m23] at g0 g1 g2 + have hd := (diag_iff (hT _ (hmem 0)) m01 m12 m23).2 ⟨g0, g1, g2⟩ + simp only [crossH, Finset.coe_filter, Finset.mem_product, mem_Ch, Set.mem_ofPred_eq] + exact ⟨⟨⟨hmem 0, hmem 2, m01.trans m12, hd.1⟩, ⟨hmem 1, hmem 3, m12.trans m23, hd.2⟩⟩, + m01, m12, m23⟩ + · rintro ⟨⟨w, y⟩, ⟨x, z⟩⟩ hp + simp only [crossH, Finset.coe_filter, Finset.mem_product, mem_Ch, + Set.mem_ofPred_eq] at hp + obtain ⟨-, h1, h2, h3⟩ := hp + have hc := card_four h1 h2 h3 + simp only [hc, dite_true] + have hu := Finset.orderEmbOfFin_unique hc (f := ![w, x, y, z]) (by + intro i; fin_cases i <;> simp) (by + rw [Fin.strictMono_iff_lt_succ] + intro i; fin_cases i <;> simp <;> linarith) + rw [← hu] + rfl + · intro Q hQ + simp only [good4, Finset.coe_filter, Finset.mem_filter, Finset.mem_powersetCard, + Set.mem_ofPred_eq] at hQ + obtain ⟨⟨⟨⟨hQU, hc⟩, -⟩, -⟩, -⟩ := hQ + simp only [hc, dite_true] + set f := Q.orderEmbOfFin hc + have m01 : f 0 < f 1 := f.strictMono (by decide) + have m12 : f 1 < f 2 := f.strictMono (by decide) + have m23 : f 2 < f 3 := f.strictMono (by decide) + apply Finset.eq_of_subset_of_card_le + · intro a ha + simp only [Finset.mem_insert, Finset.mem_singleton] at ha + rcases ha with rfl | rfl | rfl | rfl <;> exact Finset.orderEmbOfFin_mem Q hc _ + · rw [hc, card_four m01 m12 m23] + +/-- The number of 4-subsets with at least three points on a set of `n + 2` points. -/ +private lemma bad_card (n : ℕ) (U : Finset ℝ) (hU : U.card = 3 * n + 3) (p : ℝ → Prop) + [DecidablePred p] (hp : (U.filter p).card = n + 2) : + ((U.powersetCard 4).filter (fun Q => 3 ≤ (Q.filter p).card)).card + = (n + 2).choose 3 * (2 * n + 1) + (n + 2).choose 4 := by + have hnp : (U.filter (fun x => ¬ p x)).card = 2 * n + 1 := by + have := Finset.card_filter_add_card_filter_not (s := U) p + rw [hU, hp] at this + omega + have e : (U.powersetCard 4).filter (fun Q => 3 ≤ (Q.filter p).card) = + ((U.powersetCard 4).filter (fun Q => (Q.filter p).card = 3)) ∪ + ((U.powersetCard 4).filter (fun Q => (Q.filter p).card = 4)) := by + ext Q + simp only [Finset.mem_filter, Finset.mem_union, Finset.mem_powersetCard] + constructor + · rintro ⟨⟨h1, h2⟩, h3⟩ + have : (Q.filter p).card ≤ 4 := h2 ▸ Finset.card_filter_le _ _ + refine (show (Q.filter p).card = 3 ∨ (Q.filter p).card = 4 by omega).imp ?_ ?_ <;> + exact fun h => ⟨⟨h1, h2⟩, h⟩ + · rintro (⟨h1, h2⟩ | ⟨h1, h2⟩) <;> exact ⟨h1, by omega⟩ + rw [e, Finset.card_union_of_disjoint, card_filter_card_eq _ _ _ _ (by norm_num), + card_filter_card_eq _ _ _ _ (by norm_num), hp, hnp] + · simp + · rw [Finset.disjoint_left] + intro Q h1 h2 + simp only [Finset.mem_filter] at h1 h2 + omega + +/-- A 4-set cannot have three points on each of two sides. -/ +private lemma not_both_bad {Q : Finset ℝ} (hQ : Q.card = 4) (p q : ℝ → Prop) [DecidablePred p] + [DecidablePred q] (c : ℝ) (hpq : ∀ x, p x → q x → x = c) : + ¬ (3 ≤ (Q.filter p).card ∧ 3 ≤ (Q.filter q).card) := by + rintro ⟨h1, h2⟩ + have hu : (Q.filter p ∪ Q.filter q).card ≤ 4 := + hQ ▸ Finset.card_le_card (Finset.union_subset (Finset.filter_subset _ _) + (Finset.filter_subset _ _)) + have hi : (Q.filter p ∩ Q.filter q).card ≤ 1 := by + calc (Q.filter p ∩ Q.filter q).card ≤ ({c} : Finset ℝ).card := by + apply Finset.card_le_card + intro x hx + simp only [Finset.mem_inter, Finset.mem_filter] at hx + simp [hpq x hx.1.2 hx.2.2] + _ = 1 := Finset.card_singleton c + have := Finset.card_union_add_card_inter (Q.filter p) (Q.filter q) + omega + +/-- Inclusion-exclusion for the 4-subsets with no three points on a side. -/ +private lemma good4_card (n : ℕ) (T : Finset ℝ) (hN : T.card = 3 * n + 3) + (c0 : (T.filter S0).card = n + 2) (c1 : (T.filter S1).card = n + 2) + (c2 : (T.filter S2).card = n + 2) : + (good4 T).card + 3 * ((n + 2).choose 3 * (2 * n + 1) + (n + 2).choose 4) = + (3 * n + 3).choose 4 := by + have b0 := bad_card n T hN S0 c0 + have b1 := bad_card n T hN S1 c1 + have b2 := bad_card n T hN S2 c2 + set P4 := T.powersetCard 4 + have t0 := Finset.card_filter_add_card_filter_not (s := P4) + (fun Q => 3 ≤ (Q.filter S0).card) + have t1 := Finset.card_filter_add_card_filter_not + (s := P4.filter (fun Q => ¬ 3 ≤ (Q.filter S0).card)) (fun Q => 3 ≤ (Q.filter S1).card) + have t2 := Finset.card_filter_add_card_filter_not + (s := (P4.filter (fun Q => ¬ 3 ≤ (Q.filter S0).card)).filter + (fun Q => ¬ 3 ≤ (Q.filter S1).card)) (fun Q => 3 ≤ (Q.filter S2).card) + have e1 : (P4.filter (fun Q => ¬ 3 ≤ (Q.filter S0).card)).filter + (fun Q => 3 ≤ (Q.filter S1).card) = P4.filter (fun Q => 3 ≤ (Q.filter S1).card) := by + ext Q + simp only [Finset.mem_filter, P4, Finset.mem_powersetCard] + constructor + · rintro ⟨⟨h, -⟩, h'⟩; exact ⟨h, h'⟩ + · rintro ⟨h, h'⟩ + refine ⟨⟨h, fun h0 => not_both_bad h.2 S0 S1 1 + (fun x a b => by unfold S0 at a; unfold S1 at b; linarith [b.1]) ⟨h0, h'⟩⟩, h'⟩ + have e2 : ((P4.filter (fun Q => ¬ 3 ≤ (Q.filter S0).card)).filter + (fun Q => ¬ 3 ≤ (Q.filter S1).card)).filter (fun Q => 3 ≤ (Q.filter S2).card) = + P4.filter (fun Q => 3 ≤ (Q.filter S2).card) := by + ext Q + simp only [Finset.mem_filter, P4, Finset.mem_powersetCard] + constructor + · rintro ⟨⟨⟨h, -⟩, -⟩, h'⟩; exact ⟨h, h'⟩ + · rintro ⟨h, h'⟩ + refine ⟨⟨⟨h, fun h0 => not_both_bad h.2 S0 S2 0 + (fun x a b => by + unfold S0 at a; unfold S2 at b + rcases b with b | b + · linarith + · exact b) ⟨h0, h'⟩⟩, + fun h1 => not_both_bad h.2 S1 S2 2 + (fun x a b => by + unfold S1 at a; unfold S2 at b + rcases b with b | b + · linarith [a.2] + · linarith [a.1]) ⟨h1, h'⟩⟩, h'⟩ + rw [e1] at t1 + rw [e2] at t2 + have hP4 : P4.card = (3 * n + 3).choose 4 := by + simp only [P4, Finset.card_powersetCard, hN] + have : good4 T = ((P4.filter (fun Q => ¬ 3 ≤ (Q.filter S0).card)).filter + (fun Q => ¬ 3 ≤ (Q.filter S1).card)).filter (fun Q => ¬ 3 ≤ (Q.filter S2).card) := + rfl + rw [this] + omega + +/-- The total number of crossings, counted from both chords, is twice the number of crossing +pairs. -/ +private lemma sum_crossers (T : Finset ℝ) : + ∑ c ∈ Ch T, ((Ch T).filter (fun d => crossR c d)).card = 2 * (crossH T).card := by + classical + have h1 : ∑ c ∈ Ch T, ((Ch T).filter (fun d => crossR c d)).card = + ((Ch T ×ˢ Ch T).filter (fun p => crossR p.1 p.2)).card := by + rw [Finset.card_filter, Finset.sum_product] + refine Finset.sum_congr rfl fun c _ => ?_ + rw [Finset.card_filter] + have h2 : (Ch T ×ˢ Ch T).filter (fun p => crossR p.1 p.2) = + crossH T ∪ (crossH T).image Prod.swap := by + ext ⟨c, d⟩ + simp only [crossH, Finset.mem_filter, Finset.mem_union, Finset.mem_image, + Finset.mem_product, Prod.exists, Prod.swap_prod_mk, Prod.mk.injEq] + unfold crossR + constructor + · rintro ⟨⟨hc, hd⟩, h | h⟩ + · exact Or.inl ⟨⟨hc, hd⟩, h⟩ + · exact Or.inr ⟨d.1, d.2, c.1, c.2, ⟨⟨hd, hc⟩, h⟩, rfl, rfl⟩ + · rintro (⟨⟨hc, hd⟩, h⟩ | ⟨a, b, a', b', ⟨⟨h1, h2⟩, h⟩, rfl, rfl⟩) + · exact ⟨⟨hc, hd⟩, Or.inl h⟩ + · exact ⟨⟨h2, h1⟩, Or.inr h⟩ + rw [h1, h2, Finset.card_union_of_disjoint, + Finset.card_image_of_injective _ Prod.swap_injective] + · ring + · rw [Finset.disjoint_left] + rintro ⟨c, d⟩ h h' + simp only [crossH, Finset.mem_filter, Finset.mem_image, Prod.exists, Prod.swap_prod_mk, + Prod.mk.injEq] at h h' + obtain ⟨a, b, a', b', ⟨-, h3⟩, rfl, rfl⟩ := h' + obtain ⟨-, h4⟩ := h + simp only at h3 h4 + linarith [h3.1, h3.2.1, h4.1, h4.2.1] + +/-- `m choose 2` as a rational polynomial. -/ +private lemma cast_choose_two (m : ℕ) : ((m.choose 2 : ℕ) : ℚ) = m * (m - 1) / 2 := by + induction m with + | zero => simp + | succ k ih => rw [Nat.choose_succ_succ, Nat.choose_one_right]; push_cast; rw [ih]; ring + +/-- `m choose 3` as a rational polynomial. -/ +private lemma cast_choose_three (m : ℕ) : ((m.choose 3 : ℕ) : ℚ) = m * (m - 1) * (m - 2) / 6 := by + induction m with + | zero => simp + | succ k ih => rw [Nat.choose_succ_succ]; push_cast; rw [ih, cast_choose_two]; ring + +/-- `m choose 4` as a rational polynomial. -/ +private lemma cast_choose_four (m : ℕ) : + ((m.choose 4 : ℕ) : ℚ) = m * (m - 1) * (m - 2) * (m - 3) / 24 := by + induction m with + | zero => simp + | succ k ih => rw [Nat.choose_succ_succ]; push_cast; rw [ih, cast_choose_three]; ring + +/-- The total number of crossings on the chords. -/ +private lemma crossings_formula (n : ℕ) (T : Finset ℝ) (hT : ∀ t ∈ T, 0 ≤ t) + (hN : T.card = 3 * n + 3) + (c0 : (T.filter S0).card = n + 2) (c1 : (T.filter S1).card = n + 2) + (c2 : (T.filter S2).card = n + 2) : + ((∑ c ∈ Ch T, ((Ch T).filter (fun d => crossR c d)).card : ℕ) : ℚ) = + 3 / 2 * n ^ 2 * (n + 1) * (3 * n + 1) := by + rw [sum_crossers, crossH_card T hT] + have h := good4_card n T hN c0 c1 c2 + have h' : ((good4 T).card : ℚ) = ((3 * n + 3).choose 4 : ℕ) - + 3 * (((n + 2).choose 3 : ℕ) * (2 * n + 1) + ((n + 2).choose 4 : ℕ)) := by + rw [← h]; push_cast; ring + push_cast + rw [h', cast_choose_four, cast_choose_four, cast_choose_three] + push_cast + ring + +/-! ### Number of chords -/ + +/-- The number of chords is `3n(n+1)`. -/ +private lemma chords_card (n : ℕ) (T : Finset ℝ) (hN : T.card = 3 * n + 3) + (c0 : (T.filter S0).card = n + 2) (c1 : (T.filter S1).card = n + 2) + (c2 : (T.filter S2).card = n + 2) : + ((Ch T).card : ℚ) = 3 * n * (n + 1) := by + classical + have hsplit := Finset.card_filter_add_card_filter_not (s := T.offDiag) + (fun p => coSide p.1 p.2) + have hnot : T.offDiag.filter (fun p => ¬ coSide p.1 p.2) = Ch T ∪ (Ch T).image Prod.swap := by + ext ⟨a, b⟩ + simp only [Finset.mem_filter, Finset.mem_offDiag, Finset.mem_union, Finset.mem_image, + mem_Ch, Prod.exists, Prod.swap_prod_mk, Prod.mk.injEq] + constructor + · rintro ⟨⟨ha, hb, hab⟩, hc⟩ + rcases lt_or_gt_of_ne hab with h | h + · exact Or.inl ⟨ha, hb, h, hc⟩ + · refine Or.inr ⟨b, a, ⟨hb, ha, h, fun h' => hc ?_⟩, rfl, rfl⟩ + unfold coSide at h' ⊢; tauto + · rintro (⟨ha, hb, h, hc⟩ | ⟨x, y, ⟨hx, hy, h, hc⟩, rfl, rfl⟩) + · exact ⟨⟨ha, hb, ne_of_lt h⟩, hc⟩ + · refine ⟨⟨hy, hx, ne_of_gt h⟩, fun h' => hc ?_⟩ + unfold coSide at h' ⊢; tauto + have hdis : Disjoint (Ch T) ((Ch T).image Prod.swap) := by + rw [Finset.disjoint_left] + rintro ⟨a, b⟩ h h' + simp only [Finset.mem_image, mem_Ch, Prod.exists, Prod.swap_prod_mk, Prod.mk.injEq] at h h' + obtain ⟨x, y, ⟨-, -, hxy, -⟩, rfl, rfl⟩ := h' + exact lt_asymm h.2.2.1 hxy + have hyes : T.offDiag.filter (fun p => coSide p.1 p.2) = + ((T.filter S0).offDiag ∪ (T.filter S1).offDiag) ∪ (T.filter S2).offDiag := by + ext ⟨a, b⟩ + simp only [Finset.mem_filter, Finset.mem_offDiag, Finset.mem_union] + unfold coSide + tauto + have d01 : Disjoint (T.filter S0).offDiag (T.filter S1).offDiag := by + rw [Finset.disjoint_left] + rintro ⟨a, b⟩ h h' + simp only [Finset.mem_offDiag, Finset.mem_filter, S0, S1] at h h' + exact h.2.2 (by linarith [h.1.2, h.2.1.2, h'.1.2.1, h'.2.1.2.1]) + have d2 : Disjoint ((T.filter S0).offDiag ∪ (T.filter S1).offDiag) (T.filter S2).offDiag := by + rw [Finset.disjoint_left] + rintro ⟨a, b⟩ h h' + simp only [Finset.mem_union, Finset.mem_offDiag, Finset.mem_filter, S0, S1, S2] at h h' + obtain ⟨⟨-, ha⟩, ⟨-, hb⟩, hab⟩ := h' + rcases h with ⟨⟨-, ha'⟩, ⟨-, hb'⟩, -⟩ | ⟨⟨-, ha'⟩, ⟨-, hb'⟩, -⟩ + · apply hab + rcases ha with ha | ha <;> rcases hb with hb | hb + · linarith + · linarith + · linarith + · rw [ha, hb] + · apply hab + rcases ha with ha | ha <;> rcases hb with hb | hb + · linarith [ha'.2, hb'.2] + · linarith [hb'.1] + · linarith [ha'.1] + · rw [ha, hb] + rw [hnot, Finset.card_union_of_disjoint hdis, + Finset.card_image_of_injective _ Prod.swap_injective, hyes, + Finset.card_union_of_disjoint d2, Finset.card_union_of_disjoint d01, + Finset.offDiag_card, Finset.offDiag_card, Finset.offDiag_card, Finset.offDiag_card, + c0, c1, c2, hN] at hsplit + have k1 : (n + 2) ≤ (n + 2) * (n + 2) := Nat.le_mul_self _ + have k2 : (3 * n + 3) ≤ (3 * n + 3) * (3 * n + 3) := Nat.le_mul_self _ + have hq : ((((n + 2) * (n + 2) - (n + 2) + ((n + 2) * (n + 2) - (n + 2)) + + ((n + 2) * (n + 2) - (n + 2)) + ((Ch T).card + (Ch T).card)) : ℕ) : ℚ) = + (((3 * n + 3) * (3 * n + 3) - (3 * n + 3) : ℕ) : ℚ) := by rw [hsplit] + push_cast [Nat.cast_sub k1, Nat.cast_sub k2] at hq + linarith + +/-- `√3 * √3 = 3`. -/ +private lemma sqrt3_sq : Real.sqrt 3 * Real.sqrt 3 = 3 := Real.mul_self_sqrt (by norm_num) + +/-- `D a b` is continuous. -/ +private lemma continuous_D (a b : ℂ) : Continuous fun z => D a b z := by + unfold D; fun_prop + +/-- A point on the inner side of all three side lines lies in the triangle. -/ +private lemma mem_triangle_of {z : ℂ} (h0 : 0 ≤ D (corner 0) (corner 1) z) + (h1 : 0 ≤ D (corner 1) (corner 2) z) (h2 : 0 ≤ D (corner 2) (corner 0) z) : + z ∈ triangle := by + have hs := sqrt3_pos + have hs2 := sqrt3_sq + let w : Fin 3 → ℝ := ![D (corner 1) (corner 2) z / (Real.sqrt 3 / 2), + D (corner 2) (corner 0) z / (Real.sqrt 3 / 2), D (corner 0) (corner 1) z / (Real.sqrt 3 / 2)] + have key := (convex_convexHull ℝ (Set.range corner)).sum_mem (t := Finset.univ) (w := w) + (z := corner) ?_ ?_ ?_ + · unfold triangle + convert key using 1 + simp only [Fin.sum_univ_three, w, Matrix.cons_val_zero, Matrix.cons_val_one, + Matrix.cons_val_two, Matrix.head_cons, Matrix.tail_cons, corner_zero, corner_one, corner_two] + apply Complex.ext <;> + · simp only [D, Complex.add_re, Complex.add_im, Complex.smul_re, Complex.smul_im, + Complex.sub_re, Complex.sub_im, Complex.zero_re, Complex.zero_im, Complex.one_re, + Complex.one_im, smul_eq_mul] + field_simp + ring + · intro i _ + have h3 : 0 < Real.sqrt 3 / 2 := by positivity + fin_cases i + · exact div_nonneg h1 h3.le + · exact div_nonneg h2 h3.le + · exact div_nonneg h0 h3.le + · simp only [Fin.sum_univ_three, w, Matrix.cons_val_zero, Matrix.cons_val_one, + Matrix.cons_val_two, Matrix.head_cons, Matrix.tail_cons, corner_zero, corner_one, + corner_two, D, Complex.sub_re, Complex.sub_im, Complex.zero_re, Complex.zero_im, + Complex.one_re, Complex.one_im] + field_simp + ring + · intro i _ + exact subset_convexHull ℝ _ (Set.mem_range_self i) + +/-- A point strictly on the inner side of all three side lines lies in the interior. -/ +private lemma mem_interior_of {z : ℂ} (h0 : 0 < D (corner 0) (corner 1) z) + (h1 : 0 < D (corner 1) (corner 2) z) (h2 : 0 < D (corner 2) (corner 0) z) : + z ∈ interior triangle := by + let U : Set ℂ := {w | 0 < D (corner 0) (corner 1) w ∧ 0 < D (corner 1) (corner 2) w ∧ + 0 < D (corner 2) (corner 0) w} + have hU : IsOpen U := by + refine IsOpen.inter (isOpen_lt continuous_const (continuous_D _ _)) ?_ + exact IsOpen.inter (isOpen_lt continuous_const (continuous_D _ _)) + (isOpen_lt continuous_const (continuous_D _ _)) + have hsub : U ⊆ triangle := fun w hw => mem_triangle_of hw.1.le hw.2.1.le hw.2.2.le + exact interior_maximal hsub hU ⟨h0, h1, h2⟩ + +/-! ### Signs -/ + +/-- The sign of `D` at boundary points is the sign of `E`. -/ +private lemma D_pos_of {a b c : ℝ} (h : 0 < E a b c) : 0 < D (P a) (P b) (P c) := by + rw [D_P]; exact mul_pos sqrt3_pos h + +/-- The sign of `D` at boundary points is the sign of `E`. -/ +private lemma D_neg_of {a b c : ℝ} (h : E a b c < 0) : D (P a) (P b) (P c) < 0 := by + rw [D_P]; exact mul_neg_of_pos_of_neg sqrt3_pos h + +/-- A triple containing a chord is not on a common side. -/ +private lemma not_coSide3_of {a b x y z : ℝ} (hc : ¬ coSide a b) + (h : ∀ p : ℝ → Prop, p x ∧ p y ∧ p z → p a ∧ p b) : ¬ coSide3 x y z := by + unfold coSide3; unfold coSide at hc + rintro (h' | h' | h') + · exact hc (Or.inl (h S0 h')) + · exact hc (Or.inr (Or.inl (h S1 h'))) + · exact hc (Or.inr (Or.inr (h S2 h'))) + +/-- The sign of `E a b t` for a chord `(a, b)` and another boundary parameter `t`. -/ +private lemma E_sign {a b t : ℝ} (ha : 0 ≤ a) (hab : a < b) (hb : b < 3) (hc : ¬ coSide a b) + (ht0 : 0 ≤ t) (ht3 : t < 3) : + (a < t → t < b → E a b t < 0) ∧ (t < a → 0 < E a b t) ∧ (b < t → 0 < E a b t) := by + refine ⟨fun h1 h2 => ?_, fun h1 => ?_, fun h1 => ?_⟩ + · have := E_pos ha h1 h2 hb (not_coSide3_of hc (fun p h => ⟨h.1, h.2.2⟩)) + rw [E_swap]; linarith + · have := E_pos ht0 h1 hab hb (not_coSide3_of hc (fun p h => ⟨h.2.1, h.2.2⟩)) + rw [← E_cyc]; exact this + · exact E_pos ha hab h1 ht3 (not_coSide3_of hc (fun p h => ⟨h.1, h.2.1⟩)) + +/-- No other boundary point lies on the line of a chord. -/ +private lemma E_ne {a b t : ℝ} (ha : 0 ≤ a) (hab : a < b) (hb : b < 3) (hc : ¬ coSide a b) + (ht0 : 0 ≤ t) (ht3 : t < 3) (hta : t ≠ a) (htb : t ≠ b) : E a b t ≠ 0 := by + obtain ⟨s1, s2, s3⟩ := E_sign ha hab hb hc ht0 ht3 + rcases lt_or_gt_of_ne hta with h | h + · exact (s2 h).ne' + · rcases lt_or_gt_of_ne htb with h' | h' + · exact (s1 h h').ne + · exact (s3 h').ne' + +/-- No other boundary point lies on the line of a chord. -/ +private lemma D_ne {a b t : ℝ} (ha : 0 ≤ a) (hab : a < b) (hb : b < 3) (hc : ¬ coSide a b) + (ht0 : 0 ≤ t) (ht3 : t < 3) (hta : t ≠ a) (htb : t ≠ b) : D (P a) (P b) (P t) ≠ 0 := by + rw [D_P]; exact mul_ne_zero sqrt3_pos.ne' (E_ne ha hab hb hc ht0 ht3 hta htb) + +/-! ### Chords -/ + +/-- The drawn segment of a pair of parameters. -/ +private def seg (c : ℝ × ℝ) : Set ℂ := segment ℝ (P c.1) (P c.2) + +/-- The relative interior of the drawn segment of a pair of parameters. -/ +private def oseg (c : ℝ × ℝ) : Set ℂ := openSegment ℝ (P c.1) (P c.2) + +/-- The crossing point of two chords. -/ +private noncomputable def X (c d : ℝ × ℝ) : ℂ := crossPt (P c.1) (P c.2) (P d.1) (P d.2) + +/-- Standing hypothesis: all parameters lie in `[0, 3)`. -/ +private def Good (T : Finset ℝ) : Prop := ∀ t ∈ T, 0 ≤ t ∧ t < 3 + +section +variable {T : Finset ℝ} (hT : Good T) +include hT + +/-- `P` is injective on `T`. -/ +private lemma P_injT {s t : ℝ} (hs : s ∈ T) (ht : t ∈ T) (h : P s = P t) : s = t := + P_inj (hT s hs).1 (hT s hs).2 (hT t ht).1 (hT t ht).2 h + +/-- Distinct parameters of `T` give distinct points. -/ +private lemma P_ne_of_ne {s t : ℝ} (hs : s ∈ T) (ht : t ∈ T) (h : s ≠ t) : P s ≠ P t := + fun e => h (P_injT hT hs ht e) + +/-- The relative interior of a chord is strictly inside all three side lines. -/ +private lemma oseg_pos {c : ℝ × ℝ} (hc : c ∈ Ch T) {z : ℂ} (hz : z ∈ oseg c) (j : Fin 3) : + 0 < D (corner j) (corner (j + 1)) z := by + rw [mem_Ch] at hc + obtain ⟨ha, hb, -, hco⟩ := hc + have ha' := hT _ ha + have hb' := hT _ hb + apply openSeg_pos (Dline_nonneg j ha'.1 ha'.2) (Dline_nonneg j hb'.1 hb'.2) _ hz + rw [Dline_pos_iff j ha'.1 ha'.2, Dline_pos_iff j hb'.1 hb'.2] + by_contra h + push Not at h + exact hco ((coSide_iff _ _).2 ⟨j, h⟩) + +/-- The relative interior of a chord lies in the interior of the triangle. -/ +private lemma oseg_interior {c : ℝ × ℝ} (hc : c ∈ Ch T) {z : ℂ} (hz : z ∈ oseg c) : + z ∈ interior triangle := + mem_interior_of (oseg_pos hT hc hz 0) (oseg_pos hT hc hz 1) (oseg_pos hT hc hz 2) + +/-- The relative interior of a chord avoids the sides. -/ +private lemma oseg_not_side {c : ℝ × ℝ} (hc : c ∈ Ch T) {z : ℂ} (hz : z ∈ oseg c) (j : Fin 3) : + z ∉ side j := by + intro h + have := oseg_pos hT hc hz j + rw [Dline_zero_of_mem_side j h] at this + exact lt_irrefl _ this + +/-- The endpoints of a chord are distinct. -/ +private lemma chord_ne {c : ℝ × ℝ} (hc : c ∈ Ch T) : P c.1 ≠ P c.2 := by + rw [mem_Ch] at hc + exact P_ne_of_ne hT hc.1 hc.2.1 (ne_of_lt hc.2.2.1) + +omit hT in +/-- A point of a chord other than its endpoints is in its relative interior. -/ +private lemma mem_oseg_of {c : ℝ × ℝ} (_hc : c ∈ Ch T) {z : ℂ} (hz : z ∈ seg c) (h1 : z ≠ P c.1) + (h2 : z ≠ P c.2) : z ∈ oseg c := by + unfold seg at hz + rw [← insert_endpoints_openSegment] at hz + rcases hz with hz | hz | hz + · exact absurd hz h1 + · exact absurd hz h2 + · exact hz + +/-- The endpoints of a chord are not in its relative interior. -/ +private lemma endpoint_not_oseg {c : ℝ × ℝ} (hc : c ∈ Ch T) : P c.1 ∉ oseg c ∧ P c.2 ∉ oseg c := by + have hne := chord_ne hT hc + unfold oseg + rw [left_mem_openSegment_iff, right_mem_openSegment_iff] + exact ⟨hne, hne⟩ + +/-- A boundary point other than the endpoints is not on a chord. -/ +private lemma P_not_mem_seg {c : ℝ × ℝ} (hc : c ∈ Ch T) {t : ℝ} (ht : t ∈ T) (h1 : t ≠ c.1) + (h2 : t ≠ c.2) : P t ∉ seg c := by + intro h + rw [mem_Ch] at hc + have := D_ne (hT _ hc.1).1 hc.2.2.1 (hT _ hc.2.1).2 hc.2.2.2 (hT t ht).1 (hT t ht).2 h1 h2 + exact this (D_of_mem_segment h) + +/-- Two chords with interleaving endpoints cross at `X c d`. -/ +private lemma X_mem {c d : ℝ × ℝ} (hc : c ∈ Ch T) (hd : d ∈ Ch T) (h : crossR c d) : + X c d ∈ oseg c ∧ X c d ∈ oseg d := by + rw [mem_Ch] at hc hd + obtain ⟨ha, hb, hab, hcab⟩ := hc + obtain ⟨he, hf, hef, hcef⟩ := hd + obtain ⟨ha0, ha3⟩ := hT _ ha + obtain ⟨hb0, hb3⟩ := hT _ hb + obtain ⟨he0, he3⟩ := hT _ he + obtain ⟨hf0, hf3⟩ := hT _ hf + have sab_e := E_sign ha0 hab hb3 hcab he0 he3 + have sab_f := E_sign ha0 hab hb3 hcab hf0 hf3 + have sef_a := E_sign he0 hef hf3 hcef ha0 ha3 + have sef_b := E_sign he0 hef hf3 hcef hb0 hb3 + unfold crossR at h + apply crossPt_mem + · rcases h with ⟨h1, h2, h3⟩ | ⟨h1, h2, h3⟩ + · exact mul_neg_of_neg_of_pos (D_neg_of (sab_e.1 h1 (by linarith))) + (D_pos_of (sab_f.2.2 (by linarith))) + · exact mul_neg_of_pos_of_neg (D_pos_of (sab_e.2.1 h1)) + (D_neg_of (sab_f.1 (by linarith) (by linarith))) + · rcases h with ⟨h1, h2, h3⟩ | ⟨h1, h2, h3⟩ + · exact mul_neg_of_pos_of_neg (D_pos_of (sef_a.2.1 h1)) + (D_neg_of (sef_b.1 (by linarith) (by linarith))) + · exact mul_neg_of_neg_of_pos (D_neg_of (sef_a.1 h1 (by linarith))) + (D_pos_of (sef_b.2.2 (by linarith))) + +/-- Distinct chords meet in at most one point. -/ +private lemma seg_inter_unique {c d : ℝ × ℝ} (hc : c ∈ Ch T) (hd : d ∈ Ch T) (hcd : c ≠ d) + {u v : ℂ} (hu : u ∈ seg c) (hu' : u ∈ seg d) (hv : v ∈ seg c) (hv' : v ∈ seg d) : + u = v := by + have hc' := hc + rw [mem_Ch] at hc' hd + obtain ⟨ha, hb, hab, hcab⟩ := hc' + obtain ⟨he, hf, hef, -⟩ := hd + obtain ⟨ha0, ha3⟩ := hT _ ha + by_cases h1 : d.1 = c.1 ∨ d.1 = c.2 + · have h2 : d.2 ≠ c.1 ∧ d.2 ≠ c.2 := by + constructor + · intro e; rcases h1 with h1 | h1 <;> linarith + · intro e + rcases h1 with h1 | h1 + · exact hcd (Prod.ext h1.symm e.symm) + · linarith + have hD := D_ne ha0 hab (hT _ hb).2 hcab (hT _ hf).1 (hT _ hf).2 h2.1 h2.2 + unfold seg at hu hu' hv hv' + rw [segment_symm] at hu' hv' + exact seg_inter_sub hD hu hu' hv hv' + · push Not at h1 + have hD := D_ne ha0 hab (hT _ hb).2 hcab (hT _ he).1 (hT _ he).2 h1.1 h1.2 + exact seg_inter_sub hD hu hu' hv hv' + +/-- Two crossing chords meet exactly at `X c d`. -/ +private lemma seg_inter_X {c d : ℝ × ℝ} (hc : c ∈ Ch T) (hd : d ∈ Ch T) (h : crossR c d) : + seg c ∩ seg d = {X c d} := by + have hX := X_mem hT hc hd h + have hcd : c ≠ d := by + rintro rfl; unfold crossR at h + rcases h with ⟨h1, h2, h3⟩ | ⟨h1, h2, h3⟩ <;> exact lt_irrefl _ h1 + ext z + simp only [Set.mem_inter_iff, Set.mem_singleton_iff] + constructor + · rintro ⟨h1, h2⟩ + exact seg_inter_unique hT hc hd hcd h1 h2 (openSegment_subset_segment _ _ _ hX.1) + (openSegment_subset_segment _ _ _ hX.2) + · rintro rfl + exact ⟨openSegment_subset_segment _ _ _ hX.1, openSegment_subset_segment _ _ _ hX.2⟩ + +/-- Two distinct chords meeting at a point of the relative interior of one of them cross. -/ +private lemma crossR_of_mem {c d : ℝ × ℝ} (hc : c ∈ Ch T) (hd : d ∈ Ch T) (hcd : c ≠ d) {z : ℂ} + (hz : z ∈ oseg c) (hz' : z ∈ seg d) : crossR c d := by + by_contra hn + have hc' := hc + have hd' := hd + rw [mem_Ch] at hc' hd' + obtain ⟨ha, hb, hab, hcab⟩ := hc' + obtain ⟨he, hf, hef, hcef⟩ := hd' + obtain ⟨ha0, ha3⟩ := hT _ ha + obtain ⟨hb0, hb3⟩ := hT _ hb + obtain ⟨he0, he3⟩ := hT _ he + obtain ⟨hf0, hf3⟩ := hT _ hf + have hz0 : D (P c.1) (P c.2) z = 0 := D_of_mem_segment (openSegment_subset_segment _ _ _ hz) + have hne := endpoint_not_oseg hT hc + unfold crossR at hn + push Not at hn + by_cases hsh : d.1 = c.1 ∨ d.1 = c.2 ∨ d.2 = c.1 ∨ d.2 = c.2 + · -- a shared endpoint + have hzc : z ∈ seg c := openSegment_subset_segment _ _ _ hz + have hPa : P c.1 ∈ seg c := left_mem_segment _ _ _ + have hPb : P c.2 ∈ seg c := right_mem_segment _ _ _ + unfold seg at hz' hzc hPa hPb + rcases hsh with h | h | h | h + · have hf1 : d.2 ≠ c.1 := by intro e; linarith + have hf2 : d.2 ≠ c.2 := fun e => hcd (Prod.ext h.symm e.symm) + have hD := D_ne ha0 hab hb3 hcab hf0 hf3 hf1 hf2 + rw [segment_symm, h] at hz' + have e := seg_inter_sub hD hzc hz' hPa (right_mem_segment _ _ _) + rw [e] at hz; exact hne.1 hz + · have hf1 : d.2 ≠ c.1 := by intro e; linarith + have hf2 : d.2 ≠ c.2 := by intro e; linarith + have hD := D_ne ha0 hab hb3 hcab hf0 hf3 hf1 hf2 + rw [segment_symm, h] at hz' + have e := seg_inter_sub hD hzc hz' hPb (right_mem_segment _ _ _) + rw [e] at hz; exact hne.2 hz + · have he1 : d.1 ≠ c.1 := by intro e; linarith + have he2 : d.1 ≠ c.2 := by intro e; linarith + have hD := D_ne ha0 hab hb3 hcab he0 he3 he1 he2 + rw [h] at hz' + have e := seg_inter_sub hD hzc hz' hPa (right_mem_segment _ _ _) + rw [e] at hz; exact hne.1 hz + · have he1 : d.1 ≠ c.1 := fun e => hcd (Prod.ext e.symm h.symm) + have he2 : d.1 ≠ c.2 := by intro e; linarith + have hD := D_ne ha0 hab hb3 hcab he0 he3 he1 he2 + rw [h] at hz' + have e := seg_inter_sub hD hzc hz' hPb (right_mem_segment _ _ _) + rw [e] at hz; exact hne.2 hz + · push Not at hsh + obtain ⟨h1, h2, h3, h4⟩ := hsh + obtain ⟨s1, s2, s3⟩ := E_sign ha0 hab hb3 hcab he0 he3 + obtain ⟨t1, t2, t3⟩ := E_sign ha0 hab hb3 hcab hf0 hf3 + have key : (0 < D (P c.1) (P c.2) (P d.1) ∧ 0 < D (P c.1) (P c.2) (P d.2)) ∨ + (D (P c.1) (P c.2) (P d.1) < 0 ∧ D (P c.1) (P c.2) (P d.2) < 0) := by + rcases lt_or_gt_of_ne h1 with e1 | e1 + · -- d.1 < c.1 + rcases lt_or_gt_of_ne h4 with e4 | e4 + · rcases lt_or_gt_of_ne h3 with e3 | e3 + · exact Or.inl ⟨D_pos_of (s2 e1), D_pos_of (t2 e3)⟩ + · exact absurd (hn.2 e1 e3) (not_le.2 e4) + · exact Or.inl ⟨D_pos_of (s2 e1), D_pos_of (t3 e4)⟩ + · rcases lt_or_gt_of_ne h2 with e2 | e2 + · rcases lt_or_gt_of_ne h4 with e4 | e4 + · exact Or.inr ⟨D_neg_of (s1 e1 e2), D_neg_of (t1 (by linarith) e4)⟩ + · exact absurd (hn.1 e1 e2) (not_le.2 e4) + · exact Or.inl ⟨D_pos_of (s3 e2), D_pos_of (t3 (by linarith))⟩ + rcases key with ⟨k1, k2⟩ | ⟨k1, k2⟩ + · have := seg_pos k1 k2 hz' + rw [hz0] at this; exact lt_irrefl _ this + · have := seg_neg k1 k2 hz' + rw [hz0] at this; exact lt_irrefl _ this + +end + +/-! ### A one-dimensional lemma -/ + +/-- Two segments on a common line whose relative interiors share a point share a second +point. -/ +private lemma oneD {p q x y u v z : ℂ} (hpq : p ≠ q) (hx : x ∈ segment ℝ p q) + (hy : y ∈ segment ℝ p q) + (hu : u ∈ segment ℝ p q) (hv : v ∈ segment ℝ p q) (hxy : x ≠ y) (huv : u ≠ v) + (hz1 : z ∈ openSegment ℝ x y) (hz2 : z ∈ openSegment ℝ u v) : + ∃ w, w ≠ z ∧ w ∈ segment ℝ x y ∧ w ∈ segment ℝ u v := by + set L : ℝ →ᵃ[ℝ] ℂ := AffineMap.lineMap p q + have hL : Function.Injective L := AffineMap.lineMap_injective ℝ hpq + rw [segment_eq_image_lineMap] at hx hy hu hv + obtain ⟨α, -, rfl⟩ := hx + obtain ⟨β, -, rfl⟩ := hy + obtain ⟨γ, -, rfl⟩ := hu + obtain ⟨δ, -, rfl⟩ := hv + have hαβ : α ≠ β := fun h => hxy (by rw [h]) + have hγδ : γ ≠ δ := fun h => huv (by rw [h]) + rw [← image_openSegment] at hz1 hz2 + obtain ⟨ζ, hζ, rfl⟩ := hz1 + obtain ⟨ζ', hζ', hζζ⟩ := hz2 + have e := hL hζζ + rw [e] at hζ' + rw [openSegment_eq_Ioo' hαβ] at hζ + rw [openSegment_eq_Ioo' hγδ] at hζ' + set m := min (max α β) (max γ δ) + have hm1 : m ≤ max α β := min_le_left _ _ + have hm2 : m ≤ max γ δ := min_le_right _ _ + have hζm : ζ < m := lt_min hζ.2 hζ'.2 + refine ⟨L ((ζ + m) / 2), fun h => ?_, ?_, ?_⟩ + · have := hL h; linarith + · rw [← image_segment, segment_eq_uIcc] + refine ⟨(ζ + m) / 2, ?_, rfl⟩ + rw [Set.mem_uIcc] + rcases le_total α β with h | h + · left + rw [min_eq_left h] at hζ; rw [max_eq_right h] at hζ hm1 + constructor <;> linarith [hζ.1] + · right + rw [min_eq_right h] at hζ; rw [max_eq_left h] at hζ hm1 + constructor <;> linarith [hζ.1] + · rw [← image_segment, segment_eq_uIcc] + refine ⟨(ζ + m) / 2, ?_, rfl⟩ + rw [Set.mem_uIcc] + rcases le_total γ δ with h | h + · left + rw [min_eq_left h] at hζ'; rw [max_eq_right h] at hζ' hm2 + constructor <;> linarith [hζ'.1] + · right + rw [min_eq_right h] at hζ'; rw [max_eq_left h] at hζ' hm2 + constructor <;> linarith [hζ'.1] + +/-! ### Sides meet only at corners -/ + +/-- Two distinct sides share exactly one parameter, a corner. -/ +private lemma Sd_inter {j j' : Fin 3} (hjj : j ≠ j') : + ∃ c : ℝ, (c = 0 ∨ c = 1 ∨ c = 2) ∧ ∀ t, Sd j t → Sd j' t → t = c := by + fin_cases j <;> fin_cases j' + · exact absurd rfl hjj + · refine ⟨1, Or.inr (Or.inl rfl), fun t h h' => ?_⟩ + change t ≤ 1 at h; change 1 ≤ t ∧ t ≤ 2 at h'; linarith [h'.1] + · refine ⟨0, Or.inl rfl, fun t h h' => ?_⟩ + change t ≤ 1 at h; change 2 ≤ t ∨ t = 0 at h' + rcases h' with h' | h' + · linarith + · exact h' + · refine ⟨1, Or.inr (Or.inl rfl), fun t h h' => ?_⟩ + change 1 ≤ t ∧ t ≤ 2 at h; change t ≤ 1 at h'; linarith [h.1] + · exact absurd rfl hjj + · refine ⟨2, Or.inr (Or.inr rfl), fun t h h' => ?_⟩ + change 1 ≤ t ∧ t ≤ 2 at h; change 2 ≤ t ∨ t = 0 at h' + rcases h' with h' | h' + · linarith [h.2] + · linarith [h.1] + · refine ⟨0, Or.inl rfl, fun t h h' => ?_⟩ + change 2 ≤ t ∨ t = 0 at h; change t ≤ 1 at h' + rcases h with h | h + · linarith + · exact h + · refine ⟨2, Or.inr (Or.inr rfl), fun t h h' => ?_⟩ + change 2 ≤ t ∨ t = 0 at h; change 1 ≤ t ∧ t ≤ 2 at h' + rcases h with h | h + · linarith [h'.2] + · linarith [h'.1] + · exact absurd rfl hjj + +/-- Two distinct sides meet only at a corner. -/ +private lemma side_inter_corner {j j' : Fin 3} (hjj : j ≠ j') {z : ℂ} (hz : z ∈ side j) + (hz' : z ∈ side j') : z = corner 0 ∨ z = corner 1 ∨ z = corner 2 := by + obtain ⟨t, h0, h3, hs, rfl⟩ := exists_P_of_mem_side hz + have hs' := (P_mem_side_iff h0 h3).1 hz' + obtain ⟨c, hc, hc'⟩ := Sd_inter hjj + have := hc' t hs hs' + subst this + rcases hc with rfl | rfl | rfl + · exact Or.inl P_zero + · exact Or.inr (Or.inl P_one) + · exact Or.inr (Or.inr P_two) + +/-! ### The vertices -/ + +/-- The vertices on a chord: its endpoints and its crossings with the other chords. -/ +private noncomputable def VC (T : Finset ℝ) (c : ℝ × ℝ) : Finset ℂ := + insert (P c.1) (insert (P c.2) (((Ch T).filter (crossR c)).image (X c))) + +/-- The vertices on a side: the boundary points on it. -/ +private noncomputable def VS (T : Finset ℝ) (j : Fin 3) : Finset ℂ := (T.filter (Sd j)).image P + +/-- Membership in `VS T j`. -/ +private lemma mem_VS {T : Finset ℝ} {j : Fin 3} {z : ℂ} : + z ∈ VS T j ↔ ∃ t ∈ T, Sd j t ∧ P t = z := by + simp only [VS, Finset.mem_image, Finset.mem_filter, and_assoc] + +section +variable {T : Finset ℝ} (hT : Good T) {B : Finset ℂ} (hB : B = T.image P) +include hT hB + +omit hT in +/-- The points of `B` are the `P t`, `t ∈ T`. -/ +private lemma mem_B {z : ℂ} : z ∈ B ↔ ∃ t ∈ T, P t = z := by + rw [hB, Finset.mem_image] + +omit hT in +/-- The points `P t`, `t ∈ T`, are in `B`. -/ +private lemma P_mem_B {t : ℝ} (ht : t ∈ T) : P t ∈ B := (mem_B hB).2 ⟨t, ht, rfl⟩ + +/-- The drawn segments in terms of parameters. -/ +private lemma mem_drawn {s : Set ℂ} : + s ∈ drawn B ↔ ∃ e ∈ T, ∃ f ∈ T, e ≠ f ∧ s = segment ℝ (P e) (P f) := by + constructor + · rintro ⟨p, hp, q, hq, hpq, rfl⟩ + obtain ⟨e, he, rfl⟩ := (mem_B hB).1 hp + obtain ⟨f, hf, rfl⟩ := (mem_B hB).1 hq + exact ⟨e, he, f, hf, fun h => hpq (by rw [h]), rfl⟩ + · rintro ⟨e, he, f, hf, hef, rfl⟩ + exact ⟨P e, P_mem_B hB he, P f, P_mem_B hB hf, P_ne_of_ne hT he hf hef, rfl⟩ + +/-- Chords are drawn. -/ +private lemma seg_mem_drawn {c : ℝ × ℝ} (hc : c ∈ Ch T) : seg c ∈ drawn B := by + rw [mem_Ch] at hc + exact (mem_drawn hT hB).2 ⟨c.1, hc.1, c.2, hc.2.1, ne_of_lt hc.2.2.1, rfl⟩ + +omit hB in +/-- A drawn segment is a chord or lies in a side. -/ +private lemma classify {e f : ℝ} (he : e ∈ T) (hf : f ∈ T) (hef : e ≠ f) : + (∃ d ∈ Ch T, segment ℝ (P e) (P f) = seg d) ∨ + (∃ j : Fin 3, Sd j e ∧ Sd j f ∧ segment ℝ (P e) (P f) ⊆ side j) := by + by_cases hco : coSide e f + · right + obtain ⟨j, h1, h2⟩ := (coSide_iff e f).1 hco + refine ⟨j, h1, h2, (convex_segment _ _).segment_subset ?_ ?_⟩ + · exact P_mem_side (hT e he).1 (hT e he).2 h1 + · exact P_mem_side (hT f hf).1 (hT f hf).2 h2 + · left + rcases lt_or_gt_of_ne hef with h | h + · exact ⟨(e, f), mem_Ch.2 ⟨he, hf, h, hco⟩, rfl⟩ + · refine ⟨(f, e), mem_Ch.2 ⟨hf, he, h, fun h' => hco ?_⟩, segment_symm _ _ _⟩ + unfold coSide at h' ⊢; tauto + +omit hT hB in +/-- Membership in the vertex set. -/ +private lemma mem_vertices {z : ℂ} : + z ∈ vertices B ↔ z ∈ B ∨ ∃ s ∈ drawn B, ∃ t ∈ drawn B, s ∩ t = {z} := by + simp only [vertices, Set.mem_union, Finset.mem_coe, Set.mem_ofPred_eq] + +omit hT hB in +/-- Two drawn segments meeting in a single point are different. -/ +private lemma drawn_ne_of_inter {s t : Set ℂ} (hs : s ∈ drawn B) {z : ℂ} (hst : s ∩ t = {z}) : + s ≠ t := by + rintro rfl + rw [Set.inter_self] at hst + obtain ⟨p, -, q, -, hpq, rfl⟩ := hs + have h1 : p ∈ segment ℝ p q := left_mem_segment _ _ _ + have h2 : q ∈ segment ℝ p q := right_mem_segment _ _ _ + rw [hst] at h1 h2 + exact hpq (h1.trans h2.symm) + +/-- A drawn segment through a point of the relative interior of a chord `c`, other than `c` +itself, is a chord crossing `c` there. -/ +private lemma other_seg {c : ℝ × ℝ} (hc : c ∈ Ch T) {z : ℂ} (hz : z ∈ oseg c) {t : Set ℂ} + (ht : t ∈ drawn B) (hzt : z ∈ t) (htc : t ≠ seg c) : + ∃ d ∈ Ch T, crossR c d ∧ X c d = z := by + obtain ⟨g, hg, h, hh, hgh, rfl⟩ := (mem_drawn hT hB).1 ht + rcases classify hT hg hh hgh with ⟨d, hd, hdt⟩ | ⟨j, -, -, hsub⟩ + · rw [hdt] at hzt htc + have hcd : c ≠ d := fun e => htc (by rw [e]) + have hcr := crossR_of_mem hT hc hd hcd hz hzt + refine ⟨d, hd, hcr, ?_⟩ + have : z ∈ seg c ∩ seg d := ⟨openSegment_subset_segment _ _ _ hz, hzt⟩ + rw [seg_inter_X hT hc hd hcr] at this + exact this.symm + · exact absurd (hsub hzt) (oseg_not_side hT hc hz j) + +/-- The vertices on a chord. -/ +private lemma V_chord (hGP : GeneralPosition B) {c : ℝ × ℝ} (hc : c ∈ Ch T) : + vertices B ∩ seg c = ↑(VC T c) := by + ext z + simp only [Set.mem_inter_iff, Finset.mem_coe, VC, Finset.mem_insert, Finset.mem_image, + Finset.mem_filter] + constructor + · rintro ⟨hzV, hzc⟩ + by_cases h1 : z = P c.1 + · exact Or.inl h1 + by_cases h2 : z = P c.2 + · exact Or.inr (Or.inl h2) + right; right + have hzo : z ∈ oseg c := mem_oseg_of hc hzc h1 h2 + rcases (mem_vertices).1 hzV with hzB | ⟨s, hs, t, ht, hst⟩ + · exfalso + obtain ⟨u, hu, rfl⟩ := (mem_B hB).1 hzB + exact P_not_mem_seg hT hc hu (fun e => h1 (by rw [e])) (fun e => h2 (by rw [e])) hzc + · have hz2 : z ∈ s ∩ t := by rw [hst]; rfl + have hne := drawn_ne_of_inter hs hst + rcases hGP z (oseg_interior hT hc hzo) (seg c) (seg_mem_drawn hT hB hc) s hs t ht hzc + hz2.1 hz2.2 with h | h | h + · obtain ⟨d, hd, hcr, hX⟩ := other_seg hT hB hc hzo ht hz2.2 (by rw [h]; exact hne.symm) + exact ⟨d, ⟨hd, hcr⟩, hX⟩ + · obtain ⟨d, hd, hcr, hX⟩ := other_seg hT hB hc hzo hs hz2.1 (by rw [h]; exact hne) + exact ⟨d, ⟨hd, hcr⟩, hX⟩ + · exact absurd h hne + · rintro (rfl | rfl | ⟨d, ⟨hd, hcr⟩, rfl⟩) + · have hc' := (mem_Ch.1 hc).1 + exact ⟨(mem_vertices).2 (Or.inl (P_mem_B hB hc')), left_mem_segment _ _ _⟩ + · have hc' := (mem_Ch.1 hc).2.1 + exact ⟨(mem_vertices).2 (Or.inl (P_mem_B hB hc')), right_mem_segment _ _ _⟩ + · refine ⟨(mem_vertices).2 (Or.inr ⟨seg c, seg_mem_drawn hT hB hc, seg d, + seg_mem_drawn hT hB hd, seg_inter_X hT hc hd hcr⟩), ?_⟩ + exact openSegment_subset_segment _ _ _ (X_mem hT hc hd hcr).1 + +omit hT hB in +/-- The corners are in `B`. -/ +private lemma corner_mem_B (hcB : ∀ j : Fin 3, corner j ∈ B) {z : ℂ} + (h : z = corner 0 ∨ z = corner 1 ∨ z = corner 2) : z ∈ B := by + rcases h with rfl | rfl | rfl <;> exact hcB _ + +/-- The vertices on a side are the boundary points on it. -/ +private lemma V_side (hcB : ∀ j : Fin 3, corner j ∈ B) (j : Fin 3) : + vertices B ∩ side j = ↑(VS T j) := by + ext z + simp only [Set.mem_inter_iff, Finset.mem_coe, mem_VS] + constructor + · rintro ⟨hzV, hzj⟩ + have hzB : z ∈ B := by + rcases (mem_vertices).1 hzV with hzB | ⟨s, hs, t, ht, hst⟩ + · exact hzB + · by_contra hzB + have hz2 : z ∈ s ∩ t := by rw [hst]; rfl + -- each of `s`, `t` lies in a side + have key : ∀ s ∈ drawn B, z ∈ s → ∃ k : Fin 3, ∃ e ∈ T, ∃ f ∈ T, e ≠ f ∧ + s = segment ℝ (P e) (P f) ∧ Sd k e ∧ Sd k f ∧ + z ∈ openSegment ℝ (P e) (P f) := by + intro s hs hzs + obtain ⟨e, he, f, hf, hef, rfl⟩ := (mem_drawn hT hB).1 hs + have hze : z ≠ P e := fun h => hzB (h ▸ P_mem_B hB he) + have hzf : z ≠ P f := fun h => hzB (h ▸ P_mem_B hB hf) + have hzo : z ∈ openSegment ℝ (P e) (P f) := by + rw [← insert_endpoints_openSegment] at hzs + rcases hzs with h | h | h + · exact absurd h hze + · exact absurd h hzf + · exact h + rcases classify hT he hf hef with ⟨d, hd, hdt⟩ | ⟨k, h1, h2, -⟩ + · exfalso + rw [hdt] at hzs + have hd' := mem_Ch.1 hd + have := mem_oseg_of hd hzs (fun h => hzB (h ▸ P_mem_B hB hd'.1)) + (fun h => hzB (h ▸ P_mem_B hB hd'.2.1)) + exact oseg_not_side hT hd this j hzj + · exact ⟨k, e, he, f, hf, hef, rfl, h1, h2, hzo⟩ + obtain ⟨k, e, he, f, hf, hef, rfl, he1, hf1, hzo1⟩ := key s hs hz2.1 + obtain ⟨k', g, hg, h, hh, hgh, rfl, hg1, hh1, hzo2⟩ := key t ht hz2.2 + have hzk : z ∈ side k := (convex_segment _ _).segment_subset + (P_mem_side (hT e he).1 (hT e he).2 he1) (P_mem_side (hT f hf).1 (hT f hf).2 hf1) + (openSegment_subset_segment _ _ _ hzo1) + have hzk' : z ∈ side k' := (convex_segment _ _).segment_subset + (P_mem_side (hT g hg).1 (hT g hg).2 hg1) (P_mem_side (hT h hh).1 (hT h hh).2 hh1) + (openSegment_subset_segment _ _ _ hzo2) + by_cases hkk : k = k' + · subst hkk + obtain ⟨w, hwz, hw1, hw2⟩ := oneD (corner_ne k) + (P_mem_side (hT e he).1 (hT e he).2 he1) (P_mem_side (hT f hf).1 (hT f hf).2 hf1) + (P_mem_side (hT g hg).1 (hT g hg).2 hg1) (P_mem_side (hT h hh).1 (hT h hh).2 hh1) + (P_ne_of_ne hT he hf hef) (P_ne_of_ne hT hg hh hgh) hzo1 hzo2 + have : w ∈ segment ℝ (P e) (P f) ∩ segment ℝ (P g) (P h) := ⟨hw1, hw2⟩ + rw [hst] at this + exact hwz this + · exact hzB (corner_mem_B hcB (side_inter_corner hkk hzk hzk')) + obtain ⟨u, hu, rfl⟩ := (mem_B hB).1 hzB + exact ⟨u, hu, (P_mem_side_iff (hT u hu).1 (hT u hu).2).1 hzj, rfl⟩ + · rintro ⟨u, hu, hsd, rfl⟩ + exact ⟨(mem_vertices).2 (Or.inl (P_mem_B hB hu)), + P_mem_side (hT u hu).1 (hT u hu).2 hsd⟩ + +end + +/-! ### Consecutive points on a segment -/ + +open Classical in +/-- Consecutive pairs of a finite set of reals. -/ +private noncomputable def consR (T : Finset ℝ) : Finset (ℝ × ℝ) := + (T ×ˢ T).filter (fun p => p.1 < p.2 ∧ ∀ w ∈ T, ¬ (p.1 < w ∧ w < p.2)) + +/-- Membership in `consR T`. -/ +private lemma mem_consR {T : Finset ℝ} {p : ℝ × ℝ} : + p ∈ consR T ↔ p.1 ∈ T ∧ p.2 ∈ T ∧ p.1 < p.2 ∧ ∀ w ∈ T, ¬ (p.1 < w ∧ w < p.2) := by + simp only [consR, Finset.mem_filter, Finset.mem_product, and_assoc] + +/-- A nonempty finite set of reals has one consecutive pair fewer than elements. -/ +private lemma consR_card (T : Finset ℝ) (hT : T.Nonempty) : (consR T).card + 1 = T.card := by + classical + induction T using Finset.induction_on_max with + | empty => exact absurd hT (by simp) + | insert a s hlt ih => + have has : a ∉ s := fun h => lt_irrefl a (hlt a h) + rcases s.eq_empty_or_nonempty with rfl | hs + · have : consR {a} = ∅ := by + ext ⟨u, v⟩ + simp only [mem_consR, Finset.mem_singleton, Finset.notMem_empty, iff_false] + rintro ⟨rfl, rfl, h, -⟩ + exact lt_irrefl _ h + simp [this] + · have e : consR (insert a s) = insert (s.max' hs, a) (consR s) := by + ext ⟨u, v⟩ + simp only [mem_consR, Finset.mem_insert, Prod.mk.injEq] + constructor + · rintro ⟨hu, hv, huv, hw⟩ + rcases hv with rfl | hv + · left + have hu' : u ∈ s := hu.resolve_left (ne_of_lt huv) + refine ⟨?_, rfl⟩ + have hle := s.le_max' u hu' + rcases lt_or_eq_of_le hle with hlt' | heq + · exact absurd ⟨hlt', hlt _ (s.max'_mem hs)⟩ (hw _ (Or.inr (s.max'_mem hs))) + · exact heq + · right + have hva := hlt v hv + have hu' : u ∈ s := hu.resolve_left (by intro h; subst h; linarith) + exact ⟨hu', hv, huv, fun w hws => hw w (Or.inr hws)⟩ + · rintro (⟨rfl, rfl⟩ | ⟨hu, hv, huv, hw⟩) + · refine ⟨Or.inr (s.max'_mem hs), Or.inl rfl, hlt _ (s.max'_mem hs), ?_⟩ + rintro w (rfl | hws) ⟨h1, h2⟩ + · exact lt_irrefl _ h2 + · exact absurd (s.le_max' w hws) (not_le.2 h1) + · refine ⟨Or.inr hu, Or.inr hv, huv, ?_⟩ + rintro w (rfl | hws) + · rintro ⟨-, h2⟩; exact lt_irrefl _ (lt_trans h2 (hlt v hv)) + · exact hw w hws + have hnot : (s.max' hs, a) ∉ consR s := by + rw [mem_consR]; exact fun h => has h.2.1 + rw [e, Finset.card_insert_of_notMem hnot, Finset.card_insert_of_notMem has, ← ih hs] + +open Classical in +/-- The pairs of points of `F` with no point of `F` strictly between them. -/ +private noncomputable def consF (F : Finset ℂ) : Finset (Sym2 ℂ) := + ((F ×ˢ F).filter (fun p => p.1 ≠ p.2 ∧ ∀ w ∈ F, w ∉ openSegment ℝ p.1 p.2)).image + (fun p => s(p.1, p.2)) + +/-- Membership in `consF F`. -/ +private lemma mem_consF {F : Finset ℂ} {e : Sym2 ℂ} : + e ∈ consF F ↔ ∃ u v, u ∈ F ∧ v ∈ F ∧ u ≠ v ∧ (∀ w ∈ F, w ∉ openSegment ℝ u v) ∧ + e = s(u, v) := by + simp only [consF, Finset.mem_image, Finset.mem_filter, Finset.mem_product, Prod.exists] + constructor + · rintro ⟨u, v, ⟨⟨hu, hv⟩, huv, hw⟩, rfl⟩; exact ⟨u, v, hu, hv, huv, hw, rfl⟩ + · rintro ⟨u, v, hu, hv, huv, hw, rfl⟩; exact ⟨u, v, ⟨⟨hu, hv⟩, huv, hw⟩, rfl⟩ + +/-- Membership of a pair in `consF F`. -/ +private lemma mem_consF_pair {F : Finset ℂ} {u v : ℂ} : + s(u, v) ∈ consF F ↔ u ≠ v ∧ u ∈ F ∧ v ∈ F ∧ ∀ w ∈ F, w ∉ openSegment ℝ u v := by + rw [mem_consF] + constructor + · rintro ⟨u', v', hu, hv, huv, hw, he⟩ + rcases Sym2.eq_iff.1 he with ⟨rfl, rfl⟩ | ⟨rfl, rfl⟩ + · exact ⟨huv, hu, hv, hw⟩ + · refine ⟨huv.symm, hv, hu, ?_⟩ + intro w hwF; rw [openSegment_symm]; exact hw w hwF + · rintro ⟨huv, hu, hv, hw⟩ + exact ⟨u, v, hu, hv, huv, hw, rfl⟩ + +/-- A nonempty finite subset of a segment has one consecutive pair fewer than elements. -/ +private lemma consF_card {a b : ℂ} (hab : a ≠ b) (F : Finset ℂ) (hF : ↑F ⊆ segment ℝ a b) + (hne : F.Nonempty) : (consF F).card + 1 = F.card := by + classical + set f : ℝ →ᵃ[ℝ] ℂ := AffineMap.lineMap a b + have hf : Function.Injective f := AffineMap.lineMap_injective ℝ hab + set T := F.preimage f hf.injOn + have hFT : F = T.image f := by + ext z + simp only [Finset.mem_image, T, Finset.mem_preimage] + constructor + · intro hz + have := hF hz + rw [segment_eq_image_lineMap] at this + obtain ⟨t, -, rfl⟩ := this + exact ⟨t, hz, rfl⟩ + · rintro ⟨t, ht, rfl⟩; exact ht + have hseg : ∀ α β : ℝ, α < β → ∀ γ : ℝ, f γ ∈ openSegment ℝ (f α) (f β) ↔ α < γ ∧ γ < β := by + intro α β hαβ γ + rw [← image_openSegment, openSegment_eq_Ioo hαβ] + constructor + · rintro ⟨γ', hγ', h⟩; rw [← hf h]; exact hγ' + · intro h; exact ⟨γ, h, rfl⟩ + have e : consF F = (consR T).image (fun p => s(f p.1, f p.2)) := by + ext e + rw [mem_consF, Finset.mem_image] + constructor + · rintro ⟨u, v, hu, hv, huv, hw, rfl⟩ + rw [hFT, Finset.mem_image] at hu hv + obtain ⟨α, hα, rfl⟩ := hu + obtain ⟨β, hβ, rfl⟩ := hv + have hne' : α ≠ β := fun h => huv (by rw [h]) + rcases lt_or_gt_of_ne hne' with hlt | hlt + · refine ⟨(α, β), mem_consR.2 ⟨hα, hβ, hlt, fun γ hγ hb => ?_⟩, rfl⟩ + exact hw (f γ) (by rw [hFT]; exact Finset.mem_image_of_mem _ hγ) ((hseg α β hlt γ).2 hb) + · refine ⟨(β, α), mem_consR.2 ⟨hβ, hα, hlt, fun γ hγ hb => ?_⟩, Sym2.eq_swap⟩ + rw [openSegment_symm] at hw + exact hw (f γ) (by rw [hFT]; exact Finset.mem_image_of_mem _ hγ) ((hseg β α hlt γ).2 hb) + · rintro ⟨⟨α, β⟩, hp, rfl⟩ + rw [mem_consR] at hp + obtain ⟨hα, hβ, hlt, hw⟩ := hp + refine ⟨f α, f β, ?_, ?_, fun h => ne_of_lt hlt (hf h), ?_, rfl⟩ + · rw [hFT]; exact Finset.mem_image_of_mem _ hα + · rw [hFT]; exact Finset.mem_image_of_mem _ hβ + · intro w hwF hwseg + rw [hFT, Finset.mem_image] at hwF + obtain ⟨γ, hγ, rfl⟩ := hwF + exact hw γ hγ ((hseg α β hlt γ).1 hwseg) + have hinj : Set.InjOn (fun p : ℝ × ℝ => s(f p.1, f p.2)) ↑(consR T) := by + rintro ⟨p1, p2⟩ hp ⟨q1, q2⟩ hq h + simp only [Finset.mem_coe, mem_consR] at hp hq + simp only [Sym2.eq_iff] at h + rcases h with ⟨h1, h2⟩ | ⟨h1, h2⟩ + · rw [hf h1, hf h2] + · have := hf h1; have := hf h2 + exfalso; linarith [hp.2.2.1, hq.2.2.1] + have hTne : T.Nonempty := by + obtain ⟨z, hz⟩ := hne + rw [hFT, Finset.mem_image] at hz + obtain ⟨t, ht, -⟩ := hz + exact ⟨t, ht⟩ + rw [e, Finset.card_image_of_injOn hinj, consR_card T hTne, hFT, + Finset.card_image_of_injective _ hf] + +/-- Sets with no two common points have disjoint `consF`. -/ +private lemma disjoint_consF {F G : Finset ℂ} + (h : ∀ u v, u ≠ v → u ∈ F → v ∈ F → u ∈ G → v ∈ G → False) : + Disjoint (consF F) (consF G) := by + rw [Finset.disjoint_left] + intro e h1 h2 + obtain ⟨u, v, hu, hv, huv, -, rfl⟩ := mem_consF.1 h1 + obtain ⟨-, hu', hv', -⟩ := mem_consF_pair.1 h2 + exact h u v huv hu hv hu' hv' + +/-! ### The planar graph -/ + +/-- Adjacency in the planar graph. -/ +private lemma adj_iff {B : Finset ℂ} {u v : ℂ} : (planarGraph B).Adj u v ↔ + u ≠ v ∧ u ∈ vertices B ∧ v ∈ vertices B ∧ (∃ s ∈ drawn B, u ∈ s ∧ v ∈ s) ∧ + ∀ w ∈ vertices B, w ∉ openSegment ℝ u v := by + rw [planarGraph, SimpleGraph.fromRel_adj] + constructor + · rintro ⟨huv, h | h⟩ + · exact ⟨huv, h⟩ + · obtain ⟨hv, hu, ⟨s, hs, hvs, hus⟩, hw⟩ := h + refine ⟨huv, hu, hv, ⟨s, hs, hus, hvs⟩, fun w hwV => ?_⟩ + rw [openSegment_symm]; exact hw w hwV + · rintro ⟨huv, h⟩; exact ⟨huv, Or.inl h⟩ + +/-- Edges inside a convex piece `M` of the drawing whose vertices are `F`. -/ +private lemma consF_iff {B : Finset ℂ} {M : Set ℂ} (hM : Convex ℝ M) {F : Finset ℂ} + (hF : vertices B ∩ M = ↑F) {u v : ℂ} : + s(u, v) ∈ consF F ↔ u ≠ v ∧ u ∈ vertices B ∧ v ∈ vertices B ∧ u ∈ M ∧ v ∈ M ∧ + ∀ w ∈ vertices B, w ∉ openSegment ℝ u v := by + have key : ∀ z, z ∈ F ↔ z ∈ vertices B ∧ z ∈ M := by + intro z; rw [← Finset.mem_coe, ← hF]; rfl + rw [mem_consF_pair, key u, key v] + constructor + · rintro ⟨huv, ⟨hu, huM⟩, ⟨hv, hvM⟩, hw⟩ + refine ⟨huv, hu, hv, huM, hvM, fun w hwV hwo => ?_⟩ + exact hw w ((key w).2 ⟨hwV, hM.segment_subset huM hvM + (openSegment_subset_segment _ _ _ hwo)⟩) hwo + · rintro ⟨huv, hu, hv, huM, hvM, hw⟩ + exact ⟨huv, ⟨hu, huM⟩, ⟨hv, hvM⟩, fun w hwF => hw w ((key w).1 hwF).1⟩ + +/-- A chord does not cross itself. -/ +private lemma crossR_irrefl (c : ℝ × ℝ) : ¬ crossR c c := by + unfold crossR + rintro (⟨h1, -⟩ | ⟨h1, -⟩) <;> exact lt_irrefl _ h1 + +/-- The edge set as a finite set. -/ +private noncomputable def EF (T : Finset ℝ) : Finset (Sym2 ℂ) := + (Finset.univ.biUnion fun j => consF (VS T j)) ∪ ((Ch T).biUnion fun c => consF (VC T c)) + +section +variable {T : Finset ℝ} (hT : Good T) {B : Finset ℂ} (hB : B = T.image P) + (hGP : GeneralPosition B) (hcB : ∀ j : Fin 3, corner j ∈ B) +include hT hB hGP hcB + +omit hT hB hGP in +/-- The sides are drawn. -/ +private lemma side_mem_drawn (j : Fin 3) : side j ∈ drawn B := + ⟨corner j, hcB j, corner (j + 1), hcB (j + 1), corner_ne j, rfl⟩ + +/-- The edge set is the union of the consecutive pairs on the sides and on the chords. -/ +private lemma edgeSet_eq : (planarGraph B).edgeSet = ↑(EF T) := by + ext e + induction e using Sym2.ind with + | _ u v => + rw [SimpleGraph.mem_edgeSet, adj_iff, Finset.mem_coe, EF, Finset.mem_union, + Finset.mem_biUnion, Finset.mem_biUnion] + constructor + · rintro ⟨huv, hu, hv, ⟨s, hs, hus, hvs⟩, hw⟩ + obtain ⟨e, he, f, hf, hef, rfl⟩ := (mem_drawn hT hB).1 hs + rcases classify hT he hf hef with ⟨d, hd, hdt⟩ | ⟨j, -, -, hsub⟩ + · right + rw [hdt] at hus hvs + exact ⟨d, hd, (consF_iff (convex_segment _ _) (V_chord hT hB hGP hd)).2 + ⟨huv, hu, hv, hus, hvs, hw⟩⟩ + · left + exact ⟨j, Finset.mem_univ _, (consF_iff (convex_segment _ _) (V_side hT hB hcB j)).2 + ⟨huv, hu, hv, hsub hus, hsub hvs, hw⟩⟩ + · rintro (⟨j, -, h⟩ | ⟨c, hc, h⟩) + · obtain ⟨huv, hu, hv, huM, hvM, hw⟩ := + (consF_iff (convex_segment _ _) (V_side hT hB hcB j)).1 h + exact ⟨huv, hu, hv, ⟨side j, side_mem_drawn hcB j, huM, hvM⟩, hw⟩ + · obtain ⟨huv, hu, hv, huM, hvM, hw⟩ := + (consF_iff (convex_segment _ _) (V_chord hT hB hGP hc)).1 h + exact ⟨huv, hu, hv, ⟨seg c, seg_mem_drawn hT hB hc, huM, hvM⟩, hw⟩ + +omit hGP in +/-- The vertices of a side lie on it. -/ +private lemma VS_sub (j : Fin 3) : ↑(VS T j) ⊆ side j := by + rw [← V_side hT hB hcB j]; exact Set.inter_subset_right + +omit hcB in +/-- The vertices of a chord lie on it. -/ +private lemma VC_sub {c : ℝ × ℝ} (hc : c ∈ Ch T) : ↑(VC T c) ⊆ seg c := by + rw [← V_chord hT hB hGP hc]; exact Set.inter_subset_right + +omit hB hGP hcB in +/-- Distinct chords are distinct segments. -/ +private lemma seg_ne {c d : ℝ × ℝ} (hc : c ∈ Ch T) (hd : d ∈ Ch T) (hcd : c ≠ d) : + seg c ≠ seg d := by + intro h + have h1 : P c.1 ∈ seg c := left_mem_segment _ _ _ + have h2 : P c.2 ∈ seg c := right_mem_segment _ _ _ + have h1' := h1; have h2' := h2 + rw [h] at h1' h2' + exact chord_ne hT hc (seg_inter_unique hT hc hd hcd h1 h1' h2 h2') + +omit hcB in +/-- A chord carries its two endpoints and one vertex for each chord crossing it. -/ +private lemma VC_card {c : ℝ × ℝ} (hc : c ∈ Ch T) : + (VC T c).card = ((Ch T).filter (crossR c)).card + 2 := by + have hX : ∀ d ∈ (Ch T).filter (crossR c), X c d ∈ oseg c := by + intro d hd + rw [Finset.mem_filter] at hd + exact (X_mem hT hc hd.1 hd.2).1 + have hne := endpoint_not_oseg hT hc + have hinj : Set.InjOn (X c) ↑((Ch T).filter (crossR c)) := by + intro d hd d' hd' hdd + by_contra hne' + simp only [Finset.coe_filter, Set.mem_ofPred_eq] at hd hd' + have hz := X_mem hT hc hd.1 hd.2 + have hz' := X_mem hT hc hd'.1 hd'.2 + rw [← hdd] at hz' + have hcd : c ≠ d := fun e => crossR_irrefl c (e ▸ hd.2) + have hcd' : c ≠ d' := fun e => crossR_irrefl c (e ▸ hd'.2) + rcases hGP (X c d) (oseg_interior hT hc hz.1) (seg c) (seg_mem_drawn hT hB hc) + (seg d) (seg_mem_drawn hT hB hd.1) (seg d') (seg_mem_drawn hT hB hd'.1) + (openSegment_subset_segment _ _ _ hz.1) (openSegment_subset_segment _ _ _ hz.2) + (openSegment_subset_segment _ _ _ hz'.2) with h | h | h + · exact seg_ne hT hc hd.1 hcd h + · exact seg_ne hT hc hd'.1 hcd' h + · exact seg_ne hT hd.1 hd'.1 hne' h + rw [VC, Finset.card_insert_of_notMem, Finset.card_insert_of_notMem, + Finset.card_image_of_injOn hinj] + · intro h + obtain ⟨d, hd, e⟩ := Finset.mem_image.1 h + exact hne.2 (e ▸ hX d hd) + · intro h + rw [Finset.mem_insert] at h + rcases h with h | h + · exact chord_ne hT hc h + · obtain ⟨d, hd, e⟩ := Finset.mem_image.1 h + exact hne.1 (e ▸ hX d hd) + +omit hB hGP hcB in +/-- A side carries one vertex per parameter of the side. -/ +private lemma VS_card (j : Fin 3) : (VS T j).card = (T.filter (Sd j)).card := by + classical + rw [VS, Finset.card_image_of_injOn] + intro s hs t ht h + simp only [Finset.coe_filter, Set.mem_ofPred_eq] at hs ht + exact P_injT hT hs.1 ht.1 h + +/-- The edge count is the sum over the sides and the chords. -/ +private lemma EF_card : + (EF T).card = ∑ j, (consF (VS T j)).card + ∑ c ∈ Ch T, (consF (VC T c)).card := by + have hC : ((Ch T : Set (ℝ × ℝ))).PairwiseDisjoint (fun c => consF (VC T c)) := by + intro c hc d hd hcd + apply disjoint_consF + intro u v huv hu hv hu' hv' + exact huv (seg_inter_unique hT hc hd hcd (VC_sub hT hB hGP hc hu) + (VC_sub hT hB hGP hd hu') (VC_sub hT hB hGP hc hv) (VC_sub hT hB hGP hd hv')) + have hS : ((Finset.univ : Finset (Fin 3)) : Set (Fin 3)).PairwiseDisjoint + (fun j => consF (VS T j)) := by + intro j _ j' _ hjj + apply disjoint_consF + intro u v huv hu hv hu' hv' + obtain ⟨c, -, hc⟩ := Sd_inter hjj + obtain ⟨s, hs, hs1, rfl⟩ := mem_VS.1 hu + obtain ⟨t, ht, ht1, rfl⟩ := mem_VS.1 hv + obtain ⟨s', hs', hs2, e1⟩ := mem_VS.1 hu' + obtain ⟨t', ht', ht2, e2⟩ := mem_VS.1 hv' + rw [P_injT hT hs' hs e1] at hs2 + rw [P_injT hT ht' ht e2] at ht2 + exact huv (by rw [hc s hs1 hs2, hc t ht1 ht2]) + have hD : Disjoint (Finset.univ.biUnion fun j => consF (VS T j)) + ((Ch T).biUnion fun c => consF (VC T c)) := by + rw [Finset.disjoint_left] + intro e h1 h2 + rw [Finset.mem_biUnion] at h1 h2 + obtain ⟨j, -, hj⟩ := h1 + obtain ⟨c, hc, hcc⟩ := h2 + obtain ⟨u, v, hu, hv, huv, -, rfl⟩ := mem_consF.1 hj + obtain ⟨-, hu', hv', -⟩ := mem_consF_pair.1 hcc + have hus := VS_sub hT hB hcB j hu + have hvs := VS_sub hT hB hcB j hv + have huc := VC_sub hT hB hGP hc hu' + have hvc := VC_sub hT hB hGP hc hv' + have hend : ∀ z, z ∈ side j → z ∈ seg c → z = P c.1 ∨ z = P c.2 := by + intro z hz hz' + by_contra hn + push Not at hn + exact oseg_not_side hT hc (mem_oseg_of hc hz' hn.1 hn.2) j hz + have hc' := mem_Ch.1 hc + have key : P c.1 ∈ side j ∧ P c.2 ∈ side j := by + rcases hend u hus huc with h1 | h1 <;> rcases hend v hvs hvc with h2 | h2 + · exact absurd (h1.trans h2.symm) huv + · exact ⟨h1 ▸ hus, h2 ▸ hvs⟩ + · exact ⟨h2 ▸ hvs, h1 ▸ hus⟩ + · exact absurd (h1.trans h2.symm) huv + have k1 := (P_mem_side_iff (hT _ hc'.1).1 (hT _ hc'.1).2).1 key.1 + have k2 := (P_mem_side_iff (hT _ hc'.2.1).1 (hT _ hc'.2.1).2).1 key.2 + exact hc'.2.2.2 ((coSide_iff _ _).2 ⟨j, k1, k2⟩) + rw [EF, Finset.card_union_of_disjoint hD, Finset.card_biUnion hS, Finset.card_biUnion hC] + +/-- The number of edges, from the parameters. -/ +private lemma edges_eq : edges B = + ∑ j, ((T.filter (Sd j)).card - 1) + ∑ c ∈ Ch T, (((Ch T).filter (crossR c)).card + 1) := by + rw [edges, edgeSet_eq hT hB hGP hcB, Set.ncard_coe_finset, EF_card hT hB hGP hcB] + congr 1 + · refine Finset.sum_congr rfl fun j _ => ?_ + have hne : (VS T j).Nonempty := ⟨corner j, by + rw [← Finset.mem_coe, ← V_side hT hB hcB j] + exact ⟨(mem_vertices).2 (Or.inl (hcB j)), left_mem_segment _ _ _⟩⟩ + have := consF_card (corner_ne j) (VS T j) (VS_sub hT hB hcB j) hne + rw [VS_card hT j] at this + omega + · refine Finset.sum_congr rfl fun c hc => ?_ + have hne : (VC T c).Nonempty := ⟨P c.1, Finset.mem_insert_self _ _⟩ + have := consF_card (chord_ne hT hc) (VC T c) (VC_sub hT hB hGP hc) hne + rw [VC_card hT hB hGP hc] at this + omega + +end + +/-- The open parameter interval of side 0. -/ +private lemma Od_zero (t : ℝ) : Od 0 t ↔ 0 < t ∧ t < 1 := Iff.rfl +/-- The open parameter interval of side 1. -/ +private lemma Od_one (t : ℝ) : Od 1 t ↔ 1 < t ∧ t < 2 := Iff.rfl +/-- The open parameter interval of side 2. -/ +private lemma Od_two (t : ℝ) : Od 2 t ↔ 2 < t := Iff.rfl + +/-- The parameters of a placement. -/ +private lemma exists_T {n : ℕ} {B : Finset ℂ} (hB : IsPlacement n B) : + ∃ T : Finset ℝ, Good T ∧ B = T.image P ∧ T.card = 3 * n + 3 ∧ + (T.filter S0).card = n + 2 ∧ (T.filter S1).card = n + 2 ∧ (T.filter S2).card = n + 2 := by + obtain ⟨hc, hs, ho⟩ := hB + have key : ∀ z ∈ B, 0 ≤ θ z ∧ θ z < 3 ∧ P (θ z) = z := by + intro z hz + obtain ⟨j, hj⟩ := hs z hz + obtain ⟨t, h0, h3, -, rfl⟩ := exists_P_of_mem_side (j := j) hj + rw [θ_P h0 h3]; exact ⟨h0, h3, rfl⟩ + set T := B.image θ with hTdef + have hT : Good T := by + intro t ht + obtain ⟨z, hz, rfl⟩ := Finset.mem_image.1 ht + exact ⟨(key z hz).1, (key z hz).2.1⟩ + have hBT : B = T.image P := by + ext z + rw [Finset.mem_image] + constructor + · intro hz; exact ⟨θ z, Finset.mem_image_of_mem _ hz, (key z hz).2.2⟩ + · rintro ⟨t, ht, rfl⟩ + obtain ⟨w, hw, rfl⟩ := Finset.mem_image.1 ht + rw [(key w hw).2.2]; exact hw + have hPB : ∀ t ∈ T, P t ∈ B := by + intro t ht; rw [hBT]; exact Finset.mem_image_of_mem _ ht + have hmemT : ∀ t : ℝ, 0 ≤ t → t < 3 → P t ∈ B → t ∈ T := by + intro t h0 h3 hP + rw [← θ_P h0 h3]; exact Finset.mem_image_of_mem _ hP + have h0T : (0:ℝ) ∈ T := hmemT 0 (le_refl _) (by norm_num) (P_zero ▸ hc 0) + have h1T : (1:ℝ) ∈ T := hmemT 1 (by norm_num) (by norm_num) (P_one ▸ hc 1) + have h2T : (2:ℝ) ∈ T := hmemT 2 (by norm_num) (by norm_num) (P_two ▸ hc 2) + have hO : ∀ j : Fin 3, (T.filter (Od j)).card = n := by + intro j + have e : (B : Set ℂ) ∩ openSegment ℝ (corner j) (corner (j + 1)) = + ↑((T.filter (Od j)).image P) := by + ext z + simp only [Set.mem_inter_iff, Finset.mem_coe, Finset.coe_image, Finset.coe_filter, + Set.mem_image, Set.mem_ofPred_eq] + constructor + · rintro ⟨hz, hzo⟩ + have hk := key z hz + refine ⟨θ z, ⟨Finset.mem_image_of_mem _ hz, ?_⟩, hk.2.2⟩ + rw [← P_mem_openSide_iff hk.1 hk.2.1, hk.2.2]; exact hzo + · rintro ⟨t, ⟨ht, hod⟩, rfl⟩ + exact ⟨hPB t ht, (P_mem_openSide_iff (hT t ht).1 (hT t ht).2).2 hod⟩ + have := ho j + rw [e, Set.ncard_coe_finset, Finset.card_image_of_injOn] at this + · exact this + · intro s hs t ht h + simp only [Finset.coe_filter, Set.mem_ofPred_eq] at hs ht + exact P_injT hT hs.1 ht.1 h + have hO0 := hO 0 + have hO1 := hO 1 + have hO2 := hO 2 + refine ⟨T, hT, hBT, ?_, ?_, ?_, ?_⟩ + · have e : T = insert 0 (insert 1 (insert 2 + ((T.filter (Od 0) ∪ T.filter (Od 1)) ∪ T.filter (Od 2)))) := by + ext t + simp only [Finset.mem_insert, Finset.mem_union, Finset.mem_filter, Od_zero, Od_one, + Od_two] + constructor + · intro ht + obtain ⟨h0, h3⟩ := hT t ht + rcases eq_or_lt_of_le h0 with h | h + · exact Or.inl h.symm + rcases lt_trichotomy t 1 with h1 | h1 | h1 + · exact Or.inr (Or.inr (Or.inr (Or.inl (Or.inl ⟨ht, h, h1⟩)))) + · exact Or.inr (Or.inl h1) + rcases lt_trichotomy t 2 with h2 | h2 | h2 + · exact Or.inr (Or.inr (Or.inr (Or.inl (Or.inr ⟨ht, h1, h2⟩)))) + · exact Or.inr (Or.inr (Or.inl h2)) + · exact Or.inr (Or.inr (Or.inr (Or.inr ⟨ht, h2⟩))) + · rintro (rfl | rfl | rfl | ((⟨ht, -⟩ | ⟨ht, -⟩) | ⟨ht, -⟩)) + · exact h0T + · exact h1T + · exact h2T + · exact ht + · exact ht + · exact ht + have d1 : Disjoint (T.filter (Od 0)) (T.filter (Od 1)) := by + rw [Finset.disjoint_left] + intro t h h' + simp only [Finset.mem_filter, Od_zero, Od_one] at h h' + linarith [h.2.2, h'.2.1] + have d2 : Disjoint (T.filter (Od 0) ∪ T.filter (Od 1)) (T.filter (Od 2)) := by + rw [Finset.disjoint_left] + intro t h h' + simp only [Finset.mem_union, Finset.mem_filter, Od_zero, Od_one, Od_two] at h h' + rcases h with h | h + · linarith [h.2.2] + · linarith [h.2.2] + rw [e, Finset.card_insert_of_notMem, Finset.card_insert_of_notMem, + Finset.card_insert_of_notMem, Finset.card_union_of_disjoint d2, + Finset.card_union_of_disjoint d1, hO0, hO1, hO2] + · ring + · simp only [Finset.mem_union, Finset.mem_filter, Od_zero, Od_one, Od_two] + norm_num + · simp only [Finset.mem_insert, Finset.mem_union, Finset.mem_filter, Od_zero, Od_one, + Od_two] + norm_num + · simp only [Finset.mem_insert, Finset.mem_union, Finset.mem_filter, Od_zero, Od_one, + Od_two] + norm_num + · have e : T.filter S0 = insert 0 (insert 1 (T.filter (Od 0))) := by + ext t + simp only [Finset.mem_insert, Finset.mem_filter, Od_zero, S0] + constructor + · rintro ⟨ht, h1⟩ + obtain ⟨h0, -⟩ := hT t ht + rcases eq_or_lt_of_le h0 with h | h + · exact Or.inl h.symm + rcases eq_or_lt_of_le h1 with h' | h' + · exact Or.inr (Or.inl h') + · exact Or.inr (Or.inr ⟨ht, h, h'⟩) + · rintro (rfl | rfl | ⟨ht, -, h⟩) + · exact ⟨h0T, by norm_num⟩ + · exact ⟨h1T, le_refl _⟩ + · exact ⟨ht, h.le⟩ + rw [e, Finset.card_insert_of_notMem, Finset.card_insert_of_notMem, hO0] + · simp only [Finset.mem_filter, Od_zero]; norm_num + · simp only [Finset.mem_insert, Finset.mem_filter, Od_zero]; norm_num + · have e : T.filter S1 = insert 1 (insert 2 (T.filter (Od 1))) := by + ext t + simp only [Finset.mem_insert, Finset.mem_filter, Od_one, S1] + constructor + · rintro ⟨ht, h1, h2⟩ + rcases eq_or_lt_of_le h1 with h | h + · exact Or.inl h.symm + rcases eq_or_lt_of_le h2 with h' | h' + · exact Or.inr (Or.inl h') + · exact Or.inr (Or.inr ⟨ht, h, h'⟩) + · rintro (rfl | rfl | ⟨ht, h, h'⟩) + · exact ⟨h1T, le_refl _, by norm_num⟩ + · exact ⟨h2T, by norm_num, le_refl _⟩ + · exact ⟨ht, h.le, h'.le⟩ + rw [e, Finset.card_insert_of_notMem, Finset.card_insert_of_notMem, hO1] + · simp only [Finset.mem_filter, Od_one]; norm_num + · simp only [Finset.mem_insert, Finset.mem_filter, Od_one]; norm_num + · have e : T.filter S2 = insert 2 (insert 0 (T.filter (Od 2))) := by + ext t + simp only [Finset.mem_insert, Finset.mem_filter, Od_two, S2] + constructor + · rintro ⟨ht, h | h⟩ + · rcases eq_or_lt_of_le h with h' | h' + · exact Or.inl h'.symm + · exact Or.inr (Or.inr ⟨ht, h'⟩) + · exact Or.inr (Or.inl h) + · rintro (rfl | rfl | ⟨ht, h⟩) + · exact ⟨h2T, Or.inl (le_refl _)⟩ + · exact ⟨h0T, Or.inr rfl⟩ + · exact ⟨ht, Or.inl h.le⟩ + rw [e, Finset.card_insert_of_notMem, Finset.card_insert_of_notMem, hO2] + · simp only [Finset.mem_filter, Od_two]; norm_num + · simp only [Finset.mem_insert, Finset.mem_filter, Od_two]; norm_num + +/-- The conjecture of A367119: the all-chords graph of a triangle with `n` points in general +position on each side has `(3/2)(3n^4 + 4n^3 + 3n^2 + 4n + 2)` edges. -/ +theorem result : statement := by + intro n B hB hGP + have hcB : ∀ j : Fin 3, corner j ∈ B := hB.1 + obtain ⟨T, hT, hBT, hN, c0, c1, c2⟩ := exists_T hB + have e0 : T.filter (Sd 0) = T.filter S0 := Finset.filter_congr (fun x _ => Iff.rfl) + have e1 : T.filter (Sd 1) = T.filter S1 := Finset.filter_congr (fun x _ => Iff.rfl) + have e2 : T.filter (Sd 2) = T.filter S2 := Finset.filter_congr (fun x _ => Iff.rfl) + have hE : edges B = 3 * (n + 1) + + ((∑ c ∈ Ch T, ((Ch T).filter (crossR c)).card) + (Ch T).card) := by + rw [edges_eq hT hBT hGP hcB, Fin.sum_univ_three, e0, e1, e2, c0, c1, c2, + Finset.sum_add_distrib, Finset.sum_const, smul_eq_mul, mul_one] + omega + have h1 := crossings_formula n T (fun t ht => (hT t ht).1) hN c0 c1 c2 + have h2 := chords_card n T hN c0 c1 c2 + rw [hE, Nat.cast_add, Nat.cast_add, h1, h2] + push_cast + ring + +end Math0.Frontier.A367119 + +#math0_settles Math0.Frontier.A367119.result Math0.Statements.A367119.statement diff --git a/lean/Math0/Frontier/OEIS/A368846.lean b/lean/Math0/Frontier/OEIS/A368846.lean new file mode 100644 index 0000000..4033f3e --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A368846.lean @@ -0,0 +1,418 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A368846 +import Math0.Audit + +/-! +# Diagonal sums of A368846 equal A229580 (Luschny's conjecture) + +We prove `|∑_{j=0}^{k} T(k+j, k)| = A229580(k+1)` for all `k`; both sides equal +`(2k+1)·2^(2k-1)` for `k ≥ 1` (and `1` for `k = 0`). + +**The sum.** For `k = m+1` and `N = 2m+1`, the terms with `n = k+j` outside `[0, N]` vanish +(`C(2n+1, 2k) = 0` for `n < k`, `C(N, 2k) = 0`), so the sum is +`2(-1)^k ∑_{n=0}^{N} (-1)^n C(N,n) C(2n+1,2k)`. The inner sum is the coefficient of `X^(2k)` in +`(1+X)(1-(1+X)²)^N = -(1+X) X^N (X+2)^N`, i.e. `-([X¹] + [X⁰])(X+2)^N = -(N 2^(N-1) + 2^N)`. + +**The count.** Numbering the cells in row-major order turns the array graph into a path, a +coloring into a word of length `2n` over `{0,1,2}`, the mistakes into equal adjacent letters, +and "colors introduced in order" into: the word starts with `0` and every `2` is preceded by a +`1` (`Q2`). Peeling off the first letter gives recursions: proper words with a given first +letter number `2^M`, words with one mistake and given first letter `(M+1)2^M`, and the target +words of length `M+3` number `2^M + (M+1)2^M = (M+2)2^M`. +-/ + +namespace Math0.Frontier.A368846 +open Math0.Statements.A368846 Polynomial Finset + +/-- Generating function: `∑ₙ (-1)ⁿ C(N,n) C(2n+1,j)` is the coefficient of `X^j` in `(1+X)(1-(1+X)²)^N`. -/ +private theorem polySum (N j : ℕ) : + ∑ n ∈ Finset.range (N + 1), (-1 : ℤ) ^ n * (N.choose n : ℤ) * ((2 * n + 1).choose j : ℤ) = + ((1 + X : ℤ[X]) * (-(1 + X) ^ 2 + 1) ^ N).coeff j := by + rw [add_pow, Finset.mul_sum, finsetSum_coeff] + refine Finset.sum_congr rfl fun n _ => ?_ + have : (1 + X : ℤ[X]) * ((-(1 + X) ^ 2) ^ n * 1 ^ (N - n) * (N.choose n : ℤ[X])) = + C ((-1 : ℤ) ^ n * (N.choose n : ℤ)) * (1 + X) ^ (2 * n + 1) := by + simp only [map_mul, map_pow, map_neg, map_one, map_natCast, one_pow, mul_one] + rw [neg_pow, ← pow_mul] + ring + rw [this, coeff_C_mul, coeff_one_add_X_pow] + +/-- Since `1-(1+X)² = -X(X+2)`, the coefficient of `X^(2m+2)` in `(1+X)(1-(1+X)²)^(2m+1)` equals `-[X¹]((1+X)(X+2)^(2m+1)) = -(2m+3)·4^m`. -/ +private theorem polyVal (m : ℕ) : + ((1 + X : ℤ[X]) * (-(1 + X) ^ 2 + 1) ^ (2 * m + 1)).coeff (2 * m + 2) = + -((2 * m + 3 : ℤ) * 2 ^ (2 * m)) := by + have h : (1 + X : ℤ[X]) * (-(1 + X) ^ 2 + 1) ^ (2 * m + 1) = + C (-1) * (X ^ (2 * m + 1) * ((X + C 2) ^ (2 * m + 1) + X * (X + C 2) ^ (2 * m + 1))) := by + rw [show (-(1 + X) ^ 2 + 1 : ℤ[X]) = -X * (X + C 2) by simp only [map_ofNat]; ring] + rw [mul_pow, neg_pow, pow_succ (-1 : ℤ[X]), pow_mul] + simp only [map_neg, map_one, map_ofNat] + ring + rw [h, coeff_C_mul, coeff_X_pow_mul', if_pos (by omega), show 2 * m + 2 - (2 * m + 1) = 0 + 1 by omega, + coeff_add, coeff_X_mul, coeff_X_add_C_pow, coeff_X_add_C_pow] + simp only [zero_add, Nat.choose_one_right, Nat.choose_zero_right, Nat.sub_zero, Nat.add_sub_cancel] + push_cast + ring + + +/-- Closed form of the column sum: `∑_{j=0}^{m+1} T(m+1+j, m+1) = (-1)^m (2m+3) 2^(2m+1)`. -/ +private theorem sumT (m : ℕ) : ∑ j ∈ Finset.range (m + 1 + 1), T (m + 1 + j) (m + 1) = + (-1) ^ m * ((2 * m + 3 : ℤ) * 2 ^ (2 * m + 1)) := by + have hT : ∀ n, T n (m + 1) = 2 * (-1) ^ (m + 1) * + ((-1) ^ n * ((2 * m + 1).choose n : ℤ) * ((2 * n + 1).choose (2 * m + 2) : ℤ)) := by + intro n + simp only [T, Nat.add_one_ne_zero, if_false] + rw [show 2 * (m + 1) - 1 = 2 * m + 1 by omega, show 2 * (m + 1) = 2 * m + 2 by ring] + ring + have h1 : ∑ n ∈ Finset.range (2 * m + 3), T n (m + 1) = + ∑ n ∈ Finset.range (m + 1), T n (m + 1) + + ∑ j ∈ Finset.range (m + 1 + 1), T (m + 1 + j) (m + 1) := by + rw [← Finset.sum_range_add] + congr 2 + omega + have h2 : ∑ n ∈ Finset.range (m + 1), T n (m + 1) = 0 := by + refine Finset.sum_eq_zero fun n hn => ?_ + rw [Finset.mem_range] at hn + rw [hT, Nat.choose_eq_zero_of_lt (by omega : 2 * n + 1 < 2 * m + 2)] + simp + have h3 : ∑ n ∈ Finset.range (2 * m + 3), T n (m + 1) = + ∑ n ∈ Finset.range (2 * m + 1 + 1), T n (m + 1) := by + rw [Finset.sum_range_succ _ (2 * m + 2), hT (2 * m + 2), + Nat.choose_eq_zero_of_lt (by omega : 2 * m + 1 < 2 * m + 2)] + simp + rw [← zero_add (∑ j ∈ Finset.range (m + 1 + 1), T (m + 1 + j) (m + 1)), ← h2, ← h1, h3] + simp_rw [hT] + rw [← Finset.mul_sum, polySum, polyVal] + ring + +/-- Absolute value of the column sum for `k = m+1`. -/ +private theorem absSumT (m : ℕ) : |∑ j ∈ Finset.range (m + 1 + 1), T (m + 1 + j) (m + 1)| = + (2 * m + 3 : ℤ) * 2 ^ (2 * m + 1) := by + rw [sumT, abs_mul, abs_pow, abs_neg, abs_one, one_pow, one_mul, abs_of_nonneg (by positivity)] + + +/-- Number of mistakes of a word `w` of length `M+1`: adjacent positions with equal letters. -/ +private def wmis {M : ℕ} (w : Fin (M + 1) → Fin 3) : ℕ := + ∑ i : Fin M, if w i.castSucc = w i.succ then 1 else 0 + +/-- Every letter `2` of the word is preceded (strictly earlier) by a letter `1`. -/ +private def Q2 {L : ℕ} (w : Fin L → Fin 3) : Prop := ∀ i, w i = 2 → ∃ j, j < i ∧ w j = 1 + +/-- Decidability of `Q2`. -/ +private instance {L : ℕ} : DecidablePred (Q2 (L := L)) := fun w => by unfold Q2; infer_instance + +/-- Mistakes of `a :: u`. -/ +private theorem wmis_cons {M : ℕ} (a : Fin 3) (u : Fin (M + 1) → Fin 3) : + wmis (Fin.cons a u : Fin (M + 2) → Fin 3) = (if a = u 0 then 1 else 0) + wmis u := by + unfold wmis + rw [Fin.sum_univ_succ] + congr 1 + +/-- `Q2 (a :: u)` holds iff `a = 1`, or `a = 0` and `Q2 u`. -/ +private theorem Q2_cons {M : ℕ} (a : Fin 3) (u : Fin (M + 1) → Fin 3) : + Q2 (Fin.cons a u : Fin (M + 2) → Fin 3) ↔ (a = 1 ∨ (a = 0 ∧ Q2 u)) := by + constructor + · intro h + fin_cases a + · refine Or.inr ⟨rfl, fun i hi => ?_⟩ + obtain ⟨j, hj, hj1⟩ := h i.succ (by simpa using hi) + cases j using Fin.cases with + | zero => simp at hj1 + | succ j => exact ⟨j, Fin.succ_lt_succ_iff.mp hj, by simpa using hj1⟩ + · exact Or.inl rfl + · obtain ⟨j, hj, -⟩ := h 0 (by simp) + exact absurd hj (Fin.not_lt_zero j) + · rintro (rfl | ⟨rfl, h⟩) i hi + · cases i using Fin.cases with + | zero => simp at hi + | succ i => exact ⟨0, Fin.succ_pos i, by simp⟩ + · cases i using Fin.cases with + | zero => simp at hi + | succ i => + obtain ⟨j, hj, hj1⟩ := h i (by simpa using hi) + exact ⟨j.succ, Fin.succ_lt_succ_iff.mpr hj, by simpa using hj1⟩ + +/-- A word starting with `1` satisfies `Q2`. -/ +private theorem Q2_of_one {M : ℕ} (u : Fin (M + 1) → Fin 3) (h : u 0 = 1) : Q2 u := by + intro i hi + refine ⟨0, ?_, h⟩ + rw [Fin.pos_iff_ne_zero] + rintro rfl + rw [h] at hi + exact absurd hi (by decide) + +/-- A word starting with `2` fails `Q2`. -/ +private theorem not_Q2_of_two {M : ℕ} (u : Fin (M + 1) → Fin 3) (h : u 0 = 2) : ¬ Q2 u := by + intro hq + obtain ⟨j, hj, -⟩ := hq 0 h + exact Fin.not_lt_zero j hj + +/-- Counting words of length `M+2` by their first letter and their tail. -/ +private theorem card_cons {M : ℕ} (P : (Fin (M + 2) → Fin 3) → Prop) [DecidablePred P] : + (univ.filter P).card = + ∑ a : Fin 3, (univ.filter fun u : Fin (M + 1) → Fin 3 => P (Fin.cons a u)).card := by + simp only [card_filter] + rw [← (Fin.consEquiv fun _ => Fin 3).sum_comp, Fintype.sum_prod_type] + rfl + +/-- Splitting a count of words according to the first letter. -/ +private theorem card_split {M : ℕ} (Q : Fin 3 → (Fin (M + 1) → Fin 3) → Prop) + [∀ c, DecidablePred (Q c)] : + (univ.filter fun u => Q (u 0) u).card = + ∑ c : Fin 3, (univ.filter fun u => u 0 = c ∧ Q c u).card := by + simp only [card_filter] + rw [Finset.sum_comm] + refine sum_congr rfl fun u _ => ?_ + rw [Finset.sum_eq_single (u 0)] + · simp + · intro c _ hc + simp [Ne.symm hc] + · simp + + +/-- Peel off a fixed first letter `b` and split on the next letter. -/ +private theorem card_first {M : ℕ} (b : Fin 3) (R : Fin 3 → (Fin (M + 1) → Fin 3) → Prop) + [∀ c, DecidablePred (R c)] (P : (Fin (M + 2) → Fin 3) → Prop) [DecidablePred P] + (hP : ∀ a u, P (Fin.cons a u) ↔ a = b ∧ R (u 0) u) : + (univ.filter P).card = ∑ c : Fin 3, (univ.filter fun u => u 0 = c ∧ R c u).card := by + rw [card_cons, ← card_split R] + rw [Finset.sum_eq_single b] + · simp only [hP, true_and] + · intro a _ hab + simp [hP, hab] + · simp + +/-- Proper words (no mistakes) of length `M+1` with a given first letter: `2^M`. -/ +private theorem N0 : ∀ M : ℕ, ∀ b : Fin 3, + (univ.filter fun v : Fin (M + 1) → Fin 3 => v 0 = b ∧ wmis v = 0).card = 2 ^ M := by + intro M + induction M with + | zero => decide + | succ M ih => + intro b + rw [card_first b (fun c u => (if b = c then 1 else 0) + wmis u = 0) _ + (fun a u => by simp only [Fin.cons_zero, wmis_cons]; constructor <;> rintro ⟨rfl, h⟩ <;> exact ⟨rfl, h⟩)] + have key : ∀ c, (univ.filter fun u : Fin (M + 1) → Fin 3 => + u 0 = c ∧ (if b = c then 1 else 0) + wmis u = 0).card = if b = c then 0 else 2 ^ M := by + intro c + split_ifs with h + · simp + · simpa using ih c + simp only [key] + fin_cases b <;> simp [Fin.sum_univ_three] <;> ring + + +/-- Words of length `M+2` with exactly one mistake and a given first letter: `(M+1)·2^M`. -/ +private theorem N1 : ∀ M : ℕ, ∀ b : Fin 3, + (univ.filter fun v : Fin (M + 2) → Fin 3 => v 0 = b ∧ wmis v = 1).card = (M + 1) * 2 ^ M := by + intro M + induction M with + | zero => decide + | succ M ih => + intro b + rw [card_first b (fun c u => (if b = c then 1 else 0) + wmis u = 1) _ + (fun a u => by simp only [Fin.cons_zero, wmis_cons]; constructor <;> rintro ⟨rfl, h⟩ <;> exact ⟨rfl, h⟩)] + have key : ∀ c, (univ.filter fun u : Fin (M + 2) → Fin 3 => + u 0 = c ∧ (if b = c then 1 else 0) + wmis u = 1).card = + if b = c then 2 ^ (M + 1) else (M + 1) * 2 ^ M := by + intro c + split_ifs with h + · simpa using N0 (M + 1) c + · simpa using ih c + simp only [key] + fin_cases b <;> simp [Fin.sum_univ_three] <;> ring + +/-- Proper words of length `M+2` starting with `0` and satisfying `Q2`: `2^M`. -/ +private theorem P0 (M : ℕ) : + (univ.filter fun v : Fin (M + 2) → Fin 3 => v 0 = 0 ∧ wmis v = 0 ∧ Q2 v).card = 2 ^ M := by + rw [card_first 0 (fun c u => (if (0 : Fin 3) = c then 1 else 0) + wmis u = 0 ∧ Q2 u) _ + (fun a u => by + simp only [Fin.cons_zero, wmis_cons, Q2_cons] + constructor + · rintro ⟨rfl, h, h'⟩ + exact ⟨rfl, h, by simpa using h'⟩ + · rintro ⟨rfl, h, h'⟩ + exact ⟨rfl, h, Or.inr ⟨rfl, h'⟩⟩)] + rw [Fin.sum_univ_three] + have e0 : (univ.filter fun u : Fin (M + 1) → Fin 3 => + u 0 = 0 ∧ (if (0 : Fin 3) = 0 then 1 else 0) + wmis u = 0 ∧ Q2 u).card = 0 := by + simp + have e1 : (univ.filter fun u : Fin (M + 1) → Fin 3 => + u 0 = 1 ∧ (if (0 : Fin 3) = 1 then 1 else 0) + wmis u = 0 ∧ Q2 u).card = 2 ^ M := by + rw [← N0 M 1] + congr 1 + refine Finset.filter_congr fun u _ => ?_ + constructor + · rintro ⟨h1, h2, -⟩ + exact ⟨h1, by simpa using h2⟩ + · rintro ⟨h1, h2⟩ + exact ⟨h1, by simpa using h2, Q2_of_one u h1⟩ + have e2 : (univ.filter fun u : Fin (M + 1) → Fin 3 => + u 0 = 2 ∧ (if (0 : Fin 3) = 2 then 1 else 0) + wmis u = 0 ∧ Q2 u).card = 0 := by + rw [Finset.card_eq_zero, Finset.filter_eq_empty_iff] + rintro u - ⟨h1, -, h3⟩ + exact not_Q2_of_two u h1 h3 + rw [e0, e1, e2] + ring + +/-- Words of length `M+3` with one mistake, starting with `0` and satisfying `Q2`: `(M+2)·2^M`. -/ +private theorem Tgt (M : ℕ) : + (univ.filter fun v : Fin (M + 3) → Fin 3 => wmis v = 1 ∧ v 0 = 0 ∧ Q2 v).card = + (M + 2) * 2 ^ M := by + rw [card_first 0 (fun c u => (if (0 : Fin 3) = c then 1 else 0) + wmis u = 1 ∧ Q2 u) _ + (fun a u => by + simp only [Fin.cons_zero, wmis_cons, Q2_cons] + constructor + · rintro ⟨h, rfl, h'⟩ + exact ⟨rfl, h, by simpa using h'⟩ + · rintro ⟨rfl, h, h'⟩ + exact ⟨h, rfl, Or.inr ⟨rfl, h'⟩⟩)] + rw [Fin.sum_univ_three] + have e0 : (univ.filter fun u : Fin (M + 2) → Fin 3 => + u 0 = 0 ∧ (if (0 : Fin 3) = 0 then 1 else 0) + wmis u = 1 ∧ Q2 u).card = 2 ^ M := by + rw [← P0 M] + congr 1 + refine Finset.filter_congr fun u _ => ?_ + constructor + · rintro ⟨h1, h2, h3⟩ + exact ⟨h1, by simpa using h2, h3⟩ + · rintro ⟨h1, h2, h3⟩ + exact ⟨h1, by simpa using h2, h3⟩ + have e1 : (univ.filter fun u : Fin (M + 2) → Fin 3 => + u 0 = 1 ∧ (if (0 : Fin 3) = 1 then 1 else 0) + wmis u = 1 ∧ Q2 u).card = (M + 1) * 2 ^ M := by + rw [← N1 M 1] + congr 1 + refine Finset.filter_congr fun u _ => ?_ + constructor + · rintro ⟨h1, h2, -⟩ + exact ⟨h1, by simpa using h2⟩ + · rintro ⟨h1, h2⟩ + exact ⟨h1, by simpa using h2, Q2_of_one u h1⟩ + have e2 : (univ.filter fun u : Fin (M + 2) → Fin 3 => + u 0 = 2 ∧ (if (0 : Fin 3) = 2 then 1 else 0) + wmis u = 1 ∧ Q2 u).card = 0 := by + rw [Finset.card_eq_zero, Finset.filter_eq_empty_iff] + rintro u - ⟨h1, -, h3⟩ + exact not_Q2_of_two u h1 h3 + rw [e0, e1, e2] + ring + + +/-- The row-major numbering of the cells of the `n X 2` array (`2n = M+1` cells). -/ +private def eqv (n M : ℕ) (h : n * 2 = M + 1) : Cell n ≃ Fin (M + 1) := + finProdFinEquiv.trans (finCongr h) + +/-- The numbering is the rank. -/ +private theorem eqv_val {n M : ℕ} (h : n * 2 = M + 1) (p : Cell n) : (eqv n M h p).val = p.rank := by + simp [eqv, Cell.rank] + ring + +/-- The array graph is the path through the cells in row-major order. -/ +private theorem isEdge_iff {n : ℕ} (p q : Cell n) : IsEdge p q ↔ q.rank = p.rank + 1 := by + have h1 := p.2.isLt + have h2 := q.2.isLt + simp only [IsEdge, Cell.rank, Fin.ext_iff, Fin.val_zero, Fin.val_one] + omega + +/-- Mistakes of a coloring are the mistakes of its row-major word. -/ +private theorem mistakes_eq {n M : ℕ} (h : n * 2 = M + 1) (c : Cell n → Fin 3) : + mistakes c = wmis (c ∘ (eqv n M h).symm) := by + symm + rw [wmis, ← Finset.card_filter] + refine Finset.card_bij (fun i _ => ((eqv n M h).symm i.castSucc, (eqv n M h).symm i.succ)) + ?_ ?_ ?_ + · intro i hi + simp only [Finset.mem_filter, Finset.mem_univ, true_and, Function.comp_apply] at hi ⊢ + refine ⟨?_, hi⟩ + rw [isEdge_iff, ← eqv_val h, ← eqv_val h] + simp + · intro i _ j _ hij + simp only [Prod.mk.injEq] at hij + exact Fin.castSucc_injective _ ((eqv n M h).symm.injective hij.1) + · rintro ⟨p, q⟩ hpq + simp only [Finset.mem_filter, Finset.mem_univ, true_and] at hpq + obtain ⟨he, hc⟩ := hpq + rw [isEdge_iff, ← eqv_val h, ← eqv_val h] at he + have hlt : (eqv n M h p).val < M := by have := (eqv n M h q).isLt; omega + have hp : (eqv n M h).symm (Fin.castSucc ⟨(eqv n M h p).val, hlt⟩) = p := by + rw [Equiv.symm_apply_eq]; ext; simp + have hq : (eqv n M h).symm (Fin.succ ⟨(eqv n M h p).val, hlt⟩) = q := by + rw [Equiv.symm_apply_eq]; ext; simp [he] + refine ⟨⟨(eqv n M h p).val, hlt⟩, ?_, ?_⟩ + · simp only [Finset.mem_filter, Finset.mem_univ, true_and, Function.comp_apply, hp, hq] + exact hc + · simp only [hp, hq] + +/-- Colors in order means: the row-major word starts with `0` and satisfies `Q2`. -/ +private theorem colorsInOrder_iff {n M : ℕ} (h : n * 2 = M + 1) (c : Cell n → Fin 3) : + ColorsInOrder c ↔ (c ∘ (eqv n M h).symm) 0 = 0 ∧ Q2 (c ∘ (eqv n M h).symm) := by + have hr : ∀ x : Fin (M + 1), ((eqv n M h).symm x).rank = x.val := fun x => by + rw [← eqv_val h, Equiv.apply_symm_apply] + have hR : ColorsInOrder c ↔ ∀ x : Fin (M + 1), (c ∘ (eqv n M h).symm) x ≠ 0 → + ∃ y, y < x ∧ ((c ∘ (eqv n M h).symm) y).val + 1 = ((c ∘ (eqv n M h).symm) x).val := by + constructor + · intro H x hx + obtain ⟨q, hq, hv⟩ := H ((eqv n M h).symm x) hx + refine ⟨eqv n M h q, ?_, ?_⟩ + · rw [Fin.lt_def, eqv_val h, ← hr x] + exact hq + · simpa using hv + · intro H p hp + obtain ⟨y, hy, hv⟩ := H (eqv n M h p) (by simpa using hp) + refine ⟨(eqv n M h).symm y, ?_, ?_⟩ + · rw [hr y, ← eqv_val h p] + exact hy + · simpa using hv + rw [hR] + generalize c ∘ (eqv n M h).symm = w + constructor + · intro H + refine ⟨?_, fun i hi => ?_⟩ + · by_contra h0 + obtain ⟨y, hy, -⟩ := H 0 h0 + exact Fin.not_lt_zero y hy + · obtain ⟨y, hy, hv⟩ := H i (by rw [hi]; decide) + refine ⟨y, hy, ?_⟩ + rw [hi] at hv + ext + simp only [Fin.val_two] at hv + simp only [Fin.val_one] + omega + · rintro ⟨h0, hq⟩ x hx + have hx' : w x = 1 ∨ w x = 2 := by + revert hx; generalize w x = t; fin_cases t <;> simp + rcases hx' with h1 | h2 + · refine ⟨0, ?_, by rw [h0, h1]; rfl⟩ + rw [Fin.pos_iff_ne_zero] + rintro rfl + rw [h0] at h1 + exact absurd h1 (by decide) + · obtain ⟨y, hy, hy1⟩ := hq x h2 + exact ⟨y, hy, by rw [hy1, h2]; rfl⟩ + +/-- A229580 as a count of words. -/ +private theorem A229580_eq {n M : ℕ} (h : n * 2 = M + 1) : + A229580 n = (univ.filter fun w : Fin (M + 1) → Fin 3 => wmis w = 1 ∧ w 0 = 0 ∧ Q2 w).card := by + unfold A229580 + refine Finset.card_equiv (Equiv.arrowCongr (eqv n M h) (Equiv.refl _)) fun c => ?_ + have hc : (Equiv.arrowCongr (eqv n M h) (Equiv.refl (Fin 3))) c = c ∘ (eqv n M h).symm := rfl + simp only [Finset.mem_filter, Finset.mem_univ, true_and, hc] + rw [mistakes_eq h, colorsInOrder_iff h] + +/-- Closed form `A229580(m+2) = (2m+3)·2^(2m+1)`. -/ +private theorem A229580_closed (m : ℕ) : A229580 (m + 1 + 1) = (2 * m + 3) * 2 ^ (2 * m + 1) := by + rw [A229580_eq (M := 2 * m + 1 + 2) (by ring), Tgt] + +/-- Luschny's conjecture holds: `|∑_{j=0}^{k} T(k+j, k)| = A229580(k+1)` for every `k`. -/ +theorem result : statement := by + intro k + cases k with + | zero => exact statement_check 0 (by norm_num) + | succ m => + rw [absSumT, A229580_closed] + push_cast + ring + +end Math0.Frontier.A368846 + +#math0_settles Math0.Frontier.A368846.result Math0.Statements.A368846.statement diff --git a/lean/Math0/Frontier/OEIS/A369366.lean b/lean/Math0/Frontier/OEIS/A369366.lean new file mode 100644 index 0000000..2e3a56f --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A369366.lean @@ -0,0 +1,318 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A369366 +import Math0.Audit + +/-! +# The least number of inequivalent cells of a `(6k+5)`-iamond is `3(k+1)` + +We prove Exley's conjecture `a(6k+5) = 3(k+1)` for every `k ≥ 0` (OEIS A369366). + +**Lower bound.** Let `P` be a set of `n ≡ 5 (mod 6)` cells and `g` a symmetry of the grid with +`g(P) = P`. +* `g` preserves orientation (`neg = false`): a map `x ↦ -σ(x) + t` sends a cell of coordinate sum + `s` to one of coordinate sum `1 - s`, so summing `sumC` over `P` gives `2·Σ sumC = n`, which is + impossible for odd `n` (`neg_eq_false`). +* If the permutation `σ` of `g` is even, `g` is the identity. For `σ = id`, `g` is a translation + and the centroid forces `t = 0` (`t_eq_of_sym`). For `σ` a cyclic shift, `g` is a + `120°`-rotation: `g³ = id` (`rot3_cube`) and it fixes at most one cell (`rot3_fix`: the + difference of two fixed cells is `(d, d, d)`, whose sum `3d` lies in `{-1, 0, 1}`), so + `n ≡ #fixed cells ∈ {0, 1} (mod 3)` (`Equiv.Perm.card_fixedPoints_modEq`), contradicting + `n ≡ 2 (mod 3)` (`no_rot3`, `rot_trivial`). +* Hence among cells `c, d = g(c), e = h(c)` of one class, either `g` or `h` has an even + permutation (so `d = c` or `e = c`), or both are odd and `h ∘ g⁻¹` (an even permutation) maps `d` + to `e`, so `d = e` (`three`). Every class has at most two cells (`card_cls_le`), so + `n ≤ 2 · numClasses P` (`lower`), i.e. `numClasses P ≥ 3(k+1)`. + +**Upper bound.** The straight strip of `n = 2m + 1` triangles, cells +`(⌈j/2⌉, -⌊j/2⌋, 0)` for `j < n` (`strip`), is a polyiamond (`strip_isPolyiamond`) whose mirror +symmetry `(a, b, c) ↦ (b + m, a - m, c)` exchanges cells `j` and `2m - j` (`mirror_app`), so its +classes are among those of the cells `0, …, m`: at most `m + 1 = 3(k+1)` classes (`upper`). +-/ + +namespace Math0.Frontier.A369366 +open Math0.Statements.A369366 + +/-- `perm 3` is the cyclic shift `(a, b, c) ↦ (b, c, a)`. -/ +private theorem perm_three (x : Pt) : perm 3 x = (x.2.1, x.2.2, x.1) := rfl + +/-- `perm 4` is the cyclic shift `(a, b, c) ↦ (c, a, b)`. -/ +private theorem perm_four (x : Pt) : perm 4 x = (x.2.2, x.1, x.2.1) := rfl + +/-- `perm 2` swaps the first two coordinates. -/ +private theorem perm_two (x : Pt) : perm 2 x = (x.2.1, x.1, x.2.2) := rfl + +/-- A symmetry of a set of cells of odd size preserves the orientation of the cells +(`x ↦ -σ(x) + t` exchanges the cells with coordinate sum `0` and `1`). -/ +private theorem neg_eq_false {P : Finset Pt} (hodd : P.card % 2 = 1) {g : Isom} + (hg : P.image g.app = P) : g.neg = false := by + by_contra hn + have hn : g.neg = true := by simpa using hn + have h1 : ∑ x ∈ P, sumC (g.app x) = ∑ x ∈ P, sumC x := by + conv_rhs => rw [← hg] + rw [Finset.sum_image fun x _ y _ h => g.app_injective h] + have h2 : ∀ x, sumC (g.app x) = 1 - sumC x := by + intro x + rw [Isom.app, sumC_add, sumC_lin, g.ht, hn] + simp [tReq] + ring + simp only [h2, Finset.sum_sub_distrib, Finset.sum_const, nsmul_eq_mul, mul_one] at h1 + omega + +/-- A `120°`-rotation `x ↦ σ(x) + t` (`σ` a cyclic shift, `t₁ + t₂ + t₃ = 0`) has order `3`. -/ +private theorem rot3_cube {g : Isom} (hn : g.neg = false) (hs : g.s = 3 ∨ g.s = 4) (x : Pt) : + g.app (g.app (g.app x)) = x := by + obtain ⟨s, n, ⟨t1, t2, t3⟩, ht⟩ := g + simp only at hn hs + subst hn + obtain ⟨a, b, c⟩ := x + simp only [sumC, tReq, Bool.false_eq_true, if_false] at ht + rcases hs with rfl | rfl <;> + · simp only [Isom.app, lin, perm_three, perm_four, Bool.false_eq_true, if_false, + Prod.mk_add_mk, Prod.mk.injEq] + omega + +/-- A `120°`-rotation fixes at most one cell. -/ +private theorem rot3_fix {g : Isom} (hn : g.neg = false) (hs : g.s = 3 ∨ g.s = 4) {x y : Pt} + (hx : IsCell x) (hy : IsCell y) (hgx : g.app x = x) (hgy : g.app y = y) : x = y := by + obtain ⟨s, n, ⟨t1, t2, t3⟩, ht⟩ := g + simp only at hn hs + subst hn + obtain ⟨a, b, c⟩ := x + obtain ⟨a', b', c'⟩ := y + simp only [IsCell, sumC] at hx hy + rcases hs with rfl | rfl <;> + · simp only [Isom.app, lin, perm_three, perm_four, Bool.false_eq_true, if_false, + Prod.mk_add_mk, Prod.mk.injEq] at hgx hgy ⊢ + omega + +/-- No set of cells whose size is `2 mod 3` has a `120°`-rotation symmetry: the rotation permutes +the cells with orbits of size `1` or `3` and fixes at most one cell. -/ +private theorem no_rot3 {P : Finset Pt} (hcell : ∀ x ∈ P, IsCell x) (h3 : P.card % 3 = 2) + {g : Isom} (hg : P.image g.app = P) (hn : g.neg = false) (hs : g.s = 3 ∨ g.s = 4) : False := by + classical + have hmem : ∀ x ∈ P, g.app x ∈ P := (image_eq_iff P g).1 hg + let f : Function.End {x // x ∈ P} := fun x => ⟨g.app x.1, hmem x.1 x.2⟩ + have hpow : f ^ 3 ^ 1 = 1 := by + funext x + apply Subtype.ext + exact rot3_cube hn hs x.1 + have hmod := Equiv.Perm.card_fixedPoints_modEq (p := 3) (n := 1) hpow + have hfix : Fintype.card (Function.fixedPoints f) ≤ 1 := by + rw [Fintype.card_le_one_iff] + rintro ⟨⟨x, hx⟩, hxf⟩ ⟨⟨y, hy⟩, hyf⟩ + have hxf' : g.app x = x := congrArg Subtype.val hxf + have hyf' : g.app y = y := congrArg Subtype.val hyf + have := rot3_fix hn hs (hcell x hx) (hcell y hy) hxf' hyf' + subst this + rfl + rw [Fintype.card_coe] at hmod + unfold Nat.ModEq at hmod + omega + +/-- For a set of cells of size `5 mod 6`, every symmetry whose linear part is an even +permutation (a rotation) is the identity. -/ +private theorem rot_trivial {P : Finset Pt} (hcell : ∀ x ∈ P, IsCell x) (hcard : P.card % 6 = 5) + {g : Isom} (hg : P.image g.app = P) (hs : g.s = 0 ∨ g.s = 3 ∨ g.s = 4) (x : Pt) : + g.app x = x := by + have hn : g.neg = false := neg_eq_false (by omega) hg + rcases hs with hs | hs + · have hne : P.Nonempty := Finset.card_pos.1 (by omega) + have ht := t_eq_of_sym hne hg + rw [hs, hn, lin_zero, sub_self] at ht + have ht0 : g.t = 0 := by + rw [ht] + simp [divPt] + rw [Isom.app, hs, hn, lin_zero, ht0, add_zero] + · exact (no_rot3 hcell (by omega) hg hn hs).elim + +/-- The composition `h ∘ g⁻¹` of two reflections (odd permutations) is a rotation. -/ +private theorem mulTab_inv_even (i j : Fin 6) (hi : i = 1 ∨ i = 2 ∨ i = 5) + (hj : j = 1 ∨ j = 2 ∨ j = 5) : + mulTab j (invTab i) = 0 ∨ mulTab j (invTab i) = 3 ∨ mulTab j (invTab i) = 4 := by + rcases hi with rfl | rfl | rfl <;> rcases hj with rfl | rfl | rfl <;> decide + +/-- The indices of the even permutations are `0, 3, 4`; those of the odd ones are `1, 2, 5`. -/ +private theorem fin6_cases (i : Fin 6) : + (i = 0 ∨ i = 3 ∨ i = 4) ∨ (i = 1 ∨ i = 2 ∨ i = 5) := by + fin_cases i <;> simp + +/-- Among three cells `c, d, e` of `P` with `d, e` equivalent to `c`, two coincide. -/ +private theorem three {P : Finset Pt} (hcell : ∀ x ∈ P, IsCell x) (hcard : P.card % 6 = 5) + {c d e : Pt} (hd : Equivalent P c d) (he : Equivalent P c e) : d = c ∨ e = c ∨ d = e := by + obtain ⟨g, hg, rfl⟩ := hd + obtain ⟨h, hh, rfl⟩ := he + rcases fin6_cases g.s with hgs | hgs + · exact Or.inl (rot_trivial hcell hcard hg hgs c) + rcases fin6_cases h.s with hhs | hhs + · exact Or.inr (Or.inl (rot_trivial hcell hcard hh hhs c)) + have hk : P.image (h.comp g.inv).app = P := by + rw [← image_image_app] + conv_lhs => rw [← hg] + rw [image_inv_image, hh] + have := rot_trivial hcell hcard hk (mulTab_inv_even g.s h.s hgs hhs) (g.app c) + rw [Isom.comp_app, Isom.inv_app_app] at this + exact Or.inr (Or.inr this.symm) + +/-- In a set of cells of size `5 mod 6`, every class of equivalent cells has at most two cells. -/ +private theorem card_cls_le {P : Finset Pt} (hcell : ∀ x ∈ P, IsCell x) (hcard : P.card % 6 = 5) + (c : Pt) : (cls P c).card ≤ 2 := by + by_contra hlt + obtain ⟨x, hx, y, hy, z, hz, hxy, hxz, hyz⟩ := + Finset.two_lt_card.1 (show 2 < (cls P c).card by omega) + simp only [cls, Finset.mem_filter] at hx hy hz + have hxy' := equivalent_trans (equivalent_symm hx.2) hy.2 + have hxz' := equivalent_trans (equivalent_symm hx.2) hz.2 + rcases three hcell hcard hxy' hxz' with h | h | h + · exact hxy h.symm + · exact hxz h.symm + · exact hyz h + +/-- Lower bound: a set of `n ≡ 5 (mod 6)` cells has at least `(n + 1) / 2` classes. -/ +private theorem lower {P : Finset Pt} (hcell : ∀ x ∈ P, IsCell x) (hcard : P.card % 6 = 5) : + P.card ≤ 2 * numClasses P := by + unfold numClasses + apply Finset.card_le_mul_card_image + intro b hb + obtain ⟨c, -, rfl⟩ := Finset.mem_image.1 hb + calc (P.filter fun a => cls P a = cls P c).card ≤ (cls P c).card := by + apply Finset.card_le_card + intro x hx + rw [Finset.mem_filter] at hx + rw [← hx.2] + simp only [cls, Finset.mem_filter] + exact ⟨hx.1, equivalent_refl P x⟩ + _ ≤ 2 := card_cls_le hcell hcard c + +/-! ### The straight strip -/ + +/-- The `j`-th cell `(⌈j/2⌉, -⌊j/2⌋, 0)` of the straight strip (a row of triangles). -/ +private def stripCell (j : ℕ) : Pt := ((((j + 1) / 2 : ℕ) : ℤ), -(((j / 2 : ℕ)) : ℤ), 0) + +/-- The straight strip of `n` triangles. -/ +private def strip (n : ℕ) : Finset Pt := (Finset.range n).image stripCell + +/-- Distinct indices give distinct cells of the strip (`j = a - b`). -/ +private theorem stripCell_injective : Function.Injective stripCell := by + intro i j h + simp only [stripCell, Prod.mk.injEq] at h + omega + +/-- Every cell of the strip is a cell of the grid (coordinate sum `⌈j/2⌉ - ⌊j/2⌋ ∈ {0, 1}`). -/ +private theorem stripCell_isCell (j : ℕ) : IsCell (stripCell j) := by + simp only [IsCell, sumC, stripCell] + omega + +/-- Consecutive cells of the strip share an edge. -/ +private theorem stripCell_adj (j : ℕ) : Adj (stripCell j) (stripCell (j + 1)) := by + unfold Adj stripCell + simp only + rcases Nat.mod_two_eq_zero_or_one j with h | h + · have e1 : (((j + 1 + 1) / 2 : ℕ) : ℤ) - (((j + 1) / 2 : ℕ) : ℤ) = 1 := by omega + have e2 : -((((j + 1) / 2 : ℕ)) : ℤ) - -(((j / 2 : ℕ)) : ℤ) = 0 := by omega + rw [e1, e2] + norm_num + · have e1 : (((j + 1 + 1) / 2 : ℕ) : ℤ) - (((j + 1) / 2 : ℕ) : ℤ) = 0 := by omega + have e2 : -((((j + 1) / 2 : ℕ)) : ℤ) - -(((j / 2 : ℕ)) : ℤ) = -1 := by omega + rw [e1, e2] + norm_num + +/-- The `j`-th cell belongs to the strip of `n > j` triangles. -/ +private theorem stripCell_mem {n j : ℕ} (hj : j < n) : stripCell j ∈ strip n := + Finset.mem_image_of_mem _ (Finset.mem_range.2 hj) + +/-- Chains in `P` can be reversed. -/ +private theorem rtg_symm {P : Finset Pt} {x y : Pt} (h : Relation.ReflTransGen (Step P) x y) : + Relation.ReflTransGen (Step P) y x := by + induction h with + | refl => exact Relation.ReflTransGen.refl + | tail _ hbc ih => exact Relation.ReflTransGen.head ⟨hbc.2.1, hbc.1, adj_symm hbc.2.2⟩ ih + +/-- The strip is a polyiamond. -/ +private theorem strip_isPolyiamond (n : ℕ) : IsPolyiamond n (strip n) := by + refine ⟨?_, ?_, ?_⟩ + · rw [strip, Finset.card_image_of_injective _ stripCell_injective, Finset.card_range] + · intro x hx + obtain ⟨j, -, rfl⟩ := Finset.mem_image.1 hx + exact stripCell_isCell j + · have up : ∀ i d, i + d < n → + Relation.ReflTransGen (Step (strip n)) (stripCell i) (stripCell (i + d)) := by + intro i d + induction d with + | zero => intro _; exact Relation.ReflTransGen.refl + | succ d ih => + intro hd + exact (ih (by omega)).tail + ⟨stripCell_mem (by omega), stripCell_mem (by omega), stripCell_adj (i + d)⟩ + intro x hx y hy + obtain ⟨i, hi, rfl⟩ := Finset.mem_image.1 hx + obtain ⟨j, hj, rfl⟩ := Finset.mem_image.1 hy + rw [Finset.mem_range] at hi hj + rcases le_total i j with hij | hij + · obtain ⟨d, rfl⟩ := Nat.exists_eq_add_of_le hij + exact up i d hj + · obtain ⟨d, rfl⟩ := Nat.exists_eq_add_of_le hij + exact rtg_symm (up j d hi) + +/-- The mirror symmetry `(a, b, c) ↦ (b + m, a - m, c)` of the strip of `2m + 1` triangles. -/ +private def mirror (m : ℕ) : Isom := ⟨2, false, ((m : ℤ), -(m : ℤ), 0), by simp [sumC, tReq]⟩ + +/-- The mirror symmetry exchanges the cells `j` and `2m - j` of the strip. -/ +private theorem mirror_app (m j : ℕ) (hj : j ≤ 2 * m) : + (mirror m).app (stripCell j) = stripCell (2 * m - j) := by + simp only [mirror, Isom.app, lin, perm_two, stripCell, Bool.false_eq_true, if_false, + Prod.mk_add_mk, Prod.mk.injEq] + omega + +/-- The cells `j` and `2m - j` of the strip of `2m + 1` triangles are equivalent. -/ +private theorem equivalent_mirror (m j : ℕ) (hj : j ≤ 2 * m) : + Equivalent (strip (2 * m + 1)) (stripCell j) (stripCell (2 * m - j)) := by + refine ⟨mirror m, (image_eq_iff _ _).2 fun x hx => ?_, mirror_app m j hj⟩ + obtain ⟨i, hi, rfl⟩ := Finset.mem_image.1 hx + rw [Finset.mem_range] at hi + rw [mirror_app m i (by omega)] + exact stripCell_mem (by omega) + +/-- Equivalent cells have the same class. -/ +private theorem cls_eq {P : Finset Pt} {c d : Pt} (h : Equivalent P c d) : cls P c = cls P d := by + ext y + simp only [cls, Finset.mem_filter] + exact and_congr_right fun _ => + ⟨fun h' => equivalent_trans (equivalent_symm h) h', fun h' => equivalent_trans h h'⟩ + +/-- Upper bound: the strip of `2m + 1` triangles has at most `m + 1` classes. -/ +private theorem upper (m : ℕ) : numClasses (strip (2 * m + 1)) ≤ m + 1 := by + unfold numClasses + have hsub : (strip (2 * m + 1)).image (cls (strip (2 * m + 1))) ⊆ + (Finset.range (m + 1)).image fun j => cls (strip (2 * m + 1)) (stripCell j) := by + intro C hC + obtain ⟨x, hx, rfl⟩ := Finset.mem_image.1 hC + obtain ⟨j, hj, rfl⟩ := Finset.mem_image.1 hx + rw [Finset.mem_range] at hj + rcases le_or_gt j m with hjm | hjm + · exact Finset.mem_image_of_mem _ (Finset.mem_range.2 (by omega)) + · refine Finset.mem_image.2 ⟨2 * m - j, Finset.mem_range.2 (by omega), ?_⟩ + rw [cls_eq (equivalent_mirror m j (by omega))] + calc _ ≤ _ := Finset.card_le_card hsub + _ ≤ (Finset.range (m + 1)).card := Finset.card_image_le + _ = m + 1 := Finset.card_range _ + +/-- Exley's conjecture: `a(6k + 5) = 3(k + 1)` for every `k ≥ 0`. -/ +theorem result : statement := by + intro k + have hP := strip_isPolyiamond (6 * k + 5) + have hub : numClasses (strip (6 * k + 5)) ≤ 3 * (k + 1) := by + have := upper (3 * k + 2) + rwa [show 2 * (3 * k + 2) + 1 = 6 * k + 5 by ring] at this + unfold a + apply le_antisymm + · exact le_trans (Nat.sInf_le ⟨_, hP, rfl⟩) hub + · refine le_csInf ⟨_, strip (6 * k + 5), hP, rfl⟩ ?_ + rintro m ⟨P, ⟨hcard, hcell, -⟩, rfl⟩ + have := lower hcell (by omega) + omega + +end Math0.Frontier.A369366 + +#math0_settles Math0.Frontier.A369366.result Math0.Statements.A369366.statement diff --git a/lean/Math0/Frontier/OEIS/A373345.lean b/lean/Math0/Frontier/OEIS/A373345.lean new file mode 100644 index 0000000..8324f7b --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A373345.lean @@ -0,0 +1,218 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A373345 +import Math0.Audit + +/-! +# Row lengths of the Schreier-set triangle A373345 are A007895 + +We prove Paolo Xausa's conjecture: row `n` of A373345 (the Schreier set encoded by A371176(n)) +has as many elements as the Zeckendorf representation of `n` has terms. + +Write `w k` for the binary weight of `k` and `c k = #{j < k : IsTerm j}` (`Nat.count`). Since +A371176 enumerates the terms in increasing order, it suffices to show +`w k = (zeckendorf (c k + 1)).length` for every term `k`. + +* **Structure.** For `0 < 2i < 2^p`, `IsTerm (2^p + 2i) ↔ IsTerm i`; `IsTerm (2^p)` always; and + `2^p + (2i+1)` (with `2i + 1 < 2^p`) is never a term (weight `≥ 2`, lowest bit `0`). +* **Counting.** For `2i ≤ 2^p`, `c (2^p + 2i) = c (2^p) + c i + [i ≠ 0]`. Taking `i = 2^(p-1)` + gives `c (2^(p+1)) = c (2^p) + c (2^(p-1)) + 1`, so `c (2^p) + 1 = F(p+2)`. +* **Zeckendorf.** For `m < F(p+1)`, the Zeckendorf representation of `F(p+2) + m` is that of `m` + with `p + 2` prepended. +* **Induction.** A term `k` with top bit `p` is `2^p` or `2^p + 2i` with `i < 2^(p-1)` a term. + Then `w k = 1 + w i` and `c k + 1 = F(p+2) + (c i + 1)` with `c i + 1 ≤ c (2^(p-1)) < F(p+1)`; + strong induction on `k` finishes. +-/ + +namespace Math0.Frontier.A373345 +open Math0.Statements.A373345 + +/-- Binary digits of `2^p + j` for `j < 2^p`: those of `j`, then `p`. -/ +private theorem bitIndices_two_pow_add (p : ℕ) : ∀ j, j < 2 ^ p → + (2 ^ p + j).bitIndices = j.bitIndices ++ [p] := by + induction p with + | zero => + intro j hj + obtain rfl : j = 0 := by simpa using hj + simp + | succ p ih => + intro j hj + obtain ⟨j', rfl | rfl⟩ := Nat.even_or_odd' j + · have hj' : j' < 2 ^ p := by rw [pow_succ] at hj; omega + rw [show 2 ^ (p + 1) + 2 * j' = 2 * (2 ^ p + j') by ring, Nat.bitIndices_two_mul, + ih j' hj', Nat.bitIndices_two_mul] + simp + · have hj' : j' < 2 ^ p := by rw [pow_succ] at hj; omega + rw [show 2 ^ (p + 1) + (2 * j' + 1) = 2 * (2 ^ p + j') + 1 by ring, + Nat.bitIndices_two_mul_add_one, ih j' hj', Nat.bitIndices_two_mul_add_one] + simp + +/-- A positive number has a nonempty list of binary digits. -/ +private theorem exists_bitIndices_cons (i : ℕ) (hi : i ≠ 0) : + ∃ a l, i.bitIndices = a :: l := by + cases h : i.bitIndices with + | nil => + have := Nat.sum_map_two_pow_bitIndices i + rw [h] at this + simp at this + omega + | cons a l => exact ⟨a, l, rfl⟩ + +/-- Membership in A371176 for a positive number, via its list of binary digits. -/ +private theorem isTerm_iff (k : ℕ) (hk : k ≠ 0) : + IsTerm k ↔ k.bitIndices.length ≤ k.bitIndices.headD 0 + 1 := by + rw [IsTerm, padicValNat_two_mul k hk] + constructor + · exact fun h => h.2 + · exact fun h => ⟨Nat.pos_of_ne_zero hk, h⟩ + +/-- `2^p + 2i` (with `2i < 2^p`) is a term iff `i = 0` or `i` is a term. -/ +private theorem isTerm_two_pow_add_even (p i : ℕ) (hi : 2 * i < 2 ^ p) : + IsTerm (2 ^ p + 2 * i) ↔ i = 0 ∨ IsTerm i := by + rcases Nat.eq_zero_or_pos i with rfl | hi0 + · simpa using isTerm_two_pow p + · obtain ⟨a, l, hal⟩ := exists_bitIndices_cons i hi0.ne' + rw [isTerm_iff _ (by positivity), isTerm_iff _ hi0.ne', bitIndices_two_pow_add p _ hi, + Nat.bitIndices_two_mul, hal] + simp only [List.map_cons, List.cons_append, List.length_cons, List.length_append, + List.length_map, List.length_nil, List.headD_cons] + omega + +/-- `2^p + (2i + 1)` (with `2i + 1 < 2^p`) is never a term. -/ +private theorem not_isTerm_two_pow_add_odd (p i : ℕ) (hi : 2 * i + 1 < 2 ^ p) : + ¬ IsTerm (2 ^ p + (2 * i + 1)) := by + rw [isTerm_iff _ (by positivity), bitIndices_two_pow_add p _ hi, + Nat.bitIndices_two_mul_add_one] + simp + +/-- Counting terms below `2^p + 2i`. -/ +private theorem count_two_pow_add (p : ℕ) : ∀ i, 2 * i ≤ 2 ^ p → + Nat.count IsTerm (2 ^ p + 2 * i) = + Nat.count IsTerm (2 ^ p) + Nat.count IsTerm i + (if i = 0 then 0 else 1) := by + intro i + induction i with + | zero => intro _; simp + | succ i ih => + intro hi + have h1 : 2 * i < 2 ^ p := by omega + have h2 : 2 * i + 1 < 2 ^ p := by omega + rw [show 2 ^ p + 2 * (i + 1) = (2 ^ p + 2 * i) + 1 + 1 by ring, Nat.count_succ, + Nat.count_succ, ih (by omega), Nat.count_succ, + if_neg (show ¬ IsTerm (2 ^ p + 2 * i + 1) from by + rw [add_assoc]; exact not_isTerm_two_pow_add_odd p i h2)] + by_cases hi0 : i = 0 + · subst hi0 + have : ¬ IsTerm 0 := fun h => absurd h.1 (lt_irrefl 0) + simp [isTerm_two_pow, this] + · by_cases ht : IsTerm i + · have : IsTerm (2 ^ p + 2 * i) := (isTerm_two_pow_add_even p i h1).2 (Or.inr ht) + simp [hi0, ht, this] + omega + · have : ¬ IsTerm (2 ^ p + 2 * i) := fun h => by + rcases (isTerm_two_pow_add_even p i h1).1 h with h | h + · exact hi0 h + · exact ht h + simp [hi0, ht, this] + +/-- There are `F(p+2) - 1` terms below `2^p`. -/ +private theorem count_two_pow (p : ℕ) : Nat.count IsTerm (2 ^ p) + 1 = Nat.fib (p + 2) := by + have key : ∀ p, Nat.count IsTerm (2 ^ p) + 1 = Nat.fib (p + 2) ∧ + Nat.count IsTerm (2 ^ (p + 1)) + 1 = Nat.fib (p + 3) := by + have h0 : ¬ IsTerm 0 := fun h => absurd h.1 (lt_irrefl 0) + intro p + induction p with + | zero => + refine ⟨?_, ?_⟩ + · rw [pow_zero, show (1 : ℕ) = 0 + 1 from rfl, Nat.count_succ, if_neg h0] + simp + · have h1 : IsTerm 1 := by simpa using isTerm_two_pow 0 + rw [show (2 : ℕ) ^ (0 + 1) = 0 + 1 + 1 from rfl, Nat.count_succ, Nat.count_succ, + if_neg h0, if_pos h1] + simp [Nat.fib_add_two] + | succ p ih => + refine ⟨ih.2, ?_⟩ + have h := count_two_pow_add (p + 1) (2 ^ p) (by rw [pow_succ]; omega) + rw [show 2 ^ (p + 1) + 2 * 2 ^ p = 2 ^ (p + 1 + 1) by ring, + if_neg (by positivity)] at h + rw [h, show p + 1 + 3 = (p + 3) + 1 by ring, Nat.fib_add_one (by omega), + show p + 3 - 1 = p + 2 by omega, ← ih.1, ← ih.2] + ring + exact (key p).1 + +/-- The Zeckendorf representation of `F(p+2) + m` for `m < F(p+1)` is `p+2` followed by that of +`m`. -/ +private theorem zeckendorf_fib_add (p m : ℕ) (hm : m < Nat.fib (p + 1)) : + (Nat.zeckendorf (Nat.fib (p + 2) + m)).length = (Nat.zeckendorf m).length + 1 := by + have hpos : 0 < Nat.fib (p + 2) + m := by + have := Nat.fib_pos.2 (show 0 < p + 2 by omega) + omega + have hg : Nat.greatestFib (Nat.fib (p + 2) + m) = p + 2 := by + apply le_antisymm + · rw [← Nat.lt_succ_iff, Nat.greatestFib_lt, Nat.fib_add_two (n := p + 1)] + rw [show p + 1 + 1 = p + 2 by ring] + omega + · rw [Nat.le_greatestFib] + omega + rw [Nat.zeckendorf_of_pos hpos, hg, Nat.add_sub_cancel_left] + simp + +/-- The main lemma: for every term `k`, its binary weight is the Zeckendorf length of its index +`count k + 1`. -/ +private theorem main (k : ℕ) : IsTerm k → + k.bitIndices.length = (Nat.zeckendorf (Nat.count IsTerm k + 1)).length := by + induction k using Nat.strong_induction_on with + | _ k ih => + intro hk + have hk0 : k ≠ 0 := hk.1.ne' + obtain ⟨p, h1, h2⟩ : ∃ p, 2 ^ p ≤ k ∧ k < 2 ^ (p + 1) := + ⟨Nat.log 2 k, Nat.pow_log_le_self 2 hk0, Nat.lt_pow_succ_log_self (by norm_num) k⟩ + obtain ⟨j, rfl⟩ : ∃ j, k = 2 ^ p + j := ⟨k - 2 ^ p, by omega⟩ + have hj : j < 2 ^ p := by rw [pow_succ] at h2; omega + obtain ⟨i, rfl | rfl⟩ := Nat.even_or_odd' j + · rcases (isTerm_two_pow_add_even p i hj).1 hk with rfl | hi + · simp only [mul_zero, add_zero, Nat.bitIndices_two_pow, List.length_singleton] + rw [count_two_pow, ← add_zero (Nat.fib (p + 2)), + zeckendorf_fib_add p 0 (Nat.fib_pos.2 (by omega))] + simp + · have hi0 : i ≠ 0 := hi.1.ne' + obtain ⟨q, rfl⟩ : ∃ q, p = q + 1 := ⟨p - 1, by + rcases Nat.eq_zero_or_pos p with h | h + · rw [h] at hj; omega + · omega⟩ + have hiq : i < 2 ^ q := by rw [pow_succ] at hj; omega + have hlt : i < 2 ^ (q + 1) + 2 * i := by + have := Nat.one_le_two_pow (n := q + 1); omega + have IH := ih i hlt hi + have hc := count_two_pow_add (q + 1) i hj.le + rw [if_neg hi0] at hc + have hci : Nat.count IsTerm i + 1 ≤ Nat.count IsTerm (2 ^ q) := by + have := Nat.count_strict_mono hi hiq + omega + have hcq := count_two_pow q + have hcq1 := count_two_pow (q + 1) + rw [bitIndices_two_pow_add (q + 1) _ hj, Nat.bitIndices_two_mul, hc, + show Nat.count IsTerm (2 ^ (q + 1)) + Nat.count IsTerm i + 1 + 1 = + Nat.fib (q + 1 + 2) + (Nat.count IsTerm i + 1) by omega, + zeckendorf_fib_add (q + 1) _ (by rw [show q + 1 + 1 = q + 2 by ring]; omega), ← IH] + simp + · exact absurd hk (not_isTerm_two_pow_add_odd p i hj) + +/-- Row `n` of A373345 has as many elements as the Zeckendorf representation of `n`. -/ +theorem result : statement := by + intro n hn + have hinf : {k | IsTerm k}.Infinite := by + apply Set.infinite_of_not_bddAbove + rintro ⟨b, hb⟩ + have h := hb (isTerm_two_pow b) + have := Nat.lt_two_pow_self (n := b) + omega + have hterm : IsTerm (Nat.nth IsTerm (n - 1)) := Nat.nth_mem_of_infinite hinf _ + have hcount : Nat.count IsTerm (Nat.nth IsTerm (n - 1)) = n - 1 := + Nat.count_nth_of_infinite hinf _ + rw [T, A371176, List.length_reverse, List.length_map, main _ hterm, hcount, + show n - 1 + 1 = n by omega] + +end Math0.Frontier.A373345 + +#math0_settles Math0.Frontier.A373345.result Math0.Statements.A373345.statement diff --git a/lean/Math0/Frontier/OEIS/A373359.lean b/lean/Math0/Frontier/OEIS/A373359.lean new file mode 100644 index 0000000..c4e942e --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A373359.lean @@ -0,0 +1,182 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A373359 +import Math0.Audit + +/-! +# A373359: the Schreier-set rows have Zeckendorf-weight lengths + +We prove that row `n` of A373359 (the binary support of the `n`-th term of A371176, the encodings +of Schreier sets) has exactly as many elements as the Zeckendorf representation of `n`. + +Idea. Let `Q k` mean `popcount k ≤ (lowest set-bit index of k) + 1`, so `Q 0` holds and, for +`k ≥ 1`, `Q k ↔ IsTerm k`. For `2 j < 2 ^ a` the bits of `2 ^ a + 2 j` are those of `j` shifted +by one together with the top bit `a`, so `Q (2 ^ a + 2 j) ↔ Q j`, while `2 ^ a + 2 j + 1` +(for `a ≥ 1`) never satisfies `Q`. Hence, counting `Q`-numbers below a bound, +`count Q (2 ^ a + 2 k) = count Q (2 ^ a) + count Q k` whenever `2 k ≤ 2 ^ a`, and therefore +`count Q (2 ^ a) = fib (a + 2)`. Now by strong induction on `n` there is `k` with `Q k`, +`count Q k = n` and `popcount k = |zeckendorf n|`: for `n > 0`, with `g = greatestFib n = a + 2` +and `n' = n - fib g < fib (a + 1)`, take `k = 2 ^ a + 2 k'` where `k'` is given for `n'`; the +bound on `n'` forces `2 k' < 2 ^ a`. Finally `count IsTerm k = n - 1`, so `k = A371176 n`. +-/ + +namespace Math0.Frontier.A373359 +open Math0.Statements.A373359 + +/-- The Schreier condition on the binary support, including `0`. -/ +private abbrev Q (k : ℕ) : Prop := k.bitIndices.length ≤ k.bitIndices.headD 0 + 1 + +/-- The bits of `x + 2 ^ a` for `x < 2 ^ a`. -/ +private lemma bitIndices_add_two_pow {x a : ℕ} (hx : x < 2 ^ a) : + (x + 2 ^ a).bitIndices = x.bitIndices ++ [a] := by + have hs : (x.bitIndices ++ [a]).SortedLT := by + rw [List.sortedLT_iff_pairwise, List.pairwise_append] + refine ⟨List.sortedLT_iff_pairwise.1 Nat.bitIndices_sorted, by simp, ?_⟩ + intro i hi j hj + simp only [List.mem_singleton] at hj + subst hj + have := Nat.two_pow_le_of_mem_bitIndices hi + exact (Nat.pow_lt_pow_iff_right (by norm_num)).1 (lt_of_le_of_lt this hx) + have := Nat.bitIndices_sum_map_two_pow hs + simpa using this + +/-- Bits of `2 ^ a + 2 j` for `2 j < 2 ^ a`. -/ +private lemma bitIndices_block {a j : ℕ} (h : 2 * j < 2 ^ a) : + (2 ^ a + 2 * j).bitIndices = (j.bitIndices.map (· + 1)) ++ [a] := by + rw [add_comm, bitIndices_add_two_pow h, Nat.bitIndices_two_mul] + +/-- The Schreier condition is preserved by the block map `j ↦ 2 ^ a + 2 j`. -/ +private lemma Q_block {a j : ℕ} (h : 2 * j < 2 ^ a) : Q (2 ^ a + 2 * j) ↔ Q j := by + simp only [Q] + rw [bitIndices_block h] + cases j.bitIndices with + | nil => simp + | cons i l => simp + +/-- Odd numbers in the block `[2 ^ a, 2 ^ (a + 1))`, `a ≥ 1`, fail the Schreier condition. -/ +private lemma not_Q_odd {a j : ℕ} (ha : 1 ≤ a) (h : 2 * j + 1 < 2 ^ a) : + ¬ Q (2 ^ a + (2 * j + 1)) := by + obtain ⟨b, rfl⟩ : ∃ b, a = b + 1 := ⟨a - 1, by omega⟩ + have hj : j < 2 ^ b := by rw [pow_succ] at h; omega + have he : 2 ^ (b + 1) + (2 * j + 1) = 2 * (j + 2 ^ b) + 1 := by rw [pow_succ]; ring + simp only [Q] + rw [he, Nat.bitIndices_two_mul_add_one, bitIndices_add_two_pow hj] + simp + +/-- Counting `Q`-numbers across a block. -/ +private lemma count_block (a k : ℕ) (h : 2 * k ≤ 2 ^ a) : + Nat.count Q (2 ^ a + 2 * k) = Nat.count Q (2 ^ a) + Nat.count Q k := by + rw [Nat.count_add] + congr 1 + induction k with + | zero => simp + | succ k ih => + have ha : 1 ≤ a := by + rcases Nat.eq_zero_or_pos a with rfl | ha + · simp at h; omega + · exact ha + rw [show 2 * (k + 1) = 2 * k + 1 + 1 by ring, Nat.count_succ, Nat.count_succ, + ih (by omega), Nat.count_succ] + have h1 : Q (2 ^ a + 2 * k) ↔ Q k := Q_block (by omega) + have h2 : ¬ Q (2 ^ a + (2 * k + 1)) := not_Q_odd ha (by omega) + simp only [h1, h2, if_false, add_zero] + +/-- `count Q (2 ^ a) = fib (a + 2)`. -/ +private lemma count_two_pow (a : ℕ) : Nat.count Q (2 ^ a) = Nat.fib (a + 2) := by + suffices H : ∀ a, Nat.count Q (2 ^ a) = Nat.fib (a + 2) ∧ + Nat.count Q (2 ^ (a + 1)) = Nat.fib (a + 3) from (H a).1 + intro a + induction a with + | zero => + refine ⟨?_, ?_⟩ + · show Nat.count Q (0 + 1) = 1 + rw [Nat.count_succ] + simp + · show Nat.count Q (0 + 1 + 1) = 2 + rw [Nat.count_succ, Nat.count_succ] + simp + | succ a ih => + refine ⟨ih.2, ?_⟩ + have e : 2 ^ (a + 1 + 1) = 2 ^ (a + 1) + 2 * 2 ^ a := by ring + have h3 : Nat.fib (a + 1 + 3) = Nat.fib (a + 2) + Nat.fib (a + 3) := Nat.fib_add_two + rw [e, count_block _ _ (by rw [pow_succ]; omega), ih.1, ih.2, h3] + omega + +/-- The main induction along the Zeckendorf decomposition. -/ +private lemma main (n : ℕ) : ∃ k, Q k ∧ Nat.count Q k = n ∧ + k.bitIndices.length = (Nat.zeckendorf n).length := by + induction n using Nat.strong_induction_on with + | _ n ih => + rcases Nat.eq_zero_or_pos n with rfl | hn + · exact ⟨0, by simp [Q], by simp, by simp⟩ + have hg2 : 2 ≤ Nat.greatestFib n := by + rw [Nat.le_greatestFib, Nat.fib_two]; omega + obtain ⟨a, ha⟩ : ∃ a, Nat.greatestFib n = a + 2 := ⟨Nat.greatestFib n - 2, by omega⟩ + have hle := Nat.fib_greatestFib_le n + have hlt := Nat.lt_fib_greatestFib_add_one n + rw [ha] at hle hlt + have hfib : Nat.fib (a + 2 + 1) = Nat.fib (a + 1) + Nat.fib (a + 2) := Nat.fib_add_two + set n' := n - Nat.fib (a + 2) with hn' + have hn'lt : n' < Nat.fib (a + 1) := by omega + obtain ⟨k', hQ', hc', hl'⟩ := ih n' (by + have : 0 < Nat.fib (a + 2) := Nat.fib_pos.2 (by omega) + omega) + have hk' : 2 * k' < 2 ^ a := by + rcases a with _ | b + · have h0 : n' = 0 := by simp at hn'lt; omega + rcases Nat.eq_zero_or_pos k' with h | h + · simp [h] + · exfalso + have := Nat.count_monotone Q (show 1 ≤ k' from h) + simp [Nat.count_succ, Q] at this + omega + · by_contra hcon + have hb : 2 ^ b ≤ k' := by rw [pow_succ] at hcon; omega + have := Nat.count_monotone Q hb + rw [count_two_pow] at this + have e2 : Nat.fib (b + 1 + 1) = Nat.fib (b + 2) := rfl + omega + refine ⟨2 ^ a + 2 * k', (Q_block hk').2 hQ', ?_, ?_⟩ + · rw [count_block _ _ hk'.le, count_two_pow, hc'] + omega + · rw [bitIndices_block hk', Nat.zeckendorf_of_pos hn, ha] + simp [hl', hn'] + +/-- `Q` agrees with `IsTerm` on positive integers. -/ +private lemma Q_iff_isTerm {k : ℕ} (hk : 0 < k) : Q k ↔ IsTerm k := by + simp only [Q, IsTerm, padicValNat_two_mul k hk.ne', hk, true_and] + +/-- `count Q` exceeds `count IsTerm` by one (for `0`) on positive bounds. -/ +private lemma count_Q_eq (k : ℕ) : Nat.count Q (k + 1) = Nat.count IsTerm (k + 1) + 1 := by + induction k with + | zero => + have : ¬ IsTerm 0 := fun h => (lt_irrefl 0) h.1 + simp [Nat.count_succ, Q, this] + | succ k ih => + rw [Nat.count_succ, Nat.count_succ (p := IsTerm), ih] + have h := Q_iff_isTerm (show 0 < k + 1 by omega) + by_cases hq : Q (k + 1) + · rw [if_pos hq, if_pos (h.1 hq)] + · rw [if_neg hq, if_neg (fun h' => hq (h.2 h'))] + +/-- Every row of A373359 has as many elements as the Zeckendorf representation of its index. -/ +theorem result : statement := by + intro n hn + obtain ⟨k, hQ, hc, hl⟩ := main n + have hk : 0 < k := by + rcases Nat.eq_zero_or_pos k with rfl | h + · simp at hc; omega + · exact h + have hterm : IsTerm k := (Q_iff_isTerm hk).1 hQ + have hcount : Nat.count IsTerm k = n - 1 := by + obtain ⟨k0, rfl⟩ : ∃ k0, k = k0 + 1 := ⟨k - 1, by omega⟩ + have := count_Q_eq k0 + omega + have hA : A371176 n = k := by + rw [A371176, ← hcount, Nat.nth_count hterm] + rw [T, List.length_map, hA, hl] + +end Math0.Frontier.A373359 + +#math0_settles Math0.Frontier.A373359.result Math0.Statements.A373359.statement diff --git a/lean/Math0/Frontier/OEIS/A375522.lean b/lean/Math0/Frontier/OEIS/A375522.lean new file mode 100644 index 0000000..b71b2a9 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A375522.lean @@ -0,0 +1,251 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A375522 +import Math0.Audit + +/-! +# A375522: `S2(n) - S1(n) = 1` fails at `n = 42` + +The Sigrist–Sloane conjecture says that `S2(n) - S1(n) = 1` for all `n ≥ 1` except `n = 4, 6`. +We refute it: `S2(42) - S1(42) = 5`. + +Idea. Write the remainder `1 - s n = u n / D n` in lowest terms; then `S2(n) - S1(n) = u n`. +With `p` the next prime and `b = ⌊D / (u p)⌋ + 1`, the next remainder is `num / (D p b)` with +`num = u p - D % (u p)`, reduced by `g = gcd(num, D p b)`. The denominators `D n` grow doubly +exponentially (more than `10^11` digits at `n = 42`), so we never compute them. Instead we track +`D` modulo a modulus `X` (starting from `X = (190!)^2`): `D % (u p)` is known when `u p ∣ X`, +`⌊D / (u p)⌋` is then known modulo `X / (u p)`, `D p b` modulo `X / u`, and `g` is known when +`num ∣ X / u`; after dividing by `g` the new `D` is known modulo `X / u / g`. We prove that +this modular step is faithful under these checks (`mstep_spec`), and the kernel runs the 42 steps +and checks them (`mrun_42`), finding `u 42 = 5`: at `n = 42` (`p = 181`) the unreduced numerator +is `125` but only `25` cancels. +-/ + +namespace Math0.Frontier.A375522 +open Math0.Statements.A375522 + +/-- One exact step of the process on the remainder `R = 1 - s = u / D`, as a pair `(u, D)`: +with `b = D / (u p) + 1`, the new remainder is `num / den` where `num = u p b - D = u p - D % (u p)` +and `den = D p b`, reduced by `g = gcd num den`. -/ +private def tstep (p : ℕ) (x : ℕ × ℕ) : ℕ × ℕ := + let num := x.1 * p - x.2 % (x.1 * p) + let den := x.2 * (p * (x.2 / (x.1 * p) + 1)) + (num / Nat.gcd num den, den / Nat.gcd num den) + +/-- The exact pairs `(u n, D n)` with `1 - s n = u n / D n` in lowest terms. -/ +private def T : ℕ → ℕ × ℕ + | 0 => (1, 1) + | n + 1 => tstep (prime (n + 1)) (T n) + +/-- The `k`-th prime is positive. -/ +private theorem prime_pos (k : ℕ) : 0 < prime k := by + unfold prime; rw [primeAt_eq_nth]; exact (Nat.prime_nth_prime _).pos + +/-- If `R = u / D` with `u, D, p > 0`, then the greedy update +`R - 1 / (p * (1 + ⌊1 / (R p)⌋))` has numerator and denominator (in lowest terms) given by +`tstep p (u, D)`, and its numerator is positive. -/ +private theorem rat_step (R : ℚ) (u D p : ℕ) (hu : 0 < u) (hD : 0 < D) (hp : 0 < p) + (hR : R = (u : ℚ) / D) : + (R - 1 / ((p : ℚ) * ((1 + ⌊1 / (R * p)⌋ : ℤ) : ℚ))).num = (tstep p (u, D)).1 ∧ + (R - 1 / ((p : ℚ) * ((1 + ⌊1 / (R * p)⌋ : ℤ) : ℚ))).den = (tstep p (u, D)).2 ∧ + 0 < (tstep p (u, D)).1 := by + have hup : 0 < u * p := Nat.mul_pos hu hp + have hrlt : D % (u * p) < u * p := Nat.mod_lt _ hup + have hDqr : u * p * (D / (u * p)) + D % (u * p) = D := Nat.div_add_mod D (u * p) + have e1 : (tstep p (u, D)).1 = (u * p - D % (u * p)) / + Nat.gcd (u * p - D % (u * p)) (D * (p * (D / (u * p) + 1))) := rfl + have e2 : (tstep p (u, D)).2 = (D * (p * (D / (u * p) + 1))) / + Nat.gcd (u * p - D % (u * p)) (D * (p * (D / (u * p) + 1))) := rfl + rw [e1, e2] + generalize hq : D / (u * p) = q at hDqr ⊢ + generalize hr : D % (u * p) = r at hDqr hrlt ⊢ + have hnum_pos : 0 < u * p - r := by omega + have hden_pos : 0 < D * (p * (q + 1)) := by positivity + have hfloor : ⌊1 / (R * p)⌋ = (q : ℤ) := by + have : 1 / (R * p) = ((D : ℕ) : ℚ) / ((u * p : ℕ) : ℚ) := by + rw [hR]; push_cast; field_simp + rw [this, Rat.floor_natCast_div_natCast, ← hq]; rfl + have hR' : R - 1 / ((p : ℚ) * ((1 + ⌊1 / (R * p)⌋ : ℤ) : ℚ)) = + mkRat ((u * p - r : ℕ) : ℤ) (D * (p * (q + 1))) := by + rw [Rat.mkRat_eq_div, hfloor, hR] + have hnumQ : (((u * p - r : ℕ) : ℤ) : ℚ) = (u : ℚ) * p - r := by + rw [Int.cast_natCast, Nat.cast_sub hrlt.le]; push_cast; ring + have hDQ : (D : ℚ) = u * p * q + r := by rw [← hDqr]; push_cast; ring + rw [hnumQ] + have hD' : (D : ℚ) ≠ 0 := by positivity + have hp' : (p : ℚ) ≠ 0 := by positivity + have hq' : (q : ℚ) + 1 ≠ 0 := by positivity + push_cast + field_simp + linear_combination (-(q : ℚ) - 1) * hDQ + rw [hR', Rat.num_mkRat, Rat.den_mkRat, if_neg hden_pos.ne', if_neg hden_pos.ne', + Int.natAbs_natCast, Nat.gcd_comm] + refine ⟨rfl, rfl, Nat.div_pos (Nat.gcd_le_left _ hnum_pos) (Nat.gcd_pos_of_pos_left _ hnum_pos)⟩ + +/-- `T n` is the reduced numerator/denominator pair of the remainder `1 - s n`. -/ +private theorem T_spec (n : ℕ) : + (1 - s n).num = (T n).1 ∧ (1 - s n).den = (T n).2 ∧ 0 < (T n).1 := by + induction n with + | zero => simp [s, T] + | succ n ih => + obtain ⟨h1, h2, h3⟩ := ih + have hrec : 1 - s (n + 1) = (1 - s n) - 1 / ((prime (n + 1) : ℚ) * + ((1 + ⌊1 / ((1 - s n) * (prime (n + 1) : ℚ))⌋ : ℤ) : ℚ)) := by + rw [s]; ring + have hR : 1 - s n = ((T n).1 : ℚ) / ((T n).2 : ℚ) := by + rw [← Rat.num_div_den (1 - s n), h1, h2]; rfl + have hD : 0 < (T n).2 := h2 ▸ (1 - s n).den_pos + rw [hrec] + exact rat_step (1 - s n) _ _ _ h3 hD (prime_pos _) hR + +/-- `a n - S1 n` equals the numerator of the remainder `1 - s n`. -/ +private theorem diff_eq (n : ℕ) : (a n : ℤ) - S1 n = (1 - s n).num := by + have hden : (1 - s n).den = (s n).den := by + have := Rat.intCast_sub_den 1 (s n) + simp only [Int.cast_one] at this + exact this + have key : ((s n).num : ℚ) = ((1 - s n).den : ℚ) - (1 - s n).num := by + rw [← Rat.mul_den_eq_num, ← Rat.mul_den_eq_num, hden]; ring + have key' : (s n).num = ((1 - s n).den : ℤ) - (1 - s n).num := by exact_mod_cast key + unfold a S1 + rw [key', hden]; ring + +/-- The same step computed from `(u, Dm, X)` where `Dm` is a residue of the true `D` modulo `X`: +it returns the new `u`, a residue of the new `D`, and the new modulus `X / u / g`. -/ +private def mstep (p : ℕ) (st : ℕ × ℕ × ℕ) : ℕ × ℕ × ℕ := + let num := st.1 * p - st.2.1 % (st.1 * p) + let den := st.2.1 * (p * (st.2.1 / (st.1 * p) + 1)) + let g := Nat.gcd num den + (num / g, den / g % (st.2.2 / st.1 / g), st.2.2 / st.1 / g) + +/-- The side conditions under which `mstep` is faithful: `u p > 0`, `u p ∣ X`, and the new +unreduced numerator `u p - Dm % (u p)` divides `X / u`. -/ +private def mok (p : ℕ) (st : ℕ × ℕ × ℕ) : Bool := + 0 < st.1 * p && st.2.2 % (st.1 * p) == 0 && + st.2.2 / st.1 % (st.1 * p - st.2.1 % (st.1 * p)) == 0 + +/-- Run `mstep` from `(1, 1, X0)`, checking `mok` at every step (`none` if a check fails). -/ +private def mrun (X0 : ℕ) : ℕ → Option (ℕ × ℕ × ℕ) + | 0 => some (1, 1, X0) + | n + 1 => (mrun X0 n).bind fun st => + if mok (prime (n + 1)) st then some (mstep (prime (n + 1)) st) else none + +/-- Faithfulness of one modular step: if `D ≡ Dm [MOD X]` and the checks pass, the modular step +returns the true new `u` and a residue of the true new `D` modulo the new modulus. -/ +private theorem mstep_spec (p u D Dm X : ℕ) (hok : mok p (u, Dm, X) = true) + (hmod : D ≡ Dm [MOD X]) : + (tstep p (u, D)).1 = (mstep p (u, Dm, X)).1 ∧ + (tstep p (u, D)).2 ≡ (mstep p (u, Dm, X)).2.1 [MOD (mstep p (u, Dm, X)).2.2] := by + simp only [mok, Bool.and_eq_true, decide_eq_true_eq, beq_iff_eq] at hok + obtain ⟨⟨hup, hX⟩, hnum⟩ := hok + have hu : 0 < u := Nat.pos_of_mul_pos_right hup + obtain ⟨k, rfl⟩ : u * p ∣ X := Nat.dvd_of_mod_eq_zero hX + have hXu : u * p * k / u = p * k := by rw [mul_assoc, Nat.mul_div_cancel_left _ hu] + have hr : D % (u * p) = Dm % (u * p) := Nat.ModEq.of_dvd (Dvd.intro k rfl) hmod + have hD1 := Nat.div_add_mod D (u * p) + have hD2 := Nat.div_add_mod Dm (u * p) + have hX' := Nat.modEq_iff_dvd.mp hmod + have e1 : (tstep p (u, D)).1 = (u * p - D % (u * p)) / + Nat.gcd (u * p - D % (u * p)) (D * (p * (D / (u * p) + 1))) := rfl + have e2 : (tstep p (u, D)).2 = (D * (p * (D / (u * p) + 1))) / + Nat.gcd (u * p - D % (u * p)) (D * (p * (D / (u * p) + 1))) := rfl + have e3 : mstep p (u, Dm, u * p * k) = ((u * p - Dm % (u * p)) / + Nat.gcd (u * p - Dm % (u * p)) (Dm * (p * (Dm / (u * p) + 1))), + (Dm * (p * (Dm / (u * p) + 1))) / + Nat.gcd (u * p - Dm % (u * p)) (Dm * (p * (Dm / (u * p) + 1))) % + (u * p * k / u / Nat.gcd (u * p - Dm % (u * p)) (Dm * (p * (Dm / (u * p) + 1)))), + u * p * k / u / Nat.gcd (u * p - Dm % (u * p)) (Dm * (p * (Dm / (u * p) + 1)))) := rfl + rw [e1, e2, e3, hr, hXu] + simp only [hXu] at hnum + rw [hr] at hD1 + have hrlt : Dm % (u * p) < u * p := Nat.mod_lt _ hup + generalize D / (u * p) = q1 at hD1 ⊢ + generalize Dm / (u * p) = q2 at hD2 ⊢ + generalize Dm % (u * p) = r at hD1 hD2 hnum hrlt ⊢ + generalize hnumdef : u * p - r = num at hnum ⊢ + have hnumd : num ∣ p * k := Nat.dvd_of_mod_eq_zero hnum + have hq : (k : ℤ) ∣ (q2 : ℤ) - q1 := by + have e : (Dm : ℤ) - D = ((u * p : ℕ) : ℤ) * ((q2 : ℤ) - q1) := by + rw [← hD1, ← hD2]; push_cast; ring + have : ((u * p : ℕ) : ℤ) * k ∣ ((u * p : ℕ) : ℤ) * ((q2 : ℤ) - q1) := by + rw [← e]; exact_mod_cast hX' + exact (mul_dvd_mul_iff_left (by positivity)).mp this + have hd : ((p * k : ℕ) : ℤ) ∣ ((Dm * (p * (q2 + 1)) : ℕ) : ℤ) - ((D * (p * (q1 + 1)) : ℕ) : ℤ) := by + obtain ⟨c, hc⟩ := hX' + obtain ⟨e, he⟩ := hq + refine ⟨u * p * c * (q2 + 1) + D * e, ?_⟩ + push_cast at hc ⊢ + linear_combination (p : ℤ) * (q2 + 1) * hc + (p : ℤ) * D * he + have hdm : D * (p * (q1 + 1)) ≡ Dm * (p * (q2 + 1)) [MOD p * k] := Nat.modEq_iff_dvd.mpr hd + have hg : Nat.gcd num (D * (p * (q1 + 1))) = Nat.gcd num (Dm * (p * (q2 + 1))) := by + have := (hdm.of_dvd hnumd).gcd_eq + rw [Nat.gcd_comm, this, Nat.gcd_comm] + rw [hg] + refine ⟨rfl, ?_⟩ + generalize hgdef : Nat.gcd num (Dm * (p * (q2 + 1))) = g + have hg1 : g ∣ D * (p * (q1 + 1)) := hgdef ▸ hg ▸ Nat.gcd_dvd_right _ _ + have hg2 : g ∣ Dm * (p * (q2 + 1)) := hgdef ▸ Nat.gcd_dvd_right _ _ + have hg3 : g ∣ p * k := (hgdef ▸ Nat.gcd_dvd_left _ _ : g ∣ num).trans hnumd + have hgpos : 0 < g := by + rw [← hgdef]; apply Nat.gcd_pos_of_pos_left; omega + refine Nat.ModEq.trans ?_ (Nat.mod_modEq _ _).symm + obtain ⟨x1, hx1⟩ := hg1 + obtain ⟨x2, hx2⟩ := hg2 + obtain ⟨x3, hx3⟩ := hg3 + rw [hx1, hx2, hx3] at hdm + rw [hx1, hx2, hx3, Nat.mul_div_cancel_left _ hgpos, Nat.mul_div_cancel_left _ hgpos, + Nat.mul_div_cancel_left _ hgpos] + exact Nat.ModEq.mul_left_cancel' hgpos.ne' hdm + +/-- Faithfulness of the whole modular run. -/ +private theorem mrun_spec (X0 : ℕ) (n : ℕ) : + ∀ st, mrun X0 n = some st → (T n).1 = st.1 ∧ (T n).2 ≡ st.2.1 [MOD st.2.2] := by + induction n with + | zero => + intro st h + simp only [mrun, Option.some.injEq] at h + subst h + exact ⟨rfl, rfl⟩ + | succ n ih => + intro st h + simp only [mrun] at h + cases hm : mrun X0 n with + | none => rw [hm] at h; simp at h + | some st0 => + rw [hm] at h + simp only [Option.bind_some] at h + split_ifs at h with hok + cases h + obtain ⟨h1, h2⟩ := ih st0 hm + obtain ⟨u, Dm, X⟩ := st0 + have key := mstep_spec (prime (n + 1)) u (T n).2 Dm X hok h2 + have hT : T n = (u, (T n).2) := Prod.ext h1 rfl + show (tstep (prime (n + 1)) (T n)).1 = _ ∧ (tstep (prime (n + 1)) (T n)).2 ≡ _ [MOD _] + rw [hT] + exact key + +/-- The starting modulus `(190!)^2`. -/ +private def X0 : ℕ := Nat.factorial 190 ^ 2 + +/-- Kernel computation: the modular run from `X0 = (190!)^2` passes all 42 checks and gives +`u 42 = 5`. -/ +private theorem mrun_42 : (mrun X0 42).map (·.1) = some 5 := by + decide +kernel + +/-- The conjecture fails at `n = 42`: there `S2(42) - S1(42) = 5`. -/ +theorem result : ¬ statement := by + intro h + have h42 := h 42 (by norm_num) (by norm_num) (by norm_num) + rw [diff_eq, (T_spec 42).1] at h42 + obtain ⟨st, hst, h5⟩ : ∃ st, mrun X0 42 = some st ∧ st.1 = 5 := by + have := mrun_42 + cases hm : mrun X0 42 with + | none => rw [hm] at this; simp at this + | some st => rw [hm] at this; simp at this; exact ⟨st, rfl, this⟩ + rw [(mrun_spec X0 42 st hst).1, h5] at h42 + norm_num at h42 + +end Math0.Frontier.A375522 + +#math0_settles Math0.Frontier.A375522.result Math0.Statements.A375522.statement diff --git a/lean/Math0/Frontier/OEIS/A386538.lean b/lean/Math0/Frontier/OEIS/A386538.lean new file mode 100644 index 0000000..2057dfe --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A386538.lean @@ -0,0 +1,425 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A386538 +import Math0.Audit + +/-! +# A386538: a non-lattice center gives a larger lattice polygon (counterexample at `n = 7`) + +The conjecture says that the largest area of a polygon with vertices on the unit grid inside a +circle of radius `n` does not grow when the center of the circle is allowed to be any point of +the plane instead of a grid point. We refute it at `n = 7` with the center `c0 = (5/12, 5/24)`. + +* Upper bound (lattice center). Every grid point `(x, y)` with `x² + y² ≤ 49` satisfies the twelve + inequalities `±3x ± y ≤ 21`, `±x ± y ≤ 9`, `±x ± 3y ≤ 21` (a kernel-checked finite check). + Their solution set is convex (the 12-gon with vertices `(±7, 0), (±6, ±3), (±3, ±6), (0, ±7)`), + so it contains the convex hull. Cutting this 12-gon by the vertical lines `x = -6, -3, 0, 3, 6` + gives six trapezoids; thickening each vertically by `1/100` makes it a `regionBetween` of two + affine functions over a closed interval, whose volume is an explicit integral. Hence the hull + has area at most `138 + 28/100 = 3457/25` (its true area is `138`). +* Lower bound (center `c0`). For each `x ∈ {-6, …, 7}` let `lo x` and `hi x` be the lowest and + highest grid points in the disk of radius `7` around `c0` on the vertical line through `x`. + Joining consecutive columns gives eleven trapezoids (open in both directions, pairwise disjoint) + whose corners are grid points in that disk. Each trapezoid lies in the convex hull because its + points are convex combinations of its corners, and the trapezoids have total area `277/2`. +* Since `3457/25 < 277/2`, the hull for the center `c0` is strictly larger than the hull for the + lattice center, so `⨆ c, maxArea c 7 > maxArea 0 7`. +-/ + +namespace Math0.Frontier.A386538 + +open Math0.Statements.A386538 MeasureTheory Set + +/-- A trapezoid over the closed interval `[a, b]`, between the lines `y = p x + q` and +`y = r x + t` (open in the vertical direction). -/ +private def upSlab (a b p q r t : ℝ) : Set (ℝ × ℝ) := + regionBetween (fun x => p * x + q) (fun x => r * x + t) (Icc a b) + +/-- A trapezoid over the open interval `(a, b)`, strictly between the lines `y = p x + q` and +`y = r x + t`. -/ +private def lowSlab (a b p q r t : ℝ) : Set (ℝ × ℝ) := + regionBetween (fun x => p * x + q) (fun x => r * x + t) (Ioo a b) + +/-- Membership in `upSlab`. -/ +private lemma mem_upSlab {a b p q r t : ℝ} {z : ℝ × ℝ} (h1 : a ≤ z.1) (h2 : z.1 ≤ b) + (h3 : p * z.1 + q < z.2) (h4 : z.2 < r * z.1 + t) : z ∈ upSlab a b p q r t := + ⟨⟨h1, h2⟩, h3, h4⟩ + +/-- Points of `lowSlab a b …` have first coordinate in `(a, b)`. -/ +private lemma lowSlab_fst {a b p q r t : ℝ} {z : ℝ × ℝ} (h : z ∈ lowSlab a b p q r t) : + a < z.1 ∧ z.1 < b := h.1 + +/-- `lowSlab a b …` lies to the right of every `c ≤ a`. -/ +private lemma lowSlab_subset_ge {a b p q r t c : ℝ} (hc : c ≤ a) : + lowSlab a b p q r t ⊆ {z | c ≤ z.1} := fun _ hz => hc.trans (lowSlab_fst hz).1.le + +/-- `lowSlab` is measurable. -/ +private lemma measurableSet_lowSlab (a b p q r t : ℝ) : MeasurableSet (lowSlab a b p q r t) := + measurableSet_regionBetween (by fun_prop) (by fun_prop) measurableSet_Ioo + +/-- An affine function that is nonnegative at both ends of an interval is nonnegative on it +(stated for the difference of two affine functions). -/ +private lemma affine_le_of_ends {a b x p q r t : ℝ} (hab : a < b) (hxa : a ≤ x) (hxb : x ≤ b) + (ha : p * a + q ≤ r * a + t) (hb : p * b + q ≤ r * b + t) : p * x + q ≤ r * x + t := by + nlinarith [mul_nonneg (sub_nonneg.2 hxa) (sub_nonneg.2 hb), + mul_nonneg (sub_nonneg.2 hxb) (sub_nonneg.2 ha)] + +/-- The integral of the difference of two affine functions. -/ +private lemma integral_affine (a b p q r t : ℝ) : + ∫ x in a..b, ((fun x => r * x + t) - (fun x => p * x + q)) x = + (r - p) * (b ^ 2 - a ^ 2) / 2 + (t - q) * (b - a) := by + have : ((fun x : ℝ => r * x + t) - (fun x => p * x + q)) = fun x => (r - p) * x + (t - q) := by + funext x; simp only [Pi.sub_apply]; ring + rw [this, intervalIntegral.integral_add, intervalIntegral.integral_const_mul, integral_id, + intervalIntegral.integral_const] + · simp only [smul_eq_mul]; ring + · exact (continuous_const.mul continuous_id).intervalIntegrable _ _ + · exact continuous_const.intervalIntegrable _ _ + +/-- The area of a trapezoid `upSlab`. -/ +private lemma vol_up {a b p q r t : ℝ} (hab : a < b) + (ha : p * a + q ≤ r * a + t) (hb : p * b + q ≤ r * b + t) : + volume (upSlab a b p q r t) = + ENNReal.ofReal ((r - p) * (b ^ 2 - a ^ 2) / 2 + (t - q) * (b - a)) := by + rw [upSlab, Measure.volume_eq_prod, volume_regionBetween_eq_integral + (Continuous.integrableOn_Icc (by fun_prop)) (Continuous.integrableOn_Icc (by fun_prop)) + measurableSet_Icc (fun x hx => affine_le_of_ends hab hx.1 hx.2 ha hb), + integral_Icc_eq_integral_Ioc, ← intervalIntegral.integral_of_le hab.le, integral_affine] + +/-- The area of a trapezoid `lowSlab`. -/ +private lemma vol_low {a b p q r t : ℝ} (hab : a < b) + (ha : p * a + q ≤ r * a + t) (hb : p * b + q ≤ r * b + t) : + volume (lowSlab a b p q r t) = + ENNReal.ofReal ((r - p) * (b ^ 2 - a ^ 2) / 2 + (t - q) * (b - a)) := by + rw [lowSlab, Measure.volume_eq_prod, volume_regionBetween_eq_integral + ((Continuous.integrableOn_Icc (by fun_prop)).mono_set Ioo_subset_Icc_self) + ((Continuous.integrableOn_Icc (by fun_prop)).mono_set Ioo_subset_Icc_self) + measurableSet_Ioo (fun x hx => affine_le_of_ends hab hx.1.le hx.2.le ha hb), + ← integral_Ioc_eq_integral_Ioo, ← intervalIntegral.integral_of_le hab.le, integral_affine] + +/-- A trapezoid `lowSlab` whose four corners lie in a convex set `K` lies in `K`. -/ +private lemma lowSlab_subset {K : Set (ℝ × ℝ)} (hK : Convex ℝ K) {a b p q r t : ℝ} + (hab : a < b) + (h1 : (a, p * a + q) ∈ K) (h2 : (b, p * b + q) ∈ K) (h3 : (a, r * a + t) ∈ K) + (h4 : (b, r * b + t) ∈ K) : lowSlab a b p q r t ⊆ K := by + rintro ⟨x, y⟩ ⟨hx, hy⟩ + simp only [mem_Ioo] at hx hy + have hba : 0 < b - a := sub_pos.2 hab + have hL : ((x : ℝ), p * x + q) ∈ K := by + have := hK h1 h2 (a := (b - x) / (b - a)) (b := (x - a) / (b - a)) + (div_nonneg (by linarith) hba.le) (div_nonneg (by linarith) hba.le) + (by field_simp; ring) + convert this using 1 + ext <;> simp <;> field_simp <;> ring + have hU : ((x : ℝ), r * x + t) ∈ K := by + have := hK h3 h4 (a := (b - x) / (b - a)) (b := (x - a) / (b - a)) + (div_nonneg (by linarith) hba.le) (div_nonneg (by linarith) hba.le) + (by field_simp; ring) + convert this using 1 + ext <;> simp <;> field_simp <;> ring + have hd : 0 < r * x + t - (p * x + q) := by linarith + set D := r * x + t - (p * x + q) with hD + have hs : (y - (p * x + q)) / D * D = y - (p * x + q) := div_mul_cancel₀ _ hd.ne' + have hs0 : 0 ≤ (y - (p * x + q)) / D := div_nonneg (by linarith) hd.le + have hs1 : (y - (p * x + q)) / D ≤ 1 := (div_le_one hd).2 (by linarith) + have := hK hL hU (a := 1 - (y - (p * x + q)) / D) (b := (y - (p * x + q)) / D) + (by linarith) hs0 (by ring) + convert this using 1 + ext + · simp; ring + · simp only [Prod.snd_add, Prod.smul_snd, smul_eq_mul] + linear_combination (-1 : ℝ) * hs + +/-- Subadditivity of the volume, in the form used for the upper bound. -/ +private lemma le_add_of_union {s T : Set (ℝ × ℝ)} {x y : ENNReal} (hs : volume s ≤ x) + (hT : volume T ≤ y) : volume (s ∪ T) ≤ x + y := + (measure_union_le s T).trans (add_le_add hs hT) + +/-- Additivity of the volume for a trapezoid `lowSlab a b …` and a measurable set to its right. -/ +private lemma vol_union_lowSlab {a b p q r t : ℝ} {T : Set (ℝ × ℝ)} (hT : MeasurableSet T) + (hTb : T ⊆ {z | b ≤ z.1}) : + volume (lowSlab a b p q r t ∪ T) = volume (lowSlab a b p q r t) + volume T := by + refine measure_union (Set.disjoint_left.2 fun z hz hz' => ?_) hT + have h1 := (lowSlab_fst hz).2 + have h2 : b ≤ z.1 := hTb hz' + linarith + + +/-- The intersection of the closed half-planes `α x + β y ≤ γ` for `(α, β, γ) ∈ H`. -/ +private def HP (H : List (ℤ × ℤ × ℤ)) : Set (ℝ × ℝ) := + {z | ∀ h ∈ H, (h.1 : ℝ) * z.1 + (h.2.1 : ℝ) * z.2 ≤ (h.2.2 : ℝ)} + +/-- An intersection of half-planes is convex. -/ +private lemma convex_HP (H : List (ℤ × ℤ × ℤ)) : Convex ℝ (HP H) := by + intro z hz w hw a b ha hb hab h hh + have h1 := hz h hh + have h2 := hw h hh + simp only [Prod.fst_add, Prod.snd_add, Prod.smul_fst, Prod.smul_snd, smul_eq_mul] + have e : (h.2.2 : ℝ) = a * h.2.2 + b * h.2.2 := by rw [← add_mul, hab, one_mul] + rw [e] + nlinarith [mul_le_mul_of_nonneg_left h1 ha, mul_le_mul_of_nonneg_left h2 hb] + +/-- The twelve edge half-planes of the 12-gon with vertices `(±7, 0), (±6, ±3), (±3, ±6), (0, ±7)`, +the convex hull of the grid points in the disk of radius `7` around the origin. -/ +private def H0 : List (ℤ × ℤ × ℤ) := + [(-3, -1, 21), (-1, -1, 9), (-1, -3, 21), (1, -3, 21), (1, -1, 9), (3, -1, 21), + (-3, 1, 21), (-1, 1, 9), (-1, 3, 21), (1, 3, 21), (1, 1, 9), (3, 1, 21)] + +/-- Finite check: every grid point in the disk of radius `7` around the origin satisfies the +twelve inequalities of `H0`. -/ +private lemma check0 : ∀ i : ℕ, i < 15 → ∀ j : ℕ, j < 15 → + ((i : ℤ) - 7) ^ 2 + ((j : ℤ) - 7) ^ 2 ≤ 49 → + ∀ h ∈ H0, h.1 * ((i : ℤ) - 7) + h.2.1 * ((j : ℤ) - 7) ≤ h.2.2 := by + decide +kernel + +/-- `check0` restated for arbitrary integers `x, y` with `x² + y² ≤ 49`. -/ +private lemma int_check0 (x y : ℤ) (hxy : x ^ 2 + y ^ 2 ≤ 49) : + ∀ h ∈ H0, h.1 * x + h.2.1 * y ≤ h.2.2 := by + have hx1 : -7 ≤ x := by nlinarith + have hx2 : x ≤ 7 := by nlinarith + have hy1 : -7 ≤ y := by nlinarith + have hy2 : y ≤ 7 := by nlinarith + have := check0 (x + 7).toNat (by omega) (y + 7).toNat (by omega) + have ex : (((x + 7).toNat : ℕ) : ℤ) - 7 = x := by omega + have ey : (((y + 7).toNat : ℕ) : ℤ) - 7 = y := by omega + rw [ex, ey] at this + exact this hxy + +/-- The grid points in the disk of radius `7` around the origin lie in the 12-gon `HP H0`. -/ +private lemma disk0_subset : latticeDisk 0 ((7 : ℕ) : ℝ) ⊆ HP H0 := by + rintro z ⟨x, y, rfl, hxy⟩ h hh + have hxy' : x ^ 2 + y ^ 2 ≤ 49 := by + norm_num at hxy + exact_mod_cast hxy + have := int_check0 x y hxy' h hh + simp only + exact_mod_cast this + +/-- The non-lattice center. -/ +private noncomputable def c0 : ℝ × ℝ := (5 / 12, 5 / 24) + +/-- A grid point in the disk of radius `7` around `c0` lies in the convex hull of all of them. -/ +private lemma mem_hull_c0 {u v : ℝ} (x y : ℤ) (hu : u = x) (hv : v = y) + (hd : ((x : ℝ) - 5 / 12) ^ 2 + ((y : ℝ) - 5 / 24) ^ 2 ≤ 49) : + (u, v) ∈ convexHull ℝ (latticeDisk c0 ((7 : ℕ) : ℝ)) := by + apply subset_convexHull + refine ⟨x, y, by rw [hu, hv], ?_⟩ + simp only [c0] + norm_num + linarith + + +/-- Six slightly thickened trapezoids covering the convex hull of the lattice points in the disk of +radius `7` around the origin. -/ +private def U0 : Set (ℝ × ℝ) := + upSlab (-7) (-6) (-3) (-2101/100) 3 (2101/100) ∪ + (upSlab (-6) (-3) (-1) (-901/100) 1 (901/100) ∪ + (upSlab (-3) 0 (-1/3) (-701/100) (1/3) (701/100) ∪ + (upSlab 0 3 (1/3) (-701/100) (-1/3) (701/100) ∪ + (upSlab 3 6 1 (-901/100) (-1) (901/100) ∪ + (upSlab 6 7 3 (-2101/100) (-3) (2101/100)))))) + +/-- Eleven column trapezoids, all of whose corners are lattice points in the disk of radius `7` +around `c0`. -/ +private def L0 : Set (ℝ × ℝ) := + lowSlab (-6) (-5) (-2) (-14) 1 9 ∪ + (lowSlab (-5) (-4) (-1) (-9) 1 9 ∪ + (lowSlab (-4) (-3) 0 (-5) 1 9 ∪ + (lowSlab (-3) (-2) (-1) (-8) 0 6 ∪ + (lowSlab (-2) (-1) 0 (-6) 1 8 ∪ + (lowSlab (-1) 2 0 (-6) 0 7 ∪ + (lowSlab 2 3 0 (-6) (-1) 9 ∪ + (lowSlab 3 4 1 (-9) 0 6 ∪ + (lowSlab 4 5 0 (-5) (-1) 10 ∪ + (lowSlab 5 6 1 (-10) (-1) 10 ∪ + (lowSlab 6 7 2 (-16) (-2) 16)))))))))) + +/-- The polygon `HP H0` lies in the union of the six thickened trapezoids. -/ +private lemma HP_subset_U0 : HP H0 ⊆ U0 := by + intro z hz + have h1 := hz (-3, -1, 21) (by simp [H0]) + have h2 := hz (-1, -1, 9) (by simp [H0]) + have h3 := hz (-1, -3, 21) (by simp [H0]) + have h4 := hz (1, -3, 21) (by simp [H0]) + have h5 := hz (1, -1, 9) (by simp [H0]) + have h6 := hz (3, -1, 21) (by simp [H0]) + have h7 := hz (-3, 1, 21) (by simp [H0]) + have h8 := hz (-1, 1, 9) (by simp [H0]) + have h9 := hz (-1, 3, 21) (by simp [H0]) + have h10 := hz (1, 3, 21) (by simp [H0]) + have h11 := hz (1, 1, 9) (by simp [H0]) + have h12 := hz (3, 1, 21) (by simp [H0]) + push_cast at h1 h2 h3 h4 h5 h6 h7 h8 h9 h10 h11 h12 + unfold U0 + rcases le_or_gt z.1 (-6) with hx0 | hx0 + · exact Or.inl <| mem_upSlab (by linarith) (by linarith) (by linarith) (by linarith) + rcases le_or_gt z.1 (-3) with hx1 | hx1 + · exact Or.inr <| Or.inl <| mem_upSlab (by linarith) (by linarith) (by linarith) (by linarith) + rcases le_or_gt z.1 0 with hx2 | hx2 + · exact Or.inr <| Or.inr <| Or.inl <| + mem_upSlab (by linarith) (by linarith) (by linarith) (by linarith) + rcases le_or_gt z.1 3 with hx3 | hx3 + · exact Or.inr <| Or.inr <| Or.inr <| Or.inl <| + mem_upSlab (by linarith) (by linarith) (by linarith) (by linarith) + rcases le_or_gt z.1 6 with hx4 | hx4 + · exact Or.inr <| Or.inr <| Or.inr <| Or.inr <| Or.inl <| + mem_upSlab (by linarith) (by linarith) (by linarith) (by linarith) + exact Or.inr <| Or.inr <| Or.inr <| Or.inr <| Or.inr <| + mem_upSlab (by linarith) (by linarith) (by linarith) (by linarith) + +/-- The volume of `U0` is at most `3457/25 = 138.28`. -/ +private lemma vol_U0 : volume U0 ≤ ENNReal.ofReal (3457 / 25) := by + unfold U0 + have v0 : volume (upSlab (-7) (-6) (-3) (-2101/100) 3 (2101/100)) = ENNReal.ofReal (151/50) := by + rw [vol_up] <;> norm_num + have v1 : volume (upSlab (-6) (-3) (-1) (-901/100) 1 (901/100)) = ENNReal.ofReal (1353/50) := by + rw [vol_up] <;> norm_num + have v2 : volume (upSlab (-3) 0 (-1/3) (-701/100) (1/3) (701/100)) = + ENNReal.ofReal (1953/50) := by + rw [vol_up] <;> norm_num + have v3 : volume (upSlab 0 3 (1/3) (-701/100) (-1/3) (701/100)) = ENNReal.ofReal (1953/50) := by + rw [vol_up] <;> norm_num + have v4 : volume (upSlab 3 6 1 (-901/100) (-1) (901/100)) = ENNReal.ofReal (1353/50) := by + rw [vol_up] <;> norm_num + have v5 : volume (upSlab 6 7 3 (-2101/100) (-3) (2101/100)) = ENNReal.ofReal (151/50) := by + rw [vol_up] <;> norm_num + refine le_trans (le_add_of_union v0.le (le_add_of_union v1.le (le_add_of_union v2.le + (le_add_of_union v3.le (le_add_of_union v4.le v5.le))))) ?_ + repeat rw [← ENNReal.ofReal_add] + · exact ENNReal.ofReal_le_ofReal (by norm_num) + all_goals norm_num + +/-- The eleven trapezoids lie in the convex hull of the lattice points in the disk around `c0`. -/ +private lemma L0_subset : L0 ⊆ convexHull ℝ (latticeDisk c0 ((7 : ℕ) : ℝ)) := by + unfold L0 + refine union_subset ?_ ?_ + · exact lowSlab_subset (convex_convexHull ℝ _) (by norm_num) + (mem_hull_c0 (-6) (-2) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-5) (-4) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-6) (3) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-5) (4) (by norm_num) (by norm_num) (by norm_num)) + refine union_subset ?_ ?_ + · exact lowSlab_subset (convex_convexHull ℝ _) (by norm_num) + (mem_hull_c0 (-5) (-4) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-4) (-5) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-5) (4) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-4) (5) (by norm_num) (by norm_num) (by norm_num)) + refine union_subset ?_ ?_ + · exact lowSlab_subset (convex_convexHull ℝ _) (by norm_num) + (mem_hull_c0 (-4) (-5) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-3) (-5) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-4) (5) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-3) (6) (by norm_num) (by norm_num) (by norm_num)) + refine union_subset ?_ ?_ + · exact lowSlab_subset (convex_convexHull ℝ _) (by norm_num) + (mem_hull_c0 (-3) (-5) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-2) (-6) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-3) (6) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-2) (6) (by norm_num) (by norm_num) (by norm_num)) + refine union_subset ?_ ?_ + · exact lowSlab_subset (convex_convexHull ℝ _) (by norm_num) + (mem_hull_c0 (-2) (-6) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-1) (-6) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-2) (6) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-1) (7) (by norm_num) (by norm_num) (by norm_num)) + refine union_subset ?_ ?_ + · exact lowSlab_subset (convex_convexHull ℝ _) (by norm_num) + (mem_hull_c0 (-1) (-6) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (2) (-6) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (-1) (7) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (2) (7) (by norm_num) (by norm_num) (by norm_num)) + refine union_subset ?_ ?_ + · exact lowSlab_subset (convex_convexHull ℝ _) (by norm_num) + (mem_hull_c0 (2) (-6) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (3) (-6) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (2) (7) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (3) (6) (by norm_num) (by norm_num) (by norm_num)) + refine union_subset ?_ ?_ + · exact lowSlab_subset (convex_convexHull ℝ _) (by norm_num) + (mem_hull_c0 (3) (-6) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (4) (-5) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (3) (6) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (4) (6) (by norm_num) (by norm_num) (by norm_num)) + refine union_subset ?_ ?_ + · exact lowSlab_subset (convex_convexHull ℝ _) (by norm_num) + (mem_hull_c0 (4) (-5) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (5) (-5) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (4) (6) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (5) (5) (by norm_num) (by norm_num) (by norm_num)) + refine union_subset ?_ ?_ + · exact lowSlab_subset (convex_convexHull ℝ _) (by norm_num) + (mem_hull_c0 (5) (-5) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (6) (-4) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (5) (5) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (6) (4) (by norm_num) (by norm_num) (by norm_num)) + · exact lowSlab_subset (convex_convexHull ℝ _) (by norm_num) + (mem_hull_c0 (6) (-4) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (7) (-2) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (6) (4) (by norm_num) (by norm_num) (by norm_num)) + (mem_hull_c0 (7) (2) (by norm_num) (by norm_num) (by norm_num)) + +/-- The volume of `L0` is `277/2 = 138.5`. -/ +private lemma vol_L0 : volume L0 = ENNReal.ofReal (277 / 2) := by + unfold L0 + have v0 : volume (lowSlab (-6) (-5) (-2) (-14) 1 9) = ENNReal.ofReal (13/2) := by + rw [vol_low] <;> norm_num + have v1 : volume (lowSlab (-5) (-4) (-1) (-9) 1 9) = ENNReal.ofReal 9 := by + rw [vol_low] <;> norm_num + have v2 : volume (lowSlab (-4) (-3) 0 (-5) 1 9) = ENNReal.ofReal (21/2) := by + rw [vol_low] <;> norm_num + have v3 : volume (lowSlab (-3) (-2) (-1) (-8) 0 6) = ENNReal.ofReal (23/2) := by + rw [vol_low] <;> norm_num + have v4 : volume (lowSlab (-2) (-1) 0 (-6) 1 8) = ENNReal.ofReal (25/2) := by + rw [vol_low] <;> norm_num + have v5 : volume (lowSlab (-1) 2 0 (-6) 0 7) = ENNReal.ofReal 39 := by + rw [vol_low] <;> norm_num + have v6 : volume (lowSlab 2 3 0 (-6) (-1) 9) = ENNReal.ofReal (25/2) := by + rw [vol_low] <;> norm_num + have v7 : volume (lowSlab 3 4 1 (-9) 0 6) = ENNReal.ofReal (23/2) := by + rw [vol_low] <;> norm_num + have v8 : volume (lowSlab 4 5 0 (-5) (-1) 10) = ENNReal.ofReal (21/2) := by + rw [vol_low] <;> norm_num + have v9 : volume (lowSlab 5 6 1 (-10) (-1) 10) = ENNReal.ofReal 9 := by + rw [vol_low] <;> norm_num + have v10 : volume (lowSlab 6 7 2 (-16) (-2) 16) = ENNReal.ofReal 6 := by + rw [vol_low] <;> norm_num + repeat rw [vol_union_lowSlab] + · rw [v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10] + repeat rw [← ENNReal.ofReal_add] + · norm_num + all_goals norm_num + all_goals + repeat' first + | exact measurableSet_lowSlab _ _ _ _ _ _ + | exact lowSlab_subset_ge (by norm_num) + | apply MeasurableSet.union + | apply union_subset + +/-- The convex hull of the lattice points in the closed disk of radius `7` around the origin lies +in `U0`. -/ +private lemma hull0_subset : convexHull ℝ (latticeDisk 0 ((7 : ℕ) : ℝ)) ⊆ U0 := + (convexHull_min disk0_subset (convex_HP H0)).trans HP_subset_U0 + +/-- The conjecture fails at `n = 7`: with the center `c0 = (5/12, 5/24)` the convex hull of the +lattice points in the disk of radius `7` has area at least `277/2`, while with a lattice center +it has area at most `3457/25 < 277/2` (in fact exactly `138`). -/ +theorem result : ¬ statement := by + intro h + have h7 := h 7 + have hlt : maxArea 0 ((7 : ℕ) : ℝ) < maxArea c0 ((7 : ℕ) : ℝ) := by + unfold maxArea + calc volume (convexHull ℝ (latticeDisk 0 ((7 : ℕ) : ℝ))) ≤ volume U0 := + measure_mono hull0_subset + _ ≤ ENNReal.ofReal (3457 / 25) := vol_U0 + _ < ENNReal.ofReal (277 / 2) := (ENNReal.ofReal_lt_ofReal_iff (by norm_num)).2 (by norm_num) + _ = volume L0 := vol_L0.symm + _ ≤ volume (convexHull ℝ (latticeDisk c0 ((7 : ℕ) : ℝ))) := measure_mono L0_subset + have hle : maxArea c0 ((7 : ℕ) : ℝ) ≤ ⨆ c, maxArea c ((7 : ℕ) : ℝ) := + le_iSup (fun c => maxArea c ((7 : ℕ) : ℝ)) c0 + rw [h7] at hle + exact absurd hle (not_le.2 hlt) + +end Math0.Frontier.A386538 + +#math0_settles Math0.Frontier.A386538.result Math0.Statements.A386538.statement diff --git a/lean/Math0/Frontier/OEIS/A386655.lean b/lean/Math0/Frontier/OEIS/A386655.lean new file mode 100644 index 0000000..3122438 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A386655.lean @@ -0,0 +1,271 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A386655 +import Math0.Audit + +/-! +# A386655 modulo 6 is eventually periodic with pattern `[1, 0, 3, 0, 3, 2]` + +We prove Paul D. Hanna's conjecture: for `n ≥ 6`, +`a(n) = ∑_{k ≤ n} C(n,k) 2^(k(k+1)) (2^k - (n-k))^(n-k-1)` (the `k = n` term being `2^(n²)`) +satisfies `a(n) mod 6 = [1, 0, 3, 0, 3, 2][(n - 6) mod 6]`. + +**Modulo 2.** Every term with `k ≥ 1` contains the factor `2^(k(k+1))` (or `2^(n²)`), so +`a(n) ≡ (1 - n)^(n-1) ≡ n + 1 (mod 2)` for `n ≥ 2`. + +**Modulo 3.** Put `m = n - k`. As `2 ≡ -1` and `k(k+1)` is even, the term with index `m ≥ 1` is +`C(n,m) (s - m)^(m-1)` with `s = (-1)^(n-m) = (-1)^n (-1)^m`, and the term `m = 0` is +`(-1)^n`. By Fermat (`x^3 = x` in `ZMod 3`), `(s - m)^(m-1)` depends only on `m mod 6` for +`m ≥ 2`; any function of `m mod 6` with values in `ZMod 3` can be written as +`α(m) + (-1)^m β(m)` with `α, β ∈ span{1, m, C(m,2)}`, and we find explicitly +* `n` even: `α = 1 + m + C(m,2)`, `β = m - C(m,2)` (valid for all `m ≥ 0`); +* `n` odd: `α = -m + C(m,2)`, `β = -1 - C(m,2)` (valid for all `m ≠ 1`; at `m = 1` the true + value exceeds it by `1`, contributing a correction `C(n,1) = n`). +Then `∑_m C(n,m) C(m,j) x^m = C(n,j) x^j (1+x)^(n-j)` kills the `(-1)^m` part for `n ≥ 3` +and gives `a(n) ≡ 2^n + n 2^(n-1) + C(n,2) 2^(n-2)` (`n` even), resp. +`a(n) ≡ -n 2^(n-1) + C(n,2) 2^(n-2) + n` (`n` odd), modulo 3. Since `2^2 ≡ 1` and +`C(n,2) ≡ n - n²`, these depend only on `n mod 6` and equal `[1, 0, 0, 0, 0, 2][n mod 6]`. +Combining with the parity gives the claimed residues modulo 6. +-/ + +namespace Math0.Frontier.A386655 +open Math0.Statements.A386655 + +/-- Fermat's little theorem in `ZMod 3`. -/ +private lemma pow3 : ∀ x : ZMod 3, x ^ 3 = x := by decide + +/-- In `ZMod 3`, a positive power only depends on the parity of the exponent. -/ +private lemma pow_red (x : ZMod 3) : ∀ e : ℕ, x ^ (e + 1) = x ^ (e % 2 + 1) + | 0 => rfl + | 1 => rfl + | e + 2 => by + have h : x ^ (e + 2 + 1) = x ^ (e + 1) := by + rw [show e + 2 + 1 = e + 3 by omega, pow_add, pow3, pow_succ] + rw [h, pow_red x e, show (e + 2) % 2 = e % 2 by omega] + +/-- `C(m,2) ≡ m - m² (mod 3)`. -/ +private lemma choose2 : ∀ m : ℕ, ((m.choose 2 : ℕ) : ZMod 3) = (m : ZMod 3) - (m : ZMod 3) ^ 2 + | 0 => by simp + | m + 1 => by + have h3 : (3 : ZMod 3) = 0 := by decide + rw [Nat.choose_succ_succ', Nat.cast_add, choose2 m, Nat.choose_one_right] + push_cast + linear_combination (m : ZMod 3) * h3 + +/-- The function `c0 + c1 m + c2 C(m,2)` with values in `ZMod 3`. -/ +private def lin (c0 c1 c2 : ZMod 3) (m : ℕ) : ZMod 3 := c0 + c1 * m + c2 * (m.choose 2 : ZMod 3) + +/-- The reduced term `((-1)^m - m)^(m-1)` (case `n` even) as `α(m) + (-1)^m β(m)`. -/ +private lemma coreE (m : ℕ) (hm : 2 ≤ m) : + ((-1 : ZMod 3) ^ m - m) ^ (m - 1) = lin 1 1 1 m + (-1) ^ m * lin 0 1 (-1) m := by + rw [show m - 1 = (m - 2) + 1 by omega, pow_red _ (m - 2)] + unfold lin + rw [choose2, neg_one_pow_eq_pow_mod_two (R := ZMod 3) m, ← ZMod.natCast_mod m 3, + show (m - 2) % 2 = m % 6 % 2 by omega, show m % 2 = m % 6 % 2 by omega, + show m % 3 = m % 6 % 3 by omega] + have h6 : m % 6 < 6 := Nat.mod_lt _ (by norm_num) + generalize m % 6 = r at h6 ⊢ + interval_cases r <;> decide + +/-- The reduced term `(-(-1)^m - m)^(m-1)` (case `n` odd) as `α(m) + (-1)^m β(m)`. -/ +private lemma coreO (m : ℕ) (hm : 2 ≤ m) : + ((-1) * (-1 : ZMod 3) ^ m - m) ^ (m - 1) = lin 0 (-1) 1 m + (-1) ^ m * lin (-1) 0 (-1) m := by + rw [show m - 1 = (m - 2) + 1 by omega, pow_red _ (m - 2)] + unfold lin + rw [choose2, neg_one_pow_eq_pow_mod_two (R := ZMod 3) m, ← ZMod.natCast_mod m 3, + show (m - 2) % 2 = m % 6 % 2 by omega, show m % 2 = m % 6 % 2 by omega, + show m % 3 = m % 6 % 3 by omega] + have h6 : m % 6 < 6 := Nat.mod_lt _ (by norm_num) + generalize m % 6 = r at h6 ⊢ + interval_cases r <;> decide + +/-- `∑_m C(j+p,m) C(m,j) x^m = C(j+p,j) x^j (x+1)^p`. -/ +private lemma sum_choose_choose {R : Type*} [CommRing R] (j p : ℕ) (x : R) : + ∑ m ∈ Finset.range (j + p + 1), ((j + p).choose m : R) * (m.choose j : R) * x ^ m = + ((j + p).choose j : R) * x ^ j * (x + 1) ^ p := by + rw [show j + p + 1 = j + (p + 1) by omega, Finset.sum_range_add] + have h0 : ∑ m ∈ Finset.range j, ((j + p).choose m : R) * (m.choose j : R) * x ^ m = 0 := + Finset.sum_eq_zero fun m hm => by + rw [Nat.choose_eq_zero_of_lt (Finset.mem_range.1 hm)]; simp + rw [h0, zero_add, add_pow, Finset.mul_sum] + refine Finset.sum_congr rfl fun i _ => ?_ + have h := Nat.choose_mul (n := j + p) (k := j + i) (s := j) (Nat.le_add_right j i) + rw [show j + p - j = p by omega, show j + i - j = i by omega] at h + rw [← Nat.cast_mul, h, Nat.cast_mul, one_pow, mul_one, pow_add] + ring + +/-- `∑_m C(n,m) C(m,j) x^m = C(n,j) x^j (x+1)^(n-j)` for `j ≤ n`. -/ +private lemma sum_choose_choose' {R : Type*} [CommRing R] (n j : ℕ) (hj : j ≤ n) (x : R) : + ∑ m ∈ Finset.range (n + 1), (n.choose m : R) * (m.choose j : R) * x ^ m = + (n.choose j : R) * x ^ j * (x + 1) ^ (n - j) := by + obtain ⟨p, rfl⟩ := Nat.exists_eq_add_of_le hj + rw [sum_choose_choose, Nat.add_sub_cancel_left] + +/-- Binomial transform of `α(m) + (-1)^m β(m)` in `ZMod 3`; the `β` part vanishes for `n ≥ 3`. -/ +private lemma sum_lin (n : ℕ) (hn : 3 ≤ n) (c0 c1 c2 d0 d1 d2 : ZMod 3) : + ∑ m ∈ Finset.range (n + 1), + (n.choose m : ZMod 3) * (lin c0 c1 c2 m + (-1) ^ m * lin d0 d1 d2 m) = + c0 * 2 ^ n + c1 * n * 2 ^ (n - 1) + c2 * n.choose 2 * 2 ^ (n - 2) := by + have e : ∀ m : ℕ, (n.choose m : ZMod 3) * (lin c0 c1 c2 m + (-1) ^ m * lin d0 d1 d2 m) = + c0 * ((n.choose m : ZMod 3) * (m.choose 0 : ZMod 3) * 1 ^ m) + + c1 * ((n.choose m : ZMod 3) * (m.choose 1 : ZMod 3) * 1 ^ m) + + c2 * ((n.choose m : ZMod 3) * (m.choose 2 : ZMod 3) * 1 ^ m) + + (d0 * ((n.choose m : ZMod 3) * (m.choose 0 : ZMod 3) * (-1) ^ m) + + d1 * ((n.choose m : ZMod 3) * (m.choose 1 : ZMod 3) * (-1) ^ m) + + d2 * ((n.choose m : ZMod 3) * (m.choose 2 : ZMod 3) * (-1) ^ m)) := by + intro m + simp only [lin, Nat.choose_zero_right, Nat.choose_one_right, Nat.cast_one, one_pow] + ring + rw [Finset.sum_congr rfl fun m _ => e m] + simp only [Finset.sum_add_distrib, ← Finset.mul_sum] + rw [sum_choose_choose' n 0 (by omega) (1 : ZMod 3), sum_choose_choose' n 1 (by omega) (1 : ZMod 3), + sum_choose_choose' n 2 (by omega) (1 : ZMod 3), sum_choose_choose' n 0 (by omega) (-1 : ZMod 3), + sum_choose_choose' n 1 (by omega) (-1 : ZMod 3), sum_choose_choose' n 2 (by omega) (-1 : ZMod 3)] + simp only [neg_add_cancel, zero_pow (show n ≠ 0 by omega), zero_pow (show n - 1 ≠ 0 by omega), + zero_pow (show n - 2 ≠ 0 by omega), Nat.choose_zero_right, Nat.choose_one_right, + Nat.sub_zero, one_pow, one_add_one_eq_two] + ring + +/-- `2^(k(k+1)) ≡ 1 (mod 3)`. -/ +private lemma two_pow_mul_succ (k : ℕ) : (2 : ZMod 3) ^ (k * (k + 1)) = 1 := by + obtain ⟨t, ht⟩ := Nat.even_mul_succ_self k + rw [ht, ← two_mul, pow_mul, show (2 : ZMod 3) ^ 2 = 1 by decide, one_pow] + +/-- `(-1)^(n-m) = (-1)^n (-1)^m` for `m ≤ n`. -/ +private lemma neg_one_pow_sub' (n m : ℕ) (h : m ≤ n) : + (-1 : ZMod 3) ^ (n - m) = (-1) ^ n * (-1) ^ m := by + have e : (-1 : ZMod 3) ^ (n - m) * (-1) ^ m = (-1) ^ n := by + rw [← pow_add, Nat.sub_add_cancel h] + rw [← e, mul_assoc, ← pow_add, ← two_mul, pow_mul, neg_one_sq, one_pow, mul_one] + +/-- The summand with `k = n - m`, `1 ≤ m ≤ n`, modulo 3. -/ +private lemma term_cast (n m : ℕ) (h1 : 1 ≤ m) (h : m ≤ n) : + ((term n (n - m) : ℤ) : ZMod 3) = + (n.choose m : ZMod 3) * ((-1) ^ n * (-1) ^ m - m) ^ (m - 1) := by + have hne : n - m ≠ n := by omega + have hk : n - (n - m) = m := by omega + simp only [term, if_neg hne, hk, binom_eq_choose, Nat.choose_symm h] + push_cast + rw [two_pow_mul_succ, show (2 : ZMod 3) = -1 by decide, neg_one_pow_sub' n m h, mul_one] + +/-- The summand with `k = n` is `2^(n²) ≡ (-1)^n (mod 3)`. -/ +private lemma term_cast_self (n : ℕ) : ((term n n : ℤ) : ZMod 3) = (-1) ^ n := by + simp only [term] + push_cast + rw [show (2 : ZMod 3) = -1 by decide, pow_mul] + rcases Nat.even_or_odd n with he | ho + · rw [he.neg_one_pow, one_pow] + · rw [ho.neg_one_pow, ho.neg_one_pow] + +/-- Reindex the defining sum by `m = n - k`. -/ +private lemma a_reflect (n : ℕ) : + ((a n : ℤ) : ZMod 3) = ∑ m ∈ Finset.range (n + 1), ((term n (n - m) : ℤ) : ZMod 3) := by + unfold a + push_cast + rw [← Finset.sum_range_reflect] + refine Finset.sum_congr rfl fun m _ => ?_ + rw [show n + 1 - 1 - m = n - m by omega] + +/-- Closed form of `a(n)` modulo 3 for even `n ≥ 3`. -/ +private lemma a_mod3_even (n : ℕ) (hn : 3 ≤ n) (he : Even n) : + ((a n : ℤ) : ZMod 3) = 1 * 2 ^ n + 1 * n * 2 ^ (n - 1) + 1 * n.choose 2 * 2 ^ (n - 2) := by + rw [← sum_lin n hn 1 1 1 0 1 (-1), a_reflect] + refine Finset.sum_congr rfl fun m hm => ?_ + have hm' : m ≤ n := Nat.lt_succ_iff.mp (Finset.mem_range.mp hm) + rcases Nat.lt_or_ge m 2 with h | h + · interval_cases m + · rw [Nat.sub_zero, term_cast_self, he.neg_one_pow] + simp [lin] + · rw [term_cast n 1 le_rfl hm', Nat.sub_self, pow_zero, mul_one] + have : lin 1 1 1 1 + (-1) ^ 1 * lin 0 1 (-1) 1 = 1 := by decide + rw [this, mul_one] + · rw [term_cast n m (by omega) hm', he.neg_one_pow, one_mul, coreE m h] + +/-- Closed form of `a(n)` modulo 3 for odd `n ≥ 3`. -/ +private lemma a_mod3_odd (n : ℕ) (hn : 3 ≤ n) (ho : Odd n) : + ((a n : ℤ) : ZMod 3) = + 0 * 2 ^ n + (-1) * n * 2 ^ (n - 1) + 1 * n.choose 2 * 2 ^ (n - 2) + n := by + rw [← sum_lin n hn 0 (-1) 1 (-1) 0 (-1), a_reflect] + have h1 : (n : ZMod 3) = ∑ m ∈ Finset.range (n + 1), if m = 1 then (n : ZMod 3) else 0 := by + rw [Finset.sum_ite_eq', if_pos (Finset.mem_range.mpr (by omega))] + rw [h1, ← Finset.sum_add_distrib] + refine Finset.sum_congr rfl fun m hm => ?_ + have hm' : m ≤ n := Nat.lt_succ_iff.mp (Finset.mem_range.mp hm) + rcases Nat.lt_or_ge m 2 with h | h + · interval_cases m + · rw [Nat.sub_zero, term_cast_self, ho.neg_one_pow] + simp [lin] + · rw [term_cast n 1 le_rfl hm', Nat.sub_self, pow_zero, mul_one, if_pos rfl, + Nat.choose_one_right] + have : lin 0 (-1) 1 1 + (-1) ^ 1 * lin (-1) 0 (-1) 1 = 0 := by decide + rw [this, mul_zero, zero_add] + · rw [term_cast n m (by omega) hm', ho.neg_one_pow, coreO m h, if_neg (by omega), add_zero] + +/-- For `n ≥ 6`, `a(n) mod 3` is `[1, 0, 0, 0, 0, 2][n mod 6]`. -/ +private lemma a_mod3 (n : ℕ) (hn : 6 ≤ n) : + ((a n : ℤ) : ZMod 3) = ((([1, 0, 0, 0, 0, 2] : List ℤ).getD (n % 6) 0 : ℤ) : ZMod 3) := by + have h2 : (2 : ZMod 3) ^ 2 = 1 := by decide + have h6 : n % 6 < 6 := Nat.mod_lt _ (by norm_num) + rcases Nat.even_or_odd n with he | ho + · have hp : n % 6 % 2 = 0 := by have := Nat.even_iff.mp he; omega + rw [a_mod3_even n (by omega) he, choose2, pow_eq_pow_mod n h2, pow_eq_pow_mod (n - 1) h2, + pow_eq_pow_mod (n - 2) h2, ← ZMod.natCast_mod n 3, + show (n - 1) % 2 = (n % 6 + 1) % 2 by omega, show (n - 2) % 2 = n % 6 % 2 by omega, + show n % 2 = n % 6 % 2 by omega, show n % 3 = n % 6 % 3 by omega] + generalize n % 6 = r at h6 hp ⊢ + interval_cases r <;> first | decide | omega + · have hp : n % 6 % 2 = 1 := by have := Nat.odd_iff.mp ho; omega + rw [a_mod3_odd n (by omega) ho, choose2, pow_eq_pow_mod n h2, pow_eq_pow_mod (n - 1) h2, + pow_eq_pow_mod (n - 2) h2, ← ZMod.natCast_mod n 3, + show (n - 1) % 2 = (n % 6 + 1) % 2 by omega, show (n - 2) % 2 = n % 6 % 2 by omega, + show n % 2 = n % 6 % 2 by omega, show n % 3 = n % 6 % 3 by omega] + generalize n % 6 = r at h6 hp ⊢ + interval_cases r <;> first | decide | omega + +/-- In `ZMod 2`, every positive power of `x` is `x`. -/ +private lemma pow_zmod2 (x : ZMod 2) : ∀ e : ℕ, x ^ (e + 1) = x + | 0 => pow_one x + | e + 1 => by + rw [pow_succ, pow_zmod2 x e] + revert x + decide + +/-- For `n ≥ 2`, `a(n) ≡ n + 1 (mod 2)`: every term with `k ≥ 1` is even. -/ +private lemma a_mod2 (n : ℕ) (hn : 2 ≤ n) : + ((a n : ℤ) : ZMod 2) = (((n : ℤ) + 1 : ℤ) : ZMod 2) := by + unfold a + push_cast + rw [Finset.sum_eq_single 0] + · simp only [term, if_neg (show (0 : ℕ) ≠ n by omega), binom_eq_choose, Nat.choose_zero_right, + Nat.sub_zero] + push_cast + rw [show n - 1 = (n - 2) + 1 by omega, pow_zmod2, sub_eq_add_neg, ZMod.neg_eq_self_mod_two, + add_comm, one_mul] + · intro k _ hk0 + unfold term + split_ifs with h + · push_cast + rw [show (2 : ZMod 2) = 0 by decide, zero_pow (by positivity)] + · push_cast + rw [show (2 : ZMod 2) = 0 by decide, zero_pow (show k * (k + 1) ≠ 0 by positivity)] + simp + · intro h + exact absurd (Finset.mem_range.mpr (by omega)) h + +/-- Hanna's conjecture for A386655: for `n ≥ 6`, `a(n) mod 6` runs through +`[1, 0, 3, 0, 3, 2]` periodically, starting at `n = 6`. -/ +theorem result : statement := by + intro n hn + have h3 := a_mod3 n hn + have h2 := a_mod2 n (by omega) + rw [ZMod.intCast_eq_intCast_iff'] at h3 h2 + push_cast at h3 h2 + rw [show (n - 6) % 6 = n % 6 by omega] + have h6 : n % 6 < 6 := Nat.mod_lt _ (by norm_num) + generalize hr : n % 6 = r at h3 h6 ⊢ + interval_cases r <;> simp only [List.getD_cons_zero, List.getD_cons_succ] at h3 ⊢ <;> omega + +end Math0.Frontier.A386655 + +#math0_settles Math0.Frontier.A386655.result Math0.Statements.A386655.statement diff --git a/lean/Math0/Frontier/OEIS/A388724.lean b/lean/Math0/Frontier/OEIS/A388724.lean new file mode 100644 index 0000000..83a5156 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A388724.lean @@ -0,0 +1,365 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A388724 +import Math0.Audit + +/-! +# Column sums of strictly superdiagonal reversed partitions are A000245 + +We prove Gus Wiseman's conjecture for A388724: for every `k ≥ 1`, the number of strictly +superdiagonal reversed partitions (of any size) with maximum `k` is `A000245(k-1)`. + +**Idea.** Summing `T(n,k)` over `n` just counts the lists `y = (y_1 ≤ … ≤ y_m)` with `y_i > i` +and maximum `k` (`colSum_card`). Let `N k lo` count the weakly increasing lists with `y_i > i` +and all entries in `[lo, k]` (empty list included). Splitting off the first entry `j` and +subtracting `1` from the remaining entries gives `N (k+1) lo = 1 + ∑_{j = max lo 2}^{k+1} N k (j-1)` +(this is the enumeration `enum`, shown complete and duplicate-free in `mem_enum`, `nodup_enum`), +hence the Pascal-type recursion `N (k+1) lo = N (k+1) (lo+1) + N k (lo-1)` for `2 ≤ lo ≤ k+1`, +together with `N (k+1) lo = 1` for `lo ≥ k+2` and `N k 0 = N k 1 = N k 2`. In the indexing +`A k s = N k (k+1-s)` this is the Catalan triangle, and induction gives the ballot formula +`A n (m+1) = C(n+m+1, m+1) - C(n+m+1, m)` for `m < n` (`A_closed`; on the diagonal one uses +`A (n+1) (n+1) = A (n+1) n` and `C(2m+1, m+1) = C(2m+1, m)`). + +The lists with maximum `k + 1` are the lists with entries `≤ k + 1` minus those with entries +`≤ k`, so the column sum is `N (K+1) 0 - N K 0 = N (K+1) 3 = A (K+1) (K-1)` (`K = k - 1 ≥ 1`; +the column `k = 1` is empty). For `K = j + 2` this is `C(2j+4, j+1) - C(2j+4, j)`, and multiplying +by `(j+4)! (j+1)!` gives `(j+4)·(2j+4)! - (j+1)·(2j+4)! = 3·(2j+4)!`, which is the defining +formula `A000245(K) = 3 (2K)! / ((K+2)! (K-1)!)`; `K = 1` gives `1 = A000245(1)`. +-/ + +namespace Math0.Frontier.A388724 +open Math0.Statements.A388724 Finset + +/-- `SD c y`: the `i`-th entry (0-indexed) of `y` exceeds `i + c`. -/ +private def SD : ℕ → List ℕ → Prop + | _, [] => True + | c, x :: t => c < x ∧ SD (c + 1) t + +/-- `SD c y` in terms of indices. -/ +private theorem SD_iff : ∀ (c : ℕ) (y : List ℕ), SD c y ↔ ∀ i (h : i < y.length), i + c < y[i] + | c, [] => by simp [SD] + | c, x :: t => by + rw [SD, SD_iff (c + 1) t] + constructor + · rintro ⟨h0, h1⟩ i hi + cases i with + | zero => simpa using h0 + | succ i => + have := h1 i (by simpa using hi) + simp only [List.getElem_cons_succ] + omega + · intro h + have h0 := h 0 (by simp) + rw [List.getElem_cons_zero] at h0 + refine ⟨by omega, fun i hi => ?_⟩ + have := h (i + 1) (by simp; omega) + simp only [List.getElem_cons_succ] at this + omega + +/-- Shifting all entries up by one shifts the bound up by one. -/ +private theorem SD_map : ∀ (c : ℕ) (t : List ℕ), SD (c + 1) (t.map (· + 1)) ↔ SD c t + | c, [] => by simp [SD] + | c, x :: t => by + simp only [List.map_cons, SD] + exact and_congr (by omega) (SD_map (c + 1) t) + +/-- `Good lo k y`: `y` is weakly increasing, strictly superdiagonal, with entries in `[lo, k]`. -/ +private def Good (lo k : ℕ) (y : List ℕ) : Prop := + y.Pairwise (· ≤ ·) ∧ SD 1 y ∧ ∀ x ∈ y, lo ≤ x ∧ x ≤ k + +/-- Enumeration of the lists `y` with `Good lo k y`: either `y = []`, or `y = j :: (t + 1)` with +`max lo 2 ≤ j ≤ k` and `Good (j - 1) (k - 1) t`. -/ +private def enum : ℕ → ℕ → List (List ℕ) + | 0, _ => [[]] + | k + 1, lo => [] :: (List.range' (max lo 2) (k + 2 - max lo 2)).flatMap + fun j => (enum k (j - 1)).map fun t => j :: t.map (· + 1) + +/-- Subtracting then adding one is the identity on lists of positive numbers. -/ +private theorem map_sub_add : ∀ s : List ℕ, (∀ a ∈ s, 1 ≤ a) → (s.map (· - 1)).map (· + 1) = s + | [], _ => rfl + | a :: s, h => by + simp only [List.map_cons, List.cons.injEq] + exact ⟨by have := h a List.mem_cons_self; omega, + map_sub_add s fun b hb => h b (List.mem_cons_of_mem a hb)⟩ + +/-- `enum k lo` lists exactly the lists `y` with `Good lo k y`. -/ +private theorem mem_enum : ∀ (k lo : ℕ) (y : List ℕ), y ∈ enum k lo ↔ Good lo k y + | 0, lo, y => by + simp only [enum, List.mem_singleton] + constructor + · rintro rfl + simp [Good, SD] + · rintro ⟨-, hsd, hb⟩ + cases y with + | nil => rfl + | cons x t => + have := (hb x List.mem_cons_self).2 + simp only [SD] at hsd + omega + | k + 1, lo, y => by + cases y with + | nil => simp [enum, Good, SD] + | cons x s => + simp only [enum, List.mem_cons, reduceCtorEq, false_or, List.mem_flatMap, + List.mem_range'_1, List.mem_map, List.cons.injEq] + constructor + · rintro ⟨j, ⟨hj1, hj2⟩, t, ht, rfl, rfl⟩ + rw [mem_enum k (j - 1) t] at ht + obtain ⟨ht1, ht2, ht3⟩ := ht + refine ⟨?_, ?_, ?_⟩ + · rw [List.pairwise_cons, List.pairwise_map] + refine ⟨?_, ht1.imp fun h => by omega⟩ + intro a ha + rw [List.mem_map] at ha + obtain ⟨b, hb, rfl⟩ := ha + have := (ht3 b hb).1 + omega + · exact ⟨by omega, (SD_map 1 t).2 ht2⟩ + · intro a ha + rw [List.mem_cons, List.mem_map] at ha + rcases ha with rfl | ⟨b, hb, rfl⟩ + · omega + · have := ht3 b hb + omega + · rintro ⟨hp, hsd, hb⟩ + rw [List.pairwise_cons] at hp + simp only [SD] at hsd + have hx := hb x List.mem_cons_self + have hs1 : ∀ a ∈ s, 1 ≤ a := fun a ha => by have := hp.1 a ha; omega + refine ⟨x, ⟨by omega, by omega⟩, s.map (· - 1), ?_, rfl, map_sub_add s hs1⟩ + rw [mem_enum k (x - 1)] + refine ⟨?_, ?_, ?_⟩ + · rw [List.pairwise_map] + exact hp.2.imp fun h => by omega + · rw [← SD_map 1, map_sub_add s hs1] + exact hsd.2 + · intro a ha + rw [List.mem_map] at ha + obtain ⟨b, hb', rfl⟩ := ha + have h1 := hp.1 b hb' + have h2 := hb b (List.mem_cons_of_mem x hb') + omega + +/-- `enum k lo` has no repetitions. -/ +private theorem nodup_enum : ∀ (k lo : ℕ), (enum k lo).Nodup + | 0, lo => by simp [enum] + | k + 1, lo => by + rw [enum, List.nodup_cons] + refine ⟨by simp, ?_⟩ + rw [List.nodup_flatMap] + refine ⟨fun j _ => (nodup_enum k (j - 1)).map ?_, ?_⟩ + · intro t1 t2 h + simp only [List.cons.injEq, true_and] at h + exact (List.map_injective_iff.2 (add_left_injective 1)) h + · refine (List.nodup_range' (s := max lo 2) (n := k + 2 - max lo 2)).imp fun {i j} hij => ?_ + intro y hy1 hy2 + simp only [List.mem_map] at hy1 hy2 + obtain ⟨t, -, rfl⟩ := hy1 + obtain ⟨t', -, h⟩ := hy2 + exact hij (List.cons.inj h).1.symm + +/-- The number of lists `y` with `Good lo k y`. -/ +private def N (k lo : ℕ) : ℕ := (enum k lo).length + +/-- The defining recursion of `N`, from the shape of `enum`. -/ +private theorem N_succ (k lo : ℕ) : N (k + 1) lo = + 1 + ((List.range' (max lo 2) (k + 2 - max lo 2)).map fun j => N k (j - 1)).sum := by + simp only [N, enum, List.length_cons, List.length_flatMap, List.length_map] + omega + +/-- Lower bounds `lo ≤ 2` are all equivalent (the first entry is at least `2` anyway). -/ +private theorem N_low (k lo : ℕ) (h : lo ≤ 2) : N (k + 1) lo = N (k + 1) 2 := by + rw [N_succ, N_succ, max_eq_right h, max_self] + +/-- `N k 1 = N k 0`. -/ +private theorem N_one (k : ℕ) : N k 1 = N k 0 := by + cases k with + | zero => rfl + | succ k => rw [N_low k 1 (by norm_num), N_low k 0 (by norm_num)] + +/-- With lower bound above the upper bound only the empty list remains. -/ +private theorem N_top (k lo : ℕ) (h : k + 2 ≤ lo) : N (k + 1) lo = 1 := by + rw [N_succ, show k + 2 - max lo 2 = 0 by omega] + simp + +/-- Pascal-type recursion: either the first entry is `lo`, or all entries are `≥ lo + 1`. -/ +private theorem N_rec (k lo : ℕ) (h1 : 2 ≤ lo) (h2 : lo ≤ k + 1) : + N (k + 1) lo = N (k + 1) (lo + 1) + N k (lo - 1) := by + rw [N_succ, N_succ, max_eq_left h1, max_eq_left (by omega : 2 ≤ lo + 1), + show k + 2 - lo = (k + 2 - (lo + 1)) + 1 by omega, List.range'_succ] + simp only [List.map_cons, List.sum_cons] + omega + +/-- The Catalan-triangle indexing `A k s = N k (k + 1 - s)`. -/ +private def A (k s : ℕ) : ℕ := N k (k + 1 - s) + +/-- The first column of the triangle is `1`. -/ +private theorem A_zero (k : ℕ) : A k 0 = 1 := by + cases k with + | zero => rfl + | succ k => exact N_top k _ (by omega) + +/-- Pascal recursion of the Catalan triangle. -/ +private theorem A_rec (k s : ℕ) (h : s + 1 ≤ k) : + A (k + 1) (s + 1) = A (k + 1) s + A k (s + 1) := by + have := N_rec k (k + 1 - s) (by omega) (by omega) + rw [show k + 1 - s + 1 = k + 1 + 1 - s by omega, show k + 1 - s - 1 = k + 1 - (s + 1) by omega] + at this + simpa [A, show k + 1 + 1 - (s + 1) = k + 1 - s by omega] using this + +/-- The diagonal equals the subdiagonal. -/ +private theorem A_diag (k : ℕ) : A (k + 1) (k + 1) = A (k + 1) k := by + simp only [A, show k + 1 + 1 - (k + 1) = 1 by omega, show k + 1 + 1 - k = 2 by omega] + exact N_low k 1 (by norm_num) + +/-- Closed form of the Catalan triangle: `A n (m+1) = C(n+m+1, m+1) - C(n+m+1, m)`. -/ +private theorem A_closed (n : ℕ) : + ∀ m, m + 1 ≤ n → A n (m + 1) + (n + m + 1).choose m = (n + m + 1).choose (m + 1) := by + induction n with + | zero => intro m h; omega + | succ n ih => + intro m + induction m with + | zero => + intro _ + rcases Nat.eq_zero_or_pos n with rfl | hn + · rw [A_diag 0, A_zero] + simp + · rw [A_rec n 0 (by omega), A_zero] + have := ih 0 (by omega) + simp only [Nat.add_zero, Nat.zero_add, Nat.choose_zero_right, Nat.choose_one_right] + at this ⊢ + omega + | succ m ihm => + intro hm + rcases Nat.lt_or_ge (m + 1) n with hlt | hge + · have e1 : A (n + 1) (m + 1) + (n + m + 2).choose m = (n + m + 2).choose (m + 1) := by + have := ihm (by omega) + rwa [show n + 1 + m + 1 = n + m + 2 by ring] at this + have e2 : A n (m + 1 + 1) + (n + m + 2).choose (m + 1) = + (n + m + 2).choose (m + 1 + 1) := by + have := ih (m + 1) (by omega) + rwa [show n + (m + 1) + 1 = n + m + 2 by ring] at this + rw [A_rec n (m + 1) (by omega), show n + 1 + (m + 1) + 1 = n + m + 2 + 1 by ring, + Nat.choose_succ_succ' (n + m + 2) (m + 1), Nat.choose_succ_succ' (n + m + 2) m] + omega + · obtain rfl : n = m + 1 := by omega + have e1 : A (m + 1 + 1) (m + 1) + (2 * (m + 1) + 1).choose m = + (2 * (m + 1) + 1).choose (m + 1) := by + have := ihm (by omega) + rwa [show m + 1 + 1 + m + 1 = 2 * (m + 1) + 1 by ring] at this + rw [A_diag (m + 1), show m + 1 + 1 + (m + 1) + 1 = 2 * (m + 1) + 1 + 1 by ring, + Nat.choose_succ_succ' (2 * (m + 1) + 1) (m + 1), + Nat.choose_succ_succ' (2 * (m + 1) + 1) m, Nat.choose_symm_half (m + 1)] + omega + +/-- `A000245 (j+2)` as a difference of binomials. -/ +private theorem A000245_eq (j x : ℕ) + (hx : x + (2 * j + 4).choose j = (2 * j + 4).choose (j + 1)) : + A000245 (j + 2) = x := by + have h1 := Nat.choose_mul_factorial_mul_factorial (n := 2 * j + 4) (k := j + 1) (by omega) + have h0 := Nat.choose_mul_factorial_mul_factorial (n := 2 * j + 4) (k := j) (by omega) + rw [show 2 * j + 4 - (j + 1) = j + 3 by omega] at h1 + rw [show 2 * j + 4 - j = j + 4 by omega] at h0 + have key : 3 * (2 * (j + 2)).factorial = x * ((j + 2 + 2).factorial * (j + 2 - 1).factorial) := by + rw [show 2 * (j + 2) = 2 * j + 4 by ring, show j + 2 + 2 = (j + 3) + 1 by ring, + show j + 2 - 1 = j + 1 by omega, Nat.factorial_succ (j + 3), Nat.factorial_succ j] + rw [show j + 4 = (j + 3) + 1 by ring, Nat.factorial_succ (j + 3)] at h0 + rw [Nat.factorial_succ j] at h1 + have hx' : (x : ℤ) = ((2 * j + 4).choose (j + 1) : ℤ) - ((2 * j + 4).choose j : ℤ) := by + rw [← hx]; push_cast; ring + have h1' : ((2 * j + 4).choose (j + 1) : ℤ) * ((j + 1) * j.factorial) * (j + 3).factorial = + (2 * j + 4).factorial := by exact_mod_cast h1 + have h0' : ((2 * j + 4).choose j : ℤ) * j.factorial * ((j + 3 + 1) * (j + 3).factorial) = + (2 * j + 4).factorial := by exact_mod_cast h0 + have : (3 * (2 * j + 4).factorial : ℤ) = + x * ((j + 3 + 1) * (j + 3).factorial * ((j + 1) * j.factorial)) := by + rw [hx'] + linear_combination (j + 1 : ℤ) * h0' - (j + 4 : ℤ) * h1' + exact_mod_cast this + rw [A000245, if_neg (by omega), key, Nat.mul_div_cancel _ (by positivity)] + +/-- The column sum, as the number of good lists with maximum `k`. -/ +private theorem colSum_card (k : ℕ) : + ∑ᶠ n, T n k = #{y ∈ (enum k 0).toFinset | k ∈ y} := by + have hT : ∀ n, T n k = #{y ∈ {y ∈ (enum k 0).toFinset | k ∈ y} | y.sum = n} := by + intro n + rw [T, ← Set.ncard_coe_finset] + congr 1 + ext y + rw [Set.mem_ofPred_eq, Finset.mem_coe, Finset.mem_filter, Finset.mem_filter, + List.mem_toFinset, mem_enum] + simp only [Good, IsRevPartition, StrictlySuperdiagonal, List.max?_eq_some_iff, ← SD_iff 1 y] + constructor + · rintro ⟨⟨-, hp, hs⟩, hsd, hk, hle⟩ + exact ⟨⟨⟨hp, hsd, fun x hx => ⟨Nat.zero_le _, hle x hx⟩⟩, hk⟩, hs⟩ + · rintro ⟨⟨⟨hp, hsd, hb⟩, hk⟩, hs⟩ + refine ⟨⟨fun x hx => ?_, hp, hs⟩, hsd, hk, fun x hx => (hb x hx).2⟩ + obtain ⟨i, hi, rfl⟩ := List.mem_iff_getElem.1 hx + have := (SD_iff 1 y).1 hsd i hi + omega + simp_rw [hT] + rw [finsum_eq_sum_of_support_subset (s := {y ∈ (enum k 0).toFinset | k ∈ y}.image List.sum), + ← card_eq_sum_card_image] + intro n hn + rw [Function.mem_support] at hn + obtain ⟨y, hy⟩ := Finset.card_ne_zero.1 hn + rw [mem_filter] at hy + simp only [coe_image, Set.mem_image, mem_coe] + exact ⟨y, hy.1, hy.2⟩ + +/-- The good lists with maximum `k + 1` and those with maximum at most `k` make up all good +lists with entries at most `k + 1`. -/ +private theorem card_split (k : ℕ) : + #{y ∈ (enum (k + 1) 0).toFinset | k + 1 ∈ y} + N k 0 = N (k + 1) 0 := by + have hN : ∀ k, N k 0 = #(enum k 0).toFinset := fun k => + (List.toFinset_card_of_nodup (nodup_enum k 0)).symm + have hc : {y ∈ (enum (k + 1) 0).toFinset | ¬ (k + 1 ∈ y)} = (enum k 0).toFinset := by + ext y + simp only [mem_filter, List.mem_toFinset, mem_enum, Good] + constructor + · rintro ⟨⟨hp, hsd, hb⟩, hk⟩ + refine ⟨hp, hsd, fun x hx => ⟨Nat.zero_le _, ?_⟩⟩ + have := (hb x hx).2 + have : x ≠ k + 1 := fun h => hk (h ▸ hx) + omega + · rintro ⟨hp, hsd, hb⟩ + refine ⟨⟨hp, hsd, fun x hx => ⟨Nat.zero_le _, by have := (hb x hx).2; omega⟩⟩, fun hk => ?_⟩ + have := (hb _ hk).2 + omega + rw [hN, hN, ← hc, card_filter_add_card_filter_not] + +/-- The theorem: column sums of A388724 are A000245. -/ +theorem result : statement := by + intro k hk + obtain ⟨K, rfl⟩ : ∃ K, k = K + 1 := ⟨k - 1, by omega⟩ + rw [colSum_card, Nat.add_sub_cancel] + have hs := card_split K + rcases Nat.eq_zero_or_pos K with rfl | hK + · have : N (0 + 1) 0 = 1 := rfl + have h0 : N 0 0 = 1 := rfl + rw [A000245, if_pos rfl] + omega + · rw [N_low K 0 (by norm_num), N_rec K 2 le_rfl (by omega), ← N_one, + show (2 : ℕ) - 1 = 1 from rfl] + at hs + have h3 : #{y ∈ (enum (K + 1) 0).toFinset | K + 1 ∈ y} = A (K + 1) (K - 1) := by + rw [A, show K + 1 + 1 - (K - 1) = 2 + 1 by omega] + omega + rw [h3] + obtain ⟨j, rfl⟩ | rfl : (∃ j, K = j + 2) ∨ K = 1 := by + rcases K with _ | _ | j + · omega + · exact Or.inr rfl + · exact Or.inl ⟨j, by ring⟩ + · rw [show j + 2 - 1 = j + 1 by omega] + refine (A000245_eq j _ ?_).symm + have := A_closed (j + 2 + 1) j (by omega) + rwa [show j + 2 + 1 + j + 1 = 2 * j + 4 by ring] at this + · rw [show 1 - 1 = 0 by rfl, A_zero] + decide + +end Math0.Frontier.A388724 + +#math0_settles Math0.Frontier.A388724.result Math0.Statements.A388724.statement diff --git a/lean/Math0/Frontier/OEIS/A392943.lean b/lean/Math0/Frontier/OEIS/A392943.lean new file mode 100644 index 0000000..0c2fc50 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A392943.lean @@ -0,0 +1,75 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A392943 +import Math0.Audit + +/-! +# No primitive Heronian triangle has integer circumradius + +We prove Felix Huber's conjecture from OEIS A392943: if a triangle has integer sides `x, y, z`, +integer area `K` and integer circumradius `R` (`4 K R = x y z`), then `x`, `y`, `z` are all +even, so `gcd(x, y, z) ≠ 1`. + +Idea: write `P = 16 K²` (Heron) and `D = y² + z² - x²`. Then `P = 4 y² z² - D²`, and squaring +`4 K R = x y z` gives `P R² = x² y² z²`, i.e. `(y z)² (4 R² - x²) = (R D)²`. Hence `(y z)² ∣ (R D)²`, +so `y z ∣ R D`; writing `R D = y z m` and cancelling `(y z)² ≠ 0` gives `x² + m² = 4 R²`. +Squares are `0` or `1` mod `4`, so `x` is even. By symmetry `y` and `z` are even too. +Integrality of the area is only used through `P R² = (x y z)²`. +-/ + +namespace Math0.Frontier.A392943 +open Math0.Statements.A392943 + +/-- If `P(a,b,c) R² = (a b c)²` with `P` the Heron product and `b, c ≠ 0`, then `a` is even. -/ +private theorem two_dvd_of_heron (a b c R : ℤ) (hb : b ≠ 0) (hc : c ≠ 0) + (h : (a + b + c) * (-a + b + c) * (a - b + c) * (a + b - c) * R ^ 2 = (a * b * c) ^ 2) : + 2 ∣ a := by + have h1 : (b * c) ^ 2 * (4 * R ^ 2 - a ^ 2) = (R * (b ^ 2 + c ^ 2 - a ^ 2)) ^ 2 := by + linear_combination h + have hdvd : (b * c) ^ 2 ∣ (R * (b ^ 2 + c ^ 2 - a ^ 2)) ^ 2 := ⟨_, h1.symm⟩ + obtain ⟨m, hm⟩ := (Int.pow_dvd_pow_iff (by norm_num)).1 hdvd + have hbc : (b * c) ^ 2 ≠ 0 := pow_ne_zero _ (mul_ne_zero hb hc) + have h2 : (b * c) ^ 2 * (4 * R ^ 2 - a ^ 2) = (b * c) ^ 2 * m ^ 2 := by + rw [h1, hm]; ring + have h3 : a ^ 2 + m ^ 2 = 4 * R ^ 2 := by + have := mul_left_cancel₀ hbc h2 + linear_combination -this + by_contra hodd + have ha : Odd a := Int.not_even_iff_odd.1 (fun he => hodd (even_iff_two_dvd.1 he)) + have ha2 : a ^ 2 % 4 = 1 := Int.sq_mod_four_eq_one_of_odd ha + have h4 : (a ^ 2 + m ^ 2) % 4 = 0 := by rw [h3]; simp + rcases Int.even_or_odd m with ⟨j, rfl⟩ | hm' + · have hm2 : (j + j) ^ 2 = 4 * (j ^ 2) := by ring + rw [hm2] at h4 + omega + · have hm2 : m ^ 2 % 4 = 1 := Int.sq_mod_four_eq_one_of_odd hm' + omega + +/-- Every primitive Heronian triangle has non-integer circumradius: if `4 K R = x y z` for a +triangle with integer sides `x, y, z` and integer area `K`, then `2 ∣ gcd(x, y, z)`. -/ +theorem result : statement := by + intro x y z K R htri hK hgcd hR + obtain ⟨hx, hy, hz, -, -, -⟩ := htri + rw [HasArea, heron16] at hK + have hRz : ((4 * K * R : ℕ) : ℤ) = ((x * y * z : ℕ) : ℤ) := by rw [hR] + push_cast at hRz + have key : ((x : ℤ) + y + z) * (-x + y + z) * (x - y + z) * (x + y - z) * (R : ℤ) ^ 2 = + ((x : ℤ) * y * z) ^ 2 := by + rw [← hK, ← hRz]; ring + have hx0 : (x : ℤ) ≠ 0 := by exact_mod_cast hx.ne' + have hy0 : (y : ℤ) ≠ 0 := by exact_mod_cast hy.ne' + have hz0 : (z : ℤ) ≠ 0 := by exact_mod_cast hz.ne' + have h2x : (2 : ℤ) ∣ x := two_dvd_of_heron x y z R hy0 hz0 key + have h2y : (2 : ℤ) ∣ y := two_dvd_of_heron y x z R hx0 hz0 (by linear_combination key) + have h2z : (2 : ℤ) ∣ z := two_dvd_of_heron z x y R hx0 hy0 (by linear_combination key) + have h2x' : 2 ∣ x := by exact_mod_cast h2x + have h2y' : 2 ∣ y := by exact_mod_cast h2y + have h2z' : 2 ∣ z := by exact_mod_cast h2z + have : 2 ∣ Nat.gcd x (Nat.gcd y z) := Nat.dvd_gcd h2x' (Nat.dvd_gcd h2y' h2z') + rw [hgcd] at this + omega + +end Math0.Frontier.A392943 + +#math0_settles Math0.Frontier.A392943.result Math0.Statements.A392943.statement diff --git a/lean/Math0/Frontier/OEIS/A393794.lean b/lean/Math0/Frontier/OEIS/A393794.lean new file mode 100644 index 0000000..054b360 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A393794.lean @@ -0,0 +1,34 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A393794 +import Math0.Audit + +/-! +# The 1089-trick map has two 9-digit fixed points + +We refute the uniqueness conjecture of A393794. For `n = 5` the claimed unique 9-digit fixed +point is `a 5 = 109999890`, but `x = 108910890` also has 9 digits and is fixed by `T`: +`rev x = 98019801`, so `D = |x - rev x| = 10891089`, `rev D = 98019801`, and +`T x = 10891089 + 98019801 = 108910890 = x`. Since `x ≠ a 5`, uniqueness fails. +All of this is a small kernel computation. +-/ + +namespace Math0.Frontier.A393794 +open Math0.Statements.A393794 + +/-- `108910890` has 9 digits, is fixed by `T`, and differs from `a 5` (kernel-checked). -/ +private theorem witness : + (Nat.digits 10 108910890).length = 5 + 4 ∧ T 108910890 = 108910890 ∧ + 108910890 ≠ a 5 := by + decide +kernel + +/-- The conjecture fails at `n = 5`: `108910890` is a second 9-digit fixed point of `T`. -/ +theorem result : ¬ statement := by + intro h + obtain ⟨hlen, hT, hne⟩ := witness + exact hne ((h 5 (by norm_num)).2.2 108910890 hlen hT) + +end Math0.Frontier.A393794 + +#math0_settles Math0.Frontier.A393794.result Math0.Statements.A393794.statement diff --git a/lean/Math0/Frontier/OEIS/A394981.lean b/lean/Math0/Frontier/OEIS/A394981.lean new file mode 100644 index 0000000..b190f63 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A394981.lean @@ -0,0 +1,2439 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A394981 +import Math0.Audit + +/-! +# Bar tilings of the smallest-perimeter rectangle: `a(n + 1) = 4 a(n)` for odd `n ≥ 3` (A394981) + +We prove the conjecture of A394981 in the form of `statement`: for every odd `n = 2m + 1 ≥ 3`, +`a(2m + 2) = 4 a(2m + 1)`. Write `R(n)` for the number of tilings of the rectangle of `n` by the +bars `1 × 1, …, 1 × n` (each used once); the rectangles are `S = (m + 1) × (2m + 1)` for +`n = 2m + 1` and `B = (m + 1) × (2m + 3)` for `n = 2m + 2`. + +*The definition, made explicit.* `search` enumerates exactly the tilings (`search_eq`: it sums +over all assignments of placements to the tiles that partition the free cells, read through the +bitmask encoding), and the labelling it builds has the length of the covering tile in the field +of every cell (`field_cell`). Since the bars have pairwise different lengths, a symmetry fixing a +tiling fixes every tile; looking at the tiles in the corners, no non-identity symmetry of a +non-square rectangle with at least two rows and columns can do so (`stabCount_eq_one`). Hence +`a(n) = R(n) / 4` for `n ≥ 3` (`a_odd`, `a_even`). + +*Structure.* In `S` the bar `2m + 1` is a full row, so the bars `m + 1, …, 2m + 1` are horizontal; +each crosses the middle column `m`, and since two of them do not fit in one row, every row holds +exactly one of them. So the middle column is covered by the long bars and the short bars +`1, …, m` avoid it. In `B` the bars `m + 2, …, 2m + 2` are horizontal, cross column `m + 1` and +again one lies in each row. The bar `m + 1` of `B` is then either vertical, and then a full first +or last column (bar `2m + 2` must fit beside it), or horizontal, and then it shares its row with +bar `m + 2`, the two filling that row in one of two orders. + +*Four bijections.* If bar `m + 1` is the first (last) column of `B`, deleting it and the column +`m + 2` (`m + 1`) of `B`, and shortening every long bar by one, gives a tiling of `S` +(`PhiV`/`PsiV`). If bar `m + 1` is horizontal, replacing the row of `m + 1` and `m + 2` by the +bar `2m + 1`, deleting the columns `m + 1`, `m + 2` and shortening the other long bars by two, +gives a tiling of `S` (`PhiH`/`PsiH`). Hence `R(2m + 2) = 4 R(2m + 1)` (`card_big`). + +*Divisibility.* The reflections of `S` act freely on its tilings, distinguished by the row of +bar `2m + 1` (with the row of bar `2m` to break the tie at the middle row) and by the column +(`0` or `1`) of bar `2m`; so `4 ∣ R(2m + 1)` (`four_dvd_small`), and +`a(2m + 2) = R(2m + 2) / 4 = R(2m + 1) = 4 (R(2m + 1) / 4) = 4 a(2m + 1)`. +-/ + +namespace Math0.Frontier.A394981 +open Math0.Statements.A394981 Finset + +/-! ## Bits -/ + +/-- Bit `p` of `∑_{i ∈ s} 2 ^ i` is set iff `p ∈ s`. -/ +private theorem testBit_sum_two_pow (s : Finset ℕ) (p : ℕ) : + (∑ i ∈ s, 2 ^ i).testBit p = true ↔ p ∈ s := by + rw [← Nat.mem_bitIndices, ← List.mem_toFinset, Finset.toFinset_bitIndices_sum_two_pow] + +/-- The set of set bits of `X`. -/ +private def bset (X : ℕ) : Finset ℕ := X.bitIndices.toFinset + +/-- Membership in `bset X` is the bit test. -/ +private theorem mem_bset {X p : ℕ} : p ∈ bset X ↔ X.testBit p = true := by + simp [bset] + +/-- `X` is the sum of `2 ^ i` over its set bits. -/ +private theorem sum_bset (X : ℕ) : ∑ i ∈ bset X, 2 ^ i = X := + Finset.sum_toFinset_bitIndices_two_pow X + +/-- The set bits of `∑_{i ∈ s} 2 ^ i` are `s`. -/ +private theorem bset_sum (s : Finset ℕ) : bset (∑ i ∈ s, 2 ^ i) = s := + Finset.toFinset_bitIndices_sum_two_pow s + +/-- Clearing the lowest set bit. -/ +private theorem land_sub_one (v Y : ℕ) : + Nat.land (2 ^ (v + 1) * Y + 2 ^ v) (2 ^ (v + 1) * Y + 2 ^ v - 1) = 2 ^ (v + 1) * Y := by + have h1 : 2 ^ v < 2 ^ (v + 1) := Nat.pow_lt_pow_right (by norm_num) (by omega) + have h2 : 2 ^ v - 1 < 2 ^ (v + 1) := by omega + have hv : 1 ≤ 2 ^ v := Nat.one_le_two_pow + have e : 2 ^ (v + 1) * Y + 2 ^ v - 1 = 2 ^ (v + 1) * Y + (2 ^ v - 1) := by omega + rw [e] + apply Nat.eq_of_testBit_eq + intro j + have h0 : (0:ℕ) < 2 ^ (v + 1) := by positivity + rw [Nat.land_eq, Nat.testBit_and, Nat.testBit_two_pow_mul_add _ h1, + Nat.testBit_two_pow_mul_add _ h2] + conv_rhs => rw [← Nat.add_zero (2 ^ (v + 1) * Y), Nat.testBit_two_pow_mul_add _ h0] + split_ifs with hj + · rcases Nat.lt_or_ge j v with h | h + · simp [show v ≠ j by omega] + · simp [Nat.testBit_two_pow_sub_one, show ¬ j < v by omega] + · simp + +/-- `sumBits g fuel X` is `∑ g (2 ^ i)` over the set bits `i` of `X` when `fuel` is at least +their number. -/ +private theorem sumBits_eq (g : ℕ → ℕ) : ∀ (fuel X : ℕ), (bset X).card ≤ fuel → + sumBits g fuel X = ∑ i ∈ bset X, g (2 ^ i) + | 0, X, h => by + have : bset X = ∅ := Finset.card_eq_zero.mp (by omega) + rw [this, Finset.sum_empty]; rfl + | fuel + 1, X, h => by + show (bif Nat.beq X 0 then 0 else + g (X - Nat.land X (X - 1)) + sumBits g fuel (Nat.land X (X - 1))) = _ + by_cases hX : X = 0 + · subst hX + have : bset 0 = ∅ := by simp [bset] + rw [this, Finset.sum_empty]; rfl + · have hb : Nat.beq X 0 = false := by + cases h : Nat.beq X 0 + · rfl + · exact absurd (Nat.eq_of_beq_eq_true h) hX + rw [hb, cond_false] + have hne : (bset X).Nonempty := by + rw [Finset.nonempty_iff_ne_empty] + intro h0 + apply hX + rw [← sum_bset X, h0, Finset.sum_empty] + set s := bset X with hs + set v := s.min' hne with hv + have hvs : v ∈ s := Finset.min'_mem s hne + set Z := ∑ i ∈ s.erase v, 2 ^ i with hZ + have hdvd : 2 ^ (v + 1) ∣ Z := by + apply Finset.dvd_sum + intro i hi + have h1 : v ≤ i := Finset.min'_le s i (Finset.mem_of_mem_erase hi) + have h2 : i ≠ v := Finset.ne_of_mem_erase hi + exact Nat.pow_dvd_pow 2 (by omega) + obtain ⟨Y, hY⟩ := hdvd + have hX' : X = 2 ^ (v + 1) * Y + 2 ^ v := by + rw [← hY, hZ] + conv_lhs => rw [← sum_bset X] + rw [← hs, ← Finset.add_sum_erase s _ hvs] + ring + have hland : Nat.land X (X - 1) = Z := by + rw [hY, hX']; exact land_sub_one v Y + have hsub : X - Nat.land X (X - 1) = 2 ^ v := by + rw [hland, hY, hX', Nat.add_sub_cancel_left] + have hcard : (bset Z).card ≤ fuel := by + rw [hZ, bset_sum, Finset.card_erase_of_mem hvs] + omega + rw [hsub, hland, sumBits_eq g fuel Z hcard, hZ, bset_sum] + exact Finset.add_sum_erase s (fun i => g (2 ^ i)) hvs + +/-! ## Placements and tilings -/ + +/-- A placement `(i, j, d)`: first cell in row `i`, column `j`; vertical iff `d`. -/ +private abbrev Pl := ℕ × ℕ × Bool + +/-- The default placement, used outside the range of tiles. -/ +private def dflt : Pl := (0, 0, false) + +/-- Cell `(a, b)` lies in the bar of length `k` placed at `p`. -/ +private def inBar (p : Pl) (k a b : ℕ) : Prop := + if p.2.2 = true then b = p.2.1 ∧ p.1 ≤ a ∧ a < p.1 + k else a = p.1 ∧ p.2.1 ≤ b ∧ b < p.2.1 + k + +/-- Membership in a bar is decidable. -/ +private instance (p : Pl) (k a b : ℕ) : Decidable (inBar p k a b) := by + unfold inBar; infer_instance + +/-- The bar of length `k` at `p` fits in the `r × c` rectangle (and is horizontal if `k = 1`). -/ +private def Fits (r c : ℕ) (p : Pl) (k : ℕ) : Prop := + if p.2.2 = true then p.1 + k ≤ r ∧ p.2.1 < c ∧ 2 ≤ k else p.1 < r ∧ p.2.1 + k ≤ c + +/-- The cells of the bar of length `k` at `p`. -/ +private def cellsOf (p : Pl) (k : ℕ) : Finset (ℕ × ℕ) := + (range k).image (fun t => if p.2.2 = true then (p.1 + t, p.2.1) else (p.1, p.2.1 + t)) + +/-- A cell lies in `cellsOf p k` iff it lies in the bar. -/ +private theorem mem_cellsOf {p : Pl} {k a b : ℕ} : (a, b) ∈ cellsOf p k ↔ inBar p k a b := by + obtain ⟨i, j, d⟩ := p + cases d + · simp only [cellsOf, inBar, mem_image, mem_range, Bool.false_eq_true, if_false, Prod.mk.injEq] + constructor + · rintro ⟨t, ht, h1, h2⟩; omega + · rintro ⟨h1, h2, h3⟩; exact ⟨b - j, by omega, by omega, by omega⟩ + · simp only [cellsOf, inBar, mem_image, mem_range, if_true, Prod.mk.injEq] + constructor + · rintro ⟨t, ht, h1, h2⟩; omega + · rintro ⟨h1, h2, h3⟩; exact ⟨a - i, by omega, by omega, by omega⟩ + +/-- The cells of the `r × c` rectangle. -/ +private def rectS (r c : ℕ) : Finset (ℕ × ℕ) := range r ×ˢ range c + +/-- Membership in the rectangle. -/ +private theorem mem_rectS {r c a b : ℕ} : (a, b) ∈ rectS r c ↔ a < r ∧ b < c := by + simp [rectS] + +/-- A bar that fits only covers cells of the rectangle. -/ +private theorem inBar_lt {r c : ℕ} {p : Pl} {k a b : ℕ} (hf : Fits r c p k) (h : inBar p k a b) : + a < r ∧ b < c := by + obtain ⟨i, j, d⟩ := p + cases d <;> simp only [Fits, inBar, Bool.false_eq_true, if_false, if_true] at hf h <;> omega + +/-- `P` places the tiles `1, …, k` (tile `k'` at `P k'`) so that they partition `S`. -/ +private def ValidOn (r c k : ℕ) (P : ℕ → Pl) (S : Finset (ℕ × ℕ)) : Prop := + (∀ k', 1 ≤ k' → k' ≤ k → Fits r c (P k') k') ∧ + (∀ k' a b, 1 ≤ k' → k' ≤ k → inBar (P k') k' a b → (a, b) ∈ S) ∧ + (∀ a b, (a, b) ∈ S → ∃ k', 1 ≤ k' ∧ k' ≤ k ∧ inBar (P k') k' a b) ∧ + (∀ a b k1 k2, 1 ≤ k1 → k1 ≤ k → 1 ≤ k2 → k2 ≤ k → + inBar (P k1) k1 a b → inBar (P k2) k2 a b → k1 = k2) + +/-- A tiling of the `r × c` rectangle by the bars `1 × 1, …, 1 × n`. -/ +private def Valid (r c n : ℕ) (P : ℕ → Pl) : Prop := ValidOn r c n P (rectS r c) + +/-- Peeling off the largest tile: `P` places the tiles `1, …, k + 1` as a partition of `S` iff +tile `k + 1` fits inside `S` and the other tiles partition the rest. -/ +private theorem validOn_succ {r c k : ℕ} {P : ℕ → Pl} {S : Finset (ℕ × ℕ)} : + ValidOn r c (k + 1) P S ↔ Fits r c (P (k + 1)) (k + 1) ∧ cellsOf (P (k + 1)) (k + 1) ⊆ S ∧ + ValidOn r c k P (S \ cellsOf (P (k + 1)) (k + 1)) := by + constructor + · rintro ⟨h1, h2, h3, h4⟩ + refine ⟨h1 _ (by omega) le_rfl, ?_, ?_, ?_, ?_, ?_⟩ + · intro x hx + obtain ⟨a, b⟩ := x + exact h2 _ a b (by omega) le_rfl (mem_cellsOf.mp hx) + · intro k' hk1 hk2; exact h1 k' hk1 (by omega) + · intro k' a b hk1 hk2 hin + rw [mem_sdiff, mem_cellsOf] + refine ⟨h2 k' a b hk1 (by omega) hin, fun h => ?_⟩ + have := h4 a b k' (k + 1) hk1 (by omega) (by omega) le_rfl hin h + omega + · intro a b hab + rw [mem_sdiff, mem_cellsOf] at hab + obtain ⟨k', hk1, hk2, hin⟩ := h3 a b hab.1 + refine ⟨k', hk1, ?_, hin⟩ + rcases Nat.lt_or_ge k' (k + 1) with h | h + · omega + · have : k' = k + 1 := by omega + subst this; exact absurd hin hab.2 + · intro a b k1 k2 h1' h2' h3' h4' + exact h4 a b k1 k2 h1' (by omega) h3' (by omega) + · rintro ⟨hf, hsub, h1, h2, h3, h4⟩ + refine ⟨?_, ?_, ?_, ?_⟩ + · intro k' hk1 hk2 + rcases Nat.lt_or_ge k' (k + 1) with h | h + · exact h1 k' hk1 (by omega) + · have : k' = k + 1 := by omega + subst this; exact hf + · intro k' a b hk1 hk2 hin + rcases Nat.lt_or_ge k' (k + 1) with h | h + · exact (mem_sdiff.mp (h2 k' a b hk1 (by omega) hin)).1 + · have : k' = k + 1 := by omega + subst this; exact hsub (mem_cellsOf.mpr hin) + · intro a b hab + by_cases hc : (a, b) ∈ cellsOf (P (k + 1)) (k + 1) + · exact ⟨k + 1, by omega, le_rfl, mem_cellsOf.mp hc⟩ + · obtain ⟨k', hk1, hk2, hin⟩ := h3 a b (mem_sdiff.mpr ⟨hab, hc⟩) + exact ⟨k', hk1, by omega, hin⟩ + · intro a b k1 k2 hk1 hk1' hk2 hk2' hin1 hin2 + have key : ∀ k', 1 ≤ k' → k' ≤ k → inBar (P k') k' a b → + ¬ inBar (P (k + 1)) (k + 1) a b := by + intro k' h h' hin hin' + exact (mem_sdiff.mp (h2 k' a b h h' hin)).2 (mem_cellsOf.mpr hin') + rcases Nat.lt_or_ge k1 (k + 1) with h | h <;> rcases Nat.lt_or_ge k2 (k + 1) with h' | h' + · exact h4 a b k1 k2 hk1 (by omega) hk2 (by omega) hin1 hin2 + · have : k2 = k + 1 := by omega + subst this; exact absurd hin2 (key k1 hk1 (by omega) hin1) + · have : k1 = k + 1 := by omega + subst this; exact absurd hin1 (key k2 hk2 (by omega) hin2) + · omega + +/-- `ValidOn` only depends on the placements of the tiles `1, …, k`. -/ +private theorem validOn_congr_imp {r c k : ℕ} {P Q : ℕ → Pl} {S : Finset (ℕ × ℕ)} + (h : ∀ k', 1 ≤ k' → k' ≤ k → P k' = Q k') (hP : ValidOn r c k P S) : ValidOn r c k Q S := by + obtain ⟨h1, h2, h3, h4⟩ := hP + refine ⟨fun k' a b => ?_, fun k' a b c1 c2 hin => ?_, fun a b hab => ?_, + fun a b k1 k2 a1 a2 a3 a4 a5 a6 => ?_⟩ + · rw [← h k' a b]; exact h1 k' a b + · rw [← h k' c1 c2] at hin; exact h2 k' a b c1 c2 hin + · obtain ⟨k', e1, e2, e3⟩ := h3 a b hab + exact ⟨k', e1, e2, by rw [← h k' e1 e2]; exact e3⟩ + · rw [← h k1 a1 a2] at a5; rw [← h k2 a3 a4] at a6 + exact h4 a b k1 k2 a1 a2 a3 a4 a5 a6 + +/-- `ValidOn` only depends on the placements of the tiles `1, …, k` (iff form). -/ +private theorem validOn_congr {r c k : ℕ} {P Q : ℕ → Pl} {S : Finset (ℕ × ℕ)} + (h : ∀ k', 1 ≤ k' → k' ≤ k → P k' = Q k') : ValidOn r c k P S ↔ ValidOn r c k Q S := + ⟨validOn_congr_imp h, validOn_congr_imp fun k' h1 h2 => (h k' h1 h2).symm⟩ + +/-! ## The encoding used by `search` -/ + +/-- The index of the first cell of a placement. -/ +private def idx (w : ℕ) (p : Pl) : ℕ := p.1 * w + p.2.1 + +/-- The index step along a placement. -/ +private def step (w : ℕ) (p : Pl) : ℕ := if p.2.2 = true then w else 1 + +/-- The labelling built by `search` along the placements `P 1, …, P k`. -/ +private def enc (w L : ℕ) (P : ℕ → Pl) : ℕ → ℕ + | 0 => 0 + | k + 1 => enc w L P k + (k + 1) * barAt (2 ^ idx w (P (k + 1))) L (step w (P (k + 1))) (k + 1) + +/-- `enc` only depends on the placements of the tiles `1, …, k`. -/ +private theorem enc_congr {w L : ℕ} {P Q : ℕ → Pl} : ∀ k, (∀ k', 1 ≤ k' → k' ≤ k → P k' = Q k') → + enc w L P k = enc w L Q k + | 0, _ => rfl + | k + 1, h => by + simp only [enc] + rw [enc_congr k (fun k' h1 h2 => h k' h1 (by omega)), h (k + 1) (by omega) le_rfl] + +/-- The candidate placements inside the `r × c` rectangle. -/ +private def Xs (r c : ℕ) : Finset Pl := range r ×ˢ (range c ×ˢ univ) + +open Classical in +/-- All assignments of candidate placements to the tiles `1, …, k` (default elsewhere). -/ +private noncomputable def Univ (r c : ℕ) : ℕ → Finset (ℕ → Pl) + | 0 => {fun _ => dflt} + | k + 1 => ((Univ r c k) ×ˢ Xs r c).image (fun x => Function.update x.1 (k + 1) x.2) + +/-- `Univ r c k` consists of the assignments that are default outside `1, …, k` and use +candidate placements on `1, …, k`. -/ +private theorem mem_Univ {r c : ℕ} : ∀ {k : ℕ} {P : ℕ → Pl}, P ∈ Univ r c k ↔ + (∀ k', (k' = 0 ∨ k < k') → P k' = dflt) ∧ (∀ k', 1 ≤ k' → k' ≤ k → P k' ∈ Xs r c) + | 0, P => by + classical + simp only [Univ, mem_singleton] + constructor + · rintro rfl; exact ⟨fun _ _ => rfl, fun k' h1 h2 => by omega⟩ + · rintro ⟨h1, -⟩; funext k'; exact h1 k' (by omega) + | k + 1, P => by + classical + simp only [Univ, mem_image, mem_product] + constructor + · rintro ⟨⟨Q, p⟩, ⟨hQ, hp⟩, rfl⟩ + rw [mem_Univ] at hQ + refine ⟨fun k' hk' => ?_, fun k' h1 h2 => ?_⟩ + · rw [Function.update_of_ne (by omega)]; exact hQ.1 k' (by omega) + · by_cases e : k' = k + 1 + · subst e; simpa using hp + · rw [Function.update_of_ne e]; exact hQ.2 k' h1 (by omega) + · rintro ⟨h1, h2⟩ + refine ⟨⟨Function.update P (k + 1) dflt, P (k + 1)⟩, ⟨?_, h2 _ (by omega) le_rfl⟩, ?_⟩ + · rw [mem_Univ] + dsimp only + refine ⟨fun k' hk' => ?_, fun k' h1' h2' => ?_⟩ + · by_cases e : k' = k + 1 + · subst e; simp + · rw [Function.update_of_ne e]; exact h1 k' (by omega) + · rw [Function.update_of_ne (by omega)]; exact h2 k' h1' (by omega) + · funext k' + by_cases e : k' = k + 1 + · subst e; simp + · simp [Function.update_of_ne e] + +/-- Summing over `Univ r c (k + 1)` is summing over `Univ r c k` and the placement of tile +`k + 1`. -/ +private theorem sum_Univ_succ {r c k : ℕ} (F : (ℕ → Pl) → ℕ) : + ∑ P ∈ Univ r c (k + 1), F P = + ∑ P ∈ Univ r c k, ∑ p ∈ Xs r c, F (Function.update P (k + 1) p) := by + classical + rw [Univ, sum_image, sum_product] + rintro ⟨P, p⟩ hP ⟨Q, q⟩ hQ he + simp only [coe_product, Set.mem_prod, mem_coe] at hP hQ + have e1 : p = q := by have := congrFun he (k + 1); simpa using this + have hP0 := (mem_Univ.mp hP.1).1 (k + 1) (by omega) + have hQ0 := (mem_Univ.mp hQ.1).1 (k + 1) (by omega) + have e2 : P = Q := by + funext k' + by_cases e : k' = k + 1 + · subst e; rw [hP0, hQ0] + · have := congrFun he k'; simpa [Function.update_of_ne e] using this + simp [e1, e2] + +/-! ## Bitmasks of cell sets -/ + +/-- The bitmask of a set of cells, rows of length `w`. -/ +private def bmC (w : ℕ) (S : Finset (ℕ × ℕ)) : ℕ := ∑ x ∈ S, 2 ^ (x.1 * w + x.2) + +/-- Cell indices `a * w + b` with `b < w` determine the cell. -/ +private theorem idx_inj {w a b a' b' : ℕ} (hb : b < w) (hb' : b' < w) + (h : a * w + b = a' * w + b') : a = a' ∧ b = b' := by + have hw : 0 < w := by omega + have e1 : (a * w + b) / w = a := by + rw [Nat.add_comm, Nat.add_mul_div_right _ _ hw, Nat.div_eq_of_lt hb, zero_add] + have e2 : (a' * w + b') / w = a' := by + rw [Nat.add_comm, Nat.add_mul_div_right _ _ hw, Nat.div_eq_of_lt hb', zero_add] + have e3 : a = a' := by rw [← e1, ← e2, h] + subst e3 + exact ⟨rfl, by omega⟩ + +/-- The set bits of the bitmask of a cell set are the indices of its cells. -/ +private theorem testBit_bmC {w : ℕ} {S : Finset (ℕ × ℕ)} (hS : ∀ x ∈ S, x.2 < w) (p : ℕ) : + (bmC w S).testBit p = true ↔ ∃ x ∈ S, x.1 * w + x.2 = p := by + have : bmC w S = ∑ y ∈ S.image (fun x => x.1 * w + x.2), 2 ^ y := by + rw [sum_image] + · rfl + · intro x hx y hy hxy + obtain ⟨e1, e2⟩ := idx_inj (hS x hx) (hS y hy) hxy + exact Prod.ext e1 e2 + rw [this, testBit_sum_two_pow, mem_image] + +/-- The bitmask of a set difference is the difference of the bitmasks. -/ +private theorem bmC_sdiff {w : ℕ} {S B : Finset (ℕ × ℕ)} (h : B ⊆ S) : + bmC w S - bmC w B = bmC w (S \ B) := by + have := sum_sdiff (f := fun x : ℕ × ℕ => 2 ^ (x.1 * w + x.2)) h + unfold bmC; omega + +/-- A bitmask vanishes iff the cell set is empty. -/ +private theorem bmC_eq_zero {w : ℕ} {S : Finset (ℕ × ℕ)} : bmC w S = 0 ↔ S = ∅ := by + simp [bmC, Finset.sum_eq_zero_iff, Finset.eq_empty_iff_forall_notMem] + +/-- `barAt` at the first cell of a placement, with the placement's step, is the sum over its +cells (in fields of `L` bits). -/ +private theorem barAt_cells {w L : ℕ} (hw : 1 ≤ w) (hL : 1 ≤ L) (p : Pl) (k : ℕ) : + barAt (2 ^ idx w p) L (step w p) k = ∑ x ∈ cellsOf p k, 2 ^ (L * (x.1 * w + x.2)) := by + have hs : 1 ≤ L * step w p := by + unfold step; split_ifs <;> nlinarith + rw [barAt_eq hs, cellsOf, sum_image] + · apply sum_congr rfl + intro t _ + obtain ⟨i, j, d⟩ := p + cases d <;> simp only [idx, step, Bool.false_eq_true, if_false, if_true] <;> congr 2 <;> ring + · intro t1 _ t2 _ h + obtain ⟨i, j, d⟩ := p + cases d <;> simp at h <;> omega + +/-- Cells of the rectangle have column `< w` when `c < w`. -/ +private theorem rect_snd_lt {r c w : ℕ} (hcw : c < w) {S : Finset (ℕ × ℕ)} (hS : S ⊆ rectS r c) : + ∀ x ∈ S, x.2 < w := by + intro x hx + have := hS hx + obtain ⟨a, b⟩ := x + rw [mem_rectS] at this + simp only; omega + +/-- The horizontal starts of tile `k + 1` inside `S`: bit `q` of `starts` is set iff the `k + 1` +cells from `q` along its row lie in `S` (and do not run past the last column). -/ +private theorem starts_h {r c w : ℕ} (hcw : c < w) {S : Finset (ℕ × ℕ)} (hS : S ⊆ rectS r c) + (k q : ℕ) : (starts (bmC w S) 1 (k + 1)).testBit q = true ↔ + q % w + k < c ∧ ∀ t ≤ k, (q / w, q % w + t) ∈ S := by + have hS' := rect_snd_lt hcw hS + have hq := Nat.div_add_mod' q w + have hw : q % w < w := Nat.mod_lt _ (by omega) + rw [testBit_starts] + simp only [mul_one, testBit_bmC hS'] + constructor + · intro h + obtain ⟨x, hx, hxe⟩ := h 0 (by omega) + have hx2 := hS' x hx + have hxr := hS hx + obtain ⟨x1, x2⟩ := x + rw [mem_rectS] at hxr + simp only at hxe hx2 + obtain ⟨-, e2⟩ := idx_inj hx2 hw (hxe.trans (by omega : q + 0 = q / w * w + q % w)) + have hlt : q % w + k < c := by + by_contra hcon + obtain ⟨y, hy, hye⟩ := h (c - q % w) (by omega) + have hy2 := hS' y hy + have hyr := hS hy + obtain ⟨y1, y2⟩ := y + rw [mem_rectS] at hyr + simp only at hye hy2 + obtain ⟨-, e3⟩ := idx_inj hy2 hcw (hye.trans (by omega : q + (c - q % w) = q / w * w + c)) + omega + refine ⟨hlt, fun t ht => ?_⟩ + obtain ⟨z, hz, hze⟩ := h t (by omega) + have hz2 := hS' z hz + obtain ⟨z1, z2⟩ := z + simp only at hze hz2 + obtain ⟨e4, e5⟩ := idx_inj hz2 (by omega : q % w + t < w) + (hze.trans (by omega : q + t = q / w * w + (q % w + t))) + rw [e4, e5] at hz; exact hz + · rintro ⟨h1, h2⟩ t ht + exact ⟨(q / w, q % w + t), h2 t (by omega), by simp only; omega⟩ + +/-- The vertical starts of tile `k + 1` inside `S`: bit `q` of `starts` is set iff the `k + 1` +cells from `q` down its column lie in `S`. -/ +private theorem starts_v {r c w : ℕ} (hcw : c < w) {S : Finset (ℕ × ℕ)} (hS : S ⊆ rectS r c) + (k q : ℕ) : (starts (bmC w S) w (k + 1)).testBit q = true ↔ + q % w < c ∧ ∀ t ≤ k, (q / w + t, q % w) ∈ S := by + have hS' := rect_snd_lt hcw hS + have hq := Nat.div_add_mod' q w + have hw : q % w < w := Nat.mod_lt _ (by omega) + have key : ∀ t, q + t * w = (q / w + t) * w + q % w := by + intro t; rw [add_mul]; omega + rw [testBit_starts] + simp only [testBit_bmC hS'] + constructor + · intro h + obtain ⟨x, hx, hxe⟩ := h 0 (by omega) + have hxr := hS hx + obtain ⟨x1, x2⟩ := x + rw [mem_rectS] at hxr + simp only at hxe + obtain ⟨-, e2⟩ := idx_inj (by omega) hw (hxe.trans (by rw [key 0])) + refine ⟨by omega, fun t ht => ?_⟩ + obtain ⟨z, hz, hze⟩ := h t (by omega) + have hz2 := hS' z hz + obtain ⟨z1, z2⟩ := z + simp only at hze hz2 + obtain ⟨e4, e5⟩ := idx_inj hz2 hw (hze.trans (key t)) + rw [e4, e5] at hz; exact hz + · rintro ⟨h1, h2⟩ t ht + exact ⟨(q / w + t, q % w), h2 t (by omega), by simp only; rw [key t]⟩ + +/-- A horizontal bar lies in `S` iff each of its cells does. -/ +private theorem cellsOf_sub_h {S : Finset (ℕ × ℕ)} (i j k : ℕ) : + cellsOf (i, j, false) (k + 1) ⊆ S ↔ ∀ t ≤ k, (i, j + t) ∈ S := by + simp only [cellsOf, Bool.false_eq_true, if_false, image_subset_iff, mem_range] + exact ⟨fun h t ht => h t (by omega), fun h t ht => h t (by omega)⟩ + +/-- A vertical bar lies in `S` iff each of its cells does. -/ +private theorem cellsOf_sub_v {S : Finset (ℕ × ℕ)} (i j k : ℕ) : + cellsOf (i, j, true) (k + 1) ⊆ S ↔ ∀ t ≤ k, (i + t, j) ∈ S := by + simp only [cellsOf, if_true, image_subset_iff, mem_range] + exact ⟨fun h t ht => h t (by omega), fun h t ht => h t (by omega)⟩ + +/-- Summing over the set bits of `starts` is summing over the placements of tile `k + 1` with +the given orientation inside `S`. -/ +private theorem sumBits_starts {r c w : ℕ} (hcw : c < w) {S : Finset (ℕ × ℕ)} + (hS : S ⊆ rectS r c) (k : ℕ) (d : Bool) (g : ℕ → ℕ) : + sumBits g (r * w) (starts (bmC w S) (if d = true then w else 1) (k + 1)) = + ∑ p ∈ (Xs r c).filter (fun p => p.2.2 = d ∧ cellsOf p (k + 1) ⊆ S), g (2 ^ idx w p) := by + have hw0 : 0 < w := by omega + -- membership in the set bits + have hmem : ∀ q, q ∈ bset (starts (bmC w S) (if d = true then w else 1) (k + 1)) ↔ + (q / w, q % w, d) ∈ (Xs r c).filter (fun p => p.2.2 = d ∧ cellsOf p (k + 1) ⊆ S) := by + intro q + rw [mem_bset, mem_filter] + cases d + · simp only [Bool.false_eq_true, if_false, starts_h hcw hS, cellsOf_sub_h, Xs, mem_product, + mem_range, mem_univ, and_true, true_and] + constructor + · rintro ⟨h1, h2⟩ + have := mem_rectS.mp (hS (h2 0 (by omega))) + exact ⟨⟨this.1, by omega⟩, h2⟩ + · rintro ⟨⟨h1, h2⟩, h3⟩ + refine ⟨?_, h3⟩ + have := mem_rectS.mp (hS (h3 k le_rfl)) + omega + · simp only [if_true, starts_v hcw hS, cellsOf_sub_v, Xs, mem_product, + mem_range, mem_univ, and_true, true_and] + constructor + · rintro ⟨h1, h2⟩ + have := mem_rectS.mp (hS (h2 0 (by omega))) + exact ⟨⟨by omega, h1⟩, h2⟩ + · rintro ⟨⟨h1, h2⟩, h3⟩ + exact ⟨h2, h3⟩ + rw [sumBits_eq] + · apply sum_nbij' (fun q => (q / w, q % w, d)) (fun p => idx w p) + · intro q hq; exact (hmem q).mp hq + · intro p hp + have hp' := hp + rw [mem_filter] at hp + obtain ⟨hpX, hpd, -⟩ := hp + obtain ⟨i, j, d'⟩ := p + simp only at hpd + subst hpd + simp only [Xs, mem_product, mem_range, mem_univ, and_true] at hpX + rw [hmem] + have e1 : (i * w + j) / w = i := by + rw [Nat.add_comm, Nat.add_mul_div_right _ _ hw0, Nat.div_eq_of_lt (by omega), zero_add] + have e2 : (i * w + j) % w = j := by + rw [Nat.add_comm, Nat.add_mul_mod_self_right, Nat.mod_eq_of_lt (by omega)] + simp only [idx, e1, e2]; exact hp' + · intro q _; simp only [idx]; exact Nat.div_add_mod' q w + · intro p hp + rw [mem_filter] at hp + obtain ⟨hpX, hpd, -⟩ := hp + obtain ⟨i, j, d'⟩ := p + simp only at hpd + subst hpd + simp only [Xs, mem_product, mem_range, mem_univ, and_true] at hpX + have e1 : (i * w + j) / w = i := by + rw [Nat.add_comm, Nat.add_mul_div_right _ _ hw0, Nat.div_eq_of_lt (by omega), zero_add] + have e2 : (i * w + j) % w = j := by + rw [Nat.add_comm, Nat.add_mul_mod_self_right, Nat.mod_eq_of_lt (by omega)] + simp only [idx, e1, e2] + · intro q _; simp only [idx, Nat.div_add_mod'] + · calc (bset (starts (bmC w S) (if d = true then w else 1) (k + 1))).card + ≤ (range (r * w)).card := by + apply card_le_card + intro q hq + rw [hmem, mem_filter] at hq + simp only [Xs, mem_product, mem_range, mem_univ, and_true] at hq + rw [mem_range] + have h1 : (q / w + 1) * w ≤ r * w := Nat.mul_le_mul_right _ (by omega) + have h2 := Nat.div_add_mod' q w + have h3 : q % w < w := Nat.mod_lt _ hw0 + rw [add_mul, one_mul] at h1 + omega + _ = r * w := card_range _ + +/-- One step of `search`. -/ +private theorem search_succ (w N L : ℕ) (f : ℕ → ℕ) (k free lab : ℕ) : + search w N L f (k + 1) free lab = + sumBits (fun x => search w N L f k (free - barAt x 1 1 (k + 1)) + (lab + (k + 1) * barAt x L 1 (k + 1))) N (starts free 1 (k + 1)) + + bif Nat.ble 1 k then + sumBits (fun x => search w N L f k (free - barAt x 1 w (k + 1)) + (lab + (k + 1) * barAt x L w (k + 1))) N (starts free w (k + 1)) + else 0 := rfl + +/-- The base case of `search`. -/ +private theorem search_zero (w N L : ℕ) (f : ℕ → ℕ) (free lab : ℕ) : + search w N L f 0 free lab = bif Nat.beq free 0 then f lab else 0 := rfl + +/-- A placement of tile `k + 1` inside `S` fits iff it is not a vertical `1 × 1` tile. -/ +private theorem fits_iff {r c : ℕ} {S : Finset (ℕ × ℕ)} (hS : S ⊆ rectS r c) {p : Pl} {k : ℕ} + (hsub : cellsOf p (k + 1) ⊆ S) : Fits r c p (k + 1) ↔ (p.2.2 = true → 1 ≤ k) := by + obtain ⟨i, j, d⟩ := p + cases d + · have := mem_rectS.mp (hS (hsub (mem_cellsOf.mpr + (show inBar (i, j, false) (k + 1) i (j + k) by simp [inBar])))) + simp [Fits]; omega + · have := mem_rectS.mp (hS (hsub (mem_cellsOf.mpr + (show inBar (i, j, true) (k + 1) (i + k) j by simp [inBar])))) + simp [Fits]; omega + +open Classical in +/-- **The search, made explicit**: `search` sums `f` of the final labelling over the +assignments of placements to the tiles `1, …, k` that partition the free cells. -/ +private theorem search_eq {r c w L : ℕ} (hcw : c < w) (f : ℕ → ℕ) : + ∀ (k : ℕ) (S : Finset (ℕ × ℕ)), S ⊆ rectS r c → ∀ lab : ℕ, + search w (r * w) L f k (bmC w S) lab = + ∑ P ∈ Univ r c k, if ValidOn r c k P S then f (lab + enc w L P k) else 0 + | 0, S, hS, lab => by + rw [search_zero] + simp only [Univ, sum_singleton, enc, add_zero] + have hv : ValidOn r c 0 (fun _ => dflt) S ↔ S = ∅ := by + constructor + · rintro ⟨-, -, h3, -⟩ + ext ⟨a, b⟩ + simp only [Finset.notMem_empty, iff_false] + intro hab + obtain ⟨k', h1, h2, -⟩ := h3 a b hab + omega + · rintro rfl + exact ⟨fun k' h1 h2 => by omega, fun k' a b h1 h2 => by omega, + fun a b h => by simp at h, fun a b k1 k2 h1 h2 => by omega⟩ + by_cases hS0 : S = ∅ + · have hb : Nat.beq (bmC w S) 0 = true := by + rw [bmC_eq_zero.mpr hS0]; rfl + rw [hb, if_pos (hv.mpr hS0)]; rfl + · have hb : Nat.beq (bmC w S) 0 = false := by + cases h : Nat.beq (bmC w S) 0 + · rfl + · exact absurd (bmC_eq_zero.mp (Nat.eq_of_beq_eq_true h)) hS0 + rw [hb, if_neg (fun h => hS0 (hv.mp h))]; rfl + | k + 1, S, hS, lab => by + have hw1 : 1 ≤ w := by omega + have hR : (∑ P ∈ Univ r c (k + 1), if ValidOn r c (k + 1) P S then + f (lab + enc w L P (k + 1)) else 0) = + ∑ p ∈ (Xs r c).filter (fun p => Fits r c p (k + 1) ∧ cellsOf p (k + 1) ⊆ S), + search w (r * w) L f k (bmC w (S \ cellsOf p (k + 1))) + (lab + (k + 1) * barAt (2 ^ idx w p) L (step w p) (k + 1)) := by + rw [sum_Univ_succ, sum_comm, sum_filter] + apply sum_congr rfl + intro p hp + split_ifs with hc + · rw [search_eq hcw f k _ (sdiff_subset.trans hS)] + apply sum_congr rfl + intro P hP + have e1 : ValidOn r c (k + 1) (Function.update P (k + 1) p) S ↔ + ValidOn r c k P (S \ cellsOf p (k + 1)) := by + rw [validOn_succ, Function.update_self] + rw [validOn_congr (Q := P) (fun k' h1 h2 => Function.update_of_ne (by omega) _ _)] + tauto + have e2 : enc w L (Function.update P (k + 1) p) (k + 1) = + enc w L P k + (k + 1) * barAt (2 ^ idx w p) L (step w p) (k + 1) := by + simp only [enc, Function.update_self] + rw [enc_congr (P := Function.update P (k + 1) p) (Q := P) k + (fun k' h1 h2 => Function.update_of_ne (by omega) _ _)] + rw [if_congr e1 rfl rfl, e2, add_comm (enc w L P k), add_assoc] + · apply sum_eq_zero + intro P hP + rw [validOn_succ, Function.update_self, if_neg] + tauto + rw [hR, search_succ, ← sum_filter_add_sum_filter_not _ (fun p : Pl => p.2.2 = false)] + congr 1 + · have h1 := sumBits_starts hcw hS k false (fun x => search w (r * w) L f k + (bmC w S - barAt x 1 1 (k + 1)) (lab + (k + 1) * barAt x L 1 (k + 1))) + simp only [Bool.false_eq_true, if_false] at h1 + rw [h1, filter_filter] + apply sum_congr + · ext p + simp only [mem_filter] + constructor + · rintro ⟨hpX, hpd, hsub⟩ + refine ⟨hpX, ⟨(fits_iff hS hsub).mpr (by simp [hpd]), hsub⟩, hpd⟩ + · rintro ⟨hpX, ⟨-, hsub⟩, hpd⟩ + exact ⟨hpX, hpd, hsub⟩ + · intro p hp + rw [mem_filter] at hp + obtain ⟨-, ⟨-, hsub⟩, hpd⟩ := hp + have hst : step w p = 1 := by simp [step, hpd] + have hb : barAt (2 ^ idx w p) 1 1 (k + 1) = bmC w (cellsOf p (k + 1)) := by + have := barAt_cells hw1 (le_refl 1) p (k + 1) + simp only [hst, one_mul] at this + exact this + rw [hst, hb, bmC_sdiff hsub] + · by_cases hk : k = 0 + · subst hk + rw [show Nat.ble 1 0 = false from rfl, cond_false] + symm + apply sum_eq_zero + intro p hp + simp only [mem_filter] at hp + obtain ⟨⟨-, hf, -⟩, hpd⟩ := hp + obtain ⟨i, j, d⟩ := p + cases d + · simp at hpd + · simp [Fits] at hf + · have hb1 : Nat.ble 1 k = true := Nat.ble_eq_true_of_le (by omega) + rw [hb1, cond_true] + have h1 := sumBits_starts hcw hS k true (fun x => search w (r * w) L f k + (bmC w S - barAt x 1 w (k + 1)) (lab + (k + 1) * barAt x L w (k + 1))) + simp only [if_true] at h1 + rw [h1, filter_filter] + apply sum_congr + · ext p + simp only [mem_filter] + constructor + · rintro ⟨hpX, hpd, hsub⟩ + refine ⟨hpX, ⟨(fits_iff hS hsub).mpr (fun _ => by omega), hsub⟩, by simp [hpd]⟩ + · rintro ⟨hpX, ⟨-, hsub⟩, hpd⟩ + exact ⟨hpX, by simpa using hpd, hsub⟩ + · intro p hp + rw [mem_filter] at hp + obtain ⟨-, ⟨-, hsub⟩, hpd⟩ := hp + have hpd' : p.2.2 = true := by simpa using hpd + have hst : step w p = w := by simp [step, hpd'] + have hb : barAt (2 ^ idx w p) 1 w (k + 1) = bmC w (cellsOf p (k + 1)) := by + have := barAt_cells hw1 (le_refl 1) p (k + 1) + simp only [hst, one_mul] at this + exact this + rw [hst, hb, bmC_sdiff hsub] + +/-! ## Reading the labelling -/ + +/-- `∑_{p < n} (2 ^ L - 1) 2 ^ (L p) + 1 = 2 ^ (L n)`. -/ +private theorem geom_bound (L : ℕ) : ∀ n, ∑ p ∈ range n, (2 ^ L - 1) * 2 ^ (L * p) + 1 = 2 ^ (L * n) + | 0 => by simp + | n + 1 => by + rw [sum_range_succ, add_right_comm, geom_bound L n] + have h1 : 1 ≤ 2 ^ L := Nat.one_le_two_pow + have e : 2 ^ (L * (n + 1)) = 2 ^ L * 2 ^ (L * n) := by rw [← pow_add]; ring_nf + rw [e, Nat.sub_mul, one_mul] + have : 2 ^ (L * n) ≤ 2 ^ L * 2 ^ (L * n) := Nat.le_mul_of_pos_left _ (by positivity) + omega + +/-- `field` as division and remainder. -/ +private theorem field_eq (L X p : ℕ) : field L X p = X / 2 ^ (L * p) % 2 ^ L := by + simp only [field, Nat.land_eq, Nat.shiftRight_eq', Nat.shiftRight_eq_div_pow, + Nat.and_two_pow_sub_one_eq_mod] + +/-- Reading one field of a sum of fields. -/ +private theorem field_sum {L : ℕ} (T : Finset ℕ) (v : ℕ → ℕ) (hv : ∀ p ∈ T, v p < 2 ^ L) + {p0 : ℕ} (hp0 : p0 ∈ T) : field L (∑ p ∈ T, v p * 2 ^ (L * p)) p0 = v p0 := by + rw [field_eq] + rw [← sum_filter_add_sum_filter_not T (fun p => p < p0)] + have hT : T.filter (fun p => ¬ p < p0) = insert p0 (T.filter (fun p => p0 < p)) := by + ext p; simp only [mem_filter, mem_insert]; constructor + · rintro ⟨h1, h2⟩; by_cases e : p = p0 + · left; exact e + · right; exact ⟨h1, by omega⟩ + · rintro (h | ⟨h1, h2⟩) + · subst h; exact ⟨hp0, by omega⟩ + · exact ⟨h1, by omega⟩ + rw [hT, sum_insert (by simp)] + -- the low part + set A := ∑ p ∈ T.filter (fun p => p < p0), v p * 2 ^ (L * p) with hA + have hAlt : A < 2 ^ (L * p0) := by + have h1 : A ≤ ∑ p ∈ range p0, (2 ^ L - 1) * 2 ^ (L * p) := by + calc A ≤ ∑ p ∈ T.filter (fun p => p < p0), (2 ^ L - 1) * 2 ^ (L * p) := by + apply sum_le_sum + intro p hp + have := hv p (mem_filter.mp hp).1 + exact Nat.mul_le_mul_right _ (by omega) + _ ≤ ∑ p ∈ range p0, (2 ^ L - 1) * 2 ^ (L * p) := by + apply sum_le_sum_of_subset + intro p hp; simp only [mem_filter] at hp; simp [hp.2] + have h2 := geom_bound L p0 + omega + -- the high part + have hdvd : 2 ^ (L * p0) * 2 ^ L ∣ ∑ p ∈ T.filter (fun p => p0 < p), v p * 2 ^ (L * p) := by + apply dvd_sum + intro p hp + have h1 : p0 < p := (mem_filter.mp hp).2 + apply Dvd.dvd.mul_left + rw [← pow_add] + exact Nat.pow_dvd_pow 2 (by nlinarith) + obtain ⟨B, hB⟩ := hdvd + rw [hB] + have e : A + (v p0 * 2 ^ (L * p0) + 2 ^ (L * p0) * 2 ^ L * B) = + A + 2 ^ (L * p0) * (v p0 + 2 ^ L * B) := by ring + rw [e, Nat.add_mul_div_left _ _ (by positivity), Nat.div_eq_of_lt hAlt, zero_add, + Nat.add_mul_mod_self_left, Nat.mod_eq_of_lt (hv p0 hp0)] + +open Classical in +/-- The label of cell `x`: the length of the tile covering it. -/ +private noncomputable def lbl (k : ℕ) (P : ℕ → Pl) (x : ℕ × ℕ) : ℕ := + ∑ k' ∈ Icc 1 k, if inBar (P k') k' x.1 x.2 then k' else 0 + +open Classical in +/-- The labelling built along a partition of `S` writes the label of each cell of `S` in its +field. -/ +private theorem enc_formula {r c w L : ℕ} (hcw : c < w) (hL : 1 ≤ L) {P : ℕ → Pl} : + ∀ (k : ℕ) (S : Finset (ℕ × ℕ)), S ⊆ rectS r c → ValidOn r c k P S → + enc w L P k = ∑ x ∈ S, lbl k P x * 2 ^ (L * (x.1 * w + x.2)) + | 0, S, hS, hV => by + have : S = ∅ := by + ext ⟨a, b⟩ + simp only [Finset.notMem_empty, iff_false] + intro hab + obtain ⟨k', h1, h2, -⟩ := hV.2.2.1 a b hab + omega + subst this; simp [enc] + | k + 1, S, hS, hV => by + have hw1 : 1 ≤ w := by omega + obtain ⟨-, hsub, hV'⟩ := validOn_succ.mp hV + rw [enc, enc_formula hcw hL k _ (sdiff_subset.trans hS) hV', barAt_cells hw1 hL, mul_sum] + rw [← sum_sdiff hsub] + congr 1 + · apply sum_congr rfl + intro x hx + rw [mem_sdiff] at hx + obtain ⟨a, b⟩ := x + have hn : ¬ inBar (P (k + 1)) (k + 1) a b := fun h => hx.2 (mem_cellsOf.mpr h) + simp only [lbl] + rw [sum_Icc_succ_top (by omega), if_neg hn, add_zero] + · apply sum_congr rfl + intro x hx + obtain ⟨a, b⟩ := x + have hy : inBar (P (k + 1)) (k + 1) a b := mem_cellsOf.mp hx + simp only [lbl] + rw [sum_Icc_succ_top (by omega), if_pos hy, sum_eq_zero, zero_add] + intro k' hk' + rw [mem_Icc] at hk' + rw [if_neg] + intro h + have := hV'.2.1 k' a b hk'.1 hk'.2 h + exact (mem_sdiff.mp this).2 hx + +/-- In a partition, the label of a cell is the length of the tile covering it. -/ +private theorem lbl_eq {r c n : ℕ} {P : ℕ → Pl} {S : Finset (ℕ × ℕ)} (hV : ValidOn r c n P S) + {a b k : ℕ} (hk1 : 1 ≤ k) (hk2 : k ≤ n) (hin : inBar (P k) k a b) : lbl n P (a, b) = k := by + classical + simp only [lbl] + rw [sum_eq_single k] + · simp [hin] + · intro k' hk' hne + rw [mem_Icc] at hk' + rw [if_neg] + intro h + exact hne (hV.2.2.2 a b k' k hk'.1 hk'.2 hk1 hk2 h hin) + · intro h; exact absurd (mem_Icc.mpr ⟨hk1, hk2⟩) h + +/-- In a tiling, the field of cell `(a, b)` of the labelling is the length of its tile. -/ +private theorem field_cell {r c w n : ℕ} (hcw : c < w) (hn : 1 ≤ n) {P : ℕ → Pl} + (hV : Valid r c n P) {a b k : ℕ} (hab : a < r ∧ b < c) (hk1 : 1 ≤ k) (hk2 : k ≤ n) + (hin : inBar (P k) k a b) : field n (enc w n P n) (a * w + b) = k := by + have hw0 : 0 < w := by omega + rw [enc_formula hcw hn n _ (subset_refl _) hV] + have hinj : Set.InjOn (fun x : ℕ × ℕ => x.1 * w + x.2) (rectS r c : Set (ℕ × ℕ)) := by + intro x hx y hy hxy + have hx' := mem_rectS.mp (show (x.1, x.2) ∈ rectS r c from hx) + have hy' := mem_rectS.mp (show (y.1, y.2) ∈ rectS r c from hy) + obtain ⟨e1, e2⟩ := idx_inj (by omega) (by omega) hxy + exact Prod.ext e1 e2 + have hre : ∑ x ∈ rectS r c, lbl n P x * 2 ^ (n * (x.1 * w + x.2)) = + ∑ q ∈ (rectS r c).image (fun x => x.1 * w + x.2), lbl n P (q / w, q % w) * 2 ^ (n * q) := by + rw [sum_image hinj] + apply sum_congr rfl + intro x hx + obtain ⟨x1, x2⟩ := x + have hx' := mem_rectS.mp hx + have e1 : (x1 * w + x2) / w = x1 := by + rw [Nat.add_comm, Nat.add_mul_div_right _ _ hw0, Nat.div_eq_of_lt (by omega), zero_add] + have e2 : (x1 * w + x2) % w = x2 := by + rw [Nat.add_comm, Nat.add_mul_mod_self_right, Nat.mod_eq_of_lt (by omega)] + simp only [e1, e2] + rw [hre, field_sum] + · have e1 : (a * w + b) / w = a := by + rw [Nat.add_comm, Nat.add_mul_div_right _ _ hw0, Nat.div_eq_of_lt (by omega), zero_add] + have e2 : (a * w + b) % w = b := by + rw [Nat.add_comm, Nat.add_mul_mod_self_right, Nat.mod_eq_of_lt (by omega)] + rw [e1, e2, lbl_eq hV hk1 hk2 hin] + · intro q hq + obtain ⟨x, hx, rfl⟩ := mem_image.mp hq + obtain ⟨x1, x2⟩ := x + have hx' := mem_rectS.mp hx + have e1 : (x1 * w + x2) / w = x1 := by + rw [Nat.add_comm, Nat.add_mul_div_right _ _ hw0, Nat.div_eq_of_lt (by omega), zero_add] + have e2 : (x1 * w + x2) % w = x2 := by + rw [Nat.add_comm, Nat.add_mul_mod_self_right, Nat.mod_eq_of_lt (by omega)] + simp only [e1, e2] + obtain ⟨k', h1, h2, h3⟩ := hV.2.2.1 x1 x2 hx + rw [lbl_eq hV h1 h2 h3] + exact lt_of_le_of_lt h2 Nat.lt_two_pow_self + · exact mem_image.mpr ⟨(a, b), mem_rectS.mpr hab, rfl⟩ + +/-! ## No tiling has a non-trivial symmetry -/ + +/-- A conjunction over `j < n` written with the recursor gives each conjunct. -/ +private theorem rec_and {F : ℕ → Bool} : ∀ n, + Nat.rec (motive := fun _ => Bool) true (fun j ih => F j && ih) n = true → ∀ j < n, F j = true + | 0, _ => fun j hj => absurd hj (by omega) + | n + 1, h => by + have h' : (F n && Nat.rec (motive := fun _ => Bool) true (fun j ih => F j && ih) n) = true := + h + rw [Bool.and_eq_true] at h' + intro j hj + rcases Nat.lt_succ_iff_lt_or_eq.mp hj with hj | hj + · exact rec_and n h'.2 j hj + · subst hj; exact h'.1 + +/-- If `g` fixes the labelling, then the labels of `(i, j)` and `g (i, j)` agree. -/ +private theorem fixes_imp {r c w L : ℕ} {g : ℕ × ℕ → ℕ × ℕ} {lab : ℕ} + (h : fixes r c w L g lab = true) (i j : ℕ) (hi : i < r) (hj : j < c) : + field L lab ((g (i, j)).1 * w + (g (i, j)).2) = field L lab (i * w + j) := by + have h1 := rec_and (F := fun i => Nat.rec (motive := fun _ => Bool) true + (fun j ihj => Nat.beq (field L lab ((g (i, j)).1 * w + (g (i, j)).2)) + (field L lab (i * w + j)) && ihj) c) r h i hi + have h2 := rec_and (F := fun j => Nat.beq (field L lab ((g (i, j)).1 * w + (g (i, j)).2)) + (field L lab (i * w + j))) c h1 j hj + exact Nat.eq_of_beq_eq_true h2 + +/-- A bar that covers the cells `(0, b)` and `(r - 1, b)` is the vertical bar of length `r` in +column `b`. -/ +private theorem vert_full {r c : ℕ} {p : Pl} {k b : ℕ} (hr : 2 ≤ r) (hf : Fits r c p k) + (h1 : inBar p k 0 b) (h2 : inBar p k (r - 1) b) : p.2.1 = b ∧ k = r := by + obtain ⟨i, j, d⟩ := p + cases d <;> simp only [Fits, inBar, Bool.false_eq_true, if_false, if_true] at hf h1 h2 <;> + simp only <;> omega + +/-- A bar that covers the cells `(a, 0)` and `(a, c - 1)` is the horizontal bar of length `c` +in row `a`. -/ +private theorem horiz_full {r c : ℕ} {p : Pl} {k a : ℕ} (hc : 2 ≤ c) (hf : Fits r c p k) + (h1 : inBar p k a 0) (h2 : inBar p k a (c - 1)) : p.1 = a ∧ k = c := by + obtain ⟨i, j, d⟩ := p + cases d <;> simp only [Fits, inBar, Bool.false_eq_true, if_false, if_true] at hf h1 h2 <;> + simp only <;> omega + +/-- No bar covers two opposite corners of the rectangle. -/ +private theorem not_diag {r c : ℕ} {p : Pl} {k : ℕ} (hr : 2 ≤ r) (hc : 2 ≤ c) + (h1 : inBar p k 0 0) (h2 : inBar p k (r - 1) (c - 1)) : False := by + obtain ⟨i, j, d⟩ := p + cases d <;> simp only [inBar, Bool.false_eq_true, if_false, if_true] at h1 h2 <;> omega + +/-- **No symmetry.** For a non-square rectangle with at least two rows and columns, no +non-identity symmetry fixes a tiling: it would map each tile to the tile of the same length, i.e. +to itself, so two corners swapped by it would lie in one tile, which is impossible for the +half-turn and would give the same full-length tile at both ends for a reflection. -/ +private theorem stabCount_eq_one {r c w n : ℕ} (hcw : c < w) (hn : 1 ≤ n) (hr : 2 ≤ r) + (hc : 2 ≤ c) (hrc : r ≠ c) {P : ℕ → Pl} (hV : Valid r c n P) : + stabCount r c w n (enc w n P n) = 1 := by + have cover : ∀ a b, a < r → b < c → ∃ k', 1 ≤ k' ∧ k' ≤ n ∧ inBar (P k') k' a b := + fun a b ha hb => hV.2.2.1 a b (mem_rectS.mpr ⟨ha, hb⟩) + obtain ⟨k1, a1, b1, c1⟩ := cover 0 0 (by omega) (by omega) + obtain ⟨k2, a2, b2, c2⟩ := cover (r - 1) 0 (by omega) (by omega) + obtain ⟨k3, a3, b3, c3⟩ := cover 0 (c - 1) (by omega) (by omega) + obtain ⟨k4, a4, b4, c4⟩ := cover (r - 1) (c - 1) (by omega) (by omega) + have f1 := field_cell hcw hn hV ⟨by omega, by omega⟩ a1 b1 c1 + have f2 := field_cell hcw hn hV ⟨by omega, by omega⟩ a2 b2 c2 + have f3 := field_cell hcw hn hV ⟨by omega, by omega⟩ a3 b3 c3 + have f4 := field_cell hcw hn hV ⟨by omega, by omega⟩ a4 b4 c4 + simp only [zero_mul, zero_add, add_zero] at f1 f2 f3 f4 + have fit := hV.1 + have e1 : fixes r c w n (fun p => (r - 1 - p.1, p.2)) (enc w n P n) = false := by + by_contra hcon + rw [Bool.not_eq_false] at hcon + have h1 := fixes_imp hcon 0 0 (by omega) (by omega) + have h2 := fixes_imp hcon 0 (c - 1) (by omega) (by omega) + simp only [Nat.sub_zero, zero_mul, zero_add, add_zero] at h1 h2 + rw [f1, f2] at h1 + rw [f3, f4] at h2 + subst h1 h2 + obtain ⟨g1, g2⟩ := vert_full hr (fit k2 a2 b2) c1 c2 + obtain ⟨g3, g4⟩ := vert_full hr (fit k4 a4 b4) c3 c4 + have : k2 = k4 := by omega + subst this + omega + have e2 : fixes r c w n (fun p => (p.1, c - 1 - p.2)) (enc w n P n) = false := by + by_contra hcon + rw [Bool.not_eq_false] at hcon + have h1 := fixes_imp hcon 0 0 (by omega) (by omega) + have h2 := fixes_imp hcon (r - 1) 0 (by omega) (by omega) + simp only [Nat.sub_zero, zero_mul, zero_add, add_zero] at h1 h2 + rw [f1, f3] at h1 + rw [f2, f4] at h2 + subst h1 h2 + obtain ⟨g1, g2⟩ := horiz_full hc (fit k3 a3 b3) c1 c3 + obtain ⟨g3, g4⟩ := horiz_full hc (fit k4 a4 b4) c2 c4 + have : k3 = k4 := by omega + subst this + omega + have e3 : fixes r c w n (fun p => (r - 1 - p.1, c - 1 - p.2)) (enc w n P n) = false := by + by_contra hcon + rw [Bool.not_eq_false] at hcon + have h1 := fixes_imp hcon 0 0 (by omega) (by omega) + simp only [Nat.sub_zero, zero_mul, add_zero] at h1 + rw [f1, f4] at h1 + subst h1 + exact not_diag hr hc c1 c4 + simp only [stabCount, otherSymmetries, if_neg hrc, List.append_nil, e1, e2, e3, cond_false] + +/-- `∑_{b < c} 2 ^ b = 2 ^ c - 1`. -/ +private theorem sum_two_pow (c : ℕ) : ∑ b ∈ range c, 2 ^ b = 2 ^ c - 1 := by + induction c with + | zero => simp + | succ c ih => + rw [sum_range_succ, ih, pow_succ] + have := Nat.one_le_two_pow (n := c) + omega + +/-- `rectMask` is the bitmask of the rectangle. -/ +private theorem rectMask_eq (r c w : ℕ) : rectMask r c w = bmC w (rectS r c) := by + induction r with + | zero => simp [rectMask, bmC, rectS] + | succ r ih => + show rectMask r c w + (2 ^ c - 1) * 2 ^ (r * w) = _ + rw [ih] + simp only [bmC, rectS, sum_product, sum_range_succ] + congr 1 + simp only [pow_add, ← mul_sum, sum_two_pow] + ring + +open Classical in +/-- **The definition, made explicit.** For a non-square rectangle with at least two rows and +columns, the value computed by `a` is the number of tilings divided by `4`. -/ +private theorem search_count {r c n : ℕ} (hn : 1 ≤ n) (hr : 2 ≤ r) (hc : 2 ≤ c) (hrc : r ≠ c) : + search (c + 1) (r * (c + 1)) n (stabCount r c (c + 1) n) n (rectMask r c (c + 1)) 0 / + (1 + (otherSymmetries r c).length) = ((Univ r c n).filter (Valid r c n)).card / 4 := by + have hlen : (otherSymmetries r c).length = 3 := by simp [otherSymmetries, hrc] + rw [hlen, rectMask_eq, search_eq (by omega) _ n _ (subset_refl _) 0] + congr 1 + rw [card_filter] + apply sum_congr rfl + intro P _ + by_cases h : Valid r c n P + · have h' : ValidOn r c n P (rectS r c) := h + rw [if_pos h, if_pos h', zero_add, stabCount_eq_one (by omega) hn hr hc hrc h] + · have h' : ¬ ValidOn r c n P (rectS r c) := h + rw [if_neg h, if_neg h'] + +/-! ## Tilings: general facts -/ + +/-- Membership in a horizontal bar. -/ +private theorem inBar_h {p : Pl} (hd : p.2.2 = false) {k a b : ℕ} : + inBar p k a b ↔ a = p.1 ∧ p.2.1 ≤ b ∧ b < p.2.1 + k := by + simp [inBar, hd] + +/-- Membership in a vertical bar. -/ +private theorem inBar_v {p : Pl} (hd : p.2.2 = true) {k a b : ℕ} : + inBar p k a b ↔ b = p.2.1 ∧ p.1 ≤ a ∧ a < p.1 + k := by + simp [inBar, hd] + +/-- A horizontal bar fits. -/ +private theorem fits_h {r c : ℕ} {p : Pl} (hd : p.2.2 = false) {k : ℕ} : + Fits r c p k ↔ p.1 < r ∧ p.2.1 + k ≤ c := by + simp [Fits, hd] + +/-- A vertical bar fits. -/ +private theorem fits_v {r c : ℕ} {p : Pl} (hd : p.2.2 = true) {k : ℕ} : + Fits r c p k ↔ p.1 + k ≤ r ∧ p.2.1 < c ∧ 2 ≤ k := by + simp [Fits, hd] + +/-- In a tiling every tile fits. -/ +private theorem vfit {r c n : ℕ} {P : ℕ → Pl} (hV : Valid r c n P) {k : ℕ} (h1 : 1 ≤ k) + (h2 : k ≤ n) : Fits r c (P k) k := hV.1 k h1 h2 + +/-- In a tiling every cell is covered. -/ +private theorem vcover {r c n : ℕ} {P : ℕ → Pl} (hV : Valid r c n P) {a b : ℕ} (ha : a < r) + (hb : b < c) : ∃ k, 1 ≤ k ∧ k ≤ n ∧ inBar (P k) k a b := + hV.2.2.1 a b (mem_rectS.mpr ⟨ha, hb⟩) + +/-- In a tiling no cell is covered twice. -/ +private theorem vdisj {r c n : ℕ} {P : ℕ → Pl} (hV : Valid r c n P) {a b k1 k2 : ℕ} + (h1 : 1 ≤ k1) (h2 : k1 ≤ n) (h3 : 1 ≤ k2) (h4 : k2 ≤ n) + (hin1 : inBar (P k1) k1 a b) (hin2 : inBar (P k2) k2 a b) : k1 = k2 := + hV.2.2.2 a b k1 k2 h1 h2 h3 h4 hin1 hin2 + +/-- A tiling from fitting, covering and disjointness. -/ +private theorem valid_of {r c n : ℕ} {P : ℕ → Pl} + (hfit : ∀ k, 1 ≤ k → k ≤ n → Fits r c (P k) k) + (hcov : ∀ a b, a < r → b < c → ∃ k, 1 ≤ k ∧ k ≤ n ∧ inBar (P k) k a b) + (hdisj : ∀ a b k1 k2, 1 ≤ k1 → k1 ≤ n → 1 ≤ k2 → k2 ≤ n → + inBar (P k1) k1 a b → inBar (P k2) k2 a b → k1 = k2) : + Valid r c n P := + ⟨hfit, fun k _a _b h1 h2 hin => mem_rectS.mpr (inBar_lt (hfit k h1 h2) hin), + fun a b hab => hcov a b (mem_rectS.mp hab).1 (mem_rectS.mp hab).2, hdisj⟩ + +/-- A valid normalized assignment lies in `Univ`. -/ +private theorem mem_Univ_of {r c n : ℕ} {P : ℕ → Pl} (hV : Valid r c n P) + (hn : ∀ k, (k = 0 ∨ n < k) → P k = dflt) : P ∈ Univ r c n := by + rw [mem_Univ] + refine ⟨hn, fun k h1 h2 => ?_⟩ + have hf := vfit hV h1 h2 + simp only [Xs, mem_product, mem_range, mem_univ, and_true] + rcases hd : (P k).2.2 with _ | _ + · rw [fits_h hd] at hf; omega + · rw [fits_v hd] at hf; omega + +/-- Pigeonhole: an injection of `R` consecutive tiles into `R` rows hits every row. -/ +private theorem pigeon {R lo : ℕ} (f : ℕ → ℕ) (hf : ∀ k, lo ≤ k → k < lo + R → f k < R) + (hinj : ∀ k k', lo ≤ k → k < lo + R → lo ≤ k' → k' < lo + R → f k = f k' → k = k') : + ∀ a < R, ∃ k, lo ≤ k ∧ k < lo + R ∧ f k = a := by + classical + intro a ha + have hsub : (Finset.Ico lo (lo + R)).image f ⊆ Finset.range R := by + intro x hx + obtain ⟨k, hk, rfl⟩ := mem_image.mp hx + rw [mem_Ico] at hk + exact mem_range.mpr (hf k hk.1 hk.2) + have hcard : ((Finset.Ico lo (lo + R)).image f).card = R := by + rw [card_image_of_injOn] + · simp + · intro x hx y hy hxy + simp only [coe_Ico, Set.mem_Ico] at hx hy + exact hinj x y hx.1 hx.2 hy.1 hy.2 hxy + have heq := eq_of_subset_of_card_le hsub (by rw [hcard, card_range]) + have : a ∈ (Finset.Ico lo (lo + R)).image f := by rw [heq]; exact mem_range.mpr ha + obtain ⟨k, hk, rfl⟩ := mem_image.mp this + rw [mem_Ico] at hk + exact ⟨k, hk.1, hk.2, rfl⟩ + +/-- If `R` tiles are horizontal and all cross column `x`, every row holds one of them. -/ +private theorem rows_cover {R C N : ℕ} {P : ℕ → Pl} (hV : Valid R C N P) {lo x : ℕ} + (hlo : 1 ≤ lo) (hN : lo + R ≤ N + 1) + (hlong : ∀ k, lo ≤ k → k < lo + R → + (P k).2.2 = false ∧ (P k).2.1 ≤ x ∧ x < (P k).2.1 + k) : + ∀ a < R, ∃ k, lo ≤ k ∧ k < lo + R ∧ (P k).1 = a := by + apply pigeon (fun k => (P k).1) + · intro k h1 h2 + have hf := vfit hV (by omega) (show k ≤ N by omega) + rw [fits_h (hlong k h1 h2).1] at hf + exact hf.1 + · intro k k' h1 h2 h3 h4 he + obtain ⟨d1, e1, f1⟩ := hlong k h1 h2 + obtain ⟨d2, e2, f2⟩ := hlong k' h3 h4 + have he' : (P k).1 = (P k').1 := he + exact vdisj hV (a := (P k).1) (b := x) (by omega) (by omega) (by omega) (by omega) + (by rw [inBar_h d1]; omega) (by rw [inBar_h d2]; omega) + +/-- Tiles `≤ m` avoid a column all of whose cells lie in tiles `> m`. -/ +private theorem avoid_of_cover {R C N : ℕ} {P : ℕ → Pl} (hV : Valid R C N P) {m x : ℕ} + (hmN : m ≤ N) (hx : ∀ a < R, ∃ K, m < K ∧ K ≤ N ∧ inBar (P K) K a x) : + ∀ k, 1 ≤ k → k ≤ m → ∀ a b, inBar (P k) k a b → b ≠ x := by + intro k h1 h2 a b hin hb + subst hb + have hlt := inBar_lt (vfit hV h1 (show k ≤ N by omega)) hin + obtain ⟨K, hK1, hK2, hK⟩ := hx a hlt.1 + have := vdisj hV h1 (show k ≤ N by omega) (by omega) hK2 hin hK + omega + +/-- A horizontal bar avoiding column `x` lies entirely to its left or to its right. -/ +private theorem avoid_h {p : Pl} {k x : ℕ} (hd : p.2.2 = false) + (h : ∀ a b, inBar p k a b → b ≠ x) : p.2.1 + k ≤ x ∨ x < p.2.1 := by + by_contra hc + exact h p.1 x (by rw [inBar_h hd]; omega) rfl + +/-- A vertical bar avoiding column `x` is not in column `x`. -/ +private theorem avoid_v {p : Pl} {k x : ℕ} (hd : p.2.2 = true) (hk : 1 ≤ k) + (h : ∀ a b, inBar p k a b → b ≠ x) : p.2.1 ≠ x := by + intro e + exact h p.1 p.2.1 (by rw [inBar_v hd]; omega) e + +/-! ## Structure of the tilings of `(m + 1) × (2m + 1)` (tiles up to `2m + 1`) -/ + +/-- In a tiling of `(m + 1) × (2m + 1)`, tile `2m + 1` is a full row. -/ +private theorem s_top {m : ℕ} (hm : 1 ≤ m) {Q : ℕ → Pl} + (hQ : Valid (m + 1) (2 * m + 1) (2 * m + 1) Q) : + (Q (2 * m + 1)).2.2 = false ∧ (Q (2 * m + 1)).2.1 = 0 := by + have hf := vfit hQ (k := 2 * m + 1) (by omega) le_rfl + rcases hd : (Q (2 * m + 1)).2.2 with _ | _ + · rw [fits_h hd] at hf; exact ⟨rfl, by omega⟩ + · rw [fits_v hd] at hf; omega + +/-- In a tiling of `(m + 1) × (2m + 1)`, the tiles `m + 1, …, 2m + 1` are horizontal and cross the +middle column `m`. -/ +private theorem s_long {m : ℕ} (hm : 1 ≤ m) {Q : ℕ → Pl} + (hQ : Valid (m + 1) (2 * m + 1) (2 * m + 1) Q) : + ∀ k, m + 1 ≤ k → k ≤ 2 * m + 1 → + (Q k).2.2 = false ∧ (Q k).2.1 ≤ m ∧ m < (Q k).2.1 + k := by + intro k h1 h2 + have hf := vfit hQ (k := k) (by omega) h2 + rcases hd : (Q k).2.2 with _ | _ + · rw [fits_h hd] at hf; exact ⟨rfl, by omega, by omega⟩ + · rw [fits_v hd] at hf + exfalso + obtain ⟨t1, t2⟩ := s_top hm hQ + have ht := vfit hQ (k := 2 * m + 1) (by omega) le_rfl + rw [fits_h t1] at ht + have := vdisj hQ (a := (Q (2 * m + 1)).1) (b := (Q k).2.1) (k1 := k) (k2 := 2 * m + 1) + (by omega) h2 (by omega) le_rfl (by rw [inBar_v hd]; omega) (by rw [inBar_h t1]; omega) + omega + +/-- In a tiling of `(m + 1) × (2m + 1)`, every row holds one of the tiles `m + 1, …, 2m + 1`. -/ +private theorem s_rows {m : ℕ} (hm : 1 ≤ m) {Q : ℕ → Pl} + (hQ : Valid (m + 1) (2 * m + 1) (2 * m + 1) Q) : + ∀ a < m + 1, ∃ k, m + 1 ≤ k ∧ k < m + 1 + (m + 1) ∧ (Q k).1 = a := + rows_cover hQ (lo := m + 1) (x := m) (by omega) (by omega) + (fun k h1 h2 => s_long hm hQ k h1 (by omega)) + +/-- A placement of length `k` avoiding column `m`. -/ +private def AvM (m : ℕ) (q : Pl) (k : ℕ) : Prop := + (q.2.2 = false → q.2.1 + k ≤ m ∨ m < q.2.1) ∧ (q.2.2 = true → q.2.1 ≠ m) + +/-- In a tiling of `(m + 1) × (2m + 1)`, the tiles `1, …, m` avoid the middle column `m`. -/ +private theorem s_avm {m : ℕ} (hm : 1 ≤ m) {Q : ℕ → Pl} + (hQ : Valid (m + 1) (2 * m + 1) (2 * m + 1) Q) : + ∀ k, 1 ≤ k → k ≤ m → AvM m (Q k) k := by + have hcov : ∀ a < m + 1, ∃ K, m < K ∧ K ≤ 2 * m + 1 ∧ inBar (Q K) K a m := by + intro a ha + obtain ⟨K, h1, h2, h3⟩ := s_rows hm hQ a ha + obtain ⟨d, e, f⟩ := s_long hm hQ K h1 (by omega) + exact ⟨K, by omega, by omega, by rw [inBar_h d]; omega⟩ + have hav := avoid_of_cover hQ (by omega) hcov + intro k h1 h2 + refine ⟨fun hd => avoid_h hd (hav k h1 h2), fun hd => avoid_v hd h1 (hav k h1 h2)⟩ + +/-- In a tiling of `(m + 1) × (2m + 1)`, tile `2m` is horizontal, starts in column `0` or `1` and +lies in another row than tile `2m + 1`. -/ +private theorem s_two {m : ℕ} (hm : 1 ≤ m) {Q : ℕ → Pl} + (hQ : Valid (m + 1) (2 * m + 1) (2 * m + 1) Q) : + (Q (2 * m)).2.2 = false ∧ (Q (2 * m)).2.1 ≤ 1 ∧ (Q (2 * m)).1 ≠ (Q (2 * m + 1)).1 := by + obtain ⟨d1, e1, f1⟩ := s_long hm hQ (2 * m) (by omega) (by omega) + obtain ⟨d2, e2, f2⟩ := s_long hm hQ (2 * m + 1) (by omega) le_rfl + have hf := vfit hQ (k := 2 * m) (by omega) (by omega) + rw [fits_h d1] at hf + refine ⟨d1, by omega, fun he => ?_⟩ + have := vdisj hQ (a := (Q (2 * m)).1) (b := m) (k1 := 2 * m) (k2 := 2 * m + 1) + (by omega) (by omega) (by omega) le_rfl (by rw [inBar_h d1]; omega) + (by rw [inBar_h d2]; omega) + omega + +/-! ## Structure of the tilings of `(m + 1) × (2m + 3)` (tiles up to `2m + 2`) -/ + +/-- In a tiling of `(m + 1) × (2m + 3)`, the tiles `m + 2, …, 2m + 2` are horizontal and cross the +middle column `m + 1`. -/ +private theorem b_long {m : ℕ} {P : ℕ → Pl} (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) : + ∀ K, m + 2 ≤ K → K ≤ 2 * m + 2 → (P K).2.2 = false ∧ (P K).2.1 ≤ m + 1 ∧ + m + 1 < (P K).2.1 + K ∧ (P K).2.1 + K ≤ 2 * m + 3 := by + intro K h1 h2 + have hf := vfit hP (k := K) (by omega) h2 + rcases hd : (P K).2.2 with _ | _ + · rw [fits_h hd] at hf; exact ⟨rfl, by omega, by omega, by omega⟩ + · rw [fits_v hd] at hf; omega + +/-- In a tiling of `(m + 1) × (2m + 3)`, every row holds one of the tiles `m + 2, …, 2m + 2`. -/ +private theorem b_rows {m : ℕ} {P : ℕ → Pl} (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) : + ∀ a < m + 1, ∃ K, m + 2 ≤ K ∧ K < m + 2 + (m + 1) ∧ (P K).1 = a := + rows_cover hP (lo := m + 2) (x := m + 1) (by omega) (by omega) + (fun K h1 h2 => by + obtain ⟨a, b, c, -⟩ := b_long hP K h1 (by omega) + exact ⟨a, b, c⟩) + +/-- In a tiling of `(m + 1) × (2m + 3)`, a vertical tile `m + 1` is the first or the last column. -/ +private theorem b_vert {m : ℕ} (hm : 1 ≤ m) {P : ℕ → Pl} + (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) (hd : (P (m + 1)).2.2 = true) : + P (m + 1) = (0, 0, true) ∨ P (m + 1) = (0, 2 * m + 2, true) := by + have hf := vfit hP (k := m + 1) (by omega) (by omega) + rw [fits_v hd] at hf + obtain ⟨d2, e2, f2, g2⟩ := b_long hP (2 * m + 2) (by omega) le_rfl + have hf2 := vfit hP (k := 2 * m + 2) (by omega) le_rfl + rw [fits_h d2] at hf2 + have hno : ¬ ((P (2 * m + 2)).2.1 ≤ (P (m + 1)).2.1 ∧ + (P (m + 1)).2.1 < (P (2 * m + 2)).2.1 + (2 * m + 2)) := by + intro h + have := vdisj hP (a := (P (2 * m + 2)).1) (b := (P (m + 1)).2.1) (k1 := m + 1) + (k2 := 2 * m + 2) (by omega) (by omega) (by omega) le_rfl + (by rw [inBar_v hd]; omega) (by rw [inBar_h d2]; omega) + omega + have h1 : (P (m + 1)).1 = 0 := by omega + rcases Nat.lt_or_ge (P (m + 1)).2.1 1 with h | h + · left + have h2 : (P (m + 1)).2.1 = 0 := by omega + exact Prod.ext h1 (Prod.ext h2 hd) + · right + have h2 : (P (m + 1)).2.1 = 2 * m + 2 := by omega + exact Prod.ext h1 (Prod.ext h2 hd) + +/-- In a tiling of `(m + 1) × (2m + 3)`, a horizontal tile `m + 1` shares its row with tile +`m + 2`, and the two fill that row. -/ +private theorem b_horiz {m : ℕ} {P : ℕ → Pl} + (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) (hd : (P (m + 1)).2.2 = false) : + (P (m + 2)).2.2 = false ∧ (P (m + 2)).1 = (P (m + 1)).1 ∧ + (((P (m + 1)).2.1 = 0 ∧ (P (m + 2)).2.1 = m + 1) ∨ + ((P (m + 1)).2.1 = m + 2 ∧ (P (m + 2)).2.1 = 0)) := by + have hf := vfit hP (k := m + 1) (by omega) (by omega) + rw [fits_h hd] at hf + obtain ⟨K, hK1, hK2, hK3⟩ := b_rows hP (P (m + 1)).1 hf.1 + obtain ⟨d, e, f, g⟩ := b_long hP K hK1 (by omega) + have hno : ∀ b, ¬ ((P (m + 1)).2.1 ≤ b ∧ b < (P (m + 1)).2.1 + (m + 1) ∧ + (P K).2.1 ≤ b ∧ b < (P K).2.1 + K) := by + intro b h + have := vdisj hP (a := (P (m + 1)).1) (b := b) (k1 := m + 1) (k2 := K) (by omega) + (by omega) (by omega) (by omega) (by rw [inBar_h hd]; omega) (by rw [inBar_h d]; omega) + omega + have h1 := hno (P (m + 1)).2.1 + have h2 := hno (P K).2.1 + have hK : K = m + 2 := by omega + subst hK + exact ⟨d, hK3, by omega⟩ + +/-! ## Column maps between the two rectangles + +Small column `b` goes to big column `cB b`: the big rectangle has `e` extra columns on the left +and `δ` extra columns right after column `m + e`. `cF` goes back (the inserted columns go to the +small column `m`). -/ + +/-- Small column `j` as a column of the big rectangle. -/ +private def cB (m e δ j : ℕ) : ℕ := if j ≤ m then j + e else j + e + δ + +/-- Big column `j` as a column of the small rectangle (the inserted columns go to `m`). -/ +private def cF (m e δ j : ℕ) : ℕ := + if j ≤ m + e then j - e else if j ≤ m + e + δ then m else j - e - δ + +/-- A short tile of the small rectangle moved to the big rectangle. -/ +private def mvB (m e δ : ℕ) (p : Pl) : Pl := (p.1, cB m e δ p.2.1, p.2.2) + +/-- A short tile of the big rectangle moved to the small rectangle. -/ +private def mvF (m e δ : ℕ) (p : Pl) : Pl := (p.1, cF m e δ p.2.1, p.2.2) + +/-- A long tile of the small rectangle moved (and lengthened) to the big rectangle. -/ +private def lgB (e : ℕ) (p : Pl) : Pl := (p.1, p.2.1 + e, false) + +/-- A long tile of the big rectangle moved (and shortened) to the small rectangle. -/ +private def lgF (e : ℕ) (p : Pl) : Pl := (p.1, p.2.1 - e, false) + +/-- A placement of length `k` in the big rectangle avoiding the inserted columns. -/ +private def AvD (m e δ : ℕ) (p : Pl) (k : ℕ) : Prop := + e ≤ p.2.1 ∧ + (p.2.2 = false → (p.2.1 + k ≤ m + e ∨ m + e + δ < p.2.1) ∧ p.2.1 + k ≤ 2 * m + 1 + e + δ) ∧ + (p.2.2 = true → (p.2.1 < m + e ∨ m + e + δ < p.2.1) ∧ p.2.1 ≤ 2 * m + e + δ) + +/-- Membership in a moved short tile, read in the small rectangle. -/ +private theorem inBar_mvB {m e δ : ℕ} {q : Pl} {k a b : ℕ} (hq : AvM m q k) (he : e ≤ b) : + inBar (mvB m e δ q) k a b ↔ inBar q k a (cF m e δ b) := by + obtain ⟨i, j, d⟩ := q + unfold AvM at hq + cases d <;> simp only [mvB, cB, cF, inBar, Bool.false_eq_true, if_false, if_true, + forall_const] at hq ⊢ <;> split_ifs <;> omega + +/-- Membership in a lengthened long tile, read in the small rectangle. -/ +private theorem inBar_lgB {m e δ : ℕ} {q : Pl} {k a b : ℕ} (hd : q.2.2 = false) + (h1 : q.2.1 ≤ m) (h2 : m < q.2.1 + k) (he : e ≤ b) : + inBar (lgB e q) (k + δ) a b ↔ inBar q k a (cF m e δ b) := by + rw [inBar_h hd, inBar_h rfl] + simp only [lgB, cF] + split_ifs <;> omega + +/-- `cF` undoes `cB`. -/ +private theorem cF_cB (m e δ b : ℕ) : cF m e δ (cB m e δ b) = b := by + unfold cF cB; split_ifs <;> omega + +/-- `cB` skips the `e` extra columns on the left. -/ +private theorem le_cB (m e δ b : ℕ) : e ≤ cB m e δ b := by + unfold cB; split_ifs <;> omega + +/-- A short tile of the big rectangle avoiding the inserted columns moves to one avoiding the +middle column. -/ +private theorem avM_mvF {m e δ : ℕ} {p : Pl} {k : ℕ} (hp : AvD m e δ p k) : + AvM m (mvF m e δ p) k := by + obtain ⟨i, j, d⟩ := p + unfold AvD at hp + unfold AvM + cases d <;> simp only [mvF, cF, Bool.false_eq_true, Bool.true_eq_false, forall_const, + and_true, true_and, IsEmpty.forall_iff] at hp ⊢ <;> + split_ifs <;> omega + +/-- `mvB` undoes `mvF` on tiles avoiding the inserted columns. -/ +private theorem mvB_mvF {m e δ : ℕ} {p : Pl} {k : ℕ} (hp : AvD m e δ p k) : + mvB m e δ (mvF m e δ p) = p := by + obtain ⟨i, j, d⟩ := p + unfold AvD at hp + simp only [mvB, mvF, cB, cF, Prod.mk.injEq, true_and, and_true] + cases d <;> simp only [Bool.false_eq_true, Bool.true_eq_false, forall_const, + and_true, true_and, IsEmpty.forall_iff] at hp <;> split_ifs <;> omega + +/-- `mvF` undoes `mvB`. -/ +private theorem mvF_mvB (m e δ : ℕ) (q : Pl) : mvF m e δ (mvB m e δ q) = q := by + simp only [mvF, mvB, cF_cB] + +/-- `lgB` undoes `lgF` on horizontal tiles starting after the `e` extra columns. -/ +private theorem lgB_lgF {e : ℕ} {p : Pl} (hd : p.2.2 = false) (he : e ≤ p.2.1) : + lgB e (lgF e p) = p := by + obtain ⟨i, j, d⟩ := p + simp only at hd he + subst hd + simp only [lgB, lgF, Prod.mk.injEq, true_and, and_true] + omega + +/-- `lgF` undoes `lgB` on horizontal tiles. -/ +private theorem lgF_lgB {e : ℕ} {q : Pl} (hd : q.2.2 = false) : lgF e (lgB e q) = q := by + obtain ⟨i, j, d⟩ := q + simp only at hd + subst hd + simp [lgB, lgF] + +/-- A moved short tile avoids the inserted columns. -/ +private theorem avD_mvB {m e δ : ℕ} {q : Pl} {k : ℕ} (hq : AvM m q k) + (hf : Fits (m + 1) (2 * m + 1) q k) : AvD m e δ (mvB m e δ q) k := by + obtain ⟨i, j, d⟩ := q + unfold AvM at hq + unfold AvD + cases d <;> simp only [mvB, cB, Fits, Bool.false_eq_true, Bool.true_eq_false, if_false, + if_true, forall_const, and_true, true_and, IsEmpty.forall_iff] at hq hf ⊢ <;> + split_ifs <;> omega + +/-- A moved short tile fits in the big rectangle. -/ +private theorem fits_mvB {m e δ : ℕ} (hed : e + δ ≤ 2) {q : Pl} {k : ℕ} (hq : AvM m q k) + (hf : Fits (m + 1) (2 * m + 1) q k) : Fits (m + 1) (2 * m + 3) (mvB m e δ q) k := by + obtain ⟨i, j, d⟩ := q + unfold AvM at hq + cases d <;> simp only [mvB, cB, Fits, Bool.false_eq_true, Bool.true_eq_false, if_false, + if_true, forall_const, and_true, true_and, IsEmpty.forall_iff] at hq hf ⊢ <;> + split_ifs <;> omega + +/-- A moved short tile fits in the small rectangle. -/ +private theorem fits_mvF {m e δ : ℕ} {p : Pl} {k : ℕ} (hp : AvD m e δ p k) + (hf : Fits (m + 1) (2 * m + 3) p k) : Fits (m + 1) (2 * m + 1) (mvF m e δ p) k := by + obtain ⟨i, j, d⟩ := p + unfold AvD at hp + cases d <;> simp only [mvF, cF, Fits, Bool.false_eq_true, Bool.true_eq_false, if_false, + if_true, forall_const, and_true, true_and, IsEmpty.forall_iff] at hp hf ⊢ <;> + split_ifs <;> omega + +/-- Membership in a moved short tile, read in the big rectangle. -/ +private theorem inBar_mvF {m e δ : ℕ} {p : Pl} {k a b : ℕ} (hp : AvD m e δ p k) : + inBar (mvF m e δ p) k a b ↔ inBar p k a (cB m e δ b) := by + conv_rhs => rw [← mvB_mvF hp] + rw [inBar_mvB (avM_mvF hp) (le_cB m e δ b), cF_cB] + +/-- Membership in a shortened long tile, read in the big rectangle. -/ +private theorem inBar_lgF {m e δ : ℕ} {p : Pl} {k a b : ℕ} (hd : p.2.2 = false) + (he : e ≤ p.2.1) (h1 : p.2.1 ≤ m + e) (h2 : m + e < p.2.1 + k) : + inBar (lgF e p) k a b ↔ inBar p (k + δ) a (cB m e δ b) := by + conv_rhs => rw [← lgB_lgF hd he] + rw [inBar_lgB (m := m) (δ := δ) rfl (by simp only [lgF]; omega) (by simp only [lgF]; omega) + (le_cB m e δ b), cF_cB] + +/-! ## The two classes of tilings of the big rectangle -/ + +/-- Class `V`: tile `m + 1` is the vertical bar in column `s` (`s = 0`, `e = 1` or +`s = 2m + 2`, `e = 0`). -/ +private theorem bV_long {m e s : ℕ} (hes : (e = 1 ∧ s = 0) ∨ (e = 0 ∧ s = 2 * m + 2)) + {P : ℕ → Pl} (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) + (hc : P (m + 1) = (0, s, true)) : + ∀ K, m + 2 ≤ K → K ≤ 2 * m + 2 → (P K).2.2 = false ∧ e ≤ (P K).2.1 ∧ + (P K).2.1 ≤ m + e ∧ m + e < (P K).2.1 + (K - 1) ∧ (P K).2.1 + K ≤ 2 * m + 2 + e := by + intro K h1 h2 + obtain ⟨d, e1, f, g⟩ := b_long hP K h1 h2 + have hf := vfit hP (k := K) (by omega) h2 + rw [fits_h d] at hf + have hno : ¬ ((P K).2.1 ≤ s ∧ s < (P K).2.1 + K) := by + intro h + have := vdisj hP (a := (P K).1) (b := s) (k1 := m + 1) (k2 := K) (by omega) (by omega) + (by omega) h2 (by rw [hc, inBar_v rfl]; simp only [true_and]; omega) + (by rw [inBar_h d]; omega) + omega + refine ⟨d, ?_⟩ + omega + +/-- Class `V`: the tiles `1, …, m` avoid the removed columns. -/ +private theorem bV_avd {m e s : ℕ} (hes : (e = 1 ∧ s = 0) ∨ (e = 0 ∧ s = 2 * m + 2)) + {P : ℕ → Pl} (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) + (hc : P (m + 1) = (0, s, true)) : + ∀ k, 1 ≤ k → k ≤ m → AvD m e 1 (P k) k := by + have hlong := bV_long hes hP hc + have hcol : ∀ x, m + e ≤ x → x ≤ m + 1 + e → + ∀ a < m + 1, ∃ K, m < K ∧ K ≤ 2 * m + 2 ∧ inBar (P K) K a x := by + intro x hx1 hx2 a ha + obtain ⟨K, h1, h2, h3⟩ := b_rows hP a ha + obtain ⟨d, e1, f, g, -⟩ := hlong K h1 (by omega) + exact ⟨K, by omega, by omega, by rw [inBar_h d]; omega⟩ + have hs : ∀ a < m + 1, ∃ K, m < K ∧ K ≤ 2 * m + 2 ∧ inBar (P K) K a s := by + intro a ha + exact ⟨m + 1, by omega, by omega, by rw [hc, inBar_v rfl]; simp only [true_and]; omega⟩ + have A1 := avoid_of_cover hP (by omega) (hcol (m + e) le_rfl (by omega)) + have A2 := avoid_of_cover hP (by omega) (hcol (m + 1 + e) (by omega) le_rfl) + have A3 := avoid_of_cover hP (by omega) hs + intro k h1 h2 + have hf := vfit hP (k := k) h1 (by omega) + unfold AvD + rcases hd : (P k).2.2 with _ | _ + · rw [fits_h hd] at hf + have B1 := avoid_h hd (A1 k h1 h2) + have B2 := avoid_h hd (A2 k h1 h2) + have B3 := avoid_h hd (A3 k h1 h2) + exact ⟨by omega, fun _ => ⟨by omega, by omega⟩, fun h => by simp at h⟩ + · rw [fits_v hd] at hf + have B1 := avoid_v hd h1 (A1 k h1 h2) + have B2 := avoid_v hd h1 (A2 k h1 h2) + have B3 := avoid_v hd h1 (A3 k h1 h2) + exact ⟨by omega, fun h => by simp at h, fun _ => ⟨by omega, by omega⟩⟩ + +/-- Class `H`: tile `m + 1` is horizontal, starting in column `u` (`0` or `m + 2`); then tile +`m + 2` fills the rest of its row, from column `v`. -/ +private theorem bH_pair {m u v : ℕ} (huv : (u = 0 ∧ v = m + 1) ∨ (u = m + 2 ∧ v = 0)) + {P : ℕ → Pl} (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) + (hc : (P (m + 1)).2.2 = false ∧ (P (m + 1)).2.1 = u) : + (P (m + 2)).2.2 = false ∧ (P (m + 2)).1 = (P (m + 1)).1 ∧ (P (m + 2)).2.1 = v := by + obtain ⟨d, e, f⟩ := b_horiz hP hc.1 + exact ⟨d, e, by omega⟩ + +/-- In a tiling of `(m + 1) × (2m + 3)`, the tiles `m + 3, …, 2m + 2` cross the middle columns +`m, m + 1, m + 2`. -/ +private theorem bH_long {m : ℕ} {P : ℕ → Pl} (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) : + ∀ K, m + 3 ≤ K → K ≤ 2 * m + 2 → (P K).2.2 = false ∧ (P K).2.1 ≤ m ∧ + m < (P K).2.1 + (K - 2) := by + intro K h1 h2 + obtain ⟨d, e, f, g⟩ := b_long hP K (by omega) h2 + exact ⟨d, by omega, by omega⟩ + +/-- Class `H`: the tiles `1, …, m` avoid the removed columns. -/ +private theorem bH_avd {m u v : ℕ} (huv : (u = 0 ∧ v = m + 1) ∨ (u = m + 2 ∧ v = 0)) + {P : ℕ → Pl} (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) + (hc : (P (m + 1)).2.2 = false ∧ (P (m + 1)).2.1 = u) : + ∀ k, 1 ≤ k → k ≤ m → AvD m 0 2 (P k) k := by + obtain ⟨p1, p2, p3⟩ := bH_pair huv hP hc + have hf1 := vfit hP (k := m + 1) (by omega) (by omega) + rw [fits_h hc.1] at hf1 + have hcol : ∀ x, m ≤ x → x ≤ m + 2 → + ∀ a < m + 1, ∃ K, m < K ∧ K ≤ 2 * m + 2 ∧ inBar (P K) K a x := by + intro x hx1 hx2 a ha + by_cases hai : a = (P (m + 1)).1 + · rcases huv with ⟨hu, hv⟩ | ⟨hu, hv⟩ + · by_cases hx : x = m + · exact ⟨m + 1, by omega, by omega, by rw [inBar_h hc.1]; omega⟩ + · exact ⟨m + 2, by omega, by omega, by rw [inBar_h p1]; omega⟩ + · by_cases hx : x = m + 2 + · exact ⟨m + 1, by omega, by omega, by rw [inBar_h hc.1]; omega⟩ + · exact ⟨m + 2, by omega, by omega, by rw [inBar_h p1]; omega⟩ + · obtain ⟨K, h1, h2, h3⟩ := b_rows hP a ha + have hK : K ≠ m + 2 := by rintro rfl; exact hai (h3.symm.trans p2) + obtain ⟨d, e1, f⟩ := bH_long hP K (by omega) (by omega) + exact ⟨K, by omega, by omega, by rw [inBar_h d]; omega⟩ + have A1 := avoid_of_cover hP (by omega) (hcol m le_rfl (by omega)) + have A2 := avoid_of_cover hP (by omega) (hcol (m + 1) (by omega) (by omega)) + have A3 := avoid_of_cover hP (by omega) (hcol (m + 2) (by omega) le_rfl) + intro k h1 h2 + have hf := vfit hP (k := k) h1 (by omega) + unfold AvD + rcases hd : (P k).2.2 with _ | _ + · rw [fits_h hd] at hf + have B1 := avoid_h hd (A1 k h1 h2) + have B2 := avoid_h hd (A2 k h1 h2) + have B3 := avoid_h hd (A3 k h1 h2) + exact ⟨by omega, fun _ => ⟨by omega, by omega⟩, fun h => by simp at h⟩ + · rw [fits_v hd] at hf + have B1 := avoid_v hd h1 (A1 k h1 h2) + have B2 := avoid_v hd h1 (A2 k h1 h2) + have B3 := avoid_v hd h1 (A3 k h1 h2) + exact ⟨by omega, fun h => by simp at h, fun _ => ⟨by omega, by omega⟩⟩ + +/-! ## Class `V`: remove the vertical bar `m + 1` and one of the two middle columns -/ + +/-- From a big tiling of class `V` to a small tiling. -/ +private def PhiV (m e : ℕ) (P : ℕ → Pl) (k : ℕ) : Pl := + if k = 0 then dflt else if k ≤ m then mvF m e 1 (P k) + else if k ≤ 2 * m + 1 then lgF e (P (k + 1)) else dflt + +/-- From a small tiling to a big tiling of class `V`. -/ +private def PsiV (m e s : ℕ) (Q : ℕ → Pl) (k : ℕ) : Pl := + if k = 0 then dflt else if k ≤ m then mvB m e 1 (Q k) + else if k = m + 1 then (0, s, true) + else if k ≤ 2 * m + 2 then lgB e (Q (k - 1)) else dflt + +/-- `PhiV` maps tilings of class `V` to tilings of the small rectangle. -/ +private theorem phiV_valid {m e s : ℕ} (hes : (e = 1 ∧ s = 0) ∨ (e = 0 ∧ s = 2 * m + 2)) + {P : ℕ → Pl} (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) + (hc : P (m + 1) = (0, s, true)) : + Valid (m + 1) (2 * m + 1) (2 * m + 1) (PhiV m e P) := by + have hlong := bV_long hes hP hc + have havd := bV_avd hes hP hc + have hmem : ∀ k, 1 ≤ k → k ≤ 2 * m + 1 → ∀ a b, inBar (PhiV m e P k) k a b ↔ + inBar (P (if k ≤ m then k else k + 1)) (if k ≤ m then k else k + 1) a (cB m e 1 b) := by + intro k h1 h2 a b + by_cases hkm : k ≤ m + · simp only [PhiV, if_neg (show k ≠ 0 by omega), if_pos hkm] + exact inBar_mvF (havd k h1 hkm) + · simp only [PhiV, if_neg (show k ≠ 0 by omega), if_neg hkm, if_pos h2] + obtain ⟨d, e1, f, g, -⟩ := hlong (k + 1) (by omega) (by omega) + exact inBar_lgF d e1 f (by omega) + apply valid_of + · intro k h1 h2 + by_cases hkm : k ≤ m + · simp only [PhiV, if_neg (show k ≠ 0 by omega), if_pos hkm] + exact fits_mvF (havd k h1 hkm) (vfit hP h1 (by omega)) + · simp only [PhiV, if_neg (show k ≠ 0 by omega), if_neg hkm, if_pos h2] + obtain ⟨d, e1, f, g, h⟩ := hlong (k + 1) (by omega) (by omega) + have hf := vfit hP (k := k + 1) (by omega) (by omega) + rw [fits_h d] at hf + rw [fits_h rfl] + simp only [lgF] + omega + · intro a b ha hb + have hσ : cB m e 1 b < 2 * m + 3 := by unfold cB; split_ifs <;> omega + obtain ⟨K, hK1, hK2, hin⟩ := vcover hP ha hσ + by_cases hKm : K ≤ m + · refine ⟨K, hK1, by omega, (hmem K hK1 (by omega) a b).mpr ?_⟩ + rw [if_pos hKm]; exact hin + · by_cases hKs : K = m + 1 + · exfalso + subst hKs + rw [hc, inBar_v rfl] at hin + simp only at hin + unfold cB at hin + split_ifs at hin <;> omega + · refine ⟨K - 1, by omega, by omega, (hmem (K - 1) (by omega) (by omega) a b).mpr ?_⟩ + rw [if_neg (by omega), show K - 1 + 1 = K by omega]; exact hin + · intro a b k1 k2 h1 h2 h3 h4 hin1 hin2 + rw [hmem k1 h1 h2] at hin1 + rw [hmem k2 h3 h4] at hin2 + have := vdisj hP (by split_ifs <;> omega) (by split_ifs <;> omega) (by split_ifs <;> omega) + (by split_ifs <;> omega) hin1 hin2 + split_ifs at this <;> omega + +/-- Membership in the tiles of `PsiV`, read in the small rectangle. -/ +private theorem psiV_mem {m e s : ℕ} (hm : 1 ≤ m) {Q : ℕ → Pl} + (hQ : Valid (m + 1) (2 * m + 1) (2 * m + 1) Q) : + ∀ K, 1 ≤ K → K ≤ 2 * m + 2 → K ≠ m + 1 → ∀ a b, e ≤ b → + (inBar (PsiV m e s Q K) K a b ↔ inBar (Q (if K ≤ m then K else K - 1)) + (if K ≤ m then K else K - 1) a (cF m e 1 b)) := by + have hl := s_long hm hQ + have havm := s_avm hm hQ + intro K h1 h2 h3 a b hb + by_cases hKm : K ≤ m + · simp only [PsiV, if_neg (show K ≠ 0 by omega), if_pos hKm] + exact inBar_mvB (havm K h1 hKm) hb + · simp only [PsiV, if_neg (show K ≠ 0 by omega), if_neg hKm, if_neg h3, if_pos h2] + obtain ⟨d, e1, f⟩ := hl (K - 1) (by omega) (by omega) + have := inBar_lgB (m := m) (e := e) (δ := 1) (k := K - 1) (a := a) d e1 f hb + rw [show K - 1 + 1 = K by omega] at this + exact this + +/-- The tiles of `PsiV` other than `m + 1` avoid the extra columns and column `s`. -/ +private theorem psiV_col {m e s : ℕ} (hm : 1 ≤ m) + (hes : (e = 1 ∧ s = 0) ∨ (e = 0 ∧ s = 2 * m + 2)) {Q : ℕ → Pl} + (hQ : Valid (m + 1) (2 * m + 1) (2 * m + 1) Q) : + ∀ K, 1 ≤ K → K ≤ 2 * m + 2 → K ≠ m + 1 → ∀ a b, inBar (PsiV m e s Q K) K a b → + e ≤ b ∧ b ≠ s := by + intro K h1 h2 h3 a b hin + have heb : e ≤ b := by + by_cases hKm : K ≤ m + · simp only [PsiV, if_neg (show K ≠ 0 by omega), if_pos hKm] at hin + have := le_cB m e 1 (Q K).2.1 + rcases hd : (Q K).2.2 with _ | _ + · rw [inBar_h (show (mvB m e 1 (Q K)).2.2 = false from hd)] at hin + simp only [mvB] at hin + omega + · rw [inBar_v (show (mvB m e 1 (Q K)).2.2 = true from hd)] at hin + simp only [mvB] at hin + omega + · simp only [PsiV, if_neg (show K ≠ 0 by omega), if_neg hKm, if_neg h3, if_pos h2] at hin + rw [inBar_h rfl] at hin + simp only [lgB] at hin + omega + refine ⟨heb, fun hbs => ?_⟩ + rw [psiV_mem hm hQ K h1 h2 h3 a b heb] at hin + have hlt := inBar_lt (vfit hQ (by split_ifs <;> omega) (by split_ifs <;> omega)) hin + rcases hes with ⟨rfl, rfl⟩ | ⟨rfl, rfl⟩ + · omega + · subst hbs + unfold cF at hlt + split_ifs at hlt <;> omega + +/-- `PsiV` maps tilings of the small rectangle to tilings of the big one. -/ +private theorem psiV_valid {m e s : ℕ} (hm : 1 ≤ m) + (hes : (e = 1 ∧ s = 0) ∨ (e = 0 ∧ s = 2 * m + 2)) {Q : ℕ → Pl} + (hQ : Valid (m + 1) (2 * m + 1) (2 * m + 1) Q) : + Valid (m + 1) (2 * m + 3) (2 * m + 2) (PsiV m e s Q) := by + have hl := s_long hm hQ + have havm := s_avm hm hQ + have hmem := psiV_mem (e := e) (s := s) hm hQ + have hcol := psiV_col hm hes hQ + have hsp : ∀ a b, inBar (PsiV m e s Q (m + 1)) (m + 1) a b ↔ b = s ∧ a < m + 1 := by + intro a b + simp only [PsiV, if_neg (show m + 1 ≠ 0 by omega), if_neg (show ¬ m + 1 ≤ m by omega), + if_true] + rw [inBar_v rfl] + simp only + omega + apply valid_of + · intro K h1 h2 + by_cases hKm : K ≤ m + · simp only [PsiV, if_neg (show K ≠ 0 by omega), if_pos hKm] + exact fits_mvB (by omega) (havm K h1 hKm) (vfit hQ h1 (by omega)) + · by_cases hKs : K = m + 1 + · subst hKs + simp only [PsiV, if_neg (show m + 1 ≠ 0 by omega), if_neg (show ¬ m + 1 ≤ m by omega), + if_true] + rw [fits_v rfl] + simp only + omega + · simp only [PsiV, if_neg (show K ≠ 0 by omega), if_neg hKm, if_neg hKs, if_pos h2] + obtain ⟨d, e1, f⟩ := hl (K - 1) (by omega) (by omega) + have hf := vfit hQ (k := K - 1) (by omega) (by omega) + rw [fits_h d] at hf + rw [fits_h rfl] + simp only [lgB] + omega + · intro a b ha hb + by_cases hbs : b = s + · exact ⟨m + 1, by omega, by omega, (hsp a b).mpr ⟨hbs, ha⟩⟩ + · have heb : e ≤ b := by omega + have hcf : cF m e 1 b < 2 * m + 1 := by unfold cF; split_ifs <;> omega + obtain ⟨k, hk1, hk2, hin⟩ := vcover hQ ha hcf + by_cases hkm : k ≤ m + · refine ⟨k, hk1, by omega, (hmem k hk1 (by omega) (by omega) a b heb).mpr ?_⟩ + rw [if_pos hkm]; exact hin + · refine ⟨k + 1, by omega, by omega, + (hmem (k + 1) (by omega) (by omega) (by omega) a b heb).mpr ?_⟩ + rw [if_neg (by omega), show k + 1 - 1 = k by omega]; exact hin + · intro a b K1 K2 h1 h2 h3 h4 hin1 hin2 + by_cases hK1 : K1 = m + 1 + · by_cases hK2 : K2 = m + 1 + · omega + · exfalso + have := hcol K2 h3 h4 hK2 a b hin2 + subst hK1 + have := (hsp a b).mp hin1 + omega + · by_cases hK2 : K2 = m + 1 + · exfalso + have := hcol K1 h1 h2 hK1 a b hin1 + subst hK2 + have := (hsp a b).mp hin2 + omega + · have c1 := hcol K1 h1 h2 hK1 a b hin1 + have c2 := hcol K2 h3 h4 hK2 a b hin2 + rw [hmem K1 h1 h2 hK1 a b c1.1] at hin1 + rw [hmem K2 h3 h4 hK2 a b c2.1] at hin2 + have := vdisj hQ (by split_ifs <;> omega) (by split_ifs <;> omega) + (by split_ifs <;> omega) (by split_ifs <;> omega) hin1 hin2 + split_ifs at this <;> omega + +/-- `PsiV` undoes `PhiV` on tilings of class `V`. -/ +private theorem psiV_phiV {m e s : ℕ} (hes : (e = 1 ∧ s = 0) ∨ (e = 0 ∧ s = 2 * m + 2)) + {P : ℕ → Pl} (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) + (hn : ∀ k, (k = 0 ∨ 2 * m + 2 < k) → P k = dflt) (hc : P (m + 1) = (0, s, true)) : + PsiV m e s (PhiV m e P) = P := by + have hlong := bV_long hes hP hc + have havd := bV_avd hes hP hc + funext k + by_cases hk0 : k = 0 + · subst hk0; simp only [PsiV, if_true]; exact (hn 0 (Or.inl rfl)).symm + by_cases hkm : k ≤ m + · simp only [PsiV, PhiV, if_neg hk0, if_pos hkm] + exact mvB_mvF (havd k (by omega) hkm) + by_cases hks : k = m + 1 + · subst hks; simp only [PsiV, if_neg hk0, if_neg hkm, if_true]; exact hc.symm + by_cases hk2 : k ≤ 2 * m + 2 + · simp only [PsiV, if_neg hk0, if_neg hkm, if_neg hks, if_pos hk2] + simp only [PhiV, if_neg (show k - 1 ≠ 0 by omega), if_neg (show ¬ k - 1 ≤ m by omega), + if_pos (show k - 1 ≤ 2 * m + 1 by omega), show k - 1 + 1 = k by omega] + obtain ⟨d, e1, -⟩ := hlong k (by omega) hk2 + exact lgB_lgF d e1 + · simp only [PsiV, if_neg hk0, if_neg hkm, if_neg hks, if_neg hk2] + exact (hn k (Or.inr (by omega))).symm + +/-- `PhiV` undoes `PsiV`. -/ +private theorem phiV_psiV {m e s : ℕ} (hm : 1 ≤ m) {Q : ℕ → Pl} + (hQ : Valid (m + 1) (2 * m + 1) (2 * m + 1) Q) + (hn : ∀ k, (k = 0 ∨ 2 * m + 1 < k) → Q k = dflt) : PhiV m e (PsiV m e s Q) = Q := by + have hl := s_long hm hQ + funext k + by_cases hk0 : k = 0 + · subst hk0; simp only [PhiV, if_true]; exact (hn 0 (Or.inl rfl)).symm + by_cases hkm : k ≤ m + · simp only [PhiV, PsiV, if_neg hk0, if_pos hkm]; exact mvF_mvB m e 1 (Q k) + by_cases hk2 : k ≤ 2 * m + 1 + · simp only [PhiV, if_neg hk0, if_neg hkm, if_pos hk2] + simp only [PsiV, if_neg (show k + 1 ≠ 0 by omega), if_neg (show ¬ k + 1 ≤ m by omega), + if_neg (show k + 1 ≠ m + 1 by omega), if_pos (show k + 1 ≤ 2 * m + 2 by omega), + Nat.add_sub_cancel] + exact lgF_lgB (hl k (by omega) hk2).1 + · simp only [PhiV, if_neg hk0, if_neg hkm, if_neg hk2] + exact (hn k (Or.inr (by omega))).symm + +open Classical in +/-- Class `V` (with tile `m + 1` in a given end column) has as many tilings as the small +rectangle. -/ +private theorem card_classV {m e s : ℕ} (hm : 1 ≤ m) + (hes : (e = 1 ∧ s = 0) ∨ (e = 0 ∧ s = 2 * m + 2)) : + ((Univ (m + 1) (2 * m + 3) (2 * m + 2)).filter + (fun P => Valid (m + 1) (2 * m + 3) (2 * m + 2) P ∧ P (m + 1) = (0, s, true))).card = + ((Univ (m + 1) (2 * m + 1) (2 * m + 1)).filter + (Valid (m + 1) (2 * m + 1) (2 * m + 1))).card := by + apply card_nbij' (PhiV m e) (PsiV m e s) + · intro P hP + rw [mem_coe, mem_filter] at hP ⊢ + obtain ⟨hU, hV, hc⟩ := hP + have hV' := phiV_valid hes hV hc + refine ⟨mem_Univ_of hV' (fun k hk => ?_), hV'⟩ + simp only [PhiV] + split_ifs <;> first | rfl | (exfalso; omega) + · intro Q hQ + rw [mem_coe, mem_filter] at hQ ⊢ + obtain ⟨hU, hV⟩ := hQ + have hV' := psiV_valid hm hes hV + refine ⟨mem_Univ_of hV' (fun k hk => ?_), hV', ?_⟩ + · simp only [PsiV] + split_ifs <;> first | rfl | (exfalso; omega) + · simp only [PsiV, if_neg (show m + 1 ≠ 0 by omega), if_neg (show ¬ m + 1 ≤ m by omega), + if_true] + · intro P hP + rw [mem_coe, mem_filter] at hP + obtain ⟨hU, hV, hc⟩ := hP + exact psiV_phiV hes hV (mem_Univ.mp hU).1 hc + · intro Q hQ + rw [mem_coe, mem_filter] at hQ + obtain ⟨hU, hV⟩ := hQ + exact phiV_psiV hm hV (mem_Univ.mp hU).1 + +/-! ## Class `H`: merge the bars `m + 1`, `m + 2` into one row and remove two middle columns -/ + +/-- From a big tiling of class `H` to a small tiling. -/ +private def PhiH (m : ℕ) (P : ℕ → Pl) (k : ℕ) : Pl := + if k = 0 then dflt else if k ≤ m then mvF m 0 2 (P k) + else if k ≤ 2 * m then lgF 0 (P (k + 2)) + else if k = 2 * m + 1 then ((P (m + 1)).1, 0, false) else dflt + +/-- From a small tiling to a big tiling of class `H`. -/ +private def PsiH (m u v : ℕ) (Q : ℕ → Pl) (k : ℕ) : Pl := + if k = 0 then dflt else if k ≤ m then mvB m 0 2 (Q k) + else if k = m + 1 then ((Q (2 * m + 1)).1, u, false) + else if k = m + 2 then ((Q (2 * m + 1)).1, v, false) + else if k ≤ 2 * m + 2 then lgB 0 (Q (k - 2)) else dflt + +/-- `PhiH` maps tilings of class `H` to tilings of the small rectangle. -/ +private theorem phiH_valid {m u v : ℕ} (huv : (u = 0 ∧ v = m + 1) ∨ (u = m + 2 ∧ v = 0)) + {P : ℕ → Pl} (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) + (hc : (P (m + 1)).2.2 = false ∧ (P (m + 1)).2.1 = u) : + Valid (m + 1) (2 * m + 1) (2 * m + 1) (PhiH m P) := by + have hlong := bH_long hP + have havd := bH_avd huv hP hc + obtain ⟨p1, p2, p3⟩ := bH_pair huv hP hc + have hf1 := vfit hP (k := m + 1) (by omega) (by omega) + rw [fits_h hc.1] at hf1 + have hmem : ∀ k, 1 ≤ k → k ≤ 2 * m → ∀ a b, inBar (PhiH m P k) k a b ↔ + inBar (P (if k ≤ m then k else k + 2)) (if k ≤ m then k else k + 2) a (cB m 0 2 b) := by + intro k h1 h2 a b + by_cases hkm : k ≤ m + · simp only [PhiH, if_neg (show k ≠ 0 by omega), if_pos hkm] + exact inBar_mvF (havd k h1 hkm) + · simp only [PhiH, if_neg (show k ≠ 0 by omega), if_neg hkm, if_pos h2] + obtain ⟨d, e1, f⟩ := hlong (k + 2) (by omega) (by omega) + exact inBar_lgF d (Nat.zero_le _) (by omega) (by omega) + have htop : ∀ a b, inBar (PhiH m P (2 * m + 1)) (2 * m + 1) a b ↔ + a = (P (m + 1)).1 ∧ b < 2 * m + 1 := by + intro a b + simp only [PhiH, if_neg (show 2 * m + 1 ≠ 0 by omega), if_neg (show ¬ 2 * m + 1 ≤ m by omega), + if_neg (show ¬ 2 * m + 1 ≤ 2 * m by omega), if_true] + rw [inBar_h rfl] + simp only + omega + -- the cells of the special row, read in the big rectangle + have hrow : ∀ a b, b < 2 * m + 1 → a = (P (m + 1)).1 → + ∃ K, (K = m + 1 ∨ K = m + 2) ∧ inBar (P K) K a (cB m 0 2 b) := by + intro a b hb ha + unfold cB + rcases huv with ⟨hu, hv⟩ | ⟨hu, hv⟩ + · by_cases hbm : b ≤ m + · exact ⟨m + 1, Or.inl rfl, by rw [inBar_h hc.1, if_pos hbm]; omega⟩ + · exact ⟨m + 2, Or.inr rfl, by rw [inBar_h p1, if_neg hbm]; omega⟩ + · by_cases hbm : b ≤ m + · exact ⟨m + 2, Or.inr rfl, by rw [inBar_h p1, if_pos hbm]; omega⟩ + · exact ⟨m + 1, Or.inl rfl, by rw [inBar_h hc.1, if_neg hbm]; omega⟩ + apply valid_of + · intro k h1 h2 + by_cases hkm : k ≤ m + · simp only [PhiH, if_neg (show k ≠ 0 by omega), if_pos hkm] + exact fits_mvF (havd k h1 hkm) (vfit hP h1 (by omega)) + · by_cases hk2 : k ≤ 2 * m + · simp only [PhiH, if_neg (show k ≠ 0 by omega), if_neg hkm, if_pos hk2] + obtain ⟨d, e1, f⟩ := hlong (k + 2) (by omega) (by omega) + have hf := vfit hP (k := k + 2) (by omega) (by omega) + rw [fits_h d] at hf + rw [fits_h rfl] + simp only [lgF] + omega + · have hk : k = 2 * m + 1 := by omega + subst hk + simp only [PhiH, if_neg (show 2 * m + 1 ≠ 0 by omega), if_neg hkm, if_neg hk2, if_true] + rw [fits_h rfl] + simp only + omega + · intro a b ha hb + have hσ : cB m 0 2 b < 2 * m + 3 := by unfold cB; split_ifs <;> omega + obtain ⟨K, hK1, hK2, hin⟩ := vcover hP ha hσ + by_cases hKm : K ≤ m + · refine ⟨K, hK1, by omega, (hmem K hK1 (by omega) a b).mpr ?_⟩ + rw [if_pos hKm]; exact hin + · by_cases hKs : K = m + 1 ∨ K = m + 2 + · refine ⟨2 * m + 1, by omega, le_rfl, (htop a b).mpr ⟨?_, hb⟩⟩ + rcases hKs with rfl | rfl + · rw [inBar_h hc.1] at hin; exact hin.1 + · rw [inBar_h p1] at hin; rw [hin.1, p2] + · refine ⟨K - 2, by omega, by omega, (hmem (K - 2) (by omega) (by omega) a b).mpr ?_⟩ + rw [if_neg (by omega), show K - 2 + 2 = K by omega]; exact hin + · intro a b k1 k2 h1 h2 h3 h4 hin1 hin2 + have key : ∀ k, 1 ≤ k → k ≤ 2 * m → inBar (PhiH m P k) k a b → + inBar (PhiH m P (2 * m + 1)) (2 * m + 1) a b → False := by + intro k hk1 hk2 hk hs + rw [hmem k hk1 hk2] at hk + obtain ⟨ha, hb⟩ := (htop a b).mp hs + obtain ⟨K, hK, hKin⟩ := hrow a b hb ha + have := vdisj hP (by split_ifs <;> omega) (by split_ifs <;> omega) + (show 1 ≤ K by omega) (show K ≤ 2 * m + 2 by omega) hk hKin + split_ifs at this <;> omega + by_cases e1 : k1 = 2 * m + 1 + · by_cases e2 : k2 = 2 * m + 1 + · omega + · subst e1; exact (key k2 h3 (by omega) hin2 hin1).elim + · by_cases e2 : k2 = 2 * m + 1 + · subst e2; exact (key k1 h1 (by omega) hin1 hin2).elim + · rw [hmem k1 h1 (by omega)] at hin1 + rw [hmem k2 h3 (by omega)] at hin2 + have := vdisj hP (by split_ifs <;> omega) (by split_ifs <;> omega) + (by split_ifs <;> omega) (by split_ifs <;> omega) hin1 hin2 + split_ifs at this <;> omega + +/-- Membership in the tiles of `PsiH` other than `m + 1`, `m + 2`, read in the small rectangle. -/ +private theorem psiH_mem {m u v : ℕ} (hm : 1 ≤ m) {Q : ℕ → Pl} + (hQ : Valid (m + 1) (2 * m + 1) (2 * m + 1) Q) : + ∀ K, 1 ≤ K → K ≤ 2 * m + 2 → K ≠ m + 1 → K ≠ m + 2 → ∀ a b, + (inBar (PsiH m u v Q K) K a b ↔ inBar (Q (if K ≤ m then K else K - 2)) + (if K ≤ m then K else K - 2) a (cF m 0 2 b)) := by + have hl := s_long hm hQ + have havm := s_avm hm hQ + intro K h1 h2 h3 h4 a b + by_cases hKm : K ≤ m + · simp only [PsiH, if_neg (show K ≠ 0 by omega), if_pos hKm] + exact inBar_mvB (havm K h1 hKm) (Nat.zero_le _) + · simp only [PsiH, if_neg (show K ≠ 0 by omega), if_neg hKm, if_neg h3, if_neg h4, if_pos h2] + obtain ⟨d, e1, f⟩ := hl (K - 2) (by omega) (by omega) + have := inBar_lgB (m := m) (e := 0) (δ := 2) (k := K - 2) (a := a) d e1 f (Nat.zero_le b) + rw [show K - 2 + 2 = K by omega] at this + exact this + +/-- `PsiH` maps tilings of the small rectangle to tilings of the big one. -/ +private theorem psiH_valid {m u v : ℕ} (hm : 1 ≤ m) + (huv : (u = 0 ∧ v = m + 1) ∨ (u = m + 2 ∧ v = 0)) {Q : ℕ → Pl} + (hQ : Valid (m + 1) (2 * m + 1) (2 * m + 1) Q) : + Valid (m + 1) (2 * m + 3) (2 * m + 2) (PsiH m u v Q) := by + have hl := s_long hm hQ + have havm := s_avm hm hQ + obtain ⟨t1, t2⟩ := s_top hm hQ + have ht := vfit hQ (k := 2 * m + 1) (by omega) le_rfl + rw [fits_h t1] at ht + have hmem := psiH_mem (u := u) (v := v) hm hQ + have hs1 : ∀ a b, inBar (PsiH m u v Q (m + 1)) (m + 1) a b ↔ + a = (Q (2 * m + 1)).1 ∧ u ≤ b ∧ b < u + (m + 1) := by + intro a b + simp only [PsiH, if_neg (show m + 1 ≠ 0 by omega), if_neg (show ¬ m + 1 ≤ m by omega), + if_true] + rw [inBar_h rfl] + have hs2 : ∀ a b, inBar (PsiH m u v Q (m + 2)) (m + 2) a b ↔ + a = (Q (2 * m + 1)).1 ∧ v ≤ b ∧ b < v + (m + 2) := by + intro a b + simp only [PsiH, if_neg (show m + 2 ≠ 0 by omega), if_neg (show ¬ m + 2 ≤ m by omega), + if_neg (show m + 2 ≠ m + 1 by omega), if_true] + rw [inBar_h rfl] + -- small tiles other than the full row avoid its row + have hrow : ∀ k, 1 ≤ k → k ≤ 2 * m → ∀ b, ¬ inBar (Q k) k (Q (2 * m + 1)).1 b := by + intro k h1 h2 b hin + have hlt := inBar_lt (vfit hQ h1 (by omega)) hin + have := vdisj hQ h1 (by omega) (show 1 ≤ 2 * m + 1 by omega) le_rfl hin + (by rw [inBar_h t1]; omega) + omega + apply valid_of + · intro K h1 h2 + by_cases hKm : K ≤ m + · simp only [PsiH, if_neg (show K ≠ 0 by omega), if_pos hKm] + exact fits_mvB (by omega) (havm K h1 hKm) (vfit hQ h1 (by omega)) + · by_cases hK1 : K = m + 1 + · subst hK1 + simp only [PsiH, if_neg (show m + 1 ≠ 0 by omega), if_neg hKm, if_true] + rw [fits_h rfl] + simp only + omega + · by_cases hK2 : K = m + 2 + · subst hK2 + simp only [PsiH, if_neg (show m + 2 ≠ 0 by omega), if_neg hKm, if_neg hK1, if_true] + rw [fits_h rfl] + simp only + omega + · simp only [PsiH, if_neg (show K ≠ 0 by omega), if_neg hKm, if_neg hK1, if_neg hK2, + if_pos h2] + obtain ⟨d, e1, f⟩ := hl (K - 2) (by omega) (by omega) + have hf := vfit hQ (k := K - 2) (by omega) (by omega) + rw [fits_h d] at hf + rw [fits_h rfl] + simp only [lgB] + omega + · intro a b ha hb + by_cases hai : a = (Q (2 * m + 1)).1 + · rcases huv with ⟨hu, hv⟩ | ⟨hu, hv⟩ + · by_cases hbm : b ≤ m + · exact ⟨m + 1, by omega, by omega, (hs1 a b).mpr ⟨hai, by omega, by omega⟩⟩ + · exact ⟨m + 2, by omega, by omega, (hs2 a b).mpr ⟨hai, by omega, by omega⟩⟩ + · by_cases hbm : b ≤ m + 1 + · exact ⟨m + 2, by omega, by omega, (hs2 a b).mpr ⟨hai, by omega, by omega⟩⟩ + · exact ⟨m + 1, by omega, by omega, (hs1 a b).mpr ⟨hai, by omega, by omega⟩⟩ + · have hcf : cF m 0 2 b < 2 * m + 1 := by unfold cF; split_ifs <;> omega + obtain ⟨k, hk1, hk2, hin⟩ := vcover hQ ha hcf + have hk2' : k ≤ 2 * m := by + by_contra hcon + have hk : k = 2 * m + 1 := by omega + subst hk + rw [inBar_h t1] at hin + exact hai hin.1 + by_cases hkm : k ≤ m + · refine ⟨k, hk1, by omega, (hmem k hk1 (by omega) (by omega) (by omega) a b).mpr ?_⟩ + rw [if_pos hkm]; exact hin + · refine ⟨k + 2, by omega, by omega, + (hmem (k + 2) (by omega) (by omega) (by omega) (by omega) a b).mpr ?_⟩ + rw [if_neg (by omega), show k + 2 - 2 = k by omega]; exact hin + · intro a b K1 K2 h1 h2 h3 h4 hin1 hin2 + have hspec : ∀ K, (K = m + 1 ∨ K = m + 2) → inBar (PsiH m u v Q K) K a b → + a = (Q (2 * m + 1)).1 := by + rintro K (rfl | rfl) hin + · exact ((hs1 a b).mp hin).1 + · exact ((hs2 a b).mp hin).1 + have hother : ∀ K, 1 ≤ K → K ≤ 2 * m + 2 → K ≠ m + 1 → K ≠ m + 2 → + inBar (PsiH m u v Q K) K a b → a ≠ (Q (2 * m + 1)).1 := by + intro K h1 h2 h3 h4 hin ha + rw [hmem K h1 h2 h3 h4] at hin + rw [ha] at hin + exact hrow _ (by split_ifs <;> omega) (by split_ifs <;> omega) _ hin + by_cases s1 : K1 = m + 1 ∨ K1 = m + 2 + · have ha := hspec K1 s1 hin1 + by_cases s2 : K2 = m + 1 ∨ K2 = m + 2 + · rcases s1 with rfl | rfl <;> rcases s2 with rfl | rfl + · rfl + · have := (hs1 a b).mp hin1; have := (hs2 a b).mp hin2; omega + · have := (hs2 a b).mp hin1; have := (hs1 a b).mp hin2; omega + · rfl + · exact absurd ha (hother K2 h3 h4 (by omega) (by omega) hin2) + · by_cases s2 : K2 = m + 1 ∨ K2 = m + 2 + · exact absurd (hspec K2 s2 hin2) (hother K1 h1 h2 (by omega) (by omega) hin1) + · rw [hmem K1 h1 h2 (by omega) (by omega)] at hin1 + rw [hmem K2 h3 h4 (by omega) (by omega)] at hin2 + have := vdisj hQ (by split_ifs <;> omega) (by split_ifs <;> omega) + (by split_ifs <;> omega) (by split_ifs <;> omega) hin1 hin2 + split_ifs at this <;> omega + +/-- `PsiH` undoes `PhiH` on tilings of class `H`. -/ +private theorem psiH_phiH {m u v : ℕ} (huv : (u = 0 ∧ v = m + 1) ∨ (u = m + 2 ∧ v = 0)) + {P : ℕ → Pl} (hP : Valid (m + 1) (2 * m + 3) (2 * m + 2) P) + (hn : ∀ k, (k = 0 ∨ 2 * m + 2 < k) → P k = dflt) + (hc : (P (m + 1)).2.2 = false ∧ (P (m + 1)).2.1 = u) : + PsiH m u v (PhiH m P) = P := by + have hlong := bH_long hP + have havd := bH_avd huv hP hc + obtain ⟨p1, p2, p3⟩ := bH_pair huv hP hc + funext k + by_cases hk0 : k = 0 + · subst hk0; simp only [PsiH, if_true]; exact (hn 0 (Or.inl rfl)).symm + by_cases hkm : k ≤ m + · simp only [PsiH, PhiH, if_neg hk0, if_pos hkm] + exact mvB_mvF (havd k (by omega) hkm) + by_cases hk1 : k = m + 1 + · subst hk1 + simp only [PsiH, if_neg hk0, if_neg hkm, if_true] + simp only [PhiH, if_neg (show 2 * m + 1 ≠ 0 by omega), + if_neg (show ¬ 2 * m + 1 ≤ m by omega), if_neg (show ¬ 2 * m + 1 ≤ 2 * m by omega), + if_true] + exact Prod.ext rfl (Prod.ext hc.2.symm hc.1.symm) + by_cases hk2 : k = m + 2 + · subst hk2 + simp only [PsiH, if_neg hk0, if_neg hkm, if_neg hk1, if_true] + simp only [PhiH, if_neg (show 2 * m + 1 ≠ 0 by omega), + if_neg (show ¬ 2 * m + 1 ≤ m by omega), if_neg (show ¬ 2 * m + 1 ≤ 2 * m by omega), + if_true] + exact Prod.ext p2.symm (Prod.ext p3.symm p1.symm) + by_cases hk3 : k ≤ 2 * m + 2 + · simp only [PsiH, if_neg hk0, if_neg hkm, if_neg hk1, if_neg hk2, if_pos hk3] + simp only [PhiH, if_neg (show k - 2 ≠ 0 by omega), if_neg (show ¬ k - 2 ≤ m by omega), + if_pos (show k - 2 ≤ 2 * m by omega), show k - 2 + 2 = k by omega] + obtain ⟨d, -, -⟩ := hlong k (by omega) hk3 + exact lgB_lgF d (Nat.zero_le _) + · simp only [PsiH, if_neg hk0, if_neg hkm, if_neg hk1, if_neg hk2, if_neg hk3] + exact (hn k (Or.inr (by omega))).symm + +/-- `PhiH` undoes `PsiH`. -/ +private theorem phiH_psiH {m u v : ℕ} (hm : 1 ≤ m) {Q : ℕ → Pl} + (hQ : Valid (m + 1) (2 * m + 1) (2 * m + 1) Q) + (hn : ∀ k, (k = 0 ∨ 2 * m + 1 < k) → Q k = dflt) : PhiH m (PsiH m u v Q) = Q := by + have hl := s_long hm hQ + obtain ⟨t1, t2⟩ := s_top hm hQ + funext k + by_cases hk0 : k = 0 + · subst hk0; simp only [PhiH, if_true]; exact (hn 0 (Or.inl rfl)).symm + by_cases hkm : k ≤ m + · simp only [PhiH, PsiH, if_neg hk0, if_pos hkm]; exact mvF_mvB m 0 2 (Q k) + by_cases hk2 : k ≤ 2 * m + · simp only [PhiH, if_neg hk0, if_neg hkm, if_pos hk2] + simp only [PsiH, if_neg (show k + 2 ≠ 0 by omega), if_neg (show ¬ k + 2 ≤ m by omega), + if_neg (show k + 2 ≠ m + 1 by omega), if_neg (show k + 2 ≠ m + 2 by omega), + if_pos (show k + 2 ≤ 2 * m + 2 by omega), Nat.add_sub_cancel] + exact lgF_lgB (hl k (by omega) (by omega)).1 + by_cases hk3 : k = 2 * m + 1 + · subst hk3 + simp only [PhiH, if_neg hk0, if_neg hkm, if_neg hk2, if_true] + simp only [PsiH, if_neg (show m + 1 ≠ 0 by omega), if_neg (show ¬ m + 1 ≤ m by omega), + if_true] + exact Prod.ext rfl (Prod.ext t2.symm t1.symm) + · simp only [PhiH, if_neg hk0, if_neg hkm, if_neg hk2, if_neg hk3] + exact (hn k (Or.inr (by omega))).symm + +open Classical in +/-- Class `H` (with tile `m + 1` at a given end of its row) has as many tilings as the small +rectangle. -/ +private theorem card_classH {m u v : ℕ} (hm : 1 ≤ m) + (huv : (u = 0 ∧ v = m + 1) ∨ (u = m + 2 ∧ v = 0)) : + ((Univ (m + 1) (2 * m + 3) (2 * m + 2)).filter + (fun P => Valid (m + 1) (2 * m + 3) (2 * m + 2) P ∧ + ((P (m + 1)).2.2 = false ∧ (P (m + 1)).2.1 = u))).card = + ((Univ (m + 1) (2 * m + 1) (2 * m + 1)).filter + (Valid (m + 1) (2 * m + 1) (2 * m + 1))).card := by + apply card_nbij' (PhiH m) (PsiH m u v) + · intro P hP + rw [mem_coe, mem_filter] at hP ⊢ + obtain ⟨hU, hV, hc⟩ := hP + have hV' := phiH_valid huv hV hc + refine ⟨mem_Univ_of hV' (fun k hk => ?_), hV'⟩ + simp only [PhiH] + split_ifs <;> first | rfl | (exfalso; omega) + · intro Q hQ + rw [mem_coe, mem_filter] at hQ ⊢ + obtain ⟨hU, hV⟩ := hQ + have hV' := psiH_valid hm huv hV + refine ⟨mem_Univ_of hV' (fun k hk => ?_), hV', ?_⟩ + · simp only [PsiH] + split_ifs <;> first | rfl | (exfalso; omega) + · simp only [PsiH, if_neg (show m + 1 ≠ 0 by omega), if_neg (show ¬ m + 1 ≤ m by omega), + if_true] + exact ⟨trivial, trivial⟩ + · intro P hP + rw [mem_coe, mem_filter] at hP + obtain ⟨hU, hV, hc⟩ := hP + exact psiH_phiH huv hV (mem_Univ.mp hU).1 hc + · intro Q hQ + rw [mem_coe, mem_filter] at hQ + obtain ⟨hU, hV⟩ := hQ + exact phiH_psiH hm hV (mem_Univ.mp hU).1 + +/-! ## Counting: the big rectangle has four times as many tilings -/ + +open Classical in +/-- **The big rectangle has four times as many tilings**: they split into four classes (tile +`m + 1` is the first or the last column, or lies at the left or the right end of its row), each +in bijection with the tilings of the small rectangle. -/ +private theorem card_big {m : ℕ} (hm : 1 ≤ m) : + ((Univ (m + 1) (2 * m + 3) (2 * m + 2)).filter + (Valid (m + 1) (2 * m + 3) (2 * m + 2))).card = + 4 * ((Univ (m + 1) (2 * m + 1) (2 * m + 1)).filter + (Valid (m + 1) (2 * m + 1) (2 * m + 1))).card := by + have c1 := card_classV hm (e := 1) (s := 0) (Or.inl ⟨rfl, rfl⟩) + have c2 := card_classV hm (e := 0) (s := 2 * m + 2) (Or.inr ⟨rfl, rfl⟩) + have c3 := card_classH hm (u := 0) (v := m + 1) (Or.inl ⟨rfl, rfl⟩) + have c4 := card_classH hm (u := m + 2) (v := 0) (Or.inr ⟨rfl, rfl⟩) + rw [show ∀ x : ℕ, 4 * x = x + x + x + x from fun x => by ring] + nth_rw 1 [← c1] + nth_rw 1 [← c2] + nth_rw 1 [← c3] + nth_rw 1 [← c4] + simp only [card_filter, ← sum_add_distrib] + apply sum_congr rfl + intro P _ + by_cases hV : Valid (m + 1) (2 * m + 3) (2 * m + 2) P + · rcases hdd : (P (m + 1)).2.2 with _ | _ + · obtain ⟨-, -, hj⟩ := b_horiz hV hdd + have n1 : ¬ P (m + 1) = (0, 0, true) := fun h => by rw [h] at hdd; simp at hdd + have n2 : ¬ P (m + 1) = (0, 2 * m + 2, true) := fun h => by rw [h] at hdd; simp at hdd + rcases hj with ⟨hj, -⟩ | ⟨hj, -⟩ + · rw [if_pos hV, if_neg (fun h => n1 h.2), if_neg (fun h => n2 h.2), + if_pos ⟨hV, rfl, hj⟩, if_neg (fun h => by omega)] + · rw [if_pos hV, if_neg (fun h => n1 h.2), if_neg (fun h => n2 h.2), + if_neg (fun h => by omega), if_pos ⟨hV, rfl, hj⟩] + · rcases b_vert hm hV hdd with h | h + · rw [if_pos hV, if_pos ⟨hV, h⟩, if_neg (fun h' => by rw [h] at h'; simp at h'), + if_neg (fun h' => absurd h'.2.1 (by simp)), if_neg (fun h' => absurd h'.2.1 (by simp))] + · rw [if_pos hV, if_neg (fun h' => by rw [h] at h'; simp at h'), if_pos ⟨hV, h⟩, + if_neg (fun h' => absurd h'.2.1 (by simp)), if_neg (fun h' => absurd h'.2.1 (by simp))] + · rw [if_neg hV, if_neg (fun h => hV h.1), if_neg (fun h => hV h.1), if_neg (fun h => hV h.1), + if_neg (fun h => hV h.1)] + +/-! ## Counting: the small rectangle has a multiple of four tilings -/ + +/-- Reflection in the horizontal axis. -/ +private def hFlip (m : ℕ) (P : ℕ → Pl) (k : ℕ) : Pl := + if k = 0 ∨ 2 * m + 1 < k then dflt + else if (P k).2.2 = true then (m + 1 - k - (P k).1, (P k).2.1, true) + else (m - (P k).1, (P k).2.1, false) + +/-- Reflection in the vertical axis. -/ +private def vFlip (m : ℕ) (P : ℕ → Pl) (k : ℕ) : Pl := + if k = 0 ∨ 2 * m + 1 < k then dflt + else if (P k).2.2 = true then ((P k).1, 2 * m - (P k).2.1, true) + else ((P k).1, 2 * m + 1 - k - (P k).2.1, false) + +/-- Transporting a tiling along a map of the rectangle. -/ +private theorem valid_transfer {r c n : ℕ} {P Q : ℕ → Pl} (hP : Valid r c n P) + (φ : ℕ → ℕ → ℕ × ℕ) (hφ : ∀ a b, a < r → b < c → (φ a b).1 < r ∧ (φ a b).2 < c) + (hfit : ∀ k, 1 ≤ k → k ≤ n → Fits r c (Q k) k) + (hmem : ∀ k, 1 ≤ k → k ≤ n → ∀ a b, a < r → b < c → + (inBar (Q k) k a b ↔ inBar (P k) k (φ a b).1 (φ a b).2)) : + Valid r c n Q := by + apply valid_of hfit + · intro a b ha hb + obtain ⟨k, h1, h2, hin⟩ := vcover hP (hφ a b ha hb).1 (hφ a b ha hb).2 + exact ⟨k, h1, h2, (hmem k h1 h2 a b ha hb).mpr hin⟩ + · intro a b k1 k2 h1 h2 h3 h4 hin1 hin2 + have hab := inBar_lt (hfit k1 h1 h2) hin1 + exact vdisj hP h1 h2 h3 h4 ((hmem k1 h1 h2 a b hab.1 hab.2).mp hin1) + ((hmem k2 h3 h4 a b hab.1 hab.2).mp hin2) + +/-- The reflection in the horizontal axis maps tilings to tilings. -/ +private theorem hFlip_valid {m : ℕ} {P : ℕ → Pl} + (hP : Valid (m + 1) (2 * m + 1) (2 * m + 1) P) : + Valid (m + 1) (2 * m + 1) (2 * m + 1) (hFlip m P) := by + apply valid_transfer hP (fun a b => (m - a, b)) (fun a b ha hb => by simp only; omega) + · intro k h1 h2 + have hf := vfit hP h1 h2 + simp only [hFlip, if_neg (show ¬ (k = 0 ∨ 2 * m + 1 < k) by omega)] + rcases hd : (P k).2.2 with _ | _ + · rw [fits_h hd] at hf + simp only [Bool.false_eq_true, if_false] + rw [fits_h rfl]; simp only; omega + · rw [fits_v hd] at hf + simp only [if_true] + rw [fits_v rfl]; simp only; omega + · intro k h1 h2 a b ha hb + have hf := vfit hP h1 h2 + simp only [hFlip, if_neg (show ¬ (k = 0 ∨ 2 * m + 1 < k) by omega)] + rcases hd : (P k).2.2 with _ | _ + · rw [fits_h hd] at hf + simp only [Bool.false_eq_true, if_false] + rw [inBar_h rfl, inBar_h hd]; simp only; omega + · rw [fits_v hd] at hf + simp only [if_true] + rw [inBar_v rfl, inBar_v hd]; simp only; omega + +/-- The reflection in the vertical axis maps tilings to tilings. -/ +private theorem vFlip_valid {m : ℕ} {P : ℕ → Pl} + (hP : Valid (m + 1) (2 * m + 1) (2 * m + 1) P) : + Valid (m + 1) (2 * m + 1) (2 * m + 1) (vFlip m P) := by + apply valid_transfer hP (fun a b => (a, 2 * m - b)) (fun a b ha hb => by simp only; omega) + · intro k h1 h2 + have hf := vfit hP h1 h2 + simp only [vFlip, if_neg (show ¬ (k = 0 ∨ 2 * m + 1 < k) by omega)] + rcases hd : (P k).2.2 with _ | _ + · rw [fits_h hd] at hf + simp only [Bool.false_eq_true, if_false] + rw [fits_h rfl]; simp only; omega + · rw [fits_v hd] at hf + simp only [if_true] + rw [fits_v rfl]; simp only; omega + · intro k h1 h2 a b ha hb + have hf := vfit hP h1 h2 + simp only [vFlip, if_neg (show ¬ (k = 0 ∨ 2 * m + 1 < k) by omega)] + rcases hd : (P k).2.2 with _ | _ + · rw [fits_h hd] at hf + simp only [Bool.false_eq_true, if_false] + rw [inBar_h rfl, inBar_h hd]; simp only; omega + · rw [fits_v hd] at hf + simp only [if_true] + rw [inBar_v rfl, inBar_v hd]; simp only; omega + +/-- The reflection in the horizontal axis is an involution on tilings. -/ +private theorem hFlip_hFlip {m : ℕ} {P : ℕ → Pl} + (hP : Valid (m + 1) (2 * m + 1) (2 * m + 1) P) + (hn : ∀ k, (k = 0 ∨ 2 * m + 1 < k) → P k = dflt) : hFlip m (hFlip m P) = P := by + funext k + by_cases hk : k = 0 ∨ 2 * m + 1 < k + · simp only [hFlip, if_pos hk]; exact (hn k hk).symm + · have hf := vfit hP (k := k) (by omega) (by omega) + simp only [hFlip, if_neg hk] + rcases hd : (P k).2.2 with _ | _ + · rw [fits_h hd] at hf + simp only [Bool.false_eq_true, if_false] + exact Prod.ext (by simp only; omega) (Prod.ext rfl hd.symm) + · rw [fits_v hd] at hf + simp only [if_true] + exact Prod.ext (by simp only; omega) (Prod.ext rfl hd.symm) + +/-- The reflection in the vertical axis is an involution on tilings. -/ +private theorem vFlip_vFlip {m : ℕ} {P : ℕ → Pl} + (hP : Valid (m + 1) (2 * m + 1) (2 * m + 1) P) + (hn : ∀ k, (k = 0 ∨ 2 * m + 1 < k) → P k = dflt) : vFlip m (vFlip m P) = P := by + funext k + by_cases hk : k = 0 ∨ 2 * m + 1 < k + · simp only [vFlip, if_pos hk]; exact (hn k hk).symm + · have hf := vfit hP (k := k) (by omega) (by omega) + simp only [vFlip, if_neg hk] + rcases hd : (P k).2.2 with _ | _ + · rw [fits_h hd] at hf + simp only [Bool.false_eq_true, if_false] + exact Prod.ext rfl (Prod.ext (by simp only; omega) hd.symm) + · rw [fits_v hd] at hf + simp only [if_true] + exact Prod.ext rfl (Prod.ext (by simp only; omega) hd.symm) + +/-- Distinguishes a tiling from its reflection in the horizontal axis. -/ +private def alpha (m : ℕ) (P : ℕ → Pl) : Prop := + 2 * (P (2 * m + 1)).1 < m ∨ (2 * (P (2 * m + 1)).1 = m ∧ 2 * (P (2 * m)).1 < m) + +/-- Distinguishes a tiling from its reflection in the vertical axis. -/ +private def beta (m : ℕ) (P : ℕ → Pl) : Prop := (P (2 * m)).2.1 = 0 + +/-- How the two reflections act on `alpha` and `beta`. -/ +private theorem flip_alpha_beta {m : ℕ} (hm : 1 ≤ m) {P : ℕ → Pl} + (hP : Valid (m + 1) (2 * m + 1) (2 * m + 1) P) : + (alpha m (hFlip m P) ↔ ¬ alpha m P) ∧ (beta m (hFlip m P) ↔ beta m P) ∧ + (alpha m (vFlip m P) ↔ alpha m P) ∧ (beta m (vFlip m P) ↔ ¬ beta m P) := by + obtain ⟨t1, t2⟩ := s_top hm hP + obtain ⟨u1, u2, u3⟩ := s_two hm hP + have ht := vfit hP (k := 2 * m + 1) (by omega) le_rfl + have hu := vfit hP (k := 2 * m) (by omega) (by omega) + rw [fits_h t1] at ht + rw [fits_h u1] at hu + have h1 : hFlip m P (2 * m + 1) = (m - (P (2 * m + 1)).1, (P (2 * m + 1)).2.1, false) := by + rw [hFlip, if_neg (by omega), if_neg (by rw [t1]; simp)] + have h2 : hFlip m P (2 * m) = (m - (P (2 * m)).1, (P (2 * m)).2.1, false) := by + rw [hFlip, if_neg (by omega), if_neg (by rw [u1]; simp)] + have h3 : vFlip m P (2 * m + 1) = + ((P (2 * m + 1)).1, 2 * m + 1 - (2 * m + 1) - (P (2 * m + 1)).2.1, false) := by + rw [vFlip, if_neg (by omega), if_neg (by rw [t1]; simp)] + have h4 : vFlip m P (2 * m) = ((P (2 * m)).1, 2 * m + 1 - 2 * m - (P (2 * m)).2.1, false) := by + rw [vFlip, if_neg (by omega), if_neg (by rw [u1]; simp)] + simp only [alpha, beta, h1, h2, h3, h4, true_and] + omega + +open Classical in +/-- The number of tilings of the small rectangle is divisible by `4`: the reflections pair +up the tilings with and without `alpha`, and then those with and without `beta`. -/ +private theorem four_dvd_small {m : ℕ} (hm : 1 ≤ m) : + 4 ∣ ((Univ (m + 1) (2 * m + 1) (2 * m + 1)).filter + (Valid (m + 1) (2 * m + 1) (2 * m + 1))).card := by + set S := (Univ (m + 1) (2 * m + 1) (2 * m + 1)).filter + (Valid (m + 1) (2 * m + 1) (2 * m + 1)) with hS + have memS : ∀ P, P ∈ S ↔ Valid (m + 1) (2 * m + 1) (2 * m + 1) P ∧ + ∀ k, (k = 0 ∨ 2 * m + 1 < k) → P k = dflt := by + intro P + rw [hS, mem_filter] + constructor + · rintro ⟨hU, hV⟩; exact ⟨hV, (mem_Univ.mp hU).1⟩ + · rintro ⟨hV, hn⟩; exact ⟨mem_Univ_of hV hn, hV⟩ + have hnh : ∀ P, ∀ k, (k = 0 ∨ 2 * m + 1 < k) → hFlip m P k = dflt := by + intro P k hk; simp only [hFlip, if_pos hk] + have hnv : ∀ P, ∀ k, (k = 0 ∨ 2 * m + 1 < k) → vFlip m P k = dflt := by + intro P k hk; simp only [vFlip, if_pos hk] + have e1 : (S.filter (alpha m)).card = (S.filter (fun P => ¬ alpha m P)).card := by + apply card_nbij' (hFlip m) (hFlip m) + · intro P hP + rw [mem_coe, mem_filter, memS] at hP ⊢ + exact ⟨⟨hFlip_valid hP.1.1, hnh P⟩, fun h => ((flip_alpha_beta hm hP.1.1).1.mp h) hP.2⟩ + · intro P hP + rw [mem_coe, mem_filter, memS] at hP ⊢ + exact ⟨⟨hFlip_valid hP.1.1, hnh P⟩, (flip_alpha_beta hm hP.1.1).1.mpr hP.2⟩ + · intro P hP + rw [mem_coe, mem_filter, memS] at hP + exact hFlip_hFlip hP.1.1 hP.1.2 + · intro P hP + rw [mem_coe, mem_filter, memS] at hP + exact hFlip_hFlip hP.1.1 hP.1.2 + have e2 : ((S.filter (alpha m)).filter (beta m)).card = + ((S.filter (alpha m)).filter (fun P => ¬ beta m P)).card := by + apply card_nbij' (vFlip m) (vFlip m) + · intro P hP + rw [mem_coe, mem_filter, mem_filter, memS] at hP ⊢ + have hab := flip_alpha_beta hm hP.1.1.1 + exact ⟨⟨⟨vFlip_valid hP.1.1.1, hnv P⟩, hab.2.2.1.mpr hP.1.2⟩, fun h => (hab.2.2.2.mp h) hP.2⟩ + · intro P hP + rw [mem_coe, mem_filter, mem_filter, memS] at hP ⊢ + have hab := flip_alpha_beta hm hP.1.1.1 + exact ⟨⟨⟨vFlip_valid hP.1.1.1, hnv P⟩, hab.2.2.1.mpr hP.1.2⟩, hab.2.2.2.mpr hP.2⟩ + · intro P hP + rw [mem_coe, mem_filter, mem_filter, memS] at hP + exact vFlip_vFlip hP.1.1.1 hP.1.1.2 + · intro P hP + rw [mem_coe, mem_filter, mem_filter, memS] at hP + exact vFlip_vFlip hP.1.1.1 hP.1.1.2 + have t1 := card_filter_add_card_filter_not (s := S) (alpha m) + have t2 := card_filter_add_card_filter_not (s := S.filter (alpha m)) (beta m) + exact ⟨((S.filter (alpha m)).filter (beta m)).card, by omega⟩ + +/-! ## The conjecture -/ + +/-- Unfolding `a`. -/ +private theorem a_eq {n r c : ℕ} (hr : rows n = r) (hc : cols n = c) : + a n = search (c + 1) (r * (c + 1)) n (stabCount r c (c + 1) n) n (rectMask r c (c + 1)) 0 / + (1 + (otherSymmetries r c).length) := by + subst hr hc; rfl + +/-- `rows (2m + 1) = m + 1`. -/ +private theorem rows_odd (m : ℕ) : rows (2 * m + 1) = m + 1 := by + unfold rows; omega + +/-- `cols (2m + 1) = 2m + 1`. -/ +private theorem cols_odd (m : ℕ) : cols (2 * m + 1) = 2 * m + 1 := by + unfold cols + rw [rows_odd] + have : (2 * m + 1) * (2 * m + 1 + 1) / 2 = (2 * m + 1) * (m + 1) := by + rw [show (2 * m + 1) * (2 * m + 1 + 1) = 2 * ((2 * m + 1) * (m + 1)) by ring, + Nat.mul_div_cancel_left _ (by norm_num)] + rw [this, Nat.mul_div_cancel _ (by omega)] + +/-- `rows (2m + 2) = m + 1`. -/ +private theorem rows_even (m : ℕ) : rows (2 * m + 2) = m + 1 := by + unfold rows; omega + +/-- `cols (2m + 2) = 2m + 3`. -/ +private theorem cols_even (m : ℕ) : cols (2 * m + 2) = 2 * m + 3 := by + unfold cols + rw [rows_even] + have : (2 * m + 2) * (2 * m + 2 + 1) / 2 = (2 * m + 3) * (m + 1) := by + rw [show (2 * m + 2) * (2 * m + 2 + 1) = 2 * ((2 * m + 3) * (m + 1)) by ring, + Nat.mul_div_cancel_left _ (by norm_num)] + rw [this, Nat.mul_div_cancel _ (by omega)] + +open Classical in +/-- `a (2m + 1)` is the number of tilings of `(m + 1) × (2m + 1)` divided by `4`. -/ +private theorem a_odd {m : ℕ} (hm : 1 ≤ m) : + a (2 * m + 1) = ((Univ (m + 1) (2 * m + 1) (2 * m + 1)).filter + (Valid (m + 1) (2 * m + 1) (2 * m + 1))).card / 4 := by + rw [a_eq (rows_odd m) (cols_odd m)] + exact search_count (by omega) (by omega) (by omega) (by omega) + +open Classical in +/-- `a (2m + 2)` is the number of tilings of `(m + 1) × (2m + 3)` divided by `4`. -/ +private theorem a_even {m : ℕ} (hm : 1 ≤ m) : + a (2 * m + 2) = ((Univ (m + 1) (2 * m + 3) (2 * m + 2)).filter + (Valid (m + 1) (2 * m + 3) (2 * m + 2))).card / 4 := by + rw [a_eq (rows_even m) (cols_even m)] + exact search_count (by omega) (by omega) (by omega) (by omega) + +/-- **A394981, the conjecture `a(n + 1) = 4 a(n)` for odd `n ≥ 3`.** -/ +theorem result : statement := by + intro n hn hodd + obtain ⟨m, rfl⟩ := hodd + have hm : 1 ≤ m := by omega + rw [show 2 * m + 1 + 1 = 2 * m + 2 by ring, a_even hm, a_odd hm, card_big hm] + obtain ⟨q, hq⟩ := four_dvd_small hm + rw [hq] + omega + +end Math0.Frontier.A394981 + +#math0_settles Math0.Frontier.A394981.result Math0.Statements.A394981.statement diff --git a/lean/Math0/Frontier/OEIS/A395454.lean b/lean/Math0/Frontier/OEIS/A395454.lean new file mode 100644 index 0000000..d4e55b4 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A395454.lean @@ -0,0 +1,252 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A395454 +import Math0.Audit + +/-! +# Alexandersson's recurrence for the row polynomials of A395454 (rows counted from 1) + +We prove the frozen statement: for the row polynomials `P_m(t) = ∑_k T(m,k) t^k` of A395454 +(entry numbering, `P_0 = 1`), for every `m ≥ 2`, +`P_m = (m-1)(1+t)·P_{m-1} + (t - t^2)·P'_{m-1} + 2(m-1)t·P_{m-2}`, +which is Alexandersson's conjecture with the rows counted from `1`. + +**Reversed Eulerian polynomials.** Put `R_j(t) = ∑_{i=0}^{j} E2(j,i) t^{j-i}`. Since +`E2(j,i) = 0` for `i > j`, the recurrence of `E2` gives +`R_{j+1} = (j + (j+1)t)·R_j + (t - t^2)·R_j'`. + +**Binomial transform.** Because `T(n,k) = ∑_j (-1)^{n-j} C(n,j) E2(j, n-k)`, reindexing +`k = n - i` gives `P_n = S_n := ∑_{j=0}^{n} C(n,j) (-t)^{n-j} R_j`. + +**Recurrence.** Using `(t - t^2)·((-t)^k)' = k(1-t)(-t)^k`, the recurrence of `R_j`, Pascal's +rule `S_{n+1} = ∑_j C(n,j)((-t)^{n-j} R_{j+1} + (-t)^{n-j+1} R_j)` and +`(n+1)·C(n,j) = (n+1-j)·C(n+1,j)`, every quantity becomes a sum over `j ≤ n+1` of multiples of +`C(n+1,j)(-t)^{n+1-j}R_j` and `C(n+1,j)(-t)^{n+1-j}R_{j+1}`, and the identity +`S_{n+2} = (n+1)(1+t)S_{n+1} + (t-t^2)S_{n+1}' + 2(n+1)t S_n` holds term by term. +-/ + +namespace Math0.Frontier.A395454 +open Math0.Statements.A395454 +open Polynomial + +/-- `E2(j, i) = 0` whenever `i > j`. -/ +private theorem E2_eq_zero : ∀ j i : ℕ, j < i → E2 j i = 0 + | 0, 0, h => absurd h (lt_irrefl 0) + | 0, _ + 1, _ => rfl + | j + 1, 0, h => absurd h (Nat.not_lt_zero _) + | j + 1, k + 1, h => by + rw [E2, E2_eq_zero j k (by omega), E2_eq_zero j (k+1) (by omega)]; ring + +/-- The column-`0` case of the recurrence of `E2`. -/ +private theorem E2_succ_zero (j : ℕ) : E2 (j + 1) 0 = E2 j 0 := by rw [E2] + +/-- The recurrence of `E2` with simplified integer coefficients. -/ +private theorem E2_succ_succ (j k : ℕ) : E2 (j + 1) (k + 1) = + (2 * (j : ℤ) - k) * E2 j k + ((k : ℤ) + 2) * E2 j (k + 1) := by + rw [E2]; ring + +/-- The reversed second-order Eulerian polynomial `R_j(t) = ∑_{i ≤ j} E2(j,i) t^{j-i}`. -/ +private noncomputable def R (j : ℕ) : ℤ[X] := + ∑ i ∈ Finset.range (j + 1), C (E2 j i) * X ^ (j - i) + +/-- `(t - t^2)·(t^k)' = k·(t^k - t^{k+1})`. -/ +private theorem XX_deriv_pow (k : ℕ) : + (X - X ^ 2) * derivative (X ^ k : ℤ[X]) = (k : ℤ[X]) * (X ^ k - X ^ (k + 1)) := by + cases k with + | zero => simp + | succ k => + rw [derivative_X_pow] + simp only [Nat.add_sub_cancel, map_natCast] + push_cast + ring + +/-- `(t - t^2)·((-t)^k)' = k·(1 - t)·(-t)^k`. -/ +private theorem XX_deriv_negpow (k : ℕ) : + (X - X ^ 2) * derivative ((-X) ^ k : ℤ[X]) = (k : ℤ[X]) * (1 - X) * (-X) ^ k := by + cases k with + | zero => simp + | succ k => + rw [derivative_pow] + simp only [Nat.add_sub_cancel, map_natCast, derivative_neg, derivative_X] + push_cast + ring + +/-- Termwise expansion of the right-hand side of the recurrence of `R`. -/ +private theorem R_rhs (j : ℕ) : + ((j : ℤ[X]) + ((j : ℤ[X]) + 1) * X) * R j + (X - X ^ 2) * derivative (R j) = + ∑ i ∈ Finset.range (j + 1), (C (E2 j i) * ((2 * (j : ℤ[X]) - (i : ℤ[X])) * X ^ (j - i)) + + C (E2 j i) * (((i : ℤ[X]) + 1) * X ^ (j - i + 1))) := by + rw [R, Finset.mul_sum, derivative_sum, Finset.mul_sum, ← Finset.sum_add_distrib] + apply Finset.sum_congr rfl + intro i hi + have hij : i ≤ j := Nat.lt_succ_iff.mp (Finset.mem_range.mp hi) + rw [derivative_C_mul, mul_left_comm (X - X ^ 2 : ℤ[X]), XX_deriv_pow, Nat.cast_sub hij] + ring + +/-- `R_{j+1} = (j + (j+1)t)·R_j + (t - t^2)·R_j'`. -/ +private theorem R_succ (j : ℕ) : + R (j + 1) = ((j : ℤ[X]) + ((j : ℤ[X]) + 1) * X) * R j + (X - X ^ 2) * derivative (R j) := by + rw [R_rhs, Finset.sum_add_distrib] + have hL : R (j + 1) = ∑ i ∈ Finset.range (j + 1), + C (E2 j i) * ((2 * (j : ℤ[X]) - (i : ℤ[X])) * X ^ (j - i)) + + (∑ i ∈ Finset.range (j + 1), C (E2 j (i + 1)) * (((i : ℤ[X]) + 2) * X ^ (j - i)) + + C (E2 j 0) * X ^ (j + 1)) := by + rw [R, Finset.sum_range_succ' _ (j + 1), ← add_assoc, ← Finset.sum_add_distrib] + congr 1 + · apply Finset.sum_congr rfl + intro i _ + rw [E2_succ_succ, Nat.add_sub_add_right] + simp only [map_add, map_mul, map_sub, map_natCast, map_ofNat] + ring + have h1 : ∑ i ∈ Finset.range (j + 1), C (E2 j (i + 1)) * (((i : ℤ[X]) + 2) * X ^ (j - i)) + + C (E2 j 0) * X ^ (j + 1) + = ∑ i ∈ Finset.range (j + 1), C (E2 j i) * (((i : ℤ[X]) + 1) * X ^ (j - i + 1)) := by + rw [Finset.sum_range_succ (fun i => C (E2 j (i + 1)) * (((i : ℤ[X]) + 2) * X ^ (j - i))) j, + Finset.sum_range_succ' (fun i => C (E2 j i) * (((i : ℤ[X]) + 1) * X ^ (j - i + 1))) j, + E2_eq_zero j (j + 1) (by omega)] + simp only [map_zero, zero_mul, add_zero, Nat.cast_zero, zero_add, one_mul, Nat.sub_zero] + congr 1 + apply Finset.sum_congr rfl + intro i hi + have hij : i < j := Finset.mem_range.mp hi + rw [show j - (i + 1) + 1 = j - i by omega] + push_cast + ring + rw [hL, h1] + +/-- The binomial transform `S_n = ∑_{j ≤ n} C(n,j)·(-t)^{n-j}·R_j`. -/ +private noncomputable def S (n : ℕ) : ℤ[X] := + ∑ j ∈ Finset.range (n + 1), (n.choose j : ℤ[X]) * (-X) ^ (n - j) * R j + +/-- Pascal's rule applied to `S_{n+1}`. -/ +private theorem S_succ (n : ℕ) : S (n + 1) = + ∑ j ∈ Finset.range (n + 1), (n.choose j : ℤ[X]) * + ((-X) ^ (n - j) * R (j + 1) + (-X) ^ (n - j + 1) * R j) := by + have hA : ∑ j ∈ Finset.range (n + 1), + ((n + 1).choose (j + 1) : ℤ[X]) * (-X) ^ (n + 1 - (j + 1)) * R (j + 1) + = ∑ j ∈ Finset.range (n + 1), (n.choose j : ℤ[X]) * ((-X) ^ (n - j) * R (j + 1)) + + ∑ j ∈ Finset.range (n + 1), (n.choose (j + 1) : ℤ[X]) * ((-X) ^ (n - j) * R (j + 1)) := by + rw [← Finset.sum_add_distrib] + apply Finset.sum_congr rfl + intro j _ + rw [Nat.choose_succ_succ, Nat.add_sub_add_right] + push_cast + ring + have hB : ∑ j ∈ Finset.range (n + 1), (n.choose (j + 1) : ℤ[X]) * ((-X) ^ (n - j) * R (j + 1)) + + ((n + 1).choose 0 : ℤ[X]) * (-X) ^ (n + 1 - 0) * R 0 + = ∑ j ∈ Finset.range (n + 1), (n.choose j : ℤ[X]) * ((-X) ^ (n - j + 1) * R j) := by + rw [Finset.sum_range_succ (fun j => (n.choose (j + 1) : ℤ[X]) * ((-X) ^ (n - j) * R (j + 1))) n, + Finset.sum_range_succ' (fun j => (n.choose j : ℤ[X]) * ((-X) ^ (n - j + 1) * R j)) n, + Nat.choose_succ_self] + simp only [Nat.cast_zero, zero_mul, add_zero, Nat.choose_zero_right, Nat.sub_zero, mul_assoc] + congr 1 + apply Finset.sum_congr rfl + intro j hj + have hjn : j < n := Finset.mem_range.mp hj + rw [show n - (j + 1) + 1 = n - j by omega] + rw [S, Finset.sum_range_succ' _ (n + 1), hA, add_assoc, hB, ← Finset.sum_add_distrib] + apply Finset.sum_congr rfl + intro j _ + ring + +/-- Termwise form of `(t - t^2)·S_n'`, using the recurrence of `R`. -/ +private theorem S_deriv (n : ℕ) : (X - X ^ 2) * derivative (S n) = + ∑ j ∈ Finset.range (n + 1), (n.choose j : ℤ[X]) * + (((n - j : ℕ) : ℤ[X]) * (1 - X) * (-X) ^ (n - j) * R j + + (-X) ^ (n - j) * (R (j + 1) - ((j : ℤ[X]) + ((j : ℤ[X]) + 1) * X) * R j)) := by + rw [S, derivative_sum, Finset.mul_sum] + apply Finset.sum_congr rfl + intro j _ + have h := XX_deriv_negpow (n - j) + have h' : (X - X ^ 2) * derivative (R j) = + R (j + 1) - ((j : ℤ[X]) + ((j : ℤ[X]) + 1) * X) * R j := by + rw [R_succ]; ring + rw [derivative_mul, derivative_mul, derivative_natCast] + linear_combination ((n.choose j : ℤ[X]) * R j) * h + ((n.choose j : ℤ[X]) * (-X) ^ (n - j)) * h' + +/-- `(n+1)·(-t)·S_n` as a sum over `j ≤ n+1`, via `(n+1)·C(n,j) = (n+1-j)·C(n+1,j)`. -/ +private theorem S_mul (n : ℕ) : ((n : ℤ[X]) + 1) * (-X) * S n = + ∑ j ∈ Finset.range (n + 1 + 1), ((n + 1).choose j : ℤ[X]) * + (((n + 1 - j : ℕ) : ℤ[X]) * (-X) ^ (n + 1 - j) * R j) := by + rw [S, Finset.mul_sum, Finset.sum_range_succ _ (n + 1), Nat.sub_self] + simp only [Nat.cast_zero, zero_mul, mul_zero, add_zero] + apply Finset.sum_congr rfl + intro j hj + have hjn : j ≤ n := Nat.lt_succ_iff.mp (Finset.mem_range.mp hj) + have hc : (n.choose j : ℤ[X]) * ((n : ℤ[X]) + 1) = + ((n + 1).choose j : ℤ[X]) * ((n + 1 - j : ℕ) : ℤ[X]) := by + exact_mod_cast congrArg (Nat.cast : ℕ → ℤ[X]) (Nat.choose_mul_succ_eq n j) + have hp : (-X : ℤ[X]) ^ (n + 1 - j) = (-X) ^ (n - j) * (-X) := by + rw [← pow_succ]; congr 1; omega + rw [hp] + linear_combination (-X) ^ (n - j) * (-X) * R j * hc + +/-- The recurrence `S_{n+2} = (n+1)(1+t)S_{n+1} + (t-t^2)S_{n+1}' + 2(n+1)t S_n`. -/ +private theorem S_rec (n : ℕ) : S (n + 2) = + ((n : ℤ[X]) + 1) * (1 + X) * S (n + 1) + (X - X ^ 2) * derivative (S (n + 1)) + + 2 * ((n : ℤ[X]) + 1) * X * S n := by + have h3 : 2 * ((n : ℤ[X]) + 1) * X * S n = -2 * (((n : ℤ[X]) + 1) * (-X) * S n) := by ring + rw [h3, S_mul, S_deriv, show n + 2 = n + 1 + 1 from rfl, S_succ (n + 1)] + conv_rhs => rw [S] + rw [Finset.mul_sum, Finset.mul_sum, ← Finset.sum_add_distrib, ← Finset.sum_add_distrib] + apply Finset.sum_congr rfl + intro j hj + have hjn : j ≤ n + 1 := Nat.lt_succ_iff.mp (Finset.mem_range.mp hj) + rw [Nat.cast_sub hjn] + push_cast + ring + +/-- One summand of `S_n`, expanded into monomials `t^{n-i}`, `i ≤ n`. -/ +private theorem S_term (n j : ℕ) (hj : j ≤ n) : + (n.choose j : ℤ[X]) * (-X) ^ (n - j) * R j = + ∑ i ∈ Finset.range (n + 1), C ((-1) ^ (n - j) * (n.choose j : ℤ) * E2 j i) * X ^ (n - i) := by + rw [R, Finset.mul_sum] + have h : ∀ i ∈ Finset.range (j + 1), + (n.choose j : ℤ[X]) * (-X) ^ (n - j) * (C (E2 j i) * X ^ (j - i)) = + C ((-1) ^ (n - j) * (n.choose j : ℤ) * E2 j i) * X ^ (n - i) := by + intro i hi + have hij : i ≤ j := Nat.lt_succ_iff.mp (Finset.mem_range.mp hi) + rw [show n - i = (n - j) + (j - i) by omega, pow_add, neg_pow] + simp only [map_mul, map_pow, map_neg, map_one, map_natCast] + ring + rw [Finset.sum_congr rfl h] + have hsub : Finset.range (j + 1) ⊆ Finset.range (n + 1) := + Finset.range_subset_range.mpr (by omega) + apply Finset.sum_subset hsub + intro i hi hi' + have hji : j < i := by + simp only [Finset.mem_range] at hi hi' + omega + rw [E2_eq_zero j i hji] + simp + +/-- The row polynomial `P_n` equals the binomial transform `S_n`. -/ +private theorem P_eq_S (n : ℕ) : P n = S n := by + have h : ∀ j ∈ Finset.range (n + 1), (n.choose j : ℤ[X]) * (-X) ^ (n - j) * R j = + ∑ i ∈ Finset.range (n + 1), C ((-1) ^ (n - j) * (n.choose j : ℤ) * E2 j i) * X ^ (n - i) := + fun j hj => S_term n j (Nat.lt_succ_iff.mp (Finset.mem_range.mp hj)) + rw [S, Finset.sum_congr rfl h, Finset.sum_comm, P, ← Finset.sum_range_reflect] + apply Finset.sum_congr rfl + intro i hi + have hin : i ≤ n := Nat.lt_succ_iff.mp (Finset.mem_range.mp hi) + rw [Nat.add_sub_cancel, T, Nat.sub_sub_self hin, map_sum, Finset.sum_mul] + +/-- Alexandersson's recurrence for A395454 holds with the rows counted from `1`: for `n ≥ 3`, +`P(n) = (n - 2t + nt - 2)·P(n-1) + (t - t^2)·P'(n-1) + t(2n-4)·P(n-2)`, `P(n) = P1 n`. -/ +theorem result : statement := by + intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 3 := ⟨n - 3, by omega⟩ + have a1 : P1 (m + 3) = S (m + 2) := by + rw [P1, P_eq_S, show m + 3 - 1 = m + 2 by omega] + have a2 : P1 (m + 3 - 1) = S (m + 1) := by + rw [P1, P_eq_S, show m + 3 - 1 - 1 = m + 1 by omega] + have a3 : P1 (m + 3 - 2) = S m := by + rw [P1, P_eq_S, show m + 3 - 2 - 1 = m by omega] + rw [a1, a2, a3, S_rec m] + push_cast + ring + +end Math0.Frontier.A395454 + +#math0_settles Math0.Frontier.A395454.result Math0.Statements.A395454.statement diff --git a/lean/Math0/Frontier/OEIS/A397315.lean b/lean/Math0/Frontier/OEIS/A397315.lean new file mode 100644 index 0000000..ad5c4e1 --- /dev/null +++ b/lean/Math0/Frontier/OEIS/A397315.lean @@ -0,0 +1,359 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A397315 +import Math0.Audit + +/-! +# A397315: a 14-point blackout of the 5 × 8 grid refutes `T(n,m) = n + m` + +The conjecture in OEIS A397315 asserts `T(n, m) = n + m` for `min(n, m) ≥ 4` apart from +`T(4,4) = 7` and `T(4,5) = T(5,4) = 8`. In particular it predicts `T 5 8 = 13`. We refute it by +exhibiting a valid blackout of the `5 × 8` grid (`n = 5` rows `y < 5`, `k = 8` columns `x < 8`) +with 14 points, so `T 5 8 ≥ 14`. + +The blacked-out points `(x, y)` are +`(0,1), (0,4), (1,0), (1,1), (2,0), (2,3), (3,0), (4,0), (5,1), (5,2), (6,2), (6,3), (7,3), (7,4)`; +with the statement's numbering `i = 5 x + y` they form the bitmask `Bw = 837721039986`. + +Validity is checked as follows, without letting the kernel evaluate `rects 5 8` directly (that +computation uses too much memory). +* `rectMask_eq`: `rectMask? n k a b c` agrees with `fastMask n k a b c`, which computes the same + thing with natural-number arithmetic only (the dot product condition is rearranged so that no + subtraction is needed). This is a general proof, not a computation. +* `chkA a = true` for every `a < 40` (40 separate `decide +kernel` checks): for all `b, c < 40`, + whenever `fastMask 5 8 a b c = some r`, the mask `r` occurs in the explicit list `Lr` of 364 + rectangle masks. Hence every element of `rects 5 8` lies in `Lr`. +* `dist`: the visible parts `R \ Bw` for `R ∈ Lr` are pairwise distinct (`decide +kernel`). +* `rects 5 8` has no duplicates (it is an `eraseDups`), so `R ↦ R \ Bw` is injective on it, i.e. + `isValidBlackout 5 8 Bw = true`. Since `Bw` has 14 bits, `T 5 8 ≥ 14 > 13`. +-/ + +namespace Math0.Frontier.A397315 +open Math0.Statements.A397315 + +/-- `rectMask?` with natural-number arithmetic only: the coordinates are `(i / n, i % n)`, the +right-angle condition `(A - B) · (C - B) = 0` is written as `A·C + B·B = A·B + B·C`, and +`D = A + C - B` lies in the grid iff `B ≤ A + C < (k, n) + B` coordinatewise. -/ +private def fastMask (n k a b c : ℕ) : Option ℕ := + if a ≠ b ∧ b ≠ c ∧ a ≠ c ∧ + (a/n)*(c/n) + (b/n)*(b/n) + (a%n)*(c%n) + (b%n)*(b%n) = + (a/n)*(b/n) + (b/n)*(c/n) + (a%n)*(b%n) + (b%n)*(c%n) ∧ + b/n ≤ a/n + c/n ∧ a/n + c/n < k + b/n ∧ b%n ≤ a%n + c%n ∧ a%n + c%n < n + b%n + then some (2^a ||| 2^b ||| 2^c ||| 2^((a/n + c/n - b/n)*n + (a%n + c%n - b%n))) + else none + +/-- `rectMask?` and `fastMask` agree everywhere. -/ +private theorem rectMask_eq (n k a b c : ℕ) : rectMask? n k a b c = fastMask n k a b c := by + unfold rectMask? fastMask pt inGrid idx + generalize a / n = ax, a % n = ay, b / n = bx, b % n = by', c / n = cx, c % n = cy + simp only [Prod.fst_sub, Prod.snd_sub, Prod.fst_add, Prod.snd_add, Bool.and_eq_true, + decide_eq_true_eq] + have hdot : ((ax : ℤ) - bx) * ((cx : ℤ) - bx) + ((ay : ℤ) - by') * ((cy : ℤ) - by') = 0 ↔ + ax * cx + bx * bx + ay * cy + by' * by' = ax * bx + bx * cx + ay * by' + by' * cy := by + constructor + · intro h + have : ((ax * cx + bx * bx + ay * cy + by' * by' : ℕ) : ℤ) = + ((ax * bx + bx * cx + ay * by' + by' * cy : ℕ) : ℤ) := by + push_cast; linear_combination h + exact_mod_cast this + · intro h + have := congrArg (fun x : ℕ => (x : ℤ)) h + push_cast at this + linear_combination this + by_cases h : a ≠ b ∧ b ≠ c ∧ a ≠ c ∧ + ax * cx + bx * bx + ay * cy + by' * by' = ax * bx + bx * cx + ay * by' + by' * cy ∧ + bx ≤ ax + cx ∧ ax + cx < k + bx ∧ by' ≤ ay + cy ∧ ay + cy < n + by' + · obtain ⟨h1, h2, h3, h4, h5, h6, h7, h8⟩ := h + rw [if_pos ⟨h1, h2, h3, hdot.mpr h4, by omega⟩, if_pos ⟨h1, h2, h3, h4, h5, h6, h7, h8⟩] + have e1 : ((ax : ℤ) + cx - bx).toNat = ax + cx - bx := by omega + have e2 : ((ay : ℤ) + cy - by').toNat = ay + cy - by' := by omega + rw [e1, e2] + · rw [if_neg h, if_neg] + rintro ⟨h1, h2, h3, h4, h5⟩ + exact h ⟨h1, h2, h3, hdot.mp h4, by omega, by omega, by omega, by omega⟩ + +/-- The 364 rectangle vertex sets of the `5 × 8` grid, as bitmasks (sorted). -/ +private def Lr : List ℕ := [ + 99, 165, 198, 297, 330, 396, 561, 594, + 660, 792, 2210, 3075, 3168, 4420, 5125, 5280, + 6150, 6336, 8840, 9225, 9504, 10250, 10560, 12300, + 12672, 17425, 17952, 18450, 19008, 20500, 21120, 24600, + 25344, 66820, 70720, 73764, 98307, 98400, 101376, 132354, + 133640, 139298, 141440, 147528, 163845, 164000, 168960, 196614, + 196800, 202752, 264708, 278596, 282880, 294921, 295200, 304128, + 327690, 328000, 337920, 393228, 393600, 405504, 557073, 557600, + 574464, 589842, 590400, 608256, 655380, 656000, 675840, 786456, + 787200, 811008, 2130440, 2138240, 2263040, 2360448, 2621480, 3145731, + 3145824, 3148800, 3244032, 4211716, 4235328, 4276480, 4457536, 4526080, + 4720896, 5242885, 5243040, 5248000, 5406720, 6291462, 6291648, 6297600, + 6488064, 8421890, 8470656, 8912930, 8915072, 9052160, 9437193, 9437472, + 9446400, 9732096, 10485770, 10486080, 10496000, 10813440, 12582924, 12583296, + 12595200, 12976128, 17825809, 17826336, 17843200, 18382848, 18874386, 18874944, + 18892800, 19464192, 20971540, 20972160, 20992000, 21626880, 25165848, 25166592, + 25190400, 25952256, 68174080, 68423680, 72417280, 75534336, 83887360, 100663299, + 100663392, 100666368, 100761600, 103809024, 134774912, 135266820, 135530496, 136847360, + 142641152, 144834560, 150994980, 151068672, 167772165, 167772320, 167777280, 167936000, + 173015040, 201326598, 201326784, 201332736, 201523200, 207618048, 269500480, 271060992, + 285213760, 285282304, 289669120, 301989897, 301990176, 301999104, 302284800, 311427072, + 335544330, 335544640, 335554560, 335872000, 346030080, 402653196, 402653568, 402665472, + 403046400, 415236096, 570425361, 570425888, 570442752, 570982400, 588251136, 603979794, + 603980352, 603998208, 604569600, 622854144, 671088660, 671089280, 671109120, 671744000, + 692060160, 805306392, 805307136, 805330944, 806092800, 830472192, 2181570560, 2189557760, + 2317352960, 2417098752, 2684395520, 3221225475, 3221225568, 3221228544, 3221323776, 3224371200, + 3321888768, 4312797184, 4328538240, 4336975872, 4379115520, 4564516864, 4634705920, 4831839360, + 4834197504, 5368709125, 5368709280, 5368714240, 5368872960, 5373952000, 5536481280, 6442450950, + 6442451136, 6442457088, 6442647552, 6448742400, 6643777536, 8624015360, 8673951744, 9126840320, + 9129033728, 9269411840, 9663676425, 9663676704, 9663685632, 9663971328, 9673113600, 9965666304, + 10737418250, 10737418560, 10737428480, 10737745920, 10747904000, 11072962560, 12884901900, 12884902272, + 12884914176, 12885295104, 12897484800, 13287555072, 18253611025, 18253611552, 18253628416, 18254168064, + 18271436800, 18824036352, 19327352850, 19327353408, 19327371264, 19327942656, 19346227200, 19931332608, + 21474836500, 21474837120, 21474856960, 21475491840, 21495808000, 22145925120, 25769803800, 25769804544, + 25769828352, 25770590208, 25794969600, 26575110144, 69810257920, 70065848320, 74155294720, 77347160064, + 85900656640, 103079215107, 103079215200, 103079218176, 103079313408, 103082360832, 103179878400, 106300440576, + 138009509888, 138513223680, 138783227904, 140131696640, 146064539648, 148310589440, 154618859520, 154694320128, + 171798691845, 171798692000, 171798696960, 171798855680, 171803934720, 171966464000, 177167400960, 206158430214, + 206158430400, 206158436352, 206158626816, 206164721664, 206359756800, 212600881152, 275968491520, 277566455808, + 292058890240, 292129079296, 296621178880, 309237645321, 309237645600, 309237654528, 309237940224, 309247082496, + 309539635200, 318901321728, 343597383690, 343597384000, 343597393920, 343597711360, 343607869440, 343932928000, + 354334801920, 412316860428, 412316860800, 412316872704, 412317253632, 412329443328, 412719513600, 425201762304, + 584115552273, 584115552800, 584115569664, 584116109312, 584133378048, 584685977600, 602369163264, 618475290642, + 618475291200, 618475309056, 618475880448, 618494164992, 619079270400, 637802643456, 687194767380, 687194768000, + 687194787840, 687195422720, 687215738880, 687865856000, 708669603840, 824633720856, 824633721600, 824633745408, + 824634507264, 824658886656, 825439027200, 850403524608] + +/-- The witness blackout: the 14 points listed in the module docstring, as a bitmask. -/ +private def Bw : ℕ := 837721039986 + +/-- `scan r l = true` iff `r` occurs in `l` (linear scan with `Nat.beq`). -/ +private def scan (r : ℕ) (l : List ℕ) : Bool := l.rec false fun y _ ih => Nat.beq r y || ih + +/-- `memL r = true` iff `r` occurs in `Lr`. -/ +private def memL (r : ℕ) : Bool := scan r Lr + +/-- The per-triple check: if `(a, b, c)` spans a rectangle of the `5 × 8` grid, its mask is in +`Lr`. -/ +private def F (a b c : ℕ) : Bool := + match fastMask 5 8 a b c with + | none => true + | some r => memL r + +/-- `F a b c` for all `b, c < 40`. -/ +private def chkA (a : ℕ) : Bool := + Nat.rec (motive := fun _ => Bool) true (fun b ihb => + Nat.rec (motive := fun _ => Bool) true (fun c ihc => F a b c && ihc) 40 && ihb) 40 + +/-- Kernel check of `chkA 0`. -/ +private theorem chk_0 : chkA 0 = true := by decide +kernel +/-- Kernel check of `chkA 1`. -/ +private theorem chk_1 : chkA 1 = true := by decide +kernel +/-- Kernel check of `chkA 2`. -/ +private theorem chk_2 : chkA 2 = true := by decide +kernel +/-- Kernel check of `chkA 3`. -/ +private theorem chk_3 : chkA 3 = true := by decide +kernel +/-- Kernel check of `chkA 4`. -/ +private theorem chk_4 : chkA 4 = true := by decide +kernel +/-- Kernel check of `chkA 5`. -/ +private theorem chk_5 : chkA 5 = true := by decide +kernel +/-- Kernel check of `chkA 6`. -/ +private theorem chk_6 : chkA 6 = true := by decide +kernel +/-- Kernel check of `chkA 7`. -/ +private theorem chk_7 : chkA 7 = true := by decide +kernel +/-- Kernel check of `chkA 8`. -/ +private theorem chk_8 : chkA 8 = true := by decide +kernel +/-- Kernel check of `chkA 9`. -/ +private theorem chk_9 : chkA 9 = true := by decide +kernel +/-- Kernel check of `chkA 10`. -/ +private theorem chk_10 : chkA 10 = true := by decide +kernel +/-- Kernel check of `chkA 11`. -/ +private theorem chk_11 : chkA 11 = true := by decide +kernel +/-- Kernel check of `chkA 12`. -/ +private theorem chk_12 : chkA 12 = true := by decide +kernel +/-- Kernel check of `chkA 13`. -/ +private theorem chk_13 : chkA 13 = true := by decide +kernel +/-- Kernel check of `chkA 14`. -/ +private theorem chk_14 : chkA 14 = true := by decide +kernel +/-- Kernel check of `chkA 15`. -/ +private theorem chk_15 : chkA 15 = true := by decide +kernel +/-- Kernel check of `chkA 16`. -/ +private theorem chk_16 : chkA 16 = true := by decide +kernel +/-- Kernel check of `chkA 17`. -/ +private theorem chk_17 : chkA 17 = true := by decide +kernel +/-- Kernel check of `chkA 18`. -/ +private theorem chk_18 : chkA 18 = true := by decide +kernel +/-- Kernel check of `chkA 19`. -/ +private theorem chk_19 : chkA 19 = true := by decide +kernel +/-- Kernel check of `chkA 20`. -/ +private theorem chk_20 : chkA 20 = true := by decide +kernel +/-- Kernel check of `chkA 21`. -/ +private theorem chk_21 : chkA 21 = true := by decide +kernel +/-- Kernel check of `chkA 22`. -/ +private theorem chk_22 : chkA 22 = true := by decide +kernel +/-- Kernel check of `chkA 23`. -/ +private theorem chk_23 : chkA 23 = true := by decide +kernel +/-- Kernel check of `chkA 24`. -/ +private theorem chk_24 : chkA 24 = true := by decide +kernel +/-- Kernel check of `chkA 25`. -/ +private theorem chk_25 : chkA 25 = true := by decide +kernel +/-- Kernel check of `chkA 26`. -/ +private theorem chk_26 : chkA 26 = true := by decide +kernel +/-- Kernel check of `chkA 27`. -/ +private theorem chk_27 : chkA 27 = true := by decide +kernel +/-- Kernel check of `chkA 28`. -/ +private theorem chk_28 : chkA 28 = true := by decide +kernel +/-- Kernel check of `chkA 29`. -/ +private theorem chk_29 : chkA 29 = true := by decide +kernel +/-- Kernel check of `chkA 30`. -/ +private theorem chk_30 : chkA 30 = true := by decide +kernel +/-- Kernel check of `chkA 31`. -/ +private theorem chk_31 : chkA 31 = true := by decide +kernel +/-- Kernel check of `chkA 32`. -/ +private theorem chk_32 : chkA 32 = true := by decide +kernel +/-- Kernel check of `chkA 33`. -/ +private theorem chk_33 : chkA 33 = true := by decide +kernel +/-- Kernel check of `chkA 34`. -/ +private theorem chk_34 : chkA 34 = true := by decide +kernel +/-- Kernel check of `chkA 35`. -/ +private theorem chk_35 : chkA 35 = true := by decide +kernel +/-- Kernel check of `chkA 36`. -/ +private theorem chk_36 : chkA 36 = true := by decide +kernel +/-- Kernel check of `chkA 37`. -/ +private theorem chk_37 : chkA 37 = true := by decide +kernel +/-- Kernel check of `chkA 38`. -/ +private theorem chk_38 : chkA 38 = true := by decide +kernel +/-- Kernel check of `chkA 39`. -/ +private theorem chk_39 : chkA 39 = true := by decide +kernel + +/-- The visible parts of the rectangles in `Lr` under the blackout `Bw` are pairwise distinct. -/ +private theorem dist : pairwiseDistinct (Lr.map (visible · Bw)) = true := by decide +kernel + +/-- The witness has 14 points. -/ +private theorem card_Bw : card (5 * 8) Bw = 14 := by decide +kernel + +/-- A `Nat.rec` conjunction loop that evaluates to `true` gives `f c = true` for each `c < m`. -/ +private theorem loop_spec (f : ℕ → Bool) (m : ℕ) + (h : Nat.rec (motive := fun _ => Bool) true (fun c ih => f c && ih) m = true) : + ∀ c < m, f c = true := by + induction m with + | zero => intro c hc; omega + | succ m ih => + intro c hc + change (f m && Nat.rec (motive := fun _ => Bool) true (fun c ih => f c && ih) m) = true at h + rw [Bool.and_eq_true] at h + rcases Nat.lt_succ_iff_lt_or_eq.mp hc with hc | rfl + · exact ih h.2 c hc + · exact h.1 + +/-- `chkA a = true` for all `a < 40`. -/ +private theorem chk_all (a : ℕ) (ha : a < 40) : chkA a = true := by + interval_cases a + exacts [chk_0, chk_1, chk_2, chk_3, chk_4, chk_5, chk_6, chk_7, chk_8, chk_9, chk_10, chk_11, chk_12, chk_13, chk_14, chk_15, chk_16, chk_17, chk_18, chk_19, chk_20, chk_21, chk_22, chk_23, chk_24, chk_25, chk_26, chk_27, chk_28, chk_29, chk_30, chk_31, chk_32, chk_33, chk_34, chk_35, chk_36, chk_37, chk_38, chk_39] + +/-- `F a b c = true` for all `a, b, c < 40`. -/ +private theorem F_true (a b c : ℕ) (ha : a < 40) (hb : b < 40) (hc : c < 40) : + F a b c = true := + loop_spec (F a b) 40 (loop_spec (fun b => + Nat.rec (motive := fun _ => Bool) true (fun c ihc => F a b c && ihc) 40) 40 + (chk_all a ha) b hb) c hc + +/-- Soundness of a `Nat.beq` linear scan. -/ +private theorem mem_of_scan (r : ℕ) (l : List ℕ) (h : scan r l = true) : r ∈ l := by + induction l with + | nil => exact absurd (h : false = true) Bool.false_ne_true + | cons y ys ih => + change (Nat.beq r y || scan r ys) = true at h + rw [Bool.or_eq_true] at h + rcases h with h | h + · exact List.mem_cons.mpr (Or.inl (Nat.eq_of_beq_eq_true h)) + · exact List.mem_cons_of_mem _ (ih h) + +/-- Every rectangle of the `5 × 8` grid is in `Lr`. -/ +private theorem mem_rects {r : ℕ} (h : r ∈ rects 5 8) : r ∈ Lr := by + unfold rects at h + rw [List.mem_eraseDups] at h + simp only [List.mem_flatMap, List.mem_filterMap, List.mem_range] at h + obtain ⟨a, ha, b, hb, c, hc, hr⟩ := h + rw [rectMask_eq] at hr + have hF : memL r = true := by + have h1 := F_true a b c (by omega) (by omega) (by omega) + unfold F at h1 + rw [hr] at h1 + exact h1 + exact mem_of_scan r Lr hF + +/-- `notMem x l = true` iff `x ∉ l`. -/ +private theorem notMem_iff (x : ℕ) (l : List ℕ) : notMem x l = true ↔ x ∉ l := by + induction l with + | nil => exact ⟨fun _ => List.not_mem_nil, fun _ => rfl⟩ + | cons y ys ih => + change (!(Nat.beq x y) && notMem x ys) = true ↔ _ + have hb : Nat.beq x y = false ↔ ¬ x = y := + ⟨Nat.ne_of_beq_eq_false, fun h => Bool.eq_false_iff.mpr fun h' => h (Nat.eq_of_beq_eq_true h')⟩ + rw [Bool.and_eq_true, ih, List.mem_cons, not_or, Bool.not_eq_true', hb] + +/-- `pairwiseDistinct l = true` iff `l.Nodup`. -/ +private theorem pd_iff (l : List ℕ) : pairwiseDistinct l = true ↔ l.Nodup := by + induction l with + | nil => exact ⟨fun _ => List.nodup_nil, fun _ => rfl⟩ + | cons x xs ih => + change (notMem x xs && pairwiseDistinct xs) = true ↔ _ + rw [Bool.and_eq_true, notMem_iff, ih, List.nodup_cons] + +/-- `eraseDups` produces a list without duplicates. -/ +private theorem nodup_eraseDups' (l : List ℕ) : l.eraseDups.Nodup := by + induction h : l.length using Nat.strong_induction_on generalizing l with + | _ m ih => + cases l with + | nil => exact List.nodup_nil + | cons x xs => + rw [List.eraseDups_cons, List.nodup_cons] + constructor + · rw [List.mem_eraseDups, List.mem_filter] + simp + · have := List.length_filter_le (fun b => !b == x) xs + simp only [List.length_cons] at h + exact ih _ (by omega) _ rfl + +/-- The witness is a valid blackout of the `5 × 8` grid. -/ +private theorem valid : isValidBlackout 5 8 Bw = true := by + unfold isValidBlackout + rw [pd_iff] + have hL : (Lr.map (visible · Bw)).Nodup := (pd_iff _).mp dist + have hR : (rects 5 8).Nodup := by + unfold rects + exact nodup_eraseDups' _ + exact hR.map_on fun x hx y hy hxy => + List.inj_on_of_nodup_map hL (mem_rects hx) (mem_rects hy) hxy + +/-- The maximum in a `foldr`-of-`max` is at least each value. -/ +private theorem le_foldr (f : ℕ → ℕ) (l : List ℕ) (x : ℕ) (hx : x ∈ l) : + f x ≤ l.foldr (fun B m => max (f B) m) 0 := by + induction l with + | nil => exact absurd hx List.not_mem_nil + | cons y ys ih => + rw [List.foldr_cons] + rcases List.mem_cons.mp hx with rfl | h + · exact le_max_left _ _ + · exact le_trans (ih h) (le_max_right _ _) + +/-- `T 5 8 ≥ 14`. -/ +private theorem T_5_8_ge : 14 ≤ T 5 8 := by + have hmem : Bw ∈ (List.range (2 ^ (5 * 8))).filter (isValidBlackout 5 8) := by + rw [List.mem_filter, List.mem_range] + exact ⟨by norm_num [Bw], valid⟩ + have h := le_foldr (card (5 * 8)) _ _ hmem + rw [card_Bw] at h + unfold T + exact h + +/-- The conjecture of A397315 is false: it predicts `T 5 8 = 5 + 8 = 13`, but `T 5 8 ≥ 14`. -/ +theorem result : ¬ statement := by + intro h + have h58 := h 5 8 (by norm_num) + have h14 := T_5_8_ge + rw [h58] at h14 + norm_num at h14 + +end Math0.Frontier.A397315 + +#math0_settles Math0.Frontier.A397315.result Math0.Statements.A397315.statement diff --git a/lean/Math0/GreensOpenProblems/Green44_green_44.lean b/lean/Math0/GreensOpenProblems/Green44_green_44.lean new file mode 100644 index 0000000..9e202e0 --- /dev/null +++ b/lean/Math0/GreensOpenProblems/Green44_green_44.lean @@ -0,0 +1,219 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.GreensOpenProblems.«44» +import Math0.Audit + +/-! +# Sieving by 1000 primes below `N^{9/10}` can leave more than `N/10` (Green's Problem 44) + +Green's Open Problem 44 (after Erdős) asks: if one sieves `[N]` by removing half of the residue +classes modulo each of 1000 primes `p_1 < ⋯ < p_1000 < N^{9/10}`, is the remaining set of size at +most `N/10`? We refute the formal statement `Green44.green_44` with an explicit counterexample: +`N = 100000`, the 1000 consecutive primes `20011 = p_1 < ⋯ < p_1000 = 30161` (so that +`p_1000^10 < 10^45 = N^9`), and `A_i` the upper half `{⌈p_i/2⌉, …, p_i - 1}` of the residues mod +`p_i`, which has exactly `⌊p_i/2⌋` elements. Every `x ≤ 10005` is its own residue mod each `p_i` +and lies below `⌈p_i/2⌉ ≥ 10006`, so it survives; hence at least `10005 > N/10` numbers remain. +Primality of the 1000 primes is certified by a Boolean trial-division test evaluated in the kernel +(`decide +kernel`), together with a soundness lemma. +-/ + +namespace Math0.Green44 + +/-- `checkFrom n d k` is `true` only if no `m ≥ d` with `m * m ≤ n` divides `n` +(trial division starting at `d`, with fuel `k`). -/ +def checkFrom (n : ℕ) : ℕ → ℕ → Bool + | _, 0 => false + | d, k + 1 => Nat.blt n (d * d) || (n % d != 0 && checkFrom n (d + 1) k) + +/-- Soundness of trial division: a successful check rules out every divisor `m ≥ d` with +`m * m ≤ n`. -/ +theorem checkFrom_sound (n : ℕ) : ∀ (k d : ℕ), checkFrom n d k = true → + ∀ m, d ≤ m → m * m ≤ n → ¬ m ∣ n := by + intro k + induction k with + | zero => intro d h; simp [checkFrom] at h + | succ k ih => + intro d h m hdm hmn hdvd + simp only [checkFrom, Bool.or_eq_true, Nat.blt_eq, Bool.and_eq_true, bne_iff_ne, ne_eq] at h + rcases h with h | ⟨h1, h2⟩ + · have : d * d ≤ m * m := Nat.mul_le_mul hdm hdm + omega + · rcases Nat.eq_or_lt_of_le hdm with rfl | hlt + · exact h1 (Nat.mod_eq_zero_of_dvd hdvd) + · exact ih (d + 1) h2 m hlt hmn hdvd + +/-- A Boolean primality test by trial division. -/ +def isPrimeB (n : ℕ) : Bool := Nat.ble 2 n && checkFrom n 2 n + +/-- Soundness of `isPrimeB`. -/ +theorem isPrimeB_sound {n : ℕ} (h : isPrimeB n = true) : n.Prime := by + simp only [isPrimeB, Bool.and_eq_true, Nat.ble_eq] at h + obtain ⟨h2, hc⟩ := h + by_contra hnp + have hsq := Nat.minFac_sq_le_self (by omega) hnp + have hmp : (Nat.minFac n).Prime := Nat.minFac_prime (by omega) + exact checkFrom_sound n n 2 hc (Nat.minFac n) hmp.two_le (by rw [← pow_two]; exact hsq) + (Nat.minFac_dvd n) + +/-- The 1000 consecutive primes from `20011` to `30161`. -/ +def primeList : List ℕ := + [ + 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071, 20089, 20101, 20107, 20113, 20117, + 20123, 20129, 20143, 20147, 20149, 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, + 20249, 20261, 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357, 20359, + 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, 20477, 20479, 20483, 20507, + 20509, 20521, 20533, 20543, 20549, 20551, 20563, 20593, 20599, 20611, 20627, 20639, 20641, + 20663, 20681, 20693, 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, + 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897, 20899, 20903, 20921, + 20929, 20939, 20947, 20959, 20963, 20981, 20983, 21001, 21011, 21013, 21017, 21019, 21023, + 21031, 21059, 21061, 21067, 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, + 21169, 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277, 21283, 21313, + 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383, 21391, 21397, 21401, 21407, 21419, + 21433, 21467, 21481, 21487, 21491, 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, + 21559, 21563, 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, 21649, + 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, 21757, 21767, 21773, 21787, + 21799, 21803, 21817, 21821, 21839, 21841, 21851, 21859, 21863, 21871, 21881, 21893, 21911, + 21929, 21937, 21943, 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039, + 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123, 22129, 22133, 22147, + 22153, 22157, 22159, 22171, 22189, 22193, 22229, 22247, 22259, 22271, 22273, 22277, 22279, + 22283, 22291, 22303, 22307, 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, + 22441, 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, 22549, 22567, + 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, 22651, 22669, 22679, 22691, 22697, + 22699, 22709, 22717, 22721, 22727, 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, + 22811, 22817, 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943, 22961, + 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029, 23039, 23041, 23053, 23057, + 23059, 23063, 23071, 23081, 23087, 23099, 23117, 23131, 23143, 23159, 23167, 23173, 23189, + 23197, 23201, 23203, 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, + 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, 23459, 23473, 23497, + 23509, 23531, 23537, 23539, 23549, 23557, 23561, 23563, 23567, 23581, 23593, 23599, 23603, + 23609, 23623, 23627, 23629, 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, + 23743, 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, 23831, 23833, + 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, 23911, 23917, 23929, 23957, 23971, + 23977, 23981, 23993, 24001, 24007, 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, + 24083, 24091, 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, 24179, + 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, 24317, 24329, 24337, 24359, + 24371, 24373, 24379, 24391, 24407, 24413, 24419, 24421, 24439, 24443, 24469, 24473, 24481, + 24499, 24509, 24517, 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659, + 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767, 24781, 24793, 24799, + 24809, 24821, 24841, 24847, 24851, 24859, 24877, 24889, 24907, 24917, 24919, 24923, 24943, + 24953, 24967, 24971, 24977, 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, + 25097, 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, 25189, 25219, + 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, 25307, 25309, 25321, 25339, 25343, + 25349, 25357, 25367, 25373, 25391, 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, + 25469, 25471, 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603, 25609, + 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693, 25703, 25717, 25733, 25741, + 25747, 25759, 25763, 25771, 25793, 25799, 25801, 25819, 25841, 25847, 25849, 25867, 25873, + 25889, 25903, 25913, 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, + 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, 26113, 26119, 26141, + 26153, 26161, 26171, 26177, 26183, 26189, 26203, 26209, 26227, 26237, 26249, 26251, 26261, + 26263, 26267, 26293, 26297, 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, + 26399, 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497, 26501, 26513, + 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633, 26641, 26647, 26669, 26681, 26683, + 26687, 26693, 26699, 26701, 26711, 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, + 26783, 26801, 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891, 26893, + 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, 26993, 27011, 27017, 27031, + 27043, 27059, 27061, 27067, 27073, 27077, 27091, 27103, 27107, 27109, 27127, 27143, 27179, + 27191, 27197, 27211, 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, + 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449, 27457, 27479, 27481, + 27487, 27509, 27527, 27529, 27539, 27541, 27551, 27581, 27583, 27611, 27617, 27631, 27647, + 27653, 27673, 27689, 27691, 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, + 27767, 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827, 27847, 27851, + 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, 27953, 27961, 27967, 27983, 27997, + 28001, 28019, 28027, 28031, 28051, 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, + 28123, 28151, 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, 28289, + 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, 28409, 28411, 28429, 28433, + 28439, 28447, 28463, 28477, 28493, 28499, 28513, 28517, 28537, 28541, 28547, 28549, 28559, + 28571, 28573, 28579, 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649, + 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729, 28751, 28753, 28759, + 28771, 28789, 28793, 28807, 28813, 28817, 28837, 28843, 28859, 28867, 28871, 28879, 28901, + 28909, 28921, 28927, 28933, 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, + 29059, 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167, 29173, 29179, + 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251, 29269, 29287, 29297, 29303, 29311, + 29327, 29333, 29339, 29347, 29363, 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, + 29437, 29443, 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, 29581, + 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671, 29683, 29717, 29723, 29741, + 29753, 29759, 29761, 29789, 29803, 29819, 29833, 29837, 29851, 29863, 29867, 29873, 29879, + 29881, 29917, 29921, 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059, + 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137, 30139, 30161] + +/-- Kernel check that every entry of `primeList` passes the trial-division test. -/ +theorem primeList_check : primeList.all isPrimeB = true := by decide +kernel + +/-- `primeList` is strictly increasing. -/ +theorem primeList_chain : List.IsChain (· < ·) primeList := by decide +kernel + +/-- `primeList` has 1000 entries. -/ +theorem primeList_length : primeList.length = 1000 := by decide +kernel + +/-- The primes of the counterexample, indexed by `Fin 1000`. -/ +def p (i : Fin 1000) : ℕ := primeList.getD i 0 + +/-- Each `p i` is an entry of `primeList`. -/ +theorem p_eq (i : Fin 1000) : p i = primeList[i.val]'(by rw [primeList_length]; exact i.isLt) := by + unfold p; rw [List.getD_eq_getElem] + +/-- Each `p i` is prime. -/ +theorem p_prime (i : Fin 1000) : (p i).Prime := by + rw [p_eq] + apply isPrimeB_sound + exact List.all_eq_true.mp primeList_check _ (List.getElem_mem _) + +/-- `p` is strictly increasing. -/ +theorem p_strictMono : StrictMono p := by + intro i j hij + rw [p_eq, p_eq] + exact (List.sortedLT_iff_isChain.mpr primeList_chain).getElem_lt_getElem_of_lt hij + +/-- The first prime is `20011`. -/ +theorem p_zero : p 0 = 20011 := by decide +kernel + +/-- The last prime is `30161`. -/ +theorem p_last : p 999 = 30161 := by decide +kernel + +/-- Every `p i` is at least `20011`. -/ +theorem p_ge (i : Fin 1000) : 20011 ≤ p i := by + rw [← p_zero]; exact p_strictMono.monotone (Fin.zero_le i) + +/-- The removed classes: the upper half `{⌈p_i/2⌉, …, p_i - 1}` of the residues mod `p_i`. -/ +def A (i : Fin 1000) : Finset (ZMod (p i)) := + (Finset.Ico ((p i + 1) / 2) (p i)).image (fun n : ℕ => (n : ZMod (p i))) + +/-- `A i` consists of exactly `⌊p_i / 2⌋` residue classes. -/ +theorem card_A (i : Fin 1000) : (A i).card = p i / 2 := by + unfold A + rw [Finset.card_image_of_injOn] + · simp only [Nat.card_Ico]; omega + · intro a ha b hb hab + simp only [Finset.coe_Ico, Set.mem_Ico] at ha hb + rw [ZMod.natCast_eq_natCast_iff'] at hab + rwa [Nat.mod_eq_of_lt ha.2, Nat.mod_eq_of_lt hb.2] at hab + +/-- Every `x ≤ 10005` avoids all the removed classes. -/ +theorem survives {x : ℕ} (hx : x ≤ 10005) (i : Fin 1000) : (x : ZMod (p i)) ∉ A i := by + have hp := p_ge i + intro hmem + simp only [A, Finset.mem_image, Finset.mem_Ico] at hmem + obtain ⟨y, ⟨hy1, hy2⟩, hxy⟩ := hmem + rw [ZMod.natCast_eq_natCast_iff', Nat.mod_eq_of_lt hy2, Nat.mod_eq_of_lt (by omega)] at hxy + omega + +/-- Green's Problem 44 has a negative answer as formalized: sieving `[100000]` by the upper halves +of the residue classes modulo the 1000 primes `20011, …, 30161` (all below `100000^{9/10}`) leaves +at least `10005 > 100000/10` numbers. -/ +theorem green_44_false : ¬ (type_of% @Green44.green_44) := by + intro h + have key := h 100000 p A p_prime p_strictMono (by rw [p_last]; norm_num) card_A + have hsub : Finset.Icc 1 10005 ⊆ (Finset.Icc 1 100000).filter + (fun x => ∀ i, (x : ZMod (p i)) ∉ A i) := by + intro x hx + simp only [Finset.mem_Icc] at hx + simp only [Finset.mem_filter, Finset.mem_Icc] + exact ⟨⟨hx.1, by omega⟩, fun i => survives hx.2 i⟩ + have hcard := Finset.card_le_card hsub + simp only [Nat.card_Icc] at hcard + omega + +end Math0.Green44 + +#math0_refutes Math0.Green44.green_44_false Green44.green_44 diff --git a/lean/Math0/OEIS/OeisA51903_conjecture2.lean b/lean/Math0/OEIS/OeisA51903_conjecture2.lean new file mode 100644 index 0000000..9b587f8 --- /dev/null +++ b/lean/Math0/OEIS/OeisA51903_conjecture2.lean @@ -0,0 +1,112 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.OEIS.«51903» +import Math0.Audit + +/-! +# No odd n with a(n) > 1 satisfies b^n ≡ b^a(n) (mod n) for all b (OEIS A051903) + +Thomas Ordowski (OEIS A051903, Dec 2019) asked whether there are odd numbers `n` with +`a(n) > 1` (where `a(n)` is the largest exponent in the prime factorization of `n`) such that +`b ^ n ≡ b ^ a(n) (mod n)` for every `b`. We prove that there are none, i.e. the negation of the +upstream statement. If `e = a(n) ≥ 2` and `p ^ e ∣ n` (necessarily `p` odd), take `b = p + 1`; +cancelling the unit `(p+1)^e` gives `p ^ e ∣ (p+1)^(n-e) - 1`, and lifting the exponent gives +`v_p((p+1)^(n-e) - 1) = 1 + v_p(n-e)`, so `p^(e-1) ∣ n - e`. Together with `p^(e-1) ∣ n` this +forces `p^(e-1) ∣ e`, impossible since `p^(e-1) ≥ 3^(e-1) > e`. +-/ + +namespace Math0.OeisA51903 + +/-- `foldr max 0` of a list of naturals is either `0` or an element of the list. -/ +lemma foldr_max_zero_or_mem (L : List ℕ) : L.foldr max 0 = 0 ∨ L.foldr max 0 ∈ L := by + induction L with + | nil => simp + | cons x L ih => + simp only [List.foldr_cons, List.mem_cons] + rcases max_choice x (L.foldr max 0) with h | h + · rw [h]; exact Or.inr (Or.inl rfl) + · rw [h] + rcases ih with h' | h' + · exact Or.inl h' + · exact Or.inr (Or.inr h') + +/-- If `a n` is positive, it is the exponent of some prime `p` in `n`. -/ +lemma exists_prime_factorization_eq (n : ℕ) (h : 0 < OeisA51903.a n) : + ∃ p, p.Prime ∧ n.factorization p = OeisA51903.a n := by + unfold OeisA51903.a at * + rcases foldr_max_zero_or_mem (n.primeFactorsList.map (n.primeFactorsList.count ·)) with h' | h' + · omega + · obtain ⟨p, hp, hpe⟩ := List.mem_map.mp h' + exact ⟨p, Nat.prime_of_mem_primeFactorsList hp, by rw [← Nat.primeFactorsList_count_eq, hpe]⟩ + +/-- `k + 1 < 3 ^ k` for `k ≥ 1`. -/ +lemma succ_lt_three_pow (k : ℕ) (hk : 1 ≤ k) : k + 1 < 3 ^ k := by + induction k with + | zero => omega + | succ k ih => + rcases Nat.eq_zero_or_pos k with rfl | hk' + · norm_num + · have := ih hk' + rw [pow_succ]; omega + +/-- Core: if `p` is an odd prime, `e ≥ 2`, `p ^ e ∣ n` and `(p+1)^n ≡ (p+1)^e [MOD n]`, then we +reach a contradiction. -/ +lemma core (n p e : ℕ) (hp : p.Prime) (hpodd : Odd p) (he : 2 ≤ e) (hn : n ≠ 0) + (hdvd : p ^ e ∣ n) (hb : (p + 1) ^ n ≡ (p + 1) ^ e [MOD n]) : False := by + have := Fact.mk hp + have hp1 : 1 < p := hp.one_lt + have hpe_le : p ^ e ≤ n := Nat.le_of_dvd (Nat.pos_of_ne_zero hn) hdvd + have he_lt : e < p ^ e := Nat.lt_pow_self hp1 + obtain ⟨m, rfl⟩ : ∃ m, n = e + m := ⟨n - e, by omega⟩ + have hm : m ≠ 0 := by omega + have hb' : (p + 1) ^ e * (p + 1) ^ m ≡ (p + 1) ^ e * 1 [MOD p ^ e] := by + rw [← pow_add, mul_one]; exact hb.of_dvd hdvd + have hcop : Nat.gcd (p ^ e) ((p + 1) ^ e) = 1 := by + have : Nat.Coprime p (p + 1) := by simp + exact Nat.Coprime.pow e e this + have hc := Nat.ModEq.cancel_left_of_coprime hcop hb' + have hdiv : p ^ e ∣ (p + 1) ^ m - 1 := + (Nat.modEq_iff_dvd' (Nat.one_le_pow _ _ (by omega))).mp hc.symm + have hne : (p + 1) ^ m - 1 ≠ 0 := by + have : 1 < (p + 1) ^ m := Nat.one_lt_pow hm (by omega) + omega + have hv := (padicValNat_dvd_iff_le hne).mp hdiv + have hlte : padicValNat p ((p + 1) ^ m - 1 ^ m) = padicValNat p (p + 1 - 1) + padicValNat p m := + padicValNat.pow_sub_pow hpodd (by omega) (by simp) (by + intro h; have := (Nat.dvd_add_right (dvd_refl p)).mp h + exact hp.one_lt.ne' (Nat.dvd_one.mp this)) hm + rw [one_pow] at hlte + simp only [Nat.add_sub_cancel, padicValNat_self] at hlte + have hpm : p ^ (e - 1) ∣ m := + (padicValNat_dvd_iff_le hm).mpr (by omega) + have hpn : p ^ (e - 1) ∣ e + m := (pow_dvd_pow p (by omega)).trans hdvd + have hpe : p ^ (e - 1) ∣ e := (Nat.dvd_add_left hpm).mp hpn + have h1 : p ^ (e - 1) ≤ e := Nat.le_of_dvd (by omega) hpe + have h3 : 3 ≤ p := by + rcases hp.eq_two_or_odd' with h | h + · subst h; exact absurd hpodd (by decide) + · have := hp.two_le; rcases h with ⟨k, hk⟩; omega + have h2 : 3 ^ (e - 1) ≤ p ^ (e - 1) := Nat.pow_le_pow_left h3 _ + have h4 := succ_lt_three_pow (e - 1) (by omega) + omega + +/-- There is no odd `n` with `a n > 1` and `b ^ n ≡ b ^ (a n) [MOD n]` for all `b`. -/ +theorem not_conjecture2 : ¬ (type_of% @OeisA51903.conjecture2) := by + rintro ⟨n, hodd, h1, hb⟩ + obtain ⟨p, hp, hpe⟩ := exists_prime_factorization_eq n (by omega) + have hn : n ≠ 0 := by rintro rfl; exact absurd hodd (by decide) + have hdvd : p ^ OeisA51903.a n ∣ n := by + rw [← hpe]; exact Nat.ordProj_dvd n p + have hpodd : Odd p := by + rcases hp.eq_two_or_odd' with h | h + · subst h + exfalso + have : 2 ∣ n := (dvd_pow_self 2 (by omega)).trans hdvd + exact (Nat.not_even_iff_odd.mpr hodd) (even_iff_two_dvd.mpr this) + · exact h + exact core n p (OeisA51903.a n) hp hpodd h1 hn hdvd (hb (p + 1)) + +end Math0.OeisA51903 + +#math0_refutes Math0.OeisA51903.not_conjecture2 OeisA51903.conjecture2 diff --git a/lean/Math0/OEIS/OeisA51903_conjecture3.lean b/lean/Math0/OEIS/OeisA51903_conjecture3.lean new file mode 100644 index 0000000..013d765 --- /dev/null +++ b/lean/Math0/OEIS/OeisA51903_conjecture3.lean @@ -0,0 +1,51 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import FormalConjectures.OEIS.«51903» +import Math0.Audit + +/-! +# An odd $n$ with $a(n) > 1$ and $2^n \equiv 2^{a(n)} \pmod n$ + +Thomas Ordowski (OEIS A051903, Dec 2019) asked whether there are odd numbers $n$ whose maximal +prime exponent $a(n)$ exceeds $1$ and which satisfy $2^n \equiv 2^{a(n)} \pmod n$. We answer +`OeisA51903.conjecture3` positively with the explicit witness +$n = 9687963167864344937 = 7 \cdot 631 \cdot 881 \cdot 3511^2 \cdot 201961$, for which $a(n) = 2$ +and $2^n \equiv 4 \pmod n$. The factorization is certified by Mathlib's +`Nat.primeFactorsList` simproc, and the congruence by fast modular exponentiation in +`ZMod n` (`reduce_mod_char`). Conceptually, $3511$ is a Wieferich prime with +$\operatorname{ord}_{3511^2}(2) = 1755$, and the multiplicative orders of $2$ modulo the other prime +factors all divide $19305 = 11 \cdot 1755$, which divides $n - 2$. +-/ + +namespace Math0.OeisA51903 + +/-- The prime factorization of the witness: `N = 7 * 631 * 881 * 3511 ^ 2 * 201961`. -/ +theorem primeFactorsList_N : + Nat.primeFactorsList 9687963167864344937 = [7, 631, 881, 3511, 3511, 201961] := by + simp only [Nat.primeFactorsList_ofNat] + +/-- The maximal exponent in the prime factorization of the witness is `2`. -/ +theorem a_N : OeisA51903.a 9687963167864344937 = 2 := by + rw [OeisA51903.a, primeFactorsList_N] + decide + +/-- `2 ^ N = 4` in `ZMod N`, by fast modular exponentiation. -/ +theorem two_pow_N_zmod : (2 : ZMod 9687963167864344937) ^ 9687963167864344937 = 4 := by + reduce_mod_char + +/-- `2 ^ N ≡ 2 ^ 2 [MOD N]`. -/ +theorem two_pow_N_modEq : 2 ^ 9687963167864344937 ≡ 2 ^ 2 [MOD 9687963167864344937] := by + rw [← ZMod.natCast_eq_natCast_iff, Nat.cast_pow, Nat.cast_pow, Nat.cast_ofNat, two_pow_N_zmod] + rfl + +/-- There is an odd `n` with `a n > 1` and `2 ^ n ≡ 2 ^ (a n) [MOD n]`, namely +`n = 7 * 631 * 881 * 3511 ^ 2 * 201961`. -/ +theorem conjecture3 : type_of% @OeisA51903.conjecture3 := by + refine ⟨9687963167864344937, ⟨4843981583932172468, by norm_num⟩, ?_, ?_⟩ + · rw [a_N]; decide + · rw [a_N]; exact two_pow_N_modEq + +end Math0.OeisA51903 + +#math0_proves Math0.OeisA51903.conjecture3 OeisA51903.conjecture3 diff --git a/lean/Math0/Statements.lean b/lean/Math0/Statements.lean new file mode 100644 index 0000000..9729355 --- /dev/null +++ b/lean/Math0/Statements.lean @@ -0,0 +1,121 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Statements.OEIS.A001040 +import Math0.Statements.OEIS.A005590 +import Math0.Statements.OEIS.A022445 +import Math0.Statements.OEIS.A057566 +import Math0.Statements.OEIS.A057566b +import Math0.Statements.OEIS.A060693 +import Math0.Statements.OEIS.A062887 +import Math0.Statements.OEIS.A071685 +import Math0.Statements.OEIS.A073642 +import Math0.Statements.OEIS.A075855 +import Math0.Statements.OEIS.A081200 +import Math0.Statements.OEIS.A083020 +import Math0.Statements.OEIS.A086004 +import Math0.Statements.OEIS.A090905 +import Math0.Statements.OEIS.A091817 +import Math0.Statements.OEIS.A092054 +import Math0.Statements.OEIS.A093726 +import Math0.Statements.OEIS.A097154 +import Math0.Statements.OEIS.A106505 +import Math0.Statements.OEIS.A113676 +import Math0.Statements.OEIS.A115026 +import Math0.Statements.OEIS.A116184 +import Math0.Statements.OEIS.A119936 +import Math0.Statements.OEIS.A120069 +import Math0.Statements.OEIS.A121750 +import Math0.Statements.OEIS.A123710 +import Math0.Statements.OEIS.A124526 +import Math0.Statements.OEIS.A126127 +import Math0.Statements.OEIS.A127752 +import Math0.Statements.OEIS.A127755 +import Math0.Statements.OEIS.A127767 +import Math0.Statements.OEIS.A129455 +import Math0.Statements.OEIS.A132616 +import Math0.Statements.OEIS.A141412 +import Math0.Statements.OEIS.A144637 +import Math0.Statements.OEIS.A160848 +import Math0.Statements.OEIS.A172164 +import Math0.Statements.OEIS.A175385 +import Math0.Statements.OEIS.A176206 +import Math0.Statements.OEIS.A178295 +import Math0.Statements.OEIS.A182617 +import Math0.Statements.OEIS.A188474 +import Math0.Statements.OEIS.A195249 +import Math0.Statements.OEIS.A201060 +import Math0.Statements.OEIS.A209802 +import Math0.Statements.OEIS.A211343 +import Math0.Statements.OEIS.A215010 +import Math0.Statements.OEIS.A223395 +import Math0.Statements.OEIS.A229159 +import Math0.Statements.OEIS.A242396 +import Math0.Statements.OEIS.A249434 +import Math0.Statements.OEIS.A262957 +import Math0.Statements.OEIS.A265210 +import Math0.Statements.OEIS.A265649 +import Math0.Statements.OEIS.A267486 +import Math0.Statements.OEIS.A270668 +import Math0.Statements.OEIS.A275815 +import Math0.Statements.OEIS.A278212 +import Math0.Statements.OEIS.A281000 +import Math0.Statements.OEIS.A294512 +import Math0.Statements.OEIS.A300789 +import Math0.Statements.OEIS.A308107 +import Math0.Statements.OEIS.A308121 +import Math0.Statements.OEIS.A308222 +import Math0.Statements.OEIS.A308359 +import Math0.Statements.OEIS.A320099 +import Math0.Statements.OEIS.A323695 +import Math0.Statements.OEIS.A326407 +import Math0.Statements.OEIS.A326602 +import Math0.Statements.OEIS.A328202 +import Math0.Statements.OEIS.A332010 +import Math0.Statements.OEIS.A333650 +import Math0.Statements.OEIS.A334592 +import Math0.Statements.OEIS.A334595 +import Math0.Statements.OEIS.A334603 +import Math0.Statements.OEIS.A335012 +import Math0.Statements.OEIS.A338885 +import Math0.Statements.OEIS.A341761 +import Math0.Statements.OEIS.A342645 +import Math0.Statements.OEIS.A342992 +import Math0.Statements.OEIS.A344710 +import Math0.Statements.OEIS.A348484 +import Math0.Statements.OEIS.A350499 +import Math0.Statements.OEIS.A350557 +import Math0.Statements.OEIS.A350900 +import Math0.Statements.OEIS.A351743 +import Math0.Statements.OEIS.A354571 +import Math0.Statements.OEIS.A355076 +import Math0.Statements.OEIS.A355339 +import Math0.Statements.OEIS.A355360 +import Math0.Statements.OEIS.A356360 +import Math0.Statements.OEIS.A357216 +import Math0.Statements.OEIS.A357583 +import Math0.Statements.OEIS.A362086 +import Math0.Statements.OEIS.A363482 +import Math0.Statements.OEIS.A363609 +import Math0.Statements.OEIS.A367119 +import Math0.Statements.OEIS.A368846 +import Math0.Statements.OEIS.A369366 +import Math0.Statements.OEIS.A373345 +import Math0.Statements.OEIS.A373359 +import Math0.Statements.OEIS.A375522 +import Math0.Statements.OEIS.A386538 +import Math0.Statements.OEIS.A386655 +import Math0.Statements.OEIS.A388724 +import Math0.Statements.OEIS.A392943 +import Math0.Statements.OEIS.A393794 +import Math0.Statements.OEIS.A394981 +import Math0.Statements.OEIS.A395454 +import Math0.Statements.OEIS.A397315 + +/-! +# Frozen statements + +Imports every statement listed in `Math0/Statements/FROZEN.sha256`: the conjectures that math0 +formalized itself, each fidelity-reviewed and frozen before any proof attempt. Some are not yet +settled by any result. +-/ diff --git a/lean/Math0/Statements/FROZEN.sha256 b/lean/Math0/Statements/FROZEN.sha256 new file mode 100644 index 0000000..3146682 --- /dev/null +++ b/lean/Math0/Statements/FROZEN.sha256 @@ -0,0 +1,110 @@ +55c35a6ccda4ac6f9797b4e00e2cdd8a2b8aad9e35dca6da0ee246888de4288f OEIS/A005590.lean +218f1d785c0336bb2e5abbd739ca601fc11e5353b5c5c3546cc7a8fa14246ec5 OEIS/A057566.lean +7877842d97572f980cff846160a85c51cf0a650db22558b4b146782df2576b90 OEIS/A060693.lean +544c69cdd8e8fc64e48631e71fd9cdbea42b4521aa049b3391d5f7f69e77a828 OEIS/A062887.lean +0a3757cb23f2e3fda6c8be46ce23370d83db0808d0e849ebb1f3659249940c95 OEIS/A071685.lean +cf003192cf181ce8b60b821baf8cbee347f45ea89271e9be80f5c1b65851a12c OEIS/A073642.lean +2740c3cea419ce17abaf3648d27a20ff79dce2773f7db784c141a584b0a1a45c OEIS/A075855.lean +41ab2753b05020385fd32c254870891707bbee66d7f806aadcab080aaa9c3232 OEIS/A081200.lean +d520c66622e22341e5f1ab84e086464d32c9a8754255489488947b4c084ae473 OEIS/A083020.lean +adb8cf05ead84b9e12f9c33a26b89e4fb43af897c09a09aa624e55c3bb73eb5d OEIS/A086004.lean +8616fe975284f541ef01bbf111b3da1d1ee1888216fc02639bb4c8139ab42a44 OEIS/A090905.lean +0debd9c59a4d46337f8ccbec57ff7b7cc49252628ecae3c12bbac70cf2696844 OEIS/A091817.lean +adfff33f8020331c23e3b68ecfb8b9763db51c948e27909395bf3438bc76b2b3 OEIS/A092054.lean +5d599ac441eb4e1fe5dff22eac3986632062d42308eb0d3fe99f55e08f83a0ba OEIS/A093726.lean +1d7d144b852350764a5a1a6dcfd1e1bf9f5a743d3dc65930164476f67f92cbb8 OEIS/A097154.lean +f1815676be529fc38551343442651d0c3c627764d08c55f46e2ac1499b6399ac OEIS/A106505.lean +a80c3eb1efd0f394eaa3d266451c06c216f3d22bfae357ecf292126ff21afab5 OEIS/A113676.lean +39ccb0d4f52456e1f6c5c8cec62142443fec7ca4e339be3efb999ee586e799b1 OEIS/A115026.lean +a38dde38b33198a03ca30bc9be8f079101052ea1c6c5b5375c51234f01c163f9 OEIS/A116184.lean +dadd10f30a1e58a3b43569c6ba0779bbdbd9bca8e1687671e6d0f72cfcfaafc5 OEIS/A119936.lean +9c2a2c609b24301cd298c468047679430c47e8838c0f56b3f5d42d1f93d26485 OEIS/A120069.lean +c1f77c15d7d1963116580dbf9871ce99ca5b42f878e3902ed97f632208d7414b OEIS/A121750.lean +aa643c9b34447de593ff28c5e861378a376cb02dd885aa9a5cea7e6cc9c47325 OEIS/A124526.lean +9f79e91f1d7f95a3a0b07ac10041f604c671e5d08bfcd07415fb5999080f38ec OEIS/A127752.lean +e61b7ad251709cf414ac02e8742ce676cd931875aac11d096a8605db95ba9dce OEIS/A127767.lean +f807271b67fcc732750c011c90b081a7cbe778c7cf5773e10353f65e73dd80c5 OEIS/A129455.lean +3f92df650724722145d1b8f4cfb842c242774539970a00eec935beefdf733b77 OEIS/A141412.lean +8883f318d50777c4dd6b3c98e9a90c047a5046c79a27b3ed91367f0c278633f3 OEIS/A160848.lean +948ca46adfb7386febe5625ddfb1b20536c53ea8bda29c2a4430ed26b30be5f4 OEIS/A172164.lean +3e8f66aef92198462837cd5e9730c934a11ef4b9f1ffba8daf2638fcc83c8654 OEIS/A175385.lean +4f45cfdc6899fba12d3522880eec5ab40965ff90b8d45e5caab1789f2ddd5c8e OEIS/A176206.lean +70638d821a44ae1509bbbb2db3d6467d44b0cfb0983c30ff1073dd1d4bbcc412 OEIS/A178295.lean +ee654c515b89030f547bc0a0d0daeff3ba7a23fa67c35f20f587717908ffe44c OEIS/A195249.lean +902fc983123ab24699bbbdd3991485b9ffc962d55478c132676a7698c72af72b OEIS/A201060.lean +4eed8d995f35f5847b16759285639c6145c32695d9e6a92fb1b098ced50abf0d OEIS/A209802.lean +bc8da2da1c805150a00114e619f65cc51d26813ef1003868359a1f3113ac897e OEIS/A211343.lean +740251a234d79e76f05386f27cf26d506c3ec8ea9ba485d9d0c13e644c2fe40a OEIS/A215010.lean +12e141644f29d6fea94630e985ea6d96f35688f7de15bff589d548dcdf232809 OEIS/A223395.lean +634d66ee1af46cbc91d73095757e0861abacef53afa6887e0ba4df369590481a OEIS/A229159.lean +35a266981a9f235aba6be189940a3573e9447b74f2e966fc2da862bd24685b7d OEIS/A242396.lean +638b565a518f598889471d0687f9bc0a88b0542527e37fe65ce00e223ea3cb4a OEIS/A249434.lean +a21c48e26c8f676d0ed5300329e2de9c0700cc2c3612e155d8b6d890c0895207 OEIS/A262957.lean +56201c4b79c9d20613902fc9b83e0a04b5e9b44443fc64ac2ad5d994fe6fca62 OEIS/A265210.lean +6dac026f854874371bf121fdffc6e4209c43f171dc485a9d48bd112f69c55939 OEIS/A270668.lean +590fb1aa704caacbcf28997c87eece703ec9d2dbef1f1ddc1abdad42c6e507b9 OEIS/A278212.lean +4230cf53361015ca1f19b85208b457580cd71fd784cd442ff83f14045549c030 OEIS/A281000.lean +20fd25a6c3713378deaa29200141601bff1161a91ca716173b1f9822e3f89848 OEIS/A294512.lean +6d088323acf8d404c50c424958d48ec5ac7696c541df6f4343d5eecda72b05be OEIS/A300789.lean +e5f81c2e9bb74313773f25170517f4e286caf29fa1e0ab0151c0a6a169516275 OEIS/A308107.lean +70da202ad6a744a8491b4f0978dc52f81b06accd21b7990fff603350a64c9e58 OEIS/A308121.lean +99173e0012cf358d2dfdccbd16822abad7de8bdebc3b47800da448a0bcb2b7c8 OEIS/A308222.lean +84eea4b2ea212a9510170a9ad59a42bffbdb4f67be8e1e6760dc9774d3bc80f7 OEIS/A308359.lean +6d745374120a100a71c7cac753455c0196bec229c48505d2e8e624e6a16b8edd OEIS/A323695.lean +32bef0c0a9dd47952ef2b94a6974a1bb684efb7ab53ef4b8c78db164c6fc912e OEIS/A326407.lean +dcf51cfef57550694165f10688cb4b12039075f71433ebb1831f9f72e1459137 OEIS/A326602.lean +4021583e12222dea7327f5ba325aa8f07f395bbb5f577d2e3b02aecbe44ca08f OEIS/A328202.lean +4e58e0c38c885a74731ccb0bf2f54abb6c7d156cd22d1471729daec4057c09cd OEIS/A332010.lean +20320a51f9e10f74b02889857bbdfc4c7630c647ce7166657167bc8e99b96302 OEIS/A333650.lean +2bee900443c8d10461d85716926e5e26eb85e40745d90f50ca759134363ebc74 OEIS/A334595.lean +c38de19325417aa3570901c8ac187090fdedec6f4ef3eee3b641881d9e797c4b OEIS/A334603.lean +954d748db3ba63c69e9a3777eec574030f54743f7620154a575ff53abc0dbf31 OEIS/A335012.lean +c2422329710afb57ae9b4de04fb82e808b7be05268de455499903738a45e84db OEIS/A338885.lean +827988f433a3f75766558285596f166b594b353384faf9cc83702a29a01faf23 OEIS/A341761.lean +d47836b6957a9d51523fde75b0141035b767124c9b9ab6c180cbf64d665454d7 OEIS/A342992.lean +4f0e694003106fdfbc221abc928cb722f7c3149305141f3e60ad1961546fdf74 OEIS/A344710.lean +6dc8c7d53b20104de8b54fb4db1a92285f18c75227594a45cf6b8c3c1a045c66 OEIS/A348484.lean +814a4e45141b93b90dd5a050f9e85f26d473c5f2a6268fca9f28aa2d1b9fb09b OEIS/A350900.lean +41c82d152e58215f033c74de1ed3fccf80c0e8769bdd3e4974c1c834911647d3 OEIS/A351743.lean +8b6ac74ee20c9e298dbbcde0517edcdee7cb2e6d72b6da1c7e87f5070b8ca9ee OEIS/A354571.lean +e42856b0b7d86109b4648353bad024e50b438b36bcbc7705085f54ec9ed9d970 OEIS/A355076.lean +ea5b1be936111ecddc51d55cf0dce0afd018039591a6db4c16379af50ca4226b OEIS/A355339.lean +be296be341a144d0b5d4aad758eda3fd34db999af63c17bbd269c9515157f2d8 OEIS/A356360.lean +0b6d14197885221de2b8f9c9ad70aeb1eb92096adbab2bfd1cf36521a2635391 OEIS/A357216.lean +e91312615635140cee9edd60a8f67a60e29904718cd6bef797dd6f8ebf23d272 OEIS/A362086.lean +554979080db513d10f640a2e5c69f301190de8790d3ff862c433744f9886e5ef OEIS/A363482.lean +aec2c052b1f6de939669ad4050002a7bdc07b80471a8641f24079bede9245afe OEIS/A363609.lean +0972bcc5ed061e13de39c30fc789007a8ddb82ff26d0f2cbf4320dee54415bc4 OEIS/A367119.lean +3bce9518b42ab01d3f698dd705193abb28a4ce4fa486116f77fa050416a41216 OEIS/A369366.lean +75365247ced9b0a3f3f3ee6845e5fe7b58640a291361843e820fe753b02d4101 OEIS/A373345.lean +3eec79b432e282524e35eefb487c319c8cacb5ea61bbdaedd1a6161928ced342 OEIS/A375522.lean +9fb23f8d26af543176b8e57e0f9f0af27048abe22ad6f1bb2306eb9a2b1ef2f1 OEIS/A386538.lean +282e82030d617a91ea3d8a8dbe0ffb4eee86117083902e12b6d2be168c7e5019 OEIS/A386655.lean +62a9cf37148d7929b24a4419ec7a16ad2aa49db01dc231154899c5a259798e04 OEIS/A388724.lean +efec1ccc0c3a69056536f90c8b5be898c3d8d3617df812a212206fec893a3a4a OEIS/A392943.lean +3c0423ef0cfbf9698b14eb56b4d94acf1fa8ae5ad36b94de1237d245982ae69a OEIS/A393794.lean +682012a2d63576573ce2087792f33826a7586a12f9b9bba0bbf83baec25dfdde OEIS/A394981.lean +99c82099965efd27f50b634e213acbf564d726caf5d6de833cbbc46079f6646d OEIS/A395454.lean +81afd722eda9f833e6180924ef2850634e1138bf58732cce8a699639eba61c5d OEIS/A397315.lean +0d85e29f09f86f38abd6351bcf2b8c0dc2c5554825851e6f56b0c3811e6fc736 OEIS/A275815.lean +36df3ff733f4963c067b4b9dda2c7923bf5e484cfd14577238a87e8544a8e940 OEIS/A182617.lean +1626c1a2ef06dbe68c3339c0a6e7112ffe22212059c468fd744f0b433af386b5 OEIS/A368846.lean +ef2846c23b21a21c5f938d50a69a5d94db5226690e324ecea48b93214c1327c7 OEIS/A265649.lean +c5000581ba0812117c36e624c67403be963da9ad594b1fd7f466116f219ccc3e OEIS/A022445.lean +42c75f86f4752805dea143467000e275da8236a595b72bbe4d761a22676a1663 OEIS/A127755.lean +58447d499afd3c54114e8b0cb07cb1bca999d26a092da31d5ab1a6334d84fd37 OEIS/A144637.lean +ae118b7b810da3aa2406346dce5016d5bcebf30004cf89fe0c8d3e5a21dcefb0 OEIS/A334592.lean +0b48f808fc26390f813a753f148675955691cbfb901e6d38dd556761c5465eb3 OEIS/A350557.lean +f34de1a74d8bffb3eb2adecf6c4f9f7cfba693416266bc4ef0f5c9fa0672266c OEIS/A373359.lean +c7ed59c518ff0d2ca965e52e6551569ff425c7ca15a445db1dd3d1d092e735b6 OEIS/A188474.lean +9dab69782ba601f1cf308041c7d1f338f997627a37c217711b7b414c630402aa OEIS/A123710.lean +7a0383fa5f7fa3e76f6aec686c18b94c8565334fa5124f2c9db6b8a2afcf07e5 OEIS/A357583.lean +54bac3e5b5d601cb6ae984d96789c244500d6952340ab44088a89d508ace81f2 OEIS/A350499.lean +1b01c34066b7cd772ca0bd4bdda797d149ebc06d01009b88984c29683426a2a1 OEIS/A342645.lean +26eeeedb4146cfe6d2ee06e23cc23ca2a05d1e44e6f49a856d201240e5fab5bf OEIS/A057566b.lean +e2d0850e0b894852674ace16cde0aa920458911bd3e59f3d62057b580f33768b OEIS/A320099.lean +583aa2e0e1c311c5bb6b0dbe9eb74f53fb2db61614344798923cfa3cf67a0d3b OEIS/A267486.lean +9ffb27422cc593615682cf74fb6393dd0b9fa95a1fd20760454f6d1e69ea986f OEIS/A132616.lean +071aa0aa0de4832c6bd35d7e44dd5c6aae637bb3ed6d6ff4ffcde459f79ea183 OEIS/A126127.lean +3ac3c378c29e872001bbf067bb2ff68b2fe3404c1b9a0373b993910ade66ece6 OEIS/A001040.lean +39bb830d3ada926f3e9a9c8fe6fa37c34ec6423923b3301ff4e93da27d17aa56 OEIS/A355360.lean diff --git a/lean/Math0/Statements/FROZEN_WITH_PROOF.txt b/lean/Math0/Statements/FROZEN_WITH_PROOF.txt new file mode 100644 index 0000000..38ffe47 --- /dev/null +++ b/lean/Math0/Statements/FROZEN_WITH_PROOF.txt @@ -0,0 +1,94 @@ +OEIS/A005590.lean +OEIS/A057566.lean +OEIS/A060693.lean +OEIS/A062887.lean +OEIS/A071685.lean +OEIS/A073642.lean +OEIS/A075855.lean +OEIS/A081200.lean +OEIS/A083020.lean +OEIS/A086004.lean +OEIS/A090905.lean +OEIS/A091817.lean +OEIS/A092054.lean +OEIS/A093726.lean +OEIS/A097154.lean +OEIS/A106505.lean +OEIS/A113676.lean +OEIS/A115026.lean +OEIS/A116184.lean +OEIS/A119936.lean +OEIS/A120069.lean +OEIS/A121750.lean +OEIS/A124526.lean +OEIS/A127752.lean +OEIS/A127767.lean +OEIS/A129455.lean +OEIS/A141412.lean +OEIS/A160848.lean +OEIS/A172164.lean +OEIS/A175385.lean +OEIS/A176206.lean +OEIS/A178295.lean +OEIS/A195249.lean +OEIS/A201060.lean +OEIS/A209802.lean +OEIS/A211343.lean +OEIS/A215010.lean +OEIS/A223395.lean +OEIS/A229159.lean +OEIS/A242396.lean +OEIS/A249434.lean +OEIS/A262957.lean +OEIS/A265210.lean +OEIS/A270668.lean +OEIS/A278212.lean +OEIS/A281000.lean +OEIS/A294512.lean +OEIS/A300789.lean +OEIS/A308107.lean +OEIS/A308121.lean +OEIS/A308222.lean +OEIS/A308359.lean +OEIS/A323695.lean +OEIS/A326407.lean +OEIS/A326602.lean +OEIS/A328202.lean +OEIS/A332010.lean +OEIS/A333650.lean +OEIS/A334595.lean +OEIS/A334603.lean +OEIS/A335012.lean +OEIS/A338885.lean +OEIS/A341761.lean +OEIS/A342992.lean +OEIS/A344710.lean +OEIS/A348484.lean +OEIS/A350900.lean +OEIS/A351743.lean +OEIS/A354571.lean +OEIS/A355076.lean +OEIS/A355339.lean +OEIS/A356360.lean +OEIS/A357216.lean +OEIS/A362086.lean +OEIS/A363482.lean +OEIS/A363609.lean +OEIS/A367119.lean +OEIS/A369366.lean +OEIS/A373345.lean +OEIS/A375522.lean +OEIS/A386538.lean +OEIS/A386655.lean +OEIS/A388724.lean +OEIS/A392943.lean +OEIS/A393794.lean +OEIS/A394981.lean +OEIS/A395454.lean +OEIS/A397315.lean +OEIS/A022445.lean +OEIS/A127755.lean +OEIS/A144637.lean +OEIS/A334592.lean +OEIS/A350557.lean +OEIS/A373359.lean diff --git a/lean/Math0/Statements/OEIS/A001040.lean b/lean/Math0/Statements/OEIS/A001040.lean new file mode 100644 index 0000000..222ff4f --- /dev/null +++ b/lean/Math0/Statements/OEIS/A001040.lean @@ -0,0 +1,146 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A001040: Kurkov's rook-tour interpretation of `2 · n! · a(n)` + +Source: https://oeis.org/A001040, Mikhail Kurkov, Nov 19 2019 (COMMENTS section). Verbatim: +> Conjecture: 2*n!*a(n) is the number of open tours by a rook on an (n X 2) chessboard which +> ends at the opposite line of length n. + +The sequence (offset `0`) is "a(n+1) = n*a(n) + a(n-1) with a(0)=0, a(1)=1." + +## Encoding + +* `a` is the defining recursion `a 0 = 0`, `a 1 = 1`, `a (n + 2) = (n + 1) * a (n + 1) + a n` + (the OEIS recursion `a(m+1) = m*a(m) + a(m-1)` with `m = n + 1 ≥ 1`). `a_data` checks all 24 + listed terms `a 0, …, a 23`. +* The `n × 2` board is `Fin n × Fin 2`: the square `(i, c)` is the `i`-th square of the line `c` + of length `n` (there are two such lines, `c = 0` and `c = 1`; the `n` short rows of length `2` + are the sets `{(i, 0), (i, 1)}`). +* A rook move (`RookMove`) goes between two different squares in the same row or in the same + line; the rook may move any distance and pass over squares (visited or not). This is the + adjacency of the rook graph `K_n □ K_2` (`rookMove_iff`, stated with Mathlib's `boxProd`). +* An open tour (`IsOpenTour n l`) is a sequence `l` of squares that visits every square exactly + once (`l.Nodup` and every square is in `l`) and in which consecutive squares are a rook move + apart (`l.IsChain RookMove`), i.e. a Hamiltonian path of the rook graph, read with its + direction (a tour and its reversal are different tours). It "ends at the opposite line" + (`EndsOnOppositeLine l`) when its first and last squares lie in different lines of length `n`. +* Reading choices, both forced by the listed data at `n = 1` (where `2 · 1! · a(1) = 2`): on the + `1 × 2` board the only open tours are `(0,0) → (0,1)` and `(0,1) → (0,0)`, so tours are counted + as directed sequences (undirected paths would give `1`), and "open" means "not required to + return to its start", not "its ends are not a rook move apart" (that reading would give `0`). +* The count is the `Set.ncard` of the set of such lists. The set is finite; `ncard_eq_card_tours` + identifies it with the computable `Finset` `tours n` (orderings of the squares, filtered), and + `tours_card_small` kernel-checks the counts `2, 4, 36, 480` for `n = 1, 2, 3, 4`, which equal + `2 · n! · a(n)` (these values only test the encoding; they are not part of the statement). +* The conjecture is stated for every board size `n ≥ 1`. (For `n = 0` both sides are `0` under + this encoding, see `tours_zero`, so nothing would change if `n = 0` were included.) +-/ + +namespace Math0.Statements.A001040 + +open Nat + +/-- A001040: `a(0) = 0`, `a(1) = 1`, `a(n+1) = n*a(n) + a(n-1)`. -/ +def a : ℕ → ℕ + | 0 => 0 + | 1 => 1 + | n + 2 => (n + 1) * a (n + 1) + a n + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 24).map (fun i => a (i + 0)) = + [0, 1, 1, 3, 10, 43, 225, 1393, 9976, 81201, 740785, 7489051, 83120346, 1004933203, + 13147251985, 185066460993, 2789144166880, 44811373131073, 764582487395121, + 13807296146243251, 263103209266016890, 5275871481466581051, 111056404320064218961, + 2448516766522879398193] := by + decide +kernel + +/-- A rook move on the `n × 2` board `Fin n × Fin 2` (square `(i, c)` = `i`-th square of the +line `c`): between two different squares in the same row (`i`) or in the same line (`c`). -/ +def RookMove {n : ℕ} (p q : Fin n × Fin 2) : Prop := + p ≠ q ∧ (p.1 = q.1 ∨ p.2 = q.2) + +instance {n : ℕ} : DecidableRel (@RookMove n) := fun p q => by + unfold RookMove; infer_instance + +/-- Rook moves are the edges of the rook graph `K_n □ K_2`. -/ +theorem rookMove_iff {n : ℕ} (p q : Fin n × Fin 2) : + RookMove p q ↔ ((⊤ : SimpleGraph (Fin n)) □ (⊤ : SimpleGraph (Fin 2))).Adj p q := by + obtain ⟨i, c⟩ := p + obtain ⟨j, d⟩ := q + simp only [RookMove, SimpleGraph.boxProd_adj, SimpleGraph.top_adj, ne_eq, Prod.mk.injEq] + tauto + +/-- An open rook tour of the `n × 2` board: a sequence of squares visiting every square exactly +once, consecutive squares being a rook move apart. -/ +def IsOpenTour (n : ℕ) (l : List (Fin n × Fin 2)) : Prop := + l.Nodup ∧ (∀ s, s ∈ l) ∧ l.IsChain RookMove + +/-- The sequence starts and ends in different lines of length `n`. -/ +def EndsOnOppositeLine {n : ℕ} (l : List (Fin n × Fin 2)) : Prop := + ∃ s ∈ l.head?, ∃ t ∈ l.getLast?, s.2 ≠ t.2 + +instance {n : ℕ} (l : List (Fin n × Fin 2)) : Decidable (EndsOnOppositeLine l) := by + unfold EndsOnOppositeLine; infer_instance + +/-- Kurkov's conjecture: for every `n ≥ 1`, the number of open rook tours of the `n × 2` board +that end on the line of length `n` opposite to the one they start on is `2 · n! · a(n)`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + {l : List (Fin n × Fin 2) | IsOpenTour n l ∧ EndsOnOppositeLine l}.ncard = 2 * n ! * a n + +/-! ## Sanity checks of the encoding (not part of the statement) -/ + +/-- The `2n` squares of the board, each once. -/ +def squares (n : ℕ) : List (Fin n × Fin 2) := List.finRange n ×ˢ List.finRange 2 + +theorem squares_nodup (n : ℕ) : (squares n).Nodup := + (List.nodup_finRange n).product (List.nodup_finRange 2) + +theorem mem_squares {n : ℕ} (s : Fin n × Fin 2) : s ∈ squares n := by + obtain ⟨i, c⟩ := s + simp [squares] + +/-- The open tours ending on the opposite line, enumerated as the orderings of `squares n` +(`List.permutations'`) that pass the two tests. -/ +def tours (n : ℕ) : Finset (List (Fin n × Fin 2)) := + ⟨((squares n).permutations'.filter fun l => l.IsChain RookMove ∧ EndsOnOppositeLine l : List _), + ((List.permutations_perm_permutations' _).nodup_iff.mp + (List.nodup_permutations _ (squares_nodup n))).filter _⟩ + +theorem mem_tours {n : ℕ} {l : List (Fin n × Fin 2)} : + l ∈ tours n ↔ IsOpenTour n l ∧ EndsOnOppositeLine l := by + have key : List.Perm l (squares n) ↔ l.Nodup ∧ ∀ s, s ∈ l := by + constructor + · intro h + exact ⟨h.nodup_iff.mpr (squares_nodup n), fun s => h.mem_iff.mpr (mem_squares s)⟩ + · rintro ⟨hl, hs⟩ + exact (List.perm_ext_iff_of_nodup hl (squares_nodup n)).mpr + fun s => ⟨fun _ => mem_squares s, fun _ => hs s⟩ + rw [tours, Finset.mem_def] + simp only [Multiset.mem_coe, List.mem_filter, List.mem_permutations', key, decide_eq_true_eq, + IsOpenTour] + tauto + +/-- The set counted in `statement` is the finite set `tours n`. -/ +theorem ncard_eq_card_tours (n : ℕ) : + {l : List (Fin n × Fin 2) | IsOpenTour n l ∧ EndsOnOppositeLine l}.ncard = (tours n).card := by + rw [← Set.ncard_coe_finset] + congr 1 + ext l + simp [mem_tours] + +/-- The counts for `n = 1, 2, 3, 4` are `2, 4, 36, 480` (kernel-checked), and these are +`2 · n! · a(n)`. -/ +theorem tours_card_small : + (List.range 4).map (fun i => (tours (i + 1)).card) = [2, 4, 36, 480] ∧ + (List.range 4).map (fun i => 2 * (i + 1)! * a (i + 1)) = [2, 4, 36, 480] := by + decide +kernel + +/-- On the empty board there is no tour ending on the opposite line (and `2 · 0! · a(0) = 0`). -/ +theorem tours_zero : (tours 0).card = 0 := by decide +kernel + +end Math0.Statements.A001040 diff --git a/lean/Math0/Statements/OEIS/A005590.lean b/lean/Math0/Statements/OEIS/A005590.lean new file mode 100644 index 0000000..b162581 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A005590.lean @@ -0,0 +1,137 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A005590: zeros of `a(3n)` for the signed Stern sequence are the fibbinary numbers + +Source: https://oeis.org/A005590, Ralf Stephan, May 02 2003 (FORMULA section). Verbatim: +> Conjecture: a(3n)=0 iff n in A003714. + +The sequence (offset `0`) is "a(0) = 0, a(1) = 1, a(2n) = a(n), a(2n+1) = a(n+1) - a(n)." +A003714 is the sequence of fibbinary numbers, "numbers whose binary representation contains +no two adjacent 1's" (`0, 1, 2, 4, 5, 8, 9, 10, 16, …`). + +## Encoding + +* The values are signed, so `a : ℕ → ℤ`. It is computed by the defining recursion with a fuel + argument (`aux`), so that the kernel can evaluate it. With fuel `n + 1` the recursion is never + cut off: every recursive call is on a strictly smaller argument (`n / 2 < n` for even `n ≥ 2`, + `n / 2 + 1 < n` for odd `n ≥ 3`). The theorems `a_zero`, `a_one`, `a_even`, `a_odd` prove that + `a` satisfies exactly the OEIS defining equations, for every `n`, and these equations + determine the sequence. `a_data` checks all 105 listed terms `a 0, …, a 104`. +* "n in A003714" is `IsFibbinary n`: no two adjacent bits of `n` are both `1`, i.e. there is no + `i` with `Nat.testBit n i` and `Nat.testBit n (i + 1)` both true (bits beyond the length of the + binary representation are `0`, so this is a statement about the binary representation of + `n`). `isFibbinary_iff_land` shows it is equivalent to `n &&& (n >>> 1) = 0`, which makes it + decidable, and `fibbinary_data` checks that it picks out exactly the 61 terms listed in + A003714 (all fibbinary numbers up to `264`). +* The conjecture is stated for every `n ≥ 0` (both sequences start at offset `0`; `a 0 = 0` and + `0` is in A003714): `a (3 * n) = 0 ↔ IsFibbinary n`. +-/ + +namespace Math0.Statements.A005590 + +/-- The defining recursion of A005590 run with `fuel` steps (it returns `0` when the fuel is +exhausted, which never happens for `fuel > n`; see `aux_eq_aux`). -/ +def aux : ℕ → ℕ → ℤ + | 0, _ => 0 + | fuel + 1, n => + if n ≤ 1 then (n : ℤ) + else if n % 2 = 0 then aux fuel (n / 2) + else aux fuel (n / 2 + 1) - aux fuel (n / 2) + +/-- A005590: `a(0) = 0`, `a(1) = 1`, `a(2n) = a(n)`, `a(2n+1) = a(n+1) - a(n)`. -/ +def a (n : ℕ) : ℤ := aux (n + 1) n + +/-- The fueled recursion does not depend on the fuel once the fuel exceeds the argument. -/ +theorem aux_eq_aux : ∀ (f g n : ℕ), n < f → n < g → aux f n = aux g n := by + intro f + induction f with + | zero => intro g n hf; omega + | succ f ih => + intro g n hf hg + cases g with + | zero => omega + | succ g => + simp only [aux] + split_ifs with h1 h2 + · rfl + · exact ih g (n / 2) (by omega) (by omega) + · rw [ih g (n / 2 + 1) (by omega) (by omega), ih g (n / 2) (by omega) (by omega)] + +theorem aux_succ (fuel n : ℕ) : aux (fuel + 1) n = + if n ≤ 1 then (n : ℤ) + else if n % 2 = 0 then aux fuel (n / 2) + else aux fuel (n / 2 + 1) - aux fuel (n / 2) := rfl + +theorem aux_eq_a (f n : ℕ) (h : n < f) : aux f n = a n := + aux_eq_aux f (n + 1) n h (by omega) + +theorem a_zero : a 0 = 0 := by decide +kernel + +theorem a_one : a 1 = 1 := by decide +kernel + +/-- `a(2n) = a(n)` for all `n`. -/ +theorem a_even (n : ℕ) : a (2 * n) = a n := by + rcases Nat.eq_zero_or_pos n with rfl | hn + · rfl + · show aux (2 * n + 1) (2 * n) = a n + rw [aux_succ, if_neg (by omega), if_pos (by omega), Nat.mul_div_cancel_left n (by omega)] + exact aux_eq_a _ _ (by omega) + +/-- `a(2n+1) = a(n+1) - a(n)` for all `n`. -/ +theorem a_odd (n : ℕ) : a (2 * n + 1) = a (n + 1) - a n := by + rcases Nat.eq_zero_or_pos n with rfl | hn + · decide +kernel + · show aux (2 * n + 1 + 1) (2 * n + 1) = a (n + 1) - a n + have h : (2 * n + 1) / 2 = n := by omega + rw [aux_succ, if_neg (by omega), if_neg (by omega), h, aux_eq_a _ _ (by omega), + aux_eq_a _ _ (by omega)] + +/-- The definition reproduces all 105 terms listed in OEIS, `a 0, …, a 104` (kernel-checked). -/ +theorem a_data : (List.range 105).map (fun i => a (i + 0)) = + [0, 1, 1, 0, 1, -1, 0, 1, 1, -2, -1, 1, 0, 1, 1, 0, 1, -3, -2, 1, -1, 2, 1, -1, 0, 1, 1, 0, + 1, -1, 0, 1, 1, -4, -3, 1, -2, 3, 1, -2, -1, 3, 2, -1, 1, -2, -1, 1, 0, 1, 1, 0, 1, -1, 0, + 1, 1, -2, -1, 1, 0, 1, 1, 0, 1, -5, -4, 1, -3, 4, 1, -3, -2, 5, 3, -2, 1, -3, -2, 1, -1, 4, + 3, -1, 2, -3, -1, 2, 1, -3, -2, 1, -1, 2, 1, -1, 0, 1, 1, 0, 1, -1, 0, 1, 1] := by + decide +kernel + +/-- `n` is a fibbinary number (OEIS A003714): its binary representation contains no two +adjacent 1's. -/ +def IsFibbinary (n : ℕ) : Prop := + ∀ i : ℕ, ¬ (n.testBit i = true ∧ n.testBit (i + 1) = true) + +/-- The usual bitwise test for fibbinary numbers: `n AND (n >> 1) = 0`. -/ +theorem isFibbinary_iff_land (n : ℕ) : IsFibbinary n ↔ n &&& (n >>> 1) = 0 := by + constructor + · intro h + apply Nat.eq_of_testBit_eq + intro i + rw [Nat.testBit_and, Nat.testBit_shiftRight, Nat.zero_testBit] + have := h i + rw [Nat.add_comm 1 i] + cases hi : n.testBit i <;> cases hi1 : n.testBit (i + 1) <;> simp_all + · intro h i ⟨hi, hi1⟩ + have := congrArg (fun m => m.testBit i) h + simp only [Nat.testBit_and, Nat.testBit_shiftRight, Nat.zero_testBit] at this + rw [Nat.add_comm 1 i, hi, hi1] at this + simp at this + +instance : DecidablePred IsFibbinary := fun n => + decidable_of_iff _ (isFibbinary_iff_land n).symm + +/-- `IsFibbinary` picks out exactly the 61 terms listed in A003714 (kernel-checked). -/ +theorem fibbinary_data : (List.range 265).filter (fun n => decide (IsFibbinary n)) = + [0, 1, 2, 4, 5, 8, 9, 10, 16, 17, 18, 20, 21, 32, 33, 34, 36, 37, 40, 41, 42, 64, 65, 66, 68, + 69, 72, 73, 74, 80, 81, 82, 84, 85, 128, 129, 130, 132, 133, 136, 137, 138, 144, 145, 146, + 148, 149, 160, 161, 162, 164, 165, 168, 169, 170, 256, 257, 258, 260, 261, 264] := by + decide +kernel + +/-- Conjecture (Ralf Stephan, 2003): for every `n ≥ 0`, `a(3n) = 0` if and only if `n` is a +fibbinary number (in A003714), i.e. the binary representation of `n` has no two adjacent 1's. -/ +def statement : Prop := + ∀ n : ℕ, a (3 * n) = 0 ↔ IsFibbinary n + +end Math0.Statements.A005590 diff --git a/lean/Math0/Statements/OEIS/A022445.lean b/lean/Math0/Statements/OEIS/A022445.lean new file mode 100644 index 0000000..01e7182 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A022445.lean @@ -0,0 +1,501 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A022445: self-avoiding closed walks in the strip `{0, 1, 2} × ℤ` + +Source: https://oeis.org/A022445, _Ralf Stephan_, Apr 28 2004 (FORMULA section; the entry is by +Jacques Labelle, more terms by _Sean A. Irvine_, May 16 2019). Verbatim: +> G.f.: (-6*x^7+10*x^6-18*x^5+27*x^4-14*x^3+10*x^2-4*x+1) / ((1+x^2)^2*(1-2*x)^2) +> (conjectured). - _Ralf Stephan_, Apr 28 2004 + +The entry's name: "Number of self-avoiding closed walks (from 0 to 0) of length 2n in the strip +{0, 1, 2} X Z of the square lattice Z X Z." Offset `0`; data `1, 0, 4, 10, 34, 94, 222, …` +(29 terms, `a(0), …, a(28)`). + +## Encoding + +* *Walks.* A walk of length `m` in the square lattice `ℤ × ℤ` starting at the origin + `0 = (0, 0)` is given by its sequence of unit steps `t : Fin m → Fin 4`, step `j` being + `step (t j)` (right, left, up or down). Its vertices are + `vertex t i = step (t 0) + ⋯ + step (t (i - 1))` for `0 ≤ i ≤ m`. This is a bijection between + step sequences and lattice walks of length `m` from `0`. +* *The strip* `{0, 1, 2} × ℤ` is `InStrip v ↔ 0 ≤ v.1 ≤ 2`. The walks go "from 0 to 0", and the + origin lies on the boundary column `0` of the strip. (The data confirm this reading: there are + `a(2) = 4` walks of length `4`, two unit squares at `0` with two directions each; from a vertex + of the middle column there would be `8`.) +* *Self-avoiding closed walks* (`IsClosedSAW t`, `m = 2n`), with vertices `w i = vertex t i`: + - all vertices `w 0, …, w m` lie in the strip; + - the walk is closed, `w m = 0`; + - the vertices `w 0, …, w (m - 1)` are pairwise distinct (the only repeated vertex is + `w m = w 0`); + - the `m` edges `{w i, w (i + 1)}` are pairwise distinct (no edge is traversed twice). + For `m ≠ 2` the edge condition follows from the vertex condition (`closed_iff_ext`). Its only + effect is to exclude the degenerate walks `0 → v → 0` of length `2`, which retrace their edge; + this agrees with the listed `a(1) = 0`. For `m ≥ 4`, each cycle of length `m` through `0` in + the strip gives exactly two such walks, one for each direction. For `m = 0` the empty walk is + counted, so `a(0) = 1`. +* `a n` is the number of such walks of length `2n`, a `Fintype.card` of a decidable subtype of + `Fin (2n) → Fin 4`. +* *Fast evaluation (proved equal).* The kernel cannot enumerate `4^(2n)` step sequences, so the + data are checked through a depth-first search `aFast`, with `a_eq_aFast : a n = aFast n` for + every `n`. The search extends the walk one step at a time, never revisiting a vertex (except + for the final return to `0`). It prunes a branch when the `ℓ¹`-distance to the origin exceeds + the number of remaining steps (`G_succ`, `G_eq_zero`). The vertex `(c, r - R)` of the strip is + encoded by the natural numbers `(c, r)` (offset `R = 2n`), and the set of visited vertices by a + bitmask (bit `3r + c`). `dfs_eq` proves that the search computes the numbers `G` of + completions of a partial walk. +* *Data.* `a_data` checks the first 10 listed terms `a(0), …, a(9)` in the kernel (about 45 s). + The search visits about `6 · 10⁴` nodes for these, and each further term costs about 2.5 times + as much as the previous one. +* *The conjecture* (`statement`): the generating function `∑_{n ≥ 0} a(n) xⁿ` equals + `(-6x⁷ + 10x⁶ - 18x⁵ + 27x⁴ - 14x³ + 10x² - 4x + 1) / ((1 + x²)² (1 - 2x)²)`. It is stated + over `ℤ` after clearing the denominator. The denominator has constant term `1`, so it is a unit + in `ℤ⟦X⟧` and this is equivalent to the stated quotient. As a sanity check of the transcription + (not a proof), `listed_satisfy_gf` checks that the 29 listed terms agree with the coefficients + of the conjectured rational function. +-/ + +namespace Math0.Statements.A022445 + +/-! ### The definition -/ + +/-- The four unit steps of the square lattice `ℤ × ℤ`: right, left, up, down. -/ +def step : Fin 4 → ℤ × ℤ := ![(1, 0), (-1, 0), (0, 1), (0, -1)] + +/-- The vertex reached after the first `i` steps of the walk that starts at the origin and whose +`j`-th step (`j < m`) is `step (t j)`, i.e. the sum of the first `i` steps (for `i ≥ m`, the +endpoint of the walk). -/ +def vertex {m : ℕ} (t : Fin m → Fin 4) (i : ℕ) : ℤ × ℤ := + ∑ j : Fin m, if (j : ℕ) < i then step (t j) else 0 + +/-- The strip `{0, 1, 2} × ℤ` of the square lattice. -/ +def InStrip (v : ℤ × ℤ) : Prop := 0 ≤ v.1 ∧ v.1 ≤ 2 + +instance : DecidablePred InStrip := fun v => by unfold InStrip; infer_instance + +/-- The walk from the origin with steps `t` (vertices `w i = vertex t i`, `0 ≤ i ≤ m`) is a +self-avoiding closed walk from `0` to `0` in the strip: all its vertices lie in the strip, it +returns to `0`, the vertices `w 0, …, w (m - 1)` are pairwise distinct, and its edges +`{w i, w (i + 1)}` (`i < m`) are pairwise distinct. -/ +def IsClosedSAW {m : ℕ} (t : Fin m → Fin 4) : Prop := + (∀ i < m + 1, InStrip (vertex t i)) ∧ vertex t m = 0 ∧ + (∀ j < m, ∀ i < j, vertex t i ≠ vertex t j) ∧ + (∀ j < m, ∀ i < j, s(vertex t i, vertex t (i + 1)) ≠ s(vertex t j, vertex t (j + 1))) + +instance {m : ℕ} : DecidablePred (@IsClosedSAW m) := fun t => by + unfold IsClosedSAW; infer_instance + +/-- A022445: the number of self-avoiding closed walks (from `0` to `0`) of length `2n` in the strip +`{0, 1, 2} × ℤ` of the square lattice. -/ +def a (n : ℕ) : ℕ := Fintype.card {t : Fin (2 * n) → Fin 4 // IsClosedSAW t} + +/-! ### Counting extensions of a partial walk step by step -/ + +theorem vertex_zero {m : ℕ} (t : Fin m → Fin 4) : vertex t 0 = 0 := by + simp [vertex] + +theorem vertex_fin_zero (t : Fin 0 → Fin 4) (i : ℕ) : vertex t i = 0 := by + simp [vertex] + +theorem vertex_cons_succ {k : ℕ} (d : Fin 4) (t : Fin k → Fin 4) (i : ℕ) : + vertex (Fin.cons d t : Fin (k + 1) → Fin 4) (i + 1) = step d + vertex t i := by + simp [vertex, Fin.sum_univ_succ] + +/-- `Ext vis p t`: the walk that starts at `p` and makes the steps `t` (vertices +`p + vertex t i`, `0 ≤ i ≤ k`) has its vertices `1, …, k` in the strip, ends at `0`, and its +vertices `1, …, k - 1` are pairwise distinct and not in `vis`. -/ +def Ext (vis : List (ℤ × ℤ)) (p : ℤ × ℤ) {k : ℕ} (t : Fin k → Fin 4) : Prop := + (∀ i, 1 ≤ i → i ≤ k → InStrip (p + vertex t i)) ∧ p + vertex t k = 0 ∧ + (∀ i, 1 ≤ i → i < k → p + vertex t i ∉ vis) ∧ + (∀ i j, 1 ≤ i → i < j → j < k → p + vertex t i ≠ p + vertex t j) + +/-- The number of ways to complete a partial walk at `p` with visited vertices `vis` by `k` more +steps. -/ +noncomputable def G (vis : List (ℤ × ℤ)) (p : ℤ × ℤ) (k : ℕ) : ℕ := + Nat.card {t : Fin k → Fin 4 // Ext vis p t} + +theorem ext_cons (vis : List (ℤ × ℤ)) (p : ℤ × ℤ) {k : ℕ} (d : Fin 4) (t : Fin k → Fin 4) : + Ext vis p (Fin.cons d t : Fin (k + 1) → Fin 4) ↔ + InStrip (p + step d) ∧ (k ≠ 0 → p + step d ∉ vis) ∧ + Ext ((p + step d) :: vis) (p + step d) t := by + have hv : ∀ i, p + vertex (Fin.cons d t : Fin (k + 1) → Fin 4) (i + 1) = + p + step d + vertex t i := by + intro i; rw [vertex_cons_succ, add_assoc] + have hv0 : vertex t 0 = 0 := vertex_zero t + unfold Ext + constructor + · rintro ⟨h1, h2, h3, h4⟩ + refine ⟨?_, fun hk => ?_, fun i hi1 hik => ?_, ?_, fun i hi1 hik hmem => ?_, + fun i j hi hij hjk => ?_⟩ + · have := h1 (0 + 1) (by omega) (by omega); rwa [hv, hv0, add_zero] at this + · have := h3 (0 + 1) (by omega) (by omega); rwa [hv, hv0, add_zero] at this + · have := h1 (i + 1) (by omega) (by omega); rwa [hv] at this + · have := h2; rwa [hv] at this + · rcases List.mem_cons.1 hmem with h | h + · have := h4 (0 + 1) (i + 1) (by omega) (by omega) (by omega) + rw [hv, hv, hv0, add_zero] at this + exact this h.symm + · have := h3 (i + 1) (by omega) (by omega); rw [hv] at this; exact this h + · have := h4 (i + 1) (j + 1) (by omega) (by omega) (by omega) + rwa [hv, hv] at this + · rintro ⟨hq, hqv, g1, g2, g3, g4⟩ + refine ⟨fun i hi1 hik => ?_, ?_, fun i hi1 hik => ?_, fun i j hi1 hij hjk => ?_⟩ + · obtain ⟨i', rfl⟩ : ∃ i', i = i' + 1 := ⟨i - 1, by omega⟩ + rw [hv] + rcases Nat.eq_zero_or_pos i' with rfl | hi + · rwa [hv0, add_zero] + · exact g1 i' hi (by omega) + · rw [hv]; exact g2 + · obtain ⟨i', rfl⟩ : ∃ i', i = i' + 1 := ⟨i - 1, by omega⟩ + rw [hv] + rcases Nat.eq_zero_or_pos i' with rfl | hi + · rw [hv0, add_zero]; exact hqv (by omega) + · exact fun h => g3 i' hi (by omega) (List.mem_cons_of_mem _ h) + · obtain ⟨i', rfl⟩ : ∃ i', i = i' + 1 := ⟨i - 1, by omega⟩ + obtain ⟨j', rfl⟩ : ∃ j', j = j' + 1 := ⟨j - 1, by omega⟩ + rw [hv, hv] + rcases Nat.eq_zero_or_pos i' with rfl | hi + · rw [hv0, add_zero] + intro h + apply g3 j' (by omega) (by omega) + rw [← h] + exact List.mem_cons_self + · exact g4 i' j' hi (by omega) (by omega) + +theorem G_zero (vis : List (ℤ × ℤ)) (p : ℤ × ℤ) : G vis p 0 = if p = 0 then 1 else 0 := by + unfold G + have hE : ∀ t : Fin 0 → Fin 4, Ext vis p t ↔ p = 0 := by + intro t + simp only [Ext, vertex_fin_zero, add_zero] + constructor + · exact fun h => h.2.1 + · intro h + exact ⟨fun i h1 h2 => by omega, h, fun i h1 h2 => by omega, fun i j h1 h2 h3 => by omega⟩ + split_ifs with hp + · rw [Nat.card_eq_one_iff_unique] + refine ⟨⟨fun x y => Subtype.ext (Subsingleton.elim _ _)⟩, ⟨⟨Fin.elim0, (hE _).2 hp⟩⟩⟩ + · rw [Nat.card_eq_zero] + left + exact ⟨fun ⟨t, ht⟩ => hp ((hE t).1 ht)⟩ + +theorem G_succ (vis : List (ℤ × ℤ)) (p : ℤ × ℤ) (k : ℕ) : + G vis p (k + 1) = ∑ d : Fin 4, + if InStrip (p + step d) ∧ (k ≠ 0 → p + step d ∉ vis) then + G ((p + step d) :: vis) (p + step d) k else 0 := by + unfold G + let e : {t : Fin (k + 1) → Fin 4 // Ext vis p t} ≃ + Σ d : Fin 4, {t : Fin k → Fin 4 // Ext vis p (Fin.cons d t : Fin (k + 1) → Fin 4)} := + ((Fin.consEquiv fun _ => Fin 4).symm.subtypeEquiv + (q := fun x : Fin 4 × (Fin k → Fin 4) => Ext vis p (Fin.cons x.1 x.2 : Fin (k + 1) → Fin 4)) + (fun t => by simp)).trans + (Equiv.subtypeProdEquivSigmaSubtype fun d t => Ext vis p (Fin.cons d t : Fin (k + 1) → Fin 4)) + rw [Nat.card_congr e, Nat.card_sigma] + refine Finset.sum_congr rfl fun d _ => ?_ + split_ifs with h + · exact Nat.card_congr (Equiv.subtypeEquivRight fun t => by rw [ext_cons]; tauto) + · rw [Nat.card_eq_zero] + left + exact ⟨fun ⟨t, ht⟩ => h (by rw [ext_cons] at ht; exact ⟨ht.1, ht.2.1⟩)⟩ + +/-- The `ℓ¹`-distance from the origin. -/ +def dist (v : ℤ × ℤ) : ℕ := v.1.natAbs + v.2.natAbs + +theorem dist_le_step (p : ℤ × ℤ) (d : Fin 4) : dist p ≤ dist (p + step d) + 1 := by + fin_cases d <;> simp [dist, step] <;> omega + +theorem dist_le_of_ext (vis : List (ℤ × ℤ)) (p : ℤ × ℤ) {k : ℕ} (t : Fin k → Fin 4) + (h : Ext vis p t) : dist p ≤ k := by + induction k generalizing vis p with + | zero => + have h2 := h.2.1 + rw [vertex_zero, add_zero] at h2 + simp [h2, dist] + | succ k ih => + rw [← Fin.cons_self_tail t, ext_cons] at h + have := ih _ _ _ h.2.2 + have := dist_le_step p (t 0) + omega + +theorem G_eq_zero (vis : List (ℤ × ℤ)) (p : ℤ × ℤ) (k : ℕ) (h : k < dist p) : G vis p k = 0 := by + unfold G + rw [Nat.card_eq_zero] + left + exact ⟨fun ⟨t, ht⟩ => absurd (dist_le_of_ext vis p t ht) (by omega)⟩ + +/-! ### Self-avoiding closed walks are the complete extensions of the empty walk -/ + +theorem closed_iff_ext {m : ℕ} (hm : m ≠ 2) (t : Fin m → Fin 4) : + IsClosedSAW t ↔ Ext [0] 0 t := by + simp only [IsClosedSAW, Ext, zero_add, List.mem_singleton] + have h0 : vertex t 0 = 0 := vertex_zero t + constructor + · rintro ⟨h1, h2, h3, -⟩ + refine ⟨fun i _ hi => h1 i (by omega), h2, fun i hi1 hi => ?_, + fun i j hi hij hj => h3 j hj i hij⟩ + have := h3 i hi 0 (by omega) + rw [h0] at this + exact fun h => this h.symm + · rintro ⟨h1, h2, h3, h4⟩ + have hd : ∀ j < m, ∀ i < j, vertex t i ≠ vertex t j := by + intro j hj i hij + rcases Nat.eq_zero_or_pos i with rfl | hi + · rw [h0]; exact fun h => h3 j (by omega) hj h.symm + · exact h4 i j hi hij hj + refine ⟨fun i hi => ?_, h2, hd, fun j hj i hij he => ?_⟩ + · rcases Nat.eq_zero_or_pos i with rfl | hi0 + · rw [h0]; exact ⟨le_rfl, by norm_num⟩ + · exact h1 i hi0 (by omega) + · rw [Sym2.eq_iff] at he + rcases he with ⟨he1, -⟩ | ⟨he1, he2⟩ + · exact hd j hj i hij he1 + · have hj' : j = i + 1 := by + by_contra hne + exact hd j hj (i + 1) (by omega) he2 + subst hj' + by_cases hlt : i + 1 + 1 < m + · exact hd (i + 1 + 1) hlt i (by omega) he1 + · have hm2 : i + 1 + 1 = m := by omega + rw [hm2, h2] at he1 + rcases Nat.eq_zero_or_pos i with rfl | hi0 + · omega + · exact hd i (by omega) 0 hi0 (by rw [h0, he1]) + +theorem a_one : a 1 = 0 := by + unfold a + rw [Fintype.card_eq_zero_iff] + refine ⟨fun ⟨t, ht⟩ => ?_⟩ + obtain ⟨-, h2, -, h4⟩ := ht + apply h4 1 (by norm_num) 0 (by norm_num) + have h2' : vertex t (1 + 1) = 0 := h2 + rw [vertex_zero, h2'] + exact Sym2.eq_swap + +theorem a_eq_G (n : ℕ) (hn : n ≠ 1) : a n = G [0] 0 (2 * n) := by + unfold a G + rw [← Nat.card_eq_fintype_card] + exact Nat.card_congr (Equiv.subtypeEquivRight fun t => closed_iff_ext (by omega) t) + +/-! ### Fast evaluation: depth-first search with a bitmask -/ + +/-- One move of the depth-first search, to the strip vertex `(c, r - R)` (column `c`, row `r - R`), +with `k` steps left after the move. The visited vertices form the bitmask `vis` (vertex +`(c, r - R)` ↦ bit `3 r + c`). The branch is pruned if the vertex is farther than `k` from the +origin, or if it was already visited (unless it is the final step). -/ +def move (R k : ℕ) (ih : ℕ → ℕ → ℕ → ℕ) (vis c r : ℕ) : ℕ := + cond (Nat.ble (Nat.add (Nat.add c (Nat.sub r R)) (Nat.sub R r)) k && + (Nat.beq k 0 || !(Nat.testBit vis (Nat.add (Nat.mul 3 r) c)))) + (ih c r (Nat.lor vis (Nat.pow 2 (Nat.add (Nat.mul 3 r) c)))) 0 + +/-- One level of the depth-first search from `(c, r - R)`: the moves right, left, up, down +(staying in the strip and in `r ≥ 0`). -/ +def dfsStep (R k : ℕ) (ih : ℕ → ℕ → ℕ → ℕ) (c r vis : ℕ) : ℕ := + Nat.add (Nat.add (Nat.add + (cond (Nat.blt c 2) (move R k ih vis (Nat.add c 1) r) 0) + (cond (Nat.blt 0 c) (move R k ih vis (Nat.sub c 1) r) 0)) + (move R k ih vis c (Nat.add r 1))) + (cond (Nat.blt 0 r) (move R k ih vis c (Nat.sub r 1)) 0) + +/-- `dfs R k c r vis`: the number of ways to complete the partial walk at `(c, r - R)` with +visited set `vis` by `k` more steps (`dfs_eq`). -/ +def dfs (R k : ℕ) : ℕ → ℕ → ℕ → ℕ := + Nat.rec (motive := fun _ => ℕ → ℕ → ℕ → ℕ) + (fun c r _ => cond (Nat.beq c 0 && Nat.beq r R) 1 0) (fun k ih => dfsStep R k ih) k + +/-- Fast evaluation of `a` (`a_eq_aFast`). -/ +def aFast (n : ℕ) : ℕ := + if n = 1 then 0 else dfs (2 * n) (2 * n) 0 (2 * n) (2 ^ (3 * (2 * n))) + +/-- Decoding of the bit index `v = 3 r + c` as the lattice point `(c, r - R)`. -/ +def dec (R v : ℕ) : ℤ × ℤ := (((v % 3 : ℕ) : ℤ), ((v / 3 : ℕ) : ℤ) - R) + +theorem dec_inj (R : ℕ) {v w : ℕ} (h : dec R v = dec R w) : v = w := by + simp only [dec, Prod.mk.injEq] at h + obtain ⟨h1, h2⟩ := h + have h1' : v % 3 = w % 3 := by exact_mod_cast h1 + have h2' : v / 3 = w / 3 := by omega + omega + +theorem dec_code (R c r : ℕ) (hc : c < 3) : dec R (3 * r + c) = ((c : ℤ), (r : ℤ) - R) := by + have h1 : (3 * r + c) % 3 = c := by omega + have h2 : (3 * r + c) / 3 = r := by omega + simp [dec, h1, h2] + +theorem ble_eq_decide (a b : ℕ) : Nat.ble a b = decide (a ≤ b) := + Bool.eq_iff_iff.2 (by rw [Nat.ble_eq, decide_eq_true_iff]) + +theorem beq_eq_decide (a b : ℕ) : Nat.beq a b = decide (a = b) := + Bool.eq_iff_iff.2 (by rw [Nat.beq_eq, decide_eq_true_iff]) + +theorem blt_eq_decide (a b : ℕ) : Nat.blt a b = decide (a < b) := + Bool.eq_iff_iff.2 (by rw [Nat.blt_eq, decide_eq_true_iff]) + +theorem dfs_eq (R : ℕ) : ∀ k c r visN (visZ : List (ℤ × ℤ)), c ≤ 2 → k ≤ R → + (∀ v, Nat.testBit visN v = true ↔ dec R v ∈ visZ) → + dfs R k c r visN = G visZ ((c : ℤ), (r : ℤ) - R) k := by + intro k + induction k with + | zero => + intro c r visN visZ hc hk hrel + rw [G_zero] + show cond (Nat.beq c 0 && Nat.beq r R) 1 0 = _ + rw [beq_eq_decide, beq_eq_decide, ← Bool.decide_and, Bool.cond_decide] + have : (c = 0 ∧ r = R) ↔ ((c : ℤ), (r : ℤ) - R) = 0 := by + rw [Prod.ext_iff]; simp only [Prod.fst_zero, Prod.snd_zero]; omega + exact if_congr this rfl rfl + | succ k ih => + intro c r visN visZ hc hk hrel + have hmove : ∀ c' r' : ℕ, c' ≤ 2 → ∀ q : ℤ × ℤ, q = ((c' : ℤ), (r' : ℤ) - R) → + move R k (dfs R k) visN c' r' = + if InStrip q ∧ (k ≠ 0 → q ∉ visZ) then G (q :: visZ) q k else 0 := by + intro c' r' hc' q hq + have hstrip : InStrip q := by rw [hq]; exact ⟨by simp, by simp; omega⟩ + have hdist : c' + (r' - R) + (R - r') = dist q := by rw [hq]; simp [dist]; omega + have hcq : dec R (3 * r' + c') = q := by rw [dec_code R c' r' (by omega), hq] + have htb : Nat.testBit visN (3 * r' + c') = decide (q ∈ visZ) := + Bool.eq_iff_iff.2 (by rw [hrel, hcq, decide_eq_true_iff]) + have hrel' : ∀ v, Nat.testBit (visN ||| 2 ^ (3 * r' + c')) v = true ↔ + dec R v ∈ q :: visZ := by + intro v + rw [Nat.testBit_or, Bool.or_eq_true, hrel, Nat.testBit_two_pow, decide_eq_true_iff, + List.mem_cons] + constructor + · rintro (h | rfl) + · exact Or.inr h + · exact Or.inl hcq + · rintro (h | h) + · exact Or.inr (dec_inj R (h.trans hcq.symm)).symm + · exact Or.inl h + have hih := ih c' r' _ (q :: visZ) hc' (by omega) hrel' + rw [← hq] at hih + unfold move + simp only [Nat.add_eq, Nat.sub_eq, Nat.mul_eq, Nat.pow_eq, Nat.lor_eq] + rw [ble_eq_decide, beq_eq_decide, htb, hdist] + simp only [← decide_not, ← Bool.decide_or, ← Bool.decide_and, Bool.cond_decide] + split_ifs with h1 h2 h2 + · exact hih + · exfalso + exact h2 ⟨hstrip, fun hk0 => h1.2.resolve_left hk0⟩ + · by_cases hd : dist q ≤ k + · exfalso + apply h1 + refine ⟨hd, ?_⟩ + by_cases hk0 : k = 0 + · exact Or.inl hk0 + · exact Or.inr (h2.2 hk0) + · rw [G_eq_zero _ _ _ (by omega)] + · rfl + show dfsStep R k (dfs R k) c r visN = _ + rw [G_succ, Fin.sum_univ_four] + unfold dfsStep + simp only [Nat.add_eq, Nat.sub_eq] + have hs0 : step 0 = (1, 0) := rfl + have hs1 : step 1 = (-1, 0) := rfl + have hs2 : step 2 = (0, 1) := rfl + have hs3 : step 3 = (0, -1) := rfl + simp only [hs0, hs1, hs2, hs3, Prod.mk_add_mk, add_zero] + congr 1 + congr 1 + congr 1 + · -- right + by_cases h : c < 2 + · rw [show Nat.blt c 2 = true by rw [blt_eq_decide]; simpa using h, cond_true] + exact hmove (c + 1) r (by omega) _ (by rw [Prod.mk.injEq]; omega) + · rw [show Nat.blt c 2 = false by rw [blt_eq_decide]; simpa using h, cond_false, if_neg] + rintro ⟨⟨-, h2⟩, -⟩ + dsimp only at h2 + omega + · -- left + by_cases h : 0 < c + · rw [show Nat.blt 0 c = true by rw [blt_eq_decide]; simpa using h, cond_true] + exact hmove (c - 1) r (by omega) _ (by rw [Prod.mk.injEq]; omega) + · rw [show Nat.blt 0 c = false by rw [blt_eq_decide]; simpa using h, cond_false, if_neg] + rintro ⟨⟨h1, -⟩, -⟩ + dsimp only at h1 + omega + · -- up + exact hmove c (r + 1) hc _ (by rw [Prod.mk.injEq]; omega) + · -- down + by_cases h : 0 < r + · rw [show Nat.blt 0 r = true by rw [blt_eq_decide]; simpa using h, cond_true] + exact hmove c (r - 1) hc _ (by rw [Prod.mk.injEq]; omega) + · rw [show Nat.blt 0 r = false by rw [blt_eq_decide]; simpa using h, cond_false] + have hr : r = 0 := by omega + subst hr + split_ifs + · rw [G_eq_zero] + simp only [dist] + omega + · rfl + +theorem aFast_eq_G (n : ℕ) (hn : n ≠ 1) : aFast n = G [0] 0 (2 * n) := by + unfold aFast + rw [if_neg hn] + have h := dfs_eq (2 * n) (2 * n) 0 (2 * n) (2 ^ (3 * (2 * n))) [0] (by norm_num) le_rfl ?_ + · rw [h] + congr 1 + simp + · intro v + rw [Nat.testBit_two_pow, List.mem_singleton, decide_eq_true_iff] + have hc := dec_code (2 * n) 0 (2 * n) (by norm_num) + simp only [add_zero, Nat.cast_zero, sub_self] at hc + constructor + · rintro rfl + rw [hc]; rfl + · intro h + apply dec_inj (2 * n) + rw [hc, h]; rfl + +theorem a_eq_aFast (n : ℕ) : a n = aFast n := by + by_cases hn : n = 1 + · subst hn; rw [a_one]; rfl + · rw [a_eq_G n hn, aFast_eq_G n hn] + +/-- The definition reproduces the first 10 listed terms `a(0), …, a(9)` (kernel-checked). -/ +theorem a_data : (List.range 10).map a = [1, 0, 4, 10, 34, 94, 222, 516, 1202, 2738] := by + rw [show a = aFast from funext a_eq_aFast] + decide +kernel + +/-! ### The conjecture -/ + +open PowerSeries in +/-- Ralf Stephan's conjecture: the generating function of A022445 is +`∑_{n ≥ 0} a(n) xⁿ = (-6x⁷ + 10x⁶ - 18x⁵ + 27x⁴ - 14x³ + 10x² - 4x + 1) / ((1 + x²)² (1 - 2x)²)`, +stated as an identity of formal power series over `ℤ` after clearing the denominator (which has +constant term `1`, hence is a unit in `ℤ⟦X⟧`). -/ +def statement : Prop := + PowerSeries.mk (fun n => (a n : ℤ)) * ((1 + X ^ 2) ^ 2 * (1 - 2 * X) ^ 2) = + -6 * X ^ 7 + 10 * X ^ 6 - 18 * X ^ 5 + 27 * X ^ 4 - 14 * X ^ 3 + 10 * X ^ 2 - 4 * X + 1 + +/-! ### Sanity check of the transcription (not a proof) -/ + +open PowerSeries in +/-- The expanded denominator. -/ +theorem denominator_expand : + ((1 + X ^ 2) ^ 2 * (1 - 2 * X) ^ 2 : PowerSeries ℤ) = + 1 - 4 * X + 6 * X ^ 2 - 8 * X ^ 3 + 9 * X ^ 4 - 4 * X ^ 5 + 4 * X ^ 6 := by + ring + +/-- The 29 terms listed in the entry, `a(0), …, a(28)`. -/ +def listed : List ℤ := + [1, 0, 4, 10, 34, 94, 222, 516, 1202, 2738, 6110, 13496, 29586, 64350, 139006, 298636, 638578, + 1359754, 2884638, 6099552, 12859730, 27040694, 56723774, 118732340, 248034354, 517208034, + 1076694622, 2237946376, 4645007122] + +/-- Coefficients of the expanded denominator (`denominator_expand`). -/ +def denC : List ℤ := [1, -4, 6, -8, 9, -4, 4] + +/-- Coefficients of the conjectured numerator, `1 - 4x + 10x² - 14x³ + 27x⁴ - 18x⁵ + 10x⁶ - 6x⁷`. -/ +def numC : List ℤ := [1, -4, 10, -14, 27, -18, 10, -6] + +/-- The listed terms agree with the coefficients of the conjectured rational function: for +`n ≤ 28`, the coefficient of `xⁿ` in `(∑ listed(i) xⁱ) · (1 + x²)² (1 - 2x)²` is that of the +numerator. -/ +theorem listed_satisfy_gf : ∀ n < 29, + ((List.range (n + 1)).map fun i => denC.getD i 0 * listed.getD (n - i) 0).sum = + numC.getD n 0 := by + decide +kernel + +end Math0.Statements.A022445 diff --git a/lean/Math0/Statements/OEIS/A057566.lean b/lean/Math0/Statements/OEIS/A057566.lean new file mode 100644 index 0000000..a84d833 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A057566.lean @@ -0,0 +1,242 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A057566: Layman's floor formula for collinear triples in a `3 × n` grid + +Source: https://oeis.org/A057566, John W. Layman (author of the entry), Oct 04 2000 (FORMULA +section). Verbatim: +> Conjecture: a(n) = 5*floor((2n^3 - 3n^2 - n)/24) + floor((2(n-1)^3 - 3(n-1)^2 - (n-1))/24) + n, +> which fits all of the listed terms. + +The sequence (offset `0`) is "Number of collinear triples in a 3 X n rectangular grid." + +## Encoding + +* The `3 × n` grid is `grid n = {0, 1, 2} × {0, …, n - 1} ⊆ ℕ × ℕ` (row, column); it has `3n` + points (for `n = 0` it is empty). +* Three lattice points `p, q, r` are collinear iff the determinant + `cross p q r = (q.1 - p.1) * (r.2 - p.2) - (q.2 - p.2) * (r.1 - p.1)` (twice the signed area of + the triangle `p q r`, computed in `ℤ`) vanishes. A finite set of points is collinear + (`IsCollinear`) iff every three of its points (with repetitions allowed) satisfy this. + `isCollinear_triple` shows that for a set `{p, q, r}` this is just `cross p q r = 0`. +* A "collinear triple" is a 3-element subset of the grid that is collinear, so + `a n = #{s ⊆ grid n | #s = 3 ∧ IsCollinear s}`, written with `Finset.powersetCard 3`. +* `a` is computable but too slow for the kernel, so `fastA` counts the same triples by a nested + list recursion over the increasing index triples of the list `pts n` of grid points, with the + collinearity test rearranged into an equation of natural numbers. `a_eq_fastA` proves + `a n = fastA n` for every `n`, and `a_data` checks the listed terms `a 0, …, a 24` (this + includes `a 24 = 6360`). +* The floors are `Int.floor` of rational numbers, and `n - 1` is the rational (equivalently + integer) `n - 1`, so for `n = 0` it is `-1` (not truncated to `0`). +* Range of `n`: the conjecture gives none, and the sequence has offset `0`. However, for + `n = 0, 1, 2` some floor arguments are negative (`(2m^3 - 3m^2 - m)/24` is `-4/24` at + `m = -1` and `-2/24` at `m = 1`), and there the value of the formula depends on the rounding + convention: with the true floor (`⌊-1/6⌋ = -1`) it gives `-1, -4, 1` instead of `0, 1, 2`, + while with rounding toward zero (which sends those small negative quotients to `0`) it gives + exactly `0, 1, 2` and then agrees with every term `a 0, …, a 23`. That is consistent with the + author's remark "which fits all of the listed terms" if the listing then ran up to `a 23`. + To keep the formalization from being refuted by this rounding artefact at the degenerate + sizes `n ≤ 2` (an empty grid or one with fewer than three columns), the primary + formalization `statement` asserts the identity for every `n ≥ 3`. For those `n`, both floor + arguments are `≥ 0`, so floor and truncation coincide and every reading of "floor" gives + the same claim. The literal reading for every `n ≥ 0` with true floors is recorded as the + stronger variant `statement_all`, together with `statement_all_imp : statement_all → statement`. + The remark "which fits all of the listed terms" is the author's evidence, not part of the + claimed identity. +* `statement_iff_ediv` restates `statement` with integer division `/` (which is floor division + for the positive divisor `24`) in place of the rational floors. +-/ + +namespace Math0.Statements.A057566 + +/-- The `3 × n` rectangular grid: lattice points `(i, j)` with row `i < 3` and column `j < n`. -/ +def grid (n : ℕ) : Finset (ℕ × ℕ) := Finset.range 3 ×ˢ Finset.range n + +/-- The determinant `(q - p) × (r - p)`, i.e. twice the signed area of the triangle `p q r`; +it vanishes iff `p`, `q`, `r` lie on a common line. -/ +def cross (p q r : ℕ × ℕ) : ℤ := + ((q.1 : ℤ) - p.1) * ((r.2 : ℤ) - p.2) - ((q.2 : ℤ) - p.2) * ((r.1 : ℤ) - p.1) + +/-- A finite set of lattice points is collinear iff any three of its points are collinear. -/ +def IsCollinear (s : Finset (ℕ × ℕ)) : Prop := ∀ p ∈ s, ∀ q ∈ s, ∀ r ∈ s, cross p q r = 0 + +instance : DecidablePred IsCollinear := fun s => by unfold IsCollinear; infer_instance + +/-- A057566: the number of collinear triples (3-element collinear subsets) in the `3 × n` +rectangular grid. -/ +def a (n : ℕ) : ℕ := ((grid n).powersetCard 3 |>.filter IsCollinear).card + +/-! ### A fast evaluator for the data check -/ + +/-- The collinearity test `cross p q r = 0`, rearranged into an equation of natural numbers. -/ +def collB (p q r : ℕ × ℕ) : Bool := + Nat.beq (q.1 * r.2 + q.2 * p.1 + p.2 * r.1) (q.2 * r.1 + q.1 * p.2 + p.1 * r.2) + +/-- Number of `r` in `l` with `p, q, r` collinear. -/ +def cnt2 (p q : ℕ × ℕ) : List (ℕ × ℕ) → ℕ + | [] => 0 + | r :: l => cnt2 p q l + (if collB p q r then 1 else 0) + +/-- Number of pairs `q, r` (in this order) in `l` with `p, q, r` collinear. -/ +def cnt1 (p : ℕ × ℕ) : List (ℕ × ℕ) → ℕ + | [] => 0 + | q :: l => cnt1 p l + cnt2 p q l + +/-- Number of collinear triples `p, q, r` (in this order) in `l`. -/ +def cnt : List (ℕ × ℕ) → ℕ + | [] => 0 + | p :: l => cnt l + cnt1 p l + +/-- The points of `grid n`, listed once each. -/ +def pts (n : ℕ) : List (ℕ × ℕ) := List.range 3 ×ˢ List.range n + +/-- Fast evaluator of `a`. -/ +def fastA (n : ℕ) : ℕ := cnt (pts n) + +/-- Collinearity of a multiset of points. -/ +def Q (m : Multiset (ℕ × ℕ)) : Prop := ∀ p ∈ m, ∀ q ∈ m, ∀ r ∈ m, cross p q r = 0 + +instance : DecidablePred Q := fun s => by unfold Q; infer_instance + +theorem collB_iff (p q r : ℕ × ℕ) : collB p q r = true ↔ cross p q r = 0 := by + unfold collB cross + rw [Nat.beq_eq] + constructor + · intro h + have h' := congrArg (fun x : ℕ => (x : ℤ)) h + push_cast at h' + linear_combination h' + · intro h + have h' : ((q.1 * r.2 + q.2 * p.1 + p.2 * r.1 : ℕ) : ℤ) = + ((q.2 * r.1 + q.1 * p.2 + p.1 * r.2 : ℕ) : ℤ) := by + push_cast + linear_combination h + exact_mod_cast h' + +theorem Q_triple (p q r : ℕ × ℕ) : Q (([p, q, r] : List (ℕ × ℕ)) : Multiset (ℕ × ℕ)) ↔ + cross p q r = 0 := by + unfold Q + simp only [Multiset.mem_coe, List.mem_cons, List.not_mem_nil, or_false] + constructor + · intro h + exact h p (Or.inl rfl) q (Or.inr (Or.inl rfl)) r (Or.inr (Or.inr rfl)) + · intro h x hx y hy z hz + rcases hx with rfl | rfl | rfl <;> rcases hy with rfl | rfl | rfl <;> + rcases hz with rfl | rfl | rfl <;> unfold cross at * <;> + first | ring1 | linear_combination h | linear_combination -h + +/-- For a set of three points, `IsCollinear` is the vanishing of `cross`. -/ +theorem isCollinear_triple (p q r : ℕ × ℕ) : + IsCollinear {p, q, r} ↔ cross p q r = 0 := by + unfold IsCollinear + simp only [Finset.mem_insert, Finset.mem_singleton] + constructor + · intro h + exact h p (Or.inl rfl) q (Or.inr (Or.inl rfl)) r (Or.inr (Or.inr rfl)) + · intro h x hx y hy z hz + rcases hx with rfl | rfl | rfl <;> rcases hy with rfl | rfl | rfl <;> + rcases hz with rfl | rfl | rfl <;> unfold cross at * <;> + first | ring1 | linear_combination h | linear_combination -h + +theorem countP_one (p q : ℕ × ℕ) (l : List (ℕ × ℕ)) : + (l.sublistsLen 1).countP (fun t => decide (Q ((p :: q :: t : List (ℕ × ℕ)) : + Multiset (ℕ × ℕ)))) = cnt2 p q l := by + induction l with + | nil => rfl + | cons r l ih => + rw [List.sublistsLen_succ_cons, List.countP_append, ih] + simp only [List.sublistsLen_zero, List.map_cons, List.map_nil, cnt2] + congr 1 + rw [List.countP_singleton] + by_cases h : collB p q r = true + · simp [h, Q_triple, (collB_iff p q r).1 h] + · have h' : ¬ cross p q r = 0 := fun h'' => h ((collB_iff p q r).2 h'') + simp [h, Q_triple, h'] + +theorem countP_two (p : ℕ × ℕ) (l : List (ℕ × ℕ)) : + (l.sublistsLen 2).countP (fun t => decide (Q ((p :: t : List (ℕ × ℕ)) : + Multiset (ℕ × ℕ)))) = cnt1 p l := by + induction l with + | nil => rfl + | cons q l ih => + rw [List.sublistsLen_succ_cons, List.countP_append, ih, List.countP_map] + simp only [cnt1] + congr 1 + rw [← countP_one p q l] + rfl + +theorem countP_three (l : List (ℕ × ℕ)) : + (l.sublistsLen 3).countP (fun t : List (ℕ × ℕ) => decide (Q (↑t : Multiset (ℕ × ℕ)))) = + cnt l := by + induction l with + | nil => rfl + | cons p l ih => + rw [List.sublistsLen_succ_cons, List.countP_append, ih, List.countP_map] + simp only [cnt] + congr 1 + rw [← countP_two p l] + rfl + +theorem grid_val (n : ℕ) : (grid n).val = ((pts n : List (ℕ × ℕ)) : Multiset (ℕ × ℕ)) := by + rfl + +/-- The fast evaluator computes `a`. -/ +theorem a_eq_fastA (n : ℕ) : a n = fastA n := by + unfold a fastA + rw [Finset.card_def, Finset.filter_val, ← Multiset.countP_eq_card_filter] + have h1 : Multiset.countP IsCollinear ((grid n).powersetCard 3).val = + Multiset.countP Q (((grid n).powersetCard 3).val.map Finset.val) := by + rw [Multiset.countP_map, Multiset.countP_eq_card_filter] + rfl + rw [h1, Finset.map_val_val_powersetCard, grid_val, Multiset.powersetCard_coe, + Multiset.coe_countP, List.countP_map, ← countP_three] + rfl + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): +`a 0, …, a 24`. -/ +theorem a_data : (List.range 25).map (fun i => a (i + 0)) = + [0, 1, 2, 8, 20, 43, 78, 130, 200, 293, 410, 556, 732, 943, 1190, 1478, 1808, 2185, + 2610, 3088, 3620, 4211, 4862, 5578, 6360] := by + simp only [Nat.add_zero, a_eq_fastA] + decide +kernel + +/-- Layman's conjecture, for every `n ≥ 3` (where all floor arguments are nonnegative, so the +claim does not depend on the rounding convention; see the module docstring): +`a(n) = 5*floor((2n^3 - 3n^2 - n)/24) + floor((2(n-1)^3 - 3(n-1)^2 - (n-1))/24) + n`. -/ +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → (a n : ℤ) = + 5 * ⌊(2 * (n : ℚ) ^ 3 - 3 * (n : ℚ) ^ 2 - (n : ℚ)) / 24⌋ + + ⌊(2 * ((n : ℚ) - 1) ^ 3 - 3 * ((n : ℚ) - 1) ^ 2 - ((n : ℚ) - 1)) / 24⌋ + n + +/-- The literal reading of Layman's conjecture for every `n ≥ 0`, with true floors (not the +primary formalization; at `n = 0, 1, 2` it hinges on the floor of a small negative number, see +the module docstring). -/ +def statement_all : Prop := + ∀ n : ℕ, (a n : ℤ) = + 5 * ⌊(2 * (n : ℚ) ^ 3 - 3 * (n : ℚ) ^ 2 - (n : ℚ)) / 24⌋ + + ⌊(2 * ((n : ℚ) - 1) ^ 3 - 3 * ((n : ℚ) - 1) ^ 2 - ((n : ℚ) - 1)) / 24⌋ + n + +theorem statement_all_imp : statement_all → statement := + fun h n _ => h n + +/-- `statement` with the rational floors written as integer floor division. -/ +theorem statement_iff_ediv : statement ↔ ∀ n : ℕ, 3 ≤ n → (a n : ℤ) = + 5 * ((2 * (n : ℤ) ^ 3 - 3 * (n : ℤ) ^ 2 - (n : ℤ)) / 24) + + ((2 * ((n : ℤ) - 1) ^ 3 - 3 * ((n : ℤ) - 1) ^ 2 - ((n : ℤ) - 1)) / 24) + n := by + have key : ∀ m : ℤ, ⌊(2 * (m : ℚ) ^ 3 - 3 * (m : ℚ) ^ 2 - (m : ℚ)) / 24⌋ = + (2 * m ^ 3 - 3 * m ^ 2 - m) / 24 := by + intro m + have := Rat.floor_intCast_div_natCast (2 * m ^ 3 - 3 * m ^ 2 - m) 24 + push_cast at this + exact this + unfold statement + refine forall_congr' fun n => imp_congr_right fun _ => ?_ + have h1 := key (n : ℤ) + have h2 := key ((n : ℤ) - 1) + push_cast at h1 h2 + rw [h1, h2] + +end Math0.Statements.A057566 diff --git a/lean/Math0/Statements/OEIS/A057566b.lean b/lean/Math0/Statements/OEIS/A057566b.lean new file mode 100644 index 0000000..16e361b --- /dev/null +++ b/lean/Math0/Statements/OEIS/A057566b.lean @@ -0,0 +1,241 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A057566b: corrected floor formula for collinear triples in a `3 × n` grid + +Source: https://oeis.org/A057566 (FORMULA section, revision #30 of Oct 22 2026), original +conjecture by John W. Layman, Oct 2000, corrected by Alper Ferudun, Oct 21 2026. Verbatim: +> Conjecture: a(n) = 5*floor((2n^3 - 3n^2 - 2n + 3)/24) + floor((2(n-1)^3 - 3(n-1)^2 - 2(n-1) +> + 3)/24) + n, which fits all of the listed terms. [Corrected by _Alper Ferudun_, Oct 21 2026] + +The sequence (offset `0`) is "Number of collinear triples in a 3 X n rectangular grid." +This is the corrected version of the formula; the original (uncorrected) formula is the +statement `Math0.Statements.A057566.statement` in `Math0/Statements/OEIS/A057566.lean`. + +## Encoding + +* The `3 × n` grid is `grid n = {0, 1, 2} × {0, …, n - 1} ⊆ ℕ × ℕ` (row, column); it has `3n` + points (for `n = 0` it is empty). +* Three lattice points `p, q, r` are collinear iff the determinant + `cross p q r = (q.1 - p.1) * (r.2 - p.2) - (q.2 - p.2) * (r.1 - p.1)` (twice the signed area of + the triangle `p q r`, computed in `ℤ`) vanishes. A finite set of points is collinear + (`IsCollinear`) iff every three of its points (with repetitions allowed) satisfy this. + `isCollinear_triple` shows that for a set `{p, q, r}` this is just `cross p q r = 0`. +* A "collinear triple" is a 3-element subset of the grid that is collinear, so + `a n = #{s ⊆ grid n | #s = 3 ∧ IsCollinear s}`, written with `Finset.powersetCard 3`. +* `a` is computable but too slow for the kernel, so `fastA` counts the same triples by a nested + list recursion over the increasing index triples of the list `pts n` of grid points, with the + collinearity test rearranged into an equation of natural numbers. `a_eq_fastA` proves + `a n = fastA n` for every `n`, and `a_data` checks the listed terms `a 0, …, a 24` (the + brute-force count is cubic in the number of points, and `a 0, …, a 24` already takes about a + minute in the kernel). +* The floors are `Int.floor` of rational numbers (the true mathematical floor), and `n - 1` is + the rational (equivalently integer) `n - 1`, so for `n = 0` it is `-1` (not truncated to `0`). +* Range of `n`: the conjecture states no range, so `statement` asserts the identity for every + `n ≥ 0` (the offset of the sequence). The numerator `2m^3 - 3m^2 - 2m + 3` factors as + `(m - 1)(m + 1)(2m - 3)` and is `≥ 0` for every integer `m ≥ -1` (`numer_nonneg`), so for every + `n ≥ 0` both floor arguments (at `m = n` and `m = n - 1`) are nonnegative; hence floor, + truncation and integer division all agree and the claim does not depend on the rounding + convention. `statement_iff_ediv` restates `statement` with integer division `/` (floor + division for the positive divisor `24`) in place of the rational floors. +* The remark "which fits all of the listed terms" is the author's evidence, not part of the + claimed identity. +-/ + +namespace Math0.Statements.A057566b + +/-- The `3 × n` rectangular grid: lattice points `(i, j)` with row `i < 3` and column `j < n`. -/ +def grid (n : ℕ) : Finset (ℕ × ℕ) := Finset.range 3 ×ˢ Finset.range n + +/-- The determinant `(q - p) × (r - p)`, i.e. twice the signed area of the triangle `p q r`; +it vanishes iff `p`, `q`, `r` lie on a common line. -/ +def cross (p q r : ℕ × ℕ) : ℤ := + ((q.1 : ℤ) - p.1) * ((r.2 : ℤ) - p.2) - ((q.2 : ℤ) - p.2) * ((r.1 : ℤ) - p.1) + +/-- A finite set of lattice points is collinear iff any three of its points are collinear. -/ +def IsCollinear (s : Finset (ℕ × ℕ)) : Prop := ∀ p ∈ s, ∀ q ∈ s, ∀ r ∈ s, cross p q r = 0 + +instance : DecidablePred IsCollinear := fun s => by unfold IsCollinear; infer_instance + +/-- A057566: the number of collinear triples (3-element collinear subsets) in the `3 × n` +rectangular grid. -/ +def a (n : ℕ) : ℕ := ((grid n).powersetCard 3 |>.filter IsCollinear).card + +/-! ### A fast evaluator for the data check -/ + +/-- The collinearity test `cross p q r = 0`, rearranged into an equation of natural numbers. -/ +def collB (p q r : ℕ × ℕ) : Bool := + Nat.beq (q.1 * r.2 + q.2 * p.1 + p.2 * r.1) (q.2 * r.1 + q.1 * p.2 + p.1 * r.2) + +/-- Number of `r` in `l` with `p, q, r` collinear. -/ +def cnt2 (p q : ℕ × ℕ) : List (ℕ × ℕ) → ℕ + | [] => 0 + | r :: l => cnt2 p q l + (if collB p q r then 1 else 0) + +/-- Number of pairs `q, r` (in this order) in `l` with `p, q, r` collinear. -/ +def cnt1 (p : ℕ × ℕ) : List (ℕ × ℕ) → ℕ + | [] => 0 + | q :: l => cnt1 p l + cnt2 p q l + +/-- Number of collinear triples `p, q, r` (in this order) in `l`. -/ +def cnt : List (ℕ × ℕ) → ℕ + | [] => 0 + | p :: l => cnt l + cnt1 p l + +/-- The points of `grid n`, listed once each. -/ +def pts (n : ℕ) : List (ℕ × ℕ) := List.range 3 ×ˢ List.range n + +/-- Fast evaluator of `a`. -/ +def fastA (n : ℕ) : ℕ := cnt (pts n) + +/-- Collinearity of a multiset of points. -/ +def Q (m : Multiset (ℕ × ℕ)) : Prop := ∀ p ∈ m, ∀ q ∈ m, ∀ r ∈ m, cross p q r = 0 + +instance : DecidablePred Q := fun s => by unfold Q; infer_instance + +theorem collB_iff (p q r : ℕ × ℕ) : collB p q r = true ↔ cross p q r = 0 := by + unfold collB cross + rw [Nat.beq_eq] + constructor + · intro h + have h' := congrArg (fun x : ℕ => (x : ℤ)) h + push_cast at h' + linear_combination h' + · intro h + have h' : ((q.1 * r.2 + q.2 * p.1 + p.2 * r.1 : ℕ) : ℤ) = + ((q.2 * r.1 + q.1 * p.2 + p.1 * r.2 : ℕ) : ℤ) := by + push_cast + linear_combination h + exact_mod_cast h' + +theorem Q_triple (p q r : ℕ × ℕ) : Q (([p, q, r] : List (ℕ × ℕ)) : Multiset (ℕ × ℕ)) ↔ + cross p q r = 0 := by + unfold Q + simp only [Multiset.mem_coe, List.mem_cons, List.not_mem_nil, or_false] + constructor + · intro h + exact h p (Or.inl rfl) q (Or.inr (Or.inl rfl)) r (Or.inr (Or.inr rfl)) + · intro h x hx y hy z hz + rcases hx with rfl | rfl | rfl <;> rcases hy with rfl | rfl | rfl <;> + rcases hz with rfl | rfl | rfl <;> unfold cross at * <;> + first | ring1 | linear_combination h | linear_combination -h + +/-- For a set of three points, `IsCollinear` is the vanishing of `cross`. -/ +theorem isCollinear_triple (p q r : ℕ × ℕ) : + IsCollinear {p, q, r} ↔ cross p q r = 0 := by + unfold IsCollinear + simp only [Finset.mem_insert, Finset.mem_singleton] + constructor + · intro h + exact h p (Or.inl rfl) q (Or.inr (Or.inl rfl)) r (Or.inr (Or.inr rfl)) + · intro h x hx y hy z hz + rcases hx with rfl | rfl | rfl <;> rcases hy with rfl | rfl | rfl <;> + rcases hz with rfl | rfl | rfl <;> unfold cross at * <;> + first | ring1 | linear_combination h | linear_combination -h + +theorem countP_one (p q : ℕ × ℕ) (l : List (ℕ × ℕ)) : + (l.sublistsLen 1).countP (fun t => decide (Q ((p :: q :: t : List (ℕ × ℕ)) : + Multiset (ℕ × ℕ)))) = cnt2 p q l := by + induction l with + | nil => rfl + | cons r l ih => + rw [List.sublistsLen_succ_cons, List.countP_append, ih] + simp only [List.sublistsLen_zero, List.map_cons, List.map_nil, cnt2] + congr 1 + rw [List.countP_singleton] + by_cases h : collB p q r = true + · simp [h, Q_triple, (collB_iff p q r).1 h] + · have h' : ¬ cross p q r = 0 := fun h'' => h ((collB_iff p q r).2 h'') + simp [h, Q_triple, h'] + +theorem countP_two (p : ℕ × ℕ) (l : List (ℕ × ℕ)) : + (l.sublistsLen 2).countP (fun t => decide (Q ((p :: t : List (ℕ × ℕ)) : + Multiset (ℕ × ℕ)))) = cnt1 p l := by + induction l with + | nil => rfl + | cons q l ih => + rw [List.sublistsLen_succ_cons, List.countP_append, ih, List.countP_map] + simp only [cnt1] + congr 1 + rw [← countP_one p q l] + rfl + +theorem countP_three (l : List (ℕ × ℕ)) : + (l.sublistsLen 3).countP (fun t : List (ℕ × ℕ) => decide (Q (↑t : Multiset (ℕ × ℕ)))) = + cnt l := by + induction l with + | nil => rfl + | cons p l ih => + rw [List.sublistsLen_succ_cons, List.countP_append, ih, List.countP_map] + simp only [cnt] + congr 1 + rw [← countP_two p l] + rfl + +theorem grid_val (n : ℕ) : (grid n).val = ((pts n : List (ℕ × ℕ)) : Multiset (ℕ × ℕ)) := by + rfl + +/-- The fast evaluator computes `a`. -/ +theorem a_eq_fastA (n : ℕ) : a n = fastA n := by + unfold a fastA + rw [Finset.card_def, Finset.filter_val, ← Multiset.countP_eq_card_filter] + have h1 : Multiset.countP IsCollinear ((grid n).powersetCard 3).val = + Multiset.countP Q (((grid n).powersetCard 3).val.map Finset.val) := by + rw [Multiset.countP_map, Multiset.countP_eq_card_filter] + rfl + rw [h1, Finset.map_val_val_powersetCard, grid_val, Multiset.powersetCard_coe, + Multiset.coe_countP, List.countP_map, ← countP_three] + rfl + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): +`a 0, …, a 24`. -/ +theorem a_data : (List.range 25).map (fun i => a (i + 0)) = + [0, 1, 2, 8, 20, 43, 78, 130, 200, 293, 410, 556, 732, 943, 1190, 1478, 1808, 2185, + 2610, 3088, 3620, 4211, 4862, 5578, 6360] := by + simp only [Nat.add_zero, a_eq_fastA] + decide +kernel + +/-- The corrected conjecture (Layman, corrected by Ferudun), for every `n ≥ 0`, with true +floors: +`a(n) = 5*floor((2n^3 - 3n^2 - 2n + 3)/24) + floor((2(n-1)^3 - 3(n-1)^2 - 2(n-1) + 3)/24) + n`. -/ +def statement : Prop := + ∀ n : ℕ, (a n : ℤ) = + 5 * ⌊(2 * (n : ℚ) ^ 3 - 3 * (n : ℚ) ^ 2 - 2 * (n : ℚ) + 3) / 24⌋ + + ⌊(2 * ((n : ℚ) - 1) ^ 3 - 3 * ((n : ℚ) - 1) ^ 2 - 2 * ((n : ℚ) - 1) + 3) / 24⌋ + n + +/-! ### Remarks on the reading of `floor` -/ + +/-- The numerator `2m^3 - 3m^2 - 2m + 3 = (m - 1)(m + 1)(2m - 3)` is nonnegative for every +integer `m ≥ -1`; in particular both floor arguments in `statement` are nonnegative for every +`n ≥ 0`, so the reading of `floor` (true floor vs. truncation) does not matter. -/ +theorem numer_nonneg (m : ℤ) (hm : -1 ≤ m) : 0 ≤ 2 * m ^ 3 - 3 * m ^ 2 - 2 * m + 3 := by + have hf : 2 * m ^ 3 - 3 * m ^ 2 - 2 * m + 3 = (m - 1) * (m + 1) * (2 * m - 3) := by ring + rcases (show m = -1 ∨ m = 0 ∨ m = 1 ∨ 2 ≤ m by omega) with rfl | rfl | rfl | h + · norm_num + · norm_num + · norm_num + · rw [hf] + exact mul_nonneg (mul_nonneg (by omega) (by omega)) (by omega) + +/-- `statement` with the rational floors written as integer floor division. -/ +theorem statement_iff_ediv : statement ↔ ∀ n : ℕ, (a n : ℤ) = + 5 * ((2 * (n : ℤ) ^ 3 - 3 * (n : ℤ) ^ 2 - 2 * (n : ℤ) + 3) / 24) + + ((2 * ((n : ℤ) - 1) ^ 3 - 3 * ((n : ℤ) - 1) ^ 2 - 2 * ((n : ℤ) - 1) + 3) / 24) + + n := by + have key : ∀ m : ℤ, ⌊(2 * (m : ℚ) ^ 3 - 3 * (m : ℚ) ^ 2 - 2 * (m : ℚ) + 3) / 24⌋ = + (2 * m ^ 3 - 3 * m ^ 2 - 2 * m + 3) / 24 := by + intro m + have := Rat.floor_intCast_div_natCast (2 * m ^ 3 - 3 * m ^ 2 - 2 * m + 3) 24 + push_cast at this + exact this + unfold statement + refine forall_congr' fun n => ?_ + have h1 := key (n : ℤ) + have h2 := key ((n : ℤ) - 1) + push_cast at h1 h2 + rw [h1, h2] + +end Math0.Statements.A057566b diff --git a/lean/Math0/Statements/OEIS/A060693.lean b/lean/Math0/Statements/OEIS/A060693.lean new file mode 100644 index 0000000..c79770f --- /dev/null +++ b/lean/Math0/Statements/OEIS/A060693.lean @@ -0,0 +1,444 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A060693: Schulte's alternating quadratic sum over the Schröder-peaks triangle + +Source: https://oeis.org/A060693, Werner Schulte, Jan 11 2017 (FORMULA section). Verbatim: +> Conjecture: Sum_{k=0..n} (-1)^k*T(n,k)*(n+1-k)^2 = 1+n+n^2. + +The entry (F. Chapoton, Apr 20 2001; name by Peter Luschny, Jul 26 2017; offset `0`, keyword +`tabl`) is "Triangle (0 <= k <= n) read by rows: T(n, k) is the number of Schröder paths from +(0,0) to (2n,0) having k peaks." A comment by Emeric Deutsch explains: "Schroeder paths (i.e., +consisting of steps U=(1,1), D=(1,-1), H=(2,0) and never going below the x-axis) from (0,0) to +(2n,0), having k peaks. Example: T(2,1)=3 because we have UU*DD, U*DH and HU*D, the peaks being +shown by *." + +## Encoding + +* *Paths.* A path is a word `p : List Step` over the steps `U = (1,1)`, `D = (1,-1)`, + `H = (2,0)`, drawn from `(0,0)`. After the initial segment `q` of `p` the path is at the point + `(width q, height q)`, where `width` (resp. `height`) adds up the `x`- (resp. `y`-) + displacements of the steps. +* *Schröder paths.* `IsSchroderPath n p`: the path ends at `(2n, 0)` (`width p = 2 * n` and + `height p = 0`) and never goes below the `x`-axis: every initial segment `q ∈ p.inits` ends at + height `≥ 0`. (Checking the vertices suffices: between two vertices the path is a straight + segment.) +* *Peaks.* A peak is a `U` step immediately followed by a `D` step; `peaks p` is the number of + adjacent pairs `(U, D)` in `p`, i.e. of positions `i` with `p[i] = U` and `p[i+1] = D`. +* *The triangle.* `words m` lists all words of total width `m` (`mem_words`; it has no + repetitions, `nodup_words`). `schroderPaths n` is the finite set of Schröder paths from `(0,0)` + to `(2n,0)` (`mem_schroderPaths`), and `T n k` is the number of those with exactly `k` peaks + (`T_eq_ncard` restates it as the cardinality of + `{p | IsSchroderPath n p ∧ peaks p = k}`). `T` is computable but enumerates `words (2n)`, so + for evaluation we use a dynamic program: `cnt m h b k` counts the words of width `m` that, + started at height `h`, stay weakly above the axis and end on it with `k` peaks (an initial `D` + counts as a peak when `b = true`, i.e. when the step before was a `U`). It satisfies a + three-term recursion in `m` according to the first step (`cnt_step`), and the tables `tabs m` + store `cnt m` and `cnt (m+1)` (`tabs_spec`). `T_eq_Tfast` proves `T n k = Tfast n k` for all + `n, k`, where `Tfast n k` reads the value off the table. +* *Data.* `T_data` checks all 56 listed terms (rows `n = 0, …, 9` and `T(10,0) = 16796`) in the + kernel. `a` is the triangle read by rows (the OEIS sequence itself, offset `0`), and `a_data` + checks the same 56 terms as `a 0, …, a 55`. +* *The conjecture.* `statement`: for every `n ≥ 0`, + `∑_{k=0}^{n} (-1)^k · T(n,k) · (n+1-k)^2 = 1 + n + n^2`, computed in `ℤ` (so `n + 1 - k` is + integer subtraction; it is positive for `k ≤ n` anyway). `statement_check` confirms the + identity for `n ≤ 12` (a sanity check of the transcription, not a proof). +-/ + +namespace Math0.Statements.A060693 + +/-! ### Schröder paths and peaks -/ + +/-- The steps of a Schröder path: `U = (1,1)`, `D = (1,-1)`, `H = (2,0)`. -/ +inductive Step + | U + | D + | H + deriving DecidableEq, Repr + +namespace Step + +/-- The `x`-displacement of a step. -/ +def dx : Step → ℕ + | U => 1 + | D => 1 + | H => 2 + +/-- The `y`-displacement of a step. -/ +def dy : Step → ℤ + | U => 1 + | D => -1 + | H => 0 + +end Step + +open Step + +/-- The `x`-coordinate reached by the path `p` started at `(0,0)`. -/ +def width (p : List Step) : ℕ := (p.map Step.dx).sum + +/-- The `y`-coordinate reached by the path `p` started at `(0,0)`. -/ +def height (p : List Step) : ℤ := (p.map Step.dy).sum + +/-- `p` is a Schröder path from `(0,0)` to `(2n,0)`: it ends at `(2n,0)` and never goes below the +`x`-axis (every initial segment of `p` ends at height `≥ 0`). -/ +def IsSchroderPath (n : ℕ) (p : List Step) : Prop := + width p = 2 * n ∧ height p = 0 ∧ ∀ q ∈ p.inits, 0 ≤ height q + +instance (n : ℕ) : DecidablePred (IsSchroderPath n) := fun p => by + unfold IsSchroderPath; infer_instance + +/-- The number of peaks of `p`: adjacent pairs of steps `U` followed by `D`. -/ +def peaks (p : List Step) : ℕ := (p.zip p.tail).count (U, D) + +/-- All words over `{U, D, H}` of total width `m`. -/ +def words : ℕ → List (List Step) + | 0 => [[]] + | 1 => [[U], [D]] + | m + 2 => (words (m + 1)).map (U :: ·) ++ (words (m + 1)).map (D :: ·) ++ + (words m).map (H :: ·) + +/-- The Schröder paths from `(0,0)` to `(2n,0)`. -/ +def schroderPaths (n : ℕ) : Finset (List Step) := + (words (2 * n)).toFinset.filter (IsSchroderPath n) + +/-- A060693: `T(n, k)` is the number of Schröder paths from `(0,0)` to `(2n,0)` having `k` +peaks. -/ +def T (n k : ℕ) : ℕ := ((schroderPaths n).filter (fun p => peaks p = k)).card + +/-! ### Basic facts -/ + +@[simp] theorem width_nil : width [] = 0 := rfl + +@[simp] theorem width_cons (s : Step) (p : List Step) : width (s :: p) = s.dx + width p := by + simp [width] + +@[simp] theorem height_nil : height [] = 0 := rfl + +@[simp] theorem height_cons (s : Step) (p : List Step) : height (s :: p) = s.dy + height p := by + simp [height] + +theorem width_eq_zero {p : List Step} : width p = 0 ↔ p = [] := by + cases p with + | nil => simp + | cons s p => cases s <;> simp [Step.dx] + +theorem mem_words : ∀ (p : List Step) (m : ℕ), p ∈ words m ↔ width p = m + | [], 0 => by simp [words] + | [], 1 => by simp [words] + | [], m + 2 => by simp [words] + | s :: p, 0 => by cases s <;> simp [words, Step.dx] + | s :: p, 1 => by + cases s <;> simp [words, Step.dx, width_eq_zero] + omega + | s :: p, m + 2 => by + have h1 := mem_words p (m + 1) + have h0 := mem_words p m + cases s <;> simp [words, Step.dx, h1, h0] <;> omega + +theorem nodup_words : ∀ m, (words m).Nodup ∧ (words (m + 1)).Nodup + | 0 => by simp [words] + | m + 1 => by + obtain ⟨h0, h1⟩ := nodup_words m + refine ⟨h1, ?_⟩ + show ((words (m + 1)).map (U :: ·) ++ (words (m + 1)).map (D :: ·) ++ + (words m).map (H :: ·)).Nodup + have hinj : ∀ s : Step, Function.Injective (s :: · : List Step → List Step) := + fun s _ _ h => List.cons_injective h + rw [List.nodup_append, List.nodup_append] + refine ⟨⟨h1.map (hinj U), h1.map (hinj D), ?_⟩, h0.map (hinj H), ?_⟩ + · simp + · simp only [List.mem_append, List.mem_map] + rintro a (⟨a1, -, rfl⟩ | ⟨a1, -, rfl⟩) b ⟨a2, -, rfl⟩ h <;> simp at h + +theorem mem_schroderPaths (n : ℕ) (p : List Step) : p ∈ schroderPaths n ↔ IsSchroderPath n p := by + simp only [schroderPaths, Finset.mem_filter, List.mem_toFinset, mem_words] + exact ⟨fun h => h.2, fun h => ⟨h.1, h⟩⟩ + +/-- `T n k` is the number of Schröder paths from `(0,0)` to `(2n,0)` with exactly `k` peaks. -/ +theorem T_eq_ncard (n k : ℕ) : + T n k = {p : List Step | IsSchroderPath n p ∧ peaks p = k}.ncard := by + rw [T, ← Set.ncard_coe_finset] + congr 1 + ext p + simp [mem_schroderPaths] + +/-! ### A dynamic program for `T` -/ + +/-- Walking along `p` from height `h`, the path never goes below the axis and ends on it. -/ +def valid : ℕ → List Step → Bool + | h, [] => h == 0 + | h, U :: p => valid (h + 1) p + | 0, D :: _ => false + | h + 1, D :: p => valid h p + | h, H :: p => valid h p + +/-- The number of peaks of `p`, where an initial `D` also counts as a peak if `b = true` (the step +before `p` was a `U`). -/ +def peaksFrom : Bool → List Step → ℕ + | _, [] => 0 + | _, U :: p => peaksFrom true p + | b, D :: p => (if b then 1 else 0) + peaksFrom false p + | _, H :: p => peaksFrom false p + +theorem valid_iff : ∀ (p : List Step) (h : ℕ), + valid h p = true ↔ (h : ℤ) + height p = 0 ∧ ∀ q ∈ p.inits, 0 ≤ (h : ℤ) + height q + | [], h => by simp [valid] + | U :: p, h => by + rw [valid, valid_iff p (h + 1)] + simp only [List.inits_cons, List.mem_cons, List.mem_map, forall_eq_or_imp, height_nil, + forall_exists_index, and_imp, forall_apply_eq_imp_iff₂, height_cons, Step.dy] + push_cast + constructor + · rintro ⟨h1, h2⟩ + exact ⟨by omega, by omega, fun q hq => by have := h2 q hq; omega⟩ + · rintro ⟨h1, -, h2⟩ + exact ⟨by omega, fun q hq => by have := h2 q hq; omega⟩ + | D :: p, 0 => by + simp only [valid, Bool.false_eq_true, false_iff, not_and] + intro _ h2 + have := h2 [D] (by simp) + simp [Step.dy] at this + | D :: p, h + 1 => by + rw [valid, valid_iff p h] + simp only [List.inits_cons, List.mem_cons, List.mem_map, forall_eq_or_imp, height_nil, + forall_exists_index, and_imp, forall_apply_eq_imp_iff₂, height_cons, Step.dy] + push_cast + constructor + · rintro ⟨h1, h2⟩ + exact ⟨by omega, by omega, fun q hq => by have := h2 q hq; omega⟩ + · rintro ⟨h1, -, h2⟩ + exact ⟨by omega, fun q hq => by have := h2 q hq; omega⟩ + | H :: p, h => by + rw [valid, valid_iff p h] + simp only [List.inits_cons, List.mem_cons, List.mem_map, forall_eq_or_imp, height_nil, + forall_exists_index, and_imp, forall_apply_eq_imp_iff₂, height_cons, Step.dy] + constructor + · rintro ⟨h1, h2⟩ + exact ⟨by omega, by omega, fun q hq => by have := h2 q hq; omega⟩ + · rintro ⟨h1, -, h2⟩ + exact ⟨by omega, fun q hq => by have := h2 q hq; omega⟩ + +theorem peaks_cons (s : Step) (p : List Step) : + peaks (s :: p) = (if s = U ∧ p.head? = some D then 1 else 0) + peaks p := by + cases p with + | nil => simp [peaks] + | cons t p => + simp only [peaks, List.tail_cons, List.zip_cons_cons, List.count_cons, List.head?_cons, + Option.some.injEq, beq_iff_eq, Prod.mk.injEq] + omega + +theorem peaksFrom_eq : ∀ (b : Bool) (p : List Step), + peaksFrom b p = (if b = true ∧ p.head? = some D then 1 else 0) + peaks p + | _, [] => by simp [peaksFrom, peaks] + | b, U :: p => by + rw [peaksFrom, peaksFrom_eq true p, peaks_cons] + simp + | b, D :: p => by + rw [peaksFrom, peaksFrom_eq false p, peaks_cons] + cases b <;> simp + | b, H :: p => by + rw [peaksFrom, peaksFrom_eq false p, peaks_cons] + simp + +theorem peaks_eq_peaksFrom (p : List Step) : peaks p = peaksFrom false p := by + simp [peaksFrom_eq] + +theorem valid_le : ∀ (p : List Step) (h : ℕ), valid h p = true → h ≤ width p + | [], h => by simp [valid] + | U :: p, h => by + intro hv + have := valid_le p (h + 1) hv + simp [Step.dx]; omega + | D :: p, 0 => by simp [valid] + | D :: p, h + 1 => by + intro hv + have := valid_le p h hv + simp [Step.dx]; omega + | H :: p, h => by + intro hv + have := valid_le p h hv + simp [Step.dx]; omega + +theorem peaksFrom_le : ∀ (b : Bool) (p : List Step), peaksFrom b p ≤ width p + | _, [] => by simp [peaksFrom] + | _, U :: p => by + have := peaksFrom_le true p + simp [peaksFrom, Step.dx]; omega + | b, D :: p => by + have := peaksFrom_le false p + simp only [peaksFrom, width_cons, Step.dx] + split <;> omega + | _, H :: p => by + have := peaksFrom_le false p + simp [peaksFrom, Step.dx]; omega + +/-- The number of words of width `m` that, started at height `h`, stay weakly above the axis, +end on it, and have `k` peaks (an initial `D` counting as a peak when `b = true`). -/ +def cnt (m h : ℕ) (b : Bool) (k : ℕ) : ℕ := + (words m).countP (fun w => valid h w && peaksFrom b w == k) + +/-- The contribution of an initial `D` step to the recursion for `cnt`. -/ +def dTerm (f : ℕ → Bool → ℕ → ℕ) : ℕ → Bool → ℕ → ℕ + | 0, _, _ => 0 + | h + 1, false, k => f h false k + | _ + 1, true, 0 => 0 + | h + 1, true, k + 1 => f h false k + +/-- One step of the recursion: the first step is `U`, `D` or `H`. -/ +def step (f1 f0 : ℕ → Bool → ℕ → ℕ) (h : ℕ) (b : Bool) (k : ℕ) : ℕ := + f1 (h + 1) true k + dTerm f1 h b k + f0 h false k + +theorem cnt_step (m h : ℕ) (b : Bool) (k : ℕ) : + cnt (m + 2) h b k = step (cnt (m + 1)) (cnt m) h b k := by + rw [cnt, words, List.countP_append, List.countP_append, List.countP_map, List.countP_map, + List.countP_map, step] + refine congrArg₂ (· + ·) (congrArg₂ (· + ·) ?_ ?_) ?_ + · simp [cnt, valid, peaksFrom, Function.comp_def] + · rcases h with _ | h + · simp [valid, dTerm, Function.comp_def] + · rcases b with _ | _ + · simp [cnt, valid, peaksFrom, dTerm, Function.comp_def] + · rcases k with _ | k + · simp [valid, peaksFrom, dTerm, Function.comp_def] + · simp only [cnt, valid, peaksFrom, dTerm, if_true, Function.comp_def] + congr 1 + funext w + congr 1 + rw [Bool.eq_iff_iff] + simp only [beq_iff_eq] + omega + · simp [cnt, valid, peaksFrom, Function.comp_def] + +theorem cnt_eq_zero (m h : ℕ) (b : Bool) (k : ℕ) (hm : m < h ∨ m < k) : cnt m h b k = 0 := by + rw [cnt, List.countP_eq_zero] + intro w hw + rw [mem_words] at hw + have h1 := valid_le w h + have h2 := peaksFrom_le b w + simp only [Bool.and_eq_true, beq_iff_eq, not_and] + intro hv hk + have := h1 hv + omega + +/-- A table: entry `h` holds the coefficient lists (indexed by `k`) for `b = false` and +`b = true`. -/ +abbrev Tab := List (List ℕ × List ℕ) + +/-- Look up the entry `(h, b, k)` of a table (`0` outside the table). -/ +def look (t : Tab) (h : ℕ) (b : Bool) (k : ℕ) : ℕ := + (if b then (t.getD h ([], [])).2 else (t.getD h ([], [])).1).getD k 0 + +/-- The next table, of size `N × N`, computed from the previous two by `step`. -/ +def next (N : ℕ) (t0 t1 : Tab) : Tab := + (List.range N).map fun h => + ((List.range N).map fun k => step (look t1) (look t0) h false k, + (List.range N).map fun k => step (look t1) (look t0) h true k) + +theorem look_next (N : ℕ) (t0 t1 : Tab) (h : ℕ) (b : Bool) (k : ℕ) : + look (next N t0 t1) h b k = if h < N ∧ k < N then step (look t1) (look t0) h b k else 0 := by + simp only [look, next, List.getD_eq_getElem?_getD, List.getElem?_map] + by_cases hh : h < N + · rw [List.getElem?_range hh] + by_cases hk : k < N + · cases b <;> simp [hh, hk] + · cases b <;> simp [hk] + · cases b <;> simp [hh] + +/-- The tables for widths `m` and `m + 1`. -/ +def tabs : ℕ → Tab × Tab + | 0 => ([([1], [1])], [([0, 0], [0, 0]), ([1, 0], [0, 1])]) + | m + 1 => ((tabs m).2, next (m + 3) (tabs m).1 (tabs m).2) + +theorem tabs_spec : ∀ m : ℕ, + look (tabs m).1 = cnt m ∧ look (tabs m).2 = cnt (m + 1) + | 0 => by + constructor + · funext h b k + rcases h with _ | _ | h <;> rcases k with _ | _ | k <;> cases b <;> + simp [look, tabs, cnt, words, valid, peaksFrom] + · funext h b k + rcases h with _ | _ | h <;> rcases k with _ | _ | k <;> cases b <;> + simp [look, tabs, cnt, words, valid, peaksFrom] + | m + 1 => by + obtain ⟨h0, h1⟩ := tabs_spec m + refine ⟨h1, ?_⟩ + funext h b k + show look (next (m + 3) (tabs m).1 (tabs m).2) h b k = cnt (m + 2) h b k + rw [look_next, h0, h1, cnt_step] + split_ifs with hk + · rfl + · rw [← cnt_step, cnt_eq_zero] + omega + +/-- Fast evaluation of `T n k` via the tables. -/ +def Tfast (n k : ℕ) : ℕ := look (tabs (2 * n)).1 0 false k + +theorem T_eq_cnt (n k : ℕ) : T n k = cnt (2 * n) 0 false k := by + rw [T, schroderPaths, Finset.filter_filter, ← List.toFinset_eq (nodup_words _).1, + Finset.card_def, Finset.filter_val, Multiset.filter_coe, Multiset.coe_card, cnt, + List.countP_eq_length_filter] + congr 1 + apply List.filter_congr + intro w hw + rw [mem_words] at hw + rw [Bool.eq_iff_iff] + simp only [decide_eq_true_eq, Bool.and_eq_true, beq_iff_eq, valid_iff, IsSchroderPath, hw, + peaks_eq_peaksFrom] + push_cast + simp + +theorem T_eq_Tfast (n k : ℕ) : T n k = Tfast n k := by + rw [T_eq_cnt, Tfast, (tabs_spec _).1] + +/-! ### Data -/ + +/-- The definition reproduces the listed rows `n = 0, …, 9` of the triangle (kernel-checked). -/ +theorem T_data : (List.range 10).map (fun n => (List.range (n + 1)).map (T n)) = + [[1], + [1, 1], + [2, 3, 1], + [5, 10, 6, 1], + [14, 35, 30, 10, 1], + [42, 126, 140, 70, 15, 1], + [132, 462, 630, 420, 140, 21, 1], + [429, 1716, 2772, 2310, 1050, 252, 28, 1], + [1430, 6435, 12012, 12012, 6930, 2310, 420, 36, 1], + [4862, 24310, 51480, 60060, 42042, 18018, 4620, 660, 45, 1]] ∧ + T 10 0 = 16796 := by + rw [funext₂ T_eq_Tfast] + decide +kernel + +/-- A060693 as a sequence (offset `0`): the triangle `T` read by rows. (Rows `0, …, i` contain at +least `i + 1` entries, so the `i`-th entry of the concatenation lies among them.) -/ +def a (i : ℕ) : ℕ := + ((List.range (i + 1)).flatMap fun n => (List.range (n + 1)).map (T n)).getD i 0 + +/-- The definition reproduces all 56 terms listed in OEIS, `a 0, …, a 55` (kernel-checked). -/ +theorem a_data : (List.range 56).map (fun i => a (i + 0)) = + [1, 1, 1, 2, 3, 1, 5, 10, 6, 1, 14, 35, 30, 10, 1, 42, 126, 140, 70, 15, 1, 132, 462, 630, + 420, 140, 21, 1, 429, 1716, 2772, 2310, 1050, 252, 28, 1, 1430, 6435, 12012, 12012, + 6930, 2310, 420, 36, 1, 4862, 24310, 51480, 60060, 42042, 18018, 4620, 660, 45, 1, + 16796] := by + unfold a + rw [funext₂ T_eq_Tfast] + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjecture (Werner Schulte, 2017): for every `n ≥ 0`, +`∑_{k=0}^{n} (-1)^k · T(n,k) · (n+1-k)^2 = 1 + n + n^2`. -/ +def statement : Prop := + ∀ n : ℕ, ∑ k ∈ Finset.range (n + 1), (-1 : ℤ) ^ k * (T n k : ℤ) * ((n : ℤ) + 1 - k) ^ 2 = + 1 + (n : ℤ) + (n : ℤ) ^ 2 + +/-- Sanity check of the transcription (not a proof): the identity holds for `n ≤ 12`. -/ +theorem statement_check : ∀ n < 13, ∑ k ∈ Finset.range (n + 1), + (-1 : ℤ) ^ k * (T n k : ℤ) * ((n : ℤ) + 1 - k) ^ 2 = 1 + (n : ℤ) + (n : ℤ) ^ 2 := by + rw [funext₂ T_eq_Tfast] + decide +kernel + +end Math0.Statements.A060693 diff --git a/lean/Math0/Statements/OEIS/A062887.lean b/lean/Math0/Statements/OEIS/A062887.lean new file mode 100644 index 0000000..e135628 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A062887.lean @@ -0,0 +1,228 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A062887: multiples of `2n+1` with odd digits descending by 2 (mod 10) + +Source: https://oeis.org/A062887, Sean A. Irvine, Apr 14 2023 (COMMENTS section). Verbatim: +> Conjecture: The only numbers n for which a(n)=0 are those for which 2*n+1 is divisible by 125. + +The entry (Amarnath Murthy, Jun 28 2001, offset `0`) is "Smallest multiple of 2n+1 with the +property that its digits are odd and each digit is two less (mod 10) than the previous digit, or +0 if no such number exists." Data: `1, 3, 5, 7, 9, 319, 975, 75, 7531, 19, 197531975319, …` +(26 terms, `n = 0, …, 25`). + +## Encoding + +* *The digit property.* `IsDesc2 N`: `N > 0`, every decimal digit of `N` is odd, and, reading + the digits from left to right (most significant first, `(Nat.digits 10 N).reverse`), each + digit `next` is two less (mod 10) than the previous digit `prev`, i.e. + `next + 2 ≡ prev [MOD 10]`. Examples: `975`, `75`, `319`, `1`, `9753197`. The condition + `N > 0` is needed because `Nat.digits 10 0 = []` would make `0` satisfy the digit conditions + vacuously, while `0` (written "0") does not have odd digits; it is also not a meaningful + "smallest multiple". +* *The sequence.* `a n` is the least `N` with `IsDesc2 N` and `2n+1 ∣ N` if such `N` exists + (`Nat.find`), and `0` otherwise. Existence is not known to be decidable from the definition, + so `a` is noncomputable as written. +* *Data check.* `gen x L` is the little-endian digit list `[x, x+2, x+4, …] (mod 10)` of length + `L`. We prove that the numbers with `IsDesc2` are exactly the `Nat.ofDigits 10 (gen x L)` with + `x ∈ {1,3,5,7,9}`, `L ≥ 1` (`isDesc2_ofDigits_gen`, `exists_gen_of_isDesc2`). The computable + `aSearch n B` takes the least multiple of `2n+1` among these numbers with at most `B` digits; + `a_eq_of_aSearch` shows that whenever it returns `some v`, `a n = v` (any smaller element has + at most as many digits). `a_data` checks all 26 listed terms (`n = 0, …, 25`) this way, with + `B = 18` (the largest listed term has 18 digits). +* *The conjecture.* "The only numbers `n` for which `a(n) = 0` are those for which `2n+1` is + divisible by `125`" is read as the set equality `{n | a n = 0} = {n | 125 ∣ 2n+1}`: + `statement` is `∀ n, a n = 0 ↔ 125 ∣ 2 * n + 1`, over the entry's full range `n ≥ 0`. +-/ + +namespace Math0.Statements.A062887 + +/-! ### Definitions -/ + +/-- `N` is positive, its decimal digits are odd, and (reading from left to right) each digit is +two less (mod 10) than the previous digit. -/ +def IsDesc2 (N : ℕ) : Prop := + 0 < N ∧ (∀ d ∈ Nat.digits 10 N, Odd d) ∧ + (Nat.digits 10 N).reverse.IsChain (fun prev next => next + 2 ≡ prev [MOD 10]) + +instance : DecidablePred IsDesc2 := fun N => by unfold IsDesc2; infer_instance + +open Classical in +/-- A062887: the smallest multiple of `2n+1` whose digits are odd and each digit is two less +(mod 10) than the previous digit, or `0` if no such number exists (offset `0`). -/ +noncomputable def a (n : ℕ) : ℕ := + if h : ∃ N, IsDesc2 N ∧ 2 * n + 1 ∣ N then Nat.find h else 0 + +/-! ### Computable description of the numbers with the digit property -/ + +/-- The little-endian digit list `[x, x+2, x+4, …]` (mod 10) of length `L`. -/ +def gen : ℕ → ℕ → List ℕ + | _, 0 => [] + | x, L + 1 => x :: gen ((x + 2) % 10) L + +theorem length_gen (x L : ℕ) : (gen x L).length = L := by + induction L generalizing x with + | zero => rfl + | succ L ih => simp [gen, ih] + +theorem gen_lt (x L : ℕ) (hx : x < 10) : ∀ d ∈ gen x L, d < 10 := by + induction L generalizing x with + | zero => simp [gen] + | succ L ih => + intro d hd + simp only [gen, List.mem_cons] at hd + rcases hd with rfl | hd + · exact hx + · exact ih _ (Nat.mod_lt _ (by norm_num)) d hd + +theorem gen_odd (x L : ℕ) (hx : Odd x) : ∀ d ∈ gen x L, Odd d := by + induction L generalizing x with + | zero => simp [gen] + | succ L ih => + intro d hd + simp only [gen, List.mem_cons] at hd + rcases hd with rfl | hd + · exact hx + · refine ih _ ?_ d hd + rw [Nat.odd_iff] at hx ⊢ + omega + +theorem gen_chain (x L : ℕ) : + (gen x L).IsChain (fun p q => p + 2 ≡ q [MOD 10]) := by + induction L generalizing x with + | zero => simp [gen] + | succ L ih => + cases L with + | zero => simp [gen] + | succ L => + simp only [gen] at ih ⊢ + rw [List.isChain_cons_cons] + exact ⟨(Nat.mod_modEq _ _).symm, ih _⟩ + +theorem gen_of_chain : ∀ (l : List ℕ) (x : ℕ), (∀ d ∈ x :: l, d < 10) → + (x :: l).IsChain (fun p q => p + 2 ≡ q [MOD 10]) → x :: l = gen x (l.length + 1) + | [], x, _, _ => rfl + | y :: l, x, hlt, hc => by + rw [List.isChain_cons_cons] at hc + have hy : y = (x + 2) % 10 := by + have h1 : (x + 2) % 10 = y % 10 := hc.1 + have h2 : y < 10 := hlt y (by simp) + rw [Nat.mod_eq_of_lt h2] at h1 + exact h1.symm + have ih := gen_of_chain l y (fun d hd => hlt d (List.mem_cons_of_mem _ hd)) hc.2 + subst hy + rw [List.length_cons, gen, ← ih] + +theorem digits_ofDigits_gen (x L : ℕ) (hx : x < 10) (hodd : Odd x) : + Nat.digits 10 (Nat.ofDigits 10 (gen x L)) = gen x L := by + apply Nat.digits_ofDigits 10 (by norm_num) _ (gen_lt x L hx) + intro h hz + have := gen_odd x L hodd _ (List.getLast_mem h) + rw [hz] at this + exact absurd this (by decide) + +/-- Every `Nat.ofDigits 10 (gen x L)` with `x` an odd digit and `L ≥ 1` has the digit +property. -/ +theorem isDesc2_ofDigits_gen (x L : ℕ) (hx : x < 10) (hodd : Odd x) (hL : 1 ≤ L) : + IsDesc2 (Nat.ofDigits 10 (gen x L)) := by + refine ⟨?_, ?_, ?_⟩ + · obtain ⟨L, rfl⟩ : ∃ L', L = L' + 1 := ⟨L - 1, by omega⟩ + have : 1 ≤ x := by rw [Nat.odd_iff] at hodd; omega + simp only [gen, Nat.ofDigits_cons] + omega + · rw [digits_ofDigits_gen x L hx hodd] + exact gen_odd x L hodd + · rw [digits_ofDigits_gen x L hx hodd, List.isChain_reverse] + exact gen_chain x L + +/-- Every number with the digit property is `Nat.ofDigits 10 (gen x L)` with `x` an odd digit, +where `L ≥ 1` is its number of digits. -/ +theorem exists_gen_of_isDesc2 {N : ℕ} (h : IsDesc2 N) : + ∃ x L, x < 10 ∧ Odd x ∧ 1 ≤ L ∧ Nat.digits 10 N = gen x L := by + obtain ⟨hpos, hodd, hc⟩ := h + rw [List.isChain_reverse] at hc + have hlt : ∀ d ∈ Nat.digits 10 N, d < 10 := fun d hd => Nat.digits_lt_base (by norm_num) hd + cases hds : Nat.digits 10 N with + | nil => exact absurd hds (Nat.digits_ne_nil_iff_ne_zero.2 (by omega)) + | cons x l => + rw [hds] at hc hlt hodd + refine ⟨x, l.length + 1, hlt x (by simp), hodd x (by simp), by omega, ?_⟩ + exact gen_of_chain l x hlt hc + +/-- All numbers with the digit property and at most `B` digits. -/ +def cands (B : ℕ) : List ℕ := + (List.range B).flatMap fun L => [1, 3, 5, 7, 9].map fun x => Nat.ofDigits 10 (gen x (L + 1)) + +/-- The least multiple of `2n+1` among the numbers with the digit property and at most `B` +digits, if there is one. -/ +def aSearch (n B : ℕ) : Option ℕ := + ((cands B).filter fun c => c % (2 * n + 1) == 0).min? + +theorem mem_cands {B c : ℕ} : + c ∈ cands B ↔ ∃ L < B, ∃ x ∈ [1, 3, 5, 7, 9], Nat.ofDigits 10 (gen x (L + 1)) = c := by + simp only [cands, List.mem_flatMap, List.mem_range, List.mem_map] + +theorem a_eq_of_aSearch {n B v : ℕ} (h : aSearch n B = some v) : a n = v := by + rw [aSearch, List.min?_eq_some_iff] at h + obtain ⟨hv, hmin⟩ := h + rw [List.mem_filter, mem_cands] at hv + obtain ⟨⟨L, hL, x, hx, rfl⟩, hdvd⟩ := hv + have hx' : x < 10 ∧ Odd x := by + simp only [List.mem_cons, List.not_mem_nil, or_false] at hx + rcases hx with rfl | rfl | rfl | rfl | rfl <;> decide + have hdvd' : 2 * n + 1 ∣ Nat.ofDigits 10 (gen x (L + 1)) := + Nat.dvd_of_mod_eq_zero (by simpa using hdvd) + have hex : ∃ N, IsDesc2 N ∧ 2 * n + 1 ∣ N := + ⟨_, isDesc2_ofDigits_gen x (L + 1) hx'.1 hx'.2 (by omega), hdvd'⟩ + rw [a, dif_pos hex, Nat.find_eq_iff] + refine ⟨⟨isDesc2_ofDigits_gen x (L + 1) hx'.1 hx'.2 (by omega), hdvd'⟩, ?_⟩ + rintro k hk ⟨hkD, hkdvd⟩ + obtain ⟨y, M, hy, hyodd, hM, hdk⟩ := exists_gen_of_isDesc2 hkD + have hlen : M ≤ L + 1 := by + have := Nat.le_length_digits_le 10 k _ hk.le + rw [hdk, digits_ofDigits_gen x (L + 1) hx'.1 hx'.2, length_gen, length_gen] at this + exact this + have hkeq : Nat.ofDigits 10 (gen y M) = k := by rw [← hdk, Nat.ofDigits_digits] + have hy' : y ∈ [1, 3, 5, 7, 9] := by + have : ∀ y < 10, Odd y → y ∈ [1, 3, 5, 7, 9] := by decide + exact this y hy hyodd + have hkmem : k ∈ (cands B).filter fun c => c % (2 * n + 1) == 0 := by + rw [List.mem_filter, mem_cands] + refine ⟨⟨M - 1, by omega, y, hy', ?_⟩, ?_⟩ + · rw [Nat.sub_add_cancel hM, hkeq] + · simpa using Nat.mod_eq_zero_of_dvd hkdvd + have := hmin k hkmem + omega + +theorem map_a_eq_of_aSearch {B : ℕ} : + ∀ {l D : List ℕ}, l.map (fun i => aSearch i B) = D.map some → l.map a = D + | [], [], _ => rfl + | [], _ :: _, h => by simp at h + | _ :: _, [], h => by simp at h + | i :: l, d :: D, h => by + simp only [List.map_cons, List.cons.injEq] at h ⊢ + exact ⟨a_eq_of_aSearch h.1, map_a_eq_of_aSearch h.2⟩ + +/-- The entry's example: `975 = 13 · 75` has the digit property. -/ +theorem example_975 : IsDesc2 975 ∧ 13 ∣ 975 := by + refine ⟨?_, by norm_num⟩ + have := isDesc2_ofDigits_gen 5 3 (by norm_num) (by decide) (by norm_num) + simpa [gen, Nat.ofDigits] using this + +/-- The definition reproduces all 26 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 26).map (fun i => a (i + 0)) = + [1, 3, 5, 7, 9, 319, 975, 75, 7531, 19, 197531975319, 3197, 75, 5319, 319, 31, + 3197531975319, 53197531975, 1975319, 975, 531975, 1975319753197, 19753197531975, + 75319753197531, 319753197531975319, 753197531975319753] := by + simp only [Nat.add_zero] + exact map_a_eq_of_aSearch (B := 18) (by decide +kernel) + +/-! ### The conjecture -/ + +/-- Conjecture (Irvine, A062887): `a(n) = 0` exactly for those `n` with `125 ∣ 2n+1`. -/ +def statement : Prop := ∀ n : ℕ, a n = 0 ↔ 125 ∣ 2 * n + 1 + +end Math0.Statements.A062887 diff --git a/lean/Math0/Statements/OEIS/A071685.lean b/lean/Math0/Statements/OEIS/A071685.lean new file mode 100644 index 0000000..237c94a --- /dev/null +++ b/lean/Math0/Statements/OEIS/A071685.lean @@ -0,0 +1,482 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A071685: reverse-divisor numbers are `1`, `12`, `78` or `89` mod `100` + +Source: https://oeis.org/A071685, Harvey P. Dale, Dec 13 2017 (COMMENTS section). Verbatim: +> Conjecture: every term mod 100 is equal to 1, 12, 78, or 89. + +The entry's name (Labos Elemer, Jun 03 2002): "Non-palindromic numbers n, not divisible by 10, +such that either n divides R(n) or R(n) divides n, where R(n) is the digit-reversal of n." +Offset `1`; the listed data start `1089, 2178, 8712, 9801, 10989, 21978, 87912, 98901, …`. + +## Encoding + +* `R n` is the decimal digit reversal of A004086 ("Read n backwards"; "Leading zeros (after the + reversal has taken place) are omitted"): the base-`10` digits of `n` are reversed and read + again as a number, `R n = Nat.ofDigits 10 (Nat.digits 10 n).reverse`. So `R 1089 = 9801`, + `R 120 = 21`, `R 0 = 0`. +* Palindromes are encoded via the comment in A002113 (Palindromes in base 10): "n is a + palindrome … if and only if n = A004086(n)". So "non-palindromic" is `R n ≠ n`. +* `IsTerm n`: `R n ≠ n`, `¬ 10 ∣ n`, and `n ∣ R n ∨ R n ∣ n`. (`n = 0` is excluded since + `10 ∣ 0`.) This predicate is decidable. +* The sequence `a n = Nat.nth IsTerm (n - 1)` (offset `1`) lists the terms in increasing order. + `Nat.nth` is noncomputable, so `a` is noncomputable. `a_data` checks the first `16` listed + terms `a 1, …, a 16`, i.e. all listed terms below `10^7`. It rests on `term_iff`: below + `10^7` the terms are exactly these `16` numbers. That is proved by kernel scans + (`decide +kernel`) over kernel-friendly helpers proved sound for the definitions. To make the + scan feasible, a few elementary facts about leading and last digits are proved here and used + only for the data check: with `A` the leading digit and `B` the last digit of a term `n` + (at least two digits), the quotient `k` (`R n = k n` or `n = k R n`) satisfies `k ≠ 1` and + `k·A ≤ B` with `k·B ≡ A (mod 10)` (or the same with `A`, `B` swapped). That leaves + `(A, B) ∈ {(2,6), (1,7), (2,8), (1,9), (6,2), (7,1), (8,2), (9,1)}`, and since + `R n ≡ n (mod 9)` it also gives `9 ∣ n` (or `3 ∣ n` when `k = 4`). +* The conjecture: every term `n` of the sequence satisfies `n % 100 ∈ {1, 12, 78, 89}`. It is + stated for every `n` with `IsTerm n`, i.e. for every term of the sequence. This does not + depend on whether the sequence is infinite. The entry says there are `4·Fibonacci(⌊(d-2)/2⌋)` + terms with `d` digits, so the sequence is infinite; the statement is then the same as + `∀ i ≥ 1, a i % 100 ∈ {1, 12, 78, 89}`. +-/ + +namespace Math0.Statements.A071685 + +/-- `R n`: the decimal digit reversal of `n` (A004086); leading zeros after the reversal are +omitted. -/ +def R (n : ℕ) : ℕ := Nat.ofDigits 10 (Nat.digits 10 n).reverse + +/-- `n` is a term of A071685: `n` is non-palindromic (`R n ≠ n`, cf. A002113), not divisible by +`10`, and either `n` divides `R n` or `R n` divides `n`. -/ +def IsTerm (n : ℕ) : Prop := R n ≠ n ∧ ¬ 10 ∣ n ∧ (n ∣ R n ∨ R n ∣ n) + +instance : DecidablePred IsTerm := fun n => by unfold IsTerm; infer_instance + +/-- A071685 (offset `1`): the `n`-th non-palindromic number, not divisible by `10`, that +divides or is divided by its digit reversal. -/ +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) + +/-- The digit reversals in the entry's examples: `R 1089 = 9801 = 9 · 1089`, +`R 8712 = 2178 = 8712 / 4`, `R 12021 = 12021` (a palindrome), and `R 8380 = 838`; also +`R 120 = 21` and `R 0 = 0`. -/ +theorem R_examples : R 1089 = 9801 ∧ R 8712 = 2178 ∧ R 12021 = 12021 ∧ R 8380 = 838 ∧ + R 120 = 21 ∧ R 0 = 0 := by + norm_num [R, Nat.ofDigits_cons, Nat.ofDigits_nil] + +/-! ### Digit-reversal facts (used only for the data check) -/ + +theorem R_cons {n : ℕ} (hn : 0 < n) : + R n = R (n / 10) + 10 ^ (Nat.digits 10 (n / 10)).length * (n % 10) := by + unfold R + rw [Nat.digits_def' (by norm_num) hn, List.reverse_cons, Nat.ofDigits_append, + List.length_reverse, Nat.ofDigits_singleton] + +theorem len_cons {n : ℕ} (hn : 0 < n) : + (Nat.digits 10 n).length = (Nat.digits 10 (n / 10)).length + 1 := by + rw [Nat.digits_def' (by norm_num) hn, List.length_cons] + +theorem R_lt (n : ℕ) : R n < 10 ^ (Nat.digits 10 n).length := by + have h := Nat.ofDigits_lt_base_pow_length (b := 10) (l := (Nat.digits 10 n).reverse) + (by norm_num) (fun x hx => Nat.digits_lt_base (by norm_num) (List.mem_reverse.1 hx)) + rwa [List.length_reverse] at h + +/-- With `d` digits, `10^(d-1) ≤ n < 10 · 10^(d-1)`. -/ +theorem lead_bounds {n : ℕ} (hn : 0 < n) : + 10 ^ ((Nat.digits 10 n).length - 1) ≤ n ∧ n < 10 * 10 ^ ((Nat.digits 10 n).length - 1) := by + have h1 := Nat.base_pow_length_digits_le 10 n (by norm_num) hn.ne' + have h2 := Nat.lt_base_pow_length_digits (b := 10) (m := n) (by norm_num) + rw [len_cons hn, pow_succ] at h1 h2 + rw [len_cons hn, Nat.add_sub_cancel] + constructor <;> omega + +/-- The leading digit of `R n` is the last digit of `n`. -/ +theorem R_div {n : ℕ} (hn : 0 < n) : + R n / 10 ^ ((Nat.digits 10 n).length - 1) = n % 10 := by + rw [len_cons hn, Nat.add_sub_cancel, R_cons hn, + Nat.add_mul_div_left _ _ (by positivity), Nat.div_eq_of_lt (R_lt _), zero_add] + +theorem digits_R {n : ℕ} (h : n % 10 ≠ 0) : + Nat.digits 10 (R n) = (Nat.digits 10 n).reverse := by + have hn : 0 < n := Nat.pos_of_ne_zero (by rintro rfl; exact h rfl) + unfold R + apply Nat.digits_ofDigits 10 (by norm_num) + · intro x hx + exact Nat.digits_lt_base (by norm_num) (List.mem_reverse.1 hx) + · intro hne + rw [List.getLast_reverse] + have key : ∀ (l : List ℕ) (hl : l ≠ []), l = n % 10 :: Nat.digits 10 (n / 10) → + l.head hl ≠ 0 := by + rintro l hl rfl + exact h + exact key _ _ (Nat.digits_def' (by norm_num) hn) + +theorem R_R {n : ℕ} (h : n % 10 ≠ 0) : R (R n) = n := by + show Nat.ofDigits 10 (Nat.digits 10 (R n)).reverse = n + rw [digits_R h, List.reverse_reverse, Nat.ofDigits_digits] + +theorem len_R {n : ℕ} (h : n % 10 ≠ 0) : + (Nat.digits 10 (R n)).length = (Nat.digits 10 n).length := by + rw [digits_R h, List.length_reverse] + +/-- The last digit of `R n` is the leading digit of `n` (when `n` does not end in `0`). -/ +theorem R_mod {n : ℕ} (h : n % 10 ≠ 0) : + R n % 10 = n / 10 ^ ((Nat.digits 10 n).length - 1) := by + have hn : 0 < n := Nat.pos_of_ne_zero (by rintro rfl; exact h rfl) + have hR : 0 < R n := by + have := R_div hn + rcases Nat.eq_zero_or_pos (R n) with h0 | h0 + · rw [h0, Nat.zero_div] at this + exact absurd this.symm h + · exact h0 + have := R_div hR + rw [R_R h, len_R h] at this + exact this.symm + +theorem R_mod_nine (n : ℕ) : R n % 9 = n % 9 := by + have h1 : R n % 9 = (Nat.digits 10 n).sum % 9 := by + unfold R + rw [Nat.ofDigits_mod, show 10 % 9 = 1 from rfl, Nat.ofDigits_one, List.sum_reverse] + rw [h1] + exact (Nat.modEq_nine_digits_sum n).symm + +/-- `R n = k n` with leading digit `A`, last digit `B`. -/ +theorem fwd_cases : ∀ k < 10, ∀ A < 10, ∀ B < 10, 1 ≤ A → k ≠ 1 → k * A ≤ B → B * k % 10 = A → + (k = 2 ∧ A = 2 ∧ B = 6) ∨ (k = 3 ∧ A = 1 ∧ B = 7) ∨ (k = 4 ∧ A = 2 ∧ B = 8) ∨ + (k = 9 ∧ A = 1 ∧ B = 9) := by + intro k hk A hA B hB + interval_cases k <;> interval_cases A <;> omega + +/-- `n = k R n` with leading digit `A`, last digit `B`. -/ +theorem bwd_cases : ∀ k < 10, ∀ A < 10, ∀ B < 10, 1 ≤ B → k ≠ 1 → k * B ≤ A → A * k % 10 = B → + (k = 2 ∧ A = 6 ∧ B = 2) ∨ (k = 3 ∧ A = 7 ∧ B = 1) ∨ (k = 4 ∧ A = 8 ∧ B = 2) ∨ + (k = 9 ∧ A = 9 ∧ B = 1) := by + intro k hk A hA B hB + interval_cases k <;> interval_cases B <;> omega + +/-- The possible (leading digit, last digit, modulus `m` with `m ∣ n`) of a term. -/ +def tri : List (ℕ × ℕ × ℕ) := + [(2, 6, 9), (1, 7, 9), (2, 8, 3), (1, 9, 9), (6, 2, 9), (7, 1, 9), (8, 2, 3), (9, 1, 9)] + +theorem tri_of_term {n : ℕ} (h : IsTerm n) : + ∃ m, (n / 10 ^ ((Nat.digits 10 n).length - 1), n % 10, m) ∈ tri ∧ n % m = 0 := by + obtain ⟨hpal, h10, hdiv⟩ := h + have hB0 : n % 10 ≠ 0 := fun e => h10 (Nat.dvd_of_mod_eq_zero e) + have hn : 0 < n := Nat.pos_of_ne_zero (by rintro rfl; exact hB0 rfl) + have hlb := lead_bounds hn + have hRd := R_div hn + have hRm := R_mod hB0 + have hR9 := R_mod_nine n + have hP0 : 0 < 10 ^ ((Nat.digits 10 n).length - 1) := by positivity + generalize 10 ^ ((Nat.digits 10 n).length - 1) = P at hlb hRd hRm hP0 ⊢ + have hA1 : 1 ≤ n / P := (Nat.le_div_iff_mul_le hP0).2 (by omega) + have hA9 : n / P < 10 := (Nat.div_lt_iff_lt_mul hP0).2 (by omega) + have hB9 : n % 10 < 10 := Nat.mod_lt _ (by norm_num) + have hB1 : 1 ≤ n % 10 := by omega + have hRlt : R n < (n % 10 + 1) * P := (Nat.div_lt_iff_lt_mul hP0).1 (by omega) + have hRge : n % 10 * P ≤ R n := by rw [← hRd]; exact Nat.div_mul_le_self (R n) P + have hAP : n / P * P ≤ n := Nat.div_mul_le_self n P + have hnlt : n < (n / P + 1) * P := (Nat.div_lt_iff_lt_mul hP0).1 (Nat.lt_succ_self _) + rcases hdiv with ⟨k, hk⟩ | ⟨k, hk⟩ + · -- `R n = n * k` + have hk1 : k ≠ 1 := by + rintro rfl + exact hpal (by rw [hk, mul_one]) + have hkA : k * (n / P) ≤ n % 10 := by + have h1 : k * (n / P) * P < (n % 10 + 1) * P := + calc k * (n / P) * P = k * (n / P * P) := by ring + _ ≤ k * n := Nat.mul_le_mul_left _ hAP + _ = R n := by rw [hk, mul_comm] + _ < _ := hRlt + have := Nat.lt_of_mul_lt_mul_right h1 + omega + have hmod : n % 10 * k % 10 = n / P := by + rw [← hRm, hk, Nat.mul_mod n k 10, Nat.mul_mod (n % 10) k 10, Nat.mod_mod] + have hk10 : k < 10 := by + have : k ≤ k * (n / P) := Nat.le_mul_of_pos_right k hA1 + omega + rw [hk] at hR9 + rcases fwd_cases k hk10 (n / P) hA9 (n % 10) hB9 hA1 hk1 hkA hmod with + ⟨rfl, hA, hB⟩ | ⟨rfl, hA, hB⟩ | ⟨rfl, hA, hB⟩ | ⟨rfl, hA, hB⟩ + · exact ⟨9, by rw [hA, hB]; decide, by omega⟩ + · exact ⟨9, by rw [hA, hB]; decide, by omega⟩ + · exact ⟨3, by rw [hA, hB]; decide, by omega⟩ + · exact ⟨9, by rw [hA, hB]; decide, by omega⟩ + · -- `n = R n * k` + have hk1 : k ≠ 1 := by + rintro rfl + exact hpal (by rw [mul_one] at hk; exact hk.symm) + have hkB : k * (n % 10) ≤ n / P := by + have h1 : k * (n % 10) * P < (n / P + 1) * P := + calc k * (n % 10) * P = k * (n % 10 * P) := by ring + _ ≤ k * R n := Nat.mul_le_mul_left _ hRge + _ = n := by rw [mul_comm]; exact hk.symm + _ < _ := hnlt + have := Nat.lt_of_mul_lt_mul_right h1 + omega + have hmod : n / P * k % 10 = n % 10 := by + have e : n % 10 = R n * k % 10 := congrArg (· % 10) hk + rw [e, ← hRm, Nat.mul_mod (R n) k 10, Nat.mul_mod (R n % 10) k 10, Nat.mod_mod] + have hk10 : k < 10 := by + have : k ≤ k * (n % 10) := Nat.le_mul_of_pos_right k hB1 + omega + rcases bwd_cases k hk10 (n / P) hA9 (n % 10) hB9 hB1 hk1 hkB hmod with + ⟨rfl, hA, hB⟩ | ⟨rfl, hA, hB⟩ | ⟨rfl, hA, hB⟩ | ⟨rfl, hA, hB⟩ + · exact ⟨9, by rw [hA, hB]; decide, by omega⟩ + · exact ⟨9, by rw [hA, hB]; decide, by omega⟩ + · exact ⟨3, by rw [hA, hB]; decide, by omega⟩ + · exact ⟨9, by rw [hA, hB]; decide, by omega⟩ + +/-- A number `n` with `n / P = A`, `n % 10 = B` and `m ∣ n` (`m ∈ {3, 9}`, `P = 10^e`, `e ≥ 1`) +lies on the arithmetic progression scanned for `(A, B, m)` at scale `P`. -/ +theorem cover {n P A B m : ℕ} (hP0 : 0 < P) (hP9 : P % 9 = 1) (hP10 : P % 10 = 0) + (hm : m = 3 ∨ m = 9) (hA : n / P = A) (hB : n % 10 = B) (hnm : n % m = 0) : + ∃ t < P / 10 / m + 1, n = A * P + B + 10 * ((m - (A + B) % m) % m) + 10 * m * t := by + have e1 : A * P + n % P = n := by rw [← hA, mul_comm]; exact Nat.div_add_mod n P + have e2 : n % P % 10 = n % 10 := Nat.mod_mod_of_dvd n (Nat.dvd_of_mod_eq_zero hP10) + have e3 := Nat.mod_lt n hP0 + have e4 : A * P % 9 = A % 9 := by rw [Nat.mul_mod, hP9, mul_one, Nat.mod_mod] + generalize n % P = r at e1 e2 e3 + generalize A * P = X at e1 e4 ⊢ + rcases hm with rfl | rfl + · exact ⟨r / 10 / 3, by omega, by omega⟩ + · exact ⟨r / 10 / 9, by omega, by omega⟩ + +/-! ### Kernel-friendly evaluation (used only for the data check) + +The functions below are written with the recursors `Nat.rec`, `Bool.rec` and the primitive +operations `Nat.add`, `Nat.mul`, `Nat.div`, `Nat.mod`, `Nat.beq`, which the kernel evaluates +directly on numerals. Each one is proved equal to (or sound for) the definitions above. -/ + +/-- `x && y`, written with the recursor. -/ +def andK (x y : Bool) : Bool := Bool.rec (motive := fun _ => Bool) false y x + +/-- `x || y`, written with the recursor. -/ +def orK (x y : Bool) : Bool := Bool.rec (motive := fun _ => Bool) y true x + +/-- `!x`, written with the recursor. -/ +def notK (x : Bool) : Bool := Bool.rec (motive := fun _ => Bool) true false x + +theorem andK_eq (x y : Bool) : andK x y = (x && y) := by cases x <;> rfl + +theorem orK_eq (x y : Bool) : orK x y = (x || y) := by cases x <;> rfl + +theorem notK_eq (x : Bool) : notK x = !x := by cases x <;> rfl + +theorem beq_eq_decide (x y : ℕ) : Nat.beq x y = decide (x = y) := by + rw [Bool.eq_iff_iff, Nat.beq_eq, decide_eq_true_iff] + +/-- `revK fuel n acc = acc · 10^(number of digits of n) + R n` when `n < 10^fuel`. -/ +def revK (fuel : ℕ) : ℕ → ℕ → ℕ := + Nat.rec (motive := fun _ => ℕ → ℕ → ℕ) (fun _ acc => acc) + (fun _ ih n acc => Bool.rec (motive := fun _ => ℕ) + (ih (Nat.div n 10) (Nat.add (Nat.mul acc 10) (Nat.mod n 10))) acc (Nat.beq n 0)) + fuel + +theorem revK_eq : ∀ fuel n acc, n < 10 ^ fuel → + revK fuel n acc = acc * 10 ^ (Nat.digits 10 n).length + R n := by + intro fuel + induction fuel with + | zero => + intro n acc hn + obtain rfl : n = 0 := by simpa using hn + simp [revK, R] + | succ fuel ih => + intro n acc hn + rcases Nat.eq_zero_or_pos n with rfl | hpos + · simp [revK, R] + · have hb : Nat.beq n 0 = false := by + rw [beq_eq_decide, decide_eq_false_iff_not] + omega + have e : revK (fuel + 1) n acc = revK fuel (n / 10) (acc * 10 + n % 10) := by + show Bool.rec (motive := fun _ => ℕ) + (revK fuel (Nat.div n 10) (Nat.add (Nat.mul acc 10) (Nat.mod n 10))) acc + (Nat.beq n 0) = _ + rw [hb] + rfl + rw [e, ih (n / 10) _ (by rw [pow_succ] at hn; omega), R_cons hpos, len_cons hpos, + pow_succ] + ring + +/-- `IsTerm n`, given `r = R n` (without the last-digit test). -/ +def termR (n r : ℕ) : Bool := + andK (notK (Nat.beq r n)) (orK (Nat.beq (Nat.mod r n) 0) (Nat.beq (Nat.mod n r) 0)) + +/-- `IsTerm n`, kernel-friendly (correct for `n < 10^8`, see `termK_iff`). -/ +def termK (n : ℕ) : Bool := andK (notK (Nat.beq (Nat.mod n 10) 0)) (termR n (revK 8 n 0)) + +theorem termK_iff {n : ℕ} (hn : n < 10 ^ 8) : termK n = true ↔ IsTerm n := by + have hr : revK 8 n 0 = R n := by rw [revK_eq 8 n 0 hn]; simp + have e : termK n = (!decide (n % 10 = 0) && + (!decide (R n = n) && (decide (R n % n = 0) || decide (n % R n = 0)))) := by + show andK (notK (Nat.beq (n % 10) 0)) (andK (notK (Nat.beq (revK 8 n 0) n)) + (orK (Nat.beq (revK 8 n 0 % n) 0) (Nat.beq (n % revK 8 n 0) 0))) = _ + simp only [hr, andK_eq, orK_eq, notK_eq, beq_eq_decide] + rw [e] + simp only [IsTerm, Bool.and_eq_true, Bool.not_eq_true', decide_eq_false_iff_not, + Bool.or_eq_true, decide_eq_true_eq, Nat.dvd_iff_mod_eq_zero] + tauto + +/-! ### Scanning -/ + +/-- The terms listed in OEIS below `10^7`. -/ +def listed : List ℕ := + [1089, 2178, 8712, 9801, 10989, 21978, 87912, 98901, 109989, 219978, 879912, 989901, + 1099989, 2199978, 8799912, 9899901] + +/-- `check q = true` iff (`q` is a term `→ q ∈ listed`), for `q < 10^8`. -/ +def check (q : ℕ) : Bool := orK (notK (termK q)) (decide (q ∈ listed)) + +theorem check_sound {q : ℕ} (h : check q = true) (hq : IsTerm q) (hlt : q < 10 ^ 8) : + q ∈ listed := by + rw [check, orK_eq, notK_eq, (termK_iff hlt).2 hq] at h + simpa using h + +/-- `scanLoop base step cnt = true` iff `check (base + step · t)` for every `t < cnt`. -/ +def scanLoop (base step : ℕ) (cnt : ℕ) : Bool := + Nat.rec (motive := fun _ => Bool) true + (fun t ih => andK (check (Nat.add base (Nat.mul step t))) ih) cnt + +theorem scanLoop_sound (base step : ℕ) : ∀ cnt, scanLoop base step cnt = true → + ∀ t < cnt, check (base + step * t) = true := by + intro cnt + induction cnt with + | zero => intro _ t ht; omega + | succ cnt ih => + intro h t ht + have h' : andK (check (base + step * cnt)) (scanLoop base step cnt) = true := h + rw [andK_eq, Bool.and_eq_true] at h' + rcases Nat.lt_succ_iff_lt_or_eq.1 ht with ht | ht + · exact ih h'.2 t ht + · subst ht + exact h'.1 + +/-- For `x = (A, B, m) ∈ tri`, scan the numbers `n ≡ B (mod 10)` with `m ∣ n` and +`A · P ≤ n < (A + 1) · P` (and a few more). -/ +def scanAB (P : ℕ) (x : ℕ × ℕ × ℕ) : Bool := + scanLoop (x.1 * P + x.2.1 + 10 * ((x.2.2 - (x.1 + x.2.1) % x.2.2) % x.2.2)) (10 * x.2.2) + (P / 10 / x.2.2 + 1) + +/-- All the scans at scale `P`. -/ +def scanP (P : ℕ) : Bool := tri.all (scanAB P) + +theorem scanP_sound {P A B m : ℕ} (h : scanP P = true) (hx : (A, B, m) ∈ tri) : + ∀ t < P / 10 / m + 1, + check (A * P + B + 10 * ((m - (A + B) % m) % m) + 10 * m * t) = true := by + have h1 : scanAB P (A, B, m) = true := List.all_eq_true.1 h _ hx + exact scanLoop_sound _ _ _ h1 + +/-- `checkAll s len = true` iff `check q` for every `q ∈ [s, s + len)`. -/ +def checkAll (s : ℕ) (len : ℕ) : Bool := + Nat.rec (motive := fun _ => Bool) true (fun k ih => andK (check (Nat.add s k)) ih) len + +theorem checkAll_sound (s : ℕ) : ∀ len, checkAll s len = true → + ∀ k < len, check (s + k) = true := by + intro len + induction len with + | zero => intro _ k hk; omega + | succ len ih => + intro h k hk + have h' : andK (check (s + len)) (checkAll s len) = true := h + rw [andK_eq, Bool.and_eq_true] at h' + rcases Nat.lt_succ_iff_lt_or_eq.1 hk with hk | hk + · exact ih h'.2 k hk + · subst hk + exact h'.1 + +/-- All `q < 1000`. -/ +theorem scan_small : checkAll 0 1000 = true := by decide +kernel + +/-- `4`-digit candidates. -/ +theorem scan_four : scanP 1000 = true := by decide +kernel + +/-- `5`-digit candidates. -/ +theorem scan_five : scanP 10000 = true := by decide +kernel + +/-- `6`-digit candidates. -/ +theorem scan_six : scanP 100000 = true := by decide +kernel + +/-- `7`-digit candidates. -/ +theorem scan_seven : scanP 1000000 = true := by decide +kernel + +theorem mem_of_scan {n P m : ℕ} (hscan : scanP P = true) (hP0 : 0 < P) (hP9 : P % 9 = 1) + (hP10 : P % 10 = 0) (hmem : (n / P, n % 10, m) ∈ tri) (hm : n % m = 0) (hT : IsTerm n) + (hn : n < 10 ^ 8) : n ∈ listed := by + have htri : ∀ x ∈ tri, x.2.2 = 3 ∨ x.2.2 = 9 := by decide + have hm' : m = 3 ∨ m = 9 := htri _ hmem + obtain ⟨t, ht, hnt⟩ := cover hP0 hP9 hP10 hm' rfl rfl hm + have hc := scanP_sound hscan hmem t ht + rw [← hnt] at hc + exact check_sound hc hT hn + +/-- Below `10^7`, the terms are exactly the listed ones. -/ +theorem term_iff {n : ℕ} (hn : n < 10 ^ 7) : IsTerm n ↔ n ∈ listed := by + constructor + · intro hT + by_cases hs : n < 1000 + · have hc := checkAll_sound 0 1000 scan_small n hs + rw [zero_add] at hc + exact check_sound hc hT (by omega) + obtain ⟨m, hmem, hm⟩ := tri_of_term hT + have hlb := lead_bounds (by omega : 0 < n) + generalize (Nat.digits 10 n).length - 1 = e at hlb hmem + have he1 : e < 7 := by + by_contra hc + have : 10 ^ 7 ≤ 10 ^ e := Nat.pow_le_pow_right (by norm_num) (by omega) + omega + have he2 : 3 ≤ e := by + by_contra hc + have : 10 ^ e ≤ 10 ^ 2 := Nat.pow_le_pow_right (by norm_num) (by omega) + omega + interval_cases e + · exact mem_of_scan scan_four (by norm_num) (by norm_num) (by norm_num) hmem hm hT + (by omega) + · exact mem_of_scan scan_five (by norm_num) (by norm_num) (by norm_num) hmem hm hT + (by omega) + · exact mem_of_scan scan_six (by norm_num) (by norm_num) (by norm_num) hmem hm hT + (by omega) + · exact mem_of_scan scan_seven (by norm_num) (by norm_num) (by norm_num) hmem hm hT + (by omega) + · intro hq + have hall : listed.all termK = true := by decide +kernel + have hlt : ∀ x ∈ listed, x < 10 ^ 8 := by decide + rw [List.all_eq_true] at hall + exact (termK_iff (hlt n hq)).1 (hall n hq) + +theorem count_eq {n : ℕ} (hn : n ≤ 10 ^ 7) : + Nat.count IsTerm n = (listed.toFinset.filter (· < n)).card := by + rw [Nat.count_eq_card_filter_range] + congr 1 + ext q + simp only [Finset.mem_filter, Finset.mem_range, List.mem_toFinset] + constructor + · rintro ⟨h1, h2⟩ + exact ⟨(term_iff (by omega)).1 h2, h1⟩ + · rintro ⟨h1, h2⟩ + exact ⟨h2, (term_iff (by omega)).2 h1⟩ + +/-- The definition reproduces the first `16` terms listed in OEIS, `a 1, …, a 16` (all listed +terms below `10^7`; kernel-checked, see `term_iff`). -/ +theorem a_data : (List.range 16).map (fun i => a (i + 1)) = + [1089, 2178, 8712, 9801, 10989, 21978, 87912, 98901, 109989, 219978, 879912, 989901, + 1099989, 2199978, 8799912, 9899901] := by + have hcard : ∀ i < 16, (listed.toFinset.filter (· < listed.getD i 0)).card = i := by + decide +kernel + have hlt : ∀ i < 16, listed.getD i 0 < 10 ^ 7 := by decide +kernel + have hmem : ∀ i < 16, listed.getD i 0 ∈ listed := by decide +kernel + show _ = listed + apply List.ext_getElem (by simp [listed]) + intro i h1 h2 + have hi : i < 16 := by simpa using h1 + simp only [List.getElem_map, List.getElem_range, a, Nat.add_sub_cancel] + have hP : IsTerm (listed.getD i 0) := (term_iff (hlt i hi)).2 (hmem i hi) + have hc := Nat.nth_count hP + rw [count_eq (hlt i hi).le, hcard i hi] at hc + rw [hc, List.getD_eq_getElem] + +/-- Conjecture (H. P. Dale, 2017): every term `n` of A071685 (a non-palindromic number, not +divisible by `10`, with `n ∣ R n` or `R n ∣ n`) satisfies `n mod 100 ∈ {1, 12, 78, 89}`. -/ +def statement : Prop := + ∀ n : ℕ, IsTerm n → n % 100 = 1 ∨ n % 100 = 12 ∨ n % 100 = 78 ∨ n % 100 = 89 + +end Math0.Statements.A071685 diff --git a/lean/Math0/Statements/OEIS/A073642.lean b/lean/Math0/Statements/OEIS/A073642.lean new file mode 100644 index 0000000..2fe3dbd --- /dev/null +++ b/lean/Math0/Statements/OEIS/A073642.lean @@ -0,0 +1,130 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A073642: sum of the positions of the 1-bits of `n` (Yanev's identity) + +Source: https://oeis.org/A073642, Velin Yanev, Sep 09 2017 (FORMULA section). Verbatim: +> Conjecture: a(n) = (3*A011371(n) - Sum_{k=1..n} A007814(k)^2)/2 for n > 0. + +The sequence (offset `0`, Benoit Cloitre, Aug 29 2002) is "Replace 2^k in the binary +representation of n with k (i.e., if n = 2^b + 2^c + 2^d + ... then a(n) = b + c + d + ...)." +The two sequences referred to in the conjecture are +* A011371 (offset `0`): "a(n) = n minus (number of 1's in binary expansion of n). Also highest + power of 2 dividing n!."; +* A007814 (offset `1`): "Exponent of highest power of 2 dividing n, a.k.a. the binary carry + sequence, the ruler sequence, or the 2-adic valuation of n." + +## Encoding + +* `a n` is the sum of `Nat.bitIndices n`, the list of exponents `b < c < d < ⋯` with + `n = 2^b + 2^c + 2^d + ⋯` (Mathlib: `Nat.sum_map_two_pow_bitIndices`, + `Nat.mem_bitIndices`). `a_sum_two_pow` proves that `a` is exactly the OEIS definition: for + every finite set `s` of exponents, `a (∑ i ∈ s, 2 ^ i) = ∑ i ∈ s, i` (every `n` has exactly + one such representation). `a_data` checks all 88 listed terms `a 0, …, a 87`. +* `A011371 n = n - (number of 1's among the binary digits Nat.digits 2 n)` is the primary OEIS + definition of A011371; `A011371_eq_padicValNat_factorial` proves that it also equals + `padicValNat 2 n!` (the second description, Legendre's formula). `A011371_data` checks all + 73 listed terms of A011371 (`n = 0, …, 72`). +* `A007814 k = padicValNat 2 k` is the 2-adic valuation; it is only used for `k ≥ 1`, where it + is the exponent of the highest power of `2` dividing `k`. `A007814_data` checks all 111 + listed terms of A007814 (`k = 1, …, 111`). +* The conjecture is stated for every `n > 0`, as in the entry. The right-hand side is read + literally as a rational number, `(3 * A011371(n) - ∑_{k=1}^{n} A007814(k)^2) / 2` computed in + `ℚ` (so neither the subtraction nor the division is truncated, and the claim includes that + this number is the natural number `a(n)`). +* `rhs_data` is a sanity check of the encoding (not part of the statement): for `n = 1, …, 87` + the integer `3 * A011371(n) - ∑_{k=1}^{n} A007814(k)^2` equals twice the listed term `a(n)`. +-/ + +namespace Math0.Statements.A073642 + +/-- A073642: replace `2^k` in the binary representation of `n` with `k`, i.e. if +`n = 2^b + 2^c + 2^d + ⋯` (distinct exponents) then `a(n) = b + c + d + ⋯`. Here +`Nat.bitIndices n` is the increasing list of these exponents. -/ +def a (n : ℕ) : ℕ := (Nat.bitIndices n).sum + +/-- A011371: `n` minus the number of 1's in the binary expansion of `n`. -/ +def A011371 (n : ℕ) : ℕ := n - (Nat.digits 2 n).count 1 + +/-- A007814: the exponent of the highest power of `2` dividing `n` (the 2-adic valuation). -/ +def A007814 (n : ℕ) : ℕ := padicValNat 2 n + +/-! ### The definitions match the OEIS definitions -/ + +/-- The OEIS definition of A073642: if `n = ∑ i ∈ s, 2 ^ i` for a finite set `s` of exponents, +then `a(n) = ∑ i ∈ s, i`. -/ +theorem a_sum_two_pow (s : Finset ℕ) : a (∑ i ∈ s, 2 ^ i) = ∑ i ∈ s, i := by + have h := Finset.toFinset_bitIndices_sum_two_pow s + conv_rhs => rw [← h] + rw [List.sum_toFinset _ Nat.bitIndices_sorted.nodup, List.map_id'] + rfl + +/-- Binary digits are `0` or `1`, so their sum is the number of 1's. -/ +theorem count_one_digits_two (n : ℕ) : (Nat.digits 2 n).count 1 = (Nat.digits 2 n).sum := by + have h : ∀ L : List ℕ, (∀ x ∈ L, x < 2) → L.count 1 = L.sum := by + intro L + induction L with + | nil => simp + | cons x L ih => + intro hL + have hx := hL x (by simp) + rw [List.count_cons, List.sum_cons, ih (fun y hy => hL y (by simp [hy]))] + interval_cases x <;> (simp; try omega) + exact h _ (fun x hx => Nat.digits_lt_base (by norm_num) hx) + +/-- The second description of A011371: it is the exponent of the highest power of `2` +dividing `n!`. -/ +theorem A011371_eq_padicValNat_factorial (n : ℕ) : A011371 n = padicValNat 2 n.factorial := by + have h := sub_one_mul_padicValNat_factorial (p := 2) n + rw [show (2 - 1) = 1 from rfl, one_mul] at h + rw [A011371, count_one_digits_two, h] + +/-! ### Data checks -/ + +/-- The definition reproduces all 88 terms listed in OEIS, `a 0, …, a 87` (kernel-checked). -/ +theorem a_data : (List.range 88).map (fun i => a (i + 0)) = + [0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, + 10, 10, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 9, 9, 10, 10, 11, 11, 12, 12, + 12, 12, 13, 13, 14, 14, 15, 15, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10, 11, 11, 12, 12, 10, + 10, 11, 11, 12, 12, 13, 13] := by + decide +kernel + +/-- `A011371` reproduces all 73 terms listed in OEIS A011371, `n = 0, …, 72` (kernel-checked). -/ +theorem A011371_data : (List.range 73).map (fun i => A011371 (i + 0)) = + [0, 0, 1, 1, 3, 3, 4, 4, 7, 7, 8, 8, 10, 10, 11, 11, 15, 15, 16, 16, 18, 18, 19, 19, 22, 22, + 23, 23, 25, 25, 26, 26, 31, 31, 32, 32, 34, 34, 35, 35, 38, 38, 39, 39, 41, 41, 42, 42, 46, + 46, 47, 47, 49, 49, 50, 50, 53, 53, 54, 54, 56, 56, 57, 57, 63, 63, 64, 64, 66, 66, 67, 67, + 70] := by + decide +kernel + +/-- `A007814` reproduces all 111 terms listed in OEIS A007814, `k = 1, …, 111` +(kernel-checked). -/ +theorem A007814_data : (List.range 111).map (fun i => A007814 (i + 1)) = + [0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, + 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, + 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0] := by + decide +kernel + +/-- Sanity check of the encoding of the right-hand side: for `n = 1, …, 87`, the integer +`3 * A011371(n) - ∑_{k=1}^{n} A007814(k)^2` is twice the listed term `a(n)` (kernel-checked). -/ +theorem rhs_data : (List.range 87).map (fun i => + 3 * (A011371 (i + 1) : ℤ) - ∑ k ∈ Finset.Icc 1 (i + 1), (A007814 k : ℤ) ^ 2) = + ([0, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 9, 9, + 10, 10, 5, 5, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 10, 10, 11, 11, 9, 9, 10, 10, 11, 11, 12, 12, + 12, 12, 13, 13, 14, 14, 15, 15, 6, 6, 7, 7, 8, 8, 9, 9, 9, 9, 10, 10, 11, 11, 12, 12, 10, + 10, 11, 11, 12, 12, 13, 13] : List ℤ).map (2 * ·) := by + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjecture (Velin Yanev, 2017): for every `n > 0`, +`a(n) = (3 * A011371(n) - ∑_{k=1}^{n} A007814(k)^2) / 2`. -/ +def statement : Prop := + ∀ n : ℕ, 0 < n → + (a n : ℚ) = (3 * (A011371 n : ℚ) - ∑ k ∈ Finset.Icc 1 n, (A007814 k : ℚ) ^ 2) / 2 + +end Math0.Statements.A073642 diff --git a/lean/Math0/Statements/OEIS/A075855.lean b/lean/Math0/Statements/OEIS/A075855.lean new file mode 100644 index 0000000..b665f5f --- /dev/null +++ b/lean/Math0/Statements/OEIS/A075855.lean @@ -0,0 +1,353 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A075855: longest path on the black squares of an even chessboard + +Source: https://oeis.org/A075855, Jon Perry, Oct 15 2002 (edited by Dean Hickerson, +Oct 25 2002; FORMULA section). Verbatim: +> For n odd, a(n)=(n-1)^2/2+1. For n even, it is conjectured that a(n)=(n^2-n+2)/2 (it is easy +> to show this is a lower bound). + +The entry's definition (offset 1): "Maximum number of black squares on an n X n chessboard (with +a black square in at least one corner) that can be covered by a single path, traveling only to +adjacent black squares." The conjecture is the even case; the odd case is stated as a fact and +is not part of `statement`. + +## Encoding + +* *Board.* The square in row `i` and column `j` (`0`-indexed, `i, j < n`) is the pair `(i, j)`. + It is black iff `i + j` is even (`IsBlack`), so the corner `(0, 0)` is black. For even `n` the + two colourings of the board are mirror images of each other, so the choice of colouring does + not matter there; for odd `n` it is fixed by "with a black square in at least one corner". +* *Adjacency.* Two squares are adjacent iff they are distinct and touch, i.e. both coordinates + differ by at most `1` (`Adj`). Two black squares never share an edge, so for black squares + this means sharing a corner, i.e. being diagonal neighbours (`adj_iff_of_isBlack`). This is the + only reading under which a path can have more than one square, and it gives the listed values + (e.g. `a(2) = 2` uses the step `(0,0) → (1,1)`). +* *Paths.* A path is a list of black squares, consecutive squares adjacent, that does not visit a + square twice (`IsBoardPath`). The number of squares covered is its length. (If squares could be + revisited, every black square could be covered, e.g. `5` for `n = 3`, but the entry lists + `a(3) = 3`.) The empty path is allowed; it only matters for `n = 0`, outside the offset. +* *The sequence.* `a n` is computed by an exhaustive depth-first search over all paths (`dfs`, + with the visited squares kept as a bit mask), started from every black square. `a_spec` proves + that `a n` is exactly the maximum length of a path: it is the greatest element of + `{k | ∃ l, IsBoardPath n l ∧ l.length = k}`. So `a` is the entry's sequence, with no reliance on + the correctness of the search beyond what is proved here. +* *Data.* `a_data` kernel-checks the listed terms `a(1), …, a(6)` = `1, 2, 3, 7, 9, 16`. The + search visits every path, and the number of paths grows fast (`17932` directed paths for + `n = 6`, `295501` for `n = 7`), so `a(7), a(8), a(9)` = `19, 29, 33` are out of reach of the + kernel. `a_data_lower` kernel-checks explicit paths of `19`, `29` and `33` squares, so + `a(7) ≥ 19`, `a(8) ≥ 29`, `a(9) ≥ 33`. (An independent exhaustive search outside Lean, over all + `10181048` resp. `441446761` directed paths for `n = 8, 9`, gives the listed values + `a(7) = 19`, `a(8) = 29`, `a(9) = 33`; that check is not part of this file.) +* *Reading of the conjecture.* For every even `n` in the range of the entry (`n ≥ 1`, i.e. + `n ≥ 2`), `a n = (n ^ 2 - n + 2) / 2`. Here `n ^ 2 - n + 2 = n (n - 1) + 2` is even, so the + division in `ℕ` is exact, and the subtraction does not truncate since `n ≤ n ^ 2`. + Equivalently `a (2 m) = 2 m ^ 2 - m + 1` for `m ≥ 1`. +-/ + +namespace Math0.Statements.A075855 + +/-! ### Board, adjacency and paths -/ + +/-- The square `c = (i, j)` (row `i`, column `j`, `0`-indexed) of the `n × n` board is black: +`i < n`, `j < n` and `i + j` is even (the corner `(0, 0)` is black). -/ +def IsBlack (n : ℕ) (c : ℕ × ℕ) : Prop := c.1 < n ∧ c.2 < n ∧ (c.1 + c.2) % 2 = 0 + +/-- Two squares are adjacent: they are distinct and touch (each coordinate differs by at most +`1`). For black squares this means sharing a corner (`adj_iff_of_isBlack`). -/ +def Adj (c d : ℕ × ℕ) : Prop := + c ≠ d ∧ c.1 ≤ d.1 + 1 ∧ d.1 ≤ c.1 + 1 ∧ c.2 ≤ d.2 + 1 ∧ d.2 ≤ c.2 + 1 + +/-- A path on the black squares of the `n × n` board: a list of black squares, pairwise distinct +(no square is visited twice), with consecutive squares adjacent. The number of squares it covers +is its length. -/ +def IsBoardPath (n : ℕ) (l : List (ℕ × ℕ)) : Prop := + (∀ c ∈ l, IsBlack n c) ∧ l.Nodup ∧ l.IsChain Adj + +/-- Black squares are adjacent iff they are diagonal neighbours (black squares never share an +edge). -/ +theorem adj_iff_of_isBlack {n : ℕ} {c d : ℕ × ℕ} (hc : IsBlack n c) (hd : IsBlack n d) : + Adj c d ↔ (c.1 + 1 = d.1 ∨ d.1 + 1 = c.1) ∧ (c.2 + 1 = d.2 ∨ d.2 + 1 = c.2) := by + obtain ⟨c1, c2⟩ := c + obtain ⟨d1, d2⟩ := d + simp only [IsBlack, Adj, ne_eq, Prod.mk.injEq] at hc hd ⊢ + omega + +/-! ### The computable sequence -/ + +/-- `max` written with `Nat.ble`, which the kernel evaluates quickly. -/ +def nmax (x y : ℕ) : ℕ := bif Nat.ble x y then y else x + +/-- The maximum of `f` over the list `l` (`0` for the empty list). -/ +def lmax {α : Type} (l : List α) (f : α → ℕ) : ℕ := l.foldr (fun x best => nmax best (f x)) 0 + +/-- The bit used for the square `c` in the mask of visited squares. -/ +def idx (n : ℕ) (c : ℕ × ℕ) : ℕ := c.1 * n + c.2 + +/-- The diagonal neighbours of the square `d` that lie on the `n × n` board. -/ +def nbrs (n : ℕ) (d : ℕ × ℕ) : List (ℕ × ℕ) := + (bif Nat.blt (d.1 + 1) n && Nat.blt (d.2 + 1) n then [(d.1 + 1, d.2 + 1)] else []) ++ + (bif Nat.blt (d.1 + 1) n && Nat.blt 0 d.2 then [(d.1 + 1, d.2 - 1)] else []) ++ + (bif Nat.blt 0 d.1 && Nat.blt (d.2 + 1) n then [(d.1 - 1, d.2 + 1)] else []) ++ + (bif Nat.blt 0 d.1 && Nat.blt 0 d.2 then [(d.1 - 1, d.2 - 1)] else []) + +/-- Depth-first search: `dfs n fuel d mask` is the largest number of squares (at most `fuel`) by +which a path ending at the square `d`, whose visited squares are the set bits of `mask`, can be +continued. (Written with `Nat.rec` on the fuel, which the kernel evaluates faster than the +compiled structural recursion; `dfs_zero` and `dfs_succ` are the defining equations.) -/ +def dfs (n : ℕ) (fuel : ℕ) : ℕ × ℕ → ℕ → ℕ := + Nat.rec (motive := fun _ => ℕ × ℕ → ℕ → ℕ) (fun _ _ => 0) + (fun _ ih d mask => lmax ((nbrs n d).filter fun c => !mask.testBit (idx n c)) + fun c => ih c (mask ||| 1 <<< idx n c) + 1) fuel + +theorem dfs_zero (n : ℕ) (d : ℕ × ℕ) (mask : ℕ) : dfs n 0 d mask = 0 := rfl + +theorem dfs_succ (n fuel : ℕ) (d : ℕ × ℕ) (mask : ℕ) : + dfs n (fuel + 1) d mask = lmax ((nbrs n d).filter fun c => !mask.testBit (idx n c)) + fun c => dfs n fuel c (mask ||| 1 <<< idx n c) + 1 := rfl + +/-- The black squares of the `n × n` board. -/ +def cells (n : ℕ) : List (ℕ × ℕ) := + (List.range n ×ˢ List.range n).filter fun c => (c.1 + c.2) % 2 == 0 + +/-- A075855: the maximum number of black squares of the `n × n` board (corner `(0, 0)` black) +covered by a single path through adjacent black squares, found by an exhaustive search from +every black square (see `a_spec`). -/ +def a (n : ℕ) : ℕ := lmax (cells n) fun c => dfs n (n * n) c (1 <<< idx n c) + 1 + +/-- The definition reproduces the first terms listed in OEIS, `a(1), …, a(6)` +(kernel-checked). -/ +theorem a_data : (List.range 6).map (fun i => a (i + 1)) = [1, 2, 3, 7, 9, 16] := by + decide +kernel + +/-! ### `a n` is the maximum length of a path -/ + +theorem nmax_eq (x y : ℕ) : nmax x y = max x y := by + unfold nmax + cases h : Nat.ble x y + · have : ¬ x ≤ y := fun hle => by simp [Nat.ble_eq_true_of_le hle] at h + simp only [cond_false]; omega + · have : x ≤ y := Nat.le_of_ble_eq_true h + simp only [cond_true]; omega + +theorem le_lmax {α : Type} {l : List α} {f : α → ℕ} {x : α} (hx : x ∈ l) : f x ≤ lmax l f := by + induction l with + | nil => simp at hx + | cons y l ih => + simp only [lmax, List.foldr_cons, nmax_eq] at ih ⊢ + rcases List.mem_cons.1 hx with rfl | hx + · exact le_max_right _ _ + · exact (ih hx).trans (le_max_left _ _) + +theorem lmax_cases {α : Type} (l : List α) (f : α → ℕ) : + lmax l f = 0 ∨ ∃ x ∈ l, lmax l f = f x := by + induction l with + | nil => simp [lmax] + | cons y l ih => + simp only [lmax, List.foldr_cons, nmax_eq] at ih ⊢ + rcases le_total (List.foldr (fun x best => max best (f x)) 0 l) (f y) with h | h + · exact Or.inr ⟨y, List.mem_cons_self, max_eq_right h⟩ + · rw [max_eq_left h] + rcases ih with ih | ⟨x, hx, hx'⟩ + · exact Or.inl ih + · exact Or.inr ⟨x, List.mem_cons_of_mem _ hx, hx'⟩ + +theorem mem_cells {n : ℕ} {c : ℕ × ℕ} : c ∈ cells n ↔ IsBlack n c := by + obtain ⟨x, y⟩ := c + simp [cells, IsBlack, List.mem_filter, List.mem_product, List.mem_range, and_assoc] + +theorem idx_inj {n : ℕ} {c d : ℕ × ℕ} (hc : c.2 < n) (hd : d.2 < n) (h : idx n c = idx n d) : + c = d := by + obtain ⟨c1, c2⟩ := c + obtain ⟨d1, d2⟩ := d + simp only [idx] at h hc hd + have h1 : c1 = d1 := by + rcases lt_trichotomy c1 d1 with h' | h' | h' + · have : (c1 + 1) * n ≤ d1 * n := Nat.mul_le_mul_right n h' + nlinarith + · exact h' + · have : (d1 + 1) * n ≤ c1 * n := Nat.mul_le_mul_right n h' + nlinarith + subst h1 + have : c2 = d2 := by omega + rw [this] + +theorem testBit_or_one_shiftLeft (m k j : ℕ) : + (m ||| 1 <<< k).testBit j = (m.testBit j || decide (k = j)) := by + rw [Nat.testBit_or, Nat.one_shiftLeft, Nat.testBit_two_pow] + +theorem testBit_one_shiftLeft (k j : ℕ) : (1 <<< k).testBit j = decide (k = j) := by + rw [Nat.one_shiftLeft, Nat.testBit_two_pow] + +theorem mem_nbrs {n : ℕ} {c d : ℕ × ℕ} (hd1 : d.1 < n) (hd2 : d.2 < n) : + c ∈ nbrs n d ↔ c.1 < n ∧ c.2 < n ∧ + (d.1 + 1 = c.1 ∨ c.1 + 1 = d.1) ∧ (d.2 + 1 = c.2 ∨ c.2 + 1 = d.2) := by + obtain ⟨c1, c2⟩ := c + obtain ⟨d1, d2⟩ := d + simp only at hd1 hd2 ⊢ + simp only [nbrs, List.mem_append, Bool.cond_eq_ite, Bool.and_eq_true, Nat.blt_eq] + split_ifs <;> simp only [List.mem_singleton, List.not_mem_nil, Prod.mk.injEq, or_false, + false_or] + all_goals first | omega | (rw [false_iff]; omega) + +theorem isBoardPath_nil (n : ℕ) : IsBoardPath n [] := by simp [IsBoardPath] + +theorem isBoardPath_singleton {n : ℕ} {c : ℕ × ℕ} (hc : IsBlack n c) : IsBoardPath n [c] := by + simp [IsBoardPath, hc] + +theorem isBoardPath_cons_cons {n : ℕ} {c d : ℕ × ℕ} {p : List (ℕ × ℕ)} : + IsBoardPath n (c :: d :: p) ↔ + IsBlack n c ∧ c ∉ d :: p ∧ Adj c d ∧ IsBoardPath n (d :: p) := by + simp only [IsBoardPath, List.mem_cons, forall_eq_or_imp, List.nodup_cons, + List.isChain_cons_cons] + tauto + +theorem IsBoardPath.of_append {n : ℕ} {q p : List (ℕ × ℕ)} (h : IsBoardPath n (q ++ p)) : + IsBoardPath n p := + ⟨fun c hc => h.1 c (List.mem_append_right q hc), h.2.1.of_append_right, + (List.isChain_append.1 h.2.2).2.1⟩ + +theorem IsBoardPath.length_le {n : ℕ} {l : List (ℕ × ℕ)} (h : IsBoardPath n l) : + l.length ≤ n * n := by + rw [← List.toFinset_card_of_nodup h.2.1] + have hsub : l.toFinset ⊆ Finset.range n ×ˢ Finset.range n := by + intro c hc + have := h.1 c (List.mem_toFinset.1 hc) + simp only [Finset.mem_product, Finset.mem_range] + exact ⟨this.1, this.2.1⟩ + simpa using Finset.card_le_card hsub + +/-- Correctness of the search: for a path `d :: p` (most recent square `d` first) whose squares +are the set bits of `mask`, `dfs n fuel d mask` is the largest length of a continuation `q` of at +most `fuel` squares such that `q ++ d :: p` is a path. -/ +theorem dfs_spec (n : ℕ) : ∀ (fuel : ℕ) (d : ℕ × ℕ) (p : List (ℕ × ℕ)) (mask : ℕ), + IsBoardPath n (d :: p) → + (∀ e : ℕ × ℕ, e.1 < n → e.2 < n → (mask.testBit (idx n e) = true ↔ e ∈ d :: p)) → + (∀ q, IsBoardPath n (q ++ d :: p) → q.length ≤ fuel → q.length ≤ dfs n fuel d mask) ∧ + (∃ q, IsBoardPath n (q ++ d :: p) ∧ q.length = dfs n fuel d mask) := by + intro fuel + induction fuel with + | zero => + intro d p mask hP _ + refine ⟨fun q _ hq => by rw [dfs_zero]; exact hq, ⟨[], by simpa using hP, rfl⟩⟩ + | succ fuel ih => + intro d p mask hP hmask + have hd : IsBlack n d := hP.1 d List.mem_cons_self + -- the squares by which the path can be continued + have hC : ∀ c, c ∈ (nbrs n d).filter (fun c => !mask.testBit (idx n c)) ↔ + IsBoardPath n (c :: d :: p) := by + intro c + rw [List.mem_filter, mem_nbrs hd.1 hd.2.1, isBoardPath_cons_cons] + constructor + · rintro ⟨⟨hc1, hc2, hadj⟩, hbit⟩ + have hcb : IsBlack n c := by + refine ⟨hc1, hc2, ?_⟩ + have := hd.2.2 + omega + refine ⟨hcb, ?_, ?_, hP⟩ + · intro hmem + have := (hmask c hc1 hc2).2 hmem + simp [this] at hbit + · rw [adj_iff_of_isBlack hcb hd] + omega + · rintro ⟨hcb, hnot, hadj, -⟩ + rw [adj_iff_of_isBlack hcb hd] at hadj + refine ⟨⟨hcb.1, hcb.2.1, by omega⟩, ?_⟩ + cases hb : mask.testBit (idx n c) + · rfl + · exact absurd ((hmask c hcb.1 hcb.2.1).1 hb) hnot + -- the mask after visiting `c` + have hmask' : ∀ c, IsBoardPath n (c :: d :: p) → ∀ e : ℕ × ℕ, e.1 < n → e.2 < n → + ((mask ||| 1 <<< idx n c).testBit (idx n e) = true ↔ e ∈ c :: d :: p) := by + intro c hc e he1 he2 + have hcb : IsBlack n c := hc.1 c List.mem_cons_self + rw [testBit_or_one_shiftLeft, Bool.or_eq_true, hmask e he1 he2, decide_eq_true_iff, + List.mem_cons (a := e) (b := c)] + constructor + · rintro (h | h) + · exact Or.inr h + · exact Or.inl (idx_inj he2 hcb.2.1 h.symm) + · rintro (h | h) + · exact Or.inr (by rw [h]) + · exact Or.inl h + rw [dfs_succ] + constructor + · intro q hq hlen + rcases List.eq_nil_or_concat q with rfl | ⟨q', c, rfl⟩ + · simp + · simp only [List.concat_eq_append, List.append_assoc, List.cons_append, + List.nil_append] at hq + have hcP : IsBoardPath n (c :: d :: p) := hq.of_append + have hcC := (hC c).2 hcP + have := (ih c (d :: p) _ hcP (hmask' c hcP)).1 q' hq + (by simp only [List.concat_eq_append, List.length_append, List.length_singleton] + at hlen; omega) + refine le_trans ?_ (le_lmax hcC) + simp only [List.concat_eq_append, List.length_append, List.length_singleton] + omega + · rcases lmax_cases ((nbrs n d).filter fun c => !mask.testBit (idx n c)) + (fun c => dfs n fuel c (mask ||| 1 <<< idx n c) + 1) with h | ⟨c, hcC, h⟩ + · exact ⟨[], by simpa using hP, by rw [h]; rfl⟩ + · have hcP := (hC c).1 hcC + obtain ⟨q', hq', hlen⟩ := (ih c (d :: p) _ hcP (hmask' c hcP)).2 + refine ⟨q' ++ [c], ?_, ?_⟩ + · simpa only [List.append_assoc, List.cons_append, List.nil_append] using hq' + · rw [h, List.length_append, List.length_singleton, hlen] + +/-- `a n` is the maximum number of black squares of the `n × n` board covered by a single path +through adjacent black squares: some path has `a n` squares and no path has more. -/ +theorem a_spec (n : ℕ) : IsGreatest {k | ∃ l, IsBoardPath n l ∧ l.length = k} (a n) := by + have hstart : ∀ c, IsBlack n c → ∀ e : ℕ × ℕ, e.1 < n → e.2 < n → + ((1 <<< idx n c).testBit (idx n e) = true ↔ e ∈ [c]) := by + intro c hc e he1 he2 + rw [testBit_one_shiftLeft, decide_eq_true_iff, List.mem_singleton] + exact ⟨fun h => idx_inj he2 hc.2.1 h.symm, fun h => by rw [h]⟩ + constructor + · rcases lmax_cases (cells n) (fun c => dfs n (n * n) c (1 <<< idx n c) + 1) with + h | ⟨c, hc, h⟩ + · exact ⟨[], isBoardPath_nil n, by rw [a, h]; rfl⟩ + · have hcb := mem_cells.1 hc + obtain ⟨q, hq, hlen⟩ := + (dfs_spec n (n * n) c [] _ (isBoardPath_singleton hcb) (hstart c hcb)).2 + exact ⟨q ++ [c], hq, by rw [a, h, List.length_append, List.length_singleton, hlen]⟩ + · rintro k ⟨l, hl, rfl⟩ + rcases List.eq_nil_or_concat l with rfl | ⟨q, c, rfl⟩ + · simp + · simp only [List.concat_eq_append] at hl ⊢ + have hcb : IsBlack n c := (hl.of_append).1 c List.mem_cons_self + have hlen := hl.length_le + have := (dfs_spec n (n * n) c [] _ (isBoardPath_singleton hcb) (hstart c hcb)).1 q hl + (by simp only [List.length_append, List.length_singleton] at hlen; omega) + refine le_trans ?_ (le_lmax (f := fun c => dfs n (n * n) c (1 <<< idx n c) + 1) + (mem_cells.2 hcb)) + simp only [List.length_append, List.length_singleton] + omega + +/-- The remaining listed terms `a(7), a(8), a(9)` = `19, 29, 33` are lower bounds: explicit paths +covering that many squares (found by a computer search) are kernel-checked. -/ +theorem a_data_lower : 19 ≤ a 7 ∧ 29 ≤ a 8 ∧ 33 ≤ a 9 := by + refine ⟨(a_spec 7).2 ⟨[(0, 0), (1, 1), (0, 2), (1, 3), (0, 4), (1, 5), (2, 4), (3, 3), (2, 2), + (3, 1), (4, 0), (5, 1), (4, 2), (5, 3), (4, 4), (3, 5), (4, 6), (5, 5), (6, 4)], ?_, rfl⟩, + (a_spec 8).2 ⟨[(0, 0), (1, 1), (0, 2), (1, 3), (0, 4), (1, 5), (0, 6), (1, 7), (2, 6), (3, 5), + (2, 4), (3, 3), (2, 2), (3, 1), (4, 0), (5, 1), (4, 2), (5, 3), (4, 4), (5, 5), (4, 6), (5, 7), + (6, 6), (7, 5), (6, 4), (7, 3), (6, 2), (7, 1), (6, 0)], ?_, rfl⟩, + (a_spec 9).2 ⟨[(0, 0), (1, 1), (0, 2), (1, 3), (0, 4), (1, 5), (0, 6), (1, 7), (2, 6), (3, 5), + (2, 4), (3, 3), (2, 2), (3, 1), (4, 0), (5, 1), (4, 2), (5, 3), (4, 4), (5, 5), (4, 6), (3, 7), + (4, 8), (5, 7), (6, 6), (7, 7), (8, 6), (7, 5), (6, 4), (7, 3), (6, 2), (7, 1), (6, 0)], ?_, + rfl⟩⟩ <;> + · unfold IsBoardPath IsBlack Adj + decide +kernel + +/-! ### The conjecture -/ + +/-- For even `n ≥ 2` (the entry's range `n ≥ 1`, restricted to even `n`), the maximum number of +black squares of the `n × n` chessboard that a single path through adjacent black squares can +cover is `(n ^ 2 - n + 2) / 2`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → Even n → a n = (n ^ 2 - n + 2) / 2 + +end Math0.Statements.A075855 diff --git a/lean/Math0/Statements/OEIS/A081200.lean b/lean/Math0/Statements/OEIS/A081200.lean new file mode 100644 index 0000000..ac694ae --- /dev/null +++ b/lean/Math0/Statements/OEIS/A081200.lean @@ -0,0 +1,69 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A081200: collinear 5-point subsets of the `5 × 5 × ⋯ × 5` grid + +Source: https://oeis.org/A081200, Ron Hardin, May 24 2010 (COMMENTS section). Verbatim: +> Conjecture (verified up to a(9)): Number of collinear 5-tuples of points in a 5 X 5 X 5 X ... +> n-dimensional cubic grid. + +The sequence (offset `0`, by Paul Barry) is defined as "6th binomial transform of +(0,1,0,1,0,1,...), A000035." + +## Encoding + +* The `m`-th binomial transform of a sequence `b` is, in the OEIS convention, + `n ↦ ∑_{k=0}^{n} C(n,k) m^(n-k) b(k)` (`binomialTransform`). A000035 is `k ↦ k mod 2` + (offset `0`: `0, 1, 0, 1, …`). So `a n = ∑_{k=0}^{n} C(n,k) 6^(n-k) (k mod 2)`, exactly the + OEIS definition (not one of the closed forms such as `(7^n - 5^n)/2`). `a_data` checks all 23 + listed terms `a 0, …, a 22` in the kernel. +* The `n`-dimensional `5 × 5 × ⋯ × 5` cubic grid is `Fin n → Fin 5`, i.e. `{0, …, 4}^n`, sitting + in `ℝ^n = Fin n → ℝ` via `toReal` (coordinatewise inclusion `Fin 5 → ℕ → ℝ`). +* "Collinear 5-tuples of points" are read as unordered 5-element sets of grid points: a + `Finset` `s` of grid points with `s.card = 5` whose image in `ℝ^n` is collinear in Mathlib's + sense (`Collinear ℝ`, i.e. its vector span has dimension at most `1`, i.e. all its points lie + on one real line). Unordered sets is the only reading consistent with the data + (`a 1 = 1`: the one-dimensional grid has exactly one 5-element subset; ordered 5-tuples + of distinct points would give `120`). +* The count is `Set.ncard` of the (finite) set of such `s`. +* Range of `n`: the conjecture is a claim about the sequence, whose offset is `0`, so it is stated + for every `n : ℕ`. (For `n = 0` the grid is a single point, there are no 5-element subsets, + and `a 0 = 0`; for `n ≥ 1` it is the `n`-dimensional grid.) +-/ + +namespace Math0.Statements.A081200 + +/-- The `m`-th binomial transform of a sequence `b` (OEIS convention): +`n ↦ ∑_{k=0}^{n} C(n,k) m^(n-k) b(k)`. -/ +def binomialTransform (m : ℕ) (b : ℕ → ℕ) (n : ℕ) : ℕ := + ∑ k ∈ Finset.range (n + 1), n.choose k * m ^ (n - k) * b k + +/-- A000035: `k mod 2`, i.e. `0, 1, 0, 1, …` (offset `0`). -/ +def A000035 (k : ℕ) : ℕ := k % 2 + +/-- A081200: the 6th binomial transform of `(0, 1, 0, 1, 0, 1, …)` (A000035). -/ +def a (n : ℕ) : ℕ := binomialTransform 6 A000035 n + +/-- The definition reproduces all 23 terms listed in OEIS, `a 0, …, a 22` (kernel-checked). -/ +theorem a_data : (List.range 23).map (fun i => a (i + 0)) = + [0, 1, 12, 109, 888, 6841, 51012, 372709, 2687088, 19200241, 136354812, 964249309, + 6798573288, 47834153641, 336059778612, 2358521965909, 16540171339488, 115933787267041, + 812299450322412, 5689910849522509, 39848449432985688, 279034513462540441, + 1953718431395986212] := by + decide +kernel + +/-- The point of `ℝ^n` with the same coordinates as the grid point `x ∈ {0, …, 4}^n`. -/ +def toReal (n : ℕ) (x : Fin n → Fin 5) : Fin n → ℝ := fun i => ((x i : ℕ) : ℝ) + +/-- Hardin's conjecture: for every `n`, the number of 5-element sets of points of the +`n`-dimensional `5 × 5 × ⋯ × 5` grid `{0, …, 4}^n` that are collinear (lie on one line of `ℝ^n`) +equals `a n`, the 6th binomial transform of `(0, 1, 0, 1, …)`. -/ +def statement : Prop := + ∀ n : ℕ, + {s : Finset (Fin n → Fin 5) | + s.card = 5 ∧ Collinear ℝ (toReal n '' (s : Set (Fin n → Fin 5)))}.ncard = a n + +end Math0.Statements.A081200 diff --git a/lean/Math0/Statements/OEIS/A083020.lean b/lean/Math0/Statements/OEIS/A083020.lean new file mode 100644 index 0000000..c12269d --- /dev/null +++ b/lean/Math0/Statements/OEIS/A083020.lean @@ -0,0 +1,289 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A083020: the numbers `3^(3^n) + 2` are squarefree + +Source: https://oeis.org/A083020, Cino Hilliard, May 31 2003 (COMMENTS section). Verbatim: +> Conjecture: These numbers have no repeating factors or 3^(3^n) + 2 is squarefree. + +The entry (name: "Irregular triangle read by row of the prime factors of 3^(3^n) + 2", offset +`0`, keywords `easy,tabf,nonn`; corrected by T. D. Noe, Nov 15 2006; name clarified and two +more terms by Sean A. Irvine, Jan 04 2026) lists the prime factors of `3^(3^n) + 2`, row by row +for `n = 0, 1, 2, …`. Its example: +`3^(3^0)+2 = 5`, `3^(3^1)+2 = 29`, `3^(3^2)+2 = 5 * 31 * 127`, +`3^(3^3)+2 = 11 * 693236134999`, …. + +## Encoding + +* `N n = 3^(3^n) + 2`, and row `n` of the triangle is `row n = Nat.primeFactorsList (N n)`, the + prime factors of `N n` in increasing order, repeated according to multiplicity. (The listed + rows have no repeated primes, so listing distinct primes instead gives the same terms. The + conjecture is stated directly about `N n` and does not depend on this choice.) +* `a` is the triangle read by rows (the OEIS sequence itself, offset `0`): `a i` is the entry at + position `i` of `row 0 ++ row 1 ++ row 2 ++ ⋯`. Every row is nonempty (`N n ≥ 5`), so rows + `0, …, i` already contain at least `i + 1` entries, and `a i` reads the entry there. + `a` is computable but factors `N n` by trial division, so the data is checked through + certificates rather than by evaluating `a`. +* Data. `row_data` proves rows `0, …, 4`. Each one is checked against a certificate: the listed + primes are sorted, multiply to `N n`, and are prime. Primes below `10^5` are proved by + `norm_num`. Larger primes get a Lucas (Pratt) certificate from Mathlib's `lucas_primality`, + with powers mod `p` computed by `powMod` (square and multiply, proved equal to `a ^ e % p`) + and evaluated by `decide +kernel`. `a_data` then checks the first 13 listed terms + `a 0, …, a 12` (rows `0, …, 4`). +* The remaining listed terms are `a 13 = 8718…5629` (116 digits), `a 14 = 5`, `a 15 = 31`. + `a 13` is the whole of row `5`, i.e. the entry asserts that `N 5 = 3^243 + 2` is prime. Its + primality is not checked in Lean (sympy's `isprime` agrees). `N5_data` checks that the listed + 116-digit number is `N 5`, and `row6_data` checks that row `6` begins with `5, 31`. So + `a 13, a 14, a 15` are the listed terms exactly when `N 5` is prime. +* The conjecture. "These numbers have no repeating factors or 3^(3^n) + 2 is squarefree": for + every `n ≥ 0` (all rows of the triangle, offset `0`), `3^(3^n) + 2` is squarefree. + `statement` is `∀ n : ℕ, Squarefree (3 ^ (3 ^ n) + 2)`. The two phrasings in the comment say + the same thing: `statement_iff` restates it as "no prime appears twice in `row n`" + (`Nat.squarefree_iff_nodup_primeFactorsList`). The comment is part of the original entry and + carries no separate attribution. +-/ + +namespace Math0.Statements.A083020 + +/-- The number `3^(3^n) + 2`. -/ +def N (n : ℕ) : ℕ := 3 ^ (3 ^ n) + 2 + +/-- Row `n` of the triangle: the prime factors of `3^(3^n) + 2`, in increasing order and with +multiplicity. -/ +def row (n : ℕ) : List ℕ := Nat.primeFactorsList (N n) + +/-- A083020: the irregular triangle of the prime factors of `3^(3^n) + 2`, read by rows (offset +`0`). Rows `0, …, i` contain at least `i + 1` entries, so the `i`-th entry of the concatenation +lies among them. -/ +def a (i : ℕ) : ℕ := ((List.range (i + 1)).flatMap row).getD i 0 + +/-! ### Reading terms of `a` off a prefix of rows -/ + +theorem one_lt_N (n : ℕ) : 1 < N n := + Nat.lt_of_lt_of_le one_lt_two (Nat.le_add_left 2 _) + +theorem row_ne_nil (n : ℕ) : row n ≠ [] := + (Nat.primeFactorsList_ne_nil _).2 (one_lt_N n) + +theorem flatMap_range_add (k j : ℕ) : + (List.range (k + j)).flatMap row = + (List.range k).flatMap row ++ (List.range j).flatMap (fun t => row (k + t)) := by + rw [List.range_add, List.flatMap_append, List.flatMap_map] + +theorem le_length_flatMap_range (k : ℕ) : k ≤ ((List.range k).flatMap row).length := by + induction k with + | zero => simp + | succ k ih => + rw [flatMap_range_add k 1] + have : 1 ≤ (row k).length := List.length_pos_iff.2 (row_ne_nil k) + simp only [List.length_append, List.range_one, List.flatMap_cons, List.flatMap_nil, + List.append_nil, add_zero] + omega + +theorem getD_flatMap_range {k K i : ℕ} (hkK : k ≤ K) + (hi : i < ((List.range k).flatMap row).length) : + ((List.range K).flatMap row).getD i 0 = ((List.range k).flatMap row).getD i 0 := by + obtain ⟨j, rfl⟩ := Nat.exists_eq_add_of_le hkK + rw [flatMap_range_add, List.getD_append _ _ _ _ hi] + +/-- If the first `m` rows contain more than `i` entries, `a i` is the `i`-th of them. -/ +theorem a_eq (m i : ℕ) (h : i < ((List.range m).flatMap row).length) : + a i = ((List.range m).flatMap row).getD i 0 := by + have h1 : i < ((List.range (i + 1)).flatMap row).length := + Nat.lt_of_lt_of_le (Nat.lt_succ_self i) (le_length_flatMap_range _) + rw [a, ← getD_flatMap_range (le_max_left (i + 1) m) h1, + getD_flatMap_range (le_max_right (i + 1) m) h] + +/-- A list of primes in increasing order with product `n` is the list of prime factors of `n`. -/ +theorem primeFactorsList_eq_of {n : ℕ} {l : List ℕ} (hprod : l.prod = n) + (hp : ∀ p ∈ l, p.Prime) (hs : l.Pairwise (· ≤ ·)) : n.primeFactorsList = l := + ((Nat.primeFactorsList_unique hprod hp).eq_of_pairwise' hs + (Nat.primeFactorsList_sorted n).pairwise).symm + +/-! ### Lucas certificates -/ + +/-- `powModAux m f x e acc = acc * x ^ e % m` (for `e < 2 ^ f`), by square and multiply. -/ +def powModAux (m : ℕ) : ℕ → ℕ → ℕ → ℕ → ℕ + | 0, _, _, acc => acc % m + | f + 1, x, e, acc => + if e = 0 then acc % m + else powModAux m f (x * x % m) (e / 2) (if e % 2 = 1 then acc * x % m else acc) + +/-- `powMod a e m = a ^ e % m` for `e < 2 ^ 64` (`powMod_eq`). -/ +def powMod (a e m : ℕ) : ℕ := powModAux m 64 (a % m) e 1 + +theorem powModAux_eq (m : ℕ) : ∀ (f x e acc : ℕ), e < 2 ^ f → + powModAux m f x e acc = acc * x ^ e % m + | 0, x, e, acc, he => by + have : e = 0 := by simpa using he + subst this + simp [powModAux] + | f + 1, x, e, acc, he => by + rw [powModAux] + split_ifs with h0 h1 + · subst h0 + simp + · rw [powModAux_eq m f _ _ _ (by rw [pow_succ] at he; omega)] + obtain ⟨k, rfl⟩ : ∃ k, e = 2 * k + 1 := ⟨e / 2, by omega⟩ + rw [show (2 * k + 1) / 2 = k by omega] + refine ((Nat.mod_modEq _ _).mul ((Nat.mod_modEq _ _).pow _)).trans ?_ + unfold Nat.ModEq + congr 1 + ring + · rw [powModAux_eq m f _ _ _ (by rw [pow_succ] at he; omega)] + obtain ⟨k, rfl⟩ : ∃ k, e = 2 * k := ⟨e / 2, by omega⟩ + rw [show 2 * k / 2 = k by omega] + refine ((Nat.ModEq.refl acc).mul ((Nat.mod_modEq _ _).pow _)).trans ?_ + unfold Nat.ModEq + congr 1 + ring + +theorem powMod_eq (a e m : ℕ) (he : e < 2 ^ 64) : powMod a e m = a ^ e % m := by + rw [powMod, powModAux_eq m 64 _ _ _ he, one_mul, ← Nat.pow_mod] + +/-- The computable part of a Lucas primality certificate for `p`, with witness `w` and the list +`fs` of prime factors of `p - 1` (with multiplicity). -/ +def lucasCheck (p w : ℕ) (fs : List ℕ) : Bool := + decide (2 ≤ p) && decide (p < 2 ^ 64) && fs.prod == p - 1 && powMod w (p - 1) p == 1 && + fs.all fun q => powMod w ((p - 1) / q) p != 1 + +/-- Lucas' primality test (Mathlib's `lucas_primality`) in a form suited to `decide`. -/ +theorem prime_of_lucasCheck (p w : ℕ) (fs : List ℕ) (hfs : ∀ q ∈ fs, q.Prime) + (h : lucasCheck p w fs = true) : p.Prime := by + simp only [lucasCheck, Bool.and_eq_true, decide_eq_true_eq, beq_iff_eq, List.all_eq_true, + bne_iff_ne, ne_eq] at h + obtain ⟨⟨⟨⟨hp2, hp64⟩, hprod⟩, h1⟩, hall⟩ := h + have hpow : ∀ e, e ≤ p - 1 → powMod w e p = w ^ e % p := fun e he => + powMod_eq _ _ _ (by omega) + have hmod1 : 1 % p = 1 := Nat.mod_eq_of_lt (by omega) + refine lucas_primality p (w : ZMod p) ?_ ?_ + · rw [← Nat.cast_pow, ← ZMod.natCast_mod, ← hpow _ le_rfl, h1, Nat.cast_one] + · intro q hq hdvd hcontra + rw [← hprod] at hdvd + obtain ⟨r, hr, hqr⟩ := (Nat.Prime.prime hq).dvd_prod_iff.1 hdvd + rw [(Nat.prime_dvd_prime_iff_eq hq (hfs r hr)).1 hqr] at hcontra + apply hall r hr + have h := (ZMod.natCast_eq_natCast_iff' (w ^ ((p - 1) / r)) 1 p).1 + (by rw [Nat.cast_pow, Nat.cast_one]; exact hcontra) + rw [hpow _ (Nat.div_le_self _ _), h, hmod1] + +/-- Proves `∀ q ∈ l, q.Prime` for an explicit list `l`: the large primes by hypotheses in the +context, the others by `norm_num`. -/ +macro "prime_list" : tactic => + `(tactic| (simp only [List.forall_mem_cons, List.forall_mem_nil, and_true] + repeat' apply And.intro + all_goals first | assumption | norm_num)) + +theorem prime_4317661 : Nat.Prime 4317661 := + prime_of_lucasCheck 4317661 6 [2, 2, 3, 3, 5, 17, 17, 83] (by norm_num) (by decide +kernel) + +theorem prime_20172112193 : Nat.Prime 20172112193 := + prime_of_lucasCheck 20172112193 3 [2, 2, 2, 2, 2, 2, 73, 4317661] + (by have := prime_4317661; prime_list) + (by decide +kernel) + +theorem prime_121032673159 : Nat.Prime 121032673159 := + prime_of_lucasCheck 121032673159 3 [2, 3, 20172112193] + (by have := prime_20172112193; prime_list) + (by decide +kernel) + +theorem prime_22381441 : Nat.Prime 22381441 := + prime_of_lucasCheck 22381441 7 [2, 2, 2, 2, 2, 2, 2, 3, 5, 11657] (by norm_num) + (by decide +kernel) + +theorem prime_3312453269 : Nat.Prime 3312453269 := + prime_of_lucasCheck 3312453269 2 [2, 2, 37, 22381441] + (by have := prime_22381441; prime_list) + (by decide +kernel) + +theorem prime_5945531 : Nat.Prime 5945531 := + prime_of_lucasCheck 5945531 2 [2, 5, 37, 16069] (by norm_num) (by decide +kernel) + +theorem prime_2372959 : Nat.Prime 2372959 := + prime_of_lucasCheck 2372959 3 [2, 3, 3, 7, 37, 509] (by norm_num) (by decide +kernel) + +theorem prime_391151 : Nat.Prime 391151 := + prime_of_lucasCheck 391151 13 [2, 5, 5, 7823] (by norm_num) (by decide +kernel) + +theorem prime_693236134999 : Nat.Prime 693236134999 := + prime_of_lucasCheck 693236134999 7 [2, 3, 3, 11, 8951, 391151] + (by have := prime_391151; prime_list) + (by decide +kernel) + +/-! ### Data -/ + +/-- Rows `0, …, 4` of the triangle, as listed in OEIS (proved via the certificates above). -/ +theorem row_data : + row 0 = [5] ∧ row 1 = [29] ∧ row 2 = [5, 31, 127] ∧ row 3 = [11, 693236134999] ∧ + row 4 = [5, 15679, 2372959, 5945531, 3312453269, 121032673159] := by + have := prime_693236134999 + have := prime_2372959 + have := prime_5945531 + have := prime_3312453269 + have := prime_121032673159 + refine ⟨?_, ?_, ?_, ?_, ?_⟩ <;> refine primeFactorsList_eq_of ?_ (by prime_list) (by decide) <;> + simp only [N, List.prod_cons, List.prod_nil] <;> norm_num + +/-- The definition reproduces the first 13 terms listed in OEIS, `a 0, …, a 12` (rows +`0, …, 4`), via the kernel-checked certificates of `row_data`. -/ +theorem a_data : (List.range 13).map (fun i => a (i + 0)) = + [5, 29, 5, 31, 127, 11, 693236134999, 5, 15679, 2372959, 5945531, 3312453269, + 121032673159] := by + have hL : (List.range 5).flatMap row = [5, 29, 5, 31, 127, 11, 693236134999, 5, 15679, + 2372959, 5945531, 3312453269, 121032673159] := by + obtain ⟨h0, h1, h2, h3, h4⟩ := row_data + rw [show List.range 5 = [0, 1, 2, 3, 4] from rfl] + simp only [List.flatMap_cons, List.flatMap_nil, h0, h1, h2, h3, h4] + rfl + show (List.range 13).map a = _ + rw [List.map_congr_left (fun i hi => a_eq 5 i (by rw [hL]; simpa using hi)), hL] + rfl + +/-- The listed term `a 13` (116 digits) is `N 5 = 3^243 + 2`, so it is row `5` exactly when +`3^243 + 2` is prime (not checked here). -/ +theorem N5_data : N 5 = + 87189642485960958202911070585860771696964072404731750085525219437990967093723439943475549906831683116791055225665629 := by + decide +kernel + +theorem primeFactorsList_eq_minFac_cons {n : ℕ} (hn : 2 ≤ n) : + n.primeFactorsList = n.minFac :: (n / n.minFac).primeFactorsList := by + obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_le' hn + exact Nat.primeFactorsList_add_two k + +theorem minFac_eq_of {n p : ℕ} (hp : 2 ≤ p) (hd : p ∣ n) (hlt : ∀ q < p, 2 ≤ q → ¬ q ∣ n) : + n.minFac = p := by + refine le_antisymm (Nat.minFac_le_of_dvd hp hd) ?_ + have hn : n ≠ 1 := by + rintro rfl + exact absurd (Nat.le_of_dvd one_pos hd) (by omega) + refine (Nat.le_minFac'.2 fun q hq hqn => ?_).resolve_left hn + by_contra h + exact hlt q (by omega) hq hqn + +/-- Row `6` begins with `5, 31`, the listed terms `a 14, a 15`. -/ +theorem row6_data : (row 6).take 2 = [5, 31] := by + have h1 : Nat.minFac (N 6) = 5 := + minFac_eq_of (by norm_num) (Nat.dvd_of_mod_eq_zero (by decide +kernel)) (by decide +kernel) + have h2 : Nat.minFac (N 6 / 5) = 31 := + minFac_eq_of (by norm_num) (Nat.dvd_of_mod_eq_zero (by decide +kernel)) (by decide +kernel) + have h3 : 2 ≤ N 6 / 5 := by decide +kernel + rw [row, primeFactorsList_eq_minFac_cons (one_lt_N 6), h1, primeFactorsList_eq_minFac_cons h3, + h2] + rfl + +/-! ### The conjecture -/ + +/-- Conjecture (Cino Hilliard, 2003): for every `n ≥ 0`, the number `3^(3^n) + 2` is +squarefree (it has no repeated prime factors). -/ +def statement : Prop := + ∀ n : ℕ, Squarefree (3 ^ (3 ^ n) + 2) + +/-- The statement says that no row of the triangle repeats a prime. -/ +theorem statement_iff : statement ↔ ∀ n, (row n).Nodup := by + simp only [statement, row, N] + exact forall_congr' fun n => Nat.squarefree_iff_nodup_primeFactorsList (by positivity) + +end Math0.Statements.A083020 diff --git a/lean/Math0/Statements/OEIS/A086004.lean b/lean/Math0/Statements/OEIS/A086004.lean new file mode 100644 index 0000000..076c5d0 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A086004.lean @@ -0,0 +1,630 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A086004: there are no 5-Rotation Cycle Primes + +Source: https://oeis.org/A086004, Chuck Seggelin, Jul 07 2003 (COMMENTS section). Verbatim: +> Conjecture 2: There are no 5-Rotation Cycle Primes. + +The entry's name: "Primes which remain prime after one and after two and after three +applications of the rotate-and-add operation of A086002." Offset `1`; the listed data start +`12917, 12919, 18911, 18913, 22907, 24907, 26903, 28901, 1088063, …`. The comments just before +the conjecture say "Note: Have not yet found any 4-Rotation Cycle Primes.", and a later comment +by Chai Wah Wu (Aug 20 2015) says "4-Rotation Cycle Primes exist and are listed in A261458", +where A261458 is "Primes which remain prime after one, two, three and four applications of the +rotate-and-add operation of A086002". So a *`k`-Rotation Cycle Prime* is a prime that remains +prime after each of `1, 2, …, k` applications of rotate-and-add, and A086004 lists the +3-Rotation Cycle Primes. (Conjecture 1 of the entry, about even digit counts, was proved by +R. J. Mathar in 2009; it is not formalized here.) + +## Encoding + +* *Rotation* (A086002): "Let rotation rot(k) of a number k be defined by swapping the blocks of + the first [d/2] and of the last [d/2] digits of k, where d=A055642(k). If the number of digits + in k is odd, the center digit remains untouched during rotation." (e.g. `1234 ↦ 3412`, + `12345 ↦ 45312`). `rot` encodes this with R. J. Mathar's Maple program from A086002: with + `d = (Nat.digits 10 n).length` the number of decimal digits, `l = ⌊d/2⌋` and `h = ⌈d/2⌉`, + `rot n = (n mod 10^l)·10^h + (middle digit)·10^l + ⌊n / 10^h⌋`, where the middle term is + `⌊n / 10^l⌋ mod 10^(h-l)`, i.e. the centre digit for odd `d` and `0` for even `d`. + `rotDigits` is the same operation written directly on the digit list (last block, centre + digit if any, first block), and `rot_eq_rotDigits_data` kernel-checks that the two agree on + all `n < 2000` and on the numbers occurring in the OEIS examples. (`A055642(0) = 1` while + `Nat.digits 10 0 = []`, but both give `rot 0 = 0`.) +* *Rotate-and-add* is `rotAdd n = n + rot n`, and `rotAdd^[j]` is its `j`-th iterate. +* `IsRotationCyclePrime k p`: `p` is prime and `rotAdd^[j] p` is prime for every + `j = 1, …, k`. +* The sequence: `a n = Nat.nth (IsRotationCyclePrime 3) (n - 1)` (offset `1`). It is not known + whether there are infinitely many terms, so `a` is defined with `Nat.nth` and is + noncomputable. `a_data` checks the first 13 listed terms `a 1, …, a 13` (all listed terms + below `10^8`). It rests on `term_iff`: below `1530000` the 3-Rotation Cycle Primes are exactly + these 13 numbers. That is proved by kernel scans (`decide +kernel`) with kernel-friendly + helpers that are proved equal to, or sound for, the definitions: `fK_eq` (rotate-and-add), + `primeK_iff` (trial division), `sm_of_prime` (coprime to the primes below `1000`), and + `term3_iff`. Three elementary facts shrink the scan, and each is proved here: a number + `≥ 10` ending in `0, 2, 4, 5, 6, 8` is not prime; for `4`- and `6`-digit `q`, + `rotAdd q = (10^k + 1)·(⌊q/10^k⌋ + q mod 10^k)` is composite (R. J. Mathar's comment); and + for odd `q` with `2m + 1 ∈ {5, 7}` digits and `⌊q/10^(m+1)⌋` odd, `rotAdd q` is even (Chai Wah + Wu's comment in A086002). The 14th listed term, `100083679`, would need a scan up to `10^8`. +* The conjecture: for every `p`, `¬ IsRotationCyclePrime 5 p`. There is no prime `p` such that + `rotAdd^[j] p` is prime for each `j = 1, 2, 3, 4, 5`. +-/ + +namespace Math0.Statements.A086004 + +/-! ### The rotate-and-add operation -/ + +/-- The rotation of A086002: with `d` the number of decimal digits of `n`, swap the block of the +first `⌊d/2⌋` digits with the block of the last `⌊d/2⌋` digits; if `d` is odd the centre digit +stays in place. (R. J. Mathar's formula from A086002, with `l = ⌊d/2⌋`, `h = ⌈d/2⌉`.) -/ +def rot (n : ℕ) : ℕ := + let d := (Nat.digits 10 n).length + let l := d / 2 + let h := d - l + n % 10 ^ l * 10 ^ h + n / 10 ^ l % 10 ^ (h - l) * 10 ^ l + n / 10 ^ h + +/-- The same rotation on the digit list, most significant digit first: the last `⌊d/2⌋` digits, +then the centre digit (present only for odd `d`), then the first `⌊d/2⌋` digits. -/ +def rotDigits (n : ℕ) : ℕ := + let ds := (Nat.digits 10 n).reverse + let d := ds.length + let l := d / 2 + Nat.ofDigits 10 (ds.drop (d - l) ++ (ds.drop l).take (d - 2 * l) ++ ds.take l).reverse + +/-- The rotate-and-add operation of A086002: `k ↦ k + rot k`. -/ +def rotAdd (n : ℕ) : ℕ := n + rot n + +/-- `p` is a `k`-Rotation Cycle Prime: `p` is prime and remains prime after each of `1, …, k` +applications of rotate-and-add. -/ +def IsRotationCyclePrime (k p : ℕ) : Prop := + p.Prime ∧ ∀ j, 1 ≤ j → j ≤ k → (rotAdd^[j] p).Prime + +/-- A086004 (offset `1`): the `n`-th prime which remains prime after one, two and three +applications of rotate-and-add, i.e. the `n`-th 3-Rotation Cycle Prime. -/ +noncomputable def a (n : ℕ) : ℕ := Nat.nth (IsRotationCyclePrime 3) (n - 1) + +/-- The examples of A086002 (`rot 1234 = 3412`, `rot 12345 = 45312`), the rotate-and-add chain +`12917 ↦ 30829 ↦ 60659 ↦ 120319` of the A086003/A086004 examples, and the chain +`10010905789 ↦ 15800815799 ↦ 31600631599 ↦ 63200263199 ↦ 126399526399` of the A261458 example +(the first listed 4-Rotation Cycle Prime). -/ +theorem rot_examples : + rot 1234 = 3412 ∧ rot 12345 = 45312 ∧ rot 12917 = 17912 ∧ rot 30829 = 29830 ∧ + rotAdd 12917 = 30829 ∧ rotAdd 30829 = 60659 ∧ rotAdd 60659 = 120319 ∧ + rotAdd 10010905789 = 15800815799 ∧ rotAdd 15800815799 = 31600631599 ∧ + rotAdd 31600631599 = 63200263199 ∧ rotAdd 63200263199 = 126399526399 := by + decide +kernel + +/-- The arithmetic `rot` agrees with the digit-list `rotDigits` on all `n < 2000` and on the +numbers of the OEIS examples. -/ +theorem rot_eq_rotDigits_data : + (∀ n < 2000, rot n = rotDigits n) ∧ + [12345, 12917, 30829, 60659, 120319, 1528019, 10010905789].all + (fun n => rot n == rotDigits n) = true := by + decide +kernel + + +/-! ### Kernel-friendly evaluation (used only for the data check) + +The functions below are written with the recursors `Nat.rec`, `Bool.rec`, `List.rec` and the +primitive operations `Nat.add`, `Nat.mul`, `Nat.div`, `Nat.mod`, `Nat.pow`, `Nat.beq`, `Nat.blt`, +which the kernel evaluates directly on numerals. Each one is proved equal to (or sound for) the +definitions above. -/ + +/-- `x && y`, written with the recursor. -/ +def andK (x y : Bool) : Bool := Bool.rec (motive := fun _ => Bool) false y x + +/-- `x || y`, written with the recursor. -/ +def orK (x y : Bool) : Bool := Bool.rec (motive := fun _ => Bool) y true x + +/-- `!x`, written with the recursor. -/ +def notK (x : Bool) : Bool := Bool.rec (motive := fun _ => Bool) true false x + +theorem andK_eq (x y : Bool) : andK x y = (x && y) := by cases x <;> rfl + +theorem orK_eq (x y : Bool) : orK x y = (x || y) := by cases x <;> rfl + +theorem notK_eq (x : Bool) : notK x = !x := by cases x <;> rfl + +theorem blt_eq_decide (x y : ℕ) : Nat.blt x y = decide (x < y) := by + rw [Bool.eq_iff_iff, Nat.blt_eq, decide_eq_true_iff] + +theorem ble_eq_decide (x y : ℕ) : Nat.ble x y = decide (x ≤ y) := by + rw [Bool.eq_iff_iff, Nat.ble_eq, decide_eq_true_iff] + +theorem beq_eq_decide (x y : ℕ) : Nat.beq x y = decide (x = y) := by + rw [Bool.eq_iff_iff, Nat.beq_eq, decide_eq_true_iff] + +/-- Number of decimal digits of `n` (correct when `n < 10 ^ fuel`, see `nd_eq`). -/ +def nd (fuel : ℕ) : ℕ → ℕ := + Nat.rec (motive := fun _ => ℕ → ℕ) (fun _ => 0) + (fun _ ih n => Bool.rec (motive := fun _ => ℕ) (Nat.succ (ih (Nat.div n 10))) 0 (Nat.beq n 0)) + fuel + +theorem nd_eq : ∀ fuel n, n < 10 ^ fuel → nd fuel n = (Nat.digits 10 n).length := by + intro fuel + induction fuel with + | zero => + intro n hn + obtain rfl : n = 0 := by simpa using hn + rfl + | succ fuel ih => + intro n hn + cases h : Nat.beq n 0 + · have h0 : n ≠ 0 := by + rintro rfl + exact absurd h (by decide) + have e : nd (fuel + 1) n = Nat.succ (nd fuel (n / 10)) := by + show Bool.rec (motive := fun _ => ℕ) (Nat.succ (nd fuel (n / 10))) 0 (Nat.beq n 0) = _ + rw [h] + rw [e, Nat.digits_def' (by norm_num) (Nat.pos_of_ne_zero h0), List.length_cons, + ih (n / 10) (by rw [pow_succ] at hn; omega)] + · have h0 : n = 0 := Nat.eq_of_beq_eq_true h + subst h0 + rfl + +/-- `rot`, given `l = ⌊d/2⌋` and `h = ⌈d/2⌉`. -/ +def rotLH (n l h : ℕ) : ℕ := + Nat.add (Nat.add (Nat.mul (Nat.mod n (Nat.pow 10 l)) (Nat.pow 10 h)) + (Nat.mul (Nat.mod (Nat.div n (Nat.pow 10 l)) (Nat.pow 10 (Nat.sub h l))) (Nat.pow 10 l))) + (Nat.div n (Nat.pow 10 h)) + +/-- `rot`, given the number `d` of digits. -/ +def rotD (n d : ℕ) : ℕ := rotLH n (Nat.div d 2) (Nat.sub d (Nat.div d 2)) + +/-- `rotAdd`, kernel-friendly. -/ +def fK (n : ℕ) : ℕ := Nat.add n (rotD n (nd n n)) + +theorem fK_eq (n : ℕ) : fK n = rotAdd n := by + have h := nd_eq n n (Nat.lt_pow_self (by norm_num)) + unfold fK rotAdd rot + rw [h] + rfl + +/-- Trial division of `n` by `d, d + 2, d + 4, …` while the square of the divisor is at most +`n`, with `fuel`. -/ +def trialK (n : ℕ) (fuel : ℕ) : ℕ → Bool := + Nat.rec (motive := fun _ => ℕ → Bool) (fun _ => true) + (fun _ ih d => orK (Nat.blt n (Nat.mul d d)) + (andK (notK (Nat.beq (Nat.mod n d) 0)) (ih (Nat.add d 2)))) fuel + +theorem trialK_succ (n fuel d : ℕ) : trialK n (fuel + 1) d = + (decide (n < d * d) || (!decide (n % d = 0) && trialK n fuel (d + 2))) := by + show orK (Nat.blt n (d * d)) (andK (notK (Nat.beq (n % d) 0)) (trialK n fuel (d + 2))) = _ + rw [orK_eq, andK_eq, notK_eq, blt_eq_decide, beq_eq_decide] + +theorem trialK_sound : ∀ fuel d n, trialK n fuel d = true → + ∀ m, d ≤ m → m < d + 2 * fuel → m % 2 = d % 2 → m * m ≤ n → n % m ≠ 0 := by + intro fuel + induction fuel with + | zero => intro d n _ m h1 h2; omega + | succ fuel ih => + intro d n h m h1 h2 h3 h4 + rw [trialK_succ] at h + simp only [Bool.or_eq_true, decide_eq_true_eq, Bool.and_eq_true, Bool.not_eq_true', + decide_eq_false_iff_not] at h + rcases h with hlt | h + · have : d * d ≤ m * m := Nat.mul_le_mul h1 h1 + omega + · rcases Nat.eq_or_lt_of_le h1 with e | e + · exact e ▸ h.1 + · exact ih (d + 2) n h.2 m (by omega) (by omega) (by omega) h4 + +theorem trialK_complete : ∀ fuel d n, (∀ m, d ≤ m → m * m ≤ n → n % m ≠ 0) → + trialK n fuel d = true := by + intro fuel + induction fuel with + | zero => intro d n _; rfl + | succ fuel ih => + intro d n h + rw [trialK_succ] + simp only [Bool.or_eq_true, decide_eq_true_eq, Bool.and_eq_true, Bool.not_eq_true', + decide_eq_false_iff_not] + by_cases hlt : n < d * d + · exact Or.inl hlt + · exact Or.inr ⟨h d le_rfl (by omega), ih (d + 2) n fun m hm hmn => h m (by omega) hmn⟩ + +/-- Primality by trial division. -/ +def primeK (n : ℕ) : Bool := + Bool.rec (motive := fun _ => Bool) (andK (notK (Nat.beq (Nat.mod n 2) 0)) (trialK n n 3)) + (Nat.ble 2 n) (Nat.blt n 4) + +theorem primeK_iff (n : ℕ) : primeK n = true ↔ n.Prime := by + by_cases h4 : n < 4 + · have e : primeK n = Nat.ble 2 n := by + unfold primeK + rw [blt_eq_decide, decide_eq_true h4] + rw [e, ble_eq_decide, decide_eq_true_iff] + constructor + · intro h2 + interval_cases n <;> norm_num + · exact fun hp => hp.two_le + · have e : primeK n = (!decide (n % 2 = 0) && trialK n n 3) := by + unfold primeK + rw [blt_eq_decide, decide_eq_false h4] + show andK (notK (Nat.beq (n % 2) 0)) (trialK n n 3) = _ + rw [andK_eq, notK_eq, beq_eq_decide] + rw [e] + simp only [Bool.and_eq_true, Bool.not_eq_true', decide_eq_false_iff_not] + constructor + · rintro ⟨hodd, ht⟩ + by_contra hp + have hn0 : 0 < n := by omega + have hn1 : n ≠ 1 := by omega + set q := n.minFac with hq + have hqp : q.Prime := Nat.minFac_prime hn1 + have hqd : q ∣ n := Nat.minFac_dvd n + have hsq : q ^ 2 ≤ n := Nat.minFac_sq_le_self hn0 hp + have hqn : q ≤ n := Nat.le_of_dvd hn0 hqd + have hq2 : q % 2 = 1 := by + rcases hqp.eq_two_or_odd with e | e + · rw [e] at hqd + exact absurd (Nat.mod_eq_zero_of_dvd hqd) hodd + · exact e + have hq3 : 3 ≤ q := by + have := hqp.two_le + omega + exact trialK_sound n 3 n ht q hq3 (by omega) (by omega) (by nlinarith) + (Nat.mod_eq_zero_of_dvd hqd) + · intro hp + refine ⟨?_, trialK_complete n 3 n fun m hm hmn hmod => ?_⟩ + · intro h2 + rcases hp.eq_one_or_self_of_dvd 2 (Nat.dvd_of_mod_eq_zero h2) with e | e <;> omega + · rcases hp.eq_one_or_self_of_dvd m (Nat.dvd_of_mod_eq_zero hmod) with e | e + · omega + · subst e + nlinarith + +/-- The primes below `1000`. -/ +def smallPrimes : List ℕ := + [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, + 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, + 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, + 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, + 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, + 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, + 937, 941, 947, 953, 967, 971, 977, 983, 991, 997] + +theorem smallPrimes_spec : ∀ p ∈ smallPrimes, p.Prime ∧ p < 1000 := by + have h : ∀ p ∈ smallPrimes, primeK p = true ∧ p < 1000 := by decide +kernel + intro p hp + exact ⟨(primeK_iff p).1 (h p hp).1, (h p hp).2⟩ + +/-- A cheap necessary condition for primality: `n < 1000`, or `n` is coprime to the product of +the primes below `1000` (one `Nat.gcd`, which the kernel evaluates directly). -/ +def sm (n : ℕ) : Bool := orK (Nat.blt n 1000) (Nat.beq (Nat.gcd n smallPrimes.prod) 1) + +theorem sm_of_prime {n : ℕ} (hn : n.Prime) : sm n = true := by + unfold sm + rw [orK_eq, blt_eq_decide, beq_eq_decide] + by_cases h : n < 1000 + · simp [h] + · have hc : Nat.Coprime n smallPrimes.prod := Nat.coprime_list_prod_right_iff.2 fun p hp => + (Nat.coprime_primes hn (smallPrimes_spec p hp).1).2 + (by have := (smallPrimes_spec p hp).2; omega) + have hg : Nat.gcd n smallPrimes.prod = 1 := hc + simp [hg] + +/-- Decides `IsRotationCyclePrime 3 q` (see `term3_iff`): `q`, `q₁ = rotAdd q`, +`q₂ = rotAdd q₁`, `q₃ = rotAdd q₂` are prime; the cheap tests come first. -/ +def term3c (q q1 q2 q3 : ℕ) : Bool := + andK (sm q3) (andK (primeK q) (andK (primeK q1) (andK (primeK q2) (primeK q3)))) + +/-- See `term3c`. -/ +def term3b (q q1 q2 : ℕ) : Bool := andK (sm q2) (term3c q q1 q2 (fK q2)) + +/-- See `term3c`. -/ +def term3a (q q1 : ℕ) : Bool := andK (sm q1) (term3b q q1 (fK q1)) + +/-- See `term3c`. -/ +def term3 (q : ℕ) : Bool := andK (sm q) (term3a q (fK q)) + +theorem isRotationCyclePrime_three_iff (q : ℕ) : IsRotationCyclePrime 3 q ↔ + q.Prime ∧ (rotAdd q).Prime ∧ (rotAdd (rotAdd q)).Prime ∧ + (rotAdd (rotAdd (rotAdd q))).Prime := by + constructor + · rintro ⟨h0, h⟩ + exact ⟨h0, h 1 le_rfl (by norm_num), h 2 (by norm_num) (by norm_num), + h 3 (by norm_num) le_rfl⟩ + · rintro ⟨h0, h1, h2, h3⟩ + refine ⟨h0, fun j hj1 hj3 => ?_⟩ + interval_cases j + · exact h1 + · exact h2 + · exact h3 + +theorem term3_iff (q : ℕ) : term3 q = true ↔ IsRotationCyclePrime 3 q := by + rw [isRotationCyclePrime_three_iff] + simp only [term3, term3a, term3b, term3c, andK_eq, Bool.and_eq_true, primeK_iff, fK_eq] + constructor + · rintro ⟨-, -, -, -, h0, h1, h2, h3⟩ + exact ⟨h0, h1, h2, h3⟩ + · rintro ⟨h0, h1, h2, h3⟩ + exact ⟨sm_of_prime h0, sm_of_prime h1, sm_of_prime h2, sm_of_prime h3, h0, h1, h2, h3⟩ + +instance : DecidablePred (IsRotationCyclePrime 3) := + fun q => decidable_of_iff _ (term3_iff q) + +/-! ### Scanning -/ + +/-- The terms listed in OEIS below `10 ^ 8`. -/ +def listed : List ℕ := + [12917, 12919, 18911, 18913, 22907, 24907, 26903, 28901, 1088063, 1288043, 1408031, 1428029, + 1528019] + +/-- `check q = true` iff (`q` is a 3-Rotation Cycle Prime `→ q ∈ listed`). -/ +def check (q : ℕ) : Bool := orK (notK (term3 q)) (decide (q ∈ listed)) + +theorem check_sound {q : ℕ} (h : check q = true) (hq : IsRotationCyclePrime 3 q) : + q ∈ listed := by + rw [check, orK_eq, notK_eq, (term3_iff q).2 hq] at h + simpa using h + +/-- `checkAll s len = true` iff `check q` for every `q ∈ [s, s + len)`. -/ +def checkAll (s : ℕ) (len : ℕ) : Bool := + Nat.rec (motive := fun _ => Bool) true (fun k ih => andK (check (Nat.add s k)) ih) len + +theorem checkAll_sound (s : ℕ) : ∀ len, checkAll s len = true → + ∀ k < len, check (s + k) = true := by + intro len + induction len with + | zero => intro _ k hk; omega + | succ len ih => + intro h k hk + have h' : andK (check (s + len)) (checkAll s len) = true := h + rw [andK_eq, Bool.and_eq_true] at h' + rcases Nat.lt_succ_iff_lt_or_eq.1 hk with hk | hk + · exact ih h'.2 k hk + · subst hk + exact h'.1 + +/-- `check` at `b + 1`, `b + 3`, `b + 7`, `b + 9`. -/ +def check4 (b : ℕ) : Bool := + andK (check (Nat.add b 1)) + (andK (check (Nat.add b 3)) (andK (check (Nat.add b 7)) (check (Nat.add b 9)))) + +theorem check4_sound {b : ℕ} (h : check4 b = true) : + ∀ r, (r = 1 ∨ r = 3 ∨ r = 7 ∨ r = 9) → check (b + r) = true := by + have h' : (check (b + 1) && (check (b + 3) && (check (b + 7) && check (b + 9)))) = true := by + rw [← andK_eq, ← andK_eq, ← andK_eq] + exact h + simp only [Bool.and_eq_true] at h' + rintro r (rfl | rfl | rfl | rfl) + · exact h'.1 + · exact h'.2.1 + · exact h'.2.2.1 + · exact h'.2.2.2 + +/-- `inner c nt = true` iff `check4 (c + 10 t)` for every `t < nt`. -/ +def inner (c nt : ℕ) : Bool := + Nat.rec (motive := fun _ => Bool) true + (fun t ih => andK (check4 (Nat.add c (Nat.mul 10 t))) ih) nt + +theorem inner_sound (c : ℕ) : ∀ nt, inner c nt = true → ∀ t < nt, check4 (c + 10 * t) = true := by + intro nt + induction nt with + | zero => intro _ t ht; omega + | succ nt ih => + intro h t ht + have h' : andK (check4 (c + 10 * nt)) (inner c nt) = true := h + rw [andK_eq, Bool.and_eq_true] at h' + rcases Nat.lt_succ_iff_lt_or_eq.1 ht with ht | ht + · exact ih h'.2 t ht + · subst ht + exact h'.1 + +/-- `outer A₀ nA W nt = true` iff `inner ((A₀ + 2 j) * W) nt` for every `j < nA`. -/ +def outer (A0 nA W nt : ℕ) : Bool := + Nat.rec (motive := fun _ => Bool) true + (fun j ih => andK (inner (Nat.mul (Nat.add A0 (Nat.mul 2 j)) W) nt) ih) nA + +theorem outer_sound (A0 W nt : ℕ) : ∀ nA, outer A0 nA W nt = true → + ∀ j < nA, inner ((A0 + 2 * j) * W) nt = true := by + intro nA + induction nA with + | zero => intro _ j hj; omega + | succ nA ih => + intro h j hj + have h' : andK (inner ((A0 + 2 * nA) * W) nt) (outer A0 nA W nt) = true := h + rw [andK_eq, Bool.and_eq_true] at h' + rcases Nat.lt_succ_iff_lt_or_eq.1 hj with hj | hj + · exact ih h'.2 j hj + · subst hj + exact h'.1 + +/-! ### Facts that cut down the scan -/ + +theorem length_digits_eq {q k : ℕ} (h1 : 10 ^ k ≤ q) (h2 : q < 10 ^ (k + 1)) : + (Nat.digits 10 q).length = k + 1 := by + have a := (Nat.digits_length_le_iff (b := 10) (k := k + 1) (by norm_num) q).2 h2 + have b := mt (Nat.digits_length_le_iff (b := 10) (k := k) (by norm_num) q).1 (not_lt.2 h1) + omega + +/-- A number `q ≥ 10` whose last digit is not `1`, `3`, `7` or `9` is not prime. -/ +theorem not_prime_of_last_digit {q : ℕ} (hq : 10 ≤ q) + (h : ¬ (q % 10 = 1 ∨ q % 10 = 3 ∨ q % 10 = 7 ∨ q % 10 = 9)) : ¬ q.Prime := by + intro hp + rcases (by omega : q % 2 = 0 ∨ q % 5 = 0) with h2 | h5 + · rcases hp.eq_one_or_self_of_dvd 2 (Nat.dvd_of_mod_eq_zero h2) with e | e <;> omega + · rcases hp.eq_one_or_self_of_dvd 5 (Nat.dvd_of_mod_eq_zero h5) with e | e <;> omega + +/-- (R. J. Mathar, in A086004.) For a `4`-digit `q`, `rotAdd q = 101 · (⌊q/100⌋ + q mod 100)` +is not prime. -/ +theorem not_prime_rotAdd_four {q : ℕ} (h1 : 1000 ≤ q) (h2 : q < 10000) : + ¬ (rotAdd q).Prime := by + have hlen : (Nat.digits 10 q).length = 4 := + length_digits_eq (k := 3) (by norm_num; omega) (by norm_num; omega) + have hr : rotAdd q = 101 * (q / 100 + q % 100) := by + unfold rotAdd rot + simp only [hlen] + norm_num + omega + rw [hr] + exact Nat.not_prime_mul (by norm_num) (by omega) + +/-- (R. J. Mathar, in A086004.) For a `6`-digit `q`, +`rotAdd q = 1001 · (⌊q/1000⌋ + q mod 1000)` is not prime. -/ +theorem not_prime_rotAdd_six {q : ℕ} (h1 : 100000 ≤ q) (h2 : q < 1000000) : + ¬ (rotAdd q).Prime := by + have hlen : (Nat.digits 10 q).length = 6 := + length_digits_eq (k := 5) (by norm_num; omega) (by norm_num; omega) + have hr : rotAdd q = 1001 * (q / 1000 + q % 1000) := by + unfold rotAdd rot + simp only [hlen] + norm_num + omega + rw [hr] + exact Nat.not_prime_mul (by norm_num) (by omega) + +/-- (C. W. Wu, in A086002.) For an odd `5`-digit `q` with `⌊q/1000⌋` odd, `rotAdd q` is even, +so not prime. -/ +theorem not_prime_rotAdd_five {q : ℕ} (h1 : 10000 ≤ q) (h2 : q < 100000) (hq : q % 2 = 1) + (hA : q / 1000 % 2 = 1) : ¬ (rotAdd q).Prime := by + have hlen : (Nat.digits 10 q).length = 5 := + length_digits_eq (k := 4) (by norm_num; omega) (by norm_num; omega) + have hr : rotAdd q = q + (q % 100 * 1000 + q / 100 % 10 * 100 + q / 1000) := by + unfold rotAdd rot + simp only [hlen] + norm_num + intro hp + rcases hp.eq_one_or_self_of_dvd 2 (Nat.dvd_of_mod_eq_zero (by rw [hr]; omega)) with e | e + · omega + · rw [hr] at e + omega + +/-- (C. W. Wu, in A086002.) For an odd `7`-digit `q` with `⌊q/10⁴⌋` odd, `rotAdd q` is even, +so not prime. -/ +theorem not_prime_rotAdd_seven {q : ℕ} (h1 : 1000000 ≤ q) (h2 : q < 10000000) (hq : q % 2 = 1) + (hA : q / 10000 % 2 = 1) : ¬ (rotAdd q).Prime := by + have hlen : (Nat.digits 10 q).length = 7 := + length_digits_eq (k := 6) (by norm_num; omega) (by norm_num; omega) + have hr : rotAdd q = q + (q % 1000 * 10000 + q / 1000 % 10 * 1000 + q / 10000) := by + unfold rotAdd rot + simp only [hlen] + norm_num + intro hp + rcases hp.eq_one_or_self_of_dvd 2 (Nat.dvd_of_mod_eq_zero (by rw [hr]; omega)) with e | e + · omega + · rw [hr] at e + omega + +theorem rotAdd_prime_of {q : ℕ} (hq : IsRotationCyclePrime 3 q) : (rotAdd q).Prime := + hq.2 1 le_rfl (by norm_num) + +/-! ### The kernel scans -/ + +/-- All `q < 1000`. -/ +theorem scan_small : checkAll 0 1000 = true := by decide +kernel + +/-- The `5`-digit `q = A · 1000 + B` with `A` even and last digit `1`, `3`, `7` or `9`. -/ +theorem scan_five : outer 10 45 1000 100 = true := by decide +kernel + +/-- The `7`-digit `q = A · 10⁴ + B` with `A ∈ {100, 102, …, 126}` and last digit `1`, `3`, `7` or +`9`. -/ +theorem scan_seven_1 : outer 100 14 10000 1000 = true := by decide +kernel + +/-- The `7`-digit `q = A · 10⁴ + B` with `A ∈ {128, 130, …, 152}` and last digit `1`, `3`, `7` or +`9`. -/ +theorem scan_seven_2 : outer 128 13 10000 1000 = true := by decide +kernel + +/-- From an `outer` scan to the numbers it covers. -/ +theorem of_outer {A0 nA W q : ℕ} (hscan : outer A0 nA W (W / 10) = true) (hW : W % 10 = 0) + (hlo : A0 * W ≤ q) (hhi : q < (A0 + 2 * nA) * W) (hA : (q / W - A0) % 2 = 0) + (hr : q % 10 = 1 ∨ q % 10 = 3 ∨ q % 10 = 7 ∨ q % 10 = 9) (hW0 : 0 < W) : + check q = true := by + have hqA : A0 ≤ q / W := (Nat.le_div_iff_mul_le hW0).2 hlo + have hqB : q / W < A0 + 2 * nA := (Nat.div_lt_iff_lt_mul hW0).2 hhi + set j := (q / W - A0) / 2 with hj + have hj' : j < nA := by omega + have hin := outer_sound A0 W (W / 10) nA hscan j hj' + have ht : q % W / 10 < W / 10 := by + have := Nat.mod_lt q hW0 + omega + have h4 := inner_sound _ _ hin (q % W / 10) ht + have e : q = (A0 + 2 * j) * W + 10 * (q % W / 10) + q % 10 := by + have e1 : A0 + 2 * j = q / W := by omega + rw [e1] + have e2 := Nat.div_add_mod q W + have e3 : q % W % 10 = q % 10 := by + obtain ⟨c, hc⟩ : 10 ∣ W := Nat.dvd_of_mod_eq_zero hW + rw [hc, Nat.mod_mul_right_mod] + have e4 := Nat.div_add_mod (q % W) 10 + rw [mul_comm (q / W) W] + omega + rw [e] + exact check4_sound h4 _ hr + +/-- Below `1530000`, the 3-Rotation Cycle Primes are exactly the listed ones. -/ +theorem term_iff {q : ℕ} (hq : q < 1530000) : IsRotationCyclePrime 3 q ↔ q ∈ listed := by + constructor + · intro hP + have hp := hP.1 + have h1 := rotAdd_prime_of hP + by_cases hs : q < 1000 + · have hc := checkAll_sound 0 1000 scan_small q hs + rw [zero_add] at hc + exact check_sound hc hP + by_cases h4 : q < 10000 + · exact absurd h1 (not_prime_rotAdd_four (by omega) h4) + have hr : q % 10 = 1 ∨ q % 10 = 3 ∨ q % 10 = 7 ∨ q % 10 = 9 := by + by_contra h + exact not_prime_of_last_digit (by omega) h hp + by_cases h5 : q < 100000 + · by_cases hA : q / 1000 % 2 = 0 + · exact check_sound (of_outer scan_five (by norm_num) (by omega) (by omega) (by omega) hr + (by norm_num)) hP + · exact absurd h1 (not_prime_rotAdd_five (by omega) h5 (by omega) (by omega)) + by_cases h6 : q < 1000000 + · exact absurd h1 (not_prime_rotAdd_six (by omega) h6) + by_cases hA : q / 10000 % 2 = 0 + · refine check_sound ?_ hP + by_cases c1 : q < 1280000 + · exact of_outer scan_seven_1 (by norm_num) (by omega) (by omega) (by omega) hr (by norm_num) + · exact of_outer scan_seven_2 (by norm_num) (by omega) (by omega) (by omega) hr (by norm_num) + · exact absurd h1 (not_prime_rotAdd_seven (by omega) (by omega) (by omega) (by omega)) + · intro hq + have hall : listed.all term3 = true := by decide +kernel + rw [List.all_eq_true] at hall + exact (term3_iff q).1 (hall q hq) + +theorem count_eq {n : ℕ} (hn : n ≤ 1530000) : + Nat.count (IsRotationCyclePrime 3) n = (listed.toFinset.filter (· < n)).card := by + rw [Nat.count_eq_card_filter_range] + congr 1 + ext q + simp only [Finset.mem_filter, Finset.mem_range, List.mem_toFinset] + constructor + · rintro ⟨h1, h2⟩ + exact ⟨(term_iff (by omega)).1 h2, h1⟩ + · rintro ⟨h1, h2⟩ + exact ⟨h2, (term_iff (by omega)).2 h1⟩ + +/-- The definition reproduces the first 13 terms listed in OEIS, `a 1, …, a 13` (all listed +terms below `10^8`; kernel-checked, see `term_iff`). -/ +theorem a_data : (List.range 13).map (fun i => a (i + 1)) = + [12917, 12919, 18911, 18913, 22907, 24907, 26903, 28901, 1088063, 1288043, 1408031, + 1428029, 1528019] := by + have hcard : ∀ i < 13, (listed.toFinset.filter (· < listed.getD i 0)).card = i := by + decide +kernel + have hlt : ∀ i < 13, listed.getD i 0 < 1530000 := by decide +kernel + have hmem : ∀ i < 13, listed.getD i 0 ∈ listed := by decide +kernel + show _ = listed + apply List.ext_getElem (by simp [listed]) + intro i h1 h2 + have hi : i < 13 := by simpa using h1 + simp only [List.getElem_map, List.getElem_range, a, Nat.add_sub_cancel] + have hP : IsRotationCyclePrime 3 (listed.getD i 0) := + (term_iff (hlt i hi)).2 (hmem i hi) + have hc := Nat.nth_count hP + rw [count_eq (hlt i hi).le, hcard i hi] at hc + rw [hc, List.getD_eq_getElem] + +/-- Conjecture 2 (Seggelin): there are no 5-Rotation Cycle Primes, i.e. there is no prime `p` +such that `rotAdd^[j] p` is prime for each of `j = 1, 2, 3, 4, 5`. -/ +def statement : Prop := + ∀ p : ℕ, ¬ IsRotationCyclePrime 5 p + +end Math0.Statements.A086004 diff --git a/lean/Math0/Statements/OEIS/A090905.lean b/lean/Math0/Statements/OEIS/A090905.lean new file mode 100644 index 0000000..9b5fd9d --- /dev/null +++ b/lean/Math0/Statements/OEIS/A090905.lean @@ -0,0 +1,199 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A090905: the last term of row `n` is twice the largest prime of row `n - 1` + +Source: https://oeis.org/A090905, Amarnath Murthy, Dec 13 2003 (COMMENTS section). Verbatim: +> Conjecture: For n > 4 the last term of the n-th group is 2p where p is the largest prime in the +> (n-1)th group. And these are the Bertrand primes. + +The entry's name: "Left side of irregular triangle of natural numbers in which every row product +is a multiple of the previous." Offset `1`. The entry's example shows the triangle, which splits +`1, 2, 3, …` into consecutive blocks ("groups"): +`(1), (2), (3, 4), (5, 6, 7, 8), (9, …, 14), (15, …, 26), …`. +The same conjecture appears in A090904 (row products), A090906 (row lengths) and A090907. + +## Encoding + +* Row `n` (`n ≥ 1`) is the block of consecutive integers `a n, a n + 1, …, last n`, where + `a n` is its first term (this sequence), `len n ≥ 1` its length and + `last n = a n + len n - 1` its last term. The product of row `n` is + `(a n).ascFactorial (len n) = a n * (a n + 1) * ⋯ * (a n + len n - 1)` + (Mathematica's `Pochhammer[a n, len n]`). +* Row `1` is `(1)`. Row `n + 1` starts right after row `n`, at `a n + len n`, and its length is + the least `k` with `k ≥ len n` such that the product of row `n` divides + `(a (n + 1)).ascFactorial k`. This is the rule of the Mathematica program in the entry (Michael + De Vlieger, Dec 15 2016), which starts its search at `k = len n` (the previous length). The + entry's name does not mention the bound `k ≥ len n`. Searching from `k = 1` instead gives the + same rows `1, …, 20` (checked outside Lean). +* To make `a` computable, the search for `k` is `search`, which runs for a limited number of + steps (its "fuel"). `len_succ_isLeast` proves that the fuel always suffices, so `len (n + 1)` + is exactly the least admissible `k`. Some `k` always works: for `k = a (n + 1) - 1`, the + product of row `n` divides `k!`, and `k!` divides the product of any `k` consecutive integers. + The theorems `a_one`, `len_one`, `a_succ` and `len_succ_isLeast` give the defining + recursion, which determines the triangle. `row 0` is a junk value (equal to `row 1`). +* `a_data` checks the first 18 listed terms `a 1, …, a 18` (the product of row `18` has about + 610000 bits). `len_data` checks the first 17 row lengths against A090906. +* "The Bertrand primes" are A006992: `bertrand 1 = 2`, and `bertrand (k + 1)` is the largest + prime `< 2 * bertrand k`. Here this is `Nat.findGreatest Nat.Prime (2 * b - 1)`. + `bertrand_data` checks the first 13 listed terms `2, 3, 5, …, 2503`. +* Reading choices in the statement: + - "the largest prime in the (n-1)th group" is the `p` that is the greatest element of the set + of primes `q` with `a (n - 1) ≤ q ≤ last (n - 1)`. The statement asserts that this `p` + exists, so in particular the group contains a prime. + - "these are the Bertrand primes": the primes `p` (for `n > 4`, so from group `4` on) are the + Bertrand primes. The largest prime of group `4 = (5, 6, 7, 8)` is `7 = A006992(4)`, and the + groups are disjoint and increasing. So the claim is that the largest prime of group `n - 1` is + `A006992(n - 1)`. (The Bertrand primes `2, 3, 5` before `7` do not occur as such `p`. Group + `3 = (3, 4)` has largest prime `3`, and `5` is skipped. So the sentence cannot mean the whole + sequence A006992.) +-/ + +namespace Math0.Statements.A090905 + +/-- `search P s fuel k Q` is called with `Q = s.ascFactorial k`. It returns the least `j` among +`k, k + 1, …, k + fuel - 1` with `P ∣ s.ascFactorial j`. If there is none, it returns +`k + fuel`. -/ +def search (P s : ℕ) : ℕ → ℕ → ℕ → ℕ + | 0, k, _ => k + | fuel + 1, k, Q => if P ∣ Q then k else search P s fuel (k + 1) ((s + k) * Q) + +/-- From row `(s, L)` (first term `s`, length `L`) to the next row: it starts at `s + L`, and its +length is the least `k ≥ L` such that `s (s+1) ⋯ (s+L-1)` divides +`(s+L) (s+L+1) ⋯ (s+L+k-1)` (the search has fuel `s + L`, which always suffices). -/ +def next (r : ℕ × ℕ) : ℕ × ℕ := + (r.1 + r.2, + search (r.1.ascFactorial r.2) (r.1 + r.2) (r.1 + r.2) r.2 ((r.1 + r.2).ascFactorial r.2)) + +/-- Row `n` of the triangle (`n ≥ 1`), as the pair (first term, length). Row `1` is `(1)`. +(`row 0` is junk and equals `row 1`.) -/ +def row (n : ℕ) : ℕ × ℕ := next^[n - 1] (1, 1) + +/-- A090905: the first term (left side) of row `n` of the irregular triangle of natural numbers +in which every row product is a multiple of the previous. -/ +def a (n : ℕ) : ℕ := (row n).1 + +/-- The length of row `n` (A090906). -/ +def len (n : ℕ) : ℕ := (row n).2 + +/-- The last term of row `n`. -/ +def last (n : ℕ) : ℕ := a n + len n - 1 + +/-! ### The definition satisfies the defining recursion -/ + +theorem a_one : a 1 = 1 := rfl + +theorem len_one : len 1 = 1 := rfl + +theorem row_succ (n : ℕ) (hn : 1 ≤ n) : row (n + 1) = next (row n) := by + obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩ + simp only [row, Nat.add_sub_cancel] + exact Function.iterate_succ_apply' next m (1, 1) + +theorem one_le_a (n : ℕ) : 1 ≤ a n := by + suffices h : ∀ m, 1 ≤ (next^[m] (1, 1)).1 from h (n - 1) + intro m + induction m with + | zero => simp + | succ m ih => + rw [Function.iterate_succ_apply'] + simp only [next] + omega + +/-- Row `n + 1` starts right after row `n`. -/ +theorem a_succ (n : ℕ) (hn : 1 ≤ n) : a (n + 1) = a n + len n := by + simp only [a, len, row_succ n hn, next] + +theorem search_spec (P s : ℕ) : ∀ (fuel k j : ℕ), k ≤ j → j < k + fuel → + P ∣ s.ascFactorial j → + k ≤ search P s fuel k (s.ascFactorial k) ∧ + P ∣ s.ascFactorial (search P s fuel k (s.ascFactorial k)) ∧ + ∀ i, k ≤ i → i < search P s fuel k (s.ascFactorial k) → ¬ P ∣ s.ascFactorial i := by + intro fuel + induction fuel with + | zero => intro k j h1 h2; omega + | succ fuel ih => + intro k j hkj hj hP + by_cases hk : P ∣ s.ascFactorial k + · simp only [search, if_pos hk] + exact ⟨le_rfl, hk, fun i h1 h2 => by omega⟩ + · have hQ : search P s (fuel + 1) k (s.ascFactorial k) = + search P s fuel (k + 1) (s.ascFactorial (k + 1)) := by + simp only [search, if_neg hk] + rfl + rw [hQ] + have hkj' : k + 1 ≤ j := by + rcases Nat.eq_or_lt_of_le hkj with h | h + · subst h; exact absurd hP hk + · omega + obtain ⟨h1, h2, h3⟩ := ih (k + 1) j hkj' (by omega) hP + refine ⟨by omega, h2, fun i hi1 hi2 => ?_⟩ + rcases Nat.eq_or_lt_of_le hi1 with h | h + · subst h; exact hk + · exact h3 i h hi2 + +/-- Some length always works: the product of row `(s, L)` divides `(s + L - 1)!`, which divides +the product of any `s + L - 1` consecutive integers. -/ +theorem exists_len (s L : ℕ) (hs : 1 ≤ s) : + L ≤ s + L - 1 ∧ s.ascFactorial L ∣ (s + L).ascFactorial (s + L - 1) := by + refine ⟨by omega, ?_⟩ + have h1 : s.ascFactorial L ∣ Nat.factorial (s + L - 1) := + Dvd.intro_left _ (Nat.factorial_mul_ascFactorial' s L (by omega)) + exact h1.trans (Nat.factorial_dvd_ascFactorial _ _) + +/-- The length of row `n + 1` is the least `k ≥ len n` such that the product of row `n` divides +the product of the `k` consecutive integers `a (n + 1), …, a (n + 1) + k - 1`. -/ +theorem len_succ_isLeast (n : ℕ) (hn : 1 ≤ n) : + IsLeast {k | len n ≤ k ∧ (a n).ascFactorial (len n) ∣ (a (n + 1)).ascFactorial k} + (len (n + 1)) := by + have hs := one_le_a n + have ha : a (n + 1) = a n + len n := a_succ n hn + have hl : len (n + 1) = search ((a n).ascFactorial (len n)) (a n + len n) (a n + len n) + (len n) ((a n + len n).ascFactorial (len n)) := by + simp only [len, a, row_succ n hn, next] + obtain ⟨e1, e2⟩ := exists_len (a n) (len n) hs + obtain ⟨h1, h2, h3⟩ := search_spec ((a n).ascFactorial (len n)) (a n + len n) + (a n + len n) (len n) (a n + len n - 1) e1 (by omega) e2 + rw [hl, ha] + exact ⟨⟨h1, h2⟩, fun k ⟨hk1, hk2⟩ => by + by_contra hlt + exact h3 k hk1 (by omega) hk2⟩ + +/-! ### Data checks -/ + +/-- The definition reproduces the first 18 terms listed in OEIS, `a 1, …, a 18` +(kernel-checked). -/ +theorem a_data : (List.range 18).map (fun i => a (i + 1)) = + [1, 2, 3, 5, 9, 15, 27, 47, 87, 167, 327, 635, 1263, 2519, 5007, 10007, 19947, + 39875] := by + decide +kernel + +/-- The row lengths reproduce the first 17 terms of A090906 (kernel-checked). -/ +theorem len_data : (List.range 17).map (fun i => len (i + 1)) = + [1, 1, 2, 4, 6, 12, 20, 40, 80, 160, 308, 628, 1256, 2488, 5000, 9940, 19928] := by + decide +kernel + +/-! ### Bertrand primes (A006992) -/ + +/-- A006992, the Bertrand primes: `bertrand 1 = 2`, and `bertrand (k + 1)` is the largest prime +`< 2 * bertrand k`, i.e. the largest prime `≤ 2 * bertrand k - 1`. (`bertrand 0` is junk.) -/ +def bertrand (n : ℕ) : ℕ := (fun b => Nat.findGreatest Nat.Prime (2 * b - 1))^[n - 1] 2 + +/-- `bertrand` reproduces the first 13 terms listed in A006992 (kernel-checked). -/ +theorem bertrand_data : (List.range 13).map (fun i => bertrand (i + 1)) = + [2, 3, 5, 7, 13, 23, 43, 83, 163, 317, 631, 1259, 2503] := by + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjecture (Amarnath Murthy, 2003): for every `n > 4`, the group `n - 1` has a largest prime +`p`, the last term of group `n` is `2 * p`, and `p` is the Bertrand prime `A006992(n - 1)`. -/ +def statement : Prop := + ∀ n : ℕ, 4 < n → ∃ p : ℕ, + IsGreatest {q : ℕ | q.Prime ∧ a (n - 1) ≤ q ∧ q ≤ last (n - 1)} p ∧ + last n = 2 * p ∧ p = bertrand (n - 1) + +end Math0.Statements.A090905 diff --git a/lean/Math0/Statements/OEIS/A091817.lean b/lean/Math0/Statements/OEIS/A091817.lean new file mode 100644 index 0000000..cda1934 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A091817.lean @@ -0,0 +1,123 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A091817: `(2*numerator(H(p-3)) - 3*denominator(H(p-3)))/p` is always an integer + +Source: https://oeis.org/A091817, Mohammed Bouayoun and Ralf Stephan, Mar 07 2004 (proposed by +Leroy Quet). Verbatim: +> Leroy Quet conjectures that the terms are always integral. This is true for p < 3*10^4. + +The entry's name is "(2*numerator(H(p-3)) -3*denominator(H(p-3)))/p with +H(m) = 1 + 1/2 + 1/3 + ...+ 1/m", with offset 1, and its PARI program runs over the primes +`p = 3, 5, 7, 11, …` (`forprime(p=3,100,…)`), so `a(1)` belongs to `p = 3`, `a(2)` to `p = 5`, +and in general `a(n)` belongs to the `(n+1)`-th prime. + +## Encoding + +* `H m = ∑_{k = 1..m} 1/k` in `ℚ` (`H 0 = 0`, as in PARI where the empty sum is `0`, with + numerator `0` and denominator `1`). Mathlib's `Rat` is always in lowest terms with a positive + denominator, so `(H m).num` and `(H m).den` are PARI's `numerator` and `denominator`. +* `term p = (2 * (H (p-3)).num - 3 * (H (p-3)).den) / p`, computed exactly in `ℚ`: the + integrality of this quotient is the content of the conjecture, so the sequence is encoded as + `ℚ`-valued and nothing is rounded. +* `primeAt i` is the `i`-th prime, 0-indexed (`primeAt 0 = 2`, `primeAt 1 = 3`, …), computed by a + bounded search; `primeAt_eq_nth` proves `primeAt i = Nat.nth Nat.Prime i`. With offset 1, + `a n = term (primeAt n)`: `a 1 = term 3`, `a 2 = term 5`, … (`a 0 = term 2` is outside the + sequence and is never used). +* The data check reproduces all 18 listed terms (`p = 3, …, 67`). +* "The terms are always integral" is read as: for every index `n ≥ 1` (equivalently, for every + prime `p ≥ 3`), the rational number `a n` is an integer, i.e. `p` divides + `2*numerator(H(p-3)) - 3*denominator(H(p-3))` in `ℤ`. +-/ + +namespace Math0.Statements.A091817 + +/-! ### The primes -/ + +/-- The first prime among `q, q + 1, …, q + fuel - 1`, or `0` if there is none. -/ +def firstPrimeFrom : ℕ → ℕ → ℕ + | 0, _ => 0 + | fuel + 1, q => if q.Prime then q else firstPrimeFrom fuel (q + 1) + +/-- The least prime `> m`, searched in `m + 1, …, 2 m + 2` (Bertrand's postulate guarantees one, +see `primeAt_eq_nth`). -/ +def nextPrime (m : ℕ) : ℕ := firstPrimeFrom (m + 2) (m + 1) + +/-- The `i`-th prime, 0-indexed: `primeAt 0 = 2`, `primeAt 1 = 3`, … -/ +def primeAt : ℕ → ℕ + | 0 => 2 + | i + 1 => nextPrime (primeAt i) + +theorem firstPrimeFrom_spec (fuel q : ℕ) (h : ∃ r, r.Prime ∧ q ≤ r ∧ r < q + fuel) : + (firstPrimeFrom fuel q).Prime ∧ q ≤ firstPrimeFrom fuel q ∧ + ∀ r, q ≤ r → r < firstPrimeFrom fuel q → ¬ r.Prime := by + induction fuel generalizing q with + | zero => obtain ⟨r, -, h1, h2⟩ := h; omega + | succ fuel ih => + rw [firstPrimeFrom] + split_ifs with hq + · exact ⟨hq, le_rfl, fun r h1 h2 => by omega⟩ + · obtain ⟨r, hr, h1, h2⟩ := h + have hqr : q ≠ r := fun e => hq (e ▸ hr) + obtain ⟨h1', h2', h3'⟩ := ih (q + 1) ⟨r, hr, by omega, by omega⟩ + refine ⟨h1', by omega, fun r' hr1 hr2 => ?_⟩ + rcases Nat.eq_or_lt_of_le hr1 with e | e + · exact e ▸ hq + · exact h3' r' e hr2 + +/-- `primeAt` is Mathlib's `Nat.nth Nat.Prime`. -/ +theorem primeAt_eq_nth (i : ℕ) : primeAt i = Nat.nth Nat.Prime i := by + have hinf : (Set.ofPred Nat.Prime).Infinite := Nat.infinite_setOfPred_prime + induction i with + | zero => simp [primeAt] + | succ i ih => + rw [primeAt, ih] + set m := Nat.nth Nat.Prime i with hm + have hmp : m.Prime := Nat.nth_mem_of_infinite hinf i + obtain ⟨r, hr, hr1, hr2⟩ := Nat.exists_prime_lt_and_le_two_mul m hmp.ne_zero + obtain ⟨hx, hx1, hx2⟩ := + firstPrimeFrom_spec (m + 2) (m + 1) ⟨r, hr, by omega, by omega⟩ + have hn : (Nat.nth Nat.Prime (i + 1)).Prime := Nat.nth_mem_of_infinite hinf (i + 1) + have hlt : m < Nat.nth Nat.Prime (i + 1) := Nat.nth_strictMono hinf (Nat.lt_succ_self i) + rw [nextPrime] + rcases lt_trichotomy (firstPrimeFrom (m + 2) (m + 1)) (Nat.nth Nat.Prime (i + 1)) + with h | h | h + · have := Nat.le_nth_of_lt_nth_succ h hx + omega + · exact h + · exact absurd hn (hx2 _ (by omega) h) + +/-! ### Harmonic numbers and the sequence -/ + +/-- The harmonic number `H m = 1 + 1/2 + ⋯ + 1/m` (`H 0 = 0`). -/ +def H (m : ℕ) : ℚ := ((List.range m).map (fun k => (1 : ℚ) / ((k : ℚ) + 1))).sum + +/-- The quantity attached to a prime `p`: +`(2*numerator(H(p-3)) - 3*denominator(H(p-3)))/p`, computed exactly in `ℚ`. -/ +def term (p : ℕ) : ℚ := (2 * (H (p - 3)).num - 3 * ((H (p - 3)).den : ℤ) : ℚ) / (p : ℚ) + +/-- A091817 (offset 1): `a(n) = (2*numerator(H(p-3)) - 3*denominator(H(p-3)))/p` where +`p = 3, 5, 7, 11, …` is the `(n+1)`-th prime (`primeAt n`, 0-indexed), as a rational number. -/ +def a (n : ℕ) : ℚ := term (primeAt n) + +/-- The first indices: `a 1, a 2, a 3, a 4` belong to `p = 3, 5, 7, 11`. -/ +example : (List.range 4).map (fun i => primeAt (i + 1)) = [3, 5, 7, 11] := by decide +kernel + +/-- The definition reproduces all 18 terms listed in OEIS, `a 1, …, a 18` +(`p = 3, …, 67`; kernel-checked). -/ +theorem a_data : (List.range 18).map (fun i => a (i + 1)) = + [-1, 0, 2, 62, 554, 74258, 142682, 2830946, 1448977246, 12576415426, 1857881203154, + 64634117421826, 62771945063582, 164497840779865642, 350742295126606034006, + 5774653629556529218142, 5647762835059481932498, 12720214895833193424471634] := by + decide +kernel + +/-- Conjecture (Leroy Quet): the terms are always integral, i.e. for every `n ≥ 1` the rational +number `a n = (2*numerator(H(p-3)) - 3*denominator(H(p-3)))/p` (with `p` the `(n+1)`-th prime) +is an integer. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → ∃ z : ℤ, a n = (z : ℚ) + +end Math0.Statements.A091817 diff --git a/lean/Math0/Statements/OEIS/A092054.lean b/lean/Math0/Statements/OEIS/A092054.lean new file mode 100644 index 0000000..b4cdc32 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A092054.lean @@ -0,0 +1,141 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A092054: numerator plus denominator of the convergents of `[1; 1/2, 1/3, …]` + +Source: https://oeis.org/A092054, Franklin T. Adams-Watters, Feb 02 2006 (FORMULA section). +Verbatim: +> It appears that a(n) = Sum_{k=1..n} A001511(floor((k+1)/2)). Equivalently, +> a(n) = 2n + 1 - A000120(n) - A000120(n+1) = A011371(n) + A011371(n+1). + +The entry's name (Paul D. Hanna, Feb 19 2004): "Base-2 logarithm of the sum of numerator and +denominator of the convergents of the continued fraction expansion +[1; 1/2, 1/3, 1/4, ..., 1/n, ...]." Offset `1`. The entry's example: `a(4) = 6`, since +`[1; 1/2, 1/3, 1/4] = 1 + 1/(1/2 + 1/(1/3 + 1/(1/4))) = 45/19` and `45 + 19 = 2^6`. + +## Encoding + +* `cfEval [x₀, x₁, …, x_k] = x₀ + 1/(x₁ + 1/(⋯ + 1/x_k))` is the value of a finite + continued fraction with (rational) partial quotients `x₀, …, x_k`, computed in `ℚ`. + (`cfEval [] = 0` is junk and never used for `n ≥ 1`.) +* `conv n = cfEval [1, 1/2, …, 1/n]` is the `n`-th convergent `[1; 1/2, …, 1/n]` (`n ≥ 1`), + matching the example (`conv 4 = 45/19`). `conv 1 = 1`, `conv 2 = 3`, `conv 3 = 9/7`. + The partial denominators `1/(k+1)` and all tails are positive, so no division by zero + occurs and `conv n > 0`. Its numerator and denominator are taken in lowest terms + (`Rat.num`, `Rat.den`); they are A001902(n) and A092053(n) (checked in `num_data`, + `den_data`). +* `a n = Nat.log 2 (num + den)` is the (floor) base-2 logarithm of `num + den`. The entry + asserts (comment and first formula) that `num + den` is a power of `2`; the OEIS "base-2 + logarithm" is the real logarithm. So the conjectured "`a(n) = f(n)`" means + `log₂(num + den) = f(n)` with the real logarithm, i.e. `num + den = 2 ^ f(n)`. In the + statement this is expressed by the two conjuncts `2 ^ a n = num + den` (the real base-2 + logarithm of `num + den` is the integer `a n`) and `a n = f(n)`. +* Helper sequences, as in their OEIS definitions: + - A001511 (offset 1), the ruler function: `ruler m = padicValNat 2 (2 * m)`, the exponent of + the highest power of `2` dividing `2m`. + - A000120 (offset 0), the binary weight: `binWeight m = (Nat.digits 2 m).sum`. + - A011371 (offset 0): `A011371 m = m - binWeight m` ("n minus (number of 1's in binary + expansion of n)"); this never truncates, since `binWeight m ≤ m`. +* `floor((k+1)/2)` is `(k + 1) / 2` (natural-number division); for `k ≥ 1` it is `≥ 1`, inside + the range of A001511. +* The three claimed equalities ("a(n) = … Equivalently, a(n) = … = …") are all part of the + statement, for every `n ≥ 1` (the offset of A092054). The middle form + `2n + 1 - A000120(n) - A000120(n+1)` is evaluated in `ℤ`, so that no truncated subtraction + is involved (it is in fact never negative). +* `a_data` checks all 67 listed terms `a 1, …, a 67` (kernel-checked). +-/ + +namespace Math0.Statements.A092054 + +/-- The value `x₀ + 1/(x₁ + 1/(⋯ + 1/x_k))` of the finite continued fraction +`[x₀; x₁, …, x_k]` with rational partial quotients. (`cfEval [] = 0` is junk.) -/ +def cfEval : List ℚ → ℚ + | [] => 0 + | [x] => x + | x :: y :: ys => x + 1 / cfEval (y :: ys) + +/-- The `n`-th convergent `[1; 1/2, 1/3, …, 1/n]` (for `n ≥ 1`). -/ +def conv (n : ℕ) : ℚ := cfEval ((List.range n).map fun k => 1 / ((k : ℚ) + 1)) + +/-- The numerator of the `n`-th convergent, in lowest terms (A001902(n)). -/ +def num (n : ℕ) : ℕ := (conv n).num.natAbs + +/-- The denominator of the `n`-th convergent, in lowest terms (A092053(n)). -/ +def den (n : ℕ) : ℕ := (conv n).den + +/-- A092054: the base-2 logarithm of the sum of the numerator and the denominator of the +convergent `[1; 1/2, 1/3, …, 1/n]` (as a natural number: the floor base-2 logarithm). -/ +def a (n : ℕ) : ℕ := Nat.log 2 (num n + den n) + +/-- The example in the entry: `[1; 1/2, 1/3, 1/4] = 45/19`. -/ +theorem conv_four : conv 4 = 45 / 19 := by decide +kernel + +/-- The numerators are the terms `A001902(1), …, A001902(24)` (all listed terms from index +`1`; kernel-checked). -/ +theorem num_data : (List.range 24).map (fun i => num (i + 1)) = + [1, 3, 9, 45, 75, 175, 1225, 11025, 19845, 43659, 160083, 693693, 1288287, 2760615, + 41409225, 703956825, 1329696225, 2807136475, 10667118605, 44801898141, 85530896451, + 178837328943, 1371086188563, 11425718238025] := by + decide +kernel + +/-- The denominators are the terms `A092053(1), …, A092053(25)` (all listed terms; +kernel-checked). -/ +theorem den_data : (List.range 25).map (fun i => den (i + 1)) = + [1, 1, 7, 19, 53, 81, 823, 5359, 12923, 21877, 102061, 354883, 808865, 1433689, + 25699639, 369784999, 817787423, 1487830821, 6512750579, 23917578595, 51908057021, + 96040578001, 827937066989, 6166467806391, 13211837015707] := by + decide +kernel + +/-- The definition reproduces the 67 terms listed in OEIS, `a 1, …, a 67` +(kernel-checked). -/ +theorem a_data : (List.range 67).map (fun i => a (i + 1)) = + [1, 2, 4, 6, 7, 8, 11, 14, 15, 16, 18, 20, 21, 22, 26, 30, 31, 32, 34, 36, 37, 38, 41, 44, + 45, 46, 48, 50, 51, 52, 57, 62, 63, 64, 66, 68, 69, 70, 73, 76, 77, 78, 80, 82, 83, 84, + 88, 92, 93, 94, 96, 98, 99, 100, 103, 106, 107, 108, 110, 112, 113, 114, 120, 126, 127, + 128, 130] := by + decide +kernel + +/-- A001511, the ruler function: the exponent of the highest power of `2` dividing `2m` +(offset `1`). -/ +def ruler (m : ℕ) : ℕ := padicValNat 2 (2 * m) + +/-- A000120: the number of `1`'s in the binary expansion of `m` (offset `0`). -/ +def binWeight (m : ℕ) : ℕ := (Nat.digits 2 m).sum + +/-- A011371: `m` minus the number of `1`'s in the binary expansion of `m` (offset `0`). -/ +def A011371 (m : ℕ) : ℕ := m - binWeight m + +/-- `ruler` reproduces the first 34 listed terms of A001511 (kernel-checked). -/ +theorem ruler_data : (List.range 34).map (fun i => ruler (i + 1)) = + [1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, 1, 5, 1, 2, 1, 3, 1, 2, 1, 4, 1, 2, 1, 3, 1, 2, + 1, 6, 1, 2] := by + decide +kernel + +/-- `binWeight` reproduces the first 34 listed terms of A000120 (kernel-checked). -/ +theorem binWeight_data : (List.range 34).map binWeight = + [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, + 4, 5, 1, 2] := by + decide +kernel + +/-- `A011371` reproduces the first 27 listed terms of A011371 (kernel-checked). -/ +theorem A011371_data : (List.range 27).map A011371 = + [0, 0, 1, 1, 3, 3, 4, 4, 7, 7, 8, 8, 10, 10, 11, 11, 15, 15, 16, 16, 18, 18, 19, 19, 22, + 22, 23] := by + decide +kernel + +/-- Conjecture (Franklin T. Adams-Watters, 2006): for every `n ≥ 1`, the base-2 logarithm of +`num + den` (for the convergent `[1; 1/2, …, 1/n] = num/den` in lowest terms) is +`a(n) = Sum_{k=1..n} A001511(floor((k+1)/2))`, i.e. `num + den` is exactly `2 ^ a n` and +`a n` equals that sum; equivalently `a(n) = 2n + 1 - A000120(n) - A000120(n+1) += A011371(n) + A011371(n+1)`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + 2 ^ a n = num n + den n ∧ + a n = ∑ k ∈ Finset.Icc 1 n, ruler ((k + 1) / 2) ∧ + (a n : ℤ) = 2 * (n : ℤ) + 1 - (binWeight n : ℤ) - (binWeight (n + 1) : ℤ) ∧ + a n = A011371 n + A011371 (n + 1) + +end Math0.Statements.A092054 diff --git a/lean/Math0/Statements/OEIS/A093726.lean b/lean/Math0/Statements/OEIS/A093726.lean new file mode 100644 index 0000000..caa8456 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A093726.lean @@ -0,0 +1,133 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A093726: imaginary parts of the convergents of `[1+i; 1+i, 1+i, …]` + +Source: https://oeis.org/A093726, _Zhuorui He_, Jun 16 2026 (FORMULA section). Verbatim: +> Conjecture: a(n)/A093727(n) = A317974(n+1)/A138573(n). - _Zhuorui He_, Jun 16 2026 + +The entry (offset `1`) is "Given the infinite continued fraction (1+i)+1/((1+i)+1/((1+i)+...)), +where i is the square root of (-1), this is the numerator of the imaginary part of the +convergents.", with the Mathematica program +`Table[ Im[ Numerator[ FromContinuedFraction[ Table[1 + I, {n}]]]], {n, 30}]`. + +## Encoding + +* *Gaussian rationals.* `x + y i` with `x y : ℚ` is the pair `(x, y) : ℚ × ℚ`; `gadd` is the sum + and `ginv` the reciprocal `1/(x + y i) = (x - y i)/(x² + y²)` (only ever applied to nonzero + numbers here: every convergent has real part `≥ 1`, as `Re(1/z) > 0` when `Re z > 0`). +* *Convergents.* `cfValue [x₁, …, xₙ] = x₁ + 1/(x₂ + 1/(⋯ + 1/xₙ))` is Mathematica's + `FromContinuedFraction`, and the `n`-th convergent is `conv n = cfValue (replicate n (1 + i))` + for `n ≥ 1` (`conv 1 = 1 + i`, `conv 2 = (3 + i)/2`, `conv 3 = (8 + 4i)/5`, as in the entry's + examples). `conv 0` (empty continued fraction) is outside the sequence and never used. +* *Numerator and denominator.* The entry's examples write each convergent as + `(A093725(n) + a(n) i)/A093727(n)`, e.g. "(6+3*i)/4, so A093725(4)=6, a(4)=3 and + A093727(4)=4": this is Mathematica's `Numerator`/`Denominator` of a Gaussian rational + `z = x + y i`, namely the least `d ≥ 1` with `d z ∈ ℤ[i]` (`gden z = lcm(den x, den y)`, + A093727) and the Gaussian integer `d z` (whose imaginary part `gnumIm z = d y` is `a(n)`). + So `a n = gnumIm (conv n)` and `A093727 n = gden (conv n)`, both read off the reduced + `Rat` parts. This reading matches the program `Im[Numerator[…]]`, the examples, and all + listed terms. (The other conceivable reading of the name, the reduced numerator of + `Im(conv n)`, gives the same listed terms but first differs at `n = 42`, where + `den (Im (conv 42)) < lcm(den (Re (conv 42)), den (Im (conv 42)))`; it is not used.) +* `a` is `ℤ`-valued (the numerator of a rational), so nothing is truncated. +* `A317974` and `A138573` are the order-4 recurrences `u(n) = 2(u(n-1) + u(n-2) + u(n-3)) - u(n-4)` + with initial terms `0, 0, 1, 1` resp. `0, 1, 2, 5` (offset `0` for both), taken in `ℤ`. +* `a_data` checks all 30 listed terms of A093726 in the kernel; `A093727_data`, `A317974_data`, + `A138573_data` check listed terms of the cross-referenced sequences. +* The conjecture is stated for every `n ≥ 1` (the offset of A093726 and A093727) as an equality + of rational numbers `a(n)/A093727(n) = A317974(n+1)/A138573(n)` (with Lean's `x / 0 = 0` + convention; the denominators are positive anyway). +-/ + +namespace Math0.Statements.A093726 + +/-- Sum of Gaussian rationals `(x + y i) + (x' + y' i)`, written as pairs `(x, y)`. -/ +def gadd (z w : ℚ × ℚ) : ℚ × ℚ := (z.1 + w.1, z.2 + w.2) + +/-- Reciprocal of a Gaussian rational: `1/(x + y i) = x/(x² + y²) - (y/(x² + y²)) i`. -/ +def ginv (z : ℚ × ℚ) : ℚ × ℚ := + (z.1 / (z.1 * z.1 + z.2 * z.2), -z.2 / (z.1 * z.1 + z.2 * z.2)) + +/-- The value of the finite continued fraction `x₁ + 1/(x₂ + 1/(⋯ + 1/xₙ))` of Gaussian rationals +(Mathematica's `FromContinuedFraction`); the empty list gets the junk value `0`. -/ +def cfValue : List (ℚ × ℚ) → ℚ × ℚ + | [] => (0, 0) + | [x] => x + | x :: xs => gadd x (ginv (cfValue xs)) + +/-- The `n`-th convergent `(1+i) + 1/((1+i) + 1/(⋯ + 1/(1+i)))` (`n` partial quotients `1 + i`), +for `n ≥ 1`. -/ +def conv (n : ℕ) : ℚ × ℚ := cfValue (List.replicate n (1, 1)) + +/-- Mathematica's `Denominator` of a Gaussian rational `z = x + y i`: the least `d ≥ 1` with +`d z ∈ ℤ[i]`, i.e. `lcm(den x, den y)`. -/ +def gden (z : ℚ × ℚ) : ℕ := Nat.lcm z.1.den z.2.den + +/-- The imaginary part of Mathematica's `Numerator` of a Gaussian rational `z = x + y i`: the +imaginary part `d y` of the Gaussian integer `d z`, where `d = gden z`. -/ +def gnumIm (z : ℚ × ℚ) : ℤ := z.2.num * ((gden z / z.2.den : ℕ) : ℤ) + +/-- A093726: the numerator of the imaginary part of the `n`-th convergent of +`(1+i) + 1/((1+i) + 1/((1+i) + ⋯))`, i.e. `Im(Numerator(conv n))` (offset `1`). -/ +def a (n : ℕ) : ℤ := gnumIm (conv n) + +/-- A093727: the denominator of the `n`-th convergent of `(1+i) + 1/((1+i) + ⋯)` (offset `1`). -/ +def A093727 (n : ℕ) : ℕ := gden (conv n) + +/-- A317974: `u(n) = 2(u(n-1) + u(n-2) + u(n-3)) - u(n-4)` for `n ≥ 4`, with initial terms +`0, 0, 1, 1` (offset `0`). -/ +def A317974 : ℕ → ℤ + | 0 => 0 + | 1 => 0 + | 2 => 1 + | 3 => 1 + | n + 4 => 2 * (A317974 (n + 3) + A317974 (n + 2) + A317974 (n + 1)) - A317974 n + +/-- A138573: `u(n) = 2u(n-1) + 2u(n-2) + 2u(n-3) - u(n-4)` for `n ≥ 4`, with initial terms +`0, 1, 2, 5` (offset `0`). -/ +def A138573 : ℕ → ℤ + | 0 => 0 + | 1 => 1 + | 2 => 2 + | 3 => 5 + | n + 4 => 2 * A138573 (n + 3) + 2 * A138573 (n + 2) + 2 * A138573 (n + 1) - A138573 n + +/-- The definition reproduces the 30 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 30).map (fun i => a (i + 1)) = + [1, 1, 4, 3, 11, 97, 280, 101, 2337, 2251, 19516, 14101, 163009, 16245, 30256, + 245929, 11371969, 32865601, 94983348, 22875581, 19349753, 2292794785, + 6626299912, 2393795271, 2635503517, 159951677089, 462268926316, 11517086141, + 3861059617665, 247970431013] := by + decide +kernel + +/-- The companion denominators reproduce the 28 terms listed in A093727 (kernel-checked). -/ +theorem A093727_data : (List.range 28).map (fun i => A093727 (i + 1)) = + [1, 2, 5, 4, 15, 130, 377, 136, 3145, 3030, 26269, 18980, 219413, 21866, 40725, + 331024, 15306833, 44237570, 127848949, 30790860, 26045045, 3086134658, 8919094697, + 3222082760, 3547425525, 215297250946, 622220603405, 15502163092] := by + decide +kernel + +/-- The first listed terms of A317974 (kernel-checked). -/ +theorem A317974_data : (List.range 20).map A317974 = + [0, 0, 1, 1, 4, 12, 33, 97, 280, 808, 2337, 6753, 19516, 56404, 163009, 471105, + 1361520, 3934864, 11371969, 32865601] := by + decide +kernel + +/-- The first listed terms of A138573 (kernel-checked). -/ +theorem A138573_data : (List.range 20).map A138573 = + [0, 1, 2, 5, 16, 45, 130, 377, 1088, 3145, 9090, 26269, 75920, 219413, 634114, + 1832625, 5296384, 15306833, 44237570, 127848949] := by + decide +kernel + +/-- Conjecture (Zhuorui He, A093726): for every `n ≥ 1`, +`a(n)/A093727(n) = A317974(n+1)/A138573(n)`, i.e. the imaginary part of the `n`-th convergent of +`(1+i) + 1/((1+i) + ⋯)` is `A317974(n+1)/A138573(n)`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + (a n : ℚ) / (A093727 n : ℚ) = (A317974 (n + 1) : ℚ) / (A138573 n : ℚ) + +end Math0.Statements.A093726 diff --git a/lean/Math0/Statements/OEIS/A097154.lean b/lean/Math0/Statements/OEIS/A097154.lean new file mode 100644 index 0000000..a9a1da0 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A097154.lean @@ -0,0 +1,208 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A097154: 0 and 89 are the only fixed points of reverse(x) - maxdigit(x) + +Source: https://oeis.org/A097154, Jason Earls, Aug 01 2004 (COMMENTS section). Verbatim: +> a(89)=-1 because 89 is the first number that will not reach zero: 98-9=89. It is conjectured +> that 0 and 89 are the only fixed points of f. + +The entry's name: "Number of iterations of f(x) = reverse(x) - maxdigit(x) needed to reach zero, +or -1 if zero is never reached, where maxdig(n) is the largest digit of n." Offset `1`; keyword +`sign` (the value `-1` occurs). The same conjecture is repeated in A097155 and A097157. + +## Encoding + +* `rev x` is the decimal reversal of `x`: `Nat.ofDigits 10 (Nat.digits 10 x).reverse`, so + trailing zeros of `x` become dropped leading zeros (`rev 120 = 21`) and `rev 0 = 0`. +* `maxDigit x` is the largest decimal digit of `x` (`maxDigit 0 = 0`, the digit of `0`). +* `f x = rev x - maxDigit x`. This is truncated subtraction on `ℕ`, but it never truncates: + `maxDigit_le_rev` proves `maxDigit x ≤ rev x`, and `f_eq_int` restates `f` with integer + subtraction. So `f` is the entry's map on the nonnegative integers (with `f 0 = 0`). +* The sequence (offset `1`, values in `ℤ` because of `-1`): `a n` is the least `k` with + `f^[k] n = 0`, or `-1` if there is none. To keep `a` computable it searches only + `k ≤ 10 ^ d`, where `d` is the number of digits of `n`. `a_spec` proves this is no restriction: + `a n = if h : ∃ k, f^[k] n = 0 then Nat.find h else -1`. The reason is that `f` maps + `[0, 10^d)` into itself, and the iterates before the first `0` are pairwise distinct. + `a_data` kernel-checks all 127 listed terms `a 1, …, a 127`, including `a 89 = -1`. +* The conjecture: for every `x ≥ 0`, `f x = x` holds iff `x = 0` or `x = 89`. +-/ + +namespace Math0.Statements.A097154 + +/-- `reverse(x)`: the number whose decimal digits are those of `x` in reverse order +(`rev 120 = 21`, `rev 0 = 0`). -/ +def rev (x : ℕ) : ℕ := Nat.ofDigits 10 (Nat.digits 10 x).reverse + +/-- `maxdigit(x)`: the largest decimal digit of `x` (`maxDigit 0 = 0`). -/ +def maxDigit (x : ℕ) : ℕ := (Nat.digits 10 x).foldr max 0 + +/-- `f(x) = reverse(x) - maxdigit(x)`. (The subtraction never truncates; see +`maxDigit_le_rev`.) -/ +def f (x : ℕ) : ℕ := rev x - maxDigit x + +theorem le_ofDigits_of_mem : ∀ (l : List ℕ) (d : ℕ), d ∈ l → d ≤ Nat.ofDigits 10 l + | [], d, h => by simp at h + | e :: l, d, h => by + rw [Nat.ofDigits_cons] + rcases List.mem_cons.1 h with rfl | h + · omega + · have := le_ofDigits_of_mem l d h + omega + +theorem foldr_max_le : ∀ (l : List ℕ) (c : ℕ), (∀ d ∈ l, d ≤ c) → l.foldr max 0 ≤ c + | [], c, _ => Nat.zero_le c + | e :: l, c, h => by + simp only [List.foldr_cons] + exact max_le (h e List.mem_cons_self) + (foldr_max_le l c fun d hd => h d (List.mem_cons_of_mem e hd)) + +/-- The largest digit never exceeds the reversal, so `f` is an honest subtraction. -/ +theorem maxDigit_le_rev (x : ℕ) : maxDigit x ≤ rev x := + foldr_max_le _ _ fun d hd => le_ofDigits_of_mem _ d (List.mem_reverse.2 hd) + +/-- `f x = reverse(x) - maxdigit(x)` as an integer. -/ +theorem f_eq_int (x : ℕ) : (f x : ℤ) = (rev x : ℤ) - (maxDigit x : ℤ) := by + have := maxDigit_le_rev x + simp only [f] + omega + +/-- The entry's example `12 → 19 → 82 → 20 → 0`, and the fixed points `0` and `89` +(`98 - 9 = 89`). -/ +theorem f_examples : + f 12 = 19 ∧ f 19 = 82 ∧ f 82 = 20 ∧ f 20 = 0 ∧ f 0 = 0 ∧ rev 89 = 98 ∧ maxDigit 89 = 9 ∧ + f 89 = 89 := by + decide +kernel + +/-- `search x k fuel` follows the orbit `x, f x, f (f x), …` for at most `fuel` steps. It returns +`k + j` for the least `j ≤ fuel` with `f^[j] x = 0`, and `-1` if there is no such `j`. -/ +def search : ℕ → ℕ → ℕ → ℤ + | x, k, 0 => if x = 0 then (k : ℤ) else -1 + | x, k, fuel + 1 => if x = 0 then (k : ℤ) else search (f x) (k + 1) fuel + +/-- A097154 (offset `1`): the number of iterations of `f` needed to reach zero, or `-1` if zero +is never reached. The search bound `10 ^ (number of digits of n)` loses nothing (`a_spec`). -/ +def a (n : ℕ) : ℤ := search n 0 (10 ^ (Nat.digits 10 n).length) + +/-- The definition reproduces all 127 terms listed in OEIS, `a 1, …, a 127` (kernel-checked). -/ +theorem a_data : (List.range 127).map (fun i => a (i + 1)) = + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 4, 4, 5, 3, 3, 3, 3, 1, 2, 2, 4, 4, 6, 5, 3, 3, 3, 1, 2, + 2, 2, 4, 4, 7, 3, 3, 3, 1, 2, 2, 2, 2, 4, 4, 5, 3, 3, 1, 2, 2, 2, 2, 2, 4, 6, 3, 3, 1, 2, 2, + 2, 2, 2, 2, 4, 5, 3, 1, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, 2, 2, 2, 2, 2, 2, 2, 2, -1, 1, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 6, 6, 9, 7, 8, 8, 10, 7, 2, 3, 10, 7, 8, 9, 3, 3, 3, 3, 4, 4, 4, 4, + 4, 8, 4, 4] := by + decide +kernel + +/-! ### The search bound is no restriction -/ + +theorem search_of_zero : ∀ (fuel x k j : ℕ), j ≤ fuel → f^[j] x = 0 → + (∀ i < j, f^[i] x ≠ 0) → search x k fuel = ((k + j : ℕ) : ℤ) := by + intro fuel + induction fuel with + | zero => + intro x k j hj hz _ + obtain rfl : j = 0 := by omega + simp only [Function.iterate_zero, id_eq] at hz + simp [search, hz] + | succ fuel ih => + intro x k j hj hz hmin + by_cases hx : x = 0 + · have hj0 : j = 0 := by + by_contra hne + exact hmin 0 (Nat.pos_of_ne_zero hne) (by simpa using hx) + subst hj0 + simp [search, hx] + · obtain ⟨j, rfl⟩ : ∃ j', j = j' + 1 := by + rcases j with _ | j + · simp at hz + exact absurd hz hx + · exact ⟨j, rfl⟩ + rw [search, if_neg hx] + rw [Function.iterate_succ_apply] at hz + rw [ih (f x) (k + 1) j (by omega) hz fun i hi => by + have := hmin (i + 1) (by omega) + rwa [Function.iterate_succ_apply] at this] + push_cast + ring + +theorem search_of_ne : ∀ (fuel x k : ℕ), (∀ i ≤ fuel, f^[i] x ≠ 0) → search x k fuel = -1 := by + intro fuel + induction fuel with + | zero => + intro x k h + have := h 0 le_rfl + simp only [Function.iterate_zero, id_eq] at this + simp [search, this] + | succ fuel ih => + intro x k h + have hx := h 0 (Nat.zero_le _) + simp only [Function.iterate_zero, id_eq] at hx + rw [search, if_neg hx] + exact ih (f x) (k + 1) fun i hi => by + have := h (i + 1) (by omega) + rwa [Function.iterate_succ_apply] at this + +theorem f_lt {x L : ℕ} (h : x < 10 ^ L) : f x < 10 ^ L := by + have h1 : rev x < 10 ^ (Nat.digits 10 x).length := by + have := Nat.ofDigits_lt_base_pow_length (b := 10) (l := (Nat.digits 10 x).reverse) + (by norm_num) (fun d hd => Nat.digits_lt_base (by norm_num) (List.mem_reverse.1 hd)) + simpa [rev] using this + have h2 : (Nat.digits 10 x).length ≤ L := (Nat.digits_length_le_iff (by norm_num) x).2 h + have h3 : 10 ^ (Nat.digits 10 x).length ≤ 10 ^ L := Nat.pow_le_pow_right (by norm_num) h2 + unfold f + omega + +theorem iterate_lt {x L : ℕ} (h : x < 10 ^ L) : ∀ i, f^[i] x < 10 ^ L + | 0 => h + | i + 1 => by + rw [Function.iterate_succ_apply'] + exact f_lt (iterate_lt h i) + +/-- If the orbit of `n` reaches `0`, it does so within `10 ^ (number of digits of n)` steps. -/ +theorem find_lt {n : ℕ} (h : ∃ k, f^[k] n = 0) : + Nat.find h < 10 ^ (Nat.digits 10 n).length := by + have hn : n < 10 ^ (Nat.digits 10 n).length := Nat.lt_base_pow_length_digits (by norm_num) + have hk0 : f^[Nat.find h] n = 0 := Nat.find_spec h + have key : ∀ i j, i < j → j ≤ Nat.find h → f^[i] n = f^[j] n → False := by + intro i j hij hj he + have e : f^[Nat.find h] n = f^[Nat.find h - j + i] n := by + rw [show Nat.find h = Nat.find h - j + j by omega, Function.iterate_add_apply, ← he, + ← Function.iterate_add_apply] + congr 1 + omega + exact Nat.find_min h (m := Nat.find h - j + i) (by omega) (e ▸ hk0) + have hcard := Finset.card_le_card_of_injOn (fun i => f^[i] n) + (s := Finset.range (Nat.find h + 1)) (t := Finset.range (10 ^ (Nat.digits 10 n).length)) + (fun i _ => by + simp only [Finset.coe_range, Set.mem_Iio] + exact iterate_lt hn i) + (by + intro i hi j hj hij + simp only [Finset.coe_range, Set.mem_Iio] at hi hj + by_contra hne + rcases Nat.lt_or_gt_of_ne hne with hlt | hlt + · exact key i j hlt (by omega) hij + · exact key j i hlt (by omega) hij.symm) + simp only [Finset.card_range] at hcard + omega + +open Classical in +/-- `a` is the OEIS definition: the least `k` with `f^[k] n = 0`, or `-1` if there is none. -/ +theorem a_spec (n : ℕ) : a n = if h : ∃ k, f^[k] n = 0 then (Nat.find h : ℤ) else -1 := by + unfold a + split_ifs with h + · rw [search_of_zero _ n 0 (Nat.find h) (find_lt h).le (Nat.find_spec h) + fun i hi => Nat.find_min h hi] + simp + · simp only [not_exists] at h + exact search_of_ne _ n 0 fun i _ => h i + +/-- The conjecture (Earls): `0` and `89` are the only fixed points of +`f(x) = reverse(x) - maxdigit(x)` on the nonnegative integers. -/ +def statement : Prop := + ∀ x : ℕ, f x = x ↔ x = 0 ∨ x = 89 + +end Math0.Statements.A097154 diff --git a/lean/Math0/Statements/OEIS/A106505.lean b/lean/Math0/Statements/OEIS/A106505.lean new file mode 100644 index 0000000..7270ce7 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A106505.lean @@ -0,0 +1,222 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A106505: side common to angles `A` and `2A` in primitive integer triangles + +Source: https://oeis.org/A106505, Ralf Stephan, Nov 16 2010 (FORMULA section). Verbatim: +> Conjecture: for n>2, a(n+5) = a(n) + 8. + +The entry (Lekraj Beedassy, May 04 2005, offset `1`) is "Ordered and uniqued length of side +common to the two angles, one being the double of the other, of a primitive integer-sided +triangle." Data: `5, 7, 9, 11, 13, 15, 16, 17, 19, 21, 23, 24, 25, …, 111, 112`. + +## Encoding + +* *Angles of a triangle.* For a triangle with side lengths `p, q, r`, the angle opposite the side + `p` is `arccos ((q² + r² - p²) / (2 q r))` (law of cosines; this is the unoriented angle in + `[0, π]`, as for `EuclideanGeometry.angle`). This is `angleOpp p q r`. +* *Triangles with one angle the double of another.* `IsDoubleAngleTriangle x y c`: the natural + numbers `x, y, c` satisfy the strict triangle inequalities (a non-degenerate triangle; this + forces `x, y, c ≥ 1`), and the angle opposite `y` is twice the angle opposite `x`. The side + `c` joins the vertices of these two angles, so it is the side common to them. Every triangle + with two angles, one the double of the other, arises this way (name the side opposite the + smaller angle `x`, the side opposite the larger one `y`). +* *Primitive.* `gcd(x, y, c) = 1`. +* `IsSide c`: there are `x, y` with `IsDoubleAngleTriangle x y c` and `gcd(x, y, c) = 1`. + "Ordered and uniqued": `a n = Nat.nth IsSide (n - 1)` is the `n`-th smallest element of + `{c | IsSide c}` (offset `1`), noncomputable as written. +* *Decidability.* `isDoubleAngleTriangle_iff` proves (via the double-angle formula + `cos 2α = 2 cos² α - 1`) that the angle condition is equivalent to the classical metric + relation `y² = x (x + c)`. Writing `y = x + d`, this becomes `x (c - 2d) = d²` with + `0 < d`, `2d < c`, so `x` is determined by `d < c` (`isSide_iff`). This gives a + `DecidablePred IsSide` instance, and `a_data` checks all 67 listed terms (all members + `< 113`) by a kernel-checked `List.filter`. (The entry's formula "Values s^2 - r^2, where + r 2` (`n` is 1-indexed as in + the entry; it fails for `n = 1, 2`). +-/ + +namespace Math0.Statements.A106505 + +/-! ### Definitions -/ + +/-- The angle opposite the side of length `p` in a triangle with side lengths `p, q, r`, by the +law of cosines: `arccos ((q² + r² - p²) / (2 q r))`. -/ +noncomputable def angleOpp (p q r : ℝ) : ℝ := + Real.arccos ((q ^ 2 + r ^ 2 - p ^ 2) / (2 * q * r)) + +/-- `x, y, c` are the side lengths of a non-degenerate triangle in which the angle opposite `y` +is twice the angle opposite `x`. The side `c` is the side common to these two angles. -/ +def IsDoubleAngleTriangle (x y c : ℕ) : Prop := + x < y + c ∧ y < x + c ∧ c < x + y ∧ + angleOpp (y : ℝ) (x : ℝ) (c : ℝ) = 2 * angleOpp (x : ℝ) (y : ℝ) (c : ℝ) + +/-- `c` is the length of the side common to the two angles, one being the double of the other, +of a primitive integer-sided triangle. -/ +def IsSide (c : ℕ) : Prop := + ∃ x y : ℕ, IsDoubleAngleTriangle x y c ∧ Nat.gcd (Nat.gcd x y) c = 1 + +/-! ### Decidability -/ + +/-- For a non-degenerate triangle, the angle opposite `y` is twice the angle opposite `x` iff +`y² = x (x + c)`. -/ +theorem isDoubleAngleTriangle_iff (x y c : ℕ) : + IsDoubleAngleTriangle x y c ↔ + x < y + c ∧ y < x + c ∧ c < x + y ∧ y * y = x * (x + c) := by + unfold IsDoubleAngleTriangle + refine and_congr_right fun h1 => and_congr_right fun h2 => and_congr_right fun h3 => ?_ + have hx : (0 : ℝ) < x := by exact_mod_cast (show 0 < x by omega) + have hy : (0 : ℝ) < y := by exact_mod_cast (show 0 < y by omega) + have hc : (0 : ℝ) < c := by exact_mod_cast (show 0 < c by omega) + have r1 : (x : ℝ) < y + c := by exact_mod_cast h1 + have r2 : (y : ℝ) < x + c := by exact_mod_cast h2 + have r3 : (c : ℝ) < x + y := by exact_mod_cast h3 + have hcast : y * y = x * (x + c) ↔ (y : ℝ) * y = x * (x + c) := by + constructor + · intro h; exact_mod_cast h + · intro h; exact_mod_cast h + rw [hcast] + unfold angleOpp + generalize (x : ℝ) = X at * + generalize (y : ℝ) = Y at * + generalize (c : ℝ) = C at * + have hu1 : -1 ≤ (X ^ 2 + C ^ 2 - Y ^ 2) / (2 * X * C) := by + rw [le_div_iff₀ (by positivity)]; nlinarith + have hu2 : (X ^ 2 + C ^ 2 - Y ^ 2) / (2 * X * C) ≤ 1 := by + rw [div_le_iff₀ (by positivity)]; nlinarith + have hv1 : -1 ≤ (Y ^ 2 + C ^ 2 - X ^ 2) / (2 * Y * C) := by + rw [le_div_iff₀ (by positivity)]; nlinarith + have hv2 : (Y ^ 2 + C ^ 2 - X ^ 2) / (2 * Y * C) ≤ 1 := by + rw [div_le_iff₀ (by positivity)]; nlinarith + constructor + · intro h + have h' := congrArg Real.cos h + rw [Real.cos_arccos hu1 hu2, Real.cos_two_mul, Real.cos_arccos hv1 hv2] at h' + field_simp at h' + have key : (C + X) * (X - Y - C) * (X + Y - C) * (C * X + X ^ 2 - Y ^ 2) = 0 := by + linear_combination -h' + have hA : (C + X) * (X - Y - C) * (X + Y - C) ≠ 0 := by + have : (C + X) * (X - Y - C) * (X + Y - C) < 0 := by + have h4 : 0 < (C + X) * (X + Y - C) := by nlinarith + nlinarith + exact this.ne + have := (mul_eq_zero.1 key).resolve_left hA + linear_combination -this + · intro h + have hv0 : 0 ≤ (Y ^ 2 + C ^ 2 - X ^ 2) / (2 * Y * C) := by + apply div_nonneg _ (by positivity) + nlinarith + have hcos : (X ^ 2 + C ^ 2 - Y ^ 2) / (2 * X * C) = + Real.cos (2 * Real.arccos ((Y ^ 2 + C ^ 2 - X ^ 2) / (2 * Y * C))) := by + rw [Real.cos_two_mul, Real.cos_arccos hv1 hv2] + field_simp + linear_combination (C + X) * (X - Y - C) * (X + Y - C) * h + rw [hcos, Real.arccos_cos + (by linarith [Real.arccos_nonneg ((Y ^ 2 + C ^ 2 - X ^ 2) / (2 * Y * C))]) + (by linarith [Real.arccos_le_pi_div_two.2 hv0])] + +/-- `IsSide c` is decided by a search over `d = y - x < c`: then `x = d² / (c - 2d)`. -/ +theorem isSide_iff (c : ℕ) : IsSide c ↔ + ∃ d < c, 0 < d ∧ 2 * d < c ∧ d * d % (c - 2 * d) = 0 ∧ + c < d * d / (c - 2 * d) + (d * d / (c - 2 * d) + d) ∧ + Nat.gcd (Nat.gcd (d * d / (c - 2 * d)) (d * d / (c - 2 * d) + d)) c = 1 := by + constructor + · rintro ⟨x, y, h, hg⟩ + obtain ⟨h1, h2, h3, hyy⟩ := (isDoubleAngleTriangle_iff x y c).1 h + have hx : 0 < x := by omega + have hc : 0 < c := by omega + have hxy : x < y := by + by_contra hle + replace hle : y ≤ x := by omega + have := Nat.mul_le_mul hle hle + have : x * x < x * (x + c) := Nat.mul_lt_mul_of_pos_left (by omega) hx + omega + obtain ⟨d, rfl⟩ : ∃ d, y = x + d := ⟨y - x, by omega⟩ + have hd : 0 < d := by omega + have hrel : x * c = x * (2 * d) + d * d := by + have : (x + d) * (x + d) = x * x + x * (2 * d) + d * d := by ring + have : x * (x + c) = x * x + x * c := by ring + omega + have h2d : 2 * d < c := by + have : x * (2 * d) < x * c := by + have : 0 < d * d := Nat.mul_pos hd hd + omega + exact Nat.lt_of_mul_lt_mul_left this + have hdd : d * d = (c - 2 * d) * x := by + rw [Nat.sub_mul, Nat.mul_comm c x, Nat.mul_comm (2 * d) x] + omega + have hpos : 0 < c - 2 * d := by omega + have hdiv : d * d / (c - 2 * d) = x := by + rw [hdd, Nat.mul_div_cancel_left _ hpos] + refine ⟨d, by omega, hd, h2d, ?_, ?_, ?_⟩ + · rw [hdd, Nat.mul_mod_right] + · rw [hdiv]; omega + · rw [hdiv]; exact hg + · rintro ⟨d, -, hd, h2d, hmod, h3, hg⟩ + set x := d * d / (c - 2 * d) with hxdef + have hpos : 0 < c - 2 * d := by omega + have hx : x * (c - 2 * d) = d * d := Nat.div_mul_cancel (Nat.dvd_of_mod_eq_zero hmod) + refine ⟨x, x + d, (isDoubleAngleTriangle_iff _ _ _).2 ⟨by omega, by omega, h3, ?_⟩, hg⟩ + have hsub : ((c - 2 * d : ℕ) : ℤ) = (c : ℤ) - 2 * d := by + rw [Nat.cast_sub (by omega)]; push_cast; ring + have hxz : (x : ℤ) * ((c : ℤ) - 2 * d) = (d : ℤ) * d := by + rw [← hsub]; exact_mod_cast hx + have : ((x + d : ℕ) : ℤ) * (x + d : ℕ) = (x : ℤ) * ((x + c : ℕ) : ℤ) := by + push_cast + linear_combination -hxz + exact_mod_cast this + +instance : DecidablePred IsSide := fun c => decidable_of_iff _ (isSide_iff c).symm + +/-! ### The sequence -/ + +/-- A106505: the `n`-th smallest (offset `1`) length of the side common to the two angles, one +being the double of the other, of a primitive integer-sided triangle. -/ +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsSide (n - 1) + +/-- The elements `< N` satisfying `p`, in increasing order, are `nth p 0, nth p 1, …`. -/ +theorem filter_range_eq (p : ℕ → Prop) [DecidablePred p] (N : ℕ) : + (List.range N).filter (fun k => decide (p k)) = + (List.range (Nat.count p N)).map (Nat.nth p) := by + induction N with + | zero => simp + | succ N ih => + rw [List.range_succ, List.filter_append, ih, Nat.count_succ] + by_cases h : p N + · simp [h, List.range_succ, Nat.nth_count h] + · simp [h] + +theorem map_nth_eq_of_filter {p : ℕ → Prop} [DecidablePred p] {N K : ℕ} {L : List ℕ} + (h : (List.range N).filter (fun k => decide (p k)) = L) (hK : L.length = K) : + (List.range K).map (Nat.nth p) = L := by + rw [filter_range_eq] at h + subst h + simp only [List.length_map, List.length_range] at hK + rw [hK] + +/-- The entry's example: `(x, y, c) = (16, 28, 33)` and `(256, 272, 33)` are two primitive +triangles in which the angle opposite `y` is twice the angle opposite `x`, both with common +side `33` (the entry lists the sides as `(33, 28, 16)` and `(33, 272, 256)`). -/ +theorem example_33 : + IsDoubleAngleTriangle 16 28 33 ∧ IsDoubleAngleTriangle 256 272 33 := by + rw [isDoubleAngleTriangle_iff, isDoubleAngleTriangle_iff] + decide + +/-- The definition reproduces all 67 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 67).map (fun i => a (i + 1)) = + [5, 7, 9, 11, 13, 15, 16, 17, 19, 21, 23, 24, 25, 27, 29, 31, 32, 33, 35, 37, 39, 40, 41, 43, + 45, 47, 48, 49, 51, 53, 55, 56, 57, 59, 61, 63, 64, 65, 67, 69, 71, 72, 73, 75, 77, 79, 80, + 81, 83, 85, 87, 88, 89, 91, 93, 95, 96, 97, 99, 101, 103, 104, 105, 107, 109, 111, 112] := by + have : (fun i => a (i + 1)) = Nat.nth IsSide := funext fun i => by simp [a] + rw [this] + exact map_nth_eq_of_filter (N := 113) (by decide +kernel) rfl + +/-! ### The conjecture -/ + +/-- Conjecture (Stephan, A106505): for `n > 2`, `a(n + 5) = a(n) + 8`. -/ +def statement : Prop := ∀ n : ℕ, 2 < n → a (n + 5) = a n + 8 + +end Math0.Statements.A106505 diff --git a/lean/Math0/Statements/OEIS/A113676.lean b/lean/Math0/Statements/OEIS/A113676.lean new file mode 100644 index 0000000..5e045e3 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A113676.lean @@ -0,0 +1,483 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A113676: Golomb's sequence (one 2 removed) cut into a triangle, and Levine's sequence + +Source: https://oeis.org/A113676, Floor van Lamoen and Paul D. Hanna, Nov 06 2005 (COMMENTS +section). Verbatim: +> Conjecture: a(n) for n>1 gives first differences of Lionel Levine's sequence A014644(n) for n>=3. +> Conjecture: Final elements of the rows form A014644 except for duplicate 2. + +The entry's name: "Number of elements of rows of Golomb's sequence A001462, with one less 2, +interpreted as triangle: Start with first row 1. The row sum of row n-1 gives the number of +elements taken from A001642 (one less 2) of row n." ("A001642" is a typo for A001462: the +example rows `1; 2; 3,3; 4,4,4,5,5,5; …` are Golomb's sequence `1, 2, 2, 3, 3, 4, …` with one +`2` removed.) Offset `1`; the listed terms are `1, 1, 2, 6, 27, 234, 6202, 1084009, 4362192095`. + +## Encoding + +* Golomb's sequence A001462 ("a(n) is the number of times n occurs in the sequence, starting + with a(1) = 1", nondecreasing) is `golomb` (offset `1`; `golomb 0 = 0` is a junk value). It is + computed by its self-generating construction `golombAux`: start from `1, 2, 2` and, for + `k = 3, 4, …`, append `k` repeated `G(k)` times, where `G(k)` is read off the list built so far. + `golombAux_eq_flatMap` proves that every stage is `1^G(1) 2^G(2) ⋯ (m+2)^G(m+2)` (each `k` + repeated `golomb k` times, in increasing order), and `golomb_eq_getD` that `golomb` reads the + stages consistently: this is exactly the self-describing property of A001462. + `golomb_data` checks all 84 terms listed in A001462. +* `H` is Golomb's sequence with one less `2`: `H 1 = 1` and `H j = golomb (j + 1)` for `j ≥ 2`, + i.e. `1, 2, 3, 3, 4, 4, 4, 5, 5, 5, …` (both `2`s are equal, so it does not matter which one + is deleted). +* The triangle: `rowEnd n` is the number of terms of `H` used by rows `1, …, n`, and + `row n` is the list of consecutive terms `H j` with `rowEnd (n - 1) < j ≤ rowEnd n`. Row `1` + has one element, and the number of elements of row `n + 2` is the sum of row `n + 1` + (`row_one`, `length_row_succ_succ`). `rows_example` checks the four rows shown in the entry. + The sequence is `a n = (row n).length` (offset `1`); `a_data` kernel-checks all 9 listed terms + `a 1, …, a 9`. (Rows `1, …, 7` use `H 1, …, H 6473`, and row `8` ends at `H 1090482`. To make + this checkable, the proofs read Golomb's sequence from the faster `golombFast`, which is proved + to give prefixes of `golomb` (`golombFast_eq_golombAux`, `map_H_range'`, `rowPairL_eq`); `a 9` + is obtained from a weighted sum of the first `6474` terms (`a_nine`).) `rowLast_data` checks + that the last elements of rows `1, …, 7` are `1, 2, 3, 5, 11, 38, 272`. +* Levine's sequence A014644 ("Form array starting with {1,1}; then i-th term in a row gives + number of i's in next row; sequence is formed from final term in each row.", offset `1`): + `levineRow 1 = [1, 1]`, and `levineRow (k + 1)` lists `1` `c₁` times, then `2` `c₂` times, …, + where `levineRow k = [c₁, c₂, …]` (in increasing order, as in A014643, whose row 5 is + `1,2,2,3,3,4,4,4,5,5,5`). `A014644 k` is the final term of `levineRow k`. `A014644_data` + kernel-checks the first 11 listed terms `1, 2, 2, 3, 5, 11, 38, 272, 6474, 1090483, + 4363282578`. +* First conjecture: "a(n) for n>1 gives first differences of A014644(n) for n>=3" is read as + `a n = A014644 (n + 2) - A014644 (n + 1)` for every `n ≥ 2` (so `a 2` is the first difference + `A014644 4 - A014644 3` of A014644 taken from its third term on). It is stated in `ℤ`, so the + subtraction is the true difference. +* Second conjecture: the final elements of rows `1, 2, 3, …` are A014644 `= 1, 2, 2, 3, 5, …` + with one of its two equal terms `A014644 2 = A014644 3 = 2` removed, i.e. the last element of + row `1` is `A014644 1` and the last element of row `n` is `A014644 (n + 1)` for every `n ≥ 2`. + "The last element of row `n` is `x`" is `(row n).getLast? = some x`. +* `statement` is the conjunction of the two conjectures. +-/ + +namespace Math0.Statements.A113676 + +/-! ### Golomb's sequence A001462 -/ + +/-- Self-generating construction of Golomb's sequence: start from `1, 2, 2` and, for +`k = 3, …, m + 2`, append `k` repeated `G(k)` times, where `G(k)` is the `k`-th term (list index +`k - 1`) of the list built so far. -/ +def golombAux : ℕ → List ℕ + | 0 => [1, 2, 2] + | m + 1 => golombAux m ++ List.replicate ((golombAux m).getD (m + 2) 0) (m + 3) + +/-- Golomb's sequence A001462 (offset `1`): `golomb (n + 1)` is the term at list index `n` of +`golombAux n`. (`golomb 0 = 0` is a junk value.) -/ +def golomb : ℕ → ℕ + | 0 => 0 + | n + 1 => (golombAux n).getD n 0 + +/-- Golomb's sequence with one less `2` (offset `1`): `1, 2, 3, 3, 4, 4, 4, 5, 5, 5, …`, i.e. +`H 1 = golomb 1 = 1` and `H j = golomb (j + 1)` for `j ≥ 2`. (`H 0 = 0` is a junk value.) -/ +def H (j : ℕ) : ℕ := if j ≤ 1 then golomb j else golomb (j + 1) + +/-! ### The triangle and A113676 -/ + +/-- `rowEnd n` is the number of terms of `H` used by rows `1, …, n` of the triangle: row `1` has +one element, and row `n + 2` has as many elements as the sum of row `n + 1`, which consists of +the terms `H j` with `rowEnd n < j ≤ rowEnd (n + 1)`. -/ +def rowEnd : ℕ → ℕ + | 0 => 0 + | 1 => 1 + | n + 2 => rowEnd (n + 1) + + ((List.range' (rowEnd n + 1) (rowEnd (n + 1) - rowEnd n)).map H).sum + +/-- Row `n` (`n ≥ 1`) of the triangle: the consecutive terms `H j`, +`rowEnd (n - 1) < j ≤ rowEnd n`. -/ +def row (n : ℕ) : List ℕ := + (List.range' (rowEnd (n - 1) + 1) (rowEnd n - rowEnd (n - 1))).map H + +/-- A113676 (offset `1`): the number of elements of row `n` of the triangle. -/ +def a (n : ℕ) : ℕ := (row n).length + +/-! ### Levine's sequence A014644 -/ + +/-- `levineAux [c₀, c₁, …, c_r] i` is `i` repeated `c₀` times, then `i + 1` repeated `c₁` times, +…, then `i + r` repeated `c_r` times. -/ +def levineAux : List ℕ → ℕ → List ℕ + | [], _ => [] + | c :: l, i => List.replicate c i ++ levineAux l (i + 1) + +/-- Row `k` (`k ≥ 1`) of Levine's array (A014643): row `1` is `[1, 1]`, and the `i`-th term of +row `k` is the number of `i`s in row `k + 1` (listed in increasing order). +(`levineRow 0 = []` is a junk value.) -/ +def levineRow : ℕ → List ℕ + | 0 => [] + | 1 => [1, 1] + | k + 2 => levineAux (levineRow (k + 1)) 1 + +/-- Lionel Levine's sequence A014644 (offset `1`): the final term of row `k` of Levine's +array. -/ +def A014644 (k : ℕ) : ℕ := (levineRow k).getLastD 0 + +/-! ### Basic facts about the definitions -/ + +theorem golombAux_succ (m : ℕ) : + golombAux (m + 1) = golombAux m ++ List.replicate ((golombAux m).getD (m + 2) 0) (m + 3) := + rfl + +theorem golombAux_prefix {m m' : ℕ} (h : m ≤ m') : golombAux m <+: golombAux m' := by + induction h with + | refl => exact List.prefix_refl _ + | step _ ih => exact ih.trans (List.prefix_append _ _) + +theorem golombAux_pos_length (m : ℕ) : + (∀ x ∈ golombAux m, 1 ≤ x) ∧ m + 3 ≤ (golombAux m).length := by + induction m with + | zero => decide + | succ m ih => + obtain ⟨hpos, hlen⟩ := ih + have hmem : (golombAux m).getD (m + 2) 0 ∈ golombAux m := by + rw [List.getD_eq_getElem _ _ (by omega)] + exact List.getElem_mem _ + have h1 := hpos _ hmem + refine ⟨?_, ?_⟩ + · intro x hx + rw [golombAux_succ, List.mem_append] at hx + rcases hx with hx | hx + · exact hpos x hx + · rw [List.eq_of_mem_replicate hx]; omega + · rw [golombAux_succ, List.length_append, List.length_replicate]; omega + +/-- `golomb` reads every stage of the construction consistently. -/ +theorem golomb_eq_getD {m j : ℕ} (hj : j < (golombAux m).length) : + golomb (j + 1) = (golombAux m).getD j 0 := by + show (golombAux j).getD j 0 = _ + have h1 : golombAux j <+: golombAux (max j m) := golombAux_prefix (le_max_left _ _) + have h2 : golombAux m <+: golombAux (max j m) := golombAux_prefix (le_max_right _ _) + have hj' : j < (golombAux j).length := by have := (golombAux_pos_length j).2; omega + rw [List.getD_eq_getElem _ _ hj', List.getD_eq_getElem _ _ hj, h1.getElem hj', h2.getElem hj] + +theorem golombAux_eq_map (m : ℕ) : + golombAux m = (List.range' 1 (golombAux m).length).map golomb := by + apply List.ext_getElem (by simp) + intro j h1 _ + rw [List.getElem_map, List.getElem_range', show 1 + 1 * j = j + 1 by ring, golomb_eq_getD h1, + List.getD_eq_getElem _ _ h1] + +theorem golombAux_succ' (m : ℕ) : + golombAux (m + 1) = golombAux m ++ List.replicate (golomb (m + 3)) (m + 3) := by + have h : m + 2 < (golombAux m).length := by have := (golombAux_pos_length m).2; omega + rw [golombAux_succ, show m + 3 = m + 2 + 1 from rfl, golomb_eq_getD h] + +/-- The self-describing property of Golomb's sequence: stage `m` of the construction lists +`1, 2, …, m + 2` in increasing order, each `k` repeated `golomb k` times. -/ +theorem golombAux_eq_flatMap (m : ℕ) : + golombAux m = (List.range' 1 (m + 2)).flatMap (fun k => List.replicate (golomb k) k) := by + induction m with + | zero => decide + | succ m ih => + rw [golombAux_succ', ih, show m + 1 + 2 = (m + 2) + 1 by omega, + List.range'_concat (s := 1) (n := m + 2), List.flatMap_append, List.flatMap_singleton, + show 1 + 1 * (m + 2) = m + 3 by omega] + +/-- Row `1` of the triangle is `[1]`. -/ +theorem row_one : row 1 = [1] := by decide + +/-- The number of elements of row `n + 2` is the sum of row `n + 1`. -/ +theorem length_row_succ_succ (n : ℕ) : (row (n + 2)).length = (row (n + 1)).sum := by + show ((List.range' (rowEnd (n + 1) + 1) (rowEnd (n + 2) - rowEnd (n + 1))).map H).length = + ((List.range' (rowEnd n + 1) (rowEnd (n + 1) - rowEnd n)).map H).sum + rw [List.length_map, List.length_range'] + show rowEnd (n + 1) + _ - rowEnd (n + 1) = _ + omega + +/-- The four rows shown in the entry (kernel-checked). -/ +theorem rows_example : + row 1 = [1] ∧ row 2 = [2] ∧ row 3 = [3, 3] ∧ row 4 = [4, 4, 4, 5, 5, 5] := by + decide +kernel + +theorem a_succ (n : ℕ) : a (n + 1) = rowEnd (n + 1) - rowEnd n := by + simp [a, row] + +theorem row_succ (n : ℕ) : + row (n + 1) = (List.range' (rowEnd n + 1) (rowEnd (n + 1) - rowEnd n)).map H := by + simp only [row, Nat.add_sub_cancel] + +theorem levineRow_add_two (k : ℕ) : levineRow (k + 2) = levineAux (levineRow (k + 1)) 1 := rfl + +/-! ### Fast evaluation (used only to check the data) -/ + +/-- Iterating `levineAux · 1` from `[1, 2, 2]` produces longer and longer prefixes of Golomb's +sequence (`golombFast_eq_golombAux`); `golombFast 5` has `6474` terms. -/ +def golombFast : ℕ → List ℕ + | 0 => [1, 2, 2] + | i + 1 => levineAux (golombFast i) 1 + +theorem levineAux_map (f : ℕ → ℕ) (n i : ℕ) : + levineAux ((List.range' i n).map f) i = + (List.range' i n).flatMap (fun k => List.replicate (f k) k) := by + induction n generalizing i with + | zero => rfl + | succ n ih => rw [List.range'_succ, List.map_cons, levineAux, ih, List.flatMap_cons] + +theorem levineAux_golombAux (m : ℕ) : + levineAux (golombAux m) 1 = golombAux ((golombAux m).length - 2) := by + have hlen := (golombAux_pos_length m).2 + rw [golombAux_eq_flatMap ((golombAux m).length - 2), + show (golombAux m).length - 2 + 2 = (golombAux m).length by omega] + conv_lhs => rw [golombAux_eq_map m] + exact levineAux_map golomb _ 1 + +theorem golombFast_eq_golombAux (i : ℕ) : ∃ m, golombFast i = golombAux m := by + induction i with + | zero => exact ⟨0, rfl⟩ + | succ i ih => + obtain ⟨m, hm⟩ := ih + exact ⟨_, by show levineAux (golombFast i) 1 = _; rw [hm, levineAux_golombAux]⟩ + +/-- `H` read off a prefix of Golomb's sequence. -/ +def hFast (i : ℕ) : List ℕ := 1 :: (golombFast i).drop 2 + +theorem H_eq_hFast (i j : ℕ) (h1 : 1 ≤ j) (h2 : j ≤ (hFast i).length) : + H j = (hFast i).getD (j - 1) 0 := by + obtain ⟨m, hm⟩ := golombFast_eq_golombAux i + have hlen := (golombAux_pos_length m).2 + rcases (show j = 1 ∨ 2 ≤ j by omega) with rfl | hj + · rfl + · have h2' : j < (golombAux m).length := by + simp only [hFast, hm, List.length_cons, List.length_drop] at h2; omega + rw [H, if_neg (by omega), golomb_eq_getD h2', hFast, hm, + show j - 1 = (j - 2) + 1 by omega, List.getD_cons_succ, List.getD_eq_getElem?_getD, + List.getD_eq_getElem?_getD, List.getElem?_drop, show 2 + (j - 2) = j by omega] + +theorem map_H_range' (i s c : ℕ) (h : s + c ≤ (hFast i).length) : + (List.range' (s + 1) c).map H = ((hFast i).drop s).take c := by + apply List.ext_getElem + · simp; omega + · intro k h1 _ + simp only [List.length_map, List.length_range'] at h1 + rw [List.getElem_map, List.getElem_range', List.getElem_take, List.getElem_drop, + H_eq_hFast i (s + 1 + 1 * k) (by omega) (by omega), List.getD_eq_getElem _ _ (by omega)] + congr 1; omega + +/-- One step of the row recursion, on a list `hl` holding `H 1, H 2, …`: +`(rowEnd n, rowEnd (n + 1)) ↦ (rowEnd (n + 1), rowEnd (n + 2))`. -/ +def rowStepL (hl : List ℕ) (p : ℕ × ℕ) : ℕ × ℕ := + (p.2, p.2 + ((hl.drop p.1).take (p.2 - p.1)).sum) + +def rowPairL (hl : List ℕ) : ℕ → ℕ × ℕ + | 0 => (0, 1) + | n + 1 => rowStepL hl (rowPairL hl n) + +theorem rowPairL_fst_le_snd (hl : List ℕ) (n : ℕ) : (rowPairL hl n).1 ≤ (rowPairL hl n).2 := by + cases n with + | zero => show 0 ≤ 1; omega + | succ n => show (rowPairL hl n).2 ≤ (rowPairL hl n).2 + _; omega + +theorem rowPairL_fst_mono (hl : List ℕ) {n n' : ℕ} (h : n ≤ n') : + (rowPairL hl n).1 ≤ (rowPairL hl n').1 := by + induction h with + | refl => exact le_rfl + | step _ ih => exact ih.trans (rowPairL_fst_le_snd hl _) + +theorem rowPairL_eq (i n : ℕ) (h : (rowPairL (hFast i) n).1 ≤ (hFast i).length) : + rowPairL (hFast i) n = (rowEnd n, rowEnd (n + 1)) := by + induction n with + | zero => rfl + | succ n ih => + have hle := rowPairL_fst_le_snd (hFast i) n + have h' : (rowPairL (hFast i) n).2 ≤ (hFast i).length := h + have e := ih (by omega) + rw [e] at hle h' + dsimp only at hle h' + show rowStepL (hFast i) (rowPairL (hFast i) n) = (rowEnd (n + 1), rowEnd (n + 2)) + rw [e] + show (rowEnd (n + 1), rowEnd (n + 1) + _) = (rowEnd (n + 1), rowEnd (n + 1) + + ((List.range' (rowEnd n + 1) (rowEnd (n + 1) - rowEnd n)).map H).sum) + rw [map_H_range' i (rowEnd n) (rowEnd (n + 1) - rowEnd n) (by omega)] + +theorem a_eq_fast {n : ℕ} (hn : n ≤ 7) : + a (n + 1) = (rowPairL (hFast 5) n).2 - (rowPairL (hFast 5) n).1 := by + have h7 : (rowPairL (hFast 5) 7).1 ≤ (hFast 5).length := by decide +kernel + rw [a_succ, rowPairL_eq 5 n ((rowPairL_fst_mono _ hn).trans h7)] + +theorem golomb_eq_fast (i j : ℕ) (hj : j < (golombFast i).length) : + golomb (j + 1) = (golombFast i).getD j 0 := by + obtain ⟨m, hm⟩ := golombFast_eq_golombAux i + rw [hm] at hj ⊢ + exact golomb_eq_getD hj + +theorem length_levineAux (l : List ℕ) (i : ℕ) : (levineAux l i).length = l.sum := by + induction l generalizing i with + | nil => rfl + | cons c l ih => rw [levineAux, List.length_append, List.length_replicate, ih, List.sum_cons] + +/-- The weighted sum `c₀ * i + c₁ * (i + 1) + ⋯ + c_r * (i + r)` of `[c₀, c₁, …, c_r]`. -/ +def wsum : List ℕ → ℕ → ℕ + | [], _ => 0 + | c :: l, i => c * i + wsum l (i + 1) + +theorem sum_levineAux (l : List ℕ) (i : ℕ) : (levineAux l i).sum = wsum l i := by + induction l generalizing i with + | nil => rfl + | cons c l ih => rw [levineAux, List.sum_append, List.sum_replicate, ih, wsum, smul_eq_mul] + +theorem map_H_range'_golomb (s c : ℕ) (hs : 2 ≤ s) : + (List.range' s c).map H = (List.range' (s + 1) c).map golomb := by + induction c generalizing s with + | zero => rfl + | succ c ih => + rw [List.range'_succ, List.range'_succ, List.map_cons, List.map_cons, ih (s + 1) (by omega)] + simp only [H, if_neg (show ¬ s ≤ 1 by omega)] + +/-- `a 9` needs `H` up to index `1090482`; it is the sum of `golomb j` over +`6475 ≤ j ≤ 1090483`, which is evaluated as a weighted sum of the first `6474` terms. -/ +theorem a_nine : a 9 = 4362192095 := by + have h7 := rowPairL_eq 5 7 (by decide +kernel) + have hv : rowPairL (hFast 5) 7 = (6473, 1090482) := by decide +kernel + rw [hv, Prod.mk.injEq] at h7 + obtain ⟨h7a, h8⟩ := h7 + have h5len : (golombFast 5).length = 6474 := by decide +kernel + have h5sum : (golombFast 5).sum = 1090483 := by decide +kernel + have h5w : wsum (golombFast 5) 1 = 1090483 + 4362192095 := by decide +kernel + obtain ⟨m5, hm5⟩ := golombFast_eq_golombAux 5 + obtain ⟨m6, hm6⟩ := golombFast_eq_golombAux 6 + have h6len : (golombFast 6).length = 1090483 := by + show (levineAux (golombFast 5) 1).length = _ + rw [length_levineAux, h5sum] + have h6sum : (golombFast 6).sum = 1090483 + 4362192095 := by + show (levineAux (golombFast 5) 1).sum = _ + rw [sum_levineAux, h5w] + have e5 : golombFast 5 = (List.range' 1 6474).map golomb := by + rw [← h5len, hm5] + exact golombAux_eq_map m5 + have hsplit : List.range' 1 1090483 = List.range' 1 6474 ++ List.range' 6475 1084009 := + (List.range'_append (s := 1) (m := 6474) (n := 1084009) (step := 1)).symm + have e6 : golombFast 6 = (List.range' 1 6474 ++ List.range' 6475 1084009).map golomb := by + rw [← hsplit, ← h6len, hm6] + exact golombAux_eq_map m6 + have key : (golombFast 6).sum = + (golombFast 5).sum + ((List.range' 6475 1084009).map golomb).sum := by + rw [e6, List.map_append, List.sum_append, ← e5] + have e9 : + a (7 + 2) = ((List.range' (rowEnd 7 + 1) (rowEnd (7 + 1) - rowEnd 7)).map H).sum := by + rw [a, length_row_succ_succ, row_succ] + rw [show (9 : ℕ) = 7 + 2 from rfl, e9, ← h7a, ← h8, + show (6473 + 1 : ℕ) = 6474 from rfl, show (1090482 - 6473 : ℕ) = 1084009 from rfl, + map_H_range'_golomb 6474 1084009 (by norm_num), show (6474 + 1 : ℕ) = 6475 from rfl] + omega + +/-! ### Data checks -/ + +/-- The definition of Golomb's sequence reproduces all 84 terms listed in A001462 +(kernel-checked). -/ +theorem golomb_data : (List.range 84).map (fun i => golomb (i + 1)) = + [1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 14, 14, 14, + 14, 14, 14, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, + 18, 18, 18, 18, 18, 18, 18, 19] := by + have h : (golombFast 4).length = 272 := by decide +kernel + rw [List.map_congr_left (fun i hi => golomb_eq_fast 4 i (by + have := List.mem_range.1 hi; omega))] + decide +kernel + +theorem row_eq_fast {n : ℕ} (hn : n ≤ 6) : + row (n + 1) = ((hFast 5).drop (rowPairL (hFast 5) n).1).take + ((rowPairL (hFast 5) n).2 - (rowPairL (hFast 5) n).1) := by + have h7 : (rowPairL (hFast 5) 7).1 ≤ (hFast 5).length := by decide +kernel + have e := rowPairL_eq 5 n ((rowPairL_fst_mono _ (by omega : n ≤ 7)).trans h7) + have hb := (rowPairL_fst_mono (hFast 5) (by omega : n + 1 ≤ 7)).trans h7 + have hle := rowPairL_fst_le_snd (hFast 5) n + rw [e] at hle ⊢ + rw [rowPairL_eq 5 (n + 1) hb] at hb + dsimp only at hle hb ⊢ + rw [row_succ, map_H_range' 5 _ _ (by omega)] + +/-- The last elements of rows `1, …, 7` of the triangle (kernel-checked). -/ +theorem rowLast_data : (List.range 7).map (fun i => (row (i + 1)).getLast?) = + [some 1, some 2, some 3, some 5, some 11, some 38, some 272] := by + rw [List.map_congr_left (fun i hi => congrArg List.getLast? + (row_eq_fast (by have := List.mem_range.1 hi; omega)))] + decide +kernel + +/-- The definition reproduces all 9 terms listed in OEIS, `a 1, …, a 9` (kernel-checked). -/ +theorem a_data : (List.range 9).map (fun i => a (i + 1)) = + [1, 1, 2, 6, 27, 234, 6202, 1084009, 4362192095] := by + rw [show List.range 9 = List.range 8 ++ [8] by decide, List.map_append, List.map_singleton, + show a (8 + 1) = 4362192095 from a_nine, + List.map_congr_left (fun i hi => a_eq_fast (by have := List.mem_range.1 hi; omega))] + decide +kernel + +theorem levineAux_pos (l : List ℕ) (i : ℕ) : ∀ x ∈ levineAux l i, i ≤ x := by + induction l generalizing i with + | nil => intro x hx; simp [levineAux] at hx + | cons c l ih => + intro x hx + rw [levineAux, List.mem_append] at hx + rcases hx with hx | hx + · rw [List.eq_of_mem_replicate hx] + · have := ih (i + 1) x hx; omega + +theorem levineRow_pos (k : ℕ) : ∀ x ∈ levineRow k, 1 ≤ x := by + match k with + | 0 => intro x hx; simp [levineRow] at hx + | 1 => decide + | k + 2 => exact levineAux_pos _ 1 + +theorem getLast?_levineAux : ∀ (l : List ℕ) (i : ℕ), l ≠ [] → (∀ x ∈ l, 1 ≤ x) → + (levineAux l i).getLast? = some (i + l.length - 1) + | [], _, h, _ => absurd rfl h + | [c], i, _, hpos => by + have hc : 1 ≤ c := hpos c (List.mem_singleton_self c) + rw [levineAux, levineAux, List.append_nil, List.getLast?_replicate, if_neg (by omega)] + simp + | c :: d :: l, i, _, hpos => by + rw [levineAux, List.getLast?_append, getLast?_levineAux (d :: l) (i + 1) + (List.cons_ne_nil _ _) (fun x hx => hpos x (List.mem_cons_of_mem _ hx))] + simp only [Option.some_or, List.length_cons] + congr 1 + omega + +/-- The final term of row `k + 2` of Levine's array is the length of row `k + 1`. -/ +theorem A014644_add_two (k : ℕ) (hne : levineRow (k + 1) ≠ []) : + A014644 (k + 2) = (levineRow (k + 1)).length := by + rw [A014644, levineRow_add_two, List.getLastD_eq_getLast?, + getLast?_levineAux _ _ hne (levineRow_pos _)] + simp + +/-- Levine's sequence: the definition reproduces the first 11 terms listed in A014644 +(kernel-checked; terms `9`–`11` via `A014644_add_two`, `length_levineAux` and +`sum_levineAux`, since rows `9` and `10` have `1090483` and `4363282578` terms). -/ +theorem A014644_data : (List.range 11).map (fun i => A014644 (i + 1)) = + [1, 2, 2, 3, 5, 11, 38, 272, 6474, 1090483, 4363282578] := by + have h8 : (levineRow (7 + 1)).length = 6474 ∧ (levineRow (7 + 1)).sum = 1090483 ∧ + wsum (levineRow (7 + 1)) 1 = 4363282578 := by decide +kernel + have l9 : (levineRow (8 + 1)).length = 1090483 := by + rw [levineRow_add_two, length_levineAux, h8.2.1] + have s9 : (levineRow (8 + 1)).sum = 4363282578 := by + rw [levineRow_add_two, sum_levineAux, h8.2.2] + have l10 : (levineRow (9 + 1)).length = 4363282578 := by + rw [levineRow_add_two, length_levineAux, s9] + have h9 : A014644 (8 + 1) = 6474 := by + rw [A014644_add_two 7 (List.ne_nil_of_length_pos (by rw [h8.1]; norm_num)), h8.1] + have h10 : A014644 (9 + 1) = 1090483 := by + rw [A014644_add_two 8 (List.ne_nil_of_length_pos (by rw [l9]; norm_num)), l9] + have h11 : A014644 (10 + 1) = 4363282578 := by + rw [A014644_add_two 9 (List.ne_nil_of_length_pos (by rw [l10]; norm_num)), l10] + rw [show List.range 11 = List.range 8 ++ [8, 9, 10] by decide, List.map_append, + List.map_cons, List.map_cons, List.map_singleton, h9, h10, h11] + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjectures (Floor van Lamoen and Paul D. Hanna, 2005): +(1) for every `n ≥ 2`, `a n = A014644 (n + 2) - A014644 (n + 1)`, i.e. the terms `a 2, a 3, …` +are the first differences of A014644 taken from its third term on; +(2) the final elements of rows `1, 2, 3, …` of the triangle are A014644 with the duplicate `2` +(`A014644 2 = A014644 3 = 2`) removed: the last element of row `1` is `A014644 1`, and the last +element of row `n` is `A014644 (n + 1)` for every `n ≥ 2`. -/ +def statement : Prop := + (∀ n : ℕ, 2 ≤ n → (a n : ℤ) = (A014644 (n + 2) : ℤ) - (A014644 (n + 1) : ℤ)) ∧ + ((row 1).getLast? = some (A014644 1) ∧ + ∀ n : ℕ, 2 ≤ n → (row n).getLast? = some (A014644 (n + 1))) + +end Math0.Statements.A113676 diff --git a/lean/Math0/Statements/OEIS/A115026.lean b/lean/Math0/Statements/OEIS/A115026.lean new file mode 100644 index 0000000..02c9cc9 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A115026.lean @@ -0,0 +1,258 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A115026: no limiting value of the digit-power iteration exceeds 370 + +Source: https://oeis.org/A115026, Harvey P. Dale, Jun 08 2022 (COMMENTS section). Verbatim: +> Conjecture: no term is greater than 370. - _Harvey P. Dale_, Jun 08 2022 + +The sequence (offset `1`, by Sergio Pimentel) is "Limiting value of n under iteration of +"sum of the digits raised to the power of the number of digits of n" (A101337)", with the +comment "Iterate A101337 starting at n until reaching a constant value (like 370) or a cycle +(like 160, 217, 352, 160, ...). In the latter case, a(n) takes the smallest value in the cycle +(e.g., a(59) = 160)." + +## Encoding + +* `F m` is A101337: the sum of `d ^ L` over the decimal digits `d` of `m`, where `L` is the + number of decimal digits of `m` (`Nat.digits 10 m`, so `F 0 = 0`; only `m ≥ 1` matters). +* The cycle that the orbit `n, F n, F (F n), …` ends in is `limitCycle n`: the values + `F^[k] n` of the orbit that are periodic points of `F` (`F^[p] m = m` for some `p > 0`). + A fixed point ("constant value") is a cycle of length one. `a n` is the smallest element of + `limitCycle n`, as in the entry. +* `a` is computed by Floyd's cycle-finding loop (`meet`), which returns a periodic point `y` of + the orbit, followed by a walk around the cycle of `y` that records its minimum (`cycleMin`). + Both loops take a fuel argument `fuel n`. The fuel never runs out: every value of the orbit is + at most `max n C` with `C = 70 * 9 ^ 70` (`iterate_le`, because `F m < m` once `m` has at + least `70` digits), so by pigeonhole the orbit repeats within `max n C + 2` steps + (`exists_meet`). The theorem `a_spec` proves, for every `n`, that `a n ∈ limitCycle n` and + `a n ≤ m` for every `m ∈ limitCycle n`; so `a n` is exactly the OEIS definition. + `a_data` checks all 65 listed terms `a 1, …, a 65`. +* The conjecture is about all terms of the sequence, i.e. all `n ≥ 1` (the offset is `1`): + `∀ n ≥ 1, a n ≤ 370`. +-/ + +namespace Math0.Statements.A115026 + +/-- A101337: the sum of the decimal digits of `m`, each raised to the power (number of decimal +digits of `m`). -/ +def F (m : ℕ) : ℕ := ((Nat.digits 10 m).map (· ^ (Nat.digits 10 m).length)).sum + +/-- The cycle that the iteration of `F` starting at `n` eventually enters: the elements of the +orbit of `n` that are periodic points of `F`. -/ +def limitCycle (n : ℕ) : Set ℕ := + {m | (∃ k, F^[k] n = m) ∧ ∃ p, 0 < p ∧ F^[p] m = m} + +/-- Floyd's tortoise-and-hare loop: from `x = F^[k] n`, `z = F^[2k] n`, step `k ↦ k + 1` until +`x = z`, and return `x` (a periodic point of the orbit). -/ +def meet : ℕ → ℕ → ℕ → ℕ + | 0, x, _ => x + | fuel + 1, x, z => if x = z then x else meet fuel (F x) (F (F z)) + +/-- Walk from `cur` along the orbit until `y` is reached again, keeping the running minimum `m`. -/ +def cycleMin (y : ℕ) : ℕ → ℕ → ℕ → ℕ + | 0, _, m => m + | fuel + 1, cur, m => if cur = y then m else cycleMin y fuel (F cur) (min m cur) + +/-- A bound for `F` on numbers with fewer than `70` digits. -/ +def C : ℕ := 70 * 9 ^ 70 + +/-- Enough fuel for both loops (see `exists_meet`). -/ +def fuel (n : ℕ) : ℕ := (max n C + 2) ^ 2 + +/-- A115026: the smallest value of the cycle that the iteration of A101337 starting at `n` +ends in (see `a_spec`). -/ +def a (n : ℕ) : ℕ := + let y := meet (fuel n) (F n) (F (F n)) + cycleMin y (fuel n) (F y) y + +/-- The definition reproduces all 65 terms listed in OEIS, `a 1, …, a 65` (kernel-checked). -/ +theorem a_data : (List.range 65).map (fun i => a (i + 1)) = + [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 5, 1, 370, 370, 370, 370, 370, 1, 4, 5, 8, 1, 4, 370, 370, + 370, 1, 370, 9, 1, 1, 370, 370, 370, 370, 370, 370, 370, 370, 370, 4, 370, 1, 370, 370, + 370, 370, 1, 370, 370, 370, 370, 370, 370, 370, 370, 370, 160, 370, 370, 370, 370, 370, + 370] := by + decide +kernel + +/-! ### `a n` is the smallest element of the limit cycle of `n` -/ + +/-- `F m ≤ L * 9 ^ L`, where `L` is the number of digits of `m`. -/ +theorem F_le (m : ℕ) : F m ≤ (Nat.digits 10 m).length * 9 ^ (Nat.digits 10 m).length := by + unfold F + have h := List.sum_le_card_nsmul ((Nat.digits 10 m).map (· ^ (Nat.digits 10 m).length)) + (9 ^ (Nat.digits 10 m).length) (by + intro x hx + rw [List.mem_map] at hx + obtain ⟨d, hd, rfl⟩ := hx + have := Nat.digits_lt_base (by norm_num) hd + exact Nat.pow_le_pow_left (by omega) _) + simpa using h + +theorem key_ineq (L : ℕ) (hL : 70 ≤ L) : 10 * (L * 9 ^ L) < 10 ^ L := by + induction L, hL using Nat.le_induction with + | base => norm_num + | succ L hL ih => + have h1 : 9 * (L + 1) * 9 ^ L ≤ 10 * L * 9 ^ L := Nat.mul_le_mul_right _ (by omega) + rw [pow_succ, pow_succ] + nlinarith + +/-- `F m ≤ max m C`. -/ +theorem F_le_max (m : ℕ) : F m ≤ max m C := by + have h1 := F_le m + by_cases hm : (Nat.digits 10 m).length < 70 + · apply le_max_of_le_right + calc F m ≤ (Nat.digits 10 m).length * 9 ^ (Nat.digits 10 m).length := h1 + _ ≤ 70 * 9 ^ 70 := + Nat.mul_le_mul (by omega) (Nat.pow_le_pow_right (by norm_num) (by omega)) + · apply le_max_of_le_left + have hm0 : m ≠ 0 := by + rintro rfl + simp at hm + have h2 := Nat.base_pow_length_digits_le 10 m (by norm_num) hm0 + have h3 := key_ineq (Nat.digits 10 m).length (by omega) + omega + +/-- Every value of the orbit of `n` is at most `max n C`. -/ +theorem iterate_le (n : ℕ) : ∀ k, F^[k] n ≤ max n C := by + intro k + induction k with + | zero => simp + | succ k ih => + rw [Function.iterate_succ_apply'] + calc F (F^[k] n) ≤ max (F^[k] n) C := F_le_max _ + _ ≤ max n C := max_le (le_trans ih le_rfl) (le_max_right _ _) + +theorem meet_of_repeat (n i j : ℕ) (hij : i < j) (h : F^[i] n = F^[j] n) : + F^[(j - i) * (i + 1)] n = F^[2 * ((j - i) * (i + 1))] n := by + have hw : Function.IsPeriodicPt F (j - i) (F^[i] n) := by + show F^[j - i] (F^[i] n) = F^[i] n + rw [← Function.iterate_add_apply, show j - i + i = j by omega] + exact h.symm + have hK := hw.mul_const (i + 1) + have hiK : i ≤ (j - i) * (i + 1) := by + have : 1 ≤ j - i := by omega + nlinarith + have e1 : F^[(j - i) * (i + 1)] n = F^[(j - i) * (i + 1) - i] (F^[i] n) := by + rw [← Function.iterate_add_apply, Nat.sub_add_cancel hiK] + have e2 : F^[2 * ((j - i) * (i + 1))] n = + F^[(j - i) * (i + 1) - i] (F^[(j - i) * (i + 1)] (F^[i] n)) := by + rw [← Function.iterate_add_apply, ← Function.iterate_add_apply] + congr 1 + omega + rw [e1, e2, hK.eq] + +/-- By pigeonhole, Floyd's loop meets within `fuel n` steps. -/ +theorem exists_meet (n : ℕ) : ∃ K, 1 ≤ K ∧ K ≤ fuel n ∧ F^[K] n = F^[2 * K] n := by + obtain ⟨i, hi, j, hj, hij, h⟩ := Finset.exists_ne_map_eq_of_card_lt_of_maps_to + (s := Finset.range (max n C + 2)) (t := Finset.range (max n C + 1)) + (f := fun k => F^[k] n) (by simp) (by + intro k _ + simp only [Finset.coe_range, Set.mem_Iio] + exact Nat.lt_succ_of_le (iterate_le n k)) + simp only [Finset.mem_range] at hi hj + have bound : ∀ i j : ℕ, i < j → j < max n C + 2 → + 1 ≤ (j - i) * (i + 1) ∧ (j - i) * (i + 1) ≤ fuel n := by + intro i j hij hj + refine ⟨Nat.mul_pos (by omega) (by omega), ?_⟩ + unfold fuel + rw [sq] + exact Nat.mul_le_mul (by omega) (by omega) + rcases lt_or_gt_of_ne hij with hlt | hlt + · exact ⟨_, (bound i j hlt hj).1, (bound i j hlt hj).2, meet_of_repeat n i j hlt h⟩ + · exact ⟨_, (bound j i hlt hi).1, (bound j i hlt hi).2, meet_of_repeat n j i hlt h.symm⟩ + +theorem meet_spec (n : ℕ) : ∀ (f k K : ℕ), 1 ≤ k → k ≤ K → K - k < f → + F^[K] n = F^[2 * K] n → + ∃ k', 1 ≤ k' ∧ k' ≤ K ∧ meet f (F^[k] n) (F^[2 * k] n) = F^[k'] n ∧ + F^[k'] (F^[k'] n) = F^[k'] n := by + intro f + induction f with + | zero => intro k K _ _ h; omega + | succ f ih => + intro k K hk hkK hf hK + simp only [meet] + split_ifs with h + · refine ⟨k, hk, hkK, rfl, ?_⟩ + rw [← Function.iterate_add_apply, ← two_mul] + exact h.symm + · have hkK' : k + 1 ≤ K := by + rcases eq_or_lt_of_le hkK with rfl | h' + · exact absurd hK h + · exact h' + obtain ⟨k', h1, h2, h3, h4⟩ := ih (k + 1) K (by omega) hkK' (by omega) hK + have e1 : F^[k + 1] n = F (F^[k] n) := Function.iterate_succ_apply' _ _ _ + have e2 : F^[2 * (k + 1)] n = F (F (F^[2 * k] n)) := by + rw [show 2 * (k + 1) = 2 * k + 1 + 1 by ring, Function.iterate_succ_apply', + Function.iterate_succ_apply'] + rw [e1, e2] at h3 + exact ⟨k', h1, h2, h3, h4⟩ + +theorem cycleMin_spec (y p : ℕ) (hy : F^[p] y = y) : ∀ (f t m : ℕ), 1 ≤ t → t ≤ p → + p - t < f → (∃ s, F^[s] y = m) → (∀ s < t, m ≤ F^[s] y) → + (∃ s, F^[s] y = cycleMin y f (F^[t] y) m) ∧ + ∀ s, cycleMin y f (F^[t] y) m ≤ F^[s] y := by + intro f + induction f with + | zero => intros; omega + | succ f ih => + intro t m ht htp hf hm hmin + simp only [cycleMin] + split_ifs with h + · refine ⟨hm, fun s => ?_⟩ + have hper : Function.IsPeriodicPt F t y := h + rw [← hper.iterate_mod_apply] + exact hmin _ (Nat.mod_lt _ (by omega)) + · have htp' : t + 1 ≤ p := by + rcases eq_or_lt_of_le htp with rfl | h' + · exact absurd hy h + · exact h' + have e : F (F^[t] y) = F^[t + 1] y := (Function.iterate_succ_apply' _ _ _).symm + rw [e] + apply ih (t + 1) (min m (F^[t] y)) (by omega) htp' (by omega) + · rcases le_total m (F^[t] y) with hle | hle + · rw [min_eq_left hle] + exact hm + · rw [min_eq_right hle] + exact ⟨t, rfl⟩ + · intro s hs + rcases Nat.lt_succ_iff_lt_or_eq.mp hs with hs | rfl + · exact le_trans (min_le_left _ _) (hmin s hs) + · exact min_le_right _ _ + +/-- `a n` is the smallest element of the cycle that the iteration of `F` from `n` ends in. -/ +theorem a_spec (n : ℕ) : a n ∈ limitCycle n ∧ ∀ m ∈ limitCycle n, a n ≤ m := by + obtain ⟨K, hK1, hKf, hK⟩ := exists_meet n + obtain ⟨k, hk1, hkK, hy, hper⟩ := meet_spec n (fuel n) 1 K le_rfl hK1 (by omega) hK + have hy' : meet (fuel n) (F n) (F (F n)) = F^[k] n := hy + obtain ⟨⟨s, hs⟩, hmin⟩ := cycleMin_spec (F^[k] n) k hper (fuel n) 1 (F^[k] n) le_rfl hk1 + (by omega) ⟨0, rfl⟩ (by + intro s hs + rw [show s = 0 by omega] + exact le_rfl) + have ha : a n = cycleMin (F^[k] n) (fuel n) (F^[1] (F^[k] n)) (F^[k] n) := by + simp only [a, hy'] + rfl + rw [ha] + refine ⟨⟨⟨s + k, ?_⟩, k, hk1, ?_⟩, ?_⟩ + · rw [Function.iterate_add_apply, hs] + · rw [← hs, ← Function.iterate_add_apply, add_comm, Function.iterate_add_apply, hper] + · rintro m ⟨⟨i, hi⟩, q, hq, hqm⟩ + have hm' : Function.IsPeriodicPt F (q * k) m := + (show Function.IsPeriodicPt F q m from hqm).mul_const k + have hkq : k ≤ q * k := Nat.le_mul_of_pos_left k hq + have : m = F^[q * k + i - k] (F^[k] n) := by + rw [← Function.iterate_add_apply, Nat.sub_add_cancel (by omega), Function.iterate_add_apply, + hi, hm'.eq] + rw [this] + exact hmin _ + +/-- Conjecture (Harvey P. Dale, 2022): no term of A115026 is greater than `370`, i.e. for every +`n ≥ 1`, the smallest value of the cycle that the iteration of A101337 starting at `n` enters is +at most `370`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → a n ≤ 370 + +end Math0.Statements.A115026 diff --git a/lean/Math0/Statements/OEIS/A116184.lean b/lean/Math0/Statements/OEIS/A116184.lean new file mode 100644 index 0000000..f884ac8 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A116184.lean @@ -0,0 +1,192 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A116184: `n` with `37^3` dividing the numerator of `∑_{k=1}^{36} 1/k^n` + +Source: https://oeis.org/A116184, _Alexander Adamchuk_, Apr 08 2007. Verbatim (COMMENTS +section): +> Conjecture: All terms of the arithmetic progression 3+36k belong to a(n). Prime terms in a(n) +> are {3, 37, 73, 443, 739, 887, 1109, ...}. It appears that all primes in a(n) that are greater +> than 37 are of the form 37k-1. + +The sequence (offset `1`) is "Numbers n such that 37^3 divides the numerator of generalized +harmonic number H(36,n) = Sum[ 1/k^n, {k,1,36} ]." The entry's Mathematica program scans +`n = 1, …, 1000`. + +## Encoding + +* `H n : ℚ` is the generalized harmonic number `H(36, n) = ∑_{k=1}^{36} 1/k^n`, computed exactly + in `ℚ`; its numerator is `(H n).num` (Mathlib's `Rat.num`, in lowest terms; `H n > 0`). +* `IsTerm n`: `37^3 ∣ (H n).num`, i.e. `n` is a term of A116184. (`n = 0` is not a term: + `H 0 = 36`; see `not_isTerm_zero`. So the terms are exactly the positive `n` with the + property, as in the entry.) +* `a n = Nat.nth IsTerm (n - 1)` is the `n`-th smallest term (offset `1`), noncomputable as + written. `exists_a_eq_iff` shows that a positive integer `x` occurs as some `a m` (`m ≥ 1`) + iff `IsTerm x`, so "belongs to a(n)" / "primes in a(n)" are expressed with `IsTerm`. +* *Decidability.* Since `37` is prime and `37 > 36`, `H n = S / 36!^n` with + `S = ∑_{k=1}^{36} (36!/k)^n` and `gcd(37, 36!^n) = 1`, so `37^3 ∣ (H n).num ↔ 37^3 ∣ S` + (`isTerm_iff_check`); `S mod 37^3` is computed from the residues `36!/k mod 37^3`. This gives a + `DecidablePred IsTerm` instance, and `a_data` checks all 53 listed terms (all members `≤ 975`) + by a kernel-checked `List.filter`. +* *The conjecture* (both claims of the comment): `statement` is the conjunction of + (a) `IsTerm (3 + 36k)` for every `k ≥ 0` (the progression `3, 39, 75, …` starts at the term + `3`), and (b) every prime term `p > 37` is of the form `37k - 1`, written `p = 37 * k - 1` for + some `k : ℕ` (natural subtraction is harmless: `k = 0` gives `0`, and for `k ≥ 1` this is + `37 ∣ p + 1`). The list of prime terms quoted in between is a data example, not part of the + claim. +-/ + +namespace Math0.Statements.A116184 + +/-! ### Definitions -/ + +/-- The generalized harmonic number `H(36, n) = ∑_{k=1}^{36} 1/k^n`, computed exactly in `ℚ`. -/ +def H (n : ℕ) : ℚ := ∑ k ∈ Finset.Icc (1 : ℕ) 36, 1 / ((k : ℚ) ^ n) + +/-- `n` is a term of A116184: `37^3` divides the numerator of `H(36, n)`. -/ +def IsTerm (n : ℕ) : Prop := (37 ^ 3 : ℤ) ∣ (H n).num + +/-! ### A fast decision procedure -/ + +/-- The residues `36!/k mod 37^3` for `k = 1, …, 36` (`37^3 = 50653`). -/ +def coeffs : List ℕ := + [23531, 37092, 24728, 18546, 35098, 12364, 25070, 9273, 25127, 17549, 6744, 6182, 21292, 12535, + 45468, 29963, 46078, 37890, 25232, 34101, 25241, 3372, 7630, 3091, 47542, 10646, 25260, 31594, + 13038, 22734, 4027, 40308, 2248, 23039, 5014, 18945] + +theorem coeffs_eq : + coeffs = (List.range 36).map (fun i => Nat.factorial 36 / (i + 1) % 50653) := by + decide +kernel + +/-- `∑_{k=1}^{36} (36!/k)^n ≡ 0 (mod 37^3)`, computed with small residues. -/ +def check (n : ℕ) : Bool := (coeffs.map (fun c => c ^ n % 50653)).sum % 50653 == 0 + +theorem sum_range_eq_list_sum (f : ℕ → ℕ) (N : ℕ) : + ∑ i ∈ Finset.range N, f i = ((List.range N).map f).sum := by + induction N with + | zero => simp + | succ N ih => + rw [Finset.sum_range_succ, List.range_succ, List.map_append, List.sum_append, ih] + simp + +theorem sum_Icc_eq_list_sum (g : ℕ → ℕ) : + ∑ k ∈ Finset.Icc 1 36, g k = ((List.range 36).map (fun i => g (i + 1))).sum := by + rw [← Finset.Ico_add_one_right_eq_Icc, Finset.sum_Ico_eq_sum_range, sum_range_eq_list_sum] + simp [Nat.add_comm 1] + +/-- `H(36, n) = (∑_{k=1}^{36} (36!/k)^n) / 36!^n`. -/ +theorem H_eq (n : ℕ) : + H n = ((∑ k ∈ Finset.Icc 1 36, (Nat.factorial 36 / k) ^ n : ℕ) : ℚ) / + ((Nat.factorial 36 ^ n : ℕ) : ℚ) := by + have hF : ((Nat.factorial 36 : ℕ) : ℚ) ≠ 0 := by positivity + rw [H, Nat.cast_sum, Finset.sum_div] + refine Finset.sum_congr rfl fun k hk => ?_ + obtain ⟨hk1, hk36⟩ := Finset.mem_Icc.mp hk + have hkd : k ∣ Nat.factorial 36 := Nat.dvd_factorial hk1 hk36 + have hk0 : (k : ℚ) ≠ 0 := by exact_mod_cast (show k ≠ 0 by omega) + rw [Nat.cast_pow, Nat.cast_pow, Nat.cast_div hkd hk0, div_pow] + field_simp + +/-- If `q = s / b` with `b` coprime to `37`, then `37^3 ∣ q.num ↔ 37^3 ∣ s`. -/ +theorem dvd_num_iff (q : ℚ) (s b : ℕ) (hb : b ≠ 0) (hcop : Nat.Coprime (37 ^ 3) b) + (hq : q = (s : ℚ) / (b : ℚ)) : + (37 ^ 3 : ℤ) ∣ q.num ↔ (37 ^ 3 : ℤ) ∣ (s : ℤ) := by + have hb' : (b : ℚ) ≠ 0 := by exact_mod_cast hb + -- `q.num * b = s * q.den` + have key : q.num * (b : ℤ) = (s : ℤ) * (q.den : ℤ) := by + have h1 : (q.num : ℚ) / (q.den : ℚ) = (s : ℚ) / (b : ℚ) := by rw [Rat.num_div_den, hq] + have hd : (q.den : ℚ) ≠ 0 := by exact_mod_cast q.den_nz + rw [div_eq_div_iff hd hb'] at h1 + exact_mod_cast h1 + -- `q.den ∣ b` + have hden : (q.den : ℤ) ∣ (b : ℤ) := by + have : q = Rat.divInt (s : ℤ) (b : ℤ) := by + rw [hq, Rat.divInt_eq_div]; push_cast; rfl + have h := Rat.den_dvd (s : ℤ) (b : ℤ) + rwa [← this] at h + have hcopZ : IsCoprime ((37 ^ 3 : ℕ) : ℤ) (b : ℤ) := Nat.isCoprime_iff_coprime.mpr hcop + push_cast at hcopZ + have hcopD : IsCoprime (37 ^ 3 : ℤ) (q.den : ℤ) := hcopZ.of_isCoprime_of_dvd_right hden + constructor + · intro h + have : (37 ^ 3 : ℤ) ∣ (s : ℤ) * (q.den : ℤ) := key ▸ dvd_mul_of_dvd_left h _ + exact hcopD.dvd_of_dvd_mul_right this + · intro h + have : (37 ^ 3 : ℤ) ∣ q.num * (b : ℤ) := key ▸ dvd_mul_of_dvd_left h _ + exact hcopZ.dvd_of_dvd_mul_right this + +theorem isTerm_iff_check (n : ℕ) : IsTerm n ↔ check n = true := by + have h37 : Nat.Coprime 37 (Nat.factorial 36) := + (Nat.Prime.coprime_iff_not_dvd (by norm_num)).mpr + (by rw [Nat.Prime.dvd_factorial (by norm_num)]; norm_num) + have hcop : Nat.Coprime (37 ^ 3) (Nat.factorial 36 ^ n) := Nat.Coprime.pow 3 n h37 + rw [IsTerm, dvd_num_iff (H n) _ _ (by positivity) hcop (H_eq n)] + rw [show ((37 : ℤ) ^ 3) = ((37 ^ 3 : ℕ) : ℤ) by norm_num, Int.natCast_dvd_natCast, + Nat.dvd_iff_mod_eq_zero, Finset.sum_nat_mod] + simp only [Nat.pow_mod (Nat.factorial 36 / _)] + rw [sum_Icc_eq_list_sum, check, coeffs_eq, List.map_map] + simp [Function.comp_def] + +instance : DecidablePred IsTerm := fun n => decidable_of_iff _ (isTerm_iff_check n).symm + +/-! ### The sequence -/ + +/-- A116184: the `n`-th smallest (offset `1`) number `m` such that `37^3` divides the numerator +of `H(36, m) = ∑_{k=1}^{36} 1/k^m`. -/ +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) + +/-- `0` is not a term (`H(36, 0) = 36`). -/ +theorem not_isTerm_zero : ¬ IsTerm 0 := by decide +kernel + +/-- A positive integer occurs in the sequence iff it satisfies the defining property. -/ +theorem exists_a_eq_iff {x : ℕ} (hx : x ≠ 0) : (∃ m, 1 ≤ m ∧ a m = x) ↔ IsTerm x := by + constructor + · rintro ⟨m, -, hm⟩ + have h : Nat.nth IsTerm (m - 1) ≠ 0 := by rw [← a, hm]; exact hx + have := Nat.nth_mem_of_ne_zero h + rwa [← a, hm] at this + · intro h + exact ⟨Nat.count IsTerm x + 1, by omega, by simp [a, Nat.nth_count h]⟩ + +/-- The elements `< N` satisfying `p`, in increasing order, are `nth p 0, nth p 1, …`. -/ +theorem filter_range_eq (p : ℕ → Prop) [DecidablePred p] (N : ℕ) : + (List.range N).filter (fun k => decide (p k)) = + (List.range (Nat.count p N)).map (Nat.nth p) := by + induction N with + | zero => simp + | succ N ih => + rw [List.range_succ, List.filter_append, ih, Nat.count_succ] + by_cases h : p N + · simp [h, List.range_succ, Nat.nth_count h] + · simp [h] + +theorem map_nth_eq_of_filter {p : ℕ → Prop} [DecidablePred p] {N K : ℕ} {L : List ℕ} + (h : (List.range N).filter (fun k => decide (p k)) = L) (hK : L.length = K) : + (List.range K).map (Nat.nth p) = L := by + rw [filter_range_eq] at h + subst h + simp only [List.length_map, List.length_range] at hK + rw [hK] + +/-- The definition reproduces all 53 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 53).map (fun i => a (i + 1)) = + [3, 37, 39, 73, 75, 111, 147, 148, 183, 185, 219, 221, 255, 259, 291, 295, 327, 333, 363, + 369, 399, 407, 435, 443, 471, 481, 507, 517, 543, 555, 579, 591, 615, 629, 651, 665, 687, + 703, 723, 739, 759, 777, 795, 813, 831, 851, 867, 887, 903, 925, 939, 961, 975] := by + have : (fun i => a (i + 1)) = Nat.nth IsTerm := funext fun i => by simp [a] + rw [this] + exact map_nth_eq_of_filter (N := 976) (by decide +kernel) rfl + +/-! ### The conjecture -/ + +/-- Conjecture (Adamchuk, A116184): (a) every term `3 + 36k` (`k ≥ 0`) of the arithmetic +progression belongs to the sequence, and (b) every prime term greater than `37` is of the form +`37k - 1`. -/ +def statement : Prop := + (∀ k : ℕ, IsTerm (3 + 36 * k)) ∧ + (∀ p : ℕ, p.Prime → 37 < p → IsTerm p → ∃ k : ℕ, p = 37 * k - 1) + +end Math0.Statements.A116184 diff --git a/lean/Math0/Statements/OEIS/A119936.lean b/lean/Math0/Statements/OEIS/A119936.lean new file mode 100644 index 0000000..daee9e9 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A119936.lean @@ -0,0 +1,173 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A119936: row-LCM of the denominators of the cube of the mean matrix is `n³·(lcm(1..n)/n)²` + +Source: https://oeis.org/A119936, Wolfdieter Lang, Jul 20 2006 (FORMULA section). Verbatim: +> a(n)/n^3 = A027451(n) = A002944(n)^2 (the second equation is a conjecture). + +The entry (offset `1`) is named "Least common multiple (LCM) of denominators of the rows of the +triangle of rationals A119935/A119932", with the comment "The triangle of rationals is the +matrix cube of the matrix with elements a(i,j) = 1/i if j <= i, 0 if j > i" and the formula +"a(n) = lcm_{m=1..n} seq(A119932(n,m)), n >= 1". Here A119932(n,m) is the denominator of +`r(n,m) := (A^3)[n,m]` in lowest terms (A119935 is its numerator). + +## Encoding + +* *The matrix.* `A i j : ℚ` is `1/i` if `j ≤ i` and `0` otherwise (indices start at `1`). + `Amat N` is its `N × N` leading truncation, as a Mathlib `Matrix (Fin N) (Fin N) ℚ` (the + `Fin N` index `i` stands for the OEIS index `i + 1`). +* *The triangle.* `r n m` (`1 ≤ m ≤ n`) is the entry in row `n`, column `m` of `Amat n ^ 3` + (Mathlib's matrix power). Since `A` is lower triangular, `(A^3)[n,m]` only involves indices + `≤ n`, so this is the `(n,m)` entry of the cube of the infinite matrix; `r_eq_sum` and + `r_eq_explicit` prove `r n m = ∑_{k,l=1}^{n} A(n,k) A(k,l) A(l,m) + = (1/n) ∑_{m ≤ l ≤ k ≤ n} 1/(k l)`. `triangle_num_data` and `triangle_den_data` check, in the + kernel, that `r` read by rows reproduces all listed terms of A119935 (numerators, 37 terms) and + A119932 (denominators, 32 terms); `Rat.num`/`Rat.den` are in lowest terms. +* *The sequence.* `a n` is the LCM, over `m = 1, …, n`, of the denominators `(r n m).den`, as in + the name and the formula above. `a_data` checks all 19 listed terms `a(1), …, a(19)` in the + kernel. +* *The conjecture.* A027451 is "First diagonal of A027447", and A027447 lists row `n` of `A^3` + written over the least common denominator, i.e. A027447(n,m) = a(n)·r(n,m) (this is the + formula `A027447(i,j) = a(i)*A119935(i,j)/A119932(i,j)` of the entry). As `r(n,n) = 1/n³`, + A027451(n) = a(n)/n³: this is the first, non-conjectural equation. The conjecture is the second + equation, A027451(n) = A002944(n)², i.e. `a(n)/n³ = A002944(n)²`, where A002944 is + "a(n) = LCM(1,2,...,n) / n" (offset `1`). `A002944 n` is `lcmUpTo n / n` with + `lcmUpTo n = lcm(1, …, n)` (`Finset.lcm` over `[1, n]`); the division is exact for `n ≥ 1` + (`A002944_mul`), and `A002944_data` checks the 31 listed terms of A002944. + `statement` asserts `(a n : ℚ) / n³ = (A002944 n)²` in `ℚ` for every `n ≥ 1` (the common + offset of A119936, A027451 and A002944). `statement_iff` shows it is equivalent to the integer + identity `a n = n · lcm(1, …, n)²` for every `n ≥ 1`. +-/ + +namespace Math0.Statements.A119936 + +/-- The lower-triangular mean matrix (1-indexed): `A(i,j) = 1/i` if `j ≤ i`, `0` if `j > i`. -/ +def A (i j : ℕ) : ℚ := if j ≤ i then 1 / (i : ℚ) else 0 + +/-- The `N × N` leading truncation of `A`; the index `i : Fin N` stands for row/column `i + 1`. -/ +def Amat (N : ℕ) : Matrix (Fin N) (Fin N) ℚ := + Matrix.of fun i j => A ((i : ℕ) + 1) ((j : ℕ) + 1) + +/-- The triangle of rationals A119935/A119932: `r n m = (A^3)[n,m]` for `1 ≤ m ≤ n`, computed as +the `(n,m)` entry of the cube of the `n × n` truncation of `A` (`0` outside the triangle). -/ +def r (n m : ℕ) : ℚ := + if h : 1 ≤ m ∧ m ≤ n then (Amat n ^ 3) ⟨n - 1, by omega⟩ ⟨m - 1, by omega⟩ else 0 + +/-- A119936: the LCM of the (lowest-terms) denominators of row `n` of the triangle `r`, +`a(n) = lcm_{m=1..n} A119932(n,m)`. -/ +def a (n : ℕ) : ℕ := (Finset.Icc 1 n).lcm fun m => (r n m).den + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all 19 listed +terms `a(1), …, a(19)`. -/ +theorem a_data : (List.range 19).map (fun i => a (i + 1)) = + [1, 8, 108, 576, 18000, 21600, 1234800, 5644800, 57153600, 63504000, 8452382400, + 9220780800, 1688171284800, 1818030614400, 1947889944000, 8310997094400, + 2551995545299200, 2702112930316800, 1029655143835718400] := by + decide +kernel + +/-! ### Sanity checks of the triangle -/ + +/-- Rows `1, …, K` of the triangle `r`, read by rows. -/ +def triangle (K : ℕ) : List ℚ := + (List.range K).flatMap fun i => (List.range (i + 1)).map fun j => r (i + 1) (j + 1) + +/-- The numerators of `r`, read by rows, are the 37 listed terms of A119935. -/ +theorem triangle_num_data : ((triangle 9).take 37).map Rat.num = + [1, 7, 1, 85, 19, 1, 415, 115, 37, 1, 12019, 3799, 1489, 61, 1, 13489, 4669, 2059, 919, + 91, 1, 726301, 268921, 128431, 64171, 7669, 127, 1, 3144919, 1227199, 621139, + 334699, 178669, 3565, 169, 1, 30300391] := by + decide +kernel + +/-- The denominators of `r`, read by rows, are the 32 listed terms of A119932. -/ +theorem triangle_den_data : ((triangle 8).take 32).map Rat.den = + [1, 8, 8, 108, 108, 27, 576, 576, 576, 64, 18000, 18000, 18000, 2000, 125, 21600, + 21600, 21600, 21600, 5400, 216, 1234800, 1234800, 1234800, 1234800, 308700, + 12348, 343, 5644800, 5644800, 5644800, 5644800] := by + decide +kernel + +theorem sum_fin_eq_sum_Icc (n : ℕ) (f : ℕ → ℚ) : + ∑ i : Fin n, f ((i : ℕ) + 1) = ∑ k ∈ Finset.Icc 1 n, f k := by + rw [Fin.sum_univ_eq_sum_range (fun i => f (i + 1)) n, ← Finset.Ico_add_one_right_eq_Icc, + Finset.sum_Ico_eq_sum_range] + simp [add_comm] + +/-- `r n m` is the matrix-cube entry `∑_{k,l=1}^{n} A(n,k) A(k,l) A(l,m)`. -/ +theorem r_eq_sum {n m : ℕ} (hm : 1 ≤ m) (hmn : m ≤ n) : + r n m = ∑ k ∈ Finset.Icc 1 n, ∑ l ∈ Finset.Icc 1 n, A n k * A k l * A l m := by + rw [r, dif_pos ⟨hm, hmn⟩] + simp only [pow_succ', pow_zero, mul_one, Matrix.mul_apply, Amat, Matrix.of_apply, + Finset.mul_sum, ← mul_assoc] + have h1 : n - 1 + 1 = n := by omega + have h2 : m - 1 + 1 = m := by omega + simp only [h1, h2] + rw [← sum_fin_eq_sum_Icc n (fun k => ∑ l ∈ Finset.Icc 1 n, A n k * A k l * A l m)] + refine Finset.sum_congr rfl fun k _ => ?_ + exact sum_fin_eq_sum_Icc n (fun l => A n (k + 1) * A (k + 1) l * A l m) + +/-- Explicit form: `r(n,m) = (1/n) ∑_{m ≤ l ≤ k ≤ n} 1/(k l)`. -/ +theorem r_eq_explicit {n m : ℕ} (hm : 1 ≤ m) (hmn : m ≤ n) : + r n m = 1 / (n : ℚ) * ∑ k ∈ Finset.Icc m n, ∑ l ∈ Finset.Icc m k, 1 / ((k : ℚ) * l) := by + rw [r_eq_sum hm hmn, Finset.mul_sum] + have inner : ∀ k ∈ Finset.Icc 1 n, ∑ l ∈ Finset.Icc 1 n, A n k * A k l * A l m + = 1 / (n : ℚ) * ∑ l ∈ Finset.Icc m k, 1 / ((k : ℚ) * l) := by + intro k hk + rw [Finset.mem_Icc] at hk + rw [Finset.mul_sum] + have hsub : Finset.Icc m k ⊆ Finset.Icc 1 n := Finset.Icc_subset_Icc hm hk.2 + rw [← Finset.sum_subset hsub (f := fun l => A n k * A k l * A l m) ?_] + · refine Finset.sum_congr rfl fun l hl => ?_ + rw [Finset.mem_Icc] at hl + simp only [A, if_pos hk.2, if_pos hl.2, if_pos hl.1] + ring + · intro l _ hl' + simp only [Finset.mem_Icc, not_and_or, not_le] at hl' + simp only [A] + rcases hl' with h | h + · rw [if_neg (by omega : ¬ m ≤ l)]; simp + · rw [if_neg (by omega : ¬ l ≤ k)]; simp + rw [Finset.sum_congr rfl inner] + symm + apply Finset.sum_subset (Finset.Icc_subset_Icc hm le_rfl) + intro k hk hk' + simp only [Finset.mem_Icc, not_and, not_le] at hk hk' + have : Finset.Icc m k = ∅ := Finset.Icc_eq_empty (by omega) + simp [this] + +/-! ### A002944 and the conjecture -/ + +/-- `lcm(1, 2, …, n)` (A003418); `lcmUpTo 0 = 1`. -/ +def lcmUpTo (n : ℕ) : ℕ := (Finset.Icc 1 n).lcm id + +/-- A002944: `LCM(1, 2, …, n) / n` (exact division for `n ≥ 1`, see `A002944_mul`). -/ +def A002944 (n : ℕ) : ℕ := lcmUpTo n / n + +theorem A002944_mul {n : ℕ} (hn : 1 ≤ n) : A002944 n * n = lcmUpTo n := + Nat.div_mul_cancel (Finset.dvd_lcm (f := id) (Finset.mem_Icc.2 ⟨hn, le_rfl⟩)) + +/-- `A002944` reproduces the 31 listed terms of A002944 (kernel-checked). -/ +theorem A002944_data : (List.range 31).map (fun i => A002944 (i + 1)) = + [1, 1, 2, 3, 12, 10, 60, 105, 280, 252, 2520, 2310, 27720, 25740, 24024, 45045, 720720, + 680680, 12252240, 11639628, 11085360, 10581480, 232792560, 223092870, 1070845776, + 1029659400, 2974571600, 2868336900, 80313433200, 77636318760, 2329089562800] := by + decide +kernel + +/-- The conjecture: for every `n ≥ 1`, `a(n)/n³ = A002944(n)²` (here `a(n)/n³` is A027451(n), +the diagonal entry `a(n)·r(n,n)` of A027447, so this is the conjectured +`A027451(n) = A002944(n)²`). -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → (a n : ℚ) / (n : ℚ) ^ 3 = ((A002944 n : ℕ) : ℚ) ^ 2 + +/-- Equivalent integer form: `a(n) = n · lcm(1, …, n)²` for every `n ≥ 1`. -/ +theorem statement_iff : statement ↔ ∀ n : ℕ, 1 ≤ n → a n = n * lcmUpTo n ^ 2 := by + unfold statement + refine forall_congr' fun n => imp_congr_right fun hn => ?_ + have hn' : (n : ℚ) ≠ 0 := by exact_mod_cast (show n ≠ 0 by omega) + rw [← A002944_mul hn, div_eq_iff (pow_ne_zero 3 hn'), ← Nat.cast_inj (R := ℚ)] + push_cast + constructor <;> intro h <;> rw [h] <;> ring + +end Math0.Statements.A119936 diff --git a/lean/Math0/Statements/OEIS/A120069.lean b/lean/Math0/Statements/OEIS/A120069.lean new file mode 100644 index 0000000..d1486b9 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A120069.lean @@ -0,0 +1,218 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A120069: denominators of `∑_{k=1}^{n} C(k)/4^(k-1)` (Groux's and Staunton's conjectures) + +Source: https://oeis.org/A120069, _Groux Roland_, Dec 11 2010 and _Alexander Staunton_, +Feb 28 2026 (FORMULA section). Verbatim: +> Conjecture: a(n) = denominator(Catalan(n)/4^(n-1)). - _Groux Roland_, Dec 11 2010 +> +> Conjecture: a(n) = 2^(A283208(n)-2). - _Alexander Staunton_, Feb 28 2026 + +The sequence (offset `1`, by _Wolfdieter Lang_) is "Denominators of partial sums of a convergent +series involving scaled Catalan numbers A000108", where (COMMENTS/FORMULA) "The partial sums +r(n) = Sum_{k=1..n} C(k)/2^(2*(k-1)) are rationals (written in lowest terms)", `C = ` A000108 +(Catalan numbers), and "a(n) = denominator(r(n))". + +A283208 (offset `0`) is defined in its COMMENTS section: "a(n) is the least nonnegative integer +such that 2^a(n) (2n+1)/(n+1) c(2n) is a nonnegative integer, where c(2n) = c(2n-1) = +Pochhammer(1/2,n)/(n!)" (Vietoris' numbers). + +## Encoding + +* `r n : ℚ` is `∑_{k=1}^{n} C(k)/2^(2(k-1))` computed exactly in `ℚ` with Mathlib's `catalan` + (`k ≥ 1`, so `k - 1` is exact). Mathlib's `Rat` is always in lowest terms with positive + denominator, so `a n = (r n).den` is A120069's `a(n)` for `n ≥ 1`. (`a 0 = 1`, the denominator + of the empty sum, is not a term of the sequence and plays no role.) For the kernel, `catalan` is + replaced by the provably equal `catFast` (`catFast_eq`), and `a_data` checks all 27 listed + terms `a 1, …, a 27`. +* `pochhammer x n = x (x+1) ⋯ (x+n-1)` is the rising factorial (Mathematica's `Pochhammer`); + `pochhammer_eq_ascPochhammer` shows it is Mathlib's `ascPochhammer ℚ n` evaluated at `x`. + `vietoris n = Pochhammer(1/2, n)/n!` is `c(2n)`, and `w n = (2n+1)/(n+1) · c(2n)`. +* `IsNatExp n e` says `2^e · (2n+1)/(n+1) · c(2n)` is a nonnegative integer (literally: equals + `(m : ℚ)` for some `m : ℕ`). It is decidable (`exists_natCast_iff`), it holds for `e = 2n` + (`isNatExp_two_mul`, via `4^n c(2n) = C(2n, n)` and `(n+1) ∣ C(2n, n)`), so + `A283208 n = Nat.find …` is the least such `e`, exactly A283208's definition. `A283208_data` + checks all 63 listed terms `A283208 0, …, A283208 62` (kernel-checked through + `A283208_eq_of`, which uses that `IsNatExp n` is upward closed). +* *The conjecture.* Both conjectures are about the terms of A120069, i.e. `n ≥ 1`. Groux: + `a n = (C(n)/4^(n-1)).den` (with `n - 1` exact for `n ≥ 1`). Staunton: + `a(n) = 2^(A283208(n) - 2)`, stated in `ℚ` with an integer exponent, + `(a n : ℚ) = 2 ^ ((A283208 n : ℤ) - 2)`, so that no truncated natural subtraction is involved. + `statement` is the conjunction of the two, for every `n ≥ 1`. +-/ + +namespace Math0.Statements.A120069 + +open Finset + +/-! ### A120069 -/ + +/-- The partial sum `r(n) = ∑_{k=1}^{n} C(k)/2^(2(k-1))`, `C(k)` the Catalan numbers (A000108), +computed exactly in `ℚ`. -/ +def r (n : ℕ) : ℚ := ∑ k ∈ Finset.Icc 1 n, (catalan k : ℚ) / 2 ^ (2 * (k - 1)) + +/-- A120069 (offset `1`): `a(n)` is the denominator of `r(n) = ∑_{k=1}^{n} C(k)/2^(2(k-1))` +(in lowest terms). -/ +def a (n : ℕ) : ℕ := (r n).den + +/-- Catalan numbers by the recursion `C(k+1) = 2(2k+1) C(k)/(k+2)` (fast in the kernel). -/ +def catFast : ℕ → ℕ + | 0 => 1 + | k + 1 => catFast k * (2 * (2 * k + 1)) / (k + 2) + +theorem succ_succ_mul_catalan (k : ℕ) : + (k + 2) * catalan (k + 1) = 2 * (2 * k + 1) * catalan k := by + have h1 := succ_mul_catalan_eq_centralBinom (k + 1) + have h2 := succ_mul_catalan_eq_centralBinom k + have h3 := Nat.succ_mul_centralBinom_succ k + apply Nat.eq_of_mul_eq_mul_left (show 0 < k + 1 by omega) + calc (k + 1) * ((k + 2) * catalan (k + 1)) = (k + 1) * (k + 1).centralBinom := by + rw [← h1] + _ = 2 * (2 * k + 1) * ((k + 1) * catalan k) := by rw [h3, h2] + _ = (k + 1) * (2 * (2 * k + 1) * catalan k) := by ring + +theorem catFast_eq : ∀ k : ℕ, catFast k = catalan k + | 0 => by simp [catFast] + | k + 1 => by + rw [catFast, catFast_eq k, Nat.mul_comm, ← succ_succ_mul_catalan, + Nat.mul_div_cancel_left _ (by omega)] + +/-- `r` computed with `catFast`. -/ +def rFast (n : ℕ) : ℚ := ∑ k ∈ Finset.Icc 1 n, (catFast k : ℚ) / 2 ^ (2 * (k - 1)) + +theorem r_eq_rFast (n : ℕ) : r n = rFast n := by + simp [r, rFast, catFast_eq] + +/-- The definition reproduces all 27 terms listed in OEIS (`n = 1, …, 27`; kernel-checked). -/ +theorem a_data : (List.range 27).map (fun i => a (i + 1)) = + [1, 2, 16, 32, 128, 256, 4096, 8192, 32768, 65536, 524288, 1048576, 4194304, 8388608, + 268435456, 536870912, 2147483648, 4294967296, 34359738368, 68719476736, 274877906944, + 549755813888, 8796093022208, 17592186044416, 70368744177664, 140737488355328, + 1125899906842624] := by + have : a = fun n => (rFast n).den := funext fun n => by simp [a, r_eq_rFast] + rw [this] + decide +kernel + +/-! ### A283208 -/ + +/-- The rising factorial (Pochhammer symbol) `(x)_n = x (x+1) ⋯ (x+n-1)`. -/ +def pochhammer (x : ℚ) (n : ℕ) : ℚ := ∏ i ∈ Finset.range n, (x + i) + +/-- `pochhammer` is Mathlib's `ascPochhammer`. -/ +theorem pochhammer_eq_ascPochhammer (x : ℚ) (n : ℕ) : + pochhammer x n = (ascPochhammer ℚ n).eval x := by + induction n with + | zero => simp [pochhammer] + | succ n ih => rw [pochhammer, Finset.prod_range_succ, ← pochhammer, ih, ascPochhammer_succ_eval] + +/-- Vietoris' number `c(2n) = c(2n-1) = Pochhammer(1/2, n)/n!`. -/ +def vietoris (n : ℕ) : ℚ := pochhammer (1 / 2) n / (n.factorial : ℚ) + +/-- `(2n+1)/(n+1) · c(2n)`. -/ +def w (n : ℕ) : ℚ := (2 * n + 1) / (n + 1) * vietoris n + +/-- `2^e · (2n+1)/(n+1) · c(2n)` is a nonnegative integer. -/ +def IsNatExp (n e : ℕ) : Prop := ∃ m : ℕ, (2 : ℚ) ^ e * w n = m + +theorem exists_natCast_iff (q : ℚ) : (∃ m : ℕ, q = m) ↔ q.den = 1 ∧ 0 ≤ q := by + constructor + · rintro ⟨m, rfl⟩ + exact ⟨Rat.den_natCast m, Nat.cast_nonneg m⟩ + · rintro ⟨h1, h2⟩ + refine ⟨q.num.toNat, ?_⟩ + have hnum : 0 ≤ q.num := Rat.num_nonneg.mpr h2 + have hq : (q.num : ℚ) = q := Rat.coe_int_num_of_den_eq_one h1 + rw [← hq] + have : ((q.num.toNat : ℕ) : ℤ) = q.num := Int.toNat_of_nonneg hnum + exact_mod_cast this.symm + +instance (n : ℕ) : DecidablePred (IsNatExp n) := fun e => + decidable_of_iff _ (exists_natCast_iff ((2 : ℚ) ^ e * w n)).symm + +/-- `4^n c(2n) = C(2n, n)`. -/ +theorem four_pow_mul_vietoris (n : ℕ) : (4 : ℚ) ^ n * vietoris n = n.centralBinom := by + induction n with + | zero => simp [vietoris, pochhammer] + | succ n ih => + have h3 := Nat.succ_mul_centralBinom_succ n + have hcb : ((n + 1).centralBinom : ℚ) = 2 * (2 * n + 1) * n.centralBinom / (n + 1) := by + rw [eq_div_iff (by positivity)] + exact_mod_cast (by rw [mul_comm]; exact h3 : + (n + 1).centralBinom * (n + 1) = 2 * (2 * n + 1) * n.centralBinom) + rw [hcb, ← ih] + simp only [vietoris, pochhammer, Finset.prod_range_succ, Nat.factorial_succ, Nat.cast_mul, + Nat.cast_succ, pow_succ] + field_simp + ring + +theorem isNatExp_two_mul (n : ℕ) : IsNatExp n (2 * n) := by + refine ⟨(2 * n + 1) * (n.centralBinom / (n + 1)), ?_⟩ + rw [Nat.cast_mul, Nat.cast_div (Nat.succ_dvd_centralBinom n) (by positivity), w, pow_mul, + show ((2 : ℚ) ^ 2) = 4 by norm_num, ← four_pow_mul_vietoris] + push_cast + field_simp + +/-- A283208 (offset `0`): the least nonnegative integer `e` such that `2^e (2n+1)/(n+1) c(2n)` +is a nonnegative integer, `c(2n) = Pochhammer(1/2, n)/n!`. -/ +def A283208 (n : ℕ) : ℕ := Nat.find ⟨2 * n, isNatExp_two_mul n⟩ + +theorem isNatExp_succ {n e : ℕ} (h : IsNatExp n e) : IsNatExp n (e + 1) := by + obtain ⟨m, hm⟩ := h + exact ⟨2 * m, by rw [pow_succ, mul_comm ((2 : ℚ) ^ e), mul_assoc, hm]; push_cast; ring⟩ + +theorem isNatExp_mono {n e f : ℕ} (h : IsNatExp n e) (hef : e ≤ f) : IsNatExp n f := by + induction f, hef using Nat.le_induction with + | base => exact h + | succ f _ ih => exact isNatExp_succ ih + +theorem A283208_eq_of {n v : ℕ} (h1 : IsNatExp n v) (h2 : v = 0 ∨ ¬ IsNatExp n (v - 1)) : + A283208 n = v := by + rw [A283208, Nat.find_eq_iff] + refine ⟨h1, fun m hm hP => ?_⟩ + rcases h2 with h2 | h2 + · omega + · exact h2 (isNatExp_mono hP (by omega)) + +/-- Boolean check that `v` is the least exponent for `n`. -/ +def checkA283208 (n v : ℕ) : Bool := + decide (IsNatExp n v) && (v == 0 || !decide (IsNatExp n (v - 1))) + +theorem A283208_eq_of_check {n v : ℕ} (h : checkA283208 n v = true) : A283208 n = v := by + simp only [checkA283208, Bool.and_eq_true, decide_eq_true_eq, Bool.or_eq_true, beq_iff_eq, + Bool.not_eq_true', decide_eq_false_iff_not] at h + exact A283208_eq_of h.1 h.2 + +theorem map_eq_of_check {f : ℕ → ℕ} {c : ℕ → ℕ → Bool} (hc : ∀ n v, c n v = true → f n = v) + {N : ℕ} {L : List ℕ} (hN : L.length = N) (h : ∀ i < L.length, c i (L.getD i 0) = true) : + (List.range N).map f = L := by + subst hN + apply List.ext_getElem (by simp) + intro i h1 h2 + rw [List.getElem_map, List.getElem_range] + have := h i h2 + rw [List.getD_eq_getElem _ _ h2] at this + exact hc _ _ this + +/-- The definition of A283208 reproduces all 63 terms listed in OEIS (`n = 0, …, 62`; +kernel-checked). -/ +theorem A283208_data : (List.range 63).map A283208 = + [0, 2, 3, 6, 7, 9, 10, 14, 15, 17, 18, 21, 22, 24, 25, 30, 31, 33, 34, 37, 38, 40, 41, 45, 46, + 48, 49, 52, 53, 55, 56, 62, 63, 65, 66, 69, 70, 72, 73, 77, 78, 80, 81, 84, 85, 87, 88, 93, + 94, 96, 97, 100, 101, 103, 104, 108, 109, 111, 112, 115, 116, 118, 119] := by + refine map_eq_of_check (c := checkA283208) (fun _ _ h => A283208_eq_of_check h) rfl ?_ + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjectures (Groux 2010, Staunton 2026, A120069): for every `n ≥ 1`, +`a(n) = denominator(Catalan(n)/4^(n-1))` and `a(n) = 2^(A283208(n) - 2)`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + a n = ((catalan n : ℚ) / 4 ^ (n - 1)).den ∧ + (a n : ℚ) = (2 : ℚ) ^ ((A283208 n : ℤ) - 2) + +end Math0.Statements.A120069 diff --git a/lean/Math0/Statements/OEIS/A121750.lean b/lean/Math0/Statements/OEIS/A121750.lean new file mode 100644 index 0000000..5f08404 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A121750.lean @@ -0,0 +1,446 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A121750: columns of even length in deco polyominoes (Mathar's recurrence) + +Source: https://oeis.org/A121750, _R. J. Mathar_, Jul 26 2022 (FORMULA section). Verbatim: +> Conjecture D-finite with recurrence a(n) +(-n-2)*a(n-1) +(-n^2+4*n-2)*a(n-2) +> +(n^3-3*n^2-4*n+11)*a(n-3) -(n-1)*(n^2-11*n+26)*a(n-4) +(-n^3+5*n^2+7*n-43)*a(n-5) +> +(n-3)*(n-5)^2*a(n-6)=0. - _R. J. Mathar_, Jul 26 2022 + +The entry (Emeric Deutsch, Aug 20 2006, offset `1`) is "Number of columns of even length in all +deco polyominoes of height n. A deco polyomino is a directed column-convex polyomino in which the +height, measured along the diagonal, is attained only in the last column." + +## Encoding + +* *Directed column-convex polyominoes as column lists.* Cells are `(x, y)`, `x` the column. + A polyomino is counted up to translation. In a directed column-convex polyomino every column is + a vertical segment of cells, and every cell is reached from the source cell by a path of north + and east unit steps inside the polyomino; the source is the bottom cell of the first column. + Translating the source to `(0, 0)`, the polyomino is determined by its list of columns + `[(b₀, t₀), …, (b_k, t_k)]`: column `i` is the set of cells `(i, y)` with `bᵢ ≤ y ≤ tᵢ`. The + constraints are `bᵢ ≤ tᵢ` (nonempty column), `b₀ = 0` (source at the origin), and the + directedness condition `bᵢ ≤ bᵢ₊₁ ≤ tᵢ`: the bottom cell `(i+1, bᵢ₊₁)` of a column can only be + entered from the west, so `(i, bᵢ₊₁)` must be a cell of column `i`; conversely, under these + conditions every cell is reached by climbing column `0`, stepping east, climbing, and so on. + Distinct lists give distinct polyominoes. (`IsDeco` writes these conditions with list indices.) +* *Height along the diagonal.* The height measured along the diagonal is the number of diagonals + `x + y = const` met by the polyomino, `max (x + y) - min (x + y) + 1`. The minimum is `0`, at + the source, and the largest value of `x + y` in column `i` is `i + tᵢ` (its top cell). So the + height is `n` iff `i + tᵢ + 1 ≤ n` for all `i`, with equality for some `i`; a column attains the + height iff `i + tᵢ + 1 = n`, and "attained only in the last column" says that this forces + `i = k`. There is no deco polyomino of height `0` (`isDeco_zero`), so `a 0 = 0` (not a term). +* *The sequence.* A column `(b, t)` has length `t - b + 1`. `a n` is the sum, over the deco + polyominoes of height `n`, of their number of columns of even length (`evenCols`). The deco + polyominoes of height `n` are enumerated by the list `decos n` (built column by column by + `tails`), and `mem_decos`, `nodup_decos` prove that `decos n` lists exactly the column lists + satisfying `IsDeco n`, each once. So `a n = Σ_{P deco of height n} evenCols P`, literally the + OEIS definition. + For example, the deco polyominoes of height `2` are the vertical domino `[(0, 1)]` (one column + of even length) and the horizontal domino `[(0, 0), (1, 0)]` (none), so `a 2 = 1`, as in the + entry's example. The translation from cell sets to column lists above is the standard one and is + argued here in prose only; the checks below test the encoding against the OEIS data. +* *Checks.* Directly from the enumeration (kernel): `a 1, …, a 6` (`a_data_direct`), the numbers + of deco polyominoes of heights `1, …, 6` are `1!, …, 6!` (`decos_length_data_direct`; these + are the row sums of A121748, a well-known property of deco polyominoes), and rows `1..6` of the + triangle A121748 ("number of deco polyominoes of height n having k columns of even length"), + `triangle_data`. For speed, + `tab` computes the pair (number of completions, total number of even columns) for each state of + the column-by-column construction by dynamic programming; `tab_getD` proves it correct for all + arguments, so `a = aDP` (`a_eq_aDP`), and `a_data` checks all 19 listed terms `a 1, …, a 19`; + `decos_length_data` checks that there are `n!` deco polyominoes of height `n` for + `n = 1, …, 19`. +* *The conjecture.* No range of `n` is given. The recurrence involves `a(n-6)`, and the sequence + starts at `a(1)` (offset `1`), so it is stated for every `n ≥ 7`, in `ℤ`, with no other + hypothesis. `recurrence_data` checks the transcription on the listed terms (`7 ≤ n ≤ 19`). +-/ + +namespace Math0.Statements.A121750 + +/-! ### Deco polyominoes -/ + +/-- `IsDeco n cs`: the column list `cs = [(b₀, t₀), …, (b_k, t_k)]` describes a deco polyomino of +height `n`, with source cell `(0, 0)`; column `i` consists of the cells `(i, y)`, +`bᵢ ≤ y ≤ tᵢ`. -/ +def IsDeco (n : ℕ) (cs : List (ℕ × ℕ)) : Prop := + -- at least one column, and every column is a nonempty vertical segment + cs ≠ [] ∧ + (∀ c ∈ cs, c.1 ≤ c.2) ∧ + -- the source `(0, 0)` is the bottom cell of the first column + (∀ c ∈ cs.head?, c.1 = 0) ∧ + -- directed: the bottom cell of column `i + 1` has its west neighbour in column `i` + (∀ i (h : i + 1 < cs.length), cs[i].1 ≤ cs[i + 1].1 ∧ cs[i + 1].1 ≤ cs[i].2) ∧ + -- height `n` along the diagonal: `max (x + y) + 1 = n` over the cells (`min (x + y) = 0`) + (∀ i (h : i < cs.length), i + cs[i].2 + 1 ≤ n) ∧ + (∃ i, ∃ h : i < cs.length, i + cs[i].2 + 1 = n) ∧ + -- the height is attained only in the last column + (∀ i (h : i < cs.length), i + cs[i].2 + 1 = n → i + 1 = cs.length) + +/-- `tails r b`: the column lists `[(b, t₀), (b₁, t₁), …]` whose first column has bottom `b`, +with nonempty columns and the directedness condition, such that `i + tᵢ ≤ r` for every column +`i`, with equality exactly for the last column (`mem_tails`). The first column `(b, t)` is either +the last one (`t = r`), or `b ≤ t < r` and the remaining columns form a list in `tails (r - 1) b'` +with `b ≤ b' ≤ t`. -/ +def tails : ℕ → ℕ → List (List (ℕ × ℕ)) + | 0, b => if b = 0 then [[(b, 0)]] else [] + | r + 1, b => (if b ≤ r + 1 then [[(b, r + 1)]] else []) ++ + (List.range' b (r + 1 - b)).flatMap fun t => + ((List.range' b (t + 1 - b)).flatMap (tails r)).map ((b, t) :: ·) + +/-- All deco polyominoes of height `n` (as column lists), each listed once (`mem_decos`, +`nodup_decos`). -/ +def decos : ℕ → List (List (ℕ × ℕ)) + | 0 => [] + | n + 1 => tails n 0 + +/-- The number of columns of even length (`t - b + 1`) of a polyomino. -/ +def evenCols (cs : List (ℕ × ℕ)) : ℕ := + cs.countP fun c => (c.2 + 1 - c.1) % 2 == 0 + +/-- A121750: the number of columns of even length in all deco polyominoes of height `n`. -/ +def a (n : ℕ) : ℕ := ((decos n).map evenCols).sum + +/-- The definition, evaluated directly by enumerating the polyominoes, reproduces the first 6 +listed terms (kernel-checked). All 19 listed terms are checked in `a_data` below. -/ +theorem a_data_direct : (List.range 6).map (fun i => a (i + 1)) = + [0, 1, 5, 26, 184, 1338] := by + decide +kernel + +/-- There are `n!` deco polyominoes of height `n` (the row sums of A121748), `n = 1, …, 6`, +counted directly. -/ +theorem decos_length_data_direct : (List.range 6).map (fun i => (decos (i + 1)).length) = + [1, 2, 6, 24, 120, 720] := by + decide +kernel + +/-- Rows `1..6` of A121748: the number of deco polyominoes of height `n` with `k` columns of +even length, `0 ≤ k < n`, counted directly. -/ +theorem triangle_data : (List.range 6).map (fun i => + (List.range (i + 1)).map fun k => ((decos (i + 1)).filter fun P => evenCols P == k).length) = + [[1], [1, 1], [2, 3, 1], [6, 11, 6, 1], [16, 44, 42, 16, 2], [66, 209, 254, 147, 40, 4]] := by + decide +kernel + +/-! ### `decos n` lists exactly the deco polyominoes of height `n`, each once -/ + +/-- The conditions satisfied by the members of `tails r b`. -/ +def IsTail (r b : ℕ) (cs : List (ℕ × ℕ)) : Prop := + cs ≠ [] ∧ + (∀ c ∈ cs, c.1 ≤ c.2) ∧ + (∀ c ∈ cs.head?, c.1 = b) ∧ + (∀ i (h : i + 1 < cs.length), cs[i].1 ≤ cs[i + 1].1 ∧ cs[i + 1].1 ≤ cs[i].2) ∧ + (∀ i (h : i < cs.length), i + cs[i].2 ≤ r) ∧ + (∀ i (h : i < cs.length), i + cs[i].2 = r ↔ i + 1 = cs.length) + +theorem isTail_zero (b : ℕ) (cs : List (ℕ × ℕ)) : + IsTail 0 b cs ↔ b = 0 ∧ cs = [(b, 0)] := by + constructor + · rintro ⟨hne, hle, hhd, -, hdiag, hlast⟩ + rcases cs with _ | ⟨c, l⟩ + · exact absurd rfl hne + · have h0 := hdiag 0 (by simp) + have h1 := (hlast 0 (by simp)).1 (by simp at h0 ⊢; omega) + have hb := hhd c (by simp) + have hc := hle c (by simp) + simp at h0 h1 + obtain ⟨c1, c2⟩ := c + simp at h0 hb hc + subst h1 + refine ⟨by omega, ?_⟩ + simp only [List.cons.injEq, Prod.mk.injEq, and_true] + omega + · rintro ⟨rfl, rfl⟩ + refine ⟨by simp, by simp, by simp, ?_, ?_, ?_⟩ + · intro i hi; simp at hi + · intro i hi; simp at hi; subst hi; simp + · intro i hi; simp at hi; subst hi; simp + +theorem isTail_cons_succ (r b : ℕ) (c : ℕ × ℕ) (l : List (ℕ × ℕ)) : + IsTail (r + 1) b (c :: l) ↔ c.1 = b ∧ c.1 ≤ c.2 ∧ + ((l = [] ∧ c.2 = r + 1) ∨ (c.2 < r + 1 ∧ ∃ b', c.1 ≤ b' ∧ b' ≤ c.2 ∧ IsTail r b' l)) := by + constructor + · rintro ⟨-, hle, hhd, hdir, hdiag, hlast⟩ + have hb : c.1 = b := hhd c (by simp) + have hc : c.1 ≤ c.2 := hle c (by simp) + refine ⟨hb, hc, ?_⟩ + rcases l with _ | ⟨d, l⟩ + · left + have := (hlast 0 (by simp)).2 (by simp) + simpa using this + · right + have h0 := hdiag 0 (by simp) + have h0' := hlast 0 (by simp) + have hd := hdir 0 (by simp) + simp at h0 h0' hd + refine ⟨by omega, d.1, hd.1, hd.2, ?_⟩ + refine ⟨by simp, fun x hx => hle x (by simp [hx]), by simp, ?_, ?_, ?_⟩ + · intro i hi + have := hdir (i + 1) (by simp at hi ⊢; omega) + simpa using this + · intro i hi + have := hdiag (i + 1) (by simp at hi ⊢; omega) + simp at this ⊢; omega + · intro i hi + have := hlast (i + 1) (by simp at hi ⊢; omega) + simp at this ⊢; omega + · rintro ⟨hb, hc, ⟨rfl, h2⟩ | ⟨hlt, b', h1, h2, hne, hle, hhd, hdir, hdiag, hlast⟩⟩ + · refine ⟨by simp, by simpa using hc, by simpa using hb, ?_, ?_, ?_⟩ + · intro i hi; simp at hi + · intro i hi; simp at hi; subst hi; simp; omega + · intro i hi; simp at hi; subst hi; simp; omega + · rcases l with _ | ⟨d, l⟩ + · exact absurd rfl hne + have hd : d.1 = b' := hhd d (by simp) + refine ⟨by simp, ?_, by simpa using hb, ?_, ?_, ?_⟩ + · intro x hx + simp only [List.mem_cons] at hx + rcases hx with rfl | hx + · exact hc + · exact hle x (by simp [hx]) + · intro i hi + rcases i with _ | i + · simp; omega + · have := hdir i (by simp at hi ⊢; omega) + simpa using this + · intro i hi + rcases i with _ | i + · simp; omega + · have := hdiag i (by simp at hi ⊢; omega) + simp at this ⊢; omega + · intro i hi + rcases i with _ | i + · simp; omega + · have := hlast i (by simp at hi ⊢; omega) + simp at this ⊢; omega + +theorem nil_not_isTail (r b : ℕ) : ¬ IsTail r b [] := fun h => h.1 rfl + +theorem mem_tails (r b : ℕ) (cs : List (ℕ × ℕ)) : cs ∈ tails r b ↔ IsTail r b cs := by + induction r generalizing b cs with + | zero => + rw [isTail_zero, tails] + split_ifs with h <;> simp [h] + | succ r ih => + rcases cs with _ | ⟨c, l⟩ + · simp only [tails, List.mem_append, List.mem_flatMap, List.mem_map] + refine iff_of_false ?_ (nil_not_isTail _ _) + rintro (h | ⟨t, -, x, -, hx⟩) + · split_ifs at h <;> simp at h + · exact List.cons_ne_nil _ _ hx + · rw [isTail_cons_succ] + simp only [tails, List.mem_append, List.mem_flatMap, List.mem_map, ih, List.mem_range'_1] + obtain ⟨c1, c2⟩ := c + constructor + · rintro (h | ⟨t, ht, x, ⟨b', hb', hx⟩, hxe⟩) + · split_ifs at h with hb + · simp at h + obtain ⟨⟨rfl, rfl⟩, rfl⟩ := h + exact ⟨rfl, hb, Or.inl ⟨rfl, rfl⟩⟩ + · simp at h + · simp only [List.cons.injEq, Prod.mk.injEq] at hxe + obtain ⟨⟨rfl, rfl⟩, rfl⟩ := hxe + refine ⟨rfl, by omega, Or.inr ⟨by omega, b', by omega, by omega, hx⟩⟩ + · rintro ⟨rfl, hc, ⟨rfl, rfl⟩ | ⟨hlt, b', h1, h2, hx⟩⟩ + · left + simp only at hc + rw [if_pos hc] + simp + · right + exact ⟨c2, ⟨by simpa using h1.trans h2, by simp at hlt ⊢; omega⟩, l, + ⟨b', ⟨by simpa using h1, by simp at h2 ⊢; omega⟩, hx⟩, rfl⟩ + +theorem isDeco_zero (cs : List (ℕ × ℕ)) : ¬ IsDeco 0 cs := by + rintro ⟨-, -, -, -, -, ⟨i, hi, h⟩, -⟩ + omega + +theorem isDeco_succ (r : ℕ) (cs : List (ℕ × ℕ)) : IsDeco (r + 1) cs ↔ IsTail r 0 cs := by + constructor + · rintro ⟨hne, hle, hhd, hdir, hdiag, ⟨j, hj, hjn⟩, hlast⟩ + refine ⟨hne, hle, hhd, hdir, fun i hi => by have := hdiag i hi; omega, ?_⟩ + intro i hi + refine ⟨fun h => hlast i hi (by omega), fun h => ?_⟩ + have := hlast j hj hjn + obtain rfl : i = j := by omega + omega + · rintro ⟨hne, hle, hhd, hdir, hdiag, hlast⟩ + refine ⟨hne, hle, hhd, hdir, fun i hi => by have := hdiag i hi; omega, ?_, + fun i hi h => (hlast i hi).1 (by omega)⟩ + refine ⟨cs.length - 1, by have := List.length_pos_iff.2 hne; omega, ?_⟩ + have := (hlast (cs.length - 1) (by have := List.length_pos_iff.2 hne; omega)).2 + (by have := List.length_pos_iff.2 hne; omega) + omega + +/-- `decos n` consists exactly of the deco polyominoes of height `n`. -/ +theorem mem_decos (n : ℕ) (cs : List (ℕ × ℕ)) : cs ∈ decos n ↔ IsDeco n cs := by + cases n with + | zero => simp [decos, isDeco_zero] + | succ r => rw [decos, mem_tails, isDeco_succ] + +theorem head_of_mem_tails {r b : ℕ} {x : List (ℕ × ℕ)} (h : x ∈ tails r b) : + ∃ t l, x = (b, t) :: l := by + rw [mem_tails] at h + obtain ⟨hne, -, hhd, -⟩ := h + rcases x with _ | ⟨⟨c1, c2⟩, l⟩ + · exact absurd rfl hne + · have := hhd (c1, c2) (by simp) + simp at this + exact ⟨c2, l, by rw [this]⟩ + +theorem nodup_tails (r b : ℕ) : (tails r b).Nodup := by + induction r generalizing b with + | zero => rw [tails]; split_ifs <;> simp + | succ r ih => + rw [tails, List.nodup_append] + refine ⟨by split_ifs <;> simp, ?_, ?_⟩ + · refine List.nodup_flatMap.2 ⟨fun t _ => ?_, ?_⟩ + · refine List.Nodup.map List.cons_injective (List.nodup_flatMap.2 ⟨fun b' _ => ih b', ?_⟩) + refine (List.nodup_range' (s := b) (n := t + 1 - b)).imp fun {b₁ b₂} hne => ?_ + refine List.disjoint_left.2 fun x h₁ h₂ => hne ?_ + obtain ⟨t₁, l₁, rfl⟩ := head_of_mem_tails h₁ + obtain ⟨t₂, l₂, h⟩ := head_of_mem_tails h₂ + simp only [List.cons.injEq, Prod.mk.injEq] at h + exact h.1.1 + · refine (List.nodup_range' (s := b) (n := r + 1 - b)).imp fun {t₁ t₂} hne => ?_ + refine List.disjoint_left.2 fun x h₁ h₂ => hne ?_ + simp only [List.mem_map] at h₁ h₂ + obtain ⟨y₁, -, rfl⟩ := h₁ + obtain ⟨y₂, -, h⟩ := h₂ + simp only [List.cons.injEq, Prod.mk.injEq] at h + exact h.1.2.symm + · intro x hx y hy hxy + subst hxy + split_ifs at hx + · simp only [List.mem_singleton] at hx + subst hx + simp only [List.mem_flatMap, List.mem_map, List.mem_range'_1] at hy + obtain ⟨t, ht, z, -, hz⟩ := hy + simp only [List.cons.injEq, Prod.mk.injEq] at hz + omega + · simp at hx + +/-- `decos n` lists every deco polyomino of height `n` only once. -/ +theorem nodup_decos (n : ℕ) : (decos n).Nodup := by + cases n with + | zero => simp [decos] + | succ r => exact nodup_tails r 0 + +/-! ### Fast evaluation by dynamic programming -/ + +/-- `1` if the column `(b, t)` has even length, else `0`. -/ +def eo (b t : ℕ) : ℕ := if (t + 1 - b) % 2 = 0 then 1 else 0 + +/-- From the row `T` for budget `r` (entry `b'`: number of lists in `tails r b'` and their total +number of even columns), the row for budget `r + 1`, following the recursion of `tails`. -/ +def nextRow (r : ℕ) (T : List (ℕ × ℕ)) : List (ℕ × ℕ) := + (List.range (r + 2)).map fun b => + (1 + ((List.range' b (r + 1 - b)).map fun t => + ((List.range' b (t + 1 - b)).map fun b' => (T.getD b' (0, 0)).1).sum).sum, + eo b (r + 1) + ((List.range' b (r + 1 - b)).map fun t => + eo b t * ((List.range' b (t + 1 - b)).map fun b' => (T.getD b' (0, 0)).1).sum + + ((List.range' b (t + 1 - b)).map fun b' => (T.getD b' (0, 0)).2).sum).sum) + +/-- `(tab r).getD b (0, 0) = ((tails r b).length, total even columns over tails r b)` +(`tab_getD`). -/ +def tab : ℕ → List (ℕ × ℕ) + | 0 => [(1, 0)] + | r + 1 => nextRow r (tab r) + +/-- `a`, computed by dynamic programming (`a_eq_aDP`). -/ +def aDP : ℕ → ℕ + | 0 => 0 + | n + 1 => ((tab n).getD 0 (0, 0)).2 + +theorem evenCols_cons (b t : ℕ) (x : List (ℕ × ℕ)) : + evenCols ((b, t) :: x) = eo b t + evenCols x := by + simp only [evenCols, List.countP_cons, eo] + split_ifs with h1 h2 h2 <;> simp_all; omega + +theorem sum_evenCols_map_cons (b t : ℕ) (X : List (List (ℕ × ℕ))) : + ((X.map ((b, t) :: ·)).map evenCols).sum = eo b t * X.length + (X.map evenCols).sum := by + induction X with + | nil => simp + | cons x X ih => + simp only [List.map_cons, List.sum_cons, List.length_cons, evenCols_cons] at ih ⊢ + rw [ih]; ring + +theorem sum_map_flatMap {α β : Type*} (l : List α) (f : α → List β) (g : β → ℕ) : + ((l.flatMap f).map g).sum = (l.map fun x => ((f x).map g).sum).sum := by + induction l with + | nil => simp + | cons x l ih => simp [List.flatMap_cons, List.sum_append, ih] + +theorem evenCols_nil : evenCols [] = 0 := rfl + +theorem tab_getD (r b : ℕ) : + (tab r).getD b (0, 0) = ((tails r b).length, ((tails r b).map evenCols).sum) := by + induction r generalizing b with + | zero => + rcases b with _ | b + · decide + · simp [tab, tails] + | succ r ih => + rw [tab, nextRow, List.getD_eq_getElem?_getD, List.getElem?_map] + by_cases hb : b < r + 2 + · rw [List.getElem?_range hb] + simp only [Option.map_some, Option.getD_some, ih] + rw [tails, if_pos (by omega)] + simp only [List.length_append, List.length_singleton, List.length_flatMap, + List.length_map, List.map_append, List.sum_append, List.map_cons, List.map_nil, + List.sum_cons, List.sum_nil, sum_map_flatMap, sum_evenCols_map_cons, evenCols_cons, + evenCols_nil] + refine Prod.ext ?_ ?_ + · simp only + · simp only; ring + · rw [List.getElem?_eq_none_iff.2 (by simp; omega)] + rw [tails, if_neg (by omega), show r + 1 - b = 0 by omega] + simp + +theorem a_eq_aDP (n : ℕ) : a n = aDP n := by + cases n with + | zero => rfl + | succ r => rw [a, decos, aDP, tab_getD] + +/-- The number of lists in `tails r b`, read off the table. -/ +theorem length_tails (r b : ℕ) : (tails r b).length = ((tab r).getD b (0, 0)).1 := by + rw [tab_getD] + +/-- The definition reproduces all 19 terms listed in OEIS, `a 1, …, a 19` (kernel-checked, through +the proven-equal `aDP`). -/ +theorem a_data : (List.range 19).map (fun i => a (i + 1)) = + [0, 1, 5, 26, 184, 1338, 11652, 108210, 1140336, 12849714, 159858900, 2117522754, + 30442090248, 463511103426, 7569181895436, 130254363597330, 2383020441932256, + 45738553437874962, 927010880040945924] := by + simp only [a_eq_aDP] + decide +kernel + +/-- There are `n!` deco polyominoes of height `n`, for `n = 1, …, 19` (kernel-checked). -/ +theorem decos_length_data : (List.range 19).map (fun i => (decos (i + 1)).length) = + (List.range 19).map (fun i => (i + 1).factorial) := by + simp only [decos, length_tails] + decide +kernel + +/-- Mathar's conjectured recurrence: for every `n ≥ 7`, +`a(n) - (n+2)·a(n-1) + (-n²+4n-2)·a(n-2) + (n³-3n²-4n+11)·a(n-3) - (n-1)(n²-11n+26)·a(n-4) ++ (-n³+5n²+7n-43)·a(n-5) + (n-3)(n-5)²·a(n-6) = 0` (computed in `ℤ`). -/ +def statement : Prop := + ∀ n : ℕ, 7 ≤ n → + (a n : ℤ) + (-(n : ℤ) - 2) * a (n - 1) + (-(n : ℤ) ^ 2 + 4 * n - 2) * a (n - 2) + + ((n : ℤ) ^ 3 - 3 * n ^ 2 - 4 * n + 11) * a (n - 3) - + ((n : ℤ) - 1) * ((n : ℤ) ^ 2 - 11 * n + 26) * a (n - 4) + + (-(n : ℤ) ^ 3 + 5 * n ^ 2 + 7 * n - 43) * a (n - 5) + + ((n : ℤ) - 3) * ((n : ℤ) - 5) ^ 2 * a (n - 6) = 0 + +/-- Sanity check of the transcription: the recurrence of `statement` holds on the listed terms, +`7 ≤ n ≤ 19` (kernel-checked; this says nothing about larger `n`). -/ +theorem recurrence_data : ∀ n ∈ List.range' 7 13, + (a n : ℤ) + (-(n : ℤ) - 2) * a (n - 1) + (-(n : ℤ) ^ 2 + 4 * n - 2) * a (n - 2) + + ((n : ℤ) ^ 3 - 3 * n ^ 2 - 4 * n + 11) * a (n - 3) - + ((n : ℤ) - 1) * ((n : ℤ) ^ 2 - 11 * n + 26) * a (n - 4) + + (-(n : ℤ) ^ 3 + 5 * n ^ 2 + 7 * n - 43) * a (n - 5) + + ((n : ℤ) - 3) * ((n : ℤ) - 5) ^ 2 * a (n - 6) = 0 := by + simp only [a_eq_aDP] + decide +kernel + +end Math0.Statements.A121750 diff --git a/lean/Math0/Statements/OEIS/A123710.lean b/lean/Math0/Statements/OEIS/A123710.lean new file mode 100644 index 0000000..4a860d1 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A123710.lean @@ -0,0 +1,475 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A123710: rows of the inverse of `⌊n/k⌋` with exactly four nonzero entries + +Source: https://oeis.org/A123710, M. F. Hasler, Feb 12 2012 (FORMULA section). Verbatim: +> a(n) = A025475(n) for n>2 (conjectured). - _M. F. Hasler_, Feb 12 2012 + +The entry (Paul D. Hanna, Oct 09 2006, offset `1`) is "Indices k such that 4 = A123709(k) = +number of nonzero terms in row k of triangle A123706", where "Triangle A123706 is the matrix +inverse of triangle A010766, where A010766(n,k) = [n/k]". Its data start `4, 6, 8, 9, 16, 25, …`. +A025475 (offset `1`) is "1 and the prime powers p^m where m >= 2, thus excluding the primes": +`1, 4, 8, 9, 16, 25, …`. So the conjecture says that from the third term on, A123710 lists exactly +the proper prime powers. + +## Encoding + +* A010766 is the lower triangular matrix `A(n,k) = ⌊n/k⌋` (`n ≥ k ≥ 1`, and `0` above the + diagonal). `floorMat N` is its `N × N` truncation, indexed from `0`: entry `(i, j)` is + `⌊(i+1)/(j+1)⌋`, which is `0` for `j > i` (PARI: `matrix(N, N, r, c, r\c)`). +* A123706 is the matrix inverse of A010766. Since A010766 is lower triangular with ones on the + diagonal, row `n` of its inverse is the last row of the inverse of the `n × n` truncation. + `A123706 n k` is entry `(n, k)` of `(floorMat n)⁻¹` (Mathlib's `Matrix.inv`) for `1 ≤ k ≤ n`, + and `0` otherwise. This is the PARI program of A123709, + `#select((matrix(n, n, r, c, r\c)^-1)[n,], x->x)`. `A123706_eq_inv` checks that every larger + truncation gives the same entry. +* `A123709 n` is the number of `k ∈ [1, n]` with `A123706 n k ≠ 0` (so `A123709 0 = 0`). +* `IsTerm n` is `A123709 n = 4`, and `a n = Nat.nth IsTerm (n - 1)` is the `n`-th smallest such + index (offset `1`). `0` is never a term. `a` is noncomputable as written. +* `IsA025475 m` is `m = 1 ∨ ∃ p k, p.Prime ∧ 2 ≤ k ∧ m = p ^ k`, and + `A025475 n = Nat.nth IsA025475 (n - 1)` (offset `1`). +* Computation. `row n` computes row `n` of the inverse by back substitution in `T · A = I`: + `T(n,n) = 1` and `T(n,k) = -∑_{j=k+1}^{n} T(n,j) ⌊j/k⌋` for `k < n`. `Tmat_eq_inv` proves + that these rows form the inverse of every truncation, so `A123706 = T` (`A123706_eq_T`). For + speed, the data checks use `Rf`, the same back substitution that keeps only the nonzero entries, + written with `Nat.rec`/`List.rec` and kernel-accelerated `Nat` operations (so it is + noncomputable for the compiler but cheap for the kernel); `A123709_eq_Rf` proves + `A123709 = Rf`. +* Data checks (kernel): `A123706_data` checks all `113` listed terms of A123706, `A123709_data` + all `76` listed terms of A123709, `a_data` the first `21` of the `52` listed terms of A123710 + (all terms `≤ 512`; the kernel has to run the back substitution for every `n ≤ 512`, at a cost + of about `n` steps each, which is what limits the range), and `A025475_data` the first `21` + listed terms of A025475 (all terms `≤ 512`, decided through a trial-division search for the + least prime factor, `isA025475_iff`). From index `3` on the two lists agree. +* `statement`: `∀ n > 2, a n = A025475 n`, exactly as in the formula line ("for n>2"), with + both sequences indexed from `1`. With `Nat.nth`, if A123710 were finite then `a n = 0` past its + end; since A025475 is infinite with positive terms, the statement would then be false, as the + conjecture would be. +-/ + +namespace Math0.Statements.A123710 + +open Finset + +/-! ### The sequences -/ + +/-- The `N × N` truncation of the triangle A010766, `A(n,k) = ⌊n/k⌋`, indexed from `0`: entry +`(i, j)` is `⌊(i+1)/(j+1)⌋`, which is `0` above the diagonal (PARI: `matrix(N, N, r, c, r\c)`). -/ +def floorMat (N : ℕ) : Matrix (Fin N) (Fin N) ℤ := + Matrix.of fun i j => ((((i : ℕ) + 1) / ((j : ℕ) + 1) : ℕ) : ℤ) + +/-- A123706: the entry in row `n`, column `k` (`1 ≤ k ≤ n`) of the matrix inverse of the triangle +A010766, read off from the inverse of its `n × n` truncation; `0` outside `1 ≤ k ≤ n`. -/ +noncomputable def A123706 (n k : ℕ) : ℤ := + if h : 1 ≤ k ∧ k ≤ n then (floorMat n)⁻¹ ⟨n - 1, by omega⟩ ⟨k - 1, by omega⟩ else 0 + +/-- A123709: the number of nonzero entries in row `n` of A123706. -/ +noncomputable def A123709 (n : ℕ) : ℕ := #{k ∈ Icc 1 n | A123706 n k ≠ 0} + +/-- `n` is a term of A123710: row `n` of A123706 has exactly `4` nonzero entries. -/ +def IsTerm (n : ℕ) : Prop := A123709 n = 4 + +/-- A123710 (offset `1`): the `n`-th smallest index `k` such that row `k` of A123706 has exactly +`4` nonzero entries. -/ +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) + +/-- `m` is a term of A025475: `m = 1` or `m = p ^ k` with `p` prime and `k ≥ 2`. -/ +def IsA025475 (m : ℕ) : Prop := m = 1 ∨ ∃ p k : ℕ, p.Prime ∧ 2 ≤ k ∧ m = p ^ k + +/-- A025475 (offset `1`): `1` and the prime powers `p^m` with `m ≥ 2`, in increasing order. -/ +noncomputable def A025475 (n : ℕ) : ℕ := Nat.nth IsA025475 (n - 1) + +/-! ### Back substitution: the rows of the inverse -/ + +/-- `dot k j [x₀, x₁, …, x_{r-1}] = ∑_{i < r} xᵢ * ⌊(j + i) / k⌋`. -/ +def dot (k : ℕ) : ℕ → List ℤ → ℤ + | _, [] => 0 + | j, x :: xs => x * ((j / k : ℕ) : ℤ) + dot k (j + 1) xs + +/-- `tail n m = [T(n, n-m+1), …, T(n, n)]` (for `m ≤ n`): the last `m` entries of row `n` of the +inverse triangle, computed from right to left by `T(n,k) = [k = n] - ∑_{j=k+1}^{n} T(n,j) ⌊j/k⌋` +(row `n` of `T · A = I`, where `A(j,k) = ⌊j/k⌋` and `A(k,k) = 1`). -/ +def tail (n : ℕ) : ℕ → List ℤ + | 0 => [] + | m + 1 => ((if m = 0 then 1 else 0) - dot (n - m) (n - m + 1) (tail n m)) :: tail n m + +/-- Row `n` of the inverse, computed by back substitution: `[T(n,1), …, T(n,n)]`. -/ +def row (n : ℕ) : List ℤ := tail n n + +/-- The entry `T(n,k)` (`1 ≤ k ≤ n`) computed by back substitution; `0` outside `1 ≤ k ≤ n`. -/ +def T (n k : ℕ) : ℤ := if k = 0 then 0 else (row n).getD (k - 1) 0 + +theorem length_tail (n m : ℕ) : (tail n m).length = m := by + induction m with + | zero => rfl + | succ m ih => simp [tail, ih] + +theorem length_row (n : ℕ) : (row n).length = n := length_tail n n + +theorem drop_tail (n m d : ℕ) : (tail n (m + d)).drop d = tail n m := by + induction d with + | zero => rfl + | succ d ih => + show (tail n (m + d + 1)).drop (d + 1) = tail n m + simp only [tail, List.drop_succ_cons, ih] + +theorem getD_drop_zero (L : List ℤ) (d i : ℕ) : (L.drop d).getD i 0 = L.getD (d + i) 0 := by + rw [List.getD_eq_getElem?_getD, List.getD_eq_getElem?_getD, List.getElem?_drop] + +theorem getD_tail {n m : ℕ} (i : ℕ) (hm : m ≤ n) : + (tail n m).getD i 0 = T n (n - m + 1 + i) := by + have h : row n = tail n (m + (n - m)) := by rw [row, Nat.add_sub_cancel' hm] + rw [T, if_neg (by omega), show n - m + 1 + i - 1 = (n - m) + i by omega, h, + ← getD_drop_zero, drop_tail] + +theorem T_eq_head {n k : ℕ} (hk : 1 ≤ k) (hkn : k ≤ n) : + T n k = (if k = n then 1 else 0) - dot k (k + 1) (tail n (n - k)) := by + have h := getD_tail (n := n) (m := n - k + 1) 0 (by omega) + rw [show n - (n - k + 1) + 1 + 0 = k by omega] at h + rw [← h, tail, List.getD_cons_zero, show n - (n - k) = k by omega] + split_ifs <;> omega + +theorem dot_eq_sum (k j : ℕ) (L : List ℤ) : + dot k j L = ∑ i ∈ range L.length, L.getD i 0 * (((j + i) / k : ℕ) : ℤ) := by + induction L generalizing j with + | nil => simp [dot] + | cons x xs ih => + rw [dot, ih, List.length_cons, Finset.sum_range_succ', List.getD_cons_zero, add_zero, + add_comm] + congr 1 + refine Finset.sum_congr rfl fun i _ => ?_ + rw [List.getD_cons_succ, show j + 1 + i = j + (i + 1) by omega] + +theorem T_zero_right (n : ℕ) : T n 0 = 0 := by simp [T] + +theorem T_eq_zero_of_lt {n k : ℕ} (h : n < k) : T n k = 0 := by + rw [T, if_neg (by omega), List.getD_eq_default _ _ (by rw [length_row]; omega)] + +/-- Row `n` of `T · A = I`: `∑_{j=1}^{n} T(n,j) ⌊j/k⌋ = [k = n]` for every `k ≥ 1`. -/ +theorem sum_T_mul_floor {n k : ℕ} (hk : 1 ≤ k) : + ∑ l ∈ range n, T n (l + 1) * (((l + 1) / k : ℕ) : ℤ) = if k = n then 1 else 0 := by + rcases Nat.lt_or_ge n k with hnk | hkn + · rw [if_neg (by omega)] + refine Finset.sum_eq_zero fun l hl => ?_ + rw [Finset.mem_range] at hl + rw [Nat.div_eq_of_lt (by omega)] + simp + set f : ℕ → ℤ := fun l => T n (l + 1) * (((l + 1) / k : ℕ) : ℤ) with hf + have e1 : ∑ l ∈ range n, f l = + ∑ l ∈ range (k - 1), f l + ∑ x ∈ range (n - k + 1), f (k - 1 + x) := by + rw [← Finset.sum_range_add, show k - 1 + (n - k + 1) = n by omega] + have e2 : ∑ l ∈ range (k - 1), f l = 0 := by + refine Finset.sum_eq_zero fun l hl => ?_ + rw [Finset.mem_range] at hl + rw [hf] + simp only + rw [Nat.div_eq_of_lt (show l + 1 < k by omega), Nat.cast_zero, mul_zero] + have e3 : ∑ x ∈ range (n - k), f (k - 1 + (x + 1)) = dot k (k + 1) (tail n (n - k)) := by + rw [dot_eq_sum, length_tail] + refine Finset.sum_congr rfl fun i _ => ?_ + rw [getD_tail i (by omega), hf] + simp only + rw [show k - 1 + (i + 1) + 1 = k + 1 + i by omega, + show n - (n - k) + 1 + i = k + 1 + i by omega] + have e4 : f (k - 1 + 0) = T n k := by + rw [hf] + simp only + rw [show k - 1 + 0 + 1 = k by omega, Nat.div_self (by omega)] + simp + rw [e1, e2, Finset.sum_range_succ', e3, e4, T_eq_head hk hkn] + ring + +/-- The `N × N` truncation of `T` (indexed from `0`): entry `(i, j)` is `T (i+1) (j+1)`. -/ +def Tmat (N : ℕ) : Matrix (Fin N) (Fin N) ℤ := + Matrix.of fun i j => T ((i : ℕ) + 1) ((j : ℕ) + 1) + +theorem Tmat_mul_floorMat (N : ℕ) : Tmat N * floorMat N = 1 := by + ext i j + rw [Matrix.mul_apply, Matrix.one_apply] + simp only [Tmat, floorMat, Matrix.of_apply] + rw [Fin.sum_univ_eq_sum_range + (fun l => T ((i : ℕ) + 1) (l + 1) * (((l + 1) / ((j : ℕ) + 1) : ℕ) : ℤ)) N] + have hi := i.isLt + have hN : range N = range (((i : ℕ) + 1) + (N - ((i : ℕ) + 1))) := by congr 1; omega + rw [hN, Finset.sum_range_add, sum_T_mul_floor (by omega)] + rw [Finset.sum_eq_zero (s := range (N - ((i : ℕ) + 1))) fun x _ => by + rw [T_eq_zero_of_lt (by omega), zero_mul], add_zero] + by_cases e : i = j + · subst e; simp + · rw [if_neg e, if_neg] + intro e' + exact e (Fin.ext (by omega)) + +/-- The rows computed by back substitution form the matrix inverse of A010766: for every `N`, +the `N × N` truncation of `T` is the inverse of the `N × N` truncation of `⌊n/k⌋`. -/ +theorem Tmat_eq_inv (N : ℕ) : Tmat N = (floorMat N)⁻¹ := + (Matrix.inv_eq_left_inv (Tmat_mul_floorMat N)).symm + +theorem A123706_eq_T (n k : ℕ) : A123706 n k = T n k := by + rw [A123706] + split_ifs with h + · rw [← Tmat_eq_inv] + simp only [Tmat, Matrix.of_apply] + rw [Nat.sub_add_cancel (by omega), Nat.sub_add_cancel h.1] + · rcases Nat.eq_zero_or_pos k with hk | hk + · rw [hk, T_zero_right] + · rw [T_eq_zero_of_lt (by omega)] + +/-- Consistency: every truncation `N ≥ n` of A010766 gives the same entry `A123706 n k`. -/ +theorem A123706_eq_inv {n k N : ℕ} (hk : 1 ≤ k) (hkn : k ≤ n) (hn : n ≤ N) : + A123706 n k = (floorMat N)⁻¹ ⟨n - 1, by omega⟩ ⟨k - 1, by omega⟩ := by + rw [A123706_eq_T, ← Tmat_eq_inv] + simp only [Tmat, Matrix.of_apply] + rw [Nat.sub_add_cancel (by omega), Nat.sub_add_cancel hk] + +/-- `row n = [T n 1, …, T n n]`. -/ +theorem row_eq (n : ℕ) : row n = (List.range n).map (fun i => T n (i + 1)) := by + apply List.ext_getElem (by simp [length_row]) + intro i h1 h2 + rw [List.getElem_map, List.getElem_range, T, if_neg (by omega), Nat.add_sub_cancel, + List.getD_eq_getElem _ _ h1] + +theorem card_filter_Icc (q : ℕ → Prop) [DecidablePred q] (n : ℕ) : + #{k ∈ Icc 1 n | q k} = (List.range n).countP (fun i => q (i + 1)) := by + induction n with + | zero => simp + | succ n ih => + rw [← Finset.insert_Icc_right_eq_Icc_add_one (by omega), Finset.filter_insert, + List.range_succ, List.countP_append] + by_cases h : q (n + 1) + · rw [if_pos h, Finset.card_insert_of_notMem (by simp), ih] + simp [h] + · rw [if_neg h, ih] + simp [h] + +theorem A123709_eq_countP (n : ℕ) : A123709 n = (row n).countP (fun x => x ≠ 0) := by + rw [A123709, card_filter_Icc, row_eq, List.countP_map] + simp only [A123706_eq_T] + rfl + +/-! ### A fast sparse version of the back substitution, for the data checks -/ + +/-- `pdot k S`: for a list `S` of triples `(j, x⁺, x⁻)`, the pair +`(∑ x⁺ ⌊j/k⌋, ∑ x⁻ ⌊j/k⌋)`. -/ +noncomputable def pdot (k : ℕ) (S : List (ℕ × ℕ × ℕ)) : ℕ × ℕ := + List.rec (motive := fun _ => ℕ × ℕ) (0, 0) + (fun p _ r => let q := Nat.div p.1 k + (Nat.add r.1 (Nat.mul p.2.1 q), Nat.add r.2 (Nat.mul p.2.2 q))) S + +/-- The back substitution of `tail`, keeping only the nonzero entries `x` of `tail n m`, each as +a triple `(column, x⁺, x⁻)` with `x = x⁺ - x⁻`. -/ +noncomputable def ptail (n m : ℕ) : List (ℕ × ℕ × ℕ) := + Nat.rec (motive := fun _ => List (ℕ × ℕ × ℕ)) [] + (fun m S => + let r := pdot (Nat.sub n m) S + let a := Nat.add (cond (Nat.beq m 0) 1 0) r.2 + let b := r.1 + cond (Nat.beq a b) S ((Nat.sub n m, Nat.sub a b, Nat.sub b a) :: S)) m + +/-- A fast way to compute A123709 (see `A123709_eq_Rf`). -/ +noncomputable def Rf (n : ℕ) : ℕ := (ptail n n).length + +/-- The nonzero entries `(j, x⁺, x⁻)` of a list `[x₀, x₁, …]` whose entries sit in columns +`j, j+1, …`. -/ +def sp : ℕ → List ℤ → List (ℕ × ℕ × ℕ) + | _, [] => [] + | j, x :: xs => if x = 0 then sp (j + 1) xs else (j, x.toNat, (-x).toNat) :: sp (j + 1) xs + +theorem pdot_sp (k j : ℕ) (L : List ℤ) : + ((pdot k (sp j L)).1 : ℤ) - (pdot k (sp j L)).2 = dot k j L := by + induction L generalizing j with + | nil => simp [sp, pdot, dot] + | cons x xs ih => + by_cases hx : x = 0 + · simp only [sp, hx, if_true, dot, zero_mul, zero_add] + exact ih (j + 1) + · simp only [sp, hx, if_false, dot] + have h1 := ih (j + 1) + have h2 := Int.toNat_sub_toNat_neg x + change (((pdot k (sp (j + 1) xs)).1 + x.toNat * (j / k) : ℕ) : ℤ) - + (((pdot k (sp (j + 1) xs)).2 + (-x).toNat * (j / k) : ℕ) : ℤ) = _ + simp only [Nat.cast_add, Nat.cast_mul] + rw [← h1] + nth_rewrite 3 [← h2] + ring + +theorem length_sp (j : ℕ) (L : List ℤ) : (sp j L).length = L.countP (fun x => x ≠ 0) := by + induction L generalizing j with + | nil => rfl + | cons x xs ih => by_cases hx : x = 0 <;> simp [sp, hx, ih] + +theorem ptail_eq (n : ℕ) : ∀ m, m ≤ n → ptail n m = sp (n - m + 1) (tail n m) + | 0, _ => rfl + | m + 1, hm => by + have ih := ptail_eq n m (by omega) + change cond (Nat.beq (Nat.add (cond (Nat.beq m 0) 1 0) (pdot (Nat.sub n m) (ptail n m)).2) + (pdot (Nat.sub n m) (ptail n m)).1) (ptail n m) + ((Nat.sub n m, Nat.sub (Nat.add (cond (Nat.beq m 0) 1 0) (pdot (Nat.sub n m) (ptail n m)).2) + (pdot (Nat.sub n m) (ptail n m)).1, + Nat.sub (pdot (Nat.sub n m) (ptail n m)).1 + (Nat.add (cond (Nat.beq m 0) 1 0) (pdot (Nat.sub n m) (ptail n m)).2)) :: ptail n m) = _ + rw [ih, show n - (m + 1) + 1 = n - m by omega] + have hd := pdot_sp (n - m) (n - m + 1) (tail n m) + simp only [Nat.sub_eq, Nat.add_eq] at hd ⊢ + set r := pdot (n - m) (sp (n - m + 1) (tail n m)) with hr + set c : ℕ := cond (Nat.beq m 0) 1 0 with hc + have hc' : (c : ℤ) = if m = 0 then 1 else 0 := by + rw [hc]; cases m <;> rfl + set v : ℤ := (if m = 0 then 1 else 0) - dot (n - m) (n - m + 1) (tail n m) with hv + have hv' : v = ((c + r.2 : ℕ) : ℤ) - (r.1 : ℤ) := by + rw [hv, ← hd, ← hc']; push_cast; ring + rw [tail, sp, ← hv] + by_cases h : c + r.2 = r.1 + · have h0 : v = 0 := by rw [hv', h]; ring + rw [h, Nat.beq_refl, if_pos h0] + rfl + · have h0 : v ≠ 0 := by + rw [hv']; intro e; apply h; omega + have hb : Nat.beq (c + r.2) r.1 = false := by + cases hb : Nat.beq (c + r.2) r.1 + · rfl + · exact absurd (Nat.eq_of_beq_eq_true hb) h + rw [hb, if_neg h0, hv', Int.toNat_sub, neg_sub, Int.toNat_sub] + rfl + +theorem A123709_eq_Rf (n : ℕ) : A123709 n = Rf n := by + rw [A123709_eq_countP, Rf, ptail_eq n n le_rfl, length_sp, row] + +/-! ### Data checks -/ + +/-- The definition reproduces all 113 terms of A123706 listed in OEIS (rows `1, …, 14` and the +start of row `15`; kernel-checked). -/ +theorem A123706_data : + ((List.range 15).map fun i => + (List.range (i + 1)).map fun j => A123706 (i + 1) (j + 1)).flatten.take 113 = + [1, -2, 1, -1, -1, 1, 1, -1, -1, 1, -1, 0, 0, -1, 1, 2, 0, -1, 0, -1, 1, -1, 0, 0, 0, 0, -1, 1, + 0, 0, 1, -1, 0, 0, -1, 1, 0, 1, -1, 0, 0, 0, 0, -1, 1, 2, -1, 0, 1, -1, 0, 0, 0, -1, 1, -1, 0, + 0, 0, 0, 0, 0, 0, 0, -1, 1, -1, 1, 1, -1, 1, -1, 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, -1, 1, 2, -1, 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, -1, 1, 1, 1, -1, 1, -1, 0, 0, 0] := by + simp only [A123706_eq_T] + decide +kernel + +/-- The definition reproduces all 76 terms of A123709 listed in OEIS (kernel-checked). -/ +theorem A123709_data : (List.range 76).map (fun i => A123709 (i + 1)) = + [1, 2, 3, 4, 3, 4, 3, 4, 4, 6, 3, 8, 3, 6, 7, 4, 3, 8, 3, 8, 7, 6, 3, 8, 4, 6, 4, 8, 3, 11, 3, + 4, 7, 6, 7, 8, 3, 6, 7, 8, 3, 11, 3, 8, 8, 6, 3, 8, 4, 8, 7, 8, 3, 8, 7, 8, 7, 6, 3, 16, 3, + 6, 8, 4, 7, 12, 3, 8, 7, 14, 3, 8, 3, 6, 8, 8] := by + simp only [A123709_eq_Rf] + decide +kernel + +noncomputable instance : DecidablePred IsTerm := fun n => + decidable_of_iff (Rf n = 4) (by rw [IsTerm, A123709_eq_Rf]) + +/-- `firstDiv m f d`: the first `e ∈ [d, d + f)` with `e ∣ m`, or `d + f` if there is none. -/ +def firstDiv (m : ℕ) : ℕ → ℕ → ℕ + | 0, d => d + | f + 1, d => if m % d = 0 then d else firstDiv m f (d + 1) + +theorem firstDiv_eq_minFac {m : ℕ} (hm : 2 ≤ m) : firstDiv m m 2 = m.minFac := by + have key : ∀ f d, 2 ≤ d → d ≤ m.minFac → m.minFac < d + f → firstDiv m f d = m.minFac := by + intro f + induction f with + | zero => intro d _ h1 h2; omega + | succ f ih => + intro d hd h1 h2 + rw [firstDiv] + split_ifs with h + · exact le_antisymm h1 (Nat.minFac_le_of_dvd hd (Nat.dvd_of_mod_eq_zero h)) + · refine ih (d + 1) (by omega) ?_ (by omega) + rcases Nat.lt_or_ge d m.minFac with h' | h' + · omega + · exfalso + apply h + rw [le_antisymm h1 h'] + exact Nat.mod_eq_zero_of_dvd (Nat.minFac_dvd m) + refine key m 2 le_rfl (Nat.minFac_prime (by omega)).two_le ?_ + have := Nat.minFac_le (by omega : 0 < m) + omega + +theorem isA025475_iff (m : ℕ) : + IsA025475 m ↔ m = 1 ∨ (2 ≤ m ∧ firstDiv m m 2 ^ 2 ∣ m ∧ m ∣ firstDiv m m 2 ^ m) := by + constructor + · rintro (h | ⟨p, k, hp, hk, rfl⟩) + · exact Or.inl h + · right + have h2 : 2 ≤ p ^ k := le_trans hp.two_le (Nat.le_self_pow (by omega) p) + rw [firstDiv_eq_minFac h2] + have hmin : (p ^ k).minFac = p := by + have hpr : (p ^ k).minFac.Prime := Nat.minFac_prime (by omega) + exact (Nat.prime_dvd_prime_iff_eq hpr hp).1 (hpr.dvd_of_dvd_pow (Nat.minFac_dvd _)) + rw [hmin] + exact ⟨h2, pow_dvd_pow p hk, pow_dvd_pow p (Nat.lt_pow_self hp.one_lt).le⟩ + · rintro (h | ⟨h2, h3, h4⟩) + · exact Or.inl h + · right + rw [firstDiv_eq_minFac h2] at h3 h4 + have hp : m.minFac.Prime := Nat.minFac_prime (by omega) + obtain ⟨i, -, hi⟩ := (Nat.dvd_prime_pow hp).1 h4 + refine ⟨m.minFac, i, hp, ?_, hi⟩ + have h3' : m.minFac ^ 2 ∣ m.minFac ^ i := by rw [← hi]; exact h3 + exact (Nat.pow_dvd_pow_iff_le_right hp.one_lt).1 h3' + +instance : DecidablePred IsA025475 := fun m => + decidable_of_iff _ (isA025475_iff m).symm + +/-- The elements `< N` satisfying `p`, in increasing order, are `nth p 0, nth p 1, …`. -/ +theorem filter_range_eq (p : ℕ → Prop) [DecidablePred p] (N : ℕ) : + (List.range N).filter (fun k => decide (p k)) = + (List.range (Nat.count p N)).map (Nat.nth p) := by + induction N with + | zero => simp + | succ N ih => + rw [List.range_succ, List.filter_append, ih, Nat.count_succ] + by_cases h : p N + · simp [h, List.range_succ, Nat.nth_count h] + · simp [h] + +theorem map_nth_eq_of_filter {p : ℕ → Prop} [DecidablePred p] {N K : ℕ} {L : List ℕ} + (h : (List.range N).filter (fun k => decide (p k)) = L) (hK : L.length = K) : + (List.range K).map (Nat.nth p) = L := by + rw [filter_range_eq] at h + subst h hK + simp only [List.length_map, List.length_range] + +/-- The `n ≤ 512` with `IsTerm n` (kernel-checked; this runs the back substitution for every +`n ≤ 512`). -/ +theorem filter_isTerm : (List.range 513).filter (fun k => decide (IsTerm k)) = + [4, 6, 8, 9, 16, 25, 27, 32, 49, 64, 81, 121, 125, 128, 169, 243, 256, 289, 343, 361, 512] := by + decide +kernel + +/-- The definition reproduces the first 21 terms of A123710 listed in OEIS, `a 1, …, a 21` +(all terms `≤ 512`; kernel-checked in `filter_isTerm`). -/ +theorem a_data : (List.range 21).map (fun i => a (i + 1)) = + [4, 6, 8, 9, 16, 25, 27, 32, 49, 64, 81, 121, 125, 128, 169, 243, 256, 289, 343, 361, 512] := by + have e : (fun i => a (i + 1)) = Nat.nth IsTerm := funext fun i => by rw [a, Nat.add_sub_cancel] + rw [e] + exact map_nth_eq_of_filter filter_isTerm rfl + +/-- The `m ≤ 512` with `IsA025475 m` (kernel-checked). -/ +theorem filter_isA025475 : (List.range 513).filter (fun k => decide (IsA025475 k)) = + [1, 4, 8, 9, 16, 25, 27, 32, 49, 64, 81, 121, 125, 128, 169, 243, 256, 289, 343, 361, 512] := by + decide +kernel + +/-- `A025475` reproduces the first 21 terms listed in OEIS, `A025475 1, …, A025475 21` +(all terms `≤ 512`; kernel-checked in `filter_isA025475`). From index `3` on they agree with +`a_data`. -/ +theorem A025475_data : (List.range 21).map (fun i => A025475 (i + 1)) = + [1, 4, 8, 9, 16, 25, 27, 32, 49, 64, 81, 121, 125, 128, 169, 243, 256, 289, 343, 361, 512] := by + have e : (fun i => A025475 (i + 1)) = Nat.nth IsA025475 := + funext fun i => by rw [A025475, Nat.add_sub_cancel] + rw [e] + exact map_nth_eq_of_filter filter_isA025475 rfl + +/-! ### The conjecture -/ + +/-- Conjecture (M. F. Hasler, 2012): `a(n) = A025475(n)` for `n > 2`, i.e. from the third term +on, the indices of the rows of A123706 with exactly four nonzero entries are the proper prime +powers `p^m` (`m ≥ 2`) in increasing order. -/ +def statement : Prop := + ∀ n : ℕ, 2 < n → a n = A025475 n + +end Math0.Statements.A123710 diff --git a/lean/Math0/Statements/OEIS/A124526.lean b/lean/Math0/Statements/OEIS/A124526.lean new file mode 100644 index 0000000..c1a56be --- /dev/null +++ b/lean/Math0/Statements/OEIS/A124526.lean @@ -0,0 +1,140 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A124526: Hanna's product formula for partitions with `k` mixed-parity blocks + +Source: https://oeis.org/A124526, Paul D. Hanna, Nov 08 2006 (COMMENTS section). Verbatim: +> A124418(n,k) = k!*T(n,k) (conjecture). + +The same conjecture is recorded in the FORMULA section of https://oeis.org/A124418, also by +Paul D. Hanna, Nov 08 2006: +> Conjecture: T(n,k) = k!*A049020([n/2],k)*A049020([(n+1)/2],k) where +> A049020(n,k)=Sum_{i=0..n} S2(n,i)*C(i,k) and S2(n,k)=(1/k!)*Sum_{j=0..k} (-1)^(k-j)*C(k,j)*j^n +> (the Stirling numbers of 2nd kind). + +## Encoding + +* *A124526* (offset `0`, keyword `tabf`) is the triangle "read by rows, where + `T(n,k) = A049020([n/2],k)*A049020([(n+1)/2],k)`"; "Row n has 1+floor(n/2) terms", i.e. + `0 ≤ k ≤ ⌊n/2⌋`. Here `[x]` is the floor, so `[n/2] = n / 2` and `[(n+1)/2] = (n + 1) / 2` + (natural-number division). +* *A049020* is encoded by the formula given in A124526 (and A049020): + `A049020(m,k) = ∑_{i=0}^{m} S2(m,i) · C(i,k)`, where `S2` is Mathlib's `Nat.stirlingSecond` + (the Stirling numbers of the second kind; the explicit alternating sum quoted in the entry is a + standard closed form of the same numbers). +* `T n k` is A124526's `T(n,k)`; `a` is the triangle read by rows (the OEIS sequence itself, + offset `0`). `T_data` checks all 16 listed rows `n = 0, …, 15` and `a_data` checks all 72 listed + terms `a 0, …, a 71` (both kernel-checked). +* *A124418* (Emeric Deutsch, offset `0`): "Triangle read by rows: T(n,k) is the number of + partitions of the set {1,2,...,n} having exactly k blocks that contain both odd and even + entries (0<=k<=floor(n/2))." A partition of `{1, …, n}` is a Mathlib + `Finpartition (Finset.Icc 1 n)` (a finite set of nonempty, pairwise disjoint blocks whose union is + `{1, …, n}`; two partitions are equal iff they have the same blocks). A block `b` is *mixed* + (`IsMixed b`) if it contains an odd entry and an even entry. `A124418 n k` counts the partitions + of `{1, …, n}` with exactly `k` mixed blocks (`A124418_eq_card` restates it as the cardinality of + a subtype). For `n = 0` the unique (empty) partition of `∅` has no mixed block. + The definition is decidable, but Mathlib's enumeration of `Finpartition`s is doubly + exponential (it filters the powerset of the powerset), so the kernel can only evaluate it for + `n ≤ 3`: `A124418_data` checks the listed rows `n = 0, 1, 2, 3` of A124418 + (`1; 1; 1, 1; 2, 3`). Separately, `rhs_data` checks that `k! · T(n,k)` reproduces all 49 listed + terms of A124418 (rows `0, …, 12`); this only sanity-checks the transcription of the right-hand + side and proves nothing about the conjecture. +* *The conjecture.* `statement`: for all `n ≥ 0` and all `k` with `0 ≤ k ≤ ⌊n/2⌋` (the index range + of both triangles), `A124418(n,k) = k! · T(n,k)`. +-/ + +namespace Math0.Statements.A124526 + +open Finset + +/-- A049020: `A049020(m,k) = ∑_{i=0}^{m} S2(m,i) · C(i,k)`, the number of set partitions of an +`m`-set in which exactly `k` of the blocks have been distinguished (`S2` = Stirling numbers of the +second kind, `Nat.stirlingSecond`). -/ +def A049020 (m k : ℕ) : ℕ := + ∑ i ∈ range (m + 1), Nat.stirlingSecond m i * Nat.choose i k + +/-- A124526 as a triangle: `T(n,k) = A049020([n/2],k) * A049020([(n+1)/2],k)` +(`0 ≤ k ≤ ⌊n/2⌋`). -/ +def T (n k : ℕ) : ℕ := A049020 (n / 2) k * A049020 ((n + 1) / 2) k + +/-- A124526 as a sequence (offset `0`): the triangle `T` read by rows, row `n` being +`T(n,0), …, T(n,⌊n/2⌋)`. (Rows `0, …, i` contain at least `i + 1` entries, so the `i`-th entry of +the concatenation lies among them.) -/ +def a (i : ℕ) : ℕ := + ((List.range (i + 1)).flatMap fun n => (List.range (n / 2 + 1)).map (T n)).getD i 0 + +/-- The definition reproduces the 16 rows `n = 0, …, 15` listed in OEIS (kernel-checked). -/ +theorem T_data : (List.range 16).map (fun n => (List.range (n / 2 + 1)).map (T n)) = + [[1], + [1], + [1, 1], + [2, 3], + [4, 9, 1], + [10, 30, 6], + [25, 100, 36, 1], + [75, 370, 186, 10], + [225, 1369, 961, 100, 1], + [780, 5587, 4960, 750, 15], + [2704, 22801, 25600, 5625, 225, 1], + [10556, 101774, 136960, 39000, 2325, 21], + [41209, 454276, 732736, 270400, 24025, 441, 1], + [178031, 2199262, 4110512, 1849120, 217000, 6027, 28], + [769129, 10647169, 23059204, 12645136, 1960000, 82369, 784, 1], + [3630780, 55493841, 136074274, 87570056, 16787400, 944230, 13720, 36]] := by + decide +kernel + +/-- The definition reproduces all 72 terms listed in OEIS, `a 0, …, a 71` (kernel-checked). -/ +theorem a_data : (List.range 72).map (fun i => a (i + 0)) = + [1, 1, 1, 1, 2, 3, 4, 9, 1, 10, 30, 6, 25, 100, 36, 1, 75, 370, 186, 10, 225, 1369, 961, 100, + 1, 780, 5587, 4960, 750, 15, 2704, 22801, 25600, 5625, 225, 1, 10556, 101774, 136960, 39000, + 2325, 21, 41209, 454276, 732736, 270400, 24025, 441, 1, 178031, 2199262, 4110512, 1849120, + 217000, 6027, 28, 769129, 10647169, 23059204, 12645136, 1960000, 82369, 784, 1, 3630780, + 55493841, 136074274, 87570056, 16787400, 944230, 13720, 36] := by + decide +kernel + +/-! ### A124418: partitions of `{1, …, n}` by the number of mixed-parity blocks -/ + +/-- A block is *mixed* if it contains both an odd and an even entry. -/ +def IsMixed (b : Finset ℕ) : Prop := (∃ x ∈ b, Odd x) ∧ (∃ x ∈ b, Even x) + +instance : DecidablePred IsMixed := fun b => by unfold IsMixed; infer_instance + +/-- A124418: `T(n,k)` is the number of partitions of the set `{1, 2, …, n}` having exactly `k` +blocks that contain both odd and even entries. -/ +def A124418 (n k : ℕ) : ℕ := + (univ.filter fun P : Finpartition (Icc 1 n) => (P.parts.filter IsMixed).card = k).card + +/-- `A124418 n k` is the number of partitions of `{1, …, n}` with exactly `k` mixed blocks. -/ +theorem A124418_eq_card (n k : ℕ) : + A124418 n k = + Fintype.card {P : Finpartition (Icc 1 n) // (P.parts.filter IsMixed).card = k} := by + rw [A124418, Fintype.card_subtype] + +/-- The definition of A124418 reproduces its listed rows `n = 0, 1, 2, 3` (kernel-checked; the +enumeration of partitions is doubly exponential, so larger rows are out of reach). -/ +theorem A124418_data : (List.range 4).map (fun n => (List.range (n / 2 + 1)).map (A124418 n)) = + [[1], [1], [1, 1], [2, 3]] := by + decide +kernel + +/-- Sanity check of the transcription of the right-hand side (not a proof of the conjecture): +`k! · T(n,k)` reproduces all 49 listed terms of A124418 (rows `n = 0, …, 12`). -/ +theorem rhs_data : (List.range 13).flatMap + (fun n => (List.range (n / 2 + 1)).map (fun k => k.factorial * T n k)) = + [1, 1, 1, 1, 2, 3, 4, 9, 2, 10, 30, 12, 25, 100, 72, 6, 75, 370, 372, 60, 225, 1369, 1922, + 600, 24, 780, 5587, 9920, 4500, 360, 2704, 22801, 51200, 33750, 5400, 120, 10556, 101774, + 273920, 234000, 55800, 2520, 41209, 454276, 1465472, 1622400, 576600, 52920, 720] := by + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjecture (Paul D. Hanna, 2006): for all `n ≥ 0` and `0 ≤ k ≤ ⌊n/2⌋`, the number +A124418(n,k) of partitions of `{1, …, n}` with exactly `k` blocks containing both odd and even +entries equals `k! · T(n,k)`, where `T(n,k) = A049020([n/2],k) · A049020([(n+1)/2],k)` is +A124526. -/ +def statement : Prop := + ∀ n k : ℕ, k ≤ n / 2 → A124418 n k = k.factorial * T n k + +end Math0.Statements.A124526 diff --git a/lean/Math0/Statements/OEIS/A126127.lean b/lean/Math0/Statements/OEIS/A126127.lean new file mode 100644 index 0000000..a8b1f8b --- /dev/null +++ b/lean/Math0/Statements/OEIS/A126127.lean @@ -0,0 +1,276 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A126127: bivariate generating function of the inverse square of A061554 + +Source: https://oeis.org/A126127, Robert Israel, Jul 07 2019 (FORMULA section). Verbatim: +> G.f. as triangle (conjectured): (1-x)*(1-x+x^2)/(1-x*y+3*x^2-x^3*y+x^4). - _Robert Israel_, Jul 07 2019 + +The entry (Gary W. Adamson, Dec 17 2006; keywords `tabl,sign`, offset `0`) is named "Inverse +square of A061554." Its formula section says: "Given M = Pascal's triangle with descending row +terms, (A061554); A126127 = M^(-2)." + +## Encoding + +* *The triangle M.* A061554 read as a triangle is `M(n,k) = binomial(n, floor((n-k)/2))` for + `0 ≤ k ≤ n` (Barry's and Bala's formula in A061554, equivalent to the formula + `binomial(n, floor((n+1)/2 - (-1)^(n-k)*(k+1)/2))` there and to the Maple program of + A126127). `M n k : ℤ` is this for `k ≤ n` and `0` above the diagonal, so `M` is an infinite + lower-triangular matrix with `M(n,n) = 1`. +* *The inverse.* An infinite lower unitriangular matrix has a unique lower-triangular inverse, + and its leading `L × L` block is the inverse of the leading `L × L` block of `M` (this is also + how the Maple program of the entry computes it, with a `20 × 20` truncation). `Minv n k` is + computed by forward substitution for `M · N = 1`, i.e. + `N(n,k) = [k = n] - ∑_{j n` + (`Minv_rec`, `Minv_eq_zero`); the rows are built as lists (`invRows`) so that the kernel + evaluates each entry once. +* *The triangle T = M^(-2).* `T n k = ∑_{j ≤ n} N(n,j) N(j,k)`, the `(n,k)` entry of `N · N`. + That this really is `M^(-2)` is proved, not assumed: `T_spec` shows that for every `L` the + `L × L` matrix `(T i j)_{i,j + (if k = rows.length then 1 else 0) - + ∑ j ∈ range rows.length, M rows.length j * (rows.getD j []).getD k 0 + +/-- `invRows n = [row 0 of N, …, row (n-1) of N]`. -/ +def invRows : ℕ → List (List ℤ) + | 0 => [] + | n + 1 => invRows n ++ [nextRow (invRows n)] + +/-- The inverse `N = M⁻¹` of the triangle A061554 (see `Nmat_eq_inv`). -/ +def Minv (n k : ℕ) : ℤ := ((invRows (n + 1)).getD n []).getD k 0 + +/-- A126127 as a triangle: `T = M^(-2) = N · N`, `T(n,k) = ∑_{j ≤ n} N(n,j) N(j,k)` +(see `T_spec`). -/ +def T (n k : ℕ) : ℤ := ∑ j ∈ range (n + 1), Minv n j * Minv j k + +/-- The position `(n,k)` (row `n`, column `k ≤ n`) of the `i`-th term of a triangle read by +rows: `(0,0), (1,0), (1,1), (2,0), (2,1), (2,2), …` (see `pos_spec`). -/ +def pos : ℕ → ℕ × ℕ + | 0 => (0, 0) + | i + 1 => + match pos i with + | (n, k) => if k < n then (n, k + 1) else (n + 1, 0) + +/-- A126127: the triangle `T = M^(-2)` read by rows (offset `0`). -/ +def a (i : ℕ) : ℤ := T (pos i).1 (pos i).2 + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all 66 listed +terms `a(0), …, a(65)`, i.e. rows `0` to `10` of the triangle. -/ +theorem a_data : (List.range 66).map (fun i => a (i + 0)) = + [1, -2, 1, -1, -2, 1, 5, -3, -2, 1, 2, 9, -5, -2, 1, -13, 9, 13, -7, -2, 1, -5, -33, 20, 17, + -9, -2, 1, 34, -27, -61, 35, 21, -11, -2, 1, 13, 111, -73, -97, 54, 25, -13, -2, 1, -89, + 80, 248, -151, -141, 77, 29, -15, -2, 1, -34, -355, 252, 461, -269, -193, 104, 33, -17, -2, + 1] := by + decide +kernel + +/-! ### The enumeration of the triangle -/ + +theorem pos_succ (i : ℕ) : pos (i + 1) = + if (pos i).2 < (pos i).1 then ((pos i).1, (pos i).2 + 1) else ((pos i).1 + 1, 0) := by + rw [pos] + +/-- Term number `n(n+1)/2 + k` of the triangle read by rows is in row `n`, column `k`. -/ +theorem pos_spec (n k : ℕ) (hk : k ≤ n) : pos (n * (n + 1) / 2 + k) = (n, k) := by + induction n generalizing k with + | zero => + obtain rfl : k = 0 := by omega + rfl + | succ m ih => + induction k with + | zero => + have h2 : (m + 1) * (m + 1 + 1) / 2 = m * (m + 1) / 2 + m + 1 := by + have : (m + 1) * (m + 1 + 1) = m * (m + 1) + 2 * (m + 1) := by ring + rw [this, Nat.add_mul_div_left _ _ (by norm_num)] + ring + rw [h2, Nat.add_zero, pos_succ, ih m le_rfl] + simp + | succ k ihk => + rw [← Nat.add_assoc, pos_succ, ihk (by omega)] + simp only + rw [if_pos (by omega)] + +/-! ### `Minv` is the inverse of `M` -/ + +theorem invRows_length (n : ℕ) : (invRows n).length = n := by + induction n with + | zero => rfl + | succ n ih => simp [invRows, ih] + +theorem invRows_getD (n j : ℕ) : + (invRows n).getD j [] = if j < n then nextRow (invRows j) else [] := by + induction n with + | zero => simp [invRows] + | succ n ih => + rw [invRows] + rcases lt_trichotomy j n with h | h | h + · rw [List.getD_append _ _ _ _ (by rw [invRows_length]; exact h), ih, if_pos h, + if_pos (by omega)] + · subst h + rw [List.getD_append_right _ _ _ _ (by rw [invRows_length]), invRows_length, + Nat.sub_self, if_pos (by omega)] + rfl + · rw [List.getD_append_right _ _ _ _ (by rw [invRows_length]; omega), invRows_length, + if_neg (by omega)] + obtain ⟨d, hd⟩ : ∃ d, j - n = d + 1 := ⟨j - n - 1, by omega⟩ + rw [hd] + rfl + +theorem Minv_eq (n k : ℕ) : Minv n k = (nextRow (invRows n)).getD k 0 := by + rw [Minv, invRows_getD, if_pos (Nat.lt_succ_self n)] + +/-- `N` is lower triangular. -/ +theorem Minv_eq_zero (n k : ℕ) (h : n < k) : Minv n k = 0 := by + rw [Minv_eq] + exact List.getD_eq_default _ _ (by simp [nextRow, invRows_length]; omega) + +/-- Forward substitution: `N(n,k) = [k = n] - ∑_{j (if k = n then (1 : ℤ) else 0) - s) + (Finset.sum_congr rfl fun j hj => ?_) + rw [invRows_getD, if_pos (Finset.mem_range.mp hj), ← Minv_eq] + +theorem M_diag (n : ℕ) : M n n = 1 := by simp [M] + +theorem M_eq_zero (n j : ℕ) (h : n < j) : M n j = 0 := by + rw [M, if_neg (by omega)] + +/-- Row `n` of `M · N` is row `n` of the identity, as a finite sum over any range `L > n`. -/ +theorem sum_M_mul_Minv (L n k : ℕ) (hn : n < L) : + ∑ j ∈ range L, M n j * Minv j k = if n = k then 1 else 0 := by + obtain ⟨m, rfl⟩ : ∃ m, L = n + 1 + m := ⟨L - (n + 1), by omega⟩ + rw [Finset.sum_range_add, Finset.sum_eq_zero (s := range m) + (fun x _ => by rw [M_eq_zero _ _ (by omega), zero_mul]), add_zero, Finset.sum_range_succ, + M_diag, one_mul] + by_cases hk : k ≤ n + · rw [Minv_rec n k hk] + by_cases h : k = n + · rw [if_pos h, if_pos h.symm]; ring + · rw [if_neg h, if_neg (Ne.symm h)]; ring + · rw [Minv_eq_zero _ _ (by omega), if_neg (by omega), + Finset.sum_eq_zero (fun j hj => by + rw [Minv_eq_zero _ _ (by have := Finset.mem_range.mp hj; omega), mul_zero])] + ring + +/-! ### `T` is `M^(-2)` -/ + +/-- The `L × L` truncation of the triangle `M` (A061554). -/ +def Mmat (L : ℕ) : Matrix (Fin L) (Fin L) ℚ := Matrix.of fun i j => (M i j : ℚ) + +/-- The `L × L` truncation of `N = Minv`. -/ +def Nmat (L : ℕ) : Matrix (Fin L) (Fin L) ℚ := Matrix.of fun i j => (Minv i j : ℚ) + +/-- The `L × L` truncation of the triangle `T`. -/ +def Tmat (L : ℕ) : Matrix (Fin L) (Fin L) ℚ := Matrix.of fun i j => (T i j : ℚ) + +theorem Mmat_mul_Nmat (L : ℕ) : Mmat L * Nmat L = 1 := by + ext i k + simp only [Matrix.mul_apply, Mmat, Nmat, Matrix.of_apply, Matrix.one_apply] + rw [Fin.sum_univ_eq_sum_range (fun x => (M i x : ℚ) * (Minv x k : ℚ)) L] + have h := congrArg (fun z : ℤ => (z : ℚ)) (sum_M_mul_Minv L i k i.isLt) + simp only [Int.cast_sum, Int.cast_mul] at h + rw [h] + by_cases hik : i = k + · rw [if_pos hik, if_pos (congrArg Fin.val hik)]; rfl + · rw [if_neg hik, if_neg (fun h' => hik (Fin.ext h'))]; rfl + +/-- `Minv` is the inverse of `M`: for every `L`, the `L × L` truncation of `Minv` is the +(Mathlib) inverse of the `L × L` truncation of `M`. -/ +theorem Nmat_eq_inv (L : ℕ) : Nmat L = (Mmat L)⁻¹ := + (Matrix.inv_eq_right_inv (Mmat_mul_Nmat L)).symm + +/-- `T` is lower triangular. -/ +theorem T_eq_zero (n k : ℕ) (h : n < k) : T n k = 0 := + Finset.sum_eq_zero fun j hj => by + rw [Minv_eq_zero j k (by have := Finset.mem_range.mp hj; omega), mul_zero] + +/-- Row `n` of `N · N` is row `n` of `T`, as a finite sum over any range `L > n`. -/ +theorem sum_Minv_mul_Minv (L n k : ℕ) (hn : n < L) : + ∑ j ∈ range L, Minv n j * Minv j k = T n k := by + obtain ⟨m, rfl⟩ : ∃ m, L = n + 1 + m := ⟨L - (n + 1), by omega⟩ + rw [Finset.sum_range_add, Finset.sum_eq_zero (s := range m) + (fun x _ => by rw [Minv_eq_zero n _ (by omega), zero_mul]), add_zero, T] + +theorem Tmat_eq (L : ℕ) : Tmat L = Nmat L * Nmat L := by + ext i k + simp only [Matrix.mul_apply, Tmat, Nmat, Matrix.of_apply] + rw [Fin.sum_univ_eq_sum_range (fun x => (Minv i x : ℚ) * (Minv x k : ℚ)) L, + ← sum_Minv_mul_Minv L i k i.isLt] + push_cast + rfl + +/-- `T = M^(-2)`: for every `L`, the `L × L` truncation of `T` is the `-2`-nd power (in +Mathlib's sense) of the `L × L` truncation of `M`. -/ +theorem T_spec (L : ℕ) : Tmat L = Mmat L ^ (-2 : ℤ) := by + rw [Tmat_eq, Nmat_eq_inv, ← sq, Matrix.inv_pow', ← Matrix.zpow_neg_natCast] + rfl + +/-! ### The conjecture -/ + +open MvPowerSeries + +/-- The bivariate generating function of the triangle, +`∑_{n ≥ 0} ∑_{k=0}^{n} T(n,k) x^n y^k` with `x = X 0` and `y = X 1`: the coefficient of +`x^n y^k` is `T(n,k)` if `k ≤ n` and `0` otherwise. -/ +noncomputable def gf : MvPowerSeries (Fin 2) ℚ := + fun m => if m 1 ≤ m 0 then (T (m 0) (m 1) : ℚ) else 0 + +/-- The coefficient of `x^n y^k` in `gf` is `T(n,k)` for `k ≤ n` (and `0` for `k > n`). -/ +theorem coeff_gf (n k : ℕ) : + coeff (Finsupp.single 0 n + Finsupp.single 1 k) gf = if k ≤ n then (T n k : ℚ) else 0 := by + show (if _ then _ else _) = _ + simp + +/-- The conjectured g.f. of A126127 as a triangle: +`∑_{n,k} T(n,k) x^n y^k = (1-x)(1-x+x^2)/(1-xy+3x^2-x^3y+x^4)`, as an identity of formal power +series in `x = X 0` and `y = X 1` over `ℚ`. -/ +def statement : Prop := + gf = (1 - X 0) * (1 - X 0 + X 0 ^ 2) * + (1 - X 0 * X 1 + 3 * X 0 ^ 2 - X 0 ^ 3 * X 1 + X 0 ^ 4 : MvPowerSeries (Fin 2) ℚ)⁻¹ + +/-- The denominator `1 - xy + 3x^2 - x^3y + x^4`. -/ +noncomputable def den : MvPowerSeries (Fin 2) ℚ := + 1 - X 0 * X 1 + 3 * X 0 ^ 2 - X 0 ^ 3 * X 1 + X 0 ^ 4 + +theorem constantCoeff_den : constantCoeff den = 1 := by + simp [den] + +/-- The conjecture with the denominator cleared. -/ +theorem statement_iff : statement ↔ gf * den = (1 - X 0) * (1 - X 0 + X 0 ^ 2) := + MvPowerSeries.eq_mul_inv_iff_mul_eq (by simp) + +end Math0.Statements.A126127 diff --git a/lean/Math0/Statements/OEIS/A127752.lean b/lean/Math0/Statements/OEIS/A127752.lean new file mode 100644 index 0000000..7f04ff2 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A127752.lean @@ -0,0 +1,234 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A127752: row sums of the inverse of the `1/(3n+1)` band triangle, mod 2 + +Source: https://oeis.org/A127752, Paul Barry, Jan 28 2007. Verbatim: +> a(n) mod 2 is first Feigenbaum symbolic sequence A035263 (conjecture). + +followed in the entry by: "The conjecture is true at least up to 2048 first terms. (But please +note the different indexing, here 0-based.) - Antti Karttunen, Sep 29 2018". + +The entry (offset `0`, keyword `nonn`) is named "Row sums of inverse of number triangle +`A(n,k) = 1/(3n+1)` if `k <= n <= 2k`, 0 otherwise." + +## Encoding + +* *The triangle.* `A n k : ℚ` is `1/(3n+1)` if `k ≤ n ∧ n ≤ 2k` and `0` otherwise, exactly as in + the name. It is an infinite lower-triangular matrix with nonzero diagonal `A(n,n) = 1/(3n+1)`, + so it has a unique lower-triangular inverse, whose leading `N × N` block is the inverse of the + leading `N × N` block `Amat N` of `A` (this is also how the OEIS programs compute it, with a + fixed `128 × 128` truncation). +* *The sequence.* The vector of row sums `s = A⁻¹ 𝟙` is the unique solution of `A s = 𝟙`; forward + substitution gives `s(n) = (3n+1) (1 - ∑_{j 11, 1 -> 10`" (offset + `1`). `word k` is the `k`-th iterate of the morphism `sigma` applied to the word `1`; it has + length `2^k` (`word_length`) and is a prefix of `word (k+1)` (`word_prefix`), so the words + converge to an infinite word whose `n`-th letter (`n ≥ 1`) is `A035263 n`. We take this letter + from `word n` (length `2^n ≥ n`); `A035263_eq` shows that any `word k` with `n ≤ 2^k` gives + the same letter. `A035263_data` checks all `105` listed terms of A035263. +* *Indexing.* A127752 has offset `0` and A035263 has offset `1`; as Karttunen's note says, the + sequences are matched term by term from their first terms, i.e. `a(n) mod 2 = A035263(n+1)` + for all `n ≥ 0`. +* *The conjecture.* `statement : ∀ n, a n % 2 = A035263 (n + 1)`. +-/ + +namespace Math0.Statements.A127752 + +open Finset Matrix + +/-! ### The triangle and the row sums of its inverse -/ + +/-- The number triangle `A(n,k) = 1/(3n+1)` if `k ≤ n ≤ 2k`, `0` otherwise. -/ +def A (n k : ℕ) : ℚ := if k ≤ n ∧ n ≤ 2 * k then 1 / (3 * n + 1 : ℚ) else 0 + +/-- Forward substitution for `A s = 𝟙`: from `l = [s 0, …, s (n-1)]` (`n = l.length`) the next +value is `s n = 3n+1 - ∑_{j < n, n ≤ 2j} s j`. -/ +def next (l : List ℤ) : ℤ := + 3 * l.length + 1 - ∑ j ∈ range l.length, if l.length ≤ 2 * j then l.getD j 0 else 0 + +/-- `vals n = [a 0, …, a (n-1)]`. -/ +def vals : ℕ → List ℤ + | 0 => [] + | n + 1 => vals n ++ [next (vals n)] + +/-- A127752: the `n`-th row sum of the inverse of the triangle `A` (see `a_spec`). -/ +def a (n : ℕ) : ℤ := (vals (n + 1)).getD n 0 + +set_option maxRecDepth 100000 in +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all 106 listed +terms `a(0), …, a(105)`. -/ +theorem a_data : (List.range 106).map (fun i => a (i + 0)) = + [1, 4, 3, 7, 3, 6, 3, 10, 3, 6, 3, 9, 3, 6, 3, 13, 3, 6, 3, 9, 3, 6, 3, 12, 3, 6, 3, 9, 3, 6, + 3, 16, 3, 6, 3, 9, 3, 6, 3, 12, 3, 6, 3, 9, 3, 6, 3, 15, 3, 6, 3, 9, 3, 6, 3, 12, 3, 6, 3, 9, + 3, 6, 3, 19, 3, 6, 3, 9, 3, 6, 3, 12, 3, 6, 3, 9, 3, 6, 3, 15, 3, 6, 3, 9, 3, 6, 3, 12, 3, 6, + 3, 9, 3, 6, 3, 18, 3, 6, 3, 9, 3, 6, 3, 12, 3, 6] := by + decide +kernel + +/-! ### `a` gives the row sums of the inverse -/ + +theorem vals_length (n : ℕ) : (vals n).length = n := by + induction n with + | zero => rfl + | succ n ih => simp [vals, ih] + +theorem vals_getD (n j : ℕ) : (vals n).getD j 0 = if j < n then next (vals j) else 0 := by + induction n with + | zero => simp [vals] + | succ n ih => + rw [vals] + rcases lt_trichotomy j n with h | h | h + · rw [List.getD_append _ _ _ _ (by rw [vals_length]; exact h), ih, if_pos h, + if_pos (by omega)] + · subst h + rw [List.getD_append_right _ _ _ _ (by rw [vals_length]), vals_length, Nat.sub_self, + if_pos (by omega)] + rfl + · rw [List.getD_append_right _ _ _ _ (by rw [vals_length]; omega), vals_length, + if_neg (by omega)] + obtain ⟨d, hd⟩ : ∃ d, j - n = d + 1 := ⟨j - n - 1, by omega⟩ + rw [hd] + rfl + +theorem a_eq_next (n : ℕ) : a n = next (vals n) := by + rw [a, vals_getD, if_pos (Nat.lt_succ_self n)] + +/-- The forward-substitution recursion: `a n = 3n+1 - ∑_{j < n, n ≤ 2j} a j`. -/ +theorem a_rec (n : ℕ) : + a n = 3 * n + 1 - ∑ j ∈ range n, if n ≤ 2 * j then a j else 0 := by + rw [a_eq_next, next, vals_length] + refine congrArg (fun s => (3 * (n : ℤ) + 1) - s) (Finset.sum_congr rfl fun j hj => ?_) + rw [vals_getD, if_pos (Finset.mem_range.mp hj), ← a_eq_next] + +/-- Row `n` of `A` applied to the vector `a` gives `1`. -/ +theorem sum_A_mul_a (n N : ℕ) (hN : n < N) : ∑ j ∈ range N, A n j * (a j : ℚ) = 1 := by + obtain ⟨m, rfl⟩ : ∃ m, N = n + 1 + m := ⟨N - (n + 1), by omega⟩ + rw [Finset.sum_range_add, Finset.sum_eq_zero (s := range m) + (fun x _ => by rw [A, if_neg (by omega), zero_mul]), add_zero, Finset.sum_range_succ] + have h3 : (3 * n + 1 : ℚ) ≠ 0 := by positivity + have hsum : ∑ j ∈ range n, A n j * (a j : ℚ) = + (1 / (3 * n + 1 : ℚ)) * ((∑ j ∈ range n, if n ≤ 2 * j then a j else 0 : ℤ) : ℚ) := by + rw [Int.cast_sum, Finset.mul_sum] + refine Finset.sum_congr rfl fun j hj => ?_ + have hj := Finset.mem_range.mp hj + by_cases h : n ≤ 2 * j + · rw [A, if_pos ⟨hj.le, h⟩, if_pos h] + · rw [A, if_neg (fun h' => h h'.2), if_neg h] + simp + have hrec := a_rec n + rw [hsum, A, if_pos ⟨le_rfl, by omega⟩] + have hrecQ : (a n : ℚ) = 3 * n + 1 - + ((∑ j ∈ range n, if n ≤ 2 * j then a j else 0 : ℤ) : ℚ) := by + rw [hrec]; push_cast; ring + rw [hrecQ] + field_simp + ring + +/-- The `N × N` truncation of the triangle `A`. -/ +def Amat (N : ℕ) : Matrix (Fin N) (Fin N) ℚ := Matrix.of fun i j => A i j + +theorem Amat_isLowerTriangular (N : ℕ) : (Amat N).IsLowerTriangular := by + intro i j hij + have hij' : i < j := hij + simp only [Amat, Matrix.of_apply, A] + rw [if_neg (fun h => absurd h.1 (by simpa using hij'))] + +theorem Amat_det_ne_zero (N : ℕ) : (Amat N).det ≠ 0 := by + rw [Matrix.det_of_isLowerTriangular _ (Amat_isLowerTriangular N)] + refine Finset.prod_ne_zero_iff.mpr fun i _ => ?_ + simp only [Amat, Matrix.of_apply, A] + rw [if_pos ⟨le_rfl, by omega⟩] + positivity + +theorem Amat_mulVec_a (N : ℕ) : Amat N *ᵥ (fun j : Fin N => (a j : ℚ)) = fun _ => 1 := by + funext i + simp only [Matrix.mulVec, dotProduct, Amat, Matrix.of_apply] + rw [Fin.sum_univ_eq_sum_range (fun x => A i x * (a x : ℚ)) N] + exact sum_A_mul_a _ _ i.isLt + +/-- `a` gives the row sums of the inverse of `A`: for every `N` and every `n < N`, `a n` is the +sum of row `n` of `(Amat N)⁻¹`, the (Mathlib) inverse of the `N × N` truncation of `A`. -/ +theorem a_spec (N : ℕ) (i : Fin N) : (a i : ℚ) = ∑ j, (Amat N)⁻¹ i j := by + have hu : IsUnit (Amat N).det := isUnit_iff_ne_zero.mpr (Amat_det_ne_zero N) + have h := congrArg (fun v => (Amat N)⁻¹ *ᵥ v) (Amat_mulVec_a N) + simp only [Matrix.mulVec_mulVec, Matrix.nonsing_inv_mul _ hu, Matrix.one_mulVec] at h + rw [congrFun h i] + simp [Matrix.mulVec, dotProduct] + +/-! ### A035263: the first Feigenbaum symbolic sequence -/ + +/-- The morphism `0 ↦ 11, 1 ↦ 10` (only the letters `0`, `1` ever occur). -/ +def sigma (x : ℕ) : List ℕ := if x = 0 then [1, 1] else [1, 0] + +/-- `word k = sigma^k (1)`, the `k`-th step of the trajectory of `1` under `sigma`. -/ +def word : ℕ → List ℕ + | 0 => [1] + | k + 1 => (word k).flatMap sigma + +/-- A035263 (offset `1`): the `n`-th letter of the trajectory of `1` under `0 ↦ 11, 1 ↦ 10`, +read off `word n`, which has `2^n ≥ n` letters (any `word k` with `2^k ≥ n` gives the same +letter, see `A035263_eq`). -/ +def A035263 (n : ℕ) : ℕ := (word n).getD (n - 1) 0 + +/-- The definition reproduces all 105 terms of A035263 listed in OEIS (kernel-checked). -/ +theorem A035263_data : (List.range 105).map (fun i => A035263 (i + 1)) = + [1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, + 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, + 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, + 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1] := by + decide +kernel + +theorem word_length (k : ℕ) : (word k).length = 2 ^ k := by + induction k with + | zero => rfl + | succ k ih => + rw [word, List.length_flatMap, pow_succ, ← ih] + have : ∀ x ∈ word k, (sigma x).length = 2 := fun x _ => by + unfold sigma; split <;> rfl + rw [List.map_congr_left this, List.map_const', List.sum_replicate, smul_eq_mul] + +theorem word_prefix (k : ℕ) : word k <+: word (k + 1) := by + induction k with + | zero => exact ⟨[0], rfl⟩ + | succ k ih => + obtain ⟨t, ht⟩ := ih + refine ⟨t.flatMap sigma, ?_⟩ + rw [word, word, ← ht, List.flatMap_append] + +theorem word_prefix_of_le {k l : ℕ} (h : k ≤ l) : word k <+: word l := by + induction l, h using Nat.le_induction with + | base => exact List.prefix_refl _ + | succ l _ ih => exact ih.trans (word_prefix l) + +/-- The letter `A035263 n` (`n ≥ 1`) is the `n`-th letter of every `word k` with `n ≤ 2^k`. -/ +theorem A035263_eq {n k : ℕ} (hn : 1 ≤ n) (hk : n ≤ 2 ^ k) : + A035263 n = (word k).getD (n - 1) 0 := by + have hn' : n ≤ 2 ^ n := (Nat.lt_two_pow_self).le + have key : ∀ {k l : ℕ}, k ≤ l → n ≤ 2 ^ k → + (word k).getD (n - 1) 0 = (word l).getD (n - 1) 0 := by + intro k l hkl hk + have hlt : n - 1 < (word k).length := by rw [word_length]; omega + rw [List.getD_eq_getElem _ _ hlt, List.getD_eq_getElem _ _ + (lt_of_lt_of_le hlt (word_prefix_of_le hkl).length_le)] + exact (word_prefix_of_le hkl).getElem hlt + rw [A035263] + rcases le_total n k with h | h + · exact key h hn' + · exact (key h hk).symm + +/-! ### The conjecture -/ + +/-- `a(n) mod 2` is the first Feigenbaum symbolic sequence A035263, with A127752 indexed from +`0` and A035263 from `1`: `a(n) mod 2 = A035263(n+1)` for every `n ≥ 0`. -/ +def statement : Prop := ∀ n : ℕ, a n % 2 = (A035263 (n + 1) : ℤ) + +end Math0.Statements.A127752 diff --git a/lean/Math0/Statements/OEIS/A127755.lean b/lean/Math0/Statements/OEIS/A127755.lean new file mode 100644 index 0000000..2019c4f --- /dev/null +++ b/lean/Math0/Statements/OEIS/A127755.lean @@ -0,0 +1,194 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A127755: inverse of the triangle `1/n!` on `k ≤ n ≤ 2k` has integer entries + +Source: https://oeis.org/A127755, Paul Barry, Jan 28 2007. Verbatim: +> It is conjectured that this is an integer triangle. Row sums are A127756. + +The entry (offset `0`, keywords `sign,tabl`) is named "Inverse of number triangle +`A(n,k) = 1/n!` if `k <= n <= 2k`, 0 otherwise." + +## Encoding + +* *The triangle `A`.* `A n k : ℚ` is `1 / n!` if `k ≤ n ∧ n ≤ 2k` and `0` otherwise, exactly as + in the name (rows and columns indexed from `0`). It is an infinite lower-triangular matrix with + diagonal entries `A(n,n) = 1/n! ≠ 0`, so it has a unique (lower-triangular) inverse. +* *The inverse triangle `T`.* `T n k : ℚ` is computed by forward substitution from + `∑_{j ≤ n} A(n,j) T(j,k) = [n = k]`, i.e. + `T(n,k) = n! · ([n = k] - ∑_{j < n} A(n,j) T(j,k))` for `k ≤ n` and `T(n,k) = 0` for + `k > n` (`T_spec`, `T_eq_zero_of_lt`). The rows are built one at a time (`rows`) so the kernel + evaluates each entry only once. That `T` really is the inverse of `A` is proved, not assumed: + `inv_Amat` shows that for every `N` the `N × N` truncation `Tmat N` of `T` is the matrix inverse + `(Amat N)⁻¹` (Mathlib's `Matrix.inv`) of the `N × N` truncation of `A`. (For lower-triangular + infinite matrices the inverse is determined by these finite truncations.) +* *The sequence.* The OEIS sequence is the triangle read by rows, `0 ≤ k ≤ n`, offset `0`: + `a m = T n k` where `m = n(n+1)/2 + k` (`rowOf m` is this `n`). Its values are a priori + rationals, so `a : ℕ → ℚ`. `a_data` checks all `64` listed terms (rows `n = 0, …, 9` and the + first `9` entries of row `10`) in the kernel; `rows_data` checks the `13` rows `n = 0, …, 12` + shown in the entry's example. +* *The conjecture.* "This is an integer triangle": `statement` says every element `T(n,k)`, + `0 ≤ k ≤ n`, of the inverse triangle is an integer. `statement_iff_matrix` shows this is + equivalent to: for every `N`, all entries of `(Amat N)⁻¹` are integers. (Entries with `k > n` + are `0` anyway.) The second sentence of the comment (row sums are A127756) is a + cross-reference, not part of the conjecture. +-/ + +namespace Math0.Statements.A127755 + +open Finset + +/-! ### The triangle and its inverse -/ + +/-- The number triangle `A(n,k) = 1/n!` if `k ≤ n ≤ 2k`, `0` otherwise. -/ +def A (n k : ℕ) : ℚ := if k ≤ n ∧ n ≤ 2 * k then 1 / (n.factorial : ℚ) else 0 + +/-- Forward substitution: from the rows `0, …, n-1` of the inverse (`n = rs.length`), row `n` +(entries `k = 0, …, n`) is `T(n,k) = n! · ([n = k] - ∑_{j < n} A(n,j) T(j,k))`, which solves +`∑_{j ≤ n} A(n,j) T(j,k) = [n = k]` since `A(n,n) = 1/n!`. -/ +def nextRow (rs : List (List ℚ)) : List ℚ := + (List.range (rs.length + 1)).map fun k => + (rs.length.factorial : ℚ) * ((if rs.length = k then 1 else 0) - + ∑ j ∈ range rs.length, A rs.length j * (rs.getD j []).getD k 0) + +/-- The rows `0, …, n-1` of the inverse triangle. -/ +def rows : ℕ → List (List ℚ) + | 0 => [] + | n + 1 => rows n ++ [nextRow (rows n)] + +/-- The inverse triangle `T(n,k)` (entry `(n,k)` of `A⁻¹`; see `inv_Amat`). -/ +def T (n k : ℕ) : ℚ := ((rows (n + 1)).getD n []).getD k 0 + +/-- The row index `n` of position `m` when the triangle is read by rows: +the largest `n ≤ m` with `n(n+1)/2 ≤ m`. -/ +def rowOf (m : ℕ) : ℕ := + (List.range (m + 1)).foldl (fun acc n => if n * (n + 1) / 2 ≤ m then n else acc) 0 + +/-- A127755: the inverse triangle `T` read by rows (`0 ≤ k ≤ n`), offset `0`. -/ +def a (m : ℕ) : ℚ := T (rowOf m) (m - rowOf m * (rowOf m + 1) / 2) + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all 64 terms. -/ +theorem a_data : (List.range 64).map (fun i => a (i + 0)) = + ([1, 0, 1, 0, -1, 2, 0, 1, -2, 6, 0, 0, 0, -6, 24, 0, -1, 2, 0, -24, 120, 0, 0, 0, 0, 0, -120, + 720, 0, 1, -2, 6, 0, 0, -720, 5040, 0, 0, 0, 0, 0, 0, 0, -5040, 40320, 0, 0, 0, -6, 24, 0, 0, + 0, -40320, 362880, 0, 0, 0, 0, 0, 0, 0, 0, 0] : List ℤ).map (fun z => (z : ℚ)) := by + decide +kernel + +/-- The rows `0, …, 12` of the triangle shown in the entry's example (kernel-checked). -/ +theorem rows_data : rows 13 = [[1], [0, 1], [0, -1, 2], [0, 1, -2, 6], [0, 0, 0, -6, 24], + [0, -1, 2, 0, -24, 120], [0, 0, 0, 0, 0, -120, 720], [0, 1, -2, 6, 0, 0, -720, 5040], + [0, 0, 0, 0, 0, 0, 0, -5040, 40320], [0, 0, 0, -6, 24, 0, 0, 0, -40320, 362880], + [0, 0, 0, 0, 0, 0, 0, 0, 0, -362880, 3628800], + [0, -1, 2, 0, -24, 120, 0, 0, 0, 0, -3628800, 39916800], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -39916800, 479001600]] := by + decide +kernel + +/-! ### `T` is the inverse of `A` -/ + +theorem rows_length (n : ℕ) : (rows n).length = n := by + induction n with + | zero => rfl + | succ n ih => simp [rows, ih] + +theorem rows_getD (n j : ℕ) : (rows n).getD j [] = if j < n then nextRow (rows j) else [] := by + induction n with + | zero => simp [rows] + | succ n ih => + rw [rows] + rcases lt_trichotomy j n with h | h | h + · rw [List.getD_append _ _ _ _ (by rw [rows_length]; exact h), ih, if_pos h, + if_pos (by omega)] + · subst h + rw [List.getD_append_right _ _ _ _ (by rw [rows_length]), rows_length, Nat.sub_self, + if_pos (by omega)] + rfl + · rw [List.getD_append_right _ _ _ _ (by rw [rows_length]; omega), rows_length, + if_neg (by omega)] + obtain ⟨d, hd⟩ : ∃ d, j - n = d + 1 := ⟨j - n - 1, by omega⟩ + rw [hd] + rfl + +theorem T_eq (n k : ℕ) : T n k = (nextRow (rows n)).getD k 0 := by + rw [T, rows_getD, if_pos (Nat.lt_succ_self n)] + +/-- The forward-substitution recursion defining `T`. -/ +theorem T_spec (n k : ℕ) : + T n k = if k ≤ n then + (n.factorial : ℚ) * ((if n = k then 1 else 0) - ∑ j ∈ range n, A n j * T j k) else 0 := by + rw [T_eq, nextRow, rows_length, List.getD_eq_getElem?_getD, List.getElem?_map] + by_cases hk : k ≤ n + · rw [List.getElem?_range (by omega), if_pos hk, Option.map_some, Option.getD_some] + congr 2 + refine Finset.sum_congr rfl fun j hj => ?_ + rw [rows_getD, if_pos (Finset.mem_range.mp hj), ← T_eq] + · rw [List.getElem?_eq_none (by simp; omega), if_neg hk] + rfl + +theorem T_eq_zero_of_lt {n k : ℕ} (h : n < k) : T n k = 0 := by + rw [T_spec, if_neg (by omega)] + +theorem A_self (n : ℕ) : A n n = 1 / (n.factorial : ℚ) := by + rw [A, if_pos ⟨le_rfl, by omega⟩] + +theorem A_eq_zero_of_lt {n x : ℕ} (h : n < x) : A n x = 0 := by + rw [A, if_neg (by omega)] + +/-- Row `n` of `A` times column `k` of `T` is `[n = k]`. -/ +theorem sum_A_mul_T (n k N : ℕ) (hN : n < N) : + ∑ x ∈ range N, A n x * T x k = if n = k then 1 else 0 := by + obtain ⟨m, rfl⟩ : ∃ m, N = n + 1 + m := ⟨N - (n + 1), by omega⟩ + rw [Finset.sum_range_add, Finset.sum_eq_zero (s := range m) + (fun x _ => by rw [A_eq_zero_of_lt (by omega), zero_mul]), add_zero, Finset.sum_range_succ, + A_self] + have hc : (n.factorial : ℚ) ≠ 0 := by exact_mod_cast (Nat.factorial_pos n).ne' + by_cases hk : k ≤ n + · rw [T_spec n k, if_pos hk] + field_simp + ring + · rw [T_eq_zero_of_lt (by omega), if_neg (by omega), mul_zero, add_zero] + exact Finset.sum_eq_zero fun x hx => by + rw [T_eq_zero_of_lt (by have := Finset.mem_range.mp hx; omega), mul_zero] + +/-- The `N × N` truncation of the triangle `A`. -/ +def Amat (N : ℕ) : Matrix (Fin N) (Fin N) ℚ := Matrix.of fun i j => A i j + +/-- The `N × N` truncation of the triangle `T`. -/ +def Tmat (N : ℕ) : Matrix (Fin N) (Fin N) ℚ := Matrix.of fun i j => T i j + +theorem Amat_mul_Tmat (N : ℕ) : Amat N * Tmat N = 1 := by + ext i j + rw [Matrix.mul_apply, Matrix.one_apply] + simp only [Amat, Tmat, Matrix.of_apply] + rw [Fin.sum_univ_eq_sum_range (fun x => A i x * T x j) N, sum_A_mul_T _ _ _ i.isLt] + simp [Fin.ext_iff] + +/-- `T` is the inverse of `A`: for every `N`, `(Amat N)⁻¹ = Tmat N`. -/ +theorem inv_Amat (N : ℕ) : (Amat N)⁻¹ = Tmat N := + Matrix.inv_eq_right_inv (Amat_mul_Tmat N) + +/-! ### The conjecture -/ + +/-- The inverse triangle is an integer triangle: all elements `T(n,k)`, `0 ≤ k ≤ n`, are +integers. -/ +def statement : Prop := ∀ n k : ℕ, k ≤ n → ∃ z : ℤ, T n k = z + +/-- Equivalent form: for every `N`, the inverse of the `N × N` truncation of `A` has integer +entries. -/ +theorem statement_iff_matrix : + statement ↔ ∀ (N : ℕ) (i j : Fin N), ∃ z : ℤ, (Amat N)⁻¹ i j = z := by + constructor + · intro h N i j + rw [inv_Amat] + simp only [Tmat, Matrix.of_apply] + by_cases hji : (j : ℕ) ≤ i + · exact h i j hji + · exact ⟨0, by rw [T_eq_zero_of_lt (by omega)]; simp⟩ + · intro h n k hk + obtain ⟨z, hz⟩ := h (n + 1) ⟨n, by omega⟩ ⟨k, by omega⟩ + rw [inv_Amat] at hz + exact ⟨z, hz⟩ + +end Math0.Statements.A127755 diff --git a/lean/Math0/Statements/OEIS/A127767.lean b/lean/Math0/Statements/OEIS/A127767.lean new file mode 100644 index 0000000..a721d16 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A127767.lean @@ -0,0 +1,226 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A127767: inverse of the triangle `1/C(n)` on `k ≤ n ≤ 2k` has integer entries + +Source: https://oeis.org/A127767, Paul Barry, Jan 28 2007. Verbatim: +> It is conjectured that all elements of the triangle are integers. + +The entry (offset `0`, keywords `sign,tabl`) is named "Inverse of number triangle +`A(n,k) = 1/C(n)` if `k <= n <= 2k`, 0 otherwise, where `C(n) = A000108(n)`." + +## Encoding + +* *Catalan numbers.* `cat n` is `C(n) = A000108(n)`, computed by the product recursion + `C(n+1) = C(n) · 2(2n+1) / (n+2)` so that the kernel can evaluate it; `cat_eq_catalan` proves + `cat n = catalan n` (Mathlib's Catalan numbers) for every `n`. +* *The triangle `A`.* `A n k : ℚ` is `1 / C(n)` if `k ≤ n ∧ n ≤ 2k` and `0` otherwise, exactly as + in the name. It is an infinite lower-triangular matrix with diagonal entries + `A(n,n) = 1/C(n) ≠ 0`, so it has a unique (lower-triangular) inverse. +* *The inverse triangle `T`.* `T n k : ℚ` is computed by forward substitution from + `∑_{j ≤ n} A(n,j) T(j,k) = [n = k]`, i.e. + `T(n,k) = C(n) · ([n = k] - ∑_{j < n} A(n,j) T(j,k))` for `k ≤ n` and `T(n,k) = 0` for + `k > n` (`T_spec`, `T_eq_zero_of_lt`). The rows are built one at a time (`rows`) so the kernel + evaluates each entry only once. That `T` really is the inverse of `A` is proved, not assumed: + `inv_Amat` shows that for every `N` the `N × N` truncation `Tmat N` of `T` is the matrix inverse + `(Amat N)⁻¹` (Mathlib's `Matrix.inv`) of the `N × N` truncation of `A`. (For lower-triangular + infinite matrices the inverse is determined by these finite truncations.) +* *The sequence.* The OEIS sequence is the triangle read by rows, `0 ≤ k ≤ n`, offset `0`: + `a m = T n k` where `m = n(n+1)/2 + k` (`rowOf m` is this `n`). Its values are a priori + rationals, so `a : ℕ → ℚ`. `a_data` checks all `66` listed terms (rows `n = 0, …, 10`) in the + kernel; `rows_data` checks the same rows as lists. +* *The conjecture.* `statement`: every element `T(n,k)`, `0 ≤ k ≤ n`, of the inverse triangle is + an integer. `statement_iff_matrix` shows this is equivalent to: for every `N`, all entries of + `(Amat N)⁻¹` are integers. (Entries with `k > n` are `0` anyway.) +-/ + +namespace Math0.Statements.A127767 + +open Finset + +/-! ### Catalan numbers -/ + +/-- Catalan numbers `C(n) = A000108(n)` by the product recursion +`C(n+1) = C(n) · 2(2n+1) / (n+2)` (kernel-friendly; see `cat_eq_catalan`). -/ +def cat : ℕ → ℕ + | 0 => 1 + | n + 1 => cat n * (2 * (2 * n + 1)) / (n + 2) + +/-- `cat` agrees with Mathlib's `catalan`. -/ +theorem cat_eq_catalan (n : ℕ) : cat n = catalan n := by + induction n with + | zero => simp [cat] + | succ n ih => + rw [cat, ih] + have h1 := succ_mul_catalan_eq_centralBinom (n + 1) + have h2 := succ_mul_catalan_eq_centralBinom n + have h3 := Nat.succ_mul_centralBinom_succ n + have key : (n + 2) * catalan (n + 1) = 2 * (2 * n + 1) * catalan n := by + have : (n + 1) * ((n + 2) * catalan (n + 1)) = (n + 1) * (2 * (2 * n + 1) * catalan n) := by + calc (n + 1) * ((n + 2) * catalan (n + 1)) = (n + 1) * Nat.centralBinom (n + 1) := by + rw [← h1] + _ = 2 * (2 * n + 1) * Nat.centralBinom n := h3 + _ = (n + 1) * (2 * (2 * n + 1) * catalan n) := by rw [← h2]; ring + exact Nat.eq_of_mul_eq_mul_left (Nat.succ_pos n) this + rw [show catalan n * (2 * (2 * n + 1)) = (n + 2) * catalan (n + 1) by rw [key]; ring] + exact Nat.mul_div_cancel_left _ (by omega) + +theorem cat_pos (n : ℕ) : 0 < cat n := by + rw [cat_eq_catalan] + have h := succ_mul_catalan_eq_centralBinom n + have hc := Nat.centralBinom_pos n + rcases Nat.eq_zero_or_pos (catalan n) with h0 | h0 + · rw [h0, mul_zero] at h; omega + · exact h0 + +/-! ### The triangle and its inverse -/ + +/-- The number triangle `A(n,k) = 1/C(n)` if `k ≤ n ≤ 2k`, `0` otherwise. -/ +def A (n k : ℕ) : ℚ := if k ≤ n ∧ n ≤ 2 * k then 1 / (cat n : ℚ) else 0 + +/-- Forward substitution: from the rows `0, …, n-1` of the inverse (`n = rs.length`), row `n` +(entries `k = 0, …, n`) is `T(n,k) = C(n) · ([n = k] - ∑_{j < n} A(n,j) T(j,k))`, which solves +`∑_{j ≤ n} A(n,j) T(j,k) = [n = k]` since `A(n,n) = 1/C(n)`. -/ +def nextRow (rs : List (List ℚ)) : List ℚ := + (List.range (rs.length + 1)).map fun k => + (cat rs.length : ℚ) * ((if rs.length = k then 1 else 0) - + ∑ j ∈ range rs.length, A rs.length j * (rs.getD j []).getD k 0) + +/-- The rows `0, …, n-1` of the inverse triangle. -/ +def rows : ℕ → List (List ℚ) + | 0 => [] + | n + 1 => rows n ++ [nextRow (rows n)] + +/-- The inverse triangle `T(n,k)` (entry `(n,k)` of `A⁻¹`; see `inv_Amat`). -/ +def T (n k : ℕ) : ℚ := ((rows (n + 1)).getD n []).getD k 0 + +/-- The row index `n` of position `m` when the triangle is read by rows: +the largest `n ≤ m` with `n(n+1)/2 ≤ m`. -/ +def rowOf (m : ℕ) : ℕ := + (List.range (m + 1)).foldl (fun acc n => if n * (n + 1) / 2 ≤ m then n else acc) 0 + +/-- A127767: the inverse triangle `T` read by rows (`0 ≤ k ≤ n`), offset `0`. -/ +def a (m : ℕ) : ℚ := T (rowOf m) (m - rowOf m * (rowOf m + 1) / 2) + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all 66 terms. -/ +theorem a_data : (List.range 66).map (fun i => a i) = + ([1, 0, 1, 0, -1, 2, 0, 1, -2, 5, 0, 0, 0, -5, 14, 0, -1, 2, 0, -14, 42, 0, 0, 0, 0, 0, -42, + 132, 0, 1, -2, 5, 0, 0, -132, 429, 0, 0, 0, 0, 0, 0, 0, -429, 1430, 0, 0, 0, -5, 14, 0, 0, + 0, -1430, 4862, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4862, 16796] : List ℤ).map (fun z => (z : ℚ)) := by + decide +kernel + +/-- The same 66 terms, as the rows `0, …, 10` of the triangle (kernel-checked). -/ +theorem rows_data : rows 11 = [[1], [0, 1], [0, -1, 2], [0, 1, -2, 5], [0, 0, 0, -5, 14], + [0, -1, 2, 0, -14, 42], [0, 0, 0, 0, 0, -42, 132], [0, 1, -2, 5, 0, 0, -132, 429], + [0, 0, 0, 0, 0, 0, 0, -429, 1430], [0, 0, 0, -5, 14, 0, 0, 0, -1430, 4862], + [0, 0, 0, 0, 0, 0, 0, 0, 0, -4862, 16796]] := by + decide +kernel + +/-! ### `T` is the inverse of `A` -/ + +theorem rows_length (n : ℕ) : (rows n).length = n := by + induction n with + | zero => rfl + | succ n ih => simp [rows, ih] + +theorem rows_getD (n j : ℕ) : (rows n).getD j [] = if j < n then nextRow (rows j) else [] := by + induction n with + | zero => simp [rows] + | succ n ih => + rw [rows] + rcases lt_trichotomy j n with h | h | h + · rw [List.getD_append _ _ _ _ (by rw [rows_length]; exact h), ih, if_pos h, + if_pos (by omega)] + · subst h + rw [List.getD_append_right _ _ _ _ (by rw [rows_length]), rows_length, Nat.sub_self, + if_pos (by omega)] + rfl + · rw [List.getD_append_right _ _ _ _ (by rw [rows_length]; omega), rows_length, + if_neg (by omega)] + obtain ⟨d, hd⟩ : ∃ d, j - n = d + 1 := ⟨j - n - 1, by omega⟩ + rw [hd] + rfl + +theorem T_eq (n k : ℕ) : T n k = (nextRow (rows n)).getD k 0 := by + rw [T, rows_getD, if_pos (Nat.lt_succ_self n)] + +/-- The forward-substitution recursion defining `T`. -/ +theorem T_spec (n k : ℕ) : + T n k = if k ≤ n then + (cat n : ℚ) * ((if n = k then 1 else 0) - ∑ j ∈ range n, A n j * T j k) else 0 := by + rw [T_eq, nextRow, rows_length, List.getD_eq_getElem?_getD, List.getElem?_map] + by_cases hk : k ≤ n + · rw [List.getElem?_range (by omega), if_pos hk, Option.map_some, Option.getD_some] + congr 2 + refine Finset.sum_congr rfl fun j hj => ?_ + rw [rows_getD, if_pos (Finset.mem_range.mp hj), ← T_eq] + · rw [List.getElem?_eq_none (by simp; omega), if_neg hk] + rfl + +theorem T_eq_zero_of_lt {n k : ℕ} (h : n < k) : T n k = 0 := by + rw [T_spec, if_neg (by omega)] + +theorem A_self (n : ℕ) : A n n = 1 / (cat n : ℚ) := by + rw [A, if_pos ⟨le_rfl, by omega⟩] + +theorem A_eq_zero_of_lt {n x : ℕ} (h : n < x) : A n x = 0 := by + rw [A, if_neg (by omega)] + +/-- Row `n` of `A` times column `k` of `T` is `[n = k]`. -/ +theorem sum_A_mul_T (n k N : ℕ) (hN : n < N) : + ∑ x ∈ range N, A n x * T x k = if n = k then 1 else 0 := by + obtain ⟨m, rfl⟩ : ∃ m, N = n + 1 + m := ⟨N - (n + 1), by omega⟩ + rw [Finset.sum_range_add, Finset.sum_eq_zero (s := range m) + (fun x _ => by rw [A_eq_zero_of_lt (by omega), zero_mul]), add_zero, Finset.sum_range_succ, + A_self] + have hc : (cat n : ℚ) ≠ 0 := by exact_mod_cast (cat_pos n).ne' + by_cases hk : k ≤ n + · rw [T_spec n k, if_pos hk] + field_simp + ring + · rw [T_eq_zero_of_lt (by omega), if_neg (by omega), mul_zero, add_zero] + exact Finset.sum_eq_zero fun x hx => by + rw [T_eq_zero_of_lt (by have := Finset.mem_range.mp hx; omega), mul_zero] + +/-- The `N × N` truncation of the triangle `A`. -/ +def Amat (N : ℕ) : Matrix (Fin N) (Fin N) ℚ := Matrix.of fun i j => A i j + +/-- The `N × N` truncation of the triangle `T`. -/ +def Tmat (N : ℕ) : Matrix (Fin N) (Fin N) ℚ := Matrix.of fun i j => T i j + +theorem Amat_mul_Tmat (N : ℕ) : Amat N * Tmat N = 1 := by + ext i j + rw [Matrix.mul_apply, Matrix.one_apply] + simp only [Amat, Tmat, Matrix.of_apply] + rw [Fin.sum_univ_eq_sum_range (fun x => A i x * T x j) N, sum_A_mul_T _ _ _ i.isLt] + simp [Fin.ext_iff] + +/-- `T` is the inverse of `A`: for every `N`, `(Amat N)⁻¹ = Tmat N`. -/ +theorem inv_Amat (N : ℕ) : (Amat N)⁻¹ = Tmat N := + Matrix.inv_eq_right_inv (Amat_mul_Tmat N) + +/-! ### The conjecture -/ + +/-- All elements `T(n,k)`, `0 ≤ k ≤ n`, of the inverse triangle are integers. -/ +def statement : Prop := ∀ n k : ℕ, k ≤ n → ∃ z : ℤ, T n k = z + +/-- Equivalent form: for every `N`, the inverse of the `N × N` truncation of `A` has integer +entries. -/ +theorem statement_iff_matrix : + statement ↔ ∀ (N : ℕ) (i j : Fin N), ∃ z : ℤ, (Amat N)⁻¹ i j = z := by + constructor + · intro h N i j + rw [inv_Amat] + simp only [Tmat, Matrix.of_apply] + by_cases hji : (j : ℕ) ≤ i + · exact h i j hji + · exact ⟨0, by rw [T_eq_zero_of_lt (by omega)]; simp⟩ + · intro h n k hk + obtain ⟨z, hz⟩ := h (n + 1) ⟨n, by omega⟩ ⟨k, by omega⟩ + rw [inv_Amat] at hz + exact ⟨z, hz⟩ + +end Math0.Statements.A127767 diff --git a/lean/Math0/Statements/OEIS/A129455.lean b/lean/Math0/Statements/OEIS/A129455.lean new file mode 100644 index 0000000..5bd0097 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A129455.lean @@ -0,0 +1,101 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A129455: the triple-gcd analog of Pascal's triangle + +Source: https://oeis.org/A129455, Peter Bala, Apr 16 2007 (COMMENTS section). Verbatim: +> It appears that the T(n,k) are always integers. This would follow from the conjectured prime +> factorization given in A129454. Calculation suggests that the binomial coefficients C(n,k) +> divide T(n,k) and that T(n,k)/C(n,k) are perfect sixth powers. + +The entry (offset `0`, keyword `tabl`) is "An analog of Pascal's triangle based on A129454. +T(n, k) = A129454(n+1)/(A129454(n-k+1)*A129454(k+1))", where A129454 (offset `0`) is +"a(n) = Product{i=1..n-1} Product{j=1..n-1} Product{k=1..n-1} gcd(i,j,k)" (so `a(0) = a(1) = 1`, +the empty product). + +## Encoding + +* `A129454 n` is the product of `gcd(gcd(i, j), k)` over `i, j, k ∈ [1, n - 1]`, as a `Finset` + product over `Finset.Icc 1 (n - 1)` (for `n = 0` the range is empty since `0 - 1 = 0` in `ℕ`; + only arguments `≥ 1` are ever used below). `A129454_data` checks its first 10 listed terms. +* `T n k` (for `0 ≤ k ≤ n`) is `A129454 (n + 1) / (A129454 (n - k + 1) * A129454 (k + 1))`, + computed with natural-number division. A priori this quotient need not be exact; whether it is + exact is precisely the first part of the conjecture, which is therefore stated as the + divisibility `A129454 (n - k + 1) * A129454 (k + 1) ∣ A129454 (n + 1)`. Under that divisibility + `T n k` is the true (rational) value of `T(n, k)`, and under `C(n,k) ∣ T n k` the natural-number + quotient `T n k / C(n, k)` is the true value of `T(n,k)/C(n,k)`; so the conjunction below is + equivalent to the conjecture read over `ℚ`. +* `a` is the triangle read by rows (the OEIS sequence itself, offset `0`); `a_data` checks all 45 + listed terms `a 0, …, a 44` (rows `n = 0, …, 8`) in the kernel. +* The conjecture: for all `n ≥ 0` and `0 ≤ k ≤ n`, (1) `T(n,k)` is an integer, (2) `C(n,k)` + divides `T(n,k)`, and (3) `T(n,k)/C(n,k) = m^6` for some natural number `m` (a "perfect sixth + power"; since `T(n,k) > 0`, necessarily `m ≥ 1`). The remark that (1) "would follow from the + conjectured prime factorization given in A129454" is an explanation, not part of the claim, and + is not encoded. `statement_check` verifies the three claims for rows `n ≤ 8` with explicit + sixth roots (a sanity check of the transcription, not a proof). +-/ + +namespace Math0.Statements.A129455 + +/-- A129454: `a(n) = ∏_{i=1}^{n-1} ∏_{j=1}^{n-1} ∏_{k=1}^{n-1} gcd(i, j, k)`. -/ +def A129454 (n : ℕ) : ℕ := + ∏ i ∈ Finset.Icc 1 (n - 1), ∏ j ∈ Finset.Icc 1 (n - 1), ∏ k ∈ Finset.Icc 1 (n - 1), + Nat.gcd (Nat.gcd i j) k + +/-- The definition of A129454 reproduces its first listed terms (kernel-checked). -/ +theorem A129454_data : (List.range 10).map A129454 = + [1, 1, 1, 2, 6, 1536, 7680, 8806025134080, 61642175938560, + 2168841254587541957294161920] := by + decide +kernel + +/-- A129455: `T(n, k) = A129454(n+1)/(A129454(n-k+1)*A129454(k+1))` for `0 ≤ k ≤ n` +(natural-number division). -/ +def T (n k : ℕ) : ℕ := A129454 (n + 1) / (A129454 (n - k + 1) * A129454 (k + 1)) + +/-- A129455 as a sequence (offset `0`): the triangle `T` read by rows. (Rows `0, …, i` contain at +least `i + 1` entries, so the `i`-th entry of the concatenation lies among them.) -/ +def a (i : ℕ) : ℕ := + ((List.range (i + 1)).flatMap fun n => (List.range (n + 1)).map (T n)).getD i 0 + +/-- The definition reproduces all 45 terms listed in OEIS, `a 0, …, a 44` (kernel-checked). -/ +theorem a_data : (List.range 45).map (fun i => a (i + 0)) = + [1, 1, 1, 1, 2, 1, 1, 3, 3, 1, 1, 256, 384, 256, 1, 1, 5, 640, 640, 5, 1, 1, 1146617856, + 2866544640, 244611809280, 2866544640, 1146617856, 1, 1, 7, 4013162496, 6688604160, + 6688604160, 4013162496, 7, 1, 1, 35184372088832, 123145302310912, + 47066867504069920948224, 919274755938865643520, 47066867504069920948224, + 123145302310912, 35184372088832, 1] := by + decide +kernel + +/-- Conjecture (Peter Bala, 2007): for all `0 ≤ k ≤ n`, `T(n,k)` is an integer (i.e. +`A129454(n-k+1) * A129454(k+1)` divides `A129454(n+1)`), the binomial coefficient `C(n,k)` divides +`T(n,k)`, and `T(n,k)/C(n,k)` is a perfect sixth power. -/ +def statement : Prop := + ∀ n k : ℕ, k ≤ n → + A129454 (n - k + 1) * A129454 (k + 1) ∣ A129454 (n + 1) ∧ + n.choose k ∣ T n k ∧ + ∃ m : ℕ, T n k / n.choose k = m ^ 6 + +/-- Explicit sixth roots of `T(n,k)/C(n,k)` for rows `n = 0, …, 8`. -/ +def roots : List (List ℕ) := + [[1], + [1, 1], + [1, 1, 1], + [1, 1, 1, 1], + [1, 2, 2, 2, 1], + [1, 1, 2, 2, 1, 1], + [1, 24, 24, 48, 24, 24, 1], + [1, 1, 24, 24, 24, 24, 1, 1], + [1, 128, 128, 3072, 1536, 3072, 128, 128, 1]] + +/-- Sanity check of the transcription (not a proof): the three claims hold for rows `n ≤ 8`, +with the sixth roots listed in `roots`. -/ +theorem statement_check : ∀ n < 9, ∀ k < n + 1, + A129454 (n - k + 1) * A129454 (k + 1) ∣ A129454 (n + 1) ∧ + n.choose k ∣ T n k ∧ + T n k / n.choose k = ((roots.getD n []).getD k 0) ^ 6 := by + decide +kernel + +end Math0.Statements.A129455 diff --git a/lean/Math0/Statements/OEIS/A132616.lean b/lean/Math0/Statements/OEIS/A132616.lean new file mode 100644 index 0000000..6663ad7 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A132616.lean @@ -0,0 +1,141 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A132616: Irwin's nested sums for column 0 of the odd-power triangle A132615 + +Source: https://oeis.org/A132616, Benedict W. J. Irwin, Nov 29 2016 (FORMULA section). Verbatim: +> Conjecture: a(n) is described by a series of nested sums, +> a(2) = Sum_{i=1..1} 1, +> a(3) = Sum_{i=1..1+2} Sum_{j=1..i} 1, +> a(4) = Sum_{i=1..1+4} Sum_{j=1..i+2} Sum_{k=1..j} 1, +> a(5) = Sum_{i=1..1+6} Sum_{j=1..i+4} Sum_{k=1..j+2} Sum_{l=1..k} 1, +> and so on, where 2, 4, 6,... are the even numbers. + +The entry (Paul D. Hanna, Aug 24 2007; offset `0`) is "Column 0 of triangle A132615", and +A132615 (same author and date, offset `0`, keyword `tabl`) is "Triangle T, read by rows, where +row n+1 of T = row n of T^(2n-1) with appended '1' for n>=0 with T(0,0)=1." + +## Encoding + +* *The triangle.* `T` is the infinite lower-triangular matrix with `T(0,0) = 1` such that, for + every `n ≥ 0`, row `n+1` of `T` is row `n` of `T^(2n-1)` (entries `0, …, n`) followed by + `T(n+1,n+1) = 1` (and zeros after it). `tri n : Matrix (Fin (n+1)) (Fin (n+1)) ℕ` is the + leading `(n+1) × (n+1)` block of `T` (rows and columns `0, …, n`), built row by row: + `tri 0 = [[1]]`, and `tri (n+1)` is `tri n` bordered by a zero last column and by the last + row `((tri n)^(2n-1))[n, 0..n] ++ [1]` (Mathlib's matrix power). +* *Why the truncation is faithful.* `tri n` is lower triangular (`tri_lower`), hence so is `T`, + and the entry `(n, j)` of any power `T^e` only involves entries `T(i, l)` with + `j ≤ l ≤ i ≤ n`; so row `n` of `T^e` is row `n` of `(tri n)^e`. Moreover `tri (n+1)` restricts + to `tri n` on its first `n+1` rows and columns (`tri_succ_castSucc`), so all the blocks are + consistent truncations of one infinite matrix `T`, given by `T n k` below. +* *The case `n = 0`.* There the exponent `2n-1 = -1` is negative: row `1` is row `0` of `T⁻¹` + with a `1` appended. As `T` is lower unitriangular, row `0` of `T⁻¹` is `[1]` (followed by + zeros), so row `1` is `[1, 1]`. In the code the exponent is the natural number `2 * n - 1`, + which is `0` for `n = 0` (truncated subtraction); `(tri 0)^0 = [[1]]` has row `0` equal to + `[1]` as well, so this is exactly the OEIS row `1`. (The `1 × 1` matrix `[[1]] = tri 0` has + every integer power equal to `[[1]]`.) +* *Data.* `T_data` checks all 55 listed terms of A132615 (rows `0, …, 9`), and `a_data` checks + all 19 listed terms `a(0), …, a(18)` of A132616 in the kernel, where `a n = T n 0`. +* *The nested sums.* For `m` nested sums with outer bound parameter `c`, write + `nest m c = Sum_{i_1=1..c+2(m-1)} Sum_{i_2=1..i_1+2(m-2)} ⋯ Sum_{i_m=1..i_(m-1)+0} 1`; + recursively `nest 0 c = 1` and `nest (m+1) c = Sum_{i=1..c+2m} nest m i`. Irwin's `a(n)` has + `n - 1` nested sums whose upper limits add the even numbers `2(n-2), 2(n-3), …, 2, 0` to the + previous index (to `1` for the outermost sum), i.e. it is `nest (n-1) 1`. The theorems + `nest_two`, …, `nest_five` show that `nest (n-1) 1` is literally the displayed expression for + `n = 2, 3, 4, 5` (`Finset.Icc 1 b` is `{1, …, b}`). +* *The conjecture.* `statement`: for every `n ≥ 2`, `a n = nest (n - 1) 1`. The displayed + formulas start at `a(2)`, so `n ≥ 2` is the range of the conjecture. `statement_check` confirms + the identity for `2 ≤ n ≤ 12` (a sanity check of the transcription, not a proof). +-/ + +namespace Math0.Statements.A132616 + +open Finset + +/-- The leading `(n+1) × (n+1)` block of the triangle A132615 (rows and columns `0, …, n`): +`tri 0 = [[1]]`, and `tri (n+1)` keeps `tri n` in rows `0, …, n` (with a `0` in the new column +`n+1`), while its last row `n+1` is row `n` of `(tri n)^(2n-1)` with a `1` appended. -/ +def tri : (n : ℕ) → Matrix (Fin (n + 1)) (Fin (n + 1)) ℕ + | 0 => 1 + | n + 1 => Matrix.of fun i j => + if hi : (i : ℕ) ≤ n then + if hj : (j : ℕ) ≤ n then tri n ⟨i, Nat.lt_succ_of_le hi⟩ ⟨j, Nat.lt_succ_of_le hj⟩ + else 0 + else + if hj : (j : ℕ) ≤ n then (tri n ^ (2 * n - 1)) (Fin.last n) ⟨j, Nat.lt_succ_of_le hj⟩ + else 1 + +/-- The triangle A132615: `T n k` for `0 ≤ k ≤ n` (and `0` above the diagonal). -/ +def T (n k : ℕ) : ℕ := + if h : k ≤ n then tri n (Fin.last n) ⟨k, Nat.lt_succ_of_le h⟩ else 0 + +/-- A132616: column `0` of the triangle A132615, `a(n) = T(n, 0)`. -/ +def a (n : ℕ) : ℕ := T n 0 + +/-- `tri n` is lower triangular. -/ +theorem tri_lower : ∀ (n : ℕ) (i j : Fin (n + 1)), (i : ℕ) < j → tri n i j = 0 + | 0, i, j, h => by omega + | n + 1, i, j, h => by + simp only [tri, Matrix.of_apply] + split_ifs with hi hj hj + · exact tri_lower n _ _ h + · rfl + · omega + · omega + +/-- `tri (n+1)` restricts to `tri n` on rows and columns `0, …, n`. -/ +theorem tri_succ_castSucc (n : ℕ) (i j : Fin (n + 1)) : + tri (n + 1) i.castSucc j.castSucc = tri n i j := by + simp [tri, Fin.is_le] + +/-- The definition reproduces the 55 listed terms of the triangle A132615 (rows `0, …, 9`, +read by rows; kernel-checked). -/ +theorem T_data : ((List.range 10).flatMap fun n => (List.range (n + 1)).map fun k => T n k) = + [1, 1, 1, 1, 1, 1, 6, 3, 1, 1, 80, 25, 5, 1, 1, 1666, 378, 56, 7, 1, 1, 47232, 8460, 1020, 99, + 9, 1, 1, 1694704, 252087, 26015, 2134, 154, 11, 1, 1, 73552752, 9392890, 855478, + 61919, 3848, 221, 13, 1, 1, 3744491970, 420142350, 34461260, 2257413, 125760, 6290, 300, + 15, 1, 1] := by + decide +kernel + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all 19 listed +terms `a(0), …, a(18)`. -/ +theorem a_data : (List.range 19).map (fun i => a (i + 0)) = + [1, 1, 1, 6, 80, 1666, 47232, 1694704, 73552752, 3744491970, 218684051648, + 14406896813608, 1056681951098592, 85379764462169382, 7534286318509305600, + 720884741940337283712, 74330131862002429961712, 8215901579822006354547330, + 969069489665924620416715008] := by + decide +kernel + +/-- Irwin's nested sums with `m` summation signs and outer parameter `c`: +`nest m c = Sum_{i_1=1..c+2(m-1)} Sum_{i_2=1..i_1+2(m-2)} ⋯ Sum_{i_m=1..i_(m-1)} 1`. -/ +def nest : ℕ → ℕ → ℕ + | 0, _ => 1 + | m + 1, c => ∑ i ∈ Icc 1 (c + 2 * m), nest m i + +/-- The displayed instance `a(2) = Sum_{i=1..1} 1`. -/ +theorem nest_two : nest (2 - 1) 1 = ∑ _i ∈ Icc 1 1, 1 := rfl + +/-- The displayed instance `a(3) = Sum_{i=1..1+2} Sum_{j=1..i} 1`. -/ +theorem nest_three : nest (3 - 1) 1 = ∑ i ∈ Icc 1 (1 + 2), ∑ _j ∈ Icc 1 i, 1 := rfl + +/-- The displayed instance `a(4) = Sum_{i=1..1+4} Sum_{j=1..i+2} Sum_{k=1..j} 1`. -/ +theorem nest_four : + nest (4 - 1) 1 = ∑ i ∈ Icc 1 (1 + 4), ∑ j ∈ Icc 1 (i + 2), ∑ _k ∈ Icc 1 j, 1 := rfl + +/-- The displayed instance +`a(5) = Sum_{i=1..1+6} Sum_{j=1..i+4} Sum_{k=1..j+2} Sum_{l=1..k} 1`. -/ +theorem nest_five : nest (5 - 1) 1 = + ∑ i ∈ Icc 1 (1 + 6), ∑ j ∈ Icc 1 (i + 4), ∑ k ∈ Icc 1 (j + 2), ∑ _l ∈ Icc 1 k, 1 := rfl + +/-- Irwin's conjecture (2016): for every `n ≥ 2`, `a(n)` (column `0` of A132615) equals the +`n - 1` nested sums `Sum_{i_1=1..1+2(n-2)} Sum_{i_2=1..i_1+2(n-3)} ⋯ Sum_{i_(n-1)=1..i_(n-2)} 1`. -/ +def statement : Prop := ∀ n : ℕ, 2 ≤ n → a n = nest (n - 1) 1 + +/-- Sanity check of the transcription (not a proof): the identity holds for `2 ≤ n ≤ 12`. -/ +theorem statement_check : ∀ n ∈ Icc 2 12, a n = nest (n - 1) 1 := by + decide +kernel + +end Math0.Statements.A132616 diff --git a/lean/Math0/Statements/OEIS/A141412.lean b/lean/Math0/Statements/OEIS/A141412.lean new file mode 100644 index 0000000..a4be50f --- /dev/null +++ b/lean/Math0/Statements/OEIS/A141412.lean @@ -0,0 +1,100 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A141412: denominators of the coefficients of Curtz's polynomials `P(n,x)` + +Source: https://oeis.org/A141412, _Michel Marcus_, Oct 18 2018 (FORMULA section). Verbatim: +> Conjecture: T(n, k) = d(n+1, k+1), with d(n,k) = denominator(A000254(n, k)*k!/n!) where +> A000254 are the unsigned Stirling numbers of the 1st kind. See d(n,k) in Farhi link. + +The entry (_Paul Curtz_, Aug 04 2008, offset `0`, keyword `tabl`) is "Triangle c(n,k) of the +denominators of coefficients [x^k] P(n,x) of the polynomials P(n,x) of A129891", read by rows +`0 ≤ k ≤ n`. The polynomials are defined in A129891 / A140749: "P(0,x)=1 and +P(n,x) = (-1)^n/(n+1) + x* Sum_{i=0..n-1} (-1)^i*P(n-1-i,x)/(i+1)". + +## Encoding + +* `P n : ℚ[X]` is the polynomial `P(n,x)`, defined literally by that recursion (written for + `n + 1`: `P(n+1,x) = (-1)^(n+1)/((n+1)+1) + x ∑_{i=0}^{n} (-1)^i/(i+1) P(n-i,x)`). It is + noncomputable (Mathlib polynomials are), so the table entries are computed by `c n k : ℚ`, a + computable recursion for the coefficients, and `coeff_P` proves `(P n).coeff k = c n k` for all + `n, k`. +* `T n k = (c n k).den` is the denominator of `[x^k] P(n,x)` (`T_eq_den_coeff`); Mathlib's `Rat` + is in lowest terms with positive denominator, as Maple's `denom` / Mathematica's `Denominator` + in the entry's programs. `T_data` checks all 78 listed terms (rows `n = 0, …, 11`, read by + rows) in the kernel. (The triangle is named `T`, as in the conjecture, rather than `a`.) +* `d n k = den(|s(n,k)| · k!/n!)`. Although A000254 is, strictly, the one-index sequence + `|s(n+1,2)|`, the comment uses it as a two-argument function and explicitly says it means "the + unsigned Stirling numbers of the 1st kind", so `A000254(n, k)` is read as the unsigned Stirling + number of the first kind `|s(n,k)|`, Mathlib's `Nat.stirlingFirst n k` (= A132393(n,k)). This + agrees with Farhi's `d(n,k)` and with G. C. Greubel's formula/programs in the entry + (`Denominator[(k+1)!*StirlingS1[n+1,k+1]/(n+1)!]`; the sign does not affect the denominator). +* *The conjecture.* `statement`: for every entry of the triangle, i.e. all `n ≥ 0` and + `0 ≤ k ≤ n`, `T n k = d (n+1) (k+1)`. +-/ + +namespace Math0.Statements.A141412 + +open Polynomial + +/-- Curtz's polynomials (A129891, A140749): `P(0,x) = 1` and, for `n ≥ 1`, +`P(n,x) = (-1)^n/(n+1) + x ∑_{i=0}^{n-1} (-1)^i/(i+1) · P(n-1-i,x)` (written here for `n + 1`). -/ +noncomputable def P : ℕ → ℚ[X] + | 0 => 1 + | n + 1 => C ((-1) ^ (n + 1) / (((n + 1 : ℕ) : ℚ) + 1)) + + X * ∑ i ∈ Finset.range (n + 1), C ((-1) ^ i / ((i : ℚ) + 1)) * P (n - i) +decreasing_by omega + +/-- The coefficient `[x^k] P(n,x)`, by a computable recursion (see `coeff_P`). -/ +def c : ℕ → ℕ → ℚ + | 0, 0 => 1 + | 0, _ + 1 => 0 + | n + 1, 0 => (-1) ^ (n + 1) / (((n + 1 : ℕ) : ℚ) + 1) + | n + 1, k + 1 => ∑ i ∈ Finset.range (n + 1), (-1) ^ i / ((i : ℚ) + 1) * c (n - i) k + +/-- `c n k` is the coefficient of `x^k` in `P(n,x)`. -/ +theorem coeff_P (n k : ℕ) : (P n).coeff k = c n k := by + induction k generalizing n with + | zero => + cases n with + | zero => simp [P, c] + | succ n => simp [P, c] + | succ k ih => + cases n with + | zero => simp [P, c, coeff_one] + | succ n => + rw [P, c, coeff_add, coeff_C, if_neg (Nat.succ_ne_zero k), zero_add, coeff_X_mul, + finsetSum_coeff] + refine Finset.sum_congr rfl fun i _ => ?_ + rw [coeff_C_mul, ih] + +/-- A141412: `T(n,k)` is the denominator of the coefficient `[x^k] P(n,x)` (`0 ≤ k ≤ n`). -/ +def T (n k : ℕ) : ℕ := (c n k).den + +/-- `T(n,k)` is the denominator (in lowest terms) of `[x^k] P(n,x)`. -/ +theorem T_eq_den_coeff (n k : ℕ) : T n k = ((P n).coeff k).den := by + rw [T, coeff_P] + +/-- The definition reproduces all 78 terms listed in OEIS (rows `n = 0, …, 11`, read by rows; +kernel-checked). -/ +theorem T_data : (List.range 12).flatMap (fun n => (List.range (n + 1)).map (fun k => T n k)) = + [1, 2, 1, 3, 1, 1, 4, 12, 2, 1, 5, 6, 4, 1, 1, 6, 180, 8, 6, 2, 1, 7, 10, 15, 2, 6, 1, 1, 8, + 560, 240, 240, 6, 4, 2, 1, 9, 1260, 15120, 20, 144, 1, 12, 1, 1, 10, 12600, 672, 945, 32, + 240, 8, 3, 2, 1, 11, 1260, 8400, 1512, 3024, 48, 240, 3, 1, 1, 1, 12, 166320, 100800, + 64800, 12096, 12096, 480, 360, 4, 12, 2, 1] := by + decide +kernel + +/-- Farhi's `d(n,k) = denominator(|s(n,k)| · k!/n!)`, with `|s(n,k)|` the unsigned Stirling +number of the first kind (Mathlib's `Nat.stirlingFirst`). -/ +def d (n k : ℕ) : ℕ := + ((Nat.stirlingFirst n k : ℚ) * (Nat.factorial k : ℚ) / (Nat.factorial n : ℚ)).den + +/-- Conjecture (Marcus, A141412): `T(n,k) = d(n+1,k+1)` for every entry `0 ≤ k ≤ n` of the +triangle. -/ +def statement : Prop := + ∀ n k : ℕ, k ≤ n → T n k = d (n + 1) (k + 1) + +end Math0.Statements.A141412 diff --git a/lean/Math0/Statements/OEIS/A144637.lean b/lean/Math0/Statements/OEIS/A144637.lean new file mode 100644 index 0000000..f861e29 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A144637.lean @@ -0,0 +1,275 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A144637: parity of `(1/18) 6^n a(n) / n!` (column 2 of the inverse of A144385) + +Source: https://oeis.org/A144637, Peter Bala, Feb 19 2026 (FORMULA section). Verbatim: +> Conjecture: (1/18)*6^(n)*a(n)/n! is odd iff n = 2^k for k >= 1. + +The entry (offset `0`, keywords `sign,easy`) is named "Column 2 of triangle in A144633." +A144633 (offset `0`) is the "Triangle of 3-restricted Stirling numbers of the first kind +(T(n,k), 0 <= k <= n), read by rows", with the definition "take the triangle in A144385, write +it as an (infinite) upper triangular square matrix, invert it and transpose it." A144385 is the +"Triangle read by rows: T(n,k) is the number of partitions of [1, 2, ..., k] into exactly n +blocks, each of size 1, 2 or 3 (n >= 0, 0 <= k <= 3n)", with the formula +"T(n, k) = T(n - 1, k - 1) + (k - 1)*T(n - 1, k - 2) + (1/2)*(k - 1)*(k - 2)*T(n - 1, k - 3)". +Just before the conjecture the entry says that `(1/18)*A(6*x) = x^2 - 6*x^3 + 33*x^4 - ...` +(`A` the e.g.f. of the sequence) "appears to be an integral series". + +## Encoding + +* *A144385.* `S n k : ℕ` is A144385 `T(n,k)`. Row `0` is `[1]` and row `n+1` is built from row + `n` by the A144385 recurrence (this is also how the OEIS Maple/Mathematica programs compute it; + the recurrence is the usual case split on whether the element `k` lies in a block of size `1`, + `2` or `3`). The rows are stored as lists (`srow`) so the kernel computes each entry once. + `S_zero` and `S_succ` prove that `S` satisfies exactly row `0` and the A144385 recurrence for + every `n` and `k` (terms with a negative index are `0`), which determine it uniquely; + `S_data` checks all `70` listed terms of A144385 (rows `0, …, 6`). +* *A144633.* Write `M` for the infinite upper triangular matrix `M(i,j) = S i j` (`S_eq_zero_of_lt`, + `S_self`: it is unitriangular). Its inverse `R = M⁻¹` is upper triangular, and A144633 is + `T(n,k) = R(k,n)`. From `R M = 1`, forward substitution gives, for `k ≤ n`, + `T(n,k) = [n = k] - ∑_{j < n} T(j,k) S(j,n)` and `T(n,k) = 0` for `k > n` (`T_spec`); `T n k : ℤ` + is computed by this recursion, row by row (`trows`). That this really is the transposed inverse + is proved, not assumed: `Tmat_eq` shows that for every `N` the `N × N` truncation of `T` is the + transpose of Mathlib's matrix inverse `(Mmat N)⁻¹` of the `N × N` truncation of `M` (for + upper triangular infinite matrices the inverse is determined by these truncations). + `T_data` checks all `55` listed terms of A144633 (rows `0, …, 9`). +* *The sequence.* `a n = T n 2 : ℤ` (column `2`, offset `0`; the values are signed). + `a_data` checks all `23` listed terms `a(0), …, a(22)`. +* *The quantity.* `y n = (1/18) · 6^n · a(n) / n!` is computed in `ℚ`, literally as written. + `y_data` checks that `y 0, …, y 8` are the coefficients `0, 0, 1, -6, 33, -162, 630, -972, + -14499` of the series `(1/18) A(6x)` displayed in the entry. +* *The conjecture.* "`y(n)` is odd" is read as "`y(n)` is an odd integer": + `∃ m : ℤ, Odd m ∧ y n = m`. The range is all `n ≥ 0` (the offset of the entry), and + "`n = 2^k` for `k >= 1`" is `∃ k, 1 ≤ k ∧ n = 2^k`. The separate observation that every `y(n)` + appears to be an integer is not part of the conjecture and is not included in `statement`. +-/ + +namespace Math0.Statements.A144637 + +open Finset + +/-! ### A144385: partitions of `[k]` into `n` blocks of size `1`, `2` or `3` -/ + +/-- One step of the A144385 recurrence: from row `n` (the list `r` of entries `k = 0, …, 3n`) +build row `n + 1` (entries `k = 0, …, 3n + 3`) by +`T(n+1,k) = T(n,k-1) + (k-1) T(n,k-2) + (1/2)(k-1)(k-2) T(n,k-3)`, terms with a negative index +being `0`. -/ +def nextSRow (r : List ℕ) : List ℕ := + (List.range (r.length + 3)).map fun k => + (if 1 ≤ k then r.getD (k - 1) 0 else 0) + + (if 2 ≤ k then (k - 1) * r.getD (k - 2) 0 else 0) + + (if 3 ≤ k then (k - 1) * (k - 2) / 2 * r.getD (k - 3) 0 else 0) + +/-- Row `n` of A144385 (entries `k = 0, …, 3n`). -/ +def srow : ℕ → List ℕ + | 0 => [1] + | n + 1 => nextSRow (srow n) + +/-- A144385 `T(n,k)`: the number of partitions of `{1, …, k}` into exactly `n` blocks, each of +size `1`, `2` or `3` (computed by the recurrence; see `S_zero`, `S_succ`). It is `0` for +`k > 3n`. -/ +def S (n k : ℕ) : ℕ := (srow n).getD k 0 + +/-- All 70 listed terms of A144385 (rows `0, …, 6`, kernel-checked). -/ +theorem S_data : (List.range 7).map (fun n => (List.range (3 * n + 1)).map (S n)) = + [[1], [0, 1, 1, 1], [0, 0, 1, 3, 7, 10, 10], [0, 0, 0, 1, 6, 25, 75, 175, 280, 280], + [0, 0, 0, 0, 1, 10, 65, 315, 1225, 3780, 9100, 15400, 15400], + [0, 0, 0, 0, 0, 1, 15, 140, 980, 5565, 26145, 102025, 323400, 800800, 1401400, 1401400], + [0, 0, 0, 0, 0, 0, 1, 21, 266, 2520, 19425, 125895, 695695, 3273270, 12962950, 42042000, + 106506400, 190590400, 190590400]] := by + decide +kernel + +theorem srow_length (n : ℕ) : (srow n).length = 3 * n + 1 := by + induction n with + | zero => rfl + | succ n ih => simp [srow, nextSRow, ih]; ring + +/-- Row `0` of A144385: `T(0,0) = 1` and `T(0,k) = 0` for `k > 0`. -/ +theorem S_zero (k : ℕ) : S 0 k = if k = 0 then 1 else 0 := by + rcases k with _ | k + · rfl + · simp [S, srow] + +/-- The A144385 recurrence +`T(n+1,k) = T(n,k-1) + (k-1) T(n,k-2) + (1/2)(k-1)(k-2) T(n,k-3)`, for all `n` and `k` +(terms with a negative index are `0`; `(k-1)(k-2)` is even, so `/ 2` is exact). -/ +theorem S_succ (n k : ℕ) : S (n + 1) k = + (if 1 ≤ k then S n (k - 1) else 0) + + (if 2 ≤ k then (k - 1) * S n (k - 2) else 0) + + (if 3 ≤ k then (k - 1) * (k - 2) / 2 * S n (k - 3) else 0) := by + have hz : ∀ j, 3 * n + 1 ≤ j → S n j = 0 := fun j hj => by + rw [S, List.getD_eq_getElem?_getD, List.getElem?_eq_none (by rw [srow_length]; exact hj)] + rfl + rw [S, srow, nextSRow, List.getD_eq_getElem?_getD, List.getElem?_map] + by_cases hk : k < (srow n).length + 3 + · rw [List.getElem?_range hk, Option.map_some, Option.getD_some] + rfl + · rw [srow_length] at hk + rw [List.getElem?_eq_none (by simp [srow_length]; omega), Option.map_none, Option.getD_none, + if_pos (by omega), if_pos (by omega), if_pos (by omega), hz _ (by omega), hz _ (by omega), + hz _ (by omega)] + simp + +/-- `T(j,n) = 0` for `n < j`: the matrix `M(i,j) = T(i,j)` is upper triangular. -/ +theorem S_eq_zero_of_lt : ∀ {j n : ℕ}, n < j → S j n = 0 := by + intro j + induction j with + | zero => intro n h; omega + | succ j ih => + intro n h + rw [S_succ] + have h1 : 1 ≤ n → S j (n - 1) = 0 := fun _ => ih (by omega) + have h2 : 2 ≤ n → S j (n - 2) = 0 := fun _ => ih (by omega) + have h3 : 3 ≤ n → S j (n - 3) = 0 := fun _ => ih (by omega) + split_ifs <;> simp_all + +/-- `T(n,n) = 1`: the matrix `M(i,j) = T(i,j)` has unit diagonal. -/ +theorem S_self (n : ℕ) : S n n = 1 := by + induction n with + | zero => rfl + | succ n ih => + rw [S_succ, if_pos (by omega), show n + 1 - 1 = n by omega, ih] + have h2 : 2 ≤ n + 1 → S n (n + 1 - 2) = 0 := fun _ => S_eq_zero_of_lt (by omega) + have h3 : 3 ≤ n + 1 → S n (n + 1 - 3) = 0 := fun _ => S_eq_zero_of_lt (by omega) + split_ifs <;> simp_all + +/-! ### A144633: the transposed inverse of the upper triangular matrix of A144385 -/ + +/-- Forward substitution for `R M = 1` (`M(j,n) = S j n`, `R = M⁻¹`, `T(n,k) = R(k,n)`): from +the rows `0, …, n-1` of `T` (`n = rs.length`), row `n` (entries `k = 0, …, n`) is +`T(n,k) = [n = k] - ∑_{j < n} T(j,k) S(j,n)`, which solves `∑_{j ≤ n} R(k,j) M(j,n) = [k = n]` +since `M(n,n) = 1`. -/ +def nextTRow (rs : List (List ℤ)) : List ℤ := + (List.range (rs.length + 1)).map fun k => + (if rs.length = k then 1 else 0) - + ∑ j ∈ range rs.length, (rs.getD j []).getD k 0 * (S j rs.length : ℤ) + +/-- The rows `0, …, n-1` of A144633. -/ +def trows : ℕ → List (List ℤ) + | 0 => [] + | n + 1 => trows n ++ [nextTRow (trows n)] + +/-- A144633 `T(n,k)`: entry `(k,n)` of the inverse of the upper triangular matrix +`M(i,j) = S i j` of A144385 (see `Tmat_eq`); it is `0` for `k > n`. -/ +def T (n k : ℕ) : ℤ := ((trows (n + 1)).getD n []).getD k 0 + +/-- All 55 listed terms of A144633 (rows `0, …, 9`, kernel-checked). -/ +theorem T_data : (List.range 10).map (fun n => (List.range (n + 1)).map (T n)) = + [[1], [0, 1], [0, -1, 1], [0, 2, -3, 1], [0, -5, 11, -6, 1], [0, 10, -45, 35, -10, 1], + [0, 35, 175, -210, 85, -15, 1], [0, -910, -315, 1225, -700, 175, -21, 1], + [0, 11935, -6265, -5670, 5565, -1890, 322, -28, 1], + [0, -134750, 139755, -5005, -39270, 19425, -4410, 546, -36, 1]] := by + decide +kernel + +theorem trows_length (n : ℕ) : (trows n).length = n := by + induction n with + | zero => rfl + | succ n ih => simp [trows, ih] + +theorem trows_getD (n j : ℕ) : + (trows n).getD j [] = if j < n then nextTRow (trows j) else [] := by + induction n with + | zero => simp [trows] + | succ n ih => + rw [trows] + rcases lt_trichotomy j n with h | h | h + · rw [List.getD_append _ _ _ _ (by rw [trows_length]; exact h), ih, if_pos h, + if_pos (by omega)] + · subst h + rw [List.getD_append_right _ _ _ _ (by rw [trows_length]), trows_length, Nat.sub_self, + if_pos (by omega)] + rfl + · rw [List.getD_append_right _ _ _ _ (by rw [trows_length]; omega), trows_length, + if_neg (by omega)] + obtain ⟨d, hd⟩ : ∃ d, j - n = d + 1 := ⟨j - n - 1, by omega⟩ + rw [hd] + rfl + +theorem T_eq (n k : ℕ) : T n k = (nextTRow (trows n)).getD k 0 := by + rw [T, trows_getD, if_pos (Nat.lt_succ_self n)] + +/-- The forward-substitution recursion defining `T`. -/ +theorem T_spec (n k : ℕ) : + T n k = if k ≤ n then + (if n = k then 1 else 0) - ∑ j ∈ range n, T j k * (S j n : ℤ) else 0 := by + rw [T_eq, nextTRow, trows_length, List.getD_eq_getElem?_getD, List.getElem?_map] + by_cases hk : k ≤ n + · rw [List.getElem?_range (by omega), if_pos hk, Option.map_some, Option.getD_some] + congr 1 + refine Finset.sum_congr rfl fun j hj => ?_ + rw [trows_getD, if_pos (Finset.mem_range.mp hj), ← T_eq] + · rw [List.getElem?_eq_none (by simp; omega), if_neg hk] + rfl + +theorem T_eq_zero_of_lt {n k : ℕ} (h : n < k) : T n k = 0 := by + rw [T_spec, if_neg (by omega)] + +/-- Row `k` of `R = Tᵀ` times column `n` of `M` is `[k = n]`. -/ +theorem sum_T_mul_S (k n N : ℕ) (hN : n < N) : + ∑ j ∈ range N, T j k * (S j n : ℤ) = if k = n then 1 else 0 := by + obtain ⟨m, rfl⟩ : ∃ m, N = n + 1 + m := ⟨N - (n + 1), by omega⟩ + rw [Finset.sum_range_add, Finset.sum_eq_zero (s := range m) + (fun x _ => by rw [S_eq_zero_of_lt (by omega), Nat.cast_zero, mul_zero]), add_zero, + Finset.sum_range_succ, S_self, Nat.cast_one, mul_one] + by_cases hk : k ≤ n + · rw [T_spec n k, if_pos hk] + by_cases hnk : n = k + · rw [if_pos hnk, if_pos hnk.symm]; ring + · rw [if_neg hnk, if_neg (Ne.symm hnk)]; ring + · rw [T_eq_zero_of_lt (by omega), if_neg (by omega), add_zero] + exact Finset.sum_eq_zero fun x hx => by + rw [T_eq_zero_of_lt (by have := Finset.mem_range.mp hx; omega), zero_mul] + +/-- The `N × N` truncation of the upper triangular matrix `M(i,j) = S i j` (A144385). -/ +def Mmat (N : ℕ) : Matrix (Fin N) (Fin N) ℤ := Matrix.of fun i j => (S i j : ℤ) + +/-- The `N × N` truncation of the triangle `T` (A144633), `Tmat N n k = T n k`. -/ +def Tmat (N : ℕ) : Matrix (Fin N) (Fin N) ℤ := Matrix.of fun i j => T i j + +open Matrix in +theorem Tmat_transpose_mul_Mmat (N : ℕ) : (Tmat N)ᵀ * Mmat N = 1 := by + ext i j + rw [Matrix.mul_apply, Matrix.one_apply] + simp only [Tmat, Mmat, Matrix.transpose_apply, Matrix.of_apply] + rw [Fin.sum_univ_eq_sum_range (fun x => T x i * (S x j : ℤ)) N, sum_T_mul_S _ _ _ j.isLt] + simp [Fin.ext_iff] + +open Matrix in +/-- A144633 is the transpose of the inverse of the upper triangular matrix of A144385: for every +`N`, `Tmat N = ((Mmat N)⁻¹)ᵀ` (Mathlib's `Matrix.inv`). -/ +theorem Tmat_eq (N : ℕ) : Tmat N = ((Mmat N)⁻¹)ᵀ := by + rw [Matrix.inv_eq_left_inv (Tmat_transpose_mul_Mmat N), Matrix.transpose_transpose] + +/-! ### A144637 -/ + +/-- A144637: column `2` of the triangle A144633, `a(n) = T(n,2)` (offset `0`). -/ +def a (n : ℕ) : ℤ := T n 2 + +/-- The definition reproduces all 23 terms listed in OEIS, `a 0, …, a 22` (kernel-checked). -/ +theorem a_data : (List.range 23).map (fun i => a (i + 0)) = + [0, 0, 1, -3, 11, -45, 175, -315, -6265, 139755, -2127125, 28153125, -327452125, + 2921393475, -2998820825, -788463550875, 28464750689375, -739460838241125, + 16173782241491875, -294957734383186875, 3672958879661946875, 19544468129733421875, + -3601613031568517590625] := by + decide +kernel + +/-- The quantity of the conjecture, `(1/18) · 6^n · a(n) / n!`, as a rational number. -/ +def y (n : ℕ) : ℚ := (1 / 18) * 6 ^ n * (a n : ℚ) / (n.factorial : ℚ) + +/-- `y 0, …, y 8` are the coefficients `0, 0, 1, -6, 33, -162, 630, -972, -14499` of the series +`(1/18) A(6x) = x^2 - 6x^3 + 33x^4 - 162x^5 + 630x^6 - 972x^7 - 14499x^8 + ⋯` displayed in the +entry (kernel-checked). -/ +theorem y_data : (List.range 9).map y = + ([0, 0, 1, -6, 33, -162, 630, -972, -14499] : List ℤ).map (fun z => (z : ℚ)) := by + decide +kernel + +/-- Conjecture (Peter Bala, 2026): for every `n ≥ 0`, `(1/18) · 6^n · a(n) / n!` is odd (i.e. it +is an odd integer) if and only if `n = 2^k` for some `k ≥ 1`. -/ +def statement : Prop := + ∀ n : ℕ, (∃ m : ℤ, Odd m ∧ y n = (m : ℚ)) ↔ ∃ k : ℕ, 1 ≤ k ∧ n = 2 ^ k + +end Math0.Statements.A144637 diff --git a/lean/Math0/Statements/OEIS/A160848.lean b/lean/Math0/Statements/OEIS/A160848.lean new file mode 100644 index 0000000..97bf69f --- /dev/null +++ b/lean/Math0/Statements/OEIS/A160848.lean @@ -0,0 +1,479 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A160848: Barker's order-20 recurrence for the lines through an `8 × n` grid + +Source: https://oeis.org/A160848, _Colin Barker_, Dec 25 2017 (FORMULA section). Verbatim: +> Conjectures from _Colin Barker_, Dec 25 2017: (Start) +> +> G.f.: x*(1 + 66*x + 132*x^2 + 304*x^3 + 492*x^4 + 771*x^5 + 1003*x^6 + 1273*x^7 + 1390*x^8 + +> 1480*x^9 + 1374*x^10 + 1241*x^11 + 971*x^12 + 739*x^13 + 476*x^14 + 296*x^15 + 140*x^16 + +> 74*x^17 + 17*x^18 + 8*x^19 + 8*x^20) / ((1 - x)^3*(1 + x)*(1 - x + x^2)*(1 + x^2)*(1 + x + x^2)* +> (1 + x + x^2 + x^3 + x^4)*(1 + x + x^2 + x^3 + x^4 + x^5 + x^6)). +> +> a(n) = -a(n-2) + a(n-5) + a(n-6) + 2*a(n-7) + a(n-8) + a(n-9) - a(n-11) - a(n-12) - 2*a(n-13) +> - a(n-14) - a(n-15) + a(n-18) + a(n-20) for n>21. +> +> (End) + +The sequence (_Seppo Mustonen_, May 28 2009, offset `0`) is "Number of lines through at least 2 +points of an 8 X n grid of points." + +## Encoding + +* *The grid.* The `8 × n` grid of points is `{0, …, n-1} × {0, …, 7} ⊆ ℤ²` (the transposed grid + `{0, …, 7} × {0, …, n-1}` is congruent to it, so it has the same number of lines). Its points + are numbered `0, …, 8n-1`: the point with number `i` is `pt i = (i / 8, i % 8)`, and this is a + bijection from `{0, …, 8n-1}` onto the grid. For `n = 0` the grid is empty. +* *Lines.* For two distinct points `p ≠ q` of `ℤ²`, a point `r` lies on the line `pq` iff + `Collinear3 p q r`, i.e. `(q - p) × (r - p) = 0`. A line of the plane containing at least two + grid points `p ≠ q` is the line `pq`. Two distinct lines have at most one common point, so such + a line is determined by the set of grid points on it, and conversely. Hence the number of lines + through at least two grid points is the number of distinct sets + `lineThrough n i j = {k < 8n | pt k lies on the line through pt i and pt j}` with `i ≠ j`, + `i, j < 8n`. This is the definition of `a n` (a cardinality of a computable `Finset`). +* *Fast evaluation (proved equal).* Each line is counted once by its two smallest grid points in + the numbering (`IsFirst`, `a_eq_card_firstPairs`; this uses only that two distinct grid points + of a line span it, `collinear_iff`). For `i < j`, the pair `(pt i, pt j)` consists of the two + smallest grid points on its line iff `d = pt j - pt i` is primitive (`gcd = 1`) and + `pt i - d` is not a grid point (`isFirst_iff`). This gives the `O((8n)²)` count `aFast`, and + `a_eq_aFast` proves `a n = aFast n` for every `n`. +* *Data.* `a_data` checks all 41 listed terms `a(0), …, a(40)` in the kernel (via `a_eq_aFast`). + `recurrence_data` checks that these values satisfy the conjectured recurrence for + `22 ≤ n ≤ 40` (a sanity check of the transcription of the recurrence, not a proof). +* *The conjecture.* `statement` is the recurrence, for every `n > 21` exactly as in the entry + (`Recurrence`). The values are taken in `ℤ` because of the negative coefficients; for + `n > 21` every index `n - k` (`k ≤ 20`) is at least `2`, so the natural-number subtractions are + exact. The g.f. conjecture is recorded separately as `statement_gf`: the identity + `A(x) · D(x) = x · N(x)` of formal power series over `ℤ`, where `A(x) = ∑ a(n) xⁿ`, `D` is the + stated denominator and `x · N(x)` the stated numerator; since `D(0) = 1`, this is the same as + `A(x) = x · N(x) / D(x)`. (`D(x) = 1 + x² - x⁵ - x⁶ - 2x⁷ - x⁸ - x⁹ + x¹¹ + x¹² + 2x¹³ + x¹⁴ + + x¹⁵ - x¹⁸ - x²⁰` is the characteristic polynomial of the recurrence, so `statement_gf` is + equivalent to `statement` together with the agreement of the first 22 coefficients.) +-/ + +namespace Math0.Statements.A160848 + +/-! ### The sequence -/ + +/-- The grid point with number `i`: column `i / 8`, row `i % 8`. The numbers `i < 8 * n` give +each point of the `8 × n` grid `{0, …, n-1} × {0, …, 7}` exactly once. -/ +def pt (i : ℕ) : ℤ × ℤ := (((i / 8 : ℕ) : ℤ), ((i % 8 : ℕ) : ℤ)) + +/-- `p`, `q`, `r` are collinear: `(q - p) × (r - p) = 0`. For `p ≠ q` this says that `r` lies on +the line through `p` and `q`. -/ +def Collinear3 (p q r : ℤ × ℤ) : Prop := + (q.1 - p.1) * (r.2 - p.2) = (q.2 - p.2) * (r.1 - p.1) + +instance (p q r : ℤ × ℤ) : Decidable (Collinear3 p q r) := + inferInstanceAs (Decidable (_ = _)) + +/-- The (numbers of the) points of the `8 × n` grid on the line through `pt i` and `pt j`. -/ +def lineThrough (n i j : ℕ) : Finset ℕ := + (Finset.range (8 * n)).filter fun k => Collinear3 (pt i) (pt j) (pt k) + +/-- A160848: the number of lines through at least 2 points of the `8 × n` grid, i.e. the number of +distinct sets of grid points `lineThrough n i j` cut out by the lines through two distinct grid +points `pt i ≠ pt j`. -/ +def a (n : ℕ) : ℕ := + (((Finset.range (8 * n) ×ˢ Finset.range (8 * n)).filter fun ij => ij.1 ≠ ij.2).image + fun ij => lineThrough n ij.1 ij.2).card + +/-! ### Fast evaluation of `a` -/ + +/-- `pt` is injective. -/ +theorem pt_injective {i j : ℕ} (h : pt i = pt j) : i = j := by + simp only [pt, Prod.mk.injEq, Nat.cast_inj] at h + omega + +theorem collinear_left (p q : ℤ × ℤ) : Collinear3 p q p := by + simp [Collinear3] + +theorem collinear_right (p q : ℤ × ℤ) : Collinear3 p q q := by + simp only [Collinear3]; ring + +/-- Two distinct points `u ≠ w` on the line through `p ≠ q` span the same line. -/ +theorem collinear_iff {p q u w r : ℤ × ℤ} (hpq : p ≠ q) (huw : u ≠ w) + (hu : Collinear3 p q u) (hw : Collinear3 p q w) : + Collinear3 u w r ↔ Collinear3 p q r := by + obtain ⟨p1, p2⟩ := p + obtain ⟨q1, q2⟩ := q + obtain ⟨u1, u2⟩ := u + obtain ⟨w1, w2⟩ := w + obtain ⟨r1, r2⟩ := r + simp only [Collinear3, ne_eq, Prod.mk.injEq] at * + have hv : q1 - p1 ≠ 0 ∨ q2 - p2 ≠ 0 := by + by_contra h + push Not at h + exact hpq ⟨by linarith [h.1], by linarith [h.2]⟩ + have hW : w1 - u1 ≠ 0 ∨ w2 - u2 ≠ 0 := by + by_contra h + push Not at h + exact huw ⟨by linarith [h.1], by linarith [h.2]⟩ + have hX : (w1 - u1) * (u2 - p2) - (w2 - u2) * (u1 - p1) = 0 := by + rcases hv with hv | hv + · have e : (q1 - p1) * ((w1 - u1) * (u2 - p2) - (w2 - u2) * (u1 - p1)) = 0 := by + linear_combination (w1 - p1) * hu - (u1 - p1) * hw + exact (mul_eq_zero.mp e).resolve_left hv + · have e : (q2 - p2) * ((w1 - u1) * (u2 - p2) - (w2 - u2) * (u1 - p1)) = 0 := by + linear_combination (w2 - p2) * hu - (u2 - p2) * hw + exact (mul_eq_zero.mp e).resolve_left hv + constructor + · intro h + have hWc : (w1 - u1) * (r2 - p2) - (w2 - u2) * (r1 - p1) = 0 := by + linear_combination h + hX + have e1 : (w1 - u1) * ((q1 - p1) * (r2 - p2) - (q2 - p2) * (r1 - p1)) = 0 := by + linear_combination (q1 - p1) * hWc + (r1 - p1) * (hw - hu) + have e2 : (w2 - u2) * ((q1 - p1) * (r2 - p2) - (q2 - p2) * (r1 - p1)) = 0 := by + linear_combination (q2 - p2) * hWc + (r2 - p2) * (hw - hu) + rcases hW with hW | hW + · linear_combination (mul_eq_zero.mp e1).resolve_left hW + · linear_combination (mul_eq_zero.mp e2).resolve_left hW + · intro h + have e1 : (q1 - p1) * ((w1 - u1) * (r2 - p2) - (w2 - u2) * (r1 - p1)) = 0 := by + linear_combination (w1 - u1) * h - (r1 - p1) * (hw - hu) + have e2 : (q2 - p2) * ((w1 - u1) * (r2 - p2) - (w2 - u2) * (r1 - p1)) = 0 := by + linear_combination (w2 - u2) * h - (r2 - p2) * (hw - hu) + rcases hv with hv | hv + · linear_combination (mul_eq_zero.mp e1).resolve_left hv - hX + · linear_combination (mul_eq_zero.mp e2).resolve_left hv - hX + +/-- `IsFirst i j`: no grid point with a number `k < j` other than `i` lies on the line through +`pt i` and `pt j`. -/ +def IsFirst (i j : ℕ) : Prop := ∀ k < j, k ≠ i → ¬ Collinear3 (pt i) (pt j) (pt k) + +instance (i j : ℕ) : Decidable (IsFirst i j) := by unfold IsFirst; infer_instance + +/-- The pairs `⟨j, i⟩` with `i < j < 8n` such that `pt i`, `pt j` are the two smallest grid +points (in the numbering) on their line. -/ +def firstPairs (n : ℕ) : Finset (Σ _ : ℕ, ℕ) := + (Finset.range (8 * n)).sigma fun j => (Finset.range j).filter fun i => IsFirst i j + +theorem mem_lineThrough {n i j k : ℕ} : + k ∈ lineThrough n i j ↔ k < 8 * n ∧ Collinear3 (pt i) (pt j) (pt k) := by + simp [lineThrough] + +theorem eq_of_mem_of_isFirst {n i j k : ℕ} (hf : IsFirst i j) (hk : k ∈ lineThrough n i j) + (hkj : k < j) : k = i := by + by_contra hki + exact hf k hkj hki (mem_lineThrough.mp hk).2 + +/-- Every line through at least two grid points is counted exactly once by its two smallest grid +points. -/ +theorem a_eq_card_firstPairs (n : ℕ) : a n = (firstPairs n).card := by + unfold a + symm + apply Finset.card_bij (fun x _ => lineThrough n x.2 x.1) + · intro x hx + simp only [firstPairs, Finset.mem_sigma, Finset.mem_range, Finset.mem_filter] at hx + rw [Finset.mem_image] + refine ⟨(x.2, x.1), ?_, rfl⟩ + simp only [Finset.mem_filter, Finset.mem_product, Finset.mem_range] + omega + · rintro ⟨j, i⟩ hx ⟨j', i'⟩ hy hxy + simp only [firstPairs, Finset.mem_sigma, Finset.mem_range, Finset.mem_filter] at hx hy + simp only at hxy + obtain ⟨hj, hi, hf⟩ := hx + obtain ⟨hj', hi', hf'⟩ := hy + have hiS : i ∈ lineThrough n i j := + mem_lineThrough.mpr ⟨by omega, collinear_left _ _⟩ + have hjS : j ∈ lineThrough n i j := + mem_lineThrough.mpr ⟨hj, collinear_right _ _⟩ + have hi'S : i' ∈ lineThrough n i' j' := + mem_lineThrough.mpr ⟨by omega, collinear_left _ _⟩ + have hj'S : j' ∈ lineThrough n i' j' := + mem_lineThrough.mpr ⟨hj', collinear_right _ _⟩ + rw [hxy] at hiS hjS + have hjj : j = j' := by + rcases lt_trichotomy j j' with h | h | h + · have e1 := eq_of_mem_of_isFirst hf' hjS h + have e2 := eq_of_mem_of_isFirst hf' hiS (by omega) + omega + · exact h + · rw [← hxy] at hi'S hj'S + have e1 := eq_of_mem_of_isFirst hf hj'S h + have e2 := eq_of_mem_of_isFirst hf hi'S (by omega) + omega + subst hjj + have := eq_of_mem_of_isFirst hf' hiS hi + subst this + rfl + · intro S hS + simp only [Finset.mem_image, Finset.mem_filter, Finset.mem_product, Finset.mem_range] at hS + obtain ⟨⟨p, q⟩, ⟨⟨hp, hq⟩, hpq⟩, rfl⟩ := hS + simp only at hp hq hpq ⊢ + have hpS : p ∈ lineThrough n p q := mem_lineThrough.mpr ⟨hp, collinear_left _ _⟩ + have hqS : q ∈ lineThrough n p q := mem_lineThrough.mpr ⟨hq, collinear_right _ _⟩ + have hne : (lineThrough n p q).Nonempty := ⟨p, hpS⟩ + set S := lineThrough n p q with hSdef + set i := S.min' hne with hidef + have hiS : i ∈ S := Finset.min'_mem S hne + have hne2 : (S.erase i).Nonempty := by + by_cases hpi : p = i + · exact ⟨q, Finset.mem_erase.mpr ⟨by omega, hqS⟩⟩ + · exact ⟨p, Finset.mem_erase.mpr ⟨hpi, hpS⟩⟩ + set j := (S.erase i).min' hne2 with hjdef + have hjS' : j ∈ S.erase i := Finset.min'_mem _ hne2 + have hjS : j ∈ S := Finset.mem_of_mem_erase hjS' + have hji : j ≠ i := Finset.ne_of_mem_erase hjS' + have hij : i < j := lt_of_le_of_ne (Finset.min'_le S j hjS) (Ne.symm hji) + have hmin : ∀ k ∈ S, k ≠ i → j ≤ k := fun k hk hki => + Finset.min'_le _ k (Finset.mem_erase.mpr ⟨hki, hk⟩) + have hjn : j < 8 * n := (mem_lineThrough.mp hjS).1 + have hL : lineThrough n i j = S := by + ext k + rw [mem_lineThrough, hSdef, mem_lineThrough] + have hpq' : pt p ≠ pt q := fun h => hpq (pt_injective h) + have hij' : pt i ≠ pt j := fun h => hji (pt_injective h).symm + rw [collinear_iff hpq' hij' (mem_lineThrough.mp hiS).2 (mem_lineThrough.mp hjS).2] + refine ⟨⟨j, i⟩, ?_, hL⟩ + simp only [firstPairs, Finset.mem_sigma, Finset.mem_range, Finset.mem_filter] + refine ⟨hjn, hij, ?_⟩ + intro k hkj hki hcol + have hkS : k ∈ S := hL ▸ mem_lineThrough.mpr ⟨by omega, hcol⟩ + have := hmin k hkS hki + omega + +/-- Fast test, for `i < j`, of `IsFirst i j` (`isFirst_iff`): with `d = pt j - pt i`, +`gcd(d) = 1` and `pt i - d` is not a grid point. -/ +def goodF (i j : ℕ) : Bool := + decide (Nat.gcd (j / 8 - i / 8) (j % 8 - i % 8 + (i % 8 - j % 8)) = 1 ∧ + ¬(j / 8 ≤ 2 * (i / 8) ∧ j % 8 ≤ 2 * (i % 8) ∧ 2 * (i % 8) < 8 + j % 8)) + +theorem goodF_iff (i j : ℕ) : goodF i j = true ↔ + (Nat.gcd (j / 8 - i / 8) (j % 8 - i % 8 + (i % 8 - j % 8)) = 1 ∧ + ¬(j / 8 ≤ 2 * (i / 8) ∧ j % 8 ≤ 2 * (i % 8) ∧ 2 * (i % 8) < 8 + j % 8)) := + decide_eq_true_iff + +theorem gcd_eq (i j : ℕ) (hxij : i / 8 ≤ j / 8) : + Nat.gcd (j / 8 - i / 8) (j % 8 - i % 8 + (i % 8 - j % 8)) = + Int.gcd (((j / 8 : ℕ) : ℤ) - ((i / 8 : ℕ) : ℤ)) (((j % 8 : ℕ) : ℤ) - ((i % 8 : ℕ) : ℤ)) := by + rw [Int.gcd_eq_natAbs] + congr 1 <;> omega + +theorem gcd_of_isFirst {i j : ℕ} (hij : i < j) (H : IsFirst i j) : + Int.gcd (((j / 8 : ℕ) : ℤ) - ((i / 8 : ℕ) : ℤ)) + (((j % 8 : ℕ) : ℤ) - ((i % 8 : ℕ) : ℤ)) = 1 := by + have hji : (j : ℤ) - i = 8 * (((j / 8 : ℕ) : ℤ) - ((i / 8 : ℕ) : ℤ)) + + (((j % 8 : ℕ) : ℤ) - ((i % 8 : ℕ) : ℤ)) := by omega + set dx : ℤ := ((j / 8 : ℕ) : ℤ) - ((i / 8 : ℕ) : ℤ) with hdx + set dy : ℤ := ((j % 8 : ℕ) : ℤ) - ((i % 8 : ℕ) : ℤ) with hdy + by_contra hg + have hg0 : Int.gcd dx dy ≠ 0 := by + rw [Ne, Int.gcd_eq_zero_iff] + omega + have hg2 : (2 : ℤ) ≤ (Int.gcd dx dy : ℤ) := by omega + obtain ⟨A, hA⟩ := Int.gcd_dvd_left (a := dx) (b := dy) + obtain ⟨B, hB⟩ := Int.gcd_dvd_right (a := dx) (b := dy) + set g : ℤ := (Int.gcd dx dy : ℤ) with hgdef + have hdx0 : 0 ≤ dx := by omega + have hf : g * (8 * A + B) = (j : ℤ) - i := by rw [hji, hA, hB]; ring + have hpos : 0 < g * (8 * A + B) := by omega + have h8 : 0 < 8 * A + B := pos_of_mul_pos_right hpos (by omega) + have hA0 : 0 ≤ A := nonneg_of_mul_nonneg_right (hA ▸ hdx0) (by omega) + have hlt : 8 * A + B < g * (8 * A + B) := by + have := mul_le_mul_of_nonneg_right hg2 h8.le + linarith + have hy1 : ((j % 8 : ℕ) : ℤ) < 8 := by omega + have hy2 : ((i % 8 : ℕ) : ℤ) < 8 := by omega + have hyb : 0 ≤ ((i % 8 : ℕ) : ℤ) + B ∧ ((i % 8 : ℕ) : ℤ) + B < 8 := by + rcases le_or_gt 0 B with hB0 | hB0 + · have := mul_le_mul_of_nonneg_right (show (1 : ℤ) ≤ g by omega) hB0 + constructor + · omega + · linarith + · have := mul_le_mul_of_nonpos_right (show (1 : ℤ) ≤ g by omega) hB0.le + constructor + · linarith + · omega + set k : ℕ := ((i : ℤ) + 8 * A + B).toNat with hk + apply H k (by omega) (by omega) + simp only [Collinear3, pt] + have hk1 : ((k / 8 : ℕ) : ℤ) = ((i / 8 : ℕ) : ℤ) + A := by omega + have hk2 : ((k % 8 : ℕ) : ℤ) = ((i % 8 : ℕ) : ℤ) + B := by omega + rw [hk1, hk2, ← hdx, ← hdy, hA, hB] + ring + +theorem back_of_isFirst {i j : ℕ} (hij : i < j) (H : IsFirst i j) : + ¬(j / 8 ≤ 2 * (i / 8) ∧ j % 8 ≤ 2 * (i % 8) ∧ 2 * (i % 8) < 8 + j % 8) := by + rintro ⟨h1, h2, h3⟩ + apply H (2 * i - j) (by omega) (by omega) + simp only [Collinear3, pt] + have hk1 : (((2 * i - j) / 8 : ℕ) : ℤ) = 2 * ((i / 8 : ℕ) : ℤ) - ((j / 8 : ℕ) : ℤ) := by + omega + have hk2 : (((2 * i - j) % 8 : ℕ) : ℤ) = 2 * ((i % 8 : ℕ) : ℤ) - ((j % 8 : ℕ) : ℤ) := by + omega + rw [hk1, hk2] + ring + +theorem isFirst_of {i j : ℕ} (hij : i < j) + (hg : Int.gcd (((j / 8 : ℕ) : ℤ) - ((i / 8 : ℕ) : ℤ)) + (((j % 8 : ℕ) : ℤ) - ((i % 8 : ℕ) : ℤ)) = 1) + (hback : ¬(j / 8 ≤ 2 * (i / 8) ∧ j % 8 ≤ 2 * (i % 8) ∧ 2 * (i % 8) < 8 + j % 8)) : + IsFirst i j := by + intro k hkj hki hcol + simp only [Collinear3, pt] at hcol + have hji : (j : ℤ) - i = 8 * (((j / 8 : ℕ) : ℤ) - ((i / 8 : ℕ) : ℤ)) + + (((j % 8 : ℕ) : ℤ) - ((i % 8 : ℕ) : ℤ)) := by omega + have hki0 : (k : ℤ) - i = 8 * (((k / 8 : ℕ) : ℤ) - ((i / 8 : ℕ) : ℤ)) + + (((k % 8 : ℕ) : ℤ) - ((i % 8 : ℕ) : ℤ)) := by omega + have hxk : (0 : ℤ) ≤ ((k / 8 : ℕ) : ℤ) := by positivity + have hyk0 : (0 : ℤ) ≤ ((k % 8 : ℕ) : ℤ) := by positivity + have hyk : ((k % 8 : ℕ) : ℤ) < 8 := by omega + have hyi : ((i % 8 : ℕ) : ℤ) < 8 := by omega + have hxij : i / 8 ≤ j / 8 := Nat.div_le_div_right hij.le + set dx : ℤ := ((j / 8 : ℕ) : ℤ) - ((i / 8 : ℕ) : ℤ) with hdx + set dy : ℤ := ((j % 8 : ℕ) : ℤ) - ((i % 8 : ℕ) : ℤ) with hdy + set ex : ℤ := ((k / 8 : ℕ) : ℤ) - ((i / 8 : ℕ) : ℤ) with hex + set ey : ℤ := ((k % 8 : ℕ) : ℤ) - ((i % 8 : ℕ) : ℤ) with hey + have hb := Int.gcd_eq_gcd_ab dx dy + rw [hg, Nat.cast_one] at hb + set u := Int.gcdA dx dy + set v := Int.gcdB dx dy + set t := ex * u + ey * v with ht + have htx : ex = t * dx := by linear_combination ex * hb - v * hcol + have hty : ey = t * dy := by linear_combination ey * hb + u * hcol + have hki' : (k : ℤ) - i = t * ((j : ℤ) - i) := by + rw [hji, hki0, htx, hty] + ring + have hpos : (0 : ℤ) < j - i := by omega + have ht1 : t < 1 := by + by_contra h + push Not at h + have := mul_le_mul_of_nonneg_right h hpos.le + have : (k : ℤ) - i ≥ (j : ℤ) - i := by rw [hki']; linarith + omega + have ht0 : t ≠ 0 := by + rintro h0 + rw [h0, zero_mul] at hki' + omega + have htm : t ≤ -1 := by omega + have hdx0 : 0 ≤ dx := by omega + apply hback + have hc1 : dx ≤ ((i / 8 : ℕ) : ℤ) := by + have := mul_le_mul_of_nonneg_right htm hdx0 + linarith + have hc2 : dy ≤ ((i % 8 : ℕ) : ℤ) ∧ ((i % 8 : ℕ) : ℤ) - dy < 8 := by + rcases le_or_gt 0 dy with h0 | h0 + · have := mul_le_mul_of_nonneg_right htm h0 + constructor + · linarith + · omega + · have := mul_le_mul_of_nonpos_right htm h0.le + constructor + · omega + · linarith + omega + +/-- For `i < j`, `pt i` and `pt j` are the two smallest grid points of their line iff +`goodF i j`. -/ +theorem isFirst_iff {i j : ℕ} (hij : i < j) : + IsFirst i j ↔ goodF i j = true := by + have hxij : i / 8 ≤ j / 8 := Nat.div_le_div_right hij.le + rw [goodF_iff, gcd_eq i j hxij] + exact ⟨fun H => ⟨gcd_of_isFirst hij H, back_of_isFirst hij H⟩, + fun ⟨hg, hb⟩ => isFirst_of hij hg hb⟩ + +/-- `countI j m` is the number of `i < m` with `goodF i j` (`countI_eq`). -/ +def countI (j m : ℕ) : ℕ := + Nat.rec (motive := fun _ => ℕ) 0 (fun i r => cond (goodF i j) (r + 1) r) m + +/-- `countJ m = ∑_{j < m} countI j j` (`countJ_eq`). -/ +def countJ (m : ℕ) : ℕ := + Nat.rec (motive := fun _ => ℕ) 0 (fun j r => r + countI j j) m + +/-- Fast evaluation of `a` (`a_eq_aFast`). -/ +def aFast (n : ℕ) : ℕ := countJ (8 * n) + +theorem countI_eq (j m : ℕ) : + countI j m = ((Finset.range m).filter fun i => goodF i j = true).card := by + induction m with + | zero => simp [countI] + | succ m ih => + show cond (goodF m j) (countI j m + 1) (countI j m) = _ + rw [Finset.range_add_one, Finset.filter_insert, ih] + cases h : goodF m j + · simp + · simp + +theorem countJ_eq (m : ℕ) : countJ m = ∑ j ∈ Finset.range m, countI j j := by + induction m with + | zero => simp [countJ] + | succ m ih => + show countJ m + countI m m = _ + rw [Finset.sum_range_succ, ih] + +theorem a_eq_aFast (n : ℕ) : a n = aFast n := by + rw [a_eq_card_firstPairs, firstPairs, Finset.card_sigma, aFast, countJ_eq] + refine Finset.sum_congr rfl fun j _ => ?_ + rw [countI_eq] + congr 1 + refine Finset.filter_congr fun i hi => ?_ + exact isFirst_iff (Finset.mem_range.mp hi) + +/-! ### Data -/ + +set_option maxRecDepth 100000 in +/-- The definition reproduces the 41 terms `a(0), …, a(40)` listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 41).map a = + [0, 1, 66, 131, 238, 361, 534, 709, 938, 1183, 1470, 1759, 2104, 2459, 2870, 3287, 3740, 4209, + 4734, 5261, 5844, 6437, 7070, 7711, 8408, 9115, 9872, 10637, 11444, 12265, 13142, 14015, + 14944, 15889, 16876, 17871, 18914, 19967, 21076, 22193, 23352] := by + rw [show a = aFast from funext a_eq_aFast] + decide +kernel + +/-- The listed terms `a(0), …, a(40)`. -/ +def listed : List ℕ := + [0, 1, 66, 131, 238, 361, 534, 709, 938, 1183, 1470, 1759, 2104, 2459, 2870, 3287, 3740, 4209, + 4734, 5261, 5844, 6437, 7070, 7711, 8408, 9115, 9872, 10637, 11444, 12265, 13142, 14015, + 14944, 15889, 16876, 17871, 18914, 19967, 21076, 22193, 23352] + +theorem a_eq_listed {n : ℕ} (hn : n < 41) : a n = listed.getD n 0 := by + have := congrArg (fun l => l.getD n 0) a_data + simpa [listed, List.getD_eq_getElem?_getD, List.getElem?_map, List.getElem?_range hn] using this + +/-! ### The conjecture -/ + +/-- Barker's recurrence at index `n` for a sequence `f`: +`f(n) = -f(n-2) + f(n-5) + f(n-6) + 2f(n-7) + f(n-8) + f(n-9) - f(n-11) - f(n-12) - 2f(n-13) +- f(n-14) - f(n-15) + f(n-18) + f(n-20)`. -/ +def Recurrence (f : ℕ → ℤ) (n : ℕ) : Prop := + f n = -f (n - 2) + f (n - 5) + f (n - 6) + 2 * f (n - 7) + f (n - 8) + f (n - 9) + - f (n - 11) - f (n - 12) - 2 * f (n - 13) - f (n - 14) - f (n - 15) + f (n - 18) + f (n - 20) + +instance (f : ℕ → ℤ) (n : ℕ) : Decidable (Recurrence f n) := + inferInstanceAs (Decidable (_ = _)) + +/-- Sanity check (not a proof of the conjecture): the listed terms satisfy the recurrence for +`22 ≤ n ≤ 40`. -/ +theorem recurrence_data (n : ℕ) (h1 : 21 < n) (h2 : n ≤ 40) : + Recurrence (fun m => (a m : ℤ)) n := by + have key : ∀ m < 41, 21 < m → Recurrence (fun m => (listed.getD m 0 : ℤ)) m := by + decide +kernel + unfold Recurrence at * + simp (disch := omega) only [a_eq_listed] + exact key n (by omega) h1 + +/-- Barker's conjecture (recurrence form): for all `n > 21`, +`a(n) = -a(n-2) + a(n-5) + a(n-6) + 2a(n-7) + a(n-8) + a(n-9) - a(n-11) - a(n-12) - 2a(n-13) +- a(n-14) - a(n-15) + a(n-18) + a(n-20)`. -/ +def statement : Prop := + ∀ n : ℕ, 21 < n → Recurrence (fun m => (a m : ℤ)) n + +open PowerSeries in +/-- Barker's conjecture (g.f. form), as an identity of formal power series over `ℤ`: +`(∑ a(n) xⁿ) · (1 - x)³(1 + x)(1 - x + x²)(1 + x²)(1 + x + x²)(1 + x + ⋯ + x⁴)(1 + x + ⋯ + x⁶) += x(1 + 66x + ⋯ + 8x²⁰)`. -/ +def statement_gf : Prop := + PowerSeries.mk (fun n => (a n : ℤ)) * + ((1 - X) ^ 3 * (1 + X) * (1 - X + X ^ 2) * (1 + X ^ 2) * (1 + X + X ^ 2) * + (1 + X + X ^ 2 + X ^ 3 + X ^ 4) * (1 + X + X ^ 2 + X ^ 3 + X ^ 4 + X ^ 5 + X ^ 6)) = + X * (1 + 66 * X + 132 * X ^ 2 + 304 * X ^ 3 + 492 * X ^ 4 + 771 * X ^ 5 + 1003 * X ^ 6 + + 1273 * X ^ 7 + 1390 * X ^ 8 + 1480 * X ^ 9 + 1374 * X ^ 10 + 1241 * X ^ 11 + 971 * X ^ 12 + + 739 * X ^ 13 + 476 * X ^ 14 + 296 * X ^ 15 + 140 * X ^ 16 + 74 * X ^ 17 + 17 * X ^ 18 + + 8 * X ^ 19 + 8 * X ^ 20) + +end Math0.Statements.A160848 diff --git a/lean/Math0/Statements/OEIS/A172164.lean b/lean/Math0/Statements/OEIS/A172164.lean new file mode 100644 index 0000000..0070c74 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A172164.lean @@ -0,0 +1,753 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A172164: second differences of the turns of the spiral of Theodorus + +Source: https://oeis.org/A172164, Sébastien Dumortier, Jan 27 2010 (COMMENTS section). +Verbatim: +> Conjecture : The terms are only 18,19,20,21 (From the first thousand turns, there are 2,3% of +> 18, 36,5% of 19, 46,2% of 20 and 15% of 21). No period found. Probably due to Pi transcendence. + +The entry's name: "Differences between numbers of triangles entirely contained in two consecutive +turns of Pythagoras's snail (Theodorus spiral)." Offset `2`; data `20, 19, 20, 19, 20, 21, 18, 21, +19, 20, …` (69 terms). Example: "In the first turn, 16 triangles are complete. In the 2nd turn, +there are 36 triangles completely included. The difference is 20." + +## Encoding + +* *The spiral.* Pythagoras's snail (A137515) starts with the isosceles right triangle with legs + `1, 1`; each next right triangle has as legs the previous hypotenuse and a side of length `1`. + So triangle `i` (`i ≥ 1`) has legs `√i`, `1` and hypotenuse `√(i+1)`, and its angle at the + centre is `arctan (1 / √i)`. The triangles are laid side by side around the centre, starting + from a fixed ray (the first leg of length `1`), so triangle `i` occupies the angular sector + `[S (i-1), S i]`, where `S k = ∑_{i=1}^{k} arctan (1 / √i)` is the total angle of the first + `k` triangles (`S 0 = 0`). This is the formula of A072895 ("least k such that + Sum_{i=1..k} arctan(1/sqrt(i)) > 2n*Pi"). +* *Turns.* The `n`-th turn (`n ≥ 1`) is the range of angles `[2π(n-1), 2πn]`. Triangle `i` is + *entirely contained* in turn `n` iff `2π(n-1) ≤ S (i-1)` and `S i ≤ 2πn` + (`turnTriangles n`). The bounds are taken closed; the strict and non-strict versions agree on + every turn checked below, since there `S` never hits a multiple of `2π`. +* `c n = (turnTriangles n).ncard` is the number of triangles entirely contained in turn `n`. + The set is finite for every `n` (`turnTriangles_finite`, from `S k ≥ (5/6) √k`), so `c n` is + a true count. +* The sequence: `a n = c n - c (n - 1)` for `n ≥ 2` (offset `2`), computed in `ℤ` (the + difference of two counts, so that no truncated subtraction is involved). `a 0`, `a 1` are not + terms of the sequence. +* *The conjecture* (`statement`): for every `n ≥ 2`, `a n ∈ {18, 19, 20, 21}`. The percentages + and the remarks "No period found. Probably due to Pi transcendence." are observations, not part + of the formalized claim. + +## Data check + +`a` is not computable (it is defined through real numbers), so the data are proved as follows. +Write `K n` for the number of triangles in the first `n` turns, i.e. the largest `k` with +`S k ≤ 2πn` (this is A137515; `Kseq` lists `K 1, …, K 70`, and its first 42 entries are the 42 +listed terms of A137515, `Kseq_A137515`). The theorem `crossing` proves +`S (K n) < 2πn < S (K n + 1)` for `n = 1, …, 70`. From this, `turnTriangles 1 = [1, K 1]` and +`turnTriangles n = [K (n-1) + 2, K n]` for `n ≥ 2` (triangle `K (n-1) + 1` straddles the ray at +angle `2π(n-1)`). Hence `c 1 = K 1 = 16`, `c n = K n - K (n-1) - 1`, `c 2 = 36` (the entry's +example), and `a_data` checks all 69 listed terms `a 2, …, a 70` against the real definition. +(Equivalently `a n = L n - 2 L (n-1) + L (n-2)` with `L n = K n + 1` = A072895(n) and `L 0 = 0`, +the entry's formula "The second forward difference of A072895".) + +`crossing` is a rigorous, kernel-checked interval computation (`check_targets`, about half a minute +of kernel time). With `S (k+1) = π/4 + R k`, where `R k = ∑_{j=2}^{k+1} arctan (1/√j)`, each term +is enclosed using the alternating Maclaurin series of `arctan` (`Real.hasSum_arctan`, with +partial sums bracketing the limit, `arctan_alt_bounds`): for `x = 1/√j`, +`arctan x = x ∑ (-1)^m j^(-m) / (2m+1)`. `x` is enclosed by integers `qlo/2^50 ≤ x ≤ qhi/2^50` +(checked by `qlo² j ≤ 2^100 ≤ qhi² j`), and every series term is rounded down or up to an +integer multiple of `2^-50` (`term_lower`, `term_upper`). The sums run through +`j ≤ K 70 + 1 = 48836`, and they are compared with `2πn - π/4` using +`3.14159265358979323846 < π < 3.14159265358979323847` (`Real.pi_gt_d20`, `Real.pi_lt_d20`). +The accumulated width of the enclosure is about `10⁻⁷`; the smallest gap between `2πn` and the +`S k` for `n ≤ 70` is about `2·10⁻⁵` (at `n = 53`). Soundness of the computation +(`walkK_spec`, `checkK_sound`) is proved for every input, so the kernel only evaluates +arithmetic. +-/ + +namespace Math0.Statements.A172164 + +open Real Finset Filter Topology + +/-! ### The definitions -/ + +/-- `S k = ∑_{i=1}^{k} arctan (1 / √i)`: the total angle at the centre of the first `k` +triangles of the spiral of Theodorus (triangle `i` has legs `√i` and `1`). -/ +noncomputable def S (k : ℕ) : ℝ := ∑ i ∈ range k, arctan (1 / √((i : ℝ) + 1)) + +/-- The triangles entirely contained in the `n`-th turn: triangle `i ≥ 1` occupies the angular +sector `[S (i-1), S i]`, and the `n`-th turn is `[2π(n-1), 2πn]`. -/ +def turnTriangles (n : ℕ) : Set ℕ := + {i | 1 ≤ i ∧ 2 * π * ((n : ℝ) - 1) ≤ S (i - 1) ∧ S i ≤ 2 * π * n} + +/-- The number of triangles entirely contained in the `n`-th turn of Pythagoras's snail. -/ +noncomputable def c (n : ℕ) : ℕ := (turnTriangles n).ncard + +/-- A172164 (offset `2`): the difference between the numbers of triangles entirely contained in +the turns `n` and `n - 1`. -/ +noncomputable def a (n : ℕ) : ℤ := (c n : ℤ) - c (n - 1) + +/-! ### Bounds on `arctan` from its alternating Maclaurin series -/ + +/-- For `0 ≤ x < 1`, the partial sums of `∑ (-1)^i x^(2i+1)/(2i+1)` with an even (resp. odd) +number of terms are lower (resp. upper) bounds for `arctan x`. -/ +theorem arctan_alt_bounds {x : ℝ} (hx0 : 0 ≤ x) (hx1 : x < 1) (k : ℕ) : + ∑ i ∈ range (2 * k), (-1) ^ i * (x ^ (2 * i + 1) / ((2 * i + 1 : ℕ) : ℝ)) ≤ arctan x ∧ + arctan x ≤ ∑ i ∈ range (2 * k + 1), (-1) ^ i * (x ^ (2 * i + 1) / ((2 * i + 1 : ℕ) : ℝ)) := by + have hs := Real.hasSum_arctan (x := x) (by rw [Real.norm_eq_abs, abs_of_nonneg hx0]; exact hx1) + have ht : Tendsto (fun n => ∑ i ∈ range n, (-1) ^ i * (x ^ (2 * i + 1) / ((2 * i + 1 : ℕ) : ℝ))) + atTop (𝓝 (arctan x)) := by + have := hs.tendsto_sum_nat + simpa only [mul_div_assoc] using this + have hf : Antitone (fun i : ℕ => x ^ (2 * i + 1) / ((2 * i + 1 : ℕ) : ℝ)) := by + refine antitone_nat_of_succ_le fun i => ?_ + have h1 : x ^ (2 * (i + 1) + 1) ≤ x ^ (2 * i + 1) := + pow_le_pow_of_le_one hx0 hx1.le (by omega) + have h2 : ((2 * i + 1 : ℕ) : ℝ) ≤ ((2 * (i + 1) + 1 : ℕ) : ℝ) := by + exact_mod_cast (by omega : 2 * i + 1 ≤ 2 * (i + 1) + 1) + have h3 : (0 : ℝ) < ((2 * i + 1 : ℕ) : ℝ) := by positivity + exact div_le_div₀ (by positivity) h1 h3 h2 + exact ⟨hf.alternating_series_le_tendsto ht k, hf.tendsto_le_alternating_series ht k⟩ + +/-- `serA j r = ∑_{i simp [serA, serB] + | succ r ih => + rw [show 2 * (r + 1) = 2 * r + 1 + 1 by ring, sum_range_succ, sum_range_succ, ih, serA_succ, + serB_succ] + have e1 : x ^ (2 * (2 * r) + 1) = x * j⁻¹ ^ (2 * r) := by + rw [pow_succ, pow_mul, hx]; ring + have e2 : x ^ (2 * (2 * r + 1) + 1) = x * j⁻¹ ^ (2 * r + 1) := by + rw [pow_succ, pow_mul, hx]; ring + have c1 : ((2 * (2 * r) + 1 : ℕ) : ℝ) = 4 * r + 1 := by push_cast; ring + have c2 : ((2 * (2 * r + 1) + 1 : ℕ) : ℝ) = 4 * r + 3 := by push_cast; ring + have s1 : (-1 : ℝ) ^ (2 * r) = 1 := by rw [pow_mul]; norm_num + have s2 : (-1 : ℝ) ^ (2 * r + 1) = -1 := by rw [pow_succ, s1]; norm_num + rw [e1, e2, c1, c2, s1, s2] + ring + +theorem alt_sum_odd {x j : ℝ} (hx : x ^ 2 = j⁻¹) (r : ℕ) : + ∑ i ∈ range (2 * r + 1), (-1) ^ i * (x ^ (2 * i + 1) / ((2 * i + 1 : ℕ) : ℝ)) = + x * (serA j (r + 1) - serB j r) := by + rw [sum_range_succ, alt_sum_even hx r, serA_succ] + have e1 : x ^ (2 * (2 * r) + 1) = x * j⁻¹ ^ (2 * r) := by + rw [pow_succ, pow_mul, hx]; ring + have c1 : ((2 * (2 * r) + 1 : ℕ) : ℝ) = 4 * r + 1 := by push_cast; ring + have s1 : (-1 : ℝ) ^ (2 * r) = 1 := by rw [pow_mul]; norm_num + rw [e1, c1, s1] + ring + +theorem serA_sub_serB_nonneg {j : ℝ} (hj : 1 ≤ j) (r : ℕ) : 0 ≤ serA j r - serB j r := by + rw [serA, serB, ← sum_sub_distrib] + refine sum_nonneg fun i _ => ?_ + rw [sub_nonneg] + have hj0 : 0 < j⁻¹ := by positivity + have hj1 : j⁻¹ ≤ 1 := inv_le_one_of_one_le₀ hj + have h1 : j⁻¹ ^ (2 * i + 1) ≤ j⁻¹ ^ (2 * i) := pow_le_pow_of_le_one hj0.le hj1 (by omega) + have h2 : (4 * (i : ℝ) + 1) ≤ 4 * i + 3 := by linarith + exact div_le_div₀ (by positivity) h1 (by positivity) h2 + +theorem serA_le_serA_succ {j : ℝ} (hj : 0 < j) (r : ℕ) : serA j r ≤ serA j (r + 1) := by + rw [serA_succ] + have : 0 ≤ j⁻¹ ^ (2 * r) / (4 * r + 1) := by positivity + linarith + +/-! ### Rounding to integers -/ + +/-- `sumPos q j r = ∑_{i ℕ) 0 + (fun i ih => Nat.add ih + (Nat.div q (Nat.mul (Nat.add (Nat.mul 4 i) 1) (Nat.pow j (Nat.mul 2 i))))) + +/-- `sumNeg q j r = ∑_{i ℕ) 0 + (fun i ih => Nat.add ih + (Nat.div q (Nat.mul (Nat.add (Nat.mul 4 i) 3) (Nat.pow j (Nat.add (Nat.mul 2 i) 1))))) + +theorem sumPos_succ (q j r : ℕ) : + sumPos q j (r + 1) = sumPos q j r + q / ((4 * r + 1) * j ^ (2 * r)) := rfl + +theorem sumNeg_succ (q j r : ℕ) : + sumNeg q j (r + 1) = sumNeg q j r + q / ((4 * r + 3) * j ^ (2 * r + 1)) := rfl + +theorem cast_div_le_add_one (m n : ℕ) (hn : 0 < n) : (m : ℝ) / n ≤ ((m / n : ℕ) : ℝ) + 1 := by + have h := Nat.lt_mul_div_succ m hn + have hn' : (0 : ℝ) < n := by exact_mod_cast hn + rw [div_le_iff₀ hn'] + have : (m : ℝ) < n * (((m / n : ℕ) : ℝ) + 1) := by exact_mod_cast h + linarith + +theorem sumPos_bounds (q j r : ℕ) (hj : 0 < j) : + (sumPos q j r : ℝ) ≤ q * serA j r ∧ (q : ℝ) * serA j r ≤ sumPos q j r + r := by + induction r with + | zero => simp [sumPos, serA] + | succ r ih => + rw [sumPos_succ, serA_succ] + set N := (4 * r + 1) * j ^ (2 * r) with hN + have hN0 : 0 < N := by positivity + have hj0 : (j : ℝ) ≠ 0 := by positivity + have e : (q : ℝ) * ((j : ℝ)⁻¹ ^ (2 * r) / (4 * r + 1)) = (q : ℝ) / (N : ℝ) := by + rw [hN, inv_pow]; push_cast; field_simp + have h1 : ((q / N : ℕ) : ℝ) ≤ (q : ℝ) / N := Nat.cast_div_le + have h2 := cast_div_le_add_one q N hN0 + rw [Nat.cast_add, mul_add, e, Nat.cast_succ] + constructor + · linarith [ih.1] + · linarith [ih.2] + +theorem sumNeg_bounds (q j r : ℕ) (hj : 0 < j) : + (sumNeg q j r : ℝ) ≤ q * serB j r ∧ (q : ℝ) * serB j r ≤ sumNeg q j r + r := by + induction r with + | zero => simp [sumNeg, serB] + | succ r ih => + rw [sumNeg_succ, serB_succ] + set N := (4 * r + 3) * j ^ (2 * r + 1) with hN + have hN0 : 0 < N := by positivity + have hj0 : (j : ℝ) ≠ 0 := by positivity + have e : (q : ℝ) * ((j : ℝ)⁻¹ ^ (2 * r + 1) / (4 * r + 3)) = (q : ℝ) / (N : ℝ) := by + rw [hN, inv_pow]; push_cast; field_simp + have h1 : ((q / N : ℕ) : ℝ) ≤ (q : ℝ) / N := Nat.cast_div_le + have h2 := cast_div_le_add_one q N hN0 + rw [Nat.cast_add, mul_add, e, Nat.cast_succ] + constructor + · linarith [ih.1] + · linarith [ih.2] + +/-! ### Enclosing one term `arctan (1 / √j)` -/ + +/-- The scale `2^50` of the fixed-point computation. -/ +def scale : ℕ := 1125899906842624 + +theorem scale_eq : scale = 2 ^ 50 := by norm_num [scale] + +/-- `scale2 = scale * scale = 2^100`. -/ +def scale2 : ℕ := 1267650600228229401496703205376 + +theorem scale2_eq : scale2 = scale * scale := by norm_num [scale2, scale] + +theorem inv_sqrt_facts (j : ℕ) (hj : 2 ≤ j) : + 0 ≤ 1 / √(j : ℝ) ∧ 1 / √(j : ℝ) < 1 ∧ (1 / √(j : ℝ)) ^ 2 = (j : ℝ)⁻¹ := by + have hj0 : (0 : ℝ) < j := by positivity + refine ⟨by positivity, ?_, ?_⟩ + · rw [div_lt_one (Real.sqrt_pos.2 hj0), Real.lt_sqrt (by norm_num)] + have : (2 : ℝ) ≤ j := by exact_mod_cast hj + linarith + · rw [div_pow, Real.sq_sqrt hj0.le, one_pow, one_div] + +/-- Lower bound: if `ql² j ≤ scale²` then +`sumPos ql j r - sumNeg ql j r - r ≤ scale · arctan (1/√j)`. -/ +theorem term_lower (j : ℕ) (hj : 2 ≤ j) (r ql : ℕ) (hql : ql * ql * j ≤ scale * scale) : + (sumPos ql j r : ℝ) - (sumNeg ql j r + r) ≤ scale * arctan (1 / √(j : ℝ)) := by + obtain ⟨hx0, hx1, hx2⟩ := inv_sqrt_facts j hj + set x := 1 / √(j : ℝ) with hx + have hj0 : (0 : ℝ) < j := by positivity + have hj1 : (1 : ℝ) ≤ j := by exact_mod_cast (by omega : 1 ≤ j) + have hD : (0 : ℝ) ≤ scale := by positivity + have hlo : (ql : ℝ) ≤ scale * x := by + have h : (ql : ℝ) * ql * j ≤ scale * scale := by exact_mod_cast hql + have hsq : (ql : ℝ) ^ 2 ≤ (scale * x) ^ 2 := by + rw [mul_pow, hx2, le_mul_inv_iff₀ hj0] + nlinarith [h] + exact (pow_le_pow_iff_left₀ (by positivity) (by positivity) two_ne_zero).1 hsq + have hl := (arctan_alt_bounds hx0 hx1 r).1 + rw [alt_sum_even hx2] at hl + have hAB := serA_sub_serB_nonneg hj1 r + obtain ⟨p1, -⟩ := sumPos_bounds ql j r (by omega) + obtain ⟨-, n2⟩ := sumNeg_bounds ql j r (by omega) + have k1 : (ql : ℝ) * (serA j r - serB j r) ≤ scale * x * (serA j r - serB j r) := + mul_le_mul_of_nonneg_right hlo hAB + have k2 : (scale : ℝ) * (x * (serA j r - serB j r)) ≤ scale * arctan x := + mul_le_mul_of_nonneg_left hl hD + nlinarith [k1, k2, p1, n2] + +/-- Upper bound: if `scale² ≤ qh² j` then +`scale · arctan (1/√j) ≤ sumPos qh j (r+1) + (r+1) - sumNeg qh j r`. -/ +theorem term_upper (j : ℕ) (hj : 2 ≤ j) (r qh : ℕ) (hqh : scale * scale ≤ qh * qh * j) : + scale * arctan (1 / √(j : ℝ)) ≤ (sumPos qh j (r + 1) : ℝ) + ((r : ℝ) + 1) - sumNeg qh j r := by + obtain ⟨hx0, hx1, hx2⟩ := inv_sqrt_facts j hj + set x := 1 / √(j : ℝ) with hx + have hj0 : (0 : ℝ) < j := by positivity + have hj1 : (1 : ℝ) ≤ j := by exact_mod_cast (by omega : 1 ≤ j) + have hD : (0 : ℝ) ≤ scale := by positivity + have hhi : (scale : ℝ) * x ≤ qh := by + have h : (scale : ℝ) * scale ≤ qh * qh * j := by exact_mod_cast hqh + have hsq : (scale * x) ^ 2 ≤ (qh : ℝ) ^ 2 := by + rw [mul_pow, hx2, mul_inv_le_iff₀ hj0] + nlinarith [h] + exact (pow_le_pow_iff_left₀ (by positivity) (by positivity) two_ne_zero).1 hsq + have hu := (arctan_alt_bounds hx0 hx1 r).2 + rw [alt_sum_odd hx2] at hu + have hAB : 0 ≤ serA j (r + 1) - serB j r := by + have := serA_sub_serB_nonneg hj1 r + have := serA_le_serA_succ hj0 r + linarith + obtain ⟨-, p2⟩ := sumPos_bounds qh j (r + 1) (by omega) + obtain ⟨n1, -⟩ := sumNeg_bounds qh j r (by omega) + have k1 : (scale : ℝ) * x * (serA j (r + 1) - serB j r) ≤ qh * (serA j (r + 1) - serB j r) := + mul_le_mul_of_nonneg_right hhi hAB + have k2 : (scale : ℝ) * arctan x ≤ scale * (x * (serA j (r + 1) - serB j r)) := + mul_le_mul_of_nonneg_left hu hD + push_cast at p2 + nlinarith [k1, k2, p2, n1] + +/-! ### The angle sums -/ + +/-- `R k = ∑_{j=2}^{k+1} arctan (1 / √j)`, so that `S (k + 1) = π/4 + R k`. -/ +noncomputable def R (k : ℕ) : ℝ := ∑ i ∈ range k, arctan (1 / √(((i + 2 : ℕ) : ℝ))) + +theorem R_succ (k : ℕ) : R (k + 1) = R k + arctan (1 / √(((k + 2 : ℕ) : ℝ))) := by + rw [R, R, sum_range_succ] + +theorem S_succ_eq_R (k : ℕ) : S (k + 1) = π / 4 + R k := by + rw [S, sum_range_succ', R, add_comm] + congr 1 + · simp + · refine sum_congr rfl fun i _ => ?_ + congr 3 + push_cast + ring + +theorem S_succ (k : ℕ) : S (k + 1) = S k + arctan (1 / √((k : ℝ) + 1)) := by + rw [S, S, sum_range_succ] + +theorem S_strictMono : StrictMono S := strictMono_nat_of_lt_succ fun k => by + rw [S_succ] + have : 0 < arctan (1 / √((k : ℝ) + 1)) := arctan_pos.2 (by positivity) + linarith + +theorem S_zero : S 0 = 0 := by simp [S] + +theorem S_nonneg (k : ℕ) : 0 ≤ S k := S_zero ▸ S_strictMono.monotone (Nat.zero_le k) + +/-! ### Kernel-friendly evaluation -/ + +/-- `x && y`, written with the recursor. -/ +def andK (x y : Bool) : Bool := Bool.rec (motive := fun _ => Bool) false y x + +theorem lt_of_blt {x y : ℕ} (h : Nat.blt x y = true) : x < y := by + simpa [Nat.blt_eq] using h + +theorem andK_eq_true (x y : Bool) : andK x y = true ↔ x = true ∧ y = true := by + cases x <;> cases y <;> decide + +/-- Newton's iteration for `⌊√n⌋` started at `x`, stopping once it no longer decreases, with at +most `fuel` steps. (Only its speed matters: `qloOf` and `qhiOf` check their results.) -/ +def isqrtK (n : ℕ) : ℕ → ℕ → ℕ := + Nat.rec (motive := fun _ => ℕ → ℕ) (fun x => x) + (fun _ ih x => Bool.rec (motive := fun _ => ℕ) (ih (Nat.div (Nat.add x (Nat.div n x)) 2)) x + (Nat.ble x (Nat.div (Nat.add x (Nat.div n x)) 2))) + +/-- `s` if `s² j ≤ scale²` (so `s / scale ≤ 1/√j`), else `0`. -/ +def qloOf (j s : ℕ) : ℕ := + Bool.rec (motive := fun _ => ℕ) 0 s (Nat.ble (Nat.mul (Nat.mul s s) j) scale2) + +/-- `s + 1` if `scale² ≤ (s+1)² j` (so `1/√j ≤ (s+1) / scale`), else `scale`. -/ +def qhiOf (j s : ℕ) : ℕ := + Bool.rec (motive := fun _ => ℕ) scale (Nat.succ s) + (Nat.ble scale2 (Nat.mul (Nat.mul (Nat.succ s) (Nat.succ s)) j)) + +theorem qloOf_spec (j s : ℕ) : qloOf j s * qloOf j s * j ≤ scale * scale := by + unfold qloOf + cases h : Nat.ble (Nat.mul (Nat.mul s s) j) scale2 with + | false => show 0 * 0 * j ≤ scale * scale; simp + | true => + show s * s * j ≤ scale * scale + rw [← scale2_eq] + exact Nat.le_of_ble_eq_true h + +theorem qhiOf_spec (j s : ℕ) (hj : 1 ≤ j) : scale * scale ≤ qhiOf j s * qhiOf j s * j := by + unfold qhiOf + cases h : Nat.ble scale2 (Nat.mul (Nat.mul (Nat.succ s) (Nat.succ s)) j) with + | false => show scale * scale ≤ scale * scale * j; exact Nat.le_mul_of_pos_right _ hj + | true => + show scale * scale ≤ (s + 1) * (s + 1) * j + rw [← scale2_eq] + exact Nat.le_of_ble_eq_true h + +/-- Number of series terms: starting from `r` and `p`, add `1` to `r` and multiply `p` by `j⁴` +until `e ≤ p` (at most `fuel` times). -/ +def cntK (j e : ℕ) : ℕ → ℕ → ℕ → ℕ := + Nat.rec (motive := fun _ => ℕ → ℕ → ℕ) (fun r _ => r) + (fun _ ih r p => Bool.rec (motive := fun _ => ℕ) (ih (Nat.succ r) (Nat.mul p (Nat.pow j 4))) r + (Nat.ble e p)) + +/-- `2^66`. -/ +def e66 : ℕ := 73786976294838206464 + +/-- Number of pairs of series terms used for the lower bound at `j` (`j^(4r+1) ≥ 2^66`). -/ +def rl (j : ℕ) : ℕ := cntK j e66 40 1 (Nat.pow j 5) + +/-- Number of pairs of series terms used for the upper bound at `j` (`j^(4r+3) ≥ 2^66`). -/ +def ru (j : ℕ) : ℕ := cntK j e66 40 0 (Nat.pow j 3) + +/-- One step of `walkK`: add the bounds for the term `j`, computed from `s ≈ scale/√j`, to the +running sums, and continue with `k`. -/ +def stepK (j s a b c d : ℕ) (k : ℕ → ℕ → ℕ → ℕ → ℕ → ℕ → ℕ × ℕ × ℕ × ℕ × ℕ) : + ℕ × ℕ × ℕ × ℕ × ℕ := + k (Nat.succ j) s (Nat.add a (sumPos (qloOf j s) j (rl j))) + (Nat.add b (Nat.add (sumNeg (qloOf j s) j (rl j)) (rl j))) + (Nat.add c (Nat.add (sumPos (qhiOf j s) j (Nat.succ (ru j))) (Nat.succ (ru j)))) + (Nat.add d (sumNeg (qhiOf j s) j (ru j))) + +/-- `walkK len j g a b c d` processes the terms `j, j+1, …, j+len-1`, starting from the +square-root guess `g` and the running sums `a, b, c, d`; it returns the last guess and the +four sums. -/ +def walkK : ℕ → ℕ → ℕ → ℕ → ℕ → ℕ → ℕ → ℕ × ℕ × ℕ × ℕ × ℕ := + Nat.rec (motive := fun _ => ℕ → ℕ → ℕ → ℕ → ℕ → ℕ → ℕ × ℕ × ℕ × ℕ × ℕ) + (fun _ g a b c d => (g, a, b, c, d)) + (fun _ ih j g a b c d => stepK j (isqrtK (Nat.div scale2 j) 64 g) a b c d ih) + +theorem walkK_zero (j g a b c d : ℕ) : walkK 0 j g a b c d = (g, a, b, c, d) := rfl + +theorem walkK_succ (len j g a b c d : ℕ) : walkK (len + 1) j g a b c d = + walkK len (j + 1) (isqrtK (scale2 / j) 64 g) + (a + sumPos (qloOf j (isqrtK (scale2 / j) 64 g)) j (rl j)) + (b + (sumNeg (qloOf j (isqrtK (scale2 / j) 64 g)) j (rl j) + rl j)) + (c + (sumPos (qhiOf j (isqrtK (scale2 / j) 64 g)) j (ru j + 1) + (ru j + 1))) + (d + sumNeg (qhiOf j (isqrtK (scale2 / j) 64 g)) j (ru j)) := rfl + +/-- `Inv k a b c d`: the running sums enclose `scale · R k`. -/ +def Inv (k a b c d : ℕ) : Prop := (a : ℝ) - b ≤ scale * R k ∧ scale * R k ≤ (c : ℝ) - d + +theorem Inv_zero : Inv 0 0 0 0 0 := by simp [Inv, R] + +theorem Inv_step (j s a b c d : ℕ) (hj : 2 ≤ j) (h : Inv (j - 2) a b c d) : + Inv (j - 1) (a + sumPos (qloOf j s) j (rl j)) (b + (sumNeg (qloOf j s) j (rl j) + rl j)) + (c + (sumPos (qhiOf j s) j (ru j + 1) + (ru j + 1))) (d + sumNeg (qhiOf j s) j (ru j)) := by + have hk : j - 1 = (j - 2) + 1 := by omega + have hj2 : j - 2 + 2 = j := by omega + rw [Inv, hk, R_succ, hj2] + have hl := term_lower j hj (rl j) (qloOf j s) (qloOf_spec j s) + have hu := term_upper j hj (ru j) (qhiOf j s) (qhiOf_spec j s (by omega)) + obtain ⟨h1, h2⟩ := h + push_cast + constructor <;> linarith + +theorem walkK_spec (len : ℕ) : ∀ (j g a b c d : ℕ), 2 ≤ j → Inv (j - 2) a b c d → + Inv (j - 2 + len) (walkK len j g a b c d).2.1 (walkK len j g a b c d).2.2.1 + (walkK len j g a b c d).2.2.2.1 (walkK len j g a b c d).2.2.2.2 := by + induction len with + | zero => intro j g a b c d _ h; simpa [walkK_zero] using h + | succ len ih => + intro j g a b c d hj h + rw [walkK_succ] + have key := Inv_step j (isqrtK (scale2 / j) 64 g) a b c d hj h + rw [show j - 1 = j + 1 - 2 by omega] at key + have := ih (j + 1) (isqrtK (scale2 / j) 64 g) _ _ _ _ (by omega) key + rwa [show j + 1 - 2 + len = j - 2 + (len + 1) by omega] at this + +/-- The numerator of the lower bound `3.14159265358979323846` for `π`. -/ +def piLo : ℕ := 314159265358979323846 + +/-- The numerator of the upper bound `3.14159265358979323847` for `π`. -/ +def piHi : ℕ := 314159265358979323847 + +/-- `10^20`. -/ +def e20 : ℕ := 100000000000000000000 + +theorem piLo_lt : (piLo : ℝ) / e20 < π := by + have := Real.pi_gt_d20 + norm_num [piLo, e20] at this ⊢ + linarith + +theorem pi_lt_piHi : π < (piHi : ℝ) / e20 := by + have := Real.pi_lt_d20 + norm_num [piHi, e20] at this ⊢ + linarith + +/-- `4 c 10^20 < piLo (8n - 1) scale + 4 d 10^20`: then `(c - d)/scale < π (8n-1)/4`. -/ +def hiOK (n c d : ℕ) : Bool := + Nat.blt (Nat.mul (Nat.mul 4 c) e20) + (Nat.add (Nat.mul (Nat.mul piLo (Nat.sub (Nat.mul 8 n) 1)) scale) (Nat.mul (Nat.mul 4 d) e20)) + +/-- `piHi (8n - 1) scale + 4 b 10^20 < 4 a 10^20`: then `π (8n-1)/4 < (a - b)/scale`. -/ +def loOK (n a b : ℕ) : Bool := + Nat.blt (Nat.add (Nat.mul (Nat.mul piHi (Nat.sub (Nat.mul 8 n) 1)) scale) + (Nat.mul (Nat.mul 4 b) e20)) (Nat.mul (Nat.mul 4 a) e20) + +theorem S_lt_of_hiOK {n K c d : ℕ} (hn : 1 ≤ n) (hK : 1 ≤ K) (hinv : scale * R (K - 1) ≤ (c : ℝ) - d) + (h : hiOK n c d = true) : S K < 2 * π * n := by + have h' : 4 * c * e20 < piLo * (8 * n - 1) * scale + 4 * d * e20 := lt_of_blt h + have h8 : ((8 * n - 1 : ℕ) : ℝ) = 8 * n - 1 := by + rw [Nat.cast_sub (by omega)]; push_cast; ring + have hr : (4 : ℝ) * c * e20 < piLo * (8 * n - 1) * scale + 4 * d * e20 := by + rw [← h8]; exact_mod_cast h' + have hpi := piLo_lt + have hn' : (0 : ℝ) < 8 * n - 1 := by + have : (1 : ℝ) ≤ n := by exact_mod_cast hn + linarith + have hm : (piLo : ℝ) / e20 * (8 * n - 1) < π * (8 * n - 1) := mul_lt_mul_of_pos_right hpi hn' + have hS : S K = π / 4 + R (K - 1) := by + rw [← S_succ_eq_R, Nat.sub_add_cancel hK] + rw [hS] + have he : (0 : ℝ) < e20 := by norm_num [e20] + have hs : (0 : ℝ) < scale := by norm_num [scale] + rw [div_mul_eq_mul_div, div_lt_iff₀ he] at hm + -- `4 e20 scale R ≤ 4 e20 (c - d) < piLo (8n-1) scale < π (8n-1) e20 scale` + have k1 : (4 : ℝ) * e20 * (scale * R (K - 1)) ≤ 4 * e20 * ((c : ℝ) - d) := + mul_le_mul_of_nonneg_left hinv (by positivity) + have k2 : (piLo : ℝ) * (8 * n - 1) * scale < π * (8 * n - 1) * e20 * scale := + mul_lt_mul_of_pos_right hm hs + have k3 : (4 : ℝ) * R (K - 1) * (e20 * scale) < π * (8 * n - 1) * (e20 * scale) := by + nlinarith [k1, k2, hr] + have k4 : (4 : ℝ) * R (K - 1) < π * (8 * n - 1) := lt_of_mul_lt_mul_right k3 (by positivity) + nlinarith [k4] + +theorem lt_S_of_loOK {n K a b : ℕ} (hn : 1 ≤ n) (hinv : (a : ℝ) - b ≤ scale * R K) + (h : loOK n a b = true) : 2 * π * n < S (K + 1) := by + have h' : piHi * (8 * n - 1) * scale + 4 * b * e20 < 4 * a * e20 := lt_of_blt h + have h8 : ((8 * n - 1 : ℕ) : ℝ) = 8 * n - 1 := by + rw [Nat.cast_sub (by omega)]; push_cast; ring + have hr : (piHi : ℝ) * (8 * n - 1) * scale + 4 * b * e20 < 4 * a * e20 := by + rw [← h8]; exact_mod_cast h' + have hpi := pi_lt_piHi + have hn' : (0 : ℝ) < 8 * n - 1 := by + have : (1 : ℝ) ≤ n := by exact_mod_cast hn + linarith + have hm : π * (8 * n - 1) < (piHi : ℝ) / e20 * (8 * n - 1) := mul_lt_mul_of_pos_right hpi hn' + rw [S_succ_eq_R] + have he : (0 : ℝ) < e20 := by norm_num [e20] + have hs : (0 : ℝ) < scale := by norm_num [scale] + rw [div_mul_eq_mul_div, lt_div_iff₀ he] at hm + have k1 : (4 : ℝ) * e20 * ((a : ℝ) - b) ≤ 4 * e20 * (scale * R K) := + mul_le_mul_of_nonneg_left hinv (by positivity) + have k2 : π * (8 * n - 1) * e20 * scale < (piHi : ℝ) * (8 * n - 1) * scale := + mul_lt_mul_of_pos_right hm hs + have k3 : π * (8 * n - 1) * (e20 * scale) < (4 : ℝ) * R K * (e20 * scale) := by + nlinarith [k1, k2, hr] + have k4 : π * (8 * n - 1) < (4 : ℝ) * R K := lt_of_mul_lt_mul_right k3 (by positivity) + nlinarith [k4] + +/-- Second half of a check step: the lower test at `K` (sums `w` enclose `scale · R K`), then the +rest of the list. -/ +def check2 (n K : ℕ) (w : ℕ × ℕ × ℕ × ℕ × ℕ) (ih : ℕ → ℕ → ℕ → ℕ → ℕ → ℕ → Bool) : Bool := + andK (loOK n w.2.1 w.2.2.1) (ih K w.1 w.2.1 w.2.2.1 w.2.2.2.1 w.2.2.2.2) + +/-- First half of a check step: the upper test at `K - 1` (sums `w` enclose +`scale · R (K - 1)`), then one more term. -/ +def check1 (n K : ℕ) (w : ℕ × ℕ × ℕ × ℕ × ℕ) (ih : ℕ → ℕ → ℕ → ℕ → ℕ → ℕ → Bool) : Bool := + andK (hiOK n w.2.2.2.1 w.2.2.2.2) + (check2 n K (walkK 1 (Nat.succ K) w.1 w.2.1 w.2.2.1 w.2.2.2.1 w.2.2.2.2) ih) + +/-- `checkK l cur g a b c d`: for each `(n, K)` in `l` (in increasing order of `K`), certify +`S K < 2πn < S (K + 1)`, given running sums `a, b, c, d` enclosing `scale · R cur`. -/ +def checkK : List (ℕ × ℕ) → ℕ → ℕ → ℕ → ℕ → ℕ → ℕ → Bool := + List.rec (motive := fun _ => ℕ → ℕ → ℕ → ℕ → ℕ → ℕ → Bool) (fun _ _ _ _ _ _ => true) + (fun p _ ih cur g a b c d => + andK (Nat.blt cur p.2) (andK (Nat.ble 1 p.1) + (check1 p.1 p.2 (walkK (Nat.sub (Nat.sub p.2 1) cur) (Nat.add cur 2) g a b c d) ih))) + +theorem checkK_sound (l : List (ℕ × ℕ)) : ∀ (cur g a b c d : ℕ), Inv cur a b c d → + checkK l cur g a b c d = true → ∀ p ∈ l, S p.2 < 2 * π * p.1 ∧ 2 * π * p.1 < S (p.2 + 1) := by + induction l with + | nil => intro _ _ _ _ _ _ _ _ p hp; simp at hp + | cons q l ih => + intro cur g a b c d hinv h p hp + obtain ⟨n, K⟩ := q + have h0 : andK (Nat.blt cur K) (andK (Nat.ble 1 n) + (check1 n K (walkK (K - 1 - cur) (cur + 2) g a b c d) + (fun cur g a b c d => checkK l cur g a b c d))) = true := h + simp only [andK_eq_true, check1, check2] at h0 + obtain ⟨hcur, hn, hhi, hlo, hrest⟩ := h0 + have hcur' : cur < K := lt_of_blt hcur + have hn' : 1 ≤ n := Nat.le_of_ble_eq_true hn + set w := walkK (K - 1 - cur) (cur + 2) g a b c d with hw + have hw1 := walkK_spec (K - 1 - cur) (cur + 2) g a b c d (by omega) + (by rwa [show cur + 2 - 2 = cur by omega]) + rw [← hw, show cur + 2 - 2 + (K - 1 - cur) = K - 1 by omega] at hw1 + set w' := walkK 1 (K + 1) w.1 w.2.1 w.2.2.1 w.2.2.2.1 w.2.2.2.2 with hw' + have hw2 := walkK_spec 1 (K + 1) w.1 w.2.1 w.2.2.1 w.2.2.2.1 w.2.2.2.2 (by omega) + (by rwa [show K + 1 - 2 = K - 1 by omega]) + rw [← hw', show K + 1 - 2 + 1 = K by omega] at hw2 + rcases List.mem_cons.1 hp with rfl | hp + · exact ⟨S_lt_of_hiOK hn' (by omega) hw1.2 hhi, lt_S_of_loOK hn' hw2.1 hlo⟩ + · exact ih K w'.1 w'.2.1 w'.2.2.1 w'.2.2.2.1 w'.2.2.2.2 hw2 hrest p hp + +/-! ### The turn boundaries `K n` for `n ≤ 70` -/ + +/-- `K 1, …, K 70`: `K n` is the number of triangles in the first `n` turns (A137515). -/ +def Kseq : List ℕ := + [16, 53, 109, 185, 280, 395, 531, 685, 860, 1054, 1268, 1502, 1756, 2029, 2322, 2635, 2967, + 3319, 3691, 4083, 4494, 4926, 5376, 5847, 6337, 6848, 7377, 7927, 8496, 9086, 9694, 10323, + 10971, 11639, 12327, 13035, 13762, 14509, 15276, 16062, 16868, 17694, 18540, 19405, 20290, + 21195, 22120, 23064, 24029, 25012, 26016, 27039, 28082, 29145, 30228, 31330, 32452, 33594, + 34756, 35937, 37138, 38359, 39599, 40859, 42139, 43439, 44758, 46098, 47456, 48835] + +/-- The first 42 entries of `Kseq` are the 42 listed terms of A137515. -/ +theorem Kseq_A137515 : Kseq.take 42 = [16, 53, 109, 185, 280, 395, 531, 685, 860, 1054, 1268, + 1502, 1756, 2029, 2322, 2635, 2967, 3319, 3691, 4083, 4494, 4926, 5376, 5847, 6337, 6848, 7377, + 7927, 8496, 9086, 9694, 10323, 10971, 11639, 12327, 13035, 13762, 14509, 15276, 16062, 16868, + 17694] := by decide + +/-- `K n` for `1 ≤ n ≤ 70`. -/ +def Kof (n : ℕ) : ℕ := Kseq.getD (n - 1) 0 + +/-- The pairs `(n, K n)`, `n = 1, …, 70`. -/ +def targets : List (ℕ × ℕ) := (List.range 70).map fun i => (i + 1, Kof (i + 1)) + +/-- The interval computation succeeds (kernel-checked). -/ +theorem check_targets : checkK targets 0 scale 0 0 0 0 = true := by decide +kernel + +/-- `S (K n) < 2πn < S (K n + 1)` for `n = 1, …, 70`. -/ +theorem crossing (n : ℕ) (h1 : 1 ≤ n) (h2 : n ≤ 70) : + S (Kof n) < 2 * π * n ∧ 2 * π * n < S (Kof n + 1) := by + have hmem : (n, Kof n) ∈ targets := by + refine List.mem_map.2 ⟨n - 1, List.mem_range.2 (by omega), ?_⟩ + rw [Nat.sub_add_cancel h1] + exact checkK_sound targets 0 scale 0 0 0 0 Inv_zero check_targets (n, Kof n) hmem + +/-! ### Counting the triangles of a turn -/ + +theorem S_le_iff {θ : ℝ} {K : ℕ} (h1 : S K < θ) (h2 : θ < S (K + 1)) (i : ℕ) : + S i ≤ θ ↔ i ≤ K := by + constructor + · intro h + by_contra hi + have := S_strictMono.monotone (show K + 1 ≤ i by omega) + linarith + · intro hi + have := S_strictMono.monotone hi + linarith + +theorem S_lt_iff {θ : ℝ} {K : ℕ} (h1 : S K < θ) (h2 : θ < S (K + 1)) (i : ℕ) : + S i < θ ↔ i ≤ K := by + constructor + · intro h + by_contra hi + have := S_strictMono.monotone (show K + 1 ≤ i by omega) + linarith + · intro hi + have := S_strictMono.monotone hi + linarith + +theorem turnTriangles_one {K : ℕ} (h1 : S K < 2 * π * (1 : ℕ)) (h2 : 2 * π * (1 : ℕ) < S (K + 1)) : + turnTriangles 1 = Set.Icc 1 K := by + ext i + simp only [turnTriangles, Set.mem_ofPred_eq, Set.mem_Icc] + rw [S_le_iff h1 h2] + have := S_nonneg (i - 1) + constructor + · rintro ⟨h, -, h'⟩; exact ⟨h, h'⟩ + · rintro ⟨h, h'⟩; exact ⟨h, by push_cast; linarith, h'⟩ + +theorem turnTriangles_eq {n K K' : ℕ} (hn : 2 ≤ n) + (h1 : S K < 2 * π * n) (h2 : 2 * π * n < S (K + 1)) + (h1' : S K' < 2 * π * (n - 1 : ℕ)) (h2' : 2 * π * (n - 1 : ℕ) < S (K' + 1)) : + turnTriangles n = Set.Icc (K' + 2) K := by + have hc : ((n - 1 : ℕ) : ℝ) = (n : ℝ) - 1 := by rw [Nat.cast_sub (by omega), Nat.cast_one] + rw [hc] at h1' h2' + ext i + have key : 2 * π * ((n : ℝ) - 1) ≤ S (i - 1) ↔ K' + 1 ≤ i - 1 := by + rw [← not_lt, S_lt_iff h1' h2'] + omega + simp only [turnTriangles, Set.mem_ofPred_eq, Set.mem_Icc] + rw [key, S_le_iff h1 h2] + omega + +theorem ncard_Icc_nat (a b : ℕ) : (Set.Icc a b).ncard = b + 1 - a := by + rw [← Finset.coe_Icc, Set.ncard_coe_finset, Nat.card_Icc] + +/-- The numbers of complete triangles in the turns `1, …, 70`, from `Kseq`. -/ +def cK (n : ℕ) : ℕ := if n = 1 then Kof 1 else Kof n - Kof (n - 1) - 1 + +theorem c_eq (n : ℕ) (h1 : 1 ≤ n) (h2 : n ≤ 70) : c n = cK n := by + obtain ⟨hA, hB⟩ := crossing n h1 h2 + rcases Nat.eq_or_lt_of_le h1 with rfl | hn + · rw [c, turnTriangles_one hA hB, ncard_Icc_nat, cK, if_pos rfl] + rfl + · obtain ⟨hA', hB'⟩ := crossing (n - 1) (by omega) (by omega) + rw [c, turnTriangles_eq hn hA hB hA' hB', ncard_Icc_nat, cK, if_neg (by omega)] + omega + +/-- The entry's example: 16 triangles are complete in the first turn and 36 in the second. -/ +theorem c_one_two : c 1 = 16 ∧ c 2 = 36 := by + rw [c_eq 1 le_rfl (by norm_num), c_eq 2 (by norm_num) (by norm_num)] + decide + +/-- The definition reproduces all 69 terms listed in OEIS, `a 2, …, a 70` (kernel-checked +interval computation `check_targets`). -/ +theorem a_data : (List.range 69).map (fun i => a (i + 2)) = + [20, 19, 20, 19, 20, 21, 18, 21, 19, 20, 20, 20, 19, 20, 20, 19, 20, 20, 20, 19, 21, 18, 21, + 19, 21, 18, 21, 19, 21, 18, 21, 19, 20, 20, 20, 19, 20, 20, 19, 20, 20, 20, 19, 20, 20, 20, + 19, 21, 18, 21, 19, 20, 20, 20, 19, 20, 20, 20, 19, 20, 20, 19, 20, 20, 20, 19, 21, 18, + 21] := by + have h : ∀ i ∈ List.range 69, a (i + 2) = ((cK (i + 2) : ℤ) - cK (i + 1)) := by + intro i hi + rw [List.mem_range] at hi + rw [a, c_eq (i + 2) (by omega) (by omega), show i + 2 - 1 = i + 1 by omega, + c_eq (i + 1) (by omega) (by omega)] + rw [List.map_congr_left h] + decide +kernel + +/-! ### `c n` is a genuine count -/ + +theorem S_ge (k : ℕ) (hk : 2 ≤ k) : (5 / 6 : ℝ) * √(k : ℝ) ≤ S k := by + obtain ⟨hx0, hx1, hx2⟩ := inv_sqrt_facts k hk + have hk0 : (0 : ℝ) < k := by positivity + have hk2 : (2 : ℝ) ≤ k := by exact_mod_cast hk + -- each term is at least `arctan (1/√k)` + have h1 : (k : ℝ) * arctan (1 / √(k : ℝ)) ≤ S k := by + have : ∑ _i ∈ range k, arctan (1 / √(k : ℝ)) ≤ S k := by + refine sum_le_sum fun i hi => ?_ + rw [mem_range] at hi + refine arctan_strictMono.monotone ?_ + have hi' : (i : ℝ) + 1 ≤ k := by exact_mod_cast hi + exact one_div_le_one_div_of_le (by positivity) (Real.sqrt_le_sqrt hi') + simpa using this + -- `arctan x ≥ x (1 - 1/(3k)) ≥ (5/6) x` + set x := 1 / √(k : ℝ) with hx + have h2 := (arctan_alt_bounds hx0 hx1 1).1 + rw [alt_sum_even hx2] at h2 + have hA : serA (k : ℝ) 1 = 1 := by simp [serA] + have hB : serB (k : ℝ) 1 = (k : ℝ)⁻¹ / 3 := by simp [serB] + rw [hA, hB] at h2 + have hkinv : (k : ℝ)⁻¹ ≤ 1 / 2 := by rw [inv_le_comm₀ hk0 (by norm_num)]; linarith + have h3 : (5 / 6 : ℝ) * x ≤ arctan x := by nlinarith [mul_le_mul_of_nonneg_left hkinv hx0] + have h4 : (k : ℝ) * x = √(k : ℝ) := by + rw [hx, mul_one_div, Real.div_sqrt] + nlinarith [h1, h3, h4, hk0] + +theorem turnTriangles_finite (n : ℕ) : (turnTriangles n).Finite := by + refine (Set.finite_Iio (81 * n ^ 2 + 2)).subset fun i hi => ?_ + obtain ⟨-, -, hi⟩ := hi + simp only [Set.mem_Iio] + by_contra hlt + have hi2 : 2 ≤ i := by omega + have h1 := S_ge i hi2 + have hpi := Real.pi_lt_d2 + have hn : (0 : ℝ) ≤ n := by positivity + have h2 : √(i : ℝ) ≤ 9 * n := by nlinarith [Real.sqrt_nonneg (i : ℝ)] + have h3 : (i : ℝ) ≤ (9 * n) ^ 2 := by + rw [← Real.sq_sqrt (Nat.cast_nonneg i)] + exact pow_le_pow_left₀ (Real.sqrt_nonneg _) h2 2 + have h4 : (i : ℝ) < 81 * n ^ 2 + 2 := by nlinarith + have : i < 81 * n ^ 2 + 2 := by exact_mod_cast h4 + omega + +/-! ### The conjecture -/ + +/-- The conjecture of A172164: every term `a n` (`n ≥ 2`) is one of `18, 19, 20, 21`. -/ +def statement : Prop := ∀ n : ℕ, 2 ≤ n → a n = 18 ∨ a n = 19 ∨ a n = 20 ∨ a n = 21 + +end Math0.Statements.A172164 diff --git a/lean/Math0/Statements/OEIS/A175385.lean b/lean/Math0/Statements/OEIS/A175385.lean new file mode 100644 index 0000000..4db2cf7 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A175385.lean @@ -0,0 +1,51 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A175385: `∑_{i=1..n} C(2n-i-1, i-1)/i` is never an integer for `n > 1` + +Source: https://oeis.org/A175385, _Vladimir Shevelev_, _Zak Seidov_, Apr 24 2010. Verbatim +(COMMENTS section): +> We conjecture that Sum_{i=1..n} ((1/i)*C(2n-i-1,i-1)) is not an integer for n>1. + +The sequence (offset `1`) is "a(n) = numerator of Sum_{i=1..n} binomial(2n-i-1,i-1)/i." +(the denominators are A175386). + +## Encoding + +* `S n : ℚ` is the sum `∑_{i=1}^{n} C(2n-i-1, i-1)/i`, computed exactly in `ℚ` with Mathlib's + `Nat.choose`. For `1 ≤ i ≤ n` the natural-number subtractions `2n-i-1` and `i-1` are never + truncated (`2n-i-1 ≥ n-1 ≥ 0`), so this is literally the entry's sum. For `n = 0` the sum is + empty; that value is outside the sequence and never used. +* `a n` is the numerator of `S n` in lowest terms (`Rat.num`, as a natural number via + `Int.natAbs`; `S n > 0` for `n ≥ 1`). It uses the OEIS offset `1` and reproduces all 27 + listed terms (`a_data`). +* "Is not an integer" is read as: there is no integer `k` with `S n = k` in `ℚ`. The range + "for n>1" is `n ≥ 2` over the natural numbers. +-/ + +namespace Math0.Statements.A175385 + +/-- The sum `∑_{i=1}^{n} C(2n-i-1, i-1)/i`, computed exactly in `ℚ`. -/ +def S (n : ℕ) : ℚ := + ∑ i ∈ Finset.Icc 1 n, ((Nat.choose (2 * n - i - 1) (i - 1) : ℕ) : ℚ) / (i : ℚ) + +/-- A175385 (offset `1`): the numerator, in lowest terms, of +`∑_{i=1..n} binomial(2n-i-1, i-1)/i`. -/ +def a (n : ℕ) : ℕ := (S n).num.natAbs + +/-- The definition reproduces all 27 terms listed in OEIS, `a 1, …, a 27` (kernel-checked). -/ +theorem a_data : (List.range 27).map (fun i => a (i + 1)) = + [1, 3, 17, 23, 61, 107, 421, 1103, 5777, 7563, 19801, 103681, 135721, 355323, 1860497, + 2435423, 6376021, 11128427, 43701901, 114413063, 599074577, 784198803, 2053059121, + 10749957121, 14071876561, 36840651123, 192900153617] := by + decide +kernel + +/-- Conjecture (Shevelev and Seidov, A175385): for every `n > 1`, the sum +`∑_{i=1..n} C(2n-i-1, i-1)/i` is not an integer. -/ +def statement : Prop := + ∀ n : ℕ, 1 < n → ¬ ∃ k : ℤ, S n = (k : ℚ) + +end Math0.Statements.A175385 diff --git a/lean/Math0/Statements/OEIS/A176206.lean b/lean/Math0/Statements/OEIS/A176206.lean new file mode 100644 index 0000000..3f2b203 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A176206.lean @@ -0,0 +1,228 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A176206: divisors of the row terms versus the parts of the partitions of `n` + +Source: https://oeis.org/A176206, _Omar E. Pol_, Nov 23 2020 (COMMENTS section). Verbatim: +> Conjecture: all divisors of all terms in row n are also all parts of all partitions of n. + +The entry (_Alford Arnold_, Apr 11 2010; new name, offset and terms by _Omar E. Pol_, +Nov 22 2020; keyword `tabf`, offset `1`) is "Irregular triangle T(n,k) (n >= 1, k >= 1) read by +rows: row n has length A000070(n-1) and every column k gives the positive integers." Its comments +make this explicit: "Row n contains a decreasing sequence where n-k is repeated A000041(k) times, +k = 0..n-1", which is also the Mathematica program +`Table[Flatten[Table[ConstantArray[n-k,PartitionsP[k]],{k,0,n-1}]],{n,10}]`. + +## Encoding + +* `p k` is the partition number A000041(k), defined as the number of `Nat.Partition k` + (multisets of positive integers summing to `k`). It is not kernel-friendly, so we also define a + structurally recursive count `pb n m` of the partitions of `n` with all parts `≤ m` and prove + `p k = pb k k` (`p_eq_pb`); this is only used to evaluate the data. +* `row n` is row `n` of the triangle: `n, n-1, …, 1`, where `n - k` is repeated `p k` times, + for `k = 0, …, n-1` (so `row 0 = []`). We prove the two properties in the entry's name: + `length_row` (row `n` has length `∑_{k ∀ i ∈ π.parts, i ≤ m)).card + +/-- A computable count of the partitions of `n` into parts `≤ m` (`j` is the number of parts +equal to `m + 1`); `pb_eq_B` shows `pb n m = B n m`. -/ +def pb : ℕ → ℕ → ℕ + | n, 0 => if n = 0 then 1 else 0 + | n, m + 1 => ∑ j ∈ Finset.range (n / (m + 1) + 1), pb (n - j * (m + 1)) m + +theorem part_le {n : ℕ} (π : n.Partition) {i : ℕ} (hi : i ∈ π.parts) : i ≤ n := + (Multiset.le_sum_of_mem hi).trans_eq π.parts_sum + +theorem B_zero (m : ℕ) : B 0 m = 1 := by + rw [B, Finset.filter_true_of_mem (by simp), Finset.card_univ, Fintype.card_unique] + +theorem B_succ_zero (n : ℕ) : B (n + 1) 0 = 0 := by + rw [B, Finset.card_eq_zero, Finset.filter_eq_empty_iff] + intro π _ h + have h0 : π.parts = 0 := Multiset.eq_zero_of_forall_notMem fun i hi => by + have := π.parts_pos hi; have := h i hi; omega + have := π.parts_sum + rw [h0] at this + simp at this + +theorem B_succ (n m : ℕ) : + B n (m + 1) = B n m + if m + 1 ≤ n then B (n - (m + 1)) (m + 1) else 0 := by + rw [B, ← Finset.card_filter_add_card_filter_not + (fun π : n.Partition => m + 1 ∈ π.parts), add_comm] + congr 1 + · rw [B, Finset.filter_filter] + congr 1 + ext π + simp only [Finset.mem_filter, Finset.mem_univ, true_and] + constructor + · rintro ⟨h, hm⟩ i hi + have := h i hi + have : i ≠ m + 1 := fun e => hm (e ▸ hi) + omega + · intro h + exact ⟨fun i hi => (h i hi).trans (Nat.le_succ m), fun hm => by have := h _ hm; omega⟩ + · split_ifs with hmn + · rw [B] + let e := Nat.Partition.partitionWithPartEquiv (n := n) (a := m + 1) (by omega) hmn + refine Finset.card_bij' (fun π hπ => e ⟨π, (Finset.mem_filter.1 hπ).2⟩) + (fun π _ => (e.symm π).1) ?_ ?_ ?_ ?_ + · intro π hπ + simp only [Finset.mem_filter, Finset.mem_univ, true_and] at hπ ⊢ + intro i hi + rw [Nat.Partition.partitionWithPartEquiv_apply_parts] at hi + exact hπ.1 i (Multiset.mem_of_mem_erase hi) + · intro π _ + simp only [Finset.mem_filter, Finset.mem_univ, true_and] + rw [Nat.Partition.partitionWithPartEquiv_symm_apply_parts] + refine ⟨fun i hi => ?_, Multiset.mem_cons_self _ _⟩ + rcases Multiset.mem_cons.1 hi with rfl | hi + · exact le_rfl + · have h := Finset.mem_filter.1 ‹_› + exact h.2 i hi + · intro π _ + simp only [Equiv.symm_apply_apply] + · intro π _ + simp only [Subtype.coe_eta, Equiv.apply_symm_apply] + · rw [Finset.card_eq_zero, Finset.filter_eq_empty_iff] + intro π _ h + exact hmn (part_le π h) + +theorem pb_zero_right (n : ℕ) : pb n 0 = if n = 0 then 1 else 0 := by + rw [pb] + +theorem pb_succ (n m : ℕ) : + pb n (m + 1) = pb n m + if m + 1 ≤ n then pb (n - (m + 1)) (m + 1) else 0 := by + rw [pb, Finset.sum_range_succ', add_comm] + simp only [zero_mul, Nat.sub_zero] + congr 1 + split_ifs with hmn + · rw [pb, Nat.div_eq_sub_div (by omega) hmn] + refine Finset.sum_congr rfl fun j _ => ?_ + congr 1 + rw [Nat.succ_mul] + omega + · rw [Nat.div_eq_of_lt (by omega)] + simp + +theorem pb_eq_B (n : ℕ) : ∀ m, pb n m = B n m := by + induction n using Nat.strong_induction_on with + | _ n ihn => + intro m + induction m with + | zero => + rcases n with _ | n + · rw [pb_zero_right, B_zero]; rfl + · rw [pb_zero_right, B_succ_zero]; simp + | succ m ihm => + rw [pb_succ, B_succ, ihm] + split_ifs with hmn + · rw [ihn _ (by omega)] + · rfl + +/-- The partition numbers can be computed with `pb`. -/ +theorem p_eq_pb (k : ℕ) : p k = pb k k := by + rw [pb_eq_B, B, Finset.filter_true_of_mem (fun π _ i hi => part_le π hi), Finset.card_univ, p] + +/-! ### The triangle -/ + +/-- Row `n` built from a sequence `f` of multiplicities: `n - k` repeated `f k` times, for +`k = 0, …, n-1`. -/ +def rowOf (f : ℕ → ℕ) (n : ℕ) : List ℕ := + (List.range n).flatMap fun k => List.replicate (f k) (n - k) + +/-- Row `n` of A176206: `n - k` repeated `A000041(k)` times, for `k = 0, …, n-1`. -/ +def row (n : ℕ) : List ℕ := rowOf p n + +/-- Row `n` has length A000070(n-1) `= ∑_{k=0}^{n-1} A000041(k)`. -/ +theorem length_row (n : ℕ) : (row n).length = ∑ k ∈ Finset.range n, p k := by + simp only [row, rowOf, List.length_flatMap, List.length_replicate] + induction n with + | zero => simp + | succ n ih => + rw [List.range_succ, List.map_append, List.sum_append, ih, Finset.sum_range_succ] + simp + +/-- Row `n + 1` is row `n` with all entries increased by `1`, followed by `A000041(n)` ones: +every column of the triangle lists the positive integers. -/ +theorem row_succ (n : ℕ) : row (n + 1) = (row n).map (· + 1) ++ List.replicate (p n) 1 := by + simp only [row, rowOf, List.range_succ, List.flatMap_append, List.flatMap_cons, + List.flatMap_nil, List.append_nil, List.map_flatMap, List.map_replicate, + Nat.add_sub_cancel_left] + congr 1 + refine List.flatMap_congr fun k hk => ?_ + rw [List.mem_range] at hk + congr 1 + omega + +/-- `T n k`, the `k`-th term of row `n` (`n ≥ 1`, `1 ≤ k ≤ A000070(n-1)`). -/ +def T (n k : ℕ) : ℕ := (row n).getD (k - 1) 0 + +/-- Read the flattened triangle (rows given by `r`) from row `n` on, skipping `j` terms; `fuel` +bounds the number of rows visited (every row `n ≥ 1` is nonempty, so `fuel = i` suffices for the +`i`-th term). -/ +def flatAux (r : ℕ → List ℕ) : ℕ → ℕ → ℕ → ℕ + | 0, _, _ => 0 + | fuel + 1, n, j => + if j < (r n).length then (r n).getD j 0 else flatAux r fuel (n + 1) (j - (r n).length) + +/-- A176206 as a sequence (the triangle read by rows), with the OEIS indexing: `a 1, a 2, …`. -/ +def a (i : ℕ) : ℕ := flatAux row i 1 (i - 1) + +/-- The definition reproduces all 94 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 94).map (fun i => a (i + 1)) = + [1, 2, 1, 3, 2, 1, 1, 4, 3, 2, 2, 1, 1, 1, 5, 4, 3, 3, 2, 2, 2, 1, 1, 1, 1, 1, 6, 5, 4, 4, + 3, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 7, 6, 5, 5, 4, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, + 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, 3, 3, 3, + 3, 3, 3, 3] := by + have hr : row = rowOf (fun k => pb k k) := funext fun n => by + rw [row, show p = (fun k => pb k k) from funext p_eq_pb] + simp only [a, hr] + decide +kernel + +/-- Sanity check of the left-hand side against the entry's worked example for `n = 5`: the +divisors of the terms of row 5 are twelve 1's, four 2's, two 3's, one 4 and one 5 +(kernel-checked). -/ +theorem row_five_divisors : ((row 5 : Multiset ℕ).bind fun t => t.divisors.val) = + Multiset.replicate 12 1 + Multiset.replicate 4 2 + Multiset.replicate 2 3 + {4, 5} := by + rw [row, show p = (fun k => pb k k) from funext p_eq_pb] + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjecture (Omar E. Pol, A176206): for every row `n ≥ 1`, the multiset of all divisors of +all terms of row `n` (each term contributing each of its divisors once) equals the multiset of +all parts of all partitions of `n`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + (row n : Multiset ℕ).bind (fun t => t.divisors.val) = + (Finset.univ : Finset n.Partition).val.bind (fun π => π.parts) + +end Math0.Statements.A176206 diff --git a/lean/Math0/Statements/OEIS/A178295.lean b/lean/Math0/Statements/OEIS/A178295.lean new file mode 100644 index 0000000..b043352 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A178295.lean @@ -0,0 +1,448 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A178295: collinear 4-subsets of the grid `{0, …, 4}ⁿ` + +Source: https://oeis.org/A178295, _R. J. Mathar_, May 24 2010 (FORMULA section). Verbatim: +> Conjecture: a(n) = 9^n/2+3*7^n/2-2*5^n. a(n)= +21*a(n-1) -143*a(n-2) +315*a(n-3). +> G.f.: x*(-5+41*x)/((9*x-1)*(7*x-1)*(5*x-1)). [_R. J. Mathar_, May 24 2010] + +The entry (_R. H. Hardin_, May 24 2010, offset `0`) is "Number of collinear point 4-tuples in a +5 X 5 X 5 X... n-dimensional cubic grid." + +## Encoding + +* *The grid.* The `5 × 5 × ⋯ × 5` grid in dimension `n` is `Pt n = Fin n → Fin 5`, i.e. the + points of `{0, …, 4}ⁿ ⊆ ℤⁿ` (`coord p i ∈ ℤ` is the `i`-th coordinate). For `n = 0` it is a + single point. +* *"Point 4-tuples".* These are 4-element sets of grid points (unordered, distinct points): the + data `a(1) = 5 = C(5, 4)` and `a(2) = 64` (25 rows, 25 columns, 2 · 5 on the two main + diagonals and 4 on the four diagonals with 4 points) fix this reading. +* *Collinearity.* Three points are collinear (`Coll3 p q r`) iff the vectors `q - p` and `r - p` + are parallel, i.e. all `2 × 2` minors `(q - p)ᵢ (r - p)ⱼ - (q - p)ⱼ (r - p)ᵢ` vanish. A finite + set is collinear (`IsCollinear`) iff every three of its points (repetitions allowed) are. + `isCollinear_iff_collinear` proves that this is exactly Mathlib's `Collinear ℝ` for the + corresponding set of points of `ℝⁿ` (all points lie on one affine line). +* *The sequence.* `a n` is the number of 4-element subsets of `Pt n` that are collinear + (`Finset.powersetCard 4` of `Finset.univ`, filtered by `IsCollinear`); it is computable. +* *Data.* `a` is too slow for the kernel as written, so `fastA` counts the same sets: the points + are listed once each (`L n`), and for every pair `p, q` (in this order) the 4-sets with first + two elements `p, q` are counted as `C(m, 2)`, where `m` is the number of later points `r` with + `p, q, r` collinear (a 4-set `{p, q, r, s}` with `p ≠ q` is collinear iff `r` and `s` both lie + on the line `pq`, `coll4_iff`). `a_eq_fastA` proves `a n = fastA n` for every `n`. + `a_data` checks the listed terms `a(0), a(1), a(2)` in the kernel. `a(3) = 629` is out of + reach for this `O(5^{3n})` evaluator (a kernel evaluation of `a(3)` with an evaluator of this + kind ran out of memory above 10 GB), and a faster evaluator would need the structure of the + long grid lines, which is the content of the conjecture itself. (A Python brute force over + all lines gives `a(1), …, a(5) = 5, 64, 629, 5632, 48485`, as listed.) As a separate sanity + check of the transcription of the three formulas (not about `a`), `closedForm_data` and + `recurrence_data` check that the closed form gives, and the recurrence is satisfied by, all + 10 listed terms `0, 5, 64, …, 250334405`. +* *The conjecture* (`statement`) is the conjunction of the three stated formulas: + 1. `a(n) = 9^n/2 + 3*7^n/2 - 2*5^n` for every `n ≥ 0` (the offset; no range is given), in `ℚ` + so that the divisions are exact; + 2. `a(n) = 21 a(n-1) - 143 a(n-2) + 315 a(n-3)` for every `n ≥ 3` (the range where all + indices are in the domain `n ≥ 0`), in `ℤ`; + 3. the generating function: `∑ a(n) xⁿ = x(-5+41x) / ((9x-1)(7x-1)(5x-1))` as formal power + series over `ℚ`, with Mathlib's inverse of a power series; the denominator has constant + coefficient `-1 ≠ 0`, so this is the honest quotient (`genFun_iff` restates it as + `A(x) · D(x) = x(-5+41x)`). +-/ + +namespace Math0.Statements.A178295 + +/-! ### The grid and collinearity -/ + +/-- The points of the `n`-dimensional `5 × 5 × ⋯ × 5` grid `{0, …, 4}ⁿ`. -/ +abbrev Pt (n : ℕ) := Fin n → Fin 5 + +/-- The `i`-th coordinate of a grid point, as an integer. -/ +def coord {n : ℕ} (p : Pt n) (i : Fin n) : ℤ := ((p i : ℕ) : ℤ) + +/-- `p`, `q`, `r` are collinear: `q - p` and `r - p` are parallel, i.e. every `2 × 2` minor +`(q - p)ᵢ (r - p)ⱼ - (q - p)ⱼ (r - p)ᵢ` vanishes. -/ +def Coll3 {n : ℕ} (p q r : Pt n) : Prop := + ∀ i j : Fin n, (coord q i - coord p i) * (coord r j - coord p j) = + (coord q j - coord p j) * (coord r i - coord p i) + +instance {n : ℕ} (p q r : Pt n) : Decidable (Coll3 p q r) := by + unfold Coll3; infer_instance + +/-- A finite set of grid points is collinear iff any three of its points are collinear. -/ +def IsCollinear {n : ℕ} (s : Finset (Pt n)) : Prop := + ∀ p ∈ s, ∀ q ∈ s, ∀ r ∈ s, Coll3 p q r + +instance {n : ℕ} : DecidablePred (IsCollinear (n := n)) := fun s => by + unfold IsCollinear; infer_instance + +/-- A178295: the number of collinear 4-point subsets of the grid `{0, …, 4}ⁿ`. -/ +def a (n : ℕ) : ℕ := + ((Finset.univ : Finset (Pt n)).powersetCard 4 |>.filter IsCollinear).card + +/-! ### `IsCollinear` is collinearity in `ℝⁿ` -/ + +/-- A grid point as a point of `ℝⁿ`. -/ +def toReal {n : ℕ} (p : Pt n) : Fin n → ℝ := fun i => ((p i : ℕ) : ℝ) + +theorem coll3_iff_real {n : ℕ} (p q r : Pt n) : Coll3 p q r ↔ + ∀ i j : Fin n, (toReal q i - toReal p i) * (toReal r j - toReal p j) = + (toReal q j - toReal p j) * (toReal r i - toReal p i) := by + unfold Coll3 coord toReal + refine forall_congr' fun i => forall_congr' fun j => ?_ + rw [← Int.cast_inj (α := ℝ)] + push_cast + rfl + +/-- `IsCollinear s` says exactly that the points of `s` lie on one line of `ℝⁿ`. -/ +theorem isCollinear_iff_collinear {n : ℕ} (s : Finset (Pt n)) : + IsCollinear s ↔ Collinear ℝ (toReal '' (s : Set (Pt n))) := by + rw [collinear_iff_exists_forall_eq_smul_vadd] + constructor + · intro h + by_cases hs : ∃ p ∈ s, ∃ q ∈ s, toReal p ≠ toReal q + · obtain ⟨p, hp, q, hq, hpq⟩ := hs + obtain ⟨k, hk⟩ : ∃ k, toReal p k ≠ toReal q k := by + by_contra hc + push Not at hc + exact hpq (funext hc) + have hd : toReal q k - toReal p k ≠ 0 := sub_ne_zero.mpr (Ne.symm hk) + refine ⟨toReal p, toReal q - toReal p, ?_⟩ + rintro _ ⟨r, hr, rfl⟩ + refine ⟨(toReal r k - toReal p k) / (toReal q k - toReal p k), ?_⟩ + have hc := (coll3_iff_real p q r).1 (h p hp q hq r hr) + funext j + have hkj := hc k j + simp only [vadd_eq_add, Pi.add_apply, Pi.smul_apply, smul_eq_mul, Pi.sub_apply] + field_simp + linear_combination hkj + · push Not at hs + by_cases hne : s.Nonempty + · obtain ⟨p, hp⟩ := hne + refine ⟨toReal p, 0, ?_⟩ + rintro _ ⟨r, hr, rfl⟩ + exact ⟨0, by simp [hs r hr p hp]⟩ + · refine ⟨0, 0, ?_⟩ + rintro _ ⟨r, hr, rfl⟩ + exact absurd ⟨r, hr⟩ hne + · rintro ⟨p₀, v, h⟩ p hp q hq r hr + obtain ⟨x, hx⟩ := h (toReal p) ⟨p, hp, rfl⟩ + obtain ⟨y, hy⟩ := h (toReal q) ⟨q, hq, rfl⟩ + obtain ⟨z, hz⟩ := h (toReal r) ⟨r, hr, rfl⟩ + rw [coll3_iff_real] + intro i j + rw [hx, hy, hz] + simp only [vadd_eq_add, Pi.add_apply, Pi.smul_apply, smul_eq_mul] + ring + +/-! ### Collinear 4-sets -/ + +/-- Collinearity of a multiset of grid points (used for the 4-sets as lists). -/ +def Q {n : ℕ} (m : Multiset (Pt n)) : Prop := ∀ p ∈ m, ∀ q ∈ m, ∀ r ∈ m, Coll3 p q r + +instance {n : ℕ} : DecidablePred (Q (n := n)) := fun m => by unfold Q; infer_instance + +/-- If `q ≠ p` (witnessed by the coordinate `k`), all points on the line `pq` are collinear. -/ +theorem coll3_of_line {n : ℕ} (p q x y z : Pt n) (k : Fin n) (hk : coord q k ≠ coord p k) + (hx : Coll3 p q x) (hy : Coll3 p q y) (hz : Coll3 p q z) : Coll3 x y z := by + intro i j + set D := coord q k - coord p k with hD + have hD0 : D ≠ 0 := sub_ne_zero.mpr hk + have hA : ∀ i, D * (coord y i - coord x i) = + (coord q i - coord p i) * (coord y k - coord x k) := by + intro i + linear_combination hy k i - hx k i + have hB : ∀ i, D * (coord z i - coord x i) = + (coord q i - coord p i) * (coord z k - coord x k) := by + intro i + linear_combination hz k i - hx k i + apply mul_left_cancel₀ (pow_ne_zero 2 hD0) + calc D ^ 2 * ((coord y i - coord x i) * (coord z j - coord x j)) + = (D * (coord y i - coord x i)) * (D * (coord z j - coord x j)) := by ring + _ = (D * (coord y j - coord x j)) * (D * (coord z i - coord x i)) := by + rw [hA i, hB j, hA j, hB i]; ring + _ = D ^ 2 * ((coord y j - coord x j) * (coord z i - coord x i)) := by ring + +theorem coord_ne_of_ne {n : ℕ} {p q : Pt n} (h : p ≠ q) : ∃ k, coord q k ≠ coord p k := by + by_contra hc + push Not at hc + apply h + funext k + have := hc k + unfold coord at this + exact Fin.ext (by exact_mod_cast this.symm) + +theorem coll3_self_left {n : ℕ} (p q : Pt n) : Coll3 p q p := by + intro i j; ring + +theorem coll3_self_right {n : ℕ} (p q : Pt n) : Coll3 p q q := by + intro i j; ring + +/-- A 4-set `{p, q, r, s}` with `p ≠ q` is collinear iff `r` and `s` lie on the line `pq`. -/ +theorem coll4_iff {n : ℕ} {p q : Pt n} (r s : Pt n) (h : p ≠ q) : + Q (([p, q, r, s] : List (Pt n)) : Multiset (Pt n)) ↔ Coll3 p q r ∧ Coll3 p q s := by + unfold Q + simp only [Multiset.mem_coe, List.mem_cons, List.not_mem_nil, or_false] + constructor + · intro H + exact ⟨H p (Or.inl rfl) q (Or.inr (Or.inl rfl)) r (Or.inr (Or.inr (Or.inl rfl))), + H p (Or.inl rfl) q (Or.inr (Or.inl rfl)) s (Or.inr (Or.inr (Or.inr rfl)))⟩ + · rintro ⟨hr, hs⟩ + obtain ⟨k, hk⟩ := coord_ne_of_ne h + have hall : ∀ x, x = p ∨ x = q ∨ x = r ∨ x = s → Coll3 p q x := by + rintro x (rfl | rfl | rfl | rfl) + · exact coll3_self_left _ _ + · exact coll3_self_right _ _ + · exact hr + · exact hs + intro x hx y hy z hz + exact coll3_of_line p q x y z k hk (hall x hx) (hall y hy) (hall z hz) + +/-! ### A fast evaluator -/ + +/-- All points of `Pt n`, each listed once. -/ +def L : (n : ℕ) → List (Pt n) + | 0 => [fun i => i.elim0] + | n + 1 => (List.finRange 5).flatMap fun c => (L n).map fun p => (Fin.cons c p : Pt (n + 1)) + +theorem mem_L : ∀ (n : ℕ) (p : Pt n), p ∈ L n + | 0, p => by + simp only [L, List.mem_singleton] + funext i; exact i.elim0 + | n + 1, p => by + simp only [L, List.mem_flatMap, List.mem_finRange, List.mem_map, true_and] + exact ⟨p 0, Fin.tail p, mem_L n _, Fin.cons_self_tail p⟩ + +theorem nodup_L : ∀ n : ℕ, (L n).Nodup + | 0 => List.nodup_singleton _ + | n + 1 => by + simp only [L] + rw [List.nodup_flatMap] + refine ⟨fun c _ => (nodup_L n).map (Fin.cons_right_injective (α := fun _ => Fin 5) c), ?_⟩ + refine (List.nodup_finRange 5).pairwise_of_forall_ne ?_ + intro c _ d _ hcd + simp only [Function.onFun, List.disjoint_left, List.mem_map] + rintro _ ⟨x, _, rfl⟩ ⟨y, _, hy⟩ + exact hcd (congrFun hy 0).symm + +theorem univ_val (n : ℕ) : + (Finset.univ : Finset (Pt n)).val = ((L n : List (Pt n)) : Multiset (Pt n)) := by + have : (⟨(L n : Multiset (Pt n)), nodup_L n⟩ : Finset (Pt n)) = Finset.univ := + Finset.eq_univ_of_forall fun p => mem_L n p + rw [← this] + +/-- The coordinates of a grid point, as a list of natural numbers. -/ +def coords {n : ℕ} (p : Pt n) : List ℕ := List.ofFn fun i => (p i : ℕ) + +/-- Zip three lists. -/ +def zip3 : List ℕ → List ℕ → List ℕ → List (ℕ × ℕ × ℕ) + | x :: u, y :: v, z :: w => (x, y, z) :: zip3 u v w + | _, _, _ => [] + +/-- For `x = (pᵢ, qᵢ, rᵢ)`, `y = (pⱼ, qⱼ, rⱼ)`: the minor condition +`(qᵢ - pᵢ)(rⱼ - pⱼ) = (qⱼ - pⱼ)(rᵢ - pᵢ)`, rearranged into an equation of natural numbers. -/ +def minorB (x y : ℕ × ℕ × ℕ) : Bool := + Nat.beq (x.2.1 * y.2.2 + y.2.1 * x.1 + y.1 * x.2.2) (y.2.1 * x.2.2 + x.2.1 * y.1 + x.1 * y.2.2) + +/-- `minorB` holds for all pairs `i < j`. -/ +def pairsB : List (ℕ × ℕ × ℕ) → Bool + | [] => true + | x :: T => T.all (minorB x) && pairsB T + +/-- Boolean version of `Coll3`. -/ +def coll3B {n : ℕ} (p q r : Pt n) : Bool := pairsB (zip3 (coords p) (coords q) (coords r)) + +theorem zip3_ofFn : ∀ {n : ℕ} (f g h : Fin n → ℕ), + zip3 (List.ofFn f) (List.ofFn g) (List.ofFn h) = List.ofFn fun i => (f i, g i, h i) + | 0, _, _, _ => by simp [zip3] + | n + 1, f, g, h => by + rw [List.ofFn_succ, List.ofFn_succ, List.ofFn_succ, List.ofFn_succ, zip3, + zip3_ofFn (fun i => f i.succ) (fun i => g i.succ) (fun i => h i.succ)] + +theorem minorB_iff (x y : ℕ × ℕ × ℕ) : minorB x y = true ↔ + ((x.2.1 : ℤ) - x.1) * ((y.2.2 : ℤ) - y.1) = ((y.2.1 : ℤ) - y.1) * ((x.2.2 : ℤ) - x.1) := by + unfold minorB + rw [Nat.beq_eq] + constructor + · intro h + have h' := congrArg (fun t : ℕ => (t : ℤ)) h + push_cast at h' + linear_combination h' + · intro h + have h' : ((x.2.1 * y.2.2 + y.2.1 * x.1 + y.1 * x.2.2 : ℕ) : ℤ) = + ((y.2.1 * x.2.2 + x.2.1 * y.1 + x.1 * y.2.2 : ℕ) : ℤ) := by + push_cast + linear_combination h + exact_mod_cast h' + +theorem pairsB_iff (T : List (ℕ × ℕ × ℕ)) : + pairsB T = true ↔ T.Pairwise fun x y => minorB x y = true := by + induction T with + | nil => simp [pairsB] + | cons x T ih => simp [pairsB, ih, List.pairwise_cons, List.all_eq_true] + +theorem pairsB_iff_forall (T : List (ℕ × ℕ × ℕ)) : + pairsB T = true ↔ ∀ x ∈ T, ∀ y ∈ T, minorB x y = true := by + have hsymm : ∀ x y, minorB x y = true → minorB y x = true := by + intro x y h + rw [minorB_iff] at h ⊢ + exact h.symm + rw [pairsB_iff] + constructor + · intro h + refine List.Pairwise.forall_of_forall_of_flip (fun x _ => ?_) h + (h.imp fun {x y} hxy => hsymm x y hxy) + rw [minorB_iff] + · exact List.pairwise_of_forall_mem_list + +theorem coll3B_iff {n : ℕ} (p q r : Pt n) : coll3B p q r = true ↔ Coll3 p q r := by + unfold coll3B coords + rw [zip3_ofFn, pairsB_iff_forall, List.forall_mem_ofFn_iff] + refine forall_congr' fun i => ?_ + rw [List.forall_mem_ofFn_iff] + refine forall_congr' fun j => ?_ + rw [minorB_iff] + rfl + +section Count + +variable {α : Type*} (c : α → α → α → Bool) + +/-- For a point `p` and a list `l`: the sum, over the entries `q` of `l`, of `C(m, 2)`, where +`m` is the number of entries `r` after `q` with `c p q r`. -/ +def cnt2 (p : α) : List α → ℕ + | [] => 0 + | q :: l => cnt2 p l + (l.countP (c p q)).choose 2 + +/-- The sum of `cnt2 c p l'` over the entries `p` of `l` (`l'` the list after `p`). -/ +def cnt : List α → ℕ + | [] => 0 + | p :: l => cnt l + cnt2 c p l + +theorem countP_sublistsLen_one_all (P : α → Bool) (l : List α) : + (l.sublistsLen 1).countP (fun t => t.all P) = l.countP P := by + induction l with + | nil => rfl + | cons x l ih => + rw [List.sublistsLen_succ_cons, List.countP_append, ih, List.countP_cons] + simp [List.sublistsLen_zero, List.countP_singleton] + +theorem countP_sublistsLen_two_all (P : α → Bool) (l : List α) : + (l.sublistsLen 2).countP (fun t => t.all P) = (l.countP P).choose 2 := by + induction l with + | nil => rfl + | cons x l ih => + rw [List.sublistsLen_succ_cons, List.countP_append, ih, List.countP_map, List.countP_cons] + by_cases hx : P x = true + · have : ((fun t => t.all P) ∘ List.cons x) = fun t => t.all P := by + funext t; simp [hx] + rw [this, countP_sublistsLen_one_all, if_pos hx, Nat.choose_succ_succ', Nat.choose_one_right] + ring + · have : ((fun t => t.all P) ∘ List.cons x) = fun _ => false := by + funext t; simp [hx] + rw [this, if_neg hx, List.countP_false] + simp + +variable (P : List α → Bool) + (hP : ∀ p q r s, p ≠ q → P [p, q, r, s] = (c p q r && c p q s)) +include hP + +theorem countP_sublistsLen_three (p : α) (l : List α) (hp : p ∉ l) : + (l.sublistsLen 3).countP (fun t => P (p :: t)) = cnt2 c p l := by + induction l with + | nil => rfl + | cons q l ih => + have hpq : p ≠ q := fun h => hp (h ▸ List.mem_cons_self) + rw [List.sublistsLen_succ_cons, List.countP_append, ih (fun h => hp (List.mem_cons_of_mem _ h)), + List.countP_map, cnt2, ← countP_sublistsLen_two_all] + congr 1 + apply List.countP_congr + intro t ht + obtain ⟨-, hlen⟩ := List.mem_sublistsLen.1 ht + match t, hlen with + | [r, s], _ => simp [hP p q r s hpq] + +theorem countP_sublistsLen_four (l : List α) (hl : l.Nodup) : + (l.sublistsLen 4).countP P = cnt c l := by + induction l with + | nil => rfl + | cons p l ih => + rw [List.nodup_cons] at hl + rw [List.sublistsLen_succ_cons, List.countP_append, ih hl.2, List.countP_map, cnt] + congr 1 + exact countP_sublistsLen_three c P hP p l hl.1 + +end Count + +/-- Fast evaluator of `a`. -/ +def fastA (n : ℕ) : ℕ := cnt coll3B (L n) + +/-- The fast evaluator computes `a`. -/ +theorem a_eq_fastA (n : ℕ) : a n = fastA n := by + unfold a fastA + rw [Finset.card_def, Finset.filter_val, ← Multiset.countP_eq_card_filter] + have h1 : Multiset.countP IsCollinear ((Finset.univ : Finset (Pt n)).powersetCard 4).val = + Multiset.countP Q (((Finset.univ : Finset (Pt n)).powersetCard 4).val.map Finset.val) := by + rw [Multiset.countP_map, Multiset.countP_eq_card_filter] + rfl + rw [h1, Finset.map_val_val_powersetCard, univ_val, Multiset.powersetCard_coe, + Multiset.coe_countP, List.countP_map] + refine countP_sublistsLen_four coll3B _ ?_ (L n) (nodup_L n) + intro p q r s hpq + rw [Bool.eq_iff_iff, Function.comp_apply, decide_eq_true_iff, coll4_iff r s hpq, + Bool.and_eq_true, coll3B_iff, coll3B_iff] + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): `a(0), a(1), +a(2)`. -/ +theorem a_data : (List.range 3).map (fun i => a (i + 0)) = [0, 5, 64] := by + simp only [Nat.add_zero, a_eq_fastA] + decide +kernel + +/-! ### The conjecture -/ + +/-- The 10 terms listed in the entry, `a(0), …, a(9)`. -/ +def listed : List ℤ := [0, 5, 64, 629, 5632, 48485, 410944, 3470549, 29389312, 250334405] + +/-- Transcription check (not about `a`): the conjectured closed form gives the listed terms. -/ +theorem closedForm_data : + (List.range 10).map (fun n : ℕ => (9 ^ n / 2 + 3 * 7 ^ n / 2 - 2 * 5 ^ n : ℚ)) = + listed.map (fun x : ℤ => (x : ℚ)) := by + norm_num [listed, List.range_succ] + +/-- Transcription check (not about `a`): the listed terms satisfy the conjectured recurrence +for `3 ≤ n ≤ 9`. -/ +theorem recurrence_data : ∀ n ∈ [3, 4, 5, 6, 7, 8, 9], + listed.getD n 0 = 21 * listed.getD (n - 1) 0 - 143 * listed.getD (n - 2) 0 + + 315 * listed.getD (n - 3) 0 := by + decide + +/-- The conjectured denominator `(9x-1)(7x-1)(5x-1)`. -/ +noncomputable def den : PowerSeries ℚ := + (9 * PowerSeries.X - 1) * (7 * PowerSeries.X - 1) * (5 * PowerSeries.X - 1) + +/-- Mathar's conjecture (all three formulas): +`a(n) = 9^n/2 + 3*7^n/2 - 2*5^n` for all `n ≥ 0`; +`a(n) = 21 a(n-1) - 143 a(n-2) + 315 a(n-3)` for all `n ≥ 3`; +`∑ a(n) xⁿ = x(-5+41x)/((9x-1)(7x-1)(5x-1))`. -/ +def statement : Prop := + (∀ n : ℕ, (a n : ℚ) = 9 ^ n / 2 + 3 * 7 ^ n / 2 - 2 * 5 ^ n) ∧ + (∀ n : ℕ, 3 ≤ n → + (a n : ℤ) = 21 * (a (n - 1) : ℤ) - 143 * (a (n - 2) : ℤ) + 315 * (a (n - 3) : ℤ)) ∧ + PowerSeries.mk (fun n => (a n : ℚ)) = + PowerSeries.X * (-5 + 41 * PowerSeries.X) * + ((9 * PowerSeries.X - 1) * (7 * PowerSeries.X - 1) * (5 * PowerSeries.X - 1))⁻¹ + +theorem constantCoeff_den : PowerSeries.constantCoeff den ≠ 0 := by + simp [den] + +/-- The generating-function clause, with the denominator multiplied out. -/ +theorem genFun_iff : + PowerSeries.mk (fun n => (a n : ℚ)) = + PowerSeries.X * (-5 + 41 * PowerSeries.X) * + ((9 * PowerSeries.X - 1) * (7 * PowerSeries.X - 1) * (5 * PowerSeries.X - 1))⁻¹ ↔ + PowerSeries.mk (fun n => (a n : ℚ)) * den = PowerSeries.X * (-5 + 41 * PowerSeries.X) := + PowerSeries.eq_mul_inv_iff_mul_eq constantCoeff_den + +end Math0.Statements.A178295 diff --git a/lean/Math0/Statements/OEIS/A182617.lean b/lean/Math0/Statements/OEIS/A182617.lean new file mode 100644 index 0000000..f403979 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A182617.lean @@ -0,0 +1,159 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A182617: toothpicks in the toothpick spiral around `n` hexagonal cells + +Source: https://oeis.org/A182617, Vincenzo Librandi, Sep 20 2017 (FORMULA section of the entry +by Omar E. Pol, Dec 13 2010). Verbatim: +> Conjecture: a(n) = 2*n + ceiling(sqrt(12*n - 3)), for n > 0. - _Vincenzo Librandi_, Sep 20 2017 + +The sequence (offset `0`) is "Number of toothpicks in a toothpick spiral around n cells on +hexagonal net." The comments explain: a hexagonal cell is "ON" when all 6 of its vertices are +covered by toothpicks; the toothpicks form a self-avoiding walk on the edges of the net that +first goes round a central hexagon (5 edges) and then winds round the successive rings of +hexagons; the count of toothpicks is read off each time one more hexagon becomes ON. The +examples give `a(0) = 0`, `a(1) = 5`, `a(2) = 9`, `a(3) = 12`. + +## Encoding + +* **The net.** Vertices of the hexagonal net are `Pt = ℤ × ℤ` in brick-wall coordinates: `(x, y)` + is joined to `(x ± 1, y)`, and to `(x, y + 1)` if `x + y` is even, to `(x, y - 1)` if `x + y` is + odd. This is a planar straight-line drawing of the hexagonal net in which every face is a + `2 × 1` brick. The cells are these bricks: for every `c = (x, y)` with `x + y` even, the cell + `c` has the six vertices `(x, y), (x+1, y), (x+2, y), (x, y+1), (x+1, y+1), (x+2, y+1)` + (`cellVerts`). +* **The spiral.** `nbrs v` lists the neighbours of `v` counterclockwise; arriving at `v` from the + neighbour `p`, the left turn leads to the neighbour two places after `p` in this cyclic order, + the right turn to the one just after `p` (`turns`). The walk starts at `(0, 0)` with its first + toothpick going to `(1, 0)`; afterwards it turns left whenever the vertex there has not been + visited yet, and otherwise turns right (if both are visited it would stop, which never happens: + the walk winds outward forever). Thus it goes round the central hexagon with 5 toothpicks, + then steps out and goes once round the next ring until self-avoidance forces it outward, and so + on, exactly as described in the comments. `walk t` is the list of vertices covered by the first + `t` toothpicks (most recent first). Since the net is vertex-transitive under rotations, the + starting vertex and direction do not matter, and the mirror-image spiral gives the same counts. +* **Cells ON and `a(n)`.** `onCells w` is the set of cells all six of whose vertices are covered + (every such cell has its corner `c` among the covered vertices), and `onCount t` is the number + of ON cells after `t` toothpicks. `a n` is the number of toothpicks at the first moment at which + `n` cells are ON, i.e. the least `t` with `n ≤ onCount t`; so `a 0 = 0`. To keep `a` computable + the search runs over `t ≤ 6 * n` and returns `6 * n + 1` if no such `t` is found. The cap is + harmless: `a_eq_iff_isLeast` shows `a n` is the least such `t` whenever that is at most `6n`, + and `statement_iff` restates the conjecture with no cap at all (the conjectured value is at + most `6n` for `n ≥ 1`). +* **Data.** `a_data` checks all 40 listed terms `a(0), …, a(39)` in the kernel. +* **The conjecture** is stated for `n > 0`, as in the entry. `ceiling(sqrt(12*n - 3))` is + `⌈Real.sqrt (12 * n - 3)⌉₊`; for `n ≥ 1` the radicand is positive, so this is the usual ceiling + of the real square root. +-/ + +namespace Math0.Statements.A182617 + +/-- Vertices of the hexagonal net, in brick-wall coordinates. -/ +abbrev Pt := ℤ × ℤ + +/-- The three neighbours of a vertex of the hexagonal net, listed counterclockwise: for `x + y` +even they are right, up, left; for `x + y` odd they are right, left, down. -/ +def nbrs (v : Pt) : Pt × Pt × Pt := + if (v.1 + v.2) % 2 = 0 then ((v.1 + 1, v.2), (v.1, v.2 + 1), (v.1 - 1, v.2)) + else ((v.1 + 1, v.2), (v.1 - 1, v.2), (v.1, v.2 - 1)) + +/-- `turns p v = (l, r)`: arriving at `v` from its neighbour `p`, the left turn leads to `l` and +the right turn leads to `r`. -/ +def turns (p v : Pt) : Pt × Pt := + let (n0, n1, n2) := nbrs v + if p = n0 then (n2, n1) else if p = n1 then (n0, n2) else (n1, n0) + +/-- One more toothpick of the spiral. The list `w` holds the covered vertices, most recent first; +the walk turns left if that vertex is still uncovered, and otherwise right (it would stop if both +were covered). -/ +def step : List Pt → List Pt + | v :: p :: rest => + let w := v :: p :: rest + let (l, r) := turns p v + if l ∉ w then l :: w else if r ∉ w then r :: w else w + | w => w + +/-- The vertices covered by the first `t` toothpicks of the spiral (most recent first). It starts +at `(0, 0)`, and the first toothpick joins `(0, 0)` to `(1, 0)`. -/ +def walk : ℕ → List Pt + | 0 => [(0, 0)] + | t + 1 => step^[t] [(1, 0), (0, 0)] + +/-- The six vertices of the hexagonal cell with lower-left corner `c` (for `c.1 + c.2` even). -/ +def cellVerts (c : Pt) : List Pt := + [(c.1, c.2), (c.1 + 1, c.2), (c.1 + 2, c.2), + (c.1, c.2 + 1), (c.1 + 1, c.2 + 1), (c.1 + 2, c.2 + 1)] + +/-- The cells that are "ON" once the vertices in `w` are covered: the cells all six of whose +vertices are covered, each represented by its lower-left corner. -/ +def onCells (w : List Pt) : Finset Pt := + w.toFinset.filter (fun c => (c.1 + c.2) % 2 = 0 ∧ ∀ u ∈ cellVerts c, u ∈ w) + +/-- The number of ON cells after `t` toothpicks of the spiral. -/ +def onCount (t : ℕ) : ℕ := (onCells (walk t)).card + +/-- A182617: the number of toothpicks in the toothpick spiral at the first moment when it +surrounds `n` cells (has `n` cells ON), i.e. the least `t` with `n ≤ onCount t`. The search is +capped at `6 * n` (returning `6 * n + 1` beyond it); see `a_eq_iff_isLeast`. -/ +def a (n : ℕ) : ℕ := + ((List.range (6 * n + 1)).find? (fun t => n ≤ onCount t)).getD (6 * n + 1) + +/-- The definition reproduces all 40 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 40).map (fun i => a (i + 0)) = + [0, 5, 9, 12, 15, 18, 21, 23, 26, 29, 31, 34, 36, 39, 41, 44, 46, 49, 51, 53, + 56, 58, 61, 63, 65, 68, 70, 72, 75, 77, 79, 82, 84, 86, 89, 91, 93, 95, 98, 100] := by + decide +kernel + +/-- The cap in the definition of `a` does not matter: for `t ≤ 6n`, `a n = t` exactly when `t` is +the least number of toothpicks at which `n` cells are ON. -/ +theorem a_eq_iff_isLeast {n t : ℕ} (ht : t ≤ 6 * n) : + a n = t ↔ IsLeast {s | n ≤ onCount s} t := by + constructor + · intro h + unfold a at h + cases hf : (List.range (6 * n + 1)).find? (fun t => n ≤ onCount t) with + | none => rw [hf] at h; simp at h; omega + | some i => + rw [hf] at h + simp only [Option.getD_some] at h + subst h + rw [List.find?_range_eq_some] at hf + obtain ⟨h1, -, h3⟩ := hf + refine ⟨by simpa using h1, fun s hs => ?_⟩ + by_contra hlt + have := h3 s (by omega) + simp only [Set.mem_ofPred_eq] at hs + simp [hs] at this + · rintro ⟨h1, h2⟩ + have hf : (List.range (6 * n + 1)).find? (fun t => n ≤ onCount t) = some t := by + rw [List.find?_range_eq_some] + refine ⟨by simpa using h1, by simp; omega, fun j hj => ?_⟩ + have : ¬ n ≤ onCount j := fun hj' => absurd (h2 hj') (by omega) + simpa using this + unfold a + rw [hf] + rfl + +/-- Librandi's conjecture: for `n > 0`, `a(n) = 2n + ⌈√(12n - 3)⌉`. -/ +def statement : Prop := + ∀ n : ℕ, 0 < n → a n = 2 * n + ⌈Real.sqrt (12 * (n : ℝ) - 3)⌉₊ + +/-- The conjecture says exactly that, for every `n > 0`, the least number of toothpicks of the +spiral at which `n` cells are ON is `2n + ⌈√(12n - 3)⌉` (no cap on the search). -/ +theorem statement_iff : statement ↔ + ∀ n : ℕ, 0 < n → + IsLeast {t | n ≤ onCount t} (2 * n + ⌈Real.sqrt (12 * (n : ℝ) - 3)⌉₊) := by + have hb : ∀ n : ℕ, 0 < n → 2 * n + ⌈Real.sqrt (12 * (n : ℝ) - 3)⌉₊ ≤ 6 * n := by + intro n hn + have hc : ⌈Real.sqrt (12 * (n : ℝ) - 3)⌉₊ ≤ 4 * n := by + rw [Nat.ceil_le, Real.sqrt_le_left (by positivity)] + have : (1 : ℝ) ≤ n := by exact_mod_cast hn + push_cast + nlinarith + omega + exact forall₂_congr fun n hn => a_eq_iff_isLeast (hb n hn) + +end Math0.Statements.A182617 diff --git a/lean/Math0/Statements/OEIS/A188474.lean b/lean/Math0/Statements/OEIS/A188474.lean new file mode 100644 index 0000000..5ec8f4a --- /dev/null +++ b/lean/Math0/Statements/OEIS/A188474.lean @@ -0,0 +1,155 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A188474: the row sums of a generalized Deutsch triangle are A137398 + +Source: https://oeis.org/A188474, Paul Barry, Apr 01 2011 (COMMENTS section). Verbatim: +> Row sums are A137398(n+1) (conjecture). Diagonal sums are A188476. + +Only the first sentence is the conjecture. The second refers to A188476, which is defined as the +diagonal sums of this triangle; it is not part of the conjecture and is not formalized. + +The entry (offset `0`, keyword `tabl`) is named "A generalized Deutsch triangle." Its comment +says: "Member r=2 of the family of "Pascal-like" triangles with +T(n,k)=sum{j=0..n-k+1, (j/(n+2-j))*C(n+2-j,n-k+1)*C(n+2-j,k+1)*r^(j-1)}". Its formula is +"T(n,k)=sum{j=0..n-k+1, (j/(n+2-j))*C(n+2-j,n-k+1)*C(n+2-j,k+1)*2^(j-1)}", for `0 ≤ k ≤ n`. + +A137398 (Gordon Beavers, G. Starling and W. Li, Apr 11 2008; offset `1`) is named: "Let S be a +strictly monotonic sequence of length 2n and let p and q be subsequences of S each of length n +such that the least element belongs to p and every element of S belongs to either p or q. The +number of ways to select p such that for any index i the exchange of p(i) and q(i) makes at least +one of p and q non-monotonic, is given by a(n)." Its data begin `0, 1, 2, 7, 22, 74, 252, …`, +with `a(1) = 0`. + +## Encoding + +* *The triangle.* `T n k : ℚ` is the formula above with `r = 2`, computed exactly in `ℚ`. The + sum runs over `j = 0, …, n-k+1`, i.e. `j ∈ range (n-k+2)`. `j/(n+2-j)` is a rational quotient. + Its denominator `n+2-j` is computed in `ℚ`, and it is `≥ k+1 ≥ 1` for `j ≤ n-k+1`. The + binomial coefficients are Mathlib's `Nat.choose` of `n+2-j`. That natural-number subtraction is + exact, since `j ≤ n-k+1 ≤ n+1`. `2^(j-1)` is an integer power in `ℚ`. It is `1/2` for `j = 0`, + but that term vanishes anyway because of the factor `j`. The individual terms are not obviously + integers, so `T` is `ℚ`-valued. Only `0 ≤ k ≤ n` is used. +* *The sequence.* `row n = [T(n,0), …, T(n,n)]`, and `a i` is the triangle read by rows (the + OEIS sequence itself, offset `0`). `a_data` checks all `66` listed terms `a 0, …, a 65` + (rows `0, …, 10`). +* *A137398.* Only the relative order of the elements of `S` matters, so the `m`-th term uses + `S = [0, 1, …, 2m-1]` (`List.range (2 * m)`). + - `p` runs over the subsequences of `S` of length `m`. These are `List.sublistsLen m S`, which + lists each of them exactly once (Mathlib's `List.mem_sublistsLen`, `List.nodup_sublistsLen`). + - `q` is then forced. Every element of `S` lies in `p` or in `q`, and `|p| + |q| = 2m = |S|`, + so `q` consists of the elements of `S` not in `p`, in the order of `S`: + `q = S.filter (· ∉ p)`. Counting the ways to select `p` is counting these `p`. + - "The least element belongs to p" is `0 ∈ p`. + - `p(i)` and `q(i)` are the `i`-th entries of `p` and `q` (`i = 0, …, m-1`, 0-based; both + lists have length `m`, so the default value of `getD` is never used). Exchanging them gives + the lists `p.set i q(i)` and `q.set i p(i)`. + - "Monotonic" is read as increasing, i.e. in the direction of `S`: `List.Pairwise (· < ·)`. + For `m ≥ 3` this is the only possible reading. Each exchanged list still contains `m - 1 ≥ 2` + entries of the increasing `p` (resp. `q`) in their order, so it cannot be decreasing. For + `m = 2` the reading is forced by the data. If decreasing sequences also counted as monotonic, + every sequence of length `2` would be monotonic and `a(2)` would be `0`. The entry lists + `a(2) = 1`, with the example "The a(2) = 1 p/q subsequences of 1234 are 12/34". + - A strictly decreasing `S` gives the same count. The condition is symmetric in `p` and `q`, + so in either case the count is the number of unordered partitions `{p, q}` satisfying it. + + `A137398_data` checks the first `6` listed terms `a(1), …, a(6) = 0, 1, 2, 7, 22, 74` by + direct enumeration in the kernel. (`a(7)` alone takes about 1.5 minutes this way.) +* *Indexing.* The conjecture predates the correction of A137398's offset. The entry's EXTENSIONS + line reads "Offset, a(15), a(18) corrected by and more terms from _Georg Fischer_, Jun 07 2021". + The listed row sums `1, 2, 7, 22, 74, …` of A188474 are the terms of A137398 from its second + term on. So in the 2011 indexing, `A137398(n+1)` was the term matching row `n`. In the current + indexing (offset `1`, the one that matches the name: `a(m)` is about `S` of length `2m`), these + terms are `A137398(2), A137398(3), …`. So the conjecture says that row `n` sums to + `A137398(n+2)`. The literal reading `A137398(n+1)` with the current offset already fails at + `n = 0`: the row sum is `1`, but `A137398(1) = 0`. `rowSum_data` checks that the row sums for + `n = 0, …, 10` are the listed terms `A137398(2), …, A137398(12)`. `statement_check` checks + the statement itself for `n ≤ 4` (a sanity check of the transcription, not a proof). +* *The conjecture.* `statement`: for every `n ≥ 0`, `∑_{k=0}^{n} T(n,k) = A137398(n+2)`, as an + equality in `ℚ`. +-/ + +namespace Math0.Statements.A188474 + +open Finset + +/-! ### The triangle A188474 -/ + +/-- The generalized Deutsch triangle with `r = 2`: +`T(n,k) = ∑_{j=0}^{n-k+1} (j/(n+2-j)) C(n+2-j, n-k+1) C(n+2-j, k+1) 2^(j-1)`, `0 ≤ k ≤ n`, +computed exactly in `ℚ`. -/ +def T (n k : ℕ) : ℚ := + ∑ j ∈ range (n - k + 2), + (j : ℚ) / ((n : ℚ) + 2 - j) * ((n + 2 - j).choose (n - k + 1) : ℚ) * + ((n + 2 - j).choose (k + 1) : ℚ) * (2 : ℚ) ^ ((j : ℤ) - 1) + +/-- Row `n` of the triangle: `[T(n,0), …, T(n,n)]`. -/ +def row (n : ℕ) : List ℚ := (List.range (n + 1)).map (T n) + +/-- A188474: the triangle `T` read by rows (offset `0`). Rows `0, …, i` have more than `i` +entries, so the `i`-th entry of their concatenation exists. -/ +def a (i : ℕ) : ℚ := ((List.range (i + 1)).flatMap row).getD i 0 + +set_option maxRecDepth 100000 in +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all `66` listed +terms `a(0), …, a(65)`, i.e. rows `0, …, 10`. -/ +theorem a_data : (List.range 66).map (fun i => a (i + 0)) = + [1, + 1, 1, + 1, 5, 1, + 1, 10, 10, 1, + 1, 16, 40, 16, 1, + 1, 23, 102, 102, 23, 1, + 1, 31, 209, 393, 209, 31, 1, + 1, 40, 376, 1122, 1122, 376, 40, 1, + 1, 50, 620, 2656, 4296, 2656, 620, 50, 1, + 1, 61, 960, 5536, 13100, 13100, 5536, 960, 61, 1, + 1, 73, 1417, 10522, 34036, 50180, 34036, 10522, 1417, 73, 1] := by + decide +kernel + +/-! ### A137398 -/ + +/-- A137398 (offset `1`), by its definition. With `S = [0, 1, …, 2m-1]`, count the +subsequences `p` of `S` of length `m` such that, with `q` the subsequence of the remaining +elements, the least element `0` belongs to `p`, and for every index `i < m` the exchange of +`p(i)` and `q(i)` makes at least one of `p`, `q` non-monotonic (not increasing). -/ +def A137398 (m : ℕ) : ℕ := + ((List.range (2 * m)).sublistsLen m).countP fun p => + let q := (List.range (2 * m)).filter (· ∉ p) + decide (0 ∈ p ∧ ∀ i < m, + ¬ ((p.set i (q.getD i 0)).Pairwise (· < ·) ∧ (q.set i (p.getD i 0)).Pairwise (· < ·))) + +set_option maxRecDepth 100000 in +/-- The definition of A137398 reproduces its first `6` listed terms (kernel-checked). -/ +theorem A137398_data : (List.range 6).map (fun i => A137398 (i + 1)) = [0, 1, 2, 7, 22, 74] := by + decide +kernel + +/-! ### The conjecture -/ + +set_option maxRecDepth 100000 in +/-- The row sums for `n = 0, …, 10` are the listed terms `A137398(2), …, A137398(12)` +(kernel-checked; a check of the indexing, not a proof). -/ +theorem rowSum_data : (List.range 11).map (fun n => ∑ k ∈ range (n + 1), T n k) = + [1, 2, 7, 22, 74, 252, 875, 3078, 10950, 39316, 142278] := by + decide +kernel + +/-- Paul Barry's conjecture (in the current indexing of A137398): for every `n ≥ 0`, the sum +of row `n` of the triangle, `∑_{k=0}^{n} T(n,k)`, equals `A137398(n+2)`. -/ +def statement : Prop := + ∀ n : ℕ, ∑ k ∈ range (n + 1), T n k = (A137398 (n + 2) : ℚ) + +/-- The statement holds for `n ≤ 4` (a sanity check of the transcription, not a proof). -/ +theorem statement_check (n : ℕ) (hn : n < 5) : + ∑ k ∈ range (n + 1), T n k = (A137398 (n + 2) : ℚ) := by + have h1 := congrArg (fun l => l.getD n 0) rowSum_data + have h2 := congrArg (fun l => ((l.getD (n + 1) 0 : ℕ) : ℚ)) A137398_data + simp only [List.getD_eq_getElem?_getD, List.getElem?_map, List.getElem?_range, + show n < 11 by omega, show n + 1 < 6 by omega, Option.map_some, + Option.getD_some] at h1 h2 + rw [h1, h2] + interval_cases n <;> rfl + +end Math0.Statements.A188474 diff --git a/lean/Math0/Statements/OEIS/A195249.lean b/lean/Math0/Statements/OEIS/A195249.lean new file mode 100644 index 0000000..b29eb78 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A195249.lean @@ -0,0 +1,184 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A195249: lower triangles of a 3 × 3 array with king-neighbours differing by at most 2 + +Source: https://oeis.org/A195249, _R. H. Hardin_, Sep 13 2011. Verbatim (FORMULA section): +> Empirical: a(n) = 1047*n - 1459 for n>2. + +The entry's name: "Number of lower triangles of a 3 X 3 0..n array with each element differing +from all of its diagonal, vertical, antidiagonal and horizontal neighbors by two or less." +Offset `1`. The same FORMULA section also records, verbatim: +> Conjectures from _Colin Barker_, May 06 2018: (Start) +> G.f.: x*(64 + 601*x + 288*x^2 + 94*x^3) / (1 - x)^2. +> a(n) = 2*a(n-1) - a(n-2) for n>4. +> (End) + +## Encoding + +* The lower triangle of a 3 × 3 array consists of the six positions `(i, j)` (row `i`, column + `j`, both in `0, 1, 2`) with `j ≤ i`, i.e. rows of lengths 1, 2, 3, as in the entry's + examples. They are enumerated as `cell : Fin 6 → ℕ × ℕ`; `image_cell` and `cell_injective` + check (in the kernel) that `cell` lists each such position exactly once. +* Two positions are diagonal, vertical, antidiagonal or horizontal neighbours (`Adj`) iff they + are distinct and both their row indices and their column indices differ by at most one. Only + neighbours inside the triangle are constrained, since the triangle is the whole object being + counted. +* A triangle is a vector `v : Fin 6 → ℕ` of entries (entry of `cell k` is `v k`); it is valid + (`Valid`) iff every two neighbouring entries differ by two or less (`near`). +* `a n` is the number of valid triangles with all six entries in `0..n`, written as a six-fold + sum over `x₀, …, x₅ ∈ {0, …, n}` of the indicator of `Valid ![x₀, …, x₅]`. The OEIS offset is + `1`; `a 0 = 1` (the all-zero triangle) is not a term of the sequence. +* The kernel cannot afford the `(n+1)^6` loop of `a` for many `n`, so the data check goes through + a pruned copy `aL` (each entry is only searched within distance `2` of an already chosen + neighbour, and constraints are tested as early as possible), proved equal to `a` in + `a_eq_aL`. Independently, `a_small` evaluates `a 1` and `a 2` straight from the definition. +* Hardin's conjecture is `statement`: for every `n > 2`, `a(n) = 1047 n - 1459`, stated in `ℤ` + (so that no truncated subtraction is involved). +* Barker's two companion conjectures are recorded as `statementBarkerGF` (the g.f. is read as + `∑_{n ≥ 1} a(n) x^n`, matching the offset `1`, and the identity of power series over `ℤ` is + stated after clearing the denominator `(1 - x)^2`, which is a unit) and `statementBarkerRec` + (the recurrence for all `n > 4`, in `ℤ`). +-/ + +namespace Math0.Statements.A195249 + +open Finset + +/-- The six positions `(row, column)` of the lower triangle of a 3 × 3 array, i.e. the +positions `(i, j)` with `j ≤ i < 3`, listed row by row. -/ +def cell : Fin 6 → ℕ × ℕ := ![(0, 0), (1, 0), (1, 1), (2, 0), (2, 1), (2, 2)] + +/-- Two positions are diagonal, vertical, antidiagonal or horizontal neighbours iff they are +distinct and their rows and their columns each differ by at most one. -/ +def Adj (p q : ℕ × ℕ) : Prop := + p ≠ q ∧ p.1 ≤ q.1 + 1 ∧ q.1 ≤ p.1 + 1 ∧ p.2 ≤ q.2 + 1 ∧ q.2 ≤ p.2 + 1 + +/-- `x` and `y` differ by two or less. -/ +def near (x y : ℕ) : Prop := x ≤ y + 2 ∧ y ≤ x + 2 + +instance : DecidableRel near := fun x y => by unfold near; infer_instance + +/-- A filling `v` of the lower triangle (`v k` is the entry at position `cell k`) is valid iff +each entry differs from each of its neighbours by two or less. -/ +def Valid (v : Fin 6 → ℕ) : Prop := ∀ i j : Fin 6, Adj (cell i) (cell j) → near (v i) (v j) + +instance (v : Fin 6 → ℕ) : Decidable (Valid v) := by unfold Valid Adj; infer_instance + +/-- A195249: the number of lower triangles of a 3 × 3 array with entries in `0..n` in which each +element differs from all of its diagonal, vertical, antidiagonal and horizontal neighbours by +two or less (offset `1`). -/ +def a (n : ℕ) : ℕ := + ∑ x0 ∈ range (n + 1), ∑ x1 ∈ range (n + 1), ∑ x2 ∈ range (n + 1), ∑ x3 ∈ range (n + 1), + ∑ x4 ∈ range (n + 1), ∑ x5 ∈ range (n + 1), if Valid ![x0, x1, x2, x3, x4, x5] then 1 else 0 + +/-! ### Sanity checks of the encoding -/ + +/-- `cell` lists distinct positions. -/ +theorem cell_injective : Function.Injective cell := by decide + +/-- `cell` lists exactly the positions `(i, j)` with `j ≤ i < 3` of a 3 × 3 array. -/ +theorem image_cell : + univ.image cell = (range 3 ×ˢ range 3).filter (fun p => p.2 ≤ p.1) := by decide + +/-- The neighbour constraints, made explicit: the ten neighbouring pairs of the triangle are +`0–1, 0–2, 1–2, 1–3, 2–3, 1–4, 2–4, 3–4, 2–5, 4–5` (grouped by their larger index). -/ +theorem valid_iff (x0 x1 x2 x3 x4 x5 : ℕ) : + Valid ![x0, x1, x2, x3, x4, x5] ↔ + (((near x0 x1 ∧ (near x0 x2 ∧ near x1 x2)) ∧ (near x1 x3 ∧ near x2 x3)) ∧ + (near x1 x4 ∧ (near x2 x4 ∧ near x3 x4))) ∧ (near x2 x5 ∧ near x4 x5) := by + simp only [Valid, Fin.forall_fin_succ, cell, Adj, near] + simp + omega + +/-- `a 1` and `a 2`, evaluated in the kernel directly from the definition. -/ +theorem a_small : a 1 = 64 ∧ a 2 = 729 := by + decide +kernel + +/-! ### A kernel-friendly copy of the definition -/ + +/-- The values in `0..n` within distance two of `y`, as a list. -/ +def win (n y : ℕ) : List ℕ := List.range' (y - 2) (min (y + 2) n + 1 - (y - 2)) + +/-- `∑_{x ∈ l} f x` for a list `l`. -/ +def lsum (l : List ℕ) (f : ℕ → ℕ) : ℕ := l.foldr (fun x acc => f x + acc) 0 + +/-- Pruned copy of `a`: each entry is searched near an already chosen neighbour. -/ +def aL (n : ℕ) : ℕ := + lsum (List.range (n + 1)) fun x0 => + lsum (win n x0) fun x1 => + lsum (win n x0) fun x2 => if near x1 x2 then + lsum (win n x1) fun x3 => if near x2 x3 then + lsum (win n x1) fun x4 => if near x2 x4 ∧ near x3 x4 then + lsum (win n x2) fun x5 => if near x4 x5 then 1 else 0 + else 0 else 0 else 0 + +theorem lsum_eq (l : List ℕ) (f : ℕ → ℕ) : lsum l f = (l.map f).sum := by + induction l with + | nil => rfl + | cons x l ih => rw [List.map_cons, List.sum_cons, ← ih]; rfl + +theorem sum_range_eq_lsum (m : ℕ) (f : ℕ → ℕ) : + ∑ x ∈ range m, f x = lsum (List.range m) f := by + rw [lsum_eq] + induction m with + | zero => rfl + | succ m ih => + rw [sum_range_succ, ih, List.range_succ, List.map_append, List.sum_append]; simp + +theorem filter_near (n y : ℕ) : + (range (n + 1)).filter (fun x => near y x) = Icc (y - 2) (min (y + 2) n) := by + ext x + rw [mem_filter, mem_range, mem_Icc] + unfold near + omega + +theorem sum_win (n y : ℕ) (g : ℕ → ℕ) : + ∑ x ∈ range (n + 1), (if near y x then g x else 0) = lsum (win n y) g := by + rw [← sum_filter, filter_near, Nat.Icc_eq_range', lsum_eq, win] + rfl + +theorem sum_win_and (n y : ℕ) (q : ℕ → Prop) [DecidablePred q] (g : ℕ → ℕ) : + ∑ x ∈ range (n + 1), (if near y x ∧ q x then g x else 0) = + lsum (win n y) (fun x => if q x then g x else 0) := by + rw [← sum_win] + exact sum_congr rfl fun x _ => ite_and _ _ _ _ + +theorem sum_pull (s : Finset ℕ) (p : Prop) [Decidable p] (q : ℕ → Prop) [DecidablePred q] + (g : ℕ → ℕ) : + ∑ x ∈ s, (if p ∧ q x then g x else 0) = + if p then ∑ x ∈ s, (if q x then g x else 0) else 0 := by + by_cases hp : p <;> simp [hp] + +theorem a_eq_aL (n : ℕ) : a n = aL n := by + simp only [a, valid_iff, sum_pull, sum_win_and, sum_win] + rw [sum_range_eq_lsum] + rfl + +/-- The definition reproduces all 38 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 38).map (fun i => a (i + 1)) = + [64, 729, 1682, 2729, 3776, 4823, 5870, 6917, 7964, 9011, 10058, 11105, 12152, 13199, 14246, + 15293, 16340, 17387, 18434, 19481, 20528, 21575, 22622, 23669, 24716, 25763, 26810, 27857, + 28904, 29951, 30998, 32045, 33092, 34139, 35186, 36233, 37280, 38327] := by + rw [show a = aL from funext a_eq_aL] + decide +kernel + +/-! ### The conjectures -/ + +/-- Conjecture (Hardin, A195249, "Empirical"): `a(n) = 1047 n - 1459` for every `n > 2`. -/ +def statement : Prop := ∀ n : ℕ, 2 < n → (a n : ℤ) = 1047 * n - 1459 + +/-- Barker's conjectured generating function: `∑_{n ≥ 1} a(n) x^n = +x (64 + 601 x + 288 x^2 + 94 x^3) / (1 - x)^2`, with the denominator cleared. -/ +def statementBarkerGF : Prop := + (1 - PowerSeries.X) ^ 2 * PowerSeries.mk (fun n => if n = 0 then (0 : ℤ) else a n) = + PowerSeries.X * (64 + 601 * PowerSeries.X + 288 * PowerSeries.X ^ 2 + 94 * PowerSeries.X ^ 3) + +/-- Barker's conjectured recurrence: `a(n) = 2 a(n-1) - a(n-2)` for every `n > 4`. -/ +def statementBarkerRec : Prop := + ∀ n : ℕ, 4 < n → (a n : ℤ) = 2 * a (n - 1) - a (n - 2) + +end Math0.Statements.A195249 diff --git a/lean/Math0/Statements/OEIS/A201060.lean b/lean/Math0/Statements/OEIS/A201060.lean new file mode 100644 index 0000000..be00115 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A201060.lean @@ -0,0 +1,212 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A201060: repdigits whose digital product is a repdigit + +Source: https://oeis.org/A201060, Jaroslav Krizek, Nov 26 2011 (COMMENTS section). Verbatim: +> Conjecture: a(n) is repunit for n >= 16. + +The entry's name is "Repdigit numbers with repdigit digital product." (offset `1`). Data: +`0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 111, 222, 1111, 11111, …, 1111111111111111111` +(31 terms, `n = 1, …, 31`). + +## Encoding + +* *Repdigits* (A010785, which starts with `0`): `IsRepdigit m` says that all decimal digits of + `m` (`Nat.digits 10 m`) are equal. `Nat.digits 10 0 = []`, so `0` is a repdigit, as in + A010785 and in this entry (`a(1) = 0`). +* *Digital product* (A007954): `digitProd m` is the product of the decimal digits of `m`, with + `digitProd 0 = 0` as in A007954 (the empty product would give `1`; both are repdigits, so + this choice does not affect the sequence). +* *The sequence.* `IsTerm m := IsRepdigit m ∧ IsRepdigit (digitProd m)`, and + `a n = Nat.nth IsTerm (n - 1)`: the `n`-th smallest term (offset `1`, so `a 1 = 0`). The set of + terms is infinite (every repunit is a term, `infinite_isTerm`), so `a` is strictly increasing + and lists all terms. `a` is noncomputable as written (`Nat.nth`). +* *Data check.* `rep d k = Nat.ofDigits 10 (replicate k d)` is the `k`-digit repdigit with digit + `d`. We prove that the repdigits below `10 ^ L` are exactly `0` and the `rep d k` with + `1 ≤ d ≤ 9`, `1 ≤ k ≤ L` (`isRepdigit_iff_mem_repList`). Filtering this explicit list for + `L = 19` gives the 31 listed terms (kernel-checked), and `map_nth_eq_of_filter` transfers this + to `Nat.nth`. All 31 listed terms are checked (`a_data`). +* *Repunits* (A002275): `IsRepunit m` says that all decimal digits of `m` are `1`, i.e. + `m = (10^k - 1)/9` for some `k ≥ 0` (A002275 includes `R_0 = 0`; this is irrelevant here since + `a n ≥ a 16 = 1111` for `n ≥ 16`). +* *The conjecture.* "a(n) is repunit for n >= 16" is `∀ n ≥ 16, IsRepunit (a n)`, with the + entry's offset `1` (`a 16 = 1111`). +-/ + +namespace Math0.Statements.A201060 + +/-! ### Definitions -/ + +/-- `m` is a repdigit (A010785): all its decimal digits are equal (`0` counts). -/ +def IsRepdigit (m : ℕ) : Prop := ∀ x ∈ Nat.digits 10 m, ∀ y ∈ Nat.digits 10 m, x = y + +instance : DecidablePred IsRepdigit := fun m => by unfold IsRepdigit; infer_instance + +/-- The digital product of `m` (A007954): the product of its decimal digits, `0` for `m = 0`. -/ +def digitProd (m : ℕ) : ℕ := if m = 0 then 0 else (Nat.digits 10 m).prod + +/-- `m` is a repdigit whose digital product is a repdigit. -/ +def IsTerm (m : ℕ) : Prop := IsRepdigit m ∧ IsRepdigit (digitProd m) + +instance : DecidablePred IsTerm := fun m => by unfold IsTerm; infer_instance + +/-- A201060: the `n`-th repdigit number with repdigit digital product, in increasing order +(offset `1`, `a 1 = 0`). -/ +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) + +/-- `m` is a repunit (A002275): all its decimal digits are `1`. -/ +def IsRepunit (m : ℕ) : Prop := ∀ d ∈ Nat.digits 10 m, d = 1 + +/-! ### The repdigits, explicitly -/ + +/-- The repdigit with `k` decimal digits, all equal to `d`. -/ +def rep (d k : ℕ) : ℕ := Nat.ofDigits 10 (List.replicate k d) + +theorem digits_rep {d : ℕ} (hd1 : 1 ≤ d) (hd9 : d ≤ 9) (k : ℕ) : + Nat.digits 10 (rep d k) = List.replicate k d := by + apply Nat.digits_ofDigits 10 (by norm_num) + · intro x hx + rw [List.eq_of_mem_replicate hx] + omega + · intro h + have := List.getLast_mem h + rw [List.eq_of_mem_replicate this] + omega + +/-- `0` and the repdigits `rep d k` with `1 ≤ d ≤ 9`, `1 ≤ k ≤ L`. -/ +def repList (L : ℕ) : List ℕ := + 0 :: (List.range L).flatMap fun k => (List.range 9).map fun d => rep (d + 1) (k + 1) + +theorem mem_repList {L m : ℕ} : + m ∈ repList L ↔ m = 0 ∨ ∃ k < L, ∃ d < 9, rep (d + 1) (k + 1) = m := by + simp only [repList, List.mem_cons, List.mem_flatMap, List.mem_range, List.mem_map] + +/-- The repdigits below `10 ^ L` are exactly the elements of `repList L`. -/ +theorem isRepdigit_iff_mem_repList {L m : ℕ} (hm : m < 10 ^ L) : + IsRepdigit m ↔ m ∈ repList L := by + rw [mem_repList] + constructor + · intro h + rcases Nat.eq_zero_or_pos m with rfl | hpos + · exact Or.inl rfl + right + have hne : Nat.digits 10 m ≠ [] := Nat.digits_ne_nil_iff_ne_zero.2 hpos.ne' + obtain ⟨d, l', hdl⟩ := List.exists_cons_of_ne_nil hne + have hdmem : d ∈ Nat.digits 10 m := by rw [hdl]; exact List.mem_cons_self + have hrep : Nat.digits 10 m = List.replicate (Nat.digits 10 m).length d := + List.eq_replicate_iff.2 ⟨rfl, fun b hb => h b hb d hdmem⟩ + have hd10 : d < 10 := Nat.digits_lt_base (by norm_num) hdmem + have hd0 : d ≠ 0 := by + have h1 := Nat.getLast_digit_ne_zero 10 hpos.ne' + rwa [h _ (List.getLast_mem _) d hdmem] at h1 + have hlen : (Nat.digits 10 m).length ≤ L := (Nat.digits_length_le_iff (by norm_num) m).2 hm + have hlen1 : 1 ≤ (Nat.digits 10 m).length := by rw [hdl]; simp + refine ⟨(Nat.digits 10 m).length - 1, by omega, d - 1, by omega, ?_⟩ + rw [Nat.sub_add_cancel hlen1, Nat.sub_add_cancel (by omega), rep, ← hrep, + Nat.ofDigits_digits] + · rintro (rfl | ⟨k, -, d, hd, rfl⟩) + · simp [IsRepdigit] + · intro x hx y hy + rw [digits_rep (by omega) (by omega)] at hx hy + rw [List.eq_of_mem_replicate hx, List.eq_of_mem_replicate hy] + +/-- Every repunit `rep 1 k` is a term (its digital product is `1` or `0`). -/ +theorem isTerm_rep_one (k : ℕ) : IsTerm (rep 1 k) := by + have hd := digits_rep (d := 1) le_rfl (by norm_num) k + refine ⟨?_, ?_⟩ + · intro x hx y hy + rw [hd] at hx hy + rw [List.eq_of_mem_replicate hx, List.eq_of_mem_replicate hy] + · unfold digitProd + split_ifs + · simp [IsRepdigit] + · rw [hd, List.prod_replicate, one_pow] + simp [IsRepdigit] + +/-- The sequence is infinite: it contains every repunit. -/ +theorem infinite_isTerm : (Set.ofPred IsTerm).Infinite := by + refine Set.infinite_of_not_bddAbove fun ⟨B, hB⟩ => ?_ + have h1 : B < rep 1 (B + 1) := by + have h2 : 10 ^ B ≤ rep 1 (B + 1) := by + rw [← Nat.lt_digits_length_iff (by norm_num), digits_rep le_rfl (by norm_num), + List.length_replicate] + omega + have h3 : B < 10 ^ B := Nat.lt_pow_self (by norm_num) + omega + have := hB (isTerm_rep_one (B + 1)) + omega + +/-! ### Sanity checks -/ + +/-- The elements `< N` satisfying `p`, in increasing order, are `nth p 0, nth p 1, …`. -/ +theorem filter_range_eq (p : ℕ → Prop) [DecidablePred p] (N : ℕ) : + (List.range N).filter (fun k => decide (p k)) = + (List.range (Nat.count p N)).map (Nat.nth p) := by + induction N with + | zero => simp + | succ N ih => + rw [List.range_succ, List.filter_append, ih, Nat.count_succ] + by_cases h : p N + · simp [h, List.range_succ, Nat.nth_count h] + · simp [h] + +theorem map_nth_eq_of_filter {p : ℕ → Prop} [DecidablePred p] {N K : ℕ} {L : List ℕ} + (h : (List.range N).filter (fun k => decide (p k)) = L) (hK : L.length = K) : + (List.range K).map (Nat.nth p) = L := by + rw [filter_range_eq] at h + subst h + simp only [List.length_map, List.length_range] at hK + rw [hK] + +/-- The 31 terms listed in OEIS. -/ +def listed : List ℕ := + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 111, 222, 1111, 11111, 111111, 1111111, 11111111, + 111111111, 1111111111, 11111111111, 111111111111, 1111111111111, 11111111111111, + 111111111111111, 1111111111111111, 11111111111111111, 111111111111111111, + 1111111111111111111] + +/-- Filtering the repdigits with at most 19 digits gives the listed terms (kernel-checked). -/ +theorem filter_repList : + (repList 19).filter (fun m => decide (IsRepdigit (digitProd m))) = listed := by + decide +kernel + +theorem repList_lt : ∀ m ∈ repList 19, m < 10 ^ 19 := by + decide +kernel + +theorem listed_pairwise : listed.Pairwise (· < ·) := by + decide +kernel + +/-- The terms below `10 ^ 19`, in increasing order, are the listed terms. -/ +theorem filter_range_isTerm : + (List.range (10 ^ 19)).filter (fun k => decide (IsTerm k)) = listed := by + refine List.Pairwise.eq_of_mem_iff (r := (· < ·)) (List.pairwise_lt_range.filter _) + listed_pairwise fun m => ?_ + rw [← filter_repList, List.mem_filter, List.mem_filter, List.mem_range, decide_eq_true_iff, + decide_eq_true_iff, IsTerm] + constructor + · rintro ⟨hm, h1, h2⟩ + exact ⟨(isRepdigit_iff_mem_repList hm).1 h1, h2⟩ + · rintro ⟨h1, h2⟩ + have hm := repList_lt m h1 + exact ⟨hm, (isRepdigit_iff_mem_repList hm).2 h1, h2⟩ + +/-- The definition reproduces all 31 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 31).map (fun i => a (i + 1)) = + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 111, 222, 1111, 11111, 111111, 1111111, 11111111, + 111111111, 1111111111, 11111111111, 111111111111, 1111111111111, 11111111111111, + 111111111111111, 1111111111111111, 11111111111111111, 111111111111111111, + 1111111111111111111] := by + have : (fun i => a (i + 1)) = Nat.nth IsTerm := funext fun i => by simp [a] + rw [this] + exact map_nth_eq_of_filter filter_range_isTerm rfl + +/-! ### The conjecture -/ + +/-- Conjecture (Krizek, A201060): `a(n)` is a repunit for every `n ≥ 16`. -/ +def statement : Prop := ∀ n : ℕ, 16 ≤ n → IsRepunit (a n) + +end Math0.Statements.A201060 diff --git a/lean/Math0/Statements/OEIS/A209802.lean b/lean/Math0/Statements/OEIS/A209802.lean new file mode 100644 index 0000000..ec6c677 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A209802.lean @@ -0,0 +1,137 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A209802: positivity of the exponential Mertens function + +Source: https://oeis.org/A209802, _Reinhard Zumkeller_, Mar 13 2012. Verbatim (COMMENTS): +> Analog of Mertens's function, A002321; conjecture: a(n) > 0. + +The entry's name is "Partial sums of exponential Möbius function, A166234." (offset `1`). +A166234 is "The inverse of the constant 1 function under the exponential convolution (also +called the exponential Möbius function)", with the formula "Multiplicative, a(p^e) = mu(e) for +any prime power p^e (e>=1), where mu is the Möbius function A008683." (offset `1`). + +## Encoding + +* `muE n` is the exponential Möbius function `μ⁽ᵉ⁾(n) = ∏_{p^e ∥ n} μ(e)`, written with Mathlib's + `Nat.factorization` and `ArithmeticFunction.moebius`: the product over the prime factors `p` + of `n` of `μ` of the exponent of `p` in `n`. For `n = 1` it is the empty product `1`, as for any + multiplicative function. (`muE 0 = 1` is never used.) +* `a n = ∑_{k=1}^{n} muE k` (OEIS offset `1`; `a 0 = 0` is the empty sum and is not a term of + the sequence). The values are integers, so `a` is `ℤ`-valued: the sequence carries the keyword + `nonn` only because of the very conjecture formalized here. +* `muE` and `a` are computable, but `Nat.factorization` and `moebius` do not reduce well in the + kernel. For the kernel-checked data we therefore use a trial-division copy `aC` (prime divisors + found by scanning `0, …, n`, exponents via `Nat.findGreatest`, `μ` via its values on prime + powers) and prove `a = aC` (`a_eq_aC`) before running `decide +kernel`. +* The conjecture "a(n) > 0" is read for every index `n ≥ 1` of the sequence. +-/ + +namespace Math0.Statements.A209802 + +open ArithmeticFunction Finset + +/-- The exponential Möbius function A166234: multiplicative with `μ⁽ᵉ⁾(p ^ e) = μ(e)`, i.e. +`μ⁽ᵉ⁾(n) = ∏_{p ∣ n prime} μ(v_p(n))`, where `v_p(n) = n.factorization p` is the exponent of +`p` in `n`. -/ +def muE (n : ℕ) : ℤ := n.factorization.prod fun _ e => moebius e + +/-- A209802: partial sums `a(n) = ∑_{k=1}^{n} μ⁽ᵉ⁾(k)` of the exponential Möbius function +(offset `1`). -/ +def a (n : ℕ) : ℤ := ∑ k ∈ Icc 1 n, muE k + +/-! ### A kernel-friendly copy of the definition -/ + +/-- The exponent of `p` in `n` (for `p` prime, `n ≥ 1`): the largest `j ≤ n` with `p ^ j ∣ n`. -/ +def expo (p n : ℕ) : ℕ := Nat.findGreatest (fun j => p ^ j ∣ n) n + +/-- The prime divisors of `n`, found by scanning `0, …, n`. -/ +def primeDivs (n : ℕ) : Finset ℕ := (range (n + 1)).filter fun p => p ∣ n ∧ p.Prime + +/-- `∏_{p ∣ n prime} g (v_p(n))`, computed by trial division. -/ +def prodPF (g : ℕ → ℤ) (n : ℕ) : ℤ := ∏ p ∈ primeDivs n, g (expo p n) + +/-- The Möbius function, computed from its values `μ(p) = -1`, `μ(p ^ e) = 0` (`e ≥ 2`) on prime +powers. -/ +def mobC (e : ℕ) : ℤ := if e = 0 then 0 else prodPF (fun f => if f = 1 then -1 else 0) e + +/-- Trial-division copy of `muE`. -/ +def muEC (n : ℕ) : ℤ := prodPF mobC n + +/-- Trial-division copy of `a`. -/ +def aC (n : ℕ) : ℤ := ∑ k ∈ Icc 1 n, muEC k + +theorem primeDivs_eq {n : ℕ} (hn : n ≠ 0) : primeDivs n = n.primeFactors := by + ext p + simp only [primeDivs, mem_filter, mem_range, Nat.mem_primeFactors] + constructor + · rintro ⟨-, hd, hp⟩ + exact ⟨hp, hd, hn⟩ + · rintro ⟨hp, hd, -⟩ + exact ⟨Nat.lt_succ_of_le (Nat.le_of_dvd (Nat.pos_of_ne_zero hn) hd), hd, hp⟩ + +theorem expo_eq {p n : ℕ} (hp : p.Prime) (hn : n ≠ 0) : expo p n = n.factorization p := by + unfold expo + rw [Nat.findGreatest_eq_iff] + refine ⟨(Nat.factorization_lt p hn).le, fun _ => (hp.pow_dvd_iff_le_factorization hn).2 le_rfl, + ?_⟩ + intro j hj _ hd + exact absurd ((hp.pow_dvd_iff_le_factorization hn).1 hd) (not_le.2 hj) + +theorem prod_factorization_eq_prodPF (g : ℕ → ℤ) {n : ℕ} (hn : n ≠ 0) : + (n.factorization.prod fun _ e => g e) = prodPF g n := by + rw [Finsupp.prod, Nat.support_factorization, prodPF, primeDivs_eq hn] + refine prod_congr rfl fun p hp => ?_ + rw [expo_eq (Nat.prime_of_mem_primeFactors hp) hn] + +theorem moebius_eq_mobC (e : ℕ) : moebius e = mobC e := by + rcases eq_or_ne e 0 with rfl | he + · simp [mobC] + rw [IsMultiplicative.multiplicative_factorization moebius isMultiplicative_moebius he, mobC, + if_neg he, ← prod_factorization_eq_prodPF _ he, Finsupp.prod, Finsupp.prod] + refine prod_congr rfl fun p hp => ?_ + have hp' := Nat.prime_of_mem_primeFactors hp + exact moebius_apply_prime_pow hp' + (hp'.factorization_pos_of_dvd he (Nat.dvd_of_mem_primeFactors hp)).ne' + +theorem muE_eq_muEC (n : ℕ) : muE n = muEC n := by + rcases eq_or_ne n 0 with rfl | hn + · rw [show muEC 0 = 1 by decide] + simp [muE] + · unfold muE muEC + simp_rw [moebius_eq_mobC] + exact prod_factorization_eq_prodPF mobC hn + +theorem a_eq_aC : a = aC := funext fun _ => sum_congr rfl fun k _ => muE_eq_muEC k + +/-! ### Sanity checks -/ + +/-- `muE` reproduces the 91 terms of A166234 listed in OEIS (kernel-checked). -/ +theorem muE_data : (List.range 91).map (fun i => muE (i + 1)) = + [1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 0, 1, -1, 1, -1, 1, 1, 1, -1, -1, 1, -1, + -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 0, -1, -1, 1, -1, 1, -1, + 1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, 1, 1, 0, 0, 1, + 1, -1, 1, 1, 1, -1, 1, -1, 1] := by + rw [show muE = muEC from funext muE_eq_muEC] + decide +kernel + +/-- The definition reproduces all 72 terms of A209802 listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 72).map (fun i => a (i + 1)) = + [1, 2, 3, 2, 3, 4, 5, 4, 3, 4, 5, 4, 5, 6, 7, 7, 8, 7, 8, 7, 8, 9, 10, 9, 8, 9, 8, 7, 8, 9, + 10, 9, 10, 11, 12, 13, 14, 15, 16, 15, 16, 17, 18, 17, 16, 17, 18, 18, 17, 16, 17, 16, 17, + 16, 17, 16, 17, 18, 19, 18, 19, 20, 19, 20, 21, 22, 23, 22, 23, 24, 25, 26] := by + rw [a_eq_aC] + decide +kernel + +/-- The values `a(10) = 4` and `a(100) = 34` from the entry's comment (kernel-checked). -/ +theorem a_ten_hundred : a 10 = 4 ∧ a 100 = 34 := by + rw [a_eq_aC] + decide +kernel + +/-- Conjecture (Zumkeller, A209802): `a(n) > 0` for every `n ≥ 1`. -/ +def statement : Prop := ∀ n : ℕ, 1 ≤ n → 0 < a n + +end Math0.Statements.A209802 diff --git a/lean/Math0/Statements/OEIS/A211343.lean b/lean/Math0/Statements/OEIS/A211343.lean new file mode 100644 index 0000000..98a6255 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A211343.lean @@ -0,0 +1,162 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A211343: smallest parts of partitions into consecutive parts + +Source: https://oeis.org/A211343, Omar E. Pol, Apr 30 2017 (COMMENTS section). Verbatim: +> Conjecture 1: T(n,k) is the smallest part of the partition of n into k consecutive parts, if +> T(n,k) > 0. +> Conjecture 2: the last positive integer in the row n is in the column A109814(n). + +The entry (Omar E. Pol, Feb 05 2013; offset `1`, keyword `tabf`) is "Triangle read by rows: +T(n,k), n >= 1, k >= 1, in which column k lists the positive integers interleaved with k-1 zeros, +and the first element of column k is in row k(k+1)/2." Row `n` has length A003056(n), the +largest `k` with `k(k+1)/2 ≤ n`. + +A109814 (David W. Wilson) is "a(n) is the largest k such that n can be written as sum of k +consecutive positive integers." (offset `1`). + +## Encoding + +* *Columns.* `column k j` is the `j`-th entry (`j = 0, 1, 2, …`) of column `k` counted from its + first row: the positive integers interleaved with `k - 1` zeros, i.e. `1, 0^(k-1), 2, 0^(k-1), + 3, …`, so `column k j = j / k + 1` if `k ∣ j` and `0` otherwise. +* *The triangle.* Column `k ≥ 1` begins in row `k(k+1)/2`, so row `n` contains exactly the + columns `k` with `1 ≤ k` and `k(k+1)/2 ≤ n` (`InRow n k`), and + `T n k = column k (n - k(k+1)/2)` for those. Outside the triangle `T n k = 0` (a junk value; + the statement never uses it). `row n` lists `T(n,1), …, T(n, A003056(n))` (all columns of row + `n` are `≤ n`, `le_of_inRow`), and `a` is the triangle read by rows with offset `1` + (`a i` is the `i`-th entry of the concatenation of rows `1, 2, …`; `a 0 = 0` is junk). + `a_data` checks all 94 listed terms (rows `1..24`) in the kernel. +* *Partitions into consecutive parts.* A partition of `n` is Mathlib's `Nat.Partition n` (a + multiset of positive integers summing to `n`). It is a partition into `k` consecutive parts + (`HasConsecutiveParts k p`) if its multiset of parts is `{m, m+1, …, m+k-1}` for some `m`. + "The partition" is read as: such a partition exists, and every such partition has smallest + part `T(n,k)` (the partition is in fact unique, being determined by `k` and `n`); the + smallest part of `p` is expressed as `IsLeast {x | x ∈ p.parts}`. +* *A109814.* `IsConsecSum n k` says that `n = m + (m+1) + … + (m+k-1)` for some `m ≥ 1`. + `A109814 n` is computed as `Nat.findGreatest` of this property with the search for `k` and `m` + bounded by `n`; `A109814_isGreatest` proves that for `n ≥ 1` it is the largest `k` with + `IsConsecSum n k` (the unbounded OEIS definition), and `A109814_data` checks the first 40 + listed terms in the kernel. +* *Conjecture 1* (first conjunct of `statement`): for all `n ≥ 1` and all columns `k` of row `n` + (`1 ≤ k`, `k(k+1)/2 ≤ n`) with `T(n,k) > 0`, there is a partition of `n` into `k` consecutive + parts, and `T(n,k)` is the smallest part of every such partition. Only the direction stated + ("if T(n,k) > 0") is claimed. +* *Conjecture 2* (second conjunct): for all `n ≥ 1`, the column of the last positive entry of + row `n` is `A109814(n)`, i.e. `A109814 n` is the greatest `k` among the columns of row `n` + with `T(n,k) > 0` (so column `A109814 n` belongs to row `n`, its entry is positive, and every + later entry of row `n` is `0`). +-/ + +namespace Math0.Statements.A211343 + +open Finset + +/-- Column `k` read from its first row: the positive integers interleaved with `k - 1` zeros, +`1, 0, …, 0, 2, 0, …, 0, 3, …`. -/ +def column (k j : ℕ) : ℕ := if j % k = 0 then j / k + 1 else 0 + +/-- Row `n` of the triangle has an entry in column `k` iff `k ≥ 1` and column `k` has started, +i.e. its first row `k(k+1)/2` is `≤ n`. -/ +def InRow (n k : ℕ) : Prop := 1 ≤ k ∧ k * (k + 1) / 2 ≤ n + +instance (n k : ℕ) : Decidable (InRow n k) := by unfold InRow; infer_instance + +/-- The triangle `T(n,k)`: column `k` lists the positive integers interleaved with `k - 1` +zeros and starts in row `k(k+1)/2` (junk value `0` outside the triangle). -/ +def T (n k : ℕ) : ℕ := if InRow n k then column k (n - k * (k + 1) / 2) else 0 + +/-- Every column of row `n` has index at most `n`. -/ +theorem le_of_inRow {n k : ℕ} (h : InRow n k) : k ≤ n := by + obtain ⟨h1, h2⟩ := h + have : k ≤ k * (k + 1) / 2 := by + rw [Nat.le_div_iff_mul_le (by norm_num)] + nlinarith + omega + +/-- Row `n` of the triangle: `T(n,1), …, T(n, A003056(n))`. -/ +def row (n : ℕ) : List ℕ := ((List.range (n + 1)).filter (fun k => decide (InRow n k))).map (T n) + +/-- A211343: the triangle read by rows, offset `1` (`a 0 = 0` is junk). -/ +def a (i : ℕ) : ℕ := ((List.range i).flatMap (fun j => row (j + 1))).getD (i - 1) 0 + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all 94 listed +terms, i.e. rows `1` to `24`. -/ +theorem a_data : (List.range 94).map (fun i => a (i + 1)) = + [1, 2, 3, 1, 4, 0, 5, 2, 6, 0, 1, 7, 3, 0, 8, 0, 0, 9, 4, 2, 10, 0, 0, 1, 11, 5, 0, 0, 12, 0, + 3, 0, 13, 6, 0, 0, 14, 0, 0, 2, 15, 7, 4, 0, 1, 16, 0, 0, 0, 0, 17, 8, 0, 0, 0, 18, 0, 5, 3, + 0, 19, 9, 0, 0, 0, 20, 0, 0, 0, 2, 21, 10, 6, 0, 0, 1, 22, 0, 0, 4, 0, 0, 23, 11, 0, 0, 0, + 0, 24, 0, 7, 0, 0, 0] := by + decide +kernel + +/-- The same data, row by row (rows `1` to `24`), matching the example in the entry. -/ +theorem row_data : (List.range 24).map (fun n => row (n + 1)) = + [[1], [2], [3, 1], [4, 0], [5, 2], [6, 0, 1], [7, 3, 0], [8, 0, 0], [9, 4, 2], [10, 0, 0, 1], + [11, 5, 0, 0], [12, 0, 3, 0], [13, 6, 0, 0], [14, 0, 0, 2], [15, 7, 4, 0, 1], + [16, 0, 0, 0, 0], [17, 8, 0, 0, 0], [18, 0, 5, 3, 0], [19, 9, 0, 0, 0], [20, 0, 0, 0, 2], + [21, 10, 6, 0, 0, 1], [22, 0, 0, 4, 0, 0], [23, 11, 0, 0, 0, 0], [24, 0, 7, 0, 0, 0]] := by + decide +kernel + +/-- A partition `p` of `n` is a partition into `k` consecutive parts: its parts are +`m, m+1, …, m+k-1` for some `m`. -/ +def HasConsecutiveParts {n : ℕ} (k : ℕ) (p : n.Partition) : Prop := + ∃ m, p.parts = (Multiset.range k).map (fun i => m + i) + +/-- `n` can be written as the sum of `k` consecutive positive integers +`m + (m+1) + … + (m+k-1)`, `m ≥ 1`. -/ +def IsConsecSum (n k : ℕ) : Prop := ∃ m, 0 < m ∧ ∑ i ∈ range k, (m + i) = n + +/-- `IsConsecSum n k` with the start `m` searched in `[1, n]` (decidable). -/ +def IsConsecSumBdd (n k : ℕ) : Prop := ∃ m ∈ Finset.Icc 1 n, ∑ i ∈ Finset.range k, (m + i) = n + +instance (n : ℕ) : DecidablePred (IsConsecSumBdd n) := fun k => by + unfold IsConsecSumBdd; infer_instance + +/-- A109814: the largest `k` such that `n` can be written as the sum of `k` consecutive positive +integers (computed with `k ≤ n` and `m ≤ n`; see `A109814_isGreatest`). -/ +def A109814 (n : ℕ) : ℕ := Nat.findGreatest (IsConsecSumBdd n) n + +/-- For `n ≥ 1`, `A109814 n` is the largest `k` such that `n` is the sum of `k` consecutive +positive integers, as in the OEIS definition (no bound on `k` or `m`). -/ +theorem A109814_isGreatest {n : ℕ} (hn : 1 ≤ n) : + IsGreatest {k | IsConsecSum n k} (A109814 n) := by + constructor + · have h1 : IsConsecSumBdd n 1 := ⟨n, by simp [hn], by simp⟩ + obtain ⟨m, hm, hs⟩ := Nat.findGreatest_spec (P := IsConsecSumBdd n) hn h1 + exact ⟨m, (Finset.mem_Icc.1 hm).1, hs⟩ + · rintro k ⟨m, hm, hs⟩ + have hk : k ≤ n := by + have : ∑ _i ∈ range k, 1 ≤ ∑ i ∈ range k, (m + i) := + Finset.sum_le_sum (fun i _ => by omega) + simpa [hs] using this + have hk1 : 0 < k := by + rcases Nat.eq_zero_or_pos k with rfl | h + · simp at hs; omega + · exact h + have hmn : m ≤ n := by + have := Finset.single_le_sum (f := fun i => m + i) (fun i _ => Nat.zero_le _) + (Finset.mem_range.2 hk1) + simp only [add_zero] at this + omega + exact Nat.le_findGreatest hk ⟨m, Finset.mem_Icc.2 ⟨hm, hmn⟩, hs⟩ + +/-- A109814 reproduces its first 40 listed terms (kernel-checked). -/ +theorem A109814_data : (List.range 40).map (fun i => A109814 (i + 1)) = + [1, 1, 2, 1, 2, 3, 2, 1, 3, 4, 2, 3, 2, 4, 5, 1, 2, 4, 2, 5, 6, 4, 2, 3, 5, 4, 6, 7, 2, 5, 2, + 1, 6, 4, 7, 8, 2, 4, 6, 5] := by + decide +kernel + +/-- Conjecture 1: if `T(n,k) > 0` (for an entry of the triangle), then `T(n,k)` is the smallest +part of the partition of `n` into `k` consecutive parts. Conjecture 2: the last positive entry +of row `n` is in column `A109814(n)`. -/ +def statement : Prop := + (∀ n k : ℕ, 1 ≤ n → InRow n k → 0 < T n k → + (∃ p : n.Partition, HasConsecutiveParts k p) ∧ + ∀ p : n.Partition, HasConsecutiveParts k p → IsLeast {x | x ∈ p.parts} (T n k)) ∧ + (∀ n : ℕ, 1 ≤ n → IsGreatest {k | InRow n k ∧ 0 < T n k} (A109814 n)) + +end Math0.Statements.A211343 diff --git a/lean/Math0/Statements/OEIS/A215010.lean b/lean/Math0/Statements/OEIS/A215010.lean new file mode 100644 index 0000000..e54dfa3 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A215010.lean @@ -0,0 +1,165 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A215010: equiangular convex polygons with sides in arithmetic progression + +Source: https://oeis.org/A215010, Robin Garcia, Jul 31 2012. Verbatim: +> Conjecture: hexagons are the only simple convex polygons with equal interior angles with +> such property, due to the fact that cos(Pi/3) = 1/2. + +The "property" is the one in the entry's name: "Integer side lengths in arithmetic progression +of simple convex hexagons with equal interior angles. Sequence gives the values of m for sides +of lengths t+m*d, counterclockwise, for the two primitive solutions." So the `N` sides of the +polygon are the `N` terms `t, t+d, …, t+(N-1)d` of an arithmetic progression of positive +integers, in some order. + +## Encoding + +*Polygons.* A simple convex polygon with equal interior angles, traversed counterclockwise, +turns by the same exterior angle `2π/N` at each vertex. After a rotation its `k`-th edge vector +is `s k • ζ ^ k` with `ζ = exp (2πi/N)`, so it closes up iff `∑ k, s k • ζ ^ k = 0`. +Conversely, for positive lengths `s` with `∑ k, s k • ζ ^ k = 0` the closed path with vertices +`P j = ∑ k < j, s k • ζ ^ k` turns left by `2π/N` at every vertex (total turning `2π`). It is +therefore a simple convex polygon with every interior angle equal to `(N-2)π/N`. So an +equiangular simple convex `N`-gon with consecutive sides `s 0, …, s (N-1)` exists iff +`3 ≤ N`, every `s k > 0` and `∑ k, s k • ζ ^ k = 0`. This is `IsEquiangularPolygon`. + +*Arithmetic progressions.* Integer side lengths forming an arithmetic progression are +`t + m d` for `m = 0, …, N-1`, in the order given by a permutation `σ` of `Fin N`. We take +`t, d : ℕ` with `d ≥ 1`. A negative difference is the same set read backwards. `d = 0` is +excluded: the sides would all be equal, regular polygons exist for every `N`, and the +conjecture would be trivially false; the entry's solutions all use distinct values of `m`. +Positivity of the sides (so `t ≥ 1`) is part of `IsEquiangularPolygon`. + +*Reading of "only".* `statement` is the uniqueness claim: every such polygon is a hexagon. +That hexagons do have the property is the content of the sequence itself (data below). + +*The sequence.* The data `0,5,1,3,2,4,0,5,2,1,4,3` (offset 1) are the two primitive +solutions `m = (0,5,1,3,2,4)` and `(0,5,2,1,4,3)` concatenated. For `N = 6` we have +`∑ k, (t + m k d) ζ ^ k = d ∑ k, m k ζ ^ k` because `∑ k, ζ ^ k = 0`, so whether the hexagon +closes depends only on the pattern `m`. With `ζ = exp (iπ/3)`, `2 Re ζ ^ k = 2,1,-1,-2,-1,1` and +`(2/√3) Im ζ ^ k = 0,1,1,0,-1,-1` for `k = 0, …, 5`. So `∑ m k ζ ^ k = 0` iff the two integer +dot products `hexCos ⬝ m` and `hexSin ⬝ m` vanish (`hexCloses`). `hexCloses_iff` proves this +equivalence with the closing condition of `IsEquiangularPolygon` for `N = 6`, and an example +checks the entry's hexagon `(1,6,2,4,3,5)` against `IsEquiangularPolygon`. Patterns related by the +dihedral symmetries of the hexagon (rotation and reading direction) give the same hexagon up to +congruence. The entry's normal form starts at the shortest side (`m 0 = 0`) and continues +toward the longer of its two neighbours (`m 1 > m 5`). For example, the comment's hexagon +`(2,6,4,5,3,7)` is written as `(2,7,3,5,4,6)`, i.e. `m = (0,5,1,3,2,4)`. The two normal forms +are listed in lexicographic order. `a n` for `n` outside `1..12` is `0` (the sequence is +finite, keyword `fini`). +-/ + +namespace Math0.Statements.A215010 + +/-- All orderings of the list `l`, generated in lexicographic order when `l` is sorted +(`fuel` should be `l.length`; it only makes the recursion structural). -/ +def lexPerms : ℕ → List ℕ → List (List ℕ) + | 0, _ => [[]] + | fuel + 1, l => l.flatMap fun x => (lexPerms fuel (l.erase x)).map (x :: ·) + +/-- `2 cos (k π / 3)` for `k = 0, …, 5`: twice the real part of `exp (iπ/3) ^ k`. -/ +def hexCos : List ℤ := [2, 1, -1, -2, -1, 1] + +/-- `(2/√3) sin (k π / 3)` for `k = 0, …, 5`: the imaginary part of `exp (iπ/3) ^ k`, +times `2/√3`. -/ +def hexSin : List ℤ := [0, 1, 1, 0, -1, -1] + +/-- Integer dot product of a coefficient list with a list of naturals. -/ +def dot (c : List ℤ) (m : List ℕ) : ℤ := (List.zipWith (fun x y => x * (y : ℤ)) c m).sum + +/-- The equiangular hexagon with consecutive sides `t + m k * d` (`d > 0`) closes up, i.e. +`∑ k, m k * exp (iπ/3) ^ k = 0` (real and imaginary parts, rescaled to integers). -/ +def hexCloses (m : List ℕ) : Bool := dot hexCos m == 0 && dot hexSin m == 0 + +/-- The entry's normal form under the dihedral symmetries of the hexagon: start at the shortest +side (`m 0 = 0`) and go toward the longer neighbour (`m 1 > m 5`). -/ +def normalForm (m : List ℕ) : Bool := m.getD 0 0 == 0 && m.getD 5 0 < m.getD 1 0 + +/-- The primitive solutions: orderings `m` of `0, …, 5` such that the equiangular hexagon with +sides `t + m k * d`, counterclockwise, closes up, in normal form, in lexicographic order. -/ +def primitiveSolutions : List (List ℕ) := + (lexPerms 6 (List.range 6)).filter fun m => hexCloses m && normalForm m + +/-- A215010 (offset 1): the values of `m` for sides of lengths `t + m*d`, counterclockwise, of +the two primitive solutions (integer side lengths in arithmetic progression of simple convex +hexagons with equal interior angles), concatenated. `0` outside the 12 listed terms. -/ +def a (n : ℕ) : ℕ := primitiveSolutions.flatten.getD (n - 1) 0 + +/-- The definition reproduces all 12 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 12).map (fun i => a (i + 1)) = [0, 5, 1, 3, 2, 4, 0, 5, 2, 1, 4, 3] := by + decide +kernel + +/-- There are exactly two primitive solutions, so the sequence has exactly 12 terms. -/ +theorem primitiveSolutions_length : primitiveSolutions.length = 2 := by + decide +kernel + +/-- Direction of the `k`-th edge of an equiangular `N`-gon traversed counterclockwise: +`exp (2πi k / N)` (every exterior angle is `2π/N`). -/ +noncomputable def edgeDir (N k : ℕ) : ℂ := Complex.exp (2 * Real.pi * Complex.I * k / N) + +/-- A simple convex `N`-gon with equal interior angles whose consecutive sides, counterclockwise, +have lengths `s 0, …, s (N-1)` exists: `N ≥ 3`, all sides are positive, and the edge vectors +`s k • exp (2πi k / N)` sum to zero (see the module docstring for the equivalence). -/ +def IsEquiangularPolygon (N : ℕ) (s : Fin N → ℕ) : Prop := + 3 ≤ N ∧ (∀ k, 0 < s k) ∧ ∑ k : Fin N, (s k : ℂ) * edgeDir N k = 0 + +/-! ### Sanity checks linking `IsEquiangularPolygon` to `hexCloses` -/ + +/-- `exp (2πi/6) = 1/2 + (√3/2) i`. -/ +theorem edgeDir_six_one : edgeDir 6 1 = 1 / 2 + (Real.sqrt 3 / 2 : ℝ) * Complex.I := by + unfold edgeDir + have : (2 * Real.pi * Complex.I * ((1 : ℕ) : ℂ) / ((6 : ℕ) : ℂ)) = + ((Real.pi / 3 : ℝ) : ℂ) * Complex.I := by + push_cast; ring + rw [this, Complex.exp_mul_I, ← Complex.ofReal_cos, ← Complex.ofReal_sin, Real.cos_pi_div_three, + Real.sin_pi_div_three] + push_cast; ring + +theorem edgeDir_six (k : ℕ) : edgeDir 6 k = edgeDir 6 1 ^ k := by + unfold edgeDir + rw [← Complex.exp_nat_mul]; congr 1; push_cast; ring + +/-- For hexagons, the closing condition of `IsEquiangularPolygon` is exactly `hexCloses`. -/ +theorem hexCloses_iff (m : Fin 6 → ℕ) : + ∑ k : Fin 6, (m k : ℂ) * edgeDir 6 k = 0 ↔ hexCloses (List.ofFn m) = true := by + set ζ := edgeDir 6 1 with hζ + have hs : Real.sqrt 3 ^ 2 = 3 := Real.sq_sqrt (by norm_num) + have h2 : ζ ^ 2 = ζ - 1 := by + rw [hζ, edgeDir_six_one] + apply Complex.ext <;> simp [pow_two] <;> nlinarith [hs] + have hsum : ∑ k : Fin 6, (m k : ℂ) * edgeDir 6 k = + (((m 0 : ℤ) - m 2 - m 3 + m 5 : ℤ) : ℂ) + (((m 1 : ℤ) + m 2 - m 4 - m 5 : ℤ) : ℂ) * ζ := by + simp only [Fin.sum_univ_six, edgeDir_six, ← hζ] + have h3 : ζ ^ 3 = -1 := by linear_combination (ζ + 1) * h2 + have h4 : ζ ^ 4 = -ζ := by linear_combination (ζ ^ 2 + ζ) * h2 + have h5 : ζ ^ 5 = 1 - ζ := by linear_combination (ζ ^ 3 + ζ ^ 2 - 1) * h2 + simp only [Fin.val_zero, Fin.val_one, Fin.val_two] + push_cast + simp only [show ((3 : Fin 6) : ℕ) = 3 from rfl, show ((4 : Fin 6) : ℕ) = 4 from rfl, + show ((5 : Fin 6) : ℕ) = 5 from rfl] + linear_combination (m 2 : ℂ) * h2 + (m 3 : ℂ) * h3 + (m 4 : ℂ) * h4 + (m 5 : ℂ) * h5 + rw [hsum, hζ, edgeDir_six_one] + simp [hexCloses, dot, hexCos, hexSin, List.ofFn_succ, Complex.ext_iff] + rw [← Int.cast_eq_zero (α := ℝ), ← Int.cast_eq_zero (α := ℝ)] + push_cast + constructor <;> rintro ⟨h1, h2⟩ <;> constructor <;> linarith + +/-- The OEIS example `t = d = 1`, sides `(1, 6, 2, 4, 3, 5)` counterclockwise, is an +equiangular hexagon in the sense of `IsEquiangularPolygon`. -/ +example : IsEquiangularPolygon 6 (fun k => 1 + (![0, 5, 1, 3, 2, 4] : Fin 6 → ℕ) k * 1) := by + refine ⟨by norm_num, fun _ => by positivity, ?_⟩ + rw [hexCloses_iff] + decide + +/-- Conjecture (Robin Garcia, 2012): hexagons are the only simple convex polygons with equal +interior angles whose integer side lengths are the terms `t, t+d, …, t+(N-1)d` (`d ≥ 1`) of an +arithmetic progression, in some order `σ`. -/ +def statement : Prop := + ∀ (N t d : ℕ), 1 ≤ d → ∀ σ : Equiv.Perm (Fin N), + IsEquiangularPolygon N (fun k => t + (σ k : ℕ) * d) → N = 6 + +end Math0.Statements.A215010 diff --git a/lean/Math0/Statements/OEIS/A223395.lean b/lean/Math0/Statements/OEIS/A223395.lean new file mode 100644 index 0000000..780d6d5 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A223395.lean @@ -0,0 +1,242 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A223395: walks on the 4 × 4 grid graph (n × 1 arrays) + +Source: https://oeis.org/A223395, _R. H. Hardin_, Mar 19 2013 (Barker's conjectures added +Aug 20 2018). Verbatim (FORMULA section): +> Empirical: a(n) = 3*a(n-1) + 2*a(n-2) - 4*a(n-3). +> Conjectures from _Colin Barker_, Aug 20 2018: (Start) +> G.f.: 8*x*(2 - 3*x^2) / ((1 - x)*(1 - 2*x - 4*x^2)). +> a(n) = (8 + (11-5*sqrt(5))*(1-sqrt(5))^n + (1+sqrt(5))^n*(11+5*sqrt(5))) / 5. +> (End) + +The entry's name: "4 X 4 square grid graph coloring a rectangular array: number of n X 1 0..15 +arrays where 0..15 label nodes of the square grid graph and every array movement to a horizontal +or vertical neighbor moves along an edge of this graph." Offset `1`. + +## Encoding + +* The nodes `0..15` are `Fin 16`; node `k` sits in row `k / 4` and column `k % 4` of the 4 × 4 + grid, and two nodes are adjacent (`Adj`) iff they are horizontal or vertical neighbours in the + grid. `adj_iff_entry` checks (in the kernel) that this is exactly the neighbour list printed in + the entry's EXAMPLE section ("0 -> 1 4", "1 -> 0 2 5", ..., "15 -> 14 11"). +* An `n X 1` array is a single column of `n` entries, encoded as `f : Fin n → Fin 16` (entry in + row `i` is `f i`). It has no horizontal neighbours, and its vertical neighbours are the entries + in rows `i` and `i + 1`; since the grid graph is undirected (`Adj` is symmetric, so moving down + or up gives the same condition) and loopless, the condition is `Valid f`: `Adj (f i) (f (i+1))` + for all consecutive rows. `a n` is the number of valid + columns (`Fintype.card`), i.e. the number of walks with `n` vertices in the grid graph. + The OEIS offset is `1`; `a 0 = 1` (the empty array) is not a term of the sequence. +* The kernel cannot enumerate `16^n` columns, so the data check goes through the transfer-matrix + version `aL` (a list-based dynamic programme on `cnt n v`, the number of valid columns with + `n + 1` entries and top entry `v`), proved equal to `a` for every `n` (`a_eq_aL`); `a_data` + then checks all 24 listed terms `a(1..24)` with `decide +kernel`. +* Hardin's recurrence has no stated range; with offset `1` it is read for every `n ≥ 4` (the + first `n` for which `a(n-3)` is a term). It is stated in `ℤ` because of the subtraction + (`statementRec`). +* Barker's g.f. is the formal power series `∑_{n ≥ 1} a(n) x^n` over `ℤ`; it is stated after + clearing the denominator `(1 - x)(1 - 2x - 4x^2)`, which has constant term `1` and is therefore + a unit in `ℤ⟦X⟧`, so this is equivalent (`statementGF`). +* Barker's closed form is stated in `ℝ` for every term, i.e. every `n ≥ 1` (`statementClosedForm`). +* `statement` is the conjunction of the three conjectures recorded in the entry. +-/ + +namespace Math0.Statements.A223395 + +/-- Adjacency in the 4 × 4 square grid graph on nodes `0..15`, node `k` being in row `k / 4` and +column `k % 4`: two nodes are adjacent iff they are horizontal or vertical neighbours. -/ +def Adj (i j : Fin 16) : Prop := + (i.val / 4 = j.val / 4 ∧ (i.val % 4 + 1 = j.val % 4 ∨ j.val % 4 + 1 = i.val % 4)) ∨ + (i.val % 4 = j.val % 4 ∧ (i.val / 4 + 1 = j.val / 4 ∨ j.val / 4 + 1 = i.val / 4)) + +instance : DecidableRel Adj := fun i j => by unfold Adj; infer_instance + +/-- The "Vertex neighbors" list printed in the entry. -/ +def entryNbrs : Fin 16 → List (Fin 16) := + ![[1, 4], [0, 2, 5], [1, 3, 6], [2, 7], [0, 5, 8], [4, 1, 6, 9], [5, 2, 7, 10], [6, 3, 11], + [4, 9, 12], [8, 5, 10, 13], [9, 6, 11, 14], [10, 7, 15], [8, 13], [12, 9, 14], + [13, 10, 15], [14, 11]] + +/-- `Adj` is exactly the neighbour relation listed in the entry (kernel-checked). -/ +theorem adj_iff_entry : ∀ i j : Fin 16, Adj i j ↔ j ∈ entryNbrs i := by decide +kernel + +/-- An `n X 1` array (a column `f`, entry in row `i` being `f i`) is valid iff every two +vertically neighbouring entries are adjacent nodes of the grid graph. -/ +def Valid {n : ℕ} (f : Fin n → Fin 16) : Prop := + ∀ i j : Fin n, i.val + 1 = j.val → Adj (f i) (f j) + +instance (n : ℕ) : DecidablePred (@Valid n) := fun f => by unfold Valid; infer_instance + +/-- A223395: the number of `n X 1` arrays with entries in `0..15` (nodes of the 4 × 4 square grid +graph) such that every move to a vertical neighbour moves along an edge of the graph. -/ +def a (n : ℕ) : ℕ := Fintype.card {f : Fin n → Fin 16 // Valid f} + +/-! ### A fast, provably equal version for the data check -/ + +/-- Number of valid columns with `n + 1` entries whose top entry is `v`. -/ +def cnt (n : ℕ) (v : Fin 16) : ℕ := + ∑ f : Fin (n + 1) → Fin 16, if Valid f ∧ f 0 = v then 1 else 0 + +/-- One transfer-matrix step on a vector stored as a list of length 16. -/ +def stepL (l : List ℕ) : List ℕ := + (List.finRange 16).map fun v => + ((List.finRange 16).map fun u => if Adj v u then l.getD u.val 0 else 0).sum + +/-- `colsL n` lists `cnt n v` for `v = 0, …, 15`. -/ +def colsL : ℕ → List ℕ + | 0 => List.replicate 16 1 + | n + 1 => stepL (colsL n) + +/-- Fast computation of `a`. -/ +def aL : ℕ → ℕ + | 0 => 1 + | n + 1 => (colsL n).sum + +theorem valid_cons {n : ℕ} (x : Fin 16) (g : Fin (n + 1) → Fin 16) : + Valid (Fin.cons x g : Fin (n + 2) → Fin 16) ↔ Adj x (g 0) ∧ Valid g := by + constructor + · intro h + refine ⟨?_, fun i j hij => ?_⟩ + · simpa using h 0 1 (by simp) + · simpa using h i.succ j.succ (by simp [hij]) + · rintro ⟨h0, hg⟩ i j hij + induction i using Fin.cases with + | zero => + induction j using Fin.cases with + | zero => simp at hij + | succ j => + have hj : j = 0 := by ext; simp at hij; omega + subst hj + simpa using h0 + | succ i => + induction j using Fin.cases with + | zero => simp at hij + | succ j => simpa using hg i j (by simpa using hij) + +theorem cnt_zero (v : Fin 16) : cnt 0 v = 1 := by + unfold cnt + rw [← (Equiv.funUnique (Fin 1) (Fin 16)).symm.sum_comp] + have hv : ∀ x : Fin 16, Valid ((Equiv.funUnique (Fin 1) (Fin 16)).symm x) := by + intro x i j hij + have hi := i.isLt + have hj := j.isLt + omega + rw [Finset.sum_eq_single v] + · rw [if_pos ⟨hv v, rfl⟩] + · intro b _ hb + rw [if_neg] + rintro ⟨_, h⟩ + exact hb h + · intro h + exact absurd (Finset.mem_univ v) h + +/-- Splitting off the top entry of a column. -/ +theorem sum_cons (n : ℕ) (F : (Fin (n + 1) → Fin 16) → ℕ) : + ∑ f, F f = ∑ x, ∑ g : Fin n → Fin 16, F (Fin.cons x g) := by + rw [← Fintype.sum_prod_type'] + exact Fintype.sum_equiv (Fin.consEquiv fun _ => Fin 16).symm _ _ (fun f => by simp) + +theorem cnt_succ (n : ℕ) (v : Fin 16) : + cnt (n + 1) v = ∑ u, if Adj v u then cnt n u else 0 := by + unfold cnt + rw [sum_cons] + simp only [valid_cons, Fin.cons_zero] + calc + _ = ∑ g : Fin (n + 1) → Fin 16, if Adj v (g 0) ∧ Valid g then 1 else 0 := by + rw [Finset.sum_eq_single v] + · simp + · intro b _ hb + apply Finset.sum_eq_zero + intro g _ + simp [hb] + · intro h + exact absurd (Finset.mem_univ v) h + _ = ∑ g : Fin (n + 1) → Fin 16, ∑ u, + if Adj v u then (if Valid g ∧ g 0 = u then 1 else 0) else 0 := by + refine Finset.sum_congr rfl fun g _ => ?_ + rw [Finset.sum_eq_single (g 0)] + · by_cases h1 : Adj v (g 0) <;> by_cases h2 : Valid g <;> simp [h1, h2] + · intro b _ hb + simp [Ne.symm hb] + · intro h + exact absurd (Finset.mem_univ _) h + _ = _ := by + rw [Finset.sum_comm] + refine Finset.sum_congr rfl fun u _ => ?_ + by_cases h : Adj v u <;> simp [h] + +theorem a_zero : a 0 = 1 := by + unfold a + rw [Fintype.card_eq_one_iff] + refine ⟨⟨finZeroElim, fun i => i.elim0⟩, fun f => ?_⟩ + ext i + exact i.elim0 + +theorem a_succ (n : ℕ) : a (n + 1) = ∑ v, cnt n v := by + unfold a cnt + rw [Fintype.card_subtype, Finset.card_filter, Finset.sum_comm] + refine Finset.sum_congr rfl fun f _ => ?_ + rw [Finset.sum_eq_single (f 0)] + · by_cases h : Valid f <;> simp [h] + · intro b _ hb + simp [Ne.symm hb] + · intro h + exact absurd (Finset.mem_univ _) h + +theorem getD_map_finRange (w : Fin 16 → ℕ) (u : Fin 16) : + ((List.finRange 16).map w).getD u.val 0 = w u := by + simp [List.getD_eq_getElem?_getD] + +theorem colsL_eq (n : ℕ) : colsL n = (List.finRange 16).map (cnt n) := by + induction n with + | zero => + rw [show cnt 0 = fun _ => 1 from funext cnt_zero] + rfl + | succ n ih => + simp only [colsL, stepL, ih, getD_map_finRange] + refine List.map_congr_left fun v _ => ?_ + rw [cnt_succ, Fin.sum_univ_def] + +/-- `a` agrees with the fast transfer-matrix version `aL` for every `n`. -/ +theorem a_eq_aL (n : ℕ) : a n = aL n := by + cases n with + | zero => simp [a_zero, aL] + | succ n => rw [a_succ, aL, colsL_eq, Fin.sum_univ_def] + +/-- The definition reproduces the first 24 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 24).map (fun i => a (i + 1)) = + [16, 48, 152, 488, 1576, 5096, 16488, 53352, 172648, 558696, 1807976, 5850728, + 18933352, 61269608, 198272616, 641623656, 2076337768, 6719170152, + 21743691368, 70364063336, 227702892136, 736862037608, 2384535643752, + 7716519437928] := by + simp only [a_eq_aL] + decide +kernel + +/-- Hardin's empirical recurrence: `a(n) = 3 a(n-1) + 2 a(n-2) - 4 a(n-3)` for every `n ≥ 4`. -/ +def statementRec : Prop := + ∀ n : ℕ, 4 ≤ n → (a n : ℤ) = 3 * a (n - 1) + 2 * a (n - 2) - 4 * a (n - 3) + +/-- Barker's conjectured generating function: +`∑_{n ≥ 1} a(n) x^n = 8 x (2 - 3 x^2) / ((1 - x)(1 - 2x - 4x^2))`, with the (unit) +denominator cleared. -/ +def statementGF : Prop := + (1 - PowerSeries.X) * (1 - 2 * PowerSeries.X - 4 * PowerSeries.X ^ 2) * + PowerSeries.mk (fun n => if n = 0 then (0 : ℤ) else a n) = + 8 * PowerSeries.X * (2 - 3 * PowerSeries.X ^ 2) + +/-- Barker's conjectured closed form, for every term `n ≥ 1`: +`a(n) = (8 + (11 - 5√5)(1 - √5)^n + (1 + √5)^n (11 + 5√5)) / 5`. -/ +def statementClosedForm : Prop := + ∀ n : ℕ, 1 ≤ n → (a n : ℝ) = + (8 + (11 - 5 * Real.sqrt 5) * (1 - Real.sqrt 5) ^ n + + (1 + Real.sqrt 5) ^ n * (11 + 5 * Real.sqrt 5)) / 5 + +/-- The conjectures of A223395: Hardin's recurrence `a(n) = 3a(n-1) + 2a(n-2) - 4a(n-3)` +(`n ≥ 4`), together with Barker's generating function and closed form. -/ +def statement : Prop := statementRec ∧ statementGF ∧ statementClosedForm + +end Math0.Statements.A223395 diff --git a/lean/Math0/Statements/OEIS/A229159.lean b/lean/Math0/Statements/OEIS/A229159.lean new file mode 100644 index 0000000..e63b439 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A229159.lean @@ -0,0 +1,341 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A229159: smallest integer area of an integer triangle with a side of length prime(n) + +Source: https://oeis.org/A229159, _Michel Lagneau_, Sep 17 2013. Verbatim: +> Conjecture: for all prime p > 2 there exists an integer-sided triangle with integer area where +> at least one side is of length p. + +The entry's name: "Smallest integer areas of integer-sided triangles where at least one side is +of length prime(n)." Offset `1`, so `prime(1) = 2`. The listed `a(1) = 0` means that no such +triangle exists for `p = 2`. + +## Encoding + +* *Triangles.* An integer-sided triangle is a triple `x, y, z` of natural numbers satisfying the + strict triangle inequalities `x < y + z`, `y < x + z`, `z < x + y`. These make the triangle + non-degenerate and force `x, y, z ≥ 1`. Degenerate triangles are excluded. Otherwise every + `p` would trivially have an area-`0` "triangle" `(p, p, 2p)`, and `a(1) = 0` would not mean + "no triangle". +* *Integer area.* By Heron's formula, the area `S` of the triangle satisfies + `16 S² = (x+y+z)(-x+y+z)(x-y+z)(x+y-z)`. "Integer area" means `S` is a natural number `A`, + i.e. `16 A² = (x+y+z)(-x+y+z)(x-y+z)(x+y-z)` (computed in `ℤ`). This is `IsIntTriangle x y z A`. + Under the strict triangle inequalities, `A > 0` automatically. +* *A side of length `p`.* `x = p ∨ y = p ∨ z = p`. `areas p` is the set of such integer areas. +* *The sequence.* `prime n = Nat.nth Nat.Prime (n - 1)` is the `n`-th prime (1-indexed), and + `a n = sInf (areas (prime n))`. On `ℕ`, `sInf ∅ = 0`, which matches the OEIS convention + `a(1) = 0`. The set `areas p` need not be finite or decidable a priori, so `a` is + noncomputable. The values are certified by computable helpers: + - a witness triangle `(p, b, c)` with Heron product `16 A₀²` (`entryOK`); + - a kernel-checked search (`lbCheck`) showing that no triangle `(p, b, b + d)`, `0 ≤ d < p`, + has an integer area `A < A₀`. For fixed `d` the Heron product is monotone in `b`, so each + scan stops at the first `b` where the product reaches `16 A₀²` (`scan_spec`). Non-squares + are certified by `r² < N < (r+1)²` for a Newton guess `r`. + `a_one` proves `a 1 = 0` by hand: there is no integer triangle with integer area and a side of + length `2`. +* *Data.* `a_data` checks the first 19 listed terms (`n = 1, …, 19`, primes up to `67`). The + listed term `a(20) = 14910` (and also `a(25) = 420`, `a(29) = 840`, `a(32) = 11790`, + `a(40) = 3276`) is **not** the minimum. The entry's Maple program only searches sides up to + `500` and returns the first triangle found, not the smallest-area one. For example, + `(71, 505, 560)` has area `11928` and `(97, 11, 90)` has area `396`. `oeis_errata` proves these + upper bounds. The errata concern only the listed values, not the conjecture, which is a pure + existence statement. +* *The conjecture.* `statement`: for every prime `p > 2` there are natural numbers `x, y, z, A` + with `IsIntTriangle x y z A` and `p ∈ {x, y, z}`. Equivalently, `areas p` is nonempty, i.e. + `a n ≠ 0` for every `n ≥ 2`. +-/ + +namespace Math0.Statements.A229159 + +/-- `x, y, z` are the side lengths of a non-degenerate triangle (strict triangle inequalities) +whose area is the natural number `A`. By Heron's formula, +`16 · area² = (x+y+z)(-x+y+z)(x-y+z)(x+y-z)`. -/ +def IsIntTriangle (x y z A : ℕ) : Prop := + x < y + z ∧ y < x + z ∧ z < x + y ∧ + 16 * (A : ℤ) ^ 2 = + ((x : ℤ) + y + z) * (-(x : ℤ) + y + z) * ((x : ℤ) - y + z) * ((x : ℤ) + y - z) + +/-- The integer areas of the integer-sided triangles having (at least) one side of length `m`. -/ +def areas (m : ℕ) : Set ℕ := + {A | ∃ x y z : ℕ, IsIntTriangle x y z A ∧ (x = m ∨ y = m ∨ z = m)} + +/-- The `n`-th prime, 1-indexed as in OEIS: `prime 1 = 2`, `prime 2 = 3`, … -/ +noncomputable def prime (n : ℕ) : ℕ := Nat.nth Nat.Prime (n - 1) + +/-- A229159: the smallest integer area of an integer-sided triangle having a side of length +`prime n`, and `0` if there is no such triangle (on `ℕ`, `sInf ∅ = 0`). Offset `1`. -/ +noncomputable def a (n : ℕ) : ℕ := sInf (areas (prime n)) + +/-! ### Symmetry: we may assume the side `p` comes first and `b ≤ c` -/ + +theorem IsIntTriangle.swap12 {x y z A : ℕ} (h : IsIntTriangle x y z A) : + IsIntTriangle y x z A := by + obtain ⟨h1, h2, h3, h4⟩ := h + refine ⟨by omega, by omega, by omega, ?_⟩ + rw [h4]; ring + +theorem IsIntTriangle.swap13 {x y z A : ℕ} (h : IsIntTriangle x y z A) : + IsIntTriangle z y x A := by + obtain ⟨h1, h2, h3, h4⟩ := h + refine ⟨by omega, by omega, by omega, ?_⟩ + rw [h4]; ring + +theorem IsIntTriangle.swap23 {x y z A : ℕ} (h : IsIntTriangle x y z A) : + IsIntTriangle x z y A := by + obtain ⟨h1, h2, h3, h4⟩ := h + refine ⟨by omega, by omega, by omega, ?_⟩ + rw [h4]; ring + +theorem exists_le_of_isIntTriangle {m b c A : ℕ} (h : IsIntTriangle m b c A) : + ∃ b c, b ≤ c ∧ IsIntTriangle m b c A := by + rcases le_total b c with hbc | hbc + · exact ⟨b, c, hbc, h⟩ + · exact ⟨c, b, hbc, h.swap23⟩ + +theorem mem_areas_iff (m A : ℕ) : + A ∈ areas m ↔ ∃ b c, b ≤ c ∧ IsIntTriangle m b c A := by + constructor + · rintro ⟨x, y, z, h, rfl | rfl | rfl⟩ + · exact exists_le_of_isIntTriangle h + · exact exists_le_of_isIntTriangle h.swap12 + · exact exists_le_of_isIntTriangle h.swap13 + · rintro ⟨b, c, -, h⟩ + exact ⟨m, b, c, h, Or.inl rfl⟩ + +/-! ### The Heron product in `ℕ` -/ + +/-- The Heron product `(p+b+c)(b+c-p)(p+c-b)(p+b-c)` in `ℕ` (truncated subtraction). It equals +the integer Heron product when the triangle inequalities hold. -/ +def heronN (p b c : ℕ) : ℕ := (p + b + c) * (b + c - p) * (p + c - b) * (p + b - c) + +theorem heronN_cast {p b c : ℕ} (h1 : p < b + c) (h2 : b < p + c) (h3 : c < p + b) : + (heronN p b c : ℤ) = + ((p : ℤ) + b + c) * (-(p : ℤ) + b + c) * ((p : ℤ) - b + c) * ((p : ℤ) + b - c) := by + unfold heronN + push_cast [Nat.cast_sub (show p ≤ b + c by omega), Nat.cast_sub (show b ≤ p + c by omega), + Nat.cast_sub (show c ≤ p + b by omega)] + ring + +theorem isIntTriangle_iff_heronN (p b c A : ℕ) : + IsIntTriangle p b c A ↔ + p < b + c ∧ b < p + c ∧ c < p + b ∧ heronN p b c = 16 * A ^ 2 := by + constructor + · rintro ⟨h1, h2, h3, h4⟩ + refine ⟨h1, h2, h3, ?_⟩ + rw [← heronN_cast h1 h2 h3] at h4 + exact_mod_cast h4.symm + · rintro ⟨h1, h2, h3, h4⟩ + refine ⟨h1, h2, h3, ?_⟩ + rw [← heronN_cast h1 h2 h3, h4] + push_cast; ring + +/-- For fixed `p` and `d`, the Heron product of `(p, b, b + d)` is monotone in `b`. -/ +theorem heronN_mono {p d b b' : ℕ} (h : b ≤ b') : + heronN p b (b + d) ≤ heronN p b' (b' + d) := by + unfold heronN + apply Nat.mul_le_mul (Nat.mul_le_mul (Nat.mul_le_mul _ _) _) _ <;> omega + +/-! ### Certified search for the lower bound -/ + +/-- Newton iteration for the integer square root, with fuel. It is only a guess. Every use is +certified by `notSquareAux`. -/ +def sqrtGuess : ℕ → ℕ → ℕ → ℕ + | 0, _, g => g + | fuel + 1, N, g => + if (g + N / g) / 2 < g then sqrtGuess fuel N ((g + N / g) / 2) else g + +/-- `r² < N < (r + 1)²`, which certifies that `N` is not a perfect square. -/ +def notSquareAux (N r : ℕ) : Bool := r * r < N && N < (r + 1) * (r + 1) + +/-- Certified non-square test (sound by `notSquare_spec`). -/ +def notSquare (N : ℕ) : Bool := notSquareAux N (sqrtGuess 64 N (2 ^ (N.log2 / 2 + 1))) + +theorem notSquare_spec {N : ℕ} (h : notSquare N = true) (A : ℕ) : A * A ≠ N := by + simp only [notSquare, notSquareAux, Bool.and_eq_true, decide_eq_true_eq] at h + obtain ⟨h1, h2⟩ := h + set r := sqrtGuess 64 N (2 ^ (N.log2 / 2 + 1)) + intro hA + rcases le_or_gt A r with hr | hr + · have := Nat.mul_le_mul hr hr; omega + · have h3 : r + 1 ≤ A := hr + have := Nat.mul_le_mul h3 h3; omega + +/-- The pair `(b, c)` (with Heron product `P`) is not a triangle, or `P ≠ 16 A²` for every `A`. -/ +def pairOK (p b c P : ℕ) : Bool := !(p < b + c) || P % 16 != 0 || notSquare (P / 16) + +/-- One step of `scan`: stop (successfully) once the Heron product `P` reaches `M`; otherwise +check the current pair and continue with `k`. -/ +def scanAux (p M d b P : ℕ) (k : Bool) : Bool := + if M ≤ P then true else pairOK p b (b + d) P && k + +/-- `scan p M d fuel b`: walk `b, b + 1, …` (at most `fuel` steps) through the triangles +`(p, b, b + d)` until the Heron product reaches `M`, checking that no Heron product below `M` +is `16 A²`. -/ +def scan (p M d : ℕ) : ℕ → ℕ → Bool + | 0, _ => false + | fuel + 1, b => scanAux p M d b (heronN p b (b + d)) (scan p M d fuel (b + 1)) + +theorem scan_spec (p M d : ℕ) : + ∀ fuel b, scan p M d fuel b = true → + ∀ b', b ≤ b' → ∀ A, IsIntTriangle p b' (b' + d) A → M ≤ 16 * A ^ 2 := by + intro fuel + induction fuel with + | zero => intro b h; simp [scan] at h + | succ fuel ih => + intro b h b' hb' A hA + have hA' := (isIntTriangle_iff_heronN _ _ _ _).1 hA + simp only [scan, scanAux] at h + split_ifs at h with hM + · rw [← hA'.2.2.2] + exact hM.trans (heronN_mono hb') + · rw [Bool.and_eq_true] at h + rcases Nat.eq_or_lt_of_le hb' with rfl | hlt + · exfalso + have hP := h.1 + simp only [pairOK, hA'.2.2.2, Bool.or_eq_true, Bool.not_eq_true', decide_eq_false_iff_not, + not_lt, bne_iff_ne, ne_eq] at hP + rcases hP with (hP | hP) | hP + · exact absurd hA'.1 (not_lt.2 hP) + · exact hP (by omega) + · exact notSquare_spec (by rwa [show 16 * A ^ 2 / 16 = A * A by rw [sq]; omega] at hP) A rfl + · exact ih (b + 1) h.2 b' hlt A hA + +/-- No triangle `(p, b, c)` with `b ≤ c` has Heron product `16 A²` with `16 A² < M` +(see `lbCheck_spec`). -/ +def lbCheck (p M : ℕ) : Bool := (List.range p).all fun d => scan p M d 100000 0 + +theorem lbCheck_spec {p M : ℕ} (h : lbCheck p M = true) {b c A : ℕ} (hbc : b ≤ c) + (hA : IsIntTriangle p b c A) : M ≤ 16 * A ^ 2 := by + have hd : c - b < p := by have := hA.2.2.1; omega + have hs := List.all_eq_true.1 h (c - b) (List.mem_range.2 hd) + refine scan_spec p M (c - b) 100000 0 hs b (Nat.zero_le b) A ?_ + rwa [show b + (c - b) = c by omega] + +/-! ### Certified values -/ + +/-- Check that `p` is the `n`-th prime and that `(p, b, c)` is a triangle with Heron product +`16 A²`, so that `A ∈ areas (prime n)` (`witnessOK_spec`). -/ +def witnessOK (n p A b c : ℕ) : Bool := + decide (Nat.Prime p) && Nat.count Nat.Prime p == n - 1 && + decide (p < b + c) && decide (b < p + c) && decide (c < p + b) && + heronN p b c == 16 * A ^ 2 + +/-- `witnessOK`, and no triangle with a side `p` has an integer area below `A₀`, so that +`a n = A₀` (`a_eq_of_entryOK`). -/ +def entryOK (n p A₀ b c : ℕ) : Bool := + witnessOK n p A₀ b c && lbCheck p (16 * A₀ ^ 2) + +theorem prime_eq {n p : ℕ} (hp : Nat.Prime p) (hc : Nat.count Nat.Prime p = n - 1) : + prime n = p := by + rw [prime, ← hc] + exact Nat.nth_count hp + +theorem witnessOK_spec {n p A b c : ℕ} (h : witnessOK n p A b c = true) : + prime n = p ∧ A ∈ areas p := by + simp only [witnessOK, Bool.and_eq_true, decide_eq_true_eq, beq_iff_eq] at h + obtain ⟨⟨⟨⟨⟨hp, hc⟩, h1⟩, h2⟩, h3⟩, hH⟩ := h + exact ⟨prime_eq hp hc, p, b, c, (isIntTriangle_iff_heronN p b c A).2 ⟨h1, h2, h3, hH⟩, + Or.inl rfl⟩ + +theorem a_le_of_witnessOK {n p A b c : ℕ} (h : witnessOK n p A b c = true) : a n ≤ A := by + obtain ⟨hp, hA⟩ := witnessOK_spec h + rw [a, hp] + exact Nat.sInf_le hA + +theorem a_eq_of_entryOK {n p A₀ b c : ℕ} (h : entryOK n p A₀ b c = true) : a n = A₀ := by + rw [entryOK, Bool.and_eq_true] at h + obtain ⟨hp, hA₀⟩ := witnessOK_spec h.1 + rw [a, hp] + refine IsLeast.csInf_eq ⟨hA₀, ?_⟩ + intro A hA + obtain ⟨b', c', hle, ht⟩ := (mem_areas_iff _ _).1 hA + have := lbCheck_spec h.2 hle ht + by_contra hlt + replace hlt := not_le.1 hlt + have : A ^ 2 < A₀ ^ 2 := Nat.pow_lt_pow_left hlt two_ne_zero + omega + +/-- `a 1 = 0`: there is no integer-sided triangle with integer area and a side of length +`prime 1 = 2`. With sides `2 ≤ b ≤ c < b + 2`, either `c = b` and `A² = b² - 1`, which is not a +square, or `c = b + 1` and `16 A² = 3 (2b + 3)(2b - 1)`, which is odd. -/ +theorem areas_two : areas 2 = ∅ := by + ext A + simp only [Set.mem_empty_iff_false, iff_false] + intro hA + obtain ⟨b, c, hbc, h1, h2, h3, h4⟩ := (mem_areas_iff 2 A).1 hA + push_cast at h4 + rcases (show c = b ∨ c = b + 1 by omega) with hc | hc + · subst c + have hb : (2 : ℤ) ≤ b := by exact_mod_cast (show 2 ≤ b by omega) + have h16 : (16 : ℤ) * (A : ℤ) ^ 2 = 16 * ((b : ℤ) ^ 2 - 1) := by linear_combination h4 + have key : (A : ℤ) ^ 2 = (b : ℤ) ^ 2 - 1 := mul_left_cancel₀ (by norm_num) h16 + have hA0 : (0 : ℤ) ≤ A := by positivity + rcases le_or_gt (A : ℤ) (b - 1) with h | h + · nlinarith [mul_le_mul h h hA0 (by linarith)] + · have h' : (b : ℤ) ≤ A := by linarith + nlinarith [mul_le_mul h' h' (by linarith) hA0] + · subst c + push_cast at h4 + have key : (16 : ℤ) * (A : ℤ) ^ 2 = 12 * (b : ℤ) ^ 2 + 12 * b - 9 := by + linear_combination h4 + generalize (A : ℤ) ^ 2 = X at key + generalize (b : ℤ) ^ 2 = Y at key + omega + +theorem a_one : a 1 = 0 := by + rw [a, prime, Nat.sub_self, Nat.nth_prime_zero_eq_two, areas_two, Nat.sInf_empty] + +/-- `(n, prime n, a n, b, c)` for `n = 2, …, 19`, where `(prime n, b, c)` is a triangle of +area `a n` (the same triangles as in the entry's table). -/ +def table : List (ℕ × ℕ × ℕ × ℕ × ℕ) := + [(2, 3, 6, 4, 5), (3, 5, 6, 3, 4), (4, 7, 42, 15, 20), (5, 11, 66, 13, 20), (6, 13, 24, 4, 15), + (7, 17, 36, 9, 10), (8, 19, 114, 20, 37), (9, 23, 966, 140, 159), (10, 29, 60, 6, 25), + (11, 31, 930, 68, 87), (12, 37, 114, 19, 20), (13, 41, 126, 15, 28), (14, 43, 1290, 61, 68), + (15, 47, 4230, 425, 468), (16, 53, 90, 4, 51), (17, 59, 1770, 68, 109), + (18, 61, 330, 11, 60), (19, 67, 2814, 85, 116)] + +/-- Kernel check of every entry of `table` (primality, prime index, witness, lower bound). -/ +theorem table_ok : + table.all (fun e => entryOK e.1 e.2.1 e.2.2.1 e.2.2.2.1 e.2.2.2.2) = true := by + decide +kernel + +theorem a_table : ∀ e ∈ table, a e.1 = e.2.2.1 := fun e he => + a_eq_of_entryOK (List.all_eq_true.1 table_ok e he) + +/-- The definition reproduces the first 19 terms listed in OEIS (`n = 1, …, 19`), kernel-checked +through `table_ok` (`a 1 = 0` by `a_one`). -/ +theorem a_data : (List.range 19).map (fun i => a (i + 1)) = + [0, 6, 6, 42, 66, 24, 36, 114, 966, 60, 930, 114, 126, 1290, 4230, 90, 1770, 330, 2814] := by + have hidx : table.map (fun e => e.1) = (List.range 18).map (fun i => i + 2) := by + decide +kernel + calc (List.range 19).map (fun i => a (i + 1)) + = a 1 :: ((List.range 18).map (fun i => i + 2)).map a := by + rw [List.range_succ_eq_map, List.map_cons, List.map_map, List.map_map]; rfl + _ = a 1 :: table.map (fun e => a e.1) := by rw [← hidx, List.map_map]; rfl + _ = 0 :: table.map (fun e => e.2.2.1) := by rw [a_one, List.map_congr_left a_table] + _ = _ := by decide +kernel + +/-- Errata: some listed terms are not minimal. The triangles `(71, 505, 560)`, `(97, 11, 90)`, +`(109, 11, 100)`, `(131, 265, 390)` and `(173, 36, 187)` have integer areas `11928 < 14910`, +`396 < 420`, `330 < 840`, `6288 < 11790` and `2970 < 3276` (the listed `a(20)`, `a(25)`, `a(29)`, +`a(32)`, `a(40)`). -/ +theorem oeis_errata : a 20 ≤ 11928 ∧ a 25 ≤ 396 ∧ a 29 ≤ 330 ∧ a 32 ≤ 6288 ∧ a 40 ≤ 2970 := + ⟨a_le_of_witnessOK (p := 71) (b := 505) (c := 560) (by decide +kernel), + a_le_of_witnessOK (p := 97) (b := 11) (c := 90) (by decide +kernel), + a_le_of_witnessOK (p := 109) (b := 11) (c := 100) (by decide +kernel), + a_le_of_witnessOK (p := 131) (b := 265) (c := 390) (by decide +kernel), + a_le_of_witnessOK (p := 173) (b := 36) (c := 187) (by decide +kernel)⟩ + +/-! ### The conjecture -/ + +/-- Conjecture (Lagneau, A229159): for every prime `p > 2` there is an integer-sided +(non-degenerate) triangle with integer area having at least one side of length `p`. -/ +def statement : Prop := + ∀ p : ℕ, p.Prime → 2 < p → + ∃ x y z A : ℕ, IsIntTriangle x y z A ∧ (x = p ∨ y = p ∨ z = p) + +end Math0.Statements.A229159 diff --git a/lean/Math0/Statements/OEIS/A242396.lean b/lean/Math0/Statements/OEIS/A242396.lean new file mode 100644 index 0000000..46365e7 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A242396.lean @@ -0,0 +1,188 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A242396: rows of unit triangles meeting a circle of radius n + +Source: https://oeis.org/A242396, _Ralf Stephan_, May 18 2014 (entry by _Kival Ngaokrajang_, +May 13 2014). Verbatim (FORMULA section): +> G.f., conjectured: (-2*x^14 + 4*x^13 + 2*x^12 + 2*x^11 + 2*x^10 + 2*x^9 + 2*x^8 + 4*x^7 + +> 2*x^6 + 2*x^5 + 2*x^4 + 2*x^3 + 2*x^2 + 4*x)/(x^14 - x^13 - x + 1). - _Ralf Stephan_, May 18 2014 + +The next FORMULA line is a consequence drawn from that conjectured g.f.; verbatim: +> Asymptotics from g.f.: a(n) ~ 30/13 * n. - _Ralf Stephan_, May 18 2014 + +The entry's name: "Number of rows of equilateral triangles (sides length = 1) that intersect the +circumference of a circle of radius n centered at (0,0) or (1/2,0)." Offset `1`. + +## Encoding + +* The tiling is the tiling of the plane by equilateral triangles of side `1` with a vertex at + the origin and horizontal sides, as in the entry's Small Basic program and in the sibling + entries A242394 / A242395 (whose programs place the tiling vertices at `(j/2, i·√3/2)`). Its + rows are the closed horizontal strips `{(x, y) | j·√3/2 ≤ y ≤ (j+1)·√3/2}`, `j ∈ ℤ`; the + triangles of row `j` tile exactly that strip, so a row meets the circle iff the strip does. +* `RowMeets c n j` says that the circle `(x - c)² + y² = n²` (center `(c, 0)`) meets row `j`. + The name allows the center `(0,0)` or `(1/2,0)`; `rowMeets_iff` shows the condition does not + depend on `c`, so both readings give the same count. +* `MeetsInt n j` is the decidable integer form of `j·√3/2 ≤ n ∧ -n ≤ (j+1)·√3/2`, namely + `(j ≤ 0 ∨ 3 j² ≤ 4 n²) ∧ (0 ≤ j + 1 ∨ 3 (j+1)² ≤ 4 n²)`. +* `a n` counts the `i < 4n + 5` with `MeetsInt n (i - (2n+2))`, i.e. the rows + `j ∈ [-(2n+2), 2n+2]` with `MeetsInt n j` (all meeting rows lie in that range, by + `bounds_of_meetsInt`); `a_eq_ncard` proves + `a n = #{j : ℤ | RowMeets c n j}` for every real `c` (in particular `c = 0` and `c = 1/2`), + so `a` is the OEIS definition, not a closed form. +* Rows are taken closed. For `n ≥ 1` this is immaterial: `2n/√3` is irrational, so no row + boundary `y = j·√3/2` is tangent to the circle, and every boundary line that meets the circle + crosses it, entering the interiors of both adjacent rows. +* Offset `1`: `a 0` (here `2`) is not a term of the sequence. The conjectured g.f. has no + constant term (its numerator is divisible by `x` and its denominator has constant term `1`), + so it is read as `∑_{n ≥ 1} a(n) xⁿ`; the series in `statement` therefore has coefficient `0` + at `x⁰` and `a n` at `xⁿ` for `n ≥ 1`. +* `statement` is the g.f. identity in `ℤ⟦X⟧` with the denominator cleared. The denominator + `x¹⁴ - x¹³ - x + 1` has constant coefficient `1`, hence is a unit of `ℤ⟦X⟧`, so this is + equivalent to the stated equality of the series with the quotient. +* `statement_asymptotic` records the derived asymptotic claim `a(n) ~ 30/13 · n` + (`Asymptotics.IsEquivalent` along `atTop`); it is not part of `statement`. +-/ + +namespace Math0.Statements.A242396 + +open Real + +/-- Row `j : ℤ` of the unit triangular tiling (the closed strip +`j·√3/2 ≤ y ≤ (j+1)·√3/2`) meets the circle of radius `n` centered at `(c, 0)`. -/ +def RowMeets (c : ℝ) (n : ℕ) (j : ℤ) : Prop := + ∃ x y : ℝ, (x - c) ^ 2 + y ^ 2 = (n : ℝ) ^ 2 ∧ + (j : ℝ) * (√3 / 2) ≤ y ∧ y ≤ ((j : ℝ) + 1) * (√3 / 2) + +/-- Integer form of `j·√3/2 ≤ n ∧ -n ≤ (j+1)·√3/2` (see `rowMeets_iff`). -/ +def MeetsInt (n : ℕ) (j : ℤ) : Prop := + (j ≤ 0 ∨ 3 * j ^ 2 ≤ 4 * (n : ℤ) ^ 2) ∧ (0 ≤ j + 1 ∨ 3 * (j + 1) ^ 2 ≤ 4 * (n : ℤ) ^ 2) + +instance (n : ℕ) : DecidablePred (MeetsInt n) := fun _ => by + unfold MeetsInt; infer_instance + +/-- A242396: the number of rows of the unit equilateral-triangle tiling that meet the circle of +radius `n` centered at `(0,0)` (or `(1/2,0)`). Row `j` is indexed by `i = j + 2n + 2 < 4n + 5`, +i.e. `j` ranges over `[-(2n+2), 2n+2]`, which contains every meeting row; see `a_eq_ncard`. -/ +def a (n : ℕ) : ℕ := + ((Finset.range (4 * n + 5)).filter (fun i : ℕ => MeetsInt n ((i : ℤ) - (2 * n + 2)))).card + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 61).map (fun i => a (i + 1)) = + [4, 6, 8, 10, 12, 14, 18, 20, 22, 24, 26, 28, 32, 34, 36, 38, 40, 42, 44, 48, 50, 52, 54, 56, + 58, 62, 64, 66, 68, 70, 72, 74, 78, 80, 82, 84, 86, 88, 92, 94, 96, 98, 100, 102, 104, + 108, 110, 112, 114, 116, 118, 122, 124, 126, 128, 130, 132, 134, 138, 140, 142] := by + decide +kernel + +/-! ### `a` is the geometric count -/ + +theorem mul_half_sqrt_three_le_iff (k : ℤ) (n : ℕ) : + (k : ℝ) * (√3 / 2) ≤ n ↔ k ≤ 0 ∨ 3 * k ^ 2 ≤ 4 * (n : ℤ) ^ 2 := by + have h3 : √3 ^ 2 = 3 := sq_sqrt (by norm_num) + have hs : 0 ≤ √3 := sqrt_nonneg 3 + have hn : (0 : ℝ) ≤ n := Nat.cast_nonneg n + constructor + · intro h + by_cases hk : k ≤ 0 + · exact Or.inl hk + · right + push Not at hk + have hk' : (0 : ℝ) < k := by exact_mod_cast hk + have h1 : (k : ℝ) * √3 ≤ 2 * n := by linarith + have h2 : ((k : ℝ) * √3) ^ 2 ≤ (2 * (n : ℝ)) ^ 2 := + pow_le_pow_left₀ (by positivity) h1 2 + have h4 : ((3 * k ^ 2 : ℤ) : ℝ) ≤ ((4 * (n : ℤ) ^ 2 : ℤ) : ℝ) := by + push_cast + nlinarith + exact_mod_cast h4 + · rintro (hk | hk) + · have hk' : (k : ℝ) ≤ 0 := by exact_mod_cast hk + have : (k : ℝ) * (√3 / 2) ≤ 0 := mul_nonpos_of_nonpos_of_nonneg hk' (by positivity) + linarith + · have hk' : ((3 * k ^ 2 : ℤ) : ℝ) ≤ ((4 * (n : ℤ) ^ 2 : ℤ) : ℝ) := by exact_mod_cast hk + push_cast at hk' + by_contra hlt + push Not at hlt + have h1 : 2 * (n : ℝ) < (k : ℝ) * √3 := by linarith + have h2 : (2 * (n : ℝ)) ^ 2 < ((k : ℝ) * √3) ^ 2 := + pow_lt_pow_left₀ h1 (by positivity) (by norm_num) + nlinarith + +theorem rowMeets_iff_real (c : ℝ) (n : ℕ) (j : ℤ) : + RowMeets c n j ↔ (j : ℝ) * (√3 / 2) ≤ n ∧ -(n : ℝ) ≤ ((j : ℝ) + 1) * (√3 / 2) := by + have hs : 0 ≤ √3 / 2 := by positivity + have hn : (0 : ℝ) ≤ n := Nat.cast_nonneg n + constructor + · rintro ⟨x, y, hxy, h1, h2⟩ + have hy : y ^ 2 ≤ (n : ℝ) ^ 2 := by nlinarith [sq_nonneg (x - c)] + obtain ⟨hy1, hy2⟩ := abs_le_of_sq_le_sq' hy hn + exact ⟨by linarith, by linarith⟩ + · rintro ⟨h1, h2⟩ + set y := max ((j : ℝ) * (√3 / 2)) (-(n : ℝ)) with hy + have hy1 : (j : ℝ) * (√3 / 2) ≤ y := le_max_left _ _ + have hy2 : -(n : ℝ) ≤ y := le_max_right _ _ + have hy3 : y ≤ n := max_le h1 (by linarith) + have hy4 : y ≤ ((j : ℝ) + 1) * (√3 / 2) := max_le (by nlinarith) h2 + have hnn : 0 ≤ (n : ℝ) ^ 2 - y ^ 2 := by nlinarith + refine ⟨c + √((n : ℝ) ^ 2 - y ^ 2), y, ?_, hy1, hy4⟩ + rw [add_sub_cancel_left, sq_sqrt hnn] + ring + +/-- The geometric condition is equivalent to the integer condition `MeetsInt`, for every +center `(c, 0)`. -/ +theorem rowMeets_iff (c : ℝ) (n : ℕ) (j : ℤ) : RowMeets c n j ↔ MeetsInt n j := by + rw [rowMeets_iff_real, MeetsInt, mul_half_sqrt_three_le_iff] + have : -(n : ℝ) ≤ ((j : ℝ) + 1) * (√3 / 2) ↔ ((-(j + 1) : ℤ) : ℝ) * (√3 / 2) ≤ n := by + push_cast + constructor <;> intro h <;> linarith + rw [this, mul_half_sqrt_three_le_iff, neg_nonpos, neg_sq] + +theorem bounds_of_meetsInt {n : ℕ} {j : ℤ} (h : MeetsInt n j) : + -(2 * (n : ℤ) + 2) ≤ j ∧ j ≤ 2 * n + 2 := by + have hn : (0 : ℤ) ≤ n := Int.natCast_nonneg n + obtain ⟨h1 | h1, h2 | h2⟩ := h <;> constructor <;> nlinarith + +/-- `a n` is the number of rows `j : ℤ` meeting the circle of radius `n` centered at `(c, 0)`, +for any `c` (in particular for the centers `(0,0)` and `(1/2,0)` of the OEIS name). -/ +theorem a_eq_ncard (c : ℝ) (n : ℕ) : a n = {j : ℤ | RowMeets c n j}.ncard := by + have hset : {j : ℤ | RowMeets c n j} = + ↑(((Finset.range (4 * n + 5)).filter + (fun i : ℕ => MeetsInt n ((i : ℤ) - (2 * n + 2)))).image + (fun i : ℕ => (i : ℤ) - (2 * n + 2))) := by + ext j + simp only [Set.mem_ofPred_eq, rowMeets_iff, Finset.coe_image, Finset.coe_filter, + Finset.mem_range, Set.mem_image] + constructor + · intro hj + obtain ⟨hb1, hb2⟩ := bounds_of_meetsInt hj + refine ⟨(j + (2 * n + 2)).toNat, ⟨?_, ?_⟩, ?_⟩ + · omega + · rwa [Int.toNat_of_nonneg (by omega), add_sub_cancel_right] + · rw [Int.toNat_of_nonneg (by omega), add_sub_cancel_right] + · rintro ⟨i, ⟨_, hi⟩, rfl⟩ + exact hi + rw [hset, Set.ncard_coe_finset, Finset.card_image_of_injective _ (fun i i' h => by + simpa using h)] + rfl + +/-! ### The conjecture -/ + +open PowerSeries in +/-- Stephan's conjectured g.f., as an identity in `ℤ⟦X⟧` with the denominator cleared: +`(∑_{n ≥ 1} a(n) xⁿ) · (x¹⁴ - x¹³ - x + 1) = -2x¹⁴ + 4x¹³ + 2x¹² + 2x¹¹ + 2x¹⁰ + 2x⁹ + 2x⁸ + +4x⁷ + 2x⁶ + 2x⁵ + 2x⁴ + 2x³ + 2x² + 4x`. -/ +def statement : Prop := + PowerSeries.mk (fun n => if n = 0 then (0 : ℤ) else a n) * (X ^ 14 - X ^ 13 - X + 1) = + -2 * X ^ 14 + 4 * X ^ 13 + 2 * X ^ 12 + 2 * X ^ 11 + 2 * X ^ 10 + 2 * X ^ 9 + 2 * X ^ 8 + + 4 * X ^ 7 + 2 * X ^ 6 + 2 * X ^ 5 + 2 * X ^ 4 + 2 * X ^ 3 + 2 * X ^ 2 + 4 * X + +/-- The asymptotic claim drawn from the conjectured g.f.: `a(n) ~ 30/13 · n`. +Not part of `statement`. -/ +def statement_asymptotic : Prop := + Asymptotics.IsEquivalent Filter.atTop (fun n : ℕ => (a n : ℝ)) (fun n => 30 / 13 * (n : ℝ)) + +end Math0.Statements.A242396 diff --git a/lean/Math0/Statements/OEIS/A249434.lean b/lean/Math0/Statements/OEIS/A249434.lean new file mode 100644 index 0000000..691637e --- /dev/null +++ b/lean/Math0/Statements/OEIS/A249434.lean @@ -0,0 +1,210 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A249434: `A249151(k) = k` exactly when `k + 1` is prime + +Source: https://oeis.org/A249434, Antti Karttunen, Nov 02 2014 (COMMENTS section). Verbatim: +> It seems that A006093 gives all those k for which A249151(k) = k. If that is true, then this +> is a disjoint union of A006093 and A249429. + +The same claim appears in A249151 ("A006093 seems to give all such k, that a(k) = k"), and the +cross-references of A249434 list "Subsequences: A006093 (conjectured)". + +## The sequences involved + +* A249434 (offset `1`): "Integers m such that m! divides the product of elements on row m of + Pascal's triangle." Data: `0, 1, 2, 4, 6, 10, 12, 16, 18, 22, …`. +* A249151 (offset `0`): "Largest m such that m! divides the product of elements on row n of + Pascal's triangle." +* A006093 (offset `1`): `a(n) = prime(n) - 1`, i.e. `1, 2, 4, 6, 10, 12, …`. So a natural number + `k` lies in A006093 iff `k + 1` is prime. + +## Encoding + +* `rowProd n = ∏_{j = 0..n} C(n, j)` is the product of the elements of row `n` of Pascal's + triangle (A001142). +* `IsTerm m := m ! ∣ rowProd m` is the defining property of A249434, and + `a n = Nat.nth IsTerm (n - 1)` (offset `1`) lists its terms in increasing order. `Nat.nth` is + noncomputable (finiteness of the gaps is not known in Lean), so `a` is noncomputable; the + predicate `IsTerm` itself is decidable. `a_data` checks all `81` listed terms `a 1, …, a 81` + (all terms `≤ 256`) through a kernel scan over `m < 257`. For speed, the kernel computes + `rowProd m` by the recurrence `rowProd (n+1) * (n+1)! = rowProd n * (n+1)^(n+1)` + (`rowProd_succ_mul`), proved here. +* `A249151 n` is computed by an upward search (the set `{m | m ! ∣ rowProd n}` is downward closed + since `j ! ∣ m !` for `j ≤ m`, and bounded since `rowProd n ≥ 1`). `A249151_isGreatest` proves + that `A249151 n` is the greatest `m` with `m ! ∣ rowProd n`, and `A249151_data` checks the + first `81` listed terms of A249151. +* "A006093 gives all those k for which A249151(k) = k" is read as the set equality + `{k | A249151(k) = k} = A006093` (both inclusions: the follow-up "this is a disjoint union of + A006093 and A249429" and the cross-reference "Subsequences: A006093 (conjectured)" both need + `A006093 ⊆ {k | A249151(k) = k}` as well). So `statement` is: for every `k ≥ 0`, + `k` is the largest `m` with `m ! ∣ rowProd k` iff `k + 1` is prime. `statement_iff` restates + it with the function `A249151`. +-/ + +namespace Math0.Statements.A249434 + +open Finset Nat + +/-! ### The row products of Pascal's triangle -/ + +/-- The product of the elements of row `n` of Pascal's triangle, `∏_{j=0..n} C(n, j)` +(A001142). -/ +def rowProd (n : ℕ) : ℕ := ∏ j ∈ range (n + 1), n.choose j + +theorem rowProd_pos (n : ℕ) : 0 < rowProd n := + Finset.prod_pos fun j hj => Nat.choose_pos (by simp at hj; omega) + +/-- `∏_{j < N} (N - j) = N!`. -/ +theorem prod_range_sub_eq_factorial (N : ℕ) : ∏ j ∈ range N, (N - j) = N ! := by + rw [← Finset.prod_range_add_one_eq_factorial, ← Finset.prod_range_reflect (fun j => j + 1) N] + refine Finset.prod_congr rfl fun j hj => ?_ + simp at hj + omega + +/-- The recurrence `P(n+1) * (n+1)! = P(n) * (n+1)^(n+1)` for the row products. -/ +theorem rowProd_succ_mul (n : ℕ) : rowProd (n + 1) * (n + 1)! = rowProd n * (n + 1) ^ (n + 1) := by + have h1 : rowProd (n + 1) = ∏ j ∈ range (n + 1), (n + 1).choose j := by + rw [rowProd, Finset.prod_range_succ, Nat.choose_self, mul_one] + have h2 : (n + 1) ^ (n + 1) = ∏ _j ∈ range (n + 1), (n + 1) := by simp + rw [h1, ← prod_range_sub_eq_factorial, ← Finset.prod_mul_distrib, rowProd, h2, + ← Finset.prod_mul_distrib] + refine Finset.prod_congr rfl fun j _ => ?_ + rw [Nat.choose_mul_succ_eq] + +/-- Kernel-friendly computation of `(rowProd n, n !)`. -/ +def rowProdFact : ℕ → ℕ × ℕ + | 0 => (1, 1) + | n + 1 => + match rowProdFact n with + | (p, f) => (p * (n + 1) ^ (n + 1) / (f * (n + 1)), f * (n + 1)) + +theorem rowProdFact_eq (n : ℕ) : rowProdFact n = (rowProd n, n !) := by + induction n with + | zero => simp [rowProdFact, rowProd] + | succ n ih => + rw [rowProdFact, ih] + simp only [Prod.mk.injEq] + have hf : n ! * (n + 1) = (n + 1)! := by rw [Nat.factorial_succ, mul_comm] + rw [hf] + refine ⟨?_, rfl⟩ + exact Nat.div_eq_of_eq_mul_left (Nat.factorial_pos _) (rowProd_succ_mul n).symm + +/-! ### A249434 -/ + +/-- The defining property of A249434: `m !` divides the product of row `m` of Pascal's +triangle. -/ +def IsTerm (m : ℕ) : Prop := m ! ∣ rowProd m + +theorem isTerm_iff_check (m : ℕ) : + IsTerm m ↔ (rowProdFact m).1 % (rowProdFact m).2 = 0 := by + rw [rowProdFact_eq, IsTerm, Nat.dvd_iff_mod_eq_zero] + +instance : DecidablePred IsTerm := fun m => decidable_of_iff _ (isTerm_iff_check m).symm + +/-- A249434: the `n`-th smallest (offset `1`) integer `m ≥ 0` such that `m !` divides the +product of the elements on row `m` of Pascal's triangle. -/ +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) + +/-- The elements `< N` satisfying `p`, in increasing order, are `nth p 0, nth p 1, …`. -/ +theorem filter_range_eq (p : ℕ → Prop) [DecidablePred p] (N : ℕ) : + (List.range N).filter (fun k => decide (p k)) = + (List.range (Nat.count p N)).map (Nat.nth p) := by + induction N with + | zero => simp + | succ N ih => + rw [List.range_succ, List.filter_append, ih, Nat.count_succ] + by_cases h : p N + · simp [h, List.range_succ, Nat.nth_count h] + · simp [h] + +theorem map_nth_eq_of_filter {p : ℕ → Prop} [DecidablePred p] {N K : ℕ} {L : List ℕ} + (h : (List.range N).filter (fun k => decide (p k)) = L) (hK : L.length = K) : + (List.range K).map (Nat.nth p) = L := by + rw [filter_range_eq] at h + subst h + simp only [List.length_map, List.length_range] at hK + rw [hK] + +/-- The definition reproduces all 81 terms listed in OEIS (all terms `≤ 256`; kernel-checked). -/ +theorem a_data : (List.range 81).map (fun i => a (i + 1)) = + [0, 1, 2, 4, 6, 10, 12, 16, 18, 22, 28, 30, 35, 36, 39, 40, 42, 46, 52, 58, 60, 62, 66, 70, + 72, 78, 79, 82, 83, 88, 89, 96, 100, 102, 104, 106, 107, 108, 112, 126, 130, 131, 136, + 138, 143, 148, 149, 150, 153, 156, 159, 162, 164, 166, 167, 172, 174, 175, 178, 179, 180, + 181, 190, 192, 194, 196, 197, 198, 199, 207, 209, 210, 219, 222, 226, 228, 232, 238, 240, + 250, 256] := by + have : (fun i => a (i + 1)) = Nat.nth IsTerm := funext fun i => by simp [a] + rw [this] + exact map_nth_eq_of_filter (N := 257) (by decide +kernel) rfl + +/-! ### A249151 -/ + +/-- Upward search: starting from `m` with `m ! ∣ P`, step up while `(m + 1)! ∣ P`, with `fuel` +steps at most. -/ +def lastFact (P : ℕ) : ℕ → ℕ → ℕ + | 0, m => m + | f + 1, m => if (m + 1)! ∣ P then lastFact P f (m + 1) else m + +theorem lastFact_spec (P : ℕ) (hP : 0 < P) (f m : ℕ) (hm : m ! ∣ P) (hf : P ≤ m + f) : + (lastFact P f m)! ∣ P ∧ ¬ (lastFact P f m + 1)! ∣ P := by + induction f generalizing m with + | zero => + refine ⟨hm, fun h => ?_⟩ + have h1 := Nat.le_of_dvd hP h + have h2 := Nat.self_le_factorial (m + 1) + simp only [lastFact] at h1 h2 + omega + | succ f ih => + rw [lastFact] + split_ifs with h + · exact ih (m + 1) h (by omega) + · exact ⟨hm, h⟩ + +/-- A249151: the largest `m` such that `m !` divides the product of the elements on row `n` of +Pascal's triangle. -/ +def A249151 (n : ℕ) : ℕ := lastFact (rowProd n) (rowProd n) 0 + +/-- `A249151 n` is the greatest `m` with `m ! ∣ rowProd n`. -/ +theorem A249151_isGreatest (n : ℕ) : IsGreatest {m : ℕ | m ! ∣ rowProd n} (A249151 n) := by + obtain ⟨h1, h2⟩ := lastFact_spec (rowProd n) (rowProd_pos n) (rowProd n) 0 (by simp) + (by omega) + refine ⟨h1, fun m hm => ?_⟩ + by_contra hlt + exact h2 ((Nat.factorial_dvd_factorial (by unfold A249151 at *; omega)).trans hm) + +theorem A249151_eq_iff (n k : ℕ) : A249151 n = k ↔ IsGreatest {m : ℕ | m ! ∣ rowProd n} k := + ⟨fun h => h ▸ A249151_isGreatest n, fun h => (A249151_isGreatest n).unique h⟩ + +/-- Kernel-friendly version of `A249151`. -/ +def A249151' (n : ℕ) : ℕ := lastFact (rowProdFact n).1 (rowProdFact n).1 0 + +theorem A249151'_eq (n : ℕ) : A249151' n = A249151 n := by + simp [A249151', A249151, rowProdFact_eq] + +/-- The definition of `A249151` reproduces its first 81 listed terms (kernel-checked). -/ +theorem A249151_data : (List.range 81).map A249151 = + [1, 1, 2, 1, 4, 2, 6, 1, 2, 4, 10, 7, 12, 6, 4, 1, 16, 2, 18, 4, 6, 10, 22, 11, 4, 12, 2, 6, + 28, 25, 30, 1, 10, 16, 6, 36, 36, 18, 12, 40, 40, 6, 42, 10, 23, 22, 46, 19, 6, 4, 16, 12, + 52, 2, 10, 35, 18, 28, 58, 47, 60, 30, 63, 1, 12, 10, 66, 16, 22, 49, 70, 41, 72, 36, 4, + 18, 10, 12, 78, 80, 2] := by + have : A249151 = A249151' := funext fun n => (A249151'_eq n).symm + rw [this] + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjecture (Karttunen, A249434 / A249151): A006093 (the numbers `prime(n) - 1`) is exactly +the set of `k` with `A249151(k) = k`. That is, for every `k ≥ 0`, `k` is the largest `m` such +that `m !` divides the product of the elements on row `k` of Pascal's triangle if and only if +`k + 1` is prime. -/ +def statement : Prop := + ∀ k : ℕ, IsGreatest {m : ℕ | m ! ∣ rowProd k} k ↔ (k + 1).Prime + +/-- The same statement phrased with the function `A249151`. -/ +theorem statement_iff : statement ↔ ∀ k : ℕ, A249151 k = k ↔ (k + 1).Prime := by + simp only [statement, A249151_eq_iff] + +end Math0.Statements.A249434 diff --git a/lean/Math0/Statements/OEIS/A262957.lean b/lean/Math0/Statements/OEIS/A262957.lean new file mode 100644 index 0000000..ddd5ab2 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A262957.lean @@ -0,0 +1,102 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A262957: Israel's recurrence for `1 - 1/(2 + 1/(3 - 1/(4 + …)))` gives coprime pairs + +Source: https://oeis.org/A262957, _Robert Israel_, Dec 22 2015 (comment in the entry by +_Mohamed Sabba_). Verbatim (COMMENTS section): +> From _Robert Israel_, Dec 22 2015: (Start) +> a(n) is the numerator of b(n)/c(n) where +> b(1) = 2, b(2) = 3, c(1) = 3, c(2) = 5, +> b(n+1) = (((-1)^n*(n-1)+n*(n+2))*b(n) - (1+(-1)^n*(n+1))*b(n-1))/(n-(-1)^n), +> c(n+1) = (((-1)^n*(n-1)+n*(n+2))*c(n) - (1+(-1)^n*(n+1))*c(n-1))/(n-(-1)^n). +> Conjecture: b(n) and c(n) are coprime for all n, so that a(n) = b(n). +> I have verified this for n <= 10000. (End) + +The sequence (offset `1`) is "Numerators of the n-th iteration of the alternating continued +fraction formed from the positive integers, starting with (1 - ...)". The examples fix the +meaning of "n-th iteration": `a(1)`: `1-1/(2+1) = 2/3`, `a(2)`: `1-1/(2+1/(3-1)) = 3/5`, +`a(3)`: `1-1/(2+1/(3-1/(4+1))) = 19/33`, i.e. the integers `1, 2, …, n+1` are used, the sign +after `k` is `(-1)^k`, and the innermost tail is `1` (this is also what the entry's PARI +program computes). + +## Encoding + +* `cf n : ℚ` is the `n`-th iteration `1 - 1/(2 + 1/(3 - … (n+1) + (-1)^(n+1)/1))`, computed + exactly in `ℚ` as the right fold of `k, t ↦ k + (-1)^k / t` over `[1, 2, …, n+1]` starting + from `t = 1`. For `n ≥ 1` no intermediate denominator vanishes (each inner value is `≥ 1`), + so Lean's convention `x / 0 = 0` never intervenes. +* `a n` is the numerator of `cf n` in lowest terms (`Rat.num`, as a natural number via + `Int.natAbs`, matching the PARI program's `denominator(1/t)`; `cf n > 0` for `n ≥ 1`). It uses + the OEIS offset `1` and reproduces all 22 listed terms (`a_data`). +* `b n`, `c n : ℚ` are Israel's sequences, defined literally by the displayed recurrence in `ℚ` + (the recurrence involves a division, so they are a priori rationals). `b 0`, `c 0` are + never used (the recurrence starts at index 1); the step for `b (n+1)` is applied for `n ≥ 2`, + where the divisor `n - (-1)^n` is nonzero. +* The conjecture is read as: for every `n ≥ 1` (the indexing of `b`, `c` starts at `1`), + `b n` and `c n` are integers `p`, `q` with `gcd(p, q) = 1`, and the stated consequence + `a(n) = b(n)` holds. Both parts of the sentence "b(n) and c(n) are coprime for all n, so that + a(n) = b(n)" are included in `statement`; the second part also relies on Israel's (unproved + in the entry) assertion that `a(n)` is the numerator of `b(n)/c(n)`. +-/ + +namespace Math0.Statements.A262957 + +/-- The `n`-th iteration of the alternating continued fraction +`1 - 1/(2 + 1/(3 - 1/(4 + … (n+1) ± 1/1)))`: the right fold of `k, t ↦ k + (-1)^k / t` over +`k = 1, 2, …, n+1`, starting from the innermost value `1`. -/ +def cf (n : ℕ) : ℚ := + (List.range' 1 (n + 1)).foldr (fun (k : ℕ) (t : ℚ) => (k : ℚ) + (-1) ^ k / t) 1 + +/-- A262957 (offset `1`): the numerator, in lowest terms, of the `n`-th iteration of the +alternating continued fraction `1 - 1/(2 + 1/(3 - 1/(4 + …)))`. -/ +def a (n : ℕ) : ℕ := (cf n).num.natAbs + +/-- The definition reproduces all 22 terms listed in OEIS, `a 1, …, a 22` (kernel-checked). -/ +theorem a_data : (List.range 22).map (fun i => a (i + 1)) = + [2, 3, 19, 64, 538, 2833, 29169, 210308, 2572158, 23595915, 334778571, 3732092084, + 60305234822, 791741083537, 14359827157009, 217037153818264, 4366918714540522, + 74685204276602819, 1651116684587556019, 31524723785455714840, 759659139498065625218, + 16017463672140861567617] := by + decide +kernel + +/-- One step of Israel's recurrence at index `m`: given `x(m-1) = u` and `x(m) = v`, returns +`x(m+1) = (((-1)^m*(m-1) + m*(m+2))*x(m) - (1 + (-1)^m*(m+1))*x(m-1)) / (m - (-1)^m)`. -/ +def step (m : ℕ) (u v : ℚ) : ℚ := + (((-1) ^ m * ((m : ℚ) - 1) + (m : ℚ) * ((m : ℚ) + 2)) * v + - (1 + (-1) ^ m * ((m : ℚ) + 1)) * u) / ((m : ℚ) - (-1) ^ m) + +/-- The pair `(x(n+1), x(n+2))` of the sequence with `x(1) = x₁`, `x(2) = x₂` and +`x(m+1) = step m (x(m-1)) (x(m))` for `m ≥ 2`. -/ +def israelPair (x₁ x₂ : ℚ) : ℕ → ℚ × ℚ + | 0 => (x₁, x₂) + | n + 1 => + let p := israelPair x₁ x₂ n + (p.2, step (n + 2) p.1 p.2) + +/-- Israel's `b(n)` (`n ≥ 1`): `b(1) = 2`, `b(2) = 3`, +`b(n+1) = (((-1)^n*(n-1)+n*(n+2))*b(n) - (1+(-1)^n*(n+1))*b(n-1))/(n-(-1)^n)`. +(`b 0` is an unused junk value.) -/ +def b (n : ℕ) : ℚ := (israelPair 2 3 (n - 1)).1 + +/-- Israel's `c(n)` (`n ≥ 1`): `c(1) = 3`, `c(2) = 5`, same recurrence as `b`. +(`c 0` is an unused junk value.) -/ +def c (n : ℕ) : ℚ := (israelPair 3 5 (n - 1)).1 + +/-- Sanity check: `b` and `c` satisfy the stated initial values and the recurrence at +`n = 2, 3`, and give `b(3)/c(3) = 19/33`, `b(4)/c(4) = 64/111` (as in the OEIS examples). -/ +theorem bc_data : (List.range 6).map (fun i => (b (i + 1), c (i + 1))) = + [(2, 3), (3, 5), (19, 33), (64, 111), (538, 933), (2833, 4913)] := by + decide +kernel + +/-- Conjecture (Robert Israel, A262957): for all `n ≥ 1`, `b(n)` and `c(n)` are coprime +integers, so that `a(n) = b(n)`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + ∃ p q : ℤ, b n = (p : ℚ) ∧ c n = (q : ℚ) ∧ Int.gcd p q = 1 ∧ + ((a n : ℕ) : ℚ) = b n + +end Math0.Statements.A262957 diff --git a/lean/Math0/Statements/OEIS/A265210.lean b/lean/Math0/Statements/OEIS/A265210.lean new file mode 100644 index 0000000..e7ba5ba --- /dev/null +++ b/lean/Math0/Statements/OEIS/A265210.lean @@ -0,0 +1,129 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A265210: columns of the reversed ternary digits of `2^n` + +Source: https://oeis.org/A265210, L. Edson Jeffery, Dec 04 2015 (COMMENTS section). Verbatim: +> Conjecture 1: The sequence in column k is periodic, with period p(k) = 2*3^(k-1) = +> A008776(k-1), k >= 1, and in which the numbers 0,1,2 appear with equal frequency, for each +> k>1. + +The entry (L. Edson Jeffery, Dec 04 2015, offset `0`) is "Irregular triangle read by rows in +which row n lists the base 3 digits of 2^n in reverse order, n >= 0." Data: +`1, 2, 1, 1, 2, 2, 1, 2, 1, 2, 1, 0, …` (84 terms, rows `n = 0, …, 15`). + +## Encoding + +* *The triangle.* `row n = Nat.digits 3 (2 ^ n)` is row `n` (`n ≥ 0`): `Nat.digits` lists the + base-3 digits least significant first, i.e. the base-3 digits of `2^n` "in reverse order" + (row `5`: `2^5 = 1012₃`, `row 5 = [2, 1, 0, 1]`, as in the entry's example). Every row is + nonempty (`2^n > 0`). +* *The sequence.* `a m` is the `m`-th term (offset `0`) of the triangle read by rows, i.e. the + `m`-th entry of the concatenation `row 0 ++ row 1 ++ ⋯`. Since every row is nonempty, the + first `m + 1` rows already contain at least `m + 1` entries, so + `a m = (row 0 ++ ⋯ ++ row m)[m]` (the default `0` of `getD` is never used). + `a_data` checks all 84 listed terms. +* *Columns.* Column `k` (`k ≥ 1`) consists of the `k`-th entries of the rows, read top to bottom. + `T n k = (row n)[k-1]` is the entry of row `n` in column `k`; it exists iff + `k ≤ (row n).length`, i.e. iff `3^(k-1) ≤ 2^n`. Since the row lengths are nondecreasing in + `n`, column `k` is the sequence `T n₀ k, T (n₀+1) k, …`, where `n₀` is the first row of + length `≥ k`; the rows with an entry in column `k` are exactly the `n ≥ n₀`. (Column `1` is + `1, 2, 1, 2, …`; column `2` starts at row `2`: `1, 2, 2, 1, 0, 0, 1, …`; see `col1_data`, + `col2_data`, `col3_data`.) +* *Periods.* `IsColPeriod k q` says that `q` is a period of column `k`: `T (n + q) k = T n k` + for every row `n` that has an entry in column `k` (then so does row `n + q`). As a statement + about the column read as a sequence `c(j) = T (n₀ + j) k`, `j ≥ 0`, this is exactly + `∀ j, c (j + q) = c j`. +* *Reading choices.* + - "periodic, with period p(k)" is read as: `p(k) = 2*3^(k-1)` is *the* (least positive) + period of column `k`, i.e. `p(k)` is a period and no `q` with `0 < q < p(k)` is a period + (every positive multiple of a period would also be a period, so naming the specific value + `p(k)` refers to the least one). This part is asserted for every `k ≥ 1`. + - "the numbers 0,1,2 appear with equal frequency, for each k>1" is read as: for every + `k ≥ 2`, in every block of `p(k)` consecutive terms of column `k` (rows `m, …, m+p(k)-1` + with `m ≥ n₀`), the digits `0`, `1` and `2` occur the same number of times. Given the + periodicity part (a conjunct of the same statement), this is equivalent to each of + `0, 1, 2` having the same asymptotic frequency (necessarily `1/3`) in column `k`, and also + to equal counts in a single period; so the whole statement does not depend on this choice. +-/ + +namespace Math0.Statements.A265210 + +/-- Row `n` of the triangle: the base-3 digits of `2^n` in reverse order (least significant +digit first). -/ +def row (n : ℕ) : List ℕ := Nat.digits 3 (2 ^ n) + +/-- A265210: the triangle whose row `n` lists the base-3 digits of `2^n` in reverse order, read +by rows (offset `0`). The first `m + 1` rows contain at least `m + 1` entries. -/ +def a (m : ℕ) : ℕ := ((List.range (m + 1)).flatMap row).getD m 0 + +/-- The definition reproduces all 84 terms listed in OEIS (rows `0, …, 15`; kernel-checked). -/ +theorem a_data : (List.range 84).map (fun i => a (i + 0)) = + [1, 2, 1, 1, 2, 2, 1, 2, 1, 2, 1, 0, 1, 1, 0, 1, 2, 2, 0, 2, 1, 1, 1, 1, 1, 0, 0, 1, 2, 2, + 2, 0, 0, 2, 1, 2, 2, 1, 0, 1, 1, 2, 1, 2, 0, 1, 2, 2, 1, 0, 2, 1, 2, 1, 2, 1, 2, 0, 1, 0, + 2, 0, 2, 0, 1, 1, 1, 2, 0, 1, 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, 1] := by + decide +kernel + +/-- The entry's example rows `13`, `14`, `15` (kernel-checked). -/ +theorem row_example : row 13 = [2, 0, 1, 0, 2, 0, 2, 0, 1] ∧ + row 14 = [1, 1, 2, 0, 1, 1, 1, 1, 2] ∧ row 15 = [2, 2, 1, 1, 2, 2, 2, 2, 1, 1] := by + decide +kernel + +/-- The entry of row `n` in column `k` (`k ≥ 1`): the `k`-th entry of row `n`, i.e. the base-3 +digit of `2^n` at the place `3^(k-1)`. It is an actual entry of the triangle iff +`k ≤ (row n).length`. -/ +def T (n k : ℕ) : ℕ := (row n).getD (k - 1) 0 + +/-- Column `1` (starting at row `0`) begins `1, 2, 1, 2, …` (kernel-checked). -/ +theorem col1_data : (List.range 12).map (fun i => T i 1) = [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2] ∧ + 1 ≤ (row 0).length := by + decide +kernel + +/-- Column `2` starts at row `2` and begins `1, 2, 2, 1, 0, 0, 1, 2, 2, 1, 0, 0` +(kernel-checked). -/ +theorem col2_data : (row 1).length < 2 ∧ 2 ≤ (row 2).length ∧ + (List.range 12).map (fun i => T (i + 2) 2) = [1, 2, 2, 1, 0, 0, 1, 2, 2, 1, 0, 0] := by + decide +kernel + +/-- Column `3` starts at row `4` (kernel-checked). -/ +theorem col3_data : (row 3).length < 3 ∧ 3 ≤ (row 4).length ∧ + (List.range 20).map (fun i => T (i + 4) 3) = + [1, 0, 1, 2, 1, 2, 2, 2, 2, 1, 2, 1, 0, 1, 0, 0, 0, 0, 1, 0] := by + decide +kernel + +/-- `q` is a period of column `k`: for every row `n` having an entry in column `k`, the entry +of row `n + q` in column `k` is the same. -/ +def IsColPeriod (k q : ℕ) : Prop := + ∀ n : ℕ, k ≤ (row n).length → T (n + q) k = T n k + +/-- The conjectured period `p(k) = 2*3^(k-1) = A008776(k-1)` of column `k`. -/ +def p (k : ℕ) : ℕ := 2 * 3 ^ (k - 1) + +/-- Finite sanity check of the conjectured behaviour for columns `2` and `3` (not part of the +statement): `p 2 = 6` and `p 3 = 18` are periods on the first rows checked, and the first +period of each column contains each digit `0, 1, 2` equally often (kernel-checked). -/ +theorem sanity_small_columns : + p 2 = 6 ∧ p 3 = 18 ∧ + (List.range 40).all (fun i => T (i + 2 + 6) 2 == T (i + 2) 2) = true ∧ + (List.range 40).all (fun i => T (i + 4 + 18) 3 == T (i + 4) 3) = true ∧ + (List.range 3).map (fun d => ((List.range 6).filter (fun i => T (i + 2) 2 == d)).length) = + [2, 2, 2] ∧ + (List.range 3).map (fun d => ((List.range 18).filter (fun i => T (i + 4) 3 == d)).length) = + [6, 6, 6] := by + decide +kernel + +/-- Conjecture 1 (L. Edson Jeffery, 2015): for every `k ≥ 1`, column `k` is periodic with +(least) period `p(k) = 2*3^(k-1)`; and for every `k > 1`, in each period of column `k` (every +block of `p(k)` consecutive terms of the column) the digits `0`, `1`, `2` occur equally +often. -/ +def statement : Prop := + ∀ k : ℕ, 1 ≤ k → + (IsColPeriod k (p k) ∧ ∀ q : ℕ, 0 < q → q < p k → ¬ IsColPeriod k q) ∧ + (2 ≤ k → ∀ m : ℕ, k ≤ (row m).length → ∀ d e : ℕ, d < 3 → e < 3 → + ((Finset.Ico m (m + p k)).filter (fun n => T n k = d)).card = + ((Finset.Ico m (m + p k)).filter (fun n => T n k = e)).card) + +end Math0.Statements.A265210 diff --git a/lean/Math0/Statements/OEIS/A265649.lean b/lean/Math0/Statements/OEIS/A265649.lean new file mode 100644 index 0000000..c785126 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A265649.lean @@ -0,0 +1,185 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A265649: two closed forms for the triangle `T(n,k) = T(n-1,k-1) + (2n-1+k) T(n-1,k)` + +Source: https://oeis.org/A265649, _Werner Schulte_, Dec 11 2015 (FORMULA section). Verbatim: +> Conjecture: T(n,k) = 2^(n-k)*(n-k)!*binomial(n,k)*(Sum_{j=0..n-k} (-1/4)^j* +> binomial(2*j+k,j)*binomial(n,j+k)). +> Conjecture: T(n,k) = (-1)^k*Sum_{j=0..n-1} A001497(n-1,j)*A021009(j+1,k). + +The entry (_Werner Schulte_, Dec 11 2015, offset `0`, keyword `tabl`) is "Triangle of +coefficients T(n,k) of polynomials p(n,x) = Sum_{k=0..n} T(n,k)*x^k where T(0,0) = 1, and +T(n,k) = 0 for k < 0 or k > n, and T(n,k) = T(n-1,k-1) + (2*n-1+k)*T(n-1,k) for n > 0 and +0 <= k <= n." + +## Encoding + +* *The triangle.* `T : ℕ → ℕ → ℕ` is defined by the recurrence of the entry's name, written for + row `n + 1`: `T(0,0) = 1`, `T(0,k) = 0` for `k ≥ 1`, `T(n+1,0) = (2(n+1)-1+0)·T(n,0)` (the term + `T(n,-1)` is `0`), and `T(n+1,k+1) = T(n,k) + (2(n+1)-1+(k+1))·T(n,k+1)`. The definition + applies the recurrence also for `k + 1 > n + 1`; `T_eq_zero_of_lt` proves that this gives + `T(n,k) = 0` for all `k > n`, as the entry requires, so `T` is exactly the entry's triangle + (extended by `0` outside `0 ≤ k ≤ n`). +* *The sequence.* `a m` is the `m`-th term (offset `0`) of the triangle read by rows. + `a_data` checks all 55 listed terms (rows `n = 0, …, 9`) in the kernel; `T_data` checks the + same terms row by row. +* *The referenced triangles.* `A001497 m j` is the Bessel-polynomial triangle, through its + closed form from that entry, `a(n,m) = (2n-m)!/(m!(n-m)!2^(n-m))` for `n ≥ m ≥ 0`, else `0`; + `A021009 m k` is the (signed) Laguerre triangle `n!·L_n(x)`, through the closed form from that + entry, `a(n,m) = (-1)^m·n!·binomial(n,m)/m!` for `n ≥ m`, else `0`. Both are computed in `ℚ` + (so no exactness of a natural-number division is assumed); `A001497_data` and + `A021009_data` check them against all terms listed in those entries. +* *Conjecture 1* (`statement₁`): for every entry of the triangle (`n ≥ 0`, `0 ≤ k ≤ n`), + `T(n,k) = 2^(n-k)·(n-k)!·C(n,k)·∑_{j=0}^{n-k} (-1/4)^j·C(2j+k,j)·C(n,j+k)`, an identity in `ℚ` + (`n - k` is a genuine difference since `k ≤ n`). +* *Conjecture 2* (`statement₂`): for every `n ≥ 1` and `0 ≤ k ≤ n`, + `T(n,k) = (-1)^k·∑_{j=0}^{n-1} A001497(n-1,j)·A021009(j+1,k)`, an identity in `ℚ`. The range + `n ≥ 1` is forced by the formula: `A001497` has offset `0`, so `A001497(n-1,j)` only exists for + `n ≥ 1` (and for `n = 0` the sum would be empty). The terms with `j + 1 < k` vanish since then + `A021009(j+1,k) = 0`. +* *Reading choices.* Both conjectures are read on the entries of the triangle (`0 ≤ k ≤ n`); + for `k > n` both sides would be `0` anyway (`C(n,k) = 0`, resp. `A021009(j+1,k) = 0`). + `statement` is the conjunction of the two conjectures. `statement₁_check` and + `statement₂_check` verify them for `n ≤ 12` in the kernel (a sanity check of the transcription, + not a proof). +-/ + +namespace Math0.Statements.A265649 + +/-- A265649 as a triangle: `T(0,0) = 1`, `T(0,k) = 0` for `k > 0`, and for `n ≥ 0` +`T(n+1,k) = T(n,k-1) + (2(n+1)-1+k)·T(n,k)` (with `T(n,-1) = 0`). -/ +def T : ℕ → ℕ → ℕ + | 0, 0 => 1 + | 0, _ + 1 => 0 + | n + 1, 0 => (2 * (n + 1) - 1 + 0) * T n 0 + | n + 1, k + 1 => T n k + (2 * (n + 1) - 1 + (k + 1)) * T n (k + 1) + +/-- `T(n,k) = 0` for `k > n`, as in the entry. -/ +theorem T_eq_zero_of_lt {n k : ℕ} (h : n < k) : T n k = 0 := by + induction n generalizing k with + | zero => + obtain ⟨k, rfl⟩ := Nat.exists_eq_succ_of_ne_zero (by omega : k ≠ 0) + rfl + | succ n ih => + obtain ⟨k, rfl⟩ := Nat.exists_eq_succ_of_ne_zero (by omega : k ≠ 0) + rw [T, ih (by omega), ih (by omega), zero_add, mul_zero] + +/-- The recurrence of the entry, for `n > 0` and `1 ≤ k ≤ n` +(`T(n,k) = T(n-1,k-1) + (2n-1+k)·T(n-1,k)`), written with `n + 1`, `k + 1`. -/ +theorem T_succ_succ (n k : ℕ) : + T (n + 1) (k + 1) = T n k + (2 * (n + 1) - 1 + (k + 1)) * T n (k + 1) := by + rw [T] + +/-- A265649 read by rows (offset `0`): the `m`-th term is `T(n,k)` for the `m`-th pair `(n,k)`, +`0 ≤ k ≤ n`, in the order `(0,0), (1,0), (1,1), (2,0), …`. -/ +def a (m : ℕ) : ℕ := + let p := ((List.range (m + 1)).flatMap fun n => (List.range (n + 1)).map fun k => (n, k)).getD + m (0, 0) + T p.1 p.2 + +/-- The definition reproduces all 55 terms listed in OEIS (rows `0, …, 9`; kernel-checked). -/ +theorem a_data : (List.range 55).map (fun i => a (i + 0)) = + [1, 1, 1, 3, 5, 1, 15, 33, 12, 1, 105, 279, 141, 22, 1, 945, 2895, 1830, 405, 35, 1, 10395, + 35685, 26685, 7500, 930, 51, 1, 135135, 509985, 435960, 146685, 23310, 1848, 70, 1, + 2027025, 8294895, 7921305, 3076290, 589575, 60270, 3318, 92, 1, 34459425, 151335135, + 158799690, 69447105, 15457365, 1915515, 136584, 5526, 117, 1] := by + decide +kernel + +/-- The same 55 listed terms, read off `T` row by row (kernel-checked). -/ +theorem T_data : (List.range 10).flatMap (fun n => (List.range (n + 1)).map (fun k => T n k)) = + [1, 1, 1, 3, 5, 1, 15, 33, 12, 1, 105, 279, 141, 22, 1, 945, 2895, 1830, 405, 35, 1, 10395, + 35685, 26685, 7500, 930, 51, 1, 135135, 509985, 435960, 146685, 23310, 1848, 70, 1, + 2027025, 8294895, 7921305, 3076290, 589575, 60270, 3318, 92, 1, 34459425, 151335135, + 158799690, 69447105, 15457365, 1915515, 136584, 5526, 117, 1] := by + decide +kernel + +/-! ### The referenced triangles A001497 and A021009 -/ + +/-- A001497 (coefficients of the Bessel polynomials): `a(n,m) = (2n-m)!/(m!(n-m)!2^(n-m))` for +`n ≥ m ≥ 0`, else `0`. -/ +def A001497 (n m : ℕ) : ℚ := + if m ≤ n then + ((2 * n - m).factorial : ℚ) / ((m.factorial : ℚ) * ((n - m).factorial : ℚ) * 2 ^ (n - m)) + else 0 + +/-- A021009 (coefficients of `n!·L_n(x)`, rising powers of `x`): +`a(n,m) = (-1)^m·n!·binomial(n,m)/m!` for `n ≥ m`, else `0`. -/ +def A021009 (n m : ℕ) : ℚ := + if m ≤ n then + (-1) ^ m * (n.factorial : ℚ) * (n.choose m : ℚ) / (m.factorial : ℚ) + else 0 + +/-- `A001497` reproduces all 55 terms listed in that entry (rows `0, …, 9`; kernel-checked). -/ +theorem A001497_data : + (List.range 10).flatMap (fun n => (List.range (n + 1)).map (fun m => A001497 n m)) = + [1, 1, 1, 3, 3, 1, 15, 15, 6, 1, 105, 105, 45, 10, 1, 945, 945, 420, 105, 15, 1, 10395, + 10395, 4725, 1260, 210, 21, 1, 135135, 135135, 62370, 17325, 3150, 378, 28, 1, + 2027025, 2027025, 945945, 270270, 51975, 6930, 630, 36, 1, 34459425, 34459425, 16216200, + 4729725, 945945, 135135, 13860, 990, 45, 1] := by + decide +kernel + +/-- `A021009` reproduces all 47 terms listed in that entry (rows `0, …, 8` and the first two +terms of row `9`; kernel-checked). -/ +theorem A021009_data : + (List.range 9).flatMap (fun n => (List.range (n + 1)).map (fun m => A021009 n m)) ++ + [A021009 9 0, A021009 9 1] = + [1, 1, -1, 2, -4, 1, 6, -18, 9, -1, 24, -96, 72, -16, 1, 120, -600, 600, -200, 25, -1, 720, + -4320, 5400, -2400, 450, -36, 1, 5040, -35280, 52920, -29400, 7350, -882, 49, -1, + 40320, -322560, 564480, -376320, 117600, -18816, 1568, -64, 1, 362880, -3265920] := by + decide +kernel + +/-! ### The conjectures -/ + +/-- The right-hand side of the first conjecture: +`2^(n-k)·(n-k)!·C(n,k)·∑_{j=0}^{n-k} (-1/4)^j·C(2j+k,j)·C(n,j+k)`. -/ +def rhs₁ (n k : ℕ) : ℚ := + 2 ^ (n - k) * ((n - k).factorial : ℚ) * (n.choose k : ℚ) * + ∑ j ∈ Finset.range (n - k + 1), + (-1 / 4 : ℚ) ^ j * ((2 * j + k).choose j : ℚ) * (n.choose (j + k) : ℚ) + +/-- The right-hand side of the second conjecture: +`(-1)^k·∑_{j=0}^{n-1} A001497(n-1,j)·A021009(j+1,k)`. -/ +def rhs₂ (n k : ℕ) : ℚ := + (-1) ^ k * ∑ j ∈ Finset.range n, A001497 (n - 1) j * A021009 (j + 1) k + +/-- First conjecture (Werner Schulte, A265649): for all `0 ≤ k ≤ n`, +`T(n,k) = 2^(n-k)·(n-k)!·C(n,k)·∑_{j=0}^{n-k} (-1/4)^j·C(2j+k,j)·C(n,j+k)`. -/ +def statement₁ : Prop := + ∀ n k : ℕ, k ≤ n → (T n k : ℚ) = rhs₁ n k + +/-- Second conjecture (Werner Schulte, A265649): for all `n ≥ 1` and `0 ≤ k ≤ n`, +`T(n,k) = (-1)^k·∑_{j=0}^{n-1} A001497(n-1,j)·A021009(j+1,k)`. -/ +def statement₂ : Prop := + ∀ n k : ℕ, 1 ≤ n → k ≤ n → (T n k : ℚ) = rhs₂ n k + +/-- Sanity check of the first conjecture for `n ≤ 12` (kernel-checked; not a proof). -/ +theorem statement₁_check : + (List.range 13).all (fun n => (List.range (n + 1)).all + (fun k => decide ((T n k : ℚ) = rhs₁ n k))) = true := by + decide +kernel + +/-- Sanity check of the second conjecture for `1 ≤ n ≤ 12` (kernel-checked; not a proof). -/ +theorem statement₂_check : + (List.range 12).all (fun i => (List.range (i + 2)).all + (fun k => decide ((T (i + 1) k : ℚ) = rhs₂ (i + 1) k))) = true := by + decide +kernel + +/-- Both conjectures of Werner Schulte (A265649, Dec 11 2015): for all `0 ≤ k ≤ n`, +`T(n,k) = 2^(n-k)·(n-k)!·C(n,k)·∑_{j=0}^{n-k} (-1/4)^j·C(2j+k,j)·C(n,j+k)`, and for all +`n ≥ 1`, `0 ≤ k ≤ n`, `T(n,k) = (-1)^k·∑_{j=0}^{n-1} A001497(n-1,j)·A021009(j+1,k)`. -/ +def statement : Prop := + (∀ n k : ℕ, k ≤ n → + (T n k : ℚ) = 2 ^ (n - k) * ((n - k).factorial : ℚ) * (n.choose k : ℚ) * + ∑ j ∈ Finset.range (n - k + 1), + (-1 / 4 : ℚ) ^ j * ((2 * j + k).choose j : ℚ) * (n.choose (j + k) : ℚ)) ∧ + (∀ n k : ℕ, 1 ≤ n → k ≤ n → + (T n k : ℚ) = (-1) ^ k * ∑ j ∈ Finset.range n, A001497 (n - 1) j * A021009 (j + 1) k) + +/-- `statement` is the conjunction of the two conjectures. -/ +theorem statement_iff : statement ↔ statement₁ ∧ statement₂ := Iff.rfl + +end Math0.Statements.A265649 diff --git a/lean/Math0/Statements/OEIS/A267486.lean b/lean/Math0/Statements/OEIS/A267486.lean new file mode 100644 index 0000000..e2c6571 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A267486.lean @@ -0,0 +1,246 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A267486: Gaussian polynomials in the basis `(1+q^2)^k q^(g-k)` via Chebyshev products + +Source: https://oeis.org/A267486, Stephen O'Sullivan, Jan 15 2016 (COMMENTS section, text as of +revision #23, May 30 2026). Verbatim: +> Conjecture: More generally, the Gaussian polynomial [2*n+m+1-(m mod 2),m]_q = +> Sum_{k=0..g(m;n)} a(m;n,k)*(1+q^2)^k*q^(g(m;n)-k), for m >= 0, n >= 0, where g(m;n) = m*n if +> m is odd and (2*n+1)*m/2 if m is even, and the tabf array entries a(m;n,k) are the +> coefficients of the g.f. for the row n polynomials G(m;n,x) = (d^m/dt^m)G(m;n,t,x)/m!|_{t=0}, +> with G(m;n,t,x) = (1+t)*Product_{k=1..n+(m - m (mod 2))/2}(1 + t^2 + 2*t*T(k,x/2) +> (Chebyshev's T-polynomials). Hence a(m;n,k) = [x^k]G(m;n,x), for k=0..g(m;n). The present +> entry is the instance m = 2. (Thanks to _Wolfdieter Lang_ for clarifying the text on the +> general prescription of a(m;n,k).) + +The entry itself (offset `0`, keyword `tabf`) is "Triangle of coefficients of Gaussian +polynomials [2n+7,6]_q represented as finite sum of terms (1+q^2)^k*q^(g-k), where +k = 0,1,...,g with g=6n+3": row `n ≥ 0` lists `a(n,k)`, `k = 0..6n+3`, with +`[2n+7,6]_q = Sum_{k=0..g} a(n,k)*(1+q^2)^k*q^(g-k)`, and the sequence is the rows read in +order. (The representation is unique: `(1+q^2)^k*q^(g-k) = q^g*(q+1/q)^k`, and the powers of +`q+1/q` are linearly independent.) + +## Encoding + +* **The sequence `a`.** The terms are signed, so `a : ℕ → ℤ`. It is computed from the entry's + definition, not from the conjectured Chebyshev formula: `gaussL N m` is the coefficient list + of the Gaussian polynomial `[N,m]_q` (lowest degree first), computed by the q-Pascal rule + `[r+1,k+1]_q = [r,k]_q + q^(k+1)*[r,k+1]_q` (the same rule that defines `gaussBinom` below), + and `reprAux` peels off the basis elements from the top: `(1+q^2)^k*q^(g-k)` has degree + `g+k` and leading coefficient `1`, so for `k = g, g-1, …, 0` the coefficient of `q^(g+k)` in + the current remainder is the coefficient of `(1+q^2)^k*q^(g-k)`. This triangular elimination + returns the unique representation coefficients; `row_exact` checks (kernel) that the final + remainder is zero for every listed row, i.e. that the computed coefficients really represent + `[2n+7,6]_q`. `a i` finds the row `n` and position `k` of index `i` (row `n` has length + `6n+4`) and returns `a(n,k)`. `a_data` checks all 80 listed terms (rows `n = 0..4`). +* **The conjecture** is about every `m ≥ 0`, `n ≥ 0`, with `q` an indeterminate. + - `gaussBinom N m : ℤ[X]` is the Gaussian polynomial `[N,m]_q`, defined by the q-Pascal + rule with `[N,0]_q = 1` and `[0,m+1]_q = 0`; sanity lemmas `gaussBinom_four_two` and + `gaussBinom_five_two_mul` check it against the explicit value / the product formula + `[N,m]_q * Prod_{i=1..m}(1-q^i) = Prod_{i=0..m-1}(1-q^(N-i))`. + - `g m n` is `m*n` for odd `m` and `(2*n+1)*m/2` for even `m` (an exact division). + - `chebHalf k = T(k, x/2)`, Mathlib's Chebyshev polynomial of the first kind composed with + `x/2`, over `ℚ` (so that `x/2` makes sense). + - `Gt m n : ℚ[x][t]` is `G(m;n,t,x) = (1+t)*Prod_{k=1..n+(m - m mod 2)/2}(1+t^2+2t*T(k,x/2))` + as a polynomial in `t` with coefficients in `ℚ[x]`; the upper limit is written literally. + - `G m n : ℚ[x]` is `(d^m/dt^m) G(m;n,t,x) / m!` evaluated at `t = 0`, written literally with + Mathlib's iterated `derivative` (`G_eq_coeff` shows it is the `t^m`-coefficient). + - `a(m;n,k) = [x^k] G(m;n,x)` is `(G m n).coeff k : ℚ`. + - The Gaussian polynomial `[2*n+m+1-(m mod 2), m]_q` is mapped into `ℚ[q]` and compared with + `Sum_{k=0..g} C(a(m;n,k)) * (1+q^2)^k * q^(g-k)` (here `q` is `X : ℚ[X]`, and `g - k` is a + true difference since `k ≤ g`). + - The text also says that the row `n` entries `a(m;n,k)`, `k = 0..g(m;n)`, are the + coefficients of the generating function `G(m;n,x)` of row `n`; we therefore also state + `natDegree (G m n) ≤ g m n` (the row polynomial has no terms beyond `k = g(m;n)`). + Without this conjunct the identity alone would say nothing about the coefficients of `G` + beyond `x^g`. +* **Reading notes on the entry.** The comment says "The present entry is the instance m = 2", + but the entry's name, data and Maple program are the instance `m = 6` + (`[2n+7,6]_q`, `g = 6n+3`, product up to `n+3`); likewise the `%F` line and the Mathematica + program (copied from A267120) use `Product_{i=1..n+1}`, which is the `m = 6` instance only + with `n+3`. These slips do not affect the general conjecture, which is formalized as written. + `G_six_zero` checks that the formal `G 6 0` is `-1 - 2x + x^2 + x^3`, i.e. row 0 of the data, + and `G_two_zero` checks `G 2 0 = 1 + x` (`[3,2]_q = q + (1+q^2)`). +-/ + +namespace Math0.Statements.A267486 + +open Polynomial + +/-! ### The sequence (computable, from the entry's definition) -/ + +/-- Coefficientwise sum of two coefficient lists (lowest degree first). -/ +def addL : List ℤ → List ℤ → List ℤ + | [], q => q + | p, [] => p + | a :: p, b :: q => (a + b) :: addL p q + +/-- Multiplication of a coefficient list by `q ^ s`. -/ +def shiftL (s : ℕ) (p : List ℤ) : List ℤ := List.replicate s 0 ++ p + +/-- One q-Pascal step: from the list `[[r,0]_q, …, [r,m]_q]` of coefficient lists to +`[[r+1,0]_q, …, [r+1,m]_q]`, using `[r+1,0]_q = 1` and +`[r+1,k+1]_q = [r,k]_q + q^(k+1) [r,k+1]_q`. -/ +def pascalStep (m : ℕ) (prev : List (List ℤ)) : List (List ℤ) := + (List.range (m + 1)).map fun k => + match k with + | 0 => [1] + | k + 1 => addL (prev.getD k []) (shiftL (k + 1) (prev.getD (k + 1) [])) + +/-- `[[r,0]_q, …, [r,m]_q]`, starting from `[0,0]_q = 1`, `[0,k+1]_q = 0`. -/ +def gaussRows (m : ℕ) : ℕ → List (List ℤ) + | 0 => [1] :: List.replicate m [] + | r + 1 => pascalStep m (gaussRows m r) + +/-- Coefficient list (lowest degree first) of the Gaussian polynomial `[N,m]_q`. -/ +def gaussL (N m : ℕ) : List ℤ := (gaussRows m N).getD m [] + +/-- Coefficient list of `(1+q^2)^k`. -/ +def onePlusSqPow : ℕ → List ℤ + | 0 => [1] + | k + 1 => addL (onePlusSqPow k) (shiftL 2 (onePlusSqPow k)) + +/-- Coefficient list of the basis element `(1+q^2)^k * q^(g-k)`. -/ +def basisL (g k : ℕ) : List ℤ := shiftL (g - k) (onePlusSqPow k) + +/-- Triangular elimination in the basis `(1+q^2)^k q^(g-k)`: `reprAux g j r acc` treats +`k = j-1, j-2, …, 0` in turn, taking as coefficient of `(1+q^2)^k q^(g-k)` the coefficient of +`q^(g+k)` in the remainder `r` and subtracting that multiple of the basis element. It returns +the coefficients (prepended to `acc`, so in the order `k = 0, 1, …`) and the final remainder. -/ +def reprAux (g : ℕ) : ℕ → List ℤ → List ℤ → List ℤ × List ℤ + | 0, r, acc => (acc, r) + | j + 1, r, acc => + reprAux g j (addL r ((basisL g j).map fun x => -(r.getD (g + j) 0 * x))) + (r.getD (g + j) 0 :: acc) + +/-- Row `n` of A267486: the coefficients `a(n,0), …, a(n,6n+3)` of +`[2n+7,6]_q = Sum_{k=0..g} a(n,k) (1+q^2)^k q^(g-k)`, `g = 6n+3`. -/ +def row (n : ℕ) : List ℤ := (reprAux (6 * n + 3) (6 * n + 4) (gaussL (2 * n + 7) 6) []).1 + +/-- Position `(n, k)` in the triangle of the flat index `i` (row `n` has length `6n+4`); +`fuel = i + 1` always suffices since each step lowers `i` by at least `4`. -/ +def locate : ℕ → ℕ → ℕ → ℕ × ℕ + | 0, n, i => (n, i) + | fuel + 1, n, i => if i < 6 * n + 4 then (n, i) else locate fuel (n + 1) (i - (6 * n + 4)) + +/-- A267486 (offset `0`): the triangle `a(n,k)` of coefficients of `(1+q^2)^k q^(g-k)`, +`g = 6n+3`, in the Gaussian polynomial `[2n+7,6]_q`, read by rows. -/ +def a (i : ℕ) : ℤ := (row (locate (i + 1) 0 i).1).getD (locate (i + 1) 0 i).2 0 + +/-- The definition reproduces all 80 terms listed in OEIS (rows `n = 0..4`; kernel-checked). -/ +theorem a_data : (List.range 80).map (fun i => a (i + 0)) = + [-1, -2, 1, 1, 0, 2, -2, -15, 7, 17, -5, -7, 1, 1, -2, -6, 25, 71, -80, -218, 126, 284, + -106, -190, 48, 69, -11, -13, 1, 1, 0, 6, -12, -137, 196, 945, -811, -2745, 1602, + 4163, -1780, -3711, 1193, 2059, -493, -722, 123, 156, -17, -19, 1, 1, -3, -12, 94, 358, + -952, -3430, 4699, 15615, -13467, -39946, 24494, 63168, -29535, -65638, 24206, 46512, + -13652, -22891, 5294, 7834, -1386, -1831, 234, 279, -23, -25, 1, 1] := by + decide +kernel + +/-- For the listed rows the elimination leaves remainder `0`, so the computed coefficients +represent `[2n+7,6]_q` exactly; rows have length `6n+4` (kernel-checked). -/ +theorem row_exact : ∀ n < 5, + (reprAux (6 * n + 3) (6 * n + 4) (gaussL (2 * n + 7) 6) []).2.all (· = 0) = true ∧ + (row n).length = 6 * n + 4 := by + decide +kernel + +/-! ### The conjecture -/ + +/-- The Gaussian polynomial (q-binomial coefficient) `[N, m]_q ∈ ℤ[q]`, by the q-Pascal rule +`[N+1, m+1]_q = [N, m]_q + q^(m+1) [N, m+1]_q`, `[N, 0]_q = 1`, `[0, m+1]_q = 0`. -/ +noncomputable def gaussBinom : ℕ → ℕ → ℤ[X] + | _, 0 => 1 + | 0, _ + 1 => 0 + | N + 1, m + 1 => gaussBinom N m + X ^ (m + 1) * gaussBinom N (m + 1) + +theorem gaussBinom_four_two : gaussBinom 4 2 = 1 + X + 2 * X ^ 2 + X ^ 3 + X ^ 4 := by + simp [gaussBinom]; ring + +theorem gaussBinom_five_two_mul : + gaussBinom 5 2 * ((1 - X) * (1 - X ^ 2)) = (1 - X ^ 5) * (1 - X ^ 4) := by + simp [gaussBinom]; ring + +/-- `g(m;n) = m*n` if `m` is odd and `(2*n+1)*m/2` if `m` is even. -/ +def g (m n : ℕ) : ℕ := if m % 2 = 1 then m * n else (2 * n + 1) * m / 2 + +theorem g_six (n : ℕ) : g 6 n = 6 * n + 3 := by + simp [g]; omega + +/-- `T(k, x/2) ∈ ℚ[x]`, with `T` the Chebyshev polynomials of the first kind. -/ +noncomputable def chebHalf (k : ℕ) : ℚ[X] := (Chebyshev.T ℚ k).comp (C (1 / 2 : ℚ) * X) + +/-- `G(m;n,t,x) = (1+t) * Prod_{k=1..n+(m - m mod 2)/2} (1 + t^2 + 2*t*T(k,x/2))`, a polynomial +in `t` (the outer variable) with coefficients in `ℚ[x]`. -/ +noncomputable def Gt (m n : ℕ) : ℚ[X][X] := + (1 + X) * ∏ k ∈ Finset.Icc 1 (n + (m - m % 2) / 2), (1 + X ^ 2 + 2 * X * C (chebHalf k)) + +/-- `G(m;n,x) = (d^m/dt^m) G(m;n,t,x) / m! |_{t=0}`. -/ +noncomputable def G (m n : ℕ) : ℚ[X] := + C ((m.factorial : ℚ)⁻¹) * (derivative^[m] (Gt m n)).eval 0 + +/-- `G(m;n,x)` is the coefficient of `t^m` in `G(m;n,t,x)`. -/ +theorem G_eq_coeff (m n : ℕ) : G m n = (Gt m n).coeff m := by + rw [G, ← coeff_zero_eq_eval_zero, coeff_iterate_derivative, zero_add, Nat.descFactorial_self, + nsmul_eq_mul, ← mul_assoc] + have h : (m.factorial : ℚ[X]) = C (m.factorial : ℚ) := by simp + rw [h, ← C_mul, inv_mul_cancel₀ (by exact_mod_cast m.factorial_ne_zero), C_1, one_mul] + +theorem two_chebHalf_one : 2 * chebHalf 1 = X := by + apply Polynomial.funext; intro r + simp [chebHalf] + +theorem two_chebHalf_two : 2 * chebHalf 2 = X ^ 2 - 2 := by + apply Polynomial.funext; intro r + simp [chebHalf, Chebyshev.T_two]; ring + +theorem two_chebHalf_three : 2 * chebHalf 3 = X ^ 3 - 3 * X := by + have h3 : Chebyshev.T ℚ 3 = 2 * X * (2 * X ^ 2 - 1) - X := by + have := Chebyshev.T_add_two ℚ 1 + norm_num at this + rw [this, Chebyshev.T_two] + apply Polynomial.funext; intro r + simp [chebHalf, h3]; ring + +/-- Sanity check: `G(2;0,x) = 1 + x` (and indeed `[3,2]_q = 1 + q + q^2 = q + (1+q^2)`). -/ +theorem G_two_zero : G 2 0 = 1 + X := by + rw [G_eq_coeff] + have h1 : (1 + X : ℚ[X][X]) * (1 + X ^ 2 + 2 * X * C (chebHalf 1)) = + 1 + X + X ^ 2 * (1 + C (2 * chebHalf 1)) + X ^ 3 + X * C (2 * chebHalf 1) := by + rw [C_mul, C_ofNat]; ring + simp only [Gt, Nat.reduceMod, Nat.sub_zero, Nat.reduceDiv, zero_add, Finset.Icc_self, + Finset.prod_singleton] + rw [h1, two_chebHalf_one] + simp [coeff_X, coeff_one, coeff_X_pow, coeff_X_pow_mul'] + +theorem coeff_six_aux (a b c : ℚ[X]) : + ((1 + X) * ((1 + X ^ 2 + X * C a) * ((1 + X ^ 2 + X * C b) * (1 + X ^ 2 + X * C c)))).coeff 6 + = 1 + a + b + c := by + ring_nf + simp [coeff_mul_C, coeff_C_mul, coeff_mul_X_pow', coeff_X_pow, coeff_C, coeff_X, coeff_one] + +/-- Sanity check: `G(6;0,x) = -1 - 2x + x^2 + x^3`, i.e. row 0 of A267486 (`-1, -2, 1, 1`). -/ +theorem G_six_zero : G 6 0 = -1 - 2 * X + X ^ 2 + X ^ 3 := by + rw [G_eq_coeff] + have hI : Finset.Icc 1 (0 + (6 - 6 % 2) / 2) = {1, 2, 3} := by decide + have hf : ∀ k : ℕ, (1 + X ^ 2 + 2 * X * C (chebHalf k) : ℚ[X][X]) = + 1 + X ^ 2 + X * C (2 * chebHalf k) := by + intro k; rw [C_mul, C_ofNat]; ring + rw [Gt, hI, Finset.prod_insert (by decide), Finset.prod_insert (by decide), + Finset.prod_singleton, hf, hf, hf, coeff_six_aux, two_chebHalf_one, two_chebHalf_two, + two_chebHalf_three] + ring + +/-- O'Sullivan's conjecture: for all `m ≥ 0`, `n ≥ 0`, the row polynomial +`G(m;n,x) = Sum_{k=0..g(m;n)} a(m;n,k) x^k` (so of degree at most `g(m;n)`), and the Gaussian +polynomial satisfies `[2n+m+1-(m mod 2), m]_q = Sum_{k=0..g(m;n)} a(m;n,k) (1+q^2)^k q^(g(m;n)-k)` +with `a(m;n,k) = [x^k] G(m;n,x)`. -/ +def statement : Prop := + ∀ m n : ℕ, + (G m n).natDegree ≤ g m n ∧ + (gaussBinom (2 * n + m + 1 - m % 2) m).map (Int.castRingHom ℚ) = + ∑ k ∈ Finset.range (g m n + 1), C ((G m n).coeff k) * (1 + X ^ 2) ^ k * X ^ (g m n - k) + +end Math0.Statements.A267486 diff --git a/lean/Math0/Statements/OEIS/A270668.lean b/lean/Math0/Statements/OEIS/A270668.lean new file mode 100644 index 0000000..0574023 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A270668.lean @@ -0,0 +1,1121 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A270668: domino tilings of the `(2n+1) × (2m+1)` board with a central hole + +Source: https://oeis.org/A270668, _R. J. Mathar_, Mar 23 2016 (FORMULA section). Verbatim: +> Conjectured g.f. for column 3: ( -1 -4*x +543*x^2 -6238*x^3 +17032*x^4 -6238*x^5 +543*x^6 +> -4*x^7 -x^8 ) / ( (x-1) *(x^2-7*x+1) *(x^2-23*x+1) +> *(x^4 -161*x^3 +576*x^2 -161*x +1) ). - _R. J. Mathar_, Mar 23 2016 + +The entry (_R. J. Mathar_, Mar 21 2016; more terms by _Alois P. Heinz_) is "Triangle read by +rows: The number of domino tilings of the (2n+1) X (2m+1) board with a central free square." +with the comment "Arrangements obtained by rotations and flips are counted as distinct." +Offset `0`: rows `n ≥ 0`, columns `0 ≤ m ≤ n`. + +## Encoding + +* *Domino tilings.* Cells are pairs `(i, j)` of naturals (row `i`, column `j`). A domino is a + set `{(i, j), (i, j + 1)}` or `{(i, j), (i + 1, j)}` (`IsDomino`). A domino tiling of a finite + set of cells `S` is a finite set `D` of dominoes, each contained in `S`, such that every cell of + `S` lies in exactly one domino of `D` (`IsTiling`). A tiling is the set of its dominoes, so two + tilings that differ by a rotation or a flip of the board are counted as distinct, as the entry + says. +* *The triangle.* `region n m` is the `(2n+1) × (2m+1)` board (rows `0, …, 2n`, columns + `0, …, 2m`) with its central square `(n, m)` removed, and `T n m` is the number of domino + tilings of `region n m` (`Set.ncard` of the set of tilings, which is finite by + `tilings_finite`). `T` is defined for all `n, m`; the entry's triangle is `T n m` for + `0 ≤ m ≤ n`, read by rows with offset `0`, and `a` is that sequence: + `a (n (n + 1) / 2 + m) = T n m` for `m ≤ n` (`a_spec`). +* *Computation.* `a` is computed through `Tc`, a broken-profile transfer matrix whose count + vectors are packed into single natural numbers, and `T_eq_Tc` proves `T n m = Tc n m` for all + `n, m`. `a_data` checks all `36` listed terms (rows `0` to `7`) in the kernel. +* *Which column, which series.* "Column 3" is read as the third column of the triangle, `m = 2` + (boards `(2n+1) × 5`). Its odd rows vanish in the data (`T 3 2 = T 5 2 = T 7 2 = 0`; in general + by the checkerboard coloring), and the expansion of the conjectured g.f. is + `1 + 196 x + 31329 x^2 + 4941729 x^3 + 777852100 x^4 + …`, whose coefficients of `x^1, x^2, x^3` + are the listed terms `T 2 2 = 196`, `T 4 2 = 31329`, `T 6 2 = 4941729`. So the g.f. is read as + `∑_{k ≥ 0} T(2k, 2) x^k`. Its constant term is `T 0 2 = 1`, the number of tilings of the + `1 × 5` strip with its central square removed: this board is outside the triangle (`m > n`) but + is given by the same definition (`column_data` checks `T(2k, 2)` for `k ≤ 3`). The column + `m = 3` (`75272, 135663392, …`) does not match the g.f. +* *The identity.* `statement` says, in `ℚ⟦X⟧`, that the power series with coefficients + `T(2k, 2)`, `k ≥ 0`, equals `num * den⁻¹`, `num` and `den` being the stated numerator and + denominator. `den` has constant coefficient `-1`, so it is invertible, and the statement is + equivalent to `mk (fun k => T (2k) 2) * den = num` (`statement_iff`). +-/ + +namespace Math0.Statements.A270668 + +open Finset + +/-! ### Domino tilings -/ + +/-- Cells of the grid: `(i, j)` is the cell in row `i` and column `j`. -/ +abbrev Cell := ℕ × ℕ + +/-- A domino: two edge-adjacent cells, `{(i, j), (i, j + 1)}` (horizontal) or +`{(i, j), (i + 1, j)}` (vertical). -/ +def IsDomino (d : Finset Cell) : Prop := + ∃ i j : ℕ, d = {(i, j), (i, j + 1)} ∨ d = {(i, j), (i + 1, j)} + +/-- `D` is a domino tiling of the finite set of cells `S`: a set of dominoes contained in `S` +such that every cell of `S` lies in exactly one of them. -/ +def IsTiling (S : Finset Cell) (D : Finset (Finset Cell)) : Prop := + (∀ d ∈ D, IsDomino d ∧ d ⊆ S) ∧ ∀ x ∈ S, ∃! d, d ∈ D ∧ x ∈ d + +/-- The `r × c` board: rows `0, …, r - 1` and columns `0, …, c - 1`. -/ +def board (r c : ℕ) : Finset Cell := range r ×ˢ range c + +/-- The `(2n+1) × (2m+1)` board with its central square `(n, m)` removed. -/ +def region (n m : ℕ) : Finset Cell := (board (2 * n + 1) (2 * m + 1)).erase (n, m) + +/-- A270668: `T n m` is the number of domino tilings of the `(2n+1) × (2m+1)` board with a +central free square. -/ +noncomputable def T (n m : ℕ) : ℕ := {D | IsTiling (region n m) D}.ncard + +/-! ### A computable version of `T` (see `T_eq_Tc`) + +The cells of the `r × c` board are numbered row by row, cell `(i, j)` getting the index +`i * c + j`; there are `N = r * c` of them, and `hx` is the index of the hole. The count runs +through the cells `k = N - 1, …, 1, 0` (a broken-profile transfer matrix). Its state at cell `k` +is a set `M` of cells among `k, …, k + c - 1` that are already covered by dominoes placed at +earlier cells, cell `x` being recorded by bit `x % c` of `M`. The vector of counts, indexed by +`M < 2 ^ c`, is packed into one natural number, entry `M` occupying the `W` bits starting at +bit `M * W`; `dig W X M` reads it. -/ + +/-- `dbl X a e`: starting from the `a`-bit block `X`, double `e` times (`X ↦ X + X <<< a`, +`a ↦ 2 a`), i.e. repeat the block `2 ^ e` times. -/ +def dbl : ℕ → ℕ → ℕ → ℕ + | X, _, 0 => X + | X, a, e + 1 => dbl (X + (X <<< a)) (2 * a) e + +/-- The packed vector whose entry `M < 2 ^ c` is `2 ^ W - 1` if bit `s` of `M` is clear, and +`0` otherwise. -/ +def clr (c W s : ℕ) : ℕ := dbl (2 ^ (2 ^ s * W) - 1) (2 ^ (s + 1) * W) (c - (s + 1)) + +/-- The packed vector all of whose entries `M < 2 ^ c` are `1`. -/ +def ones (c W : ℕ) : ℕ := dbl 1 W c + +/-- Index `q` is a cell of the board with `N` cells and is not the hole `hx`. -/ +def inS (N hx q : ℕ) : Bool := decide (q < N ∧ q ≠ hx) + +/-- One step of the transfer matrix, at cell `k` (`s = k % c`): from the vector `X` of counts +at cell `k + 1` to the vector at cell `k`. Entries with bit `s` set (cell `k` already covered) +come from entry `M - 2 ^ s`; the others from entry `M` if `k` is not a cell of the region, and +otherwise from placing a vertical domino on `k, k + c` (entry `M + 2 ^ s`) or a horizontal one on +`k, k + 1` (entry `M + 2 ^ (s + 1)`). -/ +def stepP (c W N hx k X : ℕ) : ℕ := + (X &&& clr c W (k % c)) <<< (2 ^ (k % c) * W) + + if inS N hx k then + (if inS N hx (k + c) then (X >>> (2 ^ (k % c) * W)) &&& clr c W (k % c) else 0) + + (if k % c + 1 < c ∧ inS N hx (k + 1) then + (X >>> (2 ^ (k % c + 1) * W)) &&& (clr c W (k % c) &&& clr c W (k % c + 1)) else 0) + else X &&& clr c W (k % c) + +/-- The packed vector of counts at cell `N - j`. -/ +def vecP (c W N hx : ℕ) : ℕ → ℕ + | 0 => ones c W + | j + 1 => stepP c W N hx (N - (j + 1)) (vecP c W N hx j) + +/-- Computable version of `T` (see `T_eq_Tc`): entry `0` of the packed vector at cell `0`, +with `c = 2m+1` columns, `N = (2n+1)(2m+1)` cells, the hole at index `n c + m`, and entries of +`W = N / 2 + 1` bits. -/ +def Tc (n m : ℕ) : ℕ := + vecP (2 * m + 1) ((2 * n + 1) * (2 * m + 1) / 2 + 1) ((2 * n + 1) * (2 * m + 1)) + (n * (2 * m + 1) + m) ((2 * n + 1) * (2 * m + 1)) % + 2 ^ ((2 * n + 1) * (2 * m + 1) / 2 + 1) + +/-- Row and column of the `i`-th entry of a triangle read by rows, starting the search at row +`n` (`fuel` bounds the number of rows visited). -/ +def rowCol : ℕ → ℕ → ℕ → ℕ × ℕ + | 0, n, i => (n, i) + | fuel + 1, n, i => if i ≤ n then (n, i) else rowCol fuel (n + 1) (i - (n + 1)) + +/-- A270668 read by rows, with the OEIS offset `0`: `a 0 = T 0 0`, `a 1 = T 1 0`, +`a 2 = T 1 1`, `a 3 = T 2 0`, … (see `a_spec`). -/ +def a (i : ℕ) : ℕ := Tc (rowCol i 0 i).1 (rowCol i 0 i).2 + +/-- The definition reproduces all 36 terms listed in OEIS (rows `0` to `7`), kernel-checked. -/ +theorem a_data : (List.range 36).map (fun i => a i) = + [1, 0, 2, 1, 0, 196, 0, 32, 0, 75272, 1, 0, 31329, 0, 599466256, 0, 450, 0, 135663392, 0, + 28838245503008, 1, 0, 4941729, 0, 10956424382401, 0, 22463213552677201984, 0, 6272, 0, + 233075146752, 0, 5652453608244879872, 0, 123818965842734619629420672] := by + decide +kernel + +/-! ### Tilings: the first-cell recursion -/ + +theorem IsDomino.nonempty {d : Finset Cell} (hd : IsDomino d) : d.Nonempty := by + obtain ⟨i, j, rfl | rfl⟩ := hd <;> exact insert_nonempty _ _ + +theorem tilings_finite (S : Finset Cell) : {D | IsTiling S D}.Finite := by + refine (S.powerset.powerset.finite_toSet).subset ?_ + intro D hD + rw [mem_coe, mem_powerset] + intro d hd + rw [mem_powerset] + exact (hD.1 d hd).2 + +theorem ncard_tilings_empty : {D | IsTiling ∅ D}.ncard = 1 := by + have : {D | IsTiling ∅ D} = {∅} := by + ext D + simp only [Set.mem_ofPred_eq, Set.mem_singleton_iff] + constructor + · rintro ⟨h1, -⟩ + rw [eq_empty_iff_forall_notMem] + intro d hd + obtain ⟨x, hx⟩ := (h1 d hd).1.nonempty + simpa using (h1 d hd).2 hx + · rintro rfl + exact ⟨by simp, by simp⟩ + rw [this, Set.ncard_singleton] + +theorem isTiling_insert {F d₀ : Finset Cell} {D : Finset (Finset Cell)} (hd₀ : IsDomino d₀) + (hsub : d₀ ⊆ F) (hD : IsTiling (F \ d₀) D) : IsTiling F (insert d₀ D) := by + refine ⟨?_, ?_⟩ + · intro d hd + rcases mem_insert.1 hd with rfl | hd + · exact ⟨hd₀, hsub⟩ + · exact ⟨(hD.1 d hd).1, (hD.1 d hd).2.trans sdiff_subset⟩ + · intro x hx + by_cases hxd : x ∈ d₀ + · refine ⟨d₀, ⟨mem_insert_self _ _, hxd⟩, ?_⟩ + rintro d ⟨hd, hxd'⟩ + rcases mem_insert.1 hd with rfl | hd + · rfl + · exact absurd hxd (mem_sdiff.1 ((hD.1 d hd).2 hxd')).2 + · obtain ⟨d, ⟨hd, hxd'⟩, huniq⟩ := hD.2 x (mem_sdiff.2 ⟨hx, hxd⟩) + refine ⟨d, ⟨mem_insert_of_mem hd, hxd'⟩, ?_⟩ + rintro d' ⟨hd', hxd''⟩ + rcases mem_insert.1 hd' with rfl | hd' + · exact absurd hxd'' hxd + · exact huniq d' ⟨hd', hxd''⟩ + +theorem isTiling_erase {F d₀ : Finset Cell} {D : Finset (Finset Cell)} (hD : IsTiling F D) + (hd₀ : d₀ ∈ D) : IsTiling (F \ d₀) (D.erase d₀) := by + refine ⟨?_, ?_⟩ + · intro d hd + obtain ⟨hne, hd⟩ := mem_erase.1 hd + refine ⟨(hD.1 d hd).1, fun x hx => mem_sdiff.2 ⟨(hD.1 d hd).2 hx, fun hx₀ => hne ?_⟩⟩ + obtain ⟨e, -, he⟩ := hD.2 x ((hD.1 d hd).2 hx) + exact (he d ⟨hd, hx⟩).trans (he d₀ ⟨hd₀, hx₀⟩).symm + · intro x hx + obtain ⟨hxF, hx₀⟩ := mem_sdiff.1 hx + obtain ⟨d, ⟨hd, hxd⟩, huniq⟩ := hD.2 x hxF + refine ⟨d, ⟨mem_erase.2 ⟨fun h => hx₀ (h ▸ hxd), hd⟩, hxd⟩, ?_⟩ + rintro d' ⟨hd', hxd'⟩ + exact huniq d' ⟨(mem_erase.1 hd').2, hxd'⟩ + +/-- The tilings of `F` containing the domino `d₀ ⊆ F` correspond to the tilings of `F \ d₀`. -/ +theorem ncard_tilings_mem {F d₀ : Finset Cell} (hd₀ : IsDomino d₀) (hsub : d₀ ⊆ F) : + {D | IsTiling F D ∧ d₀ ∈ D}.ncard = {D | IsTiling (F \ d₀) D}.ncard := by + have himage : {D | IsTiling F D ∧ d₀ ∈ D} = insert d₀ '' {D | IsTiling (F \ d₀) D} := by + ext D + simp only [Set.mem_ofPred_eq, Set.mem_image] + constructor + · rintro ⟨hD, hmem⟩ + exact ⟨D.erase d₀, isTiling_erase hD hmem, insert_erase hmem⟩ + · rintro ⟨D', hD', rfl⟩ + exact ⟨isTiling_insert hd₀ hsub hD', mem_insert_self _ _⟩ + have hn : ∀ D, IsTiling (F \ d₀) D → d₀ ∉ D := by + intro D hD hmem + obtain ⟨x, hx⟩ := hd₀.nonempty + exact (mem_sdiff.1 ((hD.1 d₀ hmem).2 hx)).2 hx + rw [himage] + apply Set.InjOn.ncard_image + intro D₁ h₁ D₂ h₂ heq + rw [← erase_insert (hn D₁ h₁), heq, erase_insert (hn D₂ h₂)] + +/-- The right neighbour of a cell. -/ +def rt (p : Cell) : Cell := (p.1, p.2 + 1) + +/-- The lower neighbour of a cell. -/ +def dn (p : Cell) : Cell := (p.1 + 1, p.2) + +/-- The first-cell recursion: if `p` is the lexicographically first cell of `F`, the domino +covering `p` is `{p, rt p}` or `{p, dn p}`. -/ +theorem ncard_tilings_step {F : Finset Cell} {p : Cell} (hp : p ∈ F) + (hmin : ∀ q ∈ F, q ≠ p → p.1 < q.1 ∨ (p.1 = q.1 ∧ p.2 < q.2)) : + {D | IsTiling F D}.ncard = + (if rt p ∈ F then {D | IsTiling (F \ {p, rt p}) D}.ncard else 0) + + (if dn p ∈ F then {D | IsTiling (F \ {p, dn p}) D}.ncard else 0) := by + have hsplit : {D | IsTiling F D} = + {D | IsTiling F D ∧ {p, rt p} ∈ D} ∪ {D | IsTiling F D ∧ {p, dn p} ∈ D} := by + ext D + simp only [Set.mem_ofPred_eq, Set.mem_union] + constructor + · intro hD + obtain ⟨d, ⟨hd, hpd⟩, -⟩ := hD.2 p hp + obtain ⟨⟨i, j, rfl | rfl⟩, hsub⟩ := hD.1 d hd + · rcases mem_insert.1 hpd with rfl | hpd + · exact Or.inl ⟨hD, hd⟩ + · rw [mem_singleton] at hpd + subst hpd + have := hmin (i, j) (hsub (by simp)) (by simp) + simp at this + · rcases mem_insert.1 hpd with rfl | hpd + · exact Or.inr ⟨hD, hd⟩ + · rw [mem_singleton] at hpd + subst hpd + have := hmin (i, j) (hsub (by simp)) (by simp) + simp at this + · rintro (⟨hD, -⟩ | ⟨hD, -⟩) <;> exact hD + have hdisj : Disjoint {D | IsTiling F D ∧ {p, rt p} ∈ D} {D | IsTiling F D ∧ {p, dn p} ∈ D} := by + rw [Set.disjoint_left] + rintro D ⟨hD, h1⟩ ⟨-, h2⟩ + obtain ⟨d, -, huniq⟩ := hD.2 p hp + have : ({p, rt p} : Finset Cell) = {p, dn p} := + (huniq _ ⟨h1, by simp⟩).trans (huniq _ ⟨h2, by simp⟩).symm + have hmem : rt p ∈ ({p, dn p} : Finset Cell) := this ▸ (by simp) + simp [rt, dn, Prod.ext_iff] at hmem + rw [hsplit, Set.ncard_union_eq hdisj ((tilings_finite F).subset fun D h => h.1) + ((tilings_finite F).subset fun D h => h.1)] + congr 1 + · split_ifs with h + · refine ncard_tilings_mem ⟨p.1, p.2, Or.inl rfl⟩ ?_ + intro x hx + rcases mem_insert.1 hx with rfl | hx + · exact hp + · rw [mem_singleton] at hx; exact hx ▸ h + · convert Set.ncard_empty (Finset (Finset Cell)) + ext D + simp only [Set.mem_ofPred_eq, Set.mem_empty_iff_false, iff_false, not_and] + intro hD hmem + exact h ((hD.1 _ hmem).2 (by simp)) + · split_ifs with h + · refine ncard_tilings_mem ⟨p.1, p.2, Or.inr rfl⟩ ?_ + intro x hx + rcases mem_insert.1 hx with rfl | hx + · exact hp + · rw [mem_singleton] at hx; exact hx ▸ h + · convert Set.ncard_empty (Finset (Finset Cell)) + ext D + simp only [Set.mem_ofPred_eq, Set.mem_empty_iff_false, iff_false, not_and] + intro hD hmem + exact h ((hD.1 _ hmem).2 (by simp)) + +theorem exists_lex_min {F : Finset Cell} (hF : F.Nonempty) : + ∃ p ∈ F, ∀ q ∈ F, q ≠ p → p.1 < q.1 ∨ (p.1 = q.1 ∧ p.2 < q.2) := by + obtain ⟨p, hp, hmin⟩ := F.exists_min_image (fun q => toLex q) hF + refine ⟨p, hp, fun q hq hne => ?_⟩ + have h2 : toLex p < toLex q := lt_of_le_of_ne (hmin q hq) (fun e => hne (toLex.injective e).symm) + exact Prod.Lex.toLex_lt_toLex.1 h2 + +/-- A finite set of cells has at most `2 ^ (#F / 2)` domino tilings. -/ +theorem ncard_tilings_le (n : ℕ) : ∀ F : Finset Cell, F.card ≤ n → + {D | IsTiling F D}.ncard ≤ 2 ^ (F.card / 2) := by + induction n with + | zero => + intro F hF + rw [card_eq_zero.1 (Nat.le_zero.1 hF), ncard_tilings_empty] + simp + | succ n ih => + intro F hn + rcases F.eq_empty_or_nonempty with rfl | hne + · rw [ncard_tilings_empty]; simp + obtain ⟨p, hp, hmin⟩ := exists_lex_min hne + rw [ncard_tilings_step hp hmin] + have hbr : ∀ q, q ≠ p → q ∈ F → + {D | IsTiling (F \ {p, q}) D}.ncard ≤ 2 ^ ((F.card - 2) / 2) := by + intro q hqp hq + have hcard : (F \ {p, q}).card = F.card - 2 := by + rw [card_sdiff_of_subset (by intro x hx; simp at hx; rcases hx with rfl | rfl <;> assumption), + card_pair_eq_two_iff.2 hqp.symm] + have := ih (F \ {p, q}) (by rw [hcard]; omega) + rwa [hcard] at this + have hrt : rt p ≠ p := by simp [rt, Prod.ext_iff] + have hdn : dn p ≠ p := by simp [dn, Prod.ext_iff] + have hc2 : ∀ q, q ≠ p → q ∈ F → 2 ≤ F.card := by + intro q hqp hq + have : ({p, q} : Finset Cell).card = 2 := card_pair_eq_two_iff.2 hqp.symm + have hsub : ({p, q} : Finset Cell) ⊆ F := by + intro x hx; simp at hx; rcases hx with rfl | rfl <;> assumption + have := card_le_card hsub + omega + have hpow : 2 ^ ((F.card - 2) / 2) ≤ 2 ^ (F.card / 2) := + Nat.pow_le_pow_right (by norm_num) (by omega) + by_cases hr : rt p ∈ F + · by_cases hd : dn p ∈ F + · rw [if_pos hr, if_pos hd] + have h1 := hbr _ hrt hr + have h2 := hbr _ hdn hd + have hc := hc2 _ hrt hr + have : 2 ^ ((F.card - 2) / 2) + 2 ^ ((F.card - 2) / 2) = 2 ^ (F.card / 2) := by + rw [← two_mul, ← pow_succ'] + congr 1 + omega + omega + · rw [if_pos hr, if_neg hd] + have h1 := hbr _ hrt hr + omega + · by_cases hd : dn p ∈ F + · rw [if_neg hr, if_pos hd] + have h2 := hbr _ hdn hd + omega + · rw [if_neg hr, if_neg hd] + simp + +/-! ### Bit manipulations -/ + +theorem testBit_add_two_pow {M s : ℕ} (h : M.testBit s = false) (j : ℕ) : + (M + 2 ^ s).testBit j = (decide (j = s) || M.testBit j) := by + have hlt : M % 2 ^ s < 2 ^ s := Nat.mod_lt _ (Nat.two_pow_pos s) + have hM : M = 2 ^ s * (M / 2 ^ s) + M % 2 ^ s := (Nat.div_add_mod M (2 ^ s)).symm + have heven : M / 2 ^ s % 2 = 0 := by + rw [Nat.testBit_eq_decide_div_mod_eq] at h + simp only [decide_eq_false_iff_not] at h + omega + have hM' : M + 2 ^ s = 2 ^ s * (M / 2 ^ s + 1) + M % 2 ^ s := by + rw [mul_add, mul_one]; omega + rw [hM', Nat.testBit_two_pow_mul_add _ hlt] + conv_rhs => rw [hM, Nat.testBit_two_pow_mul_add _ hlt] + by_cases hj : j < s + · simp [hj, Nat.ne_of_lt hj] + · rw [if_neg hj, if_neg hj] + rcases Nat.lt_or_ge s j with hsj | hsj + · obtain ⟨i, hi⟩ : ∃ i, j - s = i + 1 := ⟨j - s - 1, by omega⟩ + have hjs : j ≠ s := by omega + simp only [hi, hjs, decide_false, Bool.false_or, Nat.testBit_succ] + congr 1 + omega + · have hjs : j = s := by omega + rw [hjs, Nat.sub_self, Nat.testBit_zero, decide_eq_true (rfl : s = s), Bool.true_or, + decide_eq_true_iff] + omega + +theorem testBit_sub_two_pow {M s : ℕ} (h : M.testBit s = true) (j : ℕ) : + (M - 2 ^ s).testBit j = (decide (j ≠ s) && M.testBit j) := by + have hle : 2 ^ s ≤ M := Nat.ge_two_pow_of_testBit h + have hM : M = (M - 2 ^ s) + 2 ^ s := by omega + have h' : (M - 2 ^ s).testBit s = false := by + have := Nat.testBit_two_pow_add_eq (M - 2 ^ s) s + rw [add_comm, ← hM, h] at this + cases hb : (M - 2 ^ s).testBit s + · rfl + · rw [hb] at this + exact absurd this (by decide) + have key := testBit_add_two_pow h' j + rw [← hM] at key + rw [key] + by_cases hj : j = s + · subst hj; simp [h'] + · simp [hj] + +theorem testBit_sub_two_pow_of_false {M s : ℕ} (hle : 2 ^ s ≤ M) (h : M.testBit s = false) : + (M - 2 ^ s).testBit s = true := by + by_contra h' + rw [Bool.not_eq_true] at h' + have := testBit_add_two_pow h' s + rw [Nat.sub_add_cancel hle, h] at this + simp at this + +theorem add_two_pow_lt {M s c : ℕ} (hM : M < 2 ^ c) (hs : s < c) (h : M.testBit s = false) : + M + 2 ^ s < 2 ^ c := by + apply Nat.lt_pow_two_of_testBit + intro i hi + rw [testBit_add_two_pow h, + Nat.testBit_lt_two_pow (lt_of_lt_of_le hM (Nat.pow_le_pow_right (by norm_num) hi))] + simp only [Bool.or_false, decide_eq_false_iff_not] + omega + +theorem testBit_iff_mod (M s : ℕ) : M.testBit s = true ↔ 2 ^ s ≤ M % 2 ^ (s + 1) := by + rw [Nat.mod_pow_succ, Nat.testBit_eq_decide_div_mod_eq, decide_eq_true_iff] + have := Nat.mod_lt M (Nat.two_pow_pos s) + have := Nat.mod_lt (M / 2 ^ s) (show 0 < 2 by norm_num) + constructor + · intro h; rw [h]; omega + · intro h + by_contra h' + have h0 : M / 2 ^ s % 2 = 0 := by omega + rw [h0] at h; omega + +theorem eq_of_mod_eq_window {a x c : ℕ} (h1 : a ≤ x) (h2 : x < a + c) (h : x % c = a % c) : + x = a := by + have hd : c ∣ x - a := (Nat.modEq_iff_dvd' h1).1 h.symm + have := Nat.eq_zero_of_dvd_of_lt hd (by omega) + omega + +theorem mul_add_lt_iff {M W i n : ℕ} (hi : i < W) : M * W + i < n * W ↔ M < n := by + constructor + · intro h + by_contra h' + push Not at h' + have := Nat.mul_le_mul_right W h' + omega + · intro h + have := Nat.mul_le_mul_right W (show M + 1 ≤ n from h) + rw [add_mul, one_mul] at this + omega + +theorem mul_add_mod' {M W i : ℕ} (hi : i < W) : (M * W + i) % W = i := by + rw [add_comm, Nat.add_mul_mod_self_right, Nat.mod_eq_of_lt hi] + +theorem mul_add_div' {M W i : ℕ} (hi : i < W) : (M * W + i) / W = M := by + rw [add_comm, Nat.add_mul_div_right _ _ (by omega), Nat.div_eq_of_lt hi, zero_add] + +/-! ### Packed vectors -/ + +/-- Entry `M` of the packed vector `X` (entries of `W` bits). -/ +def dig (W X M : ℕ) : ℕ := (X >>> (M * W)) % 2 ^ W + +theorem dig_lt (W X M : ℕ) : dig W X M < 2 ^ W := Nat.mod_lt _ (Nat.two_pow_pos W) + +theorem testBit_dig (W X M i : ℕ) : + (dig W X M).testBit i = (decide (i < W) && X.testBit (M * W + i)) := by + simp [dig, Nat.testBit_mod_two_pow, Nat.testBit_shiftRight] + +theorem dig_and (W X Y M : ℕ) : dig W (X &&& Y) M = dig W X M &&& dig W Y M := by + apply Nat.eq_of_testBit_eq + intro i + rw [Nat.testBit_and, testBit_dig, testBit_dig, testBit_dig, Nat.testBit_and] + cases decide (i < W) <;> simp + +theorem dig_shiftRight (W X a M : ℕ) : dig W (X >>> (a * W)) M = dig W X (M + a) := by + simp only [dig, ← Nat.shiftRight_add] + congr 2 + ring + +theorem dig_shiftLeft (W X a M : ℕ) : + dig W (X <<< (a * W)) M = if a ≤ M then dig W X (M - a) else 0 := by + apply Nat.eq_of_testBit_eq + intro i + rw [testBit_dig, Nat.testBit_shiftLeft] + split_ifs with ha + · rw [testBit_dig] + by_cases hi : i < W + · have h1 : a * W ≤ M * W := Nat.mul_le_mul_right W ha + have h2 : (M - a) * W = M * W - a * W := Nat.sub_mul M a W + rw [show M * W + i - a * W = (M - a) * W + i by omega] + simp [hi, show a * W ≤ M * W + i by omega] + · simp [hi] + · rw [Nat.zero_testBit] + by_cases hi : i < W + · have h1 : (M + 1) * W ≤ a * W := Nat.mul_le_mul_right W (by omega) + rw [add_mul, one_mul] at h1 + have : ¬ (a * W ≤ M * W + i) := by omega + simp [this] + · simp [hi] + +theorem dig_eq_div (W X M : ℕ) : dig W X M = X / (2 ^ W) ^ M % 2 ^ W := by + rw [dig, Nat.shiftRight_eq_div_pow, ← pow_mul, mul_comm] + +theorem mod_add_mod_lt {B X Y : ℕ} (hB : 0 < B) : + ∀ M, (∀ i < M, X / B ^ i % B + Y / B ^ i % B < B) → X % B ^ M + Y % B ^ M < B ^ M + | 0, _ => by rw [pow_zero, Nat.mod_one, Nat.mod_one]; norm_num + | M + 1, h => by + have ih := mod_add_mod_lt hB M (fun i hi => h i (by omega)) + have hM := h M (by omega) + rw [Nat.mod_pow_succ, Nat.mod_pow_succ, pow_succ] + have : B ^ M * (X / B ^ M % B) + B ^ M * (Y / B ^ M % B) + B ^ M ≤ B ^ M * B := by + rw [← mul_add, ← Nat.mul_succ] + exact Nat.mul_le_mul_left _ hM + omega + +/-- Adding packed vectors adds the entries, as long as no entry overflows. -/ +theorem dig_add {W X Y M : ℕ} (h : ∀ i ≤ M, dig W X i + dig W Y i < 2 ^ W) : + dig W (X + Y) M = dig W X M + dig W Y M := by + simp only [dig_eq_div] at h ⊢ + have hB : 0 < 2 ^ W := Nat.two_pow_pos W + have hpos : 0 < (2 ^ W) ^ M := pow_pos hB M + have hlow := mod_add_mod_lt hB M (fun i hi => h i hi.le) + have hdiv : (X + Y) / (2 ^ W) ^ M = X / (2 ^ W) ^ M + Y / (2 ^ W) ^ M := by + have e : X + Y = (X % (2 ^ W) ^ M + Y % (2 ^ W) ^ M) + + (2 ^ W) ^ M * (X / (2 ^ W) ^ M + Y / (2 ^ W) ^ M) := by + have := Nat.div_add_mod X ((2 ^ W) ^ M) + have := Nat.div_add_mod Y ((2 ^ W) ^ M) + rw [mul_add] + omega + rw [e, Nat.add_mul_div_left _ _ hpos, Nat.div_eq_of_lt hlow, zero_add] + rw [hdiv, Nat.add_mod, Nat.mod_eq_of_lt (h M le_rfl)] + +theorem testBit_dbl : ∀ (e X a : ℕ), 0 < a → X < 2 ^ a → ∀ j, + (dbl X a e).testBit j = (decide (j < 2 ^ e * a) && X.testBit (j % a)) + | 0, X, a, ha, hX, j => by + simp only [dbl, pow_zero, one_mul] + by_cases hj : j < a + · simp [hj, Nat.mod_eq_of_lt hj] + · simp only [hj, decide_false, Bool.false_and] + exact Nat.testBit_lt_two_pow + (lt_of_lt_of_le hX (Nat.pow_le_pow_right (by norm_num) (by omega))) + | e + 1, X, a, ha, hX, j => by + have hX' : X + (X <<< a) < 2 ^ (2 * a) := by + rw [Nat.shiftLeft_eq, two_mul, pow_add] + have : X + 1 ≤ 2 ^ a := hX + nlinarith + rw [dbl, testBit_dbl e _ (2 * a) (by omega) hX' j, + show X + (X <<< a) = 2 ^ a * X + X by rw [Nat.shiftLeft_eq]; ring, + Nat.testBit_two_pow_mul_add _ hX, + show 2 ^ e * (2 * a) = 2 ^ (e + 1) * a by ring] + have hmod : j % (2 * a) % a = j % a := Nat.mod_mod_of_dvd j (dvd_mul_left a 2) + by_cases hj : j < 2 ^ (e + 1) * a + · simp only [hj, decide_true, Bool.true_and] + have hlt : j % (2 * a) < 2 * a := Nat.mod_lt _ (by omega) + split_ifs with h + · rw [← hmod, Nat.mod_eq_of_lt h] + · have h1 : j % (2 * a) % a = j % (2 * a) - a := by + rw [Nat.mod_eq_sub_mod (show a ≤ j % (2 * a) by omega), + Nat.mod_eq_of_lt (show j % (2 * a) - a < a by omega)] + rw [← hmod, h1] + · simp [hj] + +theorem testBit_clr {c W s : ℕ} (hs : s < c) (hW : 0 < W) (j : ℕ) : + (clr c W s).testBit j = + (decide (j < 2 ^ c * W) && decide (j % (2 ^ (s + 1) * W) < 2 ^ s * W)) := by + have ha : 0 < 2 ^ (s + 1) * W := Nat.mul_pos (Nat.two_pow_pos _) hW + have hX : 2 ^ (2 ^ s * W) - 1 < 2 ^ (2 ^ (s + 1) * W) := by + have : 2 ^ (2 ^ s * W) ≤ 2 ^ (2 ^ (s + 1) * W) := + Nat.pow_le_pow_right (by norm_num) + (Nat.mul_le_mul_right _ (Nat.pow_le_pow_right (by norm_num) (by omega))) + have := Nat.two_pow_pos (2 ^ s * W) + omega + rw [clr, testBit_dbl _ _ _ ha hX, Nat.testBit_two_pow_sub_one, ← mul_assoc, ← pow_add, + show c - (s + 1) + (s + 1) = c by omega] + +theorem dig_clr {c W s : ℕ} (hs : s < c) (hW : 0 < W) (M : ℕ) : + dig W (clr c W s) M = if M < 2 ^ c ∧ M.testBit s = false then 2 ^ W - 1 else 0 := by + apply Nat.eq_of_testBit_eq + intro i + rw [testBit_dig] + by_cases hi : i < W + · rw [testBit_clr hs hW] + have e2 : (M * W + i) % (2 ^ (s + 1) * W) = W * (M % 2 ^ (s + 1)) + i := by + rw [mul_comm (2 ^ (s + 1)) W, Nat.mod_mul, mul_add_mod' hi, mul_add_div' hi] + ring + have e3 : W * (M % 2 ^ (s + 1)) + i < 2 ^ s * W ↔ M.testBit s = false := by + rw [← Bool.not_eq_true, testBit_iff_mod] + constructor + · intro h h' + have := Nat.mul_le_mul_left W h' + rw [mul_comm W (2 ^ s)] at this + omega + · intro h + push Not at h + have : W * (M % 2 ^ (s + 1)) + W ≤ W * 2 ^ s := by + rw [← Nat.mul_succ]; exact Nat.mul_le_mul_left W h + rw [mul_comm (2 ^ s) W] + omega + rw [e2] + simp only [hi, decide_true, Bool.true_and, mul_add_lt_iff hi, e3] + split_ifs with hc + · rw [Nat.testBit_two_pow_sub_one]; simp [hi, hc.1, hc.2] + · rw [Nat.zero_testBit] + by_cases h1 : M < 2 ^ c + · have h2 : ¬ M.testBit s = false := fun h2 => hc ⟨h1, h2⟩ + simp [h1, h2] + · simp [h1] + · split_ifs <;> simp [hi] + +theorem dig_ones {c W : ℕ} (hW : 0 < W) (M : ℕ) : + dig W (ones c W) M = if M < 2 ^ c then 1 else 0 := by + apply Nat.eq_of_testBit_eq + intro i + rw [testBit_dig, ones, testBit_dbl c 1 W hW (Nat.one_lt_two_pow hW.ne')] + by_cases hi : i < W + · simp only [hi, decide_true, Bool.true_and, mul_add_lt_iff hi, mul_add_mod' hi] + split_ifs with hM + · simp [hM] + · simp [hM] + · split_ifs <;> simp [hi] + rw [Nat.testBit_lt_two_pow] + exact lt_of_lt_of_le (by norm_num) (Nat.pow_le_pow_right (by norm_num) (by omega : 1 ≤ i)) + +/-! ### Cell indices and the states of the transfer matrix -/ + +/-- The cell with index `q` on a board with `c` columns. -/ +def cellOf (c q : ℕ) : Cell := (q / c, q % c) + +/-- The index of the cell `p` on a board with `c` columns. -/ +def idx (c : ℕ) (p : Cell) : ℕ := p.1 * c + p.2 + +theorem idx_cellOf (c q : ℕ) : idx c (cellOf c q) = q := Nat.div_add_mod' q c + +theorem cellOf_injective (c : ℕ) : Function.Injective (cellOf c) := fun x y h => by + rw [← idx_cellOf c x, h, idx_cellOf] + +theorem cellOf_idx {c : ℕ} {p : Cell} (hp : p.2 < c) : cellOf c (idx c p) = p := by + simp only [cellOf, idx] + rw [mul_add_div' hp, mul_add_mod' hp] + +theorem cellOf_lex {c : ℕ} {x y : ℕ} (h : x < y) : + (cellOf c x).1 < (cellOf c y).1 ∨ + ((cellOf c x).1 = (cellOf c y).1 ∧ (cellOf c x).2 < (cellOf c y).2) := by + simp only [cellOf] + rcases lt_or_eq_of_le (Nat.div_le_div_right (c := c) h.le) with h1 | h1 + · exact Or.inl h1 + · refine Or.inr ⟨h1, ?_⟩ + have e1 := Nat.div_add_mod' x c + have e2 := Nat.div_add_mod' y c + rw [h1] at e1 + omega + +theorem rt_cellOf {c k : ℕ} (hs : k % c + 1 < c) : rt (cellOf c k) = cellOf c (k + 1) := by + rw [← cellOf_idx (p := rt (cellOf c k)) hs] + congr 1 + simp only [idx, rt, cellOf] + have := Nat.div_add_mod' k c + omega + +theorem dn_cellOf {c : ℕ} (hc : 0 < c) (k : ℕ) : dn (cellOf c k) = cellOf c (k + c) := by + rw [← cellOf_idx (p := dn (cellOf c k)) (Nat.mod_lt k hc)] + congr 1 + simp only [idx, dn, cellOf] + have := Nat.div_add_mod' k c + rw [add_mul, one_mul] + omega + +/-- The indices of the cells that are still free in the state `(k, M)`: cells `x ≥ k` of the +region (all `x < N` except the hole `hx`) whose bit `x % c` of `M` is clear if `x < k + c`. -/ +def G (N c hx k M : ℕ) : Finset ℕ := + (range N).filter fun x => x ≠ hx ∧ k ≤ x ∧ ¬(x < k + c ∧ M.testBit (x % c) = true) + +theorem mem_G {N c hx k M x : ℕ} : + x ∈ G N c hx k M ↔ x < N ∧ x ≠ hx ∧ k ≤ x ∧ ¬(x < k + c ∧ M.testBit (x % c) = true) := by + simp only [G, mem_filter, mem_range] + +/-- The free cells in the state `(k, M)`. -/ +def Fs (N c hx k M : ℕ) : Finset Cell := (G N c hx k M).image (cellOf c) + +/-- The number of ways to complete the state `(k, M)` to a tiling. -/ +noncomputable def cnt (N c hx k M : ℕ) : ℕ := {D | IsTiling (Fs N c hx k M) D}.ncard + +section States + +variable {N c hx : ℕ} + +theorem mem_Fs_cellOf {k M y : ℕ} : cellOf c y ∈ Fs N c hx k M ↔ y ∈ G N c hx k M := + (cellOf_injective c).mem_finset_image + +theorem snd_lt_of_mem_Fs (hc : 0 < c) {k M : ℕ} {p : Cell} (hp : p ∈ Fs N c hx k M) : + p.2 < c := by + obtain ⟨y, -, rfl⟩ := mem_image.1 hp + exact Nat.mod_lt y hc + +theorem Fs_sdiff (k M a b : ℕ) : + Fs N c hx k M \ {cellOf c a, cellOf c b} = (G N c hx k M \ {a, b}).image (cellOf c) := by + rw [Fs, image_sdiff _ _ (cellOf_injective c)] + simp [image_insert, image_singleton] + +theorem G_of_set (hc : 0 < c) {k M : ℕ} (h : M.testBit (k % c) = true) : + G N c hx k M = G N c hx (k + 1) (M - 2 ^ (k % c)) := by + ext x + rw [mem_G, mem_G, testBit_sub_two_pow h] + constructor + · rintro ⟨hN, hh, hk, hw⟩ + have hxk : x ≠ k := by rintro rfl; exact hw ⟨by omega, h⟩ + refine ⟨hN, hh, by omega, ?_⟩ + rintro ⟨h1, h2⟩ + rw [Bool.and_eq_true, decide_eq_true_iff] at h2 + by_cases hx' : x < k + c + · exact hw ⟨hx', h2.2⟩ + · have : x = k + c := by omega + subst this + exact h2.1 (Nat.add_mod_right k c) + · rintro ⟨hN, hh, hk, hw⟩ + refine ⟨hN, hh, by omega, ?_⟩ + rintro ⟨h1, h2⟩ + apply hw + refine ⟨by omega, ?_⟩ + rw [Bool.and_eq_true, decide_eq_true_iff] + refine ⟨fun he => ?_, h2⟩ + have := eq_of_mod_eq_window (show k ≤ x by omega) h1 he + omega + +theorem G_of_notS (_hc : 0 < c) {k M : ℕ} (h : M.testBit (k % c) = false) + (hk : ¬(k < N ∧ k ≠ hx)) : G N c hx k M = G N c hx (k + 1) M := by + ext x + rw [mem_G, mem_G] + constructor + · rintro ⟨hN, hh, hk', hw⟩ + have hxk : x ≠ k := by rintro rfl; exact hk ⟨hN, hh⟩ + refine ⟨hN, hh, by omega, ?_⟩ + rintro ⟨h1, h2⟩ + by_cases hx' : x < k + c + · exact hw ⟨hx', h2⟩ + · have : x = k + c := by omega + subst this + rw [Nat.add_mod_right, h] at h2 + exact absurd h2 (by simp) + · rintro ⟨hN, hh, hk', hw⟩ + exact ⟨hN, hh, by omega, fun ⟨h1, h2⟩ => hw ⟨by omega, h2⟩⟩ + +theorem G_down (hc : 0 < c) {k M : ℕ} (h : M.testBit (k % c) = false) : + G N c hx k M \ {k, k + c} = G N c hx (k + 1) (M + 2 ^ (k % c)) := by + ext x + rw [mem_sdiff, mem_G, mem_G, testBit_add_two_pow h, mem_insert, mem_singleton] + constructor + · rintro ⟨⟨hN, hh, hk, hw⟩, hne⟩ + push Not at hne + refine ⟨hN, hh, by omega, ?_⟩ + rintro ⟨h1, h2⟩ + have h1' : x < k + c := by omega + rw [Bool.or_eq_true, decide_eq_true_iff] at h2 + rcases h2 with h2 | h2 + · exact absurd (eq_of_mod_eq_window (by omega) h1' h2) hne.1 + · exact hw ⟨h1', h2⟩ + · rintro ⟨hN, hh, hk, hw⟩ + have hne : x ≠ k + c := by + rintro rfl + exact hw ⟨by omega, by rw [Nat.add_mod_right]; simp⟩ + refine ⟨⟨hN, hh, by omega, ?_⟩, ?_⟩ + · rintro ⟨h1, h2⟩ + exact hw ⟨by omega, by rw [h2]; simp⟩ + · push Not + exact ⟨by omega, hne⟩ + +theorem G_right (hc : 0 < c) {k M : ℕ} (h : M.testBit (k % c) = false) + (h' : M.testBit (k % c + 1) = false) (hs : k % c + 1 < c) : + G N c hx k M \ {k, k + 1} = G N c hx (k + 1) (M + 2 ^ (k % c + 1)) := by + have hk1 : (k + 1) % c = k % c + 1 := by + rw [Nat.add_mod, Nat.mod_eq_of_lt (show 1 < c by omega), Nat.mod_eq_of_lt hs] + ext x + rw [mem_sdiff, mem_G, mem_G, testBit_add_two_pow h', mem_insert, mem_singleton] + constructor + · rintro ⟨⟨hN, hh, hk, hw⟩, hne⟩ + push Not at hne + refine ⟨hN, hh, by omega, ?_⟩ + rintro ⟨h1, h2⟩ + rw [Bool.or_eq_true, decide_eq_true_iff] at h2 + by_cases hx' : x < k + c + · rcases h2 with h2 | h2 + · rw [← hk1] at h2 + exact hne.2 (eq_of_mod_eq_window (by omega) (by omega) h2) + · exact hw ⟨hx', h2⟩ + · have hxe : x = k + c := by omega + subst hxe + rw [Nat.add_mod_right] at h2 + rcases h2 with h2 | h2 + · omega + · rw [h] at h2 + exact absurd h2 (by simp) + · rintro ⟨hN, hh, hk, hw⟩ + have hne : x ≠ k + 1 := by + rintro rfl + exact hw ⟨by omega, by rw [hk1]; simp⟩ + refine ⟨⟨hN, hh, by omega, ?_⟩, ?_⟩ + · rintro ⟨h1, h2⟩ + exact hw ⟨by omega, by rw [h2]; simp⟩ + · push Not + exact ⟨by omega, hne⟩ + +theorem cnt_end {k M : ℕ} (hk : N ≤ k) : cnt N c hx k M = 1 := by + have : G N c hx k M = ∅ := by + ext x + simp only [mem_G, notMem_empty, iff_false] + rintro ⟨h1, -, h3, -⟩ + omega + rw [cnt, Fs, this, image_empty, ncard_tilings_empty] + +theorem cnt_of_set (hc : 0 < c) {k M : ℕ} (h : M.testBit (k % c) = true) : + cnt N c hx k M = cnt N c hx (k + 1) (M - 2 ^ (k % c)) := by + rw [cnt, cnt, Fs, Fs, G_of_set hc h] + +theorem cnt_of_notS (hc : 0 < c) {k M : ℕ} (h : M.testBit (k % c) = false) + (hk : inS N hx k = false) : cnt N c hx k M = cnt N c hx (k + 1) M := by + have hk' : ¬(k < N ∧ k ≠ hx) := by simpa [inS] using hk + rw [cnt, cnt, Fs, Fs, G_of_notS hc h hk'] + +theorem cnt_of_free (hc : 0 < c) {k M : ℕ} (h : M.testBit (k % c) = false) + (hk : inS N hx k = true) : + cnt N c hx k M = + (if k % c + 1 < c ∧ inS N hx (k + 1) = true ∧ M.testBit (k % c + 1) = false then + cnt N c hx (k + 1) (M + 2 ^ (k % c + 1)) else 0) + + (if inS N hx (k + c) = true then cnt N c hx (k + 1) (M + 2 ^ (k % c)) else 0) := by + simp only [inS, decide_eq_true_iff] at hk ⊢ + have hkG : k ∈ G N c hx k M := mem_G.2 ⟨hk.1, hk.2, le_rfl, fun ⟨_, h2⟩ => by + rw [h] at h2; exact absurd h2 (by simp)⟩ + have hp : cellOf c k ∈ Fs N c hx k M := mem_Fs_cellOf.2 hkG + have hmin : ∀ q ∈ Fs N c hx k M, q ≠ cellOf c k → + (cellOf c k).1 < q.1 ∨ ((cellOf c k).1 = q.1 ∧ (cellOf c k).2 < q.2) := by + intro q hq hne + obtain ⟨y, hy, rfl⟩ := mem_image.1 hq + have hky : k ≤ y := (mem_G.1 hy).2.2.1 + have : k ≠ y := fun e => hne (e ▸ rfl) + exact cellOf_lex (by omega) + rw [cnt, ncard_tilings_step hp hmin] + congr 1 + · by_cases hs : k % c + 1 < c + · have hk1 : (k + 1) % c = k % c + 1 := by + rw [Nat.add_mod, Nat.mod_eq_of_lt (show 1 < c by omega), Nat.mod_eq_of_lt hs] + have hmem : k + 1 ∈ G N c hx k M ↔ + (k + 1 < N ∧ k + 1 ≠ hx) ∧ M.testBit (k % c + 1) = false := by + rw [mem_G, hk1] + constructor + · rintro ⟨h1, h2, -, h4⟩ + refine ⟨⟨h1, h2⟩, ?_⟩ + cases hb : M.testBit (k % c + 1) + · rfl + · exact absurd ⟨by omega, hb⟩ h4 + · rintro ⟨⟨h1, h2⟩, h3⟩ + refine ⟨h1, h2, by omega, ?_⟩ + rintro ⟨-, h4⟩ + rw [h3] at h4 + exact absurd h4 (by simp) + rw [rt_cellOf hs] + by_cases hcond : (k + 1 < N ∧ k + 1 ≠ hx) ∧ M.testBit (k % c + 1) = false + · rw [if_pos (mem_Fs_cellOf.2 (hmem.2 hcond)), + if_pos (show k % c + 1 < c ∧ (k + 1 < N ∧ k + 1 ≠ hx) ∧ + M.testBit (k % c + 1) = false from ⟨hs, hcond⟩), Fs_sdiff, G_right hc h hcond.2 hs] + rfl + · rw [if_neg (fun h' => hcond (hmem.1 (mem_Fs_cellOf.1 h'))), + if_neg (show ¬(k % c + 1 < c ∧ (k + 1 < N ∧ k + 1 ≠ hx) ∧ + M.testBit (k % c + 1) = false) from fun h' => hcond h'.2)] + · have : rt (cellOf c k) ∉ Fs N c hx k M := fun hm => by + have := snd_lt_of_mem_Fs hc hm + simp only [rt, cellOf] at this + omega + rw [if_neg this, if_neg (fun h' => hs h'.1)] + · rw [dn_cellOf hc k] + have hmem : k + c ∈ G N c hx k M ↔ k + c < N ∧ k + c ≠ hx := by + rw [mem_G] + constructor + · rintro ⟨h1, h2, -, -⟩ + exact ⟨h1, h2⟩ + · rintro ⟨h1, h2⟩ + exact ⟨h1, h2, by omega, fun ⟨h3, _⟩ => by omega⟩ + by_cases hcond : k + c < N ∧ k + c ≠ hx + · rw [if_pos (mem_Fs_cellOf.2 (hmem.2 hcond)), if_pos hcond, Fs_sdiff, G_down hc h] + rfl + · rw [if_neg (fun h' => hcond (hmem.1 (mem_Fs_cellOf.1 h'))), if_neg hcond] + +theorem cnt_lt {W' : ℕ} (hN : N / 2 ≤ W') (k M : ℕ) : cnt N c hx k M < 2 ^ (W' + 1) := by + have h1 : (Fs N c hx k M).card ≤ N := by + calc (Fs N c hx k M).card ≤ (G N c hx k M).card := card_image_le + _ ≤ (range N).card := card_filter_le _ _ + _ = N := card_range N + calc cnt N c hx k M ≤ 2 ^ ((Fs N c hx k M).card / 2) := ncard_tilings_le _ _ le_rfl + _ ≤ 2 ^ W' := Nat.pow_le_pow_right (by norm_num) (by omega) + _ < 2 ^ (W' + 1) := Nat.pow_lt_pow_right (by norm_num) (by omega) + +/-! ### Correctness of the packed transfer matrix -/ + +theorem dig_stepP (hc : 0 < c) {W k X : ℕ} (hW : 0 < W) + (hbound : ∀ M, cnt N c hx k M < 2 ^ W) + (hX : ∀ M < 2 ^ c, dig W X M = cnt N c hx (k + 1) M) : + ∀ M < 2 ^ c, dig W (stepP c W N hx k X) M = cnt N c hx k M := by + set s := k % c with hs_def + have hs : s < c := Nat.mod_lt k hc + -- the entries of the masked vector + have hP : ∀ M < 2 ^ c, dig W (X &&& clr c W s) M = + if M.testBit s = true then 0 else cnt N c hx (k + 1) M := by + intro M hM + rw [dig_and, dig_clr hs hW] + by_cases hb : M.testBit s = true + · rw [if_neg (fun h => by rw [hb] at h; exact absurd h.2 (by simp)), if_pos hb, Nat.and_zero] + · rw [Bool.not_eq_true] at hb + rw [if_pos ⟨hM, hb⟩, if_neg (by rw [hb]; simp), Nat.and_two_pow_sub_one_eq_mod, + Nat.mod_eq_of_lt (dig_lt _ _ _), hX M hM] + have hA : ∀ M < 2 ^ c, dig W ((X &&& clr c W s) <<< (2 ^ s * W)) M = + if M.testBit s = true then cnt N c hx (k + 1) (M - 2 ^ s) else 0 := by + intro M hM + have hM' : M - 2 ^ s < 2 ^ c := lt_of_le_of_lt (Nat.sub_le _ _) hM + rw [dig_shiftLeft] + by_cases hb : M.testBit s = true + · have hle : 2 ^ s ≤ M := Nat.ge_two_pow_of_testBit hb + have hb' : (M - 2 ^ s).testBit s = false := by + rw [testBit_sub_two_pow hb]; simp + rw [if_pos hle, if_pos hb, hP _ hM', + if_neg (show ¬((M - 2 ^ s).testBit s = true) by rw [hb']; simp)] + · have hb' : M.testBit s = false := by simpa using hb + rw [if_neg hb] + by_cases hle : 2 ^ s ≤ M + · rw [if_pos hle, hP _ hM', if_pos (testBit_sub_two_pow_of_false hle hb')] + · rw [if_neg hle] + have hfinal : ∀ Y, (∀ M < 2 ^ c, dig W Y M = if M.testBit s = true then 0 else cnt N c hx k M) → + ∀ M < 2 ^ c, dig W ((X &&& clr c W s) <<< (2 ^ s * W) + Y) M = cnt N c hx k M := by + intro Y hY + have hsum : ∀ M < 2 ^ c, + dig W ((X &&& clr c W s) <<< (2 ^ s * W)) M + dig W Y M = cnt N c hx k M := by + intro M hM + rw [hA M hM, hY M hM] + split_ifs with hb + · rw [add_zero, ← cnt_of_set hc hb] + · rw [zero_add] + intro M hM + rw [dig_add (fun i hi => by rw [hsum i (lt_of_le_of_lt hi hM)]; exact hbound i), hsum M hM] + unfold stepP + rw [← hs_def] + apply hfinal + intro M hM + have h0 : ∀ M', dig W 0 M' = 0 := fun M' => by simp [dig] + by_cases hk : inS N hx k = true + · -- `k` is a cell of the region + rw [if_pos hk] + have hD : ∀ M' < 2 ^ c, + dig W (if inS N hx (k + c) = true then (X >>> (2 ^ s * W)) &&& clr c W s else 0) M' = + if M'.testBit s = true then 0 else + if inS N hx (k + c) = true then cnt N c hx (k + 1) (M' + 2 ^ s) else 0 := by + intro M' hM' + by_cases hkc : inS N hx (k + c) = true + · rw [if_pos hkc, if_pos hkc, dig_and, dig_clr hs hW] + by_cases hb : M'.testBit s = true + · rw [if_pos hb, if_neg (show ¬(M' < 2 ^ c ∧ M'.testBit s = false) from + fun h => by rw [hb] at h; exact absurd h.2 (by simp))] + simp only [Nat.and_zero] + · have hb' : M'.testBit s = false := by simpa using hb + rw [if_neg hb, if_pos (show M' < 2 ^ c ∧ M'.testBit s = false from ⟨hM', hb'⟩), + dig_shiftRight, Nat.and_two_pow_sub_one_eq_mod, Nat.mod_eq_of_lt (dig_lt _ _ _), + hX _ (add_two_pow_lt hM' hs hb')] + · rw [if_neg hkc, if_neg hkc, h0] + split_ifs <;> rfl + have hR : ∀ M' < 2 ^ c, dig W (if s + 1 < c ∧ inS N hx (k + 1) = true then + (X >>> (2 ^ (s + 1) * W)) &&& (clr c W s &&& clr c W (s + 1)) else 0) M' = + if M'.testBit s = true then 0 else + if s + 1 < c ∧ inS N hx (k + 1) = true ∧ M'.testBit (s + 1) = false then + cnt N c hx (k + 1) (M' + 2 ^ (s + 1)) else 0 := by + intro M' hM' + by_cases hcond : s + 1 < c ∧ inS N hx (k + 1) = true + · rw [if_pos hcond, dig_and, dig_and, dig_clr hs hW, dig_clr hcond.1 hW] + by_cases hb : M'.testBit s = true + · rw [if_pos hb, if_neg (show ¬(M' < 2 ^ c ∧ M'.testBit s = false) from + fun h => by rw [hb] at h; exact absurd h.2 (by simp))] + simp only [Nat.zero_and, Nat.and_zero] + · have hb' : M'.testBit s = false := by simpa using hb + rw [if_neg hb, if_pos (show M' < 2 ^ c ∧ M'.testBit s = false from ⟨hM', hb'⟩)] + by_cases hb1 : M'.testBit (s + 1) = false + · rw [if_pos (show M' < 2 ^ c ∧ M'.testBit (s + 1) = false from ⟨hM', hb1⟩), + if_pos (show s + 1 < c ∧ inS N hx (k + 1) = true ∧ M'.testBit (s + 1) = false from + ⟨hcond.1, hcond.2, hb1⟩), Nat.and_self, dig_shiftRight, + Nat.and_two_pow_sub_one_eq_mod, Nat.mod_eq_of_lt (dig_lt _ _ _), + hX _ (add_two_pow_lt hM' hcond.1 hb1)] + · rw [if_neg (show ¬(M' < 2 ^ c ∧ M'.testBit (s + 1) = false) from fun h => hb1 h.2), + if_neg (show ¬(s + 1 < c ∧ inS N hx (k + 1) = true ∧ + M'.testBit (s + 1) = false) from fun h => hb1 h.2.2)] + simp only [Nat.and_zero] + · rw [if_neg hcond, h0] + split_ifs with h1 h2 <;> first | rfl | exact absurd ⟨h2.1, h2.2.1⟩ hcond + have hsum2 : ∀ M' < 2 ^ c, + dig W (if inS N hx (k + c) = true then (X >>> (2 ^ s * W)) &&& clr c W s else 0) M' + + dig W (if s + 1 < c ∧ inS N hx (k + 1) = true then + (X >>> (2 ^ (s + 1) * W)) &&& (clr c W s &&& clr c W (s + 1)) else 0) M' = + if M'.testBit s = true then 0 else cnt N c hx k M' := by + intro M' hM' + rw [hD M' hM', hR M' hM'] + by_cases hb : M'.testBit s = true + · simp [hb] + · have hb' : M'.testBit s = false := by simpa using hb + rw [if_neg hb, if_neg hb, if_neg hb, cnt_of_free hc hb' hk] + exact add_comm _ _ + rw [dig_add (fun i hi => by + rw [hsum2 i (lt_of_le_of_lt hi hM)] + split_ifs + · exact Nat.two_pow_pos W + · exact hbound i), hsum2 M hM] + · have hk' : inS N hx k = false := by simpa using hk + rw [if_neg hk, hP M hM] + by_cases hb : M.testBit s = true + · rw [if_pos hb, if_pos hb] + · have hb' : M.testBit s = false := by simpa using hb + rw [if_neg hb, if_neg hb, cnt_of_notS hc hb' hk'] + +end States + +/-- The packed vector at cell `N - j` holds the completion counts. -/ +theorem dig_vecP {N c hx W : ℕ} (hc : 0 < c) (hW : 0 < W) + (hbound : ∀ k M, cnt N c hx k M < 2 ^ W) : + ∀ j ≤ N, ∀ M < 2 ^ c, dig W (vecP c W N hx j) M = cnt N c hx (N - j) M + | 0, _, M, hM => by + rw [vecP, dig_ones hW, if_pos hM, Nat.sub_zero, cnt_end le_rfl] + | j + 1, hj, M, hM => by + rw [vecP] + have hk : N - (j + 1) + 1 = N - j := by omega + refine dig_stepP hc hW (hbound _) ?_ M hM + intro M' hM' + rw [hk] + exact dig_vecP hc hW hbound j (by omega) M' hM' + +/-- The region is the set of free cells of the initial state. -/ +theorem region_eq (n m : ℕ) : + region n m = Fs ((2 * n + 1) * (2 * m + 1)) (2 * m + 1) (n * (2 * m + 1) + m) 0 0 := by + ext p + simp only [region, board, Fs, mem_erase, mem_product, mem_range, mem_image, mem_G, + Nat.zero_testBit, Bool.false_eq_true, and_false, not_false_eq_true, and_true, zero_le] + constructor + · rintro ⟨hne, h1, h2⟩ + refine ⟨idx (2 * m + 1) p, ⟨(mul_add_lt_iff h2).2 h1, fun e => hne ?_⟩, cellOf_idx h2⟩ + rw [← cellOf_idx h2, e, ← cellOf_idx (p := (n, m)) (show m < 2 * m + 1 by omega)] + rfl + · rintro ⟨x, ⟨hx, hne⟩, rfl⟩ + refine ⟨fun e => hne ?_, ?_, Nat.mod_lt _ (by omega)⟩ + · rw [← idx_cellOf (2 * m + 1) x, e] + rfl + · exact (Nat.div_lt_iff_lt_mul (by omega)).2 hx + +/-- `T` is computed by `Tc`. -/ +theorem T_eq_Tc (n m : ℕ) : T n m = Tc n m := by + have hc : 0 < 2 * m + 1 := by omega + have hb : ∀ k M, cnt ((2 * n + 1) * (2 * m + 1)) (2 * m + 1) (n * (2 * m + 1) + m) k M < + 2 ^ ((2 * n + 1) * (2 * m + 1) / 2 + 1) := fun k M => cnt_lt le_rfl k M + have := dig_vecP hc (by omega) hb _ le_rfl 0 (Nat.two_pow_pos _) + rw [Nat.sub_self] at this + rw [T, region_eq, Tc, ← cnt, ← this, dig, zero_mul, Nat.shiftRight_zero] + +theorem rowCol_spec : ∀ (d n fuel m : ℕ), d ≤ fuel → m ≤ n + d → + rowCol fuel n ((∑ j ∈ range d, (n + 1 + j)) + m) = (n + d, m) + | 0, n, fuel, m, _, hm => by + rcases fuel with _ | fuel + · simp [rowCol] + · simp [rowCol, show m ≤ n by omega] + | d + 1, n, fuel, m, hd, hm => by + obtain ⟨fuel, rfl⟩ : ∃ f, fuel = f + 1 := ⟨fuel - 1, by omega⟩ + rw [sum_range_succ'] + have h1 : ¬ (∑ j ∈ range d, (n + 1 + (j + 1)) + (n + 1 + 0) + m ≤ n) := by omega + rw [rowCol, if_neg h1] + have h2 : ∑ j ∈ range d, (n + 1 + (j + 1)) + (n + 1 + 0) + m - (n + 1) = + ∑ j ∈ range d, (n + 1 + 1 + j) + m := by + have : ∑ j ∈ range d, (n + 1 + (j + 1)) = ∑ j ∈ range d, (n + 1 + 1 + j) := + sum_congr rfl fun j _ => by ring + omega + rw [h2, rowCol_spec d (n + 1) fuel m (by omega) (by omega)] + congr 1 + omega + +/-- `a` is the triangle `T` read by rows (offset `0`). -/ +theorem a_spec (n m : ℕ) (hm : m ≤ n) : a (n * (n + 1) / 2 + m) = T n m := by + have hsum : ∀ n : ℕ, ∑ j ∈ range n, (0 + 1 + j) = n * (n + 1) / 2 := by + intro n + induction n with + | zero => simp + | succ n ih => + rw [sum_range_succ, ih, + show (n + 1) * (n + 1 + 1) = n * (n + 1) + 2 * (n + 1) by ring] + omega + have hge : n ≤ ∑ j ∈ range n, (0 + 1 + j) := by + rw [sum_add_distrib]; simp + rw [a, ← hsum n, rowCol_spec n 0 _ m (by omega) (by omega), T_eq_Tc, zero_add] + +/-! ### The conjecture -/ + +open PowerSeries + +/-- The numerator of the conjectured generating function. -/ +noncomputable def num : ℚ⟦X⟧ := + -1 - 4 * X + 543 * X ^ 2 - 6238 * X ^ 3 + 17032 * X ^ 4 - 6238 * X ^ 5 + 543 * X ^ 6 - + 4 * X ^ 7 - X ^ 8 + +/-- The denominator of the conjectured generating function. -/ +noncomputable def den : ℚ⟦X⟧ := + (X - 1) * (X ^ 2 - 7 * X + 1) * (X ^ 2 - 23 * X + 1) * + (X ^ 4 - 161 * X ^ 3 + 576 * X ^ 2 - 161 * X + 1) + +/-- Mathar's conjecture: the generating function `∑_{k ≥ 0} T(2k, 2) x^k` of column `m = 2` +(the third column, `(4k+1) × 5` boards) equals `num / den`. -/ +def statement : Prop := + PowerSeries.mk (fun k => (T (2 * k) 2 : ℚ)) = num * den⁻¹ + +theorem constantCoeff_den : constantCoeff den = -1 := by + simp [den] + +/-- The conjecture with the denominator cleared. -/ +theorem statement_iff : statement ↔ PowerSeries.mk (fun k => (T (2 * k) 2 : ℚ)) * den = num := by + rw [statement, eq_mul_inv_iff_mul_eq (by rw [constantCoeff_den]; norm_num)] + +/-- Sanity check: the first coefficients `T(2k, 2)`, `k = 0, …, 3`, of the series in `statement` +are `1, 196, 31329, 4941729`, the first coefficients of the conjectured g.f. (kernel-checked). -/ +theorem column_data : (List.range 4).map (fun k => T (2 * k) 2) = [1, 196, 31329, 4941729] := by + rw [show (fun k => T (2 * k) 2) = fun k => Tc (2 * k) 2 from funext fun k => T_eq_Tc _ _] + decide +kernel + +end Math0.Statements.A270668 diff --git a/lean/Math0/Statements/OEIS/A275815.lean b/lean/Math0/Statements/OEIS/A275815.lean new file mode 100644 index 0000000..4763f4f --- /dev/null +++ b/lean/Math0/Statements/OEIS/A275815.lean @@ -0,0 +1,121 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A275815: maximum total number of moves of same-colored queens on an `n × n` board + +Source: https://oeis.org/A275815, _Alec Jones_, Nov 16 2016. Verbatim (FORMULA): +> Conjecture: a(n) = 8(n-2)^2 for n >= 6. - _Alec Jones_, Nov 16 2016 + +The entry (_Peter Kagey_, Nov 14 2016, offset `1`) is named "Maximum total number of possible +moves that any number of queens of the same color can make on an n X n chessboard." + +## Encoding + +* *Board and placements.* The squares of the `n × n` board are the pairs `(i, j)` of natural + numbers with `i, j < n` (`board n`). A placement of any number of queens (possibly none) is a + subset `S ⊆ board n`, one queen on each square of `S`. +* *Moves.* All queens have the same color, so a queen can neither capture nor jump over another + queen: it moves to an *empty* square of the board along one of its eight directions, and every + square passed on the way must be empty too. For a queen on `p` and a direction `d ∈ ℤ²`, the + queen can stop on `p + k • d` (`k ≥ 1`) iff all of `p + d, …, p + k • d` are empty squares of + the board (`isEmptySquare`). The number of such `k` is the length of the longest initial run of + empty squares among `p + t • d`, `t = 1, …, n` (`rayMoves`; the square `p + n • d` is never on + the board for `d ≠ 0`). Distinct pairs `(d, k)` give distinct target squares, so `rayMoves` + summed over the eight queen directions (`queenDirs`) is the number of moves of that queen. + `totalMoves n S` is the total number of moves, summed over all queens of `S`. This reading + reproduces the entry's example for `n = 3` (`example3`: queens on `A3, A2, B1, C3` make + `3 + 4 + 5 + 5 = 17` moves). +* *The sequence.* `a n` is the maximum of `totalMoves n` over all placements `S ⊆ board n` + (offset `1`; `a 0 = 0` is a harmless extra value). It is computable, by exhaustive search over + the `2 ^ (n * n)` placements; the definition does not use the conjectured formula. +* *The conjecture.* `statement`: for every `n ≥ 6`, `a n = 8 * (n - 2) ^ 2` (natural-number + subtraction, exact since `n ≥ 6`). No other hypotheses. + +## Data checks + +* `a_data`: the kernel computes `a 1, a 2, a 3 = 0, 4, 17`, the first three listed terms. The + definition is an exhaustive search over `2 ^ (n * n)` placements, so `n = 4` (`65536` + placements) is already far beyond what the kernel does in about a minute. +* `a_ge_data`: lower bounds for the listed terms with `4 ≤ n ≤ 12`. For each such `n` an + explicit placement (search results for `n = 4, 5`; the `4n - 4` border squares for `n ≥ 6`, as + in the entry's FORMULA section) has, by kernel computation, exactly the listed number of moves + (`witness_spec`). Hence `a n ≥ A275815(n)` for `4 ≤ n ≤ 12`. The range is sized to the kernel + budget: the checks in this file take about a minute of kernel time in total, and each further + `n ≥ 13` would add at least about 15 seconds. (Outside Lean, the border placements were also + checked to attain every listed term up to `a(32) = 7200`.) +-/ + +namespace Math0.Statements.A275815 + +/-- The squares of the `n × n` board: pairs `(i, j)` of natural numbers with `i, j < n`. -/ +def board (n : ℕ) : Finset (ℕ × ℕ) := Finset.range n ×ˢ Finset.range n + +/-- The point `(x, y) ∈ ℤ²` is a square of the `n × n` board that carries no queen of the +placement `S`. -/ +def isEmptySquare (n : ℕ) (S : Finset (ℕ × ℕ)) (x y : ℤ) : Bool := + decide (0 ≤ x ∧ x < n ∧ 0 ≤ y ∧ y < n ∧ (x.toNat, y.toNat) ∉ S) + +/-- The number of moves of a queen on the square `p` in the direction `d`: the number of `k ≥ 1` +such that `p + d, p + 2 • d, …, p + k • d` are all empty squares of the board, i.e. the length of +the longest initial segment of `t = 1, 2, …, n` for which `p + t • d` is an empty square. -/ +def rayMoves (n : ℕ) (S : Finset (ℕ × ℕ)) (p : ℕ × ℕ) (d : ℤ × ℤ) : ℕ := + ((List.range' 1 n).takeWhile fun t => + isEmptySquare n S (p.1 + t * d.1) (p.2 + t * d.2)).length + +/-- The eight directions of a queen. -/ +def queenDirs : List (ℤ × ℤ) := + [(1, 1), (1, -1), (-1, 1), (-1, -1), (1, 0), (-1, 0), (0, 1), (0, -1)] + +/-- The total number of moves that the queens of the placement `S` (all of the same color) can +make on the `n × n` board. -/ +def totalMoves (n : ℕ) (S : Finset (ℕ × ℕ)) : ℕ := + ∑ p ∈ S, (queenDirs.map (rayMoves n S p)).sum + +/-- A275815: the maximum total number of possible moves that any number of queens of the same +color can make on an `n × n` chessboard. -/ +def a (n : ℕ) : ℕ := (board n).powerset.sup (totalMoves n) + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 3).map (fun i => a (i + 1)) = [0, 4, 17] := by + decide +kernel + +/-- The entry's example for `n = 3`: queens on `A3, A2, B1, C3`, written as `(column, row - 1)`, +make `3 + 4 + 5 + 5 = 17` moves. -/ +theorem example3 : + ([(0, 2), (0, 1), (1, 0), (2, 2)].map fun p => + (queenDirs.map (rayMoves 3 {(0, 2), (0, 1), (1, 0), (2, 2)} p)).sum) = [3, 4, 5, 5] ∧ + totalMoves 3 {(0, 2), (0, 1), (1, 0), (2, 2)} = 17 := by + decide +kernel + +/-! ### Lower bounds for further listed terms -/ + +/-- The `4n - 4` squares on the border of the `n × n` board. -/ +def border (n : ℕ) : Finset (ℕ × ℕ) := + (board n).filter fun p => p.1 = 0 ∨ p.1 = n - 1 ∨ p.2 = 0 ∨ p.2 = n - 1 + +/-- Queen placements attaining the listed values for `4 ≤ n ≤ 12`. -/ +def witness : ℕ → Finset (ℕ × ℕ) + | 4 => {(0, 0), (0, 2), (0, 3), (1, 0), (2, 3), (3, 1)} + | 5 => {(0, 1), (0, 2), (0, 3), (1, 0), (1, 4), (2, 2), (3, 0), (3, 4), (4, 1), (4, 2), (4, 3)} + | n => border n + +theorem witness_spec : ∀ i < 9, witness (i + 4) ⊆ board (i + 4) ∧ + totalMoves (i + 4) (witness (i + 4)) = + [40, 76, 128, 200, 288, 392, 512, 648, 800].getD i 0 := by + decide +kernel + +/-- The listed terms `a(4), …, a(12)` are lower bounds for `a`. -/ +theorem a_ge_data : + ∀ i < 9, [40, 76, 128, 200, 288, 392, 512, 648, 800].getD i 0 ≤ a (i + 4) := by + intro i hi + obtain ⟨hS, hv⟩ := witness_spec i hi + exact hv ▸ Finset.le_sup (f := totalMoves (i + 4)) (Finset.mem_powerset.mpr hS) + +/-- Alec Jones's conjecture: for every `n ≥ 6`, the maximum total number of moves that any number +of same-colored queens can make on an `n × n` chessboard is `8 (n - 2) ^ 2`. -/ +def statement : Prop := ∀ n : ℕ, 6 ≤ n → a n = 8 * (n - 2) ^ 2 + +end Math0.Statements.A275815 diff --git a/lean/Math0/Statements/OEIS/A278212.lean b/lean/Math0/Statements/OEIS/A278212.lean new file mode 100644 index 0000000..e8fc50e --- /dev/null +++ b/lean/Math0/Statements/OEIS/A278212.lean @@ -0,0 +1,148 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A278212: maximum total number of moves of same-colored bishops on an `n × n` board + +Source: https://oeis.org/A278212, _Peter Kagey_, Nov 24 2016. Verbatim (COMMENTS): +> Conjecture: a(n) = floor(A275815(n)/2). - _Peter Kagey_, Nov 24 2016 + +The entry's name is "Maximum total number of possible moves that any number of bishops of the +same color can make on an n X n chessboard." (offset `1`). A275815 (offset `1`) is "Maximum total +number of possible moves that any number of queens of the same color can make on an n X n +chessboard." + +## Encoding + +* *Board and placements.* The squares of the `n × n` board are the pairs `(i, j)` of natural + numbers with `i, j < n` (`board n`). A placement of any number of pieces (possibly none) is a + subset `S ⊆ board n`, one piece on each square of `S`. +* *Moves.* All pieces have the same color, so a piece can neither capture nor jump over another + piece: it moves to an *empty* square of the board along one of its directions, and every + square passed on the way must be empty too. For a piece on `p` and a direction `d ∈ ℤ²`, the + piece can stop on `p + k • d` (`k ≥ 1`) iff all of `p + d, …, p + k • d` are empty squares of + the board (`isEmptySquare`). The number of such `k` is the length of the longest initial run of + empty squares among `p + t • d`, `t = 1, …, n` (`rayMoves`; the square `p + n • d` is never on + the board for `d ≠ 0`). Distinct pairs `(d, k)` give distinct target squares. + Bishops move in the four diagonal directions `(±1, ±1)` (`bishopDirs`); queens in these and + the four orthogonal directions `(±1, 0)`, `(0, ±1)` (`queenDirs`). `totalMoves dirs n S` is + the total number of moves, summed over all pieces of `S`. + "Same color" refers to the pieces (one side), not to the color of their squares: the entry's + example for `n = 5` has bishops on squares of both colors (`bishopWitness 5` below). +* *The sequences.* `a n` (A278212) and `queenMax n` (A275815) are the maxima of `totalMoves` over + all placements `S ⊆ board n`, for bishops and for queens respectively. Both are computable (by + exhaustive search over the `2 ^ (n * n)` placements). +* *The conjecture.* `statement`: for every `n ≥ 1` (the common offset of both sequences), + `a n = queenMax n / 2`, where `/` is natural-number division, i.e. `floor`. + +## Data checks + +* `a_data`, `queenMax_data`: the kernel computes `a 1, a 2, a 3 = 0, 2, 8` and + `queenMax 1, queenMax 2, queenMax 3 = 0, 4, 17`, the first three listed terms of A278212 and of + A275815. The definition is an exhaustive search over `2 ^ (n * n)` placements, so `n = 4` + (`65536` placements) is already beyond what the kernel does in about a minute. +* `a_ge_data`, `queenMax_ge_data`: lower bounds for the listed terms with `4 ≤ n ≤ 10`. For each + such `n` an explicit placement (the entry's example for bishops with `n = 5`, search results + for `n = 4` and for queens with `n = 5`, the `4n - 4` border squares for `n ≥ 6` as in the + entry's FORMULA section) has, by kernel computation, exactly the listed number of moves + (`bishopWitness_spec`, `queenWitness_spec`). Hence `a n ≥ A278212(n)` and + `queenMax n ≥ A275815(n)` for `4 ≤ n ≤ 10`. +-/ + +namespace Math0.Statements.A278212 + +/-- The squares of the `n × n` board: pairs `(i, j)` of natural numbers with `i, j < n`. -/ +def board (n : ℕ) : Finset (ℕ × ℕ) := Finset.range n ×ˢ Finset.range n + +/-- The point `(x, y) ∈ ℤ²` is a square of the `n × n` board that carries no piece of the +placement `S`. -/ +def isEmptySquare (n : ℕ) (S : Finset (ℕ × ℕ)) (x y : ℤ) : Bool := + decide (0 ≤ x ∧ x < n ∧ 0 ≤ y ∧ y < n ∧ (x.toNat, y.toNat) ∉ S) + +/-- The number of moves of a piece on the square `p` in the direction `d`: the number of `k ≥ 1` +such that `p + d, p + 2 • d, …, p + k • d` are all empty squares of the board, i.e. the length of +the longest initial segment of `t = 1, 2, …, n` for which `p + t • d` is an empty square. -/ +def rayMoves (n : ℕ) (S : Finset (ℕ × ℕ)) (p : ℕ × ℕ) (d : ℤ × ℤ) : ℕ := + ((List.range' 1 n).takeWhile fun t => + isEmptySquare n S (p.1 + t * d.1) (p.2 + t * d.2)).length + +/-- The four directions of a bishop. -/ +def bishopDirs : List (ℤ × ℤ) := [(1, 1), (1, -1), (-1, 1), (-1, -1)] + +/-- The eight directions of a queen. -/ +def queenDirs : List (ℤ × ℤ) := + [(1, 1), (1, -1), (-1, 1), (-1, -1), (1, 0), (-1, 0), (0, 1), (0, -1)] + +/-- The total number of moves that the pieces of the placement `S` (all of the same color, each +moving in the directions `dirs`) can make on the `n × n` board. -/ +def totalMoves (dirs : List (ℤ × ℤ)) (n : ℕ) (S : Finset (ℕ × ℕ)) : ℕ := + ∑ p ∈ S, (dirs.map (rayMoves n S p)).sum + +/-- A278212: the maximum total number of possible moves that any number of bishops of the same +color can make on an `n × n` chessboard. -/ +def a (n : ℕ) : ℕ := (board n).powerset.sup (totalMoves bishopDirs n) + +/-- A275815: the maximum total number of possible moves that any number of queens of the same +color can make on an `n × n` chessboard. -/ +def queenMax (n : ℕ) : ℕ := (board n).powerset.sup (totalMoves queenDirs n) + +/-- The definition reproduces the first terms listed in A278212 (kernel-checked). -/ +theorem a_data : (List.range 3).map (fun i => a (i + 1)) = [0, 2, 8] := by + decide +kernel + +/-- The definition reproduces the first terms listed in A275815 (kernel-checked). -/ +theorem queenMax_data : (List.range 3).map (fun i => queenMax (i + 1)) = [0, 4, 17] := by + decide +kernel + +/-! ### Lower bounds for further listed terms -/ + +/-- The `4n - 4` squares on the border of the `n × n` board. -/ +def border (n : ℕ) : Finset (ℕ × ℕ) := + (board n).filter fun p => p.1 = 0 ∨ p.1 = n - 1 ∨ p.2 = 0 ∨ p.2 = n - 1 + +/-- Bishop placements attaining the listed values for `4 ≤ n ≤ 10`; the one for `n = 5` is the +example in the entry (`(column, row - 1)` for the squares `A5, B5, C5, E5, E4, A3, B3, E3, E2, +A1, B1, C1, E1`). -/ +def bishopWitness : ℕ → Finset (ℕ × ℕ) + | 4 => {(0, 0), (0, 3), (1, 0), (1, 3), (2, 0), (2, 3), (3, 0), (3, 3)} + | 5 => {(0, 4), (1, 4), (2, 4), (4, 4), (4, 3), (0, 2), (1, 2), (4, 2), (4, 1), (0, 0), (1, 0), + (2, 0), (4, 0)} + | n => border n + +/-- Queen placements attaining the listed values for `4 ≤ n ≤ 10`. -/ +def queenWitness : ℕ → Finset (ℕ × ℕ) + | 4 => {(0, 0), (0, 2), (0, 3), (1, 0), (2, 3), (3, 1)} + | 5 => {(0, 1), (0, 2), (0, 3), (1, 0), (1, 4), (2, 2), (3, 0), (3, 4), (4, 1), (4, 2), (4, 3)} + | n => border n + +theorem bishopWitness_spec : ∀ i < 7, bishopWitness (i + 4) ⊆ board (i + 4) ∧ + totalMoves bishopDirs (i + 4) (bishopWitness (i + 4)) = + [20, 38, 64, 100, 144, 196, 256].getD i 0 := by + decide +kernel + +theorem queenWitness_spec : ∀ i < 7, queenWitness (i + 4) ⊆ board (i + 4) ∧ + totalMoves queenDirs (i + 4) (queenWitness (i + 4)) = + [40, 76, 128, 200, 288, 392, 512].getD i 0 := by + decide +kernel + +/-- The listed terms `a(4), …, a(10)` of A278212 are lower bounds for `a`. -/ +theorem a_ge_data : ∀ i < 7, [20, 38, 64, 100, 144, 196, 256].getD i 0 ≤ a (i + 4) := by + intro i hi + obtain ⟨hS, hv⟩ := bishopWitness_spec i hi + exact hv ▸ Finset.le_sup (f := totalMoves bishopDirs (i + 4)) (Finset.mem_powerset.mpr hS) + +/-- The listed terms `a(4), …, a(10)` of A275815 are lower bounds for `queenMax`. -/ +theorem queenMax_ge_data : + ∀ i < 7, [40, 76, 128, 200, 288, 392, 512].getD i 0 ≤ queenMax (i + 4) := by + intro i hi + obtain ⟨hS, hv⟩ := queenWitness_spec i hi + exact hv ▸ Finset.le_sup (f := totalMoves queenDirs (i + 4)) (Finset.mem_powerset.mpr hS) + +/-- Kagey's conjecture: for every `n ≥ 1`, A278212(n) = floor(A275815(n) / 2), i.e. the maximum +total number of moves of same-colored bishops on an `n × n` board is the floor of half the +maximum total number of moves of same-colored queens. -/ +def statement : Prop := ∀ n : ℕ, 1 ≤ n → a n = queenMax n / 2 + +end Math0.Statements.A278212 diff --git a/lean/Math0/Statements/OEIS/A281000.lean b/lean/Math0/Statements/OEIS/A281000.lean new file mode 100644 index 0000000..f285ae6 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A281000.lean @@ -0,0 +1,178 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A281000: Schulte's conjectures on the triangle `C(2n+1,2k+1)·Cat(n-k)` + +Source: https://oeis.org/A281000, Werner Schulte, Jan 12 2017 (FORMULA section). Verbatim: +> Conjectures: +> (1) Antidiagonal sums equal A001003(n+1); +> (2) Sum_{k=0..n} (-1)^k*T(n,k)*(2*k+1)*A000108(k)*A103365(k) = A000007(n); +> (3) Matrix inverse equals T(n,k)*A103365(n+1-k). + +The entry (offset `0`, keyword `tabl`) is "Triangle read by rows: +T(n,k) = binomial(2*n+1, 2*k+1)*binomial(2*n-2*k, n-k)/(n+1-k) for 0 <= k <= n." + +## Encoding + +* *The triangle.* `T n k` is the displayed formula, computed in `ℕ`. The division is exact + (`binomial(2m, m)` is divisible by `m + 1`: it is `(m+1)·Cat(m)`). For `k > n` the formula gives + `0` (since `binomial(2n+1, 2k+1) = 0`), i.e. `T` is extended by zeros above the diagonal, as + usual for a lower-triangular matrix. `a` is the triangle read by rows (the OEIS sequence itself, + offset `0`); `a_data` checks all 55 listed terms (rows `0, …, 9`) in the kernel. +* *A001003* (little Schröder numbers, offset `0`: `1, 1, 3, 11, 45, …`). We use the classical + Narayana-sum formula from the entry (Cloitre; "row sums of A001263 * [1, 2, 4, 8, …]"): + `A001003(0) = 1` and `A001003(n) = Σ_{j=1..n} 2^(j-1)·N(n,j)` for `n ≥ 1`, where + `N(n,j) = C(n-1,j-1)·C(n,j-1)/j` is the Narayana triangle A001263 (its OEIS definition). + `A001003_data` checks all 26 listed terms. +* *A103365* (offset `1`): "First column of triangle A103364, which equals the matrix inverse of + the Narayana triangle (A001263)". The Narayana triangle `N(n,j)` (`1 ≤ j ≤ n`) is + lower unitriangular, so the first column `b` of its inverse is the unique solution of + `Σ_{j=1..n} N(n,j)·b(j) = [n = 1]` for all `n ≥ 1`; we compute it by forward substitution, + `b(n) = [n = 1] - Σ_{j=1..n-1} N(n,j)·b(j)` (`invNarayanaCol`). `A103365 0 = 0` is a junk + value outside the offset (it is only ever multiplied by `T(n,k) = 0`, see below). + `A103365_data` checks all 20 listed terms `a(1), …, a(20)`. +* *A000108* is Mathlib's `catalan`, and *A000007(n)* is `0 ^ n` (`= 1` for `n = 0`, else `0`). + +## The three conjectures + +* `conj1` (antidiagonal sums): for every `n ≥ 0`, `Σ_{k=0..⌊n/2⌋} T(n-k,k) = A001003(n+1)`. + The `n`-th antidiagonal consists of the entries `T(i,j)` with `i + j = n`; those with + `j > i` lie outside the triangle, so the sum runs over `k = j ≤ ⌊n/2⌋`. (Index `n` of the sum + matches `A001003(n+1)`: `1 = A001003(1)`, `3 = A001003(2)`, `10 + 1 = A001003(3)`, ….) +* `conj3` (matrix inverse): the infinite lower-triangular matrix `T` has inverse + `U(n,k) = T(n,k)·A103365(n+1-k)`. Both matrices are lower triangular (for `k > n`, + `U(n,k) = 0` because `T(n,k) = 0`, whatever the natural-number subtraction `n+1-k` gives), so + this is equivalent to: for every `N`, the inverse of the `N × N` leading principal submatrix of + `T` is the `N × N` leading principal submatrix of `U`. We state it in that form over `ℚ`, + using Mathlib's matrix inverse `⁻¹`. +* `conj2` (reading choice). As written, (2) is not well defined: at `k = 0` it uses + `A103365(0)`, but A103365 has offset `1` (its first term is `A103365(1) = 1`). With only the + index shift `A103365(k) ↦ A103365(k+1)` it is false already at `n = 1` (the sum is + `3 + 3 = 6`), because the factor `(-1)^k` cancels the alternating signs of A103365. The + identity the author presumably meant is the `k = 0` column of (3) (`T · T⁻¹ = I`, with + `T⁻¹(k,0) = T(k,0)·A103365(k+1) = (2k+1)·Cat(k)·A103365(k+1)`). We therefore read the factor + `(-1)^k·A103365(k)` as `A103365(k+1)`: A103365 indexed from `0`, with its sign pattern + `(-1)^k` absorbed (for the listed terms this is the same as reading `A103365(k)` as the + `k`-th term, counted from `0`, of the unsigned sequence `|A103365|`). This is the convention of + P. D. Hanna's g.f. in the A103365 entry itself: `A(x) = Σ_{n≥0} (-1)^n·a(n)·x^n/[n!(n+1)!/2^n] + = 1 - x + 2x^2/3 - 7x^3/18 + …`, where `(-1)^n·a(n)` is `A103365(n+1)`. So `conj2` states + `Σ_{k=0..n} T(n,k)·(2k+1)·A000108(k)·A103365(k+1) = A000007(n)` for every `n ≥ 0`. + It is the `k = 0` column of `conj3`, so including it does not change the strength of + `statement`. +* `statement := conj1 ∧ conj2 ∧ conj3`. + +`conj1_check`, `conj2_check` and `conj3_check` confirm the identities for small `n` (sanity +checks of the transcription, not proofs; `conj3_check` checks the entries of the matrix product +`T · U` in `ℤ`). +-/ + +namespace Math0.Statements.A281000 + +/-! ### The triangle -/ + +/-- A281000: `T(n,k) = binomial(2n+1, 2k+1)·binomial(2n-2k, n-k)/(n+1-k)` for `0 ≤ k ≤ n` +(and `0` for `k > n`). -/ +def T (n k : ℕ) : ℕ := + Nat.choose (2 * n + 1) (2 * k + 1) * Nat.choose (2 * n - 2 * k) (n - k) / (n + 1 - k) + +/-- A281000 as a sequence (offset `0`): the triangle `T` read by rows. (Rows `0, …, i` contain at +least `i + 1` entries, so the `i`-th entry of the concatenation lies among them.) -/ +def a (i : ℕ) : ℕ := + ((List.range (i + 1)).flatMap fun n => (List.range (n + 1)).map (T n)).getD i 0 + +/-- The definition reproduces all 55 terms listed in OEIS, `a 0, …, a 54` (kernel-checked). -/ +theorem a_data : (List.range 55).map (fun i => a (i + 0)) = + [1, 3, 1, 10, 10, 1, 35, 70, 21, 1, 126, 420, 252, 36, 1, 462, 2310, 2310, 660, 55, 1, + 1716, 12012, 18018, 8580, 1430, 78, 1, 6435, 60060, 126126, 90090, 25025, 2730, + 105, 1, 24310, 291720, 816816, 816816, 340340, 61880, 4760, 136, 1, 92378, 1385670, + 4988412, 6651216, 3879876, 1058148, 135660, 7752, 171, 1] := by + decide +kernel + +/-! ### Auxiliary sequences -/ + +/-- The Narayana triangle A001263: `N(n,k) = C(n-1,k-1)·C(n,k-1)/k` for `1 ≤ k ≤ n`. -/ +def narayana (n k : ℕ) : ℕ := + Nat.choose (n - 1) (k - 1) * Nat.choose n (k - 1) / k + +/-- A001003 (little Schröder numbers, offset `0`): `A001003(0) = 1` and +`A001003(n) = Σ_{j=1..n} 2^(j-1)·N(n,j)` for `n ≥ 1`. -/ +def A001003 (n : ℕ) : ℕ := + if n = 0 then 1 else ∑ j ∈ Finset.Icc 1 n, 2 ^ (j - 1) * narayana n j + +/-- All 26 listed terms of A001003, `A001003 0, …, A001003 25` (kernel-checked). -/ +theorem A001003_data : (List.range 26).map A001003 = + [1, 1, 3, 11, 45, 197, 903, 4279, 20793, 103049, 518859, 2646723, 13648869, 71039373, + 372693519, 1968801519, 10463578353, 55909013009, 300159426963, 1618362158587, + 8759309660445, 47574827600981, 259215937709463, 1416461675464871, + 7760733824437545, 42624971294485657] := by + decide +kernel + +/-- `invNarayanaCol m = [b 1, …, b m]`: the first `m` entries of the first column `b` of the +inverse of the (lower unitriangular) Narayana triangle, by forward substitution: +`b(n) = [n = 1] - Σ_{j=1..n-1} N(n,j)·b(j)` (row `n` of `N · b = e₁`, using `N(n,n) = 1`). -/ +def invNarayanaCol : ℕ → List ℤ + | 0 => [] + | m + 1 => + let l := invNarayanaCol m + l ++ [(if m = 0 then 1 else 0) - + ((List.range m).map fun j => (narayana (m + 1) (j + 1) : ℤ) * l.getD j 0).sum] + +/-- A103365 (offset `1`): first column of the matrix inverse of the Narayana triangle A001263. +(`A103365 0 = 0` is a junk value outside the offset.) -/ +def A103365 (n : ℕ) : ℤ := + (invNarayanaCol n).getD (n - 1) 0 + +/-- All 20 listed terms of A103365, `A103365 1, …, A103365 20` (kernel-checked). -/ +theorem A103365_data : (List.range 20).map (fun i => A103365 (i + 1)) = + [1, -1, 2, -7, 39, -321, 3681, -56197, 1102571, -27036487, 810263398, -29139230033, + 1238451463261, -61408179368043, 3513348386222286, -229724924077987509, + 17023649385410772579, -1419220037471837658603, 132236541042728184852942, + -13690229149108218523467549] := by + decide +kernel + +/-! ### The conjectures -/ + +/-- Conjecture (1): the antidiagonal sums of `T` are the little Schröder numbers: +`Σ_{k=0..⌊n/2⌋} T(n-k,k) = A001003(n+1)` for every `n ≥ 0`. -/ +def conj1 : Prop := + ∀ n : ℕ, ∑ k ∈ Finset.range (n / 2 + 1), T (n - k) k = A001003 (n + 1) + +/-- Conjecture (2), in the corrected reading explained in the module docstring: +`Σ_{k=0..n} T(n,k)·(2k+1)·Cat(k)·A103365(k+1) = A000007(n) = 0^n` for every `n ≥ 0`. -/ +def conj2 : Prop := + ∀ n : ℕ, ∑ k ∈ Finset.range (n + 1), + (T n k : ℤ) * (2 * k + 1) * (catalan k : ℤ) * A103365 (k + 1) = (0 : ℤ) ^ n + +/-- Conjecture (3): the matrix inverse of `T` is `U(n,k) = T(n,k)·A103365(n+1-k)`; stated for +every leading principal `N × N` submatrix (both matrices are lower triangular). -/ +def conj3 : Prop := + ∀ N : ℕ, (Matrix.of fun i j : Fin N => (T i j : ℚ))⁻¹ = + Matrix.of fun i j : Fin N => (T i j : ℚ) * (A103365 ((i : ℕ) + 1 - (j : ℕ)) : ℚ) + +/-- Werner Schulte's conjectures (1), (2), (3) on A281000 (Jan 12 2017). -/ +def statement : Prop := + conj1 ∧ conj2 ∧ conj3 + +/-! ### Sanity checks of the transcription (not proofs) -/ + +/-- Conjecture (1) holds for `n ≤ 24`. -/ +theorem conj1_check : + ∀ n < 25, ∑ k ∈ Finset.range (n / 2 + 1), T (n - k) k = A001003 (n + 1) := by + decide +kernel + +/-- Conjecture (2) (corrected reading) holds for `n ≤ 15`. -/ +theorem conj2_check : ∀ n < 16, ∑ k ∈ Finset.range (n + 1), + (T n k : ℤ) * (2 * k + 1) * (catalan k : ℤ) * A103365 (k + 1) = (0 : ℤ) ^ n := by + simp only [catalan_eq_centralBinom_div] + decide +kernel + +/-- The entries of `T · U` for `n, k ≤ 14` are those of the identity matrix +(`U(j,k) = T(j,k)·A103365(j+1-k)`). -/ +theorem conj3_check : ∀ n < 15, ∀ k < 15, ∑ j ∈ Finset.range (n + 1), + (T n j : ℤ) * ((T j k : ℤ) * A103365 (j + 1 - k)) = if n = k then 1 else 0 := by + decide +kernel + +end Math0.Statements.A281000 diff --git a/lean/Math0/Statements/OEIS/A294512.lean b/lean/Math0/Statements/OEIS/A294512.lean new file mode 100644 index 0000000..d5c7359 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A294512.lean @@ -0,0 +1,78 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A294512: denominators of partial sums of reciprocals of octagonal numbers + +Source: https://oeis.org/A294512, _Wolfdieter Lang_, Nov 01 2017. Verbatim (FORMULA section): +> a(n) = A250400(n+1)/(n+1), n >= 0. [conjecture]. + +The entry's definition: "Denominators of partial sums of the reciprocals of octagonal numbers.", +with "The octagonal numbers are here A000567(k+1) = (k + 1)*(3*k + 1), k >= 0." and +"a(n) = denominator(V(3,1;n)) with V(3,1;n) = Sum_{k=0..n} 1/((k + 1)*(3*k + 1))". Offset `0`. + +A250400 (offset `1`, _Colin Barker_, Nov 21 2014) is the "Numerator of the harmonic mean of the +first n octagonal numbers", i.e. the numerator, in lowest terms, of +`n / Sum_{j=1..n} 1/A000567(j)`, where A000567(j) = j*(3*j-2) (so the first octagonal numbers +are 1, 8, 21, ...; the example there: `3/(1/1+1/8+1/21) = 504/197`). + +## Encoding + +* `V n : ℚ` is the partial sum `∑_{k=0}^{n} 1/((k+1)(3k+1))`, and `a n` is the denominator of + `V n` (Mathlib's `Rat.den`, i.e. in lowest terms); `a` uses the OEIS offset `0`. +* `octagonal j = j * (3 * j - 2)` is A000567 (offset `0`; the subtraction is never truncated for + `j ≥ 1`), `harmonicMean m = m / ∑_{j=1}^{m} 1/octagonal j`, and `A250400 m` is the numerator of + `harmonicMean m` in lowest terms (a positive integer for `m ≥ 1`, taken as a natural number via + `Int.natAbs`); `A250400` uses the OEIS offset `1`. +* The quotient `A250400(n+1)/(n+1)` is read as an exact rational quotient, so the conjecture + says it equals the integer `a(n)` (in particular, that `n+1` divides `A250400(n+1)`), for every + `n ≥ 0`, i.e. every natural number `n`. +-/ + +namespace Math0.Statements.A294512 + +/-- The partial sum `V(3,1;n) = ∑_{k=0}^{n} 1/((k + 1)(3k + 1))` of the reciprocals of the +octagonal numbers `A000567(k+1) = (k + 1)(3k + 1)`. -/ +def V (n : ℕ) : ℚ := ∑ k ∈ Finset.range (n + 1), 1 / (((k : ℚ) + 1) * (3 * (k : ℚ) + 1)) + +/-- A294512: the denominator (in lowest terms) of the `n`-th partial sum `V n` of the reciprocals +of the octagonal numbers (offset `0`). -/ +def a (n : ℕ) : ℕ := (V n).den + +/-- The octagonal numbers A000567: `j * (3 * j - 2)` (offset `0`). -/ +def octagonal (j : ℕ) : ℕ := j * (3 * j - 2) + +/-- The harmonic mean of the first `m` octagonal numbers `octagonal 1, …, octagonal m`. -/ +def harmonicMean (m : ℕ) : ℚ := (m : ℚ) / ∑ j ∈ Finset.Icc 1 m, 1 / (octagonal j : ℚ) + +/-- A250400: the numerator (in lowest terms) of the harmonic mean of the first `m` octagonal +numbers (offset `1`). -/ +def A250400 (m : ℕ) : ℕ := (harmonicMean m).num.natAbs + +/-- The definition reproduces all 23 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 23).map (fun i => a (i + 0)) = + [1, 8, 168, 420, 5460, 14560, 276640, 3043040, 136936800, 136936800, 4245040800, + 72165693600, 2670130663200, 2670130663200, 114815618517600, 1320379612952400, + 9242657290666800, 3080885763555600, 280080523959600, 8122335194828400, + 165154148961510800, 14533565108612950400, 973748862277067676800] := by + decide +kernel + +/-- `A250400` reproduces all 20 terms listed in OEIS A250400 (kernel-checked). -/ +theorem A250400_data : (List.range 20).map (fun i => A250400 (i + 1)) = + [1, 16, 504, 1680, 27300, 87360, 1936480, 24344320, 1232431200, 1369368000, 46695448800, + 865988323200, 34711698621600, 37381829284800, 1722234277764000, 21126073807238400, + 157125173941335600, 55455943744000800, 5321529955232400, 162446703896568000] := by + decide +kernel + +/-- The octagonal numbers start `0, 1, 8, 21, 40` (as in A000567). -/ +theorem octagonal_data : (List.range 5).map octagonal = [0, 1, 8, 21, 40] := by + decide +kernel + +/-- Conjecture (Lang, A294512): for every `n ≥ 0`, `a(n) = A250400(n+1)/(n+1)`, the quotient +being taken in `ℚ`. -/ +def statement : Prop := + ∀ n : ℕ, (A250400 (n + 1) : ℚ) / ((n : ℚ) + 1) = (a n : ℚ) + +end Math0.Statements.A294512 diff --git a/lean/Math0/Statements/OEIS/A300789.lean b/lean/Math0/Statements/OEIS/A300789.lean new file mode 100644 index 0000000..f833514 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A300789.lean @@ -0,0 +1,315 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A300789: Heinz numbers of domino-tileable Young diagrams + +Source: https://oeis.org/A300789, _Gus Wiseman_, Mar 12 2018. Verbatim (COMMENTS): +> This sequence is conjectured to be the Heinz numbers of integer partitions in which the odd +> parts appear as many times in even as in odd positions. + +The entry's name is "Heinz numbers of integer partitions whose Young diagram can be tiled by +dominos." (offset `1`), with the comment "The Heinz number of an integer partition +(y_1,...,y_k) is prime(y_1)*...*prime(y_k)." + +## Encoding + +* *Partitions and Heinz numbers.* Every `k ≥ 1` is the Heinz number of exactly one integer + partition: its parts are the prime indices of `k`, i.e. `i` once for each prime factor + `prime(i)` of `k` (with multiplicity), where `prime(1) = 2`. The index of a prime `p` is + `Nat.primeCounting p = π(p)`. `parts k` lists them in weakly decreasing order + `y_1 ≥ y_2 ≥ … ≥ y_m` (Mathlib's `Nat.primeFactorsList k` is increasing; it is reversed). + `parts 1 = []` is the empty partition. +* *Young diagram.* `youngDiagram y` is the set of cells `(i, j)` (0-indexed row `i`, column + `j`) with `i < m` and `j < y_{i+1}`: row `i` has `y_{i+1}` cells, left-justified. +* *Domino tilings.* A domino is a set of two edge-adjacent cells `{(i, j), (i + 1, j)}` or + `{(i, j), (i, j + 1)}`. A set `S` of cells is `DominoTileable` if it is the union of a family + of pairwise disjoint dominoes. (The empty diagram is tiled by the empty family, so `1` is a + term.) `IsTerm k` says `k ≥ 1` and the Young diagram of the partition with Heinz number `k` is + domino-tileable. +* *The sequence.* `a n = Nat.nth IsTerm (n - 1)`: the `n`-th term (offset `1`) is the `n`-th + smallest element of `{k | IsTerm k}`. It is noncomputable as written (`Nat.nth`), but + `IsTerm` is decidable. `tileL` is a search for a tiling (the row-major first cell of a set must + be covered by a domino with its right neighbour or with the cell below it), and + `isTerm_iff_isTermB` proves it correct. The data check transfers a kernel-checked + `List.filter` over `0, …, 131` to `Nat.nth` (`map_nth_eq_of_filter`). +* *The conjecture.* "Odd parts appear as many times in even as in odd positions": with + positions `1, …, m` of `(y_1, …, y_m)`, the number of `i` with `i` even and `y_i` odd equals + the number of `i` with `i` odd and `y_i` odd (`OddPartsBalanced`). The entry's Mathematica and + Maple programs list the parts in increasing order instead. Reversing a list of length `m` maps + position `i` to `m + 1 - i`, which either keeps every parity or swaps all of them, so the + condition is the same for both orders. `b n = Nat.nth IsConjTerm (n - 1)` is the increasing + sequence of Heinz numbers of such partitions. The conjecture "this sequence is the Heinz numbers + of [such] partitions" is read as `a n = b n` for every `n ≥ 1`. Both sets of terms are infinite + (e.g. they contain `3 ^ e`, the Heinz number of `(2, 2, …, 2)`), so this is equivalent to + `IsTerm k ↔ IsConjTerm k` for every `k`. +-/ + +namespace Math0.Statements.A300789 + +/-! ### Definitions -/ + +/-- The parts of the integer partition with Heinz number `k`, in weakly decreasing order: the +prime indices `π(p)` of the prime factors `p` of `k`, with multiplicity (`prime(π(p)) = p`). -/ +def parts (k : ℕ) : List ℕ := (k.primeFactorsList.map Nat.primeCounting).reverse + +/-- The Young diagram of the partition `y = (y_1, …, y_m)` (parts in weakly decreasing order): +the cells `(i, j)` (0-indexed) with `i < m` and `j < y_{i+1}`. -/ +def youngDiagram (y : List ℕ) : Set (ℕ × ℕ) := + {c | c.1 < y.length ∧ c.2 < y.getD c.1 0} + +/-- A domino: two edge-adjacent cells, vertical `{(i, j), (i + 1, j)}` or horizontal +`{(i, j), (i, j + 1)}`. -/ +def IsDomino (d : Set (ℕ × ℕ)) : Prop := + ∃ i j : ℕ, d = {(i, j), (i + 1, j)} ∨ d = {(i, j), (i, j + 1)} + +/-- `S` can be tiled by dominoes: it is the union of a family of pairwise disjoint dominoes. -/ +def DominoTileable (S : Set (ℕ × ℕ)) : Prop := + ∃ D : Set (Set (ℕ × ℕ)), (∀ d ∈ D, IsDomino d) ∧ D.PairwiseDisjoint id ∧ ⋃₀ D = S + +/-- `k` is a term of A300789: `k ≥ 1` is the Heinz number of an integer partition whose Young +diagram can be tiled by dominoes. -/ +def IsTerm (k : ℕ) : Prop := 0 < k ∧ DominoTileable (youngDiagram (parts k)) + +/-! ### A decision procedure for domino tileability -/ + +/-- Strict row-major (lexicographic) order on cells. -/ +def LexLt (a b : ℕ × ℕ) : Prop := a.1 < b.1 ∨ (a.1 = b.1 ∧ a.2 < b.2) + +/-- Search for a domino tiling of the cells of `l`, which are assumed to be listed in strictly +increasing row-major order. The first cell `c` must be covered by a domino with its right +neighbour or with the cell below it. `fuel ≥ l.length` only makes the recursion structural. -/ +def tileL : ℕ → List (ℕ × ℕ) → Bool + | _, [] => true + | 0, _ :: _ => false + | fuel + 1, c :: rest => + (decide ((c.1, c.2 + 1) ∈ rest) && tileL fuel (rest.erase (c.1, c.2 + 1))) || + (decide ((c.1 + 1, c.2) ∈ rest) && tileL fuel (rest.erase (c.1 + 1, c.2))) + +/-- The cells of the Young diagram of `y`, row by row (row-major order). -/ +def cellsList (y : List ℕ) : List (ℕ × ℕ) := + (List.range y.length).flatMap fun i => (List.range (y.getD i 0)).map fun j => (i, j) + +/-- Boolean version of `IsTerm` (see `isTerm_iff_isTermB`). -/ +def isTermB (k : ℕ) : Bool := + decide (0 < k) && tileL (cellsList (parts k)).length (cellsList (parts k)) + +theorem tileable_empty : DominoTileable ∅ := + ⟨∅, by simp, Set.pairwiseDisjoint_empty, Set.sUnion_empty⟩ + +theorem tileable_of_diff {S d : Set (ℕ × ℕ)} (hd : IsDomino d) (hdS : d ⊆ S) + (h : DominoTileable (S \ d)) : DominoTileable S := by + obtain ⟨D, hD, hdisj, hU⟩ := h + refine ⟨insert d D, ?_, ?_, ?_⟩ + · rintro e (rfl | he) + exacts [hd, hD e he] + · refine hdisj.insert fun e he _ => ?_ + have hsub : e ⊆ S \ d := hU ▸ Set.subset_sUnion_of_mem he + exact Set.disjoint_left.2 fun x hx hx' => (hsub hx').2 hx + · rw [Set.sUnion_insert, hU, Set.union_sdiff_cancel hdS] + +theorem exists_domino_of_tileable {S : Set (ℕ × ℕ)} (h : DominoTileable S) {c : ℕ × ℕ} + (hc : c ∈ S) : ∃ d, IsDomino d ∧ c ∈ d ∧ d ⊆ S ∧ DominoTileable (S \ d) := by + obtain ⟨D, hD, hdisj, rfl⟩ := h + obtain ⟨d, hdD, hcd⟩ := hc + refine ⟨d, hD d hdD, hcd, Set.subset_sUnion_of_mem hdD, D \ {d}, fun e he => hD e he.1, + hdisj.subset Set.sdiff_subset, ?_⟩ + ext x + simp only [Set.mem_sUnion, Set.mem_sdiff, Set.mem_singleton_iff] + constructor + · rintro ⟨e, ⟨heD, hne⟩, hxe⟩ + exact ⟨⟨e, heD, hxe⟩, fun hxd => Set.disjoint_left.1 (hdisj heD hdD hne) hxe hxd⟩ + · rintro ⟨⟨e, heD, hxe⟩, hxd⟩ + exact ⟨e, ⟨heD, fun h => hxd (h ▸ hxe)⟩, hxe⟩ + +/-- A domino containing the row-major first cell `c` of `S` and contained in `S` is +`{c, c + (0, 1)}` or `{c, c + (1, 0)}`. -/ +theorem domino_at_min {S : Set (ℕ × ℕ)} {c : ℕ × ℕ} (hmin : ∀ x ∈ S, x ≠ c → LexLt c x) + {d : Set (ℕ × ℕ)} (hd : IsDomino d) (hcd : c ∈ d) (hdS : d ⊆ S) : + d = {c, (c.1, c.2 + 1)} ∨ d = {c, (c.1 + 1, c.2)} := by + obtain ⟨i, j, rfl | rfl⟩ := hd + · simp only [Set.mem_insert_iff, Set.mem_singleton_iff] at hcd + rcases hcd with rfl | rfl + · exact Or.inr rfl + · exfalso + have := hmin (i, j) (hdS (by simp)) (by simp) + simp [LexLt] at this + · simp only [Set.mem_insert_iff, Set.mem_singleton_iff] at hcd + rcases hcd with rfl | rfl + · exact Or.inl rfl + · exfalso + have := hmin (i, j) (hdS (by simp)) (by simp) + simp [LexLt] at this + +theorem LexLt.ne {a b : ℕ × ℕ} (h : LexLt a b) : a ≠ b := by + rintro rfl + rcases h with h | ⟨-, h⟩ <;> exact lt_irrefl _ h + +theorem tileL_iff : ∀ (fuel : ℕ) (l : List (ℕ × ℕ)), l.Pairwise LexLt → l.length ≤ fuel → + (tileL fuel l = true ↔ DominoTileable {x | x ∈ l}) + | _, [], _, _ => by simp [tileL, tileable_empty] + | 0, _ :: _, _, h => by simp at h + | fuel + 1, c :: rest, hl, hlen => by + have hcmin : ∀ x ∈ rest, LexLt c x := (List.pairwise_cons.1 hl).1 + have hrest : rest.Pairwise LexLt := (List.pairwise_cons.1 hl).2 + have hnd : rest.Nodup := hrest.imp LexLt.ne + have hcnot : c ∉ rest := fun h => (hcmin c h).ne rfl + have hset : ∀ x ∈ rest, {y | y ∈ rest.erase x} = {y | y ∈ c :: rest} \ {c, x} := by + intro x _ + ext y + simp only [Set.mem_ofPred_eq, hnd.mem_erase_iff, Set.mem_sdiff, List.mem_cons, + Set.mem_insert_iff, Set.mem_singleton_iff] + constructor + · rintro ⟨hyx, hy⟩ + exact ⟨Or.inr hy, fun h => h.elim (fun h => hcnot (h ▸ hy)) hyx⟩ + · rintro ⟨hy, hn⟩ + exact ⟨fun h => hn (Or.inr h), hy.resolve_left fun h => hn (Or.inl h)⟩ + have key : ∀ x ∈ rest, (tileL fuel (rest.erase x) = true ↔ + DominoTileable ({y | y ∈ c :: rest} \ {c, x})) := by + intro x hx + rw [← hset x hx] + refine tileL_iff fuel _ (hrest.sublist List.erase_sublist) ?_ + rw [List.length_erase_of_mem hx] + simp only [List.length_cons] at hlen + omega + have hsub : ∀ x ∈ rest, ({c, x} : Set (ℕ × ℕ)) ⊆ {y | y ∈ c :: rest} := by + intro x hx y hy + simp only [Set.mem_insert_iff, Set.mem_singleton_iff] at hy + rcases hy with rfl | rfl + · exact List.mem_cons_self + · exact List.mem_cons_of_mem _ hx + have hmin : ∀ x ∈ {y | y ∈ c :: rest}, x ≠ c → LexLt c x := by + intro x hx hxc + exact hcmin x ((List.mem_cons.1 hx).resolve_left hxc) + have hmem : ∀ x, ({c, x} : Set (ℕ × ℕ)) ⊆ {y | y ∈ c :: rest} → x ≠ c → x ∈ rest := by + intro x h hxc + have : x ∈ c :: rest := h (by simp) + exact (List.mem_cons.1 this).resolve_left hxc + simp only [tileL, Bool.or_eq_true, Bool.and_eq_true, decide_eq_true_eq] + constructor + · rintro (⟨hx, ht⟩ | ⟨hx, ht⟩) + · exact tileable_of_diff ⟨c.1, c.2, Or.inr rfl⟩ (hsub _ hx) ((key _ hx).1 ht) + · exact tileable_of_diff ⟨c.1, c.2, Or.inl rfl⟩ (hsub _ hx) ((key _ hx).1 ht) + · intro h + obtain ⟨d, hd, hcd, hdS, hdt⟩ := exists_domino_of_tileable h List.mem_cons_self + rcases domino_at_min hmin hd hcd hdS with rfl | rfl + · have hx := hmem _ hdS (by simp [Prod.ext_iff]) + exact Or.inl ⟨hx, (key _ hx).2 hdt⟩ + · have hx := hmem _ hdS (by simp [Prod.ext_iff]) + exact Or.inr ⟨hx, (key _ hx).2 hdt⟩ + +theorem mem_cellsList {y : List ℕ} {c : ℕ × ℕ} : c ∈ cellsList y ↔ c ∈ youngDiagram y := by + obtain ⟨i, j⟩ := c + simp only [cellsList, List.mem_flatMap, List.mem_range, List.mem_map, Prod.mk.injEq, + youngDiagram, Set.mem_ofPred_eq] + constructor + · rintro ⟨i', hi', j', hj', rfl, rfl⟩ + exact ⟨hi', hj'⟩ + · rintro ⟨hi, hj⟩ + exact ⟨i, hi, j, hj, rfl, rfl⟩ + +theorem pairwise_cellsList (y : List ℕ) : (cellsList y).Pairwise LexLt := by + unfold cellsList + rw [List.pairwise_flatMap] + refine ⟨fun i _ => ?_, ?_⟩ + · rw [List.pairwise_map] + exact List.pairwise_lt_range.imp fun h => Or.inr ⟨rfl, h⟩ + · refine List.pairwise_lt_range.imp fun h x hx z hz => ?_ + simp only [List.mem_map, List.mem_range] at hx hz + obtain ⟨_, _, rfl⟩ := hx + obtain ⟨_, _, rfl⟩ := hz + exact Or.inl h + +theorem setOf_mem_cellsList (y : List ℕ) : {x | x ∈ cellsList y} = youngDiagram y := + Set.ext fun _ => mem_cellsList + +theorem isTerm_iff_isTermB (k : ℕ) : IsTerm k ↔ isTermB k = true := by + rw [IsTerm, isTermB, Bool.and_eq_true, decide_eq_true_eq, + tileL_iff _ _ (pairwise_cellsList _) le_rfl, setOf_mem_cellsList] + +instance : DecidablePred IsTerm := fun k => decidable_of_iff _ (isTerm_iff_isTermB k).symm + +/-! ### The sequence and the conjecture -/ + +/-- A300789: the `n`-th Heinz number (offset `1`, in increasing order) of an integer partition +whose Young diagram can be tiled by dominoes. -/ +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) + +/-- The partition `y = (y_1, …, y_m)` has as many odd parts in even positions as in odd +positions: `#{i ∈ [1, m] | i even, y_i odd} = #{i ∈ [1, m] | i odd, y_i odd}` (here `i` is +0-indexed, so position `i + 1`). -/ +def OddPartsBalanced (y : List ℕ) : Prop := + ((Finset.range y.length).filter fun i => Even (i + 1) ∧ Odd (y.getD i 0)).card = + ((Finset.range y.length).filter fun i => Odd (i + 1) ∧ Odd (y.getD i 0)).card + +/-- `k ≥ 1` is the Heinz number of a partition whose odd parts appear as many times in even as +in odd positions. -/ +def IsConjTerm (k : ℕ) : Prop := 0 < k ∧ OddPartsBalanced (parts k) + +instance : DecidablePred IsConjTerm := fun k => by + unfold IsConjTerm OddPartsBalanced + infer_instance + +/-- The `n`-th Heinz number (offset `1`, in increasing order) of a partition whose odd parts +appear as many times in even as in odd positions. -/ +noncomputable def b (n : ℕ) : ℕ := Nat.nth IsConjTerm (n - 1) + +/-! ### Sanity checks -/ + +/-- The elements `< N` satisfying `p`, in increasing order, are `nth p 0, nth p 1, …`. -/ +theorem filter_range_eq (p : ℕ → Prop) [DecidablePred p] (N : ℕ) : + (List.range N).filter (fun k => decide (p k)) = + (List.range (Nat.count p N)).map (Nat.nth p) := by + induction N with + | zero => simp + | succ N ih => + rw [List.range_succ, List.filter_append, ih, Nat.count_succ] + by_cases h : p N + · simp [h, List.range_succ, Nat.nth_count h] + · simp [h] + +theorem map_nth_eq_of_filter {p : ℕ → Prop} [DecidablePred p] {N K : ℕ} {L : List ℕ} + (h : (List.range N).filter (fun k => decide (p k)) = L) (hK : L.length = K) : + (List.range K).map (Nat.nth p) = L := by + rw [filter_range_eq] at h + subst h + simp only [List.length_map, List.length_range] at hK + rw [hK] + +/-- The entry's example: the partitions with Heinz numbers `1, 3, 4, …, 28` (the first fifteen +terms) are `(), (2), (11), (4), (22), (31), (211), (6), (1111), (8), (42), (51), (33), (222), +(411)` (kernel-checked). -/ +theorem parts_example : + [1, 3, 4, 7, 9, 10, 12, 13, 16, 19, 21, 22, 25, 27, 28].map parts = + [[], [2], [1, 1], [4], [2, 2], [3, 1], [2, 1, 1], [6], [1, 1, 1, 1], [8], [4, 2], [5, 1], + [3, 3], [2, 2, 2], [4, 1, 1]] := by + decide +kernel + +/-- The definition reproduces all 63 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 63).map (fun i => a (i + 1)) = + [1, 3, 4, 7, 9, 10, 12, 13, 16, 19, 21, 22, 25, 27, 28, 29, 34, 36, 37, 39, 40, 43, 46, 48, + 49, 52, 53, 55, 57, 61, 62, 63, 64, 70, 71, 75, 76, 79, 81, 82, 84, 85, 87, 88, 89, 90, 91, + 94, 100, 101, 107, 108, 111, 112, 113, 115, 116, 117, 118, 121, 129, 130, 131] := by + have : (fun i => a (i + 1)) = Nat.nth IsTerm := funext fun i => by simp [a] + rw [this] + exact map_nth_eq_of_filter (N := 132) (by decide +kernel) rfl + +/-- The conjectured description also reproduces the 63 listed terms (as the entry's programs, +which use it, do; kernel-checked). -/ +theorem b_data : (List.range 63).map (fun i => b (i + 1)) = + [1, 3, 4, 7, 9, 10, 12, 13, 16, 19, 21, 22, 25, 27, 28, 29, 34, 36, 37, 39, 40, 43, 46, 48, + 49, 52, 53, 55, 57, 61, 62, 63, 64, 70, 71, 75, 76, 79, 81, 82, 84, 85, 87, 88, 89, 90, 91, + 94, 100, 101, 107, 108, 111, 112, 113, 115, 116, 117, 118, 121, 129, 130, 131] := by + have : (fun i => b (i + 1)) = Nat.nth IsConjTerm := funext fun i => by simp [b] + rw [this] + exact map_nth_eq_of_filter (N := 132) (by decide +kernel) rfl + +/-- Conjecture (Wiseman, A300789): the sequence of Heinz numbers of integer partitions whose +Young diagram can be tiled by dominoes is the sequence of Heinz numbers of integer partitions in +which the odd parts appear as many times in even as in odd positions, i.e. `a(n) = b(n)` for +every `n ≥ 1`. -/ +def statement : Prop := ∀ n : ℕ, 1 ≤ n → a n = b n + +end Math0.Statements.A300789 diff --git a/lean/Math0/Statements/OEIS/A308107.lean b/lean/Math0/Statements/OEIS/A308107.lean new file mode 100644 index 0000000..f453d3d --- /dev/null +++ b/lean/Math0/Statements/OEIS/A308107.lean @@ -0,0 +1,143 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A308107: sum of smallest sides of scalene integer triangles with perimeter `n` + +Source: https://oeis.org/A308107, _Colin Barker_, May 13 2019 (FORMULA section). Verbatim: +> Conjectures from _Colin Barker_, May 13 2019: (Start) +> G.f.: x^9*(2 + 2*x + 2*x^2 + x^3) / ((1 - x)^4*(1 + x)^3*(1 + x^2)^2*(1 + x + x^2)^2). +> a(n) = -a(n-1) + 2*a(n-3) + 4*a(n-4) + 2*a(n-5) - a(n-6) - 5*a(n-7) - 5*a(n-8) - a(n-9) +> + 2*a(n-10) + 4*a(n-11) + 2*a(n-12) - a(n-14) - a(n-15) for n>15. +> (End) + +The entry (_Wesley Ivan Hurt_, May 13 2019, offset `1`) is "Sum of the smallest side lengths of +all integer-sided scalene triangles with perimeter n." + +## Encoding + +* *Triangles.* An integer-sided scalene triangle has three pairwise distinct positive integer + sides; listing them in increasing order `k < i < j` identifies each triangle with exactly one + triple, and its smallest side is `k`. For `k < i < j` the triangle inequalities reduce to + `j < k + i` (this also forces `k ≥ 1`, since `k = 0` would give `j < i`). So + `a n = ∑ k` over the triples `(k, i, j)` with `k < i < j < k + i` and `k + i + j = n`. + All sides are `≤ n`, so the triples are searched in `{0, …, n}³`; `a` is computable. +* *Offset.* The entry has offset `1`. The definition also gives `a 0 = 0` (empty sum), which is + harmless: the claimed g.f. has zero constant term, so `∑_{n ≥ 1} a(n) xⁿ = ∑_{n ≥ 0} a(n) xⁿ`. +* *Data.* `a` sums over `(n+1)³` triples, which is too slow for the kernel, so `aFast` sums + over the pairs `(k, i)` with the third side `j = n - (k + i)`; `a_eq_aFast` proves + `a n = aFast n` for every `n`. `a_data` checks all 61 listed terms `a(1), …, a(61)` in the + kernel. As a separate transcription check (not about `a`), `recurrence_data` checks that the + 61 listed terms satisfy the stated recurrence for `16 ≤ n ≤ 61`, and `den_eq` shows that the + stated denominator multiplies out to the recurrence's characteristic polynomial + `1 + x - 2x³ - 4x⁴ - 2x⁵ + x⁶ + 5x⁷ + 5x⁸ + x⁹ - 2x¹⁰ - 4x¹¹ - 2x¹² + x¹⁴ + x¹⁵`. +* *The conjecture* (`statement`) is the conjunction of the two stated formulas: + 1. the generating function: `∑ a(n) xⁿ` equals the stated rational function, as formal power + series over `ℚ`, using Mathlib's inverse of a power series; the denominator has constant + coefficient `1 ≠ 0`, so this is the honest quotient (`genFun_iff` restates it as + `A(x) · D(x) = x⁹(2 + 2x + 2x² + x³)`); + 2. the order-15 recurrence for every `n > 15` (as stated; then all indices `n - 1, …, n - 15` + are `≥ 1`, inside the entry's domain), in `ℤ`. +-/ + +namespace Math0.Statements.A308107 + +open PowerSeries + +/-- A308107: the sum of the smallest sides `k` over all integer-sided scalene triangles with +perimeter `n`, i.e. over all triples `k < i < j` with `j < k + i` and `k + i + j = n`. -/ +def a (n : ℕ) : ℕ := + ∑ t ∈ (Finset.range (n + 1) ×ˢ Finset.range (n + 1) ×ˢ Finset.range (n + 1)).filter + (fun t : ℕ × ℕ × ℕ => t.1 < t.2.1 ∧ t.2.1 < t.2.2 ∧ t.2.2 < t.1 + t.2.1 ∧ + t.1 + t.2.1 + t.2.2 = n), + t.1 + +/-- A faster evaluator: sum over the two smaller sides `k, i`; the largest is `n - (k + i)`. -/ +def aFast (n : ℕ) : ℕ := + ∑ k ∈ Finset.range (n + 1), ∑ i ∈ Finset.range (n + 1), + if k < i ∧ k + i ≤ n ∧ i < n - (k + i) ∧ n - (k + i) < k + i then k else 0 + +/-- The fast evaluator computes `a`. -/ +theorem a_eq_aFast (n : ℕ) : a n = aFast n := by + unfold a aFast + rw [Finset.sum_filter, Finset.sum_product] + refine Finset.sum_congr rfl fun k _ => ?_ + rw [Finset.sum_product] + refine Finset.sum_congr rfl fun i _ => ?_ + have h : ∀ j : ℕ, + (if k < i ∧ i < j ∧ j < k + i ∧ k + i + j = n then k else 0) = + if n - (k + i) = j then + (if k < i ∧ k + i ≤ n ∧ i < n - (k + i) ∧ n - (k + i) < k + i then k else 0) + else 0 := by + intro j + split_ifs <;> omega + simp only [h] + rw [Finset.sum_ite_eq] + simp only [Finset.mem_range] + rw [if_pos (by omega)] + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all 61 listed +terms `a(1), …, a(61)`. -/ +theorem a_data : (List.range 61).map (fun i => a (i + 1)) = + [0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 3, 5, 3, 9, 7, 13, 12, 18, 17, 29, 23, 35, 36, 48, 43, 63, + 58, 78, 75, 95, 92, 122, 111, 141, 141, 171, 162, 204, 195, 237, 231, 273, 267, 323, 306, + 362, 360, 416, 402, 474, 460, 532, 522, 594, 584, 674, 650, 740, 735, 825] := by + simp only [a_eq_aFast] + decide +kernel + +/-! ### The conjecture -/ + +/-- The 61 terms listed in the entry, `a(1), …, a(61)`, preceded by `a(0) = 0`. -/ +def listed : List ℤ := + [0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 3, 5, 3, 9, 7, 13, 12, 18, 17, 29, 23, 35, 36, 48, 43, 63, + 58, 78, 75, 95, 92, 122, 111, 141, 141, 171, 162, 204, 195, 237, 231, 273, 267, 323, 306, + 362, 360, 416, 402, 474, 460, 532, 522, 594, 584, 674, 650, 740, 735, 825] + +/-- Transcription check (not about `a`): the listed terms satisfy the conjectured recurrence for +`16 ≤ n ≤ 61`. -/ +theorem recurrence_data : ∀ n ∈ List.range' 16 46, + listed.getD n 0 = -listed.getD (n - 1) 0 + 2 * listed.getD (n - 3) 0 + + 4 * listed.getD (n - 4) 0 + 2 * listed.getD (n - 5) 0 - listed.getD (n - 6) 0 - + 5 * listed.getD (n - 7) 0 - 5 * listed.getD (n - 8) 0 - listed.getD (n - 9) 0 + + 2 * listed.getD (n - 10) 0 + 4 * listed.getD (n - 11) 0 + 2 * listed.getD (n - 12) 0 - + listed.getD (n - 14) 0 - listed.getD (n - 15) 0 := by + decide + +/-- The conjectured denominator `(1 - x)^4 (1 + x)^3 (1 + x^2)^2 (1 + x + x^2)^2`. -/ +noncomputable def den : PowerSeries ℚ := + (1 - X) ^ 4 * (1 + X) ^ 3 * (1 + X ^ 2) ^ 2 * (1 + X + X ^ 2) ^ 2 + +/-- Transcription check: the denominator is the characteristic polynomial of the recurrence. -/ +theorem den_eq : den = 1 + X - 2 * X ^ 3 - 4 * X ^ 4 - 2 * X ^ 5 + X ^ 6 + 5 * X ^ 7 + + 5 * X ^ 8 + X ^ 9 - 2 * X ^ 10 - 4 * X ^ 11 - 2 * X ^ 12 + X ^ 14 + X ^ 15 := by + unfold den + ring + +/-- Barker's conjecture (both formulas): +`∑ a(n) xⁿ = x^9 (2 + 2x + 2x^2 + x^3) / ((1 - x)^4 (1 + x)^3 (1 + x^2)^2 (1 + x + x^2)^2)`, and +`a(n) = -a(n-1) + 2a(n-3) + 4a(n-4) + 2a(n-5) - a(n-6) - 5a(n-7) - 5a(n-8) - a(n-9) + 2a(n-10) ++ 4a(n-11) + 2a(n-12) - a(n-14) - a(n-15)` for all `n > 15`. -/ +def statement : Prop := + (PowerSeries.mk (fun n => (a n : ℚ)) = + X ^ 9 * (2 + 2 * X + 2 * X ^ 2 + X ^ 3) * + ((1 - X) ^ 4 * (1 + X) ^ 3 * (1 + X ^ 2) ^ 2 * (1 + X + X ^ 2) ^ 2)⁻¹) ∧ + (∀ n : ℕ, 15 < n → + (a n : ℤ) = -(a (n - 1) : ℤ) + 2 * (a (n - 3) : ℤ) + 4 * (a (n - 4) : ℤ) + + 2 * (a (n - 5) : ℤ) - (a (n - 6) : ℤ) - 5 * (a (n - 7) : ℤ) - 5 * (a (n - 8) : ℤ) - + (a (n - 9) : ℤ) + 2 * (a (n - 10) : ℤ) + 4 * (a (n - 11) : ℤ) + 2 * (a (n - 12) : ℤ) - + (a (n - 14) : ℤ) - (a (n - 15) : ℤ)) + +theorem constantCoeff_den : PowerSeries.constantCoeff den ≠ 0 := by + simp [den] + +/-- The generating-function clause, with the denominator multiplied out. -/ +theorem genFun_iff : + PowerSeries.mk (fun n => (a n : ℚ)) = + X ^ 9 * (2 + 2 * X + 2 * X ^ 2 + X ^ 3) * + ((1 - X) ^ 4 * (1 + X) ^ 3 * (1 + X ^ 2) ^ 2 * (1 + X + X ^ 2) ^ 2)⁻¹ ↔ + PowerSeries.mk (fun n => (a n : ℚ)) * den = X ^ 9 * (2 + 2 * X + 2 * X ^ 2 + X ^ 3) := + PowerSeries.eq_mul_inv_iff_mul_eq constantCoeff_den + +end Math0.Statements.A308107 diff --git a/lean/Math0/Statements/OEIS/A308121.lean b/lean/Math0/Statements/OEIS/A308121.lean new file mode 100644 index 0000000..5ce31a0 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A308121.lean @@ -0,0 +1,91 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A308121: row 2n is row n with its halves swapped, for odd n + +Source: https://oeis.org/A308121, Charlie Neder, Jun 05 2019 (COMMENTS section). Verbatim: +> Conjecture: If n is odd, then row 2n can be obtained from row n by interchanging the first and +> second halves. + +The entry (Jamie Morken, May 13 2019; offset `1`, keywords `sign,tabf`) is the "Irregular +triangle read by rows: T(n,k) = A109395(n)*k-A076512(n)*A038566(n,k)", with the comment "Row n has +length A000010(n)." + +## Encoding + +* `totatives n` is row `n` of A038566 ("triangle in which n-th row gives phi(n) numbers between 1 + and n that are relatively prime to n"): the numbers `r` with `1 ≤ r ≤ n` and `gcd(r, n) = 1`, in + increasing order. For `n = 1` this is `[1]`, matching A038566's first row; for `n ≥ 2` it is the + list of totatives in `[1, n-1]`. +* `A109395 n` is the denominator and `A076512 n` the numerator of the reduced fraction + `phi(n)/n`, computed literally as `Rat.den` and `Rat.num` of `(Nat.totient n : ℚ) / n` + (as in the names of A109395 and A076512). +* `T n k = A109395(n) * k - A076512(n) * A038566(n, k)` in `ℤ` (the sequence is signed), for + `n ≥ 1` and `1 ≤ k ≤ phi(n)`; `A038566(n, k)` is the `k`-th entry of `totatives n` (1-based). +* `row n` is the list `[T(n,1), …, T(n, phi(n))]` (row `n` has length `A000010(n)`). +* `a_data` checks, in the kernel, that rows `1..15` concatenated are exactly the 72 listed terms + (`%S`, `%T`, `%U`), i.e. `a(1), …, a(72)` of the flattened sequence. `T_210_2` checks the + worked example `T(210,2) = -18` from the entry. +* *The conjecture.* "Row 2n can be obtained from row n by interchanging the first and second + halves" is encoded as: there are lists `A`, `B` of equal length with `row n = A ++ B` (the first + and second halves of row `n`) and `row (2n) = B ++ A`. +* *Reading choice (range of `n`).* For `n = 1`, row 1 is `[0]`, which has odd length 1 and so has + no first and second halves; the conjecture is only meaningful when row `n` has halves. For odd + `n ≥ 3`, `phi(n)` is even. We therefore quantify over odd `n` with `n > 1`. (Under any reading + that included `n = 1`, the claim would be false there: row 2 is `[1]`, not a rearrangement of + `[0]`.) `statement_check_7` and `statement_check_15` illustrate the claim for `n = 7` and + `n = 15` (sanity checks of the transcription, not a proof). +-/ + +namespace Math0.Statements.A308121 + +/-- Row `n` of A038566: the numbers `r` with `1 ≤ r ≤ n` and `gcd(r, n) = 1`, increasing. -/ +def totatives (n : ℕ) : List ℕ := + (List.range' 1 n).filter (fun r => Nat.Coprime r n) + +/-- A109395: the denominator of `phi(n)/n`. -/ +def A109395 (n : ℕ) : ℕ := ((Nat.totient n : ℚ) / n).den + +/-- A076512: the numerator of `phi(n)/n` (as an integer). -/ +def A076512 (n : ℕ) : ℤ := ((Nat.totient n : ℚ) / n).num + +/-- `T(n,k) = A109395(n)*k - A076512(n)*A038566(n,k)`, where `A038566(n,k)` is the `k`-th +(1-based) number in `[1, n]` coprime to `n`; meaningful for `n ≥ 1`, `1 ≤ k ≤ phi(n)`. -/ +def T (n k : ℕ) : ℤ := + (A109395 n : ℤ) * k - A076512 n * ((totatives n).getD (k - 1) 0 : ℕ) + +/-- Row `n` of the triangle: `[T(n,1), …, T(n, phi(n))]`. -/ +def row (n : ℕ) : List ℤ := + (List.range (Nat.totient n)).map (fun i => T n (i + 1)) + +/-- The definition reproduces the 72 listed terms of OEIS (rows `1..15`, kernel-checked). -/ +theorem a_data : (List.range 15).flatMap (fun i => row (i + 1)) = + [0, 1, 1, 2, 1, 1, 1, 2, 3, 4, 2, 1, 1, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 3, 4, + 1, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 2, 1, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 4, 5, 6, 1, 2, 3, 7, 14, 13, 4, 11, 2, 1, 8] := by + decide +kernel + +/-- The worked example of the entry: `T(210,2) = 35*2 - 8*11 = -18`. -/ +theorem T_210_2 : T 210 2 = -18 := by + decide +kernel + +/-- Charlie Neder's conjecture: for odd `n > 1` (so that row `n` has two halves), row `2n` is row +`n` with its first and second halves interchanged. -/ +def statement : Prop := + ∀ n : ℕ, Odd n → 1 < n → + ∃ A B : List ℤ, row n = A ++ B ∧ A.length = B.length ∧ row (2 * n) = B ++ A + +/-- Sanity check for `n = 7`: row 7 is `[1,2,3,4,5,6]` and row 14 is `[4,5,6,1,2,3]`. -/ +theorem statement_check_7 : + row 7 = [1, 2, 3] ++ [4, 5, 6] ∧ row 14 = [4, 5, 6] ++ [1, 2, 3] := by + decide +kernel + +/-- Sanity check for `n = 15`: row 15 is `[7,14,13,4,11,2,1,8]`, row 30 is `[11,2,1,8,7,14,13,4]`. -/ +theorem statement_check_15 : + row 15 = [7, 14, 13, 4] ++ [11, 2, 1, 8] ∧ row 30 = [11, 2, 1, 8] ++ [7, 14, 13, 4] := by + decide +kernel + +end Math0.Statements.A308121 diff --git a/lean/Math0/Statements/OEIS/A308222.lean b/lean/Math0/Statements/OEIS/A308222.lean new file mode 100644 index 0000000..26ed84e --- /dev/null +++ b/lean/Math0/Statements/OEIS/A308222.lean @@ -0,0 +1,521 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A308222: perimeters of primitive Heronian isosceles triangles + +Source: https://oeis.org/A308222, _Peter Kagey_, May 16 2019 (FORMULA section). Verbatim: +> a(n) = 2*A096033(n+2) (conjectured). + +The entry's name: "Numbers that are the perimeter of a primitive Heronian isosceles triangle." +Comment: "A primitive Heronian triangle is a triangle with integer sides and area, where the +side lengths do not share a common divisor." Offset `1`: `a(1) = 16`, from `(5, 5, 6)`. +A096033 is "Difference between leg and hypotenuse in primitive Pythagorean triangles", offset `1`: +`1, 2, 8, 9, 18, …`. + +## Encoding + +* *Triangles.* Sides are natural numbers `x, y, z` with the strict triangle inequalities + `x < y + z`, `y < x + z`, `z < x + y` (non-degenerate, so all sides are `≥ 1`). +* *Heronian.* The area is an integer `A`. By Heron's formula + `16 · area² = (x+y+z)(-x+y+z)(x-y+z)(x+y-z)` (`heron`, computed in `ℤ`), so this says + `16 A² = heron x y z` for some `A : ℕ` (`IsHeronian`). +* *Primitive.* `gcd(gcd(x, y), z) = 1` (`IsPrimitive`). *Isosceles.* Two sides are equal + (`IsIsosceles`). An equilateral triangle counts too, but none is Heronian. +* *The sequence.* `IsPerimeter P`: some such triangle has `x + y + z = P`. The entry lists each + perimeter once, in increasing order (e.g. `50` comes from both `(13,13,24)` and `(16,17,17)`), + so `a n = Nat.nth IsPerimeter (n - 1)` is the `n`-th smallest perimeter (offset `1`). +* *Deciding `IsPerimeter`.* `Nat.nth` is noncomputable, so `IsPerimeter` is made decidable by + `perimB`, a bounded search proved equivalent to it (`perimB_iff`). A triangle is written with + legs `s, s` and base `b` (`isPerimeter_iff`). Its base is even and its legs are odd + (`IsoOK.base_even`, `IsoOK.leg_odd`). So `P = 2m`, `b = 2(m - s)`, and the area is an integer + iff `m (2s - m)` is a square (`isoOK_iff_legOK`). The search runs over the odd `s` with + `m/2 < s < m`. Squares are recognized by a quadratic-residue filter and a certified integer + square root (`sqB_iff`). These are elementary rewritings of the definition, used only to + evaluate it. +* *A096033.* `IsLegHypDiff d`: there are legs `x, y ≥ 1` with `gcd(x, y) = 1` and a hypotenuse + `z` with `x² + y² = z²` and `z = x + d` (`x` may be either leg). `A096033 n` is the `n`-th + smallest such `d` (offset `1`). For decidability, `isLegHypDiff_iff` proves the + characterization stated in A096033 itself (odd squares and the numbers `2 j²`, `j ≥ 1`), using + Mathlib's classification of primitive Pythagorean triples. This concerns only A096033 and does + not touch the conjecture. +* *Data.* `a_data` checks all 46 listed terms of A308222 (`a(1..46)`, up to `3136`) in the + kernel. The search below `3137` is split into 7 separate kernel checks (`chunk_1`, …, + `chunk_7`) to bound memory. `A096033_data` checks the 52 listed terms of A096033. +* *The conjecture.* `statement`: for every `n ≥ 1`, `a(n) = 2 · A096033(n + 2)`. +-/ + +namespace Math0.Statements.A308222 + +/-! ### Primitive Heronian isosceles triangles -/ + +/-- Heron's product `(x+y+z)(-x+y+z)(x-y+z)(x+y-z)`. It equals `16 · area²` for the triangle with +sides `x, y, z`. -/ +def heron (x y z : ℤ) : ℤ := (x + y + z) * (-x + y + z) * (x - y + z) * (x + y - z) + +/-- `x, y, z` are the sides of a Heronian triangle: a non-degenerate triangle (strict triangle +inequalities) with integer sides whose area is an integer `A`, i.e. `16 A² = heron x y z`. -/ +def IsHeronian (x y z : ℕ) : Prop := + x < y + z ∧ y < x + z ∧ z < x + y ∧ ∃ A : ℕ, 16 * (A : ℤ) ^ 2 = heron x y z + +/-- The side lengths `x, y, z` have no common divisor greater than `1`. -/ +def IsPrimitive (x y z : ℕ) : Prop := Nat.gcd (Nat.gcd x y) z = 1 + +/-- Two of the sides `x, y, z` are equal. -/ +def IsIsosceles (x y z : ℕ) : Prop := x = y ∨ y = z ∨ x = z + +/-- `P` is the perimeter of a primitive Heronian isosceles triangle. -/ +def IsPerimeter (P : ℕ) : Prop := + ∃ x y z : ℕ, IsHeronian x y z ∧ IsPrimitive x y z ∧ IsIsosceles x y z ∧ x + y + z = P + +/-- A308222 (offset `1`): the `n`-th smallest perimeter of a primitive Heronian isosceles +triangle. -/ +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsPerimeter (n - 1) + +/-! ### Deciding `IsPerimeter` -/ + +/-! The decision procedure uses only `Bool`-valued primitives (`Nat.blt`, `Nat.beq`, `cond`), +which keeps kernel evaluation cheap. -/ + +/-- Newton iteration for `⌊√n⌋` with fuel. It is only a guess, certified in `sqAt`. -/ +def sqrtIter : ℕ → ℕ → ℕ → ℕ + | 0, _, g => g + | fuel + 1, n, g => + bif Nat.blt ((g + n / g) / 2) g then sqrtIter fuel n ((g + n / g) / 2) else g + +/-- A guess for `⌊√n⌋`. -/ +def sqrtGuess (n : ℕ) : ℕ := sqrtIter 64 n (2 ^ (Nat.log2 n / 2 + 1)) + +/-- Decides whether `n` is a perfect square, given a guess `r` for `⌊√n⌋`: if +`r² ≤ n < (r+1)²` then `n` is a square iff `r² = n`; otherwise an exhaustive search. -/ +def sqAt (n r : ℕ) : Bool := + bif Nat.ble (r * r) n && Nat.blt n ((r + 1) * (r + 1)) then Nat.beq (r * r) n + else (List.range (n + 1)).any fun k => Nat.beq (k * k) n + +theorem sqAt_iff (n r : ℕ) : sqAt n r = true ↔ ∃ k, k * k = n := by + unfold sqAt + cases h : (Nat.ble (r * r) n && Nat.blt n ((r + 1) * (r + 1))) + · simp only [cond_false, List.any_eq_true, List.mem_range, Nat.beq_eq] + constructor + · rintro ⟨k, -, hk⟩ + exact ⟨k, hk⟩ + · rintro ⟨k, rfl⟩ + exact ⟨k, by have := Nat.le_mul_self k; omega, rfl⟩ + · simp only [Bool.and_eq_true, Nat.ble_eq, Nat.blt_eq] at h + simp only [cond_true, Nat.beq_eq] + constructor + · intro h' + exact ⟨r, h'⟩ + · rintro ⟨k, rfl⟩ + have h1 : r ≤ k := Nat.mul_self_le_mul_self_iff.1 h.1 + have h2 : k < r + 1 := Nat.mul_self_lt_mul_self_iff.1 h.2 + rw [show r = k by omega] + +/-- Bit number `n % m` of the mask `M` (used with `M` = the set of squares modulo `m`). -/ +def qr (M m n : ℕ) : Bool := Nat.beq ((M >>> (n % m)) % 2) 1 + +theorem qr_mul_self {M m : ℕ} (hm : 0 < m) (h : ∀ r < m, qr M m (r * r) = true) (k : ℕ) : + qr M m (k * k) = true := by + have := h (k % m) (Nat.mod_lt _ hm) + unfold qr at * + rwa [← Nat.mul_mod] at this + +/-- Decides whether `n` is a perfect square: a quick test that `n` is a square modulo `64`, +`63`, `65` and `11` (bit masks of the squares), then `sqAt`. -/ +def sqB (n : ℕ) : Bool := + qr 144680414395695635 64 n && qr 288872697407275667 63 n && qr 20863489977805260307 65 n && + qr 571 11 n && sqAt n (sqrtGuess n) + +theorem sqB_iff (n : ℕ) : sqB n = true ↔ ∃ k, k * k = n := by + constructor + · intro h + simp only [sqB, Bool.and_eq_true] at h + exact (sqAt_iff _ _).1 h.2 + · rintro ⟨k, rfl⟩ + simp only [sqB, Bool.and_eq_true] + refine ⟨⟨⟨⟨qr_mul_self (by norm_num) (by decide) k, qr_mul_self (by norm_num) (by decide) k⟩, + qr_mul_self (by norm_num) (by decide) k⟩, qr_mul_self (by norm_num) (by decide) k⟩, + (sqAt_iff _ _).2 ⟨k, rfl⟩⟩ + +/-- The triangle with legs `s, s` and base `b` is a primitive Heronian triangle (in `ℕ`). -/ +def IsoOK (s b : ℕ) : Prop := + 0 < b ∧ b < 2 * s ∧ Nat.gcd s b = 1 ∧ ∃ A : ℕ, 16 * A ^ 2 = (2 * s + b) * b * b * (2 * s - b) + +theorem heron_iso {s b : ℕ} (h : b < 2 * s) : + heron s s b = (((2 * s + b) * b * b * (2 * s - b) : ℕ) : ℤ) := by + unfold heron + push_cast [Nat.cast_sub h.le] + ring + +theorem isoOK_of {s b : ℕ} (hH : IsHeronian s s b) (hg : Nat.gcd s b = 1) : IsoOK s b := by + obtain ⟨h1, -, h3, A, hA⟩ := hH + refine ⟨by omega, by omega, hg, A, ?_⟩ + rw [heron_iso (by omega)] at hA + exact_mod_cast hA + +/-- Every primitive Heronian isosceles triangle can be written with legs `s, s` and base `b`. -/ +theorem isPerimeter_iff (P : ℕ) : IsPerimeter P ↔ ∃ s b, IsoOK s b ∧ 2 * s + b = P := by + constructor + · rintro ⟨x, y, z, hH, hp, hi, hP⟩ + rcases hi with rfl | rfl | rfl + · refine ⟨x, z, isoOK_of hH ?_, by omega⟩ + simpa [IsPrimitive] using hp + · refine ⟨y, x, isoOK_of ?_ ?_, by omega⟩ + · obtain ⟨h1, h2, h3, A, hA⟩ := hH + refine ⟨by omega, by omega, by omega, A, ?_⟩ + rw [hA]; unfold heron; ring + · have : Nat.gcd (Nat.gcd x y) y = Nat.gcd y x := by + rw [Nat.gcd_assoc, Nat.gcd_self, Nat.gcd_comm] + rw [← this]; exact hp + · refine ⟨x, y, isoOK_of ?_ ?_, by omega⟩ + · obtain ⟨h1, h2, h3, A, hA⟩ := hH + refine ⟨by omega, by omega, by omega, A, ?_⟩ + rw [hA]; unfold heron; ring + · have : Nat.gcd (Nat.gcd x y) x = Nat.gcd x y := by + rw [Nat.gcd_comm, ← Nat.gcd_assoc, Nat.gcd_self] + rw [← this]; exact hp + · rintro ⟨s, b, ⟨h0, h1, hg, A, hA⟩, hP⟩ + refine ⟨s, s, b, ⟨by omega, by omega, by omega, A, ?_⟩, by simpa [IsPrimitive] using hg, + Or.inl rfl, by omega⟩ + rw [heron_iso h1] + exact_mod_cast hA + +/-- The base of a Heronian isosceles triangle is even (otherwise `16 A²` would be odd). -/ +theorem IsoOK.base_even {s b : ℕ} (h : IsoOK s b) : b % 2 = 0 := by + obtain ⟨h0, h1, -, A, hA⟩ := h + by_contra hb + have e1 : ¬ Even (2 * s + b) := by rw [Nat.even_iff]; omega + have e2 : ¬ Even (2 * s - b) := by rw [Nat.even_iff]; omega + have e3 : ¬ Even b := by rw [Nat.even_iff]; omega + have : Even ((2 * s + b) * b * b * (2 * s - b)) := hA ▸ ⟨8 * A ^ 2, by ring⟩ + simp [Nat.even_mul, e1, e2, e3] at this + +/-- Hence the legs of a primitive Heronian isosceles triangle are odd. -/ +theorem IsoOK.leg_odd {s b : ℕ} (h : IsoOK s b) : s % 2 = 1 := by + have hb := h.base_even + obtain ⟨-, -, hg, -⟩ := h + by_contra hs + have h2 : 2 ∣ Nat.gcd s b := + Nat.dvd_gcd (Nat.dvd_of_mod_eq_zero (by omega)) (Nat.dvd_of_mod_eq_zero hb) + rw [hg] at h2 + exact absurd (Nat.le_of_dvd one_pos h2) (by norm_num) + +/-- For `x ≥ 1`, `A² = x² K` has a solution `A` iff `K` is a square. -/ +theorem exists_sq_mul_iff {x K : ℕ} (hx : 0 < x) : + (∃ A : ℕ, A ^ 2 = x ^ 2 * K) ↔ ∃ h, h * h = K := by + constructor + · rintro ⟨A, hA⟩ + obtain ⟨h, rfl⟩ : x ∣ A := (Nat.pow_dvd_pow_iff two_ne_zero).1 ⟨K, hA⟩ + refine ⟨h, Nat.eq_of_mul_eq_mul_left (show 0 < x ^ 2 by positivity) ?_⟩ + rw [← hA]; ring + · rintro ⟨h, rfl⟩ + exact ⟨x * h, by ring⟩ + +/-- For the perimeter `2m`, the leg `s` (with base `2(m - s)`) gives a primitive Heronian +isosceles triangle: `m/2 < s < m`, `s` odd, `gcd(s, m) = 1`, and `m (2s - m)` is a square. -/ +def LegOK (m s : ℕ) : Prop := + m < 2 * s ∧ s < m ∧ s % 2 = 1 ∧ Nat.gcd s m = 1 ∧ ∃ h, h * h = m * (2 * s - m) + +theorem isoOK_iff_legOK (s x : ℕ) : IsoOK s (2 * x) ↔ LegOK (s + x) s := by + constructor + · intro hiso + have hodd := hiso.leg_odd + obtain ⟨h0, h1, hg, A, hA⟩ := hiso + obtain ⟨e, rfl⟩ : ∃ e, s = x + e := ⟨s - x, by omega⟩ + refine ⟨by omega, by omega, hodd, ?_, ?_⟩ + · rw [Nat.gcd_self_add_right] + exact Nat.Coprime.coprime_mul_left_right hg + · rw [show 2 * (x + e) - 2 * x = 2 * e by omega] at hA + rw [show 2 * (x + e) - (x + e + x) = e by omega] + refine (exists_sq_mul_iff (x := x) (by omega)).1 ⟨A, ?_⟩ + apply Nat.eq_of_mul_eq_mul_left (show 0 < 16 by norm_num) + rw [hA]; ring + · rintro ⟨h1, h2, hodd, hg, h, hh⟩ + obtain ⟨e, rfl⟩ : ∃ e, s = x + e := ⟨s - x, by omega⟩ + refine ⟨by omega, by omega, ?_, ?_⟩ + · apply Nat.Coprime.mul_right + · exact Nat.coprime_two_right.2 (Nat.odd_iff.2 hodd) + · rw [Nat.gcd_self_add_right] at hg + exact hg + · rw [show 2 * (x + e) - (x + e + x) = e by omega] at hh + obtain ⟨A, hA⟩ := (exists_sq_mul_iff (x := x) (by omega)).2 ⟨h, hh⟩ + refine ⟨A, ?_⟩ + rw [show 2 * (x + e) - 2 * x = 2 * e by omega, hA] + ring + +/-- `P` is a perimeter iff `P = 2m` and some leg `s` works (`LegOK m s`). -/ +theorem isPerimeter_iff_legOK (P : ℕ) : IsPerimeter P ↔ P % 2 = 0 ∧ ∃ s, LegOK (P / 2) s := by + rw [isPerimeter_iff] + constructor + · rintro ⟨s, b, hs, hP⟩ + have hb := hs.base_even + obtain ⟨x, rfl⟩ : ∃ x, b = 2 * x := ⟨b / 2, by omega⟩ + refine ⟨by omega, s, ?_⟩ + rw [show P / 2 = s + x by omega, ← isoOK_iff_legOK] + exact hs + · rintro ⟨hP, s, hs⟩ + have h2 := hs.2.1 + refine ⟨s, 2 * (P / 2 - s), ?_, by omega⟩ + rw [isoOK_iff_legOK, show s + (P / 2 - s) = P / 2 by omega] + exact hs + +/-- Boolean version of `LegOK`. -/ +def legB (m s : ℕ) : Bool := + Nat.beq (Nat.gcd s m) 1 && Nat.blt m (2 * s) && Nat.blt s m && Nat.beq (s % 2) 1 && + sqB (m * (2 * s - m)) + +theorem legB_iff (m s : ℕ) : legB m s = true ↔ LegOK m s := by + simp only [legB, Bool.and_eq_true, Nat.blt_eq, Nat.beq_eq, sqB_iff, LegOK] + constructor + · rintro ⟨⟨⟨⟨hg, h1⟩, h2⟩, h3⟩, h4⟩ + exact ⟨h1, h2, h3, hg, h4⟩ + · rintro ⟨h1, h2, h3, hg, h4⟩ + exact ⟨⟨⟨⟨hg, h1⟩, h2⟩, h3⟩, h4⟩ + +/-- `anyS m k s`: one of the legs `s, s + 2, …, s + 2(k-1)` passes `legB m` (written with +`Nat.rec`, which the kernel evaluates cheaply). -/ +def anyS (m k : ℕ) : ℕ → Bool := + Nat.rec (motive := fun _ => ℕ → Bool) (fun _ => false) (fun _ ih s => legB m s || ih (s + 2)) k + +theorem anyS_zero (m s : ℕ) : anyS m 0 s = false := rfl + +theorem anyS_succ (m k s : ℕ) : anyS m (k + 1) s = (legB m s || anyS m k (s + 2)) := rfl + +theorem anyS_iff (m : ℕ) : ∀ k s, anyS m k s = true ↔ ∃ t < k, legB m (s + 2 * t) = true + | 0, s => by simp [anyS_zero] + | k + 1, s => by + rw [anyS_succ, Bool.or_eq_true, anyS_iff m k (s + 2)] + constructor + · rintro (h | ⟨t, ht, h⟩) + · exact ⟨0, by omega, by simpa using h⟩ + · exact ⟨t + 1, by omega, by rw [show s + 2 * (t + 1) = s + 2 + 2 * t by ring]; exact h⟩ + · rintro ⟨t, ht, h⟩ + rcases t with _ | t + · left + simpa using h + · right + exact ⟨t, by omega, by rw [show s + 2 + 2 * t = s + 2 * (t + 1) by ring]; exact h⟩ + +/-- A computable test for `IsPerimeter P`: `P = 2m` is even and some odd leg `s` with +`m / 2 < s < m` passes `legB m`. -/ +def perimB (P : ℕ) : Bool := Nat.beq (P % 2) 0 && anyS (P / 2) (P / 8 + 2) (2 * (P / 8) + 1) + +theorem perimB_iff (P : ℕ) : perimB P = true ↔ IsPerimeter P := by + rw [isPerimeter_iff_legOK, perimB, Bool.and_eq_true, Nat.beq_eq, anyS_iff] + constructor + · rintro ⟨hP, t, -, hs⟩ + exact ⟨hP, _, (legB_iff _ _).1 hs⟩ + · rintro ⟨hP, s, hs⟩ + have := hs.1; have := hs.2.1; have := hs.2.2.1 + refine ⟨hP, (s - (2 * (P / 8) + 1)) / 2, by omega, ?_⟩ + rw [show 2 * (P / 8) + 1 + 2 * ((s - (2 * (P / 8) + 1)) / 2) = s by omega, legB_iff] + exact hs + +instance : DecidablePred IsPerimeter := fun P => decidable_of_iff _ (perimB_iff P) + +/-! ### A096033: differences between a leg and the hypotenuse of a primitive Pythagorean +triangle -/ + +/-- `d` is the difference between a leg and the hypotenuse of a primitive Pythagorean triangle: +there are legs `x, y ≥ 1` with `gcd(x, y) = 1` and a hypotenuse `z` with `x² + y² = z²`, and +`z = x + d` (the legs play symmetric roles, so `x` is either leg). -/ +def IsLegHypDiff (d : ℕ) : Prop := + ∃ x y z : ℕ, 0 < x ∧ 0 < y ∧ x ^ 2 + y ^ 2 = z ^ 2 ∧ Nat.gcd x y = 1 ∧ z = x + d + +/-- A096033 (offset `1`): the `n`-th smallest difference between a leg and the hypotenuse of a +primitive Pythagorean triangle. -/ +noncomputable def A096033 (n : ℕ) : ℕ := Nat.nth IsLegHypDiff (n - 1) + +/-- The differences are the odd squares and the numbers `2 j²`, `j ≥ 1` (as stated in the +entry A096033; proved here only to make `IsLegHypDiff` decidable). -/ +theorem isLegHypDiff_iff (d : ℕ) : IsLegHypDiff d ↔ + (d % 2 = 1 ∧ ∃ k, k * k = d) ∨ (d % 2 = 0 ∧ 0 < d ∧ ∃ j, j * j = d / 2) := by + constructor + · rintro ⟨x, y, z, hx, hy, hpy, hg, rfl⟩ + have h : PythagoreanTriple (x : ℤ) y ((x + d : ℕ) : ℤ) := by + unfold PythagoreanTriple + rw [← sq, ← sq, ← sq] + exact_mod_cast hpy + have hc : Int.gcd x y = 1 := by rw [Int.gcd_natCast_natCast]; exact hg + have hzpos : (0 : ℤ) < ((x + d : ℕ) : ℤ) := by exact_mod_cast (show 0 < x + d by omega) + rcases h.even_odd_of_coprime hc with ⟨-, hy2⟩ | ⟨hx2, -⟩ + · -- `x` even: `d = (m - n)²` with `m - n` odd + have hc' : Int.gcd y x = 1 := by rw [Int.gcd_comm]; exact hc + obtain ⟨m, n, -, hxe, hze, -, hpar, -⟩ := h.symm.coprime_classification' hc' hy2 hzpos + have hd : (d : ℤ) = (m - n) * (m - n) := by + have : ((x + d : ℕ) : ℤ) = x + d := by push_cast; ring + rw [this] at hze + linear_combination hze - hxe + have hodd : (m - n) % 2 = 1 := by omega + left + refine ⟨?_, (m - n).natAbs, ?_⟩ + · obtain ⟨q, hq⟩ : ∃ q, m - n = 2 * q + 1 := ⟨(m - n) / 2, by omega⟩ + rw [hq] at hd + have : (d : ℤ) = 2 * (2 * q * q + 2 * q) + 1 := by rw [hd]; ring + generalize 2 * q * q + 2 * q = w at this + omega + · have := Int.natAbs_mul_self' (m - n) + rw [← hd] at this + exact_mod_cast this + · -- `x` odd: `d = 2 n²` with `n ≠ 0` + obtain ⟨m, n, hxe, hye, hze, -, -, -⟩ := h.coprime_classification' hc hx2 hzpos + have e : ((n.natAbs * n.natAbs : ℕ) : ℤ) = n * n := by + rw [Nat.cast_mul] + exact Int.natAbs_mul_self' n + have hd : (d : ℤ) = 2 * (n.natAbs * n.natAbs : ℕ) := by + have : ((x + d : ℕ) : ℤ) = x + d := by push_cast; ring + rw [this] at hze + rw [e] + linear_combination hze - hxe + have hd' : d = 2 * (n.natAbs * n.natAbs) := by exact_mod_cast hd + have hn : n ≠ 0 := by + rintro rfl + simp at hye + omega + have hpos : 0 < n.natAbs * n.natAbs := Nat.mul_pos (by omega) (by omega) + right + refine ⟨by omega, by omega, n.natAbs, by omega⟩ + · rintro (⟨hd, k, rfl⟩ | ⟨hd, hd0, j, hj⟩) + · -- `d = k²`, `k = 2t+1`: the triangle `(2k+2, k²+2k, k²+2k+2)` + obtain ⟨t, rfl⟩ : ∃ t, k = 2 * t + 1 := by + refine ⟨k / 2, ?_⟩ + rcases Nat.even_or_odd k with ⟨r, rfl⟩ | ⟨r, rfl⟩ + · exfalso + have : (r + r) * (r + r) = 2 * (2 * r * r) := by ring + omega + · omega + refine ⟨2 * (2 * t + 1) + 2, (2 * t + 1) * (2 * t + 1) + 2 * (2 * t + 1), + (2 * t + 1) * (2 * t + 1) + 2 * (2 * t + 1) + 2, by omega, by positivity, by ring, + ?_, by ring⟩ + apply Nat.isCoprime_iff_coprime.1 + exact ⟨(t + 1 : ℤ), -1, by push_cast; ring⟩ + · -- `d = 2 j²`: the triangle `(2j+1, 2j²+2j, 2j²+2j+1)` + have hj0 : 0 < j := by + rcases Nat.eq_zero_or_pos j with rfl | h + · omega + · exact h + have hdj : d = 2 * (j * j) := by omega + subst hdj + refine ⟨2 * j + 1, 2 * (j * j) + 2 * j, 2 * (j * j) + 2 * j + 1, by omega, by positivity, + by ring, ?_, by ring⟩ + apply Nat.isCoprime_iff_coprime.1 + exact ⟨(2 * j + 1 : ℤ), -2, by push_cast; ring⟩ + +/-- Boolean version of the characterization in `isLegHypDiff_iff`. -/ +def legHypB (d : ℕ) : Bool := + (Nat.beq (d % 2) 1 && sqB d) || (Nat.beq (d % 2) 0 && Nat.blt 0 d && sqB (d / 2)) + +theorem legHypB_iff (d : ℕ) : legHypB d = true ↔ IsLegHypDiff d := by + rw [isLegHypDiff_iff] + simp [legHypB, sqB_iff, Nat.beq_eq, Nat.blt_eq, and_assoc] + +instance : DecidablePred IsLegHypDiff := fun d => decidable_of_iff _ (legHypB_iff d) + +/-! ### Data (kernel-checked) -/ + +/-- The elements `< N` satisfying `p`, in increasing order, are `nth p 0, nth p 1, …`. -/ +theorem filter_range_eq (p : ℕ → Prop) [DecidablePred p] (N : ℕ) : + (List.range N).filter (fun k => decide (p k)) = + (List.range (Nat.count p N)).map (Nat.nth p) := by + induction N with + | zero => simp + | succ N ih => + rw [List.range_succ, List.filter_append, ih, Nat.count_succ] + by_cases h : p N + · simp [h, List.range_succ, Nat.nth_count h] + · simp [h] + +theorem map_nth_eq_of_filter {p : ℕ → Prop} [DecidablePred p] {N K : ℕ} {L : List ℕ} + (h : (List.range N).filter (fun k => decide (p k)) = L) (hK : L.length = K) : + (List.range K).map (Nat.nth p) = L := by + rw [filter_range_eq] at h + subst h + simp only [List.length_map, List.length_range] at hK + rw [hK] + +/-- The perimeters `P` with `lo ≤ P < hi`, as found by the decision procedure. -/ +def chunk (lo hi : ℕ) : List ℕ := (List.range' lo (hi - lo)).filter fun k => decide (IsPerimeter k) + +theorem chunk_split {lo mid hi : ℕ} (h1 : lo ≤ mid) (h2 : mid ≤ hi) : + chunk lo hi = chunk lo mid ++ chunk mid hi := by + unfold chunk + rw [← List.filter_append, show hi - lo = (mid - lo) + (hi - mid) by omega, + ← List.range'_append_1, show lo + (mid - lo) = mid by omega] + +/-! The search below `3137` is split into chunks, each checked in the kernel separately (this +bounds the memory used by each kernel check). -/ + +theorem chunk_1 : chunk 0 1186 = + [16, 18, 36, 50, 64, 98, 100, 144, 162, 196, 242, 256, 324, 338, 400, 450, 484, 576, 578, 676, + 722, 784, 882, 900, 1024, 1058, 1156] := by + decide +kernel + +theorem chunk_2 : chunk 1186 1677 = + [1250, 1296, 1444, 1458, 1600] := by + decide +kernel + +theorem chunk_3 : chunk 1677 2054 = + [1682, 1764, 1922, 1936] := by + decide +kernel + +theorem chunk_4 : chunk 2054 2371 = + [2116, 2178, 2304] := by + decide +kernel + +theorem chunk_5 : chunk 2371 2651 = + [2450, 2500] := by + decide +kernel + +theorem chunk_6 : chunk 2651 2904 = + [2704, 2738] := by + decide +kernel + +theorem chunk_7 : chunk 2904 3137 = + [2916, 3042, 3136] := by + decide +kernel + +/-- The perimeters below `3137` are the 46 listed terms. -/ +theorem filter_range_3137 : (List.range 3137).filter (fun k => decide (IsPerimeter k)) = + [16, 18, 36, 50, 64, 98, 100, 144, 162, 196, 242, 256, 324, 338, 400, 450, 484, 576, 578, 676, + 722, 784, 882, 900, 1024, 1058, 1156, 1250, 1296, 1444, 1458, 1600, 1682, 1764, 1922, 1936, + 2116, 2178, 2304, 2450, 2500, 2704, 2738, 2916, 3042, 3136] := by + have h : (List.range 3137).filter (fun k => decide (IsPerimeter k)) = chunk 0 3137 := by + rw [chunk, Nat.sub_zero, List.range_eq_range'] + rw [h, + chunk_split (lo := 0) (mid := 1186) (hi := 3137) (by norm_num) (by norm_num), + chunk_split (lo := 1186) (mid := 1677) (hi := 3137) (by norm_num) (by norm_num), + chunk_split (lo := 1677) (mid := 2054) (hi := 3137) (by norm_num) (by norm_num), + chunk_split (lo := 2054) (mid := 2371) (hi := 3137) (by norm_num) (by norm_num), + chunk_split (lo := 2371) (mid := 2651) (hi := 3137) (by norm_num) (by norm_num), + chunk_split (lo := 2651) (mid := 2904) (hi := 3137) (by norm_num) (by norm_num)] + rw [chunk_1, chunk_2, chunk_3, chunk_4, chunk_5, chunk_6, chunk_7] + rfl + +/-- The definition reproduces all 46 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 46).map (fun i => a (i + 1)) = + [16, 18, 36, 50, 64, 98, 100, 144, 162, 196, 242, 256, 324, 338, 400, 450, 484, 576, 578, 676, + 722, 784, 882, 900, 1024, 1058, 1156, 1250, 1296, 1444, 1458, 1600, 1682, 1764, 1922, 1936, + 2116, 2178, 2304, 2450, 2500, 2704, 2738, 2916, 3042, 3136] := by + have : (fun i => a (i + 1)) = Nat.nth IsPerimeter := funext fun i => by simp [a] + rw [this] + exact map_nth_eq_of_filter filter_range_3137 rfl + +/-- The definition of A096033 reproduces its 52 listed terms (kernel-checked). -/ +theorem A096033_data : (List.range 52).map (fun i => A096033 (i + 1)) = + [1, 2, 8, 9, 18, 25, 32, 49, 50, 72, 81, 98, 121, 128, 162, 169, 200, 225, 242, 288, 289, + 338, 361, 392, 441, 450, 512, 529, 578, 625, 648, 722, 729, 800, 841, 882, 961, 968, + 1058, 1089, 1152, 1225, 1250, 1352, 1369, 1458, 1521, 1568, 1681, 1682, 1800, 1849] := by + have : (fun i => A096033 (i + 1)) = Nat.nth IsLegHypDiff := funext fun i => by simp [A096033] + rw [this] + exact map_nth_eq_of_filter (N := 1850) (by decide +kernel) rfl + +/-! ### The conjecture -/ + +/-- Conjecture (Kagey, A308222): for every `n ≥ 1`, the `n`-th smallest perimeter of a primitive +Heronian isosceles triangle is twice the `(n + 2)`-th smallest difference between a leg and the +hypotenuse of a primitive Pythagorean triangle: `a(n) = 2 · A096033(n + 2)`. -/ +def statement : Prop := ∀ n : ℕ, 1 ≤ n → a n = 2 * A096033 (n + 2) + +end Math0.Statements.A308222 diff --git a/lean/Math0/Statements/OEIS/A308359.lean b/lean/Math0/Statements/OEIS/A308359.lean new file mode 100644 index 0000000..0a31155 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A308359.lean @@ -0,0 +1,547 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A308359: fixed polyominoes with `n` cells and width `n - 2` + +Source: https://oeis.org/A308359, _R. J. Mathar_, May 22 2019 (FORMULA section). Verbatim: +> Conjecture: T(n,n-2) = 8*n^2 - 51*n + 86 for n >= 5. + +The entry is "Triangle T(n,w) read by rows: the number of fixed polyominoes with n cells and +width w of the convex hull." (offset `1`, rows `n ≥ 1`, `1 ≤ w ≤ n`). + +## Encoding + +* *Fixed polyominoes.* A fixed polyomino with `n` cells is a set of `n` unit cells of the square + grid, connected through shared edges, counted up to translation only (rotations and + reflections give different fixed polyominoes). Every translation class of a finite nonempty set + of cells of `ℤ × ℤ` contains exactly one set lying in `ℕ × ℕ` that meets both the line `x = 0` + and the line `y = 0`. So a fixed polyomino with `n` cells is encoded by such a normalized + set `S : Finset (ℕ × ℕ)`: `S.card = n`, some cell has `x = 0`, some cell has `y = 0`, and `S` + is edge-connected (`IsConnected`: any two cells of `S` are joined by a chain of cells of `S`, + consecutive ones sharing an edge (`Adj`)). Cells are written `(x, y)`, `x` the column. +* *Width.* The convex hull of the union of the unit squares of `S` spans the columns + `min x, …, max x`, so its width is `max x - min x + 1 = S.sup Prod.fst + 1` (`min x = 0`). + Only the width is prescribed; the height is unrestricted. (The entry's comment says that the + height `h` ranges over `w ≤ h ≤ n`, but the entry itself contradicts this: its formula + `T(n,n-1) = 4*n-8` counts shapes of "width n-1 and height 2", the listed `T(4,3) = 8` counts the + L, T and S/Z tetrominoes of height `2`, and the row sums are the total numbers of fixed + polyominoes, A001168, which the entry cross-references.) +* `T n w` is the number of such sets (`Set.ncard`, noncomputable). `T_eq_Tbox` proves that every + such set lies in the box `[0, w) × [0, n + 1 - w)`, so `T n w = Tbox n w`, a computable count + over the `n`-element subsets of that box. Connectivity is decided by a flood fill on bit masks + (`connBits`: the cell `(x, y)` is bit `x * D + y` with `D = max y + 2`, so that steps along a + column never wrap into the next column), proved equivalent to `IsConnected` + (`isConnected_iff_bits`, via the flood fill on finsets, `grow_eq_iff`); this keeps the kernel + computation fast. +* The triangle is read by rows (offset `1`): `a (n * (n - 1) / 2 + w) = T n w` for + `1 ≤ w ≤ n` (`a_eq_T`). `a_data` checks the first 23 listed terms (rows `1..6`, then + `T(7,1) = 1`, `T(7,2) = 66`) in the kernel, in four pieces to keep its memory use small. The + next term, `T(7,3)`, ranges over `C(15,7) = 6435` subsets and is out of reach of a quick check. +* The conjecture is stated for every `n ≥ 5` (then `w = n - 2 ≥ 3`) in `ℤ`, so the right side + `8n² - 51n + 86` is not truncated (it is positive anyway). +-/ + +namespace Math0.Statements.A308359 + +/-! ### Fixed polyominoes -/ + +/-- Two cells `p = (x, y)` and `q` of the grid share an edge. -/ +def Adj (p q : ℕ × ℕ) : Prop := + (p.1 = q.1 ∧ (p.2 + 1 = q.2 ∨ q.2 + 1 = p.2)) ∨ (p.2 = q.2 ∧ (p.1 + 1 = q.1 ∨ q.1 + 1 = p.1)) + +instance : DecidableRel Adj := fun p q => + inferInstanceAs (Decidable ((p.1 = q.1 ∧ (p.2 + 1 = q.2 ∨ q.2 + 1 = p.2)) ∨ + (p.2 = q.2 ∧ (p.1 + 1 = q.1 ∨ q.1 + 1 = p.1)))) + +/-- A step between two edge-adjacent cells of `S`. -/ +def Step (S : Finset (ℕ × ℕ)) (p q : ℕ × ℕ) : Prop := p ∈ S ∧ q ∈ S ∧ Adj p q + +/-- `S` is edge-connected: any two cells of `S` are joined by a chain of cells of `S` in which +consecutive cells share an edge. -/ +def IsConnected (S : Finset (ℕ × ℕ)) : Prop := + ∀ p ∈ S, ∀ q ∈ S, Relation.ReflTransGen (Step S) p q + +/-- `S` is (the normalized representative of) a fixed polyomino with `n` cells and width `w`: +`n` cells, translated so that the least column and the least row are `0`, edge-connected, with +columns `0, …, w - 1` spanned by its convex hull (`max x + 1 = w`). -/ +def IsPoly (n w : ℕ) (S : Finset (ℕ × ℕ)) : Prop := + S.card = n ∧ (∃ p ∈ S, p.1 = 0) ∧ (∃ p ∈ S, p.2 = 0) ∧ S.sup Prod.fst + 1 = w ∧ IsConnected S + +/-- A308359: `T(n, w)` is the number of fixed polyominoes with `n` cells whose convex hull has +width `w`. -/ +noncomputable def T (n w : ℕ) : ℕ := {S : Finset (ℕ × ℕ) | IsPoly n w S}.ncard + +/-! ### Connectivity by a flood fill -/ + +/-- Add to `R` the cells of `S` that share an edge with a cell of `R`. -/ +def step (S R : Finset (ℕ × ℕ)) : Finset (ℕ × ℕ) := R ∪ S.filter fun c => ∃ b ∈ R, Adj b c + +/-- `k` rounds of `step`. -/ +def grow (S : Finset (ℕ × ℕ)) : ℕ → Finset (ℕ × ℕ) → Finset (ℕ × ℕ) + | 0, R => R + | k + 1, R => grow S k (step S R) + +theorem adj_symm {p q : ℕ × ℕ} (h : Adj p q) : Adj q p := by + unfold Adj at * + omega + +theorem step_symm {S : Finset (ℕ × ℕ)} {p q : ℕ × ℕ} (h : Step S p q) : Step S q p := + ⟨h.2.1, h.1, adj_symm h.2.2⟩ + +theorem reach_symm {S : Finset (ℕ × ℕ)} {p q : ℕ × ℕ} + (h : Relation.ReflTransGen (Step S) p q) : Relation.ReflTransGen (Step S) q p := by + induction h with + | refl => exact Relation.ReflTransGen.refl + | tail _ hbc ih => exact Relation.ReflTransGen.head (step_symm hbc) ih + +theorem subset_step (S R : Finset (ℕ × ℕ)) : R ⊆ step S R := Finset.subset_union_left + +theorem step_subset {S R : Finset (ℕ × ℕ)} (h : R ⊆ S) : step S R ⊆ S := + Finset.union_subset h (Finset.filter_subset _ _) + +theorem grow_subset {S : Finset (ℕ × ℕ)} : + ∀ (k : ℕ) {R : Finset (ℕ × ℕ)}, R ⊆ S → grow S k R ⊆ S + | 0, _, h => h + | k + 1, _, h => grow_subset k (step_subset h) + +theorem mem_grow_of_mem {S : Finset (ℕ × ℕ)} : + ∀ (k : ℕ) {R : Finset (ℕ × ℕ)} {x : ℕ × ℕ}, x ∈ R → x ∈ grow S k R + | 0, _, _, h => h + | k + 1, _, _, h => mem_grow_of_mem k (subset_step S _ h) + +/-- Everything the flood fill reaches is reachable from `r` inside `S`. -/ +theorem grow_reach {S : Finset (ℕ × ℕ)} {r : ℕ × ℕ} : + ∀ (k : ℕ) {R : Finset (ℕ × ℕ)}, R ⊆ S → (∀ x ∈ R, Relation.ReflTransGen (Step S) r x) → + ∀ x ∈ grow S k R, Relation.ReflTransGen (Step S) r x + | 0, _, _, h => h + | k + 1, R, hR, h => by + refine grow_reach k (step_subset hR) fun x hx => ?_ + rcases Finset.mem_union.1 hx with hx | hx + · exact h x hx + · obtain ⟨hxS, b, hb, hbx⟩ := Finset.mem_filter.1 hx + exact (h b hb).tail ⟨hR hb, hxS, hbx⟩ + +theorem grow_fix {S R : Finset (ℕ × ℕ)} (h : step S R = R) : ∀ k, grow S k R = R + | 0 => rfl + | k + 1 => by rw [grow, h, grow_fix h k] + +/-- After `k` rounds the flood fill has gained `k` cells or has stopped growing. -/ +theorem grow_card_or_closed {S : Finset (ℕ × ℕ)} : + ∀ (k : ℕ) (R : Finset (ℕ × ℕ)), + R.card + k ≤ (grow S k R).card ∨ step S (grow S k R) = grow S k R + | 0, _ => Or.inl le_rfl + | k + 1, R => by + by_cases hR : step S R = R + · right + rw [grow_fix hR] + exact hR + · rcases grow_card_or_closed (S := S) k (step S R) with h | h + · left + have hlt : R.card < (step S R).card := + Finset.card_lt_card (Finset.ssubset_iff_subset_ne.2 ⟨subset_step S R, Ne.symm hR⟩) + change R.card + (k + 1) ≤ (grow S k (step S R)).card + omega + · right + exact h + +/-- If a chain inside `S` leaves `A`, some cell of `S` outside `A` is adjacent to a cell of +`A`. -/ +theorem frontier {S A : Finset (ℕ × ℕ)} {a q : ℕ × ℕ} (ha : a ∈ A) (hq : q ∉ A) + (h : Relation.ReflTransGen (Step S) a q) : ∃ b ∈ A, ∃ c ∈ S, c ∉ A ∧ Adj b c := by + induction h with + | refl => exact absurd ha hq + | @tail b c _ hbc ih => + by_cases hb : b ∈ A + · exact ⟨b, hb, c, hbc.2.1, hq, hbc.2.2⟩ + · exact ih hb + +/-- `S` is connected iff the flood fill from any one of its cells reaches all of `S` within +`S.card` rounds. -/ +theorem grow_eq_iff {S : Finset (ℕ × ℕ)} {r : ℕ × ℕ} (hr : r ∈ S) : + grow S S.card {r} = S ↔ IsConnected S := by + have hsub : grow S S.card {r} ⊆ S := grow_subset _ (by simpa using hr) + constructor + · intro heq + have hreach : ∀ x ∈ S, Relation.ReflTransGen (Step S) r x := by + intro x hx + rw [← heq] at hx + refine grow_reach _ (by simpa using hr) (fun y hy => ?_) x hx + rw [Finset.mem_singleton.1 hy] + intro p hp q hq + exact (reach_symm (hreach p hp)).trans (hreach q hq) + · intro h + have hclosed : step S (grow S S.card {r}) = grow S S.card {r} := by + rcases grow_card_or_closed (S := S) S.card {r} with h' | h' + · have := Finset.card_le_card hsub + simp at h' + omega + · exact h' + have hSsub : S ⊆ grow S S.card {r} := by + intro q hq + by_contra hqG + obtain ⟨b, hb, c, hc, hcG, hbc⟩ := + frontier (mem_grow_of_mem S.card (Finset.mem_singleton_self r)) hqG (h r hr q hq) + apply hcG + rw [← hclosed] + exact Finset.mem_union_right _ (Finset.mem_filter.2 ⟨hc, b, hb, hbc⟩) + exact Finset.Subset.antisymm hsub hSsub + +/-! ### The same flood fill on bit masks (for fast evaluation in the kernel) -/ + +/-- The bit of the cell `c = (x, y)` in a mask with `D` bits per column. -/ +def idx (D : ℕ) (c : ℕ × ℕ) : ℕ := c.1 * D + c.2 + +/-- The bit mask of a set of cells. -/ +def enc (D : ℕ) (A : Finset (ℕ × ℕ)) : ℕ := ∑ c ∈ A, 2 ^ idx D c + +/-- One round of the flood fill on masks: add to `R` the cells of `m` next to a cell of `R` +(shifts by `1` move along a column, shifts by `D` move along a row). -/ +def bstep (D m R : ℕ) : ℕ := R ||| (m &&& ((R <<< 1) ||| (R >>> 1) ||| (R <<< D) ||| (R >>> D))) + +/-- `k` rounds of `bstep`. -/ +def bgrow (D m : ℕ) : ℕ → ℕ → ℕ + | 0, R => R + | k + 1, R => bgrow D m k (bstep D m R) + +/-- The column stride used for `S`: two more than its largest row index, so that every column +of the mask has an empty top bit and the shifts by `1` never connect two columns. -/ +def stride (S : Finset (ℕ × ℕ)) : ℕ := S.sup Prod.snd + 2 + +/-- The flood fill on masks, started from the cell of `S` at the highest bit of its mask, +reaches all of `S` within `S.card` rounds. -/ +def connBits (S : Finset (ℕ × ℕ)) : Prop := + bgrow (stride S) (enc (stride S) S) S.card (2 ^ Nat.log2 (enc (stride S) S)) = + enc (stride S) S + +instance : DecidablePred connBits := fun S => + inferInstanceAs (Decidable (bgrow (stride S) (enc (stride S) S) S.card + (2 ^ Nat.log2 (enc (stride S) S)) = enc (stride S) S)) + +theorem idx_inj {D : ℕ} {b c : ℕ × ℕ} (hb : b.2 < D) (hc : c.2 < D) + (h : idx D b = idx D c) : b = c := by + unfold idx at h + have hD : 0 < D := by omega + have h1 : (D * b.1 + b.2) / D = (D * c.1 + c.2) / D := by rw [Nat.mul_comm D, Nat.mul_comm D, h] + have h2 : (D * b.1 + b.2) % D = (D * c.1 + c.2) % D := by rw [Nat.mul_comm D, Nat.mul_comm D, h] + rw [Nat.mul_add_div hD, Nat.mul_add_div hD, Nat.div_eq_of_lt hb, Nat.div_eq_of_lt hc] at h1 + rw [Nat.mul_add_mod, Nat.mul_add_mod, Nat.mod_eq_of_lt hb, Nat.mod_eq_of_lt hc] at h2 + exact Prod.ext (by omega) h2 + +theorem testBit_enc {D : ℕ} {A : Finset (ℕ × ℕ)} (hA : ∀ c ∈ A, c.2 < D) (j : ℕ) : + (enc D A).testBit j = true ↔ ∃ c ∈ A, idx D c = j := by + have hinj : Set.InjOn (idx D) A := fun b hb c hc h => idx_inj (hA b hb) (hA c hc) h + have he : enc D A = ∑ i ∈ A.image (idx D), 2 ^ i := by + rw [enc, Finset.sum_image hinj] + rw [he, ← Nat.mem_bitIndices, ← List.mem_toFinset, Finset.toFinset_bitIndices_sum_two_pow, + Finset.mem_image] + +theorem enc_inj {D : ℕ} {A B : Finset (ℕ × ℕ)} (hA : ∀ c ∈ A, c.2 < D) + (hB : ∀ c ∈ B, c.2 < D) (h : enc D A = enc D B) : A = B := by + have key : ∀ {A B : Finset (ℕ × ℕ)}, (∀ c ∈ A, c.2 < D) → (∀ c ∈ B, c.2 < D) → + enc D A = enc D B → A ⊆ B := by + intro A B hA hB h c hc + have hc' := (testBit_enc hA (idx D c)).2 ⟨c, hc, rfl⟩ + rw [h] at hc' + obtain ⟨c', hc'B, he⟩ := (testBit_enc hB _).1 hc' + rwa [← idx_inj (hB c' hc'B) (hA c hc) he] + exact Finset.Subset.antisymm (key hA hB h) (key hB hA h.symm) + +/-- Adjacent cells are the cells whose bits differ by `1` or by `D` (rows below `D - 1`). -/ +theorem adj_iff_idx {D : ℕ} {b c : ℕ × ℕ} (hb : b.2 + 2 ≤ D) (hc : c.2 + 2 ≤ D) : + Adj b c ↔ idx D b + 1 = idx D c ∨ idx D c + 1 = idx D b ∨ idx D b + D = idx D c ∨ + idx D c + D = idx D b := by + constructor + · intro h + unfold Adj at h + unfold idx + rcases h with ⟨h1, h2 | h2⟩ | ⟨h1, h2 | h2⟩ + · rw [h1]; omega + · rw [h1]; omega + · rw [← h2, Nat.add_mul, h1]; omega + · rw [← h2, Nat.add_mul, h1]; omega + · intro h + unfold Adj + rcases h with h | h | h | h + · have := idx_inj (D := D) (b := (b.1, b.2 + 1)) (c := c) (by simp; omega) (by omega) + (by unfold idx at *; simp only; omega) + rw [← this]; simp + · have := idx_inj (D := D) (b := (c.1, c.2 + 1)) (c := b) (by simp; omega) (by omega) + (by unfold idx at *; simp only; omega) + rw [← this]; simp + · have := idx_inj (D := D) (b := (b.1 + 1, b.2)) (c := c) (by simp; omega) (by omega) + (by unfold idx at *; simp only [Nat.add_mul]; omega) + rw [← this]; simp + · have := idx_inj (D := D) (b := (c.1 + 1, c.2)) (c := b) (by simp; omega) (by omega) + (by unfold idx at *; simp only [Nat.add_mul]; omega) + rw [← this]; simp + +theorem bstep_enc {D : ℕ} {S A : Finset (ℕ × ℕ)} (hS : ∀ c ∈ S, c.2 + 2 ≤ D) (hA : A ⊆ S) : + bstep D (enc D S) (enc D A) = enc D (step S A) := by + have hS' : ∀ c ∈ S, c.2 < D := fun c hc => by have := hS c hc; omega + have hA' : ∀ c ∈ A, c.2 < D := fun c hc => hS' c (hA hc) + have hT' : ∀ c ∈ step S A, c.2 < D := fun c hc => hS' c (step_subset hA hc) + apply Nat.eq_of_testBit_eq + intro j + apply Bool.eq_iff_iff.2 + rw [bstep, testBit_enc hT'] + simp only [Nat.testBit_lor, Nat.testBit_land, Nat.testBit_shiftLeft, Nat.testBit_shiftRight, + Bool.or_eq_true, Bool.and_eq_true, decide_eq_true_eq, testBit_enc hA', testBit_enc hS'] + constructor + · rintro (⟨c, hc, rfl⟩ | ⟨⟨c, hc, rfl⟩, h⟩) + · exact ⟨c, subset_step S A hc, rfl⟩ + · refine ⟨c, Finset.mem_union_right _ (Finset.mem_filter.2 ⟨hc, ?_⟩), rfl⟩ + rcases h with (((⟨h1, b, hb, hbj⟩ | ⟨b, hb, hbj⟩) | ⟨h1, b, hb, hbj⟩) | ⟨b, hb, hbj⟩) + · exact ⟨b, hb, (adj_iff_idx (hS b (hA hb)) (hS c hc)).2 (Or.inl (by omega))⟩ + · exact ⟨b, hb, (adj_iff_idx (hS b (hA hb)) (hS c hc)).2 (Or.inr (Or.inl (by omega)))⟩ + · exact ⟨b, hb, (adj_iff_idx (hS b (hA hb)) (hS c hc)).2 + (Or.inr (Or.inr (Or.inl (by omega))))⟩ + · exact ⟨b, hb, (adj_iff_idx (hS b (hA hb)) (hS c hc)).2 + (Or.inr (Or.inr (Or.inr (by omega))))⟩ + · rintro ⟨c, hc, rfl⟩ + rcases Finset.mem_union.1 hc with hc | hc + · exact Or.inl ⟨c, hc, rfl⟩ + · obtain ⟨hcS, b, hb, hbc⟩ := Finset.mem_filter.1 hc + refine Or.inr ⟨⟨c, hcS, rfl⟩, ?_⟩ + rcases (adj_iff_idx (hS b (hA hb)) (hS c hcS)).1 hbc with h | h | h | h + · exact Or.inl (Or.inl (Or.inl ⟨by omega, b, hb, by omega⟩)) + · exact Or.inl (Or.inl (Or.inr ⟨b, hb, by omega⟩)) + · exact Or.inl (Or.inr ⟨by omega, b, hb, by omega⟩) + · exact Or.inr ⟨b, hb, by omega⟩ + +theorem bgrow_enc {D : ℕ} {S : Finset (ℕ × ℕ)} (hS : ∀ c ∈ S, c.2 + 2 ≤ D) : + ∀ (k : ℕ) {A : Finset (ℕ × ℕ)}, A ⊆ S → bgrow D (enc D S) k (enc D A) = enc D (grow S k A) + | 0, _, _ => rfl + | k + 1, A, hA => by + rw [bgrow, bstep_enc hS hA, grow] + exact bgrow_enc hS k (step_subset hA) + +theorem connBits_iff {S : Finset (ℕ × ℕ)} (hne : S.Nonempty) : connBits S ↔ IsConnected S := by + have hS : ∀ c ∈ S, c.2 + 2 ≤ stride S := fun c hc => by + have := Finset.le_sup (f := Prod.snd) hc + unfold stride + omega + have hS' : ∀ c ∈ S, c.2 < stride S := fun c hc => by have := hS c hc; omega + have hm : enc (stride S) S ≠ 0 := by + obtain ⟨c, hc⟩ := hne + intro h0 + have := (testBit_enc hS' (idx (stride S) c)).2 ⟨c, hc, rfl⟩ + rw [h0, Nat.zero_testBit] at this + exact Bool.false_ne_true this + obtain ⟨r, hr, hrm⟩ := (testBit_enc hS' _).1 (Nat.testBit_log2 hm) + have h1 : 2 ^ Nat.log2 (enc (stride S) S) = enc (stride S) {r} := by + rw [← hrm] + simp only [enc, Finset.sum_singleton] + have hr' : ({r} : Finset (ℕ × ℕ)) ⊆ S := by simpa using hr + unfold connBits + rw [h1, bgrow_enc hS _ hr', ← grow_eq_iff hr] + exact ⟨enc_inj (fun c hc => hS' c (grow_subset _ hr' hc)) hS', fun h => by rw [h]⟩ + +theorem isConnected_iff_bits (S : Finset (ℕ × ℕ)) : S.card = 0 ∨ connBits S ↔ IsConnected S := by + rcases S.eq_empty_or_nonempty with rfl | hne + · simp only [Finset.card_empty, true_or, true_iff] + intro p hp + simp at hp + · rw [connBits_iff hne] + have := hne.card_pos + exact ⟨fun h => h.resolve_left (by omega), Or.inr⟩ + +instance : DecidablePred IsConnected := fun S => decidable_of_iff _ (isConnected_iff_bits S) + +instance (n w : ℕ) : DecidablePred (IsPoly n w) := fun S => + inferInstanceAs (Decidable (S.card = n ∧ (∃ p ∈ S, p.1 = 0) ∧ (∃ p ∈ S, p.2 = 0) ∧ + S.sup Prod.fst + 1 = w ∧ IsConnected S)) + +/-! ### A polyomino with `n` cells and width `w` fits in a `w × (n + 1 - w)` box -/ + +/-- Along a chain inside `S`, a coordinate `f` that changes by at most one per step takes every +intermediate value on some cell of `S`. -/ +theorem exists_coord {S : Finset (ℕ × ℕ)} (f : ℕ × ℕ → ℕ) + (hf : ∀ p q, Adj p q → f q ≤ f p + 1) {a b : ℕ × ℕ} (ha : a ∈ S) + (hab : Relation.ReflTransGen (Step S) a b) : + ∀ k, f a ≤ k → k ≤ f b → ∃ c ∈ S, f c = k := by + induction hab with + | refl => + intro k h1 h2 + exact ⟨a, ha, by omega⟩ + | @tail b c _ hbc ih => + intro k h1 h2 + by_cases hk : k ≤ f b + · exact ih k h1 hk + · have := hf b c hbc.2.2 + exact ⟨c, hbc.2.1, by omega⟩ + +/-- A connected set of cells occupying `C` columns and `R` rows has at least `C + R - 1` +cells. -/ +theorem cols_add_rows_le {S : Finset (ℕ × ℕ)} (hS : IsConnected S) (hne : S.Nonempty) : + (S.image Prod.fst).card + (S.image Prod.snd).card ≤ S.card + 1 := by + obtain ⟨s, hs⟩ := hne + have key : ∀ k, k + 1 ≤ S.card → ∃ A ⊆ S, A.card = k + 1 ∧ + (A.image Prod.fst).card + (A.image Prod.snd).card ≤ k + 2 := by + intro k + induction k with + | zero => + intro _ + exact ⟨{s}, by simpa using hs, by simp, by simp⟩ + | succ k ih => + intro hk + obtain ⟨A, hAS, hAc, hAb⟩ := ih (by omega) + have hq : ∃ q ∈ S, q ∉ A := by + by_contra hcon + have hSA : S ⊆ A := fun q hq => by + by_contra hqA + exact hcon ⟨q, hq, hqA⟩ + have := Finset.card_le_card hSA + omega + obtain ⟨q, hqS, hqA⟩ := hq + obtain ⟨a, haA⟩ : A.Nonempty := by + rw [← Finset.card_pos] + omega + obtain ⟨b, hbA, c, hcS, hcA, hbc⟩ := frontier haA hqA (hS a (hAS haA) q hqS) + refine ⟨insert c A, Finset.insert_subset hcS hAS, by + rw [Finset.card_insert_of_notMem hcA, hAc], ?_⟩ + rw [Finset.image_insert, Finset.image_insert] + have h1 := Finset.card_insert_le c.1 (A.image Prod.fst) + have h2 := Finset.card_insert_le c.2 (A.image Prod.snd) + rcases hbc with ⟨h, -⟩ | ⟨h, -⟩ + · have hm : c.1 ∈ A.image Prod.fst := Finset.mem_image.2 ⟨b, hbA, h⟩ + rw [Finset.card_insert_of_mem hm] + omega + · have hm : c.2 ∈ A.image Prod.snd := Finset.mem_image.2 ⟨b, hbA, h⟩ + rw [Finset.card_insert_of_mem hm] + omega + have hpos := Finset.card_pos.2 ⟨s, hs⟩ + obtain ⟨A, hAS, hAc, hAb⟩ := key (S.card - 1) (by omega) + have hA : A = S := Finset.eq_of_subset_of_card_le hAS (by omega) + subst hA + omega + +/-- The search box `[0, w) × [0, n + 1 - w)`. -/ +def box (n w : ℕ) : Finset (ℕ × ℕ) := Finset.range w ×ˢ Finset.range (n + 1 - w) + +theorem subset_box {n w : ℕ} {S : Finset (ℕ × ℕ)} (h : IsPoly n w S) : S ⊆ box n w := by + obtain ⟨hcard, ⟨p0, hp0S, hp0⟩, ⟨q0, hq0S, hq0⟩, hsup, hconn⟩ := h + have hne : S.Nonempty := ⟨p0, hp0S⟩ + obtain ⟨m, hmS, hm⟩ := Finset.exists_mem_eq_sup S hne Prod.fst + have hfst : ∀ p q : ℕ × ℕ, Adj p q → q.1 ≤ p.1 + 1 := by + intro p q h + unfold Adj at h + omega + have hsnd : ∀ p q : ℕ × ℕ, Adj p q → q.2 ≤ p.2 + 1 := by + intro p q h + unfold Adj at h + omega + have hcols : Finset.range w ⊆ S.image Prod.fst := by + intro k hk + rw [Finset.mem_range] at hk + obtain ⟨c, hc, hck⟩ := + exists_coord Prod.fst hfst hp0S (hconn p0 hp0S m hmS) k (by omega) (by omega) + exact Finset.mem_image.2 ⟨c, hc, hck⟩ + have hbound := cols_add_rows_le hconn hne + have hw := Finset.card_le_card hcols + rw [Finset.card_range] at hw + intro p hp + have hp1 : p.1 ≤ S.sup Prod.fst := Finset.le_sup (f := Prod.fst) hp + have hrows : Finset.range (p.2 + 1) ⊆ S.image Prod.snd := by + intro k hk + rw [Finset.mem_range] at hk + obtain ⟨c, hc, hck⟩ := + exists_coord Prod.snd hsnd hq0S (hconn q0 hq0S p hp) k (by omega) (by omega) + exact Finset.mem_image.2 ⟨c, hc, hck⟩ + have hh := Finset.card_le_card hrows + rw [Finset.card_range] at hh + rw [box, Finset.mem_product, Finset.mem_range, Finset.mem_range] + omega + +/-- A computable count of the fixed polyominoes with `n` cells and width `w`: those +`n`-element subsets of the box that are normalized polyominoes of width `w`. -/ +def Tbox (n w : ℕ) : ℕ := (((box n w).powersetCard n).filter (IsPoly n w)).card + +theorem T_eq_Tbox (n w : ℕ) : T n w = Tbox n w := by + rw [T, Tbox, ← Set.ncard_coe_finset] + congr 1 + ext S + simp only [Set.mem_ofPred_eq, Finset.coe_filter, Finset.mem_powersetCard] + exact ⟨fun h => ⟨⟨subset_box h, h.1⟩, h⟩, fun h => h.2⟩ + +/-! ### The triangle read by rows -/ + +/-- Position `k` of row `n` (`1 ≤ k ≤ n`) and the following positions of rows `n + 1, …`: +returns the (row, column) of the `k`-th entry counted from the start of row `n`. -/ +def pos : ℕ → ℕ → ℕ → ℕ × ℕ + | 0, k, n => (n, k) + | fuel + 1, k, n => if k ≤ n then (n, k) else pos fuel (k - n) (n + 1) + +/-- A308359 as a sequence (offset `1`): the triangle `T(n, w)`, `1 ≤ w ≤ n`, read by rows. -/ +def a (k : ℕ) : ℕ := Tbox (pos k k 1).1 (pos k k 1).2 + +theorem pos_eq : ∀ (d j fuel w : ℕ), 1 ≤ w → w ≤ j + d → d < fuel → + pos fuel (w + ∑ i ∈ Finset.range d, (j + i)) j = (j + d, w) + | 0, j, fuel + 1, w, _, h2, _ => by simp [pos, show w ≤ j by omega] + | d + 1, j, fuel + 1, w, h1, h2, h3 => by + rw [Finset.sum_range_succ'] + have hs : ∑ i ∈ Finset.range d, (j + (i + 1)) = ∑ i ∈ Finset.range d, (j + 1 + i) := + Finset.sum_congr rfl fun i _ => by omega + rw [hs, pos, if_neg (by omega)] + rw [show w + (∑ i ∈ Finset.range d, (j + 1 + i) + (j + 0)) - j = + w + ∑ i ∈ Finset.range d, (j + 1 + i) by omega] + rw [pos_eq d (j + 1) fuel w h1 (by omega) (by omega)] + simp only [Prod.mk.injEq, and_true] + omega + +/-- `a` reads the triangle by rows: `a (n(n-1)/2 + w) = T(n, w)` for `1 ≤ w ≤ n`. -/ +theorem a_eq_T {n w : ℕ} (hw : 1 ≤ w) (hwn : w ≤ n) : a (n * (n - 1) / 2 + w) = T n w := by + have hsum : ∑ i ∈ Finset.range (n - 1), (1 + i) = n * (n - 1) / 2 := by + rw [← Finset.sum_range_id, show n = (n - 1) + 1 by omega, Finset.sum_range_succ'] + simp only [Nat.add_sub_cancel] + rw [Finset.sum_congr rfl fun i _ => (Nat.add_comm i 1).symm] + simp + have hge : n - 1 ≤ ∑ i ∈ Finset.range (n - 1), (1 + i) := by + rw [Finset.sum_add_distrib] + simp + have hk : pos (n * (n - 1) / 2 + w) (n * (n - 1) / 2 + w) 1 = (n, w) := by + have := pos_eq (n - 1) 1 (n * (n - 1) / 2 + w) w hw (by omega) (by omega) + rw [hsum, show 1 + (n - 1) = n by omega, Nat.add_comm w] at this + exact this + rw [a, hk, T_eq_Tbox] + +/-! ### The listed terms + +The check is split into four kernel computations (rows `1..5`, two halves of row `6`, the start +of row `7`) so that each one stays small in memory. -/ + +theorem a_data_rows_one_to_five : (List.range 15).map (fun i => a (i + 1)) = + [1, 1, 1, 1, 4, 1, 1, 9, 8, 1, 1, 18, 31, 12, 1] := by + decide +kernel + +theorem a_data_row_six_a : (List.range 3).map (fun i => a (i + 16)) = [1, 35, 95] := by + decide +kernel + +theorem a_data_row_six_b : (List.range 3).map (fun i => a (i + 19)) = [68, 16, 1] := by + decide +kernel + +theorem a_data_row_seven : (List.range 2).map (fun i => a (i + 22)) = [1, 66] := by + decide +kernel + +/-- The definition reproduces the first 23 listed terms: rows `1..6` and `T(7,1)`, `T(7,2)` +(kernel-checked, in the four pieces above). -/ +theorem a_data : (List.range 23).map (fun i => a (i + 1)) = + [1, 1, 1, 1, 4, 1, 1, 9, 8, 1, 1, 18, 31, 12, 1, 1, 35, 95, 68, 16, 1, 1, 66] := by + have e : (List.range 23).map (fun i => a (i + 1)) = + (List.range 15).map (fun i => a (i + 1)) ++ (List.range 3).map (fun i => a (i + 16)) ++ + (List.range 3).map (fun i => a (i + 19)) ++ (List.range 2).map (fun i => a (i + 22)) := by + simp only [List.range_succ, List.range_zero, List.map_cons, List.map_nil, List.nil_append, + List.cons_append] + rw [e, a_data_rows_one_to_five, a_data_row_six_a, a_data_row_six_b, a_data_row_seven] + rfl + +/-! ### The conjecture -/ + +/-- Conjecture (Mathar, A308359): for every `n ≥ 5`, the number of fixed polyominoes with `n` +cells and width `n - 2` is `T(n, n - 2) = 8n² - 51n + 86`. -/ +def statement : Prop := + ∀ n : ℕ, 5 ≤ n → (T n (n - 2) : ℤ) = 8 * (n : ℤ) ^ 2 - 51 * n + 86 + +end Math0.Statements.A308359 diff --git a/lean/Math0/Statements/OEIS/A320099.lean b/lean/Math0/Statements/OEIS/A320099.lean new file mode 100644 index 0000000..b9bdb52 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A320099.lean @@ -0,0 +1,678 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A320099: Kagey's order-10 recurrence for no-leaf subgraphs of the `5 × n` grid + +Source: https://oeis.org/A320099, Peter Kagey (author of the entry), Oct 05 2018 (FORMULA +section). Verbatim: +> Conjecture: a(n) = 103*a(n-1) + 1063*a(n-2) - 1873*a(n-3) - 20274*a(n-4) + 44071*a(n-5) - +> 10365*a(n-6) - 20208*a(n-7) + 5959*a(n-8) + 2300*a(n-9) - 500*a(n-10) for n > 10. + +The sequence (offset `1`) is "Number of no-leaf subgraphs of the 5 X n grid." with the comment +"Also, the number of ways to lay unit-length matchsticks on a 5 X n grid of points in such a way +that no end is "orphaned"." + +## Encoding + +* The `5 × n` grid is Mathlib's `pathGraph 5 □ pathGraph n` on `Fin 5 × Fin n` (row, column): + `(r, c)` and `(r', c')` are adjacent iff they agree in one coordinate and differ by `1` in the + other. It has `4n` vertical and `5(n - 1)` horizontal edges. +* A subgraph is identified with its edge set `S ⊆ E(grid n)`, all vertices being kept (a spanning + subgraph); a leaf is a vertex of degree exactly `1`, and the degree `deg S v` of `v` is the + number of edges of `S` containing `v` (the grid has no loops). So + `a n = #{S ⊆ E(grid n) | ∀ v, deg S v ≠ 1}`. This is the matchstick reading of the comment + (a matchstick is a grid edge, an orphaned end is a point touched by exactly one matchstick), + and it is the reading fixed by the data: `a(1) = 1`, since every nonempty edge set of the path + `5 × 1` has an end of degree `1` (if subgraphs could also omit vertices, the empty edge set + alone would give `2^5` subgraphs of the `5 × 1` grid). +* The OEIS offset is `1`; `a 0 = 1` (the empty grid) is not a term of the sequence. +* `a` is computable but far too slow for the kernel, so `a_eq_T` proves, for every `n`, that + `a n = (T ^ n) noH noH` for the `32 × 32` column transfer matrix `T` (states are the sets of + horizontal edges between consecutive columns, `T L R` counts the vertical-edge sets of a + column that leave no vertex of that column with degree `1`). The proof is a bijection between + edge sets and column data (`dec`, `enc`) that reads off every degree (`deg_dec`). Then + `a_eq_fastA` turns this into a list computation and `a_data` checks all `15` listed terms + `a(1), …, a(15)` with `decide +kernel`. +* `statement` asserts the recurrence for every `n > 10`, as stated, as an identity in `ℤ` + (because of the subtractions). The indices `n - k` (`1 ≤ k ≤ 10`) are natural-number + subtractions; for `n > 10` they are exact and `≥ 1`, so only terms of the sequence occur. + `statement_check_listed` checks (in the kernel) that the identity holds at `n = 11, …, 15`, + as a guard against transcription errors; this is not a proof of `statement`. +-/ + +namespace Math0.Statements.A320099 + +open Finset SimpleGraph + +/-- The `5 × n` grid graph: Mathlib's box product of the path graphs on `5` and on `n` vertices, +with vertex set `Fin 5 × Fin n` (row, column). Two vertices are adjacent iff they agree in one +coordinate and differ by `1` in the other. -/ +abbrev grid (n : ℕ) : SimpleGraph (Fin 5 × Fin n) := pathGraph 5 □ pathGraph n + +/-- Adjacency in the grid is decidable (unfolded through `boxProd_adj` and `pathGraph_adj`). -/ +instance (n : ℕ) : DecidableRel (grid n).Adj := fun x y => + decidable_of_iff + ((x.1.val + 1 = y.1.val ∨ y.1.val + 1 = x.1.val) ∧ x.2 = y.2 ∨ + (x.2.val + 1 = y.2.val ∨ y.2.val + 1 = x.2.val) ∧ x.1 = y.1) + (by simp only [boxProd_adj, pathGraph_adj]) + +/-- The degree of the vertex `v` in the (spanning) subgraph with edge set `S`: the number of edges +of `S` that contain `v`. -/ +def deg {n : ℕ} (S : Finset (Sym2 (Fin 5 × Fin n))) (v : Fin 5 × Fin n) : ℕ := #{e ∈ S | v ∈ e} + +/-- A320099: the number of no-leaf subgraphs of the `5 × n` grid, i.e. the number of edge sets +`S ⊆ E(grid n)` such that no vertex has degree exactly `1` in `S`. -/ +def a (n : ℕ) : ℕ := #{S ∈ (grid n).edgeFinset.powerset | ∀ v, deg S v ≠ 1} + +/-! ### The column transfer matrix + +The data check cannot enumerate the `2 ^ (9n - 5)` edge sets of the grid, so `a` is computed by +the standard column transfer matrix, and `a_eq_T` proves that this is correct for every `n`. -/ + +/-- A set of horizontal edges between two consecutive columns: `L r` says whether the edge in +row `r` is present. -/ +abbrev St := Fin 5 → Bool + +/-- A set of vertical edges inside one column: `V i` says whether the edge between rows `i` and +`i + 1` is present. -/ +abbrev Col := Fin 4 → Bool + +/-- The degree of the vertex in row `r` of a column, given the horizontal edges `L` to its left, +the vertical edges `V` of the column and the horizontal edges `R` to its right. -/ +def colDeg (L : St) (V : Col) (R : St) (r : Fin 5) : ℕ := + (if L r then 1 else 0) + (if R r then 1 else 0) + + #{i : Fin 4 | V i = true ∧ (i.castSucc = r ∨ i.succ = r)} + +/-- No vertex of the column is a leaf. -/ +def ok (L : St) (V : Col) (R : St) : Prop := ∀ r : Fin 5, colDeg L V R r ≠ 1 + +instance (L : St) (V : Col) (R : St) : Decidable (ok L V R) := by unfold ok; infer_instance + +/-- The `32 × 32` transfer matrix: `T L R` counts the vertical-edge sets of a column that make +no vertex of the column a leaf, given `L` and `R`. -/ +def T : Matrix St St ℕ := fun L R => #{V : Col | ok L V R} + +/-- Column data of a `5 × n` grid: for each column `c`, its vertical edges and the horizontal +edges from column `c` to column `c + 1`. -/ +abbrev ColSeq (n : ℕ) := Fin n → Col × St + +/-- No horizontal edges. -/ +def noH : St := fun _ => false + +/-- The horizontal edges to the left of column `c` (`s` for the first column). -/ +def prevH {n : ℕ} (s : St) (x : ColSeq n) (c : Fin n) : St := + if c.val = 0 then s else (x ⟨c.val - 1, by omega⟩).2 + +/-- The horizontal edges to the right of the last column (`s` if there are no columns). -/ +def lastH {n : ℕ} (s : St) (x : ColSeq n) : St := + if h : n = 0 then s else (x ⟨n - 1, by omega⟩).2 + +/-- Column data, starting with horizontal edges `s` and ending with `e`, with no leaf. -/ +def Good {n : ℕ} (s e : St) (x : ColSeq n) : Prop := + (∀ c, ok (prevH s x c) (x c).1 (x c).2) ∧ lastH s x = e + +instance {n : ℕ} (s e : St) : DecidablePred (@Good n s e) := fun x => by + unfold Good; infer_instance + +theorem cons_mk {n : ℕ} (y : Col × St) (x : ColSeq n) (k : ℕ) (hk : k + 1 < n + 1) : + (Fin.cons y x : ColSeq (n + 1)) ⟨k + 1, hk⟩ = x ⟨k, by omega⟩ := + Fin.cons_succ (α := fun _ => Col × St) y x ⟨k, by omega⟩ + +theorem prevH_cons_zero {n : ℕ} (s : St) (y : Col × St) (x : ColSeq n) : + prevH s (Fin.cons y x : ColSeq (n + 1)) 0 = s := by + simp [prevH] + +theorem prevH_cons_succ {n : ℕ} (s : St) (y : Col × St) (x : ColSeq n) (c : Fin n) : + prevH s (Fin.cons y x : ColSeq (n + 1)) c.succ = prevH y.2 x c := by + unfold prevH + rw [if_neg (by simp)] + rcases c with ⟨k, hk⟩ + rcases k with _ | k + · simp + · simp only [Fin.succ_mk, Nat.add_sub_cancel, Nat.add_one_ne_zero, if_false] + exact congrArg Prod.snd (cons_mk y x k _) + +theorem lastH_cons {n : ℕ} (s : St) (y : Col × St) (x : ColSeq n) : + lastH s (Fin.cons y x : ColSeq (n + 1)) = lastH y.2 x := by + unfold lastH + rw [dif_neg (by omega)] + rcases n with _ | n + · simp + · rw [dif_neg (by omega)] + exact congrArg Prod.snd (cons_mk y x n _) + +theorem good_cons {n : ℕ} (s e : St) (y : Col × St) (x : ColSeq n) : + Good s e (Fin.cons y x : ColSeq (n + 1)) ↔ ok s y.1 y.2 ∧ Good y.2 e x := by + unfold Good + rw [Fin.forall_fin_succ] + simp only [prevH_cons_zero, prevH_cons_succ, Fin.cons_zero, Fin.cons_succ, lastH_cons] + tauto + +theorem sum_cons (n : ℕ) (F : ColSeq (n + 1) → ℕ) : + ∑ f, F f = ∑ y : Col × St, ∑ g : ColSeq n, F (Fin.cons y g) := by + rw [← Fintype.sum_prod_type'] + exact Fintype.sum_equiv (Fin.consEquiv fun _ => Col × St).symm _ _ (fun f => by simp) + +theorem T_apply (L R : St) : T L R = #{V : Col | ok L V R} := rfl + +/-- Counting column data by the transfer matrix. -/ +theorem card_good : ∀ (n : ℕ) (s e : St), #{x : ColSeq n | Good s e x} = (T ^ n) s e + | 0, s, e => by + rw [pow_zero, Matrix.one_apply] + have h : ∀ x : ColSeq 0, Good s e x ↔ s = e := fun x => by simp [Good, lastH] + simp only [h] + by_cases hse : s = e <;> simp [hse] + | n + 1, s, e => by + rw [pow_succ', Matrix.mul_apply, Finset.card_filter, sum_cons] + simp only [good_cons, Fintype.sum_prod_type] + rw [Finset.sum_comm] + refine Finset.sum_congr rfl fun R _ => ?_ + have h1 : ∀ V : Col, (∑ x : ColSeq n, if ok s V R ∧ Good R e x then 1 else 0) = + if ok s V R then (T ^ n) R e else 0 := by + intro V + by_cases hV : ok s V R + · simp only [hV, true_and, if_true] + rw [← card_good n R e, Finset.card_filter] + · simp [hV] + simp only [h1] + rw [← Finset.sum_filter, Finset.sum_const, smul_eq_mul, T_apply] + + +/-! ### Graph side -/ + +section Graph + +variable {n : ℕ} + +/-- The vertical edge between rows `i` and `i + 1` of column `c`. -/ +def vE (i : Fin 4) (c : Fin n) : Sym2 (Fin 5 × Fin n) := s((i.castSucc, c), (i.succ, c)) + +/-- The horizontal edge between columns `c` and `c + 1` in row `r`. -/ +def hE (r : Fin 5) (c : Fin n) (h : c.val + 1 < n) : Sym2 (Fin 5 × Fin n) := + s((r, c), (r, ⟨c.val + 1, h⟩)) + +theorem mem_edges (u w : Fin 5 × Fin n) : s(u, w) ∈ (grid n).edgeFinset ↔ + ((u.1.val + 1 = w.1.val ∨ w.1.val + 1 = u.1.val) ∧ u.2.val = w.2.val) ∨ + ((u.2.val + 1 = w.2.val ∨ w.2.val + 1 = u.2.val) ∧ u.1.val = w.1.val) := by + rw [mem_edgeFinset, mem_edgeSet, boxProd_adj, pathGraph_adj, pathGraph_adj, Fin.ext_iff, + Fin.ext_iff] + +theorem vE_mem (i : Fin 4) (c : Fin n) : vE i c ∈ (grid n).edgeFinset := by + rw [vE, mem_edges]; simp + +theorem hE_mem (r : Fin 5) (c : Fin n) (h : c.val + 1 < n) : hE r c h ∈ (grid n).edgeFinset := by + rw [hE, mem_edges]; simp + +theorem vE_inj {i i' : Fin 4} {c c' : Fin n} : vE i c = vE i' c' ↔ i = i' ∧ c = c' := by + simp only [vE, Sym2.eq_iff, Prod.ext_iff, Fin.ext_iff, Fin.val_castSucc, Fin.val_succ] + omega + +theorem hE_inj {r r' : Fin 5} {c c' : Fin n} {h : c.val + 1 < n} {h' : c'.val + 1 < n} : + hE r c h = hE r' c' h' ↔ r = r' ∧ c = c' := by + simp only [hE, Sym2.eq_iff, Prod.ext_iff, Fin.ext_iff] + omega + +theorem vE_ne_hE (i : Fin 4) (c : Fin n) (r : Fin 5) (c' : Fin n) (h : c'.val + 1 < n) : + vE i c ≠ hE r c' h := by + simp only [vE, hE, ne_eq, Sym2.eq_iff, Prod.ext_iff, Fin.ext_iff, Fin.val_castSucc, + Fin.val_succ] + omega + +theorem edge_cases {e : Sym2 (Fin 5 × Fin n)} (he : e ∈ (grid n).edgeFinset) : + (∃ i c, e = vE i c) ∨ ∃ r c h, e = hE r c h := by + induction e using Sym2.ind with + | _ u w => + rw [mem_edges] at he + rcases u with ⟨⟨r, hr⟩, ⟨c, hc⟩⟩ + rcases w with ⟨⟨r', hr'⟩, ⟨c', hc'⟩⟩ + simp only at he + rcases he with ⟨h1 | h1, h2⟩ | ⟨h1 | h1, h2⟩ + · left + refine ⟨⟨r, by omega⟩, ⟨c, hc⟩, ?_⟩ + simp only [vE, Sym2.eq_iff, Prod.ext_iff, Fin.ext_iff, Fin.val_castSucc, Fin.val_succ, + true_and, and_true] + omega + · left + refine ⟨⟨r', by omega⟩, ⟨c, hc⟩, ?_⟩ + simp only [vE, Sym2.eq_iff, Prod.ext_iff, Fin.ext_iff, Fin.val_castSucc, Fin.val_succ, + true_and, and_true] + omega + · right + refine ⟨⟨r, hr⟩, ⟨c, hc⟩, by simp only; omega, ?_⟩ + simp only [hE, Sym2.eq_iff, Prod.ext_iff, Fin.ext_iff, true_and] + omega + · right + refine ⟨⟨r, hr⟩, ⟨c', hc'⟩, by simp only; omega, ?_⟩ + simp only [hE, Sym2.eq_iff, Prod.ext_iff, Fin.ext_iff, true_and, and_true] + omega + +theorem deg_eq_nbrs (S : Finset (Sym2 (Fin 5 × Fin n))) (v : Fin 5 × Fin n) : + deg S v = #{w | s(v, w) ∈ S} := by + unfold deg + symm + apply Finset.card_nbij (fun w => s(v, w)) + · intro w hw + simp only [coe_filter, mem_univ, true_and, Set.mem_ofPred_eq] at hw + simp only [coe_filter, Set.mem_ofPred_eq] + exact ⟨hw, Sym2.mem_mk_left _ _⟩ + · intro w _ w' _ h + exact Sym2.congr_right.mp h + · intro e he + simp only [coe_filter, Set.mem_ofPred_eq] at he + obtain ⟨hS, hv⟩ := he + refine ⟨Sym2.Mem.other hv, ?_, Sym2.other_spec hv⟩ + simp only [coe_filter, mem_univ, true_and, Set.mem_ofPred_eq] + rw [Sym2.other_spec hv] + exact hS + +theorem card_filter_single {α : Type*} [Fintype α] [DecidableEq α] (Q : α → Prop) + [DecidablePred Q] (w0 : α) (R : Prop) [Decidable R] (h : ∀ w, Q w ↔ w = w0 ∧ R) : + #{w | Q w} = if R then 1 else 0 := by + by_cases hR : R + · rw [if_pos hR, Finset.card_eq_one] + refine ⟨w0, ?_⟩ + ext w + simp [h, hR] + · rw [if_neg hR, Finset.card_eq_zero, Finset.filter_eq_empty_iff] + intro w _ hw + exact hR ((h w).1 hw).2 + +/-- Purely finite fact about one column. -/ +theorem col_count : ∀ (Q : Fin 4 → Bool) (r : Fin 5), + #{r' : Fin 5 | ∃ i : Fin 4, Q i = true ∧ + ((i.castSucc = r ∧ i.succ = r') ∨ (i.succ = r ∧ i.castSucc = r'))} = + #{i : Fin 4 | Q i = true ∧ (i.castSucc = r ∨ i.succ = r)} := by + decide + +open Classical in +/-- The column data of an edge set. -/ +noncomputable def dec (S : Finset (Sym2 (Fin 5 × Fin n))) : ColSeq n := fun c => + (fun i => decide (vE i c ∈ S), fun r => decide (∃ h, hE r c h ∈ S)) + +/-- The degree of a vertex, read off from the column data. -/ +theorem deg_dec {S : Finset (Sym2 (Fin 5 × Fin n))} (hS : S ⊆ (grid n).edgeFinset) + (r : Fin 5) (c : Fin n) : + deg S (r, c) = colDeg (prevH noH (dec S) c) (dec S c).1 (dec S c).2 r := by + classical + have adj : ∀ w : Fin 5 × Fin n, s((r, c), w) ∈ S → + ((r.val + 1 = w.1.val ∨ w.1.val + 1 = r.val) ∧ c.val = w.2.val) ∨ + ((c.val + 1 = w.2.val ∨ w.2.val + 1 = c.val) ∧ r.val = w.1.val) := + fun w hw => (mem_edges _ _).1 (hS hw) + rw [deg_eq_nbrs] + -- split the neighbours by column + have hsplit : #{w | s((r, c), w) ∈ S} = + #{w | s((r, c), w) ∈ S ∧ w.2.val = c.val} + + #{w | s((r, c), w) ∈ S ∧ w.2.val + 1 = c.val} + + #{w | s((r, c), w) ∈ S ∧ c.val + 1 = w.2.val} := by + simp only [Finset.card_filter, ← Finset.sum_add_distrib] + refine Finset.sum_congr rfl fun w _ => ?_ + by_cases hw : s((r, c), w) ∈ S + · have := adj w hw + simp only [hw, true_and, if_true] + split_ifs <;> omega + · simp [hw] + -- same column + have h1 : #{w | s((r, c), w) ∈ S ∧ w.2.val = c.val} = + #{i : Fin 4 | (dec S c).1 i = true ∧ (i.castSucc = r ∨ i.succ = r)} := by + rw [← col_count] + apply Finset.card_nbij' Prod.fst (fun r' => (r', c)) + · intro w hw + simp only [coe_filter, mem_univ, true_and, Set.mem_ofPred_eq] at hw ⊢ + obtain ⟨hw, hc⟩ := hw + have hwc : w = (w.1, c) := Prod.ext rfl (Fin.ext hc) + rw [hwc] at hw + have := adj _ hw + simp only at this + rcases this with ⟨h | h, -⟩ | ⟨h, -⟩ + · refine ⟨⟨r.val, by omega⟩, ?_, Or.inl ⟨Fin.ext rfl, Fin.ext (by simp; omega)⟩⟩ + simp only [dec, decide_eq_true_eq] + convert hw using 1 + simp only [vE, Sym2.eq_iff, Prod.ext_iff, Fin.ext_iff, Fin.val_castSucc, Fin.val_succ, + true_and, and_true] + omega + · refine ⟨⟨w.1.val, by omega⟩, ?_, Or.inr ⟨Fin.ext (by simp; omega), Fin.ext rfl⟩⟩ + simp only [dec, decide_eq_true_eq] + convert hw using 1 + simp only [vE, Sym2.eq_iff, Prod.ext_iff, Fin.ext_iff, Fin.val_castSucc, Fin.val_succ, + true_and, and_true] + omega + · omega + · intro r' hr' + simp only [coe_filter, mem_univ, true_and, Set.mem_ofPred_eq, and_true] at hr' ⊢ + obtain ⟨i, hi, hor⟩ := hr' + simp only [dec, decide_eq_true_eq] at hi + convert hi using 1 + simp only [vE, Sym2.eq_iff, Prod.ext_iff, Fin.ext_iff, Fin.val_castSucc, Fin.val_succ, + and_true] at hor ⊢ + omega + · intro w hw + simp only [coe_filter, mem_univ, true_and, Set.mem_ofPred_eq] at hw + exact Prod.ext rfl (Fin.ext hw.2.symm) + · intro r' _ + rfl + -- left neighbour + have h2 : #{w | s((r, c), w) ∈ S ∧ w.2.val + 1 = c.val} = + if prevH noH (dec S) c r then 1 else 0 := by + by_cases hc0 : c.val = 0 + · have : prevH noH (dec S) c = noH := by simp [prevH, hc0] + rw [this, noH, if_neg (by simp), Finset.card_eq_zero, Finset.filter_eq_empty_iff] + intro w _ hw + omega + · obtain ⟨k, hk⟩ : ∃ k, c.val = k + 1 := ⟨c.val - 1, by omega⟩ + have hkn : k < n := by omega + have hp : prevH noH (dec S) c r = decide (∃ h, hE r ⟨k, hkn⟩ h ∈ S) := by + simp only [prevH, dec, hk, Nat.add_sub_cancel, Nat.add_one_ne_zero, if_false] + rw [hp] + simp only [decide_eq_true_eq] + apply card_filter_single _ (r, ⟨k, hkn⟩) + intro w + have key : ∀ h, hE r ⟨k, hkn⟩ h = s((r, c), (r, ⟨k, hkn⟩)) := by + intro h + simp only [hE, Sym2.eq_iff, Prod.ext_iff, Fin.ext_iff, true_and] + omega + constructor + · rintro ⟨hw, hwc⟩ + have := adj w hw + have hw0 : w = (r, ⟨k, hkn⟩) := by + ext <;> simp <;> omega + subst hw0 + exact ⟨rfl, by have := c.isLt; omega, by rw [key]; exact hw⟩ + · rintro ⟨rfl, h, hm⟩ + rw [key] at hm + exact ⟨hm, by show k + 1 = c.val; omega⟩ + -- right neighbour + have h3 : #{w | s((r, c), w) ∈ S ∧ c.val + 1 = w.2.val} = + if (dec S c).2 r then 1 else 0 := by + simp only [dec, decide_eq_true_eq] + by_cases hcn : c.val + 1 < n + · have hiff : (∃ h, hE r c h ∈ S) ↔ s((r, c), (r, ⟨c.val + 1, hcn⟩)) ∈ S := + ⟨fun ⟨_, h⟩ => h, fun h => ⟨hcn, h⟩⟩ + rw [if_congr hiff rfl rfl] + apply card_filter_single _ (r, ⟨c.val + 1, hcn⟩) + intro w + constructor + · rintro ⟨hw, hwc⟩ + have := adj w hw + have hw0 : w = (r, ⟨c.val + 1, hcn⟩) := by + ext <;> simp <;> omega + subst hw0 + exact ⟨rfl, hw⟩ + · rintro ⟨rfl, hm⟩ + exact ⟨hm, rfl⟩ + · rw [if_neg (fun ⟨h, _⟩ => hcn h), Finset.card_eq_zero, Finset.filter_eq_empty_iff] + intro w _ hw + have := w.2.isLt + omega + rw [hsplit, h1, h2, h3, colDeg] + omega + + +open Classical in +/-- The edge set with the given column data. -/ +noncomputable def enc (x : ColSeq n) : Finset (Sym2 (Fin 5 × Fin n)) := + (grid n).edgeFinset.filter fun e => + (∃ i c, e = vE i c ∧ (x c).1 i = true) ∨ ∃ r c h, e = hE r c h ∧ (x c).2 r = true + +theorem enc_subset (x : ColSeq n) : enc x ⊆ (grid n).edgeFinset := by + classical + unfold enc + exact Finset.filter_subset _ _ + +theorem enc_dec {S : Finset (Sym2 (Fin 5 × Fin n))} (hS : S ⊆ (grid n).edgeFinset) : + enc (dec S) = S := by + classical + ext e + unfold enc + rw [Finset.mem_filter] + constructor + · rintro ⟨-, ⟨i, c, rfl, hi⟩ | ⟨r, c, h, rfl, hr⟩⟩ + · simpa [dec] using hi + · simp only [dec, decide_eq_true_eq] at hr + obtain ⟨_, hm⟩ := hr + exact hm + · intro he + refine ⟨hS he, ?_⟩ + rcases edge_cases (hS he) with ⟨i, c, rfl⟩ | ⟨r, c, h, rfl⟩ + · exact Or.inl ⟨i, c, rfl, by simpa [dec] using he⟩ + · exact Or.inr ⟨r, c, h, rfl, by simp only [dec, decide_eq_true_eq]; exact ⟨h, he⟩⟩ + +theorem dec_enc {x : ColSeq n} (hx : lastH noH x = noH) : dec (enc x) = x := by + classical + funext c + refine Prod.ext (funext fun i => ?_) (funext fun r => ?_) + · have : vE i c ∈ enc x ↔ (x c).1 i = true := by + unfold enc + rw [Finset.mem_filter] + constructor + · rintro ⟨-, ⟨i', c', h, hi⟩ | ⟨r', c', h', h, -⟩⟩ + · obtain ⟨rfl, rfl⟩ := vE_inj.1 h + exact hi + · exact absurd h (vE_ne_hE _ _ _ _ _) + · intro hi + exact ⟨vE_mem i c, Or.inl ⟨i, c, rfl, hi⟩⟩ + simp only [dec] + rw [Bool.eq_iff_iff, decide_eq_true_iff] + exact this + · have : (∃ h, hE r c h ∈ enc x) ↔ (x c).2 r = true := by + by_cases hcn : c.val + 1 < n + · unfold enc + constructor + · rintro ⟨h, hm⟩ + rw [Finset.mem_filter] at hm + rcases hm with ⟨-, ⟨i', c', h', -⟩ | ⟨r', c', h'', h', hr⟩⟩ + · exact absurd h'.symm (vE_ne_hE _ _ _ _ _) + · obtain ⟨rfl, rfl⟩ := hE_inj.1 h' + exact hr + · intro hr + exact ⟨hcn, Finset.mem_filter.2 ⟨hE_mem r c hcn, Or.inr ⟨r, c, hcn, rfl, hr⟩⟩⟩ + · have hlast : (x c).2 = noH := by + rw [← hx] + unfold lastH + rw [dif_neg (by have := c.isLt; omega)] + congr 2 + ext + simp only + have := c.isLt + omega + rw [hlast] + simp only [noH, Bool.false_eq_true, iff_false] + rintro ⟨h, -⟩ + exact hcn h + simp only [dec] + rw [Bool.eq_iff_iff, decide_eq_true_iff] + exact this + +theorem lastH_dec (S : Finset (Sym2 (Fin 5 × Fin n))) : lastH noH (dec S) = noH := by + classical + unfold lastH + split_ifs with hn + · rfl + · funext r + simp only [dec, noH, decide_eq_false_iff_not] + rintro ⟨h, -⟩ + omega + +/-- `a n` counts the sequences of column data that are `Good` from `noH` to `noH`. -/ +theorem a_eq_card_good (n : ℕ) : a n = #{x : ColSeq n | Good noH noH x} := by + classical + unfold a + apply Finset.card_nbij' dec enc + · intro S hS + simp only [coe_filter, mem_powerset, Set.mem_ofPred_eq, mem_univ, true_and] at hS ⊢ + refine ⟨fun c r => ?_, lastH_dec S⟩ + rw [← deg_dec hS.1] + exact hS.2 (r, c) + · intro x hx + simp only [coe_filter, mem_powerset, Set.mem_ofPred_eq, mem_univ, true_and] at hx ⊢ + refine ⟨enc_subset x, fun v => ?_⟩ + rw [deg_dec (enc_subset x), dec_enc hx.2] + exact hx.1 v.2 v.1 + · intro S hS + simp only [coe_filter, mem_powerset, Set.mem_ofPred_eq] at hS + exact enc_dec hS.1 + · intro x hx + simp only [coe_filter, Set.mem_ofPred_eq, mem_univ, true_and] at hx + exact dec_enc hx.2 + +/-- The transfer-matrix formula for `a`, valid for every `n`. -/ +theorem a_eq_T (n : ℕ) : a n = (T ^ n) noH noH := by + rw [a_eq_card_good, card_good] +end Graph + +/-! ### Fast evaluation -/ + +/-- All `32` sets of horizontal edges between two columns, starting with `noH`. -/ +def states : List St := (List.finRange 32).map (fun k r => k.val.testBit r.val) + +theorem states_nodup : states.Nodup := by decide +kernel + +theorem mem_states : ∀ L : St, L ∈ states := by decide +kernel + +theorem states_eq_cons : states = noH :: states.tail := by decide +kernel + +theorem sum_states (f : St → ℕ) : ∑ L, f L = (states.map f).sum := by + rw [← List.sum_toFinset f states_nodup] + congr 1 + ext L + simp [mem_states] + +/-- The columns of `T` (indexed as in `states`), as a literal table. -/ +def Mcols : List (List ℕ) := + [[1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 2, + 0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3], + [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3, + 1, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 5], + [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 3], + [1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 3, 2, 4, + 1, 2, 1, 2, 2, 3, 2, 4, 2, 3, 2, 4, 3, 5, 3, 6], + [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, + 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3, 2, 2, 2, 4], + [1, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, + 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 5, 2, 4, 4, 6], + [1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, + 1, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 3, 2, 4, 4, 4], + [1, 2, 1, 2, 2, 3, 2, 4, 2, 3, 2, 4, 2, 3, 2, 4, + 2, 3, 2, 4, 2, 3, 2, 4, 3, 5, 3, 6, 4, 6, 4, 8], + [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3, + 1, 1, 1, 2, 1, 2, 2, 3, 1, 1, 1, 2, 1, 2, 2, 3], + [1, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 5, + 1, 2, 2, 3, 2, 3, 3, 5, 1, 2, 2, 3, 2, 3, 3, 5], + [1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 3, + 1, 2, 2, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 3, 3, 3], + [1, 2, 1, 2, 2, 3, 2, 4, 2, 3, 2, 4, 3, 5, 3, 6, + 2, 3, 2, 4, 3, 5, 3, 6, 2, 3, 2, 4, 3, 5, 3, 6], + [1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3, 2, 2, 2, 4, + 1, 2, 2, 3, 2, 2, 2, 4, 1, 2, 2, 3, 2, 2, 2, 4], + [1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 5, 2, 4, 4, 6, + 2, 3, 3, 5, 2, 4, 4, 6, 2, 3, 3, 5, 2, 4, 4, 6], + [1, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 3, 2, 4, 4, 4, + 2, 3, 3, 3, 2, 4, 4, 4, 2, 3, 3, 3, 2, 4, 4, 4], + [2, 3, 2, 4, 2, 3, 2, 4, 3, 5, 3, 6, 4, 6, 4, 8, + 3, 5, 3, 6, 4, 6, 4, 8, 3, 5, 3, 6, 4, 6, 4, 8], + [0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3, + 1, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 5], + [1, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 5, + 1, 2, 2, 3, 2, 3, 3, 5, 2, 3, 3, 5, 3, 5, 5, 8], + [1, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 3, + 1, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 3, 5, 5, 5], + [1, 2, 1, 2, 2, 3, 2, 4, 2, 3, 2, 4, 3, 5, 3, 6, + 2, 3, 2, 4, 3, 5, 3, 6, 3, 5, 3, 6, 5, 8, 5, 10], + [1, 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3, 2, 2, 2, 4, + 1, 2, 2, 3, 2, 2, 2, 4, 2, 3, 3, 5, 3, 3, 3, 6], + [1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 5, 2, 4, 4, 6, + 2, 3, 3, 5, 2, 4, 4, 6, 3, 5, 5, 8, 3, 6, 6, 9], + [1, 2, 2, 2, 1, 2, 2, 2, 2, 3, 3, 3, 2, 4, 4, 4, + 2, 3, 3, 3, 2, 4, 4, 4, 3, 5, 5, 5, 3, 6, 6, 6], + [2, 3, 2, 4, 2, 3, 2, 4, 3, 5, 3, 6, 4, 6, 4, 8, + 3, 5, 3, 6, 4, 6, 4, 8, 5, 8, 5, 10, 6, 9, 6, 12], + [1, 1, 1, 2, 1, 2, 2, 3, 1, 1, 1, 2, 1, 2, 2, 3, + 1, 2, 2, 3, 2, 3, 3, 5, 2, 2, 2, 4, 2, 4, 4, 6], + [1, 2, 2, 3, 2, 3, 3, 5, 1, 2, 2, 3, 2, 3, 3, 5, + 2, 3, 3, 5, 3, 5, 5, 8, 2, 4, 4, 6, 4, 6, 6, 10], + [1, 2, 2, 2, 2, 3, 3, 3, 1, 2, 2, 2, 2, 3, 3, 3, + 2, 3, 3, 3, 3, 5, 5, 5, 2, 4, 4, 4, 4, 6, 6, 6], + [2, 3, 2, 4, 3, 5, 3, 6, 2, 3, 2, 4, 3, 5, 3, 6, + 3, 5, 3, 6, 5, 8, 5, 10, 4, 6, 4, 8, 6, 10, 6, 12], + [1, 2, 2, 3, 2, 2, 2, 4, 1, 2, 2, 3, 2, 2, 2, 4, + 2, 3, 3, 5, 3, 3, 3, 6, 2, 4, 4, 6, 4, 4, 4, 8], + [2, 3, 3, 5, 2, 4, 4, 6, 2, 3, 3, 5, 2, 4, 4, 6, + 3, 5, 5, 8, 3, 6, 6, 9, 4, 6, 6, 10, 4, 8, 8, 12], + [2, 3, 3, 3, 2, 4, 4, 4, 2, 3, 3, 3, 2, 4, 4, 4, + 3, 5, 5, 5, 3, 6, 6, 6, 4, 6, 6, 6, 4, 8, 8, 8], + [3, 5, 3, 6, 4, 6, 4, 8, 3, 5, 3, 6, 4, 6, 4, 8, + 5, 8, 5, 10, 6, 9, 6, 12, 6, 10, 6, 12, 8, 12, 8, 16]] + +theorem Mcols_eq : Mcols = states.map (fun R => states.map (fun L => T L R)) := by + decide +kernel + +/-- Dot product of two lists. -/ +def dot (u w : List ℕ) : ℕ := (List.zipWith (· * ·) u w).sum + +/-- One transfer-matrix step on a row vector. -/ +def step (v : List ℕ) : List ℕ := Mcols.map (dot v) + +/-- The row of the identity matrix at `noH`. -/ +def row0 : List ℕ := 1 :: List.replicate 31 0 + +theorem row0_eq : row0 = states.map (fun R => if noH = R then 1 else 0) := by decide +kernel + +/-- `fastRow n` is the row of `T ^ n` at `noH`. -/ +def fastRow : ℕ → List ℕ + | 0 => row0 + | n + 1 => step (fastRow n) + +/-- Fast evaluator of `a`. -/ +def fastA (n : ℕ) : ℕ := (fastRow n).headD 0 + +theorem fastRow_eq (n : ℕ) : fastRow n = states.map (fun R => (T ^ n) noH R) := by + induction n with + | zero => + rw [fastRow, row0_eq] + simp [Matrix.one_apply] + | succ n ih => + rw [fastRow, ih, step, Mcols_eq, List.map_map] + refine List.map_congr_left fun R _ => ?_ + simp only [Function.comp, dot, List.zipWith_map, List.zipWith_self] + rw [pow_succ, Matrix.mul_apply, sum_states] + +/-- The fast evaluator computes `a`, for every `n`. -/ +theorem a_eq_fastA (n : ℕ) : a n = fastA n := by + rw [a_eq_T, fastA, fastRow_eq, states_eq_cons, List.map_cons, List.headD_cons] + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all `15` listed +terms `a(1), …, a(15)`. -/ +theorem a_data : (List.range 15).map (fun i => a (i + 1)) = + [1, 50, 5193, 583199, 65485654, 7354266811, 825905301851, 92751581627976, + 10416273692997679, 1169777980482365913, 131369486228240893660, + 14753177269494392259423, 1656824927874469183283433, 186066281959642930757881316, + 20895787297635543757965741097] := by + simp only [a_eq_fastA] + decide +kernel + + +/-- Kagey's conjecture: for every `n > 10`, +`a(n) = 103*a(n-1) + 1063*a(n-2) - 1873*a(n-3) - 20274*a(n-4) + 44071*a(n-5) - 10365*a(n-6) +- 20208*a(n-7) + 5959*a(n-8) + 2300*a(n-9) - 500*a(n-10)` (an identity of integers). -/ +def statement : Prop := + ∀ n : ℕ, 10 < n → + (a n : ℤ) = 103 * (a (n - 1) : ℤ) + 1063 * (a (n - 2) : ℤ) - 1873 * (a (n - 3) : ℤ) + - 20274 * (a (n - 4) : ℤ) + 44071 * (a (n - 5) : ℤ) - 10365 * (a (n - 6) : ℤ) + - 20208 * (a (n - 7) : ℤ) + 5959 * (a (n - 8) : ℤ) + 2300 * (a (n - 9) : ℤ) + - 500 * (a (n - 10) : ℤ) + +/-- Sanity check of the transcription (not a proof of `statement`): the identity holds for +`n = 11, …, 15`, the values of `n > 10` within the listed data. -/ +theorem statement_check_listed : ∀ n : ℕ, 10 < n → n ≤ 15 → + (a n : ℤ) = 103 * (a (n - 1) : ℤ) + 1063 * (a (n - 2) : ℤ) - 1873 * (a (n - 3) : ℤ) + - 20274 * (a (n - 4) : ℤ) + 44071 * (a (n - 5) : ℤ) - 10365 * (a (n - 6) : ℤ) + - 20208 * (a (n - 7) : ℤ) + 5959 * (a (n - 8) : ℤ) + 2300 * (a (n - 9) : ℤ) + - 500 * (a (n - 10) : ℤ) := by + intro n h1 h2 + simp only [a_eq_fastA] + interval_cases n <;> decide +kernel + +end Math0.Statements.A320099 diff --git a/lean/Math0/Statements/OEIS/A323695.lean b/lean/Math0/Statements/OEIS/A323695.lean new file mode 100644 index 0000000..7df13b0 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A323695.lean @@ -0,0 +1,197 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A323695: parity of the coefficients of `∑ x^n (1 - x^(n+1))^n / (1 + x^(n+1))^(n+1)` + +Source: https://oeis.org/A323695, _Paul D. Hanna_, Feb 23 2019. Verbatim: +> Odd terms occur only at n = k*(k+2) for k >= 0 (conjecture); + +The entry's definition (offset 0): "G.f.: Sum_{n>=0} x^n * (1 - x^(n+1))^n / (1 + x^(n+1))^(n+1)", +i.e. `a(N)` is the coefficient of `x^N` in this power series. + +## Encoding + +* `summand m : ℤ⟦X⟧` is `X^m * (1 - X^(m+1))^m * ((1 + X^(m+1))^(m+1))⁻¹`, the inverse being + `PowerSeries.invOfUnit _ 1` (the factor has constant coefficient `1`); `summand_spec` records + the defining identity `(1 + X^(m+1))^(m+1) * summand m = X^m * (1 - X^(m+1))^m`. +* `summand m` is divisible by `X^m` (`coeff_summand_of_lt`), so the series converges + `X`-adically. `A` is its sum, defined coefficientwise as the finite sum over `m ≤ N`, and + `hasSum_summand` proves `HasSum summand A` in the product (coefficientwise) topology on `ℤ⟦X⟧`. +* `a N` is defined by an explicit finite formula `coeffA N`, obtained by expanding + `(1 - X^(m+1))^m = ∑_i (-1)^i C(m,i) X^((m+1) i)` with the binomial theorem and + `(1 + X^(m+1))^(-(m+1)) = ∑_j (-1)^j C(m+j, m) X^((m+1) j)`. The theorem `a_eq_coeff` proves + (in Lean) that `a N = coeff N A`, so `a` is exactly the OEIS definition; the explicit formula + only serves to make `a` computable for the kernel-checked data. Only the summands with + `m + 1 ∣ N + 1` can contribute (`term_eq_zero`), and `coeffA` skips the others to make kernel + evaluation fast; `coeff_A` accounts for this. The terms are signed (keyword `sign`), so + `a : ℕ → ℤ`, and `a_data` checks all 121 terms listed in the entry's data (`n = 0..120`). +* Reading of the conjecture: "odd terms occur only at `n = k*(k+2)`" is the one-directional + claim `Odd (a n) → ∃ k, n = k * (k + 2)` for every `n ≥ 0` (offset 0), with `k : ℕ` + (so `k ≥ 0`). The converse, `a(n*(n+2)) = 1 (mod 2)`, is listed separately in the entry's + formula section (not marked as a conjecture there) and is not part of `statement`. +-/ + +namespace Math0.Statements.A323695 + +open PowerSeries + +/-! ### The generating function -/ + +/-- The `m`-th summand `x^m * (1 - x^(m+1))^m / (1 + x^(m+1))^(m+1)` of the g.f., in `ℤ⟦X⟧`. -/ +noncomputable def summand (m : ℕ) : PowerSeries ℤ := + X ^ m * (1 - X ^ (m + 1)) ^ m * invOfUnit ((1 + X ^ (m + 1)) ^ (m + 1)) 1 + +theorem constantCoeff_one_add_X_pow_pow (b d : ℕ) (hb : b ≠ 0) : + constantCoeff ((1 + X ^ b : PowerSeries ℤ) ^ d) = ((1 : ℤˣ) : ℤ) := by + simp [map_pow, zero_pow hb] + +/-- `summand m` is the quotient `x^m * (1 - x^(m+1))^m / (1 + x^(m+1))^(m+1)`. -/ +theorem summand_spec (m : ℕ) : + (1 + X ^ (m + 1)) ^ (m + 1) * summand m = X ^ m * (1 - X ^ (m + 1)) ^ m := by + rw [summand, mul_comm, mul_assoc, invOfUnit_mul _ _ + (constantCoeff_one_add_X_pow_pow _ _ (by omega)), mul_one] + +/-- `summand m` is divisible by `X ^ m`. -/ +theorem coeff_summand_of_lt {N m : ℕ} (h : N < m) : coeff N (summand m) = 0 := by + rw [summand, mul_assoc, coeff_X_pow_mul', if_neg (by omega)] + +/-- The generating function `A(x) = ∑_{m ≥ 0} summand m`, defined coefficientwise +(the coefficient of `x^N` only involves the summands with `m ≤ N`, see `coeff_summand_of_lt`). -/ +noncomputable def A : PowerSeries ℤ := + mk fun N => ∑ m ∈ Finset.range (N + 1), coeff N (summand m) + +open scoped PowerSeries.WithPiTopology in +/-- `A` is the sum of the family `summand` in the coefficientwise topology of `ℤ⟦X⟧`. -/ +theorem hasSum_summand : HasSum summand A := by + rw [PowerSeries.WithPiTopology.hasSum_iff_hasSum_coeff] + intro N + rw [A, coeff_mk] + apply hasSum_sum_of_ne_finset_zero + intro n hn + rw [Finset.mem_range, not_lt] at hn + exact coeff_summand_of_lt (by omega) + +/-! ### An explicit formula for the coefficients -/ + +/-- Binomial coefficient via descending factorials (fast in the kernel); equals `Nat.choose`. -/ +def binom (n k : ℕ) : ℕ := n.descFactorial k / k.factorial + +theorem binom_eq_choose (n k : ℕ) : binom n k = n.choose k := + (Nat.choose_eq_descFactorial_div_factorial n k).symm + +/-- Contribution of `(-1)^i C(m,i) X^((m+1) i)` (from `(1 - X^(m+1))^m`) to the coefficient of +`x^N` in `summand m`: with `k = (m+1) i + m`, it is `(-1)^i C(m,i) (-1)^q C(m+q, m)` when +`N - k = (m+1) q`, and `0` otherwise. -/ +def term (N m i : ℕ) : ℤ := + if (m + 1) * i + m ≤ N ∧ (N - ((m + 1) * i + m)) % (m + 1) = 0 then + (-1) ^ i * (binom m i : ℤ) * + ((-1) ^ ((N - ((m + 1) * i + m)) / (m + 1)) * + (binom (m + (N - ((m + 1) * i + m)) / (m + 1)) m : ℤ)) + else 0 + +/-- `term N m i` vanishes unless `m + 1` divides `N + 1`. -/ +theorem term_eq_zero {N m : ℕ} (h : (N + 1) % (m + 1) ≠ 0) (i : ℕ) : term N m i = 0 := by + unfold term + rw [if_neg] + rintro ⟨h1, h2⟩ + apply h + apply Nat.mod_eq_zero_of_dvd + have h3 : N + 1 = (N - ((m + 1) * i + m)) + (m + 1) * (i + 1) := by + rw [mul_add, mul_one]; omega + rw [h3] + exact dvd_add (Nat.dvd_of_mod_eq_zero h2) (dvd_mul_right _ _) + +/-- The coefficient of `x^N` in the g.f., by the explicit formula (see `coeff_A`). Only the +summands with `m + 1 ∣ N + 1` contribute (`term_eq_zero`); the guard only speeds up evaluation. -/ +def coeffA (N : ℕ) : ℤ := + ∑ m ∈ Finset.range (N + 1), + if (N + 1) % (m + 1) = 0 then ∑ i ∈ Finset.range (m + 1), term N m i else 0 + +/-- A323695: `a N` is the coefficient of `x^N` in +`∑_{m ≥ 0} x^m * (1 - x^(m+1))^m / (1 + x^(m+1))^(m+1)` (see `a_eq_coeff`). -/ +def a (N : ℕ) : ℤ := coeffA N + +/-- `(1 + X^b)^(d+1) * ∑_j (-1)^j C(d+j, d) X^(b j) = 1`. -/ +theorem one_add_X_pow_pow_mul (b d : ℕ) (hb : b ≠ 0) : + (1 + X ^ b : PowerSeries ℤ) ^ (d + 1) * + expand b hb (evalNegHom (mk fun j => (Nat.choose (d + j) d : ℤ))) = 1 := by + have h := congrArg (fun f => expand b hb (evalNegHom f)) + (mk_add_choose_mul_one_sub_pow_eq_one (S := ℤ) d) + simp only [map_mul, map_pow, map_sub, map_one, evalNegHom_X, sub_neg_eq_add] at h + rw [mul_comm] + simpa [add_comm] using h + +theorem invOfUnit_one_add_X_pow_pow (b d : ℕ) (hb : b ≠ 0) : + invOfUnit ((1 + X ^ b : PowerSeries ℤ) ^ (d + 1)) 1 = + expand b hb (evalNegHom (mk fun j => (Nat.choose (d + j) d : ℤ))) := by + set φ : PowerSeries ℤ := (1 + X ^ b) ^ (d + 1) + set E := expand b hb (evalNegHom (mk fun j => (Nat.choose (d + j) d : ℤ))) + have h1 : φ * invOfUnit φ 1 = 1 := + mul_invOfUnit _ _ (constantCoeff_one_add_X_pow_pow _ _ hb) + have h2 : φ * E = 1 := one_add_X_pow_pow_mul b d hb + calc invOfUnit φ 1 = (E * φ) * invOfUnit φ 1 := by rw [mul_comm E, h2, one_mul] + _ = E := by rw [mul_assoc, h1, mul_one] + +theorem coeff_E (b d r : ℕ) (hb : b ≠ 0) : + coeff r (expand b hb (evalNegHom (mk fun j => (Nat.choose (d + j) d : ℤ)))) = + if r % b = 0 then (-1) ^ (r / b) * (Nat.choose (d + r / b) d : ℤ) else 0 := by + rw [coeff_expand] + by_cases h : b ∣ r + · rw [if_pos h, if_pos (Nat.mod_eq_zero_of_dvd h)] + simp [evalNegHom] + · rw [if_neg h, if_neg (fun h' => h (Nat.dvd_of_mod_eq_zero h'))] + +/-- The explicit formula for the coefficients of a summand. -/ +theorem coeff_summand (N m : ℕ) : + coeff N (summand m) = ∑ i ∈ Finset.range (m + 1), term N m i := by + rw [summand, invOfUnit_one_add_X_pow_pow _ _ (by omega), sub_eq_neg_add, add_pow, + Finset.mul_sum, Finset.sum_mul, map_sum] + refine Finset.sum_congr rfl fun i _ => ?_ + have hE : ∀ E : PowerSeries ℤ, + X ^ m * ((-X ^ (m + 1)) ^ i * 1 ^ (m - i) * ((m.choose i : ℕ) : PowerSeries ℤ)) * E = + C ((-1) ^ i * (m.choose i : ℤ)) * (X ^ ((m + 1) * i + m) * E) := by + intro E + simp only [map_mul, map_pow, map_neg, map_one, map_natCast] + ring + rw [hE, coeff_C_mul, coeff_X_pow_mul', coeff_E _ _ _ (by omega), term] + simp only [binom_eq_choose] + split_ifs with h1 h2 h3 h3 h3 + · ring + · exact absurd ⟨h1, h2⟩ h3 + · exact absurd h3.2 h2 + · rw [mul_zero] + · exact absurd h3.1 h1 + · rw [mul_zero] + +/-- The coefficients of the g.f. are given by `coeffA`. -/ +theorem coeff_A (N : ℕ) : coeff N A = coeffA N := by + rw [A, coeff_mk, coeffA] + refine Finset.sum_congr rfl fun m _ => ?_ + rw [coeff_summand] + split_ifs with h + · rfl + · exact Finset.sum_eq_zero fun i _ => term_eq_zero h i + +/-- `a N` is the coefficient of `x^N` in the g.f. `A`, as in OEIS. -/ +theorem a_eq_coeff (N : ℕ) : a N = coeff N A := by + rw [coeff_A, a] + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 121).map (fun i => a (i + 0)) = + [1, 0, 2, -3, 2, 0, 2, -14, 15, 0, 2, -22, 2, 0, 84, -93, 2, 0, 2, -38, 172, 0, 2, -508, 323, + 0, 292, -54, 2, 0, 2, -1212, 444, 0, 2580, -1753, 2, 0, 628, -2396, 2, 0, 2, -86, 8142, 0, 2, + -18554, 8991, 0, 1092, -102, 2, 0, 16724, -6716, 1372, 0, 2, -44844, 2, 0, 81846, -58747, + 33284, 0, 2, -134, 2028, 0, 2, -127882, 2, 0, 62326, -150, 268492, 0, 2, -468282, 268541, 0, + 2, -249196, 100100, 0, 3252, -26748, 2, 0, 738612, -182, 3724, 0, 157780, -2117880, 2, 0, + 2517158, -1462761, 2, 0, 2, -44508, 2003576, 0, 2, -897068, 2, 0, 5332, -4736762, 2, 0, + 344084, -230, 9352622, 0, 3769924, -15721720, 8097455] := by + decide +kernel + +/-- Conjecture (Hanna, A323695): odd terms `a n` occur only at `n = k * (k + 2)`, `k ≥ 0`. -/ +def statement : Prop := + ∀ n : ℕ, Odd (a n) → ∃ k : ℕ, n = k * (k + 2) + +end Math0.Statements.A323695 diff --git a/lean/Math0/Statements/OEIS/A326407.lean b/lean/Math0/Statements/OEIS/A326407.lean new file mode 100644 index 0000000..747085b --- /dev/null +++ b/lean/Math0/Statements/OEIS/A326407.lean @@ -0,0 +1,154 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A326407: prime-Minesweeper on the A060734 square array, `a(n) < 6`, `a(n) = 5` only at `6` + +Source: https://oeis.org/A326407, _Witold Tatkiewicz_, Oct 02 2019. Verbatim (COMMENTS): +> a(n) < 6 (conjectured). +> +> a(n) = 5 for n={6} (conjectured). + +(The entry also has a third comment, "Set of n such that a(n) = 4 is unbounded (conjectured).", +which is not part of `statement`; it is recorded separately as `statement_four_unbounded`.) + +The entry's definition (offset 1): "Minesweeper sequence of positive integers arranged on a 2D +grid along a square array that grows by alternately adding a row at its bottom edge and a column +at its right edge." "Place positive integers on a 2D grid starting with 1 in the top left corner +and continue along an increasing square array as in A060734. Replace each prime with -1 and each +nonprime with the number of primes in adjacent grid cells around them. n is replaced by a(n)." +The example shows the array +``` + 1 4 9 16 25 36 + 2 3 8 15 24 35 + 5 6 7 14 23 34 + 10 11 12 13 22 33 + 17 18 19 20 21 32 + 26 27 28 29 30 31 +``` + +## Encoding + +* `val r c` is the entry in row `r`, column `c` (both 0-indexed, row 0 on top, column 0 on the + left): `(c + 1)^2 - r` if `r ≤ c` and `r^2 + 1 + c` if `r > c`. `val_data` checks it against + the first 66 terms of A060734 (the array read by antidiagonals downwards) and against the + array of the example. +* `pos n` is the cell holding `n ≥ 1`, computed with `k = Nat.sqrt (n - 1)` (the cell lies on the + `k`-th "hook" `max r c = k`). `pos_val` and `val_pos` prove that `val` and `pos` are mutually + inverse bijections between `ℕ × ℕ` and the positive integers, so every positive integer occurs + exactly once in the array. +* "Adjacent grid cells" are the Minesweeper neighbours: the cells `(i, j) ≠ (r, c)` with + `|i - r| ≤ 1` and `|j - c| ≤ 1` that lie in the grid (`i, j ≥ 0`), so there are 8 of them in + general, 5 on the top row or left column and 3 at the corner `(0, 0)`. `near x` lists the + admissible coordinates within distance 1 of `x`, and `neighbours n` lists the values in the + neighbouring cells of `pos n` (without repetitions, since `val` is injective by `pos_val`). +* `a n : ℤ` is `-1` if `n` is prime and otherwise the number of primes among `neighbours n`. + It is meaningful for `n ≥ 1` (offset 1); `a 0` is a junk value. `a_data` checks all 81 listed + terms `a 1, …, a 81`. +* The two conjectures are stated over the whole range `n ≥ 1` of the sequence: + `a n < 6` for every `n ≥ 1`, and, for `n ≥ 1`, `a n = 5` iff `n = 6` (the set of `n` with + `a(n) = 5` is exactly `{6}`). +-/ + +namespace Math0.Statements.A326407 + +/-- The entry in row `r`, column `c` (0-indexed) of the A060734 array: +`(c + 1)^2 - r` on and above the diagonal (`r ≤ c`), `r^2 + 1 + c` below it (`r > c`). -/ +def val (r c : ℕ) : ℕ := if r ≤ c then (c + 1) ^ 2 - r else r ^ 2 + 1 + c + +/-- The cell `(row, column)` holding `n ≥ 1` in the A060734 array. With `k = ⌊√(n-1)⌋`, +the numbers `k^2 + 1, …, k^2 + k` fill row `k` from the left (columns `0, …, k - 1`) and +`k^2 + k + 1, …, (k+1)^2` fill column `k` from the bottom (rows `k, …, 0`). -/ +def pos (n : ℕ) : ℕ × ℕ := + if n ≤ Nat.sqrt (n - 1) ^ 2 + Nat.sqrt (n - 1) then + (Nat.sqrt (n - 1), n - Nat.sqrt (n - 1) ^ 2 - 1) + else ((Nat.sqrt (n - 1) + 1) ^ 2 - n, Nat.sqrt (n - 1)) + +/-- `pos` inverts `val`: in particular `val` is injective. -/ +theorem pos_val (r c : ℕ) : pos (val r c) = (r, c) := by + unfold val + split_ifs with h + · have e : (c + 1) ^ 2 = c * c + 2 * c + 1 := by ring + have e2 : c ^ 2 = c * c := by ring + have hs : Nat.sqrt ((c + 1) ^ 2 - r - 1) = c := by + rw [e, show c * c + 2 * c + 1 - r - 1 = c * c + (2 * c - r) by omega] + exact Nat.sqrt_add_eq c (by omega) + unfold pos + rw [hs, e, e2, if_neg (by omega)] + rw [Prod.mk.injEq]; omega + · have e : (r + 1) ^ 2 = r * r + 2 * r + 1 := by ring + have e2 : r ^ 2 = r * r := by ring + have hs : Nat.sqrt (r ^ 2 + 1 + c - 1) = r := by + rw [e2, show r * r + 1 + c - 1 = r * r + c by omega] + exact Nat.sqrt_add_eq r (by omega) + unfold pos + rw [hs, e2, if_pos (by omega)] + rw [Prod.mk.injEq]; omega + +/-- `val` inverts `pos` on the positive integers: every `n ≥ 1` occurs in the array. -/ +theorem val_pos {n : ℕ} (hn : 1 ≤ n) : val (pos n).1 (pos n).2 = n := by + have h1 := Nat.sqrt_le (n - 1) + have h2 := Nat.lt_succ_sqrt (n - 1) + unfold pos + generalize Nat.sqrt (n - 1) = k at h1 h2 ⊢ + have e : (k + 1) ^ 2 = k * k + 2 * k + 1 := by ring + have e2 : k ^ 2 = k * k := by ring + have e3 : Nat.succ k * Nat.succ k = k * k + 2 * k + 1 := by rw [Nat.succ_eq_add_one]; ring + rw [e3] at h2 + rw [e, e2] + split_ifs with h + · unfold val + rw [e2, if_neg (by omega)] + omega + · unfold val + rw [e, if_pos (by omega)] + omega + +/-- The coordinates at distance at most 1 from `x` that are still in the grid (`≥ 0`). -/ +def near (x : ℕ) : List ℕ := if x = 0 then [0, 1] else [x - 1, x, x + 1] + +/-- The numbers in the grid cells adjacent to the cell of `n` (horizontally, vertically or +diagonally, as in Minesweeper): up to 8 of them, fewer on the border of the grid. -/ +def neighbours (n : ℕ) : List ℕ := + (near (pos n).1).flatMap fun i => + (near (pos n).2).filterMap fun j => + if (i, j) = pos n then none else some (val i j) + +/-- A326407 (offset 1): `-1` if `n` is prime, otherwise the number of primes in the grid cells +adjacent to the cell of `n` in the A060734 array. -/ +def a (n : ℕ) : ℤ := + if n.Prime then -1 else (((neighbours n).filter fun m => m.Prime).length : ℤ) + +/-- `val` reproduces the 66 listed terms of A060734 (the array read by antidiagonals downwards, +i.e. `val 0 d, val 1 (d - 1), …, val d 0` for `d = 0, …, 10`), and the 6 × 6 array of the +A326407 example (kernel-checked). -/ +theorem val_data : + ((List.range 11).flatMap fun d => (List.range (d + 1)).map fun i => val i (d - i)) = + [1, 4, 2, 9, 3, 5, 16, 8, 6, 10, 25, 15, 7, 11, 17, 36, 24, 14, 12, 18, 26, 49, 35, 23, 13, + 19, 27, 37, 64, 48, 34, 22, 20, 28, 38, 50, 81, 63, 47, 33, 21, 29, 39, 51, 65, 100, 80, + 62, 46, 32, 30, 40, 52, 66, 82, 121, 99, 79, 61, 45, 31, 41, 53, 67, 83, 101] ∧ + ((List.range 6).map fun r => (List.range 6).map fun c => val r c) = + [[1, 4, 9, 16, 25, 36], [2, 3, 8, 15, 24, 35], [5, 6, 7, 14, 23, 34], + [10, 11, 12, 13, 22, 33], [17, 18, 19, 20, 21, 32], [26, 27, 28, 29, 30, 31]] := by + decide +kernel + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 81).map (fun i => a (i + 1)) = + [2, -1, -1, 2, -1, 5, -1, 2, 1, 3, -1, 4, -1, 3, 2, 0, -1, 3, -1, 3, 3, 2, -1, 1, 0, 2, 3, 2, + -1, 3, -1, 1, 2, 2, 2, 0, -1, 1, 2, 3, -1, 3, -1, 3, 3, 2, -1, 1, 0, 1, 2, 2, -1, 2, 3, 2, 3, + 2, -1, 2, -1, 3, 2, 0, 1, 2, -1, 2, 1, 1, -1, 3, -1, 1, 1, 1, 3, 3, -1, 1, 0] := by + decide +kernel + +/-- Conjectures (Tatkiewicz, A326407): for every `n ≥ 1`, `a(n) < 6`; and `a(n) = 5` holds for +`n = 6` and for no other `n ≥ 1`. -/ +def statement : Prop := + (∀ n : ℕ, 1 ≤ n → a n < 6) ∧ (∀ n : ℕ, 1 ≤ n → (a n = 5 ↔ n = 6)) + +/-- The third conjecture of the entry (not part of `statement`): the set of `n` with +`a(n) = 4` is unbounded. -/ +def statement_four_unbounded : Prop := + ∀ N : ℕ, ∃ n : ℕ, N ≤ n ∧ a n = 4 + +end Math0.Statements.A326407 diff --git a/lean/Math0/Statements/OEIS/A326602.lean b/lean/Math0/Statements/OEIS/A326602.lean new file mode 100644 index 0000000..1dd52e3 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A326602.lean @@ -0,0 +1,209 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A326602: parity of the coefficients of `∑ (x^(2n-1)+1)^n x^n / (1+x^(2n+1))^(n+1)` + +Source: https://oeis.org/A326602, _Paul D. Hanna_, Aug 08 2019. Verbatim: +> a(n) is odd iff n is square (conjecture). + +The entry's definition (offset 0): "G.f.: Sum_{n>=0} (x^(2*n-1) + 1)^n * x^n / +(1 + x^(2*n+1))^(n+1), an even function." and "G.f. A(x) = Sum_{n>=0} a(n)*x^(2*n)", i.e. +`a(n)` is the coefficient of `x^(2n)` in this power series (whose odd coefficients vanish). + +## Encoding + +* `summand n : ℤ⟦X⟧` is `(X^(2n-1) + 1)^n * X^n * ((1 + X^(2n+1))^(n+1))⁻¹`, the inverse being + `PowerSeries.invOfUnit _ 1` (the factor has constant coefficient `1`); `summand_spec` records + the defining identity `(1 + X^(2n+1))^(n+1) * summand n = (X^(2n-1) + 1)^n * X^n`. + For `n = 0` the OEIS factor `(x^(-1) + 1)^0` is `1`; in `ℕ` the exponent `2*0-1` truncates to + `0`, giving `(X^0 + 1)^0 = 1` as well. +* `summand n` is divisible by `X^n` (`coeff_summand_of_lt`), so the series converges + `X`-adically. `A` is its sum, defined coefficientwise as the finite sum over `n ≤ N`, and + `hasSum_summand` proves `HasSum summand A` in the product (coefficientwise) topology on `ℤ⟦X⟧`. +* `a n` is defined by an explicit finite formula, `coeffA (2 * n)`, obtained by expanding + `(X^(2m-1) + 1)^m` with the binomial theorem and `(1 + X^(2m+1))^(-(m+1))` as + `∑_j (-1)^j C(m+j, j) X^((2m+1) j)`. The theorem `a_eq_coeff` proves (in Lean) that + `a n = coeff (2 * n) A`, so `a` is exactly the OEIS definition; the explicit formula only + serves to make `a` computable for the kernel-checked data. +* The conjecture is stated for every `n ≥ 0` (offset 0), with "square" meaning `n = k * k` for + some `k : ℕ` (`IsSquare n`), so `n = 0` counts as a square. +-/ + +namespace Math0.Statements.A326602 + +open PowerSeries + +/-! ### The generating function -/ + +/-- The `n`-th summand `(x^(2n-1) + 1)^n * x^n / (1 + x^(2n+1))^(n+1)` of the g.f., in `ℤ⟦X⟧`. +(For `n = 0` the truncated exponent `2*0-1 = 0` is harmless: the factor is raised to the +power `0`.) -/ +noncomputable def summand (n : ℕ) : PowerSeries ℤ := + (X ^ (2 * n - 1) + 1) ^ n * X ^ n * invOfUnit ((1 + X ^ (2 * n + 1)) ^ (n + 1)) 1 + +theorem constantCoeff_one_add_X_pow_pow (b d : ℕ) (hb : b ≠ 0) : + constantCoeff ((1 + X ^ b : PowerSeries ℤ) ^ d) = ((1 : ℤˣ) : ℤ) := by + simp [map_pow, zero_pow hb] + +/-- `summand n` is the quotient `(x^(2n-1) + 1)^n * x^n / (1 + x^(2n+1))^(n+1)`. -/ +theorem summand_spec (n : ℕ) : + (1 + X ^ (2 * n + 1)) ^ (n + 1) * summand n = (X ^ (2 * n - 1) + 1) ^ n * X ^ n := by + rw [summand, mul_comm, mul_assoc, invOfUnit_mul _ _ + (constantCoeff_one_add_X_pow_pow _ _ (by omega)), mul_one] + +/-- `summand n` is divisible by `X ^ n`. -/ +theorem coeff_summand_of_lt {N n : ℕ} (h : N < n) : coeff N (summand n) = 0 := by + rw [summand, mul_comm ((X ^ (2 * n - 1) + 1) ^ n) (X ^ n), mul_assoc, coeff_X_pow_mul', + if_neg (by omega)] + +/-- The generating function `A(x) = ∑_{n ≥ 0} summand n`, defined coefficientwise +(the coefficient of `x^N` only involves the summands with `n ≤ N`, see `coeff_summand_of_lt`). -/ +noncomputable def A : PowerSeries ℤ := + mk fun N => ∑ n ∈ Finset.range (N + 1), coeff N (summand n) + +open scoped PowerSeries.WithPiTopology in +/-- `A` is the sum of the family `summand` in the coefficientwise topology of `ℤ⟦X⟧`. -/ +theorem hasSum_summand : HasSum summand A := by + rw [PowerSeries.WithPiTopology.hasSum_iff_hasSum_coeff] + intro N + rw [A, coeff_mk] + apply hasSum_sum_of_ne_finset_zero + intro n hn + rw [Finset.mem_range, not_lt] at hn + exact coeff_summand_of_lt (by omega) + +/-! ### An explicit formula for the coefficients -/ + +/-- Binomial coefficient via descending factorials (fast in the kernel); equals `Nat.choose`. -/ +def binom (n k : ℕ) : ℕ := n.descFactorial k / k.factorial + +theorem binom_eq_choose (n k : ℕ) : binom n k = n.choose k := + (Nat.choose_eq_descFactorial_div_factorial n k).symm + +/-- Contribution of `C(m,i) X^((2m-1) i)` (from `(X^(2m-1)+1)^m`) to the coefficient of `x^N` +in `summand m`: with `k = (2m-1) i + m`, it is `C(m,i) (-1)^q C(m+q, q)` when +`N - k = (2m+1) q`, and `0` otherwise. -/ +def term (N m i : ℕ) : ℤ := + if (2 * m - 1) * i + m ≤ N ∧ (N - ((2 * m - 1) * i + m)) % (2 * m + 1) = 0 then + (-1) ^ ((N - ((2 * m - 1) * i + m)) / (2 * m + 1)) * + ((binom m i * binom (m + (N - ((2 * m - 1) * i + m)) / (2 * m + 1)) + ((N - ((2 * m - 1) * i + m)) / (2 * m + 1)) : ℕ) : ℤ) + else 0 + +/-- `term N m i = 0` unless `i ≤ iBound N m` (see `term_eq_zero`); this only speeds up the +computation of `coeffA`. -/ +def iBound (N m : ℕ) : ℕ := min m ((N - m) / (2 * m - 1)) + +/-- The coefficient of `x^N` in the g.f., by an explicit formula (see `coeff_A`): +`∑_{m ≤ N} ∑_{i ≤ iBound N m} term N m i`. -/ +def coeffA (N : ℕ) : ℤ := + ∑ m ∈ Finset.range (N + 1), ∑ i ∈ Finset.range (iBound N m + 1), term N m i + +theorem term_eq_zero {N m i : ℕ} (him : i ≤ m) (hi : iBound N m < i) : term N m i = 0 := by + rw [term, if_neg] + rintro ⟨h, -⟩ + rw [iBound] at hi + generalize hx : (N - m) / (2 * m - 1) = x at hi + have hm : 0 < 2 * m - 1 := by omega + have h1 : x < i := by omega + rw [← hx, Nat.div_lt_iff_lt_mul hm] at h1 + rw [mul_comm] at h1 + generalize (2 * m - 1) * i = y at h h1 + omega + +theorem coeffA_eq (N : ℕ) : + coeffA N = ∑ m ∈ Finset.range (N + 1), ∑ i ∈ Finset.range (m + 1), term N m i := by + refine Finset.sum_congr rfl fun m _ => Finset.sum_subset ?_ fun i him hi => ?_ + · intro i + simp only [Finset.mem_range, iBound] + omega + · simp only [Finset.mem_range] at him hi + exact term_eq_zero (by omega) (by omega) + +/-- A326602: `a n` is the coefficient of `x^(2n)` in +`∑_{m ≥ 0} (x^(2m-1) + 1)^m * x^m / (1 + x^(2m+1))^(m+1)` (see `a_eq_coeff`). -/ +def a (n : ℕ) : ℤ := coeffA (2 * n) + +/-- `(1 + X^b)^(d+1) * ∑_j (-1)^j C(d+j, d) X^(b j) = 1` (from `1/(1-X)^(d+1)` by `X ↦ -X^b`). -/ +theorem one_add_X_pow_pow_mul (b d : ℕ) (hb : b ≠ 0) : + (1 + X ^ b : PowerSeries ℤ) ^ (d + 1) * + expand b hb (evalNegHom (mk fun j => (Nat.choose (d + j) d : ℤ))) = 1 := by + have h := congrArg (fun f => expand b hb (evalNegHom f)) + (mk_add_choose_mul_one_sub_pow_eq_one (S := ℤ) d) + simp only [map_mul, map_pow, map_sub, map_one, evalNegHom_X, sub_neg_eq_add] at h + rw [mul_comm] + simpa [add_comm] using h + +theorem invOfUnit_one_add_X_pow_pow (b d : ℕ) (hb : b ≠ 0) : + invOfUnit ((1 + X ^ b : PowerSeries ℤ) ^ (d + 1)) 1 = + expand b hb (evalNegHom (mk fun j => (Nat.choose (d + j) d : ℤ))) := by + set φ : PowerSeries ℤ := (1 + X ^ b) ^ (d + 1) + set E := expand b hb (evalNegHom (mk fun j => (Nat.choose (d + j) d : ℤ))) + have h1 : φ * invOfUnit φ 1 = 1 := + mul_invOfUnit _ _ (constantCoeff_one_add_X_pow_pow _ _ hb) + have h2 : φ * E = 1 := one_add_X_pow_pow_mul b d hb + calc invOfUnit φ 1 = (E * φ) * invOfUnit φ 1 := by rw [mul_comm E, h2, one_mul] + _ = E := by rw [mul_assoc, h1, mul_one] + +theorem coeff_E (b d r : ℕ) (hb : b ≠ 0) : + coeff r (expand b hb (evalNegHom (mk fun j => (Nat.choose (d + j) d : ℤ)))) = + if r % b = 0 then (-1) ^ (r / b) * (Nat.choose (d + r / b) (r / b) : ℤ) else 0 := by + rw [coeff_expand] + by_cases h : b ∣ r + · rw [if_pos h, if_pos (Nat.mod_eq_zero_of_dvd h)] + simp [evalNegHom] + rw [Nat.choose_symm_add] + · rw [if_neg h, if_neg (fun h' => h (Nat.dvd_of_mod_eq_zero h'))] + +/-- The explicit formula for the coefficients of a summand. -/ +theorem coeff_summand (N m : ℕ) : + coeff N (summand m) = ∑ i ∈ Finset.range (m + 1), term N m i := by + rw [summand, invOfUnit_one_add_X_pow_pow _ _ (by omega), add_pow, Finset.sum_mul, + Finset.sum_mul, map_sum] + refine Finset.sum_congr rfl fun i _ => ?_ + rw [one_pow, mul_one, ← map_natCast (C (R := ℤ)), ← pow_mul, + show ∀ f g h e : PowerSeries ℤ, f * g * h * e = g * (f * h * e) from + fun f g h e => by ring, + coeff_C_mul, ← pow_add, coeff_X_pow_mul', coeff_E _ _ _ (by omega), term] + simp only [binom_eq_choose] + split_ifs with h1 h2 h3 h3 h3 + · push_cast; ring + · exact absurd ⟨h1, h2⟩ h3 + · exact absurd h3.2 h2 + · rw [mul_zero] + · exact absurd h3.1 h1 + · rw [mul_zero] + +/-- The coefficients of the g.f. are given by `coeffA`. -/ +theorem coeff_A (N : ℕ) : coeff N A = coeffA N := by + rw [A, coeff_mk, coeffA_eq] + exact Finset.sum_congr rfl fun m _ => coeff_summand N m + +/-- `a n` is the coefficient of `x^(2n)` in the g.f. `A`, as in OEIS. -/ +theorem a_eq_coeff (n : ℕ) : a n = coeff (2 * n) A := by + rw [coeff_A, a] + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 68).map (fun i => a (i + 0)) = + [1, 3, 0, 2, 9, -12, 8, 12, -10, 15, -36, 46, -18, 20, 12, -82, 101, -162, 302, -168, -100, + 92, 32, 40, -244, 351, -452, 1052, -1528, 1144, -394, -494, 948, -438, 370, -1474, 2805, + -2860, 2560, -4762, 6554, -4104, 926, 480, -1820, 3074, -2546, 1072, -2518, 9745, -17810, + 21300, -28982, 37560, -26380, 6162, 686, 2, 2364, -12342, 30356, -39584, 19448, 7562, 9491, + -63824, 99128, -116668] := by + decide +kernel + +/-- Sanity check of "an even function": the first odd-index coefficients of the g.f. vanish +(kernel-checked). -/ +theorem coeffA_odd_data : + (List.range 40).map (fun i => coeffA (2 * i + 1)) = List.replicate 40 0 := by + decide +kernel + +/-- Conjecture (Hanna, A326602): for every `n ≥ 0`, `a n` (the coefficient of `x^(2n)` in the +g.f., `a_eq_coeff`) is odd iff `n` is a square. -/ +def statement : Prop := + ∀ n : ℕ, Odd (a n) ↔ IsSquare n + +end Math0.Statements.A326602 diff --git a/lean/Math0/Statements/OEIS/A328202.lean b/lean/Math0/Statements/OEIS/A328202.lean new file mode 100644 index 0000000..f157d64 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A328202.lean @@ -0,0 +1,99 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A328202: gcd of the interior binomial coefficients of row `n` + +Source: https://oeis.org/A328202, _Jon Maiga_, Oct 08 2019 (FORMULA section). Verbatim: +> a(n) = A014963(n) * A014963(n - 1) (conjecture). - _Jon Maiga_, Oct 08 2019 + +The entry (by _Joel Kaufmann_, Oct 07 2019) is named "a(n) is the greatest common divisor of +all the numbers in row n of Pascal's triangle excluding 1 and n.", with offset `4`. Its listed +data are `a(4), …, a(78)`. + +The same entry also contains, in the COMMENTS, a second conjecture (from _Robert Israel_, +Oct 16 2019): +> If p is a Fermat prime > 3, a(p)=2*p. +> If p is a Mersenne prime, a(p+1)=2*p. +> Conjecture: these are the only cases where a(n)>n. + +It is recorded below as `statementIsrael`; the main target of this file is `statement`. + +## Encoding + +* *The sequence.* Row `n` of Pascal's triangle is `C(n, 0), C(n, 1), …, C(n, n)`. Excluding + the entries `1` and `n` means dropping `C(n, 0) = C(n, n) = 1` and `C(n, 1) = C(n, n-1) = n`; + for `n ≥ 4` every remaining entry `C(n, k)`, `2 ≤ k ≤ n - 2`, is `> n`, so nothing else is + dropped. Hence `a n = gcd {C(n, k) : 2 ≤ k ≤ n - 2}`, written as + `(Finset.Icc 2 (n - 2)).gcd (Nat.choose n)`. (This matches the entry's programs, which take the + gcd over `2 ≤ k ≤ n/2`, a set with the same values by `C(n, k) = C(n, n - k)`.) The value of + `a n` for `n < 4` is irrelevant: the offset is `4` and every statement below assumes `n ≥ 4`. + `a_data` kernel-checks all `75` listed terms `a(4), …, a(78)`. +* *A014963.* Its name: "Exponential of Mangoldt function M(n): a(n) = 1 unless n is a prime or + prime power, in which case a(n) = that prime." (offset `1`). `expMangoldt m` is `m.minFac` + (the prime `p`) when `IsPrimePow m` (i.e. `m = p ^ k` with `p` prime and `k ≥ 1`), and `1` + otherwise. `cast_expMangoldt` proves it equals `exp (Λ m)` for Mathlib's von Mangoldt function + `ArithmeticFunction.vonMangoldt`, and `expMangoldt_data` kernel-checks the `95` listed terms + `A014963(1), …, A014963(95)`. +* *The conjecture* (`statement`): for every `n ≥ 4`, `a n = expMangoldt n * expMangoldt (n - 1)`. + Since `n ≥ 4`, `n - 1 ≥ 3` and the natural-number subtraction is exact. +* *Israel's conjecture* (`statementIsrael`, secondary): "these are the only cases where + a(n) > n" is read as: for every `n ≥ 4` with `a n > n`, either `n` is a Fermat prime `> 3` + (a prime of the form `2 ^ (2 ^ k) + 1`, `Nat.fermatNumber k`) or `n - 1` is a Mersenne prime + (a prime of the form `2 ^ m - 1`, `mersenne m`), i.e. `n = p + 1` for a Mersenne prime `p`. + The two displayed facts (the converse direction) are stated in the entry as facts, not as + part of the conjecture, so they are not included. +-/ + +namespace Math0.Statements.A328202 + +/-- A328202: `a(n)` is the greatest common divisor of all the numbers in row `n` of Pascal's +triangle excluding `1` and `n`, i.e. `gcd {C(n, k) : 2 ≤ k ≤ n - 2}` (offset `4`). -/ +def a (n : ℕ) : ℕ := (Finset.Icc 2 (n - 2)).gcd (Nat.choose n) + +set_option maxRecDepth 100000 in +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all `75` listed +terms `a(4), …, a(78)`. -/ +theorem a_data : (List.range 75).map (fun i => a (i + 4)) = + [6, 10, 5, 7, 14, 6, 3, 11, 11, 13, 13, 1, 2, 34, 17, 19, 19, 1, 1, 23, 23, 5, 5, 3, 3, 29, + 29, 31, 62, 2, 1, 1, 1, 37, 37, 1, 1, 41, 41, 43, 43, 1, 1, 47, 47, 7, 7, 1, 1, 53, 53, 1, 1, + 1, 1, 59, 59, 61, 61, 1, 2, 2, 1, 67, 67, 1, 1, 71, 71, 73, 73, 1, 1, 1, 1] := by + decide +kernel + +/-- A014963, the exponential of the von Mangoldt function: `1` unless `m` is a prime power +`p ^ k` (`p` prime, `k ≥ 1`), in which case it is that prime `p` (which is `m.minFac`). -/ +def expMangoldt (m : ℕ) : ℕ := if IsPrimePow m then m.minFac else 1 + +/-- `expMangoldt m = exp (Λ m)`, with `Λ` Mathlib's von Mangoldt function. -/ +theorem cast_expMangoldt (m : ℕ) : + (expMangoldt m : ℝ) = Real.exp (ArithmeticFunction.vonMangoldt m) := by + rw [ArithmeticFunction.vonMangoldt_apply, expMangoldt] + split_ifs with h + · rw [Real.exp_log] + exact_mod_cast Nat.minFac_pos m + · simp + +set_option maxRecDepth 100000 in +/-- `expMangoldt` reproduces the `95` terms `A014963(1), …, A014963(95)` listed in OEIS +(kernel-checked). -/ +theorem expMangoldt_data : (List.range 95).map (fun i => expMangoldt (i + 1)) = + [1, 2, 3, 2, 5, 1, 7, 2, 3, 1, 11, 1, 13, 1, 1, 2, 17, 1, 19, 1, 1, 1, 23, 1, 5, 1, 3, 1, 29, + 1, 31, 2, 1, 1, 1, 1, 37, 1, 1, 1, 41, 1, 43, 1, 1, 1, 47, 1, 7, 1, 1, 1, 53, 1, 1, 1, 1, 1, + 59, 1, 61, 1, 1, 2, 1, 1, 67, 1, 1, 1, 71, 1, 73, 1, 1, 1, 1, 1, 79, 1, 3, 1, 83, 1, 1, 1, 1, + 1, 89, 1, 1, 1, 1, 1, 1] := by + decide +kernel + +/-- Jon Maiga's conjecture: for every `n ≥ 4`, `a(n) = A014963(n) * A014963(n - 1)`. -/ +def statement : Prop := + ∀ n : ℕ, 4 ≤ n → a n = expMangoldt n * expMangoldt (n - 1) + +/-- Robert Israel's conjecture (secondary, from the COMMENTS of the same entry): if `n ≥ 4` and +`a(n) > n`, then `n` is a Fermat prime `> 3` or `n - 1` is a Mersenne prime. -/ +def statementIsrael : Prop := + ∀ n : ℕ, 4 ≤ n → n < a n → + (n.Prime ∧ 3 < n ∧ ∃ k, n = Nat.fermatNumber k) ∨ + ((n - 1).Prime ∧ ∃ m, n - 1 = mersenne m) + +end Math0.Statements.A328202 diff --git a/lean/Math0/Statements/OEIS/A332010.lean b/lean/Math0/Statements/OEIS/A332010.lean new file mode 100644 index 0000000..00210a7 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A332010.lean @@ -0,0 +1,206 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A332010: denominators of the average first letter of derangements with `k` descents + +Source: https://oeis.org/A332010, _Peter Kagey_, Feb 04 2020 (COMMENTS section). Verbatim: +> Conjecture: T(n, 1) = 2^(n-2). + +The entry's name is "Irregular triangle of denominators of the average value of the first letter +over all derangements of {1, 2, ..., n} with k descents." (keyword `tabf`, offset `2`, i.e. the +rows are `n = 2, 3, …`). Its comments add "Even-indexed rows have length n - 1; odd-indexed rows +have length n - 2." The example: "T(4,1) = 4 because the derangements of four letters with one +descent are [2,3,4,1], [2,4,1,3], [3,4,1,2], and [4,1,2,3], and the expected value of the first +letter is (2+2+3+4)/4 = 11/4, which has 4 as its denominator." + +## Encoding + +* *Permutations as words.* As in the entry's example, a permutation of `{1, …, n}` is written in + one-line notation, as the word (list) `w = [w₁, …, wₙ]` of its values. The permutations of + `{1, …, n}` are enumerated by Mathlib's `List.permutations (List.range' 1 n)`, which lists every + rearrangement of `[1, 2, …, n]` (`List.mem_permutations`) exactly once + (`List.nodup_permutations`); `mem_ders` and `nodup_ders` record this for the words used here. +* *Derangement.* `IsDerangement w`: no letter is in its own position, i.e. `w[i] ≠ i + 1` for + every `0`-based index `i` (position `i + 1`). +* *Descents.* `des w` is the number of adjacent positions with `wᵢ > wᵢ₊₁`, counted over the + pairs `(wᵢ, wᵢ₊₁)` of `w.zip w.tail`. +* *First letter.* `w.headD 0`; all words used have length `n ≥ 1`, so this is `w₁`. +* *The triangle.* `ders n k` is the list of derangements of `{1, …, n}` with exactly `k` + descents, `avgFirst n k ∈ ℚ` is the average of their first letters (sum divided by count), and + `T n k` is its denominator `Rat.den`; a Mathlib rational is always in lowest terms, so this is + the denominator of the reduced fraction. (When there is no such derangement the average is + `0 / 0 = 0` and `T n k = 1`, but such `(n, k)` are not entries of the triangle.) +* *Rows.* Row `n ≥ 2` is `T(n, 1), …, T(n, rowLen n)` with `rowLen n = n - 1` for even `n` and + `n - 2` for odd `n`, as stated in the entry's comment. (Derangements have at least one descent, + since the only permutation without descents is the identity, and the only permutation with + `n - 1` descents is the reversal, a derangement exactly when `n` is even.) +* *Data check.* `List.permutations` is defined by well-founded recursion, which the kernel does + not evaluate well. The kernel copy `rowC` enumerates the words with Mathlib's structurally + recursive `List.permutations'`, keeps the derangements once (`DC n`, via the recursive test + `derB`), and splits them by the recursive descent count `desB`. `derB_one` and `desB_eq` + identify the tests with `IsDerangement` and `des`, and `ders_perm` shows the resulting word + lists are permutations of `ders n k`, so they give the same count and the same sum of first + letters (`row_eq_rowC`). `a_data` checks, in the kernel, the 25 listed terms of rows `2` to `8` + of the triangle read by rows (row `8` runs through all `8! = 40320` words, about a minute; the + entry's 50 listed terms reach row `11`, whose `11!` words are out of the kernel's reach). These + include `T(n, 1) = 2^(n-2)` for `2 ≤ n ≤ 8`; `example_T41` checks the entry's worked example. +* *The conjecture.* "T(n, 1) = 2^(n-2)" carries no explicit range; it is read for every row of + the triangle, i.e. for all `n ≥ 2` (offset `2`; `T(n, 1)` is the first entry of row `n`, and + every row `n ≥ 2` is nonempty). For `n ≥ 2` the natural-number subtraction `n - 2` is exact. +-/ + +namespace Math0.Statements.A332010 + +/-! ### Definitions -/ + +/-- A word `w = [w₁, …, wₙ]` (a permutation in one-line notation) is a derangement: no letter +is in its own position, i.e. `w[i] ≠ i + 1` for every `0`-based index `i`. -/ +def IsDerangement (w : List ℕ) : Prop := ∀ (i : ℕ) (h : i < w.length), w[i] ≠ i + 1 + +instance : DecidablePred IsDerangement := fun w => by unfold IsDerangement; infer_instance + +/-- The number of descents of a word: the number of adjacent pairs `(wᵢ, wᵢ₊₁)` with +`wᵢ > wᵢ₊₁`. -/ +def des (w : List ℕ) : ℕ := (w.zip w.tail).countP fun p => p.2 < p.1 + +/-- The derangements of `{1, 2, …, n}` with exactly `k` descents, in one-line notation (each +listed once, see `mem_ders` and `nodup_ders`). -/ +def ders (n k : ℕ) : List (List ℕ) := + (List.range' 1 n).permutations.filter fun w => decide (IsDerangement w) && des w == k + +/-- The average value of the first letter over a list `E` of words: the sum of their first +letters divided by their number. -/ +def avgFirstLetter (E : List (List ℕ)) : ℚ := + (((E.map fun w => w.headD 0).sum : ℕ) : ℚ) / ((E.length : ℕ) : ℚ) + +/-- The average value of the first letter over all derangements of `{1, 2, …, n}` with `k` +descents. -/ +def avgFirst (n k : ℕ) : ℚ := avgFirstLetter (ders n k) + +/-- A332010: `T(n, k)` is the denominator (in lowest terms) of the average value of the first +letter over all derangements of `{1, 2, …, n}` with `k` descents. -/ +def T (n k : ℕ) : ℕ := (avgFirst n k).den + +/-- The length of row `n` of the triangle (entry's comment): `n - 1` for even `n`, `n - 2` for +odd `n`. -/ +def rowLen (n : ℕ) : ℕ := if n % 2 = 0 then n - 1 else n - 2 + +/-- Row `n` of the triangle: `T(n, 1), …, T(n, rowLen n)`. -/ +def row (n : ℕ) : List ℕ := (List.range (rowLen n)).map fun j => T n (j + 1) + +/-! ### Faithfulness of the word enumeration -/ + +/-- The words in `ders n k` are exactly the rearrangements of `[1, …, n]` that are derangements +with `k` descents. -/ +theorem mem_ders {n k : ℕ} {w : List ℕ} : + w ∈ ders n k ↔ w.Perm (List.range' 1 n) ∧ IsDerangement w ∧ des w = k := by + simp [ders, List.mem_permutations] + +/-- Each derangement is listed only once in `ders n k`. -/ +theorem nodup_ders (n k : ℕ) : (ders n k).Nodup := + (List.nodup_permutations _ List.nodup_range').filter _ + +/-! ### A kernel-friendly copy of the definition -/ + +/-- `derB w i` checks that the `j`-th letter of `w` (`0`-based) is never `j + i`. -/ +def derB : List ℕ → ℕ → Bool + | [], _ => true + | x :: xs, i => x != i && derB xs (i + 1) + +/-- Structurally recursive count of descents. -/ +def desB : List ℕ → ℕ + | x :: y :: l => (if y < x then 1 else 0) + desB (y :: l) + | _ => 0 + +theorem derB_iff (w : List ℕ) (i : ℕ) : + derB w i = true ↔ ∀ (j : ℕ) (h : j < w.length), w[j] ≠ j + i := by + induction w generalizing i with + | nil => simp [derB] + | cons x xs ih => + simp only [derB, Bool.and_eq_true, bne_iff_ne, ne_eq, ih, List.length_cons] + constructor + · rintro ⟨hx, h⟩ j hj + cases j with + | zero => simpa using hx + | succ j => + have := h j (by omega) + simp only [List.getElem_cons_succ] + omega + · intro h + refine ⟨by simpa using h 0 (by omega), fun j hj => ?_⟩ + have := h (j + 1) (by omega) + simp only [List.getElem_cons_succ] at this + omega + +theorem derB_one (w : List ℕ) : derB w 1 = decide (IsDerangement w) := by + rw [Bool.eq_iff_iff, derB_iff, decide_eq_true_iff] + rfl + +theorem desB_eq : ∀ w : List ℕ, desB w = des w + | [] => rfl + | [_] => rfl + | x :: y :: l => by + rw [desB, desB_eq (y :: l)] + simp only [des, List.tail_cons, List.zip_cons_cons, List.countP_cons, decide_eq_true_eq] + omega + +/-- The derangements of `{1, …, n}`, enumerated through the structurally recursive +`List.permutations'`. -/ +def DC (n : ℕ) : List (List ℕ) := (List.range' 1 n).permutations'.filter fun w => derB w 1 + +/-- Row `n` computed from a single enumeration `DC n` of the derangements. -/ +def rowC (n : ℕ) : List ℕ := + (List.range (rowLen n)).map fun j => (avgFirstLetter ((DC n).filter fun w => desB w == j + 1)).den + +theorem avgFirstLetter_perm {E F : List (List ℕ)} (h : E.Perm F) : + avgFirstLetter E = avgFirstLetter F := by + simp only [avgFirstLetter, h.length_eq, (h.map fun w => w.headD 0).sum_eq] + +theorem ders_perm (n k : ℕ) : (ders n k).Perm ((DC n).filter fun w => desB w == k) := by + rw [DC, List.filter_filter] + have : (fun w => (desB w == k) && derB w 1) = + (fun w => decide (IsDerangement w) && des w == k) := by + funext w + rw [desB_eq, derB_one, Bool.and_comm] + rw [this] + exact (List.permutations_perm_permutations' _).filter _ + +theorem row_eq_rowC (n : ℕ) : row n = rowC n := by + unfold row rowC + congr 1 + funext j + rw [T, avgFirst, avgFirstLetter_perm (ders_perm n (j + 1))] + +/-! ### Sanity checks -/ + +/-- The entry's example: the derangements of four letters with one descent are `[2,3,4,1]`, +`[2,4,1,3]`, `[3,4,1,2]`, `[4,1,2,3]`, with average first letter `11/4`, so `T(4, 1) = 4`. -/ +theorem example_T41 : + (ders 4 1).Perm [[2, 3, 4, 1], [2, 4, 1, 3], [3, 4, 1, 2], [4, 1, 2, 3]] ∧ + avgFirst 4 1 = 11 / 4 ∧ T 4 1 = 4 := by + have h : ((DC 4).filter fun w => desB w == 1).Perm + [[2, 3, 4, 1], [2, 4, 1, 3], [3, 4, 1, 2], [4, 1, 2, 3]] := by decide +kernel + have h1 : avgFirst 4 1 = 11 / 4 := by + rw [avgFirst, avgFirstLetter_perm ((ders_perm 4 1).trans h)] + decide +kernel + exact ⟨(ders_perm 4 1).trans h, h1, by rw [T, h1]; decide +kernel⟩ + +/-- The definition reproduces the first 25 listed terms of OEIS, i.e. rows `2` to `8` of the +triangle read by rows (kernel-checked). -/ +theorem a_data : (List.range 7).flatMap (fun i => row (i + 2)) = + [1, 2, 4, 1, 1, 8, 3, 4, 16, 104, 40, 24, 1, 32, 392, 896, 480, 54, 64, 152, 308, 1496, 63, + 108, 1] := by + simp only [row_eq_rowC] + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjecture (Kagey, A332010): `T(n, 1) = 2^(n-2)` for every row `n ≥ 2`, i.e. the average +first letter of the derangements of `{1, …, n}` with exactly one descent has denominator +`2^(n-2)` in lowest terms. -/ +def statement : Prop := ∀ n : ℕ, 2 ≤ n → T n 1 = 2 ^ (n - 2) + +end Math0.Statements.A332010 diff --git a/lean/Math0/Statements/OEIS/A333650.lean b/lean/Math0/Statements/OEIS/A333650.lean new file mode 100644 index 0000000..3a785e5 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A333650.lean @@ -0,0 +1,518 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A333650: domino towers counted by number of bricks and height + +Source: https://oeis.org/A333650, _Peter Kagey_, Mar 31 2020 (the first conjecture is the entry +author's; the next three are later comments). Verbatim: +> Conjecture: For n > 1, T(n,2) = A000071(n+2). +> +> Conjecture: T(n,n-1) = A339252(n-2). - _Peter Kagey_, Nov 21 2020 +> +> Conjecture: T(n,n-2) = A339254(n-3). - _Peter Luschny_, Nov 29 2020 +> +> Conjecture: T(n,n-3) = A339029(n-4). - _Peter Luschny_, Dec 01 2020 +> +> From _Peter Luschny_, Dec 01 2020: (Start) +> The above conjectures can be summarized as follows: +> T(2*n + k, n + k) = d_{n}(n + k - 1) for k >= 1 and 0 <= n <= 3, where +> d_{0}(m) = 2^(m-1)*2; +> d_{1}(m) = 2^(m-3)*(10 + 6*m); +> d_{2}(m) = 2^(m-5)*(70 + 43*m + 9*m^2); +> d_{3}(m) = 2^(m-7)*(588 + 367*m + 84*m^2 + 9*m^3). (End) + +The entry's definition: "Triangle read by rows: T(n,k) gives the number of domino towers of +height k consisting of n bricks." and "The towers must have a contiguous base of bricks, and each +brick must be at least half supported below by another brick. The stacks do not need to be +stable." Offset `1`: rows `n ≥ 1`, columns `1 ≤ k ≤ n`. + +## Encoding + +* Horizontal positions are measured in half bricks. A brick of layer `i` (layer `0` is the + bottom) with left end `x ∈ ℤ` occupies `[x, x + 2)`. A tower is the list `t = [t₀, …, t_{k-1}]` + of its layers, bottom first, each layer being the finset of left ends of its bricks. Its height + is its number `k` of layers (all nonempty) and its number of bricks is `∑ᵢ #tᵢ` (`IsTower`). +* Towers are counted up to horizontal translation, so the base (a contiguous row of `b ≥ 1` + bricks side by side) is normalised to `t₀ = {0, 2, …, 2b - 2}` (`base b`). Mirror images are + different towers (`T(2,2) = 2`). +* Domino towers (Gouyou-Beauchamps–Viennot, Bétréma–Penaud, Zeilberger, all cited in the entry) + are laid in the brick-wall pattern: consecutive layers are staggered by half a brick, i.e. the + bricks of layer `i` have left ends `≡ i (mod 2)`. The entry's data force this reading: allowing + a brick exactly on top of another would give `T(2,2) = 3` and `T(n,n) = 3^(n-1)`, whereas the + entry lists `T(2,2) = 2` and states `T(n,n) = 2^(n-1)`; its picture of the four towers counted + by `T(3,2) = 4` shows staggered layers only. +* The bricks of a layer do not overlap: distinct left ends in one layer differ by at least `2` + (this follows from the staggering, but is stated explicitly). +* "Each brick must be at least half supported below by another brick": a brick `[x, x + 2)` of + layer `i + 1` overlaps some brick `[y, y + 2)` of layer `i` in a segment of length + `2 - |x - y| ≥ 1`, i.e. `|x - y| ≤ 1`. Stability is not required. +* `T n k` is the number (`Set.ncard`) of towers of height `k` with `n` bricks. The computable + `Tc n k` builds the towers layer by layer (each layer above the base is a nonempty set of + positions `y ± 1` with `y` in the layer below); `T_eq_Tc` proves `T n k = Tc n k`, so in + particular the set of towers is finite. +* `a` is the triangle read by rows with the OEIS offset `1`; `a_spec` proves + `a (n * (n - 1) / 2 + k) = T n k` for `1 ≤ k ≤ n`. `a_data` checks all 55 terms listed in the + entry's DATA section (rows `1` to `10`) in the kernel. +* The other sequences are encoded by their own OEIS definitions and checked against their listed + terms: A000071 (offset 1) is `Fibonacci(n) - 1`; A339252 and A339254 (offset 0) are given by + their defining recurrences; A339029 (offset 0) is the coefficient sequence of the power series + `(1 + 4x - 20x^2 + 8x^3 + 33x^4 - 4x^5 - 33x^6)/(1 - 2x)^4`, the inverse of `(1 - 2x)^4` being + taken in `ℤ⟦X⟧` (`invOfUnit`). All four are `ℤ`-valued, and `T` is cast to `ℤ`. +* `statement` is the conjunction of the four conjectures. The first carries its own range + `n > 1`. The other three state no range; they are read for every `n` at which the index of the + right-hand sequence (offset `0`) is a natural number, i.e. `n ≥ 2`, `n ≥ 3`, `n ≥ 4` + respectively (equivalently, the column `n - 1`, `n - 2`, `n - 3` is at least `1`), so the + natural-number subtractions below are exact. +* Luschny's summary is a reformulation, through the closed forms of A339252, A339254, A339029 + listed in those entries, of the last three conjectures (on smaller ranges of `n`) together with + the formula `T(n,n) = 2^(n-1)` stated in the entry; it is not formalized separately. +* `statement_check` verifies the four identities on the rows `n ≤ 10` (a consistency check of + the offsets, not a proof). +-/ + +namespace Math0.Statements.A333650 + +open Finset + +/-! ### Domino towers -/ + +/-- The base of `b` bricks side by side: left ends `0, 2, …, 2b - 2`. -/ +def base (b : ℕ) : Finset ℤ := (range b).image fun j : ℕ => 2 * (j : ℤ) + +/-- `t = [t₀, …, t_{k-1}]` is a domino tower of height `k` with `n` bricks: `tᵢ` is the finset of +left ends of the bricks of layer `i` (layer `0` at the bottom), a brick with left end `x` +occupying `[x, x + 2)` in half-brick units; the base is translated to start at `0`. -/ +def IsTower (n k : ℕ) (t : List (Finset ℤ)) : Prop := + -- `k` layers, none of them empty + t.length = k ∧ (∀ L ∈ t, L.Nonempty) ∧ + -- the bottom layer is a contiguous row of `b ≥ 1` bricks, translated to start at `0` + (∃ b, 0 < b ∧ t.head? = some (base b)) ∧ + -- the bricks of a layer do not overlap + (∀ L ∈ t, ∀ x ∈ L, ∀ y ∈ L, x ≠ y → 2 ≤ |x - y|) ∧ + -- brick-wall pattern: layer `i` is shifted by `i` half bricks + (∀ (i : ℕ) (hi : i < t.length), ∀ x ∈ t[i], Even (x - i)) ∧ + -- each brick above the base overlaps a brick of the layer below by at least half a brick + (∀ (i : ℕ) (hi : i + 1 < t.length), ∀ x ∈ t[i + 1], ∃ y ∈ t[i], |x - y| ≤ 1) ∧ + -- `n` bricks in total + (t.map Finset.card).sum = n + +/-- A333650: `T n k` is the number of domino towers of height `k` consisting of `n` bricks. -/ +noncomputable def T (n k : ℕ) : ℕ := {t | IsTower n k t}.ncard + +/-! ### Computing `T` -/ + +/-- The left ends of the bricks that a layer `L` supports in the next layer: `y ± 1`, `y ∈ L`. -/ +def supported (L : Finset ℤ) : Finset ℤ := L.image (· - 1) ∪ L.image (· + 1) + +/-- `ways L h m`: the number of ways to put `h` further nonempty layers, with `m` bricks in total, +on top of the layer `L`, each layer consisting of positions supported by the layer below. -/ +def ways (L : Finset ℤ) : ℕ → ℕ → ℕ + | 0, m => if m = 0 then 1 else 0 + | h + 1, m => ∑ j ∈ Icc 1 (m - h), ∑ L' ∈ (supported L).powersetCard j, ways L' h (m - j) + +/-- Computable version of `T` (see `T_eq_Tc`): sum over the size `b` of the base. -/ +def Tc (n k : ℕ) : ℕ := if k = 0 then 0 else ∑ b ∈ Icc 1 n, ways (base b) (k - 1) (n - b) + +/-- Row and column of the `i`-th term of a triangle read by rows, starting the search at row `n` +(`fuel` bounds the number of rows visited). -/ +def rowCol : ℕ → ℕ → ℕ → ℕ × ℕ + | 0, n, i => (n, i) + | fuel + 1, n, i => if i ≤ n then (n, i) else rowCol fuel (n + 1) (i - n) + +/-- A333650 read by rows, with the OEIS offset `1`: `a 1 = T 1 1`, `a 2 = T 2 1`, `a 3 = T 2 2`, +`a 4 = T 3 1`, … (see `a_spec`). -/ +def a (i : ℕ) : ℕ := Tc (rowCol i 1 i).1 (rowCol i 1 i).2 + +/-- The definition reproduces the 55 terms listed in OEIS (rows 1 to 10), kernel-checked. -/ +theorem a_data : (List.range 55).map (fun i => a (i + 1)) = + [1, 1, 2, 1, 4, 4, 1, 7, 11, 8, 1, 12, 24, 28, 16, 1, 20, 52, 70, 68, 32, 1, 33, 110, 168, + 193, 160, 64, 1, 54, 228, 401, 497, 510, 368, 128, 1, 88, 467, 944, 1257, 1412, 1304, 832, + 256, 1, 143, 949, 2187, 3172, 3736, 3879, 3248, 1856, 512] := by + decide +kernel + +/-! ### `T = Tc` -/ + +/-- `s` (bottom first) is a stack of nonempty layers on top of the layer `L`, each consisting of +positions supported by the layer below it. -/ +def Stack : Finset ℤ → List (Finset ℤ) → Prop + | _, [] => True + | L, L' :: s => L'.Nonempty ∧ L' ⊆ supported L ∧ Stack L' s + +/-- The finset of the stacks counted by `ways L h m`. -/ +def stackSet (L : Finset ℤ) : ℕ → ℕ → Finset (List (Finset ℤ)) + | 0, m => if m = 0 then {[]} else ∅ + | h + 1, m => (Icc 1 (m - h)).biUnion fun j => + ((supported L).powersetCard j).biUnion fun L' => (stackSet L' h (m - j)).image (L' :: ·) + +theorem length_le_sum : ∀ {L : Finset ℤ} {s : List (Finset ℤ)}, Stack L s → + s.length ≤ (s.map Finset.card).sum + | _, [], _ => by simp + | _, L' :: s, ⟨hne, _, hs⟩ => by + have h1 := length_le_sum hs + have h2 := hne.card_pos + simp only [List.length_cons, List.map_cons, List.sum_cons] + omega + +theorem mem_stacks (h : ℕ) : ∀ (L : Finset ℤ) (m : ℕ) (s : List (Finset ℤ)), + s ∈ stackSet L h m ↔ s.length = h ∧ Stack L s ∧ (s.map Finset.card).sum = m := by + induction h with + | zero => + intro L m s + rcases s with _ | ⟨L', s⟩ + · by_cases hm : m = 0 <;> simp [stackSet, hm, Stack, eq_comm] + · by_cases hm : m = 0 <;> simp [stackSet, hm] + | succ h ih => + intro L m s + rcases s with _ | ⟨L', s⟩ + · simp [stackSet] + · simp only [stackSet, mem_biUnion, mem_image, mem_Icc, mem_powersetCard, ih, + List.cons.injEq, List.length_cons, List.map_cons, List.sum_cons, Stack] + constructor + · rintro ⟨j, ⟨hj1, hj2⟩, L'', ⟨hsub, hcard⟩, s', ⟨hlen, hst, hsum⟩, rfl, rfl⟩ + exact ⟨by omega, ⟨card_pos.1 (by omega), hsub, hst⟩, by omega⟩ + · rintro ⟨hlen, ⟨hne, hsub, hst⟩, hsum⟩ + have h1 := length_le_sum hst + have h2 := hne.card_pos + exact ⟨L'.card, ⟨by omega, by omega⟩, L', ⟨hsub, rfl⟩, s, ⟨by omega, hst, by omega⟩, + rfl, rfl⟩ + +theorem card_stacks (h : ℕ) : ∀ (L : Finset ℤ) (m : ℕ), (stackSet L h m).card = ways L h m := by + induction h with + | zero => intro L m; by_cases hm : m = 0 <;> simp [stackSet, ways, hm] + | succ h ih => + intro L m + rw [stackSet, ways, card_biUnion] + · refine sum_congr rfl fun j _ => ?_ + rw [card_biUnion] + · refine sum_congr rfl fun L' _ => ?_ + rw [card_image_of_injective _ List.cons_injective, ih] + · intro L₁ _ L₂ _ hne + rw [Function.onFun, disjoint_left] + intro s hs1 hs2 + simp only [mem_image] at hs1 hs2 + obtain ⟨s1, _, rfl⟩ := hs1 + obtain ⟨s2, _, h2⟩ := hs2 + exact hne (List.cons.inj h2).1.symm + · intro j₁ _ j₂ _ hne + rw [Function.onFun, disjoint_left] + intro s hs1 hs2 + simp only [mem_biUnion, mem_image, mem_powersetCard] at hs1 hs2 + obtain ⟨L1, ⟨_, hc1⟩, s1, _, rfl⟩ := hs1 + obtain ⟨L2, ⟨_, hc2⟩, s2, _, h2⟩ := hs2 + rw [(List.cons.inj h2).1] at hc2 + exact hne (hc1.symm.trans hc2) + +theorem card_base (b : ℕ) : (base b).card = b := by + rw [base, card_image_of_injective _ (fun x y hxy => by simpa using hxy), card_range] + +/-- The towers, as a finset (see `isTower_iff`). -/ +def towerFinset (n k : ℕ) : Finset (List (Finset ℤ)) := + if k = 0 then ∅ else + (Icc 1 n).biUnion fun b => (stackSet (base b) (k - 1) (n - b)).image (base b :: ·) + +theorem card_towerFinset (n k : ℕ) : (towerFinset n k).card = Tc n k := by + unfold towerFinset Tc + split_ifs with hk + · rfl + · rw [card_biUnion] + · refine sum_congr rfl fun b _ => ?_ + rw [card_image_of_injective _ List.cons_injective, card_stacks] + · intro b₁ _ b₂ _ hne + rw [Function.onFun, disjoint_left] + intro s hs1 hs2 + simp only [mem_image] at hs1 hs2 + obtain ⟨s1, _, rfl⟩ := hs1 + obtain ⟨s2, _, h2⟩ := hs2 + have h3 := congrArg Finset.card (List.cons.inj h2).1 + rw [card_base, card_base] at h3 + exact hne h3.symm + +theorem mem_supported {L : Finset ℤ} {x : ℤ} : x ∈ supported L ↔ x + 1 ∈ L ∨ x - 1 ∈ L := by + simp only [supported, mem_union, mem_image] + constructor + · rintro (⟨y, hy, rfl⟩ | ⟨y, hy, rfl⟩) + · left; simpa using hy + · right; simpa using hy + · rintro (h | h) + · left; exact ⟨x + 1, h, by ring⟩ + · right; exact ⟨x - 1, h, by ring⟩ + +theorem stack_iff (L : Finset ℤ) (s : List (Finset ℤ)) : + Stack L s ↔ (∀ L' ∈ s, L'.Nonempty) ∧ + ∀ (i : ℕ) (hi : i < s.length), s[i] ⊆ supported ((L :: s)[i]'(by simp; omega)) := by + induction s generalizing L with + | nil => simp [Stack] + | cons L' s ih => + rw [Stack, ih, List.forall_mem_cons] + constructor + · rintro ⟨hne, hsub, hall, hst⟩ + refine ⟨⟨hne, hall⟩, fun i hi => ?_⟩ + rcases i with _ | i + · exact hsub + · exact hst i (by simp at hi; omega) + · rintro ⟨⟨hne, hall⟩, hst⟩ + exact ⟨hne, hst 0 (by simp), hall, fun i hi => hst (i + 1) (by simp; omega)⟩ + +theorem isTower_iff (n k : ℕ) (t : List (Finset ℤ)) : IsTower n k t ↔ t ∈ towerFinset n k := by + constructor + · rintro ⟨hlen, hne, ⟨b, hb, hhead⟩, -, hpar, hsupp, hsum⟩ + rcases t with _ | ⟨L, s⟩ + · simp at hhead + simp only [List.head?_cons, Option.some.injEq] at hhead + subst hhead + have hcard : (base b).card ≤ n := by + rw [← hsum]; simp + rw [card_base] at hcard + have hk : k ≠ 0 := by rw [← hlen]; simp + simp only [towerFinset, if_neg hk, mem_biUnion, mem_Icc, mem_image] + refine ⟨b, ⟨hb, hcard⟩, s, ?_, rfl⟩ + rw [mem_stacks] + refine ⟨by simp at hlen; omega, ?_, by simp [card_base] at hsum; omega⟩ + rw [stack_iff] + refine ⟨fun L' h => hne L' (by simp [h]), fun i hi x hx => ?_⟩ + have hi' : i + 1 < (base b :: s).length := by simp; omega + obtain ⟨y, hy, hxy⟩ := hsupp i hi' x hx + obtain ⟨r, hr⟩ := hpar (i + 1) hi' x hx + obtain ⟨r', hr'⟩ := hpar i (by omega) y hy + push_cast at hr hr' + rw [mem_supported] + rcases abs_cases (x - y) with ⟨h1, h2⟩ | ⟨h1, h2⟩ <;> rw [h1] at hxy + · have : x = y + 1 := by omega + right; rw [this]; simpa using hy + · have : x = y - 1 := by omega + left; rw [this]; simpa using hy + · intro ht + have hk : k ≠ 0 := by rintro rfl; simp [towerFinset] at ht + simp only [towerFinset, if_neg hk, mem_biUnion, mem_Icc, mem_image] at ht + obtain ⟨b, ⟨hb, hbn⟩, s, hs, rfl⟩ := ht + rw [mem_stacks, stack_iff] at hs + obtain ⟨hlen, ⟨hne, hst⟩, hsum⟩ := hs + -- each layer above the base is supported by the layer below + have hst' : ∀ (i : ℕ) (hi : i + 1 < (base b :: s).length), + (base b :: s)[i + 1] ⊆ supported (base b :: s)[i] := + fun i hi => hst i (by simp at hi; omega) + -- parity of every layer + have hpar : ∀ (i : ℕ) (hi : i < (base b :: s).length), ∀ x ∈ (base b :: s)[i], + Even (x - i) := by + intro i + induction i with + | zero => + intro hi x hx + simp only [List.getElem_cons_zero, base, mem_image, mem_range] at hx + obtain ⟨j, -, rfl⟩ := hx + exact ⟨j, by push_cast; ring⟩ + | succ i ih => + intro hi x hx + have := hst' i hi hx + rw [mem_supported] at this + rcases this with h | h + · obtain ⟨r, hr⟩ := ih (by omega) _ h + exact ⟨r - 1, by push_cast at hr ⊢; linarith⟩ + · obtain ⟨r, hr⟩ := ih (by omega) _ h + exact ⟨r, by push_cast at hr ⊢; linarith⟩ + refine ⟨by simp; omega, ?_, ⟨b, hb, rfl⟩, ?_, hpar, ?_, ?_⟩ + · intro L hL + rcases List.mem_cons.1 hL with rfl | h + · exact ⟨0, mem_image.2 ⟨0, mem_range.2 hb, by simp⟩⟩ + · exact hne L h + · intro L hL x hx y hy hxy + obtain ⟨i, hi, rfl⟩ := List.getElem_of_mem hL + obtain ⟨r, hr⟩ := hpar i hi x hx + obtain ⟨r', hr'⟩ := hpar i hi y hy + rcases abs_cases (x - y) with ⟨h1, h2⟩ | ⟨h1, h2⟩ <;> rw [h1] <;> omega + · intro i hi x hx + have := hst' i hi hx + rw [mem_supported] at this + rcases this with h | h + · exact ⟨x + 1, h, by simp⟩ + · exact ⟨x - 1, h, by simp⟩ + · simp [card_base]; omega + +/-- `T n k = Tc n k`; in particular there are finitely many towers of each size. -/ +theorem T_eq_Tc (n k : ℕ) : T n k = Tc n k := by + have : {t | IsTower n k t} = (towerFinset n k : Set (List (Finset ℤ))) := by + ext t; simp [isTower_iff] + rw [T, this, Set.ncard_coe_finset, card_towerFinset] + +theorem rowCol_spec (d : ℕ) : ∀ (n fuel k : ℕ), d ≤ fuel → 1 ≤ k → k ≤ n + d → + rowCol fuel n ((∑ j ∈ range d, (n + j)) + k) = (n + d, k) := by + induction d with + | zero => + intro n fuel k _ _ hk + rcases fuel with _ | fuel + · simp [rowCol] + · simp [rowCol, show k ≤ n by omega] + | succ d ih => + intro n fuel k hd hk1 hk + obtain ⟨fuel, rfl⟩ : ∃ f, fuel = f + 1 := ⟨fuel - 1, by omega⟩ + rw [sum_range_succ'] + have h1 : ¬ (∑ j ∈ range d, (n + (j + 1)) + (n + 0) + k ≤ n) := by omega + rw [rowCol, if_neg h1] + have h2 : ∑ j ∈ range d, (n + (j + 1)) + (n + 0) + k - n = + ∑ j ∈ range d, (n + 1 + j) + k := by + have : ∑ j ∈ range d, (n + (j + 1)) = ∑ j ∈ range d, (n + 1 + j) := + sum_congr rfl fun j _ => by ring + omega + rw [h2, ih (n + 1) fuel k (by omega) hk1 (by omega), show n + 1 + d = n + (d + 1) by omega] + +/-- `a` is the triangle `T` read by rows (offset `1`). -/ +theorem a_spec (n k : ℕ) (hk : 1 ≤ k) (hkn : k ≤ n) : a (n * (n - 1) / 2 + k) = T n k := by + obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩ + have hsum : (m + 1) * (m + 1 - 1) / 2 = ∑ j ∈ range m, (1 + j) := by + rw [← sum_range_id (m + 1), sum_range_succ'] + simp [add_comm] + have hge : m ≤ ∑ j ∈ range m, (1 + j) := by + rw [sum_add_distrib]; simp + rw [a, hsum, rowCol_spec m 1 _ k (by omega) hk (by omega), T_eq_Tc, add_comm 1 m] + +/-! ### The sequences on the right-hand sides -/ + +/-- A000071 (offset 1): `a(n) = Fibonacci(n) - 1`. -/ +def A000071 (n : ℕ) : ℤ := (Nat.fib n : ℤ) - 1 + +theorem A000071_data : (List.range 40).map (fun i => A000071 (i + 1)) = + [0, 0, 1, 2, 4, 7, 12, 20, 33, 54, 88, 143, 232, 376, 609, 986, 1596, 2583, 4180, 6764, + 10945, 17710, 28656, 46367, 75024, 121392, 196417, 317810, 514228, 832039, 1346268, 2178308, + 3524577, 5702886, 9227464, 14930351, 24157816, 39088168, 63245985, 102334154] := by + decide +kernel + +/-- A339252 (offset 0): `a(0) = 1`, `a(1) = 4`, `a(2) = 11`, and +`a(n) = 4*a(n-1) - 4*a(n-2)` for `n ≥ 3`. -/ +def A339252 : ℕ → ℤ + | 0 => 1 + | 1 => 4 + | 2 => 11 + | n + 3 => 4 * A339252 (n + 2) - 4 * A339252 (n + 1) + +theorem A339252_data : (List.range 32).map A339252 = + [1, 4, 11, 28, 68, 160, 368, 832, 1856, 4096, 8960, 19456, 41984, 90112, 192512, 409600, + 868352, 1835008, 3866624, 8126464, 17039360, 35651584, 74448896, 155189248, 322961408, + 671088640, 1392508928, 2885681152, 5972688896, 12348030976, 25501368320, + 52613349376] := by + decide +kernel + +/-- A339254 (offset 0): `a(n) = 6*a(n - 1) - 12*a(n - 2) + 8*a(n - 3)` for `n ≥ 5`, +`a(0) = 1`, `a(1) = 7`, `a(2) = 24`, `a(3) = 70`, `a(4) = 193`. -/ +def A339254 : ℕ → ℤ + | 0 => 1 + | 1 => 7 + | 2 => 24 + | 3 => 70 + | 4 => 193 + | n + 5 => 6 * A339254 (n + 4) - 12 * A339254 (n + 3) + 8 * A339254 (n + 2) + +theorem A339254_data : (List.range 30).map A339254 = + [1, 7, 24, 70, 193, 510, 1304, 3248, 7920, 18976, 44800, 104448, 240896, 550400, 1247232, + 2805760, 6270976, 13934592, 30801920, 67764224, 148439040, 323878912, 704118784, + 1525678080, 3295674368, 7098859520, 15250489344, 32682016768, 69877104640, + 149082341376] := by + decide +kernel + +open PowerSeries in +/-- A339029 (offset 0): expansion of +`(1 + 4*x - 20*x^2 + 8*x^3 + 33*x^4 - 4*x^5 - 33*x^6)/(1 - 2*x)^4`, i.e. the coefficients of the +power series `P * ((1 - 2X)^4)⁻¹` in `ℤ⟦X⟧` (`(1 - 2X)^4` has constant coefficient `1`). -/ +noncomputable def A339029 (n : ℕ) : ℤ := + coeff n ((1 + 4 * X - 20 * X ^ 2 + 8 * X ^ 3 + 33 * X ^ 4 - 4 * X ^ 5 - 33 * X ^ 6 : ℤ⟦X⟧) * + invOfUnit ((1 - 2 * X) ^ 4) 1) + +/-- A computable version of `A339029` (see `A339029_eq`), by the recurrence read off from the +generating function. -/ +def A339029rec : ℕ → ℤ + | 0 => 1 + | 1 => 12 + | 2 => 52 + | 3 => 168 + | 4 => 497 + | 5 => 1412 + | 6 => 3879 + | n + 7 => 8 * A339029rec (n + 6) - 24 * A339029rec (n + 5) + 32 * A339029rec (n + 4) - + 16 * A339029rec (n + 3) + +open PowerSeries in +theorem A339029rec_gf : ((1 - 2 * X) ^ 4 : ℤ⟦X⟧) * PowerSeries.mk A339029rec = + 1 + 4 * X - 20 * X ^ 2 + 8 * X ^ 3 + 33 * X ^ 4 - 4 * X ^ 5 - 33 * X ^ 6 := by + have e1 : ((1 - 2 * X) ^ 4 : ℤ⟦X⟧) * PowerSeries.mk A339029rec = PowerSeries.mk A339029rec + - C 8 * (X ^ 1 * PowerSeries.mk A339029rec) + C 24 * (X ^ 2 * PowerSeries.mk A339029rec) + - C 32 * (X ^ 3 * PowerSeries.mk A339029rec) + + C 16 * (X ^ 4 * PowerSeries.mk A339029rec) := by + simp only [map_ofNat]; ring + have e2 : (1 + 4 * X - 20 * X ^ 2 + 8 * X ^ 3 + 33 * X ^ 4 - 4 * X ^ 5 - 33 * X ^ 6 : ℤ⟦X⟧) = + 1 + C 4 * X ^ 1 - C 20 * X ^ 2 + C 8 * X ^ 3 + C 33 * X ^ 4 - C 4 * X ^ 5 - C 33 * X ^ 6 := by + simp only [map_ofNat]; ring + rw [e1, e2] + ext n + simp only [map_sub, map_add, coeff_C_mul, coeff_X_pow_mul', coeff_mk, coeff_one, coeff_X_pow] + rcases n with _ | _ | _ | _ | _ | _ | _ | n + · simp [A339029rec] + · simp [A339029rec] + · simp [A339029rec] + · simp [A339029rec] + · simp [A339029rec] + · simp [A339029rec] + · simp [A339029rec] + · have h1 : 1 ≤ n + 7 := by omega + have h2 : 2 ≤ n + 7 := by omega + have h3 : 3 ≤ n + 7 := by omega + have h4 : 4 ≤ n + 7 := by omega + simp only [h1, h2, h3, h4, if_true, A339029rec] + simp + ring + +open PowerSeries in +theorem A339029_eq (n : ℕ) : A339029 n = A339029rec n := by + have hu : constantCoeff ((1 - 2 * X) ^ 4 : ℤ⟦X⟧) = ((1 : ℤˣ) : ℤ) := by + simp + have h : PowerSeries.mk A339029rec = + (1 + 4 * X - 20 * X ^ 2 + 8 * X ^ 3 + 33 * X ^ 4 - 4 * X ^ 5 - 33 * X ^ 6 : ℤ⟦X⟧) * + invOfUnit ((1 - 2 * X) ^ 4) 1 := by + rw [← A339029rec_gf, mul_comm ((1 - 2 * X) ^ 4 : ℤ⟦X⟧), mul_assoc, mul_invOfUnit _ _ hu, + mul_one] + rw [A339029, ← h, coeff_mk] + +theorem A339029_data : (List.range 29).map A339029 = + [1, 12, 52, 168, 497, 1412, 3879, 10360, 27016, 69024, 173264, 428288, 1044480, 2516992, + 6001408, 14174208, 33191936, 77127680, 177967104, 408027136, 930021376, 2108424192, + 4756275200, 10680270848, 23880794112, 53185871872, 118016180224, 260969594880, + 575223627776] := by + rw [show A339029 = A339029rec from funext A339029_eq] + decide +kernel + +/-! ### The conjectures -/ + +/-- Consistency check of the offsets (not a proof): the four identities below hold on the rows +`n ≤ 10` listed in OEIS. Kernel-checked. -/ +theorem statement_check : + (∀ n < 11, 1 < n → (T n 2 : ℤ) = A000071 (n + 2)) ∧ + (∀ n < 11, 2 ≤ n → (T n (n - 1) : ℤ) = A339252 (n - 2)) ∧ + (∀ n < 11, 3 ≤ n → (T n (n - 2) : ℤ) = A339254 (n - 3)) ∧ + (∀ n < 11, 4 ≤ n → (T n (n - 3) : ℤ) = A339029 (n - 4)) := by + simp only [T_eq_Tc, A339029_eq] + decide +kernel + +/-- Kagey (Mar 31 2020): for `n > 1`, `T(n,2) = A000071(n+2)`. -/ +def statement_col2 : Prop := + ∀ n : ℕ, 1 < n → (T n 2 : ℤ) = A000071 (n + 2) + +/-- Kagey (Nov 21 2020): `T(n,n-1) = A339252(n-2)`, for every `n ≥ 2`. -/ +def statement_diag1 : Prop := + ∀ n : ℕ, 2 ≤ n → (T n (n - 1) : ℤ) = A339252 (n - 2) + +/-- Luschny (Nov 29 2020): `T(n,n-2) = A339254(n-3)`, for every `n ≥ 3`. -/ +def statement_diag2 : Prop := + ∀ n : ℕ, 3 ≤ n → (T n (n - 2) : ℤ) = A339254 (n - 3) + +/-- Luschny (Dec 01 2020): `T(n,n-3) = A339029(n-4)`, for every `n ≥ 4`. -/ +def statement_diag3 : Prop := + ∀ n : ℕ, 4 ≤ n → (T n (n - 3) : ℤ) = A339029 (n - 4) + +/-- The four conjectures of A333650: the number of domino towers with `n` bricks and height `2` +is `A000071(n+2)` (`n > 1`), and those of height `n - 1`, `n - 2`, `n - 3` are counted by +`A339252(n-2)`, `A339254(n-3)`, `A339029(n-4)`. -/ +def statement : Prop := + statement_col2 ∧ statement_diag1 ∧ statement_diag2 ∧ statement_diag3 + +end Math0.Statements.A333650 diff --git a/lean/Math0/Statements/OEIS/A334592.lean b/lean/Math0/Statements/OEIS/A334592.lean new file mode 100644 index 0000000..4d9a423 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A334592.lean @@ -0,0 +1,129 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A334592: zeros in the XOR-triangle of the binary expansion of `n`; records at powers of 2 + +Source: https://oeis.org/A334592, Peter Kagey, May 07 2020 (COMMENTS section). Verbatim: +> Conjecture: Records occur at powers of two. + +The sequence (offset `1`) is "Number of zeros in XOR-triangle with first row generated from the +binary expansion of n", where "An XOR-triangle is an inverted 0-1 triangle formed by choosing a +top row and having each entry in the subsequent rows be the XOR of the two values above it." +(Example from the entry: `53 = 110101₂` gives the rows `110101, 01111, 1000, 100, 10, 1`, which +contain `9` zeros, so `a(53) = 9`.) + +## Encoding + +* `binary n` is the binary expansion of `n`, most significant bit first, as a `List Bool` + (`true` = digit `1`). It is computed with a fuel argument so that the kernel can evaluate it; + `binary_eq_digits` proves that it is exactly the reversed `Nat.digits 2 n` with digits `1` + read as `true` and `0` as `false`. +* `xorRow r` is the row below `r`: the XOR of each pair of adjacent entries of `r` (length one + less). `xorTriangle r` is the list of rows `r, xorRow r, xorRow (xorRow r), …` down to the row + of length `1` (the triangle has `r.length` rows, as in the Mathematica program of the entry, + which iterates while the row has length `> 1`). `a n` is the total number of `false` entries + (zeros) over all rows of `xorTriangle (binary n)`. The value `a 0 = 0` is outside the OEIS + range and is never used by `statement`. +* `a_data` checks all 77 listed terms `a 1, …, a 77`; `triangle_53` checks the triangle of the + example `n = 53`. +* "Records": following the OEIS convention, `n` (in the range `n ≥ 1` of the sequence) is a + record position when `a n` is strictly larger than every earlier term, i.e. `a m < a n` for all + `1 ≤ m < n` (so `n = 1` is a record). Strictness matters: with non-strict records `n = 3` + (`a 3 = a 2 = 1`) would be a record. +* Reading of "Records occur at powers of two": the record positions are exactly the powers of + two, i.e. for every `n`, `n` is a record position iff `n = 2^k` for some `k ≥ 0`. The weaker + one-directional reading (every record position is a power of two) is `statement_weak`, implied + by `statement` (`statement_imp_weak`); it is not the primary formalization. +-/ + +namespace Math0.Statements.A334592 + +/-- Binary digits of `n`, least significant first, computed with `fuel` steps (the fuel is +never exhausted when `n ≤ fuel`, see `bitsLE_eq_digits`). -/ +def bitsLE : ℕ → ℕ → List Bool + | 0, _ => [] + | fuel + 1, n => if n = 0 then [] else (n % 2 == 1) :: bitsLE fuel (n / 2) + +/-- The binary expansion of `n`, most significant bit first (`true` = `1`, `false` = `0`); +empty for `n = 0`. -/ +def binary (n : ℕ) : List Bool := (bitsLE n n).reverse + +theorem bitsLE_eq_digits : ∀ (fuel n : ℕ), n ≤ fuel → + bitsLE fuel n = (Nat.digits 2 n).map (fun d => d == 1) := by + intro fuel + induction fuel with + | zero => + intro n hn + have : n = 0 := by omega + subst this + simp [bitsLE] + | succ f ih => + intro n hn + rcases Nat.eq_zero_or_pos n with rfl | hpos + · simp [bitsLE] + · rw [bitsLE, if_neg (by omega), Nat.digits_def' (by norm_num) hpos, List.map_cons, + ih (n / 2) (by omega)] + +/-- `binary n` is the reversed list of base-2 digits of `n` (Mathlib's `Nat.digits 2 n`, which +lists digits least significant first), with `1 ↦ true` and `0 ↦ false`. -/ +theorem binary_eq_digits (n : ℕ) : + binary n = ((Nat.digits 2 n).map (fun d => d == 1)).reverse := by + rw [binary, bitsLE_eq_digits n n le_rfl] + +/-- The next row of an XOR-triangle: each entry is the XOR of the two adjacent entries above +it. -/ +def xorRow (r : List Bool) : List Bool := List.zipWith xor r r.tail + +/-- The first `k` rows `r, xorRow r, xorRow (xorRow r), …` of the XOR-triangle with top row +`r`. -/ +def rows : ℕ → List Bool → List (List Bool) + | 0, _ => [] + | k + 1, r => r :: rows k (xorRow r) + +/-- The XOR-triangle with top row `r`: all its rows, of lengths `r.length, r.length - 1, …, 1`. -/ +def xorTriangle (r : List Bool) : List (List Bool) := rows r.length r + +/-- A334592: the number of zeros in the XOR-triangle whose first row is the binary expansion of +`n` (offset `1`). -/ +def a (n : ℕ) : ℕ := ((xorTriangle (binary n)).map (List.count false)).sum + +/-- The example of the entry: `53 = 110101₂` and its XOR-triangle (kernel-checked). -/ +theorem triangle_53 : xorTriangle (binary 53) = + [[true, true, false, true, false, true], + [false, true, true, true, true], + [true, false, false, false], + [true, false, false], + [true, false], + [true]] := by + decide +kernel + +theorem a_53 : a 53 = 9 := by decide +kernel + +/-- The definition reproduces all 77 terms listed in OEIS, `a 1, …, a 77` (kernel-checked). -/ +theorem a_data : (List.range 77).map (fun i => a (i + 1)) = + [0, 1, 1, 3, 2, 2, 3, 6, 4, 5, 3, 5, 3, 4, 6, 10, 7, 6, 7, 7, 8, 5, 6, 8, 7, 6, 5, 7, 6, 7, + 10, 15, 11, 11, 9, 9, 9, 11, 9, 11, 9, 13, 9, 9, 7, 9, 9, 13, 9, 9, 11, 9, 9, 7, 9, 11, 9, + 9, 9, 11, 9, 11, 15, 21, 16, 14, 15, 16, 13, 13, 12, 14, 11, 13, 12, 17, 12] := by + decide +kernel + +/-- `n` is a record position of A334592 (offset `1`): `n ≥ 1` and `a n` is strictly larger than +every earlier term `a m`, `1 ≤ m < n`. -/ +def IsRecord (n : ℕ) : Prop := 1 ≤ n ∧ ∀ m : ℕ, 1 ≤ m → m < n → a m < a n + +/-- Kagey's conjecture: the records of A334592 occur at the powers of two, i.e. `n` is a record +position if and only if `n = 2^k` for some `k ≥ 0`. -/ +def statement : Prop := + ∀ n : ℕ, IsRecord n ↔ ∃ k : ℕ, n = 2 ^ k + +/-- The weaker one-directional reading (every record position is a power of two). Not the +primary formalization. -/ +def statement_weak : Prop := + ∀ n : ℕ, IsRecord n → ∃ k : ℕ, n = 2 ^ k + +theorem statement_imp_weak : statement → statement_weak := + fun h n hn => (h n).1 hn + +end Math0.Statements.A334592 diff --git a/lean/Math0/Statements/OEIS/A334595.lean b/lean/Math0/Statements/OEIS/A334595.lean new file mode 100644 index 0000000..3cc2e13 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A334595.lean @@ -0,0 +1,106 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A334595: right diagonal of the XOR-triangle of the binary expansion of `n` + +Source: https://oeis.org/A334595, Peter Kagey, May 07 2020 (COMMENTS section). Verbatim: +> Conjecture: Records occur at 1 and at 2^n + 1. +> +> Conjecture: a(n) = 1 if and only if n is a power of two. + +The sequence (offset `1`) is "Binary interpretation of the right diagonal of the XOR-triangle +with first row generated from the binary expansion of n", where "An XOR-triangle is an inverted +0-1 triangle formed by choosing a top row and having each entry in the subsequent rows be the +XOR of the two values above it." Example from the entry: for `n = 19 = 10011₂` the triangle is +`10011 / 1010 / 111 / 00 / 0`, and "Reading the right side of the triangle starting from the +upper-right corner gives 10100 which is the binary representation of 20 = a(19)." + +## Encoding + +* `binExp n` is the binary expansion of `n`, most significant bit first, i.e. the reverse of + `Nat.digits 2 n` (so `binExp 19 = [1, 0, 0, 1, 1]`; `binExp 0 = []`). Its entries are `0` or + `1`, and on `{0, 1}` the bitwise `x ^^^ y` is exactly XOR. +* `xorRow row` is the next row of the XOR-triangle: entry `i` is `row[i] ^^^ row[i+1]`, so it is + one shorter than `row`. `triangle row` lists the `row.length` rows + `row, xorRow row, xorRow (xorRow row), …` (the last one has length `1`), and `rightDiag row` + is the list of last entries of these rows, i.e. the right side of the triangle read from the + upper-right corner downwards. +* `a n` reads `rightDiag (binExp n)` as a binary numeral whose first entry is the most + significant bit (`Nat.ofDigits 2` takes the least significant digit first, hence the + `reverse`). This is exactly the PARI program in the entry. `triangle_19` and `a_19` check the + worked example, and `a_data` checks all 70 listed terms `a 1, …, a 70`. +* The sequence has offset `1`, so both conjectures are about indices `n ≥ 1` (the value `a 0 = 0` + of the encoding plays no role). +* "Records": following the usual OEIS convention, `n ≥ 1` is a record position (`IsRecord n`) + when `a n` is strictly larger than every earlier term `a m`, `1 ≤ m < n`. "Records occur at 1 + and at 2^n + 1" is read as: the set of record positions is exactly + `{1} ∪ {2^k + 1 : k ≥ 1}`. The exponent ranges over `k ≥ 1`, like the index `n` of the sequence + that the conjecture reuses as the exponent's name (offset `1`); `2^0 + 1 = 2` is not a record + since `a 2 = a 1 = 1`, and `1` is listed separately in the conjecture. +* "a(n) = 1 if and only if n is a power of two" is stated for every `n ≥ 1`, with "power of two" + meaning `n = 2^k` for some `k ≥ 0` (so `n = 1 = 2^0` is included; `a 1 = 1`). +* `statement` is the conjunction of the two conjectures (`statement_records` and + `statement_powTwo`). +-/ + +namespace Math0.Statements.A334595 + +/-- The binary expansion of `n`, most significant bit first (`binExp 19 = [1, 0, 0, 1, 1]`). -/ +def binExp (n : ℕ) : List ℕ := (Nat.digits 2 n).reverse + +/-- The next row of an XOR-triangle: each entry is the XOR of the two entries above it (the +entries are `0`/`1`, for which `^^^` is XOR). -/ +def xorRow (row : List ℕ) : List ℕ := List.zipWith (fun x y => x ^^^ y) row row.tail + +/-- The XOR-triangle with first row `row`: the rows `xorRow^[r] row` for `r < row.length`. -/ +def triangle (row : List ℕ) : List (List ℕ) := + (List.range row.length).map (fun r => xorRow^[r] row) + +/-- The right side of the XOR-triangle with first row `row`, read from the upper-right corner: +the last entry of each row, top to bottom. -/ +def rightDiag (row : List ℕ) : List ℕ := (triangle row).map (fun r => r.getLastD 0) + +/-- A334595: the binary interpretation (first entry = most significant bit) of the right +diagonal of the XOR-triangle whose first row is the binary expansion of `n`. -/ +def a (n : ℕ) : ℕ := Nat.ofDigits 2 (rightDiag (binExp n)).reverse + +/-- The worked example of the entry: the XOR-triangle of `19 = 10011₂` (kernel-checked). -/ +theorem triangle_19 : + triangle (binExp 19) = [[1, 0, 0, 1, 1], [1, 0, 1, 0], [1, 1, 1], [0, 0], [0]] := by + decide +kernel + +/-- The worked example of the entry: `a(19) = 20 = 10100₂` (kernel-checked). -/ +theorem a_19 : rightDiag (binExp 19) = [1, 0, 1, 0, 0] ∧ a 19 = 20 := by + decide +kernel + +/-- The definition reproduces all 70 terms listed in OEIS, `a 1, …, a 70` (kernel-checked). -/ +theorem a_data : (List.range 70).map (fun i => a (i + 1)) = + [1, 1, 2, 1, 6, 3, 4, 1, 14, 4, 11, 2, 13, 7, 8, 1, 30, 11, 20, 7, 24, 13, 18, 3, 28, 9, 22, + 5, 26, 15, 16, 1, 62, 20, 43, 13, 50, 24, 39, 5, 58, 16, 47, 9, 54, 28, 35, 2, 61, 23, 40, + 14, 49, 27, 36, 6, 57, 19, 44, 10, 53, 31, 32, 1, 126, 43, 84, 24, 103, 50] := by + decide +kernel + +/-- `n` is a record position of the sequence (offset `1`): `n ≥ 1` and `a n` is strictly larger +than every earlier term `a m`, `1 ≤ m < n`. -/ +def IsRecord (n : ℕ) : Prop := + 1 ≤ n ∧ ∀ m : ℕ, 1 ≤ m → m < n → a m < a n + +/-- First conjecture (Peter Kagey, 2020): the records occur exactly at `1` and at `2^k + 1` for +`k ≥ 1`, i.e. at `1, 3, 5, 9, 17, 33, …`. -/ +def statement_records : Prop := + ∀ n : ℕ, IsRecord n ↔ (n = 1 ∨ ∃ k : ℕ, 1 ≤ k ∧ n = 2 ^ k + 1) + +/-- Second conjecture (Peter Kagey, 2020): for `n ≥ 1`, `a(n) = 1` if and only if `n` is a power +of two. -/ +def statement_powTwo : Prop := + ∀ n : ℕ, 1 ≤ n → (a n = 1 ↔ ∃ k : ℕ, n = 2 ^ k) + +/-- Both conjectures of A334595: the record positions are exactly `1` and the numbers `2^k + 1` +(`k ≥ 1`), and for `n ≥ 1`, `a(n) = 1` if and only if `n` is a power of two. -/ +def statement : Prop := + statement_records ∧ statement_powTwo + +end Math0.Statements.A334595 diff --git a/lean/Math0/Statements/OEIS/A334603.lean b/lean/Math0/Statements/OEIS/A334603.lean new file mode 100644 index 0000000..0389d1a --- /dev/null +++ b/lean/Math0/Statements/OEIS/A334603.lean @@ -0,0 +1,214 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A334603: the period of the decimal expansion of `1/11^n` + +Source: https://oeis.org/A334603, _Bernard Schott_, May 07 2020. Verbatim: +> Conjecture proposed by the authors in References page 205: if p is a prime with gcd(p,30) = 1 +> and if the period of 1/p is m then the period of 1/p^n is m*p^(n-1). + +and (FORMULA section): +> a(n) = 2 * 11^(n-1) [conjectured, see comments]. + +The reference is J.-M. De Koninck & A. Mercier, *1001 Problèmes en Théorie Classique des +Nombres*, Problème 346, Ellipses 2004. The entry's name is "Period of the fraction 1/11^n for +n >= 1." (offset `1`). + +## Encoding + +* `period m` is the period of the decimal expansion of `1/m` for `m` coprime to `10`: the least + `k ≥ 1` with `10 ^ k ≡ 1 [MOD m]`, i.e. the multiplicative order of `10` modulo `m`. For such + `m` the expansion of `1/m` is purely periodic (`1/m = c / (10^k - 1)` with + `c = (10^k - 1)/m` exactly when `m ∣ 10^k - 1`), so its minimal period is this order; this is + also what the entry's programs compute (`MultiplicativeOrder[10, 11^n]`, + `znorder(Mod(10, 11^n))`). The definition uses `Nat.find`, which needs a witness: Euler's + theorem gives `10 ^ φ(m) ≡ 1 [MOD m]`. For `m` not coprime to `10` we set `period m = 0`; + this case never occurs below. (For `m = 1` the definition gives `1`, while A051626 lists `0` + since `1/1` terminates; `m = 1` never occurs below either.) `period_eq_orderOf` proves + `period m = orderOf (10 : ZMod m)` for `m` coprime to `10`. +* `a n = period (11 ^ n)` (OEIS offset `1`; `a 0 = period 1 = 1` is not a term). +* `a_data` checks all 20 listed terms `a(1), …, a(20)` in the kernel. A naive search up to + `a(20) ≈ 1.2·10^20` is infeasible, so it goes through the order certificate + `orderOf_eq_of_pow_and_pow_div_prime` (`10^L ≡ 1` and `10^(L/q) ≢ 1` for each prime `q ∣ L`), + with the modular powers computed by binary exponentiation `powMod` (proved equal to + `b ^ e % m`). `period_data` checks `period` against the 35 terms of A051626 ("Period of decimal + representation of 1/n") with `3 ≤ n ≤ 90` and `gcd(n, 10) = 1`. +* `statement` is the conjecture of the FORMULA line, the one specific to this sequence: + `a(n) = 2 * 11^(n-1)` for every index `n ≥ 1` of the sequence. +* `statement_general` is the book conjecture quoted in the COMMENTS line, of which `statement` is + the case `p = 11` (`period 11 = 2`): for every prime `p` with `gcd(p, 30) = 1` and every + `n ≥ 1` (the exponent `n - 1` must be a natural number, and `1/p^0 = 1` has no period), + `period (p ^ n) = period p * p ^ (n - 1)`. Such `p` is coprime to `10`, so `period` is the + genuine period there. +-/ + +namespace Math0.Statements.A334603 + +/-- For `m` coprime to `10` some positive power of `10` is `≡ 1 (mod m)` (Euler's theorem). -/ +theorem exists_pow_modEq_one {m : ℕ} (h : Nat.Coprime 10 m) : + ∃ k, 0 < k ∧ 10 ^ k ≡ 1 [MOD m] := by + have hm : m ≠ 0 := by + rintro rfl + exact absurd (Nat.coprime_zero_right 10 |>.1 h) (by norm_num) + exact ⟨Nat.totient m, Nat.totient_pos.2 (Nat.pos_of_ne_zero hm), Nat.ModEq.pow_totient h⟩ + +/-- The period of the decimal expansion of `1/m` for `m` coprime to `10`: the least `k ≥ 1` with +`10 ^ k ≡ 1 (mod m)` (the multiplicative order of `10` modulo `m`). Set to `0` when +`gcd(m, 10) ≠ 1` (never used). -/ +def period (m : ℕ) : ℕ := + if h : Nat.Coprime 10 m then Nat.find (exists_pow_modEq_one h) else 0 + +/-- A334603: the period of the fraction `1/11^n` (offset `1`). -/ +def a (n : ℕ) : ℕ := period (11 ^ n) + +/-! ### Characterizations of `period` -/ + +theorem period_eq_iff {m L : ℕ} (hm : Nat.Coprime 10 m) : + period m = L ↔ (0 < L ∧ 10 ^ L ≡ 1 [MOD m]) ∧ + ∀ k, k < L → ¬ (0 < k ∧ 10 ^ k ≡ 1 [MOD m]) := by + rw [period, dif_pos hm, Nat.find_eq_iff] + +theorem pow_eq_one_iff (m k : ℕ) : (10 : ZMod m) ^ k = 1 ↔ 10 ^ k ≡ 1 [MOD m] := by + rw [← ZMod.natCast_eq_natCast_iff] + push_cast + rfl + +/-- For `m` coprime to `10`, `period m` is the multiplicative order of `10` in `ZMod m`. -/ +theorem period_eq_orderOf {m : ℕ} (hm : Nat.Coprime 10 m) : + period m = orderOf (10 : ZMod m) := by + obtain ⟨k, hk0, hk⟩ := exists_pow_modEq_one hm + have hpos : 0 < orderOf (10 : ZMod m) := + orderOf_pos_iff.2 (isOfFinOrder_iff_pow_eq_one.2 ⟨k, hk0, (pow_eq_one_iff m k).2 hk⟩) + rw [period_eq_iff hm] + refine ⟨⟨hpos, (pow_eq_one_iff m _).1 (pow_orderOf_eq_one _)⟩, fun j hj ⟨hj0, hj1⟩ => ?_⟩ + exact (orderOf_eq_iff hpos |>.1 rfl).2 j hj hj0 ((pow_eq_one_iff m j).2 hj1) + +/-- Order certificate: `10 ^ L ≡ 1` and `10 ^ (L / q) ≢ 1` for every prime `q ∣ L`. -/ +theorem period_eq_of_cert {m L : ℕ} (hm : Nat.Coprime 10 m) (hL : 0 < L) + (h1 : 10 ^ L ≡ 1 [MOD m]) (h2 : ∀ q, q.Prime → q ∣ L → ¬ 10 ^ (L / q) ≡ 1 [MOD m]) : + period m = L := by + rw [period_eq_orderOf hm] + exact orderOf_eq_of_pow_and_pow_div_prime hL ((pow_eq_one_iff m L).2 h1) + fun q hq hqL h => h2 q hq hqL ((pow_eq_one_iff m _).1 h) + +/-! ### Kernel-friendly modular exponentiation -/ + +/-- Binary exponentiation `b ^ e % m`, with a fuel argument. -/ +def powModAux (m : ℕ) : ℕ → ℕ → ℕ → ℕ + | 0, _, _ => 1 % m + | fuel + 1, b, e => + if e = 0 then 1 % m + else if e % 2 = 1 then powModAux m fuel (b * b % m) (e / 2) * b % m + else powModAux m fuel (b * b % m) (e / 2) + +/-- `powMod b e m = b ^ e % m` (`powMod_eq`). -/ +def powMod (b e m : ℕ) : ℕ := powModAux m e b e + +theorem powModAux_eq (m : ℕ) : + ∀ fuel b e, e < 2 ^ fuel → powModAux m fuel b e = b ^ e % m := by + intro fuel + induction fuel with + | zero => + intro b e he + have : e = 0 := by simpa using he + subst this + simp [powModAux] + | succ f ih => + intro b e he + have he2 : e / 2 < 2 ^ f := by + rw [pow_succ] at he + omega + rw [powModAux, ih _ _ he2, ← Nat.pow_mod] + split_ifs with h0 h1 + · simp [h0] + · rw [Nat.mod_mul_mod, ← pow_two, ← pow_mul, ← pow_succ] + congr 2 + omega + · rw [← pow_two, ← pow_mul] + congr 2 + omega + +theorem powMod_eq (b e m : ℕ) : powMod b e m = b ^ e % m := + powModAux_eq m e b e Nat.lt_two_pow_self + +theorem modEq_one_iff_powMod (m e : ℕ) : 10 ^ e ≡ 1 [MOD m] ↔ powMod 10 e m = 1 % m := by + rw [powMod_eq] + rfl + +/-! ### Sanity checks -/ + +/-- The prime divisors of `2 * 11 ^ i` are `2` and `11`. -/ +theorem prime_dvd_two_mul_pow {q i : ℕ} (hq : q.Prime) (h : q ∣ 2 * 11 ^ i) : q = 2 ∨ q = 11 := by + rcases (Nat.Prime.dvd_mul hq).1 h with h | h + · exact Or.inl ((Nat.prime_dvd_prime_iff_eq hq Nat.prime_two).1 h) + · exact Or.inr ((Nat.prime_dvd_prime_iff_eq hq (by norm_num)).1 (hq.dvd_of_dvd_pow h)) + +/-- The certificate for the listed terms, checked in the kernel. -/ +theorem cert_data : ∀ i < 20, + powMod 10 (2 * 11 ^ i) (11 ^ (i + 1)) = 1 % 11 ^ (i + 1) ∧ + powMod 10 (2 * 11 ^ i / 2) (11 ^ (i + 1)) ≠ 1 % 11 ^ (i + 1) ∧ + (i = 0 ∨ powMod 10 (2 * 11 ^ i / 11) (11 ^ (i + 1)) ≠ 1 % 11 ^ (i + 1)) := by + decide +kernel + +/-- The definition reproduces all 20 terms `a(1), …, a(20)` listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 20).map (fun i => a (i + 1)) = + [2, 22, 242, 2662, 29282, 322102, 3543122, 38974342, 428717762, 4715895382, + 51874849202, 570623341222, 6276856753442, 69045424287862, 759499667166482, + 8354496338831302, 91899459727144322, 1010894056998587542, 11119834626984462962, + 122318180896829092582] := by + have key : ∀ i < 20, a (i + 1) = 2 * 11 ^ i := by + intro i hi + obtain ⟨h1, h2, h3⟩ := cert_data i hi + refine period_eq_of_cert (Nat.Coprime.pow_right _ (by norm_num)) (by positivity) + ((modEq_one_iff_powMod _ _).2 h1) fun q hq hqL h => ?_ + rw [modEq_one_iff_powMod] at h + rcases prime_dvd_two_mul_pow hq hqL with rfl | rfl + · exact h2 h + · rcases h3 with rfl | h3 + · norm_num at hqL + · exact h3 h + rw [List.map_congr_left fun i hi => key i (List.mem_range.1 hi)] + decide +kernel + +/-- A decidable check that `period m = L`: `gcd(10, m) = 1`, `L ≥ 1`, `10 ^ L ≡ 1 (mod m)` and +`10 ^ k ≢ 1 (mod m)` for `0 < k < L`. -/ +def checkPeriod (m L : ℕ) : Bool := + Nat.gcd 10 m == 1 && 0 < L && 10 ^ L % m == 1 % m && + (List.range L).all fun k => k == 0 || 10 ^ k % m != 1 % m + +theorem period_eq_of_checkPeriod {m L : ℕ} (h : checkPeriod m L = true) : period m = L := by + simp only [checkPeriod, Bool.and_eq_true, beq_iff_eq, decide_eq_true_eq, List.all_eq_true, + List.mem_range, Bool.or_eq_true, bne_iff_ne, ne_eq] at h + obtain ⟨⟨⟨hm, hL⟩, h1⟩, h2⟩ := h + rw [period_eq_iff hm] + refine ⟨⟨hL, h1⟩, fun k hk ⟨hk0, hk1⟩ => ?_⟩ + rcases h2 k hk with h | h + · omega + · exact h hk1 + +/-- `period` agrees with the 35 terms `A051626(m)` listed in OEIS with `3 ≤ m ≤ 90` and +`gcd(m, 10) = 1` (A051626: period of the decimal representation of `1/m`; kernel-checked). -/ +theorem period_data : ∀ p ∈ [(3, 1), (7, 6), (9, 1), (11, 2), (13, 6), (17, 16), (19, 18), + (21, 6), (23, 22), (27, 3), (29, 28), (31, 15), (33, 2), (37, 3), (39, 6), (41, 5), (43, 21), + (47, 46), (49, 42), (51, 16), (53, 13), (57, 18), (59, 58), (61, 60), (63, 6), (67, 33), + (69, 22), (71, 35), (73, 8), (77, 6), (79, 13), (81, 9), (83, 41), (87, 28), (89, 44)], + period p.1 = p.2 := by + intro p hp + exact period_eq_of_checkPeriod (by revert p; decide +kernel) + +/-! ### The conjectures -/ + +/-- Conjecture (A334603, FORMULA, "conjectured, see comments"): the period of the decimal +expansion of `1/11^n` is `2 * 11^(n-1)`, for every `n ≥ 1`. -/ +def statement : Prop := ∀ n : ℕ, 1 ≤ n → a n = 2 * 11 ^ (n - 1) + +/-- The general conjecture of De Koninck & Mercier quoted in the COMMENTS of A334603: if `p` is a +prime with `gcd(p, 30) = 1` and the period of `1/p` is `m`, then for every `n ≥ 1` the period of +`1/p^n` is `m * p^(n-1)`. -/ +def statement_general : Prop := + ∀ p n : ℕ, p.Prime → Nat.gcd p 30 = 1 → 1 ≤ n → period (p ^ n) = period p * p ^ (n - 1) + +end Math0.Statements.A334603 diff --git a/lean/Math0/Statements/OEIS/A335012.lean b/lean/Math0/Statements/OEIS/A335012.lean new file mode 100644 index 0000000..953e0bc --- /dev/null +++ b/lean/Math0/Statements/OEIS/A335012.lean @@ -0,0 +1,103 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A335012: distinct remainders of the repunits 1, 11, ..., R_n modulo n + +Source: https://oeis.org/A335012, _Sen-Peng Eu_, May 19 2020. Verbatim: +> Conjecture: a(n) = n-1 if and only if n is a long period prime (A006883), that is, n is a prime +> and the decimal expansion of 1/n has period n-1. + +The entry's definition: "Number of different remainders when the first n terms of +1, 11, 111, 1111, ... are divided by n." (offset `1`). + +## Encoding + +* The `k`-th term of `1, 11, 111, ...` is the repunit `R_k = (10^k - 1) / 9` (`k ≥ 1`), and + `a n` is the number of distinct values `R_k % n` for `1 ≤ k ≤ n`, i.e. the cardinality of the + image of `k ↦ R_k % n` on `Finset.Icc 1 n`. This is exactly the PARI/Maple programs of the + entry. `a_data` checks all 81 listed terms `a(1..81)`. +* A006883 ("Long period primes: the decimal expansion of 1/p has period p-1") includes `2`, by the + convention stated there (1/2 = 0.5000..., period 1 = 2-1); its own Maple/Mathematica programs + test `p = 2 ∨ ord_p(10) = p - 1` over primes `p`. For a prime `p ∉ {2, 5}` the period of the + decimal expansion of `1/p` is the multiplicative order of `10` modulo `p`; for `p = 5` the + period is `1 ≠ 4` (and `orderOf (10 : ZMod 5) = orderOf 0 = 0 ≠ 4` in Mathlib, so no special + case is needed there). Hence `IsLongPeriodPrime p := p.Prime ∧ (p = 2 ∨ orderOf (10 : ZMod p) = + p - 1)`. As a sanity check, `isLongPeriodPrime_data` (kernel-checked, through the decidable + reformulation `isLongPeriodPrimeB_iff`) reproduces the first 24 listed terms of A006883 (the + members below 270). +* The conjecture is read for every index of the sequence, i.e. all `n ≥ 1` (offset 1). (For + `n = 0` the truncated subtraction would make `a 0 = 0 - 1` hold vacuously, so the range + `1 ≤ n` is part of the statement.) +-/ + +namespace Math0.Statements.A335012 + +/-- A335012: the number of different remainders when the first `n` repunits +`1, 11, 111, ..., R_n` (with `R_k = (10^k - 1) / 9`) are divided by `n`. -/ +def a (n : ℕ) : ℕ := ((Finset.Icc 1 n).image (fun k => ((10 ^ k - 1) / 9) % n)).card + +/-- The definition reproduces the 81 terms `a(1), ..., a(81)` listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 81).map (fun i => a (i + 1)) = + [1, 1, 3, 2, 1, 3, 6, 3, 9, 1, 2, 4, 6, 6, 3, 4, 16, 9, 18, 2, 6, 2, 22, 5, 2, 6, 27, 7, 28, 3, + 15, 5, 6, 16, 6, 10, 3, 18, 6, 3, 5, 6, 21, 3, 9, 22, 46, 6, 42, 2, 48, 7, 13, 27, 2, 8, 18, + 28, 58, 4, 60, 15, 18, 6, 6, 6, 33, 17, 66, 6, 35, 11, 8, 3, 4, 19, 6, 6, 13, 4, 81] := by + decide +kernel + +/-- Long period primes (A006883): primes `p` such that the decimal expansion of `1/p` has period +`p - 1`. For `p = 2` the period is `1 = p - 1` (A006883 includes `2`); for every other prime the +condition is that `10` has multiplicative order `p - 1` modulo `p` (for `p = 5`, where `10 ≡ 0`, +Mathlib's `orderOf` is `0`, matching the fact that `1/5` has period `1 ≠ 4`). -/ +def IsLongPeriodPrime (p : ℕ) : Prop := + p.Prime ∧ (p = 2 ∨ orderOf (10 : ZMod p) = p - 1) + +/-- A decidable reformulation of `IsLongPeriodPrime`, used only for the sanity check below. -/ +def isLongPeriodPrimeB (p : ℕ) : Bool := + decide p.Prime && (p == 2 || (10 ^ (p - 1) % p == 1 % p && + (List.range' 1 (p - 2)).all fun m => 10 ^ m % p != 1 % p)) + +theorem isLongPeriodPrimeB_iff (p : ℕ) : isLongPeriodPrimeB p = true ↔ IsLongPeriodPrime p := by + have key : ∀ m : ℕ, (10 : ZMod p) ^ m = 1 ↔ 10 ^ m % p = 1 % p := fun m => by + rw [← ZMod.natCast_eq_natCast_iff'] + push_cast + rfl + simp only [isLongPeriodPrimeB, IsLongPeriodPrime, Bool.and_eq_true, decide_eq_true_eq, + Bool.or_eq_true, beq_iff_eq, List.all_eq_true, List.mem_range'_1, bne_iff_ne, ne_eq] + constructor + · rintro ⟨hp, h⟩ + refine ⟨hp, ?_⟩ + rcases h with h | ⟨h1, h2⟩ + · exact Or.inl h + · right + have h2' := hp.two_le + rw [orderOf_eq_iff (by omega)] + refine ⟨(key _).2 h1, fun m hm hm0 => ?_⟩ + rw [Ne, key] + exact h2 m ⟨hm0, by omega⟩ + · rintro ⟨hp, h⟩ + refine ⟨hp, ?_⟩ + rcases h with h | h + · exact Or.inl h + · right + have h2' := hp.two_le + rw [orderOf_eq_iff (by omega)] at h + refine ⟨(key _).1 h.1, fun m hm => ?_⟩ + rw [← key] + exact h.2 m (by omega) hm.1 + +/-- Sanity check: the long period primes below `270` are exactly the first 24 terms of A006883 +listed in OEIS (kernel-checked). -/ +theorem isLongPeriodPrime_data : + (List.range 270).filter isLongPeriodPrimeB = + [2, 7, 17, 19, 23, 29, 47, 59, 61, 97, 109, 113, 131, 149, 167, 179, 181, 193, 223, 229, + 233, 257, 263, 269] := by + decide +kernel + +/-- Conjecture (Eu, A335012): for every `n ≥ 1`, `a(n) = n - 1` if and only if `n` is a long +period prime (A006883), i.e. `n` is prime and the decimal expansion of `1/n` has period `n - 1`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → (a n = n - 1 ↔ IsLongPeriodPrime n) + +end Math0.Statements.A335012 diff --git a/lean/Math0/Statements/OEIS/A338885.lean b/lean/Math0/Statements/OEIS/A338885.lean new file mode 100644 index 0000000..038b9ec --- /dev/null +++ b/lean/Math0/Statements/OEIS/A338885.lean @@ -0,0 +1,215 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A338885: diagonal lattice rectangles inscribed in an n X k box + +Source: https://oeis.org/A338885, _Peter Kagey_, Nov 14 2020. Verbatim: +> Conjecture: The smallest number in the n-th row is A228286(n). + +The entry's definition: "Irregular triangle read by rows in which the n-th row lists all numbers +k such that there exists a diagonal lattice rectangle touching all four sides of an n X k +rectangle." and "A diagonal lattice rectangle is a rectangle with integer coordinates and no side +parallel to the x-axis." Rows are indexed from `n = 2` (offset `2`), and A228286 (offset `2`) is +"Smallest x + y*z, given x*y + z = n (for positive integers x, y, z)." + +## Encoding + +* The `n X k` rectangle is the closed box `[0, n] × [0, k]` in the plane. +* A lattice rectangle is given by one vertex `(x₀, y₀) ∈ ℤ²` and two perpendicular integer side + vectors `u = (u₁, u₂)`, `v = (v₁, v₂)`; its vertices are `P₀ = (x₀, y₀)`, `P₀ + u`, + `P₀ + u + v`, `P₀ + v`. Every rectangle with integer vertices arises this way (squares included). +* "No side parallel to the x-axis": every side is parallel to `u` or to `v`, so this is + `u₂ ≠ 0 ∧ v₂ ≠ 0`; in particular `u, v ≠ 0`, so the rectangle is non-degenerate. +* "Touching all four sides of the n X k rectangle" is read as: the lattice rectangle lies inside + the box (i.e. all four vertices do, the rectangle being their convex hull) and meets each of the + four sides. For a convex polygon inside the box, meeting the side on the line `x = 0` (resp. + `x = n`, `y = 0`, `y = k`) is the same as having a vertex on that line. +* `InRow n k` is this geometric condition. We prove (`inRow_iff_param`) that it is equivalent to + `∃ a b c d > 0, a + b = n ∧ c + d = k ∧ a * b = c * d`, deduce the bound + `k ≤ n * n / 4 + 1` for every `k` in row `n`, and so the finite list `row n` (computed by a + bounded search, increasing) has exactly the members of row `n` (`mem_row`). The flattened + sequence `a` uses the OEIS indexing of the b-file (`a 2, a 3, …` are the terms, row by row). +* `A228286 n` is the minimum of `x + y * z` over the (finitely many) positive triples with + `x * y + z = n`, computed by a bounded search; `isLeast_A228286` certifies it for `n ≥ 2`. +* The conjecture concerns every row, i.e. every `n ≥ 2`. +-/ + +namespace Math0.Statements.A338885 + +/-- The integer point `(x, y)` lies in the closed box `[0, n] × [0, k]`. -/ +def InBox (n k : ℕ) (p : ℤ × ℤ) : Prop := + 0 ≤ p.1 ∧ p.1 ≤ n ∧ 0 ≤ p.2 ∧ p.2 ≤ k + +/-- The four vertices `P₀, P₀ + u, P₀ + u + v, P₀ + v` of the lattice rectangle with corner +`P₀ = (x₀, y₀)` and side vectors `u = (u₁, u₂)`, `v = (v₁, v₂)`. -/ +def vertices (x₀ y₀ u₁ u₂ v₁ v₂ : ℤ) : List (ℤ × ℤ) := + [(x₀, y₀), (x₀ + u₁, y₀ + u₂), (x₀ + u₁ + v₁, y₀ + u₂ + v₂), (x₀ + v₁, y₀ + v₂)] + +/-- `k` belongs to the `n`-th row: there is a diagonal lattice rectangle (integer vertices, +perpendicular sides, no side parallel to the x-axis) lying in the `n X k` box `[0, n] × [0, k]` +and touching all four of its sides. -/ +def InRow (n k : ℕ) : Prop := + ∃ x₀ y₀ u₁ u₂ v₁ v₂ : ℤ, + -- the sides `u` and `v` are perpendicular (so the parallelogram is a rectangle) + u₁ * v₁ + u₂ * v₂ = 0 ∧ + -- no side is parallel to the x-axis + u₂ ≠ 0 ∧ v₂ ≠ 0 ∧ + -- the rectangle lies in the box + (∀ p ∈ vertices x₀ y₀ u₁ u₂ v₁ v₂, InBox n k p) ∧ + -- it touches the sides `x = 0`, `x = n`, `y = 0`, `y = k` + (∃ p ∈ vertices x₀ y₀ u₁ u₂ v₁ v₂, p.1 = 0) ∧ + (∃ p ∈ vertices x₀ y₀ u₁ u₂ v₁ v₂, p.1 = n) ∧ + (∃ p ∈ vertices x₀ y₀ u₁ u₂ v₁ v₂, p.2 = 0) ∧ + (∃ p ∈ vertices x₀ y₀ u₁ u₂ v₁ v₂, p.2 = k) + +/-- Boolean search used to compute the rows: `a * (n - a) = c * (k - c)` for some +`0 < a < n`, `0 < c < k`. Justified by `inRowB_iff`. -/ +def inRowB (n k : ℕ) : Bool := + (List.range' 1 (n - 1)).any fun a => (List.range' 1 (k - 1)).any fun c => + a * (n - a) == c * (k - c) + +/-- The `n`-th row, in increasing order: all `k ≤ n * n / 4 + 1` with `inRowB n k` +(see `mem_row`: these are exactly the `k` with `InRow n k`). -/ +def row (n : ℕ) : List ℕ := + (List.range (n * n / 4 + 2)).filter (inRowB n) + +/-- Read the flattened triangle starting at row `n`, skipping `j` terms (`fuel` bounds the +number of rows visited; every row `n ≥ 2` is nonempty, so `fuel = i` suffices below). -/ +def flatAux : ℕ → ℕ → ℕ → ℕ + | 0, _, _ => 0 + | fuel + 1, n, j => + if j < (row n).length then (row n).getD j 0 else flatAux fuel (n + 1) (j - (row n).length) + +/-- A338885 as a flattened sequence, indexed as in the OEIS b-file (`a 2` is the first term). -/ +def a (i : ℕ) : ℕ := flatAux i 2 (i - 2) + +/-! ### The rows: geometric definition versus the computed list -/ + +/-- The four side lengths of a diagonal rectangle in the box: `InRow n k` iff +`n = a + b`, `k = c + d` and `a * b = c * d` for some positive `a, b, c, d`. -/ +theorem inRow_iff_param (n k : ℕ) : + InRow n k ↔ ∃ a b c d : ℕ, 0 < a ∧ 0 < b ∧ 0 < c ∧ 0 < d ∧ + a + b = n ∧ c + d = k ∧ a * b = c * d := by + constructor + · rintro ⟨x₀, y₀, u₁, u₂, v₁, v₂, hperp, hu, hv, hbox, h0, hn, h0', hk⟩ + simp only [vertices, InBox, List.forall_mem_cons, List.not_mem_nil, IsEmpty.forall_iff, + forall_const, and_true] at hbox + simp only [vertices, List.mem_cons, List.not_mem_nil, or_false, or_and_right, exists_or, + exists_eq_left] at h0 hn h0' hk + have huv : u₂ * v₂ ≠ 0 := mul_ne_zero hu hv + have hu₁ : u₁ ≠ 0 := by rintro rfl; apply huv; linarith + have hv₁ : v₁ ≠ 0 := by rintro rfl; apply huv; linarith + have hprod : u₁.natAbs * v₁.natAbs = u₂.natAbs * v₂.natAbs := by + have h := congrArg Int.natAbs (show u₁ * v₁ = -(u₂ * v₂) by linarith) + simpa [Int.natAbs_mul, Int.natAbs_neg] using h + refine ⟨u₁.natAbs, v₁.natAbs, u₂.natAbs, v₂.natAbs, Int.natAbs_pos.mpr hu₁, + Int.natAbs_pos.mpr hv₁, Int.natAbs_pos.mpr hu, Int.natAbs_pos.mpr hv, ?_, ?_, hprod⟩ + · omega + · omega + · rintro ⟨a, b, c, d, ha, hb, hc, hd, hn, hk, hab⟩ + subst hn hk + refine ⟨b, 0, a, c, -b, d, ?_, by exact_mod_cast hc.ne', by exact_mod_cast hd.ne', ?_, ?_, ?_, + ?_, ?_⟩ + · have : ((a * b : ℕ) : ℤ) = ((c * d : ℕ) : ℤ) := by rw [hab] + push_cast at this; linarith + all_goals simp [vertices, InBox] + all_goals omega + +theorem inRowB_iff (n k : ℕ) : + inRowB n k = true ↔ ∃ a b c d : ℕ, 0 < a ∧ 0 < b ∧ 0 < c ∧ 0 < d ∧ + a + b = n ∧ c + d = k ∧ a * b = c * d := by + simp only [inRowB, List.any_eq_true, List.mem_range'_1, beq_iff_eq] + constructor + · rintro ⟨a, ⟨ha1, ha2⟩, c, ⟨hc1, hc2⟩, h⟩ + exact ⟨a, n - a, c, k - c, by omega, by omega, by omega, by omega, by omega, by omega, h⟩ + · rintro ⟨a, b, c, d, ha, hb, hc, hd, rfl, rfl, h⟩ + exact ⟨a, ⟨ha, by omega⟩, c, ⟨hc, by omega⟩, by simpa using h⟩ + +/-- Every member of row `n` is at most `n * n / 4 + 1`. -/ +theorem le_of_inRow {n k : ℕ} (h : InRow n k) : k ≤ n * n / 4 + 1 := by + obtain ⟨a, b, c, d, ha, hb, hc, hd, rfl, rfl, hab⟩ := (inRow_iff_param _ _).1 h + have h1 : c + d ≤ c * d + 1 := by nlinarith + have h2 : a * b ≤ (a + b) * (a + b) / 4 := by + rw [Nat.le_div_iff_mul_le (by norm_num)] + zify + nlinarith [sq_nonneg ((a : ℤ) - b)] + omega + +/-- `row n` lists exactly the members of the `n`-th row. -/ +theorem mem_row (n k : ℕ) : k ∈ row n ↔ InRow n k := by + rw [row, List.mem_filter, List.mem_range, inRowB_iff, ← inRow_iff_param] + constructor + · exact fun h => h.2 + · exact fun h => ⟨by have := le_of_inRow h; omega, h⟩ + +/-- `row n` is strictly increasing, as the OEIS rows are listed. -/ +theorem row_sorted (n : ℕ) : (row n).Pairwise (· < ·) := + (List.pairwise_lt_range).filter _ + +/-- The first terms listed in OEIS (rows 2 to 12 complete and the start of row 13), +kernel-checked. -/ +theorem a_data : (List.range 71).map (fun i => a (i + 2)) = + [2, 3, 4, 5, 4, 5, 7, 6, 9, 10, 5, 7, 8, 11, 13, 7, 8, 10, 13, 16, 17, 6, 9, 11, 12, 15, 19, + 21, 6, 8, 10, 11, 14, 17, 22, 25, 26, 7, 9, 10, 11, 13, 14, 16, 17, 19, 25, 29, 31, 9, 12, + 13, 15, 18, 20, 21, 28, 33, 36, 37, 7, 8, 11, 12, 13, 14, 15, 17, 20, 22, 23] := by + decide +kernel + +/-! ### A228286 -/ + +/-- The values `x + y * z` over positive integers `x, y, z` with `x * y + z = n`. -/ +def A228286Set (n : ℕ) : Set ℕ := + {m | ∃ x y z : ℕ, 0 < x ∧ 0 < y ∧ 0 < z ∧ x * y + z = n ∧ m = x + y * z} + +/-- The list of the values `x + y * (n - x * y)` over `0 < x, y < n` with `x * y < n`. -/ +def A228286List (n : ℕ) : List ℕ := + (List.range' 1 (n - 1)).flatMap fun x => (List.range' 1 (n - 1)).filterMap fun y => + if x * y < n then some (x + y * (n - x * y)) else none + +/-- A228286: smallest `x + y * z`, given `x * y + z = n` (for positive integers `x, y, z`); +computed as the minimum of `A228286List n` (see `isLeast_A228286`). -/ +def A228286 (n : ℕ) : ℕ := (A228286List n).min?.getD 0 + +theorem mem_A228286List (n m : ℕ) : m ∈ A228286List n ↔ m ∈ A228286Set n := by + simp only [A228286List, List.mem_flatMap, List.mem_range'_1, List.mem_filterMap, + Option.ite_none_right_eq_some, Option.some.injEq, A228286Set, Set.mem_ofPred_eq] + constructor + · rintro ⟨x, ⟨hx1, hx2⟩, y, ⟨hy1, hy2⟩, hxy, rfl⟩ + exact ⟨x, y, n - x * y, by omega, by omega, by omega, by omega, rfl⟩ + · rintro ⟨x, y, z, hx, hy, hz, rfl, rfl⟩ + have h1 : x ≤ x * y := Nat.le_mul_of_pos_right x hy + have h2 : y ≤ x * y := Nat.le_mul_of_pos_left y hx + exact ⟨x, ⟨hx, by omega⟩, y, ⟨hy, by omega⟩, by omega, by + rw [show x * y + z - x * y = z by omega]⟩ + +/-- `A228286 n` is the least element of `A228286Set n` for `n ≥ 2` (the OEIS range). -/ +theorem isLeast_A228286 {n : ℕ} (hn : 2 ≤ n) : IsLeast (A228286Set n) (A228286 n) := by + have hne : A228286List n ≠ [] := by + intro h + have : n - 1 + 1 * 1 ∈ A228286List n := by + rw [mem_A228286List] + exact ⟨n - 1, 1, 1, by omega, by omega, by omega, by omega, rfl⟩ + rw [h] at this + simp at this + obtain ⟨m, hm⟩ := Option.isSome_iff_exists.mp (List.isSome_min?_of_ne_nil hne) + rw [A228286, hm, Option.getD_some] + obtain ⟨hmem, hle⟩ := List.min?_eq_some_iff.mp hm + exact ⟨(mem_A228286List n m).1 hmem, fun b hb => hle b ((mem_A228286List n b).2 hb)⟩ + +/-- A228286 (offset 2) reproduces its first 70 listed OEIS terms (kernel-checked). -/ +theorem A228286_data : (List.range 70).map (fun i => A228286 (i + 2)) = + [2, 3, 4, 4, 6, 5, 7, 6, 6, 7, 9, 7, 10, 9, 8, 8, 12, 9, 12, 9, 10, 13, 15, 10, 10, 15, 12, + 11, 15, 11, 16, 12, 14, 17, 12, 12, 17, 21, 16, 13, 18, 13, 19, 15, 14, 19, 24, 14, 14, 15, + 20, 17, 21, 15, 16, 15, 22, 25, 28, 16, 22, 27, 16, 16, 18, 17, 23, 21, 25, 17] := by + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjecture (Kagey, A338885): for every row `n ≥ 2`, the smallest number `k` such that a +diagonal lattice rectangle touches all four sides of the `n X k` box is `A228286 n`. -/ +def statement : Prop := + ∀ n : ℕ, 2 ≤ n → IsLeast {k : ℕ | InRow n k} (A228286 n) + +end Math0.Statements.A338885 diff --git a/lean/Math0/Statements/OEIS/A341761.lean b/lean/Math0/Statements/OEIS/A341761.lean new file mode 100644 index 0000000..d02e3b9 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A341761.lean @@ -0,0 +1,205 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A341761: leading coefficient of the subword complexity polynomial + +Source: https://oeis.org/A341761, Shiyao Guo, Feb 19 2021 (COMMENTS section). Verbatim: +> Conjecture: the coefficient of x^n in S(n,x) is n*(n+1)/2. + +The entry (offset `0`, keywords `sign,tabl`) is "Triangle read by rows in which row n is the +coefficients of the subword complexity polynomial S(n,x)." Its comments explain: "S(n,x) is the +sum of subword complexities (number of nonempty distinct subwords) of all words of length n and an +alphabet with size x", and "The degree of S(n,x) is n." The example (`S(3,2) = 36`: the words +`aaa, aab, …, bbb` have `3, 5, 5, 5, 5, 5, 5, 3` distinct nonempty subwords) and the Mathematica +program (which takes all `Subsequences`, i.e. contiguous pieces) confirm that "subword" means a +*factor* (contiguous subword), and that the coefficients are listed constant term first. + +## Encoding + +* *Factors.* `factors w` is the finite set of distinct nonempty factors of the word `w`, computed + as the nonempty prefixes of the suffixes of `w`; `mem_factors` proves + `u ∈ factors w ↔ u ≠ [] ∧ u <:+: w` (`<:+:` is Mathlib's "is a contiguous infix of"). + `complexity w = (factors w).card` is the subword complexity of `w`. +* *`S(n, x)`.* `S n x = ∑ w : Fin n → Fin x, complexity (List.ofFn w)`: the words of length `n` + over an alphabet of size `x` are the maps `Fin n → Fin x`. (For `x = 0, n ≥ 1` there are no + words and `S n 0 = 0`; for `n = 0` there is one, empty, word with complexity `0`.) For + evaluation, `words x n` lists the same words as lists and `S_eq_Sw` proves + `S n x = Sw n x := ((words x n).map complexity).sum`. +* *The polynomial and the conjecture.* "The polynomial `S(n,x)`" is read as a polynomial + `P : ℚ[X]` with `P(x) = S(n, x)` for every `x ∈ ℕ`. Such a `P` is unique when it exists, since + two polynomials agreeing on the infinite set `ℕ` coincide (`poly_unique`). `statement` says: for + every `n ≥ 0` there is such a polynomial `P` and its coefficient of `x^n` is `n(n+1)/2`. The + entry asserts, as a fact, that `S(n, x)` is a polynomial in `x` of degree `n`; the existential + in `statement` includes the polynomiality part. Rational coefficients are allowed, so no + integrality is assumed. +* *The triangle.* Row `n` lists the `n + 1` coefficients of `x^0, …, x^n` (the triangle shape + encodes the degree `n` stated in the entry). Since a polynomial of degree `≤ n` is determined by + its values at `x = 0, …, n`, `row n` computes these coefficients from `S(n,0), …, S(n,n)` by + Newton's forward-difference formula `P(x) = ∑_{k ≤ n} Δ^k S(n,·)(0) · C(x, k)` (`interp`), + working in `ℚ`. This reproduces the coefficients of `S(n,x)` exactly when `S(n,·)` is a + polynomial of degree `≤ n`, as the entry states. `a` is the triangle read by rows (offset `0`): + `a m` is entry `k` of row `n`, where `m = n(n+1)/2 + k`, `0 ≤ k ≤ n` (`rowCol`). It is + `ℚ`-valued because the interpolation is done over `ℚ`; the data check confirms the listed terms + are the integers given in OEIS. +* *Data.* `S(n, x)` is computed by brute force over all `x^n` words, so the kernel can only reach + small rows: `rows_data` checks rows `n = 0, …, 5`, and `a_data` the corresponding first `21` + terms `a 0, …, a 20` (row `6` would need the `46656` words of length `6` over `6` letters). +-/ + +namespace Math0.Statements.A341761 + +open Polynomial + +/-! ### Factors, subword complexity and `S(n, x)` -/ + +/-- The distinct nonempty factors (contiguous subwords) of the word `w`: the nonempty prefixes of +the suffixes of `w` (see `mem_factors`). -/ +def factors {α : Type*} [DecidableEq α] (w : List α) : Finset (List α) := + (w.tails.flatMap fun t => t.inits.tail).toFinset + +theorem mem_inits_tail {α : Type*} (u : List α) : + ∀ t : List α, u ∈ t.inits.tail ↔ u ≠ [] ∧ u <+: t + | [] => by simp + | a :: l => by + simp only [List.inits_cons, List.tail_cons, List.mem_map, List.mem_inits] + constructor + · rintro ⟨v, hv, rfl⟩ + exact ⟨List.cons_ne_nil _ _, List.prefix_cons_inj _ |>.2 hv⟩ + · rintro ⟨hu, hp⟩ + rcases u with _ | ⟨b, v⟩ + · exact absurd rfl hu + · obtain ⟨rfl, hv⟩ := List.cons_prefix_cons.1 hp + exact ⟨v, hv, rfl⟩ + +/-- `factors w` is exactly the set of nonempty contiguous subwords of `w`. -/ +theorem mem_factors {α : Type*} [DecidableEq α] (w u : List α) : + u ∈ factors w ↔ u ≠ [] ∧ u <:+: w := by + simp only [factors, List.mem_toFinset, List.mem_flatMap, List.mem_tails, mem_inits_tail, + List.infix_iff_prefix_suffix] + constructor + · rintro ⟨t, ht, hu, hp⟩ + exact ⟨hu, t, hp, ht⟩ + · rintro ⟨hu, t, hp, ht⟩ + exact ⟨t, ht, hu, hp⟩ + +/-- The subword complexity of `w`: the number of distinct nonempty factors of `w`. -/ +def complexity {α : Type*} [DecidableEq α] (w : List α) : ℕ := (factors w).card + +/-- `S(n, x)`: the sum of the subword complexities of all `x^n` words of length `n` over an +alphabet of size `x` (the words are the maps `Fin n → Fin x`). -/ +def S (n x : ℕ) : ℕ := ∑ w : Fin n → Fin x, complexity (List.ofFn w) + +/-- Two polynomials over `ℚ` that agree at every natural number are equal; so "the polynomial +`S(n, x)`" is well defined whenever one exists. -/ +theorem poly_unique (P Q : ℚ[X]) (h : ∀ x : ℕ, P.eval (x : ℚ) = Q.eval (x : ℚ)) : P = Q := by + apply Polynomial.eq_of_infinite_eval_eq + apply Set.infinite_of_injective_forall_mem (f := fun x : ℕ => (x : ℚ)) Nat.cast_injective + intro x + exact h x + +/-! ### Evaluating `S(n, x)` -/ + +/-- All words of length `n` over the alphabet `Fin x`, as lists. -/ +def words (x : ℕ) : ℕ → List (List (Fin x)) + | 0 => [[]] + | n + 1 => (List.finRange x).flatMap fun c => (words x n).map (c :: ·) + +theorem sum_map_flatMap {β γ : Type*} (l : List β) (f : β → List γ) (g : γ → ℕ) : + ((l.flatMap f).map g).sum = (l.map fun b => ((f b).map g).sum).sum := by + induction l with + | nil => simp + | cons b l ih => simp [List.flatMap_cons, List.sum_append, ih] + +theorem sum_ofFn_eq (x : ℕ) : ∀ (n : ℕ) (g : List (Fin x) → ℕ), + ∑ w : Fin n → Fin x, g (List.ofFn w) = ((words x n).map g).sum + | 0, g => by simp [words] + | n + 1, g => by + rw [← (Fin.consEquiv (fun _ => Fin x)).sum_comp, Fintype.sum_prod_type, Fin.sum_univ_def, + words, sum_map_flatMap] + congr 1 + refine List.map_congr_left fun c _ => ?_ + rw [List.map_map, ← sum_ofFn_eq x n (g ∘ fun l => c :: l)] + simp [Fin.consEquiv_apply, List.ofFn_succ] + +/-- `S(n, x)` summed over the list `words x n`. -/ +def Sw (n x : ℕ) : ℕ := ((words x n).map complexity).sum + +theorem S_eq_Sw : S = Sw := by + funext n x + exact sum_ofFn_eq x n complexity + +/-! ### The triangle -/ + +/-- One step of forward differences: `[v₀, v₁, v₂, …] ↦ [v₁ - v₀, v₂ - v₁, …]`. -/ +def diff (v : List ℚ) : List ℚ := List.zipWith (fun a b => b - a) v v.tail + +/-- Multiply the polynomial with coefficient list `p` (constant term first) by `X - c`. -/ +def mulXSub (c : ℚ) (p : List ℚ) : List ℚ := + List.zipWith (· + ·) (0 :: p) (p.map (fun a => -c * a) ++ [0]) + +/-- The coefficients (constant term first) of `C(X, k) = X (X - 1) ⋯ (X - k + 1) / k!`. -/ +def binomCoeffs (k : ℕ) : List ℚ := + ((List.range k).foldl (fun p i => mulXSub i p) [1]).map (· / k.factorial) + +/-- The coefficients `[c₀, …, cₙ]` (constant term first) of the polynomial of degree `≤ n` that +takes the values `v = [v₀, …, vₙ]` at `x = 0, …, n`, by Newton's forward-difference formula +`P(x) = ∑_{k ≤ n} Δ^k v₀ · C(x, k)`. -/ +def interp (v : List ℚ) : List ℚ := + (List.range v.length).map fun j => + ((List.range v.length).map fun k => (diff^[k] v).headD 0 * (binomCoeffs k).getD j 0).sum + +/-- Row `n` of the triangle: the coefficients of `x^0, …, x^n` in `S(n, x)`, interpolated from +the values `S(n, 0), …, S(n, n)`. -/ +def row (n : ℕ) : List ℚ := interp ((List.range (n + 1)).map fun x => (S n x : ℚ)) + +/-- The position `m` of a triangle read by rows is entry `k` of row `n`, where +`m = n(n+1)/2 + k` and `0 ≤ k ≤ n`; `rowCol m = (n, k)`. -/ +def rowCol (m : ℕ) : ℕ × ℕ := + let n := (List.range (m + 1)).foldl (fun acc i => if i * (i + 1) / 2 ≤ m then i else acc) 0 + (n, m - n * (n + 1) / 2) + +/-- A341761: the triangle read by rows whose row `n` lists the coefficients (of `x^0, …, x^n`) +of the subword complexity polynomial `S(n, x)`. -/ +def a (m : ℕ) : ℚ := (row (rowCol m).1).getD (rowCol m).2 0 + +/-! ### Data -/ + +/-- `row` with `S` replaced by its list evaluation `Sw`. -/ +def rowW (n : ℕ) : List ℚ := interp ((List.range (n + 1)).map fun x => (Sw n x : ℚ)) + +theorem row_eq_rowW : row = rowW := by + funext n + simp only [row, rowW, S_eq_Sw] + +set_option maxRecDepth 100000 in +/-- Rows `n = 0, …, 5` of the triangle, as listed in OEIS (kernel-checked). -/ +theorem rows_data : (List.range 6).map row = + [[0], [0, 1], [0, -1, 3], [0, 0, -3, 6], [0, -1, 1, -6, 10], [0, 2, -6, 4, -10, 15]] := by + rw [row_eq_rowW] + decide +kernel + +theorem a_eq_getD (N m : ℕ) (h : (rowCol m).1 < N) : + a m = (((List.range N).map row).getD (rowCol m).1 []).getD (rowCol m).2 0 := by + simp [a, List.getD_eq_getElem?_getD, List.getElem?_map, List.getElem?_range h] + +/-- The definition reproduces the first `21` terms listed in OEIS (rows `0`–`5`; +kernel-checked through `rows_data`). -/ +theorem a_data : (List.range 21).map (fun i => a (i + 0)) = + [0, 0, 1, 0, -1, 3, 0, 0, -3, 6, 0, -1, 1, -6, 10, 0, 2, -6, 4, -10, 15] := by + have hlt : ∀ m ∈ List.range 21, (rowCol m).1 < 6 := by decide + rw [List.map_congr_left fun m hm => a_eq_getD 6 (m + 0) (hlt m hm), rows_data] + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjecture (Shiyao Guo): for every `n ≥ 0`, the subword complexity polynomial `S(n, x)` (a +polynomial `P` with `P(x) = S(n, x)` for all `x ∈ ℕ`, unique by `poly_unique`) has coefficient +`n(n+1)/2` at `x^n`. -/ +def statement : Prop := + ∀ n : ℕ, ∃ P : ℚ[X], (∀ x : ℕ, P.eval (x : ℚ) = (S n x : ℚ)) ∧ + P.coeff n = (n : ℚ) * (n + 1) / 2 + +end Math0.Statements.A341761 diff --git a/lean/Math0/Statements/OEIS/A342645.lean b/lean/Math0/Statements/OEIS/A342645.lean new file mode 100644 index 0000000..3221d02 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A342645.lean @@ -0,0 +1,385 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A342645: diagonals of the eventual Mahonian-column polynomials + +Source: https://oeis.org/A342645, _Peter Kagey_, Mar 17 2021 (COMMENTS and FORMULA sections). +Verbatim: +> Conjecture: For each m, T(n,n-m) is a polynomial of degree 2m whose leading coefficient is +> abs(A290030(m)/A053657(m+1)). + +and +> Conjectures: +> T(n,n) = 1. +> T(n,n-1) = (-3n + n^2)/2. +> T(n,n-2) = (-2n + 21n^2 - 22n^3 + 3n^4)/24. +> T(n,n-3) = (96n - 134n^2 + 13n^3 + 37n^4 - 13n^5 + n^6)/48. + +The entry (offset `0`, keywords `sign,tabl`) is "Triangle read by rows: T(n,k) gives n! times +the coefficient of x^k in the polynomial that describes the number of permutations on x letters +with major index n", with the comment "This n-th row describes a polynomial that eventually +agrees with the n-th column of A008302." + +## Encoding + +* *Mahonian numbers.* `mahonianPoly x = ∏_{i=0}^{x-1} (1 + q + ⋯ + q^i) ∈ ℕ[q]` is the generating + polynomial of row `x` of A008302 ("Triangle of Mahonian numbers T(n,k): coefficients in + expansion of Product_{i=0..n-1} (1 + x + ... + x^i)"). `mahonian x n` computes its coefficient + of `q^n` by a row recursion (multiply the previous row by `1 + q + ⋯ + q^x`), and + `coeff_mahonianPoly` proves `(mahonianPoly x).coeff n = mahonian x n` for all `x, n`. By + MacMahon's theorem this is the number of permutations of `x` letters with major index `n`; + `mahonian_eq_majCount` checks this in the kernel against a literal count (`majCount`: the + arrangements `List.permutations' [0, …, x-1]`, with major index `maj` = sum of the 1-based + positions `i` with `w_i > w_{i+1}`) for all `x ≤ 6` and `n ≤ 15`. +* *The polynomial of column `n`.* For `x ≥ n` the number `mahonian x n` is a polynomial in `x` + of degree `n`: modulo `q^(n+1)`, `∏_{i=1}^{x} (1 - q^i)` does not depend on `x` once `x ≥ n`, + so `mahonian x n = [q^n] ∏_{i=1}^{x} (1 - q^i) / (1 - q)^x = ∑_{j ≤ n} e_j · C(x+n-j-1, n-j)` + with `x`-independent `e_j` (this is Mike Earnest's MSE answer linked from the entry). So "the + polynomial that describes" column `n` is the unique polynomial `P_n` of degree `≤ n` through + the `n + 1` points `(x, mahonian x n)`, `x = n, …, 2n`. (The entry's Mathematica program + interpolates the same column on `x = n, …, 2n+2`.) `Trow n` is the coefficient list of + `n! · P_n`, computed in `ℤ` by Newton's forward-difference formula + `n! · P_n(x) = ∑_{j=0}^{n} Δ^j · (n!/j!) · (x - n)(x - n - 1)⋯(x - n - j + 1)`, + where `Δ^j` is the `j`-th forward difference of `x ↦ mahonian x n` at `x = n` + (`column`, `diffHeads`, `fallingFrom`, `newton`). `T n k` is the coefficient of `x^k`. + `rowPoly_agrees` checks in the kernel, for every `n ≤ 9`, that + `∑_k T(n,k) x^k = n! · mahonian x n` for all `x = n, …, 3n+2`, i.e. also beyond the + interpolation nodes. +* *Data.* `T_data` checks all 55 listed terms (rows `n = 0, …, 9`) row by row, and `a_data` + checks them again for `a`, the triangle read by rows (the OEIS sequence itself, offset `0`). +* *A290030* is "Leading coefficients of numerators of Norlund's B_{nu}^(n) polynomials", with + Mathematica program `NorlundB[n, x] // Together // Numerator // Coefficient[#, x, n]`. The + Nørlund polynomial is `B_n^(x) = n! [t^n] (t/(e^t - 1))^x`. We compute + `G = t/(e^t - 1)` as the reciprocal of `(e^t - 1)/t = ∑_k t^k/(k+1)!` (`bernG`), and then use the + binomial series: with `H = G - 1` (no constant term), `[t^n] G^x = ∑_{j=0}^{n} C(x, j) [t^n] H^j` + as polynomials in `x` (both sides are polynomials in `x` that agree at every natural number + `x`, by the binomial theorem). So `norlund n`, the coefficient list of `B_n^(x)` in `x`, is + `∑_{j=0}^{n} (n!/j!) · [t^n] H^j · x(x-1)⋯(x-j+1)`; `norlund_check` compares it in the kernel + with `n! [t^n] G^x` computed by repeated multiplication, for `n ≤ 6`, `x ≤ 8`. Writing a + polynomial with rational coefficients over the least common multiple `L` of their + denominators (as `Together` does; `L · B_n^(x)` then has integer coefficients with no factor + in common with `L`, so nothing cancels), its numerator is `L · B_n^(x)`, and A290030(n) is the + coefficient of `x^n` there: `A290030 n = L · [x^n] B_n^(x)` (an integer, since the denominator + of `[x^n] B_n^(x)` divides `L`). `A290030_data` checks the first 26 listed terms. +* *A053657* is defined by its name, `a(n) = Product_{p prime} p^{Sum_{k>=0} + floor((n-1)/((p-1)p^k))}` (offset `1`); only primes `p ≤ n` and exponents `k < n` can + contribute, since otherwise `(p-1)p^k > n - 1`. `A053657_data` checks all 19 listed terms. +* *The conjecture.* `statementDiagonals`: for every `m ≥ 0` there is `Q ∈ ℚ[X]` of degree exactly + `2m` with leading coefficient `|A290030(m)/A053657(m+1)|` (computed in `ℚ`) such that + `T(n, n-m) = Q(n)` for every `n ≥ m`, i.e. for every row in which `T(n, n-m)` is an entry of + the triangle. (The weaker reading "for all sufficiently large `n`" is implied.) + `statementFormulas`: the four FORMULA identities, each for all `n` with `T(n, n-m)` an entry + (`n ≥ m` for `m = 0, 1, 2, 3`), with exact rational division. `statement` is the conjunction. + `formulas_check` and `leading_check` are sanity checks of the transcription, not proofs: the + four formulas hold for `n ≤ 12`, and `|A290030(m)/A053657(m+1)| = 1/(2^m m!)` for `m ≤ 9`, + which matches the leading coefficients `1, 1/2, 3/24, 1/48` of the four formulas. +-/ + +namespace Math0.Statements.A342645 + +open Polynomial + +/-! ### Mahonian numbers (A008302) -/ + +/-- The generating polynomial `∏_{i=0}^{x-1} (1 + q + ⋯ + q^i)` of row `x` of A008302. -/ +noncomputable def mahonianPoly (x : ℕ) : ℕ[X] := + ∏ i ∈ Finset.range x, ∑ j ∈ Finset.range (i + 1), (X : ℕ[X]) ^ j + +/-- Coefficientwise sum of two coefficient lists (lowest degree first). -/ +def addN : List ℕ → List ℕ → List ℕ + | [], q => q + | a :: p, [] => a :: p + | a :: p, b :: q => (a + b) :: addN p q + +/-- Multiply a coefficient list by `1 + q + ⋯ + q^(m-1)`. -/ +def mulOnes (m : ℕ) (r : List ℕ) : List ℕ := + r.foldr (fun a acc => addN (List.replicate m a) (0 :: acc)) [] + +/-- The coefficient list of `mahonianPoly x`. -/ +def mahonianRow : ℕ → List ℕ + | 0 => [1] + | x + 1 => mulOnes (x + 1) (mahonianRow x) + +/-- The Mahonian number A008302`(x, n)`: the number of permutations of `x` letters with major +index (equivalently, with inversion number) `n`. -/ +def mahonian (x n : ℕ) : ℕ := (mahonianRow x).getD n 0 + +/-- The polynomial with coefficient list `l` (lowest degree first). -/ +noncomputable def toPoly : List ℕ → ℕ[X] + | [] => 0 + | a :: l => C a + X * toPoly l + +theorem coeff_toPoly (l : List ℕ) (k : ℕ) : (toPoly l).coeff k = l.getD k 0 := by + induction l generalizing k with + | nil => simp [toPoly] + | cons a l ih => + cases k with + | zero => simp [toPoly] + | succ k => simp [toPoly, coeff_X_mul, ih] + +theorem toPoly_addN (p q : List ℕ) : toPoly (addN p q) = toPoly p + toPoly q := by + induction p generalizing q with + | nil => simp [addN, toPoly] + | cons a p ih => + cases q with + | nil => simp [addN, toPoly] + | cons b q => simp only [addN, toPoly, ih, map_add]; ring + +theorem toPoly_replicate (m a : ℕ) : + toPoly (List.replicate m a) = C a * ∑ j ∈ Finset.range m, (X : ℕ[X]) ^ j := by + induction m with + | zero => simp [toPoly] + | succ m ih => + have hs : ∑ j ∈ Finset.range (m + 1), (X : ℕ[X]) ^ j = + 1 + X * ∑ j ∈ Finset.range m, (X : ℕ[X]) ^ j := by + rw [Finset.sum_range_succ', Finset.mul_sum, add_comm] + simp [pow_succ'] + rw [List.replicate_succ, toPoly, ih, hs] + ring + +theorem toPoly_mulOnes (m : ℕ) (r : List ℕ) : + toPoly (mulOnes m r) = toPoly r * ∑ j ∈ Finset.range m, (X : ℕ[X]) ^ j := by + induction r with + | nil => simp [mulOnes, toPoly] + | cons a r ih => + have h : mulOnes m (a :: r) = addN (List.replicate m a) (0 :: mulOnes m r) := rfl + rw [h, toPoly_addN, toPoly_replicate, toPoly, toPoly, ih, map_zero] + ring + +theorem mahonianPoly_eq (x : ℕ) : mahonianPoly x = toPoly (mahonianRow x) := by + induction x with + | zero => simp [mahonianPoly, mahonianRow, toPoly] + | succ x ih => + rw [mahonianPoly, Finset.prod_range_succ, ← mahonianPoly, ih, mahonianRow, toPoly_mulOnes] + +/-- `mahonian x n` is the coefficient of `q^n` in `∏_{i=0}^{x-1} (1 + q + ⋯ + q^i)`. -/ +theorem coeff_mahonianPoly (x n : ℕ) : (mahonianPoly x).coeff n = mahonian x n := by + rw [mahonianPoly_eq, coeff_toPoly, mahonian] + +/-- The major index of a word `w`: the sum of the (1-based) positions `i` with `w_i > w_{i+1}`. -/ +def maj (w : List ℕ) : ℕ := + ((List.range (w.length - 1)).map fun i => + if w.getD (i + 1) 0 < w.getD i 0 then i + 1 else 0).sum + +/-- The number of permutations of the `x` letters `0, …, x-1` with major index `n` (literal +count). -/ +def majCount (x n : ℕ) : ℕ := ((List.range x).permutations'.filter fun w => maj w = n).length + +/-- Sanity check (MacMahon): `mahonian x n` counts the permutations of `x` letters with major +index `n`, for `x ≤ 6` (all `n ≤ 15 = 6·5/2`). -/ +theorem mahonian_eq_majCount : ∀ x < 7, ∀ n < 16, majCount x n = mahonian x n := by + decide +kernel + +/-! ### The triangle -/ + +/-- Forward differences: `diffHeads k v = [Δ^0 v (0), Δ^1 v (0), …, Δ^(k-1) v (0)]`, where +`(Δ v)(i) = v(i+1) - v(i)`. -/ +def diffHeads : ℕ → List ℤ → List ℤ + | 0, _ => [] + | k + 1, v => v.headD 0 :: diffHeads k (List.zipWith (· - ·) v.tail v) + +/-- Coefficientwise sum of two integer coefficient lists (lowest degree first). -/ +def addZ : List ℤ → List ℤ → List ℤ + | [], q => q + | a :: p, [] => a :: p + | a :: p, b :: q => (a + b) :: addZ p q + +/-- Multiply a coefficient list by `x - c`. -/ +def mulXsub (c : ℤ) (p : List ℤ) : List ℤ := addZ (0 :: p) (p.map fun a => -c * a) + +/-- The coefficient list of `(x - c)(x - c - 1)⋯(x - c - j + 1)`. -/ +def fallingFrom (c : ℕ) : ℕ → List ℤ + | 0 => [1] + | j + 1 => mulXsub ((c + j : ℕ) : ℤ) (fallingFrom c j) + +/-- Column `n` of A008302 at the interpolation nodes: `[mahonian n n, …, mahonian (2n) n]`. -/ +def column (n : ℕ) : List ℤ := (List.range (n + 1)).map fun i => (mahonian (n + i) n : ℤ) + +/-- Newton's forward-difference sum `∑_{i} d_i · (n!/(j+i)!) · fallingFrom n (j+i)`, for the +list of differences `[d_0, d_1, …]` starting at index `j`. -/ +def newton (n : ℕ) : ℕ → List ℤ → List ℤ + | _, [] => [] + | j, d :: ds => + addZ ((fallingFrom n j).map fun a => d * ((n.factorial / j.factorial : ℕ) : ℤ) * a) + (newton n (j + 1) ds) + +/-- Row `n` of the triangle: the coefficient list of `n! · P_n(x)`, where `P_n` is the polynomial +of degree `≤ n` through `(x, mahonian x n)`, `x = n, …, 2n` (Newton's formula). -/ +def Trow (n : ℕ) : List ℤ := newton n 0 (diffHeads (n + 1) (column n)) + +/-- A342645: `T(n, k)` is `n!` times the coefficient of `x^k` in the polynomial that describes +the number of permutations on `x` letters with major index `n` (for `x ≥ n`). -/ +def T (n k : ℕ) : ℤ := (Trow n).getD k 0 + +/-- Evaluate an integer coefficient list (lowest degree first) at `x`. -/ +def evalZ (l : List ℤ) (x : ℤ) : ℤ := l.foldr (fun a acc => a + x * acc) 0 + +/-- Sanity check: for `n ≤ 9`, `∑_k T(n,k) x^k = n! · mahonian x n` for all `x = n, …, 3n+2`, +and row `n` has exactly `n + 1` entries. -/ +theorem rowPoly_agrees : ∀ n < 10, (Trow n).length = n + 1 ∧ ∀ i < 2 * n + 3, + evalZ (Trow n) ((n + i : ℕ) : ℤ) = (n.factorial : ℤ) * (mahonian (n + i) n : ℤ) := by + decide +kernel + +/-- The definition reproduces all 55 terms listed in OEIS, rows `n = 0, …, 9` (kernel-checked). -/ +theorem T_data : (List.range 10).map (fun n => (List.range (n + 1)).map (T n)) = + [[1], + [-1, 1], + [-2, -1, 1], + [0, -7, 0, 1], + [0, -14, -13, 2, 1], + [120, -46, -65, -15, 5, 1], + [0, 516, -356, -165, -5, 9, 1], + [5040, 1392, 266, -1421, -280, 28, 14, 1], + [0, 46320, 3772, -5740, -3871, -280, 98, 20, 1], + [0, 215280, 212724, -26272, -31437, -7791, 126, 222, 27, 1]] := by + decide +kernel + +/-- A342645 as a sequence (offset `0`): the triangle `T` read by rows. Entry `i` lies in the row +`n` with `n(n+1)/2 ≤ i < (n+1)(n+2)/2`, at column `i - n(n+1)/2`. -/ +def a (i : ℕ) : ℤ := + let n := Nat.findGreatest (fun n => n * (n + 1) / 2 ≤ i) i + T n (i - n * (n + 1) / 2) + +/-- The definition reproduces all 55 terms listed in OEIS, `a 0, …, a 54` (kernel-checked). -/ +theorem a_data : (List.range 55).map (fun i => a (i + 0)) = + [1, -1, 1, -2, -1, 1, 0, -7, 0, 1, 0, -14, -13, 2, 1, 120, -46, -65, -15, 5, 1, 0, 516, -356, + -165, -5, 9, 1, 5040, 1392, 266, -1421, -280, 28, 14, 1, 0, 46320, 3772, -5740, -3871, -280, + 98, 20, 1, 0, 215280, 212724, -26272, -31437, -7791, 126, 222, 27, 1] := by + decide +kernel + +/-! ### A290030 and A053657 -/ + +/-- `revG k = [G_k, G_{k-1}, …, G_0]`, where `t/(e^t - 1) = ∑ G_k t^k`, computed as the +reciprocal of `(e^t - 1)/t = ∑_k t^k/(k+1)!`: `G_0 = 1` and +`G_{k+1} = -∑_{i=0}^{k} G_{k-i}/(i+2)!`. -/ +def revG : ℕ → List ℚ + | 0 => [1] + | k + 1 => (-(List.zipWith (fun g i => g / ((i + 2).factorial : ℚ)) (revG k) + (List.range (k + 1))).sum) :: revG k + +/-- The coefficients `[G_0, …, G_n]` of `t/(e^t - 1)`. -/ +def bernG (n : ℕ) : List ℚ := (revG n).reverse + +/-- Coefficientwise sum of two rational coefficient lists (lowest degree first). -/ +def addQ : List ℚ → List ℚ → List ℚ + | [], q => q + | a :: p, [] => a :: p + | a :: p, b :: q => (a + b) :: addQ p q + +/-- Product of two rational coefficient lists. -/ +def mulQ (p q : List ℚ) : List ℚ := p.foldr (fun a acc => addQ (q.map (a * ·)) (0 :: acc)) [] + +/-- `H = t/(e^t - 1) - 1`, truncated after `t^n`. -/ +def Hser (n : ℕ) : List ℚ := 0 :: (bernG n).tail + +/-- `powsH n H k P = [[t^n] P, [t^n] P·H, …, [t^n] P·H^(k-1)]` (power series truncated after +`t^n`). -/ +def powsH (n : ℕ) (H : List ℚ) : ℕ → List ℚ → List ℚ + | 0, _ => [] + | k + 1, P => P.getD n 0 :: powsH n H k ((mulQ P H).take (n + 1)) + +/-- The coefficient list of `x(x-1)⋯(x-j+1)`. -/ +def descQ : ℕ → List ℚ + | 0 => [1] + | j + 1 => addQ (0 :: descQ j) ((descQ j).map fun a => -(j : ℚ) * a) + +/-- `∑_{i} (n!/(j+i)!) · c_i · x(x-1)⋯(x-(j+i)+1)` for the list `[c_0, c_1, …]` starting at +index `j`. -/ +def norlundAux (n : ℕ) : ℕ → List ℚ → List ℚ + | _, [] => [] + | j, c :: cs => addQ ((descQ j).map fun a => (n.factorial : ℚ) * c / (j.factorial : ℚ) * a) + (norlundAux n (j + 1) cs) + +/-- The coefficient list (in `x`, lowest degree first) of Nørlund's polynomial +`B_n^(x) = n! [t^n] (t/(e^t - 1))^x = n! ∑_{j=0}^{n} C(x, j) [t^n] H^j`. -/ +def norlund (n : ℕ) : List ℚ := norlundAux n 0 (powsH n (Hser n) (n + 1) [1]) + +/-- Evaluate a rational coefficient list (lowest degree first) at `x`. -/ +def evalQ (l : List ℚ) (x : ℚ) : ℚ := l.foldr (fun a acc => a + x * acc) 0 + +/-- `(t/(e^t - 1))^x`, truncated after `t^n`, by repeated multiplication. -/ +def powG (n : ℕ) : ℕ → List ℚ + | 0 => [1] + | x + 1 => (mulQ (powG n x) (bernG n)).take (n + 1) + +/-- Sanity check of the binomial-series step: `B_n^(x) = n! [t^n] (t/(e^t - 1))^x` for `n ≤ 6` +and `x ≤ 8`. -/ +theorem norlund_check : ∀ n < 7, ∀ x : ℕ, x < 9 → + evalQ (norlund n) (x : ℚ) = (n.factorial : ℚ) * (powG n x).getD n 0 := by + decide +kernel + +/-- The least common multiple of the denominators of a list of rationals. -/ +def lcmDen (l : List ℚ) : ℕ := (l.map (·.den)).foldr Nat.lcm 1 + +/-- A290030: the leading coefficient (coefficient of `x^n`) of the numerator `L · B_n^(x)` of +Nørlund's polynomial `B_n^(x)`, where `L` is the least common denominator of its coefficients. +-/ +def A290030 (n : ℕ) : ℤ := ((lcmDen (norlund n) : ℚ) * (norlund n).getD n 0).num + +/-- The definition reproduces the first 26 terms listed in OEIS, `a(0), …, a(25)` +(kernel-checked). -/ +theorem A290030_data : (List.range 26).map A290030 = + [1, -1, 3, -1, 15, -3, 63, -9, 135, -15, 99, -9, 12285, -945, 405, -27, 6885, -405, 161595, + -8505, 1403325, -66825, 419175, -18225, 24877125, -995085] := by + decide +kernel + +/-- A053657 (offset `1`): `a(n) = ∏_{p prime} p^(∑_{k ≥ 0} ⌊(n-1)/((p-1) p^k)⌋)`; only primes +`p ≤ n` and `k < n` contribute. -/ +def A053657 (n : ℕ) : ℕ := + ∏ p ∈ (Finset.range (n + 1)).filter Nat.Prime, + p ^ (∑ k ∈ Finset.range n, (n - 1) / ((p - 1) * p ^ k)) + +/-- The definition reproduces all 19 terms listed in OEIS, `a(1), …, a(19)` (kernel-checked). -/ +theorem A053657_data : (List.range 19).map (fun i => A053657 (i + 1)) = + [1, 2, 24, 48, 5760, 11520, 2903040, 5806080, 1393459200, 2786918400, 367873228800, + 735746457600, 24103053950976000, 48206107901952000, 578473294823424000, + 1156946589646848000, 9440684171518279680000, 18881368343036559360000, + 271211974879377138647040000] := by + decide +kernel + +/-! ### The conjecture -/ + +/-- Kagey's conjecture (COMMENTS): for each `m ≥ 0`, `n ↦ T(n, n-m)` (`n ≥ m`) is a polynomial +in `n` of degree `2m` whose leading coefficient is `|A290030(m)/A053657(m+1)|`. -/ +def statementDiagonals : Prop := + ∀ m : ℕ, ∃ Q : ℚ[X], Q.degree = ((2 * m : ℕ) : WithBot ℕ) ∧ + Q.leadingCoeff = |(A290030 m : ℚ) / (A053657 (m + 1) : ℚ)| ∧ + ∀ n : ℕ, m ≤ n → (T n (n - m) : ℚ) = Q.eval (n : ℚ) + +/-- Kagey's conjectured formulas (FORMULA): `T(n,n) = 1`, `T(n,n-1) = (-3n + n^2)/2`, +`T(n,n-2) = (-2n + 21n^2 - 22n^3 + 3n^4)/24` and +`T(n,n-3) = (96n - 134n^2 + 13n^3 + 37n^4 - 13n^5 + n^6)/48`, each for every `n` such that the +left side is an entry of the triangle. -/ +def statementFormulas : Prop := + (∀ n : ℕ, T n n = 1) ∧ + (∀ n : ℕ, 1 ≤ n → (T n (n - 1) : ℚ) = (-3 * (n : ℚ) + (n : ℚ) ^ 2) / 2) ∧ + (∀ n : ℕ, 2 ≤ n → (T n (n - 2) : ℚ) = + (-2 * (n : ℚ) + 21 * (n : ℚ) ^ 2 - 22 * (n : ℚ) ^ 3 + 3 * (n : ℚ) ^ 4) / 24) ∧ + (∀ n : ℕ, 3 ≤ n → (T n (n - 3) : ℚ) = + (96 * (n : ℚ) - 134 * (n : ℚ) ^ 2 + 13 * (n : ℚ) ^ 3 + 37 * (n : ℚ) ^ 4 + - 13 * (n : ℚ) ^ 5 + (n : ℚ) ^ 6) / 48) + +/-- The conjectures of A342645 (COMMENTS and FORMULA sections). -/ +def statement : Prop := statementDiagonals ∧ statementFormulas + +/-- Sanity check of the transcription (not a proof): the four formulas hold for `n ≤ 12`. -/ +theorem formulas_check : ∀ n < 13, + T n n = 1 ∧ + (1 ≤ n → (T n (n - 1) : ℚ) = (-3 * (n : ℚ) + (n : ℚ) ^ 2) / 2) ∧ + (2 ≤ n → (T n (n - 2) : ℚ) = + (-2 * (n : ℚ) + 21 * (n : ℚ) ^ 2 - 22 * (n : ℚ) ^ 3 + 3 * (n : ℚ) ^ 4) / 24) ∧ + (3 ≤ n → (T n (n - 3) : ℚ) = + (96 * (n : ℚ) - 134 * (n : ℚ) ^ 2 + 13 * (n : ℚ) ^ 3 + 37 * (n : ℚ) ^ 4 + - 13 * (n : ℚ) ^ 5 + (n : ℚ) ^ 6) / 48) := by + decide +kernel + +/-- Sanity check (not part of the conjecture): `|A290030(m)/A053657(m+1)| = 1/(2^m m!)` for +`m ≤ 9`. -/ +theorem leading_check : ∀ m < 10, + |(A290030 m : ℚ) / (A053657 (m + 1) : ℚ)| = 1 / (2 ^ m * (m.factorial : ℚ)) := by + decide +kernel + +end Math0.Statements.A342645 diff --git a/lean/Math0/Statements/OEIS/A342992.lean b/lean/Math0/Statements/OEIS/A342992.lean new file mode 100644 index 0000000..be5e476 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A342992.lean @@ -0,0 +1,139 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A342992: smallest multiple of `n` with only prime digits + +Source: https://oeis.org/A342992, _Metin Sariyar_, Apr 13 2021 (COMMENTS section). Verbatim: +> Conjecture: a(n) > 0 for all n that are not divisible by 5. + +The entry's name: "Smallest k such that k*n contains only prime digits, or 0 if no such k +exists." Offset `1`. Data: `2, 1, 1, 8, 1, 12, 1, 4, 3, 0, 2, 6, …` (81 terms, `n = 1, …, 81`). + +## Encoding + +* *Prime digits.* `PrimeDigits m`: `m > 0` and every decimal digit of `m` (`Nat.digits 10 m`) + is a prime, i.e. lies in `{2, 3, 5, 7}`. The condition `m > 0` is needed because + `Nat.digits 10 0 = []` would make `0` satisfy the digit condition vacuously, while `0` + (written "0") has the non-prime digit `0`. In particular `k = 0` never qualifies, so the + "smallest k" is automatically a positive integer, as in the entry (whose PARI program starts + the search at `k = 1`). +* *The sequence.* `a n` is the least `k` with `PrimeDigits (k * n)` (`Nat.find`) if such `k` + exists, and `0` otherwise. Existence is not decidable from the definition as written (it is + an unbounded search), so `a` is noncomputable. `a_pos_iff` records that `0 < a n` holds + exactly when some `k` with `PrimeDigits (k * n)` exists. +* *Data check.* The computable `aSearch n B` returns `some 0` when `n > 0` and `10 ∣ n` (then + every positive multiple of `n` ends in the digit `0`, so no `k` exists), and otherwise the + least `k < B` with `PrimeDigits (k * n)` (tested by the Boolean `primeDigitsB`), if any. + `a_eq_of_aSearch` proves that `aSearch n B = some v` implies `a n = v`. `a_data` checks all 81 + listed terms (`n = 1, …, 81`) this way with `B = 100` (the largest listed term is `93`). +* *The conjecture.* `statement`: for every `n ≥ 1` (the entry's offset) with `5 ∤ n`, + `a n > 0`. (The hypothesis `n ≥ 1` is the entry's range; it is redundant since `5 ∣ 0`.) +-/ + +namespace Math0.Statements.A342992 + +/-! ### Definitions -/ + +/-- `m` is positive and all its decimal digits are prime. -/ +def PrimeDigits (m : ℕ) : Prop := 0 < m ∧ ∀ d ∈ Nat.digits 10 m, d.Prime + +instance : DecidablePred PrimeDigits := fun m => by unfold PrimeDigits; infer_instance + +open Classical in +/-- A342992: the smallest `k` such that `k * n` contains only prime digits, or `0` if no such +`k` exists (offset `1`). -/ +noncomputable def a (n : ℕ) : ℕ := + if h : ∃ k, PrimeDigits (k * n) then Nat.find h else 0 + +/-- `a n > 0` exactly when some multiple `k * n` has only prime digits. -/ +theorem a_pos_iff (n : ℕ) : 0 < a n ↔ ∃ k, PrimeDigits (k * n) := by + constructor + · intro h + by_contra hne + rw [a, dif_neg hne] at h + exact lt_irrefl 0 h + · intro h + rw [a, dif_pos h] + by_contra h0 + have h0' : Nat.find h = 0 := by omega + have := Nat.find_spec h + rw [h0', zero_mul] at this + exact lt_irrefl 0 this.1 + +/-! ### Computable certificates -/ + +/-- Boolean version of `PrimeDigits` (see `primeDigitsB_iff`). -/ +def primeDigitsB (m : ℕ) : Bool := + decide (0 < m) && (Nat.digits 10 m).all fun d => d == 2 || d == 3 || d == 5 || d == 7 + +theorem prime_iff_of_lt_ten {d : ℕ} (hd : d < 10) : + d.Prime ↔ (d == 2 || d == 3 || d == 5 || d == 7) = true := by + interval_cases d <;> norm_num + +theorem primeDigitsB_iff (m : ℕ) : primeDigitsB m = true ↔ PrimeDigits m := by + simp only [primeDigitsB, Bool.and_eq_true, decide_eq_true_eq, List.all_eq_true, PrimeDigits] + refine and_congr Iff.rfl (forall₂_congr fun d hd => ?_) + exact (prime_iff_of_lt_ten (Nat.digits_lt_base (by norm_num) hd)).symm + +/-- If `n > 0` and `10 ∣ n`, then no multiple of `n` has only prime digits. -/ +theorem not_exists_of_ten_dvd {n : ℕ} (h10 : 10 ∣ n) : ¬ ∃ k, PrimeDigits (k * n) := by + rintro ⟨k, hpos, hd⟩ + have hmem : (k * n) % 10 ∈ Nat.digits 10 (k * n) := by + rw [Nat.digits_def' (by norm_num) hpos] + exact List.mem_cons_self + have h0 : (k * n) % 10 = 0 := Nat.mod_eq_zero_of_dvd (Dvd.dvd.mul_left h10 k) + have := hd _ hmem + rw [h0] at this + exact Nat.not_prime_zero this + +/-- `some 0` if `n > 0` and `10 ∣ n`; otherwise the least `k < B` such that `k * n` has only +prime digits, if there is one. -/ +def aSearch (n B : ℕ) : Option ℕ := + if 0 < n ∧ n % 10 = 0 then some 0 else (List.range B).find? fun k => primeDigitsB (k * n) + +theorem a_eq_of_aSearch {n B v : ℕ} (h : aSearch n B = some v) : a n = v := by + unfold aSearch at h + split_ifs at h with h10 + · rw [Option.some.injEq] at h + subst h + rw [a, dif_neg (not_exists_of_ten_dvd (Nat.dvd_of_mod_eq_zero h10.2))] + · rw [List.find?_range_eq_some] at h + obtain ⟨hv, -, hlt⟩ := h + have hv' : PrimeDigits (v * n) := (primeDigitsB_iff _).1 hv + have hex : ∃ k, PrimeDigits (k * n) := ⟨v, hv'⟩ + rw [a, dif_pos hex, Nat.find_eq_iff] + refine ⟨hv', fun j hj hjP => ?_⟩ + have := hlt j hj + rw [(primeDigitsB_iff _).2 hjP] at this + exact absurd this (by decide) + +theorem map_a_eq_of_aSearch {B : ℕ} : + ∀ {l D : List ℕ}, l.map (fun i => aSearch i B) = D.map some → l.map a = D + | [], [], _ => rfl + | [], _ :: _, h => by simp at h + | _ :: _, [], h => by simp at h + | i :: l, d :: D, h => by + simp only [List.map_cons, List.cons.injEq] at h ⊢ + exact ⟨a_eq_of_aSearch h.1, map_a_eq_of_aSearch h.2⟩ + +/-- The entry's example: `a(4) = 8`, since `8 * 4 = 32`. -/ +theorem a_four : a 4 = 8 := a_eq_of_aSearch (B := 9) (by decide +kernel) + +/-- The definition reproduces all 81 terms listed in OEIS (`n = 1, …, 81`, kernel-checked). -/ +theorem a_data : (List.range 81).map (fun i => a (i + 1)) = + [2, 1, 1, 8, 1, 12, 1, 4, 3, 0, 2, 6, 4, 18, 5, 2, 15, 4, 3, 0, 12, 1, 1, 3, 1, 2, 1, 9, 8, + 0, 12, 1, 1, 8, 1, 2, 1, 14, 7, 0, 13, 6, 54, 8, 5, 7, 5, 49, 15, 0, 5, 1, 1, 43, 1, 42, 1, + 4, 43, 0, 12, 6, 4, 43, 5, 42, 5, 4, 8, 0, 5, 1, 1, 3, 1, 7, 1, 74, 3, 0, 93] := by + rw [show (fun i => a (i + 1)) = a ∘ (fun i => i + 1) from rfl, ← List.map_map] + exact map_a_eq_of_aSearch (B := 100) (by decide +kernel) + +/-! ### The conjecture -/ + +/-- Conjecture (Sariyar, A342992): `a(n) > 0` for every `n ≥ 1` not divisible by `5`, i.e. every +such `n` has a positive multiple all of whose decimal digits are prime. -/ +def statement : Prop := ∀ n : ℕ, 1 ≤ n → ¬ 5 ∣ n → 0 < a n + +end Math0.Statements.A342992 diff --git a/lean/Math0/Statements/OEIS/A344710.lean b/lean/Math0/Statements/OEIS/A344710.lean new file mode 100644 index 0000000..a5c52fc --- /dev/null +++ b/lean/Math0/Statements/OEIS/A344710.lean @@ -0,0 +1,235 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A344710: smallest non-obtuse lattice triangles with no side shorter than √n + +Source: https://oeis.org/A344710, _Jonathan F. Waldmann_, May 26 2021. Verbatim (FORMULA +section): +> a(n) > sqrt(3/4)*n (conjectured). + +The entry's name: "a(n)/2 is the smallest possible area of a non-obtuse triangle with coordinates +in Z^2 and no side shorter than sqrt(n)." Offset `1`, so the sequence (and the conjecture) +concerns every `n ≥ 1`. + +## Encoding + +* A lattice triangle is a triple `A, B, C : ℤ × ℤ` of non-collinear points, i.e. + `det2 A B C = det(B - A, C - A) ≠ 0`. Its area is `|det2 A B C| / 2` (shoelace formula), so + `a n` is the least value of `|det2 A B C|` over the admissible triangles. +* "No side shorter than `√n`": the three squared side lengths `dist2` are all `≥ n`. +* "Non-obtuse": every angle is at most `90°`. The angle of the triangle at the vertex `V` (with + other vertices `P`, `Q`) is `≤ 90°` iff `(P - V) · (Q - V) ≥ 0` (`dotAt V P Q`). Theorem + `nonObtuse_iff` shows this is the criterion of the entry's first comment, + `2*max{|AB|,|BC|,|CA|} ≤ |AB|+|BC|+|CA|` (squared lengths). + For `n ≥ 1` this already forces `det2 A B C ≠ 0`, so non-collinearity is not an extra + restriction there. It is included because a triangle is non-degenerate. +* `areas n` is the set of the values `|det2 A B C|` over admissible triangles, and + `a n := sInf (areas n)`. The set is nonempty (`areas_nonempty`), so `a n` is its least element + (`isLeast_a`). That is, `a n` is exactly the sequence as defined in the entry. +* The statement is `√(3/4) * n < a n` (in `ℝ`) for every `n ≥ 1`. + +The entry's comment also lists "Conjectured next terms (from the conjectured inequality +a(n) > sqrt(3/4)*n) are a(50,...,64) ?= 45, 48, 48, 52, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, +56." Those values are guesses derived from the inequality, not a separate conjecture, and are not +formalized here. + +## Data check + +`a` is not computable as written: the admissible triangles range over all of `ℤ²`, and bounding +their size in terms of the area needs an inequality of the same kind as the conjecture +(`4 det² ≥ 3 |AB|² |AC|²` at the largest angle). That bound is not proved here. The checks +below are therefore of two kinds. + +* `a_data_le` (kernel-checked, about `a` itself): `a n ≤` the listed term for all 49 listed + terms `n = 1, …, 49`. It comes from the computable search `aRegion` via `a_le_aRegion`. +* `aRegion_data` (kernel-checked, about the helper): `aRegion n` equals the listed term for all + 49 listed terms. `aRegion n` is the least `|det2|` over admissible triangles with `A = (0, 0)`, + `C` in the annulus `n ≤ |P|² ≤ 5n/4 + 2` (`mem_annulus`) and `B` in its first octant + `0 ≤ y ≤ x`. So no admissible triangle in that region does better (`aRegion_le`). The region + follows the search described in the entry's comments ("set A to (0,0), and look for B and C in + the set of points X with sqrt(n) <= |AX| < sqrt(5n/4). Furthermore, B can be assumed to be in + the first octant"), widened by `2` so that it also covers the `n` that are not sums of two + squares. That this region always contains an optimal triangle is not proved here. +-/ + +namespace Math0.Statements.A344710 + +/-- Twice the signed area of the triangle `A B C`: `det(B - A, C - A)`. -/ +def det2 (A B C : ℤ × ℤ) : ℤ := (B.1 - A.1) * (C.2 - A.2) - (C.1 - A.1) * (B.2 - A.2) + +/-- The squared Euclidean distance between the lattice points `P` and `Q`. -/ +def dist2 (P Q : ℤ × ℤ) : ℤ := (P.1 - Q.1) * (P.1 - Q.1) + (P.2 - Q.2) * (P.2 - Q.2) + +/-- The dot product `(P - V) · (Q - V)`. The angle `∠PVQ` is at most `90°` iff it is `≥ 0`. -/ +def dotAt (V P Q : ℤ × ℤ) : ℤ := (P.1 - V.1) * (Q.1 - V.1) + (P.2 - V.2) * (Q.2 - V.2) + +/-- `A B C` is a non-obtuse lattice triangle with no side shorter than `√n`: the points are not +collinear, all three squared side lengths are `≥ n`, and all three angles are `≤ 90°`. -/ +def IsValid (n : ℕ) (A B C : ℤ × ℤ) : Prop := + det2 A B C ≠ 0 ∧ + (n : ℤ) ≤ dist2 A B ∧ (n : ℤ) ≤ dist2 B C ∧ (n : ℤ) ≤ dist2 C A ∧ + 0 ≤ dotAt A B C ∧ 0 ≤ dotAt B C A ∧ 0 ≤ dotAt C A B + +instance (n : ℕ) (A B C : ℤ × ℤ) : Decidable (IsValid n A B C) := + inferInstanceAs (Decidable (_ ∧ _ ∧ _ ∧ _ ∧ _ ∧ _ ∧ _)) + +/-- The non-obtuse condition is the entry's criterion +`2 * max {|AB|², |BC|², |CA|²} ≤ |AB|² + |BC|² + |CA|²`. -/ +theorem nonObtuse_iff (A B C : ℤ × ℤ) : + (0 ≤ dotAt A B C ∧ 0 ≤ dotAt B C A ∧ 0 ≤ dotAt C A B) ↔ + 2 * max (dist2 A B) (max (dist2 B C) (dist2 C A)) ≤ + dist2 A B + dist2 B C + dist2 C A := by + have hA : 2 * dotAt A B C = dist2 A B + dist2 C A - dist2 B C := by + simp only [dotAt, dist2]; ring + have hB : 2 * dotAt B C A = dist2 A B + dist2 B C - dist2 C A := by + simp only [dotAt, dist2]; ring + have hC : 2 * dotAt C A B = dist2 B C + dist2 C A - dist2 A B := by + simp only [dotAt, dist2]; ring + omega + +/-- The values `2 * area = |det2 A B C|` of the non-obtuse lattice triangles with no side shorter +than `√n`. -/ +def areas (n : ℕ) : Set ℕ := + {k | ∃ A B C : ℤ × ℤ, IsValid n A B C ∧ (det2 A B C).natAbs = k} + +/-- A344710: `a n / 2` is the smallest possible area of a non-obtuse triangle with coordinates in +`ℤ²` and no side shorter than `√n`. -/ +noncomputable def a (n : ℕ) : ℕ := sInf (areas n) + +/-- The right isosceles triangle with legs `n + 1` is admissible, so `areas n` is nonempty. -/ +theorem areas_nonempty (n : ℕ) : (areas n).Nonempty := by + have hd : det2 (0, 0) ((n : ℤ) + 1, 0) (0, (n : ℤ) + 1) = ((n : ℤ) + 1) ^ 2 := by + simp only [det2]; ring + refine ⟨((n : ℤ) + 1) ^ 2 |>.natAbs, (0, 0), ((n : ℤ) + 1, 0), (0, (n : ℤ) + 1), ?_, + by rw [hd]⟩ + have hn : (0 : ℤ) ≤ n := Int.natCast_nonneg n + have h1 : dist2 (0, 0) ((n : ℤ) + 1, 0) = ((n : ℤ) + 1) ^ 2 := by simp only [dist2]; ring + have h2 : dist2 ((n : ℤ) + 1, 0) (0, (n : ℤ) + 1) = 2 * ((n : ℤ) + 1) ^ 2 := by + simp only [dist2]; ring + have h3 : dist2 (0, (n : ℤ) + 1) (0, 0) = ((n : ℤ) + 1) ^ 2 := by simp only [dist2]; ring + have h4 : dotAt (0, 0) ((n : ℤ) + 1, 0) (0, (n : ℤ) + 1) = 0 := by simp only [dotAt]; ring + have h5 : dotAt ((n : ℤ) + 1, 0) (0, (n : ℤ) + 1) (0, 0) = ((n : ℤ) + 1) ^ 2 := by + simp only [dotAt]; ring + have h6 : dotAt (0, (n : ℤ) + 1) (0, 0) ((n : ℤ) + 1, 0) = ((n : ℤ) + 1) ^ 2 := by + simp only [dotAt]; ring + have hsq : (n : ℤ) ≤ ((n : ℤ) + 1) ^ 2 := by nlinarith + have hpos : 0 < ((n : ℤ) + 1) ^ 2 := by positivity + simp only [IsValid, hd, h1, h2, h3, h4, h5, h6] + omega + +/-- `a n` is the least element of `areas n`: the definition is a true minimum. -/ +theorem isLeast_a (n : ℕ) : IsLeast (areas n) (a n) := + ⟨Nat.sInf_mem (areas_nonempty n), fun _ hk => Nat.sInf_le hk⟩ + +/-! ### Computable search over a bounded region (helper for the data check) -/ + +/-- The bound on squared distances used by the helper search: `5n/4 + 2`. -/ +def bnd (n : ℕ) : ℕ := 5 * n / 4 + 2 + +/-- The lattice points `P` with `n ≤ |P|² ≤ bnd n` (see `mem_annulus`). Their coordinates lie in +`[-r, r]` with `r = n / 2 + 2`. -/ +def annulus (n : ℕ) : List (ℤ × ℤ) := + let r : ℕ := n / 2 + 2 + let coords : List ℤ := ((List.range (2 * r + 1)).map fun i : ℕ => (i : ℤ) - r).filter + fun x => decide (x * x ≤ (bnd n : ℤ)) + (coords.flatMap fun x => coords.map fun y => (x, y)).filter fun P => + decide ((n : ℤ) ≤ P.1 * P.1 + P.2 * P.2 ∧ P.1 * P.1 + P.2 * P.2 ≤ bnd n) + +theorem mem_annulus (n : ℕ) (P : ℤ × ℤ) : + P ∈ annulus n ↔ (n : ℤ) ≤ P.1 * P.1 + P.2 * P.2 ∧ P.1 * P.1 + P.2 * P.2 ≤ bnd n := by + obtain ⟨x, y⟩ := P + simp only [annulus, List.mem_filter, List.mem_flatMap, List.mem_map, Prod.mk.injEq, + decide_eq_true_eq] + constructor + · rintro ⟨-, h⟩ + exact h + · rintro ⟨h1, h2⟩ + refine ⟨?_, h1, h2⟩ + -- every coordinate `t` with `t² ≤ bnd n` satisfies `|t| ≤ n / 2 + 2`, so it is listed + have hm : (n : ℤ) ≤ 2 * ((n / 2 : ℕ) : ℤ) + 1 := by omega + have hb : 4 * (bnd n : ℤ) ≤ 5 * n + 8 := by simp only [bnd]; omega + have bound : ∀ t : ℤ, t * t ≤ (bnd n : ℤ) → + -((n / 2 + 2 : ℕ) : ℤ) ≤ t ∧ t ≤ ((n / 2 + 2 : ℕ) : ℤ) := by + intro t ht + push_cast + constructor <;> by_contra hc <;> push Not at hc + · have h3 : ((n / 2 : ℕ) : ℤ) + 3 ≤ -t := by omega + nlinarith + · have h3 : ((n / 2 : ℕ) : ℤ) + 3 ≤ t := by omega + nlinarith + have hx : x * x ≤ (bnd n : ℤ) := by nlinarith [mul_self_nonneg y] + have hy : y * y ≤ (bnd n : ℤ) := by nlinarith [mul_self_nonneg x] + have bx := bound x hx + have bY := bound y hy + set r : ℤ := ((n / 2 + 2 : ℕ) : ℤ) + refine ⟨x, ⟨⟨(x + r).toNat, List.mem_range.mpr (by omega), by omega⟩, hx⟩, + ⟨y, ⟨⟨(y + r).toNat, List.mem_range.mpr (by omega), by omega⟩, hy⟩, rfl, rfl⟩⟩ + +/-- The points of `annulus n` in the first octant `0 ≤ y ≤ x`. -/ +def octant (n : ℕ) : List (ℤ × ℤ) := + (annulus n).filter fun P => decide (0 ≤ P.2 ∧ P.2 ≤ P.1) + +/-- The values `|det2|` of the admissible triangles with `A = (0, 0)`, `B ∈ octant n` and +`C ∈ annulus n`. -/ +def regionDets (n : ℕ) : List ℕ := + (octant n).flatMap fun B => (annulus n).filterMap fun C => + if IsValid n (0, 0) B C then some (det2 (0, 0) B C).natAbs else none + +theorem mem_regionDets {n k : ℕ} : + k ∈ regionDets n ↔ ∃ B ∈ octant n, ∃ C ∈ annulus n, + IsValid n (0, 0) B C ∧ (det2 (0, 0) B C).natAbs = k := by + simp only [regionDets, List.mem_flatMap, List.mem_filterMap, Option.ite_none_right_eq_some, + Option.some.injEq] + +/-- The least `|det2|` over admissible triangles with `A = (0, 0)`, `B ∈ octant n` and +`C ∈ annulus n` (`0` if there is none). -/ +def aRegion (n : ℕ) : ℕ := (regionDets n).min?.getD 0 + +/-- If the bounded search finds a triangle, its value bounds `a n` from above. -/ +theorem a_le_aRegion {n : ℕ} (h : aRegion n ≠ 0) : a n ≤ aRegion n := by + cases hm : (regionDets n).min? with + | none => simp [aRegion, hm] at h + | some m => + have hmem := (List.min?_eq_some_iff.mp hm).1 + obtain ⟨B, -, C, -, hv, hk⟩ := mem_regionDets.mp hmem + rw [aRegion, hm, Option.getD_some] + exact Nat.sInf_le ⟨(0, 0), B, C, hv, hk⟩ + +/-- No admissible triangle in the search region beats `aRegion n`. -/ +theorem aRegion_le {n : ℕ} {B C : ℤ × ℤ} (hB : B ∈ octant n) (hC : C ∈ annulus n) + (hv : IsValid n (0, 0) B C) : aRegion n ≤ (det2 (0, 0) B C).natAbs := by + have hmem : (det2 (0, 0) B C).natAbs ∈ regionDets n := + mem_regionDets.mpr ⟨B, hB, C, hC, hv, rfl⟩ + cases hm : (regionDets n).min? with + | none => simp [List.min?_eq_none_iff] at hm; simp [hm] at hmem + | some m => + rw [aRegion, hm, Option.getD_some] + exact (List.min?_eq_some_iff.mp hm).2 _ hmem + +/-- The 49 terms listed in OEIS (`n = 1, …, 49`). -/ +def data : List ℕ := + [1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 12, 12, 12, 15, 15, 15, 15, 18, 20, 20, 23, 23, 23, 23, 23, + 24, 28, 28, 28, 30, 30, 30, 30, 30, 34, 34, 34, 38, 38, 38, 39, 42, 42, 42, 42, 45, 45, 45, + 45] + +/-- The bounded search reproduces all 49 terms listed in OEIS (kernel-checked). -/ +theorem aRegion_data : (List.range 49).map (fun i => aRegion (i + 1)) = data := by + decide +kernel + +/-- `a n` is at most the listed term, for all 49 terms listed in OEIS. -/ +theorem a_data_le : ∀ i < 49, a (i + 1) ≤ data.getD i 0 := by + intro i hi + have h := congrArg (fun l => l.getD i 0) aRegion_data + simp only [List.getD_eq_getElem?_getD, List.getElem?_map, List.getElem?_range hi, + Option.map_some, Option.getD_some] at h + rw [List.getD_eq_getElem?_getD, ← h] + exact a_le_aRegion (by rw [h]; interval_cases i <;> decide) + +/-- Conjecture (Waldmann, A344710): `a(n) > √(3/4) * n` for every `n ≥ 1`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → Real.sqrt (3 / 4) * (n : ℝ) < (a n : ℝ) + +end Math0.Statements.A344710 diff --git a/lean/Math0/Statements/OEIS/A348484.lean b/lean/Math0/Statements/OEIS/A348484.lean new file mode 100644 index 0000000..9061287 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A348484.lean @@ -0,0 +1,332 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A348484: squares of an `n × n` board, no two exactly two steps apart in a row or column + +Source: https://oeis.org/A348484, _Yang Hong_, Oct 20 2021. Verbatim (FORMULA section): +> Conjectures: +> a(n) = n^2/2 for n == 0 (mod 4). +> a(n) = (n^2 + 1)/2 for n == 1 or 3 (mod 4). +> a(n) = n^2/2 + 2 for n == 2 (mod 4). + +The entry's name: "Maximum number of squares on an n X n chessboard such that no two are two +steps apart horizontally or vertically." Offset `1`, so the sequence (and the conjecture) +concerns every `n ≥ 1`. + +## Encoding + +* A square of the `n × n` board is a pair `(i, j) : Fin n × Fin n` (row, column). +* Two squares are "two steps apart horizontally or vertically" (`TwoApart`) iff they lie in the + same row and their columns differ by exactly `2`, or they lie in the same column and their rows + differ by exactly `2`. The entry's examples confirm this reading: for `n = 2` all four squares + are taken (so diagonal neighbours, at taxicab distance `2`, are allowed), its `n = 4` + example `1100/1100/0011/0011` takes squares that are two steps apart diagonally, and its + `n = 5` example row `11001` takes squares three and four steps apart in a row. +* `Admissible S`: no two squares of `S` are two steps apart. +* `a n` is the largest `S.card` over admissible `S ⊆ Fin n × Fin n`, written as a `Finset.sup` + over all subsets of the board (`∅` is admissible, so this is a genuine maximum). +* In the statement, `/` is natural-number division. Each of the three formulas is exact in its + case (`n²` is even for even `n`, `n² + 1` is even for odd `n`), so they mean the same as the + entry's rational expressions. "n == 1 or 3 (mod 4)" is `n % 4 = 1 ∨ n % 4 = 3`. + +## Data check + +`a` is computable but enumerates all `2^(n²)` subsets of the board, which the kernel cannot do +beyond very small `n`. Each listed value `a n = v` (`n = 1, …, 10`, all 10 listed terms) is +therefore proved from a finite certificate by `a_eq_of_cert`, with every side condition checked +by `decide +kernel`: + +* a lower-bound witness: an admissible set of `v` squares (`ofRows n rowsN`, given by row + bitmasks: square `(i, j)` is taken iff bit `j` of the `i`-th mask is set, so column `0` is + the rightmost digit of each `0b` literal); +* an upper-bound certificate: a labelling of the `n²` squares by labels `< v` (`labOf n labelsN`, + a table indexed by row and column) in which any two distinct squares with the same label are + two steps apart. An admissible set takes at most one square per label, so it has at most `v` + squares. + +Both certificates were found by computer (a maximum matching of the "two steps apart" graph). +They only certify the ten listed terms. As an independent check of the certificate method, +`a_small` evaluates `a 1, a 2, a 3` by brute force straight from the definition. +-/ + +namespace Math0.Statements.A348484 + +/-- Two squares of the `n × n` board are two steps apart horizontally or vertically: they are in +the same row with columns differing by exactly `2`, or in the same column with rows differing by +exactly `2`. -/ +def TwoApart {n : ℕ} (c d : Fin n × Fin n) : Prop := + (c.1 = d.1 ∧ (c.2.val + 2 = d.2.val ∨ d.2.val + 2 = c.2.val)) ∨ + (c.2 = d.2 ∧ (c.1.val + 2 = d.1.val ∨ d.1.val + 2 = c.1.val)) + +instance {n : ℕ} (c d : Fin n × Fin n) : Decidable (TwoApart c d) := + inferInstanceAs (Decidable (_ ∨ _)) + +/-- A set of squares of the `n × n` board no two of which are two steps apart horizontally or +vertically. -/ +def Admissible {n : ℕ} (S : Finset (Fin n × Fin n)) : Prop := + ∀ c ∈ S, ∀ d ∈ S, ¬ TwoApart c d + +instance {n : ℕ} (S : Finset (Fin n × Fin n)) : Decidable (Admissible S) := + inferInstanceAs (Decidable (∀ c ∈ S, ∀ d ∈ S, ¬ TwoApart c d)) + +/-- A348484: the maximum number of squares on an `n × n` chessboard such that no two are two +steps apart horizontally or vertically (OEIS offset `1`; `a 0 = 0`). -/ +def a (n : ℕ) : ℕ := + ((Finset.univ : Finset (Finset (Fin n × Fin n))).filter Admissible).sup Finset.card + +/-- Certificate for a value of `a`: an admissible set of `v` squares, and a labelling of the +squares by labels `< v` in which squares with equal labels are equal or two steps apart. -/ +theorem a_eq_of_cert {n v : ℕ} (S : Finset (Fin n × Fin n)) (hS : Admissible S) + (hcard : S.card = v) (lab : Fin n × Fin n → ℕ) (hlt : ∀ c, lab c < v) + (hfib : ∀ c d, lab c = lab d → c = d ∨ TwoApart c d) : a n = v := by + apply le_antisymm + · apply Finset.sup_le + intro T hT + have hT' : Admissible T := (Finset.mem_filter.1 hT).2 + have hinj : Set.InjOn lab T := by + intro c hc d hd h + rcases hfib c d h with h | h + · exact h + · exact absurd h (hT' c hc d hd) + calc T.card = (T.image lab).card := (Finset.card_image_of_injOn hinj).symm + _ ≤ (Finset.range v).card := Finset.card_le_card fun x hx => by + obtain ⟨c, -, rfl⟩ := Finset.mem_image.1 hx + exact Finset.mem_range.2 (hlt c) + _ = v := Finset.card_range v + · rw [← hcard] + exact Finset.le_sup (Finset.mem_filter.2 ⟨Finset.mem_univ _, hS⟩) + +/-- The squares selected by row bitmasks: `(i, j)` is selected iff bit `j` of `rows[i]` is set. -/ +def ofRows (n : ℕ) (rows : List ℕ) : Finset (Fin n × Fin n) := + Finset.univ.filter fun c => (rows.getD c.1 0).testBit c.2 + +/-- The labelling given by a table: square `(i, j)` gets the label `tab[i][j]`. -/ +def labOf (n : ℕ) (tab : List (List ℕ)) (c : Fin n × Fin n) : ℕ := + (tab.getD c.1 []).getD c.2 0 + +/-! ### Certificates for the ten listed terms -/ + +/-- `a 1 = 1`: the witness `rows1` and the labelling `labels1`. -/ +def rows1 : List ℕ := [0b1] + +def labels1 : List (List ℕ) := + [[0]] + +theorem a_1 : a 1 = 1 := + a_eq_of_cert (ofRows 1 rows1) (by decide +kernel) (by decide +kernel) + (labOf 1 labels1) (by decide +kernel) (by decide +kernel) + +/-- `a 2 = 4`: the witness `rows2` and the labelling `labels2`. -/ +def rows2 : List ℕ := + [0b11, + 0b11] + +def labels2 : List (List ℕ) := + [[0, 1], + [2, 3]] + +theorem a_2 : a 2 = 4 := + a_eq_of_cert (ofRows 2 rows2) (by decide +kernel) (by decide +kernel) + (labOf 2 labels2) (by decide +kernel) (by decide +kernel) + +/-- `a 3 = 5`: the witness `rows3` and the labelling `labels3`. -/ +def rows3 : List ℕ := + [0b100, + 0b110, + 0b011] + +def labels3 : List (List ℕ) := + [[0, 1, 3], + [2, 4, 2], + [0, 1, 3]] + +theorem a_3 : a 3 = 5 := + a_eq_of_cert (ofRows 3 rows3) (by decide +kernel) (by decide +kernel) + (labOf 3 labels3) (by decide +kernel) (by decide +kernel) + +/-- `a 4 = 8`: the witness `rows4` and the labelling `labels4`. -/ +def rows4 : List ℕ := + [0b1100, + 0b1100, + 0b0011, + 0b0011] + +def labels4 : List (List ℕ) := + [[0, 1, 0, 1], + [2, 3, 2, 3], + [4, 5, 4, 5], + [6, 7, 6, 7]] + +theorem a_4 : a 4 = 8 := + a_eq_of_cert (ofRows 4 rows4) (by decide +kernel) (by decide +kernel) + (labOf 4 labels4) (by decide +kernel) (by decide +kernel) + +/-- `a 5 = 13`: the witness `rows5` and the labelling `labels5`. -/ +def rows5 : List ℕ := + [0b11001, + 0b01100, + 0b00110, + 0b10011, + 0b11001] + +def labels5 : List (List ℕ) := + [[12, 0, 1, 0, 1], + [2, 3, 4, 3, 4], + [9, 6, 5, 6, 11], + [2, 8, 7, 8, 7], + [9, 10, 5, 10, 11]] + +theorem a_5 : a 5 = 13 := + a_eq_of_cert (ofRows 5 rows5) (by decide +kernel) (by decide +kernel) + (labOf 5 labels5) (by decide +kernel) (by decide +kernel) + +/-- `a 6 = 20`: the witness `rows6` and the labelling `labels6`. -/ +def rows6 : List ℕ := + [0b110011, + 0b110011, + 0b001100, + 0b001100, + 0b110011, + 0b110011] + +def labels6 : List (List ℕ) := + [[16, 0, 1, 0, 1, 2], + [3, 17, 3, 4, 18, 4], + [9, 10, 5, 6, 5, 2], + [7, 13, 7, 8, 14, 15], + [9, 10, 11, 6, 11, 19], + [12, 13, 12, 8, 14, 15]] + +theorem a_6 : a 6 = 20 := + a_eq_of_cert (ofRows 6 rows6) (by decide +kernel) (by decide +kernel) + (labOf 6 labels6) (by decide +kernel) (by decide +kernel) + +/-- `a 7 = 25`: the witness `rows7` and the labelling `labels7`. -/ +def rows7 : List ℕ := + [0b1001100, + 0b1100110, + 0b0110011, + 0b0011001, + 0b1001100, + 0b1100110, + 0b0110011] + +def labels7 : List (List ℕ) := + [[0, 1, 2, 1, 2, 3, 9], + [4, 24, 4, 6, 5, 6, 5], + [0, 14, 7, 8, 7, 3, 9], + [10, 18, 10, 11, 19, 20, 12], + [13, 14, 13, 8, 15, 16, 23], + [17, 18, 17, 11, 19, 20, 12], + [21, 22, 21, 22, 15, 16, 23]] + +theorem a_7 : a 7 = 25 := + a_eq_of_cert (ofRows 7 rows7) (by decide +kernel) (by decide +kernel) + (labOf 7 labels7) (by decide +kernel) (by decide +kernel) + +/-- `a 8 = 32`: the witness `rows8` and the labelling `labels8`. -/ +def rows8 : List ℕ := + [0b11001100, + 0b11001100, + 0b00110011, + 0b00110011, + 0b11001100, + 0b11001100, + 0b00110011, + 0b00110011] + +def labels8 : List (List ℕ) := + [[0, 1, 8, 3, 2, 3, 2, 11], + [4, 5, 4, 13, 6, 7, 14, 15], + [0, 1, 8, 9, 18, 9, 10, 11], + [20, 5, 12, 13, 6, 7, 14, 15], + [16, 17, 24, 17, 18, 19, 10, 27], + [20, 21, 12, 29, 22, 23, 30, 31], + [16, 25, 24, 25, 26, 19, 26, 27], + [28, 21, 28, 29, 22, 23, 30, 31]] + +theorem a_8 : a 8 = 32 := + a_eq_of_cert (ofRows 8 rows8) (by decide +kernel) (by decide +kernel) + (labOf 8 labels8) (by decide +kernel) (by decide +kernel) + +/-- `a 9 = 41`: the witness `rows9` and the labelling `labels9`. -/ +def rows9 : List ℕ := + [0b110011001, + 0b011001100, + 0b001100110, + 0b100110011, + 0b110011001, + 0b011001100, + 0b001100110, + 0b100110011, + 0b110011001] + +def labels9 : List (List ℕ) := + [[0, 1, 0, 3, 2, 3, 4, 12, 4], + [5, 6, 5, 14, 7, 8, 15, 16, 9], + [17, 1, 10, 11, 2, 11, 40, 12, 21], + [22, 6, 13, 14, 7, 8, 15, 16, 9], + [17, 18, 10, 18, 19, 20, 19, 20, 21], + [22, 23, 13, 32, 24, 25, 33, 34, 26], + [35, 36, 27, 28, 37, 38, 29, 30, 39], + [31, 23, 31, 32, 24, 25, 33, 34, 26], + [35, 36, 27, 28, 37, 38, 29, 30, 39]] + +theorem a_9 : a 9 = 41 := + a_eq_of_cert (ofRows 9 rows9) (by decide +kernel) (by decide +kernel) + (labOf 9 labels9) (by decide +kernel) (by decide +kernel) + +/-- `a 10 = 52`: the witness `rows10` and the labelling `labels10`. -/ +def rows10 : List ℕ := + [0b1100110011, + 0b1100110011, + 0b0011001100, + 0b0011001100, + 0b1100110011, + 0b1100110011, + 0b0011001100, + 0b0011001100, + 0b1100110011, + 0b1100110011] + +def labels10 : List (List ℕ) := + [[0, 1, 0, 3, 2, 3, 4, 5, 4, 5], + [6, 48, 6, 13, 49, 7, 14, 15, 8, 9], + [16, 1, 10, 50, 2, 19, 51, 11, 20, 21], + [22, 23, 12, 13, 24, 7, 14, 15, 8, 9], + [16, 17, 10, 17, 18, 19, 18, 11, 20, 21], + [22, 23, 12, 25, 24, 25, 26, 35, 26, 27], + [36, 37, 28, 29, 38, 39, 30, 31, 40, 41], + [42, 43, 32, 33, 44, 45, 34, 35, 46, 27], + [36, 37, 28, 29, 38, 39, 30, 31, 40, 41], + [42, 43, 32, 33, 44, 45, 34, 47, 46, 47]] + +theorem a_10 : a 10 = 52 := + a_eq_of_cert (ofRows 10 rows10) (by decide +kernel) (by decide +kernel) + (labOf 10 labels10) (by decide +kernel) (by decide +kernel) + +/-- Independent cross-check of the first three values by brute force over all subsets of the +board, straight from the definition of `a` (no certificates). -/ +theorem a_small : [a 1, a 2, a 3] = [1, 4, 5] := by + decide +kernel + +/-- The definition reproduces the first 10 terms listed in OEIS (all listed terms). Each value is +proved by `a_eq_of_cert` from certificates whose side conditions are kernel-checked +(`decide +kernel`). -/ +theorem a_data : (List.range 10).map (fun i => a (i + 1)) = + [1, 4, 5, 8, 13, 20, 25, 32, 41, 52] := by + show [a 1, a 2, a 3, a 4, a 5, a 6, a 7, a 8, a 9, a 10] = _ + rw [a_1, a_2, a_3, a_4, a_5, a_6, a_7, a_8, a_9, a_10] + +/-- Conjecture (Yang Hong, A348484): for every `n ≥ 1`, `a(n) = n²/2` if `n ≡ 0 (mod 4)`, +`a(n) = (n² + 1)/2` if `n ≡ 1` or `3 (mod 4)`, and `a(n) = n²/2 + 2` if `n ≡ 2 (mod 4)`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + (n % 4 = 0 → a n = n ^ 2 / 2) ∧ + (n % 4 = 1 ∨ n % 4 = 3 → a n = (n ^ 2 + 1) / 2) ∧ + (n % 4 = 2 → a n = n ^ 2 / 2 + 2) + +end Math0.Statements.A348484 diff --git a/lean/Math0/Statements/OEIS/A350499.lean b/lean/Math0/Statements/OEIS/A350499.lean new file mode 100644 index 0000000..6597ec5 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A350499.lean @@ -0,0 +1,595 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A350499: Kurkov's recursion for the free cumulants + +Source: https://oeis.org/A350499, _Mikhail Kurkov_, Mar 30 2025 (FORMULA section; the entry is by +_Tom Copeland_, Jan 01 2022, with terms `a(19)` and beyond by _Andrew Howroyd_). Verbatim: +> Conjecture: free cumulants in terms of the free moments are R(n,1) for n > 0 where +> R(n,k) = R(n-1,k+1) - Sum_{j=1..n-1} R(j,k)*R(n-j,1) for n > 1, k > 0 with R(1,k) = m_k for +> k > 0. - _Mikhail Kurkov_, Mar 30 2025 + +The entry's name: "Unsigned coefficients of free moment partition polynomials determining the free +cumulants from the free moments of free probability theory. Irregular triangle with row lengths +given by A000041, n >= 1." Comment: "Coefficients are listed in Abramowitz and Stegun order +(A036036)." Formula: "O.g.f.: C(x) = 1 + c_1 x + c_2 x^2 + ... = x / (x + m_1 x^2 + m_2 x^3 + +m_3 x^4 + ...)^(-1) = x / M^(-1)(x), the shifted reciprocal of the compositional inverse of a +power series M(x) = x + m_1 x^2 + m_2 x^3 + ..., the o.g.f. of the free moments m_n in free +probability theory." Offset `1`; data: 66 terms (rows `n = 1, …, 8`). + +## Encoding + +* *Moments.* The conjecture is an identity between polynomials in the free moments, so the + moments are the indeterminates `m_k = MvPolynomial.X k` (`k ≥ 1`) of `ℤ[m_1, m_2, …] = + MvPolynomial ℕ ℤ`, with the normalization `m_0 = 1` (`mom`). (This is the universal case: by + evaluation it implies the identity for every sequence of moments in every commutative ring.) +* *Free cumulants*, following the entry's o.g.f.: `M(x) = x + m₁x² + m₂x³ + ⋯` (`M`); its + compositional inverse `M^⟨-1⟩` is Mathlib's `PowerSeries.substInvOfIsUnit` (`Minv`; it is a + two-sided inverse, `M_subst_Minv : M(M^⟨-1⟩(x)) = x` and `Minv_subst_M`); `C(x) = x / M^⟨-1⟩(x)` + (`Cgf`) is defined as the inverse of the power series `M^⟨-1⟩(x)/x`, which has constant term `1` + (so `Cgf_mul_Minv : C(x) · M^⟨-1⟩(x) = x`, which determines `C`); and the free cumulant + `c_n = freeCumulant n` is the coefficient of `xⁿ` in `C(x)` (so `c_0 = 1`). +* *The triangle.* `T n k` (`n ≥ 1`, `0 ≤ k < p(n)`) is the absolute value of the coefficient, in + `c_n`, of the monomial `m_λ = m_{λ₁} m_{λ₂} ⋯` of the `k`-th partition `λ` of `n` (counting from + `0`) in Abramowitz–Stegun order. `asPartitions n` produces that order: by increasing number of + parts, then in increasing lexicographic order of the weakly increasing lists of parts (the + definition of A036036). It lists every partition of `n` exactly once (`mem_asPartitions`, + `nodup_asPartitions`) and reproduces all 99 listed terms of A036036 (`asPartitions_A036036`). +* *Computing `T`.* `T` is computable: `c_n` is computed in a list representation of integer + polynomials (`Poly`, with meaning `ev`) by the recursion `c_0 = 1`, + `c_t = m_t - ∑_{n=1}^{t-1} c_n [x^(t-n)] P(x)^n`, where `P(x) = M(x)/x`. This recursion is the + coefficient form of `C(M(x)) = M(x)/x` and is *derived* from the definitions above + (`Cgf_subst_M`, `cumulant_moment`, `freeCumulant_succ`). `ev_cumPoly` proves that the computed + list denotes `freeCumulant n`, and `T_eq_coeff` restates `T n k` as + `|MvPolynomial.coeff λ (freeCumulant n)|`; so the computable `T` is provably the entry's + definition. As a check of the signs, `cumulant_examples` reproduces the signed polynomials + `c_1, …, c_5` shown in the entry's EXAMPLE section. +* *Data.* `a` is the triangle read by rows (offset `1`); `a_data` checks all 66 listed terms + `a 1, …, a 66` in the kernel. +* *Kurkov's array* `R m n k` is defined for any commutative ring and moment sequence `m`; + `R_one` and `R_rec` are the literal clauses `R(1,k) = m_k` and + `R(n,k) = R(n-1,k+1) - ∑_{j=1}^{n-1} R(j,k) R(n-j,1)` (`n > 1`). The recursion only ever + increases `k`, so starting from `k = 1` it uses only `k > 0` and `m_k` with `k > 0`, as in the + entry; the values `R(0, k)` (junk, `0`) are never used for `n ≥ 1`. +* *The conjecture* (`statement`): for every `n > 0`, `R(n, 1) = c_n` in `ℤ[m_1, m_2, …]`, where + `R` is built from `R(1, k) = m_k`. +-/ + +namespace Math0.Statements.A350499 + +open PowerSeries + +/-! ### Free moments and free cumulants -/ + +/-- The free moments as polynomials over `ℤ` in the indeterminates `m_1, m_2, …`: `mom 0 = 1` +(normalization `m_0 = 1`) and `mom k = m_k = X k` for `k ≥ 1`. -/ +noncomputable def mom (k : ℕ) : MvPolynomial ℕ ℤ := if k = 0 then 1 else MvPolynomial.X k + +/-- The moment series `M(x) = x + m₁ x² + m₂ x³ + ⋯` (the coefficient of `x^(k+1)` is `m_k`). -/ +noncomputable def M : PowerSeries (MvPolynomial ℕ ℤ) := + PowerSeries.mk fun i => if i = 0 then 0 else mom (i - 1) + +theorem constantCoeff_M : constantCoeff M = 0 := by + simp [M, ← coeff_zero_eq_constantCoeff_apply] + +theorem coeff_one_M : coeff 1 M = 1 := by + simp [M, mom] + +theorem isUnit_coeff_one_M : IsUnit (coeff 1 M) := by + rw [coeff_one_M]; exact isUnit_one + +/-- The compositional inverse `M^⟨-1⟩` of `M` (Mathlib's `PowerSeries.substInvOfIsUnit`). -/ +noncomputable def Minv : PowerSeries (MvPolynomial ℕ ℤ) := + M.substInvOfIsUnit isUnit_coeff_one_M + +/-- `M(M^⟨-1⟩(x)) = x`. -/ +theorem M_subst_Minv : M.subst Minv = X := + M.subst_substInvOfIsUnit_right constantCoeff_M isUnit_coeff_one_M + +/-- `M^⟨-1⟩(M(x)) = x`. -/ +theorem Minv_subst_M : Minv.subst M = X := + M.subst_substInvOfIsUnit_left constantCoeff_M isUnit_coeff_one_M + +theorem constantCoeff_Minv : constantCoeff Minv = 0 := + M.constantCoeff_substInvOfIsUnit isUnit_coeff_one_M + +theorem coeff_one_Minv : coeff 1 Minv = 1 := by + rw [Minv, coeff_one_substInvOfIsUnit] + have : isUnit_coeff_one_M.unit = 1 := Units.ext coeff_one_M + rw [this, inv_one, Units.val_one] + +/-- The generating function of the free cumulants, `C(x) = x / M^⟨-1⟩(x)`: writing +`M^⟨-1⟩(x) = x · Q(x)` with `Q(x) = 1 + q₁ x + ⋯`, it is `C = Q⁻¹`. -/ +noncomputable def Cgf : PowerSeries (MvPolynomial ℕ ℤ) := + invOfUnit (PowerSeries.mk fun n => coeff (n + 1) Minv) 1 + +/-- `C(x) · M^⟨-1⟩(x) = x`, i.e. `C(x) = x / M^⟨-1⟩(x)`. -/ +theorem Cgf_mul_Minv : Cgf * Minv = X := by + have h := sub_const_eq_X_mul_shift Minv + rw [constantCoeff_Minv, map_zero, sub_zero] at h + rw [h, mul_comm, mul_assoc, Cgf, mul_invOfUnit, mul_one] + simp [coeff_one_Minv, ← coeff_zero_eq_constantCoeff_apply] + +/-- The free cumulant `c_n = [x^n] C(x)`, a polynomial in the free moments. -/ +noncomputable def freeCumulant (n : ℕ) : MvPolynomial ℕ ℤ := coeff n Cgf + +/-! ### The moment–cumulant relation `C(M(x)) = M(x)/x` -/ + +/-- `P(x) = 1 + m₁ x + m₂ x² + ⋯ = M(x)/x`. -/ +noncomputable def P : PowerSeries (MvPolynomial ℕ ℤ) := PowerSeries.mk mom + +theorem M_eq : M = X * P := by + ext n; cases n <;> simp [M, P, coeff_succ_X_mul] + +theorem hasSubst_M : HasSubst M := HasSubst.of_constantCoeff_zero' constantCoeff_M + +theorem Cgf_subst_M : (Cgf.subst M : PowerSeries (MvPolynomial ℕ ℤ)) = P := by + have h1 : ((Cgf * Minv).subst M : PowerSeries (MvPolynomial ℕ ℤ)) = + (Cgf.subst M : PowerSeries (MvPolynomial ℕ ℤ)) * X := by + rw [subst_mul hasSubst_M, Minv_subst_M] + rw [Cgf_mul_Minv, subst_X hasSubst_M] at h1 + refine PowerSeries.ext fun n => ?_ + have h2 := congrArg (coeff (n + 1)) h1 + have h3 := congrArg (coeff (n + 1)) M_eq + rw [coeff_succ_mul_X] at h2 + rw [coeff_succ_X_mul] at h3 + rw [← h2, h3] + +theorem coeff_M_pow (d e : ℕ) : + coeff e (M ^ d) = if d ≤ e then coeff (e - d) (P ^ d) else 0 := by + rw [M_eq, mul_pow, coeff_X_pow_mul'] + +theorem constantCoeff_P : constantCoeff P = 1 := by + simp [P, mom, ← coeff_zero_eq_constantCoeff_apply] + +theorem coeff_zero_P_pow (d : ℕ) : coeff 0 (P ^ d) = 1 := by + rw [coeff_zero_eq_constantCoeff_apply, map_pow, constantCoeff_P, one_pow] + +/-- `∑_{d=0}^{e} c_d [x^(e-d)] P(x)^d = m_e`, the coefficient form of `C(M(x)) = P(x)`. -/ +theorem cumulant_moment (e : ℕ) : + ∑ d ∈ Finset.range (e + 1), freeCumulant d * coeff (e - d) (P ^ d) = mom e := by + have h := congrArg (coeff e) Cgf_subst_M + rw [coeff_subst' hasSubst_M, finsum_eq_sum_of_support_subset _ (s := Finset.range (e + 1))] + at h + · rw [P, coeff_mk] at h + rw [← h] + refine Finset.sum_congr rfl fun d hd => ?_ + rw [Finset.mem_range] at hd + rw [smul_eq_mul, coeff_M_pow, if_pos (by omega), freeCumulant, P] + · intro d hd + rw [Function.mem_support] at hd + rw [Finset.coe_range, Set.mem_Iio] + by_contra hlt + apply hd + rw [coeff_M_pow, if_neg (by omega), smul_zero] + +theorem freeCumulant_zero : freeCumulant 0 = 1 := by + simpa [mom, coeff_zero_P_pow] using cumulant_moment 0 + +theorem freeCumulant_succ (t : ℕ) : freeCumulant (t + 1) = mom (t + 1) - + ∑ n ∈ Finset.range t, freeCumulant (n + 1) * coeff (t - n) (P ^ (n + 1)) := by + have h := cumulant_moment (t + 1) + rw [Finset.sum_range_succ, Finset.sum_range_succ'] at h + simp only [Nat.sub_self, coeff_zero_P_pow, mul_one, pow_zero, Nat.sub_zero, coeff_one, + Nat.add_one_ne_zero, if_false, mul_zero, add_zero, Nat.add_sub_add_right] at h + rw [← h] + ring + +/-! ### Computable polynomial arithmetic -/ + +/-- A polynomial with integer coefficients in the moments `m_1, m_2, …`, as a list of terms +`(l, c)` standing for `c · m_{l₁} m_{l₂} ⋯` (repeated monomials are allowed: their coefficients +add up). Its meaning is `ev`. -/ +abbrev Poly := List (List ℕ × ℤ) + +/-- The meaning of a single term `(l, c)`: `c · ∏_{i ∈ l} m_i`. -/ +noncomputable def tm (t : List ℕ × ℤ) : MvPolynomial ℕ ℤ := + MvPolynomial.C t.2 * (t.1.map MvPolynomial.X).prod + +/-- The polynomial denoted by `p : Poly`. -/ +noncomputable def ev (p : Poly) : MvPolynomial ℕ ℤ := (p.map tm).sum + +/-- Insert an index into a weakly increasing list of indices (keeps monomials sorted, so that +equal monomials are recognised by `addTerm`). -/ +def insertIdx (i : ℕ) : List ℕ → List ℕ + | [] => [i] + | j :: l => if i ≤ j then i :: j :: l else j :: insertIdx i l + +/-- Add one term to a polynomial, merging it with a term having the same index list. -/ +def addTerm (t : List ℕ × ℤ) : Poly → Poly + | [] => [t] + | s :: p => if s.1 = t.1 then (s.1, s.2 + t.2) :: p else s :: addTerm t p + +/-- Sum of two polynomials. -/ +def padd (p q : Poly) : Poly := q.foldl (fun acc t => addTerm t acc) p + +/-- Negation. -/ +def pneg (p : Poly) : Poly := p.map fun t => (t.1, -t.2) + +/-- Product of two polynomials. -/ +def pmul (p q : Poly) : Poly := + p.foldl (fun acc s => q.foldl (fun acc' t => addTerm (s.1.foldr insertIdx t.1, s.2 * t.2) acc') + acc) [] + +/-- Sum of a list of polynomials. -/ +def psum (l : List Poly) : Poly := l.foldl padd [] + +/-- The coefficient of the monomial `∏_{i ∈ μ} m_i` (the multiset of indices `μ`). -/ +def coeffOf (p : Poly) (μ : List ℕ) : ℤ := + (p.map fun t => if (t.1 : Multiset ℕ) = μ then t.2 else 0).sum + +@[simp] theorem ev_nil : ev [] = 0 := rfl + +@[simp] theorem ev_cons (t : List ℕ × ℤ) (p : Poly) : ev (t :: p) = tm t + ev p := by + simp [ev] + +theorem ev_addTerm (t : List ℕ × ℤ) : ∀ p, ev (addTerm t p) = ev p + tm t + | [] => by simp [addTerm] + | s :: p => by + unfold addTerm + split_ifs with h + · simp only [ev_cons, tm, h, map_add] + ring + · simp only [ev_cons, ev_addTerm t p] + ring + +theorem ev_foldl_addTerm : ∀ (q p : Poly), + ev (q.foldl (fun acc t => addTerm t acc) p) = ev p + ev q + | [], p => by simp + | t :: q, p => by + simp only [List.foldl_cons, ev_foldl_addTerm q, ev_addTerm, ev_cons] + ring + +@[simp] theorem ev_padd (p q : Poly) : ev (padd p q) = ev p + ev q := ev_foldl_addTerm q p + +@[simp] theorem ev_pneg : ∀ p : Poly, ev (pneg p) = -ev p + | [] => by simp [pneg] + | t :: p => by + have := ev_pneg p + simp only [pneg, List.map_cons, ev_cons] at this ⊢ + rw [this, tm, tm, map_neg] + ring + +theorem prod_insertIdx (i : ℕ) : ∀ l : List ℕ, + ((insertIdx i l).map MvPolynomial.X).prod = + (MvPolynomial.X i : MvPolynomial ℕ ℤ) * (l.map MvPolynomial.X).prod + | [] => by simp [insertIdx] + | j :: l => by + unfold insertIdx + split_ifs + · simp + · simp only [List.map_cons, List.prod_cons, prod_insertIdx i l] + ring + +theorem prod_foldr_insertIdx (u v : List ℕ) : + ((u.foldr insertIdx v).map MvPolynomial.X).prod = + ((u.map MvPolynomial.X).prod : MvPolynomial ℕ ℤ) * (v.map MvPolynomial.X).prod := by + induction u with + | nil => simp + | cons i u ih => + simp only [List.foldr_cons, prod_insertIdx, ih, List.map_cons, List.prod_cons] + ring + +theorem ev_inner (s : List ℕ × ℤ) : ∀ (q acc : Poly), + ev (q.foldl (fun acc' t => addTerm (s.1.foldr insertIdx t.1, s.2 * t.2) acc') acc) = + ev acc + tm s * ev q + | [], acc => by simp + | t :: q, acc => by + simp only [List.foldl_cons, ev_inner s q, ev_addTerm, ev_cons, tm, prod_foldr_insertIdx, + map_mul] + ring + +theorem ev_outer (q : Poly) : ∀ (p acc : Poly), + ev (p.foldl (fun acc s => q.foldl + (fun acc' t => addTerm (s.1.foldr insertIdx t.1, s.2 * t.2) acc') acc) acc) = + ev acc + ev p * ev q + | [], acc => by simp + | s :: p, acc => by + simp only [List.foldl_cons, ev_outer q p, ev_inner, ev_cons] + ring + +@[simp] theorem ev_pmul (p q : Poly) : ev (pmul p q) = ev p * ev q := by + simp [pmul, ev_outer] + +theorem ev_foldl_padd : ∀ (l : List Poly) (acc : Poly), + ev (l.foldl padd acc) = ev acc + (l.map ev).sum + | [], acc => by simp + | p :: l, acc => by + simp only [List.foldl_cons, ev_foldl_padd l, ev_padd, List.map_cons, List.sum_cons] + ring + +@[simp] theorem ev_psum (l : List Poly) : ev (psum l) = (l.map ev).sum := by + simp [psum, ev_foldl_padd] + +theorem sum_map_range {β : Type*} [AddCommMonoid β] (f : ℕ → β) (n : ℕ) : + ((List.range n).map f).sum = ∑ i ∈ Finset.range n, f i := by + induction n with + | zero => simp + | succ n ih => simp [List.range_succ, Finset.sum_range_succ, ih] + +theorem prod_map_X (l : List ℕ) : (l.map MvPolynomial.X).prod = + (MvPolynomial.monomial (Multiset.toFinsupp (l : Multiset ℕ)) 1 : MvPolynomial ℕ ℤ) := by + induction l with + | nil => simp + | cons i l ih => + rw [List.map_cons, List.prod_cons, ih, MvPolynomial.X, MvPolynomial.monomial_mul, one_mul, + ← Multiset.cons_coe, ← Multiset.singleton_add, Multiset.toFinsupp_add, + Multiset.toFinsupp_singleton] + +/-- `coeffOf` computes coefficients. -/ +theorem coeff_ev (p : Poly) (μ : List ℕ) : + MvPolynomial.coeff (Multiset.toFinsupp (μ : Multiset ℕ)) (ev p) = coeffOf p μ := by + induction p with + | nil => simp [coeffOf] + | cons t p ih => + have h : coeffOf (t :: p) μ = (if (t.1 : Multiset ℕ) = μ then t.2 else 0) + coeffOf p μ := by + simp [coeffOf] + rw [h, ev_cons, MvPolynomial.coeff_add, ih, tm, prod_map_X, MvPolynomial.C_mul_monomial, + mul_one, MvPolynomial.coeff_monomial] + by_cases ht : (t.1 : Multiset ℕ) = μ <;> simp [ht] + +/-! ### Computing the free cumulants -/ + +/-- The coefficient of `x^s` in `P(x) = 1 + m₁ x + m₂ x² + ⋯`. -/ +def Pl (s : ℕ) : Poly := if s = 0 then [([], 1)] else [([s], 1)] + +theorem ev_Pl (s : ℕ) : ev (Pl s) = mom s := by + unfold Pl mom; split_ifs <;> simp [tm] + +/-- The product of two power series given by their lists of coefficients, truncated to the +coefficients of `x^0, …, x^D`. -/ +def serMul (D : ℕ) (f g : List Poly) : List Poly := + (List.range (D + 1)).map fun t => + psum ((List.range (t + 1)).map fun i => pmul (f.getD i []) (g.getD (t - i) [])) + +theorem ev_serMul (D : ℕ) (f g : List Poly) {t : ℕ} (ht : t ≤ D) : + ev ((serMul D f g).getD t []) = + ∑ i ∈ Finset.range (t + 1), ev (f.getD i []) * ev (g.getD (t - i) []) := by + rw [serMul, List.getD_eq_getElem?_getD, List.getElem?_map, List.getElem?_range (by omega)] + simp [sum_map_range, Function.comp_def] + +/-- `[P^0, P^1, …, P^n]`, each truncated to the coefficients of `x^0, …, x^D`. -/ +def powsL (D : ℕ) : ℕ → List (List Poly) + | 0 => [(List.range (D + 1)).map fun s => if s = 0 then [([], 1)] else []] + | n + 1 => powsL D n ++ [serMul D ((powsL D n).getD n []) ((List.range (D + 1)).map Pl)] + +theorem powsL_spec (D : ℕ) : ∀ n, (powsL D n).length = n + 1 ∧ + ∀ j ≤ n, ∀ s ≤ D, ev (((powsL D n).getD j []).getD s []) = coeff s (P ^ j) + | 0 => by + refine ⟨rfl, fun j hj s hs => ?_⟩ + obtain rfl : j = 0 := by omega + rw [powsL, List.getD_cons_zero, List.getD_eq_getElem?_getD, List.getElem?_map, + List.getElem?_range (by omega)] + by_cases h : s = 0 <;> simp [h, tm, coeff_one] + | n + 1 => by + obtain ⟨hl, hs⟩ := powsL_spec D n + refine ⟨by simp [powsL, hl], fun j hj s hsD => ?_⟩ + rw [powsL] + rcases Nat.lt_or_ge j (n + 1) with hjn | hjn + · rw [List.getD_append _ _ _ _ (by omega)] + exact hs j (by omega) s hsD + · obtain rfl : j = n + 1 := by omega + rw [List.getD_append_right _ _ _ _ (by omega), hl, Nat.sub_self, List.getD_cons_zero, + ev_serMul D _ _ hsD, pow_succ, coeff_mul, Finset.Nat.sum_antidiagonal_eq_sum_range_succ + (fun i k => coeff i (P ^ n) * coeff k P)] + refine Finset.sum_congr rfl fun i hi => ?_ + rw [Finset.mem_range] at hi + rw [hs n le_rfl i (by omega), List.getD_eq_getElem?_getD, List.getElem?_map, + List.getElem?_range (by omega), Option.map_some, Option.getD_some, ev_Pl, P, coeff_mk] + +/-- `[c_0, c_1, …, c_t]`, computed by the recursion `freeCumulant_succ`, given the table `pw` of +the coefficients of the powers of `P` (see `powsL`). -/ +def cumsL (pw : List (List Poly)) : ℕ → List Poly + | 0 => [[([], 1)]] + | t + 1 => cumsL pw t ++ [padd (Pl (t + 1)) (pneg (psum ((List.range t).map fun n => + pmul ((cumsL pw t).getD (n + 1) []) ((pw.getD (n + 1) []).getD (t - n) []))))] + +theorem cumsL_spec (D : ℕ) (pw : List (List Poly)) + (hpw : ∀ j ≤ D, ∀ s ≤ D, ev ((pw.getD j []).getD s []) = coeff s (P ^ j)) : + ∀ t ≤ D, (cumsL pw t).length = t + 1 ∧ + ∀ j ≤ t, ev ((cumsL pw t).getD j []) = freeCumulant j + | 0, _ => by + refine ⟨rfl, fun j hj => ?_⟩ + obtain rfl : j = 0 := by omega + simp [cumsL, tm, freeCumulant_zero] + | t + 1, ht => by + obtain ⟨hl, hc⟩ := cumsL_spec D pw hpw t (by omega) + refine ⟨by simp [cumsL, hl], fun j hj => ?_⟩ + rw [cumsL] + rcases Nat.lt_or_ge j (t + 1) with hjt | hjt + · rw [List.getD_append _ _ _ _ (by omega)] + exact hc j (by omega) + · obtain rfl : j = t + 1 := by omega + rw [List.getD_append_right _ _ _ _ (by omega), hl, Nat.sub_self, List.getD_cons_zero, + ev_padd, ev_pneg, ev_psum, ev_Pl, freeCumulant_succ, sub_eq_add_neg, List.map_map, + sum_map_range] + congr 2 + refine Finset.sum_congr rfl fun i hi => ?_ + rw [Finset.mem_range] at hi + simp only [Function.comp_apply, ev_pmul] + rw [hc (i + 1) (by omega), hpw (i + 1) (by omega) (t - i) (by omega)] + +/-- The `n`-th free cumulant, as a computed list of terms. -/ +def cumPoly (n : ℕ) : Poly := (cumsL (powsL n n) n).getD n [] + +/-- `cumPoly n` is the free cumulant `c_n`. -/ +theorem ev_cumPoly (n : ℕ) : ev (cumPoly n) = freeCumulant n := + (cumsL_spec n (powsL n n) (fun j hj s hs => (powsL_spec n n).2 j hj s hs) n le_rfl).2 n le_rfl + +/-! ### Partitions in Abramowitz–Stegun order -/ + +/-- `partsAsc n j lo`: the partitions of `n` into exactly `j` parts, all of them `≥ lo`, each +written as a weakly increasing list, listed in increasing lexicographic order (the first part +`p` runs upward from `lo`, and the remaining parts form a partition of `n - p` into `j - 1` +parts `≥ p`). -/ +def partsAsc (n : ℕ) : ℕ → ℕ → List (List ℕ) + | 0, _ => if n = 0 then [[]] else [] + | j + 1, lo => + (List.range' lo (n + 1 - lo)).flatMap fun p => (partsAsc (n - p) j p).map (p :: ·) + +/-- The partitions of `n` in Abramowitz–Stegun order (A036036): by increasing number of parts +`1, 2, …, n`, and for a fixed number of parts in increasing lexicographic order of the weakly +increasing lists of parts. -/ +def asPartitions (n : ℕ) : List (List ℕ) := + (List.range n).flatMap fun j => partsAsc n (j + 1) 1 + +theorem mem_partsAsc : ∀ (j n lo : ℕ) (l : List ℕ), l ∈ partsAsc n j lo ↔ + l.length = j ∧ l.Pairwise (· ≤ ·) ∧ (∀ x ∈ l, lo ≤ x) ∧ l.sum = n + | 0, n, lo, l => by + unfold partsAsc + split_ifs with h + · subst h + constructor + · intro hl; simp at hl; simp [hl] + · rintro ⟨h1, -, -, -⟩; simpa using h1 + · simp only [List.not_mem_nil, false_iff, not_and] + intro h1 _ _ h4 + rw [List.length_eq_zero_iff.1 h1] at h4 + exact h (h4.symm.trans rfl) + | j + 1, n, lo, l => by + simp only [partsAsc, List.mem_flatMap, List.mem_range'_1, List.mem_map] + constructor + · rintro ⟨x, hx, l', hl', rfl⟩ + obtain ⟨h1, h2, h3, h4⟩ := (mem_partsAsc j _ _ _).1 hl' + refine ⟨by simp [h1], List.pairwise_cons.2 ⟨h3, h2⟩, ?_, ?_⟩ + · intro y hy + rcases List.mem_cons.1 hy with rfl | hy + · omega + · have := h3 y hy; omega + · rw [List.sum_cons, h4]; omega + · rintro ⟨h1, h2, h3, h4⟩ + cases l with + | nil => simp at h1 + | cons x l' => + rw [List.pairwise_cons] at h2 + simp only [List.length_cons, Nat.add_right_cancel_iff, List.mem_cons, forall_eq_or_imp, + List.sum_cons] at h1 h3 h4 + refine ⟨x, ⟨h3.1, by omega⟩, l', (mem_partsAsc j _ _ _).2 ⟨h1, h2.2, h2.1, by omega⟩, rfl⟩ + +/-- `asPartitions n` lists exactly the partitions of `n`, written as nonempty weakly increasing +lists of positive integers with sum `n` (for `n = 0` the list is empty: row `0` is not part of +the triangle). -/ +theorem mem_asPartitions (n : ℕ) (l : List ℕ) : l ∈ asPartitions n ↔ + l ≠ [] ∧ l.Pairwise (· ≤ ·) ∧ (∀ x ∈ l, 1 ≤ x) ∧ l.sum = n := by + simp only [asPartitions, List.mem_flatMap, List.mem_range, mem_partsAsc] + constructor + · rintro ⟨j, -, h1, h2, h3, h4⟩ + exact ⟨fun h => by simp [h] at h1, h2, h3, h4⟩ + · rintro ⟨h1, h2, h3, h4⟩ + have := List.length_le_sum_of_one_le l h3 + have := List.length_pos_iff.2 h1 + exact ⟨l.length - 1, by omega, by omega, h2, h3, h4⟩ + +/-- `asPartitions n` lists each partition of `n` only once. -/ +theorem nodup_asPartitions (n : ℕ) : (asPartitions n).Nodup := by + have hp : ∀ j n lo, (partsAsc n j lo).Nodup := by + intro j + induction j with + | zero => intro n lo; unfold partsAsc; split_ifs <;> simp + | succ j ih => + intro n lo + rw [partsAsc, List.nodup_flatMap] + refine ⟨fun p _ => (ih _ _).map List.cons_injective, ?_⟩ + refine (List.nodup_range' (s := lo) (n := n + 1 - lo)).pairwise_of_forall_ne + fun p _ q _ hpq => ?_ + rw [Function.onFun, List.disjoint_left] + simp only [List.mem_map] + rintro _ ⟨l, -, rfl⟩ ⟨l', -, h⟩ + exact hpq (List.cons_eq_cons.1 h).1.symm + rw [asPartitions, List.nodup_flatMap] + refine ⟨fun j _ => hp _ _ _, ?_⟩ + refine List.nodup_range.pairwise_of_forall_ne fun j _ j' _ hjj => ?_ + rw [Function.onFun, List.disjoint_left] + intro l hl hl' + rw [mem_partsAsc] at hl hl' + exact hjj (by omega) + +/-- The generator reproduces all 99 terms of A036036 listed in OEIS (rows `1, …, 6` and the +start of row `7`; kernel-checked). -/ +theorem asPartitions_A036036 : + ((List.range 7).flatMap fun n => (asPartitions (n + 1)).flatten).take 99 = + [1, 2, 1, 1, 3, 1, 2, 1, 1, 1, 4, 1, 3, 2, 2, 1, 1, 2, 1, 1, 1, 1, 5, 1, 4, 2, 3, 1, 1, 3, + 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 6, 1, 5, 2, 4, 3, 3, 1, 1, 4, 1, 2, 3, 2, 2, 2, 1, 1, + 1, 3, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 7, 1, 6, 2, 5, 3, 4, 1, 1, 5, 1, 2, 4, + 1, 3, 3, 2, 2, 3, 1, 1, 1] := by + decide +kernel + +/-! ### The sequence -/ + +/-- `T(n, k)`, for `n ≥ 1` and `0 ≤ k < p(n)`: the unsigned coefficient, in the free cumulant +`c_n`, of the monomial `m_{λ₁} m_{λ₂} ⋯` of the `k`-th partition `λ` of `n` in +Abramowitz–Stegun order (counting from `k = 0`). Computed from `cumPoly`; `T_eq_coeff` restates +it with `freeCumulant n`. -/ +def T (n k : ℕ) : ℕ := (coeffOf (cumPoly n) ((asPartitions n).getD k [])).natAbs + +/-- `T(n, k) = |[m_λ] c_n|` where `m_λ = ∏_{i ∈ λ} m_i` and `λ` is the `k`-th partition of `n` in +Abramowitz–Stegun order. -/ +theorem T_eq_coeff (n k : ℕ) : T n k = (MvPolynomial.coeff + (Multiset.toFinsupp ((asPartitions n).getD k [] : Multiset ℕ)) (freeCumulant n)).natAbs := by + rw [T, ← ev_cumPoly, coeff_ev] + +/-- A350499 (offset `1`): the irregular triangle `T` read by rows `n = 1, 2, 3, …`, row `n` +having `p(n)` entries (one per partition of `n`). Rows `1, …, i` contain at least `i` entries, so +entry number `i` of the concatenation lies among them. -/ +def a (i : ℕ) : ℕ := + ((List.range i).flatMap fun n => + (List.range (asPartitions (n + 1)).length).map (T (n + 1))).getD (i - 1) 0 + +/-- The definition reproduces all 66 terms listed in OEIS, `a 1, …, a 66` (rows `1, …, 8`; +kernel-checked). -/ +theorem a_data : (List.range 66).map (fun i => a (i + 1)) = + [1, 1, 1, 1, 3, 2, 1, 4, 2, 10, 5, 1, 5, 5, 15, 15, 35, 14, 1, 6, 6, 3, 21, 42, 7, 56, 84, + 126, 42, 1, 7, 7, 7, 28, 56, 28, 28, 84, 252, 84, 210, 420, 462, 132, 1, 8, 8, 8, 4, 36, + 72, 72, 36, 36, 120, 360, 180, 360, 30, 330, 1320, 660, 792, 1980, 1716, 429] := by + decide +kernel + +/-- Sanity check of the signs (kernel-checked): the signed coefficients of `c_1, …, c_5` in +Abramowitz–Stegun order, as in the entry's EXAMPLE section: `c_1 = m_1`, `c_2 = m_2 - m_1^2`, +`c_3 = m_3 - 3 m_2 m_1 + 2 m_1^3`, `c_4 = m_4 - 4 m_3 m_1 - 2 m_2^2 + 10 m_2 m_1^2 - 5 m_1^4`, +`c_5 = m_5 - 5 m_4 m_1 - 5 m_2 m_3 + 15 m_3 m_1^2 + 15 m_2^2 m_1 - 35 m_2 m_1^3 + 14 m_1^5` +(by `coeff_ev` and `ev_cumPoly` these are the coefficients of `freeCumulant n`). -/ +theorem cumulant_examples : + (List.range 5).map (fun n => (asPartitions (n + 1)).map (coeffOf (cumPoly (n + 1)))) = + [[1], [1, -1], [1, -3, 2], [1, -4, -2, 10, -5], [1, -5, -5, 15, 15, -35, 14]] := by + decide +kernel + +/-! ### Kurkov's recursion and the conjecture -/ + +/-- Kurkov's array over a commutative ring `A` with moments `m : ℕ → A`: +`R(1, k) = m_k` and `R(n, k) = R(n-1, k+1) - ∑_{j=1}^{n-1} R(j, k) R(n-j, 1)` for `n > 1` +(see `R_one`, `R_rec`). (`R(0, k) = 0` is a junk value; it is never used by the recursion for +`n ≥ 1`. Likewise only `m_k` with `k ≥ 1` enter `R(n, k)` for `n, k ≥ 1`.) In the sum below, +`j : Fin (n + 1)` stands for the index `j + 1 ∈ {1, …, n + 1}`. -/ +def R {A : Type*} [CommRing A] (m : ℕ → A) : ℕ → ℕ → A + | 0, _ => 0 + | 1, k => m k + | n + 2, k => R m (n + 1) (k + 1) - ∑ j : Fin (n + 1), R m (j + 1) k * R m (n + 1 - j) 1 +termination_by n => n +decreasing_by all_goals omega + +theorem R_one {A : Type*} [CommRing A] (m : ℕ → A) (k : ℕ) : R m 1 k = m k := by + rw [R] + +/-- Kurkov's recursion, literally: `R(n,k) = R(n-1,k+1) - ∑_{j=1}^{n-1} R(j,k) R(n-j,1)` for +`n > 1`. -/ +theorem R_rec {A : Type*} [CommRing A] (m : ℕ → A) {n : ℕ} (hn : 1 < n) (k : ℕ) : + R m n k = R m (n - 1) (k + 1) - ∑ j ∈ Finset.Icc 1 (n - 1), R m j k * R m (n - j) 1 := by + obtain ⟨n, rfl⟩ : ∃ n', n = n' + 2 := ⟨n - 2, by omega⟩ + rw [R, show n + 2 - 1 = n + 1 by omega, + Fin.sum_univ_eq_sum_range (fun j => R m (j + 1) k * R m (n + 1 - j) 1)] + congr 1 + rw [show Finset.Icc 1 (n + 1) = Finset.Ico 1 (n + 2) by ext; simp; omega, + Finset.sum_Ico_eq_sum_range, show n + 2 - 1 = n + 1 by omega] + refine Finset.sum_congr rfl fun j _ => ?_ + rw [show 1 + j = j + 1 by omega, show n + 2 - (j + 1) = n + 1 - j by omega] + +/-- Conjecture (Mikhail Kurkov, 2025): the free cumulants in terms of the free moments are +`c_n = R(n, 1)` for `n > 0`, where `R` is Kurkov's array with `R(1, k) = m_k`; as an identity of +polynomials over `ℤ` in the indeterminate moments `m_k = X k`. -/ +def statement : Prop := + ∀ n : ℕ, 0 < n → R (fun k => (MvPolynomial.X k : MvPolynomial ℕ ℤ)) n 1 = freeCumulant n + +end Math0.Statements.A350499 diff --git a/lean/Math0/Statements/OEIS/A350557.lean b/lean/Math0/Statements/OEIS/A350557.lean new file mode 100644 index 0000000..ca58524 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A350557.lean @@ -0,0 +1,126 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A350557: the signed triangle is the matrix inverse of A350512 + +Source: https://oeis.org/A350557, Werner Schulte, Jan 05 2022 (FORMULA section of the entry he +authored). Verbatim: +> Conjecture: M(n,k) = (-1)^(n-k) * T(n,k) is matrix inverse of A350512. + +The entry (offset `0`, keyword `tabl`) is "Triangle T(n,k) read by rows with +T(n,0) = (2*n)! / (2^n * n!) for n >= 0 and +T(n,k) = (Sum_{i=k..n} binomial(i-1,k-1) * 2^i * i! / (2*i)!) * (2*n)! / (2^n * n!) +for 0 < k <= n." +A350512 (Werner Schulte, Jan 02 2022, offset `0`, keyword `tabl`) is "Triangle read by rows +with T(n,0) = 1 for n >= 0 and T(n,k) = binomial(n-1,k-1)*(2*k*(n-k) + n)/k for 0 < k <= n." + +## Encoding + +* *The triangles.* Both definitions involve divisions, so both triangles are encoded literally + as rational-valued functions `T n k : ℚ` (A350557) and `L n k : ℚ` (A350512), using exactly the + formulas of the two names (`/` is division in `ℚ`; `binomial(i-1,k-1)` and `n-k` only occur + with `1 ≤ k ≤ i` resp. `k ≤ n`, so the natural-number subtractions there are exact). Outside + the triangles (`k > n`) both are set to `0`: the triangles are the nonzero parts of infinite + lower-triangular matrices, which is how "matrix inverse" is meant for them. +* *Data.* `T_data` checks, as rational numbers, all 45 listed terms of A350557 (rows + `n = 0, …, 8`); in particular these values are integers. `L_data` checks all 66 listed terms of + A350512 (rows `n = 0, …, 10`). The sequence `a` (offset `0`) is A350557 read by rows, with the + rational entries converted to `ℕ` by `⌊·⌋₊` (the entries are nonnegative integers, so this is + the identity on them; `T_data` shows this on the listed range); `a_data` checks `a 0, …, a 44`. +* *The conjecture.* `M n k = (-1)^(n-k) * T n k` (with `M n k = 0` for `k > n`, as `T n k = 0` + there). For lower-triangular infinite matrices the products are finite: the `(n, j)` entry of + `L * M` is `∑_{k=0}^{n} L(n,k) M(k,j)`, since `L(n,k) = 0` for `k > n`, and similarly for + `M * L`. "M is the matrix inverse of L" is encoded as `L * M = I` and `M * L = I`, i.e. for all + `n, j ≥ 0` both sums equal `1` if `n = j` and `0` otherwise. (Equivalently: for every `N`, the + `N × N` upper-left blocks of `L` and `M` are mutually inverse matrices.) `statement_check` + confirms both identities for `n, j < 12` (a sanity check of the transcription, not a proof). +-/ + +namespace Math0.Statements.A350557 + +/-- A350557: `T(n,0) = (2n)! / (2^n n!)` and, for `0 < k ≤ n`, +`T(n,k) = (∑_{i=k}^{n} binomial(i-1,k-1) · 2^i · i! / (2i)!) · (2n)! / (2^n n!)`; +`T(n,k) = 0` outside the triangle (`k > n`). Computed in `ℚ`, literally as in the name. -/ +def T (n k : ℕ) : ℚ := + if n < k then 0 + else if k = 0 then ((2 * n).factorial : ℚ) / (2 ^ n * n.factorial) + else (∑ i ∈ Finset.Icc k n, + ((i - 1).choose (k - 1) : ℚ) * 2 ^ i * i.factorial / (2 * i).factorial) * + (2 * n).factorial / (2 ^ n * n.factorial) + +/-- A350512: `L(n,0) = 1` and, for `0 < k ≤ n`, `L(n,k) = binomial(n-1,k-1) · (2k(n-k) + n) / k`; +`L(n,k) = 0` outside the triangle (`k > n`). Computed in `ℚ`, literally as in the name. -/ +def L (n k : ℕ) : ℚ := + if n < k then 0 + else if k = 0 then 1 + else ((n - 1).choose (k - 1) : ℚ) * (2 * k * (n - k : ℕ) + n) / k + +/-- The signed triangle `M(n,k) = (-1)^(n-k) · T(n,k)` of the conjecture. -/ +def M (n k : ℕ) : ℚ := (-1) ^ (n - k) * T n k + +/-! ### Data -/ + +/-- The definition of `T` reproduces all 45 listed terms of A350557 (rows `n = 0, …, 8`) exactly, +as rational numbers (kernel-checked). -/ +theorem T_data : (List.range 9).map (fun n => (List.range (n + 1)).map (T n)) = + [[1], + [1, 1], + [3, 4, 1], + [15, 21, 7, 1], + [105, 148, 52, 10, 1], + [945, 1333, 472, 96, 13, 1], + [10395, 14664, 5197, 1066, 153, 16, 1], + [135135, 190633, 67567, 13873, 2009, 223, 19, 1], + [2027025, 2859496, 1013512, 208116, 30170, 3380, 306, 22, 1]] := by + decide +kernel + +/-- The definition of `L` reproduces all 66 listed terms of A350512 (rows `n = 0, …, 10`) exactly, +as rational numbers (kernel-checked). -/ +theorem L_data : (List.range 11).map (fun n => (List.range (n + 1)).map (L n)) = + [[1], + [1, 1], + [1, 4, 1], + [1, 7, 7, 1], + [1, 10, 18, 10, 1], + [1, 13, 34, 34, 13, 1], + [1, 16, 55, 80, 55, 16, 1], + [1, 19, 81, 155, 155, 81, 19, 1], + [1, 22, 112, 266, 350, 266, 112, 22, 1], + [1, 25, 148, 420, 686, 686, 420, 148, 25, 1], + [1, 28, 189, 624, 1218, 1512, 1218, 624, 189, 28, 1]] := by + decide +kernel + +/-- A350557 as a sequence (offset `0`): the triangle `T` read by rows, entries converted to `ℕ` +by `⌊·⌋₊`. (Rows `0, …, i` contain at least `i + 1` entries, so the `i`-th entry of the +concatenation lies among them.) -/ +def a (i : ℕ) : ℕ := + ((List.range (i + 1)).flatMap fun n => (List.range (n + 1)).map fun k => ⌊T n k⌋₊).getD i 0 + +/-- The definition reproduces all 45 terms listed in OEIS, `a 0, …, a 44` (kernel-checked). -/ +theorem a_data : (List.range 45).map (fun i => a (i + 0)) = + [1, 1, 1, 3, 4, 1, 15, 21, 7, 1, 105, 148, 52, 10, 1, 945, 1333, 472, 96, 13, 1, 10395, + 14664, 5197, 1066, 153, 16, 1, 135135, 190633, 67567, 13873, 2009, 223, 19, 1, + 2027025, 2859496, 1013512, 208116, 30170, 3380, 306, 22, 1] := by + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjecture (Werner Schulte, 2022): the lower-triangular matrix `M(n,k) = (-1)^(n-k) T(n,k)` +is the matrix inverse of the lower-triangular matrix `L` of A350512, i.e. `L * M = I` and +`M * L = I`: for all `n, j ≥ 0`, `∑_{k=0}^{n} L(n,k) M(k,j) = [n = j]` and +`∑_{k=0}^{n} M(n,k) L(k,j) = [n = j]` (the terms with `k > n` vanish since both matrices are +lower triangular). -/ +def statement : Prop := + (∀ n j : ℕ, ∑ k ∈ Finset.range (n + 1), L n k * M k j = if n = j then 1 else 0) ∧ + (∀ n j : ℕ, ∑ k ∈ Finset.range (n + 1), M n k * L k j = if n = j then 1 else 0) + +/-- Sanity check of the transcription (not a proof): both identities hold for `n, j < 12`. -/ +theorem statement_check : + (∀ n < 12, ∀ j < 12, ∑ k ∈ Finset.range (n + 1), L n k * M k j = if n = j then 1 else 0) ∧ + (∀ n < 12, ∀ j < 12, ∑ k ∈ Finset.range (n + 1), M n k * L k j = if n = j then 1 else 0) := by + decide +kernel + +end Math0.Statements.A350557 diff --git a/lean/Math0/Statements/OEIS/A350900.lean b/lean/Math0/Statements/OEIS/A350900.lean new file mode 100644 index 0000000..acd1545 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A350900.lean @@ -0,0 +1,183 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A350900: Schulte's gcd-ratio double sum as a Dirichlet convolution + +Source: https://oeis.org/A350900, Werner Schulte, Jan 21 2022 (COMMENTS section). Verbatim: +> Conjecture: Let f be an arbitrary arithmetic function. Define for n > 0 the sequence +> a(f; n) = Sum_{i=1..n, k=1..n} f(gcd(i,n)/gcd(gcd(i,k),n)); a(f; n) equals Dirichlet +> convolution of f(n)*A000010(n) and A057660(n); if f is multiplicative, then a(f; n) is +> multiplicative; row sums of this triangle use f(n) = n (see formula section). + +and, in the FORMULA section of the same entry (same author and date). Verbatim: +> Conjecture: Row sums equal Dirichlet convolution of A002618 and A057660. + +The entry (keyword `tabl`, offset `1`) is "Triangle read by rows: +T(n, k) = Sum_{i=1..n} gcd(i,n) / gcd(gcd(i,k),n) for 1 <= k <= n." + +## Encoding + +* *The triangle.* `T n k = ∑_{i=1}^{n} gcd(i,n) / gcd(gcd(i,k),n)` with natural-number division; + the division is exact, since `gcd(gcd(i,k),n)` divides `gcd(i,n)`. `T_data` checks the 12 rows + listed in OEIS (`n = 1, …, 12`, i.e. all 78 listed terms) in the kernel. +* *The sequence.* `a` is the triangle read by rows with OEIS offset `1`: `pos i` is the pair + `(n, k)` in position `i` (0-based) of the row-by-row reading `(1,1), (2,1), (2,2), (3,1), …` + (rows `1, …, i + 1` contain at least `i + 1` entries, so the position exists), and + `a (i + 1) = T (pos i).1 (pos i).2`; `a 0 = 0` is outside the offset. `a_data` checks all 78 + listed terms `a 1, …, a 78`. +* *Referenced sequences.* `A000010` is Euler's totient (`Nat.totient`), packaged as the + arithmetic function `phi`. `A057660 m = ∑_{k=1}^{m} m / gcd(m,k)` is the OEIS definition of + A057660 (checked against its 52 listed terms in `A057660_data`), packaged as the arithmetic + function `A057660Fn`. `A002618 n = n * phi(n)` is the OEIS definition of A002618 (its first + 20 terms are checked in `A002618_data`), packaged as `A002618Fn`. +* *Arithmetic functions and Dirichlet convolution.* "Arbitrary arithmetic function" is read as + a complex-valued function on the positive integers, i.e. Mathlib's `ArithmeticFunction ℂ` + (a function `ℕ → ℂ` whose value at `0` is `0`; the value at `0` never enters `a(f; n)`, since + for `1 ≤ i ≤ n` the argument `gcd(i,n)/gcd(gcd(i,k),n)` is `≥ 1`). Dirichlet convolution is + Mathlib's product `*` of arithmetic functions, + `(g * h) n = ∑_{d e = n} g d * h e`, the pointwise product `f(n)*A000010(n)` is + `f.pmul phi`, and ℕ-valued functions are coerced to ℂ-valued ones. "Multiplicative" is + Mathlib's `ArithmeticFunction.IsMultiplicative` (`g 1 = 1` and `g (m n) = g m g n` for + coprime `m, n`). +* *`a(f; n)`.* `aF f n = ∑_{i=1}^{n} ∑_{k=1}^{n} f (gcd(i,n) / gcd(gcd(i,k),n))`, for any + coefficient semiring (the statement uses `ℂ`); it is `0` at `n = 0` (empty sum), so it is + itself an arithmetic function `aFun f`, which is how "a(f; n) is multiplicative" is read. +* *The conjecture.* `statement` is the conjunction of + 1. for every arithmetic function `f` and every `n > 0`: + `a(f; n) = ((f · A000010) * A057660)(n)`; + 2. for every multiplicative `f`, `a(f; ·)` is multiplicative; + 3. "row sums of this triangle use f(n) = n": for `n > 0`, + `∑_{k=1}^{n} T(n,k) = a(id; n)` (with `id` the identity arithmetic function, cast to `ℂ`); + 4. the FORMULA-section conjecture: for `n > 0`, + `∑_{k=1}^{n} T(n,k) = (A002618 * A057660)(n)` (computed in `ℕ`). + Parts 1, 3, 4 restrict to `n > 0` as the entry does (at `n = 0` all sides are `0` anyway). + `statement_check_rows` confirms part 4 for `n ≤ 12`, and `statement_check_aF` confirms the + identity of part 1 for `n ≤ 12` for one non-multiplicative ℕ-valued test function (sanity + checks of the transcription, not proofs). +-/ + +namespace Math0.Statements.A350900 + +open ArithmeticFunction + +/-! ### The triangle and the sequence -/ + +/-- A350900: `T(n, k) = Sum_{i=1..n} gcd(i,n) / gcd(gcd(i,k),n)`. -/ +def T (n k : ℕ) : ℕ := + ∑ i ∈ Finset.Icc 1 n, Nat.gcd i n / Nat.gcd (Nat.gcd i k) n + +/-- The definition reproduces the 12 rows listed in OEIS (kernel-checked). -/ +theorem T_data : + (List.range 12).map (fun r => (List.range (r + 1)).map (fun j => T (r + 1) (j + 1))) = + [[1], + [3, 2], + [5, 5, 3], + [8, 5, 8, 4], + [9, 9, 9, 9, 5], + [15, 10, 9, 10, 15, 6], + [13, 13, 13, 13, 13, 13, 7], + [20, 12, 20, 9, 20, 12, 20, 8], + [21, 21, 11, 21, 21, 11, 21, 21, 9], + [27, 18, 27, 18, 15, 18, 27, 18, 27, 10], + [21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 11], + [40, 25, 24, 20, 40, 15, 40, 20, 24, 25, 40, 12]] := by + decide +kernel + +/-- The pair `(n, k)` (with `1 ≤ k ≤ n`) in position `i` (0-based) of the triangle read by rows: +`(1,1), (2,1), (2,2), (3,1), …`. Rows `1, …, i + 1` contain at least `i + 1` entries. -/ +def pos (i : ℕ) : ℕ × ℕ := + ((List.range (i + 1)).flatMap fun r => (List.range (r + 1)).map fun j => (r + 1, j + 1)).getD + i (0, 0) + +/-- A350900 as a sequence (offset `1`): the triangle `T` read by rows. -/ +def a : ℕ → ℕ + | 0 => 0 + | i + 1 => T (pos i).1 (pos i).2 + +/-- The definition reproduces all 78 terms listed in OEIS, `a 1, …, a 78` (kernel-checked). -/ +theorem a_data : (List.range 78).map (fun i => a (i + 1)) = + [1, 3, 2, 5, 5, 3, 8, 5, 8, 4, 9, 9, 9, 9, 5, 15, 10, 9, 10, 15, 6, 13, 13, 13, 13, 13, 13, + 7, 20, 12, 20, 9, 20, 12, 20, 8, 21, 21, 11, 21, 21, 11, 21, 21, 9, 27, 18, 27, 18, 15, + 18, 27, 18, 27, 10, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 11, 40, 25, 24, 20, 40, 15, + 40, 20, 24, 25, 40, 12] := by + decide +kernel + +/-! ### Referenced sequences as arithmetic functions -/ + +/-- A000010, Euler's totient, as an arithmetic function. -/ +def phi : ArithmeticFunction ℕ := ⟨Nat.totient, Nat.totient_zero⟩ + +/-- A057660: `a(m) = Sum_{k=1..m} m/gcd(m,k)`. -/ +def A057660 (m : ℕ) : ℕ := ∑ k ∈ Finset.Icc 1 m, m / Nat.gcd m k + +/-- The definition of `A057660` reproduces its 52 listed terms (kernel-checked). -/ +theorem A057660_data : (List.range 52).map (fun i => A057660 (i + 1)) = + [1, 3, 7, 11, 21, 21, 43, 43, 61, 63, 111, 77, 157, 129, 147, 171, 273, 183, 343, 231, + 301, 333, 507, 301, 521, 471, 547, 473, 813, 441, 931, 683, 777, 819, 903, 671, 1333, + 1029, 1099, 903, 1641, 903, 1807, 1221, 1281, 1521, 2163, 1197, 2101, 1563, 1911, + 1727] := by + decide +kernel + +/-- A057660 as an arithmetic function (its value at `0` is the empty sum `0`). -/ +def A057660Fn : ArithmeticFunction ℕ := ⟨A057660, by simp [A057660]⟩ + +/-- A002618: `a(n) = n*phi(n)`. -/ +def A002618 (n : ℕ) : ℕ := n * Nat.totient n + +/-- The definition of `A002618` reproduces its first 20 listed terms (kernel-checked). -/ +theorem A002618_data : (List.range 20).map (fun i => A002618 (i + 1)) = + [1, 2, 6, 8, 20, 12, 42, 32, 54, 40, 110, 48, 156, 84, 120, 128, 272, 108, 342, 160] := by + decide +kernel + +/-- A002618 as an arithmetic function. -/ +def A002618Fn : ArithmeticFunction ℕ := ⟨A002618, by simp [A002618]⟩ + +/-! ### Schulte's `a(f; n)` -/ + +/-- `a(f; n) = Sum_{i=1..n, k=1..n} f(gcd(i,n)/gcd(gcd(i,k),n))`. -/ +def aF {R : Type*} [AddCommMonoid R] (f : ArithmeticFunction R) (n : ℕ) : R := + ∑ i ∈ Finset.Icc 1 n, ∑ k ∈ Finset.Icc 1 n, f (Nat.gcd i n / Nat.gcd (Nat.gcd i k) n) + +/-- `a(f; ·)` as an arithmetic function (it vanishes at `0`, an empty sum). -/ +def aFun {R : Type*} [AddCommMonoid R] (f : ArithmeticFunction R) : ArithmeticFunction R := + ⟨aF f, by simp [aF]⟩ + +/-! ### The conjecture -/ + +/-- Conjecture (Werner Schulte, Jan 21 2022): for every arithmetic function `f`, +1. `a(f; n)` equals the Dirichlet convolution of `f(n)*A000010(n)` and `A057660(n)`, for `n > 0`; +2. if `f` is multiplicative, then `a(f; ·)` is multiplicative; +3. the row sums of the triangle are `a(f; n)` for `f(n) = n`, for `n > 0`; + +and (FORMULA section) 4. the row sums of the triangle equal the Dirichlet convolution of A002618 +and A057660, for `n > 0`. -/ +def statement : Prop := + (∀ f : ArithmeticFunction ℂ, ∀ n : ℕ, 0 < n → + aF f n = (f.pmul (phi : ArithmeticFunction ℂ) * (A057660Fn : ArithmeticFunction ℂ)) n) ∧ + (∀ f : ArithmeticFunction ℂ, f.IsMultiplicative → (aFun f).IsMultiplicative) ∧ + (∀ n : ℕ, 0 < n → + ((∑ k ∈ Finset.Icc 1 n, T n k : ℕ) : ℂ) = + aF ((ArithmeticFunction.id : ArithmeticFunction ℕ) : ArithmeticFunction ℂ) n) ∧ + (∀ n : ℕ, 0 < n → ∑ k ∈ Finset.Icc 1 n, T n k = (A002618Fn * A057660Fn) n) + +/-! ### Sanity checks of the transcription (not proofs) -/ + +/-- Part 4 of `statement` holds for `n ≤ 12`. -/ +theorem statement_check_rows : + ∀ n < 13, 0 < n → ∑ k ∈ Finset.Icc 1 n, T n k = (A002618Fn * A057660Fn) n := by + decide +kernel + +/-- A non-multiplicative ℕ-valued test function, `f(m) = 2m + (m mod 3)` for `m ≥ 1`. -/ +def fTest : ArithmeticFunction ℕ := ⟨fun m => if m = 0 then 0 else 2 * m + m % 3, rfl⟩ + +/-- The identity of part 1 of `statement`, with `fTest` in place of `f` (computed in `ℕ`), holds +for `n ≤ 12`. -/ +theorem statement_check_aF : + ∀ n < 13, 0 < n → aF fTest n = (fTest.pmul (phi : ArithmeticFunction ℕ) * + (A057660Fn : ArithmeticFunction ℕ)) n := by + decide +kernel + +end Math0.Statements.A350900 diff --git a/lean/Math0/Statements/OEIS/A351743.lean b/lean/Math0/Statements/OEIS/A351743.lean new file mode 100644 index 0000000..0d0d688 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A351743.lean @@ -0,0 +1,217 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A351743: greatest divisor of the partial sum prime to the previous term + +Sources (all verbatim): + +* https://oeis.org/A351743, _David James Sycamore_, Jun 07 2022 (COMMENTS section): + > Conjecture: a(n)=1 occurs infinitely many times, and therefore so does a(n)=2. +* https://oeis.org/A351743, FORMULA section: + > Conjectures from _Rémy Sigrist_, Jun 20 2022: (Start) + > - a(2*(n+21)-1) = a(2*n-1) for n >= 70, + > - a(2*(n+21)) = 3645*a(2*n) + b(n) for n >= 70 (where b is 21-periodic). + > (End) +* https://oeis.org/A355149 ("Partial sums of A351743", offset `1`; _Michael De Vlieger_, + _Rémy Sigrist_ and _David James Sycamore_, Jun 21 2022), FORMULA section: + > Conjecture: a(n + 42) = 3645*a(n) + b(n) for n >= 138 (where b is 42-periodic). + +The definition of A351743 (offset `1`): "a(1)=1. Thereafter, a(n+1) is the greatest divisor of +s(n) which is prime to a(n), where s(n) is the n-th partial sum." + +## Encoding + +* `a : ℕ → ℕ` with the OEIS offset `1`; `a 0 = 0` is a junk value that no statement uses (it is + different from `1` and `2`, so it does not affect the sets in `sycamore` either). + `s n = ∑ k ∈ [1, n], a k` is the `n`-th partial sum, literally; it is A355149 (offset `1`). +* Computation: the greatest divisor of `w > 0` prime to `v` is computed as in the entry's PARI + program, by dividing `w` by `gcd(w, v)` while this gcd exceeds `1` (`strip`, `coprimePart`). + The pairs `(a(n), s(n))` are produced by iterating `step` from `(a(1), s(1)) = (1, 1)`. + The theorems `a_one` and `a_succ_isGreatest` prove that `a` satisfies exactly the OEIS + definition: `a 1 = 1`, and for every `n ≥ 1`, `a (n + 1)` is the greatest element of + `{d | d ∣ s n ∧ Nat.Coprime d (a n)}`. These conditions determine the sequence. + `a_data` checks all 67 listed terms `a 1, …, a 67`, `s_data` the 50 listed terms of + A355149, and `a_example` the values `a(150), …, a(153)` of the entry's last example. +* Sycamore's conjecture (`sycamore`): both sets `{n | a n = 1}` and `{n | a n = 2}` are + infinite. The "and therefore" part is included as a second conjunct, since the conjecture + asserts it too. +* Sigrist's first formula (`sigristOdd`): for every `n ≥ 70`, `a(2(n+21)-1) = a(2n-1)` + (natural subtraction is harmless here, `2n - 1 ≥ 139`). +* Sigrist's second formula (`sigristEven`): "b is 21-periodic" is read as: there is an + integer sequence `b : ℕ → ℤ` with `b (n + 21) = b n` for all `n`, such that + `a(2(n+21)) = 3645 a(2n) + b(n)` for all `n ≥ 70`. The equation is stated in `ℤ`, as `b` may + a priori take negative values. (Asking `b` to be periodic on all of `ℕ` rather than only on + `n ≥ 70` changes nothing, since a sequence periodic from `70` on extends backwards + periodically.) +* The A355149 conjecture (`partialSums`), with `s` in place of A355149's `a`: there is + `c : ℕ → ℤ` with `c (n + 42) = c n` for all `n`, such that `s(n+42) = 3645 s(n) + c(n)` for + all `n ≥ 138`. +* `statement` is the conjunction of these four conjectures. +-/ + +namespace Math0.Statements.A351743 + +/-- Divide `w` by `gcd(w, v)` as long as this gcd is not `1`, for at most `fuel` steps. -/ +def strip : ℕ → ℕ → ℕ → ℕ + | 0, w, _ => w + | fuel + 1, w, v => if Nat.gcd w v = 1 then w else strip fuel (w / Nat.gcd w v) v + +/-- The greatest divisor of `w` prime to `v`, for `w > 0` (see `coprimePart_isGreatest`). -/ +def coprimePart (w v : ℕ) : ℕ := strip w w v + +/-- From `(a(n), s(n))` to `(a(n+1), s(n+1))`. -/ +def step (p : ℕ × ℕ) : ℕ × ℕ := + match p with + | (x, y) => + match coprimePart y x with + | z => (z, y + z) + +/-- `state n = (a(n+1), s(n+1))`. -/ +def state (n : ℕ) : ℕ × ℕ := step^[n] (1, 1) + +/-- A351743 (offset `1`): `a(1) = 1`, and `a(n+1)` is the greatest divisor of the partial sum +`s(n) = a(1) + ⋯ + a(n)` which is prime to `a(n)`. (`a 0 = 0` is a junk value.) -/ +def a : ℕ → ℕ + | 0 => 0 + | n + 1 => (state n).1 + +/-- The `n`-th partial sum `s(n) = a(1) + ⋯ + a(n)` of A351743, i.e. A355149 (offset `1`). -/ +def s (n : ℕ) : ℕ := ∑ k ∈ Finset.Icc 1 n, a k + +/-! ### `a` satisfies the OEIS definition -/ + +/-- `strip` computes the greatest divisor of `w` prime to `v`, once the fuel is at least `w`. -/ +theorem strip_isGreatest (v : ℕ) : + ∀ (fuel w : ℕ), 0 < w → w ≤ fuel → + IsGreatest {d | d ∣ w ∧ Nat.Coprime d v} (strip fuel w v) := by + intro fuel + induction fuel with + | zero => intro w hw hf; omega + | succ fuel ih => + intro w hw hf + simp only [strip] + split_ifs with hg + · refine ⟨⟨dvd_refl w, hg⟩, ?_⟩ + rintro d ⟨hd, -⟩ + exact Nat.le_of_dvd hw hd + · set g := Nat.gcd w v with hgdef + have hgw : g ∣ w := Nat.gcd_dvd_left w v + have hgpos : 0 < g := Nat.gcd_pos_of_pos_left v hw + have hg2 : 2 ≤ g := by omega + have hwg : 0 < w / g := Nat.div_pos (Nat.le_of_dvd hw hgw) hgpos + have hlt : w / g < w := Nat.div_lt_self hw (by omega) + have key := ih (w / g) hwg (by omega) + have hset : {d | d ∣ w / g ∧ Nat.Coprime d v} = {d | d ∣ w ∧ Nat.Coprime d v} := by + ext d + constructor + · rintro ⟨hd, hc⟩ + exact ⟨dvd_trans hd (Nat.div_dvd_of_dvd hgw), hc⟩ + · rintro ⟨hd, hc⟩ + refine ⟨?_, hc⟩ + have hcg : Nat.Coprime d g := Nat.Coprime.coprime_dvd_right (Nat.gcd_dvd_right w v) hc + apply hcg.dvd_of_dvd_mul_right + rw [Nat.div_mul_cancel hgw] + exact hd + rw [hset] at key + exact key + +/-- `coprimePart w v` is the greatest divisor of `w > 0` which is prime to `v`. -/ +theorem coprimePart_isGreatest (w v : ℕ) (hw : 0 < w) : + IsGreatest {d | d ∣ w ∧ Nat.Coprime d v} (coprimePart w v) := + strip_isGreatest v w w hw le_rfl + +theorem state_succ (n : ℕ) : + state (n + 1) = (coprimePart (state n).2 (state n).1, + (state n).2 + coprimePart (state n).2 (state n).1) := by + unfold state + rw [Function.iterate_succ_apply'] + rfl + +/-- `a(1) = 1`. -/ +theorem a_one : a 1 = 1 := rfl + +theorem a_succ_succ (n : ℕ) : a (n + 2) = coprimePart (state n).2 (state n).1 := by + show (state (n + 1)).1 = _ + rw [state_succ] + +theorem s_succ (n : ℕ) : s (n + 1) = s n + a (n + 1) := by + unfold s + rw [Finset.sum_Icc_succ_top (by omega)] + +/-- The second component of `state n` is the partial sum `s(n+1)`. -/ +theorem state_snd (n : ℕ) : (state n).2 = s (n + 1) := by + induction n with + | zero => rfl + | succ n ih => + rw [s_succ, ← ih, state_succ, a_succ_succ] + +theorem s_pos (n : ℕ) : 0 < s (n + 1) := by + rw [s_succ] + cases n with + | zero => simp [a_one] + | succ n => have := s_pos n; omega + +/-- The OEIS definition: for every `n ≥ 1`, `a(n+1)` is the greatest divisor of the partial sum +`s(n)` which is prime to `a(n)`. -/ +theorem a_succ_isGreatest (n : ℕ) (hn : 1 ≤ n) : + IsGreatest {d | d ∣ s n ∧ Nat.Coprime d (a n)} (a (n + 1)) := by + obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩ + rw [a_succ_succ, state_snd] + exact coprimePart_isGreatest _ _ (s_pos m) + +/-! ### Data checks -/ + +/-- The definition reproduces all 67 terms listed in OEIS, `a 1, …, a 67` (kernel-checked). -/ +theorem a_data : (List.range 67).map (fun i => a (i + 1)) = + [1, 1, 2, 1, 5, 2, 3, 5, 4, 3, 1, 28, 1, 57, 2, 29, 5, 6, 13, 1, 170, 1, 341, 2, 171, 5, 172, + 3, 115, 2, 9, 43, 28, 11, 113, 12, 19, 73, 20, 37, 41, 38, 21, 11, 148, 3, 593, 4, 297, 1, + 2674, 1, 5349, 2, 2675, 1, 13376, 1, 26753, 2, 13377, 5, 13378, 3, 991, 82, 31] := by + decide +kernel + +/-- The partial sums reproduce all 50 terms listed in A355149, `s 1, …, s 50` +(kernel-checked). -/ +theorem s_data : (List.range 50).map (fun i => s (i + 1)) = + [1, 2, 4, 5, 10, 12, 15, 20, 24, 27, 28, 56, 57, 114, 116, 145, 150, 156, 169, 170, 340, + 341, 682, 684, 855, 860, 1032, 1035, 1150, 1152, 1161, 1204, 1232, 1243, 1356, 1368, 1387, + 1460, 1480, 1517, 1558, 1596, 1617, 1628, 1776, 1779, 2372, 2376, 2673, 2674] := by + decide +kernel + +/-- The entry's last example: `a(150) = 473394`, `a(151) = 1`, `a(152) = 2840365`, +`a(153) = 2` (kernel-checked). -/ +theorem a_example : (List.range 4).map (fun i => a (i + 150)) = [473394, 1, 2840365, 2] := by + decide +kernel + +/-! ### The conjectures -/ + +/-- Sycamore's conjecture: `a(n) = 1` occurs infinitely many times, and so does `a(n) = 2`. -/ +def sycamore : Prop := + {n : ℕ | a n = 1}.Infinite ∧ {n : ℕ | a n = 2}.Infinite + +/-- Sigrist's first conjecture: `a(2(n+21)-1) = a(2n-1)` for all `n ≥ 70`. -/ +def sigristOdd : Prop := + ∀ n : ℕ, 70 ≤ n → a (2 * (n + 21) - 1) = a (2 * n - 1) + +/-- Sigrist's second conjecture: `a(2(n+21)) = 3645 a(2n) + b(n)` for all `n ≥ 70`, for some +21-periodic integer sequence `b`. -/ +def sigristEven : Prop := + ∃ b : ℕ → ℤ, (∀ n, b (n + 21) = b n) ∧ + ∀ n : ℕ, 70 ≤ n → (a (2 * (n + 21)) : ℤ) = 3645 * (a (2 * n) : ℤ) + b n + +/-- The A355149 conjecture: the partial sums satisfy `s(n+42) = 3645 s(n) + c(n)` for all +`n ≥ 138`, for some 42-periodic integer sequence `c`. -/ +def partialSums : Prop := + ∃ c : ℕ → ℤ, (∀ n, c (n + 42) = c n) ∧ + ∀ n : ℕ, 138 ≤ n → (s (n + 42) : ℤ) = 3645 * (s n : ℤ) + c n + +/-- The conjectures on A351743 and its partial sums A355149: `1` and `2` occur infinitely often +(Sycamore); the odd-indexed terms are eventually 42-periodic and the even-indexed terms satisfy +`a(2(n+21)) = 3645 a(2n) + b(n)` with `b` 21-periodic, both for `n ≥ 70` (Sigrist); and the +partial sums satisfy `s(n+42) = 3645 s(n) + c(n)` with `c` 42-periodic, for `n ≥ 138` +(A355149). -/ +def statement : Prop := + sycamore ∧ sigristOdd ∧ sigristEven ∧ partialSums + +end Math0.Statements.A351743 diff --git a/lean/Math0/Statements/OEIS/A354571.lean b/lean/Math0/Statements/OEIS/A354571.lean new file mode 100644 index 0000000..e928b1f --- /dev/null +++ b/lean/Math0/Statements/OEIS/A354571.lean @@ -0,0 +1,334 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A354571: even legs of primitive Pythagorean triangles with odd prime factors `≡ 3 (mod 4)` + +Source: https://oeis.org/A354571, _Lothar Selle_, Jun 04 2022 (COMMENTS section). Verbatim: +> Conjecture: lim_{n->oo} a(n)/n = Pi. Also, lim_{n->oo} A354570(n)/n = Pi. + +A354571 (offset `1`) is "Ordered even leg lengths k (listed with multiplicity) of primitive +Pythagorean triangles such that all odd prime factors of k are congruent to 3 (mod 4) and at +least one prime factor is odd." (`12, 12, 24, 24, 28, 28, 36, …`; `12` is listed twice because of +the triangles `(5,12,13)` and `(12,35,37)`.) + +A354570 (offset `1`, same author, Jun 03 2022) is "Ordered odd leg lengths k (listed with +multiplicity) of primitive Pythagorean triangles such that all prime factors of k are congruent +to 3 (mod 4)." (`3, 7, 9, 11, 19, 21, 21, 23, …`.) The conjecture speaks about both sequences, so +both are formalized here. + +## Encoding + +* `IsPPT x y z`: `(x, y, z)` is a primitive Pythagorean triangle with legs `x, y` and hypotenuse + `z`, i.e. `0 < x`, `0 < y`, `x² + y² = z²` and `gcd(x, y, z) = 1`. +* `legTriangles k : Finset (ℕ × ℕ)` is the set of pairs `(b, c)` (other leg, hypotenuse) such + that `IsPPT b k c`, i.e. it lists the primitive Pythagorean triangles having `k` as a leg, each + exactly once (a triangle cannot have two equal legs, since `2x² = z²` has no positive integer + solution). The theorem `mem_legTriangles` proves `(b, c) ∈ legTriangles k ↔ IsPPT b k c` for all + `k, b, c`; the `Finset` is computed by running `d = c - b` over `0, …, k - 1` (if `b² + k² = c²` + with `b, k > 0`, then `k² = d (2b + d)`, so `d < k`, `b = (k²/d - d)/2` and `c = b + d`), which + only matters for the speed of evaluation. +* The multiplicity of `k` in A354571 is the number of primitive Pythagorean triangles whose even + leg is `k`: `wE k = #legTriangles k` if `k` is even and satisfies `CondE k`, else `0`. Here + `CondE k` says that every odd prime factor `p` of `k` (`p ∈ k.primeFactors`, `Odd p`) satisfies + `p % 4 = 3`, and some prime factor of `k` is odd. Likewise the multiplicity of `k` in A354570 is + `wO k = #legTriangles k` if `k` is odd and satisfies `CondO k` (every prime factor of `k` is + `≡ 3 (mod 4)`), else `0`. +* For a weight `w`, `numLE w k = ∑_{j ≤ k} w j` is the number of terms `≤ k` (with + multiplicity) of the ordered list in which each `k` appears `w k` times, and + `nthTerm w n = sInf {k | n ≤ numLE w k}` is its `n`-th term (offset `1`). The theorems + `a_spec` / `a354570_spec` show that, for every `n`, this infimum is attained: `a n` is the + least `k` with at least `n` terms `≤ k` (this uses `exists_le_numLE_wE` / `..._wO`, i.e. both + lists are infinite). So `a n` = A354571(n) and `a354570 n` = A354570(n) for `n ≥ 1` + (`a 0 = a354570 0 = 0` are junk values that do not affect the limits). +* `a_data` checks all 58 listed terms of A354571 and `a354570_data` all 60 listed terms of + A354570 (kernel-checked, via `nthTerm_eq_getElem_expand`, which identifies `nthTerm w (i + 1)` + with the `i`-th entry of the explicitly expanded list). +* *The conjecture* is the conjunction of `a(n)/n → π` and `A354570(n)/n → π` as `n → ∞`, with the + quotients taken in `ℝ`. +-/ + +namespace Math0.Statements.A354571 + +/-! ### Primitive Pythagorean triangles with a given leg -/ + +/-- `(x, y, z)` is a primitive Pythagorean triangle: positive legs `x, y`, hypotenuse `z`, +`x² + y² = z²`, and `gcd(x, y, z) = 1`. -/ +def IsPPT (x y z : ℕ) : Prop := + 0 < x ∧ 0 < y ∧ x ^ 2 + y ^ 2 = z ^ 2 ∧ Nat.gcd (Nat.gcd x y) z = 1 + +instance (x y z : ℕ) : Decidable (IsPPT x y z) := + inferInstanceAs (Decidable (0 < x ∧ 0 < y ∧ x ^ 2 + y ^ 2 = z ^ 2 ∧ + Nat.gcd (Nat.gcd x y) z = 1)) + +/-- The candidate `(b, c)` with `c - b = d` for a triangle with leg `k`. -/ +def cand (k d : ℕ) : ℕ × ℕ := ((k ^ 2 / d - d) / 2, (k ^ 2 / d - d) / 2 + d) + +/-- The primitive Pythagorean triangles having `k` as a leg, as pairs `(other leg, hypotenuse)` +(see `mem_legTriangles`). -/ +def legTriangles (k : ℕ) : Finset (ℕ × ℕ) := + ((Finset.range k).filter (fun d => IsPPT (cand k d).1 k (cand k d).2)).image (cand k) + +/-- `legTriangles k` is exactly the set of `(b, c)` with `(b, k, c)` a primitive Pythagorean +triangle. -/ +theorem mem_legTriangles {k b c : ℕ} : (b, c) ∈ legTriangles k ↔ IsPPT b k c := by + constructor + · intro h + obtain ⟨d, hd, hdc⟩ := Finset.mem_image.mp h + have hd' := (Finset.mem_filter.mp hd).2 + rw [hdc] at hd' + exact hd' + · intro h + obtain ⟨hb, hk, hsq, hg⟩ := h + have hbc : b < c := by + by_contra hcon + have : c ^ 2 ≤ b ^ 2 := Nat.pow_le_pow_left (by omega) 2 + have : 0 < k ^ 2 := by positivity + omega + obtain ⟨d, rfl⟩ : ∃ d, c = b + d := ⟨c - b, by omega⟩ + have hk2 : k ^ 2 = d * (2 * b + d) := by nlinarith + have hd0 : 0 < d := by omega + have hdiv : k ^ 2 / d = 2 * b + d := by + rw [hk2, Nat.mul_div_cancel_left _ hd0] + have hcand : cand k d = (b, b + d) := by + simp only [cand, hdiv, Prod.mk.injEq] + omega + have hdk : d < k := by + have : d ^ 2 < k ^ 2 := by rw [hk2]; nlinarith + exact lt_of_pow_lt_pow_left₀ 2 (Nat.zero_le _) this + refine Finset.mem_image.mpr ⟨d, Finset.mem_filter.mpr ⟨Finset.mem_range.mpr hdk, ?_⟩, hcand⟩ + rw [hcand] + exact ⟨hb, hk, hsq, hg⟩ + +/-! ### The two sequences -/ + +/-- All odd prime factors of `k` are `≡ 3 (mod 4)`, and at least one prime factor is odd. -/ +def CondE (k : ℕ) : Prop := + (∀ p ∈ k.primeFactors, Odd p → p % 4 = 3) ∧ ∃ p ∈ k.primeFactors, Odd p + +instance : DecidablePred CondE := fun k => + inferInstanceAs (Decidable ((∀ p ∈ k.primeFactors, Odd p → p % 4 = 3) ∧ + ∃ p ∈ k.primeFactors, Odd p)) + +/-- All prime factors of `k` are `≡ 3 (mod 4)`. -/ +def CondO (k : ℕ) : Prop := ∀ p ∈ k.primeFactors, p % 4 = 3 + +instance : DecidablePred CondO := fun k => + inferInstanceAs (Decidable (∀ p ∈ k.primeFactors, p % 4 = 3)) + +/-- Multiplicity of `k` in A354571: the number of primitive Pythagorean triangles whose even leg +is `k`, if `k` satisfies `CondE`; `0` otherwise. -/ +def wE (k : ℕ) : ℕ := if Even k ∧ CondE k then (legTriangles k).card else 0 + +/-- Multiplicity of `k` in A354570: the number of primitive Pythagorean triangles whose odd leg +is `k`, if `k` satisfies `CondO`; `0` otherwise. -/ +def wO (k : ℕ) : ℕ := if Odd k ∧ CondO k then (legTriangles k).card else 0 + +/-- The number of terms `≤ k` of the ordered list in which each `j` occurs `w j` times. -/ +def numLE (w : ℕ → ℕ) (k : ℕ) : ℕ := ∑ j ∈ Finset.range (k + 1), w j + +/-- The `n`-th term (offset `1`) of the ordered list in which each `j` occurs `w j` times: the +least `k` such that at least `n` terms are `≤ k`. -/ +noncomputable def nthTerm (w : ℕ → ℕ) (n : ℕ) : ℕ := sInf {k | n ≤ numLE w k} + +/-- A354571: ordered even leg lengths `k` (listed with multiplicity) of primitive Pythagorean +triangles such that all odd prime factors of `k` are `≡ 3 (mod 4)` and at least one prime factor +is odd (offset `1`). -/ +noncomputable def a (n : ℕ) : ℕ := nthTerm wE n + +/-- A354570: ordered odd leg lengths `k` (listed with multiplicity) of primitive Pythagorean +triangles such that all prime factors of `k` are `≡ 3 (mod 4)` (offset `1`). -/ +noncomputable def a354570 (n : ℕ) : ℕ := nthTerm wO n + +/-! ### `nthTerm` is the `n`-th term -/ + +theorem numLE_mono (w : ℕ → ℕ) {j k : ℕ} (h : j ≤ k) : numLE w j ≤ numLE w k := + Finset.sum_le_sum_of_subset (Finset.range_subset_range.mpr (by omega)) + +theorem numLE_add_le (w : ℕ → ℕ) {j k : ℕ} (h : j < k) : numLE w j + w k ≤ numLE w k := by + unfold numLE + have hk : k ∉ Finset.range (j + 1) := by simp; omega + calc ∑ x ∈ Finset.range (j + 1), w x + w k + = ∑ x ∈ insert k (Finset.range (j + 1)), w x := by rw [Finset.sum_insert hk, add_comm] + _ ≤ ∑ x ∈ Finset.range (k + 1), w x := Finset.sum_le_sum_of_subset (by + intro x hx + simp only [Finset.mem_insert, Finset.mem_range] at hx ⊢ + omega) + +/-- If the weight `w` is positive at arbitrarily large arguments, every `n` is reached. -/ +theorem exists_le_numLE (w : ℕ → ℕ) (hw : ∀ K, ∃ k, K < k ∧ 1 ≤ w k) (n : ℕ) : + ∃ k, n ≤ numLE w k := by + induction n with + | zero => exact ⟨0, Nat.zero_le _⟩ + | succ n ih => + obtain ⟨k, hk⟩ := ih + obtain ⟨k', hkk', hw'⟩ := hw k + exact ⟨k', by have := numLE_add_le w hkk'; omega⟩ + +/-- When the infimum is attained, `nthTerm w n` is the least `k` with `n ≤ numLE w k`. -/ +theorem nthTerm_spec (w : ℕ → ℕ) {n : ℕ} (h : ∃ k, n ≤ numLE w k) : + n ≤ numLE w (nthTerm w n) ∧ ∀ j < nthTerm w n, numLE w j < n := + ⟨Nat.sInf_mem h, fun _ hj => not_le.mp + (Nat.notMem_of_lt_sInf (s := {k | n ≤ numLE w k}) hj)⟩ + +theorem nthTerm_eq {w : ℕ → ℕ} {n K : ℕ} (h1 : n ≤ numLE w K) (h2 : ∀ j < K, numLE w j < n) : + nthTerm w n = K := + le_antisymm (Nat.sInf_le h1) + (le_csInf ⟨K, h1⟩ fun j hj => not_lt.mp fun hlt => (Nat.lt_irrefl _) ((h2 j hlt).trans_le hj)) + +/-- The ordered list of all terms `< K`, each `k` repeated `w k` times. -/ +def expand (w : ℕ → ℕ) (K : ℕ) : List ℕ := (List.range K).flatMap (fun k => List.replicate (w k) k) + +theorem expand_succ (w : ℕ → ℕ) (K : ℕ) : + expand w (K + 1) = expand w K ++ List.replicate (w K) K := by + simp [expand, List.range_succ, List.flatMap_append] + +theorem length_expand (w : ℕ → ℕ) (K : ℕ) : + (expand w K).length = ∑ j ∈ Finset.range K, w j := by + induction K with + | zero => simp [expand] + | succ K ih => rw [expand_succ, List.length_append, ih, List.length_replicate, + Finset.sum_range_succ] + +/-- The `i`-th entry (from `0`) of the expanded list is the `(i + 1)`-th term. -/ +theorem nthTerm_eq_getElem_expand (w : ℕ → ℕ) (K : ℕ) (i : ℕ) (hi : i < (expand w K).length) : + nthTerm w (i + 1) = (expand w K)[i] := by + induction K generalizing i with + | zero => simp [expand] at hi + | succ K ih => + simp only [expand_succ] at hi ⊢ + by_cases hlt : i < (expand w K).length + · rw [List.getElem_append_left hlt] + exact ih i hlt + · rw [List.getElem_append_right (by omega), List.getElem_replicate] + rw [List.length_append, List.length_replicate] at hi + have hlen := length_expand w K + apply nthTerm_eq + · show i + 1 ≤ ∑ j ∈ Finset.range (K + 1), w j + rw [Finset.sum_range_succ] + omega + · intro j hj + have : numLE w j ≤ ∑ j ∈ Finset.range K, w j := + Finset.sum_le_sum_of_subset (Finset.range_subset_range.mpr (by omega)) + omega + +/-- Reading off the first `L` terms from the expanded list. -/ +theorem map_nthTerm_eq (w : ℕ → ℕ) (K L : ℕ) (l : List ℕ) + (h : (expand w K).take L = l ∧ L ≤ (expand w K).length) : + (List.range L).map (fun i => nthTerm w (i + 1)) = l := by + obtain ⟨h1, h2⟩ := h + subst h1 + apply List.ext_getElem + · simp [h2] + · intro i hi _ + simp only [List.getElem_map, List.getElem_range, List.getElem_take] + simp only [List.length_map, List.length_range] at hi + exact nthTerm_eq_getElem_expand w K i (by omega) + +/-! ### Both lists are infinite, so `a n` and `a354570 n` are genuinely the `n`-th terms -/ + +theorem wE_pos (m : ℕ) : 1 ≤ wE (4 * 3 ^ (m + 1)) := by + set u := 2 * 3 ^ (m + 1) with hu + have hu6 : 6 ≤ u := by + have : 3 ≤ 3 ^ (m + 1) := Nat.le_self_pow (by omega) 3 + omega + have hk : 4 * 3 ^ (m + 1) = 2 * u := by omega + have hcond : Even (4 * 3 ^ (m + 1)) ∧ CondE (4 * 3 ^ (m + 1)) := by + refine ⟨⟨2 * 3 ^ (m + 1), by ring⟩, ?_⟩ + have hpf : (4 * 3 ^ (m + 1)).primeFactors = {2, 3} := by + rw [Nat.primeFactors_mul (by norm_num) (by positivity), + Nat.primeFactors_prime_pow (by omega) Nat.prime_three, + show (4 : ℕ) = 2 ^ 2 by norm_num, Nat.primeFactors_prime_pow (by omega) Nat.prime_two] + rfl + rw [CondE, hpf] + decide + -- the triangle `(u² - 1, 2u, u² + 1)` + obtain ⟨v, hv⟩ : ∃ v, u ^ 2 = v + 1 := ⟨u ^ 2 - 1, by have : 1 ≤ u ^ 2 := (by nlinarith); omega⟩ + have hv4 : 2 ∣ u := ⟨3 ^ (m + 1), hu⟩ + have hvodd : v % 2 = 1 := by + obtain ⟨t, ht⟩ := hv4 + have : u ^ 2 = 4 * t ^ 2 := by rw [ht]; ring + omega + have hppt : IsPPT v (4 * 3 ^ (m + 1)) (v + 2) := by + refine ⟨by nlinarith, by positivity, ?_, ?_⟩ + · rw [hk]; nlinarith + · have h1 : Nat.gcd (Nat.gcd v (4 * 3 ^ (m + 1))) (v + 2) ∣ 2 := by + have ha : Nat.gcd (Nat.gcd v (4 * 3 ^ (m + 1))) (v + 2) ∣ v := + (Nat.gcd_dvd_left _ _).trans (Nat.gcd_dvd_left _ _) + have hb : Nat.gcd (Nat.gcd v (4 * 3 ^ (m + 1))) (v + 2) ∣ v + 2 := Nat.gcd_dvd_right _ _ + exact (Nat.dvd_add_right ha).mp hb + have h2 : Nat.gcd (Nat.gcd v (4 * 3 ^ (m + 1))) (v + 2) ∣ v := + (Nat.gcd_dvd_left _ _).trans (Nat.gcd_dvd_left _ _) + rcases (Nat.dvd_prime Nat.prime_two).mp h1 with h | h + · exact h + · rw [h] at h2; omega + have hmem : (v, v + 2) ∈ legTriangles (4 * 3 ^ (m + 1)) := mem_legTriangles.mpr hppt + rw [wE, if_pos hcond] + exact Finset.card_pos.mpr ⟨_, hmem⟩ + +theorem wO_pos (m : ℕ) : 1 ≤ wO (3 ^ (m + 1)) := by + have hodd : Odd (3 ^ (m + 1)) := Odd.pow (by decide) + have hcond : Odd (3 ^ (m + 1)) ∧ CondO (3 ^ (m + 1)) := by + refine ⟨hodd, ?_⟩ + rw [CondO, Nat.primeFactors_prime_pow (by omega) Nat.prime_three] + decide + -- the triangle `(3^(m+1), v, v + 1)` with `3^(2(m+1)) = 2v + 1` + obtain ⟨v, hv⟩ : ∃ v, (3 ^ (m + 1)) ^ 2 = 2 * v + 1 := (hodd.pow (n := 2)) + have h9 : 9 ≤ (3 ^ (m + 1)) ^ 2 := by + have : 3 ≤ 3 ^ (m + 1) := Nat.le_self_pow (by omega) 3 + nlinarith + have hppt : IsPPT v (3 ^ (m + 1)) (v + 1) := by + refine ⟨by omega, by positivity, by nlinarith, ?_⟩ + have ha : Nat.gcd (Nat.gcd v (3 ^ (m + 1))) (v + 1) ∣ v := + (Nat.gcd_dvd_left _ _).trans (Nat.gcd_dvd_left _ _) + have hb : Nat.gcd (Nat.gcd v (3 ^ (m + 1))) (v + 1) ∣ v + 1 := Nat.gcd_dvd_right _ _ + exact Nat.dvd_one.mp ((Nat.dvd_add_right ha).mp hb) + have hmem : (v, v + 1) ∈ legTriangles (3 ^ (m + 1)) := mem_legTriangles.mpr hppt + rw [wO, if_pos hcond] + exact Finset.card_pos.mpr ⟨_, hmem⟩ + +theorem exists_le_numLE_wE (n : ℕ) : ∃ k, n ≤ numLE wE k := + exists_le_numLE wE (fun K => ⟨4 * 3 ^ (K + 1), by + have := Nat.lt_pow_self (n := K + 1) (show 1 < 3 by norm_num); omega, wE_pos K⟩) n + +theorem exists_le_numLE_wO (n : ℕ) : ∃ k, n ≤ numLE wO k := + exists_le_numLE wO (fun K => ⟨3 ^ (K + 1), by + have := Nat.lt_pow_self (n := K + 1) (show 1 < 3 by norm_num); omega, wO_pos K⟩) n + +/-- `a n` is the least `k` such that at least `n` terms of A354571 (with multiplicity) are +`≤ k`, i.e. it is the `n`-th term of A354571. -/ +theorem a_spec (n : ℕ) : n ≤ numLE wE (a n) ∧ ∀ j < a n, numLE wE j < n := + nthTerm_spec wE (exists_le_numLE_wE n) + +/-- `a354570 n` is the least `k` such that at least `n` terms of A354570 (with multiplicity) are +`≤ k`, i.e. it is the `n`-th term of A354570. -/ +theorem a354570_spec (n : ℕ) : + n ≤ numLE wO (a354570 n) ∧ ∀ j < a354570 n, numLE wO j < n := + nthTerm_spec wO (exists_le_numLE_wO n) + +/-! ### Data -/ + +/-- The definition reproduces all 58 terms of A354571 listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 58).map (fun i => a (i + 1)) = + [12, 12, 24, 24, 28, 28, 36, 36, 44, 44, 48, 48, 56, 56, 72, 72, 76, 76, 84, 84, 84, 84, 88, + 88, 92, 92, 96, 96, 108, 108, 112, 112, 124, 124, 132, 132, 132, 132, 144, 144, 152, 152, + 168, 168, 168, 168, 172, 172, 176, 176, 184, 184, 188, 188, 192, 192, 196, 196] := + map_nthTerm_eq wE 197 58 _ (by decide +kernel) + +/-- The definition reproduces all 60 terms of A354570 listed in OEIS (kernel-checked). -/ +theorem a354570_data : (List.range 60).map (fun i => a354570 (i + 1)) = + [3, 7, 9, 11, 19, 21, 21, 23, 27, 31, 33, 33, 43, 47, 49, 57, 57, 59, 63, 63, 67, 69, 69, 71, + 77, 77, 79, 81, 83, 93, 93, 99, 99, 103, 107, 121, 127, 129, 129, 131, 133, 133, 139, 141, + 141, 147, 147, 151, 161, 161, 163, 167, 171, 171, 177, 177, 179, 189, 189, 191] := + map_nthTerm_eq wO 192 60 _ (by decide +kernel) + +/-! ### The conjecture -/ + +/-- Conjecture (Selle, A354571 and A354570): `a(n)/n → π` and `A354570(n)/n → π` as `n → ∞`. -/ +def statement : Prop := + Filter.Tendsto (fun n : ℕ => (a n : ℝ) / n) Filter.atTop (nhds Real.pi) ∧ + Filter.Tendsto (fun n : ℕ => (a354570 n : ℝ) / n) Filter.atTop (nhds Real.pi) + +end Math0.Statements.A354571 diff --git a/lean/Math0/Statements/OEIS/A355076.lean b/lean/Math0/Statements/OEIS/A355076.lean new file mode 100644 index 0000000..072d613 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A355076.lean @@ -0,0 +1,120 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A355076: denominators of the partial sums of `fusc(k)/fusc(k+1)` + +Source: https://oeis.org/A355076, _Rémy Sigrist_, Jun 18 2022 (FORMULA section). Verbatim: +> Conjecture: a(n) = 1 for n of the form 2*4^k - 1 or 2*4^k - 2 for some k >= 0. + +The entry's definition (offset `0`): "a(n) is the denominator of Sum_{k = 0..n} fusc(k)/fusc(k+1) +(where fusc is Stern's diatomic series A002487)." A002487 (offset `0`) is "a(0) = 0, a(1) = 1; +for n > 0: a(2*n) = a(n), a(2*n+1) = a(n) + a(n+1)." + +## Encoding + +* `fusc` is computed by the defining recursion of A002487 with a fuel argument (`fuscAux`), so + that the kernel can evaluate it. With fuel `n + 1` the recursion is never cut off: every + recursive call is on a strictly smaller argument (`n / 2 < n` and `n / 2 + 1 < n` for + `n ≥ 2`). The theorems `fusc_zero`, `fusc_one`, `fusc_even`, `fusc_odd` prove that `fusc` + satisfies exactly the defining equations of A002487 (the last two for every `n`, which + includes the entry's range `n > 0`), and these equations determine the sequence. + `fusc_data` checks the 92 terms of A002487 listed in OEIS. +* `a n` is the denominator (`Rat.den`, the denominator of the reduced fraction, always `≥ 1`) of + the rational number `∑_{k=0}^{n} fusc(k)/fusc(k+1)`, computed exactly in `ℚ`. The divisors + `fusc(k+1)` are all nonzero (`fusc m > 0` for `m ≥ 1`), so Lean's convention `x / 0 = 0` plays + no role. `a_data` checks all 53 listed terms `a 0, …, a 52`. +* The conjecture is stated literally: for every `n` such that `n = 2*4^k - 1` or + `n = 2*4^k - 2` for some `k ≥ 0`, `a n = 1`. Since `2*4^k ≥ 2`, the natural-number + subtractions are exact (`k = 0` gives `n = 1` and `n = 0`). +-/ + +namespace Math0.Statements.A355076 + +/-- The defining recursion of A002487 run with `fuel` steps (it returns `0` when the fuel is +exhausted, which never happens for `fuel > n`; see `fuscAux_eq_fuscAux`). -/ +def fuscAux : ℕ → ℕ → ℕ + | 0, _ => 0 + | fuel + 1, n => + if n ≤ 1 then n + else if n % 2 = 0 then fuscAux fuel (n / 2) + else fuscAux fuel (n / 2) + fuscAux fuel (n / 2 + 1) + +/-- Stern's diatomic series A002487: `fusc 0 = 0`, `fusc 1 = 1`, `fusc (2n) = fusc n`, +`fusc (2n+1) = fusc n + fusc (n+1)`. -/ +def fusc (n : ℕ) : ℕ := fuscAux (n + 1) n + +/-- The fueled recursion does not depend on the fuel once the fuel exceeds the argument. -/ +theorem fuscAux_eq_fuscAux : ∀ (f g n : ℕ), n < f → n < g → fuscAux f n = fuscAux g n := by + intro f + induction f with + | zero => intro g n hf; omega + | succ f ih => + intro g n hf hg + cases g with + | zero => omega + | succ g => + simp only [fuscAux] + split_ifs with h1 h2 + · rfl + · exact ih g (n / 2) (by omega) (by omega) + · rw [ih g (n / 2) (by omega) (by omega), ih g (n / 2 + 1) (by omega) (by omega)] + +theorem fuscAux_succ (fuel n : ℕ) : fuscAux (fuel + 1) n = + if n ≤ 1 then n + else if n % 2 = 0 then fuscAux fuel (n / 2) + else fuscAux fuel (n / 2) + fuscAux fuel (n / 2 + 1) := rfl + +theorem fuscAux_eq_fusc (f n : ℕ) (h : n < f) : fuscAux f n = fusc n := + fuscAux_eq_fuscAux f (n + 1) n h (by omega) + +theorem fusc_zero : fusc 0 = 0 := by decide +kernel + +theorem fusc_one : fusc 1 = 1 := by decide +kernel + +/-- `fusc (2n) = fusc n` for all `n`. -/ +theorem fusc_even (n : ℕ) : fusc (2 * n) = fusc n := by + rcases Nat.eq_zero_or_pos n with rfl | hn + · rfl + · show fuscAux (2 * n + 1) (2 * n) = fusc n + rw [fuscAux_succ] + rw [if_neg (by omega), if_pos (by omega), show 2 * n / 2 = n by omega] + exact fuscAux_eq_fusc _ _ (by omega) + +/-- `fusc (2n+1) = fusc n + fusc (n+1)` for all `n`. -/ +theorem fusc_odd (n : ℕ) : fusc (2 * n + 1) = fusc n + fusc (n + 1) := by + rcases Nat.eq_zero_or_pos n with rfl | hn + · rfl + · show fuscAux (2 * n + 1 + 1) (2 * n + 1) = fusc n + fusc (n + 1) + rw [fuscAux_succ] + rw [if_neg (by omega), if_neg (by omega), show (2 * n + 1) / 2 = n by omega] + rw [fuscAux_eq_fusc _ _ (by omega), fuscAux_eq_fusc _ _ (by omega)] + +/-- `fusc` reproduces the 92 terms of A002487 listed in OEIS (kernel-checked). -/ +theorem fusc_data : (List.range 92).map fusc = + [0, 1, 1, 2, 1, 3, 2, 3, 1, 4, 3, 5, 2, 5, 3, 4, 1, 5, 4, 7, 3, 8, 5, 7, 2, 7, 5, 8, 3, 7, + 4, 5, 1, 6, 5, 9, 4, 11, 7, 10, 3, 11, 8, 13, 5, 12, 7, 9, 2, 9, 7, 12, 5, 13, 8, 11, 3, + 10, 7, 11, 4, 9, 5, 6, 1, 7, 6, 11, 5, 14, 9, 13, 4, 15, 11, 18, 7, 17, 10, 13, 3, 14, 11, + 19, 8, 21, 13, 18, 5, 17, 12, 19] := by + decide +kernel + +/-- A355076: `a(n)` is the denominator of `∑_{k=0}^{n} fusc(k)/fusc(k+1)` (a rational number, +in lowest terms), where `fusc` is Stern's diatomic series A002487. -/ +def a (n : ℕ) : ℕ := + (∑ k ∈ Finset.range (n + 1), ((fusc k : ℚ) / (fusc (k + 1) : ℚ))).den + +/-- The definition reproduces all 53 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 53).map a = + [1, 1, 2, 2, 6, 3, 1, 1, 4, 12, 60, 60, 12, 4, 2, 2, 10, 20, 140, 420, 840, 840, 840, 840, + 840, 840, 420, 140, 20, 5, 1, 1, 6, 30, 90, 180, 1980, 13860, 13860, 13860, 13860, 27720, + 360360, 72072, 72072, 72072, 8008, 8008, 72072, 72072, 72072, 360360, 27720] := by + decide +kernel + +/-- Conjecture (Rémy Sigrist, 2022): `a(n) = 1` (i.e. `∑_{k=0}^{n} fusc(k)/fusc(k+1)` is an +integer) for every `n` of the form `2*4^k - 1` or `2*4^k - 2` with `k ≥ 0`. -/ +def statement : Prop := + ∀ n : ℕ, (∃ k : ℕ, n = 2 * 4 ^ k - 1 ∨ n = 2 * 4 ^ k - 2) → a n = 1 + +end Math0.Statements.A355076 diff --git a/lean/Math0/Statements/OEIS/A355339.lean b/lean/Math0/Statements/OEIS/A355339.lean new file mode 100644 index 0000000..f0fefdc --- /dev/null +++ b/lean/Math0/Statements/OEIS/A355339.lean @@ -0,0 +1,228 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A355339: central even terms in the knight-move triangle A355320 + +Source: https://oeis.org/A355339, _Rémy Sigrist_, Jun 29 2022 (FORMULA section). Verbatim: +> Conjecture: a(n) = 1 iff n > 0 and n belongs to A000918. + +The entry's definition (offset `0`): "a(n) is the number of central even terms in the n-th row +of triangle A355320; a(0) = 0." A355320 is the "Irregular triangle T(n, k), n >= 0, +-2*n <= k <= 2*n, read by rows; T(0, 0) = 1; for n > 0, T(n, k) is the sum of all terms in +previous rows at one knight's move away." Its FORMULA section makes the knight moves explicit: +"T(n, k) = T'(n-1, k-2) + T'(n-1, k+2) + T'(n-2, k-1) + T'(n-2, k+1) for n > 0 (where T' +extends T with 0's outside its domain of definition)." A000918 is "a(n) = 2^n - 2" (offset `0`, +so its terms are `-1, 0, 2, 6, 14, …`). + +## Encoding + +* Row `n` of A355320 is stored as the list `row n` of its `4n+1` entries `T(n,-2n), …, T(n,2n)` + (list index `k + 2n`). Rows are built two at a time (`step`, iterated from the pair + (row `-1` = `[]`, row `0` = `[1]`)); `step` is the knight-move recurrence written as a sum of + shifted lists: entry `k` of row `n+1` collects `T(n, k±2)` (list shifts `0` and `4`) and + `T(n-1, k±1)` (list shifts `3` and `5`). This is also the polynomial recurrence + `R(n+1) = (1+X^4) R(n) + (X^3+X^5) R(n-1)` of the entry's PARI program. +* `T n k` (`k : ℤ`) reads entry `k` of row `n` and is `0` for `|k| > 2n`, i.e. it is the + zero extension `T'` of the entry. The theorems `T_zero_zero`, `T_eq_zero`, `T_one`, + `T_add_two` prove that `T` satisfies exactly the defining equations above (the recurrence even + holds for every `k ∈ ℤ`), and these equations determine `T` by induction on `n`. + `T_data` checks the 91 listed terms of A355320 (rows `0..6`). +* "The number of central even terms" is read as the size of the maximal block of consecutive + even entries of row `n` that contains the central position `k = 0` (it is `0` when `T(n,0)` + is odd). With `right` the number of `k ≥ 0` such that `T(n,0), …, T(n,k)` are all even, and + `left` the same for `T(n,0), T(n,-1), …, T(n,-k)`, this size is `left + right - 1` when + `T(n,0)` is even (`k = 0` is counted on both sides) and `0` otherwise. The entry's + example and its PARI program (`max(0, 2*valuation(r >> (2*n), 2) - 1)`, i.e. `2*right - 1` + for symmetric rows) agree with this reading. `a 0 = 0` is imposed literally, as in the + entry (it also follows from `T(0,0) = 1` being odd). `a_eq` restates `a` in terms of `T`. + `a_data` checks all 77 listed terms `a 0, …, a 76`. +* The conjecture: for every `n ≥ 0` (offset `0`), `a(n) = 1` iff `n > 0` and `n` is a term + `2^m - 2` (`m ≥ 0`) of A000918. Membership in A000918 is stated in `ℤ`, literally as + `(n : ℤ) = 2^m - 2`. +-/ + +namespace Math0.Statements.A355339 + +/-- Entrywise sum of two lists of naturals, the shorter one padded with zeros. -/ +def addL : List ℕ → List ℕ → List ℕ + | [], l => l + | x :: xs, [] => x :: xs + | x :: xs, y :: ys => (x + y) :: addL xs ys + +/-- From (row `n-1`, row `n`) to (row `n`, row `n+1`): entry `k` of row `n+1` is +`T(n,k+2) + T(n,k-2) + T(n-1,k+1) + T(n-1,k-1)`, written as shifts of the stored lists. -/ +def step (pq : List ℕ × List ℕ) : List ℕ × List ℕ := + (pq.2, addL (addL pq.2 (List.replicate 4 0 ++ pq.2)) + (addL (List.replicate 3 0 ++ pq.1) (List.replicate 5 0 ++ pq.1))) + +/-- `rowPair n = (row (n-1), row n)`, starting from row `-1` (empty, all zeros) and row `0`. -/ +def rowPair (n : ℕ) : List ℕ × List ℕ := step^[n] ([], [1]) + +/-- Row `n` of A355320: the list `T(n,-2n), …, T(n,2n)`. -/ +def row (n : ℕ) : List ℕ := (rowPair n).2 + +/-- Entry `k` of a stored row `r` with index `m` (list position `k + 2m`), `0` outside. -/ +def entry (r : List ℕ) (m : ℕ) (k : ℤ) : ℕ := + if 0 ≤ k + 2 * m then r.getD (k + 2 * m).toNat 0 else 0 + +/-- The triangle A355320, `T(n, k)`, extended by `0` outside `-2n ≤ k ≤ 2n`. -/ +def T (n : ℕ) (k : ℤ) : ℕ := entry (row n) n k + +/-! ### `T` satisfies the defining equations of A355320 -/ + +theorem getD_addL : ∀ (l₁ l₂ : List ℕ) (i : ℕ), + (addL l₁ l₂).getD i 0 = l₁.getD i 0 + l₂.getD i 0 + | [], l, i => by simp [addL] + | x :: xs, [], i => by simp [addL] + | x :: xs, y :: ys, 0 => by simp [addL] + | x :: xs, y :: ys, i + 1 => by + simp only [addL, List.getD_cons_succ]; exact getD_addL xs ys i + +theorem length_addL : ∀ (l₁ l₂ : List ℕ), (addL l₁ l₂).length = max l₁.length l₂.length + | [], l => by simp [addL] + | x :: xs, [] => by simp [addL] + | x :: xs, y :: ys => by simp [addL, length_addL xs ys, Nat.succ_max_succ] + +theorem getD_replicate_append (l : List ℕ) : + ∀ (j i : ℕ), (List.replicate j 0 ++ l).getD i 0 = if i < j then 0 else l.getD (i - j) 0 + | 0, i => by simp + | j + 1, 0 => by simp + | j + 1, i + 1 => by + rw [List.replicate_succ, List.cons_append, List.getD_cons_succ, getD_replicate_append l j i] + simp only [Nat.add_lt_add_iff_right, Nat.add_sub_add_right] + +theorem rowPair_succ (n : ℕ) : rowPair (n + 1) = step (rowPair n) := + Function.iterate_succ_apply' step n ([], [1]) + +theorem rowPair_succ_fst (n : ℕ) : (rowPair (n + 1)).1 = row n := by + rw [rowPair_succ]; rfl + +theorem row_succ (n : ℕ) : row (n + 1) = + addL (addL (row n) (List.replicate 4 0 ++ row n)) + (addL (List.replicate 3 0 ++ (rowPair n).1) (List.replicate 5 0 ++ (rowPair n).1)) := by + unfold row; rw [rowPair_succ]; rfl + +theorem length_rowPair (n : ℕ) : + (rowPair n).2.length = 4 * n + 1 ∧ (rowPair n).1.length ≤ 4 * n := by + induction n with + | zero => simp [rowPair] + | succ n ih => + have h2 := row_succ n + unfold row at h2 + rw [h2, rowPair_succ_fst] + unfold row + simp only [length_addL, List.length_append, List.length_replicate] + omega + +theorem length_row (n : ℕ) : (row n).length = 4 * n + 1 := (length_rowPair n).1 + +theorem entry_of_eq (r : List ℕ) (m : ℕ) (k : ℤ) (i c : ℕ) (h : k + 2 * m = (i : ℤ) - c) : + entry r m k = if i < c then 0 else r.getD (i - c) 0 := by + unfold entry + split_ifs with h1 h2 h2 + · omega + · have h3 : k + 2 * m = ((i - c : ℕ) : ℤ) := by omega + rw [h3, Int.toNat_natCast] + · rfl + · omega + +theorem entry_of_neg (r : List ℕ) (m : ℕ) (k : ℤ) (h : k + 2 * m < 0) : entry r m k = 0 := by + unfold entry; rw [if_neg (by omega)] + +/-- `T(0, 0) = 1`. -/ +theorem T_zero_zero : T 0 0 = 1 := by decide +kernel + +/-- `T(n, k) = 0` outside `-2n ≤ k ≤ 2n` (`T` is the zero extension `T'`). -/ +theorem T_eq_zero (n : ℕ) (k : ℤ) (h : 2 * (n : ℤ) < |k|) : T n k = 0 := by + unfold T entry + split_ifs with h1 + · apply List.getD_eq_default + rw [length_row] + rcases abs_cases k with ⟨hk, -⟩ | ⟨hk, -⟩ <;> omega + · rfl + +/-- The knight-move recurrence for `n = 1` (row `-1` does not exist). -/ +theorem T_one (k : ℤ) : T 1 k = T 0 (k - 2) + T 0 (k + 2) := by + unfold T + rw [row_succ] + have hp : (rowPair 0).1 = [] := rfl + rw [hp] + rcases lt_or_ge (k + 2 * ((0 + 1 : ℕ) : ℤ)) 0 with hk | hk + · rw [entry_of_neg _ _ _ hk, entry_of_neg _ _ _ (by omega), + entry_of_neg _ _ _ (by omega)] + · obtain ⟨i, hi⟩ := Int.eq_ofNat_of_zero_le hk + rw [entry_of_eq _ _ _ i 0 (by omega), entry_of_eq _ _ _ i 4 (by omega), + entry_of_eq _ _ _ i 0 (by omega)] + simp only [Nat.not_lt_zero, if_false, Nat.sub_zero, getD_addL, getD_replicate_append, + List.getD_nil] + split_ifs <;> omega + +/-- The knight-move recurrence for `n ≥ 2`: +`T(n+2, k) = T(n+1, k-2) + T(n+1, k+2) + T(n, k-1) + T(n, k+1)`, for every `k ∈ ℤ`. -/ +theorem T_add_two (n : ℕ) (k : ℤ) : + T (n + 2) k = T (n + 1) (k - 2) + T (n + 1) (k + 2) + T n (k - 1) + T n (k + 1) := by + unfold T + rw [row_succ (n + 1), rowPair_succ_fst] + rcases lt_or_ge (k + 2 * ((n + 1 + 1 : ℕ) : ℤ)) 0 with hk | hk + · rw [entry_of_neg _ _ _ (by omega), entry_of_neg _ _ _ (by omega), + entry_of_neg _ _ _ (by omega), entry_of_neg _ _ _ (by omega), + entry_of_neg _ _ _ (by omega)] + · obtain ⟨i, hi⟩ := Int.eq_ofNat_of_zero_le hk + rw [entry_of_eq _ _ _ i 0 (by omega), entry_of_eq _ _ _ i 4 (by omega), + entry_of_eq _ _ _ i 0 (by omega), entry_of_eq _ _ _ i 5 (by omega), + entry_of_eq _ _ _ i 3 (by omega)] + simp only [Nat.not_lt_zero, if_false, Nat.sub_zero, getD_addL, getD_replicate_append] + split_ifs <;> omega + +/-- `T` reproduces the 91 terms of A355320 listed in OEIS (rows `0..6`; kernel-checked). -/ +theorem T_data : + (List.range 7).flatMap (fun n => (List.range (4 * n + 1)).map fun i => T n (i - 2 * n)) = + [1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 2, 1, 0, 0, 1, 1, 0, 0, 2, 3, 2, 0, 2, 3, 2, 0, 0, 1, 1, 0, + 0, 3, 4, 3, 1, 6, 8, 6, 1, 3, 4, 3, 0, 0, 1, 1, 0, 0, 4, 5, 4, 3, 12, 16, 12, 6, 12, 16, + 12, 3, 4, 5, 4, 0, 0, 1, 1, 0, 0, 5, 6, 5, 6, 20, 27, 21, 18, 33, 44, 33, 18, 21, 27, 20, + 6, 5, 6, 5, 0, 0, 1] := by + decide +kernel + +/-! ### The sequence A355339 -/ + +/-- A355339: `a(n)` is the number of central even terms in row `n` of A355320, i.e. the size of +the maximal block of consecutive even entries `T(n, k)` containing `k = 0` (`0` if `T(n, 0)` is +odd); `a(0) = 0`. Here `right` counts the `k ∈ {0, …, 2n}` with `T(n,0), …, T(n,k)` all even, +`left` counts the `k ∈ {0, …, 2n}` with `T(n,0), T(n,-1), …, T(n,-k)` all even, and the block is +`{-(left-1), …, right-1}`. (The row is bound once as `r`, so that `entry r n k = T n k`; see +`a_eq`.) -/ +def a (n : ℕ) : ℕ := + if n = 0 then 0 else + let r := row n + let right := (((List.range (2 * n + 1)).map fun k : ℕ => entry r n k).takeWhile + fun x => x % 2 == 0).length + let left := (((List.range (2 * n + 1)).map fun k : ℕ => entry r n (-k)).takeWhile + fun x => x % 2 == 0).length + if right = 0 then 0 else left + right - 1 + +/-- `a` written directly in terms of the triangle `T`. -/ +theorem a_eq (n : ℕ) : a n = + if n = 0 then 0 else + let right := (((List.range (2 * n + 1)).map fun k : ℕ => T n k).takeWhile + fun x => x % 2 == 0).length + let left := (((List.range (2 * n + 1)).map fun k : ℕ => T n (-k)).takeWhile + fun x => x % 2 == 0).length + if right = 0 then 0 else left + right - 1 := rfl + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all 77 listed +terms `a 0, …, a 76`. -/ +theorem a_data : (List.range 77).map (fun i => a (i + 0)) = + [0, 3, 1, 3, 3, 7, 1, 3, 5, 3, 5, 11, 3, 11, 1, 3, 5, 7, 7, 3, 5, 7, 9, 19, 7, 3, 5, 19, 3, + 11, 1, 3, 5, 7, 9, 11, 13, 11, 7, 3, 5, 7, 9, 11, 13, 15, 17, 35, 15, 11, 7, 3, 5, 7, 9, + 35, 7, 3, 5, 19, 3, 11, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 23, 19, 15] := by + decide +kernel + +/-- Sigrist's conjecture (A355339, FORMULA section): for every `n ≥ 0`, `a(n) = 1` if and only +if `n > 0` and `n` is a term of A000918, i.e. `n = 2^m - 2` for some `m ≥ 0`. -/ +def statement : Prop := + ∀ n : ℕ, a n = 1 ↔ (0 < n ∧ ∃ m : ℕ, (n : ℤ) = 2 ^ m - 2) + +end Math0.Statements.A355339 diff --git a/lean/Math0/Statements/OEIS/A355360.lean b/lean/Math0/Statements/OEIS/A355360.lean new file mode 100644 index 0000000..c05866b --- /dev/null +++ b/lean/Math0/Statements/OEIS/A355360.lean @@ -0,0 +1,300 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A355360: columns 1 and 2 of the theta-series triangle + +Source: https://oeis.org/A355360, _Paul D. Hanna_, Jul 19 2022 (COMMENTS section of the entry, +by its author). Verbatim: +> Conjectures. +> (C.1) Column 1 equals A000716, the number of partitions into parts of 3 kinds. +> (C.2) Column 2 equals twice A023005, the number of partitions into parts of 6 kinds. + +The entry's name: "G.f. A(x,y) satisfies: x*y*A(x,y) = Sum_{n=-oo..+oo} (-1)^n * +x^(n*(n+1)/2) * A(x,y)^n, with coefficients T(n,k) of x^n*y^k in A(x,y) given as a triangle +read by rows." Keyword `tabl`, offset `0`: rows `n ≥ 0`, columns `0 ≤ k ≤ n`; the DATA section +lists rows `0` to `10` (66 terms). + +## Encoding + +* *The g.f.* `A(x,y) = ∑_{m ≥ 0} a_m(y) x^m` is a power series in `x` whose coefficients + `a_m(y) = ∑_k T(m,k) y^k` are polynomials in `y` with integer coefficients. Write + `F(B) = ∑_{n ∈ ℤ} (-1)^n x^{n(n+1)/2} B^n`; the defining equation is `x y A = F(A)`. + Negative powers require `A` to be invertible, i.e. `a_0` invertible. +* *The solution is unique and is computed order by order* (this is what `coeffs` does): + - order `x^0`: only `n = 0` and `n = -1` have `n(n+1)/2 = 0`, so `0 = 1 - a_0⁻¹`, i.e. + `a_0 = 1`; + - order `x^m`, `m ≥ 1`: the left side gives `y a_{m-1}`. On the right side every term with + `n ≠ -1` has `n(n+1)/2 ≥ 1` or is the constant `1`, so its `x^m`-coefficient involves only + `a_0, …, a_{m-1}`; and `-A⁻¹ = -A_{ q + | a :: p, [] => a :: p + | a :: p, b :: q => (a + b) :: padd p q + +/-- Multiplication of a polynomial by an integer. -/ +def pscale (c : ℤ) (p : Poly) : Poly := p.map (c * ·) + +/-- Product of polynomials. -/ +def pmul : Poly → Poly → Poly + | [], _ => [] + | a :: p, q => padd (pscale a q) (0 :: pmul p q) + +/-- A power series in `x` with coefficients in `ℤ[y]`, truncated: `[b₀, b₁, …]` is +`b₀ + b₁ x + ⋯` (missing coefficients are `0`). -/ +abbrev Ser := List Poly + +/-- The coefficient of `x^i` in `A * B`. -/ +def mulCoeff (A B : Ser) (i : ℕ) : Poly := + (List.range (i + 1)).foldl (fun s j => padd s (pmul (A.getD j []) (B.getD (i - j) []))) [] + +/-- `A * B mod x^L`. -/ +def smul (L : ℕ) (A B : Ser) : Ser := (List.range L).map (mulCoeff A B) + +/-- `A⁻¹ mod x^L`, for a series `A` with constant term `1`: +`b₀ = 1`, `b_i = -∑_{j=1}^{i} a_j b_{i-j}`. -/ +def sinv (L : ℕ) (A : Ser) : Ser := + (List.range L).foldl (fun B i => B ++ [if i = 0 then [1] else + pscale (-1) ((List.range i).foldl + (fun s j => padd s (pmul (A.getD (j + 1) []) (B.getD (i - 1 - j) []))) [])]) [] + +/-- `[x^m] ∑_{n ∈ ℤ} (-1)^n x^{n(n+1)/2} B^n`, for a series `B` with constant term `1`, computed +mod `x^{m+1}` as `∑_{n ≥ 0, n(n+1)/2 ≤ m} (-1)^n [x^{m - n(n+1)/2}] (B^n - B^{-(n+1)})` +(the terms `n` and `-1-n` grouped together). The state of the loop is +`(partial sum, B^n, B^{-(n+1)})`. -/ +def thetaCoeff (B : Ser) (m : ℕ) : Poly := + let L := m + 1 + let Binv := sinv L B + ((List.range L).foldl (fun (st : Poly × Ser × Ser) n => + let t := n * (n + 1) / 2 + if t ≤ m then + (padd st.1 (pscale ((-1) ^ n) + (padd (st.2.1.getD (m - t) []) (pscale (-1) (st.2.2.getD (m - t) [])))), + smul L st.2.1 B, smul L st.2.2 Binv) + else st) ([], [[1]], Binv)).1 + +/-- `coeffs m = [a₀, …, a_m]`, the first coefficients (in `x`) of the unique solution `A(x,y)` of +`x y A = ∑_{n ∈ ℤ} (-1)^n x^{n(n+1)/2} A^n`: `a₀ = 1` and +`a_{m+1} = y a_m - [x^{m+1}] F(a₀ + ⋯ + a_m x^m)`. -/ +def coeffs : ℕ → Ser + | 0 => [[1]] + | m + 1 => + let B := coeffs m + B ++ [padd (0 :: B.getD m []) (pscale (-1) (thetaCoeff B (m + 1)))] + +/-- `T(n,k)`, the coefficient of `x^n y^k` in `A(x,y)`. -/ +def T (n k : ℕ) : ℤ := ((coeffs n).getD n []).getD k 0 + +/-- The definition reproduces all 66 terms of the DATA section (rows `0` to `10`, read by rows; +kernel-checked). -/ +theorem a_data : (List.range 11).flatMap (fun n => (List.range (n + 1)).map (T n)) = + [1, 0, 1, 0, 3, 2, 0, 9, 12, 5, 0, 22, 54, 46, 14, 0, 51, 196, 282, 175, 42, 0, 108, 630, + 1360, 1365, 666, 132, 0, 221, 1836, 5635, 8190, 6321, 2541, 429, 0, 429, 4984, + 20850, 41405, 45326, 28448, 9724, 1430, 0, 810, 12744, 70737, 184527, 270060, 237209, + 125532, 37323, 4862, 0, 1479, 31050, 223652, 745745, 1404102, 1625932, 1193116, 546039, + 143650, 16796] := by + decide +kernel + +/-- Rows `11` and `12`, as displayed in the EXAMPLE section of the entry (kernel-checked). -/ +theorem T_example_rows : (List.range 2).map (fun i => (List.range (i + 12)).map (T (i + 11))) = + [[0, 2640, 72560, 667005, 2784110, 6565030, 9646462, 9242178, 5826171, 2349490, 554268, + 58786], + [0, 4599, 163632, 1892670, 9729720, 28161819, 51126740, 61555824, 50308245, 27806065, + 10023948, 2143428, 208012]] := by + decide +kernel + +/-! ### Partitions into parts of several kinds -/ + +/-- The partition number A000041(m): the number of partitions of `m`. -/ +def p (m : ℕ) : ℕ := Fintype.card (Nat.Partition m) + +/-- The number of partitions of `n` into parts of `j` kinds: `j`-tuples of partitions (the parts +of each kind) of total size `n`, i.e. `∑_{n_1 + ⋯ + n_j = n} p(n_1) ⋯ p(n_j)`. -/ +def partitionsOfKinds (j n : ℕ) : ℕ := + ∑ f ∈ Finset.Nat.antidiagonalTuple j n, ∏ i, p (f i) + +/-- A000716(n): the number of partitions of `n` into parts of 3 kinds. -/ +def A000716 (n : ℕ) : ℕ := partitionsOfKinds 3 n + +/-- A023005(n): the number of partitions of `n` into parts of 6 kinds. -/ +def A023005 (n : ℕ) : ℕ := partitionsOfKinds 6 n + +/-! ### The conjecture -/ + +/-- Hanna's conjectures (C.1) and (C.2): column 1 of the triangle is A000716, +`T(n+1, 1) = A000716(n)` for all `n ≥ 0`, and column 2 is twice A023005, +`T(n+2, 2) = 2 · A023005(n)` for all `n ≥ 0`. -/ +def statement : Prop := + (∀ n : ℕ, T (n + 1) 1 = A000716 n) ∧ (∀ n : ℕ, T (n + 2) 2 = 2 * A023005 n) + +/-! ### Sanity checks of the transcription (not a proof) -/ + +/-- The number of partitions of `n` all of whose parts are `≤ m`. -/ +def B (n m : ℕ) : ℕ := + (Finset.univ.filter (fun π : n.Partition => ∀ i ∈ π.parts, i ≤ m)).card + +/-- A computable count of the partitions of `n` into parts `≤ m` (`j` is the number of parts +equal to `m + 1`); `pb_eq_B` shows `pb n m = B n m`. -/ +def pb : ℕ → ℕ → ℕ + | n, 0 => if n = 0 then 1 else 0 + | n, m + 1 => ∑ j ∈ Finset.range (n / (m + 1) + 1), pb (n - j * (m + 1)) m + +theorem part_le {n : ℕ} (π : n.Partition) {i : ℕ} (hi : i ∈ π.parts) : i ≤ n := + (Multiset.le_sum_of_mem hi).trans_eq π.parts_sum + +theorem B_zero (m : ℕ) : B 0 m = 1 := by + rw [B, Finset.filter_true_of_mem (by simp), Finset.card_univ, Fintype.card_unique] + +theorem B_succ_zero (n : ℕ) : B (n + 1) 0 = 0 := by + rw [B, Finset.card_eq_zero, Finset.filter_eq_empty_iff] + intro π _ h + have h0 : π.parts = 0 := Multiset.eq_zero_of_forall_notMem fun i hi => by + have := π.parts_pos hi; have := h i hi; omega + have := π.parts_sum + rw [h0] at this + simp at this + +theorem B_succ (n m : ℕ) : + B n (m + 1) = B n m + if m + 1 ≤ n then B (n - (m + 1)) (m + 1) else 0 := by + rw [B, ← Finset.card_filter_add_card_filter_not + (fun π : n.Partition => m + 1 ∈ π.parts), add_comm] + congr 1 + · rw [B, Finset.filter_filter] + congr 1 + ext π + simp only [Finset.mem_filter, Finset.mem_univ, true_and] + constructor + · rintro ⟨h, hm⟩ i hi + have := h i hi + have : i ≠ m + 1 := fun e => hm (e ▸ hi) + omega + · intro h + exact ⟨fun i hi => (h i hi).trans (Nat.le_succ m), fun hm => by have := h _ hm; omega⟩ + · split_ifs with hmn + · rw [B] + let e := Nat.Partition.partitionWithPartEquiv (n := n) (a := m + 1) (by omega) hmn + refine Finset.card_bij' (fun π hπ => e ⟨π, (Finset.mem_filter.1 hπ).2⟩) + (fun π _ => (e.symm π).1) ?_ ?_ ?_ ?_ + · intro π hπ + simp only [Finset.mem_filter, Finset.mem_univ, true_and] at hπ ⊢ + intro i hi + rw [Nat.Partition.partitionWithPartEquiv_apply_parts] at hi + exact hπ.1 i (Multiset.mem_of_mem_erase hi) + · intro π _ + simp only [Finset.mem_filter, Finset.mem_univ, true_and] + rw [Nat.Partition.partitionWithPartEquiv_symm_apply_parts] + refine ⟨fun i hi => ?_, Multiset.mem_cons_self _ _⟩ + rcases Multiset.mem_cons.1 hi with rfl | hi + · exact le_rfl + · have h := Finset.mem_filter.1 ‹_› + exact h.2 i hi + · intro π _ + simp only [Equiv.symm_apply_apply] + · intro π _ + simp only [Subtype.coe_eta, Equiv.apply_symm_apply] + · rw [Finset.card_eq_zero, Finset.filter_eq_empty_iff] + intro π _ h + exact hmn (part_le π h) + +theorem pb_zero_right (n : ℕ) : pb n 0 = if n = 0 then 1 else 0 := by + rw [pb] + +theorem pb_succ (n m : ℕ) : + pb n (m + 1) = pb n m + if m + 1 ≤ n then pb (n - (m + 1)) (m + 1) else 0 := by + rw [pb, Finset.sum_range_succ', add_comm] + simp only [zero_mul, Nat.sub_zero] + congr 1 + split_ifs with hmn + · rw [pb, Nat.div_eq_sub_div (by omega) hmn] + refine Finset.sum_congr rfl fun j _ => ?_ + congr 1 + rw [Nat.succ_mul] + omega + · rw [Nat.div_eq_of_lt (by omega)] + simp + +theorem pb_eq_B (n : ℕ) : ∀ m, pb n m = B n m := by + induction n using Nat.strong_induction_on with + | _ n ihn => + intro m + induction m with + | zero => + rcases n with _ | n + · rw [pb_zero_right, B_zero]; rfl + · rw [pb_zero_right, B_succ_zero]; simp + | succ m ihm => + rw [pb_succ, B_succ, ihm] + split_ifs with hmn + · rw [ihn _ (by omega)] + · rfl + +/-- The partition numbers can be computed with `pb`. -/ +theorem p_eq_pb (m : ℕ) : p m = pb m m := by + rw [pb_eq_B, B, Finset.filter_true_of_mem (fun π _ i hi => part_le π hi), Finset.card_univ, p] + +/-- The first 10 listed terms of A000716 (kernel-checked through `p_eq_pb`). -/ +theorem A000716_data : + (List.range 10).map (fun n => A000716 n) = [1, 3, 9, 22, 51, 108, 221, 429, 810, 1479] := by + simp only [A000716, partitionsOfKinds, p_eq_pb] + decide +kernel + +/-- The first 6 listed terms of A023005 (kernel-checked through `p_eq_pb`). -/ +theorem A023005_data : + (List.range 6).map (fun n => A023005 n) = [1, 6, 27, 98, 315, 918] := by + simp only [A023005, partitionsOfKinds, p_eq_pb] + decide +kernel + +/-- Both conjectured identities hold for the first values of `n` (rows `1` to `10` for column 1 +and rows `2` to `7` for column 2). A consistency check of the offsets, not a proof. -/ +theorem statement_check : + (∀ n < 10, T (n + 1) 1 = A000716 n) ∧ (∀ n < 6, T (n + 2) 2 = 2 * A023005 n) := by + simp only [A000716, A023005, partitionsOfKinds, p_eq_pb] + decide +kernel + +end Math0.Statements.A355360 diff --git a/lean/Math0/Statements/OEIS/A356360.lean b/lean/Math0/Statements/OEIS/A356360.lean new file mode 100644 index 0000000..85d015b --- /dev/null +++ b/lean/Math0/Statements/OEIS/A356360.lean @@ -0,0 +1,68 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A356360: denominators of `1/(2-3/(3-4/(...(n-1)-n/(n+1))))` are 1 or prime + +Source: https://oeis.org/A356360, Mohammed Bouras, Oct 15 2022. Verbatim: +> Conjecture: The sequence contains only 1's and the primes. + +The sequence (offset 3) is the "Denominator of the continued fraction +1/(2-3/(3-4/(4-5/(...(n-1)-n/(n+1)))))". For `n = 3` the innermost level `(n-1) - n/(n+1)` +is already the outer one, giving `1/(2 - 3/4) = 4/5`, so `a(3) = 5`; next +`1/(2 - 3/(3 - 4/5)) = 11/7` and `1/(2 - 3/(3 - 4/(4 - 5/6))) = 11/3`, giving `a(4) = 7`, +`a(5) = 3`, as listed. + +## Encoding + +The continued fraction is evaluated in `ℚ` from the inside out: start with `n + 1` and apply +`step k t = k - (k+1)/t` for `k = n-1, n-2, …, 2` (this is `List.foldr step (n + 1)` over +`[2, 3, …, n-1] = List.range' 2 (n - 2)`), then take the reciprocal. `a n` is the denominator +`Rat.den` of the resulting rational number in lowest terms (always positive, and `1` when the +value is an integer, e.g. `a 8 = 1`). + +Lean's `x / 0 = 0` convention plays no role for `n ≥ 3`: no tail of the continued fraction +vanishes. (The numbers `u_k = k(k-2)/(k-1)` satisfy `u_k = k - (k+1)/u_{k+1}`, `u_2 = 0` and +`u_k > 0` for `k ≥ 3`. The innermost value `n + 1` exceeds `u_n`, and `t ↦ k - (k+1)/t` is +increasing for `t > 0`, so by downward induction every tail `t_k` (`2 ≤ k ≤ n-1`) satisfies +`t_k > u_k ≥ 0`. It was also checked by exact arithmetic for `3 ≤ n < 800`.) +The definition reproduces all 82 terms listed in the entry (`a_data`, `n = 3, …, 84`). Values of +`a n` for `n < 3` are outside the sequence and are never used. + +*Reading of the conjecture.* "The sequence contains only 1's and the primes" is read as: every +term `a n` with `n ≥ 3` (the offset) is `1` or a prime. (It does not claim that every prime +occurs.) +-/ + +namespace Math0.Statements.A356360 + +/-- One level of the continued fraction: `step k t = k - (k+1)/t`. -/ +def step (k : ℕ) (t : ℚ) : ℚ := (k : ℚ) - ((k : ℚ) + 1) / t + +/-- The continued fraction `1/(2 - 3/(3 - 4/(4 - 5/(… (n-1) - n/(n+1)))))`, evaluated from the +inside out: `step 2 (step 3 (… (step (n-1) (n+1))))`, then the reciprocal. -/ +def cf (n : ℕ) : ℚ := 1 / (List.range' 2 (n - 2)).foldr step ((n : ℚ) + 1) + +/-- A356360 (offset 3): the denominator of the continued fraction +`1/(2-3/(3-4/(4-5/(...(n-1)-n/(n+1)))))`, in lowest terms. -/ +def a (n : ℕ) : ℕ := (cf n).den + +/-- The first values: `cf 3 = 1/(2 - 3/4) = 4/5`, `cf 4 = 11/7`, `cf 5 = 11/3`. -/ +example : cf 3 = 4 / 5 ∧ cf 4 = 11 / 7 ∧ cf 5 = 11 / 3 := by decide +kernel + +/-- The definition reproduces all 82 terms listed in OEIS, `a 3, …, a 84` (kernel-checked). -/ +theorem a_data : (List.range 82).map (fun i => a (i + 3)) = + [5, 7, 3, 11, 13, 1, 17, 19, 1, 23, 1, 1, 29, 31, 1, 1, 37, 1, 41, 43, 1, 47, 1, 1, 53, 1, + 1, 59, 61, 1, 1, 67, 1, 71, 73, 1, 1, 79, 1, 83, 1, 1, 89, 1, 1, 1, 97, 1, 101, 103, 1, + 107, 109, 1, 113, 1, 1, 1, 1, 1, 1, 127, 1, 131, 1, 1, 137, 139, 1, 1, 1, 1, 149, 151, 1, + 1, 157, 1, 1, 163, 1, 167] := by + decide +kernel + +/-- Conjecture (Mohammed Bouras, 2022): the sequence contains only 1's and the primes, i.e. +every term `a n` (`n ≥ 3`) is either `1` or a prime. -/ +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → a n = 1 ∨ (a n).Prime + +end Math0.Statements.A356360 diff --git a/lean/Math0/Statements/OEIS/A357216.lean b/lean/Math0/Statements/OEIS/A357216.lean new file mode 100644 index 0000000..ece75b1 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A357216.lean @@ -0,0 +1,293 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A357216: regions in a regular n-gon cut by k internal n-gons + +Source: https://oeis.org/A357216, _Scott R. Shannon_, Sep 18 2022. Verbatim (COMMENTS and +FORMULA sections): +> Conjecture: the only n-gons that contain non-simple intersections are the 3-gon (triangle), +> 4-gon (square), and 6-gon (hexagon). + +> Conjectured formula for all columns for n >= 7: T(n,k) = n*k^2 + 1. + +> Conjectured formula for all rows except for n = 3, 4, 6: T(n,k) = n*k^2 + 1. + +The entry's definition: "Table read by antidiagonals: T(n,k) (n >= 3, k >= 0) is the number of +regions in an n-gon when k internal n-gons are drawn between the n*k points that divide each side +into k+1 equal parts." (offset 3). + +## Encoding + +*Geometry (used by `statement`).* The plane is `ℂ`. The regular `n`-gon has vertices +`vertex n j = exp (2πij/n)`, `j = 0, …, n-1` (`vertex n n = vertex n 0`); side `j` runs from +`vertex n j` to `vertex n (j+1)`. Its `m`-th division point (`m = 1, …, k`) is +`divPt n k j m = V_j + m/(k+1) (V_{j+1} - V_j)`. The `m`-th internal `n`-gon joins the `m`-th +division points of consecutive sides, so its sides are the segments +`chord n k (j, m-1) = [divPt n k j m, divPt n k (j+1) m]` (indexed by `Fin n × Fin k`). Each +internal `n`-gon is then a rotated and scaled copy of the outer one; this reading reproduces the +data (see below). The regions are the connected components of the interior of the +outer polygon with all `n*k` chords removed: `regions n k = Nat.card (ConnectedComponents …)`. +(The sides of the outer polygon are its frontier, removed by taking the interior.) + +A *non-simple intersection* is a point where three or more of the drawn lines meet, i.e. a point +lying on at least three distinct chords (`HasNonSimpleIntersection`). The division points +themselves are not counted: there only two chords meet (together with a side of the outer +polygon), for every `n` and `k`. A point on three distinct chords can only be an interior point +(the relative interior of each chord lies in the open polygon, and the endpoints of the chords +are the division points, each the endpoint of exactly two chords), so no further restriction is +needed. + +*Reading of the conjecture.* "The only n-gons that contain non-simple intersections are the +3-gon, 4-gon and 6-gon" is read as: for `n ≥ 3`, some `k` gives a non-simple intersection iff +`n ∈ {3, 4, 6}` (they occur first at `k = 5`, `5`, `9` respectively: the data give +`T(3,5) = 70 < 76`, `T(4,5) = 93 < 101`, `T(6,9) = 475 < 487`). The two conjectured formulas +together say `T(n,k) = n*k^2 + 1` for `n = 5` and every `n ≥ 7`, for all `k ≥ 0` (the table's +range of `k`). `statement` is the conjunction of these two claims. + +*The computable table `T`.* The count is computed exactly; the link `T n k = regions n k` is +the intended meaning and is not proved here. +* Coordinates. With `ζ = exp (2πi/n)` and `c = ζ + 1/ζ = 2 cos (2π/n)`, the map + `(x, y) ↦ x + y ζ` is an `ℝ`-linear bijection `ℝ² → ℂ`, so it preserves incidences. Since + `ζ^2 = c ζ - 1`, every `ζ^j` is `A_j(c) + B_j(c) ζ` with integer polynomials `A_j, B_j` + (`zpow`), and all coordinates of the division points (scaled by `k+1`, `divPtC`) lie in + `ℤ[c] ≅ ℤ[t]/(ψ_n)`. Here `ψ_n` (`psi`) is the minimal polynomial of `c`, obtained from the + palindromic cyclotomic polynomial `Φ_n` (`cycloBE`, computed by exact division of `x^n - 1` by + the `Φ_d`, `d ∣ n`, `d < n`) via `x^(-D) Φ_n(x) = ψ_n(x + 1/x)`. Elements of `ℤ[c]` are kept + reduced modulo `ψ_n`, so an element is `0` iff its reduced coefficient list is `0`. +* Counting. For chords whose endpoints lie on the boundary of a convex polygon (here: in the + relative interiors of two different sides), adding the chords one at a time, a chord splits as + many regions as the number of pieces it is cut into, i.e. `1 +` the number of distinct points + of the open chord lying on earlier chords. Add the chords in order of `m`. Two sides of the same + internal `n`-gon meet only at its vertices, on the boundary, so the earlier chords meeting + chord `(j, m)` inside the polygon are chords `(j', m')` with `m' < m`. The rotation by `2π/n` + maps the drawing onto itself and chord `(j, m)` to `(j+1, m)`. Hence + `T(n,k) = 1 + n * ∑_{m=1}^{k} (1 + E_m)`, where `E_m` (`newPoints`) is the number of distinct + points in which chord `(0, m)` meets the chords `(j', m')`, `m' < m`. +* Crossings. Two chords meet in the open polygon iff their four endpoints are distinct and + interleave along the boundary of the convex polygon (`crosses`; the `m`-th division point of + side `j` has boundary position `j*(k+1)+m`). Chords sharing an endpoint meet only there: three + points in the relative interiors of three distinct sides of a convex polygon are never + collinear. +* Distinct meeting points. The chord `(j', m')` on the line `a x + b y = e` (`chordLine`) meets + chord `(0, m)`, from `P` to `Q`, at `P + λ (Q - P)` with `λ = num / den`, + `num = e - a P_x - b P_y`, `den = a (Q - P)_x + b (Q - P)_y ≠ 0` (`meetParam`). Two such points + coincide iff `num₁ den₂ - num₂ den₁ = 0` in `ℤ[c]` (`countDistinct`). + +A Python transcription of `T`, and of a second exact variant that sums over all chords in the +cyclotomic ring `ℤ[ζ]` without the symmetry reduction, reproduces all 195 values of the entry's +EXAMPLE table (`n = 3..15`, `k = 0..14`). An independent floating-point computation (orientation +tests for crossings, clustering of intersection points) reproduces the 66 listed terms, and the +crossing criterion agrees with floating-point orientation tests for `n ≤ 20`, `k ≤ 15`. + +*Sequence indexing.* `a` reads the table by antidiagonals (`a 3 = T(3,0)`, `a 4 = T(3,1)`, +`a 5 = T(4,0)`, …), indexed from the entry's offset `3`; `a_data` checks all 66 listed terms +(antidiagonals `n + k = 3, …, 13`). +-/ + +namespace Math0.Statements.A357216 + +/-! ### The geometric definition -/ + +/-- The `j`-th vertex `exp (2πij/n)` of the regular `n`-gon inscribed in the unit circle. -/ +noncomputable def vertex (n j : ℕ) : ℂ := Complex.exp (2 * Real.pi * Complex.I * j / n) + +/-- The `m`-th of the `k` points dividing side `j` (from `vertex n j` to `vertex n (j+1)`) +into `k+1` equal parts. -/ +noncomputable def divPt (n k j m : ℕ) : ℂ := + vertex n j + ((m : ℂ) / ((k : ℂ) + 1)) * (vertex n (j + 1) - vertex n j) + +/-- Side `c.1` of the internal `n`-gon number `c.2 + 1`: the segment joining the +`(c.2+1)`-th division points of sides `c.1` and `c.1 + 1`. -/ +noncomputable def chord (n k : ℕ) (c : Fin n × Fin k) : Set ℂ := + segment ℝ (divPt n k (c.1 : ℕ) ((c.2 : ℕ) + 1)) (divPt n k ((c.1 : ℕ) + 1) ((c.2 : ℕ) + 1)) + +/-- The (closed) regular `n`-gon. -/ +noncomputable def polygon (n : ℕ) : Set ℂ := + convexHull ℝ (Set.range fun j : Fin n => vertex n j) + +/-- The interior of the `n`-gon with the sides of all `k` internal `n`-gons removed. -/ +noncomputable def regionSet (n k : ℕ) : Set ℂ := + interior (polygon n) \ ⋃ c : Fin n × Fin k, chord n k c + +/-- `T(n,k)` as defined in the entry: the number of regions (connected components) into which +the `k` internal `n`-gons cut the regular `n`-gon. -/ +noncomputable def regions (n k : ℕ) : ℕ := + Nat.card (ConnectedComponents (regionSet n k)) + +/-- The drawing for `(n, k)` has a non-simple intersection: some point lies on three distinct +sides of the internal `n`-gons. -/ +def HasNonSimpleIntersection (n k : ℕ) : Prop := + ∃ p : ℂ, ∃ c₁ c₂ c₃ : Fin n × Fin k, c₁ ≠ c₂ ∧ c₁ ≠ c₃ ∧ c₂ ≠ c₃ ∧ + p ∈ chord n k c₁ ∧ p ∈ chord n k c₂ ∧ p ∈ chord n k c₃ + +/-! ### The exact computation + +Little-endian lists are integer polynomials (`[c₀, c₁, …] = c₀ + c₁ t + …`); `BE` functions work +on big-endian lists (leading coefficient first). -/ + +/-- Sum of polynomials. -/ +def padd : List ℤ → List ℤ → List ℤ + | [], q => q + | p, [] => p + | a :: p, b :: q => (a + b) :: padd p q + +/-- Negation of a polynomial. -/ +def pneg (p : List ℤ) : List ℤ := p.map fun a => -a + +/-- Difference of polynomials. -/ +def psub (p q : List ℤ) : List ℤ := padd p (pneg q) + +/-- Scalar multiple of a polynomial. -/ +def psmul (c : ℤ) (p : List ℤ) : List ℤ := p.map fun a => c * a + +/-- Product of polynomials. -/ +def pmul : List ℤ → List ℤ → List ℤ + | [], _ => [] + | a :: p, q => padd (psmul a q) (0 :: pmul p q) + +/-- Coefficientwise difference of big-endian lists aligned at the leading end. -/ +def subFront : List ℤ → List ℤ → List ℤ + | p, [] => p + | [], q => pneg q + | a :: p, b :: q => (a - b) :: subFront p q + +/-- One step of long division by the monic big-endian divisor `1 :: qs`. -/ +def cancelLead (qs : List ℤ) : List ℤ → List ℤ + | [] => [] + | a :: p => subFront p (psmul a qs) + +/-- Remainder of `p` modulo the monic `q` (big-endian; `fuel ≥ p.length` suffices). -/ +def remBE (q : List ℤ) : ℕ → List ℤ → List ℤ + | 0, p => p + | fuel + 1, p => if q.length ≤ p.length then remBE q fuel (cancelLead q.tail p) else p + +/-- Quotient of `p` by the monic `q` (big-endian; `fuel ≥ p.length` suffices). -/ +def quotBE (q : List ℤ) : ℕ → List ℤ → List ℤ + | 0, _ => [] + | fuel + 1, p => + if q.length ≤ p.length then p.headD 0 :: quotBE q fuel (cancelLead q.tail p) else [] + +/-- `x ^ n - 1`, big-endian (`n ≥ 1`). -/ +def xPowSubOneBE (n : ℕ) : List ℤ := 1 :: List.replicate (n - 1) 0 ++ [-1] + +/-- The cyclotomic polynomial `Φ_n = (x^n - 1) / ∏_{d ∣ n, d < n} Φ_d`, big-endian. -/ +def cycloBE : ℕ → ℕ → List ℤ + | 0, _ => [1] + | fuel + 1, n => + (List.range n).foldl + (fun acc d => if 0 < d ∧ n % d = 0 then quotBE (cycloBE fuel d) acc.length acc else acc) + (xPowSubOneBE n) + +/-- `∑ a_i D_i` for the Dickson polynomials `D_{i+1} = t D_i - D_{i-1}`, starting from +`acc` with the current pair `(D_{i-1}, D_i)`. -/ +def dicksonSum : List ℤ → List ℤ → List ℤ → List ℤ → List ℤ + | acc, _, _, [] => acc + | acc, Dp, Dc, a :: as => dicksonSum (padd acc (psmul a Dc)) Dc (psub (0 :: Dc) Dp) as + +/-- The minimal polynomial `ψ_n` of `2 cos (2π/n)` (`n ≥ 3`), little-endian. Writing the +palindromic `Φ_n(x) = ∑_{i ≤ 2D} a_i x^i`, we have +`ψ_n(x + 1/x) = x^(-D) Φ_n(x) = a_D + ∑_{i=1}^{D} a_{D+i} D_i(x + 1/x)`. -/ +def psi (n : ℕ) : List ℤ := + let cyc := cycloBE n n + dicksonSum [cyc.getD (cyc.length / 2) 0] [2] [0, 1] (cyc.drop (cyc.length / 2 + 1)) + +/-- Reduction of a little-endian polynomial modulo the monic big-endian `q`. -/ +def red (q p : List ℤ) : List ℤ := (remBE q p.length p.reverse).reverse + +/-- Zero test for a reduced element. -/ +def isZero (p : List ℤ) : Bool := p.all (· == 0) + +/-- Coordinates `(A_j, B_j)` of `ζ^j = A_j + B_j ζ`, as polynomials in `c = ζ + 1/ζ` reduced +modulo `q = ψ_n` (big-endian), from `ζ^2 = c ζ - 1`. -/ +def zpow (q : List ℤ) : ℕ → List ℤ × List ℤ + | 0 => ([1], []) + | j + 1 => match zpow q j with + | (a, b) => (pneg b, red q (padd a (0 :: b))) + +/-- `(k+1)` times the `m`-th division point of side `j`, in coordinates. -/ +def divPtC (q : List ℤ) (k j m : ℕ) : List ℤ × List ℤ := + match zpow q j, zpow q (j + 1) with + | (a, b), (a', b') => + (padd (psmul ((k + 1 - m : ℕ) : ℤ) a) (psmul (m : ℤ) a'), + padd (psmul ((k + 1 - m : ℕ) : ℤ) b) (psmul (m : ℤ) b')) + +/-- The line `a x + b y = e` through `(k+1) P_{j,m}` and `(k+1) P_{j+1,m}`. -/ +def chordLine (q : List ℤ) (k j m : ℕ) : List ℤ × List ℤ × List ℤ := + match divPtC q k j m, divPtC q k (j + 1) m with + | (x₁, y₁), (x₂, y₂) => + (psub y₁ y₂, psub x₂ x₁, red q (padd (pmul (psub y₁ y₂) x₁) (pmul (psub x₂ x₁) y₁))) + +/-- Boundary positions of the two endpoints of chord `(j, m)`. -/ +def endpoints (n k : ℕ) (c : ℕ × ℕ) : ℕ × ℕ := + (c.1 * (k + 1) + c.2, ((c.1 + 1) % n) * (k + 1) + c.2) + +/-- `x` lies strictly between `a` and `b`. -/ +def strictlyBetween (a b x : ℕ) : Bool := (a < x && x < b) || (b < x && x < a) + +/-- Chords `c` and `e` meet inside the polygon: their endpoints are distinct and interleave +along the boundary. -/ +def crosses (n k : ℕ) (c e : ℕ × ℕ) : Bool := + match endpoints n k c, endpoints n k e with + | (a, b), (x, y) => + a != x && a != y && b != x && b != y && (strictlyBetween a b x != strictlyBetween a b y) + +/-- The parameter `num / den` along chord `(0, m)` (scaled by `k+1`, from `(k+1) P_{0,m}` to +`(k+1) P_{1,m}`) of its meeting point with the line `L`. -/ +def meetParam (q : List ℤ) (k m : ℕ) (L : List ℤ × List ℤ × List ℤ) : List ℤ × List ℤ := + match divPtC q k 0 m, divPtC q k 1 m, L with + | (x₁, y₁), (x₂, y₂), (a, b, e) => + (red q (psub e (padd (pmul a x₁) (pmul b y₁))), + red q (padd (pmul a (psub x₂ x₁)) (pmul b (psub y₂ y₁)))) + +/-- Number of distinct parameters `num / den` in the list (all `den ≠ 0`). -/ +def countDistinct (q : List ℤ) : List (List ℤ × List ℤ) → List (List ℤ × List ℤ) → ℕ + | _, [] => 0 + | seen, p :: ps => + (if seen.any (fun p' => isZero (red q (psub (pmul p.1 p'.2) (pmul p'.1 p.2)))) then 0 else 1) + + countDistinct q (p :: seen) ps + +/-- `E_m`: the number of distinct points in which chord `(0, m)` meets chords `(j, m')` +with `m' < m`. -/ +def newPoints (n k : ℕ) (q : List ℤ) (m : ℕ) : ℕ := + countDistinct q [] + (((List.range (m - 1)).flatMap fun m' => (List.range n).map fun j => (j, m' + 1)).filter + (fun c => crosses n k (0, m) c) |>.map fun c => meetParam q k m (chordLine q k c.1 c.2)) + +/-- `T(n,k)` computed exactly: `1 + n * ∑_{m=1}^{k} (1 + E_m)` (see the module docstring). -/ +def T (n k : ℕ) : ℕ := + let q := (psi n).reverse + 1 + n * ((List.range k).map fun m => 1 + newPoints n k q (m + 1)).sum + +/-- `antidiagPos i = (d, r)`: the `i`-th term (from `0`) of a table read by antidiagonals is +term `r` (from `0`) of antidiagonal `d`. -/ +def antidiagPos : ℕ → ℕ × ℕ + | 0 => (0, 0) + | i + 1 => match antidiagPos i with + | (d, r) => if r < d then (d, r + 1) else (d + 1, 0) + +/-- A357216 as a sequence (offset 3): the table `T(n,k)` (`n ≥ 3`, `k ≥ 0`) read by +antidiagonals, `T(3,0), T(3,1), T(4,0), T(3,2), T(4,1), T(5,0), …`. -/ +def a (i : ℕ) : ℕ := + match antidiagPos (i - 3) with + | (d, r) => T (3 + r) (d - r) + +/-- The definition reproduces all 66 terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 66).map (fun i => a (i + 3)) = + [1, 4, 1, 13, 5, 1, 28, 17, 6, 1, 49, 37, 21, 7, 1, 70, 65, 46, 25, 8, 1, 109, 93, 81, 55, + 29, 9, 1, 148, 145, 126, 97, 64, 33, 10, 1, 181, 181, 181, 151, 113, 73, 37, 11, 1, 244, + 257, 246, 217, 176, 129, 82, 41, 12, 1, 301, 309, 321, 295, 253, 201, 145, 91, 45, 13, + 1] := by + decide +kernel + +/-- Conjecture (Scott R. Shannon, 2022): among the regular `n`-gons (`n ≥ 3`) cut by `k` +internal `n`-gons, exactly the triangle, the square and the hexagon have (for some `k`) a point +on three or more of the drawn lines; and for `n = 5` and every `n ≥ 7` the number of regions is +`T(n,k) = n*k^2 + 1` for all `k ≥ 0`. -/ +def statement : Prop := + (∀ n : ℕ, 3 ≤ n → ((∃ k : ℕ, HasNonSimpleIntersection n k) ↔ (n = 3 ∨ n = 4 ∨ n = 6))) ∧ + (∀ n k : ℕ, (n = 5 ∨ 7 ≤ n) → regions n k = n * k ^ 2 + 1) + +end Math0.Statements.A357216 diff --git a/lean/Math0/Statements/OEIS/A357583.lean b/lean/Math0/Statements/OEIS/A357583.lean new file mode 100644 index 0000000..0c0a535 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A357583.lean @@ -0,0 +1,180 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A357583: Kurkov's recursion for the row polynomials of convolution triangles + +Source: https://oeis.org/A357583, Mikhail Kurkov, Apr 05 2025 (FORMULA section). Verbatim: +> Conjecture: row polynomials are x*R(n,1) for n > 0 where R(n,k) = R(n-1,k+1) + +> x*R(n-1,1)*R(1,k) for n > 1, k > 0 with R(1,k) = Bell(k) for k > 0. The same recursion seems +> to work for self-convolution of any other sequence. + +The entry (Peter Luschny, Oct 05 2022; offset `0`, keyword `tabl`) is "Triangle read by rows. +Convolution triangle of the Bell numbers." It is computed as `PMatrix(10, combinat[bell])` with +the Maple procedure `PMatrix` of A357368, whose comments fix the terminology: the convolution +triangle of a sequence `a(1), a(2), …` (only the terms with index `≥ 1` are used) is the +`(0,0)`-based lower triangular matrix with `T(0,0) = 1`, `T(n,0) = 0` for `n > 0`, `T(n,1) = a(n)`, +and in general `T(n,k) = [z^n] A(z)^k` with `A(z) = ∑_{j ≥ 1} a(j) z^j`. + +## Encoding + +* *Convolution triangles.* For a sequence `s : ℕ → R` (`R` a commutative semiring) `pad s` is + `s` with its value at `0` replaced by `0`, so only `s 1, s 2, …` matter, and `convT s n k` is + defined by `convT s n 0 = [n = 0]` and + `convT s n (k+1) = ∑_{i + j = n} pad s i * convT s j k`. `convT_eq_coeff` proves + `convT s n k = [z^n] (gf s)^k` with `gf s = ∑_{j ≥ 1} s(j) z^j` (a `PowerSeries`). This agrees + with `PMatrix`: its recursion `T(n,k) = ∑_{i=1}^{n-k+1} a(i) T(n-i,k-1)` (for `2 ≤ k+1 ≤ n`) and + `T(n,n) = a(1) T(n-1,n-1)` differ from ours only by terms with `T(m,j)`, `j > m`, which vanish; + the data check below confirms the agreement on all listed terms. +* *Bell numbers.* `Bell(k)` is Mathlib's `Nat.bell k` (`Bell(0) = 1`, + `Bell(n+1) = ∑_{i ≤ n} C(n,i) Bell(n-i)`, i.e. A000110). +* *The triangle.* `T n k = convT Nat.bell n k` (over `ℕ`). For kernel evaluation `col` computes + the columns of a convolution triangle as lists (`col_getD`), and `T_eq_Tfast` rewrites `T` to + that. `T_data` checks all 11 listed rows `n = 0, …, 10` (66 terms). `a` is the triangle read + by rows (the OEIS sequence itself, offset `0`), and `a_data` checks the 66 listed terms + `a 0, …, a 65`. +* *Kurkov's polynomials.* For a sequence `s : ℕ → ℤ`, `R s n k : ℤ[X]` (the variable `X` is the + `x` of the conjecture) is given by `R s 1 k = s(k)` and + `R s n k = R s (n-1) (k+1) + X * R s (n-1) 1 * R s 1 k` for `n > 1`. The conjecture only + uses `n ≥ 1, k ≥ 1`; starting from `R s n 1` the recursion only reaches indices `n ≥ 1, k ≥ 1`, + so the values at `n = 0` (set to `0`) and `k = 0` (given by the same formulas) are never used. + The Bell instance is `R bellZ`, `bellZ k = Bell(k)` as an integer. +* *Row polynomials.* The row polynomial of row `n` of the convolution triangle of `s` is + `rowPoly s n = ∑_{k=0}^{n} convT s n k * X^k`. +* *The conjecture.* `statement` is the conjunction of its two sentences: + 1. for every `n > 0`, `∑_{k=0}^{n} T(n,k) X^k = X * R bellZ n 1` in `ℤ[X]`; + 2. for every integer sequence `s` (only `s(k)` for `k ≥ 1` matter) and every `n > 0`, + `rowPoly s n = X * R s n 1` in `ℤ[X]` ("the same recursion" with `R(1,k) = s(k)` for the + convolution triangle of `s`). We read "any other sequence" as any integer sequence, as + OEIS sequences are integer sequences. +-/ + +namespace Math0.Statements.A357583 + +open Polynomial + +/-! ### Convolution triangles -/ + +section ConvolutionTriangle + +variable {R : Type*} [CommSemiring R] + +/-- The sequence `s` with its value at `0` replaced by `0`: a convolution triangle only uses +`s 1, s 2, …`. -/ +def pad (s : ℕ → R) (j : ℕ) : R := if j = 0 then 0 else s j + +/-- The convolution triangle of the sequence `s(1), s(2), …` (A357368's `PMatrix`): +`convT s n k = [z^n] (∑_{j ≥ 1} s(j) z^j)^k` (see `convT_eq_coeff`). -/ +def convT (s : ℕ → R) : ℕ → ℕ → R + | n, 0 => if n = 0 then 1 else 0 + | n, k + 1 => ∑ p ∈ Finset.HasAntidiagonal.antidiagonal n, pad s p.1 * convT s p.2 k + +/-- The generating function `∑_{j ≥ 1} s(j) z^j` of the sequence `s(1), s(2), …`. -/ +noncomputable def gf (s : ℕ → R) : PowerSeries R := PowerSeries.mk (pad s) + +/-- The convolution triangle as coefficients of powers of the generating function: +`T(n,k) = [z^n] (∑_{j ≥ 1} s(j) z^j)^k`. -/ +theorem convT_eq_coeff (s : ℕ → R) (n k : ℕ) : + convT s n k = PowerSeries.coeff n (gf s ^ k) := by + induction k generalizing n with + | zero => simp [convT, PowerSeries.coeff_one] + | succ k ih => + rw [pow_succ', PowerSeries.coeff_mul, convT] + refine Finset.sum_congr rfl fun p _ => ?_ + rw [ih, gf, PowerSeries.coeff_mk] + +/-- The columns `0, 1, …` of the convolution triangle of `s`, each as the list of its first `N` +entries (for fast evaluation). -/ +def col (s : ℕ → R) (N : ℕ) : ℕ → List R + | 0 => (List.range N).map (fun n => if n = 0 then 1 else 0) + | k + 1 => (List.range N).map (fun n => + ∑ p ∈ Finset.HasAntidiagonal.antidiagonal n, pad s p.1 * (col s N k).getD p.2 0) + +theorem col_getD (s : ℕ → R) (N k n : ℕ) (hn : n < N) : + (col s N k).getD n 0 = convT s n k := by + induction k generalizing n with + | zero => simp [col, convT, List.getD_eq_getElem?_getD, List.getElem?_range hn] + | succ k ih => + simp only [col, convT, List.getD_eq_getElem?_getD, List.getElem?_map, List.getElem?_range hn, + Option.map_some, Option.getD_some] + refine Finset.sum_congr rfl fun p hp => ?_ + rw [Finset.HasAntidiagonal.mem_antidiagonal] at hp + rw [← ih p.2 (by omega), List.getD_eq_getElem?_getD] + +end ConvolutionTriangle + +/-! ### The triangle A357583 -/ + +/-- A357583: `T(n, k)` is the convolution triangle of the Bell numbers, +`T(n,k) = [z^n] (∑_{j ≥ 1} Bell(j) z^j)^k`. -/ +def T (n k : ℕ) : ℕ := convT Nat.bell n k + +/-- Fast evaluation of `T n k` via the column lists. -/ +def Tfast (n k : ℕ) : ℕ := (col Nat.bell (n + 1) k).getD n 0 + +theorem T_eq_Tfast (n k : ℕ) : T n k = Tfast n k := + (col_getD Nat.bell (n + 1) k n (Nat.lt_succ_self n)).symm + +/-- The definition reproduces the 11 listed rows `n = 0, …, 10` of the triangle +(kernel-checked). -/ +theorem T_data : (List.range 11).map (fun n => (List.range (n + 1)).map (T n)) = + [[1], + [0, 1], + [0, 2, 1], + [0, 5, 4, 1], + [0, 15, 14, 6, 1], + [0, 52, 50, 27, 8, 1], + [0, 203, 189, 113, 44, 10, 1], + [0, 877, 764, 471, 212, 65, 12, 1], + [0, 4140, 3311, 2013, 974, 355, 90, 14, 1], + [0, 21147, 15378, 8951, 4440, 1790, 550, 119, 16, 1], + [0, 115975, 76418, 41745, 20526, 8727, 3027, 805, 152, 18, 1]] := by + rw [funext₂ T_eq_Tfast] + decide +kernel + +/-- A357583 as a sequence (offset `0`): the triangle `T` read by rows. (Rows `0, …, i` contain at +least `i + 1` entries, so the `i`-th entry of the concatenation lies among them.) -/ +def a (i : ℕ) : ℕ := + ((List.range (i + 1)).flatMap fun n => (List.range (n + 1)).map (T n)).getD i 0 + +/-- The definition reproduces all 66 terms listed in OEIS, `a 0, …, a 65` (kernel-checked). -/ +theorem a_data : (List.range 66).map (fun i => a (i + 0)) = + [1, 0, 1, 0, 2, 1, 0, 5, 4, 1, 0, 15, 14, 6, 1, 0, 52, 50, 27, 8, 1, 0, 203, 189, 113, 44, + 10, 1, 0, 877, 764, 471, 212, 65, 12, 1, 0, 4140, 3311, 2013, 974, 355, 90, 14, 1, 0, + 21147, 15378, 8951, 4440, 1790, 550, 119, 16, 1, 0, 115975, 76418, 41745, 20526, 8727, + 3027, 805, 152, 18, 1] := by + unfold a + rw [funext₂ T_eq_Tfast] + decide +kernel + +/-! ### Kurkov's recursion -/ + +/-- Kurkov's polynomials for the sequence `s`: `R(1,k) = s(k)` and +`R(n,k) = R(n-1,k+1) + x * R(n-1,1) * R(1,k)` for `n > 1` (only `n, k ≥ 1` are meaningful; +`R s 0 k = 0` is a junk value). -/ +noncomputable def R (s : ℕ → ℤ) : ℕ → ℕ → ℤ[X] + | 0, _ => 0 + | 1, k => C (s k) + | n + 2, k => R s (n + 1) (k + 1) + X * R s (n + 1) 1 * R s 1 k + +/-- The Bell numbers as integers. -/ +def bellZ (k : ℕ) : ℤ := (Nat.bell k : ℤ) + +/-- The row polynomial `∑_{k=0}^{n} T(n,k) x^k` of row `n` of the convolution triangle of `s`. -/ +noncomputable def rowPoly (s : ℕ → ℤ) (n : ℕ) : ℤ[X] := + ∑ k ∈ Finset.range (n + 1), C (convT s n k) * X ^ k + +/-! ### The conjecture -/ + +/-- Conjecture (Mikhail Kurkov, 2025): (1) for every `n > 0`, the row polynomial +`∑_{k=0}^{n} T(n,k) x^k` of A357583 equals `x * R(n,1)`, where `R(1,k) = Bell(k)` and +`R(n,k) = R(n-1,k+1) + x * R(n-1,1) * R(1,k)` for `n > 1`, `k > 0`; and (2) the same holds for +the convolution triangle of any (integer) sequence `s(1), s(2), …`, with `R(1,k) = s(k)`. -/ +def statement : Prop := + (∀ n : ℕ, 0 < n → + ∑ k ∈ Finset.range (n + 1), C (T n k : ℤ) * X ^ k = X * R bellZ n 1) ∧ + (∀ s : ℕ → ℤ, ∀ n : ℕ, 0 < n → rowPoly s n = X * R s n 1) + +end Math0.Statements.A357583 diff --git a/lean/Math0/Statements/OEIS/A362086.lean b/lean/Math0/Statements/OEIS/A362086.lean new file mode 100644 index 0000000..ffa017e --- /dev/null +++ b/lean/Math0/Statements/OEIS/A362086.lean @@ -0,0 +1,67 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A362086: denominators of `1/(2-3/(3-4/(...(n-1)-n/(-3))))` are 1 or prime, except 9 + +Source: https://oeis.org/A362086, Mohammed Bouras, May 28 2023. Verbatim: +> Conjecture: Except for 9, every term of this sequence is either a prime or 1. + +The sequence (offset 3) is the "Denominator of the continued fraction +1/(2-3/(3-4/(4-5/(...(n-1)-n/(-3)))))". The entry's examples fix the shape: +`a(3)` is the denominator of `1/(2 - 3/(-3)) = 1/3`, `a(4)` that of +`1/(2 - 3/(3 - 4/(-3))) = 13/17`, and `a(5)` that of `1/(2 - 3/(3 - 4/(4 - 5/(-3)))) = 13/9`. + +## Encoding + +The continued fraction is evaluated in `ℚ` from the inside out: start with `-3` and apply +`step k t = k - (k+1)/t` for `k = n-1, n-2, …, 2` (this is `List.foldr step (-3)` over +`[2, 3, …, n-1] = List.range' 2 (n - 2)`), then take the reciprocal. `a n` is the denominator +`Rat.den` of the resulting rational number in lowest terms (always positive, and `1` when the +value is an integer, e.g. `a 21 = 1`). + +Lean's `x / 0 = 0` convention plays no role for `n ≥ 3`: no inner tail of the continued fraction +vanishes. (The innermost value `-3` is nonzero; the tail `t_{n-1} = (n-1) + n/3` is `≥ 2`, the +tails `t_k` with `5 ≤ k < n-1` are then `≥ (k-1)/2 ≥ 2`, `t_4 ≥ 3/2` and `t_3 ≥ 1/3`, so all tails +`t_k`, `k ≥ 3`, are positive. The numbers `u_k = k(k-2)/(k-1)` satisfy `u_k = k - (k+1)/u_{k+1}` +and `u_2 = 0`, so by injectivity of `t ↦ k - (k+1)/t` a vanishing outer tail `t_2 = 0` would +force `t_{n-1} = (n-1)(n-3)/(n-2) < n-1`, which is false. It was also checked by exact arithmetic +for `3 ≤ n < 1500`.) The definition reproduces all 57 terms listed in the entry (`a_data`, +`n = 3, …, 59`). Values of `a n` for `n < 3` are outside the sequence and are never used. + +*Reading of "Except for 9".* The exception is the value `9` (which is `a 5`, see `a_data`): +every term `a n` with `n ≥ 3` that is not `9` is `1` or a prime. +-/ + +namespace Math0.Statements.A362086 + +/-- One level of the continued fraction: `step k t = k - (k+1)/t`. -/ +def step (k : ℕ) (t : ℚ) : ℚ := (k : ℚ) - ((k : ℚ) + 1) / t + +/-- The continued fraction `1/(2 - 3/(3 - 4/(4 - 5/(… (n-1) - n/(-3)))))`, evaluated from the +inside out: `step 2 (step 3 (… (step (n-1) (-3))))`, then the reciprocal. -/ +def cf (n : ℕ) : ℚ := 1 / (List.range' 2 (n - 2)).foldr step (-3) + +/-- A362086 (offset 3): the denominator of the continued fraction +`1/(2-3/(3-4/(4-5/(...(n-1)-n/(-3)))))`, in lowest terms. -/ +def a (n : ℕ) : ℕ := (cf n).den + +/-- The entry's examples: `a(3)`, `a(4)`, `a(5)` come from `1/3`, `13/17`, `13/9`. -/ +example : cf 3 = 1 / 3 ∧ cf 4 = 13 / 17 ∧ cf 5 = 13 / 9 := by decide +kernel + +/-- The definition reproduces all 57 terms listed in OEIS, `a 3, …, a 59` (kernel-checked). -/ +theorem a_data : (List.range 57).map (fun i => a (i + 3)) = + [3, 17, 9, 13, 53, 23, 29, 107, 43, 17, 179, 23, 79, 269, 101, 113, 29, 139, 1, 503, 61, + 199, 647, 233, 251, 809, 17, 103, 43, 1, 373, 1187, 419, 443, 61, 1, 173, 1637, 191, + 601, 1889, 659, 53, 127, 751, 1, 2447, 283, 883, 2753, 953, 1, 181, 1063, 367, 263, + 131] := by + decide +kernel + +/-- Conjecture (Mohammed Bouras, 2023): except for `9`, every term `a n` (`n ≥ 3`) of the +sequence is either a prime or `1`. -/ +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → a n ≠ 9 → a n = 1 ∨ (a n).Prime + +end Math0.Statements.A362086 diff --git a/lean/Math0/Statements/OEIS/A363482.lean b/lean/Math0/Statements/OEIS/A363482.lean new file mode 100644 index 0000000..d7fbb0c --- /dev/null +++ b/lean/Math0/Statements/OEIS/A363482.lean @@ -0,0 +1,65 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A363482: denominators of `1/(2-3/(3-4/(...(n-1)-n/(-5))))` are 1 or prime, except 49 + +Source: https://oeis.org/A363482, Mohammed Bouras, Jun 04 2023. Verbatim: +> Conjecture: Except for 49, every term of this sequence is either a prime or 1. + +The sequence (offset 3) is the "Denominator of the continued fraction +1/(2-3/(3-4/(4-5/(...(n-1)-n/(-5)))))". The entry's examples fix the shape: +`a(3)` is the denominator of `1/(2 - 3/(-5)) = 5/13`, `a(4)` that of +`1/(2 - 3/(3 - 4/(-5))) = 19/23`, and `a(5)` that of `1/(2 - 3/(3 - 4/(4 - 5/(-5)))) = 11/7`. + +## Encoding + +The continued fraction is evaluated in `ℚ` from the inside out: start with `-5` and apply +`step k t = k - (k+1)/t` for `k = n-1, n-2, …, 2` (this is `List.foldr step (-5)` over +`[2, 3, …, n-1] = List.range' 2 (n - 2)`), then take the reciprocal. `a n` is the denominator +`Rat.den` of the resulting rational number in lowest terms (always positive, and `1` when the +value is an integer, e.g. `a 12 = 1`). + +Lean's `x / 0 = 0` convention plays no role for `n ≥ 3`: no inner tail of the continued fraction +vanishes. (By the convergent recurrences, a vanishing tail would force the value to equal +`!m / 2` for some left factorial `!m`, while the value is `!(n-3)/2 + 5(n-1)(n-3)!/(2(n^2+3n-5))`; +this never happens for `n ≥ 3`. It was also checked by exact arithmetic for `3 ≤ n < 1200`.) +The definition reproduces all 61 terms listed in the entry (`a_data`, `n = 3, …, 63`). Values of +`a n` for `n < 3` are outside the sequence and are never used. + +*Reading of "Except for 49".* The exception is the value `49` (which is `a 6`, see `a_data`): +every term `a n` with `n ≥ 3` that is not `49` is `1` or a prime. +-/ + +namespace Math0.Statements.A363482 + +/-- One level of the continued fraction: `step k t = k - (k+1)/t`. -/ +def step (k : ℕ) (t : ℚ) : ℚ := (k : ℚ) - ((k : ℚ) + 1) / t + +/-- The continued fraction `1/(2 - 3/(3 - 4/(4 - 5/(… (n-1) - n/(-5)))))`, evaluated from the +inside out: `step 2 (step 3 (… (step (n-1) (-5))))`, then the reciprocal. -/ +def cf (n : ℕ) : ℚ := 1 / (List.range' 2 (n - 2)).foldr step (-5) + +/-- A363482 (offset 3): the denominator of the continued fraction +`1/(2-3/(3-4/(4-5/(...(n-1)-n/(-5)))))`, in lowest terms. -/ +def a (n : ℕ) : ℕ := (cf n).den + +/-- The entry's examples: `a(3)`, `a(4)`, `a(5)` come from `5/13`, `19/23`, `11/7`. -/ +example : cf 3 = 5 / 13 ∧ cf 4 = 19 / 23 ∧ cf 5 = 11 / 7 := by decide +kernel + +/-- The definition reproduces all 61 terms listed in OEIS, `a 3, …, a 63` (kernel-checked). -/ +theorem a_data : (List.range 61).map (fun i => a (i + 3)) = + [13, 23, 7, 49, 13, 83, 103, 5, 149, 1, 29, 233, 53, 23, 67, 373, 59, 1, 499, 109, 593, 643, + 139, 107, 1, 863, 71, 197, 1049, 223, 1, 179, 53, 1399, 59, 1553, 71, 1, 257, 1, 1973, 2063, + 431, 173, 67, 349, 2543, 1, 2749, 571, 2963, 439, 1, 3299, 683, 3533, 281, 151, 557, 1, + 4153] := by + decide +kernel + +/-- Conjecture (Mohammed Bouras, 2023): except for `49`, every term `a n` (`n ≥ 3`) of the +sequence is either a prime or `1`. -/ +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → a n ≠ 49 → a n = 1 ∨ (a n).Prime + +end Math0.Statements.A363482 diff --git a/lean/Math0/Statements/OEIS/A363609.lean b/lean/Math0/Statements/OEIS/A363609.lean new file mode 100644 index 0000000..9215f77 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A363609.lean @@ -0,0 +1,1534 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A363609: minimum number of visible pips on a polycube made of `n` dice + +Source: https://oeis.org/A363609, _Matt Donahoe_, Jun 11 2023 (last edited Sep 03 2023). +Verbatim (FORMULA, unattributed): +> Conjecture: a(k^3) = 6*(k+2)*k for k > 1. + +The entry's name is "Minimum sum of the visible pips on a polycube made from n dice." (offset `1`) +with the comment "This sequence is calculated using standard six-sided dice of the same chirality. +Opposite sides sum to seven." Example: "For n = 2, two dice are conjoined to hide both their +6-pip faces, so a(2) = 30." + +## Encoding + +* *Polycubes.* Unit cells of the cubic lattice are indexed by `Cell = ℤ × ℤ × ℤ`. The six faces + of a cell have outward normals in `dirs = {±e₁, ±e₂, ±e₃}`. A polycube with `n` cells is a + finset `P` of `n` cells that is face-connected: any two cells of `P` are joined by a chain of + cells of `P` in which consecutive cells differ by a vector of `dirs` (`FaceConnected`). Every + cell carries one die. +* *Dice.* An orientation of a die is a pair `o = (u, v)` of perpendicular unit vectors + (`IsOrientation`). The die shows `1` pip on its face with outer normal `u`, `2` on `v`, `3` on + `u × v`, and `7 - k` on the face opposite to the `k`-face (`pips`). So opposite faces sum to + seven, faces `1, 2, 3` form a right-handed frame, and every die has the same chirality. The `24` + pairs `(u, v)` are exactly the `24` rotations of the reference die (`1, 2, 3` on `+x, +y, +z`). + Dice are oriented independently. (The entry does not say which of the two chiralities is used; + reflecting a whole configuration in a plane turns every die into its mirror image, so the + minimum is the same for both.) +* *Visible pips.* The face of the cell `c ∈ P` with normal `d` is visible iff `c + d ∉ P`. All + six sides count, including the bottom, so a single die shows `21` pips. `visiblePips P o` is the + sum of the pips on the visible faces when the die in cell `c` has orientation `o c`. (Faces + towards an enclosed empty cell also count as visible. This matches the listed data: with the + other reading the `3 × 3 × 3` cube minus its centre would give `a(26) ≤ 90`, but the entry lists + `a(26) = 93`. For `n = k³` the conjectured optimum, the full cube, has no cavity.) +* *The sequence.* `totals n` is the set of all values `visiblePips P o` for polycubes `P` with + `n` cells and orientations `o` of their dice. `a n = sInf (totals n)` is its minimum. Offset + `1`. (`a 0 = 0` comes from the empty polycube and is not part of the sequence.) `a` is + noncomputable as written: it is an infimum over infinitely many polycubes. +* *The conjecture.* `statement`: for every natural number `k > 1`, `a (k ^ 3) = 6 * (k + 2) * k`. + +## Certified values + +The section "Certification" connects `a` to kernel-checked computations, with proofs: +* Since the dice are oriented independently, the minimum over orientations is + `LB P = ∑ c ∈ P, fmin (exposed P c)`, where `fmin E` is the least number of pips a single die + can show on the set of directions `E` (`LB_le_visiblePips`, `visiblePips_best`). +* *Upper bounds.* `wits` lists, for every term `a(1), …, a(57)` in the entry's DATA, a polycube + (cells encoded as natural numbers, `dec k = (k % 32, k / 32 % 32, k / 1024)`) that attains the + listed value. The polycube comes with a growth order certifying face-connectedness. The kernel + checks each witness (`wits_ok`), so `a n ≤` the listed value for all `57` listed terms + (`a_le_data`). +* *Lower bounds.* `LB` does not change under translations and under the symmetries of the + lattice, because `fmin` is invariant under the `48` symmetries of the cube (`Adm`; the + symmetries are generated by `G 0`, `G 1`, `G 2`). `reps` lists representatives of the + polycubes with `1, …, 6` cells up to symmetry (`1, 1, 2, 7, 23, 112` of them). `complete` + proves that every polycube with at most `6` cells is mapped onto one of them by an admissible + map. The proof uses that a connected polycube with at least two cells has a cell whose removal + leaves it connected (`exists_leaf`), and kernel-checked certificates (`hints`, `certs_ok`) + that every one-cell extension of a representative is mapped onto a representative with one + more cell. The kernel computes the minimum of `LB` over the representatives (`minVal_ok`) and + checks that every one-cell extension of a `6`-cell representative has `LB ≥ 54` (`kids_ok`). +* Together: `a_data` gives the exact values `a(1), …, a(7) = 21, 30, 40, 40, 51, 52, 54`, as + listed. Going on to `a(8)` this way (`607` representatives with `7` cells, about `18000` + extensions) is beyond what the kernel does in about a minute. +-/ + +namespace Math0.Statements.A363609 + +open Finset + +/-! ## The definition -/ + +/-- Unit cells of the cubic lattice: `(x, y, z)` is the cube `[x, x+1] × [y, y+1] × [z, z+1]`. -/ +abbrev Cell := ℤ × ℤ × ℤ + +/-- The six unit vectors `±e₁, ±e₂, ±e₃`: the outward normals of the six faces of a cell. -/ +def dirs : Finset Cell := {(1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0, -1)} + +/-- Dot product on `ℤ³`. -/ +def dot (u v : Cell) : ℤ := u.1 * v.1 + u.2.1 * v.2.1 + u.2.2 * v.2.2 + +/-- Cross product on `ℤ³`. -/ +def cross (u v : Cell) : Cell := + (u.2.1 * v.2.2 - u.2.2 * v.2.1, u.2.2 * v.1 - u.1 * v.2.2, u.1 * v.2.1 - u.2.1 * v.1) + +/-- An orientation of a die: a pair `(u, v)` of perpendicular unit vectors. The face with one pip +has outer normal `u`, the face with two pips has outer normal `v`. -/ +def IsOrientation (o : Cell × Cell) : Prop := o.1 ∈ dirs ∧ o.2 ∈ dirs ∧ dot o.1 o.2 = 0 + +/-- The number of pips on the face with outer normal `d` of a standard die in orientation +`o = (u, v)`: `1` on `u`, `2` on `v`, `3` on `u × v`, and `7 - k` on the face opposite to the face +with `k` pips. (`0` for a vector `d` that is not a face normal.) -/ +def pips (o : Cell × Cell) (d : Cell) : ℕ := + if d = o.1 then 1 else if d = o.2 then 2 else if d = cross o.1 o.2 then 3 + else if d = -cross o.1 o.2 then 4 else if d = -o.2 then 5 else if d = -o.1 then 6 else 0 + +/-- The total number of visible pips of the polycube `P` when the die in cell `c` has orientation +`o c`: the face of `c` with normal `d` is visible iff the neighbouring cell `c + d` is not in `P`. -/ +def visiblePips (P : Finset Cell) (o : Cell → Cell × Cell) : ℕ := + ∑ c ∈ P, ∑ d ∈ dirs, if c + d ∈ P then 0 else pips (o c) d + +/-- `u` and `v` are cells of `P` sharing a face. -/ +def Adj (P : Finset Cell) (u v : Cell) : Prop := u ∈ P ∧ v ∈ P ∧ v - u ∈ dirs + +/-- `P` is face-connected: any two cells of `P` are joined by a chain of face-adjacent cells of +`P`. -/ +def FaceConnected (P : Finset Cell) : Prop := + ∀ x ∈ P, ∀ y ∈ P, Relation.ReflTransGen (Adj P) x y + +/-- The possible totals of visible pips of polycubes made from `n` dice. -/ +def totals (n : ℕ) : Set ℕ := + {t | ∃ P : Finset Cell, P.card = n ∧ FaceConnected P ∧ + ∃ o : Cell → Cell × Cell, (∀ c ∈ P, IsOrientation (o c)) ∧ visiblePips P o = t} + +/-- A363609: the minimum sum of the visible pips on a polycube made from `n` dice. Offset `1`. -/ +noncomputable def a (n : ℕ) : ℕ := sInf (totals n) + +/-! ## Certification + +### Per-die minima -/ + +/-- The face normals as a list. -/ +def dirsL : List Cell := [(1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0, -1)] + +theorem dirsL_nodup : dirsL.Nodup := by decide +kernel + +theorem dirs_eq : dirs = dirsL.toFinset := by decide +kernel + +theorem mem_dirs {d : Cell} : d ∈ dirs ↔ d ∈ dirsL := by rw [dirs_eq, List.mem_toFinset] + +theorem neg_mem_dirs {d : Cell} (h : d ∈ dirs) : -d ∈ dirs := by + rw [mem_dirs] at h ⊢ + simp only [dirsL, List.mem_cons, List.not_mem_nil, or_false] at h + rcases h with rfl | rfl | rfl | rfl | rfl | rfl <;> decide +kernel + +/-- The `24` orientations, as a list. -/ +def orientL : List (Cell × Cell) := + (dirsL.flatMap fun u => dirsL.map fun v => (u, v)).filter fun o => dot o.1 o.2 = 0 + +theorem mem_orientL {o : Cell × Cell} (h : IsOrientation o) : o ∈ orientL := by + obtain ⟨h1, h2, h3⟩ := h + rw [mem_dirs] at h1 h2 + simp only [orientL, List.mem_filter, List.mem_flatMap, List.mem_map, decide_eq_true_eq] + exact ⟨⟨o.1, h1, o.2, h2, rfl⟩, h3⟩ + +theorem isOrientation_of_mem {o : Cell × Cell} (h : o ∈ orientL) : IsOrientation o := by + simp only [orientL, List.mem_filter, List.mem_flatMap, List.mem_map, decide_eq_true_eq] at h + obtain ⟨⟨u, hu, v, hv, rfl⟩, h⟩ := h + exact ⟨mem_dirs.2 hu, mem_dirs.2 hv, h⟩ + +/-- The number of pips shown on the faces with normals in `E` by a die in orientation `o`. -/ +def sumPips (E : List Cell) (o : Cell × Cell) : ℕ := (E.map (pips o)).sum + +/-- A minimiser of `g` among `init` and the elements of `l`. -/ +def argminL {β : Type} (g : β → ℕ) (init : β) (l : List β) : β := + l.foldr (fun o acc => if g o ≤ g acc then o else acc) init + +theorem argminL_spec {β : Type} (g : β → ℕ) (init : β) (l : List β) : + (argminL g init l = init ∨ argminL g init l ∈ l) ∧ g (argminL g init l) ≤ g init ∧ + ∀ o ∈ l, g (argminL g init l) ≤ g o := by + induction l with + | nil => simp [argminL] + | cons b l ih => + simp only [argminL, List.foldr_cons] at ih ⊢ + obtain ⟨h1, h2, h3⟩ := ih + split_ifs with h + · refine ⟨Or.inr List.mem_cons_self, h.trans h2, fun o ho => ?_⟩ + rcases List.mem_cons.1 ho with rfl | ho + · exact le_rfl + · exact h.trans (h3 o ho) + · have h := (not_le.1 h).le + refine ⟨h1.imp id (List.mem_cons_of_mem _), h2, fun o ho => ?_⟩ + rcases List.mem_cons.1 ho with rfl | ho + · exact h + · exact h3 o ho + +/-- An orientation minimising the number of pips shown on the faces with normals in `E`. -/ +def bestOrient (E : List Cell) : Cell × Cell := argminL (sumPips E) ((1, 0, 0), (0, 1, 0)) orientL + +/-- The least number of pips a die can show on the faces with normals in `E`. -/ +def fmin (E : List Cell) : ℕ := sumPips E (bestOrient E) + +theorem fmin_le (E : List Cell) {o : Cell × Cell} (h : IsOrientation o) : fmin E ≤ sumPips E o := + (argminL_spec _ _ _).2.2 o (mem_orientL h) + +theorem isOrientation_bestOrient (E : List Cell) : IsOrientation (bestOrient E) := by + rcases (argminL_spec (sumPips E) ((1, 0, 0), (0, 1, 0)) orientL).1 with h | h + · rw [bestOrient, h] + exact ⟨by decide +kernel, by decide +kernel, by decide +kernel⟩ + · exact isOrientation_of_mem h + +/-- The normals of the faces of the cell `c` that are not covered by a cell of `P`. -/ +def exposed (P : Finset Cell) (c : Cell) : List Cell := dirsL.filter fun d => c + d ∉ P + +/-- The minimum over all orientations of the dice of the number of visible pips of `P`. -/ +def LB (P : Finset Cell) : ℕ := ∑ c ∈ P, fmin (exposed P c) + +theorem sum_dirs_eq (P : Finset Cell) (c : Cell) (o : Cell × Cell) : + (∑ d ∈ dirs, if c + d ∈ P then 0 else pips o d) = sumPips (exposed P c) o := by + rw [dirs_eq, List.sum_toFinset _ dirsL_nodup, sumPips, exposed] + induction dirsL with + | nil => simp + | cons d l ih => by_cases h : c + d ∈ P <;> simp [h, ih] + +theorem LB_le_visiblePips {P : Finset Cell} {o : Cell → Cell × Cell} + (ho : ∀ c ∈ P, IsOrientation (o c)) : LB P ≤ visiblePips P o := by + unfold LB visiblePips + refine Finset.sum_le_sum fun c hc => ?_ + rw [sum_dirs_eq] + exact fmin_le _ (ho c hc) + +theorem visiblePips_best (P : Finset Cell) : + visiblePips P (fun c => bestOrient (exposed P c)) = LB P := by + unfold LB visiblePips + refine Finset.sum_congr rfl fun c _ => ?_ + rw [sum_dirs_eq] + rfl + +theorem LB_mem_totals {P : Finset Cell} {n : ℕ} (hc : P.card = n) (hP : FaceConnected P) : + LB P ∈ totals n := + ⟨P, hc, hP, _, fun _ _ => isOrientation_bestOrient _, visiblePips_best P⟩ + +theorem exists_LB_le {n t : ℕ} (ht : t ∈ totals n) : + ∃ P : Finset Cell, P.card = n ∧ FaceConnected P ∧ LB P ≤ t := by + obtain ⟨P, hc, hP, o, ho, rfl⟩ := ht + exact ⟨P, hc, hP, LB_le_visiblePips ho⟩ + +theorem LB_image_add (P : Finset Cell) (t : Cell) : LB (P.image (· + t)) = LB P := by + unfold LB + rw [Finset.sum_image fun x _ y _ h => add_right_cancel h] + refine Finset.sum_congr rfl fun c _ => ?_ + have key : ∀ d x : Cell, x + t = c + t + d ↔ x = c + d := fun d x => by + rw [add_right_comm c t d] + exact add_left_inj t + unfold exposed + congr 1 + refine List.filter_congr fun d _ => ?_ + simp only [Finset.mem_image, key, exists_eq_right] + +/-! ### Connectivity -/ + +theorem adj_symm {P : Finset Cell} {u v : Cell} (h : Adj P u v) : Adj P v u := + ⟨h.2.1, h.1, by rw [← neg_sub]; exact neg_mem_dirs h.2.2⟩ + +/-- A growth certificate: every cell of the list is face-adjacent to a later cell. -/ +def growsB : List Cell → Bool + | [] => true + | [_] => true + | x :: y :: l => (y :: l).any (fun z => decide (x - z ∈ dirs)) && growsB (y :: l) + +theorem faceConnected_of_growsB : ∀ l : List Cell, growsB l = true → FaceConnected l.toFinset + | [], _ => by intro x hx; simp at hx + | [x], _ => by + intro u hu v hv + simp only [List.toFinset_cons, List.toFinset_nil, insert_empty_eq, mem_singleton] at hu hv + subst hu; subst hv + exact Relation.ReflTransGen.refl + | x :: y :: l, h => by + simp only [growsB, Bool.and_eq_true, List.any_eq_true, decide_eq_true_eq] at h + obtain ⟨⟨z, hz, hxz⟩, h⟩ := h + have IH := faceConnected_of_growsB (y :: l) h + have hP : (x :: y :: l).toFinset = insert x (y :: l).toFinset := List.toFinset_cons + rw [hP] + have hzQ : z ∈ (y :: l).toFinset := List.mem_toFinset.2 hz + have lift : ∀ u ∈ (y :: l).toFinset, ∀ v ∈ (y :: l).toFinset, + Relation.ReflTransGen (Adj (insert x (y :: l).toFinset)) u v := fun u hu v hv => + Relation.ReflTransGen.mono + (fun a b (hab : Adj _ a b) => (⟨mem_insert_of_mem hab.1, mem_insert_of_mem hab.2.1, + hab.2.2⟩ : Adj (insert x (y :: l).toFinset) a b)) u v (IH u hu v hv) + have zx : Adj (insert x (y :: l).toFinset) z x := ⟨mem_insert_of_mem hzQ, mem_insert_self _ _, hxz⟩ + intro u hu v hv + rw [mem_insert] at hu hv + rcases hu with rfl | hu <;> rcases hv with rfl | hv + · exact Relation.ReflTransGen.refl + · exact (Relation.ReflTransGen.single (adj_symm zx)).trans (lift _ hzQ v hv) + · exact (lift u hu _ hzQ).tail zx + · exact lift u hu v hv + +theorem exists_cut {P S : Finset Cell} {a b : Cell} (h : Relation.ReflTransGen (Adj P) a b) + (ha : a ∈ S) (hb : b ∉ S) : ∃ u ∈ S, ∃ v, v ∉ S ∧ Adj P u v := by + induction h with + | refl => exact absurd ha hb + | @tail b c _ hbc ih => + by_cases hb' : b ∈ S + · exact ⟨b, hb', c, hb, hbc⟩ + · exact ih hb' + +theorem exists_growsB {P : Finset Cell} (hP : FaceConnected P) (hne : P.Nonempty) : + ∃ l : List Cell, growsB l = true ∧ l.Nodup ∧ l.toFinset = P := by + obtain ⟨r, hr⟩ := hne + suffices H : ∀ k, ∀ l : List Cell, l ≠ [] → growsB l = true → l.Nodup → l.toFinset ⊆ P → + P.card - l.length = k → ∃ l', growsB l' = true ∧ l'.Nodup ∧ l'.toFinset = P from + H _ [r] (by simp) rfl (List.nodup_singleton r) (by simpa using hr) rfl + intro k + induction k with + | zero => + intro l _ hg hn hs hk + refine ⟨l, hg, hn, Finset.eq_of_subset_of_card_le hs ?_⟩ + rw [List.toFinset_card_of_nodup hn] + omega + | succ k ih => + intro l hl hg hn hs hk + have hlt : l.toFinset ≠ P := by + intro h + rw [← h, List.toFinset_card_of_nodup hn] at hk + omega + obtain ⟨y, hyP, hyl⟩ : ∃ y ∈ P, y ∉ l.toFinset := by + by_contra hc + refine hlt (Finset.Subset.antisymm hs fun y hy => ?_) + by_contra hy' + exact hc ⟨y, hy, hy'⟩ + obtain ⟨x, hxl⟩ := List.exists_mem_of_ne_nil l hl + have hxP : x ∈ P := hs (List.mem_toFinset.2 hxl) + obtain ⟨u, hu, v, hv, huv⟩ := exists_cut (hP x hxP y hyP) (List.mem_toFinset.2 hxl) hyl + refine ih (v :: l) (by simp) ?_ ?_ ?_ ?_ + · obtain ⟨w, l', rfl⟩ := List.exists_cons_of_ne_nil hl + simp only [growsB, Bool.and_eq_true, hg, and_true, List.any_eq_true, decide_eq_true_eq] + exact ⟨u, List.mem_toFinset.1 hu, huv.2.2⟩ + · exact List.nodup_cons.2 ⟨fun h => hv (List.mem_toFinset.2 h), hn⟩ + · intro w hw + rcases List.mem_cons.1 (List.mem_toFinset.1 hw) with rfl | hw + · exact huv.2.1 + · exact hs (List.mem_toFinset.2 hw) + · simp only [List.length_cons] + omega + +/-- A face-connected polycube with at least two cells has a cell `x`, adjacent to a cell `z` of +the rest `Q`, such that `Q` is still face-connected. -/ +theorem exists_leaf {P : Finset Cell} (hP : FaceConnected P) (h2 : 2 ≤ P.card) : + ∃ x Q z, P = insert x Q ∧ x ∉ Q ∧ FaceConnected Q ∧ z ∈ Q ∧ x - z ∈ dirs := by + obtain ⟨l, hg, hn, rfl⟩ := exists_growsB hP (Finset.card_pos.1 (by omega)) + rw [List.toFinset_card_of_nodup hn] at h2 + match l, hg, hn, h2 with + | x :: y :: l, hg, hn, _ => + simp only [growsB, Bool.and_eq_true, List.any_eq_true, decide_eq_true_eq] at hg + obtain ⟨⟨z, hz, hxz⟩, hg⟩ := hg + exact ⟨x, (y :: l).toFinset, z, List.toFinset_cons, + fun h => (List.nodup_cons.1 hn).1 (List.mem_toFinset.1 h), + faceConnected_of_growsB _ hg, List.mem_toFinset.2 hz, hxz⟩ + +/-! ### Cells encoded as natural numbers + +For the kernel computations a cell `(x, y, z)` with `0 ≤ x, y < 32`, `0 ≤ z` is encoded as +`x + 32 y + 1024 z`. -/ + +/-- Decoding: `dec k = (k % 32, k / 32 % 32, k / 1024)`. -/ +def dec (k : ℕ) : Cell := (((k % 32 : ℕ) : ℤ), ((k / 32 % 32 : ℕ) : ℤ), ((k / 1024 : ℕ) : ℤ)) + +/-- The set of cells encoded by a list of codes. -/ +def D (L : List ℕ) : Finset Cell := (L.map dec).toFinset + +theorem dec_inj : Function.Injective dec := by + intro a b h + simp only [dec, Prod.mk.injEq, Nat.cast_inj] at h + omega + +/-- Codes whose six neighbours are computed by adding `±1, ±32, ±1024`. -/ +def good (k : ℕ) : Bool := + 1 ≤ k % 32 && k % 32 ≤ 30 && 1 ≤ k / 32 % 32 && k / 32 % 32 ≤ 30 && 1 ≤ k / 1024 + +/-- The codes of the six neighbours, in the order of `dirsL`. -/ +def nbrs (k : ℕ) : List ℕ := [k + 1, k - 1, k + 32, k - 32, k + 1024, k - 1024] + +theorem dec_nbrs {k : ℕ} (hk : good k = true) : (nbrs k).map dec = dirsL.map (dec k + ·) := by + simp only [good, Bool.and_eq_true, decide_eq_true_eq] at hk + simp only [nbrs, dirsL, List.map_cons, List.map_nil, List.cons.injEq, and_true, dec, + Prod.mk_add_mk, Prod.mk.injEq] + omega + +theorem mem_D {L : List ℕ} {k : ℕ} : dec k ∈ D L ↔ k ∈ L := by + simp only [D, List.mem_toFinset, List.mem_map, dec_inj.eq_iff, exists_eq_right] + +/-! ### The value of a list of codes -/ + +/-- `fmin` as a table: the arguments say which of the six faces (in the order of `dirsL`) are +exposed. -/ +def tabF : Bool → Bool → Bool → Bool → Bool → Bool → ℕ + | false, false, false, false, false, false => 0 + | true, false, false, false, false, false => 1 + | false, true, false, false, false, false => 1 + | true, true, false, false, false, false => 7 + | false, false, true, false, false, false => 1 + | true, false, true, false, false, false => 3 + | false, true, true, false, false, false => 3 + | true, true, true, false, false, false => 8 + | false, false, false, true, false, false => 1 + | true, false, false, true, false, false => 3 + | false, true, false, true, false, false => 3 + | true, true, false, true, false, false => 8 + | false, false, true, true, false, false => 7 + | true, false, true, true, false, false => 8 + | false, true, true, true, false, false => 8 + | true, true, true, true, false, false => 14 + | false, false, false, false, true, false => 1 + | true, false, false, false, true, false => 3 + | false, true, false, false, true, false => 3 + | true, true, false, false, true, false => 8 + | false, false, true, false, true, false => 3 + | true, false, true, false, true, false => 6 + | false, true, true, false, true, false => 6 + | true, true, true, false, true, false => 10 + | false, false, false, true, true, false => 3 + | true, false, false, true, true, false => 6 + | false, true, false, true, true, false => 6 + | true, true, false, true, true, false => 10 + | false, false, true, true, true, false => 8 + | true, false, true, true, true, false => 10 + | false, true, true, true, true, false => 10 + | true, true, true, true, true, false => 15 + | false, false, false, false, false, true => 1 + | true, false, false, false, false, true => 3 + | false, true, false, false, false, true => 3 + | true, true, false, false, false, true => 8 + | false, false, true, false, false, true => 3 + | true, false, true, false, false, true => 6 + | false, true, true, false, false, true => 6 + | true, true, true, false, false, true => 10 + | false, false, false, true, false, true => 3 + | true, false, false, true, false, true => 6 + | false, true, false, true, false, true => 6 + | true, true, false, true, false, true => 10 + | false, false, true, true, false, true => 8 + | true, false, true, true, false, true => 10 + | false, true, true, true, false, true => 10 + | true, true, true, true, false, true => 15 + | false, false, false, false, true, true => 7 + | true, false, false, false, true, true => 8 + | false, true, false, false, true, true => 8 + | true, true, false, false, true, true => 14 + | false, false, true, false, true, true => 8 + | true, false, true, false, true, true => 10 + | false, true, true, false, true, true => 10 + | true, true, true, false, true, true => 15 + | false, false, false, true, true, true => 8 + | true, false, false, true, true, true => 10 + | false, true, false, true, true, true => 10 + | true, true, false, true, true, true => 15 + | false, false, true, true, true, true => 14 + | true, false, true, true, true, true => 15 + | false, true, true, true, true, true => 15 + | true, true, true, true, true, true => 21 + +/-- The sublist of `dirsL` selected by six booleans. -/ +def sel (b0 b1 b2 b3 b4 b5 : Bool) : List Cell := + dirsL.filter fun d => (d == (1, 0, 0) && b0) || (d == (-1, 0, 0) && b1) || + (d == (0, 1, 0) && b2) || (d == (0, -1, 0) && b3) || (d == (0, 0, 1) && b4) || + (d == (0, 0, -1) && b5) + +theorem fmin_sel : ∀ b0 b1 b2 b3 b4 b5 : Bool, + fmin (sel b0 b1 b2 b3 b4 b5) = tabF b0 b1 b2 b3 b4 b5 := by decide +kernel + +theorem filter_dirsL (p : Cell → Bool) : + dirsL.filter p = sel (p (1, 0, 0)) (p (-1, 0, 0)) (p (0, 1, 0)) (p (0, -1, 0)) (p (0, 0, 1)) + (p (0, 0, -1)) := by + simp only [sel, dirsL, List.filter_cons, List.filter_nil] + cases p (1, 0, 0) <;> cases p (-1, 0, 0) <;> cases p (0, 1, 0) <;> cases p (0, -1, 0) <;> + cases p (0, 0, 1) <;> cases p (0, 0, -1) <;> decide +kernel + +/-- A bitmask of the codes in `L`. -/ +def maskOf (L : List ℕ) : ℕ := L.foldr (fun k m => m ||| 2 ^ k) 0 + +theorem testBit_maskOf (L : List ℕ) (j : ℕ) : (maskOf L).testBit j = decide (j ∈ L) := by + induction L with + | nil => simp [maskOf] + | cons k L ih => + simp only [maskOf, List.foldr_cons] at ih ⊢ + rw [Nat.testBit_or, ih, Nat.testBit_two_pow] + by_cases h : j = k + · subst h; simp + · simp [h, Ne.symm h] + +/-- The least number of visible pips of the die with code `k`, in the polycube with bitmask +`M`. -/ +def cellVal (M k : ℕ) : ℕ := + tabF (!M.testBit (k + 1)) (!M.testBit (k - 1)) (!M.testBit (k + 32)) (!M.testBit (k - 32)) + (!M.testBit (k + 1024)) (!M.testBit (k - 1024)) + +/-- `LB` of the polycube encoded by `L`, computed on codes. -/ +def valW (L : List ℕ) : ℕ := (L.map (cellVal (maskOf L))).sum + +theorem cellVal_eq {L : List ℕ} {k : ℕ} (hk : good k = true) : + cellVal (maskOf L) k = fmin (exposed (D L) (dec k)) := by + have h := dec_nbrs hk + simp only [nbrs, dirsL, List.map_cons, List.map_nil, List.cons.injEq, and_true] at h + obtain ⟨h1, h2, h3, h4, h5, h6⟩ := h + rw [exposed, filter_dirsL, fmin_sel, cellVal] + simp only [testBit_maskOf, ← h1, ← h2, ← h3, ← h4, ← h5, ← h6, mem_D, decide_not] + +theorem valW_eq {L : List ℕ} (hn : L.Nodup) (hg : ∀ k ∈ L, good k = true) : + valW L = LB (D L) := by + rw [LB, D, List.sum_toFinset _ (hn.map dec_inj), List.map_map, valW] + congr 1 + refine List.map_congr_left fun k hk => ?_ + rw [Function.comp_apply, cellVal_eq (hg k hk)] + rfl + +/-! ### Upper bounds from witnesses -/ + +/-- Whether two codes are face-adjacent. -/ +def isNbr (j k : ℕ) : Bool := + j == k + 1 || k == j + 1 || j == k + 32 || k == j + 32 || j == k + 1024 || k == j + 1024 + +/-- A growth certificate on codes: every code is adjacent to a later one. -/ +def growsC : List ℕ → Bool + | [] => true + | [_] => true + | x :: y :: l => (y :: l).any (isNbr x) && growsC (y :: l) + +/-- The list is strictly decreasing. -/ +def sdesc : List ℕ → Bool + | [] => true + | [_] => true + | x :: y :: l => Nat.blt y x && sdesc (y :: l) + +theorem sdesc_lt : ∀ {x : ℕ} {l : List ℕ}, sdesc (x :: l) = true → ∀ z ∈ l, z < x + | _, [], _, z, hz => absurd hz List.not_mem_nil + | x, y :: l, h, z, hz => by + simp only [sdesc, Bool.and_eq_true, Nat.blt_eq] at h + rcases List.mem_cons.1 hz with rfl | hz + · exact h.1 + · exact (sdesc_lt h.2 z hz).trans h.1 + +theorem sdesc_nodup : ∀ {l : List ℕ}, sdesc l = true → l.Nodup + | [], _ => List.nodup_nil + | [x], _ => List.nodup_singleton x + | x :: y :: l, h => by + refine List.nodup_cons.2 ⟨fun hx => lt_irrefl x (sdesc_lt h x hx), sdesc_nodup ?_⟩ + simp only [sdesc, Bool.and_eq_true] at h + exact h.2 + +theorem dec_sub_mem_dirs {j k : ℕ} (hj : good j = true) (hk : good k = true) + (h : isNbr j k = true) : dec j - dec k ∈ dirs := by + have hj' := dec_nbrs hj + have hk' := dec_nbrs hk + simp only [nbrs, dirsL, List.map_cons, List.map_nil, List.cons.injEq, and_true] at hj' hk' + simp only [isNbr, Bool.or_eq_true, beq_iff_eq] at h + rcases h with ((((h | h) | h) | h) | h) | h <;> subst h + · rw [hk'.1, add_sub_cancel_left]; decide +kernel + · rw [hj'.1, sub_add_cancel_left]; decide +kernel + · rw [hk'.2.2.1, add_sub_cancel_left]; decide +kernel + · rw [hj'.2.2.1, sub_add_cancel_left]; decide +kernel + · rw [hk'.2.2.2.2.1, add_sub_cancel_left]; decide +kernel + · rw [hj'.2.2.2.2.1, sub_add_cancel_left]; decide +kernel + +theorem growsB_of_growsC : ∀ {L : List ℕ}, growsC L = true → (∀ k ∈ L, good k = true) → + growsB (L.map dec) = true + | [], _, _ => rfl + | [_], _, _ => rfl + | x :: y :: l, h, hg => by + simp only [growsC, Bool.and_eq_true, List.any_eq_true] at h + obtain ⟨⟨z, hz, hxz⟩, h⟩ := h + simp only [List.map_cons, growsB, Bool.and_eq_true, List.any_eq_true, decide_eq_true_eq] + refine ⟨⟨dec z, ?_, dec_sub_mem_dirs (hg x List.mem_cons_self) (hg z + (List.mem_cons_of_mem _ hz)) hxz⟩, ?_⟩ + · rw [← List.map_cons]; exact List.mem_map_of_mem hz + · rw [← List.map_cons] + exact growsB_of_growsC h fun k hk => hg k (List.mem_cons_of_mem _ hk) + +/-- A witness `(n, v, L)`: `L` encodes a polycube with `n` cells whose least number of visible +pips is `v`. -/ +def witOK (e : ℕ × ℕ × List ℕ) : Bool := + e.2.2.length == e.1 && sdesc e.2.2 && e.2.2.all good && growsC e.2.2 && valW e.2.2 == e.2.1 + +theorem mem_totals_of_witOK {e : ℕ × ℕ × List ℕ} (h : witOK e = true) : e.2.1 ∈ totals e.1 := by + obtain ⟨n, v, L⟩ := e + simp only [witOK, Bool.and_eq_true, beq_iff_eq, List.all_eq_true] at h + obtain ⟨⟨⟨⟨hl, hs⟩, hg⟩, hgr⟩, hv⟩ := h + have hn := sdesc_nodup hs + have hmem : LB (D L) ∈ totals n := by + refine LB_mem_totals ?_ ?_ + · rw [D, List.toFinset_card_of_nodup (hn.map dec_inj), List.length_map, hl] + · exact faceConnected_of_growsB _ (growsB_of_growsC hgr hg) + rwa [← valW_eq hn hg, hv] at hmem + +/-- Witnesses for the terms `a(1), …, a(57)` listed in the entry. -/ +def wits : List (ℕ × ℕ × List ℕ) := [ + (1, 21, [1057]), + (2, 30, [2081, 1057]), + (3, 40, [2081, 1089, 1057]), + (4, 40, [2113, 2081, 1089, 1057]), + (5, 51, [2081, 1090, 1089, 1058, 1057]), + (6, 52, [2082, 2081, 1090, 1089, 1058, 1057]), + (7, 54, [2113, 2082, 2081, 1090, 1089, 1058, 1057]), + (8, 48, [2114, 2113, 2082, 2081, 1090, 1089, 1058, 1057]), + (9, 60, [3105, 2114, 2113, 2082, 2081, 1090, 1089, 1058, 1057]), + (10, 62, [3106, 3105, 2114, 2113, 2082, 2081, 1090, 1089, 1058, 1057]), + (11, 65, [3137, 3106, 3105, 2114, 2113, 2082, 2081, 1090, 1089, 1058, 1057]), + (12, 60, [3138, 3137, 3106, 3105, 2114, 2113, 2082, 2081, 1090, 1089, 1058, 1057]), + (13, 72, [4129, 3138, 3137, 3106, 3105, 2114, 2113, 2082, 2081, 1090, 1089, 1058, 1057]), + (14, 74, [4130, 4129, 3138, 3137, 3106, 3105, 2114, 2113, 2082, 2081, 1090, 1089, 1058, 1057]), + (15, 77, [4161, 4130, 4129, 3138, 3137, 3106, 3105, 2114, 2113, 2082, 2081, 1090, 1089, 1058, + 1057]), + (16, 72, [4162, 4161, 4130, 4129, 3138, 3137, 3106, 3105, 2114, 2113, 2082, 2081, 1090, 1089, + 1058, 1057]), + (17, 78, [3169, 3138, 3137, 3106, 3105, 2146, 2145, 2114, 2113, 2082, 2081, 1122, 1121, 1090, + 1089, 1058, 1057]), + (18, 74, [3170, 3169, 3138, 3137, 3106, 3105, 2146, 2145, 2114, 2113, 2082, 2081, 1122, 1121, + 1090, 1089, 1058, 1057]), + (19, 86, [4129, 3170, 3169, 3138, 3137, 3106, 3105, 2146, 2145, 2114, 2113, 2082, 2081, 1122, + 1121, 1090, 1089, 1058, 1057]), + (20, 84, [5186, 5185, 5154, 5153, 4162, 4161, 4130, 4129, 3138, 3137, 3106, 3105, 2114, 2113, + 2082, 2081, 1090, 1089, 1058, 1057]), + (21, 91, [3169, 3138, 3137, 3106, 3105, 2178, 2177, 2146, 2145, 2114, 2113, 2082, 2081, 1154, + 1153, 1122, 1121, 1090, 1089, 1058, 1057]), + (22, 88, [4162, 4161, 4130, 4129, 3170, 3169, 3138, 3137, 3106, 3105, 2146, 2145, 2114, 2113, + 2082, 2081, 1122, 1121, 1090, 1089, 1058, 1057]), + (23, 92, [4193, 4162, 4161, 4130, 4129, 3170, 3169, 3138, 3137, 3106, 3105, 2146, 2145, 2114, + 2113, 2082, 2081, 1122, 1121, 1090, 1089, 1058, 1057]), + (24, 88, [4194, 4193, 4162, 4161, 4130, 4129, 3170, 3169, 3138, 3137, 3106, 3105, 2146, 2145, + 2114, 2113, 2082, 2081, 1122, 1121, 1090, 1089, 1058, 1057]), + (25, 95, [3169, 3139, 3138, 3137, 3107, 3106, 3105, 2147, 2146, 2145, 2115, 2114, 2113, 2083, + 2082, 2081, 1123, 1122, 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (26, 93, [3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2147, 2146, 2145, 2115, 2114, 2113, + 2083, 2082, 2081, 1123, 1122, 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (27, 90, [3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2147, 2146, 2145, 2115, 2114, + 2113, 2083, 2082, 2081, 1123, 1122, 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (28, 102, [5186, 5185, 5154, 5153, 4194, 4193, 4162, 4161, 4130, 4129, 3170, 3169, 3138, 3137, + 3106, 3105, 2146, 2145, 2114, 2113, 2082, 2081, 1122, 1121, 1090, 1089, 1058, 1057]), + (29, 105, [4130, 4129, 3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2147, 2146, 2145, + 2115, 2114, 2113, 2083, 2082, 2081, 1123, 1122, 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (30, 102, [5218, 5217, 5186, 5185, 5154, 5153, 4194, 4193, 4162, 4161, 4130, 4129, 3170, 3169, + 3138, 3137, 3106, 3105, 2146, 2145, 2114, 2113, 2082, 2081, 1122, 1121, 1090, 1089, 1058, + 1057]), + (31, 106, [4195, 4194, 4163, 4162, 3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2147, + 2146, 2145, 2115, 2114, 2113, 2083, 2082, 2081, 1123, 1122, 1121, 1091, 1090, 1089, 1059, + 1058, 1057]), + (32, 104, [4226, 4225, 4194, 4193, 4162, 4161, 4130, 4129, 3202, 3201, 3170, 3169, 3138, 3137, + 3106, 3105, 2178, 2177, 2146, 2145, 2114, 2113, 2082, 2081, 1154, 1153, 1122, 1121, 1090, + 1089, 1058, 1057]), + (33, 107, [4163, 4162, 4161, 4131, 4130, 4129, 3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, + 3105, 2147, 2146, 2145, 2115, 2114, 2113, 2083, 2082, 2081, 1123, 1122, 1121, 1091, 1090, + 1089, 1059, 1058, 1057]), + (34, 110, [3170, 3169, 3140, 3139, 3138, 3137, 3108, 3107, 3106, 3105, 2148, 2147, 2146, 2145, + 2116, 2115, 2114, 2113, 2084, 2083, 2082, 2081, 1124, 1123, 1122, 1121, 1092, 1091, 1090, + 1089, 1060, 1059, 1058, 1057]), + (35, 109, [4194, 4193, 4163, 4162, 4161, 4131, 4130, 4129, 3171, 3170, 3169, 3139, 3138, 3137, + 3107, 3106, 3105, 2147, 2146, 2145, 2115, 2114, 2113, 2083, 2082, 2081, 1123, 1122, 1121, + 1091, 1090, 1089, 1059, 1058, 1057]), + (36, 106, [4195, 4194, 4193, 4163, 4162, 4161, 4131, 4130, 4129, 3171, 3170, 3169, 3139, 3138, + 3137, 3107, 3106, 3105, 2147, 2146, 2145, 2115, 2114, 2113, 2083, 2082, 2081, 1123, 1122, + 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (37, 118, [5153, 4195, 4194, 4193, 4163, 4162, 4161, 4131, 4130, 4129, 3171, 3170, 3169, 3139, + 3138, 3137, 3107, 3106, 3105, 2147, 2146, 2145, 2115, 2114, 2113, 2083, 2082, 2081, 1123, + 1122, 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (38, 120, [5218, 5217, 5186, 5185, 5154, 5153, 4226, 4225, 4194, 4193, 4162, 4161, 4130, 4129, + 3202, 3201, 3170, 3169, 3138, 3137, 3106, 3105, 2178, 2177, 2146, 2145, 2114, 2113, 2082, + 2081, 1154, 1153, 1122, 1121, 1090, 1089, 1058, 1057]), + (39, 121, [3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2211, 2210, 2209, 2179, 2178, + 2177, 2147, 2146, 2145, 2115, 2114, 2113, 2083, 2082, 2081, 1187, 1186, 1185, 1155, 1154, + 1153, 1123, 1122, 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (40, 120, [5250, 5249, 5218, 5217, 5186, 5185, 5154, 5153, 4226, 4225, 4194, 4193, 4162, 4161, + 4130, 4129, 3202, 3201, 3170, 3169, 3138, 3137, 3106, 3105, 2178, 2177, 2146, 2145, 2114, + 2113, 2082, 2081, 1154, 1153, 1122, 1121, 1090, 1089, 1058, 1057]), + (41, 125, [3202, 3201, 3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2211, 2210, 2209, + 2179, 2178, 2177, 2147, 2146, 2145, 2115, 2114, 2113, 2083, 2082, 2081, 1187, 1186, 1185, + 1155, 1154, 1153, 1123, 1122, 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (42, 123, [5187, 5186, 5185, 5155, 5154, 5153, 4195, 4194, 4193, 4163, 4162, 4161, 4131, 4130, + 4129, 3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2147, 2146, 2145, 2115, 2114, + 2113, 2083, 2082, 2081, 1123, 1122, 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (43, 126, [3171, 3170, 3169, 3141, 3140, 3139, 3138, 3137, 3109, 3108, 3107, 3106, 3105, 2149, + 2148, 2147, 2146, 2145, 2117, 2116, 2115, 2114, 2113, 2085, 2084, 2083, 2082, 2081, 1125, + 1124, 1123, 1122, 1121, 1093, 1092, 1091, 1090, 1089, 1061, 1060, 1059, 1058, 1057]), + (44, 125, [5218, 5217, 5187, 5186, 5185, 5155, 5154, 5153, 4195, 4194, 4193, 4163, 4162, 4161, + 4131, 4130, 4129, 3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2147, 2146, 2145, + 2115, 2114, 2113, 2083, 2082, 2081, 1123, 1122, 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (45, 122, [5219, 5218, 5217, 5187, 5186, 5185, 5155, 5154, 5153, 4195, 4194, 4193, 4163, 4162, + 4161, 4131, 4130, 4129, 3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2147, 2146, + 2145, 2115, 2114, 2113, 2083, 2082, 2081, 1123, 1122, 1121, 1091, 1090, 1089, 1059, 1058, + 1057]), + (46, 128, [4194, 4193, 4164, 4163, 4162, 4161, 4132, 4131, 4130, 4129, 3172, 3171, 3170, 3169, + 3140, 3139, 3138, 3137, 3108, 3107, 3106, 3105, 2148, 2147, 2146, 2145, 2116, 2115, 2114, + 2113, 2084, 2083, 2082, 2081, 1124, 1123, 1122, 1121, 1092, 1091, 1090, 1089, 1060, 1059, + 1058, 1057]), + (47, 127, [4226, 4225, 4195, 4194, 4193, 4163, 4162, 4161, 4131, 4130, 4129, 3203, 3202, 3201, + 3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2179, 2178, 2177, 2147, 2146, 2145, + 2115, 2114, 2113, 2083, 2082, 2081, 1155, 1154, 1153, 1123, 1122, 1121, 1091, 1090, 1089, + 1059, 1058, 1057]), + (48, 124, [4227, 4226, 4225, 4195, 4194, 4193, 4163, 4162, 4161, 4131, 4130, 4129, 3203, 3202, + 3201, 3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2179, 2178, 2177, 2147, 2146, + 2145, 2115, 2114, 2113, 2083, 2082, 2081, 1155, 1154, 1153, 1123, 1122, 1121, 1091, 1090, + 1089, 1059, 1058, 1057]), + (49, 136, [5153, 4227, 4226, 4225, 4195, 4194, 4193, 4163, 4162, 4161, 4131, 4130, 4129, 3203, + 3202, 3201, 3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2179, 2178, 2177, 2147, + 2146, 2145, 2115, 2114, 2113, 2083, 2082, 2081, 1155, 1154, 1153, 1123, 1122, 1121, 1091, + 1090, 1089, 1059, 1058, 1057]), + (50, 138, [5282, 5281, 5250, 5249, 5218, 5217, 5186, 5185, 5154, 5153, 4258, 4257, 4226, 4225, + 4194, 4193, 4162, 4161, 4130, 4129, 3234, 3233, 3202, 3201, 3170, 3169, 3138, 3137, 3106, + 3105, 2210, 2209, 2178, 2177, 2146, 2145, 2114, 2113, 2082, 2081, 1186, 1185, 1154, 1153, + 1122, 1121, 1090, 1089, 1058, 1057]), + (51, 139, [6211, 6210, 6209, 6179, 6178, 6177, 5219, 5218, 5217, 5187, 5186, 5185, 5155, 5154, + 5153, 4195, 4194, 4193, 4163, 4162, 4161, 4131, 4130, 4129, 3171, 3170, 3169, 3139, 3138, + 3137, 3107, 3106, 3105, 2147, 2146, 2145, 2115, 2114, 2113, 2083, 2082, 2081, 1123, 1122, + 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (52, 140, [4227, 4226, 4225, 4195, 4194, 4193, 4163, 4162, 4161, 4131, 4130, 4129, 3203, 3202, + 3201, 3171, 3170, 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2179, 2178, 2177, 2147, 2146, + 2145, 2116, 2115, 2114, 2113, 2084, 2083, 2082, 2081, 1155, 1154, 1153, 1123, 1122, 1121, + 1092, 1091, 1090, 1089, 1060, 1059, 1058, 1057]), + (53, 141, [6242, 6241, 6211, 6210, 6209, 6179, 6178, 6177, 5219, 5218, 5217, 5187, 5186, 5185, + 5155, 5154, 5153, 4195, 4194, 4193, 4163, 4162, 4161, 4131, 4130, 4129, 3171, 3170, 3169, + 3139, 3138, 3137, 3107, 3106, 3105, 2147, 2146, 2145, 2115, 2114, 2113, 2083, 2082, 2081, + 1123, 1122, 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (54, 138, [6243, 6242, 6241, 6211, 6210, 6209, 6179, 6178, 6177, 5219, 5218, 5217, 5187, 5186, + 5185, 5155, 5154, 5153, 4195, 4194, 4193, 4163, 4162, 4161, 4131, 4130, 4129, 3171, 3170, + 3169, 3139, 3138, 3137, 3107, 3106, 3105, 2147, 2146, 2145, 2115, 2114, 2113, 2083, 2082, + 2081, 1123, 1122, 1121, 1091, 1090, 1089, 1059, 1058, 1057]), + (55, 145, [4165, 4164, 4163, 4162, 4161, 4133, 4132, 4131, 4130, 4129, 3173, 3172, 3171, 3170, + 3169, 3141, 3140, 3139, 3138, 3137, 3109, 3108, 3107, 3106, 3105, 2149, 2148, 2147, 2146, + 2145, 2117, 2116, 2115, 2114, 2113, 2085, 2084, 2083, 2082, 2081, 1125, 1124, 1123, 1122, + 1121, 1093, 1092, 1091, 1090, 1089, 1061, 1060, 1059, 1058, 1057]), + (56, 144, [5188, 5187, 5186, 5185, 5156, 5155, 5154, 5153, 4196, 4195, 4194, 4193, 4164, 4163, + 4162, 4161, 4132, 4131, 4130, 4129, 3172, 3171, 3170, 3169, 3140, 3139, 3138, 3137, 3108, + 3107, 3106, 3105, 2148, 2147, 2146, 2145, 2116, 2115, 2114, 2113, 2084, 2083, 2082, 2081, + 1124, 1123, 1122, 1121, 1092, 1091, 1090, 1089, 1060, 1059, 1058, 1057]), + (57, 143, [5219, 5218, 5217, 5187, 5186, 5185, 5155, 5154, 5153, 4227, 4226, 4225, 4195, 4194, + 4193, 4163, 4162, 4161, 4131, 4130, 4129, 3203, 3202, 3201, 3171, 3170, 3169, 3139, 3138, + 3137, 3107, 3106, 3105, 2179, 2178, 2177, 2147, 2146, 2145, 2115, 2114, 2113, 2083, 2082, + 2081, 1155, 1154, 1153, 1123, 1122, 1121, 1091, 1090, 1089, 1059, 1058, 1057])] + +theorem wits_ok : wits.all witOK = true := by decide +kernel + +/-! ### Normalised lists of codes -/ + +/-- Insert into a sorted list. -/ +def ins (k : ℕ) : List ℕ → List ℕ + | [] => [k] + | a :: l => if k ≤ a then k :: a :: l else a :: ins k l + +/-- Insertion sort. -/ +def insSort (L : List ℕ) : List ℕ := L.foldr ins [] + +/-- Translate the polycube so that its first code becomes `16912 = dec⁻¹ (16, 16, 16)`. -/ +def normC (M : List ℕ) : List ℕ := M.map fun k => k + 16912 - M.headD 0 + +/-- The least value of `valW` on a list of polycubes. -/ +def minVal (ps : List (List ℕ)) : ℕ := ps.foldr (fun L acc => min (valW L) acc) 100000 + +/-- Codes of cells with all coordinates in `[10, 22]`. -/ +def goodT (k : ℕ) : Bool := + 10 ≤ k % 32 && k % 32 ≤ 22 && 10 ≤ k / 32 % 32 && k / 32 % 32 ≤ 22 && 10 ≤ k / 1024 && + k / 1024 ≤ 22 + +/-- Codes of cells with all coordinates in `[9, 23]`. -/ +def Near (k : ℕ) : Prop := + 9 ≤ k % 32 ∧ k % 32 ≤ 23 ∧ 9 ≤ k / 32 % 32 ∧ k / 32 % 32 ≤ 23 ∧ 9 ≤ k / 1024 ∧ k / 1024 ≤ 23 + +theorem near_of_goodT {k : ℕ} (h : goodT k = true) : Near k := by + simp only [goodT, Bool.and_eq_true, decide_eq_true_eq] at h + unfold Near + omega + +theorem good_of_near {k : ℕ} (h : Near k) : good k = true := by + unfold Near at h + simp only [good, Bool.and_eq_true, decide_eq_true_eq] + omega + +theorem near_of_mem_nbrs {k j : ℕ} (h : goodT k = true) (hj : j ∈ nbrs k) : Near j := by + simp only [goodT, Bool.and_eq_true, decide_eq_true_eq] at h + simp only [nbrs, List.mem_cons, List.not_mem_nil, or_false] at hj + unfold Near + omega + +theorem dec_shift {k h : ℕ} (hk : Near k) (hh : Near h) : + dec (k + 16912 - h) = dec k + ((16, 16, 16) - dec h) := by + unfold Near at hk hh + simp only [dec, Prod.mk_add_mk, Prod.mk_sub_mk, Prod.mk.injEq] + omega + +theorem mem_D_iff {L : List ℕ} {c : Cell} : c ∈ D L ↔ ∃ k ∈ L, dec k = c := by + simp only [D, List.mem_toFinset, List.mem_map] + +theorem D_normC {M : List ℕ} (hM : M ≠ []) (hn : ∀ k ∈ M, Near k) : + D (normC M) = (D M).image (· + ((16, 16, 16) - dec (M.headD 0))) := by + have hh : M.headD 0 ∈ M := by + obtain ⟨x, l, rfl⟩ := List.exists_cons_of_ne_nil hM + exact List.mem_cons_self + ext c + simp only [D, normC, List.map_map, List.mem_toFinset, List.mem_map, Function.comp_apply, + Finset.mem_image] + constructor + · rintro ⟨k, hk, rfl⟩ + exact ⟨dec k, ⟨k, hk, rfl⟩, (dec_shift (hn k hk) (hn _ hh)).symm⟩ + · rintro ⟨y, ⟨k, hk, rfl⟩, rfl⟩ + exact ⟨k, hk, dec_shift (hn k hk) (hn _ hh)⟩ + +theorem mem_ins {k x : ℕ} : ∀ {L : List ℕ}, x ∈ ins k L ↔ x = k ∨ x ∈ L + | [] => by simp [ins] + | a :: l => by + simp only [ins] + split_ifs + · simp + · simp only [List.mem_cons, mem_ins] + tauto + +theorem ins_perm (k : ℕ) : ∀ L : List ℕ, (ins k L).Perm (k :: L) + | [] => by simp [ins] + | a :: l => by + simp only [ins] + split_ifs + · exact List.Perm.refl _ + · exact ((ins_perm k l).cons a).trans (List.Perm.swap k a l) + +theorem ins_ne_nil (k : ℕ) : ∀ L : List ℕ, ins k L ≠ [] + | [] => by simp [ins] + | a :: l => by simp only [ins]; split_ifs <;> simp + +theorem mem_insSort {x : ℕ} : ∀ {L : List ℕ}, x ∈ insSort L ↔ x ∈ L + | [] => by simp [insSort] + | a :: L => by + show x ∈ ins a (insSort L) ↔ x ∈ a :: L + rw [mem_ins, mem_insSort, List.mem_cons] + +theorem insSort_ne_nil : ∀ {L : List ℕ}, L ≠ [] → insSort L ≠ [] + | [], h => absurd rfl h + | a :: L, _ => ins_ne_nil a (insSort L) + +theorem D_insSort (L : List ℕ) : D (insSort L) = D L := by + ext c + simp only [mem_D_iff, mem_insSort] + +theorem D_ins (j : ℕ) (L : List ℕ) : D (ins j L) = insert (dec j) (D L) := by + ext c + simp only [D, List.mem_toFinset, List.mem_map, mem_insert, mem_ins] + constructor + · rintro ⟨k, rfl | hk, rfl⟩ + · exact Or.inl rfl + · exact Or.inr ⟨k, hk, rfl⟩ + · rintro (rfl | ⟨k, hk, rfl⟩) + · exact ⟨j, Or.inl rfl, rfl⟩ + · exact ⟨k, Or.inr hk, rfl⟩ + +theorem minVal_le {ps : List (List ℕ)} {L : List ℕ} (h : L ∈ ps) : minVal ps ≤ valW L := by + induction ps with + | nil => simp at h + | cons M ps ih => + simp only [minVal, List.foldr_cons] at ih ⊢ + rcases List.mem_cons.1 h with rfl | h + · exact min_le_left _ _ + · exact (min_le_right _ _).trans (ih h) + +/-! ### Symmetries + +`G 0`, `G 1`, `G 2` are the isometries `(x, y, z) ↦ (y, x, z)`, `(x, y, z) ↦ (y, z, x)` and +`(x, y, z) ↦ (32 - x, y, z)` of the lattice. Together with the translations they generate all +symmetries of the lattice. A map `h` is *admissible* (`Adm h`) if it is injective, preserves +face-adjacency and does not change `LB`. -/ + +theorem fmin_exposed (P : Finset Cell) (c : Cell) : + fmin (exposed P c) = tabF (decide (c + (1, 0, 0) ∉ P)) (decide (c + (-1, 0, 0) ∉ P)) + (decide (c + (0, 1, 0) ∉ P)) (decide (c + (0, -1, 0) ∉ P)) (decide (c + (0, 0, 1) ∉ P)) + (decide (c + (0, 0, -1) ∉ P)) := by + rw [exposed, filter_dirsL, fmin_sel] + +theorem LB_image_of {g : Cell → Cell} (hg : Function.Injective g) (e0 e1 e2 e3 e4 e5 : Cell) + (h : ∀ c, g c + (1, 0, 0) = g (c + e0) ∧ g c + (-1, 0, 0) = g (c + e1) ∧ + g c + (0, 1, 0) = g (c + e2) ∧ g c + (0, -1, 0) = g (c + e3) ∧ + g c + (0, 0, 1) = g (c + e4) ∧ g c + (0, 0, -1) = g (c + e5)) + (hs : ∀ (P : Finset Cell) (c : Cell), tabF (decide (c + e0 ∉ P)) (decide (c + e1 ∉ P)) + (decide (c + e2 ∉ P)) (decide (c + e3 ∉ P)) (decide (c + e4 ∉ P)) (decide (c + e5 ∉ P)) = + fmin (exposed P c)) + (P : Finset Cell) : LB (P.image g) = LB P := by + unfold LB + rw [Finset.sum_image fun x _ y _ hxy => hg hxy] + refine Finset.sum_congr rfl fun c _ => ?_ + obtain ⟨h0, h1, h2, h3, h4, h5⟩ := h c + rw [fmin_exposed, h0, h1, h2, h3, h4, h5] + simp only [hg.mem_finset_image] + exact hs P c + +theorem tabF_swap : ∀ b0 b1 b2 b3 b4 b5 : Bool, + tabF b2 b3 b0 b1 b4 b5 = tabF b0 b1 b2 b3 b4 b5 := by decide + +theorem tabF_cycle : ∀ b0 b1 b2 b3 b4 b5 : Bool, + tabF b2 b3 b4 b5 b0 b1 = tabF b0 b1 b2 b3 b4 b5 := by decide + +theorem tabF_refl : ∀ b0 b1 b2 b3 b4 b5 : Bool, + tabF b1 b0 b2 b3 b4 b5 = tabF b0 b1 b2 b3 b4 b5 := by decide + +/-- The generators: `G 0` swaps `x` and `y`, `G 1` permutes the coordinates cyclically and +`G (i + 2)` reflects `x ↦ 32 - x`. -/ +def G : ℕ → Cell → Cell + | 0, c => (c.2.1, c.1, c.2.2) + | 1, c => (c.2.1, c.2.2, c.1) + | _ + 2, c => (32 - c.1, c.2.1, c.2.2) + +theorem G_inj (i : ℕ) : Function.Injective (G i) := by + intro a b h + obtain ⟨a1, a2, a3⟩ := a + obtain ⟨b1, b2, b3⟩ := b + rcases i with _ | _ | i <;> simp only [G, Prod.mk.injEq] at h ⊢ <;> omega + +theorem LB_image_G (i : ℕ) (P : Finset Cell) : LB (P.image (G i)) = LB P := by + rcases i with _ | _ | i + · refine LB_image_of (G_inj 0) (0, 1, 0) (0, -1, 0) (1, 0, 0) (-1, 0, 0) (0, 0, 1) (0, 0, -1) + (fun c => ?_) (fun P c => ?_) P + · obtain ⟨x, y, z⟩ := c + simp only [G, Prod.mk_add_mk, and_self] + · rw [fmin_exposed] + exact tabF_swap _ _ _ _ _ _ + · refine LB_image_of (G_inj 1) (0, 1, 0) (0, -1, 0) (0, 0, 1) (0, 0, -1) (1, 0, 0) (-1, 0, 0) + (fun c => ?_) (fun P c => ?_) P + · obtain ⟨x, y, z⟩ := c + simp only [G, Prod.mk_add_mk, and_self] + · rw [fmin_exposed] + exact tabF_cycle _ _ _ _ _ _ + · refine LB_image_of (G_inj (i + 2)) (-1, 0, 0) (1, 0, 0) (0, 1, 0) (0, -1, 0) (0, 0, 1) + (0, 0, -1) (fun c => ?_) (fun P c => ?_) P + · obtain ⟨x, y, z⟩ := c + simp only [G, Prod.mk_add_mk, Prod.mk.injEq, and_true] + omega + · rw [fmin_exposed] + exact tabF_refl _ _ _ _ _ _ + +/-- The linear part of `G i`. -/ +def A : ℕ → Cell → Cell + | 0, c => (c.2.1, c.1, c.2.2) + | 1, c => (c.2.1, c.2.2, c.1) + | _ + 2, c => (-c.1, c.2.1, c.2.2) + +theorem G_sub (i : ℕ) (x z : Cell) : G i x - G i z = A i (x - z) := by + obtain ⟨x1, x2, x3⟩ := x + obtain ⟨z1, z2, z3⟩ := z + rcases i with _ | _ | i + · simp only [G, A, Prod.mk_sub_mk] + · simp only [G, A, Prod.mk_sub_mk] + · simp only [G, A, Prod.mk_sub_mk, Prod.mk.injEq, and_true] + omega + +theorem A_mem : ∀ i, ∀ d ∈ dirsL, A i d ∈ dirsL + | 0 => by decide +kernel + | 1 => by decide +kernel + | _ + 2 => (by decide +kernel : ∀ d ∈ dirsL, A 2 d ∈ dirsL) + +theorem G_sub_mem (i : ℕ) {x z : Cell} (h : x - z ∈ dirs) : G i x - G i z ∈ dirs := by + rw [mem_dirs] at h ⊢ + rw [G_sub] + exact A_mem i _ h + +/-- Admissible maps: injective, preserving face-adjacency and `LB`. -/ +def Adm (h : Cell → Cell) : Prop := + Function.Injective h ∧ (∀ P, LB (P.image h) = LB P) ∧ ∀ x z, x - z ∈ dirs → h x - h z ∈ dirs + +theorem adm_id : Adm id := ⟨Function.injective_id, fun P => by simp, fun _ _ h => h⟩ + +theorem Adm.comp {f g : Cell → Cell} (hf : Adm f) (hg : Adm g) : Adm (f ∘ g) := + ⟨hf.1.comp hg.1, fun P => by rw [← Finset.image_image, hf.2.1, hg.2.1], + fun x z h => hf.2.2 _ _ (hg.2.2 x z h)⟩ + +theorem adm_add (t : Cell) : Adm (· + t) := + ⟨add_left_injective t, fun P => LB_image_add P t, fun x z h => by simpa using h⟩ + +theorem adm_G (i : ℕ) : Adm (G i) := ⟨G_inj i, LB_image_G i, fun _ _ h => G_sub_mem i h⟩ + +/-! ### Symmetries on codes -/ + +/-- The code of the cell `(x, y, z)`. -/ +def enc (x y z : ℕ) : ℕ := x + 32 * y + 1024 * z + +theorem enc_spec {x y z : ℕ} (hx : x < 32) (hy : y < 32) : + enc x y z % 32 = x ∧ enc x y z / 32 % 32 = y ∧ enc x y z / 1024 = z := by + unfold enc + omega + +/-- The generators acting on codes. -/ +def gC : ℕ → ℕ → ℕ + | 0, k => enc (k / 32 % 32) (k % 32) (k / 1024) + | 1, k => enc (k / 32 % 32) (k / 1024) (k % 32) + | _ + 2, k => enc (32 - k % 32) (k / 32 % 32) (k / 1024) + +theorem gC_spec (i : ℕ) {k : ℕ} (hk : Near k) : Near (gC i k) ∧ dec (gC i k) = G i (dec k) := by + unfold Near at hk ⊢ + rcases i with _ | _ | i + · obtain ⟨h1, h2, h3⟩ := enc_spec (x := k / 32 % 32) (y := k % 32) (z := k / 1024) (by omega) + (by omega) + simp only [gC, dec, G, h1, h2, h3, and_true] + omega + · obtain ⟨h1, h2, h3⟩ := enc_spec (x := k / 32 % 32) (y := k / 1024) (z := k % 32) (by omega) + (by omega) + simp only [gC, dec, G, h1, h2, h3, and_true] + omega + · obtain ⟨h1, h2, h3⟩ := enc_spec (x := 32 - k % 32) (y := k / 32 % 32) (z := k / 1024) + (by omega) (by omega) + simp only [gC, dec, G, h1, h2, h3, Prod.mk.injEq, and_true] + omega + +/-- Apply a word in the generators (first letter first) to a list of codes. -/ +def applyWord : List ℕ → List ℕ → List ℕ + | [], L => L + | i :: w, L => applyWord w (L.map (gC i)) + +/-- The map of cells given by a word in the generators. -/ +def Gw : List ℕ → Cell → Cell + | [] => id + | i :: w => Gw w ∘ G i + +theorem adm_Gw : ∀ w : List ℕ, Adm (Gw w) + | [] => adm_id + | i :: w => (adm_Gw w).comp (adm_G i) + +theorem applyWord_spec : ∀ (w L : List ℕ), (∀ k ∈ L, Near k) → + (∀ k ∈ applyWord w L, Near k) ∧ (applyWord w L).map dec = L.map (Gw w ∘ dec) + | [], L, h => ⟨h, by simp [applyWord, Gw]⟩ + | i :: w, L, h => by + have h' : ∀ k ∈ L.map (gC i), Near k := by + intro k hk + obtain ⟨m, hm, rfl⟩ := List.mem_map.1 hk + exact (gC_spec i (h m hm)).1 + obtain ⟨h1, h2⟩ := applyWord_spec w _ h' + refine ⟨h1, ?_⟩ + show (applyWord w (L.map (gC i))).map dec = _ + rw [h2, List.map_map] + refine List.map_congr_left fun k hk => ?_ + simp only [Function.comp_apply, Gw, (gC_spec i (h k hk)).2] + +/-- A certificate `normC (insSort (applyWord w L)) = X` turns `D L` into `D X` by an admissible +map. -/ +theorem D_cert (w : List ℕ) {L : List ℕ} (hne : L ≠ []) (hn : ∀ k ∈ L, Near k) : + ∃ g, Adm g ∧ D (normC (insSort (applyWord w L))) = (D L).image g := by + obtain ⟨h1, h2⟩ := applyWord_spec w L hn + have hne' : applyWord w L ≠ [] := by + intro he + rw [he, List.map_nil] at h2 + exact hne (List.map_eq_nil_iff.1 h2.symm) + refine ⟨_, (adm_add ((16, 16, 16) - dec ((insSort (applyWord w L)).headD 0))).comp (adm_Gw w), + ?_⟩ + rw [D_normC (insSort_ne_nil hne') fun k hk => h1 k (mem_insSort.1 hk), D_insSort, + ← Finset.image_image] + congr 1 + ext c + simp only [D, List.mem_toFinset, h2, List.mem_map, Function.comp_apply, Finset.mem_image] + constructor + · rintro ⟨k, hk, rfl⟩ + exact ⟨dec k, ⟨k, hk, rfl⟩, rfl⟩ + · rintro ⟨y, ⟨k, hk, rfl⟩, rfl⟩ + exact ⟨k, hk, rfl⟩ + +/-! ### Polycubes up to symmetry -/ + +/-- The one-cell extensions of a list of codes (unnormalised, with repetitions). -/ +def kids (C : List ℕ) : List (List ℕ) := + C.flatMap fun k => ((nbrs k).filter fun j => decide (j ∉ C)).map fun j => ins j C + +theorem mem_kids {C : List ℕ} {k j : ℕ} (hk : k ∈ C) (hj : j ∈ nbrs k) (hjC : j ∉ C) : + ins j C ∈ kids C := by + unfold kids + rw [List.mem_flatMap] + exact ⟨k, hk, List.mem_map.2 ⟨j, List.mem_filter.2 ⟨hj, by simpa using hjC⟩, rfl⟩⟩ + +/-- One certificate: `ch` is mapped by the word `h.1` onto the representative `Cn[h.2]`. -/ +def certOK (Cn : List (List ℕ)) (ch : List ℕ) (h : List ℕ × ℕ) : Bool := + match Cn[h.2]? with + | some X => decide (normC (insSort (applyWord h.1 ch)) = X) + | none => false + +/-- A list of certificates for a list of polycubes. -/ +def allCert (Cn : List (List ℕ)) : List (List ℕ) → List (List ℕ × ℕ) → Bool + | [], [] => true + | ch :: chs, h :: hs => certOK Cn ch h && allCert Cn chs hs + | _, _ => false + +/-- Certificates for all one-cell extensions of all polycubes of a list. -/ +def levelCert (Cn : List (List ℕ)) : List (List ℕ) → List (List (List ℕ × ℕ)) → Bool + | [], [] => true + | C :: Cs, H :: Hs => allCert Cn (kids C) H && levelCert Cn Cs Hs + | _, _ => false + +theorem certOK_spec {Cn : List (List ℕ)} {ch : List ℕ} {h : List ℕ × ℕ} + (hc : certOK Cn ch h = true) : ∃ X ∈ Cn, ∃ w, normC (insSort (applyWord w ch)) = X := by + unfold certOK at hc + split at hc + · next X hX => exact ⟨X, List.mem_of_getElem? hX, h.1, of_decide_eq_true hc⟩ + · exact absurd hc Bool.false_ne_true + +theorem allCert_spec {Cn : List (List ℕ)} : ∀ {chs : List (List ℕ)} {H : List (List ℕ × ℕ)}, + allCert Cn chs H = true → ∀ ch ∈ chs, ∃ X ∈ Cn, ∃ w, normC (insSort (applyWord w ch)) = X + | [], [], _ => by simp + | ch :: chs, h :: hs, hc => by + simp only [allCert, Bool.and_eq_true] at hc + intro c hc' + rcases List.mem_cons.1 hc' with rfl | hc' + · exact certOK_spec hc.1 + · exact allCert_spec hc.2 c hc' + | [], _ :: _, hc => by simp [allCert] at hc + | _ :: _, [], hc => by simp [allCert] at hc + +theorem levelCert_spec {Cn : List (List ℕ)} : ∀ {Cs : List (List ℕ)} {H : List (List (List ℕ × ℕ))}, + levelCert Cn Cs H = true → + ∀ C ∈ Cs, ∀ ch ∈ kids C, ∃ X ∈ Cn, ∃ w, normC (insSort (applyWord w ch)) = X + | [], [], _ => by simp + | C :: Cs, h :: hs, hc => by + simp only [levelCert, Bool.and_eq_true] at hc + intro C' hC' + rcases List.mem_cons.1 hC' with rfl | hC' + · exact allCert_spec hc.1 + · exact levelCert_spec hc.2 C' hC' + | [], _ :: _, hc => by simp [levelCert] at hc + | _ :: _, [], hc => by simp [levelCert] at hc + +/-- Representatives of the polycubes with `6` cells, part 1 of 4. -/ +def reps5a : List (List ℕ) := [ + [16912, 16913, 16914, 16915, 16916, 16917], [16912, 16913, 16914, 16915, 16916, 16944], + [16912, 16913, 16914, 16915, 16916, 16945], [16912, 16913, 16914, 16915, 16916, 16946], + [16912, 16913, 16914, 16915, 16943, 16944], [16912, 16913, 16914, 16915, 16944, 16945], + [16912, 16913, 16914, 16915, 16944, 16946], [16912, 16913, 16914, 16915, 16944, 16947], + [16912, 16913, 16914, 16915, 16944, 16976], [16912, 16913, 16914, 16915, 16944, 17936], + [16912, 16913, 16914, 16915, 16944, 17937], [16912, 16913, 16914, 16915, 16944, 17938], + [16912, 16913, 16914, 16915, 16944, 17939], [16912, 16913, 16914, 16915, 16944, 17968], + [16912, 16913, 16914, 16915, 16945, 16946], [16912, 16913, 16914, 16915, 16945, 16977], + [16912, 16913, 16914, 16915, 16945, 17937], [16912, 16913, 16914, 16915, 16945, 17938], + [16912, 16913, 16914, 16915, 16945, 17969], [16912, 16913, 16914, 16942, 16943, 16944], + [16912, 16913, 16914, 16943, 16944, 16945], [16912, 16913, 16914, 16943, 16944, 16946], + [16912, 16913, 16914, 16943, 16944, 16975], [16912, 16913, 16914, 16943, 16944, 16976], + [16912, 16913, 16914, 16943, 16944, 17936], [16912, 16913, 16914, 16943, 16944, 17937], + [16912, 16913, 16914, 16943, 16944, 17938], [16912, 16913, 16914, 16943, 16944, 17967]] + +/-- Representatives of the polycubes with `6` cells, part 2 of 4. -/ +def reps5b : List (List ℕ) := [ + [16912, 16913, 16914, 16943, 16944, 17968], [16912, 16913, 16914, 16944, 16945, 16946], + [16912, 16913, 16914, 16944, 16945, 16976], [16912, 16913, 16914, 16944, 16945, 16977], + [16912, 16913, 16914, 16944, 16945, 17936], [16912, 16913, 16914, 16944, 16945, 17937], + [16912, 16913, 16914, 16944, 16945, 17938], [16912, 16913, 16914, 16944, 16945, 17968], + [16912, 16913, 16914, 16944, 16945, 17969], [16912, 16913, 16914, 16944, 16946, 16976], + [16912, 16913, 16914, 16944, 16946, 17936], [16912, 16913, 16914, 16944, 16946, 17937], + [16912, 16913, 16914, 16944, 16946, 17968], [16912, 16913, 16914, 16944, 16975, 16976], + [16912, 16913, 16914, 16944, 16976, 17936], [16912, 16913, 16914, 16944, 16976, 17937], + [16912, 16913, 16914, 16944, 16976, 17938], [16912, 16913, 16914, 16944, 17904, 17936], + [16912, 16913, 16914, 16944, 17905, 17937], [16912, 16913, 16914, 16944, 17906, 17938], + [16912, 16913, 16914, 16944, 17936, 17968], [16912, 16913, 16914, 16944, 17937, 17968], + [16912, 16913, 16914, 16944, 17937, 17969], [16912, 16913, 16914, 16944, 17937, 18961], + [16912, 16913, 16914, 16944, 17938, 17968], [16912, 16913, 16914, 16944, 17967, 17968], + [16912, 16913, 16914, 16944, 17968, 17969], [16912, 16913, 16914, 16944, 17968, 18000]] + +/-- Representatives of the polycubes with `6` cells, part 3 of 4. -/ +def reps5c : List (List ℕ) := [ + [16912, 16913, 16914, 16944, 17968, 18992], [16912, 16913, 16914, 16945, 16976, 16977], + [16912, 16913, 16914, 16945, 16977, 17009], [16912, 16913, 16914, 16945, 16977, 17937], + [16912, 16913, 16914, 16945, 16977, 17969], [16912, 16913, 16914, 16945, 16977, 18001], + [16912, 16913, 16914, 16945, 17904, 17936], [16912, 16913, 16914, 16945, 17905, 17937], + [16912, 16913, 16914, 16945, 17937, 17969], [16912, 16913, 16914, 16945, 17968, 17969], + [16912, 16913, 16914, 16945, 17969, 18001], [16912, 16913, 16914, 16945, 17969, 18993], + [16912, 16913, 16914, 17905, 17937, 17969], [16912, 16913, 16942, 16943, 16944, 16974], + [16912, 16913, 16942, 16943, 16944, 16975], [16912, 16913, 16942, 16943, 16944, 16976], + [16912, 16913, 16943, 16944, 16945, 16975], [16912, 16913, 16943, 16944, 16945, 16976], + [16912, 16913, 16943, 16944, 16974, 16975], [16912, 16913, 16943, 16944, 16975, 17936], + [16912, 16913, 16943, 16944, 16975, 17937], [16912, 16913, 16943, 16944, 16975, 17968], + [16912, 16913, 16943, 16944, 16976, 16977], [16912, 16913, 16943, 16944, 16976, 17008], + [16912, 16913, 16943, 16944, 16976, 17936], [16912, 16913, 16943, 16944, 16976, 17937], + [16912, 16913, 16943, 16944, 16976, 17967], [16912, 16913, 16943, 16944, 16976, 17968]] + +/-- Representatives of the polycubes with `6` cells, part 4 of 4. -/ +def reps5d : List (List ℕ) := [ + [16912, 16913, 16943, 16944, 16976, 18000], [16912, 16913, 16943, 16944, 17904, 17936], + [16912, 16913, 16943, 16944, 17905, 17937], [16912, 16913, 16943, 16944, 17935, 17936], + [16912, 16913, 16943, 16944, 17935, 17967], [16912, 16913, 16943, 16944, 17936, 17937], + [16912, 16913, 16943, 16944, 17936, 17967], [16912, 16913, 16943, 16944, 17936, 17968], + [16912, 16913, 16943, 16944, 17937, 17938], [16912, 16913, 16943, 16944, 17937, 17967], + [16912, 16913, 16943, 17936, 17967, 17968], [16912, 16913, 16944, 16945, 17936, 17937], + [16912, 16913, 16944, 16945, 17936, 17969], [16912, 16913, 16944, 16975, 16976, 17008], + [16912, 16913, 16944, 16975, 16976, 17936], [16912, 16913, 16944, 16975, 16976, 17937], + [16912, 16913, 16944, 16975, 16976, 17968], [16912, 16913, 16944, 16976, 17007, 17008], + [16912, 16913, 16944, 17903, 17904, 17936], [16912, 16913, 16944, 17904, 17935, 17936], + [16912, 16913, 16944, 17905, 17906, 17937], [16912, 16913, 16944, 17905, 17936, 17937], + [16912, 16913, 16944, 17906, 17937, 17938], [16912, 16913, 16944, 17937, 17968, 17969], + [16912, 16913, 17904, 17936, 17968, 18960], [16912, 16942, 16943, 16944, 16945, 16975], + [16912, 16942, 16943, 16944, 16945, 16976], [16912, 16943, 16944, 16945, 16976, 17968]] + +/-- `reps.getD n []` lists representatives of the polycubes with `n + 1` cells (`n ≤ 5`) up to +the symmetries of the lattice, as normalised sorted lists of codes. -/ +def reps : List (List (List ℕ)) := [ + [ + [16912]], + [ + [16912, 16913]], + [ + [16912, 16913, 16914], [16912, 16913, 16944]], + [ + [16912, 16913, 16914, 16915], [16912, 16913, 16914, 16944], [16912, 16913, 16914, 16945], + [16912, 16913, 16943, 16944], [16912, 16913, 16944, 16945], [16912, 16913, 16944, 17936], + [16912, 16913, 16944, 17937]], + [ + [16912, 16913, 16914, 16915, 16916], [16912, 16913, 16914, 16915, 16944], + [16912, 16913, 16914, 16915, 16945], [16912, 16913, 16914, 16943, 16944], + [16912, 16913, 16914, 16944, 16945], [16912, 16913, 16914, 16944, 16946], + [16912, 16913, 16914, 16944, 16976], [16912, 16913, 16914, 16944, 17936], + [16912, 16913, 16914, 16944, 17937], [16912, 16913, 16914, 16944, 17938], + [16912, 16913, 16914, 16944, 17968], [16912, 16913, 16914, 16945, 16977], + [16912, 16913, 16914, 16945, 17937], [16912, 16913, 16914, 16945, 17969], + [16912, 16913, 16943, 16944, 16975], [16912, 16913, 16943, 16944, 16976], + [16912, 16913, 16943, 16944, 17936], [16912, 16913, 16943, 16944, 17937], + [16912, 16913, 16944, 16945, 17936], [16912, 16913, 16944, 16975, 16976], + [16912, 16913, 16944, 17905, 17937], [16912, 16913, 16944, 17937, 17968], + [16912, 16943, 16944, 16945, 16976]], + reps5a ++ reps5b ++ reps5c ++ reps5d] + +/-- Certificates: for each representative `C` with at most `5` cells and each entry of `kids C` +(in order), a word in the generators and the index of the representative it is mapped to. -/ +def hints : List (List (List (List ℕ × ℕ))) := [ + [ + [ + ([], 0), ([], 0), ([0], 0), ([0], 0), ([1, 0], 0), ([1, 0], 0)]], + [ + [ + ([], 0), ([], 1), ([0, 2], 1), ([0, 1], 1), ([1, 1, 2], 1), ([], 0), ([2], 1), + ([2, 0, 2], 1), ([0, 1, 2], 1), ([2, 1, 1, 2], 1)]], + [ + [ + ([], 0), ([], 1), ([0, 2, 0], 1), ([0, 1], 1), ([1, 1, 2, 0], 1), ([], 2), ([0, 2, 0], 2), + ([0, 1], 2), ([1, 1, 2, 0], 2), ([], 0), ([2], 1), ([0, 2, 0, 2], 1), ([0, 1, 2], 1), + ([1, 1, 2, 0, 2], 1)], + [ + ([], 2), ([0], 2), ([], 5), ([1, 0, 2], 5), ([], 1), ([], 4), ([0], 3), ([], 6), + ([1, 1, 2, 1], 6), ([], 4), ([], 3), ([0], 1), ([0], 6), ([1, 0, 2, 1], 6)]], + [ + [ + ([], 0), ([], 1), ([0, 2, 0], 1), ([0, 1], 1), ([1, 1, 2, 0], 1), ([], 2), ([0, 2, 0], 2), + ([0, 1], 2), ([1, 1, 2, 0], 2), ([2], 2), ([0, 2, 0, 2], 2), ([0, 1, 2], 2), + ([1, 1, 2, 0, 2], 2), ([], 0), ([2], 1), ([0, 2, 0, 2], 1), ([0, 1, 2], 1), + ([1, 1, 2, 0, 2], 1)], + [ + ([], 2), ([0], 11), ([], 7), ([1, 1, 2, 0], 7), ([], 4), ([0], 15), ([], 8), + ([1, 1, 2, 1], 8), ([], 1), ([], 5), ([0], 19), ([], 9), ([1, 1, 2, 1], 9), ([], 4), + ([], 3), ([], 6), ([], 10), ([1, 1, 2, 1], 10)], + [ + ([2], 2), ([], 4), ([0, 2], 15), ([0, 1], 8), ([1, 1, 2, 0], 8), ([], 22), ([], 12), + ([1, 1, 2, 0], 12), ([], 2), ([2], 4), ([2, 0, 2], 15), ([0, 1, 2], 8), + ([1, 1, 2, 0, 2], 8), ([2], 4), ([], 4), ([], 11), ([], 13), ([1, 1, 2, 1], 13)], + [ + ([], 4), ([0, 2, 0, 2], 15), ([], 16), ([1, 1, 2, 1], 16), ([], 3), ([0, 2, 0, 2], 4), + ([2, 0, 2], 14), ([], 17), ([1, 1, 2, 1], 17), ([0, 2, 0, 2], 3), ([], 14), ([], 4), + ([0, 2, 0, 2], 17), ([1, 2, 1, 2, 1, 2], 17), ([0, 2, 0, 2], 4), ([], 15), + ([0, 2, 0, 2], 16), ([1, 2, 1, 2, 1, 2], 16)], + [ + ([2], 4), ([0, 2], 4), ([], 18), ([1, 0, 2, 1], 18), ([], 4), ([2, 0, 2], 4), ([2], 18), + ([1, 1, 2, 1, 2], 18), ([0, 2, 0, 2], 4), ([0], 4), ([0, 2], 18), ([1, 0, 2, 1, 2], 18), + ([0, 2, 0], 4), ([2, 0], 4), ([2, 0, 2], 18), ([1, 2, 1, 2, 1, 2], 18)], + [ + ([], 12), ([0], 12), ([1, 0], 12), ([], 7), ([], 18), ([0], 16), ([0, 1], 18), + ([1, 1], 16), ([], 18), ([], 16), ([0], 7), ([1], 18), ([1, 0], 16), ([0, 1], 18), + ([0, 1], 16), ([1], 18), ([1], 16), ([1, 0], 7)], + [ + ([0, 1, 2], 8), ([0], 13), ([0, 1], 18), ([1, 1, 2], 16), ([], 8), ([2], 18), + ([2, 0, 2], 16), ([2, 1, 1], 13), ([2], 18), ([], 17), ([0], 10), ([], 21), + ([0, 1, 2], 20), ([0, 1, 2], 17), ([0, 1], 18), ([0, 1, 2], 21), ([], 20), ([2, 1, 1], 10)]], + [ + [ + ([], 0), ([], 1), ([0, 2, 0], 1), ([0, 1], 1), ([1, 1, 2, 0], 1), ([], 2), ([0, 2, 0], 2), + ([0, 1], 2), ([1, 1, 2, 0], 2), ([], 3), ([0, 2, 0], 3), ([0, 1], 3), ([1, 1, 2, 0], 3), + ([2], 2), ([0, 2, 0, 2], 2), ([0, 1, 2], 2), ([1, 1, 2, 0, 2], 2), ([], 0), ([2], 1), + ([0, 2, 0, 2], 1), ([0, 1, 2], 1), ([1, 1, 2, 0, 2], 1)], + [ + ([], 2), ([0], 58), ([], 9), ([1, 1, 2, 0], 9), ([], 5), ([0], 79), ([], 10), + ([1, 1, 2, 1], 10), ([], 6), ([0], 97), ([], 11), ([1, 1, 2, 1], 11), ([], 1), ([], 7), + ([0], 101), ([], 12), ([1, 1, 2, 1], 12), ([], 5), ([], 4), ([], 8), ([], 13), + ([1, 1, 2, 1], 13)], + [ + ([], 3), ([], 5), ([0, 2], 79), ([0, 1], 10), ([1, 1, 2, 0], 10), ([2], 110), ([], 16), + ([1, 1, 2, 0], 16), ([], 14), ([], 109), ([], 17), ([1, 1, 2, 1], 17), ([], 2), ([2], 6), + ([2, 0, 2], 97), ([0, 1, 2], 11), ([1, 1, 2, 0, 2], 11), ([], 14), ([], 5), ([], 15), + ([], 18), ([1, 1, 2, 1], 18)], + [ + ([], 5), ([0, 2, 0, 2], 71), ([], 24), ([1, 1, 2, 1], 24), ([], 20), ([0, 2, 0, 2], 70), + ([], 25), ([1, 1, 2, 1], 25), ([], 4), ([], 21), ([0, 2, 0, 2], 69), ([], 26), + ([1, 1, 2, 1], 26), ([], 19), ([], 22), ([], 5), ([], 27), ([1, 1, 2, 1], 27), ([], 20), + ([], 23), ([], 28), ([1, 1, 2, 1], 28)], + [ + ([], 14), ([0, 2], 31), ([], 32), ([1, 1, 2, 1], 32), ([0], 73), ([], 33), + ([1, 1, 2, 1], 33), ([], 5), ([], 29), ([0, 2, 0, 2], 72), ([], 34), ([1, 1, 2, 1], 34), + ([], 20), ([], 30), ([], 35), ([1, 1, 2, 1], 35), ([], 29), ([], 31), ([], 36), + ([1, 1, 2, 1], 36)], + [ + ([2], 6), ([0, 2], 57), ([], 38), ([1, 1, 2, 1], 38), ([], 29), ([0], 78), ([], 39), + ([1, 1, 2, 1], 39), ([], 6), ([2, 0, 2], 57), ([2], 38), ([1, 1, 2, 1, 2], 38), ([], 29), + ([], 21), ([], 37), ([], 40), ([1, 1, 2, 1], 40), ([2], 21), ([], 29), ([2], 37), + ([2], 40), ([1, 1, 2, 1, 2], 40)], + [ + ([], 15), ([0], 15), ([], 42), ([1, 0, 2, 1], 42), ([], 30), ([0], 23), ([], 43), + ([1, 1, 2, 1], 43), ([], 8), ([], 37), ([0], 41), ([], 44), ([1, 1, 2, 1], 44), ([], 30), + ([], 23), ([0], 43), ([1, 0, 2, 1], 43), ([0], 37), ([], 41), ([0], 8), ([0], 44), + ([1, 0, 2, 1], 44)], + [ + ([], 16), ([0], 59), ([1, 1], 59), ([], 32), ([0], 80), ([0, 1], 32), ([1, 1], 80), + ([], 9), ([], 38), ([0], 98), ([0, 1], 38), ([1, 1], 98), ([], 32), ([], 24), ([], 42), + ([], 48), ([0, 1], 45), ([0, 1], 32), ([0, 1], 24), ([], 48), ([], 45), ([0, 1], 42)], + [ + ([], 17), ([0], 60), ([0, 1], 32), ([1, 1, 2], 80), ([], 33), ([0], 83), ([1], 108), + ([], 10), ([], 39), ([0], 100), ([0, 1, 2], 34), ([2, 1, 1, 2], 84), ([], 33), ([], 25), + ([], 43), ([], 49), ([0, 1], 62), ([0, 1, 2], 34), ([0, 1], 32), ([], 50), ([], 46), + ([], 51)], + [ + ([0, 1, 2], 11), ([0], 61), ([0, 1], 38), ([1, 1, 2], 98), ([], 34), ([0], 84), + ([0, 1, 2], 34), ([2, 1, 1], 84), ([], 11), ([2], 38), ([2, 0, 2], 98), ([2, 1, 1], 61), + ([], 34), ([], 26), ([], 44), ([], 52), ([0, 1, 2], 47), ([0, 1, 2], 26), ([0, 1, 2], 34), + ([0, 1, 2], 52), ([], 47), ([0, 1, 2], 44)], + [ + ([], 18), ([1, 2], 51), ([], 48), ([1, 1, 2, 0], 45), ([], 35), ([0], 81), ([], 49), + ([1, 1, 2, 0], 62), ([], 13), ([], 40), ([0], 99), ([], 52), ([1, 1, 2, 0, 2], 47), + ([], 35), ([], 28), ([0], 43), ([1, 2, 0], 67), ([], 54), ([], 53), ([], 55), ([], 48), + ([], 56)], + [ + ([2], 15), ([], 31), ([0, 2], 71), ([0, 1], 51), ([1, 1, 2, 0], 51), ([0, 2], 110), + ([], 59), ([1, 1, 2, 1], 59), ([], 15), ([2], 31), ([2, 0, 2], 71), ([0, 1, 2], 51), + ([1, 1, 2, 0, 2], 51), ([2], 31), ([], 31), ([], 60), ([1, 1, 2, 1], 60), ([2], 57), + ([], 57), ([], 58), ([], 61), ([1, 1, 2, 1], 61)], + [ + ([2], 16), ([], 33), ([0, 2], 83), ([0, 1], 33), ([1, 1, 2], 83), ([], 111), ([0, 1], 111), + ([], 16), ([2], 33), ([2, 0, 2], 83), ([0, 1, 2], 33), ([2, 1, 1, 2], 83), ([2], 33), + ([], 33), ([], 59), ([], 64), ([0, 1], 63), ([0, 1, 2], 33), ([0, 1], 33), ([], 64), + ([], 63), ([0, 1], 59)], + [ + ([2], 18), ([], 36), ([0, 2], 82), ([0, 1], 50), ([1, 1, 2, 0], 46), ([1, 2, 1], 108), + ([], 64), ([1, 1, 2, 0], 63), ([], 18), ([2], 36), ([2, 0, 2], 82), ([0, 1, 2], 50), + ([1, 1, 2, 0, 2], 46), ([2], 36), ([], 36), ([], 60), ([0, 1], 68), ([2], 65), ([], 65), + ([], 66), ([], 64), ([], 67)], + [ + ([], 30), ([0], 70), ([], 75), ([1, 1, 2, 1], 75), ([], 22), ([], 72), ([0], 74), ([], 76), + ([1, 1, 2, 1], 76), ([], 70), ([], 30), ([0], 75), ([1, 0, 2, 1], 75), ([], 72), ([0], 72), + ([], 77), ([1, 0, 2, 1], 77), ([0], 72), ([], 74), ([0], 22), ([0], 76), ([1, 0, 2, 1], 76)], + [ + ([], 31), ([0], 109), ([], 80), ([1, 1, 2, 1], 80), ([], 23), ([], 73), ([2, 0, 2], 70), + ([], 81), ([1, 1, 2, 1], 81), ([], 71), ([0], 72), ([], 31), ([], 82), ([1, 1, 2, 1], 82), + ([], 73), ([], 83), ([1, 1, 2, 1], 83), ([], 78), ([0], 72), ([], 79), ([], 84), + ([1, 1, 2, 1], 84)], + [ + ([], 33), ([0, 2, 0, 2], 83), ([1, 1], 63), ([], 24), ([0, 2, 0, 2], 36), ([2, 0, 2], 77), + ([], 89), ([1, 1], 85), ([0, 2, 0, 2], 28), ([], 75), ([], 33), ([], 90), ([1, 1], 102), + ([0, 2, 0, 2], 36), ([], 80), ([], 91), ([0, 1], 103), ([], 89), ([], 87), ([], 91), + ([], 85), ([1, 1], 45)], + [ + ([], 34), ([0, 2, 0, 2], 82), ([], 89), ([1, 1, 2], 85), ([], 25), ([0, 2, 0, 2], 35), + ([2, 0, 2], 75), ([2, 1, 1], 66), ([0, 2, 0, 2], 27), ([], 76), ([], 34), ([], 93), + ([0, 1, 2], 106), ([0, 2, 0, 2], 35), ([], 81), ([0, 2, 0, 2], 90), ([2, 1, 2, 1, 2], 102), + ([], 92), ([], 89), ([0, 2, 0, 2], 88), ([], 86), ([2, 1, 1], 55)], + [ + ([2], 33), ([0, 2], 33), ([1, 0], 64), ([], 32), ([2, 0, 2], 36), ([], 95), ([1, 1], 91), + ([0, 2, 0, 2], 36), ([0], 32), ([0], 95), ([1, 0], 91), ([0, 2, 0], 35), ([2, 0], 35), + ([], 96), ([1], 105), ([], 95), ([0, 1], 89), ([0], 95), ([1], 89), ([1, 0], 48)], + [ + ([], 57), ([0, 2, 0, 2], 97), ([], 98), ([1, 1, 2, 1], 98), ([], 41), ([2, 0, 2], 72), + ([2, 0, 2], 69), ([], 99), ([1, 1, 2, 1], 99), ([2, 0, 2], 72), ([0], 72), ([], 100), + ([1, 1, 2, 1], 100), ([0, 2, 0, 2], 41), ([0], 69), ([0], 72), ([0, 2, 0, 2], 99), + ([1, 2, 1, 2, 1, 2], 99), ([0, 2, 0, 2], 57), ([], 97), ([0, 2, 0, 2], 98), + ([1, 2, 1, 2, 1, 2], 98)], + [ + ([2], 62), ([0], 65), ([], 105), ([1, 0, 2, 0], 102), ([], 46), ([2, 1], 89), + ([2, 0, 2], 89), ([2, 1, 2, 0, 2], 46), ([2, 1], 89), ([], 86), ([0], 53), + ([2, 1, 0, 2, 1, 2], 94), ([1, 0, 2, 0, 2], 104), ([], 104), ([1], 94), + ([2, 1, 0, 2, 0, 2], 53), ([2, 1, 2, 0, 2], 86), ([2, 0, 2], 89), ([1, 0, 2, 1, 2], 102), + ([], 105), ([2, 1, 0, 2, 0, 2], 65), ([2, 1, 2, 0], 62)], + [ + ([0, 1, 2], 50), ([1, 2], 50), ([1, 0], 95), ([1, 0, 2], 87), ([], 49), ([2], 96), + ([2, 0, 2], 90), ([2, 1, 1, 2], 65), ([2], 96), ([0, 2, 0, 2], 90), ([0], 49), + ([1, 2, 0, 2], 65), ([1, 1, 2, 0], 88), ([1, 0], 95), ([], 107), ([2, 1, 0, 2, 1, 2], 94), + ([2, 1, 1], 54), ([], 107), ([1, 2, 1, 2, 1, 2], 94), ([1, 0, 2, 0], 88), ([1, 0], 95), + ([1, 2, 0], 54)], + [ + ([], 73), ([2], 73), ([0], 110), ([1, 1], 108), ([1, 1, 2], 108), ([], 110), ([0], 73), + ([2], 73), ([1, 0], 108), ([1, 0, 2], 108), ([], 111), ([1, 0, 2, 1], 111), ([2], 110), + ([2, 0], 73), ([], 73), ([2, 1, 0], 108), ([2, 1, 0, 2], 108), ([2, 0], 73), ([0], 73), + ([0, 2], 110), ([1, 2, 1], 108), ([1, 2, 1, 2], 108)]]] + + +/-- Every representative is a duplicate-free list of codes with coordinates in `[10, 22]`. -/ +theorem reps_ok : ∀ n < 6, ((reps.getD n []).all fun C => decide C.Nodup && C.all goodT) = true := by + decide +kernel + +/-- The certificates are correct. -/ +theorem certs_ok : ∀ n < 5, levelCert (reps.getD (n + 1) []) (reps.getD n []) (hints.getD n []) = + true := by + decide +kernel + +theorem reps_spec {n : ℕ} (hn : n < 6) {C : List ℕ} (hC : C ∈ reps.getD n []) : + C.Nodup ∧ ∀ k ∈ C, goodT k = true := by + have h := List.all_eq_true.1 (reps_ok n hn) C hC + simp only [Bool.and_eq_true, decide_eq_true_eq, List.all_eq_true] at h + exact h + +/-- One-cell extension of a polycube that has a representative. -/ +theorem kid_step {C : List ℕ} (hC : ∀ k ∈ C, goodT k = true) {Q : Finset Cell} + {h : Cell → Cell} (hh : Adm h) (hQ : Q.image h = D C) {x z : Cell} (hxQ : x ∉ Q) + (hz : z ∈ Q) (hxz : x - z ∈ dirs) : + ∃ j k, k ∈ C ∧ j ∈ nbrs k ∧ j ∉ C ∧ (insert x Q).image h = D (ins j C) := by + have hzC : h z ∈ D C := hQ ▸ Finset.mem_image_of_mem h hz + obtain ⟨k, hk, hkz⟩ := mem_D_iff.1 hzC + have hd := hh.2.2 x z hxz + obtain ⟨j, hj, hjx⟩ : ∃ j ∈ nbrs k, dec j = h x := by + have h2 : dec k + (h x - h z) ∈ (nbrs k).map dec := by + rw [dec_nbrs (good_of_near (near_of_goodT (hC k hk)))] + exact List.mem_map_of_mem (mem_dirs.1 hd) + rw [hkz, add_sub_cancel] at h2 + simpa only [List.mem_map] using h2 + have hjC : j ∉ C := by + intro hjC + have h3 : dec j ∈ D C := mem_D.2 hjC + rw [← hQ, hjx, hh.1.mem_finset_image] at h3 + exact hxQ h3 + refine ⟨j, k, hk, hj, hjC, ?_⟩ + rw [Finset.image_insert, hQ, D_ins, hjx] + +theorem ins_facts {C : List ℕ} (hC : C.Nodup ∧ ∀ k ∈ C, goodT k = true) {j k : ℕ} (hk : k ∈ C) + (hj : j ∈ nbrs k) (hjC : j ∉ C) : (ins j C).Nodup ∧ ∀ m ∈ ins j C, Near m := by + refine ⟨(ins_perm j C).nodup_iff.2 (List.nodup_cons.2 ⟨hjC, hC.1⟩), fun m hm => ?_⟩ + rcases mem_ins.1 hm with rfl | hm + · exact near_of_mem_nbrs (hC.2 k hk) hj + · exact near_of_goodT (hC.2 m hm) + +/-- Every polycube with `n + 1 ≤ 6` cells is mapped onto a representative by an admissible +map. -/ +theorem complete : ∀ n ≤ 5, ∀ P : Finset Cell, P.card = n + 1 → FaceConnected P → + ∃ C ∈ reps.getD n [], ∃ h, Adm h ∧ P.image h = D C := by + intro n + induction n with + | zero => + intro _ P hc _ + obtain ⟨x, rfl⟩ := Finset.card_eq_one.1 hc + refine ⟨[16912], by decide +kernel, (· + ((16, 16, 16) - x)), adm_add _, ?_⟩ + rw [Finset.image_singleton, add_sub_cancel] + decide +kernel + | succ n ih => + intro hn P hc hP + obtain ⟨x, Q, z, rfl, hxQ, hQ, hzQ, hxz⟩ := exists_leaf hP (by omega) + rw [Finset.card_insert_of_notMem hxQ] at hc + obtain ⟨C, hC, h, hh, hQC⟩ := ih (by omega) Q (by omega) hQ + have hCs := reps_spec (by omega) hC + obtain ⟨j, k, hk, hj, hjC, hP'⟩ := kid_step hCs.2 hh hQC hxQ hzQ hxz + obtain ⟨X, hX, w, hw⟩ := + levelCert_spec (certs_ok n (by omega)) C hC (ins j C) (mem_kids hk hj hjC) + obtain ⟨g, hg, hD⟩ := D_cert w (ins_ne_nil j C) (ins_facts hCs hk hj hjC).2 + exact ⟨X, hX, g ∘ h, hg.comp hh, by rw [← Finset.image_image, hP', ← hD, hw]⟩ + +/-! ### Lower bounds -/ + +/-- The terms `a(1), …, a(57)` listed in the entry (DATA). -/ +def oeisData : List ℕ := + [21, 30, 40, 40, 51, 52, 54, 48, 60, 62, 65, 60, 72, 74, 77, 72, 78, 74, 86, 84, 91, 88, 92, + 88, 95, 93, 90, 102, 105, 102, 106, 104, 107, 110, 109, 106, 118, 120, 121, 120, 125, 123, + 126, 125, 122, 128, 127, 124, 136, 138, 139, 140, 141, 138, 145, 144, 143] + +/-- The least value of `LB` over the representatives with `n + 1 ≤ 6` cells is the listed +term. -/ +theorem minVal_ok : ∀ n < 6, minVal (reps.getD n []) = oeisData.getD n 0 := by decide +kernel + +/-- All one-cell extensions of `C` have value at least `v`. -/ +def kidsGe (v : ℕ) (C : List ℕ) : Bool := (kids C).all fun ch => Nat.ble v (valW ch) + +theorem kids_ok_a : reps5a.all (kidsGe 54) = true := by decide +kernel + +theorem kids_ok_b : reps5b.all (kidsGe 54) = true := by decide +kernel + +theorem kids_ok_c : reps5c.all (kidsGe 54) = true := by decide +kernel + +theorem kids_ok_d : reps5d.all (kidsGe 54) = true := by decide +kernel + +theorem kids_ok {C : List ℕ} (hC : C ∈ reps.getD 5 []) : kidsGe 54 C = true := by + have e : reps.getD 5 [] = reps5a ++ reps5b ++ reps5c ++ reps5d := rfl + rw [e] at hC + simp only [List.mem_append] at hC + rcases hC with ((hC | hC) | hC) | hC + · exact List.all_eq_true.1 kids_ok_a C hC + · exact List.all_eq_true.1 kids_ok_b C hC + · exact List.all_eq_true.1 kids_ok_c C hC + · exact List.all_eq_true.1 kids_ok_d C hC + +theorem LB_ge_minVal {n : ℕ} (hn : n ≤ 5) {P : Finset Cell} (hc : P.card = n + 1) + (hP : FaceConnected P) : minVal (reps.getD n []) ≤ LB P := by + obtain ⟨C, hC, h, hh, hPC⟩ := complete n hn P hc hP + obtain ⟨hnd, hg⟩ := reps_spec (by omega) hC + calc minVal (reps.getD n []) ≤ valW C := minVal_le hC + _ = LB (D C) := valW_eq hnd fun k hk => good_of_near (near_of_goodT (hg k hk)) + _ = LB P := by rw [← hPC, hh.2.1] + +theorem LB_ge_seven {P : Finset Cell} (hc : P.card = 7) (hP : FaceConnected P) : 54 ≤ LB P := by + obtain ⟨x, Q, z, rfl, hxQ, hQ, hzQ, hxz⟩ := exists_leaf hP (by omega) + rw [Finset.card_insert_of_notMem hxQ] at hc + obtain ⟨C, hC, h, hh, hQC⟩ := complete 5 le_rfl Q (by omega) hQ + have hCs := reps_spec (by omega) hC + obtain ⟨j, k, hk, hj, hjC, hP'⟩ := kid_step hCs.2 hh hQC hxQ hzQ hxz + obtain ⟨hnd, hnear⟩ := ins_facts hCs hk hj hjC + have hv := List.all_eq_true.1 (kids_ok hC) _ (mem_kids hk hj hjC) + calc 54 ≤ valW (ins j C) := Nat.le_of_ble_eq_true hv + _ = LB (D (ins j C)) := valW_eq hnd fun m hm => good_of_near (hnear m hm) + _ = LB (insert x Q) := by rw [← hP', hh.2.1] + +/-! ## The data -/ + +theorem wits_data : wits.map (fun e => (e.1, e.2.1)) = + (List.range 57).map (fun i => (i + 1, oeisData.getD i 0)) := by decide +kernel + +theorem mem_totals_data : ∀ i < 57, oeisData.getD i 0 ∈ totals (i + 1) := by + intro i hi + have hmem : (i + 1, oeisData.getD i 0) ∈ wits.map (fun e => (e.1, e.2.1)) := by + rw [wits_data] + exact List.mem_map.2 ⟨i, List.mem_range.2 hi, rfl⟩ + obtain ⟨e, he, hee⟩ := List.mem_map.1 hmem + have := mem_totals_of_witOK (List.all_eq_true.1 wits_ok e he) + simp only [Prod.mk.injEq] at hee + rwa [hee.1, hee.2] at this + +/-- Upper bounds: `a n` is at most the listed value, for all `57` listed terms (kernel-checked +witnesses). -/ +theorem a_le_data : ∀ i < 57, a (i + 1) ≤ oeisData.getD i 0 := + fun i hi => Nat.sInf_le (mem_totals_data i hi) + +theorem a_eq_of {n v : ℕ} (hv : v ∈ totals n) + (hlb : ∀ P : Finset Cell, P.card = n → FaceConnected P → v ≤ LB P) : a n = v := + IsLeast.csInf_eq ⟨hv, fun _ ht => by + obtain ⟨P, hc, hP, hle⟩ := exists_LB_le ht + exact (hlb P hc hP).trans hle⟩ + +theorem a_eq_data {i : ℕ} (hi : i ≤ 5) : a (i + 1) = oeisData.getD i 0 := + a_eq_of (mem_totals_data i (by omega)) fun _ hc hP => + (minVal_ok i (by omega)).symm ▸ LB_ge_minVal hi hc hP + +/-- The definition reproduces the first seven listed terms exactly (kernel-checked enumeration of +all polycubes with at most `7` cells, up to symmetry). -/ +theorem a_data : (List.range 7).map (fun i => a (i + 1)) = [21, 30, 40, 40, 51, 52, 54] := by + have e7 : a 7 = 54 := a_eq_of (mem_totals_data 6 (by norm_num)) fun _ hc hP => LB_ge_seven hc hP + show [a 1, a 2, a 3, a 4, a 5, a 6, a 7] = [21, 30, 40, 40, 51, 52, 54] + rw [a_eq_data (i := 0) (by norm_num), a_eq_data (i := 1) (by norm_num), + a_eq_data (i := 2) (by norm_num), a_eq_data (i := 3) (by norm_num), + a_eq_data (i := 4) (by norm_num), a_eq_data (i := 5) (by norm_num), e7] + rfl + +/-! ## The conjecture -/ + +/-- The conjecture of A363609: `a(k^3) = 6 (k + 2) k` for every `k > 1`. (The `k × k × k` cube +with the dice turned so that `1, 2, 3` are visible at the `8` corners, `1, 2` on the `12 (k - 2)` +edge dice and `1` on the `6 (k - 2)²` face dice shows `48 + 36 (k - 2) + 6 (k - 2)² = 6 k (k + 2)` +pips, so `a (k ^ 3) ≤ 6 k (k + 2)`; the conjecture is the matching lower bound.) -/ +def statement : Prop := ∀ k : ℕ, 1 < k → a (k ^ 3) = 6 * (k + 2) * k + +end Math0.Statements.A363609 diff --git a/lean/Math0/Statements/OEIS/A367119.lean b/lean/Math0/Statements/OEIS/A367119.lean new file mode 100644 index 0000000..77d1ac9 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A367119.lean @@ -0,0 +1,156 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A367119: edges of the all-chords graph of a triangle with `n` general points per side + +Source: https://oeis.org/A367119, _Scott R. Shannon_ and _N. J. A. Sloane_, Nov 05 2023 +(FORMULA section). Verbatim: +> Conjecture: a(n) = (3/2)*(3*n^4 + 4*n^3 + 3*n^2 + 4*n + 2). + +The entry's definition (offset `0`): "Place n points in general position on each side of an +equilateral triangle, and join every pair of the 3*n+3 boundary points by a chord; sequence gives +number of edges in the resulting planar graph." Comment: "'In general position' implies that the +internal lines (or chords) only have simple intersections. There is no interior point where three +or more chords meet." Data: `3, 24, 153, 588, 1635, 3708, 7329, 13128, 21843, 34320, 51513, …`. + +## Encoding + +*Geometry (used by `statement`).* The plane is `ℂ`. The equilateral triangle `triangle` is the +convex hull of `corner 0 = 0`, `corner 1 = 1`, `corner 2 = 1/2 + (√3/2) i`; side `j` (`j : Fin 3`, +so `2 + 1 = 0`) is the segment from `corner j` to `corner (j + 1)`. +* `IsPlacement n B`: the finite set `B ⊆ ℂ` of boundary points consists of the three corners + together with exactly `n` points in the relative interior (`openSegment`) of each side, and + nothing else (every point of `B` lies on a closed side). So `B` has `3n+3` points. +* The drawn segments `drawn B` are the segments `[p, q]` for all pairs `p ≠ q` of points of `B` + ("join every pair of the 3n+3 boundary points by a chord"). A pair of points on a common side + gives a piece of that side, so the sides of the triangle belong to the drawing. +* `GeneralPosition B` is the entry's comment: no point of the interior of the triangle lies on + three pairwise distinct drawn segments. No other condition is imposed ("general position" is + read exactly as the comment explains it). +* The planar graph. Its vertices (`vertices B`) are the points of `B` and the points where two + drawn segments meet in a single point (`s ∩ t = {z}`; this excludes overlapping pieces of a + common side, whose points are not vertices). Two distinct vertices `u, v` are adjacent + (`planarGraph B`, a `SimpleGraph ℂ` whose non-vertices are isolated) iff they lie on a common + drawn segment and no vertex lies strictly between them (`openSegment ℝ u v`), i.e. `[u, v]` + is a piece of the drawing between consecutive vertices. `edges B` is the number of edges of + this graph (`edgeSet.ncard`; the edge set is finite since the vertex set is). +* The entry's `a(n)` is `edges B` for any `B` with `IsPlacement n B` and `GeneralPosition B` + (the entry presupposes that this number does not depend on the choice of `B`). The conjecture + is therefore read as: for every `n ≥ 0` (offset `0`) and every placement `B` of `n` points per + side in general position, `edges B = (3/2)(3n^4 + 4n^3 + 3n^2 + 4n + 2)`, as rationals. + +*The computable sequence `a`.* For the data check the count is computed combinatorially; the +link `a n = edges B` (for `B` as above) is the intended meaning and is not proved here. +Number the `3n+3` boundary points `0, 1, …, 3n+2` in cyclic order, with `corner j` at position +`j(n+1)`; the closed side `j` consists of the positions `j(n+1), …, (j+1)(n+1)` (position +`3(n+1)` being `0`). A pair of positions on a common closed side spans a piece of a side, and the +boundary is cut by the `3n+3` points into `3n+3` edges. Every other pair `x < y` +(`chordList n`) spans a chord whose relative interior lies in the open triangle (a segment +joining two boundary points of a convex polygon that are not on a common side). Two such chords +meet in the open triangle iff their endpoints are four distinct positions that interleave in the +cyclic order (`crosses`); chords sharing an endpoint meet only there, and two distinct chords +never overlap (a line not containing a side meets the boundary in at most two points). In general +position the points where a given chord meets the other chords are pairwise distinct, so the +chord is cut into `1 +` (number of chords crossing it) edges. Hence +`a n = (3n+3) + ∑_{chords c} (1 + #{chords crossing c})`. + +A Python transcription of `a` reproduces the listed terms for `n = 0, …, 15`. `a_data` checks +the first 11 listed terms `a 0, …, a 10` in the kernel. +-/ + +namespace Math0.Statements.A367119 + +/-! ### The geometric definition -/ + +/-- The corners `0`, `1`, `1/2 + (√3/2) i` of an equilateral triangle in the plane `ℂ`. -/ +noncomputable def corner : Fin 3 → ℂ := ![0, 1, ⟨1 / 2, Real.sqrt 3 / 2⟩] + +/-- The closed equilateral triangle. -/ +noncomputable def triangle : Set ℂ := convexHull ℝ (Set.range corner) + +/-- `B` is a placement of `n` points on each side of the triangle: `B` contains the three +corners, exactly `n` points in the relative interior of each side, and no other points (every +point of `B` lies on a closed side). -/ +def IsPlacement (n : ℕ) (B : Finset ℂ) : Prop := + (∀ j : Fin 3, corner j ∈ B) ∧ + (∀ z ∈ B, ∃ j : Fin 3, z ∈ segment ℝ (corner j) (corner (j + 1))) ∧ + (∀ j : Fin 3, ((B : Set ℂ) ∩ openSegment ℝ (corner j) (corner (j + 1))).ncard = n) + +/-- The drawn segments: the segments joining every pair of distinct boundary points. -/ +def drawn (B : Finset ℂ) : Set (Set ℂ) := + {s | ∃ p ∈ B, ∃ q ∈ B, p ≠ q ∧ s = segment ℝ p q} + +/-- General position (the entry's comment): there is no interior point of the triangle where +three or more of the drawn chords meet. -/ +def GeneralPosition (B : Finset ℂ) : Prop := + ∀ z ∈ interior triangle, ∀ s₁ ∈ drawn B, ∀ s₂ ∈ drawn B, ∀ s₃ ∈ drawn B, + z ∈ s₁ → z ∈ s₂ → z ∈ s₃ → s₁ = s₂ ∨ s₁ = s₃ ∨ s₂ = s₃ + +/-- The vertices of the planar graph: the boundary points, and the points where two drawn +segments meet in a single point. -/ +def vertices (B : Finset ℂ) : Set ℂ := + (B : Set ℂ) ∪ {z | ∃ s ∈ drawn B, ∃ t ∈ drawn B, s ∩ t = {z}} + +/-- The planar graph (on the vertex type `ℂ`, points that are not vertices being isolated): two +distinct vertices are adjacent iff they lie on a common drawn segment and no vertex lies strictly +between them. -/ +def planarGraph (B : Finset ℂ) : SimpleGraph ℂ := + SimpleGraph.fromRel fun u v => + u ∈ vertices B ∧ v ∈ vertices B ∧ (∃ s ∈ drawn B, u ∈ s ∧ v ∈ s) ∧ + ∀ w ∈ vertices B, w ∉ openSegment ℝ u v + +/-- The number of edges of the planar graph obtained from the boundary points `B`. -/ +noncomputable def edges (B : Finset ℂ) : ℕ := (planarGraph B).edgeSet.ncard + +/-! ### The combinatorial computation -/ + +/-- Boundary position `x` (`0 ≤ x < 3n+3`, corner `j` at position `j(n+1)`) lies on the closed +side `j` (`j < 3`), which consists of the positions `j(n+1), …, (j+1)(n+1)`, position +`3(n+1)` being position `0`. -/ +def onSide (n j x : ℕ) : Bool := + (j * (n + 1) ≤ x && x ≤ (j + 1) * (n + 1)) || (j == 2 && x == 0) + +/-- The positions `x < y` are not on a common closed side, so they span a chord through the +interior of the triangle. -/ +def isChord (n x y : ℕ) : Bool := + x < y && !((onSide n 0 x && onSide n 0 y) || (onSide n 1 x && onSide n 1 y) || + (onSide n 2 x && onSide n 2 y)) + +/-- The interior chords, as pairs of positions `(x, y)` with `x < y`. -/ +def chordList (n : ℕ) : List (ℕ × ℕ) := + (List.range (3 * n + 3)).flatMap fun x => + ((List.range (3 * n + 3)).filter fun y => isChord n x y).map fun y => (x, y) + +/-- Two chords `(x, y)`, `(u, v)` (`x < y`, `u < v`) cross inside the triangle: their four +endpoints are distinct and interleave in the cyclic order. -/ +def crosses (c d : ℕ × ℕ) : Bool := + (c.1 < d.1 && d.1 < c.2 && c.2 < d.2) || (d.1 < c.1 && c.1 < d.2 && d.2 < c.2) + +/-- The number of edges lying on the chords: each chord is cut into `1 +` (number of chords +crossing it) edges. -/ +def chordEdges (cs : List (ℕ × ℕ)) : ℕ := + (cs.map fun c => 1 + cs.countP fun d => crosses c d).sum + +/-- A367119: the number of edges of the planar graph formed by all chords joining the `3n+3` +boundary points of an equilateral triangle with `n` points in general position on each side: +`3n+3` boundary edges plus the edges on the interior chords. -/ +def a (n : ℕ) : ℕ := + (3 * n + 3) + chordEdges (chordList n) + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 11).map (fun i => a i) = + [3, 24, 153, 588, 1635, 3708, 7329, 13128, 21843, 34320, 51513] := by + decide +kernel + +/-- Conjecture (Shannon and Sloane, 2023): for every `n ≥ 0`, if `n` points are placed in +general position on each side of an equilateral triangle and every pair of the `3n+3` boundary +points is joined by a chord, the resulting planar graph has +`(3/2)(3n^4 + 4n^3 + 3n^2 + 4n + 2)` edges. -/ +def statement : Prop := + ∀ (n : ℕ) (B : Finset ℂ), IsPlacement n B → GeneralPosition B → + (edges B : ℚ) = 3 / 2 * (3 * n ^ 4 + 4 * n ^ 3 + 3 * n ^ 2 + 4 * n + 2) + +end Math0.Statements.A367119 diff --git a/lean/Math0/Statements/OEIS/A368846.lean b/lean/Math0/Statements/OEIS/A368846.lean new file mode 100644 index 0000000..61f187e --- /dev/null +++ b/lean/Math0/Statements/OEIS/A368846.lean @@ -0,0 +1,130 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A368846: Luschny's diagonal sums of the Bernoulli triangle and A229580 + +Source: https://oeis.org/A368846, Peter Luschny, Jan 07 2024 (COMMENTS section). Verbatim: +> Conjecture: |Sum_{j=0..k} T(k + j, k)| = A229580(k + 1) for k >= 0. + +The entry (offset `0`, keywords `sign,tabl`) is "Triangle read by rows: T(n, k) = (-1)^(n + k)*2* +binomial(2*k - 1, n)* binomial(2*n + 1, 2*k) for k > 0, and k^n for k = 0." The referenced +sequence A229580 (R. H. Hardin, Sep 26 2013, offset `1`) is "Number of defective 3-colorings of an +n X 2 0..2 array connected horizontally and antidiagonally with exactly one mistake, and colors +introduced in row-major 0..2 order." + +## Encoding + +* *The triangle.* `T n k : ℤ` is the displayed formula, with `ℕ`-valued binomials cast to `ℤ`. + For `k > 0` the factor `2*k - 1` is a natural number (`k ≥ 1`), so truncated subtraction is + harmless. For `k = 0` the value is `k^n = 0^n` (so `T 0 0 = 1` and `T n 0 = 0` for `n > 0`). + The formula is used for all `n, k`; the conjecture only evaluates `T (k + j) k` with + `k ≤ k + j`, i.e. inside the triangle `0 ≤ k ≤ n`. +* *The sequence.* `a` is the triangle read by rows (the OEIS sequence itself, offset `0`); rows + `0, …, i` hold at least `i + 1` entries, so the `i`-th entry of the concatenation lies among + them. `a_data` checks all 55 listed terms (rows `0, …, 9`) in the kernel. +* *A229580.* An `n X 2` array has `n` rows and `2` columns (as in the examples of A229580, which + show `3` rows of `2` entries for `n = 3`). A cell is `(i, j) : Fin n × Fin 2` (row `i`, column + `j`), and a 0..2 coloring is a map `c : Fin n × Fin 2 → Fin 3`. The connections are + horizontal, `(i, 0)–(i, 1)`, and antidiagonal, `(i, 1)–(i + 1, 0)`; `IsEdge p q` lists each + such edge exactly once, as the ordered pair `(p, q)` in which `p` comes first in row-major + order. A *mistake* is an edge whose two ends have the same color; `mistakes c` counts them. + *Colors introduced in row-major 0..2 order* (`ColorsInOrder c`): writing `rank (i, j) = + 2 i + j` for the row-major position, every cell of nonzero color `t` is preceded (in row-major + order) by some cell of color `t - 1`. Equivalently the row-major color word is a restricted + growth word: it starts with `0`, and each color first appears only after all smaller colors + have appeared; this picks one coloring from each orbit under permutations of the colors. + `A229580 n` is the number of colorings with exactly one mistake and colors introduced in this + order. `A229580_data` checks `A229580 1, A229580 2, A229580 3 = 1, 6, 40` (the first three + listed terms) in the kernel; larger `n` enumerate `3^(2n)` maps and are too slow. +* *The conjecture.* `statement`: for every `k ≥ 0`, + `|∑_{j=0}^{k} T(k + j, k)| = A229580(k + 1)`, computed in `ℤ`. +* *Sanity checks* (of the transcription, not a proof): `sum_data` evaluates the left-hand side + for `k = 0, …, 21` and finds the 22 terms listed in A229580, and `statement_check` confirms + the conjecture with the definition `A229580` for `k = 0, 1, 2`. +-/ + +namespace Math0.Statements.A368846 + +/-! ### The triangle A368846 -/ + +/-- The triangle of A368846: `T(n, k) = (-1)^(n + k) * 2 * binomial(2k - 1, n) * +binomial(2n + 1, 2k)` for `k > 0`, and `T(n, 0) = k^n = 0^n`. -/ +def T (n k : ℕ) : ℤ := + if k = 0 then 0 ^ n + else (-1) ^ (n + k) * 2 * ((2 * k - 1).choose n : ℤ) * ((2 * n + 1).choose (2 * k) : ℤ) + +/-- A368846 as a sequence (offset `0`): the triangle `T` (`0 ≤ k ≤ n`) read by rows. -/ +def a (i : ℕ) : ℤ := + ((List.range (i + 1)).flatMap fun n => (List.range (n + 1)).map (T n)).getD i 0 + +/-- The definition reproduces all 55 terms listed in OEIS, `a 0, …, a 54` (kernel-checked). -/ +theorem a_data : (List.range 55).map (fun i => a (i + 0)) = + [1, 0, 6, 0, 0, 30, 0, 0, -70, 140, 0, 0, 0, -840, 630, 0, 0, 0, 924, -6930, 2772, 0, 0, 0, + 0, 18018, -48048, 12012, 0, 0, 0, 0, -12870, 216216, -300300, 51480, 0, 0, 0, 0, 0, + -350064, 2042040, -1750320, 218790, 0, 0, 0, 0, 0, 184756, -5542680, 16628040, -9699690, + 923780] := by + decide +kernel + +/-! ### A229580: defective 3-colorings of the `n X 2` array -/ + +/-- A cell `(i, j)` of the `n X 2` array: row `i < n`, column `j < 2`. -/ +abbrev Cell (n : ℕ) := Fin n × Fin 2 + +/-- The row-major position of the cell `(i, j)`: `2 i + j`. -/ +def Cell.rank {n : ℕ} (p : Cell n) : ℕ := 2 * p.1.val + p.2.val + +/-- The connections of the array: horizontal `(i, 0)–(i, 1)` and antidiagonal +`(i, 1)–(i + 1, 0)`. Each edge is listed once, as the ordered pair `(p, q)` with `p` first in +row-major order. -/ +def IsEdge {n : ℕ} (p q : Cell n) : Prop := + (p.1 = q.1 ∧ p.2 = 0 ∧ q.2 = 1) ∨ (p.1.val + 1 = q.1.val ∧ p.2 = 1 ∧ q.2 = 0) + +instance {n : ℕ} : DecidableRel (IsEdge (n := n)) := fun p q => by + unfold IsEdge; infer_instance + +/-- The number of mistakes of a coloring: edges whose two ends have the same color. -/ +def mistakes {n : ℕ} (c : Cell n → Fin 3) : ℕ := + (Finset.univ.filter fun e : Cell n × Cell n => IsEdge e.1 e.2 ∧ c e.1 = c e.2).card + +/-- Colors are introduced in row-major `0..2` order: every cell of nonzero color `t` is preceded, +in row-major order, by a cell of color `t - 1`. -/ +def ColorsInOrder {n : ℕ} (c : Cell n → Fin 3) : Prop := + ∀ p : Cell n, c p ≠ 0 → ∃ q : Cell n, q.rank < p.rank ∧ (c q).val + 1 = (c p).val + +instance {n : ℕ} : DecidablePred (ColorsInOrder (n := n)) := fun c => by + unfold ColorsInOrder; infer_instance + +/-- A229580(n): the number of 0..2 colorings of the `n X 2` array, connected horizontally and +antidiagonally, with exactly one mistake and colors introduced in row-major `0..2` order. -/ +def A229580 (n : ℕ) : ℕ := + (Finset.univ.filter fun c : Cell n → Fin 3 => mistakes c = 1 ∧ ColorsInOrder c).card + +/-- The definition of A229580 reproduces its first three listed terms (kernel-checked). -/ +theorem A229580_data : (List.range 3).map (fun i => A229580 (i + 1)) = [1, 6, 40] := by + decide +kernel + +/-! ### The conjecture -/ + +/-- Sanity check: `|∑_{j=0}^{k} T(k + j, k)|` for `k = 0, …, 21` are the 22 terms of A229580 +listed in OEIS (kernel-checked). -/ +theorem sum_data : (List.range 22).map (fun k => |∑ j ∈ Finset.range (k + 1), T (k + j) k|) = + [1, 6, 40, 224, 1152, 5632, 26624, 122880, 557056, 2490368, 11010048, 48234496, 209715200, + 905969664, 3892314112, 16642998272, 70866960384, 300647710720, 1271310319616, + 5360119185408, 22539988369408, 94557999988736] := by + decide +kernel + +/-- Luschny's conjecture: for every `k ≥ 0`, the absolute value of the `k`-th column sum +`∑_{j=0}^{k} T(k + j, k)` of the triangle A368846 equals A229580(k + 1). -/ +def statement : Prop := + ∀ k : ℕ, |∑ j ∈ Finset.range (k + 1), T (k + j) k| = (A229580 (k + 1) : ℤ) + +/-- Sanity check of the transcription: the conjecture holds for `k = 0, 1, 2` (kernel-checked; +this is not a proof of `statement`). -/ +theorem statement_check : + ∀ k < 3, |∑ j ∈ Finset.range (k + 1), T (k + j) k| = (A229580 (k + 1) : ℤ) := by + decide +kernel + +end Math0.Statements.A368846 diff --git a/lean/Math0/Statements/OEIS/A369366.lean b/lean/Math0/Statements/OEIS/A369366.lean new file mode 100644 index 0000000..70d65d3 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A369366.lean @@ -0,0 +1,833 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A369366: least number of inequivalent cells of an `n`-iamond, `a(6k+5) = 3(k+1)` + +Source: https://oeis.org/A369366, _Peter Exley_, Apr 07 2026 (COMMENTS section). Verbatim: +> Conjecture: a(6k+5) = 3(k+1) for all k >= 0. Observed for k = 0, 1, 2 (n = 5, 11, 17). The +> next test case is a(23), predicted to be 12. + +The entry (offset `1`) is "Least number of inequivalent cells in a polyiamond with n cells.", +with the comment "Equivalently, a(n) is the least number of free rooted (or pointed) polyiamonds +(A369365) corresponding to a given polyiamond with n cells." + +## Encoding + +* *Cells.* The triangular grid is cut by three families of parallel lines. A cell (triangle) is + labelled by the indices `(a, b, c) ∈ ℤ³` of the strips of the three families that contain it + (`⌊p·u₁⌋, ⌊p·u₂⌋, ⌊p·u₃⌋` for an interior point `p`, where `u₁ + u₂ + u₃ = 0`, shifted by a + constant), normalised so that `a + b + c ∈ {0, 1}` (`0` for one orientation of triangles, `1` + for the other). Every such triple is exactly one cell (`IsCell`). Two cells share an edge iff + their labels differ by `±1` in exactly one coordinate, i.e. `|a - a'| + |b - b'| + |c - c'| = 1` + (`Adj`). +* *Polyiamonds.* A polyiamond with `n` cells is a finite set `P` of `n` cells that is + edge-connected (`IsConnected`: any two cells of `P` are joined by a chain of cells of `P`, + consecutive ones sharing an edge). `IsPolyiamond n P`. +* *Symmetries.* The symmetries of the triangular grid (the wallpaper group `p6m`) are, in these + coordinates, the maps `x ↦ σ(x) + t` with `t₁ + t₂ + t₃ = 0` and `x ↦ -σ(x) + t` with + `t₁ + t₂ + t₃ = 1`, where `σ` is one of the six permutations of the coordinates (`perm`): + the coordinate permutations are the reflections and `120°`-rotations exchanging the three line + families, `x ↦ -x + (const)` is a half-turn, and the translations of the grid are the integer + vectors with coordinate sum `0` (`Isom`, `Isom.app`). (An isometry of the plane mapping a + polyiamond onto itself maps its boundary corners, which are grid vertices, to grid vertices and + its boundary edge directions to grid directions, so it is a symmetry of the grid: reading + "inequivalent" with all isometries of the plane gives the same classes.) +* *Inequivalent cells.* Two cells `c, d` of `P` are equivalent (`Equivalent P c d`) when some + symmetry of the grid maps `P` onto itself and `c` to `d`; equivalently, the rooted polyiamonds + `(P, c)` and `(P, d)` are the same free rooted polyiamond. This is an equivalence relation + (`equivalent_refl`, `equivalent_symm`, `equivalent_trans`); `numClasses P` is the number of its + classes, i.e. the number of distinct sets `{d ∈ P | Equivalent P c d}` for `c ∈ P`. +* `a n` is the least value of `numClasses P` over all polyiamonds `P` with `n` cells (`sInf`; + this set is nonempty for every `n ≥ 1`). This definition is not computable as it stands. + `a_eq_aComp` proves `a n = aComp n` for every `n ≥ 1`, where `aComp` enumerates the + polyiamonds with `n` cells up to symmetry (`polys`: grown one cell at a time from a single + cell, each new set replaced by its image under some symmetry of the grid (`canon`), exact + duplicates removed) and computes the number of classes from the explicit list of symmetries of + each listed set (`numClassesC`; the translation part of a symmetry is forced by the centroid, + `t_eq_of_sym`). The proof uses only soundness and completeness of the enumeration up to + symmetry (`isPolyiamond_of_mem_polys`, `exists_sub_mem_polys`) and the invariance of + `numClasses` under symmetries of the grid (`numClasses_image`); which symmetric image `canon` + picks (`bestLin`, `keyOf`, `codeZ`) only affects efficiency, not correctness. +* `a_data` checks the first 8 listed terms `a(1), …, a(8)` in the kernel (about a minute). Each + further term multiplies the kernel time by about three (the enumeration has 66, 160, 448 free + polyiamonds with 8, 9, 10 cells), so `a(9)`, `a(10)`, … are not checked. +* The conjecture is stated for every `k ≥ 0`: `a (6k + 5) = 3(k + 1)`. +-/ + +namespace Math0.Statements.A369366 + +/-! ### Cells, adjacency and the symmetries of the triangular grid -/ + +/-- Labels `(a, b, c) ∈ ℤ³`; the cells of the triangular grid are the labels with coordinate sum +`0` or `1`. -/ +abbrev Pt := ℤ × ℤ × ℤ + +/-- The coordinate sum `a + b + c`. -/ +def sumC (x : Pt) : ℤ := x.1 + x.2.1 + x.2.2 + +/-- `x` is (the label of) a cell of the triangular grid. -/ +def IsCell (x : Pt) : Prop := sumC x = 0 ∨ sumC x = 1 + +/-- The cells `x` and `y` share an edge: their labels differ by `±1` in exactly one coordinate. -/ +def Adj (x y : Pt) : Prop := |y.1 - x.1| + |y.2.1 - x.2.1| + |y.2.2 - x.2.2| = 1 + +/-- The six permutations `σ` of the three coordinates. -/ +def perm {α : Type} (s : Fin 6) (x : α × α × α) : α × α × α := + match s.val with + | 0 => (x.1, x.2.1, x.2.2) + | 1 => (x.1, x.2.2, x.2.1) + | 2 => (x.2.1, x.1, x.2.2) + | 3 => (x.2.1, x.2.2, x.1) + | 4 => (x.2.2, x.1, x.2.1) + | _ => (x.2.2, x.2.1, x.1) + +/-- The linear part `x ↦ σ(x)` (`neg = false`) or `x ↦ -σ(x)` (`neg = true`) of a symmetry. -/ +def lin (s : Fin 6) (neg : Bool) (x : Pt) : Pt := if neg then -perm s x else perm s x + +/-- The coordinate sum required of the translation part: `0` for `x ↦ σ(x) + t`, `1` for +`x ↦ -σ(x) + t`. -/ +def tReq (neg : Bool) : ℤ := if neg then 1 else 0 + +/-- A symmetry of the triangular grid: `x ↦ σ(x) + t` with `t₁ + t₂ + t₃ = 0`, or +`x ↦ -σ(x) + t` with `t₁ + t₂ + t₃ = 1`. -/ +structure Isom where + /-- the coordinate permutation `σ` -/ + s : Fin 6 + /-- whether the map is `x ↦ -σ(x) + t` -/ + neg : Bool + /-- the translation part -/ + t : Pt + ht : sumC t = tReq neg + +/-- The action of a symmetry on labels. -/ +def Isom.app (g : Isom) (x : Pt) : Pt := lin g.s g.neg x + g.t + +/-! ### Polyiamonds and inequivalent cells -/ + +/-- One step of a chain inside `P`: two cells of `P` sharing an edge. -/ +def Step (P : Finset Pt) (u v : Pt) : Prop := u ∈ P ∧ v ∈ P ∧ Adj u v + +/-- `P` is edge-connected: any two cells of `P` are joined by a chain of cells of `P` in which +consecutive cells share an edge. -/ +def IsConnected (P : Finset Pt) : Prop := + ∀ x ∈ P, ∀ y ∈ P, Relation.ReflTransGen (Step P) x y + +/-- `P` is a polyiamond with `n` cells. -/ +def IsPolyiamond (n : ℕ) (P : Finset Pt) : Prop := + P.card = n ∧ (∀ x ∈ P, IsCell x) ∧ IsConnected P + +/-- The cells `c` and `d` of `P` are equivalent: some symmetry of the grid maps `P` onto itself +and `c` to `d`. -/ +def Equivalent (P : Finset Pt) (c d : Pt) : Prop := + ∃ g : Isom, P.image g.app = P ∧ g.app c = d + +open Classical in +/-- The equivalence class `{d ∈ P | Equivalent P c d}` of `c` in `P`. -/ +noncomputable def cls (P : Finset Pt) (c : Pt) : Finset Pt := P.filter (Equivalent P c) + +/-- The number of inequivalent cells of `P` (the number of equivalence classes). -/ +noncomputable def numClasses (P : Finset Pt) : ℕ := (P.image (cls P)).card + +/-- A369366: the least number of inequivalent cells in a polyiamond with `n` cells. -/ +noncomputable def a (n : ℕ) : ℕ := + sInf {m | ∃ P : Finset Pt, IsPolyiamond n P ∧ numClasses P = m} + +/-! ### Algebra of the symmetries -/ + +/-- Multiplication table of the coordinate permutations: `perm (mulTab i j) = perm i ∘ perm j`. -/ +def mulTab (i j : Fin 6) : Fin 6 := + ![![0, 1, 2, 3, 4, 5], ![1, 0, 3, 2, 5, 4], ![2, 4, 0, 5, 1, 3], ![3, 5, 1, 4, 0, 2], + ![4, 2, 5, 0, 3, 1], ![5, 3, 4, 1, 2, 0]] i j + +/-- Inverses of the coordinate permutations. -/ +def invTab (i : Fin 6) : Fin 6 := ![0, 1, 2, 4, 3, 5] i + +theorem perm_mul (i j : Fin 6) (x : Pt) : perm (mulTab i j) x = perm i (perm j x) := by + fin_cases i <;> fin_cases j <;> rfl + +theorem perm_zero (x : Pt) : perm 0 x = x := rfl + +theorem mulTab_invTab (i : Fin 6) : mulTab i (invTab i) = 0 := by + fin_cases i <;> rfl + +theorem invTab_mulTab (i : Fin 6) : mulTab (invTab i) i = 0 := by + fin_cases i <;> rfl + +theorem perm_add (s : Fin 6) (x y : Pt) : perm s (x + y) = perm s x + perm s y := by + fin_cases s <;> rfl + +theorem perm_neg (s : Fin 6) (x : Pt) : perm s (-x) = -perm s x := by + fin_cases s <;> rfl + +theorem sumC_perm (s : Fin 6) (x : Pt) : sumC (perm s x) = sumC x := by + fin_cases s <;> simp only [perm, sumC] <;> ring + +theorem sumC_add (x y : Pt) : sumC (x + y) = sumC x + sumC y := by + simp only [sumC, Prod.fst_add, Prod.snd_add] + ring + +theorem sumC_neg (x : Pt) : sumC (-x) = -sumC x := by + simp only [sumC, Prod.fst_neg, Prod.snd_neg] + ring + +theorem lin_add (s : Fin 6) (n : Bool) (x y : Pt) : lin s n (x + y) = lin s n x + lin s n y := by + cases n + · simp [lin, perm_add] + · simp only [lin, if_true, perm_add, neg_add] + +theorem lin_neg (s : Fin 6) (n : Bool) (x : Pt) : lin s n (-x) = -lin s n x := by + cases n <;> simp [lin, perm_neg] + +theorem lin_sub (s : Fin 6) (n : Bool) (x y : Pt) : lin s n (x - y) = lin s n x - lin s n y := by + rw [sub_eq_add_neg, lin_add, lin_neg, ← sub_eq_add_neg] + +theorem lin_lin (s₁ s₂ : Fin 6) (n₁ n₂ : Bool) (x : Pt) : + lin s₁ n₁ (lin s₂ n₂ x) = lin (mulTab s₁ s₂) (Bool.xor n₁ n₂) x := by + cases n₁ <;> cases n₂ <;> simp [lin, perm_neg, perm_mul] + +theorem lin_zero (x : Pt) : lin 0 false x = x := rfl + +theorem sumC_lin (s : Fin 6) (n : Bool) (x : Pt) : + sumC (lin s n x) = if n then -sumC x else sumC x := by + cases n <;> simp [lin, sumC_neg, sumC_perm] + +/-- The identity symmetry. -/ +def Isom.id : Isom := ⟨0, false, 0, by simp [sumC, tReq]⟩ + +theorem Isom.id_app (x : Pt) : Isom.id.app x = x := by + simp [Isom.id, Isom.app, lin_zero] + +theorem Isom.id_app' : Isom.id.app = _root_.id := funext Isom.id_app + +/-- Composition of symmetries. -/ +def Isom.comp (g h : Isom) : Isom where + s := mulTab g.s h.s + neg := Bool.xor g.neg h.neg + t := lin g.s g.neg h.t + g.t + ht := by + rw [sumC_add, sumC_lin, g.ht, h.ht] + cases g.neg <;> cases h.neg <;> simp [tReq] + +theorem Isom.comp_app (g h : Isom) (x : Pt) : (g.comp h).app x = g.app (h.app x) := by + simp only [Isom.app, Isom.comp, lin_add, lin_lin] + abel + +/-- The inverse of a symmetry. -/ +def Isom.inv (g : Isom) : Isom where + s := invTab g.s + neg := g.neg + t := -lin (invTab g.s) g.neg g.t + ht := by + rw [sumC_neg, sumC_lin, g.ht] + cases g.neg <;> simp [tReq] + +theorem Isom.inv_app_app (g : Isom) (x : Pt) : g.inv.app (g.app x) = x := by + simp only [Isom.app, Isom.inv, lin_add, lin_lin, invTab_mulTab, Bool.xor_self, lin_zero] + abel + +theorem Isom.app_inv_app (g : Isom) (x : Pt) : g.app (g.inv.app x) = x := by + simp only [Isom.app, Isom.inv, lin_add, lin_neg, lin_lin, mulTab_invTab, Bool.xor_self, + lin_zero] + abel + +theorem Isom.app_injective (g : Isom) : Function.Injective g.app := fun x y h => by + rw [← g.inv_app_app x, h, g.inv_app_app] + +theorem Isom.isCell_app (g : Isom) {x : Pt} (hx : IsCell x) : IsCell (g.app x) := by + obtain ⟨s, n, t, ht⟩ := g + unfold IsCell at * + simp only [Isom.app, sumC_add, sumC_lin, ht, tReq] + cases n <;> simp <;> omega + +/-- The `ℓ¹` norm `|a| + |b| + |c|`. -/ +def l1 (v : Pt) : ℤ := |v.1| + |v.2.1| + |v.2.2| + +theorem adj_iff (x y : Pt) : Adj x y ↔ l1 (y - x) = 1 := Iff.rfl + +theorem l1_perm (s : Fin 6) (v : Pt) : l1 (perm s v) = l1 v := by + fin_cases s <;> simp only [perm, l1] <;> ring + +theorem l1_neg (v : Pt) : l1 (-v) = l1 v := by + simp only [l1, Prod.fst_neg, Prod.snd_neg, abs_neg] + +theorem l1_lin (s : Fin 6) (n : Bool) (v : Pt) : l1 (lin s n v) = l1 v := by + cases n + · simp [lin, l1_perm] + · simp only [lin, if_true, l1_neg, l1_perm] + +theorem Isom.adj_app (g : Isom) (x y : Pt) : Adj (g.app x) (g.app y) ↔ Adj x y := by + rw [adj_iff, adj_iff, Isom.app, Isom.app, add_sub_add_right_eq_sub, ← lin_sub, l1_lin] + +theorem adj_symm {x y : Pt} (h : Adj x y) : Adj y x := by + rw [adj_iff] at * + rw [← neg_sub, l1_neg] + exact h + +/-! ### Equivalence of cells -/ + +theorem image_image_app (P : Finset Pt) (g h : Isom) : + (P.image h.app).image g.app = P.image (g.comp h).app := by + rw [Finset.image_image] + congr 1 + funext x + exact (Isom.comp_app g h x).symm + +theorem image_inv_image (P : Finset Pt) (h : Isom) : (P.image h.app).image h.inv.app = P := by + rw [Finset.image_image] + conv_rhs => rw [← Finset.image_id (s := P)] + congr 1 + funext x + exact h.inv_app_app x + +theorem equivalent_refl (P : Finset Pt) (c : Pt) : Equivalent P c c := + ⟨Isom.id, by rw [Isom.id_app', Finset.image_id], Isom.id_app c⟩ + +theorem equivalent_symm {P : Finset Pt} {c d : Pt} (h : Equivalent P c d) : Equivalent P d c := by + obtain ⟨g, hg, rfl⟩ := h + refine ⟨g.inv, ?_, g.inv_app_app c⟩ + conv_lhs => rw [← hg] + exact image_inv_image P g + +theorem equivalent_trans {P : Finset Pt} {c d e : Pt} (h₁ : Equivalent P c d) + (h₂ : Equivalent P d e) : Equivalent P c e := by + obtain ⟨g, hg, rfl⟩ := h₁ + obtain ⟨h, hh, rfl⟩ := h₂ + refine ⟨h.comp g, ?_, h.comp_app g c⟩ + rw [← image_image_app, hg, hh] + +/-- Conjugating by a symmetry `h` of the grid. -/ +theorem equivalent_image (P : Finset Pt) (h : Isom) (c d : Pt) : + Equivalent (P.image h.app) (h.app c) (h.app d) ↔ Equivalent P c d := by + constructor + · rintro ⟨g, hg, hgc⟩ + refine ⟨h.inv.comp (g.comp h), ?_, ?_⟩ + · rw [← image_image_app, ← image_image_app, hg, image_inv_image] + · rw [Isom.comp_app, Isom.comp_app, hgc, Isom.inv_app_app] + · rintro ⟨g, hg, rfl⟩ + refine ⟨h.comp (g.comp h.inv), ?_, ?_⟩ + · rw [← image_image_app, ← image_image_app, image_inv_image, hg] + · rw [Isom.comp_app, Isom.comp_app, Isom.inv_app_app] + +theorem cls_image (P : Finset Pt) (h : Isom) (c : Pt) : + cls (P.image h.app) (h.app c) = (cls P c).image h.app := by + ext y + simp only [cls, Finset.mem_filter, Finset.mem_image] + constructor + · rintro ⟨⟨x, hx, rfl⟩, hxy⟩ + exact ⟨x, ⟨hx, (equivalent_image P h c x).1 hxy⟩, rfl⟩ + · rintro ⟨x, ⟨hx, hcx⟩, rfl⟩ + exact ⟨⟨x, hx, rfl⟩, (equivalent_image P h c x).2 hcx⟩ + +/-- The number of inequivalent cells is invariant under the symmetries of the grid. -/ +theorem numClasses_image (P : Finset Pt) (h : Isom) : + numClasses (P.image h.app) = numClasses P := by + unfold numClasses + rw [Finset.image_image] + have : (cls (P.image h.app) ∘ h.app) = (Finset.image h.app) ∘ cls P := by + funext c + exact cls_image P h c + rw [this, ← Finset.image_image] + exact Finset.card_image_of_injective _ (Finset.image_injective h.app_injective) + +/-- A symmetry maps `P` onto itself iff it maps `P` into itself. -/ +theorem image_eq_iff (P : Finset Pt) (g : Isom) : P.image g.app = P ↔ ∀ x ∈ P, g.app x ∈ P := by + constructor + · intro h x hx + rw [← h] + exact Finset.mem_image_of_mem _ hx + · intro h + apply Finset.eq_of_subset_of_card_le + · exact Finset.image_subset_iff.2 h + · exact (Finset.card_image_of_injective _ g.app_injective).ge + +/-! ### Computing the number of inequivalent cells -/ + +/-- The twelve linear parts `(σ, ±)`. -/ +def allLin : List (Fin 6 × Bool) := (List.finRange 6).flatMap fun s => [(s, false), (s, true)] + +theorem mem_allLin : ∀ sn : Fin 6 × Bool, sn ∈ allLin := by + decide + +/-- Componentwise integer division. -/ +def divPt (v : Pt) (k : ℤ) : Pt := (v.1 / k, v.2.1 / k, v.2.2 / k) + +theorem divPt_smul (t : Pt) {k : ℤ} (hk : k ≠ 0) : divPt (k • t) k = t := by + obtain ⟨a, b, c⟩ := t + simp [divPt, Int.mul_ediv_cancel_left _ hk] + +theorem perm_zero' (s : Fin 6) : perm s (0 : Pt) = 0 := by + fin_cases s <;> rfl + +/-- The linear part of a symmetry, as an additive map. -/ +def linHom (s : Fin 6) (n : Bool) : Pt →+ Pt where + toFun := lin s n + map_zero' := by cases n <;> simp [lin, perm_zero'] + map_add' := lin_add s n + +/-- A symmetry `g` of a nonempty finite set `P` fixes its centroid, so its translation part is +`(Σ P - (±σ)(Σ P)) / |P|`. -/ +theorem t_eq_of_sym {P : Finset Pt} (hP : P.Nonempty) {g : Isom} (hg : P.image g.app = P) : + g.t = divPt (P.sum id - lin g.s g.neg (P.sum id)) P.card := by + have h1 : P.sum id = P.sum g.app := by + conv_lhs => rw [← hg] + rw [Finset.sum_image fun x _ y _ h => g.app_injective h] + rfl + have h2 : P.sum g.app = lin g.s g.neg (P.sum id) + (P.card : ℤ) • g.t := by + rw [show P.sum g.app = ∑ x ∈ P, (lin g.s g.neg x + g.t) from rfl, + Finset.sum_add_distrib, Finset.sum_const, ← natCast_zsmul] + congr 1 + exact (map_sum (linHom g.s g.neg) id P).symm + rw [sub_eq_iff_eq_add'.2 (h1.trans h2), divPt_smul _ (by exact_mod_cast hP.card_pos.ne')] + +/-- The translation part forced by the centroid of `Q` for the linear part `sn`. -/ +def tOf (Q : List Pt) (sn : Fin 6 × Bool) : Pt := + divPt (Q.toFinset.sum id - lin sn.1 sn.2 (Q.toFinset.sum id)) Q.toFinset.card + +/-- The symmetries `(σ, ±, t)` of the grid mapping the cells of `Q` into themselves (the +translation part is forced by the centroid, `t_eq_of_sym`). -/ +def symsC (Q : List Pt) : List (Fin 6 × Bool × Pt) := + allLin.filterMap fun sn => + if sumC (tOf Q sn) = tReq sn.2 ∧ ∀ x ∈ Q, lin sn.1 sn.2 x + tOf Q sn ∈ Q then + some (sn.1, sn.2, tOf Q sn) + else none + +theorem of_mem_symsC {Q : List Pt} {s : Fin 6} {n : Bool} {t : Pt} (h : (s, n, t) ∈ symsC Q) : + sumC t = tReq n ∧ ∀ x ∈ Q, lin s n x + t ∈ Q := by + obtain ⟨sn, -, hsn⟩ := List.mem_filterMap.1 h + split_ifs at hsn with hc + cases hsn + exact hc + +theorem mem_symsC_of_sym {Q : List Pt} (hQ : Q ≠ []) {g : Isom} + (hg : Q.toFinset.image g.app = Q.toFinset) : (g.s, g.neg, g.t) ∈ symsC Q := by + have hne : Q.toFinset.Nonempty := by + obtain ⟨x, xs, rfl⟩ := List.exists_cons_of_ne_nil hQ + exact ⟨x, by simp⟩ + have ht : tOf Q (g.s, g.neg) = g.t := (t_eq_of_sym hne hg).symm + have hc : sumC g.t = tReq g.neg ∧ ∀ x ∈ Q, lin g.s g.neg x + g.t ∈ Q := + ⟨g.ht, fun x hx => List.mem_toFinset.1 ((image_eq_iff _ g).1 hg x (List.mem_toFinset.2 hx))⟩ + refine List.mem_filterMap.2 ⟨(g.s, g.neg), mem_allLin _, ?_⟩ + dsimp only + rw [ht, if_pos hc] + +/-- The orbit of `c` under the symmetries of `Q`. -/ +def orbitC (Q : List Pt) (c : Pt) : List Pt := (symsC Q).map fun g => lin g.1 g.2.1 c + g.2.2 + +theorem equivalent_iff_mem_orbitC {Q : List Pt} (hQ : Q ≠ []) (c d : Pt) : + Equivalent Q.toFinset c d ↔ d ∈ orbitC Q c := by + simp only [orbitC, List.mem_map] + constructor + · rintro ⟨g, hg, rfl⟩ + exact ⟨(g.s, g.neg, g.t), mem_symsC_of_sym hQ hg, rfl⟩ + · rintro ⟨⟨s, n, t⟩, hm, rfl⟩ + obtain ⟨h1, h2⟩ := of_mem_symsC hm + refine ⟨⟨s, n, t, h1⟩, (image_eq_iff _ _).2 fun x hx => ?_, rfl⟩ + exact List.mem_toFinset.2 (h2 x (List.mem_toFinset.1 hx)) + +/-- The number of inequivalent cells of the polyiamond listed by `Q`, computed from the list of +its symmetries. -/ +def numClassesC (Q : List Pt) : ℕ := + (Q.toFinset.image fun c => Q.toFinset.filter (· ∈ orbitC Q c)).card + +theorem numClassesC_eq {Q : List Pt} (hQ : Q ≠ []) : numClassesC Q = numClasses Q.toFinset := by + unfold numClassesC numClasses + congr 1 + apply Finset.image_congr + intro c _ + ext d + simp only [cls, Finset.mem_filter] + exact and_congr_right fun _ => (equivalent_iff_mem_orbitC hQ c d).symm + +/-! ### Enumerating polyiamonds up to symmetry -/ + +/-- The three cells sharing an edge with the cell `x`. -/ +def nbrs (x : Pt) : List Pt := + if sumC x = 0 then [x + (1, 0, 0), x + (0, 1, 0), x + (0, 0, 1)] + else [x - (1, 0, 0), x - (0, 1, 0), x - (0, 0, 1)] + +theorem of_mem_nbrs {x y : Pt} (hx : IsCell x) (h : y ∈ nbrs x) : Adj x y ∧ IsCell y := by + unfold nbrs at h + unfold IsCell sumC at * + unfold Adj + split_ifs at h <;> + · simp only [List.mem_cons, List.not_mem_nil, or_false, Prod.ext_iff, Prod.fst_add, + Prod.snd_add, Prod.fst_sub, Prod.snd_sub] at h + rcases abs_cases (y.1 - x.1) with h1 | h1 <;> rcases abs_cases (y.2.1 - x.2.1) with h2 | h2 <;> + rcases abs_cases (y.2.2 - x.2.2) with h3 | h3 <;> omega + +theorem mem_nbrs {x y : Pt} (hx : IsCell x) (hy : IsCell y) (h : Adj x y) : y ∈ nbrs x := by + unfold nbrs + unfold IsCell sumC at * + unfold Adj at h + split_ifs <;> + · simp only [List.mem_cons, List.not_mem_nil, or_false, Prod.ext_iff, Prod.fst_add, + Prod.snd_add, Prod.fst_sub, Prod.snd_sub] + rcases abs_cases (y.1 - x.1) with h1 | h1 <;> rcases abs_cases (y.2.1 - x.2.1) with h2 | h2 <;> + rcases abs_cases (y.2.2 - x.2.2) with h3 | h3 <;> omega + +/-- The least element of a list of naturals (`0` for the empty list). -/ +def listMin : List ℕ → ℕ + | [] => 0 + | x :: xs => xs.foldl min x + +/-- The largest element of a list of naturals (`0` for the empty list). -/ +def listMax : List ℕ → ℕ + | [] => 0 + | x :: xs => xs.foldl max x + +/-- A translation (coordinate sum `0`) moving the least first and second coordinates of the +cells of `l` to `0`. -/ +def shiftOf : List Pt → Pt + | [] => 0 + | x :: xs => + (-(xs.foldl (fun m y => min m y.1) x.1), -(xs.foldl (fun m y => min m y.2.1) x.2.1), + xs.foldl (fun m y => min m y.1) x.1 + xs.foldl (fun m y => min m y.2.1) x.2.1) + +theorem sumC_shiftOf (l : List Pt) : sumC (shiftOf l) = 0 := by + cases l with + | nil => rfl + | cons x xs => simp only [shiftOf, sumC]; ring + +/-- `(1, 0, 0)` for `x ↦ -σ(x)` (to bring the coordinate sums back to `{0, 1}`), else `0`. -/ +def eVec (neg : Bool) : Pt := if neg then (1, 0, 0) else 0 + +theorem sumC_eVec (neg : Bool) : sumC (eVec neg) = tReq neg := by + cases neg <;> rfl + +/-- The image of `l` under the linear part `sn`, translated so that the least first and second +coordinates of its cells are `0`. -/ +def image12 (l : List Pt) (sn : Fin 6 × Bool) : List Pt := + (l.map fun x => lin sn.1 sn.2 x + eVec sn.2).map + (· + shiftOf (l.map fun x => lin sn.1 sn.2 x + eVec sn.2)) + +/-- A numerical code of a cell (used only to order cells). -/ +def codeZ (x : Pt) : ℕ := (x.1.toNat * 128 + x.2.1.toNat) * 2 + (sumC x).toNat + +/-- Offset natural coordinates of a label (used only to choose a representative). -/ +def natC (x : Pt) : ℕ × ℕ × ℕ := ((x.1 + 64).toNat, (x.2.1 + 64).toNat, (x.2.2 + 64).toNat) + +/-- For a cell with offset coordinates `p`, given the coordinatewise minima `mn` and maxima `mx`: +`(p - mn, mx - p, orientation)` (used only to choose a representative). -/ +def prep (mn mx : ℕ × ℕ × ℕ) (p : ℕ × ℕ × ℕ) : (ℕ × ℕ × ℕ) × (ℕ × ℕ × ℕ) × ℕ := + ((p.1 - mn.1, p.2.1 - mn.2.1, p.2.2 - mn.2.2), (mx.1 - p.1, mx.2.1 - p.2.1, mx.2.2 - p.2.2), + p.1 + p.2.1 + p.2.2 - 192) + +/-- For small polyiamonds, the sum of `2 ^ codeZ y` over the cells `y` of `image12 l sn`, +computed with natural numbers from the data `prep` of the cells of `l` (used only to choose a +representative). -/ +def keyOf (D : List ((ℕ × ℕ × ℕ) × (ℕ × ℕ × ℕ) × ℕ)) (sn : Fin 6 × Bool) : ℕ := + D.foldl (fun acc d => acc + 2 ^ (if sn.2 then + ((perm sn.1 d.2.1).1 * 128 + (perm sn.1 d.2.1).2.1) * 2 + (1 - d.2.2) + else ((perm sn.1 d.1).1 * 128 + (perm sn.1 d.1).2.1) * 2 + d.2.2)) 0 + +/-- A linear part whose normalised image of `l` has the least key, with that key (used only to +choose a representative). -/ +def bestLin (l : List Pt) : ℕ × (Fin 6 × Bool) := + let N := l.map natC + let mn := (listMin (N.map (·.1)), listMin (N.map (·.2.1)), listMin (N.map (·.2.2))) + let mx := (listMax (N.map (·.1)), listMax (N.map (·.2.1)), listMax (N.map (·.2.2))) + let D := N.map (prep mn mx) + allLin.foldl (fun best sn => if keyOf D sn < best.1 then (keyOf D sn, sn) else best) + (keyOf D (0, false), (0, false)) + +/-- A representative of the cell set `l` up to symmetry, with a key: a normalised image of `l` +under one of the twelve linear parts, its cells sorted. -/ +def canon (l : List Pt) : ℕ × List Pt := + ((bestLin l).1, (image12 l (bestLin l).2).insertionSort fun x y => codeZ x ≤ codeZ y) + +theorem toFinset_map (l : List Pt) (f : Pt → Pt) : (l.map f).toFinset = l.toFinset.image f := by + ext x + simp + +theorem image12_spec (l : List Pt) (sn : Fin 6 × Bool) : + ∃ g : Isom, (image12 l sn).toFinset = l.toFinset.image g.app := by + refine ⟨⟨sn.1, sn.2, eVec sn.2 + shiftOf (l.map fun x => lin sn.1 sn.2 x + eVec sn.2), ?_⟩, ?_⟩ + · rw [sumC_add, sumC_eVec, sumC_shiftOf, add_zero] + · rw [image12, List.map_map, toFinset_map] + congr 1 + funext x + simp only [Function.comp, Isom.app, add_assoc] + +theorem canon_spec (l : List Pt) : + ∃ g : Isom, (canon l).2.toFinset = l.toFinset.image g.app := by + obtain ⟨g, hg⟩ := image12_spec l (bestLin l).2 + refine ⟨g, ?_⟩ + simp only [canon] + rw [List.toFinset_eq_of_perm _ _ (List.perm_insertionSort _ _), hg] + +/-- The cell sets obtained from `Q` by adding one cell sharing an edge with a cell of `Q`, each +replaced by its representative up to symmetry. -/ +def children (Q : List Pt) : List (ℕ × List Pt) := + (Q.flatMap nbrs).filterMap fun y => if y ∈ Q then none else some (canon (y :: Q)) + +/-- Insert `k` into `acc` unless it is already there. -/ +def addNew (acc : List (ℕ × List Pt)) (k : ℕ × List Pt) : List (ℕ × List Pt) := + if k ∈ acc then acc else k :: acc + +theorem mem_foldl_addNew (k : ℕ × List Pt) : + ∀ (l acc : List (ℕ × List Pt)), k ∈ l.foldl addNew acc ↔ k ∈ acc ∨ k ∈ l + | [], acc => by simp + | x :: xs, acc => by + rw [List.foldl_cons, mem_foldl_addNew k xs, addNew] + split_ifs with h + · constructor + · rintro (h' | h') + · exact Or.inl h' + · exact Or.inr (List.mem_cons_of_mem _ h') + · rintro (h' | h') + · exact Or.inl h' + · rcases List.mem_cons.1 h' with rfl | h' + · exact Or.inl h + · exact Or.inr h' + · simp only [List.mem_cons] + tauto + +/-- One growth step, with duplicates removed. -/ +def grow (L : List (ℕ × List Pt)) : List (ℕ × List Pt) := + (L.flatMap fun e => children e.2).foldl addNew [] + +theorem mem_grow {L : List (ℕ × List Pt)} {k : ℕ × List Pt} : + k ∈ grow L ↔ ∃ e ∈ L, ∃ b ∈ e.2, ∃ y ∈ nbrs b, y ∉ e.2 ∧ k = canon (y :: e.2) := by + rw [grow, mem_foldl_addNew] + simp only [List.not_mem_nil, false_or, List.mem_flatMap, children, List.mem_filterMap] + constructor + · rintro ⟨e, he, y, ⟨b, hb, hy⟩, h⟩ + split_ifs at h with hyQ + exact ⟨e, he, b, hb, y, hy, hyQ, (Option.some.inj h).symm⟩ + · rintro ⟨e, he, b, hb, y, hy, hyQ, rfl⟩ + exact ⟨e, he, y, ⟨b, hb, hy⟩, by rw [if_neg hyQ]⟩ + +/-- Representatives (with keys), up to symmetry, of all polyiamonds with `n` cells (possibly with +repetitions up to symmetry). -/ +def polys : ℕ → List (ℕ × List Pt) + | 0 => [(0, [])] + | 1 => [(0, [0])] + | n + 2 => grow (polys (n + 1)) + +theorem foldl_min_le : ∀ (xs : List ℕ) (x : ℕ), xs.foldl min x ≤ x ∧ ∀ y ∈ xs, xs.foldl min x ≤ y + | [], x => by simp + | z :: zs, x => by + obtain ⟨h1, h2⟩ := foldl_min_le zs (min x z) + refine ⟨h1.trans (min_le_left _ _), fun y hy => ?_⟩ + rcases List.mem_cons.1 hy with rfl | hy + · exact h1.trans (min_le_right _ _) + · exact h2 y hy + +theorem foldl_min_mem : ∀ (xs : List ℕ) (x : ℕ), xs.foldl min x ∈ x :: xs + | [], x => by simp + | z :: zs, x => by + rcases List.mem_cons.1 (foldl_min_mem zs (min x z)) with h | h + · rw [List.foldl_cons, h] + rcases min_choice x z with h' | h' <;> rw [h'] <;> simp + · exact List.mem_cons_of_mem _ (List.mem_cons_of_mem _ h) + +theorem listMin_le {l : List ℕ} {y : ℕ} (hy : y ∈ l) : listMin l ≤ y := by + cases l with + | nil => simp at hy + | cons x xs => + rcases List.mem_cons.1 hy with rfl | hy + · exact (foldl_min_le xs _).1 + · exact (foldl_min_le xs x).2 y hy + +theorem listMin_mem {l : List ℕ} (hl : l ≠ []) : listMin l ∈ l := by + cases l with + | nil => exact absurd rfl hl + | cons x xs => exact foldl_min_mem xs x + +/-- A computable version of A369366 (equal to `a n` for `n ≥ 1`, `a_eq_aComp`). -/ +def aComp (n : ℕ) : ℕ := listMin ((polys n).map fun e => numClassesC e.2) + +/-! ### Correctness of the enumeration -/ + +/-- Mapping a chain along `f`. -/ +theorem rtg_map {r p : Pt → Pt → Prop} (f : Pt → Pt) (h : ∀ u v, r u v → p (f u) (f v)) + {x y : Pt} (hxy : Relation.ReflTransGen r x y) : Relation.ReflTransGen p (f x) (f y) := by + induction hxy with + | refl => exact Relation.ReflTransGen.refl + | tail _ hbc ih => exact ih.tail (h _ _ hbc) + +theorem isPolyiamond_image {n : ℕ} {P : Finset Pt} (hP : IsPolyiamond n P) (g : Isom) : + IsPolyiamond n (P.image g.app) := by + obtain ⟨hcard, hcell, hconn⟩ := hP + refine ⟨by rw [Finset.card_image_of_injective _ g.app_injective, hcard], ?_, ?_⟩ + · intro x hx + obtain ⟨y, hy, rfl⟩ := Finset.mem_image.1 hx + exact g.isCell_app (hcell y hy) + · intro x' hx' y' hy' + obtain ⟨x, hx, rfl⟩ := Finset.mem_image.1 hx' + obtain ⟨y, hy, rfl⟩ := Finset.mem_image.1 hy' + exact rtg_map g.app + (fun u v (huv : Step P u v) => ⟨Finset.mem_image_of_mem _ huv.1, + Finset.mem_image_of_mem _ huv.2.1, (g.adj_app u v).2 huv.2.2⟩) + (hconn x hx y hy) + +theorem isConnected_insert {P : Finset Pt} (hP : IsConnected P) {b y : Pt} (hb : b ∈ P) + (hby : Adj b y) : IsConnected (insert y P) := by + have mono : ∀ u v, Relation.ReflTransGen (Step P) u v → + Relation.ReflTransGen (Step (insert y P)) u v := fun u v h => + rtg_map _root_.id (fun p q (hpq : Step P p q) => + ⟨Finset.mem_insert_of_mem hpq.1, Finset.mem_insert_of_mem hpq.2.1, hpq.2.2⟩) h + have hbI : b ∈ insert y P := Finset.mem_insert_of_mem hb + have hyI : y ∈ insert y P := Finset.mem_insert_self y P + have to_y : ∀ u ∈ P, Relation.ReflTransGen (Step (insert y P)) u y := fun u hu => + (mono u b (hP u hu b hb)).tail ⟨hbI, hyI, hby⟩ + have from_y : ∀ u ∈ P, Relation.ReflTransGen (Step (insert y P)) y u := fun u hu => + Relation.ReflTransGen.head ⟨hyI, hbI, adj_symm hby⟩ (mono b u (hP b hb u hu)) + intro u hu v hv + rcases Finset.mem_insert.1 hu with hu | hu <;> rcases Finset.mem_insert.1 hv with hv | hv + · rw [hu, hv] + · rw [hu] + exact from_y v hv + · rw [hv] + exact to_y u hu + · exact mono u v (hP u hu v hv) + +/-- Every listed cell set is a polyiamond with `n` cells. -/ +theorem isPolyiamond_of_mem_polys : ∀ (n : ℕ), 1 ≤ n → ∀ e ∈ polys n, + IsPolyiamond n e.2.toFinset + | 0, h, _, _ => absurd h (by norm_num) + | 1, _, e, he => by + rw [polys, List.mem_singleton] at he + subst he + refine ⟨by simp, ?_, ?_⟩ + · intro x hx + simp only [List.mem_toFinset, List.mem_singleton] at hx + subst hx + left + simp [sumC] + · intro x hx y hy + simp only [List.mem_toFinset, List.mem_singleton] at hx hy + subst hx hy + exact Relation.ReflTransGen.refl + | n + 2, _, e', he' => by + rw [polys, mem_grow] at he' + obtain ⟨e, he, b, hb, y, hy, hyQ, rfl⟩ := he' + obtain ⟨hcard, hcell, hconn⟩ := isPolyiamond_of_mem_polys (n + 1) (by omega) e he + set Q := e.2 + have hbQ : b ∈ Q.toFinset := List.mem_toFinset.2 hb + obtain ⟨hadj, hycell⟩ := of_mem_nbrs (hcell b hbQ) hy + have hP : IsPolyiamond (n + 2) (y :: Q).toFinset := by + rw [List.toFinset_cons] + refine ⟨?_, ?_, isConnected_insert hconn hbQ hadj⟩ + · rw [Finset.card_insert_of_notMem (by simpa using hyQ), hcard] + · intro x hx + rcases Finset.mem_insert.1 hx with rfl | hx + · exact hycell + · exact hcell x hx + obtain ⟨g, hg⟩ := canon_spec (y :: Q) + rw [hg] + exact isPolyiamond_image hP g + +theorem frontier {P A : Finset Pt} {x q : Pt} (hx : x ∈ A) (hq : q ∉ A) + (h : Relation.ReflTransGen (Step P) x q) : ∃ b ∈ A, ∃ c ∈ P, c ∉ A ∧ Adj b c := by + induction h with + | refl => exact absurd hx hq + | @tail b c _ hbc ih => + by_cases hb : b ∈ A + · exact ⟨b, hb, c, hbc.2.1, hq, hbc.2.2⟩ + · exact ih hb + +/-- A symmetry moving the cell `p` to `0`. -/ +theorem exists_isom_zero {p : Pt} (hp : IsCell p) : ∃ g : Isom, g.app p = 0 := by + rcases hp with hp | hp + · refine ⟨⟨0, false, -p, by rw [sumC_neg, hp]; rfl⟩, ?_⟩ + simp [Isom.app, lin_zero] + · refine ⟨⟨0, true, p, by rw [hp]; rfl⟩, ?_⟩ + simp [Isom.app, lin, perm_zero] + +/-- Every polyiamond with at least `k ≥ 1` cells contains `k` cells whose set is mapped by a +symmetry onto a listed cell set. -/ +theorem exists_sub_mem_polys {P : Finset Pt} (hcell : ∀ x ∈ P, IsCell x) (hconn : IsConnected P) : + ∀ k, 1 ≤ k → k ≤ P.card → ∃ A ⊆ P, A.card = k ∧ ∃ Q ∈ polys k, ∃ g : Isom, + A.image g.app = Q.2.toFinset + | 0, h, _ => absurd h (by norm_num) + | 1, _, hk => by + obtain ⟨p, hp⟩ := Finset.card_pos.1 (show 0 < P.card by omega) + obtain ⟨g, hg⟩ := exists_isom_zero (hcell p hp) + refine ⟨{p}, Finset.singleton_subset_iff.2 hp, rfl, (0, [0]), List.mem_singleton_self _, g, + ?_⟩ + rw [Finset.image_singleton, hg] + simp + | k + 2, _, hk => by + obtain ⟨A, hAP, hAc, e, he, g, hg⟩ := exists_sub_mem_polys hcell hconn (k + 1) (by omega) + (by omega) + set Q := e.2 with hQe + obtain ⟨q, hqP, hqA⟩ := Finset.exists_mem_notMem_of_card_lt_card (s := A) (t := P) + (by omega) + obtain ⟨x, hx⟩ : A.Nonempty := Finset.card_pos.1 (by omega) + obtain ⟨b, hbA, c, hcP, hcA, hbc⟩ := frontier hx hqA (hconn x (hAP hx) q hqP) + have hgb : g.app b ∈ Q := by + rw [← List.mem_toFinset, ← hg] + exact Finset.mem_image_of_mem _ hbA + have hgc : g.app c ∉ Q := by + intro h + rw [← List.mem_toFinset, ← hg] at h + obtain ⟨c', hc', hcc⟩ := Finset.mem_image.1 h + exact hcA (g.app_injective hcc ▸ hc') + have hnb : g.app c ∈ nbrs (g.app b) := + mem_nbrs (g.isCell_app (hcell b (hAP hbA))) (g.isCell_app (hcell c hcP)) + ((g.adj_app b c).2 hbc) + obtain ⟨g', hg'⟩ := canon_spec (g.app c :: Q) + refine ⟨insert c A, Finset.insert_subset hcP hAP, by + rw [Finset.card_insert_of_notMem hcA, hAc], canon (g.app c :: Q), ?_, g'.comp g, ?_⟩ + · rw [polys, mem_grow] + exact ⟨e, he, g.app b, hgb, g.app c, hnb, hgc, rfl⟩ + · rw [hg', ← image_image_app, Finset.image_insert, hg, List.toFinset_cons] + +theorem a_eq_aComp {n : ℕ} (hn : 1 ≤ n) : a n = aComp n := by + have hval : ∀ Q ∈ polys n, numClassesC Q.2 = numClasses Q.2.toFinset := by + intro Q hQ + apply numClassesC_eq + intro h + have := (isPolyiamond_of_mem_polys n hn _ hQ).1 + rw [h] at this + simp at this + omega + have cover : ∀ P, IsPolyiamond n P → ∃ Q ∈ polys n, numClasses P = numClassesC Q.2 := by + rintro P ⟨hcard, hcell, hconn⟩ + obtain ⟨A, hAP, hAc, Q, hQ, g, hg⟩ := + exists_sub_mem_polys hcell hconn n hn hcard.ge + have hA : A = P := Finset.eq_of_subset_of_card_le hAP (by omega) + subst hA + refine ⟨Q, hQ, ?_⟩ + rw [hval Q hQ, ← hg, numClasses_image] + unfold a aComp + by_cases hL : polys n = [] + · rw [hL, List.map_nil, listMin] + convert Nat.sInf_empty + ext m + simp only [Set.mem_ofPred_eq, Set.mem_empty_iff_false, iff_false] + rintro ⟨P, hP, -⟩ + obtain ⟨Q, hQ, -⟩ := cover P hP + rw [hL] at hQ + simp at hQ + · have hne : (polys n).map (fun e => numClassesC e.2) ≠ [] := by simpa using hL + obtain ⟨Q, hQ, hQm⟩ := List.mem_map.1 (listMin_mem hne) + have hmem : listMin ((polys n).map fun e => numClassesC e.2) ∈ + {m | ∃ P : Finset Pt, IsPolyiamond n P ∧ numClasses P = m} := + ⟨Q.2.toFinset, isPolyiamond_of_mem_polys n hn Q hQ, by rw [← hQm, hval Q hQ]⟩ + apply le_antisymm (Nat.sInf_le hmem) + apply le_csInf ⟨_, hmem⟩ + rintro m ⟨P, hP, rfl⟩ + obtain ⟨Q', hQ', hQ'm⟩ := cover P hP + rw [hQ'm] + have hm : numClassesC Q'.2 ∈ (polys n).map fun e => numClassesC e.2 := + List.mem_map_of_mem hQ' + exact listMin_le hm + +/-! ### Data and the conjecture -/ + +/-- The definition reproduces the first 8 listed terms `a(1), …, a(8)` (kernel-checked). -/ +theorem a_data : (List.range 8).map (fun i => a (i + 1)) = [1, 1, 2, 2, 3, 1, 3, 3] := by + rw [show (fun i => a (i + 1)) = fun i => aComp (i + 1) from + funext fun i => a_eq_aComp (by omega)] + decide +kernel + +/-- Conjecture (Exley, A369366): for every `k ≥ 0`, the least number of inequivalent cells in a +polyiamond with `6k + 5` cells is `3(k + 1)`. -/ +def statement : Prop := ∀ k : ℕ, a (6 * k + 5) = 3 * (k + 1) + +end Math0.Statements.A369366 diff --git a/lean/Math0/Statements/OEIS/A373345.lean b/lean/Math0/Statements/OEIS/A373345.lean new file mode 100644 index 0000000..62b9cac --- /dev/null +++ b/lean/Math0/Statements/OEIS/A373345.lean @@ -0,0 +1,304 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A373345: the row lengths of the Schreier-set triangle are A007895 + +Source: https://oeis.org/A373345, Paolo Xausa, Jun 01 2024 (CROSSREFS section). Verbatim: +> Cf. A007895 (conjectured row lengths), A072649 (first column), A373346 (row sums), A373347. + +That is: row `n` of A373345 has length A007895(n), the number of terms in the Zeckendorf +representation of `n`. + +## The OEIS definitions + +* A373345 (offset `1`, keyword `tabf`): "Irregular triangle read by rows where row n lists (in + decreasing order) the elements of the Schreier set encoded by A371176(n)." Per its comments, + `k` encodes the set of "the 1-based position of the ones in the binary expansion of k (where + position 1 corresponds to the least significant bit)". Example rows: row 4 (`A371176(4) = 6 = + 110₂`) is `3, 2`; row 12 (`28 = 11100₂`) is `5, 4, 3`. +* A371176 (offset `1`): "Numbers k such that A000120(k) <= A001511(k)", where A000120(k) is the + binary weight of `k` (number of ones in its binary expansion) and A001511(k) is the ruler + function, "the 2-adic valuation of 2n" (defined for `k ≥ 1`). Its terms start + `1, 2, 4, 6, 8, 10, 12, 16, …`. +* A007895 (offset `0`): "Number of terms in the Zeckendorf representation of n (write n as a sum + of non-consecutive distinct Fibonacci numbers)." + +## Encoding + +* `IsTerm k` is A371176-membership: `0 < k ∧ k.bitIndices.length ≤ padicValNat 2 (2 * k)`. + Mathlib's `Nat.bitIndices k` is the increasing list of the (0-based) indices of the ones in the + binary expansion of `k` (`Nat.mem_bitIndices : i ∈ k.bitIndices ↔ k.testBit i`), so its length + is A000120(k); `padicValNat 2 (2 * k)` is A001511(k). The condition `0 < k` reflects that + A371176 is a sequence of positive integers (A001511 is only defined for `k ≥ 1`; without it, + `k = 0` would satisfy `0 ≤ 0`). +* `A371176 n = Nat.nth IsTerm (n - 1)` is the `n`-th term (offset `1`, so `n ≥ 1`). +* `T n` is row `n` of A373345: `((A371176 n).bitIndices.map (· + 1)).reverse`, i.e. the 1-based + positions of the ones of `A371176 n`, in decreasing order. Its length is the row length + (the cardinality of the Schreier set). `T_ne_nil` shows every row is nonempty. +* `Nat.zeckendorf n` is Mathlib's Zeckendorf representation of `n`: the list of indices `i ≥ 2` + (strictly decreasing, pairwise non-consecutive) with `n = ∑ fib i`. Its length is the number of + terms in the Zeckendorf representation, i.e. A007895(n). +* *Alignment.* Row `n` of A373345 (`n ≥ 1`) is matched with A007895(n): this is the only reading + consistent with the data (row 1 = `{1}` has length `1 = A007895(1)`, row 4 = `{3, 2}` has length + `2 = A007895(4)`, row 12 = `{5, 4, 3}` has length `3 = A007895(12)`; matching row 1 with the + first listed term A007895(0) = 0 would fail at once). `statement_check` kernel-checks the + claimed equality for the rows `n = 1, …, 42` covered by the listed data, as a sanity check of + this alignment. +* *Computation.* `Nat.bitIndices`, `Nat.nth` and `Nat.zeckendorf` are not suitable for kernel + evaluation, so computable versions are used for the checks and proved equal to them: + `bitPos_eq_bitIndices` (bits via `Nat.testBit` below `Nat.log2 k + 1`), `isTermB_iff` (the + ruler function is one more than the lowest set-bit index), `code_eq_nth` (`code i`, obtained by + `i` steps of a bounded search for the next term starting from `1`, equals `Nat.nth IsTerm i`; + the search window `(k, 2k + 1]` always contains the power of two `2 ^ (log2 k + 1)`, a term), + `row_eq_T`, and `zeckAux_eq` (fuel-bounded greedy Zeckendorf). +* `a m` is the flattened sequence (offset `1`): the `m`-th entry of `T 1 ++ T 2 ++ ⋯`. Since every + row is nonempty, the first `m` rows already contain at least `m` entries, so + `a m = ((List.range m).flatMap (fun i => T (i + 1))).getD (m - 1) 0` (`a_eq`). `a_data` + checks all 91 listed terms `a 1, …, a 91` (rows 1 to 42). +* *The conjecture* (`statement`): for every `n ≥ 1`, `(T n).length = (Nat.zeckendorf n).length`. +-/ + +namespace Math0.Statements.A373345 + +/-! ### The OEIS definitions -/ + +/-- `k` is a term of A371176: `k ≥ 1` and A000120(k) ≤ A001511(k), i.e. the number of ones in the +binary expansion of `k` is at most the 2-adic valuation of `2k`. -/ +def IsTerm (k : ℕ) : Prop := 0 < k ∧ k.bitIndices.length ≤ padicValNat 2 (2 * k) + +/-- A371176(n), the `n`-th term (offset `1`) of A371176. -/ +noncomputable def A371176 (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) + +/-- Row `n` (`n ≥ 1`) of A373345: the elements of the Schreier set encoded by A371176(n), i.e. the +1-based positions of the ones in the binary expansion of A371176(n), in decreasing order. -/ +noncomputable def T (n : ℕ) : List ℕ := ((A371176 n).bitIndices.map (· + 1)).reverse + +/-! ### Kernel-computable versions -/ + +/-- The 0-based positions of the ones in the binary expansion of `k`, in increasing order. -/ +def bitPos (k : ℕ) : List ℕ := (List.range (k.log2 + 1)).filter (fun i => k.testBit i) + +theorem bitPos_eq_bitIndices (k : ℕ) : bitPos k = k.bitIndices := by + apply List.SortedLT.eq_of_mem_iff + · exact (List.pairwise_lt_range.filter _).sortedLT + · exact Nat.bitIndices_sorted + · intro i + simp only [bitPos, List.mem_filter, List.mem_range, Nat.mem_bitIndices] + constructor + · exact fun h => h.2 + · intro h + refine ⟨?_, h⟩ + have hk : k ≠ 0 := by + rintro rfl + simp at h + have := (Nat.le_log2 hk).2 (Nat.ge_two_pow_of_testBit h) + omega + +/-- A001511(k) is one more than the index of the lowest one bit of `k`. -/ +theorem padicValNat_two_mul (k : ℕ) (hk : k ≠ 0) : + padicValNat 2 (2 * k) = k.bitIndices.headD 0 + 1 := by + obtain ⟨v, m, hm, rfl⟩ := Nat.exists_eq_two_pow_mul_odd hk + obtain ⟨m', rfl⟩ := hm + have hb : (2 ^ v * (2 * m' + 1)).bitIndices.headD 0 = v := by + rw [Nat.bitIndices_two_pow_mul, Nat.bitIndices_two_mul_add_one] + simp + rw [hb, show 2 * (2 ^ v * (2 * m' + 1)) = 2 ^ (v + 1) * (2 * m' + 1) by ring, + padicValNat.mul (by positivity) (by omega), padicValNat.prime_pow, + padicValNat.eq_zero_of_not_dvd (by omega)] + +/-- Boolean test for membership in A371176. -/ +def isTermB (k : ℕ) : Bool := + decide (0 < k) && decide ((bitPos k).length ≤ (bitPos k).headD 0 + 1) + +theorem isTermB_iff (k : ℕ) : isTermB k = true ↔ IsTerm k := by + simp only [isTermB, IsTerm, Bool.and_eq_true, decide_eq_true_eq, bitPos_eq_bitIndices] + constructor + · rintro ⟨hk, h⟩ + exact ⟨hk, by rw [padicValNat_two_mul k hk.ne']; exact h⟩ + · rintro ⟨hk, h⟩ + exact ⟨hk, by rw [padicValNat_two_mul k hk.ne'] at h; exact h⟩ + +instance : DecidablePred IsTerm := fun k => decidable_of_iff _ (isTermB_iff k) + +theorem isTerm_two_pow (e : ℕ) : IsTerm (2 ^ e) := by + refine ⟨by positivity, ?_⟩ + rw [Nat.bitIndices_two_pow, ← pow_succ', padicValNat.prime_pow] + simp + +/-- `search f s`: the first `j ∈ [s, s + f)` with `isTermB j`, or `s + f` if there is none. -/ +def search : ℕ → ℕ → ℕ + | 0, s => s + | f + 1, s => if isTermB s then s else search f (s + 1) + +theorem search_spec (f s : ℕ) (h : ∃ j, s ≤ j ∧ j < s + f ∧ isTermB j = true) : + s ≤ search f s ∧ isTermB (search f s) = true ∧ + ∀ j, s ≤ j → j < search f s → isTermB j = false := by + induction f generalizing s with + | zero => + obtain ⟨j, h1, h2, _⟩ := h + omega + | succ f ih => + simp only [search] + split_ifs with hs + · exact ⟨le_rfl, hs, fun j h1 h2 => by omega⟩ + · have h' : ∃ j, s + 1 ≤ j ∧ j < s + 1 + f ∧ isTermB j = true := by + obtain ⟨j, h1, h2, h3⟩ := h + refine ⟨j, ?_, by omega, h3⟩ + rcases Nat.eq_or_lt_of_le h1 with rfl | h1 + · exact absurd h3 hs + · omega + obtain ⟨ih1, ih2, ih3⟩ := ih (s + 1) h' + refine ⟨by omega, ih2, fun j h1 h2 => ?_⟩ + rcases Nat.eq_or_lt_of_le h1 with rfl | h1 + · simpa using hs + · exact ih3 j h1 h2 + +/-- The least term of A371176 exceeding `k` (for `k ≥ 1`; see `nextTerm_spec`). -/ +def nextTerm (k : ℕ) : ℕ := search (k + 1) (k + 1) + +theorem nextTerm_spec (k : ℕ) (hk : 0 < k) : + k < nextTerm k ∧ IsTerm (nextTerm k) ∧ ∀ j, k < j → j < nextTerm k → ¬ IsTerm j := by + unfold nextTerm + have hex : ∃ j, k + 1 ≤ j ∧ j < k + 1 + (k + 1) ∧ isTermB j = true := by + refine ⟨2 ^ (k.log2 + 1), ?_, ?_, (isTermB_iff _).2 (isTerm_two_pow _)⟩ + · have := Nat.lt_log2_self (n := k) + omega + · have := Nat.log2_self_le hk.ne' + rw [pow_succ] + omega + obtain ⟨h1, h2, h3⟩ := search_spec (k + 1) (k + 1) hex + refine ⟨h1, (isTermB_iff _).1 h2, fun j hj1 hj2 => ?_⟩ + rw [← isTermB_iff, h3 j hj1 hj2] + simp + +theorem count_step (c c' : ℕ) (hc : IsTerm c) (hlt : c < c') + (hno : ∀ j, c < j → j < c' → ¬ IsTerm j) : + Nat.count IsTerm c' = Nat.count IsTerm c + 1 := by + obtain ⟨d, rfl⟩ : ∃ d, c' = c + d + 1 := ⟨c' - c - 1, by omega⟩ + induction d with + | zero => rw [add_zero, Nat.count_succ, if_pos hc] + | succ d ih => + rw [show c + (d + 1) + 1 = (c + d + 1) + 1 by ring, Nat.count_succ, + ih (by omega) (fun j h1 h2 => hno j h1 (by omega)), + if_neg (hno _ (by omega) (by omega))] + +/-- `code i` is the `i`-th term (0-indexed) of A371176, computed by iterating `nextTerm`. -/ +def code (i : ℕ) : ℕ := nextTerm^[i] 1 + +theorem code_spec (i : ℕ) : IsTerm (code i) ∧ Nat.count IsTerm (code i) = i := by + induction i with + | zero => + refine ⟨by simpa [code] using isTerm_two_pow 0, ?_⟩ + simp [code, Nat.count_succ, IsTerm] + | succ i ih => + have hc : code (i + 1) = nextTerm (code i) := Function.iterate_succ_apply' _ _ _ + obtain ⟨h1, h2, h3⟩ := nextTerm_spec (code i) ih.1.1 + rw [hc] + exact ⟨h2, by rw [count_step _ _ ih.1 h1 h3, ih.2]⟩ + +/-- The computed terms are the terms of A371176. -/ +theorem code_eq_nth (i : ℕ) : code i = Nat.nth IsTerm i := by + have h := Nat.nth_count (code_spec i).1 + rw [(code_spec i).2] at h + exact h.symm + +/-- Row of the triangle for the code `k`. -/ +def rowOf (k : ℕ) : List ℕ := ((bitPos k).map (· + 1)).reverse + +/-- Computable version of row `n` of A373345. -/ +def row (n : ℕ) : List ℕ := rowOf (code (n - 1)) + +theorem row_eq_T (n : ℕ) : row n = T n := by + simp [row, rowOf, T, A371176, code_eq_nth, bitPos_eq_bitIndices] + +/-- Every row is nonempty. -/ +theorem T_ne_nil (n : ℕ) : T n ≠ [] := by + have hpos := (code_spec (n - 1)).1.1 + rw [← row_eq_T] + simp only [row, rowOf, bitPos_eq_bitIndices, ne_eq, List.reverse_eq_nil_iff, List.map_eq_nil_iff] + intro hnil + have := Nat.sum_map_two_pow_bitIndices (code (n - 1)) + rw [hnil] at this + simp at this + omega + +/-- `codesAux N k = [k, nextTerm k, …, nextTerm^[N-1] k]`. -/ +def codesAux : ℕ → ℕ → List ℕ + | 0, _ => [] + | N + 1, k => k :: codesAux N (nextTerm k) + +theorem codesAux_eq (N k : ℕ) : codesAux N k = (List.range N).map (fun i => nextTerm^[i] k) := by + induction N generalizing k with + | zero => rfl + | succ N ih => + rw [codesAux, ih, List.range_succ_eq_map, List.map_cons, List.map_map] + rfl + +/-- A373345 as a flattened sequence (offset `1`): `a m` is the `m`-th entry of +`T 1 ++ T 2 ++ T 3 ++ ⋯` (see `a_eq`). -/ +def a (m : ℕ) : ℕ := ((codesAux m 1).flatMap rowOf).getD (m - 1) 0 + +theorem a_eq (m : ℕ) : a m = ((List.range m).flatMap (fun i => T (i + 1))).getD (m - 1) 0 := by + rw [a, codesAux_eq, List.flatMap_map] + congr 2 + funext i + rw [← row_eq_T] + rfl + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all 91 listed +terms, i.e. rows 1 to 42. -/ +theorem a_data : (List.range 91).map (fun i => a (i + 1)) = + [1, 2, 3, 3, 2, 4, 4, 2, 4, 3, 5, 5, 2, 5, 3, 5, 4, 5, 4, 3, 6, 6, 2, 6, 3, 6, 4, 6, 4, 3, 6, + 5, 6, 5, 3, 6, 5, 4, 7, 7, 2, 7, 3, 7, 4, 7, 4, 3, 7, 5, 7, 5, 3, 7, 5, 4, 7, 6, 7, 6, 3, 7, + 6, 4, 7, 6, 5, 7, 6, 5, 4, 8, 8, 2, 8, 3, 8, 4, 8, 4, 3, 8, 5, 8, 5, 3, 8, 5, 4, 8, 6] := by + decide +kernel + +/-- The first terms of A371176 (data of that entry, `n = 1, …, 42`), kernel-checked. -/ +theorem code_data : (List.range 42).map code = + [1, 2, 4, 6, 8, 10, 12, 16, 18, 20, 24, 28, 32, 34, 36, 40, 44, 48, 52, 56, 64, 66, 68, 72, + 76, 80, 84, 88, 96, 100, 104, 112, 120, 128, 130, 132, 136, 140, 144, 148, 152, 160] := by + decide +kernel + +/-! ### Zeckendorf representation, computably (for the sanity check only) -/ + +/-- Greedy Zeckendorf representation with fuel. -/ +def zeckAux : ℕ → ℕ → List ℕ + | 0, _ => [] + | f + 1, m => if m = 0 then [] else Nat.greatestFib m :: zeckAux f (m - Nat.fib (Nat.greatestFib m)) + +theorem zeckAux_eq (f m : ℕ) (h : m ≤ f) : zeckAux f m = Nat.zeckendorf m := by + induction f generalizing m with + | zero => + obtain rfl : m = 0 := by omega + simp [zeckAux] + | succ f ih => + rcases Nat.eq_zero_or_pos m with rfl | hm + · simp [zeckAux] + · have hfib : 0 < Nat.fib (Nat.greatestFib m) := Nat.fib_pos.2 (Nat.greatestFib_pos.2 hm) + rw [zeckAux, if_neg hm.ne', Nat.zeckendorf_of_pos hm, ih _ (by omega)] + +/-- Sanity check of the alignment of rows with A007895: the claimed equality holds for the rows +`n = 1, …, 42` covered by the listed data. -/ +theorem statement_check : ∀ n, 1 ≤ n → n ≤ 42 → (T n).length = (Nat.zeckendorf n).length := by + have h : (List.range 42).all + (fun i => (row (i + 1)).length == (zeckAux (i + 1) (i + 1)).length) = true := by + decide +kernel + intro n h1 h2 + rw [← row_eq_T, ← zeckAux_eq n n le_rfl] + rw [List.all_eq_true] at h + have := h (n - 1) (List.mem_range.2 (by omega)) + rw [show n - 1 + 1 = n by omega] at this + simpa using this + +/-! ### The conjecture -/ + +/-- OEIS A373345 (Paolo Xausa, CROSSREFS: "A007895 (conjectured row lengths)"): for every +`n ≥ 1`, row `n` of the triangle (the Schreier set encoded by A371176(n)) has as many elements as +there are terms in the Zeckendorf representation of `n`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → (T n).length = (Nat.zeckendorf n).length + +end Math0.Statements.A373345 diff --git a/lean/Math0/Statements/OEIS/A373359.lean b/lean/Math0/Statements/OEIS/A373359.lean new file mode 100644 index 0000000..f282614 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A373359.lean @@ -0,0 +1,306 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A373359: the row lengths of the Schreier-set triangle (increasing rows) are A007895 + +Source: https://oeis.org/A373359, Paolo Xausa, Jun 04 2024 (CROSSREFS section). Verbatim: +> Cf. A007895 (conjectured row lengths), A373346 (row sums), A373347. + +That is: row `n` of A373359 has length A007895(n), the number of terms in the Zeckendorf +representation of `n`. + +## The OEIS definitions + +* A373359 (offset `1`, keyword `tabf`): "Irregular triangle read by rows where row n lists (in + increasing order) the elements of the Schreier set encoded by A371176(n)." The encoding (see + A373345, to which the entry refers, and the example table of A373359) takes `k` to the set of + the 1-based positions of the ones in the binary expansion of `k`, position 1 being the least + significant bit. Example rows: row 4 (`A371176(4) = 6 = 110₂`) is `2, 3`; row 12 + (`A371176(12) = 28 = 11100₂`) is `3, 4, 5`. +* A371176 (offset `1`): "Numbers k such that A000120(k) <= A001511(k)", where A000120(k) is the + binary weight of `k` (number of ones in its binary expansion) and A001511(k) is the ruler + function, "the 2-adic valuation of 2n" (defined for `k ≥ 1`). Its terms start + `1, 2, 4, 6, 8, 10, 12, 16, …`. +* A007895 (offset `0`): "Number of terms in the Zeckendorf representation of n (write n as a sum + of non-consecutive distinct Fibonacci numbers)." + +## Encoding + +* `IsTerm k` is A371176-membership: `0 < k ∧ k.bitIndices.length ≤ padicValNat 2 (2 * k)`. + Mathlib's `Nat.bitIndices k` is the increasing list of the (0-based) indices of the ones in the + binary expansion of `k` (`Nat.mem_bitIndices : i ∈ k.bitIndices ↔ k.testBit i`), so its length + is A000120(k); `padicValNat 2 (2 * k)` is A001511(k). The condition `0 < k` reflects that + A371176 is a sequence of positive integers (A001511 is only defined for `k ≥ 1`; without it, + `k = 0` would satisfy `0 ≤ 0`). +* `A371176 n = Nat.nth IsTerm (n - 1)` is the `n`-th term (offset `1`, so `n ≥ 1`). +* `T n` is row `n` of A373359: `(A371176 n).bitIndices.map (· + 1)`, i.e. the 1-based positions + of the ones of `A371176 n`, in increasing order. Its length is the row length (the cardinality + of the Schreier set). `T_ne_nil` shows every row is nonempty. +* `Nat.zeckendorf n` is Mathlib's Zeckendorf representation of `n`: the list of indices `i ≥ 2` + (strictly decreasing, pairwise non-consecutive) with `n = ∑ fib i`. Its length is the number of + terms in the Zeckendorf representation, i.e. A007895(n). +* *Alignment.* Row `n` of A373359 (`n ≥ 1`) is matched with A007895(n): this is the only reading + consistent with the data (row 1 = `{1}` has length `1 = A007895(1)`, row 4 = `{2, 3}` has length + `2 = A007895(4)`, row 12 = `{3, 4, 5}` has length `3 = A007895(12)`; matching row 1 with the + first listed term A007895(0) = 0 would fail at once). `statement_check` kernel-checks the + claimed equality for the rows `n = 1, …, 42` covered by the listed data, as a sanity check of + this alignment. +* *Computation.* `Nat.bitIndices`, `Nat.nth` and `Nat.zeckendorf` are not suitable for kernel + evaluation, so computable versions are used for the checks and proved equal to them: + `bitPos_eq_bitIndices` (bits via `Nat.testBit` below `Nat.log2 k + 1`), `isTermB_iff` (the + ruler function is one more than the lowest set-bit index), `code_eq_nth` (`code i`, obtained by + `i` steps of a bounded search for the next term starting from `1`, equals `Nat.nth IsTerm i`; + the search window `(k, 2k + 1]` always contains the power of two `2 ^ (log2 k + 1)`, a term), + `row_eq_T`, and `zeckAux_eq` (fuel-bounded greedy Zeckendorf). +* `a m` is the flattened sequence (offset `1`): the `m`-th entry of `T 1 ++ T 2 ++ ⋯`. Since every + row is nonempty, the first `m` rows already contain at least `m` entries, so + `a m = ((List.range m).flatMap (fun i => T (i + 1))).getD (m - 1) 0` (`a_eq`). `a_data` + checks all 91 listed terms `a 1, …, a 91` (rows 1 to 42). +* *The conjecture* (`statement`): for every `n ≥ 1`, `(T n).length = (Nat.zeckendorf n).length`. +-/ + +namespace Math0.Statements.A373359 + +/-! ### The OEIS definitions -/ + +/-- `k` is a term of A371176: `k ≥ 1` and A000120(k) ≤ A001511(k), i.e. the number of ones in the +binary expansion of `k` is at most the 2-adic valuation of `2k`. -/ +def IsTerm (k : ℕ) : Prop := 0 < k ∧ k.bitIndices.length ≤ padicValNat 2 (2 * k) + +/-- A371176(n), the `n`-th term (offset `1`) of A371176. -/ +noncomputable def A371176 (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) + +/-- Row `n` (`n ≥ 1`) of A373359: the elements of the Schreier set encoded by A371176(n), i.e. the +1-based positions of the ones in the binary expansion of A371176(n), in increasing order. -/ +noncomputable def T (n : ℕ) : List ℕ := (A371176 n).bitIndices.map (· + 1) + +/-! ### Kernel-computable versions -/ + +/-- The 0-based positions of the ones in the binary expansion of `k`, in increasing order. -/ +def bitPos (k : ℕ) : List ℕ := (List.range (k.log2 + 1)).filter (fun i => k.testBit i) + +theorem bitPos_eq_bitIndices (k : ℕ) : bitPos k = k.bitIndices := by + apply List.SortedLT.eq_of_mem_iff + · exact (List.pairwise_lt_range.filter _).sortedLT + · exact Nat.bitIndices_sorted + · intro i + simp only [bitPos, List.mem_filter, List.mem_range, Nat.mem_bitIndices] + constructor + · exact fun h => h.2 + · intro h + refine ⟨?_, h⟩ + have hk : k ≠ 0 := by + rintro rfl + simp at h + have := (Nat.le_log2 hk).2 (Nat.ge_two_pow_of_testBit h) + omega + +/-- A001511(k) is one more than the index of the lowest one bit of `k`. -/ +theorem padicValNat_two_mul (k : ℕ) (hk : k ≠ 0) : + padicValNat 2 (2 * k) = k.bitIndices.headD 0 + 1 := by + obtain ⟨v, m, hm, rfl⟩ := Nat.exists_eq_two_pow_mul_odd hk + obtain ⟨m', rfl⟩ := hm + have hb : (2 ^ v * (2 * m' + 1)).bitIndices.headD 0 = v := by + rw [Nat.bitIndices_two_pow_mul, Nat.bitIndices_two_mul_add_one] + simp + rw [hb, show 2 * (2 ^ v * (2 * m' + 1)) = 2 ^ (v + 1) * (2 * m' + 1) by ring, + padicValNat.mul (by positivity) (by omega), padicValNat.prime_pow, + padicValNat.eq_zero_of_not_dvd (by omega)] + +/-- Boolean test for membership in A371176. -/ +def isTermB (k : ℕ) : Bool := + decide (0 < k) && decide ((bitPos k).length ≤ (bitPos k).headD 0 + 1) + +theorem isTermB_iff (k : ℕ) : isTermB k = true ↔ IsTerm k := by + simp only [isTermB, IsTerm, Bool.and_eq_true, decide_eq_true_eq, bitPos_eq_bitIndices] + constructor + · rintro ⟨hk, h⟩ + exact ⟨hk, by rw [padicValNat_two_mul k hk.ne']; exact h⟩ + · rintro ⟨hk, h⟩ + exact ⟨hk, by rw [padicValNat_two_mul k hk.ne'] at h; exact h⟩ + +instance : DecidablePred IsTerm := fun k => decidable_of_iff _ (isTermB_iff k) + +theorem isTerm_two_pow (e : ℕ) : IsTerm (2 ^ e) := by + refine ⟨by positivity, ?_⟩ + rw [Nat.bitIndices_two_pow, ← pow_succ', padicValNat.prime_pow] + simp + +/-- `search f s`: the first `j ∈ [s, s + f)` with `isTermB j`, or `s + f` if there is none. -/ +def search : ℕ → ℕ → ℕ + | 0, s => s + | f + 1, s => if isTermB s then s else search f (s + 1) + +theorem search_spec (f s : ℕ) (h : ∃ j, s ≤ j ∧ j < s + f ∧ isTermB j = true) : + s ≤ search f s ∧ isTermB (search f s) = true ∧ + ∀ j, s ≤ j → j < search f s → isTermB j = false := by + induction f generalizing s with + | zero => + obtain ⟨j, h1, h2, _⟩ := h + omega + | succ f ih => + simp only [search] + split_ifs with hs + · exact ⟨le_rfl, hs, fun j h1 h2 => by omega⟩ + · have h' : ∃ j, s + 1 ≤ j ∧ j < s + 1 + f ∧ isTermB j = true := by + obtain ⟨j, h1, h2, h3⟩ := h + refine ⟨j, ?_, by omega, h3⟩ + rcases Nat.eq_or_lt_of_le h1 with rfl | h1 + · exact absurd h3 hs + · omega + obtain ⟨ih1, ih2, ih3⟩ := ih (s + 1) h' + refine ⟨by omega, ih2, fun j h1 h2 => ?_⟩ + rcases Nat.eq_or_lt_of_le h1 with rfl | h1 + · simpa using hs + · exact ih3 j h1 h2 + +/-- The least term of A371176 exceeding `k` (for `k ≥ 1`; see `nextTerm_spec`). -/ +def nextTerm (k : ℕ) : ℕ := search (k + 1) (k + 1) + +theorem nextTerm_spec (k : ℕ) (hk : 0 < k) : + k < nextTerm k ∧ IsTerm (nextTerm k) ∧ ∀ j, k < j → j < nextTerm k → ¬ IsTerm j := by + unfold nextTerm + have hex : ∃ j, k + 1 ≤ j ∧ j < k + 1 + (k + 1) ∧ isTermB j = true := by + refine ⟨2 ^ (k.log2 + 1), ?_, ?_, (isTermB_iff _).2 (isTerm_two_pow _)⟩ + · have := Nat.lt_log2_self (n := k) + omega + · have := Nat.log2_self_le hk.ne' + rw [pow_succ] + omega + obtain ⟨h1, h2, h3⟩ := search_spec (k + 1) (k + 1) hex + refine ⟨h1, (isTermB_iff _).1 h2, fun j hj1 hj2 => ?_⟩ + rw [← isTermB_iff, h3 j hj1 hj2] + simp + +theorem count_step (c c' : ℕ) (hc : IsTerm c) (hlt : c < c') + (hno : ∀ j, c < j → j < c' → ¬ IsTerm j) : + Nat.count IsTerm c' = Nat.count IsTerm c + 1 := by + obtain ⟨d, rfl⟩ : ∃ d, c' = c + d + 1 := ⟨c' - c - 1, by omega⟩ + induction d with + | zero => rw [add_zero, Nat.count_succ, if_pos hc] + | succ d ih => + rw [show c + (d + 1) + 1 = (c + d + 1) + 1 by ring, Nat.count_succ, + ih (by omega) (fun j h1 h2 => hno j h1 (by omega)), + if_neg (hno _ (by omega) (by omega))] + +/-- `code i` is the `i`-th term (0-indexed) of A371176, computed by iterating `nextTerm`. -/ +def code (i : ℕ) : ℕ := nextTerm^[i] 1 + +theorem code_spec (i : ℕ) : IsTerm (code i) ∧ Nat.count IsTerm (code i) = i := by + induction i with + | zero => + refine ⟨by simpa [code] using isTerm_two_pow 0, ?_⟩ + simp [code, Nat.count_succ, IsTerm] + | succ i ih => + have hc : code (i + 1) = nextTerm (code i) := Function.iterate_succ_apply' _ _ _ + obtain ⟨h1, h2, h3⟩ := nextTerm_spec (code i) ih.1.1 + rw [hc] + exact ⟨h2, by rw [count_step _ _ ih.1 h1 h3, ih.2]⟩ + +/-- The computed terms are the terms of A371176. -/ +theorem code_eq_nth (i : ℕ) : code i = Nat.nth IsTerm i := by + have h := Nat.nth_count (code_spec i).1 + rw [(code_spec i).2] at h + exact h.symm + +/-- Row of the triangle for the code `k`: the 1-based positions of the ones of `k`, increasing. -/ +def rowOf (k : ℕ) : List ℕ := (bitPos k).map (· + 1) + +/-- Computable version of row `n` of A373359. -/ +def row (n : ℕ) : List ℕ := rowOf (code (n - 1)) + +theorem row_eq_T (n : ℕ) : row n = T n := by + simp [row, rowOf, T, A371176, code_eq_nth, bitPos_eq_bitIndices] + +/-- Every row is nonempty. -/ +theorem T_ne_nil (n : ℕ) : T n ≠ [] := by + have hpos := (code_spec (n - 1)).1.1 + rw [← row_eq_T] + simp only [row, rowOf, bitPos_eq_bitIndices, ne_eq, List.map_eq_nil_iff] + intro hnil + have := Nat.sum_map_two_pow_bitIndices (code (n - 1)) + rw [hnil] at this + simp at this + omega + +/-- `codesAux N k = [k, nextTerm k, …, nextTerm^[N-1] k]`. -/ +def codesAux : ℕ → ℕ → List ℕ + | 0, _ => [] + | N + 1, k => k :: codesAux N (nextTerm k) + +theorem codesAux_eq (N k : ℕ) : codesAux N k = (List.range N).map (fun i => nextTerm^[i] k) := by + induction N generalizing k with + | zero => rfl + | succ N ih => + rw [codesAux, ih, List.range_succ_eq_map, List.map_cons, List.map_map] + rfl + +/-- A373359 as a flattened sequence (offset `1`): `a m` is the `m`-th entry of +`T 1 ++ T 2 ++ T 3 ++ ⋯` (see `a_eq`). -/ +def a (m : ℕ) : ℕ := ((codesAux m 1).flatMap rowOf).getD (m - 1) 0 + +theorem a_eq (m : ℕ) : a m = ((List.range m).flatMap (fun i => T (i + 1))).getD (m - 1) 0 := by + rw [a, codesAux_eq, List.flatMap_map] + congr 2 + funext i + rw [← row_eq_T] + rfl + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked): all 91 listed +terms, i.e. rows 1 to 42. -/ +theorem a_data : (List.range 91).map (fun i => a (i + 1)) = + [1, 2, 3, 2, 3, 4, 2, 4, 3, 4, 5, 2, 5, 3, 5, 4, 5, 3, 4, 5, 6, 2, 6, 3, 6, 4, 6, 3, 4, 6, 5, + 6, 3, 5, 6, 4, 5, 6, 7, 2, 7, 3, 7, 4, 7, 3, 4, 7, 5, 7, 3, 5, 7, 4, 5, 7, 6, 7, 3, 6, 7, 4, + 6, 7, 5, 6, 7, 4, 5, 6, 7, 8, 2, 8, 3, 8, 4, 8, 3, 4, 8, 5, 8, 3, 5, 8, 4, 5, 8, 6, 8] := by + decide +kernel + +/-- The first terms of A371176 (data of that entry, `n = 1, …, 42`), kernel-checked. -/ +theorem code_data : (List.range 42).map code = + [1, 2, 4, 6, 8, 10, 12, 16, 18, 20, 24, 28, 32, 34, 36, 40, 44, 48, 52, 56, 64, 66, 68, 72, + 76, 80, 84, 88, 96, 100, 104, 112, 120, 128, 130, 132, 136, 140, 144, 148, 152, 160] := by + decide +kernel + +/-! ### Zeckendorf representation, computably (for the sanity check only) -/ + +/-- Greedy Zeckendorf representation with fuel. -/ +def zeckAux : ℕ → ℕ → List ℕ + | 0, _ => [] + | f + 1, m => + if m = 0 then [] else Nat.greatestFib m :: zeckAux f (m - Nat.fib (Nat.greatestFib m)) + +theorem zeckAux_eq (f m : ℕ) (h : m ≤ f) : zeckAux f m = Nat.zeckendorf m := by + induction f generalizing m with + | zero => + obtain rfl : m = 0 := by omega + simp [zeckAux] + | succ f ih => + rcases Nat.eq_zero_or_pos m with rfl | hm + · simp [zeckAux] + · have hfib : 0 < Nat.fib (Nat.greatestFib m) := Nat.fib_pos.2 (Nat.greatestFib_pos.2 hm) + rw [zeckAux, if_neg hm.ne', Nat.zeckendorf_of_pos hm, ih _ (by omega)] + +/-- Sanity check of the alignment of rows with A007895: the claimed equality holds for the rows +`n = 1, …, 42` covered by the listed data. -/ +theorem statement_check : ∀ n, 1 ≤ n → n ≤ 42 → (T n).length = (Nat.zeckendorf n).length := by + have h : (List.range 42).all + (fun i => (row (i + 1)).length == (zeckAux (i + 1) (i + 1)).length) = true := by + decide +kernel + intro n h1 h2 + rw [← row_eq_T, ← zeckAux_eq n n le_rfl] + rw [List.all_eq_true] at h + have := h (n - 1) (List.mem_range.2 (by omega)) + rw [show n - 1 + 1 = n by omega] at this + simpa using this + +/-! ### The conjecture -/ + +/-- OEIS A373359 (Paolo Xausa, CROSSREFS: "A007895 (conjectured row lengths)"): for every +`n ≥ 1`, row `n` of the triangle (the Schreier set encoded by A371176(n), listed in increasing +order) has as many elements as there are terms in the Zeckendorf representation of `n`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → (T n).length = (Nat.zeckendorf n).length + +end Math0.Statements.A373359 diff --git a/lean/Math0/Statements/OEIS/A375522.lean b/lean/Math0/Statements/OEIS/A375522.lean new file mode 100644 index 0000000..995136b --- /dev/null +++ b/lean/Math0/Statements/OEIS/A375522.lean @@ -0,0 +1,163 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A375522: denominators of the prime-scaled greedy Egyptian sums below 1 + +Source: https://oeis.org/A375522, Rémy Sigrist and N. J. A. Sloane, Aug 30 2024. Verbatim: +> Let S(n) = Sum_{k = 1..n} 1 / (k*A375781(k)) = S1(n)/S2(n) when reduced to lowest terms, +> where S1(n) = A375521(n), S2(n) = the present sequence. +> The differences S2(n) - S1(n) are surprisingly small: for n = 1,2,...,34 the values +> S2(n) - S1(n) are: +> 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +> 1, 1 +> suggesting the conjecture that they are always 1 except for n = 4 and 6 (compare the Theorem +> in A374983). + +## Encoding + +* A375781 (Rémy Sigrist) is the "lexicographically earliest sequence of positive integers + a(1), a(2), a(3), ... such that for any n > 0, Sum_{k = 1..n} 1 / (prime(k)*a(k)) < 1". The + entries' Maple and Mathematica programs (and the PARI and Python programs) compute it greedily: + with `s(0) = 0`, + `b(n) = 1 + floor(1/((1 - s(n-1)) * prime(n)))` and `s(n) = s(n-1) + 1/(prime(n) * b(n))`. + (When `s(n-1) < 1`, `b(n)` is the least positive integer with + `s(n-1) + 1/(prime(n) b(n)) < 1`.) We encode + exactly this recursion over `ℚ` with `Int.floor` (`s`, `b`). +* The entry's name and comment write `1 / (k*A375781(k))`, but its data, example + (`0/1, 1/2, 5/6, 14/15, …`), Maple, Mathematica and Python programs all use + `1 / (prime(k)*A375781(k))` (with `k` instead of `prime(k)` the first sum would already be + `1/1`). So `k` there is a typo for `prime(k)`, and we use `prime(k)`. The data check below + confirms this reading. +* `prime k` is the `k`-th prime (`k ≥ 1`), computed by a bounded search (`primeAt`, 0-indexed). + `primeAt_eq_nth` proves `primeAt i = Nat.nth Nat.Prime i`, so `prime k` is Mathlib's + `k`-th prime. +* `S1 n = (s n).num` (A375521) and `a n = S2 n = (s n).den` (A375522, offset 0, `a 0 = 1`); + Mathlib's `Rat` is always in lowest terms with positive denominator. +* The conjecture is about `n = 1, 2, …` (the range of the comment). For `n = 0` the difference + is also `1` (`s 0 = 0/1`), so this choice does not matter. The difference is taken in `ℤ`. + We state the "always 1" part; the two exceptions (difference `2` at `n = 4, 6`) are checked + by `diff_data`. +-/ + +namespace Math0.Statements.A375522 + +/-! ### The primes -/ + +/-- The first prime among `q, q + 1, …, q + fuel - 1`, or `0` if there is none. -/ +def firstPrimeFrom : ℕ → ℕ → ℕ + | 0, _ => 0 + | fuel + 1, q => if q.Prime then q else firstPrimeFrom fuel (q + 1) + +/-- The least prime `> m`, searched in `m + 1, …, 2 m + 2` (Bertrand's postulate guarantees one, +see `primeAt_eq_nth`). -/ +def nextPrime (m : ℕ) : ℕ := firstPrimeFrom (m + 2) (m + 1) + +/-- The `i`-th prime, 0-indexed: `primeAt 0 = 2`, `primeAt 1 = 3`, … -/ +def primeAt : ℕ → ℕ + | 0 => 2 + | i + 1 => nextPrime (primeAt i) + +/-- The `k`-th prime, 1-indexed as in the OEIS: `prime 1 = 2`, `prime 2 = 3`, … -/ +def prime (k : ℕ) : ℕ := primeAt (k - 1) + +theorem firstPrimeFrom_spec (fuel q : ℕ) (h : ∃ r, r.Prime ∧ q ≤ r ∧ r < q + fuel) : + (firstPrimeFrom fuel q).Prime ∧ q ≤ firstPrimeFrom fuel q ∧ + ∀ r, q ≤ r → r < firstPrimeFrom fuel q → ¬ r.Prime := by + induction fuel generalizing q with + | zero => obtain ⟨r, -, h1, h2⟩ := h; omega + | succ fuel ih => + rw [firstPrimeFrom] + split_ifs with hq + · exact ⟨hq, le_rfl, fun r h1 h2 => by omega⟩ + · obtain ⟨r, hr, h1, h2⟩ := h + have hqr : q ≠ r := fun e => hq (e ▸ hr) + obtain ⟨h1', h2', h3'⟩ := ih (q + 1) ⟨r, hr, by omega, by omega⟩ + refine ⟨h1', by omega, fun r' hr1 hr2 => ?_⟩ + rcases Nat.eq_or_lt_of_le hr1 with e | e + · exact e ▸ hq + · exact h3' r' e hr2 + +/-- `primeAt` is Mathlib's `Nat.nth Nat.Prime`. -/ +theorem primeAt_eq_nth (i : ℕ) : primeAt i = Nat.nth Nat.Prime i := by + have hinf : (Set.ofPred Nat.Prime).Infinite := Nat.infinite_setOfPred_prime + induction i with + | zero => simp [primeAt] + | succ i ih => + rw [primeAt, ih] + set m := Nat.nth Nat.Prime i with hm + have hmp : m.Prime := Nat.nth_mem_of_infinite hinf i + obtain ⟨r, hr, hr1, hr2⟩ := Nat.exists_prime_lt_and_le_two_mul m hmp.ne_zero + obtain ⟨hx, hx1, hx2⟩ := + firstPrimeFrom_spec (m + 2) (m + 1) ⟨r, hr, by omega, by omega⟩ + have hn : (Nat.nth Nat.Prime (i + 1)).Prime := Nat.nth_mem_of_infinite hinf (i + 1) + have hlt : m < Nat.nth Nat.Prime (i + 1) := Nat.nth_strictMono hinf (Nat.lt_succ_self i) + rw [nextPrime] + rcases lt_trichotomy (firstPrimeFrom (m + 2) (m + 1)) (Nat.nth Nat.Prime (i + 1)) + with h | h | h + · have := Nat.le_nth_of_lt_nth_succ h hx + omega + · exact h + · exact absurd hn (hx2 _ (by omega) h) + +/-! ### The sums `s n` and the sequences -/ + +/-- `s n = ∑_{k = 1..n} 1 / (prime k * b k)` with the greedy +`b k = 1 + ⌊1 / ((1 - s (k - 1)) * prime k)⌋` (A375781), `s 0 = 0`. -/ +def s : ℕ → ℚ + | 0 => 0 + | n + 1 => s n + 1 / ((prime (n + 1) : ℚ) * + ((1 + ⌊1 / ((1 - s n) * (prime (n + 1) : ℚ))⌋ : ℤ) : ℚ)) + +/-- A375781: `b n = 1 + floor(1/((1 - s(n-1)) * prime(n)))` for `n ≥ 1`. -/ +def b (n : ℕ) : ℤ := 1 + ⌊1 / ((1 - s (n - 1)) * (prime n : ℚ))⌋ + +/-- The recursion of the OEIS programs: `s(n) = s(n-1) + 1/(prime(n) * b(n))`. -/ +theorem s_succ (n : ℕ) : s (n + 1) = s n + 1 / ((prime (n + 1) : ℚ) * (b (n + 1) : ℚ)) := rfl + +/-- A375521: `S1 n`, the numerator of `s n` in lowest terms. -/ +def S1 (n : ℕ) : ℤ := (s n).num + +/-- A375522: `a n = S2 n`, the denominator of `s n = ∑_{k = 1..n} 1 / (prime k * A375781 k)` +in lowest terms. -/ +def a (n : ℕ) : ℕ := (s n).den + +/-- The definition reproduces all 11 terms listed in OEIS (offset 0, kernel-checked). -/ +theorem a_data : (List.range 11).map (fun i => a i) = + [1, 2, 6, 15, 105, 1155, 1336335, 892896284280, 398631887241408183843480, + 19863422690705846097977473796903171171326157280, + 14091270035344566960604487534521565339065390839583445590118556137472614250693240040301050080] + := by + decide +kernel + +/-- `S1` reproduces the 11 terms listed in A375521 (offset 0, kernel-checked). -/ +theorem S1_data : (List.range 11).map (fun i => S1 i) = + [0, 1, 5, 14, 103, 1154, 1336333, 892896284279, 398631887241408183843479, + 19863422690705846097977473796903171171326157279, + 14091270035344566960604487534521565339065390839583445590118556137472614250693240040301050079] + := by + decide +kernel + +/-- `b` reproduces the 11 terms listed in A375781 (offset 1, kernel-checked). -/ +theorem b_data : (List.range 11).map (fun i => b (i + 1)) = + [1, 1, 2, 3, 5, 89, 39304, 46994541278, 17331821184409051471456, + 684945610024339520619912889548385212804350252, + 454557097914340869696918952726502107711786801276885341616727617337826266151394840009711293] + := by + decide +kernel + +/-- The differences `S2(n) - S1(n)` for `n = 1, …, 24` (kernel-checked), matching the start of +the list in the comment: `2` at `n = 4` and `n = 6`, `1` otherwise. (`a 24` has about +1.5 million digits; the comment's list goes on to `n = 34`.) -/ +theorem diff_data : (List.range 24).map (fun i => (a (i + 1) : ℤ) - S1 (i + 1)) = + [1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] := by + decide +kernel + +/-- Conjecture (Sigrist and Sloane, 2024): for every `n ≥ 1` other than `n = 4` and `n = 6`, +`S2(n) - S1(n) = 1`, i.e. `s n = 1 - 1 / a n`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → n ≠ 4 → n ≠ 6 → (a n : ℤ) - S1 n = 1 + +end Math0.Statements.A375522 diff --git a/lean/Math0/Statements/OEIS/A386538.lean b/lean/Math0/Statements/OEIS/A386538.lean new file mode 100644 index 0000000..1c1bf52 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A386538.lean @@ -0,0 +1,134 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A386538: maximum area of a lattice polygon inside a circle of radius `n` + +Source: https://oeis.org/A386538, _Felix Huber_, Aug 05 2025. Verbatim (COMMENTS section): +> Conjecture: The maximum possible area of a polygon within the circle would be the same if only +> the vertices but not the center were fixed on grid points. + +The entry's definition (offset 0): "a(n) is the maximum possible area of a polygon within a +circle of radius n, where both the center and the vertices lie on points of a unit square grid." + +## Encoding + +* The unit square grid is `ℤ × ℤ ⊆ ℝ × ℝ`; "within a circle of radius `r` with center `c`" means + in the closed disk `(x - c₁)² + (y - c₂)² ≤ r²` (boundary allowed; `a(1) = 2`, the square with + vertices `(±1, 0), (0, ±1)`, requires this). `latticeDisk c r` is the set of grid points in + that disk. +* Polygon areas. For a finite point set `S`, the largest area of a polygon whose vertices lie in + `S` is the area of the convex hull of `S`: the region of any polygon with vertices in `S` lies + in `convexHull S`, and `convexHull S` is itself a convex polygon with vertices in `S` (it lies + in the disk because the disk is convex). Degenerate cases (fewer than three non-collinear points) + give area `0`. So the maximum area of a polygon with grid vertices within the circle of radius + `r` around `c` is `maxArea c r = volume (convexHull ℝ (latticeDisk c r))`, the Lebesgue measure + in `ℝ × ℝ`. +* By translation invariance, the center on a grid point may be taken to be the origin; the + entry's `a(n)` is `maxArea 0 n` (a real number, in fact an even integer). +* The computable `a n` is the same quantity computed exactly: the grid points in the disk of + radius `n` around the origin are listed in lexicographic order (`pts`), their convex hull is + computed by Andrew's monotone chain algorithm (`chain` builds the lower hull from the sorted + list and the upper hull from the reversed list), and twice the area is the shoelace sum over + both chains (`twiceArea`). Since the hull is invariant under the rotation by 90°, twice the area + is a multiple of 4, so `a n = twiceArea n / 2` is exact. (`a n = (maxArea 0 n).toReal` is the + intended meaning; it is not proved here.) A Python transcription and `scipy.spatial.ConvexHull` + give the same values for `n ≤ 48`. +* Data. `a_data` checks the listed terms `a(0), …, a(12)`. The listed terms from `a(13)` on are + not all the true maximum areas: e.g. the entry lists `a(13) = 512`, but the convex 20-gon with + vertices `(±13, 0), (±12, ±5), (±10, ±8), (±8, ±10), (±5, ±12), (0, ±13)` (all on the circle) + has area 516, and `a_13` checks `a 13 = 516`. In the range `13 ≤ n ≤ 48` of the listed data, + the definition (and `a`) agrees with the listed values exactly for + `n = 14, 15, 16, 19, 20, 21, 24, 25`, which `a_data_more` checks; it gives larger values for all + other `n` in that range. The conjecture is read with its own definition of `a(n)` (the maximum + area), not with the listed numbers. +* Reading of the conjecture: for every `n ≥ 0` (the entry's offset), the maximum area of a + polygon with grid vertices within a circle of radius `n` whose center is an arbitrary point + `c ∈ ℝ²` (the maximum taken over the center as well) equals the maximum with a grid-point + center, i.e. `⨆ c, maxArea c n = maxArea 0 n`. Since `c = 0` is allowed, this is equivalent to + `maxArea c n ≤ maxArea 0 n` for all `c`. +-/ + +namespace Math0.Statements.A386538 + +open MeasureTheory + +/-! ### The computable sequence -/ + +/-- The grid points `(x, y) ∈ ℤ²` with `x² + y² ≤ n²`, in lexicographic order (by `x`, then `y`). -/ +def pts (n : ℕ) : List (ℤ × ℤ) := + (List.range (2 * n + 1)).flatMap fun i => (List.range (2 * n + 1)).filterMap fun j => + let x : ℤ := (i : ℤ) - n + let y : ℤ := (j : ℤ) - n + if x * x + y * y ≤ (n : ℤ) * n then some (x, y) else none + +/-- The cross product `(a - o) × (b - o)`; it is positive iff `o, a, b` make a left turn. -/ +def cross (o a b : ℤ × ℤ) : ℤ := (a.1 - o.1) * (b.2 - o.2) - (a.2 - o.2) * (b.1 - o.1) + +/-- One step of the monotone chain algorithm: the stack `s` holds the current chain with its last +point first; pop the last point while it does not make a strict left turn with `p`, then push +`p`. -/ +def push (p : ℤ × ℤ) : List (ℤ × ℤ) → List (ℤ × ℤ) + | a :: b :: rest => if cross b a p ≤ 0 then push p (b :: rest) else p :: a :: b :: rest + | s => p :: s +termination_by structural s => s + +/-- The monotone chain of a list of points (the lower hull for a lexicographically sorted list, +the upper hull for the reversed list), as a stack with its last point first. -/ +def chain (l : List (ℤ × ℤ)) : List (ℤ × ℤ) := l.foldl (fun s p => push p s) [] + +/-- The shoelace sum `Σ (xᵢ yᵢ₊₁ - xᵢ₊₁ yᵢ)` over the consecutive points of an open path. -/ +def pathCross : List (ℤ × ℤ) → ℤ + | a :: b :: rest => (a.1 * b.2 - b.1 * a.2) + pathCross (b :: rest) + | _ => 0 +termination_by structural s => s + +/-- Twice the area of the convex hull of the grid points in the closed disk of radius `n` around +the origin: the lower chain (first to last point) followed by the upper chain (last to first +point) is the hull boundary traversed counterclockwise; the stacks hold the chains reversed, +hence the sign. -/ +def twiceArea (n : ℕ) : ℤ := + -(pathCross (chain (pts n)) + pathCross (chain (pts n).reverse)) + +/-- `a n` is the maximum area of a polygon with vertices on grid points within the circle of +radius `n` centered at a grid point, computed as the area of the convex hull of the grid points +in the closed disk of radius `n` around the origin. -/ +def a (n : ℕ) : ℕ := (twiceArea n).toNat / 2 + +/-- The definition reproduces the first terms listed in OEIS, `a(0), …, a(12)` (kernel-checked). -/ +theorem a_data : (List.range 13).map (fun i => a (i + 0)) = + [0, 2, 8, 24, 42, 74, 104, 138, 186, 240, 304, 362, 424] := by + decide +kernel + +/-- The listed terms `a(13)` to `a(48)` that agree with the definition (kernel-checked). -/ +theorem a_data_more : [14, 15, 16, 19, 20, 21, 24, 25].map a = + [594, 690, 776, 1104, 1232, 1346, 1762, 1930] := by + decide +kernel + +/-- The true value at `n = 13` (the entry lists `512`): the convex hull of the grid points in the +disk of radius 13 is the 20-gon with vertices `(±13, 0), (±12, ±5), (±10, ±8), (±8, ±10), +(±5, ±12), (0, ±13)`, of area 516. -/ +theorem a_13 : a 13 = 516 := by + decide +kernel + +/-! ### The geometric quantity and the conjecture -/ + +/-- The grid points `(x, y) ∈ ℤ²` (as points of `ℝ × ℝ`) in the closed disk of radius `r` around +`c`. -/ +def latticeDisk (c : ℝ × ℝ) (r : ℝ) : Set (ℝ × ℝ) := + {p | ∃ x y : ℤ, p = ((x : ℝ), (y : ℝ)) ∧ ((x : ℝ) - c.1) ^ 2 + ((y : ℝ) - c.2) ^ 2 ≤ r ^ 2} + +/-- The maximum area of a polygon with vertices on grid points within the circle of radius `r` +around `c`: the Lebesgue measure of the convex hull of `latticeDisk c r`. -/ +noncomputable def maxArea (c : ℝ × ℝ) (r : ℝ) : ENNReal := + volume (convexHull ℝ (latticeDisk c r)) + +/-- The conjecture: for every `n ≥ 0`, the maximum area of a polygon with grid vertices within a +circle of radius `n` whose center is an arbitrary point of the plane (maximum over the center as +well) equals the maximum area when the center is a grid point (the origin), i.e. `a(n)`. -/ +def statement : Prop := + ∀ n : ℕ, (⨆ c : ℝ × ℝ, maxArea c n) = maxArea 0 n + +end Math0.Statements.A386538 diff --git a/lean/Math0/Statements/OEIS/A386655.lean b/lean/Math0/Statements/OEIS/A386655.lean new file mode 100644 index 0000000..34bb92a --- /dev/null +++ b/lean/Math0/Statements/OEIS/A386655.lean @@ -0,0 +1,149 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A386655: residues mod 6 of the e.g.f. coefficients of `∑ (2^n x + LambertW(x))^n / n!` + +Source: https://oeis.org/A386655, _Paul D. Hanna_, Aug 23 2025. Verbatim: +> Conjecture: for n >= 6, a(n) (mod 6) equals [1, 0, 3, 0, 3, 2] repeating. + +The entry's definition (offset 0): "E.g.f.: Sum_{n>=0} (2^n*x + LambertW(x))^n / n!", i.e. +`a(n) = n! [x^n] ∑_{m ≥ 0} (2^m x + W(x))^m / m!`, where `W(x) = LambertW(x)` is the power +series with `W(0) = 0` and `W(x) e^{W(x)} = x`. + +## Encoding + +* `a n` is the explicit formula listed in the entry (formula section; the first PARI program + is this formula): + `a(n) = Sum_{k=0..n} binomial(n,k) * 2^(k*(k+1)) * (2^k - (n-k))^(n-k-1)`. + For `k = n` the exponent is `-1` and the summand is `2^(n(n+1)) * (2^n)^(-1) = 2^(n^2)` + (as PARI evaluates it); `term n n` is this value `2^(n*n)`. For `k < n` the exponent + `n-k-1` is a natural number, the base `2^k - (n-k)` is an integer that may be negative, and + `0^0 = 1` (the case `n = 1`, `k = 0`), again as in PARI. So `a : ℕ → ℤ`; the sequence is + nonnegative (keyword `nonn`), and the conjecture is read with the residue `a n % 6` in + `{0, …, 5}` (`Int.emod`). +* The formula follows from the e.g.f. via `(2^m x + W)^m/m! = ∑_j 2^(m j) x^j/j! · W^(m-j)/(m-j)!` + (giving the entry's form `∑_j 2^(j^2) e^{2^j W} x^j/j!`) and the classical expansion + `e^{c W(x)} = ∑_k c (c-k)^(k-1) x^k/k!`; it is not a conjectured formula. This equivalence + is not proved in Lean here (Mathlib has neither the Lambert `W` series nor Lagrange + inversion). Instead, the definition is cross-checked in the kernel against a direct, literal + evaluation of the e.g.f. (`egf`): `W` is obtained from its defining equation + `W = x e^{-W}` by fixed-point iteration (`lambertW`, with `lambertW_spec` checking + `W e^W = x`), and `∑_m (2^m x + W)^m/m!` is evaluated with truncated e.g.f. arithmetic over + `ℤ` (coefficient lists of `x^i/i!`; `F^m/m!` is computed as `((F^(m-1)/(m-1)!) · F) / m`, + where every division is exact since `F` has zero constant term). Only `m ≤ N` contributes to + the coefficients of `x^0, …, x^N`, because `2^m x + W = O(x)`. `a_eq_egf` checks + `a n = egf` coefficient for `n = 0..16`, beyond the 13 listed terms. +* `a_data` checks all 13 terms listed in the entry (`n = 0..12`). +* The conjecture: for every `n ≥ 6`, `a(n) mod 6` is the `((n - 6) mod 6)`-th entry + (0-based) of `[1, 0, 3, 0, 3, 2]`, i.e. `a(6) ≡ 1`, `a(7) ≡ 0`, `a(8) ≡ 3`, `a(9) ≡ 0`, + `a(10) ≡ 3`, `a(11) ≡ 2`, `a(12) ≡ 1`, … (mod 6). `statement_data` confirms this reading + agrees with the listed terms `n = 6..12`. +-/ + +namespace Math0.Statements.A386655 + +/-! ### The explicit formula -/ + +/-- Binomial coefficient via descending factorials (fast in the kernel); equals `Nat.choose`. -/ +def binom (n k : ℕ) : ℕ := n.descFactorial k / k.factorial + +theorem binom_eq_choose (n k : ℕ) : binom n k = n.choose k := + (Nat.choose_eq_descFactorial_div_factorial n k).symm + +/-- The `k`-th summand `binomial(n,k) * 2^(k*(k+1)) * (2^k - (n-k))^(n-k-1)` of the explicit +formula; for `k = n` (exponent `-1`) it is `2^(n(n+1)) / 2^n = 2^(n^2)`. -/ +def term (n k : ℕ) : ℤ := + if k = n then 2 ^ (n * n) + else (binom n k : ℤ) * 2 ^ (k * (k + 1)) * ((2 : ℤ) ^ k - ((n - k : ℕ) : ℤ)) ^ (n - k - 1) + +/-- A386655: `a n = n! [x^n] ∑_{m ≥ 0} (2^m x + LambertW(x))^m / m!`, given by the entry's +explicit formula `a(n) = ∑_{k=0..n} binomial(n,k) 2^(k(k+1)) (2^k - (n-k))^(n-k-1)`. -/ +def a (n : ℕ) : ℤ := ∑ k ∈ Finset.range (n + 1), term n k + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 13).map (fun i => a (i + 0)) = + [1, 3, 23, 708, 82677, 39043808, 75384175459, 594418947869568, 19030890530555146281, + 2460681168464503636482816, 1280084112577610436036966382815, + 2672769582069469500760580570122074560, + 22366167041278673568399013569832022272725469] := by + decide +kernel + +/-! ### Cross-check: direct evaluation of the e.g.f. -/ + +/-- A truncated e.g.f. is a list `f` standing for `∑_i f[i] x^i / i!`; `coef f i = f[i]`. -/ +def coef (f : List ℤ) (i : ℕ) : ℤ := f.getD i 0 + +/-- Sum of e.g.f.s, truncated after `x^N`. -/ +def eadd (N : ℕ) (f g : List ℤ) : List ℤ := + (List.range (N + 1)).map fun n => coef f n + coef g n + +/-- Product of e.g.f.s, truncated after `x^N`: `(f g)_n = ∑_k C(n,k) f_k g_(n-k)`. -/ +def emul (N : ℕ) (f g : List ℤ) : List ℤ := + (List.range (N + 1)).map fun n => + ((List.range (n + 1)).map fun k => (binom n k : ℤ) * coef f k * coef g (n - k)).sum + +/-- `x · f`, truncated after `x^N`: `(x f)_n = n f_(n-1)`. -/ +def xmul (N : ℕ) (f : List ℤ) : List ℤ := + (List.range (N + 1)).map fun (n : ℕ) => (n : ℤ) * coef f (n - 1) + +/-- The e.g.f. `1`, truncated after `x^N`. -/ +def eone (N : ℕ) : List ℤ := 1 :: List.replicate N 0 + +/-- `F^m / m!`, truncated after `x^N`, for `F` with zero constant term (the division by `m` +is exact, as `F^m/m!` has integral e.g.f. coefficients). -/ +def powDivFact (N : ℕ) (F : List ℤ) : ℕ → List ℤ + | 0 => eone N + | m + 1 => (emul N (powDivFact N F m) F).map (· / ((m + 1 : ℕ) : ℤ)) + +/-- The pair `(F^j/j!, ∑_{i ≤ j} F^i/i!)`, truncated after `x^N`. -/ +def expAux (N : ℕ) (F : List ℤ) : ℕ → List ℤ × List ℤ + | 0 => (eone N, eone N) + | j + 1 => + let p := expAux N F j + let q := (emul N p.1 F).map (· / ((j + 1 : ℕ) : ℤ)) + (q, eadd N p.2 q) + +/-- `exp F = ∑_{j ≤ N} F^j/j!`, truncated after `x^N`, for `F` with zero constant term. -/ +def eexp (N : ℕ) (F : List ℤ) : List ℤ := (expAux N F N).2 + +/-- Fixed-point iteration `W ↦ x e^{-W}` from `W = 0`; after `i` steps the coefficients of +`x^0, …, x^(i-1)` agree with those of `LambertW(x)`. -/ +def lambertWIter (N : ℕ) : ℕ → List ℤ + | 0 => List.replicate (N + 1) 0 + | i + 1 => xmul N (eexp N ((lambertWIter N i).map (- ·))) + +/-- `LambertW(x)`, the solution of `W = x e^{-W}` (i.e. `W e^W = x`), truncated after `x^N`. -/ +def lambertW (N : ℕ) : List ℤ := lambertWIter N (N + 1) + +/-- `n! [x^n] ∑_{m ≥ 0} (2^m x + LambertW(x))^m / m!` for `n = 0..N` (only `m ≤ N` +contributes). -/ +def egf (N : ℕ) : List ℤ := + (List.range (N + 1)).foldl + (fun acc m => eadd N acc (powDivFact N (eadd N (lambertW N) [0, 2 ^ m]) m)) + (List.replicate (N + 1) 0) + +/-- Sanity check of `lambertW`: `W e^W = x` up to `x^16`, and its first coefficients are +`(-k)^(k-1)` as in the entry's example. -/ +theorem lambertW_spec : + emul 16 (lambertW 16) (eexp 16 (lambertW 16)) = eadd 16 [] [0, 1] ∧ + (lambertW 16).take 8 = [0, 1, -2, 9, -64, 625, -7776, 117649] := by + decide +kernel + +/-- The explicit formula agrees with the direct evaluation of the e.g.f. for `n = 0..16`. -/ +theorem a_eq_egf : (List.range 17).map a = egf 16 := by + decide +kernel + +/-- Hanna's conjecture (A386655): for `n ≥ 6`, `a(n) mod 6` runs through `[1, 0, 3, 0, 3, 2]` +periodically, starting with `1` at `n = 6`. -/ +def statement : Prop := + ∀ n : ℕ, 6 ≤ n → a n % 6 = ([1, 0, 3, 0, 3, 2] : List ℤ).getD ((n - 6) % 6) 0 + +/-- The reading of `statement` agrees with the listed terms `n = 6..12` (not a proof). -/ +theorem statement_data : + ∀ n ∈ List.range' 6 7, a n % 6 = ([1, 0, 3, 0, 3, 2] : List ℤ).getD ((n - 6) % 6) 0 := by + decide +kernel + +end Math0.Statements.A386655 diff --git a/lean/Math0/Statements/OEIS/A388724.lean b/lean/Math0/Statements/OEIS/A388724.lean new file mode 100644 index 0000000..66a4a57 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A388724.lean @@ -0,0 +1,258 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A388724: strictly superdiagonal reversed partitions by maximum + +Source: https://oeis.org/A388724, _Gus Wiseman_, Sep 24 2025 (FORMULA section). Verbatim: +> Conjecture: Column sums are A000245. + +The entry (offset `0`, keywords `nonn,tabl`) is "Triangle read by rows where T(n,k) is the number +of strictly superdiagonal reversed integer partitions of n with maximum k.", with the comment +"A sequence (y_1, ..., y_k) is strictly superdiagonal iff y_i > i for all i = 1..k." Its +Mathematica program counts `Reverse /@ IntegerPartitions[n]` (the partitions of `n` listed in +weakly increasing order) with `Max @@ # == k` and `y_i > i` for every position `i`, for +`0 ≤ k ≤ n`. + +A000245 (N. J. A. Sloane, offset `0`) is "a(n) = 3*(2*n)!/((n+2)!*(n-1)!)." with data +`0, 1, 3, 9, 28, 90, …`. + +## Encoding + +* *Reversed partitions.* A reversed integer partition of `n` is its multiset of parts listed in + weakly increasing order, i.e. a list `y = [y_1, …, y_m]` of positive integers with + `y_1 ≤ … ≤ y_m` and `y_1 + … + y_m = n` (`IsRevPartition n y`); each partition of `n` + corresponds to exactly one such list. The empty list is the reversed partition of `0`. +* *Strictly superdiagonal.* `y_i > i` for every position `i = 1, …, m`; with 0-indexed + `y[i] = y_{i+1}` this is `i + 1 < y[i]` for every `i < m` (`StrictlySuperdiagonal y`). +* *Maximum.* "With maximum `k`" is `y.max? = some k`. The empty partition of `0` has no maximum + (Mathematica's `Max[]` is `-Infinity`), so it is not counted for any `k`, which agrees with + the listed `T(0,0) = 0`. +* *The triangle.* `T n k` is the number (`Set.ncard`) of lists `y` that are reversed partitions + of `n`, strictly superdiagonal and have maximum `k`. It is defined for all `n, k`; outside the + triangle (`k > n`) it is `0` since the maximum part is at most the sum. The set is finite + (`T_eq_Tc` identifies it with a filtered finite list), so `Set.ncard` is its true size. + `a i` is the triangle read by rows with offset `0`: row `n` occupies the positions + `n(n+1)/2, …, n(n+1)/2 + n`, and its entries are `T(n,0), …, T(n,n)` (`rowOf i` is the row of + position `i`, the largest `n` with `n(n+1)/2 ≤ i`). +* *Computation.* `gen fuel lo n` enumerates the weakly increasing lists of integers `≥ lo` + with sum `n` (`mem_gen`, for `lo ≥ 1` and `n ≤ fuel`) without repetitions (`nodup_gen`), and + `T_eq_Tc` rewrites `T` as the length of a filter of `gen n 1 n`. `a_data` checks all 78 listed + terms (rows `0..11`) in the kernel. +* *A000245.* `A000245 n = 3 * (2n)! / ((n+2)! * (n-1)!)` for `n ≥ 1` (an exact division) and + `A000245 0 = 0`, as listed (the formula's `(-1)!` is infinite at `n = 0`). `A000245_data` + checks the first 28 listed terms. +* *The conjecture.* Column `k` of the triangle consists of the entries `T(n,k)`, `n ≥ k`; its + sum is `∑ᶠ n, T n k` (only finitely many terms are nonzero: `T n k = 0` for `n > k(k-1)`, + `T_eq_zero_of_lt`, so this is an honest finite sum, `colSum_eq`). The column sums are + `0, 0, 1, 3, 9, 28, 90, …` for `k = 0, 1, 2, …`, and "Column sums are A000245" is read with the + only alignment matching the listed values: the sum of column `k` is `A000245(k-1)` for every + `k ≥ 1` (column `0` is identically zero and is an extra leading `0`; nothing is claimed about + it). `statement_check` verifies this for `k = 1, …, 5` in the kernel (column sums + `0, 1, 3, 9, 28`; the naive enumeration of all partitions of `n ≤ 30` needed for `k = 6` + exhausts the kernel's memory). +-/ + +namespace Math0.Statements.A388724 + +open Finset + +/-! ### Definitions -/ + +/-- `y` is a reversed integer partition of `n`: a list of positive integers in weakly increasing +order with sum `n`. -/ +def IsRevPartition (n : ℕ) (y : List ℕ) : Prop := + (∀ x ∈ y, 0 < x) ∧ y.Pairwise (· ≤ ·) ∧ y.sum = n + +/-- `y = (y_1, …, y_m)` is strictly superdiagonal: `y_i > i` for all `i = 1..m` (0-indexed: +`y[i] > i + 1` for `i < m`). -/ +def StrictlySuperdiagonal (y : List ℕ) : Prop := ∀ i (h : i < y.length), i + 1 < y[i] + +instance : DecidablePred StrictlySuperdiagonal := fun y => by + unfold StrictlySuperdiagonal + infer_instance + +/-- A388724 as a triangle: `T(n,k)` is the number of strictly superdiagonal reversed integer +partitions of `n` with maximum `k`. -/ +noncomputable def T (n k : ℕ) : ℕ := + {y : List ℕ | IsRevPartition n y ∧ StrictlySuperdiagonal y ∧ y.max? = some k}.ncard + +/-- The row of position `i` in the triangle read by rows (offset `0`): the largest `n` with +`n(n+1)/2 ≤ i`. -/ +def rowOf (i : ℕ) : ℕ := Nat.findGreatest (fun n => n * (n + 1) / 2 ≤ i) i + +/-- A388724: the triangle `T(n,k)`, `0 ≤ k ≤ n`, read by rows (offset `0`). -/ +noncomputable def a (i : ℕ) : ℕ := T (rowOf i) (i - rowOf i * (rowOf i + 1) / 2) + +/-- A000245: `a(n) = 3*(2*n)!/((n+2)!*(n-1)!)`, with `a(0) = 0`. -/ +def A000245 (n : ℕ) : ℕ := + if n = 0 then 0 else 3 * (2 * n).factorial / ((n + 2).factorial * (n - 1).factorial) + +/-! ### Enumerating reversed partitions -/ + +/-- The weakly increasing lists of integers `≥ lo` with sum `n` (correct when `1 ≤ lo` and +`n ≤ fuel`, see `mem_gen`): the first entry is some `j ∈ [lo, n]`, followed by such a list with +entries `≥ j` and sum `n - j`. -/ +def gen : ℕ → ℕ → ℕ → List (List ℕ) + | 0, _, n => if n = 0 then [[]] else [] + | fuel + 1, lo, n => + if n = 0 then [[]] else + (List.range' lo (n + 1 - lo)).flatMap fun j => (gen fuel j (n - j)).map (j :: ·) + +theorem eq_nil_of_sum_eq_zero {lo : ℕ} {y : List ℕ} (hlo : 1 ≤ lo) (h : ∀ x ∈ y, lo ≤ x) + (hs : y.sum = 0) : y = [] := by + cases y with + | nil => rfl + | cons x t => + have hx := h x List.mem_cons_self + simp only [List.sum_cons] at hs + omega + +theorem mem_gen : ∀ (fuel lo n : ℕ) (y : List ℕ), 1 ≤ lo → n ≤ fuel → + (y ∈ gen fuel lo n ↔ (∀ x ∈ y, lo ≤ x) ∧ y.Pairwise (· ≤ ·) ∧ y.sum = n) + | 0, lo, n, y, hlo, hn => by + have hn0 : n = 0 := by omega + subst hn0 + simp only [gen, if_true, List.mem_singleton] + constructor + · rintro rfl + simp + · rintro ⟨h1, -, h3⟩ + exact eq_nil_of_sum_eq_zero hlo h1 h3 + | fuel + 1, lo, n, y, hlo, hn => by + by_cases hn0 : n = 0 + · subst hn0 + simp only [gen, if_true, List.mem_singleton] + constructor + · rintro rfl + simp + · rintro ⟨h1, -, h3⟩ + exact eq_nil_of_sum_eq_zero hlo h1 h3 + · simp only [gen, if_neg hn0, List.mem_flatMap, List.mem_range'_1, List.mem_map] + constructor + · rintro ⟨j, ⟨h1, h2⟩, t, ht, rfl⟩ + rw [mem_gen fuel j (n - j) t (by omega) (by omega)] at ht + obtain ⟨ht1, ht2, ht3⟩ := ht + simp only [List.mem_cons, forall_eq_or_imp, List.pairwise_cons, List.sum_cons] + exact ⟨⟨h1, fun x hx => le_trans h1 (ht1 x hx)⟩, ⟨ht1, ht2⟩, by omega⟩ + · rintro ⟨h1, h2, h3⟩ + cases y with + | nil => simp at h3; omega + | cons x t => + simp only [List.mem_cons, forall_eq_or_imp, List.pairwise_cons, List.sum_cons] + at h1 h2 h3 + refine ⟨x, ⟨h1.1, by omega⟩, t, ?_, rfl⟩ + rw [mem_gen fuel x (n - x) t (by omega) (by omega)] + exact ⟨h2.1, h2.2, by omega⟩ + +theorem nodup_gen : ∀ (fuel lo n : ℕ), (gen fuel lo n).Nodup + | 0, lo, n => by + unfold gen + split <;> simp + | fuel + 1, lo, n => by + unfold gen + split + · simp + · rw [List.nodup_flatMap] + refine ⟨fun j _ => (nodup_gen fuel j (n - j)).map List.cons_injective, ?_⟩ + refine (List.nodup_range' (s := lo) (n := n + 1 - lo)).imp fun {i j} hij => ?_ + intro y hy1 hy2 + simp only [List.mem_map] at hy1 hy2 + obtain ⟨t, -, rfl⟩ := hy1 + obtain ⟨t', -, h⟩ := hy2 + exact hij (List.cons.inj h).1.symm + +/-- Computable version of `T` (see `T_eq_Tc`). -/ +def Tc (n k : ℕ) : ℕ := + ((gen n 1 n).filter fun y => decide (StrictlySuperdiagonal y ∧ y.max? = some k)).length + +theorem T_eq_Tc (n k : ℕ) : T n k = Tc n k := by + have hset : {y : List ℕ | IsRevPartition n y ∧ StrictlySuperdiagonal y ∧ y.max? = some k} = + ↑((gen n 1 n).filter fun y => decide (StrictlySuperdiagonal y ∧ y.max? = some k)).toFinset + := by + ext y + simp only [Set.mem_ofPred_eq, List.coe_toFinset, List.mem_filter, decide_eq_true_eq, + mem_gen n 1 n y le_rfl le_rfl, IsRevPartition, Nat.one_le_iff_ne_zero, + Nat.pos_iff_ne_zero] + rw [T, hset, Set.ncard_coe_finset, List.toFinset_card_of_nodup ((nodup_gen n 1 n).filter _), + Tc] + +/-! ### Columns are finite -/ + +/-- A strictly superdiagonal reversed partition with maximum `k` has fewer than `k` parts, all at +most `k`, so its sum is at most `k(k-1)`. -/ +theorem T_eq_zero_of_lt {n k : ℕ} (h : k * (k - 1) < n) : T n k = 0 := by + have hempty : {y : List ℕ | IsRevPartition n y ∧ StrictlySuperdiagonal y ∧ + y.max? = some k} = ∅ := by + refine Set.eq_empty_iff_forall_notMem.2 ?_ + rintro y ⟨⟨-, -, hsum⟩, hss, hmax⟩ + rw [List.max?_eq_some_iff] at hmax + obtain ⟨hk, hle⟩ := hmax + have hpos : 0 < y.length := List.length_pos_of_mem hk + have hlast := hss (y.length - 1) (by omega) + have hlen : y.length + 1 ≤ k := by + have hmem : y[y.length - 1]'(by omega) ∈ y := List.getElem_mem _ + have := hle _ hmem + omega + have hs : y.sum ≤ y.length * k := by + simpa using List.sum_le_card_nsmul y k hle + have : y.length * k ≤ (k - 1) * k := Nat.mul_le_mul_right k (by omega) + rw [Nat.mul_comm (k - 1) k] at this + omega + rw [T, hempty, Set.ncard_empty] + +/-- The column sum `∑ᶠ n, T n k` is the finite sum over `n ≤ k(k-1)`. -/ +theorem colSum_eq (k : ℕ) : ∑ᶠ n, T n k = ∑ n ∈ range (k * (k - 1) + 1), T n k := by + apply finsum_eq_sum_of_support_subset + intro n hn + simp only [Function.mem_support, ne_eq, coe_range, Set.mem_Iio] at hn ⊢ + by_contra hlt + exact hn (T_eq_zero_of_lt (by omega)) + +/-! ### Data checks -/ + +theorem a_eq (i : ℕ) : + a i = Tc (rowOf i) (i - rowOf i * (rowOf i + 1) / 2) := by + rw [a, T_eq_Tc] + +/-- The definition reproduces all 78 terms listed in OEIS (rows `0..11`; kernel-checked). -/ +theorem a_data : (List.range 78).map (fun i => a i) = + [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, + 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 2, + 2, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 2, 2, 1, 1, 1, 0, 1] := by + simp only [a_eq] + decide +kernel + +/-- A000245: the first 28 listed terms (kernel-checked). -/ +theorem A000245_data : (List.range 28).map A000245 = + [0, 1, 3, 9, 28, 90, 297, 1001, 3432, 11934, 41990, 149226, 534888, 1931540, 7020405, + 25662825, 94287120, 347993910, 1289624490, 4796857230, 17902146600, 67016296620, + 251577050010, 946844533674, 3572042254128, 13505406670700, 51166197843852, + 194214400834356] := by + decide +kernel + +/-! ### The conjecture -/ + +/-- Conjecture (Wiseman, A388724): the column sums of the triangle are A000245, i.e. for every +`k ≥ 1`, the sum over all `n` of `T(n,k)` (the number of strictly superdiagonal reversed integer +partitions, of any size, with maximum `k`) equals `A000245(k-1)`. -/ +def statement : Prop := ∀ k : ℕ, 1 ≤ k → ∑ᶠ n, T n k = A000245 (k - 1) + +/-- Sanity check: the conjecture holds for the columns `k = 1, …, 5` (column sums +`0, 1, 3, 9, 28`; kernel-checked). -/ +theorem statement_check : ∀ k : ℕ, 1 ≤ k → k ≤ 5 → ∑ᶠ n, T n k = A000245 (k - 1) := by + have h : (List.range 5).map (fun j => ∑ n ∈ range ((j + 1) * j + 1), Tc n (j + 1)) = + (List.range 5).map A000245 := by + decide +kernel + intro k hk1 hk2 + obtain ⟨j, rfl⟩ : ∃ j, k = j + 1 := ⟨k - 1, by omega⟩ + have hj : j < 5 := by omega + have := congrArg (fun l => l[j]?) h + simp only [List.getElem?_map, List.getElem?_range hj, Option.map_some, Option.some.injEq] + at this + rw [colSum_eq, Nat.add_sub_cancel] + simpa [T_eq_Tc] using this + +end Math0.Statements.A388724 diff --git a/lean/Math0/Statements/OEIS/A392943.lean b/lean/Math0/Statements/OEIS/A392943.lean new file mode 100644 index 0000000..ac99e7f --- /dev/null +++ b/lean/Math0/Statements/OEIS/A392943.lean @@ -0,0 +1,402 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A392943: triangles with integer sides, area and circumradius, by semiperimeter + +Source: https://oeis.org/A392943, _Felix Huber_, Feb 04 2026. Verbatim: +> Conjecture: There is no primitive Heronian triangle with integer circumradius. + +The entry's name: "a(n) is the number of integer-sided triangles whose area and circumradius are +integers, and whose semiperimeter equals A392942(n)." (offset `1`). A392942 (same author, offset +`1`) is "Distinct semiperimeters of triangles with integer sides, integer area, and integer +circumradius.", listed in increasing order. + +## Encoding + +* A triangle is a triple of positive integer side lengths `x, y, z` satisfying the strict + triangle inequalities (`IsTriangle`), so it is nondegenerate. +* Area: by Heron's formula `16 · area² = (x+y+z)(-x+y+z)(x-y+z)(x+y-z)` (`heron16`). "Integer + area" means the area is a natural number `K`, i.e. `16 K² = heron16 x y z` (`HasArea`); for a + triangle the area is positive, so `K > 0`. +* Circumradius: `R = x y z / (4 K)`. Since `K > 0`, "integer circumradius" means + `4 K R = x y z` for a natural number `R` (the circumradius is positive). +* A Heronian triangle is one with integer sides and integer area; it is primitive when + `gcd(x, y, z) = 1`. `statement` says: no triangle with integer sides `x, y, z`, + `gcd(x, y, z) = 1` and integer area `K` has integer circumradius. +* For the sequence, triangles are counted up to congruence, i.e. as `x ≤ y ≤ z` (as in the + entry's Maple program and examples). The semiperimeter is `(x + y + z) / 2`, so "semiperimeter + `s`" means `x + y + z = 2 s`. No triangle is lost by taking `s` to be a natural number: a + triangle with integer sides and integer area has even perimeter (`even_perimeter`). `count s` + is computed by a fast loop and `count_eq_card` proves that it is the number of such triples + `(x, y, z)` (the Finset `triangles s`). +* `A392942 n` is computed by a search over `s ≤ 12 n` (every positive multiple of `12` is a + semiperimeter, by `isSemiperimeter_twelve_mul`), and `A392942_eq_nth` proves that it is the + `n`-th smallest semiperimeter, `Nat.nth IsSemiperimeter (n - 1)`, for `n ≥ 1`. + `a n = count (A392942 n)`; the value `a 0` is a junk value outside the OEIS offset. +* `a_data` checks the first 30 of the 88 listed terms (semiperimeters up to `A392942 30 = 156`); + all 88 listed terms agree with this definition in an independent Python computation. +-/ + +namespace Math0.Statements.A392943 + +/-- `x, y, z` are the side lengths of a nondegenerate triangle. -/ +def IsTriangle (x y z : ℕ) : Prop := + 0 < x ∧ 0 < y ∧ 0 < z ∧ x < y + z ∧ y < x + z ∧ z < x + y + +/-- Heron's formula: `16 · area² = (x+y+z)(-x+y+z)(x-y+z)(x+y-z)`. -/ +def heron16 (x y z : ℕ) : ℤ := + ((x : ℤ) + y + z) * (-x + y + z) * (x - y + z) * (x + y - z) + +/-- The triangle with sides `x, y, z` has area `K`, i.e. `16 K² = heron16 x y z`. -/ +def HasArea (x y z K : ℕ) : Prop := + 16 * (K : ℤ) ^ 2 = heron16 x y z + +/-- `x, y, z` is a triangle with integer sides, integer area `K` and integer circumradius +`R = x y z / (4 K)`. -/ +def IsGood (x y z : ℕ) : Prop := + IsTriangle x y z ∧ ∃ K R : ℕ, HasArea x y z K ∧ 4 * K * R = x * y * z + +/-! ### A fast Boolean decision procedure for `IsGood` (`goodB_iff`) + +The kernel evaluates the raw functions `Nat.add`, `Nat.ble`, ... much faster than the +corresponding notation, so the Boolean functions below are written with them. -/ + +/-- Boolean version of `IsTriangle`. -/ +def triB (x y z : ℕ) : Bool := + Nat.blt 0 x && Nat.blt 0 y && Nat.blt 0 z && Nat.blt x (Nat.add y z) && + Nat.blt y (Nat.add x z) && Nat.blt z (Nat.add x y) + +theorem triB_iff (x y z : ℕ) : triB x y z = true ↔ IsTriangle x y z := by + simp [triB, IsTriangle, Nat.blt_eq, and_assoc] + +/-- `sqMaskAux m n`: the bitmask with bit `r * r % m` set for every `r < n`. -/ +def sqMaskAux (m n : ℕ) : ℕ := + Nat.rec (motive := fun _ => ℕ) 0 + (fun r acc => Nat.lor acc (Nat.shiftLeft 1 (Nat.mod (Nat.mul r r) m))) n + +/-- The bitmask of the squares modulo `m`. -/ +def sqMask (m : ℕ) : ℕ := sqMaskAux m m + +theorem testBit_sqMaskAux (m n t : ℕ) (ht : t < n) : + (sqMaskAux m n).testBit (t * t % m) = true := by + induction n with + | zero => omega + | succ n ih => + show ((sqMaskAux m n) ||| (1 <<< (n * n % m))).testBit (t * t % m) = true + rw [Nat.testBit_or, Bool.or_eq_true] + rcases Nat.lt_succ_iff_lt_or_eq.1 ht with h | rfl + · exact Or.inl (ih h) + · right; simp [Nat.testBit_shiftLeft] + +/-- Bit number `n % m` of the bitmask of the squares modulo `m`: a necessary condition for `n` +to be a perfect square (`qrBit_mul_self`). -/ +def qrBit (m n : ℕ) : Bool := + Nat.beq (Nat.mod (Nat.shiftRight (sqMask m) (Nat.mod n m)) 2) 1 + +theorem qrBit_eq_testBit (m n : ℕ) : qrBit m n = (sqMask m).testBit (n % m) := by + rw [Nat.testBit_eq_decide_div_mod_eq, Bool.eq_iff_iff] + show Nat.beq ((sqMask m >>> (n % m)) % 2) 1 = true ↔ _ + rw [Nat.shiftRight_eq_div_pow, Nat.beq_eq, decide_eq_true_eq] + +theorem qrBit_mul_self (m r : ℕ) (hm : 0 < m) : qrBit m (r * r) = true := by + rw [qrBit_eq_testBit, Nat.mul_mod] + exact testBit_sqMaskAux m m _ (Nat.mod_lt _ hm) + +/-- A quick sieve: `false` only if `n` is not a perfect square, using the squares modulo +`4095 = 63 · 65`, `3553 = 11 · 17 · 19`, `667 = 23 · 29`, `1147 = 31 · 37`, `1763 = 41 · 43` +(see `maybeSquare_mul_self`). -/ +def maybeSquare (n : ℕ) : Bool := + qrBit 4095 n && (qrBit 3553 n && (qrBit 667 n && (qrBit 1147 n && qrBit 1763 n))) + +theorem maybeSquare_mul_self (r : ℕ) : maybeSquare (r * r) = true := by + simp [maybeSquare, qrBit_mul_self] + +/-- `16 · area²` computed in `ℕ` (exact for triangles, where no subtraction truncates). -/ +def heronNat (x y z : ℕ) : ℕ := + Nat.mul (Nat.mul (Nat.mul (Nat.add (Nat.add x y) z) (Nat.sub (Nat.add y z) x)) + (Nat.sub (Nat.add x z) y)) (Nat.sub (Nat.add x y) z) + +theorem heron16_eq (x y z : ℕ) (h : IsTriangle x y z) : + heron16 x y z = (heronNat x y z : ℤ) := by + obtain ⟨-, -, -, h1, h2, h3⟩ := h + have e : heronNat x y z = (x + y + z) * (y + z - x) * (x + z - y) * (x + y - z) := rfl + rw [heron16, e] + push_cast [Nat.cast_sub h1.le, Nat.cast_sub h2.le, Nat.cast_sub h3.le] + ring + +/-- With `r = ⌊√P⌋`, `P = heronNat x y z`: `P = r²`, `4 ∣ r` (so the area is `K = r / 4`) and +`r = 4 K` divides `x y z`. -/ +def finishB (x y z r : ℕ) : Bool := + Nat.beq (Nat.mul r r) (heronNat x y z) && + (Nat.beq (Nat.mod r 4) 0 && Nat.beq (Nat.mod (Nat.mul (Nat.mul x y) z) r) 0) + +theorem finishB_eq (x y z r : ℕ) : finishB x y z r = + (Nat.beq (r * r) (heronNat x y z) && (Nat.beq (r % 4) 0 && Nat.beq (x * y * z % r) 0)) := + rfl + +/-- `IsGood x y z` for a triangle `x, y, z`: the sieve, then the exact test on `⌊√P⌋`. -/ +def coreB (x y z : ℕ) : Bool := + maybeSquare (heronNat x y z) && finishB x y z (Nat.sqrt (heronNat x y z)) + +/-- Boolean version of `IsGood`, see `goodB_iff`. -/ +def goodB (x y z : ℕ) : Bool := + triB x y z && coreB x y z + +theorem goodB_iff (x y z : ℕ) : goodB x y z = true ↔ IsGood x y z := by + constructor + · intro h + simp only [goodB, coreB, finishB_eq, Bool.and_eq_true, Nat.beq_eq, triB_iff] at h + obtain ⟨htri, -, hsq, h4, hdvd⟩ := h + set r := Nat.sqrt (heronNat x y z) + obtain ⟨K, hK⟩ := Nat.dvd_of_mod_eq_zero h4 + refine ⟨htri, K, x * y * z / r, ?_, ?_⟩ + · rw [HasArea, heron16_eq _ _ _ htri, ← hsq, hK] + push_cast; ring + · rw [← hK, Nat.mul_div_cancel' (Nat.dvd_of_mod_eq_zero hdvd)] + · rintro ⟨htri, K, R, hK, hR⟩ + have hP : heronNat x y z = (4 * K) * (4 * K) := by + rw [HasArea, heron16_eq _ _ _ htri] at hK + have : ((heronNat x y z : ℕ) : ℤ) = (((4 * K) * (4 * K) : ℕ) : ℤ) := by + rw [← hK]; push_cast; ring + exact_mod_cast this + simp only [goodB, coreB, finishB_eq, Bool.and_eq_true, Nat.beq_eq, triB_iff, hP, Nat.sqrt_eq, + maybeSquare_mul_self] + refine ⟨htri, trivial, trivial, by simp, ?_⟩ + rw [← hR]; simp [Nat.mul_mod_right] + +instance (x y z : ℕ) : Decidable (IsGood x y z) := decidable_of_iff _ (goodB_iff x y z) + +/-- A triangle with integer sides and integer area has even perimeter: otherwise all four +factors of `heron16` are odd, while `16 K²` is even. -/ +theorem even_perimeter {x y z : ℕ} (h : IsGood x y z) : Even (x + y + z) := by + obtain ⟨-, K, -, hK, -⟩ := h + by_contra hodd + rw [Nat.not_even_iff_odd] at hodd + have h1 : Odd ((x : ℤ) + y + z) := by + have := (Int.odd_coe_nat (x + y + z)).2 hodd + push_cast at this + exact this + have h2 : Odd (-(x : ℤ) + y + z) := by + have e : -(x : ℤ) + y + z = ((x : ℤ) + y + z) - 2 * x := by ring + rw [e]; exact h1.sub_even (even_two_mul _) + have h3 : Odd ((x : ℤ) - y + z) := by + have e : (x : ℤ) - y + z = ((x : ℤ) + y + z) - 2 * y := by ring + rw [e]; exact h1.sub_even (even_two_mul _) + have h4 : Odd ((x : ℤ) + y - z) := by + have e : (x : ℤ) + y - z = ((x : ℤ) + y + z) - 2 * z := by ring + rw [e]; exact h1.sub_even (even_two_mul _) + have hodd16 : Odd (heron16 x y z) := ((h1.mul h2).mul h3).mul h4 + rw [HasArea] at hK + rw [← hK] at hodd16 + exact (Int.not_even_iff_odd.2 hodd16) ⟨8 * (K : ℤ) ^ 2, by ring⟩ + +/-! ### Counting the triangles with a given semiperimeter -/ + +/-- `sumIco a b f = ∑ k ∈ [a, b), f k`, written with the recursor so that the kernel +evaluates it quickly (see `sumIco_eq`). -/ +def sumIco (a b : ℕ) (f : ℕ → ℕ) : ℕ := + Nat.rec (motive := fun _ => ℕ) 0 (fun k acc => Nat.add acc (f (Nat.add a k))) (b - a) + +theorem sumIco_eq (a b : ℕ) (f : ℕ → ℕ) : sumIco a b f = ∑ k ∈ Finset.Ico a b, f k := by + rw [Finset.sum_Ico_eq_sum_range] + unfold sumIco + induction b - a with + | zero => simp + | succ n ih => rw [Finset.sum_range_succ, ← ih]; rfl + +/-- The triangle with sides `x ≤ y ≤ z = 2 s - x - y` is counted (Boolean form, `condB_iff`). -/ +def condB (s x y : ℕ) : Bool := + Nat.ble (Nat.add x y) (Nat.mul 2 s) && Nat.ble x y && + Nat.ble y (Nat.sub (Nat.sub (Nat.mul 2 s) x) y) && + goodB x y (Nat.sub (Nat.sub (Nat.mul 2 s) x) y) + +theorem condB_iff (s x y : ℕ) : condB s x y = true ↔ + x + y ≤ 2 * s ∧ x ≤ y ∧ y ≤ 2 * s - x - y ∧ IsGood x y (2 * s - x - y) := by + simp only [condB, Bool.and_eq_true, Nat.ble_eq, goodB_iff, and_assoc] + rfl + +/-- Number of triangles with integer sides `x ≤ y ≤ z`, semiperimeter `s` (`x + y + z = 2 s`), +integer area and integer circumradius. The loops run over `1 ≤ x ≤ 2 s / 3` and +`max(x, s + 1 - x) ≤ y ≤ (2 s - x) / 2`, i.e. exactly over the triangles `x ≤ y ≤ z = 2 s - x - y` +(`condB_eq_coreB`), so only the area and circumradius test `coreB` is needed in the loop body. +`count_eq_card` proves that this counts the triangles in question. -/ +def count (s : ℕ) : ℕ := + sumIco 1 (2 * s / 3 + 1) fun x => + sumIco (max x (s + 1 - x)) ((2 * s - x) / 2 + 1) fun y => + (coreB x y (Nat.sub (Nat.sub (Nat.mul 2 s) x) y)).toNat + +/-- The triangles counted by `count s`: triples `(x, y, z)` with `x ≤ y ≤ z`, `x + y + z = 2 s`, +integer area and integer circumradius. -/ +def triangles (s : ℕ) : Finset (ℕ × ℕ × ℕ) := + (Finset.range (2 * s + 1) ×ˢ Finset.range (2 * s + 1) ×ˢ Finset.range (2 * s + 1)).filter + fun t => t.1 ≤ t.2.1 ∧ t.2.1 ≤ t.2.2 ∧ t.1 + t.2.1 + t.2.2 = 2 * s ∧ IsGood t.1 t.2.1 t.2.2 + +theorem condB_eq_coreB {s x y : ℕ} (hx : x ∈ Finset.Ico 1 (2 * s / 3 + 1)) + (hy : y ∈ Finset.Ico (max x (s + 1 - x)) ((2 * s - x) / 2 + 1)) : + condB s x y = coreB x y (Nat.sub (Nat.sub (Nat.mul 2 s) x) y) := by + simp only [Finset.mem_Ico, max_le_iff] at hx hy + have e : Nat.sub (Nat.sub (Nat.mul 2 s) x) y = 2 * s - x - y := rfl + have h1 : Nat.ble (Nat.add x y) (Nat.mul 2 s) = true := by + rw [Nat.ble_eq]; show x + y ≤ 2 * s; omega + have h2 : Nat.ble x y = true := by rw [Nat.ble_eq]; omega + have h3 : Nat.ble y (Nat.sub (Nat.sub (Nat.mul 2 s) x) y) = true := by + rw [Nat.ble_eq, e]; omega + have h4 : triB x y (Nat.sub (Nat.sub (Nat.mul 2 s) x) y) = true := + (triB_iff _ _ _).2 (by rw [e]; unfold IsTriangle; omega) + simp only [condB, goodB, h1, h2, h3, h4, Bool.true_and] + +theorem condB_bounds {s x y : ℕ} (h : condB s x y = true) : + x ∈ Finset.Ico 1 (2 * s / 3 + 1) ∧ + y ∈ Finset.Ico (max x (s + 1 - x)) ((2 * s - x) / 2 + 1) := by + rw [condB_iff] at h + obtain ⟨h1, h2, h3, ⟨hx, hy, hz, t1, t2, t3⟩, -⟩ := h + simp only [Finset.mem_Ico, max_le_iff] + omega + +theorem sum_z (s x y : ℕ) : + ∑ z ∈ Finset.range (2 * s + 1), + (if x ≤ y ∧ y ≤ z ∧ x + y + z = 2 * s ∧ IsGood x y z then 1 else 0) = + (condB s x y).toNat := by + rw [Finset.sum_eq_single (2 * s - x - y)] + · by_cases hxy : x + y ≤ 2 * s + · have e : x + y + (2 * s - x - y) = 2 * s := by omega + by_cases hc : condB s x y = true + · rw [hc, if_pos] + · rfl + rw [condB_iff] at hc + exact ⟨hc.2.1, hc.2.2.1, e, hc.2.2.2⟩ + · rw [Bool.not_eq_true] at hc + rw [hc, if_neg] + · rfl + rintro ⟨h1, h2, -, h4⟩ + have := (condB_iff s x y).2 ⟨hxy, h1, h2, h4⟩ + rw [hc] at this + exact absurd this (by decide) + · have hc : condB s x y = false := by + rw [← Bool.not_eq_true, condB_iff]; omega + rw [hc, if_neg] + · rfl + omega + · intro z _ hz + rw [if_neg] + omega + · intro h; simp at h; omega + +/-- `count s` is the number of triangles with integer sides, area and circumradius and +semiperimeter `s`, up to congruence. -/ +theorem count_eq_card (s : ℕ) : count s = (triangles s).card := by + rw [triangles, Finset.card_filter, Finset.sum_product] + simp_rw [Finset.sum_product, sum_z] + rw [count, sumIco_eq] + have hR : ∀ x : ℕ, x ∈ Finset.Ico 1 (2 * s / 3 + 1) → + sumIco (max x (s + 1 - x)) ((2 * s - x) / 2 + 1) + (fun y => (coreB x y (Nat.sub (Nat.sub (Nat.mul 2 s) x) y)).toNat) = + ∑ y ∈ Finset.range (2 * s + 1), (condB s x y).toNat := by + intro x hx + rw [sumIco_eq, ← Finset.sum_congr rfl fun y hy => congrArg Bool.toNat (condB_eq_coreB hx hy)] + apply Finset.sum_subset + · intro y hy; simp only [Finset.mem_Ico, Finset.mem_range] at hy ⊢; omega + · intro y _ hy + cases hc : condB s x y + · rfl + · exact absurd (condB_bounds hc).2 hy + rw [Finset.sum_congr rfl hR] + apply Finset.sum_subset + · intro x hx; simp only [Finset.mem_Ico, Finset.mem_range] at hx ⊢; omega + · intro x _ hx + apply Finset.sum_eq_zero + intro y _ + cases hc : condB s x y + · rfl + · exact absurd (condB_bounds hc).1 hx + +/-! ### The semiperimeters (OEIS A392942) -/ + +/-- `s` is the semiperimeter of some triangle with integer sides, integer area and integer +circumradius. -/ +def IsSemiperimeter (s : ℕ) : Prop := 0 < count s + +instance : DecidablePred IsSemiperimeter := fun s => inferInstanceAs (Decidable (0 < count s)) + +theorem isGood_scaled (m : ℕ) (hm : 0 < m) : IsGood (6 * m) (8 * m) (10 * m) := by + refine ⟨by unfold IsTriangle; omega, 24 * m ^ 2, 5 * m, ?_, by ring⟩ + simp only [HasArea, heron16] + push_cast + ring + +/-- Every positive multiple of `12` is a semiperimeter: the triangle `(6m, 8m, 10m)` has +semiperimeter `12 m`, area `24 m²` and circumradius `5 m`. -/ +theorem isSemiperimeter_twelve_mul (m : ℕ) (hm : 0 < m) : IsSemiperimeter (12 * m) := by + rw [IsSemiperimeter, count_eq_card, Finset.card_pos] + refine ⟨(6 * m, 8 * m, 10 * m), ?_⟩ + simp only [triangles, Finset.mem_filter, Finset.mem_product, Finset.mem_range] + exact ⟨⟨by omega, by omega, by omega⟩, by omega, by omega, by omega, isGood_scaled m hm⟩ + +theorem le_count_twelve_mul (n : ℕ) : n ≤ Nat.count IsSemiperimeter (12 * n + 1) := by + rw [Nat.count_eq_card_filter_range] + calc n = ((Finset.range n).image fun k => 12 * (k + 1)).card := by + rw [Finset.card_image_of_injective _ (fun a b h => by simpa using h), Finset.card_range] + _ ≤ _ := by + apply Finset.card_le_card + intro t ht + simp only [Finset.mem_image, Finset.mem_range] at ht + obtain ⟨k, hk, rfl⟩ := ht + simp only [Finset.mem_filter, Finset.mem_range] + exact ⟨by omega, isSemiperimeter_twelve_mul _ (by omega)⟩ + +theorem infinite_isSemiperimeter : (Set.ofPred IsSemiperimeter).Infinite := by + apply Set.infinite_of_not_bddAbove + rintro ⟨B, hB⟩ + have := hB (show 12 * (B + 1) ∈ Set.ofPred IsSemiperimeter from + isSemiperimeter_twelve_mul _ (by omega)) + omega + +/-- OEIS A392942 (`n ≥ 1`): the `n`-th smallest semiperimeter, found as the `s ≤ 12 n` that is +a semiperimeter with exactly `n - 1` semiperimeters below it (see `A392942_eq_nth`). -/ +def A392942 (n : ℕ) : ℕ := + ((List.range (12 * n + 1)).find? fun s => + IsSemiperimeter s ∧ Nat.count IsSemiperimeter s = n - 1).getD 0 + +theorem A392942_eq_nth (n : ℕ) (hn : 1 ≤ n) : + A392942 n = Nat.nth IsSemiperimeter (n - 1) := by + set m := Nat.nth IsSemiperimeter (n - 1) + have hpm : IsSemiperimeter m := Nat.nth_mem_of_infinite infinite_isSemiperimeter _ + have hcm : Nat.count IsSemiperimeter m = n - 1 := + Nat.count_nth_of_infinite infinite_isSemiperimeter _ + have hmlt : m < 12 * n + 1 := + Nat.nth_lt_of_lt_count (by have := le_count_twelve_mul n; omega) + unfold A392942 + cases hf : (List.range (12 * n + 1)).find? fun s => + IsSemiperimeter s ∧ Nat.count IsSemiperimeter s = n - 1 with + | none => + rw [List.find?_eq_none] at hf + exact absurd (by simp [hpm, hcm]) (hf m (List.mem_range.2 hmlt)) + | some t => + have ht := List.find?_some hf + simp only [decide_eq_true_eq] at ht + exact Nat.count_injective ht.1 hpm (ht.2.trans hcm.symm) + +/-! ### The sequence -/ + +/-- OEIS A392943: `a n` is the number of triangles with integer sides, integer area and integer +circumradius whose semiperimeter is `A392942 n` (counted up to congruence, see +`count_eq_card`). -/ +def a (n : ℕ) : ℕ := count (A392942 n) + +/-- The definition reproduces the first terms listed in OEIS (kernel-checked). -/ +theorem a_data : (List.range 30).map (fun i => a (i + 1)) = + [1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 3, 2, 1, 1, 2, 1, 1, 4, 2, 2, 3, 2, 3, 1, 2, + 2] := by + decide +kernel + +/-- There is no primitive Heronian triangle with integer circumradius: for every triangle with +integer sides `x, y, z` with `gcd(x, y, z) = 1` and integer area `K`, the circumradius +`x y z / (4 K)` is not an integer `R`. -/ +def statement : Prop := + ∀ x y z K R : ℕ, IsTriangle x y z → HasArea x y z K → Nat.gcd x (Nat.gcd y z) = 1 → + 4 * K * R ≠ x * y * z + +end Math0.Statements.A392943 diff --git a/lean/Math0/Statements/OEIS/A393794.lean b/lean/Math0/Statements/OEIS/A393794.lean new file mode 100644 index 0000000..f140f37 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A393794.lean @@ -0,0 +1,83 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A393794: fixed points of the 1089-trick map + +Source: https://oeis.org/A393794, _Remco Havenaar_, Feb 27 2026. Verbatim (COMMENTS section): +> a(n) is the unique fixed point of the 1089-trick map T among all (n+4)-digit numbers (verified +> exhaustively for n = 1..4; conjectured for all n >= 1). + +The entry's name: "Fixed points of the 1089-trick map +T(n) = |n - reverse(n)| + reverse(|n - reverse(n)|)." + +## Encoding + +* `rev m` is `reverse(m)` (A004086): the decimal digits of `m` read backwards, as a number, so + leading zeros drop (`rev 10890 = 9801`, as in the entry's example `10890 - 09801 = 1089`). + It is `Nat.ofDigits 10 (Nat.digits 10 m).reverse` (`Nat.digits` is little-endian). +* `T x = D + rev D` with `D = |x - rev x|`, the absolute difference taken as `Nat.dist` + (no truncated subtraction). +* `a n = 110 * (10 ^ (n + 1) - 1)` for `n ≥ 1` (offset 1). This is the entry's formula + `a(n) = 110*(10^(n+1) - 1)`, which its data, Mathematica and Python programs all use to + generate the terms, and which its comment proves to be a fixed point of `T`. The conjecture + (the comment quoted above) is exactly the claim that these terms are the only fixed points + of their digit lengths, so `a` is not defined as "the `n`-th fixed point of `T`": that + reading of the name would make the conjecture assume what it claims. (`a 0 = 990` lies outside + the offset and is not used.) Kernel checks below: `a` reproduces all 18 listed terms + (`a_data`); `T` fixes each of them and each `a (i + 1)` has `i + 5` digits (`T_data`, + `digits_data`); and `10890 = a 1` is the least positive fixed point of `T` + (`least_fixed_point`), matching the name. +* "(n+4)-digit numbers" are the `x` with `(Nat.digits 10 x).length = n + 4`, i.e. + `10 ^ (n + 3) ≤ x < 10 ^ (n + 4)`. +* The statement covers every `n ≥ 1`, as the comment says ("conjectured for all n >= 1"; the + exhaustive checks for `n = 1..4` are part of that range). "a(n) is the unique fixed point + among all (n+4)-digit numbers" is encoded in full: `a n` has `n + 4` digits, `T (a n) = a n`, + and every `(n + 4)`-digit `x` with `T x = x` equals `a n`. +-/ + +namespace Math0.Statements.A393794 + +/-- `reverse(m)` (A004086): the number whose decimal digits are those of `m` in reverse order +(leading zeros of the result are dropped). -/ +def rev (m : ℕ) : ℕ := Nat.ofDigits 10 (Nat.digits 10 m).reverse + +/-- The 1089-trick map `T(x) = |x - reverse(x)| + reverse(|x - reverse(x)|)`. -/ +def T (x : ℕ) : ℕ := Nat.dist x (rev x) + rev (Nat.dist x (rev x)) + +/-- A393794: `a(n) = 110 * (10^(n+1) - 1)` (`n ≥ 1`), the fixed points `10890, 109890, +1099890, …` of the 1089-trick map `T` listed in the entry; `a(n)` has `n + 4` digits. -/ +def a (n : ℕ) : ℕ := 110 * (10 ^ (n + 1) - 1) + +/-- The definition reproduces all 18 terms listed in OEIS (offset 1, kernel-checked). -/ +theorem a_data : (List.range 18).map (fun i => a (i + 1)) = + [10890, 109890, 1099890, 10999890, 109999890, 1099999890, 10999999890, 109999999890, + 1099999999890, 10999999999890, 109999999999890, 1099999999999890, 10999999999999890, + 109999999999999890, 1099999999999999890, 10999999999999999890, 109999999999999999890, + 1099999999999999999890] := by + decide +kernel + +/-- `T` fixes each of the 18 listed terms (kernel-checked). -/ +theorem T_data : (List.range 18).all (fun i => T (a (i + 1)) == a (i + 1)) = true := by + decide +kernel + +/-- Each of the 18 listed terms `a (i + 1)` has `i + 5` decimal digits (kernel-checked). -/ +theorem digits_data : + (List.range 18).all (fun i => (Nat.digits 10 (a (i + 1))).length == i + 5) = true := by + decide +kernel + +/-- `10890 = a 1` is the least positive fixed point of `T` (kernel-checked; `T 0 = 0`). -/ +theorem least_fixed_point : + T (a 1) = a 1 ∧ (List.range (a 1)).all (fun x => x == 0 || T x != x) = true := by + decide +kernel + +/-- Conjecture (Havenaar, A393794): for every `n ≥ 1`, `a(n)` is the unique fixed point of the +1089-trick map `T` among all `(n + 4)`-digit numbers. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + (Nat.digits 10 (a n)).length = n + 4 ∧ T (a n) = a n ∧ + ∀ x : ℕ, (Nat.digits 10 x).length = n + 4 → T x = x → x = a n + +end Math0.Statements.A393794 diff --git a/lean/Math0/Statements/OEIS/A394981.lean b/lean/Math0/Statements/OEIS/A394981.lean new file mode 100644 index 0000000..7ee8ad7 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A394981.lean @@ -0,0 +1,247 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A394981: tilings of the smallest-perimeter rectangle by the bars `1 × 1, …, 1 × n` + +Source: https://oeis.org/A394981, _Gary Yane_, Apr 08 2026 (a(1)-a(2) corrected by +_Pontus von Brömssen_, May 13 2026). Verbatim (FORMULA section, unattributed): +> Conjecture: If n is odd, then a(n+1) = 4*a(n). + +The entry's definition (NAME): "Given a set of n rectangular tiles, +{1 X 1, 1 X 2, 1 X 3, 1 X 4, ..., 1 X n}, then a(n) is the number of tilings up to symmetry of the +rectangle having smallest possible perimeter with area n*(n+1)/2 using all n tiles." Its comment +fixes the rectangle: "The only rectangle we are looking at is the one with the smallest perimeter. +So, when n=8 the area is 36 and we are only counting the number of ways to use the tiles to make a +4 X 9 rectangle not 1 X 36, 2 X 18, nor 3 X 12 rectangles. That is, the short side of the +rectangle has length floor((n+1)/2)." Offset `1`; data `1, 1, 1, 4, 10, 40, 112, 448, 1360, 5440, +…` (20 terms listed). + +## Encoding + +* **The rectangle** has `r = rows n = ⌊(n + 1) / 2⌋` rows (the short side, as the comment says) + and `c = cols n = (n (n + 1) / 2) / r` columns, so its area is `n (n + 1) / 2`: it is `r × n` + for odd `n` and `r × (n + 1)` for even `n` (`rect_data`, `area_data`). This is the rectangle of + area `n (n + 1) / 2` of smallest perimeter among those the `1 × n` tile fits in (the comment's + `n = 8` example is `4 × 9`, not the `6 × 6` square, in which `1 × 8` does not fit). +* **Cells and cell sets.** Cell `(i, j)` (`i < r`, `j < c`) has index `p = i * w + j`, where + `w = c + 1`: each row is followed by one padding index `i * w + c` that is not a cell, so a run of + consecutive indices inside the rectangle never wraps from one row to the next. A set `S` of + indices is the bitmask `∑_{p ∈ S} 2 ^ p`; the rectangle is `rectMask r c w`. +* **Placements.** A placement of the `1 × k` tile is the set of cells it covers: the `k` cells + `q, q + 1, …, q + (k - 1)` (horizontal) or `q, q + w, …, q + (k - 1) w` (vertical) of one row + or column, all inside the rectangle. Their bitmasks are `barAt (2 ^ q) 1 1 k` and + `barAt (2 ^ q) 1 w k` (`barAt_eq` gives the sum of powers). For `k = 1` both orientations cover + the same single cell, i.e. are the same placement, so the vertical one is only used for `k ≥ 2`. +* **Tilings.** A tiling is an assignment, to every tile `k = 1, …, n`, of a placement, the + placements being pairwise disjoint and covering the rectangle. As the tiles have pairwise + different lengths, this is the same as a partition of the rectangle into one bar of each length + `1, …, n`, and different assignments are different tilings. +* **Enumeration.** `search` places the tiles `n, n - 1, …, 1` one after the other, each at every + placement inside the still free cells `free` (initially the whole rectangle), and at the end + requires that no free cell is left. So every tiling is produced exactly once (by the branch that + chooses its own placement for each tile). The possible first cells `q` of tile `k` in the + direction with step `s` are the set bits of `starts free s k`, whose bit `q` is set iff the cells + `q, q + s, …, q + (k - 1) s` all lie in `free` (`testBit_starts`); since `free` only contains + cells of the rectangle and the padding indices `i * w + c` and the indices `≥ r * w` are never + free, these are exactly the placements of tile `k` inside `free`. `sumBits g N X` is + `∑ g (2 ^ q)` over the set bits `q` of `X` (it peels off the lowest set bit + `X - (X &&& (X - 1))` of `X ≠ 0`, and `X &&& (X - 1)` is `X` with that bit cleared; all sets + here are subsets of `{0, …, N - 1}`, `N = r * w`, so `N` steps suffice). +* **The tiling as a labelling.** Along the way `lab` records the tiling: the field of `n` bits at + bit position `n * p` holds the length `k` of the tile covering cell `p` (`k ≤ n < 2 ^ n`, and the + placements are disjoint, so the fields never overflow into each other). `field n lab p` reads it. +* **Up to symmetry.** The symmetry group `G` of the rectangle acts on the cells, hence on tilings + (tile `k` of `g • T` covers the `g`-image of the cells of tile `k` of `T`). For a non-square + rectangle `G` consists of the identity, the two reflections in the axes and the half-turn; for a + square (here only `n = 1`, the `1 × 1` square) all 8 symmetries of the square. `g` fixes `T` iff + the labelling of `T` is `g`-invariant: `label (g p) = label p` for every cell `p` (`fixes`). + `a n` is the number of orbits, computed by Burnside's lemma as `(∑_T |Stab T|) / |G|`, where + `stabCount` is `|Stab T|` (the identity plus the non-identity symmetries `otherSymmetries` that + fix `T`). +* For speed in the kernel, the recursions are written with the recursors and the bit operations + with `Nat.land`/`Nat.shiftRight`/`Nat.beq` and `Bool` tests. +* **Data check.** `a_data` checks `a 1, …, a 9` against the listed terms in the kernel (about + 30 s of kernel time and 2.5 GB of memory on our machine; most of it is `a 9`, whose search has + about 42000 nodes). `a 10` is out of reach of the kernel: its search has about 258000 nodes, + roughly six times the time and memory of `a 9`. Not kernel-checked, but as further evidence: + `#eval` of this definition gives `a 10 = 5440` and `a 11 = 17728`, as listed, and an + independent Python enumeration (tilings as partitions of the rectangle into one bar of each + length, orbits under the symmetries of the rectangle) gives the listed `a 1, …, a 10`. + +## Reading of the conjecture + +With offset `1`, "if n is odd" literally includes `n = 1`, but the entry's own (corrected) data have +`a(1) = a(2) = 1` (the `1 × 1` square and the `1 × 3` rectangle each have exactly one tiling), so +the literal reading fails at `n = 1` (`literal_fails_at_one`, kernel-checked). The conjecture is +read as the pattern it describes in the listed data, `a(n + 1) = 4 a(n)` for every odd `n ≥ 3` +(it holds for all listed pairs `n = 3, 5, …, 19`). `statement` is this reading, with no other +hypotheses. +-/ + +namespace Math0.Statements.A394981 + +open Finset + +/-- The number of rows (the short side) of the rectangle for `n` tiles: `⌊(n + 1) / 2⌋`. -/ +def rows (n : ℕ) : ℕ := (n + 1) / 2 + +/-- The number of columns (the long side) of the rectangle for `n` tiles: the area +`n (n + 1) / 2` divided by `rows n` (this is `n` for odd `n` and `n + 1` for even `n`). -/ +def cols (n : ℕ) : ℕ := n * (n + 1) / 2 / rows n + +/-- The rectangles for `n = 1, …, 20`: `rows n × cols n`. -/ +theorem rect_data : (List.range 20).map (fun i => (rows (i + 1), cols (i + 1))) = + [(1, 1), (1, 3), (2, 3), (2, 5), (3, 5), (3, 7), (4, 7), (4, 9), (5, 9), (5, 11), (6, 11), + (6, 13), (7, 13), (7, 15), (8, 15), (8, 17), (9, 17), (9, 19), (10, 19), (10, 21)] := by + decide +kernel + +/-- The rectangle `rows n × cols n` has area `n (n + 1) / 2` for `n = 1, …, 20`. -/ +theorem area_data : + (List.range 20).all (fun i => rows (i + 1) * cols (i + 1) == (i + 1) * (i + 2) / 2) = true := by + decide +kernel + +/-- `barAt x b s k = x ^ b * (2 ^ (b s k) - 1) / (2 ^ (b s) - 1)`; for `x = 2 ^ q` this is +`∑_{t < k} 2 ^ (b (q + t s))` (`barAt_eq`): with `b = 1`, the bitmask of the `k` cells +`q, q + s, …, q + (k - 1) s`; with `b = n`, the same cells in fields of `n` bits. -/ +def barAt (x b s k : ℕ) : ℕ := x ^ b * ((2 ^ (b * (s * k)) - 1) / (2 ^ (b * s) - 1)) + +/-- `barAt (2 ^ q) b s k` is `∑_{t < k} 2 ^ (b (q + t s))`, for `b s ≥ 1`. -/ +theorem barAt_eq {b s : ℕ} (h : 1 ≤ b * s) (q k : ℕ) : + barAt (2 ^ q) b s k = ∑ t ∈ range k, 2 ^ (b * (q + t * s)) := by + have h2 : 2 ≤ 2 ^ (b * s) := by + calc 2 = 2 ^ 1 := by norm_num + _ ≤ 2 ^ (b * s) := Nat.pow_le_pow_right (by norm_num) h + have hg := Nat.geomSum_eq h2 k + have e1 : (2 ^ q) ^ b = 2 ^ (b * q) := by rw [← pow_mul, mul_comm] + have e2 : 2 ^ (b * (s * k)) = (2 ^ (b * s)) ^ k := by rw [← pow_mul, mul_assoc] + rw [barAt, e1, e2, ← hg, Finset.mul_sum] + refine Finset.sum_congr rfl fun t _ => ?_ + rw [← pow_mul, ← pow_add] + congr 1 + ring + +/-- The bitmask of the cells `(i, j)`, `i < r`, `j < c`, of the `r × c` rectangle with rows of +length `w` (cell `(i, j)` has index `i * w + j`): `∑_{i < r} (2 ^ c - 1) 2 ^ (i w)`. -/ +def rectMask (r c w : ℕ) : ℕ := + Nat.rec (motive := fun _ => ℕ) 0 (fun i m => m + (2 ^ c - 1) * 2 ^ (i * w)) r + +/-- `starts free s k` (for `k ≥ 1`) is `free &&& (free >>> s) &&& ⋯ &&& (free >>> ((k - 1) s))`: +its bit `q` is set iff the cells `q, q + s, …, q + (k - 1) s` all lie in `free` +(`testBit_starts`). -/ +def starts (free s k : ℕ) : ℕ := + Nat.rec (motive := fun _ => ℕ) free + (fun t acc => Nat.land acc (Nat.shiftRight free ((t + 1) * s))) (k - 1) + +/-- Bit `q` of `starts free s (k + 1)` is set iff bits `q, q + s, …, q + k s` of `free` are. -/ +theorem testBit_starts (free s q k : ℕ) : + (starts free s (k + 1)).testBit q = true ↔ ∀ t < k + 1, free.testBit (q + t * s) = true := by + simp only [starts, Nat.add_sub_cancel] + induction k with + | zero => simp + | succ k ih => + change (Nat.land (Nat.rec (motive := fun _ => ℕ) free + (fun t acc => Nat.land acc (Nat.shiftRight free ((t + 1) * s))) k) + (Nat.shiftRight free ((k + 1) * s))).testBit q = true ↔ _ + rw [Nat.land_eq, Nat.testBit_and, Bool.and_eq_true, ih, Nat.shiftRight_eq, + Nat.testBit_shiftRight] + constructor + · rintro ⟨h1, h2⟩ t ht + rcases Nat.lt_succ_iff_lt_or_eq.mp ht with ht | ht + · exact h1 t ht + · subst ht; rwa [Nat.add_comm] + · intro h + exact ⟨fun t ht => h t (by omega), by rw [Nat.add_comm]; exact h (k + 1) (by omega)⟩ + +/-- `sumBits g fuel X` is the sum of `g (2 ^ q)` over the set bits `q` of `X`, if `X` has at most +`fuel` set bits: `X - (X &&& (X - 1))` is the lowest set bit `2 ^ q` of `X ≠ 0`, and +`X &&& (X - 1)` is `X` with that bit cleared. -/ +def sumBits (g : ℕ → ℕ) (fuel : ℕ) : ℕ → ℕ := + Nat.rec (motive := fun _ => ℕ → ℕ) (fun _ => 0) + (fun _ ih X => + bif Nat.beq X 0 then 0 else g (X - Nat.land X (X - 1)) + ih (Nat.land X (X - 1))) fuel + +/-- `search w N L f k free lab` is the sum of `f lab'` over all ways of placing the tiles +`k, k - 1, …, 1` (in this order) at pairwise disjoint placements inside the set of free cells +`free` (rows of length `w`, all indices `< N`) that leave no cell free, where `lab'` is `lab` +plus the labels of the placed tiles (fields of `L` bits). Tile `k` goes horizontally at the first +cells `q` given by the set bits of `starts free 1 k`, or, if `k ≥ 2`, vertically at those of +`starts free w k`; its cells are then removed from `free`, and `k` is written into their fields +of `lab`. -/ +def search (w N L : ℕ) (f : ℕ → ℕ) : ℕ → ℕ → ℕ → ℕ := + Nat.rec (motive := fun _ => ℕ → ℕ → ℕ) + (fun free lab => bif Nat.beq free 0 then f lab else 0) + (fun k ih free lab => + sumBits (fun x => ih (free - barAt x 1 1 (k + 1)) (lab + (k + 1) * barAt x L 1 (k + 1))) + N (starts free 1 (k + 1)) + + bif Nat.ble 1 k then + sumBits (fun x => ih (free - barAt x 1 w (k + 1)) (lab + (k + 1) * barAt x L w (k + 1))) + N (starts free w (k + 1)) + else 0) + +/-- The label of cell `p` in the labelling `lab` (fields of `L` bits): the field at bit position +`L * p`. -/ +def field (L lab p : ℕ) : ℕ := Nat.land (Nat.shiftRight lab (L * p)) (2 ^ L - 1) + +/-- The non-identity symmetries of the `r × c` rectangle, as maps on cell coordinates `(i, j)`: +the reflections in the horizontal and in the vertical axis, and the half-turn; if the rectangle is +a square (`r = c`), also the reflections in the two diagonals and the two quarter-turns. Together +with the identity they form the symmetry group of the rectangle. -/ +def otherSymmetries (r c : ℕ) : List (ℕ × ℕ → ℕ × ℕ) := + [fun p => (r - 1 - p.1, p.2), fun p => (p.1, c - 1 - p.2), + fun p => (r - 1 - p.1, c - 1 - p.2)] ++ + (if r = c then + [fun p => (p.2, p.1), fun p => (c - 1 - p.2, r - 1 - p.1), fun p => (p.2, r - 1 - p.1), + fun p => (c - 1 - p.2, p.1)] + else []) + +/-- Whether the symmetry `g` fixes the tiling with labelling `lab` (fields of `L` bits, rows of +length `w`) of the `r × c` rectangle: `label (g (i, j)) = label (i, j)` for all cells `(i, j)`. +(Tile `k` of `g • T` covers the `g`-image of tile `k` of `T`, so `g • T = T` iff the labelling is +`g`-invariant.) -/ +def fixes (r c w L : ℕ) (g : ℕ × ℕ → ℕ × ℕ) (lab : ℕ) : Bool := + Nat.rec (motive := fun _ => Bool) true + (fun i ih => + Nat.rec (motive := fun _ => Bool) true + (fun j ihj => + Nat.beq (field L lab ((g (i, j)).1 * w + (g (i, j)).2)) (field L lab (i * w + j)) && + ihj) c && + ih) r + +/-- The size of the stabilizer of the tiling with labelling `lab`: the identity (which fixes every +tiling) plus the non-identity symmetries of the rectangle fixing it. -/ +def stabCount (r c w L : ℕ) (lab : ℕ) : ℕ := + 1 + List.rec (motive := fun _ => ℕ) 0 + (fun g _ ih => (bif fixes r c w L g lab then 1 else 0) + ih) (otherSymmetries r c) + +/-- A394981: the number of tilings, up to the symmetries of the rectangle, of the +`rows n × cols n` rectangle (area `n (n + 1) / 2`, smallest perimeter) by the `n` tiles +`1 × 1, 1 × 2, …, 1 × n`, each used exactly once. By Burnside's lemma it is the sum of the +stabilizer sizes over all tilings (enumerated by `search`, starting from the whole rectangle free +and the empty labelling, with fields of `n` bits) divided by the order `1 + |otherSymmetries|` of +the symmetry group. -/ +def a (n : ℕ) : ℕ := + let r := rows n + let c := cols n + let w := c + 1 + search w (r * w) n (stabCount r c w n) n (rectMask r c w) 0 / + (1 + (otherSymmetries r c).length) + +/-- The definition reproduces the first 9 terms listed in OEIS (offset 1, kernel-checked). -/ +theorem a_data : (List.range 9).map (fun i => a (i + 1)) = + [1, 1, 1, 4, 10, 40, 112, 448, 1360] := by + decide +kernel + +/-- The literal reading of the conjecture, which includes `n = 1`, fails there: +`a 2 = 1 ≠ 4 = 4 * a 1` (kernel-checked). This is why `statement` starts at `n = 3`. -/ +theorem literal_fails_at_one : a (1 + 1) ≠ 4 * a 1 := by + decide +kernel + +/-- Conjecture (A394981, FORMULA section): if `n` is odd, then `a(n + 1) = 4 a(n)`; read for every +odd `n ≥ 3`, since the degenerate case `n = 1` fails (`literal_fails_at_one`). -/ +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → Odd n → a (n + 1) = 4 * a n + +end Math0.Statements.A394981 diff --git a/lean/Math0/Statements/OEIS/A395454.lean b/lean/Math0/Statements/OEIS/A395454.lean new file mode 100644 index 0000000..1d04b47 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A395454.lean @@ -0,0 +1,144 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A395454: a polynomial recurrence for the row polynomials of a binomial/Eulerian triangle + +Source: https://oeis.org/A395454, Per W. Alexandersson, Jun 27 2026 (FORMULA section; the entry +itself is by Peter Luschny, Apr 23 2026). Verbatim: +> Conjecture: Let P(n) be the generating polynomial (in t) of row n. Then P(n) = (n - 2*t + n*t +> - 2)*P(n-1) + (t - t^2)*P'(n-1) + t*(2*n-4)*P(n-2). + +The entry (offset `0`, keyword `tabl`) is "Triangle read by rows: T(n, k) = Sum_{j=0..n} +C(-j-1, -n-1)*E2(j, n-k), E2 the Eulerian numbers A201637", with Maple program +`A395454 := (n, k) -> add(binomial(-j-1, -n-1)*combinat:-eulerian2(j, n-k), j=0..n)`, and rows +`n = 0, 1, 2, …` with `0 ≤ k ≤ n`. + +## Encoding + +* *Second-order Eulerian numbers* (A201637, Concrete Mathematics / Maple indexing): `E2 n k` + is given by `E2(0,0) = 1`, `E2(0,k) = 0` for `k ≥ 1`, and for `n ≥ 1` the recurrence of + A201637, `E2(n,k) = (2n-1-k)·E2(n-1,k-1) + (k+1)·E2(n-1,k)` (with `E2(n-1,-1) = 0`, so + `E2(n,0) = E2(n-1,0)`). It is computed in `ℤ`, so `2n-1-k` is honest integer subtraction. +* *The binomial factor.* Maple's `binomial(-j-1, -n-1)` (defined for negative integers by the + Gamma-function limit) equals `(-1)^(n-j)·C(n,j)` for `0 ≤ j ≤ n`; that is what we use. So + `T n k = ∑_{j=0}^{n} (-1)^(n-j)·C(n,j)·E2(j, n-k)` in `ℤ` (it is only used for `k ≤ n`, so + `n - k` is the true difference). +* *Data.* `a` is the triangle read by rows (the OEIS sequence itself, offset `0`), and `a_data` + checks all 55 listed terms (rows `0, …, 9`) as `a 0, …, a 54` in the kernel. +* *Row polynomials.* `P n = ∑_{k=0}^{n} T(n,k)·t^k ∈ ℤ[t]` is the generating polynomial of the + row with index `n` in the entry's numbering (offset `0`: `P 0 = 1`, `P 1 = 0`, `P 2 = 2t`, + `P 3 = 6t + 2t^2`, …). `P'` is the formal derivative in `t`. + +## Reading of the conjecture + +Read with the entry's row numbering (row `n` = `P n`, offset `0`), the recurrence is false at +every `n ≥ 2` for which it can be tested: already at `n = 2` the right-hand side is +`0·P(1) + (t - t^2)·P'(1) + t·0·P(0) = 0` (as `P 1 = 0`), while `P 2 = 2t` +(`not_statement_literal`, kernel-checked), and at `n = 3` it gives `4t` instead of +`6t + 2t^2`; an exact computation finds it false for every `n = 2, …, 19`. With the rows counted +from `1` instead (the `n`-th row is the row with index `n - 1`, i.e. `P(n)` of the conjecture is +`P (n - 1)` here) the same recurrence holds for all of `n = 3, …, 20` (exact computation, not +kernel-checked). So the conjecture is read as the claim it makes about the listed rows, with +the rows numbered from `1`, as the author's `P(n)` evidently does: + +* `P1 n = P (n - 1)` is the generating polynomial of the `n`-th row counted from `1` + (`P1 1 = 1`, `P1 2 = 0`, `P1 3 = 2t`, …; it is only used for `n ≥ 1`). +* `statement`: for every `n ≥ 3` (the range in which `P(n)`, `P(n-1)` and `P(n-2)` are all rows; + the formula itself states no range, and at `n = 2` the would-be `P(0)` has the coefficient + `2n - 4 = 0`), `P(n) = (n - 2t + n t - 2)·P(n-1) + (t - t^2)·P'(n-1) + t·(2n-4)·P(n-2)` in + `ℤ[t]`, with `P = P1` and all coefficients `n - 2`, `2n - 4` read as integers. In the entry's + numbering (`m = n - 1 ≥ 2`) this is + `P_m = (m-1)(1+t)·P_{m-1} + (t - t^2)·P'_{m-1} + 2(m-1)t·P_{m-2}`. +* The literal reading with the entry's numbering is recorded as `statement_literal`, together + with its refutation `not_statement_literal` at `n = 2`; it is not the primary formalization. +-/ + +namespace Math0.Statements.A395454 + +open Polynomial + +/-- The second-order Eulerian numbers `E2(n, k)` of A201637 (Graham–Knuth–Patashnik indexing, as +in Maple's `combinat:-eulerian2`): `E2(0,0) = 1`, `E2(0,k) = 0` for `k ≥ 1`, and +`E2(n,k) = (2n-1-k)·E2(n-1,k-1) + (k+1)·E2(n-1,k)` for `n ≥ 1` (with `E2(n-1,-1) = 0`). -/ +def E2 : ℕ → ℕ → ℤ + | 0, 0 => 1 + | 0, _ + 1 => 0 + | n + 1, 0 => E2 n 0 + | n + 1, k + 1 => + (2 * ((n : ℤ) + 1) - 1 - ((k : ℤ) + 1)) * E2 n k + ((k : ℤ) + 1 + 1) * E2 n (k + 1) + +/-- `E2` reproduces rows `0, …, 8` of A201637 (kernel-checked). -/ +theorem E2_data : (List.range 9).flatMap (fun n => (List.range (n + 1)).map (E2 n)) = + [1, 1, 0, 1, 2, 0, 1, 8, 6, 0, 1, 22, 58, 24, 0, 1, 52, 328, 444, 120, 0, 1, 114, 1452, + 4400, 3708, 720, 0, 1, 240, 5610, 32120, 58140, 33984, 5040, 0, 1, 494, 19950, 195800, + 644020, 785304, 341136, 40320, 0] := by + decide +kernel + +/-- The triangle `T(n, k) = ∑_{j=0}^{n} binomial(-j-1, -n-1)·E2(j, n-k)` of A395454, where +Maple's `binomial(-j-1, -n-1) = (-1)^(n-j)·C(n, j)` for `0 ≤ j ≤ n`. Meaningful for `k ≤ n`. -/ +def T (n k : ℕ) : ℤ := + ∑ j ∈ Finset.range (n + 1), (-1) ^ (n - j) * (n.choose j : ℤ) * E2 j (n - k) + +/-- A395454 itself: the triangle `T` read by rows (`0 ≤ k ≤ n`), offset `0`. -/ +def a (i : ℕ) : ℤ := + ((List.range (i + 1)).flatMap fun n => (List.range (n + 1)).map (T n)).getD i 0 + +/-- The definition reproduces all 55 terms listed in OEIS, `a 0, …, a 54` (rows `0, …, 9`; +kernel-checked). -/ +theorem a_data : (List.range 55).map (fun i => a (i + 0)) = + [1, 0, 0, 0, 2, 0, 0, 6, 2, 0, 0, 24, 34, 2, 0, 0, 120, 324, 98, 2, 0, 0, 720, 2988, 2096, + 234, 2, 0, 0, 5040, 28944, 34704, 9804, 514, 2, 0, 0, 40320, 300816, 533592, 276004, + 38856, 1082, 2, 0, 0, 362880, 3371040, 8137512, 6535272, 1766008, 139940, 2226, 2, 0] := by + decide +kernel + +/-- The generating polynomial (in `t`) of row `n` of the triangle: +`P(n) = ∑_{k=0}^{n} T(n,k)·t^k`. -/ +noncomputable def P (n : ℕ) : ℤ[X] := + ∑ k ∈ Finset.range (n + 1), C (T n k) * X ^ k + +/-- The generating polynomial of the `n`-th row of the triangle counted from `1` (the row with +index `n - 1` in the entry's numbering): `P1 n = P (n - 1)`. Meaningful for `n ≥ 1`. -/ +noncomputable def P1 (n : ℕ) : ℤ[X] := P (n - 1) + +/-- Alexandersson's conjecture (A395454), with the rows counted from `1` (see the module +docstring): for all `n ≥ 3`, +`P(n) = (n - 2t + n t - 2)·P(n-1) + (t - t^2)·P'(n-1) + t·(2n-4)·P(n-2)`, where `P(n) = P1 n`. -/ +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → + P1 n = ((n : ℤ[X]) - 2 * X + (n : ℤ[X]) * X - 2) * P1 (n - 1) + + (X - X ^ 2) * derivative (P1 (n - 1)) + + X * (2 * (n : ℤ[X]) - 4) * P1 (n - 2) + +/-- The literal reading of the conjecture with the entry's own row numbering (offset `0`, +`P(n) = P n`), for all `n ≥ 2`. Not the primary formalization: it fails at `n = 2` +(`not_statement_literal`). -/ +def statement_literal : Prop := + ∀ n : ℕ, 2 ≤ n → + P n = ((n : ℤ[X]) - 2 * X + (n : ℤ[X]) * X - 2) * P (n - 1) + + (X - X ^ 2) * derivative (P (n - 1)) + + X * (2 * (n : ℤ[X]) - 4) * P (n - 2) + +theorem P_one : P 1 = 0 := by + have h0 : T 1 0 = 0 := by decide +kernel + have h1 : T 1 1 = 0 := by decide +kernel + simp [P, Finset.sum_range_succ, h0, h1] + +theorem P_two : P 2 = C 2 * X := by + have h0 : T 2 0 = 0 := by decide +kernel + have h1 : T 2 1 = 2 := by decide +kernel + have h2 : T 2 2 = 0 := by decide +kernel + simp [P, Finset.sum_range_succ, h0, h1, h2] + +/-- The literal reading fails at `n = 2`: `P 2 = 2t`, but the right-hand side is `0` +(kernel-checked). -/ +theorem not_statement_literal : ¬ statement_literal := by + intro h + have h2 := h 2 le_rfl + have hc := congrArg (fun p : ℤ[X] => p.coeff 1) h2 + simp only [Nat.reduceSub, P_one, P_two, mul_zero, derivative_zero, zero_add] at hc + norm_num at hc + +end Math0.Statements.A395454 diff --git a/lean/Math0/Statements/OEIS/A397315.lean b/lean/Math0/Statements/OEIS/A397315.lean new file mode 100644 index 0000000..c7e58f8 --- /dev/null +++ b/lean/Math0/Statements/OEIS/A397315.lean @@ -0,0 +1,173 @@ +/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Mathlib + +/-! +# OEIS A397315: maximum blackout of an `n × k` grid keeping all lattice rectangles identifiable + +Source: https://oeis.org/A397315, _Arjun Pemmasani_, Sep 02 2026. Verbatim (COMMENTS section): +> Conjecture: T(n,m) = n+m whenever min(n,m) >= 4, except T(4,4) = 7 and T(4,5) = 8 (verified +> on seven cells through 6 X 6). + +The entry's definition: "Table read by antidiagonals: T(n,k) = maximum number of points that can +be blacked out of an n X k grid of points so that every rectangle with all four vertices on grid +points (tilted rectangles included) is uniquely identifiable from its set of visible vertices; +n, k >= 2." The comments make "identifiable" precise: the map `R ↦ C(R) \ S` (vertex set of the +rectangle minus the blacked-out set `S`) must be injective over all rectangles. + +## Encoding + +* The `n × k` grid is `{0, …, k-1} × {0, …, n-1} ⊆ ℤ × ℤ`, exactly as in the entry's Python and + PARI programs (`x < k`, `y < n`). Its points are numbered `i = x * n + y`, `0 ≤ i < n * k`, so + point `i` is `pt n i = (i / n, i % n)`; a set of grid points is a bitmask (bit `i` set iff + point `i` is in the set). +* A rectangle (tilted ones included, squares included) is the vertex set `{a, b, c, d}` of three + pairwise distinct grid points `a, b, c` with a right angle at `b`, i.e. + `(a - b) · (c - b) = 0`, whose fourth vertex `d = a + c - b` is again a grid point. These are + exactly the conditions of the entry's programs. `rects n k` lists every such vertex set once + (duplicates, which arise from the 8 ways to choose `(a, b, c)` for one rectangle, are erased). +* A blackout `B ⊆ grid` is valid iff the visible parts `R \ B` of the distinct rectangles `R` are + pairwise distinct, i.e. `R ↦ R \ B` is injective on rectangles. `T n k` is the largest number of + points of a valid blackout, the maximum being taken over all `2 ^ (n * k)` subsets of the grid + (the empty blackout is always valid). For speed in the kernel, the list recursions in + `notMem` and `pairwiseDistinct` are written with `List.rec`, the bit operations with + `Nat.land`/`Nat.xor`/`Nat.beq`, and `card` counts bits by halving; they compute exactly what + their docstrings say. +* `a` is the table flattened by antidiagonals as in the entry (`n + k = 4, 5, 6, …`, and within an + antidiagonal `n = 2, 3, …`, `k = (n + k) - n`, which is the order of the entry's Python program), + indexed from the entry's offset `2`: `a 2 = T 2 2`, `a 3 = T 2 3`, `a 4 = T 3 2`, …. + (`a 0 = a 1 = 0` are junk values.) The table is symmetric, `T n k = T k n`, by transposition. +* Reading of the conjecture: for all `n, m` with `min(n, m) ≥ 4`, `T(n, m) = n + m`, except + `T(4,4) = 7` and `T(4,5) = 8`. Since the table is symmetric (and the entry's data list + `T(5,4) = 8`), the exception `T(4,5) = 8` is read as covering both cells `(4,5)` and `(5,4)`; + reading it as covering `(4,5)` alone would make the conjecture contradict the entry's own data + at `(5,4)`. The two exceptional values are part of the statement. +* Kernel check: the first 10 terms (antidiagonals `n + k ≤ 7`, grids of at most 12 points) are + checked, each value `T n k` by its own `decide +kernel` (one joint `decide` over all ten runs + out of memory), and `a_data` assembles them. These ten checks take about a minute; the two + 12-point grids `3 × 4` and `4 × 3` (4096 subsets each) dominate. The next term needs another + 12-point grid and the terms after it grids of 15 or more points (`2 ^ 15` or more subsets), + which is beyond the kernel in that budget. (A Python transcription of the same encoding + reproduces the first 15 listed terms.) +-/ + +namespace Math0.Statements.A397315 + +/-- The coordinates `(x, y) = (i / n, i % n)` of the point with index `i` of the `n × k` grid +`{0, …, k-1} × {0, …, n-1}`; the indices `0, …, n * k - 1` enumerate the grid. -/ +def pt (n i : ℕ) : ℤ × ℤ := (((i / n : ℕ) : ℤ), ((i % n : ℕ) : ℤ)) + +/-- Whether an integer point lies in the grid `{0, …, k-1} × {0, …, n-1}`. -/ +def inGrid (n k : ℕ) (p : ℤ × ℤ) : Bool := + decide (0 ≤ p.1) && decide (p.1 < k) && decide (0 ≤ p.2) && decide (p.2 < n) + +/-- The index `x * n + y` of a grid point `(x, y)` (the inverse of `pt n` on the grid). -/ +def idx (n : ℕ) (p : ℤ × ℤ) : ℕ := p.1.toNat * n + p.2.toNat + +/-- For grid point indices `a, b, c`: if `a, b, c` are pairwise distinct, the angle at `b` is right +(`(a - b) · (c - b) = 0`) and the fourth vertex `d = a + c - b` lies in the grid, the vertex set +`{a, b, c, d}` of this rectangle as a bitmask; otherwise `none`. -/ +def rectMask? (n k a b c : ℕ) : Option ℕ := + let A := pt n a + let B := pt n b + let C := pt n c + let D := A + C - B + if a ≠ b ∧ b ≠ c ∧ a ≠ c ∧ (A.1 - B.1) * (C.1 - B.1) + (A.2 - B.2) * (C.2 - B.2) = 0 ∧ + inGrid n k D = true then + some (2 ^ a ||| 2 ^ b ||| 2 ^ c ||| 2 ^ idx n D) + else none + +/-- The vertex sets (as bitmasks) of all rectangles, tilted ones included, with all four vertices +in the `n × k` grid, each listed once. -/ +def rects (n k : ℕ) : List ℕ := + ((List.range (n * k)).flatMap fun a => (List.range (n * k)).flatMap fun b => + (List.range (n * k)).filterMap fun c => rectMask? n k a b c).eraseDups + +/-- The visible part `R \ B` of a vertex set `R` when the points of `B` are blacked out +(bitmasks: clear in `R` the bits of `B`). -/ +def visible (R B : ℕ) : ℕ := Nat.xor R (Nat.land R B) + +/-- `true` iff `x` does not occur in `l`. -/ +def notMem (x : ℕ) (l : List ℕ) : Bool := l.rec true fun y _ ih => !(Nat.beq x y) && ih + +/-- `true` iff the entries of `l` are pairwise distinct (i.e. `l.Nodup`). -/ +def pairwiseDistinct (l : List ℕ) : Bool := l.rec true fun x xs ih => notMem x xs && ih + +/-- `B` (a set of grid points, as a bitmask) is a valid blackout of the `n × k` grid: distinct +rectangles have distinct visible parts, i.e. `R ↦ R \ B` is injective on the rectangles. -/ +def isValidBlackout (n k B : ℕ) : Bool := pairwiseDistinct ((rects n k).map (visible · B)) + +/-- `card len B` is the number of points with index `< len` in the set `B` (a bitmask), i.e. the +number of 1 bits among the lowest `len` binary digits of `B`. -/ +def card : ℕ → ℕ → ℕ + | 0, _ => 0 + | len + 1, B => B % 2 + card len (B / 2) + +/-- A397315 as a table: `T n k` is the maximum number of points that can be blacked out of the +`n × k` grid so that every rectangle with all four vertices on grid points (tilted rectangles +included) is uniquely identifiable from its set of visible vertices. The maximum runs over all +subsets `B` of the grid, i.e. all bitmasks `B < 2 ^ (n * k)`. -/ +def T (n k : ℕ) : ℕ := + ((List.range (2 ^ (n * k))).filter (isValidBlackout n k)).foldr + (fun B m => max (card (n * k) B) m) 0 + +/-- The `j`-th cell `(n, k)` (`j ≥ 0`) of the table in the entry's reading order: by antidiagonals +`n + k = 4, 5, 6, …`, and within an antidiagonal by increasing `n`. (The list below has +`(j + 1)(j + 2)/2 > j` entries, so the default value is never used.) -/ +def cell (j : ℕ) : ℕ × ℕ := + ((List.range (j + 1)).flatMap fun d => + (List.range (d + 1)).map fun i => (2 + i, 2 + d - i)).getD j (0, 0) + +/-- A397315 as a sequence, with the entry's offset `2`: `a i = T n k` for the `(i - 2)`-th cell +`(n, k)` in the antidiagonal reading order (`a 0 = a 1 = 0` are junk values). -/ +def a (i : ℕ) : ℕ := if i < 2 then 0 else T (cell (i - 2)).1 (cell (i - 2)).2 + +/-- The reading order of the cells: `(2,2), (2,3), (3,2), (2,4), (3,3), (4,2), …`. -/ +theorem cell_data : (List.range 15).map cell = + [(2, 2), (2, 3), (3, 2), (2, 4), (3, 3), (4, 2), (2, 5), (3, 4), (4, 3), (5, 2), + (2, 6), (3, 5), (4, 4), (5, 3), (6, 2)] := by + decide +kernel + +/-- `a (j + 2)` is the value of `T` at the `j`-th cell. -/ +theorem a_add_two (j : ℕ) : a (j + 2) = T (cell j).1 (cell j).2 := by + simp [a] + +/-! The values of `T` on the first 10 cells, each checked by the kernel separately. -/ + +theorem T_2_2 : T 2 2 = 4 := by decide +kernel +theorem T_2_3 : T 2 3 = 4 := by decide +kernel +theorem T_3_2 : T 3 2 = 4 := by decide +kernel +theorem T_2_4 : T 2 4 = 5 := by decide +kernel +theorem T_3_3 : T 3 3 = 5 := by decide +kernel +theorem T_4_2 : T 4 2 = 5 := by decide +kernel +set_option maxRecDepth 100000 in +theorem T_2_5 : T 2 5 = 6 := by decide +kernel +set_option maxRecDepth 100000 in +theorem T_3_4 : T 3 4 = 6 := by decide +kernel +set_option maxRecDepth 100000 in +theorem T_4_3 : T 4 3 = 6 := by decide +kernel +set_option maxRecDepth 100000 in +theorem T_5_2 : T 5 2 = 6 := by decide +kernel + +/-- The definition reproduces the first 10 terms listed in OEIS (each value of `T` kernel-checked +by `decide +kernel` above; the cells by `cell_data`). -/ +theorem a_data : (List.range 10).map (fun i => a (i + 2)) = [4, 4, 4, 5, 5, 5, 6, 6, 6, 6] := by + have hcell : (List.range 10).map cell = + [(2, 2), (2, 3), (3, 2), (2, 4), (3, 3), (4, 2), (2, 5), (3, 4), (4, 3), (5, 2)] := by + decide +kernel + rw [List.map_congr_left (fun j _ => a_add_two j), + show (fun j => T (cell j).1 (cell j).2) = (fun c : ℕ × ℕ => T c.1 c.2) ∘ cell from rfl, + ← List.map_map, hcell] + simp only [List.map_cons, List.map_nil, T_2_2, T_2_3, T_3_2, T_2_4, T_3_3, T_4_2, T_2_5, + T_3_4, T_4_3, T_5_2] + +/-- Conjecture (Pemmasani, A397315): `T(n, m) = n + m` whenever `min(n, m) ≥ 4`, except +`T(4,4) = 7` and `T(4,5) = 8` (with `T(5,4) = T(4,5) = 8` by symmetry). -/ +def statement : Prop := + ∀ n m : ℕ, 4 ≤ min n m → + T n m = if n = 4 ∧ m = 4 then 7 + else if (n = 4 ∧ m = 5) ∨ (n = 5 ∧ m = 4) then 8 + else n + m + +end Math0.Statements.A397315 diff --git a/lean/lake-manifest.json b/lean/lake-manifest.json new file mode 100644 index 0000000..fbe9345 --- /dev/null +++ b/lean/lake-manifest.json @@ -0,0 +1,106 @@ +{"version": "1.2.0", + "packagesDir": ".lake/packages", + "packages": + [{"url": "https://github.com/leanprover-community/mathlib4", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "0df444a360eaa60ab8c11dca51a86af692955474", + "name": "mathlib", + "manifestFile": "lake-manifest.json", + "inputRev": "v4.33.1", + "inherited": false, + "configFile": "lakefile.lean"}, + {"url": "https://github.com/google-deepmind/formal-conjectures", + "type": "git", + "subDir": null, + "scope": "", + "rev": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "name": "formal_conjectures", + "manifestFile": "lake-manifest.json", + "inputRev": "c77fdd446d23539302aa73bcfae4a9fa962b8382", + "inherited": false, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/plausible", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "b7eb3304aeae834b12dda98993a37f6a41f6f0bb", + "name": "plausible", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/LeanSearchClient", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "5f4d51b81cbd3f6b32b156bfad9056621a040404", + "name": "LeanSearchClient", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/import-graph", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "16f02aa7642864af59f1ff0e384a015994db9118", + "name": "importGraph", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/ProofWidgets4", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "4be2e3d5087eeb272cf5a8853b8f9dd025ef5957", + "name": "proofwidgets", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.lean"}, + {"url": "https://github.com/leanprover-community/aesop", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "3448c0bcc5ce01b2d1546e483ec3620e32df3d0e", + "name": "aesop", + "manifestFile": "lake-manifest.json", + "inputRev": "master", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/quote4", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "92c15be17b7caf78c2ad767ec40f89052d908d81", + "name": "Qq", + "manifestFile": "lake-manifest.json", + "inputRev": "master", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover-community/batteries", + "type": "git", + "subDir": null, + "scope": "leanprover-community", + "rev": "4488d40d070b9700d4d5a6aa342f0d40c31b2a2d", + "name": "batteries", + "manifestFile": "lake-manifest.json", + "inputRev": "main", + "inherited": true, + "configFile": "lakefile.toml"}, + {"url": "https://github.com/leanprover/lean4-cli", + "type": "git", + "subDir": null, + "scope": "leanprover", + "rev": "6130a47896ce867c6a4a55373441e59e565bad0f", + "name": "Cli", + "manifestFile": "lake-manifest.json", + "inputRev": "v4.33.0", + "inherited": true, + "configFile": "lakefile.toml"}], + "name": "math0", + "lakeDir": ".lake", + "fixedToolchain": false} diff --git a/lean/lakefile.toml b/lean/lakefile.toml new file mode 100644 index 0000000..6b38429 --- /dev/null +++ b/lean/lakefile.toml @@ -0,0 +1,23 @@ +name = "math0" +version = "0.1.0" +defaultTargets = ["Math0"] + +[leanOptions] +pp.unicode.fun = true +autoImplicit = false +relaxedAutoImplicit = false + +# Third-party statements of open problems. Pinned so that every statement we +# prove is exactly the one published upstream at this commit. +[[require]] +name = "formal_conjectures" +git = "https://github.com/google-deepmind/formal-conjectures" +rev = "c77fdd446d23539302aa73bcfae4a9fa962b8382" + +[[require]] +name = "mathlib" +scope = "leanprover-community" +rev = "v4.33.1" + +[[lean_lib]] +name = "Math0" diff --git a/lean/lean-toolchain b/lean/lean-toolchain new file mode 100644 index 0000000..a8afa7d --- /dev/null +++ b/lean/lean-toolchain @@ -0,0 +1 @@ +leanprover/lean4:v4.33.1 diff --git a/results/arxiv-0805-3777-ismaxrank-le-two-mul-isgenericrank/README.md b/results/arxiv-0805-3777-ismaxrank-le-two-mul-isgenericrank/README.md new file mode 100644 index 0000000..544233f --- /dev/null +++ b/results/arxiv-0805-3777-ismaxrank-le-two-mul-isgenericrank/README.md @@ -0,0 +1,30 @@ +# Maximal tensor rank is at most twice the generic rank (Blekherman–Teitler) + +**Classification:** First formal proof of a known result +**Area:** Algebraic geometry, Linear algebra +**Source problem:** arXiv:0805.3777 +**Date:** 2026-10-17 + +## Result + +Let ds be any list of dimensions, and consider complex tensors (Holor ℂ ds) with the product topology on HolorIndex ds → ℂ. Suppose r is a generic rank: there is an open dense set U of tensors, all of CP rank exactly r. Suppose R is the maximal rank: R is the largest CP rank of any tensor of format ds. Then R ≤ 2r. This is [BT15, Theorem 1] (Blekherman–Teitler), as formalized in formal-conjectures (FormalConjectures/Arxiv/0805.3777/TensorRank.lean). + +## Verification + +The Lean file [`lean/Math0/Arxiv/Arxiv_0805_3777_isMaxRank_le_two_mul_isGenericRank.lean`](../../lean/Math0/Arxiv/Arxiv_0805_3777_isMaxRank_le_two_mul_isGenericRank.lean) proves the upstream statement [`Arxiv.«0805.3777».isMaxRank_le_two_mul_isGenericRank`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/0805.3777/TensorRank.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +The source is G. Blekherman and Z. Teitler, "On maximum, typical and generic ranks", Math. Ann. 362 (2015), 1021–1031, doi:10.1007/s00208-014-1150-3, arXiv:1402.2371, Theorem 1. It states that the maximum rank is at most twice the generic rank for any nondegenerate irreducible variety. The case here is the Segre variety, i.e. tensors. The upstream file is FormalConjectures/Arxiv/0805.3777/TensorRank.lean, which builds on Friedland, LAA 436 (2012), arXiv:0805.3777. It has no formal_proof link for this item, and I know of no earlier Lean proof. + +## Citation + +```bibtex +@misc{math0:arxiv-0805-3777-ismaxrank-le-two-mul-isgenericrank, + author = {{math0}}, + title = {{Maximal tensor rank is at most twice the generic rank (Blekherman–Teitler)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/arxiv-0805-3777-ismaxrank-le-two-mul-isgenericrank}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/arxiv-1609-08688-maximallength-ge-of-issquare/README.md b/results/arxiv-1609-08688-maximallength-ge-of-issquare/README.md new file mode 100644 index 0000000..6c5349a --- /dev/null +++ b/results/arxiv-1609-08688-maximallength-ge-of-issquare/README.md @@ -0,0 +1,30 @@ +# Gowers–Long lower bound: F(k²) ≥ k³ for 2-increasing sequences of triples + +**Classification:** First formal proof of a known result +**Area:** Combinatorics +**Source problem:** arXiv:1609.08688 +**Date:** 2026-10-17 + +## Result + +Say that a triple a = (a_1,a_2,a_3) is 2-less than b = (b_1,b_2,b_3) if a_i < b_i for at least two coordinates i. A finite sequence of triples is 2-increasing if every earlier term is 2-less than every later term. Let F(n) be the largest length of a 2-increasing sequence of triples with all coordinates in {1,...,n}. (Formally, F(n) is the sSup in ℕ of the set of such lengths.) If n is a perfect square then (√n)^3 ≤ F(n), i.e. F(k^2) ≥ k^3 for every natural number k. + +## Verification + +The Lean file [`lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_ge_of_isSquare.lean`](../../lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_ge_of_isSquare.lean) proves the upstream statement [`Arxiv.«1609.08688».maximalLength_ge_of_isSquare`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/1609.08688/sIncreasingrTuples.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +The source is W. T. Gowers and J. Long, "The length of an s-increasing sequence of r-tuples", arXiv:1609.08688, published in Combinatorics, Probability and Computing 30 (2021), 686–721. Proposition 1.4 states F(n) ≤ n^2 for all n, and F(n) ≥ n^{3/2} when n is a perfect square, using the lexicographic construction of triples ((a,b),(a,c),(b,c)). The result is known and elementary. In formal-conjectures, both the pinned checkout and the latest upstream HEAD (d9ce556, 2026-10-17) still leave `maximalLength_ge_of_isSquare` as `sorry`. The upper bound `maximalLength_le` is already proved upstream. I found no existing Lean proof of the lower bound. + +## Citation + +```bibtex +@misc{math0:arxiv-1609-08688-maximallength-ge-of-issquare, + author = {{math0}}, + title = {{Gowers–Long lower bound: F(k²) ≥ k³ for 2-increasing sequences of triples}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/arxiv-1609-08688-maximallength-ge-of-issquare}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/arxiv-1609-08688-maximallength-pow/README.md b/results/arxiv-1609-08688-maximallength-pow/README.md new file mode 100644 index 0000000..0ce9992 --- /dev/null +++ b/results/arxiv-1609-08688-maximallength-pow/README.md @@ -0,0 +1,30 @@ +# Supermultiplicativity of F gives arbitrarily large m with F(m) ≥ m^α (Gowers–Long) + +**Classification:** First formal proof of a known result +**Area:** Combinatorics +**Source problem:** arXiv:1609.08688 +**Date:** 2026-10-17 + +## Result + +Let F(n) be the largest length of a sequence of triples in {1,…,n}^3 that is 2-increasing: every earlier triple is strictly smaller than every later one in at least two of the three coordinates. Let n > 1 be a natural number and e a real number with F(n) = n^e. Then (m : ℝ)^e ≤ F(m) for arbitrarily large natural numbers m, i.e. ∃ᶠ m in atTop. + +## Verification + +The Lean file [`lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_pow.lean`](../../lean/Math0/Arxiv/Arxiv_1609_08688_maximalLength_pow.lean) proves the upstream statement [`Arxiv.«1609.08688».maximalLength_pow`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/1609.08688/sIncreasingrTuples.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +W. T. Gowers and J. Long, "The length of an s-increasing sequence of r-tuples", arXiv:1609.08688; Combinatorics, Probability and Computing 30 (2021), 686–721. Section 1 notes that F is supermultiplicative, F(mn) ≥ F(m)F(n), using the lexicographic product of sequences. So F(n) = n^α implies F(n^k) ≥ n^{αk}, which gives arbitrarily large m with F(m) ≥ m^α. This is the upstream statement `maximalLength_pow`, which is tagged "research solved" and was proved upstream only by sorry. I found no existing Lean formalization. + +## Citation + +```bibtex +@misc{math0:arxiv-1609-08688-maximallength-pow, + author = {{math0}}, + title = {{Supermultiplicativity of F gives arbitrarily large m with F(m) ≥ m^α (Gowers–Long)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/arxiv-1609-08688-maximallength-pow}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/arxiv-2602-05192-four-2/README.md b/results/arxiv-2602-05192-four-2/README.md new file mode 100644 index 0000000..7ae2de2 --- /dev/null +++ b/results/arxiv-2602-05192-four-2/README.md @@ -0,0 +1,30 @@ +# Finite free Stam inequality in degree 2 (First Proof, Problem 4, n = 2): it holds with equality + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Real analysis +**Source problem:** arXiv:2602.05192 +**Date:** 2026-10-17 + +## Result + +Let p and q be monic real polynomials of degree 2, each having 2 real roots counted with multiplicity. Let p ⊞_2 q be their finite additive convolution, Σ_{k=0}^{2} c_k x^{2-k} with c_k = Σ_{i+j=k} (2-i)!(2-j)!/(2!(2-k)!) a_i b_j, where a_i and b_j are the coefficients of x^{2-i} in p and x^{2-j} in q. For a monic polynomial with simple roots λ_1,…,λ_n, set Φ_n(p) = Σ_i (Σ_{j≠i} 1/(λ_i-λ_j))^2, and set Φ_n(p) = ∞ when p has a repeated root. Then, in [0,∞], 1/Φ_2(p) + 1/Φ_2(q) ≤ 1/Φ_2(p ⊞_2 q). In fact equality always holds. + +## Verification + +The Lean file [`lean/Math0/Arxiv/Arxiv_2602_05192_four_2.lean`](../../lean/Math0/Arxiv/Arxiv_2602_05192_four_2.lean) proves the upstream statement [`Arxiv.«2602.05192».four_2`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/2602.05192/FirstProof4.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +The problem is First Proof (Abouzaid, Blumberg, Hairer, Kileel, Kolda, Nelson, Spielman, Srivastava, Ward, Weinberger, Williams), arXiv:2602.05192v2, Problem 4: the finite free Stam / harmonic-mean inequality for ⊞_n. ⊞_n is the finite free additive convolution of Marcus–Spielman–Srivastava ("Finite free convolutions of polynomials"; "Interlacing families II"). The general statement was answered affirmatively by the First Proof solutions. It was formalized in Lean 4 by FrenzyMath's Archon in the repository frenzymath/Archon-FirstProof-Results, file FirstProof/FirstProof4/Problem4.lean, theorem harmonic_mean_inequality_full, for all n ≥ 2 with zero sorrys according to its README. Upstream links that file as `formal_proof` on `four`. The n = 2 case is an elementary identity: ⊞_2 adds discriminants (second cumulants), so equality holds. + +## Citation + +```bibtex +@misc{math0:arxiv-2602-05192-four-2, + author = {{math0}}, + title = {{Finite free Stam inequality in degree 2 (First Proof, Problem 4, n = 2): it holds with equality}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/arxiv-2602-05192-four-2}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/arxiv-2605-12342-conjecture-1-variants-rank-3-3/README.md b/results/arxiv-2605-12342-conjecture-1-variants-rank-3-3/README.md new file mode 100644 index 0000000..8291cd8 --- /dev/null +++ b/results/arxiv-2605-12342-conjecture-1-variants-rank-3-3/README.md @@ -0,0 +1,30 @@ +# Γ_{3⊕3} (equal-sign pairs in S₃ × S₃) is not 2-generated + +**Classification:** First formal proof of a known result +**Area:** Group theory +**Source problem:** arXiv:2605.12342 +**Date:** 2026-10-17 + +## Result + +Let Γ = Γ_{3⊕3} = {(σ₁, σ₂) ∈ S₃ × S₃ : sgn σ₁ = sgn σ₂}. In the formal statement Γ is the kernel of (σ₁,σ₂) ↦ sgn σ₁ · sgn σ₂⁻¹. For all h₁, h₂ ∈ Γ, the subgroup of Γ generated by {h₁, h₂} is not all of Γ. So Γ is not 2-generated, which is the rank-3 claim Fernandes records in arXiv:2605.12342. + +## Verification + +The Lean file [`lean/Math0/Arxiv/Arxiv_2605_12342_conjecture_1_variants_rank_3_3.lean`](../../lean/Math0/Arxiv/Arxiv_2605_12342_conjecture_1_variants_rank_3_3.lean) proves the upstream statement [`Arxiv.«2605.12342».conjecture_1.variants.rank_3_3`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/2605.12342/Conjecture1.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +V. H. Fernandes, "Groups of permutations that are even on maximal proper subsets, and related monoids", arXiv:2605.12342 (2026). It states, as a GAP computation, that Γ3⊕3, Γ4⊕3 and Γ4⊕4 are not 2-generated, so rank(Γ3⊕3) = 3, and gives Conjecture 1 for all other (m, n). It also follows from elementary group theory: Γ3⊕3 is the generalized dihedral group Dih(C3×C3), and any 2-generated subgroup of it has order at most 9. Existing Lean work: K. Kitamura, github.com/KitaKen1/fernandes-conjecture-1-lean, proves only the main conjecture_1 (the non-exceptional cases are 2-generated), not the rank-3 exceptions. Upstream formal-conjectures main (checked 2026-10-17) still has `sorry` for conjecture_1.variants.rank_3_3. + +## Citation + +```bibtex +@misc{math0:arxiv-2605-12342-conjecture-1-variants-rank-3-3, + author = {{math0}}, + title = {{Γ_{3⊕3} (equal-sign pairs in S₃ × S₃) is not 2-generated}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/arxiv-2605-12342-conjecture-1-variants-rank-3-3}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/arxiv-math-0608009-poisson-conjecture-variants-dimension-three/README.md b/results/arxiv-math-0608009-poisson-conjecture-variants-dimension-three/README.md new file mode 100644 index 0000000..fc7a30d --- /dev/null +++ b/results/arxiv-math-0608009-poisson-conjecture-variants-dimension-three/README.md @@ -0,0 +1,30 @@ +# The Poisson conjecture fails in dimension three + +**Classification:** First formal proof of a known result +**Area:** Algebraic geometry, Nonassociative algebra +**Source problem:** arXiv:math.0608009 +**Date:** 2026-10-17 + +## Result + +Let K be a field of characteristic zero and P_3(K) = K[x_1,x_2,x_3,y_1,y_2,y_3] with the canonical Poisson bracket {f,g} = sum_i (d_{x_i} f d_{y_i} g - d_{y_i} f d_{x_i} g). Then some K-algebra endomorphism phi of P_3(K) is not bijective even though it preserves the bracket on generators ({phi(v), phi(w)} = {v, w} for all variables v, w). So PC_3 (every Poisson endomorphism of P_3(K) is an automorphism) is false. Formally: for every field K with CharZero K, ¬ PoissonConjectureFor K 3. + +## Verification + +The Lean file [`lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_dimension_three.lean`](../../lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_dimension_three.lean) proves the upstream statement [`Arxiv.«math.0608009».poisson_conjecture.variants.dimension_three`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/math.0608009/PoissonConjecture.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +[AvdE07] K. Adjamagbo and A. van den Essen, arXiv:math/0608009, Acta Math. Vietnam. 32 (2007): defines PC_n (Notations 5), Lemma 2 (preserving brackets on generators suffices), and Theorem 7 (JC_{2n} ⇒ PC_n ⇒ DC_n ⇒ JC_n). [Alp26] L. Alpöge (2026): counterexample to the Jacobian conjecture in dimension 3. The upstream formal-conjectures file FormalConjectures/Wikipedia/JacobianConjecture.lean formalizes a variant G with Jacobian determinant 1 that is not injective (det_jacobian_G, aeval_G_eq). Upstream FormalConjectures/Arxiv/math.0608009/PoissonConjecture.lean marks dimension_three as "research solved" with a sorry proof, no formal_proof link, and a docstring describing exactly this cotangent-lift argument. [Lon26] C. D. Long, arXiv:2608.23777, settles PC_2 and is not relevant to n=3. + +## Citation + +```bibtex +@misc{math0:arxiv-math-0608009-poisson-conjecture-variants-dimension-three, + author = {{math0}}, + title = {{The Poisson conjecture fails in dimension three}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/arxiv-math-0608009-poisson-conjecture-variants-dimension-three}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/arxiv-math-0608009-poisson-conjecture-variants-jacobian-implication/README.md b/results/arxiv-math-0608009-poisson-conjecture-variants-jacobian-implication/README.md new file mode 100644 index 0000000..5251a4d --- /dev/null +++ b/results/arxiv-math-0608009-poisson-conjecture-variants-jacobian-implication/README.md @@ -0,0 +1,30 @@ +# The Jacobian conjecture in dimension 2n implies the Poisson conjecture in dimension n + +**Classification:** First formal proof of a known result +**Area:** Algebraic geometry, Nonassociative algebra +**Source problem:** arXiv:math.0608009 +**Date:** 2026-10-17 + +## Result + +Let K be a field of characteristic zero and n a natural number. Suppose the Jacobian conjecture holds in 2n variables over K: every polynomial map F : K^{2n} -> K^{2n} whose Jacobian determinant is a unit of K[x_1,...,x_{2n}] has a polynomial two-sided compositional inverse. Then every K-algebra endomorphism phi of K[x_1..x_n, y_1..y_n] that preserves the canonical Poisson bracket {f,g} = sum_i (d_{x_i} f d_{y_i} g - d_{y_i} f d_{x_i} g) on the generators, i.e. {phi(X_v), phi(X_w)} = {X_v, X_w} for all v, w, is bijective. (Adjamagbo and van den Essen, arXiv math/0608009, Theorems 1 and 7.) + +## Verification + +The Lean file [`lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_jacobian_implication.lean`](../../lean/Math0/Arxiv/Arxiv_math_0608009_poisson_conjecture_variants_jacobian_implication.lean) proves the upstream statement [`Arxiv.«math.0608009».poisson_conjecture.variants.jacobian_implication`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Arxiv/math.0608009/PoissonConjecture.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +K. Adjamagbo and A. van den Essen, "On the equivalence of the Jacobian, Dixmier and Poisson conjectures in any characteristic", arXiv math/0608009, published as "A proof of the equivalence of the Dixmier, Jacobian and Poisson conjectures", Acta Math. Vietnam. 32 (2007) 205-214. Theorem 1 / Theorem 7 there state JC_{2n} ⇒ PC_n ⇒ DC_n ⇒ JC_n; JC_{2n} ⇒ PC_n is the step proved here. Related: Bass-Connell-Wright 1982 (DC_n ⇒ JC_n); Tsuchimoto and Belov-Kanel-Kontsevich (JC_{2n} ⇒ DC_n). Upstream records JC as false in dimension 3 (Alpöge 2026) and PC_2 as false (Long 2026), so the hypothesis here is false for n ≥ 2 and the case that still matters, JC_2 ⇒ PC_1, is nontrivial. Upstream has no formal_proof link for this item. + +## Citation + +```bibtex +@misc{math0:arxiv-math-0608009-poisson-conjecture-variants-jacobian-implication, + author = {{math0}}, + title = {{The Jacobian conjecture in dimension 2n implies the Poisson conjecture in dimension n}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/arxiv-math-0608009-poisson-conjecture-variants-jacobian-implication}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/bugeaud06-problem-10-6-variant-1/README.md b/results/bugeaud06-problem-10-6-variant-1/README.md new file mode 100644 index 0000000..cda75f8 --- /dev/null +++ b/results/bugeaud06-problem-10-6-variant-1/README.md @@ -0,0 +1,44 @@ +# A sequence with ratio floor 1 + c/log n that is dense mod 1 for every irrational (Bugeaud 10.6, ratio reading) + +**Classification:** Misformalization found (upstream statement does not match the problem) +**Area:** Number theory +**Source problem:** Books / BugeaudDistributionModuloOne / Problem10_6 +**Date:** 2026-10-17 + +## Result + +There is a strictly increasing sequence m : ℕ → ℕ with two properties. First, it is "genuinely sublacunary": for some c > 0, m(n+1)/m(n) ≥ 1 + c/log n for all sufficiently large n. Second, for every irrational ξ, the points ξ·m(n) mod 1 are dense in ℝ/ℤ. + +## Verification + +The Lean file [`lean/Math0/Books/Bugeaud06_problem_10_6_variant_1.lean`](../../lean/Math0/Books/Bugeaud06_problem_10_6_variant_1.lean) proves the upstream statement [`Bugeaud06.problem_10_6_variant_1`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_6.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research open`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +- **Ajtai, Havas, Komlós (1983):** M. Ajtai, I. Havas and J. Komlós, "Every group admits a bad topology", in Studies in Pure Mathematics (to the memory of P. Turán), Birkhäuser, Basel, 1983, pp. 21–34. For any ε_n → 0+ there are integers m_n with m_{n+1}/m_n > 1 + ε_n such that (ξ m_n) is uniformly distributed mod 1 for every irrational ξ. This implies `problem_10_6_variant_1`. +- **Bugeaud (2012):** Y. Bugeaud, Distribution Modulo One and Diophantine Approximation, Cambridge Tracts in Mathematics 193. + - The Chapter 2 notes (p. 45) cite the AHK result above. + - Problem 10.6 is on p. 215; it was checked against the text of the book. +- **Boshernitzan (1983):** M. D. Boshernitzan, Monatsh. Math. 96 (1983), 173–181. Bugeaud cites it as "see also [121]" for the AHK result. +- **Formal Lean proofs:** none found, either in formal_conjectures or as a formal_proof link. Upstream has `formal_proof` links only for the growth and sparsity variants (rwst fork, commit 63c3e72). - Y. Bugeaud, Distribution Modulo One and Diophantine Approximation, Cambridge Tracts in Math. 193 (2012): + - Problem 10.6 is on p. 215, after the remarks on Furstenberg's 2^n 3^m and on Pollington and de Mathan. + - §2.8 Notes, p. 45, states the Ajtai–Havas–Komlós theorem: for any ε_n → 0 there is an integer sequence with m_{n+1}/m_n > 1 + ε_n that is u.d. mod 1 for every irrational ξ ("see also [121]"). + - PDF used: https://staff.dc.uba.ar/becher/aa/Bugeaud2012.pdf + +(Abridged; the manuscript discusses the literature in full.) + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:bugeaud06-problem-10-6-variant-1, + author = {{math0}}, + title = {{A sequence with ratio floor 1 + c/log n that is dense mod 1 for every irrational (Bugeaud 10.6, ratio reading)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/bugeaud06-problem-10-6-variant-1}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/bugeaud06-problem-10-6-variant-1/paper.pdf b/results/bugeaud06-problem-10-6-variant-1/paper.pdf new file mode 100644 index 0000000..31e9149 Binary files /dev/null and b/results/bugeaud06-problem-10-6-variant-1/paper.pdf differ diff --git a/results/bugeaud06-problem-10-6-variant-1/paper.tex b/results/bugeaud06-problem-10-6-variant-1/paper.tex new file mode 100644 index 0000000..a7a08bb --- /dev/null +++ b/results/bugeaud06-problem-10-6-variant-1/paper.tex @@ -0,0 +1,387 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8} +% Unicode inside listings (pdfLaTeX listings cannot read multibyte characters directly). +\lstset{keepspaces=true, literate={ξ}{{$\xi$}}1 {ε}{{$\varepsilon$}}1 {ᶠ}{{$^{\mathrm{f}}$}}1 + {↑}{{$\uparrow$}}1 {ℕ}{{$\mathbb{N}$}}1 {ℝ}{{$\mathbb{R}$}}1 {→}{{$\to$}}1 {∀}{{$\forall$}}1 + {∃}{{$\exists$}}1 {∧}{{$\wedge$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {⟨}{{$\langle$}}1 + {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1 {∈}{{$\in$}}1 {∨}{{$\vee$}}1 {–}{{-}}1 {ó}{{\'o}}1 {§}{{\S}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{ξ}{\ensuremath{\xi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\R}{\mathbb{R}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\frc}{\operatorname{frac}} + +\title[Ratio floor $1+c/\log n$ and density modulo one]{A sequence with consecutive ratios at least $1+c/\log n$ whose irrational dilates are dense modulo one, and the status of a formal statement of Bugeaud's Problem 10.6} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 17, 2026} + +\begin{document} +\begin{abstract} +We construct a strictly increasing sequence $(m_n)_{n\ge0}$ of positive integers with $m_{n+1}/m_n\ge 1+1/(8\log n)$ for every $n\ge2$ such that $(\xi m_n)_{n\ge0}$ is dense modulo one for every irrational $\xi$. +This proves the statement \decl{Bugeaud06.problem_10_6_variant_1} of the formal-conjectures repository, which reads Bugeaud's Problem~10.6 (``to find a very rapidly increasing sequence'' with this density property) as a ratio floor $1+c/\log n$ and labels it as an open research problem. +The statement is, however, a special case of a 1983 theorem of Ajtai, Havas and Koml\'os that Bugeaud records in the same book, so it does not express the open problem; this is a misformalization report, not progress on Problem~10.6, and we propose a corrected labelling and an accompanying solved statement. +Our proof is elementary and self-contained and gives density only, not uniform distribution; it is verified in Lean~4 against the upstream formal-conjectures statement. +\end{abstract} +\maketitle + +\section{Introduction}\label{sec:intro} + +For a sequence $(m_n)$ of positive integers and $\xi\in\R$ one asks whether the fractional parts of $\xi m_n$ are dense in $[0,1)$, that is, whether the image of $(\xi m_n)$ in $\R/\Z$ is dense. +For lacunary sequences ($m_{n+1}/m_n\ge\lambda>1$ for all $n$) the answer is negative for some irrational $\xi$: answering a question of Erd\H{o}s, Pollington \cite{Pol79} and de Mathan \cite{Mat80} showed that such $\xi$ always exist, and indeed there are uncountably many of them \cite[pp.~29 and~215]{Bug12}. +On the other hand, Furstenberg \cite{Fur67} proved that $(\xi\,2^a3^b)_{a,b\ge1}$ is dense modulo one for every irrational $\xi$. +Between these two facts Bugeaud poses the following problem \cite[Problem~10.6, p.~215]{Bug12}: +\begin{quote} +\emph{To find a very rapidly increasing sequence $(m_n)_{n\ge1}$ of positive integers such that $(\xi m_n)_{n\ge1}$ is dense modulo one for every irrational number $\xi$.} +\end{quote} + +\subsection*{A known theorem} +In the notes to Chapter~2 of the same book \cite[\S2.8, p.~45]{Bug12}, Bugeaud records that ``Ajtai, Havas and Koml\'os [26] showed that, for any given sequence $(\varepsilon_n)_{n\ge1}$ of positive real numbers tending to $0$, there exists a sequence $(m_n)_{n\ge1}$ of positive integers such that $m_{n+1}/m_n>1+\varepsilon_n$ for $n\ge1$ and the sequence $(\xi m_n)_{n\ge1}$ is uniformly distributed modulo one for every irrational number $\xi$; see also [121]'', where [26] and [121] are \cite{AHK83} and \cite{Bos83}. +We rely on this statement of the theorem of \cite{AHK83} as recorded by Bugeaud. +Gao, Mooroogen and Yip \cite[Example~2.4(d)]{GMY} describe the same result in the form: if $(b_n)$ has sub-exponential growth and $d_n\to\infty$, there is $(a_n)$ with $b_n\le a_n\le b_n+d_n$ such that $(xa_n)$ is uniformly distributed modulo one for every real $x\ne0$. + +\subsection*{The formal statement} +The formal-conjectures repository \cite{FC} formalizes Problem~10.6 in \path{FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_6.lean}. +Its module docstring lists three readings of ``very rapidly increasing'' (a lower bound on the terms, an upper bound on the counting function, a lower bound on the ratios), records that the first two are not open, and states that the third, the ratio floor $m_{n+1}/m_n\ge1+c/\log n$, ``remains open''. +That reading is \decl{Bugeaud06.problem_10_6_variant_1}, tagged \texttt{research open}. +With $\varepsilon_n=1/\log(n+2)$, the theorem quoted above implies it directly (Section~\ref{sec:defect}), so the label is incorrect; and since Bugeaud records that theorem in the same book, this reading is unlikely to be what Problem~10.6 asks. + +\subsection*{Contribution and status} +We give an elementary, self-contained proof of \decl{problem_10_6_variant_1} (Theorem~\ref{thm:main}) and verify it in Lean~4. +The proof does not rely on \cite{AHK83}, and it yields only density, not uniform distribution. +Since the formal statement is a special case of a known theorem and does not capture the open problem, we classify this result as a \emph{misformalization report}; it is not progress on Problem~10.6 under any reading that is still open. +If the upstream reading is instead taken at face value as the intended mathematics, what remains is a formal proof of a special case of a known result, not a new theorem. +Section~\ref{sec:defect} explains the defect and proposes a corrected statement. +We found no earlier formal proof: \decl{problem_10_6_variant_1} is still proved by \texttt{sorry} in the formal-conjectures repository and in the fork that supplies \texttt{formal\_proof} links for other statements of the same file (a complete search of public Lean code was not possible). + +\section{Statement}\label{sec:statement} + +Throughout, $\N=\{0,1,2,\dots\}$, $\log$ is the natural logarithm, and a sequence $(t_n)$ of reals is \emph{dense modulo one} if its image under the quotient map $\pi\colon\R\to\R/\Z$ is dense. +Following \cite{FC}, call $m\colon\N\to\N$ \emph{genuinely sublacunary} if there is $c>0$ such that +\begin{equation}\label{eq:floor} + 1+\frac{c}{\log n}\le\frac{m(n+1)}{m(n)}\qquad\text{for all sufficiently large }n. +\end{equation} +(In Lean, $\log 0=0$ and division by zero gives $0$; this plays no role, since \eqref{eq:floor} is only required for large $n$ and our sequence has positive terms.) + +\begin{theorem}\label{thm:main} +There is a strictly increasing $m\colon\N\to\N$ with $m(n)\ge1$ for all $n$ and +\[ + m(n+1)\ge\Bigl(1+\frac{1}{8\log n}\Bigr)m(n)\qquad\text{for all }n\ge2, +\] +such that $(\xi m(n))_{n\in\N}$ is dense modulo one for every irrational $\xi$. In particular $m$ is genuinely sublacunary, with $c=1/8$. +\end{theorem} + +The upstream statement, copied verbatim from \path{Problem10_6.lean} at commit \texttt{c77fdd4} (inside \texttt{namespace Bugeaud06}, with \texttt{open Filter}; the docstring of the theorem is omitted), is: +\begin{lstlisting} +/-- The sequence $m$ eventually grows at least geometrically with a logarithmic correction. -/ +def IsGenuinelySublacunary (m : ℕ → ℕ) : Prop := + ∃ c > 0, ∀ᶠ (n : ℕ) in atTop, (1 + c / Real.log n) ≤ (m (n+1) : ℝ) / m n + +@[category research open, AMS 11] +theorem problem_10_6_variant_1 : + ∃ m : ℕ → ℕ, + StrictMono m ∧ + IsGenuinelySublacunary m ∧ + ∀ ξ : ℝ, Irrational ξ → + Dense (Set.range fun n => (↑(ξ * m n) : AddCircle (1 : ℝ))) := by + sorry +\end{lstlisting} +Here \texttt{AddCircle (1 : ℝ)} is $\R/\Z$ with its quotient topology, and \texttt{↑} is the quotient map $\pi$. +The omitted docstring states Problem~10.6, says that this ratio reading ``is the one that remains open'', and argues that it ``is not answered by runs of consecutive integers, since inside a run $m_{n+1}-m_n=1$''. +Theorem~\ref{thm:main} proves this statement. The formal statement indexes the sequence from $0$ rather than from $1$ as in \cite{Bug12}, which is immaterial. + +\section{Proof}\label{sec:proof} + +\subsection{The construction} +For $k\in\N$ put +\[ + K_k=2^k,\quad M_k=2^{4^k},\quad D_k=2^{M_k},\quad W_k=2D_kK_k,\quad A_k=K_kW_k,\quad L_k=M_k+2k+1, +\] +\[ + B_k=\bigl\{A_k+rW_k+(D_k+r)j : 0\le rr'$ then $x\ge A+(r'+1)W\ge y+D$ by (iii), contradicting $xi$ and $y\ge2^{i+1}$. If $y\in B_k$ then $2^i1/2$. +If $x$ falls under Lemma~\ref{lem:gaps}(b), then $y\ge2x\ge(1+\frac1{8\log n})x$, because $\frac1{8\log n}<\frac14$. +Otherwise $x\in B_k$ for some $k$. By Lemmas~\ref{lem:block}(ii),(iv) and~\ref{lem:enum}, $2^{L_k}=A_k\le x\le2^n$, so $n\ge L_k\ge M_k=2^{4^k}$ and $\log n\ge4^k\log2\ge4^k/2$. By Lemma~\ref{lem:block}(ii),(iv), $x<2A_k=4\cdot4^kD_k$. Hence +\[ + \frac{x}{8\log n}\le\frac{4\cdot4^kD_k}{8\cdot4^k/2}=D_k, +\] +and Lemma~\ref{lem:gaps}(a) gives $y\ge x+D_k\ge\bigl(1+\frac1{8\log n}\bigr)x$. +\end{proof} + +\subsection{Density} +For real $t$ write $\lfloor t\rfloor$ for the floor and $\frc(t)=t-\lfloor t\rfloor\in[0,1)$. + +\begin{lemma}[Stepping]\label{lem:step} +Let $s\ne0$ and $\eta>0$ be real with $|s|\le\eta$, and let $N\in\N$ with $N|s|\ge1$. For all real $u,a$ there are $j\in\{0,\dots,N\}$ and $z\in\Z$ with $a\le u+js+z\le a+\eta$. +\end{lemma} + +\begin{proof} +Let $s>0$. Put $w=\frc(a-u)$, $j=\lceil w/s\rceil$ and $z=\lfloor a-u\rfloor$. Then $w\le jsk$. Write $K,D,W,A$ for the parameters of block $k$. + +\emph{Step 1: choosing the progression.} +Lemma~\ref{lem:step} with step $\delta$, window length $\eta/2$ (note $|\delta|\le\eta/2$ and $N_1|\delta|\ge1$), $u=\xi D$, and $\eta/2$ in place of $a$ gives $j_1\le N_1$ and $z_1\in\Z$ such that $s:=\xi D+j_1\delta+z_1\in[\eta/2,\eta]$. Put $r=j_1q$; then $r\le N_1q\le k0$ makes the sequence eventually lacunary, and then density fails for some irrational $\xi$ by Pollington and de Mathan \cite{Pol79,Mat80}. Since Bugeaud states the theorem of \cite{AHK83} before posing Problem~10.6, the problem presumably asks for something that a bare existence statement with a ratio condition does not capture, such as an explicit or natural sequence. We do not attempt to formalize that. + +\subsection*{Proposed correction} +We propose (1) changing the attribute of \decl{problem_10_6_variant_1} to \texttt{@[category research solved, AMS 11]}, replacing ``and it is the one that remains open'' in its docstring (and the corresponding sentence in the module docstring) by a reference to \cite{AHK83} and \cite[\S2.8]{Bug12}; and (2) adding the theorem of \cite{AHK83}, in the density form that suffices here, as a solved statement: +\begin{lstlisting} +/-- Ajtai–Havas–Komlós [AHK83], as recorded in [Bug12, §2.8], in the weaker form of +density modulo one (they obtain uniform distribution). -/ +@[category research solved, AMS 11] +theorem problem_10_6_variants.ajtai_havas_komlos (ε : ℕ → ℝ) (hε : ∀ n, 0 < ε n) + (hlim : Tendsto ε atTop (nhds 0)) : + ∃ m : ℕ → ℕ, (∀ n, 0 < m n) ∧ (∀ n, 1 + ε n < (m (n + 1) : ℝ) / m n) ∧ + ∀ ξ : ℝ, Irrational ξ → + Dense (Set.range fun n => (↑(ξ * m n) : AddCircle (1 : ℝ))) := by + sorry +\end{lstlisting} +In a scratch file outside the repository, with the pinned versions of Section~\ref{sec:lean}, we checked that this statement elaborates in \texttt{namespace Bugeaud06} and that, taken as a hypothesis, it implies \decl{problem_10_6_variant_1} by the argument above, using only the three standard axioms. The math0 result does not depend on it. + +\section{Machine verification}\label{sec:lean} + +\subsection*{File and declarations} +The proof is the file \path{lean/Math0/Books/Bugeaud06_problem_10_6_variant_1.lean} of the math0 repository (\url{https://github.com/Foundation-0/math0}). It imports only the upstream file \path{Problem10_6.lean} and the audit commands \path{lean/Math0/Audit.lean}. In \texttt{namespace Math0.Bugeaud06} it defines the parameters $K_k,M_k,D_k,W_k,A_k,L_k$ of Section~\ref{sec:proof} as \decl{bK}, \decl{bM}, \decl{bD}, \decl{bW}, \decl{bA}, \decl{bL}, the block element \texttt{elt k r j}~$=A_k+rW_k+(D_k+r)j$, the set \decl{S} exactly as in Section~\ref{sec:proof}, and \texttt{seq := Nat.nth (· ∈ S)}, the increasing enumeration of $S$. +The lemmas correspond to Section~\ref{sec:proof} as follows: Lemma~\ref{lem:block} is \decl{bK_le_bD}, \decl{bA_eq}, \decl{bA_eq'}, \decl{two_mul_bA}, \decl{key_bound}, \decl{elt_ge}, \decl{elt_add_le}, \decl{within_gap} and \decl{bL_lt}; Lemma~\ref{lem:gaps} is \decl{gap_block}, \decl{gap_filler} and \decl{S_cases}; Lemma~\ref{lem:enum} is \decl{S_infinite}, \decl{seq_strictMono}, \decl{seq_mem}, \decl{range_seq}, \decl{seq_le_pow} and \decl{seq_pos}; Proposition~\ref{prop:ratio} is \decl{sublacunary} (which proves \decl{IsGenuinelySublacunary}~\texttt{seq} with $c=1/8$, using Mathlib's bound $\log2>0.6931471803$); Lemma~\ref{lem:step} is \decl{step_pos} and \decl{step_any}; Proposition~\ref{prop:dense} is \decl{dense_aux}; and the final projection to $\R/\Z$ is \decl{dense_seq}. The file ends with +\begin{lstlisting} +theorem problem_10_6_variant_1 : type_of% @Bugeaud06.problem_10_6_variant_1 := + ⟨seq, seq_strictMono, sublacunary, dense_seq⟩ + +end Math0.Bugeaud06 + +#math0_proves Math0.Bugeaud06.problem_10_6_variant_1 Bugeaud06.problem_10_6_variant_1 +\end{lstlisting} +The file contains no \texttt{sorry}, \texttt{native\_decide}, \texttt{set\_option} or new axioms, and it compiles in about 15 seconds. + +\subsection*{Audit} +The command \decl{#math0_proves}, defined in \path{lean/Math0/Audit.lean}, fails unless (1) the two declarations have the same universe parameters, (2) the type of \decl{Math0.Bugeaud06.problem_10_6_variant_1} is syntactically identical to the type of the upstream \decl{Bugeaud06.problem_10_6_variant_1}, up to metadata annotations only (no unfolding and no definitional-equality check), and (3) our theorem depends on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which rules out \decl{sorryAx}, the axioms behind \decl{native_decide} and custom axioms. On this file it reports +\begin{lstlisting} +math0 audit: 'Math0.Bugeaud06.problem_10_6_variant_1' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Bugeaud06.problem_10_6_variant_1' proves 'Bugeaud06.problem_10_6_variant_1' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1}, Mathlib \cite{Mathlib} \texttt{v4.33.1} and formal-conjectures \cite{FC} at commit \texttt{c77fdd446d23539302aa73bcfae4a9fa962b8382}, all pinned in \path{lean/}. To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. A single file can be checked with \texttt{lake env lean} from \path{lean/}. + +\begin{thebibliography}{99} +\raggedright + +\bibitem{AHK83} +M.~Ajtai, I.~Havas, and J.~Koml\'os, \emph{Every group admits a bad topology}, in: Studies in Pure Mathematics (to the memory of P.~Tur\'an), Birkh\"auser, Basel, 1983, 21--34. + +\bibitem{Bos83} +M.~D. Boshernitzan, \emph{Homogeneously distributed sequences and Poincar\'e sequences of integers of sublacunary growth}, Monatsh. Math. \textbf{96} (1983), 173--181. + +\bibitem{Bug12} +Y.~Bugeaud, \emph{Distribution Modulo One and Diophantine Approximation}, Cambridge Tracts in Mathematics \textbf{193}, Cambridge University Press, Cambridge, 2012. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Fur67} +H.~Furstenberg, \emph{Disjointness in ergodic theory, minimal sets, and a problem in Diophantine approximation}, Math. Systems Theory \textbf{1} (1967), 1--49. + +\bibitem{GMY} +X.~Gao, Y.~Mooroogen, and C.~H. Yip, \emph{On an Erd\H{o}s similarity problem in the large}, Bull. Lond. Math. Soc. \textbf{57} (2025), no.~6, 1801--1818; arXiv:2311.06727 (numbering cited from arXiv v3). + +\bibitem{Mat80} +B.~de Mathan, \emph{Numbers contravening a condition in density modulo~$1$}, Acta Math. Acad. Sci. Hungar. \textbf{36} (1980), 237--241. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Pol79} +A.~D. Pollington, \emph{On the density of sequence $\{n_k\xi\}$}, Illinois J. Math. \textbf{23} (1979), 511--515. + +\end{thebibliography} + +\end{document} diff --git a/results/bugeaud08-problem-10-8-variants-quadratic/README.md b/results/bugeaud08-problem-10-8-variants-quadratic/README.md new file mode 100644 index 0000000..24ffec7 --- /dev/null +++ b/results/bugeaud08-problem-10-8-variants-quadratic/README.md @@ -0,0 +1,30 @@ +# The p-adic Littlewood conjecture for real quadratic irrationals + +**Classification:** First formal proof of a known result +**Area:** Number theory +**Source problem:** Books / BugeaudDistributionModuloOne / Problem10_8 +**Date:** 2026-10-17 + +## Result + +Let p be a prime and ξ a real number whose minimal polynomial over ℚ has degree 2. Then inf over integers q ≥ 1 of q · |q|_p · ‖qξ‖ is 0. Here ‖·‖ is the distance to the nearest integer, |·|_p is the p-adic absolute value, and the infimum is the real sInf of the set {q · padicNorm p q · distToNearestInt(qξ) : q ∈ ℕ, q ≥ 1}. + +## Verification + +The Lean file [`lean/Math0/Books/Bugeaud08_problem_10_8_variants_quadratic.lean`](../../lean/Math0/Books/Bugeaud08_problem_10_8_variants_quadratic.lean) proves the upstream statement [`Bugeaud08.problem_10_8.variants.quadratic`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_8.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +de Mathan, B. and Teulié, O., "Problèmes diophantiens simultanés", Monatshefte für Mathematik 143 (2004), 229–245. They proved the p-adic Littlewood conjecture for quadratic irrationals, in a stronger form with a log factor. The problem is stated as Problem 10.8 in Bugeaud, "Distribution modulo one and Diophantine approximation" (CUP, 2012), Chapter 10. The elementary Pell/units argument used here is the standard proof of the quadratic case. I found no prior Lean formalization: there is no formal_proof attribute on Bugeaud08.problem_10_8.variants.quadratic, nothing in Mathlib, and the related formal_conjectures statement LittlewoodConjecture.padic_littlewood_conjecture is open and sorried. + +## Citation + +```bibtex +@misc{math0:bugeaud08-problem-10-8-variants-quadratic, + author = {{math0}}, + title = {{The p-adic Littlewood conjecture for real quadratic irrationals}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/bugeaud08-problem-10-8-variants-quadratic}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/bugeaud09-problem-10-9-variants-dimh-lt-one/README.md b/results/bugeaud09-problem-10-9-variants-dimh-lt-one/README.md new file mode 100644 index 0000000..a5693b2 --- /dev/null +++ b/results/bugeaud09-problem-10-9-variants-dimh-lt-one/README.md @@ -0,0 +1,30 @@ +# The set of Mahler Z-numbers is countable, so its Hausdorff dimension is 0, which is less than 1 + +**Classification:** First formal proof of a known result +**Area:** Number theory +**Source problem:** Books / BugeaudDistributionModuloOne / Problem10_9 +**Date:** 2026-10-17 + +## Result + +A Z-number is a real ξ > 0 such that the fractional part {ξ (3/2)^n} lies in [0, 1/2) for every integer n ≥ 1. The set Z of all Z-numbers has Hausdorff dimension < 1, i.e. dimH {ξ : ℝ | IsZNumber ξ} < 1 in ℝ≥0∞. Flatto, Lagarias and Pollington (1995) proved this result, recorded in Bugeaud, Problem 10.9. We prove something stronger, going back to Mahler (1968): Z is countable, so dimH Z = 0. + +## Verification + +The Lean file [`lean/Math0/Books/Bugeaud09_problem_10_9_variants_dimH_lt_one.lean`](../../lean/Math0/Books/Bugeaud09_problem_10_9_variants_dimH_lt_one.lean) proves the upstream statement [`Bugeaud09.problem_10_9.variants.dimH_lt_one`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_9.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Mahler, K. "An unsolved problem on the powers of 3/2", J. Austral. Math. Soc. 8 (1968) 313-321: shows each interval [k, k+1) contains at most one Z-number, so the set of Z-numbers is countable (hence of Lebesgue measure 0 and Hausdorff dimension 0). Flatto, Lagarias and Pollington, "On the range of fractional parts {ξ(p/q)^n}", Acta Arith. 70 (1995) 125-147, credited by the upstream docstring; for this particular set their result is weaker than Mahler's countability. Bugeaud, "Distribution modulo one and Diophantine approximation" (CUP 2012), Ch. 10, Problem 10.9. I know of no prior Lean formalization: the upstream formal_conjectures statement is `sorry` with no formal_proof link, and Mathlib has no Z-number results. + +## Citation + +```bibtex +@misc{math0:bugeaud09-problem-10-9-variants-dimh-lt-one, + author = {{math0}}, + title = {{The set of Mahler Z-numbers is countable, so its Hausdorff dimension is 0, which is less than 1}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/bugeaud09-problem-10-9-variants-dimh-lt-one}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/bugeaud09-problem-10-9-variants-measure-zero/README.md b/results/bugeaud09-problem-10-9-variants-measure-zero/README.md new file mode 100644 index 0000000..e784ec3 --- /dev/null +++ b/results/bugeaud09-problem-10-9-variants-measure-zero/README.md @@ -0,0 +1,30 @@ +# Mahler's Z-numbers form a Lebesgue-null set + +**Classification:** First formal proof of a known result +**Area:** Number theory +**Source problem:** Books / BugeaudDistributionModuloOne / Problem10_9 +**Date:** 2026-10-17 + +## Result + +A Z-number is a real number ξ > 0 such that the fractional part {ξ (3/2)^n} lies in [0, 1/2) for every integer n ≥ 1. The set of Z-numbers has Lebesgue measure zero (Mahler 1968; Bugeaud, Distribution modulo one and Diophantine approximation, Problem 10.9, measure-zero variant). Formally: MeasureTheory.volume {ξ : ℝ | IsZNumber ξ} = 0. + +## Verification + +The Lean file [`lean/Math0/Books/Bugeaud09_problem_10_9_variants_measure_zero.lean`](../../lean/Math0/Books/Bugeaud09_problem_10_9_variants_measure_zero.lean) proves the upstream statement [`Bugeaud09.problem_10_9.variants.measure_zero`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Books/BugeaudDistributionModuloOne/Problem10_9.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +K. Mahler, "An unsolved problem on the powers of 3/2", J. Austral. Math. Soc. 8 (1968) 313-321: at most one Z-number in each interval [k, k+1) (n ≥ 0 normalization), so Z-numbers are countable, with counting function O(x^0.7). This gives measure zero. Y. Bugeaud, Distribution Modulo One and Diophantine Approximation (CUP 2012), Ch. 10, Problem 10.9. Flatto–Lagarias–Pollington, Acta Arith. 70 (1995), is the source of the related dimH variant. I know of no earlier Lean formalization: the upstream formal-conjectures item is a `sorry` with no formal_proof link. I could not search GitHub because session access is limited to configured repositories. + +## Citation + +```bibtex +@misc{math0:bugeaud09-problem-10-9-variants-measure-zero, + author = {{math0}}, + title = {{Mahler's Z-numbers form a Lebesgue-null set}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/bugeaud09-problem-10-9-variants-measure-zero}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/equidistribution-isaccumulationpoint-three-halves-pow-infinite/README.md b/results/equidistribution-isaccumulationpoint-three-halves-pow-infinite/README.md new file mode 100644 index 0000000..1ce49dd --- /dev/null +++ b/results/equidistribution-isaccumulationpoint-three-halves-pow-infinite/README.md @@ -0,0 +1,30 @@ +# The fractional parts of (3/2)^n have infinitely many accumulation points + +**Classification:** First formal proof of a known result +**Area:** Number theory +**Source problem:** Books / UniformDistributionOfSequences / Equidistribution +**Date:** 2026-10-17 + +## Result + +Let r_n = {(3/2)^n} be the fractional part of (3/2)^n for n = 0, 1, 2, .... Call x an accumulation point of (r_n) if x lies in the closure of {r_n : n ∈ ℕ} \ {x}. Then the set of accumulation points of (r_n) is infinite. (Vijayaraghavan's theorem, cited in Kuipers–Niederreiter, Uniform Distribution of Sequences, Ch. 1.) + +## Verification + +The Lean file [`lean/Math0/Books/Equidistribution_isAccumulationPoint_three_halves_pow_infinite.lean`](../../lean/Math0/Books/Equidistribution_isAccumulationPoint_three_halves_pow_infinite.lean) proves the upstream statement [`Equidistribution.isAccumulationPoint_three_halves_pow_infinite`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/Books/UniformDistributionOfSequences/Equidistribution.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +T. Vijayaraghavan, "On the fractional parts of the powers of a number", J. London Math. Soc. 15 (1940), 159–160, proves that {(p/q)^n}, and in particular {(3/2)^n}, has infinitely many limit points. Kuipers & Niederreiter, Uniform Distribution of Sequences (1974), Ch. 1 notes cite it in the source referenced by the upstream file. Upstream google-deepmind/formal-conjectures (main, checked 2026-10-17) still has `sorry` for this theorem, and I know of no previous Lean proof. + +## Citation + +```bibtex +@misc{math0:equidistribution-isaccumulationpoint-three-halves-pow-infinite, + author = {{math0}}, + title = {{The fractional parts of (3/2)^n have infinitely many accumulation points}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/equidistribution-isaccumulationpoint-three-halves-pow-infinite}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos10-erdos-10-variants-grechuk-example/README.md b/results/erdos10-erdos-10-variants-grechuk-example/README.md new file mode 100644 index 0000000..51fbcd1 --- /dev/null +++ b/results/erdos10-erdos-10-variants-grechuk-example/README.md @@ -0,0 +1,39 @@ +# Grechuk's example: 1117175146 is not a prime plus at most three powers of two + +**Classification:** First formal proof of a known result +**Area:** Combinatorics, Number theory +**Source problem:** Erdős Problem #10 +**Date:** 2026-10-17 + +## Result + +Let N = 1117175146. There is no prime p and no multiset of at most three natural numbers e_1, ..., e_k (k ≤ 3, repetitions allowed) with N = p + 2^{e_1} + ... + 2^{e_k}. Formally: 1117175146 ∉ sumPrimeAndTwoPows 3, where sumPrimeAndTwoPows k = { p + Σ_{e ∈ pows} 2^e : p prime, pows a multiset of naturals with card pows ≤ k }. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos10_erdos_10_variants_grechuk_example.lean`](../../lean/Math0/ErdosProblems/Erdos10_erdos_10_variants_grechuk_example.lean) proves the upstream statement [`Erdos10.erdos_10.variants.grechuk_example`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/10.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Sources: +- erdosproblems.com/10: the problem is open; it records Bogdan Grechuk's observation that 1117175146 is not a prime plus at most 3 powers of 2, without showing how it was verified. The local problems.yaml lists problem 10 with status open and formalized "yes", with no Lean proof noted for this example. +- Related references: Granville and Soundararajan (1998), the conjecture this example bears on for even integers; Crocker (1971), the infinitude construction. +- The upstream formal_proof link for the infinite variant `erdos_10.variants.grechuk` (DaryxXx gist e112c74c…, Main.lean) does not contain 1117175146. The `two_pows` link is to anatoliiohorodnyk/lean-fc-proofs, whose (truncated) listing has no grechuk_example file. +- A web search for "1117175146" with Lean found nothing. +- Conclusion: the statement is known (a computational fact due to Grechuk), and this appears to be its first Lean formalization. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:erdos10-erdos-10-variants-grechuk-example, + author = {{math0}}, + title = {{Grechuk's example: 1117175146 is not a prime plus at most three powers of two}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos10-erdos-10-variants-grechuk-example}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos10-erdos-10-variants-grechuk-example/paper.pdf b/results/erdos10-erdos-10-variants-grechuk-example/paper.pdf new file mode 100644 index 0000000..8671238 Binary files /dev/null and b/results/erdos10-erdos-10-variants-grechuk-example/paper.pdf differ diff --git a/results/erdos10-erdos-10-variants-grechuk-example/paper.tex b/results/erdos10-erdos-10-variants-grechuk-example/paper.tex new file mode 100644 index 0000000..6c60e81 --- /dev/null +++ b/results/erdos10-erdos-10-variants-grechuk-example/paper.tex @@ -0,0 +1,417 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{booktabs} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, upquote=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {≤}{{$\le$}}1 {∉}{{$\notin$}}1 {·}{{$\cdot$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {▸}{{$\triangleright$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{▸}{\ensuremath{\triangleright}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\cS}{\mathcal{S}} +\newcommand{\wt}{\nu} + +\title[$1117175146$ is not a prime plus at most three powers of two]{The integer $1117175146$ is not the sum of a prime and at most three powers of two} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 17, 2026} + +\begin{document} +\begin{abstract} +We prove that $N=1117175146$ cannot be written as $p+2^{e_1}+\dots+2^{e_k}$ with $p$ prime, $0\le k\le 3$, and exponents $e_1,\dots,e_k\ge 0$ that need not be distinct. +This was observed by Bogdan Grechuk in connection with Erd\H{o}s Problem~\#10, and shows that the restriction to odd integers in a conjecture of Granville and Soundararajan cannot simply be dropped; the result is known, and we provide a complete certificate-based proof and, to our knowledge, its first formal proof. +The proof bounds every exponent by $30$ and checks, for each of the $5828$ admissible exponent multisets with sum $s$, that $N-s$ has a proper divisor in an explicit list of $38$ primes; we also give a hand-checkable form of this certificate based on $N-1=(2^{16}-1)\cdot 17047$. +The argument is verified in Lean~4, with the finite computation carried out by the Lean kernel, against the statement \decl{Erdos10.erdos_10.variants.grechuk_example} of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +Erd\H{o}s asked whether there is a constant $k$ such that every sufficiently large integer is the sum of a prime and at most $k$ powers of $2$ \cite[p.~96]{Er80}, \cite[p.~28]{ErGr80}. +This is Problem~\#10 on the Erd\H{o}s Problems website \cite{EP10}, where it is listed as open. +Gallagher \cite{Ga75} proved that for every $\varepsilon>0$ there is $k(\varepsilon)$ such that the integers that are the sum of a prime and at most $k(\varepsilon)$ powers of $2$ have lower density at least $1-\varepsilon$. +Granville and Soundararajan \cite{GrSo98} conjectured that at most three powers of $2$ suffice for all odd integers, and hence at most four suffice for all even integers. + +As recorded on \cite{EP10}, the restriction to odd integers matters: Bogdan Grechuk observed that $1117175146$ is not the sum of a prime and at most three powers of $2$. +Grechuk also pointed out that parity considerations, together with the existence of many integers that are not the sum of a prime and two powers of $2$, suggest that infinitely many even integers are not the sum of a prime and at most three powers of $2$. +The formal-conjectures repository \cite{FC} notes that this infinite statement follows from Crocker's construction \cite{Cr71} of infinitely many odd integers that are not the sum of a prime and two powers of $2$, and links a Lean formalisation of the infinite statement \cite{Da}; that formalisation does not treat the specific integer $1117175146$. + +\subsection*{Status and contribution} +The statement proved here is Grechuk's observation and is not new. +The page \cite{EP10} records it without describing how it was verified. +We give (i) a complete proof by an explicit finite certificate (Section~\ref{sec:proof}); (ii) a form of the certificate that can be checked by hand, in which all but $44$ of the remainders are handled by one congruence argument (Section~\ref{sec:hand}); and (iii) a Lean~4 proof of the upstream formal statement \decl{Erdos10.erdos_10.variants.grechuk_example} of \cite{FC} (Section~\ref{sec:lean}). +The upstream file links no formal proof for this statement. The Lean files it links as formal proofs of two neighbouring variants (the infinite statement above \cite{Da}, and a statement about two powers of $2$ \cite{Oh}) do not prove it: the first does not mention $1117175146$, and the second restates it with \texttt{sorry}. A web search found no other formal proof. +We therefore classify the result as the \emph{first formal proof of a known result}. +We do not know how Grechuk found or verified the example. + +\section{Statement}\label{sec:statement} + +Let $\N=\{0,1,2,\dots\}$. For $k\in\N$ let +\[ + \cS_k=\Bigl\{\,p+\sum_{i=1}^{j}2^{e_i} \;:\; p \text{ prime},\ 0\le j\le k,\ e_1,\dots,e_j\in\N\,\Bigr\}. +\] +Here $2^0=1$ counts as a power of two, and the exponents need not be distinct. + +\begin{theorem}\label{thm:main} +Let $N=1117175146$. Then $N\notin\cS_3$; that is, there are no prime $p$, integer $0\le j\le 3$ and exponents $e_1,\dots,e_j\in\N$ with $N=p+2^{e_1}+\dots+2^{e_j}$. +\end{theorem} + +Because repeated exponents, the exponent $0$, and fewer than three summands are all allowed, Theorem~\ref{thm:main} implies the variants in which the powers are required to be distinct, to be at least $2$, or to be exactly three in number. + +In the formal-conjectures repository \cite{FC} (commit \texttt{c77fdd4}) the set $\cS_k$ is the abbreviation \texttt{sumPrimeAndTwoPows}~$k$, in which the exponents form a multiset \texttt{pows} of natural numbers of cardinality at most $k$. A multiset of cardinality $j$ is the same as an unordered $j$-tuple, so this is exactly the set $\cS_k$ above. +The definition and the statement, copied verbatim from \path{FormalConjectures/ErdosProblems/10.lean}, are: +\begin{lstlisting} +/-- +The set of natural numbers that can be written as a sum +of a prime and at most $k$ powers of $2$. +-/ +abbrev sumPrimeAndTwoPows (k : ℕ) : Set ℕ := + { p + (pows.map (2 ^ ·)).sum | (p : ℕ) (pows : Multiset ℕ) (_ : p.Prime) + (_ : pows.card ≤ k)} + +/-- +Bogdan Grechuk has observed that `1117175146` is not the sum of a prime +and at most $3$ powers of $2$. +-/ +@[category research solved, AMS 5 11] +theorem erdos_10.variants.grechuk_example : + 1117175146 ∉ sumPrimeAndTwoPows 3 := by + sorry +\end{lstlisting} + +\section{Proof}\label{sec:proof} + +Throughout, $N=1117175146$. Its binary expansion is +\[ +N=2^{30}+2^{25}+2^{23}+2^{20}+2^{18}+2^{17}+2^{15}+2^{13}+2^{12}+2^{11}+2^{10}+2^{8}+2^{6}+2^{5}+2^{3}+2^{1}, +\] +so in particular $2^{30}\le N<2^{31}=2147483648$. + +\subsection{The certificate} +Let $W$ be the following list of $38$ primes: +\[ +\begin{aligned} +W=(&2, 3, 5, 7, 11, 13, 17, 19, 23, 37, 41, 47, 59, 61, 73, 79, 89, 97, 101,\\ + &103, 107, 131, 163, 199, 211, 229, 257, 379, 547, 659, 877, 1381, 1481,\\ + &1699, 2099, 7283, 7703, 19391). +\end{aligned} +\] + +\begin{definition}\label{def:cert} +An integer $m\in\N$ is \emph{certified} if $m<2$, or if there is $q\in W$ with $q\mid m$ and $qN$. +\end{proof} + +\begin{proposition}\label{prop:finite} +Let $j\in\{0,1,2,3\}$ and $e_1,\dots,e_j\in\N$, and put $s=\sum_{i=1}^j 2^{e_i}$. If $s\le N$, then $N-s$ is certified. +\end{proposition} + +\begin{proof} +Each summand satisfies $1\le 2^{e_i}\le s\le N$, so $e_i\le 30$ by Lemma~\ref{lem:exp}. It therefore suffices to check the claim for the tuples $(e_1,\dots,e_j)\in\{0,\dots,30\}^j$ with $s\le N$: the empty tuple ($s=0$), the $31$ singletons, $952$ of the $31^2=961$ ordered pairs, and $29009$ of the $31^3=29791$ ordered triples. For each of these one verifies by trial division that $N-s$ has a divisor $q\in W$ with $q m % q == 0 && q < m) + +def check3 : Bool := + (List.range 31).all fun x => (List.range 31).all fun y => (List.range 31).all fun z => + !(2 ^ x + 2 ^ y + 2 ^ z ≤ 1117175146) || good (1117175146 - (2 ^ x + 2 ^ y + 2 ^ z)) + +theorem check3_eq : check3 = true := by decide +kernel + +theorem erdos_10_grechuk_example : type_of% @Erdos10.erdos_10.variants.grechuk_example := by + rintro ⟨p, pows, hp, hcard, h⟩ + induction pows using Quotient.inductionOn with + | h l => + rcases l with _ | ⟨a, _ | ⟨b, _ | ⟨c, _ | ⟨d, l⟩⟩⟩⟩ + · simp at h + exact not_prime_of_good (h ▸ good_N) hp + · simp at h + have hs : 2 ^ a ≤ 1117175146 := by omega + exact not_prime_of_good (show p = 1117175146 - 2 ^ a by omega ▸ spec1 hs) hp + · simp at h + have hs : 2 ^ a + 2 ^ b ≤ 1117175146 := by omega + exact not_prime_of_good (show p = 1117175146 - (2 ^ a + 2 ^ b) by omega ▸ spec2 hs) hp + · simp at h + have hs : 2 ^ a + 2 ^ b + 2 ^ c ≤ 1117175146 := by omega + exact not_prime_of_good (show p = 1117175146 - (2 ^ a + 2 ^ b + 2 ^ c) by omega ▸ spec3 hs) hp + · simp at hcard + omega + +#math0_proves Math0.Erdos10.erdos_10_grechuk_example Erdos10.erdos_10.variants.grechuk_example +\end{lstlisting} +\caption{Verbatim excerpt of the Lean file.} +\label{fig:lean} +\end{figure} +The main proof follows Section~\ref{sec:proof}: the multiset of exponents is replaced by a list representing it (via \decl{Quotient.inductionOn}); the list is split by length, \decl{omega} derives $s\le N$ and $p=N-s$ from $p+s=N$, and the certificate gives $\neg\,\mathrm{Prime}(p)$. In the last case \decl{simp} rewrites the cardinality hypothesis as an inequality between numerals and the list length that \decl{omega} refutes. + +\subsection*{Kernel computation} +The finite verification consists of the four theorems \decl{good_N}, \decl{check1_eq}, \decl{check2_eq} and \decl{check3_eq}, each proved by \texttt{decide +kernel}. This tactic closes a decidable goal with a proof term whose type-correctness the Lean kernel establishes by reducing the decision procedure to \decl{true}, evaluating the Boolean functions by definitional unfolding with its built-in arbitrary-precision arithmetic on natural-number literals. No compiled code is trusted: the file does not use \decl{native_decide}, which would introduce the axiom \decl{Lean.ofReduceBool}. The largest check, \decl{check3_eq}, runs through all $29791$ triples and takes about $20$ seconds; the whole file compiles in about $30$ seconds with default settings. + +\subsection*{Audit} +The last command of the file is \texttt{\#math0\_proves}, applied to our theorem and the upstream declaration (Figure~\ref{fig:lean}). This command, defined in \path{lean/Math0/Audit.lean}, fails unless (1) the two declarations have the same universe parameters, (2) their types are syntactically identical after removing metadata annotations, with no unfolding and no definitional-equality check, and (3) our theorem depends on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}. In particular it rejects \decl{sorryAx}, \decl{Lean.ofReduceBool} and \decl{Lean.trustCompiler}, and any custom axiom. On this file it reports +\begin{lstlisting} +math0 audit: 'Math0.Erdos10.erdos_10_grechuk_example' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Erdos10.erdos_10_grechuk_example' proves 'Erdos10.erdos_10.variants.grechuk_example' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1}, Mathlib \cite{Mathlib} \texttt{v4.33.1} and formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, all pinned in \path{lean/}. +To reproduce, run \path{scripts/verify.sh} from the repository root. It fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The single file can also be checked by running \texttt{lake env lean} on it from the \path{lean} directory. +A recomputation in Python (SymPy) confirmed all counts above and that no remainder $N-s$ is prime. + +\begin{thebibliography}{99} + +\bibitem{EP10} +T.~F. Bloom, \emph{Erd\H{o}s Problems}, Problem \#10, \url{https://www.erdosproblems.com/10}, accessed October 2026. + +\bibitem{Cr71} +R.~Crocker, \emph{On the sum of a prime and of two powers of two}, Pacific J. Math. \textbf{36} (1971), no.~1, 103--107. + +\bibitem{Da} +DaryxXx, \emph{Lean formalisation of \texttt{erdos\_10.variants.grechuk}}, GitHub gist, file \texttt{Main.lean}, revision \texttt{4b34789}, \url{https://gist.github.com/DaryxXx/e112c74cc648b08a420b0959315cf65f}, linked from \cite{FC}. + +\bibitem{Er80} +P.~Erd\H{o}s, \emph{A survey of problems in combinatorial number theory}, Ann. Discrete Math. \textbf{6} (1980), 89--115. + +\bibitem{ErGr80} +P.~Erd\H{o}s and R.~L. Graham, \emph{Old and new problems and results in combinatorial number theory}, Monographies de L'Enseignement Math\'ematique \textbf{28}, Universit\'e de Gen\`eve, Geneva, 1980. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Ga75} +P.~X. Gallagher, \emph{Primes and powers of $2$}, Invent. Math. \textbf{29} (1975), 125--142. + +\bibitem{GrSo98} +A.~Granville and K.~Soundararajan, \emph{A binary additive problem of Erd\H{o}s and the order of $2$ mod $p^2$}, Ramanujan J. \textbf{2} (1998), 283--298. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Oh} +anatoliiohorodnyk, \emph{lean-fc-proofs}, GitHub repository, file \path{Proofs/T_Erdos10_erdos_10_variants_two_pows.lean} at commit \texttt{5da9642}, \url{https://github.com/anatoliiohorodnyk/lean-fc-proofs}, linked from \cite{FC}. + +\end{thebibliography} + +\end{document} diff --git a/results/erdos1000-erdos-1000-variants-limsup-eq-one/README.md b/results/erdos1000-erdos-1000-variants-limsup-eq-one/README.md new file mode 100644 index 0000000..3e47313 --- /dev/null +++ b/results/erdos1000-erdos-1000-variants-limsup-eq-one/README.md @@ -0,0 +1,30 @@ +# Erdős Problem 1000: liminf φ_A(k)/n_k = 0 forces limsup φ_A(k)/n_k = 1 + +**Classification:** First formal proof of a known result +**Area:** Number theory +**Source problem:** Erdős Problem #1000 +**Date:** 2026-10-17 + +## Result + +Let n_0 < n_1 < n_2 < ... be a strictly increasing sequence of positive integers. Let φ_A(k) be the number of integers 1 ≤ m ≤ n_k such that n_k / gcd(m, n_k) divides no n_j with j < k. Put r_k = φ_A(k)/n_k. If liminf_{k→∞} r_k = 0, then limsup_{k→∞} r_k = 1. (Erdős [Er64b], recorded as erdosproblems.com/1000.) + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_limsup_eq_one.lean`](../../lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_limsup_eq_one.lean) proves the upstream statement [`Erdos1000.erdos_1000.variants.limsup_eq_one`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1000.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +The result is Erdős, P., "Problems and results on diophantine approximations", Compositio Math. 16 (1964), 52-65 [Er64b]: if liminf φ_A(k)/n_k = 0 then limsup φ_A(k)/n_k = 1. The function φ_A was introduced by Cassels, "Some metrical theorems in Diophantine approximation. I", Proc. Cambridge Philos. Soc. (1950) [Ca50b]. Cassels's existence result (liminf of the Cesàro averages equal to 0) shows the hypothesis can hold. Haight's PhD thesis [Ha] settled the main problem: the averages can tend to 0. The problem is erdosproblems.com/1000, listed as "proved (Lean)". That status refers to the main problem, whose existing formalization is https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1000.lean. That file covers only the main existence theorem, not the limsup_eq_one variant. + +## Citation + +```bibtex +@misc{math0:erdos1000-erdos-1000-variants-limsup-eq-one, + author = {{math0}}, + title = {{Erdős Problem 1000: liminf φ_A(k)/n_k = 0 forces limsup φ_A(k)/n_k = 1}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1000-erdos-1000-variants-limsup-eq-one}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1000-erdos-1000-variants-not-tendsto-zero/README.md b/results/erdos1000-erdos-1000-variants-not-tendsto-zero/README.md new file mode 100644 index 0000000..3d24226 --- /dev/null +++ b/results/erdos1000-erdos-1000-variants-not-tendsto-zero/README.md @@ -0,0 +1,30 @@ +# Erdős Problem 1000: φ_A(k)/n_k does not tend to 0 + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Number theory +**Source problem:** Erdős Problem #1000 +**Date:** 2026-10-17 + +## Result + +Let n_0 < n_1 < n_2 < ... be a strictly increasing sequence of positive integers. Let φ_A(k) be the number of integers 1 ≤ m ≤ n_k such that n_k / gcd(m, n_k) divides none of the earlier terms n_j with j < k. Then φ_A(k)/n_k does not tend to 0 as k → ∞. (Erdős [Er64b], erdosproblems.com/1000.) + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_not_tendsto_zero.lean`](../../lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_not_tendsto_zero.lean) proves the upstream statement [`Erdos1000.erdos_1000.variants.not_tendsto_zero`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1000.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Erdős, Problems and results on diophantine approximations, Compositio Math. 1964 [Er64b], where Erdős proves that lim φ_A(k)/n_k ≠ 0 and that liminf = 0 forces limsup = 1. Cassels [Ca50b] introduced φ_A. Haight solved the main question. erdosproblems.com/1000 lists the problem as "proved (Lean)"; that formal proof (plby/lean-proofs src/v4.29.1/ErdosProblems/Erdos1000.lean) covers only Haight's main theorem. math0 had already committed a proof of upstream erdos_1000.variants.limsup_eq_one (lean/Math0/ErdosProblems/Erdos1000_erdos_1000_variants_limsup_eq_one.lean), and this result follows from it directly. + +## Citation + +```bibtex +@misc{math0:erdos1000-erdos-1000-variants-not-tendsto-zero, + author = {{math0}}, + title = {{Erdős Problem 1000: φ_A(k)/n_k does not tend to 0}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1000-erdos-1000-variants-not-tendsto-zero}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1008-erdos-1008-variants-lower-bound/README.md b/results/erdos1008-erdos-1008-variants-lower-bound/README.md new file mode 100644 index 0000000..2030c1d --- /dev/null +++ b/results/erdos1008-erdos-1008-variants-lower-bound/README.md @@ -0,0 +1,30 @@ +# Erdős Problem 1008: every graph with m edges has a C4-free subgraph with at least √m/2 edges + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Combinatorics +**Source problem:** Erdős Problem #1008 +**Date:** 2026-10-17 + +## Result + +There is a constant c > 0 such that for every finite type V and every simple graph G on V, some subgraph H ≤ G contains no copy of the 4-cycle C4 and satisfies c · m^{1/2} ≤ |E(H)|, where m = |E(G)|. (Erdős, [Er71], called this bound "trivial" and asked for m^{2/3}.) We prove it with c = 1/2. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1008_erdos_1008_variants_lower_bound.lean`](../../lean/Math0/ErdosProblems/Erdos1008_erdos_1008_variants_lower_bound.lean) proves the upstream statement [`Erdos1008.erdos_1008.variants.lower_bound`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1008.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +The source is Erdős [Er71], "Some unsolved problems in graph theory and combinatorial analysis" (1971), which notes that ≫ m^{1/2} is trivial and asks for m^{2/3}. The m^{2/3} bound was proved by Conlon, Fox and Sudakov [CFS14b], "Large subgraphs without complete bipartite graphs" (arXiv:1401.6711), and Hunter gave a simpler proof in the erdosproblems forum. The main statement is formalized in Lean at https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1008.lean (Aristotle / Boris Alexeev), with constant 1/2 and exponent 2/3, and erdosproblems.com lists 1008 as "proved (Lean)". The exponent-1/2 variant follows immediately from that formalized result. The folklore argument used here (max degree versus maximum matching, m ≤ 2Δν) is standard. + +## Citation + +```bibtex +@misc{math0:erdos1008-erdos-1008-variants-lower-bound, + author = {{math0}}, + title = {{Erdős Problem 1008: every graph with m edges has a C4-free subgraph with at least √m/2 edges}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1008-erdos-1008-variants-lower-bound}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1010-erdos-1010-variants-rademacher/README.md b/results/erdos1010-erdos-1010-variants-rademacher/README.md new file mode 100644 index 0000000..f214607 --- /dev/null +++ b/results/erdos1010-erdos-1010-variants-rademacher/README.md @@ -0,0 +1,34 @@ +# Rademacher's theorem: ⌊n²/4⌋+1 edges force ⌊n/2⌋ triangles + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Combinatorics +**Source problem:** Erdős Problem #1010 +**Date:** 2026-10-17 + +## Result + +For every n ∈ ℕ and every simple graph G on the vertex set Fin n with exactly ⌊n²/4⌋ + 1 edges, G contains at least ⌊n/2⌋ triangles (3-cliques). + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1010_erdos_1010_variants_rademacher.lean`](../../lean/Math0/ErdosProblems/Erdos1010_erdos_1010_variants_rademacher.lean) proves the upstream statement [`Erdos1010.erdos_1010.variants.rademacher`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1010.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Rademacher (1941, unpublished, reported by Erdős): a graph with ⌊n²/4⌋+1 edges has at least ⌊n/2⌋ triangles. Erdős, "On a theorem of Rademacher-Turán", Illinois J. Math. 6 (1962) 122-127, proves t⌊n/2⌋ for t < cn. Lovász–Simonovits (1976) and Nikiforov–Khadzhiivanov, C. R. Acad. Bulgare Sci. (1981), settle the case t < ⌊n/2⌋ (erdosproblems #1010, status: proved). An existing Lean 4 formalization of the general statement, which implies this variant at t = 1, is plby/lean-proofs src/latest/ErdosProblems/Erdos1010.lean (commit 8822f7ddef30fadbd92e1c6ab4ed897af356af5e, theorem erdos_1010 at L612). It is linked through the formal_proof attribute on Erdos1010.erdos_1010 in /home/user/math0/lean/.lake/packages/formal_conjectures/FormalConjectures/ErdosProblems/1010.lean. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:erdos1010-erdos-1010-variants-rademacher, + author = {{math0}}, + title = {{Rademacher's theorem: ⌊n²/4⌋+1 edges force ⌊n/2⌋ triangles}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1010-erdos-1010-variants-rademacher}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1010-erdos-1010-variants-rademacher/paper.pdf b/results/erdos1010-erdos-1010-variants-rademacher/paper.pdf new file mode 100644 index 0000000..813c834 Binary files /dev/null and b/results/erdos1010-erdos-1010-variants-rademacher/paper.pdf differ diff --git a/results/erdos1010-erdos-1010-variants-rademacher/paper.tex b/results/erdos1010-erdos-1010-variants-rademacher/paper.tex new file mode 100644 index 0000000..7710f12 --- /dev/null +++ b/results/erdos1010-erdos-1010-variants-rademacher/paper.tex @@ -0,0 +1,504 @@ +% math0 manuscript template. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\small, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +% listings does not handle multi-byte UTF-8 input; map the characters used below. +\lstset{literate={∀}{{$\forall$}}1 {ℕ}{{$\mathbb{N}$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 + {·}{{$\cdot$}}1 {⊆}{{$\subseteq$}}1, keepspaces=true, basicstyle=\ttfamily\footnotesize} +\setlength{\emergencystretch}{3em} +\newcommand{\floor}[1]{\left\lfloor #1\right\rfloor} +\newcommand{\Tri}{\mathcal{T}} +\newcommand{\adj}{\sim} +\newcommand{\lean}[1]{\texttt{#1}} + +\title[Rademacher's theorem in Lean 4]{Graphs with $\lfloor n^2/4\rfloor+1$ edges contain at least $\lfloor n/2\rfloor$ triangles: a Lean~4 proof of Rademacher's theorem} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 17, 2026} + +\begin{document} +\begin{abstract} +We give a complete, self-contained proof of Rademacher's theorem: every simple graph on $n$ +vertices with exactly $\lfloor n^2/4\rfloor+1$ edges contains at least $\lfloor n/2\rfloor$ +triangles. The proof is a strong induction over vertex subsets. It derives Mantel's theorem +along the way and splits on the degree sums along the edges of a triangle. The result is +classical. It is the case $t=1$ of Erdős Problem~\#1010, whose general form was proved by +Lovász--Simonovits and by Nikiforov--Khadzhiivanov, and a Lean proof of that general form +already exists. Our contribution is therefore an independent formal proof of a known result. It +is verified in Lean~4 with Mathlib against the statement +\texttt{Erdos1010.erdos\_1010.variants.rademacher} of the formal-conjectures repository and uses +only the standard axioms. +\end{abstract} +\maketitle + +\section{Introduction} + +Mantel's theorem~\cite{Mantel} says that a graph on $n$ vertices with more than +$\lfloor n^2/4\rfloor$ edges contains a triangle. The bound is attained by the balanced complete +bipartite graph $K_{\lceil n/2\rceil,\lfloor n/2\rfloor}$. In 1941 Rademacher proved, without +publishing it, that one edge beyond this threshold already forces many triangles: every graph on +$n$ vertices with $\lfloor n^2/4\rfloor+1$ edges contains at least $\lfloor n/2\rfloor$ triangles. +The result first appeared in print, with a short proof, in a paper of Erdős~\cite{Erdos55}; see also~\cite{Erdos62} and the account +in~\cite{LiuPikhurko}. The bound is sharp. Add one edge inside the larger part of +$K_{\lceil n/2\rceil,\lfloor n/2\rfloor}$ (with $n\ge 3$). Every triangle of the resulting graph +contains the added edge, and its third vertex lies in the other part, so there are exactly +$\lfloor n/2\rfloor$ triangles. + +Erdős~\cite{Erdos62} extended Rademacher's theorem: a graph on $n$ vertices with +$\lfloor n^2/4\rfloor+t$ edges contains at least $t\lfloor n/2\rfloor$ triangles whenever $t0$. He asked whether the same holds for all +$t<\lfloor n/2\rfloor$. This is Erdős Problem~\#1010 on the website maintained by +Bloom~\cite{EP1010}. The question was answered affirmatively, independently by Lovász and +Simonovits~\cite{LovaszSimonovits} and by Nikiforov and Khadzhiivanov~\cite{NikiforovKh}. +The more general Erdős--Rademacher problem asks for the minimum number of triangles in a graph of +given order and size. It has a large literature. For large $n$ and edge density bounded away +from $1$, it was solved exactly by Liu, Pikhurko and Staden~\cite{LPS}, whose introduction surveys +the history. + +\subsection*{Formal statements and prior formalization} +The formal-conjectures repository~\cite{FC} formalizes Problem~\#1010 in Lean~4 as +\texttt{Erdos1010.erdos\_1010}. It also records Rademacher's case $t=1$ as a separate statement, +\texttt{Erdos1010.erdos\_1010.variants.rademacher}, which is the statement proved here. Both are +tagged \texttt{research solved}. The upstream file attaches a \texttt{formal\_proof} link to the +general statement \texttt{erdos\_1010}. The link points to a Lean~4 proof in the repository +\texttt{plby/lean-proofs}~\cite{plby} (file +\nolinkurl{src/latest/ErdosProblems/Erdos1010.lean}, commit \texttt{8822f7d}). That proof covers +every finite vertex type and every $t<\lfloor n/2\rfloor$. Taking $t=1$ gives the present +statement for $n\ge 4$. The remaining cases are trivial (Remark~\ref{rem:small}). The variant +itself carries no \texttt{formal\_proof} attribute upstream, but a formal proof of a statement +that implies it was already available. We therefore do not claim a first formalization. + +What this note adds is an independent machine-checked proof of the variant, stated exactly as +upstream. The proof is a short, self-contained double induction and needs about 330 lines of +Lean. According to its header, the existing development uses maximum-cut charge bounds and a +reduction for odd orders. The argument formalized here is elementary, and we make no claim that it +is new as a piece of mathematics. Its first half is the standard inductive proof of Mantel's +theorem. + +\section{Statement} + +All graphs are finite and simple. For a graph $G$ we write $u\adj v$ when $u$ and $v$ are +adjacent, $e(G)$ for the number of edges, and $t(G)$ for the number of triangles, i.e.\ of +$3$-element vertex sets that span a complete graph. + +\begin{theorem}[Rademacher]\label{thm:main} +Let $n\ge 0$ and let $G$ be a simple graph on the vertex set $\{0,\dots,n-1\}$ with +$e(G)=\lfloor n^2/4\rfloor+1$. Then $t(G)\ge\lfloor n/2\rfloor$. +\end{theorem} + +The upstream statement is copied below verbatim from the file +\nolinkurl{FormalConjectures/ErdosProblems/1010.lean} of formal-conjectures at commit +\texttt{c77fdd4}. It sits inside \lean{namespace Erdos1010}, with \lean{open SimpleGraph} in +effect: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +open scoped Classical in +/-- +Rademacher proved that every graph on $n$ vertices with $\lfloor n^2/4\rfloor+1$ edges contains at +least $\lfloor n/2\rfloor$ triangles. +-/ +@[category research solved, AMS 5] +theorem erdos_1010.variants.rademacher : ∀ n : ℕ, ∀ G : SimpleGraph (Fin n), + G.edgeFinset.card = n ^ 2 / 4 + 1 → n / 2 ≤ (G.cliqueFinset 3).card := by + sorry +\end{lstlisting} +Here \lean{n \textasciicircum{} 2 / 4} and \lean{n / 2} use natural-number division, so they equal +$\lfloor n^2/4\rfloor$ and $\lfloor n/2\rfloor$. The finset \lean{G.cliqueFinset 3} consists of +the $3$-element vertex sets that are cliques, i.e.\ the unordered triangles. The decidability +instances that \lean{edgeFinset} and \lean{cliqueFinset} need come from \lean{open scoped Classical}. +So the formal statement is exactly Theorem~\ref{thm:main}. + +\begin{remark}\label{rem:small} +For $n\le 2$ the hypothesis is impossible, because $e(G)\le\binom n2<\lfloor n^2/4\rfloor+1$. For +$n=3$ it forces $G=K_3$, and then $t(G)=1=\lfloor 3/2\rfloor$. The proof below does not treat +these cases separately. The theorem also holds with ``at least $\lfloor n^2/4\rfloor+1$ edges'', +since deleting edges cannot create triangles. In fact the Lean proof establishes the ``at least'' +form for every vertex subset (Theorem~\ref{thm:strong}). +\end{remark} + +\section{Proof} + +Fix a finite vertex set $V$ and a simple graph $G$ on $V$. All sets below are subsets of $V$. + +\begin{definition}\label{def:notation} +For $S\subseteq V$ and $v\in V$ (not necessarily in $S$) let $[v\adj w]\in\{0,1\}$ be the +adjacency indicator, and define +\[ + d_S(v)=\sum_{w\in S}[v\adj w],\qquad D(S)=\sum_{v\in S}d_S(v),\qquad + \Tri(S)=\{U\subseteq S:\ U \text{ is a triangle of } G\}. +\] +So $d_S(v)=|N(v)\cap S|$ and $D(S)=2e(G[S])$. In Lean these are \lean{dg}, \lean{D} and +\lean{tri}; \lean{tri G S} is \lean{(G.cliqueFinset 3).filter (· ⊆ S)}. +\end{definition} + +We prove the following stronger statement. It is the Lean lemma \lean{main}. + +\begin{theorem}\label{thm:strong} +For every $S\subseteq V$, if $D(S)\ge 2\bigl(\lfloor |S|^2/4\rfloor+1\bigr)$, then +$|\Tri(S)|\ge\lfloor |S|/2\rfloor$. +\end{theorem} + +\subsection{Bookkeeping lemmas} + +\begin{lemma}[\lean{dg\_erase}, \lean{D\_erase}]\label{lem:erase} +Let $x\in S$. For every $v\in V$, $d_S(v)=[v\adj x]+d_{S\setminus x}(v)$. Moreover +$D(S)=D(S\setminus x)+2d_S(x)$. +\end{lemma} +\begin{proof} +The first identity splits off the term $w=x$. For the second, split off $v=x$ in $D(S)$ and apply +the first identity to the remaining terms: +\[ + D(S)=d_S(x)+\sum_{v\in S\setminus x}\bigl([x\adj v]+d_{S\setminus x}(v)\bigr) + =d_S(x)+d_{S\setminus x}(x)+D(S\setminus x). +\] +Here we used the symmetry $[v\adj x]=[x\adj v]$. Finally $d_{S\setminus x}(x)=d_S(x)$, because +$[x\adj x]=0$. +\end{proof} + +\begin{lemma}[\lean{D\_erase\_two}]\label{lem:erase2} +If $x,y\in S$ and $x\adj y$, then $D(S)+2=D(S\setminus\{x,y\})+2d_S(x)+2d_S(y)$. +\end{lemma} +\begin{proof} +We have $y\in S\setminus x$ since $x\ne y$. Apply Lemma~\ref{lem:erase} twice: +$D(S)=D(S\setminus\{x,y\})+2d_{S\setminus x}(y)+2d_S(x)$. Also +$d_S(y)=[y\adj x]+d_{S\setminus x}(y)=1+d_{S\setminus x}(y)$. +\end{proof} + +\begin{lemma}[\lean{sq\_div\_four}]\label{lem:arith} +For every $M\in\mathbb N$, $\lfloor (M+2)^2/4\rfloor=\lfloor M^2/4\rfloor+M+1$. +\end{lemma} +\begin{proof} +$(M+2)^2=M^2+4(M+1)$. +\end{proof} + +\begin{lemma}[\lean{step\_bound}]\label{lem:step} +Let $x,y\in S$ with $x\adj y$ and $d_S(x)+d_S(y)\le|S|$, and suppose +$D(S)\ge2(\lfloor|S|^2/4\rfloor+1)$. Put $S'=S\setminus\{x,y\}$. Then $|S'|=|S|-2$ and +$D(S')\ge 2(\lfloor|S'|^2/4\rfloor+1)$. +\end{lemma} +\begin{proof} +Let $M=|S'|$, so $|S|=M+2$. By Lemmas~\ref{lem:erase2} and~\ref{lem:arith}, +\[ + D(S')=D(S)+2-2\bigl(d_S(x)+d_S(y)\bigr) + \ge 2\bigl(\lfloor M^2/4\rfloor+M+2\bigr)+2-2(M+2)=2\bigl(\lfloor M^2/4\rfloor+1\bigr).\qedhere +\] +\end{proof} + +\begin{lemma}[\lean{exists\_common}]\label{lem:common} +If $x,y\in V$ and $d_S(x)+d_S(y)>|S|$, then some $z\in S$ satisfies $x\adj z$ and $y\adj z$. +\end{lemma} +\begin{proof} +The sets $N(x)\cap S$ and $N(y)\cap S$ are subsets of $S$ whose sizes add up to more than $|S|$. +By inclusion--exclusion their intersection is nonempty. +\end{proof} + +\subsection{Mantel's theorem} + +\begin{lemma}[Mantel; \lean{mantel}]\label{lem:mantel} +If $D(S)\ge2(\lfloor|S|^2/4\rfloor+1)$, then there are $x,y,z\in S$ with $x\adj y$, $x\adj z$ +and $y\adj z$. +\end{lemma} +\begin{proof} +We use strong induction on $|S|$. Since $D(S)>0$, $S$ contains an edge $xy$ +(\lean{exists\_adj\_of\_D\_pos}). If $d_S(x)+d_S(y)>|S|$, Lemma~\ref{lem:common} gives a common +neighbour $z\in S$. Otherwise Lemma~\ref{lem:step} shows that $S\setminus\{x,y\}$ satisfies the +hypothesis. Since it is smaller than $S$, the induction hypothesis gives a triangle inside it, +and hence inside $S$. +\end{proof} + +The three vertices are automatically distinct, because $G$ has no loops. So $\{x,y,z\}\in\Tri(S)$ +(\lean{mem\_tri}). + +\subsection{The two cases} + +Let $N=|S|$ and let $xyz$ be a triangle in $S$. + +\begin{lemma}[Case 1; \lean{case\_one}]\label{lem:case1} +Suppose $D(S)\ge2(\lfloor N^2/4\rfloor+1)$ and $d_S(x)+d_S(y)\le N$. Put $S'=S\setminus\{x,y\}$ +and suppose Theorem~\ref{thm:strong} holds for $S'$. Then $|\Tri(S)|\ge\lfloor N/2\rfloor$. +\end{lemma} +\begin{proof} +By Lemma~\ref{lem:step}, $S'$ satisfies the hypothesis of Theorem~\ref{thm:strong} and +$|S'|=N-2$, so $|\Tri(S')|\ge\lfloor (N-2)/2\rfloor$. Every triangle in $S'$ is a triangle in $S$ +(\lean{tri\_mono}). The triangle $\{x,y,z\}$ lies in $\Tri(S)$ but not in $\Tri(S')$, because +$x\notin S'$. Hence $|\Tri(S)|\ge\lfloor (N-2)/2\rfloor+1=\lfloor N/2\rfloor$. The last equality +uses $N\ge2$, which holds because $S$ contains the triangle $\{x,y,z\}$. +\end{proof} + +\begin{lemma}[Case 2; \lean{case\_two}]\label{lem:case2} +Suppose $d_S(x)+d_S(y)>N$, $d_S(y)+d_S(z)>N$ and $d_S(x)+d_S(z)>N$. Then +$|\Tri(S)|\ge\lfloor N/2\rfloor$. +\end{lemma} +No assumption on the number of edges is needed here. +\begin{proof} +Let $R=S\setminus\{x,y,z\}$, so $|R|=N-3$. Each of $x,y,z$ is adjacent to the other two and not +to itself. So three applications of Lemma~\ref{lem:erase} give +\begin{equation}\label{eq:dR} + d_S(x)=2+d_R(x),\qquad d_S(y)=2+d_R(y),\qquad d_S(z)=2+d_R(z). +\end{equation} +Index the three edges of the triangle by $i\in\{0,1,2\}$ as $e_0=\{x,y\}$, $e_1=\{y,z\}$, +$e_2=\{x,z\}$. In Lean, $e_i=\{p_i,r_i\}$ with $p=(x,y,x)$ and $r=(y,z,z)$. Let +\[ + P=\{(w,i)\in R\times\{0,1,2\}:\ w \text{ is adjacent to both endpoints of } e_i\}, + \qquad f(w,i)=e_i\cup\{w\}. +\] + +\emph{Counting $P$.} Fix $w\in R$ and let $k_w=[x\adj w]+[y\adj w]+[z\adj w]\in\{0,1,2,3\}$. The +three edges $e_i$ are the three pairs of vertices from $\{x,y,z\}$. So the number of $i$ with +$(w,i)\in P$ equals $\binom{k_w}{2}$, and $k_w\le\binom{k_w}{2}+1$ for $k_w\le3$. Summing over +$w\in R$ gives +\begin{equation}\label{eq:P} + d_R(x)+d_R(y)+d_R(z)\le|P|+|R|. +\end{equation} +In Lean this is \lean{sum\_le\_sum} followed by a case split over the eight adjacency patterns of +$w$ with $x,y,z$. + +\emph{Injectivity.} Each $f(w,i)$ is a triangle in $S$. Its vertices lie in $S$, $e_i$ is an edge, +and $w$ is adjacent to both ends of $e_i$. The map $f$ is injective on $P$. Indeed, suppose +$f(w,i)=f(w',i')$. Then $w$ is the only element of $f(w,i)$ outside $\{x,y,z\}$, so $w=w'$, and +then $e_i=f(w,i)\cap\{x,y,z\}$ determines $i$. In Lean, $w=w'$ is shown first, and then all nine +pairs $(i,i')$ are checked by comparing which of $x,y,z$ belong to the two sets. Finally +$\{x,y,z\}\notin f(P)$, because every element of $f(P)$ contains a vertex of $R$. Therefore +$\{\{x,y,z\}\}\cup f(P)\subseteq\Tri(S)$ is a disjoint union, and +\[ + |\Tri(S)|\ge|P|+1. +\] + +\emph{Conclusion.} By \eqref{eq:P} and \eqref{eq:dR}, +\[ + |\Tri(S)|\ge d_R(x)+d_R(y)+d_R(z)-|R|+1=d_S(x)+d_S(y)+d_S(z)-6-(N-3)+1. +\] +Adding the three hypotheses gives $2(d_S(x)+d_S(y)+d_S(z))\ge3N+3$. So +$2|\Tri(S)|\ge 3N+3-2N-4=N-1$, and since $|\Tri(S)|$ is an integer, +$|\Tri(S)|\ge\lceil (N-1)/2\rceil=\lfloor N/2\rfloor$. In Lean this last step is a single +\lean{omega} call over natural numbers, using the facts above. +\end{proof} + +\subsection{Proof of Theorems~\ref{thm:strong} and~\ref{thm:main}} + +\begin{proof}[Proof of Theorem~\ref{thm:strong}] +We use strong induction on $|S|$ (\lean{main}). Lemma~\ref{lem:mantel} gives a triangle $xyz$ in +$S$. If one of its edges, say $uv$, has $d_S(u)+d_S(v)\le|S|$, apply Lemma~\ref{lem:case1} to +that edge and the third vertex. The required instance of the theorem for $S\setminus\{u,v\}$ is +the induction hypothesis, since $|S\setminus\{u,v\}|<|S|$ (\lean{card\_erase\_two\_lt}). In Lean the +three edges are handled by three calls to \lean{case\_one} with the vertices permuted. Otherwise +all three degree sums exceed $|S|$, and Lemma~\ref{lem:case2} applies. +\end{proof} + +No separate base case is needed. When $|S|\le 2$ the hypothesis fails. Inside the induction this +is visible because Lemma~\ref{lem:mantel} produces three distinct vertices of $S$. + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +Take $V=\{0,\dots,n-1\}$ and $S=V$. By the handshake lemma (Mathlib's +\lean{sum\_degrees\_eq\_twice\_card\_edges}; Lean lemma \lean{D\_univ}), $D(V)=2e(G)=2(\lfloor +n^2/4\rfloor+1)$. So Theorem~\ref{thm:strong} gives $|\Tri(V)|\ge\lfloor n/2\rfloor$, and +$\Tri(V)$ is the set of all triangles of $G$. +\end{proof} + +\section{Machine verification} + +\subsection*{Files and declarations} +The proof is in the file +\begin{center} +\nolinkurl{lean/Math0/ErdosProblems/Erdos1010_erdos_1010_variants_rademacher.lean} +\end{center} +of the math0 repository (\url{https://github.com/Foundation-0/math0}), in namespace +\lean{Math0.Erdos1010}. It has 333 lines. The main theorem is stated by reference to the upstream +type: +\begin{lstlisting} +theorem erdos_1010_rademacher : type_of% @Erdos1010.erdos_1010.variants.rademacher := by + intro n G h + classical + have key := main G _ (univ : Finset (Fin n)) rfl (by rw [D_univ, h]; simp) + simpa [tri] using key + +end Math0.Erdos1010 + +#math0_proves Math0.Erdos1010.erdos_1010_rademacher Erdos1010.erdos_1010.variants.rademacher +\end{lstlisting} +The auxiliary development is stated for an arbitrary \lean{Fintype V} with decidable equality and +decidable adjacency. It is instantiated at \lean{Fin n} with the classical instances of the +upstream statement. The correspondence with the text is: Definition~\ref{def:notation}: +\lean{ind}, \lean{dg}, \lean{D}, \lean{tri}; Lemma~\ref{lem:erase}: \lean{dg\_erase}, +\lean{D\_erase}; Lemma~\ref{lem:erase2}: \lean{D\_erase\_two}; Lemma~\ref{lem:arith}: +\lean{sq\_div\_four}; Lemma~\ref{lem:step}: \lean{step\_bound}; Lemma~\ref{lem:common}: +\lean{exists\_common} (with \lean{dg\_eq\_card}); Lemma~\ref{lem:mantel}: \lean{mantel} +(with \lean{exists\_adj\_of\_D\_pos}); Lemmas~\ref{lem:case1} and~\ref{lem:case2}: +\lean{case\_one}, \lean{case\_two} (with \lean{mem\_tri}, \lean{tri\_mono}); +Theorem~\ref{thm:strong}: \lean{main}; the handshake step: \lean{D\_univ}. The proof involves no +large finite computation. The only case analyses are the eight adjacency patterns in~\eqref{eq:P} +and the nine pairs $(i,i')$ in the injectivity argument. Both are discharged by \lean{by\_cases}, +\lean{fin\_cases} and \lean{simp} and are checked by the kernel like any other proof term. The +file contains no \lean{sorry}, \lean{native\_decide}, \lean{axiom} or \lean{set\_option}. + +\subsection*{Audit} +The last command of the file, \lean{\#math0\_proves}, is defined in +\nolinkurl{lean/Math0/Audit.lean}. It fails the build unless the following hold. +\begin{enumerate} +\item The type of \lean{Math0.Erdos1010.erdos\_1010\_rademacher} is syntactically identical to the +type of the upstream declaration \lean{Erdos1010.erdos\_1010.variants.rademacher}. The comparison +ignores metadata annotations only: no unfolding and no definitional equality. The universe +parameters must also agree. +\item The theorem depends on no axioms beyond \lean{propext}, \lean{Classical.choice} and +\lean{Quot.sound}. This is computed with Lean's \lean{collectAxioms}. It rules out +\lean{sorryAx}, the axioms behind \lean{native\_decide}, and custom axioms. +\end{enumerate} +On compilation the file reports: +\begin{lstlisting}[language={},basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Erdos1010.erdos_1010_rademacher' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Erdos1010.erdos_1010_rademacher' proves 'Erdos1010.erdos_1010.variants.rademacher' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +The toolchain is Lean~4~\cite{Lean4} at version \texttt{v4.33.1} with Mathlib~\cite{mathlib} at version \texttt{v4.33.1}. The upstream statements come +from formal-conjectures at commit \texttt{c77fdd446d23539302aa73bcfae4a9fa962b8382} +(\texttt{c77fdd4}), pinned in \nolinkurl{lean/lakefile.toml}. To reproduce, run +\nolinkurl{scripts/verify.sh} from a checkout of the repository with \texttt{elan} installed. It +fetches the Mathlib cache, builds every result with \texttt{lake build}, checks that the +formal-conjectures and Mathlib package checkouts have no local modifications, and reports the +number of statement checks that passed. To check this file alone, run the following in the +\texttt{lean} directory. It takes well under a minute once the dependencies are built. +\begin{lstlisting}[language={}] +lake env lean Math0/ErdosProblems/Erdos1010_erdos_1010_variants_rademacher.lean +\end{lstlisting} + +\begin{thebibliography}{10} + +\bibitem{EP1010} +T.~F. Bloom, \emph{Erdős Problem \#1010}, +\url{https://www.erdosproblems.com/1010}, accessed 2026-10-17. + +\bibitem{Erdos55} +P.~Erdős, \emph{Some theorems on graphs}, Riveon Lematematika \textbf{9} (1955), 13--17. + +\bibitem{Erdos62} +P.~Erdős, \emph{On a theorem of {R}ademacher--{T}urán}, Illinois J. Math. \textbf{6} (1962), +122--127. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horváth, Y.~Dillies, C.~Sönne, E.~Wieser, F.~Zhang, +T.~Hubert, B.~Agüera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving +benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: +\url{https://github.com/google-deepmind/formal-conjectures}, commit \texttt{c77fdd4}. + +\bibitem{LiuPikhurko} +X.~Liu and O.~Pikhurko, \emph{A note on extremal constructions for the +{E}rdős--{R}ademacher problem}, Combin. Probab. Comput. \textbf{34} (2025), no.~1, 52--62; +arXiv:2311.18753. + +\bibitem{LPS} +H.~Liu, O.~Pikhurko, and K.~Staden, \emph{The exact minimum number of triangles in graphs with +given order and size}, Forum Math. Pi \textbf{8} (2020), e8. + +\bibitem{LovaszSimonovits} +L.~Lovász and M.~Simonovits, \emph{On the number of complete subgraphs of a graph}, in: +Proceedings of the Fifth British Combinatorial Conference (Aberdeen, 1975), Congressus +Numerantium XV, Utilitas Math., Winnipeg, 1976, pp.~431--441. + +\bibitem{Mantel} +W.~Mantel, \emph{Problem 28}, Wiskundige Opgaven \textbf{10} (1907), 60--61. + +\bibitem{mathlib} +The mathlib Community, \emph{The {L}ean mathematical library}, in: Proceedings of the 9th ACM +SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, +pp.~367--381. + +\bibitem{Lean4} +L.~de~Moura and S.~Ullrich, \emph{The {L}ean 4 theorem prover and programming language}, in: +Automated Deduction -- CADE 28, Lecture Notes in Computer Science, vol.~12699, Springer, 2021, +pp.~625--635. + +\bibitem{NikiforovKh} +V.~S. Nikiforov and N.~G. Khadzhiivanov, \emph{Solution of the problem of {P}. {E}rdős on the +number of triangles in graphs with $n$ vertices and $[n^2/4]+l$ edges}, C. R. Acad. Bulgare Sci. +\textbf{34} (1981), no.~7, 969--970. + +\bibitem{plby} +\texttt{plby/lean-proofs}, \nolinkurl{src/latest/ErdosProblems/Erdos1010.lean}, theorem +\texttt{erdos\_1010}, commit \texttt{8822f7ddef30fadbd92e1c6ab4ed897af356af5e}, +\url{https://github.com/plby/lean-proofs}, accessed 2026-10-17. + +\end{thebibliography} + +\end{document} diff --git a/results/erdos1026-erdos-1026-variants-upper-bound/README.md b/results/erdos1026-erdos-1026-variants-upper-bound/README.md new file mode 100644 index 0000000..d581055 --- /dev/null +++ b/results/erdos1026-erdos-1026-variants-upper-bound/README.md @@ -0,0 +1,36 @@ +# Erdős 1026: no constant c > 1 is admissible (Cambie's construction) + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Combinatorics +**Source problem:** Erdős Problem #1026 +**Date:** 2026-10-17 + +## Result + +Call c admissible if for every ε > 0, for all sufficiently large n, every sequence x_1,...,x_n of distinct positive reals has a monotone (non-decreasing or non-increasing) subsequence whose sum is at least (c − ε)/√n · Σ_i x_i. Then every admissible constant satisfies c ≤ 1, i.e. 1 is an upper bound of the set of admissible constants. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1026_erdos_1026_variants_upper_bound.lean`](../../lean/Math0/ErdosProblems/Erdos1026_erdos_1026_variants_upper_bound.lean) proves the upstream statement [`Erdos1026.erdos_1026.variants.upper_bound`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1026.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +- Erdős, "Some unsolved problems in graph theory and combinatorial analysis" (1971) [Er71]: the original problem. +- erdosproblems.com/1026 forum: van Doorn's precise formulation, and Cambie's construction showing c ≤ 1. +- Tidor, Wang and Yang, arXiv:1608.04153 [TWY16], and Wagner, J. Graph Theory 2017 [Wa17]: the weighted Erdős–Szekeres theorem, which gives c ≥ 1 and hence c = 1. +- Hanani 1957 [Ha57]: c ≥ 1/√2. +- Steele 1995 [St95]. +- Existing Lean formalization by Aristotle and Boris Alexeev: https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1026.lean. Its theorem `c_opt_eq_k_div_sq_add_a` gives the exact c_opt(n) for all n, which implies the upper bound. erdosproblems problems.yaml lists the status as "solved (Lean)", last updated 2025-12-12. +- Background: Tao's blog post https://terrytao.wordpress.com/2025/12/08/the-story-of-erdos-problem-126/. + +## Citation + +```bibtex +@misc{math0:erdos1026-erdos-1026-variants-upper-bound, + author = {{math0}}, + title = {{Erdős 1026: no constant c > 1 is admissible (Cambie's construction)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1026-erdos-1026-variants-upper-bound}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1048-erdos-1048-variants-diam-ge-two-is-best/README.md b/results/erdos1048-erdos-1048-variants-diam-ge-two-is-best/README.md new file mode 100644 index 0000000..9223b30 --- /dev/null +++ b/results/erdos1048-erdos-1048-variants-diam-ge-two-is-best/README.md @@ -0,0 +1,33 @@ +# Erdős 1048: the component of {|zⁿ| ≤ 1} containing 0 has diameter exactly 2 + +**Classification:** First formal proof of a known result +**Area:** Complex analysis +**Source problem:** Erdős Problem #1048 +**Date:** 2026-10-17 + +## Result + +For every natural number n ≥ 1, the connected component containing 0 of the level set {z ∈ ℂ : |zⁿ| ≤ 1} has (extended) diameter exactly 2. So the Erdős–Herzog–Piranian bound, which says the component containing 0 has diameter ≥ 2 when all roots lie in |z| ≤ r ≤ 1/2, is attained by f(z) = zⁿ. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1048_erdos_1048_variants_diam_ge_two_is_best.lean`](../../lean/Math0/ErdosProblems/Erdos1048_erdos_1048_variants_diam_ge_two_is_best.lean) proves the upstream statement [`Erdos1048.erdos_1048.variants.diam_ge_two_is_best`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1048.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +- Erdős, P., Herzog, F. and Piranian, G., "Metric properties of polynomials", J. Analyse Math. 6 (1958), 125–148. This is the source of the diam ≥ 2 bound for 0 ≤ r ≤ 1/2 and of the remark that zⁿ shows it is sharp. +- Pommerenke, Ch., "On metric properties of complex polynomials", Michigan Math. J. (1961), 97–115. +- erdosproblems.com/1048: status "disproved (Lean)" as of 2026-01-27. +- The existing Lean proof at https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1048.lean (Aristotle / Boris Alexeev) covers only the main disproof, `not_erdos_1048`, through Pommerenke's zⁿ − rⁿ example with r > 1. It does not prove `erdos_1048.variants.diam_ge_two_is_best`. + +## Citation + +```bibtex +@misc{math0:erdos1048-erdos-1048-variants-diam-ge-two-is-best, + author = {{math0}}, + title = {{Erdős 1048: the component of {|zⁿ| ≤ 1} containing 0 has diameter exactly 2}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1048-erdos-1048-variants-diam-ge-two-is-best}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1098-erdos-1098-variants-upper-bound/README.md b/results/erdos1098-erdos-1098-variants-upper-bound/README.md new file mode 100644 index 0000000..221550d --- /dev/null +++ b/results/erdos1098-erdos-1098-variants-upper-bound/README.md @@ -0,0 +1,30 @@ +# Cliques in the non-commuting graph have at most [G : Z(G)] vertices + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Combinatorics, Group theory +**Source problem:** Erdős Problem #1098 +**Date:** 2026-10-17 + +## Result + +Let G be a group and let Γ(G) be its non-commuting graph: the vertices are the elements of G, and g and h are adjacent iff gh ≠ hg. If the centre Z(G) has finite index n = [G : Z(G)], then Γ(G) contains no complete subgraph on n + 1 vertices (Lean: `(nonCommutingGraph G).CliqueFree ((Subgroup.center G).index + 1)` under `[(Subgroup.center G).FiniteIndex]`). This is the remark Neumann (1976) made in answering Erdős Problem 1098. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1098_erdos_1098_variants_upper_bound.lean`](../../lean/Math0/ErdosProblems/Erdos1098_erdos_1098_variants_upper_bound.lean) proves the upstream statement [`Erdos1098.erdos_1098.variants.upper_bound`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1098.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +B. H. Neumann, "A problem of Paul Erdős on groups", J. Austral. Math. Soc. Ser. A 21 (1976), 467–472. It proves that Γ(G) has no infinite clique iff [G:Z(G)] < ∞, and remarks that a clique has at most [G:Z(G)] vertices. erdosproblems.com/1098 lists the problem as "proved (Lean)" (problems.yaml, 2026-05-02). The existing Lean formalization is plby/lean-proofs, src/v4.29.1/ErdosProblems/Erdos1098.lean, which is linked as formal_proof on upstream erdos_1098. Its theorem `erdos1098` contains the same coset-injection bound S.card ≤ Nat.card (G ⧸ center G) for pairwise non-commuting finsets under finite index, and `IsFIZGroup.isPEGroup` uses the same argument. + +## Citation + +```bibtex +@misc{math0:erdos1098-erdos-1098-variants-upper-bound, + author = {{math0}}, + title = {{Cliques in the non-commuting graph have at most [G : Z(G)] vertices}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1098-erdos-1098-variants-upper-bound}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1119-erdos-1119-variants-erdos-wetzel/README.md b/results/erdos1119-erdos-1119-variants-erdos-wetzel/README.md new file mode 100644 index 0000000..74181d6 --- /dev/null +++ b/results/erdos1119-erdos-1119-variants-erdos-wetzel/README.md @@ -0,0 +1,36 @@ +# Erdős–Wetzel theorem: if ℵ₁ < 𝔠, families of entire functions with countably many values at each point are countable + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Logic, Complex analysis +**Source problem:** Erdős Problem #1119 +**Date:** 2026-10-17 + +## Result + +Assume ℵ₁ < 𝔠. Let F be a set of entire functions ℂ → ℂ such that for every z₀ ∈ ℂ the set of values {f(z₀) : f ∈ F} is countable. Then F is countable. (Formally, the hypothesis ℵ_1 < 𝔠 is stated in an arbitrary universe `Cardinal.{u_1}`.) + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1119_erdos_1119_variants_erdos_wetzel.lean`](../../lean/Math0/ErdosProblems/Erdos1119_erdos_1119_variants_erdos_wetzel.lean) proves the upstream statement [`Erdos1119.erdos_1119.variants.erdos_wetzel`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1119.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +- Erdős, P., "An interpolation problem associated with the continuum hypothesis", Michigan Math. J. 11 (1964), 9–10. This is the original theorem: ¬CH implies the family is countable, and CH gives an uncountable counterexample. +- Hayman, W. K., Research problems in function theory (1974), Problem 2.46. +- Kumar–Shelah, Fund. Math. 2017, and Schilhan–Weinert, J. London Math. Soc. 2024. These give the independence of the general-cardinal problem. +- Earlier formalizations: + - plby/lean-proofs (Boris Alexeev; Codex/GPT), src/latest/ErdosProblems/Erdos1119.lean at commit 8822f7ddef30fadbd92e1c6ab4ed897af356af5e. It proves easy_case and `erdos_1119` (ℵ_1 < 𝔠 → pointwise-countable entire family is countable), and aliases it to `erdos_1119.variants.erdos_wetzel`. + - Collin Yuanjie Ren, Lean proof of the full Wetzel/CH biconditional (github.com/CollinYuanjieRen/awards, jsp-000930-cyr). It is credited in the erdosproblems.com formal_status note, and the formalized state there is "yes". + - L. C. Paulson, "Wetzel's Problem and the Continuum Hypothesis", Isabelle AFP (2022). + +## Citation + +```bibtex +@misc{math0:erdos1119-erdos-1119-variants-erdos-wetzel, + author = {{math0}}, + title = {{Erdős–Wetzel theorem: if ℵ₁ < 𝔠, families of entire functions with countably many values at each point are countable}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1119-erdos-1119-variants-erdos-wetzel}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1121-erdos-1121-variants-higher-dimension/README.md b/results/erdos1121-erdos-1121-variants-higher-dimension/README.md new file mode 100644 index 0000000..0ce5927 --- /dev/null +++ b/results/erdos1121-erdos-1121-variants-higher-dimension/README.md @@ -0,0 +1,30 @@ +# Goodman–Goodman covering theorem for balls in ℝ^d (Erdős 1121, higher-dimensional variant) + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** Erdős Problem #1121 +**Date:** 2026-10-17 + +## Result + +Let d, n be natural numbers, c_1,…,c_n points of ℝ^d and r_1,…,r_n > 0. Suppose that for every nonzero v ∈ ℝ^d and every t ∈ ℝ, if the hyperplane {p : ⟨v,p⟩ = t} meets none of the closed balls B_i = B̄(c_i, r_i), then either ⟨v,c_i⟩ < t for all i or ⟨v,c_i⟩ > t for all i. Then there is z ∈ ℝ^d with ⋃_i B_i ⊆ B̄(z, R), where R = Σ_i r_i. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1121_erdos_1121_variants_higher_dimension.lean`](../../lean/Math0/ErdosProblems/Erdos1121_erdos_1121_variants_higher_dimension.lean) proves the upstream statement [`Erdos1121.erdos_1121.variants.higher_dimension`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1121.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +The result is Goodman, A. W. and Goodman, R. E., "A circle covering theorem", Amer. Math. Monthly 52 (1945), 494–498. The upstream docstring notes that their proof generalises to higher dimensions. Hadwiger, "Nonseparable convex systems", Amer. Math. Monthly 54 (1947), 583–585, extends it to convex bodies. Bezdek and Litvak, "Packing convex bodies by cylinders", Discrete Comput. Geom. (2016), 725–738, give an alternative proof. erdosproblems.com/1121 lists the problem as "proved (Lean)". That refers to the 2D statement, whose existing Lean proof (https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1121.lean, by Aristotle and Amogh Parab) is restricted to EuclideanSpace ℝ (Fin 2). The higher-dimensional variant has no formal_proof link in the pinned upstream or the current upstream main branch. + +## Citation + +```bibtex +@misc{math0:erdos1121-erdos-1121-variants-higher-dimension, + author = {{math0}}, + title = {{Goodman–Goodman covering theorem for balls in ℝ^d (Erdős 1121, higher-dimensional variant)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1121-erdos-1121-variants-higher-dimension}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1136-erdos-1136-variants-mueller/README.md b/results/erdos1136-erdos-1136-variants-mueller/README.md new file mode 100644 index 0000000..efca83e --- /dev/null +++ b/results/erdos1136-erdos-1136-variants-mueller/README.md @@ -0,0 +1,33 @@ +# Müller's set avoids sums equal to powers of two and has density 1/2 (Erdős 1136) + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Number theory +**Source problem:** Erdős Problem #1136 +**Date:** 2026-10-17 + +## Result + +Let M be the set of natural numbers n such that n ≡ 3·2^i (mod 2^{i+2}) for some i ≥ 0. Then (1) no a, b ∈ M (not necessarily distinct) satisfy a + b = 2^k for any k ≥ 0, and (2) M has natural density 1/2: #(M ∩ [0,b)) / b → 1/2 as b → ∞. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_mueller.lean`](../../lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_mueller.lean) proves the upstream statement [`Erdos1136.erdos_1136.variants.mueller`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1136.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +The result is H. Müller, "Über ein additiv-zahlentheoretisches Problem von P. Erdős", Mitt. Math. Ges. Hamburg (2011), 75-78. erdosproblems.com/1136 lists the status "proved (Lean)" (2026-04-19). Earlier Lean proofs exist: +- plby/lean-proofs src/v4.29.1/ErdosProblems/Erdos1136.lean (by Aristotle, L. Luccioli and W. van Doorn), which proves the same set is sum-free (`A_sumfree`) and has density 1/2 (`A_density_half`). +- Luccioli's gist on live.lean-lang.org. +- Woett/Lean-files ErdosProblem1136.lean. + +## Citation + +```bibtex +@misc{math0:erdos1136-erdos-1136-variants-mueller, + author = {{math0}}, + title = {{Müller's set avoids sums equal to powers of two and has density 1/2 (Erdős 1136)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1136-erdos-1136-variants-mueller}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1136-erdos-1136-variants-multiples-of-three/README.md b/results/erdos1136-erdos-1136-variants-multiples-of-three/README.md new file mode 100644 index 0000000..c135758 --- /dev/null +++ b/results/erdos1136-erdos-1136-variants-multiples-of-three/README.md @@ -0,0 +1,30 @@ +# The multiples of 3 avoid sums equal to powers of two and have density 1/3 + +**Classification:** First formal proof of a known result +**Area:** Number theory +**Source problem:** Erdős Problem #1136 +**Date:** 2026-10-17 + +## Result + +Let A = {n ∈ ℕ : 3 ∣ n}. (i) For all a, b ∈ A (not necessarily distinct) and all k ≥ 0, a + b ≠ 2^k. (ii) A has natural density 1/3: the quantity #(A ∩ [0, b)) / #[0, b) tends to 1/3 as b → ∞. This is the trivial benchmark in Erdős Problem 1136, which asks for a set with lower density greater than 1/3 and the same avoidance property. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_multiples_of_three.lean`](../../lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_multiples_of_three.lean) proves the upstream statement [`Erdos1136.erdos_1136.variants.multiples_of_three`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1136.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Erdős Problem 1136 (erdosproblems.com/1136; problems.yaml gives status "proved (Lean)", last updated 2026-04-19). H. Müller, "Über ein additiv-zahlentheoretisches Problem von P. Erdős", Mitt. Math. Ges. Hamburg (2011), 75-78: Müller's set has density 1/2, and density 1/2 is optimal. The density-1/3 example using multiples of 3 is a folklore fact noted as trivial in the upstream docstring. The existing Lean proof at plby/lean-proofs (src/v4.29.1/ErdosProblems/Erdos1136.lean) formalizes the main problem, Müller's set and the upper bound, but not the multiples-of-3 variant. + +## Citation + +```bibtex +@misc{math0:erdos1136-erdos-1136-variants-multiples-of-three, + author = {{math0}}, + title = {{The multiples of 3 avoid sums equal to powers of two and have density 1/3}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1136-erdos-1136-variants-multiples-of-three}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1136-erdos-1136-variants-upper-bound/README.md b/results/erdos1136-erdos-1136-variants-upper-bound/README.md new file mode 100644 index 0000000..4d40ac3 --- /dev/null +++ b/results/erdos1136-erdos-1136-variants-upper-bound/README.md @@ -0,0 +1,30 @@ +# Sets avoiding sums equal to powers of two have lower density at most 1/2 (Müller) + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Number theory +**Source problem:** Erdős Problem #1136 +**Date:** 2026-10-17 + +## Result + +Let A ⊆ ℕ be such that a + b ≠ 2^k for all a, b ∈ A (not necessarily distinct) and all k ≥ 0. Then the lower natural density of A, liminf_{N→∞} |A ∩ [0, N)| / N, is at most 1/2. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_upper_bound.lean`](../../lean/Math0/ErdosProblems/Erdos1136_erdos_1136_variants_upper_bound.lean) proves the upstream statement [`Erdos1136.erdos_1136.variants.upper_bound`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1136.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Müller, Helmut, "Über ein additiv-zahlentheoretisches Problem von P. Erdős", Mitt. Math. Ges. Hamburg (2011), 75-78. Müller proves the existence of a set with density 1/2 and that every such set has density at most 1/2. erdosproblems.com/1136 has status "proved (Lean)" in problems.yaml (formal_status Lean, 2026-04-19). The existing Lean proof is linked from the upstream formal_proof attribute: https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1136.lean (Aristotle, Lorenzo Luccioli, Wouter van Doorn). It contains `sumfree_upperDensity_le_half`, an upper density ≤ 1/2 bound for any power-of-two-sum-free S ⊆ ℕ, and `main_result`. Related formalizations are Luccioli's gist (mathlib v4.28.0) and https://github.com/Woett/Lean-files/blob/main/ErdosProblem1136.lean. + +## Citation + +```bibtex +@misc{math0:erdos1136-erdos-1136-variants-upper-bound, + author = {{math0}}, + title = {{Sets avoiding sums equal to powers of two have lower density at most 1/2 (Müller)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1136-erdos-1136-variants-upper-bound}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1148-erdos-1148-variants-weaker/README.md b/results/erdos1148-erdos-1148-variants-weaker/README.md new file mode 100644 index 0000000..8cd386c --- /dev/null +++ b/results/erdos1148-erdos-1148-variants-weaker/README.md @@ -0,0 +1,30 @@ +# Every n is x² + y² − z² with max(x², y², z²) ≤ n + 2√n + +**Classification:** First formal proof of a known result +**Area:** Number theory +**Source problem:** Erdős Problem #1148 +**Date:** 2026-10-17 + +## Result + +For every natural number n there exist natural numbers x, y, z with n = x² + y² − z² (the subtraction is truncated subtraction on ℕ) and x², y², z² ≤ n + 2√n, where √n is the real square root. This is the relaxed form of Erdős Problem 1148, which [Va99] calls "obvious". + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1148_erdos_1148_variants_weaker.lean`](../../lean/Math0/ErdosProblems/Erdos1148_erdos_1148_variants_weaker.lean) proves the upstream statement [`Erdos1148.erdos_1148.variants.weaker`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1148.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +[Va99] "Some of Paul's favorite problems", the booklet for the conference "Paul Erdős and his mathematics" (Budapest, 1999), calls the n + 2√n relaxation "obvious". The main Erdős 1148 problem (bound ≤ n, for large n) was proved by Chojecki [Ch26], "Bounded Representations by x²+y²−z²" (2026). Its Lean proof is plby/lean-proofs src/latest/ErdosProblems/Erdos1148.lean at commit 8822f7d, and it covers only the main theorem for large n, not the weaker variant for every n. In erdosproblems.com's problems.yaml, problem 1148 has status "proved (Lean)" and OEIS entries A390380 and A393168. The upstream formal-conjectures file FormalConjectures/ErdosProblems/1148.lean has a formal_proof link on erdos_1148 only. + +## Citation + +```bibtex +@misc{math0:erdos1148-erdos-1148-variants-weaker, + author = {{math0}}, + title = {{Every n is x² + y² − z² with max(x², y², z²) ≤ n + 2√n}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1148-erdos-1148-variants-weaker}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1180-erdos-1180-variants-optimal/README.md b/results/erdos1180-erdos-1180-variants-optimal/README.md new file mode 100644 index 0000000..1356d45 --- /dev/null +++ b/results/erdos1180-erdos-1180-variants-optimal/README.md @@ -0,0 +1,38 @@ +# Erdős 1180, "optimal" variant: false as stated (C_ε grows exponentially in 1/ε, because the constant must cover all primes) + +**Classification:** Misformalization found (upstream statement does not match the problem) +**Area:** Number theory +**Source problem:** Erdős Problem #1180 +**Date:** 2026-10-17 + +## Result + +For ε > 0 let C(ε) be the least natural number C such that for every prime p and every residue a mod p there is a multiset s of integers n with 1 ≤ n ≤ p^ε and gcd(n,p)=1, |s| ≤ C, and Σ_{n∈s} n^{-1} ≡ a (mod p). If no such C exists, C(ε) = 0 (Lean's sInf ∅ = 0). The upstream statement says: for every δ > 0, C(ε) ≤ ε^{-(1+δ)} for all sufficiently small ε > 0. We prove the negation: there is a δ > 0 (δ = 1 works) such that C(ε) > ε^{-2} for arbitrarily small ε > 0, namely ε = 1/(m+1) for every large m. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1180_erdos_1180_variants_optimal.lean`](../../lean/Math0/ErdosProblems/Erdos1180_erdos_1180_variants_optimal.lean) refutes (proves the negation of) the upstream statement [`Erdos1180.erdos_1180.variants.optimal`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1180.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research open`). Its final command `#math0_refutes` checks that our theorem's type is syntactically identical to the upstream statement (negated) and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Erdős and Graham, Old and new problems and results in combinatorial number theory (1980), the source of the question. Shparlinski, Arch. Math. (Basel) 2002, pp. 445–448: at most ε⁻³ summands for all p ≥ P(ε). Glibichuk, Mat. Zametki 2006, pp. 384–395: at most ε⁻² summands for all p ≥ P(ε); his covering lemma is the 8XY = F_p result for antisymmetric Y with |X||Y| > p. erdosproblems.com/1180 is marked proved, and its remark that "it may be that C_ε ≤ ε^{-1-o(1)}" is meant for large primes. The upstream formal-conjectures file 1180.lean already notes, in the docstring of variants.shparlinski, that no polynomial bound can hold for all primes. Upstream also links Lean proofs of the main statement and the shparlinski, glibichuk and lower_bound variants (plby/lean-proofs and linrock/math-proofs). The Glibichuk part of this file is adapted from plby/lean-proofs. The "optimal" variant has no prior formal resolution I know of. Its falsity as formalized follows from the small-prime obstruction that the upstream file itself states. - erdosproblems.com/1180. The ε^{-1-o(1)} question is listed there as still open. The page credits Shparlinski with ≪ε^{-3}, Glibichuk with ≪ε^{-2}, and Croot with (log p)^{3+o(1)}. +- [Sh02] I. E. Shparlinski, "On a question of Erdős and Graham", Arch. Math. (Basel) 78 (2002), 445–448. +- [Gl06] A. A. Glibichuk, Mat. Zametki 79 (2006), 384–395 (mathnet.ru mzm2708): N = 8([1/ε+1/2]+1)^2 summands for sufficiently large p. + +(Abridged; the manuscript discusses the literature in full.) + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:erdos1180-erdos-1180-variants-optimal, + author = {{math0}}, + title = {{Erdős 1180, "optimal" variant: false as stated (C_ε grows exponentially in 1/ε, because the constant must cover all primes)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1180-erdos-1180-variants-optimal}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1180-erdos-1180-variants-optimal/paper.pdf b/results/erdos1180-erdos-1180-variants-optimal/paper.pdf new file mode 100644 index 0000000..50925bc Binary files /dev/null and b/results/erdos1180-erdos-1180-variants-optimal/paper.pdf differ diff --git a/results/erdos1180-erdos-1180-variants-optimal/paper.tex b/results/erdos1180-erdos-1180-variants-optimal/paper.tex new file mode 100644 index 0000000..19fe567 --- /dev/null +++ b/results/erdos1180-erdos-1180-variants-optimal/paper.tex @@ -0,0 +1,383 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,sorry}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, aboveskip=6pt, belowskip=6pt} +% Unicode inside listings (pdfLaTeX listings cannot read multibyte characters directly). +\lstset{keepspaces=true, literate={ℕ}{{$\mathbb{N}$}}1 {ℝ}{{$\mathbb{R}$}}1 {ε}{{$\varepsilon$}}1 + {δ}{{$\delta$}}1 {≤}{{$\le$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {→}{{$\to$}}1 + {↦}{{$\mapsto$}}1 {∧}{{$\wedge$}}1 {¬}{{$\neg$}}1 {∈}{{$\in$}}1 {⁻}{{$^{-}$}}1 {¹}{{$^{1}$}}1 + {ᶠ}{{$^{\mathsf{f}}$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\R}{\mathbb{R}} +\newcommand{\F}{\mathbb{F}_p} +\newcommand{\eps}{\varepsilon} + +\title[A defect in a formal statement of Erd\H{o}s Problem \#1180]{Small primes force $C_{1/(m+1)}\ge 2^m$: the formal ``optimal'' variant of Erd\H{o}s Problem \#1180 is false} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 17, 2026} + +\begin{document} +\begin{abstract} +For $\eps>0$ let $C_\eps$ be the least $C$ such that, for every prime $p$, every residue modulo $p$ is a sum of at most $C$ inverses $n^{-1}\bmod p$ with $1\le n\le p^\eps$. +The formal-conjectures statement \decl{Erdos1180.erdos_1180.variants.optimal} asserts that for every $\delta>0$ one has $C_\eps\le\eps^{-1-\delta}$ for all small $\eps>0$; we prove it false by showing $C_{1/(m+1)}\ge2^m$ for every $m\ge2$, since for $\eps=1/(m+1)$ and a Bertrand prime $2^m0$, is there a constant $C_\eps$ such that, for every prime $p$, every residue modulo $p$ is a sum of at most $C_\eps$ elements of $\{n^{-1}:1\le n\le p^\eps\}$, where $n^{-1}$ is the inverse of $n$ modulo $p$? + +\subsection*{Known results} +Shparlinski \cite{Sh02} answered the question affirmatively, even with pairwise distinct denominators. +The problem page \cite{EP1180} records the quantitative form $C_\eps\ll\eps^{-3}$ of Shparlinski's result, and Glibichuk's improvement to $\ll\eps^{-2}$ \cite{Gl06}: for every sufficiently large prime $p$ every residue is a sum of $8(\lfloor1/\eps+1/2\rfloor+1)^2$ such inverses. +As in \cite{Gl06}, and as the upstream formal statements record for both bounds, these quantitative bounds concern sufficiently large primes $p\ge P(\eps)$. +The page also records a result of Croot with $(\log p)^{3+o(1)}$ summands, notes that $\gg\eps^{-1}$ summands are trivially necessary, and remarks that ``it may be that $C_\eps\le\eps^{-1-o(1)}$ is possible''. +The main question is thus settled, and the last remark is the open part of the problem. + +\subsection*{The formal statements and prior work} +The formal-conjectures repository \cite{FC} formalizes the problem in \path{FormalConjectures/ErdosProblems/1180.lean}, with $C_\eps$ defined as the least bound valid for \emph{all} primes. +The main statement \decl{erdos_1180} and the variants \decl{shparlinski}, \decl{glibichuk} and \decl{lower_bound} are tagged \emph{solved}, with linked Lean proofs in plby/lean-proofs \cite{plby} and linrock/math-proofs \cite{linrock}; the variant \decl{erdos_1180.variants.optimal}, which asks whether $C_\eps\le\eps^{-1-\delta}$ for every $\delta>0$ and all small $\eps$, is tagged \emph{research open}. +The obstruction used here is known upstream: commit \texttt{377a7b38} (pull request \#6486) \cite{PR6486} restated \decl{shparlinski} and \decl{glibichuk} for large primes only, because no bound on the all-primes constant can be polynomial in $\eps^{-1}$, as $1$ is the only admissible denominator when $p^\eps<2$, and its message notes that ``the audit also flags \texttt{variants.optimal} as questionable for the same reason (it uses the all-primes \texttt{C})'', but leaves that statement unchanged because the problem page reuses $C_\eps$ there without a prime threshold. + +A Lean disproof already exists: linrock/math-proofs \cite{linrock}, at commit \texttt{ba96303b}, proves $\neg$\decl{Erdos1180OptimalConjecture}, a verbatim copy of the upstream statement and its definitions, as \decl{Erdos1180.Palomar.not_erdos_1180_variants_optimal}, together with $2^{1/\eps}\le4C_\eps$. +This work is registered as Palomar entry PALOMAR-2026-10-12-000005 \cite{Palomar}, cited in the upstream file; pull request \#7219 \cite{PR7219} linked it for the three other variants, while \decl{variants.optimal} carries no link at commit \texttt{c77fdd4}. +Our refutation is therefore not the first formal one; it is independent, and it is checked against the upstream declaration itself rather than a copy. +The part of our Lean file that proves \decl{erdos_1180} (Glibichuk's argument, Sections~\ref{sec:glib}--\ref{sec:params}) is adapted, under its Apache-2.0 licence, from plby/lean-proofs \cite{plby}, with lists replaced by multisets. +We classify the result as a \emph{misformalization report}: the formal statement fails because it quantifies over all primes, including those below $2^{1/\eps}$, while the open question concerns large primes. Section~\ref{sec:defect} proposes a corrected statement. + +\section{Statement}\label{sec:statement} + +Throughout, $\N=\{0,1,2,\dots\}$, $\F=\mathbb{Z}/p\mathbb{Z}$, and powers $x^y$ with real exponent are real powers. +Let $\eps\in\R$, let $p$ be a prime and $a\in\F$. +An \emph{$\eps$-representation of $a$} is a finite multiset $s$ of natural numbers such that every $n\in s$ satisfies $1\le n\le p^\eps$ and $\gcd(n,p)=1$ (we call such $n$ \emph{admissible}), and $\sum_{n\in s}n^{-1}=a$ in $\F$, counted with multiplicity. +Let $S_\eps\subseteq\N$ be the set of $C$ such that every $a\in\F$ has an $\eps$-representation of size at most $C$, for every prime $p$, and put $C_\eps=\min S_\eps$ if $S_\eps\ne\emptyset$ and $C_\eps=0$ otherwise. +The upstream statement asserts: +\begin{equation}\label{eq:O} + \forall\delta>0\ \ \exists\eta>0\ \ \forall\eps\in(0,\eta):\quad C_\eps\le\eps^{-(1+\delta)}. +\end{equation} +The definitions and the statement, copied verbatim from \path{FormalConjectures/ErdosProblems/1180.lean} at commit \texttt{c77fdd4} (inside \texttt{namespace Erdos1180}, with \texttt{open Filter}; docstrings of the two definitions omitted), read: +\begin{lstlisting} +def Represents (ε : ℝ) (p : ℕ) (a : ZMod p) (s : Multiset ℕ) : Prop := + (∀ n ∈ s, 1 ≤ n ∧ (n : ℝ) ≤ (p : ℝ) ^ ε ∧ n.Coprime p) ∧ + (s.map fun n : ℕ ↦ (n : ZMod p)⁻¹).sum = a + +noncomputable def C (ε : ℝ) : ℕ := + sInf {C | ∀ p : ℕ, p.Prime → ∀ a : ZMod p, ∃ s : Multiset ℕ, s.card ≤ C ∧ Represents ε p a s} + +/-- Is $C_\epsilon\leq \epsilon^{-1-o(1)}$? -/ +@[category research open, question, AMS 11] +theorem erdos_1180.variants.optimal : ∀ δ : ℝ, 0 < δ → + ∀ᶠ ε : ℝ in nhdsWithin 0 (Set.Ioi 0), (C ε : ℝ) ≤ ε⁻¹ ^ (1 + δ) := by + sorry +\end{lstlisting} +Since \texttt{sInf}~$\emptyset=0$ in $\N$, the filter \texttt{nhdsWithin 0 (Set.Ioi 0)} consists of the sets containing some $(0,\eta)$, and $(\eps^{-1})^{1+\delta}=\eps^{-(1+\delta)}$ for $\eps>0$, the Lean statement is exactly~\eqref{eq:O}. + +\begin{theorem}\label{thm:main} +Statement \eqref{eq:O} is false. In fact it fails for $\delta=1$: $C_{1/(m+1)}>(m+1)^2$ for every $m\ge6$. +\end{theorem} + +In Lean, Theorem~\ref{thm:main} is \decl{Math0.Erdos1180.not_erdos_1180_variants_optimal}, whose type is $\neg$\,\decl{(type_of%}~\decl{@_root_.Erdos1180.erdos_1180.variants.optimal)}, the negation of the upstream statement. +The proof rests on two facts; the first is needed because if $S_\eps$ were empty, then $C_\eps=0$ and the inequality in~\eqref{eq:O} would hold trivially. + +\begin{theorem}[after Glibichuk \cite{Gl06}; upstream \decl{erdos_1180}]\label{thm:glib} +Let $\eps>0$ and let $k$ be an integer with $k>2/\eps+1$. There is $P_0$ such that for every prime $p\ge P_0$ every $a\in\F$ has an $\eps$-representation of size exactly $8k^2$. Consequently $\max(8k^2,P_0)\in S_\eps$; in particular $S_\eps\ne\emptyset$. +\end{theorem} + +\begin{proposition}\label{prop:lower} +For every integer $m\ge2$, $C_{1/(m+1)}\ge 2^m$. +\end{proposition} + + +\section{Proof}\label{sec:proof} + +\subsection{Glibichuk's covering lemma}\label{sec:glib} +Let $p$ be prime and $X,Y\subseteq\F$ with $N=|X||Y|$. +For $\xi\in\F$ let $A_\xi=\{x+\xi y:x\in X,\,y\in Y\}$ and let $E_\xi$ be the number of pairs $(u,v)\in(X\times Y)^2$ with $u_1+\xi u_2=v_1+\xi v_2$. +Write $XY=\{xy:x\in X,y\in Y\}$ and $hXY$ for the $h$-fold sumset $XY+\dots+XY$. +Call $Y$ \emph{antisymmetric} if $-y\notin Y$ for every $y\in Y$. + +\begin{lemma}\label{lem:energy} +\textup{(a)} $N^2\le|A_\xi|\,E_\xi$ for every $\xi$. +\textup{(b)} $\sum_{\xi\ne0}E_\xi\le(p-1)N+N^2$; hence some $\xi\ne0$ satisfies $E_\xi\le N+N^2/(p-1)$. +\textup{(c)} $E_{-\xi}=E_\xi$. +\end{lemma} + +\begin{proof} +(a) For $z\in A_\xi$ let $r(z)$ be the number of $u\in X\times Y$ with $u_1+\xi u_2=z$. Then $\sum_z r(z)=N$ and $\sum_z r(z)^2=E_\xi$, and Cauchy--Schwarz gives $N^2\le|A_\xi|\sum_zr(z)^2$. +(b) The sum counts triples $(\xi,u,v)$ with $\xi\ne0$ and $u_1+\xi u_2=v_1+\xi v_2$. Triples with $u=v$ number at most $(p-1)N$. If $u\ne v$ and some $\xi$ solves the equation, then $u_2\ne v_2$ (otherwise the equation forces $u_1=v_1$), and two solutions $\xi,\eta$ give $(\xi-\eta)(u_2-v_2)=0$, so $\xi=\eta$; hence these triples number at most $N^2$. The second claim follows by averaging over the $p-1$ values $\xi\ne0$. +(c) The involution $((x_1,y_1),(x_2,y_2))\mapsto((x_1,y_2),(x_2,y_1))$ of $(X\times Y)^2$ maps solutions for $\xi$ to solutions for $-\xi$, since $x_1+\xi y_1=x_2+\xi y_2$ is equivalent to $x_1-\xi y_2=x_2-\xi y_1$. +\end{proof} + +\begin{lemma}\label{lem:half} +Let $p>2$ be prime, $N>p$ and $E_\xi\le N+N^2/(p-1)$. Then $2|A_\xi|>p$. +\end{lemma} + +\begin{proof} +Suppose $2|A_\xi|\le p$. As $p$ is odd, $2|A_\xi|\le p-1$. By Lemma~\ref{lem:energy}(a), $2N^2\le2|A_\xi|E_\xi\le(p-1)E_\xi\le(p-1)N+N^2$, so $N\le p-1$, a contradiction. +\end{proof} + +\begin{proposition}[Glibichuk]\label{prop:cover} +Let $p>2$ be prime and $X,Y\subseteq\F$ with $|X||Y|>p$ and $Y$ antisymmetric. Then $8XY=\F$. +\end{proposition} + +\begin{proof} +By Lemmas~\ref{lem:energy} and~\ref{lem:half} there is $\xi\ne0$ with $2|A_\xi|>p$ and $2|A_{-\xi}|>p$. +A set $A\subseteq\F$ with $2|A|>p$ meets $-A$, since otherwise $|A\cup(-A)|=2|A|>p$. +So $x_1+\xi y_1=-(x_2+\xi y_2)$ for some $x_i\in X$, $y_i\in Y$, that is, $\xi(y_1+y_2)=-(x_1+x_2)$, and $c=y_1+y_2\ne0$ because $Y$ is antisymmetric. +For $x_3\in X$, $y_3\in Y$, +\[ + c\,(x_3-\xi y_3)=x_3y_1+x_3y_2+x_1y_3+x_2y_3\in 4XY. +\] +Multiplication by $c$ is injective, so $|4XY|\ge|A_{-\xi}|>p/2$, i.e.\ $2|4XY|\ge p+1$. +By the Cauchy--Davenport theorem, $|4XY+4XY|\ge\min(p,2|4XY|-1)=p$, so $8XY=\F$. +\end{proof} + +\subsection{Sums of reciprocals of primes in blocks}\label{sec:blocks} +Let $p$ be prime, $k\ge1$, $L\ge0$, $H0$ and let $k$ be an integer with $k>2/\eps+1$. Put $\delta=2/(4k-1)$, $\gamma=(\delta+\frac1{2k})/2$ and $t=(\gamma/\delta+1)/2$. Then $0<\gamma<\delta<1$, $(2k-1)\delta<1$, $2\delta\le\eps$, $2k\gamma>1$, $01$. Next $\delta<1$ as $k>1$, and $(2k-1)\delta=\frac{4k-2}{4k-1}<1$. From $k\eps>2+\eps$ we get $\eps(4k-1)>8+3\eps>4$, i.e.\ $2\delta\le\eps$. Finally $\gamma/\delta\in(0,1)$ gives $t\in(0,1)$, and $\delta t=(\gamma+\delta)/2>\gamma$. +\end{proof} + +\begin{lemma}\label{lem:good} +With the parameters of Lemma~\ref{lem:params}, for all sufficiently large $n$, writing $H=\lfloor n^\delta\rfloor$ and $L=\lfloor n^\gamma\rfloor$: +\textup{(G1)} $n>2$; \textup{(G2)} $Hn^\gamma/2$, so $L^{2k}>2^{-2k}n^{2k\gamma}>n$ for large $n$, as $2k\gamma>1$. +(G6): we first show $\pi(x)\ge x^t$ for all large integers $x$. Chebyshev's bound $\pi(x)\ge(x\log2-\log(x+1))/\log x$ holds for all integers $x\ge2$; for $x\ge6$ we have $(x+1)^2\le2^x$, so $\log(x+1)\le\frac{x\log2}2$, and for large $x$ also $\log x\le\frac{\log2}{2}x^{1-t}$, whence $x^t\log x\le\frac{x\log 2}{2}\le x\log2-\log(x+1)$. Since $H\to\infty$, for large $n$ we get $\pi(H)\ge H^t>(n^\delta/2)^t=2^{-t}n^{\delta t}>k\,n^\gamma\ge kL$, using $H>n^\delta/2$ and $\delta t>\gamma$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:glib}] +Take $P_0$ such that every $n\ge P_0$ satisfies (G1)--(G6). Let $p\ge P_0$ be prime and $a\in\F$. By (G6) there are $kL$ distinct primes $\le H$; label them $q_{i,j}$ ($ip$. Proposition~\ref{prop:cover} with $X=Y=B$ (using (G1)) gives $8BB=\F$, and Lemma~\ref{lem:exact} (using (G4)) gives an $\eps$-representation of $a$ of size $8k^2$. +For a prime $p2^m\ge4$ is odd while $2^{m+1}$ is even. By Theorem~\ref{thm:glib}, $S_\eps\ne\emptyset$, so $C_\eps=\min S_\eps\in S_\eps$, and $-1\in\F$ has an $\eps$-representation $s$ with $|s|\le C_\eps$. By Lemma~\ref{lem:one} with $k=m+1$, $C_\eps\ge|s|\ge p-1\ge2^m$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +Suppose \eqref{eq:O} holds and apply it with $\delta=1$. Since $\eps_m=1/(m+1)$ tends to $0$ through positive values, there is $M$ with $C_{\eps_m}\le\eps_m^{-2}=(m+1)^2$ for all $m\ge M$. Take $m=M+10$. Proposition~\ref{prop:lower} gives $2^m\le C_{\eps_m}\le(m+1)^2$. But $(m+1)^2<2^m$ for $m\ge6$, by induction: $49<64$, and $(m+2)^2\le2(m+1)^2<2\cdot2^m$. Contradiction. +\end{proof} + +The Lean proof carries out the argument of Proposition~\ref{prop:lower} inline for $m=M+10$, using Mathlib's \decl{Nat.exists_prime_lt_and_le_two_mul} (Bertrand) and \decl{Nat.sInf_mem}. + +\section{The defect and a corrected statement}\label{sec:defect} + +The lower bound of Proposition~\ref{prop:lower} comes only from primes $p<2^{1/\eps}$, for which $1$ is the only admissible denominator (Theorem~\ref{thm:glib} only ensures that $C_\eps$ is a genuine minimum); any bound valid for all primes is at least $p-1$ for each such $p$, so $C_\eps$ is exponential in $1/\eps$ whatever happens for large primes. The bounds of Shparlinski and Glibichuk concern the least bound valid for all primes $p\ge P(\eps)$, for which $\gg\eps^{-1}$ summands are also trivially necessary, and we read the remark ``it may be that $C_\eps\le\eps^{-1-o(1)}$'' as referring to that quantity, since for the all-primes constant it fails trivially. Theorem~\ref{thm:main} says nothing about the large-prime quantity, and whether it is $\eps^{-1-o(1)}$ remains open. + +Following the form that \cite{PR6486} gave to the \decl{shparlinski} and \decl{glibichuk} variants, we propose: +\begin{lstlisting} +/-- Is $C_\epsilon\leq \epsilon^{-1-o(1)}$, for all sufficiently large primes? -/ +@[category research open, question, AMS 11] +theorem erdos_1180.variants.optimal : ∀ δ : ℝ, 0 < δ → + ∀ᶠ ε : ℝ in nhdsWithin 0 (Set.Ioi 0), ∃ P : ℕ, ∀ p : ℕ, P ≤ p → p.Prime → ∀ a : ZMod p, + ∃ s : Multiset ℕ, (s.card : ℝ) ≤ ε⁻¹ ^ (1 + δ) ∧ Represents ε p a s := by + sorry +\end{lstlisting} +We checked that this elaborates against the pinned versions of Section~\ref{sec:lean}. Alternatively, one can bound a large-prime constant in place of \decl{C}, as linrock/math-proofs does with \decl{CAsymptotic} \cite{linrock}. + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +{\raggedright The proof is the file \path{lean/Math0/ErdosProblems/Erdos1180_erdos_1180_variants_optimal.lean} (1073 lines) of the math0 repository (\url{https://github.com/Foundation-0/math0}). It imports only the upstream file \path{FormalConjectures/ErdosProblems/1180.lean} and the audit commands \path{lean/Math0/Audit.lean}, and contains no \texttt{sorry}, \decl{native_decide}, \decl{set_option} or new axioms. The main declarations, in the namespace \decl{Math0.Erdos1180}, are: +\decl{exists_good_slope}, \decl{affEnergy_neg} (Lemma~\ref{lem:energy}); +\decl{card_affImg_large} (Lemma~\ref{lem:half}); +\decl{glibichuk} (Proposition~\ref{prop:cover}, using Mathlib's \decl{ZMod.cauchy_davenport}); +\decl{recSum_injective}, \decl{card_recSet}, \decl{recSet_antisymm} (Lemma~\ref{lem:blocks}); +\decl{sum8_exactRep} (Lemma~\ref{lem:exact}); +\decl{choose_params} (Lemma~\ref{lem:params}); +\decl{ev_good}, \decl{ev_primeCounting_ge} (Lemma~\ref{lem:good}, using Mathlib's \decl{Chebyshev.pi_ge}); +\decl{exists_bound} (Theorem~\ref{thm:glib}); +\decl{card_ge_of_represents_neg_one} (Lemma~\ref{lem:one}); +\decl{not_erdos_1180_variants_optimal} (Theorem~\ref{thm:main}). +The statement of \decl{exists_bound} is that of upstream \decl{erdos_1180}; only the final theorem is audited against an upstream declaration, by the last line of the file,\par} +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +#math0_refutes Math0.Erdos1180.not_erdos_1180_variants_optimal Erdos1180.erdos_1180.variants.optimal +\end{lstlisting} + +\subsection*{Audit} +The command \decl{#math0_refutes} (defined in \path{lean/Math0/Audit.lean}) fails unless the two theorems have the same universe parameters, the type of ours is syntactically identical (up to metadata, with no unfolding or definitional-equality check) to $\neg T$ for $T$ the type of \decl{Erdos1180.erdos_1180.variants.optimal}, and ours depends on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}; this rejects \decl{sorryAx}, the axioms behind \decl{native_decide} and custom axioms. On this file it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize, upquote=true] +math0 audit: 'Math0.Erdos1180.not_erdos_1180_variants_optimal' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Erdos1180.not_erdos_1180_variants_optimal' refutes 'Erdos1180.erdos_1180.variants.optimal' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1}, Mathlib \cite{Mathlib} \texttt{v4.33.1} and formal-conjectures \cite{FC} at commit \texttt{c77fdd446d23539302aa73bcfae4a9fa962b8382}, all pinned in \path{lean/}. To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib cache, builds all math0 results with \texttt{lake build} (re-running every audit), and checks that the pinned \decl{formal_conjectures} and \decl{mathlib} checkouts are unmodified. The single file can be checked in about a minute with \texttt{lake env lean} from \path{lean/}. + +\begin{thebibliography}{99} +\small\raggedright + +\bibitem{EP1180} +T.~F. Bloom, \emph{Erd\H{o}s Problems}, Problem \#1180, \url{https://www.erdosproblems.com/1180}, accessed October 2026. + +\bibitem{ErGr80} +P.~Erd\H{o}s and R.~L. Graham, \emph{Old and new problems and results in combinatorial number theory}, Monographies de L'Enseignement Math\'ematique \textbf{28}, Universit\'e de Gen\`eve, 1980. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{PR6486} +formal-conjectures, commit \texttt{377a7b38} (pull request \#6486), \emph{fix(ErdosProblems/1180): bound summands for large primes only}, 22 September 2026, \url{https://github.com/google-deepmind/formal-conjectures/pull/6486}. + +\bibitem{PR7219} +formal-conjectures, commit \texttt{da0010d4} (pull request \#7219), \emph{feat(ErdosProblems/1180): link formal proofs for solved variants}, 13 October 2026, \url{https://github.com/google-deepmind/formal-conjectures/pull/7219}. + +\bibitem{Gl06} +A.~A. Glibichuk, \emph{Combinatorial properties of sets of residues modulo a prime and the Erd\H{o}s--Graham problem}, Mat. Zametki \textbf{79} (2006), no.~3, 384--395; English transl.\ in Math. Notes \textbf{79} (2006), no.~3, 356--365. + +\bibitem{linrock} +linrock, \emph{math-proofs}, directory \path{erdos-1180/} at commit \texttt{ba96303b34a95ac458958c1eb0bbdee54733484a}, \url{https://github.com/linrock/math-proofs}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Palomar} +Palomar registry, entry PALOMAR-2026-10-12-000005, version 1, \url{https://palomar-registry.org/entry.html?id=PALOMAR-2026-10-12-000005&version=1}. + +\bibitem{plby} +plby, \emph{lean-proofs}, file \path{src/latest/ErdosProblems/Erdos1180.lean} at commit \texttt{8822f7ddef30fadbd92e1c6ab4ed897af356af5e}, \url{https://github.com/plby/lean-proofs}. + +\bibitem{Sh02} +I.~E. Shparlinski, \emph{On a question of Erd\H{o}s and Graham}, Arch. Math. (Basel) \textbf{78} (2002), no.~6, 445--448. + +\end{thebibliography} + +\end{document} diff --git a/results/erdos1193-erdos-1193-parts-i/README.md b/results/erdos1193-erdos-1193-parts-i/README.md new file mode 100644 index 0000000..be2e71c --- /dev/null +++ b/results/erdos1193-erdos-1193-parts-i/README.md @@ -0,0 +1,30 @@ +# Erdős Problem 1193 (i): the lower density of {n : 1_A*1_A(n) = g(n)} need not be 0 + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Combinatorics, Number theory +**Source problem:** Erdős Problem #1193 +**Date:** 2026-10-17 + +## Result + +It is not true that for every A ⊆ ℕ and every non-decreasing g : ℕ → ℕ with g(n) > 0 for all n, the set {n ∈ ℕ : 1_A ∗ 1_A(n) = g(n)} has lower natural density 0. Here 1_A ∗ 1_A(n) = #{(a,b) ∈ ℕ² : a + b = n, a ∈ A, b ∈ A} counts ordered representations (with 0 ∈ ℕ). The lower density of S is liminf_{N→∞} #(S ∩ [0,N)) / N. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_i.lean`](../../lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_i.lean) proves the upstream statement [`Erdos1193.erdos_1193.parts.i`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1193.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +The problem is Erdős Problem #1193 (erdosproblems.com/1193), from P. Erdős, "A survey of problems in combinatorial number theory", Ann. Discrete Math. (1980), 89–115. The site marks it "solved (Lean)": the literal question is trivially false via A = ℕ, which gives 1_A∗1_A(n) = n+1. The existing Lean formalization is plby/lean-proofs src/v4.29.1/ErdosProblems/Erdos1193.lean (Aristotle / Pietro Monticone; forum thread erdosproblems.com/forum/thread/1193#post-5360). It is linked from the upstream variant erdos_1193.variants.sumRep_univ and proves the key identity conv_ind univ n = n+1, but not the density step. + +## Citation + +```bibtex +@misc{math0:erdos1193-erdos-1193-parts-i, + author = {{math0}}, + title = {{Erdős Problem 1193 (i): the lower density of {n : 1_A*1_A(n) = g(n)} need not be 0}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1193-erdos-1193-parts-i}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos1193-erdos-1193-parts-ii/README.md b/results/erdos1193-erdos-1193-parts-ii/README.md new file mode 100644 index 0000000..14af316 --- /dev/null +++ b/results/erdos1193-erdos-1193-parts-ii/README.md @@ -0,0 +1,30 @@ +# Erdős Problem 1193 (ii): the upper density of {n : 1_A*1_A(n) = g(n)} need not be bounded away from 1 + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Combinatorics, Number theory +**Source problem:** Erdős Problem #1193 +**Date:** 2026-10-17 + +## Result + +There is no real constant c < 1 such that for every A ⊆ ℕ and every monotone g : ℕ → ℕ with g(n) > 0 for all n, the set {n ∈ ℕ : sumRep A n = g n} has upper density < c. Here sumRep A n is the number of ordered pairs (a, b) ∈ A × A with a + b = n (i.e. 1_A * 1_A(n)), and the upper density of S ⊆ ℕ is limsup_{N→∞} |S ∩ [0, N)| / N. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_ii.lean`](../../lean/Math0/ErdosProblems/Erdos1193_erdos_1193_parts_ii.lean) proves the upstream statement [`Erdos1193.erdos_1193.parts.ii`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/1193.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Erdős, P., "A survey of problems in combinatorial number theory", Ann. Discrete Math. (1980), 89-115 [Er80]. erdosproblems.com/1193 says the question as stated is trivially "no" because of A = ℕ (1_A*1_A(n) = n+1), and its data file gives the status as "solved (Lean)" (2026-04-13). An existing Lean formalization is linked from the upstream formal_conjectures file: https://github.com/plby/lean-proofs/blob/main/src/v4.29.1/ErdosProblems/Erdos1193.lean. + +## Citation + +```bibtex +@misc{math0:erdos1193-erdos-1193-parts-ii, + author = {{math0}}, + title = {{Erdős Problem 1193 (ii): the upper density of {n : 1_A*1_A(n) = g(n)} need not be bounded away from 1}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos1193-erdos-1193-parts-ii}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos142-erdos-142-variants-istheta/README.md b/results/erdos142-erdos-142-variants-istheta/README.md new file mode 100644 index 0000000..5093888 --- /dev/null +++ b/results/erdos142-erdos-142-variants-istheta/README.md @@ -0,0 +1,50 @@ +# Erdős 142 (Θ variant): no k-independent order of magnitude for r_k(N) + +**Classification:** Misformalization found (upstream statement does not match the problem) +**Area:** Number theory +**Source problem:** Erdős Problem #142 +**Date:** 2026-10-17 + +## Result + +Let r_k(N) = Set.IsAPOfLengthFree.maxCard k N be the largest size of a subset of {1,...,N} that contains no non-trivial k-term arithmetic progression. The upstream statement asks for one function answer : ℕ → ℝ such that for every k ∈ ℕ, (N ↦ r_k(N)) =Θ[atTop] answer. We prove the negation for every possible value of the unknown: for all a : ℕ → ℝ, ¬ ∀ k : ℕ, (fun N => (r k N : ℝ)) =Θ[atTop] a. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos142_erdos_142_variants_isTheta.lean`](../../lean/Math0/ErdosProblems/Erdos142_erdos_142_variants_isTheta.lean) refutes, for every possible value of its unknown, the upstream statement [`Erdos142.erdos_142.variants.isTheta`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/142.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research open`). Its final command `#math0_refutes_every_answer` checks that our theorem's type is syntactically identical to the upstream statement negated and universally quantified over the unknown and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Erdős Problem 142 (erdosproblems.com/142, $10000 prize, listed open, OEIS A003002–A003005) asks for the order of magnitude, or an asymptotic formula, of r_k(N), the largest subset of {1,...,N} with no k-term AP. + +Known results: +- Szemerédi: r_k(N) = o(N). +- Behrend (k = 3) and Rankin (general k): lower bounds of the form N·exp(−c(log N)^{1/ℓ}). +- Gowers: upper bounds for general k. +- Kelley–Meka (2023), improved by Bloom–Sisask: r_3(N) ≤ N·exp(−c(log N)^{1/12}), later exponent 1/9. +- Green–Tao: bounds for r_4. +- Leng–Sah–Sawhney (2024): r_k(N) ≤ N·exp(−(log log N)^{c_k}). + +The order of magnitude of r_k is open for every k ≥ 3. + +The facts the refutation uses are trivial and belong to the formal library: r_1(N) = N (`Set.IsAPOfLengthFree.maxCard_one`), and r_2(N) ≤ 1 because any two points form a 2-term AP. I know of no previous Lean artifact reporting that `erdos_142.variants.isTheta` (or the sibling `erdos_142`) is false because its answer does not depend on k. - erdosproblems.com/142: open, $10000; it gives order of magnitude as the "more reasonable" goal and cites [Er80], [Va99]. Best known bounds: Kelley–Meka 2023 (k=3), Green–Tao 2017 (k=4), Leng–Sah–Sawhney 2024 (k≥5). Lower bounds: Behrend 1946 and Rankin 1961. +- erdosproblems.com/forum/thread/142: a single comment by jleng01 (2026-08-09), unrelated to formalization. +- google-deepmind/formal-conjectures PR #5446 (open, 2026-09-10): flags 142.lean:37,56 as answer slots that cannot depend on the required binder k. + +(Abridged; the manuscript discusses the literature in full.) + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:erdos142-erdos-142-variants-istheta, + author = {{math0}}, + title = {{Erdős 142 (Θ variant): no k-independent order of magnitude for r_k(N)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos142-erdos-142-variants-istheta}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos142-erdos-142-variants-istheta/paper.pdf b/results/erdos142-erdos-142-variants-istheta/paper.pdf new file mode 100644 index 0000000..2f38b5d Binary files /dev/null and b/results/erdos142-erdos-142-variants-istheta/paper.pdf differ diff --git a/results/erdos142-erdos-142-variants-istheta/paper.tex b/results/erdos142-erdos-142-variants-istheta/paper.tex new file mode 100644 index 0000000..87facf0 --- /dev/null +++ b/results/erdos142-erdos-142-variants-istheta/paper.tex @@ -0,0 +1,393 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\small, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8} +% Unicode inside listings (pdfLaTeX listings cannot read multibyte characters directly). +\lstset{keepspaces=true, literate={α}{{$\alpha$}}1 {∞}{{$\infty$}}1 {•}{{$\bullet$}}1 {Θ}{{$\Theta$}}1 + {ℕ}{{$\mathbb{N}$}}1 {ℝ}{{$\mathbb{R}$}}1 {→}{{$\to$}}1 {¬}{{$\neg$}}1 {∀}{{$\forall$}}1 + {∃}{{$\exists$}}1 {∧}{{$\wedge$}}1 {⊆}{{$\subseteq$}}1 {≤}{{$\le$}}1 {⟨}{{$\langle$}}1 + {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1 {↦}{{$\mapsto$}}1 {∈}{{$\in$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{Θ}{\ensuremath{\Theta}} +\newunicodechar{•}{\ensuremath{\bullet}} +\newunicodechar{≍}{\ensuremath{\asymp}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\R}{\mathbb{R}} + +\title[No $k$-independent order of magnitude for $r_k(N)$]{There is no $k$-independent order of magnitude for $r_k(N)$: a defect in a formal statement of Erd\H{o}s Problem \#142} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 17, 2026} + +\begin{document} +\begin{abstract} +Let $r_k(N)$ be the largest size of a subset of $\{1,\dots,N\}$ that contains no non-trivial $k$-term arithmetic progression. +Erd\H{o}s Problem \#142 asks, for each fixed $k$, for an asymptotic formula for $r_k(N)$, and in a weaker form for its order of magnitude; the formalization \decl{Erdos142.erdos_142.variants.isTheta} of the order-of-magnitude question in the formal-conjectures repository instead asks for a single function $f\colon\N\to\R$, not depending on $k$, with $r_k\asymp f$ for every $k\in\N$. +We prove that no such function exists, because $r_1(N)=N$, $r_2(N)\le1$, and $\asymp$ is an equivalence relation. +This is a misformalization report, not progress on the research problem: the argument uses only the degenerate cases $k=1,2$, the problem remains open for every $k\ge3$, and we propose a corrected statement in which the unknown depends on $k$. +The refutation, valid for every value of the unknown, is verified in Lean~4 against the upstream formal-conjectures statement at commit \texttt{c77fdd4}. +\end{abstract} +\maketitle + +\section{Introduction}\label{sec:intro} + +For $k\ge1$ and $N\ge0$ let $r_k(N)$ be the largest size of a subset of $\{1,\dots,N\}$ containing no non-trivial arithmetic progression of length $k$. +Erd\H{o}s Problem~\#142 \cite{EP142} asks for an asymptotic formula for $r_k(N)$; the problem page records that Erd\H{o}s also asked for the order of magnitude of $r_k(N)$ \cite{Er80}, lists a prize of \$10000, and states that an asymptotic formula is out of reach even for $k=3$. +The first values of $r_3,\dots,r_6$ are the OEIS sequences A003002--A003005 \cite{OEIS}. + +\subsection*{Known results} +Szemer\'edi proved that $r_k(N)=o(N)$ for every fixed $k$ \cite{Sz75}, and Gowers gave the first reasonable quantitative bounds for general $k$, $r_k(N)\le N(\log\log N)^{-c_k}$ \cite{Go01}. +Much stronger upper bounds are now known: $r_3(N)\le N\exp(-c(\log N)^{1/12})$ by Kelley and Meka \cite{KM23}, with the exponent improved to $1/9$ by Bloom and Sisask \cite{BS23} (a 2026 preprint of Raghavan \cite{Rag26} announces $r_3(N)\le N\exp(-c(\log N)^{1/6}(\log\log N)^{-1})$); $r_4(N)\le N(\log N)^{-c}$ by Green and Tao \cite{GT17}; and $r_k(N)\le N\exp(-(\log\log N)^{c_k})$ for $k\ge5$ by Leng, Sah and Sawhney \cite{LSS24}. +In the other direction, Behrend's construction gives $r_3(N)\ge N\exp(-c\sqrt{\log N})$ \cite{Be46}, and Rankin generalized the construction to all $k$ \cite{Ra61}; in the explicit form given by O'Bryant \cite{OB11}, for $k\ge3$ and $n=\lceil\log_2k\rceil$ one has $r_k(N)\ge N\exp(-c_k(\log N)^{1/n})$ for large $N$. +The order of magnitude of $r_k(N)$ is unknown for every $k\ge3$. + +\subsection*{The formal statement} +The formal-conjectures repository \cite{FC} formalizes Problem~\#142 in \path{FormalConjectures/ErdosProblems/142.lean}. +The docstring of \decl{erdos_142.variants.isTheta} reads ``find $f_k$ with $r_k(N)\asymp_k f_k(N)$'', so the intended unknown is a family of functions indexed by $k$. +In the formal statement, however, the unknown is a top-level definition \decl{erdos_142.variants.isTheta.answer} of type $\N\to\R$, which cannot depend on $k$, while the theorem quantifies over all $k\in\N$, including $k=0,1,2$. +The quantifier pattern $\forall k\,\exists f_k$ of the problem has become $\exists f\,\forall k$. + +\subsection*{Contribution and status} +We prove that the formal statement is false whatever value is chosen for its unknown (Theorem~\ref{thm:main}) and verify this in Lean~4. +The proof uses only $r_1(N)=N$ and $r_2(N)\le1$, so it says nothing about $r_k$ for $k\ge3$; we classify it as a \emph{misformalization report}. + +The difficulty has been noticed upstream but not fixed. +When the hypothesis $1 (r k N : ℝ)) =Θ[atTop] erdos_142.variants.isTheta.answer := by + sorry +\end{lstlisting} +Writing $f$ for the value of the unknown, the statement asserts +\begin{equation}\label{eq:P} + P(f):\qquad r_k\asymp f\quad\text{for every }k\in\N, +\end{equation} +where $r_k$ is the function $N\mapsto r_k(N)$, viewed as real-valued. + +\subsection{Main result} +\begin{theorem}\label{thm:main} +For every $f\colon\N\to\R$ the statement $P(f)$ is false. More precisely, there is no $f\colon\N\to\R$ with both $r_1\asymp f$ and $r_2\asymp f$. +\end{theorem} + +In Lean, Theorem~\ref{thm:main} is the following declaration (in \texttt{namespace Math0.Erdos142}); its type is the negation of the upstream statement, universally quantified over the unknown. +\begin{lstlisting} +theorem not_isTheta : ∀ a : ℕ → ℝ, + ¬ ∀ k : ℕ, (fun N => (Erdos142.r k N : ℝ)) =Θ[atTop] a +\end{lstlisting} + +\section{Proof}\label{sec:proof} + +\begin{lemma}\label{lem:r1} +$r_1(N)=N$ for every $N\in\N$. +\end{lemma} + +\begin{proof} +Every set is free of progressions of length $1$, so the set in the definition of $r_1(N)$ is $\{|S| : S\subseteq\{1,\dots,N\}\}=\{0,1,\dots,N\}$, whose supremum is $N$, attained by $S=\{1,\dots,N\}$. +\end{proof} + +In Lean this is the library lemma \decl{Set.IsAPOfLengthFree.maxCard_one} of \cite{FC}. + +\begin{lemma}\label{lem:pair} +Let $S\subseteq\N$ be a finite set that is free of progressions of length $2$. Then $|S|\le1$. +\end{lemma} + +\begin{proof} +Suppose $S$ has two distinct elements, and call them $a (r k N : ℝ)) =Θ[atTop] erdos_142.variants.isTheta.answer k := by + sorry +\end{lstlisting} +We checked that this elaborates against the pinned Lean, Mathlib and formal-conjectures versions of Section~\ref{sec:lean}. +Once the unknown depends on $k$, the hypothesis $3\le k$ is no longer needed for satisfiability (for $k\le2$ the functions $r_k$ are known explicitly), but it matches the intended problem. +The same change, giving \decl{erdos_142.answer} the type $\N\to\N\to\R$ and applying it to $k$, repairs the main statement \decl{erdos_142}. +As the description of pull request \#5810 \cite{PR5810} notes for value questions of this shape, the tautological value $\texttt{answer}\ k = r_k$ satisfies such a statement; the repository's contribution guidelines treat this as out of scope, and it is not specific to Problem~\#142. + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is the file \path{lean/Math0/ErdosProblems/Erdos142_erdos_142_variants_isTheta.lean} of the math0 repository (\url{https://github.com/Foundation-0/math0}). +It imports only the upstream file \path{FormalConjectures/ErdosProblems/142.lean} and the audit commands \path{lean/Math0/Audit.lean}. +Its declarations, in the namespace \decl{Math0.Erdos142}, are \decl{isTheta_card_le_one_of_free} (Lemma~\ref{lem:pair}), \decl{isTheta_r_two_le_one} (Corollary~\ref{cor:r2}) and the main theorem \decl{not_isTheta} (Theorem~\ref{thm:main}). +The file contains no \texttt{sorry}, no \decl{native_decide} and no new axioms. +The main proof and the final audit command are: +\begin{lstlisting} +theorem not_isTheta : ∀ a : ℕ → ℝ, + ¬ ∀ k : ℕ, (fun N => (Erdos142.r k N : ℝ)) =Θ[atTop] a := by + intro a h + have h12 : (fun N => (Erdos142.r 1 N : ℝ)) =O[atTop] (fun N => (Erdos142.r 2 N : ℝ)) := + ((h 1).trans (h 2).symm).isBigO + have h2b : (fun N => (Erdos142.r 2 N : ℝ)) =O[atTop] (fun _ => (1 : ℝ)) := by + apply Asymptotics.IsBigO.of_bound 1 + filter_upwards with N + simp only [Real.norm_eq_abs, abs_one, mul_one, Nat.abs_cast] + exact_mod_cast isTheta_r_two_le_one N + have h3 := h12.trans h2b + simp only [Erdos142.r, Set.IsAPOfLengthFree.maxCard_one] at h3 + rw [Asymptotics.isBigO_one_iff] at h3 + exact Filter.not_isBoundedUnder_of_tendsto_atTop + (tendsto_norm_atTop_atTop.comp tendsto_natCast_atTop_atTop) h3 + +#math0_refutes_every_answer Math0.Erdos142.not_isTheta Erdos142.erdos_142.variants.isTheta with Erdos142.erdos_142.variants.isTheta.answer +\end{lstlisting} + +\subsection*{Audit} +The command \decl{#math0_refutes_every_answer}, defined in \path{lean/Math0/Audit.lean}, is the math0 audit for misformalization reports on value questions. It fails unless: +(1) our theorem has the same universe parameters as the upstream theorem, and the unknown is not universe-polymorphic; +(2) the type of our theorem is syntactically identical, up to metadata annotations and with no unfolding or definitional-equality check, to $\forall a,\ \neg B[a]$, where $B[a]$ is the type of the upstream theorem with every occurrence of the constant \decl{Erdos142.erdos_142.variants.isTheta.answer} replaced by a bound variable $a$ of the same type $\N\to\R$; +(3) our theorem depends on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, so \decl{sorryAx}, the axioms behind \decl{native_decide} and custom axioms are rejected. +Condition (2) ensures that the theorem refutes the upstream statement as published, for every value of its unknown. On this file the command reports +\begin{lstlisting} +math0 audit: 'Math0.Erdos142.not_isTheta' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Erdos142.not_isTheta' refutes 'Erdos142.erdos_142.variants.isTheta' for every value of 'Erdos142.erdos_142.variants.isTheta.answer' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1}, Mathlib \cite{Mathlib} \texttt{v4.33.1} and formal-conjectures \cite{FC} at commit \texttt{c77fdd446d23539302aa73bcfae4a9fa962b8382}, all pinned in \path{lean/}. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. +The single file can also be checked with \texttt{lake env lean} from the \path{lean} directory. + +\begin{thebibliography}{99} +\raggedright + +\bibitem{Be46} +F.~A. Behrend, \emph{On sets of integers which contain no three terms in arithmetical progression}, Proc. Nat. Acad. Sci. U.S.A. \textbf{32} (1946), 331--332. + +\bibitem{BS23} +T.~F. Bloom and O.~Sisask, \emph{An improvement to the Kelley--Meka bounds on three-term arithmetic progressions}, arXiv:2309.02353, 2023. + +\bibitem{EP142} +T.~F. Bloom, \emph{Erd\H{o}s Problems}, Problem \#142, \url{https://www.erdosproblems.com/142}, accessed October 2026. + +\bibitem{Er80} +P.~Erd\H{o}s, \emph{A survey of problems in combinatorial number theory}, Ann. Discrete Math. \textbf{6} (1980), 89--115. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{PR1187} +formal-conjectures, pull request \#1187 (commit \texttt{bf0ea56}), \emph{fix: exclude 0 and 1 cases when using} \texttt{Set.IsAPOfLengthFree.maxCard}, 11 November 2025, \url{https://github.com/google-deepmind/formal-conjectures/pull/1187}. + +\bibitem{PR5446} +formal-conjectures, pull request \#5446, \emph{fix: answer slots that cannot depend on the inputs they must depend on}, opened 10 September 2026, \url{https://github.com/google-deepmind/formal-conjectures/pull/5446}. + +\bibitem{PR5810} +formal-conjectures, pull request \#5810 (commit \texttt{7f64240}), \emph{fix(Erdos/142): ask for asymptotic formula; order of magnitude variant}, 12 September 2026, \url{https://github.com/google-deepmind/formal-conjectures/pull/5810}. + +\bibitem{PR7327} +formal-conjectures, pull request \#7327 (commit \texttt{2c24ebe}), \emph{feat(Util) replace \texttt{answer(sorry)} with \texttt{def answer}}, 14 October 2026, \url{https://github.com/google-deepmind/formal-conjectures/pull/7327}. + +\bibitem{Go01} +W.~T. Gowers, \emph{A new proof of Szemer\'edi's theorem}, Geom. Funct. Anal. \textbf{11} (2001), 465--588. + +\bibitem{GT17} +B.~Green and T.~Tao, \emph{New bounds for Szemer\'edi's theorem, III: a polylogarithmic bound for $r_4(N)$}, Mathematika \textbf{63} (2017), no.~3, 944--1040. + +\bibitem{KM23} +Z.~Kelley and R.~Meka, \emph{Strong bounds for 3-progressions}, in: 2023 IEEE 64th Annual Symposium on Foundations of Computer Science (FOCS), IEEE, 2023, 933--973; arXiv:2302.05537. + +\bibitem{LSS24} +J.~Leng, A.~Sah, and M.~Sawhney, \emph{Improved bounds for Szemer\'edi's theorem}, arXiv:2402.17995, 2024. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{OB11} +K.~O'Bryant, \emph{Sets of integers that do not contain long arithmetic progressions}, Electron. J. Combin. \textbf{18} (2011), no.~1, Paper~59; arXiv:0811.3057. + +\bibitem{OEIS} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, sequences A003002, A003003, A003004, A003005, \url{https://oeis.org/A003002}. + +\bibitem{Ra61} +R.~A. Rankin, \emph{Sets of integers containing not more than a given number of terms in arithmetical progression}, Proc. Roy. Soc. Edinburgh Sect. A \textbf{65} (1960/61), 332--344. + +\bibitem{Rag26} +R.~Raghavan, \emph{Improved bounds for 3-progressions}, arXiv:2603.27045, 2026. + +\bibitem{Sz75} +E.~Szemer\'edi, \emph{On sets of integers containing no $k$ elements in arithmetic progression}, Acta Arith. \textbf{27} (1975), 199--245. + +\end{thebibliography} + +\end{document} diff --git a/results/erdos142-erdos-142/README.md b/results/erdos142-erdos-142/README.md new file mode 100644 index 0000000..98c36ac --- /dev/null +++ b/results/erdos142-erdos-142/README.md @@ -0,0 +1,49 @@ +# Erdős 142: no single k-independent asymptotic formula for r_k(N) + +**Classification:** Misformalization found (upstream statement does not match the problem) +**Area:** Number theory +**Source problem:** Erdős Problem #142 +**Date:** 2026-10-17 + +## Result + +Let r_k(N) = Set.IsAPOfLengthFree.maxCard k N be the largest size of a subset of {1,...,N} that contains no non-trivial k-term arithmetic progression. The upstream statement says that for every k ∈ ℕ, the sequence N ↦ r_k(N) is asymptotically equivalent (as N → ∞) to erdos_142.answer : ℕ → ℝ, which is one fixed function that does not depend on k. We prove that this fails for every possible choice of that function: ∀ a : ℕ → ℝ, ¬ ∀ k, (fun N => (r k N : ℝ)) ~[atTop] a. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos142_erdos_142.lean`](../../lean/Math0/ErdosProblems/Erdos142_erdos_142.lean) refutes, for every possible value of its unknown, the upstream statement [`Erdos142.erdos_142`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/142.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research open`). Its final command `#math0_refutes_every_answer` checks that our theorem's type is syntactically identical to the upstream statement negated and universally quantified over the unknown and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Erdős Problem 142 ($10000 prize) is open. In erdosproblems problems.yaml, entry "142" has status "open" and formal_status "unformalized". The OEIS sequences A003002–A003005 give r_3 through r_6. Known bounds include: +- Szemerédi: r_k(N) = o(N). +- Behrend and Rankin: lower bounds of the form N·exp(-c(log N)^{1/ℓ}). +- Kelley–Meka (2023) and Bloom–Sisask: r_3(N) ≤ N·exp(-c(log N)^{1/9}). +- Green–Tao: k = 4. +- Leng–Sah–Sawhney (2024): k ≥ 5. + +No asymptotic formula r_k(N) ~ f_k(N) is known for any k ≥ 3. The Lean result does not touch this question. It only shows that the upstream statement, with one answer for every k ∈ ℕ including k = 1 and k = 2, is false, which is a trivial consequence of r_1(N) = N and r_2(N) ≤ 1. Sources: +- erdosproblems.com/142: the problem is open, $10000 prize; the page says an asymptotic formula is "still far out of reach, even for k=3", lists bounds by Kelley–Meka (k=3), Green–Tao (k=4) and Leng–Sah–Sawhney (k≥5), and notes Erdős's [Er80] remark that it is not known whether r_k/r_{k+1} → 0. +- erdosproblems.com/forum/thread/142: only one unrelated comment, and nothing about the formal statement. + +Upstream formal-conjectures history (google-deepmind/formal-conjectures): +- Commit 2c24ebe7 (#7327, 2026-10-14, M. Firsching): introduced the k-independent top-level `def erdos_142.answer : ℕ → ℝ := sorry`. +- Commit 7f64240c (#5810, 2026-09-12, S. Mercuri): changed Θ to ~ (fixes #5628 and #4922). + +(Abridged; the manuscript discusses the literature in full.) + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:erdos142-erdos-142, + author = {{math0}}, + title = {{Erdős 142: no single k-independent asymptotic formula for r_k(N)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos142-erdos-142}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos142-erdos-142/paper.pdf b/results/erdos142-erdos-142/paper.pdf new file mode 100644 index 0000000..461cc2f Binary files /dev/null and b/results/erdos142-erdos-142/paper.pdf differ diff --git a/results/erdos142-erdos-142/paper.tex b/results/erdos142-erdos-142/paper.tex new file mode 100644 index 0000000..896ebba --- /dev/null +++ b/results/erdos142-erdos-142/paper.tex @@ -0,0 +1,368 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage[T1]{fontenc} +\usepackage{lmodern} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,sorry}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + upquote=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℝ}{{$\mathbb{R}$}}1 {≤}{{$\le$}}1 {·}{{$\cdot$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {¬}{{$\neg$}}1 {→}{{$\to$}}1 {⊆}{{$\subseteq$}}1 {∅}{{$\emptyset$}}1 + {∧}{{$\wedge$}}1 {•}{{$\bullet$}}1 {∞}{{$\infty$}}1 {α}{{$\alpha$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{•}{\ensuremath{\bullet}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\R}{\mathbb{R}} +\newcommand{\Ninf}{\N\cup\{\infty\}} + +\title[No $k$-independent asymptotic formula for $r_k(N)$]{No single function is asymptotic to $r_k(N)$ for every $k$: a defect in the formal statement of Erd\H{o}s Problem \#142} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 17, 2026} + +\begin{document} +\begin{abstract} +Let $r_k(N)$ be the largest size of a subset of $\{1,\dots,N\}$ that contains no non-trivial $k$-term arithmetic progression. Erd\H{o}s Problem \#142 asks for an asymptotic formula for $r_k(N)$ for each fixed $k$, and it is open. The formal-conjectures repository states it in Lean as the claim that $r_k\sim A$ for every $k\in\N$, where $A\colon\N\to\R$ is one unknown function that does not depend on $k$. We prove that this claim is false for every choice of $A$, because $r_1(N)=N$ while $r_2(N)\le 1$; the argument is elementary, so this is a misformalization report that says nothing about the open problem, and we propose a corrected statement. The proof is verified in Lean~4 against the upstream formal-conjectures statement, together with a check that our theorem is exactly that statement, negated and quantified over all values of the unknown. +\end{abstract} +\maketitle + +\section{Introduction} + +For $k\ge 1$ and $N\ge 0$ let $r_k(N)$ be the largest size of a subset of $\{1,\dots,N\}$ that contains no non-trivial arithmetic progression of length $k$. The interesting range is $k\ge 3$. Roth \cite{Ro53} proved $r_3(N)=o(N)$ and Szemer\'edi \cite{Sz75} proved $r_k(N)=o(N)$ for every $k\ge 3$. Behrend \cite{Be46} (for $k=3$) and Rankin \cite{Ra61} (for general $k$) constructed large progression-free sets, giving lower bounds of the form $r_k(N)\ge N\exp(-c_k(\log N)^{\gamma_k})$ with $0<\gamma_k<1$. The upper bounds that \cite{EP142} lists as the best known are due to Kelley and Meka \cite{KM23} for $k=3$, namely $r_3(N)\le N\exp(-c(\log N)^{1/12})$, with the exponent improved to $1/9$ by Bloom and Sisask \cite{BS23} (a 2026 preprint of Raghavan \cite{Rag26} claims $r_3(N)\le N\exp(-c(\log N)^{1/6}(\log\log N)^{-1})$); to Green and Tao \cite{GT17} for $k=4$, namely $r_4(N)\le N(\log N)^{-c}$; and to Leng, Sah and Sawhney \cite{LSS24} for $k\ge 5$, namely $r_k(N)\le N\exp(-(\log\log N)^{c_k})$. The values of $r_3,\dots,r_6$ for small $N$ are the OEIS sequences A003002--A003005 \cite{OEIS}. + +Erd\H{o}s Problem \#142 \cite{EP142} asks to prove an asymptotic formula for $r_k(N)$, that is, to find $f_k$ with $r_k(N)/f_k(N)\to 1$ as $N\to\infty$. It goes back to Erd\H{o}s \cite{Er80,Er81,Er97}; in \cite{Er81} he offered \$10000 for it. The problem is open, and \cite{EP142} describes an asymptotic formula as ``still far out of reach, even for $k=3$''. The same page records that in \cite{Er80} Erd\H{o}s also asked for the order of magnitude of $r_k(N)$, and remarked that it was not even known whether $r_k(N)/r_{k+1}(N)\to 0$ for any $k\ge 3$. + +The formal-conjectures repository \cite{FC} contains a Lean statement \decl{Erdos142.erdos_142} of this problem. At the pinned commit \texttt{c77fdd4} its unknown is a single top-level definition \decl{erdos_142.answer} of type $\N\to\R$, and the theorem asserts $r_k\sim\texttt{erdos\_142.answer}$ for every $k\in\N$ (Section~\ref{sec:statement}). The answer therefore cannot depend on $k$, although the docstring asks for $f_k$, and $k$ ranges over all natural numbers, including the degenerate values $0,1,2$. + +\subsection*{Contribution and status} +We prove (Theorem~\ref{thm:main}) that \decl{Erdos142.erdos_142} is false for every possible value of its unknown. The reason is elementary: $r_1(N)=N$ is unbounded and $r_2(N)\le 1$ is bounded, so they are not asymptotic to a common function. This is a \emph{misformalization report}. It gives no information about the problem for $k\ge 3$. That the statement has this defect had already been noted informally in an open pull request to \cite{FC} (see Section~\ref{sec:defect}); we found no previous formal proof that the statement is false, either in \cite{FC} or on the forum thread of \cite{EP142}. Section~\ref{sec:defect} proposes a corrected statement. + +\section{Statement}\label{sec:statement} + +\subsection{Definitions} +Let $\N=\{0,1,2,\dots\}$, and let $|s|\in\Ninf$ denote the cardinality of a set $s\subseteq\N$. The following definitions are those of \cite{FC}, in the file \path{FormalConjecturesForMathlib/Combinatorics/AP/Basic.lean}. + +\begin{definition}\label{def:ap} +Let $s\subseteq\N$ and $l\in\Ninf$. +\begin{enumerate} +\item $s$ is an \emph{arithmetic progression of length $l$} if there are $a,d\in\N$ with $|s|=l$ and $s=\{a+nd:\ n\in\N,\ n0$ there is $N_0$ with $|f(N)-g(N)|\le\varepsilon|g(N)|$ for all $N\ge N_0$. +\end{definition} + +This is Mathlib's \texttt{Asymptotics.IsEquivalent atTop f g}, written \texttt{f \textasciitilde[atTop] g} and defined as $f-g=o(g)$. When $g(N)\ne 0$ for all large $N$, it is equivalent to $f(N)/g(N)\to 1$. + +\subsection{The upstream statement} +The relevant upstream definitions are, verbatim (docstrings omitted; $\alpha$ is an additive commutative monoid, here $\N$, and $k$ is coerced to $\Ninf$): +\begin{lstlisting} +def Set.IsAPOfLengthWith (s : Set α) (l : ℕ∞) (a d : α) : Prop := + ENat.card s = l ∧ s = {a + n • d | (n : ℕ) (_ : n < l)} + +def Set.IsAPOfLength (s : Set α) (l : ℕ∞) : Prop := + ∃ a d : α, s.IsAPOfLengthWith l a d + +def Set.IsAPOfLengthFree (s : Set α) (l : ℕ∞) : Prop := + ∀ t ⊆ s, t.IsAPOfLength l → l ≤ 1 + +noncomputable def Set.IsAPOfLengthFree.maxCard (k : ℕ) (N : ℕ) : ℕ := + sSup {Finset.card S | (S) (_ : S ⊆ Finset.Icc 1 N) (_ : (S : Set ℕ).IsAPOfLengthFree k)} +\end{lstlisting} +The statement, copied verbatim from \path{FormalConjectures/ErdosProblems/142.lean} (lines 32--43, namespace \decl{Erdos142}, with \texttt{open Asymptotics Filter}) at commit \texttt{c77fdd4}, is: +\begin{lstlisting} +noncomputable abbrev r := Set.IsAPOfLengthFree.maxCard + +def erdos_142.answer : ℕ → ℝ := sorry + +/-- +Prove an asymptotic formula for $r_k(N)$, the largest possible size of a subset +of $\{1, \dots, N\}$ that does not contain any non-trivial $k$-term arithmetic progression. +That is, find $f_k$ with $r_k(N) / f_k(N) \to 1$ as $N \to \infty$. +-/ +@[category research open, question value, AMS 11] +theorem erdos_142 (k : ℕ) : (fun N => (r k N : ℝ)) ~[atTop] erdos_142.answer := by + sorry +\end{lstlisting} +In the notation above, it asserts that the function $A=\texttt{erdos\_142.answer}\colon\N\to\R$ satisfies +\begin{equation}\label{eq:upstream} +r_k\sim A\qquad\text{for every } k\in\N . +\end{equation} + +\subsection{Main result} + +\begin{theorem}\label{thm:main} +There is no function $A\colon\N\to\R$ satisfying \eqref{eq:upstream}. More precisely, for every $A\colon\N\to\R$, the relations $r_1\sim A$ and $r_2\sim A$ do not both hold. +\end{theorem} + +In Lean (namespace \decl{Math0.Erdos142}): +\begin{lstlisting} +theorem erdos_142_refuted : + ∀ a : ℕ → ℝ, ¬ ∀ k : ℕ, (fun N => (Erdos142.r k N : ℝ)) ~[atTop] a +\end{lstlisting} +This type is the type of \decl{Erdos142.erdos_142} with the constant \decl{erdos_142.answer} replaced by a bound variable \texttt{a}, negated and quantified over \texttt{a}. So it refutes the upstream statement for every way of filling in the unknown; Section~\ref{sec:lean} describes the check. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file. Lemmas~\ref{lem:free2} and~\ref{lem:r2} are its two auxiliary theorems, Lemma~\ref{lem:r1} is an upstream lemma and Lemma~\ref{lem:equiv} collects Mathlib lemmas. + +\begin{lemma}[upstream \decl{Set.IsAPOfLengthFree.maxCard_one}]\label{lem:r1} +$r_1(N)=N$ for every $N\in\N$. +\end{lemma} + +\begin{proof} +Every set is free of $1$-term progressions, since the required conclusion $1\le 1$ holds. So $C_1(N)$ is the set of cardinalities of all subsets of $\{1,\dots,N\}$, whose maximum is $N$, attained by $\{1,\dots,N\}$. +\end{proof} + +\begin{lemma}[\decl{card_le_one_of_free_two}]\label{lem:free2} +Let $S\subseteq\N$ be finite and free of $2$-term progressions. Then $|S|\le 1$. +\end{lemma} + +\begin{proof} +Suppose $|S|\ge 2$, and pick distinct $a,b\in S$; by symmetry $a0$. Eventually $|f-g|\le\frac12|g|$ and $f>2M$. If $g\le 0$, then $f\le g+\frac12|g|=\frac12 g\le 0$, which is impossible. Hence $g>0$, $f\le\frac32 g$, and $g\ge\frac23 f>\frac43 M>M$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +Let $A\colon\N\to\R$ and suppose that $r_k\sim A$ for every $k\in\N$, where $r_k$ is viewed as the real-valued function $N\mapsto r_k(N)$. Taking $k=1$ and $k=2$ gives $r_1\sim A$ and $r_2\sim A$. By Lemma~\ref{lem:equiv}(1) $A\sim r_2$, and by Lemma~\ref{lem:equiv}(2) $r_1\sim r_2$. By Lemma~\ref{lem:r1}, $r_1(N)=N\to+\infty$, so $r_2(N)\to+\infty$ by Lemma~\ref{lem:equiv}(3). In particular $r_2(N)>1$ for some $N$, contradicting Lemma~\ref{lem:r2}. +\end{proof} + +\begin{remark} +Only $k=1$ and $k=2$ are used. Since $r_0(N)=N$ as well (upstream lemma \decl{Set.IsAPOfLengthFree.maxCard_zero}), $k=0$ could replace $k=1$. None of these values lies in the range $k\ge 3$ that Erd\H{o}s Problem \#142 is about. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is the file \path{lean/Math0/ErdosProblems/Erdos142_erdos_142.lean} of the math0 repository (\url{https://github.com/Foundation-0/math0}). It imports the upstream file \path{FormalConjectures/ErdosProblems/142.lean} and the math0 audit commands (\path{lean/Math0/Audit.lean}). It declares \decl{Math0.Erdos142.card_le_one_of_free_two} (Lemma~\ref{lem:free2}, for a \texttt{Finset ℕ}), \decl{Math0.Erdos142.r_two_le_one} (Lemma~\ref{lem:r2}) and the main theorem \decl{Math0.Erdos142.erdos_142_refuted} (Theorem~\ref{thm:main}), and uses the upstream and Mathlib lemmas named in Lemmas~\ref{lem:r1}--\ref{lem:equiv} and their proofs, together with \decl{tendsto_natCast_atTop_atTop}. It contains no \texttt{sorry}, \texttt{native\_decide}, \texttt{set\_option} or \texttt{axiom}. The tactic proof of the main theorem follows the proof of Theorem~\ref{thm:main} step by step: \texttt{h1.trans h2.symm} gives $r_1\sim r_2$; \decl{Set.IsAPOfLengthFree.maxCard_one} gives $r_1(N)=N\to\infty$; \texttt{h12.tendsto\_atTop} transfers this to $r_2$; \texttt{eventually\_gt\_atTop 1} produces an $N$ with $r_2(N)>1$; and \decl{r_two_le_one}, cast to $\R$, gives the contradiction by \texttt{linarith}. The file ends, after the namespace, with the audit command +\begin{lstlisting} +#math0_refutes_every_answer Math0.Erdos142.erdos_142_refuted Erdos142.erdos_142 with Erdos142.erdos_142.answer +\end{lstlisting} + +\subsection*{Audit} +The command \texttt{\#math0\_refutes\_every\_answer} is defined in \path{lean/Math0/Audit.lean}. Given our theorem, the upstream theorem \decl{Erdos142.erdos_142} and its unknown \decl{Erdos142.erdos_142.answer} of type $T$, it fails the build unless: +\begin{enumerate} +\item the two theorems have the same universe parameters and the unknown is not universe-polymorphic; +\item the type of our theorem is syntactically identical, after removing metadata annotations and with no unfolding or definitional-equality check, to $\forall\, a : T,\ \neg P[a]$, where $P[a]$ is the type of the upstream theorem with every occurrence of the constant \decl{Erdos142.erdos_142.answer} replaced by the bound variable $a$; +\item our theorem depends on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}; in particular not on \decl{sorryAx}, on \decl{Lean.ofReduceBool} (used by \texttt{native\_decide}) or on a custom axiom. +\end{enumerate} +The quantification over $a$ is needed because the body of the upstream definition is \texttt{sorry}. Applying our theorem to the constant itself yields a term of type \texttt{¬ Erdos142.erdos\_142}, but its axiom closure contains \decl{sorryAx}, reached through the body of the placeholder. The quantified form avoids this and also refutes every future version in which the definition is filled in and the theorem is left unchanged. On this file the command prints: +\begin{lstlisting} +math0 audit: 'Math0.Erdos142.erdos_142_refuted' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Erdos142.erdos_142_refuted' refutes 'Erdos142.erdos_142' for every value of 'Erdos142.erdos_142.answer' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1}, Mathlib \cite{Mathlib} \texttt{v4.33.1} and formal-conjectures \cite{FC} at commit \texttt{c77fdd4} (\texttt{c77fdd446d23539302aa73bcfae4a9fa962b8382}), all pinned in the \path{lean} directory (files \path{lakefile.toml} and \path{lean-toolchain}). To reproduce, run \path{scripts/verify.sh} from the repository root. It downloads the Mathlib build cache, builds all math0 results with \texttt{lake build} (which re-runs every audit command), checks that the \texttt{formal\_conjectures} and \texttt{mathlib} checkouts have no local modifications, and reports the number of passed statement checks. The single file can be checked with \texttt{lake env lean Math0/ErdosProblems/Erdos142\_erdos\_142.lean} from the \path{lean} directory, which takes about 9 seconds on our machine once the dependencies are built. + +\section{The defect and a corrected statement}\label{sec:defect} + +\subsection*{The defect} +Erd\H{o}s Problem \#142 asks, for each fixed $k$, for a function $f_k$ with $r_k(N)\sim f_k(N)$, and the upstream docstring also asks to ``find $f_k$''; the problem is non-trivial only for $k\ge 3$. The Lean statement differs in two ways. First, \decl{erdos_142.answer} is declared once, outside the scope of the binder $k$, so it cannot depend on $k$. Second, $k$ ranges over all of $\N$, including the degenerate values $k=0,1,2$, for which $r_0(N)=r_1(N)=N$ and $r_2(N)=\min(N,1)$. Together these make the statement false for the elementary reason of Theorem~\ref{thm:main}. + +The history of the file in \cite{FC} explains how this happened. Commit \texttt{bf0ea56f} (pull request \#1187, November 2025) observed that $\texttt{maxCard}\ k\ N=N$ for $k=0,1$ and added the hypothesis $1.answer}; for this file that produced the $k$-independent definition shown in Section~\ref{sec:statement}. Pull request \#5446 \cite{PR5446}, opened on September 10, 2026 and still open in October 2026, lists this statement among answer slots that cannot depend on the inputs they must depend on, and leaves it unchanged. + +\subsection*{A corrected statement} +The repository's contribution guidelines say that if the type of the unknown depends on parameters of the theorem, these become parameters of the definition, and some files already use answer definitions with parameters (for example \decl{erdos_506.variants.large_n.answer}, which takes $n$). Here the type $\N\to\R$ does not depend on $k$ but the value must, and the same device applies. We propose to make $k$ an argument of the unknown and to exclude the degenerate cases: +\begin{lstlisting} +def erdos_142.answer : ℕ → ℕ → ℝ := sorry + +@[category research open, question value, AMS 11] +theorem erdos_142 (k : ℕ) (hk : 3 ≤ k) : + (fun N => (r k N : ℝ)) ~[atTop] erdos_142.answer k := by + sorry +\end{lstlisting} +We checked that this compiles against the pinned formal-conjectures checkout (with the upstream docstring, which we omit here). The essential change is that the answer depends on $k$; the hypothesis $3\le k$ removes the degenerate cases, whose answers $N$, $N$ and $\min(N,1)$ are trivial. As for every value question in \cite{FC}, the corrected statement can be closed by the tautological filling in which \decl{erdos_142.answer} $k$ is $r_k$; the contribution guidelines state that deciding whether a filled-in answer is a mathematically meaningful solution is outside the scope of the repository. + +The sibling statement \decl{erdos_142.variants.isTheta} has the same defect, since $r_1(N)=N=\Theta(f)$ and $r_2(N)=\Theta(f)$ would force $N=O(1)$; math0 treats it in a separate report. The statement \decl{erdos_142.variants.three}, which fixes $k=3$, and \decl{erdos_142.variants.lower}, which assumes $11$ there are integers $N0$ with $B'\subsetneq B$, and one not containing $1$ has negative signed sum. Hence $c(N)=\Theta(N)$; the exact value of $c(N)$ is not known, and no asymptotic constant has been established in the refereed literature. When we checked in October 2026, the forum thread of \cite{EP319} had no comments, and the page listed one unrefereed proof claim, submitted in July 2026, asserting $c(N)=N-o(N)$; we have not checked it, and nothing below depends on it. + +The formal-conjectures repository \cite{FC} contains a Lean statement \decl{Erdos319.erdos_319} of this problem, together with the variants \decl{erdos_319.variants.isTheta} ($c(N)=\Theta(N)$) and \decl{erdos_319.variants.lb} (Adenwalla's bound), both tagged as solved and left with \texttt{sorry} proofs. At the pinned commit \texttt{c77fdd4} the unknown of the main statement is a single top-level definition \decl{erdos_319.answer} of type $\N$, and the theorem asserts, for every $N\in\N$, that this number is the greatest element of the set of sizes of admissible subsets of $\{1,\dots,N\}$ (Section~\ref{sec:statement}). So it claims that $c(N)$ is constant. + +\subsection*{Contribution and status} +We prove (Theorem~\ref{thm:main}) that \decl{Erdos319.erdos_319} is false for every possible value of its unknown, because $c(0)=0$ and $c(6)\ge 3$. This is a \emph{misformalization report}. The argument is elementary and gives no information about the growth of $c(N)$. The defect itself had already been noted informally: the open pull request \#5446 to formal-conjectures \cite{PR5446} lists the answer slot of this statement among slots ``with the same defect'' (answers that cannot depend on inputs they must depend on) which it does not fix; see Section~\ref{sec:defect}. We found no previous formal proof that the statement is false. Section~\ref{sec:defect} proposes a corrected statement. + +\section{Statement}\label{sec:statement} + +\subsection{The upstream statement} +The statement, copied verbatim from \path{FormalConjectures/ErdosProblems/319.lean} (lines 34--52, namespace \decl{Erdos319}, with \texttt{open Filter} and \texttt{open scoped Topology Finset Real}) at commit \texttt{c77fdd4}, is: +\begin{lstlisting} +def erdos_319.answer : ℕ := sorry + +/-- What is the size of the largest $A\subseteq\{1, \dots, N\}$ such that there is a function +$\delta : A \to \{-1, 1\}$ such that +$$ + \sum_{n\in A} \frac{\delta n}{n} = 0 +$$ +and +$$ + \sum_{n\in A'}\frac{\delta n}{n} \neq 0 +$$ +for all non-empty $A'\subsetneq A$. -/ +@[category research open, question value, AMS 5] +theorem erdos_319 (N : ℕ) : IsGreatest + { #A | (A) (_ : A ⊆ Finset.Icc 1 N) + (_ : ∃ δ : ℕ → ℤˣ, ∑ n ∈ A, (δ n : ℚ) / n = 0 ∧ + ∀ A' ⊂ A, A'.Nonempty → ∑ n ∈ A', (δ n : ℚ) / n ≠ 0) } + erdos_319.answer := by + sorry +\end{lstlisting} + +\subsection{Reading of the Lean statement} +Here \texttt{A} and \texttt{A'} range over \texttt{Finset ℕ}, \texttt{\#A} is the cardinality of \texttt{A}, \texttt{Finset.Icc 1 N} is $\{1,\dots,N\}$ (empty for $N=0$) and \texttt{A' ⊂ A} is strict inclusion. The signs are a function $\delta\colon\N\to\Z^\times$, the units of $\Z$, i.e.\ $\delta(n)\in\{-1,1\}$, cast to $\Q$; only its values on $A$ matter, and every map $A\to\{-1,1\}$ extends to such a function, so this matches the docstring. Since $A\subseteq\{1,\dots,N\}$, every denominator is positive, and Lean's convention $x/0=0$ plays no role. The set-builder notation denotes +\[ +S_N=\bigl\{\,|A| \;:\; A\subseteq\{1,\dots,N\},\ A \text{ admissible}\,\bigr\}\subseteq\N, +\] +with admissibility as in \eqref{eq:adm}, and \texttt{IsGreatest S a} means $a\in S$ and $x\le a$ for all $x\in S$. The empty set is admissible (its signed sum is $0$ and it has no nonempty proper subset) and $S_N\subseteq\{0,\dots,N\}$, so $S_N$ has a greatest element, namely $c(N)$. Thus, for each fixed $N$, the proposition \texttt{IsGreatest} $S_N$ $a$ says exactly $a=c(N)$; the encoding of the problem for fixed $N$ is faithful. Writing $a$ for \decl{erdos_319.answer}, the upstream theorem asserts +\begin{equation}\label{eq:upstream} +a=\max S_N=c(N)\qquad\text{for every } N\in\N . +\end{equation} + +\subsection{Main result} + +\begin{theorem}\label{thm:main} +There is no $a\in\N$ satisfying \eqref{eq:upstream}. More precisely, no $a\in\N$ is the greatest element of both $S_0$ and $S_6$. +\end{theorem} + +In Lean (namespace \decl{Math0.Erdos319}): +\begin{lstlisting} +theorem erdos_319_refuted : ∀ c : ℕ, ¬ ∀ N : ℕ, IsGreatest + { #A | (A) (_ : A ⊆ Finset.Icc 1 N) + (_ : ∃ δ : ℕ → ℤˣ, ∑ n ∈ A, (δ n : ℚ) / n = 0 ∧ + ∀ A' ⊂ A, A'.Nonempty → ∑ n ∈ A', (δ n : ℚ) / n ≠ 0) } c +\end{lstlisting} +This type is the type of \decl{Erdos319.erdos_319} with the constant \decl{erdos_319.answer} replaced by a bound variable \texttt{c}, negated and quantified over \texttt{c}. So it refutes the upstream statement for every way of filling in the unknown; Section~\ref{sec:lean} describes the check. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file; each lemma below is a theorem there, named in brackets. Let $\delta_0\colon\N\to\{-1,1\}$ be given by $\delta_0(2)=1$ and $\delta_0(n)=-1$ for $n\ne 2$ (the Lean definition \texttt{δ₀}). + +\begin{lemma}[\decl{eq_zero_of_mem}]\label{lem:S0} +Every element of $S_0$ is $0$. +\end{lemma} + +\begin{proof} +If $|A|\in S_0$ is witnessed by $A$, then $A\subseteq\{1,\dots,0\}=\emptyset$, so $A=\emptyset$ and $|A|=0$. +\end{proof} + +\begin{lemma}[\decl{sum_witness}]\label{lem:sum} +$\sum_{n\in\{2,3,6\}}\delta_0(n)/n=0$. +\end{lemma} + +\begin{proof} +The sum is $\frac12-\frac13-\frac16=\frac{3-2-1}{6}=0$. In Lean, \texttt{simp} with \decl{Finset.sum_insert} and the definition of \texttt{δ₀} expands the sum into these three terms, and \texttt{norm\_num} evaluates it. +\end{proof} + +\begin{lemma}[\decl{proper_witness}]\label{lem:proper} +For every nonempty $A'\subsetneq\{2,3,6\}$, $\sum_{n\in A'}\delta_0(n)/n\ne 0$. +\end{lemma} + +\begin{proof} +The proper subsets of $\{2,3,6\}$ are $\emptyset$ and the six sets in the following table, which lists their signed sums under $\delta_0$: +\begin{center} +\begin{tabular}{@{}lcccccc@{}} +\toprule +$A'$ & $\{2\}$ & $\{3\}$ & $\{6\}$ & $\{2,3\}$ & $\{2,6\}$ & $\{3,6\}$\\ +\midrule +$\sum_{n\in A'}\delta_0(n)/n$ & $\frac12$ & $-\frac13$ & $-\frac16$ & $\frac12-\frac13=\frac16$ & $\frac12-\frac16=\frac13$ & $-\frac13-\frac16=-\frac12$\\ +\bottomrule +\end{tabular} +\end{center} +All six are nonzero, and $\emptyset$ is excluded by the hypothesis that $A'$ is nonempty. + +The Lean proof enumerates the proper subsets by a finite computation. From $A'\subset\{2,3,6\}$ it obtains $A'\subseteq\{2,3,6\}$ and $A'\ne\{2,3,6\}$, i.e.\ $A'\in\mathcal P(\{2,3,6\})\setminus\{\{2,3,6\}\}$ (\texttt{Finset.powerset} followed by \texttt{Finset.erase}). It then proves the equality of finite sets of finite sets +\begin{lstlisting} +(({2, 3, 6} : Finset ℕ).powerset.erase {2, 3, 6}) = + {∅, {2}, {3}, {6}, {2, 3}, {2, 6}, {3, 6}} +\end{lstlisting} +by \texttt{decide}. Equality of \texttt{Finset (Finset ℕ)} is decidable, and the kernel evaluates this decision procedure on the two closed terms, computing the powerset and the erasure, and checks that the result is \texttt{true}; no compiled code (\texttt{native\_decide}) is involved. Rewriting membership in the right-hand side gives seven cases. The case $A'=\emptyset$ contradicts nonemptiness, and in each of the other six cases \texttt{simp} expands the sum as in Lemma~\ref{lem:sum} and \texttt{norm\_num} proves that the resulting rational number, which is the corresponding entry of the table, is nonzero. +\end{proof} + +\begin{lemma}[\decl{three_mem}]\label{lem:S6} +$3\in S_6$. +\end{lemma} + +\begin{proof} +Take $A=\{2,3,6\}$ and the signs $\delta_0$. Then $A\subseteq\{1,\dots,6\}$, the signed sum over $A$ vanishes by Lemma~\ref{lem:sum}, and no nonempty proper subset has vanishing signed sum by Lemma~\ref{lem:proper}. So $A$ is admissible and $|A|=3\in S_6$. In Lean, the inclusion $\{2,3,6\}\subseteq$ \texttt{Finset.Icc 1 6} and the equality $|\{2,3,6\}|=3$ are each closed by \texttt{decide}. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +Let $a\in\N$ and suppose that $a$ is the greatest element of $S_N$ for every $N$. For $N=0$, the membership $a\in S_0$ and Lemma~\ref{lem:S0} give $a=0$. For $N=6$, $a$ is an upper bound of $S_6$, so Lemma~\ref{lem:S6} gives $3\le a$. Together $3\le a=0$, a contradiction (closed by \texttt{omega} in Lean). +\end{proof} + +\begin{remark}\label{rem:values} +The proof uses only that $c(0)=0$ and $c(6)\ge 3$. The degenerate value $N=0$ is not essential: in fact $c(N)=0$ for $0\le N\le 5$ and $c(6)=4$, so any $N\le 5$ could replace $N=0$. We include the short argument, which is not part of the Lean development. Let $A\subseteq\{1,\dots,6\}$ be nonempty with $\sum_{n\in A}\delta(n)/n=0$, and multiply by $60$: $\sum_{n\in A}\delta(n)\,m_n=0$ with $(m_1,\dots,m_6)=(60,30,20,15,12,10)$. Reducing modulo $5$ shows $5\notin A$, since $m_5=12$ is the only $m_n$ not divisible by $5$. Then reducing modulo $2$ shows $4\notin A$, since $m_4=15$ is the only remaining odd $m_n$. Hence $A\subseteq\{1,2,3,6\}$ and $|A|\le 4$. If moreover $A\subseteq\{1,\dots,5\}$, then $A\subseteq\{1,2,3\}$, reducing modulo $3$ excludes $3$ (as $3\mid 60,30$ but $3\nmid 20$), and $\pm60$, $\pm30$, $\pm60\pm30$ are nonzero; so no nonempty subset of $\{1,\dots,5\}$ has a vanishing signed sum and $S_N=\{0\}$ for $N\le 5$. Conversely, $\{1,2,3,6\}$ with $\delta(1)=1$ and $\delta=-1$ elsewhere is admissible by the argument used for $B\cup\{1\}$ in the introduction, since $\frac12+\frac13+\frac16=1$. A direct computer search, also outside the Lean development, gives $c(N)=4$ for $6\le N\le 10$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is the file \path{lean/Math0/ErdosProblems/Erdos319_erdos_319.lean} of the math0 repository (\url{https://github.com/Foundation-0/math0}). It imports the upstream file \path{FormalConjectures/ErdosProblems/319.lean} and the math0 audit commands (\path{lean/Math0/Audit.lean}). In the namespace \decl{Math0.Erdos319} it declares the sign function \texttt{δ₀} and the theorems \decl{sum_witness} (Lemma~\ref{lem:sum}), \decl{proper_witness} (Lemma~\ref{lem:proper}), \decl{three_mem} (Lemma~\ref{lem:S6}), \decl{eq_zero_of_mem} (Lemma~\ref{lem:S0}) and the main theorem \decl{erdos_319_refuted} (Theorem~\ref{thm:main}). It contains no \texttt{sorry}, \texttt{native\_decide}, \texttt{set\_option} or \texttt{axiom}; the only uses of \texttt{decide} are the three small finite-set facts described in Section~\ref{sec:proof}. The file ends, after the namespace, with the audit command +\begin{lstlisting} +#math0_refutes_every_answer Math0.Erdos319.erdos_319_refuted Erdos319.erdos_319 with + Erdos319.erdos_319.answer +\end{lstlisting} + +\subsection*{Audit} +The command \texttt{\#math0\_refutes\_every\_answer} is defined in \path{lean/Math0/Audit.lean}. Given our theorem, the upstream theorem \decl{Erdos319.erdos_319} and its unknown \decl{Erdos319.erdos_319.answer} of type $T$ (here $T=\N$), it fails the build unless: +\begin{enumerate} +\item the two theorems have the same universe parameters and the unknown is not universe-polymorphic; +\item the type of our theorem is syntactically identical, after removing metadata annotations and with no unfolding or definitional-equality check, to $\forall\, a : T,\ \neg P[a]$, where $P[a]$ is the type of the upstream theorem with every occurrence of the constant \decl{Erdos319.erdos_319.answer} replaced by the bound variable $a$; +\item our theorem depends on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}; in particular not on \decl{sorryAx}, on \decl{Lean.ofReduceBool} (used by \texttt{native\_decide}) or on a custom axiom. +\end{enumerate} +The quantification over $a$ is needed because the body of the upstream definition is \texttt{sorry}: a proof of \texttt{¬ Erdos319.erdos\_319} itself would mention the constant \decl{erdos_319.answer}, whose axiom closure contains \decl{sorryAx}. The quantified form avoids this, and it also refutes every future version in which the definition is filled in and the theorem is left unchanged. On this file the command prints: +\begin{lstlisting} +math0 audit: 'Math0.Erdos319.erdos_319_refuted' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Erdos319.erdos_319_refuted' refutes 'Erdos319.erdos_319' for every value of 'Erdos319.erdos_319.answer' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1}, Mathlib \cite{Mathlib} \texttt{v4.33.1} and formal-conjectures \cite{FC} at commit \texttt{c77fdd4} (\texttt{c77fdd446d23539302aa73bcfae4a9fa962b8382}), all pinned in \path{lean/lakefile.toml} and \path{lean/lean-toolchain}. To reproduce, run \path{scripts/verify.sh} from the repository root. It downloads the Mathlib build cache, builds all math0 results with \texttt{lake build} (which re-runs every audit command), checks that the \texttt{formal\_conjectures} and \texttt{mathlib} checkouts have no local modifications, and reports the number of passed statement checks. The single file can be checked with \texttt{lake env lean Math0/ErdosProblems/Erdos319\_erdos\_319.lean} from the \path{lean} directory, which takes about 9 seconds once the dependencies are built. + +\section{The defect and a corrected statement}\label{sec:defect} + +\subsection*{The defect} +Erd\H{o}s Problem \#319 asks for $c(N)$ as a function of $N$, and the upstream docstring asks for ``the size of the largest $A\subseteq\{1,\dots,N\}$''. In the Lean statement, however, \decl{erdos_319.answer} is a natural number declared once, outside the scope of the binder $N$, so it cannot depend on $N$. Since $c$ is not constant, the statement is false for the elementary reason of Theorem~\ref{thm:main}. Unlike some statements with the same kind of defect, restricting the range of $N$ does not help: by Remark~\ref{rem:values}, $c(1)=0<4=c(6)$, and since $c(N)\ge(1-\frac1e+o(1))N$, no constant equals $c(N)$ for all large $N$ either. The repository's own guidelines for reviewing statements ask to check, for a question that asks for a value, ``that the parameters it depends on are parameters of the definition''. + +The history of the file in \cite{FC} shows how the statement reached this form. The original formalization (commit \texttt{aadedd6a}, May 2025) wrote the unknown inline as \texttt{answer(sorry)} after the binder $N$. Pull request \#5446 \cite{PR5446}, opened on September 10, 2026 and still open in October 2026, is titled ``fix: answer slots that cannot depend on the inputs they must depend on''; after fixing several such slots elsewhere, it lists \texttt{319.lean:46} (in the version of the file current at that time, the line holding this \texttt{answer(sorry)}) among further slots with the same defect that it does not fix. Commit \texttt{2c24ebe7} (pull request \#7327, October 14, 2026) then replaced the inline placeholders of value questions by top-level definitions \texttt{.answer}, which for this file produced the $N$-independent definition shown in Section~\ref{sec:statement}. As of October 2026 the file on the main branch of \cite{FC} is unchanged in this respect. + +\subsection*{A corrected statement} +The repository's contribution guidelines let the answer definition take parameters of the theorem. We propose to make $N$ an argument of the unknown: +\begin{lstlisting} +def erdos_319.answer : ℕ → ℕ := sorry + +@[category research open, question value, AMS 5] +theorem erdos_319 (N : ℕ) : IsGreatest + { #A | (A) (_ : A ⊆ Finset.Icc 1 N) + (_ : ∃ δ : ℕ → ℤˣ, ∑ n ∈ A, (δ n : ℚ) / n = 0 ∧ + ∀ A' ⊂ A, A'.Nonempty → ∑ n ∈ A', (δ n : ℚ) / n ≠ 0) } + (erdos_319.answer N) := by + sorry +\end{lstlisting} +We checked that this compiles against the pinned formal-conjectures checkout; the upstream docstring, omitted here, should be kept (without it the repository's docstring linter warns). As for every value question in \cite{FC}, the corrected statement can be closed by the tautological filling in which \decl{erdos_319.answer} $N$ is $\max S_N$; the contribution guidelines state that deciding whether a filled-in answer is a mathematically meaningful solution is outside the scope of the repository. The upstream file itself notes that a solution may have to be expressed asymptotically, which is the role of \decl{erdos_319.variants.isTheta}. That variant and \decl{erdos_319.variants.lb} quantify over $N$ correctly (the former takes $c\colon\N\to\R$ as an argument, with the hypothesis that $c(N)=\max S_N$ for every $N$; the latter uses $\sup S_N$) and are not affected by the defect. + +\begin{thebibliography}{99} + +\bibitem{EP319} +T.~F. Bloom, \emph{Erd\H{o}s Problem \#319}, \url{https://www.erdosproblems.com/319}, accessed October 2026. + +\bibitem{Cr01} +E.~S. Croot III, \emph{On unit fractions with denominators in short intervals}, Acta Arith. \textbf{99} (2001), no.~2, 99--114. + +\bibitem{EPdb} +Erd\H{o}s problems database contributors (maintained by T.~F. Bloom and T.~Tao), \emph{Erd\H{o}s problems database}, \url{https://github.com/teorth/erdosproblems}, accessed October 2026. + +\bibitem{ErGr80} +P.~Erd\H{o}s and R.~L. Graham, \emph{Old and New Problems and Results in Combinatorial Number Theory}, Monographies de L'Enseignement Math\'ematique \textbf{28}, Universit\'e de Gen\`eve, Geneva, 1980. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{PR5446} +formal-conjectures, pull request \#5446, \emph{fix: answer slots that cannot depend on the inputs they must depend on}, opened September 10, 2026, \url{https://github.com/google-deepmind/formal-conjectures/pull/5446}. + +\end{thebibliography} + +\end{document} diff --git a/results/erdos367-erdos-367-variants-higher-full-parts/README.md b/results/erdos367-erdos-367-variants-higher-full-parts/README.md new file mode 100644 index 0000000..ba4e124 --- /dev/null +++ b/results/erdos367-erdos-367-variants-higher-full-parts/README.md @@ -0,0 +1,44 @@ +# Erdős 367 (higher full parts): the product of r-full parts beats n^(1+ε) infinitely often + +**Classification:** First formal proof of a known result +**Area:** Number theory +**Source problem:** Erdős Problem #367 +**Date:** 2026-10-17 + +## Result + +Let $B_r(m)=\prod_{p^a\,\|\,m,\ a\ge r} p^a$ be the $r$-full part of $m$ (with $B_r(0)=1$). For all integers $r\ge 3$ and $k\ge 2$ there is some $\varepsilon=\varepsilon(r,k)>0$ such that +$$\limsup_{n\to\infty}\frac{\prod_{n\le m0" wording; status open (also open in local problems.yaml, formalized 2026-08-20). +- Forum thread erdosproblems.com/forum/thread/367: + - post-1766, Woett (van Doorn), 20 Nov 2025: proposes the ε=ε(r,k) reading. + - post-6910, ScottHughes, 10 Jun 2026: claims an affirmative resolution for all r,k≥2 with any ε<(r+1)/r², via n=(t^r−1)^r (odd r) and n=(t^r+1)^r−1 (even r). These constructions trivially give ε<1/r. +- Repository: https://github.com/scottdhughes/erdos367 + +(Abridged.) + +## Citation + +```bibtex +@misc{math0:erdos367-erdos-367-variants-higher-full-parts, + author = {{math0}}, + title = {{Erdős 367 (higher full parts): the product of r-full parts beats n^(1+ε) infinitely often}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos367-erdos-367-variants-higher-full-parts}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos409-erdos-409-parts-i/README.md b/results/erdos409-erdos-409-parts-i/README.md new file mode 100644 index 0000000..329164d --- /dev/null +++ b/results/erdos409-erdos-409-parts-i/README.md @@ -0,0 +1,34 @@ +# Erdős 409(i): no constant iteration count works for every starting value (formalization defect) + +**Classification:** Misformalization found (upstream statement does not match the problem) +**Area:** Number theory +**Source problem:** Erdős Problem #409 +**Date:** 2026-10-17 + +## Result + +The upstream statement says: for every n > 0, the least i ≥ 0 such that the i-th iterate of f(m) = φ(m) + 1, started at n, is prime equals one fixed natural number `erdos_409.parts.i.answer` (a constant that does not depend on n). We prove the negation for every possible value of that constant: for all a ∈ ℕ, it is not the case that for every n > 0, a is the least element of {i : f^[i](n) is prime}. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos409_erdos_409_parts_i.lean`](../../lean/Math0/ErdosProblems/Erdos409_erdos_409_parts_i.lean) refutes, for every possible value of its unknown, the upstream statement [`Erdos409.erdos_409.parts.i`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/409.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research open`). Its final command `#math0_refutes_every_answer` checks that our theorem's type is syntactically identical to the upstream statement negated and universally quantified over the unknown and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +erdosproblems.com/409 (problems.yaml: status open, last_update 2025-08-31; OEIS A039651, A229487) asks how many iterations of n ↦ φ(n)+1 are needed to reach a prime. The answer is a function c(n), as in OEIS A039651, whose values include c(2)=0 and c(4)=1. The solver did not settle the actual asymptotic question, which the upstream erdos_409.parts.i.isTheta/isBigO/isLittleO variants state. The refutation uses only the fact that c(n) is not constant. erdosproblems.com/409 (open; attributed to Finucane, [ErGr80, p.81], Guy B41; it reads the question as bounding F(n), notes F(n)=o(n) is trivial and F(n)=1 infinitely often, per comments by S. Cambie). OEIS A039651 (number of iterations of n -> phi(n)+1 to reach a prime: a(1)=1, a(2)=0, a(3)=0, a(4)=1, so the value is not constant) and A229487. Local problems.yaml entry for 409: status open (2025-08-31), formalized yes. Upstream google-deepmind/formal-conjectures FormalConjectures/ErdosProblems/409.lean on main still declares `def erdos_409.parts.i.answer : ℕ := sorry` with the per-n IsLeast claim. The file has isTheta/isBigO/isLittleO variants with c : ℕ → ℕ that state the intended problem correctly. Formal Conjectures paper (arXiv 2605.13171) gives the misformalization taxonomy (translation-level error). I found no prior public report of this specific defect. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:erdos409-erdos-409-parts-i, + author = {{math0}}, + title = {{Erdős 409(i): no constant iteration count works for every starting value (formalization defect)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos409-erdos-409-parts-i}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos409-erdos-409-parts-i/paper.pdf b/results/erdos409-erdos-409-parts-i/paper.pdf new file mode 100644 index 0000000..e7deb08 Binary files /dev/null and b/results/erdos409-erdos-409-parts-i/paper.pdf differ diff --git a/results/erdos409-erdos-409-parts-i/paper.tex b/results/erdos409-erdos-409-parts-i/paper.tex new file mode 100644 index 0000000..06ede6a --- /dev/null +++ b/results/erdos409-erdos-409-parts-i/paper.tex @@ -0,0 +1,288 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage[T1]{fontenc} +\usepackage{lmodern} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,sorry,subst}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + upquote=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℝ}{{$\mathbb{R}$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {·}{{$\cdot$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {¬}{{$\neg$}}1 {→}{{$\to$}}1 {↦}{{$\mapsto$}}1 {∈}{{$\in$}}1 + {φ}{{$\varphi$}}1 {σ}{{$\sigma$}}1 {Θ}{{$\Theta$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{Θ}{\ensuremath{\Theta}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\DeclareMathOperator{\IsLeast}{IsLeast} + +\title[The iteration count of $n\mapsto\varphi(n)+1$ is not constant]{The number of iterations of $n\mapsto\varphi(n)+1$ needed to reach a prime is not constant: a defect in the formal statement of Erd\H{o}s Problem \#409(i)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 17, 2026} + +\begin{document} +\begin{abstract} +Let $F(n)$ be the least number of iterations of $m\mapsto\varphi(m)+1$, started at $n$, after which a prime is reached; the first part of Erd\H{o}s Problem \#409 asks how large $F(n)$ is, and it is open. The formal-conjectures repository states this part in Lean as the claim that $F(n)$ equals one unknown natural number, the same for every $n>0$. We prove that this claim is false for every value of the unknown, because $F(2)=0$ while $F(4)\ne 0$; the argument is elementary, so this is a misformalization report that says nothing about the open problem, and we discuss a corrected statement. The proof is verified in Lean~4 against the upstream formal-conjectures statement, together with a check that our theorem is exactly that statement, negated and quantified over all values of the unknown. +\end{abstract} +\maketitle + +\section{Introduction} + +Let $\varphi$ be Euler's totient function and $f(m)=\varphi(m)+1$. Since $\varphi(m)=m-1$ exactly when $m$ is prime, and $f(0)=1$, $f(1)=2$, the fixed points of $f$ are exactly the primes. If $n>1$ is not prime, then $\varphi(n)0$, this number is the least $i$ with $f^{(i)}(n)$ prime (Section~\ref{sec:statement}). The unknown cannot depend on $n$. The same file also states the question in three asymptotic forms, \decl{erdos_409.parts.i.isTheta}, \decl{erdos_409.parts.i.isBigO} and \decl{erdos_409.parts.i.isLittleO}, in which the iteration count is a function $c\colon\N\to\N$; these match the problem and are not affected by the present note. + +\subsection*{Contribution and status} +We prove (Theorem~\ref{thm:main}) that \decl{Erdos409.erdos_409.parts.i} is false for every possible value of its unknown, because $F(2)=0$ and $F(4)\ne 0$. This is a \emph{misformalization report}. It does not bear on the open question of how $F(n)$ grows. The defect had already been pointed out informally: an open pull request to \cite{FC} lists this statement among answer slots that cannot depend on inputs they must depend on (Section~\ref{sec:defect}). We found no previous formal proof that the statement is false. Section~\ref{sec:defect} discusses a corrected statement (the fix proposed in that pull request, adapted to the current form of the file) and notes that the sibling statement \decl{erdos_409.variants.sigma} has the same defect. + +\section{Statement}\label{sec:statement} + +\subsection{Notation} +Let $\N=\{0,1,2,\dots\}$, let $\varphi\colon\N\to\N$ be Euler's totient function (Mathlib's \decl{Nat.totient}, with $\varphi(0)=0$), and let $f(m)=\varphi(m)+1$. Write $f^{(0)}=\mathrm{id}$ and $f^{(i+1)}=f\circ f^{(i)}$. For $n\in\N$ put +\[ +S(n)=\{\,i\in\N:\ f^{(i)}(n)\text{ is prime}\,\}. +\] +For $S\subseteq\N$ and $a\in\N$, $\IsLeast(S,a)$ means that $a\in S$ and $a\le i$ for all $i\in S$ (Mathlib's \decl{IsLeast}). For $n>0$ the set $S(n)$ is nonempty (this is the upstream lemma \decl{erdos_409.variants.termination}, proved by the argument in the introduction), and $F(n)=\min S(n)$ is the unique $a$ with $\IsLeast(S(n),a)$. + +\subsection{The upstream statement} +The statement, copied verbatim from \path{FormalConjectures/ErdosProblems/409.lean} (lines 33--44, namespace \decl{Erdos409}, with \texttt{open scoped Nat}, so that \texttt{φ} denotes \decl{Nat.totient}) at commit \texttt{c77fdd4}, is: +\begin{lstlisting} +def erdos_409.parts.i.answer : ℕ := sorry + +/-- +How many iterations of $n\mapsto\phi(n) + 1$ are needed before a prime is reached? +-/ +-- Formalisation note: the sequence of iterates always terminates if `n > 0` +-- since it is strictly decreasing unless the input is prime, at which point +-- it becomes static. See also https://oeis.org/A39651 +@[category research open, question value, AMS 11] +theorem erdos_409.parts.i (n : ℕ) (hn : 0 < n) : + IsLeast { i | (φ · + 1)^[i] n |>.Prime } erdos_409.parts.i.answer := by + sorry +\end{lstlisting} +Here \texttt{(φ · + 1)} is the function $f$, \texttt{g\^{}[i]} is the $i$-th iterate of \texttt{g}, and \texttt{x |>.Prime} is \texttt{Nat.Prime x}. So the set in the statement is $S(n)$, and with $A=\texttt{erdos\_409.parts.i.answer}\in\N$ the statement asserts +\begin{equation}\label{eq:upstream} +\IsLeast\bigl(S(n),A\bigr)\qquad\text{for every } n\in\N \text{ with } n>0, +\end{equation} +that is, $F(n)=A$ for every $n>0$. + +\subsection{Main result} + +\begin{theorem}\label{thm:main} +There is no $a\in\N$ such that $\IsLeast(S(n),a)$ holds for every $n>0$. More precisely, no $a\in\N$ satisfies both $\IsLeast(S(2),a)$ and $\IsLeast(S(4),a)$. +\end{theorem} + +In Lean (namespace \decl{Math0.Erdos409}): +\begin{lstlisting} +theorem erdos_409_parts_i_refuted : ∀ a : ℕ, ¬ ∀ (n : ℕ) (_ : 0 < n), + IsLeast { i | (φ · + 1)^[i] n |>.Prime } a +\end{lstlisting} +This type is the type of \decl{Erdos409.erdos_409.parts.i} with the constant \decl{erdos_409.parts.i.answer} replaced by a bound variable \texttt{a}, negated and quantified over \texttt{a}. So it refutes the upstream statement for every way of filling in the unknown; Section~\ref{sec:lean} describes the check. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file, whose two auxiliary theorems are Lemmas~\ref{lem:two} and~\ref{lem:four}. + +\begin{lemma}[\decl{eq_zero_of_isLeast_two}]\label{lem:two} +If $a\in\N$ and $\IsLeast(S(2),a)$, then $a=0$. +\end{lemma} + +\begin{proof} +Since $f^{(0)}(2)=2$ is prime (Mathlib's \decl{Nat.prime_two}), $0\in S(2)$. As $a$ is a lower bound of $S(2)$, $a\le 0$, hence $a=0$. +\end{proof} + +\begin{lemma}[\decl{not_isLeast_four_zero}]\label{lem:four} +$\IsLeast(S(4),0)$ does not hold. +\end{lemma} + +\begin{proof} +$\IsLeast(S(4),0)$ would give $0\in S(4)$, that is, $f^{(0)}(4)=4$ would be prime. But $4=2\cdot 2$ is not prime. +\end{proof} + +In Lean, the membership statements are reduced to \texttt{Nat.Prime 2} and \texttt{Nat.Prime 4} by \texttt{simp} with the lemmas \decl{Set.mem_ofPred_eq}, \decl{Function.iterate_zero} and \decl{id_eq}. The fact $\neg\,\texttt{Nat.Prime 4}$ is proved by \texttt{decide}: the kernel evaluates Mathlib's decision procedure \decl{Nat.decidablePrime}, which tests $2\le p$ and that no $m$ with $2\le m0$. Taking $n=2$ gives $\IsLeast(S(2),a)$, so $a=0$ by Lemma~\ref{lem:two}. Taking $n=4$ now gives $\IsLeast(S(4),0)$, which contradicts Lemma~\ref{lem:four}. +\end{proof} + +\begin{remark} +The proof only uses that $F(2)=0$ and $F(4)\ne 0$. In fact $F(4)=1$, since $f(4)=\varphi(4)+1=3$, and more generally $F(2p)=1$ for every odd prime $p$, since $2p$ is not prime and $\varphi(2p)+1=p$; this is one way to see the remark of \cite{EP409} that $F(n)=1$ infinitely often. Also $F(1)=1$ because $f(1)=2$. These values agree with A039651 \cite{OEIS-A039651}. None of this is needed for Theorem~\ref{thm:main}, and none of it says anything about upper bounds for $F(n)$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is the file \path{lean/Math0/ErdosProblems/Erdos409_erdos_409_parts_i.lean} of the math0 repository (\url{https://github.com/Foundation-0/math0}). It imports the upstream file \path{FormalConjectures/ErdosProblems/409.lean} and the math0 audit commands (\path{lean/Math0/Audit.lean}). It declares \decl{Math0.Erdos409.eq_zero_of_isLeast_two} (Lemma~\ref{lem:two}), \decl{Math0.Erdos409.not_isLeast_four_zero} (Lemma~\ref{lem:four}) and the main theorem \decl{Math0.Erdos409.erdos_409_parts_i_refuted} (Theorem~\ref{thm:main}). It contains no \texttt{sorry}, \texttt{native\_decide}, \texttt{set\_option} or \texttt{axiom}. The file ends, after the namespace, with the audit command +\begin{lstlisting} +#math0_refutes_every_answer Math0.Erdos409.erdos_409_parts_i_refuted Erdos409.erdos_409.parts.i + with Erdos409.erdos_409.parts.i.answer +\end{lstlisting} + +\subsection*{Audit} +The command \texttt{\#math0\_refutes\_every\_answer} is defined in \path{lean/Math0/Audit.lean}. Given our theorem, the upstream theorem \decl{Erdos409.erdos_409.parts.i} and its unknown \decl{Erdos409.erdos_409.parts.i.answer} of type $T$ (here $T=\N$), it fails the build unless: +\begin{enumerate} +\item the two theorems have the same universe parameters and the unknown is not universe-polymorphic; +\item the type of our theorem, after metadata annotations are removed, is equal as a Lean expression (up to the names and binder annotations of bound variables, with no unfolding of definitions and no definitional-equality check) to $\forall\, a : T,\ \neg P[a]$, where $P[a]$ is the type of the upstream theorem with every occurrence of the constant \decl{Erdos409.erdos_409.parts.i.answer} replaced by the bound variable $a$; +\item our theorem depends on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}; in particular not on \decl{sorryAx}, on \decl{Lean.ofReduceBool} (used by \texttt{native\_decide}) or on a custom axiom. +\end{enumerate} +The quantification over $a$ is needed because the body of the upstream definition is \texttt{sorry}. Applying our theorem to the constant itself yields a proof of the negation of the statement of \decl{Erdos409.erdos_409.parts.i}, but its axiom closure contains \decl{sorryAx}, reached through the body of the placeholder. The quantified form avoids this, and it also refutes every future version in which the definition is filled in and the theorem is left unchanged. On this file the command prints: +\begin{lstlisting} +math0 audit: 'Math0.Erdos409.erdos_409_parts_i_refuted' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Erdos409.erdos_409_parts_i_refuted' refutes 'Erdos409.erdos_409.parts.i' for every value of 'Erdos409.erdos_409.parts.i.answer' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1}, Mathlib \cite{Mathlib} \texttt{v4.33.1} and formal-conjectures \cite{FC} at commit \texttt{c77fdd4} (\texttt{c77fdd446d23539302aa73bcfae4a9fa962b8382}), all pinned in the \path{lean} directory (files \path{lakefile.toml} and \path{lean-toolchain}). To reproduce, run \path{scripts/verify.sh} from the repository root. It downloads the Mathlib build cache, builds all math0 results with \texttt{lake build} (which re-runs every audit command), checks that the \texttt{formal\_conjectures} and \texttt{mathlib} checkouts have no local modifications, and reports the number of passed statement checks. The single file can be checked with \texttt{lake env lean Math0/ErdosProblems/Erdos409\_erdos\_409\_parts\_i.lean} from the \path{lean} directory, which takes a few seconds once the dependencies are built. + +\section{The defect and a corrected statement}\label{sec:defect} + +\subsection*{The defect} +The quantity asked about in Erd\H{o}s Problem \#409(i) is the function $n\mapsto F(n)$, and the question is how it grows. The Lean statement \decl{erdos_409.parts.i} instead declares its unknown \decl{erdos_409.parts.i.answer} once, outside the scope of the binder $n$, as a single natural number, and asserts that it equals $F(n)$ for every $n>0$. Since $F$ is not constant, this is false for the elementary reason of Theorem~\ref{thm:main}. + +In earlier versions of the file the unknown was written inline as \texttt{answer(sorry)} inside the statement, after the binder $n$. Commit \texttt{2c24ebe7} (pull request \#7327, October 14, 2026) replaced inline \texttt{answer(sorry)} placeholders of value questions by top-level definitions \texttt{.answer}; for this statement that produced the $n$-independent definition shown in Section~\ref{sec:statement}. Pull request \#5446 \cite{PR5446}, opened on September 10, 2026 and still open in October 2026, lists \decl{erdos_409.parts.i} and \decl{erdos_409.variants.sigma} among answer slots that cannot depend on the inputs they must depend on, in the setting where the answer is extracted to a closed top-level definition, and proposes to apply a closed function to the theorem's binders. + +\subsection*{A corrected statement} +The contribution guidelines of \cite{FC} say that if the type of the unknown depends on parameters of the theorem, these become parameters of the definition. Here the type $\N$ does not depend on $n$ but the value must, and the same device applies; this is the fix proposed in \cite{PR5446} (written there for the earlier inline placeholder), restated with a top-level definition: +\begin{lstlisting} +def erdos_409.parts.i.answer : ℕ → ℕ := sorry + +@[category research open, question value, AMS 11] +theorem erdos_409.parts.i (n : ℕ) (hn : 0 < n) : + IsLeast { i | (φ · + 1)^[i] n |>.Prime } (erdos_409.parts.i.answer n) := by + sorry +\end{lstlisting} +We checked that this compiles against the pinned formal-conjectures checkout (docstring omitted here). It is consistent, but it only asks for the function $F$ itself, and it is satisfied by the tautological filling $\texttt{answer}\ n=\min S(n)$ (Lean's \decl{sInf}). We checked this filling in Lean as well, with a two-line proof from the upstream lemma \decl{erdos_409.variants.termination} and Mathlib's \decl{Nat.sInf_mem} and \decl{Nat.sInf_le}, using only the three permitted axioms; this check is not part of the math0 repository. The contribution guidelines state that deciding whether a filled-in answer is a mathematically meaningful solution is outside the scope of the repository, so this is not a defect of the corrected form. Still, the content of the question, good upper bounds for $F(n)$, is carried by the asymptotic variants, for example +\begin{lstlisting} +theorem erdos_409.parts.i.isTheta (c : ℕ → ℕ) + (h : ∀ n > 0, IsLeast { i | (φ · + 1)^[i] n |>.Prime } (c n)) : + (fun n => (c n : ℝ)) =Θ[atTop] erdos_409.parts.i.isTheta.answer := by + sorry +\end{lstlisting} +in which $c$ is a function of $n$. An alternative correction is therefore to remove \decl{erdos_409.parts.i} and keep these variants. + +\subsection*{The \texorpdfstring{$\sigma$}{sigma} variant} +The statement \decl{erdos_409.variants.sigma} (lines 131--143 of the same file) has the same defect. With $g(m)=\sigma(m)-1$, where $\sigma$ is the sum-of-divisors function, it asserts that one constant \decl{erdos_409.variants.sigma.answer} is the least $i$ with $g^{(i)}(n)$ prime, for every $n>1$ whose $g$-trajectory reaches a prime. At $n=2$ this least $i$ is $0$. At $n=4$, which is not prime, the trajectory $4\mapsto 6\mapsto 11$ reaches a prime, since $\sigma(4)-1=6$ and $\sigma(6)-1=11$, and the least $i$ is $2\ne 0$. So this statement is also false for every value of its unknown, by the same two-point argument. This observation is not part of the Lean development described here. + +\begin{thebibliography}{99} + +\bibitem{EP409} +T.~F. Bloom, \emph{Erd\H{o}s Problem \#409}, \url{https://www.erdosproblems.com/409}, accessed October 2026. + +\bibitem{EPdb} +Erd\H{o}s problems database contributors, \emph{Erd\H{o}s problem database}, \url{https://github.com/teorth/erdosproblems}, entry 409 (status: open, last updated August 31, 2025). + +\bibitem{ErGr80} +P.~Erd\H{o}s and R.~L. Graham, \emph{Old and new problems and results in combinatorial number theory}, Monographies de L'Enseignement Math\'ematique \textbf{28}, Universit\'e de Gen\`eve, Geneva, 1980. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Gu04} +R.~K. Guy, \emph{Unsolved Problems in Number Theory}, 3rd ed., Problem Books in Mathematics, Springer-Verlag, New York, 2004. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{OEIS-A039651} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, sequence A039651 (D.~W. Wilson), \emph{Number of iterations of $f(x)=\varphi(x)+1$ on $n$ required to reach a prime}, \url{https://oeis.org/A039651}. + +\bibitem{OEIS-A229487} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, sequence A229487 (T.~D. Noe), \emph{Conjectured greatest number that converges to prime$(n)$ under the iteration $x\mapsto\varphi(x)+1$}, \url{https://oeis.org/A229487}. + +\bibitem{PR5446} +formal-conjectures, pull request \#5446, \emph{fix: answer slots that cannot depend on the inputs they must depend on}, opened September 10, 2026, \url{https://github.com/google-deepmind/formal-conjectures/pull/5446}. + +\end{thebibliography} + +\end{document} diff --git a/results/erdos723-erdos-723-variants-prime-power-is-projplane-order/README.md b/results/erdos723-erdos-723-variants-prime-power-is-projplane-order/README.md new file mode 100644 index 0000000..4c74dcf --- /dev/null +++ b/results/erdos723-erdos-723-variants-prime-power-is-projplane-order/README.md @@ -0,0 +1,30 @@ +# Projective planes exist for every prime-power order (Erdős 723, existence variant) + +**Classification:** First formal proof of a known result +**Area:** Combinatorics +**Source problem:** Erdős Problem #723 +**Date:** 2026-10-17 + +## Result + +For every natural number n that is a prime power, there exist types P, L (in Type), a membership (incidence) relation between P and L, Fintype structures on P and L, and a projective plane structure pp on (P, L) whose order is exactly n. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos723_erdos_723_variants_prime_power_is_projplane_order.lean`](../../lean/Math0/ErdosProblems/Erdos723_erdos_723_variants_prime_power_is_projplane_order.lean) proves the upstream statement [`Erdos723.erdos_723.variants.prime_power_is_projplane_order`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/723.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +The construction of the Desarguesian projective plane PG(2, q) for every prime power q goes back to O. Veblen and W. H. Bussey, "Finite projective geometries", Trans. AMS 7 (1906), 241–259. Standard textbook sources are M. Hall, "Combinatorial Theory", and P. Dembowski, "Finite Geometries" (1968). The open converse is the prime power conjecture (Erdős Problem 723). Related results are Bruck–Ryser (1949), and Lam–Thiel–Swiercz (1989), who showed there is no plane of order 10. In Lean, Mathlib's Combinatorics/Configuration.lean has `Configuration.ofField` (the ProjectivePlane instance on ℙ(K³)) and `ProjectivePlane.card_points`, and LinearAlgebra/Projectivization/Cardinality.lean has `Projectivization.card_of_finrank`. Mathlib does not state the order of ofField or the existence of a plane of every prime-power order, and erdosproblems.com lists 723 as formal_status "unformalized". + +## Citation + +```bibtex +@misc{math0:erdos723-erdos-723-variants-prime-power-is-projplane-order, + author = {{math0}}, + title = {{Projective planes exist for every prime-power order (Erdős 723, existence variant)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos723-erdos-723-variants-prime-power-is-projplane-order}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos750-erdos-750-variants-c-gt-quarter/README.md b/results/erdos750-erdos-750-variants-c-gt-quarter/README.md new file mode 100644 index 0000000..7f1924b --- /dev/null +++ b/results/erdos750-erdos-750-variants-c-gt-quarter/README.md @@ -0,0 +1,40 @@ +# Erdős–Hajnal: infinite chromatic number with independent sets of size m/2 − cm for every c > 1/4 + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Combinatorics +**Source problem:** Erdős Problem #750 +**Date:** 2026-10-17 + +## Result + +For every real c > 1/4 (formally c ∈ ℝ≥0) there is a graph G, on a vertex type in any prescribed universe, with chromatic number ∞, such that every set S of m ≥ 1 vertices contains an independent set I with m/2 − c·m ≤ |I|. The subtraction is truncated subtraction in ℝ≥0. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos750_erdos_750_variants_c_gt_quarter.lean`](../../lean/Math0/ErdosProblems/Erdos750_erdos_750_variants_c_gt_quarter.lean) proves the upstream statement [`Erdos750.erdos_750.variants.c_gt_quarter`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/750.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +The problem and its variants: +- Erdős and Hajnal [ErHa67b], "On chromatic graphs", Mat. Lapok (1967), 1–4: graphs of infinite chromatic number in which every m-vertex subgraph has an independent set of size at least m/2 − cm, for any c > 1/4. The classical example is the shift graph with the random-cut argument used here. +- Erdős, Hajnal and Szemerédi [EHS82]: the f(m) = εm case, via a comment by Sellke on erdosproblems. +- Chojecki with GPT-5.5 Pro (ulam.ai/research/erdos750.pdf): the general f → ∞ case. +- Stiebitz [St85], Sachs and Stiebitz [SaSt89], Müller and Stehlík [MuSt19]: the generalised Mycielskian chromatic bound used in that proof. + +Existing Lean proofs: +- plby/lean-proofs src/latest/ErdosProblems/Erdos750.lean, commit 8822f7dd: an unconditional `theorem erdos_750` in formal-conjectures form. It implies variants.c_gt_quarter directly by taking f(m) = c·m. +- Jayyhk/erdos-lean problems/750/Erdos750.lean. +- Shashi456/erdos-formalizations: the conditional version. +- erdosproblems.com lists #750 as "proved (Lean)", last updated 2025-08-31. + +## Citation + +```bibtex +@misc{math0:erdos750-erdos-750-variants-c-gt-quarter, + author = {{math0}}, + title = {{Erdős–Hajnal: infinite chromatic number with independent sets of size m/2 − cm for every c > 1/4}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos750-erdos-750-variants-c-gt-quarter}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos775-erdos-775-variants-moon-moser/README.md b/results/erdos775-erdos-775-variants-moon-moser/README.md new file mode 100644 index 0000000..0f2858c --- /dev/null +++ b/results/erdos775-erdos-775-variants-moon-moser/README.md @@ -0,0 +1,30 @@ +# Moon–Moser: a graph on n vertices has at most n − log₂ n + 1 maximal-clique sizes + +**Classification:** First formal proof of a known result +**Area:** Combinatorics +**Source problem:** Erdős Problem #775 +**Date:** 2026-10-17 + +## Result + +There is a real constant C such that for every n ∈ ℕ and every simple graph G on Fin n, the number of distinct sizes of maximal cliques of G (the ncard of SimpleGraph.cliqueSizes G = {k | ∃ S : Finset, S is a maximal clique, |S| = k}) is at most n − log₂ n + C. Here Real.logb 2 0 = 0. We prove it with C = 1, for every n including n = 0. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos775_erdos_775_variants_moon_moser.lean`](../../lean/Math0/ErdosProblems/Erdos775_erdos_775_variants_moon_moser.lean) proves the upstream statement [`Erdos775.erdos_775.variants.moon_moser`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/775.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +J. W. Moon and L. Moser, "On cliques in graphs", Israel J. Math. 3 (1965), 23-28. Proves that the number of distinct maximal-clique sizes on n vertices is at most n − ⌊log₂ n⌋, which is the n − log₂ n + O(1) upper bound. J. H. Spencer, "On cliques in graphs", Israel J. Math. 9 (1971), 419-421. Gives the matching lower-bound construction. J. Gao, "On cliques in hypergraphs", arXiv:2510.14804 (2025). Settles the main 3-uniform hypergraph question. erdosproblems.com/775 has status "disproved (Lean)". The existing Lean proof (github.com/plby/lean-proofs src/v4.29.1/ErdosProblems/Erdos775.lean, by Aristotle and L. Luccioli) covers only Gao's hypergraph theorem, not the graph Moon–Moser variant. + +## Citation + +```bibtex +@misc{math0:erdos775-erdos-775-variants-moon-moser, + author = {{math0}}, + title = {{Moon–Moser: a graph on n vertices has at most n − log₂ n + 1 maximal-clique sizes}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos775-erdos-775-variants-moon-moser}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos816-erdos-816-variants-complete-bipartite/README.md b/results/erdos816-erdos-816-variants-complete-bipartite/README.md new file mode 100644 index 0000000..37b6225 --- /dev/null +++ b/results/erdos816-erdos-816-variants-complete-bipartite/README.md @@ -0,0 +1,30 @@ +# K_{n,n+1} is extremal for Erdős Problem 816 + +**Classification:** First formal proof of a known result +**Area:** Combinatorics +**Source problem:** Erdős Problem #816 +**Date:** 2026-10-17 + +## Result + +For every natural number n, the complete bipartite graph K_{n,n+1} (vertex set Fin n ⊕ Fin (n+1), so 2n+1 vertices) has exactly n^2 + n edges, and it does not contain two distinct vertices u ≠ v with deg u = deg v that are joined by a path of length 3. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos816_erdos_816_variants_complete_bipartite.lean`](../../lean/Math0/ErdosProblems/Erdos816_erdos_816_variants_complete_bipartite.lean) proves the upstream statement [`Erdos816.erdos_816.variants.complete_bipartite`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/816.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Erdős Problem 816 (Erdős–Hajnal), erdosproblems.com/816 (status: proved, not marked as Lean). [Er91] Erdős, Problems and results in combinatorial analysis and combinatorial number theory (1991), where K_{n,n+1} is the standard example showing that n^2+n edges do not suffice. [ChMa25] K. Chen and J. Ma, arXiv:2503.19569 (2025), proved the main conjecture and showed that for n ≥ 600, K_{n,n+1} is the unique exception with n^2+n edges. The main theorem has an existing Lean proof at plby/lean-proofs (commit 8822f7d, src/latest/ErdosProblems/Erdos816.lean, L939), but that file contains no K_{n,n+1} or complete_bipartite lemma. So this variant appears to be formalized here for the first time. + +## Citation + +```bibtex +@misc{math0:erdos816-erdos-816-variants-complete-bipartite, + author = {{math0}}, + title = {{K_{n,n+1} is extremal for Erdős Problem 816}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos816-erdos-816-variants-complete-bipartite}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos834-erdos-834-parts-ii/README.md b/results/erdos834-erdos-834-parts-ii/README.md new file mode 100644 index 0000000..ae99073 --- /dev/null +++ b/results/erdos834-erdos-834-parts-ii/README.md @@ -0,0 +1,30 @@ +# A 7-regular 3-critical 3-uniform hypergraph on 9 vertices (Erdős Problem 834, chromatic version) + +**Classification:** First formal proof of a known result +**Area:** Combinatorics +**Source problem:** Erdős Problem #834 +**Date:** 2026-10-17 + +## Result + +There exist n and a 3-uniform hypergraph H on the vertex set {0,…,n−1} such that: (1) H has weak chromatic number exactly 3, meaning it has a vertex 3-coloring with no monochromatic edge but no such coloring with 0, 1 or 2 colors; (2) for every edge e of H, the hypergraph H − e is 2-colorable; (3) for every vertex v, the hypergraph made of the edges of H that avoid v is 2-colorable; and (4) every vertex of {0,…,n−1} lies in at least 7 edges. This is the question of Erdős and Lovász, Erdős Problem 834, part (ii), answered positively by Li [Li25] with a 22-edge example. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos834_erdos_834_parts_ii.lean`](../../lean/Math0/ErdosProblems/Erdos834_erdos_834_parts_ii.lean) proves the upstream statement [`Erdos834.erdos_834.parts.ii`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/834.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Erdős Problem 834 (erdosproblems.com/834, from [Er74d, p.282], a problem of Erdős and Lovász). It was solved by R. Li, "On an Erdős–Lovász problem: 3-critical 3-graphs of minimum degree 7", arXiv:2512.24850 (Dec 2025). For the transversal reading, Li shows there are at most 10 edges, so some vertex has degree at most 6, and K_5^(3) shows this is sharp. For the chromatic reading, Li gives an explicit 9-vertex 3-graph with minimum degree 7 (22 edges per the solver) and backs it with witness 2-colorings and a verification script, not a Lean proof. The erdosproblems database (problems.yaml) lists status "solved" (not "(Lean)") and formal_status "unformalized". The formal-conjectures statement Erdos834.erdos_834.parts.ii is still sorry. The solver's witness is a different, 21-edge 7-regular hypergraph on 9 vertices. + +## Citation + +```bibtex +@misc{math0:erdos834-erdos-834-parts-ii, + author = {{math0}}, + title = {{A 7-regular 3-critical 3-uniform hypergraph on 9 vertices (Erdős Problem 834, chromatic version)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos834-erdos-834-parts-ii}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/erdos835-johnsongraph-18-9-chromaticnumber/README.md b/results/erdos835-johnsongraph-18-9-chromaticnumber/README.md new file mode 100644 index 0000000..794f59a --- /dev/null +++ b/results/erdos835-johnsongraph-18-9-chromaticnumber/README.md @@ -0,0 +1,30 @@ +# The Johnson graph J(18, 9) has chromatic number at least 11 + +**Classification:** First formal proof of a known result +**Area:** Combinatorics +**Source problem:** Erdős Problem #835 +**Date:** 2026-10-17 + +## Result + +Let J(18, 9) be the Johnson graph. Its vertices are the 9-element subsets of an 18-element set, and two vertices are adjacent when they share exactly 8 elements. Then χ(J(18, 9)) > 9 + 1, so χ(J(18, 9)) ≥ 11. This is the case k = 9 of Erdős Problem 835, which asks whether χ(J(2k, k)) = k + 1 for some k > 2. + +## Verification + +The Lean file [`lean/Math0/ErdosProblems/Erdos835_johnsonGraph_18_9_chromaticNumber.lean`](../../lean/Math0/ErdosProblems/Erdos835_johnsonGraph_18_9_chromaticNumber.lean) proves the upstream statement [`Erdos835.johnsonGraph_18_9_chromaticNumber`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/ErdosProblems/835.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research solved`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Erdős Problem 835 (erdosproblems.com/835). problems.yaml lists its status as "verifiable" and its formal_status as "unformalized"; there is no "(Lean)" marker. The general question stays open, but the k = 9 case is known. The odd-k lower bound χ(J(2k,k)) > k+1 follows from Johnson's bound for constant-weight codes (S. M. Johnson, 1962) through α(J(2k,k)) ≤ A(2k,4,k). For k = 9 this gives α ≤ 4420 and χ ≥ ⌈48620/4420⌉ = 11. The bound is tabulated on A. E. Brouwer's Johnson-graphs page (aeb.win.tue.nl/graphs/Johnson.html). Ma and Tang (2025, github.com/QuanyuTang/erdos-problem-835) prove χ(J(2k,k)) > k+1 for every k > 2 with k+1 composite, which includes k = 9. No previous sorry-free Lean proof was found: in formal_conjectures, indepNum_johnson_le_johnsonBound is sorry, and every upstream lower-bound statement depends on it or is itself sorry. + +## Citation + +```bibtex +@misc{math0:erdos835-johnsongraph-18-9-chromaticnumber, + author = {{math0}}, + title = {{The Johnson graph J(18, 9) has chromatic number at least 11}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/erdos835-johnsongraph-18-9-chromaticnumber}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/green44-green-44/README.md b/results/green44-green-44/README.md new file mode 100644 index 0000000..0deec37 --- /dev/null +++ b/results/green44-green-44/README.md @@ -0,0 +1,38 @@ +# Sieving [N] by half the classes mod 1000 primes below N^{9/10} can leave more than N/10 (Green's Problem 44 refuted as formalized) + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Number theory +**Source problem:** Ben Green's 100 open problems, #44 +**Date:** 2026-10-17 + +## Result + +Green's Open Problem 44 (from Erdős 1980, Section 6, Problem 3): sieve [N] by removing half the residue classes mod p_i, for primes 2 ≤ p_1 < ... < p_1000 < N^{9/10}. Does the remaining set have size at most N/10? The formal statement Green44.green_44 says yes: for all N, all strictly increasing p : Fin 1000 → ℕ of primes with p_999^10 < N^9, and all A_i ⊆ ZMod p_i with |A_i| = ⌊p_i/2⌋, the set {x ∈ [1,N] : x mod p_i ∉ A_i for all i} has 10·|remaining| ≤ N. We prove the negation. Counterexample: N = 100000, p_0 < ... < p_999 the 1000 consecutive primes 20011, ..., 30161, and A_i the upper half {⌈p_i/2⌉, ..., p_i − 1} of the residues mod p_i. + +## Verification + +The Lean file [`lean/Math0/GreensOpenProblems/Green44_green_44.lean`](../../lean/Math0/GreensOpenProblems/Green44_green_44.lean) refutes (proves the negation of) the upstream statement [`Green44.green_44`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/GreensOpenProblems/44.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research open`). Its final command `#math0_refutes` checks that our theorem's type is syntactically identical to the upstream statement (negated) and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Sources: +- Erdős, "A survey of problems in combinatorial number theory", Ann. Discrete Math. 6 (1980) 89-115, p.107, §6 Problem 3 (scan at https://users.renyi.hu/~p_erdos/1980-03.pdf). +- B. Green, 100 Open Problems, Problem 44 (https://people.maths.ox.ac.uk/greenbj/papers/open-problems.pdf, Dec 2025 version; no update recorded). +- Erdős Problem #1202 (https://www.erdosproblems.com/1202): "resolved in the negative by Price and GPT-5.4 Pro". It identifies the problem with Green #44. Last edited 2026-04-12; local DB marks it solved on 2026-04-04. Write-up: https://www.overleaf.com/read/qyhdmrchqnvb. +- #1202 forum thread (https://www.erdosproblems.com/forum/thread/1202): Z. Hunter and T. Bloom, 16-17 Apr 2026, on large-sieve bounds and refinements. +- Justin Sun Prize catalog entry JSP-001007 (TheJustinSunPrize/awards, problems/catalog-1001-1022.md): "Solved, Price and GPT-5.4 Pro". +- Existing Lean formalization: github.com/tester-lean/awards @ f26433803cfbd924569aebbdcc1c39321ecb9971, submissions/jsp-001007. Theorems JSP001007.green44_counterexample (every k ≥ 1, all large N, more than N/10 survivors, p^10 < N^9, |A_i| = (p-1)/2) and JSP001007.not_green44_conjecture. Submitted as https://github.com/TheJustinSunPrize/awards/issues/104 on 2026-09-16; pending and unreviewed. Its header cites formal-conjectures Green44. + +(Abridged.) + +## Citation + +```bibtex +@misc{math0:green44-green-44, + author = {{math0}}, + title = {{Sieving [N] by half the classes mod 1000 primes below N^{9/10} can leave more than N/10 (Green's Problem 44 refuted as formalized)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/green44-green-44}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a001040/README.md b/results/oeis-a001040/README.md new file mode 100644 index 0000000..9ef69f1 --- /dev/null +++ b/results/oeis-a001040/README.md @@ -0,0 +1,57 @@ +# Kurkov's rook-tour conjecture for A001040: 2·n!·a(n) counts opposite-line Hamiltonian paths of K_n □ K_2 + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A001040 +**Date:** 2026-10-29 + +## Result + +For every n ≥ 1, take the n × 2 board with squares (i,c), i ∈ [n], c ∈ {0,1}. Two different squares are a rook move apart when they share a row i or a line c (this is the graph K_n □ K_2). An open tour is a sequence that visits every square exactly once, with consecutive squares a rook move apart; a tour and its reversal count separately. Count the tours whose first and last squares lie on different lines. Kurkov conjectured that this count is 2·n!·a(n), where a(0)=0, a(1)=1 and a(m+1) = m·a(m) + a(m−1) (OEIS A001040). The statement is proved. + +## Assessment + +Split a directed Hamiltonian path of the 2 x n rook graph at its moves between the two lines. The path ends on the opposite line exactly when there is an odd number 2q-1 of such switches. The path is then fixed by three choices: the start line, the ordered switch rows, and how the free squares of each line fill q ordered slots. This gives 2 n! times the sum over k of C(n-1-k,k)(n-1-k)!/k!, term by term. That sum is Paul Barry's formula for a(n), already listed in the entry. Each step is a short, standard counting argument of well under a page. The Lean proof is long and checks the closed form through a first-step recursion instead of the bijection, but that is formalization work, not a new mathematical idea. + +*Follows from:* Paul Barry's formula a(n+1) = Sum_k C(n-k,k)(n-k)!/k! in A001040 (%F), combined with the standard decomposition of a Hamiltonian path of K_n x K_2 into runs within one line joined by switch rows. The "Further refinement" formula in A096121 already has the opposite-line count as its first summand, without saying so. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A001040](https://oeis.org/A001040) as [`Math0.Statements.A001040.statement`](../../lean/Math0/Statements/OEIS/A001040.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A001040.lean`](../../lean/Math0/Frontier/OEIS/A001040.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C A001040 Conjecture: 2*n!*a(n) is the number of open tours by a rook on an (n X 2) chessboard which ends at the opposite line of length n. - _Mikhail Kurkov_, Nov 19 2019 + +Referees: OEIS sources (read from the local mirror): +- A001040: Kurkov's conjecture, Nov 19 2019, still marked as a conjecture in revision #140 of Oct 15 2026. The entry also has Paul Barry's 2004 formula a(n+1) = Sum_k C(n-k,k)(n-k)!/k!. +- A001053: the companion same-line conjecture, still open in revision #131 of Oct 22 2026. +- A096121: Hugo van der Sanden, 2004, counts directed Hamiltonian paths of the 2 x n rook graph. It contains: + - the recurrence a(n+1) = n(n+1)(a(n)+a(n-1)); + - an unattributed "Further refinement" formula whose two summands are exactly the opposite-line and same-line counts, though they are not labeled as such; + - Kurkov's Feb 2019 conjecture that the total is 2*n!*A102038(n); + - Grossman's 2024 shoe-arrangement reading; + - a citation of Y. Cha's 2011 FSU thesis, Example 5.1.1, which I could not open (HTTP 403). +- A102038: equals A001040 + A001053. +- A269565: Andrew Howroyd's array of directed Hamiltonian paths in K_n x K_m. +- A360878: Andrew Howroyd's May 2025 switch-decomposition formula for undirected paths. +- A276356 and A089039: the Hamiltonian-cycle analogue. + +Other sources: +- MathOverflow q/469606 (Kurkov, Apr 2024), "On a A089039 and pair of sequences with simple recursion". I read it: Max Alekseyev proves only the cycle formula, using Zeilberger's algorithm. +- Web searches found no prior proof of the path refinement. They covered arXiv, MSE, MO, Google-style queries on rook tours of 2 x n boards, Hamiltonian paths of K_n x K_2, and the shoe or jealousy-free linear arrangements. + +## Citation + +```bibtex +@misc{math0:oeis-a001040, + author = {{math0}}, + title = {{Kurkov's rook-tour conjecture for A001040: 2·n!·a(n) counts opposite-line Hamiltonian paths of K_n □ K_2}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a001040}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a005590/README.md b/results/oeis-a005590/README.md new file mode 100644 index 0000000..1cd47c7 --- /dev/null +++ b/results/oeis-a005590/README.md @@ -0,0 +1,53 @@ +# Zeros of a(3n) for the signed Stern sequence A005590 are exactly the fibbinary numbers + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Number theory +**Source problem:** OEIS A005590 +**Date:** 2026-10-18 + +## Result + +Let a : N -> Z be given by a(0)=0, a(1)=1, a(2n)=a(n), a(2n+1)=a(n+1)-a(n) (OEIS A005590). Then for every n >= 0, a(3n)=0 if and only if n is fibbinary (OEIS A003714), i.e. the binary representation of n has no two adjacent 1 bits. This is Ralf Stephan's 2003 conjecture. + +## Assessment + +The proof follows the pair (a(m), a(m+1)) along the binary digits of m. The pair stays at (0,1) or (1,1) while the digits form blocks 0 and 11. As soon as a 0 is read in state (1,1), the pair lands on (1,0), and from then on a one-line sign invariant (x>0 and y 0 + | fuel + 1, n => + if n ≤ 1 then (n : ℤ) + else if n % 2 = 0 then aux fuel (n / 2) + else aux fuel (n / 2 + 1) - aux fuel (n / 2) +def a (n : ℕ) : ℤ := aux (n + 1) n +def IsFibbinary (n : ℕ) : Prop := + ∀ i : ℕ, ¬ (n.testBit i = true ∧ n.testBit (i + 1) = true) +def statement : Prop := + ∀ n : ℕ, a (3 * n) = 0 ↔ IsFibbinary n +end Math0.Statements.A005590 +\end{lstlisting} +The encoding matches Definition~\ref{def:main}. +The values are signed, so \decl{a} takes values in $\Z$ and the subtraction is exact. +The function \decl{aux} runs the OEIS recursion with a fuel argument, so that the kernel can evaluate it; with fuel $n+1$ the fuel is never exhausted, because each recursive call is on a smaller argument ($\lfloor n/2\rfloor>> 1) = 0 +\end{lstlisting} +\decl{IsFibbinary} is the literal reading of the description of A003714 quoted above: \texttt{Nat.testBit n i} is $b_i(n)$, and bits beyond the length of the binary expansion are $0$. +The lemma \decl{isFibbinary_iff_land} gives the usual bitwise test, which makes the predicate decidable. +Two data lemmas, proved by \texttt{decide +kernel}, compare the definitions with the OEIS: \decl{a_data} checks all $105$ listed terms $a(0),\dots,a(104)$ of A005590, and \decl{fibbinary_data} checks that the numbers $n<265$ with \texttt{IsFibbinary n} are exactly the $61$ listed terms $0,1,2,\dots,264$ of A003714. +The statement quantifies over all $n\in\N$ and adds no hypotheses. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A005590.lean}; the name of the corresponding Lean declaration is given with each step. For $m\ge0$ put +\[ + v(m)=(a(m),a(m+1))\in\Z^2 . +\] + +\begin{lemma}\label{lem:vec} +For all $m\ge0$, if $v(m)=(x,y)$ then $v(2m)=(x,\,y-x)$ and $v(2m+1)=(y-x,\,y)$. +\end{lemma} + +\begin{proof} +By \decl{a_even} and \decl{a_odd}, $a(2m)=a(m)=x$ and $a(2m+1)=a(m+1)-a(m)=y-x$; by \decl{a_even} at $m+1$, $a(2m+2)=a(m+1)=y$. +\end{proof} + +\begin{definition}[the automaton, \decl{st}]\label{def:st} +Define $\delta_0,\delta_1\colon\{0,1,2\}\to\{0,1,2\}$ by +\[ +\begin{array}{c|ccc} + s & 0 & 1 & 2\\\hline + \delta_0(s) & 0 & 2 & 2\\ + \delta_1(s) & 1 & 0 & 2 +\end{array} +\] +and $\st\colon\N\to\{0,1,2\}$ by $\st(0)=0$ and $\st(m)=\delta_{m\bmod 2}(\st(\lfloor m/2\rfloor))$ for $m\ge1$. +\end{definition} + +Since $\delta_0(0)=0$, the recursion also holds at $m=0$, so +\begin{equation}\label{eq:st} + \st(2k)=\delta_0(\st(k)),\qquad \st(2k+1)=\delta_1(\st(k))\qquad(k\ge0) +\end{equation} +(\decl{st_even}, \decl{st_odd}). +Thus $\st(m)$ is the state reached from state $0$ by reading the binary digits of $m$ from the most significant one; leading zeros do not matter. +In Lean, \decl{st} is a function $\N\to\N$ defined by well-founded recursion, with the recursive call at $\lfloor m/2\rfloor0$ and $0<1$, $P(1,0)$ holds: (I2). +If $k$ satisfies (I2), then $\st(m)=2$. If $00>x$, so it holds by its second alternative. Hence (I2). + +Let $m=2k+1$ with $k\ge0$. Then $k0$ and $y 0 + | n + 1 => + if (n + 1) % 2 = 0 then (if st ((n + 1) / 2) = 0 then 0 else 2) + else (if st ((n + 1) / 2) = 0 then 1 else if st ((n + 1) / 2) = 1 then 0 else 2) + decreasing_by all_goals omega +private def Inv (m : ℕ) : Prop := + (st m = 0 ∧ a m = 0 ∧ a (m + 1) = 1) ∨ (st m = 1 ∧ a m = 1 ∧ a (m + 1) = 1) ∨ + (st m = 2 ∧ ((0 < a m ∧ a (m + 1) < a m) ∨ (a m < 0 ∧ a m < a (m + 1)))) +theorem result : statement := by + intro n + rw [a_eq_zero_iff, st_three_mul] +end Math0.Frontier.A005590 +#math0_settles Math0.Frontier.A005590.result Math0.Statements.A005590.statement +\end{lstlisting} +The proof file uses no \texttt{decide} or \texttt{native\_decide} tactic and no \texttt{set\_option}. From the statement file it uses \decl{a_zero}, \decl{a_one}, \decl{a_even} and \decl{a_odd}; the first two, and the case $n=0$ of \decl{a_odd}, are proved there by \texttt{decide +kernel}, i.e.\ by evaluation in the kernel, which adds no axioms. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (rejecting \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata, with no unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A005590.statement' depends on axioms [propext] +math0 audit: 'Math0.Frontier.A005590.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A005590.result' proves 'Math0.Statements.A005590.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A005590.lean} in the directory \path{lean}; this takes under a minute on our machine, most of it spent loading Mathlib. + +{\small +\begin{thebibliography}{99} + +\bibitem{Ad} +T.~Adamczewski, \emph{OEIS Open: How many conjectures can language models turn into theorems?}, arXiv:2608.11941, 2026. + +\bibitem{AMF} +J.-P. Allouche and M.~Mend\`es France, \emph{Lacunary formal power series and the Stern--Brocot sequence}, Acta Arith.\ \textbf{159} (2013), 47--61; arXiv:1202.0211 (first version titled \emph{Stern--Brocot polynomials and power series}). + +\bibitem{AS} +J.-P. Allouche and J.~Shallit, \emph{The ring of $k$-regular sequences}, Theoret.\ Comput.\ Sci.\ \textbf{98} (1992), 163--197. + +\bibitem{De} +C.~Defant, \emph{Upper bounds for Stern's diatomic sequence and related sequences}, arXiv:1506.07824, 2015. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Fr} +S.~Fried, \emph{Further proofs of conjectures from the OEIS}, arXiv:2607.24832, 2026. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{No} +S.~Northshield, \emph{Three analogues of Stern's diatomic sequence}, arXiv:1503.03433, 2015. + +\bibitem{Rez84} +B.~Reznick, \emph{A new sequence with many properties}, Abstract 809-10-185, Abstracts Amer.\ Math.\ Soc.\ \textbf{5} (1984), 16. Annotated scan, with a letter to N.~J.~A. Sloane (June~3, 1991), at \url{https://oeis.org/A005590/a005590.png}. + +\bibitem{Rez85} +B.~Reznick, \emph{Some extremal problems for continued fractions}, Illinois J. Math.\ \textbf{29} (1985), 261--279. + +\bibitem{Rez06} +B.~Reznick, \emph{Regularity properties of the Stern enumeration of the rationals}, J. Integer Seq.\ \textbf{11} (2008), Article~08.4.1; arXiv:math/0610601. + +\bibitem{St03} +R.~Stephan, \emph{Divide-and-conquer generating functions. Part I. Elementary sequences}, arXiv:math/0307027, 2003. + +\bibitem{St04} +R.~Stephan, \emph{Prove or disprove. 100 conjectures from the OEIS}, arXiv:math/0409509, 2004. + +\bibitem{APN} +G.~Tsoukalas et al., \emph{Advancing Mathematics Research with AI-Driven Formal Proof Search}, arXiv:2605.22763, 2026. + +\bibitem{A002487} +The OEIS Foundation Inc., \url{https://oeis.org/A002487} (Stern's diatomic series), entry by N.~J.~A. Sloane. + +\bibitem{A003714} +The OEIS Foundation Inc., \url{https://oeis.org/A003714} (fibbinary numbers), entry by N.~J.~A. Sloane. + +\bibitem{A005590} +The OEIS Foundation Inc., \url{https://oeis.org/A005590}, entry by N.~J.~A. Sloane; conjecture by R.~Stephan (May 2, 2003); revision \#97, Nov.~5, 2025. + +\bibitem{A277335} +The OEIS Foundation Inc., \url{https://oeis.org/A277335}, entry by A.~Karttunen (2016). + +\bibitem{A290258} +The OEIS Foundation Inc., \url{https://oeis.org/A290258}, entry by E.~Deutsch (2017). + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a022445/README.md b/results/oeis-a022445/README.md new file mode 100644 index 0000000..d8eb027 --- /dev/null +++ b/results/oeis-a022445/README.md @@ -0,0 +1,43 @@ +# The generating function of A022445 (closed self-avoiding walks in the strip {0,1,2} x Z) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A022445 +**Date:** 2026-10-26 + +## Result + +Let a(n) be the number of closed walks of length 2n in the square lattice that start and end at the origin (a vertex of the boundary column 0), stay in the strip {0,1,2} x Z, and visit no vertex twice except that the endpoint equals the start (a(0) = 1; length-2 walks that retrace their edge are excluded, so a(1) = 0). Then +sum_{n>=0} a(n) x^n = (1 - 4x + 10x^2 - 14x^3 + 27x^4 - 18x^5 + 10x^6 - 6x^7) / ((1 + x^2)^2 (1 - 2x)^2). +In Lean this is stated in Z[[X]] with the denominator cleared. + +## Assessment + +The proof rests on one observation: a self-avoiding polygon in the strip {0,1,2} x Z crosses each horizontal cut in an even number of distinct columns, at most three, so in 0 or 2 of them. The polygon is therefore two strands, with three possible states per row, and its perimeter series comes from a 3-state transfer matrix (in Lean, a linear recursion for half-strip excursions), with rooting handled by marking column-0 vertices; clearing denominators is then algebra. This is the textbook transfer-matrix method for polygons in narrow strips; it fits in about a page and is the same calculation that gave the area version (A038579) attributed to Labelle. The Lean formalization is long, but the mathematical idea is standard. + +*Follows from:* Standard transfer-matrix / row-by-row decomposition of self-avoiding polygons in a strip of fixed width (e.g. Stanley, EC1 Sec. 4.7). In a 3-column strip every horizontal cut meets the polygon in 0 or 2 vertical edges, so the polygons are row-convex with three row states. The same method gives the area generating function of the same objects, A038579, credited to Labelle (Bull. ICA 23, 1998) and cited in the entry. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A022445](https://oeis.org/A022445) as [`Math0.Statements.A022445.statement`](../../lean/Math0/Statements/OEIS/A022445.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A022445.lean`](../../lean/Math0/Frontier/OEIS/A022445.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A022445 G.f.: (-6*x^7+10*x^6-18*x^5+27*x^4-14*x^3+10*x^2-4*x+1) / ((1+x^2)^2*(1-2*x)^2) (conjectured). - _Ralf Stephan_, Apr 28 2004 + +Referees: OEIS A022445 (local mirror and current github.com/oeis/oeisdata, %I #10 May 16 2019): GF marked "(conjectured). - Ralf Stephan, Apr 28 2004". Sister entry A022444: GF also still conjectured. Related entries A038578 and A038579 have rooted area GFs credited to Labelle by E. Deutsch (Apr 29 2004). Other related entries: A007825, A038577, A302408. J. Labelle, "Self-avoiding walks and polyominoes in strips", Bull. ICA 23 (1998) 88-98; full text not accessible, so I cannot rule out that it has the perimeter GF, but the OEIS has kept it "conjectured" since 2004. M. von Thaden, "Self-avoiding polygons on a three-row square-lattice strip", arXiv:2607.27397 (Jul 2026): unrooted polygon counts on Z×{0,1,2}, does not mention A022445. M. Bousquet-Mélou & R. Brak, "Exactly solved models", and A. J. Guttmann & I. Jensen, "Polygons in strips", both in Polygons, Polyominoes and Polycubes, LNP 775 (2009): unrooted polygon GFs only. Not relevant to this GF: Batchelor–Yung 1994 (transfer-matrix SAWs across strips); Dyhr–Gilbert–Kennedy arXiv:1008.4321; Zeilberger arXiv:math/9506214 and Benjamin, Fib. Quart. 44 (2006) (two-row strip). jOEIS programs for A022444/A022445 use brute-force enumeration. I found no prior proof of the A022445 GF in any of these sources. + +## Citation + +```bibtex +@misc{math0:oeis-a022445, + author = {{math0}}, + title = {{The generating function of A022445 (closed self-avoiding walks in the strip {0,1,2} x Z)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a022445}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a057566/README.md b/results/oeis-a057566/README.md new file mode 100644 index 0000000..c4fa98a --- /dev/null +++ b/results/oeis-a057566/README.md @@ -0,0 +1,43 @@ +# Layman's floor formula for collinear triples in a 3 × n grid (A057566), as printed until its October 2026 correction, fails at n = 24 + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A057566 +**Date:** 2026-10-21 + +## Result + +Let a(n) be the number of 3-element collinear subsets of the 3 × n grid {0,1,2} × {0,...,n-1}. Layman's conjecture (OEIS A057566, Oct 2000), as printed in the entry until 21 Oct 2026, says that for every n ≥ 3, a(n) = 5*floor((2n^3 - 3n^2 - n)/24) + floor((2(n-1)^3 - 3(n-1)^2 - (n-1))/24) + n. The frozen statement is this conjecture for all n ≥ 3. We prove it is false: the identity fails at n = 24. On 21 Oct 2026, after this statement was frozen, OEIS corrected the formula to a(n) = 5*floor((2n^3 - 3n^2 - 2n + 3)/24) + floor((2(n-1)^3 - 3(n-1)^2 - 2(n-1) + 3)/24) + n. This result concerns only the formula as printed before that correction; the corrected formula is not refuted, and it agrees with a brute-force count for n <= 60 and with the proved closed form 3*C(n,3) + n + 2*floor((n-1)^2/4) for n <= 20000. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A057566](https://oeis.org/A057566) as [`Math0.Statements.A057566.statement`](../../lean/Math0/Statements/OEIS/A057566.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A057566.lean`](../../lean/Math0/Frontier/OEIS/A057566.lean) refutes (proves the negation of) it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Correction (noted 26 Oct 2026): OEIS A057566 now reads "Conjecture: a(n) = 5*floor((2n^3 - 3n^2 - 2n + 3)/24) + floor((2(n-1)^3 - 3(n-1)^2 - 2(n-1) + 3)/24) + n, which fits all of the listed terms. [Corrected by Alper Ferudun, Oct 21 2026]" (oeisdata, checked 26 Oct 2026). The statement here was frozen from the earlier text, quoted below, which is what the Lean file refutes. Reported in review of math0 PR #1. + +Conjecture as stated in OEIS: %F A057566 Conjecture: a(n) = 5*floor((2n^3 - 3n^2 - n)/24) + floor((2(n-1)^3 - 3(n-1)^2 - (n-1))/24) + n, which fits all of the listed terms. (John W. Layman, author of the entry, Oct 04 2000) + +Referees: There is no explicit published refutation, but OEIS already contains everything needed: +- A057566 data lists a(24) = 6360. Layman's formula gives 6365 there. Paolo Xausa's b-file (2024) covers n = 0..10000. +- A057566 %F, R. J. Mathar, May 23 2010: a(n) = n^3/2 - n^2 + n + (1-(-1)^n)/4, with recurrence signature (3,-2,-2,3,-1) and g.f. x(1-x+4x^2+2x^3)/((1+x)(x-1)^4). +- A262402, proof by N. J. A. Sloane, Dec 16 2017, following Jared Nash's formula and his linked PDF "Formula for number of triangles in a 3 X n grid". It proves the number of collinear triples with one point per row in a 3 x n grid is n + 2*floor((n-1)^2/4). Hence a(n) = 3*C(n,3) + n + 2*floor((n-1)^2/4). +- A334704 (N. J. A. Sloane and Tom Duff, 2020) tabulates collinear-triple counts for n x k grids up to 50 x 50; row 3 is A057566. +- I searched the web (arXiv including 2609.25133, general search) and found no explicit statement that Layman's floor conjecture fails. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a057566, + author = {{math0}}, + title = {{Layman's floor formula for collinear triples in a 3 × n grid (A057566), as printed until its October 2026 correction, fails at n = 24}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a057566}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a057566/paper.pdf b/results/oeis-a057566/paper.pdf new file mode 100644 index 0000000..ea494f1 Binary files /dev/null and b/results/oeis-a057566/paper.pdf differ diff --git a/results/oeis-a057566/paper.tex b/results/oeis-a057566/paper.tex new file mode 100644 index 0000000..a9605ec --- /dev/null +++ b/results/oeis-a057566/paper.tex @@ -0,0 +1,361 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,at}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 + {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {∈}{{$\in$}}1 + {×}{{$\times$}}1 {ˢ}{{$^{\mathrm{s}}$}}1 {⌊}{{$\lfloor$}}1 {⌋}{{$\rfloor$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{ˢ}{\ensuremath{^{\mathrm{s}}}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\cross}{\operatorname{cr}} + +\title[Layman's formula for collinear triples in a $3\times n$ grid fails]{The number of collinear triples in a $3\times n$ grid: Layman's floor formula (OEIS A057566), as printed until October 2026, fails at $n=24$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 21, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the number of $3$-element collinear subsets of the grid $\{0,1,2\}\times\{0,\dots,n-1\}$ (OEIS A057566). +The OEIS entry, submitted by John W. Layman in October 2000, records the conjecture $a(n)=5\lfloor(2n^3-3n^2-n)/24\rfloor+\lfloor(2(n-1)^3-3(n-1)^2-(n-1))/24\rfloor+n$. +We show that this identity is false for $n=24$: the $3\times 24$ grid has $6360$ collinear triples, while the formula gives $6365$. +The falsity is not new in substance, since $a(24)=6360$ is listed in the entry's own data and a proved closed form for $a(n)$ follows from an argument recorded in OEIS A262402; we know of no explicit published refutation, and this is the first formal proof of the known result. +The refutation is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definition of $a$ is checked by the kernel against the first $25$ listed terms $a(0),\dots,a(24)$. +\end{abstract} +\maketitle + +\section{Introduction} + +For $n\ge0$ let $G_n=\{0,1,2\}\times\{0,1,\dots,n-1\}\subset\Z^2$ be the $3\times n$ grid of lattice points, and let $a(n)$ be the number of $3$-element subsets of $G_n$ whose points lie on a common line. +This is the sequence A057566 of the OEIS \cite{A057566}, ``Number of collinear triples in a 3 X n rectangular grid'', with offset $0$ and first terms $0, 1, 2, 8, 20, 43, 78, 130, 200, 293, 410,\dots$ +The entry was submitted by John W. Layman on October~4, 2000. Its FORMULA section contains the conjecture +\begin{equation}\label{eq:layman} + a(n)\overset{?}{=}5f(n)+f(n-1)+n,\qquad f(m)=\Bigl\lfloor\frac{2m^3-3m^2-m}{24}\Bigr\rfloor, +\end{equation} +with the remark that it ``fits all of the listed terms''. The line was still labelled ``Conjecture'' in revision \#27 of the entry (February~22, 2024), the text formalized here; it has since been corrected (see the note below). +We prove that \eqref{eq:layman} fails at $n=24$ (Theorem~\ref{thm:main}). + +\paragraph{Note added on October 26, 2026.} On October 21, 2026, after the statement studied here was frozen, the formula in the entry was corrected by Alper Ferudun to +\[ + a(n)=5\Bigl\lfloor\frac{2n^3-3n^2-2n+3}{24}\Bigr\rfloor+\Bigl\lfloor\frac{2(n-1)^3-3(n-1)^2-2(n-1)+3}{24}\Bigr\rfloor+n . +\] +Our theorem concerns only the formula as printed before that correction, quoted in Section~\ref{sec:statement}. The corrected formula is not refuted: it agrees with a brute-force count of collinear triples for $n\le 60$ and with the closed form of Proposition~\ref{prop:closed} for $n\le 20000$. A proof of the corrected formula is not part of this paper. + +\subsection*{Prior work and status} +The refutation is elementary and its ingredients are already in the OEIS; we credit them precisely. +\begin{itemize} +\item The data section of A057566 lists $a(0),\dots,a(42)$, including $a(24)=6360$, and the entry links a table of $a(n)$ for $n\le10000$ by Paolo Xausa \cite{A057566}. Formula \eqref{eq:layman} gives $6365$ at $n=24$, so the remark ``fits all of the listed terms'' is contradicted by the entry's own data. We do not know how many terms were listed in 2000; the formula agrees with $a(n)$ for $3\le n\le 23$. +\item On May~23, 2010, R.~J. Mathar added to A057566 the closed form $a(n)=n^3/2-n^2+n+(1-(-1)^n)/4$, the linear recurrence with signature $(3,-2,-2,3,-1)$ and the generating function $x(1-x+4x^2+2x^3)/((1+x)(x-1)^4)$ \cite{A057566}. The entry states these without proof. +\item In OEIS A262402 \cite{A262402} (triangles with vertices in a $3\times n$ grid), N.~J.~A. Sloane gave on December~16, 2017 a proof of a formula of Jared Nash; see also Nash's note linked there \cite{Nash}. The proof shows that the number of collinear triples with one point in each row of the $3\times n$ grid is $n+2\lfloor(n-1)^2/4\rfloor$. Together with the $3\binom n3$ triples inside a single row (a triple with exactly two points in one row is never collinear), this gives a proof of $a(n)=3\binom n3+n+2\lfloor(n-1)^2/4\rfloor$, which equals Mathar's closed form and gives $a(24)=6360$. +\item The triangle A334704 \cite{A334704} (N.~J.~A. Sloane, 2020, with rows $6$ onwards from Tom Duff, who computed the values for grids up to $50\times50$) counts collinear triples in $n\times k$ grids ($1\le k\le n$); in the full symmetric array of which it is the lower half, row~$3$ (the $3\times k$ grids, $k\ge1$) is A057566, as the entry notes. +\end{itemize} +The math0 referees found no explicit statement, in the OEIS or elsewhere (arXiv and general web searches), that Layman's conjecture is false. Comparing \eqref{eq:layman} with the listed term $a(24)$, or with Mathar's closed form, is a one-line computation, so we classify the result as the \emph{first formal proof of a known result}, not as a new result. + +\subsection*{What is proved formally} +The Lean proof shows that the identity \eqref{eq:layman} does not hold for all $n\ge3$, by exhibiting $n=24$. It does not formalize the closed form for $a(n)$ (Proposition~\ref{prop:closed}) or the fact that \eqref{eq:layman} fails for every $n\ge24$ (Remark~\ref{rem:all}); both are proved here on paper only. + +\section{Statement}\label{sec:statement} + +The FORMULA section of A057566 \cite{A057566} contains, verbatim, the unsigned line +\begin{quote} +{\small\raggedright\texttt{Conjecture: a(n) = 5*floor((2n\^{}3 - 3n\^{}2 - n)/24) + floor((2(n-1)\^{}3 - 3(n-1)\^{}2 - (n-1))/24) + n, which fits all of the listed terms.}\par} +\end{quote} +It is the first FORMULA line of the entry, whose author line reads \texttt{\_John W. Layman\_, Oct 04 2000}; we attribute the conjecture to him, as the math0 statement file does. + +\begin{theorem}\label{thm:main} +Let $a(n)$ be the number of collinear $3$-element subsets of $\{0,1,2\}\times\{0,\dots,n-1\}$, and let $f(m)=\lfloor(2m^3-3m^2-m)/24\rfloor$ for $m\in\Z$. Then +\[ + a(24)=6360\ne 6365=5f(24)+f(23)+24 . +\] +In particular, it is false that $a(n)=5f(n)+f(n-1)+n$ for all $n\ge3$. +\end{theorem} + +\subsection*{\texorpdfstring{The range of $n$}{The range of n}} +The conjecture names no range for $n$, and the sequence has offset $0$. For $n\le2$ some of the arguments of the floors are negative: $(2m^3-3m^2-m)/24$ equals $-4/24$ at $m=-1$ and $-2/24$ at $m=1$. With true floors, \eqref{eq:layman} gives $-1,-4,1$ at $n=0,1,2$ instead of $0,1,2$; with rounding toward zero it gives exactly $0,1,2$, and then agrees with $a(0),\dots,a(23)$. A refutation at $n\le2$ would thus rest on a rounding convention at degenerate grid sizes. For $n\ge3$ both arguments are nonnegative ($2m^3-3m^2-m=m\bigl(m(2m-3)-1\bigr)>0$ for $m\ge2$), so every reading of ``floor'' gives the same claim. The math0 statement therefore asserts \eqref{eq:layman} for $n\ge3$ only. This is the weakest faithful reading, and refuting it refutes every reading; the literal reading for all $n\ge0$ is recorded separately as \decl{statement_all}, with a proof that it implies \decl{statement}. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A057566.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{218f1d78\ldots 6ec5}) before any proof attempt. The definitions and the statement read as follows (verbatim; the copyright header, the import, docstrings, blank lines, the fast evaluator of Section~\ref{sec:proof} with its auxiliary multiset predicate \decl{Q}, all theorems, and the variant \decl{statement_all}, which is \decl{statement} without the hypothesis \texttt{3 ≤ n}, are omitted): +\begin{lstlisting} +namespace Math0.Statements.A057566 +def grid (n : ℕ) : Finset (ℕ × ℕ) := Finset.range 3 ×ˢ Finset.range n +def cross (p q r : ℕ × ℕ) : ℤ := + ((q.1 : ℤ) - p.1) * ((r.2 : ℤ) - p.2) - ((q.2 : ℤ) - p.2) * ((r.1 : ℤ) - p.1) +def IsCollinear (s : Finset (ℕ × ℕ)) : Prop := ∀ p ∈ s, ∀ q ∈ s, ∀ r ∈ s, cross p q r = 0 +instance : DecidablePred IsCollinear := fun s => by unfold IsCollinear; infer_instance +def a (n : ℕ) : ℕ := ((grid n).powersetCard 3 |>.filter IsCollinear).card +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → (a n : ℤ) = + 5 * ⌊(2 * (n : ℚ) ^ 3 - 3 * (n : ℚ) ^ 2 - (n : ℚ)) / 24⌋ + + ⌊(2 * ((n : ℚ) - 1) ^ 3 - 3 * ((n : ℚ) - 1) ^ 2 - ((n : ℚ) - 1)) / 24⌋ + n +end Math0.Statements.A057566 +\end{lstlisting} +A point is a pair (row, column) of natural numbers, and \texttt{grid n} is $G_n$. For points $p,q,r$ the integer +\[ + \cross(p,q,r)=(q_1-p_1)(r_2-p_2)-(q_2-p_2)(r_1-p_1) +\] +is twice the signed area of the triangle $pqr$, so it vanishes exactly when $p,q,r$ lie on a common line. A finite set is \decl{IsCollinear} if $\cross$ vanishes on every three of its points (repetitions allowed), and \texttt{a n} is the number of $3$-element subsets of \texttt{grid n} with this property, i.e.\ the number of collinear triples. The floors are \texttt{Int.floor} of rational numbers, and $n-1$ is computed in $\Q$, so it is not truncated at $0$. Among other lemmas, the statement file proves (statements shown, proofs omitted): +\begin{lstlisting} +theorem isCollinear_triple (p q r : ℕ × ℕ) : + IsCollinear {p, q, r} ↔ cross p q r = 0 +theorem a_eq_fastA (n : ℕ) : a n = fastA n +theorem a_data : (List.range 25).map (fun i => a (i + 0)) = + [0, 1, 2, 8, 20, 43, 78, 130, 200, 293, 410, 556, 732, 943, 1190, 1478, 1808, 2185, + 2610, 3088, 3620, 4211, 4862, 5578, 6360] +theorem statement_all_imp : statement_all → statement +theorem statement_iff_ediv : statement ↔ ∀ n : ℕ, 3 ≤ n → (a n : ℤ) = + 5 * ((2 * (n : ℤ) ^ 3 - 3 * (n : ℤ) ^ 2 - (n : ℤ)) / 24) + + ((2 * ((n : ℤ) - 1) ^ 3 - 3 * ((n : ℤ) - 1) ^ 2 - ((n : ℤ) - 1)) / 24) + n +\end{lstlisting} +The lemma \decl{isCollinear_triple} shows that for a $3$-element set the collinearity condition is the single equation $\cross(p,q,r)=0$. The data check \decl{a_data}, proved by \texttt{decide +kernel} through \decl{a_eq_fastA}, confirms that the definition reproduces the first $25$ terms of the OEIS data, $a(0),\dots,a(24)$; this anchors the definition to the entry independently of the conjecture. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A057566.lean}. It has two steps: the left-hand side $a(24)$ is computed by the kernel through a verified fast counter, and the right-hand side is evaluated by integer arithmetic. + +\subsection{Counting the triples: a verified evaluator} +The definition of \decl{a} enumerates the $3$-element subsets of a finset, which is too slow for evaluation in the kernel. The statement file therefore also defines a list-based counter (verbatim, docstrings omitted): +\begin{lstlisting} +def collB (p q r : ℕ × ℕ) : Bool := + Nat.beq (q.1 * r.2 + q.2 * p.1 + p.2 * r.1) (q.2 * r.1 + q.1 * p.2 + p.1 * r.2) +def cnt2 (p q : ℕ × ℕ) : List (ℕ × ℕ) → ℕ + | [] => 0 + | r :: l => cnt2 p q l + (if collB p q r then 1 else 0) +def cnt1 (p : ℕ × ℕ) : List (ℕ × ℕ) → ℕ + | [] => 0 + | q :: l => cnt1 p l + cnt2 p q l +def cnt : List (ℕ × ℕ) → ℕ + | [] => 0 + | p :: l => cnt l + cnt1 p l +def pts (n : ℕ) : List (ℕ × ℕ) := List.range 3 ×ˢ List.range n +def fastA (n : ℕ) : ℕ := cnt (pts n) +\end{lstlisting} +Thus $\mathrm{cnt}(\ell)$ is the number of triples of positions $ia(n)$ for all $n\ge27$, and $L(n)-a(n)=n/4+O(1)$. Together with the values $L(n)-a(n)=5,1,5$ at $n=24,25,26$, this shows that \eqref{eq:layman} fails for every $n\ge24$. It holds for $3\le n\le23$ (a finite check, which we did by computer), so $n=24$ is the least counterexample with $n\ge3$. The failure is therefore not a rounding artefact: the cubic and quadratic terms of \eqref{eq:layman} are correct, but its linear term $5n/4$ should be $n$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A057566.lean} in the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A057566.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A057566.result}, of type $\neg$\,\decl{Math0.Statements.A057566.statement}; the only auxiliary declaration is the private lemma \decl{a_24}. The proof reads, verbatim (header, imports, module docstring and docstrings omitted): +\begin{lstlisting} +namespace Math0.Frontier.A057566 +open Math0.Statements.A057566 +private theorem a_24 : a 24 = 6360 := by + rw [a_eq_fastA] + decide +kernel +theorem result : ¬ statement := by + rw [statement_iff_ediv] + intro h + have h24 := h 24 (by norm_num) + rw [a_24] at h24 + norm_num at h24 +end Math0.Frontier.A057566 +#math0_settles Math0.Frontier.A057566.result Math0.Statements.A057566.statement +\end{lstlisting} +Neither file uses \texttt{sorry}, \texttt{native\_decide}, custom axioms or \texttt{set\_option}. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically \decl{statement} or $\neg$\,\decl{statement}, up to metadata annotations, with no unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A057566.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A057566.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A057566.result' refutes 'Math0.Statements.A057566.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use, since the statement is a math0 formalization of an OEIS conjecture and not part of formal-conjectures. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A057566.lean} in the directory \path{lean}; on our machine this took about one minute of CPU time (user and system), including loading Mathlib and the kernel evaluation of Lemma~\ref{lem:a24}. + +{\small +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171 [cs.AI], 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Nash} +J.~Nash, \emph{Formula for number of triangles in a 3 X n grid}, note linked from OEIS A262402, \url{https://oeis.org/A262402/a262402.pdf}. + +\bibitem{A057566} +The OEIS Foundation Inc., \emph{Number of collinear triples in a $3\times n$ rectangular grid}, entry A057566 (J.~W. Layman, 2000) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A057566}; revision \#27, February~22, 2024. + +\bibitem{A262402} +The OEIS Foundation Inc., \emph{Number of triangles that can be formed from the points of a $3\times n$ grid}, entry A262402 (R.~Pan, 2015; revised by N.~J.~A. Sloane, 2017) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A262402}. + +\bibitem{A334704} +The OEIS Foundation Inc., \emph{Triangle read by rows: number of ways to choose three collinear points from an $n\times k$ grid of points}, entry A334704 (N.~J.~A. Sloane and T.~Duff, 2020) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A334704}. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a057566b/README.md b/results/oeis-a057566b/README.md new file mode 100644 index 0000000..2e98b91 --- /dev/null +++ b/results/oeis-a057566b/README.md @@ -0,0 +1,35 @@ +# The corrected floor formula for collinear triples in a 3 x n grid (OEIS A057566) holds for all n + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A057566 (formula as corrected on 21 Oct 2026) +**Date:** 2026-10-29 + +## Result + +Let a(n) be the number of 3-element collinear subsets of the grid {0,1,2} x {0,...,n-1}. Then for every n >= 0, a(n) = 5*floor((2n^3 - 3n^2 - 2n + 3)/24) + floor((2(n-1)^3 - 3(n-1)^2 - 2(n-1) + 3)/24) + n, with true floors (equivalently integer floor division, since both numerators are nonnegative for n >= 0). + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A057566 (formula as corrected on 21 Oct 2026)](https://oeis.org/A057566) as [`Math0.Statements.A057566b.statement`](../../lean/Math0/Statements/OEIS/A057566b.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A057566b.lean`](../../lean/Math0/Frontier/OEIS/A057566b.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: a(n) = 5*floor((2n^3 - 3n^2 - 2n + 3)/24) + floor((2(n-1)^3 - 3(n-1)^2 - 2(n-1) + 3)/24) + n, which fits all of the listed terms. [Corrected by _Alper Ferudun_, Oct 21 2026] (OEIS A057566, %F line; original conjecture by John W. Layman, Oct 2000) + +Referees: - OEIS A057566 revision #30 (Oct 22 2026): corrected floor conjecture (Layman 2000, corrected by Alper Ferudun Oct 21 2026), still marked "Conjecture". The same entry has R. J. Mathar's formula (May 23 2010), a(n) = n^3/2 - n^2 + n + (1-(-1)^n)/4, with g.f. x*(1-x+4x^2+2x^3)/((1+x)(x-1)^4) and the order-5 recurrence. The floor formula is equivalent to this closed form by a mod-24 residue check. +- OEIS A334704 (Sloane 2020, data by Tom Duff): A057566 is row 3 of the m x n collinear-triple array. Cross-references checked: A000938 (Larrosa Cañestro gcd-sum formula, 2010; Guy & Kelly, Canad. Math. Bull. 11 (1968)), A047264, A010686. +- Ko Yun Tung, Puk Hoi Chun, Yeung Wai Kwan, "On the generalisations of the No-Three-in-Line problem", Hang Lung Mathematics Awards 2025 (bronze), Thm 2.2.1: exact count S(p,q) of collinear triples by slope in an m x n lattice. It specializes to the 3 x n case. +- No explicit proof of the floor form itself was found. Searched: arXiv 2607.24832 (S. Fried, Further proofs of conjectures from the OEIS) and arXiv 2609.25133 (neither treats A057566), MSE/MO, SeqFan archives, and the web. + +## Citation + +```bibtex +@misc{math0:oeis-a057566b, + author = {{math0}}, + title = {{The corrected floor formula for collinear triples in a 3 x n grid (OEIS A057566) holds for all n}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a057566b}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a060693/README.md b/results/oeis-a060693/README.md new file mode 100644 index 0000000..5386cdc --- /dev/null +++ b/results/oeis-a060693/README.md @@ -0,0 +1,37 @@ +# Schulte's alternating quadratic sum over the Schröder-peaks triangle (A060693) + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Discrete geometry +**Source problem:** OEIS A060693 +**Date:** 2026-10-21 + +## Result + +Let T(n,k) be the number of Schröder paths from (0,0) to (2n,0) (steps U=(1,1), D=(1,-1), H=(2,0), never going below the x-axis) that have exactly k peaks (a peak is a U step immediately followed by a D step). Then for every n ≥ 0, + Σ_{k=0}^{n} (-1)^k · T(n,k) · (n+1-k)^2 = 1 + n + n^2. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A060693](https://oeis.org/A060693) as [`def statement`](../../lean/Math0/Statements/OEIS/A060693.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A060693.lean`](../../lean/Math0/Frontier/OEIS/A060693.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: Sum_{k=0..n} (-1)^k*T(n,k)*(n+1-k)^2 = 1+n+n^2. - _Werner Schulte_, Jan 11 2017" + +Referees: Prior Lean proof: the-omega-institute/trureturing, PR #7436 by ElonSG, "prove: OEIS A060693 Schröder-path peak identity (Schulte 2017)", merged into dev on 2026-09-13 (https://github.com/the-omega-institute/trureturing/pull/7436). It supersedes PR #7402 (https://github.com/the-omega-institute/trureturing/pull/7402), with pre-registration issue #7384 (https://github.com/the-omega-institute/trureturing/issues/7384). The file is D5/S1/Recurrence/Invariants/SchroederPeakAlternatingQuadraticMoment.lean and the theorem is schulte_a060693. The result also follows directly from the OEIS A060693 formula T_n(x) = C_n(x+1) with C_n the Narayana row polynomial (Mitch Harris, Jan 2007), plus the Narayana values N(n,1)=1 and N(n,2)=n(n-1)/2 (A001263). The OEIS entry (local mirror, %I #147, Oct 04 2026) still says "Conjecture". The identity is not in the OEIS Open benchmark (arXiv:2608.11941; tadamcz.com/oeis-open results.json). LANTERN (arXiv:2609.32264), cited in the entry, is about cross-reference relations and does not address this conjecture. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a060693, + author = {{math0}}, + title = {{Schulte's alternating quadratic sum over the Schröder-peaks triangle (A060693)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a060693}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a060693/paper.pdf b/results/oeis-a060693/paper.pdf new file mode 100644 index 0000000..42dff05 Binary files /dev/null and b/results/oeis-a060693/paper.pdf differ diff --git a/results/oeis-a060693/paper.tex b/results/oeis-a060693/paper.tex new file mode 100644 index 0000000..b15efbd --- /dev/null +++ b/results/oeis-a060693/paper.tex @@ -0,0 +1,353 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,inductive,deriving}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 + {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {∈}{{$\in$}}1 + {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {∑}{{$\sum$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +\allowdisplaybreaks +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\def\UrlFont{\normalfont\ttfamily}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Av}{\mathcal{A}} +\newcommand{\ib}[1]{[\,#1\,]} +\newcommand{\lb}{\char123} +\newcommand{\rb}{\char125} + +\title[Schulte's alternating quadratic identity for Schr\"oder paths]{Schr\"oder paths counted by peaks: a formal proof of Schulte's alternating quadratic identity (OEIS A060693)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 21, 2026} + +\begin{document} +\begin{abstract} +Let $T(n,k)$ be the number of Schr\"oder paths from $(0,0)$ to $(2n,0)$ with exactly $k$ peaks (OEIS A060693). +We prove that $\sum_{k=0}^{n}(-1)^k\,T(n,k)\,(n+1-k)^2=1+n+n^2$ for every $n\ge0$, as conjectured by Werner Schulte in the OEIS entry in 2017, by computing the alternating falling-factorial moments of order $0,1,2$ of the peak statistic, for paths started at any height. +The identity is not new: it follows quickly from Harris's formula $T_n(x)=C_n(x+1)$ (2007) relating the row polynomials to the Narayana polynomials, and a Lean proof was merged into the \texttt{trureturing} repository in September 2026; ours is an independent formal proof. +It is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, in which $T(n,k)$ is defined by enumerating paths and checked by the kernel against all $56$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +A \emph{Schr\"oder path} of semilength $n$ is a lattice path from $(0,0)$ to $(2n,0)$ with steps $U=(1,1)$, $D=(1,-1)$ and $H=(2,0)$ that never goes below the $x$-axis; a \emph{peak} is a step $U$ immediately followed by a step $D$. The number $T(n,k)$ of Schr\"oder paths of semilength $n$ with exactly $k$ peaks ($0\le k\le n$) is the triangle A060693 of the OEIS \cite{A060693}, submitted by F.~Chapoton in 2001; the path description is a comment of Emeric Deutsch (2003), which became the name of the entry in 2017. + +On January 11, 2017, Werner Schulte added to the entry the line +\begin{equation}\label{eq:schulte} + \sum_{k=0}^{n}(-1)^k\,T(n,k)\,(n+1-k)^2=1+n+n^2 , +\end{equation} +labelled ``Conjecture''; two days earlier he had added, without that label, the linear companion $\sum_{k=0}^n(-1)^k(1+x(n-k))T(n,k)=x+(1-x)\ib{n=0}$. In revision \#147 of the entry (October~4, 2026) the line \eqref{eq:schulte} is still labelled ``Conjecture''. We prove it for all $n\ge0$ (Theorem~\ref{thm:main}), with a Lean proof of the full statement. + +\subsection*{Prior work and status} +\begin{itemize} +\item \emph{A short proof from known formulas.} The entry records Mitch Harris's formula $T_n(x)=C_n(x+1)$ (January 2007), where $T_n(x)=\sum_kT(n,k)x^k$ and $C_n(x)=\sum_{k=1}^{n}N(n,k)x^k$, with $N(n,k)$ the Narayana numbers A001263 \cite{A001263}, is the $n$-th Narayana row polynomial (the formula is meant for $n\ge1$); equivalently, for all $n\ge0$, $T(n,k)=\sum_j N(n,j)\binom jk$ with $N$ the Narayana triangle A090181 \cite{A090181}, which has $N(0,0)=1$ (Ph.~Deléham, May 2007). Together with $N(n,1)=1$ and $N(n,2)=\binom n2$ for $n\ge1$, this gives \eqref{eq:schulte} in a few lines (Remark~\ref{rem:narayana}, not formalized). In substance, the identity is a corollary of formulas that were in the entry before the conjecture was posted. +\item \emph{A prior formal proof.} A Lean proof of \eqref{eq:schulte}, the theorem \texttt{schulte\_a060693} in the file \path{SchroederPeakAlternatingQuadraticMoment.lean}, was merged into the \texttt{dev} branch of the GitHub repository \texttt{the-omega-institute/trureturing} on September~13, 2026, in pull request \#7436 by ElonSG \cite{TRU}, which supersedes pull request \#7402 and was pre-registered in issue \#7384. According to the math0 literature referee, who read the source but could not compile it (nor have we), $T$ is defined there through a first-return decomposition of Schr\"oder words, and the proof uses recurrences for the signed falling-factorial moments of orders $0,1,2$. It was found by the math0 literature review after our proof was written; the two developments are independent. +\item The math0 referees found no other proof in arXiv, MathOverflow or Mathematics Stack Exchange. +\end{itemize} +We therefore classify our result as an \emph{independent formal proof} of a known result. Our proof uses only the combinatorial definition of $T$. + +\section{Statement}\label{sec:statement} + +The FORMULA section of A060693 \cite{A060693} (offset $0$, $0\le k\le n$) contains, verbatim, the line +\begin{quote}\raggedright +\texttt{Conjecture: Sum\_\lb k=0..n\rb\ (-1)\^{}k*T(n,k)*(n+1-k)\^{}2 = 1+n+n\^{}2. - \_Werner Schulte\_, Jan 11 2017} +\end{quote} + +\begin{theorem}\label{thm:main} +For $n,k\ge0$ let $T(n,k)$ be the number of lattice paths from $(0,0)$ to $(2n,0)$ with steps $U=(1,1)$, $D=(1,-1)$, $H=(2,0)$ that never go below the $x$-axis and contain exactly $k$ occurrences of $U$ immediately followed by $D$. Then for every $n\ge0$, +\[ + \sum_{k=0}^{n}(-1)^k\,T(n,k)\,(n+1-k)^2=1+n+n^2 . +\] +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A060693.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{7877842d\ldots 6b90}) before any proof attempt. Its definitions and the statement read as follows (verbatim; we omit the import, comments, blank lines, all theorems, a \texttt{DecidablePred} instance for \decl{IsSchroderPath}, the definitions \decl{valid}, \decl{peaksFrom}, \decl{cnt}, \decl{dTerm}, \decl{step}, \decl{Tab}, \decl{look}, \decl{next}, \decl{tabs}, \decl{Tfast}, \decl{a} of the evaluator and data checks described below, and, at the start of the namespace, the inductive type \texttt{Step} with constructors \texttt{U}, \texttt{D}, \texttt{H}, its displacements \texttt{Step.dx : Step → ℕ} and \texttt{Step.dy : Step → ℤ}, giving $(1,1)$, $(1,-1)$, $(2,0)$, and the line \texttt{open Step}): +\begin{lstlisting} +namespace Math0.Statements.A060693 +def width (p : List Step) : ℕ := (p.map Step.dx).sum +def height (p : List Step) : ℤ := (p.map Step.dy).sum +def IsSchroderPath (n : ℕ) (p : List Step) : Prop := + width p = 2 * n ∧ height p = 0 ∧ ∀ q ∈ p.inits, 0 ≤ height q +def peaks (p : List Step) : ℕ := (p.zip p.tail).count (U, D) +def words : ℕ → List (List Step) + | 0 => [[]] + | 1 => [[U], [D]] + | m + 2 => (words (m + 1)).map (U :: ·) ++ (words (m + 1)).map (D :: ·) ++ + (words m).map (H :: ·) +def schroderPaths (n : ℕ) : Finset (List Step) := + (words (2 * n)).toFinset.filter (IsSchroderPath n) +def T (n k : ℕ) : ℕ := ((schroderPaths n).filter (fun p => peaks p = k)).card +def statement : Prop := + ∀ n : ℕ, ∑ k ∈ Finset.range (n + 1), (-1 : ℤ) ^ k * (T n k : ℤ) * ((n : ℤ) + 1 - k) ^ 2 = + 1 + (n : ℤ) + (n : ℤ) ^ 2 +end Math0.Statements.A060693 +\end{lstlisting} +A path is a word \texttt{p : List Step} drawn from the origin. For a word $p$ let $|p|=\#U+\#D+2\#H$ be its \emph{width} and $\operatorname{ht}(p)=\#U-\#D$ its \emph{height}; after a prefix $q$ the path is at $(|q|,\operatorname{ht}(q))$. \texttt{IsSchroderPath n p} says that the path ends at $(2n,0)$ and that every prefix (\texttt{p.inits} includes the empty prefix and $p$) ends at height $\ge0$; checking vertices suffices, since the path is straight between them. \texttt{peaks p} counts adjacent pairs $(U,D)$. The list \texttt{words m} contains every word of width $m$ exactly once (\decl{mem_words}, \decl{nodup_words}), so \texttt{T n k} is $T(n,k)$; the file proves \decl{T_eq_ncard}: \texttt{T n k = \lb p : List Step | IsSchroderPath n p ∧ peaks p = k\rb.ncard}. The sum is computed in $\Z$, so $n+1-k$ is not truncated, and \decl{statement} covers all $n\ge0$ with no further hypothesis. + +\emph{Data checks.} As \texttt{T} enumerates exponentially many words, the file also defines a table-based evaluator \decl{Tfast} from the recursion of Lemma~\ref{lem:cnt}(b) below and proves \decl{T_eq_Tfast}: \texttt{T n k = Tfast n k} for all $n,k$. Through this lemma, \texttt{decide +kernel} checks in the kernel that \texttt{T} reproduces rows $n=0,\dots,9$ and $T(10,0)=16796$ (\decl{T_data}), and that the triangle read by rows reproduces all $56$ terms of the OEIS data (\decl{a_data}). This anchors the definition to the entry independently of the conjecture. The file also checks \eqref{eq:schulte} for $n\le12$ (\decl{statement_check}), as a transcription check only. + +\section{Proof}\label{sec:proof} + +The proof follows \path{lean/Math0/Frontier/OEIS/A060693.lean}. Throughout, $b$ ranges over $\{0,1\}$ (the Lean \texttt{false}, \texttt{true}), $\ib{P}$ is $1$ if $P$ holds and $0$ otherwise, and $\Av_m$ is the set of words of width $m$. + +\subsection{Generalized counts} +The statement file defines, by recursion on words, \decl{valid} and \decl{peaksFrom}: +\[ +\begin{aligned} +&\operatorname{valid}_h(\varepsilon)=\ib{h=0},\quad \operatorname{valid}_h(Up)=\operatorname{valid}_{h+1}(p),\quad \operatorname{valid}_0(Dp)=0,\\ +&\operatorname{valid}_{h+1}(Dp)=\operatorname{valid}_h(p),\quad \operatorname{valid}_h(Hp)=\operatorname{valid}_h(p);\\ +&\operatorname{pk}_b(\varepsilon)=0,\quad \operatorname{pk}_b(Up)=\operatorname{pk}_1(p),\quad \operatorname{pk}_b(Dp)=b+\operatorname{pk}_0(p),\quad \operatorname{pk}_b(Hp)=\operatorname{pk}_0(p). +\end{aligned} +\] +So $\operatorname{valid}_h(p)$ holds if and only if the path $p$ started at height $h$ never goes below the axis and ends on it (\decl{valid_iff}), and $\operatorname{pk}_b(p)$ is the number of peaks of $p$, plus $1$ if $b=1$ and $p$ begins with $D$ (\decl{peaksFrom_eq}); the flag $b$ records that the step before $p$ was a $U$. The count \decl{cnt} is +\[ + c(m,h,b,k)=\#\{p\in\Av_m:\ \operatorname{valid}_h(p),\ \operatorname{pk}_b(p)=k\}. +\] + +\begin{lemma}[(a)--(c) in the statement file]\label{lem:cnt} +For all $m,h,k,n\in\N$ and $b\in\{0,1\}$: +\begin{enumerate} +\item[(a)] $T(n,k)=c(2n,0,0,k)$ \quad(\decl{T_eq_cnt}); +\item[(b)] $c(m+2,h,b,k)=c(m+1,h+1,1,k)+\delta(m,h,b,k)+c(m,h,0,k)$, where $\delta=0$ if $h=0$; $\delta=c(m+1,h-1,0,k)$ if $h\ge1$, $b=0$; and $\delta=\ib{k\ge1}\,c(m+1,h-1,0,k-1)$ if $h\ge1$, $b=1$ \quad(\decl{cnt_step}); +\item[(c)] $c(m,h,b,k)=0$ if $mn$. +\end{corollary} + +\subsection{Weighted sums} +For a weight $w\colon\N\to\Z$ put $W_w(m,h,b)=\sum_{k=0}^{m}w(k)\,c(m,h,b,k)$ (Lean \texttt{W w m h b}). +By Lemma~\ref{lem:cnt}(c) the range of summation may be replaced by $\{0,\dots,N-1\}$ for any $N\ge m+1$ (\decl{W_eq_range}); $W_w(m,h,b)=0$ if $m next + 2 ≡ prev [MOD 10]) +open Classical in +noncomputable def a (n : ℕ) : ℕ := + if h : ∃ N, IsDesc2 N ∧ 2 * n + 1 ∣ N then Nat.find h else 0 +def statement : Prop := ∀ n : ℕ, a n = 0 ↔ 125 ∣ 2 * n + 1 +end Math0.Statements.A062887 +\end{lstlisting} +Here \texttt{Nat.digits 10 N} is the digit list $(d_0,\dots,d_{L-1})$ defined above (empty for $N=0$), so its reverse lists the digits from left to right, and \texttt{IsChain R} requires $R$ between each pair of consecutive entries. Thus \texttt{IsDesc2 N} says that $N\in\cD$; the condition $0 [] + | x, L + 1 => x :: gen ((x + 2) % 10) L +theorem isDesc2_ofDigits_gen (x L : ℕ) (hx : x < 10) (hodd : Odd x) (hL : 1 ≤ L) : + IsDesc2 (Nat.ofDigits 10 (gen x L)) +theorem exists_gen_of_isDesc2 {N : ℕ} (h : IsDesc2 N) : + ∃ x L, x < 10 ∧ Odd x ∧ 1 ≤ L ∧ Nat.digits 10 N = gen x L +theorem a_eq_of_aSearch {n B v : ℕ} (h : aSearch n B = some v) : a n = v +theorem a_data : (List.range 26).map (fun i => a (i + 0)) = + [1, 3, 5, 7, 9, 319, 975, 75, 7531, 19, 197531975319, 3197, 75, 5319, 319, 31, + 3197531975319, 53197531975, 1975319, 975, 531975, 1975319753197, 19753197531975, + 75319753197531, 319753197531975319, 753197531975319753] := by + simp only [Nat.add_zero] + exact map_a_eq_of_aSearch (B := 18) (by decide +kernel) +\end{lstlisting} +The list \texttt{gen x L} is $\bigl(x,(x+2)\bmod10,(x+4)\bmod10,\dots\bigr)$ of length $L$, and the first two theorems say that $\cD$ consists exactly of the numbers with digit list \texttt{gen x L}, $x$ an odd digit and $L\ge1$ (Lemma~\ref{lem:gen} below). The computable function \texttt{aSearch n B} (defined in the file through a list \decl{cands} of candidates) returns the least multiple of $2n+1$ among the $5B$ admissible numbers \texttt{Nat.ofDigits 10 (gen x L)} with $x\in\{1,3,5,7,9\}$ and $1\le L\le B$, if there is one. By \decl{a_eq_of_aSearch}, a value \texttt{some v} determines \texttt{a n = v}: an admissible $k0$. For each $i$, $d_{i+1}\equiv d_i+2\pmod{10}$ and $0\le d_{i+1}<10$ give $d_{i+1}=(d_i+2)\bmod 10$, so by induction along the list $(d_0,\dots,d_{L-1})=\gamma(d_0,L)$, and $d_0$ is an odd digit. (In Lean, \decl{List.isChain_reverse} turns the condition on the reversed list for $(\mathit{prev},\mathit{next})\mapsto \mathit{next}+2\equiv \mathit{prev}$ into the condition on the list itself for $(p,q)\mapsto p+2\equiv q$, and the induction is \decl{gen_of_chain}.) +\end{proof} + +\begin{lemma}[\decl{a_eq_zero_iff}]\label{lem:zero} +For every $n\ge0$, $a(n)=0$ if and only if no admissible number is divisible by $2n+1$. +\end{lemma} + +\begin{proof} +If some admissible number is divisible by $2n+1$, then $a(n)$ is the least such number; it is admissible, hence positive. Otherwise $a(n)=0$ by definition. +\end{proof} + +\begin{lemma}[\decl{not_dvd_125}]\label{lem:125} +No admissible number is divisible by $125$. +\end{lemma} + +\begin{proof} +Let $N$ be admissible. By Lemma~\ref{lem:gen}, $N=G(x,L)$ with $x\in\{1,3,5,7,9\}$ and $L\ge1$. Applying \eqref{eq:rec} up to three times gives the following values, where $K=G\bigl((x+6)\bmod 10,L-3\bigr)\ge0$ for $L\ge3$: +\[ +\begin{array}{c|ccccc} + x & 1 & 3 & 5 & 7 & 9\\\hline + N\ (L=1) & 1 & 3 & 5 & 7 & 9\\ + N\ (L=2) & 31 & 53 & 75 & 97 & 19\\ + N-1000K\ (L\ge3) & 531 & 753 & 975 & 197 & 319\\ + (N-1000K)\bmod 125 & 31 & 3 & 100 & 72 & 69 +\end{array} +\] +If $L\le2$, then $0 1. C is 4 or 9, and N is 87…12 or 98…01. OEIS A031877 comment (Hasler 2014, annotated by Sloane Oct 19 2014): "All terms are of the form 87...12 = 4*21...78 or 98...01 = 9*10...89. [This was proved by Hoey, 1992.]" L. F. Klosinski and D. C. Smolarski, "On the Reversing of Digits", Math. Mag. 42 (1969) 208-210: k ∈ {1, 4, 9}. D. W. Wilson's theorem (1997) in A001232/A008918: terms are 99·m and 198·m with m a 0/1 palindrome with no singleton digits, so they are ≡ 89 and ≡ 78 (mod 100). N. J. A. Sloane, "2178 And All That", arXiv:1307.0453, Fib. Quart. 52 (2014) 99-120. L. H. Kendrick, "Young Graphs: 1089 et al.", J. Integer Seq. 18 (2015) 15.9.7. B. V. Holt, INTEGERS 14 (2014) A42. Webster and Williams, Math. Spectrum 45 (2012/13) 96-102. M. F. Hasler, A001232 comment (Oct 2022): terms begin and end with 109*89. Dale's conjecture (Dec 2017) came after all of these. The OEIS entry was not updated to mark it resolved, and I found no prior Lean formalization. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a071685, + author = {{math0}}, + title = {{Reverse-divisor numbers are 1, 12, 78 or 89 mod 100 (A071685, Dale's conjecture)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a071685}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a071685/paper.pdf b/results/oeis-a071685/paper.pdf new file mode 100644 index 0000000..2b2a7ab Binary files /dev/null and b/results/oeis-a071685/paper.pdf differ diff --git a/results/oeis-a071685/paper.tex b/results/oeis-a071685/paper.tex new file mode 100644 index 0000000..5a6442b --- /dev/null +++ b/results/oeis-a071685/paper.tex @@ -0,0 +1,371 @@ +% math0 manuscript template. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,apply,unfold,infer_instance}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, keepspaces=true, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 + {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {≠}{{$\ne$}}1 {∣}{{$\mid$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\sw}{\sigma} +\newcommand{\len}{\ell} + +\title[Reverse divisors modulo 100]{Non-palindromic numbers not divisible by $10$ that divide or are divided by their digit reversal are congruent to $1$, $12$, $78$ or $89$ modulo $100$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + +\begin{document} +\begin{abstract} +Let $R(n)$ be the decimal digit reversal of $n$. OEIS A071685 lists the non-palindromic numbers $n$, not divisible by $10$, such that $n\mid R(n)$ or $R(n)\mid n$, and in 2017 H.~P. Dale conjectured there that every term is congruent to $1$, $12$, $78$ or $89$ modulo $100$. +We give a proof that uses only the two leading and two trailing digits of $n$: if $R(n)=kn$, they reduce the problem to a finite check over $k<10$ and $n\bmod100$, whose only solutions are $(k,n\bmod100)=(4,78)$ and $(9,89)$, and the case $n=k\,R(n)$ follows by applying this to $R(n)$. +The statement is a known result: it follows at once from the classification of base-$10$ reverse multiples due to Hoey (1992) and Wilson (1997), which was recorded in the OEIS before the conjecture was posed, so our contribution is the first formal proof of a known result. +The proof is verified in Lean~4 against a statement that math0 formalized from the OEIS entry; its definitions are checked by the kernel against the $16$ listed terms below $10^7$, and it was reviewed for fidelity and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +For $n\in\N$ let $R(n)$ be the number obtained by writing the decimal digits of $n$ in reverse order, leading zeros being dropped (OEIS A004086 \cite{A004086}); thus $R(1089)=9801$ and $R(120)=21$. The two smallest numbers that are proper divisors of their reversal, $1089$ and $2178$, with $9\cdot1089=9801$ and $4\cdot2178=8712$, are classical \cite{Sloane}. The OEIS entry A071685 \cite{A071685}, contributed by Labos Elemer in 2002, lists the \emph{non-palindromic numbers $n$, not divisible by $10$, such that $n\mid R(n)$ or $R(n)\mid n$}: +\[ + 1089,\ 2178,\ 8712,\ 9801,\ 10989,\ 21978,\ 87912,\ 98901,\ 109989,\ 219978,\ \dots +\] +On December~13, 2017, Harvey P. Dale added to the entry the conjecture that every term is congruent to $1$, $12$, $78$ or $89$ modulo $100$. We prove this conjecture (Theorem~\ref{thm:main}). + +\subsection*{Prior work} +Numbers $n$ with $R(n)=kn$, $k\ge2$, are called \emph{reverse multiples}, and the multiples $N=k\,R(N)$ \emph{palintiples}. Their systematic study in arbitrary bases began with Sutcliffe \cite{Sutcliffe}; see Sloane \cite{Sloane} for a history. In base $10$, Klosinski and Smolarski \cite{KS} showed that $R(n)=kn$ forces $k\in\{1,4,9\}$ (as recorded by D.~W. Wilson in A008919 \cite{A008919}). D.~J. Hoey \cite{Hoey}, in a rec.puzzles article of May 1992, described all base-$10$ solutions of $N=C\cdot R(N)$ with $C>1$ by finite-state machines: only $C\in\{4,9\}$ occurs, and $N$ has the shape $87\cdots12$ or $98\cdots01$. Accordingly the OEIS entry A031877 \cite{A031877} states (M.~F. Hasler, August~18, 2014) that ``All terms are of the form 87...12 = 4*21...78 or 98...01 = 9*10...89'', annotated ``This was proved by Hoey, 1992'' by N.~J.~A. Sloane (October~19, 2014). D.~W. Wilson stated in A001232 \cite{A001232} (December~15, 1997) that the positive solutions of $9n=R(n)$ have the form $99m$ with $m$ a palindrome with digits in $\{0,1\}$ and no isolated digit, and in A008918 \cite{A008918} that the positive solutions of $4n=R(n)$ are their doubles. Young \cite{Young,Young2} introduced trees for $k$-reverse multiples, Sloane \cite{Sloane} turned them into ``Young graphs'' and enumerated the solutions, and Kendrick \cite{Kendrick}, Holt \cite{Holt} and Webster and Williams \cite{WW} gave further accounts and generalizations. + +Dale's conjecture is an immediate consequence of Hoey's or Wilson's description. By its own comments, A071685 is the union of A008919 (the $n$ with $R(n)=kn$, $k\ge2$) and A031877 (their reversals). In Wilson's description $m$ begins and therefore ends with the block $11$, so the solutions of $R(n)=9n$ and $R(n)=4n$ are $\equiv99\cdot11\equiv89$ and $\equiv198\cdot11\equiv78\pmod{100}$, and their reversals $9n$ and $4n$ are $\equiv1$ and $\equiv12$. The entry A071685 (revision \#39 of November~5, 2025) still lists the statement as a conjecture, and the math0 referees found no publication that addresses Dale's comment explicitly. Thus the result is known; to our knowledge the present proof is its first formalization: the referees found no earlier Lean or Mathlib formalization, and the statement is not in the formal-conjectures repository \cite{FC} (checked at commit \texttt{c77fdd4}). + +Our proof does not use the classification. If $n$ has $d\ge2$ digits and $10\nmid n$, the two leading digits of $R(n)$ are the two trailing digits of $n$ exchanged, and vice versa. If $R(n)=kn$, comparing both sides at the scale $10^{d-2}$ gives inequalities and a congruence between $k$, the two leading digits of $n$ and $n\bmod100$, and a finite check leaves only $(k,n\bmod100)=(4,78)$ and $(9,89)$. This is the familiar analysis of the outer digits of a reverse multiple, carried to two digits; we claim no novelty for it. + +\section{Statement}\label{sec:statement} + +The entry A071685 \cite{A071685} reads in part (verbatim): +\begin{quote}\raggedright +\textsc{Name}: Non-palindromic numbers n, not divisible by 10, such that either n divides R(n) or R(n) divides n, where R(n) is the digit-reversal of n.\\[2pt] +\textsc{Comments}: The quotient R(n)/n or n/R(n) is always 4 or 9. [\dots]\\ +Conjecture: every term mod 100 is equal to 1, 12, 78, or 89. - \emph{Harvey P. Dale}, Dec 13 2017 +\end{quote} +Here R is A004086 \cite{A004086}, ``Read n backwards'', with the comment ``Leading zeros (after the reversal has taken place) are omitted''; and by a comment in A002113 \cite{A002113} (Palindromes in base 10), ``n is a palindrome [\dots] if and only if n = A004086(n)''. + +\begin{definition}\label{def:R} +For $n\in\N$ let $\len(n)$ be the number of decimal digits of $n$, with $\len(0)=0$, and let $d_0,\dots,d_{\len(n)-1}$ be these digits, least significant first, so that $n=\sum_i d_i10^i$. Put $R(n)=\sum_{i}d_{\len(n)-1-i}10^i$. Call $n$ a \emph{term} if $R(n)\ne n$, $10\nmid n$, and $n\mid R(n)$ or $R(n)\mid n$. +\end{definition} + +\begin{theorem}[Dale's conjecture]\label{thm:main} +Every term $n$ satisfies $n\bmod100\in\{1,12,78,89\}$. +\end{theorem} + +All four residues occur: $9801\equiv1$, $8712\equiv12$, $2178\equiv78$ and $1089\equiv89$. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A071685.lean}, reviewed for fidelity, and frozen before the proof attempt (SHA-256 \texttt{0a3757cb\dots 40c95}). Its definitions, main data check and statement are, verbatim except that docstrings, comments, the proof of \decl{a_data} and all other declarations are omitted (the latter are \decl{R_examples}, and the lemmas and kernel-evaluation helpers that serve the data check; five of these lemmas are reused in Section~\ref{sec:proof}): +\begin{lstlisting} +namespace Math0.Statements.A071685 + +def R (n : ℕ) : ℕ := Nat.ofDigits 10 (Nat.digits 10 n).reverse + +def IsTerm (n : ℕ) : Prop := R n ≠ n ∧ ¬ 10 ∣ n ∧ (n ∣ R n ∨ R n ∣ n) + +instance : DecidablePred IsTerm := fun n => by unfold IsTerm; infer_instance + +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) + +theorem a_data : (List.range 16).map (fun i => a (i + 1)) = + [1089, 2178, 8712, 9801, 10989, 21978, 87912, 98901, 109989, 219978, 879912, 989901, + 1099989, 2199978, 8799912, 9899901] := by + -- (kernel scans, omitted; see the text) + +def statement : Prop := + ∀ n : ℕ, IsTerm n → n % 100 = 1 ∨ n % 100 = 12 ∨ n % 100 = 78 ∨ n % 100 = 89 + +end Math0.Statements.A071685 +\end{lstlisting} + +\emph{Encoding.} Mathlib's \texttt{Nat.digits 10 n} is the list $[d_0,\dots,d_{\len(n)-1}]$ of decimal digits of $n$, least significant first (empty for $n=0$), and \texttt{Nat.ofDigits 10 L} evaluates a list $L$ in the same order, $\sum_i L_i10^i$. So \decl{R} is $R$ of Definition~\ref{def:R}. Trailing zeros of $n$ become top entries of the reversed list and contribute nothing, as A004086 prescribes ($R(8380)=838$). Non-palindromic is \texttt{R n ≠ n}, following A002113, and divisibility on $\N$ is $a\mid b\iff\exists c,\ b=ac$. \decl{IsTerm} is the entry's name clause by clause, and \decl{statement} is Theorem~\ref{thm:main}, quantified over all terms. There is no degenerate case: $n=0$ is excluded by $10\mid0$, and $R(n)=0$ only for $n=0$. The sequence itself (offset~$1$) is \decl{a}; the statement does not use it. + +\emph{Checks against the OEIS.} \decl{R_examples} checks $R(1089)=9801$, $R(8712)=2178$, $R(12021)=12021$, $R(8380)=838$, $R(120)=21$ and $R(0)=0$; here $12021$ and $8380$ are the palindrome and the multiple of $10$ that the entry's example names as excluded. \decl{a_data} checks that the definitions reproduce the first $16$ listed terms, which are all listed terms below $10^7$. It rests on the lemma \decl{term_iff}: below $10^7$ the terms are exactly these $16$ numbers. It is proved by kernel evaluation (\texttt{decide +kernel}) of helper functions written with recursors and primitive arithmetic, each proved sound for \decl{R} and \decl{IsTerm}: all $n<1000$ are scanned, and for $4$ to $7$ digits about $150{,}000$ candidates on arithmetic progressions, selected by one-digit facts on the leading and last digits and by $R(n)\equiv n\pmod9$, all proved in the same file. In Python, the fidelity reviewer recomputed the terms below $10^7$, and a referee checked that the $10{,}000$ terms of the OEIS b-file are terms and satisfy the congruence. + +\section{Proof}\label{sec:proof} + +We follow the Lean proof; each statement carries the names of the corresponding declarations. Besides $\len$ and $R$ we use +\[ + \sw(x)=10\,(x\bmod10)+\lfloor x/10\rfloor\qquad(x\in\N), +\] +which exchanges the two digits of a number $x<100$ (\decl{rev2}), and for $n\ge10$ the scale $P_n=10^{\len(\lfloor n/100\rfloor)}$; by Lemma~\ref{lem:len} below, $P_n=10^{\len(n)-2}$. + +\begin{lemma}[\decl{R_cons}, \decl{len_cons}, \decl{R_lt}, \decl{R_R}, \decl{len_R}; statement file]\label{lem:basic} +\begin{enumerate} +\item[(a)] If $n\ge1$, then $\len(n)=\len(\lfloor n/10\rfloor)+1$ and $R(n)=R(\lfloor n/10\rfloor)+10^{\len(\lfloor n/10\rfloor)}\,(n\bmod10)$. +\item[(b)] $R(n)<10^{\len(n)}$ for all $n$. +\item[(c)] If $10\nmid n$, then $\len(R(n))=\len(n)$ and $R(R(n))=n$. +\end{enumerate} +\end{lemma} + +\begin{proof} +(a) For $n\ge1$ the digit list of $n$ is $(n\bmod10)$ followed by the digit list of $\lfloor n/10\rfloor$. Reversing puts $n\bmod10$ at the end, at position $\len(\lfloor n/10\rfloor)$, after the reversed digit list of $\lfloor n/10\rfloor$, whose value is $R(\lfloor n/10\rfloor)$. +(b) $R(n)$ is the value of a list of $\len(n)$ entries, each at most $9$. +(c) Since $10\nmid n$, we have $n\ge1$ and $d_0\ne0$. So the reversed list consists of digits and its most significant entry $d_0$ is nonzero, hence it is the digit list of its value $R(n)$. Thus the digit list of $R(n)$ is the reverse of that of $n$, which gives $\len(R(n))=\len(n)$, and reversing once more gives $R(R(n))=n$. +\end{proof} + +\begin{lemma}[\decl{len_two}, \decl{P_le}]\label{lem:len} +Let $n\ge10$ and $P=P_n$. Then $\len(n)=\len(\lfloor n/100\rfloor)+2$ and $10P\le n$. +\end{lemma} + +\begin{proof} +The first claim is Lemma~\ref{lem:basic}(a) applied to $n$ and to $\lfloor n/10\rfloor\ge1$, since $\lfloor\lfloor n/10\rfloor/10\rfloor=\lfloor n/100\rfloor$. Let $q=\lfloor n/100\rfloor$. If $q=0$, then $P=1$ and $10P\le n$. If $q\ge1$, then $10^{\len(q)}\le10q$, as $q$ has $\len(q)$ digits, so $10P\le100q\le n$. +\end{proof} + +\begin{lemma}[\decl{R_div_P}]\label{lem:Rlead} +Let $n\ge10$ and $P=P_n$. Then $\lfloor R(n)/P\rfloor=\sw(n\bmod100)$: the two leading digits of $R(n)$ are the two trailing digits of $n$, exchanged. +\end{lemma} + +\begin{proof} +Let $q=\lfloor n/100\rfloor$, $u=n\bmod10$ and $t=\lfloor n/10\rfloor\bmod10$. Lemma~\ref{lem:basic}(a) for $\lfloor n/10\rfloor$ gives $\len(\lfloor n/10\rfloor)=\len(q)+1$ and $R(\lfloor n/10\rfloor)=R(q)+P\,t$, and then for $n$ it gives +\[ + R(n)=R(q)+P\,t+10P\,u=R(q)+P\,(10u+t). +\] +By Lemma~\ref{lem:basic}(b), $0\le R(q)<10^{\len(q)}=P$. Hence $\lfloor R(n)/P\rfloor=10u+t$, and $10u+t=\sw(n\bmod100)$ because $(n\bmod100)\bmod10=u$ and $\lfloor(n\bmod100)/10\rfloor=t$. +\end{proof} + +\begin{lemma}[\decl{R_ge}, \decl{div_P}]\label{lem:nlead} +Let $n\ge10$ with $10\nmid n$, and $P=P_n$. Then $R(n)\ge10$ and $\lfloor n/P\rfloor=\sw(R(n)\bmod100)$. +\end{lemma} + +\begin{proof} +By Lemmas~\ref{lem:basic}(c) and~\ref{lem:len}, $\len(R(n))=\len(n)\ge2$, so $R(n)\ge10$. Lemma~\ref{lem:len} for $n$ and for $R(n)$ gives $\len(\lfloor R(n)/100\rfloor)=\len(R(n))-2=\len(n)-2=\len(\lfloor n/100\rfloor)$, so $P_{R(n)}=P$. Lemma~\ref{lem:Rlead} applied to $R(n)$, together with $R(R(n))=n$, gives the claim. +\end{proof} + +The finite step concerns the multiplier $k$ and the residue $B=n\bmod100$. For $k,B\in\N$ let $A(k,B)=\sw(kB\bmod100)$, and let $\mathrm{Ok}(k,B)$ be the conjunction of +\[ + \text{(i) } B\bmod10\ne0,\quad + \text{(ii) } k\ne1,\quad + \text{(iii) } A(k,B)\ge10,\quad + \text{(iv) } k\,A(k,B)\le\sw(B) by unfold Ok; infer_instance + +private theorem check : + ∀ k < 10, ∀ B < 100, Ok k B → (k = 4 ∧ B = 78) ∨ (k = 9 ∧ B = 89) := by + decide +kernel +\end{lstlisting} +The certificate is the decision procedure itself: the \texttt{Decidable} instance for the bounded quantifiers $\forall k<10$, $\forall B<100$ and for \decl{Ok} yields a Boolean, and \texttt{decide +kernel} asks the kernel to confirm by definitional unfolding (with its built-in arithmetic on numerals) that it evaluates to \texttt{true} on all $1000$ pairs. No compiled code is trusted and no axiom is added (unlike \texttt{native\_decide}, which adds \decl{Lean.ofReduceBool}). For the reader we also verify the lemma by hand. + +\begin{proof}[Proof of Lemma~\ref{lem:check} by hand] +Write $B=10\beta+b$ with digits $\beta,b$, so $\sw(B)=10b+\beta$ and $b\ge1$ by (i). Write $A=A(k,B)=10a+a'$ with $a=kb\bmod10$ and $a'=\lfloor kB/10\rfloor\bmod10$. By (iii), $a\ge1$, so $k\ne0$. By (iv), $10ka\le kA\le\sw(B)\le10b+9$, hence $ka\le b$. + +\emph{Last digit and leading digit.} We have $2\le k\le ka\le b\le9$ and $kb\equiv a\pmod{10}$ with $a\ge1$. If $k\ge5$, then $a=1$ and $kb\equiv1\pmod{10}$, so $k\in\{7,9\}$ with $b=3$ or $b=9$ respectively, and $k\le b$ leaves $(k,a,b)=(9,1,9)$. If $k=4$, then $a\le2$ and $a$ is even, so $a=2$, $4b\equiv2$ gives $b\in\{3,8\}$, and $b\ge8$ leaves $(4,2,8)$. If $k=3$, then $a\le3$, and $3b\equiv a$ gives $(a,b)\in\{(1,7),(2,4),(3,1)\}$, of which only $(1,7)$ satisfies $3a\le b$. If $k=2$, then $a\le4$ is even, so $a\in\{2,4\}$; $a=2$ gives $b\in\{1,6\}$, and $b\ge4$ leaves $b=6$, while $a=4$ gives $b\in\{2,7\}$, both $<8$. So +\[ + (k,a,b)\in\{(2,2,6),\ (3,1,7),\ (4,2,8),\ (9,1,9)\}. +\] + +\emph{Second digits.} Condition (iv) reads $10ka+ka'\le10b+\beta<10ka+ka'+k$, with $a',\beta\le9$. +For $(2,2,6)$ it requires $60+\beta<42+2a'\le60$, which is impossible; for $(3,1,7)$ it requires $70+\beta<33+3a'\le60$, also impossible. +For $(4,2,8)$ it says $4a'\le\beta<4a'+4$, that is $a'=\lfloor\beta/4\rfloor$, while $4B=40\beta+32$ gives $a'=(4\beta+3)\bmod10$. For $\beta=0,\dots,9$ the first expression takes the values $0,0,0,0,1,1,1,1,2,2$ and the second $3,7,1,5,9,3,7,1,5,9$; they agree only for $\beta=7$. So $B=78$, and indeed $4\cdot78=312$, $A=\sw(12)=21$, $84\le87<88$. +For $(9,1,9)$ it says $9a'\le\beta<9a'+9$, that is $a'=\lfloor\beta/9\rfloor$, while $9B=90\beta+81$ gives $a'=(9\beta+8)\bmod10$. The first expression is $0$ for $\beta\le8$ and $1$ for $\beta=9$; the second is $8-\beta$ for $\beta\le8$ and $9$ for $\beta=9$. They agree only for $\beta=8$. So $B=89$, and indeed $9\cdot89=801$, $A=\sw(1)=10$, $90\le98<99$. +\end{proof} + +\begin{proposition}[\decl{fwd}]\label{prop:fwd} +Let $n,k\in\N$ with $10\nmid n$, $R(n)=nk$ and $R(n)\ne n$. Then $(k,\,n\bmod100)$ is $(4,78)$ or $(9,89)$. +\end{proposition} + +\begin{proof} +First, $n\ge10$. Indeed $n\ne0$ since $10\mid0$, and if $1\le n\le9$, Lemma~\ref{lem:basic}(a) gives $R(n)=R(0)+10^{0}\,n=n$, contrary to $R(n)\ne n$. + +Let $P=P_n$, $A=\lfloor n/P\rfloor$ and $B=n\bmod100$. By Lemma~\ref{lem:nlead}, $A=\sw(R(n)\bmod100)=\sw(nk\bmod100)=\sw(Bk\bmod100)=A(k,B)$. By Lemma~\ref{lem:Rlead}, $\lfloor nk/P\rfloor=\lfloor R(n)/P\rfloor=\sw(B)$. By Lemma~\ref{lem:len}, $A\ge10$, which is (iii). Since $nk=R(n)\ge10$ by Lemma~\ref{lem:nlead}, $k\ge1$, and $k\ne1$ because $R(n)\ne n$, which is (ii). Division with remainder gives +\[ + AP\le n<(A+1)P,\qquad \sw(B)\,P\le nk<(\sw(B)+1)P . +\] +Hence $kAP\le kn<(\sw(B)+1)P$, so $kA\le\sw(B)$; and $\sw(B)P\le kn 0, a(n) = (3*A011371(n) - Sum_{k=1..n} A007814(k)^2)/2, with the right-hand side computed exactly in Q. + +## Assessment + +The identity is equivalent to the local step 2a(n+1) + v2(n+1)^2 = 2a(n) + 3*v2(n+1). This is immediate: if n ends in t one-bits, then adding 1 clears bit positions 0..t-1 and sets bit t, so a(n+1) = a(n) - t(t-1)/2 + t. Summing this step over n is the whole proof. You can also get it in a few lines by writing both sides as Sum_j c_j*floor(n/2^j), using Legendre's formula and the standard count of multiples of 2^j, or by reading it off Gutkovskiy's g.f. in the entry. It takes a few lines of classical bit-counting, and the manuscript itself says it claims no new method. + +*Follows from:* Gutkovskiy's g.f. in the entry, (1/(1-x)) * Sum_{k>=1} k*x^(2^k)/(1+x^(2^k)), together with Legendre's formula A011371(n) = Sum_j floor(n/2^j) and the classical count Sum_{k<=n} f(v2(k)) = Sum_j (f(j)-f(j-1)) floor(n/2^j). Alternatively it follows directly from the binary-increment step n -> n+1 (Stephan's recursion in the entry gives the same thing). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A073642](https://oeis.org/A073642) as [`Math0.Statements.A073642.statement`](../../lean/Math0/Statements/OEIS/A073642.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A073642.lean`](../../lean/Math0/Frontier/OEIS/A073642.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: A073642 (if n = 2^b+2^c+..., a(n)=b+c+...): "Conjecture: a(n) = (3*A011371(n) - Sum_{k=1..n} A007814(k)^2)/2 for n > 0. - _Velin Yanev_, Sep 09 2017". Siblings: A059906: "Conjecture: a(n) = n - (1/2)*Sum_{k=1..n} (sqrt(2)^A007814(k) + (-sqrt(2))^A007814(k)) = -Sum_{k=1..n} (-1)^k * 2^floor(k/2) * floor(n/2^k). - _Velin Yanev_, Dec 01 2016". A048702: "Conjecture: a(n) = 2^floor(log_2(n)) * Sum_{i=1..n} 1/(2^v_2(i))" and "Conjecture: a(n) = n*2^floor(log_2(n)) - Sum_{i=1..floor(log_2(n))} 2^(floor(log_2(n)) - i)*floor(n/(2^i))." + +Referees: I found no prior resolution. +- **OEIS entry.** A073642 (#121, Jul 05 2026) still lists "Conjecture ... Velin Yanev, Sep 09 2017", with no proof note or %E edit about it. +- **Related OEIS entries.** A011371, A007814, A029931, A115364, A198192 and A198193 contain no such identity, and no OEIS sequence holds the partial sums of A007814(k)^2. +- **Fried, "Proofs of some conjectures of Yanev" (2025).** This OEIS attachment covers only A000188, A001157 and A006519, and A073642 does not link to it. +- **Fried's OEIS papers.** None of these mentions A073642: arXiv:2410.07237, JIS 28 (2025) Art. 25.4.3, JIS 29 (2026) Art. 26.1.8, and arXiv:2607.24832. +- **Formalization datasets.** A073642 is not in google-deepmind/formal-conjectures, in Epoch's OEIS Open / LeanOpenProblems (arXiv:2608.11941), or in alphaproof-nexus-results. +- **Ingredients of the proof.** These are classical: Legendre's formula v2(n!) = n - s2(n), and Sum_{k<=n} f(v2(k)) = Sum_j (f(j)-f(j-1)) floor(n/2^j). The identity also follows from Gutkovskiy's 2019 g.f. in the entry. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a073642, + author = {{math0}}, + title = {{Yanev's identity for A073642 (sum of the positions of the 1-bits)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a073642}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a073642/paper.pdf b/results/oeis-a073642/paper.pdf new file mode 100644 index 0000000..0346178 Binary files /dev/null and b/results/oeis-a073642/paper.pdf differ diff --git a/results/oeis-a073642/paper.tex b/results/oeis-a073642/paper.tex new file mode 100644 index 0000000..7c4d847 --- /dev/null +++ b/results/oeis-a073642/paper.tex @@ -0,0 +1,337 @@ +% math0 manuscript template. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,apply,unfold,rw,exact_mod_cast,only}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, keepspaces=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 {→}{{$\to$}}1 + {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {∑}{{$\sum$}}1 {∈}{{$\in$}}1 {·}{{$\cdot$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {₂}{{$_2$}}1 {²}{{$^2$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +\raggedbottom +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\vt}{\nu_2} +\newcommand{\Bits}{\mathrm{I}} + +\title[Yanev's identity for OEIS A073642]{The sum of the positions of the 1-bits of $n$ equals $\tfrac12\bigl(3\,\nu_2(n!)-\sum_{k=1}^{n}\nu_2(k)^2\bigr)$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + +\begin{document} +\begin{abstract} +For $n\ge0$ let $a(n)$ be the sum of the exponents $i$ such that $2^i$ occurs in the binary expansion of $n$ (OEIS A073642). In 2017 V.~Yanev conjectured in that entry that $a(n)=\frac12\bigl(3\,\mathrm{A011371}(n)-\sum_{k=1}^{n}\mathrm{A007814}(k)^2\bigr)$ for $n>0$, where $\mathrm{A011371}(n)=n-s_2(n)=\nu_2(n!)$ and $\mathrm{A007814}(k)=\nu_2(k)$. +We prove this by induction on $n$ from the local identity $2a(n+1)+\nu_2(n+1)^2=2a(n)+3\,\nu_2(n+1)$, which in turn follows by induction over the parity of $n$ from the recursions $a(2k)=a(2k+1)=a(k)+s_2(k)$ and the identity $s_2(n+1)+\nu_2(n+1)=s_2(n)+1$. +The entry still lists the formula as a conjecture and we found no earlier proof, so we classify the result as new; it is, however, an elementary consequence of classical facts such as Legendre's formula, and we claim no new method. +The proof is verified in Lean~4 against a statement that math0 formalized from the OEIS entry; its definitions are checked by the kernel against the listed terms, and it was reviewed for fidelity and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +Every $n\in\N$ has a unique binary expansion $n=\sum_{i\in\Bits(n)}2^i$ with a finite set $\Bits(n)\subset\N$ of \emph{bit positions}. The OEIS entry A073642 \cite{A073642}, contributed by Benoit Cloitre in 2002, is the sequence +\[ + a(n)=\sum_{i\in\Bits(n)} i:\qquad 0,\,0,\,1,\,1,\,2,\,2,\,3,\,3,\,3,\,3,\,4,\,4,\,5,\,5,\,6,\,6,\,4,\,\dots\quad(n\ge0); +\] +for example $25=2^4+2^3+2^0$ gives $a(25)=7$. By a comment of A.~Ayyer in the entry, which refers to Macdonald \cite{Macdonald}, $2^{a(n)}$ is the number of partitions of $n$ whose dimension, given by the hook-length formula, is odd; the entry also links to Ayyer, Prasad and Spallone \cite{APS} on such partitions. The entry records the recursion $a(2n)=a(n)+s_2(n)$, $a(2n+1)=a(2n)$ (R.~Stephan, 2003), where $s_2(n)=|\Bits(n)|$ is the binary weight (A000120 \cite{A000120}), and the generating function $(1-x)^{-1}\sum_{k\ge1}k\,x^{2^k}/(1+x^{2^k})$ (I.~Gutkovskiy, 2019). + +On September~9, 2017, Velin Yanev added the following conjecture to the entry: for $n>0$, +\begin{equation}\label{eq:yanev} + a(n)=\frac{3\,\mathrm{A011371}(n)-\sum_{k=1}^{n}\mathrm{A007814}(k)^2}{2}, +\end{equation} +where $\mathrm{A011371}(n)=n-s_2(n)$ \cite{A011371}, which equals $\vt(n!)$ by Legendre's formula \cite{Legendre}, and $\mathrm{A007814}(k)=\vt(k)$ is the $2$-adic valuation \cite{A007814}. We prove \eqref{eq:yanev} (Theorem~\ref{thm:main}). + +\subsection*{Prior work and status} +We found no earlier proof. The math0 referees report that revision \#121 of A073642 (July~5, 2026) still lists \eqref{eq:yanev} as a conjecture, with no comment or edit about a proof; that the related entries A011371, A007814, A029931, A115364, A198192 and A198193 contain no such identity; and that no OEIS sequence lists the partial sums of $\mathrm{A007814}(k)^2$. S.~Fried \cite{Fried} proved several other conjectures of Yanev, in A000188, A001157 and A006519; his note treats only those three entries (we checked its text) and is not linked from A073642, and the referees found no mention of A073642 in Fried's other papers on OEIS conjectures. The statement is not in the formal-conjectures repository \cite{FC}, and the referees did not find it in other public collections of formalized OEIS conjectures. We therefore classify Theorem~\ref{thm:main} as a new result, in the sense that it is the first recorded proof of a conjecture listed as open. + +The identity is elementary, and we claim no new technique. Its ingredients are classical: Legendre's formula $\vt(n!)=n-s_2(n)$, and the evaluation of $\sum_{k\le n}f(\vt(k))$ through the counts $\lfloor n/2^j\rfloor$ of multiples of $2^j$. As the referees observed, the identity also follows from Gutkovskiy's generating function; see Remark~\ref{rem:closed}, which gives this second proof. The proof that we formalized (Section~\ref{sec:proof}) is a short induction: the step from $n$ to $n+1$ is the local identity $2a(n+1)+\vt(n+1)^2=2a(n)+3\,\vt(n+1)$ (Lemma~\ref{lem:key}). + +\section{Statement}\label{sec:statement} + +The entry A073642 \cite{A073642} reads in part (verbatim; \textsc{Formula} lists further formulas): +\begin{quote}\raggedright +\textsc{Name}: \texttt{Replace 2\char`\^k in the binary representation of n with k (i.e., if n = 2\char`\^b + 2\char`\^c + 2\char`\^d + ... then a(n) = b + c + d + ...).}\\[2pt] +\textsc{Formula}: \texttt{Conjecture: a(n) = (3*A011371(n) - Sum\char`\_\char`\{k=1..n\char`\}\ A007814(k)\char`\^2)/2 for n > 0. - Velin Yanev, Sep 09 2017} +\end{quote} +The offset is $0$. The two sequences in the conjecture are A011371 \cite{A011371} (offset $0$), ``a(n) = n minus (number of 1's in binary expansion of n). Also highest power of 2 dividing n!.'', and A007814 \cite{A007814} (offset $1$), ``Exponent of highest power of 2 dividing n, a.k.a. the binary carry sequence, the ruler sequence, or the 2-adic valuation of n.'' + +\begin{theorem}[Yanev's conjecture]\label{thm:main} +For every integer $n\ge1$, +\[ + \sum_{i\in\Bits(n)} i \;=\; \frac{3\,\bigl(n-s_2(n)\bigr)-\sum_{k=1}^{n}\vt(k)^2}{2}, +\] +where the right-hand side is computed in $\Q$. Equivalently, $2a(n)+\sum_{k=1}^{n}\vt(k)^2=3\,\vt(n!)$. +\end{theorem} + +For instance, $n=6$ gives $a(6)=1+2=3$, $n-s_2(n)=4$ and $\sum_{k=1}^{6}\vt(k)^2=0+1+0+4+0+1=6$, and indeed $(12-6)/2=3$. The identity also holds for $n=0$, where both sides vanish. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A073642.lean}, reviewed for fidelity, and frozen before the proof attempt (SHA-256 \texttt{cf003192\dots 51a12c}). Listing~\ref{lst:stmt} reproduces its three definitions, two of its lemmas and the statement, verbatim except that the copyright header, the \texttt{import Mathlib} line, docstrings and comments, the proofs, the helper lemma \decl{count_one_digits_two} and the four kernel-checked data lemmas are omitted. +\begin{lstlisting}[float=tp,caption={The frozen statement file \texttt{Math0/Statements/OEIS/A073642.lean} (excerpt).},label=lst:stmt] +namespace Math0.Statements.A073642 + +def a (n : ℕ) : ℕ := (Nat.bitIndices n).sum + +def A011371 (n : ℕ) : ℕ := n - (Nat.digits 2 n).count 1 + +def A007814 (n : ℕ) : ℕ := padicValNat 2 n + +theorem a_sum_two_pow (s : Finset ℕ) : a (∑ i ∈ s, 2 ^ i) = ∑ i ∈ s, i := by + -- (proof omitted) + +theorem A011371_eq_padicValNat_factorial (n : ℕ) : A011371 n = padicValNat 2 n.factorial := by + -- (proof omitted) + +def statement : Prop := + ∀ n : ℕ, 0 < n → + (a n : ℚ) = (3 * (A011371 n : ℚ) - ∑ k ∈ Finset.Icc 1 n, (A007814 k : ℚ) ^ 2) / 2 + +end Math0.Statements.A073642 +\end{lstlisting} + + +\emph{Encoding.} Mathlib's \texttt{Nat.bitIndices n} is the increasing list of the elements of $\Bits(n)$; it is defined by binary recursion, and Mathlib proves that $\sum_i 2^i$ over this list is $n$. So \decl{a} is $a$. The lemma \decl{a_sum_two_pow} states the OEIS definition literally: $a\bigl(\sum_{i\in s}2^i\bigr)=\sum_{i\in s}i$ for every finite set $s\subset\N$. \texttt{Nat.digits 2 n} is the list of binary digits of $n$, so \decl{A011371} is the primary OEIS definition of A011371; the truncated subtraction on $\N$ is harmless, as the number of $1$'s is at most $n$. The lemma \decl{A011371_eq_padicValNat_factorial} proves the entry's second description, $\mathrm{A011371}(n)=\vt(n!)$ (Lemma~\ref{lem:legendre} below). \decl{A007814} is \texttt{padicValNat 2}, which is $\vt$ on $k\ge1$ (and $0$ at $k=0$, a value that the statement never uses, since $k$ ranges over $\{1,\dots,n\}$). The statement quantifies over $n>0$, as the entry does, and evaluates the right-hand side in $\Q$, so neither the subtraction nor the division by $2$ is truncated; it thus also asserts that the right-hand side is the natural number $a(n)$. + +\emph{Checks against the OEIS.} Four lemmas of the statement file, all proved by kernel evaluation (\texttt{decide +kernel}), check the encoding: \decl{a_data} reproduces all $88$ listed terms $a(0),\dots,a(87)$; \decl{A011371_data} reproduces the $73$ listed terms of A011371 ($n=0,\dots,72$); \decl{A007814_data} reproduces the $111$ listed terms of A007814 ($k=1,\dots,111$); and \decl{rhs_data} checks that $3\,\mathrm{A011371}(n)-\sum_{k=1}^{n}\mathrm{A007814}(k)^2$, computed in $\mathbb{Z}$, is twice the listed $a(n)$ for $n=1,\dots,87$. The last lemma is a sanity check of the encoding and is not part of the statement. The fidelity reviewer compared the data with the OEIS by script, and a referee checked \eqref{eq:yanev} in exact rational arithmetic for all $n\le 200{,}000$. + +\section{Proof}\label{sec:proof} + +We follow the Lean proof; each lemma carries the names of the corresponding declarations. Throughout, $s(n)=s_2(n)=|\Bits(n)|$ (in Lean the private function \decl{L}, the length of \texttt{Nat.bitIndices n}) and $\nu=\vt$, with $\nu(0)=0$ as in Mathlib. + +\begin{lemma}[\decl{a_two_mul}, \decl{a_two_mul_add_one}, \decl{L_two_mul}, \decl{L_two_mul_add_one}]\label{lem:rec} +For every $k\in\N$, +\[ + a(2k)=a(2k+1)=a(k)+s(k),\qquad s(2k)=s(k),\qquad s(2k+1)=s(k)+1 . +\] +\end{lemma} + +\begin{proof} +From $k=\sum_{i\in\Bits(k)}2^i$ we get $2k=\sum_{i\in\Bits(k)}2^{i+1}$ and $2k+1=2^0+\sum_{i\in\Bits(k)}2^{i+1}$, so by uniqueness of the binary expansion $\Bits(2k)=\{i+1:i\in\Bits(k)\}$ and $\Bits(2k+1)=\{0\}\cup\{i+1:i\in\Bits(k)\}$, the union being disjoint. (In Lean these are the Mathlib simplification lemmas \texttt{Nat.bitIndices\_two\_mul} and \texttt{Nat.bitIndices\_two\_mul\_add\_one}, which hold by the recursive definition of \texttt{Nat.bitIndices}.) Hence $a(2k)=\sum_{i\in\Bits(k)}(i+1)=a(k)+s(k)$, the extra position $0$ adds nothing to $a(2k+1)$, and the sizes are $s(k)$ and $s(k)+1$. +\end{proof} + +This is Stephan's recursion recorded in the entry. + +\begin{lemma}[\decl{v2_odd}, \decl{v2_two_mul}]\label{lem:val} +For every $k\in\N$, $\nu(2k+1)=0$; and if $k\ge1$, then $\nu(2k)=\nu(k)+1$. +\end{lemma} + +\begin{proof} +$2\nmid 2k+1$. For $k\ge1$, $\vt$ is additive on products of nonzero numbers and $\vt(2)=1$ (Mathlib's \texttt{padicValNat.mul} and \texttt{padicValNat.self}). +\end{proof} + +\begin{lemma}[\decl{L_succ}]\label{lem:pop} +For every $n\in\N$, $s(n+1)+\nu(n+1)=s(n)+1$. +\end{lemma} + +\begin{proof} +By strong induction on $n$. If $n=2k$, then by Lemmas~\ref{lem:rec} and~\ref{lem:val}, $s(2k+1)+\nu(2k+1)=s(k)+1=s(2k)+1$. If $n=2k+1$, then $n+1=2(k+1)$ with $k+1\ge1$, so +\[ + s(n+1)+\nu(n+1)=s(k+1)+\nu(k+1)+1=s(k)+2=s(2k+1)+1, +\] +where the middle step is the induction hypothesis for $k= 1. Use the n x n board with rows and columns numbered 0..n-1, and call square (i,j) black when i+j is even. Two black squares are adjacent when they are diagonal neighbours, that is |di| = |dj| = 1. A path is a sequence of distinct black squares in which each square is adjacent to the next. Claim: the largest number of squares on such a path is a(n) = (n^2 - n + 2)/2 = 2m^2 - m + 1. In the frozen statement, a n is computed by exhaustive search, and the file's lemma a_spec shows it is the greatest path length. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A075855](https://oeis.org/A075855) as [`Math0.Statements.A075855.statement`](../../lean/Math0/Statements/OEIS/A075855.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A075855.lean`](../../lean/Math0/Frontier/OEIS/A075855.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A075855: "For n odd, a(n)=(n-1)^2/2+1. For n even, it is conjectured that a(n)=(n^2-n+2)/2 (it is easy to show this is a lower bound)." (entry by Jon Perry, Oct 15 2002; edited by Dean Hickerson, Oct 25 2002). Barker's 'Empirical g.f.' (Apr 12 2012) is equivalent. + +Referees: - USAMO 2008 Problem 3 (proposed by Gabriel Carroll): S_n = {(x,y) in Z^2 : |x|+|y+1/2| < n} cannot be partitioned into fewer than n unit-step paths. Under the isomorphism (i,j) -> ((i-j)/2, (i+j)/2 - m), S_m is the graph of black squares of the 2m x 2m board with diagonal adjacency. Adding the uncovered squares as one-point paths then gives the A075855 upper bound 2m^2 - m + 1 directly. See the AoPS wiki page 2008_USAMO_Problems/Problem_3 and Evan Chen's USAMO 2008 solution notes. +- Evan Chen, "Iberoamerican 2019/5" (Twitch Solves ISL Ep. 109), https://web.evanchen.cc/twitch/Ep109-Iberoamerican-2019-5-Solution.pdf. It uses USAMO 2008/3 as the claim that the "blue zigzags" (the diagonal-move graph on one colour class of a (2m)x(2m) vertex grid) need at least m paths. +- Lean formalization of USAMO 2008/3: compfiles, https://github.com/dwrensha/compfiles/blob/main/Compfiles/Usa2008P3.lean (problem usa2008_p3; no sorry). +- OEIS A075855 (Jon Perry, 2002; edited by Dean Hickerson) still states the even case as a conjecture. OEIS A249333 (Richard Stanley) cross-references it as "conjecturally the same as b(n+1) for A075855", which this result also settles. +- I found no explicit statement anywhere of the A075855 to USAMO 2008/3 link. The classification rests on this one-line reduction to a known theorem, not on a direct citation. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a075855, + author = {{math0}}, + title = {{The longest path on the black squares of an even chessboard has (n^2-n+2)/2 squares (A075855)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a075855}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a075855/paper.pdf b/results/oeis-a075855/paper.pdf new file mode 100644 index 0000000..bf3253d Binary files /dev/null and b/results/oeis-a075855/paper.pdf differ diff --git a/results/oeis-a075855/paper.tex b/results/oeis-a075855/paper.tex new file mode 100644 index 0000000..c4482c2 --- /dev/null +++ b/results/oeis-a075855/paper.tex @@ -0,0 +1,345 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,bif,rw,apply,ring}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {∈}{{$\in$}}1 {∉}{{$\notin$}}1 + {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {¬}{{$\neg$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 + {↔}{{$\leftrightarrow$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {≠}{{$\ne$}}1 {×}{{$\times$}}1 + {ˢ}{{$^{\mathrm{s}}$}}1 {α}{{$\alpha$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\Ib}[1]{[\,#1\,]} +\newcommand{\cM}{\mathcal{M}} +\newcommand{\cU}{\mathcal{U}} + +\title[Longest black-square paths on even chessboards (OEIS A075855)]{The longest path through diagonally adjacent black squares of a $2m\times 2m$ chessboard has $2m^2-m+1$ squares: the conjecture in OEIS A075855} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 19, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the largest number of black squares of an $n\times n$ chessboard with a black corner that a single path through adjacent black squares can cover; this is the sequence A075855 of the OEIS, contributed by Jon Perry in 2002, and the entry conjectures that $a(n)=(n^2-n+2)/2$ for even $n$. We give a complete proof: for $n=2m$ a weighting of the black squares shows that every path misses at least $m-1$ of the $2m^2$ black squares, and an explicit snake misses exactly $m-1$. +The upper bound is a direct consequence of Problem~3 of the 2008 USA Mathematical Olympiad (G.~Carroll), whose official solution uses the same weighting, so we classify the result as the first formal proof of a known result, although we found no source that states the connection with A075855. +The theorem is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before the proof attempt; in it $a(n)$ is computed by an exhaustive search that is proved to return the maximum, and is checked by the kernel against the first six listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +Colour an $n\times n$ chessboard so that a corner is black. Two black squares never share a side, so a path ``traveling only to adjacent black squares'' moves diagonally, one step at a time. The sequence A075855 of the OEIS \cite{A075855}, contributed by Jon Perry in 2002, lists the largest number $a(n)$ of black squares covered by such a path without repetition: $a(1),\dots,a(9)=1,2,3,7,9,16,19,29,33$. Its formula section states $a(n)=(n-1)^2/2+1$ for odd $n$ and conjectures $a(n)=(n^2-n+2)/2$ for even $n$, noting that this is easily seen to be a lower bound; an empirical generating function added by Colin Barker (2012) encodes the same two formulas. We prove the conjecture: $a(2m)=2m^2-m+1$ for $m\ge1$ (Theorem~\ref{thm:main}). The odd case is not considered here. + +\emph{Method.} Let $n=2m$, number rows $i$ and columns $j$ from $0$ and give the black square $(i,j)$ weight $-1$ if $i+j ℕ × ℕ → ℕ → ℕ) (fun _ _ => 0) + (fun _ ih d mask => lmax ((nbrs n d).filter fun c => !mask.testBit (idx n c)) + fun c => ih c (mask ||| 1 <<< idx n c) + 1) fuel +def cells (n : ℕ) : List (ℕ × ℕ) := + (List.range n ×ˢ List.range n).filter fun c => (c.1 + c.2) % 2 == 0 +def a (n : ℕ) : ℕ := lmax (cells n) fun c => dfs n (n * n) c (1 <<< idx n c) + 1 +theorem a_data : (List.range 6).map (fun i => a (i + 1)) = [1, 2, 3, 7, 9, 16] := by + decide +kernel +theorem a_spec (n : ℕ) : IsGreatest {k | ∃ l, IsBoardPath n l ∧ l.length = k} (a n) +theorem a_data_lower : 19 ≤ a 7 ∧ 29 ≤ a 8 ∧ 33 ≤ a 9 +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → Even n → a n = (n ^ 2 - n + 2) / 2 +end Math0.Statements.A075855 +\end{lstlisting} +Here \texttt{c.1} is the row and \texttt{c.2} the column; \decl{IsBlack}, \decl{Adj} and \decl{IsBoardPath} are the notions of Definition~\ref{def:board} (\texttt{Nodup}: no square repeated; \texttt{IsChain Adj}: consecutive squares adjacent). The function \decl{a} is an exhaustive depth-first search (\texttt{lmax l f} is the maximum of \texttt{f} over \texttt{l}, \texttt{nbrs n d} lists the diagonal neighbours of \texttt{d}, and the visited squares are the set bits of \texttt{mask}, square $(i,j)$ having bit $in+j$). Rather than relying on this program, the file proves \decl{a_spec}: \texttt{IsGreatest S x} means that $x\in S$ and $x$ is an upper bound of $S$, so \texttt{a n} is $a(n)$. In \decl{a_data} the kernel runs the search and reproduces the listed terms $a(1),\dots,a(6)$; for $n\ge7$ the number of paths is too large (already $17932$ directed paths for $n=6$), and \decl{a_data_lower} checks explicit paths of $19$, $29$ and $33$ squares for $n=7,8,9$. In \decl{statement}, $n^2-n+2=n(n-1)+2$ is even and $n\le n^2$, so the truncated subtraction and floor division of $\mathbb N$ agree with the rational formula, and $1\le n$ is the offset of the entry. Thus \decl{statement} is Theorem~\ref{thm:main}. + +\section{Proof}\label{sec:proof} + +We follow \path{lean/Math0/Frontier/OEIS/A075855.lean}, naming the corresponding declarations. Throughout, $n=2m$ with $m\ge1$, $\Ib{P}$ is $1$ if the statement $P$ holds and $0$ otherwise, and $c^+=(i+1,j+1)$ for a square $c=(i,j)$. + +\emph{Reduction.} Since $(2m)^2-2m+2=2(2m^2-m+1)$, Theorem~\ref{thm:main} says $a(2m)=2m^2-m+1$. By \decl{a_spec}, $a(2m)$ is the length of some path and bounds the length of every path, so it suffices to show that every path has length $L$ with $L+m\le 2m^2+1$ (Proposition~\ref{prop:upper}) and that some path has length $L$ with $L+m=2m^2+1$ (Lemma~\ref{lem:lower}). The proof of \decl{result} (Section~\ref{sec:lean}) is this reduction; the search \decl{a} is used only through \decl{a_spec} and is never evaluated. + +\subsection{Upper bound} +Let $\cM$ (\decl{mi}, the squares of weight $-1$) be the set of squares $(i,j)$ with $i+j ((x i : ℕ) : ℝ) +def statement : Prop := + ∀ n : ℕ, + {s : Finset (Fin n → Fin 5) | + s.card = 5 ∧ Collinear ℝ (toReal n '' (s : Set (Fin n → Fin 5)))}.ncard = a n +end Math0.Statements.A081200 +\end{lstlisting} +This encodes the first equality of Theorem~\ref{thm:main}; the second equality is Lemma~\ref{lem:aeq} below, which is also proved in the Lean file (\decl{a_eq}). The encoding is as follows. +\begin{itemize} +\item \decl{a} is the binomial transform named in the OEIS entry, in the OEIS convention $(m,b)\mapsto\bigl(n\mapsto\sum_{k=0}^n\binom nk m^{n-k}b(k)\bigr)$; it is not defined by a closed form. The lemma \decl{a_data} checks all $23$ listed terms $a(0),\dots,a(22)$ (from $0$ to $1953718431395986212$) by \texttt{decide +kernel}. +\item $G_n$ is \texttt{Fin n → Fin 5}, and the injective map \decl{toReal} sends a grid point to the point of $\R^n$ (\texttt{Fin n → ℝ}) with the same coordinates. Mathlib's \texttt{Collinear ℝ S} says that the vector span of $S$ has rank at most $1$; by \decl{collinear_iff_exists_forall_eq_smul_vadd} this is our notion of collinearity. +\item A ``collinear $5$-tuple'' is read as an unordered set, a \texttt{Finset} of $5$ grid points. The data force this reading: $a(1)=1$, whereas ordered $5$-tuples would give $120$; and $a(2)=12$ counts five rows, five columns and two diagonals. +\item The count is \texttt{Set.ncard} of a set of \texttt{Finset}s of a finite type; that set is finite, so \texttt{ncard} is its true cardinality. The statement covers all $n\in\N$, matching the offset $0$; for $n=0$ both sides are $0$. +\end{itemize} +Independent brute-force counts by the math0 referees gave $c(1),\dots,c(4)=1,12,109,888=a(1),\dots,a(4)$. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file (Section~\ref{sec:lean}); each step names its Lean declaration. We write $[5]=\{0,1,2,3,4\}$, so that $G_n=[5]^n$. + +\subsection{Words and their lines} +Let $A=\{0,1,2,3,4,\up,\dn\}$. In Lean, $A$ is \texttt{Fin 7}, with $5$ standing for $\up$ and $6$ for $\dn$. +The letters $0,\dots,4$ are \emph{constant} letters and $\up,\dn$ are \emph{arrows}. +For $c\in A$ and $t\in[5]$ define $\ev(c,t)\in[5]$ by +\[ + \ev(c,t)=c\ \ (c\in[5]),\qquad \ev(\up,t)=t,\qquad \ev(\dn,t)=4-t . +\] +Let $\rev\colon A\to A$ swap $\up$ and $\dn$ and fix the constant letters. For $u_0,u_4\in[5]$ let $\code(u_0,u_4)$ be $u_0$ if $u_0=u_4$; $\up$ if $u_0\ne u_4$ and $u_0=0$; and $\dn$ otherwise. +A \emph{word} is an element $w\in A^n$. It defines the points $p_w(t)\in G_n$ for $t\in[5]$, with coordinates $p_w(t)_i=\ev(w_i,t)$, and its \emph{line} +\[ + L(w)=\{p_w(t): t\in[5]\}\subseteq G_n . +\] +Let $\NC_n\subseteq A^n$ be the set of \emph{non-constant} words, those with at least one arrow, and write $\rev(w)$ for the word $(\rev(w_i))_i$. +In Lean (where \texttt{Fin.rev t} is $4-t$ and \texttt{rw7} is $\rev$): +\begin{lstlisting} +private def ev (c : Fin 7) (t : Fin 5) : Fin 5 := + if h : c.val < 5 then ⟨c.val, h⟩ else if c.val = 5 then t else Fin.rev t +private def rw7 (c : Fin 7) : Fin 7 := if c = 5 then 6 else if c = 6 then 5 else c +private def code (u0 u4 : Fin 5) : Fin 7 := + if u0 = u4 then ⟨u0.val, by omega⟩ else if u0.val = 0 then 5 else 6 +private def pt {n : ℕ} (w : Fin n → Fin 7) (t : Fin 5) : Fin n → Fin 5 := fun i => ev (w i) t +private def line {n : ℕ} (w : Fin n → Fin 7) : Finset (Fin n → Fin 5) := + Finset.univ.image (pt w) +private def T : Finset (Fin 7) := Finset.univ.filter (fun c => c.val < 5) +private def NC (n : ℕ) : Finset (Fin n → Fin 7) := Finset.univ \ Fintype.piFinset (fun _ => T) +\end{lstlisting} + +\subsection{Finite checks} +In Lean the next three lemmas (the first split into six declarations) are closed propositions quantified over \texttt{Fin 7} and \texttt{Fin 5}, each proved by \texttt{decide +kernel}: the kernel evaluates its \texttt{Decidable} instance by definitional unfolding to \texttt{true}. Unlike \texttt{native\_decide}, this runs no compiled code and adds no axiom. We also give proofs by hand. + +\begin{lemma}[\decl{ev_inj}, \decl{ev_const}, \decl{ev_invol}, \decl{ev_rw7}, \decl{rw7_ge}, \decl{ev_affine}]\label{lem:letters} +For all $c\in A$ and $t,u\in[5]$: +\begin{enumerate} +\item if $c$ is an arrow, then $t\mapsto\ev(c,t)$ is injective, and $\ev(c,\ev(c,t))=t$; +\item if $c$ is constant, then $\ev(c,t)=\ev(c,0)$; +\item $\ev(\rev c,t)=\ev(c,4-t)$, and if $c$ is an arrow, then $\rev c$ is an arrow other than $c$; +\item $\ev(c,t)=\ev(c,0)+t\,\bigl(\ev(c,1)-\ev(c,0)\bigr)$ in $\Z$. +\end{enumerate} +\end{lemma} + +\begin{proof} +The maps $t\mapsto t$ and $t\mapsto 4-t$ are involutions of $[5]$, which gives~(1); (2) and~(3) are immediate from the definitions. For~(4), the three kinds of letters give $\ev(c,\cdot)$ equal to $t\mapsto c$, $t\mapsto t$ and $t\mapsto 4-t$, all affine in $t$. +\end{proof} + +\begin{lemma}[\decl{H}]\label{lem:H} +Let $u_0,u_1,u_4,t,v\in[5]$ satisfy +\[ + u_4-u_0=4(u_1-u_0)\qquad\text{and}\qquad t\,(u_4-u_0)=4(v-u_0) +\] +in $\Z$. Then $\ev(\code(u_0,u_4),t)=v$. +\end{lemma} + +\begin{proof} +By the first equation $u_4-u_0$ is a multiple of $4$ in $[-4,4]$, so it is $0$, $4$ or $-4$. +If it is $0$, then $\code(u_0,u_4)=u_0$, and the second equation gives $v=u_0$. +If it is $4$, then $u_0=0$ and $u_4=4$, so $\code(u_0,u_4)=\up$, and the second equation gives $v=t$. +If it is $-4$, then $u_0=4\ne0$ and $u_4=0$, so $\code(u_0,u_4)=\dn$, and the second equation gives $v=4-t$. +In Lean the lemma is checked over all $5^5=3125$ tuples $(u_0,u_1,u_4,t,v)$. +\end{proof} + +\begin{lemma}[\decl{F}]\label{lem:F} +Let $a,a'$ be arrows and $b,b'\in A$, and suppose that $\ev(b,\ev(a,\ev(a',t)))=\ev(b',t)$ for all $t\in[5]$. If $a'=a$ then $b'=b$, and if $a'\ne a$ then $b'=\rev b$. +\end{lemma} + +\begin{proof} +The map $b\mapsto\ev(b,\cdot)$ from $A$ to functions $[5]\to[5]$ is injective: its values are the five distinct constant functions, the identity and $t\mapsto4-t$. +If $a'=a$, then $\ev(a,\ev(a,t))=t$ by Lemma~\ref{lem:letters}(1), so $\ev(b,\cdot)=\ev(b',\cdot)$ and $b'=b$. +If $a'\ne a$, then $\{a,a'\}=\{\up,\dn\}$ and $\ev(a,\ev(a',t))=4-t$, so $\ev(b',t)=\ev(b,4-t)=\ev(\rev b,t)$ by Lemma~\ref{lem:letters}(3), and $b'=\rev b$. +In Lean the lemma is checked over all $7^4=2401$ quadruples $(a,a',b,b')$, each with the five values of $t$. +\end{proof} + +\subsection{Lines of words} + +\begin{lemma}[\decl{pt_inj}, \decl{card_line}, \decl{line_collinear}]\label{lem:line} +For every word $w$, the set $L(w)$ is collinear. If $w\in\NC_n$, then $t\mapsto p_w(t)$ is injective, so $|L(w)|=5$. +\end{lemma} + +\begin{proof} +Let $v\in\R^n$ have coordinates $v_i=\ev(w_i,1)-\ev(w_i,0)$. By Lemma~\ref{lem:letters}(4), $p_w(t)=p_w(0)+t\,v$ for every $t$, so $L(w)$ lies on the line through $p_w(0)$ with direction $v$. +If $w_i$ is an arrow, then $p_w(t)_i=\ev(w_i,t)$ is injective in $t$ by Lemma~\ref{lem:letters}(1). +\end{proof} + +\begin{lemma}[\decl{line_rev}]\label{lem:rev} +For every word $w$, $L(\rev w)=L(w)$. +\end{lemma} + +\begin{proof} +By Lemma~\ref{lem:letters}(3), $p_{\rev w}(t)=p_w(4-t)$, and $t\mapsto4-t$ is a bijection of $[5]$. +\end{proof} + +\begin{lemma}[\decl{line_eq}]\label{lem:lineeq} +If $w,w'\in\NC_n$ and $L(w')=L(w)$, then $w'=w$ or $w'=\rev w$. +\end{lemma} + +\begin{proof} +Choose $i_0$ such that $w_{i_0}$ is an arrow. Let $t\in[5]$. Since $p_{w'}(t)\in L(w)$, there is $u\in[5]$ with $p_w(u)=p_{w'}(t)$. Comparing coordinate $i_0$ gives $\ev(w_{i_0},u)=\ev(w'_{i_0},t)$. Applying $\ev(w_{i_0},\cdot)$, an involution by Lemma~\ref{lem:letters}(1), gives $u=\sigma(t)$, where $\sigma(t)=\ev(w_{i_0},\ev(w'_{i_0},t))$. Hence +\begin{equation}\label{eq:sigma} + p_w(\sigma(t))=p_{w'}(t)\qquad\text{for all }t\in[5]. +\end{equation} +The letter $w'_{i_0}$ is an arrow. Otherwise $\ev(w'_{i_0},\cdot)$ would be constant by Lemma~\ref{lem:letters}(2), so $\sigma(1)=\sigma(0)$, and \eqref{eq:sigma} would give $p_{w'}(1)=p_{w'}(0)$, contradicting Lemma~\ref{lem:line}. +For each coordinate $j$, \eqref{eq:sigma} says $\ev(w_j,\ev(w_{i_0},\ev(w'_{i_0},t)))=\ev(w'_j,t)$ for all $t$. Lemma~\ref{lem:F} with $(a,a',b,b')=(w_{i_0},w'_{i_0},w_j,w'_j)$ gives $w'_j=w_j$ for all $j$ if $w'_{i_0}=w_{i_0}$, and $w'_j=\rev(w_j)$ for all $j$ otherwise. +\end{proof} + +\subsection{Collinear sets are lines} + +\begin{lemma}[\decl{P_of_collinear}]\label{lem:P} +Let $S\subseteq G_n$ be collinear. Then for all $x,y,z\in S$ and all coordinates $i,j$, +\begin{equation}\label{eq:P} + (x_i-z_i)(y_j-z_j)=(x_j-z_j)(y_i-z_i)\qquad\text{in }\Z . +\end{equation} +\end{lemma} + +\begin{proof} +Since $z\in S$ and $S$ is collinear, there is $v\in\R^n$ with $x=z+rv$ and $y=z+r'v$ for some $r,r'\in\R$ (in Lean, \decl{collinear_iff_of_mem}). Both sides of \eqref{eq:P} equal $rr'v_iv_j$. The identity holds in $\R$ between integers, hence in $\Z$. +\end{proof} + +\begin{proposition}[\decl{exists_line}]\label{prop:exists} +Every $S\in\mathcal C_n$ is of the form $L(w)$ with $w\in\NC_n$. +\end{proposition} + +\begin{proof} +Let $S\subseteq G_n$ be collinear with $|S|=5$. Choose distinct $y,z\in S$ and a coordinate $i_0$ with $y_{i_0}\ne z_{i_0}$. + +\emph{Step 1: the map $x\mapsto x_{i_0}$ is injective on $S$.} Suppose $x,x'\in S$, $x\ne x'$ and $x_{i_0}=x'_{i_0}$, and choose $j$ with $x_j\ne x'_j$. Apply \eqref{eq:P} to the points $(y,x',x)$ in place of $(x,y,z)$ and to the coordinates $(i_0,j)$: +\[ + (y_{i_0}-x_{i_0})(x'_j-x_j)=(y_j-x_j)(x'_{i_0}-x_{i_0})=0 . +\] +Since $x'_j\ne x_j$, we get $y_{i_0}=x_{i_0}$. The same argument with $z$ in place of $y$ gives $z_{i_0}=x_{i_0}$. Hence $y_{i_0}=z_{i_0}$, a contradiction. + +\emph{Step 2: the points $q_t$.} By Step~1 the image of $S$ under $x\mapsto x_{i_0}$ has $5$ elements, so it is all of $[5]$. For each $t\in[5]$ choose $q_t\in S$ with $(q_t)_{i_0}=t$. + +\emph{Step 3: the word.} Define $w\in A^n$ by $w_j=\code((q_0)_j,(q_4)_j)$. Fix $t$ and $j$, and put $u_0=(q_0)_j$, $u_1=(q_1)_j$, $u_4=(q_4)_j$ and $v=(q_t)_j$. +Applying \eqref{eq:P} to the points $(q_1,q_4,q_0)$ and the coordinates $(i_0,j)$ gives $1\cdot(u_4-u_0)=(u_1-u_0)\cdot4$. Applying it to $(q_t,q_4,q_0)$ gives $t\,(u_4-u_0)=(v-u_0)\cdot4$. +By Lemma~\ref{lem:H}, $\ev(w_j,t)=v$. Hence $p_w(t)=q_t$ for all $t$. +Moreover $w_{i_0}=\code(0,4)=\up$, so $w\in\NC_n$. + +\emph{Step 4: $L(w)=S$.} We have $L(w)=\{q_t: t\in[5]\}\subseteq S$. The $q_t$ are distinct, because $(q_t)_{i_0}=t$, so $|L(w)|=5=|S|$ and $L(w)=S$. +\end{proof} + +\subsection{Counting} + +\begin{lemma}[\decl{card_NC}, \decl{two_mul_card}]\label{lem:count} +$|\NC_n|=7^n-5^n$, and $2\,\bigl|\{L(w): w\in\NC_n\}\bigr|=|\NC_n|$. +\end{lemma} + +\begin{proof} +$\NC_n$ is the complement in $A^n$ of the $5^n$ words with only constant letters, so $|\NC_n|=7^n-5^n$. +For the second claim, partition $\NC_n$ into the fibres of $w\mapsto L(w)$. Let $w\in\NC_n$ and choose $i_0$ with $w_{i_0}$ an arrow. By Lemma~\ref{lem:letters}(3), $\rev w\in\NC_n$ and $(\rev w)_{i_0}\ne w_{i_0}$, so $\rev w\ne w$. By Lemmas~\ref{lem:rev} and~\ref{lem:lineeq}, the fibre of $L(w)$ is exactly $\{w,\rev w\}$, which has two elements. Summing over the fibres gives $|\NC_n|=2\,|\{L(w): w\in\NC_n\}|$. +\end{proof} + +\begin{lemma}[\decl{a_eq}]\label{lem:aeq} +$2a(n)+5^n=7^n$ for every $n\ge0$. +\end{lemma} + +\begin{proof} +By the binomial theorem, $7^n=(1+6)^n=\sum_{k=0}^n\binom nk 6^{n-k}$ and $5^n=(-1+6)^n=\sum_{k=0}^n\binom nk 6^{n-k}(-1)^k$. Since $2\,(k\bmod 2)=1-(-1)^k$, subtracting gives $7^n-5^n=\sum_{k=0}^n\binom nk6^{n-k}\cdot2\,(k\bmod2)=2a(n)$. In Lean this computation is done in $\Z$ and then cast back to $\N$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +By Proposition~\ref{prop:exists} and Lemma~\ref{lem:line}, $\mathcal C_n=\{L(w): w\in\NC_n\}$ (\decl{set_eq}). By Lemma~\ref{lem:count}, $2\,|\mathcal C_n|=7^n-5^n$, and by Lemma~\ref{lem:aeq}, $2a(n)=7^n-5^n$. Hence $|\mathcal C_n|=a(n)=(7^n-5^n)/2$. In Lean the last step is done by \texttt{omega} from $2\,|\mathcal C_n|=|\NC_n|$, $|\NC_n|=7^n-5^n$ (natural subtraction) and $2a(n)+5^n=7^n$. +\end{proof} + +\begin{remark}[other side lengths; not formalized]\label{rem:k} +For any side $k\ge2$ (grid $\{0,\dots,k-1\}^n$, letters $0,\dots,k-1,\up,\dn$ with $\ev(\dn,t)=k-1-t$, and $k$-element collinear subsets) the same argument gives $((k+2)^n-k^n)/2$ subsets; in Lemma~\ref{lem:H} the relation at $t=1$ forces $u_{k-1}-u_0\in\{0,\pm(k-1)\}$. As the $m$-th binomial transform of $0,1,0,1,\dots$ is $((m+1)^n-(m-1)^n)/2$, this settles, in the same reading, Hardin's comments in A081199 ($k=4$) and A081201 ($k=6$); like the case $k=5$, these follow from the classical count together with the step of Proposition~\ref{prop:exists}. Only $k=5$ is formalized here. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in the file \path{lean/Math0/Frontier/OEIS/A081200.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A081200.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. +The main declaration is the theorem \decl{Math0.Frontier.A081200.result}, whose type is \decl{statement}. It is proved by rewriting with \decl{set_eq} and \decl{Set.ncard_coe_finset} and combining \decl{two_mul_card}, \decl{card_NC} and \decl{a_eq} by \texttt{omega}; all auxiliary definitions and lemmas are \texttt{private}. The file ends with the command +\begin{lstlisting} +#math0_settles Math0.Frontier.A081200.result Math0.Statements.A081200.statement +\end{lstlisting} +The proof file contains no \texttt{sorry}, \texttt{admit}, \texttt{native\_decide}, \texttt{axiom} or \texttt{set\_option}. All finite checks (\decl{ev_inj}, \decl{ev_const}, \decl{ev_invol}, \decl{ev_rw7}, \decl{rw7_ge}, \decl{ev_affine}, \decl{H}, \decl{F}) are proved by \texttt{decide +kernel} within the default heartbeat limit. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which rejects \decl{sorryAx}, \decl{Lean.ofReduceBool} (from \texttt{native\_decide}) and custom axioms; and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata, with no unfolding. Here it reports: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A081200.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A081200.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A081200.result' proves 'Math0.Statements.A081200.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, both pinned in \path{lean/}. The repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The single file is checked by \texttt{lake env lean Math0/Frontier/OEIS/A081200.lean} in the directory \path{lean}, in under two minutes on our machine, including loading Mathlib. + +{\footnotesize +\begin{thebibliography}{99} + +\bibitem{CTK} +A.~Bogomolny, \emph{Tic-Tac-Toe in 3D}, Cut The Knot, \url{https://www.cut-the-knot.org/proofs/tictactoe.shtml} (excerpt from \cite{Ho}). + +\bibitem{ES} +P.~Erd\H{o}s and J.~L. Selfridge, \emph{On a combinatorial game}, J. Combin. Theory Ser.~A \textbf{14} (1973), no.~3, 298--301. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{GH} +S.~W. Golomb and A.~W. Hales, \emph{Hypercube tic-tac-toe}, in: R.~J. Nowakowski (ed.), \emph{More Games of No Chance}, MSRI Publications \textbf{42}, Cambridge University Press, 2002, 167--182. + +\bibitem{HJ} +A.~W. Hales and R.~I. Jewett, \emph{Regularity and positional games}, Trans. Amer. Math. Soc. \textbf{106} (1963), no.~2, 222--229. + +\bibitem{Ho} +R.~Honsberger, \emph{Mathematical Morsels}, Mathematical Association of America, 1978. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Pa} +O.~Patashnik, \emph{Qubic: $4\times4\times4$ tic-tac-toe}, Math. Mag. \textbf{53} (1980), no.~4, 202--216. + +\bibitem{A000035} +The OEIS Foundation Inc., \url{https://oeis.org/A000035}. + +\bibitem{A005059} +The OEIS Foundation Inc., \url{https://oeis.org/A005059}; comment by D.~W. Wilson (c.~1999). + +\bibitem{A081199} +The OEIS Foundation Inc., \url{https://oeis.org/A081199}; conjecture by R.~H. Hardin (May 24, 2010). + +\bibitem{A081200} +The OEIS Foundation Inc., \url{https://oeis.org/A081200}, entry by P.~Barry (March 11, 2003); conjecture by R.~Hardin (May 24, 2010); revision \#53, September 22, 2025. + +\bibitem{A081201} +The OEIS Foundation Inc., \url{https://oeis.org/A081201}; conjecture by R.~H. Hardin (May 23, 2010). + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a083020/README.md b/results/oeis-a083020/README.md new file mode 100644 index 0000000..c2dd449 --- /dev/null +++ b/results/oeis-a083020/README.md @@ -0,0 +1,45 @@ +# 3^(3^18) + 2 is divisible by 31^2, so Hilliard's squarefree conjecture (A083020) fails + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A083020 +**Date:** 2026-10-21 + +## Result + +The conjecture (Cino Hilliard, 2003, OEIS A083020) says that 3^(3^n) + 2 is squarefree for every n ≥ 0. We prove it is false: 31^2 = 961 divides 3^(3^18) + 2, so that number is not squarefree. + +## Assessment + +The refutation is a single explicit counterexample: 31^2 divides 3^(3^18)+2. To find it you reduce 3^n modulo φ(p^2) for small primes p and check whether 3^(3^n) ≡ -2 (mod p^2). This is a short modular-exponentiation search, and a few lines of code find (n, p) = (18, 31) at once. Checking it only needs Euler's theorem and the congruence 3^159 ≡ -2 (mod 961). No new idea or construction was needed, and the counterexample is a genuine failure of the conjecture as its author meant it, not a degenerate case. + +*Follows from:* Euler's theorem (3^930 ≡ 1 mod 31^2) plus a direct search for a prime p and an n with p^2 | 3^(3^n)+2 + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A083020](https://oeis.org/A083020) as [`def statement`](../../lean/Math0/Statements/OEIS/A083020.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A083020.lean`](../../lean/Math0/Frontier/OEIS/A083020.lean) refutes (proves the negation of) it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C A083020 Conjecture: These numbers have no repeating factors or 3^(3^n) + 2 is squarefree. (entry by Cino Hilliard, May 31 2003) + +Referees: I found no prior resolution. Sources checked: the OEIS A083020 entry (local mirror and https://raw.githubusercontent.com/oeis/oeisdata/main/seq/A083/A083020.seq, revision #20 of Jan 04 2026, which still states the conjecture with no refutation), cross-referenced/related entries A055777, A129290, A129291, A113913, A140331 and A061678, R. Stephan's "Prove or Disprove. 100 Conjectures from the OEIS" (arXiv:math/0409509, which does not contain A083020), and primepuzzles.net Conjecture 107 (unrelated). I also ran web searches for "3^(3^n)+2 squarefree", "Cino Hilliard 3^3^n+2 seqfan" and "3^{3^n}+2 squarefree mathoverflow/stackexchange". None of these reported a counterexample or a proof. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a083020, + author = {{math0}}, + title = {{3^(3^18) + 2 is divisible by 31^2, so Hilliard's squarefree conjecture (A083020) fails}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a083020}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a083020/paper.pdf b/results/oeis-a083020/paper.pdf new file mode 100644 index 0000000..d9f601d Binary files /dev/null and b/results/oeis-a083020/paper.pdf differ diff --git a/results/oeis-a083020/paper.tex b/results/oeis-a083020/paper.tex new file mode 100644 index 0000000..97dddf2 --- /dev/null +++ b/results/oeis-a083020/paper.tex @@ -0,0 +1,396 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{booktabs} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,unfold,rw,at}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 + {←}{{$\leftarrow$}}1 {≡}{{$\equiv$}}1 {∣}{{$\mid$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +\raggedbottom +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} + +\title[A counterexample to the squarefree conjecture in OEIS A083020]{The number $3^{3^{18}}+2$ is divisible by $31^2$: a counterexample to Hilliard's squarefree conjecture in OEIS A083020} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 21, 2026} + +\begin{document} +\begin{abstract} +The OEIS entry A083020 (Cino Hilliard, 2003) lists the prime factors of the numbers $N_n=3^{3^n}+2$, $n\ge0$, and conjectures that every $N_n$ is squarefree. +We show that $31^2$ divides $N_{18}$, a number with $184{,}846{,}550$ decimal digits, so the conjecture is false; the proof reduces the exponent $3^{18}$ modulo $\varphi(31^2)=930$ and then needs only the congruence $3^{159}\equiv-2\pmod{961}$. +We also show, without formalizing it, that $31^2\mid N_n$ exactly when $n\equiv18\pmod{60}$ and $29^2\mid N_n$ exactly when $n\equiv73\pmod{84}$, so infinitely many $N_n$ are not squarefree. +To our knowledge the counterexample is new: the OEIS entry still states the conjecture and we found no recorded resolution, although the argument is elementary. +The refutation is verified in Lean~4 with Mathlib against the frozen statement that math0 formalized from the OEIS entry; its definitions are checked by the kernel against the entry's data, and it was reviewed for fidelity before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +For $n\ge0$ let +\[ + N_n = 3^{3^n}+2 . +\] +The OEIS entry A083020 \cite{A083020}, submitted by Cino Hilliard on May~31, 2003, is the irregular triangle whose row $n$ lists the prime factors of $N_n$ in increasing order. +Its example section reads $N_0=5$, $N_1=29$, $N_2=5\cdot31\cdot127$, $N_3=11\cdot693236134999$; the listed terms continue with the six prime factors of $N_4=3^{81}+2$, the $116$-digit number $N_5=3^{243}+2$ (so the entry asserts that $N_5$ is prime), and the two smallest prime factors $5,31$ of the $348$-digit number $N_6$. +The comments contain the conjecture that all of these numbers are squarefree (Conjecture~\ref{conj} below). + +We show that the conjecture fails at $n=18$. + +\begin{theorem}\label{thm:main} +$31^2=961$ divides $N_{18}=3^{3^{18}}+2$. In particular $N_{18}$ is not squarefree. +\end{theorem} + +The number $N_{18}$ has $\lfloor 3^{18}\log_{10}3\rfloor+1=184{,}846{,}550$ decimal digits, so it is far out of reach of factorization; but divisibility by the fixed number $961$ only depends on the residue of $3^{3^{18}}$ modulo $961$, which Euler's theorem reduces to the residue of $3^{159}$ (Section~\ref{sec:proof}). +The same reduction describes all $n$ (Proposition~\ref{prop:all}): $961\mid N_n$ if and only if $n\equiv18\pmod{60}$, and $29^2=841$ divides $N_n$ if and only if $n\equiv73\pmod{84}$. +In particular infinitely many $N_n$ are not squarefree. + +\subsection*{Status and prior work} +The entry A083020 (revision \#20 of January~4, 2026, which is still the current revision in October~2026) still states the conjecture; its EXTENSIONS section records only a correction by T.~D.~Noe (November~15, 2006) and a clarified name with the terms $a(14),a(15)$ added by Sean A.~Irvine (January~4, 2026). +The math0 literature referees found no prior counterexample or proof. +They checked the OEIS entries on related numbers, namely A055777 ($3^{3^n}$) \cite{A055777}, A129290 ($3^{3^n}+1$) \cite{A129290}, A129291 \cite{A129291}, A113913 \cite{A113913}, A140331 \cite{A140331} and A061678 \cite{A061678}, none of which discusses the squarefreeness of $N_n$; Stephan's collection \emph{Prove or disprove.\ 100 conjectures from the OEIS} \cite{St04}, which does not contain A083020; and web searches of arXiv, MathOverflow, Mathematics Stack Exchange and the SeqFan mailing list. +The conjecture is not among the OEIS statements of the formal-conjectures repository \cite{FC} at the commit pinned by math0 (\texttt{c77fdd4}). +We therefore classify Theorem~\ref{thm:main} as a new result, with the caveat that the argument is elementary and the counterexample may have been noticed without being recorded. +We do not claim that $n=18$ is the least $n$ for which $N_n$ is not squarefree (Remark~\ref{rem:small}). + +\section{Statement}\label{sec:statement} + +\subsection*{The OEIS conjecture} +The COMMENTS section of A083020 contains the following sentence, verbatim: +\begin{quote} +\raggedright{\small\texttt{Conjecture: These numbers have no repeating factors or 3\^{}(3\^{}n) + 2 is squarefree.}} +\end{quote} +The comment carries no separate attribution; it is part of the original entry by Cino Hilliard, May~31, 2003. +The entry has offset $0$, so ``these numbers'' are $N_n$ for all $n\ge0$, and the two phrasings joined by ``or'' say the same thing: $N_n$ has no repeated prime factor. + +\begin{conjecture}[Hilliard]\label{conj} +For every integer $n\ge0$, the number $N_n=3^{3^n}+2$ is squarefree. +\end{conjecture} + +By Theorem~\ref{thm:main}, Conjecture~\ref{conj} is false. + +\subsection*{Lean statement} +The statement is the definition \decl{Math0.Statements.A083020.statement} in the math0 statement file \path{lean/Math0/Statements/OEIS/A083020.lean}, which was reviewed for fidelity and frozen (SHA-256 \texttt{d520c666\ldots ae473}) before any proof attempt. +The definitions that encode the triangle, and the statement, read verbatim (docstrings omitted; namespace \decl{Math0.Statements.A083020}): +\begin{lstlisting} +def N (n : ℕ) : ℕ := 3 ^ (3 ^ n) + 2 + +def row (n : ℕ) : List ℕ := Nat.primeFactorsList (N n) + +def a (i : ℕ) : ℕ := ((List.range (i + 1)).flatMap row).getD i 0 + +def statement : Prop := + ∀ n : ℕ, Squarefree (3 ^ (3 ^ n) + 2) +\end{lstlisting} +In Mathlib, \texttt{Squarefree r} is defined as $\forall x,\ x\cdot x\mid r\to\texttt{IsUnit}\ x$, and the only unit of $\N$ is $1$ (\decl{Nat.isUnit_iff}); so for a natural number $r$ it says that no square $x^2$ with $x\ge2$ divides $r$, which is the usual notion. +Thus \decl{statement} is Conjecture~\ref{conj}, quantified over all $n\in\N$ as the offset $0$ requires, with no extra hypotheses; it involves no subtraction or division in $\N$, and $N_n\ge5$ rules out degenerate cases. +The file also proves +\begin{lstlisting} +theorem statement_iff : statement ↔ ∀ n, (row n).Nodup +\end{lstlisting} +from Mathlib's \decl{Nat.squarefree_iff_nodup_primeFactorsList}; this is the ``no repeating factors'' phrasing: no prime occurs twice in row $n$. +We prove \texttt{¬ statement}. + +\subsection*{Encoding and check against the OEIS data} +Row $n$ of the triangle is \texttt{row n}, Mathlib's list of the prime factors of $N_n$ in increasing order with multiplicity. The listed rows contain no repeated primes, so listing distinct primes instead would give the same terms; the conjecture is stated directly about $N_n$ in any case. +The sequence itself is \texttt{a}, the triangle read by rows with offset $0$: \texttt{a i} is the entry at position $i$ of the concatenation of rows $0,\dots,i$, which has at least $i+1$ entries because every row is nonempty. + +The function \texttt{a} is computable, but evaluating it means factoring $N_n$ by trial division, so the statement file checks the data through certificates instead. +The lemma \decl{primeFactorsList_eq_of} says that a sorted list of primes with product $m$ is \texttt{Nat.primeFactorsList m} (uniqueness of factorization), and \decl{row_data} applies it to +\[ + 5,\quad 29,\quad 5\cdot31\cdot127,\quad 11\cdot 693236134999,\quad 5\cdot15679\cdot2372959\cdot5945531\cdot3312453269\cdot121032673159 +\] +for $n=0,\dots,4$. The products are checked by \texttt{norm\_num}, sortedness by \texttt{decide}, primes below $10^5$ by \texttt{norm\_num}, and the larger primes by Lucas certificates (Table~\ref{tab:lucas}). +Mathlib's \decl{lucas_primality} says that $p$ is prime if some $w$ satisfies $w^{p-1}\equiv1\pmod p$ and $w^{(p-1)/q}\not\equiv1\pmod p$ for every prime $q\mid p-1$. +The Boolean function \decl{lucasCheck} tests these conditions for a given $w$ and a list of primes with product $p-1$, computing powers with a square-and-multiply function \decl{powMod} that is proved equal to $w^e\bmod p$ for $e<2^{64}$; the theorem \decl{prime_of_lucasCheck} turns a successful check into a proof of primality, and each check is evaluated by \texttt{decide +kernel}. +The primes in the lists for $p-1$ are proved prime by \texttt{norm\_num} or by certificates of their own. +The theorem \decl{a_data} then states that $a(0),\dots,a(12)$ are the $13$ listed terms $5, 29, 5, 31, 127, 11, 693236134999, 5, 15679, 2372959, 5945531, 3312453269, 121032673159$. + +\begin{table}[h] +\centering\small +\begin{tabular}{rrl} +\toprule +$p$ & $w$ & factorization of $p-1$\\ +\midrule +$391151$ & $13$ & $2\cdot5^2\cdot7823$\\ +$693236134999$ & $7$ & $2\cdot3^2\cdot11\cdot8951\cdot391151$\\ +$2372959$ & $3$ & $2\cdot3^2\cdot7\cdot37\cdot509$\\ +$5945531$ & $2$ & $2\cdot5\cdot37\cdot16069$\\ +$22381441$ & $7$ & $2^7\cdot3\cdot5\cdot11657$\\ +$3312453269$ & $2$ & $2^2\cdot37\cdot22381441$\\ +$4317661$ & $6$ & $2^2\cdot3^2\cdot5\cdot17^2\cdot83$\\ +$20172112193$ & $3$ & $2^6\cdot73\cdot4317661$\\ +$121032673159$ & $3$ & $2\cdot3\cdot20172112193$\\ +\bottomrule +\end{tabular} +\caption{The Lucas certificates in the statement file: for each $p$, the witness $w$ and the prime factors of $p-1$.} +\label{tab:lucas} +\end{table} + +The remaining listed terms are $a(13)$, a $116$-digit number, and $a(14)=5$, $a(15)=31$. +The theorem \decl{N5_data} checks that $a(13)$ as listed equals $N_5=3^{243}+2$, and \decl{row6_data} checks that row $6$ begins with $5,31$, by computing the two smallest prime factors of $N_6$. +The primality of $N_5$ is not proved in Lean (SymPy's primality test reports it prime), so $a(13),a(14),a(15)$ sit at the listed positions exactly when $N_5$ is prime, and these positions are not checked as indices. +All of these checks live in the statement file; the refutation below does not depend on them. + +\section{Proof}\label{sec:proof} + +The proof follows the declarations of the Lean file: the private lemmas \decl{pow_930}, \decl{split_exp} and \decl{sq_dvd}, and the theorem \decl{result}. +Congruences are in $\N$ (\texttt{Nat.ModEq}). + +\begin{lemma}[\decl{pow_930}]\label{lem:euler} +$3^{930}\equiv1\pmod{961}$. +\end{lemma} + +\begin{proof} +Since $31$ is prime, $\varphi(31^2)=31\cdot30=930$, and $\gcd(3,961)=1$, so this is Euler's theorem. +The Lean proof does not use Euler's theorem: it unfolds the congruence to $3^{930}\bmod 961=1\bmod 961$ and checks this equation by \texttt{decide +kernel}, which makes the kernel evaluate both sides; $3^{930}$ has $1475$ binary digits. +\end{proof} + +\begin{lemma}[\decl{split_exp}]\label{lem:split} +$3^{18}=930\cdot416581+159$, and hence $3^{3^{18}}=\bigl(3^{930}\bigr)^{416581}\cdot3^{159}$. +\end{lemma} + +\begin{proof} +$3^{18}=387420489$ and $930\cdot416581=387420330$. +The second claim follows from the first by the laws $(x^b)^c=x^{bc}$ and $x^bx^c=x^{b+c}$. +In Lean, the right-hand side is rewritten with these two laws (\decl{pow_mul}, \decl{pow_add}) into $3^{930\cdot416581+159}$, and \texttt{norm\_num} checks that the two exponents agree; the number $3^{3^{18}}$ is never evaluated. +\end{proof} + +\begin{lemma}[\decl{sq_dvd}]\label{lem:dvd} +$31\cdot31$ divides $3^{3^{18}}+2$. +\end{lemma} + +\begin{proof} +Raising Lemma~\ref{lem:euler} to the power $416581$, multiplying by $3^{159}$ on the right and adding $2$ gives +\[ + \bigl(3^{930}\bigr)^{416581}\cdot3^{159}+2\equiv 1^{416581}\cdot3^{159}+2\pmod{961} +\] +(\decl{Nat.ModEq.pow}, \decl{Nat.ModEq.mul_right}, \decl{Nat.ModEq.add_right}). +Next, $3^{159}\equiv959\equiv-2\pmod{961}$, so $1^{416581}\cdot 3^{159}+2\equiv961\equiv0\pmod{961}$. +To check the residue by hand: the successive squares $3^{2^k}\bmod961$ for $k=0,\dots,7$ are +\[ + 3,\ 9,\ 81,\ 795,\ 648,\ 908,\ 887,\ 671, +\] +and $159=2^7+2^4+2^3+2^2+2+1$, so $3^{159}\equiv3\cdot9\cdot81\cdot795\cdot648\cdot671$; the partial products reduce to $27,\ 265,\ 216,\ 623,\ 959$ modulo $961$. +In Lean, the congruence $1^{416581}\cdot3^{159}+2\equiv0\pmod{961}$ is checked by \texttt{decide +kernel}. +By transitivity and Lemma~\ref{lem:split}, $3^{3^{18}}+2\equiv0\pmod{961}$, that is, $961$ divides $3^{3^{18}}+2$ (\decl{Nat.modEq_zero_iff_dvd}). +In Lean the goal $31\cdot31\mid\dots$ is first rewritten with Lemma~\ref{lem:split}, and $31\cdot31$ is identified with $961$ by evaluating the product of the two literals. +\end{proof} + +As a consistency check, which the proof does not use: modulo $31$ we have $3^{30}\equiv1$ and $3^{18}\equiv9\pmod{30}$, so $3^{3^{18}}\equiv3^9\equiv29\equiv-2\pmod{31}$, as Lemma~\ref{lem:dvd} requires. + +\begin{proof}[Proof of Theorem~\ref{thm:main} and of \texttt{¬ statement} (\decl{result})] +Lemma~\ref{lem:dvd} is the first claim. +Suppose that \decl{statement} holds. Then $N_{18}$ is squarefree, so by the definition of \texttt{Squarefree}, applied to $x=31$ and Lemma~\ref{lem:dvd}, $31$ is a unit of $\N$. +By \decl{Nat.isUnit_iff} this means $31=1$, which is false (\texttt{omega}). +\end{proof} + +\subsection*{All \texorpdfstring{$n$}{n}, and small primes} +The following is not part of the formal proof. + +\begin{proposition}\label{prop:all} +For $n\ge0$: $961\mid N_n$ if and only if $n\equiv18\pmod{60}$, and $841\mid N_n$ if and only if $n\equiv73\pmod{84}$. +In particular infinitely many $N_n$ are not squarefree. +\end{proposition} + +\begin{proof} +Let $x_n=3^{3^n}\bmod961$, so that $x_{n+1}\equiv x_n^3\pmod{961}$, and $961\mid N_n$ if and only if $x_n=959$. +By Lemma~\ref{lem:euler}, $x_n$ depends only on $3^n\bmod930$. +Now $930=3\cdot310$ with $\gcd(3,310)=1$. For $n\ge1$ we have $3^n\equiv0\pmod 3$, and $3^n\bmod310$ is periodic in $n$ with period the order of $3$ modulo $310=2\cdot5\cdot31$, which is $\operatorname{lcm}(1,4,30)=60$. +By the Chinese remainder theorem, $3^n\bmod930$, and hence $x_n$, depends only on $n\bmod60$ for $n\ge1$. +Computing $x_1,\dots,x_{60}$ by repeated cubing modulo $961$ gives $x_n=959$ only for $n=18$, and $x_0=3$. +This proves the first claim. +For $841=29^2$ we have $\varphi(841)=812=2^2\cdot7\cdot29$, which is prime to $3$, so $3^n\bmod812$ is purely periodic in $n$ with period the order of $3$ modulo $812$, which is $\operatorname{lcm}(2,6,28)=84$. Hence $y_n=3^{3^n}\bmod841$ is periodic with period dividing $84$, and computing $y_0,\dots,y_{83}$ gives $y_n=839$ only for $n=73$. +\end{proof} + +\begin{remark}[Smaller $n$]\label{rem:small} +For $n\le4$ the factorizations in \decl{row_data} show that $N_n$ is squarefree, and $N_5$ is squarefree if it is prime, as the entry asserts. +For $6\le n\le17$ we do not know whether $N_n$ is squarefree: these numbers have between $348$ and about $6.2\times10^7$ decimal digits, and none of them is completely factored (for $N_6$ only the factors $5$ and $31$ and a composite cofactor are known). +A computer search (not part of the formal proof) that computes $3^{3^n}\bmod p^2$ by repeated cubing, for every prime $p<10^8$ and every $n\le18$, finds $p^2\mid N_n$ only for $(n,p)=(18,31)$. +So $n=18$ is the least $n$ for which $N_n$ is divisible by the square of a prime below $10^8$, but we do not know whether it is the least $n$ for which $N_n$ is not squarefree. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in the file \path{lean/Math0/Frontier/OEIS/A083020.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. +It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A083020.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. +The main declaration is \decl{Math0.Frontier.A083020.result}, of type \texttt{¬ Math0.Statements.A083020.statement}; the auxiliary lemmas \decl{pow_930}, \decl{split_exp} and \decl{sq_dvd} are private. +The proof file reads, verbatim except for the license header, the imports, the docstrings and blank lines: +\begin{lstlisting} +namespace Math0.Frontier.A083020 +open Math0.Statements.A083020 +private theorem pow_930 : 3 ^ 930 ≡ 1 [MOD 961] := by + unfold Nat.ModEq + decide +kernel +private theorem split_exp : (3 : ℕ) ^ (3 ^ 18) = (3 ^ 930) ^ 416581 * 3 ^ 159 := by + rw [← pow_mul, ← pow_add] + norm_num +private theorem sq_dvd : 31 * 31 ∣ 3 ^ (3 ^ 18) + 2 := by + have h : (3 ^ 930) ^ 416581 * 3 ^ 159 + 2 ≡ 1 ^ 416581 * 3 ^ 159 + 2 [MOD 961] := + ((pow_930.pow 416581).mul_right _).add_right _ + have h0 : 1 ^ 416581 * 3 ^ 159 + 2 ≡ 0 [MOD 961] := by + unfold Nat.ModEq + decide +kernel + rw [split_exp] + exact Nat.modEq_zero_iff_dvd.1 (h.trans h0) +theorem result : ¬ statement := by + intro h + have hu : IsUnit (31 : ℕ) := h 18 31 sq_dvd + rw [Nat.isUnit_iff] at hu + omega +end Math0.Frontier.A083020 +#math0_settles Math0.Frontier.A083020.result Math0.Statements.A083020.statement +\end{lstlisting} +The file uses no \texttt{sorry}, \texttt{native\_decide}, \texttt{set\_option} or macros. + +\subsection*{How the kernel checks the computations} +The tactic \texttt{decide +kernel} proves a decidable proposition by asking the kernel to reduce its decision procedure to \texttt{true}. +Lean's kernel evaluates arithmetic on natural number literals (addition, multiplication, powers, division and remainder, among others) with arbitrary-precision integer arithmetic, so the checks $3^{930}\bmod961=1$ and $(1^{416581}\cdot3^{159}+2)\bmod961=0$ are immediate; unlike \texttt{native\_decide}, this adds no axiom. +The only large exponent is handled symbolically: the proof manipulates \texttt{Nat.ModEq} terms whose sides are never evaluated, and Lemma~\ref{lem:split} only compares the exponents $3^{18}$ and $930\cdot416581+159$. +The data checks in the statement file (Section~\ref{sec:statement}) use \texttt{decide +kernel} in the same way, on the Lucas certificates. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) both \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which rejects \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} introduced by \texttt{native\_decide}, and custom axioms; and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata annotations, with no unfolding. +Running \texttt{lake env lean Math0/Frontier/OEIS/A083020.lean} in the directory \path{lean} prints\par\nobreak\noindent +\begin{minipage}{\linewidth} +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A083020.statement' depends on axioms [propext] +math0 audit: 'Math0.Frontier.A083020.result' depends on axioms [Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A083020.result' refutes 'Math0.Statements.A083020.statement' +\end{lstlisting} +\end{minipage} +so \decl{result} proves the negation of the statement and depends only on \decl{propext} and \decl{Quot.sound}, a subset of the three permitted axioms. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. +To check this result alone, run \texttt{lake build Math0.Statements.OEIS.A083020} and then \texttt{lake env lean Math0/Frontier/OEIS/A083020.lean} in the directory \path{lean}; the kernel computations take a few seconds, and most of the running time is spent loading Mathlib. + +{\small +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A055777} +The OEIS Foundation Inc., \url{https://oeis.org/A055777} ($3^{3^n}$), entry by H.~Bottomley, Jul.~12, 2000. + +\bibitem{A061678} +The OEIS Foundation Inc., \url{https://oeis.org/A061678} (continued fraction for $\sum_{k\ge0}3^{-3^k}$), entry by J.~Earls, Jun.~23, 2001. + +\bibitem{A083020} +The OEIS Foundation Inc., \url{https://oeis.org/A083020} (prime factors of $3^{3^n}+2$), entry by C.~Hilliard, May~31, 2003; revision \#20, Jan.~4, 2026. + +\bibitem{A113913} +The OEIS Foundation Inc., \url{https://oeis.org/A113913} (number of distinct prime factors of $3^{3^n}+1$), entry by J.~Coveiro, Jan.~29, 2006. + +\bibitem{A129290} +The OEIS Foundation Inc., \url{https://oeis.org/A129290} (base-$3$ Fermat numbers $3^{3^n}+1$), entry by A.~Adamchuk, Apr.~8, 2007. + +\bibitem{A129291} +The OEIS Foundation Inc., \url{https://oeis.org/A129291} ($1-3^{3^n}+9^{3^n}$), entry by A.~Adamchuk, Apr.~8, 2007. + +\bibitem{A140331} +The OEIS Foundation Inc., \url{https://oeis.org/A140331} (smallest $k$ such that $3^{3^n}-k$ is prime), entry by J.~Vos Post, May~26, 2008. + +\bibitem{St04} +R.~Stephan, \emph{Prove or disprove. 100 conjectures from the OEIS}, arXiv:math/0409509, 2004. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a086004/README.md b/results/oeis-a086004/README.md new file mode 100644 index 0000000..a503e11 --- /dev/null +++ b/results/oeis-a086004/README.md @@ -0,0 +1,45 @@ +# There are no 5-Rotation Cycle Primes (A086004, Conjecture 2) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Sequences and series +**Source problem:** OEIS A086004 +**Date:** 2026-10-19 + +## Result + +Let rot be the rotation of A086002. For a number n with d decimal digits, rot(n) swaps the block of the first floor(d/2) digits with the block of the last floor(d/2) digits; when d is odd, the centre digit stays where it is. Let f(n) = n + rot(n). Then no prime p has f(p), f^2(p), f^3(p), f^4(p) and f^5(p) all prime. + +## Assessment + +The proof is a one-page argument about decimal digits. It reuses Mathar's factorization for even digit counts and Wu's setup from A261458, where the first four iterates must keep the same odd number of digits. On top of that it makes one simple observation: the centre digit M becomes 2M mod 10, and if M is at most 4 then f(n) is fixed by the rotation, so the next iterate is 2f(n) and cannot be prime. A five-case check on the centre digit (it must run 9, 8, 6, 2) then finishes the proof. Wu stopped at six steps in 2015, but the extra step uses a short and standard idea that a competent mathematician working from the material in the entry and its cross-references would find quickly. + +*Follows from:* Mathar's factorization f(n) = (10^k+1)(a+b) for even digit counts (A086004 comment) and Wu's no-carry, fixed-digit-length argument in A261458, together with the elementary block decomposition f(n) = 10^(m+1)S + 2M*10^m + S + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A086004](https://oeis.org/A086004) as [`Math0.Statements.A086004.statement`](../../lean/Math0/Statements/OEIS/A086004.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A086004.lean`](../../lean/Math0/Frontier/OEIS/A086004.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture 2: There are no 5-Rotation Cycle Primes." (A086004, entry by _Chuck Seggelin_, Jul 07 2003. Conjecture 1 was settled by R. J. Mathar in 2009. Chai Wah Wu added on Aug 20 2015 that 4-rotation cycle primes exist (A261458), and in A261458 he proved there are none surviving 6 applications.) + +Referees: I found no prior resolution. OEIS A086004 (Seggelin 2003, last edited Jun 2025) still lists Conjecture 2 as open. OEIS A261458 (Chai Wah Wu, Aug 2015) proves the weaker statement that no chain of 6 steps exists, using a leading-digit/carry argument, and gives 4-step examples such as 10010905789. Mathar's 2009 comment on A086004 proves Conjecture 1 (even digit counts) only. Web searches (OEIS-indexed pages, arXiv, StackExchange-style queries, primepuzzles) found nothing on the 5-step case. The SeqFan archive could not be reached from here, so it was not checked. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a086004, + author = {{math0}}, + title = {{There are no 5-Rotation Cycle Primes (A086004, Conjecture 2)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a086004}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a086004/paper.pdf b/results/oeis-a086004/paper.pdf new file mode 100644 index 0000000..c3e0d67 Binary files /dev/null and b/results/oeis-a086004/paper.pdf differ diff --git a/results/oeis-a086004/paper.tex b/results/oeis-a086004/paper.tex new file mode 100644 index 0000000..203f3f1 --- /dev/null +++ b/results/oeis-a086004/paper.tex @@ -0,0 +1,324 @@ +% math0 manuscript template. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, keepspaces=true, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {→}{{$\to$}}1 + {≤}{{$\le$}}1 {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\DeclareMathOperator{\rot}{rot} +\newcommand{\nd}{D} + +\title[No prime survives five rotate-and-add steps]{No prime survives five rotate-and-add steps: a proof of Seggelin's Conjecture~2 in OEIS A086004} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 19, 2026} + +\begin{document} +\begin{abstract} +Let $\rot(n)$ be the decimal rotation of OEIS A086002, which exchanges the first and the last $\lfloor d/2\rfloor$ digits of a $d$-digit number $n$ and keeps the centre digit in place when $d$ is odd, and let $f(n)=n+\rot(n)$. +We prove that there is no prime $p$ for which $f(p),f^2(p),f^3(p),f^4(p),f^5(p)$ are all prime; this is Conjecture~2 of Chuck Seggelin (2003) in OEIS A086004, and since primes with four prime iterates exist (A261458), five is the least length with this property. +The proof is elementary: besides R.~J. Mathar's factorization for even digit counts, it uses that while the number of digits stays the same the centre digit $M$ of $n$ becomes the centre digit $2M\bmod 10$ of $f(n)$, and that if moreover $M\le4$, then $f(n)$ is a fixed point of $\rot$, so that the following iterate $f(f(n))=2f(n)$ is not prime. +To our knowledge the result is new; C.~W. Wu had proved in 2015 that no prime has six consecutive prime iterates. +The proof is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the listed terms below $10^8$ and which was reviewed for fidelity and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +For a positive integer $n$ with $d$ decimal digits, the \emph{rotation} $\rot(n)$ of OEIS A086002 \cite{A086002} exchanges the block of the first $\lfloor d/2\rfloor$ digits with the block of the last $\lfloor d/2\rfloor$ digits; if $d$ is odd, the centre digit stays where it is. For example $\rot(1234)=3412$ and $\rot(12345)=45312$. Let $f(n)=n+\rot(n)$ (\emph{rotate-and-add}) and let $f^j$ be its $j$-th iterate. On July~7, 2003, Chuck Seggelin contributed A086002, A086003 \cite{A086003} and A086004 \cite{A086004}, the primes $p$ such that $f^j(p)$ is prime for all $1\le j\le k$, with $k=1$, $2$ and $3$ respectively; for instance $12917\mapsto30829\mapsto60659\mapsto120319$ are all prime. + +The entry A086004 records two conjectures of Seggelin. Conjecture~1, that a prime with an even number of digits added to its rotation is never prime, was proved by R.~J. Mathar in a comment of September~17, 2009: if $n=10^ka+b$ with $0\le b<10^k$ has $2k$ digits, then $\rot(n)=10^kb+a$ and $f(n)=(10^k+1)(a+b)$. Conjecture~2 says that there are no \emph{5-Rotation Cycle Primes}, where a $k$-Rotation Cycle Prime is a prime that remains prime after each of the first $k$ applications of $f$ (Section~\ref{sec:statement} explains this reading). On August~20, 2015, Chai Wah Wu added that 4-Rotation Cycle Primes exist; they are listed in A261458 \cite{A261458}, whose first term $10010905789$ has the prime iterates $15800815799$, $31600631599$, $63200263199$, $126399526399$, while the fifth iterate $652798652798$ is even. + +\subsection*{Prior work} +In a comment in A261458 dated August~21, 2015, Wu proved that there are no 6-Rotation Cycle Primes. By Mathar's factorization, all members of such a chain except the last have the same odd number $2m+1$ of digits. Wu follows the first and the $(m+2)$-th digit: without a carry both are at least the sum of the previous pair, so from at least $(1,0)$ one reaches at least $(1,1),(2,2),(4,4),(8,8)$, and a carry, which adds a digit, is forced by the fifth application. This rules out chains of six applications but not of five, for which only the first four applications must keep the number of digits. Wu also observed in A086002 (August~19, 2015) that a $(2m+1)$-digit term of A086002 has an even $m$-th digit, since otherwise $f(p)$ is even. + +The math0 referees found no earlier resolution of Conjecture~2. The entry A086004 (revision \#20, June~8, 2025) still lists it as a conjecture, and searches of OEIS-indexed pages, arXiv, question-and-answer sites and the Prime Puzzles site found nothing on the five-step case; the archive of the SeqFan mailing list could not be reached and was not checked. The conjecture is not among the statements of the formal-conjectures repository \cite{FC} (checked at commit \texttt{c77fdd4}). With this caveat, we believe the result is new. + +We prove Conjecture~2 (Theorem~\ref{thm:main}); as 4-Rotation Cycle Primes exist, $5$ is the least $k$ for which there are no $k$-Rotation Cycle Primes. The argument tracks the centre digit. While the number of digits stays $2m+1$, the centre digit $M$ of $n$ becomes $2M\bmod10$ in $f(n)$, and if $M\le4$, then $f(n)$ is fixed by $\rot$, so $f(f(n))=2f(n)$ is twice a prime. Together with Mathar's factorization this forces the centre digits along a chain of primes to be $9,8,6,2$, which leaves room for at most four prime iterates. + +\section{Statement}\label{sec:statement} + +The entry A086004 \cite{A086004}, by Chuck Seggelin, July~7, 2003, condensed by R.~J. Mathar, September~17, 2009, reads in part (verbatim): +\begin{quote}\raggedright +\textsc{Name}: Primes which remain prime after one and after two and after three applications of the rotate-and-add operation of A086002.\\[2pt] +\textsc{Comments}: [\dots] Note: Have not yet found any 4-Rotation Cycle Primes.\\ +Conjecture 1: Rotation and addition of primes with even numbers of digits never yields a prime.\\ +Conjecture 2: There are no 5-Rotation Cycle Primes.\\ +{[}Conjecture 1 is true because rotation for even numbers of the form 10\^{}k*a+b yields 10\^{}k*b+a, so rotation-and-add yields (10\^{}k+1)*(a+b), which obviously contains a divisor A000533. RJM, Sep 17 2009{]}\\ +4-Rotation Cycle Primes exist and are listed in A261458. - Chai Wah Wu, Aug 20 2015 +\end{quote} +The rotation is defined in A086002 \cite{A086002} (verbatim): ``Let rotation rot(k) of a number k be defined by swapping the blocks of the first [d/2] and of the last [d/2] digits of k, where d=A055642(k). If the number of digits in k is odd, the center digit remains untouched during rotation.'' Here A055642 \cite{A055642} is the number of decimal digits. + +\begin{definition}\label{def:rot} +For $n\in\N$ let $\nd(n)$ be the number of decimal digits of $n$, so that $10^{\nd(n)-1}\le n<10^{\nd(n)}$ for $n\ge1$, and $\nd(0)=0$. Put $l=\lfloor \nd(n)/2\rfloor$, $h=\nd(n)-l=\lceil \nd(n)/2\rceil$ and +\[ + \rot(n)=(n\bmod 10^{l})\cdot10^{h}+\bigl(\lfloor n/10^{l}\rfloor\bmod 10^{h-l}\bigr)\cdot10^{l}+\lfloor n/10^{h}\rfloor . +\] +Let $f(n)=n+\rot(n)$, and let $f^j$ be the $j$-th iterate of $f$ ($f^0=\mathrm{id}$, $f^{j+1}=f\circ f^j$). For $k\in\N$, a \emph{$k$-Rotation Cycle Prime} is a prime $p$ such that $f^j(p)$ is prime for every $j$ with $1\le j\le k$. +\end{definition} + +If $\nd(n)=2k$, then $l=h=k$, the middle term vanishes (any number modulo $10^0=1$ is $0$), and $\rot(n)=(n\bmod10^k)10^k+\lfloor n/10^k\rfloor$: the last $k$ digits followed by the first $k$ digits. If $\nd(n)=2m+1$, then $l=m$, $h=m+1$, and the middle term is $(\lfloor n/10^m\rfloor\bmod10)\cdot10^m$, the centre digit kept in place. A moved block may start with zeros, which are then dropped, as in the Mathematica program of the entries: $\rot(10203)=3210$. The formula is R.~J. Mathar's Maple program in A086002, and it gives $\rot(0)=0$ although A055642 assigns one digit to $0$; the value at $0$ plays no role here. + +The reading of ``$k$-Rotation'' is fixed by the entries themselves: A086004 lists the primes that survive three applications of $f$, and its note ``Have not yet found any 4-Rotation Cycle Primes'' refers to a fourth application; Wu identifies the 4-Rotation Cycle Primes with A261458, the ``Primes which remain prime after one, two, three and four applications of the rotate-and-add operation of A086002''. So $k$ counts applications of $f$. (Counting the primes in the chain instead would make the conjecture false, since 4-Rotation Cycle Primes give chains of five primes.) + +\begin{theorem}[Seggelin's Conjecture~2]\label{thm:main} +There are no 5-Rotation Cycle Primes: there is no prime $p$ such that $f(p)$, $f^2(p)$, $f^3(p)$, $f^4(p)$ and $f^5(p)$ are all prime. +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A086004.lean}, reviewed for fidelity, and frozen before the proof attempt (SHA-256 \texttt{adb8cf05\dots73eb5d}). Its definitions, data checks and statement are, verbatim except that docstrings, the proof of \decl{a_data}, two further data checks (described below) and the helpers and lemmas used only in these checks are omitted: +\begin{lstlisting} +namespace Math0.Statements.A086004 + +def rot (n : ℕ) : ℕ := + let d := (Nat.digits 10 n).length + let l := d / 2 + let h := d - l + n % 10 ^ l * 10 ^ h + n / 10 ^ l % 10 ^ (h - l) * 10 ^ l + n / 10 ^ h + +def rotAdd (n : ℕ) : ℕ := n + rot n + +def IsRotationCyclePrime (k p : ℕ) : Prop := + p.Prime ∧ ∀ j, 1 ≤ j → j ≤ k → (rotAdd^[j] p).Prime + +noncomputable def a (n : ℕ) : ℕ := Nat.nth (IsRotationCyclePrime 3) (n - 1) + +theorem a_data : (List.range 13).map (fun i => a (i + 1)) = + [12917, 12919, 18911, 18913, 22907, 24907, 26903, 28901, 1088063, 1288043, 1408031, + 1428029, 1528019] := by + -- (kernel scans, omitted; see the text) + +def statement : Prop := + ∀ p : ℕ, ¬ IsRotationCyclePrime 5 p + +end Math0.Statements.A086004 +\end{lstlisting} + +\emph{Encoding.} Mathlib's \texttt{Nat.digits 10 n} is the list of decimal digits of $n$, least significant first, and is empty for $n=0$; its length is $\nd(n)$. The natural-number operations \texttt{/} and \texttt{\%} are the floor quotient and the remainder, and \texttt{d - l}, \texttt{h - l} are exact because $l\le h\le d$. Hence \decl{rot} is $\rot$ of Definition~\ref{def:rot}, \decl{rotAdd} is $f$, and \texttt{rotAdd\^{}[j]} is $f^j$. \decl{IsRotationCyclePrime}~$k$~$p$ says that $p$ is a $k$-Rotation Cycle Prime, and \decl{statement} is Theorem~\ref{thm:main}. There is no degenerate case: $p\ge2$, and the iterates are at least $p$. The sequence A086004 itself, with offset~$1$, is \texttt{a n}, the $(n-1)$-th element (counted from $0$) of the increasing enumeration of the 3-Rotation Cycle Primes. + +\emph{Checks against the OEIS.} All checks are proved in the kernel with \texttt{decide +kernel}. The theorem \decl{rot_examples} checks the examples of A086002 and the chains of the A086004 and A261458 examples; \decl{rot_eq_rotDigits_data} checks that $\rot$ agrees, for all $n<2000$ and on the numbers of the examples, with \decl{rotDigits}, a direct transcription of the A086002 definition on the digit list. \decl{a_data} checks that the definitions reproduce the first $13$ listed terms, which are all listed terms below $10^8$. Its proof shows that below $1530000$ the 3-Rotation Cycle Primes are exactly these $13$ numbers, by kernel scans over about $127{,}000$ candidates with helper functions written with recursors and primitive arithmetic, each proved equal to or sound for the definitions; the scan is shortened by three facts proved in the same file (the last digit of a prime $\ge10$; Mathar's factorization for $4$- and $6$-digit numbers; Wu's parity observation for $5$- and $7$-digit numbers). Independently, the fidelity reviewer compared \decl{rot} in Python with the Mathematica \texttt{rot} of the entries on all $n<200000$ and on $200000$ random numbers of up to $30$ digits, and recomputed all $24$ listed terms of A086004 from the formal definitions. + +\section{Proof}\label{sec:proof} + +We follow the Lean proof; each lemma below carries the name of the corresponding declaration. Throughout, $m\in\N$, $P=10^m$, and for $10^{2m}\le n<10^{2m+1}$ (that is, $\nd(n)=2m+1$) we write +\[ + X(n)=\lfloor n/10P\rfloor,\qquad M(n)=\lfloor n/P\rfloor\bmod10,\qquad Y(n)=n\bmod P,\qquad S(n)=X(n)+Y(n). +\] +Thus $X(n)$ is formed by the first $m$ digits, $M(n)$ is the centre digit and $Y(n)$ is formed by the last $m$ digits of $n$. For $10^k\le n<10^{k+1}$ we have $\nd(n)=k+1$ (the lemma \decl{length_digits_eq} of the statement file). + +\begin{lemma}[\decl{rotAdd_even}; Mathar]\label{lem:even} +If $\nd(n)=2k$, then $f(n)=\bigl(\lfloor n/10^k\rfloor+(n\bmod10^k)\bigr)(10^k+1)$. +\end{lemma} + +\begin{proof} +Here $l=h=k$ and the middle term of $\rot(n)$ is $(\lfloor n/10^k\rfloor\bmod1)\cdot10^k=0$. Writing $a=\lfloor n/10^k\rfloor$ and $b=n\bmod10^k$, we have $n=10^ka+b$ and $f(n)=10^ka+b+10^kb+a=(a+b)(10^k+1)$. +\end{proof} + +\begin{lemma}[\decl{odd_range}]\label{lem:odd} +If $n$ and $f(n)$ are prime, then $10^{2m}\le n<10^{2m+1}$ for some $m\in\N$. +\end{lemma} + +\begin{proof} +Since $n\ne0$, $\nd(n)\ge1$. If $\nd(n)=2m+1$ is odd, then $10^{2m}\le n<10^{2m+1}$. Suppose $\nd(n)=2k$ is even; then $k\ge1$ and $n\ge10^{2k-1}\ge10^k$. By Lemma~\ref{lem:even}, $f(n)=(a+b)(10^k+1)$ with $a=\lfloor n/10^k\rfloor$, $b=n\bmod10^k$. A product of two natural numbers is prime only if one factor is $1$ and the other is prime. The factor $10^k+1$ is not $1$, so $a+b=1$. Since $n\ge10^k$ we have $a\ge1$, hence $a=1$ and $b=0$. Then $10^k\mid n$, so $2\mid n$, and as $n$ is prime, $n=2$. This contradicts $n\ge10^k\ge10$. +\end{proof} + +\begin{lemma}[\decl{decomp}, \decl{rot_odd}, \decl{rotAdd_odd}, \decl{rot_lt}]\label{lem:shape} +Let $10^{2m}\le n<10^{2m+1}$, and write $X,M,Y,S$ for $X(n),M(n),Y(n),S(n)$. Then +\begin{enumerate} +\item[(a)] $n=10P\,X+P\,M+Y$; +\item[(b)] $\rot(n)=10P\,Y+P\,M+X$; +\item[(c)] $f(n)=10P\,S+2P\,M+S$; +\item[(d)] $\rot(n)<10^{2m+1}$. +\end{enumerate} +\end{lemma} + +\begin{proof} +(a) Divide $n$ by $P$ and then $\lfloor n/P\rfloor$ by $10$: $n=P\lfloor n/P\rfloor+Y$ and $\lfloor n/P\rfloor=10\lfloor\lfloor n/P\rfloor/10\rfloor+M=10X+M$, using $\lfloor\lfloor n/P\rfloor/10\rfloor=\lfloor n/10P\rfloor$. +(b) Since $\nd(n)=2m+1$, we have $l=m$, $h=m+1$, $h-l=1$, so the definition gives $\rot(n)=Y\cdot10P+M\cdot P+X$. +(c) Add (a) and (b). +(d) We have $Y\le P-1$, $M\le9$, and $X\le P-1$ because $n<10P\cdot P$. Hence $\rot(n)\le10P(P-1)+9P+(P-1)=10P^2-1<10^{2m+1}$. +\end{proof} + +\begin{lemma}[\decl{stay}]\label{lem:stay} +If $10^{2m}\le n<10^{2m+1}$ and $f(n)$ and $f(f(n))$ are prime, then $f(n)<10^{2m+1}$. +\end{lemma} + +\begin{proof} +By Lemma~\ref{lem:odd} applied to $f(n)$, there is $m'$ with $10^{2m'}\le f(n)<10^{2m'+1}$. By Lemma~\ref{lem:shape}(d), $f(n)=n+\rot(n)<2\cdot10^{2m+1}<10^{2m+2}$. If $m'>m$, then $10^{2m+2}\le10^{2m'}\le f(n)$, a contradiction. So $m'\le m$ and $f(n)<10^{2m'+1}\le10^{2m+1}$. +\end{proof} + +\begin{lemma}[\decl{mid}, \decl{blocks}]\label{lem:mid} +Let $10^{2m}\le n<10^{2m+1}$ and $f(n)<10^{2m+1}$, and let $M=M(n)$. Then +\begin{enumerate} +\item[(a)] $M(f(n))=2M\bmod10$; +\item[(b)] if $M<5$, then $f(f(n))=2f(n)$. +\end{enumerate} +\end{lemma} + +\begin{proof} +Let $S=S(n)$. By Lemma~\ref{lem:shape}(c), $f(n)=10P\,S+2M\,P+S$. Since $10P\,S\le f(n)<10^{2m+1}=10P\cdot P$, we get $S 4, +- group n-1 has a largest prime p, +- the last term of group n is 2p, +- p = B_{n-1}. + +## Assessment + +Take consecutive Bertrand primes b < a < c, so that row n is [2b+1, 2a]. The prime c lies in row n, and the first multiple of c after 2a is 2c, so the next row must reach 2c. Ending at 2c is enough because (2a)!^2 divides (2b)!(2c)!, which follows from a short Legendre-formula check on floor functions plus a small prime-power case. The only deep input is a known prime-gap bound (Nagura 1952), and the first rows are checked by computer. The whole argument is elementary and fits in about a page; the scouting pass found it straight away. The long Lean file mostly reproves Nagura's bound with Chebyshev weights, which is formalization work, not a new idea. + +*Follows from:* Nagura's theorem (1952: a prime in (x, 6x/5) for x >= 25), which gives the ratio bounds 5/3 between consecutive Bertrand primes (A006992), combined with Legendre's formula for the factorial divisibility (2a)!^2 | (2b)!(2c)! and a finite computer check of the first rows + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A090905](https://oeis.org/A090905) as [`Math0.Statements.A090905.statement`](../../lean/Math0/Statements/OEIS/A090905.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A090905.lean`](../../lean/Math0/Frontier/OEIS/A090905.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C Conjecture: For n > 4 the last term of the n-th group is 2p where p is the largest prime in the (n-1)th group. And these are the Bertrand primes. (Amarnath Murthy, Dec 13 2003) + +Referees: I found no prior proof or refutation. +- OEIS A090904, A090905, A090906 and A090907 (Murthy, Dec 2003; last edited Dec 2016) state the claim only as a conjecture. A090907 adds "verified for 4= 5, without proof. +- Related: A113117 and A113118 (L. Quet, 2006), A093911 (Murthy's variant), and A006992 (Bertrand primes). +- The key analytic input is Nagura's theorem (J. Nagura, Proc. Japan Acad. 28 (1952) 177-181: for x >= 25 there is a prime between x and 6x/5). The Lean development reproves the form it needs (a prime in (5x/3, 2x) for x >= 83) from scratch. +- Searches of arXiv, MathOverflow/MSE, SeqFan-style queries and the formal-conjectures repository found no prior resolution and no prior formalization. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a090905, + author = {{math0}}, + title = {{A090905: every row ends at twice the largest prime of the previous row (Murthy's conjecture proved)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a090905}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a090905/paper.pdf b/results/oeis-a090905/paper.pdf new file mode 100644 index 0000000..2b675cf Binary files /dev/null and b/results/oeis-a090905/paper.pdf differ diff --git a/results/oeis-a090905/paper.tex b/results/oeis-a090905/paper.tex new file mode 100644 index 0000000..6a36fbb --- /dev/null +++ b/results/oeis-a090905/paper.tex @@ -0,0 +1,346 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {∧}{{$\wedge$}}1 + {→}{{$\to$}}1 {≤}{{$\le$}}1 {∣}{{$\mid$}}1 {×}{{$\times$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\rf}[2]{#1^{\overline{#2}}} +\newcommand{\fl}[1]{\lfloor #1\rfloor} + +\title[The divisible-product triangle A090905 and the Bertrand primes]{The rows of the divisible-product triangle OEIS A090905 end at twice the Bertrand primes} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + +\begin{document} +\begin{abstract} +Split $1,2,3,\dots$ into consecutive blocks: block $1$ is $(1)$, and each later block is the shortest block, not shorter than its predecessor, whose product is a multiple of the product of its predecessor (OEIS A090905). +We prove Amarnath Murthy's 2003 conjecture from this entry: for every $n>4$ the last term of block $n$ is $2p$, where $p$ is the largest prime of block $n-1$, and $p$ is the Bertrand prime $B_{n-1}$ (OEIS A006992: $B_1=2$, and $B_{k+1}$ is the largest prime below $2B_k$). +The proof combines Legendre's formula with a prime in $(5x/3,2x)$ for every integer $x\ge83$, a weak form of Nagura's 1952 theorem, which we reprove by an explicit prime ladder and Chebyshev's method. +We know of no earlier proof, so we classify the result as new, although the argument is elementary once the prime-gap bound is available. +The theorem is verified in Lean~4 against the frozen, fidelity-reviewed math0 formalization of the conjecture, whose definitions are checked by the kernel against the OEIS data. +\end{abstract} +\maketitle + +\section{Introduction} + +OEIS A090905 \cite{A090905}, contributed by Amarnath Murthy on December~13, 2003, is the ``Left side of irregular triangle of natural numbers in which every row product is a multiple of the previous''. The triangle splits $1,2,3,\dots$ into consecutive blocks (``groups'') $(1)$, $(2)$, $(3,4)$, $(5,\dots,8)$, $(9,\dots,14)$, $(15,\dots,26)$, $(27,\dots,46)$, \dots\ Each block starts right after the previous one, and its length is the least $k$, not smaller than the previous length, such that the product of the previous block divides the product of the new one; this is the rule of the Mathematica program of M.~De Vlieger (2016) in the entry. The companion entries A090904, A090906 and A090907 \cite{A090904} list the row products, the row lengths, and the ratios of consecutive row products. All four entries carry Murthy's conjecture (quoted in Section~\ref{sec:statement}): for $n>4$ the last term of row $n$ is twice the largest prime of row $n-1$, and these primes are the Bertrand primes A006992 \cite{A006992}. We prove it (Theorem~\ref{thm:main}). + +\subsection*{Method} +Let $b5b$ and $3c>5a$, i.e.\ a prime in $(5x/3,2x)$ for every integer $x\ge83$. This follows from Nagura's theorem \cite{Nag} (a prime in $(x,6x/5)$ for $x\ge25$); the Lean development proves the needed form from scratch, by a ladder of primes below $10^6$ and by Chebyshev's method \cite{Cheb} above. + +\subsection*{Status and prior work} +The entries A090904--A090907 (last edited in December 2016) state the claim only as a conjecture. A090907 \cite{A090904} gives a formula for the ratios in terms of A006992, ``verified for $44$; as written it is off by one index (it gives $12$ for $n=5$, whereas the fifth row length is $6$). Theorem~\ref{thm:main} gives the shifted form $2(\mathrm{A006992}(n-1)-\mathrm{A006992}(n-2))$ for $n\ge6$, and the formula of A090907 for $n\ge6$ (neither consequence is formalized). A381901 \cite{A381901} (A.~Niedermaier, March 2025) defines the same partition without the lower bound on the row length and states, without proof, that the last term of row $n$ is $2\,\mathrm{A006992}(n-1)$ for $n\ge5$; this follows from Theorem~\ref{thm:main} and Remark~\ref{rem:bound}. Related entries are A113117, A113118 (L.~Quet, 2006) and Murthy's variant A093911 \cite{A093911}. The math0 referees found no proof or counterexample in searches of arXiv, MathOverflow, Mathematics Stack Exchange and SeqFan-style queries, and no formalization in the formal-conjectures repository \cite{FC}. + +\section{Statement}\label{sec:statement} + +For integers $s\ge1$ and $k\ge0$ write $\rf{s}{k}=s(s+1)\cdots(s+k-1)$ (Lean's \decl{Nat.ascFactorial}), the product of the block $s,\dots,s+k-1$. + +\begin{definition}\label{def:tri} +Let $a(1)=1$, $L(1)=1$ and, for $n\ge1$, +\[ +a(n+1)=a(n)+L(n),\qquad L(n+1)=\min\{k\ge L(n): \rf{a(n)}{L(n)}\mid \rf{a(n+1)}{k}\}. +\] +Row $n$ is the block $[a(n),e(n)]$ with $e(n)=a(n)+L(n)-1$. The Bertrand primes are $B_1=2$ and $B_{k+1}=$ the largest prime $<2B_k$; thus $(B_k)_{k\ge1}=2,3,5,7,13,23,43,83,163,317,\dots$ +\end{definition} + +The minimum exists: $k=a(n+1)-1=a(n)+L(n)-1\ge L(n)$ is admissible, because the row product divides $(a(n+1)-1)!$, which divides the product of any $a(n+1)-1$ consecutive integers. The COMMENTS section of A090905 reads, verbatim (the entry is by Amarnath Murthy, December~13, 2003): +\begin{quote} +{\small\raggedright\texttt{Conjecture: For n > 4 the last term of the n-th group is 2p where p is the largest prime in the (n-1)th group. And these are the Bertrand primes.}\par} +\end{quote} + +\begin{theorem}\label{thm:main} +For every $n\ge5$, the set of primes in row $n-1$ has a largest element $p$; moreover $e(n)=2p$ and $p=B_{n-1}$. +\end{theorem} + +Applying this to $n$ and to $n-1$ and using $a(n)=e(n-1)+1$, we see that row $n$ is $[2B_{n-2}+1,\,2B_{n-1}]$ and $L(n)=2B_{n-1}-2B_{n-2}$ for every $n\ge6$. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A090905.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{8616fe97\ldots a42a44}) before any proof attempt. Its definitions read as follows (verbatim; docstrings and the auxiliary theorems are omitted): +\begin{lstlisting} +namespace Math0.Statements.A090905 +def search (P s : ℕ) : ℕ → ℕ → ℕ → ℕ + | 0, k, _ => k + | fuel + 1, k, Q => if P ∣ Q then k else search P s fuel (k + 1) ((s + k) * Q) +def next (r : ℕ × ℕ) : ℕ × ℕ := + (r.1 + r.2, + search (r.1.ascFactorial r.2) (r.1 + r.2) (r.1 + r.2) r.2 ((r.1 + r.2).ascFactorial r.2)) +def row (n : ℕ) : ℕ × ℕ := next^[n - 1] (1, 1) +def a (n : ℕ) : ℕ := (row n).1 +def len (n : ℕ) : ℕ := (row n).2 +def last (n : ℕ) : ℕ := a n + len n - 1 +def bertrand (n : ℕ) : ℕ := (fun b => Nat.findGreatest Nat.Prime (2 * b - 1))^[n - 1] 2 +def statement : Prop := + ∀ n : ℕ, 4 < n → ∃ p : ℕ, + IsGreatest {q : ℕ | q.Prime ∧ a (n - 1) ≤ q ∧ q ≤ last (n - 1)} p ∧ + last n = 2 * p ∧ p = bertrand (n - 1) +\end{lstlisting} +A row is stored as the pair (first term, length). Called with $Q=\rf{s}{k}$, \lstinline|search P s fuel k Q| returns the least $j\in[k,k+\mathit{fuel})$ with $P\mid\rf{s}{j}$ (or $k+\mathit{fuel}$ if there is none). The file proves \decl{a_one}, \decl{len_one}, \decl{a_succ} and \decl{len_succ_isLeast}, i.e.\ the recursion of Definition~\ref{def:tri} for $n\ge1$; in particular the fuel $a(n+1)$ always suffices (the admissible $k=a(n+1)-1$ lies in the search window), so \decl{a}, \decl{len}, \decl{last} are exactly $a$, $L$, $e$ (and $a(n)\ge1$, so the truncated subtraction in \decl{last} is harmless). Since $B_k\ge2$, \lstinline|Nat.findGreatest Nat.Prime (2 * b - 1)| at $b=B_k$ is the largest prime $<2B_k$, so \decl{bertrand} is A006992. Lemmas proved by \texttt{decide +kernel} check $a(1),\dots,a(18)$, $L(1),\dots,L(17)$ and $B_1,\dots,B_{13}$ against the data of A090905, A090906 and A006992 (\decl{a_data}, \decl{len_data}, \decl{bertrand_data}). + +``The largest prime in the $(n-1)$th group'' is the greatest element of the set of primes in $[a(n-1),e(n-1)]$, whose existence is asserted. ``These are the Bertrand primes'' is read as $p=B_{n-1}$: for $n=5$ the largest prime of row $4=(5,\dots,8)$ is $7=B_4$, and the rows are disjoint and increasing ($2,3,5$ do not occur as such $p$). This is the strongest natural reading; the weaker reading ``each such $p$ is a Bertrand prime'' follows from it. + +\begin{remark}\label{rem:bound} +The bound $k\ge L(n)$ comes from De Vlieger's program, not from the entry's name. Dropping it does not change the triangle (not formalized): rows $1$--$20$ agree by computer check, and for $n\ge10$ the minimality argument of Lemma~\ref{lem:step} does not use the bound. +\end{remark} + +\section{Proof}\label{sec:proof} + +We follow the Lean proof; names of its (private) lemmas are given in brackets. + +\subsection{\texorpdfstring{A prime between $5x/3$ and $2x$}{A prime between 5x/3 and 2x}} + +\begin{proposition}[\decl{exists_prime}]\label{prop:nagura} +For every integer $x\ge83$ there is a prime $p$ with $5x<3p<6x$. +\end{proposition} + +This follows from Nagura's theorem \cite{Nag} at $5x/3\ge25$; we give the self-contained proof that is formalized. + +\begin{lemma}[\decl{ladder_aux}]\label{lem:ladder} +Let $q_0=138$, and let $q_1<\dots0}c_i+\sum_{c_i<0}c_i/2$ and $E^-=\sum_{c_i>0}c_i/2+\sum_{c_i<0}c_i$. For $W_L$: $D_1=196\log2+126\log3+70\log5\ge386.94$, $D_2=-\log420\ge-6.05$, $S=-1$, $E^-=-2$. For $W_U$: $D_1=192\log2+123\log3+70\log5+35\log7\le448.99$, $D_2=-\log11760\le-9.37$, $S=-6$, $E^+=1$. These numerical bounds use Mathlib's $0.6931471803<\log2<0.6931471808$ and $16$ terms of the series of $\log(1-t)$ at $t=\frac14,\frac15,\frac18$ with Mathlib's remainder bound \decl{Real.abs_log_sub_add_sum_range_le}. Combining with $G_{W_L}(420m)\le\psi(420m)\le G_{W_U}(420m)+\psi(m)$ gives the claim. +\end{proof} + +\begin{proof}[Proof of Proposition~\ref{prop:nagura} for $x\ge10^6$ \textup{(\decl{exists_prime_large})}] +For an integer $p$, $5x<3p<6x$ means $\fl{5x/3}0.05379$ and $2.8286\log2\le1.9608$, so $0.05379\,x\le837.27+\lambda/2+1.9608\,s+2.9715\,s\lambda$. From $\log(s/1000)\le s/1000-1$ and $\log1000=3\log2+3\log5\le6.9078$ we get $\lambda=2\log s\le11.8157+s/500$. Substituting this and $x=s^2$ yields $0.0478\,s^2-37.08\,s-843.2\le0$, which is false because $s^2\ge1000s$ (one \texttt{linarith} call in Lean). +\end{proof} + +\subsection{The Bertrand chain} + +\begin{lemma}[\decl{chain_step}, \decl{bertrand_ge}]\label{lem:chain} +For $k\ge8$: $B_k\ge83$, $5B_k<3B_{k+1}$, $B_{k+1}<2B_k$, and no prime lies in $(B_{k+1},2B_k)$. +\end{lemma} + +\begin{proof} +If $b\ge83$ and $c$ is the largest prime $\le2b-1$, Proposition~\ref{prop:nagura} gives a prime $p\le2b-1$ with $5b<3p$, so $5b<3c$; the other claims hold by the choice of $c$. Now induct from $B_8=83$ (a kernel computation). +\end{proof} + +\subsection{The factorial divisibility} + +\begin{lemma}[\decl{pointwise}]\label{lem:pointwise} +Let $a<2b$ and $5a<3c$. For an integer $y\ge1$ put $k=\fl{2a/y}$ and $f(y)=\fl{2b/y}+\fl{2c/y}-2k$. Then \textup{(i)} $f(y)\ge-1$; \textup{(ii)} $f(y)\ge0$ unless $c2a$ forces $k=0$. If $y\le c$, then $q_2\ge2$, which gives $f\ge0$ for $k\le1$; for $k\ge2$ the bounds $q_1\ge\lceil(k-1)/2\rceil$ and $q_2\ge\lceil(5k-2)/3\rceil$ give $q_1+q_2\ge2k$ (directly for $2\le k\le6$, and from $(13k-7)/6\ge2k$ for $k\ge7$). In Lean all cases are closed by \texttt{omega}. +\end{proof} + +\begin{lemma}[\decl{fact_dvd}]\label{lem:factdvd} +Let $b\ge83$, $5b<3a$, $a<2b$, $5a<3c$, $c<2a$, and suppose that no prime lies in $(c,2a)$. Then $(2a)!^2\mid(2b)!\,(2c)!$. +\end{lemma} + +\begin{proof} +By Legendre's formula (Mathlib's \decl{Nat.factorization_factorial}) it suffices to show $\sum_{j\ge1}f(\ell^j)\ge0$ for every prime $\ell$, with $f$ as in Lemma~\ref{lem:pointwise}. If no power $\ell^j$ ($j\ge1$) lies in $(c,2a]$, every term is $\ge0$ by Lemma~\ref{lem:pointwise}(ii). Otherwise let $c<\ell^j\le2a$. This $j$ is unique: if also $c<\ell^i\le2a$ with $i2c$, contradicting $c>5a/3$. Moreover $j\ge2$: a prime $\ell\in(c,2a)$ is excluded by hypothesis, and $\ell=2a$ is impossible since $2a>2$ is even. Hence $\ell^2\le2a$, and so $13\ell\le2a$ (from $\ell^2\le2a$ if $\ell\ge13$, and from $2a>10b/3>156$ if $\ell<13$). Thus $\fl{2a/\ell}\ge13$, so $f(\ell)\ge1$ by (iii), $f(\ell^j)\ge-1$ by (i), and all other terms are $\ge0$ by (ii). +\end{proof} + +\subsection{The rows} + +\begin{lemma}[\decl{step_core}]\label{lem:step} +Under the hypotheses of Lemma~\ref{lem:factdvd}, if $c$ is prime, then $2c-2a$ is the least $k\ge2a-2b$ with $\rf{(2b+1)}{2a-2b}\mid\rf{(2a+1)}{k}$. +\end{lemma} + +\begin{proof} +First, $c>5a/3$ and $b>a/2$ give $b+c>2a$, i.e.\ $2c-2a\ge2a-2b$. Next, $(2b)!\,\rf{(2b+1)}{2a-2b}=(2a)!$ and $(2a)!\,\rf{(2a+1)}{2c-2a}=(2c)!$; multiplying the desired divisibility by $(2b)!\,(2a)!$ turns it into Lemma~\ref{lem:factdvd}, so $k=2c-2a$ is admissible. Finally, $c>5a/3>25b/9>2b$ and $c<2a$, so the prime $c$ divides $\rf{(2b+1)}{2a-2b}$. If $k<2c-2a$, the factors $2a+1,\dots,2a+k$ of $\rf{(2a+1)}{k}$ lie strictly between $c$ and $2c$, so $c\nmid\rf{(2a+1)}{k}$ and $k$ is not admissible. (This part does not use the bound $k\ge2a-2b$.) +\end{proof} + +\begin{proposition}[\decl{rows}]\label{prop:rows} +For every $n\ge10$, $a(n)=2B_{n-2}+1$ and $L(n)=2B_{n-1}-2B_{n-2}$. +\end{proposition} + +\begin{proof} +Induction on $n$. For $n=10$ the kernel evaluates $a(10)=167$, $L(10)=160$, $B_8=83$ and $B_9=163$ (\texttt{decide +kernel}). For the step put $b=B_{n-2}$, $a=B_{n-1}$, $c=B_n$. Lemma~\ref{lem:chain} gives the hypotheses of Lemmas~\ref{lem:factdvd} and~\ref{lem:step}. By the induction hypothesis row $n$ is $[2b+1,2a]$, so $a(n+1)=2a+1$, and \decl{len_succ_isLeast} together with Lemma~\ref{lem:step} gives $L(n+1)=2c-2a$. +\end{proof} + +\subsection{Proof of Theorem~\ref{thm:main}} +For $n=5,\dots,10$, row $n-1$ is $[5,8]$, $[9,14]$, $[15,26]$, $[27,46]$, $[47,86]$, $[87,166]$, with largest prime $p=7,13,23,43,83,163$, which is $B_{n-1}$, and $e(n)=14,26,46,86,166,326=2p$. These values are evaluated by the kernel (\texttt{decide +kernel}), and the absence of primes in $(p,e(n-1)]$ is checked by \texttt{interval\_cases} and \texttt{norm\_num} (\decl{small_case}). Let $n\ge11$. By Proposition~\ref{prop:rows}, row $n-1$ is $[2B_{n-3}+1,2B_{n-2}]$ and $e(n)=2B_{n-1}$. By the chain inequalities, $p=B_{n-1}$ satisfies $p>25B_{n-3}/9>2B_{n-3}$ and $p<2B_{n-2}$, so it is a prime in row $n-1$. A prime $q>p$ in row $n-1$ would satisfy $q<2B_{n-2}$ (as $2B_{n-2}>2$ is even), contradicting the absence of primes in $(B_{n-1},2B_{n-2})$. Hence $p$ is the largest prime of row $n-1$, and $e(n)=2p$. \qed + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and audit} +The proof is the file \path{lean/Math0/Frontier/OEIS/A090905.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. The main declaration is \decl{Math0.Frontier.A090905.result}, of type \decl{Math0.Statements.A090905.statement}; all other declarations in the file are private. The file uses no \texttt{sorry}, \texttt{native\_decide}, \texttt{axiom} or \texttt{set\_option}; the finite computations use \texttt{decide}, \texttt{decide +kernel} and \texttt{norm\_num}, whose results are checked by the kernel. The file ends with \lstinline|#math0_settles result statement| (with fully qualified names), a command defined in \path{lean/Math0/Audit.lean} for statements formalized by math0. It fails unless \decl{statement} is a \texttt{Prop}-valued definition without universe parameters, the type of \decl{result} is syntactically \decl{statement} or its negation (up to metadata, without unfolding), and both depend only on the axioms \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (which excludes \decl{sorryAx}, \texttt{native\_decide} and custom axioms). It reports: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize,belowskip=0pt] +math0 audit: 'Math0.Statements.A090905.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A090905.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A090905.result' proves 'Math0.Statements.A090905.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. To reproduce, run \path{scripts/verify.sh}: it fetches the Mathlib cache, builds the library with \texttt{lake build} (re-running every audit), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and counts the passed statement checks. + +{\footnotesize\raggedright +\begin{thebibliography}{99} + +\bibitem{Cheb} +P.~L. Tchebichef, \emph{M\'emoire sur les nombres premiers}, J. Math.\ Pures Appl.\ (1) \textbf{17} (1852), 366--390. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput.\ Sci.\ \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Nag} +J.~Nagura, \emph{On the interval containing at least one prime number}, Proc.\ Japan Acad.\ \textbf{28} (1952), 177--181. + +\bibitem{A006992} +The OEIS Foundation Inc., A006992 (Bertrand primes), \url{https://oeis.org/A006992}. + +\bibitem{A090904} +The OEIS Foundation Inc., A090904, A090906, A090907 (A.~Murthy, 2003), \url{https://oeis.org/A090904}, \url{https://oeis.org/A090906}, \url{https://oeis.org/A090907}. + +\bibitem{A090905} +The OEIS Foundation Inc., A090905 (A.~Murthy, Dec.~13, 2003), \url{https://oeis.org/A090905}. + +\bibitem{A093911} +The OEIS Foundation Inc., A093911 (A.~Murthy, 2004), A113117, A113118 (L.~Quet, 2006), \url{https://oeis.org/A093911}, \url{https://oeis.org/A113117}, \url{https://oeis.org/A113118}. + +\bibitem{A381901} +The OEIS Foundation Inc., A381901 (A.~Niedermaier, Mar.~9, 2025), \url{https://oeis.org/A381901}. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a091817/README.md b/results/oeis-a091817/README.md new file mode 100644 index 0000000..f5a80d0 --- /dev/null +++ b/results/oeis-a091817/README.md @@ -0,0 +1,44 @@ +# Quet's integrality conjecture for A091817 holds + +**Classification:** First formal proof of a known result +**Area:** Number theory +**Source problem:** OEIS A091817 +**Date:** 2026-10-18 + +## Result + +For every prime p >= 3, write H(p-3) = 1 + 1/2 + ... + 1/(p-3) = N/D in lowest terms (H(0) = 0/1). Then p divides 2N - 3D. Equivalently, every term a(n) = (2N - 3D)/p of OEIS A091817 (p the (n+1)-th prime, n >= 1) is an integer. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A091817](https://oeis.org/A091817) as [`Math0.Statements.A091817.statement`](../../lean/Math0/Statements/OEIS/A091817.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A091817.lean`](../../lean/Math0/Frontier/OEIS/A091817.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Leroy Quet conjectures that the terms are always integral. This is true for p < 3*10^4. (Entry: (2*numerator(H(p-3)) - 3*denominator(H(p-3)))/p, Bouayoun and Stephan, Mar 07 2004) + +Referees: - OEIS A091817 and its history (oeis.org/history?seq=A091817): the conjecture is still stated as open, verified for p < 3*10^4, and has no proof note. +- Classical source: H(p-1) ≡ 0 (mod p) (Wolstenholme 1862; Hardy & Wright, An Introduction to the Theory of Numbers, Thm 115). +- Explicit reflection congruence H_{p-k} ≡ H_{k-1} (mod p), 1 <= k <= p-1: Z.-W. Sun & L.-L. Zhao, "Arithmetic theory of harmonic numbers (II)", Colloq. Math. 130 (2013), 67-78, arXiv:0911.4433 (proof of (2.2)). Taking k = 3 gives H_{p-3} ≡ 3/2 (mod p), which settles the conjecture at once. +- The same lemma is cited in arXiv:1108.2361 (Lemma 2.1 of its ref. [13]) and arXiv:1803.02966. +- Analogous k = 2 fact in OEIS A064169 (Adamchuk, Jun 09 2006: p divides a(p-2)). +- No prior formalization found: + - not in google-deepmind/formal-conjectures (checked locally at commit c77fdd4); + - not among the OEIS Open benchmark statements (Adamczewski, arXiv:2608.11941); + - no other formal proof turned up in searches. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a091817, + author = {{math0}}, + title = {{Quet's integrality conjecture for A091817 holds}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a091817}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a091817/paper.pdf b/results/oeis-a091817/paper.pdf new file mode 100644 index 0000000..66b6f80 Binary files /dev/null and b/results/oeis-a091817/paper.pdf differ diff --git a/results/oeis-a091817/paper.tex b/results/oeis-a091817/paper.tex new file mode 100644 index 0000000..28a24c1 --- /dev/null +++ b/results/oeis-a091817/paper.tex @@ -0,0 +1,372 @@ +% math0 manuscript template. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, keepspaces=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 + {∃}{{$\exists$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {∈}{{$\in$}}1 + {∑}{{$\sum$}}1 {∧}{{$\wedge$}}1 {⁻¹}{{$^{-1}$}}2} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\F}{\mathbb{F}_p} +\newcommand{\res}[1]{\overline{#1}} +\DeclareMathOperator{\num}{num} +\DeclareMathOperator{\den}{den} + +\title[The congruence $2H_{p-3}\equiv 3\pmod p$ and OEIS A091817]{The congruence $2H_{p-3}\equiv 3 \pmod p$ and the integrality of the terms of OEIS A091817} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +For a prime $p\ge 3$ write the harmonic number $H_{p-3}=1+\frac12+\dots+\frac1{p-3}$ in lowest terms as $N/D$ (with $H_0=0/1$). We prove that $p$ divides $2N-3D$, which confirms Leroy Quet's conjecture, recorded in OEIS A091817 in 2004, that the terms $(2N-3D)/p$ of that sequence are always integers. +The result is not new mathematics: it is the case $k=3$ of the known congruence $H_{p-k}\equiv H_{k-1}\pmod p$, an immediate consequence of the classical fact $H_{p-1}\equiv0\pmod p$, although we found no place where this consequence is recorded for A091817. +We classify the note as the first formal proof of a known result. +The proof is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against all $18$ listed terms and which was reviewed for fidelity and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +Let $H_m=\sum_{k=1}^{m}1/k$ denote the $m$-th harmonic number, with $H_0=0$. The OEIS sequence A091817 \cite{A091817}, contributed by Mohammed Bouayoun and Ralf Stephan on March~7, 2004, and proposed by Leroy Quet, is +\[ + a(n)=\frac{2\num(H_{p-3})-3\den(H_{p-3})}{p},\qquad p\text{ the $(n+1)$-th prime},\ n\ge1, +\] +where $\num$ and $\den$ denote the numerator and the (positive) denominator in lowest terms. Its first terms, for $p=3,5,7,11,13$, are $-1,0,2,62,554$. The entry records that Quet conjectured that the terms are always integral, and that this was checked for $p<3\cdot10^4$. The math0 referees read the edit history of the entry: the current revision (\#8, March~11, 2014) still states the conjecture without a proof or a reference. + +\subsection*{Prior work} +The conjecture follows at once from classical facts. For an odd prime $p$, pairing $1/k$ with $1/(p-k)$ shows that $p$ divides the numerator of $H_{p-1}$; Wolstenholme proved in 1862 that $p^2$ divides it when $p>3$ \cite{Wol}, \cite[Theorem~115]{HW}. Since $1/(p-j)\equiv-1/j\pmod p$, this gives the reflection congruence +\begin{equation}\label{eq:reflection} + H_{p-k}=H_{p-1}-\sum_{j=1}^{k-1}\frac1{p-j}\equiv H_{k-1}\pmod p,\qquad 1\le k\le p-1, +\end{equation} +understood in the ring of rationals whose denominator is prime to $p$. The congruence in \eqref{eq:reflection} is (2.1) in Lemma~2.1 of Z.-W.~Sun's preprint arXiv:0911.4433v3 (2009) \cite{Sun-pre}, whose journal version is \cite{Sun}, and the same derivation appears in the proof of the second congruence in (2.2) of Sun and Zhao \cite{SZ}, the final version of the same arXiv number. The congruence is quoted from \cite{Sun-pre,Sun}, in the equivalent form $H_{p-k-1}\equiv H_k\pmod p$ for $1\le k\le p-2$, as Lemma~2.2 of Me\v{s}trovi\'c \cite{Me}, and attributed to Sun \cite{Sun} by Yang and Wang \cite{YW}. Taking $k=3$ gives $H_{p-3}\equiv H_2=3/2\pmod p$, which for $p\ge5$ is exactly Quet's conjecture; the case $p=3$ is $a(1)=-1$. The analogous case $k=2$, namely that $p$ divides $\num(H_{p-2})-\den(H_{p-2})$, is recorded by Alexander Adamchuk (June~9, 2006) in the entry A064169 \cite{A064169}. We found no place, in the OEIS or elsewhere, where the case $k=3$ is connected with A091817. + +The conjecture is not among the OEIS statements of the formal-conjectures repository \cite{FC} (checked at commit \texttt{c77fdd4}), nor among the OEIS conjectures of the OEIS Open benchmark \cite{Ad}, and the referees found no other formal proof. What this note adds is therefore a self-contained proof that matches a kernel-checked Lean proof of a frozen formal statement of the conjecture (Section~\ref{sec:lean}); to our knowledge it is the first formal proof of the statement. + +\section{Statement}\label{sec:statement} + +For $x\in\Q$ we write $x=\num(x)/\den(x)$ in lowest terms with $\den(x)\ge1$; thus $\num(0)=0$ and $\den(0)=1$. + +\begin{definition}\label{def:main} +For $m\in\N$ let $H_m=\sum_{k=1}^{m}1/k\in\Q$, and for a prime $p\ge3$ let +\[ + t(p)=\frac{2\num(H_{p-3})-3\den(H_{p-3})}{p}\in\Q. +\] +For $n\ge1$ let $a(n)=t(p_n)$, where $p_0=2 0 + | fuel + 1, q => if q.Prime then q else firstPrimeFrom fuel (q + 1) + +def nextPrime (m : ℕ) : ℕ := firstPrimeFrom (m + 2) (m + 1) + +def primeAt : ℕ → ℕ + | 0 => 2 + | i + 1 => nextPrime (primeAt i) + +theorem primeAt_eq_nth (i : ℕ) : primeAt i = Nat.nth Nat.Prime i + +def H (m : ℕ) : ℚ := ((List.range m).map (fun k => (1 : ℚ) / ((k : ℚ) + 1))).sum + +def term (p : ℕ) : ℚ := (2 * (H (p - 3)).num - 3 * ((H (p - 3)).den : ℤ) : ℚ) / (p : ℚ) + +def a (n : ℕ) : ℚ := term (primeAt n) + +theorem a_data : (List.range 18).map (fun i => a (i + 1)) = + [-1, 0, 2, 62, 554, 74258, 142682, 2830946, 1448977246, 12576415426, 1857881203154, + 64634117421826, 62771945063582, 164497840779865642, 350742295126606034006, + 5774653629556529218142, 5647762835059481932498, 12720214895833193424471634] := by + decide +kernel + +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → ∃ z : ℤ, a n = (z : ℚ) + +end Math0.Statements.A091817 +\end{lstlisting} + +The encoding matches Definition~\ref{def:main}. +\texttt{H m} is the exact rational sum $\sum_{k=0}^{m-1}1/(k+1)=H_m$, so \texttt{H 0} $=0$, as for the empty sum in PARI. +Mathlib's \decl{Rat.num} and \decl{Rat.den} are the numerator and the positive denominator in lowest terms, so they agree with PARI's \texttt{numerator} and \texttt{denominator}. +\texttt{term p} is $t(p)$, computed in $\Q$ without rounding; the sequence is $\Q$-valued because its integrality is exactly what the conjecture asserts. +\texttt{primeAt i} is the $i$-th prime, indexed from $0$, computed by a bounded search for the next prime in $(m,2m+2]$; the lemma \decl{primeAt_eq_nth} proves that it equals Mathlib's \texttt{Nat.nth Nat.Prime i}, using Bertrand's postulate. Hence \texttt{a n} $=a(n)$. +The statement quantifies over $n\ge1$, that is, over the primes $p\ge3$, and asserts that $a(n)$ is equal to (the image of) an integer. For $n\ge1$ the subtraction $p-3$ in $\N$ is exact and the division is by $p\ne0$. The restriction $n\ge1$ is necessary: for $n=0$, $p=2$, the truncated subtraction gives $2-3=0$ and \texttt{a 0} $=-3/2$, which the fidelity review checked in the kernel. + +The theorem \decl{a_data}, proved by \texttt{decide +kernel}, checks that the definitions reproduce all $18$ terms listed in the OEIS, $a(1),\dots,a(18)$ for $p=3,\dots,67$; the omitted \texttt{example} checks, also in the kernel, that $a(1),\dots,a(4)$ belong to $p=3,5,7,11$. The fidelity reviewer also recomputed the $18$ terms independently in Python. The OEIS formula line states $a(n)=(2A001008(p-3)-3A002805(p-3))/p$ for primes $p\ge5$ \cite{A001008,A002805}; the data, the PARI program and the formal statement also include $p=3$, so the formal statement is at least as strong as the conjecture under either reading. + +\section{Proof}\label{sec:proof} + +We follow the Lean proof, which has four auxiliary results (Lemmas~\ref{lem:succ}--\ref{lem:val}) and a final deduction. Throughout, $p$ is a prime, $\F=\Z/p\Z$, and $\res x\in\F$ is the residue of an integer $x$. As in Lean, the inverse in the field $\F$ is extended by $0^{-1}=0$; with this convention $x\mapsto x^{-1}$ is an involution of $\F$, hence a bijection. For $m\in\N$ put +\[ + S(m)=\sum_{k=0}^{m-1}\bigl(\res k+1\bigr)^{-1}=\sum_{k=1}^{m}\res{k}^{\,-1}\in\F . +\] +This is the private definition \texttt{invSum p m}. For $m2$, so $p\ge3$. + +Let $m=p-3= 1, write the convergent [1; 1/2, 1/3, ..., 1/n] = 1 + 1/(1/2 + 1/(1/3 + ... + 1/(1/n))) in lowest terms as p/q. Then p + q is a power of 2, namely p + q = 2^a(n). Here a(n) is the base-2 logarithm, and a(n) = Sum_{k=1..n} A001511(floor((k+1)/2)) = 2n + 1 - s2(n) - s2(n+1) = A011371(n) + A011371(n+1). In these formulas A001511 is the ruler function, s2 = A000120 is the binary digit sum, and A011371(m) = m - s2(m). + +## Assessment + +The proof writes the convergents as P(n)/Q(n) using a three-term recurrence and checks closed forms for P and P+Q by a short induction. The odd parts of the factorials divide the odd double factorial because C(2m,m) is an integer, and Legendre's formula gives the exponent. Each step is standard: the link to Wallis products and the power-of-2 property are already recorded in the cross-referenced entries, and the manuscript itself calls the result a short consequence of classical facts. The informal argument is about a page; most of the work went into the Lean formalization. + +*Follows from:* The cross-referenced entries already link the convergents to the partial Wallis products (A001902 and A092053 comments; Ordowski's [1;1,1/2,...,1/n] formula in A001901/A001902; Draim 1969), and A001901 is recorded as a subsequence of the powers of 2. Combine this with the closed form W(2m) = 16^m/((2m+1)·C(2m,m)^2), Kummer's theorem v2(C(2m,m)) = s2(m) (also in A056982 for even n), and Legendre's formula v2(m!) = m - s2(m). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A092054](https://oeis.org/A092054) as [`Math0.Statements.A092054.statement`](../../lean/Math0/Statements/OEIS/A092054.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A092054.lean`](../../lean/Math0/Frontier/OEIS/A092054.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: It appears that a(n) = Sum_{k=1..n} A001511(floor((k+1)/2)). Equivalently, a(n) = 2n + 1 - A000120(n) - A000120(n+1) = A011371(n) + A011371(n+1). - _Franklin T. Adams-Watters_, Feb 02 2006 + +Referees: No prior explicit proof of A092054's conjectured formula found. Relevant partial or adjacent sources: +- OEIS A092054 (#43, Aug 09 2026): the formula is still marked "It appears". +- M. A. Suchenek, "Elementary Yet Precise Worst-Case Analysis of Floyd's Heap-Construction Program", Fundamenta Informaticae 120 (2012) 75-92, doi:10.3233/FI-2012-751. It proves 2N-2s2(N)-e2(N) for heap construction, which is algebraically equivalent to the conjectured formula. It does not prove the continued-fraction statement; the link to A092054 rests only on an OEIS comment. +- OEIS A001901: reduced Wallis numerators, "Subsequence of A000079" (powers of 2). Ordowski (2024): A001901(n) = numerator of [1;1,1/2,...,1/n]. +- OEIS A056982 (Weisstein): 4^A005187(n) = denominator of prod_{k<=n}(1-1/(4k^2)). This gives the even-index exponent. +- OEIS A001902 and A092053 (Hanna 2004): the convergent numerators are the Wallis denominators. +- N. A. Draim, "Pi in the form of a continued fraction with infinite terms", Fibonacci Quarterly 7.3 (1969) 275-276, https://www.mathstat.dal.ca/FQ/Scanned/7-3/draim.pdf: Wallis partial products equal the convergents of a continued fraction with partial numerators (n-1)n. +- Kummer/Legendre: v2(C(2m,m)) = s2(m), v2(m!) = m - s2(m). + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a092054, + author = {{math0}}, + title = {{Convergents of [1; 1/2, 1/3, ..., 1/n]: numerator + denominator = 2^(v2(n!) + v2((n+1)!)) (A092054)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a092054}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a092054/paper.pdf b/results/oeis-a092054/paper.pdf new file mode 100644 index 0000000..28fabe2 Binary files /dev/null and b/results/oeis-a092054/paper.pdf differ diff --git a/results/oeis-a092054/paper.tex b/results/oeis-a092054/paper.tex new file mode 100644 index 0000000..ac9b121 --- /dev/null +++ b/results/oeis-a092054/paper.tex @@ -0,0 +1,381 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\small, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8} +% Multi-byte characters inside listings. +\lstset{keepspaces=true, literate={ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {ℤ}{{$\mathbb{Z}$}}1 + {→}{{$\to$}}1 {∀}{{$\forall$}}1 {≤}{{$\le$}}1 {∧}{{$\wedge$}}1 {∑}{{$\sum$}}1 {∈}{{$\in$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em + +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\Z}{\mathbb{Z}} + + +\title[{Numerator plus denominator of the convergents of $[1;1/2,\dots,1/n]$}]{Numerator plus denominator of the convergents of $[1;\,1/2,\,1/3,\dots,1/n]$ is $2^{v_2(n!)+v_2((n+1)!)}$: a proof of the conjectured formula in OEIS A092054} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 21, 2026} + +\begin{document} +\begin{abstract} +For $n\ge1$ let $p_n/q_n$ be the continued fraction $[1;1/2,1/3,\dots,1/n]$ in lowest terms. +We prove that $p_n+q_n=2^{a(n)}$ with $a(n)=v_2(n!)+v_2((n+1)!)=2n+1-s_2(n)-s_2(n+1)=\sum_{k=1}^{n}\rho(\lfloor(k+1)/2\rfloor)$, where $s_2$ is the binary digit sum and $\rho$ the ruler function; this is the formula conjectured by Franklin T. Adams-Watters in 2006 in OEIS A092054, together with the entry's assertion that $p_n+q_n$ is a power of $2$. +The proof uses closed forms for scaled convergents, the integrality of $\binom{2m}{m}$, and Legendre's formula. +We found no earlier proof and classify the result as new, though it is a short consequence of classical facts and the case of even $n$ is effectively recorded in OEIS A056982. +The proof is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the listed terms and which was reviewed for fidelity and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +On February~19, 2004, Paul D. Hanna contributed to the OEIS the sequences A092053 \cite{A092053} and A092054 \cite{A092054}. They list the denominator of $c_n=[1;1/2,1/3,\dots,1/n]=1+1/(1/2+1/(1/3+\dots+1/(1/n)))$, $n\ge1$, and the base-$2$ logarithm of numerator plus denominator of $c_n$. Hanna observed that the numerators are the terms of A001902 \cite{A001901}, the reduced denominators of the partial Wallis products for $\pi/2$, and that numerator plus denominator is a power of $2$; for example $c_4=45/19$ and $45+19=2^6$. On February~2, 2006, Franklin T. Adams-Watters added the formula, marked ``It appears'', that the exponent is +\[ + a(n)=\sum_{k=1}^{n}\rho\bigl(\lfloor (k+1)/2\rfloor\bigr)=2n+1-s_2(n)-s_2(n+1)=A011371(n)+A011371(n+1), +\] +where $\rho=$ A001511 \cite{OEIS} is the ruler function, $s_2=$ A000120 \cite{OEIS} is the binary digit sum, and $A011371(m)=m-s_2(m)$ \cite{OEIS}. In the current revision (\#43, August~9, 2026) the formula is still marked ``It appears''. + +We prove the formula, together with the claim that $p_n+q_n$ is a power of $2$ (Theorem~\ref{thm:main}). Since $A011371(m)=v_2(m!)$ by Legendre's formula, the exponent is $a(n)=v_2(n!\,(n+1)!)$. The key point is that the odd part of $m!$ divides $1\cdot3\cdots(2m-1)$, because $\binom{2m}{m}$ is an integer; this makes the odd part of numerator plus denominator of the unreduced convergent equal to their $\gcd$. + +\subsection*{Prior work} +The math0 referees found no earlier proof of the formula. Related results are as follows. + +\emph{Heap construction.} M.~A. Suchenek \cite{Suchenek} analyzed the worst-case number of comparisons of Floyd's heap-construction program. In 2014 he added to A092054 the comment that $a(n-1)$ is this number for an $n$-element heap, and the formula $a(n-1)=2n-2s_2(n)-v_2(n)$, ``see Suchenek link for a proof''. Since $s_2(n-1)=s_2(n)-1+v_2(n)$, this is Adams-Watters's expression at $n-1$. But the identification of $a(n-1)$ with the comparison count is only asserted in the entry, and the abstract of \cite{Suchenek} (the referees could not obtain the full text) shows no continued-fraction content; as far as we can tell, \cite{Suchenek} proves the closed form for the heap count, not for $a(n)$. + +\emph{Wallis products.} The reduced partial Wallis products have numerators A001901 and denominators A001902 \cite{A001901}; the OEIS lists A001901 as a subsequence of the powers of $2$. In 2024 T.~Ordowski noted that A001901$(n)$/A001902$(n)$ is $[1;1,1/2,\dots,1/n]=1+1/c_n$, so that $p_n+q_n=$ A001901$(n)$. N.~A. Draim \cite{Draim} observed that the partial Wallis products are the convergents of a continued fraction with partial numerators $(n-1)n$. + +\emph{Even indices.} E.~W. Weisstein's entry A056982 \cite{A056982} records that the reduced denominator of $\prod_{k=1}^{m}(1-1/(4k^2))$ is $4^{A005187(m)}$, where $A005187(m)=2m-s_2(m)$ \cite{OEIS}. Since this product is the reciprocal of the partial Wallis product $W(2m)=1+1/c_{2m}$ of Remark~\ref{rem:wallis}, this is the case $a(2m)=4m-2s_2(m)$ of the formula, which also follows from Kummer's theorem $v_2\binom{2m}{m}=s_2(m)$. + +Searching arXiv, MathOverflow, Mathematics Stack Exchange, MathWorld, the SeqFan archives and the web, the referees found no treatment of odd $n$ and no proof of the formula. The formula is not among the statements of the formal-conjectures repository \cite{FC}. With these caveats we regard the result as new, though modest: an elementary consequence of the Wallis connection, the integrality of $\binom{2m}{m}$ and Legendre's formula. + +\section{Statement}\label{sec:statement} + +The entry A092054 \cite{A092054}, by Paul D. Hanna, February~19, 2004, reads in part (verbatim): +\begin{quote}\raggedright\small +\textsc{Name}: Base-2 logarithm of the sum of numerator and denominator of the convergents of the continued fraction expansion [1; 1/2, 1/3, 1/4, ..., 1/n, ...].\\[2pt] +\textsc{Comments}: [\dots] The sum of the numerators and the denominators equals a power of 2: A001902(n) + A092053(n) = 2\^{}a(n).\\[2pt] +\textsc{Formula}: [\dots] It appears that a(n) = Sum\_\{k=1..n\} A001511(floor((k+1)/2)). Equivalently, a(n) = 2n + 1 - A000120(n) - A000120(n+1) = A011371(n) + A011371(n+1). - \emph{Franklin T. Adams-Watters}, Feb 02 2006 +\end{quote} +The offset is $1$. Let $v_2$ be the $2$-adic valuation, $s_2(m)$ the binary digit sum, and $\rho(m)=v_2(2m)$ ($m\ge1$). + +\begin{theorem}[Adams-Watters's formula]\label{thm:main} +For $n\ge1$ write $[1;1/2,\dots,1/n]=p_n/q_n$ with $p_n,q_n$ coprime positive integers. Then $p_n+q_n=2^{a(n)}$, where +\begin{align*} + a(n)&=v_2(n!)+v_2((n+1)!)=\textstyle\sum_{k=1}^{n}\rho\bigl(\lfloor (k+1)/2\rfloor\bigr)\\ + &=2n+1-s_2(n)-s_2(n+1)=A011371(n)+A011371(n+1). +\end{align*} +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A092054.lean}, reviewed for fidelity, and frozen before the proof attempt (SHA-256 \texttt{adfff33f\dots76b2b3}). Its definitions and statement are as follows, verbatim except that the license header, the line \texttt{import Mathlib}, the docstrings, blank lines and the data checks other than \decl{conv_four} are omitted: +\begin{lstlisting}[basicstyle=\ttfamily\footnotesize] +namespace Math0.Statements.A092054 +def cfEval : List ℚ → ℚ + | [] => 0 + | [x] => x + | x :: y :: ys => x + 1 / cfEval (y :: ys) +def conv (n : ℕ) : ℚ := cfEval ((List.range n).map fun k => 1 / ((k : ℚ) + 1)) +def num (n : ℕ) : ℕ := (conv n).num.natAbs +def den (n : ℕ) : ℕ := (conv n).den +def a (n : ℕ) : ℕ := Nat.log 2 (num n + den n) +theorem conv_four : conv 4 = 45 / 19 := by decide +kernel +def ruler (m : ℕ) : ℕ := padicValNat 2 (2 * m) +def binWeight (m : ℕ) : ℕ := (Nat.digits 2 m).sum +def A011371 (m : ℕ) : ℕ := m - binWeight m +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + 2 ^ a n = num n + den n ∧ + a n = ∑ k ∈ Finset.Icc 1 n, ruler ((k + 1) / 2) ∧ + (a n : ℤ) = 2 * (n : ℤ) + 1 - (binWeight n : ℤ) - (binWeight (n + 1) : ℤ) ∧ + a n = A011371 n + A011371 (n + 1) +end Math0.Statements.A092054 +\end{lstlisting} + +\emph{Encoding.} \decl{cfEval} evaluates $[x_0;x_1,\dots,x_k]=x_0+1/(x_1+1/(\dots+1/x_k))$ over $\Q$ and \texttt{conv n} is $[1;1/2,\dots,1/n]$; all tails are positive, so the Lean convention $1/0=0$ never applies. \decl{num} and \decl{den} are $p_n$ and $q_n$, since rationals are stored in lowest terms, and \texttt{a n} is $\lfloor\log_2(p_n+q_n)\rfloor$. The OEIS $a(n)$ is the real logarithm, so the conjectured ``$a(n)=f(n)$'' means $p_n+q_n=2^{f(n)}$. The statement says exactly this through the conjuncts $2^{a(n)}=p_n+q_n$ (also the entry's power-of-$2$ claim) and $a(n)=f(n)$. \decl{ruler}, \decl{binWeight}, \decl{A011371} follow the OEIS names of A001511, A000120, A011371; the subtraction in \decl{A011371} never truncates, and the middle form is evaluated in $\Z$. Adams-Watters's three forms are equal by Lemmas~\ref{lem:legendre} and~\ref{lem:ruler}, so stating all three adds nothing. + +\emph{Checks against the OEIS.} The statement file proves the following by evaluation in the kernel (\texttt{decide +kernel}): the example $c_4=45/19$; all $67$ listed terms of A092054 (\decl{a_data}); the numerators $p_1,\dots,p_{24}$, which are the listed terms A001902$(1..24)$; all $25$ listed terms of A092053 as $q_1,\dots,q_{25}$; and the first listed terms of A001511, A000120 and A011371. A reviewer also checked every conjunct in exact arithmetic for $n<300$. + +\section{Proof}\label{sec:proof} + +We follow the Lean proof; lemmas carry the names of the corresponding declarations. Let $x_k=1/(k+1)$ for $k\ge0$, so that $c_n$ is the continued fraction of the list $(x_0,\dots,x_{n-1})$. + +\subsection{Convergents}\label{sec:cf} +For a list $\ell$ of rationals let $E(\ell)$ be its value under \decl{cfEval}: $E(())=0$, $E((x))=x$, $E((x,y,\dots))=x+1/E((y,\dots))$. For a list $\ell$ and a rational tail $t$ let $F((),t)=t$ and $F((x)\frown\ell,t)=x+1/F(\ell,t)$, where $\frown$ is concatenation. Thus $F((y_0,\dots,y_r),t)=[y_0;y_1,\dots,y_r,t]$; this is \decl{tailEval}. + +\begin{lemma}[\decl{cfEval_append_singleton}, \decl{tailEval_append}]\label{lem:tail} +For every list $\ell$ and $x,y,t\in\Q$: (a) $E(\ell\frown(y))=F(\ell,y)$; (b) $F(\ell\frown(x),t)=F(\ell,x+1/t)$. +\end{lemma} + +\begin{proof} +Induction on $\ell$. For (a): $E((y))=y=F((),y)$, $E((x,y))=x+1/y=F((x),y)$, and if $\ell=(x)\frown\ell'$ with $\ell'\ne()$, then $E(\ell\frown(y))=x+1/E(\ell'\frown(y))=x+1/F(\ell',y)=F(\ell,y)$. Part (b) follows by the same induction. +\end{proof} + +Define integer sequences by $P(0)=P(1)=1$, $Q(0)=0$, $Q(1)=1$ and, for $X\in\{P,Q\}$, +\[ + X(n+2)=X(n+1)+(n+1)(n+2)\,X(n). +\] +The sum $T=P+Q$ satisfies the same recurrence (\decl{T_succ_succ}). For instance $c_5=225/159=75/53$. + +\begin{lemma}[\decl{Q_pos}]\label{lem:qpos} +$Q(n)\ge1$ for all $n\ge1$, since $Q(1)=1$ and $Q(n+2)\ge Q(n+1)$. +\end{lemma} + +\begin{lemma}[\decl{tailEval_range}]\label{lem:moebius} +For every $m\ge0$ and every rational $t>0$, +\[ + F\bigl((x_0,\dots,x_m),\,t\bigr)=\frac{P(m+1)\,t+(m+1)P(m)}{Q(m+1)\,t+(m+1)Q(m)}, +\] +and the denominator on the right is positive. +\end{lemma} + +\begin{proof} +Induction on $m$. For $m=0$ both sides are $1+1/t=(t+1)/t$. For the step, Lemma~\ref{lem:tail}(b) gives $F((x_0,\dots,x_{m+1}),t)=F((x_0,\dots,x_m),s)$ with $s=1/(m+2)+1/t>0$. By the induction hypothesis at $s$, this equals $\bigl(P(m+1)s+(m+1)P(m)\bigr)/\bigl(Q(m+1)s+(m+1)Q(m)\bigr)$, whose denominator is positive by Lemma~\ref{lem:qpos}. Now multiply numerator and denominator by $(m+2)t>0$. The numerator becomes +\[ + P(m+1)(t+m+2)+(m+1)(m+2)\,t\,P(m)=P(m+2)\,t+(m+2)P(m+1) +\] +by the recurrence, and likewise the denominator becomes $Q(m+2)t+(m+2)Q(m+1)>0$. +\end{proof} + +\begin{corollary}[\decl{conv_eq}]\label{cor:conv} +$c_n=P(n)/Q(n)$ for every $n\ge1$. +\end{corollary} + +\begin{proof} +$c_1=E((1))=1=P(1)/Q(1)$. For $n=m+2$, Lemma~\ref{lem:tail}(a) gives $c_{m+2}=F((x_0,\dots,x_m),1/(m+2))$. Lemma~\ref{lem:moebius} with $t=1/(m+2)$ then gives +\[ + c_{m+2}=\frac{P(m+1)+(m+1)(m+2)P(m)}{Q(m+1)+(m+1)(m+2)Q(m)}=\frac{P(m+2)}{Q(m+2)}, +\] +after multiplying numerator and denominator by $m+2$. +\end{proof} + +\subsection{Closed forms} +Let $D(0)=1$ and $D(m+1)=(2m+1)D(m)$, so $D(m)=1\cdot3\cdots(2m-1)$. + +\begin{lemma}[\decl{D_odd}, \decl{D_dvd_succ}, \decl{factorial_two_mul}]\label{lem:D} +$D(m)$ is odd, $D(m)\mid D(m+1)$, and $(2m)!=2^m\,m!\,D(m)$. +\end{lemma} + +\begin{proof} +The first two claims are clear. For the third, use induction: $(2m+2)!=2(m+1)(2m+1)(2m)!=2^{m+1}(m+1)!\,D(m+1)$. +\end{proof} + +\begin{lemma}[\decl{P_closed}, \decl{T_closed}, \decl{P_odd}]\label{lem:closed} +For every $m\ge0$, +\begin{gather*} + P(2m)=D(m)^2(2m+1),\qquad P(2m+1)=D(m+1)^2,\\ + T(2m)=4^m(m!)^2,\qquad T(2m+1)=2^{2m+1}m!\,(m+1)!. +\end{gather*} +In particular $P(n)$ is odd for every $n$. +\end{lemma} + +\begin{proof} +For $m=0$ these read $P(0)=P(1)=1$, $T(0)=1$, $T(1)=2$. Assume them for $m$. Using $D(m+1)=(2m+1)D(m)$ and the recurrences, +\begin{align*} + P(2m+2)&=D(m+1)^2+(2m+1)(2m+2)D(m)^2(2m+1)=D(m+1)^2(2m+3),\\ + P(2m+3)&=D(m+1)^2(2m+3)\bigl(1+(2m+2)\bigr)=D(m+2)^2,\\ + T(2m+2)&=2^{2m+1}m!\,(m+1)!\bigl(1+(2m+1)\bigr)=4^{m+1}((m+1)!)^2,\\ + T(2m+3)&=2^{2m+2}((m+1)!)^2\bigl(1+(2m+3)\bigr)=2^{2m+3}(m+1)!\,(m+2)!. +\end{align*} +Here $(2m+2)4^m(m!)^2=2^{2m+1}m!\,(m+1)!$ and $(2m+2)2^{2m+1}m!\,(m+1)!=2^{2m+2}((m+1)!)^2$. Oddness of $P(n)$ follows from Lemma~\ref{lem:D}. +\end{proof} + +\subsection{Two-adic valuations} +Let $V(k)=v_2(k!)$. + +\begin{lemma}[\decl{odd_part}]\label{lem:oddpart} +If $m!=2^v w$ with $w$ odd, then $w\mid D(m)$. +\end{lemma} + +\begin{proof} +Since $\binom{2m}{m}\in\N$, $m!\,m!$ divides $(2m)!=2^m\,m!\,D(m)$, so $m!\mid 2^mD(m)$. Hence $w\mid 2^mD(m)$, and since $w$ is odd, $w\mid D(m)$. +\end{proof} + +\begin{lemma}[\decl{V_two_mul}, \decl{V_two_mul_add_one}]\label{lem:V} +If $m!=2^vw$ with $w$ odd, then $V(2m)=m+v$. Also $V(2m+1)=V(2m)$. +\end{lemma} + +\begin{proof} +By Lemma~\ref{lem:D}, $(2m)!=2^{m+v}\,(w\,D(m))$ with $w\,D(m)$ odd, and $(2m+1)!=(2m+1)(2m)!$. +\end{proof} + +\begin{lemma}[\decl{key}]\label{lem:key} +For every $n\ge0$ there are $e,u\in\N$ with $T(n)=2^e u$, $u\mid P(n)$ and $e=V(n)+V(n+1)$. +\end{lemma} + +\begin{proof} +If $n=2m$, write $m!=2^vw$ with $w$ odd, and take $u=w^2$ and $e=2m+2v$. Then $T(2m)=4^m(2^vw)^2=2^eu$. By Lemma~\ref{lem:oddpart}, $w^2\mid D(m)^2\mid P(2m)$. By Lemma~\ref{lem:V}, $V(2m)+V(2m+1)=2(m+v)=e$. + +If $n=2m+1$, write $m!=2^vw$ and $(m+1)!=2^{v'}w'$ with $w,w'$ odd, and take $u=ww'$ and $e=2m+1+v+v'$. Then $T(2m+1)=2^eu$. By Lemmas~\ref{lem:oddpart} and~\ref{lem:D}, $ww'\mid D(m)D(m+1)\mid D(m+1)^2=P(2m+1)$. By Lemma~\ref{lem:V}, $V(2m+1)+V(2m+2)=(m+v)+(m+1+v')=e$. +\end{proof} + +\begin{lemma}[\decl{num_add_den_eq}]\label{lem:lowest} +Let $A,B,e,u\in\N$ with $B>0$, $A$ odd, $A+B=2^eu$ and $u\mid A$. If $A/B=r/s$ in lowest terms, with $r\in\Z$, $s\ge1$ and $\gcd(|r|,s)=1$, then $|r|+s=2^e$. +\end{lemma} + +\begin{proof} +Let $g=\gcd(A,B)=\gcd(A,A+B)=\gcd(A,2^eu)$. Since $g\mid A$, $g$ is odd; as $g\mid 2^eu$, it follows that $g\mid u$. Conversely $u\mid A$ and $u\mid 2^eu$, so $u\mid g$. Hence $g=u$, and $u>0$. Write $A=uA'$ and $B=uB'$. Then $\gcd(A',B')=1$, $B'>0$ and $A/B=A'/B'$, so $r=A'$ and $s=B'$. Finally, $u(A'+B')=A+B=2^eu$ gives $A'+B'=2^e$. +\end{proof} + +\subsection{The other forms of the exponent} + +\begin{lemma}[\decl{V_eq}, \decl{V_add_binWeight}; Legendre]\label{lem:legendre} +$V(m)=m-s_2(m)=A011371(m)$ and $V(m)+s_2(m)=m$ for every $m\ge0$. +\end{lemma} + +\begin{proof} +This is Legendre's formula $(p-1)\,v_p(m!)=m-s_p(m)$ for $p=2$, which is \decl{sub_one_mul_padicValNat_factorial} in Mathlib, together with $s_2(m)\le m$. +\end{proof} + +\begin{lemma}[\decl{V_add_two}, \decl{ruler_sum}]\label{lem:ruler} +For every $n\ge0$, $V(n+2)=V(n)+\rho(\lfloor(n+2)/2\rfloor)$, and $\sum_{k=1}^{n}\rho(\lfloor(k+1)/2\rfloor)=V(n)+V(n+1)$. +\end{lemma} + +\begin{proof} +We have $V(n+2)=V(n)+v_2(n+1)+v_2(n+2)$. Exactly one of $n+1$ and $n+2$ is even, and it equals $2j$ with $j=\lfloor(n+2)/2\rfloor$. The odd one has valuation $0$, so $v_2(n+1)+v_2(n+2)=v_2(2j)=\rho(j)$. The sum identity follows by induction on $n$: both sides vanish at $n=0$, and the new term $k=n+1$ is $\rho(\lfloor(n+2)/2\rfloor)=V(n+2)-V(n)$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +Let $n\ge1$ and take $e,u$ from Lemma~\ref{lem:key}. By Corollary~\ref{cor:conv}, $c_n=P(n)/Q(n)$, where $Q(n)>0$ (Lemma~\ref{lem:qpos}) and $P(n)$ is odd (Lemma~\ref{lem:closed}). Lemma~\ref{lem:lowest} with $A=P(n)$ and $B=Q(n)$ gives $p_n+q_n=2^e$. Hence $a(n)=\lfloor\log_2 2^e\rfloor=e=V(n)+V(n+1)$ and $2^{a(n)}=p_n+q_n$. The ruler-sum form is Lemma~\ref{lem:ruler}, and the form $A011371(n)+A011371(n+1)$ is Lemma~\ref{lem:legendre}. Finally, $V(n)=n-s_2(n)$ and $V(n+1)=n+1-s_2(n+1)$ in $\Z$, which gives $a(n)=2n+1-s_2(n)-s_2(n+1)$. +\end{proof} + +\begin{remark}\label{rem:wallis} +(Not formalized.) (1) In W.~Lang's indexing \cite{A001901}, the partial Wallis products are $W(n)=\prod_{k=0}^{n}N(k)/D'(k)$, with $N(0)=1$, $N(k)=2\lfloor(k+1)/2\rfloor$ for $k\ge1$, and $D'(k)=2\lfloor k/2\rfloor+1$. Lemma~\ref{lem:closed} shows that $\prod_{k\le n}N(k)=T(n)$ and $\prod_{k\le n}D'(k)=P(n)$. Hence $W(n)=T(n)/P(n)=1+1/c_n$. As $\gcd(T(n),P(n))=\gcd(P(n),Q(n))$, $W(n)$ reduces to $2^{a(n)}/p_n$, confirming Hanna's and Ordowski's identifications and A001901$(n)=2^{a(n)}$. (2) Suchenek's formula $a(n-1)=2n-2s_2(n)-v_2(n)$ ($n\ge2$) follows; his comment that this is the heap-construction count rests on \cite{Suchenek}. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +The proof is in the file \path{lean/Math0/Frontier/OEIS/A092054.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file and the audit commands in \path{lean/Math0/Audit.lean}. It contains the private definitions \decl{tailEval}, \decl{pq} ($k\mapsto x_k$), \decl{P}, \decl{Q}, \decl{D} and \decl{V}, the private lemmas named in Section~\ref{sec:proof}, and a few auxiliary lemmas. The main declaration is \decl{Math0.Frontier.A092054.result}, of type \decl{Math0.Statements.A092054.statement}, and the file ends with the command \texttt{\#math0\_settles Math0.Frontier.A092054.result Math0.Statements.A092054.statement}. + +One step has no counterpart in Section~\ref{sec:proof}: because the type ascription \texttt{(k : ℚ)} makes the bound variable \texttt{k} rational, Lean elaborates the list in \decl{conv} through a coercion from \texttt{List ℕ} to \texttt{List ℚ} via the list monad, and the lemma \decl{conv_eq_pq} rewrites it to the plain list $(x_0,\dots,x_{n-1})$. The proof contains no \texttt{sorry}, no \texttt{native\_decide} and no \texttt{maxHeartbeats} option, and uses \texttt{decide} only for the base cases $0= 1, a(n)/A093727(n) = A317974(n+1)/A138573(n) as rational numbers. + +## Assessment + +The convergent is c_n = U(n+1)/U(n) = U(n+1)conj(U(n))/|U(n)|^2 for the Gaussian continuants U. A138573 already records that the denominator |U(n)|^2 equals A138573(n). The numerator's imaginary part Q(n) = Im(U(n+1)conj U(n)) is built from the same characteristic roots, so it satisfies the same order-4 recurrence. Matching four initial values identifies it with A317974(n+1). The whole argument is standard continued-fraction and linear-recurrence bookkeeping, plus a short check that a(n)/A093727(n) is just Im c_n. It fits in well under a page and leans mainly on a formula already in a cross-referenced entry. + +*Follows from:* The classical continuant formula c_n = U(n+1)/U(n) for U(n) = (1+i)U(n-1) + U(n-2), together with Peter Bala's 2014 formula in A138573: A138573(n) = |U(n)|^2, and the o.g.f. as a Hadamard product of x/(1-(1+i)x-x^2) and x/(1-(1-i)x-x^2). The same Hadamard-product argument puts Im(U(n+1) conj U(n)) in the signature-(2,2,2,-1) recurrence space, so four initial values match it with A317974(n+1). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A093726](https://oeis.org/A093726) as [`Math0.Statements.A093726.statement`](../../lean/Math0/Statements/OEIS/A093726.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A093726.lean`](../../lean/Math0/Frontier/OEIS/A093726.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: a(n)/A093727(n) = A317974(n+1)/A138573(n). - _Zhuorui He_, Jun 16 2026 + +Referees: OEIS A093726 rev #13 (Jun 20 2026): the formula is still marked "Conjecture: a(n)/A093727(n) = A317974(n+1)/A138573(n). - Zhuorui He, Jun 16 2026"; there is no later %E edit recording a proof. Related prior work: Peter Bala's 2014 formula in OEIS A138573 that A138573(n) = |U(n)|^2 for the Gaussian Lucas sequence U(n) = (1+i)U(n-1) + U(n-2), which covers the denominator part only. A317974 (rev #35, Jun 30 2026) has no relevant formula. Not covered by S. Fried, "Further proofs of conjectures from the OEIS", arXiv:2607.24832 (Jul 2026); I checked its full text for the A-numbers. Fried's earlier papers (arXiv:2410.07237; JIS 2025 and 2026) predate the conjecture. No MathOverflow, Math StackExchange, SeqFan or arXiv resolution found. Sources: https://raw.githubusercontent.com/oeis/oeisdata/main/seq/A093/A093726.seq, https://arxiv.org/abs/2607.24832 + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a093726, + author = {{math0}}, + title = {{Imaginary parts of the convergents of [1+i; 1+i, 1+i, ...] are A317974(n+1)/A138573(n)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a093726}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a093726/paper.pdf b/results/oeis-a093726/paper.pdf new file mode 100644 index 0000000..b1db26e Binary files /dev/null and b/results/oeis-a093726/paper.pdf differ diff --git a/results/oeis-a093726/paper.tex b/results/oeis-a093726/paper.tex new file mode 100644 index 0000000..38ae2e1 --- /dev/null +++ b/results/oeis-a093726/paper.tex @@ -0,0 +1,391 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 + {→}{{$\to$}}1 {≤}{{$\le$}}1 {×}{{$\times$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +\newcommand{\li}{\lstinline[basicstyle=\ttfamily]} +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\cj}[1]{\overline{#1}} +\newcommand{\seq}[1]{\mathrm{A#1}} +\DeclareMathOperator{\re}{Re} +\DeclareMathOperator{\im}{Im} +\DeclareMathOperator{\den}{den} +\DeclareMathOperator{\num}{num} + +\title[Convergents of $\lbrack1+i;1+i,1+i,\dots\rbrack$]{The imaginary parts of the convergents of +$\lbrack1+i;\,1+i,\,1+i,\dots\rbrack$ are $\mathrm{A317974}(n+1)/\mathrm{A138573}(n)$} +\hypersetup{pdftitle={The imaginary parts of the convergents of [1+i; 1+i, 1+i, ...] are A317974(n+1)/A138573(n)}, + pdfauthor={math0}} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +Let $c_n$ be the $n$-th convergent of the continued fraction $(1+i)+1/((1+i)+1/((1+i)+\cdots))$ and write $c_n=(\seq{093725}(n)+\seq{093726}(n)\,i)/\seq{093727}(n)$, where $\seq{093727}(n)$ is the least positive integer $d$ with $dc_n\in\Z[i]$. +We prove Zhuorui He's 2026 conjecture from OEIS A093726 that $\seq{093726}(n)/\seq{093727}(n)=\seq{317974}(n+1)/\seq{138573}(n)$ for all $n\ge1$, i.e.\ $\im c_n=\seq{317974}(n+1)/\seq{138573}(n)$, where both sequences satisfy $u(n)=2(u(n-1)+u(n-2)+u(n-3))-u(n-4)$. +The proof writes $c_n=U(n+1)/U(n)$ for the Gaussian continuants $U$ and identifies $|U(n)|^2$ (as observed by P.~Bala for A138573) and $\im\bigl(U(n+1)\cj{U(n)}\bigr)$ with the two recurrence sequences. +We know of no earlier proof, so we classify the result as new, although the argument is elementary. +The theorem is verified in Lean~4 against the frozen, fidelity-reviewed math0 formalization of the conjecture, whose definitions are checked by the kernel against the OEIS data. +\end{abstract} +\maketitle + +\section{Introduction} + +OEIS A093726 \cite{A093726}, contributed by Robert G.~Wilson~v on March~11, 2004, lists the numerators of the imaginary parts of the convergents of the periodic Gaussian continued fraction +\[ +(1+i)+\cfrac{1}{(1+i)+\cfrac{1}{(1+i)+\cdots}}\,; +\] +its companions A093725 and A093727 \cite{A093725} list the numerators of the real parts and the common denominators. The convergents begin $1+i$, $(3+i)/2$, $(8+4i)/5$, $(6+3i)/4$, $(23+11i)/15$. On June~16, 2026, Zhuorui He corrected the definition of A093726, extended its data to $30$ terms, added these worked examples, and added the conjecture +\[ +\seq{093726}(n)/\seq{093727}(n)=\seq{317974}(n+1)/\seq{138573}(n)\qquad(n\ge1), +\] +in which A317974 \cite{A317974} (N.~J.~A. Sloane, 2018) and A138573 \cite{A138573} (B.~Cloitre, 2008) are the solutions of the recurrence with signature $(2,2,2,-1)$, +\begin{equation}\label{eq:rec} +u(n)=2u(n-1)+2u(n-2)+2u(n-3)-u(n-4)\qquad(n\ge4), +\end{equation} +with initial terms $0,0,1,1$ and $0,1,2,5$ respectively. We prove the conjecture (Theorem~\ref{thm:main}). + +\subsection*{Prior work and status} +In A138573, Peter Bala (March~4, 2014) noted that $\seq{138573}(n)=|U(n)|^2$ for the Lucas sequence $U(0)=0$, $U(1)=1$, $U(n)=(1+i)U(n-1)+U(n-2)$ in the Gaussian integers \cite{A138573}. Since $U(n)$ is the $n$-th continuant of the continued fraction, this explains the denominators $\seq{138573}(n)$ in the conjecture. We found no statement, in OEIS or elsewhere, connecting A317974 with these convergents; besides its recurrence and programs, the entry A317974 contains a generating function (C.~Barker), a growth rate (A.~H.~M. Smeets) and links to Coxeter's paper on loxodromic sequences of tangent spheres \cite{Cox} and to MathWorld. As of revision~\#13 of A093726 (June~20, 2026) the formula is still marked as a conjecture, and no later edit records a proof. The math0 referees searched arXiv, MathOverflow, Mathematics Stack Exchange and the SeqFan archives and found no proof or counterexample; the recent collection of proofs of OEIS conjectures by S.~Fried \cite{Fried} does not treat A093726, A093727, A317974 or A138573. We therefore classify the result as new. It is elementary: the new ingredient, beyond the classical continuant formula $c_n=U(n+1)/U(n)$ and Bala's observation, is the identification of $\im\bigl(U(n+1)\cj{U(n)}\bigr)$ with $\seq{317974}(n+1)$. + +\subsection*{Method} +Put $S(n)=|U(n)|^2$ and $P(n)+iQ(n)=U(n+1)\cj{U(n)}$. Then $c_n=(P(n)+iQ(n))/S(n)$ for $n\ge1$. Three integer identities relating $P,Q,S$ at $n$ and $n+1$ drive an induction for this closed form, and imply that $S$ and $Q$ satisfy \eqref{eq:rec}; comparing four initial values gives $S(n)=\seq{138573}(n)$ and $Q(n)=\seq{317974}(n+1)$. Finally, the left-hand side of the conjecture is exactly $\im c_n$. + +\section{Statement}\label{sec:statement} + +For $x\in\Q$ let $\num x\in\Z$ and $\den x\ge1$ be its numerator and denominator in lowest terms. For a Gaussian rational $z=x+yi$ ($x,y\in\Q$) let +\[ +\den z=\operatorname{lcm}(\den x,\den y),\qquad \num z=(\den z)\,z\in\Z[i]. +\] +Thus $\den z$ is the least positive integer $d$ with $dz\in\Z[i]$; this is the convention of Mathematica's \texttt{Numerator} and \texttt{Denominator} for Gaussian rationals. + +\begin{definition}\label{def:seq} +Let $c_1=1+i$ and $c_{n+1}=(1+i)+1/c_n$ for $n\ge1$, so that $c_n=[1+i;1+i,\dots,1+i]$ has $n$ partial quotients. (This is well defined: if $\re c_n\ge1$ then $\re(1/c_n)=\re c_n/|c_n|^2>0$, so $\re c_{n+1}\ge1$.) Set +\[ +\seq{093725}(n)=\re\num c_n,\qquad a(n)=\seq{093726}(n)=\im\num c_n,\qquad \seq{093727}(n)=\den c_n. +\] +Let $\seq{317974}$ and $\seq{138573}$ be the sequences (offset $0$) satisfying \eqref{eq:rec} with initial terms $0,0,1,1$ and $0,1,2,5$. +\end{definition} + +For example, $c_4=\frac32+\frac34 i=(6+3i)/4$, so $\seq{093725}(4)=6$, $a(4)=3$, $\seq{093727}(4)=4$, as in the examples of A093726. +The FORMULA section of A093726 reads, verbatim: +\begin{quote} +{\small\raggedright\texttt{Conjecture: a(n)/A093727(n) = A317974(n+1)/A138573(n). - \_Zhuorui He\_, Jun 16 2026}\par} +\end{quote} + +\begin{theorem}\label{thm:main} +For every $n\ge1$, +\[ +\frac{a(n)}{\seq{093727}(n)}=\frac{\seq{317974}(n+1)}{\seq{138573}(n)} +\] +as rational numbers. +\end{theorem} + +In the proof (Section~\ref{sec:proof}) we show that both sides equal $\im c_n$. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A093726.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{5d599ac4\ldots 08f83a0ba}) before any proof attempt. Its definitions and the statement read as follows (verbatim; docstrings and the data theorems are omitted): +\begin{lstlisting} +namespace Math0.Statements.A093726 +def gadd (z w : ℚ × ℚ) : ℚ × ℚ := (z.1 + w.1, z.2 + w.2) +def ginv (z : ℚ × ℚ) : ℚ × ℚ := + (z.1 / (z.1 * z.1 + z.2 * z.2), -z.2 / (z.1 * z.1 + z.2 * z.2)) +def cfValue : List (ℚ × ℚ) → ℚ × ℚ + | [] => (0, 0) + | [x] => x + | x :: xs => gadd x (ginv (cfValue xs)) +def conv (n : ℕ) : ℚ × ℚ := cfValue (List.replicate n (1, 1)) +def gden (z : ℚ × ℚ) : ℕ := Nat.lcm z.1.den z.2.den +def gnumIm (z : ℚ × ℚ) : ℤ := z.2.num * ((gden z / z.2.den : ℕ) : ℤ) +def a (n : ℕ) : ℤ := gnumIm (conv n) +def A093727 (n : ℕ) : ℕ := gden (conv n) +def A317974 : ℕ → ℤ + | 0 => 0 + | 1 => 0 + | 2 => 1 + | 3 => 1 + | n + 4 => 2 * (A317974 (n + 3) + A317974 (n + 2) + A317974 (n + 1)) - A317974 n +def A138573 : ℕ → ℤ + | 0 => 0 + | 1 => 1 + | 2 => 2 + | 3 => 5 + | n + 4 => 2 * A138573 (n + 3) + 2 * A138573 (n + 2) + 2 * A138573 (n + 1) - A138573 n +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + (a n : ℚ) / (A093727 n : ℚ) = (A317974 (n + 1) : ℚ) / (A138573 n : ℚ) +\end{lstlisting} + +\subsection*{How the definitions encode the entry} +A Gaussian rational $x+yi$ is the pair $(x,y)\in\Q\times\Q$; \decl{gadd} is addition and \decl{ginv} is $1/(x+yi)=(x-yi)/(x^2+y^2)$ (Lean's division by $0$ returns $0$, but \decl{ginv} is only ever applied to nonzero values here). \decl{cfValue} evaluates $x_1+1/(x_2+\dots+1/x_n)$, like Mathematica's \texttt{FromContinuedFraction}, and \li|conv n| follows the entry's program \decl|Table[Im[Numerator[FromContinuedFraction[Table[1+I,{n}]]]],{n,30}]|. Since \li|List.replicate (n+2) (1, 1)| is $(1,1)$ followed by a nonempty list, \li|conv (n + 2)| unfolds to \li|gadd (1, 1) (ginv (conv (n + 1)))|, and \li|conv 1 = (1, 1)|; so \li|conv n| is $c_n$ for $n\ge1$. \decl{gden} is $\den z$, and since $\den y\mid\den z$ the natural-number quotient in \decl{gnumIm} is exact, so \li|gnumIm z| $=\num y\cdot(\den z/\den y)=\im\num z$. The sequences A317974 and A138573 are their defining recurrences, with offset $0$; A093726 and A093727 have offset $1$, matching the hypothesis $1\le n$. The statement is an equality in $\Q$, and both denominators are positive. + +The file checks in the kernel (\texttt{decide +kernel}) that \decl{a} reproduces all $30$ listed terms of A093726, \decl{A093727} all $28$ listed terms of A093727, and \decl{A317974}, \decl{A138573} their first $20$ listed terms (theorems \decl{a_data}, \decl{A093727_data}, \decl{A317974_data}, \decl{A138573_data}). No instance of the conjecture is checked in the statement file. + +\begin{remark}[Reading of the name]\label{rem:reading} +The name of A093726 (``the numerator of the imaginary part of the convergents'') could also be read as $\num(\im c_n)$. The formalization uses $\im\num c_n$, which is what the entry's program computes and what its examples use (``(6+3*i)/4, so A093725(4)=6, a(4)=3 and A093727(4)=4''). The two readings agree on all listed terms but first differ at $n=42$ (computer check, not formalized): $\im c_{42}=18854485653829/25378408048970$ in lowest terms, while $\seq{093727}(42)=329919304636610=13\cdot25378408048970$, so $a(42)=13\cdot18854485653829$. Under the other reading the left side of the conjecture would be $\im c_{42}/13$, and the conjecture would fail at $n=42$. +\end{remark} + +\section{Proof}\label{sec:proof} + +We follow the Lean proof in \path{lean/Math0/Frontier/OEIS/A093726.lean}; the names of its (private) lemmas are given in brackets. + +\subsection{Continuants} +Define Gaussian integers $U(n)$, stored in Lean as integer pairs, by +\[ +U(0)=0,\qquad U(1)=1,\qquad U(k+2)=(1+i)\,U(k+1)+U(k) +\] +(\decl{U}, \decl{step}), and put +\[ +S(n)=|U(n)|^2,\qquad P(n)+iQ(n)=W(n):=U(n+1)\,\cj{U(n)}\qquad(P(n),Q(n)\in\Z) +\] +(\decl{S}, \decl{P}, \decl{Q}). In coordinates, if $U(n)=x_0+y_0i$ and $U(n+1)=x_1+y_1i$, then $P(n)=x_1x_0+y_1y_0$ and $Q(n)=y_1x_0-x_1y_0$. The first values are +\[ +\begin{array}{c|ccccccc} +n&0&1&2&3&4&5&6\\\hline +U(n)&0&1&1+i&1+2i&4i&-3+6i&-9+7i\\ +S(n)&0&1&2&5&16&45&130\\ +P(n)&0&1&3&8&24&69&199\\ +Q(n)&0&1&1&4&12&33&97 +\end{array} +\] + +\begin{lemma}\label{lem:step} +For every $n\ge0$: +\begin{enumerate} +\item[(a)] $P(n+1)=S(n+1)+P(n)$; +\item[(b)] $Q(n+1)=S(n+1)-Q(n)$; +\item[(c)] $P(n)^2+Q(n)^2=S(n)\,S(n+1)$; +\item[(d)] $S(n+2)=2S(n+1)+S(n)+2P(n)-2Q(n)$. +\end{enumerate} +\end{lemma} + +\begin{proof} +We have +$W(n+1)=\bigl((1+i)U(n+1)+U(n)\bigr)\cj{U(n+1)}=(1+i)S(n+1)+\cj{W(n)}$; its real and imaginary parts give (a) and (b). (c) is $|W(n)|^2=|U(n+1)|^2|U(n)|^2$. For (d), expand, using $|1+i|^2=2$, +$S(n+2)=|(1+i)U(n+1)+U(n)|^2=2S(n+1)+S(n)+2\re\bigl((1+i)W(n)\bigr)$ and use $\re((1+i)(P+iQ))=P-Q$. +In Lean, (a) and (b) are proved inside \decl{conv_eq} by unfolding $U(n+2)$ through \decl{step} and normalizing with \texttt{ring}, and (c) by \texttt{ring} (the Lagrange identity $(x_1x_0+y_1y_0)^2+(y_1x_0-x_1y_0)^2=(x_0^2+y_0^2)(x_1^2+y_1^2)$), in the instances needed there. Identity (d) is used only in our derivation by hand of Lemma~\ref{lem:rec}; the Lean proof does not need it. +\end{proof} + +\begin{lemma}[\decl{S_rec}, \decl{Q_rec}]\label{lem:rec} +$S$ and $Q$ satisfy \eqref{eq:rec}: for every $n\ge0$, +\begin{align*} +S(n+4)&=2S(n+3)+2S(n+2)+2S(n+1)-S(n),\\ +Q(n+4)&=2Q(n+3)+2Q(n+2)+2Q(n+1)-Q(n). +\end{align*} +\end{lemma} + +\begin{proof} +In Lean, $U(n+2),\dots,U(n+5)$ are unfolded through \decl{step} into integer-linear expressions in the four coordinates $x_0,y_0,x_1,y_1$ of $U(n)$ and $U(n+1)$; both identities then become polynomial identities in $x_0,y_0,x_1,y_1$, which \texttt{ring} verifies. We give a derivation by hand from Lemma~\ref{lem:step}. + +Put $D(n)=P(n)-Q(n)$. By (a) and (b), $D(n+1)=P(n)+Q(n)$, and hence +$D(n+2)=P(n+1)+Q(n+1)=2S(n+1)+D(n)$. By (d), $2D(n)=T(n)$ with $T(n)=S(n+2)-2S(n+1)-S(n)$. Therefore $T(n+2)=2D(n+2)=4S(n+1)+T(n)$, that is, +\[ +S(n+4)-2S(n+3)-S(n+2)=4S(n+1)+S(n+2)-2S(n+1)-S(n), +\] +which is the recurrence for $S$. For $Q$, let $R(n)=Q(n+4)-2Q(n+3)-2Q(n+2)-2Q(n+1)+Q(n)$. By (b), $Q(m)+Q(m+1)=S(m+1)$ for all $m\ge0$, so $R(n)+R(n+1)$ is the recurrence expression for $S$ at $n+1$, which vanishes. Hence $R(n)=(-1)^nR(0)$, and $R(0)=12-2\cdot4-2\cdot1-2\cdot1+0=0$. +\end{proof} + +\begin{lemma}[\decl{S_eq_Q_eq}]\label{lem:ident} +For every $n\ge0$, $S(n)=\seq{138573}(n)$ and $Q(n)=\seq{317974}(n+1)$. +\end{lemma} + +\begin{proof} +The Lean proof shows by induction on $n$ that the four equalities $S(n+j)=\seq{138573}(n+j)$, $j=0,1,2,3$, and the four equalities $Q(n+j)=\seq{317974}(n+j+1)$, $j=0,1,2,3$, hold. For $n=0$ these say that $S(0),\dots,S(3)$ are $0,1,2,5$ and that $Q(0),\dots,Q(3)$ are $0,1,1,4$, i.e.\ $\seq{317974}(1),\dots,\seq{317974}(4)$; the kernel evaluates both sides (\texttt{decide}). For the step, the window shifts by one and the new value is supplied by Lemma~\ref{lem:rec} and the recurrence~\eqref{eq:rec}, which $\seq{138573}$ and $n\mapsto\seq{317974}(n+1)$ both satisfy. +\end{proof} + +\begin{lemma}[\decl{A138573_mono}, \decl{A138573_pos}, \decl{S_pos}]\label{lem:pos} +$\seq{138573}$ is nonnegative and nondecreasing, and $\seq{138573}(n)\ge1$ for $n\ge1$. Hence $S(n)\ne0$ for $n\ge1$. +\end{lemma} + +\begin{proof} +Write $u=\seq{138573}$. We show $0\le u(n)\le u(n+1)\le u(n+2)\le u(n+3)$ by induction on $n$; for $n=0$ this is $0\le0\le1\le2\le5$. For the step, $0\le u(n+1)$ follows from $0\le u(n)\le u(n+1)$, and +\[ +u(n+4)-u(n+3)=\bigl(u(n+3)-u(n)\bigr)+2u(n+2)+2u(n+1)\ge0. +\] +Since $u(1)=1$, monotonicity gives $u(n)\ge1$ for $n\ge1$, and $S(n)=u(n)$ by Lemma~\ref{lem:ident}. +\end{proof} + +\subsection{The convergents} + +\begin{lemma}[\decl{alg}]\label{lem:alg} +Let $p,q,s,s'\in\Q$ with $s,s'\ne0$ and $p^2+q^2=ss'$. Then +\[ +(1+i)+\frac{1}{(p+qi)/s}=\frac{(s'+p)+(s'-q)\,i}{s'}. +\] +\end{lemma} + +\begin{proof} +We have $(p/s)^2+(q/s)^2=s'/s\neq0$, so $1/((p+qi)/s)=(p-qi)/s\cdot s/s'=(p-qi)/s'$, and $(1+i)+(p-qi)/s'=((s'+p)+(s'-q)i)/s'$. In Lean the statement reads \li|gadd (1, 1) (ginv (p / s, q / s)) = ((s' + p) / s', (s' - q) / s')|, and its proof derives $(p/s)^2+(q/s)^2=s'/s$ by \texttt{field\_simp} and \texttt{linear\_combination}, then closes the two coordinates by \texttt{field\_simp} and \texttt{ring}. +\end{proof} + +\begin{proposition}[\decl{conv_eq}]\label{prop:conv} +For every $n\ge1$, +\[ +c_n=\frac{P(n)+Q(n)\,i}{S(n)}=\frac{U(n+1)}{U(n)}. +\] +In particular $\im c_n=Q(n)/S(n)=\seq{317974}(n+1)/\seq{138573}(n)$. +\end{proposition} + +\begin{proof} +Induction on $n$. For $n=1$: $P(1)=Q(1)=S(1)=1$ (checked by \texttt{decide}) and $c_1=1+i$. Suppose the claim holds for $n\ge1$. Put $p=P(n)$, $q=Q(n)$, $s=S(n)$, $s'=S(n+1)$. Then $s,s'\ne0$ by Lemma~\ref{lem:pos} and $p^2+q^2=ss'$ by Lemma~\ref{lem:step}(c), so Lemma~\ref{lem:alg} gives +\[ +c_{n+1}=(1+i)+\frac1{c_n}=\frac{(S(n+1)+P(n))+(S(n+1)-Q(n))\,i}{S(n+1)}=\frac{P(n+1)+Q(n+1)\,i}{S(n+1)} +\] +by Lemma~\ref{lem:step}(a),(b). The second form of $c_n$ follows from $W(n)/S(n)=U(n+1)\cj{U(n)}/|U(n)|^2$ (it is not needed in Lean); the last statement follows from Lemma~\ref{lem:ident}. +\end{proof} + +\subsection{Proof of Theorem~\ref{thm:main}} +Let $n\ge1$ and $c_n=x+yi$, and put $L=\den c_n=\operatorname{lcm}(\den x,\den y)$, which is positive. Since $\den y\mid L$, +\[ +\frac{a(n)}{\seq{093727}(n)}=\frac{\num y\cdot(L/\den y)}{L}=\frac{\num y}{\den y}=y=\im c_n. +\] +In Lean this is the step \texttt{hl} of \decl{result}, using \decl{Nat.dvd_lcm_right}, \decl{Nat.cast_div} and \decl{Rat.num_div_den}. By Proposition~\ref{prop:conv}, $\im c_n=\seq{317974}(n+1)/\seq{138573}(n)$. \qed + +\begin{remark}[Consequences, not formalized] +(i) Lemma~\ref{lem:step}(b) and Lemma~\ref{lem:ident} give $\seq{317974}(n)+\seq{317974}(n+1)=\seq{138573}(n)$ for $n\ge0$; this also follows directly from the generating functions $x^2(1-x)/(1-2x-2x^2-2x^3+x^4)$ and $x(1-x)(1+x)/(1-2x-2x^2-2x^3+x^4)$ recorded in the two entries. +(ii) By Lemma~\ref{lem:step}(a) and $P(0)=0$, $\re c_n=P(n)/S(n)=\bigl(\sum_{k=1}^n\seq{138573}(k)\bigr)/\seq{138573}(n)$. +(iii) With $g_n=\gcd(P(n),Q(n),S(n))$, one has $\seq{093727}(n)=S(n)/g_n$ (because $dc_n\in\Z[i]$ iff $S(n)\mid dP(n)$ and $S(n)\mid dQ(n)$, iff $S(n)/g_n\mid d$), $a(n)=Q(n)/g_n$ and $\seq{093725}(n)=P(n)/g_n$. For example $g_4=4$, $g_5=3$, and $g_{42}=15457$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and audit} +The proof is the file \path{lean/Math0/Frontier/OEIS/A093726.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. The main declaration is \decl{Math0.Frontier.A093726.result}, of type \decl{Math0.Statements.A093726.statement}; the auxiliary definitions \decl{step}, \decl{U}, \decl{S}, \decl{P}, \decl{Q} and the lemmas \decl{S_rec}, \decl{Q_rec}, \decl{S_eq_Q_eq}, \decl{A138573_mono}, \decl{A138573_pos}, \decl{S_pos}, \decl{alg}, \decl{conv_eq} are private. The file uses no \texttt{sorry}, \texttt{native\_decide}, \texttt{axiom} or \texttt{set\_option}; the only finite computations are the base cases, closed by \texttt{decide}, which the kernel checks. The frozen statement file was not modified. The proof file ends with +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +#math0_settles Math0.Frontier.A093726.result Math0.Statements.A093726.statement +\end{lstlisting} +a command defined in \path{lean/Math0/Audit.lean} for statements formalized by math0. It fails unless \decl{statement} is a \texttt{Prop}-valued definition without universe parameters, the type of \decl{result} is syntactically \decl{statement} or its negation (up to metadata, without unfolding), and both depend only on the axioms \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (which excludes \decl{sorryAx}, \texttt{native\_decide} and custom axioms). Compiling the file with \texttt{lake env lean} reports: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize,belowskip=0pt] +math0 audit: 'Math0.Statements.A093726.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A093726.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A093726.result' proves 'Math0.Statements.A093726.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use (the statement is math0's own formalization). To reproduce, run \path{scripts/verify.sh}: it fetches the Mathlib cache, builds the library with \texttt{lake build} (re-running every audit), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and counts the passed statement checks. + +{\footnotesize\raggedright +\begin{thebibliography}{99} + +\bibitem{Cox} +H.~S.~M. Coxeter, \emph{Loxodromic sequences of tangent spheres}, Aequationes Math.\ \textbf{1} (1968), 104--121. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Fried} +S.~Fried, \emph{Further proofs of conjectures from the OEIS}, arXiv:2607.24832, 2026. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput.\ Sci.\ \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A093725} +The OEIS Foundation Inc., A093725 and A093727 (R.~G. Wilson~v, Mar.~11, 2004), \url{https://oeis.org/A093725}, \url{https://oeis.org/A093727}. + +\bibitem{A093726} +The OEIS Foundation Inc., A093726 (R.~G. Wilson~v, Mar.~11, 2004; definition corrected and conjecture added by Z.~He, Jun.~16, 2026), \url{https://oeis.org/A093726}. + +\bibitem{A138573} +The OEIS Foundation Inc., A138573 (B.~Cloitre, May~12, 2008; formulas by P.~Bala, Mar.~4, 2014), \url{https://oeis.org/A138573}. + +\bibitem{A317974} +The OEIS Foundation Inc., A317974 (N.~J.~A. Sloane, Sep.~3, 2018), \url{https://oeis.org/A317974}. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a097154/README.md b/results/oeis-a097154/README.md new file mode 100644 index 0000000..8abb234 --- /dev/null +++ b/results/oeis-a097154/README.md @@ -0,0 +1,56 @@ +# The only fixed points of reverse(x) - maxdigit(x) are 0 and 89 + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Sequences and series +**Source problem:** OEIS A097154 +**Date:** 2026-10-19 + +## Result + +For a natural number x, let rev(x) be its decimal reversal (rev 0 = 0, trailing zeros are dropped) and maxdig(x) its largest decimal digit (maxdig 0 = 0). Let f(x) = rev(x) - maxdig(x). Then f(x) = x if and only if x = 0 or x = 89. + +## Assessment + +A fixed point satisfies rev(x) = x + maxdig(x). Reversal keeps the digit sum, so maxdig(x) must be divisible by 9, which leaves only rev(x) = x + 9. Comparing the leading and units digits mod 10 and bounding the middle block then gives x = 10a + (a+1), and the largest-digit condition picks out 89. That is under a page of textbook digit arithmetic that a competent mathematician would find quickly. The entry itself carries the keyword 'easy', and the length of the Lean proof reflects formalization effort, not mathematical depth. + +*Follows from:* The standard fact that a number is congruent to its digit sum mod 9, so rev(x) ≡ x (mod 9). This forces maxdig(x) = 9 at a nonzero fixed point. A units-digit comparison mod 10 and a size bound then finish it. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A097154](https://oeis.org/A097154) as [`Math0.Statements.A097154.statement`](../../lean/Math0/Statements/OEIS/A097154.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A097154.lean`](../../lean/Math0/Frontier/OEIS/A097154.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "a(89)=-1 because 89 is the first number that will not reach zero: 98-9=89. It is conjectured that 0 and 89 are the only fixed points of f." (A097154, entry by _Jason Earls_, Aug 01 2004. The same sentence appears in A097155 and A097157.) + +Referees: **OEIS (local mirror, cross-checked against the current raw GitHub oeisdata files).** +- A097154 (#4, Dec 15 2017), A097155 (#11, last edited Aug 29 2025) and A097157 (#3) all still say "It is conjectured that 0 and 89 are the only fixed points of f". +- None has an %E line, comment, formula or link recording a proof or counterexample. A097155's only %E is a 2011 data correction by Harvey P. Dale. +- The cross-referenced entries A097153, A097156 and A097158 (Earls, Aug 2004; extensions by Robert G. Wilson v and Klaus Brockhaus) are purely computational. +- A grep of the whole local oeisdata mirror finds no other entry that references A097153 through A097158. + +**Web searches.** Queries covered the exact map text, "reversal minus largest digit", SeqFan 2004, Math StackExchange/MathOverflow-style phrasing, and an extended search. None found a proof. +- Hits were only the OEIS pages themselves. +- Unrelated digit-reversal work also came up: arXiv 2410.11784 (1089 attractor), arXiv 2404.06656 (reverse divisors), arXiv math/0511366, and OEIS A393794 (fixed points of the 1089-trick map, Havenaar 2026, a different map). +- A GMAT forum problem covers only the two-digit equation reverse(n) = n + 9, which has eight solutions (12, ..., 89). That is a different condition and does not address this conjecture. + +No prior resolution was found, so this appears to be the first written proof, and it is Lean-verified. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a097154, + author = {{math0}}, + title = {{The only fixed points of reverse(x) - maxdigit(x) are 0 and 89}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a097154}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a097154/paper.pdf b/results/oeis-a097154/paper.pdf new file mode 100644 index 0000000..1289c59 Binary files /dev/null and b/results/oeis-a097154/paper.pdf differ diff --git a/results/oeis-a097154/paper.tex b/results/oeis-a097154/paper.tex new file mode 100644 index 0000000..4ac973c --- /dev/null +++ b/results/oeis-a097154/paper.tex @@ -0,0 +1,362 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,constructor,right,unfold,by_cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 + {≠}{{$\ne$}}1 {∈}{{$\in$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\rev}{\operatorname{rev}} +\newcommand{\maxdig}{\operatorname{maxdig}} +\newcommand{\val}{\operatorname{val}} + +\title[Fixed points of reversal minus largest digit]{The only fixed points of $x\mapsto\rev(x)-\maxdig(x)$ are $0$ and $89$: Earls' conjecture in OEIS A097154} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 19, 2026} + +\begin{document} +\begin{abstract} +For a nonnegative integer $x$ let $\rev(x)$ be the number obtained by reversing the decimal digits of $x$, and let $\maxdig(x)$ be the largest decimal digit of $x$. We prove that the map $f(x)=\rev(x)-\maxdig(x)$ has exactly two fixed points, $0$ and $89$, which was stated as a conjecture by Jason Earls in OEIS A097154 (2004) and repeated in A097155 and A097157. +The proof combines the congruence $\rev(x)\equiv x\pmod 9$, which forces $\maxdig(x)=9$ at a nonzero fixed point, with a comparison of the leading and units digits. +To our knowledge the result is new, although the argument is elementary; the OEIS entries still list the statement as a conjecture. +The theorem is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before any proof attempt, whose definitions are checked by the kernel against the listed OEIS terms; this statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +In August 2004 Jason Earls contributed to the OEIS a group of sequences A097153--A097158 about the map +\[ + f(x)=\rev(x)-\maxdig(x)\qquad(x\ge0), +\] +where $\rev(x)$ is the decimal reversal of $x$ (sequence A004086 \cite{A004086}, with leading zeros of the reversed string dropped, so that $\rev(120)=21$) and $\maxdig(x)$ is the largest decimal digit of $x$. The values $f(n)$ form A097153 \cite{A097153}. A097154 \cite{A097154} gives the number of iterations of $f$ needed to bring $n$ to $0$, or $-1$ if $0$ is never reached; for example $12\mapsto19\mapsto82\mapsto20\mapsto0$, so that $a(12)=4$. The first value $-1$ is $a(89)$, because $f(89)=98-9=89$. A097155 \cite{A097155} lists the numbers whose orbit reaches $89$, A097157 \cite{A097157} the number of iterations they need to reach $89$, A097156 \cite{A097156} the least number that needs exactly $n$ iterations to reach $0$, and A097158 \cite{A097158} the numbers that set a new record for the number of iterations needed to reach $0$. +The comments of A097154, A097155 and A097157 all contain the sentence ``It is conjectured that 0 and 89 are the only fixed points of f.'' We prove this (Theorem~\ref{thm:main}). + +\subsection*{Method} +If $f(x)=x$ then $\rev(x)=x+\maxdig(x)$. Reversal preserves the digit sum, so $\rev(x)\equiv x\pmod 9$, and therefore $9\mid\maxdig(x)$; for $x\ne0$ this gives $\maxdig(x)=9$. It remains to solve $\rev(x)=x+9$ with largest digit $9$. Writing $x$ as units digit $b$, middle block $M$ and leading digit $a$, the equation modulo $10$ leaves two cases for $(a,b)$; one is impossible by size, and the other forces the middle block to be empty, so that $x=10a+(a+1)$, and the condition on the largest digit gives $x=89$. + +\subsection*{Status and prior work} +The local copy of the OEIS data used by math0, which the referees cross-checked against the current OEIS data files, has A097154 at revision \#4 (December~15, 2017), A097155 at revision \#11 (August~29, 2025) and A097157 at revision \#3 (December~15, 2017). All three still state the conjecture, and none has a comment, formula, link or edit note recording a proof or a counterexample; the only edit note in A097155 is a correction of its data by Harvey P.~Dale (2011). The related entries A097153, A097156 and A097158, with extensions by Robert G.~Wilson~v and Klaus Brockhaus, are computational, and no other OEIS entry in that copy refers to A097153--A097158. +Web searches by the math0 referees (for the definition of the map, for phrasings such as ``reversal minus largest digit'', and in the SeqFan archives and question-and-answer sites) found no proof; they found only the OEIS pages themselves and work on other digit-reversal maps. +The statement is not among the OEIS statements of the formal-conjectures repository \cite{FC}. +We therefore classify the result as \emph{new}. The argument uses only congruences modulo $9$ and $10$ and a size comparison, and it may well have been noticed without being recorded. + +We note that the conjecture is about fixed points in the literal sense, $f(x)=x$; A097155 calls $89$ ``the fixed point 89''. We do not address the stronger question whether $f$ has periodic orbits of length at least $2$, that is, whether every orbit ends at $0$ or at $89$ (Remark~\ref{rem:cycles}). + +\section{Statement}\label{sec:statement} + +\subsection*{Notation} +For a finite list $\ell=(e_0,\dots,e_{n-1})$ of natural numbers we write $|\ell|=n$, +\[ + \val(\ell)=\sum_{i=0}^{n-1}e_i\,10^i,\qquad \ell^R=(e_{n-1},\dots,e_0),\qquad \mu(\ell)=\max(0,e_0,\dots,e_{n-1}). +\] +In Lean these are \texttt{Nat.ofDigits 10 $\ell$}, \texttt{$\ell$.reverse} and \texttt{$\ell$.foldr max 0}. We use $\val(())=0$, $\val(e::\ell)=e+10\val(\ell)$ and $\val(\ell\mathbin{+\!\!+}\ell')=\val(\ell)+10^{|\ell|}\val(\ell')$, where $e::\ell$ is the list with first entry $e$ followed by $\ell$ and $\mathbin{+\!\!+}$ is concatenation. +For $x\in\N$ let $\delta(x)$ be the list of decimal digits of $x$, least significant first (\texttt{Nat.digits 10 x}). Thus $\delta(0)=()$, and for $x\ge1$ the list $\delta(x)$ is nonempty, its entries lie in $\{0,\dots,9\}$, its last entry (the leading digit) is nonzero, and $\val(\delta(x))=x$. + +\begin{definition}\label{def:f} +For $x\in\N$ put +\[ + \rev(x)=\val\bigl(\delta(x)^R\bigr),\qquad \maxdig(x)=\mu\bigl(\delta(x)\bigr),\qquad f(x)=\rev(x)-\maxdig(x). +\] +\end{definition} + +So $\rev(x)$ is the number whose decimal digits are those of $x$ in reverse order, with leading zeros dropped, and $\rev(0)=\maxdig(0)=0$. By Lemma~\ref{lem:max}(c) below, $\maxdig(x)\le\rev(x)$, so $f$ maps $\N$ to $\N$ and the subtraction is exact. For example $f(10)=1-1=0$ and $f(89)=98-9=89$. + +\begin{theorem}\label{thm:main} +For every $x\in\N$, $f(x)=x$ if and only if $x=0$ or $x=89$. +\end{theorem} + +\subsection*{The OEIS conjecture} +The entry A097154 \cite{A097154}, contributed by Jason Earls on August~1, 2004, is named ``Number of iterations of f(x) = reverse(x) - maxdigit(x) needed to reach zero, or -1 if zero is never reached, where maxdig(n) is the largest digit of n'', with offset $1$ and keywords \texttt{base}, \texttt{easy}, \texttt{sign}. Its COMMENTS section reads, verbatim (the comment carries no separate signature): +\begin{quote} +{\small\raggedright\texttt{a(89)=-1 because 89 is the first number that will not reach zero: 98-9=89. It is conjectured that 0 and 89 are the only fixed points of f. See A097155 for numbers that reach 89.}\par} +\end{quote} +The same conjecture appears in the comments of A097155 and A097157, also contributed by Earls on August~1, 2004. + +\subsection*{Lean formalization} +The statement was formalized by math0 in the file \path{lean/Math0/Statements/OEIS/A097154.lean}. It was reviewed for fidelity and frozen before any proof attempt; its SHA-256 hash is \texttt{1d7d144b\ldots cbb8}. The definitions of the map and the statement read as follows (verbatim; the import, docstrings, blank lines and all other declarations are omitted): +\begin{lstlisting} +namespace Math0.Statements.A097154 +def rev (x : ℕ) : ℕ := Nat.ofDigits 10 (Nat.digits 10 x).reverse +def maxDigit (x : ℕ) : ℕ := (Nat.digits 10 x).foldr max 0 +def f (x : ℕ) : ℕ := rev x - maxDigit x +def statement : Prop := + ∀ x : ℕ, f x = x ↔ x = 0 ∨ x = 89 +end Math0.Statements.A097154 +\end{lstlisting} +These are the definitions $\rev$, $\maxdig$ and $f$ of Definition~\ref{def:f}, and \decl{statement} is Theorem~\ref{thm:main}; the biconditional says both that $0$ and $89$ are fixed points and that there are no others. The subtraction in \decl{f} is truncated subtraction on $\N$, but the file proves that it never truncates, and the same file also encodes the sequence A097154 itself. Its other declarations include the following (statements shown, proofs omitted): +\begin{lstlisting} +theorem maxDigit_le_rev (x : ℕ) : maxDigit x ≤ rev x +theorem f_eq_int (x : ℕ) : (f x : ℤ) = (rev x : ℤ) - (maxDigit x : ℤ) +theorem f_examples : + f 12 = 19 ∧ f 19 = 82 ∧ f 82 = 20 ∧ f 20 = 0 ∧ f 0 = 0 ∧ rev 89 = 98 ∧ maxDigit 89 = 9 ∧ + f 89 = 89 +def search : ℕ → ℕ → ℕ → ℤ + | x, k, 0 => if x = 0 then (k : ℤ) else -1 + | x, k, fuel + 1 => if x = 0 then (k : ℤ) else search (f x) (k + 1) fuel +def a (n : ℕ) : ℤ := search n 0 (10 ^ (Nat.digits 10 n).length) +open Classical in +theorem a_spec (n : ℕ) : a n = if h : ∃ k, f^[k] n = 0 then (Nat.find h : ℤ) else -1 +\end{lstlisting} +By \decl{maxDigit_le_rev} and \decl{f_eq_int}, \decl{f} agrees with the integer-valued map of the OEIS entry, so the truncated subtraction creates no junk values. +The sequence takes the value $-1$, so \decl{a} has values in $\Z$. It follows the orbit of $n$ for at most $10^d$ steps, where $d$ is the number of digits of $n$, which makes it computable; \decl{a_spec} shows that this bound loses nothing, so that \decl{a} is exactly the OEIS definition (the least $k$ with $f^k(n)=0$, and $-1$ if there is none). Its proof shows that $f$ maps $\{0,\dots,10^d-1\}$ into itself and that the iterates before the first $0$ are pairwise distinct, and then applies the pigeonhole principle. +Two lemmas proved by \texttt{decide +kernel} compare the definitions with the entry: \decl{a_data} checks all $127$ listed terms $a(1),\dots,a(127)$ of A097154, including $a(89)=-1$, and \decl{f_examples} checks the example $12\mapsto19\mapsto82\mapsto20\mapsto0$ of the entry, together with $f(0)=0$ and $f(89)=98-9=89$. +The reversal convention (trailing zeros of $x$ disappear) is the one the data require, since $a(10)=a(20)=\dots=1$. +The statement quantifies over all $x\in\N$, including $x=0$, which the conjecture names as a fixed point, and adds no hypotheses. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A097154.lean}; the name of the corresponding Lean declaration is given with each step. Lemma~\ref{lem:mem} and parts (b) and (c) of Lemma~\ref{lem:max} are proved in the statement file and reused; part (a) of Lemma~\ref{lem:max} is proved in the proof file. + +\begin{lemma}[\decl{le_ofDigits_of_mem}]\label{lem:mem} +If $e$ is an entry of the list $\ell$, then $e\le\val(\ell)$. +\end{lemma} + +\begin{proof} +By induction on $\ell$. The empty list has no entries. If $\ell=e'::\ell'$, then $\val(\ell)=e'+10\val(\ell')$; either $e=e'\le\val(\ell)$, or $e$ is an entry of $\ell'$ and $e\le\val(\ell')\le\val(\ell)$ by induction. +\end{proof} + +\begin{lemma}[\decl{le_foldr_max}, \decl{foldr_max_le}, \decl{maxDigit_le_rev}]\label{lem:max} +Let $\ell$ be a list of natural numbers. +\begin{enumerate} +\item[(a)] Every entry $e$ of $\ell$ satisfies $e\le\mu(\ell)$. +\item[(b)] If $c\in\N$ and every entry of $\ell$ is at most $c$, then $\mu(\ell)\le c$. +\item[(c)] For every $x\in\N$, $\maxdig(x)\le\rev(x)$. +\end{enumerate} +\end{lemma} + +\begin{proof} +Parts (a) and (b) follow by induction on $\ell$ from $\mu(())=0$ and $\mu(e::\ell)=\max(e,\mu(\ell))$. For (c), every entry of $\delta(x)$ is an entry of $\delta(x)^R$, hence at most $\val(\delta(x)^R)=\rev(x)$ by Lemma~\ref{lem:mem}; now apply (b) with $c=\rev(x)$. +\end{proof} + +\begin{lemma}[\decl{ofDigits_reverse_mod}]\label{lem:mod9} +For every list $\ell$ of natural numbers, $\val(\ell^R)\equiv\val(\ell)\pmod 9$. +\end{lemma} + +\begin{proof} +Since $10\equiv1\pmod9$, we have $\val(\ell)=\sum_i e_i10^i\equiv\sum_i e_i\pmod 9$ (in Lean, \decl{Nat.ofDigits_modEq} and \decl{Nat.ofDigits_one}), and likewise for $\ell^R$. The entries of $\ell$ and $\ell^R$ have the same sum (\decl{List.sum_reverse}). +\end{proof} + +\begin{lemma}[\decl{ofDigits_eq_zero}]\label{lem:zero} +If every entry of $\ell$ is $0$, then $\val(\ell)=0$. +\end{lemma} + +\begin{proof} +Immediate by induction on $\ell$. +\end{proof} + +We also use that $\val(\ell)<10^{|\ell|}$ whenever all entries of $\ell$ are at most $9$ (\decl{Nat.ofDigits_lt_base_pow_length} in Mathlib). The heart of the proof is a statement about digit lists. + +\begin{proposition}[\decl{key}]\label{prop:key} +Let $\ell$ be a nonempty list with entries in $\{0,\dots,9\}$ whose last entry is nonzero, and suppose that +\begin{equation}\label{eq:hyp} + \val(\ell^R)=\val(\ell)+\mu(\ell). +\end{equation} +Then $\ell=(9,8)$. +\end{proposition} + +\begin{proof} +Put $c=\mu(\ell)$. All entries of $\ell$ are at most $9$, so $c\le9$ by Lemma~\ref{lem:max}(b). + +\emph{One entry.} If $\ell=(b)$, then $\ell^R=\ell$, so \eqref{eq:hyp} gives $c=0$. By Lemma~\ref{lem:max}(a), $b\le c=0$, contradicting the assumption that the last entry $b$ is nonzero. + +\emph{At least two entries.} Then $\ell=b::(M\mathbin{+\!\!+}(a))$ (\decl{List.eq_nil_or_concat'}), where $b$ is the first entry (the units digit), $a$ is the last entry (the leading digit) and $M$ is a possibly empty list of length $k$. We have $1\le a\le9$, $0\le b\le9$, and $a\le c$, $b\le c$ by Lemma~\ref{lem:max}(a). Put +\[ + m=\val(M),\qquad r=\val(M^R),\qquad P=10^k. +\] +Since $\ell^R=a::(M^R\mathbin{+\!\!+}(b))$ and $|M^R|=k$, the rules for $\val$ give +\begin{equation}\label{eq:vals} + \val(\ell)=b+10m+10Pa,\qquad \val(\ell^R)=a+10r+10Pb. +\end{equation} +We record three facts. +\begin{enumerate} +\item[(i)] $m 2 (Ralf Stephan's conjecture in OEIS A106505). + +## Assessment + +The proof works out the set of common sides. A coprime difference of squares s^2 - r^2 is either odd or divisible by 8. Two one-line families of triangles realize every odd c >= 5 and every multiple of 8 from 16 on, and the small cases are checked by hand. Since the set is periodic mod 8 with five residues per period, the recurrence follows at once. This is about half a page of elementary number theory, using the formula already given in the entry, and the cross-referenced A321499 already contains the same set characterization. The Lean work (deriving y^2 = x(x+c) from the arccos definition, plus the counting with Nat.nth) is formalization effort and adds no mathematical depth. + +*Follows from:* The entry's own %F formula: the terms are the values s^2 - r^2 with r < s < 2r and gcd(r,s) = 1 (classical parametrization of A/2A triangles, Luthar 1984; A343063). With that formula, a parity argument mod 8 plus the families (m, m+1) and (2j+1, 2j+3) give the set {odd >= 5} together with {8m : m >= 2}. Cross-reference A321499 (Hasler) already proves the same set with 3 added and records a(n+5) = a(n) + 8 there. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A106505](https://oeis.org/A106505) as [`Math0.Statements.A106505.statement`](../../lean/Math0/Statements/OEIS/A106505.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A106505.lean`](../../lean/Math0/Frontier/OEIS/A106505.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: for n>2, a(n+5) = a(n) + 8. - _Ralf Stephan_, Nov 16 2010." Also: "Empirical g.f.: ... - _Colin Barker_, Oct 05 2013" + +Referees: No earlier proof found. OEIS A106505 (GitHub oeisdata main, rev #21, Apr 23 2021) still states it as a conjecture (Ralf Stephan, Nov 16 2010), with an empirical g.f. by Colin Barker (2013). OEIS A321499 (M. F. Hasler, Nov 2018; rev #24, Feb 2025) proves that {d²(2m+d)} = odd numbers > 1 together with multiples of 8 > 8, and records a(n+5) = a(n) + 8 for A321499 (D. A. Corneth). It still says "Cf. A106505 (conjectured to be the sequence without the 3)". The closely related A321501 complement analysis (Hasler) is also there. Related OEIS entries: A343063 and A343064 (B. Schott, 2021), which give the parametrization a = m² − k², b = mk, c = k² with gcd(m,k) = 1 and k < m < 2k, but no set characterization; and A229849, which says A106505 "seems" to give those values. Parametrization background: M. N. Deshpande, Math. Gazette (2002); K. Zelator, arXiv 1208.0497; R. S. Luthar (1984). None of these addresses the conjecture. Not covered in S. Fried, arXiv 2410.07237 or arXiv 2607.24832, nor in Adamczewski's OEIS Open benchmark (arXiv 2608.11941), which uses the Tsoukalas et al. dataset in epoch-research/LeanOpenProblems; also absent from google-deepmind/formal-conjectures. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a106505, + author = {{math0}}, + title = {{A106505: common sides of A/2A primitive triangles are periodic mod 8, so a(n+5) = a(n) + 8}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a106505}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a106505/paper.pdf b/results/oeis-a106505/paper.pdf new file mode 100644 index 0000000..25c1a20 Binary files /dev/null and b/results/oeis-a106505/paper.pdf differ diff --git a/results/oeis-a106505/paper.tex b/results/oeis-a106505/paper.tex new file mode 100644 index 0000000..6d1d5b8 --- /dev/null +++ b/results/oeis-a106505/paper.tex @@ -0,0 +1,378 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,private,set,rw,rwa,only}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℝ}{{$\mathbb{R}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {∧}{{$\wedge$}}1 + {∨}{{$\vee$}}1 {≤}{{$\le$}}1 {²}{{$^2$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 + {π}{{$\pi$}}1 {·}{{$\cdot$}}1 {…}{{$\dots$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\code}[1]{\texttt{#1}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\R}{\mathbb{R}} +\newcommand{\Side}{\mathcal{S}} +\newcommand{\ang}{\theta} +\DeclareMathOperator{\cnt}{N} + +\title[The common side of the angles $A$ and $2A$]{The common side of the angles $A$ and $2A$ in primitive integer triangles: a proof of Stephan's conjecture $a(n+5)=a(n)+8$ for OEIS A106505} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 19, 2026} + +\begin{document} +\begin{abstract} +OEIS A106505 lists, in increasing order and without repetition, the integers $c$ such that some primitive integer-sided triangle has two angles $A$ and $2A$ whose common side has length $c$: $5,7,9,11,13,15,16,17,\dots$. +We prove the conjecture recorded by Ralf Stephan in the entry in 2010, that the $n$-th term satisfies $a(n+5)=a(n)+8$ for all $n>2$. +The proof determines the set of these lengths: it consists of the odd numbers $c\ge5$ and the multiples of $8$ with $c\ge16$, so that from $9$ on it is periodic modulo $8$ with five residues per period. The argument is elementary (a residue computation modulo $8$ and two explicit families of triangles); the OEIS entry still lists the statement as a conjecture and we found no recorded proof, so we classify the result as new, with the caveat that the set description is close to known facts recorded for the related sequence A321499. +The theorem is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before the proof attempt, whose definitions are checked by the kernel against all $67$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +Let a triangle have integer side lengths with $\gcd$ equal to $1$ (a \emph{primitive} triangle), and suppose that two of its angles are $A$ and $2A$. The side joining the vertices of these two angles is the side \emph{common} to them. The sequence A106505 of the OEIS \cite{A106505}, contributed by Lekraj Beedassy on May~4, 2005 and extended by Ray Chandler, is titled +\begin{quote} +``Ordered and uniqued length of side common to the two angles, one being the double of the other, of a primitive integer-sided triangle.'' +\end{quote} +It has offset $1$ and begins $5,7,9,11,13,15,16,17,19,21,23,24,25,\dots$; the entry lists $67$ terms, up to $112$. For example, $33$ is the common side of the two primitive triangles with sides $(33,28,16)$ and $(33,272,256)$. On November~16, 2010, Ralf Stephan added to the FORMULA section of the entry the conjecture +\begin{quote} +``Conjecture: for n$>$2, a(n+5) = a(n) + 8. -{}~Ralf Stephan, Nov 16 2010.'' +\end{quote} +and on October~5, 2013, Colin Barker added an ``empirical'' generating function, which is equivalent to the same recurrence together with the first eight terms. We prove Stephan's conjecture (Theorem~\ref{thm:main}), by determining the set of common sides (Theorem~\ref{thm:set}): it is $\{c \text{ odd}: c\ge 5\}\cup\{8m: m\ge2\}$. + +\subsection*{Background} +If a triangle with sides $a,b,c$ opposite the angles $A,B,C$ has $B=2A$, then $b^2=a(a+c)$, and conversely; Zelator \cite{Ze} gives a proof and traces this relation to a 1976 note in the Mathematical Gazette. The primitive integer triangles with one angle twice another were determined by Luthar \cite{Lu}; parametric families were given by Deshpande \cite{De}, and Zelator \cite{Ze} gives formulas covering all integer triangles with this property. In the notation of OEIS A343063 \cite{A343063} (B.~Schott, 2021), which lists the primitive triples, the common side is $m^2-k^2$ and the other two sides are $mk$ and $k^2$, where $\gcd(m,k)=1$ and $ky>0$. Its comment shows that these are exactly the odd numbers $>2$ and the multiples of $8$ larger than $8$, and D.~A. Corneth recorded there that $a(n+5)=a(n)+8$ for $n>3$ for that sequence; the complement is analysed in A321501 \cite{A321501}. A321499 concerns a different set, and its cross-reference still reads ``Cf.\ A106505 (conjectured to be the sequence without the 3)''; Theorem~\ref{thm:set} proves this identification. The math0 referees found no proof of Stephan's conjecture in the OEIS entries that cite A106505, in Fried's papers on OEIS conjectures \cite{Fr24,Fr26}, in the OEIS Open benchmark \cite{Ad} (built on the Lean formalizations of Tsoukalas et al.\ \cite{APN}), in the formal-conjectures repository \cite{FC}, or by web searches (including Mathematics Stack Exchange and the SeqFan list). We therefore classify the result as \emph{new}, with a caveat: it is elementary. Granting the parametrization above, the set description reduces to the fact that $s^2-r^2$ is odd or divisible by $8$ when $\gcd(r,s)=1$, plus two explicit families, and it may well be known informally; what we did not find recorded is a proof of the statement in the entry. + +\subsection*{Method} +Following the Lean proof, we work with the relation $y^2=x(x+c)$ (Lemma~\ref{lem:metric}) rather than the parametrization: a residue computation modulo $8$ (Lemma~\ref{lem:mod}), two explicit families (Lemma~\ref{lem:families}), and a counting argument (Lemma~\ref{lem:count}). + +\section{Statement}\label{sec:statement} + +For positive reals $p,q,r$ satisfying the strict triangle inequalities, the angle opposite the side $p$ in the triangle with sides $p,q,r$ is, by the law of cosines, +\[ + \ang(p;q,r)=\arccos\frac{q^2+r^2-p^2}{2qr}\in(0,\pi). +\] + +\begin{definition}\label{def:side} +For $x,y,c\in\N$, write $T(x,y,c)$ if $x2$, $a(n+5)=a(n)+8$. +\end{theorem} + +\begin{theorem}\label{thm:set} +$\Side=\{c\in\N:\ c\ \text{odd},\ c\ge5\}\cup\{8m:\ m\in\N,\ m\ge2\}$. +\end{theorem} + +Explicitly, $a(1)=5$, $a(2)=7$, and for $k\ge0$ the five terms $a(5k+3),\dots,a(5k+7)$ are $8k+9$, $8k+11$, $8k+13$, $8k+15$, $8k+16$. The recurrence fails for $n=1,2$: $a(6)=15\ne13$ and $a(7)=16\ne15$. + +\begin{remark}\label{rem:gf} +Theorem~\ref{thm:main} implies Barker's generating function +\[ + \sum_{n\ge1}a(n)x^n=\frac{x\,(5+2x+2x^2+2x^3+2x^4-3x^5-x^6-x^7)}{(1-x)(1-x^5)} +\] +(the entry writes the denominator as $(x-1)^2(x^4+x^3+x^2+x+1)$): by Theorem~\ref{thm:main}, $(1-x)(1-x^5)\sum a(n)x^n$ is a polynomial of degree at most $8$, and computing it from $a(1),\dots,a(8)$ gives the numerator above. This consequence is not formalized. +\end{remark} + +\subsection*{The Lean statement} +The statement was formalized by math0 in the file \path{lean/Math0/Statements/OEIS/A106505.lean}, reviewed for fidelity against the OEIS entry, and frozen (SHA-256 \texttt{f1815676\ldots99ac}) before any proof attempt. Its definitions and the statement are, verbatim: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +/-- The angle opposite the side of length `p` in a triangle with side lengths `p, q, r`, by the +law of cosines: `arccos ((q² + r² - p²) / (2 q r))`. -/ +noncomputable def angleOpp (p q r : ℝ) : ℝ := + Real.arccos ((q ^ 2 + r ^ 2 - p ^ 2) / (2 * q * r)) + +/-- `x, y, c` are the side lengths of a non-degenerate triangle in which the angle opposite `y` +is twice the angle opposite `x`. The side `c` is the side common to these two angles. -/ +def IsDoubleAngleTriangle (x y c : ℕ) : Prop := + x < y + c ∧ y < x + c ∧ c < x + y ∧ + angleOpp (y : ℝ) (x : ℝ) (c : ℝ) = 2 * angleOpp (x : ℝ) (y : ℝ) (c : ℝ) + +/-- `c` is the length of the side common to the two angles, one being the double of the other, +of a primitive integer-sided triangle. -/ +def IsSide (c : ℕ) : Prop := + ∃ x y : ℕ, IsDoubleAngleTriangle x y c ∧ Nat.gcd (Nat.gcd x y) c = 1 + +instance : DecidablePred IsSide := fun c => decidable_of_iff _ (isSide_iff c).symm + +/-- A106505: the `n`-th smallest (offset `1`) length of the side common to the two angles, one +being the double of the other, of a primitive integer-sided triangle. -/ +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsSide (n - 1) + +/-- Conjecture (Stephan, A106505): for `n > 2`, `a(n + 5) = a(n) + 8`. -/ +def statement : Prop := ∀ n : ℕ, 2 < n → a (n + 5) = a n + 8 +\end{lstlisting} +All declarations are in the namespace \decl{Math0.Statements.A106505}. + +\subsection*{How the Lean definitions encode the entry} +The definitions follow the name of the entry, not its formula $s^2-r^2$. \code{angleOpp p q r} is $\ang(p;q,r)$, the unoriented angle given by the real arccosine. \code{IsDoubleAngleTriangle x y c} is $T(x,y,c)$; the strict triangle inequalities make the triangle non-degenerate and force $x,y,c\ge1$. \code{IsSide c} adds primitivity, $\gcd(\gcd(x,y),c)=1$, and quantifies over all $x,y$, which covers every labelling of the triangle. ``Ordered and uniqued'' with offset $1$ is \code{a n = Nat.nth IsSide (n - 1)}, where \code{Nat.nth p k} is the $k$-th smallest element (counted from $0$) of $\{n : p(n)\}$. Since $\Side$ is infinite, the junk value $0$ that Mathlib assigns to \decl{Nat.nth} beyond the end of a finite set does not arise, and since $n>2$ the truncated subtraction $n-1$ is harmless. The statement is Stephan's conjecture verbatim, with $1$-indexed $n$. + +The statement file also proves that the angle condition is equivalent to $y^2=x(x+c)$ (\decl{isDoubleAngleTriangle_iff}, Lemma~\ref{lem:metric} below), and turns membership in $\Side$ into a bounded search (\decl{isSide_iff}, Corollary~\ref{cor:search}), which yields the \decl{DecidablePred} instance shown above. With it, the theorem \decl{a_data} checks that $a(1),\dots,a(67)$ are the $67$ terms listed in the entry: the kernel evaluates \decl{List.filter} over $\{0,\dots,112\}$ (by \texttt{decide +kernel}), and a general lemma, \decl{map_nth_eq_of_filter}, identifies the filtered list with the list of the values \code{Nat.nth IsSide k} for $k<67$. The theorem \decl{example_33} checks the two triangles with common side $33$ quoted in the entry, $(x,y,c)=(16,28,33)$ and $(256,272,33)$. + +\section{Proof}\label{sec:proof} + +\begin{lemma}[metric relation; \decl{isDoubleAngleTriangle_iff}]\label{lem:metric} +Let $x,y,c\in\N$ satisfy $x0$ for the three lengths as reals, and put +\[ + u=\frac{X^2+C^2-Y^2}{2XC},\qquad v=\frac{Y^2+C^2-X^2}{2YC}, +\] +so that $\ang(y;x,c)=\arccos u$ and $\ang(x;y,c)=\arccos v$. The triangle inequalities give $(X-C)^20$, a direct computation gives +\begin{equation}\label{eq:factor} + 2XY^2C^2\,(u-2v^2+1)=P\cdot\bigl(X(X+C)-Y^2\bigr). +\end{equation} + +Suppose $\arccos u=2\arccos v$. Taking cosines, and using $\cos\arccos t=t$ for $t\in[-1,1]$ and $\cos2\alpha=2\cos^2\alpha-1$, we get $u=2v^2-1$, so \eqref{eq:factor} gives $Y^2=X(X+C)$. + +Conversely, suppose $Y^2=X(X+C)$. Then $u=2v^2-1=\cos(2\arccos v)$ by \eqref{eq:factor}. Moreover $Y^2+C^2-X^2=XC+C^2>0$, so $v\ge0$ and $\arccos v\in[0,\pi/2]$. Hence $t=2\arccos v\in[0,\pi]$, where $\arccos(\cos t)=t$, and $\arccos u=\arccos(\cos t)=2\arccos v$. +\end{proof} + +\begin{corollary}[\decl{isSide_iff}]\label{cor:search} +If $T(x,y,c)$, then $d=y-x$ satisfies $0x^2$, so $d=y-x>0$, and expanding $(x+d)^2=x^2+xc$ gives $xc=2xd+d^2$. Since $d^2>0$, $c>2d$, and $x(c-2d)=d^2$. For the converse, the given $x$ and $y=x+d$ satisfy $x1$, which holds for $m\ge2$. Since $2m+1=1+2m$, $\gcd(m,2m+1)=1$, so $\gcd(m^2,2m+1)=1$, and $\gcd(x,y,c)$ divides $\gcd(x,c)=1$. + +For (2), let $x=n^2$, $y=n(n+2)$ and $c=8j+8=4(n+1)$. Then $y^2=n^2(n^2+4n+4)=x(x+c)$. The inequality $x0$, which holds as $n\ge3$. Since $c=4+4n$, $\gcd(n,c)=\gcd(n,4)=1$ because $n$ is odd; so $\gcd(n^2,c)=1$ and $\gcd(x,y,c)=1$. +\end{proof} + +\begin{proposition}[\decl{isSide_iff_large}, \decl{isSide_add_eight}]\label{prop:large} +For $c\ge9$, $c\in\Side$ if and only if $c$ is odd or $8\mid c$. Consequently $c+8\in\Side\iff c\in\Side$ for all $c\ge9$. +\end{proposition} + +\begin{proof} +Necessity is Lemma~\ref{lem:mod}. An odd $c\ge9$ is $2m+1$ with $m\ge4$, and a multiple of $8$ with $c\ge9$ is $8j+8$ with $j\ge1$; Lemma~\ref{lem:families} applies. The second statement holds because ``odd or divisible by $8$'' depends only on $c\bmod8$, and both $c$ and $c+8$ are at least $9$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:set}] +For $c\ge9$ this is Proposition~\ref{prop:large}. For $c\le8$, Lemma~\ref{lem:mod} leaves the candidates $0,1,3,5,7,8$; $0\notin\Side$ by the triangle inequalities, $1,3,8\notin\Side$ by the computation after Corollary~\ref{cor:search}, and $5,7\in\Side$ by Lemma~\ref{lem:families}(1) with $m=2,3$, realized by the triangles $(x,y,c)=(4,6,5)$ and $(9,12,7)$. +\end{proof} + +For the counting argument, let $\cnt(t)=\#\{c=2. Cut H into consecutive rows: row 1 is [H(1)], and row n+2 has as many terms as the sum of row n+1. Let a(n) be the length of row n. Levine's array has row 1 = [1,1], and row k+1 lists 1 c_1 times, 2 c_2 times, ..., where row k = [c_1, c_2, ...]. A014644(k) is the last term of Levine row k. Claim (both conjectures of van Lamoen and Hanna, 2005): (1) for every n>=2, a(n) = A014644(n+2) - A014644(n+1); (2) the last term of row 1 is A014644(1), and for every n>=2 the last term of row n is A014644(n+1). + +## Assessment + +The one real idea is that each Levine row from row 2 on is a prefix of Golomb's sequence, so its sum is the length of the next row. That is immediate from Golomb's self-describing property and is already known: A014643 hints at it and Claes and Miyamoto state it. Everything else is a telescoping sum and a short induction showing that the triangle's rows are the blocks of G between consecutive Levine row lengths; both conjectures then follow. The whole argument fits in about a page of elementary steps, and the manuscript itself calls the result "a short consequence" of known facts. + +*Follows from:* The fact that from row 2 on, the rows of Levine's array (A014643) are initial segments of Golomb's sequence A001462. A014643's cross-reference note "Rows converge to A001462" points to this, and Claes and Miyamoto, arXiv:2602.10992, p. 3, eqs. (3)-(4) state it: the Levine step maps the first n Golomb terms to the first A001463(n) terms. Golomb's self-describing property gives it at once. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A113676](https://oeis.org/A113676) as [`Math0.Statements.A113676.statement`](../../lean/Math0/Statements/OEIS/A113676.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A113676.lean`](../../lean/Math0/Frontier/OEIS/A113676.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C Conjecture: a(n) for n>1 gives first differences of Lionel Levine's sequence A014644(n) for n>=3. %C Conjecture: Final elements of the rows form A014644 except for duplicate 2. (Floor van Lamoen and Paul D. Hanna, Nov 06 2005) + +Referees: No prior proof found. +- OEIS A113676 (van Lamoen & Hanna, Nov 2005; rev #9, Mar 2025) still lists both conjectures. +- OEIS A001462 has van Lamoen's related conjecture (Nov 06 2005), still unresolved in the Aug 2026 revision. +- OEIS A014643 has the %Y note "Rows converge to A001462". +- J. Claes and R. Miyamoto, "Golombic and Levine sequences", arXiv:2602.10992 [math.CO] (Feb 2026), p. 3, eqs. (3)–(4). It observes that Γ maps the first n Golomb terms to the first A001463(n) terms (so the A014643 rows are Golomb prefixes), and that |a| = #Γa and #a = (Γa)(|a|). These are the key ingredients, but the paper does not mention A113676 or prove its conjectures. +- Cross-checked entries: A014644, A014643, A011784, A012257, A001463, A113722, A113724, A113730 and A304679. None records a resolution. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a113676, + author = {{math0}}, + title = {{The Golomb-row triangle A113676 and Levine's sequence A014644}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a113676}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a113676/paper.pdf b/results/oeis-a113676/paper.pdf new file mode 100644 index 0000000..23a646e Binary files /dev/null and b/results/oeis-a113676/paper.pdf differ diff --git a/results/oeis-a113676/paper.tex b/results/oeis-a113676/paper.tex new file mode 100644 index 0000000..ee41f0d --- /dev/null +++ b/results/oeis-a113676/paper.tex @@ -0,0 +1,371 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {↔}{{$\leftrightarrow$}}1 + {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {<}{{$<$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Lev}{\mathrm{Lev}} +\newcommand{\last}{\operatorname{last}} +\newcommand{\len}[1]{\lvert #1\rvert} +\newcommand{\A}{A} + +\title[The Golomb triangle A113676 and Levine's sequence A014644]{The row lengths and row ends of the Golomb triangle OEIS A113676 are given by Levine's sequence A014644} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + +\begin{document} +\begin{abstract} +Cut Golomb's sequence with one of its two $2$'s removed, $1,2,3,3,4,4,4,5,5,5,\dots$, into consecutive rows so that the first row is $(1)$ and each further row has as many terms as the sum of the previous row; the row lengths form OEIS A113676. +We prove both conjectures that Floor van Lamoen and Paul D.\ Hanna recorded in that entry in 2005: for $n\ge2$ the length of row $n$ equals $A(n+2)-A(n+1)$, and the last term of row $n$ equals $A(n+1)$, where $A$ is Levine's sequence A014644 (and row $1$ ends in $A(1)=1$). +The proof rests on the fact, also observed by Claes and Miyamoto, that from the second row on the rows of Levine's array are initial segments of Golomb's sequence; a telescoping identity and an induction then locate the rows of the triangle exactly. +To our knowledge the result is new, though elementary; the OEIS entry still lists both statements as conjectures. +The theorem is verified in Lean~4 against a frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the listed OEIS terms. +\end{abstract} +\maketitle + +\section{Introduction} + +\emph{Golomb's sequence} $G$ (OEIS A001462 \cite{A001462}; Golomb \cite{Go}, Guy \cite[E25]{Guy}) is the unique nondecreasing sequence of positive integers with $G(1)=1$ in which every $n\ge1$ occurs exactly $G(n)$ times: +\[ + G = 1,2,2,3,3,4,4,4,5,5,5,6,6,6,6,7,\dots +\] +\emph{Levine's array} A014643 \cite{A014643} starts with the row $(1,1)$, and the $i$-th term of each row is the number of $i$'s in the next row, listed in increasing order: +\[ + (1,1),\quad (1,2),\quad (1,2,2),\quad (1,2,2,3,3),\quad (1,2,2,3,3,4,4,4,5,5,5),\ \dots +\] +The final terms of the rows form Levine's sequence A014644 \cite{A014644}, +\[ + A = 1,2,2,3,5,11,38,272,6474,1090483,4363282578,\dots +\] +(terms $A(1),\dots,A(11)$ were computed by C.~Mallows and $A(12),\dots,A(15)$ by J.~Claes in 2005; the b-file of the entry now gives nineteen terms, the last four computed by Claes and Miyamoto \cite{A014644,CM}). + +The OEIS entry A113676 \cite{A113676}, by Floor van Lamoen and Paul D.\ Hanna (November~6, 2005), takes Golomb's sequence with one $2$ removed, $1,2,3,3,4,4,4,5,5,5,\dots$, and cuts it into consecutive rows: the first row is $(1)$, and the number of terms of row $n$ is the sum of row $n-1$. The triangle begins +\[ + (1);\quad (2);\quad (3,3);\quad (4,4,4,5,5,5);\ \dots +\] +and $a(n)$ is the number of terms of row $n$: $1,1,2,6,27,234,6202,1084009,4362192095$. +The entry records two conjectures, quoted in Section~\ref{sec:statement}: the row lengths $a(n)$, $n\ge2$, are the first differences of $A$ from its third term on, and the final terms of the rows are the terms of $A$ with its duplicate $2$ removed. We prove both (Theorem~\ref{thm:main}). + +\subsection*{Method} +Write $P(l)=(G(1),\dots,G(l))$ and $L_k$ for the number of terms of row $k$ of Levine's array. +Since $G$ describes itself, the Levine step sends $P(l)$ to the list $1^{G(1)}2^{G(2)}\cdots l^{G(l)}$, which is again an initial segment of $G$; so row $k\ge2$ of Levine's array is $P(L_k)$ (Lemma~\ref{lem:levine}). Taking sums gives the telescoping identity $G(L_k+1)+\dots+G(L_{k+1})=L_{k+2}-L_{k+1}$ (Lemma~\ref{lem:tele}), and an induction shows that row $n\ge2$ of the triangle is exactly the block $G(L_n+1),\dots,G(L_{n+1})$ (Lemma~\ref{lem:rowend}). Since $L_k=A(k+1)$ and the last term of $P(L_{n+1})$ is $A(n+1)$, both conjectures follow. + +\subsection*{Status and prior work} +The entry A113676 (revision \#9, March~5, 2025) still lists both statements as conjectures, with no proof or comment on them. +The comments of A001462 contain a related conjecture of van Lamoen of the same date, phrased in terms of a differently described triangle and partial sums of its row sums; it is still worded as a conjecture in the current revision, and we do not address it here. +The key ingredient of our proof is known: the note ``Rows converge to A001462'' in A014643 reflects it, and Claes and Miyamoto \cite[p.~3, eqs.~(3)--(4)]{CM} observe that the Levine step (their ``golombic operator'' $\Gamma$) maps the first $n$ terms of Golomb's sequence to its first A001463$(n)$ terms \cite{A001463}, so that the rows of A014643 are initial segments of $G$, and they record how the length, the sum and the last term of a list relate to those of its image under the Levine step (our Lemma~\ref{lem:gamma}). Their paper does not mention A113676 or the triangle, and does not derive the two statements proved here. +The math0 referees also checked A014644, A014643, A011784, A012257, A001463, A113722, A113724, A113730 and A304679, and web searches (including arXiv and the SeqFan list) found no resolution. +We therefore classify the result as new, with the caveat that it is a short consequence (a telescoping sum and an induction) of the initial-segment property above. + +\section{Statement}\label{sec:statement} + +For a finite list $c=(c_1,\dots,c_l)$ of natural numbers we write $\len c=l$ for its length, $\Sigma c=c_1+\dots+c_l$ for its sum and $\last(c)=c_l$ for its last term (if $l\ge1$). We write $i^{m}$ for the list of $m$ copies of $i$ and juxtaposition for concatenation, and define the \emph{Levine step} +\[ + \Gamma(c_1,\dots,c_l) = 1^{c_1}\,2^{c_2}\cdots l^{c_l}. +\] + +\begin{definition}\label{def:main} +Let $G$ be Golomb's sequence and $P(l)=(G(1),\dots,G(l))$. +\begin{enumerate} +\item Let $H(1)=1$ and $H(j)=G(j+1)$ for $j\ge2$, so $H=1,2,3,3,4,4,4,5,5,5,\dots$. +\item Let $E(0)=0$, $E(1)=1$ and $E(n+2)=E(n+1)+\sum_{E(n)1 gives first differences of Lionel Levine's sequence A014644(n) for n>=3.}}\\ +{\small\texttt{Conjecture: Final elements of the rows form A014644 except for duplicate 2.}} +\end{quote} +The name of the entry refers to ``A001642''; this is a typo for A001462, as the example rows of the entry show. + +\begin{theorem}\label{thm:main} +\textup{(1)} For every $n\ge2$, $a(n)=A(n+2)-A(n+1)$. +\textup{(2)} $\last(R_1)=A(1)$, and $\last(R_n)=A(n+1)$ for every $n\ge2$. +\end{theorem} + +The proof in Section~\ref{sec:proof} gives slightly more, which is not part of the formal statement below (it appears only as intermediate steps of the Lean proof): for $n\ge2$ row $n$ of the triangle is the block $R_n=(G(i))_{A(n+1) [1, 2, 2] + | m + 1 => golombAux m ++ List.replicate ((golombAux m).getD (m + 2) 0) (m + 3) +def golomb : ℕ → ℕ + | 0 => 0 + | n + 1 => (golombAux n).getD n 0 +def H (j : ℕ) : ℕ := if j ≤ 1 then golomb j else golomb (j + 1) +def rowEnd : ℕ → ℕ + | 0 => 0 + | 1 => 1 + | n + 2 => rowEnd (n + 1) + + ((List.range' (rowEnd n + 1) (rowEnd (n + 1) - rowEnd n)).map H).sum +def row (n : ℕ) : List ℕ := + (List.range' (rowEnd (n - 1) + 1) (rowEnd n - rowEnd (n - 1))).map H +def a (n : ℕ) : ℕ := (row n).length +def levineAux : List ℕ → ℕ → List ℕ + | [], _ => [] + | c :: l, i => List.replicate c i ++ levineAux l (i + 1) +def levineRow : ℕ → List ℕ + | 0 => [] + | 1 => [1, 1] + | k + 2 => levineAux (levineRow (k + 1)) 1 +def A014644 (k : ℕ) : ℕ := (levineRow k).getLastD 0 +def statement : Prop := + (∀ n : ℕ, 2 ≤ n → (a n : ℤ) = (A014644 (n + 2) : ℤ) - (A014644 (n + 1) : ℤ)) ∧ + ((row 1).getLast? = some (A014644 1) ∧ + ∀ n : ℕ, 2 ≤ n → (row n).getLast? = some (A014644 (n + 1))) +end Math0.Statements.A113676 +\end{lstlisting} +The encoding matches Definition~\ref{def:main}: \decl{rowEnd} is $E$, \decl{row} is $R_n$, \texttt{levineAux l 1} is $\Gamma(l)$, \decl{levineRow} is $\Lev_k$ and \decl{A014644} is $A$ (all with offset $1$; the values at $0$ are never used). Golomb's sequence is computed by its self-generating construction: \texttt{golombAux m} starts from $1,2,2$ and appends, for $k=3,\dots,m+2$, the number $k$ repeated $G(k)$ times, where $G(k)$ is read off the list built so far. The file proves (proofs omitted) +\begin{lstlisting} +theorem golombAux_eq_flatMap (m : ℕ) : + golombAux m = (List.range' 1 (m + 2)).flatMap (fun k => List.replicate (golomb k) k) +theorem golombAux_eq_map (m : ℕ) : + golombAux m = (List.range' 1 (golombAux m).length).map golomb +theorem a_data : (List.range 9).map (fun i => a (i + 1)) = + [1, 1, 2, 6, 27, 234, 6202, 1084009, 4362192095] +theorem A014644_data : (List.range 11).map (fun i => A014644 (i + 1)) = + [1, 2, 2, 3, 5, 11, 38, 272, 6474, 1090483, 4363282578] +\end{lstlisting} +The first two say that every stage is $P(\ell)=1^{G(1)}2^{G(2)}\cdots(m+2)^{G(m+2)}$ for its length $\ell$, which is the self-describing property of A001462; together with $G(1)=1$ it determines the sequence. The file also checks by kernel evaluation all $84$ terms of A001462 listed in the OEIS (\decl{golomb_data}), the four example rows of A113676 (\decl{rows_example}), and the last terms $1,2,3,5,11,38,272$ of rows $1$ to $7$ (\decl{rowLast_data}); \decl{a_data} and \decl{A014644_data} check all $9$ listed terms of A113676 and the first $11$ of A014644. +The large values are certified without computing long lists in the kernel. The iterates of $\Gamma$ starting from $(1,2,2)$ are proved to be initial segments of $G$ (\decl{golombFast_eq_golombAux}); the fifth one, $P(6474)$, is evaluated by \texttt{decide +kernel}, and the sixth one, $P(1090483)$, is never built: its length and sum are obtained from the sum $1090483$ and the weighted sum $\sum_{i\le 6474}iG(i)=4363282578$ of $P(6474)$, via the lemmas that $\len{\Gamma(c)}=\Sigma c$ and $\Sigma\Gamma(c)=\sum_i i\,c_i$. The rows $1,\dots,7$ and $a(1),\dots,a(8)$ are read off $P(6474)$; $a(9)=\sum_{6475\le i\le 1090483}G(i)=4363282578-1090483$ is obtained as above; and the same two lemmas applied to $\Lev_8=P(6474)$, together with $A(k+2)=L_{k+1}$ (\decl{A014644_add_two}), give $A(9),A(10),A(11)$. These checks only concern the fidelity of the definitions; the proof of Theorem~\ref{thm:main} uses none of them. + +The statement is computed in $\Z$, so the difference in (1) is a true difference, and ``the last term of row $n$ is $x$'' is \texttt{(row n).getLast? = some x}, which fails for an empty row. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A113676.lean}; the names of the corresponding Lean lemmas are given in brackets. + +\begin{lemma}[Levine step]\label{lem:gamma} +Let $c=(c_1,\dots,c_l)$. Then $\len{\Gamma(c)}=\Sigma c$ {\upshape[\decl{length_levineAux}]}, and all terms of $\Gamma(c)$ are $\ge1$ {\upshape[\decl{levineAux_pos}]}. If $l\ge1$ and all $c_i\ge1$, then $\last(\Gamma(c))=l$ {\upshape[\decl{getLast?_levineAux}]}. If all $c_i\ge1$, then $\Sigma c\ge l$. +\end{lemma} + +\begin{proof} +The first two claims are immediate from the definition. If $l\ge1$ and $c_l\ge1$, the last block $l^{c_l}$ of $\Gamma(c)$ is nonempty, so $\Gamma(c)$ ends in $l$. The last claim is clear. +\end{proof} + +\begin{lemma}[Golomb's sequence]\label{lem:golomb} +$G(i)\ge1$ for $i\ge1$ {\upshape[\decl{golomb_pos}]}, and for every $l\ge2$, +\[ + \Gamma(P(l))=1^{G(1)}2^{G(2)}\cdots l^{G(l)}=P(l'),\qquad l'=G(1)+\dots+G(l). +\] +\end{lemma} + +\begin{proof} +Positivity holds because every stage of the construction consists of positive numbers [\decl{golombAux_pos_length}]. Let $m=l-2$. By \decl{golombAux_eq_flatMap}, the stage \texttt{golombAux m} is $1^{G(1)}\cdots l^{G(l)}=\Gamma(P(l))$, and by \decl{golombAux_eq_map} it is $P(l')$ for its length $l'$, which is $\Sigma P(l)$ by Lemma~\ref{lem:gamma}. +\end{proof} + +\begin{lemma}[Levine's rows]\label{lem:levine} +For $k\ge1$: $L_k\ge2$ {\upshape[\decl{two_le_length_levineRow}]}, $L_{k+1}=\Sigma\Lev_k\ge L_k$ {\upshape[\decl{length_levineRow_succ}, \decl{length_levineRow_le}]}, and $A(k+1)=L_k$ {\upshape[\decl{A014644_add_two}]}. For $k\ge2$: $\Lev_k=P(L_k)$ {\upshape[\decl{levineRow_eq}]}. +\end{lemma} + +\begin{proof} +All terms of $\Lev_k$ are $\ge1$ ($\Lev_1=(1,1)$ and Lemma~\ref{lem:gamma}). Hence $L_{k+1}=\len{\Gamma(\Lev_k)}=\Sigma\Lev_k\ge L_k$, and $L_k\ge L_1=2$ by induction. Since $\Lev_k$ is nonempty with positive terms, $A(k+1)=\last(\Gamma(\Lev_k))=L_k$ by Lemma~\ref{lem:gamma}. +For the last claim we induct on $k\ge2$. For $k=2$, $\Lev_2=(1,2)=P(2)$ (checked by \texttt{decide}). If $\Lev_k=P(L_k)$ with $L_k\ge2$, then by Lemma~\ref{lem:golomb} $\Lev_{k+1}=\Gamma(P(L_k))=P(l')$ for some $l'$, and necessarily $l'=L_{k+1}$. +\end{proof} + +\begin{lemma}[Telescoping]\label{lem:tele} +For $k\ge2$ {\upshape[\decl{sum_block}]}, +\[ + L_{k+1}+\sum_{i=L_k+1}^{L_{k+1}}G(i)=L_{k+2}. +\] +\end{lemma} + +\begin{proof} +As $L_k\le L_{k+1}$, $P(L_{k+1})$ is $P(L_k)$ followed by $(G(L_k+1),\dots,G(L_{k+1}))$. By Lemma~\ref{lem:levine}, $P(L_{k+1})=\Lev_{k+1}$ and $P(L_k)=\Lev_k$; taking sums and using $\Sigma\Lev_{k+1}=L_{k+2}$, $\Sigma\Lev_k=L_{k+1}$ gives the claim. +\end{proof} + +\begin{lemma}[Row ends]\label{lem:rowend} +For every $n\ge1$, $E(n)+1=L_{n+1}$ and $E(n+1)+1=L_{n+2}$ {\upshape[\decl{rowEnd_eq}]}. +\end{lemma} + +\begin{proof} +Induction on $n$. For $n=1$: $E(1)=1$, $E(2)=E(1)+H(1)=2$, $L_2=2$ and $L_3=3$ (checked by \texttt{decide}). Assume both equalities for $n$; the first one for $n+1$ is the second one for $n$. By definition, +\[ + E(n+2)=E(n+1)+\sum_{j=E(n)+1}^{E(n+1)}H(j). +\] +Since $E(n)+1=L_{n+1}\ge2$, every index $j$ in the sum is $\ge2$, so $H(j)=G(j+1)$ [\decl{map_H_range'_golomb}], and the sum equals $\sum_{i=L_{n+1}+1}^{L_{n+2}}G(i)$, which is $L_{n+3}-L_{n+2}$ by Lemma~\ref{lem:tele} with $k=n+1\ge2$. Hence $E(n+2)+1=L_{n+2}+(L_{n+3}-L_{n+2})=L_{n+3}$. +\end{proof} + +\begin{lemma}[Strict growth]\label{lem:strict} +$L_{k+1}E(n-1)$, so +\[ + R_n=(H(j))_{E(n-1)= 1, a(n) is the smallest element of the cycle that the orbit n, F(n), F(F(n)), ... eventually enters (A115026). Harvey P. Dale conjectured that a(n) <= 370 for all n >= 1. This is false: a(119) = 371. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A115026](https://oeis.org/A115026) as [`Math0.Statements.A115026.statement`](../../lean/Math0/Statements/OEIS/A115026.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A115026.lean`](../../lean/Math0/Frontier/OEIS/A115026.lean) refutes (proves the negation of) it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: no term is greater than 370. - _Harvey P. Dale_, Jun 08 2022" + +Referees: OEIS A151543, "Smallest precursor of n-th cycle in the 'Recurring Digital Invariant Variant' problem" (N. J. A. Sloane, May 15 2009, based on an email from Eric Angelini, Feb 18 2009, with a cycle table by Hans Havermann). Its table entry "13 { 119, 1, {371}}" names 119 as the smallest number whose orbit under A101337 ends in the fixed point 371, so a(119) = 371. The same table has "19 { 407, 1, {407}}" and other cycles with minima above 370. Related pre-2022 OEIS entries: A151544 (2009) lists the cycle elements, including 371 and 407. A157714 (Havermann, Mar 2009) lists numbers in cycles of period greater than 1, such as 2929 and 18829. A005188 lists the narcissistic numbers 153, 370, 371, 407, 1634, ...; since 371 is a fixed point, a(371) = 371 > 370 trivially. Angelini's page "A Recurring Digital Invariant Variant" is at cetteadressecomportecinquantesignes.com/RecurDigit.htm, with a cached copy at oeis.org/A151543/a151543.pdf. The A115026 entry itself (revision #12, Jun 08 2022, unchanged upstream) still states the conjecture and has no correction or %E extension. Web searches found no explicit published retraction of Dale's comment. Sources: https://oeis.org/A115026, https://oeis.org/A151543, https://en.wikipedia.org/wiki/Narcissistic_number + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a115026, + author = {{math0}}, + title = {{A115026 has a term greater than 370: a(119) = 371}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a115026}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a115026/paper.pdf b/results/oeis-a115026/paper.pdf new file mode 100644 index 0000000..c4466c2 Binary files /dev/null and b/results/oeis-a115026/paper.pdf differ diff --git a/results/oeis-a115026/paper.tex b/results/oeis-a115026/paper.tex new file mode 100644 index 0000000..8d9a919 --- /dev/null +++ b/results/oeis-a115026/paper.tex @@ -0,0 +1,351 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 + {→}{{$\to$}}1 {≤}{{$\le$}}1 {∈}{{$\in$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Cyc}{\Lambda} +\newcommand{\Lm}[1]{\mathtt{#1}} + +\title[The digit-power iteration from 119 ends at 371 (OEIS A115026)]{The digit-power iteration started at $119$ ends at the fixed point $371$: a counterexample to the conjecture in OEIS A115026} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Let $F(m)$ be the sum of the $L$-th powers of the decimal digits of $m$, where $L$ is the number of digits of $m$ (OEIS A101337), and let $a(n)$ be the smallest element of the cycle that the orbit $n,F(n),F(F(n)),\dots$ eventually enters (OEIS A115026). +In 2022 Harvey P.~Dale conjectured in the OEIS entry that no term $a(n)$, $n\ge1$, is greater than $370$. +The conjecture is false: $119\mapsto731\mapsto371\mapsto371$, so $a(119)=371$. +This counterexample is not new, since a 2009 table of cycles of the same iteration by Hans Havermann in OEIS A151543 already records that $119$ is the smallest number whose orbit ends at the fixed point $371$; we therefore classify this note as the first formal proof of a known result. +The refutation is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, which was reviewed for fidelity and frozen before the proof attempt, and in which $a$ is a computable function proved to return the minimum of the limit cycle and checked by the kernel against all $65$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +For an integer $m\ge1$ with $L$ decimal digits $d_{L-1}\cdots d_1d_0$, let +\[ + F(m)=\sum_{i=0}^{L-1} d_i^{\,L}. +\] +This is OEIS A101337 \cite{A101337} (Gordon Hamilton, 2004). For example, $F(89)=8^2+9^2=145$ and $F(145)=1^3+4^3+5^3=190$; note that the exponent is the number of digits of the current argument, so it can change along an orbit. +The fixed points of $F$ are the positive narcissistic (Armstrong, pluperfect) numbers $1,\dots,9,153,370,371,407,1634,\dots$ of A005188 \cite{A005188}. +Every orbit of $F$ is eventually periodic, because $F(m)370$. + +\subsection*{Prior work} +The counterexample was in the OEIS thirteen years before the conjecture was stated. +The same iteration was studied in 2009 under the name ``Recurring Digital Invariant Variant'' (A151543 \cite{A151543} attributes the name to Mensanator on the rec.puzzles site). +The entry A151543, ``Smallest precursor of $n$-th cycle in the `Recurring Digital Invariant Variant' problem'', was created by N.~J.~A. Sloane on May~15, 2009, based on an email from Eric Angelini of February~18, 2009 (see also Angelini's web page \cite{Angelini}), and contains a table, computed by Hans Havermann, of the cycles of $F$ ordered by the smallest number whose orbit ends in them (Havermann's reply to the SeqFan mailing list of February~18, 2009, reproduced on Angelini's page, already gives the first $34$ rows of this table, including the row quoted next). +Its entry ``13 \{ 119, 1, \{371\}\}'' states that $119$ is the smallest number whose orbit ends in the fixed point $371$; in the notation of A115026 this is $a(119)=371$. +The table also lists the fixed points $407$, $1634$, $8208$, \dots{} and cycles of length greater than one with minima $2929$, $18829$, $58618$, \dots, all of which are values of $a$ greater than $370$. +The table moreover implies that $119$ is the smallest counterexample: the cycles reached from some $n<119$ are the first twelve of the table, whose minima are $1,\dots,9$, $370$, $160$ and $153$. +(We confirmed by a direct computation, which is not part of the formal proof, that $a(n)\le370$ for $1\le n\le118$.) +The cycle elements are listed in A151544 \cite{A151544} (Sloane, 2009), and the elements of cycles of length greater than one in A157714 \cite{A157714} (Havermann, March~4, 2009). +Even more directly, $371$ and $407$ are narcissistic numbers, listed in A005188 \cite{A005188} long before 2022; for a fixed point $m$ of $F$ one has $a(m)=m$, so $a(371)=371$ and $a(407)=407$ also contradict the conjecture. + +The entry A115026 (revision \#12 of June~8, 2022, the version we read) does not cross-reference A151543 or A005188, has no correction of Dale's comment, and still states the conjecture. +The math0 referees found no published retraction of the comment, and the statement is not among the OEIS statements of the formal-conjectures repository \cite{FC}. +The mathematics is elementary. +What we add is a formal statement of the conjecture, with a definition of $a$ that is proved to agree with the OEIS definition, and a kernel-checked refutation. +We classify the result as the first formal proof of a known result. + +\section{Statement}\label{sec:statement} + +\subsection*{The OEIS definition and conjecture} +The name of A115026 and its first comment read, verbatim: +\begin{quote}\raggedright\frenchspacing +{\small\texttt{Limiting value of n under iteration of "sum of the digits raised to the power of the number of digits of n" (A101337).}}\\[3pt] +{\small\texttt{Iterate A101337 starting at n until reaching a constant value (like 370) or a cycle (like 160, 217, 352, 160, ...). In the latter case, a(n) takes the smallest value in the cycle (e.g., a(59) = 160). Since k*9\textasciicircum{}k < 10\textasciicircum{}k for all k > 34, each number n is guaranteed to yield a smaller number a(n) if n > 10\textasciicircum{}34, so every number reaches a constant or a cycle under this sequence.}} +\end{quote} +(Its conclusion is correct, but the inequality quoted does not by itself give $F(n) x + | fuel + 1, x, z => if x = z then x else meet fuel (F x) (F (F z)) +def cycleMin (y : ℕ) : ℕ → ℕ → ℕ → ℕ + | 0, _, m => m + | fuel + 1, cur, m => if cur = y then m else cycleMin y fuel (F cur) (min m cur) +def C : ℕ := 70 * 9 ^ 70 +def fuel (n : ℕ) : ℕ := (max n C + 2) ^ 2 +def a (n : ℕ) : ℕ := + let y := meet (fuel n) (F n) (F (F n)) + cycleMin y (fuel n) (F y) y +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → a n ≤ 370 +end Math0.Statements.A115026 +\end{lstlisting} +Here \texttt{Nat.digits 10 m} is the list of decimal digits of $m$, least significant first (empty for $m=0$), so \decl{F} is $F$, and \decl{limitCycle} is $\Cyc$. +The function \decl{a} is computable, so that the kernel can evaluate it: \decl{meet} is Floyd's tortoise-and-hare loop, which compares $F^k(n)$ with $F^{2k}(n)$ for $k=1,2,\dots$ and returns the first $F^k(n)$ with $F^k(n)=F^{2k}(n)$, and \decl{cycleMin} walks around the cycle of the returned point $y$ and keeps the minimum. Both loops carry an explicit fuel argument. +Among other lemmas, the file proves the following (statements verbatim, proofs omitted): +\begin{lstlisting} +theorem a_data : (List.range 65).map (fun i => a (i + 1)) = + [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 5, 1, 370, 370, 370, 370, 370, 1, 4, 5, 8, 1, 4, 370, 370, + 370, 1, 370, 9, 1, 1, 370, 370, 370, 370, 370, 370, 370, 370, 370, 4, 370, 1, 370, 370, + 370, 370, 1, 370, 370, 370, 370, 370, 370, 370, 370, 370, 160, 370, 370, 370, 370, 370, + 370] +theorem a_spec (n : ℕ) : a n ∈ limitCycle n ∧ ∀ m ∈ limitCycle n, a n ≤ m +\end{lstlisting} +The theorem \decl{a_data}, proved by \texttt{decide +kernel}, checks that $a(1),\dots,a(65)$ are the $65$ terms listed in the OEIS (the full \texttt{\%S}, \texttt{\%T}, \texttt{\%U} lines of the entry). +The theorem \decl{a_spec} states that \decl{a} computes $\min\Cyc(n)$ for every $n$; so the Lean function \decl{a} is the sequence of Definition~\ref{def:main}, not a conjectured formula for it. +Since the offset is $1$, ``no term is greater than $370$'' is $\forall n\ge1,\ a(n)\le370$, which is \decl{statement}; it adds no hypotheses. +We sketch the proof of \decl{a_spec}, following the lemmas of the statement file. + +\begin{lemma}[\decl{F_le}, \decl{key_ineq}, \decl{F_le_max}, \decl{iterate_le}]\label{lem:bound} +Let $C=70\cdot9^{70}$. For all $m,n\in\N$ and $k\ge0$ we have $F(m)\le\max(m,C)$ and $F^k(n)\le\max(n,C)$. +\end{lemma} + +\begin{proof} +If $m$ has $L$ digits, each at most $9$, then $F(m)\le L\cdot9^L$. If $L<70$ this is at most $C$. If $L\ge70$, then $10L\cdot9^L<10^L$ (by induction on $L$: it holds for $L=70$, and $10(L+1)9^{L+1}=9\cdot10(L+1)9^L\le10\cdot10L\cdot9^L<10^{L+1}$ since $9(L+1)\le10L$), and $10^L\le10m$ because $m\ge10^{L-1}$; hence $10F(m)<10m$. The bound for $F^k(n)$ follows by induction on $k$. +\end{proof} + +\begin{proposition}[\decl{a_spec}]\label{prop:spec} +For every $n\in\N$, $a(n)\in\Cyc(n)$ and $a(n)\le m$ for every $m\in\Cyc(n)$. +\end{proposition} + +\begin{proof}[Sketch] +Let $M=\max(n,C)$, so that \texttt{fuel n} is $(M+2)^2$. By Lemma~\ref{lem:bound} the $M+2$ values $F^0(n),\dots,F^{M+1}(n)$ lie in $\{0,\dots,M\}$, so by the pigeonhole principle $F^i(n)=F^j(n)$ for some $i119$; all that matters below is $N\ge2$. By definition, $a(119)=\Lm{cycleMin}(y,N,F(y),y)$ with $y=\Lm{meet}(N,F(119),F(F(119)))$. By Lemma~\ref{lem:orbit}, +\[ + y=\Lm{meet}(N,731,371)=\Lm{meet}(N-1,F(731),F(F(371)))=\Lm{meet}(N-1,371,371)=371, +\] +where the first step uses $731\ne371$ and $N\ge1$, and the last uses $371=371$ and $N-1\ge1$. Then +\[ + a(119)=\Lm{cycleMin}(371,N,F(371),371)=\Lm{cycleMin}(371,N,371,371)=371, +\] +because $N\ge1$ and the current point $371$ equals $y$, so the loop returns its accumulator $371$ at once. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +By Lemma~\ref{lem:a119} and Proposition~\ref{prop:spec}, $a(119)=371$ for the sequence of Definition~\ref{def:main}. If $a(n)\le370$ held for all $n\ge1$, then in particular $371=a(119)\le370$, which is absurd. This is the Lean theorem \decl{result}: it applies the hypothesis at $n=119$, rewrites with $a(119)=371$, and derives a contradiction from the hypothesis $371\le370$ with \texttt{omega}. +\end{proof} + +\begin{remark}[direct check]\label{rem:direct} +The value $a(119)=371$ can also be read off from Definition~\ref{def:main} without the algorithm. By Lemma~\ref{lem:orbit} the orbit of $119$ is $\{119,731,371\}$. The point $371$ is periodic with period $1$. The point $119$ is not periodic, because $F^p(119)\in\{731,371\}$ for all $p\ge1$, and $731$ is not periodic, because $F^p(731)=371$ for all $p\ge1$. So $\Cyc(119)=\{371\}$ and $a(119)=371$. In the Lean development this argument is not needed, since Proposition~\ref{prop:spec} holds for every $n$. +\end{remark} + +\begin{remark}[the certificate]\label{rem:kernel} +The Lean proof of Lemma~\ref{lem:a119} is \texttt{decide +kernel}: the kernel reduces the decision procedure for the equality \texttt{a 119 = 371} on natural numbers to \texttt{true}, unfolding \decl{a}, \decl{fuel}, \decl{meet}, \decl{cycleMin}, \decl{F} and \texttt{Nat.digits}. Arithmetic on numerals, including $C\approx4.4\cdot10^{68}$ and $N\approx1.9\cdot10^{137}$, uses the kernel's built-in arbitrary-precision natural numbers, and only the two iterations of \decl{meet} and the single iteration of \decl{cycleMin} described in the proof of Lemma~\ref{lem:a119} are executed, so the size of the fuel is harmless. The theorem \decl{a_data} of the statement file is checked in the same way. Unlike \texttt{native\_decide}, this introduces no axiom and does not trust the compiler. +\end{remark} + +\begin{remark}[further counterexamples; not formalized] +By direct computation, the integers $n\le200$ with $a(n)>370$ begin $119,137,147,159,168,173,\dots$, with $a(137)=a(173)=371$, $a(147)=18829$ (the minimum of a cycle of length $14$) and $a(177)=58618$ (the minimum of a cycle of length $2$). Every narcissistic number $m\ge371$, such as $371$, $407$ or $1634$, satisfies $a(m)=m$. The Lean proof uses only $n=119$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in the file \path{lean/Math0/Frontier/OEIS/A115026.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A115026.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A115026.result}, of type $\neg$\,\decl{Math0.Statements.A115026.statement}. The file reads, verbatim (the copyright header, imports, module docstring and docstrings omitted): +\begin{lstlisting} +namespace Math0.Frontier.A115026 +open Math0.Statements.A115026 +private theorem a_119 : a 119 = 371 := by + decide +kernel +theorem result : ¬ statement := by + intro h + have h119 := h 119 (by norm_num) + rw [a_119] at h119 + omega +end Math0.Frontier.A115026 +#math0_settles Math0.Frontier.A115026.result Math0.Statements.A115026.statement +\end{lstlisting} +The file uses no \texttt{native\_decide}, \texttt{sorry}, \texttt{axiom} or \texttt{set\_option}. It does not use \decl{a_spec}: the theorem \decl{result} refutes \decl{statement} as stated, about the function \decl{a}, and \decl{a_spec} is what identifies that function with the OEIS sequence. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} introduced by \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata annotations, with no unfolding. On this file it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A115026.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A115026.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A115026.result' refutes 'Math0.Statements.A115026.statement' +\end{lstlisting} +so \decl{result} proves the negation of the statement and depends only on the three standard axioms. The theorems \decl{a_data} and \decl{a_spec} of the statement file also depend only on these axioms. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A115026.lean} in the directory \path{lean}; this takes about a minute or less on our machine, most of it spent loading Mathlib. + +{\small +\begin{thebibliography}{99} + +\bibitem{Angelini} +E.~Angelini, \emph{A Recurring Digital Invariant Variant}, web page, \url{http://www.cetteadressecomportecinquantesignes.com/RecurDigit.htm}; cached copy at \url{https://oeis.org/A151543/a151543.pdf}. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A005188} +The OEIS Foundation Inc., \url{https://oeis.org/A005188} (Armstrong, or narcissistic, numbers), entry by N.~J.~A. Sloane and R.~G. Wilson~v. + +\bibitem{A101337} +The OEIS Foundation Inc., \url{https://oeis.org/A101337}, entry by G.~Hamilton (Dec.~24, 2004). + +\bibitem{A115026} +The OEIS Foundation Inc., \url{https://oeis.org/A115026}, entry by S.~Pimentel (Feb.~24, 2006); conjecture by H.~P. Dale (June~8, 2022); revision \#12, June~8, 2022. + +\bibitem{A151543} +The OEIS Foundation Inc., \url{https://oeis.org/A151543}, entry by N.~J.~A. Sloane (May~15, 2009), based on an email from E.~Angelini (Feb.~18, 2009), with a table of cycles by H.~Havermann. + +\bibitem{A151544} +The OEIS Foundation Inc., \url{https://oeis.org/A151544}, entry by N.~J.~A. Sloane (May~15, 2009), based on an email from E.~Angelini. + +\bibitem{A157714} +The OEIS Foundation Inc., \url{https://oeis.org/A157714} (base-10 pseudo-altruistic numbers), entry by H.~Havermann (Mar.~4, 2009). + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a116184/README.md b/results/oeis-a116184/README.md new file mode 100644 index 0000000..677aecf --- /dev/null +++ b/results/oeis-a116184/README.md @@ -0,0 +1,51 @@ +# A116184: Adamchuk's conjectures on 37^3 dividing the numerator of sum_{k=1}^{36} 1/k^n + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Number theory +**Source problem:** OEIS A116184 +**Date:** 2026-10-19 + +## Result + +Let H(n) = sum_{k=1}^{36} 1/k^n, a rational number. Claim (a): for every k >= 0, 37^3 divides the numerator of H(3 + 36k). Claim (b): if p > 37 is a prime and 37^3 divides the numerator of H(p), then p = 37k - 1 for some natural number k, that is, p ≡ -1 (mod 37). + +## Assessment + +Both claims are about one fixed modulus, 37^3, and the denominator of H(36,n) is prime to 37. By Euler's theorem, whether n is a term depends only on n mod 49284. Both conjectures therefore reduce to a finite computation over one period. For (b), a prime above 37 is coprime to 49284, so only the residues coprime to 49284 need checking. The manuscript's truncated binomial expansion only makes this check cheaper. Its alternative derivation also takes just a few lines from Sun's power-sum congruence, Kummer's congruences and the irregular pair (37,32). No new idea was needed. + +*Follows from:* Euler's theorem: since 37 does not divide k for 1 <= k <= 36, whether 37^3 divides the numerator of H(36,n) depends only on n mod phi(37^3) = 49284, so both claims reduce to checking one period. Alternatively, it follows from the classical power-sum congruence of Glaisher/Sun, S_m = p B_m + (p^2/2) m B_{m-1} + ... (mod p^3), together with Kummer's congruences and the fact that (37,32) is the only irregular pair of 37. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A116184](https://oeis.org/A116184) as [`Math0.Statements.A116184.statement`](../../lean/Math0/Statements/OEIS/A116184.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A116184.lean`](../../lean/Math0/Frontier/OEIS/A116184.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: All terms of the arithmetic progression 3+36k belong to a(n). ... It appears that all primes in a(n) that are greater than 37 are of the form 37k-1. (Alexander Adamchuk, Apr 08 2007) + +Referees: No explicit prior resolution of the A116184 conjecture found. OEIS A116184 is unchanged (rev #6, Feb 16 2025) with no %E line or resolving comment, and no other mirror entry cross-references it. Classical ingredients that make it an easy corollary: +- J.W.L. Glaisher, Q. J. Math. 31 (1900) 321-353: H(p-1,m) ≡ -m(m+1)/(2(m+2))·p^2·B_{p-2-m} (mod p^3) for odd m ≤ p-3. +- Z.-H. Sun, "Congruences concerning Bernoulli numbers and Bernoulli polynomials", Discrete Appl. Math. 105 (2000) 193-223: Thm 5.1(a) (k ≤ p-4) and the power-sum formula S_k ≡ pB_k + (p^2/2)kB_{k-1} + (p^3/6)k(k-1)B_{k-2} (mod p^3), as quoted in C. Levaillant, arXiv:2005.09434, Results 2 and 4. +- J. Zhao, arXiv:math/0301252: (p, p-2n-1) is irregular iff H(p-1, 2n-1) ≡ 0 (mod p^3) for p ≥ 2n+3. +- Kummer congruences, plus (37,32) being an irregular pair. +- R. Meštrović, arXiv:1111.3057, eq. (22). +- OEIS A007408 comment (Adamchuk 2006): 37^3 | numerator of H(36,3), i.e. the k=0 case. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a116184, + author = {{math0}}, + title = {{A116184: Adamchuk's conjectures on 37^3 dividing the numerator of sum_{k=1}^{36} 1/k^n}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a116184}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a116184/paper.pdf b/results/oeis-a116184/paper.pdf new file mode 100644 index 0000000..ddab892 Binary files /dev/null and b/results/oeis-a116184/paper.pdf differ diff --git a/results/oeis-a116184/paper.tex b/results/oeis-a116184/paper.tex new file mode 100644 index 0000000..fc9c112 --- /dev/null +++ b/results/oeis-a116184/paper.tex @@ -0,0 +1,375 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 + {∃}{{$\exists$}}1 {→}{{$\to$}}1 {∧}{{$\wedge$}}1 {∑}{{$\sum$}}1 {∈}{{$\in$}}1 + {∣}{{$\mid$}}1 {≥}{{$\ge$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {…}{{$\dots$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} +\emergencystretch=3em + +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\code}[1]{\texttt{#1}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\Term}{\mathcal{T}} +\newcommand{\Zm}{\Z/37^3\Z} +\DeclareMathOperator{\num}{num} + +\title[Adamchuk's conjectures for OEIS A116184]{Divisibility of the numerators of $\sum_{k=1}^{36}k^{-n}$ by $37^3$: a proof of Adamchuk's conjectures on OEIS A116184} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 19, 2026} +\hypersetup{pdftitle={Divisibility of the numerators of sum 1/k\textasciicircum n (k=1..36) by 37\textasciicircum 3: a proof of Adamchuk's conjectures on OEIS A116184},pdfauthor={math0}} + +\begin{document} +\begin{abstract} +OEIS A116184 lists the integers $n\ge1$ for which $37^3$ divides the numerator of $H(n)=\sum_{k=1}^{36}k^{-n}$, and records two conjectures of Alexander Adamchuk (2007): every $n=3+36k$ with $k\ge0$ is a term, and every prime term $p>37$ is of the form $37k-1$. We prove both conjectures. The proof reduces the condition to the vanishing modulo $37^3$ of a sum of $n$-th powers of $36$ explicit residues, uses a binomial expansion truncated modulo $37^3$ to show that it depends only on $n\bmod 36$ and $\lfloor n/36\rfloor\bmod 37^2$, and finishes with a finite computation. We found no earlier proof and classify the result as new, with the caveat that it is close to classical theory: the case $k=0$ is a known consequence of $37$ dividing the numerator of $B_{32}$, and the whole statement can also be derived from congruences of Sun, von Staudt--Clausen and Kummer (Remark~\ref{rem:classical}). The theorem is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before the proof attempt, whose definitions are checked by the kernel against all $53$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +For an integer $n\ge0$ put +\[ + H(n)=\sum_{k=1}^{36}\frac1{k^n}\in\Q , +\] +the generalized harmonic number written $H(36,n)$ in the OEIS, and let $\num H(n)$ be its numerator in lowest terms. The sequence A116184 of the OEIS \cite{A116184}, contributed by Alexander Adamchuk on April~8, 2007, is +\begin{quote} +``Numbers n such that 37\^{}3 divides the numerator of generalized harmonic number H(36,n) = Sum[ 1/k\^{}n, \{k,1,36\} ].'' +\end{quote} +It has offset $1$ and lists $53$ terms, $3,37,39,73,75,111,147,148,\dots,961,975$. In the COMMENTS section Adamchuk wrote: +\begin{quote} +``Conjecture: All terms of the arithmetic progression 3+36k belong to a(n). Prime terms in a(n) are \{3, 37, 73, 443, 739, 887, 1109, ...\}. It appears that all primes in a(n) that are greater than 37 are of the form 37k-1.'' (Alexander Adamchuk, Apr~08 2007) +\end{quote} +We prove both conjectural claims (Theorem~\ref{thm:main}). + +\subsection*{Background} +The prime $37$ is the smallest irregular prime: it divides the numerator of the Bernoulli number $B_{32}=-7709321041217/510$ and of no other $B_e$ with $e\in\{2,4,\dots,34\}$, so $(37,32)$ is its only irregular pair (see \cite{Wa} for irregular primes and Kummer's congruences). Wolstenholme-type congruences relate $H(p-1,m)=\sum_{k=1}^{p-1}k^{-m}$ modulo powers of $p$ to Bernoulli numbers; see the survey of Me\v{s}trovi\'c \cite{Me}. For odd $m$ with $1\le m\le p-4$, a congruence going back to Glaisher \cite{Gl} and given in this form by Sun \cite[Thm.~5.1(a)]{Su} (see also \cite[Result~4]{Le}) states +\[ + H(p-1,m)\equiv\frac{m(m+1)}{2}\cdot\frac{B_{p-2-m}}{p-2-m}\,p^2\pmod{p^3}, +\] +and Zhao \cite[Thm.~2.8]{Zh} shows that, for $p\ge 2n+3$, $p\mid B_{p-2n-1}$ if and only if $H(p-1,2n-1)\equiv0\pmod{p^3}$. With $p=37$ and $m=3$ this gives $37^3\mid\num H(3)$, the case $k=0$ of the first conjecture; Adamchuk recorded this divisibility in OEIS A007408 \cite{A007408} in 2006. Zhao \cite[\S2.1]{Zh} also studies the $p$-adic valuation of $H(p-1,s)$ for general $s$, via power sums and Kummer's congruences; he determines it for regular $p$ and bounds it for irregular $p$ under extra hypotheses, noting $p=37$, $s=1048$ as the first case where the bound fails without them \cite[Rem.~2.6]{Zh}. These results do not address the progression $3+36k$ or the prime terms. + +\subsection*{Status} +In the current revision of A116184 (\#6, February~16, 2025) both statements are still conjectures, and the entry has no later comment on them. The math0 referees found no proof in the OEIS entries related to A116184 (A007408, A119722, A017533 and other entries by Adamchuk) or by web searches. We therefore classify Theorem~\ref{thm:main} as a \emph{new result}, with a caveat: it is elementary. Our proof is a periodicity argument plus a finite computation, and Remark~\ref{rem:classical} sketches an alternative derivation from classical congruences that a specialist could carry out in a few lines; we did not find that derivation written down. + +\section{Statement}\label{sec:statement} + +Let $\Term=\{n\in\N:\ 37^3\mid\num H(n)\}$. Since $H(0)=36$, $0\notin\Term$, so $\Term$ is the set of terms of A116184. + +\begin{theorem}\label{thm:main} +\leavevmode +\begin{enumerate} +\item[(a)] For every integer $k\ge0$, $37^3$ divides the numerator of $H(3+36k)$. +\item[(b)] If $p>37$ is a prime and $37^3$ divides the numerator of $H(p)$, then $p=37k-1$ for some integer $k\ge1$, that is, $p\equiv-1\pmod{37}$. +\end{enumerate} +\end{theorem} + +\subsection*{The Lean statement} +The statement was formalized by math0 in the file \path{lean/Math0/Statements/OEIS/A116184.lean}, reviewed for fidelity against the OEIS entry, and frozen (SHA-256 \texttt{a38dde38\ldots f163f9}) before any proof attempt. The definitions used by the statement, the sequence \code{a}, and the statement itself are, verbatim: +\begin{lstlisting} +/-- The generalized harmonic number `H(36, n) = ∑_{k=1}^{36} 1/k^n`, computed exactly in `ℚ`. -/ +def H (n : ℕ) : ℚ := ∑ k ∈ Finset.Icc (1 : ℕ) 36, 1 / ((k : ℚ) ^ n) + +/-- `n` is a term of A116184: `37^3` divides the numerator of `H(36, n)`. -/ +def IsTerm (n : ℕ) : Prop := (37 ^ 3 : ℤ) ∣ (H n).num + +/-- A116184: the `n`-th smallest (offset `1`) number `m` such that `37^3` divides the numerator +of `H(36, m) = ∑_{k=1}^{36} 1/k^m`. -/ +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) + +/-- Conjecture (Adamchuk, A116184): (a) every term `3 + 36k` (`k ≥ 0`) of the arithmetic +progression belongs to the sequence, and (b) every prime term greater than `37` is of the form +`37k - 1`. -/ +def statement : Prop := + (∀ k : ℕ, IsTerm (3 + 36 * k)) ∧ + (∀ p : ℕ, p.Prime → 37 < p → IsTerm p → ∃ k : ℕ, p = 37 * k - 1) +\end{lstlisting} +All declarations are in the namespace \decl{Math0.Statements.A116184}. + +\subsection*{How the Lean definitions encode the entry} +\code{H n} is $H(n)$, computed exactly in $\Q$, and \code{(H n).num} is Mathlib's \decl{Rat.num}, the numerator in lowest terms. So \code{IsTerm n} is $n\in\Term$, the defining property of the entry, and \code{a n = Nat.nth IsTerm (n - 1)} is the $n$-th smallest term with offset $1$. The statement file proves that $0$ is not a term (\decl{not_isTerm_zero}) and that a positive integer $x$ equals $a(m)$ for some $m\ge1$ if and only if \code{IsTerm x} (\decl{exists_a_eq_iff}); therefore ``belongs to a(n)'' and ``primes in a(n)'' are expressed through \code{IsTerm}. Part (a) of \code{statement} quantifies over $k\ge0$; the progression starts at the listed term $3$. In part (b), $37k-1$ is truncated subtraction in $\N$; it is harmless, because $k=0$ gives $0\ne p$, and for $k\ge1$ it is ordinary subtraction. The list of prime terms quoted in the comment is example data, not a claim, and is not formalized. + +The statement file also gives a decision procedure for \code{IsTerm} (Lemma~\ref{lem:reduce} below; \decl{isTerm_iff_check}) and a \decl{DecidablePred} instance built from it. With it, the theorem \decl{a_data} checks that $a(1),\dots,a(53)$ are the $53$ terms listed in the entry: the kernel evaluates a \decl{List.filter} over $\{0,\dots,975\}$ (by \texttt{decide +kernel}), and a general lemma, \decl{map_nth_eq_of_filter}, identifies the filtered list with the values \code{Nat.nth IsTerm i} for $i<53$. (The entry's program scans $n\le1000$; the next term, $999=27\cdot37$, is not in the listed data and is not used.) + +\section{Proof}\label{sec:proof} + +Throughout, $M=37^3=50653$ and congruences without modulus are in $\Zm$. Let $\iota=25327$; then $2\iota=M+1$, so $\iota$ is the inverse of $2$ in $\Zm$. + +\subsection{Reduction to a sum of residues} +Let $F=36!$ and, for $1\le k\le36$, let $c_k\in\{0,\dots,M-1\}$ be the residue of $F/k$ modulo $M$. The list $C=(c_1,\dots,c_{36})=(23531,37092,24728,\dots,18945)$ is written out in the statement file as \code{coeffs}, and \decl{coeffs_eq} checks it by kernel evaluation. For $n\in\N$ let +\[ + \Sigma(n)=\sum_{k=1}^{36}c_k^{\,n}\in\Zm. +\] + +\begin{lemma}[\decl{H_eq}, \decl{dvd_num_iff}, \decl{isTerm_iff_check}, \decl{check_iff}]\label{lem:reduce} +For every $n\in\N$, $n\in\Term$ if and only if $\Sigma(n)=0$ in $\Zm$. +\end{lemma} + +\begin{proof} +Since $k\mid F$ for $1\le k\le 36$, $H(n)=s/F^n$ with $s=\sum_{k=1}^{36}(F/k)^n\in\N$. As $37$ is prime and $37>36$, $\gcd(M,F^n)=1$. We claim that if $q=s/b$ with $b\ne0$ and $\gcd(M,b)=1$, then $M\mid\num q$ if and only if $M\mid s$. Indeed, writing $q=\num q/\operatorname{den}q$ in lowest terms, we have $\num q\cdot b=s\cdot\operatorname{den}q$ and $\operatorname{den}q\mid b$, so $\operatorname{den}q$ is prime to $M$ as well. If $M\mid\num q$, then $M\mid s\operatorname{den}q$ and hence $M\mid s$; if $M\mid s$, then $M\mid \num q\cdot b$ and hence $M\mid\num q$. Finally $s\equiv\sum_k c_k^n\pmod M$. +\end{proof} + +In the statement file this is \decl{isTerm_iff_check}, with the Boolean test \code{check n}: $\bigl(\sum_{c\in C}(c^n\bmod M)\bigr)\bmod M=0$; the proof file restates it in $\Zm$ (Mathlib's \code{ZMod 50653}) as \decl{check_iff}. + +\subsection{A truncated binomial expansion} +For $c\in C$ put $a_c=\bigl((c^{36}\bmod M)-1\bigr)/37$ (integer division). + +\begin{lemma}[\decl{A_spec}]\label{lem:fermat} +For every $c\in C$, $c^{36}\bmod M=1+37a_c$. In particular $c^{36}=1+37a_c$ in $\Zm$, and $0\le a_c<37^2$. +\end{lemma} + +\begin{proof} +Since $37\nmid c$, $c^{36}\equiv1\pmod{37}$ by Fermat's little theorem, so $c^{36}\bmod M-1$ is divisible by $37$. In Lean the $36$ instances are checked directly by kernel evaluation (\texttt{decide +kernel}); the values $a_c$ lie between $7$ and $1336$. +\end{proof} + +\begin{lemma}[\decl{key_pow}]\label{lem:binom} +Let $x,a\in\Zm$ with $x^{36}=1+37a$. Then for all $r,t\in\N$, +\[ + x^{r+36t}=x^r\bigl(1+37\,a\,t+37^2\iota\,a^2\,t(t-1)\bigr). +\] +\end{lemma} + +\begin{proof} +As $x^{r+36t}=x^r(1+37a)^t$, it suffices to show $(1+37a)^t=Q(t)$, where $Q(t)=1+37at+37^2\iota a^2t(t-1)$. For $t=0$ both sides are $1$. For the induction step, a direct expansion gives +\[ + Q(t)(1+37a)-Q(t+1)=37^2a^2t\,(1-2\iota)+37^3\iota a^3t(t-1)=M\bigl(-37^2a^2t+\iota a^3t(t-1)\bigr), +\] +using $1-2\iota=-M$. This is $0$ in $\Zm$, so $(1+37a)^{t+1}=Q(t)(1+37a)=Q(t+1)$. +\end{proof} + +For $j\in\{0,1,2\}$ and $r\in\N$ define the natural numbers +\[ + S_j(r)=\sum_{c\in C}c^r a_c^{\,j}. +\] + +\begin{lemma}[\decl{sum_pow}]\label{lem:sum} +For all $r,t\in\N$, in $\Zm$, +\[ + \Sigma(r+36t)=S_0(r)+37\,t\,S_1(r)+37^2\iota\,t(t-1)\,S_2(r). +\] +\end{lemma} + +\begin{proof} +Apply Lemma~\ref{lem:binom} to each $c\in C$, which is allowed by Lemma~\ref{lem:fermat}, and sum over $C$. +\end{proof} + +\subsection{Part (a)} +By kernel evaluation, $M$ divides $S_0(3)$, $37\,S_1(3)$ and $37^2S_2(3)$; in fact $S_0(3)\equiv0$, $S_1(3)\equiv10952=8\cdot37^2$ and $S_2(3)\equiv7215=195\cdot37\pmod M$. Hence, by Lemma~\ref{lem:sum} with $r=3$ and $t=k$, +\[ + \Sigma(3+36k)=S_0(3)+k\cdot\bigl(37S_1(3)\bigr)+\iota k(k-1)\cdot\bigl(37^2S_2(3)\bigr)=0 +\] +for every $k\in\N$, and $3+36k\in\Term$ by Lemma~\ref{lem:reduce}. This is \decl{part_a}. \qed + +\subsection{Part (b)} +For $a_0,a_1,a_2\in\Zm$ and $t\in\N$ let $E(t)=a_0+37ta_1+37^2\iota\,t(t-1)a_2$. + +\begin{lemma}[\decl{reduce_t}]\label{lem:period} +$E(t)=E(t\bmod 37^2)$ for every $t\in\N$. +\end{lemma} + +\begin{proof} +Write $t=u+37^2q$ with $u=t\bmod37^2$. Then $37t=37u+Mq$, and +\[ + t(t-1)=u(u-1)+37^2q\,(2u-1+37^2q), +\] +so $37^2\iota\,t(t-1)-37^2\iota\,u(u-1)=37\cdot M\iota q(2u-1+37^2q)$. Both differences vanish in $\Zm$. +\end{proof} + +Thus, for fixed $r$, $\Sigma(r+36t)$ depends only on $t\bmod 37^2$. The values $T_j(r)=S_j(r)\bmod M$ for $r<36$ and $j=0,1,2$ are written out as three lists of $36$ numbers in the proof file (\code{T0}, \code{T1}, \code{T2}), and the kernel checks that they are correct (\decl{T0_spec}, \decl{T1_spec}, \decl{T2_spec}). Let +\[ + R=\{r<36:\ r\text{ odd},\ 3\nmid r\}=\{1,5,7,11,13,17,19,23,25,29,31,35\}. +\] + +\begin{lemma}[\decl{finite_b_aux}, \decl{finite_b}]\label{lem:finite} +Let $r\in R$ and $0\le u<37^2$, and suppose $r+36u\not\equiv0\pmod{37}$ and +\[ + T_0(r)+37\,u\,T_1(r)+37^2\iota\,u\,(u+M-1)\,T_2(r)\equiv0\pmod M. +\] +Then $r+36u\equiv36\pmod{37}$. +\end{lemma} + +\begin{proof} +This is a finite check of $12\cdot1369=16428$ pairs $(r,u)$. In Lean, the test for one pair is the Boolean function +\begin{lstlisting} +private def okU (r a0 a1 a2 u : ℕ) : Bool := + (r + 36 * u) % 37 == 0 || + (a0 + 37 * u * a1 + 1369 * 25327 * u * (u + 50652) * a2) % 50653 != 0 || + (r + 36 * u) % 37 == 36 +\end{lstlisting} +and \decl{finite_b_aux} states that \code{okU r (T0.getD r 0) (T1.getD r 0) (T2.getD r 0) u = true} for all $r<36$ with $r\bmod 2=1$, $r\bmod 3\ne0$, and all $u<1369$. It is proved by \texttt{decide +kernel}: the kernel evaluates the bounded quantifiers and the test, using its built-in arithmetic on natural number literals. The factor $u+M-1$ is used in place of $u-1$ to avoid truncated subtraction; it is congruent to $u-1$ modulo $M$. (Exactly $407$ pairs satisfy both hypotheses.) +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}(b)] +Let $p>37$ be a prime with $p\in\Term$. Then $p$ is divisible by none of $2$, $3$, $37$. Write $p=r+36t$ with $r=p\bmod36$ and $t=\lfloor p/36\rfloor$, and let $u=t\bmod37^2$. Since $2\mid36$ and $3\mid36$, $r$ is odd and $3\nmid r$, so $r\in R$. By Lemmas~\ref{lem:reduce}, \ref{lem:sum} and \ref{lem:period}, +\[ + 0=\Sigma(p)=S_0(r)+37\,u\,S_1(r)+37^2\iota\,u(u-1)\,S_2(r), +\] +and reducing $S_j(r)$ modulo $M$ gives the congruence in Lemma~\ref{lem:finite}. Moreover $p=r+36u+36\cdot37^2\lfloor t/37^2\rfloor\equiv r+36u\pmod{37}$, so $r+36u\not\equiv0\pmod{37}$. Lemma~\ref{lem:finite} gives $r+36u\equiv36\pmod{37}$, hence $p\equiv36\pmod{37}$ and $p=37\bigl(\lfloor p/37\rfloor+1\bigr)-1$. This is \decl{part_b}. +\end{proof} + +Theorem~\ref{thm:main} is \code{result : statement}, proved as the pair of \decl{part_a} and \decl{part_b}. + +\begin{remark}[periodicity] +By Lemmas~\ref{lem:reduce}, \ref{lem:sum} and~\ref{lem:period}, membership in $\Term$ depends only on $n\bmod \varphi(37^3)=36\cdot37^2=49284$. The proof organizes the check of one period so that part~(a) needs three divisibilities and part~(b) needs $16428$ evaluations of a quadratic polynomial. +\end{remark} + +\begin{remark}[a derivation from classical congruences; not formalized]\label{rem:classical} +Theorem~\ref{thm:main} also follows from classical results. Let $p=37$, let $n$ be odd, and choose $N$, a multiple of $49284$, with $N>n+4$. Then $H(n)\equiv\sum_{k=1}^{36}k^{N-n}\pmod{p^3}$ in $\Z_{(p)}$, and $m=N-n$ is odd with $m\ge5$, so $B_m=B_{m-2}=0$, and Sun's congruence for power sums \cite{Su} (see \cite[Result~2]{Le}), +\[ + \sum_{k=1}^{p-1}k^m\equiv pB_m+\tfrac{p^2}{2}mB_{m-1}+\tfrac{p^3}{6}m(m-1)B_{m-2}\pmod{p^3}, +\] +gives $H(n)\equiv\tfrac{p^2}{2}mB_{m-1}\pmod{p^3}$. Note $m\equiv-n\pmod{p^2}$, since $p^2\mid N$, and $m-1\equiv-(n+1)$ modulo $p$ and modulo $p-1=36$. +If $n\not\equiv35\pmod{36}$, then $p-1\nmid m-1$, so $B_{m-1}/(m-1)$ is $p$-integral, and by Kummer's congruences it is congruent modulo $p$ to $B_e/e$, where $e\in\{2,\dots,34\}$ and $e\equiv-(n+1)\pmod{36}$. Since $32$ is the only such index with $p\mid B_e$, and since $p\mid m\iff37\mid n$ and $p\mid m-1\iff37\mid n+1$, one obtains: $n\in\Term$ if and only if $37\mid n$, or $37\mid n+1$, or $n\equiv3\pmod{36}$. +If $n\equiv35\pmod{36}$, then $pB_{m-1}\equiv-1\pmod p$ by the von Staudt--Clausen theorem, so $v_p(H(n))=1+v_p(n)$ when $v_p(n)\le1$, and $n\in\Term$ if and only if $37^2\mid n$. +Part~(a) is the case $n\equiv3\pmod{36}$. For part~(b), let $p'>37$ be a prime in $\Term$. Then $p'$ is odd and $37^2\nmid p'$, so $p'\not\equiv35\pmod{36}$ by the second case; and $37\nmid p'$ and $p'\not\equiv3\pmod{36}$ (as $3\nmid p'$), so $37\mid p'+1$ by the first case. We checked this characterization of the odd elements of $\Term$ numerically over a full period $1\le n\le49284$; it is not part of the formal proof. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in the file \path{lean/Math0/Frontier/OEIS/A116184.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file (Section~\ref{sec:statement}) and \path{Math0/Audit.lean}. The main declaration is \code{theorem result : statement} in the namespace \decl{Math0.Frontier.A116184}; the file ends with the command +\begin{lstlisting} +#math0_settles Math0.Frontier.A116184.result Math0.Statements.A116184.statement +\end{lstlisting} +Of the declarations named in Section~\ref{sec:proof}, \decl{coeffs_eq}, \decl{H_eq}, \decl{dvd_num_iff} and \decl{isTerm_iff_check} are in the statement file; the others, except \code{result}, are private lemmas of the proof file. The algebra in $\Zm$ is done in \code{ZMod 50653}. Lemmas~\ref{lem:binom} and~\ref{lem:period} are proved with \texttt{linear\_combination}, using the fact \code{(50653 : ZMod 50653) = 0}; the coefficients of these linear combinations are the multipliers of $M$ displayed in the proofs above. Lemma~\ref{lem:sum} follows from Lemma~\ref{lem:binom} by \texttt{ring} and a list lemma, \code{sum\_expand}, that distributes the sum. + +\subsection*{The certificate} +All finite facts are proved by \texttt{decide +kernel}, so they are checked by the Lean kernel, which evaluates arithmetic on natural number literals with its built-in big-number operations. They are: the residue table \decl{coeffs_eq}, the data check \decl{a_data} and \decl{not_isTerm_zero} (statement file); \decl{A_spec} ($36$ instances); the tables \decl{T0_spec}, \decl{T1_spec}, \decl{T2_spec} ($3\times36$ entries, involving $c^r$ for $r\le35$); the three divisibilities for $r=3$ in \decl{part_a}; and \decl{finite_b_aux} ($16428$ evaluations of \code{okU}). Neither file uses \texttt{native\_decide}, \texttt{sorry}, \texttt{set\_option} or new axioms. Checking the proof file with \texttt{lake env lean} takes about one minute. + +\subsection*{Audit} +The command \texttt{\#math0\_settles} (in \path{lean/Math0/Audit.lean}) is used for statements that math0 formalizes itself. It fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (so no \decl{sorryAx}, no \texttt{native\_decide}, and no custom axioms); and (3) the type of \decl{result} is syntactically the constant \decl{statement} or its negation, up to metadata, with no unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A116184.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A116184.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A116184.result' proves 'Math0.Statements.A116184.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use (A116184 is not in formal-conjectures). To reproduce, run \path{scripts/verify.sh} from the repository root; it builds all math0 results with \texttt{lake build}, re-running every audit command, and checks that the pinned dependencies are unmodified. The single file is checked by \texttt{lake env lean Math0/Frontier/OEIS/A116184.lean} in \path{lean/}. + +{\small +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching et al., \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026; \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Gl} +J.~W.~L. Glaisher, \emph{On the residues of the sums of products of the first $p-1$ numbers, and their powers, to modulus $p^2$ or $p^3$}, Quart.\ J. Math.\ \textbf{31} (1900), 321--353. + +\bibitem{Le} +C.~I. Levaillant, \emph{Congruences related to Miki's identity}, arXiv:2005.09434, 2020. + +\bibitem{Me} +R.~Me\v{s}trovi\'c, \emph{Wolstenholme's theorem: its generalizations and extensions in the last hundred and fifty years (1862--2012)}, arXiv:1111.3057, 2011. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput.\ Sci.\ \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Su} +Z.-H. Sun, \emph{Congruences concerning Bernoulli numbers and Bernoulli polynomials}, Discrete Appl.\ Math.\ \textbf{105} (2000), 193--223. + +\bibitem{Wa} +L.~C. Washington, \emph{Introduction to Cyclotomic Fields}, 2nd ed., Graduate Texts in Mathematics \textbf{83}, Springer, 1997. + +\bibitem{Zh} +J.~Zhao, \emph{Multiple harmonic sums I: generalizations of Wolstenholme's theorem}, arXiv:math/0301252 (v6, 2006; numbering cited from this version); published as \emph{Wolstenholme type theorem for multiple harmonic sums}, Int.\ J. Number Theory \textbf{4} (2008), 73--106. + +\bibitem{A007408} +The OEIS Foundation Inc., \url{https://oeis.org/A007408}, Wolstenholme numbers: numerator of $\sum_{k=1}^{n}1/k^3$; comment by A.~Adamchuk (Nov.~7, 2006). + +\bibitem{A116184} +The OEIS Foundation Inc., \url{https://oeis.org/A116184}, entry by A.~Adamchuk (Apr.~8, 2007); revision \#6, Feb.~16, 2025. + +\end{thebibliography} +} +\end{document} diff --git a/results/oeis-a119936/README.md b/results/oeis-a119936/README.md new file mode 100644 index 0000000..8795a8a --- /dev/null +++ b/results/oeis-a119936/README.md @@ -0,0 +1,52 @@ +# The row-LCM of denominators of the cube of the mean matrix is n · lcm(1..n)² + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A119936 +**Date:** 2026-10-24 + +## Result + +Let A be the lower-triangular matrix with A(i,j) = 1/i for j ≤ i and 0 otherwise. Its cube has entries r(n,m) = (1/n) Σ_{m ≤ l ≤ k ≤ n} 1/(k l) for 1 ≤ m ≤ n. Let a(n) be the lcm, over m = 1..n, of the reduced denominators of r(n,m). Then for every n ≥ 1, a(n)/n³ = A002944(n)² = (lcm(1..n)/n)². Equivalently, a(n) = n · lcm(1,…,n)². This is the equation that OEIS A119936 (Wolfdieter Lang, 2006) labels a conjecture. + +## Assessment + +The divisibility a(n) | n·lcm(1..n)^2 is immediate, because each product kl divides lcm(1..n)^2. For the reverse divisibility, take each prime p separately and use the column m equal to the largest multiple of p^e that is at most n, where p^e ≤ n < p^{e+1}. In that column, k = l = m is the only term whose valuation reaches -2e, so the full p-power survives in the denominator. This is the textbook unique-minimal-valuation trick used for harmonic sums. The whole argument fits in under a page, and the scout record set it out almost in full before any formalization, so it is a short, standard proof and not a new idea. + +*Follows from:* The standard p-adic argument in which a sum has a single term of minimal valuation, the same idea as the classical proof that the harmonic numbers H_n are not integers (Taeisinger/Kürschák), applied to the explicit formula r(n,m) = (1/n) Σ_{m≤l≤k≤n} 1/(kl) and to v_p(lcm(1..n)) = floor(log_p n). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A119936](https://oeis.org/A119936) as [`Math0.Statements.A119936.statement`](../../lean/Math0/Statements/OEIS/A119936.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A119936.lean`](../../lean/Math0/Frontier/OEIS/A119936.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A119936 a(n)/n^3 = A027451(n) = A002944(n)^2 (the second equation is a conjecture). (Wolfdieter Lang, Jul 20 2006) + +Referees: I found no prior proof or counterexample. +- OEIS A119936 (Lang 2006, edit #22 Nov 2019) still calls a(n)/n^3 = A002944(n)^2 a conjecture. +- A027451 states (lcm(1..n)/n)^2 as a formula (Meijer, 2009) without proof. Detlefs' comment there begins "It appears". +- A120078 and A120079 say "conjectured to be A027451". +- Crowley, arXiv:1207.1126, says only that a denominator "appears to be" A119936. +- Fried's OEIS-conjecture series does not mention A119936 or the related sequences: arXiv:2410.07237 / JIS 25.4.3, JIS 26.1.8, arXiv:2606.09913, arXiv:2607.24832. +- Sloane, math/0409509: no mention. +- Web, MSE/MO and SeqFan searches turned up nothing. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a119936, + author = {{math0}}, + title = {{The row-LCM of denominators of the cube of the mean matrix is n · lcm(1..n)²}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a119936}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a119936/paper.pdf b/results/oeis-a119936/paper.pdf new file mode 100644 index 0000000..44eb3cd Binary files /dev/null and b/results/oeis-a119936/paper.pdf differ diff --git a/results/oeis-a119936/paper.tex b/results/oeis-a119936/paper.tex new file mode 100644 index 0000000..5c8ce73 --- /dev/null +++ b/results/oeis-a119936/paper.tex @@ -0,0 +1,364 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 {→}{{$\to$}}1 + {↔}{{$\leftrightarrow$}}1 {∧}{{$\wedge$}}1 {≥}{{$\ge$}}1 {≤}{{$\le$}}1 {…}{{$\dots$}}1 + {·}{{$\cdot$}}1 {×}{{$\times$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 + {²}{{$^2$}}1 {³}{{$^3$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem}[section] +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} +\newtheorem{example}[theorem]{Example} +\emergencystretch=3em + +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\code}[1]{\texttt{#1}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\DeclareMathOperator{\lcm}{lcm} +\DeclareMathOperator{\den}{den} +\DeclareMathOperator{\num}{num} + +\title[Row denominators of the cube of the mean matrix]{The least common denominator of row $n$ of the cube of the mean matrix is $n\cdot\lcm(1,\dots,n)^2$: a proof of Lang's conjecture in OEIS A119936} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} +\hypersetup{pdftitle={The least common denominator of row n of the cube of the mean matrix is n lcm(1,...,n)\textasciicircum 2: a proof of Lang's conjecture in OEIS A119936},pdfauthor={math0}} + +\begin{document} +\begin{abstract} +Let $A$ be the infinite lower-triangular mean matrix, $A(i,j)=1/i$ for $j\le i$ and $A(i,j)=0$ for $j>i$, and let $a(n)$ be the least common multiple of the reduced denominators of the entries of row $n$ of $A^3$. We prove that $a(n)=n\cdot\lcm(1,\dots,n)^2$ for every $n\ge1$, equivalently $a(n)/n^3=\mathrm{A002944}(n)^2$; this is the equation that Wolfdieter Lang labelled a conjecture in OEIS A119936 in 2006, and it also proves the formula $\mathrm{A027451}(n)=(\lcm(1,\dots,n)/n)^2$, which J.~W. Meijer added to OEIS A027451 in 2009 without proof. The proof is elementary: for each prime $p$ it exhibits a column of row $n$ whose denominator contains the full power of $p$ dividing $n\cdot\lcm(1,\dots,n)^2$. We found no earlier proof and classify the result as new, with the caveat that the argument is short and may be known informally. The theorem is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before the proof attempt; its definitions are checked by the kernel against the listed terms of A119936, A119935, A119932 and A002944. +\end{abstract} +\maketitle + +\section{Introduction} + +Let $A=(A(i,j))_{i,j\ge1}$ be the infinite lower-triangular matrix with +\[ + A(i,j)=\begin{cases}1/i,& j\le i,\\ 0,& j>i.\end{cases} +\] +Applied to a sequence $(x_j)$, it returns the sequence of arithmetic means $(x_1+\dots+x_i)/i$; it is the matrix of Ces\`aro means of order one, called the lower triangular mean matrix in OEIS A027447 \cite{A027447}. Its cube $A^3$ is again lower triangular, and for $1\le m\le n$ its entries are +\begin{equation}\label{eq:r} + r(n,m):=(A^3)(n,m)=\frac1n\sum_{m\le l\le k\le n}\frac1{kl} +\end{equation} +(Lemma~\ref{lem:explicit}). The OEIS contains several sequences built from this triangle: the numerators A119935 \cite{A119935} and denominators A119932 \cite{A119932} of $r(n,m)$ in lowest terms (Wolfdieter Lang, 2006); the integer triangle A027447 \cite{A027447} (Olivier G\'erard) of the numerators when each row of $A^3$ is written over its least common denominator; its first diagonal A027451 \cite{A027451}; and the sequence A119936 \cite{A119936} (Lang, July~20, 2006), +\[ + a(n)=\lcm_{1\le m\le n}\den r(n,m)\qquad(n\ge1), +\] +the least common denominator of row $n$, which begins $1, 8, 108, 576, 18000, 21600, 1234800,\dots$. In the FORMULA section of A119936 Lang wrote: +\begin{quote} +``a(n)/n\^{}3 = A027451(n) = A002944(n)\^{}2 (the second equation is a conjecture).'' (Wolfdieter Lang, Jul~20 2006) +\end{quote} +Here A002944 \cite{A002944} is $\lcm(1,2,\dots,n)/n$. Row $n$ of A027447 is $a(n)\,r(n,m)$, $1\le m\le n$, and $r(n,n)=1/n^3$, so $\mathrm{A027451}(n)=a(n)/n^3$ by definition: the first equation is not in doubt. The conjecture is the second equation, that is, +\[ + \frac{a(n)}{n^3}=\Bigl(\frac{\lcm(1,\dots,n)}{n}\Bigr)^2,\qquad\text{equivalently}\qquad a(n)=n\cdot\lcm(1,\dots,n)^2 . +\] +We prove it for every $n\ge1$ (Theorem~\ref{thm:main}). + +\subsection*{Related statements in the OEIS} +In A027451, Johannes W. Meijer added (July~21, 2009) the formula ``a(n) = (lcm(1..n)/n)\^{}2'' and the cross-reference ``Equals A002944(n)\^{}2'', with no proof or reference. Since $\mathrm{A027451}(n)=a(n)/n^3$, this formula is equivalent to Lang's conjecture, so Theorem~\ref{thm:main} proves it as well (Corollary~\ref{cor:A027451}). The same entry contains a comment of Gary Detlefs (2010), ``It appears that a(n) = denominator of n\^{}2*sum(1/k\^{}2,k=1..n)''; this is a different statement, which we do not address. A119936 also lists the formula $a(n)/n^3=(\mathrm{A099946}(n)\,(n-1))^2$ for $n\ge2$, marked ``from the conjecture''; since $\mathrm{A099946}(n)=\lcm(1,\dots,n)/(n(n-1))$, it is the same identity. Lang's entries A120078 and A120079 \cite{A120078}, on generating functions related to the hydrogen spectrum, say that a sequence beginning $1,1,4,9,144,\dots$ that arises there is ``conjectured to be A027451(n)''; those sequences have other definitions and are not addressed here. Crowley's paper \cite{Cr}, which A119936 links to, mentions a sequence of denominators that ``appears to be'' A119936, and gives no proof of the formula. + +\subsection*{Status} +The current revision of A119936 (\#22, November~5, 2019) still calls the second equation a conjecture. The math0 referees found no proof or counterexample in the OEIS entries related to A119936 (A027447, A027451, A119932, A119935, A002944, A099946, A120078, A120079 and others), in Stephan's collection of OEIS conjectures \cite{St}, in Fried's paper on proofs of OEIS conjectures \cite{Fr} and the later papers in his series, or by web searches. We therefore classify Theorem~\ref{thm:main} as a \emph{new result}. The proof is a short argument, one prime at a time, and it may well be known informally; we did not find it written down. + +\section{Statement}\label{sec:statement} + +For $n\ge1$ put $L_n=\lcm(1,2,\dots,n)$. For $q\in\Q$ write $q=\num(q)/\den(q)$ in lowest terms, with $\den(q)\ge1$ and $\gcd(|\num(q)|,\den(q))=1$. For a prime $p$ and a positive integer $j$, $v_p(j)$ is the exponent of $p$ in $j$. + +\begin{theorem}\label{thm:main} +For every integer $n\ge1$, +\[ + a(n)=\lcm_{1\le m\le n}\den r(n,m)=n\,L_n^2, + \qquad\text{equivalently}\qquad + \frac{a(n)}{n^3}=\Bigl(\frac{L_n}{n}\Bigr)^2=\mathrm{A002944}(n)^2 . +\] +\end{theorem} + +\begin{corollary}[not formalized separately]\label{cor:A027451} +For every $n\ge1$, $\mathrm{A027451}(n)=(L_n/n)^2=\mathrm{A002944}(n)^2$, and for $n\ge2$, $a(n)/n^3=(\mathrm{A099946}(n)\,(n-1))^2$. +\end{corollary} + +\begin{proof} +$\mathrm{A027451}(n)=a(n)\,r(n,n)=a(n)/n^3$ by the definitions of A027451 and A027447, and $\mathrm{A099946}(n)\,(n-1)=L_n/n$. +\end{proof} + +\subsection*{The Lean statement} +The statement was formalized by math0 in the file \path{lean/Math0/Statements/OEIS/A119936.lean}, reviewed for fidelity against the OEIS entries, and frozen (SHA-256 \texttt{dadd10f3\ldots cfcfaafc5}) before any proof attempt. The definitions used by the statement, and the statement itself, are verbatim: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +/-- The lower-triangular mean matrix (1-indexed): `A(i,j) = 1/i` if `j ≤ i`, `0` if `j > i`. -/ +def A (i j : ℕ) : ℚ := if j ≤ i then 1 / (i : ℚ) else 0 + +/-- The `N × N` leading truncation of `A`; the index `i : Fin N` stands for row/column `i + 1`. -/ +def Amat (N : ℕ) : Matrix (Fin N) (Fin N) ℚ := + Matrix.of fun i j => A ((i : ℕ) + 1) ((j : ℕ) + 1) + +/-- The triangle of rationals A119935/A119932: `r n m = (A^3)[n,m]` for `1 ≤ m ≤ n`, computed as +the `(n,m)` entry of the cube of the `n × n` truncation of `A` (`0` outside the triangle). -/ +def r (n m : ℕ) : ℚ := + if h : 1 ≤ m ∧ m ≤ n then (Amat n ^ 3) ⟨n - 1, by omega⟩ ⟨m - 1, by omega⟩ else 0 + +/-- A119936: the LCM of the (lowest-terms) denominators of row `n` of the triangle `r`, +`a(n) = lcm_{m=1..n} A119932(n,m)`. -/ +def a (n : ℕ) : ℕ := (Finset.Icc 1 n).lcm fun m => (r n m).den + +/-- `lcm(1, 2, …, n)` (A003418); `lcmUpTo 0 = 1`. -/ +def lcmUpTo (n : ℕ) : ℕ := (Finset.Icc 1 n).lcm id + +/-- A002944: `LCM(1, 2, …, n) / n` (exact division for `n ≥ 1`, see `A002944_mul`). -/ +def A002944 (n : ℕ) : ℕ := lcmUpTo n / n + +/-- The conjecture: for every `n ≥ 1`, `a(n)/n³ = A002944(n)²` (here `a(n)/n³` is A027451(n), +the diagonal entry `a(n)·r(n,n)` of A027447, so this is the conjectured +`A027451(n) = A002944(n)²`). -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → (a n : ℚ) / (n : ℚ) ^ 3 = ((A002944 n : ℕ) : ℚ) ^ 2 +\end{lstlisting} +All declarations are in the namespace \decl{Math0.Statements.A119936}. The same file proves +\begin{lstlisting} +theorem statement_iff : statement ↔ ∀ n : ℕ, 1 ≤ n → a n = n * lcmUpTo n ^ 2 +\end{lstlisting} +which is the equivalence of the two forms in Theorem~\ref{thm:main}. + +\subsection*{How the Lean definitions encode the entries} +\code{A i j} is $A(i,j)$ with indices starting at $1$. \code{Amat N} is the leading $N\times N$ block of $A$ as a Mathlib matrix indexed by \code{Fin N}, where the index $i$ stands for $i+1$. \code{r n m} is the entry in row $n$, column $m$ of \code{Amat n \^{} 3}, computed with Mathlib's matrix multiplication and power, and is $0$ outside $1\le m\le n$. Taking the $n\times n$ truncation is exact: $(A^3)(n,m)=\sum_{k,l}A(n,k)A(k,l)A(l,m)$, and $A(n,k)=0$ for $k>n$ and $A(k,l)=0$ for $l>k$, so only indices $\le n$ contribute. The statement file proves this in the form~\eqref{eq:r} (\decl{r_eq_sum}, \decl{r_eq_explicit}; Lemma~\ref{lem:explicit} below). \code{(r n m).den} is Mathlib's \decl{Rat.den}, the denominator in lowest terms, so \code{a n} is $a(n)$ as given by the name of A119936 and by its formula $a(n)=\lcm_{m=1..n}\mathrm{A119932}(n,m)$. \code{lcmUpTo n} is $L_n$, and \code{A002944 n} is $L_n/n$ computed with division in $\N$, which is exact for $n\ge1$ (\decl{A002944_mul}). Finally \code{statement} asserts $a(n)/n^3=\mathrm{A002944}(n)^2$ in $\Q$ for all $n\ge1$, the common offset of A119936, A027451 and A002944; as explained in the introduction, $a(n)/n^3$ is $\mathrm{A027451}(n)$, so this is exactly the conjectured equation. + +The statement file checks the definitions against the OEIS data by kernel evaluation (\texttt{decide +kernel}): \decl{a_data} reproduces all $19$ listed terms of A119936, from $a(1)=1$ to $a(19)=1029655143835718400$; \decl{triangle_num_data} and \decl{triangle_den_data} reproduce the $37$ listed terms of A119935 and the $32$ listed terms of A119932, read by rows; and \decl{A002944_data} reproduces the $31$ listed terms of A002944. During the fidelity review, an independent computation with exact rational arithmetic reproduced the $19$ terms of A119936. + +\section{Proof}\label{sec:proof} + +Throughout, $n\ge1$ is fixed, $L=L_n$ and $D=nL^2$. For a prime $p$ let $e_p=\lfloor\log_p n\rfloor$, the largest $e$ with $p^e\le n$ (Mathlib's \code{Nat.log p n}). + +\begin{lemma}[\decl{r_eq_sum}, \decl{r_eq_explicit}]\label{lem:explicit} +For $1\le m\le n$, +\[ + r(n,m)=\sum_{k=1}^n\sum_{l=1}^nA(n,k)A(k,l)A(l,m)=\frac1n\sum_{k=m}^n\sum_{l=m}^k\frac1{kl}. +\] +\end{lemma} + +\begin{proof} +The first equality is the definition of the matrix cube, after shifting the indices of \code{Fin n} by one. For $1\le k\le n$ we have $A(n,k)=1/n$, and $A(k,l)A(l,m)$ equals $1/(kl)$ if $m\le l\le k$ and $0$ otherwise. Terms with $kn$ we have $e=0$, $c=n$ and $m_p=n$; then $N(n)=L^2/n^2$ is prime to $p$, and the lemma holds trivially. + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +\emph{$a(n)\mid D$.} For $1\le m\le n$, Lemma~\ref{lem:N} gives $N(m)=D\,r(n,m)$ with $N(m),D\in\N$, so $\den r(n,m)\mid D$ by Lemma~\ref{lem:den}(ii). Hence the least common multiple $a(n)$ divides $D$. + +\emph{$D\mid a(n)$.} It suffices to show that every prime power $p^k$ dividing $D$ divides $a(n)$ (Mathlib's \decl{Nat.dvd_iff_prime_pow_dvd_dvd}). Let $m_p$ be the column of Lemma~\ref{lem:column}. Then $N(m_p)=D\,r(n,m_p)$ and $p\nmid N(m_p)$, so $p^k\mid\den r(n,m_p)$ by Lemma~\ref{lem:den}(iii), and $\den r(n,m_p)\mid a(n)$ because $1\le m_p\le n$. + +The two natural numbers divide each other, so $a(n)=D=nL^2$ (this is the private lemma \decl{a_eq}). Dividing by $n^3$ and using $\mathrm{A002944}(n)\cdot n=L$ (\decl{A002944_mul}) gives $a(n)/n^3=(L/n)^2=\mathrm{A002944}(n)^2$; in Lean this last step is the statement file's \decl{statement_iff}, and the theorem is proved as \lstinline|result := statement_iff.2 fun _ hn => a_eq hn|. +\end{proof} + +\begin{example} +For $n=4$: $L=12$, $D=576$, and row $4$ of $A^3$ is $\frac{415}{576},\frac{115}{576},\frac{37}{576},\frac1{64}$, so $a(4)=576$. For $p=3$: $e_3=1$, $m_3=3$, and $N(3)=\frac{144}{9}+\frac{144}{12}+\frac{144}{16}=16+12+9=37$, which is prime to $3$; so $3^2\mid\den r(4,3)=576$. For $p=2$: $e_2=2$, $m_2=4$, $N(4)=144/16=9$ is odd, and $2^6\mid\den r(4,4)=64$. +\end{example} + +\begin{remark} +The proof shows more: for each prime $p$, the $p$-part of $\den r(n,m_p)$ is exactly $p^{v_p(n)+2e_p}$, the $p$-part of $D$. The column $m_p$ depends on $p$, and a fixed column such as $m=1$ need not carry all primes: for $n=14$ an exact computation (not part of the formal proof) gives $\den r(14,1)=D/7$, while the column $m_7=14$ carries the factor $7^3$ of $D$. The same computation shows that for every $n\le80$ some single column has denominator exactly $D$ (for $n=14$, the column $m=8$); we neither prove nor need this. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in the file \path{lean/Math0/Frontier/OEIS/A119936.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file (Section~\ref{sec:statement}) and \path{lean/Math0/Audit.lean}. The main declaration is \code{theorem result : statement} in the namespace \decl{Math0.Frontier.A119936}. The lemmas of Section~\ref{sec:proof} correspond to Lean declarations as follows: Lemma~\ref{lem:explicit} is \decl{r_eq_sum} and \decl{r_eq_explicit} (statement file); Lemma~\ref{lem:val} is \decl{factorization_lcmUpTo} (a wrapper of Mathlib's \decl{Nat.factorization_lcmUpto}) and \decl{factorization_le_log}; Lemma~\ref{lem:N} is \decl{mul_dvd_sq}, the definition \decl{N} and \decl{N_cast}; Lemma~\ref{lem:den} is \decl{num_mul_eq}, \decl{den_dvd_of} and \decl{pow_dvd_den}; Lemma~\ref{lem:column} is \decl{exists_good}, with facts (b) and (c) as \decl{p_dvd_term} and \decl{not_p_dvd_term}; and the integer identity $a(n)=nL^2$ is \decl{a_eq}. Apart from \decl{r_eq_sum} and \decl{r_eq_explicit}, these are private declarations of the proof file. The denominator arguments use Mathlib's \decl{Rat.reduced} (coprimality of numerator and denominator) and \decl{Rat.mul_den_eq_num}. The proof involves no finite computation; the only kernel evaluations are the data checks of the statement file described in Section~\ref{sec:statement}. Neither file uses \decl{sorry}, \decl{native_decide}, \decl{set_option} or new axioms. + +\subsection*{Audit} +The proof file ends with the command +\begin{lstlisting} +#math0_settles Math0.Frontier.A119936.result Math0.Statements.A119936.statement +\end{lstlisting} +The command \decl{#math0_settles} (defined in \path{lean/Math0/Audit.lean}) is used for statements that math0 formalizes itself. It fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which excludes \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} introduced by \decl{native_decide}, and custom axioms; and (3) the type of \decl{result} is syntactically the constant \decl{statement} or its negation, up to metadata annotations, with no unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A119936.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A119936.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A119936.result' proves 'Math0.Statements.A119936.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}. The repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}; this result does not use it, since A119936 is not among its statements. To reproduce, run \path{scripts/verify.sh} from the repository root. It builds all math0 results with \texttt{lake build}, which re-runs every audit command, and it checks that the pinned dependencies have no local modifications. To check this file alone, build the statement module (\texttt{lake build Math0.Statements.OEIS.A119936}; the kernel check \decl{a_data} takes about $75$\,s of CPU time) and then run \texttt{lake env lean Math0/Frontier/OEIS/A119936.lean} in \path{lean/}, which takes about $20$\,s. + +{\small +\begin{thebibliography}{99} + +\bibitem{Cr} +S.~Crowley, \emph{Two new zeta constants: fractal string, continued fraction, and hypergeometric aspects of the Riemann zeta function}, arXiv:1207.1126, 2012. + +\bibitem{FC} +M.~Firsching et al., \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026; \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Fr} +S.~Fried, \emph{Proofs of some conjectures from the OEIS}, arXiv:2410.07237, 2024. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput.\ Sci.\ \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{St} +R.~Stephan, \emph{Prove or disprove. 100 conjectures from the OEIS}, arXiv:math/0409509, 2004. + +\bibitem{A002944} +The OEIS Foundation Inc., \url{https://oeis.org/A002944}, $a(n)=\mathrm{LCM}(1,2,\dots,n)/n$; entry by N.~J.~A. Sloane. + +\bibitem{A027447} +The OEIS Foundation Inc., \url{https://oeis.org/A027447}, triangle read by rows: cube of the lower triangular mean matrix; entry by O.~G\'erard. + +\bibitem{A027451} +The OEIS Foundation Inc., \url{https://oeis.org/A027451}, first diagonal of A027447; entry by O.~G\'erard, formula by J.~W. Meijer (Jul.~21, 2009). + +\bibitem{A119932} +The OEIS Foundation Inc., \url{https://oeis.org/A119932}, triangle of denominators of the cube of a certain lower triangular matrix; entry by W.~Lang (Jul.~20, 2006). + +\bibitem{A119935} +The OEIS Foundation Inc., \url{https://oeis.org/A119935}, triangle of numerators of the cube of a certain lower triangular matrix; entry by W.~Lang (Jul.~20, 2006). + +\bibitem{A119936} +The OEIS Foundation Inc., \url{https://oeis.org/A119936}, least common multiple of denominators of the rows of the triangle of rationals A119935/A119932; entry by W.~Lang (Jul.~20, 2006); revision \#22, Nov.~5, 2019. + +\bibitem{A120078} +The OEIS Foundation Inc., \url{https://oeis.org/A120078} and \url{https://oeis.org/A120079}; entries by W.~Lang (Jul.~20, 2006). + +\end{thebibliography} +} +\end{document} diff --git a/results/oeis-a120069/README.md b/results/oeis-a120069/README.md new file mode 100644 index 0000000..9973b15 --- /dev/null +++ b/results/oeis-a120069/README.md @@ -0,0 +1,54 @@ +# Denominators of Sum C(k)/4^(k-1): Groux's and Staunton's conjectures (A120069) + +**Classification:** First formal proof of a known result +**Area:** Sequences and series +**Source problem:** OEIS A120069 +**Date:** 2026-10-20 + +## Result + +Let C(k) be the Catalan numbers, r(n) = Sum_{k=1..n} C(k)/4^(k-1), and a(n) the denominator of r(n) in lowest terms (A120069). Let A283208(n) be the least e >= 0 such that 2^e (2n+1)/(n+1) c(2n) is a nonnegative integer, where c(2n) = Pochhammer(1/2,n)/n!. Then for every n >= 1: (Groux) a(n) = denominator(C(n)/4^(n-1)), and (Staunton) a(n) = 2^(A283208(n) - 2), with the exponent taken in the integers. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A120069](https://oeis.org/A120069) as [`Math0.Statements.A120069.statement`](../../lean/Math0/Statements/OEIS/A120069.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A120069.lean`](../../lean/Math0/Frontier/OEIS/A120069.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: A120069 (Denominators of partial sums r(n) = Sum_{k=1..n} C(k)/2^(2(k-1)), C = Catalan): "Conjecture: a(n) = denominator(Catalan(n)/4^(n-1)). - _Groux Roland_, Dec 11 2010" and "Conjecture: a(n) = 2^(A283208(n)-2). - _Alexander Staunton_, Feb 28 2026" + +Referees: OEIS sources (read from the local mirror; A120069 also checked against GitHub oeisdata main): +- A120778, formula by Groux Roland, Jan 04 2011: sum_{k=0..n} C(k)/4^k = 2(1 - binomial(2n+2,n+1)/4^(n+1)). +- A119951, comment by Pieter Mostert, Oct 12 2012: r(n) = sum_{k=1..n} C(k)/4^(k-1) = 4 - binomial(2n+2,n+1)/2^(2n-1). +- A120777, which records: + - Johannes W. Meijer, Jul 06 2009: a(n) = denominator(C(2n+2,n+1)/2^(2n+1)). + - Peter Luschny's new name, Apr 2024: a(n) = 2^(2n - v2(Catalan(n))). + - Amiram Eldar, Apr 18 2024: a(n) = 2^(2n - A048881(n)) = 2^A283208(n). + - A comment that its terms coincide with the denominators of sum_{k=0..n} C(k)/4^k. +- A283208: + - Comment: 2^a(n) is the denominator of 2^(-2n)·A001700(n). + - Formula by Zabolotskii, 2021: a(n) = A005187(n+1) - 1. + +Combining these gives A120069(n) = A120777(n)/4 = 2^(A283208(n)-2) = den(C(n)/4^(n-1)). No explicit paper, MSE/MO post or SeqFan message resolving the A120069 conjectures by name was found. A120069 #30 (Mar 10 2026) still lists both as conjectures. + +Web pages: +- https://oeis.org/A120778 +- https://oeis.org/A120777 +- https://oeis.org/A119951 +- arXiv:0906.4290, "Asymptotics of partial sums of central binomial coefficients and Catalan numbers". Found in search; related, but I did not read it. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a120069, + author = {{math0}}, + title = {{Denominators of Sum C(k)/4^(k-1): Groux's and Staunton's conjectures (A120069)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a120069}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a120069/paper.pdf b/results/oeis-a120069/paper.pdf new file mode 100644 index 0000000..a3d9bb7 Binary files /dev/null and b/results/oeis-a120069/paper.pdf differ diff --git a/results/oeis-a120069/paper.tex b/results/oeis-a120069/paper.tex new file mode 100644 index 0000000..3bd7fcc --- /dev/null +++ b/results/oeis-a120069/paper.tex @@ -0,0 +1,372 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,private,set,rw,rwa,only}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {ℝ}{{$\mathbb{R}$}}1 + {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {∧}{{$\wedge$}}1 + {∨}{{$\vee$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {²}{{$^2$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 + {∑}{{$\sum$}}1 {∏}{{$\prod$}}1 {∈}{{$\in$}}1 {⋯}{{$\cdots$}}1 + {π}{{$\pi$}}1 {·}{{$\cdot$}}1 {…}{{$\dots$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{⋯}{\ensuremath{\cdots}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\code}[1]{\texttt{#1}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\DeclareMathOperator{\den}{den} +\newcommand{\E}{\mathrm{E}} + +\title[Denominators of partial sums of $C_k/4^{k-1}$]{The denominators of $\sum_{k=1}^{n} C_k/4^{k-1}$: a formally verified proof of the conjectures of Groux and Staunton for OEIS A120069} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + +\begin{document} +\begin{abstract} +Let $C_k$ be the Catalan numbers and let $a(n)$ be the denominator, in lowest terms, of $r(n)=\sum_{k=1}^{n}C_k/4^{k-1}$ (OEIS A120069). We prove, for every $n\ge1$, the two formulas recorded as conjectures in the entry: $a(n)=\den\bigl(C_n/4^{n-1}\bigr)$ (Groux, 2010) and $a(n)=2^{\E(n)-2}$, where $\E(n)$ is the minimal-exponent sequence A283208 associated with Vietoris' numbers (Staunton, 2026). The proof is elementary: it combines the closed form $r(n)=4-(2n+1)C_n/4^{n-1}$ with the bound $C_n\le4^{n-1}$, and shows that both sides equal $2^{2n-2-v}$, where $2^v$ is the exact power of $2$ dividing $C_n$. Both formulas also follow quickly from identities already recorded in other OEIS entries (A119951, A120777, A120778, A283208), so we classify the result as a known result receiving its first formal proof, not a new theorem. The proof is verified in Lean~4 with Mathlib against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before the proof attempt; its definitions are checked by the kernel against all listed terms of A120069 and A283208. +\end{abstract} +\maketitle + +\section{Introduction} + +The sequence A120069 of the OEIS \cite{A120069}, contributed by Wolfdieter Lang on July~20, 2006, lists the denominators of the partial sums +\[ + r(n)=\sum_{k=1}^{n}\frac{C_k}{2^{2(k-1)}},\qquad C_k=\frac{1}{k+1}\binom{2k}{k}\ \text{(A000108)}, +\] +written in lowest terms; the numerators form A119951 \cite{A119951}. The series converges to $4$, and the sequence, with offset $1$, begins +\[ + 1,\ 2,\ 16,\ 32,\ 128,\ 256,\ 4096,\ 8192,\ 32768,\ 65536,\ \dots; +\] +for instance $r(3)=1+\tfrac{2}{4}+\tfrac{5}{16}=\tfrac{29}{16}$. The FORMULA section of the entry contains two conjectures: +\begin{quote} +``Conjecture: a(n) = denominator(Catalan(n)/4\textasciicircum{}(n-1)). -{}~Groux Roland, Dec 11 2010''\\ +``Conjecture: a(n) = 2\textasciicircum{}(A283208(n)-2). -{}~Alexander Staunton, Feb 28 2026'' +\end{quote} +Here A283208 \cite{A283208}, due to I.~Cação, M.~I.~Falcão and H.~Malonek (2017), is defined from Vietoris' numbers $c(2n)=c(2n-1)=(1/2)_n/n!$ \cite{Vie,CFM}: its $n$-th term is the least $e\ge0$ such that $2^{e}\,\frac{2n+1}{n+1}\,c(2n)$ is a nonnegative integer. The current revision of A120069 (\#30, March~10, 2026) still labels both statements as conjectures. We prove both, for every $n\ge1$ (Theorem~\ref{thm:main}). + +\subsection*{Prior work and status} +Neither conjecture is resolved by name in the literature that the math0 referees found (OEIS, arXiv, Mathematics Stack Exchange and MathOverflow, the SeqFan list, general web searches). However, both follow in a few lines from formulas already recorded in related OEIS entries: +\begin{itemize} +\item In A120778 \cite{A120778}, Groux himself recorded on January~4, 2011 the closed form $\sum_{k=0}^{n}C_k/4^k=2\bigl(1-\binom{2n+2}{n+1}/4^{n+1}\bigr)$. +\item In A119951 \cite{A119951}, Pieter Mostert recorded on October~12, 2012 the equivalent closed form $r(n)=4-\binom{2n+2}{n+1}/2^{2n-1}$ for the partial sums of A120069. +\item The entry A120777 \cite{A120777}, named $a(n)=2^{2n-\nu_2(C_n)}$ since April~16, 2024 (P.~Luschny), records that its terms coincide with the denominators of $\sum_{k=0}^{n}C_k/4^k$, the formula $a(n)=\den\bigl(\binom{2n+2}{n+1}/2^{2n+1}\bigr)$ (J.~W.~Meijer, July~6, 2009), and the formula $a(n)=2^{2n-\mathrm{A048881}(n)}=2^{\mathrm{A283208}(n)}$ (A.~Eldar, April~18, 2024). +\item A283208 \cite{A283208} itself records that $2^{\mathrm{A283208}(n)}$ is the denominator of $\binom{2n+1}{n+1}/4^{n}$, and the formula $\mathrm{A283208}(n)=\mathrm{A005187}(n+1)-1$ (A.~Zabolotskii, 2021). +\end{itemize} +Since $r(n)=4\sum_{k=0}^{n}C_k/4^k-4$, these give $a(n)=\mathrm{A120777}(n)/4=2^{2n-2-\nu_2(C_n)}=2^{\mathrm{A283208}(n)-2}$ for $n\ge1$, which contains both conjectures. The conjecture labels in A120069 are therefore stale, and we do not claim a new theorem: the contribution is a self-contained proof that settles both statements explicitly, and its formal verification in Lean~4, which to our knowledge is the first. The formal-conjectures repository \cite{FC} does not contain these statements; the Lean statement used here was written by math0. + +\subsection*{Method} +The proof follows the Lean proof. The closed form $r(n)=4-(2n+1)C_n/4^{n-1}$ (Lemma~\ref{lem:closed}) reduces both conjectures to the $2$-adic structure of $C_n/4^{n-1}$. Writing $C_n=2^vu$ with $u$ odd, the elementary bound $C_n\le 4^{n-1}$ (Lemma~\ref{lem:bound}) gives $v\le 2n-2$, and this is all that is needed: both sides of each conjecture equal $2^{2n-2-v}$, whatever the value of $v$. In particular Kummer's or Legendre's formula for $\nu_2(C_n)$ is not used (see Remark~\ref{rem:legendre}). + +\section{Statement}\label{sec:statement} + +Throughout, $C_k=\binom{2k}{k}/(k+1)$, and every rational number is written in lowest terms with positive denominator; $\den q$ denotes that denominator. For $n\ge0$ put +\[ + r(n)=\sum_{k=1}^{n}\frac{C_k}{2^{2(k-1)}}\in\Q,\qquad a(n)=\den r(n). +\] +For $n\ge1$, $a(n)$ is the $n$-th term of A120069. Let $(x)_n=x(x+1)\cdots(x+n-1)$ be the rising factorial, and put +\[ + c(2n)=\frac{(1/2)_n}{n!},\qquad w(n)=\frac{2n+1}{n+1}\,c(2n)\in\Q . +\] +Say that $e\in\N$ is \emph{admissible} for $n$ if $2^{e}w(n)\in\N$, and let $\E(n)$ be the least admissible $e$; it exists because $e=2n$ is admissible (Lemma~\ref{lem:vietoris}). Then $\E(n)$ is the $n$-th term of A283208 (offset $0$). + +\begin{theorem}\label{thm:main} +For every integer $n\ge1$, +\[ + \text{(Groux)}\quad a(n)=\den\Bigl(\frac{C_n}{4^{\,n-1}}\Bigr) + \qquad\text{and}\qquad + \text{(Staunton)}\quad a(n)=2^{\E(n)-2}, +\] +where in Staunton's formula the exponent $\E(n)-2$ is taken in $\Z$ and the power is computed in $\Q$. +\end{theorem} + +Theorem~\ref{thm:main} is exactly the formal statement displayed below. Its proof (Section~\ref{sec:proof}) establishes a little more along the way: if $C_n=2^{v}u$ with $u$ odd, then $v\le 2n-2$, $a(n)=\den(C_n/4^{n-1})=2^{2n-2-v}$ and $\E(n)=2n-v$; in particular $\E(n)-2\ge0$ for $n\ge1$. These intermediate facts are proved inside the Lean proof but are not part of the formal statement. For example, $C_3=5$ gives $v=0$, $a(3)=2^4=16$ and $\E(3)=6$; $C_2=2$ gives $v=1$, $a(2)=2$ and $\E(2)=3$. + +\subsection*{The Lean statement} +The statement was formalized by math0 in the file \path{lean/Math0/Statements/OEIS/A120069.lean}, reviewed for fidelity against the OEIS entries, and frozen (SHA-256 \texttt{9c2a2c60\ldots26485}) before any proof attempt. The definitions entering the statement, and the statement itself, read verbatim as follows (the auxiliary lemmas \decl{exists_natCast_iff} and \decl{isNatExp_two_mul} that they use, and the other lemmas and data checks of the file, are omitted): +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +/-- The partial sum `r(n) = ∑_{k=1}^{n} C(k)/2^(2(k-1))`, `C(k)` the Catalan numbers (A000108), +computed exactly in `ℚ`. -/ +def r (n : ℕ) : ℚ := ∑ k ∈ Finset.Icc 1 n, (catalan k : ℚ) / 2 ^ (2 * (k - 1)) + +/-- A120069 (offset `1`): `a(n)` is the denominator of `r(n) = ∑_{k=1}^{n} C(k)/2^(2(k-1))` +(in lowest terms). -/ +def a (n : ℕ) : ℕ := (r n).den + +/-- The rising factorial (Pochhammer symbol) `(x)_n = x (x+1) ⋯ (x+n-1)`. -/ +def pochhammer (x : ℚ) (n : ℕ) : ℚ := ∏ i ∈ Finset.range n, (x + i) + +/-- Vietoris' number `c(2n) = c(2n-1) = Pochhammer(1/2, n)/n!`. -/ +def vietoris (n : ℕ) : ℚ := pochhammer (1 / 2) n / (n.factorial : ℚ) + +/-- `(2n+1)/(n+1) · c(2n)`. -/ +def w (n : ℕ) : ℚ := (2 * n + 1) / (n + 1) * vietoris n + +/-- `2^e · (2n+1)/(n+1) · c(2n)` is a nonnegative integer. -/ +def IsNatExp (n e : ℕ) : Prop := ∃ m : ℕ, (2 : ℚ) ^ e * w n = m + +instance (n : ℕ) : DecidablePred (IsNatExp n) := fun e => + decidable_of_iff _ (exists_natCast_iff ((2 : ℚ) ^ e * w n)).symm + +/-- A283208 (offset `0`): the least nonnegative integer `e` such that `2^e (2n+1)/(n+1) c(2n)` +is a nonnegative integer, `c(2n) = Pochhammer(1/2, n)/n!`. -/ +def A283208 (n : ℕ) : ℕ := Nat.find ⟨2 * n, isNatExp_two_mul n⟩ + +/-- Conjectures (Groux 2010, Staunton 2026, A120069): for every `n ≥ 1`, +`a(n) = denominator(Catalan(n)/4^(n-1))` and `a(n) = 2^(A283208(n) - 2)`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + a n = ((catalan n : ℚ) / 4 ^ (n - 1)).den ∧ + (a n : ℚ) = (2 : ℚ) ^ ((A283208 n : ℤ) - 2) +\end{lstlisting} +All declarations are in the namespace \decl{Math0.Statements.A120069}. + +\subsection*{How the Lean definitions encode the entries} +\code{catalan} is Mathlib's Catalan sequence. \code{r n} is $r(n)$, computed in $\Q$; since $k\ge1$ in the sum, the natural subtraction $k-1$ is exact. Mathlib's rationals are normalized (coprime numerator and denominator, positive denominator), so \code{a n = (r n).den} is ``the denominator of $r(n)$ in lowest terms''; the value \code{a 0} $=1$ is not a term of the sequence and is not used. \code{pochhammer x n} is $(x)_n$, and the file proves it equal to Mathlib's \decl{ascPochhammer} (\decl{pochhammer_eq_ascPochhammer}). \code{vietoris n} is $c(2n)$ and \code{w n} is $w(n)$, with division in $\Q$. \code{IsNatExp n e} says literally that $2^e w(n)$ equals a natural number; it is decided through the equivalence $(\exists m\in\N,\ q=m)\iff \den q=1\wedge q\ge0$ (\decl{exists_natCast_iff}). \code{A283208 n} is the least such $e$ (\decl{Nat.find}), the witness $e=2n$ being \decl{isNatExp_two_mul}. This follows the definition of A283208 in its COMMENTS section, not one of its formulas. Finally, \code{statement} is the conjunction of the two conjectures for all $n\ge1$; in Groux's formula $n-1$ is exact because $n\ge1$, and Staunton's formula is stated in $\Q$ with the integer exponent $(\E(n):\Z)-2$ (\code{zpow}), so no truncated subtraction occurs. + +The file checks the definitions against the data of the entries, by kernel evaluation (\texttt{decide +kernel}, no \texttt{native\_decide}): +\begin{itemize} +\item \decl{a_data}: $a(1),\dots,a(27)$ are the $27$ terms listed in A120069, from $1$ to $1125899906842624$. For the evaluation, \code{catalan} is replaced by \code{catFast}, defined by $\mathrm{catFast}(0)=1$ and $\mathrm{catFast}(k+1)=\lfloor \mathrm{catFast}(k)\cdot2(2k+1)/(k+2)\rfloor$, which is proved equal to \code{catalan} (\decl{catFast_eq}) using the recursion of Lemma~\ref{lem:rec} below, where the division is exact. +\item \decl{A283208_data}: $\E(0),\dots,\E(62)$ are the $63$ terms listed in A283208, from $0$ to $119$. Each value $v$ is certified by the Boolean check that $v$ is admissible and that $v=0$ or $v-1$ is not admissible; since admissibility is upward closed (Lemma~\ref{lem:admissible}), this certifies that $v$ is the least admissible exponent (\decl{A283208_eq_of_check}). +\end{itemize} + +\section{Proof}\label{sec:proof} + +We follow the Lean proof. Lemmas~\ref{lem:rec} and~\ref{lem:admissible}, and Lemma~\ref{lem:vietoris} except for the formula for $w(n)$, are proved in the statement file; the remaining statements are private lemmas of the proof file. We use two facts from Mathlib: $(n+1)C_n=\binom{2n}{n}$ (\decl{succ_mul_catalan_eq_centralBinom}) and $(n+1)\binom{2n+2}{n+1}=2(2n+1)\binom{2n}{n}$ (\decl{Nat.succ_mul_centralBinom_succ}). In particular $C_n>0$ for all $n$, since $\binom{2n}{n}>0$ (the private lemma \decl{catalan_ne_zero'}, from Mathlib's \decl{Nat.centralBinom_pos}). + +\begin{lemma}[\decl{succ_succ_mul_catalan}]\label{lem:rec} +For all $k\ge0$, $(k+2)\,C_{k+1}=2(2k+1)\,C_k$. +\end{lemma} + +\begin{proof} +Multiplying by $k+1$ and using the two facts above, +$(k+1)(k+2)C_{k+1}=(k+1)\binom{2k+2}{k+1}=2(2k+1)\binom{2k}{k}=(k+1)\cdot2(2k+1)C_k$; cancel $k+1$. +\end{proof} + +\begin{lemma}[\decl{four_pow_mul_vietoris}, \decl{w_eq}, \decl{isNatExp_two_mul}]\label{lem:vietoris} +For all $n\ge0$, $4^n c(2n)=\binom{2n}{n}$ and $w(n)=(2n+1)\,C_n/4^n$. In particular $4^n w(n)=(2n+1)C_n\in\N$, so $e=2n$ is admissible for $n$. +\end{lemma} + +\begin{proof} +Induction on $n$; for $n=0$ both sides equal $1$. Since $(1/2)_{n+1}=(1/2)_n\,(n+\tfrac12)$, +\[ + 4^{n+1}c(2n+2)=4\cdot4^n c(2n)\cdot\frac{n+\frac12}{n+1}=\frac{2(2n+1)}{n+1}\binom{2n}{n}=\binom{2n+2}{n+1}. +\] +Then $w(n)=\frac{2n+1}{n+1}\binom{2n}{n}4^{-n}=(2n+1)C_n/4^n$. (In the statement file the witness for $e=2n$ is written $(2n+1)\cdot\bigl(\binom{2n}{n}/(n+1)\bigr)$, using $(n+1)\mid\binom{2n}{n}$.) +\end{proof} + +\begin{lemma}[\decl{isNatExp_mono}, \decl{A283208_eq_of}]\label{lem:admissible} +If $e$ is admissible for $n$, so is every $f\ge e$. Consequently, if $v$ is admissible for $n$ and either $v=0$ or $v-1$ is not admissible, then $\E(n)=v$. +\end{lemma} + +\begin{proof} +If $2^{e}w(n)=m\in\N$ then $2^{e+1}w(n)=2m\in\N$; induct. For the second claim, $\E(n)\le v$ by minimality. If $\E(n)0$, so $u/2^k$ is already in lowest terms (Mathlib's \decl{Rat.den_div_eq_of_coprime}). +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main} (\code{result})] +Let $n\ge1$ and write $n=m+1$. Since $C_{m+1}\ne0$, write $C_{m+1}=2^{v}u$ with $u$ odd (Mathlib's \decl{Nat.exists_eq_two_pow_mul_odd}). + +\emph{The exponent.} By Lemma~\ref{lem:bound}, $2^{v}\le 2^vu=C_{m+1}\le 4^m=2^{2m}$, so $v\le 2m$. Hence $4^m=2^{2m-v}\,2^{v}$ and +\begin{equation}\label{eq:key} + \frac{C_{m+1}}{4^{m}}=\frac{u}{2^{\,2m-v}} . +\end{equation} + +\emph{The denominator $a(n)$.} The number $N=(2m+3)u$ is odd. By Lemma~\ref{lem:closed} and \eqref{eq:key}, +\[ + r(m+1)=4-\frac{N}{2^{\,2m-v}} . +\] +Subtracting a rational number from an integer does not change its denominator (Mathlib's \decl{Rat.ofNat_sub_den}), so by Lemma~\ref{lem:den}, $a(m+1)=\den\bigl(N/2^{2m-v}\bigr)=2^{2m-v}$. + +\emph{Groux's formula.} By \eqref{eq:key} and Lemma~\ref{lem:den}, $\den\bigl(C_n/4^{n-1}\bigr)=\den\bigl(u/2^{2m-v}\bigr)=2^{2m-v}=a(n)$. + +\emph{The value of $\E(n)$.} By Lemma~\ref{lem:vietoris} and $4^{m+1}=2^{2m-v+2}\,2^{v}$, +\[ + w(m+1)=\frac{(2m+3)\,C_{m+1}}{4^{m+1}}=\frac{N}{2^{\,2m-v+2}} . +\] +The exponent $e=2m+2-v=(2m-v)+2$ is admissible, because $2^{e}w(m+1)=N\in\N$. The exponent $e-1=(2m-v)+1$ is not: if $2^{e-1}w(m+1)=N/2$ were equal to some $k\in\N$, then $N=2k$ would be even. By Lemma~\ref{lem:admissible}, $\E(m+1)=2m+2-v$. + +\emph{Staunton's formula.} In $\Z$, $\E(n)-2=2m-v\ge0$, so $2^{\E(n)-2}=2^{2m-v}=a(n)$ in $\Q$. + +With $m=n-1$, the exponents are $2m-v=2n-2-v$ and $\E(n)=2n-v$, as stated after Theorem~\ref{thm:main}. +\end{proof} + +\begin{remark}[not formalized]\label{rem:legendre} +The proof never determines $v=\nu_2(C_n)$: both conjectures only need $v\le 2n-2$. If one adds Legendre's formula, then $\nu_2\binom{2n}{n}=s_2(n)$ and $s_2(n+1)=s_2(n)+1-\nu_2(n+1)$, where $s_2$ is the binary digit sum, give $\nu_2(C_n)=s_2(n+1)-1$. The identities $a(n)=2^{2n-2-v}$ and $\E(n)=2n-v$ established in the proof of Theorem~\ref{thm:main} then yield $a(n)=2^{2n-1-s_2(n+1)}$ and $\E(n)=2n+1-s_2(n+1)$; the latter agrees with Zabolotskii's formula $\E(n)=\mathrm{A005187}(n+1)-1$ recorded in A283208, since $\mathrm{A005187}(m)=2m-s_2(m)$. Independently of Legendre's formula, the identity $a(n)=2^{2n-2-v}$, together with Luschny's name $\mathrm{A120777}(n)=2^{2n-v}$, gives $a(n)=\mathrm{A120777}(n)/4$ for $n\ge1$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in the file \path{lean/Math0/Frontier/OEIS/A120069.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file of Section~\ref{sec:statement} and the audit commands. The main declaration is \code{theorem result : statement} in the namespace \decl{Math0.Frontier.A120069}; its proof follows Section~\ref{sec:proof} step by step. The private lemmas are \decl{r_succ_closed} (Lemma~\ref{lem:closed}), \decl{catalan_succ_le} (Lemma~\ref{lem:bound}), \decl{catalan_ne_zero'}, \decl{den_odd_div_two_pow} (Lemma~\ref{lem:den}) and \decl{w_eq} (the formula for $w(n)$ in Lemma~\ref{lem:vietoris}); the other declarations named in Lemmas~\ref{lem:rec}--\ref{lem:admissible} are in the statement file. The main Mathlib lemmas used are \decl{succ_mul_catalan_eq_centralBinom}, \decl{Nat.succ_mul_centralBinom_succ}, \decl{Nat.exists_eq_two_pow_mul_odd}, \decl{Rat.den_div_eq_of_coprime} and \decl{Rat.ofNat_sub_den}. The proof file contains no computation by kernel evaluation; the only kernel evaluations are the data checks \decl{a_data} and \decl{A283208_data} of the statement file, which are not used by the proof. Neither file uses \texttt{sorry}, \texttt{native\_decide}, custom axioms or \texttt{set\_option}. The file ends with the command +\begin{lstlisting} +#math0_settles Math0.Frontier.A120069.result Math0.Statements.A120069.statement +\end{lstlisting} + +\subsection*{Audit} +The command \texttt{\#math0\_settles} (in \path{lean/Math0/Audit.lean}) is the audit for statements formalized by math0 itself. It fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (so no \decl{sorryAx}, no axioms introduced by \texttt{native\_decide}, and no custom axioms); and (3) the type of \decl{result} is syntactically the constant \decl{statement} or its negation, up to metadata, with no unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A120069.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A120069.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A120069.result' proves 'Math0.Statements.A120069.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. To reproduce, run \path{scripts/verify.sh} from the repository root; it builds all math0 results with \texttt{lake build}, which re-runs every audit command, and checks that the pinned dependencies are unmodified. The single file is checked by \texttt{lake env lean Math0/Frontier/OEIS/A120069.lean} in \path{lean/}. + +{\small +\begin{thebibliography}{99} + +\bibitem{CFM} +I.~Cação, M.~I.~Falcão and H.~R.~Malonek, \emph{Hypercomplex polynomials, Vietoris' rational numbers and a related integer numbers sequence}, Complex Anal.\ Oper.\ Theory \textbf{11} (2017), no.~5, 1059--1076, \url{https://doi.org/10.1007/s11785-017-0649-5}. + +\bibitem{FC} +M.~Firsching et al., \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026; \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput.\ Sci.\ \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Vie} +L.~Vietoris, \emph{Über das Vorzeichen gewisser trigonometrischer Summen}, Sitzungsber.\ Österr.\ Akad.\ Wiss.\ \textbf{167} (1958), 125--135. + +\bibitem{A120069} +The OEIS Foundation Inc., \url{https://oeis.org/A120069}, entry by W.~Lang (July~20, 2006); conjectures by R.~Groux (Dec.~11, 2010) and A.~Staunton (Feb.~28, 2026); revision \#30, Mar.~10, 2026. + +\bibitem{A119951} +The OEIS Foundation Inc., \url{https://oeis.org/A119951}, entry by W.~Lang (July~20, 2006); comment by P.~Mostert (Oct.~12, 2012). + +\bibitem{A120777} +The OEIS Foundation Inc., \url{https://oeis.org/A120777}, entry by W.~Lang (July~20, 2006); formulas by J.~W.~Meijer (July~6, 2009) and A.~Eldar (Apr.~18, 2024); name by P.~Luschny (Apr.~16, 2024). + +\bibitem{A120778} +The OEIS Foundation Inc., \url{https://oeis.org/A120778}, entry by W.~Lang (July~20, 2006); formula by R.~Groux (Jan.~4, 2011). + +\bibitem{A283208} +The OEIS Foundation Inc., \url{https://oeis.org/A283208}, entry by I.~Cação, M.~I.~Falcão and H.~Malonek (Mar.~8, 2017); formula by A.~Zabolotskii (Mar.~26, 2021). + +\end{thebibliography} +} +\end{document} diff --git a/results/oeis-a121750/README.md b/results/oeis-a121750/README.md new file mode 100644 index 0000000..8d60b75 --- /dev/null +++ b/results/oeis-a121750/README.md @@ -0,0 +1,56 @@ +# Mathar's order-6 recurrence for A121750 (even-length columns in deco polyominoes) holds for all n >= 7 + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A121750 +**Date:** 2026-10-24 + +## Result + +Let a(n) be the total number of columns of even length over all deco polyominoes of height n (OEIS A121750). The polyominoes are encoded as column lists, as in the statement file. Then for every n >= 7: +a(n) - (n+2)a(n-1) + (-n^2+4n-2)a(n-2) + (n^3-3n^2-4n+11)a(n-3) - (n-1)(n^2-11n+26)a(n-4) + (-n^3+5n^2+7n-43)a(n-5) + (n-3)(n-5)^2 a(n-6) = 0. + +## Assessment + +The proof splits each deco polyomino at its first column, the standard recursive decomposition, and uses the fact that shifting columns does not change the count. This gives a small first-order system for the counts and even-column totals. The order-6 recurrence then follows by unrolling the system six steps in each parity class and expanding a polynomial identity, which is a mechanical computation. The manuscript itself says the recurrence follows by routine closure arguments from Deutsch's first-order recurrence in the same entry. The new part is deriving that first-order relation from the definition, which takes about a page of standard combinatorics and needs no new idea. + +*Follows from:* Deutsch's first-order recurrence in the same entry, a(n) = n*a(n-1) + d(n-1) + (n-1)!*floor((n-1)/2), together with the closure properties of D-finite sequences (Stanley 1980). The row-polynomial recurrence for Q[n] in the cross-referenced A121748 gives the same route. Both are stated in OEIS without proof. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A121750](https://oeis.org/A121750) as [`Math0.Statements.A121750.statement`](../../lean/Math0/Statements/OEIS/A121750.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A121750.lean`](../../lean/Math0/Frontier/OEIS/A121750.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F Conjecture D-finite with recurrence a(n) +(-n-2)*a(n-1) +(-n^2+4*n-2)*a(n-2) +(n^3-3*n^2-4*n+11)*a(n-3) -(n-1)*(n^2-11*n+26)*a(n-4) +(-n^3+5*n^2+7*n-43)*a(n-5) +(n-3)*(n-5)^2*a(n-6)=0. - R. J. Mathar, Jul 26 2022 + +Referees: I found no published proof of this recurrence. Sources checked: +- OEIS A121750, local mirror and upstream raw oeisdata (revision #13, 2024-08-20, still says 'Conjecture'). Cross-references A121748, A121747, A121749, A121751 also contain no proof. +- E. Barcucci, S. Brunetti, F. Del Ristoro, 'Succession rules and deco polyominoes', RAIRO ITA 34 (2000) 1-14. Full text read; it does not treat even-length columns. +- E. Barcucci, A. Del Lungo, R. Pinzani, TCS 159 (1996) 29-42. +- E. Deutsch, E. Pergola, R. Pinzani, 'Six bijections between deco polyominoes and permutations', arXiv:0810.2876. It gives the definition of directed height and has no even-column results. +- S. B. Ekhad, X. Yang, D. Zeilberger, arXiv:1707.04654. It predates the 2022 conjecture. +- S. Fried, arXiv:2410.07237; JIS 28 (2025) Art. 25.4.3; JIS vol. 29 fried21; arXiv:2607.24832. None covers A121750. +- T. Niu, arXiv:2605.15500, 2605.04369, 2605.08444, 2605.16553 (2026). None covers A121750. +- M. Kauers, C. Koutschan, arXiv:2303.02793. Does not cover A121750. + +Note: the order-6 recurrence would follow routinely from Deutsch's first-order recurrence in the same entry (holonomic closure). That recurrence is stated in the entry without proof. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a121750, + author = {{math0}}, + title = {{Mathar's order-6 recurrence for A121750 (even-length columns in deco polyominoes) holds for all n >= 7}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a121750}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a121750/paper.pdf b/results/oeis-a121750/paper.pdf new file mode 100644 index 0000000..160e2a2 Binary files /dev/null and b/results/oeis-a121750/paper.pdf differ diff --git a/results/oeis-a121750/paper.tex b/results/oeis-a121750/paper.tex new file mode 100644 index 0000000..c257c6e --- /dev/null +++ b/results/oeis-a121750/paper.tex @@ -0,0 +1,351 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,at}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, upquote=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 + {≠}{{$\ne$}}1 {∈}{{$\in$}}1 {×}{{$\times$}}1 {·}{{$\cdot$}}1 {⟨}{{$\langle$}}1 + {⟩}{{$\rangle$}}1 {⌊}{{$\lfloor$}}1 {⌋}{{$\rfloor$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\ev}{\operatorname{ev}} +\newcommand{\cT}{\mathcal{T}} +\newcommand{\Iv}[1]{[\,#1\,]} + +\title[Mathar's recurrence for even columns in deco polyominoes]{Mathar's order-six D-finite recurrence for the number of even-length columns in deco polyominoes (OEIS A121750)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the total number of columns of even length over all deco polyominoes of height $n$ (OEIS A121750). In 2022 R.~J. Mathar conjectured that $a$ satisfies a linear recurrence of order~$6$ whose coefficients are polynomials in $n$ of degree at most~$3$. We prove this recurrence for every $n\ge7$. Starting from the combinatorial definition, a translation-invariance argument reduces the column-by-column enumeration to a small system of first-order relations, and Mathar's operator annihilates every solution of this system. We found no earlier proof, so we classify the result as new; it is not deep, since the recurrence would also follow by routine closure computations from a first-order recurrence of E.~Deutsch that the entry states without proof. The proof is verified in Lean~4 with Mathlib against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry; there $a(n)$ is defined by enumerating deco polyominoes and is checked by the kernel against all $19$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +A polyomino is \emph{directed} if each cell can be reached from a source cell by north and east unit steps inside the polyomino, and \emph{column-convex} if each column is a vertical segment. Its \emph{height measured along the diagonal} is the number of diagonals $x+y=\mathrm{const}$ that meet it. A \emph{deco polyomino} is a directed column-convex polyomino whose height along the diagonal is attained only in its last column. Barcucci, Del Lungo and Pinzani introduced deco polyominoes as a class in bijection with permutations, so that there are $n!$ of height $n$ \cite{BDP}. They were studied with succession rules in \cite{BBD}, and six bijections with permutations are given in \cite{DPP}. + +E.~Deutsch's OEIS entry A121750 \cite{A121750} (2006, offset~$1$) is the sequence $a(n)$, the total number of columns of even length over all deco polyominoes of height $n$: $0,1,5,26,184,1338,11652,\dots$; the corresponding triangle is A121748 \cite{A121748}. The entry records Deutsch's first-order recurrence +\begin{equation}\label{eq:deutsch} + a(n)=n\,a(n-1)+d(n-1)+(n-1)!\,\lfloor (n-1)/2\rfloor\qquad(n\ge2), +\end{equation} +with $a(1)=0$, $d(1)=1$, $d(2)=0$, $d(2m)=3!+5!+\dots+(2m-1)!$ and $d(2m+1)=-d(2m)$, without proof or reference. On July 26, 2022, R.~J. Mathar added the conjecture that $a$ satisfies the order-$6$ recurrence \eqref{eq:mathar} below. The current revision of the entry (\#13, August 20, 2024) still labels it ``Conjecture''. + +\subsection*{Prior work and status} +Conjectures recorded in the OEIS, among them many recurrences conjectured by Mathar, are the subject of several papers: Ekhad, Yang and Zeilberger prove many of Mathar's conjectured recurrences automatically \cite{EYZ} (their paper predates this conjecture), Fried proves a range of OEIS conjectures \cite{Fr24,Fr26}, and Kauers and Koutschan study OEIS sequences that appear to be D-finite \cite{KK}. None of them treats A121750, and the literature on deco polyominoes \cite{BDP,BBD,DPP} does not study columns of even length. The math0 referees found no proof of \eqref{eq:mathar} there, in the related entries A121747--A121751, or elsewhere on the web, so we classify the result as \emph{new}. It is not deep: if \eqref{eq:deutsch} is taken as known, $a$ is P-recursive by the closure properties of D-finite sequences \cite{Stanley}, and \eqref{eq:mathar} could be verified by a routine computation. Our proof does not assume \eqref{eq:deutsch}; it starts from the definition, and on paper the same relations also give \eqref{eq:deutsch} (Remark~\ref{rem:deutsch}). + +\section{Statement}\label{sec:statement} + +The FORMULA section of A121750 \cite{A121750} contains, verbatim: +\begin{lstlisting}[language={},basicstyle=\ttfamily\footnotesize] +Conjecture D-finite with recurrence a(n) +(-n-2)*a(n-1) +(-n^2+4*n-2)*a(n-2) +(n^3-3*n^2-4*n+11)*a(n-3) -(n-1)*(n^2-11*n+26)*a(n-4) +(-n^3+5*n^2+7*n-43)*a(n-5) +(n-3)*(n-5)^2*a(n-6)=0. - _R. J. Mathar_, Jul 26 2022 +\end{lstlisting} +For $n\in\Z$ put $p_0(n)=1$, $p_1(n)=-n-2$, $p_2(n)=-n^2+4n-2$, $p_3(n)=n^3-3n^2-4n+11$, $p_4(n)=-(n-1)(n^2-11n+26)$, $p_5(n)=-n^3+5n^2+7n-43$, $p_6(n)=(n-3)(n-5)^2$, and $L_n(x_0,\dots,x_6)=\sum_{k=0}^{6}p_k(n)\,x_k$. + +\begin{theorem}\label{thm:main} +Let $a(n)$ be the total number of columns of even length over all deco polyominoes of height $n$. Then for every $n\ge7$, +\begin{equation}\label{eq:mathar} + \sum_{k=0}^{6}p_k(n)\,a(n-k)=0 . +\end{equation} +\end{theorem} + +Mathar gives no range; since the sequence starts at $a(1)$ and \eqref{eq:mathar} involves $a(n-6)$, the natural range is $n\ge7$. (The Lean definition has $a(0)=0$, and with this value \eqref{eq:mathar} fails at $n=6$, with left-hand side $-3$.) + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A121750.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{c1f77c15\ldots 7414b}) before any proof attempt. The definitions and the statement read as follows (verbatim; omitted are the copyright header, the import, the module docstring, section headings, docstrings, blank lines, all theorems, and the auxiliary definitions \decl{IsTail}, \decl{eo}, \decl{nextRow}, \decl{tab} and \decl{aDP}, which are used only in proofs and data checks): +\begin{lstlisting} +namespace Math0.Statements.A121750 +def IsDeco (n : ℕ) (cs : List (ℕ × ℕ)) : Prop := + -- at least one column, and every column is a nonempty vertical segment + cs ≠ [] ∧ + (∀ c ∈ cs, c.1 ≤ c.2) ∧ + -- the source `(0, 0)` is the bottom cell of the first column + (∀ c ∈ cs.head?, c.1 = 0) ∧ + -- directed: the bottom cell of column `i + 1` has its west neighbour in column `i` + (∀ i (h : i + 1 < cs.length), cs[i].1 ≤ cs[i + 1].1 ∧ cs[i + 1].1 ≤ cs[i].2) ∧ + -- height `n` along the diagonal: `max (x + y) + 1 = n` over the cells (`min (x + y) = 0`) + (∀ i (h : i < cs.length), i + cs[i].2 + 1 ≤ n) ∧ + (∃ i, ∃ h : i < cs.length, i + cs[i].2 + 1 = n) ∧ + -- the height is attained only in the last column + (∀ i (h : i < cs.length), i + cs[i].2 + 1 = n → i + 1 = cs.length) +def tails : ℕ → ℕ → List (List (ℕ × ℕ)) + | 0, b => if b = 0 then [[(b, 0)]] else [] + | r + 1, b => (if b ≤ r + 1 then [[(b, r + 1)]] else []) ++ + (List.range' b (r + 1 - b)).flatMap fun t => + ((List.range' b (t + 1 - b)).flatMap (tails r)).map ((b, t) :: ·) +def decos : ℕ → List (List (ℕ × ℕ)) + | 0 => [] + | n + 1 => tails n 0 +def evenCols (cs : List (ℕ × ℕ)) : ℕ := + cs.countP fun c => (c.2 + 1 - c.1) % 2 == 0 +def a (n : ℕ) : ℕ := ((decos n).map evenCols).sum +def statement : Prop := + ∀ n : ℕ, 7 ≤ n → + (a n : ℤ) + (-(n : ℤ) - 2) * a (n - 1) + (-(n : ℤ) ^ 2 + 4 * n - 2) * a (n - 2) + + ((n : ℤ) ^ 3 - 3 * n ^ 2 - 4 * n + 11) * a (n - 3) - + ((n : ℤ) - 1) * ((n : ℤ) ^ 2 - 11 * n + 26) * a (n - 4) + + (-(n : ℤ) ^ 3 + 5 * n ^ 2 + 7 * n - 43) * a (n - 5) + + ((n : ℤ) - 3) * ((n : ℤ) - 5) ^ 2 * a (n - 6) = 0 +end Math0.Statements.A121750 +\end{lstlisting} + +\emph{Encoding.} Translate a directed column-convex polyomino so that its source, the bottom cell of its first column, is $(0,0)$. It is then determined by its columns $((b_0,t_0),\dots,(b_k,t_k))$, column $i$ being the cells $(i,y)$ with $b_i\le y\le t_i$, subject to $b_i\le t_i$, $b_0=0$ and $b_i\le b_{i+1}\le t_i$ (the bottom cell of column $i+1$ can only be entered from the west; conversely every cell is then reached by climbing a column, stepping east, and so on). The largest value of $x+y$ in column $i$ is $i+t_i$, and the smallest overall is $0$. So the height is $n$ iff $i+t_i+1\le n$ for all $i$ with equality for some $i$, and it is attained only in the last column iff equality forces $i=k$. These are the clauses of \decl{IsDeco}. The statement file proves that \texttt{decos n} lists exactly the column lists satisfying \texttt{IsDeco n}, each once (\decl{mem_decos}, \decl{nodup_decos}), so, up to this encoding, \texttt{a n} is literally the OEIS definition. The value \texttt{a 0} $=0$ is not a term and does not enter the statement. The arithmetic is in $\Z$, and the natural-number indices $n-k$, $k\le6= 2). Hasler's conjecture: a(n) = A025475(n) for all n > 2. Equivalently, R(n) = 4 exactly when n = 6 or n is a proper prime power. + +## Assessment + +The proof uses the closed form T(n,k) = f(k) - f(k+1), with f(k) = mu(n/k) when k | n and 0 otherwise. That formula is already stated in cross-referenced A123706, and checking it is a short Moebius-inversion and Abel-summation calculation. Row n then has one nonzero entry for each place where f changes value. If n is not squarefree, the support of f has 2^omega(n) elements and no two of them are consecutive, so the row has 2^(omega+1) nonzero entries; this gives 4 exactly for proper prime powers. For squarefree n, a short case check (two consecutive divisors k, k+1 force k(k+1) | n) leaves only n = 6. All of this is an elementary page-length argument that follows from material already in the entry's cross-references. + +*Follows from:* The closed form T(n,k) = mu(n/k) - mu(n/(k+1)) given in cross-referenced A123706 (Perez Herrero, 2012), together with Hasler's 2^k / omega description of A123709 (exception n = 6). Checking the closed form is a one-line Moebius inversion (sum over d | m of mu(d) = [m = 1]). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A123710](https://oeis.org/A123710) as [`Math0.Statements.A123710.statement`](../../lean/Math0/Statements/OEIS/A123710.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A123710.lean`](../../lean/Math0/Frontier/OEIS/A123710.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A123710 a(n) = A025475(n) for n>2 (conjectured). - _M. F. Hasler_, Feb 12 2012 + +Referees: OEIS sequences, all read from the local mirror and checked against https://raw.githubusercontent.com/oeis/oeisdata/main/seq/: +- A123710 (#27, Sep 05 2025): formula still marked "(conjectured)" (Hasler, Feb 12 2012). +- A123709: Hasler's 2^k / omega formula with the n = 6 exception, given without proof. Links Luschny's seqcomp message http://groups.google.com/group/seqcomp/msg/2aabf27ef9b698ef (Feb 2012). The visible part of that thread has the closed form and asks for a proof of A123712 = A178212, but nothing on A123710. +- A123706: Perez Herrero closed form T(n,k) = mu(n/k) - mu(n/(k+1)) (Feb 21 2012), without proof. +- A123711 and A200511, A123712 and A178212: related conjectures, still open. +- A206706: Luschny's variant triangle. + +Other sources: +- OEIS wiki, "Sequences determined by prime signature": lists A123711 and A123712 under "Examples which need to be checked". +- S. Fried, JIS 28 (2025) Art. 25.4.3; JIS 29 (2026) Art. 26.1.8; arXiv:2607.24832 (Jul 2026). None treat A123710. + +Searches of arXiv, MathOverflow and MSE found no proof of A123710. The SeqFan Feb 2012 archive was unreachable. + +## Citation + +```bibtex +@misc{math0:oeis-a123710, + author = {{math0}}, + title = {{A123710: the rows of inv(floor(n/k)) with four nonzero entries are 6 and the proper prime powers}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a123710}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a124526/README.md b/results/oeis-a124526/README.md new file mode 100644 index 0000000..6580fab --- /dev/null +++ b/results/oeis-a124526/README.md @@ -0,0 +1,43 @@ +# Hanna's conjecture A124418(n,k) = k! * A124526(n,k) (partitions with k mixed-parity blocks) proved + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A124526 +**Date:** 2026-10-21 + +## Result + +For all n >= 0 and 0 <= k <= floor(n/2): the number A124418(n,k) of set partitions of {1,...,n} with exactly k blocks containing both an odd and an even entry equals k! * A049020(floor(n/2),k) * A049020(floor((n+1)/2),k), where A049020(m,k) = sum_{i=0}^{m} S2(m,i) * C(i,k) and S2 is the Stirling number of the second kind. (The proof does not need the bound k <= floor(n/2); the identity holds for every k.) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A124526](https://oeis.org/A124526) as [`Math0.Statements.A124526.statement`](../../lean/Math0/Statements/OEIS/A124526.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A124526.lean`](../../lean/Math0/Frontier/OEIS/A124526.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: A124526: "A124418(n,k) = k!*T(n,k) (conjecture)."; A124418 %F: "Conjecture: T(n,k) = k!*A049020([n/2],k)*A049020([(n+1)/2],k) ... - _Paul D. Hanna_, Nov 08 2006" + +Referees: OEIS entries read from the local mirror: A124526, A124418 (Hanna's 2006 conjecture in %F; Heinz's 2013 alternative Maple program uses the equivalent product formula), A049020 (cites East–Gray and Halverson–Jacobson), A244489, A124419 (k=0 column: Bell(floor(n/2))·Bell(ceil(n/2))), A124529, A362495. + +Prior proofs, stated in partition-monoid and partition-category language: +- J. East and R. D. Gray, "Diagram monoids and Graham–Houghton graphs: Idempotents and generating sets of ideals", J. Combin. Theory Ser. A 146 (2017) 63–128, doi:10.1016/j.jcta.2016.09.001, arXiv:1404.2359. Proof of Theorem 7.5 and Remark 7.7: |J_r(P_n)| = ρ_{nr}^2·r!, with ρ_{nr} = Σ_j S(n,j)C(j,r). This is the even-n case. +- T. Halverson and T. N. Jacobson, "Set-partition tableaux and representations of diagram algebras", arXiv:1808.08118 (Algebraic Combinatorics 2020), Remark 3.23: the rank-m diagrams in P_k number |W^m_k|^2·m!, where |W^m_k| = A049020(k,m). +- I. Đurđev, I. Dolinka and J. East, "Sandwich semigroups in diagram categories", arXiv:1910.10286 (Internat. J. Algebra Comput. 2021), Proposition 4.11 and Remark 4.12: for the partition category P_{mn}, |D_r| = r!·[Σ_q C(q,r)S(m,q)]·[Σ_q C(q,r)S(n,q)]. Taking m = ⌈n/2⌉ and n = ⌊n/2⌋ gives the full conjecture. + +Checked and not relevant: Yaqubi–Mirzavaziri arXiv:2608.30097; Ehrenborg–Hedmark–Hettle (JIS 2017, odd/even block sizes); Shattuck arXiv:1401.6588. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a124526, + author = {{math0}}, + title = {{Hanna's conjecture A124418(n,k) = k! * A124526(n,k) (partitions with k mixed-parity blocks) proved}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a124526}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a124526/paper.pdf b/results/oeis-a124526/paper.pdf new file mode 100644 index 0000000..cf6a572 Binary files /dev/null and b/results/oeis-a124526/paper.pdf differ diff --git a/results/oeis-a124526/paper.tex b/results/oeis-a124526/paper.tex new file mode 100644 index 0000000..7b2c29d --- /dev/null +++ b/results/oeis-a124526/paper.tex @@ -0,0 +1,410 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage[T1]{fontenc} +\usepackage{lmodern} +\usepackage{amsmath,amssymb,amsthm,mathtools,mathrsfs} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{booktabs} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,unfold,rw,at,infer_instance}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {∑}{{$\sum$}}1 + {∈}{{$\in$}}1 {∧}{{$\wedge$}}1 {≤}{{$\le$}}1 {→}{{$\to$}}1 {¬}{{$\neg$}}1 + {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +\raggedbottom +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Stir}[2]{S(#1,#2)} +\newcommand{\nC}{n_{\mathrm C}} +\newcommand{\nN}{n_{\mathrm N}} +\newcommand{\nM}{n_{\mathrm M}} +\newcommand{\cnt}{\operatorname{cnt}} +\newcommand{\ins}{\operatorname{ins}} + +\title[Partitions with $k$ blocks of mixed parity]{Set partitions of $\{1,\dots,n\}$ with $k$ blocks of mixed parity: a formal proof of Hanna's product formula (OEIS A124418, A124526)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 21, 2026} + +\begin{document} +\begin{abstract} +Let $M(n,k)$ be the number of set partitions of $\{1,\dots,n\}$ with exactly $k$ blocks that contain both an odd and an even entry (OEIS A124418). +In 2006 P.~D.~Hanna conjectured that $M(n,k)=k!\,a(\lfloor n/2\rfloor,k)\,a(\lceil n/2\rceil,k)$, where $a(m,k)=\sum_i S(m,i)\binom ik$ (OEIS A049020) counts the partitions of an $m$-set with $k$ distinguished blocks; both OEIS entries still record the formula as a conjecture. +We prove it for all $n\ge0$ and $0\le k\le\lfloor n/2\rfloor$, the full index range of both triangles, by counting, by induction on the ground set, the partitions with given numbers of blocks meeting the odd entries, the even entries, and both. +The formula is not new: with the odd entries as the top row and the even entries as the bottom row of a partition diagram, mixed blocks are the transversal blocks, and the formula is the known count of partition diagrams of rank $k$ (East and Gray for even $n$; Dolinka, \DJ ur\dj ev and East for all $n$); our contribution is the first formal proof. +The proof is verified in Lean~4 with Mathlib against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry; its definitions are checked by the kernel against the entry's data. +\end{abstract} +\maketitle + +\section{Introduction} + +A \emph{partition} of a finite set $s$ is a set of nonempty, pairwise disjoint subsets of $s$ (the \emph{blocks}) whose union is $s$. +Call a block $b\subseteq\N$ \emph{mixed} if it contains an odd and an even number. +The OEIS triangle A124418 \cite{A124418}, contributed by Emeric Deutsch on October~31, 2006, has entries +\[ + M(n,k)=\#\{\text{partitions of }[n]=\{1,\dots,n\}\text{ with exactly $k$ mixed blocks}\},\qquad 0\le k\le\lfloor n/2\rfloor . +\] +For example, $M(4,0)=4$, $M(4,1)=9$ and $M(4,2)=2$, the last two partitions being $12|34$ and $14|23$. +Let $S(m,i)$ denote the Stirling numbers of the second kind and +\[ + a(m,k)=\sum_{i=0}^{m}S(m,i)\binom ik , +\] +the triangle A049020 \cite{A049020}: $a(m,k)$ is the number of partitions of an $m$-set in which $k$ of the blocks have been distinguished. +On November~8, 2006, Paul D.~Hanna contributed the triangle A124526 \cite{A124526}, +\[ + T(n,k)=a(\lfloor n/2\rfloor,k)\,a(\lfloor (n+1)/2\rfloor,k), +\] +together with the conjecture $M(n,k)=k!\,T(n,k)$, recorded in both entries (Section~\ref{sec:statement}). +We prove it. + +\begin{theorem}\label{thm:main} +For all $n\ge0$ and all $k$ with $0\le k\le\lfloor n/2\rfloor$, +\[ + M(n,k)=k!\,T(n,k)=k!\;a\bigl(\lfloor n/2\rfloor,k\bigr)\;a\bigl(\lceil n/2\rceil,k\bigr). +\] +\end{theorem} + +This is exactly the statement verified in Lean (Section~\ref{sec:statement}): Hanna's conjecture over the full index range of both triangles. +The proof does not use the bound $k\le\lfloor n/2\rfloor$. The identity also holds, trivially, for $k>\lfloor n/2\rfloor$, where both sides vanish: each mixed block contains one of the $\lfloor n/2\rfloor$ even entries, and $\binom ik=0$ for $i\le\lfloor n/2\rfloor (List.range (n / 2 + 1)).map (T n)).getD i 0 + +def IsMixed (b : Finset ℕ) : Prop := (∃ x ∈ b, Odd x) ∧ (∃ x ∈ b, Even x) + +instance : DecidablePred IsMixed := fun b => by unfold IsMixed; infer_instance + +def A124418 (n k : ℕ) : ℕ := + (univ.filter fun P : Finpartition (Icc 1 n) => (P.parts.filter IsMixed).card = k).card + +def statement : Prop := + ∀ n k : ℕ, k ≤ n / 2 → A124418 n k = k.factorial * T n k +\end{lstlisting} + +\subsection*{Encoding and check against the OEIS data} +\texttt{A049020 m k} is $a(m,k)$, with Mathlib's \decl{Nat.stirlingSecond}, defined by the recurrence $S(0,0)=1$, $S(0,i+1)=S(m+1,0)=0$, $S(m+1,i+1)=(i+1)S(m,i+1)+S(m,i)$; this agrees with the explicit alternating sum quoted in the entry. +In $\N$, \texttt{n / 2} and \texttt{(n + 1) / 2} are $\lfloor n/2\rfloor$ and $\lfloor(n+1)/2\rfloor=\lceil n/2\rceil$, so \texttt{T n k} is A124526's $T(n,k)$, and \texttt{a} is the triangle read by rows with offset~$0$. +A Mathlib \texttt{Finpartition (Icc 1 n)} is a finite set of nonempty, pairwise disjoint finite sets with union $\{1,\dots,n\}$, and two such are equal iff they have the same parts; so \texttt{A124418 n k} is Deutsch's definition of $M(n,k)$, not the conjectured formula. +For $n=0$ the empty partition has no mixed block, matching row $0$ of A124418. The statement quantifies over the full index range of both triangles. + +The statement file checks its definitions against the OEIS data by \texttt{decide +kernel}: \decl{T_data} and \decl{a_data} reproduce all $16$ listed rows and all $72$ listed terms of A124526; \decl{A124418_data} evaluates the \texttt{Finpartition}-based definition of A124418 on rows $n=0,\dots,3$, giving $1;\,1;\,1,1;\,2,3$ as listed (Mathlib enumerates \texttt{Finpartition}s through the power set of the power set of the ground set, and a kernel evaluation of row $n=4$ did not finish); and \decl{rhs_data} checks that $k!\,T(n,k)$ reproduces all $49$ listed terms of A124418 (rows $0,\dots,12$), which tests the transcription of the right-hand side but proves nothing about the conjecture. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A124526.lean}; the names in parentheses are the corresponding Lean declarations. +Throughout, $c$ is a decidable predicate on $\N$, $s$ is a finite subset of $\N$, and partitions are as above. +Say that a block $b$ \emph{meets} $c$ if $c(x)$ holds for some $x\in b$. +For a partition $P$ of $s$ let $\nC(P)$, $\nN(P)$ and $\nM(P)$ be the numbers of blocks of $P$ that meet $c$, that meet $\neg c$, and that meet both $c$ and $\neg c$. +Let $\cnt_c(s;i,j,k)$ be the number of partitions $P$ of $s$ with $(\nC,\nN,\nM)(P)=(i,j,k)$, and +\[ + F(o,e,i,j,k)=S(o,i)\,S(e,j)\binom ik\binom jk k! . +\] + +\begin{proposition}[\decl{cnt_eq}]\label{prop:refined} +Let $o=\#\{x\in s:c(x)\}$ and $e=\#\{x\in s:\neg c(x)\}$. Then $\cnt_c(s;i,j,k)=F(o,e,i,j,k)$ for all $i,j,k\ge0$. +\end{proposition} + +\begin{remark}[Bijective meaning]\label{rem:bij} +$F(o,e,i,j,k)$ counts triples consisting of a partition of $s\cap c$ into $i$ blocks with $k$ of them marked, a partition of $s\setminus c$ into $j$ blocks with $k$ of them marked, and a bijection between the two sets of marked blocks. +Restricting a partition of $s$ to $s\cap c$ and to $s\setminus c$, marking the traces of the mixed blocks and matching the two traces of each mixed block is a bijection onto such triples, which proves Proposition~\ref{prop:refined} directly. +The formal proof uses the induction below instead, which needs only one simple bijection. +\end{remark} + +\subsection{Inserting one element} +Let $t$ be finite, $a\notin t$, and $P$ a partition of $t$. For $x\in\{\varnothing\}\cup P$ define (\decl{insP}, \decl{ins}) +\[ + \ins(P,\varnothing)=P\cup\bigl\{\{a\}\bigr\},\qquad + \ins(P,b)=\bigl(P\setminus\{b\}\bigr)\cup\bigl\{b\cup\{a\}\bigr\}\quad(b\in P). +\] +Each is a partition of $t\cup\{a\}$: its blocks are nonempty subsets of $t\cup\{a\}$, and every $y\in t\cup\{a\}$ lies in exactly one of them (in Lean, \decl{Finpartition.ofExistsUnique} builds the partition from these three facts). + +\begin{lemma}[\decl{ins_injective}, \decl{ins_surjective}, \decl{card_filter_ins}]\label{lem:ins} +The map $(P,x)\mapsto\ins(P,x)$, from pairs of a partition $P$ of $t$ and $x\in\{\varnothing\}\cup P$, to partitions of $t\cup\{a\}$, is a bijection. Consequently, for every property $f$ of partitions of $t\cup\{a\}$, +\[ + \#\{R: f(R)\}=\sum_{P}\#\bigl\{x\in\{\varnothing\}\cup P: f(\ins(P,x))\bigr\}. +\] +\end{lemma} + +\begin{proof} +Since $a$ lies in no block of $P$, deleting $a$ from every block of $\ins(P,x)$ and discarding the empty set returns $P$ (\decl{rec_insP}); so $\ins(P,x)=\ins(P',x')$ implies $P=P'$. +Next, $\{a\}\in\ins(P,\varnothing)$ but $\{a\}\notin\ins(P,b)$, because $b\cup\{a\}\ne\{a\}$ ($b$ is nonempty) and no block of $P$ contains $a$ (\decl{insP_none_ne_some}). +Finally, if $\ins(P,b)=\ins(P,b')$ then $b\cup\{a\}$ is a block of $\ins(P,b')$ containing $a$, hence equals $b'\cup\{a\}$, and removing $a$ gives $b=b'$. This proves injectivity. +For surjectivity, let $R$ be a partition of $t\cup\{a\}$, let $B$ be its block containing $a$, and let $P$ be obtained from $R$ by deleting $a$ from every block and discarding the empty set (\decl{recP}); $P$ is a partition of $t$. +If $B=\{a\}$ then $R=\ins(P,\varnothing)$; otherwise $B\setminus\{a\}\in P$ and $R=\ins(P,B\setminus\{a\})$. +The counting formula is the cardinality of a set of pairs computed through this bijection (\decl{card_bij}). +\end{proof} + +\begin{lemma}[\decl{card_filter_not_C}]\label{lem:notC} +The number of blocks of $P$ that do not meet $c$ is $\nN(P)-\nM(P)$. +\end{lemma} + +\begin{proof} +The blocks meeting $\neg c$ split into the mixed ones and those not meeting $c$; conversely a block not meeting $c$ is nonempty and therefore meets $\neg c$. +\end{proof} + +\begin{lemma}[\decl{stats_none}, \decl{stats_some_C}, \decl{stats_some_N}]\label{lem:stats} +Let $c(a)$ hold and let $P$ be a partition of $t$. Then +\begin{enumerate} +\item $(\nC,\nN,\nM)(\ins(P,\varnothing))=(\nC(P)+1,\nN(P),\nM(P))$; +\item if $b\in P$ meets $c$, then $(\nC,\nN,\nM)(\ins(P,b))=(\nC,\nN,\nM)(P)$; +\item if $b\in P$ does not meet $c$, then $(\nC,\nN,\nM)(\ins(P,b))=(\nC(P)+1,\nN(P),\nM(P)+1)$. +\end{enumerate} +\end{lemma} + +\begin{proof} +(1) The new block $\{a\}$ meets $c$ but not $\neg c$. +In (2) and (3), the block $b$ is replaced by $b\cup\{a\}$, which meets $c$ and meets $\neg c$ iff $b$ does (as $c(a)$). +In (2), $b$ and $b\cup\{a\}$ therefore have the same three properties. +In (3), $b$ does not meet $c$, so it meets $\neg c$ (it is nonempty) and is not mixed, while $b\cup\{a\}$ meets $c$ and is mixed; so $\nC$ and $\nM$ increase by one and $\nN$ is unchanged. +\end{proof} + +\begin{lemma}[\decl{card_choices}, \decl{cnt_insert}, \decl{sum1_zero}--\decl{sum3_succ}]\label{lem:rec} +Let $c(a)$ hold, and write $N(i,j,k)=\cnt_c(t;i,j,k)$ and $N'(i,j,k)=\cnt_c(t\cup\{a\};i,j,k)$. Then for all $i,j,k$, +\begin{align*} + N'(0,j,k)&=0,\qquad N'(i+1,j,0)=N(i,j,0)+(i+1)N(i+1,j,0),\\ + N'(i+1,j,k+1)&=N(i,j,k+1)+(i+1)N(i+1,j,k+1)+(j-k)N(i,j,k), +\end{align*} +where $j-k$ is truncated subtraction in $\N$ (it only multiplies terms with $k\le j$). +\end{lemma} + +\begin{proof} +Apply Lemma~\ref{lem:ins} with $f(R)$: $(\nC,\nN,\nM)(R)=(I,J,K)$. For fixed $P$ with statistics $(i',j',k')$, Lemmas~\ref{lem:stats} and~\ref{lem:notC} show that the choice $x=\varnothing$ gives $(i'+1,j',k')$, each of the $i'$ blocks meeting $c$ gives $(i',j',k')$, and each of the $j'-k'$ blocks not meeting $c$ gives $(i'+1,j',k'+1)$. +Summing over $P$, the first kind contributes $0$ if $I=0$ and $N(I-1,J,K)$ otherwise; the second contributes $I\cdot N(I,J,K)$, which is $0$ if $I=0$; the third contributes $0$ if $I=0$ or $K=0$, and $\bigl(J-(K-1)\bigr)\,N(I-1,J,K-1)$ otherwise. +\end{proof} + +\begin{lemma}[\decl{step}]\label{lem:step} +$F(o+1,e,\cdot,\cdot,\cdot)$ is obtained from $F(o,e,\cdot,\cdot,\cdot)$ by the recurrence of Lemma~\ref{lem:rec}. Hence, if $c(a)$ holds and $\cnt_c(t;i,j,k)=F(o,e,i,j,k)$ for all $i,j,k$, where $o,e$ are the counts for $t$, then $\cnt_c(t\cup\{a\};i,j,k)=F(o+1,e,i,j,k)$ for all $i,j,k$. +\end{lemma} + +\begin{proof} +Write $S=S(o,\cdot)$, $S'=S(e,\cdot)$ and use $S(o+1,0)=0$ and $S(o+1,i+1)=(i+1)S(o,i+1)+S(o,i)$. +If $i=0$, then $F(o+1,e,0,j,k)=0$. +If $k=0$, then $F(o+1,e,i+1,j,0)=\bigl((i+1)S(i+1)+S(i)\bigr)S'(j)$, which is the right-hand side. +For the indices $(i+1,j,k+1)$, expanding $S(o+1,i+1)$ and using Pascal's rule $\binom{i+1}{k+1}=\binom ik+\binom i{k+1}$, the difference between $F(o+1,e,i+1,j,k+1)$ and the right-hand side +$F(o,e,i,j,k+1)+(i+1)F(o,e,i+1,j,k+1)+(j-k)F(o,e,i,j,k)$ equals +\[ + S(i)\,S'(j)\binom ik k!\Bigl(\binom j{k+1}(k+1)-\binom jk(j-k)\Bigr)=0, +\] +by $(k+1)!=(k+1)k!$ and the identity $\binom j{k+1}(k+1)=\binom jk(j-k)$ (\decl{Nat.choose_succ_right_eq}, valid with truncated subtraction). +In Lean the last case is closed by \texttt{linear\_combination} over $\mathbb Z$ after this identity is cast. +\end{proof} + +\begin{proof}[Proof of Proposition~\ref{prop:refined}] +Induction on $s$ (\decl{Finset.induction_on}), for all $(i,j,k)$ simultaneously. +For $s=\varnothing$ the only partition is the empty one, so $\cnt(\varnothing;i,j,k)=[i=j=k=0]$, and $F(0,0,i,j,k)=[i=0][j=0]\binom 0k^2k!=[i=j=k=0]$. +For $s=t\cup\{a\}$ with $a\notin t$: if $c(a)$, then $s$ has $o+1$ elements satisfying $c$ and $e$ satisfying $\neg c$, and Lemma~\ref{lem:step} applies. +If $\neg c(a)$, replace $c$ by $\neg c$. This exchanges $\nC$ and $\nN$ and fixes $\nM$, so $\cnt_{\neg c}(s;i,j,k)=\cnt_c(s;j,i,k)$ (\decl{cnt_not}), and $F(o,e,i,j,k)=F(e,o,j,i,k)$ (\decl{F_comm}). +The induction hypothesis for $t$ thus gives $\cnt_{\neg c}(t;\cdot)=F(e,o,\cdot)$; since $\neg c(a)$, Lemma~\ref{lem:step} for $\neg c$ gives $\cnt_{\neg c}(s;j,i,k)=F(e+1,o,j,i,k)$, that is, $\cnt_c(s;i,j,k)=F(o,e+1,i,j,k)$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main} (\decl{result})] +Take $c=\mathrm{Odd}$ and $s=[n]$. By induction on $n$, $[n]$ has $o=\lceil n/2\rceil=\lfloor(n+1)/2\rfloor$ odd and $e=\lfloor n/2\rfloor$ non-odd elements (\decl{card_odd}). +A block is \texttt{IsMixed} iff it meets $\mathrm{Odd}$ and $\neg\mathrm{Odd}$, since a natural number is even iff it is not odd; so $M(n,k)$ counts the partitions with $\nM=k$. +Each statistic is at most the number of blocks, which is at most $n$ (\decl{Finpartition.card_parts_le_card}). +Grouping the partitions with $\nM=k$ by $(\nC,\nN)\in\{0,\dots,n\}^2$ (\decl{card_eq_sum_card_fiberwise}) and applying Proposition~\ref{prop:refined}, +\[ + M(n,k)=\sum_{i=0}^{n}\sum_{j=0}^{n}S(o,i)S(e,j)\binom ik\binom jk k! + =k!\Bigl(\sum_{i=0}^{n}S(o,i)\binom ik\Bigr)\Bigl(\sum_{j=0}^{n}S(e,j)\binom jk\Bigr). +\] +Since $S(m,i)=0$ for $i>m$ and $o,e\le n$, the two sums are $a(o,k)$ and $a(e,k)$ (\decl{sum_eq_A049020}), so $M(n,k)=k!\,a(e,k)\,a(o,k)=k!\,T(n,k)$. +The hypothesis $k\le\lfloor n/2\rfloor$ of \decl{statement} is introduced and not used. +\end{proof} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is the file \path{lean/Math0/Frontier/OEIS/A124526.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. +It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A124526.lean} and the audit commands in \path{lean/Math0/Audit.lean}. +The main declaration is \decl{Math0.Frontier.A124526.result}, declared as \texttt{theorem result : statement}; its type is the constant \decl{Math0.Statements.A124526.statement}. +All other declarations are private; the main ones are named in Section~\ref{sec:proof}. +The private definitions \texttt{nC}, \texttt{nN}, \texttt{nM}, \texttt{cnt} and \texttt{F} are those of Section~\ref{sec:proof}, with \texttt{Finpartition s} for partitions and \texttt{\#(P.parts.filter $\cdots$)} for the numbers of blocks; Proposition~\ref{prop:refined} reads +\begin{lstlisting} +private theorem cnt_eq (s : Finset ℕ) : + ∀ i j k, cnt c s i j k = F #(s.filter c) #(s.filter fun x => ¬ c x) i j k +\end{lstlisting} +No bounded computation is used, and the file has no \texttt{sorry}, \texttt{native\_decide}, \texttt{set\_option}, axioms or custom syntax. + + + +\subsection*{Audit} +The file ends with the command \texttt{\#math0\_settles}~\decl{Math0.Frontier.A124526.result}~\decl{Math0.Statements.A124526.statement}. +This command, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a universe-monomorphic \texttt{Prop}-valued definition; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} behind \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically \decl{statement} or its negation, without unfolding. +Running \texttt{lake env lean Math0/Frontier/OEIS/A124526.lean} in the directory \path{lean} prints\par\nobreak\noindent +\begin{minipage}{\linewidth} +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A124526.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A124526.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A124526.result' proves 'Math0.Statements.A124526.statement' +\end{lstlisting} +\end{minipage} +so \decl{result} proves the statement using only the three permitted axioms. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use (the statement is math0's own). +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib cache, runs \texttt{lake build} (re-running every audit command), and checks that the pinned dependencies are unmodified. +For this result alone, run \texttt{lake build Math0.Statements.OEIS.A124526} and then the command above in \path{lean}; the proof file elaborates in under half a minute. + +{\small +\begin{thebibliography}{99} + +\bibitem{DDE21} +I.~Dolinka, I.~\DJ ur\dj ev and J.~East, \emph{Sandwich semigroups in diagram categories}, Internat.\ J.\ Algebra Comput.\ \textbf{31} (2021), no.~7, 1339--1404, doi:10.1142/S021819672150048X; arXiv:1910.10286. + +\bibitem{EG17} +J.~East and R.~D.~Gray, \emph{Diagram monoids and Graham--Houghton graphs: idempotents and generating sets of ideals}, J.\ Combin.\ Theory Ser.~A \textbf{146} (2017), 63--128, doi:10.1016/j.jcta.2016.09.001; arXiv:1404.2359. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{HJ20} +T.~Halverson and T.~N.~Jacobson, \emph{Set-partition tableaux and representations of diagram algebras}, Algebr.\ Comb.\ \textbf{3} (2020), no.~2, 509--538, doi:10.5802/alco.102; arXiv:1808.08118. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{A049020} +The OEIS Foundation Inc., \url{https://oeis.org/A049020}. + +\bibitem{A124418} +The OEIS Foundation Inc., \url{https://oeis.org/A124418}, entry by E.~Deutsch, Oct.~31, 2006. + +\bibitem{A124419} +The OEIS Foundation Inc., \url{https://oeis.org/A124419}, entry by E.~Deutsch, Oct.~31, 2006. + +\bibitem{A124526} +The OEIS Foundation Inc., \url{https://oeis.org/A124526}, entry by P.~D.~Hanna, Nov.~8, 2006. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a126127/README.md b/results/oeis-a126127/README.md new file mode 100644 index 0000000..1b02c59 --- /dev/null +++ b/results/oeis-a126127/README.md @@ -0,0 +1,41 @@ +# A126127: Israel's conjectured bivariate g.f. of the inverse square of A061554 holds + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A126127 +**Date:** 2026-10-29 + +## Result + +Let M be the infinite lower-triangular matrix with M(n,k) = binomial(n, floor((n-k)/2)) for 0 <= k <= n (A061554), and let T = M^(-2) (A126127). Then, as formal power series in x, y over Q, sum_{n>=0} sum_{k=0}^{n} T(n,k) x^n y^k = (1-x)(1-x+x^2) / (1 - xy + 3x^2 - x^3 y + x^4). + +## Assessment + +A130777, which A126127 itself points to as the inverse of A061554, already identifies M^(-1) as the Riordan array ((1-x)/(1+x^2), x/(1+x^2)). The conjecture is about the square of that array. Squaring it with the standard Riordan product rule and simplifying two short rational functions gives the stated g.f. in a few lines. The Lean proof avoids Riordan machinery and uses recurrences instead, but that is formalization effort, not a new mathematical idea. + +*Follows from:* The cross-referenced entry A130777 says it is the inverse of A061554 and gives it as the Riordan array ((1-x)/(1+x^2), x/(1+x^2)) (Paul Barry, 2009). Its row-polynomial o.g.f. (1-z)/(1-xz+z^2) is the bivariate g.f. of M^(-1). The standard Riordan group product (g,f)*(h,l) = (g*(h o f), l o f) then gives M^(-2) = (g*(g o f), f o f), where g*(g o f) = (1-x)(1-x+x^2)/(1+3x^2+x^4) and f o f = x(1+x^2)/(1+3x^2+x^4). That is exactly Israel's g.f. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A126127](https://oeis.org/A126127) as [`Math0.Statements.A126127.statement`](../../lean/Math0/Statements/OEIS/A126127.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A126127.lean`](../../lean/Math0/Frontier/OEIS/A126127.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A126127 G.f. as triangle (conjectured): (1-x)*(1-x+x^2)/(1-x*y+3*x^2-x^3*y+x^4). - _Robert Israel_, Jul 07 2019 + +Referees: OEIS A126127 (Gary W. Adamson, 2006): conjectured g.f. by Robert Israel, Jul 07 2019, still marked conjectured upstream (oeisdata seq/A126/A126127.seq, %I #10, no %E edits). OEIS A130777: "Inverse of triangle in A061554", Riordan array ((1-x)/(1+x^2), x/(1+x^2)) by Paul Barry, May 21 2009; together with the standard Riordan group product rule (Shapiro, Getu, Woan, Woodson, 1991), this makes the conjecture an immediate corollary, but no source found states or proves the g.f. of the square. OEIS A061554: Riordan array (1/(1-x-x^2c(x^2)), x c(x^2)) by Philippe Deléham, 2007. Web searches (OEIS, arXiv, MathOverflow/Math StackExchange, SeqFan) found no prior proof or counterexample. + +## Citation + +```bibtex +@misc{math0:oeis-a126127, + author = {{math0}}, + title = {{A126127: Israel's conjectured bivariate g.f. of the inverse square of A061554 holds}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a126127}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a127752/README.md b/results/oeis-a127752/README.md new file mode 100644 index 0000000..a0e3430 --- /dev/null +++ b/results/oeis-a127752/README.md @@ -0,0 +1,45 @@ +# A127752 mod 2 is the first Feigenbaum symbolic sequence A035263 + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A127752 +**Date:** 2026-10-25 + +## Result + +Let A(n,k) = 1/(3n+1) if k <= n <= 2k and 0 otherwise (n, k >= 0), and let a(n) be the row sums of the inverse of this lower-triangular matrix. Equivalently, a is defined by forward substitution: a(n) = 3n+1 - sum_{j 11, 1 -> 10 (offset 1). Then for every n >= 0, a(n) mod 2 = A035263(n+1). This is Paul Barry's 2007 conjecture. + +## Assessment + +The whole argument is to write row n of A s = 1 as a window sum, sum_{j=ceil(n/2)}^{n} s(j) = 3n+1, and subtract consecutive rows. This gives s(2m+2)=3 and s(2m+1)=s(m)+3, which also yields a closed form in terms of the 2-adic valuation of n+1. Parity then follows by a one-line induction against the recursion a(2n)=1-a(n), a(2n+1)=1, which is already listed in A035263. This is a half-page, standard telescoping argument that a competent mathematician would find within minutes. Most of the effort went into the formalization (morphic-word indexing, matrix-inverse link), not into new mathematics. + +*Follows from:* The row-n equation of the lower-triangular system A s = 1, i.e. sum_{ceil(n/2)<=j<=n} s(j) = 3n+1. Taking differences of consecutive rows gives s(0)=1, s(2m+2)=3 and s(2m+1)=s(m)+3. Compare this with the formula a(2n)=1-a(n), a(2n+1)=1 already listed in A035263 (equivalently, the parity of the 2-adic valuation of 2n). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A127752](https://oeis.org/A127752) as [`Math0.Statements.A127752.statement`](../../lean/Math0/Statements/OEIS/A127752.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A127752.lean`](../../lean/Math0/Frontier/OEIS/A127752.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: a(n) mod 2 is first Feigenbaum symbolic sequence A035263 (conjecture). (Paul Barry, Jan 28 2007; checked to 2048 terms by Antti Karttunen, Sep 29 2018) + +Referees: OEIS A127752 (P. Barry, Jan 28 2007; current version #11, Feb 11 2021) still says "(conjecture)", with A. Karttunen's 2018 check of the first 2048 terms. A127751 (#5) still calls it conjectural, and the related A127750, A127749 and A111967 conjectures (Fredholm-Rueppel parity for the 1/(2n+1) triangle) remain open. Checked and not relevant: S. Fried, "On the inverse of a certain triangular matrix and its connection to the largest odd divisor", NNTDM 32(2) (2026) 255-262, which covers A127793 and A000265, not A127752; S. Fried, JIS 28 (2025) Art. 25.4.3 and JIS 29 (2026) Art. 26.1.8; S. Fried, arXiv:2607.24832. No prior proof or counterexample found, and no existing formalization in formal-conjectures. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a127752, + author = {{math0}}, + title = {{A127752 mod 2 is the first Feigenbaum symbolic sequence A035263}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a127752}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a127752/paper.pdf b/results/oeis-a127752/paper.pdf new file mode 100644 index 0000000..cee3bb2 Binary files /dev/null and b/results/oeis-a127752/paper.pdf differ diff --git a/results/oeis-a127752/paper.tex b/results/oeis-a127752/paper.tex new file mode 100644 index 0000000..ecae94f --- /dev/null +++ b/results/oeis-a127752/paper.tex @@ -0,0 +1,349 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,at,split_ifs,push_cast,using}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 + {∧}{{$\wedge$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {∈}{{$\in$}}1 {∑}{{$\sum$}}1 + {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {↦}{{$\mapsto$}}1 {⁻}{{$^{-}$}}1 {¹}{{$^{1}$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {⊢}{{$\vdash$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{⊢}{\ensuremath{\vdash}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\pd}{\mathbf{d}} + +\title[Row sums of an inverse band triangle modulo 2]{The row sums of the inverse of the band triangle $1/(3n+1)$, $k\le n\le 2k$, are the period-doubling sequence modulo~$2$ (OEIS A127752)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 25, 2026} + +\begin{document} +\begin{abstract} +Let $A$ be the infinite lower-triangular matrix with entries $A(n,k)=1/(3n+1)$ for $k\le n\le 2k$ and $A(n,k)=0$ otherwise, and let $a(n)$ be the $n$-th row sum of $A^{-1}$ (OEIS A127752). +We prove Paul Barry's 2007 conjecture that $a(n)\bmod 2$ is the first Feigenbaum symbolic (period-doubling) sequence A035263, the fixed point of the morphism $0\mapsto11$, $1\mapsto10$; precisely, $a(n)\bmod 2=\mathrm{A035263}(n+1)$ for all $n\ge0$. +The proof derives $a(0)=1$, $a(2m+2)=3$ and $a(2m+1)=a(m)+3$ from the system $A\,a=\mathbf 1$ and compares this with the self-similarity of the morphic word. +To our knowledge this is a new result: the conjecture is still marked as open in the OEIS, where it had been checked for the first 2048 terms. +The proof is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definitions are proved to agree with the matrix-inverse definition and are checked by the kernel against the listed terms of both sequences. +\end{abstract} +\maketitle + +\section{Introduction} + +Let $A=(A(n,k))_{n,k\ge0}$ be the number triangle +\[ + A(n,k)=\begin{cases}\dfrac1{3n+1}, & k\le n\le 2k,\\[4pt] 0, & \text{otherwise.}\end{cases} +\] +Row $n$ of $A$ has the entry $1/(3n+1)$ in the columns $\lceil n/2\rceil\le k\le n$. Since $A$ is lower triangular with nonzero diagonal entries $A(n,n)=1/(3n+1)$, it has a unique lower-triangular inverse $A^{-1}$, and its leading $N\times N$ block is the inverse of the leading $N\times N$ block of $A$. The inverse is the triangle A127751 \cite{A127751}, and its row sums +\[ + a(n)=\sum_{k=0}^{n}A^{-1}(n,k)\qquad(n\ge0) +\] +form the sequence A127752 \cite{A127752}: $1, 4, 3, 7, 3, 6, 3, 10, 3, 6, 3, 9, 3, 6, 3, 13,\dots$ +Both entries were submitted by Paul Barry on January~28, 2007. The entry A127752 contains the comment +\begin{quote} +{\small\texttt{a(n) mod 2 is first Feigenbaum symbolic sequence A035263 (conjecture).}} +\end{quote} +Here A035263 \cite{A035263} is the trajectory of $1$ under the morphism $0\mapsto11$, $1\mapsto10$, also known as the period-doubling sequence: $1,0,1,1,1,0,1,0,1,0,1,1,\dots$ (offset $1$). +We prove this conjecture (Theorem~\ref{thm:main}). + +\subsection*{Prior work and status} +\begin{itemize} +\item In the current revision of A127752 (\#11, February~11, 2021) the statement is still labelled ``(conjecture)''. On September~29, 2018, Antti Karttunen added the remark that ``the conjecture is true at least up to 2048 first terms'' (noting that the indexing of A127752 starts at $0$), a b-file of $a(n)$ for $n\le2048$, and a PARI program; Jean-Fran\c{c}ois Alcover added a Mathematica program on February~11, 2021. Both programs invert a fixed finite truncation of $A$. The entry has no formula section \cite{A127752}. +\item The triangle entry A127751 (revision \#5, September~29, 2018) repeats the conjecture: ``Row sums A127752 mod 2 are conjectured to be first Feigenbaum symbolic sequence A035263'' \cite{A127751}. +\item The companion entries A127749 and A127750 (Barry, same day) concern the triangle with $1/(2n+1)$ in place of $1/(3n+1)$ and conjecture that the row sums of its inverse are, modulo~$2$, the Fredholm--Rueppel sequence A036987 \cite{A127749,A127750}; R.~J. Mathar noted in 2021 that this is equivalent to the row-sum conjecture in A111967 \cite{A127749,A111967}. These are still labelled as conjectures; see Remark~\ref{rem:companion}. +\item S.~Fried \cite{Fried} proved conjectures of Barry about the triangle A127793, the inverse of the band triangle with the same support $k\le n\le2k$ but entries $1/\lfloor(n+2)/2\rfloor$, and its connection with the largest odd divisor A000265. That paper does not treat A127752. +\end{itemize} +The math0 referees searched the OEIS (including all entries that cite A127751 or A127752), arXiv, the web and recent papers proving OEIS conjectures, and found no earlier proof or counterexample; the statement is not in the formal-conjectures repository \cite{FC}. We therefore classify Theorem~\ref{thm:main} as a \emph{new result}. The proof is short and elementary; the only point is to compare consecutive equations of the triangular system $A\,a=\mathbf1$. + +\section{Statement}\label{sec:statement} + +Write $\pd(n)=\mathrm{A035263}(n)$ for $n\ge1$. Let $\sigma$ be the morphism of the free monoid on $\{0,1\}$ with $\sigma(0)=11$ and $\sigma(1)=10$, and let $w_k=\sigma^k(1)$, so $w_0=1$, $w_1=10$, $w_2=1011$, $w_3=10111010$. Each $w_k$ has length $2^k$ and is a prefix of $w_{k+1}$ (by induction, since $w_0$ is a prefix of $w_1$ and $\sigma$ preserves prefixes), so the $w_k$ converge to an infinite word $\pd(1)\pd(2)\pd(3)\cdots$. + +\begin{theorem}[Barry's conjecture]\label{thm:main} +For every $n\ge0$, +\[ + a(n)\equiv \pd(n+1)\pmod 2 . +\] +Equivalently, $a(n)$ is odd if and only if $\pd(n+1)=1$. +\end{theorem} + +\subsection*{The conjecture and its indexing} +The comment quoted in the introduction is unsigned; as is usual in the OEIS, we attribute it to the author of the entry, Paul Barry (January~28, 2007). A127752 has offset $0$ and A035263 has offset $1$, and the conjecture compares the two sequences term by term from their first terms: $a(0),a(1),a(2),\dots$ modulo $2$ is $1,0,1,1,1,0,\dots=\pd(1),\pd(2),\pd(3),\dots$. This is the reading of Karttunen's remark in the entry (``please note the different indexing, here 0-based''); the other alignment, $a(n)\equiv\pd(n)$, fails already at $n=1$, where $a(1)=4$ and $\pd(1)=1$. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A127752.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{9f79e91f\ldots 0f38ec}) before any proof attempt. Its definitions and the statement read as follows (verbatim and in order; the copyright header, the import, comments, docstrings and all theorems are omitted): +\begin{lstlisting} +namespace Math0.Statements.A127752 +open Finset Matrix +def A (n k : ℕ) : ℚ := if k ≤ n ∧ n ≤ 2 * k then 1 / (3 * n + 1 : ℚ) else 0 +def next (l : List ℤ) : ℤ := + 3 * l.length + 1 - ∑ j ∈ range l.length, if l.length ≤ 2 * j then l.getD j 0 else 0 +def vals : ℕ → List ℤ + | 0 => [] + | n + 1 => vals n ++ [next (vals n)] +def a (n : ℕ) : ℤ := (vals (n + 1)).getD n 0 +def Amat (N : ℕ) : Matrix (Fin N) (Fin N) ℚ := Matrix.of fun i j => A i j +def sigma (x : ℕ) : List ℕ := if x = 0 then [1, 1] else [1, 0] +def word : ℕ → List ℕ + | 0 => [1] + | k + 1 => (word k).flatMap sigma +def A035263 (n : ℕ) : ℕ := (word n).getD (n - 1) 0 +def statement : Prop := ∀ n : ℕ, a n % 2 = (A035263 (n + 1) : ℤ) +end Math0.Statements.A127752 +\end{lstlisting} + +\emph{The triangle and its row sums.} \texttt{A n k} is $A(n,k)$, a rational number, and \texttt{Amat N} is the leading $N\times N$ block $A_N$ of $A$. The sequence $a$ is not defined through a matrix inverse but by forward substitution in $A\,s=\mathbf1$: row $n$ of this system reads $\frac1{3n+1}\sum_{\lceil n/2\rceil\le j\le n}s(j)=1$, so +\begin{equation}\label{eq:rec} + s(n)=3n+1-\sum_{\substack{j n. Then T(n,k) is an integer for all 0 ≤ k ≤ n. This was conjectured by Paul Barry in OEIS A127755. + +## Assessment + +The conjecture follows in a few lines. Multiplying row n by n! turns A into the 0/1 lower-unitriangular matrix A101688. Its inverse (A111967) is therefore an integer matrix, and A^{-1} is that inverse with column k scaled by k!. R. J. Mathar already gave the same diagonal-scaling argument for the sibling entry A127749, and the Lean proof is just a strong induction on the forward-substitution recursion. No new idea was needed, so the result is routine, even though it had stayed formally open since 2007. + +*Follows from:* Factor A = D^{-1}·B, where D = diag(n!) and B is the 0/1 unitriangular triangle A101688. Then A^{-1} = B^{-1}·D, so T(n,k) = k!·A111967(n,k). A111967 is the inverse of B (cross-referenced), and the inverse of a unitriangular integer matrix has integer entries. The forward-substitution recursion shows the same thing directly, because n!·A(n,j) is 0 or 1. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A127755](https://oeis.org/A127755) as [`Math0.Statements.A127755.statement`](../../lean/Math0/Statements/OEIS/A127755.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A127755.lean`](../../lean/Math0/Frontier/OEIS/A127755.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C A127755 It is conjectured that this is an integer triangle. Row sums are A127756. (_Paul Barry_, Jan 28 2007) + +Referees: I found no prior proof or counterexample for A127755. Sources checked: +- Local mirror and current GitHub oeisdata entry for A127755 (revision #5, Sep 29 2018), still marked conjectured. +- Related OEIS entries: A127756; A101688 (the 0/1 triangle [k<=n<=2k]); A111967 (its inverse, by Barry, 2005), with A127755(n,k) = k!·A111967(n,k). +- A127749: R. J. Mathar (Apr 21 2021) gives T(n,k) = (2k+1)·A111967(n,k), the same diagonal-scaling argument applied to the 1/(2n+1) sibling. +- A127793: FUNG Cheok Yin (Sep 2022) gives a formula implying integrality for the 1/floor((n+2)/2) sibling. Sela Fried, "On the inverse of a certain triangular matrix and its connection to the largest odd divisor", Notes Num. Theor. Disc. Math. 32(2) (2026) 255-262, doi:10.7546/nntdm.2026.32.2.255-262, proves it; the paper does not mention A127755. +- Sibling integrality conjectures that are also still open in OEIS: A127710, A127711, A127771. +- Web searches (OEIS/SeqFan/arXiv/MathOverflow/MSE-style queries) found nothing more. + +## Citation + +```bibtex +@misc{math0:oeis-a127755, + author = {{math0}}, + title = {{The inverse of the triangle 1/n! [k ≤ n ≤ 2k] is an integer triangle}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a127755}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a127767/README.md b/results/oeis-a127767/README.md new file mode 100644 index 0000000..d6a356a --- /dev/null +++ b/results/oeis-a127767/README.md @@ -0,0 +1,51 @@ +# The inverse of the 1/Catalan band triangle (A127767) has integer entries + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A127767 +**Date:** 2026-10-24 + +## Result + +Let C(n) be the Catalan numbers. Let A be the infinite lower-triangular matrix with A(n,k) = 1/C(n) if k ≤ n ≤ 2k and A(n,k) = 0 otherwise. Let T be its inverse, which is also lower triangular. Then every entry T(n,k) with 0 ≤ k ≤ n is an integer. In the frozen statement, T is defined by forward substitution: T(n,k) = C(n)·([n=k] − Σ_{j n. + +## Assessment + +The conjecture follows from one observation. Every nonzero entry in row n of A equals 1/C(n), so A is the 0/1 band matrix [k<=n<=2k] with each row scaled by 1/C(n). That band matrix is lower unitriangular, so its inverse has integer entries. Inverting A then just multiplies column k of that integer inverse by C(k). This is standard linear algebra that fits in a few lines. The method was already used for the sibling triangle A127749, and the manuscript itself calls the result an elementary observation. The integrality conjecture was meant literally, and the proof settles it as stated. + +*Follows from:* The factorization A = diag(1/C_n) * M, where M(n,k) = [k <= n <= 2k] is the lower unitriangular 0/1 triangle A101688. Its inverse is the integer triangle A111967, so T = M^{-1} * diag(C_k), that is, T(n,k) = C_k * A111967(n,k). The same factorization appears in R. J. Mathar's 2021 formula for the sibling triangle A127749. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A127767](https://oeis.org/A127767) as [`Math0.Statements.A127767.statement`](../../lean/Math0/Statements/OEIS/A127767.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A127767.lean`](../../lean/Math0/Frontier/OEIS/A127767.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C It is conjectured that all elements of the triangle are integers. (Paul Barry, Jan 28 2007) + +Referees: - OEIS A127767 (P. Barry, Jan 28 2007). Local mirror and current GitHub oeisdata, #11 Sep 30 2018: the conjecture is still marked as conjectured, with no proof or formula. Cross-references: A127768, A127769, A127770, A000108. +- OEIS A101688: the 0/1 triangle [k<=n<=2k]. +- OEIS A111967: inverse of A101688. It is an integer triangle because A101688 is unitriangular. T(n,k) = A000108(k)·A111967(n,k) is the identity that settles A127767. +- OEIS A127749, R. J. Mathar, Apr 21 2021: T(n,k) = (2k+1)·A111967(n,k). This is the same factorisation applied to a sibling triangle. It is the closest prior use of the method, but it does not resolve A127767. +- OEIS A127793: the integrality conjecture for the 1/floor((n+2)/2) sibling was proved by FUNG Cheok Yin (Sep 2022) and by S. Fried, "On the inverse of a certain triangular matrix and its connection to the largest odd divisor", Notes Num. Theor. Disc. Math. 32(2) (2026) 255-262, doi:10.7546/nntdm.2026.32.2.255-262 (https://nntdm.net/papers/nntdm-32/NNTDM-32-2-255-262.pdf). This covers A127793 only; there is no general remark that would cover A127767. +- Siblings with the same still-open integrality conjecture, all settled by the same argument: A127710, A127711, A127755, A127771. +- No relevant hits on arXiv, MathOverflow/MSE or SeqFan for A127767. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a127767, + author = {{math0}}, + title = {{The inverse of the 1/Catalan band triangle (A127767) has integer entries}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a127767}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a127767/paper.pdf b/results/oeis-a127767/paper.pdf new file mode 100644 index 0000000..75b4061 Binary files /dev/null and b/results/oeis-a127767/paper.pdf differ diff --git a/results/oeis-a127767/paper.tex b/results/oeis-a127767/paper.tex new file mode 100644 index 0000000..4943937 --- /dev/null +++ b/results/oeis-a127767/paper.tex @@ -0,0 +1,328 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\small, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +\allowdisplaybreaks +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\def\UrlFont{\normalfont\ttfamily}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\ib}[1]{[\,#1\,]} +\newcommand{\diag}{\operatorname{diag}} + +% Unicode inside listings is mapped via `literate` (listings splits multi-byte characters). +\lstset{keepspaces=true, literate={ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {ℤ}{{$\mathbb{Z}$}}1 + {→}{{$\to$}}1 {↔}{{$\leftrightarrow$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {∈}{{$\in$}}1 + {∑}{{$\sum$}}1 {∧}{{$\wedge$}}1 {≤}{{$\le$}}1 {⁻¹}{{$^{-1}$}}2} + +\title[Integrality of the inverse Catalan band triangle]{The inverse of the triangle $\ib{k\le n\le 2k}/C_n$ has integer entries: a proof of Barry's conjecture in OEIS A127767} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +Let $C_n$ be the Catalan numbers and let $A$ be the infinite lower-triangular matrix with $A(n,k)=1/C_n$ if $k\le n\le 2k$ and $A(n,k)=0$ otherwise. We prove that every entry $T(n,k)$, $0\le k\le n$, of the inverse matrix $T=A^{-1}$ is an integer; the proof shows that it is in fact an integer multiple of $C_k$. This settles a conjecture that Paul Barry recorded in OEIS entry A127767 in 2007 and that is still listed there as open. We classify the result as new, but the proof is elementary: it amounts to the factorization $A=\diag(1/C_n)\,M$ with $M$ a unitriangular $0/1$ matrix, the same idea as a 2021 formula of R.~J.~Mathar for a sibling triangle. The theorem is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry; in that statement $T$ is defined by forward substitution, proved to invert every finite truncation of $A$, and checked by the kernel against all $66$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +Let $C_n=\frac1{n+1}\binom{2n}{n}$ be the $n$-th Catalan number (A000108 \cite{A000108}). In January 2007 Paul Barry added to the OEIS a family of number triangles, each the inverse of a lower-triangular matrix supported on the band $k\le n\le 2k$ whose nonzero entries in row $n$ all equal $1/d(n)$ for some positive arithmetic function $d$: for example $d(n)=n+1$ (A127710 \cite{A127710}), the Fibonacci number $F_{n+1}$ (A127711 \cite{A127711}), $2n+1$ (A127749 \cite{A127749}), $n!$ (A127755 \cite{A127755}), $C_n$ (A127767 \cite{A127767}), Euler's totient $\varphi(n+1)$ (A127771 \cite{A127771}) and $\lfloor (n+2)/2\rfloor$ (A127793 \cite{A127793}). For most of these he recorded the conjecture that the inverse has integer entries. This note concerns the Catalan case, A127767. Its entry is named +\begin{quote}\raggedright +\texttt{Inverse of number triangle A(n,k) = 1/C(n) if k <= n <= 2k, 0 otherwise, where C(n) = A000108(n).} +\end{quote} +and its comment line reads, verbatim, +\begin{quote}\raggedright +\texttt{It is conjectured that all elements of the triangle are integers.} +\end{quote} +The entry was submitted by Paul Barry on January~28, 2007. In its current revision (\#11, September~30, 2018) the statement is still labelled a conjecture. The entry has no formula section; besides the data, the examples and cross-references it contains only a PARI program (Michel Marcus, 2018) that computes the rows by inverting a finite matrix. We prove the conjecture (Theorem~\ref{thm:main}), with a Lean proof of the full statement. + +\subsection*{Prior work and status} +The math0 literature review found the following related work and no prior resolution of the conjecture in A127767. +\begin{itemize} +\item The $0/1$ triangle $M(n,k)=\ib{k\le n\le 2k}$ is A101688 \cite{A101688}, read as a triangle, and its inverse is A111967 \cite{A111967} (P.~Barry, 2005). Since $M$ is lower unitriangular with integer entries, A111967 is an integer triangle. The identity $T(n,k)=C_k\cdot\mathrm{A111967}(n,k)$, which we prove as Corollary~\ref{cor:A111967}, settles A127767; it does not appear in either entry. +\item In A127749 (the case $d(n)=2n+1$), R.~J.~Mathar added on April~21, 2021 the formula $T(n,k)=(2k+1)\cdot\mathrm{A111967}(n,k)$ \cite{A127749}. This is the same factorization applied to a sibling triangle, and it is the closest prior use of the method. A127749 itself carries no integrality conjecture, and the factorization was not recorded for A127767 or stated as a general principle. +\item For A127793 (the case $d(n)=\lfloor(n+2)/2\rfloor$) the integrality conjecture was proved by FUNG Cheok Yin (comment in the entry, September 2022) and by S.~Fried \cite{Fried}, who also gave an explicit formula for the entries. Fried's paper treats only A127793 and does not state a general factorization. +\item The conjectures in A127710, A127711, A127755 and A127771 are, like A127767, still listed as open in the OEIS; the argument of this note settles them as well (Remark~\ref{rem:siblings}). A search of arXiv, MathOverflow, Mathematics Stack Exchange and the SeqFan list found nothing on A127767. +\end{itemize} +We therefore classify Theorem~\ref{thm:main} as a \emph{new result}, with the caveat that it is an elementary observation rather than a substantive theorem: once $A$ is written as $\diag(1/C_n)\,M$, integrality is a one-line consequence. + +\section{Statement}\label{sec:statement} + +Infinite lower-triangular matrices over $\Q$, indexed by $\N\times\N$, form a ring: entries of a product are finite sums. A lower-triangular matrix with nonzero diagonal entries has a unique two-sided inverse in this ring, and the inverse is again lower triangular. Moreover, the $N\times N$ leading truncation of a product of lower-triangular matrices is the product of the truncations, so $T$ is the inverse of $A$ if and only if, for every $N$, the truncation $T_N$ is the inverse of the truncation $A_N$. + +\begin{theorem}\label{thm:main} +Let $A$ be the lower-triangular matrix with entries +\[ + A(n,k)=\begin{cases}1/C_n & \text{if } k\le n\le 2k,\\ 0 & \text{otherwise,}\end{cases}\qquad n,k\ge0, +\] +and let $T=A^{-1}$. Then $T(n,k)\in\Z$ for all $0\le k\le n$. +\end{theorem} + +Since $T$ is lower triangular, $T(n,k)=0$ for $k>n$, so every entry of $T$ is an integer. The proof gives more: $T(n,k)\in C_k\Z$ for all $n,k$ (Proposition~\ref{prop:mult}). + +The rows $n=0,\dots,4$ of $T$ are $(1)$, $(0,1)$, $(0,-1,2)$, $(0,1,-2,5)$, $(0,0,0,-5,14)$. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A127767.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{e61b7ad2\ldots 9dce}) before any proof attempt. Its definitions and the statement read as follows. The listing is verbatim, except that we omit the import, comments, blank lines, all theorems, and the definitions \decl{rowOf} and \decl{a} (reading the triangle by rows) and \decl{Amat}, \decl{Tmat} (the $N\times N$ truncations of \texttt{A} and \texttt{T}, as matrices \texttt{Matrix (Fin N) (Fin N) ℚ}). +\begin{lstlisting} +namespace Math0.Statements.A127767 +open Finset +def cat : ℕ → ℕ + | 0 => 1 + | n + 1 => cat n * (2 * (2 * n + 1)) / (n + 2) +def A (n k : ℕ) : ℚ := if k ≤ n ∧ n ≤ 2 * k then 1 / (cat n : ℚ) else 0 +def nextRow (rs : List (List ℚ)) : List ℚ := + (List.range (rs.length + 1)).map fun k => + (cat rs.length : ℚ) * ((if rs.length = k then 1 else 0) - + ∑ j ∈ range rs.length, A rs.length j * (rs.getD j []).getD k 0) +def rows : ℕ → List (List ℚ) + | 0 => [] + | n + 1 => rows n ++ [nextRow (rows n)] +def T (n k : ℕ) : ℚ := ((rows (n + 1)).getD n []).getD k 0 +def statement : Prop := ∀ n k : ℕ, k ≤ n → ∃ z : ℤ, T n k = z +end Math0.Statements.A127767 +\end{lstlisting} + +\emph{How the definitions encode the entry.} The function \texttt{cat} computes $C_n$ by the product recursion $C_{n+1}=C_n\cdot 2(2n+1)/(n+2)$, in which the natural-number division is exact; the file proves \decl{cat_eq_catalan}: \texttt{cat n = catalan n} (Mathlib's Catalan numbers) and \decl{cat_pos}: \texttt{0 < cat n}, so \texttt{1 / (cat n : ℚ)} never divides by zero. The rational number \texttt{A n k} is $A(n,k)$, exactly as in the name of the entry. The rows of $T$ are built one at a time: if \texttt{rs} holds rows $0,\dots,n-1$ (so \texttt{rs.length} $=n$), then \texttt{nextRow rs} is the list of the numbers +\begin{equation}\label{eq:fs} + T(n,k)=C_n\Bigl(\ib{n=k}-\sum_{jj$. This is forward substitution for the equations $\sum_{j\le n}A(n,j)T(j,k)=\ib{n=k}$, using $A(n,n)=1/C_n$. The values are rationals; integrality is not built into the types. That \texttt{T} is the inverse of \texttt{A} is proved, not assumed. The file proves the following, with proofs omitted here: +\begin{lstlisting} +theorem T_spec (n k : ℕ) : + T n k = if k ≤ n then + (cat n : ℚ) * ((if n = k then 1 else 0) - ∑ j ∈ range n, A n j * T j k) else 0 +theorem inv_Amat (N : ℕ) : (Amat N)⁻¹ = Tmat N +theorem statement_iff_matrix : + statement ↔ ∀ (N : ℕ) (i j : Fin N), ∃ z : ℤ, (Amat N)⁻¹ i j = z +\end{lstlisting} +Here \decl{T_spec} is \eqref{eq:fs} together with $T(n,k)=0$ for $k>n$, and \texttt{(Amat N)⁻¹} is Mathlib's matrix inverse. The proof of \decl{inv_Amat} shows $\sum_{xn$ vanish, and the term $x=n$ is $T(n,k)/C_n$, which \decl{T_spec} identifies. Hence $A_NT_N=1$, and a right inverse of a square matrix is its inverse (\texttt{Matrix.inv\_eq\_right\_inv}). By the remark at the start of this section, \decl{statement} is exactly the assertion of Theorem~\ref{thm:main}; the entries with $k>n$, which are not part of the statement, are $0$ (\decl{T_eq_zero_of_lt}). By \decl{statement_iff_matrix} it is also equivalent to the integrality of every finite inverse $A_N^{-1}$. + +\emph{Data checks.} The file defines the triangle read by rows, \texttt{a m = T n k} for $m=n(n+1)/2+k$, $0\le k\le n$, with offset $0$ as in the entry. Two theorems proved by \texttt{decide +kernel} check that \texttt{a} reproduces all $66$ terms of the OEIS data (\decl{a_data}) and that \texttt{rows 11} is the list of rows $0,\dots,10$ (\decl{rows_data}). Here the Lean kernel itself evaluates \texttt{cat}, \texttt{A} and \texttt{rows} with exact rational arithmetic and compares the result with the literal list. A script confirmed that this list equals the \texttt{\%S}, \texttt{\%T}, \texttt{\%U} lines of the entry. These checks anchor the definitions to the entry independently of the conjecture; the proof below does not use them. + +\section{Proof}\label{sec:proof} + +The proof follows \path{lean/Math0/Frontier/OEIS/A127767.lean}. It works directly with the recursion \decl{T_spec} and does not use matrices. Write +\[ + M(n,j)=\ib{j\le n\le 2j}\in\{0,1\},\qquad\text{so that}\qquad A(n,j)=M(n,j)/C_n . +\] +From the statement file we use only $C_n>0$ (\decl{cat_pos}) and the following form of \decl{T_spec}: for all $n,k$, +\begin{equation}\label{eq:spec} + T(n,k)=\begin{cases} C_n\bigl(\ib{n=k}-\sum_{jn.\end{cases} +\end{equation} + +\begin{proposition}[\decl{T_eq_int_mul_cat}]\label{prop:mult} +For all $n,k\in\N$ there is $z\in\Z$ with $T(n,k)=z\,C_k$. +\end{proposition} + +\begin{proof} +By strong induction on $n$, for all $k$ simultaneously. Fix $n$ and $k$, and assume that for every $jn$, then $T(n,k)=0=0\cdot C_k$ by \eqref{eq:spec}. + +Let $k\le n$. For $jn$. Multiplying \eqref{eq:spec} out, using $C_nA(n,j)=M(n,j)$ and $C_n\ib{n=k}=C_k\ib{n=k}$, and dividing by $C_k$, we get for $k\le n$ +\[ + U(n,k)=\ib{n=k}-\sum_{j0$ (\decl{A129454_pos}), and cancelling it in \eqref{eq:main} gives $T(n,k)=\binom nkM^6$, which is~(2). Since $\binom nk>0$ for $k\le n$, also $T(n,k)/\binom nk=M^6$, which is~(3). In Lean, the same cancellations show that the truncating divisions in \decl{T} and in the third conjunct are exact, and $M$ is the witness for \texttt{m}. +\end{proof} + +\begin{remark}[$p$-adic form; not formalized in this form]\label{rem:padic} +Collecting in Lemma~\ref{lem:products} the factors $L(p^t)=p$ for a fixed prime $p$ gives $v_p(G(m))=\sum_{t\ge1}\fl{m/p^t}^3$, which is Ma's formula for $q=3$; Proposition~\ref{prop:main} likewise gives $v_p(\binom nk)=\sum_{t\ge1,\,p^t\le n}c_{p^t}$, the number of carries when $k$ and $n-k$ are added in base $p$ (Kummer's theorem), and $v_p(M)=\sum_{t\ge1,\,p^t\le n}e_{p^t}$. In terms of A129454 the first formula reads $v_p(\mathrm{A129454}(n))=\sum_{t\ge1}\fl{(n-1)/p^t}^3$ for $n\ge1$. The conjectured factorization in A129454 \cite{A129454} has $\fl{n/p^t}$ in place of $\fl{(n-1)/p^t}$; read with the entry's offset $0$, it describes $\mathrm{A129454}(n+1)$ rather than $\mathrm{A129454}(n)$. For example it predicts $2^{8+1}\cdot3=1536$ for $n=4$, while $\mathrm{A129454}(4)=6$ and $\mathrm{A129454}(5)=1536$. This shift does not affect the formal statement, which uses the defining product of A129454 directly. +\end{remark} + +\begin{remark}[the square case; not formalized]\label{rem:square} +The same argument with $\fl{m/d}^2$ in place of $\fl{m/d}^3$, and with the identity $(A+B+c)^2=A^2+B^2+c+2\bigl(AB+c(A+B)\bigr)$ for $c\in\{0,1\}$, gives $G_2(n)=G_2(k)\,G_2(n-k)\binom nk\bigl(\prod_{d=1}^nL(d)^{A_dB_d+c_d(A_d+B_d)}\bigr)^2$. This proves the analogous statement of Bala in A129453 \cite{A129453}: the entries are integers, divisible by $\binom nk$, with perfect-square quotients. We checked this numerically for $n<40$ but did not formalize it, and we make no claim about its novelty. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is the file \path{lean/Math0/Frontier/OEIS/A129455.lean} in the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A129455.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A129455.result}, of type \decl{Math0.Statements.A129455.statement}. All auxiliary declarations are \texttt{private}: the definition \decl{L} and the lemmas \decl{L_pos}, \decl{log_L}, \decl{prod_divisors_L}, \decl{decomp}, \decl{count_mult}, \decl{factorial_eq}, \decl{G_eq}, \decl{two_dvd}, \decl{cube_identity}, \decl{main_identity} and \decl{A129454_pos}, which correspond to the steps of Section~\ref{sec:proof}. The statements of the main identity and of the theorem, and the audit command at the end of the file, read verbatim (proofs omitted): +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +private lemma main_identity (n k : ℕ) (hk : k ≤ n) : + ∃ M : ℕ, A129454 (n + 1) = A129454 (n - k + 1) * A129454 (k + 1) * (n.choose k * M ^ 6) := by +theorem result : statement := by +#math0_settles Math0.Frontier.A129455.result Math0.Statements.A129455.statement +\end{lstlisting} +The proof file uses no \texttt{decide}, \texttt{native\_decide} or \texttt{set\_option}; it is a proof for all $n$ and $k$, not a finite computation. Besides the Mathlib lemmas named in Section~\ref{sec:proof}, the main ones it uses are \decl{Real.log_injOn_pos}, \decl{Nat.choose_mul_factorial_mul_factorial} ($\binom nk\,k!\,(n-k)!=n!$), and \decl{Finset.prod_comm} and \decl{Finset.prod_pow_eq_pow_sum} for rearranging the finite products. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which rules out \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} introduced by \texttt{native\_decide}, and custom axioms; and (3) the type of \decl{result} is syntactically \decl{statement} or its negation, up to metadata annotations, with no unfolding. Running \texttt{lake env lean Math0/Frontier/OEIS/A129455.lean} in the directory \path{lean} prints +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A129455.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A129455.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A129455.result' proves 'Math0.Statements.A129455.statement' +\end{lstlisting} +and takes about $16$ seconds on our machine, most of it spent loading Mathlib. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. To reproduce, run \path{scripts/verify.sh} from the repository root. It fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of statement checks that passed. + +{\small +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Ma} +W.~Ma, \emph{Generalized factorials characterized by Dirichlet convolution}, arXiv:2509.13354, 2025. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Mi} +A.~B. Mingarelli, \emph{Abstract factorials}, Notes on Number Theory and Discrete Mathematics \textbf{19} (2013), no.~4, 43--76; arXiv:0705.4299. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A092287} +OEIS Foundation Inc., Entry A092287 in \emph{The On-Line Encyclopedia of Integer Sequences}, \url{https://oeis.org/A092287}; entry by N.~J.~A. Sloane after L.~Quet (2004), with comments by P.~Bala (2007), C.~R. Greathouse~IV and D.~Forgues (2013); revision \#71, Sep.~22, 2025. + +\bibitem{A129453} +OEIS Foundation Inc., Entry A129453 in \emph{The On-Line Encyclopedia of Integer Sequences}, \url{https://oeis.org/A129453}; entry by P.~Bala (Apr.~16, 2007); revision \#9, Feb.~7, 2024. + +\bibitem{A129454} +OEIS Foundation Inc., Entry A129454 in \emph{The On-Line Encyclopedia of Integer Sequences}, \url{https://oeis.org/A129454}; entry by P.~Bala (Apr.~16, 2007); revision \#8, Feb.~7, 2024. + +\bibitem{A129455} +OEIS Foundation Inc., Entry A129455 in \emph{The On-Line Encyclopedia of Integer Sequences}, \url{https://oeis.org/A129455}; entry by P.~Bala (Apr.~16, 2007); revision \#9, Feb.~8, 2024. + +\bibitem{A224479} +OEIS Foundation Inc., Entry A224479 in \emph{The On-Line Encyclopedia of Integer Sequences}, \url{https://oeis.org/A224479}; entry by P.~Luschny (Apr.~7, 2013). + +\bibitem{A224497} +OEIS Foundation Inc., Entry A224497 in \emph{The On-Line Encyclopedia of Integer Sequences}, \url{https://oeis.org/A224497}; entry by P.~Luschny (Apr.~8, 2013). + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a132616/README.md b/results/oeis-a132616/README.md new file mode 100644 index 0000000..73a64ac --- /dev/null +++ b/results/oeis-a132616/README.md @@ -0,0 +1,39 @@ +# Irwin's nested sums give column 0 of the triangle A132615 (A132616) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A132616 +**Date:** 2026-10-29 + +## Result + +Let T be the infinite lower-triangular matrix with T(0,0) = 1 in which, for every n ≥ 0, row n+1 is row n of T^(2n-1) followed by a 1. For n = 0 the formal exponent is 0, which gives the same row [1, 1]. Let a(n) = T(n,0) (OEIS A132616). Define nest 0 c = 1 and nest (m+1) c = Sum_{i=1..c+2m} nest m i. Then nest(n-1, 1) is Irwin's nested sum Sum_{i_1=1..1+2(n-2)} Sum_{i_2=1..i_1+2(n-3)} ... Sum_{i_(n-1)=1..i_(n-2)} 1. Claim: for every n ≥ 2, a(n) = nest(n-1, 1). + +## Assessment + +The proof strengthens the claim to every power of the triangle: the (n,k) entry of T^p is Irwin's nested sum with outer bound p. Somos's two-argument program a(n,k) in the entry and Hanna's partial-sums "alternate generating method" in A132615 already point to this generalization. The proof then checks the semigroup law M_p M_q = M_{p+q} by a short double induction: when p goes up by one, row n+1 changes by row n of M at a shifted exponent, and the induction hypothesis matches the two sides. It ends with uniqueness of T, so M_1 = T. This is a standard strengthen-the-induction argument of about half a page, which a competent combinatorialist would find quickly once looking at the powers, a natural move for a triangle defined by its own powers. So it is routine, even though no proof had been published before. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A132616](https://oeis.org/A132616) as [`Math0.Statements.A132616.statement`](../../lean/Math0/Statements/OEIS/A132616.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A132616.lean`](../../lean/Math0/Frontier/OEIS/A132616.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A132616 From Benedict W. J. Irwin, Nov 29 2016: Conjecture: a(n) is described by a series of nested sums, a(2) = Sum_{i=1..1} 1, a(3) = Sum_{i=1..1+2} Sum_{j=1..i} 1, a(4) = Sum_{i=1..1+4} Sum_{j=1..i+2} Sum_{k=1..j} 1, a(5) = Sum_{i=1..1+6} Sum_{j=1..i+4} Sum_{k=1..j+2} Sum_{l=1..k} 1, and so on. + +Referees: I found no prior proof or counterexample. Checked: the OEIS entries A132616 and A132615 (Hanna 2007, which includes the unproved "alternate generating method", an equivalent partial-sums form of Irwin's sums), A132617, A132618, A132619, A132610, A101479, A101481 (Kirchner 2017 recurrence, different triangle), and A304190, A304191, A304193 (Hanna 2018, conjectural g.f. links). Local mirror versions match current GitHub oeisdata, with no %E line recording a proof. Also checked S. Fried, "Proofs of several conjectures from the OEIS", JIS 28 (2025) Art. 25.4.3 (https://cs.uwaterloo.ca/journals/JIS/VOL28/Fried/fried15.html); S. Fried, "Proofs of ten conjectures from the OEIS", JIS 29 (2026) Art. 26.1.8 (https://cs.uwaterloo.ca/journals/JIS/VOL29/Fried/fried21.html); arXiv:2410.07237; arXiv:2606.09913, which proves Irwin's A007405 conjecture but not this one; and arXiv:2607.24832. None mentions A132616 or A132615. Unrelated constructions: P. Barry, arXiv:1804.06801, and arXiv:1203.4419 (Hanna's triangle A096651). Web searches of MathOverflow, Math StackExchange and SeqFan returned only the OEIS pages. + +## Citation + +```bibtex +@misc{math0:oeis-a132616, + author = {{math0}}, + title = {{Irwin's nested sums give column 0 of the triangle A132615 (A132616)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a132616}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a141412/README.md b/results/oeis-a141412/README.md new file mode 100644 index 0000000..6bb9046 --- /dev/null +++ b/results/oeis-a141412/README.md @@ -0,0 +1,36 @@ +# Denominators of Curtz's polynomials are Farhi's d(n+1,k+1) (A141412, Marcus's conjecture) + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A141412 +**Date:** 2026-10-20 + +## Result + +Let P(0,x)=1 and P(n+1,x) = (-1)^(n+1)/(n+2) + x * sum_{i=0}^{n} (-1)^i/(i+1) * P(n-i,x) over Q, and let c(n,k) = [x^k] P(n,x) (computed by the matching recursion c in the statement file). Let T(n,k) be the reduced denominator of c(n,k), and let d(n,k) be the reduced denominator of |s(n,k)| * k!/n!, where |s(n,k)| is the unsigned Stirling number of the first kind (Nat.stirlingFirst). Then T(n,k) = d(n+1,k+1) for every 0 <= k <= n. The proof gives this for all n and k. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A141412](https://oeis.org/A141412) as [`Math0.Statements.A141412.statement`](../../lean/Math0/Statements/OEIS/A141412.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A141412.lean`](../../lean/Math0/Frontier/OEIS/A141412.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: T(n, k) = d(n+1, k+1), with d(n,k) = denominator(A000254(n, k)*k!/n!) where A000254 are the unsigned Stirling numbers of the 1st kind. See d(n,k) in Farhi link. - _Michel Marcus_, Oct 18 2018" + +Referees: P. Flajolet, X. Gourdon and B. Salvy, "Sur une famille de polynômes issus de l'analyse numérique", Gazette des Mathématiciens 55 (1993) 67-78, also INRIA Research Report RR-1857 (Feb 1993), https://inria.hal.science/inria-00074815/document. Eq. (3) is the generating function log(1+z)/(z(1-x·log(1+z))), and eq. (6) is P_n(x) = (-1)^n/(n+1)! Σ_k s_{n+1,k+1}(k+1)!(-x)^k, which gives the conjecture at once. This paper is cited in A141412's own %D line. The OEIS records the same identity in A140749 %F (Paul Curtz, Jul 17 2008, numerators = those of A048594(n+1,k+1)/(n+1)!) and A141412 %F (G. C. Greubel, Oct 24 2023, "Equals denominators of A048594(n+1,k+1)/(n+1)!"), with A048594's column e.g.f. log(1+x)^k. Farhi's d(n,k) comes from B. Farhi, arXiv:1810.07560 (Funct. Approx. Comment. Math. 61 (2019)). I found no earlier formal proof. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a141412, + author = {{math0}}, + title = {{Denominators of Curtz's polynomials are Farhi's d(n+1,k+1) (A141412, Marcus's conjecture)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a141412}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a141412/paper.pdf b/results/oeis-a141412/paper.pdf new file mode 100644 index 0000000..df34fd6 Binary files /dev/null and b/results/oeis-a141412/paper.pdf differ diff --git a/results/oeis-a141412/paper.tex b/results/oeis-a141412/paper.tex new file mode 100644 index 0000000..91acb96 --- /dev/null +++ b/results/oeis-a141412/paper.tex @@ -0,0 +1,405 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,decreasing_by,rw,apply,ring}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 {→}{{$\to$}}1 + {≤}{{$\le$}}1 {∈}{{$\in$}}1 {∑}{{$\sum$}}1 {⟦}{{$[\![$}}1 {⟧}{{$]\!]$}}1 + {⁄}{{/}}1 {←}{{$\leftarrow$}}1 {·}{{$\cdot$}}1 {≠}{{$\ne$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{⟦}{\ensuremath{[\![}} +\newunicodechar{⟧}{\ensuremath{]\!]}} +\newunicodechar{⁄}{/} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\den}{\operatorname{den}} +\newcommand{\st}[2]{\genfrac{[}{]}{0pt}{}{#1}{#2}} +\newcommand{\fps}{\Q[\![X]\!]} +\newcommand{\coef}[1]{[X^{#1}]} + +\title[Denominators of Curtz's polynomials (OEIS A141412)]{Denominators of Curtz's polynomials are Farhi's $d(n+1,k+1)$: a formal proof of Marcus's conjecture for OEIS A141412} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + +\begin{document} +\begin{abstract} +Curtz's polynomials are defined by $P_0(x)=1$ and $P_n(x)=(-1)^n/(n+1)+x\sum_{i=0}^{n-1}\frac{(-1)^i}{i+1}P_{n-1-i}(x)$ for $n\ge1$, and OEIS A141412 is the triangle $T(n,k)$ of the reduced denominators of the coefficients $[x^k]P_n(x)$. +In 2018 Michel Marcus conjectured in that entry that $T(n,k)=d(n+1,k+1)$, where $d(n,k)$ is the denominator of $\st nk k!/n!$, with $\st nk$ the unsigned Stirling numbers of the first kind; these are the numbers $d_{n,k}$ of Farhi. +We give a machine-checked proof of this conjecture for every entry $0\le k\le n$ of the triangle. The proof goes through the identity $[x^k]P_n(x)=(-1)^{n+k}(k+1)!\st{n+1}{k+1}/(n+1)!$ ($n,k\ge0$), from which the conjecture follows at once and which is checked in Lean as an auxiliary lemma. +This identity is not new: it is equation~(6) of a 1993 paper of Flajolet, Gourdon and Salvy, and it is also recorded in OEIS formulas of Curtz (2008) and Greubel (2023); our contribution is the first formal proof of this known result. +The proof is verified in Lean~4 with Mathlib against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before any proof attempt; its definitions are checked by the kernel against all $78$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +In 1992 Paul Curtz \cite{Cu92} introduced the polynomials $P_n(x)\in\Q[x]$ defined by +\begin{equation}\label{eq:rec} + P_0(x)=1,\qquad P_n(x)=\frac{(-1)^n}{n+1}+x\sum_{i=0}^{n-1}\frac{(-1)^i}{i+1}\,P_{n-1-i}(x)\quad(n\ge1). +\end{equation} +They are the characteristic polynomials of the matrices that occur in Adams' method for the numerical solution of ordinary differential equations \cite{FGS}, and Curtz conjectured in \cite{Cu92} that $P_n$ has no real root for even $n$ and exactly one positive real root for odd $n$. +Flajolet, Gourdon and Salvy \cite{FGS} proved this conjecture in 1993. +Their starting point is the bivariate generating function +\begin{equation}\label{eq:fgs3} + \sum_{n\ge0}P_n(x)z^n=\frac{\log(1+z)}{z}\cdot\frac{1}{1-x\log(1+z)} +\end{equation} +(\cite[eq.~(3)]{FGS}), which they compare with the classical generating function of the Stirling numbers of the first kind \cite{Co74} to obtain (\cite[eq.~(6)]{FGS}) +\begin{equation}\label{eq:fgs6} + P_n(x)=\frac{(-1)^n}{(n+1)!}\sum_{k=0}^{n}\st{n+1}{k+1}(k+1)!\,(-x)^k , +\end{equation} +where $\st nk$ denotes the unsigned Stirling number of the first kind (the number of permutations of $n$ elements with $k$ cycles). + +In the OEIS the polynomials are defined in a comment of A129891 \cite{A129891} (whose terms are the row sums of a related family of polynomials with integer coefficients, not of the $P_n$), and the numerators and denominators of their coefficients $c(n,k)=[x^k]P_n(x)$ form the triangles A140749 \cite{A140749} and A141412 \cite{A141412}; all three entries are due to Curtz. A141412 lists the triangle $T(n,k)=\den c(n,k)$ for $0\le k\le n\le 11$. +On October~18, 2018, Michel Marcus added to A141412 the conjecture that $T(n,k)=d(n+1,k+1)$, where $d(n,k)$ is the denominator of $\st nk k!/n!$, referring to the numbers $d_{n,k}$ of Farhi \cite{Fa19}. +Farhi defines $F_{n,k}=\sum 1/(i_1i_2\cdots i_k)$, the sum over all $(i_1,\dots,i_k)$ of positive integers with $i_1+\dots+i_k=n$, and $d_{n,k}=\den F_{n,k}$; by \cite[Prop.~4.1]{Fa19}, $F_{n,k}=\st nk k!/n!$, so Marcus's $d(n,k)$ is Farhi's $d_{n,k}$. + +\subsection*{Status and prior work} +Formula~\eqref{eq:fgs6} gives $c(n,k)=(-1)^{n+k}\st{n+1}{k+1}(k+1)!/(n+1)!$, and since a sign does not change a reduced denominator, Marcus's conjecture follows immediately from the 1993 paper \cite{FGS}, which the entry A141412 itself cites. +The OEIS also records the numerator and denominator parts of this identity, in terms of the triangle $A048594(n,k)=k!\,s(n,k)$ of signed Stirling numbers, whose $k$-th column has exponential generating function $\log(1+x)^k$ \cite{A048594}: in A140749 Curtz noted on July~17, 2008 that the numerators of the $c(n,k)$ are those of $A048594(n+1,k+1)/(n+1)!$, and in A141412 G.~C. Greubel added on October~24, 2023 the formula ``Equals denominators of $A048594(n+1,k+1)/(n+1)!$'', with Mathematica, Magma and Sage programs that compute the triangle this way. +Nevertheless the entry (revision \#32, November~7, 2023) still labels Marcus's statement a conjecture. + +The mathematics in this paper is therefore known; the result is a \emph{first formal proof of a known result}. +The math0 referees found no earlier formal proof of the statement, and it is not among the OEIS statements of the formal-conjectures repository \cite{FC} (at the commit pinned in Section~\ref{sec:lean}). +Our proof (Section~\ref{sec:proof}) is the column-by-column form of the generating-function argument of \cite{FGS}, with the Stirling generating function derived from a differential equation. + +\section{Statement}\label{sec:statement} + +\begin{definition}\label{def:main} +Let $P_n(x)\in\Q[x]$ be defined by~\eqref{eq:rec} and let $c(n,k)=[x^k]P_n(x)$ for $n,k\ge0$. For $q\in\Q$ let $\den q\ge1$ be the denominator of $q$ in lowest terms. Put +\[ + T(n,k)=\den c(n,k),\qquad d(n,k)=\den\Bigl(\st nk\frac{k!}{n!}\Bigr)\qquad(n,k\ge0), +\] +where $\st nk$ is the unsigned Stirling number of the first kind, given by $\st00=1$, $\st0{k+1}=\st{n+1}0=0$ and +$\st{n+1}{k+1}=n\st n{k+1}+\st nk$. +\end{definition} + +The first rows of $(c(n,k))_{0\le k\le n}$ are +\[ + 1;\quad -\tfrac12,\ 1;\quad \tfrac13,\ -1,\ 1;\quad -\tfrac14,\ \tfrac{11}{12},\ -\tfrac32,\ 1;\quad \tfrac15,\ -\tfrac56,\ \tfrac74,\ -2,\ 1;\quad\dots, +\] +so that $T$ begins $1;\ 2,1;\ 3,1,1;\ 4,12,2,1;\ 5,6,4,1,1$, as in A141412. +The FORMULA section of A141412 \cite{A141412} contains, verbatim: +\begin{quote} +{\small\raggedright\texttt{Conjecture: T(n, k) = d(n+1, k+1), with d(n,k) = denominator(A000254(n, k)*k!/n!) where A000254 are the unsigned Stirling numbers of the 1st kind. See d(n,k) in Farhi link. - \_Michel Marcus\_, Oct 18 2018}\par} +\end{quote} +Strictly, A000254 \cite{A000254} is the one-index sequence $\st{n+1}2$; the comment uses it as a function of two arguments and states that it means the unsigned Stirling numbers of the first kind, so we read $A000254(n,k)$ as $\st nk$ (the triangle A132393 \cite{A132393}). This agrees with Farhi's $d_{n,k}$ and with Greubel's formula and programs in the entry. + +\begin{theorem}[Marcus's conjecture]\label{thm:main} +For all $n\ge0$ and $0\le k\le n$, $T(n,k)=d(n+1,k+1)$. +\end{theorem} + +Theorem~\ref{thm:main} follows from the following identity, which is~\eqref{eq:fgs6}. + +\begin{theorem}[{\cite[eq.~(6)]{FGS}}]\label{thm:coef} +For all $n,k\ge0$, +\[ + c(n,k)=(-1)^{n+k}\,\st{n+1}{k+1}\frac{(k+1)!}{(n+1)!}. +\] +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A141412.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{3f92df65\ldots7b77}) before any proof attempt. Its definitions read, verbatim (header, import, docstrings, blank lines and the three theorems are omitted): +\begin{lstlisting} +namespace Math0.Statements.A141412 +open Polynomial +noncomputable def P : ℕ → ℚ[X] + | 0 => 1 + | n + 1 => C ((-1) ^ (n + 1) / (((n + 1 : ℕ) : ℚ) + 1)) + + X * ∑ i ∈ Finset.range (n + 1), C ((-1) ^ i / ((i : ℚ) + 1)) * P (n - i) +decreasing_by omega +def c : ℕ → ℕ → ℚ + | 0, 0 => 1 + | 0, _ + 1 => 0 + | n + 1, 0 => (-1) ^ (n + 1) / (((n + 1 : ℕ) : ℚ) + 1) + | n + 1, k + 1 => ∑ i ∈ Finset.range (n + 1), (-1) ^ i / ((i : ℚ) + 1) * c (n - i) k +def T (n k : ℕ) : ℕ := (c n k).den +def d (n k : ℕ) : ℕ := + ((Nat.stirlingFirst n k : ℚ) * (Nat.factorial k : ℚ) / (Nat.factorial n : ℚ)).den +def statement : Prop := + ∀ n k : ℕ, k ≤ n → T n k = d (n + 1) (k + 1) +end Math0.Statements.A141412 +\end{lstlisting} +The encoding matches Definition~\ref{def:main} as follows. +The polynomial \decl{P} is~\eqref{eq:rec} written for $n+1$: $P_{n+1}=(-1)^{n+1}/(n+2)+X\sum_{i=0}^{n}\frac{(-1)^i}{i+1}P_{n-i}$. Mathlib polynomials are noncomputable, so the table entries are given by the computable recursion \decl{c}, which is the coefficientwise form of the same recursion; the theorem \decl{coeff_P} in the same file, \texttt{(P n).coeff k = c n k} for all \texttt{n k}, proves by induction on $k$ that the two agree. +\decl{T} takes \decl{Rat.den}, the positive denominator of a rational number in lowest terms, as Maple's \texttt{denom} in the entry's program; the theorem \decl{T_eq_den_coeff}, \texttt{T n k = ((P n).coeff k).den}, restates $T(n,k)=\den([x^k]P_n)$. +\decl{T_data} states that the list of the $78$ values $T(n,k)$, $0\le k\le n\le 11$, read by rows (written \texttt{(List.range 12).flatMap (fun n => (List.range (n + 1)).map (fun k => T n k))}), equals the list of the terms in A141412; it is proved by \texttt{decide +kernel}, i.e.\ by evaluation in the Lean kernel, in about $9$ seconds. +\decl{Nat.stirlingFirst} is Mathlib's unsigned Stirling number of the first kind, defined by exactly the recursion of Definition~\ref{def:main}; in \decl{d} the division is in $\Q$. +The statement quantifies over the whole triangle $0\le k\le n$ and adds no hypotheses. The proof does not use the hypothesis $k\le n$; for $k>n$ both sides equal $1$. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A141412.lean}; the name of the corresponding Lean declaration is given with each step (all of them are \texttt{private}, except \decl{result}). +We work in the ring $\fps$ of formal power series, and write $\coef N g$ for the coefficient of $X^N$ in $g$ and $g'$ for the formal derivative. Define +\begin{align*} + L&=\sum_{j\ge1}\frac{(-1)^{j+1}}{j}X^j &&(\text{the series }\log(1+X);\ \text{\decl{L}}),\\ + F_m&=\sum_{N\ge0}(-1)^{N+m}\st Nm\frac{m!}{N!}X^N &&(m\ge0;\ \text{\decl{F}}),\\ + C_k&=\sum_{n\ge0}c(n,k)X^n &&(k\ge0;\ \text{\decl{Cs}}). +\end{align*} +Thus $\coef0L=0$ and $\coef jL=(-1)^{j+1}/j$ for $j\ge1$. + +\begin{lemma}[\decl{coeff_one_add_X_mul_deriv}]\label{lem:deriv} +For every $g\in\fps$ and $N\ge0$, +$\coef N\bigl((1+X)g'\bigr)=(N+1)\coef{N+1}g+N\coef Ng$. +\end{lemma} + +\begin{proof} +We have $\coef N g'=(N+1)\coef{N+1}g$. For $N\ge1$, $\coef N(Xg')=\coef{N-1}g'=N\coef Ng$; for $N=0$, $\coef0(Xg')=0=N\coef Ng$. Add the two. +\end{proof} + +\begin{lemma}[\decl{one_add_X_mul_deriv_L}]\label{lem:L} +$(1+X)L'=1$. +\end{lemma} + +\begin{proof} +By Lemma~\ref{lem:deriv}, the constant coefficient is $1\cdot\coef1L+0=1$, and for $N\ge1$ the coefficient of $X^N$ is $(N+1)\cdot(-1)^{N+2}/(N+1)+N\cdot(-1)^{N+1}/N=(-1)^N-(-1)^N=0$. +\end{proof} + +\begin{lemma}[\decl{one_add_X_mul_deriv_F}]\label{lem:F} +For every $m\ge0$, $(1+X)F_{m+1}'=(m+1)F_m$. +\end{lemma} + +\begin{proof} +Fix $N\ge0$ and put $\varepsilon=(-1)^{N+m}$. By Lemma~\ref{lem:deriv}, the Stirling recurrence $\st{N+1}{m+1}=N\st N{m+1}+\st Nm$ and $(N+1)!=(N+1)N!$, +\begin{align*} + \coef N\bigl((1+X)F_{m+1}'\bigr) + &=(N+1)\,\varepsilon\st{N+1}{m+1}\frac{(m+1)!}{(N+1)!}+N\,(-\varepsilon)\st N{m+1}\frac{(m+1)!}{N!}\\ + &=\varepsilon\frac{(m+1)!}{N!}\Bigl(N\st N{m+1}+\st Nm-N\st N{m+1}\Bigr) + =(m+1)\,\varepsilon\st Nm\frac{m!}{N!}, +\end{align*} +which is $\coef N\bigl((m+1)F_m\bigr)$, since $(m+1)!=(m+1)m!$. +In Lean: \decl{Nat.stirlingFirst_succ_succ}, \decl{Nat.factorial_succ}, then \texttt{field\_simp} and \texttt{ring}. +\end{proof} + +\begin{lemma}[\decl{F_eq}]\label{lem:Feq} +For every $m\ge0$, $F_m=L^m$. +\end{lemma} + +\begin{proof} +By induction on $m$. Since $\st N0=1$ for $N=0$ and $0$ otherwise, $F_0=1=L^0$. +Assume $F_m=L^m$. By the power rule (\decl{derivative_pow}) and Lemma~\ref{lem:L}, +\[ + (1+X)\bigl(L^{m+1}\bigr)'=(m+1)L^m\cdot(1+X)L'=(m+1)L^m=(m+1)F_m=(1+X)F_{m+1}', +\] +the last step by Lemma~\ref{lem:F}. The constant coefficient of $1+X$ is $1$, so $1+X\neq0$, and $\fps$ is an integral domain; cancelling gives $(L^{m+1})'=F_{m+1}'$. +The constant coefficients agree: $\coef0F_{m+1}=\st0{m+1}\cdot(\dots)=0$ and $\coef0L^{m+1}=(\coef0L)^{m+1}=0$. +Over a ring without additive torsion, such as $\Q$, a power series is determined by its derivative and its constant coefficient (Mathlib's \decl{PowerSeries.derivative.ext}). Hence $F_{m+1}=L^{m+1}$. +\end{proof} + +Lemma~\ref{lem:Feq} is the classical identity $\sum_N s(N,m)z^N/N!=\log(1+z)^m/m!$ for the signed Stirling numbers $s(N,m)=(-1)^{N+m}\st Nm$ \cite{Co74}, which Mathlib does not provide. + +\begin{lemma}[\decl{c_zero}]\label{lem:c0} +For every $n\ge0$, $c(n,0)=(-1)^n/(n+1)$. +\end{lemma} + +\begin{proof} +For $n=0$ both sides are $1$; for $n\ge1$ this is the defining equation of \decl{c}. +\end{proof} + +\begin{lemma}[\decl{Cs_succ}]\label{lem:Cs} +For every $k\ge0$, $C_{k+1}=L\,C_k$. +\end{lemma} + +\begin{proof} +The constant coefficients are $c(0,k+1)=0$ and $\coef0L\cdot c(0,k)=0$. For $n\ge0$, +\[ + \coef{n+1}(L\,C_k)=\sum_{j=0}^{n+1}\coef jL\;c(n+1-j,k)=\sum_{i=0}^{n}\coef{i+1}L\;c(n-i,k)=\sum_{i=0}^{n}\frac{(-1)^i}{i+1}\,c(n-i,k), +\] +where we dropped the term $j=0$ (as $\coef0L=0$) and put $j=i+1$; the right-hand side is the definition of $c(n+1,k+1)$. In Lean the reindexing uses \decl{Finset.Nat.sum_antidiagonal_succ} and \decl{Finset.Nat.sum_antidiagonal_eq_sum_range_succ_mk}. +\end{proof} + +\begin{lemma}[\decl{X_mul_Cs}]\label{lem:XCs} +For every $k\ge0$, $X\,C_k=L^{k+1}$. +\end{lemma} + +\begin{proof} +By induction on $k$. For $k=0$: both sides have constant coefficient $0$, and for $n\ge0$, $\coef{n+1}(XC_0)=c(n,0)=(-1)^n/(n+1)=(-1)^{n+2}/(n+1)=\coef{n+1}L$ by Lemma~\ref{lem:c0}. If $XC_k=L^{k+1}$, then $XC_{k+1}=X\,L\,C_k=L\cdot L^{k+1}=L^{k+2}$ by Lemma~\ref{lem:Cs}. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:coef} \textup{(\texttt{c\_eq})}] +Comparing the coefficients of $X^{n+1}$ in Lemma~\ref{lem:XCs} and using Lemma~\ref{lem:Feq} with $m=k+1$, +\[ + c(n,k)=\coef{n+1}(XC_k)=\coef{n+1}L^{k+1}=\coef{n+1}F_{k+1}=(-1)^{(n+1)+(k+1)}\st{n+1}{k+1}\frac{(k+1)!}{(n+1)!}, +\] +and $(-1)^{(n+1)+(k+1)}=(-1)^{n+k}$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main} \textup{(\texttt{result})}] +Let $n,k\ge0$ and $q=\st{n+1}{k+1}(k+1)!/(n+1)!$. By Theorem~\ref{thm:coef}, $c(n,k)$ is $q$ or $-q$ (\decl{neg_one_pow_eq_or}). Since $\den(-q)=\den q$ (\decl{Rat.neg_den}), $T(n,k)=\den c(n,k)=\den q=d(n+1,k+1)$. The hypothesis $k\le n$ is not used. +\end{proof} + +\begin{remark}[not formalized]\label{rem:farhi} +Lemma~\ref{lem:XCs} also yields Farhi's form of the coefficients directly. Expanding the power, +\[ + c(n,k)=\coef{n+1}L^{k+1}=\sum_{\substack{i_1+\dots+i_{k+1}=n+1\\ i_j\ge1}}\ \prod_{j=1}^{k+1}\frac{(-1)^{i_j+1}}{i_j}=(-1)^{n+k}F_{n+1,k+1}, +\] +with $F_{n,k}$ as in the introduction. Together with $F_{n,k}=\st nk k!/n!$ \cite[Prop.~4.1]{Fa19} this gives Theorem~\ref{thm:coef} again, and it shows that $T(n,k)=d_{n+1,k+1}$ holds with Farhi's original definition of $d_{n,k}$. Summing Lemma~\ref{lem:XCs} over $k$ with weight $x^k$ gives~\eqref{eq:fgs3}. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A141412.lean} in the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A141412.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A141412.result}, of type \decl{Math0.Statements.A141412.statement}. The auxiliary declarations are the private definitions and lemmas named in Section~\ref{sec:proof}. The three series and the end of the file read, verbatim (header, imports, docstrings, blank lines, the \texttt{namespace} and \texttt{open} lines and the other lemmas omitted): +\begin{lstlisting} +private noncomputable def L : ℚ⟦X⟧ := + PowerSeries.mk fun n => if n = 0 then 0 else (-1 : ℚ) ^ (n + 1) / n +private noncomputable def F (m : ℕ) : ℚ⟦X⟧ := + PowerSeries.mk fun N => + (-1 : ℚ) ^ (N + m) * (Nat.stirlingFirst N m : ℚ) * (m.factorial : ℚ) / (N.factorial : ℚ) +private noncomputable def Cs (k : ℕ) : ℚ⟦X⟧ := + PowerSeries.mk fun n => c n k +theorem result : statement := by + intro n k _ + rw [T, d, c_eq] + rcases neg_one_pow_eq_or ℚ (n + 1 + (k + 1)) with h | h + · rw [h, one_mul] + · rw [h, neg_one_mul, Rat.neg_den] +end Math0.Frontier.A141412 +#math0_settles Math0.Frontier.A141412.result Math0.Statements.A141412.statement +\end{lstlisting} +The proof file uses no \texttt{sorry}, \texttt{decide}, \texttt{native\_decide}, custom axioms or \texttt{set\_option}; it does not use \decl{T_data}, \decl{P} or \decl{coeff_P}, since \decl{statement} is expressed through \decl{c} directly. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically \decl{statement} or $\neg$\,\decl{statement}, up to metadata annotations, with no unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A141412.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A141412.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A141412.result' proves 'Math0.Statements.A141412.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib cache, builds all math0 results with \texttt{lake build} (re-running every audit command), and checks that the pinned dependencies are unmodified. The single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A141412.lean} in the directory \path{lean}, once the statement module has been built with \texttt{lake build Math0.Statements.OEIS.A141412}; on our machine the check takes about $25$ seconds, most of it spent loading Mathlib. + +{\small +\begin{thebibliography}{99} + +\bibitem{Co74} +L.~Comtet, \emph{Advanced Combinatorics}, Reidel, Dordrecht, 1974. + +\bibitem{Cu92} +P.~Curtz, Probl\`eme soumis, \emph{Gazette des Math\'ematiciens} \textbf{52} (1992), 44. + +\bibitem{Fa19} +B.~Farhi, \emph{On the derivatives of the integer-valued polynomials}, Funct.\ Approx.\ Comment.\ Math.\ \textbf{61} (2019), no.~2, 227--241; arXiv:1810.07560. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{FGS} +P.~Flajolet, X.~Gourdon, and B.~Salvy, \emph{Sur une famille de polyn\^omes issus de l'analyse num\'erique}, Gazette des Math\'ematiciens \textbf{55} (1993), 67--78. Also INRIA Research Report RR-1857, February 1993, \url{https://inria.hal.science/inria-00074815}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput.\ Sci.\ \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A000254} +The OEIS Foundation Inc., \url{https://oeis.org/A000254}, entry by N.~J.~A. Sloane. + +\bibitem{A048594} +The OEIS Foundation Inc., \url{https://oeis.org/A048594}, entry by O.~Marichev. + +\bibitem{A129891} +The OEIS Foundation Inc., \url{https://oeis.org/A129891}, entry by P.~Curtz (2007). + +\bibitem{A132393} +The OEIS Foundation Inc., \url{https://oeis.org/A132393}, entry by P.~Del\'eham. + +\bibitem{A140749} +The OEIS Foundation Inc., \url{https://oeis.org/A140749}, entry by P.~Curtz (2008). + +\bibitem{A141412} +The OEIS Foundation Inc., \url{https://oeis.org/A141412}, entry by P.~Curtz (2008); conjecture by M.~Marcus (2018); revision \#32, Nov.~7, 2023. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a144637/README.md b/results/oeis-a144637/README.md new file mode 100644 index 0000000..5633f10 --- /dev/null +++ b/results/oeis-a144637/README.md @@ -0,0 +1,41 @@ +# A144637: (1/18) 6^n a(n)/n! is odd iff n = 2^k with k >= 1 + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A144637 +**Date:** 2026-10-26 + +## Result + +Let S(n,k) be A144385: the number of partitions of {1,...,k} into exactly n blocks, each of size 1, 2 or 3. Let T = A144633 be the transpose of the inverse of the upper unitriangular matrix M(i,j) = S(i,j). Let a(n) = T(n,2), and y(n) = (1/18) 6^n a(n) / n!. Then for every n >= 0, y(n) is an odd integer if and only if n = 2^k for some k >= 1. + +## Assessment + +The entry already gives the algebraic equation 36y^3 + 3y^2 + (1+6x)y = x^2 for y(x) = A(6x)/18. Rewritten as y = x^2 - 6xy - 3y^2 - 36y^3 with y(0) = 0, it determines each coefficient from earlier ones using only integer arithmetic, so every coefficient is an integer. Reducing mod 2 gives y = x^2 + y^2 over F_2, and the Frobenius map then forces y = sum over k >= 1 of x^(2^k). The whole argument takes a few lines and uses standard tricks. The Lean proof is long only because it also has to derive the cubic from the matrix-inverse definition. + +*Follows from:* Bala's formula in the entry: (1/18)A(6x) satisfies 36y^3 + 3y^2 + (1+6x)y = x^2 (this follows from Jovovic's e.g.f. B(x)^2/2, where B is the series reversion of x + x^2/2 + x^3/6, as given in A144636). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A144637](https://oeis.org/A144637) as [`Math0.Statements.A144637.statement`](../../lean/Math0/Statements/OEIS/A144637.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A144637.lean`](../../lean/Math0/Frontier/OEIS/A144637.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: (1/18)*6^(n)*a(n)/n! is odd iff n = 2^k for k >= 1. (End) - _Peter Bala_, Feb 19 2026 + +Referees: OEIS A144637 (Bala conjecture, Feb 19 2026; entry revision #25, Mar 14 2026; no proof recorded). The companion conjecture in OEIS A144636 (Bala, Feb 16 2026) is also unresolved. OEIS A144633 and A144385 give the definitions. Checked with nothing found on either conjecture: S. Fried, "Proofs of Ten Conjectures From the OEIS", J. Integer Sequences 29 (2026), Art. 26.1.8; S. Fried, "Further proofs of conjectures from the OEIS", arXiv:2607.24832 (full text grepped); Epoch AI, "OEIS Open", arXiv:2608.11941 and github.com/epoch-research/LeanOpenProblems (no A14463x file); Engbers–Galvin–Smyth, "Restricted Stirling and Lah number matrices and their inverses", JCTA 2019 (integrality of inverses, not parity). No prior proof or counterexample found. + +## Citation + +```bibtex +@misc{math0:oeis-a144637, + author = {{math0}}, + title = {{A144637: (1/18) 6^n a(n)/n! is odd iff n = 2^k with k >= 1}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a144637}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a160848/README.md b/results/oeis-a160848/README.md new file mode 100644 index 0000000..90e9307 --- /dev/null +++ b/results/oeis-a160848/README.md @@ -0,0 +1,51 @@ +# Barker's order-20 recurrence for the lines through an 8 x n grid holds + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A160848 +**Date:** 2026-10-24 + +## Result + +Let a(n) be the number of lines in the plane through at least 2 points of the 8 x n grid {0..n-1} x {0..7} (OEIS A160848). Then for every n > 21: a(n) = -a(n-2) + a(n-5) + a(n-6) + 2a(n-7) + a(n-8) + a(n-9) - a(n-11) - a(n-12) - 2a(n-13) - a(n-14) - a(n-15) + a(n-18) + a(n-20) (Colin Barker's 2017 conjecture). + +## Assessment + +The conjecture follows readily from the slope-sum formula already in the entry. With 8 rows, y ranges over a bounded set, and for each fixed y the second difference in n of Sum_x (n-|kx|)[gcd(x,y)=1] is a gcd indicator that is periodic with period at most 7 (at most 6 for the k=2 term). So the second difference of a(n) is eventually a combination of sequences with periods 1..7. That means a(n) is annihilated by (1-x)^2 times lcm(1-x^q : q<=7), which is exactly Barker's denominator (1-x)^3 Phi_2...Phi_7. The manuscript re-derives the counting formula via "first pairs" and checks the period-420 identity by kernel computation, but the underlying idea is a standard half-page quasi-polynomial argument. + +*Follows from:* The entry's own formula a(n) = (1/2)(f(8,n,1) - f(8,n,2)), with f(m,n,k) = Sum (n-|kx|)(m-|ky|) over coprime (x,y), proved by Mustonen (PointsInGrid.pdf, Section 3) and repeated in the parent array A295707. Taking the second difference in n gives a periodic residual, which is Mustonen's eq. (38) for m=8. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A160848](https://oeis.org/A160848) as [`Math0.Statements.A160848.statement`](../../lean/Math0/Statements/OEIS/A160848.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A160848.lean`](../../lean/Math0/Frontier/OEIS/A160848.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjectures from _Colin Barker_, Dec 25 2017: "a(n) = -a(n-2) + a(n-5) + a(n-6) + 2*a(n-7) + a(n-8) + a(n-9) - a(n-11) - a(n-12) - 2*a(n-13) - a(n-14) - a(n-15) + a(n-18) + a(n-20) for n>21", with g.f. denominator (1-x)^3(1+x)(1-x+x^2)(1+x^2)(1+x+x^2)(1+...+x^4)(1+...+x^6). + +Referees: - OEIS A160848 (local mirror, revision #13 of Dec 25 2017): Barker's g.f. and order-20 recurrence are labelled "Conjectures from Colin Barker, Dec 25 2017", with no later %E. Siblings A160845, A160846, A160847, A160849 and A160850 are likewise still conjectural or empirical; A295707 is the parent array. +- S. Mustonen, "On lines and their intersection points in a rectangular grid of points", http://www.survo.fi/papers/PointsInGrid.pdf (2009). Section 3 proves L(m,n) = ½[f(m,n,1) - f(m,n,2)]. Appendix 2, eq. (38), gives the second-difference recursion L(m,n) = 2L(m,n-1) - L(m,n-2) + 2ψ1 + 2ψ4 with periodic residuals, supported by a heuristic "bearing points" argument and numerical checks; that recursion is the basis of the Mathematica code in the OEIS entry. +- P. Haukkanen and J. K. Merikoski, arXiv:1108.1041 (2011), Remark 2: for n1 ≠ n2, "Mustonen [5] conjectured a recursive formula", and the question is "more difficult". +- A.-M. Ernvall-Hytönen, K. Matomäki, P. Haukkanen and J. K. Merikoski, "Formulas for the number of gridlines", Monatsh. Math. 164 (2011) 157-170: proves Mustonen's recursions only for n×n and (n-1)×n grids. +- S. Mustonen, "On lines through a given number of points in a rectangular grid of points", LinesInGrid2.pdf: covers square grids only. + +No prior proof or counterexample of Barker's A160848 recurrence was found. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a160848, + author = {{math0}}, + title = {{Barker's order-20 recurrence for the lines through an 8 x n grid holds}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a160848}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a160848/paper.pdf b/results/oeis-a160848/paper.pdf new file mode 100644 index 0000000..52e0342 Binary files /dev/null and b/results/oeis-a160848/paper.pdf differ diff --git a/results/oeis-a160848/paper.tex b/results/oeis-a160848/paper.tex new file mode 100644 index 0000000..d453201 --- /dev/null +++ b/results/oeis-a160848/paper.tex @@ -0,0 +1,338 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,at}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {↔}{{$\leftrightarrow$}}1 + {¬}{{$\neg$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {∧}{{$\wedge$}}1 + {×}{{$\times$}}1 {ˢ}{{$^{\mathrm{s}}$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{ˢ}{\ensuremath{^{\mathrm{s}}}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Gb}{G^{\flat}} +\newcommand{\ind}[1]{[\,#1\,]} + +\title[Barker's recurrence for lines through an $8\times n$ grid]{Lines through at least two points of an $8\times n$ grid: a proof of Barker's order-$20$ recurrence (OEIS A160848)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the number of lines in the plane that pass through at least two points of the $8\times n$ grid of lattice points (OEIS A160848). +We prove the conjecture of Colin Barker (2017) that $a$ satisfies, for all $n>21$, the linear recurrence of order $20$ with characteristic polynomial $(1-x)^3\Phi_2\Phi_3\Phi_4\Phi_5\Phi_6\Phi_7$, namely $a(n)=-a(n-2)+a(n-5)+\dots+a(n-18)+a(n-20)$. +The proof shows that the second difference $a(n+1)-2a(n)+a(n-1)$ is, for $n\ge3$, an integer combination of gcd indicators with periods at most $7$; this is a rigorous form, for eight rows, of a recursion that S.~Mustonen found experimentally in 2009 and supported by a heuristic argument. +We found no earlier proof of Barker's recurrence and classify the result as new, though elementary. +The proof is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definition of $a$ is checked by the kernel against all $41$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +For $n\ge0$ let $\Gamma_n=\{0,\dots,n-1\}\times\{0,\dots,7\}\subset\Z^2$, and let $a(n)$ be the number of lines in $\mathbb R^2$ containing at least two points of $\Gamma_n$. This is A160848 of the OEIS \cite{A160848}, ``Number of lines through at least 2 points of an 8 X n grid of points'', contributed by Seppo Mustonen on May~28, 2009, with offset $0$ and first terms $0,1,66,131,238,361,534,\dots$; it is column $8$ of the array A295707 \cite{A295707}. On December~25, 2017, Colin Barker added to the entry a conjectured rational generating function and the corresponding linear recurrence of order $20$ (quoted in Section~\ref{sec:statement}). In revision \#13 (December~25, 2017), which is still the current revision of the entry in October~2026, both are labelled ``Conjectures''. We prove the recurrence (Theorem~\ref{thm:main}), and with it the generating function (Corollary~\ref{cor:gf}). + +\subsection*{Prior work} +\begin{itemize} +\item Mustonen \cite{Mustonen} proves a closed formula $L(m,n)=\tfrac12\bigl(f(m,n,1)-f(m,n,2)\bigr)$ for the number $L(m,n)$ of lines through at least two points of an $m\times n$ grid, by summing over slopes (his Section~3); it is the formula quoted in A160848. In his Appendix~2 he observes experimentally that for fixed $m$ the residual $L(m,n)-2L(m,n-1)+L(m,n-2)$ is periodic in $n$, and gives it explicitly in his formula~(38), supported by an explanation in terms of the first two grid points of a line (his ``bearing points'') and by numerical checks. The Mathematica program in A160848 implements (38). +\item Haukkanen and Merikoski \cite{HM}, Remark~2, write that for rectangular grids with unequal sides ``the question about recursive formulas is more difficult. Mustonen [5] conjectured a recursive formula for $l_{\ge2}(n_1,n_2)$'', where $l_{\ge2}(n_1,n_2)$ is the number of lines through at least two points of an $n_1\times n_2$ grid. +\item Ernvall-Hytönen, Matomäki, Haukkanen and Merikoski \cite{EMHM} prove Mustonen's conjectured recursive formulas for the $n\times n$ and $(n-1)\times n$ grids; they do not treat grids with a fixed number of rows. +\end{itemize} +The math0 referees found no proof or refutation of Barker's recurrence for A160848; the analogous formulas in the sibling entries A160845--A160847, A160849 and A160850 are likewise still labelled conjectural or empirical. Our Proposition~\ref{prop:second} is Mustonen's formula (38) for $m=8$ (Remark~\ref{rem:mustonen}); once it is proved, the recurrence follows from the periodicity of the residual by a routine cyclotomic argument. We therefore regard the result as new but elementary: a first rigorous proof of a consequence of a formula that was previously supported only heuristically. + +\section{Statement}\label{sec:statement} + +\begin{theorem}\label{thm:main} +For every integer $n>21$, +\[ +\begin{aligned} +a(n)={}&-a(n-2)+a(n-5)+a(n-6)+2a(n-7)+a(n-8)+a(n-9)\\ +&-a(n-11)-a(n-12)-2a(n-13)-a(n-14)-a(n-15)+a(n-18)+a(n-20). +\end{aligned} +\] +Equivalently, $\sum_{k=0}^{20}p_k\,a(n-k)=0$ for $n\ge22$, where +\[ +P(x)=\sum_{k=0}^{20}p_kx^k=1+x^2-x^5-x^6-2x^7-x^8-x^9+x^{11}+x^{12}+2x^{13}+x^{14}+x^{15}-x^{18}-x^{20}. +\] +\end{theorem} + +Expanding shows $P(x)=(1-x)^3(1+x)(1-x+x^2)(1+x^2)(1+x+x^2)(1+\dots+x^4)(1+\dots+x^6)=(1-x)^3\prod_{d=2}^{7}\Phi_d(x)$, which is Barker's denominator. The recurrence fails for $n=20$ and $n=21$ (the left side minus the right side is $8$ in both cases), so the range $n>21$ is sharp. + +\begin{corollary}[not formalized]\label{cor:gf} +$\sum_{n\ge0}a(n)x^n=xN(x)/P(x)$, where $xN(x)$ is the numerator in Barker's generating function below. +\end{corollary} + +\begin{proof} +The coefficient of $x^n$ in $P(x)\sum_n a(n)x^n$ is $\sum_{k\le\min(n,20)}p_k a(n-k)$. For $n\ge22$ it vanishes by Theorem~\ref{thm:main}, as does the coefficient of $x^n$ in $xN(x)$, which has degree $21$. For $n\le21$ the two coefficients agree by a direct computation from $a(0),\dots,a(21)$, which are among the kernel-checked terms (\decl{a_data} below). +\end{proof} + +\subsection*{The OEIS conjecture} +The FORMULA section of A160848 \cite{A160848} contains, verbatim: +\begin{lstlisting}[language={},keywordstyle={},frame=none,basicstyle=\ttfamily\scriptsize] +Conjectures from _Colin Barker_, Dec 25 2017: (Start) +G.f.: x*(1 + 66*x + 132*x^2 + 304*x^3 + 492*x^4 + 771*x^5 + 1003*x^6 + 1273*x^7 + 1390*x^8 + 1480*x^9 + 1374*x^10 + 1241*x^11 + 971*x^12 + 739*x^13 + 476*x^14 + 296*x^15 + 140*x^16 + 74*x^17 + 17*x^18 + 8*x^19 + 8*x^20) / ((1 - x)^3*(1 + x)*(1 - x + x^2)*(1 + x^2)*(1 + x + x^2)*(1 + x + x^2 + x^3 + x^4)*(1 + x + x^2 + x^3 + x^4 + x^5 + x^6)). +a(n) = -a(n-2) + a(n-5) + a(n-6) + 2*a(n-7) + a(n-8) + a(n-9) - a(n-11) - a(n-12) - 2*a(n-13) - a(n-14) - a(n-15) + a(n-18) + a(n-20) for n>21. +(End) +\end{lstlisting} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A160848.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{8883f318\ldots 633f3}) before any proof attempt. The definitions on which the statement depends, and the statement itself, read as follows (verbatim and in order; the header, import, docstrings, the definitions used only for fast evaluation and the data check, the theorems, the \texttt{Decidable} instance for \decl{Recurrence} and the unproved variant \decl{statement_gf} are omitted): +\begin{lstlisting} +namespace Math0.Statements.A160848 +def pt (i : ℕ) : ℤ × ℤ := (((i / 8 : ℕ) : ℤ), ((i % 8 : ℕ) : ℤ)) +def Collinear3 (p q r : ℤ × ℤ) : Prop := + (q.1 - p.1) * (r.2 - p.2) = (q.2 - p.2) * (r.1 - p.1) +instance (p q r : ℤ × ℤ) : Decidable (Collinear3 p q r) := + inferInstanceAs (Decidable (_ = _)) +def lineThrough (n i j : ℕ) : Finset ℕ := + (Finset.range (8 * n)).filter fun k => Collinear3 (pt i) (pt j) (pt k) +def a (n : ℕ) : ℕ := + (((Finset.range (8 * n) ×ˢ Finset.range (8 * n)).filter fun ij => ij.1 ≠ ij.2).image + fun ij => lineThrough n ij.1 ij.2).card +def Recurrence (f : ℕ → ℤ) (n : ℕ) : Prop := + f n = -f (n - 2) + f (n - 5) + f (n - 6) + 2 * f (n - 7) + f (n - 8) + f (n - 9) + - f (n - 11) - f (n - 12) - 2 * f (n - 13) - f (n - 14) - f (n - 15) + f (n - 18) + f (n - 20) +def statement : Prop := + ∀ n : ℕ, 21 < n → Recurrence (fun m => (a m : ℤ)) n +end Math0.Statements.A160848 +\end{lstlisting} +The point with number $i<8n$ is $\mathrm{pt}(i)=(\lfloor i/8\rfloor,\,i\bmod 8)$, so $i\mapsto\mathrm{pt}(i)$ is a bijection from $\{0,\dots,8n-1\}$ onto $\Gamma_n$ and the number of $(x,y)$ is $\nu(x,y)=8x+y$. (OEIS writes ``$8\times n$''; $\Gamma_n$ and its transpose are congruent, so they have the same number of lines.) For $p\ne q$, \decl{Collinear3}$(p,q,r)$ says that $r$ lies on the line $pq$. Thus \decl{lineThrough}$(n,i,j)$ is the set of grid points on the line through $\mathrm{pt}(i)\ne\mathrm{pt}(j)$, and \decl{a}$(n)$ is the number of distinct such sets. A line through two grid points is determined by its set of grid points, and two distinct lines share at most one point, so \decl{a}$(n)$ is exactly the number of lines through at least two points of $\Gamma_n$. The values are cast to $\Z$ because of the negative coefficients; for $n>21$ every index $n-k$ ($k\le20$) is at least $2$, so the truncated subtractions in $\N$ are exact. The statement file also proves the following (statements shown, proofs omitted); \decl{IsFirst}, \decl{goodF} and \decl{aFast} are explained in Lemma~\ref{lem:first}: +\begin{lstlisting} +theorem isFirst_iff {i j : ℕ} (hij : i < j) : IsFirst i j ↔ goodF i j = true +theorem a_eq_aFast (n : ℕ) : a n = aFast n +theorem a_data : (List.range 41).map a = + [0, 1, 66, 131, 238, 361, 534, 709, 938, 1183, 1470, 1759, 2104, 2459, 2870, 3287, 3740, 4209, + 4734, 5261, 5844, 6437, 7070, 7711, 8408, 9115, 9872, 10637, 11444, 12265, 13142, 14015, + 14944, 15889, 16876, 17871, 18914, 19967, 21076, 22193, 23352] +\end{lstlisting} +The list in \decl{a_data} is the full DATA section of the entry, $a(0),\dots,a(40)$; it is proved by \texttt{decide +kernel} after rewriting with \decl{a_eq_aFast}. This anchors the definition to the entry independently of the conjecture. The file also checks that these terms satisfy the recurrence for $22\le n\le40$ (\decl{recurrence_data}), a check of the transcription only. + +\section{Proof}\label{sec:proof} + +The proof follows \path{lean/Math0/Frontier/OEIS/A160848.lean}; bracketed names are the corresponding Lean declarations. Write $\ind{A}$ for the indicator of a statement $A$ and $u(a,b)=\ind{\gcd(a,b)=1}$ for $a,b\in\N$; note $u(a,0)=\ind{a=1}$. + +\subsection{Counting each line once (statement file)} +Call a pair $i0$ and $d_1\ge0$. If $g=\gcd(d_1,|d_2|)\ge2$, the point $P+d/g$ lies in $\Gamma_n$ (its coordinates lie between those of $\mathrm{pt}(i)$ and $\mathrm{pt}(j)$), on the line, with number $i+(j-i)/g\in(i,j)$. If $P-d\in\N\times\{0,\dots,7\}$, then also $x-d_1\le x= 1 that lie entirely inside turn n, that is, with 2pi(n-1) <= S(i-1) and S(i) <= 2pi n. Then for every n >= 2, the difference a(n) = c(n) - c(n-1) is one of 18, 19, 20, 21. This is Dumortier's conjecture in OEIS A172164. + +## Assessment + +The heuristic is immediate: the turn boundaries are roughly floor((pi n + c)^2), whose second differences are within 2 of 2 pi^2 = 19.74, which leaves only 18..21 with about 0.26 of slack. The proof turns this into an effective argument in a standard way. Two elementary one-step inequalities show that S(k) - 2 sqrt k is nonincreasing and that S(k) - 2 sqrt k - 2/sqrt k is nondecreasing (the usual sum-versus-integral comparison). A squeeze over three consecutive turns then gives |a(n) - 2 pi^2| < 2.13 for n >= 71, and a finite interval computation covers n <= 70. This is about a page of standard effective asymptotics plus a finite check, and the scout's own plan (Euler-Maclaurin plus a check of small n) already calls every step standard. The Lean work, including the kernel-evaluated interval certificate, was heavy, but that is formalization effort and not new mathematics. + +*Follows from:* Hlawka's asymptotic Sum_{x2\pi n$, and A137515 \cite{A137515} (S.~Dumortier, 2008) lists the number $K_n=\text{A072895}(n)-1$ of triangles in the first $n$ turns: $16,53,109,185,\dots$ +A comment in A137515 says that ``from one term to the next one, the number added grows by 18, 19, 20 or 21 (tested up to 5000 terms)'' (restated by H.~P.~Dale, 2019). +Finally A172164 \cite{A172164} (S.~Dumortier, 2010) lists $a(n)=c(n)-c(n-1)$, where $c(n)$ is the number of triangles entirely contained in turn $n$, and conjectures that $a(n)\in\{18,19,20,21\}$ for all $n\ge2$ (Conjecture~\ref{conj}). +R.~G.~Wilson~v and H.~Kociemba added frequency counts of the four values over the first $10^5$ and $10^7$ turns (2013). + +The conjecture is explained by the asymptotics of $S$. +Hlawka \cite{Hl80} showed that $S(k)=2\sqrt k+\kappa+o(1)$, where $\kappa=-2.1577829966\ldots$ is Hlawka's \emph{Schneckenkonstante} (denoted $K$ in A105459 \cite{A105459}); see Davis \cite[pp.~157--167]{Da93} for an English account and Brink \cite{Br12} for the relation of the spiral to zeta values at the half-integers. +Hence $K_n\approx(\pi n-\kappa/2)^2$; Kociemba observed numerically (A072895) that $\lfloor(\pi n-\kappa/2)^2-1/6\rfloor=\text{A072895}(n)$ for $n<10^9$. +Since the second difference $\Delta^2$ of $(\pi n+\text{const})^2$ is $2\pi^2=19.739\ldots$ and $|\Delta^2\lfloor y_n\rfloor-\Delta^2y_n|<2$ for real sequences, this suggests exactly the values $18,\dots,21$. +A proof needs explicit error terms: an error of $1$ in $K_n$ would allow errors of up to $4$ in $a(n)$. + +We prove the conjecture (Theorem~\ref{thm:main}) without using Hlawka's constant or any limit. +Two one-step inequalities (Lemmas~\ref{lem:up} and~\ref{lem:low}) show that $E(k)=S(k)-2\sqrt k$ is nonincreasing and $E(k)-2/\sqrt k$ is nondecreasing; on a window of three consecutive turns this gives $|a(n)-2\pi^2|<2.13$ once $n\ge71$ (Proposition~\ref{prop:core}). +The terms with $n\le70$ come from an interval computation evaluated by the Lean kernel. + +\subsection*{Status and prior work} +The math0 literature referees found no prior proof and no counterexample. +A172164 still states the conjecture at its current revision (\#25, August~11, 2026), the comments in A137515 and A072895 are numerical, and W.~Lang's related entries (A296179, A296181, A295338, A295339) do not address the bound. +Searches of arXiv, MathOverflow, Mathematics Stack Exchange, the SeqFan list and the literature on the spiral \cite{Hl80,Da93,Br12} found no statement of the bound; Kociemba's web page on the spiral, linked from A072895, could only be seen through search snippets, which mention no proof. +The conjecture is not among the statements of the formal-conjectures repository \cite{FC} at the commit pinned by math0 (\texttt{c77fdd4}). +We therefore classify Theorem~\ref{thm:main} as a new result. The mathematics is modest, an effective version of Hlawka's formula (Remark~\ref{rem:hlawka}), and the bound may be known to experts without having been written down. + +\section{Statement}\label{sec:statement} + +Let $S$ be as above. For $n\ge1$ let +\[ + T(n)=\{\,i\ge1:\ 2\pi(n-1)\le S(i-1)\ \text{and}\ S(i)\le2\pi n\,\},\qquad c(n)=\#T(n), +\] +the set and number of triangles lying entirely in the $n$-th turn, and for $n\ge2$ let $a(n)=c(n)-c(n-1)$. + +\begin{theorem}\label{thm:main} +For every integer $n\ge2$, $a(n)\in\{18,19,20,21\}$. +\end{theorem} + +All four values occur: $a(2)=20$, $a(3)=19$, $a(7)=21$ and $a(8)=18$. + +\subsection*{The OEIS conjecture} +The entry A172164 \cite{A172164} is named ``Differences between numbers of triangles entirely contained in two consecutive turns of Pythagoras's snail (Theodorus spiral).'' It has offset $2$, lists $69$ terms $a(2),\dots,a(70)$, and gives the example ``In the first turn, 16 triangles are complete. In the 2nd turn, there are 36 triangles completely included. The difference is 20.'' +Its COMMENTS section contains, verbatim, the following conjecture by S\'ebastien Dumortier, dated January~27, 2010: +\begin{quote}\small +\texttt{Conjecture : The terms are only 18,19,20,21 (From the first thousand turns, there are 2,3\% of 18, 36,5\% of 19, 46,2\% of 20 and 15\% of 21). No period found. Probably due to Pi transcendence.} +\end{quote} + +\begin{conjecture}[Dumortier]\label{conj} +Every term $a(n)$, $n\ge2$, of A172164 is one of $18,19,20,21$. +\end{conjecture} + +The percentages and the last two sentences are observations, not part of the formalized claim. + +\subsection*{Lean statement} +The statement is the definition \decl{Math0.Statements.A172164.statement} in the math0 statement file \path{lean/Math0/Statements/OEIS/A172164.lean}, which was reviewed for fidelity and frozen (SHA-256 \texttt{948ca46a\dots b30be5f4}) before any proof attempt. +The definitions and the statement read verbatim (docstrings, blank lines, the auxiliary lemmas and the data checks omitted):\par\nobreak\noindent +\begin{minipage}{\linewidth} +\begin{lstlisting} +namespace Math0.Statements.A172164 +open Real Finset Filter Topology +noncomputable def S (k : ℕ) : ℝ := ∑ i ∈ range k, arctan (1 / √((i : ℝ) + 1)) +def turnTriangles (n : ℕ) : Set ℕ := + {i | 1 ≤ i ∧ 2 * π * ((n : ℝ) - 1) ≤ S (i - 1) ∧ S i ≤ 2 * π * n} +noncomputable def c (n : ℕ) : ℕ := (turnTriangles n).ncard +noncomputable def a (n : ℕ) : ℤ := (c n : ℤ) - c (n - 1) +def statement : Prop := ∀ n : ℕ, 2 ≤ n → a n = 18 ∨ a n = 19 ∨ a n = 20 ∨ a n = 21 +\end{lstlisting} +\end{minipage} + +\emph{Encoding.} \texttt{S k} is $\sum_{i=0}^{k-1}\arctan(1/\sqrt{i+1})=S(k)$, and \texttt{turnTriangles n} is $T(n)$: \texttt{i - 1} is guarded by $1\le i$, and $n-1$ in the turn bound is computed in $\mathbb R$. +\texttt{Set.ncard} returns $0$ on infinite sets, but \decl{turnTriangles_finite} shows that $T(n)\subseteq[0,81n^2+2)$, using $S(k)\ge\frac56\sqrt k$ for $k\ge2$ (\decl{S_ge}), so \texttt{c n} is the true count. +\texttt{a n} is computed in $\mathbb Z$, and for $n\ge2$ the index $n-1\ge1$ is the previous turn. +The turn bounds are closed, the natural reading of ``entirely contained''; with open bounds triangle $1$, which starts at $S(0)=0$, would not count for turn $1$, contradicting the example $c(1)=16$. Otherwise the readings differ only if $S(k)\in2\pi\mathbb Z$ for some $k\ge1$. This does not happen for $k\le K_{70}$ (Proposition~\ref{prop:crossing}); we do not know whether it can happen at all, and Section~\ref{sec:proof} does not assume that it cannot. + +\emph{Checks against the OEIS data.} The statement file proves, against the real-number definitions, that $c(1)=16$ and $c(2)=36$, as in the example (\decl{c_one_two}), and that $a(2),\dots,a(70)$ are the $69$ listed terms (\decl{a_data}). +Along the way it certifies the turn boundaries $K_1,\dots,K_{70}$, the first $42$ of which are the $42$ listed terms of A137515 (\decl{Kseq_A137515}). +These checks rest on the interval computation of Section~\ref{sec:small}, and the case $n\le70$ of Theorem~\ref{thm:main} uses them. + +\section{Proof}\label{sec:proof} + +Write $f(j)=\arctan(1/\sqrt j)$ and $E(k)=S(k)-2\sqrt k$. +Each lemma names its Lean declaration: unmarked names are private lemmas of the proof file, names marked (St) are in the statement file. +For $0\le x<1$ the terms of $\arctan x=\sum_{i\ge0}(-1)^ix^{2i+1}/(2i+1)$ decrease, so partial sums with an even (odd) number of terms are lower (upper) bounds (\decl{arctan_alt_bounds}, St); in particular $x-x^3/3\le\arctan x\le x$. + +\subsection{Two one-step inequalities} + +\begin{lemma}[\decl{step_upper}]\label{lem:up} +For every $k\ge0$, $f(k+1)\le2(\sqrt{k+1}-\sqrt k)$. +\end{lemma} + +\begin{proof} +Let $p=\sqrt k$ and $q=\sqrt{k+1}\ge1$, so $q^2=p^2+1$. +If $q=1$ then $f(1)=\pi/4<1=1/q$; if $q>1$ then $\arctan(1/q)\le1/q$ by the alternating-series bound. +Finally $2q(q-p)-1=q^2+(q^2-1)-2pq=(q-p)^2\ge0$, so $1/q\le2(q-p)$. +\end{proof} + +\begin{lemma}[\decl{step_lower}]\label{lem:low} +For every $k\ge1$, $f(k+1)\ge2(\sqrt{k+1}-\sqrt k)+2/\sqrt{k+1}-2/\sqrt k$. +\end{lemma} + +\begin{proof} +Let $p=\sqrt k$, $q=\sqrt{k+1}$, so $00$. +\end{proof} + +\begin{corollary}[\decl{E_anti}, \decl{E_mono}]\label{cor:E} +\textup{(a)} If $k\le m$ then $E(m)\le E(k)$; in particular $E(k)\le E(0)=0$ for all $k$. +\textup{(b)} If $1\le k\le m$ then $E(k)-2/\sqrt k\le E(m)-2/\sqrt m$. +\end{corollary} + +\begin{proof} +Since $S(k+1)=S(k)+f(k+1)$ (\decl{S_succ}, St), Lemma~\ref{lem:up} says $E(k+1)\le E(k)$ and Lemma~\ref{lem:low} says $E(k)-2/\sqrt k\le E(k+1)-2/\sqrt{k+1}$ for $k\ge1$. Induct on $m$. +\end{proof} + +\begin{remark}\label{rem:hlawka} +Corollary~\ref{cor:E} implies that $E(k)$ converges to a limit, Hlawka's constant $\kappa$ \cite{Hl80}, with $0\le E(k)-\kappa\le2/\sqrt k$ for $k\ge1$. This is not used below and not formalized. +\end{remark} + +\subsection{Counting the triangles of a turn} +$S$ is strictly increasing with $S(0)=0$ (\decl{S_strictMono}, \decl{S_zero}, St), unbounded because $S(k)\ge\frac56\sqrt k$ (\decl{S_unbounded}), and $S(k+1)0$ for $P\ge200$. So $VT_1\le0.129$, and $V^2/2\le0.001$. +\end{proof} + +\begin{lemma}[\decl{final_bound}]\label{lem:final} +Let $3.14<\pi'<3.1416$, let $T_0,V,K_1,K_2,L_0,L_1$ be reals with $X=V(T_0+2\pi')+V^2/2\le0.13$, and put $T_1=T_0+2\pi'$, $T_2=T_0+4\pi'$. If +\begin{align*} + &\text{(F1)}\ 4K_2\le(T_2+V)^2, &&\text{(F2)}\ T_2^2<4(K_2+1), &&\text{(F3)}\ 4L_0\le(T_0+V)^2+4,\\ + &\text{(F4)}\ T_0^2\le4L_0, &&\text{(F5)}\ T_1^2-2<2(K_1+L_1), &&\text{(F6)}\ 2(K_1+L_1)\le(T_1+V)^2+2, +\end{align*} +then $A=(K_2-L_1)-(K_1-L_0)$ satisfies $178\pi'^2-4X-8$. So $|A-2\pi'^2|<2+X\le2.13$, and $9.85<\pi'^2<9.87$ gives $172\pi r\ge2\cdot3.14\cdot69$, so $\sqrt{K_0+1}>216$ and $K_0\ge40000$. +Put $P=\sqrt{K_0}\ge200$, $Q=\sqrt{K_2}\ge P$ and $V=2/P-2/Q$. Then $V\ge0$, $V\le2/P\le1/100$, and $VPQ=2(Q-P)$ gives $VP^2\le2(Q-P)$. +For $K_0\le k\le K_2$, Corollary~\ref{cor:E}(b) (applicable as $K_0\ge1$) gives $E(k)\ge e-2/P+2/\sqrt k\ge e-V$, so: +(iii) if $K_0\le K\le K_2$ and $S(K)\le\theta$, then $2\sqrt K\le\theta-e+V$. +Next, $T_0=\theta_0-S(K_0)+2P\ge2P$; and since $(P+\frac1{2P})^2\ge K_0+1$, (i) gives $T_0<2\sqrt{K_0+1}\le2P+1/P$. By (iii) with $K=K_2$, $2Q\le T_2+V=T_0+4\pi+V$. +With $3.14<\pi<3.1416$ (Mathlib's \decl{Real.pi_gt_d2}, \decl{Real.pi_lt_d4}), Lemma~\ref{lem:X} gives $X\le0.13$. +It remains to verify (F1)--(F6) of Lemma~\ref{lem:final}; each follows by squaring inequalities between nonnegative numbers. +(F1) is (iii) at $K_2$, and (F2) is (i) at $K_2$. +For (F3), $L_0\le K_0+1$ and $4K_0=4P^2\le T_0^2\le(T_0+V)^2$. +For (F4): if $L_0=K_0$ and $S(K_0)=\theta_0$, then (ii) gives $T_0\le2\sqrt{K_0}$, so $T_0^2\le4L_0$; if $L_0=K_0+1$, (i) at $K_0$ gives $T_0^2<4L_0$. +For (F5): if $L_1=K_1$ and $S(K_1)=\theta_1$, (ii) gives $T_1^2\le4K_1=2(K_1+L_1)$; if $L_1=K_1+1$, (i) gives $T_1^2<4(K_1+1)=2(K_1+L_1)+2$. +For (F6), $L_1\le K_1+1$ and (iii) at $K_1$ gives $4K_1\le(T_1+V)^2$. +Lemma~\ref{lem:final} with $\pi'=\pi$ completes the proof. +\end{proof} + +\subsection{The turns \texorpdfstring{$n\le70$}{n <= 70}}\label{sec:small} +All declarations named in this subsection are in the statement file. +Let $K_1,\dots,K_{70}$ be the numbers $16,53,109,\dots,47456,48835$ of the list \decl{Kseq}. + +\begin{proposition}[\decl{crossing}, St]\label{prop:crossing} +For $1\le n\le70$, $S(K_n)<2\pi n\pi_{\rm hi}(8n-1)/4$ for $k=K_n$, where $\pi_{\rm lo}=3.14159265358979323846<\pi<\pi_{\rm hi}=\pi_{\rm lo}+10^{-20}$ (Mathlib's \decl{Real.pi_gt_d20}, \decl{Real.pi_lt_d20}). +As $2\pi n-\pi/4=\pi(8n-1)/4$, the tests give $S(K_n)<2\pi n 1 (A175385) + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Number theory +**Source problem:** OEIS A175385 +**Date:** 2026-10-18 + +## Result + +For every integer n ≥ 2, the rational number S(n) = ∑_{i=1}^{n} C(2n-i-1, i-1)/i is not an integer. This is the Shevelev–Seidov conjecture from OEIS A175385. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A175385](https://oeis.org/A175385) as [`Math0.Statements.A175385.statement`](../../lean/Math0/Statements/OEIS/A175385.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A175385.lean`](../../lean/Math0/Frontier/OEIS/A175385.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: We conjecture that Sum_{i=1..n} ((1/i)*C(2n-i-1,i-1)) is not an integer for n>1. (Vladimir Shevelev, Zak Seidov, Apr 24 2010) + +Referees: OEIS A175386 (cross-reference of A175385), comment by Ralf Stephan, May 25 2026: the conjecture was proved by an autonomous AI agent (AlphaProof Nexus). Lean file: https://github.com/google-deepmind/alphaproof-nexus-results/blob/main/APNOutputs/OEIS/oeis_175386_conjecture_0.lean (theorem target_theorem_0: for n > 1, the denominator of S(n) is not 1; checked, no sorry). Papers: G. Tsoukalas et al., "Advancing Mathematics Research with AI-Driven Formal Proof Search", arXiv:2605.22763 (May 2026); T. Adamczewski, "OEIS Open: How many conjectures can language models turn into theorems?", arXiv:2608.11941 (Aug 2026), cited by OEIS for the proof on p. 15, Appendix A. Classical implication: P. S. Bruckman, "Lucas Pseudoprimes Are Odd", Fibonacci Quarterly 32(2) (1994) 155-157 (https://www.mathstat.dal.ca/FQ/Scanned/32-2/bruckman2.pdf). No even composite N has N | L_N − 1, and with 2n·S(n) = L_{2n} − 1 this settles the conjecture. The A175385 entry itself (https://oeis.org/A175385, history up to #14, Mar 2023) records no proof. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a175385, + author = {{math0}}, + title = {{∑_{i=1..n} C(2n-i-1, i-1)/i is never an integer for n > 1 (A175385)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a175385}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a175385/paper.pdf b/results/oeis-a175385/paper.pdf new file mode 100644 index 0000000..b84d6ea Binary files /dev/null and b/results/oeis-a175385/paper.pdf differ diff --git a/results/oeis-a175385/paper.tex b/results/oeis-a175385/paper.tex new file mode 100644 index 0000000..532f0b2 --- /dev/null +++ b/results/oeis-a175385/paper.tex @@ -0,0 +1,455 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,set,rw,at,push_cast,exact_mod_cast,apply,by_cases,field_simp,linear_combination}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, upquote=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={∑}{{$\sum$}}1 {∈}{{$\in$}}1 {ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {ℤ}{{$\mathbb{Z}$}}1 + {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {≥}{{$\ge$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {…}{{$\ldots$}}1 + {¬}{{$\neg$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 + {∣}{{$\mid$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{…}{\ensuremath{\ldots}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\F}{\mathbb{F}} + +\title[Non-integrality of a binomial sum (OEIS A175385)]{The sum $\sum_{i=1}^{n}\frac{1}{i}\binom{2n-i-1}{i-1}$ is not an integer for $n\ge 2$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +For $n\ge1$ let $S(n)=\sum_{i=1}^{n}\frac1i\binom{2n-i-1}{i-1}$. +We prove that $S(n)$ is not an integer for any $n\ge2$, as conjectured by V.~Shevelev and Z.~Seidov in 2010 in OEIS A175385. +The proof combines the identity $2nS(n)+1=L_{2n}$, where $L_j$ is the $j$th Lucas number, with a congruence modulo $4$ for even $n$ and, for odd $n$, an argument in an algebraic closure of $\F_p$, where $p$ is the least prime factor of $n$. +The result is not new: it follows from the classical theorem that no even composite $N$ divides $L_N-1$ (White, Hunt and Dresel 1977; Di Porto 1993; Bruckman 1994), and a Lean proof found by the AlphaProof Nexus agent was published in 2026, so ours is an independent formal proof of a known result. +It is verified in Lean~4 with Mathlib against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the $27$ listed terms of the sequence. +\end{abstract} +\maketitle + +\section{Introduction} + +The OEIS sequence A175385 \cite{A175385}, contributed by Vladimir Shevelev and Zak Seidov on April~24, 2010, lists the numerators of the rational numbers +\[ + S(n)=\sum_{i=1}^{n}\frac{1}{i}\binom{2n-i-1}{i-1},\qquad n\ge1, +\] +and its companion A175386 \cite{A175386} lists their denominators: +$S(1)=1$, $S(2)=3/2$, $S(3)=17/6$, $S(4)=23/4$, $S(5)=61/5$, \dots. +Both entries record the conjecture that $S(n)$ is not an integer for $n>1$. +They also give the closed form $S(n)=\bigl({}_2F_1(\tfrac12-n,-n;1-2n;-4)-1\bigr)/(2n)$. + +The problem becomes transparent once one notices the identity +\begin{equation}\label{eq:lucas} + 2n\,S(n)+1=L_{2n}\qquad(n\ge1), +\end{equation} +where $L_j=F_{j+1}+F_{j-1}$ are the Lucas numbers \cite{A000032} and $F_j$ the Fibonacci numbers (Proposition~\ref{prop:closed} below; it follows from the diagonal sums of Pascal's triangle). +Thus $S(n)\in\Z$ if and only if $2n\mid L_{2n}-1$, and the conjecture says that $2n\nmid L_{2n}-1$ for every $n\ge2$. + +\subsection*{Prior work} +In this form the conjecture is a special case of a classical theorem. +A composite number $N$ with $N\mid L_N-1$ is called a (Bruckman--)Lucas pseudoprime \cite{A005845}, and Bruckman \cite{Br} proved that such numbers are odd: no even composite $N$ divides $L_N-1$. +As Bruckman acknowledges in \cite{Br}, this had been proved earlier by White, Hunt and Dresel \cite{WHD}, and independently by Di Porto \cite{DP}, who calls such $N$ Fibonacci pseudoprimes of the first kind. +For $n\ge2$ the number $N=2n\ge4$ is even and composite, so this theorem and \eqref{eq:lucas} give the conjecture. +The conjecture, posed in 2010, is therefore a consequence of results published between 1977 and 1994. +This deduction was pointed out by the math0 referees; we do not know whether it was recorded earlier, but it is not mentioned in A175385. + +More recently, on May~25, 2026, Ralf Stephan added a comment to A175386 \cite{A175386} stating that the conjecture was proved by an autonomous AI agent, with references to the paper of Tsoukalas et al.\ \cite{Ts} and to a Lean file of Google DeepMind's AlphaProof Nexus \cite{APN}; the entry also cites Adamczewski \cite[p.~15, Appendix~A]{Ad} for a proof. +The Lean file proves, for $n>1$, that the denominator of $S(n)$ is not $1$, which is equivalent to the conjecture. +It also starts from \eqref{eq:lucas} and splits on the parity of $n$. +For odd $n$ it uses $L_{2n}=L_n^2+2$, the factorization $F_{3n}=F_n(L_n^2+1)$, the divisibility $p\mid F_{p^2-1}$ for primes $p\ne2,5$, and the strong divisibility property of the Fibonacci numbers to conclude that the least prime factor of $n$ divides $F_3=2$. +The entry A175385 itself (revision \#14, March 2023) records no proof. + +\subsection*{This paper} +We give a self-contained proof of the conjecture and an independent Lean formalization of it, checked against a statement that math0 formalized from A175385 (Section~\ref{sec:statement}). +The case of even $n$ is a congruence modulo $4$, as in \cite{APN}. +For odd $n$ we argue in an algebraic closure of $\F_p$, where $p$ is the least prime factor of $n$: a root $\alpha$ of $X^2-X-1$ satisfies $\alpha^{p^2-1}=1$, and from $L_{2n}\equiv1\pmod p$ we derive $\alpha^6=-1$, which forces $p\mid 20$. +Arguments of this kind are standard in the study of Lucas sequences modulo primes, and we claim no novelty for the mathematics. +We classify the result as an \emph{independent formal proof of a known result}. + +\section{Statement}\label{sec:statement} + +\begin{theorem}\label{thm:main} +For every integer $n\ge2$, the rational number $S(n)=\sum_{i=1}^{n}\frac{1}{i}\binom{2n-i-1}{i-1}$ is not an integer. +\end{theorem} + +The COMMENTS section of A175385 \cite{A175385} reads, verbatim: +\begin{quote} +\raggedright\texttt{We conjecture that Sum\_\char`\{i=1..n\char`\}\ ((1/i)*C(2n-i-1,i-1)) is not an integer for n>1.} +\end{quote} +The entry is authored by Vladimir Shevelev and Zak Seidov and dated April~24, 2010; the name of the sequence is \texttt{a(n) = numerator of Sum\_\char`\{i=1..n\char`\}\ binomial(2n-i-1,i-1)/i} (offset~$1$). +The same conjecture appears in A175386 \cite{A175386}. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A175385.lean}; it was reviewed for fidelity and frozen (SHA-256 \texttt{3e8f66ae\ldots c8654}) before any proof attempt. +After the copyright header, the import of Mathlib and the module docstring, the file reads verbatim: +\begin{lstlisting} +namespace Math0.Statements.A175385 + +/-- The sum `∑_{i=1}^{n} C(2n-i-1, i-1)/i`, computed exactly in `ℚ`. -/ +def S (n : ℕ) : ℚ := + ∑ i ∈ Finset.Icc 1 n, ((Nat.choose (2 * n - i - 1) (i - 1) : ℕ) : ℚ) / (i : ℚ) + +/-- A175385 (offset `1`): the numerator, in lowest terms, of +`∑_{i=1..n} binomial(2n-i-1, i-1)/i`. -/ +def a (n : ℕ) : ℕ := (S n).num.natAbs + +/-- The definition reproduces all 27 terms listed in OEIS, `a 1, …, a 27` (kernel-checked). -/ +theorem a_data : (List.range 27).map (fun i => a (i + 1)) = + [1, 3, 17, 23, 61, 107, 421, 1103, 5777, 7563, 19801, 103681, 135721, 355323, 1860497, + 2435423, 6376021, 11128427, 43701901, 114413063, 599074577, 784198803, 2053059121, + 10749957121, 14071876561, 36840651123, 192900153617] := by + decide +kernel + +/-- Conjecture (Shevelev and Seidov, A175385): for every `n > 1`, the sum +`∑_{i=1..n} C(2n-i-1, i-1)/i` is not an integer. -/ +def statement : Prop := + ∀ n : ℕ, 1 < n → ¬ ∃ k : ℤ, S n = (k : ℚ) + +end Math0.Statements.A175385 +\end{lstlisting} +The definition \decl{S} is the defining sum of the entry, computed exactly in $\Q$ with Mathlib's \decl{Nat.choose}; it is not the hypergeometric formula. +Subtraction in $\N$ is truncated, but for $1\le i\le n$ we have $2n-i-1\ge n-1\ge0$ and $i-1\ge0$, so no truncation occurs, and the divisor $i$ is at least $1$. +The function \decl{a} is the numerator of $S(n)$ in lowest terms (\decl{Rat.num}, converted to $\N$ by \decl{Int.natAbs}, which is harmless since $S(n)>0$ for $n\ge1$), with the OEIS offset~$1$. +The lemma \decl{a_data} checks, by \texttt{decide +kernel}, that $a(1),\dots,a(27)$ are exactly the $27$ terms listed in the entry; the Lean kernel evaluates the $27$ rational sums from the definitions and compares the numerators. +This ties \decl{S} to the OEIS data; \decl{a} itself does not occur in \decl{statement}. +Finally, ``is not an integer'' is encoded as the nonexistence of $k\in\Z$ with $S(n)=k$ in $\Q$, and ``for $n>1$'' as the hypothesis \texttt{1 < n} on $n\in\N$. +The excluded value $n=1$ is a genuine exception, since $S(1)=1$. + +\section{Proof}\label{sec:proof} + +We write $F_0=0$, $F_1=1$, $F_{j+2}=F_{j+1}+F_j$ (Mathlib's \decl{Nat.fib}), and use the convention $\binom{a}{b}=0$ for $b>a$. +For $n\ge1$ we put +\[ + T(n)=F_{2n+1}+F_{2n-1}, +\] +which is the Lucas number $L_{2n}$; the formal proof works with $T(n)$ directly and never defines Lucas numbers. +The proof follows the structure of the Lean file; Section~\ref{sec:lean} lists the corresponding declarations. + +\subsection{The closed form} + +\begin{lemma}[Diagonal sums of Pascal's triangle]\label{lem:diag} +If $m,N\in\N$ and $m<2N$, then $F_{m+1}=\sum_{k=0}^{N-1}\binom{m-k}{k}$. +\end{lemma} + +\begin{proof} +Mathlib's \decl{Nat.fib_succ_eq_sum_choose} states $F_{m+1}=\sum_{a+b=m}\binom{a}{b}$; reindexing the antidiagonal gives $F_{m+1}=\sum_{k=0}^{m}\binom{m-k}{k}$. +If $k\ge N$ then $2k\ge 2N>m$, so $m-km$. +Hence both $\sum_{k=0}^{m}$ and $\sum_{k=0}^{N-1}$ equal the sum over $0\le k\le N+m$. +\end{proof} + +\begin{lemma}\label{lem:term} +For $1\le i\le n$, +\[ + \frac{2n}{i}\binom{2n-i-1}{i-1}=\binom{2n-i}{i}+\binom{2n-i-1}{i-1}. +\] +\end{lemma} + +\begin{proof} +The identity $(M+1)\binom{M}{k}=(k+1)\binom{M+1}{k+1}$ (\decl{Nat.add_one_mul_choose_eq}) with $M=2n-i-1$ and $k=i-1$ gives $(2n-i)\binom{2n-i-1}{i-1}=i\binom{2n-i}{i}$. +Adding $i\binom{2n-i-1}{i-1}$ to both sides and dividing by $i$ gives the claim. +\end{proof} + +\begin{proposition}\label{prop:closed} +For every $n\ge1$, $2n\,S(n)+1=T(n)=F_{2n+1}+F_{2n-1}$. +\end{proposition} + +\begin{proof} +Write $n=m+1$ and substitute $i=j+1$; then $S(n)=\sum_{j=0}^{m}\binom{2m-j}{j}/(j+1)$. +By Lemma~\ref{lem:term}, +\[ + 2n\,S(n)=\sum_{j=0}^{m}\binom{2m+1-j}{j+1}+\sum_{j=0}^{m}\binom{2m-j}{j}. +\] +Lemma~\ref{lem:diag} with $(m,N)$ replaced by $(2m+2,m+2)$ gives $F_{2m+3}=\sum_{k=0}^{m+1}\binom{2m+2-k}{k}=1+\sum_{j=0}^{m}\binom{2m+1-j}{j+1}$, where we split off $k=0$ and put $k=j+1$. +Lemma~\ref{lem:diag} with $(2m,m+1)$ gives $F_{2m+1}=\sum_{j=0}^{m}\binom{2m-j}{j}$. +Hence $2nS(n)=(F_{2m+3}-1)+F_{2m+1}=T(n)-1$. +\end{proof} + +\subsection{Lucas numbers in a commutative ring} + +\begin{lemma}\label{lem:ring} +Let $R$ be a commutative ring and $\alpha\in R$ with $\alpha^2=\alpha+1$. Then: +\begin{enumerate} +\item $\alpha^{j+1}=F_{j+1}\alpha+F_j$ for all $j\ge0$; +\item $\beta=1-\alpha$ satisfies $\beta^2=\beta+1$ and $\alpha\beta=-1$; +\item $\alpha^{2n}+(1-\alpha)^{2n}=T(n)\cdot1_R$ for all $n\ge1$. +\end{enumerate} +\end{lemma} + +\begin{proof} +(1) By induction on $j$: the case $j=0$ is trivial, and +$\alpha^{j+2}=\alpha(F_{j+1}\alpha+F_j)=F_{j+1}(\alpha+1)+F_j\alpha=F_{j+2}\alpha+F_{j+1}$. +(2) $\beta^2=1-2\alpha+\alpha^2=2-\alpha=\beta+1$ and $\alpha\beta=\alpha-\alpha^2=-1$. +(3) Apply (1) to $\alpha$ and to $\beta$ with $j=2n-1$ and add: +$\alpha^{2n}+\beta^{2n}=F_{2n}(\alpha+\beta)+2F_{2n-1}=F_{2n}+2F_{2n-1}=F_{2n+1}+F_{2n-1}$. +\end{proof} + +\subsection{\texorpdfstring{Even $n$}{Even n}} + +\begin{lemma}\label{lem:mod4} +$F_{j+6}\equiv F_j\pmod4$ for all $j\ge0$. Consequently, if $n\ge2$ is even, then $T(n)\equiv2$ or $3\pmod4$. +\end{lemma} + +\begin{proof} +The addition formula $F_{a+b+1}=F_aF_b+F_{a+1}F_{b+1}$ (\decl{Nat.fib_add}) with $a=5$ gives $F_{j+6}=5F_j+8F_{j+1}\equiv F_j\pmod 4$. +So $F_j\bmod 4$ depends only on $j\bmod 6$, and $(F_0,\dots,F_5)\equiv(0,1,1,2,3,1)\pmod4$. +Write $n=m+1$ with $m$ odd, so $m\equiv1,3,5\pmod6$ and correspondingly $(2m+3,2m+1)\equiv(5,3),(3,1),(1,5)\pmod6$. +Hence $T(n)=F_{2m+3}+F_{2m+1}\equiv 1+2,\ 2+1,\ 1+1$, that is $3,3,2\pmod4$. +\end{proof} + +\subsection{\texorpdfstring{Odd $n$}{Odd n}} + +\begin{lemma}\label{lem:reduce} +Let $n\ge1$ and suppose that $S(n)=k$ with $k\in\Z$. Then $T(n)=2nk+1$ in $\Z$, and $T(n)\cdot1_R=1$ in every commutative ring $R$ whose characteristic divides $n$. +\end{lemma} + +\begin{proof} +The first claim is Proposition~\ref{prop:closed}, transported from $\Q$ to $\Z$ by injectivity of $\Z\to\Q$. Mapping it to $R$, where $n\cdot1_R=0$, gives the second. +\end{proof} + +\begin{lemma}[Frobenius]\label{lem:frob} +Let $K$ be a field of prime characteristic $p$ and $\alpha\in K$ with $\alpha^2=\alpha+1$. Then $\alpha\ne0$ and $\alpha^{p^2-1}=1$. +\end{lemma} + +\begin{proof} +Since $x\mapsto x^p$ is a ring endomorphism of $K$, $y=\alpha^p$ satisfies $y^2=(\alpha^2)^p=(\alpha+1)^p=y+1$. +Then $(y-\alpha)\bigl(y-(1-\alpha)\bigr)=y^2-y+\alpha-\alpha^2=(y+1)-y+\alpha-(\alpha+1)=0$, so $y=\alpha$ or $y=1-\alpha$. +In the first case $\alpha^{p^2}=y^p=\alpha^p=\alpha$; in the second $\alpha^{p^2}=(1-\alpha)^p=1-\alpha^p=1-(1-\alpha)=\alpha$. +Finally $\alpha\neq0$ because $0^2\ne0+1$, and cancelling $\alpha$ from $\alpha^{p^2}=\alpha$ gives $\alpha^{p^2-1}=1$. +\end{proof} + +\begin{lemma}\label{lem:coprime} +Let $n>1$ be odd and let $p$ be its least prime factor. Then $\gcd(n,p^2-1)=1$. +\end{lemma} + +\begin{proof} +Write $p=r+1$, so $r\ge1$, $r$ is even (as $p$ is odd), and $p^2-1=r(r+2)$. +Let $q$ be a prime dividing both $n$ and $r(r+2)$. Then $q\ge p=r+1$, and $q$ is odd because $n$ is. +If $q\mid r$ then $q\le r$, which is impossible. +If $q\mid r+2$ then $q\le r+2$, so $q=r+1$ or $q=r+2$. +In the first case $r+1$ divides $(r+2)-(r+1)=1$, so $r=0$, a contradiction; in the second $q=r+2$ is even, a contradiction. +\end{proof} + +\begin{lemma}\label{lem:core} +Let $K$ be a field of prime characteristic $p\notin\{2,5\}$, let $\alpha\in K$ with $\alpha^2=\alpha+1$, and let $N$ be an odd natural number with $\gcd(N,p^2-1)=1$. Then $\alpha^{2N}+(1-\alpha)^{2N}\ne1$. +\end{lemma} + +\begin{proof} +Suppose $\alpha^{2N}+(1-\alpha)^{2N}=1$ and put $x=\alpha^{2N}$, $x'=(1-\alpha)^{2N}$. +By Lemma~\ref{lem:ring}(2), $xx'=(\alpha(1-\alpha))^{2N}=(-1)^{2N}=1$. Hence +\[ + x^2-x+1=x(x+x'-1)-(xx'-1)=0, +\] +and $x^3+1=(x+1)(x^2-x+1)=0$, that is $\alpha^{6N}=-1$ and $\alpha^{12N}=1$. +Let $d$ be the multiplicative order of $\alpha$, which is finite by Lemma~\ref{lem:frob}. +Then $d\mid 12N$, and $d\mid p^2-1$ by Lemma~\ref{lem:frob}; since $\gcd(N,p^2-1)=1$ we get $\gcd(d,N)=1$ and hence $d\mid 12$, i.e.\ $\alpha^{12}=1$. +Writing $N=2t+1$, we obtain $-1=\alpha^{6N}=(\alpha^{12})^t\alpha^6=\alpha^6$. +By Lemma~\ref{lem:ring}(1), $\alpha^6=F_6\alpha+F_5=8\alpha+5$, so $8\alpha=-6$. +Using $\alpha^2=\alpha+1$ we compute $64\alpha^2$ in two ways: +$64\alpha^2=(8\alpha)^2=36$ and $64\alpha^2=8\cdot(8\alpha)+64=-48+64=16$. +Hence $20=0$ in $K$, so $p\mid20$ and $p\in\{2,5\}$, a contradiction. +(The Lean proof obtains $20=0$ in one step from the identity +$20=(14-8X)(X^6+1)+(8X^5-6X^4+2X^3-4X^2-2X-6)(X^2-X-1)$ in $\Z[X]$, evaluated at $X=\alpha$.) +\end{proof} + +\subsection{\texorpdfstring{Proof of Theorem~\ref{thm:main}}{Proof of Theorem 1}}\label{sec:assembly} +Let $n\ge2$ and suppose that $S(n)=k\in\Z$. By Lemma~\ref{lem:reduce}, $T(n)=2nk+1$. + +\emph{Case $n$ even.} Write $n=2t$. Then $T(n)=4tk+1\equiv1\pmod4$, contradicting Lemma~\ref{lem:mod4}. + +\emph{Case $n$ odd.} Let $p$ be the least prime factor of $n$; then $p\ne2$. + +\emph{Subcase $p=5$.} Take $R=\Z/5\Z$, whose characteristic $5$ divides $n$, so $T(n)=1$ in $\Z/5\Z$ by Lemma~\ref{lem:reduce}. +The element $\alpha=3$ satisfies $\alpha^2=9=4=\alpha+1$ in $\Z/5\Z$, and $1-\alpha=-2=3$. +By Lemma~\ref{lem:ring}(3) and since $3^2=-1$ and $n$ is odd, +$T(n)=3^{2n}+3^{2n}=2\,(3^2)^n=2\,(-1)^n=-2=3$ in $\Z/5\Z$. As $3\ne1$ in $\Z/5\Z$, this is a contradiction. + +\emph{Subcase $p\ne5$.} Let $K$ be an algebraic closure of $\Z/p\Z$; it is a field of characteristic $p$. +Choose $s\in K$ with $s^2=5$ (Mathlib's \decl{IsAlgClosed.exists_eq_mul_self}); since $p\ne2$, $2\ne0$ in $K$, and $\alpha=(1+s)/2$ satisfies +$\alpha^2=(6+2s)/4=\alpha+1$. +By Lemma~\ref{lem:ring}(3) and Lemma~\ref{lem:reduce} applied to $R=K$, $\alpha^{2n}+(1-\alpha)^{2n}=T(n)\cdot1_K=1$. +But $n$ is odd and $\gcd(n,p^2-1)=1$ by Lemma~\ref{lem:coprime}, so Lemma~\ref{lem:core} with $N=n$ shows that $\alpha^{2n}+(1-\alpha)^{2n}\ne1$, a contradiction. + +In all cases the assumption $S(n)\in\Z$ is contradictory, which proves Theorem~\ref{thm:main}.\qed + +\begin{remark} +The prime $p=3$ needs no separate treatment: it is covered by the last subcase. +The prime $p=5$ must be treated separately, because $X^2-X-1=(X-3)^2$ over $\F_5$ and $20=0$ in characteristic $5$, so Lemma~\ref{lem:core} gives nothing. +The algebraic closure is used only to provide a square root of $5$; the field $\F_{p^2}$ would suffice. +By \eqref{eq:lucas}, Theorem~\ref{thm:main} is equivalent to the assertion that no even $N\ge4$ divides $L_N-1$, which is exactly the theorem that Lucas pseudoprimes are odd \cite{WHD,DP,Br}, since the even composite numbers are the even numbers $N\ge4$. So the argument above is also a proof of that theorem; we have not compared it with the published proofs. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is the file \path{lean/Math0/Frontier/OEIS/A175385.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. +It imports the frozen statement file of Section~\ref{sec:statement} and the audit commands of \path{lean/Math0/Audit.lean}. +Its only public declaration is \texttt{theorem result : statement} in the namespace \decl{Math0.Frontier.A175385}, so \decl{Math0.Frontier.A175385.result} has type exactly \decl{Math0.Statements.A175385.statement}. +All auxiliary lemmas are \texttt{private}. They correspond to Section~\ref{sec:proof} as follows: +\begin{center} +\small +\begin{tabular}{ll} +Lemma~\ref{lem:diag} & \decl{fib_succ_eq_sum_range}, \decl{fib_succ_eq_sum_range'}\\ +Lemma~\ref{lem:term} & \decl{term_identity}\\ +Proposition~\ref{prop:closed} & \decl{S_succ}, \decl{main_identity}\\ +Lemma~\ref{lem:ring} & \decl{pow_eq_fib}, \decl{lucas}\\ +Lemma~\ref{lem:mod4} & \decl{fib_add_six_mod}, \decl{fib_mod_four}, \decl{T_mod_four}\\ +Lemma~\ref{lem:frob} & \decl{frob}\\ +Lemma~\ref{lem:coprime} & \decl{coprime_minFac}\\ +Lemma~\ref{lem:core} & \decl{field_part}, \decl{prime_dvd_twenty}\\ +Lemma~\ref{lem:reduce}, Section~\ref{sec:assembly} & \decl{result} (with the local fact \decl{key}) +\end{tabular} +\end{center} +The least prime factor is Mathlib's \decl{Nat.minFac}, the characteristic is expressed by the class \decl{CharP}, the algebraic closure is \texttt{AlgebraicClosure (ZMod p)}, and the multiplicative order is \decl{orderOf}. +The Frobenius step uses \decl{add_pow_char} and \decl{sub_pow_char} directly, with no appeal to the cardinality of a finite field. +The finite computations are all small: $F_5=5$ and $F_6=8$ in \decl{fib_add_six_mod} (by \texttt{rfl}); the residues $F_j\bmod4$ for $j\le5$ in \decl{T_mod_four}, and $3^2=3+1$, $1-3=3$, $3^2=-1$ and $-1+(-1)\ne1$ in $\Z/5\Z$ (by \texttt{decide}); and the primes dividing $20$ in \decl{prime_dvd_twenty} (by \texttt{interval\_cases}). +The file uses no \texttt{sorry}, \texttt{native\_decide}, \texttt{set\_option}, new axioms or new syntax. + +\subsection*{Audit} +The file ends with the command \texttt{\#math0\_settles}, applied to \decl{Math0.Frontier.A175385.result} and \decl{Math0.Statements.A175385.statement}; this command is defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself. +It fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} introduced by \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the constant \decl{statement} or its negation, after removing metadata annotations and without unfolding. +On this file it reports +\begin{lstlisting} +math0 audit: 'Math0.Statements.A175385.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A175385.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A175385.result' proves 'Math0.Statements.A175385.statement' +\end{lstlisting} +The SHA-256 hash of the statement file is unchanged from the value recorded when it was frozen. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use, since the statement is not part of formal-conjectures. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. +The single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A175385.lean} in the directory \path{lean}; this takes a few minutes on our machine, most of it spent loading Mathlib. + +\begin{thebibliography}{99} + +\bibitem{Ad} +T.~Adamczewski, \emph{OEIS Open: How many conjectures can language models turn into theorems?}, arXiv:2608.11941, 2026. + +\bibitem{Br} +P.~S. Bruckman, \emph{Lucas pseudoprimes are odd}, Fibonacci Quart. \textbf{32} (1994), no.~2, 155--157. + +\bibitem{DP} +A.~Di Porto, \emph{Nonexistence of even Fibonacci pseudoprimes of the 1st kind}, Fibonacci Quart. \textbf{31} (1993), no.~2, 173--177. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{APN} +Google DeepMind, \emph{AlphaProof Nexus: A175386 Lean file}, \url{https://github.com/google-deepmind/alphaproof-nexus-results/blob/main/APNOutputs/OEIS/oeis_175386_conjecture_0.lean}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A000032} +The OEIS Foundation Inc., \url{https://oeis.org/A000032} (Lucas numbers). + +\bibitem{A005845} +The OEIS Foundation Inc., \url{https://oeis.org/A005845} (Bruckman--Lucas pseudoprimes). + +\bibitem{A175385} +The OEIS Foundation Inc., \url{https://oeis.org/A175385}, entry by V.~Shevelev and Z.~Seidov (2010). + +\bibitem{A175386} +The OEIS Foundation Inc., \url{https://oeis.org/A175386}, entry by Z.~Seidov and V.~Shevelev (2010), comment by R.~Stephan (2026). + +\bibitem{Ts} +G.~Tsoukalas et al., \emph{Advancing Mathematics Research with AI-Driven Formal Proof Search}, arXiv:2605.22763, 2026. + +\bibitem{WHD} +D.~J. White, J.~N. Hunt, and L.~A.~G. Dresel, \emph{Uniform Huffman sequences do not exist}, Bull. London Math. Soc. \textbf{9} (1977), no.~2, 193--198. + +\end{thebibliography} + +\end{document} diff --git a/results/oeis-a176206/README.md b/results/oeis-a176206/README.md new file mode 100644 index 0000000..41b1c5a --- /dev/null +++ b/results/oeis-a176206/README.md @@ -0,0 +1,36 @@ +# Divisors of the terms of row n of A176206 are the parts of the partitions of n + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A176206 +**Date:** 2026-10-24 + +## Result + +Row n of A176206 lists n - k repeated p(k) times for k = 0, ..., n-1, where p is the partition function. Pol's conjecture says that for every n >= 1, the multiset of all divisors of all terms of row n equals the multiset of all parts of all partitions of n. Divisors and parts are counted with multiplicity: each term t of the row contributes each divisor of t once, and each partition contributes all of its parts. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A176206](https://oeis.org/A176206) as [`Math0.Statements.A176206.statement`](../../lean/Math0/Statements/OEIS/A176206.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A176206.lean`](../../lean/Math0/Frontier/OEIS/A176206.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C Conjecture: all divisors of all terms in row n are also all parts of all partitions of n. (Omar E. Pol, Nov 2020) + +Referees: OEIS A066633 (number of k's in all partitions of n): g.f. x^k/(1-x^k)*Prod 1/(1-x^m) by V. Jovovic (Jan 2002); T(n,k) = Sum_{j0}p(n-jk)=\sum_{0\le i List.replicate (f k) (n - k) + +def row (n : ℕ) : List ℕ := rowOf p n + +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + (row n : Multiset ℕ).bind (fun t => t.divisors.val) = + (Finset.univ : Finset n.Partition).val.bind (fun π => π.parts) +\end{lstlisting} +In Mathlib, \texttt{Nat.Partition n} is the finite type of partitions of $n$, each given by a multiset \texttt{parts} of positive integers with sum $n$. So \texttt{p k} is $p(k)$, and \texttt{row n} is $R_n$: the concatenation over $k pb k k)}, both data theorems are proved by \texttt{decide +kernel}: the kernel evaluates the terms and compares them with the listed values. +The right side $\Pi_n$ is not evaluated in the kernel (enumerating \texttt{Nat.Partition n} is too slow), and the proof below does not use these checks. + +\section{Proof}\label{sec:proof} + +We follow the declarations of the Lean file (namespace \decl{Math0.Frontier.A176206}). +For $d,t\in\N$ let $c(d,t)$ be the multiplicity of $d$ in the multiset of divisors of $t$ (\texttt{c d t := t.divisors.val.count d}), and for $d,n\in\N$ let +\[ + F(d,n)=\sum_{\pi\vdash n}m_d(\pi),\qquad H(d,n)=\sum_{k=0}^{n-1}p(k)\,c(d,n-k). +\] + +\begin{lemma}[\decl{c_eq}]\label{lem:c} +$c(d,t)=1$ if $d\mid t$ and $t\neq0$, and $c(d,t)=0$ otherwise. +\end{lemma} + +\begin{proof} +By \decl{Nat.mem_divisors}, $d$ lies in the finset of divisors of $t$ exactly when $d\mid t$ and $t\ne0$, and the multiset underlying a finset has no repeated elements. +\end{proof} + +\begin{lemma}[\decl{lhs_count}]\label{lem:lhs} +For all $d,n\in\N$, the multiplicity of $d$ in $\Delta_n$ is $H(d,n)$, and the multiplicity of $d$ in $\Pi_n$ is $F(d,n)$. +\end{lemma} + +\begin{proof} +The multiplicity of $d$ in $\sum_{t\in s}f(t)$ is $\sum_{t\in s}(\text{multiplicity of $d$ in } f(t))$ (\decl{Multiset.count_bind}). +For $\Pi_n$ this is $\sum_{\pi\vdash n}m_d(\pi)=F(d,n)$, which in Lean holds by definition. +For $\Delta_n$ it is the sum of $c(d,t)$ over the entries $t$ of the list $R_n$. The list $R_n$ is the concatenation of blocks, the $k$-th block consisting of $p(k)$ copies of $n-k$, which contributes $p(k)\,c(d,n-k)$; summing over $k ?_ + rw [Multiset.count_bind, Multiset.count_bind, lhs_count, ← F_eq_H] + rfl + +#math0_settles Math0.Frontier.A176206.result Math0.Statements.A176206.statement +\end{lstlisting} +\end{minipage} +The file contains no \texttt{sorry}, \texttt{native\_decide}, \texttt{set\_option} or macros, and, unlike the data checks of the statement file (which it does not use), the proof does not use \texttt{decide}. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which rejects \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} of \texttt{native\_decide}, and custom axioms; and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata, with no unfolding. +Running \texttt{lake env lean Math0/Frontier/OEIS/A176206.lean} in the directory \path{lean} prints\par\nobreak\vspace{4pt}\nobreak\noindent +\begin{minipage}{\linewidth} +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A176206.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A176206.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A176206.result' proves 'Math0.Statements.A176206.statement' +\end{lstlisting} +\end{minipage} +so \decl{result} proves the statement and depends only on the three permitted axioms. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root; it fetches the Mathlib build cache, rebuilds all math0 results (re-running every audit command), checks that the pinned dependencies are unmodified, and reports the number of passed statement checks. +For this result alone, run the \texttt{lake env lean} command above in \path{lean/} after building its imports with \texttt{lake build Math0.Statements.OEIS.A176206 Math0.Audit}. + +{\small +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{DS10} +M.~Ghosh Dastidar and S.~Sen Gupta, \emph{Extension of Stanley's theorem for partitions}, arXiv:1007.3459, 2010. + +\bibitem{DS11} +M.~Ghosh Dastidar and S.~Sen Gupta, \emph{Generalization of a few results in integer partitions}, arXiv:1111.0094, 2011. + +\bibitem{Haz16} +S.~Hazra, \emph{On Stanley's theorem and its generalizations}, arXiv:1610.01863, 2016. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Mer23} +M.~Merca, \emph{A note on a classical connection between partitions and divisors}, Ann. Acad. Rom. Sci. Ser. Math. Appl. \textbf{15} (2023), no.~1--2, 163--174, \url{https://doi.org/10.56082/annalsarscimath.2023.1-2.163}. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A000041} +The OEIS Foundation Inc., \url{https://oeis.org/A000041} (partition numbers), entry by N.~J.~A. Sloane. + +\bibitem{A000070} +The OEIS Foundation Inc., \url{https://oeis.org/A000070} (partial sums of A000041), entry by N.~J.~A. Sloane. + +\bibitem{A066633} +The OEIS Foundation Inc., \url{https://oeis.org/A066633} (number of $k$'s in all partitions of $n$), entry by N.~Nomoto, Jan.~9, 2002. + +\bibitem{A176206} +The OEIS Foundation Inc., \url{https://oeis.org/A176206}, entry by A.~Arnold, Apr.~11, 2010; name and conjecture by O.~E. Pol, Nov.~22--23, 2020; revision \#107, Jun.~4, 2022. + +\bibitem{A336811} +The OEIS Foundation Inc., \url{https://oeis.org/A336811}, entry by O.~E. Pol, Nov.~20, 2020. + +\bibitem{A338156} +The OEIS Foundation Inc., \url{https://oeis.org/A338156}, entry by O.~E. Pol, Oct.~14, 2020. + +\bibitem{A340061} +The OEIS Foundation Inc., \url{https://oeis.org/A340061}, entry by O.~E. Pol, Dec.~28, 2020. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a178295/README.md b/results/oeis-a178295/README.md new file mode 100644 index 0000000..936e0b3 --- /dev/null +++ b/results/oeis-a178295/README.md @@ -0,0 +1,56 @@ +# A178295: collinear 4-subsets of {0,...,4}^n number 9^n/2 + 3*7^n/2 - 2*5^n (Mathar's conjecture, all three formulas) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A178295 +**Date:** 2026-10-24 + +## Result + +Let a(n) be the number of 4-element subsets of the grid {0,...,4}^n whose points lie on one line. Collinearity means that all 2x2 minors of the difference vectors vanish. Then three things hold. (1) a(n) = 9^n/2 + 3*7^n/2 - 2*5^n for every n >= 0. (2) a(n) = 21 a(n-1) - 143 a(n-2) + 315 a(n-3) for every n >= 3. (3) As formal power series over Q, sum a(n) x^n = x(-5+41x) / ((9x-1)(7x-1)(5x-1)). + +## Assessment + +Any line meeting {0,...,4}^n in 4 or more points has a primitive direction in {0,±1}^n, because a coordinate step of 2 or more allows at most 3 points. So a collinear 4-set is either 4 consecutive points on such a line, which Golomb-Hales word counting gives as (9^n-5^n)/2 (9 choices per coordinate, not all constant, up to reversal), or one of the 3 non-consecutive 4-subsets of a full 5-point line, giving 3(7^n-5^n)/2. The recurrence and generating function then follow mechanically from the closed form. This is a standard argument of under a page, an easy variant of the classical count; the manuscript itself calls it short and elementary. The formalized route through a finite classification of columns is formalization engineering, not a new mathematical idea. + +*Follows from:* The classical tic-tac-toe line count ((k+2)^n - k^n)/2 for the grid {0,...,k-1}^n (Erdos-Selfridge 1973; Golomb-Hales 2002, Theorem 1; Moser's word-counting proof). With k=5 this gives the (7^n-5^n)/2 full lines, which is OEIS A081200. The same word-counting method gives (9^n-5^n)/2 runs of four consecutive collinear points. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A178295](https://oeis.org/A178295) as [`Math0.Statements.A178295.statement`](../../lean/Math0/Statements/OEIS/A178295.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A178295.lean`](../../lean/Math0/Frontier/OEIS/A178295.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: a(n) = 9^n/2+3*7^n/2-2*5^n. a(n)= +21*a(n-1) -143*a(n-2) +315*a(n-3). G.f.: x*(-5+41*x)/((9*x-1)*(7*x-1)*(5*x-1)). [_R. J. Mathar_, May 24 2010] + +Referees: No published resolution of the A178295 formula was found. Local mirror oeisdata seq/A178/A178295.seq (%I #15, Jul 22 2025): the formula is still labelled "Conjecture [R. J. Mathar, May 24 2010]", with no %E lines and no cross-references to it. + +Related sources: +- **R. J. Mathar, "Points on a line in the finite d-dimensional simple cubic lattice"** (oeis.org/A178294/a178294.pdf). Its abstract calls it a "mostly speculative summary", fitting Hardin's tables to Ehrhart polynomials. I saw only search snippets and an independent report, not the full text: the mirror has only an LFS pointer, and oeis.org and the Wayback Machine were inaccessible. +- **the-omega-institute/trureturing, GitHub issue #7376 (Sep 12–13, 2026).** A Lean proof of sibling A178294 (triples in the 4^n grid). Its literature check found "no proof or refutation as of 2026-09-13" and says the Mathar PDF gives the formula only as a fit. It does not mention A178295. +- **Classical full-line count ((k+2)^n - k^n)/2**, which gives the (7^n-5^n)/2 ingredient (A081200, itself still labelled a Hardin conjecture in OEIS): + - P. Erdős and J. L. Selfridge, J. Combin. Theory Ser. A 14 (1973) 298-301. + - S. W. Golomb and A. W. Hales, "Hypercube Tic-Tac-Toe", MSRI Publ. 42 (2002), Theorem 1. + - L. Moser's proof, via Honsberger. + - O. Patashnik, Math. Mag. 53 (1980). +- **Same-batch siblings, still labelled conjectures:** A081199, A081200, A081201, A178294, A178296-A178299. +- **Checked, no relevant result:** arXiv:2609.25133 (Kudriashov, Sep 2026), arXiv:2404.02369, arXiv:1107.0327. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a178295, + author = {{math0}}, + title = {{A178295: collinear 4-subsets of {0,...,4}^n number 9^n/2 + 3*7^n/2 - 2*5^n (Mathar's conjecture, all three formulas)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a178295}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a178295/paper.pdf b/results/oeis-a178295/paper.pdf new file mode 100644 index 0000000..44cfa79 Binary files /dev/null and b/results/oeis-a178295/paper.pdf differ diff --git a/results/oeis-a178295/paper.tex b/results/oeis-a178295/paper.tex new file mode 100644 index 0000000..2be92e4 --- /dev/null +++ b/results/oeis-a178295/paper.tex @@ -0,0 +1,350 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,noncomputable}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {ℝ}{{$\mathbb{R}$}}1 + {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {∈}{{$\in$}}1 {→}{{$\to$}}1 {↔}{{$\leftrightarrow$}}1 + {∧}{{$\wedge$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {⁻¹}{{$^{-1}$}}2 {↪}{{$\hookrightarrow$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\R}{\mathbb{R}} +\newcommand{\cQ}{\mathcal{Q}} +\newcommand{\cK}{\mathcal{K}} +\newcommand{\cC}{\mathcal{C}} + + +\title[Collinear four-point subsets of $\{0,\dots,4\}^n$]{Collinear four-point subsets of the grid $\{0,1,2,3,4\}^n$: a proof of Mathar's formulas for OEIS A178295} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the number of $4$-element subsets of the grid $\{0,1,2,3,4\}^n\subset\R^n$ that lie on a line. We prove that $a(n)=9^n/2+3\cdot7^n/2-2\cdot5^n$ for every $n\ge0$, together with the recurrence $a(n)=21a(n-1)-143a(n-2)+315a(n-3)$ for $n\ge3$ and the generating function $x(-5+41x)/((9x-1)(7x-1)(5x-1))$; these three formulas were conjectured by R.~J. Mathar in OEIS A178295 in 2010. +The proof writes an ordered collinear $4$-tuple as $n$ columns in $\{0,\dots,4\}^4$ that are pairwise affinely related, and a finite classification of the $120$ injective columns into $12$ classes of size $4$ and $36$ classes of size $2$ gives $24\,a(n)=12(9^n-5^n)+36(7^n-5^n)$. +We found no earlier proof and classify the result as new, although it is elementary and close to the classical count of lines in $n$-dimensional tic-tac-toe. +The theorem is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, with the finite facts about columns checked by kernel evaluation. +\end{abstract} +\maketitle + +\section{Introduction} + +Let $G_n=\{0,1,2,3,4\}^n\subset\R^n$. A set $S\subseteq\R^n$ is \emph{collinear} if it is contained in an affine line. Let $\cQ_n$ be the set of collinear $4$-element subsets of $G_n$ and $a(n)=|\cQ_n|$. +The OEIS entry A178295 \cite{A178295}, contributed by R.~H. Hardin on May~24, 2010 at the suggestion of R.~J. Mathar on the Sequence Fans mailing list, lists +\[ +a(0),\dots,a(9)=0,\ 5,\ 64,\ 629,\ 5632,\ 48485,\ 410944,\ 3470549,\ 29389312,\ 250334405 . +\] +The same day Mathar recorded three conjectural formulas: a closed form, a linear recurrence of order $3$ and a rational generating function. In the current revision of the entry (\#15, July~22, 2025) they are still labelled as a conjecture. We prove all three (Theorem~\ref{thm:main}). +Related entries created the same day carry analogous conjectures of Mathar, among them A178294 \cite{A178294} (collinear triples in the grid of side $4$), A178296 \cite{A178296} ($5$-tuples, side $6$) and A178297 \cite{A178297} ($6$-tuples, side $7$). + +\subsection*{Prior work} +Mathar's manuscript \cite{Ma}, linked from A178294, fits Hardin's tables to Ehrhart polynomials; its abstract calls it a ``mostly speculative summary''. We could not obtain its full text. Our knowledge of it comes from search snippets of the abstract, seen by the math0 literature referee, and from the following report. +Issue \#7376 of the GitHub repository \texttt{the-omega-institute/trureturing} \cite{TRU} (opened September~12 and closed September~13, 2026) reports a Lean proof of Mathar's closed form for A178294, collinear triples in $\{0,1,2,3\}^n$. Its literature check found no earlier proof or disproof and describes \cite{Ma} as presenting the formula as a fit, without proof. It does not mention A178295. + +The count of \emph{full} lines is classical: the grid $\{0,\dots,k-1\}^n$, the board of $n$-dimensional tic-tac-toe of side $k$, has $((k+2)^n-k^n)/2$ lines containing $k$ grid points. Erd\H{o}s and Selfridge state this count \cite{ES}, Golomb and Hales prove it \cite[Theorem~1]{GH}, and Honsberger presents a proof due to L.~Moser \cite{Ho}; for $k=4$, $n=3$ it gives the $76$ winning lines of Qubic \cite{Pa}. For $k=5$ the count is $(7^n-5^n)/2$, OEIS A081200 \cite{A081200}, where Hardin's comment identifying the sequence with this count is also still labelled as a conjecture; math0 has formalized a proof of that identification separately. Mathar's closed form can be written as +\[ + a(n)=\frac{9^n-5^n}{2}+3\cdot\frac{7^n-5^n}{2}, +\] +and Remark~\ref{rem:geom} explains the two terms geometrically; a reader who knows the word-counting method of \cite{GH} can derive the formula quickly in this way. The math0 referees searched arXiv, MathOverflow, Mathematics Stack Exchange, the Sequence Fans mailing list and the tic-tac-toe literature, including \cite{GH}, and found no published statement of the number of collinear $4$-subsets, or of the term $(9^n-5^n)/2$, and no resolution of the conjecture. We therefore classify Theorem~\ref{thm:main} as a \emph{new result}, with two caveats: the argument is short and elementary, and the full text of \cite{Ma} could not be checked. + +Our proof, which is the one formalized, does not use the structure of lattice lines. It writes an ordered collinear $4$-tuple as $n$ columns in $\{0,\dots,4\}^4$, reduces collinearity to a pairwise relation between columns, and classifies the columns by a finite computation (Section~\ref{sec:proof}). + +\section{Statement}\label{sec:statement} + +\begin{theorem}\label{thm:main} +Let $a(n)$ be the number of collinear $4$-element subsets of $\{0,1,2,3,4\}^n\subset\R^n$. Then: +\begin{enumerate} +\item $a(n)=9^n/2+3\cdot7^n/2-2\cdot5^n$ for every $n\ge0$; +\item $a(n)=21\,a(n-1)-143\,a(n-2)+315\,a(n-3)$ for every $n\ge3$; +\item $\sum_{n\ge0}a(n)\,x^n=x(-5+41x)/\bigl((9x-1)(7x-1)(5x-1)\bigr)$ in the ring $\Q[[x]]$ of formal power series. +\end{enumerate} +\end{theorem} + +The entry A178295 \cite{A178295} (offset $0$) reads, verbatim (name, author and formula lines): +\begin{lstlisting}[language={},frame=none,basicstyle=\ttfamily\footnotesize,literate={}] +Number of collinear point 4-tuples in a 5 X 5 X 5 X... n-dimensional cubic grid. +_R. H. Hardin_, suggested by R. J. Mathar in the Sequence Fans Mailing List, May 24 2010 +Conjecture: a(n) = 9^n/2+3*7^n/2-2*5^n. a(n)= +21*a(n-1) -143*a(n-2) +315*a(n-3). G.f.: x*(-5+41*x)/((9*x-1)*(7*x-1)*(5*x-1)). [_R. J. Mathar_, May 24 2010] +\end{lstlisting} + +\subsection*{Lean formalization} +math0 formalized the statement in \path{lean/Math0/Statements/OEIS/A178295.lean}, namespace \decl{Math0.Statements.A178295}. The file was reviewed for fidelity, and its SHA-256 hash \texttt{70638d82\ldots bbcc412} recorded, before any proof attempt; the file has not changed since, and this hash is listed in \path{lean/Math0/Statements/FROZEN.sha256}. The definitions used by the statement, and the statement itself, are (verbatim; docstrings, the two decidability instances, which are obtained by \texttt{infer\_instance}, and auxiliary declarations are omitted): +\begin{lstlisting}[basicstyle=\ttfamily\footnotesize] +abbrev Pt (n : ℕ) := Fin n → Fin 5 +def coord {n : ℕ} (p : Pt n) (i : Fin n) : ℤ := ((p i : ℕ) : ℤ) +def Coll3 {n : ℕ} (p q r : Pt n) : Prop := + ∀ i j : Fin n, (coord q i - coord p i) * (coord r j - coord p j) = + (coord q j - coord p j) * (coord r i - coord p i) +def IsCollinear {n : ℕ} (s : Finset (Pt n)) : Prop := + ∀ p ∈ s, ∀ q ∈ s, ∀ r ∈ s, Coll3 p q r +def a (n : ℕ) : ℕ := + ((Finset.univ : Finset (Pt n)).powersetCard 4 |>.filter IsCollinear).card +def statement : Prop := + (∀ n : ℕ, (a n : ℚ) = 9 ^ n / 2 + 3 * 7 ^ n / 2 - 2 * 5 ^ n) ∧ + (∀ n : ℕ, 3 ≤ n → + (a n : ℤ) = 21 * (a (n - 1) : ℤ) - 143 * (a (n - 2) : ℤ) + 315 * (a (n - 3) : ℤ)) ∧ + PowerSeries.mk (fun n => (a n : ℚ)) = + PowerSeries.X * (-5 + 41 * PowerSeries.X) * + ((9 * PowerSeries.X - 1) * (7 * PowerSeries.X - 1) * (5 * PowerSeries.X - 1))⁻¹ +\end{lstlisting} + +\emph{Encoding.} The grid $G_n$ is \texttt{Pt n}; for $n=0$ it has one point. \texttt{Coll3 p q r} says that every $2\times2$ minor $(q-p)_i(r-p)_j-(q-p)_j(r-p)_i$ vanishes in $\Z$, and \texttt{IsCollinear s} requires this for all triples of points of $s$, repetitions allowed. The statement file proves \decl{isCollinear_iff_collinear}: \texttt{IsCollinear s} holds if and only if \texttt{Collinear ℝ (toReal '' s)}, where \decl{toReal} views a grid point as a point of $\R^n$ and Mathlib's \texttt{Collinear} says that the points lie on one affine line. ``Point $4$-tuples'' are read as unordered sets of four distinct points (\texttt{powersetCard 4}); the data force this reading, since $a(1)=5=\binom54$ and $a(2)=64=25+25+10+4$ counts the four-point subsets of the $5$ rows, the $5$ columns and the $2$ main diagonals, and the $4$ diagonals with exactly $4$ points. The closed form is stated in $\Q$, so the halves are exact, for all $n\ge0$ (the offset; the entry gives no range). The recurrence is stated in $\Z$ for $n\ge3$, where all indices are defined. The generating function uses Mathlib's inverse in $\Q[[x]]$; the denominator has constant coefficient $-1\ne0$, so this is the true quotient, and \decl{genFun_iff} restates the clause as $A(x)D(x)=x(-5+41x)$, where $A(x)=\sum a(n)x^n$ and $D(x)=(9x-1)(7x-1)(5x-1)$. + +\emph{Data check.} The definition of \texttt{a} is computable but too slow for the kernel. The statement file defines an evaluator \decl{fastA}, which, for each pair of points $p,q$ with $p$ before $q$ in a fixed list, adds $\binom m2$, where $m$ is the number of points after $q$ on the line $pq$, and proves $a(n)=\mathtt{fastA}(n)$ for every $n$ (\decl{a_eq_fastA}). The lemma \decl{a_data} checks $a(0),a(1),a(2)=0,5,64$ by \texttt{decide +kernel}. The evaluator does about $5^{3n}$ work, and a kernel evaluation of $a(3)$ with an evaluator of this kind ran out of memory, so only these three terms are kernel-checked against \texttt{a}. The lemmas \decl{closedForm_data} and \decl{recurrence_data} check that the transcribed closed form gives all ten listed terms and that these terms satisfy the transcribed recurrence; they concern the formulas, not \texttt{a}. Outside Lean, the math0 referees reproduced $a(1),\dots,a(5)=5,64,629,5632,48485$ by brute force. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file (Section~\ref{sec:lean}); each step names its Lean declaration. Write $[5]=\{0,1,2,3,4\}$ and $I=\{0,1,2,3\}$. + +\subsection{Columns and compatibility} +A \emph{column} is a map $u\colon I\to[5]$, written $u=(u_0,u_1,u_2,u_3)$ or as a word $u_0u_1u_2u_3$; let $\cK=[5]^I$ be the set of the $625$ columns and $\cC\subseteq\cK$ the set of constant columns. A column is \emph{injective} if its four entries are distinct. + +\begin{definition}[\decl{RR}] +Columns $u,w$ are \emph{compatible}, written $u\sim w$, if $(u_b-u_a)(w_c-w_a)=(w_b-w_a)(u_c-u_a)$ for all $a,b,c\in I$; that is, the four points $(u_a,w_a)\in\Z^2$ are collinear. +\end{definition} + +\begin{lemma}[\decl{RR_symm}, \decl{RR_const_right}, \decl{const_of_RR}, \decl{RR_trans}]\label{lem:alg} +Let $u,v,w,t\in\cK$. +\begin{enumerate} +\item If $u\sim w$ then $w\sim u$. +\item If $w$ is constant, then $u\sim w$. +\item If $w\sim t$, $w_a=w_b$ and $t_a\ne t_b$ for some $a,b\in I$, then $w$ is constant. +\item If $v_{a_0}\ne v_{b_0}$ for some $a_0,b_0\in I$, $v\sim u$ and $v\sim w$, then $u\sim w$. +\end{enumerate} +\end{lemma} + +\begin{proof} +(1) and (2) are immediate. (3) The instance $(a,b,c)$ of $w\sim t$ reads $0=(t_b-t_a)(w_c-w_a)$, and $t_b\ne t_a$, so $w_c=w_a$ for every $c$. +(4) Put $D=v_{b_0}-v_{a_0}\ne0$, $P=u_{b_0}-u_{a_0}$ and $R=w_{b_0}-w_{a_0}$. Subtracting the instances $(a_0,b_0,x)$ and $(a_0,b_0,y)$ of $v\sim u$ gives $D(u_y-u_x)=P(v_y-v_x)$ for all $x,y\in I$, and likewise $D(w_y-w_x)=R(v_y-v_x)$. Hence $D^2(u_b-u_a)(w_c-w_a)=PR\,(v_b-v_a)(v_c-v_a)=D^2(w_b-w_a)(u_c-u_a)$ for all $a,b,c$, and we cancel $D^2\ne0$ in $\Z$. +\end{proof} + +\subsection{The finite classification} +Let $r_1,\dots,r_{48}$ be the following injective columns (the list \decl{repL}): +$r_1,\dots,r_{12}$ are the $12$ permutations of $0123$ with first entry $0$ or $1$, in lexicographic order ($0123,\dots,1320$); +$r_{13},\dots,r_{48}$ are the $36$ injective columns $u$ whose entries include $0$ and $4$ and which are lexicographically smaller than $4-u=(4-u_a)_a$, in lexicographic order ($0124,\dots,2140$). +For $1\le k\le48$ let $A_k=\{w\in\cK: r_k\sim w\}$. + +\begin{lemma}[\decl{rep_injB}, \decl{rep_sep}, \decl{cover_check}, \decl{count_check}, \decl{const_check}]\label{lem:finite} +\leavevmode +\begin{enumerate} +\item Each $r_k$ is injective. +\item If $k\ne k'$ then $r_k\not\sim r_{k'}$. +\item Every injective column is compatible with some $r_k$. +\item $|A_k|=9$ for $k\le12$ and $|A_k|=7$ for $k>12$. +\item $|\cC|=5$. +\end{enumerate} +\end{lemma} + +\emph{The certificate.} In Lean each item is a closed decidable proposition proved by \texttt{decide +kernel}: the kernel itself reduces the Boolean test to \texttt{true}, with no compiled code and no extra axiom. The test \decl{RRb} evaluates the $64$ instances $(a,b,c)$ of the compatibility identity with the statement file's \decl{minorB}, which compares two sums of products in $\N$ (correct by \decl{minorB_iff}), and \decl{RRb_iff} proves that \decl{RRb} decides $\sim$. Items (3)--(5) run over the statement file's list \texttt{L 4} of all $625$ columns, which \decl{mem_L} and \decl{nodup_L} show to be complete and duplicate-free; \decl{card_filter_col} turns counts along \texttt{L 4} into cardinalities of finite sets. The kernel thus tests at most $48\cdot625$ pairs of columns per item. + +\begin{proof}[Proof by hand] +Lean uses only the computation. Let $u$ be injective. If $w=\alpha u+\beta$ with $\alpha,\beta\in\Q$, both sides of the identity defining $u\sim w$ equal $\alpha(u_b-u_a)(u_c-u_a)$, so $u\sim w$. Conversely, if $u\sim w$, the instances $(a_0,b_0,c)$ with $a_0\ne b_0$ fixed give $w=\alpha u+\beta$. So $A_u=\{w:u\sim w\}$ consists of the $5$ constant columns ($\alpha=0$) and of injective columns $\alpha u+\beta$ whose span $\max-\min$ is $|\alpha|$ times that of $u$; four distinct values in $[5]$ have span $3$ or $4$. +If $u$ has span $3$, its values are $m,\dots,m+3$ with $m\in\{0,1\}$, and $|\alpha|\in\{1,4/3\}$; $|\alpha|=4/3$ is impossible, since the entries of $w$ where $u$ takes the values $m$ and $m+1$ would differ by $4/3$. So $w\in\{u-m,\ u-m+1,\ m+3-u,\ m+4-u\}$. +If $u$ has span $4$, its values are $0 0, a(n) = 2n + ceil(sqrt(12n - 3)). This is Librandi's conjecture from 2017. + +## Assessment + +The walk is an explicit spiral. Ring m of vertices is visited during times 6m^2+2m to 6m^2+14m+7. Cell s of cell ring j becomes ON at time 6j^2 - 1 + 2s + c, where c (1 to 6) is one more than the number of ring corners passed so far. With n = 3j(j-1)+1+s we have 12n-3 = (6j-3)^2 + 12s, and checking which pair of consecutive squares this lies between gives ceil(sqrt(12n-3)) = 6j-3+c. Equivalently, the result is Harborth's known spiral-polyhex edge count combined with Euler's formula. That is about a page of standard counting. The long Lean proof (coordinates, case analysis over the six sides) is formalization effort, not a new idea. + +*Follows from:* Harborth's formula 3n + ceil(sqrt(12n-3)) for the minimal edge count of an n-cell polyhex (A135708), which spiral polyhexes attain (Harary-Harborth 1976). Together with Euler's formula this gives |V| = 2n + ceil(sqrt(12n-3)) + 1 for the n-cell spiral. The toothpick path at stage n covers exactly the spiral's vertices, so a(n) = |V| - 1. The ring-by-ring increments listed in A182618 lead to the same result. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A182617](https://oeis.org/A182617) as [`Math0.Statements.A182617.statement`](../../lean/Math0/Statements/OEIS/A182617.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A182617.lean`](../../lean/Math0/Frontier/OEIS/A182617.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A182617 Conjecture: a(n) = 2*n + ceiling(sqrt(12*n - 3)), for n > 0. - _Vincenzo Librandi_, Sep 20 2017 + +Referees: OEIS A182617 (rev #35, Sep 23 2025): the formula is still marked "Conjecture", with no %E lines recording a resolution. No other OEIS entry in the local mirror references A182617. Related known results: +- A135708, minimal edge count of an n-cell polyhex, 3n + ceil(sqrt(12n-3)), attributed to H. Harborth; Kupitz 1991. +- A135711, minimal polyhex perimeter, 2*ceil(sqrt(12n-3)). +- F. Harary and H. Harborth, "Extremal animals", J. Combin. Inform. System Sci. 1 (1976): spiral animals attain the minimum. +- G. Malen, É. Roldán and R. Toalá-Enríquez, "Extremal {p,q}-Animals", Ann. Comb. (2023), arXiv:2109.05331, Cor. 1.9. +- É. Roldán and R. Toalá-Enríquez, "Isoperimetric Formulas for Hyperbolic Animals", arXiv:2206.14910. +- A036496 (W. C. Yang): ceil(sqrt(12n-3)) for a triangular-lattice spiral. +- Applegate, Pol and Sloane, "The Toothpick Sequence and Other Sequences from Cellular Automata", Congr. Numer. 206 (2010), arXiv:1004.3036: background only, no formula for A182617. +None of these states or proves the A182617 formula. They imply it only together with the extra fact that the toothpick walk's vertex set at time a(n) equals the vertex set of the extremal n-cell spiral, which I found nowhere in print. + +## Citation + +```bibtex +@misc{math0:oeis-a182617, + author = {{math0}}, + title = {{The toothpick spiral around n hexagonal cells (A182617): a(n) = 2n + ceil(sqrt(12n - 3))}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a182617}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a188474/README.md b/results/oeis-a188474/README.md new file mode 100644 index 0000000..5932c53 --- /dev/null +++ b/results/oeis-a188474/README.md @@ -0,0 +1,47 @@ +# The row sums of the generalized Deutsch triangle A188474 are A137398 + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A188474 +**Date:** 2026-10-29 + +## Result + +Let T(n,k) = sum_{j=0}^{n-k+1} (j/(n+2-j)) C(n+2-j, n-k+1) C(n+2-j, k+1) 2^(j-1), computed in Q, for 0 <= k <= n. Let A137398(m) be the number of subsequences p of S = (0,1,...,2m-1) of length m with 0 in p such that, with q the complementary subsequence, no index i < m has the property that exchanging p(i) and q(i) leaves both p and q strictly increasing. Then for every n >= 0, sum_{k=0}^{n} T(n,k) = A137398(n+2). (This is Paul Barry's 2011 conjecture "Row sums are A137398(n+1)", in the current offset of A137398.) + +## Assessment + +The row sum collapses with one application of Vandermonde's identity to the sum of 2^(j-1)(j/N)C(2N,N-j) over j. The ballot formula turns this into a geometric series in x^2C(x)^2, and a few lines of algebra show it equals the generating function already printed in A137398, which matches Callan's path decomposition there. The Lean proof does more work, because it starts from A137398's combinatorial definition: it shows that a swap keeps both lists increasing exactly when the walk has a "hump", which is Callan's path model, and then counts with first-passage numbers. That is only a short observation plus formalization effort, so the mathematics is standard and fits in about a page. + +*Follows from:* Vandermonde's identity and the ballot/Lagrange formula (j/N)C(2N,N-j) = [x^N](xC(x)^2)^j give the row-sum g.f. x^2C^2/(1-2x^2C^2). That equals the g.f. 2x^2/(1-2x-4x^2+sqrt(1-4x)) stated in A137398 (%F), and also Callan's 2021 path decomposition F = x(C-1)+2x(C-1)F in A137398. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A188474](https://oeis.org/A188474) as [`Math0.Statements.A188474.statement`](../../lean/Math0/Statements/OEIS/A188474.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A188474.lean`](../../lean/Math0/Frontier/OEIS/A188474.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C A188474 Row sums are A137398(n+1) (conjecture). Diagonal sums are A188476. (_Paul Barry_, Apr 01 2011) + +Referees: No prior explicit resolution of Barry's conjecture found. The A188474 entry (local mirror, revision #6, Mar 30 2012) still marks the row-sum claim as "(conjecture)". The relevant prior material that makes it nearly immediate: +- **Callan's comment on OEIS A137398 (Nov 25 2021).** A137398 counts Grand Dyck paths starting with U with no peak at height 1 and no valley at height −1, with g.f. satisfying F = x(C−1)+2x(C−1)F. This is exactly the row-sum g.f. of A188474. +- **OEIS A137398 G.f. line.** 2x²/(1−2x−4x²+√(1−4x)), the same function after rationalizing; the original authors' recurrence a(n)=2a(n−1)+2a(n−2)+Σ C(k)a(n−k−1) is also on the entry. +- **OEIS A100754 (E. Deutsch).** Deutsch's g.f. tzr/(1−tzr) with the Narayana function r, from which Barry's r-family g.f. follows. +- **Goy & Shattuck, Carpathian Math. Publ. 15(2) (2023) 420–436, arXiv:2303.10223.** Thm 5 eq. (25) proves that a Fine-number determinant equals A137398, taking A137398's recurrence as its definition. It does not address A188474. + +Searches came up empty for arXiv, the web generally, and SeqFan (not specifically found or checked). They covered "A188474", "A137398", "generalized Deutsch triangle", the term string 1,2,7,22,74,252,875,3078, and Barry's Riordan/Pascal-like papers (JIS 2007, 2011, 2019; arXiv 2606.22070). + +## Citation + +```bibtex +@misc{math0:oeis-a188474, + author = {{math0}}, + title = {{The row sums of the generalized Deutsch triangle A188474 are A137398}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a188474}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a195249/README.md b/results/oeis-a195249/README.md new file mode 100644 index 0000000..06529c6 --- /dev/null +++ b/results/oeis-a195249/README.md @@ -0,0 +1,45 @@ +# 3 × 3 lower triangles with neighbours differing by at most two: a(n) = 1047 n - 1459 for n > 2 (A195249) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A195249 +**Date:** 2026-10-20 + +## Result + +Let a(n) be the number of fillings (x0,...,x5) of the six cells of the lower triangle of a 3 × 3 array (rows of lengths 1, 2, 3) with entries in {0,...,n}, such that any two king-adjacent cells (horizontal, vertical or diagonal neighbours) have entries differing by at most 2. The adjacent pairs are 0-1, 0-2, 1-2, 1-3, 2-3, 1-4, 2-4, 3-4, 2-5, 4-5. Then a(n) = 1047 n - 1459 for every n > 2. This is Hardin's empirical formula from OEIS A195249. + +## Assessment + +The proof uses one standard observation. Every entry lies within 4 of the apex, so fillings are translates of finitely many shapes. That makes a(n) affine in n beyond a small threshold, and a finite computation (T(8,4) = 1047 and a(3) to a(7)) supplies the slope and intercept. The manuscript itself says this is essentially Israel's bounded-span argument from the sibling sequence A195232. No new idea is needed: it is a short argument plus a direct computation, and the work beyond that is formalization. + +*Follows from:* The standard bounded-span (translation) argument, written down by Robert Israel (Nov 21 2017) for the sibling table A195232: any two cells of the triangle are joined by at most two neighbouring steps, so every valid filling spans at most 4. Hence a(n) = sum over s of N_s*(n+1-s), which is linear in n once n >= 3. A finite count of shapes (or of T(8,4) = 1047 plus a(3..7)) fixes the constants. This is also Hardin's 'Generalizing' remark in A195248 (slope = A195214(3)). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A195249](https://oeis.org/A195249) as [`Math0.Statements.A195249.statement`](../../lean/Math0/Statements/OEIS/A195249.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A195249.lean`](../../lean/Math0/Frontier/OEIS/A195249.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F Empirical: a(n) = 1047*n - 1459 for n>2. (R. H. Hardin, Sep 13 2011); %F Conjectures from Colin Barker, May 06 2018: G.f.: x*(64 + 601*x + 288*x^2 + 94*x^3) / (1 - x)^2. a(n) = 2*a(n-1) - a(n-2) for n>4. + +Referees: I found no prior proof of A195249 or of row 3 of A195248. The local OEIS mirror entries for A195249, A195248 and A195214 have no %E lines and still mark the formulas 'Empirical'. The closest prior work is Robert Israel's comment (Nov 21 2017) on the sibling sequence OEIS A195232 ('one or less' variant), which proves the analogous linearity in k with the same span argument; this is a direct template for the current proof. Israel's Ehrhart-polynomial comment on A195220 (Oct 06 2019) is related. Hardin's own 'Generalizing' note on A195248 gives no proof. Searches I checked that turned up nothing relevant: Dougherty-Bliss & Kauers, 'Hardinian Arrays', Electron. J. Combin. 31(2) P9 (arXiv:2309.00487), which treats a different Hardin family; Ekhad-Yang-Zeilberger arXiv:1707.04654, which treats Mathar's conjectures; and web, arXiv and MathOverflow searches for the formula, the A-numbers and the entry's name text. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a195249, + author = {{math0}}, + title = {{3 × 3 lower triangles with neighbours differing by at most two: a(n) = 1047 n - 1459 for n > 2 (A195249)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a195249}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a195249/paper.pdf b/results/oeis-a195249/paper.pdf new file mode 100644 index 0000000..88c38bb Binary files /dev/null and b/results/oeis-a195249/paper.pdf differ diff --git a/results/oeis-a195249/paper.tex b/results/oeis-a195249/paper.tex new file mode 100644 index 0000000..88d0138 --- /dev/null +++ b/results/oeis-a195249/paper.tex @@ -0,0 +1,365 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {↔}{{$\leftrightarrow$}}1 + {∧}{{$\wedge$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {∑}{{$\sum$}}1 {∈}{{$\in$}}1 + {×}{{$\times$}}1 {ˢ}{{$^{\mathrm{s}}$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\DeclareUrlCommand\decl{\urlstyle{tt}} +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\nr}{\approx} +\newcommand{\monus}{\mathbin{\dot{-}}} +\newcommand{\ind}[1]{[\,#1\,]} + +\title[Hardin's formula for OEIS A195249]{Lower triangles of a $3\times3$ array whose king-neighbours differ by at most two: proof of Hardin's formula $a(n)=1047n-1459$ (OEIS A195249)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the number of ways to fill the six cells of the lower triangle of a $3\times3$ array with integers in $\{0,\dots,n\}$ so that any two cells that are horizontal, vertical or diagonal neighbours receive entries differing by at most $2$; this is OEIS A195249. +We prove the formula $a(n)=1047n-1459$ for all $n>2$, which R.~H. Hardin recorded as empirical in 2011; the generating function and the recurrence conjectured by C.~Barker in 2018 follow at once. +The proof splits the count by the entry at the apex; since every entry lies within distance $4$ of the apex, the count for a fixed apex is invariant under raising the upper bound and under translation once the apex is far from both ends of the range, which reduces the formula to a finite computation. +To our knowledge this is the first proof (the OEIS entry still lists the formula as empirical), but the argument is routine: it is essentially the bounded-span argument given by R.~Israel in 2017 for a sibling table. +The theorem is verified in Lean~4 against a statement that math0 formalized from the OEIS entry and froze after a fidelity review, with definitions checked by the kernel against all $38$ listed terms; it is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +The sequence A195249 of the OEIS \cite{A195249} was contributed by R.~H. Hardin on September~13, 2011. Its offset is $1$, its first terms are $64, 729, 1682, 2729, 3776, 4823, 5870,\dots$, and its name reads +\begin{quote} +\small Number of lower triangles of a 3 X 3 0..n array with each element differing from all of its diagonal, vertical, antidiagonal and horizontal neighbors by two or less. +\end{quote} +It is row $3$ of Hardin's table A195248 \cite{A195248}, whose entry in row $m$ and column $k$ counts the lower triangles of an $m\times m$ array with entries in $0..k$ under the same condition (the OEIS quotations below call this entry \texttt{T(n,k)}; it is unrelated to the function $T(n,c)$ used in our proof). +Hardin recorded in A195249 the ``empirical'' formula $a(n)=1047n-1459$ for $n>2$, and in A195248 empirical linear formulas for rows $1$ to $7$ together with the remark \texttt{Generalizing, T(n,k) = A195214(n)*k + const(n) for k>2*n-4}. Here A195214 \cite{A195214} counts the same triangles with entries in $\Z$, two triangles that differ by a constant being counted once; A195214$(3)=1047$. +On May~6, 2018, C.~Barker added to A195249 a conjectured generating function and a conjectured recurrence (both quoted in Section~\ref{sec:statement}). +We prove Hardin's formula (Theorem~\ref{thm:main}) and deduce Barker's two conjectures (Corollary~\ref{cor:barker}). +Let $T(n,c)$ be the number of valid triangles with entries in $0..n$ and apex entry $c$. All their entries lie in $[c-4,c+4]$, so $T(n+1,c)=T(n,c)$ if $c+4\le n$, and $T(n+1,c+1)=T(n,c)$ if $c\ge4$ (Lemmas~\ref{lem:up}, \ref{lem:shift}). Hence $a(n)=a(n-1)+T(8,4)$ for $n\ge8$, and the computations $T(8,4)=1047$ and $a(3),\dots,a(7)$ complete the proof. + +\subsection*{Status and prior work} +The closest earlier work is a comment of Robert Israel, dated November~21, 2017, in the sibling table A195232 \cite{A195232}, where neighbouring entries differ by one or less: \texttt{Since elements of a solution differ by no more than n, T(n,k)-T(n,k-1) is constant for k >= n. This confirms the empirical formula: T(n,k) is a polynomial of degree 1 in k for k > n-3.} +Our proof applies the same bounded-span idea to row $3$ of A195248, with explicit thresholds and a finite computation. +In A195220 \cite{A195220}, which counts the triangles with entries in $\Z$, up to constants, when neighbours differ by $k$ or less (its column $2$ is A195214), Israel noted on October~6, 2019, that the count is an Ehrhart polynomial in $k$. +Dougherty-Bliss and Kauers \cite{DBK} proved several of Hardin's OEIS conjectures, among them formulas linear in one dimension of the array, for a different family of king-move arrays that Hardin contributed in 2014; their paper does not mention A195248 or A195249. +In the copy of the OEIS that we used (A195249 at revision \#9 of May~6, 2018), the entries A195249, A195248 and A195214 have no edit notes; the first two still mark their formulas as empirical or conjectural, as does the live entry A195249 as of October 2026, and A195214 contains no formula. The math0 referees found no proof in searches of the web, arXiv and MathOverflow for the formula, the A-numbers and the name of the entry. +The conjecture is not among the OEIS statements of the formal-conjectures repository \cite{FC}. +We therefore classify the result as \emph{new}, with the caveat that it is not new mathematics: given Israel's comment, what remains is to fix the thresholds and to carry out the finite computation, and the contribution of this note is a complete, machine-checked proof. + +\section{Statement}\label{sec:statement} + +\begin{definition}\label{def:main} +Number the six cells $(i,j)$, $0\le j\le i\le2$ (row $i$, column $j$), of the lower triangle of a $3\times3$ array as +\[ + \begin{aligned}&c_0=(0,0),\quad c_1=(1,0),\quad c_2=(1,1),\\ &c_3=(2,0),\quad c_4=(2,1),\quad c_5=(2,2),\end{aligned} + \qquad\text{with entries}\qquad + \begin{array}{ccc} x_0 & & \\ x_1 & x_2 & \\ x_3 & x_4 & x_5 \end{array} +\] +for a filling $x=(x_0,\dots,x_5)\in\N^6$. Two distinct cells are \emph{neighbours} if their rows and their columns each differ by at most $1$ (horizontal, vertical, diagonal and antidiagonal neighbours). The neighbouring pairs $\{k,l\}$ of indices are the ten pairs +\begin{equation}\label{eq:edges} + 01,\ 02,\ 12,\ 13,\ 23,\ 14,\ 24,\ 34,\ 25,\ 45 . +\end{equation} +For $x,y\in\N$ write $x\nr y$ if $|x-y|\le2$. A filling is \emph{valid} if $x_k\nr x_l$ for every neighbouring pair $\{k,l\}$, and $a(n)$ is the number of valid fillings in $\{0,\dots,n\}^6$. +\end{definition} + +The FORMULA section of A195249 \cite{A195249} contains, verbatim, Hardin's formula and Barker's conjectures: +\begin{quote}\small\ttfamily +Empirical: a(n) = 1047*n - 1459 for n>2.\\ +Conjectures from \_Colin Barker\_, May 06 2018: (Start)\\ +G.f.: x*(64 + 601*x + 288*x\^{}2 + 94*x\^{}3) / (1 - x)\^{}2.\\ +a(n) = 2*a(n-1) - a(n-2) for n>4.\\ +(End) +\end{quote} + +\begin{theorem}\label{thm:main} +For every integer $n\ge3$, $a(n)=1047n-1459$. +\end{theorem} + +The bound is sharp: $a(2)=3^6=729$, while $1047\cdot2-1459=635$. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A195249.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{ee654c51\ldots fe44c}) before any proof attempt. Its definitions and the statement read (verbatim; the header, the import, comments and docstrings, blank lines, two decidability instances, all theorems, the auxiliary definitions \decl{win}, \decl{lsum} and \decl{aL} (shown in Section~\ref{sec:proof}) and the two propositions recording Barker's conjectures are omitted): +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +namespace Math0.Statements.A195249 +open Finset +def cell : Fin 6 → ℕ × ℕ := ![(0, 0), (1, 0), (1, 1), (2, 0), (2, 1), (2, 2)] +def Adj (p q : ℕ × ℕ) : Prop := + p ≠ q ∧ p.1 ≤ q.1 + 1 ∧ q.1 ≤ p.1 + 1 ∧ p.2 ≤ q.2 + 1 ∧ q.2 ≤ p.2 + 1 +def near (x y : ℕ) : Prop := x ≤ y + 2 ∧ y ≤ x + 2 +def Valid (v : Fin 6 → ℕ) : Prop := ∀ i j : Fin 6, Adj (cell i) (cell j) → near (v i) (v j) +def a (n : ℕ) : ℕ := + ∑ x0 ∈ range (n + 1), ∑ x1 ∈ range (n + 1), ∑ x2 ∈ range (n + 1), ∑ x3 ∈ range (n + 1), + ∑ x4 ∈ range (n + 1), ∑ x5 ∈ range (n + 1), if Valid ![x0, x1, x2, x3, x4, x5] then 1 else 0 +def statement : Prop := ∀ n : ℕ, 2 < n → (a n : ℤ) = 1047 * n - 1459 +end Math0.Statements.A195249 +\end{lstlisting} +This encodes Definition~\ref{def:main}: \decl{cell} lists $c_0,\dots,c_5$, \decl{Adj} is the neighbour relation and \decl{near} is $\nr$ (both written without truncated subtraction), and \texttt{a n} is the six-fold sum over $\{0,\dots,n\}^6$ of the indicator of validity, i.e.\ the OEIS definition itself. The statement is cast to $\Z$, so $1047n-1459$ is not a truncated difference; it has exactly the hypothesis $n>2$ of the OEIS formula, and as the offset is $1$, the value $a(0)=1$ plays no role. Barker's conjectures are recorded in the same file as separate propositions (\decl{statementBarkerGF}, \decl{statementBarkerRec}), not proved in Lean here. +The file also proves the following sanity checks: \decl{cell_injective} and \decl{image_cell} (by \texttt{decide}) state that \decl{cell} lists each position $(i,j)$ with $j\le i<3$ exactly once; \decl{valid_iff} states that \texttt{Valid ![x0, x1, x2, x3, x4, x5]} is equivalent to the conjunction of the ten conditions \texttt{near xk xl} for the pairs \eqref{eq:edges}; \decl{a_small} states \texttt{a 1 = 64 ∧ a 2 = 729}, evaluated in the kernel straight from the definition (\texttt{decide +kernel}); and \decl{a_data} states that \texttt{(List.range 38).map (fun i => a (i + 1))} is the list of all $38$ terms $64,729,\dots,38327$ listed in the OEIS entry, evaluated in the kernel through the pruned copy \decl{aL} of Section~\ref{sec:proof} and the lemma \texttt{a\_eq\_aL (n : ℕ) : a n = aL n}. + +\section{Proof}\label{sec:proof} + +The proof follows \path{lean/Math0/Frontier/OEIS/A195249.lean}; we give the Lean name of each step. + +\subsection{Windows and the apex decomposition} +For $n,y\in\N$ let +\[ + W_n(y)=\{x\in\N : y\monus2\le x\le\min(y+2,n)\},\qquad y\monus 2=\max(y-2,0). +\] +Then $W_n(y)=\{x\in\{0,\dots,n\}: x\nr y\}$ (\decl{filter_near}). In Lean the window is the list \texttt{win n y} of consecutive integers from $y\monus 2$ to $\min(y+2,n)$, sums over lists are written with \decl{lsum}, and the statement file defines the pruned copy \decl{aL} of \decl{a}: +\begin{lstlisting} +def win (n y : ℕ) : List ℕ := List.range' (y - 2) (min (y + 2) n + 1 - (y - 2)) +def lsum (l : List ℕ) (f : ℕ → ℕ) : ℕ := l.foldr (fun x acc => f x + acc) 0 +def aL (n : ℕ) : ℕ := + lsum (List.range (n + 1)) fun x0 => + lsum (win n x0) fun x1 => + lsum (win n x0) fun x2 => if near x1 x2 then + lsum (win n x1) fun x3 => if near x2 x3 then + lsum (win n x1) fun x4 => if near x2 x4 ∧ near x3 x4 then + lsum (win n x2) fun x5 => if near x4 x5 then 1 else 0 + else 0 else 0 else 0 +\end{lstlisting} +For $n,c\in\N$ define, with $\ind{P}\in\{0,1\}$ the indicator of $P$, +\begin{multline}\label{eq:T} + T(n,c)=\sum_{x_1\in W_n(c)}\ \sum_{x_2\in W_n(c)}\ind{x_1\nr x_2}\sum_{x_3\in W_n(x_1)}\ind{x_2\nr x_3}\\ + \sum_{x_4\in W_n(x_1)}\ind{x_2\nr x_4,\ x_3\nr x_4}\sum_{x_5\in W_n(x_2)}\ind{x_4\nr x_5}. +\end{multline} +In Lean, \texttt{T n c} is literally the inner function of \decl{aL}. + +\begin{lemma}[\decl{a_eq_aL}, \decl{a_eq_sum}]\label{lem:sum} +For every $n$, $a(n)=\sum_{c=0}^{n}T(n,c)$, and $T(n,c)$ is the number of valid fillings $x\in\{0,\dots,n\}^6$ with $x_0=c$. +\end{lemma} + +\begin{proof} +By \decl{valid_iff}, validity is the conjunction of the ten conditions $x_k\nr x_l$ for the pairs \eqref{eq:edges}. Attach each condition to the larger index of its pair, so that $x_1,\dots,x_5$ carry $\{01\}$, $\{02,12\}$, $\{13,23\}$, $\{14,24,34\}$, $\{25,45\}$. In the six-fold sum defining $a(n)$, move each condition outwards to the sum over the variable carrying it (\decl{sum_pull}), and use the condition of $x_1,\dots,x_5$ with $x_0,x_0,x_1,x_1,x_2$ respectively to restrict the range $\{0,\dots,n\}$ of that variable to a window (\decl{sum_win}, \decl{sum_win_and}); the other conditions stay as indicators. This gives \eqref{eq:T} for the sum over $x_1,\dots,x_5$ with $x_0=c$ fixed, and is \decl{a_eq_aL} of the statement file; \decl{a_eq_sum} rewrites the outer list sum as $\sum_{c=0}^n$ (\decl{sum_range_eq_lsum}). +\end{proof} + +\begin{lemma}\label{lem:win} +Let $n,y,x\in\N$. +\begin{enumerate} +\item[(a)] \textup{(\decl{mem_win})} If $x\in W_n(y)$ then $y\monus2\le x\le y+2$ and $x\le n$. +\item[(b)] \textup{(\decl{win_succ_up})} If $y+2\le n$ then $W_{n+1}(y)=W_n(y)$. +\item[(c)] \textup{(\decl{win_succ_shift})} If $y\ge2$ then $W_{n+1}(y+1)=W_n(y)+1$, where $W_n(y)+1\coloneqq\{x+1: x\in W_n(y)\}$. +\item[(d)] \textup{(\decl{near_succ})} $x+1\nr y+1$ if and only if $x\nr y$. +\end{enumerate} +\end{lemma} + +\begin{proof} +(a) is the definition. For (b), $\min(y+2,n+1)=y+2=\min(y+2,n)$. For (c), $y\ge2$ gives $(y+1)\monus2=(y\monus2)+1$, and $\min(y+3,n+1)=\min(y+2,n)+1$; so both windows are intervals, the first being the second shifted by $1$. (d) is clear. In Lean, (b) and (c) are equalities of lists (for (c), \decl{List.map_add_range'}), so sums over the windows can be rewritten with them. +\end{proof} + +\subsection{Two stability properties} + +\begin{lemma}[upper stability, \decl{T_up}]\label{lem:up} +If $c+4\le n$ then $T(n+1,c)=T(n,c)$. +\end{lemma} + +\begin{proof} +Since $c+2\le n$, Lemma~\ref{lem:win}(b) gives $W_{n+1}(c)=W_n(c)$, so in \eqref{eq:T} for $T(n+1,c)$ the outer two sums run over the same windows as for $T(n,c)$. For $x_1,x_2\in W_n(c)$, Lemma~\ref{lem:win}(a) gives $x_1,x_2\le c+2$, hence $x_1+2\le n$ and $x_2+2\le n$, and Lemma~\ref{lem:win}(b) gives $W_{n+1}(x_1)=W_n(x_1)$ and $W_{n+1}(x_2)=W_n(x_2)$. Thus the inner sums also agree, term by term (\decl{lsum_congr}). +\end{proof} + +\begin{lemma}[translation, \decl{T_shift}]\label{lem:shift} +If $c\ge4$ then $T(n+1,c+1)=T(n,c)$. +\end{lemma} + +\begin{proof} +Since $c\ge2$, Lemma~\ref{lem:win}(c) gives $W_{n+1}(c+1)=W_n(c)+1$, so in \eqref{eq:T} for $T(n+1,c+1)$ we may substitute $x_1=x_1'+1$ and $x_2=x_2'+1$ with $x_1',x_2'\in W_n(c)$ (\decl{lsum_map_succ}). By Lemma~\ref{lem:win}(a), $x_1',x_2'\ge c-2\ge2$, so Lemma~\ref{lem:win}(c) gives $W_{n+1}(x_1'+1)=W_n(x_1')+1$ and $W_{n+1}(x_2'+1)=W_n(x_2')+1$, and we substitute $x_k=x_k'+1$ for $k=3,4,5$ as well. By Lemma~\ref{lem:win}(d), every indicator $\ind{x_k'+1\nr x_l'+1}$ equals $\ind{x_k'\nr x_l'}$, and the resulting expression is \eqref{eq:T} for $T(n,c)$. +\end{proof} + +Combinatorially (Lemma~\ref{lem:sum}), Lemma~\ref{lem:up} says that no valid filling with apex $c$ has an entry above $c+4$, and Lemma~\ref{lem:shift} that adding $1$ to every entry maps the valid fillings in $\{0,\dots,n\}^6$ with apex $c$ bijectively onto those in $\{0,\dots,n+1\}^6$ with apex $c+1$. + +\subsection{The finite computations} + +\begin{lemma}[\decl{T_eight}, \decl{T_four}, \decl{a_vals}]\label{lem:comp} +$T(8,4)=1047$, and hence $T(m+8,4)=1047$ for every $m\ge0$. Moreover $a(3)=1682$, $a(4)=2729$, $a(5)=3776$, $a(6)=4823$ and $a(7)=5870$. +\end{lemma} + +\begin{proof} +The values $T(8,4)$ and $a(3),\dots,a(7)$ (the latter as $\mathrm{aL}(3),\dots,\mathrm{aL}(7)$, by \decl{a_eq_aL}) are computed by \texttt{decide +kernel}. The second claim follows by induction on $m$ from Lemma~\ref{lem:up}, which applies since $4+4\le m+8$. +\end{proof} + +No certificate is involved: \texttt{decide +kernel} turns the \texttt{Decidable} instance into a proof that the kernel checks by reducing, e.g., \texttt{decide (T 8 4 = 1047)} to \texttt{true}, evaluating the nested sums \eqref{eq:T} with its built-in arithmetic on natural-number literals. Each window has at most $5$ elements, so $T(n,c)$ has at most $5^5=3125$ innermost terms. Unlike \texttt{native\_decide}, this trusts no compiled code and adds no axiom. + +\subsection{Constant first differences and the proof of Theorem~\ref{thm:main}} + +\begin{lemma}[\decl{step}]\label{lem:step} +For every $m\ge0$, $a(m+8)=a(m+7)+1047$. +\end{lemma} + +\begin{proof} +Put $N=m+8$. By Lemma~\ref{lem:sum}, +\[ + a(N)=\sum_{c=0}^{3}T(N,c)+T(N,4)+\sum_{c=5}^{N}T(N,c),\qquad + a(N-1)=\sum_{c=0}^{3}T(N-1,c)+\sum_{c=4}^{N-1}T(N-1,c) +\] +(\decl{split4}, \decl{Finset.sum_range_succ'}). For $c\le3$ we have $c+4\le7\le N-1$, so $T(N,c)=T(N-1,c)$ by Lemma~\ref{lem:up}. For $5\le c\le N$, Lemma~\ref{lem:shift} applied to $c-1\ge4$ gives $T(N,c)=T(N-1,c-1)$, so $\sum_{c=5}^{N}T(N,c)=\sum_{c=4}^{N-1}T(N-1,c)$. Finally $T(N,4)=1047$ by Lemma~\ref{lem:comp}. Hence $a(N)=a(N-1)+1047$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] (\decl{formula}, \decl{result}) +For $3\le n\le7$ the values of Lemma~\ref{lem:comp} agree with $1047n-1459$, which takes the values $1682, 2729, 3776, 4823, 5870$. For $n\ge7$ write $n=m+7$ and induct on $m$: the case $m=0$ is $a(7)=5870=1047\cdot7-1459$, and if $a(m+7)=1047(m+7)-1459$ then Lemma~\ref{lem:step} gives $a(m+8)=1047(m+8)-1459$. In Lean this induction is carried out in $\Z$. +\end{proof} + +\subsection{Consequences and a remark (not formalized)} + +\begin{corollary}[Barker's conjectures]\label{cor:barker} +For $n>4$, $a(n)=2a(n-1)-a(n-2)$, and +\[ + \sum_{n\ge1}a(n)x^n=\frac{x(64+601x+288x^2+94x^3)}{(1-x)^2}. +\] +\end{corollary} + +\begin{proof} +For $n\ge5$ the indices $n,n-1,n-2$ are at least $3$, so the recurrence holds because $a$ is affine there by Theorem~\ref{thm:main}. Multiplying the power series by $(1-x)^2$, the coefficient of $x^k$ is $a(k)-2a(k-1)+a(k-2)$ (with $a(0)$ and $a(-1)$ read as $0$), which is $64$, $729-128=601$, $1682-1458+64=288$, $2729-3364+729=94$ for $k=1,2,3,4$, and $0$ for $k\ge5$ by the recurrence. +\end{proof} + +The recurrence fails at $n=4$ ($2a(3)-a(2)=2635$). Corollary~\ref{cor:barker} is not formalized. + +\begin{remark}[shapes]\label{rem:shapes} +Call a valid filling with entries in $\Z$ and minimum $0$ a \emph{shape}, and its maximum its \emph{span}. Any two cells are joined by a chain of at most two neighbouring pairs, so every span is at most $4$, and a shape of span $s$ has $\max(0,n+1-s)$ translates in $\{0,\dots,n\}^6$. Hence $a(n)=\sum_{s=0}^{4}N_s\max(0,n+1-s)$, where $N_s$ is the number of shapes of span $s$. A computer enumeration (not part of the Lean development) gives $(N_0,\dots,N_4)=(1,62,602,288,94)$: there are $1047=\text{A195214}(3)$ shapes, of total span $2506$. For $n\ge3$ this gives again $a(n)=1047(n+1)-2506=1047n-1459$ (Israel's bounded-span argument; the slope is A195214$(3)$, as in Hardin's ``Generalizing'' remark); it also gives $\sum_{n\ge1}a(n)x^n=(1+62x+602x^2+288x^3+94x^4)/(1-x)^2-1$, Barker's generating function. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is the file \path{lean/Math0/Frontier/OEIS/A195249.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A195249.result}, of type \decl{Math0.Statements.A195249.statement}; all other declarations are \texttt{private}, among them the function \decl{T} (the inner function of \decl{aL}) and the lemmas \decl{a_eq_sum}, \decl{T_up}, \decl{T_shift}, \decl{T_eight}, \decl{T_four}, \decl{step}, \decl{a_vals} and \decl{formula}, whose statements are those of Section~\ref{sec:proof}. The proof of \decl{a_vals} is \texttt{simp only [a\_eq\_aL]} followed by \texttt{decide +kernel}, and neither file contains \texttt{sorry}, \texttt{native\_decide}, \texttt{axiom} or \texttt{set\_option}. Verbatim excerpts: +\begin{lstlisting} +private theorem T_eight : T 8 4 = 1047 := by + decide +kernel +theorem result : statement := ... +#math0_settles Math0.Frontier.A195249.result Math0.Statements.A195249.statement +\end{lstlisting} + +\subsection*{Audit} +The command \texttt{\#math0\_settles} (in \path{lean/Math0/Audit.lean}) fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (rejecting \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically \decl{statement} or its negation, up to metadata. It reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A195249.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A195249.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A195249.result' proves 'Math0.Statements.A195249.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, not used here. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib cache, builds all math0 results with \texttt{lake build} (re-running every audit), checks that the pinned dependencies are unmodified, and reports the number of passed statement checks. The proof file alone (\texttt{lake env lean} in \path{lean}) takes under half a minute of CPU time. + +{\footnotesize +\begin{thebibliography}{99} + +\bibitem{DBK} +R.~Dougherty-Bliss and M.~Kauers, \emph{Hardinian arrays}, Electron.\ J. Combin.\ \textbf{31}(2) (2024), Paper No.~P2.9; arXiv:2309.00487. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{A195214} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, \url{https://oeis.org/A195214}, entry by R.~H. Hardin (September~13, 2011). + +\bibitem{A195220} +The OEIS Foundation Inc., \url{https://oeis.org/A195220}, entry by R.~H. Hardin (September~13, 2011); comment by R.~Israel (October~6, 2019). + +\bibitem{A195232} +The OEIS Foundation Inc., \url{https://oeis.org/A195232}, entry by R.~H. Hardin (September~13, 2011); comment by R.~Israel (November~21, 2017). + +\bibitem{A195248} +The OEIS Foundation Inc., \url{https://oeis.org/A195248}, entry by R.~H. Hardin (September~13, 2011). + +\bibitem{A195249} +The OEIS Foundation Inc., \url{https://oeis.org/A195249}, entry by R.~H. Hardin (September~13, 2011); conjectures by C.~Barker (May~6, 2018); revision \#9, May~6, 2018. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a201060/README.md b/results/oeis-a201060/README.md new file mode 100644 index 0000000..a1eadb1 --- /dev/null +++ b/results/oeis-a201060/README.md @@ -0,0 +1,43 @@ +# Repdigits with repdigit digital product are repunits from a(16) = 1111 on (A201060) + +**Classification:** First formal proof of a known result +**Area:** Sequences and series +**Source problem:** OEIS A201060 +**Date:** 2026-10-20 + +## Result + +Let a(1) < a(2) < ... list the repdigits (all decimal digits equal; 0 counts) whose digital product is also a repdigit. Then a(n) is a repunit (all digits equal to 1) for every n >= 16. Formally: forall n >= 16, IsRepunit (a n), where a n = Nat.nth IsTerm (n - 1). + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A201060](https://oeis.org/A201060) as [`def statement`](../../lean/Math0/Statements/OEIS/A201060.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A201060.lean`](../../lean/Math0/Frontier/OEIS/A201060.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: a(n) is repunit for n >= 16." (A201060, entry by _Jaroslav Krizek_, Nov 26 2011) + +Referees: Main citations: +- R. Obláth, "Une propriété des puissances parfaites", Mathesis 65 (1956), 356–364. It shows that the only perfect powers with all decimal digits equal to some a != 1 are 4, 8 and 9. +- Y. Bugeaud and M. Mignotte, "On integers with identical digits", Mathematika 46 (1999), 411–417. It shows that no decimal repunit with two or more digits is a perfect power. +Together these say that no repdigit >= 10 is a perfect power, and the A201060 conjecture follows directly, since d^k >= 16 for 2 <= d <= 9 and k >= 4. + +Both results are restated in O. Kihel and F. Luca, "Perfect Powers With All Equal Digits But One", J. Integer Seq. 8 (2005), Article 05.5.7, Introduction (https://cs.uwaterloo.ca/journals/JIS/VOL8/Kihel/kihel7.html). See also A. Gica and L. Panaitopol, "On Oblath's Problem", J. Integer Seq. 6 (2003), Article 03.3.5, which is linked from OEIS A018885 and A368049. The Wikipedia article "Repdigit" (https://en.wikipedia.org/wiki/Repdigit) covers the related Nagell–Ljunggren equation and cites Bugeaud–Mignotte 2002. + +The OEIS entry A201060 (local mirror, revision #11, 2012) still labels the statement as a conjecture, and I found no web or arXiv discussion that names A201060. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a201060, + author = {{math0}}, + title = {{Repdigits with repdigit digital product are repunits from a(16) = 1111 on (A201060)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a201060}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a201060/paper.pdf b/results/oeis-a201060/paper.pdf new file mode 100644 index 0000000..63986f0 Binary files /dev/null and b/results/oeis-a201060/paper.pdf differ diff --git a/results/oeis-a201060/paper.tex b/results/oeis-a201060/paper.tex new file mode 100644 index 0000000..0cfc5db --- /dev/null +++ b/results/oeis-a201060/paper.tex @@ -0,0 +1,371 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,private,rw,apply,interval_cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {∈}{{$\in$}}1 {→}{{$\to$}}1 + {↔}{{$\leftrightarrow$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 + {¬}{{$\neg$}}1 {·}{{$\cdot$}}1 {←}{{$\leftarrow$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\rep}{\operatorname{rep}} +\newcommand{\dprod}{\operatorname{p}} + +\title[Repdigits with repdigit digital product (OEIS A201060)]{A repdigit with at least four digits whose digital product is a repdigit is a repunit: the conjecture in OEIS A201060} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + +\begin{document} +\begin{abstract} +Let $a(1)= 16.}} +\end{quote} +The entry gives no date for this comment; the entry itself is credited to Jaroslav Krizek, November~26, 2011. + +\begin{theorem}\label{thm:main} +For every $n\ge16$, $a(n)$ is a repunit. +\end{theorem} + +\begin{remark}\label{rem:closed} +Combined with the listed data, Theorem~\ref{thm:main} determines the sequence: the terms below $1111$ are $a(1),\dots,a(15)=0,1,\dots,9,11,22,33,111,222$, and every repunit $R_k$ with $k\ge4$ is a term, so $a(n)=R_{n-12}=(10^{n-12}-1)/9$ for all $n\ge16$. This closed form is not stated as a separate Lean declaration; its ingredients are Theorem~\ref{thm:main}, Lemma~\ref{lem:seq} and the fact that every repunit is a term. +\end{remark} + +\subsection*{Lean formalization} +The statement was formalized by math0 in the file \path{lean/Math0/Statements/OEIS/A201060.lean}, and was reviewed for fidelity and frozen (SHA-256 \texttt{902fc983\ldots 2af72b}) before any proof attempt. Its definitions and the statement read as follows (verbatim; the copyright header, the import, the module docstring, section headers, docstrings, blank lines, the two decidability instances, the auxiliary definitions \decl{rep}, \decl{repList} and \decl{listed}, and all theorems are omitted): +\begin{lstlisting} +namespace Math0.Statements.A201060 +def IsRepdigit (m : ℕ) : Prop := ∀ x ∈ Nat.digits 10 m, ∀ y ∈ Nat.digits 10 m, x = y +def digitProd (m : ℕ) : ℕ := if m = 0 then 0 else (Nat.digits 10 m).prod +def IsTerm (m : ℕ) : Prop := IsRepdigit m ∧ IsRepdigit (digitProd m) +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) +def IsRepunit (m : ℕ) : Prop := ∀ d ∈ Nat.digits 10 m, d = 1 +def statement : Prop := ∀ n : ℕ, 16 ≤ n → IsRepunit (a n) +end Math0.Statements.A201060 +\end{lstlisting} +Here \texttt{Nat.digits 10 m} is the list $\delta(m)$ of decimal digits of $m$, least significant first, with \texttt{Nat.digits 10 0 = []}; so \decl{IsRepdigit}, \decl{IsRepunit} and \decl{digitProd} are the notions of Definition~\ref{def:main}, and $0$ is a repdigit, as in A010785 and in the entry ($a(1)=0$). The convention $\dprod(0)=0$ follows A007954; the empty product $1$ would give the same sequence, since $0$ and $1$ are both repdigits. \decl{IsRepunit} also holds for $0$ (as A002275 includes $R_0=0$), which is irrelevant here because $a(n)\ge a(16)=1111$ for $n\ge16$. +\texttt{Nat.nth p k} is the $k$-th element, counting from $0$, of $\{m: p(m)\}$ in increasing order, so \decl{a} is the sequence of Definition~\ref{def:main} with the entry's offset $1$. When the set is infinite, \texttt{Nat.nth p} is strictly increasing and enumerates the whole set; the statement file proves that $S$ is infinite. The statement keeps the entry's range $n\ge16$ and adds no hypotheses. + +To compare the definitions with the OEIS data, the statement file introduces $\rep(d,k)=\sum_{i a (i + 1)) = + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 111, 222, 1111, 11111, 111111, 1111111, 11111111, + 111111111, 1111111111, 11111111111, 111111111111, 1111111111111, 11111111111111, + 111111111111111, 1111111111111111, 11111111111111111, 111111111111111111, + 1111111111111111111] +\end{lstlisting} +Here \texttt{repList L} is the explicit list consisting of $0$ and the numbers $\rep(d,k)$ with $1\le d\le9$, $1\le k\le L$; so \decl{isRepdigit_iff_mem_repList} says that the repdigits below $10^L$ are exactly $0$ and these numbers. +The theorem \decl{a_data} checks all $31$ listed terms. Its proof does not enumerate the numbers below $10^{19}$. Instead, the kernel filters the $1+9\cdot19=172$ elements of \texttt{repList 19} by the condition ``$\dprod(m)$ is a repdigit'' and checks that the result is the list of the $31$ listed terms, that every element of \texttt{repList 19} is below $10^{19}$, and that the listed terms are strictly increasing (three proofs by \texttt{decide +kernel}). By \decl{isRepdigit_iff_mem_repList} with $L=19$, the terms below $10^{19}$ and the listed terms then have the same elements; both lists are strictly increasing, so they are equal, and a general lemma (\decl{map_nth_eq_of_filter}) converts the statement about the sorted list of terms below $10^{19}$ into the values \texttt{Nat.nth IsTerm i} for $i<31$. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A201060.lean}; the name of the corresponding Lean declaration is given with each step. We write $\rep(e,j)$ as above and $R_j=\rep(1,j)$. + +\begin{lemma}[\decl{digits_rep}, \decl{rep_succ}, \decl{rep_eq_mul}, \decl{odd_rep_one}]\label{lem:rep} +For all $e,j\in\N$: +\begin{enumerate} +\item if $1\le e\le9$, the decimal digits of $\rep(e,j)$ are $j$ copies of $e$; +\item $\rep(e,j+1)=e+10\,\rep(e,j)$; +\item $\rep(e,j)=e\,R_j$; +\item $R_{j+1}$ is odd. +\end{enumerate} +\end{lemma} + +\begin{proof} +(1) holds because the digit list $(e,\dots,e)$ consists of digits less than $10$ and has a nonzero last (leading) entry, so it is the digit list of the number it represents. (2) is the definition of $\rep$ via \texttt{Nat.ofDigits}. (3) follows from (2) by induction on $j$, with $\rep(e,0)=0$. By (2), $R_{j+1}=1+10R_j=2\cdot5R_j+1$, which gives (4). +\end{proof} + +\begin{lemma}[\decl{isRepdigit_iff_mem_repList}, \decl{repdigit_eq}]\label{lem:shape} +Every repdigit $N\ge1$ equals $\rep(e,j)$ for some $1\le e\le9$ and $j\ge1$. +\end{lemma} + +\begin{proof} +Since $N\ge1$, its digit list is nonempty; let $e$ be its first entry and $j\ge1$ its length. All entries equal $e$, so $N=\rep(e,j)$. Moreover $e\le9$ because $e$ is a digit, and $e\ge1$ because the last (leading) digit of a positive number is nonzero. In Lean this is the forward direction of \decl{isRepdigit_iff_mem_repList}, applied with $L=N$ (using $N<10^N$). +\end{proof} + +\begin{lemma}[\decl{repdigit_not_dvd_sixteen}]\label{lem:16} +No repdigit $N\ge1$ is divisible by $16$. +\end{lemma} + +\begin{proof} +By Lemmas~\ref{lem:shape} and~\ref{lem:rep}(3), $N=e\,R_j$ with $1\le e\le9$ and $j\ge1$. By Lemma~\ref{lem:rep}(4), $R_j$ is odd, so it is coprime to $2$ and hence to $16=2^4$. If $16\mid eR_j$, then $16\mid e$, which forces $16\le e$ since $e\ge1$; this contradicts $e\le9$. +\end{proof} + +\begin{lemma}[\decl{repdigit_mod_hundred}]\label{lem:100} +If $N\ge10$ is a repdigit, then $N\bmod 100$ is divisible by $11$. +\end{lemma} + +\begin{proof} +By Lemma~\ref{lem:shape}, $N=\rep(e,j)$ with $1\le e\le9$ and $j\ge1$. If $j=1$ then $N=e\le9$, which is excluded; so $j=i+2$ for some $i\ge0$, and Lemma~\ref{lem:rep}(2), applied twice, gives +\[ + N=e+10\bigl(e+10\,\rep(e,i)\bigr)=11e+100\,\rep(e,i). +\] +Since $11e\le99$, we get $N\bmod100=11e$, which is divisible by $11$. +\end{proof} + +\begin{lemma}[\decl{pow_mod_mem}]\label{lem:orbit} +Let $D\in\N$ and let $T$ be a finite set of natural numbers with $1\in T$ and $(tD)\bmod100\in T$ for every $t\in T$. Then $D^K\bmod 100\in T$ for every $K\ge0$. +\end{lemma} + +\begin{proof} +Induction on $K$: $D^0\bmod100=1\in T$, and $D^{K+1}\bmod100=\bigl((D^K\bmod100)\cdot D\bigr)\bmod100$, which lies in $T$ by the hypothesis applied to $t=D^K\bmod100\in T$. +\end{proof} + +The two residue sets used are +\begin{align*} +T_3&=\{1,3,9,27,81,43,29,87,61,83,49,47,41,23,69,7,21,63,89,67\},\\ +T_5&=\{1,5,25\}. +\end{align*} +$T_3$ is the set of the $20$ residues of $3^0,\dots,3^{19}$ modulo $100$, listed in this order; it is the subgroup of $(\mathbb{Z}/100\mathbb{Z})^\times$ generated by $3$, which contains $7\equiv3^{15}$ and $9=3^2$. In Lean, $T_3$ and $T_5$ are the lists \decl{T3} and \decl{T5}, and the facts needed about them are finite checks: + +\begin{lemma}[finite checks, \texttt{decide}]\label{lem:tables} +The following hold. +\begin{enumerate} +\item $1\in T_3$, and $(3t)\bmod100$, $(7t)\bmod100$ and $(9t)\bmod100$ lie in $T_3$ for every $t\in T_3$. +\item $1\in T_5$, and $(5t)\bmod100\in T_5$ for every $t\in T_5$. +\item No element of $T_3\cup T_5$ is divisible by $11$. +\end{enumerate} +\end{lemma} + +\begin{proof} +Direct computation. For (3), the residues modulo $11$ of the elements of $T_3$ lie in $\{1,3,4,\dots,10\}$, and $1,5,25\equiv1,5,3\pmod{11}$. In Lean each of the twelve membership and divisibility claims (three for each of $D=3,5,7,9$) is closed by \texttt{decide}, which evaluates the corresponding decision procedure on these explicit lists in the kernel. +\end{proof} + +\begin{lemma}[\decl{not_repdigit_even}, \decl{not_repdigit_odd}, \decl{not_repdigit_pow}]\label{lem:pow} +If $2\le D\le9$ and $K\ge4$, then $D^K$ is not a repdigit. +\end{lemma} + +\begin{proof} +First, $D^K\ge2^K\ge2^4=16\ge10$. The proof splits into the eight values of $D$ (\texttt{interval\_cases}). + +\emph{$D\in\{2,4,6,8\}$.} Since $2\mid D$ and $K\ge4$, we have $16=2^4\mid 2^K\mid D^K$. As $D^K\ge1$, Lemma~\ref{lem:16} shows that $D^K$ is not a repdigit. + +\emph{$D\in\{3,5,7,9\}$.} Let $T=T_5$ if $D=5$ and $T=T_3$ otherwise. By Lemmas~\ref{lem:tables}(1),(2) and~\ref{lem:orbit}, $D^K\bmod100\in T$, so by Lemma~\ref{lem:tables}(3), $D^K\bmod100$ is not divisible by $11$. Since $D^K\ge10$, Lemma~\ref{lem:100} shows that $D^K$ is not a repdigit. +\end{proof} + +\begin{remark} +The congruence modulo $100$ alone does not suffice for even $D$: for instance $2^{18}=262144\equiv44$ and $2^{19}=524288\equiv88\pmod{100}$, so the last two digits of a power of $2$ can agree. This is why the even case uses divisibility by $16$ instead. +\end{remark} + +\begin{lemma}[\decl{isRepunit_of_isTerm}]\label{lem:term} +Every $m\in S$ with $m\ge1111$ is a repunit. +\end{lemma} + +\begin{proof} +Since $m$ is a repdigit and $m\ge1$, Lemma~\ref{lem:shape} gives $m=\rep(e,j)$ with $1\le e\le9$ and $j\ge1$. By Lemma~\ref{lem:rep}(1), $m$ has exactly $j$ digits, so $m<10^j$; as $m\ge1111\ge10^3$, this forces $j\ge4$. If $e=1$, all digits of $m$ equal $1$ and $m$ is a repunit. Otherwise $2\le e\le9$, and by Lemma~\ref{lem:rep}(1) the digital product of $m$ is $e^j$, which is a repdigit because $m\in S$. This contradicts Lemma~\ref{lem:pow} with $D=e$, $K=j\ge4$. +\end{proof} + +\begin{lemma}[\decl{infinite_isTerm}, \decl{a_data}, \decl{a_sixteen}]\label{lem:seq} +The set $S$ is infinite, and $a(16)=1111$. +\end{lemma} + +\begin{proof} +For every $B$, the repunit $R_{B+1}$ lies in $S$ (its digital product is $1$) and satisfies $R_{B+1}\ge10^B>B$; so $S$ is unbounded, hence infinite. The value $a(16)=1111$ is the sixteenth entry of \decl{a_data} (Section~\ref{sec:statement}). +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +Let $n\ge16$. Since $S$ is infinite (Lemma~\ref{lem:seq}), $a(n)$, the element of $S$ with index $n-1$ counting from $0$, lies in $S$ (\texttt{Nat.nth\_mem\_of\_infinite}); and \texttt{Nat.nth} is monotone for an infinite set (\texttt{Nat.nth\_monotone}), so $a(n)\ge a(16)=1111$ because $n-1\ge15$. By Lemma~\ref{lem:term}, $a(n)$ is a repunit. +\end{proof} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is the file \path{lean/Math0/Frontier/OEIS/A201060.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A201060.lean} (Section~\ref{sec:statement}) and the audit commands of \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A201060.result}, of type \decl{Math0.Statements.A201060.statement}; the auxiliary declarations named in Section~\ref{sec:proof} are private to the proof file, except \decl{digits_rep}, \decl{isRepdigit_iff_mem_repList}, \decl{infinite_isTerm} and \decl{a_data}, which come from the statement file (together with \decl{mem_repList}). The residue tables and the end of the proof file read, verbatim (docstrings, blank lines and all other declarations omitted): +\begin{lstlisting} +private def T3 : List ℕ := + [1, 3, 9, 27, 81, 43, 29, 87, 61, 83, 49, 47, 41, 23, 69, 7, 21, 63, 89, 67] +private def T5 : List ℕ := [1, 5, 25] +theorem result : statement := by + intro n hn + have hterm : IsTerm (a n) := Nat.nth_mem_of_infinite infinite_isTerm (n - 1) + have hge : 1111 ≤ a n := by + rw [← a_sixteen] + exact Nat.nth_monotone infinite_isTerm (by omega) + exact isRepunit_of_isTerm hterm hge +end Math0.Frontier.A201060 +#math0_settles Math0.Frontier.A201060.result Math0.Statements.A201060.statement +\end{lstlisting} +The proof file contains no \texttt{sorry}, \texttt{native\_decide}, \texttt{axiom} or \texttt{set\_option}; its finite checks (Lemma~\ref{lem:tables}) use \texttt{decide}, and the data lemmas of the statement file use \texttt{decide +kernel}. Both evaluate decision procedures in the Lean kernel and add no axioms. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (rejecting \decl{sorryAx}, the axioms introduced by \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the constant \decl{statement} or its negation, up to metadata, with no unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A201060.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A201060.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A201060.result' proves 'Math0.Statements.A201060.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. With the dependencies built, the single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A201060.lean} in the directory \path{lean}; this prints the three audit lines above. + +{\small +\begin{thebibliography}{99} + +\bibitem{BM99} +Y.~Bugeaud and M.~Mignotte, \emph{On integers with identical digits}, Mathematika \textbf{46} (1999), 411--417. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{GP03} +A.~Gica and L.~Panaitopol, \emph{On Obl\'ath's problem}, J. Integer Seq.\ \textbf{6} (2003), Article~03.3.5. + +\bibitem{KL05} +O.~Kihel and F.~Luca, \emph{Perfect powers with all equal digits but one}, J. Integer Seq.\ \textbf{8} (2005), Article~05.5.7, \url{https://cs.uwaterloo.ca/journals/JIS/VOL8/Kihel/kihel7.html}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput.\ Sci.\ \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Obl56} +R.~Obl\'ath, \emph{Une propri\'et\'e des puissances parfaites}, Mathesis \textbf{65} (1956), 356--364. + +\bibitem{A002275} +The OEIS Foundation Inc., \url{https://oeis.org/A002275}, \emph{Repunits: $(10^n-1)/9$}, entry by N.~J.~A. Sloane. + +\bibitem{A007954} +The OEIS Foundation Inc., \url{https://oeis.org/A007954}, \emph{Product of decimal digits of $n$}, entry by R.~Muller. + +\bibitem{A010785} +The OEIS Foundation Inc., \url{https://oeis.org/A010785}, \emph{Repdigit numbers, or numbers whose digits are all equal}, entry by N.~J.~A. Sloane. + +\bibitem{A201060} +The OEIS Foundation Inc., \url{https://oeis.org/A201060}, \emph{Repdigit numbers with repdigit digital product}, entry by J.~Krizek (Nov.~26, 2011); revision \#11, Mar.~30, 2012. + +\end{thebibliography} +} +\end{document} diff --git a/results/oeis-a209802/README.md b/results/oeis-a209802/README.md new file mode 100644 index 0000000..bd5ac77 --- /dev/null +++ b/results/oeis-a209802/README.md @@ -0,0 +1,51 @@ +# Positivity of the exponential Mertens function (A209802) + +**Classification:** First formal proof of a known result +**Area:** Sequences and series +**Source problem:** OEIS A209802 +**Date:** 2026-10-18 + +## Result + +Let mu_e be the exponential Möbius function (A166234). It is multiplicative with mu_e(p^e) = mu(e), so mu_e(n) = prod_{p | n} mu(v_p(n)). Let a(n) = sum_{k=1}^{n} mu_e(k) (A209802). Then a(n) > 0 for every n >= 1. This is Zumkeller's conjecture in the OEIS entry. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A209802](https://oeis.org/A209802) as [`Math0.Statements.A209802.statement`](../../lean/Math0/Statements/OEIS/A209802.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A209802.lean`](../../lean/Math0/Frontier/OEIS/A209802.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: A209802 (Partial sums of exponential Möbius function, A166234): "Analog of Mertens's function, A002321; conjecture: a(n) > 0." (entry by _Reinhard Zumkeller_, Mar 13 2012) + +Referees: No explicit resolution of the A209802 conjecture found: +- OEIS A209802 (https://oeis.org/A209802) and its history (https://oeis.org/history?seq=A209802, versions 1-29) still list "conjecture: a(n) > 0"; nothing about a proof is recorded. +- A166234 (exponential Möbius function) and A368405 add nothing on positivity. + +Prior results that imply the conjecture at once: +- K. Rogers, "The Schnirelmann density of the squarefree integers", Proc. Amer. Math. Soc. 15 (1964) 515-516, doi:10.1090/S0002-9939-1964-0163893-X. It proves Q(n) >= 53n/88 for all n, with equality only at n = 176. +- L. Moser and R. A. MacLeod, "The error term for the squarefree integers", Canad. Math. Bull. 9 (1966), doi:10.4153/CMB-1966-039-4. +- The same bound is recorded in an OEIS A013928 comment (M. Marcus 2012; C. R. Greathouse IV 2016). +- L. Tóth, "On certain arithmetic functions involving exponential divisors, II", Annales Univ. Sci. Budapest. Sect. Comp. 27 (2007) 155-166, arXiv:0708.3557. It gives mu_e taking values in {-1, 0, 1} with mu_e(p) = 1, and the asymptotic sum mu_e(n) = c x + O(x^{1/2} log x) with c about 0.36094. That settles positivity only for large x. + +Together these give a(n) >= 2Q(n) - n >= 9n/44 > 0 for all n >= 1. + +Also checked, with nothing relevant found: +- Lelechenko, arXiv:1405.7597 +- Cao and Zhai, J. Integer Seq. 13 (2010) +- Web, MathOverflow and Math StackExchange searches + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a209802, + author = {{math0}}, + title = {{Positivity of the exponential Mertens function (A209802)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a209802}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a209802/paper.pdf b/results/oeis-a209802/paper.pdf new file mode 100644 index 0000000..054d451 Binary files /dev/null and b/results/oeis-a209802/paper.pdf differ diff --git a/results/oeis-a209802/paper.tex b/results/oeis-a209802/paper.tex new file mode 100644 index 0000000..2c1677c --- /dev/null +++ b/results/oeis-a209802/paper.tex @@ -0,0 +1,335 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, + literate={∑}{{$\sum$}}1 {∈}{{$\in$}}1 {ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 + {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 {≤}{{$\le$}}1 {→}{{$\to$}}1 {∣}{{$\mid$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\mue}{\mu^{(e)}} +\newcommand{\ind}[1]{[\,#1\,]} + +\title[Positivity of the exponential Mertens function]{Positivity of the partial sums of the exponential M\"obius function (OEIS A209802)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Let $\mue$ be the exponential M\"obius function, the multiplicative function with $\mue(p^e)=\mu(e)$ for every prime power $p^e$, and let $a(n)=\sum_{k=1}^{n}\mue(k)$ (OEIS A209802). +We prove that $a(n)\ge n/36$, and in particular $a(n)>0$, for every $n\ge1$; this is the conjecture ``$a(n)>0$'' recorded by R.~Zumkeller in the OEIS entry in 2012. +The result is not new mathematics: since $\mue(k)=1$ for squarefree $k$ and $|\mue(k)|\le1$ always, it follows at once from K.~Rogers' 1964 bound $Q(n)\ge 53n/88$ for the number $Q(n)$ of squarefree integers up to $n$, and our proof is a self-contained elementary version of that argument with a weaker constant. +What is new is the first formal proof: positivity is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before the proof attempt, and whose definitions are checked by the Lean kernel against the listed OEIS terms. +\end{abstract} +\maketitle + +\section{Introduction} + +Let $n=p_1^{e_1}\cdots p_r^{e_r}$ with distinct primes $p_i$ and $e_i\ge1$. A divisor $d$ of $n$ is an \emph{exponential divisor} if $d=p_1^{b_1}\cdots p_r^{b_r}$ with $b_i\mid e_i$ for all $i$. These divisors and the associated exponential convolution of arithmetic functions were introduced by M.~V.~Subbarao \cite{Sub}. The inverse of the constant function $1$ under this convolution is the \emph{exponential M\"obius function} $\mue$. It is multiplicative with $\mue(p^e)=\mu(e)$, where $\mu$ is the M\"obius function, so +\[ + \mue(1)=1,\qquad \mue(p_1^{e_1}\cdots p_r^{e_r})=\mu(e_1)\cdots\mu(e_r), +\] +and $\mue(n)\in\{-1,0,1\}$, with $\mue(p)=1$ and $\mue(p^2)=\mue(p^3)=-1$ for every prime $p$ \cite[\S2]{Toth}. The values of $\mue$ form OEIS A166234 \cite{A166234}. + +The partial sums $a(n)=\sum_{k\le n}\mue(k)$ form OEIS A209802 \cite{A209802}, contributed by Reinhard Zumkeller on March~13, 2012, with the comment ``Analog of Mertens's function, A002321; conjecture: $a(n)>0$.'' The analogy is with the Mertens function $M(n)=\sum_{k\le n}\mu(k)$ (A002321 \cite{A002321}), which does take negative values (already $M(3)=-1$). The first terms of $a$ are $1,2,3,2,3,4,5,4,3,4,\dots$, and C.~R.~Greathouse~IV recorded in the entry the values $a(10^m)=4,34,355,3610,36116,\dots$ for $m=1,2,3,\dots$. + +\subsection*{Prior work} +L.~T\'oth \cite[Theorem~1]{Toth} proved that every multiplicative $f$ with $|f(n)|\le1$ and $f(p)=1$ for all primes $p$ satisfies $\sum_{n\le x}f(n)=m(f)\,x+O(x^{1/2}\log x)$, with mean value $m(f)=\prod_p\bigl(1+\sum_{a\ge2}(f(p^a)-f(p^{a-1}))p^{-a}\bigr)$, and he sharpened the error term for $f=\mue$ \cite[Theorem~2]{Toth}. For $\mue$ the mean value is $0.3609447238\ldots$ (as recorded in the OEIS entry \cite{A209802}), so $a(n)>0$ for all sufficiently large $n$; since the implied constant is not explicit, this alone does not settle the conjecture for every $n$. + +The conjecture is still listed as open in the current revision (\#29, May~30, 2025) of the entry. The math0 referees read the revision history of A209802 and the entries A166234 and A368405, and searched arXiv, MathOverflow and Mathematics Stack Exchange; they found no explicit resolution. However, the conjecture follows in two lines from a classical result. If $Q(n)$ denotes the number of squarefree integers in $[1,n]$, then $\mue(k)=1$ for squarefree $k$ and $\mue(k)\ge-1$ otherwise, so +\[ + a(n)\ \ge\ Q(n)-\bigl(n-Q(n)\bigr)\ =\ 2Q(n)-n . +\] +K.~Rogers \cite{Rogers} proved in 1964 that $Q(n)\ge \tfrac{53}{88}\,n$ for all $n\ge1$, with equality only at $n=176$; that is, the Schnirelmann density of the squarefree integers is $53/88$. (This is also recorded in a comment by M.~Marcus and C.~R.~Greathouse~IV in OEIS A013928 \cite{A013928}; see also Moser and MacLeod \cite{MM} on the error term $Q(x)-6x/\pi^2$.) Hence $a(n)\ge\tfrac{9}{44}n>0$ for all $n\ge1$. Even the weaker bound $Q(n)>n/2$ suffices. We therefore classify the result as \emph{a known result, formalized here for the first time}: the mathematics has been available since 1964, and the contribution of this note is a written resolution of the OEIS conjecture together with a kernel-checked proof. + +\subsection*{This note} +The proof formalized here does not use Rogers' theorem. It bounds the number of non-squarefree $k\le n$ by a union bound over the squares $4$, $9$ and $(2j+5)^2$, and shows $a(n)\ge n/36$ (Theorem~\ref{thm:main}). The constant is far from optimal: the referees' computations, which are not part of the formal proof, show that $a(n)>0$ for all $n\le 2\cdot10^6$ and that the minimum of $a(n)/n$ over this range is $a(28)/28=1/4$. + +\section{Statement}\label{sec:statement} + +For $n\ge1$ and a prime $p$ let $v_p(n)$ denote the exponent of $p$ in $n$. + +\begin{definition}\label{def:main} +For $n\ge1$ let $\mue(n)=\prod_{p\mid n}\mu(v_p(n))$, the product running over the primes dividing $n$ (so $\mue(1)=1$), and let $a(n)=\sum_{k=1}^{n}\mue(k)\in\Z$. +\end{definition} + +The function $\mue$ is multiplicative and $\mue(p^e)=\mu(e)$ for $e\ge1$, which is the formula given in the entry A166234 \cite{A166234}: +\begin{quote}\raggedright +\texttt{Multiplicative, a(p\^{}e) = mu(e) for any prime power p\^{}e (e>=1), where mu is the M\"obius function A008683.} +\end{quote} +The sequence A209802 \cite{A209802} has the name ``Partial sums of exponential M\"obius function, A166234'' and offset $1$, so its $n$-th term is $a(n)$. Its COMMENTS section contains, verbatim, the following comment by Reinhard Zumkeller, the author of the entry (March~13, 2012): +\begin{quote}\raggedright +\texttt{Analog of Mertens's function, A002321; conjecture: a(n) > 0.} +\end{quote} + +\begin{conjecture}[Zumkeller \cite{A209802}]\label{conj} +$a(n)>0$ for every $n\ge1$. +\end{conjecture} + +\begin{theorem}\label{thm:main} +For every $n\ge1$, +\[ + a(n)\ \ge\ n-2\Bigl(\Bigl\lfloor\frac n4\Bigr\rfloor+\Bigl\lfloor\frac n9\Bigr\rfloor+\sum_{j=0}^{n-1}\Bigl\lfloor\frac{n}{(2j+5)^2}\Bigr\rfloor\Bigr)\ \ge\ \frac{n}{36}. +\] +In particular Conjecture~\ref{conj} holds. +\end{theorem} + +The formal theorem is the final assertion $a(n)>0$; the Lean proof establishes the first inequality and the strict positivity of the middle expression, by the argument of Section~\ref{sec:proof}. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A209802.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{4eed8d99\ldots 0abf0d}) before any proof attempt. It is not part of the formal-conjectures repository \cite{FC}. Its definitions and the statement are, verbatim except that docstrings, a kernel-friendly copy of the definitions and the data lemmas are omitted: +\begin{lstlisting} +namespace Math0.Statements.A209802 +open ArithmeticFunction Finset + +def muE (n : ℕ) : ℤ := n.factorization.prod fun _ e => moebius e + +def a (n : ℕ) : ℤ := ∑ k ∈ Icc 1 n, muE k + +def statement : Prop := ∀ n : ℕ, 1 ≤ n → 0 < a n +end Math0.Statements.A209802 +\end{lstlisting} +The encoding matches Definition~\ref{def:main}. In Mathlib, \decl{n.factorization} is the finitely supported function $p\mapsto v_p(n)$, whose support is the set of prime factors of $n$, and \decl{Finsupp.prod} multiplies $g(p,v_p(n))$ over that support; \decl{moebius} is the M\"obius function $\mu$ as an integer-valued arithmetic function. So \texttt{muE n} is $\prod_{p\mid n}\mu(v_p(n))$, and \texttt{muE 1} is the empty product $1$. Every exponent in the support is at least $1$, so the value $\mu(0)$ never enters. (The value \texttt{muE 0} is never used.) \texttt{a n} is the sum over $k\in\{1,\dots,n\}$; it takes values in $\Z$, so there is no truncated subtraction. Note that the entry carries the keyword \texttt{nonn} only because of the conjecture itself. The statement quantifies over every index $n\ge1$ of the sequence and excludes the empty sum $a(0)=0$. + +The file also checks the definitions against the OEIS data. The lemma \decl{muE_data} states that $\mue(1),\dots,\mue(91)$ are the $91$ listed terms of A166234, \decl{a_data} that $a(1),\dots,a(72)$ are the $72$ listed terms of A209802, and \decl{a_ten_hundred} that $a(10)=4$ and $a(100)=34$, as in Greathouse's comment. The Mathlib functions \decl{Nat.factorization} and \decl{moebius} do not reduce well in the kernel, so the file also defines trial-division copies \decl{muEC} and \decl{aC}: prime divisors are found by scanning $0,\dots,n$, exponents are computed with \decl{Nat.findGreatest}, and $\mu$ is computed from its values on prime powers. It proves \decl{muE_eq_muEC} and \decl{a_eq_aC} for all $n$, using the multiplicativity of $\mu$ and the characterization $p^j\mid n\iff j\le v_p(n)$. Each data lemma is proved by rewriting with these equalities and then running \texttt{decide +kernel}, so the Lean kernel itself evaluates the copies and compares them with the listed terms. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A209802.lean}; the corresponding declarations are listed in Section~\ref{sec:lean}. For a statement $P$ we write $\ind{P}=1$ if $P$ holds and $\ind{P}=0$ otherwise. + +\begin{lemma}\label{lem:values} +Let $k\ge1$. If $k$ is squarefree, then $\mue(k)=1$. In general $|\mue(k)|\le1$; in particular $\mue(k)\ge-1$. +\end{lemma} + +\begin{proof} +If $k$ is squarefree, then $v_p(k)\le1$ for every prime $p$, and $v_p(k)\ne0$ for the primes in the product, so every factor is $\mu(1)=1$. In general $\mue(k)$ is a product of values of $\mu$, each of absolute value at most $1$. +\end{proof} + +For $n,k\in\N$ put +\[ + S(n,k)=\ind{4\mid k}+\ind{9\mid k}+\sum_{j=0}^{n-1}\ind{(2j+5)^2\mid k}\ \in\Z_{\ge0}. +\] + +\begin{lemma}\label{lem:pointwise} +If $1\le k\le n$, then $\mue(k)\ge 1-2S(n,k)$. +\end{lemma} + +\begin{proof} +If $k$ is squarefree, then $\mue(k)=1\ge1-2S(n,k)$ by Lemma~\ref{lem:values} and $S(n,k)\ge0$. Otherwise there is a prime $p$ with $p^2\mid k$, and $p\le k\le n$ because $p\mid k$ and $k\ge1$. Since $\mue(k)\ge-1$ by Lemma~\ref{lem:values}, it suffices to show $S(n,k)\ge1$, which holds because one of its summands, all of which are nonnegative, equals $1$: +if $p=2$, then $\ind{4\mid k}=1$; if $p=3$, then $\ind{9\mid k}=1$; otherwise $p$ is an odd prime with $p\ge5$, so $j=(p-5)/2$ is a natural number with $2j+5=p$ and $j0$. +\end{proof} + +In Lean the last step is carried out in $\Q$: the integer $2(\lfloor n/4\rfloor+\lfloor n/9\rfloor+\sum_j\lfloor n/(2j+5)^2\rfloor)$ is cast to $\Q$, bounded by $\tfrac{35}{36}n= 1) begins in row k(k+1)/2 and lists 1, 0^(k-1), 2, 0^(k-1), 3, ... going down. In other words, for 1 <= k and k(k+1)/2 <= n we have T(n,k) = j/k + 1 when k divides j = n - k(k+1)/2, and T(n,k) = 0 otherwise. Two claims are made. (1) For n >= 1 and any entry (n,k) of the triangle with T(n,k) > 0, n has a partition into k consecutive parts m, m+1, ..., m+k-1, and T(n,k) is the smallest part of every such partition. (2) For n >= 1, A109814(n), the largest k such that n is a sum of k consecutive positive integers, is the largest column k of row n with T(n,k) > 0. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A211343](https://oeis.org/A211343) as [`Math0.Statements.A211343.statement`](../../lean/Math0/Statements/OEIS/A211343.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A211343.lean`](../../lean/Math0/Frontier/OEIS/A211343.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C Conjecture 1: T(n,k) is the smallest part of the partition of n into k consecutive parts, if T(n,k) > 0. %C Conjecture 2: the last positive integer in the row n is in the column A109814(n). (Omar E. Pol, Apr 30 2017) + +Referees: OEIS (local mirror): A261699 comment by Peter Munn, Jul 30 2017 ("A211343(n,k) = abs(n/d - d/2) + 1/2, smallest part"; one-to-one link between odd divisors and partitions into k consecutive parts). A286013 comment by Peter Munn, Jun 18 2017 (trapezoid proof of the largest-part companion conjecture, which carries over directly to smallest parts). A285898 comment by David A. Corneth, Apr 28 2017 (n has a partition into k consecutive parts iff (n - C(k,2))/k is a positive integer). A196020 formula by Max Alekseyev, Nov 18 2013 (T(n,k) = 2n/k - k on the support), combined with the A211343 formula T = floor((1+A196020)/2). A237048 property by Hartmut F. W. Hoft, Oct 2014. A286000 "Theorem" (Pol). A379632 (Pol, Dec 2024: "Positive terms of A211343", "Right border gives A118235"). A118235 (smallest part of partitions into consecutive parts). A109814 (Jaap Spies / David W. Wilson: 2n = k(2m+k-1)). The classical background is Sylvester's enumeration of partitions into consecutive parts. Not retrievable (web.archive.org unreachable): Joerg Arndt, SeqFan, Jun 3 2017, proof of the A285914/A204217 conjectures. Web searches found no counterexample and no paper on A211343 specifically. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a211343, + author = {{math0}}, + title = {{A211343: positive entries are smallest parts of consecutive-part partitions; last positive column is A109814(n)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a211343}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a211343/paper.pdf b/results/oeis-a211343/paper.pdf new file mode 100644 index 0000000..28235a9 Binary files /dev/null and b/results/oeis-a211343/paper.pdf differ diff --git a/results/oeis-a211343/paper.tex b/results/oeis-a211343/paper.tex new file mode 100644 index 0000000..614715a --- /dev/null +++ b/results/oeis-a211343/paper.tex @@ -0,0 +1,356 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,at,subst,constructor,unfold}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {↔}{{$\leftrightarrow$}}1 + {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {∧}{{$\wedge$}}1 {≤}{{$\le$}}1 {∈}{{$\in$}}1 + {∑}{{$\sum$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} + +\title[Smallest parts of partitions into consecutive parts (OEIS A211343)]{The triangle OEIS A211343: its positive entries are the smallest parts of partitions into consecutive parts, and the last one in row $n$ lies in column A109814$(n)$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +Let $T(n,k)$ be the triangle OEIS A211343, in which column $k$ lists the positive integers interleaved with $k-1$ zeros, starting in row $k(k+1)/2$. +We prove the two conjectures recorded in the entry by Omar E. Pol in April 2017: if $T(n,k)>0$, then $T(n,k)$ is the smallest part of the partition of $n$ into $k$ consecutive parts; and the last positive entry of row $n$ lies in column A109814$(n)$, the largest $k$ such that $n$ is a sum of $k$ consecutive positive integers. +Both follow from the identity $m+(m+1)+\dots+(m+k-1)=km+k(k-1)/2$, and the key facts are already recorded, partly with proofs, in neighbouring OEIS entries (D.~A. Corneth, P.~Munn, M.~Alekseyev); we therefore classify the result as the first formal proof of a known result, not as a new result. +The proof is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the $94$ listed terms of A211343 and the first $40$ terms of A109814. +\end{abstract} +\maketitle + +\section{Introduction} + +For $k\ge1$ write $\Delta_k=k(k+1)/2$ for the $k$-th triangular number. The OEIS entry A211343 \cite{A211343}, contributed by Omar E. Pol on February~5, 2013, is the irregular triangle $T(n,k)$ ($n\ge1$, $1\le k$, $\Delta_k\le n$) in which column $k$ begins in row $\Delta_k$ and reads, going down, +\[ + 1,\ \underbrace{0,\dots,0}_{k-1},\ 2,\ \underbrace{0,\dots,0}_{k-1},\ 3,\ \dots +\] +Row $n$ thus has length A003056$(n)$, the largest $k$ with $\Delta_k\le n$. Rows $15$ to $18$ are $[15,7,4,0,1]$, $[16,0,0,0,0]$, $[17,8,0,0,0]$, $[18,0,5,3,0]$. +On April~30, 2017 Pol added two conjectures to the entry (quoted verbatim in Section~\ref{sec:statement}): a positive entry $T(n,k)$ is the smallest part of the partition of $n$ into $k$ consecutive parts, and the last positive entry of row $n$ is in column A109814$(n)$ \cite{A109814}, the largest $k$ for which $n$ is a sum of $k$ consecutive positive integers. For example, the partitions of $15$ into consecutive parts are $15$, $8+7$, $6+5+4$ and $5+4+3+2+1$, with smallest parts $15,7,4,1$ in columns $1,2,3,5$, and A109814$(15)=5$. Both lines are still labelled ``Conjecture'' in the revision of the entry we used (\#54, March~12, 2021). We prove both conjectures (Theorem~\ref{thm:main}). The key fact (Proposition~\ref{prop:support}) is that for $n\ge1$ the entry $T(n,k)$ is positive exactly when $n=m+(m+1)+\dots+(m+k-1)$ for some $m\ge1$, and then $T(n,k)=m$. + +\subsection*{Prior work and status} +The substance of the result is already in the literature and in the OEIS. +\begin{itemize} +\item Writing $n=m+(m+1)+\dots+(m+k-1)$ as $2n=k(2m+k-1)$, in which exactly one factor is odd, shows that the partitions of $n$ into consecutive parts correspond to the odd divisors of $n$. This classical enumeration is the one-run case of Sylvester's refinement of Euler's partition theorem \cite{Sylvester}; it is called Sylvester's enumeration in A001227 \cite{A001227}; see also Apostol \cite{Apostol}. In A109814 \cite{A109814}, J.~Spies (August~16, 2005, after D.~W. Wilson) uses $2n=k(2m+k-1)$ to compute A109814. +\item In A285898 \cite{A285898}, D.~A. Corneth noted on April~28, 2017 that $n$ has a partition into exactly $k$ consecutive parts if and only if $(n-\binom k2)/k$ is a positive integer, which is the starting part $m$. In the same entry S.~Cadot remarked (January~22, 2023) that there is at most one such partition. +\item For the companion triangle A196020 \cite{A196020} (odd numbers in place of the positive integers), M.~Alekseyev gave on November~18, 2013 the closed form $2n/k-k$ on its support. Combined with the relation $T(n,k)=\lfloor(1+\text{A196020}(n,k))/2\rfloor$ in A211343, this yields $T(n,k)=n/k-(k-1)/2$ on the support, which is the smallest part $m$ above. H.~F.~W. Hoft (A237048 \cite{A237048}, October~23, 2014) described the support of these triangles via the odd divisors of $n$. +\item For the companion triangle A286013 \cite{A286013} (column $k$ lists $k,k+1,\dots$ interleaved with zeros), whose positive entries are $T(n,k)+k-1$, P.~Munn gave on June~18, 2017 a proof, by trapezoidal dot patterns, of the analogous conjecture for largest parts: the positive entries of column $k$ correspond one-to-one to the partitions of $n$ into $k$ consecutive parts. The same argument proves Conjecture~1. In A261699 \cite{A261699} (July~30, 2017) Munn states explicitly that A211343$(n,k)=|n/d-d/2|+1/2$ is the smallest part of the partition of $n$ attached to the odd divisor $d$ (with some steps left as ``it can be shown''). +\item Other entries by Pol state both conjectures as facts. A379632 \cite{A379632} (December~31, 2024), the smallest parts of the partitions of $n$ into consecutive parts, is cross-referenced as ``Positive terms of A211343'' with ``Right border gives A118235'', where A118235 \cite{A118235} (R.~Zumkeller, 2006) is the smallest part of the longest such partition. The cross-references of A286013, which has the same support as A211343, include ``The last positive term in row $n$ is in column A109814$(n)$''. +\end{itemize} +The math0 referees found no paper addressing A211343 by name. Since the conjectures follow from these identities in a few lines, we classify our result as the \emph{first formal proof of a known result}. + +\section{Statement}\label{sec:statement} + +\subsection*{The OEIS conjectures} +The name of A211343 \cite{A211343} (Omar E. Pol, February~5, 2013; offset $1$) is, verbatim, +\begin{quote}\small +Triangle read by rows: T(n,k), n \textgreater{}= 1, k \textgreater{}= 1, in which column k lists the positive integers interleaved with k-1 zeros, and the first element of column k is in row k(k+1)/2. +\end{quote} +Its COMMENTS section contains, verbatim, under the heading ``From \emph{Omar E. Pol}, Apr 30 2017'': +\begin{quote}\small +Conjecture 1: T(n,k) is the smallest part of the partition of n into k consecutive parts, if T(n,k) \textgreater{} 0.\\ +Conjecture 2: the last positive integer in the row n is in the column A109814(n). +\end{quote} +The sequence A109814 \cite{A109814} (David W. Wilson) is ``a(n) is the largest k such that n can be written as sum of k consecutive positive integers.'' + +\subsection*{The theorem} +For $k\ge1$ and $j\ge0$ let $c_k(j)=j/k+1$ if $k\mid j$ and $c_k(j)=0$ otherwise; this is column $k$ read from its first row. Row $n$ consists of the columns $k$ with $1\le k$ and $\Delta_k\le n$, and for these $T(n,k)=c_k(n-\Delta_k)$. A \emph{partition of $n$ into $k$ consecutive parts} is a multiset of positive integers with sum $n$ of the form $\{m,m+1,\dots,m+k-1\}$. + +\begin{theorem}\label{thm:main} +Let $n\ge1$. +\begin{enumerate} +\item If $1\le k$, $\Delta_k\le n$ and $T(n,k)>0$, then $n$ has a partition into $k$ consecutive parts, and $T(n,k)$ is the smallest part of every such partition. +\item Let $A(n)$ be the largest $k$ such that $n$ is a sum of $k$ consecutive positive integers. Then $A(n)$ is the largest $k$ with $1\le k$, $\Delta_k\le n$ and $T(n,k)>0$. +\end{enumerate} +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A211343.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{bc8da2da\ldots 897e}) before any proof attempt. The definitions and the statement read as follows (verbatim; the copyright header, the import, the module docstring and all docstrings are omitted): +\begin{lstlisting} +namespace Math0.Statements.A211343 +open Finset +def column (k j : ℕ) : ℕ := if j % k = 0 then j / k + 1 else 0 +def InRow (n k : ℕ) : Prop := 1 ≤ k ∧ k * (k + 1) / 2 ≤ n +instance (n k : ℕ) : Decidable (InRow n k) := by unfold InRow; infer_instance +def T (n k : ℕ) : ℕ := if InRow n k then column k (n - k * (k + 1) / 2) else 0 +def row (n : ℕ) : List ℕ := ((List.range (n + 1)).filter (fun k => decide (InRow n k))).map (T n) +def a (i : ℕ) : ℕ := ((List.range i).flatMap (fun j => row (j + 1))).getD (i - 1) 0 +def HasConsecutiveParts {n : ℕ} (k : ℕ) (p : n.Partition) : Prop := + ∃ m, p.parts = (Multiset.range k).map (fun i => m + i) +def IsConsecSum (n k : ℕ) : Prop := ∃ m, 0 < m ∧ ∑ i ∈ range k, (m + i) = n +def IsConsecSumBdd (n k : ℕ) : Prop := ∃ m ∈ Finset.Icc 1 n, ∑ i ∈ Finset.range k, (m + i) = n +instance (n : ℕ) : DecidablePred (IsConsecSumBdd n) := fun k => by + unfold IsConsecSumBdd; infer_instance +def A109814 (n : ℕ) : ℕ := Nat.findGreatest (IsConsecSumBdd n) n +def statement : Prop := + (∀ n k : ℕ, 1 ≤ n → InRow n k → 0 < T n k → + (∃ p : n.Partition, HasConsecutiveParts k p) ∧ + ∀ p : n.Partition, HasConsecutiveParts k p → IsLeast {x | x ∈ p.parts} (T n k)) ∧ + (∀ n : ℕ, 1 ≤ n → IsGreatest {k | InRow n k ∧ 0 < T n k} (A109814 n)) +end Math0.Statements.A211343 +\end{lstlisting} +The file also proves the following (statements shown, proofs omitted; the lists of $94$ terms, $24$ rows and $40$ terms on the right-hand sides of the data checks are elided): +\begin{lstlisting} +theorem le_of_inRow {n k : ℕ} (h : InRow n k) : k ≤ n +theorem a_data : (List.range 94).map (fun i => a (i + 1)) = + [1, 2, 3, 1, 4, 0, 5, 2, 6, 0, 1, 7, 3, 0, 8, 0, 0, 9, 4, 2, ..., 24, 0, 7, 0, 0, 0] +theorem row_data : (List.range 24).map (fun n => row (n + 1)) = [[1], [2], [3, 1], ...] +theorem A109814_isGreatest {n : ℕ} (hn : 1 ≤ n) : + IsGreatest {k | IsConsecSum n k} (A109814 n) +theorem A109814_data : (List.range 40).map (fun i => A109814 (i + 1)) = + [1, 1, 2, 1, 2, 3, 2, 1, 3, 4, 2, 3, 2, 4, 5, 1, 2, 4, 2, 5, ..., 8, 2, 4, 6, 5] +\end{lstlisting} + +\subsection*{How the definitions encode the OEIS entry} +\emph{The triangle} follows the name of the entry, not any conjectured formula. \texttt{column k j} is $c_k(j)$: for $k\ge1$, \texttt{j \% k = 0} means $k\mid j$. \texttt{InRow n k} says that $(n,k)$ is a position of the triangle; \texttt{k * (k + 1) / 2} is exactly $\Delta_k$, and under \texttt{InRow} the truncated subtraction \texttt{n - k * (k + 1) / 2} is the true difference. Outside the triangle \texttt{T n k} is $0$, a junk value that \decl{statement} never uses, since both conjuncts assume \texttt{InRow n k}. \texttt{row n} lists $T(n,1),\dots,T(n,\text{A003056}(n))$ (by \decl{le_of_inRow}, no column exceeds $n$), and \texttt{a} is the triangle read by rows with offset $1$. + +\emph{Data checks.} \decl{a_data} states that $a(1),\dots,a(94)$ are the $94$ terms in the DATA section of A211343 (rows $1$ to $24$), \decl{row_data} that rows $1$ to $24$ agree with the first $24$ rows displayed in the EXAMPLE section (which shows rows $1$ to $28$), and \decl{A109814_data} that \texttt{A109814} reproduces the first $40$ listed terms of A109814. All three are proved by \texttt{decide +kernel}: the kernel evaluates both sides and checks that they are equal. This anchors the definitions to the entry independently of the conjectures. + +\emph{Partitions.} A partition of $n$ is Mathlib's \texttt{Nat.Partition n}, a multiset \texttt{parts} of positive integers with sum $n$. \texttt{HasConsecutiveParts k p} says that \texttt{p.parts} is $\{m+i: 0\le i0$. + +\emph{A109814.} \texttt{IsConsecSum n k} says that $n=\sum_{i0$; this set contains $k=1$, as $T(n,1)=n$. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A211343.lean}; the Lean names of the lemmas are given in brackets. Throughout, $S_k=0+1+\dots+(k-1)=k(k-1)/2$. + +\begin{lemma}[\decl{tri_eq}, \decl{consec_sum}, \decl{multiset_consec_sum}]\label{lem:sums} +For all $k,m\ge0$: $\Delta_k=S_k+k$, and both $\sum_{i0$, then $n=k\,T(n,k)+S_k$. +\end{lemma} + +\begin{proof} +Let $j=n-\Delta_k\ge0$. By definition $T(n,k)=c_k(j)$, and $c_k(j)>0$ rules out the branch $c_k(j)=0$; so $k\mid j$ and $T(n,k)=j/k+1$. Hence, using Lemma~\ref{lem:sums}, +\[ + k\,T(n,k)+S_k=k\cdot\frac jk+k+S_k=j+\Delta_k=n. \qedhere +\] +\end{proof} + +\begin{lemma}[\decl{T_of_eq}]\label{lem:bwd} +If $k\ge1$, $m\ge1$ and $n=km+S_k$, then $1\le k$, $\Delta_k\le n$ and $T(n,k)=m$. +\end{lemma} + +\begin{proof} +Since $km\ge k$, we have $\Delta_k=S_k+k\le S_k+km=n$. Moreover $j=n-\Delta_k=km-k=k(m-1)$, so $k\mid j$ and $T(n,k)=c_k(j)=(m-1)+1=m$. +\end{proof} + +\begin{proposition}[\decl{inRow_T_pos_iff}]\label{prop:support} +Let $n\ge1$ and $k\ge0$. Then +\[ + \bigl(1\le k,\ \Delta_k\le n\ \text{and}\ T(n,k)>0\bigr)\iff \exists\,m\ge1:\ \sum_{i0$ equals the set of $k$ such that $n$ is a sum of $k$ consecutive positive integers. By Lemma~\ref{lem:a109814}, A109814$(n)$ is the greatest element of the latter set, hence of the former. +\end{proof} + +\begin{remark}\label{rem:converse} +Proposition~\ref{prop:support}, whose ingredients are formalized (\decl{inRow_T_pos_iff} and \decl{T_of_eq}), also gives the converse of Conjecture~1: every partition of $n$ into $k$ consecutive parts, $k\ge1$, starts at $m=T(n,k)>0$. This converse is not part of \decl{statement} and is not stated as a separate Lean theorem. Thus the positive entries of row $n$ are exactly the smallest parts of the partitions of $n$ into consecutive parts, one for each number of parts, and each such partition is unique. On the support, $T(n,k)=n/k-(k-1)/2$, in agreement with Alekseyev's formula (Section~1). That the number of positive entries of row $n$ is the number of odd divisors of $n$, as stated in A211343 \cite{A211343}, then follows from the classical enumeration recalled in Section~1; this count is not formalized here. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A211343.lean} in the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A211343.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A211343.result}, of type \decl{Math0.Statements.A211343.statement}. The six auxiliary lemmas are private. Their statements read verbatim as follows (all proofs, the header, the imports and the docstrings omitted; the $33$-line proof of \decl{result} carries out the proof of Theorem~\ref{thm:main} in the order given in Section~\ref{sec:proof}): +\begin{lstlisting} +namespace Math0.Frontier.A211343 +open Math0.Statements.A211343 +open Finset +private lemma tri_eq (k : ℕ) : k * (k + 1) / 2 = (∑ i ∈ range k, i) + k +private lemma consec_sum (m k : ℕ) : + ∑ i ∈ range k, (m + i) = k * m + ∑ i ∈ range k, i +private lemma multiset_consec_sum (m k : ℕ) : + ((Multiset.range k).map (fun i => m + i)).sum = k * m + ∑ i ∈ range k, i +private lemma eq_of_T_pos {n k : ℕ} (h : InRow n k) (hT : 0 < T n k) : + n = k * T n k + ∑ i ∈ range k, i +private lemma T_of_eq {n k m : ℕ} (hk : 1 ≤ k) (hm : 1 ≤ m) + (hn : n = k * m + ∑ i ∈ range k, i) : InRow n k ∧ T n k = m +private lemma inRow_T_pos_iff {n k : ℕ} (hn : 1 ≤ n) : + (InRow n k ∧ 0 < T n k) ↔ IsConsecSum n k +theorem result : statement +end Math0.Frontier.A211343 +#math0_settles Math0.Frontier.A211343.result Math0.Statements.A211343.statement +\end{lstlisting} +The arithmetic is closed by \texttt{omega}, with the sums $S_k$ and products such as $k\,T(n,k)$ as atoms. No computation is involved in the proof; the only kernel evaluations are the data checks of the statement file. Neither file uses \texttt{sorry}, \texttt{native\_decide}, custom axioms or \texttt{set\_option}. + +\subsection*{Audit} +The command \texttt{\#math0\_settles} (\path{lean/Math0/Audit.lean}), used for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically \decl{statement} or $\neg$\,\decl{statement}, up to metadata annotations, with no unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A211343.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A211343.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A211343.result' proves 'Math0.Statements.A211343.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use, since the statement is a math0 formalization of an OEIS conjecture and not part of formal-conjectures. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A211343.lean} in the directory \path{lean} after \texttt{lake build Math0.Statements.OEIS.A211343}; on our machine the former took well under a minute, and the latter, which includes the kernel data checks, about $5.5$ minutes of wall time under heavy load (less than a minute of CPU time for the data checks). + +{\small +\begin{thebibliography}{99} + +\bibitem{Apostol} +T.~M. Apostol, \emph{Sums of consecutive positive integers}, Math. Gazette \textbf{87} (2003), no.~508, 98--101. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171 [cs.AI], 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Sylvester} +J.~J. Sylvester, \emph{A constructive theory of partitions, arranged in three acts, an interact and an exodion}, Amer. J. Math. \textbf{5} (1882), 251--330. + +\bibitem{A001227} +The OEIS Foundation Inc., OEIS entry A001227, \url{https://oeis.org/A001227}. + +\bibitem{A109814} +The OEIS Foundation Inc., OEIS entry A109814 (D.~W. Wilson), \url{https://oeis.org/A109814}. + +\bibitem{A118235} +The OEIS Foundation Inc., OEIS entry A118235 (R.~Zumkeller, 2006), \url{https://oeis.org/A118235}. + +\bibitem{A196020} +The OEIS Foundation Inc., OEIS entry A196020 (O.~E. Pol, 2013), \url{https://oeis.org/A196020}. + +\bibitem{A211343} +The OEIS Foundation Inc., OEIS entry A211343 (O.~E. Pol, 2013), \url{https://oeis.org/A211343}, revision \#54. + +\bibitem{A237048} +The OEIS Foundation Inc., OEIS entry A237048 (O.~E. Pol, 2014), \url{https://oeis.org/A237048}. + +\bibitem{A261699} +The OEIS Foundation Inc., OEIS entry A261699 (O.~E. Pol, 2015), \url{https://oeis.org/A261699}. + +\bibitem{A285898} +The OEIS Foundation Inc., OEIS entry A285898 (O.~E. Pol and N.~J.~A. Sloane, 2017), \url{https://oeis.org/A285898}. + +\bibitem{A286013} +The OEIS Foundation Inc., OEIS entry A286013 (O.~E. Pol, 2017), \url{https://oeis.org/A286013}. + +\bibitem{A379632} +The OEIS Foundation Inc., OEIS entry A379632 (O.~E. Pol, 2024), \url{https://oeis.org/A379632}. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a215010/README.md b/results/oeis-a215010/README.md new file mode 100644 index 0000000..52407a6 --- /dev/null +++ b/results/oeis-a215010/README.md @@ -0,0 +1,48 @@ +# An equiangular decagon with sides in arithmetic progression (A215010) + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A215010 +**Date:** 2026-10-18 + +## Result + +Garcia's conjecture (OEIS A215010) says that hexagons are the only equiangular simple convex polygons whose integer side lengths are the N terms t, t+d, ..., t+(N-1)d (with d ≥ 1) of an arithmetic progression, in some order. Formally: if N ≥ 3, every side t + σ(k)·d is positive, and Σ_k (t + σ(k)d)·exp(2πik/N) = 0 for a permutation σ of Fin N, then N = 6. We prove that this is false. Take N = 10 and t = d = 1, with consecutive sides (1, 4, 5, 8, 9, 2, 3, 6, 7, 10), so σ = (0, 3, 4, 7, 8, 1, 2, 5, 6, 9). This gives an equiangular decagon. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A215010](https://oeis.org/A215010) as [`Math0.Statements.A215010.statement`](../../lean/Math0/Statements/OEIS/A215010.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A215010.lean`](../../lean/Math0/Frontier/OEIS/A215010.lean) refutes (proves the negation of) it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: hexagons are the only simple convex polygons with equal interior angles with such property, due to the fact that cos(Pi/3) = 1/2." Here 'such property' means integer side lengths in arithmetic progression t+m*d, as in the entry name. (entry by _Robin Garcia_, Jul 31 2012) + +Referees: Prior refutations, all at least as old as or published soon after Garcia's 2012 conjecture: + +(1) OEIS A118887 (H. Pfoertner, May 03 2006). "Number of ways to place n objects with weights 1,...,n evenly spaced around a circle so it balances." T. D. Noe, Sep 13 2005: "Also number of equiangular polygons whose sides are some permutation of 1,2,3,...,n." The data have included a(10)=24, a(12)=732, a(14)=720, a(15)=48 since the first revision in 2006. W. Edwin Clark (Sep 14 2005) proved there are no solutions when n is a prime power. J. Sondow (Oct 17 2013) records that Murray Klamkin proved solutions exist when n is not a prime power, and adds the formula a(A024619(n)) > 0. The problem was proposed by Brendan McKay on the SeqFan mailing list, Sep 12 2005. https://oeis.org/A118887 + +(2) G. J. Woeginger, "Nothing new about equiangular polygons", Amer. Math. Monthly 120(9) (2013) 849–850, doi:10.4169/amer.math.monthly.120.09.849. Abstract: "We survey results on equiangular n-vertex polygons with edge lengths in arithmetic progression. Such a polygon exists if and only if n has at least two distinct prime factors." This is exactly the A215010 setting, and it gives n = 10, 12, 14, 15, ... as counterexamples. + +(3) Supporting references: +- D. Ball, "Equiangular polygons", Math. Gazette 86 (2002) 396–407. +- A. Bernoff, "Bernoff's Puzzler", MuddMath Newsletter 4(1) (2005), p. 10. +- M. Munteanu and L. Munteanu, "Rational equiangular polygons", Applied Math. 4 (2013) 1460–1465, doi:10.4236/am.2013.410197. +- U. Abel, "Coincidence of the barycentre and the geometric centre of weighted points", Math. Gazette (online Oct 2019). It restates the criterion: at least two distinct prime factors. + +A215010 itself (history checked through revision #43, Jan 23 2015) never cites any of these, and its conjecture remains uncorrected. I found no earlier formalization in Lean or any other proof assistant. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a215010, + author = {{math0}}, + title = {{An equiangular decagon with sides in arithmetic progression (A215010)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a215010}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a215010/paper.pdf b/results/oeis-a215010/paper.pdf new file mode 100644 index 0000000..ce8cdfb Binary files /dev/null and b/results/oeis-a215010/paper.pdf differ diff --git a/results/oeis-a215010/paper.tex b/results/oeis-a215010/paper.tex new file mode 100644 index 0000000..20f4ec3 --- /dev/null +++ b/results/oeis-a215010/paper.tex @@ -0,0 +1,406 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{tikz} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,ring,push_cast,set,unfold,convert,rw,congr,linear_combination}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℝ}{{$\mathbb{R}$}}1 {ℂ}{{$\mathbb{C}$}}1 + {∀}{{$\forall$}}1 {∑}{{$\sum$}}1 {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 + {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 + {·}{{$\cdot$}}1 {ζ}{{$\zeta$}}1 {Φ}{{$\Phi$}}1 {σ}{{$\sigma$}}1 {α}{{$\alpha$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{ζ}{\ensuremath{\zeta}} +\newunicodechar{Φ}{\ensuremath{\Phi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\C}{\mathbb{C}} +\newcommand{\Eq}{\mathsf{E}} + +\title[An equiangular decagon with sides $1,\dots,10$ (OEIS A215010)]{An equiangular convex decagon with side lengths $1,2,\dots,10$: the conjecture in OEIS A215010 is false} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +The OEIS entry A215010 (Robin Garcia, 2012) lists the equiangular convex hexagons whose integer side lengths, in some order, are the terms of an arithmetic progression, and states the conjecture that hexagons are the only simple convex equiangular polygons with this property. +We show that the decagon whose consecutive sides have lengths $1,4,5,8,9,2,3,6,7,10$ and whose interior angles all equal $144^\circ$ closes up, so the conjecture is false. +The underlying fact is classical: an equiangular $n$-gon whose sides are, in some order, the $n$ terms of a nonconstant arithmetic progression exists if and only if $n$ has at least two distinct prime factors, as surveyed by Woeginger in 2013, and decagons of this kind are counted in OEIS A118887. +We therefore classify this note as the first formal proof, to our knowledge, of a known result, not as new mathematics. +The refutation is verified in Lean~4 with Mathlib against a statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the entry's data, and which was reviewed for fidelity and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +A convex polygon with equal interior angles turns by the same exterior angle $2\pi/N$ at each of its $N$ vertices. +If its consecutive sides, counterclockwise, have lengths $s_0,\dots,s_{N-1}$, then after a rotation its $k$th edge is the vector $s_k\zeta^k$, where $\zeta=e^{2\pi i/N}$, so such a polygon exists if and only if +\begin{equation}\label{eq:close} + \sum_{k=0}^{N-1} s_k\,\zeta^k = 0 +\end{equation} +(Remark~\ref{rem:encoding}). +The OEIS entry A215010 \cite{A215010}, submitted by Robin Garcia on July~31, 2012, has the name ``Integer side lengths in arithmetic progression of simple convex hexagons with equal interior angles. Sequence gives the values of m for sides of lengths t+m*d, counterclockwise, for the two primitive solutions.'' +Its $12$ terms $0,5,1,3,2,4,\ 0,5,2,1,4,3$ are the two patterns $m$, up to rotation and reflection, for which the hexagon with sides $t+m_kd$ closes up; for $t=d=1$ the first gives the hexagon with sides $1,6,2,4,3,5$. +The entry conjectures that hexagons are the only simple convex equiangular polygons with this property (Section~\ref{sec:statement}). +We show that this is false; the smallest counterexample is a decagon (Figure~\ref{fig:decagon}, Remark~\ref{rem:minimal}). + +\subsection*{Prior work} +The facts that refute the conjecture were recorded in the OEIS before it was stated. +Since $\sum_k\zeta^k=0$, the base term $t$ and the nonzero factor $d$ drop out of \eqref{eq:close}, and the question becomes whether an equiangular $N$-gon can have sides that are a permutation of $1,2,\dots,N$. +This is the subject of OEIS A118887 \cite{A118887}, created by Hugo Pfoertner on May~3, 2006: ``Number of ways to place n objects with weights 1,2,...,n evenly spaced around the circumference of a circular disk so that the disk will exactly balance on the center point''. +According to the entry, the problem was proposed by Brendan McKay on the SeqFan mailing list on September~12, 2005; T.~D.~Noe remarked on September~13, 2005 that the terms also count ``equiangular polygons whose sides are some permutation of 1,2,3,...,n''; W.~Edwin Clark proved on September~14, 2005 that there are no solutions when $n$ is a prime power; and Jonathan Sondow recorded on October~17, 2013 that Murray Klamkin proved that solutions exist when $n$ is not a prime power. +The entry lists $a(6)=2$, matching the two hexagons of A215010, and $a(10)=24$, $a(12)=732$, $a(14)=720$, $a(15)=48$; the math0 literature referee reports that these values have been in the entry since its first revision in 2006. +Woeginger's note ``Nothing new about equiangular polygons'' \cite{Woeginger} surveys results on equiangular $n$-gons with edge lengths in arithmetic progression, which is exactly the setting of A215010, and states that such a polygon exists if and only if $n$ has at least two distinct prime factors. +Related references are Ball \cite{Ball} on equiangular polygons with integer sides, Bernoff's puzzle column \cite{Bernoff} and M.~and L.~Munteanu \cite{Munteanu} (these two, like Woeginger's note, are linked from A118887), and Abel \cite{Abel}, who restates the criterion. + +The entry A215010 (revision \#43 of January~23, 2015, the version we read) does not cross-reference A118887 or any of these works and still states the conjecture. +The math0 referees found no earlier formal proof of a counterexample, in Lean or another proof assistant (their search was not exhaustive), and the statement is not among those of the formal-conjectures repository \cite{FC} at the commit pinned by math0 (\texttt{c77fdd4}). +What we add is an explicit counterexample with a complete elementary proof that matches a kernel-checked Lean proof of a frozen formal statement (Section~\ref{sec:lean}). + +\begin{figure}[t] +\begin{minipage}[c]{0.3\textwidth} +\centering +\begin{tikzpicture}[scale=0.17] + \draw[thick, fill=gray!12] (0.000,0.000) -- (1.000,0.000) -- (4.236,2.351) -- (5.781,7.106) -- (3.309,14.715) -- (-3.972,20.005) -- (-5.972,20.005) -- (-8.399,18.242) -- (-10.253,12.535) -- (-8.090,5.878) -- cycle; + \fill (0,0) circle (6pt); + \node[font=\scriptsize] at (0.50,-1.90) {$1$}; + \node[font=\scriptsize] at (3.73,-0.36) {$4$}; + \node[font=\scriptsize] at (6.82,4.14) {$5$}; + \node[font=\scriptsize] at (6.35,11.50) {$8$}; + \node[font=\scriptsize] at (0.79,18.90) {$9$}; + \node[font=\scriptsize] at (-4.97,21.90) {$2$}; + \node[font=\scriptsize] at (-8.30,20.66) {$3$}; + \node[font=\scriptsize] at (-11.13,15.98) {$6$}; + \node[font=\scriptsize] at (-10.98,8.62) {$7$}; + \node[font=\scriptsize] at (-5.16,1.40) {$10$}; +\end{tikzpicture} +\end{minipage}\hfill +\begin{minipage}[c]{0.66\textwidth} +\caption{The equiangular decagon of Theorem~\ref{thm:main}, sides labelled by their lengths. From the marked vertex $P_0=0$, counterclockwise, the sides are $1,4,5,8,9,2,3,6,7,10$; the vertices are $P_j=\sum_{k0$ for all $k$, and $\sum_{k=0}^{N-1}s_k\,e^{2\pi ik/N}=0$ in $\C$. +\end{definition} + +\begin{remark}[Encoding of polygons]\label{rem:encoding} +For $N\ge3$ and $s_0,\dots,s_{N-1}>0$, a simple convex polygon with equal interior angles and consecutive sides $s_0,\dots,s_{N-1}$ (counterclockwise) exists if and only if \eqref{eq:close} holds with $\zeta=e^{2\pi i/N}$. +Indeed, the exterior angles of such a polygon are equal and sum to $2\pi$, so after a rotation the $k$th edge vector is $s_k\zeta^k$, and the polygon closes. +Conversely, if \eqref{eq:close} holds, the closed path $P_j=\sum_{k t + (σ k : ℕ) * d) → N = 6 +\end{lstlisting} +Here \texttt{edgeDir N k} is $e^{2\pi ik/N}$, \texttt{IsEquiangularPolygon N s} is $\Eq_N(s)$, and \decl{statement} is the universal claim negated in Theorem~\ref{thm:main}; we prove \texttt{¬ statement}. + +\subsection*{Encoding} +Polygons are encoded by Definition~\ref{def:E} (Remark~\ref{rem:encoding}); $N\ge3$ excludes $N=0$, where the closing condition would hold vacuously, and $N=1,2$. +The $N$ sides are $t,t+d,\dots,t+(N-1)d$ in the order given by $\sigma$; a negative difference gives the same set of sides, and positivity of the sides forces $t\ge1$. +The case $d=0$ is excluded, since regular polygons exist for every $N$ and would make the statement trivially false; the entry's solutions have distinct sides. +``Only'' is read as the claim that every such polygon has $N=6$; that hexagons have the property is the content of the sequence. +The only coercions are from $\mathrm{Fin}\,N$ to $\N$, from $\N$ to $\C$, and from $\mathbb{R}$ to $\C$ (for $\pi$), and \decl{statement} contains no subtraction or division in $\N$. + +\subsection*{Check against the OEIS data} +The statement file computes the sequence from its definition, without hardcoding the terms. +The function \decl{lexPerms} lists the $720$ orderings $m$ of $0,\dots,5$ in lexicographic order, and \decl{primitiveSolutions} keeps those that pass two Boolean tests. +The first, \decl{hexCloses}, says $\sum_k m_k\omega^k=0$ for $\omega=e^{i\pi/3}$ as two integer dot products with the vectors $(2\operatorname{Re}\omega^k)_k=(2,1,-1,-2,-1,1)$ and $((2/\sqrt3)\operatorname{Im}\omega^k)_k=(0,1,1,0,-1,-1)$; as noted above, $t$ and $d$ drop out of \eqref{eq:close}. +The second, \decl{normalForm}, is the entry's normalization up to rotation and reflection: start at the shortest side ($m_0=0$) and go toward the longer neighbour ($m_1>m_5$), as in the entry's comment, which rewrites $(2,6,4,5,3,7)$ as $(2,7,3,5,4,6)$. +The sequence \decl{a} concatenates the surviving patterns (offset $1$, and $0$ outside $1,\dots,12$). +The kernel checks, by \texttt{decide +kernel}, the theorems \decl{a_data} ($a(1),\dots,a(12)$ are the $12$ listed terms) and \decl{primitiveSolutions_length} (there are exactly two patterns, so no further terms); both use only the axiom \decl{propext}. +The theorem \decl{hexCloses_iff} proves that for every $m\colon\mathrm{Fin}\,6\to\N$ the sum $\sum_k m_k\cdot\texttt{edgeDir 6 k}$ vanishes if and only if \texttt{hexCloses (List.ofFn m)} holds, tying the data check to the predicate in \decl{statement}; an \texttt{example} checks the entry's hexagon $(1,6,2,4,3,5)$ against \texttt{IsEquiangularPolygon 6}. + +\section{Proof}\label{sec:proof} + +Throughout, $\zeta=e^{2\pi i/10}$; in Lean, $\zeta$ is \texttt{edgeDir 10 1}. +The proof follows the auxiliary declarations of the Lean file: the permutation \texttt{σ10}, the lemmas \decl{zeta_props} and \decl{edgeDir_ten}, and the theorem \decl{decagon}. + +\begin{lemma}[\decl{zeta_props}]\label{lem:zeta} +$\zeta^5=-1$ and $\Phi_{10}(\zeta)=\zeta^4-\zeta^3+\zeta^2-\zeta+1=0$. +\end{lemma} + +\begin{proof} +The number $\zeta$ is a primitive $10$th root of unity; in Lean this is Mathlib's \decl{Complex.isPrimitiveRoot_exp}, after identifying \texttt{edgeDir 10 1} with $e^{2\pi i/10}$ by normalizing the exponent. +Since $5\mid10$, $\zeta^5$ is a primitive square root of unity (\decl{IsPrimitiveRoot.pow_of_dvd}), hence $\zeta^5=-1$ (\decl{IsPrimitiveRoot.eq_neg_one_of_two_right}). +Next, $\zeta+1\ne0$: otherwise $\zeta=-1$ and $\zeta^2=1$, contradicting primitivity since $0<2<10$ (\decl{IsPrimitiveRoot.pow_ne_one_of_pos_of_lt}). +Finally, $(x+1)(x^4-x^3+x^2-x+1)=x^5+1$ gives $(\zeta+1)\Phi_{10}(\zeta)=\zeta^5+1=0$, and $\zeta+1\ne0$ yields $\Phi_{10}(\zeta)=0$. +\end{proof} + +\begin{lemma}[\decl{edgeDir_ten}]\label{lem:pow} +For every $k\in\N$, $e^{2\pi ik/10}=\zeta^k$. +\end{lemma} + +\begin{proof} +$\zeta^k=\exp(2\pi i/10)^k=\exp(k\cdot 2\pi i/10)$ (\decl{Complex.exp_nat_mul}), and $k\cdot2\pi i/10=2\pi ik/10$. +\end{proof} + +\begin{proposition}[\decl{decagon}]\label{prop:decagon} +With $s$ as in Theorem~\ref{thm:main}, $\Eq_{10}(s)$ holds. +\end{proposition} + +\begin{proof} +We have $10\ge3$ and $s_k\ge1>0$ for every $k$. +By Lemma~\ref{lem:pow}, the closing sum is +\[ + S=\sum_{k=0}^{9}s_k\zeta^k = 1+4\zeta+5\zeta^2+8\zeta^3+9\zeta^4+2\zeta^5+3\zeta^6+6\zeta^7+7\zeta^8+10\zeta^9 . +\] +By Lemma~\ref{lem:zeta}, $\zeta^{5+j}=-\zeta^j$ for $j=0,\dots,4$. +In $\Z[x]$ we have the identity +\[ + \sum_{k=0}^{9}s_kx^k + = -\Phi_{10}(x) + 2(x^5+1) + 3(x^6+x) + 6(x^7+x^2) + 7(x^8+x^3) + 10(x^9+x^4), +\] +since on the right the coefficients of $x^5,\dots,x^9$ are $2,3,6,7,10=s_5,\dots,s_9$ and those of $x^0,\dots,x^4$ are $-1+2,\,1+3,\,-1+6,\,1+7,\,-1+10=s_0,\dots,s_4$. +At $x=\zeta$ every term on the right vanishes, so $S=0$. +Equivalently, folding with $\zeta^{k+5}=-\zeta^k$ gives $S=\sum_{k<5}(s_k-s_{k+5})\zeta^k=-1+\zeta-\zeta^2+\zeta^3-\zeta^4=-\Phi_{10}(\zeta)=0$. +\end{proof} + +In Lean, \texttt{simp} with \decl{Fin.sum_univ_succ} and the definition of \texttt{σ10} expands the sum into its ten terms, \texttt{norm\_num} normalizes the numerals, and \texttt{linear\_combination} with coefficients $-1,2,3,6,7,10$ applied to $\Phi_{10}(\zeta)=0$ and $\zeta^{5+j}=-\zeta^j$ checks the identity above by ring normalization. + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +The map $\sigma$ has the inverse $\tau=(0,5,6,1,2,7,8,3,4,9)$; in Lean, \texttt{σ10} is the permutation with these two vectors as maps $\mathrm{Fin}\,10\to\mathrm{Fin}\,10$, and both inverse identities are checked by \texttt{decide} on all ten inputs. +The claim $\Eq_{10}(s)$ is Proposition~\ref{prop:decagon}. +If the universal statement held, then applying it with $N=10$, $t=1$, $d=1\ge1$ and $\sigma$ would give $10=6$, which is false. +\end{proof} + +\begin{remark}[Minimality and other counterexamples; not formalized]\label{rem:minimal} +By Remark~\ref{rem:encoding}, Theorem~\ref{thm:main} gives a simple convex decagon with interior angles $144^\circ$ and sides $1,4,5,8,9,2,3,6,7,10$ in counterclockwise order (Figure~\ref{fig:decagon}); the sides $t+(s_k-1)d$ give one for every $t,d\ge1$. +No counterexample has $N<10$: the values $N\in\{3,4,5,7,8,9\}$ are prime powers, and the following standard argument, in the spirit of Clark's result recorded in A118887, excludes them. +Let $N=p^a$, $M=p^{a-1}$, $\zeta_N=e^{2\pi i/N}$, and suppose $\sum_k(t+\sigma(k)d)\zeta_N^k=0$ with $d\ge1$. +Since $\sum_k\zeta_N^k=0$, the polynomial $f(x)=\sum_{k 1 + (σ10 k : ℕ) * 1) := by + refine ⟨by norm_num, fun _ => by positivity, ?_⟩ + obtain ⟨hΦ, h5⟩ := zeta_props + rw [Finset.sum_congr rfl fun k _ => by rw [edgeDir_ten]] + set ζ := edgeDir 10 1 + simp [Fin.sum_univ_succ, σ10] + have h6 : ζ ^ 6 = -ζ := by linear_combination ζ * h5 + have h7 : ζ ^ 7 = -ζ ^ 2 := by linear_combination ζ ^ 2 * h5 + have h8 : ζ ^ 8 = -ζ ^ 3 := by linear_combination ζ ^ 3 * h5 + have h9 : ζ ^ 9 = -ζ ^ 4 := by linear_combination ζ ^ 4 * h5 + norm_num + linear_combination (-1 : ℂ) * hΦ + 2 * h5 + 3 * h6 + 6 * h7 + 7 * h8 + 10 * h9 +theorem result : ¬ statement := by + intro h + have := h 10 1 1 le_rfl σ10 decagon + norm_num at this +end Math0.Frontier.A215010 +#math0_settles Math0.Frontier.A215010.result Math0.Statements.A215010.statement +\end{lstlisting} +The proof file uses no \texttt{sorry}, \texttt{native\_decide} or \texttt{set\_option}; its only uses of \texttt{decide} are the two ten-case checks for \texttt{σ10}. +The data checks of Section~\ref{sec:statement} live in the statement file; \decl{result} does not depend on them. + +\subsection*{Audit} +The command \texttt{\#math0\_settles} (in \path{lean/Math0/Audit.lean}, for statements that math0 formalizes itself) fails unless \decl{statement} is a \texttt{Prop}-valued definition without universe parameters, both \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} introduced by \texttt{native\_decide}, and custom axioms), and the type of \decl{result} is syntactically the statement or its negation, up to metadata annotations, with no unfolding. +Running \texttt{lake env lean Math0/Frontier/OEIS/A215010.lean} in the directory \path{lean} prints +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A215010.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A215010.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A215010.result' refutes 'Math0.Statements.A215010.statement' +\end{lstlisting} +so \decl{result} proves the negation of the statement and depends only on the three standard axioms; the statement itself uses \decl{Classical.choice} and \decl{Quot.sound} through Mathlib's construction of $\mathbb{R}$ and $\C$. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. +To check this result alone, run \texttt{lake build Math0.Statements.OEIS.A215010} and then \texttt{lake env lean Math0/Frontier/OEIS/A215010.lean} in the directory \path{lean}; on our machine the second command takes well under a minute of wall time (about $22$ seconds in our last run), most of it spent loading Mathlib. + +{\small +\begin{thebibliography}{99} + +\bibitem{Abel} +U.~Abel, \emph{Coincidence of the barycentre and the geometric centre of weighted points}, Math. Gaz. \textbf{103} (2019), no.~558, 409--415, doi:10.1017/mag.2019.101. + +\bibitem{Ball} +D.~Ball, \emph{Equiangular polygons}, Math. Gaz. \textbf{86} (2002), no.~507, 396--407, doi:10.2307/3621131. + +\bibitem{Bernoff} +A.~Bernoff, \emph{Bernoff's Puzzler}, MuddMath Newsletter \textbf{4} (Spring 2005), no.~1, p.~10, Harvey Mudd College. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Munteanu} +M.~Munteanu and L.~Munteanu, \emph{Rational equiangular polygons}, Applied Math. \textbf{4} (2013), no.~10, 1460--1465, doi:10.4236/am.2013.410197. + +\bibitem{A118887} +The OEIS Foundation Inc., \url{https://oeis.org/A118887}, entry by H.~Pfoertner, May~3, 2006; revision \#45, Mar.~19, 2026. + +\bibitem{A215010} +The OEIS Foundation Inc., \url{https://oeis.org/A215010}, entry by R.~Garcia, Jul.~31, 2012; revision \#43, Jan.~23, 2015. + +\bibitem{Woeginger} +G.~J. Woeginger, \emph{Nothing new about equiangular polygons}, Amer. Math. Monthly \textbf{120} (2013), no.~9, 849--850, doi:10.4169/amer.math.monthly.120.09.849. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a223395/README.md b/results/oeis-a223395/README.md new file mode 100644 index 0000000..f19e613 --- /dev/null +++ b/results/oeis-a223395/README.md @@ -0,0 +1,61 @@ +# A223395: walks on the 4 x 4 grid graph satisfy Hardin's recurrence, Barker's g.f. and closed form + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A223395 +**Date:** 2026-10-24 + +## Result + +Let a(n) be the number of walks with n vertices in the 4 x 4 grid graph P4 x P4 (the number of n x 1 arrays over the nodes 0..15 where vertically adjacent entries are adjacent nodes). Then (1) a(n) = 3a(n-1) + 2a(n-2) - 4a(n-3) for all n >= 4 (in Z); (2) (1 - x)(1 - 2x - 4x^2) * sum_{n>=1} a(n) x^n = 8x(2 - 3x^2) as formal power series over Z; (3) a(n) = (8 + (11 - 5 sqrt5)(1 - sqrt5)^n + (1 + sqrt5)^n (11 + 5 sqrt5)) / 5 for all n >= 1 (in R). + +## Assessment + +The sequence counts walks in a fixed 16-vertex graph, so it equals 1^T A^(n-1) 1. Its recurrence therefore comes from the polynomial of least degree that annihilates the all-ones vector under A. The proof checks the identity A^3·1 + 4·1 = 3A^2·1 + 2A·1 directly at every vertex, which comes down to three small symmetric 4x4 arrays, and then applies A repeatedly to get the identity for all n. The generating function and the closed form follow from the recurrence and the first three terms by routine algebra. This is a textbook transfer-matrix or main-eigenvalue argument plus a finite computation, and the manuscript itself calls it routine. + +*Follows from:* The transfer-matrix method, a(n) = 1^T A^(n-1) 1 for the adjacency matrix A of P4 x P4, together with standard main-eigenvalue theory (Cvetkovic-Doob-Sachs). The main eigenvalues of P4 x P4 are 1+sqrt5, 1 and 1-sqrt5, which are the roots of (x-1)(x^2-2x-4). In practice everything reduces to the finite check A^3·1 + 4·1 = 3A^2·1 + 2A·1 on 16 vertices. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A223395](https://oeis.org/A223395) as [`Math0.Statements.A223395.statement`](../../lean/Math0/Statements/OEIS/A223395.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A223395.lean`](../../lean/Math0/Frontier/OEIS/A223395.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Empirical: a(n) = 3*a(n-1) + 2*a(n-2) - 4*a(n-3)." and "Conjectures from _Colin Barker_, Aug 20 2018: G.f.: 8*x*(2 - 3*x^2) / ((1 - x)*(1 - 2*x - 4*x^2)) ..." + +Referees: OEIS sources (local mirror): +- A223395 (R. H. Hardin, Mar 19 2013; Barker's conjectures added Aug 20 2018; rev #7). The recurrence is still "Empirical" and the g.f. and closed form are still "Conjectures"; there are no %E lines. +- A223402 (rev #8, Oct 03 2025). The column k=1 recurrence is still listed as empirical. +- A223372 (the 3x3 analogue, also empirical). +- A081057 (P. D. Hanna 2003; g.f. and recurrence by M. Somos and V. Jovovic, Mar 2003; R. J. Mathar, Oct 2010: "apparently" counts walks from a corner of the 4x4 board; D. Scambler, Oct 2010: decomposition into independent horizontal and vertical walks, giving a binomial convolution of Fibonacci numbers; I. M. Gessel 2022). It has the same signature (3,2,−4), but for corner-start walks only. I observed that A223395(n) = 2(A081057(n) + A081057(n+1)); this identity is not recorded anywhere. +- A052899 (same signature; R. Jehn's Oct 2024 comment on walks leaving a 4x4 board). + +General theory (implies the result routinely but does not state it): +- D. Cvetković, M. Doob, H. Sachs, Spectra of Graphs (1980), Thm 1.11: the generating function of total walk counts, in terms of the characteristic polynomials of G and its complement. +- P. Rowlinson, "The main eigenvalues of a graph: a survey", Appl. Anal. Discrete Math. 1 (2007) 455–471. +- The classical spectrum of P_m□P_n, {2cos(iπ/(m+1)) + 2cos(jπ/(n+1))}. + +Checked and not relevant (they concern a different Hardin family): +- R. Dougherty-Bliss & M. Kauers, "Hardinian Arrays", arXiv:2309.00487. +- G. Spahn & R. Dougherty-Bliss, "Rectangular Hardinian Arrays" (2024). + +Web searches (arXiv, MathOverflow/MSE, general) found no explicit prior proof of the A223395 recurrence, g.f. or closed form. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a223395, + author = {{math0}}, + title = {{A223395: walks on the 4 x 4 grid graph satisfy Hardin's recurrence, Barker's g.f. and closed form}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a223395}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a223395/paper.pdf b/results/oeis-a223395/paper.pdf new file mode 100644 index 0000000..d5588ee Binary files /dev/null and b/results/oeis-a223395/paper.pdf differ diff --git a/results/oeis-a223395/paper.tex b/results/oeis-a223395/paper.tex new file mode 100644 index 0000000..474b4d2 --- /dev/null +++ b/results/oeis-a223395/paper.tex @@ -0,0 +1,353 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℝ}{{$\mathbb{R}$}}1 {∀}{{$\forall$}}1 + {∑}{{$\textstyle\sum$}}1 {∈}{{$\in$}}1 {→}{{$\to$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 + {↔}{{$\leftrightarrow$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\R}{\mathbb{R}} +\newcommand{\one}{\mathbf{1}} +\newcommand{\sq}{\mathbin{\square}} + +\title[Walks on the $4\times4$ grid graph (OEIS A223395)]{Walks on the $4\times4$ grid graph: a proof of the recurrence, generating function and closed form conjectured in OEIS A223395} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the number of walks with $n$ vertices in the $4\times4$ grid graph $P_4\sq P_4$; this is the OEIS sequence A223395, defined there as a count of $n\times1$ arrays. +We prove the three formulas that the entry records as empirical or conjectural: R.~H. Hardin's recurrence $a(n)=3a(n-1)+2a(n-2)-4a(n-3)$ for $n\ge4$, and Colin Barker's generating function $8x(2-3x^2)/((1-x)(1-2x-4x^2))$ and closed form. +The proof reduces everything to the single identity $A^3\one+4\cdot\one=3A^2\one+2A\one$ for the adjacency matrix $A$; it is a routine instance of the transfer-matrix method and of the theory of main eigenvalues, and we classify it as a new result only in the narrow sense that we found no recorded proof of these formulas. +The theorem is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definition of $a$ the kernel checks against all $24$ terms listed there. +\end{abstract} +\maketitle + +\section{Introduction} + +In March 2013 R.~H. Hardin contributed a family of OEIS sequences of the following kind: the nodes of a graph are labelled $0,1,\dots$, and one counts the $n\times k$ arrays of labels in which every move from an entry to a horizontal or vertical neighbour in the array moves along an edge of the graph. +For the $4\times4$ square grid graph these numbers form the table A223402 \cite{A223402}, and its first column ($k=1$) is A223395 \cite{A223395}. An $n\times1$ array has no horizontal neighbours, so it is simply a walk with $n$ vertices ($n-1$ steps) in the grid graph $G=P_4\sq P_4$. If $A$ is the adjacency matrix of $G$ and $\one$ the all-ones vector, then $a(n)=\one^{\mathsf T}A^{\,n-1}\one$ for $n\ge1$, and the sequence begins $16,48,152,488,1576,\dots$. + +The entry \cite{A223395} lists Hardin's ``Empirical'' recurrence $a(n)=3a(n-1)+2a(n-2)-4a(n-3)$ (March~19, 2013) and, as ``Conjectures'' added by Colin Barker on August~20, 2018, a rational generating function and a closed form (quoted in Section~\ref{sec:statement}). In revision \#7 (August~20, 2018), the latest in the copy of the OEIS data we consulted, these labels are unchanged and there is no correction line; the table A223402 (revision \#8, October~3, 2025) still lists the recurrence of column $k=1$ as empirical, and so does the $3\times3$ analogue A223372 \cite{A223372} for its recurrence $a(n)=8a(n-2)$, $n>3$. We prove the three formulas of A223395 (Theorem~\ref{thm:main}) and verify the proof in Lean~4. + +\subsection*{Prior work and status} +The math0 referees searched the OEIS, arXiv, MathOverflow, Mathematics Stack Exchange and the general web and found no explicit proof of the recurrence, the generating function or the closed form of A223395. The result is nevertheless a routine consequence of classical theory, and we do not present it as a substantive new theorem. +Since $a(n)=\one^{\mathsf T}A^{n-1}\one$, the sequence satisfies the linear recurrence given by the monic polynomial of least degree that annihilates $\one$ under $A$. Cvetkovi\'c, Doob and Sachs \cite[Theorem~1.11]{CDS} express the generating function of the total numbers of walks of a graph through the characteristic polynomials of the graph and of its complement. The roots of the annihilating polynomial are the \emph{main eigenvalues} of $G$, those whose eigenspaces are not orthogonal to $\one$ (see Rowlinson's survey \cite{Ro}); the spectrum of $P_m\sq P_n$ is the classical set $\{2\cos\frac{i\pi}{m+1}+2\cos\frac{j\pi}{n+1}\}$ \cite{CDS}, and for $P_4\sq P_4$ the main eigenvalues are $1+\sqrt5$, $1$ and $1-\sqrt5$ (Remark~\ref{rem:spectral}). None of these sources states the formulas for $P_4\sq P_4$. + +The closest prior source is A081057 \cite{A081057} (P.~D. Hanna, 2003), defined by the exponential generating function $\bigl(\sum_{n\ge0}F_{n+1}x^n/n!\bigr)^2$. M.~Somos and V.~Jovovic (March 2003) gave its generating function, its recurrence, of the same signature $(3,2,-4)$, and a closed form; R.~J. Mathar (October 2010) noted that it ``apparently'' counts the walks on the $4\times4$ board that start at a corner; D.~Scambler (October 2010) decomposed such rook walks into independent horizontal and vertical walks, giving an exponential (binomial) convolution of Fibonacci numbers; and I.~M. Gessel (2022) gave the formula $(2^nL_{n+2}+2)/5$. A comment of R.~Jehn (October 2024) in A052899 \cite{A052899}, a sequence with the same signature, concerns walks leaving a $4\times4$ board. These entries concern walks from a corner, not all walks; the relation with A223395 (Remark~\ref{rem:A081057}) is not recorded in the OEIS. Dougherty-Bliss and Kauers \cite{DK} proved conjectured recurrences for a different family of Hardin's array sequences (king moves), which does not include the sequences considered here. + +Our contribution is a complete elementary proof, which avoids eigenvalues, together with a machine-checked version of it. We are not aware of an earlier formal proof. + +\section{Statement}\label{sec:statement} + +Let $V=\{0,1,\dots,15\}$, and place node $k$ in row $\lfloor k/4\rfloor$ and column $k\bmod 4$ of a $4\times4$ grid. Nodes $u,v$ are adjacent, $u\sim v$, if they are horizontal or vertical neighbours in the grid; this is the graph $G=P_4\sq P_4$, with $24$ edges. For $n\ge1$ let $a(n)$ be the number of sequences $(v_1,\dots,v_n)\in V^n$ with $v_i\sim v_{i+1}$ for $1\le i if n = 0 then (0 : ℤ) else a n) = + 8 * PowerSeries.X * (2 - 3 * PowerSeries.X ^ 2) +def statementClosedForm : Prop := + ∀ n : ℕ, 1 ≤ n → (a n : ℝ) = + (8 + (11 - 5 * Real.sqrt 5) * (1 - Real.sqrt 5) ^ n + + (1 + Real.sqrt 5) ^ n * (11 + 5 * Real.sqrt 5)) / 5 +def statement : Prop := statementRec ∧ statementGF ∧ statementClosedForm +end Math0.Statements.A223395 +\end{lstlisting} +\begin{itemize} +\item Node $k$ is \texttt{k : Fin 16}, in row $k/4$ and column $k\%4$, and \decl{Adj} is grid adjacency; \decl{adj_iff_entry} checks in the kernel that it is exactly the neighbour list printed in the entry. An $n\times1$ array is a column \texttt{f : Fin n → Fin 16}. It has no horizontal neighbours, and as \decl{Adj} is symmetric, moving down or up between rows $i$ and $i+1$ gives the same condition, \decl{Valid}. \decl{Adj} is irreflexive, so equal consecutive entries are excluded, as the data require ($a(2)=48$ is twice the number of edges). +\item \decl{a} is the number of valid columns, a count and not a formula. The offset is $1$; the value $a(0)=1$ (the empty column) is not a term and is not used by the statement. The file also defines the walk counts \decl{cnt}, the list-based transfer step \decl{stepL}, its iterates \decl{colsL} and the fast count \decl{aL}, proves \decl{a_eq_aL} (\texttt{a n = aL n} for all \texttt{n}), and checks all $24$ listed terms $a(1),\dots,a(24)=16,\dots,7716519437928$ by \texttt{decide +kernel} (\decl{a_data}). The lemmas used for this (\decl{valid_cons}, \decl{cnt_zero}, \decl{cnt_succ}, \decl{a_succ}, \decl{colsL_eq}, \dots) are reused in our proof. +\item Hardin's recurrence carries no range in the entry; with offset $1$ it is read for all $n\ge4$, the first $n$ for which $a(n-3)$ is a term. It is stated in $\Z$ with every value of \decl{a} cast to $\Z$, so the subtraction is not truncated, and the index subtractions are exact since $n\ge4$. (With $a(0)=1$ the identity would fail at $n=3$: $152\ne172$.) Barker's series has constant term $0$ and its unit denominator is cleared, as in Theorem~\ref{thm:main}(2). The closed form is stated in $\R$ for $n\ge1$; at $n=0$ it would give $6\ne a(0)$. +\end{itemize} + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file (Section~\ref{sec:lean}); each step names its Lean declaration. + +\subsection{Walk counts by starting vertex} +For $n\ge0$ and $v\in V$ let $c_n(v)$ be the number of walks $(v_0,\dots,v_n)$ with $n+1$ vertices and $v_0=v$. In Lean, \texttt{cnt n v} is the number of valid columns \mbox{\texttt{f : Fin (n+1) → Fin 16}} with \texttt{f 0 = v}. + +\begin{lemma}[\decl{cnt_zero}, \decl{cnt_succ}, \decl{a_succ}]\label{lem:transfer} +For all $n\ge0$ and $v\in V$: $\ c_0(v)=1,\quad c_{n+1}(v)=\sum_{u\sim v}c_n(u),\quad a(n+1)=\sum_{v\in V}c_n(v)$. +\end{lemma} + +\begin{proof} +A walk with one vertex is determined by that vertex. A sequence $(v,v_1,\dots,v_{n+1})$ is a walk if and only if $v\sim v_1$ and $(v_1,\dots,v_{n+1})$ is a walk (\decl{valid_cons}); grouping these walks by $u=v_1$ gives the second identity. Grouping the walks with $n+1$ vertices by their first vertex gives the third. +\end{proof} + +In vector notation $c_0=\one$ and $c_{n+1}=Ac_n$, so $c_n=A^n\one$ and $a(n+1)=\one^{\mathsf T}A^n\one$. + +\subsection{The key identity} + +\begin{lemma}[\decl{cnt_base}]\label{lem:base} +For every $v\in V$, $c_3(v)+4c_0(v)=3c_2(v)+2c_1(v)$. +\end{lemma} + +\begin{proof} +Write a vector on $V$ as a $4\times4$ array in grid position. Lemma~\ref{lem:transfer} gives $c_1(v)=\deg v$ and +\[ + c_1=\begin{pmatrix}2&3&3&2\\3&4&4&3\\3&4&4&3\\2&3&3&2\end{pmatrix},\quad + c_2=\begin{pmatrix}6&9&9&6\\9&14&14&9\\9&14&14&9\\6&9&9&6\end{pmatrix},\quad + c_3=\begin{pmatrix}18&29&29&18\\29&46&46&29\\29&46&46&29\\18&29&29&18\end{pmatrix}. +\] +For instance, node $1$ has the neighbours $0$, $2$ and $5$, so $c_2(1)=2+3+4=9$ and $c_3(1)=6+9+14=29$. The claim reads $18+4=3\cdot6+2\cdot2$ at the corners, $29+4=3\cdot9+2\cdot3$ at the other boundary nodes and $46+4=3\cdot14+2\cdot4$ at the inner nodes. +In Lean, \decl{cnt_eq_colsL} (from \decl{colsL_eq}) rewrites $c_n(v)$ as the $v$-th entry of the list \texttt{colsL n}, obtained from the all-ones list of length $16$ by $n$ applications of the transfer step \decl{stepL}, and the $16$ resulting equations are proved by \texttt{decide +kernel}: the kernel evaluates the decision procedure by definitional unfolding to \texttt{true}. No compiled code is run and no axiom is added. +\end{proof} + +\begin{lemma}[\decl{cnt_rec}]\label{lem:propagate} +For all $n\ge0$ and $v\in V$, $c_{n+3}(v)+4c_n(v)=3c_{n+2}(v)+2c_{n+1}(v)$. +\end{lemma} + +\begin{proof} +Induction on $n$; the case $n=0$ is Lemma~\ref{lem:base}. If the identity holds for $n$ and all vertices, then by Lemma~\ref{lem:transfer} +\[ + c_{n+4}(v)+4c_{n+1}(v)=\sum_{u\sim v}\bigl(c_{n+3}(u)+4c_n(u)\bigr) + =\sum_{u\sim v}\bigl(3c_{n+2}(u)+2c_{n+1}(u)\bigr)=3c_{n+3}(v)+2c_{n+2}(v). +\] +All quantities are natural numbers and no subtraction occurs. +\end{proof} + +\begin{lemma}[\decl{a_rec}]\label{lem:arec} +For every $m\ge0$, $a(m+4)+4a(m+1)=3a(m+3)+2a(m+2)$. +\end{lemma} + +\begin{proof} +Sum Lemma~\ref{lem:propagate} (with $n=m$) over $v\in V$ and use $a(k+1)=\sum_vc_k(v)$ (Lemma~\ref{lem:transfer}). +\end{proof} + +\begin{lemma}[\decl{a_small}]\label{lem:small} +$a(1)=16$, $a(2)=48$ and $a(3)=152$. +\end{lemma} + +\begin{proof} +These are the sums of the entries of $c_0$, $c_1$ and $c_2$. In Lean: rewriting with \decl{a_eq_aL}, then \texttt{decide +kernel}. +\end{proof} + +\subsection{Proof of Theorem~\ref{thm:main}} + +\emph{(1) The recurrence} (\decl{rec_part}). Let $n\ge4$ and write $n=m+4$. Casting Lemma~\ref{lem:arec} to $\Z$ and rearranging gives $a(n)=3a(n-1)+2a(n-2)-4a(n-3)$. + +\emph{(2) The generating function} (\decl{gf_part}). Put $b_0=0$ and $b_n=a(n)$ for $n\ge1$, so that $F=\sum_{n\ge0}b_nx^n$ is the series of the statement. We have $(1-x)(1-2x-4x^2)=1-3x-2x^2+4x^3$ and $8x(2-3x^2)=16x-24x^3$. The coefficient of $x^k$ in $(1-3x-2x^2+4x^3)F$ is $b_k-3b_{k-1}-2b_{k-2}+4b_{k-3}$, where terms with a negative index are omitted. By Lemma~\ref{lem:small} it equals $0$ for $k=0$; $16$ for $k=1$; $48-3\cdot16=0$ for $k=2$; and $152-3\cdot48-2\cdot16=-24$ for $k=3$. For $k=m+4$ it equals $a(m+4)-3a(m+3)-2a(m+2)+4a(m+1)=0$ by Lemma~\ref{lem:arec}. These are the coefficients of $16x-24x^3$. In Lean the coefficients are extracted with \decl{PowerSeries.coeff_X_pow_mul'} and \decl{PowerSeries.coeff_C_mul}, followed by the case split $k\in\{0,1,2,3\}$ or $k\ge4$. + +\emph{(3) The closed form} (\decl{cf_part}). Let $s=\sqrt5$, so $s^2=5$, and for $n\ge0$ let +\[ + r(n)=\bigl(8+(11-5s)(1-s)^n+(1+s)^n(11+5s)\bigr)/5. +\] +\emph{Initial values.} Using $s^2=5$, $(1\mp s)^j(11\mp5s)$ equals $36\mp16s$, $116\mp52s$, $376\mp168s$ for $j=1,2,3$; hence $r(1)=(8+72)/5=16$, $r(2)=(8+232)/5=48$ and $r(3)=(8+752)/5=152$. +\emph{Recurrence.} For $t\in\{1,1-s,1+s\}$ we have $t^3-3t^2-2t+4=(t-1)(t^2-2t-4)=0$: for $t=1$ the first factor vanishes, and for $t=1\pm s$ the second factor is $s^2-5=0$. Multiplying by $t^{m+1}$ and combining gives $r(m+4)=3r(m+3)+2r(m+2)-4r(m+1)$ for all $m\ge0$. Explicitly, as a polynomial identity in an indeterminate $s$, +\[ + r(m+4)-3r(m+3)-2r(m+2)+4r(m+1)=\tfrac{1}{5}\,s\,(s^2-5)\bigl((1+s)^{m+1}(11+5s)-(1-s)^{m+1}(11-5s)\bigr). +\] +\emph{Induction.} We show by induction on $m\ge0$ that $a(m+j)=r(m+j)$ for $j=1,2,3$. For $m=0$ this is Lemma~\ref{lem:small} together with the initial values. If it holds for $m$, the first two equalities for $m+1$ are hypotheses, and Lemma~\ref{lem:arec}, cast to $\R$, gives +$a(m+4)=3a(m+3)+2a(m+2)-4a(m+1)=3r(m+3)+2r(m+2)-4r(m+1)=r(m+4)$. +Hence $a(n)=r(n)$ for all $n\ge1$. In Lean the initial values and the inductive step are each closed by one \texttt{linear\_combination} using $s^2=5$. + +The three parts give \decl{statement}: in Lean, \texttt{theorem result : statement := ⟨rec\_part, gf\_part, cf\_part⟩}.\qed + +\subsection{Remarks (not formalized)} + +\begin{remark}[spectral explanation]\label{rem:spectral} +The eigenvalues of $P_4$ are $2\cos(j\pi/5)$, $j=1,\dots,4$, with eigenvectors $(\sin(ij\pi/5))_{i=1}^4$; for even $j$ these are antisymmetric under $i\mapsto5-i$, hence orthogonal to $\one$, while for $j=1,3$ their coordinate sums are nonzero. So the main eigenvalues of $P_4$ are $\varphi=2\cos(\pi/5)=(1+\sqrt5)/2$ and $\psi=2\cos(3\pi/5)=(1-\sqrt5)/2$. Since $A_{G\sq H}=A_G\otimes I+I\otimes A_H$ and $\one_{G\sq H}=\one_G\otimes\one_H$, the main eigenvalues of $P_4\sq P_4$ are $2\varphi=1+\sqrt5$, $\varphi+\psi=1$ and $2\psi=1-\sqrt5$, the roots of $(t-1)(t^2-2t-4)$. This explains Lemma~\ref{lem:base}, but the proof above uses only the finite check. +\end{remark} + +\begin{remark}[relation with A081057]\label{rem:A081057} +Let $h(n)$ be A081057, so that +\[ + \sum_{n\ge0}h(n)\frac{x^n}{n!}=\Bigl(\sum_{n\ge0}F_{n+1}\frac{x^n}{n!}\Bigr)^2=\frac{\bigl(\varphi e^{\varphi x}-\psi e^{\psi x}\bigr)^2}{5}. +\] +As $\varphi+\psi=1$ and $\varphi\psi=-1$, this gives $h(n)=\bigl(2+\varphi^2(1+\sqrt5)^n+\psi^2(1-\sqrt5)^n\bigr)/5$ for $n\ge0$. Since $2\varphi^2(1+2\varphi)=(3+\sqrt5)(2+\sqrt5)=11+5\sqrt5$ and $2\psi^2(1+2\psi)=11-5\sqrt5$, Theorem~\ref{thm:main}(3) yields +$a(n)=2\bigl(h(n)+h(n+1)\bigr)$ for $n\ge1$; e.g.\ $16=2(2+6)$, $48=2(6+18)$, $152=2(18+58)$. We have not looked for a bijective explanation. +\end{remark} + +\begin{remark}[the $3\times3$ grid]\label{rem:3x3} +The same method proves the empirical recurrence of A223372 \cite{A223372}, the walk counts of $P_3\sq P_3$: there $c_1$ takes the values $2,3,4$ at the corners, the boundary midpoints and the centre, and $c_3$ the values $16,24,32$, so $A^3\one=8A\one$. Applying $A^k$ and summing gives $a(n)=8a(n-2)$ whenever $n-1\ge3$, i.e.\ for $n>3$, exactly Hardin's range; at $n=3$ it fails, as $a(3)=68\ne8a(1)=72$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +The proof is in the file \path{lean/Math0/Frontier/OEIS/A223395.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A223395.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is the theorem \decl{Math0.Frontier.A223395.result}, whose type is \decl{Math0.Statements.A223395.statement}; the auxiliary lemmas \decl{cnt_eq_colsL}, \decl{cnt_base}, \decl{cnt_rec}, \decl{a_rec}, \decl{rec_part}, \decl{a_small}, \decl{gf_part} and \decl{cf_part} are \texttt{private} and state what Section~\ref{sec:proof} says. Neither file contains \texttt{sorry}, \texttt{admit}, \texttt{native\_decide}, \texttt{axiom} or \texttt{set\_option}; the kernel computations (\texttt{decide +kernel} in \decl{cnt_base} and \decl{a_small}, and in \decl{adj_iff_entry} and \decl{a_data} of the statement file) run within the default heartbeat limit. The proof file ends with + +\noindent\begin{minipage}{\linewidth} +\begin{lstlisting} +#math0_settles Math0.Frontier.A223395.result Math0.Statements.A223395.statement +\end{lstlisting} +\end{minipage} + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which rejects \decl{sorryAx}, \decl{Lean.ofReduceBool} (from \texttt{native\_decide}) and custom axioms; and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata, with no unfolding. Here it reports: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A223395.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A223395.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A223395.result' proves 'Math0.Statements.A223395.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, both pinned in \path{lean/}. The repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}; this result does not use it, since the statement is math0's own formalization of the OEIS entry. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The single file is checked by \texttt{lake env lean Math0/Frontier/OEIS/A223395.lean} in the directory \path{lean}, in about $15$ seconds on our machine. + +{\footnotesize +\begin{thebibliography}{99} + +\bibitem{CDS} +D.~M. Cvetkovi\'c, M.~Doob, and H.~Sachs, \emph{Spectra of Graphs: Theory and Application}, Pure and Applied Mathematics \textbf{87}, Academic Press, New York, 1980. + +\bibitem{DK} +R.~Dougherty-Bliss and M.~Kauers, \emph{Hardinian arrays}, Electron. J. Combin. \textbf{31} (2024), no.~2, Paper No.~P2.9; arXiv:2309.00487. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A052899} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, A052899, \url{https://oeis.org/A052899}. + +\bibitem{A081057} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, A081057, \url{https://oeis.org/A081057}. + +\bibitem{A223372} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, A223372, \url{https://oeis.org/A223372}. + +\bibitem{A223395} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, A223395, \url{https://oeis.org/A223395}. + +\bibitem{A223402} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, A223402, \url{https://oeis.org/A223402}. + +\bibitem{Ro} +P.~Rowlinson, \emph{The main eigenvalues of a graph: a survey}, Appl. Anal. Discrete Math. \textbf{1} (2007), no.~2, 455--471. + +\end{thebibliography} +} +\end{document} diff --git a/results/oeis-a229159/README.md b/results/oeis-a229159/README.md new file mode 100644 index 0000000..209460a --- /dev/null +++ b/results/oeis-a229159/README.md @@ -0,0 +1,36 @@ +# Every odd prime is a side of a Heronian triangle (A229159) + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A229159 +**Date:** 2026-10-18 + +## Result + +For every prime p > 2 there are natural numbers x, y, z, A such that x, y, z satisfy the strict triangle inequalities (x < y + z, y < x + z, z < x + y), Heron's formula 16 A^2 = (x+y+z)(-x+y+z)(x-y+z)(x+y-z) holds in Z, and at least one of x, y, z equals p. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A229159](https://oeis.org/A229159) as [`Math0.Statements.A229159.statement`](../../lean/Math0/Statements/OEIS/A229159.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A229159.lean`](../../lean/Math0/Frontier/OEIS/A229159.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: for all prime p > 2 there exists an integer-sided triangle with integer area where at least one side is of length p." (entry by _Michel Lagneau_, Sep 17 2013) + +Referees: Classical formula (n, (n^2-1)/2, (n^2+1)/2) for odd n, credited to the Pythagoreans (Proclus, Commentary on Euclid's Elements I.47; H. Eves, An Introduction to the History of Mathematics, sec. 3-4; cf. Euclid, Elements X, Lemma 1 before Prop. 29). OEIS A046079, comment by Richard R. Forberg, May 31 2013: "For odd n: L = (n^2-1)/2 and H = L+1". In the same entry, Ant King (Jan 29 2011) notes that for n > 2 the n with exactly one Pythagorean triangle on leg n are the primes and their doubles. OEIS A042965 (Sloane, May 30 2014): the primes that are a difference of two squares are exactly the odd primes. Related: A009004 (short legs of Pythagorean triangles). Mathlib has the Pythagorean triple classification (Mathlib/NumberTheory/PythagoreanTriples.lean) but not this Heronian statement. I found no source that addresses A229159's conjecture directly; it is resolved immediately by the classical formula. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a229159, + author = {{math0}}, + title = {{Every odd prime is a side of a Heronian triangle (A229159)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a229159}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a229159/paper.pdf b/results/oeis-a229159/paper.pdf new file mode 100644 index 0000000..2afa9af Binary files /dev/null and b/results/oeis-a229159/paper.pdf differ diff --git a/results/oeis-a229159/paper.tex b/results/oeis-a229159/paper.tex new file mode 100644 index 0000000..f63e250 --- /dev/null +++ b/results/oeis-a229159/paper.tex @@ -0,0 +1,376 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,ring,push_cast}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {→}{{$\to$}}1 + {≤}{{$\le$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\T}{\mathsf{T}} +\newcommand{\pr}{\operatorname{prime}} + +\title[Every odd prime is a side of a Heronian triangle]{Every odd prime is a side length of a triangle with integer sides and integer area (OEIS A229159)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +We prove that for every prime $p>2$ there is a non-degenerate triangle with integer side lengths and integer area one of whose sides has length $p$; this is the conjecture recorded by Michel Lagneau in 2013 in the OEIS entry A229159, whose terms are the least such areas. +The conjecture is an immediate consequence of the classical fact, attributed to Pythagoras by Proclus, that every odd $n=2m+1\ge 3$ is a leg of the right triangle with sides $n$, $(n^2-1)/2$, $(n^2+1)/2$, whose area $m(m+1)(2m+1)$ is an integer. +The result is therefore known, and we classify this note as a first formal proof of a known result, not as new mathematics. +The theorem is verified in Lean~4 against a statement that math0 formalized from the OEIS entry and that was reviewed for fidelity and frozen before the proof attempt; the definitions in that statement file are checked by the kernel against the first $19$ listed terms, and the same file shows that five later listed terms are not minimal. +\end{abstract} +\maketitle + +\section{Introduction} + +A \emph{Heronian triangle} is a non-degenerate triangle whose side lengths and area are integers. +The OEIS entry A229159 \cite{A229159}, submitted by Michel Lagneau on September~17, 2013, has the name ``Smallest integer areas of integer-sided triangles where at least one side is of length prime(n)'', with offset~$1$; its first terms are +\[ + 0,\ 6,\ 6,\ 42,\ 66,\ 24,\ 36,\ 114,\ 966,\ 60,\ 930,\ 114,\ 126,\ 1290,\ 4230,\ 90,\ 1770,\ 330,\ 2814,\ \dots, +\] +where $a(1)=0$ records that no such triangle has a side of length $\pr(1)=2$. +The entry states the conjecture that every prime $p>2$ is a side length of a Heronian triangle (Section~\ref{sec:statement}), that is, $a(n)>0$ for all $n\ge2$. +A companion entry by the same author, A226453 \cite{A226453}, lists the integer areas of integer-sided triangles with at least one side of prime length. + +\subsection*{Prior work} +The conjecture follows at once from a classical construction. +Proclus, in his commentary on Proposition~I.47 of Euclid's \emph{Elements} \cite{Proclus}, attributes to Pythagoras a rule that takes an odd number $n$ as the shorter leg of a right triangle, $(n^2-1)/2$ as the other leg and $(n^2+1)/2$ as the hypotenuse; see also Eves \cite[Sec.~3-4]{Eves}. +The lemma that precedes Proposition~X.29 of the \emph{Elements} \cite[vol.~3]{Heath} constructs, in general, two square numbers whose sum is a square; in modern terms it contains this rule as a special case. +For an odd prime $p$ the rule gives a right triangle with integer sides whose area $p(p^2-1)/4$ is an integer, since $8\mid p^2-1$. + +The rule, and the fact that every odd prime is a leg of a Pythagorean triangle, were recorded in the OEIS before Lagneau's entry. +In A046079 \cite{A046079} (number of Pythagorean triangles with leg $n$), Ant King noted on January~29, 2011 that for $n>2$ the positions of the ones are the primes and their doubles, so each odd prime is a leg of exactly one Pythagorean triangle; and Richard R.~Forberg noted on May~31, 2013, with $L$ the length of the longest leg and $H$ the hypotenuse, that ``For odd $n$: $L=(n^2-1)/2$ and $H=L+1$''. +In a related direction, A042965 \cite{A042965} records (in a comment by Sharon Sela, January~25, 2002) that its terms are the nonnegative integers that are differences of two squares, and N.~J.~A.~Sloane added on May~30, 2014, after Lagneau's entry, that the primes in the sequence are all the odd primes. + +The A229159 entry (revision \#18 of September~16, 2017, which is the version we read) still states the conjecture and does not mention this construction. +The math0 referees found no source that addresses the conjecture of A229159 directly. +Mathlib \cite{Mathlib} contains the classification of Pythagorean triples (\path{Mathlib/NumberTheory/PythagoreanTriples.lean}) but not this statement, and the statement is not among those of the formal-conjectures repository \cite{FC}. +The mathematics in this note is classical and elementary. +What we add is a complete proof that matches a kernel-checked Lean proof of a frozen formal statement (Section~\ref{sec:lean}); to our knowledge it is the first formal proof of the statement. +We also record (Remark~\ref{rem:errata}) a by-product of the check of the formal definitions against the OEIS data: the listed terms $a(20)$, $a(25)$, $a(29)$, $a(32)$ and $a(40)$ are not minimal. + +\section{Statement}\label{sec:statement} + +\subsection*{The OEIS conjecture} +The comments of A229159 contain the following sentence, verbatim: +\begin{quote} +Conjecture: for all prime p $>$ 2 there exists an integer-sided triangle with integer area where at least one side is of length p. +\end{quote} +This is the wording of the current revision (\#18). +Michel Lagneau added the conjecture when he submitted the entry on September~17, 2013 (revision \#7 in the entry's edit history), in the form ``Conjecture: for all prime p $>$ 2 there exists an integer-sided triangles where at least one side is of p length.'' +The words ``with integer area'' and the present phrasing come from a copy-edit by Jon E.~Schoenfield of September~15, 2017 (revision \#12, approved as revision \#18). +Read together with the entry's name, which asks for integer areas, the original wording expresses the same conjecture; we formalize the current wording. + +\subsection*{Mathematical formulation} +By Heron's formula, a triangle with side lengths $x,y,z$ has area $S$ with +\[ + 16S^2=(x+y+z)(-x+y+z)(x-y+z)(x+y-z). +\] +A triple of positive reals is the triple of side lengths of a non-degenerate triangle if and only if it satisfies the three strict triangle inequalities, and the right-hand side is then positive. +This motivates the following definition. + +\begin{definition}\label{def:T} +For $x,y,z,A\in\N$ write $\T(x,y,z;A)$ if $x2$ there are $x,y,z,A\in\N$ with $\T(x,y,z;A)$ and $p\in\{x,y,z\}$. +\end{theorem} + +The proof (Section~\ref{sec:proof}) gives an explicit witness: if $p=2m+1$, then +\[ + \T\bigl(2m+1,\ 2m^2+2m,\ 2m^2+2m+1;\ m(m+1)(2m+1)\bigr). +\] + +\subsection*{Lean statement} +The statement is the definition \decl{Math0.Statements.A229159.statement} in the frozen math0 statement file \path{lean/Math0/Statements/OEIS/A229159.lean}. +The two definitions it consists of are, verbatim (docstrings omitted; both lie in the namespace \decl{Math0.Statements.A229159}): +\begin{lstlisting} +def IsIntTriangle (x y z A : ℕ) : Prop := + x < y + z ∧ y < x + z ∧ z < x + y ∧ + 16 * (A : ℤ) ^ 2 = + ((x : ℤ) + y + z) * (-(x : ℤ) + y + z) * ((x : ℤ) - y + z) * ((x : ℤ) + y - z) + +def statement : Prop := + ∀ p : ℕ, p.Prime → 2 < p → + ∃ x y z A : ℕ, IsIntTriangle x y z A ∧ (x = p ∨ y = p ∨ z = p) +\end{lstlisting} +\texttt{IsIntTriangle x y z A} is $\T(x,y,z;A)$, and \decl{statement} is Theorem~\ref{thm:main}. + +\subsection*{Encoding} +An ``integer-sided triangle'' is a triple of natural numbers satisfying the strict triangle inequalities, so degenerate triangles are excluded and every side is at least~$1$. +Without this exclusion the statement would be trivial, since $(p,p,2p)$ would be a ``triangle'' of area~$0$, and $a(1)=0$ would no longer mean that there is no triangle. +``Integer area'' means that the area given by Heron's formula is a natural number $A$; the formal statement uses Heron's formula as the definition of the area and does not refer to Euclidean geometry. +The four factors are computed in $\Z$, so truncated subtraction in $\N$ plays no role. +``At least one side is of length $p$'' is the disjunction $x=p\lor y=p\lor z=p$. +The entry's Maple program uses the same notion: for sides $a\le b\le c$ it computes $x=s(s-a)(s-b)(s-c)$ with $s=(a+b+c)/2$, takes $\sqrt{x}$ only when $x>0$, and tests whether it is an integer; since $16x$ is the Heron product, this is the condition $\T(a,b,c;\sqrt{x})$. + +\subsection*{Check against the OEIS data} +The statement file also defines the sequence itself: +\begin{lstlisting} +def areas (m : ℕ) : Set ℕ := + {A | ∃ x y z : ℕ, IsIntTriangle x y z A ∧ (x = m ∨ y = m ∨ z = m)} + +noncomputable def prime (n : ℕ) : ℕ := Nat.nth Nat.Prime (n - 1) + +noncomputable def a (n : ℕ) : ℕ := sInf (areas (prime n)) +\end{lstlisting} +Here \texttt{prime n} is the $n$th prime with \texttt{prime 1 = 2}, and \decl{sInf} on $\N$ is the least element of a nonempty set and $0$ for the empty set, which matches the convention $a(1)=0$. +In these terms \decl{statement} says that \texttt{areas p} is nonempty for every prime $p>2$, that is, $a(n)\ne0$ for $n\ge2$. + +The file proves \decl{a_data}, which states that $(a(1),\dots,a(19))$ equals the first $19$ listed terms (the primes up to~$67$). +The value $a(1)=0$ is proved by hand from \texttt{areas 2 =~}$\emptyset$ (Remark~\ref{rem:two}). +For $n=2,\dots,19$ a single \texttt{decide +kernel} evaluates, in the kernel, a Boolean certificate for each table entry $(n,p,A_0,b,c)$: that $p$ is prime and is the $n$th prime (via \decl{Nat.count}); that $(p,b,c)$ satisfies the triangle inequalities with Heron product $16A_0^2$ (the witnesses are the triangles in the entry's table); and that no triangle with a side $p$ has an integer area below $A_0$. +For the last check, a triangle $(p,b,c)$ with $b\le c$ has $d=c-b0$, so $x0$, so $z2$. +Then $p\ne2$, so $p$ is odd and $p=2m+1$ for some $m\in\N$; since $p>2$ we have $m\ge1$. +Lemma~\ref{lem:odd} gives $\T(p,\,2m^2+2m,\,2m^2+2m+1;\,m(m+1)(2m+1))$, and the first side is $p$. +\end{proof} + +In Lean, the oddness of $p$ is \decl{Nat.Prime.odd_of_ne_two}, and the witness is supplied with the first disjunct $x=p$. + +\begin{remark} +The triangle of Lemma~\ref{lem:odd} is the right triangle of the Pythagorean rule: $x^2+y^2=z^2$, and $A=xy/2$. +Neither fact is used in the proof, which checks Heron's identity directly. +Primality is used only to obtain that $p$ is odd, so the argument shows that every odd $n\ge3$ is a side length of a Heronian triangle. +It also gives $1\le a(n)\le \pr(n)\bigl(\pr(n)^2-1\bigr)/4$ for $n\ge2$; we did not state this bound in Lean. +The witness is in general far from minimal: for $p=7$ it has area $84$, whereas $a(4)=42$, attained by $(7,15,20)$. +\end{remark} + +\begin{remark}\label{rem:two} +The hypothesis $p>2$ is necessary; the statement file proves \texttt{areas 2 =~}$\emptyset$. +By symmetry of $\T$ it suffices to consider triangles $(2,b,c)$ with $b\le c$, and then $c=1} a(n) x^n * (x^14 - x^13 - x + 1) = -2x^14 + 4x^13 + 2x^12 + 2x^11 + 2x^10 + 2x^9 + 2x^8 + 4x^7 + 2x^6 + 2x^5 + 2x^4 + 2x^3 + 2x^2 + 4x in Z[[x]]. We prove that this identity is false. + +## Assessment + +A row meets the circle exactly when its vertical extent overlaps [-n, n]. That gives a(n) = 2*floor(2n/sqrt(3)) + 2, which is also what the entry's own program computes for n up to 100. A rational g.f. with denominator (1-x)(1-x^13) would force a(n+13) - a(n) = 30 for every n. Because the slope 4/sqrt(3) is irrational, this cannot hold for all n, and a direct computation of four values gives the first failure at n = 97 (226 instead of 224). The refutation needs only this short argument and a finite check: Stephan's g.f. was a fit to the 61 listed terms, and no new idea was required. The counterexample is a real failure of the g.f. for the sequence as defined, not a degenerate or excluded case. + +*Follows from:* Elementary closed form a(n) = 2*floor(2n/sqrt(3)) + 2, which is what the entry's own Small Basic program computes, together with direct evaluation of a(83), a(84), a(96), a(97) and comparison of the x^97 coefficient after clearing the denominator (1-x)(1-x^13). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A242396](https://oeis.org/A242396) as [`Math0.Statements.A242396.statement`](../../lean/Math0/Statements/OEIS/A242396.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A242396.lean`](../../lean/Math0/Frontier/OEIS/A242396.lean) refutes (proves the negation of) it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: G.f., conjectured: (-2*x^14 + 4*x^13 + 2*x^12 + 2*x^11 + 2*x^10 + 2*x^9 + 2*x^8 + 4*x^7 + 2*x^6 + 2*x^5 + 2*x^4 + 2*x^3 + 2*x^2 + 4*x)/(x^14 - x^13 - x + 1). - _Ralf Stephan_, May 18 2014 (also: Asymptotics from g.f.: a(n) ~ 30/13 * n. - _Ralf Stephan_, May 18 2014) + +Referees: Sources checked: +- The OEIS A242396 entry, from the local mirror and https://raw.githubusercontent.com/oeis/oeisdata/main/seq/A242/A242396.seq. Both show revision #18 (May 31, 2014), and the g.f. is still marked "conjectured" with no correction. +- The cross-referenced entries A242394 and A242395. +- A mirror search for the sequences ⌊2n/√3⌋ and 2⌊2n/√3⌋+2. The only match was A242396 itself. +- Ralf Stephan's conjecture list at ark.in-berlin.de/conj.txt, which covers only the 2004–2005 list. +- Four papers on proving OEIS conjectures, none of which mention A242396: + - arXiv:2607.24832, "Further proofs of conjectures from the OEIS" + - arXiv:2410.07237 + - S. Fried, JIS vol. 28 (fried15) + - S. Fried, JIS vol. 29 (fried21) +- General web searches (arXiv, MathOverflow/Math StackExchange, SeqFan). These found no counterexample or refutation of Stephan's g.f. for A242396. + +No prior resolution was found. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a242396, + author = {{math0}}, + title = {{Stephan's conjectured g.f. for A242396 is false (first failure at n = 97)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a242396}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a242396/paper.pdf b/results/oeis-a242396/paper.pdf new file mode 100644 index 0000000..b87b68a Binary files /dev/null and b/results/oeis-a242396/paper.pdf differ diff --git a/results/oeis-a242396/paper.tex b/results/oeis-a242396/paper.tex new file mode 100644 index 0000000..5723306 --- /dev/null +++ b/results/oeis-a242396/paper.tex @@ -0,0 +1,313 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,unfold,infer_instance}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℝ}{{$\mathbb{R}$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {≤}{{$\le$}}1 + {√}{{$\surd$}}1 {⟦}{{$[\![$}}1 {⟧}{{$]\!]$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{√}{\ensuremath{\surd}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\R}{\mathbb{R}} +\newcommand{\fps}{\Z[\![x]\!]} +\newcommand{\coef}[1]{[x^{#1}]} +\newcommand{\MI}{\mathrm{M}} + +\title[The conjectured generating function of OEIS A242396 is false]{Rows of the unit triangular tiling meeting a circle of radius $n$: the conjectured generating function of OEIS A242396 fails at $n=97$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 21, 2026} + +\begin{document} +\begin{abstract} +For $n\ge1$ let $a(n)$ be the number of rows of the tiling of the plane by unit equilateral triangles that meet a circle of radius $n$ (OEIS A242396). In 2014 R.~Stephan conjectured that $\sum_{n\ge1}a(n)x^n=N(x)/\bigl((1-x)(1-x^{13})\bigr)$ for an explicit polynomial $N$ of degree~$14$; this rational function reproduces all $61$ terms listed in the entry. +We prove that the conjecture is false: comparing coefficients of $x^{97}$, it would force $a(97)-a(96)-a(84)+a(83)=0$, whereas $a(83),a(84),a(96),a(97)=192,194,222,226$, so this expression equals $2$. As far as we and the math0 referees could determine, the refutation is a new result, although the argument is elementary. +It is verified in Lean~4 against a statement that math0 formalized from the OEIS entry and that was reviewed for fidelity and frozen before any proof attempt; in that statement $a(n)$ is proved equal to the geometric row count, and its first $61$ values are checked by the kernel against the OEIS data. +\end{abstract} +\maketitle + +\section{Introduction} + +On May~13, 2014, K.~Ngaokrajang contributed three related sequences to the OEIS. A242394 \cite{A242394} and A242395 \cite{A242395} count the unit equilateral triangles of the standard triangular tiling that meet the circle of radius $n$ centred at $(0,0)$ and at $(1/2,0)$, respectively. A242396 \cite{A242396} counts the \emph{rows} of the tiling that meet the circle; the comments of A242394 and A242395 note that this count is the same for both centres. The entry A242396 lists the $61$ terms $a(1),\dots,a(61)=4,6,8,\dots,142$ and contains a Small Basic program that prints $a(1),\dots,a(100)$. + +On May~18, 2014, R.~Stephan added a conjectured rational generating function with denominator $x^{14}-x^{13}-x+1=(1-x)(1-x^{13})$, together with the consequence $a(n)\sim\frac{30}{13}n$ (both quoted verbatim in Section~\ref{sec:statement}). The rational function reproduces all $61$ listed terms. We show that the conjecture is false (Theorem~\ref{thm:main}). + +\subsection*{Method} +A row meets the circle exactly when its vertical extent meets $[-n,n]$; this gives $a(n)=2\lfloor 2n/\sqrt3\rfloor+2$ (Lemma~\ref{lem:closed}). Clearing the denominator, the conjecture forces the coefficient of $x^{97}$ in $\bigl(\sum_{n\ge1}a(n)x^n\bigr)(x^{14}-x^{13}-x+1)$, namely $a(97)-a(96)-a(84)+a(83)$, to vanish, but this coefficient is $226-222-194+192=2$. The Lean proof extracts this coefficient and lets the kernel evaluate the four values directly from the definition of $a$. Since $a(n)$ grows with the irrational slope $4/\sqrt3$, no identity of this shape can hold; Remark~\ref{rem:mech} identifies $n=97$ as the first coefficient at which the conjectured series and $a$ differ. + +\subsection*{Status and prior work} +The math0 referees checked the current version of the entry, both in a local mirror of the OEIS data and in the public \texttt{oeisdata} repository: it is revision \#18 (May~31, 2014), and the generating function is still marked ``conjectured'', with no correction or comment. The cross-referenced entries A242394 and A242395 say nothing about it, and a search of the OEIS mirror for the sequences $\lfloor 2n/\sqrt3\rfloor$ and $2\lfloor 2n/\sqrt3\rfloor+2$ finds only A242396 itself. The status page \url{http://www.ark.in-berlin.de/conj.txt} of Stephan's earlier conjecture collection covers only conjectures from 2004--2005 and does not mention A242396. Fried's papers proving conjectures from the OEIS \cite{Fr24,Fr25,Fr26a,Fr26b} do not mention A242396, and searches of arXiv, MathOverflow, Mathematics Stack Exchange and the SeqFan mailing list found no counterexample or refutation. The sequence is not among the OEIS statements of the formal-conjectures repository \cite{FC} (at the commit pinned in math0). We therefore classify the result as \emph{new}, with two caveats: the argument is elementary, and the entry's own program, which runs up to $n=100$, already computes $a(97)=226$, a value incompatible with the conjectured generating function (Remark~\ref{rem:program}). We found no record that this discrepancy had been noticed. + +\section{Statement}\label{sec:statement} + +Let $h=\sqrt3/2$. The tiling of the plane by equilateral triangles of side $1$ with a vertex at the origin and horizontal sides has vertices $(k+\tfrac i2,\,ih)$, $i,k\in\Z$; this is consistent with the program of A242394, which searches for tiling vertices on the circle among the points $(s/2,\,ih)$, $s,i\in\Z$. For $j\in\Z$, the triangles between the lines $y=jh$ and $y=(j+1)h$ form \emph{row~$j$}; they tile exactly the closed strip $S_j=\{(x,y)\in\R^2 : jh\le y\le (j+1)h\}$, so row~$j$ meets a set exactly when $S_j$ does. + +\begin{definition}\label{def:a} +For $c\in\R$ and $n\in\N$ let $C_{c,n}=\{(x,y):(x-c)^2+y^2=n^2\}$ and $a(n)=\#\{j\in\Z : S_j\cap C_{c,n}\neq\emptyset\}$. By Lemma~\ref{lem:geom} this does not depend on $c$; in particular the centres $(0,0)$ and $(1/2,0)$ of the OEIS name give the same sequence. +\end{definition} + +The entry A242396 \cite{A242396} (offset $1$, author K.~Ngaokrajang) has the name ``Number of rows of equilateral triangles (sides length = 1) that intersect the circumference of a circle of radius n centered at (0,0) or (1/2,0).'' Its FORMULA section reads, verbatim: +\begin{quote} +{\small\texttt{G.f., conjectured: (-2*x\^{}14 + 4*x\^{}13 + 2*x\^{}12 + 2*x\^{}11 + 2*x\^{}10 + 2*x\^{}9 + 2*x\^{}8 + 4*x\^{}7 + 2*x\^{}6 + 2*x\^{}5 + 2*x\^{}4 + 2*x\^{}3 + 2*x\^{}2 + 4*x)/(x\^{}14 - x\^{}13 - x + 1). - \_Ralf Stephan\_, May 18 2014}} + +{\small\texttt{Asymptotics from g.f.: a(n) \textasciitilde{} 30/13 * n. - \_Ralf Stephan\_, May 18 2014}} +\end{quote} +Put $F(x)=\sum_{n\ge1}a(n)x^n\in\fps$, $D(x)=x^{14}-x^{13}-x+1=(1-x)(1-x^{13})$ and +\[ + N(x)=4x+2x^2+2x^3+2x^4+2x^5+2x^6+4x^7+2x^8+2x^9+2x^{10}+2x^{11}+2x^{12}+4x^{13}-2x^{14}. +\] + +\begin{conjecture}[Stephan, 2014]\label{conj} +$F(x)=N(x)/D(x)$ in $\fps$. +\end{conjecture} + +Since $D$ has constant term $1$, it is a unit of $\fps$, so Conjecture~\ref{conj} is equivalent to $F(x)\,D(x)=N(x)$. + +\begin{theorem}\label{thm:main} +Conjecture~\ref{conj} is false: the coefficient of $x^{97}$ in $F(x)D(x)$ is $2$, whereas the coefficient of $x^{97}$ in $N(x)$ is $0$. +\end{theorem} + +The derived claim $a(n)\sim\frac{30}{13}n$ is also false (Remark~\ref{rem:mech}); it is not part of Theorem~\ref{thm:main} and is not formalized. + +\subsection*{Lean formalization} +math0 formalized the statement in \path{lean/Math0/Statements/OEIS/A242396.lean}, which was reviewed for fidelity and frozen before any proof attempt. Its definitions, verbatim (the copyright header, the import, docstrings, blank lines, theorems and the auxiliary definition \decl{statement_asymptotic} omitted), are: +\begin{lstlisting} +namespace Math0.Statements.A242396 +open Real +def RowMeets (c : ℝ) (n : ℕ) (j : ℤ) : Prop := + ∃ x y : ℝ, (x - c) ^ 2 + y ^ 2 = (n : ℝ) ^ 2 ∧ + (j : ℝ) * (√3 / 2) ≤ y ∧ y ≤ ((j : ℝ) + 1) * (√3 / 2) +def MeetsInt (n : ℕ) (j : ℤ) : Prop := + (j ≤ 0 ∨ 3 * j ^ 2 ≤ 4 * (n : ℤ) ^ 2) ∧ (0 ≤ j + 1 ∨ 3 * (j + 1) ^ 2 ≤ 4 * (n : ℤ) ^ 2) +instance (n : ℕ) : DecidablePred (MeetsInt n) := fun _ => by + unfold MeetsInt; infer_instance +def a (n : ℕ) : ℕ := + ((Finset.range (4 * n + 5)).filter (fun i : ℕ => MeetsInt n ((i : ℤ) - (2 * n + 2)))).card +open PowerSeries in +def statement : Prop := + PowerSeries.mk (fun n => if n = 0 then (0 : ℤ) else a n) * (X ^ 14 - X ^ 13 - X + 1) = + -2 * X ^ 14 + 4 * X ^ 13 + 2 * X ^ 12 + 2 * X ^ 11 + 2 * X ^ 10 + 2 * X ^ 9 + 2 * X ^ 8 + + 4 * X ^ 7 + 2 * X ^ 6 + 2 * X ^ 5 + 2 * X ^ 4 + 2 * X ^ 3 + 2 * X ^ 2 + 4 * X +end Math0.Statements.A242396 +\end{lstlisting} +Here \texttt{RowMeets c n j} says $S_j\cap C_{c,n}\ne\emptyset$, and \texttt{MeetsInt n j} is the integer condition +\[ + \MI(n,j):\quad \bigl(j\le0\ \text{or}\ 3j^2\le4n^2\bigr)\ \text{and}\ \bigl(j+1\ge0\ \text{or}\ 3(j+1)^2\le4n^2\bigr). +\] +The function \decl{a} counts the $i<4n+5$ with $\MI(n,i-(2n+2))$, i.e.\ the $j\in[-(2n+2),2n+2]$ with $\MI(n,j)$; it is a finite count that the kernel can evaluate, not a closed form. The statement file connects it with Definition~\ref{def:a} and with the OEIS data through the following proved theorems (statements verbatim): +\begin{lstlisting} +theorem rowMeets_iff (c : ℝ) (n : ℕ) (j : ℤ) : RowMeets c n j ↔ MeetsInt n j +theorem bounds_of_meetsInt {n : ℕ} {j : ℤ} (h : MeetsInt n j) : + -(2 * (n : ℤ) + 2) ≤ j ∧ j ≤ 2 * n + 2 +theorem a_eq_ncard (c : ℝ) (n : ℕ) : a n = {j : ℤ | RowMeets c n j}.ncard +\end{lstlisting} +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +theorem a_data : (List.range 61).map (fun i => a (i + 1)) = + [4, 6, 8, 10, 12, 14, 18, 20, 22, 24, 26, 28, 32, 34, 36, 38, 40, 42, 44, 48, 50, 52, 54, 56, + 58, 62, 64, 66, 68, 70, 72, 74, 78, 80, 82, 84, 86, 88, 92, 94, 96, 98, 100, 102, 104, + 108, 110, 112, 114, 116, 118, 122, 124, 126, 128, 130, 132, 134, 138, 140, 142] +\end{lstlisting} +The first three are the content of Lemma~\ref{lem:geom}; \decl{a_data}, proved by \texttt{decide +kernel} (evaluation in the Lean kernel), says that $a(1),\dots,a(61)$ are exactly the terms listed in the entry. + +\begin{lemma}\label{lem:geom} +Let $c\in\R$, $n\in\N$ and $j\in\Z$. +\begin{enumerate} +\item $S_j\cap C_{c,n}\ne\emptyset$ if and only if $jh\le n$ and $-n\le(j+1)h$. +\item For $k\in\Z$: $kh\le n$ if and only if $k\le0$ or $3k^2\le4n^2$. +\item $S_j\cap C_{c,n}\ne\emptyset$ if and only if $\MI(n,j)$. +\item If $\MI(n,j)$, then $-(2n+2)\le j\le 2n+2$. +\end{enumerate} +Consequently, for every $c$, the number computed by \textup{\texttt{a}} equals $\#\{j\in\Z:S_j\cap C_{c,n}\ne\emptyset\}$. +\end{lemma} + +\begin{proof} +(1) If $(x,y)\in S_j\cap C_{c,n}$, then $y^2\le n^2$, so $-n\le y\le n$, and $jh\le y\le(j+1)h$ gives both inequalities. Conversely, put $y=\max(jh,-n)$. Then $jh\le y\le n$ and $y\le(j+1)h$ (using $h\ge0$, $n\ge0$ and the hypotheses), so $|y|\le n$ and the point $(c+\sqrt{n^2-y^2},\,y)$ lies in $S_j\cap C_{c,n}$. +(2) If $k\le0$ then $kh\le0\le n$. If $k>0$, both sides of $k\sqrt3\le2n$ are nonnegative, so it is equivalent to $3k^2\le4n^2$. +(3) The condition $-n\le(j+1)h$ reads $(-(j+1))h\le n$; apply (1) and (2) with $k=j$ and $k=-(j+1)$. +(4) If $j>2n+2$, then $j>0$ and $3j^2>4n^2$, so the first clause of $\MI(n,j)$ fails; if $j<-(2n+2)$, then $j+1<0$ and $3(j+1)^2>4n^2$, so the second fails. +By (3) and (4), $i\mapsto i-(2n+2)$ is a bijection from the set counted by \decl{a} onto $\{j:S_j\cap C_{c,n}\ne\emptyset\}$. +\end{proof} + +In the statement file, items (1)--(4) are \decl{rowMeets_iff_real}, \decl{mul_half_sqrt_three_le_iff}, \decl{rowMeets_iff} and \decl{bounds_of_meetsInt}, and the final assertion is \decl{a_eq_ncard}; their Lean proofs follow the argument above. + +\begin{remark}[encoding choices]\label{rem:enc} +(i) Rows are closed strips. Open strips give the same count for $n\ge1$: the two conditions differ only if $jh=n$ or $(j+1)h=-n$, which would make $\sqrt3$ rational. +(ii) The definition gives $a(0)=2$ (the degenerate circle $\{(c,0)\}$ meets rows $-1$ and $0$), which is not a term of the sequence (offset~$1$). The series in \decl{statement} has coefficient $0$ at $x^0$, so it is $F(x)$; this matches the conjectured generating function, which vanishes at $x=0$. +(iii) The identity is stated in $\fps$ with the unit denominator cleared; there is no truncated subtraction or division. +(iv) The separate definition \decl{statement_asymptotic} records $a(n)\sim\frac{30}{13}n$; it is not part of \decl{statement} and is not addressed by the Lean proof. +\end{remark} + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A242396.lean}: the identity is reduced to one linear relation between four values of $a$ (Lemma~\ref{lem:coef}), and these values are computed (Lemma~\ref{lem:vals}). + +\begin{lemma}\label{lem:coef} +Let $b\colon\N\to\Z$ and $B(x)=\sum_{n\ge0}b(n)x^n\in\fps$. For every $n\ge14$, +$\coef{n}\bigl(B(x)\,D(x)\bigr)=b(n)-b(n-1)-b(n-13)+b(n-14)$. +\end{lemma} + +\begin{proof} +$B\,D=x^{14}B-x^{13}B-xB+B$, and $\coef{n}\bigl(x^kB(x)\bigr)=b(n-k)$ for $k\le n$. +\end{proof} + +\begin{lemma}[closed form; not used in Lean]\label{lem:closed} +Let $m(n)=\max\{k\in\N:3k^2\le4n^2\}=\lfloor 2n/\sqrt3\rfloor$. Then $a(n)=2m(n)+2$ for all $n\in\N$. +\end{lemma} + +\begin{proof} +For $k\in\N$, $3k^2\le4n^2$ if and only if $k\le 2n/\sqrt3$, if and only if $k\le m(n)$. By Lemma~\ref{lem:geom}, $a(n)=\#\{j\in\Z:\MI(n,j)\}$. If $j\ge1$, the second clause of $\MI(n,j)$ holds and the first holds if and only if $j\le m(n)$: $m(n)$ values. If $j\in\{-1,0\}$, both clauses hold: $2$ values. If $j\le-2$, the first clause holds and the second holds if and only if $-(j+1)\le m(n)$, i.e.\ $j\in\{-m(n)-1,\dots,-2\}$: $m(n)$ values. +\end{proof} + +\begin{lemma}[\decl{vals}]\label{lem:vals} +$a(83)=192$, $a(84)=194$, $a(96)=222$ and $a(97)=226$. +\end{lemma} + +\begin{proof} +By Lemma~\ref{lem:closed} it suffices to determine $m(n)$, and $m(n)=k$ is certified by $3k^2\le4n^2<3(k+1)^2$: +\[ +\begin{array}{c|c|c|c|c} + n & 3k^2 & 4n^2 & 3(k+1)^2 & m(n)=k,\ a(n)=2k+2\\\hline + 83 & 27075 & 27556 & 27648 & 95,\ 192\\ + 84 & 27648 & 28224 & 28227 & 96,\ 194\\ + 96 & 36300 & 36864 & 36963 & 110,\ 222\\ + 97 & 37632 & 37636 & 38307 & 112,\ 226 +\end{array}\qedhere +\] +\end{proof} + +In Lean, Lemma~\ref{lem:vals} is the private declaration \decl{vals}, proved by \texttt{decide +kernel} without Lemma~\ref{lem:closed}. The kernel evaluates the decision procedure for the conjunction of the four equalities by unfolding \decl{a}: for each of the four values of $n$ it runs through the $4n+5\le393$ indices $i$, decides $\MI(n,i-(2n+2))$ by exact integer arithmetic, and counts the successes. The kernel has built-in arbitrary-precision arithmetic on natural-number literals; unlike \texttt{native\_decide}, this adds no axiom and does not trust compiled code. The table above is an independent, human-checkable certificate for the same values. + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +Apply Lemma~\ref{lem:coef} with $n=97$ to $b(0)=0$ and $b(k)=a(k)$ for $k\ge1$, so that $B=F$. By Lemma~\ref{lem:vals}, +\[ + \coef{97}\bigl(F(x)D(x)\bigr)=a(97)-a(96)-a(84)+a(83)=226-222-194+192=2 . +\] +Every monomial of $N(x)$ has degree at most $14$, so $\coef{97}N(x)=0$, and $F(x)D(x)\ne N(x)$. +\end{proof} + +The Lean proof of \decl{result} follows these lines. It assumes \decl{statement}, rewrites the numerals $2$ and $4$ of $\fps$ as the constant series $C\,2$ and $C\,4$, and applies \texttt{coeff 97} to both sides. Simplification with distributivity, linearity of \texttt{coeff}, and Mathlib's lemmas \decl{coeff_C_mul}, \decl{coeff_X_pow}, \decl{coeff_X} and \decl{coeff_X_pow_mul'} (the identity $\coef{n}(x^kB)=b(n-k)$ for $k\le n$ used in Lemma~\ref{lem:coef}) reduces the hypothesis to a linear equation in $\Z$ between $a(97)$, $a(96)$, $a(84)$ and $a(83)$ expressing that the coefficient vanishes. Substituting the values from \decl{vals} yields a false numerical equation, which \texttt{norm\_num} refutes. + +\begin{remark}[why and where the conjecture fails; not formalized]\label{rem:mech} +Let $P_n=\sum_{k\le n}\coef{k}N(x)$, so $P_n=N(1)=30$ for $n\ge14$. Since $F\,D=N$ is equivalent to $F(x)(1-x^{13})=N(x)/(1-x)=\sum_nP_nx^n$, Conjecture~\ref{conj} says $a(n)-a(n-13)=P_n$ for all $n\ge1$ (with $a(k)=0$ for $k\le0$). For $n\le13$ this is $a(n)=P_n$, true by the data ($P_1,\dots,P_{13}=4,6,\dots,28,32$); so the conjecture is equivalent to $a(n+13)-a(n)=30$ for all $n\ge1$. Now $15<26/\sqrt3<16$ (as $675<676<768$); write $26/\sqrt3=15+\delta$, $\delta=0.0111\ldots$. With $t=2n/\sqrt3$, Lemma~\ref{lem:closed} gives $a(n+13)-a(n)=2(\lfloor t+15+\delta\rfloor-\lfloor t\rfloor)$, which is $30$ if $\{t\}<1-\delta$ and $32$ otherwise. Hence the conjecture holds if and only if $\{2n/\sqrt3\}<16-26/\sqrt3=0.98889\ldots$ for all $n\ge1$. For $n=84$, $\lfloor168/\sqrt3\rfloor=96$, and $\{168/\sqrt3\}\ge16-26/\sqrt3$ is equivalent to $194/\sqrt3\ge112$, i.e.\ to $194^2=37636\ge37632=3\cdot112^2$, the certificate for $a(97)$ above. So $a(97)-a(84)=32$, while $a(96)-a(83)=30$. A direct computation shows that $n=84$ is the smallest $n\ge1$ with $\{2n/\sqrt3\}\ge1-\delta$ (the next are $168$ and $265$), so the coefficients of $N/D$ agree with $a(n)$ exactly for $n\le96$, and at $n=97$ they give $224$ instead of $226$. + +Failures recur infinitely often: if $a(n+13)-a(n)=30$ for all large $n$, then $a(n)/n\to30/13$, whereas Lemma~\ref{lem:closed} gives $a(n)/n\to4/\sqrt3=2.3094\ldots\ne30/13=2.3077\ldots$. The same limit shows that the derived claim $a(n)\sim\frac{30}{13}n$ is false. +\end{remark} + +\begin{remark}[the entry's program]\label{rem:program} +The Small Basic program in A242396 sets $r=n\sin(30^\circ)/(\sqrt3/2)=n/\sqrt3$ and prints $4\operatorname{round}(r)$ if $r-\lfloor r\rfloor>\frac12$ and $2(2\operatorname{round}(r)+1)$ otherwise. In both cases this is $2\lfloor2r\rfloor+2=2\lfloor2n/\sqrt3\rfloor+2$ ($\{r\}=\frac12$ is impossible). The program runs for $n=1,\dots,100$, so it prints $a(97)=226$, while the published data stop at $n=61$. The math0 referees confirmed the agreement numerically for $n\le5000$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A242396.lean} of the math0 repository (\url{https://github.com/Foundation-0/math0}). It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A242396.lean} and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A242396.result}, of type $\neg$\,\decl{Math0.Statements.A242396.statement}. Verbatim (the copyright header, imports, docstrings, blank lines, and the \texttt{namespace}, \texttt{open} and \texttt{end} lines omitted): +\begin{lstlisting} +private lemma vals : a 97 = 226 ∧ a 96 = 222 ∧ a 84 = 194 ∧ a 83 = 192 := by + decide +kernel +theorem result : ¬ statement := by + intro h + have e2 : (2 : ℤ⟦X⟧) = C 2 := (map_ofNat C 2).symm + have e4 : (4 : ℤ⟦X⟧) = C 4 := (map_ofNat C 4).symm + rw [statement, e2, e4] at h + have h97 := congrArg (coeff 97) h + simp only [mul_sub, mul_add, mul_one, neg_mul, map_add, map_sub, map_neg, coeff_C_mul, + coeff_X_pow, coeff_X] at h97 + simp [mul_comm _ (X ^ _), coeff_X_pow_mul'] at h97 + obtain ⟨h1, h2, h3, h4⟩ := vals + rw [h1, h2, h3, h4] at h97 + norm_num at h97 +#math0_settles Math0.Frontier.A242396.result Math0.Statements.A242396.statement +\end{lstlisting} +Neither file contains \texttt{sorry}, \texttt{native\_decide}, \texttt{axiom} or \texttt{set\_option}; the only auxiliary declaration of the proof file, \decl{vals}, is private. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless: (1) \decl{statement} is a universe-monomorphic definition of type \texttt{Prop}; (2) \decl{statement} and \decl{result} depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which excludes \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} introduced by \texttt{native\_decide}, and any custom axiom; (3) the type of \decl{result} is syntactically \decl{statement} or $\neg$\,\decl{statement}, up to metadata annotations, with no unfolding or definitional equality. Compiling the proof file prints +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A242396.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A242396.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A242396.result' refutes 'Math0.Statements.A242396.statement' +\end{lstlisting} +The SHA-256 hash of the statement file equals the hash recorded when it was frozen, \texttt{35a266981a9f235aba6be189940a3573e9447b74f2e966fc2da862bd24685b7d}. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of statement checks that passed. To check this file alone, run \texttt{lake env lean Math0/Frontier/OEIS/A242396.lean} in the directory \path{lean}. + +{\small +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Fr24} +S.~Fried, \emph{Proofs of some conjectures from the OEIS}, arXiv:2410.07237, 2024. + +\bibitem{Fr25} +S.~Fried, \emph{Proofs of several conjectures from the OEIS}, J. Integer Seq.\ \textbf{28} (2025), Article~25.4.3. + +\bibitem{Fr26a} +S.~Fried, \emph{Proofs of ten conjectures from the OEIS}, J. Integer Seq.\ \textbf{29} (2026), Article~26.1.8. + +\bibitem{Fr26b} +S.~Fried, \emph{Further proofs of conjectures from the OEIS}, arXiv:2607.24832, 2026. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381; arXiv:1910.09336. + +\bibitem{A242394} +The OEIS Foundation Inc., \url{https://oeis.org/A242394}, entry by K.~Ngaokrajang (May~13, 2014). + +\bibitem{A242395} +The OEIS Foundation Inc., \url{https://oeis.org/A242395}, entry by K.~Ngaokrajang (May~13, 2014). + +\bibitem{A242396} +The OEIS Foundation Inc., \url{https://oeis.org/A242396}, entry by K.~Ngaokrajang (May~13, 2014); conjectured generating function by R.~Stephan (May~18, 2014); revision \#18, May~31, 2014. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a249434/README.md b/results/oeis-a249434/README.md new file mode 100644 index 0000000..48197b7 --- /dev/null +++ b/results/oeis-a249434/README.md @@ -0,0 +1,45 @@ +# A249151(k) = k exactly when k + 1 is prime (Karttunen's conjecture, A249434/A249151) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A249434 +**Date:** 2026-10-25 + +## Result + +Let P(k) = prod_{j=0..k} C(k,j) be the product of row k of Pascal's triangle. For every k >= 0, k is the largest m with m! | P(k) if and only if k+1 is prime. Equivalently, A249151(k) = k iff k+1 is prime, so A006093 = {k : A249151(k) = k}. + +## Assessment + +The prime case takes one line: v_p(C(p,j)) = 1 for 0= s(u) whenever f(u) >= 1, then shows the excess is either negative or greater than e. All of this is about a page of elementary p-adic valuation bookkeeping (Legendre/Kummer-type sums) that someone fluent in such calculations would find quickly, so it is routine. The fact that the conjecture stayed open in the OEIS reflects lack of attention, not hidden difficulty. + +*Follows from:* A001142's product formula P(k) = prod_{j=1..k} j^(2j-1-k), giving P(k)/k! = prod_{jn$. +For example $M(4)=4$, because $P(4)=96=4\cdot 4!$ and $5!\nmid 96$, while $M(3)=1$ because $P(3)=9$. +The data suggest that $M(k)=k$ happens exactly when $k+1$ is prime, and Karttunen recorded this as a conjecture in A249434, A249151 and A249431 \cite{A249431}. We prove it. + +\begin{theorem}\label{thm:main} +For every integer $k\ge0$, $M(k)=k$ if and only if $k+1$ is prime. Equivalently, $k!\mid P(k)$ and $(k+1)!\nmid P(k)$ if and only if $k+1$ is prime. +\end{theorem} + +\subsection*{Method} +Fix a prime $q$ and put $n=k+1$. The identity $P(n)\,n!=P(n-1)\,n^{n}$ gives $v_q(P(k))-v_q(k!)=D_q(n):=v_q(P(n))-(n-1)v_q(n)$ (Lemma~\ref{lem:D}), so $k!\mid P(k)$ means $D_q(n)\ge0$ for all $q$, and $(k+1)!\mid P(k)$ means $D_q(n)\ge v_q(n)$ for all $q$. +A $q$-adic recursion for $v_q(P(n))$ (Lemma~\ref{lem:grec}) yields a closed form for $D_q(q^eu)$ and an inequality between $v_q(P(u))$ and the base-$q$ digit sum of $u$ (Lemma~\ref{lem:key}). Together they show that if $q\mid n$ and $n\ne q$, then $D_q(n)<0$ or $D_q(n)>v_q(n)$ (Proposition~\ref{prop:dich}), while $D_q(q)=0<1=v_q(q)$. + +\subsection*{Status and prior work} +The OEIS entries A249434 (revision \#20, September 10, 2025), A249151 (\#38, August 24, 2025) and A249431 (\#16, August 24, 2025) still state the claim with ``It seems''; A249434 lists A006093 among its subsequences as ``(conjectured)'', and none of the entries records a proof. +The vanishing criterion of Lagarias and Mehta \cite[Theorem~6.7]{LM} describes the case $v_q(P(u))=0$ that occurs in our dichotomy (Remark~\ref{rem:A249429}), but \cite{LM} does not discuss the divisibility of $G_n$ by factorials, the sequence A249151, or the primality of $n+1$, and the papers \cite{DL,DLY} do not address the conjecture either. +The conjecture is not among the OEIS statements of the formal-conjectures repository \cite{FC} (checked at the commit pinned by math0, Section~\ref{sec:lean}), nor among the $492$ OEIS conjectures formalized in Lean by Tsoukalas et al.\ \cite{APN} that make up the OEIS Open benchmark \cite{Ad}. The math0 referees' searches of MathOverflow, Mathematics Stack Exchange and the SeqFan mailing list found no proof or counterexample. +We therefore classify the result as \emph{new}. The argument is elementary; besides the recurrence of Lemma~\ref{lem:rec}, it uses only Legendre's formula for $v_q(m!)$. + +\section{Statement}\label{sec:statement} + +The COMMENTS section of A249434 \cite{A249434} (entry by Antti Karttunen, November~2, 2014) contains, verbatim: +\begin{quote} +{\small\texttt{It seems that A006093 gives all those k for which A249151(k) = k. If that is true, then this is a disjoint union of A006093 and A249429.}} +\end{quote} +Here A006093 \cite{A006093} is $a(n)=\mathrm{prime}(n)-1$ ($n\ge1$), so $k\ge0$ belongs to A006093 if and only if $k+1$ is prime. +A249151 (by Karttunen, October~25, 2014) has the comment ``\texttt{A006093 seems to give all such k, that a(k) = k.}'', A249431 ($a(n)=\text{A249151}(n)-n$) has ``\texttt{It seems that A006093 gives the positions of zeros.}'', and the cross-references of A249434 contain the line ``\texttt{Subsequences: A006093 (conjectured), A249429, A249430, A249432.}'' +We read the conjecture as the set equality $\{k\ge0: M(k)=k\}=\text{A006093}$, which is Theorem~\ref{thm:main}; the second sentence of the comment and the cross-reference both presuppose the inclusion $\text{A006093}\subseteq\{k: M(k)=k\}$ as well. That second sentence then follows at once: A249434 $=\{k: M(k)\ge k\}$ is the disjoint union of $\{k: M(k)=k\}=\text{A006093}$ and $\{k:M(k)>k\}=\text{A249429}$. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A249434.lean}. The file was reviewed for fidelity before the proof attempt; that review recorded its SHA-256 hash \texttt{638b565a\ldots cb4a}, the file has not changed since, and the hash is listed in \path{lean/Math0/Statements/FROZEN.sha256}. Its main definitions and theorem statements read as follows (verbatim, in file order; the import, docstrings, blank lines, all proofs, the kernel-friendly helpers \decl{rowProdFact} and \decl{A249151'}, the \texttt{DecidablePred} instance and the auxiliary lemmas are omitted, and the two data lists are abbreviated): +\begin{lstlisting} +namespace Math0.Statements.A249434 +open Finset Nat +def rowProd (n : ℕ) : ℕ := ∏ j ∈ range (n + 1), n.choose j +theorem rowProd_succ_mul (n : ℕ) : rowProd (n + 1) * (n + 1)! = rowProd n * (n + 1) ^ (n + 1) +def IsTerm (m : ℕ) : Prop := m ! ∣ rowProd m +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) +theorem a_data : (List.range 81).map (fun i => a (i + 1)) = [0, 1, 2, 4, 6, 10, ..., 250, 256] +def lastFact (P : ℕ) : ℕ → ℕ → ℕ + | 0, m => m + | f + 1, m => if (m + 1)! ∣ P then lastFact P f (m + 1) else m +def A249151 (n : ℕ) : ℕ := lastFact (rowProd n) (rowProd n) 0 +theorem A249151_isGreatest (n : ℕ) : IsGreatest {m : ℕ | m ! ∣ rowProd n} (A249151 n) +theorem A249151_data : (List.range 81).map A249151 = [1, 1, 2, 1, 4, 2, 6, ..., 78, 80, 2] +def statement : Prop := + ∀ k : ℕ, IsGreatest {m : ℕ | m ! ∣ rowProd k} k ↔ (k + 1).Prime +theorem statement_iff : statement ↔ ∀ k : ℕ, A249151 k = k ↔ (k + 1).Prime +end Math0.Statements.A249434 +\end{lstlisting} +\texttt{rowProd n} is $P(n)$, and \texttt{IsGreatest S k} means that $k\in S$ and $k$ is an upper bound of $S$. Thus \decl{statement} is Theorem~\ref{thm:main}, for every $k\in\N$; it does not refer to the search function \decl{A249151}, which implements the OEIS definition by an upward search from $m=0$. \decl{A249151_isGreatest} proves that this search returns the largest $m$ with $m!\mid P(n)$, and \decl{statement_iff} restates \decl{statement} as $\forall k,\ \text{A249151}(k)=k\leftrightarrow k+1\text{ prime}$. +The data lemmas compare the definitions with the OEIS by evaluation in the kernel (\texttt{decide +kernel}, no \texttt{native\_decide}): \decl{a_data} checks that the $m<257$ with $m!\mid P(m)$ are exactly the $81$ listed terms of A249434 (the sequence \decl{a} has offset $1$), and \decl{A249151_data} checks the $81$ listed terms $M(0),\dots,M(80)$ of A249151. For speed, the kernel computes $(P(n),n!)$ by the recurrence $P(n+1)(n+1)!=P(n)(n+1)^{n+1}$ (\decl{rowProd_succ_mul}, proved in the file). +The variable $k$ ranges over all of $\N$, as A249151 has offset $0$; for $k=0$ both sides are false, since $M(0)=1$ and $1$ is not prime. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A249434.lean}; each step names the corresponding Lean declaration. +Throughout, $q$ is a prime and $v=v_q$ is the $q$-adic valuation of positive integers. For $n\ge0$ put +\[ + g(n)=v_q(P(n)),\qquad L(n)=v_q(n!),\qquad S(n)=n-(q-1)L(n) +\] +(\texttt{g q n} and \texttt{L q n} in Lean; $S$ appears only as the expression $n-(q-1)L(n)$). By Legendre's formula $S(n)$ is the sum of the base-$q$ digits of $n$, but we use only Lemma~\ref{lem:S}. All identities below are identities between integers; in Lean they are stated in $\Z$ after casting from $\N$. + +\begin{lemma}[\decl{isGreatest_iff}, \decl{dvd_rowProd_iff}]\label{lem:red} +\textup{(a)} For integers $N\ge1$ and $k\ge0$, $k$ is the largest $m$ with $m!\mid N$ if and only if $k!\mid N$ and $(k+1)!\nmid N$. +\textup{(b)} For integers $d,N\ge1$, $d\mid N$ if and only if $v_q(d)\le v_q(N)$ for every prime $q$. +\end{lemma} + +\begin{proof} +(a) If $k$ is the largest such $m$, then $k!\mid N$ and, as $k+1>k$, $(k+1)!\nmid N$. Conversely, if $k!\mid N$ and $m!\mid N$ for some $m>k$, then $(k+1)!\mid m!\mid N$. (b) is unique factorization (Mathlib's \decl{Nat.factorization_prime_le_iff_dvd}). +\end{proof} + +\begin{lemma}[\decl{rowProd_succ_mul}, \decl{rec_val}]\label{lem:rec} +For $n\ge0$, $P(n+1)\,(n+1)!=P(n)\,(n+1)^{n+1}$. Consequently, for every prime $q$, +\begin{equation}\label{eq:rec} + g(n+1)+L(n+1)=g(n)+(n+1)\,v(n+1). +\end{equation} +\end{lemma} + +\begin{proof} +For $0\le j\le n$ we have $\binom nj(n+1)=\binom{n+1}{j}(n+1-j)$. Multiplying over $j=0,\dots,n$ and using $\prod_{j=0}^{n}(n+1-j)=(n+1)!$ and $\binom{n+1}{n+1}=1$ gives $P(n)(n+1)^{n+1}=P(n+1)(n+1)!$. Both sides are positive; take $v_q$. +\end{proof} + +\begin{lemma}[\decl{key_rel}, \decl{val_fact_iff}, \decl{val_fact_succ_iff}]\label{lem:D} +Let $k\ge0$, $n=k+1$ and $D_q(n)=g(n)-(n-1)\,v(n)$. Then $g(k)-L(k)=D_q(n)$. Consequently +\begin{align} + k!\mid P(k)&\iff D_q(n)\ge0\ \text{for every prime } q,\label{eq:div1}\\ + (k+1)!\mid P(k)&\iff D_q(n)\ge v_q(n)\ \text{for every prime } q.\label{eq:div2} +\end{align} +\end{lemma} + +\begin{proof} +Since $n!=n\cdot k!$, $L(n)=L(k)+v(n)$; subtracting this from \eqref{eq:rec} at $k$ gives $g(k)-L(k)=g(n)-k\,v(n)$. Now $v_q(k!)\le v_q(P(k))$ means $D_q(n)\ge0$, and $v_q((k+1)!)=v(n)+L(k)\le g(k)$ means $D_q(n)\ge v(n)$. Apply Lemma~\ref{lem:red}(b) with $N=P(k)\ge1$. +\end{proof} + +\begin{remark}\label{rem:pow} +As $P(k)/k!=P(n)/n^{n-1}$ by Lemma~\ref{lem:rec}, Theorem~\ref{thm:main} is equivalent to: for $n\ge1$, $n^{n-1}\mid P(n)$ and $n^n\nmid P(n)$ if and only if $n$ is prime. (This form is not stated in Lean.) +\end{remark} + +\begin{lemma}[\decl{L_mul_add}, \decl{L_mul}, \decl{v_mul}, \decl{v_eq_zero}]\label{lem:L} +For $m\ge0$ and $0\le re=v(n)$. +\end{proposition} + +\begin{proof} +Write $n=q^eu$ with $q\nmid u$ (Mathlib's \decl{Nat.exists_eq_pow_mul_and_not_dvd}); then $u\ge1$, $v(n)=e$, and $e\ge1$ since $q\mid n$. Put $S=S(u)\ge1$ (Lemma~\ref{lem:S}). By Lemma~\ref{lem:pow}, +\begin{equation}\label{eq:closed} + (q-1)D=(q-1)g(q^eu)-(q-1)(q^eu-1)e=q^e\bigl((q-1)g(u)-S\bigr)+S+(q-1)e. +\end{equation} +\emph{Case $g(u)=0$.} Then $(q-1)D=(q-1)e-(q^e-1)S$. If $e=1$, then $u\ne1$ because $n\ne q$, so $u\ge2$ and $S\ge2$ by Lemma~\ref{lem:S}(b), and $(q-1)D=(q-1)(1-S)<0$. If $e\ge2$, then $(q^e-1)S\ge q^e-1=(q-1)(1+q+\dots+q^{e-1})>(q-1)e$ (\decl{pow_gt}, proved in Lean by induction on $e$), so again $(q-1)D<0$. Hence $D<0$. + +\emph{Case $g(u)\ge1$.} By Lemma~\ref{lem:key}, $(q-1)g(u)-S\ge0$, so \eqref{eq:closed} gives $(q-1)D\ge S+(q-1)e\ge1+(q-1)e$, that is, $(q-1)(D-e)\ge1$. Hence $D>e$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main} (\decl{result})] +By Lemma~\ref{lem:red}(a) we must show: $k!\mid P(k)$ and $(k+1)!\nmid P(k)$ if and only if $n=k+1$ is prime. We use Lemma~\ref{lem:D}. + +\emph{$n$ prime.} Let $q$ be a prime. If $q\nmid n$, then $v_q(n)=0$ and $D_q(n)=g(n)\ge0$. If $q\mid n$, then $q=n$, and $D_n(n)=g(n)-(n-1)\cdot1=0$ by Lemma~\ref{lem:grec}. Hence $k!\mid P(k)$ by \eqref{eq:div1}. Since $D_n(n)=0<1=v_n(n)$, \eqref{eq:div2} fails at $q=n$, so $(k+1)!\nmid P(k)$. + +\emph{$n$ not prime} (this includes $n=1$). Assume $k!\mid P(k)$, so $D_q(n)\ge0$ for all $q$ by \eqref{eq:div1}. Let $q$ be a prime. If $q\nmid n$, then $D_q(n)\ge0=v_q(n)$. If $q\mid n$, then $n\ne q$, so by Proposition~\ref{prop:dich}, as $D_q(n)<0$ is excluded, $D_q(n)\ge v_q(n)$. By \eqref{eq:div2}, $(k+1)!\mid P(k)$. +\end{proof} + +\begin{remark}[a description of A249429; not formalized]\label{rem:A249429} +Let $n=k+1$ be $1$ or composite, and for each prime $q\mid n$ let $u_q$ be the part of $n$ prime to $q$. The proof shows: if $v_q(P(u_q))\ge1$ for every prime $q\mid n$, then $(k+1)!\mid P(k)$ and $M(k)>k$; otherwise $D_q(n)<0$ for some $q$, and $M(k)= 1, b(n) and c(n) are integers with gcd(b(n), c(n)) = 1, and a(n) = b(n). + +## Assessment + +The n-th iterate is a finite continued fraction with integer partial denominators and numerators ±1. Its value is therefore (P_n ± P_{n-1})/(Q_n ± Q_{n-1}) for the standard convergents, and that numerator and denominator are coprime by the textbook determinant identity. The only remaining step is to check that these sums satisfy Israel's recurrence. That is a polynomial identity in two cases by parity, which a computer-algebra system or ring normalisation settles mechanically. Spotting that Israel's b, c are just the convergent numerators and denominators is the one small insight, and it is the obvious guess, so the whole argument is well under a page of standard continued-fraction theory. + +*Follows from:* The classical fundamental recurrence and determinant identity for continued-fraction convergents, P_k Q_{k-1} - P_{k-1} Q_k = ±1 (e.g. Lorentzen-Waadeland), applied to the finite continued fraction 1 - 1/(2 + 1/(3 - ...)) whose last partial denominator is (n+1) ± 1. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A262957](https://oeis.org/A262957) as [`Math0.Statements.A262957.statement`](../../lean/Math0/Statements/OEIS/A262957.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A262957.lean`](../../lean/Math0/Frontier/OEIS/A262957.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: b(n) and c(n) are coprime for all n, so that a(n) = b(n). I have verified this for n <= 10000. - _Robert Israel_, Dec 22 2015 [b(1)=2, b(2)=3, c(1)=3, c(2)=5, b(n+1) = (((-1)^n*(n-1)+n*(n+2))*b(n) - (1+(-1)^n*(n+1))*b(n-1))/(n-(-1)^n), same recurrence for c] + +Referees: OEIS A262957 (local mirror, rev #80, Mar 2025): Robert Israel's comment of Dec 22 2015 states the conjecture, verified for n <= 10000, and it is still listed as open. Peter Bala, "A note on A262957 and A263295" (Dec 24 2015, linked from the OEIS entry): proves the simple continued fraction expansion [0;1,1,2,1,3,4,1,5,6,...] of the limit, but not Israel's recurrence or the coprimality. The cross-referenced entries A263295, A346590, A244279 and A244280 contain no proof. A262957 is absent from Tom Adamczewski, "OEIS Open: How many conjectures can language models turn into theorems?", arXiv:2608.11941 (2026), and from the epoch-research/LeanOpenProblems and LeanOpenProblems-results repositories. Web searches of arXiv, MathOverflow, Math StackExchange and SeqFan found no prior resolution. The proof uses the classical determinant identity for continued-fraction convergents (p_{k+1}q_k - p_k q_{k+1} = ±1). + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a262957, + author = {{math0}}, + title = {{A262957: Israel's b(n), c(n) are coprime integers and a(n) = b(n)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a262957}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a262957/paper.pdf b/results/oeis-a262957/paper.pdf new file mode 100644 index 0000000..8beefc4 Binary files /dev/null and b/results/oeis-a262957/paper.pdf differ diff --git a/results/oeis-a262957/paper.tex b/results/oeis-a262957/paper.tex new file mode 100644 index 0000000..4662629 --- /dev/null +++ b/results/oeis-a262957/paper.tex @@ -0,0 +1,398 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,at,push_cast,exact_mod_cast,set,linear_combination}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 + {∃}{{$\exists$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {∧}{{$\wedge$}}1 {×}{{$\times$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {₀}{{$_0$}}1 {₁}{{$_1$}}1 {₂}{{$_2$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} + +\title[Israel's conjecture for OEIS A262957]{Israel's sequences for the alternating continued fraction $1-1/(2+1/(3-1/(4+\cdots)))$ are coprime integers (OEIS A262957)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Let $\xi_n=1-1/(2+1/(3-\cdots(n+1)+(-1)^{n+1}/1))$ and let $a(n)$ be the numerator of $\xi_n$ in lowest terms (OEIS A262957). In 2015 Robert Israel gave a three-term recurrence with rational coefficients for two sequences $b(n),c(n)$ and conjectured that $b(n)$ and $c(n)$ are coprime for all $n$, so that $a(n)=b(n)$. We prove that for every $n\ge1$ the numbers $b(n)$ and $c(n)$ are coprime integers and $a(n)=b(n)$; along the way we show that $b(n),c(n)>0$ and $\xi_n=b(n)/c(n)$. The proof identifies $b(n)$ and $c(n)$ with $P_n\pm P_{n-1}$ and $Q_n\pm Q_{n-1}$, where $P_k/Q_k$ are the convergents, and uses the determinant identity $P_kQ_{k-1}-P_{k-1}Q_k=\pm1$. To our knowledge the result is new (the entry still lists it as a conjecture), although it is a routine consequence of classical continued-fraction theory once this identification is made. The theorem is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the listed terms; this statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +For an integer $k\ge1$ and a rational $t\ne0$ put $f_k(t)=k+(-1)^k/t$, and for $n\ge0$ let +\[ + \xi_n=f_1\bigl(f_2(\cdots f_{n+1}(1)\cdots)\bigr) + =1-\cfrac{1}{2+\cfrac{1}{3-\cfrac{1}{\ddots\;(n+1)+\cfrac{(-1)^{n+1}}{1}}}}\,. +\] +Thus $\xi_1=2/3$, $\xi_2=3/5$, $\xi_3=19/33$, $\xi_4=64/111$. +The OEIS entry A262957 \cite{A262957}, contributed by Mohamed Sabba in November 2015, lists the numerators $a(n)$ of $\xi_n$ in lowest terms, with offset~$1$; the denominators form A263295 \cite{A263295}, and the analogous fractions beginning with $1+\cdots$ form A244279 and A244280 \cite{A244279,A244280}. +The entry also records that $\xi_n$ converges to $0.57663338973\ldots$ (A346590 \cite{A346590}), a number with simple continued fraction $[0;1,1,2,1,3,4,1,5,6,1,7,8,\dots]$. This follows from Peter Bala's note \cite{Bala}, linked from the entry, which shows that for every integer sequence $(a_n)$ with $a_n>1$ for $n\ge2$ the infinite alternating continued fraction $a_1-1/(a_2+1/(a_3-\cdots))$ converges, and gives its simple continued fraction explicitly in terms of the $a_n$. + +On December~22, 2015, Robert Israel added to the entry a three-term recurrence with rational coefficients for sequences $b(n),c(n)$ such that $a(n)$ is the numerator of $b(n)/c(n)$, and conjectured that $b(n)$ and $c(n)$ are coprime for all $n$, ``so that $a(n)=b(n)$''; he verified this for $n\le10000$ (the comment is quoted in Section~\ref{sec:statement}). +We prove the conjecture, including the integrality of $b(n)$ and $c(n)$ (Theorem~\ref{thm:main}); along the way we prove the identity $\xi_n=b(n)/c(n)$, which underlies Israel's assertion, stated in the entry without proof, that $a(n)$ is the numerator of $b(n)/c(n)$. + +\subsection*{Method} +Let $P_k/Q_k$ be the convergents of $f_1(f_2(f_3(\cdots)))$, so that $P_k=(k+1)P_{k-1}+(-1)^kP_{k-2}$, and likewise for $Q_k$. +Since $\xi_n$ is this continued fraction cut after the partial denominator $n+1$ with tail $(-1)^{n+1}/1$, we have $\xi_n=x(n)/y(n)$ with $x(n)=P_n+(-1)^{n+1}P_{n-1}$ and $y(n)=Q_n+(-1)^{n+1}Q_{n-1}$ (Lemma~\ref{lem:fold}). +A computation split by the parity of $n$ shows that $x$ and $y$ satisfy Israel's recurrence (Lemma~\ref{lem:israel}); the initial values are $2,3$ and $3,5$, so $b=x$ and $c=y$. +Finally $x(n)Q_{n-1}-P_{n-1}y(n)=P_nQ_{n-1}-P_{n-1}Q_n=\pm1$, so $x(n)$ and $y(n)$ are coprime, and they are positive. + +\subsection*{Status and prior work} +The statement is still marked ``Conjecture'' in A262957 (revision \#80, March~4, 2025). +Bala's note \cite{Bala} concerns only the limit of $\xi_n$; it does not mention Israel's recurrence or the coprimality of $b(n)$ and $c(n)$, and the cross-referenced entries \cite{A263295,A346590,A244279,A244280} contain no proof. +A262957 is not among the conjectures of the OEIS Open benchmark \cite{Ad}, nor in the GitHub repositories \texttt{epoch-research/LeanOpenProblems} and \texttt{LeanOpenProblems-results}, nor in formal-conjectures \cite{FC}; searches of arXiv, MathOverflow, Mathematics Stack Exchange and the SeqFan mailing list by the math0 referees found no proof or counterexample. +We therefore classify the result as \emph{new}, with the caveat that the argument is a routine application of the classical theory of convergents (see e.g.\ \cite{LW}); the one step that needs an idea is to recognize Israel's recurrence as the recurrence satisfied by $P_n\pm P_{n-1}$. +The conjecture does not follow from the recurrence directly: the recurrence divides by $n\mp1$, so integrality is not evident, and the cross-determinants $b(n+1)c(n)-b(n)c(n+1)$ have absolute value $n$ or $n+2$, which, granting integrality, only shows that $\gcd(b(n),c(n))$ divides $3$ (Remark~\ref{rem:D}). + +\section{Statement}\label{sec:statement} + +\begin{definition}\label{def:main} +For $n\ge0$ let $\xi_n\in\Q$ be as above, and for $n\ge1$ let $a(n)$ be the numerator of $\xi_n$ in lowest terms. +(For $k\ge2$ and $t\ge1$ we have $f_k(t)\ge k-1\ge1$, so every inner value in $\xi_n$ is at least $1$ and no division by zero occurs; for $n\ge1$, $\xi_n=1-1/t$ with $t=f_2(\cdots)>2$, so $\xi_n>0$.) +Define $b,c\colon\{1,2,\dots\}\to\Q$ by $b(1)=2$, $b(2)=3$, $c(1)=3$, $c(2)=5$ and, for $n\ge2$ and $w\in\{b,c\}$, +\begin{equation}\label{eq:israel} + w(n+1)=\frac{\bigl((-1)^n(n-1)+n(n+2)\bigr)\,w(n)-\bigl(1+(-1)^n(n+1)\bigr)\,w(n-1)}{n-(-1)^n}. +\end{equation} +The divisor $n-(-1)^n\in\{n-1,n+1\}$ is nonzero for $n\ge2$. +\end{definition} + +The COMMENTS section of A262957 \cite{A262957} contains, verbatim: +\begin{lstlisting}[keywords={},frame=none,basicstyle=\ttfamily\footnotesize] +From _Robert Israel_, Dec 22 2015: (Start) +a(n) is the numerator of b(n)/c(n) where +b(1) = 2, b(2) = 3, c(1) = 3, c(2) = 5, +b(n+1) = (((-1)^n*(n-1)+n*(n+2))*b(n) - (1+(-1)^n*(n+1))*b(n-1))/(n-(-1)^n), +c(n+1) = (((-1)^n*(n-1)+n*(n+2))*c(n) - (1+(-1)^n*(n+1))*c(n-1))/(n-(-1)^n). +Conjecture: b(n) and c(n) are coprime for all n, so that a(n) = b(n). +I have verified this for n <= 10000. (End) +\end{lstlisting} + +\begin{theorem}\label{thm:main} +For every $n\ge1$, the numbers $b(n)$ and $c(n)$ are integers, $\gcd(b(n),c(n))=1$, and $a(n)=b(n)$. +\end{theorem} + +Theorem~\ref{thm:main} is exactly the Lean statement below. The proof shows moreover that $b(n)>0$, $c(n)>0$ and $\xi_n=b(n)/c(n)$ for $n\ge1$ (Corollaries~\ref{cor:cf} and~\ref{cor:bc} and Lemma~\ref{lem:pos}); these facts are proved in the Lean file as auxiliary lemmas but are not part of the formal statement. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A262957.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{a21c48e2\dots0895207}) before any proof attempt. Its declarations are, verbatim with the docstrings omitted: +\begin{lstlisting} +import Mathlib +namespace Math0.Statements.A262957 +def cf (n : ℕ) : ℚ := + (List.range' 1 (n + 1)).foldr (fun (k : ℕ) (t : ℚ) => (k : ℚ) + (-1) ^ k / t) 1 +def a (n : ℕ) : ℕ := (cf n).num.natAbs +theorem a_data : (List.range 22).map (fun i => a (i + 1)) = + [2, 3, 19, 64, 538, 2833, 29169, 210308, 2572158, 23595915, 334778571, 3732092084, + 60305234822, 791741083537, 14359827157009, 217037153818264, 4366918714540522, + 74685204276602819, 1651116684587556019, 31524723785455714840, 759659139498065625218, + 16017463672140861567617] := by + decide +kernel +def step (m : ℕ) (u v : ℚ) : ℚ := + (((-1) ^ m * ((m : ℚ) - 1) + (m : ℚ) * ((m : ℚ) + 2)) * v + - (1 + (-1) ^ m * ((m : ℚ) + 1)) * u) / ((m : ℚ) - (-1) ^ m) +def israelPair (x₁ x₂ : ℚ) : ℕ → ℚ × ℚ + | 0 => (x₁, x₂) + | n + 1 => + let p := israelPair x₁ x₂ n + (p.2, step (n + 2) p.1 p.2) +def b (n : ℕ) : ℚ := (israelPair 2 3 (n - 1)).1 +def c (n : ℕ) : ℚ := (israelPair 3 5 (n - 1)).1 +theorem bc_data : (List.range 6).map (fun i => (b (i + 1), c (i + 1))) = + [(2, 3), (3, 5), (19, 33), (64, 111), (538, 933), (2833, 4913)] := by + decide +kernel +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + ∃ p q : ℤ, b n = (p : ℚ) ∧ c n = (q : ℚ) ∧ Int.gcd p q = 1 ∧ + ((a n : ℕ) : ℚ) = b n +end Math0.Statements.A262957 +\end{lstlisting} + +\emph{Encoding.} +\texttt{List.range' 1 (n + 1)} is $[1,2,\dots,n+1]$, so \texttt{cf n} is the right fold $f_1(f_2(\cdots f_{n+1}(1)\cdots))=\xi_n$, computed exactly in $\Q$; as every inner value is at least $1$, Lean's convention $x/0=0$ never intervenes. +\decl{Rat.num} is the numerator in lowest terms (with positive denominator), so \texttt{a n} $=|\mathrm{num}(\xi_n)|=a(n)$; the absolute value mirrors the entry's PARI program, which returns \texttt{denominator(1/t)}. +\texttt{step m u v} is the right-hand side of \eqref{eq:israel} with $n=m$, $w(n-1)=u$, $w(n)=v$, and by induction \texttt{israelPair} $x_1$ $x_2$ \texttt{k} is $(w(k+1),w(k+2))$ for the sequence with $w(1)=x_1$, $w(2)=x_2$ and \eqref{eq:israel}, the step from $k$ to $k+1$ using \eqref{eq:israel} at $n=k+2\ge2$. Hence \texttt{b n}, \texttt{c n} are $b(n)$, $c(n)$ for $n\ge1$ (the values at $n=0$ are unused). +The data lemmas are proved by evaluation in the kernel (\texttt{decide +kernel}, which, unlike \texttt{native\_decide}, does not trust compiled code): \decl{a_data} reproduces all $22$ terms $a(1),\dots,a(22)$ listed in A262957, and \decl{bc_data} gives $(b(n),c(n))$ for $n\le6$, matching the initial values, the examples $19/33$ and $64/111$, and the first terms of A263295. + +\emph{Reading of the conjecture.} +Since \eqref{eq:israel} divides, $b(n)$ and $c(n)$ are a priori rationals; ``coprime'' presupposes that they are integers, and \decl{statement} asserts this (the integers $p,q$) together with $\gcd(p,q)=1$. It keeps the stated consequence ``so that $a(n)=b(n)$'' as a conjunct, cast to $\Q$; this depends on Israel's unproved assertion that $a(n)$ is the numerator of $b(n)/c(n)$, which our proof establishes (Corollaries~\ref{cor:cf} and~\ref{cor:bc}). The range $n\ge1$ is the index range of $b$ and $c$. + +\section{Proof}\label{sec:proof} + +The proof follows \path{lean/Math0/Frontier/OEIS/A262957.lean}; each step names the corresponding Lean declaration. + +\begin{definition}[\decl{seq}, \decl{z}]\label{def:seq} +For $r_0,r_1\in\Z$ let $r\colon\N\to\Z$ be given by $r(0)=r_0$, $r(1)=r_1$ and +\begin{equation}\label{eq:rec} + r(k+2)=(k+2)\,r(k+1)+(-1)^{k+1}\,r(k)\qquad(k\ge0), +\end{equation} +and put $z_r(n)=r(n+1)+(-1)^{n+1}r(n)$. Let $p$ and $q$ be the sequences with $(r_0,r_1)=(1,1)$ and $(0,1)$, and put $x=z_p$, $y=z_q$. +\end{definition} + +Thus $p=1,1,1,4,15,79,459,\dots$, $q=0,1,2,7,26,137,796,\dots$, $x(1),x(2),\ldots=2,3,19,64,\dots$ and $y(1),y(2),\ldots=3,5,33,111,\dots$. In the notation of the introduction $p(k)=P_{k-1}$ and $q(k)=Q_{k-1}$, with the usual initial values $P_{-1}=P_0=1$, $Q_{-1}=0$, $Q_0=1$ \cite{LW}; we do not use this interpretation, since Lemma~\ref{lem:fold} proves what is needed. + +\begin{lemma}[\decl{fold_eq}]\label{lem:fold} +For every $k\ge0$ and every $t\in\Q$ with $t\ge1$, +\begin{equation}\label{eq:fold} + f_1\bigl(f_2(\cdots f_{k+1}(t)\cdots)\bigr) + =\frac{p(k+1)\,t+(-1)^{k+1}p(k)}{q(k+1)\,t+(-1)^{k+1}q(k)} . +\end{equation} +\end{lemma} + +As in Lean, $u/0$ is read as $0$; the only property of division used is $(N/t)/(D/t)=N/D$ for $t\neq0$, which also holds when $D=0$. The left-hand side involves no division by zero, since every argument of an $f_i$ is at least $1$. + +\begin{proof} +Induction on $k$, for all $t\ge1$ simultaneously. Write $F_k(t)$ for the left-hand side and $\varepsilon_k=(-1)^{k}$. +For $k=0$, $F_0(t)=1-1/t=(t-1)/t$, which is the right-hand side $(1\cdot t-1)/(1\cdot t-0)$. +Let $k\ge0$ and $t\ge1$. Since $[1,\dots,k+2]$ is $[1,\dots,k+1]$ followed by $k+2$ (in Lean, \decl{List.range'_concat} and \decl{List.foldr_append}), $F_{k+1}(t)=F_k(t')$ with $t'=f_{k+2}(t)=k+2+\varepsilon_{k+2}/t$. +As $0<1/t\le1$, $t'\ge k+1\ge1$, so the induction hypothesis gives $F_{k+1}(t)=N'/D'$ with $N'=p(k+1)t'+\varepsilon_{k+1}p(k)$ and $D'=q(k+1)t'+\varepsilon_{k+1}q(k)$. By \eqref{eq:rec}, +\[ + t\,N'=\bigl((k+2)p(k+1)+\varepsilon_{k+1}p(k)\bigr)t+\varepsilon_{k+2}\,p(k+1) + =p(k+2)\,t+\varepsilon_{k+2}\,p(k+1)=:N, +\] +and likewise $t\,D'=q(k+2)t+\varepsilon_{k+2}q(k+1)=:D$. Hence $F_{k+1}(t)=(N/t)/(D/t)=N/D$, which is \eqref{eq:fold} for $k+1$. +\end{proof} + +\begin{corollary}[\decl{cf_eq}]\label{cor:cf} +For every $n\ge0$, $\xi_n=x(n)/y(n)$. +\end{corollary} + +\begin{proof} +Take $k=n$ and $t=1$ in Lemma~\ref{lem:fold}. +\end{proof} + +\begin{lemma}[\decl{step_z}]\label{lem:israel} +Let $r$ satisfy \eqref{eq:rec} and $z=z_r$. For every $m\ge0$, $z$ satisfies \eqref{eq:israel} at $n=m+2$: +\[ + z(m+3)=\frac{\bigl((-1)^{m}(m+1)+(m+2)(m+4)\bigr)\,z(m+2)-\bigl(1+(-1)^{m}(m+3)\bigr)\,z(m+1)}{m+2-(-1)^{m}} . +\] +\end{lemma} + +\begin{proof} +Put $u=r(m+1)$, $v=r(m+2)$ and $s=(-1)^m$, so $s^2=1$. By \eqref{eq:rec}, $r(m+3)=(m+3)v+su$ and $r(m+4)=(m+4)\,r(m+3)-sv$, hence +\[ +\begin{gathered} + z(m+1)=v+su,\qquad + z(m+2)=(m+3-s)\,v+su,\\ + z(m+3)=\bigl((m+4+s)(m+3)-s\bigr)v+\bigl(1+(m+4)s\bigr)u. +\end{gathered} +\] +The divisor $m+2-s\in\{m+1,m+3\}$ is nonzero, so the claim is equivalent to +\[ + \bigl(s(m+1)+(m+2)(m+4)\bigr)\,z(m+2)-\bigl(1+s(m+3)\bigr)\,z(m+1)=(m+2-s)\,z(m+3). +\] +If $s=1$, both sides equal $(m+1)(m+5)\,u+(m^3+9m^2+22m+14)\,v$: the left is $(m^2+7m+9)\bigl(u+(m+2)v\bigr)-(m+4)(u+v)$ and the right is $(m+1)\bigl((m+5)u+(m^2+8m+14)v\bigr)$. +If $s=-1$, both sides equal $-(m+3)^2u+(m^3+9m^2+28m+30)\,v$: the left is $(m^2+5m+7)\bigl((m+4)v-u\bigr)+(m+2)(v-u)$ and the right is $(m+3)\bigl(-(m+3)u+(m^2+6m+10)v\bigr)$. +\end{proof} + +In Lean, after rewriting $r(m+3)$ and $r(m+4)$ by \eqref{eq:rec}, the proof splits on $(-1)^m=\pm1$ (\decl{neg_one_pow_eq_or}), clears the divisor (\decl{div_eq_iff}) and closes each case with \decl{ring}. + +\begin{corollary}[\decl{israelPair_z}]\label{cor:bc} +For every $n\ge1$, $b(n)=x(n)$ and $c(n)=y(n)$; in particular $b(n),c(n)\in\Z$. +\end{corollary} + +\begin{proof} +We have $x(1)=p(2)+p(1)=2$, $x(2)=p(3)-p(2)=3$, $y(1)=q(2)+q(1)=3$ and $y(2)=q(3)-q(2)=5$, the initial values of $b$ and $c$. +For $r$ satisfying \eqref{eq:rec}, induction on $k$ with Lemma~\ref{lem:israel} at $m=k$ shows that \decl{israelPair} started from $(z_r(1),z_r(2))$ equals $(z_r(k+1),z_r(k+2))$ at step $k$. Taking $r=p,q$ and $k=n-1$ gives the claim. +\end{proof} + +\begin{lemma}[\decl{det_eq}]\label{lem:det} +For every $k\ge0$, $d(k):=p(k+1)q(k)-p(k)q(k+1)\in\{1,-1\}$. +\end{lemma} + +\begin{proof} +$d(0)=1\cdot0-1\cdot1=-1$, and by \eqref{eq:rec}, with $\varepsilon=(-1)^{k+1}$, +\[ + d(k+1)=\bigl((k+2)p(k+1)+\varepsilon p(k)\bigr)q(k+1)-p(k+1)\bigl((k+2)q(k+1)+\varepsilon q(k)\bigr) + =-\varepsilon\,d(k). \qedhere +\] +\end{proof} + +\begin{corollary}\label{cor:coprime} +For every $n\ge0$, $\gcd(x(n),y(n))=1$. +\end{corollary} + +\begin{proof} +The terms $\pm p(n)q(n)$ cancel in $x(n)q(n)-p(n)y(n)$, which therefore equals $p(n+1)q(n)-p(n)q(n+1)=d(n)$. +With $d=d(n)$ we have $d^2=1$ by Lemma~\ref{lem:det}, so $\bigl(d\,q(n)\bigr)x(n)+\bigl(-d\,p(n)\bigr)y(n)=1$. In Lean these coefficients witness \texttt{IsCoprime (z 1 1 n) (z 0 1 n)} (closed by \decl{linear_combination}), which \decl{Int.isCoprime_iff_gcd_eq_one} turns into $\gcd=1$. +\end{proof} + +\begin{lemma}[\decl{seq_mono}]\label{lem:mono} +If $0\le r_0\le r_1$, then $0\le r(k)\le r(k+1)$ for every $k\ge0$. +\end{lemma} + +\begin{proof} +Induction on $k$. If $0\le r(k)\le r(k+1)$, then $r(k+1)\ge0$ and $(-1)^{k+1}r(k)\ge-r(k)\ge-r(k+1)$, so by \eqref{eq:rec} $r(k+2)\ge(k+1)r(k+1)\ge r(k+1)$. +\end{proof} + +\begin{lemma}[\decl{z_pos}]\label{lem:pos} +If $0\le r_0\le r_1$ and $r_1\ge1$, then $z_r(n)>0$ for every $n\ge1$. In particular $x(n),y(n)>0$ for $n\ge1$. +\end{lemma} + +\begin{proof} +Write $n=j+1$ and $s=(-1)^j$. By Lemma~\ref{lem:mono}, $r$ is nondecreasing, so $r(j+1)\ge r_1\ge1$ and $0\le r(j)\le r(j+1)$. By \eqref{eq:rec}, $z_r(j+1)=r(j+2)+s\,r(j+1)=(j+2+s)\,r(j+1)-s\,r(j)$. +If $s=1$ this is $(j+3)r(j+1)-r(j)\ge(j+2)r(j+1)>0$; if $s=-1$ it is $(j+1)r(j+1)+r(j)>0$. The pairs $(r_0,r_1)=(1,1)$ and $(0,1)$ satisfy the hypotheses. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main} (\decl{result})] +Let $n\ge1$. By Corollary~\ref{cor:bc}, $b(n)=x(n)$ and $c(n)=y(n)$ are integers; they are positive by Lemma~\ref{lem:pos}, coprime by Corollary~\ref{cor:coprime}, and $\xi_n=x(n)/y(n)$ by Corollary~\ref{cor:cf}. +A fraction $x/y$ with $y>0$ and $\gcd(x,y)=1$ has numerator $x$ in lowest terms (\decl{Rat.num_div_eq_of_coprime}), so $a(n)=|x(n)|=x(n)=b(n)$. In the Lean statement take $p=x(n)$, $q=y(n)$. +\end{proof} + +\begin{remark}[not formalized]\label{rem:D} +Applied to \eqref{eq:israel} directly, the determinant argument does not suffice. Let $D(n)=b(n+1)c(n)-b(n)c(n+1)$. Substituting \eqref{eq:israel}, the terms in $b(n)c(n)$ cancel and $D(n)=\frac{1+(-1)^n(n+1)}{n-(-1)^n}D(n-1)$ for $n\ge2$, with $D(1)=-1$; the factor is $(n+2)/(n-1)$ for even $n$ and $-n/(n+1)$ for odd $n$, so $|D(n)|=n$ for odd $n$ and $n+2$ for even $n$ ($D=-1,-4,3,6,-5,-8,\dots$). Granting integrality, a common divisor of $b(n)$ and $c(n)$ divides $D(n-1)$ and $D(n)$; for odd $n\ge3$ these are $\pm(n+1)$ and $\pm n$, but for even $n$ they are $\pm(n-1)$ and $\pm(n+2)$, so a common factor $3$ is not excluded when $n\equiv4\pmod6$ (e.g.\ $n=4$: $D(3)=3$, $D(4)=6$, and $3\mid c(4)=111$). +\end{remark} + +\section{Machine verification}\label{sec:lean} + +The proof is the file \path{lean/Math0/Frontier/OEIS/A262957.lean} of the math0 repository (\url{https://github.com/Foundation-0/math0}). It imports the frozen statement file of Section~\ref{sec:statement} and the audit commands \path{lean/Math0/Audit.lean}. The main declaration is +\begin{lstlisting} +theorem result : statement +\end{lstlisting} +in namespace \decl{Math0.Frontier.A262957}, with type \decl{Math0.Statements.A262957.statement}. All auxiliary declarations are \texttt{private}: \decl{seq}, \decl{seq_succ_succ}, \decl{z}, \decl{step_z}, \decl{israelPair_z}, \decl{seq_mono}, \decl{z_pos}, \decl{det_eq}, \decl{fold_eq} and \decl{cf_eq}, as in Section~\ref{sec:proof}; $p,q,x,y$ are \texttt{seq 1 1}, \texttt{seq 0 1}, \texttt{z 1 1}, \texttt{z 0 1}. The proof treats all $n$ at once; the only evaluations are of $z_p(1),z_p(2),z_q(1),z_q(2)$ (by \decl{norm_num}) and of $d(0)=-1$ (by \decl{decide}). The data lemmas \decl{a_data} and \decl{bc_data} are not used. The file contains no \texttt{sorry}, \texttt{native\_decide}, \texttt{set\_option} or \texttt{axiom}. + +\subsection*{Audit} +The file ends with +\begin{lstlisting} +#math0_settles Math0.Frontier.A262957.result Math0.Statements.A262957.statement +\end{lstlisting} +This command, used for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, the \decl{Lean.ofReduceBool} and \decl{Lean.trustCompiler} axioms behind \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the constant \decl{statement} or its negation, up to metadata annotations, with no unfolding. Running \texttt{lake env lean Math0/Frontier/OEIS/A262957.lean} in \path{lean/} prints +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize,keywords={}] +math0 audit: 'Math0.Statements.A262957.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A262957.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A262957.result' proves 'Math0.Statements.A262957.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/lean-toolchain} and \path{lean/lake-manifest.json}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root. It fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (which re-runs every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. + +{\small +\begin{thebibliography}{99} + +\bibitem{Ad} +T.~Adamczewski, \emph{OEIS Open: How many conjectures can language models turn into theorems?}, arXiv:2608.11941, 2026. + +\bibitem{Bala} +P.~Bala, \emph{A note on A262957 and A263295}, December 24, 2015, linked from \cite{A262957}: \url{https://oeis.org/A262957/a262957.pdf}. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{LW} +L.~Lorentzen and H.~Waadeland, \emph{Continued Fractions with Applications}, Studies in Computational Mathematics~3, North-Holland, Amsterdam, 1992. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A244279} +The OEIS Foundation Inc., Sequence A244279, The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A244279}. + +\bibitem{A244280} +The OEIS Foundation Inc., Sequence A244280, The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A244280}. + +\bibitem{A262957} +The OEIS Foundation Inc., Sequence A262957, The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A262957}. + +\bibitem{A263295} +The OEIS Foundation Inc., Sequence A263295, The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A263295}. + +\bibitem{A346590} +The OEIS Foundation Inc., Sequence A346590, The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A346590}. + +\end{thebibliography} +} +\end{document} diff --git a/results/oeis-a265210/README.md b/results/oeis-a265210/README.md new file mode 100644 index 0000000..e155eb9 --- /dev/null +++ b/results/oeis-a265210/README.md @@ -0,0 +1,40 @@ +# Ternary digits of 2^n: column k has least period 2*3^(k-1) and balanced digits for k ≥ 2 + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A265210 +**Date:** 2026-10-24 + +## Result + +Let T(n,k) be the k-th base-3 digit (from the least significant end) of 2^n, i.e. the digit at the place 3^(k-1). Column k consists of the rows n with 3^(k-1) ≤ 2^n. Then for every k ≥ 1: (i) p(k) = 2*3^(k-1) is a period of column k (T(n+p(k),k) = T(n,k) for every row n in the column), and no q with 0 < q < p(k) is a period; (ii) for k ≥ 2, in every block of p(k) consecutive rows m, ..., m+p(k)-1 (m in the column) the digits 0, 1 and 2 occur equally often (in fact exactly 2*3^(k-2) times each). This is Conjecture 1 of OEIS A265210 (L. Edson Jeffery, 2015). + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A265210](https://oeis.org/A265210) as [`Math0.Statements.A265210.statement`](../../lean/Math0/Statements/OEIS/A265210.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A265210.lean`](../../lean/Math0/Frontier/OEIS/A265210.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture 1: The sequence in column k is periodic, with period p(k) = 2*3^(k-1) = A008776(k-1), k >= 1, and in which the numbers 0,1,2 appear with equal frequency, for each k>1. (_L. Edson Jeffery_, Dec 04 2015) + +Referees: E. de Faria and C. Tresser, "On Sloane's persistence problem", arXiv:1307.1188 (2013), Section 3.1, Lemma 3 and the paragraph after it. It shows 2^n mod 3^k has minimum period 2*3^(k-1) and that every allowable length-k ternary tail appears exactly once per period. This predates the Dec 2015 OEIS conjecture. +J. C. Lagarias, "Ternary expansions of powers of 2", J. London Math. Soc. 79 (2009) 562-588, arXiv:math/0512006, proof of Thm 1.4, eq. (3.3): 2 is a primitive root mod 3^k, so 2^n runs over all units mod 3^k. +Y. N. Aliyev, "Digits of powers of 2 in ternary numeral system", Notes Number Theory Discrete Math. 29(3) (2023) 474-485, Lemmas 3.2-3.3 and Observation I. It gives ord_{3^(n+1)} 2 = 2*3^n and shows the last-k-digit tails are periodic with period 2*3^(k-1) and run through all endings that don't end in 0. +Also standard textbook material (2 is a primitive root mod 3^k; e.g. LeVeque, Rosen) and the A008776 comment (J. Song, 2021). +OEIS A265210 itself (rev. #18, Dec 2015) still lists the statement as a conjecture and has no proof note. The single-column least-period refinement is not stated explicitly in these sources, but it is a short elementary consequence of the same facts. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a265210, + author = {{math0}}, + title = {{Ternary digits of 2^n: column k has least period 2*3^(k-1) and balanced digits for k ≥ 2}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a265210}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a265210/paper.pdf b/results/oeis-a265210/paper.pdf new file mode 100644 index 0000000..c6ce48e Binary files /dev/null and b/results/oeis-a265210/paper.pdf differ diff --git a/results/oeis-a265210/paper.tex b/results/oeis-a265210/paper.tex new file mode 100644 index 0000000..fd5ff13 --- /dev/null +++ b/results/oeis-a265210/paper.tex @@ -0,0 +1,399 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,at}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {∧}{{$\wedge$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\len}{\operatorname{len}} + +\title[Columns of the ternary digits of $2^n$]{The base-$3$ digit of $2^n$ at a fixed place: least period $2\cdot3^{k-1}$ and equidistribution (Conjecture~1 of OEIS A265210)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +Let $T(n,k)$ be the base-$3$ digit of $2^n$ at the place $3^{k-1}$; for fixed $k$, the sequence $n\mapsto T(n,k)$ over the rows $n$ with $3^{k-1}\le 2^n$ is column $k$ of the triangle OEIS A265210. +We prove that column $k$ has least period $2\cdot3^{k-1}$ for every $k\ge1$, and that for $k\ge2$ each of the digits $0,1,2$ occurs exactly $2\cdot3^{k-2}$ times in every block of $2\cdot3^{k-1}$ consecutive entries; this is Conjecture~1 of the entry (L.~Edson Jeffery, 2015). +The result follows quickly from the classical fact that $2$ is a primitive root modulo $3^k$, and its periodicity and equidistribution parts are immediate from results of de~Faria and Tresser (2013) and of Aliyev (2023) on the last $k$ ternary digits of $2^n$, so we classify it as the first formal proof of a known result; the least period of a single column, which we did not find stated explicitly, is a short consequence of the same facts. +Our proof avoids multiplicative orders and unit groups and uses three explicit congruences obtained by lifting the exponent. +It is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the $84$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +Write $2^n$ in base $3$ and list its digits from the least significant one: row $n$ of the irregular triangle A265210 of the OEIS \cite{A265210} is this list (rows $0$--$5$ are $1;\ 2;\ 1,1;\ 2,2;\ 1,2,1;\ 2,1,0,1$). Column $k$ of the triangle consists of the $k$-th entries of the rows that have at least $k$ entries, read from top to bottom; its entry in row $n$ is the digit $T(n,k)=\lfloor 2^n/3^{k-1}\rfloor \bmod 3$ of $2^n$ at the place $3^{k-1}$. Column~$1$ is $1,2,1,2,\dots$, column~$2$ starts in row~$2$ with $1,2,2,1,0,0,1,2,2,1,0,0,\dots$, and column~$3$ starts in row~$4$ with $1,0,1,2,1,2,2,2,2,1,2,1,0,1,0,0,0,0,1,0,\dots$. +The entry was submitted by L.~Edson Jeffery on December~4, 2015, together with a conjecture that column $k$ is periodic with period $2\cdot3^{k-1}$ and, for $k>1$, equidistributed among the digits $0,1,2$ (Section~\ref{sec:statement}). When we checked it in October 2026, the entry was still at revision \#18 (December~6, 2015); it labels the statement a conjecture and contains no proof note. We prove it in the form of Theorem~\ref{thm:main}, with $2\cdot3^{k-1}$ the \emph{least} period. + +\subsection*{Prior work and status} +The mathematics is classical, and we credit it as follows. +\begin{itemize} +\item It is well known that $2$ is a primitive root modulo $3^k$ for every $k\ge1$: the residues $2^n \bmod 3^k$ have least period $\varphi(3^k)=2\cdot3^{k-1}$ and run through all units modulo $3^k$ (de~Faria and Tresser cite \cite[p.~81]{LeV} for this). Lagarias uses this in the proof of his Theorem~1.4 \cite[eq.~(3.3)]{Lag}. +\item De~Faria and Tresser \cite[\S3.1, Lemma~3 and the paragraph following it]{dFT} state that $2^n \bmod 3^k$ has minimum period $2\cdot3^{k-1}$ and that in any full minimum period each of the $2\cdot3^{k-1}$ ternary strings of length $k$ not ending in $0$ occurs exactly once as the string of the last $k$ digits of $2^n$. Since for $k\ge2$ exactly $2\cdot3^{k-2}$ of these strings have a given digit at the place $3^{k-1}$, the equidistribution and the period $2\cdot3^{k-1}$ of column $k$ follow at once. Their preprint (July 2013) predates the conjecture. +\item Aliyev \cite[Lemmas~3.1--3.3, the Note after Lemma~3.2, and Observation~I]{Ali} proves that $3^k$ exactly divides $2^{3^{k-1}}+1$, deduces that the order of $2$ modulo $3^{n+1}$ is $2\cdot3^n$, and shows that the last $k$ ternary digits of $2^n$ are periodic and run through all endings that do not end in $0$. His Lemma~3.1 is a weaker form of our Lemma~\ref{lem:key}. +\item A comment of Jianing Song (2021) in A008776 \cite{A008776} (the sequence $2\cdot3^n$) records that $2\cdot3^n$ is the order modulo $3^{n+1}$ of every integer congruent to $2$ or $5$ modulo $9$. +\end{itemize} +The one part we did not find stated explicitly is that a single column (rather than the block of the last $k$ digits) has \emph{least} period exactly $2\cdot3^{k-1}$. For $k\ge2$ it follows in a few lines from the congruences $2^{3^{k-1}}\equiv-1$ and $2^{2\cdot3^{k-2}}\equiv 1+3^{k-1} \pmod{3^k}$ (Corollary~\ref{cor:E}), which is not a new idea. We therefore classify the result as the \emph{first formal proof of a known result}. (One math0 referee classified it as settling the OEIS conjecture; the other, whose literature search produced the references above, judged it known; we follow the second.) All of Theorem~\ref{thm:main} is proved in Lean, without multiplicative orders or unit groups; only Remark~\ref{rem:primroot} is not formalized. + +\section{Statement}\label{sec:statement} + +\subsection{The OEIS entry} +The name of A265210 \cite{A265210} is \texttt{Irregular triangle read by rows in which row n lists the base 3 digits of 2\^{}n in reverse order, n >= 0} (offset $0$; $84$ terms listed, rows $0$ to $15$). The COMMENTS section contains, verbatim, +\begin{quote} +{\small\raggedright\texttt{Conjecture 1: The sequence in column k is periodic, with period p(k) = 2*3\^{}(k-1) = A008776(k-1), k >= 1, and in which the numbers 0,1,2 appear with equal frequency, for each k>1.}\par} +\end{quote} +The comment is unsigned. The entry's author line reads \texttt{\_L. Edson Jeffery\_, Dec 04 2015}, and the revision history of the entry shows that he wrote the comment on that day (revisions \#2--\#5), so we attribute the conjecture to him, as the math0 statement file does. + +\subsection{The theorem} +For $n\ge0$ and $k\ge1$ let $T(n,k)=\lfloor 2^n/3^{k-1}\rfloor \bmod 3$, let $C_k=\{n\ge0: 3^{k-1}\le 2^n\}$ be the set of rows having an entry in column $k$ (an up-set of $\N$), and let $p(k)=2\cdot3^{k-1}$. + +\begin{theorem}\label{thm:main} +Let $k\ge1$. +\begin{enumerate} +\item[(i)] $T(n+p(k),k)=T(n,k)$ for every $n\in C_k$; and for every integer $q$ with $0 a (i + 0)) = + [1, 2, 1, 1, 2, 2, 1, 2, 1, 2, 1, 0, 1, 1, 0, 1, 2, 2, 0, 2, 1, 1, ..., 2, 2, 1, 1] := by + decide +kernel +def T (n k : ℕ) : ℕ := (row n).getD (k - 1) 0 +def IsColPeriod (k q : ℕ) : Prop := + ∀ n : ℕ, k ≤ (row n).length → T (n + q) k = T n k +def p (k : ℕ) : ℕ := 2 * 3 ^ (k - 1) +def statement : Prop := + ∀ k : ℕ, 1 ≤ k → + (IsColPeriod k (p k) ∧ ∀ q : ℕ, 0 < q → q < p k → ¬ IsColPeriod k q) ∧ + (2 ≤ k → ∀ m : ℕ, k ≤ (row m).length → ∀ d e : ℕ, d < 3 → e < 3 → + ((Finset.Ico m (m + p k)).filter (fun n => T n k = d)).card = + ((Finset.Ico m (m + p k)).filter (fun n => T n k = e)).card) +end Math0.Statements.A265210 +\end{lstlisting} + +\emph{Encoding.} \texttt{Nat.digits 3 x} lists the base-$3$ digits of $x$, least significant first, so \texttt{row n} is row $n$ of the triangle. \texttt{a m} is entry $m$ (offset $0$) of the concatenation of rows $0,\dots,m$, which has more than $m$ entries since every row is nonempty, so the default $0$ of \texttt{getD} is never used. \texttt{T n k} is entry $k$ of row $n$ (with default $0$), which is an actual entry of the triangle exactly when \texttt{k ≤ (row n).length}. Row lengths are nondecreasing, so the rows with an entry in column $k$ are $n_0,n_0+1,\dots$ for some $n_0=n_0(k)$, and \texttt{IsColPeriod k q} says exactly that the column, read as the sequence $c(i)=T(n_0+i,k)$, satisfies $c(i+q)=c(i)$ for all $i\ge0$. \texttt{p k} is $2\cdot3^{k-1}$, with no truncated subtraction since $k\ge1$ wherever it is used. + +\emph{Reading choices.} (1) ``Periodic, with period $p(k)$'' is read as ``$p(k)$ is the least positive period'': every multiple of a period is a period, so naming one value refers to the least one. (2) ``Appear with equal frequency'' is read as equal counts of $0,1,2$ in every block of $p(k)$ consecutive entries; given periodicity, this is equivalent to equal counts in one period and to asymptotic frequencies $1/3$, so the truth value does not depend on this choice. Periodicity is asserted for $k\ge1$ and equidistribution for $k\ge2$, as in the conjecture (column~$1$ contains no $0$). Both math0 referees judged the statement faithful. + +\emph{Data checks.} The definitions are anchored to the entry by lemmas proved with \texttt{decide +kernel}: \decl{a_data} reproduces all $84$ listed terms (rows $0$--$15$), \decl{row_example} the example rows $13$--$15$, and \decl{col1_data}, \decl{col2_data}, \decl{col3_data} the first terms of columns $1,2,3$ and the rows where columns $2,3$ start; \decl{sanity_small_columns} checks the periods $6$ and $18$ on the first $40$ rows of columns $2,3$ and the counts $(2,2,2)$, $(6,6,6)$ in their first periods. The proof does not use these checks. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A265210.lean}; Lean names are given in brackets. Throughout, for $j\ge0$ we write +\[ + B=3^{j+1},\qquad M=3^{j+2}=3B,\qquad r=2\cdot3^j,\qquad P=2B=3r=p(j+2), +\] +and $d(n)=\lfloor 2^n/B\rfloor \bmod 3$, $s(n)=2^n \bmod 3$. Column $j+2$ is the case $k=j+2\ge2$. + +\subsection{Digits and lengths} + +\begin{lemma}[\decl{T_eq}, \decl{len_iff}]\label{lem:digit} +For all $n\ge0$ and $k\ge1$, $T(n,k)$ as defined in Lean equals $\lfloor 2^n/3^{k-1}\rfloor \bmod 3$, and \texttt{k ≤ (row n).length} holds if and only if $3^{k-1}\le 2^n$. In particular $T(n,j+2)=d(n)$. +\end{lemma} + +\begin{proof} +For $b\ge2$, entry $i$ (counting from $0$, with default $0$) of the digit list of $x$ in base $b$ is $\lfloor x/b^i\rfloor \bmod b$ (\texttt{Nat.getD\_digits}); this includes the case where $i$ is at least the length of the list, since then $x= 2}} +Fix $j\ge0$ and let $k=j+2$, so that $C_k=\{n: B\le 2^n\}$ by Lemma~\ref{lem:digit}. Call $x\ge0$ a \emph{column period} [\decl{Per}] if $d(n+x)=d(n)$ for all $n\in C_k$. By Lemma~\ref{lem:digit}, $q$ is a column period exactly when \texttt{IsColPeriod (j+2) q} holds. + +\begin{lemma}[\decl{Per_mul}, \decl{Per_gcd}]\label{lem:per} +(a) If $x$ is a column period, so is $xt$ for every $t\ge0$. +(b) If $q$ and $Q$ are column periods and $g=\gcd(q,Q) absurd h (by norm_num)⟩ + · obtain ⟨j, rfl⟩ : ∃ j, k = j + 2 := ⟨k - 2, by omega⟩ + obtain ⟨h1, h2⟩ := col_ge_two j + refine ⟨h1, fun _ m _ d e hd he => ?_⟩ + rw [h2 m d hd, h2 m e he] +end Math0.Frontier.A265210 +#math0_settles Math0.Frontier.A265210.result Math0.Statements.A265210.statement +\end{lstlisting} +Neither file uses \texttt{sorry}, \texttt{native\_decide}, custom axioms or \texttt{set\_option}. + +\subsection*{Audit} +The command \texttt{\#math0\_settles} (in \path{lean/Math0/Audit.lean}, for statements that math0 formalizes itself) fails unless (1) \decl{statement} is a universe-monomorphic \texttt{Prop}-valued definition; (2) \decl{statement} and \decl{result} depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which rejects \decl{sorryAx}, \decl{Lean.ofReduceBool} (from \texttt{native\_decide}) and custom axioms; and (3) the type of \decl{result} is syntactically \decl{statement} or $\neg$\,\decl{statement}, up to metadata, with no unfolding. It reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A265210.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A265210.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A265210.result' proves 'Math0.Statements.A265210.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use (the statement is math0's own formalization of the OEIS conjecture). +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib cache, runs \texttt{lake build} on all math0 results (re-running every audit), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The single file is checked by \texttt{lake env lean Math0/Frontier/OEIS/A265210.lean} in \path{lean} (about $17$\,s on our machine). + +{\small +\begin{thebibliography}{99} + +\bibitem{Ali} +Y.~N. Aliyev, \emph{Digits of powers of 2 in ternary numeral system}, Notes Number Theory Discrete Math.\ \textbf{29} (2023), no.~3, 474--485, \url{https://doi.org/10.7546/nntdm.2023.29.3.474-485}. + +\bibitem{dFT} +E.~de~Faria and C.~Tresser, \emph{On Sloane's persistence problem}, Exp.\ Math.\ \textbf{23} (2014), no.~4, 363--382, \url{https://doi.org/10.1080/10586458.2014.910849}; arXiv:1307.1188 (July 2013), whose numbering we use. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Lag} +J.~C. Lagarias, \emph{Ternary expansions of powers of 2}, J. Lond.\ Math.\ Soc.\ (2) \textbf{79} (2009), no.~3, 562--588, \url{https://doi.org/10.1112/jlms/jdn080}; arXiv:math/0512006 (v4, July 2008), whose numbering we use. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{LeV} +W.~LeVeque, \emph{Fundamentals of Number Theory}, Addison-Wesley, Reading, Massachusetts, 1977. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{A008776} +The OEIS Foundation Inc., \emph{Pisot sequences $E(2,6)$, $L(2,6)$, $P(2,6)$, $T(2,6)$} (the numbers $2\cdot3^n$), entry A008776 (N.~J.~A. Sloane and D.~W. Wilson) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A008776}. + +\bibitem{A265210} +The OEIS Foundation Inc., \emph{Irregular triangle read by rows in which row $n$ lists the base $3$ digits of $2^n$ in reverse order, $n\ge0$}, entry A265210 (L.~E. Jeffery, 2015) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A265210}; revision \#18, December~6, 2015. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a265649/README.md b/results/oeis-a265649/README.md new file mode 100644 index 0000000..f654d34 --- /dev/null +++ b/results/oeis-a265649/README.md @@ -0,0 +1,36 @@ +# A265649: both of Werner Schulte's closed forms hold + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A265649 +**Date:** 2026-10-29 + +## Result + +Let T(0,0)=1, T(0,k)=0 for k>0, and T(n,k) = T(n-1,k-1) + (2n-1+k)·T(n-1,k) for n ≥ 1, with T(n,-1)=0. Then (i) for all 0 ≤ k ≤ n, T(n,k) = 2^(n-k)·(n-k)!·C(n,k)·Σ_{j=0}^{n-k} (-1/4)^j·C(2j+k,j)·C(n,j+k). (ii) For all n ≥ 1 and 0 ≤ k ≤ n, T(n,k) = (-1)^k·Σ_{j=0}^{n-1} A001497(n-1,j)·A021009(j+1,k). Here A001497(n,m) = (2n-m)!/(m!(n-m)!2^(n-m)) is the Bessel triangle and A021009(n,m) = (-1)^m·n!·C(n,m)/m! is the signed Laguerre triangle, both zero outside 0 ≤ m ≤ n. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A265649](https://oeis.org/A265649) as [`Math0.Statements.A265649.statement`](../../lean/Math0/Statements/OEIS/A265649.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A265649.lean`](../../lean/Math0/Frontier/OEIS/A265649.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A265649 Conjecture: T(n,k) = 2^(n-k)*(n-k)!*binomial(n,k)*(Sum_{j=0..n-k} (-1/4)^j* binomial(2*j+k,j)*binomial(n,j+k)). %F A265649 Conjecture: T(n,k) = (-1)^k*Sum_{j=0..n-1} A001497(n-1,j)*A021009(j+1,k). (_Werner Schulte_, Dec 11 2015) + +Referees: No explicit prior proof of either formula was found, and OEIS A265649 (rev. #40, Mar 2024) still marks both as "Conjecture". Both are immediate special cases of known results: +(1) L. C. Hsu and P. J.-S. Shiue, "A unified approach to generalized Stirling numbers", Adv. Appl. Math. 20 (1998) 366-384: generalized Stirling numbers S(n,k;α,β,r), whose defining connection relation directly gives the product formula. +(2) R. S. Maier, "Boson Operator Ordering Identities from Generalized Stirling and Eulerian Numbers", arXiv:2308.10332 (v4, 9 Feb 2024), linked from the A265649 entry. Eq. (18) gives the product formula S(α,γ;r1+r2) = S(α,β;r1)S(β,γ;r2). §5, p. 19 identifies A265649 = S_{n,k}(-2,1;1). Pp. 17-18 identify A001497 = b̂^(1) = S(-2,-1;1) and A021009 = L̂^(1) = S(-1,1;1) (signed), and Thm 5.1 (ii'), (iv') gives their closed forms. Eq. (72) states the r=0 analogue S(-2,1;0) = S(-2,-1;0)S(-1,1;0) of Conjecture 2. Thm 5.2(vi) gives a different, proved 2F1 closed form for S_{n,k}(-2,1;1). +Conjecture 2 = S(-2,-1;0)·S(-1,1;1), and Conjecture 1 = S(-2,2;2)·S(2,1;-1), reindexed; both checked numerically. +Also checked, with no A265649 resolution found: P. Barry, arXiv:1702.04011, Example 1 (displays the array as the exponential Riordan array [1/sqrt(1-2x), 1/sqrt(1-2x)-1], with no proof of the conjectures); S. Fried's OEIS-conjecture series (arXiv:2410.07237; JIS 28 (2025) Art. 25.4.3; JIS 29 (2026) Art. 26.1.8; arXiv:2607.24832); cross-referencing entries A370419, A347204 and A035342. + +## Citation + +```bibtex +@misc{math0:oeis-a265649, + author = {{math0}}, + title = {{A265649: both of Werner Schulte's closed forms hold}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a265649}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a267486/README.md b/results/oeis-a267486/README.md new file mode 100644 index 0000000..1502117 --- /dev/null +++ b/results/oeis-a267486/README.md @@ -0,0 +1,46 @@ +# O'Sullivan's Gaussian-polynomial / Chebyshev representation conjecture (A267486), proved + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A267486 +**Date:** 2026-10-29 + +## Result + +Fix m, n ≥ 0 and put N = n + ⌊m/2⌋, so that 2n + m + 1 - (m mod 2) = 2N + 1. Let g = g(m;n) be mn for odd m and (2n+1)m/2 for even m. Let G(m;n,x) be the coefficient of t^m in (1+t) ∏_{k=1}^{N} (1 + t² + 2t T_k(x/2)), where T_k is the Chebyshev polynomial of the first kind. Write a(m;n,k) = [x^k] G(m;n,x). The claim is that deg_x G(m;n,x) ≤ g, and that the Gaussian polynomial satisfies [2N+1, m]_q = Σ_{k=0}^{g} a(m;n,k) (1+q²)^k q^{g-k}. The Gaussian polynomial is the one defined by the q-Pascal rule [M+1,m+1] = [M,m] + q^{m+1}[M,m+1]. + +## Assessment + +Put x = q + 1/q. Then 2T_k(x/2) = q^k + q^{-k}, so each factor 1 + t^2 + 2tT_k(x/2) splits as (1+tq^k)(1+tq^{-k}), and (1+t) times the product equals prod_{j=-N}^{N}(1+tq^j). The classical finite q-binomial theorem then gives the coefficient of t^m as q^{-g}[2N+1,m]_q, which is exactly the claimed expansion. The degree bound follows because [2N+1,m]_q has q-span 2g. This is the full proof, well under a page, built from two textbook facts. It settles the general conjecture as the author intended it, not only some degenerate reading. + +*Follows from:* The Cauchy/Rothe finite q-binomial theorem, prod_{j=0}^{M-1}(1+q^j t) = sum_m q^{C(m,2)} [M,m]_q t^m, combined with the standard Chebyshev identity 2T_k((q+1/q)/2) = q^k + q^{-k}. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A267486](https://oeis.org/A267486) as [`Math0.Statements.A267486.statement`](../../lean/Math0/Statements/OEIS/A267486.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A267486.lean`](../../lean/Math0/Frontier/OEIS/A267486.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C A267486 Conjecture: More generally, the Gaussian polynomial [2*n+m+1-(m mod 2),m]_q = Sum_{k=0..g(m;n)} a(m;n,k)*(1+q^2)^k*q^(g(m;n)-k), for m >= 0, n >= 0, where g(m;n) = m*n if m is odd and (2*n+1)*m/2 if m is even, and ... a(m;n,k) = [x^k]G(m;n,x), G(m;n,x) = (d^m/dt^m)G(m;n,t,x)/m!|_{t=0}, G(m;n,t,x) = (1+t)*Product_{k=1..n+(m - m mod 2)/2}(1 + t^2 + 2*t*T(k,x/2)). (Stephen O'Sullivan, entry author, 2016) + +Referees: - OEIS A267486 (local mirror, revision #23, May 30 2026) and its siblings A267120, A267482, A267483, A267484, A267485 all state the same general conjecture with no recorded proof. +- A267482: W. Lang (Oct 19 2019) proves the m=1 case only, settling T. Baruchel's 2018 conjecture R(n,x) = S(n,x) + S(n-1,x) via [2n+1]_q = q^n S(2n, q^(1/2)+q^(-1/2)). +- S. O'Sullivan, 'A class of high-order Runge-Kutta-Chebyshev stability polynomials', J. Comput. Phys. 300 (2015) 665-678, arXiv:1507.08631, Eqs. (19)-(20): the representation [P,k]_q = Sum r_g q^(G_k/2-g)(1+q^2)^g, with generating function (1-t)·Prod_{k=1..N}(1+t^2-2tC_k), is stated without proof (P = 2N+1). +- O'Sullivan's follow-ups arXiv:1702.03818 and arXiv:1712.03971 do not treat it. +- The classical Cauchy/Rothe finite q-binomial theorem, Prod_{j=0..M-1}(1+q^j t) = Sum_m q^(C(m,2))[M,m]_q t^m, makes the general identity a direct corollary, though I found no source that writes out this deduction for the conjecture. +- Not related to this conjecture: J.-C. Liu, arXiv:2509.06357 (Chebyshev expansions of MacMahon-type q-series). + +## Citation + +```bibtex +@misc{math0:oeis-a267486, + author = {{math0}}, + title = {{O'Sullivan's Gaussian-polynomial / Chebyshev representation conjecture (A267486), proved}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a267486}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a270668/README.md b/results/oeis-a270668/README.md new file mode 100644 index 0000000..24ec0f7 --- /dev/null +++ b/results/oeis-a270668/README.md @@ -0,0 +1,38 @@ +# Mathar's generating function for column 3 of A270668 (domino tilings of (4k+1)x5 boards with central hole) + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A270668 +**Date:** 2026-10-25 + +## Result + +Let c_k = T(2k, 2) be the number of domino tilings of the (4k+1) x 5 board with its central cell removed (c_0 = 1 for the 1 x 5 strip with its middle cell removed). Then, in Q[[x]], + sum_{k>=0} c_k x^k = (-1 - 4x + 543x^2 - 6238x^3 + 17032x^4 - 6238x^5 + 543x^6 - 4x^7 - x^8) / ((x-1)(x^2-7x+1)(x^2-23x+1)(x^4-161x^3+576x^2-161x+1)). +This is R. J. Mathar's 2016 conjectured g.f. for "column 3" of OEIS A270668. Equivalently, (sum c_k x^k) * den = num. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A270668](https://oeis.org/A270668) as [`Math0.Statements.A270668.statement`](../../lean/Math0/Statements/OEIS/A270668.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A270668.lean`](../../lean/Math0/Frontier/OEIS/A270668.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A270668 Conjectured g.f. for column 3: ( -1 -4*x +543*x^2 -6238*x^3 +17032*x^4 -6238*x^5 +543*x^6 -4*x^7 -x^8 ) / ( (x-1) *(x^2-7*x+1) *(x^2-23*x+1) *(x^4 -161*x^3 +576*x^2 -161*x +1) ). - _R. J. Mathar_, Mar 23 2016 + +Referees: R. J. Mathar, "A270668: Domino tilings with one monomer in the center", PDF linked from OEIS A270668 (https://oeis.org/A270668/a270668.pdf), dated Apr 13 2016. It counts the 5 x (2m+1) floor with a central monomer by the transfer-matrix method: 50 states, nine centre configurations, and left/right Hadamard products of rational g.f.s in x = z^5. It appears to derive the column-3 g.f. that Mathar had conjectured on Mar 23 2016 in OEIS A270668 (still labelled "Conjectured" there). I saw its content only through search-engine extracts; the full PDF could not be downloaded. Related but not resolving: OEIS A143659 / M. Ciucu arXiv:0710.4500 (diagonal); A189003/A189006 (5xn corner-removed, same characteristic polynomial t^4-15t^3+32t^2-15t+1); A003775, A006238; B. E. Tenner, EJC 11(2) R17 (2005); Byun-Goddard arXiv:2502.05918; Stanley EC1 section 4.2.5 (Hadamard products of rational series). No prior Lean or other formalization found. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a270668, + author = {{math0}}, + title = {{Mathar's generating function for column 3 of A270668 (domino tilings of (4k+1)x5 boards with central hole)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a270668}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a270668/paper.pdf b/results/oeis-a270668/paper.pdf new file mode 100644 index 0000000..22b9cb2 Binary files /dev/null and b/results/oeis-a270668/paper.pdf differ diff --git a/results/oeis-a270668/paper.tex b/results/oeis-a270668/paper.tex new file mode 100644 index 0000000..5a1bdd7 --- /dev/null +++ b/results/oeis-a270668/paper.tex @@ -0,0 +1,381 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{booktabs} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {∈}{{$\in$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {⊆}{{$\subseteq$}}1 {×}{{$\times$}}1 + {ˢ}{{$^{\mathrm{s}}$}}1 {⁻}{{$^{-}$}}1 {¹}{{$^{1}$}}1 + {⟦}{{$[\![$}}1 {⟧}{{$]\!]$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{ˢ}{\ensuremath{^{\mathrm{s}}}} +\newunicodechar{⟦}{\ensuremath{[\![}} +\newunicodechar{⟧}{\ensuremath{]\!]}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +\allowdisplaybreaks +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\def\UrlFont{\normalfont\ttfamily}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\ib}[1]{[\,#1\,]} +\newcommand{\Til}{\operatorname{Til}} +\newcommand{\cnt}{\operatorname{cnt}} +\newcommand{\rest}{\operatorname{rest}} +\newcommand{\cA}{\mathcal{A}} +\newcommand{\cG}{\mathcal{G}} +\newcommand{\cC}{\mathcal{C}} +\newcommand{\cR}{\mathcal{R}} +\newcommand{\one}{\mathbf{1}} + +\title[Domino tilings of $(4k+1)\times5$ boards with a central hole]{The generating function for domino tilings of $(4k+1)\times 5$ boards with a central hole: a formal proof of Mathar's conjecture in OEIS A270668} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 25, 2026} + +\begin{document} +\begin{abstract} +Let $c_k$ be the number of domino tilings of the $(4k+1)\times5$ board with its central cell removed. +We prove that $\sum_{k\ge0}c_kx^k$ equals the rational function with denominator $(x-1)(x^2-7x+1)(x^2-23x+1)(x^4-161x^3+576x^2-161x+1)$ that R.~J.~Mathar conjectured in 2016 for column~3 of the OEIS triangle A270668. The proof writes $c_{k+1}$ as a bilinear form in two vectors built from a $32$-state row transfer matrix, whose entries satisfy an order-$4$ recurrence, and derives the order-$9$ recurrence of the denominator for the products. +The entry still calls the formula conjectured, but a transfer-matrix note by Mathar, linked from the entry and dated three weeks later, derives exactly this rational function, so we classify our result as the first formal proof of a known result. +It is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry; there the tiling count is defined from first principles and checked by the kernel against all $36$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +For $0\le m\le n$ let $T(n,m)$ be the number of domino tilings of the $(2n+1)\times(2m+1)$ board with its central cell removed. Tilings that differ by a rotation or reflection of the board are distinct. This is the triangle A270668 of the OEIS \cite{A270668}, created by R.~J.~Mathar on March~21, 2016, with more terms by A.~P.~Heinz ($36$ terms, rows $0$ to $7$). Its diagonal is A143659 \cite{A143659}, the odd square with a central unit hole, studied by Ciucu \cite{Ciucu}. The checkerboard colouring shows that $T(n,m)=0$ when $n+m$ is odd. The four corners have the same colour, so the board has one extra cell of that colour, and the centre has that colour exactly when $n+m$ is even. + +On March~23, 2016, Mathar added a ``Conjectured g.f.\ for column 3'' (quoted in Section~\ref{sec:statement}). Column~3 is the third column, $m=2$ (boards of width $5$). Its nonzero terms are $T(2k,2)$, and the conjecture gives $\sum_{k\ge0}T(2k,2)x^k$ as an explicit rational function. We prove it (Theorem~\ref{thm:main}). + +\emph{Prior work and status.} The entry links a five-page note by Mathar, \emph{A270668: Domino tilings with one monomer in the center} \cite{MatharNote}, dated April~13, 2016, the date of the entry's latest revision. (The math0 referees saw it only through search-engine extracts; we read the full note for this manuscript.) It counts the tilings of the $5\times(2m+1)$ board with a central monomer by the transfer-matrix method, with $50$ states of the front line. Drawing the board with $5$ rows, it distinguishes nine configurations of the dominoes covering the two cells directly above and below the central cell, five of which contribute. For each of these it combines the counts of the two halves of the board on either side of the central cell by a Hadamard product of rational series, which is again rational (the note cites \cite{EC1} for this). Its final section sums the five contributions and states the generating function +\[ + \frac{1+4x-543x^2+6238x^3-17032x^4+6238x^5-543x^6+4x^7+x^8}{(1-x)(x^2-7x+1)(x^2-23x+1)(x^4-161x^3+576x^2-161x+1)} + =1+196x+31329x^2+\cdots, +\] +which is the conjectured one with the numerator and the factor $x-1$ both negated. The note gives the generating functions of the halves and of their Hadamard products without the computations behind them. So Mathar derived the column-$3$ generating function three weeks after conjecturing it, although the entry still says ``Conjectured''. The quartic $t^4-15t^3+32t^2-15t+1$ that drives our proof is the characteristic polynomial of the recurrence of A006238 (spanning trees of the $3\times n$ grid) \cite{A006238}. Evaluated at $x^2$, it is, up to sign, also the denominator of the generating function of A189003 \cite{A189003}; in $z^5$ it is the denominator of the half-board series in \cite{MatharNote}. Other work on domino tilings with holes includes Tenner's parity results, which cover squares with a central square hole \cite{Tenner}, and the divisibility and parity results of Byun and Goddard for one-hole tilings of squares and rectangles \cite{BG}. According to the referees, neither these papers nor \cite{Ciucu} treat this column, and they found no earlier formalization. We therefore classify our result as the \emph{first formal proof of a known result}. Our argument has the same overall shape as the note's: split the board at the hole and combine the two halves by products of sequences that satisfy linear recurrences. The details differ. We use a $32$-state row transfer matrix and its symmetry instead of front-line states and centre configurations. We also prove the order-$9$ recurrence for products of solutions of an order-$4$ recurrence as a polynomial identity, instead of computing Hadamard products of generating functions. + +\section{Statement}\label{sec:statement} + +The FORMULA section of A270668 \cite{A270668} contains, verbatim, the line +\begin{lstlisting}[language={},frame=none,basicstyle=\ttfamily\footnotesize] +Conjectured g.f. for column 3: ( -1 -4*x +543*x^2 -6238*x^3 +17032*x^4 -6238*x^5 +543*x^6 -4*x^7 -x^8 ) / ( (x-1) *(x^2-7*x+1) *(x^2-23*x+1) *(x^4 -161*x^3 +576*x^2 -161*x +1) ). - _R. J. Mathar_, Mar 23 2016 +\end{lstlisting} + +\begin{theorem}\label{thm:main} +For $k\ge0$ let $c_k=T(2k,2)$ be the number of domino tilings of the $(4k+1)\times5$ board with its central cell (row $2k$, column $2$, counting from $0$) removed. Then $\sum_{k\ge0}c_kx^k=N(x)/D(x)$ in $\Q[[x]]$, where +\begin{align*} + N(x)&=-1-4x+543x^2-6238x^3+17032x^4-6238x^5+543x^6-4x^7-x^8,\\ + D(x)&=(x-1)(x^2-7x+1)(x^2-23x+1)(x^4-161x^3+576x^2-161x+1). +\end{align*} +\end{theorem} + +The series is $1+196x+31329x^2+4941729x^3+777852100x^4+\cdots$. The coefficients of $x,x^2,x^3$ are the listed $T(2,2)$, $T(4,2)$, $T(6,2)$. The constant term is $T(0,2)=1$, for the $1\times5$ strip minus its middle cell. That board lies outside the triangle ($m>n$) but is covered by the same definition. Expanding, $D(x)=\sum_{j=0}^{9}d_jx^j$ with +\begin{equation}\label{eq:den} + (d_0,\dots,d_9)=(-1,192,-5760,49283,-147264,147264,-49283,5760,-192,1). +\end{equation} +As $D(0)=-1$, the theorem is equivalent to $\bigl(\sum_kc_kx^k\bigr)D(x)=N(x)$, i.e.\ to +\begin{equation}\label{eq:coeff} + \textstyle\sum_{j=0}^{\min(n,9)}d_j\,c_{n-j}=\nu_n\qquad(n\ge0), +\end{equation} +where $\nu_n$ is the coefficient of $x^n$ in $N$ ($\nu_n=0$ for $n\ge9$). + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A270668.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{6dac026f\ldots c55939}) before any proof attempt. Its definitions and statement read as follows. They are quoted verbatim, except that we omit the import, comments, docstrings, blank lines, all theorems, the computable evaluator described below, and the auxiliary definitions used only in proofs (such as \decl{cnt} in Section~\ref{sec:proof}). +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +namespace Math0.Statements.A270668 +open Finset +abbrev Cell := ℕ × ℕ +def IsDomino (d : Finset Cell) : Prop := + ∃ i j : ℕ, d = {(i, j), (i, j + 1)} ∨ d = {(i, j), (i + 1, j)} +def IsTiling (S : Finset Cell) (D : Finset (Finset Cell)) : Prop := + (∀ d ∈ D, IsDomino d ∧ d ⊆ S) ∧ ∀ x ∈ S, ∃! d, d ∈ D ∧ x ∈ d +def board (r c : ℕ) : Finset Cell := range r ×ˢ range c +def region (n m : ℕ) : Finset Cell := (board (2 * n + 1) (2 * m + 1)).erase (n, m) +noncomputable def T (n m : ℕ) : ℕ := {D | IsTiling (region n m) D}.ncard +open PowerSeries +noncomputable def num : ℚ⟦X⟧ := + -1 - 4 * X + 543 * X ^ 2 - 6238 * X ^ 3 + 17032 * X ^ 4 - 6238 * X ^ 5 + 543 * X ^ 6 - + 4 * X ^ 7 - X ^ 8 +noncomputable def den : ℚ⟦X⟧ := + (X - 1) * (X ^ 2 - 7 * X + 1) * (X ^ 2 - 23 * X + 1) * + (X ^ 4 - 161 * X ^ 3 + 576 * X ^ 2 - 161 * X + 1) +def statement : Prop := + PowerSeries.mk (fun k => (T (2 * k) 2 : ℚ)) = num * den⁻¹ +end Math0.Statements.A270668 +\end{lstlisting} +A cell $(i,j)$ lies in row $i$ and column $j$; a domino is $\{(i,j),(i,j+1)\}$ or $\{(i,j),(i+1,j)\}$ over $\N$, so nothing wraps around. A tiling of $S$ is a set of dominoes inside $S$ covering every cell of $S$ exactly once, so rotated or reflected tilings are distinct, as the entry requires. \texttt{region n m} is the board minus its central cell $(n,m)$. \texttt{T n m} counts its tilings; the set of tilings is finite (\decl{tilings_finite}), so \texttt{ncard} is not a junk value. \texttt{T} is defined for all $n,m$, so it covers $T(0,2)$. Since \texttt{den} has constant coefficient $-1$, \texttt{den⁻¹} is its true inverse, and \decl{statement_iff} shows that the statement is equivalent to \texttt{mk (fun k => T (2k) 2) * den = num}. + +\emph{Data checks.} The file defines a computable evaluator \decl{Tc} (Lemma~\ref{lem:init}) and proves \decl{T_eq_Tc}: $T(n,m)=\texttt{Tc}(n,m)$ for all $n,m$. It also proves that the triangle \decl{a} read by rows with offset $0$ satisfies $a(n(n+1)/2+m)=T(n,m)$ for $m\le n$ (\decl{a_spec}). \decl{a_data} checks by \texttt{decide +kernel} that $a(0),\dots,a(35)$ are the $36$ terms of the entry. Column $m=1$ and column $m=3$ ($75272,135663392,\dots$) do not match the conjectured series, which confirms that $m=2$ is the intended reading of ``column 3''. + +\section{Proof}\label{sec:proof} + +We follow \path{lean/Math0/Frontier/OEIS/A270668.lean}; Lemmas~\ref{lem:step} and~\ref{lem:cnt} are proved in the statement file. We write $\ib{P}$ for $1$ if $P$ holds and $0$ otherwise, and $\Til(F)$ for the set of domino tilings of a finite set of cells $F$. + +\begin{lemma}[\decl{ncard_tilings_step}, \decl{ncard_tilings_le}]\label{lem:step} +Let $p$ be the lexicographically least cell of a finite set of cells $F\neq\emptyset$. Let $\mathrm{rt}(i,j)=(i,j+1)$ and $\mathrm{dn}(i,j)=(i+1,j)$. Then +$\#\Til(F)=\ib{\mathrm{rt}\,p\in F}\,\#\Til(F\setminus\{p,\mathrm{rt}\,p\})+\ib{\mathrm{dn}\,p\in F}\,\#\Til(F\setminus\{p,\mathrm{dn}\,p\})$. +Also $\Til(\emptyset)=\{\emptyset\}$, and $\#\Til(F)\le2^{\lfloor|F|/2\rfloor}$ for all finite $F$. +\end{lemma} + +\begin{proof} +The domino of a tiling that contains $p$ has its other cell in $F$, so that cell does not precede $p$; hence the domino is $\{p,\mathrm{rt}\,p\}$ or $\{p,\mathrm{dn}\,p\}$. For a domino $d\subseteq F$, removing $d$ is a bijection from the tilings of $F$ containing $d$ onto $\Til(F\setminus d)$. The bound follows by induction on $|F|$. +\end{proof} + +\subsection{States} +Fix $K\ge0$. Then $c_{K+1}=T(2K+2,2)$ is the number of tilings of the board with rows $0,\dots,4K+4$ and columns $0,\dots,4$, minus the cell $(2K+2,2)$. We number cell $(i,j)$ as $5i+j$. There are $N=20K+25$ cells, the hole has index $h=10K+12$, and we put $S=\{x= 6 holds + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A275815 +**Date:** 2026-10-29 + +## Result + +For n >= 6, take a set S of squares on the n x n board and put a queen on each square of S. All queens have the same colour, so a queen may move along any of its 8 directions only to an empty square, and only through empty squares. Let M(S) be the total number of moves available to all the queens. Then the maximum of M(S) over all S is exactly 8(n-2)^2. In the formal version, a n = (board n).powerset.sup (totalMoves n), and the claim is that a n = 8 * (n - 2)^2 for every n >= 6. + +## Assessment + +A short argument settles the general case, so no computer-found flow certificate is needed. Counting moves line by line gives an exact formula, which leaves only the empty border squares to be paid for. Each interior queen pays 2 along each line to an empty border square at most 2 squares away, and that covers every border square except a deficit of at most 1 at each corner, paid by a queen near the corner that kept its units. This is about a page of standard double counting and charging for n >= 10, and n = 6..9 are finite computations whose values are already in the entry's data. The only new part beyond math0's earlier A278212 result is n = 6, a finite check of a known value. A one-page charging proof of the queen bound for n >= 8 was found during this assessment and then verified by two independent checks (a hand re-derivation and an exhaustive and randomized computer search for counterexamples): see results/oeis-a275815/short-proof.md. It is not formalized in Lean. + +*Follows from:* The charging proof in results/oeis-a275815/short-proof.md (n >= 8), plus the finite cases n = 6, 7; Wu's border placement gives the lower bound. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. A second assessor, asked to show it is routine, found it routine. (2026-10-29) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A275815](https://oeis.org/A275815) as [`Math0.Statements.A275815.statement`](../../lean/Math0/Statements/OEIS/A275815.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A275815.lean`](../../lean/Math0/Frontier/OEIS/A275815.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: a(n) = 8(n-2)^2 for n >= 6. - _Alec Jones_, Nov 16 2016 + +Referees: The OEIS entry A275815 (#43, Jul 11 2021) still lists Jones's formula as a conjecture, with keyword "more". It records Wu's bounds 8(n-2)^2 <= a(n) <= 8n^2 (Nov 2016), a(6) from Branicky (Feb 2021) and a(7)-a(32) from Randell's MiniZinc runs (Jul 2021). + +Jim Randell, "Enigma 69: Maximum queen moves", https://enigmaticcode.wordpress.com/2013/03/10/enigma-69-maximum-queen-moves/, has only computation: a 6x6 exhaustive check (2017), a MiniZinc model run up to 64x64 (2020) and solver comparisons (2025). It gives no general proof. + +The cross-referenced entries A278211, A278212 and A278214 contain no proof. A278214's T(n, n^2-k) = 8k for k <= (n-2)^2 is only the easy per-empty-square bound. + +Web searches of arXiv, MathOverflow, Math StackExchange, Puzzling, SeqFan and the chess-puzzle literature found no general proof or counterexample. + +The one prior proof found is internal: math0's own results/oeis-a278212 (2026-10-24) already proves a(n) = 8(n-2)^2 for n >= 7 (Math0/Frontier/OEIS/A278212.lean). The present file adds the exact n=6 case (a(6) = 128, already known by computer) and states the full conjecture formally. + +Short proof (29 Oct 2026): the queen upper bound M <= 8(n-2)^2 also has a one-page charging proof for n >= 8, written up in results/oeis-a275815/short-proof.md and checked by two independent agents; it is not formalized in Lean. + +## Citation + +```bibtex +@misc{math0:oeis-a275815, + author = {{math0}}, + title = {{A275815: Jones's conjecture a(n) = 8(n-2)^2 for n >= 6 holds}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a275815}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a275815/short-proof.md b/results/oeis-a275815/short-proof.md new file mode 100644 index 0000000..c51afa9 --- /dev/null +++ b/results/oeis-a275815/short-proof.md @@ -0,0 +1,156 @@ +# A short proof of the queen-mobility bound for n ≥ 8 + +**Status: informal, not formalized in Lean.** The Lean proofs in math0 establish the same bound +by a different route: computer-found linear-programming dual (flow) certificates in +[`A278212.lean`](../../lean/Math0/Frontier/OEIS/A278212.lean) (n ≥ 7) and +[`A275815.lean`](../../lean/Math0/Frontier/OEIS/A275815.lean) (n = 6). The argument below was found +on 29 Oct 2026 by an assessor agent that was asked to judge how hard that result was. Two further +agents then checked it independently: + +- one re-derived every step by hand and wrote out the corner cases, which the first version left + terse; +- the other implemented the move count and the charging scheme and searched for counterexamples. + This covered all 2^25 queen patterns on a 5 × 5 corner block against several backgrounds, + exhaustive enumeration of the squares each bound depends on, and random and annealed boards for + n = 8 to 14. + +Neither found a gap or a counterexample. The argument shows that the A275815 bound needs no +computer certificate for n ≥ 8. For that reason the results for +[A275815](README.md) and [A278212](../oeis-a278212/README.md) are both rated *routine*. + +## Setting + +The board is {1, …, n} × {1, …, n}. Q is a set of squares, each holding a queen; all the queens +are the same colour. A queen moves along any of its 8 rays, to an empty square, passing only +through empty squares. M(Q) is the total number of moves available to all the queens. + +**Claim.** For n ≥ 8, M(Q) ≤ 8(n − 2)² for every Q. Equality holds when every border square holds +a queen. + +## 1. Counting along lines + +The *lines* are the n rows, the n columns, and the 2n − 1 diagonals in each direction. This +includes the length-1 diagonals, each of which consists of a single corner square. Every square +lies on exactly 4 lines. + +Fix a line with E empty squares. Let g₁ and g₂ be its *end gaps*: the number of empty squares +before the first queen, counted from each end. A line with no queen has g₁ = g₂ = its length. +Every empty square between two queens on the line can be reached by both of them, and every empty +square in an end gap by one queen only. So the moves along this line number 2E − g₁ − g₂. + +Summing over all lines, and using that each square lies on 4 lines, + + M(Q) = 8(n² − |Q|) − Σ (end gaps over all line ends). + +Every line end is a border square, and the gap at an end occupied by a queen is 0. There are +n² − (n − 2)² = 4(n − 1) border squares. For an empty border square b, let G(b) be the sum of the +gaps of the line ends at b, and let Q_int be the set of interior queens. Then the claim is +equivalent to + + Σ_{empty border b} (G(b) − 8) + 8·|Q_int| ≥ 0. (∗) + +A border square that is not a corner is an end of 3 lines: the line perpendicular to its edge and +its two diagonals. The line along its edge ends at the two corners. A corner is an end of 5 +line ends: its row, its column, the long diagonal, and both ends of its length-1 diagonal. + +## 2. Discharging + +Each interior queen starts with 8 units, 2 for each of its 4 lines. Consider one line through the +queen q, and an end b of that line that is empty. If q is the first queen seen from b, and q is +the 2nd or 3rd square counted from b (so the gap at b is 1 or 2), then q sends its 2 units on that +line to b. If both ends of the line qualify, which needs the line to have length at most 5, q sends +1 unit to each end instead. So no queen sends more than 8 units. + +Let val(b) be G(b) plus the units b receives. Then (∗) follows if every empty border square has +val(b) ≥ 8. The only exceptions are a deficit of exactly 1 at no more than one square in each +corner region, and each such deficit is covered by one unit that a distinct interior queen did not +send. + +## 3. The value of a line end + +The *value* of a line end at b is its gap plus the units b receives along that line. + +- **A line of length at least 6 whose 2nd and 3rd squares from b are interior.** + - Gap 1: a queen on the 2nd square sends 2. It cannot qualify for the far end, because the line + is too long. The value is 3. + - Gap 2: the value is 2 + 2 = 4. + - Gap at least 3: the value is at least 3. + + So the value is always at least 3. This covers every line perpendicular to an edge at a + non-corner border square. It also covers every diagonal of length at least 6 that starts at a + border square. +- **A diagonal of length 5:** at least 3. Its 2nd, 3rd and 4th squares are interior. The queen + splits its units only if it sits on the middle square, and then the gap is 2, so the value is + 2 + 1 = 3. +- **A diagonal of length 3 or 4:** at least 2. +- **The length-2 diagonal** through the two neighbours of a corner: 1 if the other square holds a + queen (gap 1, and a border queen sends nothing), and 2 if it is empty. +- **The length-1 diagonal at an empty corner:** it contributes 2, a gap of 1 at each of its two ends. +- **The row and the column along the edges through a corner:** they contain no interior queens, so + they contribute only their gaps. + +## 4. Border squares at least two squares from every corner + +Take b = (r, 1) with 3 ≤ r ≤ n − 2; the other edges are symmetric. Its perpendicular line gives at +least 3. Its two diagonals have lengths r and n + 1 − r, which add up to n + 1 ≥ 9. So one of them +has length at least 5 and gives at least 3, and the other has length at least 3 and gives at least +2. Hence val(b) ≥ 8. + +This is where n ≥ 8 is used. For n = 7, the square (4, 1) has two diagonals of length 4 and can +have value 3 + 2 + 2 = 7. + +## 5. Corner regions + +Take the corner C = (1, 1) and its neighbours A = (2, 1) and B = (1, 2); the other corners are +symmetric. A lies on row 1 and B lies on column 1. + +**C empty.** Then + + val(C) = (gap of row 1 at C) + (gap of column 1 at C) + d + 2, + +where d ≥ 3 is the value of the long diagonal at C. If A is empty, the row gap is at least 2, and +if B is empty, the column gap is at least 2. So val(C) ≥ 7, with equality only when A and B both +hold queens and d = 3. + +**A empty.** The line ends at A are: +- column 2, with value at least 3; +- the long diagonal through A, of length n − 1 ≥ 7, with value at least 3; +- the length-2 diagonal A–B, with value 1 or 2. + +So val(A) ≥ 7, with equality only when B holds a queen and the first two values are exactly 3. +The same holds for B, with the roles of A and B swapped. + +**At most one square per region falls short, and by exactly 1.** +- C empty, A and B queens: only C can fall short. +- C empty, B a queen, A empty: the row gap at C is at least 2, so val(C) ≥ 8. Only A can fall + short. The case with A and B swapped is symmetric. +- C, A and B all empty: val(C) ≥ 2 + 2 + 3 + 2 = 9 and val(A), val(B) ≥ 3 + 3 + 2 = 8. +- C a queen: A falls short only if B is a queen, and B only if A is a queen. So they cannot both + fall short. + +**Covering the shortfall.** +- **C is short.** Then d = 3, so one of two things holds: + - (2, 2) holds a queen. Row 2 runs from B to (n, 2). B holds a queen, and (n, 2) is n − 2 squares + away, so this queen sends nothing along row 2. Its 2 row units are unsent. + - (2, 2) and (3, 3) are empty and (4, 4) holds a queen. That queen is 3 squares from C and n − 4 + from (n, n), so it sends nothing along the main diagonal. Its 2 diagonal units are unsent. +- **A is short.** Column 2 has value 3, so one of two things holds: + - (2, 2) holds a queen. Its row-2 units are unsent, as above. + - (2, 2) and (2, 3) are empty and (2, 4) holds a queen. That queen is 3 squares from A and n − 4 + from (2, n), so its 2 column units are unsent. +- **B is short:** symmetric, using (2, 2) or (4, 2). + +The covering queens near (1, 1) lie among (2, 2), (4, 4), (2, 4) and (4, 2), and the covering queens +near the other corners lie in the mirror-image positions. For n ≥ 8 these four sets are disjoint. +Each region needs at most one unit, so each covering queen gives at most one unit, and only from +units it did not send. + +## 6. Conclusion + +Every empty border square has val ≥ 8. The only exception is at most one square per corner region +with val = 7, and each of those is covered by one unsent unit of its own interior queen. So (∗) +holds, and M(Q) ≤ 8(n − 2)² for every n ≥ 8. + +For n = 6 and n = 7 the charging scheme fails locally. The values a(6) = 128 and a(7) = 200 come +from the Lean proofs above. The checking agent also confirmed them, and a(8) = 288 and +a(9) = 392, with an exact integer program. diff --git a/results/oeis-a278212/README.md b/results/oeis-a278212/README.md new file mode 100644 index 0000000..13af7a6 --- /dev/null +++ b/results/oeis-a278212/README.md @@ -0,0 +1,52 @@ +# Kagey's conjecture for A278212: a(n) = floor(A275815(n)/2), via exact bishop and queen maxima from flow (LP-dual) certificates + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A278212 +**Date:** 2026-10-24 + +## Result + +For every n >= 1, let a(n) be the largest total number of moves that same-colored bishops can make on an n x n board, and queenMax(n) the same for queens. A piece can only move to an empty square, and every square it passes must be empty. Then a(n) = floor(queenMax(n)/2). More precisely, the proof shows the following. For bishops, a(4) = 20, a(5) = 38 and a(n) = 4(n-2)^2 for n >= 6. For queens, queenMax(4) is 40 or 41, queenMax(5) is 76 or 77, queenMax(6) is 128 or 129, and queenMax(n) = 8(n-2)^2 for n >= 7. That last formula also settles Alec Jones's conjecture on A275815 for n >= 7. The cases n <= 3 come from the listed values. + +## Assessment + +Earlier rated substantial, because the queen upper bound 8(n-2)^2 seemed to need the computer-found LP-dual certificates used in the Lean proof. That bound turns out to have a one-page elementary proof for n >= 8: count moves line by line, which leaves only the empty border squares to pay for, and let each interior queen pay 2 units along each of its lines to an empty border square at most 2 squares away. A one-page charging proof of the queen bound for n >= 8 was found while assessing A275815 and then verified by two independent checks (a hand re-derivation and an exhaustive and randomized computer search for counterexamples): see results/oeis-a275815/short-proof.md. It is not formalized in Lean. With it, the whole result is a short argument plus small finite cases, so it is now rated routine. The bishop half was always routine. + +*Follows from:* Howroyd's per-diagonal bound in the entry (with a short corner argument) for bishops; for queens, the one-page charging proof in results/oeis-a275815/short-proof.md (verified 29 Oct 2026, not formalized). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. *Revised:* First rated substantial, by the assessor and again by a second, adversarial assessor (26 Oct 2026), because the queen bound seemed to need computer-found certificates. Revised to routine on 29 Oct 2026, after a one-page proof of that bound was found and independently verified (results/oeis-a275815/short-proof.md). (2026-10-29) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A278212](https://oeis.org/A278212) as [`Math0.Statements.A278212.statement`](../../lean/Math0/Statements/OEIS/A278212.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A278212.lean`](../../lean/Math0/Frontier/OEIS/A278212.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: a(n) = floor(A275815(n)/2). - _Peter Kagey_, Nov 24 2016" (also A275815: "Conjecture: a(n) = 8(n-2)^2 for n >= 6. - _Alec Jones_, Nov 16 2016") + +Referees: I found no prior resolution, only computation and partial bounds: +- OEIS A278212 (#36, Nov 19 2023): Kagey's 2016 conjecture is still listed as open. It records Chai Wah Wu's bounds 4(n-2)² ≤ a(n) ≤ 4n² (Nov 2016), Andrew Howroyd's a(n) ≤ 4(n-2)²+4 (Oct 2023), and terms a(7)–a(50) computed by Christian Sievers with an ILP (PuLP), after M. S. Branicky's a(6). +- OEIS A275815 (#43, Jul 2021): Alec Jones's conjecture a(n)=8(n-2)² for n≥6 is still a conjecture, with keyword "more". It records Wu's bounds 8(n-2)² ≤ a(n) ≤ 8n² and terms a(7)–a(32) computed by Jim Randell with MiniZinc. +- Jim Randell, Enigma 69 "Maximum queen moves" (enigmaticcode.wordpress.com, 2013, comments through 2025): the 6×6 case is verified by computer and the border formula is called "presumed". There is no general proof. +- Related entries A278211, A278213 and A278214 contain no proof. +- Searches of arXiv, MathOverflow, Math StackExchange, Puzzling, SeqFan and Google Scholar-style queries found no general proof or counterexample. + +Short proof (29 Oct 2026): the queen upper bound M <= 8(n-2)^2 also has a one-page charging proof for n >= 8, written up in results/oeis-a275815/short-proof.md and checked by two independent agents; it is not formalized in Lean. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a278212, + author = {{math0}}, + title = {{Kagey's conjecture for A278212: a(n) = floor(A275815(n)/2), via exact bishop and queen maxima from flow (LP-dual) certificates}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a278212}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a278212/paper.pdf b/results/oeis-a278212/paper.pdf new file mode 100644 index 0000000..9fed5b5 Binary files /dev/null and b/results/oeis-a278212/paper.pdf differ diff --git a/results/oeis-a278212/paper.tex b/results/oeis-a278212/paper.tex new file mode 100644 index 0000000..ccd60c4 --- /dev/null +++ b/results/oeis-a278212/paper.tex @@ -0,0 +1,398 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{booktabs} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 + {¬}{{$\neg$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {∈}{{$\in$}}1 {∉}{{$\notin$}}1 + {∧}{{$\wedge$}}1 {∑}{{$\sum$}}1 {∨}{{$\vee$}}1 + {×}{{$\times$}}1 {ˢ}{{$^{\mathrm{s}}$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{ˢ}{\ensuremath{^{\mathrm{s}}}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +\setlength{\textfloatsep}{12pt plus 2pt minus 4pt} +\lstset{aboveskip=6pt,belowskip=6pt} +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\mob}{\operatorname{mob}} +\newcommand{\DB}{\mathcal{D}_{\mathrm B}} +\newcommand{\DQ}{\mathcal{D}_{\mathrm Q}} + +\title[Maximal mobility of bishops and queens]{Maximal mobility of same-colored bishops and queens: a proof of Kagey's conjecture $\mathrm{A278212}(n)=\lfloor\mathrm{A275815}(n)/2\rfloor$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + + +\begin{document} +\begin{abstract} +Let $a(n)$ (OEIS A278212) and $q(n)$ (OEIS A275815) be the maximum total number of moves that any number of bishops, respectively queens, of one color can make on an $n\times n$ board. +We prove Peter Kagey's 2016 conjecture $a(n)=\lfloor q(n)/2\rfloor$ for all $n\ge1$. +We also determine $a(n)=4(n-2)^2$ for $n\ge6$ and $q(n)=8(n-2)^2$ for $n\ge7$; the latter proves Alec Jones's 2016 conjecture on A275815 for $n\ge7$. The upper bounds come from flow certificates, which are dual solutions of a linear programming relaxation, together with short case splits on small boards. +To our knowledge this is a new result. It is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, and the Lean kernel checks every finite certificate. +\end{abstract} +\maketitle + +\section{Introduction} + +Place any number of pieces of one color on an $n\times n$ board. A piece cannot capture or jump over a piece of its own color. It may move along one of its lines to an empty square, provided every square it passes is empty. Peter Kagey defined the maximum total number of such moves for queens as A275815 \cite{A275815}, for rooks as A278211 \cite{A278211}, and for bishops as A278212 \cite{A278212}, all in November 2016. A275815 contains \texttt{Conjecture: a(n) = 8(n-2)\^{}2 for n >= 6. - \_Alec Jones\_, Nov 16 2016}, and A278212 contains Kagey's conjecture, quoted in Section~\ref{sec:statement}. + +\subsection*{Prior work} +Chai Wah Wu (November 2016) placed pieces on the $4n-4$ border squares to get $q(n)\ge8(n-2)^2$ and $a(n)\ge4(n-2)^2$. He also noted $q(n)\le8n^2$ and $a(n)\le4n^2$ \cite{A275815,A278212}. Andrew Howroyd (October 2023) proved $a(n)\le4(n-2)^2+4$ by bounding the moves on each diagonal \cite{A278212}. Michael S. Branicky computed $a(6)=64$ and $q(6)=128$ (2021) \cite{A275815,A278212}. Jim Randell computed $q(7),\dots,q(32)$ with MiniZinc \cite{A275815,Randell}, and Christian Sievers computed $a(7),\dots,a(50)$ with an integer linear program \cite{A278212,A278214}. All these values agree with both conjectures. Randell's page \cite{Randell} is about Enigma~69 from \emph{New Scientist} (1980). That puzzle asserts without proof that the border placement is optimal for queens on the $8\times8$ board, and asks for the $4\times4$ board. Randell states the general border formula only conditionally; in its comments he verifies by computer that $q(6)=128$ (2017) and reports MiniZinc checks of boards up to $64\times64$ (2020, 2025). These are finite computations, not a general proof. We found no general proof or counterexample in the related entries A278211, A278213 and A278214, or in searches of arXiv, MathOverflow, Mathematics Stack Exchange, Puzzling Stack Exchange and the SeqFan list. Both conjectures are still marked as conjectures in the current revisions of the entries (A278212 \#36, 2023; A275815 \#43, 2021). + +\subsection*{Results} +\begin{theorem}\label{thm:main} +For every $n\ge1$, $a(n)=\lfloor q(n)/2\rfloor$. +\end{theorem} + +\begin{theorem}\label{thm:values} +\textup{(1)} $a(1),\dots,a(5)=0,2,8,20,38$, and $a(n)=4(n-2)^2$ for $n\ge6$. +\textup{(2)} $q(1),q(2),q(3)=0,4,17$; $40\le q(4)\le41$, $76\le q(5)\le77$, $128\le q(6)\le129$; and $q(n)=8(n-2)^2$ for $n\ge7$. +\end{theorem} + +Part~(2) proves Jones's conjecture for $n\ge7$. With the computed value $q(6)=128$ (Randell \cite{Randell}, Branicky \cite{A275815}) the conjecture holds for all $n\ge6$, but our proof alone gives only $128\le q(6)\le129$. Likewise the known values $q(4)=40$, $q(5)=76$ are not reproved; the floor absorbs the remaining unit. + +The upper bounds use flows along each direction whose terms telescope (Proposition~\ref{prop:key}), i.e.\ weak duality for a linear programming (LP) relaxation; an LP solver found the flows and the Lean kernel checks them. + +\section{Statement}\label{sec:statement} + +Let $\Omega_n=\{0,\dots,n-1\}^2\subset\Z^2$. A \emph{placement} is a subset $S\subseteq\Omega_n$, and a square $c$ is \emph{empty} if $c\in\Omega_n\setminus S$. Let $\DB=\{(\pm1,\pm1)\}$ and $\DQ=\DB\cup\{(\pm1,0),(0,\pm1)\}$. For $p\in S$ and a direction $d$, let $r_S(p,d)$ be the number of $k\ge1$ such that $p+d,\dots,p+kd$ are all empty. Let $\mob_{\mathcal D}(S)=\sum_{p\in S}\sum_{d\in\mathcal D}r_S(p,d)$. Then $a(n)=\max_{S}\mob_{\DB}(S)$ and $q(n)=\max_S\mob_{\DQ}(S)$, where $S$ runs over all subsets of $\Omega_n$. + +A278212 \cite{A278212} (``Maximum total number of possible moves that any number of bishops of the same color can make on an n X n chessboard'') and A275815 \cite{A275815} (the same for queens) both have offset~$1$. The author line of A278212 reads \texttt{\_Peter Kagey\_, Nov 15 2016}, and its COMMENTS section contains, verbatim, +\begin{quote}\raggedright +\texttt{Conjecture: a(n) = floor(A275815(n)/2). - \_Peter Kagey\_, Nov 24 2016} +\end{quote} +which is Theorem~\ref{thm:main}. + +\subsection*{Lean formalization} +math0 formalized the statement in \path{lean/Math0/Statements/OEIS/A278212.lean}. The file was reviewed for fidelity and frozen (SHA-256 \texttt{590fb1aa\ldots 07b9}) before any proof attempt. Verbatim, with the header, import, docstrings, blank lines, witnesses and theorems omitted: +\begin{lstlisting} +namespace Math0.Statements.A278212 +def board (n : ℕ) : Finset (ℕ × ℕ) := Finset.range n ×ˢ Finset.range n +def isEmptySquare (n : ℕ) (S : Finset (ℕ × ℕ)) (x y : ℤ) : Bool := + decide (0 ≤ x ∧ x < n ∧ 0 ≤ y ∧ y < n ∧ (x.toNat, y.toNat) ∉ S) +def rayMoves (n : ℕ) (S : Finset (ℕ × ℕ)) (p : ℕ × ℕ) (d : ℤ × ℤ) : ℕ := + ((List.range' 1 n).takeWhile fun t => + isEmptySquare n S (p.1 + t * d.1) (p.2 + t * d.2)).length +def bishopDirs : List (ℤ × ℤ) := [(1, 1), (1, -1), (-1, 1), (-1, -1)] +def queenDirs : List (ℤ × ℤ) := + [(1, 1), (1, -1), (-1, 1), (-1, -1), (1, 0), (-1, 0), (0, 1), (0, -1)] +def totalMoves (dirs : List (ℤ × ℤ)) (n : ℕ) (S : Finset (ℕ × ℕ)) : ℕ := + ∑ p ∈ S, (dirs.map (rayMoves n S p)).sum +def a (n : ℕ) : ℕ := (board n).powerset.sup (totalMoves bishopDirs n) +def queenMax (n : ℕ) : ℕ := (board n).powerset.sup (totalMoves queenDirs n) +def border (n : ℕ) : Finset (ℕ × ℕ) := + (board n).filter fun p => p.1 = 0 ∨ p.1 = n - 1 ∨ p.2 = 0 ∨ p.2 = n - 1 +def statement : Prop := ∀ n : ℕ, 1 ≤ n → a n = queenMax n / 2 +end Math0.Statements.A278212 +\end{lstlisting} +Here \texttt{board n} is $\Omega_n$. \texttt{rayMoves n S p d} is the length of the longest initial run of $t=1,\dots,n$ for which $p+td\in\Z^2$ is an empty square. This equals $r_S(p,d)$, because $p+td\notin\Omega_n$ for $t\ge n$. \texttt{totalMoves} is $\mob_{\mathcal D}$; \texttt{a} and \texttt{queenMax} are suprema in $\N$ over all placements, i.e.\ maxima; \texttt{/} is floor division; and $n\ge1$ is the common offset. ``Same color'' refers to the pieces, not to square colors: the entry's $5\times5$ example has bishops on A1 and B1, which have different colors. + +The statement file checks the definitions against the OEIS data by \texttt{decide +kernel}. The theorems \decl{a_data} and \decl{queenMax_data} evaluate the exhaustive definitions to $a(1),a(2),a(3)=0,2,8$ and $q(1),q(2),q(3)=0,4,17$. The theorems \decl{a_ge_data} and \decl{queenMax_ge_data} show that the listed terms for $4\le n\le10$ are lower bounds, using explicit placements \decl{bishopWitness} and \decl{queenWitness} whose mobility the kernel computes. For $n\ge6$ these are the border, and for bishops with $n=5$ the entry's example. + +\section{Proof}\label{sec:proof} + +We follow \path{lean/Math0/Frontier/OEIS/A278212.lean}, with the names of its lemmas in brackets. Fix $n$, a placement $S$, and a set $\mathcal D\subseteq\{-1,0,1\}^2\setminus\{0\}$. For $c\in\Z^2$, let $x(c)=1$ if $c\in S$ and $x(c)=0$ otherwise. + +\subsection{Moves counted at their targets} +For $d\in\mathcal D$ and $c\in\Z^2$, let $Y_d(c)=1$ if there is a $k\ge0$ such that $c-(k+1)d\in S$ and $c,c-d,\dots,c-kd$ are empty, and let $Y_d(c)=0$ otherwise. Such a $k$ is unique: if $k0$ together with functions $G_d\colon\Z^2\to\Z_{\ge0}$, one for each $d\in\mathcal D$, such that +(F1) $G_d(c)=0$ unless $c,c-d\in\Omega_n$, and +(F2) $G_d(c)\le D+G_d(c+d)$ whenever $c,c-d\in\Omega_n$. +Let $\alpha_d(c)=D+G_d(c+d)-G_d(c)\ge0$ if $c-d\in\Omega_n$, and $\alpha_d(c)=0$ otherwise. The \emph{empty weight} of $c$ is $A(c)=\sum_{d}\alpha_d(c)$, and its \emph{occupied weight} is $B(c)=\sum_dG_d(c+d)$. +\end{definition} + +\begin{lemma}[\decl{dir_ineq}]\label{lem:dir} +For each $d\in\mathcal D$, +$D\sum_{p\in S}r_S(p,d)\le\sum_{c\in\Omega_n}\bigl(\alpha_d(c)(1-x(c))+G_d(c+d)\,x(c)\bigr)$. +\end{lemma} + +\begin{proof} +Write $G=G_d$, $Y=Y_d$ and $\alpha=\alpha_d$. For every $c\in\Omega_n$, +\begin{equation}\label{eq:cell} +D\,Y(c)+G(c+d)\,Y(c)\le\alpha(c)(1-x(c))+G(c)\,x(c-d)+G(c)\,Y(c-d). +\end{equation} +Indeed, the right-hand side is nonnegative, which settles the case $Y(c)=0$. If $c-d\notin\Omega_n$, then $Y(c)=0$ by Lemma~\ref{lem:Y}(c). If $c-d\in\Omega_n$ and $Y(c)=1$, then $x(c)=0$ and $x(c-d)+Y(c-d)\ge1$ by Lemma~\ref{lem:Y}, so the right-hand side is at least $\alpha(c)+G(c)=D+G(c+d)$. + +By (F1), the substitution $c\mapsto c+d$ gives $\sum_{c\in\Omega_n}G(c+d)g(c)=\sum_{c\in\Omega_n}G(c)g(c-d)$ for every function $g$ (\decl{shift_sum}). Sum \eqref{eq:cell} over $\Omega_n$. With $g=Y$, the terms $G(c+d)Y(c)$ and $G(c)Y(c-d)$ cancel. With $g=x$, $\sum G(c)x(c-d)$ becomes $\sum G(c+d)x(c)$. Lemma~\ref{lem:target} finishes the proof. +\end{proof} + +\begin{proposition}[\decl{key}]\label{prop:key} +For every flow certificate, summing Lemma~\ref{lem:dir} over $d\in\mathcal D$ gives +$D\cdot\mob_{\mathcal D}(S)\le\sum_{c\in S}B(c)+\sum_{c\in\Omega_n\setminus S}A(c)\le\sum_{c\in\Omega_n}\max(A(c),B(c))$. +\end{proposition} + +\begin{corollary}[\decl{leaf}]\label{cor:leaf} +Let $I,O\subseteq\Omega_n$ and $T\in\N$. Set $\beta(c)=B(c)$ for $c\in I$, $\beta(c)=A(c)$ for $c\in O\setminus I$, and $\beta(c)=\max(A(c),B(c))$ otherwise. If $\sum_{c\in\Omega_n}\beta(c)= 8}} +For $0\le x\le n-1$ define the position class $\kappa_3(x)=x$ if $x<3$, $\kappa_3(x)=6-(n-1-x)$ if $n-1-x<3\le x$, and $\kappa_3(x)=3$ otherwise. Define $\kappa_4$ in the same way with $3,6$ replaced by $4,8$. So the class records the distance to the nearer side, up to a cut-off. For $n\ge8$, $\kappa_4$ takes each value in $E=\{0,1,2,3,5,6,7,8\}$ exactly once and the value $4$ exactly $n-8$ times. A \emph{class table} $L\colon\{0,\dots,6\}^2\times\mathcal D\to\N$ defines the flow $G_d(c)=L(\kappa_3(c_1),\kappa_3(c_2),d)$ if $c,c-d\in\Omega_n$, and $G_d(c)=0$ otherwise (\decl{Gc}). The Lean file contains a table \decl{LQ} for queens with $D=2$ (124 nonzero entries) and a table \decl{LB} for bishops with $D=1$ (52 nonzero entries), both found by linear programming. + +\begin{lemma}[\decl{cls3_shift}, \decl{ok4_iff}, \decl{Af_ty}, \decl{Bf_ty}]\label{lem:classes} +Let $n\ge8$, $0\le x\le n-1$ and $\delta\in\{-1,0,1\}$. Then $\kappa_4(x)$ and $\delta$ determine whether $0\le x+\delta\le n-1$, and if so they determine $\kappa_3(x+\delta)$. Hence, for a class table, $A(c)=A^*(\kappa_4(c_1),\kappa_4(c_2))$ and $B(c)=B^*(\kappa_4(c_1),\kappa_4(c_2))$ for functions $A^*,B^*$ on $\{0,\dots,8\}^2$ computed from $L$ and $D$. Also, (F2) follows from a check over all $9\times9$ class pairs and all $d$ \textup{(\decl{checkTy})}. +\end{lemma} +\begin{proof} +Let $v=\kappa_4(x)$. If $v\le3$, then $x=v$, so $x+\delta\le4 n. Let N(n,j) = C(n-1,j-1)·C(n,j-1)/j be the Narayana numbers, s = A001003 the little Schröder numbers, with s(0) = 1 and s(n) = Σ_{j=1..n} 2^{j-1} N(n,j) for n ≥ 1, and b = A103365 the first column of the inverse of the lower-unitriangular Narayana matrix, so that Σ_{j=1..n} N(n,j) b(j) = [n = 1]. Then: +(1) for every n ≥ 0, Σ_{k=0..⌊n/2⌋} T(n-k,k) = s(n+1); +(2) (corrected reading) for every n ≥ 0, Σ_{k=0..n} T(n,k)(2k+1)Cat(k)·b(k+1) = 0^n; +(3) for every N, the inverse over ℚ of the N×N leading block of T is the N×N leading block of U(n,k) = T(n,k)·b(n+1-k). + +## Assessment + +The inverse in (3) is immediate once you see that T and the Narayana triangle are both diagonal conjugates of the same Toeplitz matrix built from c(j) = 1/(j!(j+1)!). Inverting that Toeplitz matrix is exactly the reciprocal power series that Hanna's g.f. in A103365 already records. Conjecture (2), read as its evidently intended column-0 case, is just the first column of T*T^{-1} = I. Conjecture (1) takes about a page, either with Vandermonde's identity and Cloitre's Narayana formula for A001003 or with the Motzkin bivariate g.f. that Barry's A097610 comment points to. The paper itself calls the result routine, and none of these steps needs a new idea. + +*Follows from:* The scaling T(n,k) = (2n+1)!/(2k+1)! * c(n-k) with c(j) = 1/(j!(j+1)!), together with P. D. Hanna's g.f. in A103365 (A(x) = 1/B(x), B(x) = Sum x^n/[n!(n+1)!/2^n]), gives (3) at once; T. Copeland's inverse-pair comment in A238390 (Jan 30 2016) gives the same. (2) is the first column of (3). (1) follows from P. Barry's comment in A097610 (diagonal sums of the Motzkin triangle are the aerated large Schroeder numbers) plus a short g.f. parity argument, or from a Vandermonde/Narayana binomial identity. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A281000](https://oeis.org/A281000) as [`Math0.Statements.A281000.statement`](../../lean/Math0/Statements/OEIS/A281000.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A281000.lean`](../../lean/Math0/Frontier/OEIS/A281000.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A281000 Conjectures: (1) Antidiagonal sums equal A001003(n+1); (2) Sum_{k=0..n} (-1)^k*T(n,k)*(2*k+1)*A000108(k)*A103365(k) = A000007(n); (3) Matrix inverse equals T(n,k)*A103365(n+1-k). (Werner Schulte, Jan 12 2017) + +Referees: No prior resolution found. Sources checked: +- Local OEIS mirror: A281000 (#17, Nov 25 2018), A280580, A103365, A103364, A238390, A097610, A001003, A006318, A126120, A180874. No entry other than A281000 itself mentions A281000. +- arXiv 2607.24832 and 2410.07237 (Sela Fried, proofs of OEIS conjectures); no mention. +- arXiv 2608.11941 (Adamczewski, "OEIS Open") and the epoch-research/LeanOpenProblems-results repo; A281000 is not among its conjectures. +- Web searches on arXiv, MathOverflow, the OEIS wiki and SeqFan; no hits. + +Closest prior material, which makes the result routine without explicitly resolving it: +- T. Copeland, comment in A238390 (Jan 30 2016): the inverse pair C(n,k)·A126120(n−k) ↔ C(n,k)·m(n−k), with m(2j) = (−1)^j·A238390(j). Its odd–odd block gives conjecture (3). +- V. Kotesovec, Mathematica in A103365 (2014), and P. D. Hanna's g.f. (2009): link A103365 to x/BesselJ(1,2x), so (−1)^j·A238390(j) = Cat(j)·A103365(j+1). +- P. Bala, A103364 (2013): generalized Riordan array (1/E(y), y). +- P. Barry, A097610 (Apr 2010): diagonal sums of the Motzkin triangle are the aerated large Schröder numbers. Restricting to an odd number of level steps gives half of that, which is conjecture (1). + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a281000, + author = {{math0}}, + title = {{Schulte's conjectures on A281000, T(n,k) = C(2n+1,2k+1)·Cat(n-k): antidiagonal sums and matrix inverse}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a281000}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a281000/paper.pdf b/results/oeis-a281000/paper.pdf new file mode 100644 index 0000000..85e8b09 Binary files /dev/null and b/results/oeis-a281000/paper.pdf differ diff --git a/results/oeis-a281000/paper.tex b/results/oeis-a281000/paper.tex new file mode 100644 index 0000000..b0a284f --- /dev/null +++ b/results/oeis-a281000/paper.tex @@ -0,0 +1,354 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 + {→}{{$\to$}}1 {≤}{{$\le$}}1 {∈}{{$\in$}}1 {∧}{{$\wedge$}}1 {∑}{{$\sum$}}1 {·}{{$\cdot$}}1 + {⁻¹}{{$^{-1}$}}2 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +\allowdisplaybreaks +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\def\UrlFont{\normalfont\ttfamily}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\ib}[1]{[\,#1\,]} +\newcommand{\lb}{\char123} +\newcommand{\rb}{\char125} + +\title[Schulte's conjectures on OEIS A281000]{Antidiagonal sums and the matrix inverse of the triangle $\binom{2n+1}{2k+1}C_{n-k}$: proof of Schulte's conjectures on OEIS A281000} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 25, 2026} + + +\begin{document} +\begin{abstract} +Let $T(n,k)=\binom{2n+1}{2k+1}C_{n-k}$ for $0\le k\le n$, where $C_m$ are the Catalan numbers (OEIS A281000). +We prove the conjectures that Werner Schulte recorded in this entry in 2017: the antidiagonal sums of $T$ are the little Schr\"oder numbers $s(n+1)$; the inverse of the lower unitriangular matrix $T$ is $\bigl(T(n,k)\,b(n+1-k)\bigr)$, where $b$ (A103365) is the first column of the inverse Narayana matrix; and, in a corrected reading of a conjecture that as printed refers to the undefined term A103365$(0)$, $\sum_kT(n,k)(2k+1)C_k\,b(k+1)=0^n$. +The proofs are finite binomial-coefficient identities, and the math0 referees found no earlier proof, so we classify the result as new; it is routine, however, and can also be derived from generating-function facts recorded in related OEIS entries. +The proof is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry. +\end{abstract} +\maketitle + +\section{Introduction} + +Let $C_m=\binom{2m}{m}/(m+1)$ be the Catalan numbers (A000108 \cite{A000108}). The triangle +\[ + T(n,k)=\binom{2n+1}{2k+1}\binom{2n-2k}{n-k}\Big/(n+1-k)=\binom{2n+1}{2k+1}C_{n-k}\qquad(0\le k\le n), +\] +with rows $1;\ 3,1;\ 10,10,1;\ 35,70,21,1;\dots$, is the entry A281000 of the OEIS \cite{A281000}, submitted by Werner Schulte on January 12, 2017. We put $T(n,k)=0$ for $k>n$, so $T$ is an infinite lower triangular matrix with unit diagonal. As the entry notes, $T(n,k)=M(2n+1,2k+1)$, where $M(n,k)=\binom nk C_{(n-k)/2}$ ($0$ if $n-k$ is odd) counts Motzkin paths of length $n$ with $k$ level steps (A097610 \cite{A097610}). Schulte recorded three conjectures in the entry, on the antidiagonal sums of $T$, a weighted row sum, and the inverse matrix (Section~\ref{sec:statement}); in revision \#17 (November 25, 2018), the version in our local mirror of the OEIS, they are still labelled ``Conjectures''. We prove all three (Theorem~\ref{thm:main}), the second in the corrected reading of Remark~\ref{rem:reading}. + +\subsection*{Prior work and status} +\begin{itemize} +\item The math0 literature referees checked A281000 and the related entries A280580, A103365, A103364, A238390, A097610, A001003, A006318, A126120 and A180874 (no entry other than A281000 mentions A281000), and searched arXiv (including recent papers devoted to proofs of OEIS conjectures), MathOverflow, the OEIS wiki and the SeqFan list. They found no proof of any of the conjectures. +\item \emph{(3) and (2) from known formulas.} Tom Copeland states in A238390 \cite{A238390} (January 30, 2016) that the matrices $\binom nk A126120(n-k)$ (A126120 \cite{A126120} is the aerated Catalan sequence) and $\binom nk m(n-k)$, with $m(2j)=(-1)^jA238390(j)$ and $m(2j+1)=0$, are mutually inverse. The first is $M$; both vanish unless $n-k$ is even, so $T^{-1}$ is the odd--odd block of the second, $T^{-1}(n,k)=\binom{2n+1}{2k+1}(-1)^{n-k}A238390(n-k)$. Comparing the e.g.f.\ $x/J_1(2x)$ of A238390 with P.~D.~Hanna's g.f.\ in A103365 \cite{A103365} (2009) gives $(-1)^jA238390(j)=C_j\,b(j+1)$, whence (3), and (2) is its first column. This derivation was pointed out by the referees; we did not find it in print. +\item \emph{(1) from known formulas.} Paul Barry notes in A097610 (April 21, 2010) that the diagonal sums $\sum_kM(m-k,k)$ are the aerated large Schr\"oder numbers $r$ (A006318 \cite{A006318}). For $m=2n+2$ the terms with $k$ odd form the $n$-th antidiagonal sum of $T$; since $\sum_k(-1)^kM(m-k,k)=0$ for $m\ge1$ (a generating-function computation not in the entry) and $r(n)=2s(n)$ for $n\ge1$, this gives (1). +\end{itemize} +We therefore classify the result as new, with the caveat that it is a routine consequence of known generating-function facts. Our proof uses no generating functions: it consists of finite binomial identities, chosen because they are easy to formalize. Remark~\ref{rem:toeplitz} explains the structure behind the proof of (3); it is close to Peter Bala's description (2013) of the inverse Narayana matrix A103364 \cite{A103364} as a generalized Riordan array. + +\section{Statement}\label{sec:statement} + +The FORMULA section of A281000 \cite{A281000} (offset $0$, $0\le k\le n$; entry by Werner Schulte, January 12, 2017) contains, verbatim, +\begin{quote}\raggedright\footnotesize +\texttt{Conjectures:}\\ +\texttt{\ \ (1) Antidiagonal sums equal A001003(n+1);}\\ +\texttt{\ \ (2) Sum\_\lb k=0..n\rb\ (-1)\^{}k*T(n,k)*(2*k+1)*A000108(k)*A103365(k) = A000007(n);}\\ +\texttt{\ \ (3) Matrix inverse equals T(n,k)*A103365(n+1-k).} +\end{quote} +Here A000007$(n)=0^n$. Let $N(n,j)=\binom{n-1}{j-1}\binom n{j-1}/j$ ($1\le j\le n$) be the Narayana numbers (A001263 \cite{A001263}); the matrix $(N(n,j))_{n,j\ge1}$ is lower unitriangular. Let $s(n)$ be the little Schr\"oder numbers $1,1,3,11,45,\dots$ (A001003 \cite{A001003}); we use B.~Cloitre's formula from that entry (2003, reindexed), $s(n)=\sum_{j=1}^{n}2^{j-1}N(n,j)$ for $n\ge1$, as the definition. Let $b(m)$, $m\ge1$, be A103365 \cite{A103365}, ``the first column of triangle A103364, which equals the matrix inverse of the Narayana triangle (A001263)'', i.e.\ the solution of $\sum_{j=1}^{n}N(n,j)\,b(j)=\ib{n=1}$ $(n\ge1)$: $1,-1,2,-7,39,-321,\dots$ + +\begin{theorem}\label{thm:main} +\begin{enumerate} +\item[(1)] For every $n\ge0$, $\displaystyle\sum_{k=0}^{\lfloor n/2\rfloor}T(n-k,k)=s(n+1)$; +\item[(2)] for every $n\ge0$, $\displaystyle\sum_{k=0}^{n}T(n,k)\,(2k+1)\,C_k\,b(k+1)=0^n$; +\item[(3)] for every $N\ge0$, the matrix $(T(i,j))_{0\le i,ji$. +\end{enumerate} +\end{theorem} +As $T$ and $U$ are lower triangular, (3) is equivalent to $T^{-1}=U$ for the infinite matrices. + +\begin{remark}[The reading of (2)]\label{rem:reading} +As printed, (2) is not well defined: at $k=0$ it uses A103365$(0)$, but A103365 has offset $1$. With the index shift A103365$(k)\mapsto b(k+1)$ alone it is false at $n=1$, where the sum is $3+3=6$, because $(-1)^k$ cancels the alternating signs of $b$; giving A103365$(0)$ the value $0$ or $1$ fails as well. We read $(-1)^k$A103365$(k)$ as $b(k+1)$, i.e.\ A103365 as the unsigned sequence indexed from $0$ (for the listed terms, $b(k+1)$ has sign $(-1)^k$). This is the convention of Hanna's g.f.\ in A103365, where $(-1)^na(n)$ stands for $b(n+1)$, and of Schulte's analogous conjecture $\sum_k(-1)^k\binom{2n}{2k}C_{n-k}A238390(k)=0^n$ in A280580 \cite{A280580} (January 5, 2017), with A238390 unsigned of offset $0$. So read, (2) is the column $k=0$ of $T\cdot U=I$, since $T(k,0)=(2k+1)C_k$; it does not change the strength of the statement, which is equivalent to (1) and (3). +\end{remark} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A281000.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{4230cf53\ldots c030}) before any proof attempt. Its definitions and the statement read (verbatim; we omit the import, comments, docstrings, all theorems, and the definition \decl{a} of the triangle read by rows, used only in the data check): +\begin{lstlisting} +namespace Math0.Statements.A281000 +def T (n k : ℕ) : ℕ := + Nat.choose (2 * n + 1) (2 * k + 1) * Nat.choose (2 * n - 2 * k) (n - k) / (n + 1 - k) +def narayana (n k : ℕ) : ℕ := + Nat.choose (n - 1) (k - 1) * Nat.choose n (k - 1) / k +def A001003 (n : ℕ) : ℕ := + if n = 0 then 1 else ∑ j ∈ Finset.Icc 1 n, 2 ^ (j - 1) * narayana n j +def invNarayanaCol : ℕ → List ℤ + | 0 => [] + | m + 1 => + let l := invNarayanaCol m + l ++ [(if m = 0 then 1 else 0) - + ((List.range m).map fun j => (narayana (m + 1) (j + 1) : ℤ) * l.getD j 0).sum] +def A103365 (n : ℕ) : ℤ := + (invNarayanaCol n).getD (n - 1) 0 +def conj1 : Prop := + ∀ n : ℕ, ∑ k ∈ Finset.range (n / 2 + 1), T (n - k) k = A001003 (n + 1) +def conj2 : Prop := + ∀ n : ℕ, ∑ k ∈ Finset.range (n + 1), + (T n k : ℤ) * (2 * k + 1) * (catalan k : ℤ) * A103365 (k + 1) = (0 : ℤ) ^ n +def conj3 : Prop := + ∀ N : ℕ, (Matrix.of fun i j : Fin N => (T i j : ℚ))⁻¹ = + Matrix.of fun i j : Fin N => (T i j : ℚ) * (A103365 ((i : ℕ) + 1 - (j : ℕ)) : ℚ) +def statement : Prop := + conj1 ∧ conj2 ∧ conj3 +end Math0.Statements.A281000 +\end{lstlisting} +\emph{Encoding.} \texttt{T} is the formula in the name of the entry, computed in $\N$ with truncated subtraction and floor division; it equals $\binom{2n+1}{2k+1}C_{n-k}$ for $k\le n$ and $0$ for $k>n$ (Lemma~\ref{lem:closed}). Likewise \texttt{narayana} is $N$, with exact division. \texttt{A001003} is Cloitre's formula. \texttt{invNarayanaCol m} is the list $[b(1),\dots,b(m)]$ computed by forward substitution, $b(m+1)=\ib{m=0}-\sum_{ji$. Mathlib's \texttt{catalan} is A000108, and \texttt{⁻¹} is Mathlib's matrix inverse (which would be $0$ for a singular matrix; here $\det=1$). + +\emph{Data checks.} By \texttt{decide +kernel}, the statement file checks that the triangle read by rows reproduces all $55$ listed terms of A281000 (\decl{a_data}), that \texttt{A001003} reproduces all $26$ listed terms $s(0),\dots,s(25)$ (\decl{A001003_data}), and that \texttt{A103365} reproduces all $20$ listed terms $b(1),\dots,b(20)$ (\decl{A103365_data}). It also checks \texttt{conj1} for $n\le24$, \texttt{conj2} for $n\le15$, and the entries of $T\cdot U$ for indices $\le14$; these are transcription checks only. + +\section{Proof}\label{sec:proof} + +The proof follows \path{lean/Math0/Frontier/OEIS/A281000.lean}; Lean names are given in parentheses. We write $\ib P$ for $1$ if $P$ holds and $0$ otherwise, and $\binom ab=0$ for $b>a$. + +\subsection{Closed forms} + +\begin{lemma}\label{lem:closed} +For all $n,k,p,M,i,j\ge0$: +\begin{enumerate} +\item[(a)] $T(n,k)=0$ if $nn$, in $\Q$, with $l+1-k$ truncated at $0$ and $b(0)=0$ (as in Lean), +\[ + \sum_{l=0}^{L-1}T(n,l)\,T(l,k)\,b(l+1-k)=\ib{n=k}. +\] +\end{lemma} + +\begin{proof} +If $k>n$, every term vanishes by Lemma~\ref{lem:closed}(a): $T(l,k)=0$ for $l\le n$ and $T(n,l)=0$ for $l>n$. Let $n=k+p$. The terms with $l>n$ or $ln/2\ge i/2$, +\[ + \sum_{k=0}^{\lfloor n/2\rfloor}T(n-k,k)=\sum_{i=0}^{n}N(n+1,i+1)\sum_{k=0}^{\lfloor n/2\rfloor}\binom{i+1}{2k+1}=\sum_{i=0}^{n}2^i\,N(n+1,i+1)=s(n+1).\qedhere +\] +\end{proof} + +\section{Machine verification}\label{sec:lean} + +The proof is the file \path{lean/Math0/Frontier/OEIS/A281000.lean} in the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A281000.result}, of type \decl{statement}, the conjunction of \decl{conj1_proof}, \decl{conj2_proof} and \decl{conj3_proof}; all auxiliary declarations are \texttt{private}, and the main ones are named in Section~\ref{sec:proof}. Neither file uses \texttt{sorry}, \texttt{native\_decide}, custom axioms or \texttt{set\_option}; the proof file uses no \texttt{decide}, and the kernel evaluations of the statement file's data checks are not used by the proof. The file ends with +\begin{lstlisting} +#math0_settles Math0.Frontier.A281000.result Math0.Statements.A281000.statement +\end{lstlisting} +This command (in \path{lean/Math0/Audit.lean}, for statements that math0 formalizes itself) fails unless \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; \decl{statement} and \decl{result} depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (rejecting \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and the type of \decl{result} is syntactically \decl{statement} or $\neg$\,\decl{statement}, up to metadata, with no unfolding. It reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A281000.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A281000.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A281000.result' proves 'Math0.Statements.A281000.statement' +\end{lstlisting} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use, as its statement was formalized by math0 from the OEIS entry. To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib cache, builds all math0 results with \texttt{lake build} (re-running every audit command) and checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified. The single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A281000.lean} in \path{lean/}; on our machine this took about 20 seconds, including loading Mathlib. + +{\footnotesize +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A000108} +The OEIS Foundation Inc., \emph{Catalan numbers: $C(n)=\binom{2n}{n}/(n+1)=(2n)!/(n!(n+1)!)$}, entry A000108 (N.~J.~A. Sloane) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A000108}. + +\bibitem{A001003} +The OEIS Foundation Inc., \emph{Schroeder's second problem (generalized parentheses); also called super-Catalan numbers or little Schroeder numbers}, entry A001003 (N.~J.~A. Sloane) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A001003}. + +\bibitem{A001263} +The OEIS Foundation Inc., \emph{Triangle of Narayana numbers $T(n,k)=C(n-1,k-1)C(n,k-1)/k$ with $1\le k\le n$, read by rows}, entry A001263 (N.~J.~A. Sloane) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A001263}. + +\bibitem{A006318} +The OEIS Foundation Inc., \emph{Large Schr\"oder numbers}, entry A006318 (N.~J.~A. Sloane) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A006318}. + +\bibitem{A097610} +The OEIS Foundation Inc., \emph{Triangle read by rows: $T(n,k)$ is number of Motzkin paths of length $n$ and having $k$ horizontal steps}, entry A097610 (E.~Deutsch, 2004) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A097610}. + +\bibitem{A103364} +The OEIS Foundation Inc., \emph{Matrix inverse of the Narayana triangle A001263}, entry A103364 (P.~D. Hanna, 2005) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A103364}. + +\bibitem{A103365} +The OEIS Foundation Inc., \emph{First column of triangle A103364, which equals the matrix inverse of the Narayana triangle (A001263)}, entry A103365 (P.~D. Hanna, 2005) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A103365}. + +\bibitem{A126120} +The OEIS Foundation Inc., \emph{Catalan numbers (A000108) interpolated with 0's}, entry A126120 (Ph.~Del\'eham, 2007) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A126120}. + +\bibitem{A238390} +The OEIS Foundation Inc., \emph{E.g.f.: $x/\mathrm{BesselJ}(1,2x)$ (even powers only)}, entry A238390 (V.~Kotesovec, 2014) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A238390}. + +\bibitem{A280580} +The OEIS Foundation Inc., \emph{Triangle read by rows: $T(n,k)=\binom{2n}{2k}\binom{2n-2k}{n-k}/(n+1-k)$ for $0\le k\le n$}, entry A280580 (W.~Schulte, 2017) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A280580}. + +\bibitem{A281000} +The OEIS Foundation Inc., \emph{Triangle read by rows: $T(n,k)=\binom{2n+1}{2k+1}\binom{2n-2k}{n-k}/(n+1-k)$ for $0\le k\le n$}, entry A281000 (W.~Schulte, 2017) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A281000}; revision \#17, November 25, 2018. + +\end{thebibliography} +} +\end{document} diff --git a/results/oeis-a294512/README.md b/results/oeis-a294512/README.md new file mode 100644 index 0000000..d261428 --- /dev/null +++ b/results/oeis-a294512/README.md @@ -0,0 +1,45 @@ +# Lang's conjecture a(n) = A250400(n+1)/(n+1) for A294512 fails at n = 164 + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Sequences and series +**Source problem:** OEIS A294512 +**Date:** 2026-10-18 + +## Result + +Let V(n) = sum_{k=0}^{n} 1/((k+1)(3k+1)) and let a(n) be the denominator of V(n) in lowest terms (OEIS A294512). Let A250400(m) be the numerator, in lowest terms, of the harmonic mean m / sum_{j=1}^{m} 1/(j(3j-2)) of the first m octagonal numbers. Lang's conjecture (A294512, FORMULA, 2017) says that A250400(n+1)/(n+1) = a(n) in Q for every n >= 0. This is false. The first failure is at n = 164, where A250400(165)/165 = a(164)/11. + +## Assessment + +Since the harmonic mean is (n+1)/V(n), the conjecture holds exactly when n+1 is coprime to the numerator of V(n). Checking that condition with exact rational arithmetic finds the first failure at n = 164, where 11 divides both 165 and num V(164). The Lean proof confirms the identity 11*A250400(165) = 165*a(164) by kernel evaluation. The paper's hand argument for why 11 divides the numerator is a nice touch but not needed: the result is a direct finite search, and the relevant value was already in Barker's A250400 table. This is a genuine counterexample to the conjecture as intended, not a degenerate case. + +*Follows from:* A harmonic-mean identity that follows straight from the definitions in A294512/A250400: H(n+1) = (n+1)/V(n), so A250400(n+1) = (n+1)*a(n)/gcd(n+1, numerator V(n)). Barker's b-file for A250400 (m <= 1000) already lists A250400(165) = 15*a(164). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A294512](https://oeis.org/A294512) as [`Math0.Statements.A294512.statement`](../../lean/Math0/Statements/OEIS/A294512.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A294512.lean`](../../lean/Math0/Frontier/OEIS/A294512.lean) refutes (proves the negation of) it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: A294512 (Denominators of partial sums of the reciprocals of octagonal numbers), FORMULA: "a(n) = A250400(n+1)/(n+1), n >= 0. [conjecture]." (entry by _Wolfdieter Lang_, Nov 01 2017). Companion A294513 (Lang, Nov 02 2017): "a(n) = 2*A250327(n+1)/(n+1) [conjecture]." + +Referees: OEIS A294512 (W. Lang, Nov 01 2017; history #1-#13, last edit Nov 12 2017, formula "a(n) = A250400(n+1)/(n+1), n >= 0. [conjecture]" still present). OEIS A250401 (C. Barker 2014; Lang comment Nov 01 2017 conditional on "n+1 divides A250400(n+1)", still present, history #1-#19). OEIS A250400 (C. Barker, Nov 21 2014, b-file n=1..1000, which contains A250400(165) = 15*a(164)). Sibling Lang conjectures in A294513, A294515 are unresolved there too. Not in google-deepmind/formal-conjectures (FormalConjectures/OEIS); not in Tsoukalas et al. / Epoch OEIS Open (arXiv 2608.11941; github.com/epoch-research/LeanOpenProblems-results; SeqFan thread "Language models resolving OEIS conjectures", Aug 2026). No SeqFan, MathOverflow, MSE or arXiv discussion found. Independent check: the failures for n < 3000 are exactly n = 164 (gcd 11) and n = 2413 (gcd 17). + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a294512, + author = {{math0}}, + title = {{Lang's conjecture a(n) = A250400(n+1)/(n+1) for A294512 fails at n = 164}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a294512}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a294512/paper.pdf b/results/oeis-a294512/paper.pdf new file mode 100644 index 0000000..dbb2add Binary files /dev/null and b/results/oeis-a294512/paper.pdf differ diff --git a/results/oeis-a294512/paper.tex b/results/oeis-a294512/paper.tex new file mode 100644 index 0000000..5250fa7 --- /dev/null +++ b/results/oeis-a294512/paper.tex @@ -0,0 +1,386 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,set_option,rw,at,push_cast,exact_mod_cast}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={∑}{{$\sum$}}1 {∈}{{$\in$}}1 {ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 + {∀}{{$\forall$}}1 {≥}{{$\ge$}}1 {…}{{$\ldots$}}1 {¬}{{$\neg$}}1 {⊢}{{$\vdash$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{⊢}{\ensuremath{\vdash}} +\newunicodechar{…}{\ensuremath{\ldots}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Zl}{\mathbb{Z}_{(11)}} +\DeclareMathOperator{\num}{num} +\DeclareMathOperator{\den}{den} + +\title[Lang's formula for OEIS A294512 fails at $n=164$]{A counterexample at $n=164$ to a conjectured formula for the denominators of partial sums of reciprocal octagonal numbers} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the denominator, in lowest terms, of $V(n)=\sum_{k=0}^{n}1/((k+1)(3k+1))$ (OEIS A294512), and let $A250400(m)$ be the numerator of the harmonic mean of the first $m$ octagonal numbers. +In 2017 W.~Lang recorded in the OEIS the conjecture that $a(n)=A250400(n+1)/(n+1)$ for all $n\ge 0$. +We show that the conjecture holds at $n$ exactly when $n+1$ is coprime to the numerator of $V(n)$, and that it fails at $n=164$: there $11$ divides both $165$ and the numerator of $V(164)$, and $11\cdot A250400(165)=165\cdot a(164)$, so $A250400(165)/165=a(164)/11$, which is not an integer. +To our knowledge this is a new result, although an elementary one: the formula is still marked as a conjecture in the OEIS, and no earlier counterexample has been recorded. +The refutation is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the listed OEIS terms; this statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +The octagonal numbers are $O_j=j(3j-2)$, $j\ge 0$ (OEIS A000567 \cite{A000567}). In Lang's notation \cite{A294512}, the partial sums of their reciprocals are +\[ + V(n)=V(3,1;n)=\sum_{k=0}^{n}\frac{1}{(k+1)(3k+1)}=\sum_{j=1}^{n+1}\frac{1}{O_j},\qquad n\ge 0, +\] +and they converge to $(\pi/\sqrt3+3\log 3)/4=1.2774\ldots$ \cite{A294512}. +Sums of this kind arise from series $\sum_{k\ge1}c(k)/k$ with periodic coefficients, a topic going back to Euler and treated in Koecher's book \cite[pp.~189--193]{Koe}; see the comments in \cite{A294512}. +The OEIS sequence A294512, contributed by Wolfdieter Lang on November~1, 2017 \cite{A294512}, lists the denominators $a(n)$ of $V(n)$ in lowest terms, and states that the corresponding numerators are given in A250401 \cite{A250401}, i.e.\ that $\num V(n)=A250401(n+1)$; we shall see that this identification also fails at $n=164$ (Corollary~\ref{cor:exact}). + +Three years earlier, Colin Barker had contributed the sequences A250400 and A250401 \cite{A250400,A250401}: the numerators and denominators of the harmonic mean $H(m)=m/\sum_{j=1}^{m}O_j^{-1}=m/V(m-1)$ of the first $m$ octagonal numbers, with tables for $m\le 1000$. +Because $H(n+1)=(n+1)/V(n)$, one expects the numerator of $H(n+1)$ to be $(n+1)\,a(n)$. +Lang recorded this in the FORMULA section of A294512 as a conjecture, $a(n)=A250400(n+1)/(n+1)$ for $n\ge 0$, and added a comment to A250401 that assumes it (``assuming that $n+1$ divides $A250400(n+1)$''). +The formula holds for the $23$ listed terms $n\le 22$, and in fact for all $n\le 163$. + +\subsection*{Result} +The conjecture holds at $n$ if and only if $\gcd(n+1,\num V(n))=1$ (Lemma~\ref{lem:reduction}), and this fails at $n=164$, where $11$ divides $165$ and $\num V(164)$ (Lemma~\ref{lem:11adic}). The formal proof checks $11\cdot A250400(165)=165\cdot a(164)$ by kernel evaluation and derives a contradiction (Theorem~\ref{thm:main}). Below $5000$ the failures are $n=164$, $2413$, $4520$ (Remark~\ref{rem:more}; not formalized). + +\subsection*{Status and prior work} +The conjecture still carries the tag ``[conjecture]'' in the current revision of A294512 (revision~\#13, November~12, 2017), and the comment in A250401 is still stated conditionally. +The math0 referees read the edit histories of A294512, A250400 and A250401 and checked the sibling entries A294513 and A294515; none records a counterexample. +They also found no discussion on the SeqFan mailing list, MathOverflow, Mathematics Stack Exchange or arXiv. +The conjecture is not among the OEIS statements of the formal-conjectures repository \cite{FC}, nor among the $492$ OEIS conjectures, formalized in Lean by Tsoukalas et al., that make up the OEIS Open benchmark \cite{Ad}. +We therefore classify the result as \emph{new}, with two caveats. +First, it is elementary and of modest significance: the counterexample is found by exact rational arithmetic over $165$ terms. +Second, the decisive value was implicitly available since 2014: Barker's table of A250400 \cite{A250400} lists $A250400(165)$, which equals $15\,a(164)$; what was apparently never done is to compare it with the denominator of $V(164)$, since the table of A294512 stops at $n=22$. + +\section{Statement}\label{sec:statement} + +For $x\in\Q$ we write $x=\num(x)/\den(x)$ in lowest terms with $\den(x)\ge 1$. + +\begin{definition}\label{def:main} +For $n\ge 0$ and $m\ge 1$ let +\begin{gather*} + V(n)=\sum_{k=0}^{n}\frac{1}{(k+1)(3k+1)},\qquad a(n)=\den V(n),\\ + H(m)=\frac{m}{\sum_{j=1}^{m}1/(j(3j-2))},\qquad A250400(m)=\num H(m). +\end{gather*} +\end{definition} + +Thus $a$ is A294512 (offset $0$) and $A250400$ is A250400 (offset $1$). The FORMULA section of A294512 (W.~Lang, Nov.~01, 2017) contains, verbatim: +\begin{quote} +\texttt{a(n) = A250400(n+1)/(n+1), n >= 0. [conjecture].} +\end{quote} + +\begin{conjecture}[Lang \cite{A294512}]\label{conj} +For every $n\ge 0$, $A250400(n+1)/(n+1)=a(n)$, the quotient being taken in $\Q$. +\end{conjecture} + +\begin{theorem}\label{thm:main} +$11\cdot A250400(165)=165\cdot a(164)$. Consequently $A250400(165)/165=a(164)/11\ne a(164)$, and Conjecture~\ref{conj} is false. +\end{theorem} + +In addition, $11\nmid a(164)$ (Corollary~\ref{cor:exact}), so $A250400(165)/165$ is not even an integer. Since $a(164)\ge1$, the conjecture also fails at $n=164$ if the quotient is read as integer division: $\lfloor a(164)/11\rfloor1$ exactly for $n=164$, $2413$ and $4520$, with gcd $11$, $17$ and $137$; so $n=164$ is the least counterexample. +Lang's analogous conjecture in A294513 \cite{A294513}, for $V(3,2;n)=\sum_{k\le n}1/((k+1)(3k+2))$ and pentagonal numbers, holds for $n<2500$ except at $n=1891$, where $11$ divides both $1892$ and $\num V(3,2;1891)$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in the file \path{lean/Math0/Frontier/OEIS/A294512.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A294512.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. Its contents after the module docstring are, verbatim except that docstrings are omitted: +\begin{lstlisting} +namespace Math0.Frontier.A294512 +open Math0.Statements.A294512 + +set_option maxHeartbeats 4000000 in +private theorem key : A250400 165 * 11 = 165 * a 164 := by + decide +kernel + +theorem result : ¬ statement := by + intro h + have h1 := h 164 + have hk := key + have hpos : 0 < a 164 := (V 164).den_pos + have h2 : (A250400 165 : ℚ) = 165 * (a 164 : ℚ) := by + rw [div_eq_iff (by norm_num)] at h1 + push_cast at h1 ⊢ + linarith + have h3 : A250400 165 = 165 * a 164 := by exact_mod_cast h2 + omega + +end Math0.Frontier.A294512 + +#math0_settles Math0.Frontier.A294512.result Math0.Statements.A294512.statement +\end{lstlisting} +The main declaration \decl{Math0.Frontier.A294512.result} has type $\neg$\,\decl{Math0.Statements.A294512.statement}; its proof is that of Section~\ref{sec:deduction}, with \decl{omega} doing the final arithmetic. + +\subsection*{Kernel computation} +The lemma \decl{key} is the certificate of Proposition~\ref{prop:key}. With \texttt{decide +kernel}, the Lean kernel itself reduces the decision procedure for this equality in $\N$ to \decl{true}: it unfolds the definitions of Section~\ref{sec:statement}, adds the $165$ rationals of each of the two sums, normalizing to lowest terms with its built-in arbitrary-precision arithmetic on natural-number literals, and compares the two resulting $159$-digit numbers. No compiled code is trusted; \decl{native_decide}, which would add the axiom \decl{Lean.ofReduceBool}, is not used. The option \texttt{maxHeartbeats 4000000} applies to \decl{key} only. The whole file compiles in about $20$ seconds on our machine, most of it spent loading Mathlib. + +\subsection*{Audit} +The file ends with \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself. It fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, \decl{Lean.ofReduceBool}, \decl{Lean.trustCompiler} and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation, after removing metadata annotations, with no unfolding. On this file it reports +\begin{lstlisting} +math0 audit: 'Math0.Statements.A294512.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A294512.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A294512.result' refutes 'Math0.Statements.A294512.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A294512.lean} in the directory \path{lean}. + +\begin{thebibliography}{99} + +\bibitem{Ad} +T.~Adamczewski, \emph{OEIS Open: How many conjectures can language models turn into theorems?}, arXiv:2608.11941, 2026. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Koe} +M.~Koecher, \emph{Klassische elementare Analysis}, Birkh\"auser, Basel, Boston, 1987. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A000567} +The OEIS Foundation Inc., \url{https://oeis.org/A000567} (octagonal numbers). + +\bibitem{A250328} +The OEIS Foundation Inc., \url{https://oeis.org/A250328}, entry by C.~Barker (2014). + +\bibitem{A250400} +The OEIS Foundation Inc., \url{https://oeis.org/A250400}, entry by C.~Barker (2014). + +\bibitem{A250401} +The OEIS Foundation Inc., \url{https://oeis.org/A250401}, entry by C.~Barker (2014), comment by W.~Lang (2017). + +\bibitem{A294512} +The OEIS Foundation Inc., \url{https://oeis.org/A294512}, entry by W.~Lang (2017). + +\bibitem{A294513} +The OEIS Foundation Inc., \url{https://oeis.org/A294513}, entry by W.~Lang (2017). + +\end{thebibliography} + +\end{document} diff --git a/results/oeis-a300789/README.md b/results/oeis-a300789/README.md new file mode 100644 index 0000000..01476e9 --- /dev/null +++ b/results/oeis-a300789/README.md @@ -0,0 +1,41 @@ +# Domino-tileable Young diagrams are exactly the colour-balanced ones (A300789) + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A300789 +**Date:** 2026-10-18 + +## Result + +For every integer partition y = (y_1 >= y_2 >= ... >= y_m), the Young diagram of y can be tiled by dominoes if and only if the number of odd parts in even positions equals the number of odd parts in odd positions. So the Heinz numbers of domino-tileable partitions (A300789) are exactly the Heinz numbers of partitions whose odd parts appear as often in even as in odd positions. Equivalently, a(n) = b(n) for all n >= 1, where a(n) and b(n) are the n-th smallest Heinz numbers of the two classes. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A300789](https://oeis.org/A300789) as [`Math0.Statements.A300789.statement`](../../lean/Math0/Statements/OEIS/A300789.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A300789.lean`](../../lean/Math0/Frontier/OEIS/A300789.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C A300789 This sequence is conjectured to be the Heinz numbers of integer partitions in which the odd parts appear as many times in even as in odd positions. (_Gus Wiseman_, Mar 12 2018) + +Referees: Already known, so the Lean proof is a first formalization, not a new result: +- Classical 2-core / beta-number theory. I.G. Macdonald, Symmetric Functions and Hall Polynomials (2nd ed. 1995), Ch. I §1 Ex. 8, pp. 12-15: the r-core is empty iff the beta-numbers are equidistributed mod r. D.E. Littlewood, Modular representations of symmetric groups, Proc. Roy. Soc. A 209 (1951) 333-353. +- Explicit statement of the parity form. S.P. Albion, "Proof of some Littlewood identities conjectured by Lee, Rains and Warnaar", arXiv:2108.12766, Lemma 2.1: empty 2-core (i.e. domino-tileable) iff {lambda_i + 2n - i} has n even and n odd elements, which is equivalent to the A300789 parity condition. +- Black = white criterion for Young diagrams. Codeforces Round 609 editorial, problem 1268B/1269D "Domino for Young" (Dec 2019, codeforces.com/blog/entry/72358). +- OEIS. A304710 (A. P. Heinz, May 2018) states the equivalence as fact: "number of partitions of 2n where the number of odd parts in even positions differs from the number of odd parts in odd positions". A000712 has Meeussen's 2013 comment and Karlsson's Dec 2025 comment. Heinz's Maple program and b-file for A300789 use the criterion. +- The A300789 entry itself (rev #11, May 22 2018, local mirror = GitHub) still says "conjectured" and has no %E updates. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a300789, + author = {{math0}}, + title = {{Domino-tileable Young diagrams are exactly the colour-balanced ones (A300789)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a300789}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a300789/paper.pdf b/results/oeis-a300789/paper.pdf new file mode 100644 index 0000000..b1cfb6a Binary files /dev/null and b/results/oeis-a300789/paper.pdf differ diff --git a/results/oeis-a300789/paper.tex b/results/oeis-a300789/paper.tex new file mode 100644 index 0000000..e1d179e --- /dev/null +++ b/results/oeis-a300789/paper.tex @@ -0,0 +1,338 @@ +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {∧}{{$\wedge$}}1 {×}{{$\times$}}1 {∈}{{$\in$}}1 {→}{{$\to$}}1 + {∃}{{$\exists$}}1 {∀}{{$\forall$}}1 {∨}{{$\vee$}}1 {⋃₀}{{$\textstyle\bigcup_0$}}2 {≤}{{$\le$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\ind}[1]{[\,#1\,]} +\newcommand{\imb}{\operatorname{I}} +\newcommand{\sh}{\operatorname{D}} + +\title[Domino-tileable Young diagrams (OEIS A300789)]{A Young diagram can be tiled by dominoes if and only if its odd parts occupy as many even as odd positions: the conjecture in OEIS A300789} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +We prove that the Young diagram of an integer partition $y_1\ge y_2\ge\dots\ge y_m$ can be tiled by dominoes if and only if the number of odd parts $y_i$ with $i$ even equals the number of odd parts $y_i$ with $i$ odd. +Equivalently, the sequence A300789 of Heinz numbers of domino-tileable partitions coincides with the sequence of Heinz numbers of partitions satisfying this parity condition, as conjectured in the OEIS entry A300789 (G.~Wiseman, 2018). +The result is not new: it is the case $r=2$ of the classical description of partitions with empty $r$-core, and the parity form appears explicitly in a lemma of Albion (arXiv 2021, published 2024); the OEIS entry nevertheless still records it as a conjecture. +Our contribution is, to our knowledge, the first formal proof: it is verified in Lean~4, with Mathlib, against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before any proof attempt, and whose definitions are checked by the kernel against the $63$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +The Heinz number of an integer partition $y=(y_1,\dots,y_m)$ is $p_{y_1}p_{y_2}\cdots p_{y_m}$, where $p_j$ is the $j$-th prime ($p_1=2$); by unique factorization, every integer $k\ge1$ is the Heinz number of exactly one partition, and $k=1$ belongs to the empty partition. +The OEIS entry A300789 \cite{A300789}, created by Gus Wiseman on March~12, 2018, lists the Heinz numbers of the partitions whose Young diagram can be tiled by dominoes: +\[ +1,3,4,7,9,10,12,13,16,19,21,22,25,27,28,29,34,36,\dots +\] +The entry records the conjecture that these are exactly the Heinz numbers of the partitions ``in which the odd parts appear as many times in even as in odd positions'' (quoted in full in Section~\ref{sec:statement}). +For example, $10=p_3p_1$ is a term: $(3,1)$ has odd parts in positions $1$ and $2$, and its diagram is tiled by one vertical and one horizontal domino. The odd parts of $(3,2,1)$, with Heinz number $30$, are both in odd positions, and its diagram has four cells of one chessboard colour and two of the other. +We prove the conjecture (Theorem~\ref{thm:main} and Corollary~\ref{cor:seq}). + +\subsection*{Prior work and status} +The statement is classical, and we do not claim it as new. +The necessity of the condition is the chessboard-colouring argument: each domino covers one cell of each colour, and a row of length $y_i$ contributes $\pm[y_i\text{ odd}]$ to the colour difference (Lemma~\ref{lem:row}). +For sufficiency, in the language of cores, a partition's diagram is domino-tileable exactly when its $2$-core is empty: removing rim dominoes, which preserves the colour difference, leads to the $2$-core, which is a staircase $(k,k-1,\dots,1)$, and a nonempty staircase has nonzero colour difference. +Littlewood's decomposition of a partition into its $r$-core and $r$-quotient \cite{Lit51} is classical; see James and Kerber \cite{JK81} and Macdonald \cite[Ch.~I, \S1, Ex.~8, pp.~12--15]{Mac95}, where the $r$-core is read off from the distribution of the beta-numbers of the partition modulo $r$; when the number of beta-numbers is a multiple of $r$, the $r$-core is empty exactly when they are equidistributed modulo $r$. +For $r=2$ this is the parity condition in another form. +Albion \cite[Lemma~2.1]{Alb24}, who takes domino-tileability as a definition of empty $2$-core, states for $\lambda$ with at most $2n$ parts that $\lambda$ has empty $2$-core if and only if $\{\lambda_i+2n-i: 1\le i\le 2n\}$ contains $n$ even and $n$ odd integers, noting that the equivalences ``easily follow by induction on $|\lambda|$''. Since $\lambda_i+2n-i\equiv\lambda_i+i\pmod 2$, counting the even and odd values position by position shows that this is exactly the condition of A300789. +The black-equals-white criterion for Young diagrams is also the key fact behind the competitive-programming problem ``Domino for Young'' (Codeforces Round~\#609, December 2019, problems 1268B and 1269D \cite{CF}), whose answer, the maximum number of disjoint dominoes in a Young diagram, is the smaller of the two colour counts. + +Within the OEIS, the entry A304710 \cite{A304710} (A.~P. Heinz, May~17, 2018), which counts the partitions of $2n$ whose diagram cannot be tiled with dominoes, states, without the word ``conjectured'', that it also counts the partitions of $2n$ in which the number of odd parts in even positions differs from the number in odd positions, and its example section gives the colouring argument for $(3,2,1)$. +In A000712 \cite{A000712} (partitions of $n$ into parts of two kinds), W.~Meeussen (April~17, 2013) and J.~Karlsson (December~9, 2025) commented that it also counts the partitions of $2n$ satisfying the parity condition, respectively the domino-tileable ones. +Both programs in A300789 itself generate the terms from the parity condition: the Mathematica program is labelled ``Conjectured'', while the Maple program (A.~P. Heinz, May~22, 2018) carries no such label. +The entry (revision \#11, May~22, 2018) still describes the statement as a conjecture and cites no proof; the statement is not among those of the formal-conjectures repository \cite{FC}. +We therefore classify our result as the first formal proof, to our knowledge, of a known result. + +\subsection*{Method} +We follow the standard argument: the chessboard imbalance of a diagram vanishes exactly under the parity condition, and it vanishes for every tileable diagram (Lemmas~\ref{lem:balanced} and~\ref{lem:fwd}); conversely, a balanced diagram is tiled by removing rim dominoes, since a diagram without a removable rim domino is a staircase (Proposition~\ref{prop:bwd}). + +\section{Statement}\label{sec:statement} + +We index rows and columns from $0$. For a partition $y=(y_1\ge\dots\ge y_m)$ with $y_m\ge1$ let $Y(i)=y_{i+1}$ for $i Even (i + 1) ∧ Odd (y.getD i 0)).card = + ((Finset.range y.length).filter fun i => Odd (i + 1) ∧ Odd (y.getD i 0)).card +def IsConjTerm (k : ℕ) : Prop := 0 < k ∧ OddPartsBalanced (parts k) +noncomputable def b (n : ℕ) : ℕ := Nat.nth IsConjTerm (n - 1) +def statement : Prop := ∀ n : ℕ, 1 ≤ n → a n = b n +end Math0.Statements.A300789 +\end{lstlisting} +Here \texttt{Nat.primeFactorsList k} is the increasing list of prime factors of $k$ with multiplicity and \texttt{Nat.primeCounting p} $=\pi(p)$ is the index of the prime $p$, so \texttt{parts k} is the partition with Heinz number $k$ in weakly decreasing order. As \texttt{y.getD i 0} is the $i$-th entry of \texttt{y} (from $0$), or $0$ beyond its length, \decl{youngDiagram} is the diagram defined above and \decl{OddPartsBalanced} is \eqref{eq:par} with position $i+1$ for index $i$. \texttt{Nat.nth p j} is the $j$-th smallest (from $0$) number satisfying $p$, so \decl{a} and \decl{b} are the sequences of Corollary~\ref{cor:seq} with offset $1$. +The statement file decides \decl{IsTerm} by a verified search (Section~\ref{sec:fwd}) and proves by \texttt{decide +kernel}, i.e.\ by evaluation in the kernel, that $a(1),\dots,a(63)$ and $b(1),\dots,b(63)$ are both the $63$ terms $1,3,\dots,131$ listed in the entry (\decl{a_data}, \decl{b_data}; a kernel-checked \texttt{List.filter} over $\{0,\dots,131\}$ is transferred to \decl{Nat.nth} by \decl{map_nth_eq_of_filter}), and that \decl{parts} gives the partitions of the entry's example (\decl{parts_example}). +The conjecture is read as equality of the two increasing sequences, with no extra hypotheses; Corollary~\ref{cor:seq} is exactly \decl{statement}. Both term sets contain every $3^e$ (the partition $(2,\dots,2)$), so they are infinite and this reading is equivalent to equality of the two sets; the proof establishes the latter directly. Since every partition is \texttt{parts k} for its Heinz number $k$, equality of the two sets is in turn equivalent to Theorem~\ref{thm:main}; this last step uses the bijection between partitions and Heinz numbers, which is not formalized (see the remark after the proof of Theorem~\ref{thm:main}). + +\section{Proof}\label{sec:proof} + +The proof follows \path{lean/Math0/Frontier/OEIS/A300789.lean}; Lean names are given in parentheses. Write $\ind{P}\in\{0,1\}$ for the truth value of $P$. +For a function $Y\colon\N\to\N$ and $N\in\N$ define the \emph{imbalance} and the \emph{diagram} +\[ +\imb_N(Y)=\sum_{i true + | 0, _ :: _ => false + | fuel + 1, c :: rest => + (decide ((c.1, c.2 + 1) ∈ rest) && tileL fuel (rest.erase (c.1, c.2 + 1))) || + (decide ((c.1 + 1, c.2) ∈ rest) && tileL fuel (rest.erase (c.1 + 1, c.2))) +\end{lstlisting} + +\begin{lemma}[\decl{tileL_iff}, in the statement file]\label{lem:search} +If the list $l$ of cells is strictly increasing in row-major order and has length at most $f$, then \texttt{tileL f l = true} if and only if the set of entries of $l$ is domino-tileable. +\end{lemma} + +\begin{proof}[Proof sketch] +Induction on $l$. If $S$ is tileable and $c$ is its row-major first cell, the domino $d\ni c$ of a tiling lies in $S$, so its other cell is not before $c$; hence $d=\{c,c+(0,1)\}$ or $d=\{c,c+(1,0)\}$ (\decl{domino_at_min}), and $S\setminus d$ is tiled by the remaining dominoes (\decl{exists_domino_of_tileable}). Conversely, adding a domino $d\subseteq S$ to a tiling of $S\setminus d$ tiles $S$ (\decl{tileable_of_diff}). Removing two entries from a strictly increasing list leaves a strictly increasing list. +\end{proof} + +\begin{lemma}[\decl{sum_wt_of_tileL}, \decl{sum_cellsList}]\label{lem:fwd} +If \texttt{tileL f l = true}, then $\sum_{c\in l}w(c)=0$. For every list $y$ of length $m$, $\sum_{c\in\texttt{cellsList }y}w(c)=\imb_m(Y_y)$. +\end{lemma} + +\begin{proof} +For the first claim, induct on $f$. If $l=c::\mathit{rest}$ is accepted, then some $c'\in\{c+(0,1),c+(1,0)\}$ lies in $\mathit{rest}$ and $\mathit{rest}.\mathrm{erase}\ c'$ is accepted with fuel $f-1$, so its weight is $0$ by induction. Since $c::\mathit{rest}$ is a permutation of $c::c'::(\mathit{rest}.\mathrm{erase}\ c')$ and $w(c')=-w(c)$, the weight of $l$ is $w(c)+w(c')+0=0$. The second claim follows by summing Lemma~\ref{lem:row} over the rows $iY(i+2)$ for some $i$.} Then $Y(i+1)\ge1$, so $i+1Y'(i)$, and for $b\ge i+2$ we have $Y'(b)=Y(b)\le Y(i+2)\le Y(i+1)-1=Y'(i+1)=Y'(i)$. The rows $i$ and $i+1$ have equal lengths before and after, so their contributions $(-1)^i\varepsilon+(-1)^{i+1}\varepsilon$ to the imbalance (with $\varepsilon=\ind{Y(i)\text{ odd}}$, respectively $\ind{Y(i)-1\text{ odd}}$) are $0$ in both $Y$ and $Y'$, while all other rows are unchanged; hence $\imb_N(Y')=\imb_N(Y)=0$. + +\emph{Case 3: neither case applies.} Then for every $i$, $Y(i+1)\le Y(i)\le Y(i+1)+1$, and $Y(i+1)=Y(i)$ implies $Y(i+2)\ge Y(i+1)$, hence $Y(i+2)=Y(i+1)$. So if $Y(r+1)=Y(r)$ for some $r$, then by induction $Y(r+t+1)=Y(r+t)$ for all $t$, and $Y(r)=Y(r+N)=0$ (\decl{hflat}). We now show $Y(r)=\max(k-r,0)$ with $k=Y(0)$, by induction on $r$ (\decl{hst}). The case $r=0$ is clear. Given it for $r$: either $Y(r+1)=Y(r)$, and then $Y(r)=0$, so $k\le r$ and $Y(r+1)=0=\max(k-r-1,0)$; or $Y(r+1)=Y(r)-1$, and then $Y(r)\ge1$, so $Y(r)=k-r$ and $Y(r+1)=k-(r+1)$. Thus $Y$ is a staircase with $Y(0)\ge1$, and Lemma~\ref{lem:stair} gives $\imb_N(Y)\ne0$, a contradiction. So Case~3 cannot occur. +\end{proof} + +In Lean, $Y'$ is the function \texttt{fun r => if r = i then Y r - 2 else Y r} (in Case~2, \texttt{if r = i $\vee$ r = i + 1 then Y r - 1 else Y r}), so no list manipulation is needed; the arithmetic side conditions are discharged by \texttt{omega}. + +\subsection{Proof of Theorem~\ref{thm:main} and Corollary~\ref{cor:seq}} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +Let $y$ be a partition with $m$ parts, so that $Y_y$ is weakly decreasing, vanishes from $m$ on, and \texttt{youngDiagram y} $=\sh(Y_y)$ (\decl{youngDiagram_eq}; the condition $i=0} a(n) x^n = x^9 (2 + 2x + 2x^2 + x^3) / ((1-x)^4 (1+x)^3 (1+x^2)^2 (1+x+x^2)^2) as formal power series over Q, and (2) for every n > 15, a(n) = -a(n-1) + 2a(n-3) + 4a(n-4) + 2a(n-5) - a(n-6) - 5a(n-7) - 5a(n-8) - a(n-9) + 2a(n-10) + 4a(n-11) + 2a(n-12) - a(n-14) - a(n-15). + +## Assessment + +The proof writes each scalene integer triangle with three positive parameters in one linear relation, 2u+4v+3w=n, with smallest side v+w. Summing this linear weight over the parameters gives the rational generating function in a few lines by a standard MacMahon-type calculation. The order-15 recurrence then follows directly from the denominator. The paper itself calls the argument elementary and a routine computation. The Lean proof's chain of shift bijections is only formalization effort, not a new idea. + +*Follows from:* Standard parametrization of integer triangles (as in Alcuin's sequence A005044 / Andrews-Paule-Riese k-gon partitions): scalene triangles of perimeter n are (k,i,j)=(v+w, v+w+u, 2v+w+u) with u,v,w>=1 and 2u+4v+3w=n, so the g.f. is sum (v+w) x^(2u+4v+3w) = x^9(2-x^3-x^4)/((1-x^2)(1-x^3)^2(1-x^4)^2). Alternatively, Cuculiere's bijection in A005044 reduces it to A307686. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A308107](https://oeis.org/A308107) as [`Math0.Statements.A308107.statement`](../../lean/Math0/Statements/OEIS/A308107.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A308107.lean`](../../lean/Math0/Frontier/OEIS/A308107.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A308107 Conjectures from Colin Barker, May 13 2019: (Start) G.f.: x^9*(2 + 2*x + 2*x^2 + x^3) / ((1 - x)^4*(1 + x)^3*(1 + x^2)^2*(1 + x + x^2)^2). a(n) = -a(n-1) + 2*a(n-3) + ... - a(n-15) for n>15. (End) + +Referees: The OEIS entry A308107 (local mirror and current GitHub oeisdata, version #14 of Sep 12 2021) still marks Barker's May 13 2019 g.f. and recurrence as conjectures, with no proof note or %E edit. Its cross-reference A307686 and the related entries A308108, A308109 and A308158 also leave their Barker conjectures unproved. A005044 has Roger Cuculière's comment that scalene triangles of perimeter n+6 correspond to all triangles of perimeter n; this gives a reduction, not a proof. Sela Fried's proofs of OEIS conjectures (arXiv:2410.07237; JIS 28, 2025, Art. 25.4.3; JIS 29, 2026, Art. 26.1.8; arXiv:2607.24832) do not cover A308107 or any triangle sequence near it. Andrews–Paule–Riese (MacMahon's Partition Analysis IX, k-gon partitions), Hirschhorn on k-gon partitions, and arXiv:2308.01912 on Alcuin's sequence treat only the unweighted triangle count. I found no prior proof or counterexample. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a308107, + author = {{math0}}, + title = {{A308107: Barker's rational generating function and order-15 recurrence for the sum of smallest sides of scalene integer triangles}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a308107}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a308107/paper.pdf b/results/oeis-a308107/paper.pdf new file mode 100644 index 0000000..869e549 Binary files /dev/null and b/results/oeis-a308107/paper.pdf differ diff --git a/results/oeis-a308107/paper.tex b/results/oeis-a308107/paper.tex new file mode 100644 index 0000000..30eb28d --- /dev/null +++ b/results/oeis-a308107/paper.tex @@ -0,0 +1,436 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,unfold,rw,at,apply,ring,linear_combination}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 + {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 {←}{{$\leftarrow$}}1 {→}{{$\to$}}1 {·}{{$\cdot$}}1 + {∑}{{$\sum$}}1 {∈}{{$\in$}}1 {∧}{{$\wedge$}}1 {×}{{$\times$}}1 {ˢ}{{$^{s}$}}1 + {⁻}{{$^{-}$}}1 {¹}{{$^{1}$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {₀}{{$_0$}}1 + {⟦}{{$[\![$}}1 {⟧}{{$]\!]$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +\raggedbottom +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Qx}{\Q[\![X]\!]} + +\title[Smallest sides of scalene integer triangles (OEIS A308107)]{The sum of the smallest sides of scalene integer triangles of perimeter $n$: a proof of Barker's generating function and recurrence for OEIS A308107} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the sum of the smallest sides of all scalene triangles with integer sides and perimeter $n$ (OEIS A308107). +We prove the two formulas that Colin Barker conjectured for this sequence in 2019: the generating function $\sum_n a(n)x^n = x^9(2+2x+2x^2+x^3)/D(x)$, where $D(x)=(1-x)^4(1+x)^3(1+x^2)^2(1+x+x^2)^2$, and the resulting linear recurrence of order $15$, valid for $n>15$. +The proof separates the triangles whose middle side exceeds the smallest side by one, parametrizes these by two positive integers, and turns a chain of bijective shift relations into an identity of formal power series. +To our knowledge this is the first recorded proof (the entry still lists both formulas as conjectures), although the argument is elementary. +The result is verified in Lean~4 with Mathlib against the frozen statement that math0 formalized from the OEIS entry; that statement was reviewed for fidelity before any proof attempt, and its definition of $a$ is checked by the kernel against all $61$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +For $n\in\N$ let +\[ + T(n)=\{(k,i,j)\in\N^3 : kj-i\ge1$. +So $T(n)$ is the set of scalene integer triangles of perimeter $n$, $k$ is the smallest side, and $a(n)$ is the sequence A308107 of the OEIS \cite{A308107}, submitted by Wesley Ivan Hurt on May~13, 2019, with offset $1$. +Its first nonzero terms are $a(9)=2$ (the triangle $(2,3,4)$), $a(11)=2$ (the triangle $(2,4,5)$) and $a(12)=3$ (the triangle $(3,4,5)$). +On the same day Colin Barker added two conjectured formulas to the entry (Conjecture~\ref{conj} below). +We prove both. + +\begin{theorem}\label{thm:main} +As formal power series over $\Q$, +\begin{equation}\label{eq:gf} + \sum_{n\ge0} a(n)\,x^n=\frac{x^9\,(2+2x+2x^2+x^3)}{(1-x)^4(1+x)^3(1+x^2)^2(1+x+x^2)^2}, +\end{equation} +and for every integer $n>15$, +\begin{multline}\label{eq:rec} + a(n) = -a(n-1) + 2a(n-3) + 4a(n-4) + 2a(n-5) - a(n-6) - 5a(n-7) - 5a(n-8) \\ + - a(n-9) + 2a(n-10) + 4a(n-11) + 2a(n-12) - a(n-14) - a(n-15). +\end{multline} +\end{theorem} + +By the factorizations in the proof of Proposition~\ref{prop:AD}, the right-hand side of \eqref{eq:gf} equals +\[ + \frac{x^9\,(2-x^3-x^4)}{(1-x^2)(1-x^3)^2(1-x^4)^2}=\sum_{u,v,w\ge1}(v+w)\,x^{2u+4v+3w}, +\] +which reflects the parametrization $(k,i,j)=(v+w,\,v+w+u,\,2v+w+u)$ of $T(n)$ by the positive integers $u,v,w$ with $2u+4v+3w=n$. +The Lean proof, which we follow in Section~\ref{sec:proof}, uses this parametrization in steps: it removes $u$ by the shift $(k,i,j)\mapsto(k,i+1,j+1)$, and then $v$ and $w$ by further shifts, each giving an identity $(1-X^d)F=G$ in $\Qx$. + +\subsection*{Prior work and status} +The number of integer triangles of perimeter $n$ is Alcuin's sequence A005044 \cite{A005044}, with generating function $x^3/((1-x^2)(1-x^3)(1-x^4))$; Andrews, Paule and Riese \cite{APR01} extended this to $k$-gons with MacMahon's partition analysis, Hirschhorn \cite{Hir02} gave a short derivation of their result, and Patronis and Rizos \cite{PR23} compare two elementary methods for triangles. +These works count triangles and do not consider sums of side lengths. +Hurt's related entries A307686 (smallest sides, all triangles) \cite{A307686}, A308108 and A308109 (largest and middle sides, scalene) \cite{A308108,A308109} and A308158 (smallest sides, isosceles) \cite{A308158} also carry generating functions conjectured by Barker in May 2019. +These entries, and A308107 itself (revision \#14 of September~12, 2021, the current one), still mark Barker's formulas as conjectures and record no proof. +A comment of Roger Cuculière in A005044 relates the scalene triangles of perimeter $n+6$ to all triangles of perimeter $n$; this reduces A308107 to A307686 (Remark~\ref{rem:A307686}) but proves neither. +Fried's proofs of OEIS conjectures \cite{Fri24,Fri25,Fri26,Fri26b} do not cover these sequences. +The math0 literature referees found no prior proof or counterexample, so we classify Theorem~\ref{thm:main} as a new result; the argument is a routine computation of MacMahon type, and the formula may have been derived elsewhere without being recorded. + +\section{Statement}\label{sec:statement} + +\subsection*{The OEIS conjecture} +The FORMULA section of A308107 reads, verbatim: +\begin{lstlisting}[language={}] +Conjectures from _Colin Barker_, May 13 2019: (Start) +G.f.: x^9*(2 + 2*x + 2*x^2 + x^3) / ((1 - x)^4*(1 + x)^3*(1 + x^2)^2*(1 + x + x^2)^2). +a(n) = -a(n-1) + 2*a(n-3) + 4*a(n-4) + 2*a(n-5) - a(n-6) - 5*a(n-7) - 5*a(n-8) - a(n-9) + 2*a(n-10) + 4*a(n-11) + 2*a(n-12) - a(n-14) - a(n-15) for n>15. +(End) +\end{lstlisting} + +\begin{conjecture}[Barker, 2019]\label{conj} +The sequence $a$ satisfies \eqref{eq:gf}, and \eqref{eq:rec} for all $n>15$. +\end{conjecture} + +The entry's defining formula (also used in its PARI and Mathematica programs) is +\[ + a(n)=\sum_{k=1}^{\lfloor(n-1)/3\rfloor}\ \sum_{i=k+1}^{\lfloor(n-k-1)/2\rfloor}\operatorname{sign}\Bigl(\Bigl\lfloor\frac{i+k}{n-i-k+1}\Bigr\rfloor\Bigr)\,k . +\] +With $j=n-i-k$, the bound on $i$ says $i t.1 < t.2.1 ∧ t.2.1 < t.2.2 ∧ t.2.2 < t.1 + t.2.1 ∧ + t.1 + t.2.1 + t.2.2 = n), + t.1 + +def statement : Prop := + (PowerSeries.mk (fun n => (a n : ℚ)) = + X ^ 9 * (2 + 2 * X + 2 * X ^ 2 + X ^ 3) * + ((1 - X) ^ 4 * (1 + X) ^ 3 * (1 + X ^ 2) ^ 2 * (1 + X + X ^ 2) ^ 2)⁻¹) ∧ + (∀ n : ℕ, 15 < n → + (a n : ℤ) = -(a (n - 1) : ℤ) + 2 * (a (n - 3) : ℤ) + 4 * (a (n - 4) : ℤ) + + 2 * (a (n - 5) : ℤ) - (a (n - 6) : ℤ) - 5 * (a (n - 7) : ℤ) - 5 * (a (n - 8) : ℤ) - + (a (n - 9) : ℤ) + 2 * (a (n - 10) : ℤ) + 4 * (a (n - 11) : ℤ) + 2 * (a (n - 12) : ℤ) - + (a (n - 14) : ℤ) - (a (n - 15) : ℤ)) +\end{lstlisting} + +\subsection*{Encoding} +A triple \texttt{t} stands for $(k,i,j)=(\texttt{t.1},\texttt{t.2.1},\texttt{t.2.2})$, so \texttt{a n} is $\sum_{T(n)}k$; the range $\{0,\dots,n\}^3$ loses nothing as the sides sum to $n$. +The entry has offset $1$; the extra value $a(0)=0$ (an empty sum) is harmless, as the right-hand side of \eqref{eq:gf} has zero constant term. +The first clause is \eqref{eq:gf} in Mathlib's ring $\Qx$, where \texttt{PowerSeries.mk f} is $\sum_n f(n)X^n$ and \texttt{⁻¹} is the inverse of power series over a field. +The denominator $D=(1-X)^4(1+X)^3(1+X^2)^2(1+X+X^2)^2$ has constant coefficient $1$, so $D^{-1}$ is its true inverse, and \decl{genFun_iff} (from Mathlib's \decl{PowerSeries.eq_mul_inv_iff_mul_eq}) shows that the first clause is equivalent to +\begin{equation}\label{eq:AD} + A\cdot D = X^9(2+2X+2X^2+X^3),\qquad A=\textstyle\sum_{n\ge0}a(n)X^n . +\end{equation} +The second clause is \eqref{eq:rec} in $\Z$ for $n>15$; then $n-15\ge1$, so no truncated subtraction occurs. + +\subsection*{Checks against the OEIS data} +The statement file defines a faster evaluator \decl{aFast}, which sums over the pairs $(k,i)$ with $j=n-(k+i)$, proves \decl{a_eq_aFast} (\texttt{a n = aFast n} for all $n$), and checks in \decl{a_data}, by \texttt{decide +kernel}, that $a(1),\dots,a(61)$ are the $61$ listed terms $0,\dots,0,2,0,2,3,5,3,9,\dots,740,735,825$. +Two further checks concern the transcription of the conjecture: \decl{recurrence_data} checks by \texttt{decide} that the listed terms satisfy \eqref{eq:rec} for $16\le n\le61$, and \decl{den_eq} checks by \texttt{ring} that +\begin{equation}\label{eq:den} + D = 1 + X - 2X^3 - 4X^4 - 2X^5 + X^6 + 5X^7 + 5X^8 + X^9 - 2X^{10} - 4X^{11} - 2X^{12} + X^{14} + X^{15}, +\end{equation} +the characteristic polynomial of \eqref{eq:rec}. + +\section{Proof}\label{sec:proof} + +We follow the declarations of the Lean file, whose names we give in brackets; all except \decl{result} are private. +We write $[P]$ for $1$ if $P$ holds and $0$ otherwise. +Besides $T(n)$ (\decl{T}; $a(n)=\sum_{T(n)}k$ is \decl{a_eq_T}) we use $U(n)=\{(v,w)\in\N^2 : v,w\ge1,\ 4v+3w+2=n\}$ (\decl{U}) and +\[ + b_v(n)=\sum_{U(n)}v,\quad b_w(n)=\sum_{U(n)}w,\quad c(n)=\#U(n),\quad e(n)=\#\{(v,w)\in U(n): v=1\} +\] +(\decl{bv}, \decl{bw}, \decl{c}, \decl{e}); in Lean, $T(n)$ and $U(n)$ are filtered from $\{0,\dots,n\}^3$ and $\{0,\dots,n\}^2$. +Each bijection below is applied with Mathlib's \decl{Finset.sum_nbij'}, which needs the two maps, membership of their images, the two inverse identities and equality of the summands; after unfolding membership, these goals are closed by \texttt{omega} (a few trivial ones by \texttt{simp} or \texttt{rfl}). + +\subsection*{Step 1: the middle side} + +\begin{lemma}[\decl{sum_T_filter}]\label{lem:tight} +For every $n$, $\displaystyle\sum_{(k,i,j)\in T(n),\ i=k+1}k=\sum_{(v,w)\in U(n)}(v+w)$. +\end{lemma} + +\begin{proof} +Let $\varphi(v,w)=(v+w,\,v+w+1,\,2v+w+1)$ and $\psi(k,i,j)=(j-k-1,\,2k+1-j)$. +If $(v,w)\in U(n)$, then $(k,i,j)=\varphi(v,w)$ satisfies $i=k+1$, $ki$, $w=2k+1-j\ge1$ because $j15$. +The coefficient of $X^n$ in $X^mA$ is $a(n-m)$ for $m\le n$ (\decl{coeff_shift}), so the coefficient of $X^n$ in $A\cdot D$ is $\sum_{m=0}^{15}d_m\,a(n-m)$; in $X^9(2+2X+2X^2+X^3)=2X^9+2X^{10}+2X^{11}+X^{12}$ it is $0$, as $n\notin\{9,\dots,12\}$. +Hence $a(n)=-\sum_{m=1}^{15}d_m\,a(n-m)$ in $\Q$, which is \eqref{eq:rec} by \eqref{eq:den}; as the cast $\Z\to\Q$ is injective (\decl{Int.cast_injective}), \eqref{eq:rec} holds in $\Z$. +\end{proof} + +\begin{remark}[A307686; not formalized]\label{rem:A307686} +Let $s(n)$ be the sum of the smallest sides of all integer triangles $k\le i\le j (a n : ℚ)) * den = X ^ 9 * (2 + 2 * X + 2 * X ^ 2 + X ^ 3) +\end{lstlisting} +The file uses no \texttt{sorry}, \texttt{native\_decide}, \texttt{set\_option} or macros, and its only kernel evaluation is \decl{a_zero_one} ($a(0)=a(1)=0$, by \texttt{decide}); the computational checks of the data, \decl{a_data} and \decl{recurrence_data}, are in the statement file, where \texttt{decide +kernel} makes the kernel evaluate \decl{aFast} on $n\le61$ (about $8\cdot10^4$ pairs in total) and compare with the listed terms. + +\subsection*{Audit} +The proof file ends with \texttt{\#math0\_settles} applied to \decl{result} and \decl{statement}. This command, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless \decl{statement} is a \texttt{Prop}-valued definition without universe parameters, both declarations use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (which rejects \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} behind \texttt{native\_decide}, and custom axioms), and the type of \decl{result} is syntactically the statement or its negation, up to metadata, with no unfolding. +Running \texttt{lake env lean Math0/Frontier/OEIS/A308107.lean} in the directory \path{lean} prints\par\nobreak\noindent +\begin{minipage}{\linewidth} +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A308107.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A308107.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A308107.result' proves 'Math0.Statements.A308107.statement' +\end{lstlisting} +\end{minipage} +so \decl{result} proves the statement and depends only on the three permitted axioms. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which does not contain A308107 and is not used by this result. +To reproduce, run \path{scripts/verify.sh} from the repository root; it fetches the Mathlib cache, builds all math0 results with \texttt{lake build} (re-running every audit command) and checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified. +For this result alone, run \texttt{lake build Math0.Statements.OEIS.A308107} and \texttt{lake env lean Math0/Frontier/OEIS/A308107.lean} in \path{lean}; the second takes under a minute. + +{\small +\begin{thebibliography}{99} + +\bibitem{APR01} +G.~E. Andrews, P.~Paule, and A.~Riese, \emph{MacMahon's partition analysis IX: $k$-gon partitions}, Bull. Austral. Math. Soc. \textbf{64} (2001), no.~2, 321--329. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Fri24} +S.~Fried, \emph{Proofs of some conjectures from the OEIS}, arXiv:2410.07237, 2024. + +\bibitem{Fri25} +S.~Fried, \emph{Proofs of several conjectures from the OEIS}, J. Integer Seq. \textbf{28} (2025), Article 25.4.3. + +\bibitem{Fri26} +S.~Fried, \emph{Proofs of ten conjectures from the OEIS}, J. Integer Seq. \textbf{29} (2026), Article 26.1.8. + +\bibitem{Fri26b} +S.~Fried, \emph{Further proofs of conjectures from the OEIS}, arXiv:2607.24832, 2026. + +\bibitem{Hir02} +M.~D. Hirschhorn, \emph{$k$-gon partitions}, Bull. Austral. Math. Soc. \textbf{66} (2002), no.~1, 149--150. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A005044} +The OEIS Foundation Inc., \url{https://oeis.org/A005044} (Alcuin's sequence), entry by R.~G. Wilson~v. + +\bibitem{A307686} +The OEIS Foundation Inc., \url{https://oeis.org/A307686}, entry by W.~I. Hurt, May~11, 2019. + +\bibitem{A308107} +The OEIS Foundation Inc., \url{https://oeis.org/A308107}, entry by W.~I. Hurt, May~13, 2019; revision \#14, Sep.~12, 2021. + +\bibitem{A308108} +The OEIS Foundation Inc., \url{https://oeis.org/A308108}, entry by W.~I. Hurt, May~13, 2019. + +\bibitem{A308109} +The OEIS Foundation Inc., \url{https://oeis.org/A308109}, entry by W.~I. Hurt, May~13, 2019. + +\bibitem{A308158} +The OEIS Foundation Inc., \url{https://oeis.org/A308158}, entry by W.~I. Hurt, May~14, 2019. + +\bibitem{PR23} +T.~Patronis and I.~Rizos, \emph{Triangles with integer sides and given perimeter}, Mathematical Review \textbf{97--98} (2022), 78--89 (in Greek); arXiv:2308.01912. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a308121/README.md b/results/oeis-a308121/README.md new file mode 100644 index 0000000..dbec708 --- /dev/null +++ b/results/oeis-a308121/README.md @@ -0,0 +1,50 @@ +# A308121: for odd n > 1, row 2n is row n with its halves swapped + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A308121 +**Date:** 2026-10-25 + +## Result + +Let T(n,k) = b_n·k − a_n·r_k(n), where r_1(n) < ... < r_φ(n)(n) are the totatives of n and a_n/b_n is φ(n)/n in lowest terms (A076512/A109395). Row n is (T(n,1), ..., T(n,φ(n))). Claim (Charlie Neder's conjecture): for every odd n > 1, row n splits into two halves A, B of equal length with row n = A ++ B, and row 2n = B ++ A. + +## Assessment + +For odd n, the totatives of 2n are 2r-n for the totatives r of n above n/2, followed by n+2r for those below n/2. The symmetry r -> n-r puts exactly half of the totatives on each side of n/2. The reduced form of phi(2n)/(2n) is (a_n/2)/b_n, and after substituting both facts the identity T(2n,k) = T(n,k±phi(n)/2) is two lines of algebra using a_n n = b_n phi(n). This is a short, standard elementary argument, about a page, and a competent number theorist would find it quickly. The manuscript itself calls the argument elementary. The length of the Lean proof reflects list bookkeeping, not mathematical depth. + +*Follows from:* The classical fact that for odd n, phi(2n) = phi(n) and the totatives of 2n are the odd residues coprime to n. They are 2r-n for the totatives r > n/2, followed by n+2r for the totatives r < n/2. The symmetry r -> n-r (implicit in the entry's x+y = A109395(n) comment) shows that each half contains phi(n)/2 totatives. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A308121](https://oeis.org/A308121) as [`Math0.Statements.A308121.statement`](../../lean/Math0/Statements/OEIS/A308121.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A308121.lean`](../../lean/Math0/Frontier/OEIS/A308121.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: If n is odd, then row 2n can be obtained from row n by interchanging the first and second halves. (Charlie Neder, Jun 05 2019) + +Referees: - OEIS A308121 (Jamie Morken, May 13 2019; last edited Aug 05 2019, revision #47). Charlie Neder's conjecture of Jun 05 2019 is still marked "Conjecture," with no %E or comment recording a proof. +- The two entries that cite it, A307964 and A309497, do not resolve it. +- The cross-referenced entries A109395, A076512, A038566 and A076511 contain nothing about the conjecture. +- The classical background is phi(2n) = phi(n) for odd n and the bijection between totatives of n and of 2n; see arXiv 0907.1689, which treats a related map as a routine exercise. +- A308121 is absent from google-deepmind/formal-conjectures, and so from the OEIS Open benchmark (arXiv 2608.11941). +- Web searches (arXiv, MSE/MO, OEIS wiki) found no prior proof or counterexample. The SeqFan archive could not be reached (503 / connection reset). + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a308121, + author = {{math0}}, + title = {{A308121: for odd n > 1, row 2n is row n with its halves swapped}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a308121}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a308121/paper.pdf b/results/oeis-a308121/paper.pdf new file mode 100644 index 0000000..bfacc8a Binary files /dev/null and b/results/oeis-a308121/paper.pdf differ diff --git a/results/oeis-a308121/paper.tex b/results/oeis-a308121/paper.tex new file mode 100644 index 0000000..128f3a4 --- /dev/null +++ b/results/oeis-a308121/paper.tex @@ -0,0 +1,394 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,linear_combination}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 + {∃}{{$\exists$}}1 {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 + {→}{{$\to$}}1 {≤}{{$\le$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} +\newtheorem{example}[theorem]{Example} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\Tot}{\operatorname{Tot}} +\newcommand{\R}{\mathcal{R}} +\newcommand{\cat}{\mathbin{+\!\!+}} +\newcommand{\iv}[2]{[#1\,..\,#2]} + +\title[Neder's conjecture for OEIS A308121]{For odd $n>1$, row $2n$ of the triangle $T(n,k)=\operatorname{den}\bigl(\tfrac{\varphi(n)}{n}\bigr)k-\operatorname{num}\bigl(\tfrac{\varphi(n)}{n}\bigr)r_k(n)$ is row $n$ with its halves interchanged: Neder's conjecture for OEIS A308121} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 25, 2026} + +\begin{document} +\begin{abstract} +For $n\ge1$ let $r_1(n)<\dots1$, row $2n$ is obtained from row $n$ by interchanging its first and second halves. +The proof lists the totatives of $2n$ as the images of the totatives of $n$ above $n/2$ under $r\mapsto 2r-n$, followed by the images of those below $n/2$ under $r\mapsto n+2r$, and shows that $\varphi(2n)/(2n)$ has reduced form $(a_n/2)/b_n$. +To our knowledge the result is new, although the argument is elementary; the OEIS entry still lists the statement as a conjecture. +The theorem is verified in Lean~4 against a frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the $72$ listed terms; this statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +For an integer $n\ge1$ let $\varphi$ be Euler's totient function and let +\[ + r_1(n)1$ (Theorem~\ref{thm:main}). +We do not treat Neder's observation on rows $pn$. + +\subsection*{Method} +For odd $n\ge3$ the totatives of $2n$ are, in increasing order, $2r-n$ for the totatives $r>n/2$ of $n$, followed by $n+2r$ for the totatives $r1$ be odd. Then $\varphi(n)=\varphi(2n)=2h$ for an integer $h\ge1$, and +\[ + T(2n,k)=T(n,h+k),\qquad T(2n,h+k)=T(n,k)\qquad(1\le k\le h). +\] +Equivalently, there are lists $A,B$ with $|A|=|B|$, $\R(n)=A\cat B$ and $\R(2n)=B\cat A$. +\end{theorem} + +For $n\ge3$ the number $\varphi(n)$ is even, so the halves of $\R(n)$ exist and are unique; $\R(1)=(0)$ has no halves. +For even $n$ the statement does not apply, since then $\varphi(2n)=2\varphi(n)$. + +\subsection*{Lean formalization} +The statement was formalized by math0 in the file \path{lean/Math0/Statements/OEIS/A308121.lean}. It was reviewed for fidelity and frozen (SHA-256 \texttt{70da202a\ldots c9e58}) before any proof attempt. Its definitions read as follows (verbatim; the copyright header, the import, the module docstring, the docstrings, blank lines and the four theorems are omitted): +\begin{lstlisting} +namespace Math0.Statements.A308121 +def totatives (n : ℕ) : List ℕ := + (List.range' 1 n).filter (fun r => Nat.Coprime r n) +def A109395 (n : ℕ) : ℕ := ((Nat.totient n : ℚ) / n).den +def A076512 (n : ℕ) : ℤ := ((Nat.totient n : ℚ) / n).num +def T (n k : ℕ) : ℤ := + (A109395 n : ℤ) * k - A076512 n * ((totatives n).getD (k - 1) 0 : ℕ) +def row (n : ℕ) : List ℤ := + (List.range (Nat.totient n)).map (fun i => T n (i + 1)) +def statement : Prop := + ∀ n : ℕ, Odd n → 1 < n → + ∃ A B : List ℤ, row n = A ++ B ∧ A.length = B.length ∧ row (2 * n) = B ++ A +end Math0.Statements.A308121 +\end{lstlisting} +Here \texttt{List.range' 1 n} is $\iv{1}{n}$, so \decl{totatives} is $\Tot(n)$, i.e.\ row $n$ of A038566, described there as the ``triangle in which n-th row gives phi(n) numbers between 1 and n that are relatively prime to n'' \cite{A038566}; in particular \texttt{totatives 1 = [1]}. +\decl{A109395} and \decl{A076512} are the denominator and numerator of the reduced rational number $\varphi(n)/n$, as in the names of A109395 and (via its comment ``Numerator of phi(n)/n'') A076512; Lean's \texttt{Rat.num} and \texttt{Rat.den} return the reduced form with positive denominator. +\decl{T} computes $b_nk-a_nr_k(n)$ in $\Z$, because the sequence is signed; the index $k$ is $1$-based through \texttt{getD (k - 1) 0} (only the values with $1\le k\le\varphi(n)$ are used), and \decl{row} lists $T(n,1),\dots,T(n,\varphi(n))$, matching the comment ``Row n has length A000010(n)''. +The conjecture is encoded literally: the first and second halves of row $n$ are lists $A,B$ of equal length with $\R(n)=A\cat B$, and $\R(2n)=B\cat A$. +The hypothesis \texttt{1 < n} excludes $n=1$, for which row $1=(0)$ has no halves (and row $2=(1)$); the statement file documents this reading. +Four theorems in the statement file, all proved by \texttt{decide +kernel} (evaluation in the kernel), compare the definitions with the OEIS entry; two of them read: +\begin{lstlisting} +theorem a_data : (List.range 15).flatMap (fun i => row (i + 1)) = + [0, 1, 1, 2, 1, 1, 1, 2, 3, 4, 2, 1, 1, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 3, 4, + 1, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 2, 1, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 4, 5, 6, 1, 2, 3, 7, 14, 13, 4, 11, 2, 1, 8] +theorem T_210_2 : T 210 2 = -18 +\end{lstlisting} +\decl{a_data} checks that rows $1,\dots,15$, flattened, are exactly the $72$ listed terms $a(1),\dots,a(72)$ of A308121; \decl{T_210_2} checks the worked example $T(210,2)=35\cdot2-8\cdot11=-18$ of the entry; \decl{statement_check_7} and \decl{statement_check_15} check the halves swap for $n=7$ and $n=15$ (sanity checks of the transcription, not part of the proof). + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A308121.lean}; the names of the corresponding Lean declarations are given with each step. +Throughout, $t\ge1$ and $n=2t+1$, and +\[ + L=\iv{1}{t}|_{C_n},\qquad H=\iv{t+1}{2t}|_{C_n},\qquad h=|L|. +\] +Thus $L$ lists the totatives of $n$ below $n/2$ and $H$ those above $n/2$, both increasing. + +\begin{lemma}[\decl{len_tot}]\label{lem:len} +For every $m\ge1$, $|\Tot(m)|=\varphi(m)$. +\end{lemma} + +\begin{proof} +$|\Tot(m)|$ is the number of integers $r\in[1,m]$ with $\gcd(r,m)=1$, which is $\varphi(m)$. In Lean this is Mathlib's \decl{Nat.filter_coprime_Ico_eq_totient}, which counts the integers coprime to $m$ in any interval of $m$ consecutive integers. +\end{proof} + +\begin{lemma}[\decl{tot_split}, \decl{map_sub_range'}, \decl{len_eq}]\label{lem:tot} +$\Tot(n)=L\cat H$ and $|H|=|L|=h$. Consequently $\varphi(n)=2h$. +\end{lemma} + +\begin{proof} +We have $\iv{1}{n}=\iv{1}{t}\cat\iv{t+1}{2t}\cat(n)$, and $\gcd(n,n)=n>1$, so $n$ is removed by the filter. Filtering commutes with concatenation, so $\Tot(n)=L\cat H$. + +Let $\rho(r)=n-r$. Then $\rho\bigl(\iv{1}{t}\bigr)=(n-1,n-2,\dots,n-t)$ is the reverse of $\iv{t+1}{2t}$ (\decl{map_sub_range'}). Since $\gcd(n-r,n)=\gcd(r,n)$ for $1\le r\le t$, the predicates $C_n\circ\rho$ and $C_n$ agree on $\iv{1}{t}$. Filtering commutes with reversal, and the filter of a mapped list is the map of the filter by the composed predicate, so +\[ + \operatorname{rev}(H)=\iv{t+1}{2t}^{\mathrm{rev}}\big|_{C_n}=\rho\bigl(\iv{1}{t}\bigr)\big|_{C_n}=\rho\bigl(\iv{1}{t}|_{C_n\circ\rho}\bigr)=\rho(L). +\] +Hence $|H|=|L|=h$, and $\varphi(n)=|L|+|H|=2h$ by Lemma~\ref{lem:len}. +\end{proof} + +\begin{lemma}[\decl{filter_pair}]\label{lem:pair} +Let $m\ge1$, let $a$ be odd and $k\ge0$. Then +\[ + \iv{a}{a+2k-1}\big|_{C_{2m}}=(a,a+2,\dots,a+2k-2)\big|_{C_m}. +\] +\end{lemma} + +\begin{proof} +Induction on $k$; the case $k=0$ is trivial. The list $\iv{a}{a+2k+1}$ begins with $a,a+1$, followed by $\iv{a+2}{a+2k+1}$, and $a+2$ is odd. Since $a$ is odd, $\gcd(a,2m)=1$ if and only if $\gcd(a,m)=1$; since $a+1$ is even, $\gcd(a+1,2m)\ne1$. Applying the induction hypothesis to $a+2$ gives the claim for $k+1$. +\end{proof} + +\begin{lemma}[\decl{range'_two_eq_map}, \decl{cop_hi}, \decl{cop_lo}, \decl{tot2_split}]\label{lem:tot2} +Let $\sigma(r)=2r-n$ and $\tau(r)=n+2r$. Then +\[ + \Tot(2n)=\sigma(H)\cat\tau(L). +\] +Consequently $\varphi(2n)=2h$. +\end{lemma} + +\begin{proof} +Split $\iv{1}{2n}=\iv{1}{2t}\cat(2t+1,2t+2)\cat\iv{2t+3}{4t+2}$. The middle entries are removed by the filter $C_{2n}$: $\gcd(2t+1,2n)=n>1$, and $2t+2$ is even. By Lemma~\ref{lem:pair} with $m=n$, $k=t$ and $a=1$, respectively $a=2t+3$, +\[ + \Tot(2n)=(1,3,\dots,2t-1)\big|_{C_n}\cat(2t+3,2t+5,\dots,4t+1)\big|_{C_n}. +\] +Since $\sigma(t+1)=1$ and $\sigma(r+1)=\sigma(r)+2$, we have $(1,3,\dots,2t-1)=\sigma\bigl(\iv{t+1}{2t}\bigr)$; likewise $\tau(1)=2t+3$ and $\tau(r+1)=\tau(r)+2$ give $(2t+3,\dots,4t+1)=\tau\bigl(\iv{1}{t}\bigr)$ (\decl{range'_two_eq_map}). +Because $n$ is odd, $\gcd(2r-n,n)=\gcd(2r,n)=\gcd(r,n)$ for $2r\ge n$ (\decl{cop_hi}) and $\gcd(n+2r,n)=\gcd(2r,n)=\gcd(r,n)$ (\decl{cop_lo}). Hence $C_n\circ\sigma=C_n$ on $\iv{t+1}{2t}$ and $C_n\circ\tau=C_n$ on $\iv{1}{t}$, and as in the proof of Lemma~\ref{lem:tot}, +\[ + \sigma\bigl(\iv{t+1}{2t}\bigr)\big|_{C_n}=\sigma(H),\qquad \tau\bigl(\iv{1}{t}\bigr)\big|_{C_n}=\tau(L). +\] +Finally $\varphi(2n)=|\sigma(H)|+|\tau(L)|=|H|+|L|=2h$ by Lemmas~\ref{lem:len} and~\ref{lem:tot}. +\end{proof} + +In Lean, $\sigma$ is written with truncated subtraction \texttt{2 * r - (2 * t + 1)}; on $\iv{t+1}{2t}$ we have $2r\ge2t+2>n$, so the subtraction is exact. + +\begin{lemma}[\decl{rat_facts}]\label{lem:frac} +Let $n>1$ be odd. Then $b_{2n}=b_n$, $2a_{2n}=a_n$, and $a_n\,n=b_n\,\varphi(n)$. +\end{lemma} + +\begin{proof} +Let $q=\varphi(n)/n=a_n/b_n$. Clearing denominators gives $a_n\,n=b_n\,\varphi(n)$. Since $\gcd(2,n)=1$, $\varphi(2n)=\varphi(2)\varphi(n)=\varphi(n)$, so $\varphi(2n)/(2n)=q/2$. +As $n>2$, $\varphi(n)$ is even, so $a_n\,n$ is even; as $n$ is odd, $a_n$ is even, say $a_n=2c$. From $\gcd(a_n,b_n)=1$ we get $\gcd(c,b_n)=1$. Therefore $q/2=c/b_n$ with $b_n\ge1$ and $\gcd(c,b_n)=1$, and by uniqueness of the reduced form (Mathlib's \decl{Rat.num_div_eq_of_coprime} and \decl{Rat.den_div_eq_of_coprime}) $a_{2n}=c$ and $b_{2n}=b_n$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main} (\decl{result})] +Let $n=2t+1$ with $t\ge1$, and let $L,H,h$ be as above. By Lemmas~\ref{lem:tot} and~\ref{lem:tot2}, $\varphi(n)=\varphi(2n)=2h$. Write $a=a_n$, $b=b_n$ and $c=a_{2n}$. By Lemma~\ref{lem:frac}, $b_{2n}=b$, $a=2c$ and $an=2bh$, so +\begin{equation}\label{eq:key} + c\,n=b\,h . +\end{equation} +If $\varphi(m)=2h$, then $\R(m)=\bigl(T(m,1),\dots,T(m,h)\bigr)\cat\bigl(T(m,h+1),\dots,T(m,2h)\bigr)$ (\decl{row_split}). Apply this to $m=n$, and let $A$ and $B$ be the two halves of $\R(n)$, so $\R(n)=A\cat B$ and $|A|=|B|=h$. Apply it also to $m=2n$; it remains to show that the first half of $\R(2n)$ is $B$ and the second is $A$, i.e.\ the two identities of the theorem. + +Let $1\le k\le h$. By Lemma~\ref{lem:tot2}, $r_k(2n)=\sigma(H_k)=2H_k-n$ and $r_{h+k}(2n)=\tau(L_k)=n+2L_k$; by Lemma~\ref{lem:tot}, $r_k(n)=L_k$ and $r_{h+k}(n)=H_k$. Using $a=2c$ and \eqref{eq:key}, +\begin{align*} + T(2n,k)&=bk-c\,(2H_k-n)=bk-aH_k+cn=b(h+k)-aH_k=T(n,h+k),\\ + T(2n,h+k)&=b(h+k)-c\,(n+2L_k)=b(h+k)-bh-aL_k=bk-aL_k=T(n,k). +\end{align*} +Hence $\R(2n)=B\cat A$. +\end{proof} + +In Lean, the index bookkeeping (the positions $k$ and $h+k$ in $L\cat H$ and in $\sigma(H)\cat\tau(L)$) is done with \decl{List.getElem_append_left} and \decl{List.getElem_append_right}, and the two displayed identities are closed by \texttt{linear\_combination} from $2c=a$ and \eqref{eq:key}. + +\begin{remark}\label{rem:map} +Lemma~\ref{lem:tot2} says that $r\mapsto(2r+n)\bmod 2n$ maps $\Tot(n)$ bijectively onto $\Tot(2n)$, increasingly on each of $L$ and $H$, with the image of $H$ preceding that of $L$. This map is the composition of doubling modulo $n$, $r\mapsto 2r\bmod n$, with the isomorphism $y\mapsto y$ ($y$ odd), $y\mapsto y+n$ ($y$ even) used by Nijenhuis \cite{Nij}. Theorem~\ref{thm:main} can also be read as $T(2n,k)=T(n,k')$, where $k'\equiv k+h\pmod{2h}$ and $1\le k'\le 2h$. +\end{remark} + +\begin{example} +For $n=15$: $\varphi(15)/15=8/15$, $L=(1,2,4,7)$, $H=(8,11,13,14)$, $h=4$, and $\R(15)=(7,14,13,4\mid 11,2,1,8)$. Lemma~\ref{lem:tot2} gives $\Tot(30)=(1,7,11,13,17,19,23,29)$, and $\varphi(30)/30=4/15$, so $c=4$, $b=15$, and $\R(30)=(11,2,1,8\mid 7,14,13,4)$, as in the b-file of A308121 (rows $1,\dots,210$). Similarly row $210$, which contains the entry's worked example $T(210,2)=-18$, is row $105$ with its halves of length $24$ interchanged. +\end{example} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in the file \path{lean/Math0/Frontier/OEIS/A308121.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A308121.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A308121.result}, of type \decl{Math0.Statements.A308121.statement}. The auxiliary lemmas are private: \decl{filter_pair} (Lemma~\ref{lem:pair}), \decl{range'_two_eq_map}, \decl{map_sub_range'}, \decl{len_tot} (Lemma~\ref{lem:len}), \decl{cop_hi}, \decl{cop_lo}, \decl{tot_split}, \decl{tot2_split}, \decl{len_eq}, \decl{rat_facts} (Lemma~\ref{lem:frac}), \decl{getD_lt} and \decl{row_split}. Two of them, and the end of the file, read verbatim (docstrings and proofs omitted): +\begin{lstlisting} +private lemma tot2_split (t : ℕ) (ht : 1 ≤ t) : + totatives (2 * (2 * t + 1)) = + ((List.range' (t + 1) t).filter (fun r => Nat.Coprime r (2 * t + 1))).map + (fun r => 2 * r - (2 * t + 1)) ++ + ((List.range' 1 t).filter (fun r => Nat.Coprime r (2 * t + 1))).map + (fun r => (2 * t + 1) + 2 * r) +private lemma rat_facts (n : ℕ) (hn : Odd n) (h1 : 1 < n) : + A109395 (2 * n) = A109395 n ∧ A076512 (2 * n) * 2 = A076512 n ∧ + A076512 n * n = A109395 n * Nat.totient n +theorem result : statement := by + ... +end Math0.Frontier.A308121 +#math0_settles Math0.Frontier.A308121.result Math0.Statements.A308121.statement +\end{lstlisting} +The proof is general: it contains no finite case check, and it uses no \texttt{decide} or \texttt{native\_decide} tactic and no \texttt{set\_option}. It does not use the data theorems of the statement file. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata annotations, with no unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A308121.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A308121.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A308121.result' proves 'Math0.Statements.A308121.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A308121.lean} in the directory \path{lean}; this takes between about 20 seconds and a minute on our machine, depending on load. +Independently of Lean, the referees checked the conjecture numerically for all odd $n$ with $3\le n<6000$, and the intermediate Lemmas~\ref{lem:tot}, \ref{lem:tot2} and~\ref{lem:frac} for all odd $n$ with $3\le n<4000$. + +{\small +\begin{thebibliography}{99} + +\bibitem{Ad} +T.~Adamczewski, \emph{OEIS Open: How many conjectures can language models turn into theorems?}, arXiv:2608.11941, 2026. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Nij} +A.~Nijenhuis, \emph{Small Gamma products with simple values}, arXiv:0907.1689, 2009. + +\bibitem{A038566} +The OEIS Foundation Inc., \url{https://oeis.org/A038566}, entry by N.~J.~A. Sloane. + +\bibitem{A076512} +The OEIS Foundation Inc., \url{https://oeis.org/A076512}, entry by R.~Zumkeller (Oct.~15, 2002). + +\bibitem{A109395} +The OEIS Foundation Inc., \url{https://oeis.org/A109395}, entry by F.~Vrabec (Aug.~26, 2005). + +\bibitem{A307964} +The OEIS Foundation Inc., \url{https://oeis.org/A307964}, entry by J.~Morken (July~29, 2019). + +\bibitem{A308121} +The OEIS Foundation Inc., \url{https://oeis.org/A308121}, entry by J.~Morken (May~13, 2019); conjecture by C.~Neder (June~5, 2019); revision \#47, Aug.~5, 2019. + +\bibitem{A309497} +The OEIS Foundation Inc., \url{https://oeis.org/A309497}, entry by J.~Morken (Aug.~5, 2019). + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a308222/README.md b/results/oeis-a308222/README.md new file mode 100644 index 0000000..6487393 --- /dev/null +++ b/results/oeis-a308222/README.md @@ -0,0 +1,40 @@ +# Perimeters of primitive Heronian isosceles triangles: A308222(n) = 2 · A096033(n + 2) + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A308222 +**Date:** 2026-10-19 + +## Result + +Let a(n) be the n-th smallest perimeter of a primitive Heronian isosceles triangle (integer sides with no common divisor, integer area, two sides equal). Let A096033(n) be the n-th smallest difference z - x, where x is a leg and z the hypotenuse of a primitive Pythagorean triangle. Then for every n ≥ 1, a(n) = 2 · A096033(n + 2). + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A308222](https://oeis.org/A308222) as [`Math0.Statements.A308222.statement`](../../lean/Math0/Statements/OEIS/A308222.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A308222.lean`](../../lean/Math0/Frontier/OEIS/A308222.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F a(n) = 2*A096033(n+2) (conjectured). (Peter Kagey, May 16 2019) + +Referees: Main prior resolution: Math StackExchange answer 3230072 by user "George", 2019-05-17 (https://math.stackexchange.com/a/3230072), answering Peter Kagey's question 3230019, "Semiperimeter of isosceles Heronian triangles". It is linked in the A308222 %H line. It derives that primitive isosceles Heronian triangles are (u^2+v^2, u^2+v^2, 2(u^2-v^2)) or (u^2+v^2, u^2+v^2, 4uv) with semiperimeters 2u^2 or (u+v)^2, citing J. R. Carlson, "Determination of Heronian Triangles", Fibonacci Quarterly 8 (1970) 499-506, Lemma 2. + +Also: Wikipedia, "Integer triangle", section "Isosceles Heronian triangles" (the same parametrization: two copies of a Pythagorean triangle joined along a leg). The A096033 comment (Weimholt, 2010) says A096033 is the odd squares together with the numbers 2n^2. + +No prior formalization found. OEIS A308222 (local mirror, #20, Aug 12 2022) still marks the formula "(conjectured)". + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a308222, + author = {{math0}}, + title = {{Perimeters of primitive Heronian isosceles triangles: A308222(n) = 2 · A096033(n + 2)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a308222}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a308222/paper.pdf b/results/oeis-a308222/paper.pdf new file mode 100644 index 0000000..99bc32b Binary files /dev/null and b/results/oeis-a308222/paper.pdf differ diff --git a/results/oeis-a308222/paper.tex b/results/oeis-a308222/paper.tex new file mode 100644 index 0000000..965c20a --- /dev/null +++ b/results/oeis-a308222/paper.tex @@ -0,0 +1,343 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {∧}{{$\wedge$}}1 + {∨}{{$\vee$}}1 {≤}{{$\le$}}1 {²}{{$^2$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 + {×}{{$\times$}}1 {∈}{{$\in$}}1 {≥}{{$\ge$}}1 {·}{{$\cdot$}}1 {…}{{$\dots$}}1 + {^}{{\textasciicircum}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\code}[1]{\texttt{#1}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Per}{\mathcal{P}} +\newcommand{\Leg}{\mathcal{L}} +\newcommand{\LegOK}{\mathrm{LegOK}} +\DeclareMathOperator{\cnt}{count} +\DeclareMathOperator{\nth}{nth} + +\title[Perimeters of primitive Heronian isosceles triangles]{Perimeters of primitive Heronian isosceles triangles: a formal proof that $\mathrm{A308222}(n)=2\cdot\mathrm{A096033}(n+2)$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 19, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the $n$-th smallest perimeter of a primitive Heronian isosceles triangle (OEIS A308222), and let $\mathrm{A096033}(n)$ be the $n$-th smallest difference between a leg and the hypotenuse of a primitive Pythagorean triangle. We prove that $a(n)=2\cdot\mathrm{A096033}(n+2)$ for every $n\ge1$, an identity that P.~Kagey recorded as a conjecture in 2019 and that the entry still marks as conjectured. The identity is a short consequence of the classical description of primitive isosceles Heronian triangles as two copies of a primitive Pythagorean triangle glued along a leg (Carlson 1970, corrected by Singmaster 1973), and a Mathematics Stack Exchange answer linked from the entry derives the relevant semiperimeters; we therefore classify our result as the first formal proof of a known result. Our proof shows directly that $2m$ is a perimeter if and only if $m\ge3$ is an odd square or twice a square, and transfers this to the two sequences by a counting argument. It is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, reviewed for fidelity, and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +A triangle is \emph{Heronian} if its side lengths and its area are integers, and \emph{primitive} if its three side lengths have no common divisor greater than $1$. The OEIS entry A308222 \cite{A308222}, contributed by Peter Kagey on May~16, 2019, is ``Numbers that are the perimeter of a primitive Heronian isosceles triangle'': $16,18,36,50,64,98,100,144,\dots$, starting with the triangles $(5,5,6)$ and $(5,5,8)$. Its FORMULA section relates it to A096033 \cite{A096033}, ``Difference between leg and hypotenuse in primitive Pythagorean triangles'': $1,2,8,9,18,25,32,49,50,\dots$ (Beedassy, 2004). The conjecture is that the perimeters are twice the leg--hypotenuse differences, with an index shift of two; Theorem~\ref{thm:main} proves it. + +\subsection*{Prior work} +The structure behind the identity is classical. Carlson \cite{Carlson} proved that every Heronian triangle is, up to scaling, two Pythagorean triangles joined along a common side. His Lemma~2 states that a primitive Heronian triangle is isosceles if and only if its sides are given by his general formulas with the two Pythagorean triangles taken equal, that is, $(u^2+v^2,\,u^2+v^2,\,2(u^2-v^2))$ or $(u^2+v^2,\,u^2+v^2,\,4uv)$, or a reduction of one of these; in other words, the triangle is two copies of one Pythagorean triangle. Singmaster \cite{Singmaster} pointed out errors in Carlson's paper (notably the use of the form $u^2+v^2,u^2-v^2,2uv$ for all Pythagorean triangles), remarked that Lemma~2 is unclearly stated, and gave a corrected form of it: the isosceles Heronian triangles are exactly $a(u^2+v^2),a(u^2+v^2),4auv$ and $a(u^2+v^2),a(u^2+v^2),2a(u^2-v^2)$, and such a triangle is primitive if and only if $a=1$, $\gcd(u,v)=1$ and $u\not\equiv v\pmod 2$. The same parametrization appears in the Wikipedia article \cite{Wiki}, which the entry links. On May~17, 2019, the day after creating the entry, Kagey asked on Mathematics Stack Exchange \cite{MSEq} for a characterization of the semiperimeters of (not necessarily primitive) isosceles Heronian triangles. An answer by the user ``George'' \cite{MSEa}, linked from A308222, quotes Carlson's lemma and concludes that the semiperimeters of the primitive ones are $2u^2$ and $(u+v)^2$. The answer states only this necessity direction; it does not state that every such value occurs, nor the identity with A096033. That A096033 consists of the odd squares and the numbers $2j^2$ is a comment in that entry (A.~Weimholt, 2010). + +From Singmaster's form of Lemma~2 the conjecture follows in a few lines (Remark~\ref{rem:lit}). Accordingly we classify our result as the \emph{first formal proof of a known result}. The math0 referees found no explicit statement and proof of the identity itself in the literature or in the cross-referenced OEIS entries, and no prior formalization; the current revision of A308222 (\#20, August~12, 2022) still marks it ``(conjectured)''. Our proof (Section~\ref{sec:proof}) works with the perimeter directly: it reduces the area condition to ``$m(2s-m)$ is a square'' and handles the two parities of $m$ by coprimality arguments, with explicit legs and B\'ezout certificates for the converse. + +\section{Statement}\label{sec:statement} + +\begin{definition}\label{def:main} +For $x,y,z\in\N$ let $H(x,y,z)=(x+y+z)(-x+y+z)(x-y+z)(x+y-z)\in\Z$. By Heron's formula, $H(x,y,z)=16\cdot\mathrm{area}^2$ for a triangle with sides $x,y,z$. +\begin{enumerate} +\item $\Per$ is the set of $P\in\N$ for which there are $x,y,z\in\N$ with $x+y+z=P$ such that: $x0$. Conversely, for odd $k$ the triple $(x,y,z)=(2k+2,\,k^2+2k,\,k^2+2k+2)$ satisfies $x^2+y^2=z^2$ and $z-x=k^2$; with $k=2t+1$, the identity $(t+1)x-y=1$ shows $\gcd(x,y)=1$. For $j\ge1$ the triple $(2j+1,\,2j^2+2j,\,2j^2+2j+1)$ satisfies $x^2+y^2=z^2$ and $z-x=2j^2$, and $(2j+1)x-2y=1$. +\end{proof} + +Consequently $\Leg\cap[0,3)=\{1,2\}$, and $\Leg$ is infinite because it contains $2(N+1)^2$ for every $N$ (\decl{infinite_L}, in the proof file). + +\begin{lemma}[\decl{sq_of_coprime_mul}]\label{lem:coprime} +If $a,b\in\N$ are coprime and $ab=c^2$, then $a$ is a perfect square. +\end{lemma} + +\begin{proof} +This is Mathlib's \decl{exists_eq_pow_of_mul_eq_pow}, applied in $\N$, where the only unit is $1$. +\end{proof} + +\begin{lemma}[\decl{isLegHypDiff_of_legOK}]\label{lem:nec} +If $\LegOK(m,s)$ holds for some $s$, then $m\in\Leg$. +\end{lemma} + +\begin{proof} +Write $2s=m+e$ with $e\ge1$, and let $h^2=me$. + +\emph{$m$ odd.} Then $\gcd(m,2)=1$ and $\gcd(m,s)=1$, so $\gcd(m,2s)=1$, and $\gcd(m,e)=\gcd(m,m+e)=\gcd(m,2s)=1$. By Lemma~\ref{lem:coprime}, $m$ is a square, and it is odd. + +\emph{$m=2m'$ even.} Since $2s=2m'+e$, $e=2f$ is even and $s=m'+f$. As $m'\mid m$ and $\gcd(s,m)=1$, $\gcd(m',s)=1$, hence $\gcd(m',f)=\gcd(m',m'+f)=1$. Now $h^2=4m'f$ is even, so $h=2r$ and $r^2=m'f$. By Lemma~\ref{lem:coprime}, $m'=k^2$, so $m=2k^2$; and $k\ge1$ because $m>s\ge1$. + +In both cases $m\in\Leg$ by Lemma~\ref{lem:L}. +\end{proof} + +\begin{lemma}[\decl{legOK_of_isLegHypDiff}]\label{lem:suff} +If $m\in\Leg$ and $m\ge3$, then $\LegOK(m,s)$ holds for some $s$. +\end{lemma} + +\begin{proof} +By Lemma~\ref{lem:L} there are two cases. + +\emph{$m$ an odd square.} Since $m\ge3$, $m=(2u+3)^2$ with $u\ge0$. Take $s=4(u+1)^2+1$, which is odd. Then +\[ + 2s-m=8u^2+16u+10-(4u^2+12u+9)=(2u+1)^2>0,\qquad m-s=4u+4>0, +\] +so $m<2s$, $s0$ and $m-s=(v+2)^2-(v+1)^2=2v+3>0$, so $m<2s$, $sv\ge1$, $\gcd(u,v)=1$ and $u\not\equiv v\pmod2$. Their semiperimeters are $(u+v)^2$ and $2u^2$, as in \cite{MSEa}. Here $u+v$ is odd and at least $3$, and every odd $k\ge3$ occurs, with $(u,v)=((k+1)/2,(k-1)/2)$; and $u\ge2$, where every $u\ge2$ occurs, with $v=u-1$. So the semiperimeters are the odd squares $\ge9$ and the numbers $2u^2$ with $u\ge2$, that is, by the characterization of A096033, the elements of $\Leg$ other than $1$ and $2$. This is Theorem~\ref{thm:set}, and Theorem~\ref{thm:main} follows by counting, as above. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A308222.lean} ($172$ lines) of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A308222.lean} without modifying it, proves \code{theorem result : statement} in the namespace \decl{Math0.Frontier.A308222}, and ends with +\begin{lstlisting} +#math0_settles Math0.Frontier.A308222.result Math0.Statements.A308222.statement +\end{lstlisting} +Lemmas~\ref{lem:legok} and~\ref{lem:L} are in the statement file. Lemmas~\ref{lem:coprime}, \ref{lem:nec}, \ref{lem:suff} and~\ref{lem:count}, Corollary~\ref{cor:per} and \decl{infinite_L} are private declarations of the proof file, named in Section~\ref{sec:proof}. The proof file contains two small evaluations by \code{decide} (the base case of Lemma~\ref{lem:count} and $\cnt_\Leg(2)=1$). The proof term that \code{decide} produces is checked by the kernel, which reduces the decidability instances; these instances are defined through \decl{decidable_of_iff} from Boolean searches proved equivalent to the predicates (\decl{perimB_iff}, \decl{legHypB_iff}). The kernel data checks of the statement file use \texttt{decide +kernel}. Neither file uses \texttt{native\_decide}, \texttt{sorry}, \texttt{set\_option}, or a declared axiom. + +\subsection*{Audit} +\texttt{\#math0\_settles} (in \path{lean/Math0/Audit.lean}) fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which excludes \decl{sorryAx}, the axioms behind \texttt{native\_decide}, and custom axioms; and (3) the type of \decl{result} is syntactically \decl{statement} or its negation, up to metadata, with no unfolding. Running \texttt{lake env lean Math0/Frontier/OEIS/A308222.lean} in \path{lean/} (about $10$--$20$ seconds) reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A308222.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A308222.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A308222.result' proves 'Math0.Statements.A308222.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}. The repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}; this conjecture is not in that collection, so math0 formalized it. To reproduce, run \path{scripts/verify.sh} from the repository root: it builds all math0 results with \texttt{lake build}, which re-runs every audit command, and checks that the pinned dependencies are unmodified. Building the statement file alone (\texttt{lake build Math0.Statements.OEIS.A308222}) takes about two minutes, almost all of it in the kernel data checks. Independently of the formal proof, the referees checked numerically that the perimeters up to $8000$ are $74$ numbers, of which the first $46$ are the listed terms, and that they satisfy $a(n)=2\cdot\mathrm{A096033}(n+2)$ for all $74$ indices. + +{\small +\begin{thebibliography}{99} + +\bibitem{Carlson} +J.~R. Carlson, \emph{Determination of Heronian triangles}, Fibonacci Quart.\ \textbf{8} (1970), no.~5, 499--506, 551. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{MSEa} +George (Mathematics Stack Exchange user), answer to \emph{Semiperimeter of isosceles Heronian triangles}, Mathematics Stack Exchange, May~17, 2019, \url{https://math.stackexchange.com/a/3230072}. + +\bibitem{MSEq} +P.~Kagey, \emph{Semiperimeter of isosceles Heronian triangles}, Mathematics Stack Exchange, question~3230019, May~17, 2019, \url{https://math.stackexchange.com/q/3230019}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput.\ Sci.\ \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A096033} +The OEIS Foundation Inc., \emph{Difference between leg and hypotenuse in primitive Pythagorean triangles}, \url{https://oeis.org/A096033}, entry by L.~Beedassy (Jun.~16, 2004). + +\bibitem{A308222} +The OEIS Foundation Inc., \emph{Numbers that are the perimeter of a primitive Heronian isosceles triangle}, \url{https://oeis.org/A308222}, entry by P.~Kagey (May~16, 2019), conjecture added May~17, 2019; revision \#20, Aug.~12, 2022. + +\bibitem{Singmaster} +D.~Singmaster, \emph{Some corrections to Carlson's ``Determination of Heronian triangles''}, Fibonacci Quart.\ \textbf{11} (1973), no.~2, 157--158. + +\bibitem{Wiki} +Wikipedia, \emph{Integer triangle}, section ``Isosceles Heronian triangles'', \url{https://en.wikipedia.org/wiki/Integer_triangle}, accessed October~2026. + +\end{thebibliography} +} +\end{document} diff --git a/results/oeis-a308359/README.md b/results/oeis-a308359/README.md new file mode 100644 index 0000000..7906905 --- /dev/null +++ b/results/oeis-a308359/README.md @@ -0,0 +1,36 @@ +# Fixed polyominoes with n cells and width n-2: T(n,n-2) = 8n^2 - 51n + 86 (A308359) + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A308359 +**Date:** 2026-10-19 + +## Result + +For every n >= 5, the number T(n, n-2) of fixed polyominoes with n cells whose convex hull has width n-2 equals 8n^2 - 51n + 86. A fixed polyomino is a finite edge-connected set of grid cells, taken up to translation. The statement file encodes it as the normalized set S in N x N that has min x = 0 and min y = 0. The height is unrestricted. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A308359](https://oeis.org/A308359) as [`Math0.Statements.A308359.statement`](../../lean/Math0/Statements/OEIS/A308359.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A308359.lean`](../../lean/Math0/Frontier/OEIS/A308359.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A308359 Conjecture: T(n,n-2) = 8*n^2 - 51*n + 86 for n >= 5. (Entry by _R. J. Mathar_, May 22 2019; last edit Oct 10 2022.) + +Referees: A. Goupil, H. Cloutier, F. Nouboud, "Enumeration of inscribed polyominos", FPSAC 2010, DMTCS proc. AN (2010) 737-748 (https://dmtcs.episciences.org/2808; hal-01186234; cited in OEIS A196593). Theorem 1 gives pmin(b,k) = 2k+2b-3bk-8+8*C(b+k-2,b-1), so pmin(w,3) = 4w^2-3w-2. Theorem 3 (k=2, b>2) gives pmin+1(b,2) = 4b^2-16b+18. Since T(n,n-2) = pmin(n-2,3) + pmin+1(n-2,2) = 8(n-2)^2-19(n-2)+16 = 8n^2-51n+86, Mathar's 2019 conjecture follows directly. The OEIS A308359 entry (last edited Oct 2022) still says "Conjecture" and has no proof note. Related but not resolving: L. Marin, "Counting Polyominoes in a Rectangle b x h", arXiv:2406.16413 (EPTCS 403, 2024), which covers fixed width and any height. I found no MathOverflow, Math StackExchange or SeqFan discussion explicitly proving the A308359 formula. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a308359, + author = {{math0}}, + title = {{Fixed polyominoes with n cells and width n-2: T(n,n-2) = 8n^2 - 51n + 86 (A308359)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a308359}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a308359/paper.pdf b/results/oeis-a308359/paper.pdf new file mode 100644 index 0000000..d5f55e0 Binary files /dev/null and b/results/oeis-a308359/paper.pdf differ diff --git a/results/oeis-a308359/paper.tex b/results/oeis-a308359/paper.tex new file mode 100644 index 0000000..f0d3546 --- /dev/null +++ b/results/oeis-a308359/paper.tex @@ -0,0 +1,339 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{booktabs} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {∧}{{$\wedge$}}1 + {∨}{{$\vee$}}1 {≤}{{$\le$}}1 {²}{{$^2$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 + {×}{{$\times$}}1 {∈}{{$\in$}}1 {≥}{{$\ge$}}1 {·}{{$\cdot$}}1 {…}{{$\dots$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\code}[1]{\texttt{#1}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\tru}{\mathsf{t}} +\newcommand{\fls}{\mathsf{f}} + +\title[Fixed polyominoes with $n$ cells and width $n-2$]{Fixed polyominoes with $n$ cells and width $n-2$: a formal proof of $T(n,n-2)=8n^2-51n+86$ (OEIS A308359)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 19, 2026} + + +\begin{document} +\begin{abstract} +Let $T(n,w)$ be the number of fixed polyominoes with $n$ cells whose bounding box has width $w$ (OEIS A308359). We prove that $T(n,n-2)=8n^2-51n+86$ for every $n\ge5$, which R.~J. Mathar recorded as a conjecture in the entry in 2019. The formula can also be derived from two theorems of Goupil, Cloutier and Nouboud (2010) on polyominoes inscribed in a rectangle, so we classify our result as the first formal proof of a known result. Our proof is self-contained: it shows that such a polyomino lies in a strip of height $3$ and has interval columns, and counts these shapes with a $36$-state transfer matrix, whose counting vector has quadratic polynomials in the width as entries. It is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, reviewed for fidelity, and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +A \emph{fixed polyomino} with $n$ cells is a set of $n$ unit squares of the square grid, connected through shared edges, taken up to translation only. Their number is OEIS A001168 \cite{A001168}. The triangle A308359 \cite{A308359}, contributed by R.~J. Mathar on May~22, 2019, refines this count: ``Triangle T(n,w) read by rows: the number of fixed polyominoes with n cells and width w of the convex hull.'' Its rows for $n\le7$ are $1$; $1,1$; $1,4,1$; $1,9,8,1$; $1,18,31,12,1$; $1,35,95,68,16,1$; $1,66,269,282,121,20,1$. The entry gives $T(n,1)=T(n,n)=1$ and $T(n,n-1)=4n-8$ for $n\ge3$, and its FORMULA section, part of Mathar's entry, states +\begin{quote} +``\verb|Conjecture: T(n,n-2) = 8*n^2 - 51*n + 86 for n >= 5.|'' +\end{quote} +The column $w=3$ is A335606 \cite{A335606}, and A292357 \cite{A292357} counts fixed polyominoes by width and height. In the current revision of A308359 (\#23, October~10, 2022) the formula is still marked as a conjecture, and no proof is recorded. We prove it (Theorem~\ref{thm:main}). + +\subsection*{Prior work} +The math0 literature referee observed that the formula follows from results of Goupil, Cloutier and Nouboud \cite{GCN}, published nine years before the conjecture. They count the polyominoes \emph{inscribed} in a $b\times k$ rectangle (that is, with this bounding box) that have the minimum number $b+k-1$ of cells, $p_{\min}(b,k)$, and those with $b+k$ cells, $p_{\min+1}(b,k)$. A polyomino of width $w$ with $w+2$ cells has height $3$ (minimum area) or $2$ (minimum area plus one), so $T(w+2,w)=p_{\min}(w,3)+p_{\min+1}(w,2)$, and their Theorems~1 and~3 evaluate this to $8w^2-19w+16$ (Remark~\ref{rem:gcn}). This consequence is not stated in \cite{GCN}, which predates the triangle, and the referees found no place where it is drawn: the OEIS entry records no proof, and they found none on arXiv, MathOverflow, Mathematics Stack Exchange or the SeqFan list. Marin \cite{Ma} constructs automata for polyominoes inscribed in a rectangle of fixed width and growing height; this does not address the diagonal $w=n-2$. Since the statement follows from published theorems, we classify our result as the \emph{first formal proof of a known result}. Our proof (Section~\ref{sec:proof}) does not port the case analysis of \cite{GCN}: it reduces the count to a transfer matrix on $36$ states and certifies quadratic closed forms by finite computations that the Lean kernel checks. + +\section{Statement}\label{sec:statement} + +We write cells as pairs $(x,y)\in\N^2$, with column $x$ and row $y$. Two cells are \emph{adjacent} if they agree in one coordinate and differ by $1$ in the other, and a finite set $S\subseteq\N^2$ is \emph{connected} if any two of its cells are joined by a chain of cells of $S$ in which consecutive cells are adjacent. Each translation class of finite nonempty sets of cells of $\Z^2$ contains exactly one set $S\subseteq\N^2$ that meets both the column $x=0$ and the row $y=0$. Its bounding box (equivalently, its convex hull) has width $\max_{p\in S}p_x+1$. + +\begin{definition}\label{def:T} +A \emph{normalized polyomino with $n$ cells and width $w$} is a connected set $S\subseteq\N^2$ with $|S|=n$ that meets the column $x=0$ and the row $y=0$ and has $\max_{p\in S}p_x+1=w$. Let $T(n,w)$ be the number of these sets. +\end{definition} + +\begin{theorem}[Mathar's conjecture]\label{thm:main} +For every integer $n\ge5$, $T(n,n-2)=8n^2-51n+86$. Equivalently, $T(w+2,w)=8w^2-19w+16$ for every $w\ge3$. +\end{theorem} + +For $n=5,\dots,11$ the formula gives the listed values $31,68,121,190,275,376,493$. For $w=1,2$ it fails: $T(3,1)=1$ and $T(4,2)=9$, while $8w^2-19w+16$ equals $5$ and $10$. + +\subsection*{The Lean statement} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A308359.lean}, reviewed for fidelity against the OEIS entry, and frozen (SHA-256 \texttt{84eea4b2\ldots80f7}) before any proof attempt. Its definitions (without their docstrings and without the \code{DecidableRel} instance for \code{Adj}) and the statement (with its docstring) read verbatim, in the namespace \decl{Math0.Statements.A308359}: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +def Adj (p q : ℕ × ℕ) : Prop := + (p.1 = q.1 ∧ (p.2 + 1 = q.2 ∨ q.2 + 1 = p.2)) ∨ (p.2 = q.2 ∧ (p.1 + 1 = q.1 ∨ q.1 + 1 = p.1)) +def Step (S : Finset (ℕ × ℕ)) (p q : ℕ × ℕ) : Prop := p ∈ S ∧ q ∈ S ∧ Adj p q +def IsConnected (S : Finset (ℕ × ℕ)) : Prop := + ∀ p ∈ S, ∀ q ∈ S, Relation.ReflTransGen (Step S) p q +def IsPoly (n w : ℕ) (S : Finset (ℕ × ℕ)) : Prop := + S.card = n ∧ (∃ p ∈ S, p.1 = 0) ∧ (∃ p ∈ S, p.2 = 0) ∧ S.sup Prod.fst + 1 = w ∧ IsConnected S +noncomputable def T (n w : ℕ) : ℕ := {S : Finset (ℕ × ℕ) | IsPoly n w S}.ncard + +/-- Conjecture (Mathar, A308359): for every `n ≥ 5`, the number of fixed polyominoes with `n` +cells and width `n - 2` is `T(n, n - 2) = 8n² - 51n + 86`. -/ +def statement : Prop := + ∀ n : ℕ, 5 ≤ n → (T n (n - 2) : ℤ) = 8 * (n : ℤ) ^ 2 - 51 * n + 86 +\end{lstlisting} + +\subsection*{How the Lean definitions encode the entry} +\code{IsPoly n w S} is Definition~\ref{def:T}: \code{IsConnected} is connectivity through chains of adjacent cells (the reflexive--transitive closure of \code{Step S}), and \code{S.sup Prod.fst} is $\max_{p\in S}p_x$. \code{T} counts with \decl{Set.ncard}, which returns $0$ on infinite sets; this junk value does not arise, since the statement file proves (\decl{T_eq_Tbox}) that every such $S$ lies in the box $[0,w)\times[0,n+1-w)$ (Lemma~\ref{lem:box}), so that $T(n,w)$ equals a computable count \code{Tbox n w} over the $n$-element subsets of the box. For $n\ge5$ the truncated subtraction $n-2$ in $\N$ is exact, and the right-hand side is computed in $\Z$. + +Only the width is prescribed. The comment line of the entry says that the height $h$ satisfies $w\le h\le n$, but the entry contradicts this: $T(4,3)=8$ counts the eight tetrominoes of width $3$, all of height $2$; the formula $T(n,n-1)=4n-8$ is annotated ``width n-1 and height 2''; and the row sums are A001168. Under the restriction $h\ge w$ the listed $T(6,4)=68$ would be $0$, since a polyomino of width $4$ with $6$ cells has height at most $3$ (Lemma~\ref{lem:box}). The formalization follows the data. To check it against the data, the statement file defines the triangle read by rows, \code{a}, proves $a(n(n-1)/2+w)=T(n,w)$ for $1\le w\le n$ (\decl{a_eq_T}), and proves, by four \texttt{decide +kernel} computations, that $a(1),\dots,a(23)$ are the first $23$ listed terms (\decl{a_data}: rows $1$ to $6$, $T(7,1)=1$, $T(7,2)=66$), including the first two values $T(5,3)=31$ and $T(6,4)=68$ of the conjecture. For this evaluation, connectivity is decided by a flood fill on bit masks, proved equivalent to \code{IsConnected} (\decl{isConnected_iff_bits}). + +\section{Proof}\label{sec:proof} + +The \emph{column} $x$ of $S\subseteq\N^2$ is $S_x=\{y:(x,y)\in S\}$, and $[a,b]=\{y\in\N: a\le y\le b\}$. The first three lemmas are proved in the statement file. + +\begin{lemma}[\decl{frontier}, \decl{exists_coord}]\label{lem:chain} +Let $c_0,\dots,c_m$ be a chain in $S$. (1) If $c_0\in A$ and $c_m\notin A$, then some cell of $A\cap S$ is adjacent to some cell of $S\setminus A$. (2) If $f$ is one of the two coordinates, every integer $k$ between $f(c_0)$ and $f(c_m)$ equals $f(c)$ for some $c\in S$. +\end{lemma} + +\begin{proof} +(1) If $j$ is the first index with $c_j\notin A$, then $c_{j-1}\in A$ is adjacent to $c_j$. (2) Each step changes $f$ by at most $1$. +\end{proof} + +\begin{lemma}[\decl{cols_add_rows_le}]\label{lem:colsrows} +If $S$ is nonempty, connected, and occupies $C$ columns and $R$ rows, then $C+R\le|S|+1$. +\end{lemma} + +\begin{proof} +Start from one cell, which occupies $1+1$ columns and rows. While some cell of $S$ is not yet taken, Lemma~\ref{lem:chain}(1) (applied to a chain from a taken cell to an untaken one) gives an untaken cell $c$ adjacent to a taken cell $b$. Take $c$. As $c$ shares its column or its row with $b$, the number of occupied columns and rows grows by at most $1$ per cell. +\end{proof} + +\begin{lemma}[\decl{subset_box}]\label{lem:box} +A normalized polyomino $S$ with $n$ cells and width $w$ lies in $[0,w)\times[0,n+1-w)$, and its columns $S_0,\dots,S_{w-1}$ are nonempty. +\end{lemma} + +\begin{proof} +Lemma~\ref{lem:chain}(2), applied to a chain from a cell in column $0$ to a cell in column $w-1$, shows that all $w$ columns $0,\dots,w-1$ are occupied. For $p\in S$, a chain from a cell in row $0$ to $p$ shows that the rows $0,\dots,p_y$ are occupied. By Lemma~\ref{lem:colsrows}, $w+p_y+1\le n+1$. Finally $p_x\le w-1$ by the definition of the width. +\end{proof} + +From now on $w\ge1$ and $n=w+2$. By Lemma~\ref{lem:box}, a normalized polyomino with $w+2$ cells and width $w$ lies in $[0,w)\times\{0,1,2\}$ and has $w$ nonempty columns, so +\begin{equation}\label{eq:excess} + \textstyle\sum_{xk$ contains a vertical step from some $(c,k)$ to $(c,k+1)$, namely its first step into a row $>k$ (\decl{cross}). Suppose $(x,0),(x,2)\in S$ and $(x,1)\notin S$. Applying this to a chain from $(x,0)$ to $(x,2)$ with $k=0$ and with $k=1$ gives columns $c_1,c_2$ with $\{0,1\}\subseteq S_{c_1}$ and $\{1,2\}\subseteq S_{c_2}$, both different from $x$ because $1\notin S_x$. If $c_1=c_2$, then $|S_{c_1}|-1\ge2$ and $|S_x|-1\ge1$; otherwise $x,c_1,c_2$ are three distinct columns with $|S_\cdot|-1\ge1$. Either way $\sum_{x'2$; the sum is $8w^2-19w+16$ (for $w=3,4$: $25+6$ and $50+18$). Theorem~1 with $k=2$ also gives the entry's $T(n,n-1)=p_{\min}(n-1,2)=4n-8$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files, declarations and kernel computations} +The proof, about $750$ lines, is the file \path{lean/Math0/Frontier/OEIS/A308359.lean} of the math0 repository \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file without modifying it, proves \code{theorem result : statement} in the namespace \decl{Math0.Frontier.A308359}, and ends with +\begin{lstlisting} +#math0_settles Math0.Frontier.A308359.result Math0.Statements.A308359.statement +\end{lstlisting} +Section~\ref{sec:proof} names the declaration behind each step; Lemmas~\ref{lem:chain}--\ref{lem:box} are in the statement file, the rest are private declarations of the proof file, where $P(w,s)$ is \code{Pset w s}, a filter of the powerset of $[0,w)\times[0,3)$. Five finite facts are proved by \texttt{decide +kernel}: \decl{D_three} (the base case of Lemma~\ref{lem:poly}), \decl{coefA}, \decl{coefB}, \decl{coefC} (the identities \eqref{eq:coef} for all $36$ states), and \decl{final_sum}. With \texttt{decide +kernel} the Lean kernel itself reduces the \code{Decidable} instance of the proposition to \code{isTrue}, so these steps add no axioms and trust no compiled code; the first four carry \texttt{set\_option maxHeartbeats 4000000}, a resource limit. Neither file uses \texttt{native\_decide}, \texttt{sorry}, or a declared axiom. + +\subsection*{Audit} +\texttt{\#math0\_settles} (in \path{lean/Math0/Audit.lean}) fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (excluding \decl{sorryAx}, the axioms behind \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically \decl{statement} or its negation, up to metadata, with no unfolding. It reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A308359.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A308359.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A308359.result' proves 'Math0.Statements.A308359.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}. The repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}; this conjecture is not in that collection, so math0 formalized it. To reproduce, run \path{scripts/verify.sh} from the repository root: it builds all math0 results with \texttt{lake build}, re-running every audit command, and checks that the pinned dependencies are unmodified. The single file is checked by \texttt{lake env lean Math0/Frontier/OEIS/A308359.lean} in \path{lean/}. Independently of the formal proof, the referees checked the formula numerically: an enumeration of all fixed polyominoes with up to $13$ cells agreed with the listed terms, and a column transfer matrix with full connectivity tracking, not using Proposition~\ref{prop:struct}, confirmed it for $5\le n\le32$. + +{\small +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026; \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{GCN} +A.~Goupil, H.~Cloutier, F.~Nouboud, \emph{Enumeration of inscribed polyominos}, in: 22nd International Conference on Formal Power Series and Algebraic Combinatorics (FPSAC 2010), Discrete Math.\ Theor.\ Comput.\ Sci.\ Proc.\ \textbf{AN} (2010), 737--748, doi:10.46298/dmtcs.2808. + +\bibitem{Ma} +L.~Marin, \emph{Counting polyominoes in a rectangle $b\times h$}, in: Proceedings of GASCom 2024, Electron.\ Proc.\ Theor.\ Comput.\ Sci.\ \textbf{403} (2024), 145--149, doi:10.4204/EPTCS.403.30; arXiv:2406.16413. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput.\ Sci.\ \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A001168} +The OEIS Foundation Inc., \emph{Number of fixed polyominoes with $n$ cells}, \url{https://oeis.org/A001168}. + +\bibitem{A292357} +The OEIS Foundation Inc., \url{https://oeis.org/A292357}, entry by A.~Howroyd (Oct.~2, 2017). + +\bibitem{A308359} +The OEIS Foundation Inc., \url{https://oeis.org/A308359}, entry and conjecture by R.~J. Mathar (May~22, 2019); revision \#23, Oct.~10, 2022. + +\bibitem{A335606} +The OEIS Foundation Inc., \url{https://oeis.org/A335606}, entry by R.~J. Mathar (Jun.~15, 2020). + +\end{thebibliography} +} +\end{document} diff --git a/results/oeis-a320099/README.md b/results/oeis-a320099/README.md new file mode 100644 index 0000000..e5f7831 --- /dev/null +++ b/results/oeis-a320099/README.md @@ -0,0 +1,46 @@ +# Kagey's order-10 recurrence for no-leaf subgraphs of the 5 × n grid holds + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A320099 +**Date:** 2026-10-29 + +## Result + +Let a(n) be the number of edge subsets S of the 5 × n grid graph (all vertices kept) such that no vertex has degree exactly 1 in S (OEIS A320099). Then for every n > 10, a(n) = 103 a(n-1) + 1063 a(n-2) - 1873 a(n-3) - 20274 a(n-4) + 44071 a(n-5) - 10365 a(n-6) - 20208 a(n-7) + 5959 a(n-8) + 2300 a(n-9) - 500 a(n-10). This is an identity of integers. + +## Assessment + +The proof writes a(n) as an entry of the n-th power of the standard 32 x 32 column transfer matrix, which is the textbook way to count local subgraph patterns on a strip of fixed width. The recurrence then follows from one finite linear identity among the first 11 rows of powers of T, checked by direct computation, and multiplying that identity by T^m extends it to every n. No new idea was needed: the method is standard, and once set up the conjecture is a finite computation. Most of the Lean work goes into formalizing the edge-set/column-data bijection, and that effort does not make the mathematics substantial. + +*Follows from:* Standard column transfer-matrix method (e.g. Raff, arXiv:0809.2551). A 32 x 32 matrix T has rows and columns indexed by the sets of horizontal edges between adjacent columns, and a(n) = (T^n)[0,0]. The recurrence then reduces to a finite check: the row vector e_0 is annihilated by x*P(T), where P is Kagey's characteristic polynomial. A Cayley-Hamilton argument does the same job. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A320099](https://oeis.org/A320099) as [`Math0.Statements.A320099.statement`](../../lean/Math0/Statements/OEIS/A320099.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A320099.lean`](../../lean/Math0/Frontier/OEIS/A320099.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A320099 Conjecture: a(n) = 103*a(n-1) + 1063*a(n-2) - 1873*a(n-3) - 20274*a(n-4) + 44071*a(n-5) - 10365*a(n-6) - 20208*a(n-7) + 5959*a(n-8) + 2300*a(n-9) - 500*a(n-10) for n > 10. (_Peter Kagey_, Oct 05 2018) + +Referees: - OEIS A320099 (Peter Kagey, Oct 05 2018; latest revision #20, Jun 09 2019): the recurrence is still listed as "Conjecture", with no proof recorded. +- Related entries with no proof for 5×n: A320097 (4×n; Kagey's conjecture and Colin Barker's empirical generating function, both unproved in OEIS), A301976 (3×n, Barker's conjectures), A320101 (the n×k table) and A093129 (2×n). +- Prior formal work on a different sequence: the-omega-institute/trureturing issue #7458 and PR #7536 (Sep 13, 2026) give a Lean transfer-matrix proof of the 3×n recurrence (A301976). The repository has no issue or pull request for A320099 or A320097. +- Peter Kagey's problem page https://peterkagey.com/problems/083/ covers only the 2×n case. +- General transfer-matrix background: Raff, arXiv:0809.2551; Golin et al., ANALCO 2005. +- No arXiv, MathOverflow, Math StackExchange or SeqFan source proving or refuting the order-10 recurrence for the 5×n grid was found. + +## Citation + +```bibtex +@misc{math0:oeis-a320099, + author = {{math0}}, + title = {{Kagey's order-10 recurrence for no-leaf subgraphs of the 5 × n grid holds}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a320099}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a323695/README.md b/results/oeis-a323695/README.md new file mode 100644 index 0000000..64c45e8 --- /dev/null +++ b/results/oeis-a323695/README.md @@ -0,0 +1,45 @@ +# Odd terms of A323695 occur only at n = k(k+2) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Sequences and series +**Source problem:** OEIS A323695 +**Date:** 2026-10-18 + +## Result + +Let a(N) be the coefficient of x^N in Sum_{m>=0} x^m (1 - x^(m+1))^m / (1 + x^(m+1))^(m+1) (OEIS A323695, offset 0). If a(n) is odd, then n = k(k+2) for some natural number k. Equivalently, if a(n) is odd then n + 1 is a perfect square. + +## Assessment + +The proof reduces the generating function modulo 2. There the numerator and denominator of each summand have the same base, so the m-th summand cancels down to x^m/(1+x^(m+1)). The sum is then the classical Lambert series for the divisor function, so a(n) is congruent mod 2 to d(n+1), and d(n+1) is odd exactly when n+1 is a square, by pairing each divisor d with N/d. This is a few lines of standard reasoning that a competent mathematician would find almost at once; the manuscript itself calls the result elementary. Unlike the sibling entries A323557 and A325046, nothing fails to cancel here, and the conjecture is the intended statement, not a degenerate reading of it. + +*Follows from:* Reduce the entry's own g.f. modulo 2. Since 1 - x^(m+1) = 1 + x^(m+1) mod 2, each summand becomes x^m/(1+x^(m+1)), and the series becomes the standard Lambert series Sum_m x^m/(1-x^(m+1)) = Sum_n d(n+1) x^n. The classical fact that d(N) is odd iff N is a perfect square finishes the proof. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A323695](https://oeis.org/A323695) as [`Math0.Statements.A323695.statement`](../../lean/Math0/Statements/OEIS/A323695.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A323695.lean`](../../lean/Math0/Frontier/OEIS/A323695.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: A323695 (G.f.: Sum_{n>=0} x^n (1 - x^(n+1))^n/(1 + x^(n+1))^(n+1)): "Odd terms occur only at n = k*(k+2) for k >= 0 (conjecture);" (_Paul D. Hanna_, Feb 23 2019). A324300 (G.f.: Sum_{n>=0} x^n (x^(n+1)+i)^n/(1 + i x^(n+1))^(n+1)): "Odd terms occur only at n = k*(k+2) for k >= 0 (conjecture);" (Hanna, Feb 21 2019). + +Referees: OEIS A323695 (Hanna, Feb 23 2019; still labeled "(conjecture)" at rev #24, Dec 15 2024; history checked) and its cross-references A323696, A324300 (same conjecture for an i-variant, also unproved), A323675 and A323680. Sibling results proved by others, which do not cover A323695: A325046, odd terms iff N = m(m+1), in S. Fried, "Further proofs of conjectures from the OEIS", arXiv:2607.24832 (Thm 50), also in google-deepmind/alphaproof-nexus-results; A323557, odd terms at r(r+1), in T. Adamczewski, "OEIS Open", arXiv:2608.11941 and AlphaProof Nexus (Tsoukalas et al.). A323695 is in neither google-deepmind/formal-conjectures nor epoch-research/LeanOpenProblems. It is not mentioned in Fried's arXiv:2410.07237 (JIS 25.4.3), JIS 26.1.8 or arXiv:2606.09913. MathOverflow, Math StackExchange and SeqFan searches found nothing. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a323695, + author = {{math0}}, + title = {{Odd terms of A323695 occur only at n = k(k+2)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a323695}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a323695/paper.pdf b/results/oeis-a323695/paper.pdf new file mode 100644 index 0000000..ab48f49 Binary files /dev/null and b/results/oeis-a323695/paper.pdf differ diff --git a/results/oeis-a323695/paper.tex b/results/oeis-a323695/paper.tex new file mode 100644 index 0000000..16d0eec --- /dev/null +++ b/results/oeis-a323695/paper.tex @@ -0,0 +1,366 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,rw,at,by_contra,ring,generalize,split_ifs}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={∑}{{$\sum$}}1 {∈}{{$\in$}}1 {ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 + {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {≤}{{$\le$}}1 + {≠}{{$\ne$}}1 {∧}{{$\wedge$}}1 {∣}{{$\mid$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 + {…}{{$\ldots$}}1 {¬}{{$\neg$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{…}{\ensuremath{\ldots}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\F}{\mathbb{F}_2} +\newcommand{\coef}[1]{[x^{#1}]} + +\title[Odd coefficients of the generating function of OEIS A323695]{The coefficients of $\sum_{m\ge0}x^m(1-x^{m+1})^m/(1+x^{m+1})^{m+1}$ are odd only at indices $k(k+2)$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the coefficient of $x^n$ in $\sum_{m\ge0}x^m(1-x^{m+1})^m/(1+x^{m+1})^{m+1}$, the sequence A323695 of the OEIS. +In 2019 P.~D.~Hanna conjectured that the odd terms occur only at $n=k(k+2)$, $k\ge0$. +We prove this conjecture: modulo $2$ the $m$-th summand reduces to $x^m/(1+x^{m+1})$, so $a(n)$ is congruent modulo $2$ to the number of divisors of $n+1$, which is odd only when $n+1$ is a perfect square; the same argument gives the converse, which is also recorded in the entry. +To our knowledge this is a new, though elementary, result: the conjecture is still marked as open in the OEIS, and we found no proof in the literature. +The proof is checked in Lean~4 against a statement that math0 formalized from the OEIS entry; there the sequence is proved equal to the coefficients of the generating function and is checked by the kernel against all $121$ listed terms. This statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +The OEIS entry A323695, contributed by Paul D.~Hanna on February~23, 2019 \cite{A323695}, is the sequence of coefficients of the power series +\begin{equation}\label{eq:gf} + A(x)=\sum_{n\ge0}a(n)x^n=\sum_{m\ge0}\frac{x^m\,(1-x^{m+1})^m}{(1+x^{m+1})^{m+1}} + =1+2x^2-3x^3+2x^4+2x^6-14x^7+15x^8+\cdots. +\end{equation} +The entry lists the terms $a(0),\dots,a(120)$ and links a table of $a(n)$ for $n\le 10201$, both by Hanna. Its first comment is the conjecture that odd terms occur only at $n=k(k+2)$. Its formula section states, without proof, the converse $a(n(n+2))\equiv1\pmod2$, as well as $a(4n+1)=0$ and $a(p-1)=2$ for odd primes~$p$. The terms $a(k(k+2))$ form the sequence A323696 \cite{A323696}. + +Hanna contributed several related series of the shape $\sum_m x^m P_m(x)^m/Q_m(x)^{m+1}$ with parity conjectures of the same kind. For A324300 \cite{A324300}, with summands $x^m(x^{m+1}+i)^m/(1+ix^{m+1})^{m+1}$, the entry conjectures that odd terms occur only at $n=k(k+2)$; this conjecture is also still marked as open, and we know of no proof. For A323557 and A325046 \cite{A323557,A325046}, with summands $x^m(1+x^m)^m/(1+x^{m+1})^{m+1}$ and $x^m(1+x^m)^m/(1-x^{m+1})^{m+1}$, the conjecture is that odd terms occur only at $n=m(m+1)$. Both of these have been settled. Fried proved the A325046 conjecture in a note attached to the entry \cite{FriedNote}, and again in \cite[pp.~50--51]{Fried}. The AI system AlphaProof Nexus \cite{APN} produced Lean proofs of both conjectures, and the two entries also point to a proof in Adamczewski's study \cite{Ad}. In those two cases the factors $(1+x^m)^m$ and $(1\pm x^{m+1})^{m+1}$ do not cancel modulo~$2$, and the published arguments are longer. For A323695 the numerator and denominator have the same base modulo~$2$, and the proof below is short. + +\subsection*{Status and prior work} +The comment in A323695 is still tagged ``(conjecture)'' in the current revision~\#24 (December~15, 2024). The edit history of the entry consists of Hanna's own edits of February~23--24, 2019, which built up the entry, and a change to a cross-reference in December~2024; no revision mentions a proof. The math0 referees also checked the cross-referenced entries A323675, A323680, A323696 and A324300; none contains a proof. A323695 is not among the OEIS statements of the formal-conjectures repository \cite{FC}, nor among the $492$ OEIS conjectures of the OEIS Open benchmark \cite{Ad}. The proofs of the sibling conjectures cited above \cite{FriedNote,Fried,APN,Ad} do not treat A323695, and it is not mentioned in Fried's earlier papers on OEIS conjectures that the referees checked. Searches of MathOverflow, Mathematics Stack Exchange and the SeqFan mailing list found nothing. We therefore classify the result as \emph{new}, with the caveat that it is elementary: once the series is reduced modulo~$2$, the argument takes a few lines. + +\section{Statement}\label{sec:statement} + +All power series have integer coefficients unless stated otherwise, and $\coef{N}f$ denotes the coefficient of $x^N$ in~$f$. For $m\ge0$ the series $(1+x^{m+1})^{m+1}$ has constant term~$1$, so it is a unit of $\Z[[x]]$. + +\begin{definition}\label{def:main} +For $m\ge0$ let +\[ + S_m=x^m(1-x^{m+1})^m\,(1+x^{m+1})^{-(m+1)}\in\Z[[x]], +\] +and for $N\ge0$ let $a(N)=\sum_{m=0}^{N}\coef{N}S_m$. +\end{definition} + +Since $S_m\in x^m\Z[[x]]$, the series $\sum_{m\ge0}S_m$ converges $x$-adically, and $a(N)$ is the coefficient of $x^N$ in its sum. So $a$ is the sequence A323695 with offset~$0$. The comment section of the entry contains, verbatim: +\begin{quote} +\texttt{Odd terms occur only at n = k*(k+2) for k >= 0 (conjecture);} +\end{quote} +The entry, including this comment, is by Paul D.~Hanna, February~23, 2019. + +\begin{theorem}\label{thm:main} +For every $n\ge0$, if $a(n)$ is odd, then $n=k(k+2)$ for some integer $k\ge0$. Equivalently, if $a(n)$ is odd, then $n+1$ is a perfect square. +\end{theorem} + +The proof also gives the converse and an exact description of the parity; only Theorem~\ref{thm:main} is formalized, together with the congruence of Lemma~\ref{lem:cast} in the form $a(N)\equiv\#\{m\le N:(m+1)\mid(N+1)\}\pmod 2$ (the identification of this count with $d(N+1)$ is not formalized). + +\begin{theorem}\label{thm:full} +For every $N\ge0$, $a(N)\equiv d(N+1)\pmod 2$, where $d$ is the number-of-divisors function. Consequently, $a(N)$ is odd if and only if $N=k(k+2)$ for some $k\ge0$. +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A323695.lean}. It was reviewed for fidelity and frozen (SHA-256 \texttt{6d745374\ldots 8edd}) before any proof attempt. The definitions and the statement are, verbatim except that docstrings are omitted: +\begin{lstlisting} +namespace Math0.Statements.A323695 +open PowerSeries + +noncomputable def summand (m : ℕ) : PowerSeries ℤ := + X ^ m * (1 - X ^ (m + 1)) ^ m * invOfUnit ((1 + X ^ (m + 1)) ^ (m + 1)) 1 + +noncomputable def A : PowerSeries ℤ := + mk fun N => ∑ m ∈ Finset.range (N + 1), coeff N (summand m) + +def binom (n k : ℕ) : ℕ := n.descFactorial k / k.factorial + +def term (N m i : ℕ) : ℤ := + if (m + 1) * i + m ≤ N ∧ (N - ((m + 1) * i + m)) % (m + 1) = 0 then + (-1) ^ i * (binom m i : ℤ) * + ((-1) ^ ((N - ((m + 1) * i + m)) / (m + 1)) * + (binom (m + (N - ((m + 1) * i + m)) / (m + 1)) m : ℤ)) + else 0 + +def coeffA (N : ℕ) : ℤ := + ∑ m ∈ Finset.range (N + 1), + if (N + 1) % (m + 1) = 0 then ∑ i ∈ Finset.range (m + 1), term N m i else 0 + +def a (N : ℕ) : ℤ := coeffA N + +def statement : Prop := + ∀ n : ℕ, Odd (a n) → ∃ k : ℕ, n = k * (k + 2) +\end{lstlisting} +The file also proves the following facts, which tie these definitions to Definition~\ref{def:main} and to the OEIS data (proofs omitted, data list abbreviated): +\begin{lstlisting} +theorem summand_spec (m : ℕ) : + (1 + X ^ (m + 1)) ^ (m + 1) * summand m = X ^ m * (1 - X ^ (m + 1)) ^ m +theorem hasSum_summand : HasSum summand A +theorem a_eq_coeff (N : ℕ) : a N = coeff N A +theorem a_data : (List.range 121).map (fun i => a (i + 0)) = + [1, 0, 2, -3, 2, 0, 2, -14, 15, 0, 2, -22, …, 3769924, -15721720, 8097455] +\end{lstlisting} + +\emph{Encoding.} \texttt{invOfUnit f 1} is the inverse of a power series $f$ with constant coefficient~$1$, so \texttt{summand m} is $S_m$, as \decl{summand_spec} records. \decl{A} is defined coefficientwise as the finite sum of Definition~\ref{def:main}, and \decl{hasSum_summand} proves that it is the sum of the family $(S_m)_{m\ge0}$ in the product topology on $\Z[[x]]$. The sequence \decl{a} itself is given by an explicit formula, so that the kernel can evaluate it. Expanding $(1-y)^m=\sum_i(-1)^i\binom{m}{i}y^i$ and $(1+y)^{-(m+1)}=\sum_q(-1)^q\binom{m+q}{m}y^q$ with $y=x^{m+1}$, the term with indices $i,q$ contributes to $x^N$ exactly when $N=m+(m+1)(i+q)$; this is \texttt{term N m i}, with $q=(N-(m+1)i-m)/(m+1)$. Such a term exists only if $m+1$ divides $N+1$, so \decl{coeffA} skips the other values of~$m$; the lemma \decl{term_eq_zero} justifies the skip. The theorem \decl{a_eq_coeff} proves $a(N)=\coef{N}A$ for every~$N$, so the explicit formula is a theorem, not part of the definition of the sequence. The truncated subtraction and division in \decl{term} occur only inside the definition of \decl{a} and are covered by \decl{a_eq_coeff}. + +\emph{Data check.} \decl{a_data} checks all $121$ terms listed in the entry, $a(0),\dots,a(120)$, by \texttt{decide +kernel}, in about $20$ seconds. A referee compared this list with the OEIS data by script and found them identical. + +\emph{Reading of the conjecture.} ``Odd terms occur only at $n=k(k+2)$'' is the one-directional claim that $a(n)$ odd implies $\exists k\in\N,\ n=k(k+2)$, for all $n\ge0$. Here \decl{Odd} is taken in $\Z$, which handles the negative terms (for example $a(3)=-3$). The converse is stated separately in the formula section of the entry and is not marked as a conjecture there, so it is not part of \decl{statement}. + +\section{Proof}\label{sec:proof} + +Write $\F=\Z/2\Z$ and let $\pi\colon\Z[[x]]\to\F[[x]]$ be the ring homomorphism that reduces every coefficient modulo~$2$. Then $\coef{N}\pi(f)=\pi(\coef{N}f)$, where on the right $\pi$ denotes reduction $\Z\to\F$. For $b\ge1$ let +\[ + E_b=\sum_{j\ge0}(-1)^jx^{bj}\in\Z[[x]]. +\] +In Lean, $E_b$ is obtained from $\sum_j\binom{0+j}{0}x^j=1/(1-x)$ by the substitutions $x\mapsto-x$ and $x\mapsto x^b$. The statement file proves the following two facts as the case $d=0$ of \decl{one_add_X_pow_pow_mul} and \decl{coeff_E}: +\begin{equation}\label{eq:E} + (1+x^b)\,E_b=1,\qquad + \coef{r}E_b=\begin{cases}(-1)^{r/b}&\text{if }b\mid r,\\ 0&\text{otherwise.}\end{cases} +\end{equation} + +\begin{lemma}[\decl{map_summand}]\label{lem:map} +For every $m\ge0$, $\pi(S_m)=x^m\,\pi(E_{m+1})$ in $\F[[x]]$. +\end{lemma} + +\begin{proof} +Put $u=1+x^{m+1}$, $s=\pi(S_m)$ and $e=\pi(E_{m+1})$ in $\F[[x]]$. Since $-1=1$ in $\F[[x]]$, we have $\pi(1-x^{m+1})=1-x^{m+1}=u$. Applying $\pi$ to the identity $(1+x^{m+1})^{m+1}S_m=x^m(1-x^{m+1})^m$ gives $u^{m+1}s=x^mu^m$, and applying it to \eqref{eq:E} gives $ue=1$. Hence +\[ + s=(ue)^{m+1}s=e^{m+1}\bigl(u^{m+1}s\bigr)=e^{m+1}x^mu^m=x^m e\,(ue)^m=x^me.\qedhere +\] +\end{proof} + +\begin{lemma}[\decl{coeff_map_summand}]\label{lem:coeff} +For all $N,m\ge0$, +\[ + \coef{N}\pi(S_m)=\begin{cases}1&\text{if }m\le N\text{ and }(m+1)\mid(N+1),\\0&\text{otherwise.}\end{cases} +\] +\end{lemma} + +\begin{proof} +By Lemma~\ref{lem:map}, $\coef{N}\pi(S_m)=\coef{N}\bigl(x^m\pi(E_{m+1})\bigr)$. This is $0$ if $N hne' ⟨k, hk⟩ + have h1 : ((a n : ℤ) : ZMod 2) = 1 := ZMod.intCast_eq_one_iff_odd.mpr hodd + rw [cast_a, sum_eq_zero n hne] at h1 + exact absurd h1 (by decide) +\end{lstlisting} +The core of \decl{map_summand} is the computation in the proof of Lemma~\ref{lem:map}. After the three factors are generalized to variables $s$, $e$ and $u$, it is a \texttt{calc} chain whose steps are closed by \texttt{rw} with $ue=1$ and $u^{m+1}s=x^mu^m$ and by \texttt{ring}. The proof does no large computation: the only uses of \texttt{decide} check the identities $-1=1$, $-0=0$, $1+1=0$ and $0\ne1$ in $\Z/2\Z$, and the remaining coefficient and divisibility goals in Lemma~\ref{lem:coeff} are closed by \texttt{simp}, \texttt{omega} and standard divisibility lemmas. The kernel evaluation \decl{a_data} in the statement file is a check of the definitions against the OEIS data and is not used by the proof. + +\subsection*{Audit} +The file ends with +\begin{center} +\texttt{\#math0\_settles Math0.Frontier.A323695.result Math0.Statements.A323695.statement}. +\end{center} +This command is defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself. It fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which rejects \decl{sorryAx}, the axioms \decl{Lean.ofReduceBool} and \decl{Lean.trustCompiler} introduced by \decl{native_decide}, and custom axioms; and (3) the type of \decl{result} is syntactically the statement or its negation, after removing metadata annotations and with no unfolding. On this file it reports: +\begin{lstlisting} +math0 audit: 'Math0.Statements.A323695.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A323695.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A323695.result' proves 'Math0.Statements.A323695.statement' +\end{lstlisting} +Neither file contains \texttt{sorry}, \texttt{native\_decide}, \texttt{axiom} or \texttt{set\_option}. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}. The repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. To reproduce, run \path{scripts/verify.sh} from the repository root. It fetches the Mathlib build cache, builds all math0 results with \texttt{lake build}, which re-runs every audit command, checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. To check this result alone, run \texttt{lake build Math0.Statements.OEIS.A323695} (which includes the data check \decl{a_data}) and then \texttt{lake env lean Math0/Frontier/OEIS/A323695.lean} in the directory \path{lean}. + +\begin{thebibliography}{99} + +\bibitem{Ad} +T.~Adamczewski, \emph{OEIS Open: How many conjectures can language models turn into theorems?}, arXiv:2608.11941, 2026. Code: \url{https://github.com/epoch-research/LeanOpenProblems}. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{FriedNote} +S.~Fried, \emph{Proof of a conjecture stated in A325046}, 2025, \url{https://oeis.org/A325046/a325046.pdf}. + +\bibitem{Fried} +S.~Fried, \emph{Further proofs of conjectures from the OEIS}, arXiv:2607.24832, 2026. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A323557} +The OEIS Foundation Inc., \url{https://oeis.org/A323557}, entry by P.~D.~Hanna (2019). + +\bibitem{A323695} +The OEIS Foundation Inc., \url{https://oeis.org/A323695}, entry by P.~D.~Hanna (2019). + +\bibitem{A323696} +The OEIS Foundation Inc., \url{https://oeis.org/A323696}, entry by P.~D.~Hanna (2019). + +\bibitem{A324300} +The OEIS Foundation Inc., \url{https://oeis.org/A324300}, entry by P.~D.~Hanna (2019). + +\bibitem{A325046} +The OEIS Foundation Inc., \url{https://oeis.org/A325046}, entry by P.~D.~Hanna (2019). + +\bibitem{APN} +G.~Tsoukalas et al., \emph{Advancing Mathematics Research with AI-Driven Formal Proof Search}, arXiv:2605.22763, 2026. Lean proofs: \url{https://github.com/google-deepmind/alphaproof-nexus-results}. + +\end{thebibliography} + +\end{document} diff --git a/results/oeis-a326407/README.md b/results/oeis-a326407/README.md new file mode 100644 index 0000000..1228411 --- /dev/null +++ b/results/oeis-a326407/README.md @@ -0,0 +1,45 @@ +# Prime-Minesweeper on the A060734 array: a(n) < 6, and a(n) = 5 only at n = 6 + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A326407 +**Date:** 2026-10-18 + +## Result + +Write the positive integers into the square array A060734. The cell in row r, column c (both counted from 0) holds val(r,c) = (c+1)^2 - r if r <= c, and r^2 + 1 + c if r > c. Every positive integer appears in exactly one cell. Set a(n) = -1 if n is prime. Otherwise a(n) is the number of primes in the king-move neighbouring cells of n's cell. There are up to 8 such cells, 5 on row 0 or column 0, and 3 at the corner (0,0). Claim: for every n >= 1 we have a(n) < 6, and a(n) = 5 holds exactly when n = 6. + +## Assessment + +The whole proof rests on one observation: in A060734 the entry in cell (i,j) has the parity of i+j+1. So for any interior cell, either its four orthogonal neighbours or its four diagonal neighbours hold even numbers, and only the cell of 2 can break this. That gives at most 4 primes everywhere except the cell of 6, which is next to 2. The edge cells and the few cells near 2 take a short parity check or direct evaluation. This is a standard argument of well under a page, and the OEIS already uses the same parity method for the sibling hexagonal entry A327893. The conjectures are settled as they were intended. The third conjecture, that a(n)=4 for infinitely many n, is not touched and remains open. + +*Follows from:* Checkerboard parity of the A060734 array: val(i,j) is congruent to i+j+1 mod 2. This is the same parity technique that the OEIS records in A327893 (Tatkiewicz's comment bounding the hexagonal-spiral Minesweeper terms by 4), applied to this grid. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A326407](https://oeis.org/A326407) as [`Math0.Statements.A326407.statement`](../../lean/Math0/Statements/OEIS/A326407.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A326407.lean`](../../lean/Math0/Frontier/OEIS/A326407.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C a(n) < 6 (conjectured). %C a(n) = 5 for n={6} (conjectured). %C Set of n such that a(n) = 4 is unbounded (conjectured). (Witold Tatkiewicz, Oct 02 2019) + +Referees: OEIS A326407 (Tatkiewicz, Oct 2019; last edit #27, Mar 20 2020) still lists "a(n) < 6" and "a(n) = 5 for n={6}" as conjectured, with no %E edits or proof links. OEIS A327893 (hexagonal spiral, De Vlieger 2019) records Tatkiewicz's parity argument bounding its terms by 4. That is the same technique applied to a different grid, not a proof for A326407. OEIS A326408 and A326409 state "a(n) < 5" without "(conjectured)" but give no proof. A326405, A326406, A326410, A060734, A136626 and A136627 contain nothing relevant. Web searches (arXiv, MathOverflow/Math StackExchange, SeqFan, general) found no prior proof or counterexample for A326407. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a326407, + author = {{math0}}, + title = {{Prime-Minesweeper on the A060734 array: a(n) < 6, and a(n) = 5 only at n = 6}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a326407}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a326407/paper.pdf b/results/oeis-a326407/paper.pdf new file mode 100644 index 0000000..5e6f56f Binary files /dev/null and b/results/oeis-a326407/paper.pdf differ diff --git a/results/oeis-a326407/paper.tex b/results/oeis-a326407/paper.tex new file mode 100644 index 0000000..23b9a91 --- /dev/null +++ b/results/oeis-a326407/paper.tex @@ -0,0 +1,434 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,subst,by_contra,by_cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {→}{{$\to$}}1 + {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {≠}{{$\ne$}}1 {×}{{$\times$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} +\newtheorem{conjecture}[theorem]{Conjecture} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\val}{\operatorname{val}} +\newcommand{\pos}{\operatorname{pos}} +\newcommand{\near}{\operatorname{near}} + +\title[Prime neighbours in the square array A060734]{In the square array A060734 only the cell of $6$ has more than four prime neighbours (OEIS A326407)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Write the positive integers in the square array A060734, and let $a(n)=-1$ if $n$ is prime and otherwise let $a(n)$ be the number of primes in the at most eight cells adjacent (horizontally, vertically or diagonally) to the cell of $n$; this is the ``Minesweeper sequence'' OEIS A326407. +We prove the two conjectures that Witold Tatkiewicz recorded in that entry in 2019: $a(n)<6$ for every $n\ge1$, and $a(n)=5$ only for $n=6$. +The proof is a checkerboard parity argument: the entry in row $i$ and column $j$ has the parity of $i+j+1$ and the only even prime sits in a single cell, so at most four neighbours of any cell other than the cell of $6$ can hold primes. +We found no earlier proof and classify the result as new, although the argument is elementary and of the same kind as one recorded in the OEIS for a hexagonal arrangement (A327893). +The theorem is verified in Lean~4 against a statement that math0 formalized from the OEIS entry and that was reviewed for fidelity and frozen before the proof attempt; its definitions are checked by the kernel against all $81$ listed terms of A326407 and $66$ terms of A060734. +\end{abstract} +\maketitle + +\section{Introduction} + +In 2019 Witold Tatkiewicz contributed to the OEIS a family of ``Minesweeper sequences'' (A326405--A326410): the positive integers are written along a path that fills a two-dimensional grid, each prime is treated as a mine and replaced by $-1$, and each non-prime is replaced by the number of primes in the adjacent grid cells, as in the game Minesweeper. +In A326407 \cite{A326407} the grid is the square array A060734 \cite{A060734}, which grows by alternately adding a row at its bottom edge and a column at its right edge: +\[ +\begin{array}{rrrrrrl} + 1 & 4 & 9 & 16 & 25 & 36 & \cdots\\ + 2 & 3 & 8 & 15 & 24 & 35 & \\ + 5 & 6 & 7 & 14 & 23 & 34 & \\ + 10 & 11 & 12 & 13 & 22 & 33 & \\ + 17 & 18 & 19 & 20 & 21 & 32 & \\ + 26 & 27 & 28 & 29 & 30 & 31 & \cdots +\end{array} +\] +The sequence begins $a(1),a(2),\ldots = 2,-1,-1,2,-1,5,-1,2,1,3,-1,4,\dots$; for example, $6$ is not prime and five of its eight neighbours ($2,3,5,7,11$) are prime, so $a(6)=5$. +The entry states three conjectures (Section~\ref{sec:statement}): $a(n)<6$; $a(n)=5$ only for $n=6$; and $a(n)=4$ for infinitely many $n$. +We prove the first two (Theorem~\ref{thm:main}). +In fact we prove the slightly stronger statement that every cell of the array other than the cell of $6$, including the cells that hold primes, has at most four prime neighbours (Theorem~\ref{thm:cells}). + +\subsection*{Prior work} +The entry, in revision \#27 of March~20, 2020, which is the version we read, still marks both statements as conjectured; it has no correction lines and no link to a proof. +In the entry A327893 \cite{A327893} (Michael De Vlieger, October~9, 2019), the analogous sequence for a hexagonal spiral, a comment credited to Tatkiewicz explains that its largest term is $4$ by the pattern of odd and even numbers in that arrangement. +This is an argument of the same kind as ours, applied to a different arrangement, and it does not address A326407. +The sibling entries A326408 \cite{A326408} and A326409 \cite{A326409} state $a(n)<5$ for their arrangements without the qualifier ``conjectured'', but give no argument; the math0 referees found nothing relevant in A326405, A326406, A326410 or A060734, and searches of arXiv, MathOverflow, Mathematics Stack Exchange, the SeqFan list and the general web found no proof or counterexample. +On this basis we classify the result as new. +The proof is short and elementary; this note adds a complete written proof and a kernel-checked formal proof of a frozen formal statement of the two conjectures (Section~\ref{sec:lean}). +The third conjecture is not addressed; see Remark~\ref{rem:four}. + +\section{Statement}\label{sec:statement} + +\subsection*{The OEIS conjecture} +The entry A326407, by Witold Tatkiewicz, October~2, 2019, has the name ``Minesweeper sequence of positive integers arranged on a 2D grid along a square array that grows by alternately adding a row at its bottom edge and a column at its right edge'' and offset~$1$. +Its definition reads, verbatim: +\begin{quote} +Place positive integers on a 2D grid starting with 1 in the top left corner and continue along an increasing square array as in A060734. +Replace each prime with -1 and each nonprime with the number of primes in adjacent grid cells around them. +n is replaced by a(n). +\end{quote} +The conjectures are three comments of the entry, verbatim: +\begin{quote} +a(n) $<$ 6 (conjectured).\\ +a(n) = 5 for n=\{6\} (conjectured).\\ +Set of n such that a(n) = 4 is unbounded (conjectured). +\end{quote} +We read the second comment as saying that the set of $n$ with $a(n)=5$ is exactly $\{6\}$. +The formal statement covers the first two comments. + +\subsection*{Mathematical formulation} +We index rows and columns from $0$, with row $0$ on top and column $0$ on the left. +For $k\ge0$ the \emph{hook} $k$ consists of the $2k+1$ cells $(r,c)$ with $\max(r,c)=k$; in A060734 it holds the numbers $k^2+1,\dots,(k+1)^2$, with $k^2+1,\dots,k^2+k$ in row $k$ from left to right (columns $0,\dots,k-1$) and $k^2+k+1,\dots,(k+1)^2$ in column $k$ from bottom to top (rows $k,\dots,0$). + +\begin{definition}\label{def:array} +For $r,c\in\N$ put +\[ + \val(r,c)=\begin{cases}(c+1)^2-r, & r\le c,\\ r^2+1+c, & r>c,\end{cases} +\] +and for $n\in\N$ put $k=\lfloor\sqrt{n-1}\rfloor$ (with $0-1=0$ in $\N$) and +\[ + \pos(n)=\begin{cases}(k,\ n-k^2-1), & n\le k^2+k,\\ \bigl((k+1)^2-n,\ k\bigr), & n>k^2+k.\end{cases} +\] +\end{definition} + +\begin{lemma}[\decl{pos_val}, \decl{val_pos}]\label{lem:bij} +$\pos(\val(r,c))=(r,c)$ for all $r,c\in\N$, and $\val(\pos(n))=n$ for all $n\ge1$. +In particular, since $\val(r,c)\ge1$ for all $r,c$, the map $\val$ is a bijection from $\N^2$ onto the positive integers. +\end{lemma} + +\begin{proof} +If $r\le c$ then $n=\val(r,c)=(c+1)^2-r$ satisfies $c^2+c\le n-1=c^2+(2c-r)\le c^2+2c$, so $\lfloor\sqrt{n-1}\rfloor=c$ and $n>c^2+c$; hence $\pos(n)=((c+1)^2-n,c)=(r,c)$. +If $r>c$ then $n=r^2+1+c$ with $c\le r-1$, so $n-1=r^2+c$ has $\lfloor\sqrt{n-1}\rfloor=r$ and $n\le r^2+r$; hence $\pos(n)=(r,n-r^2-1)=(r,c)$. +Conversely, let $n\ge1$ and $k=\lfloor\sqrt{n-1}\rfloor$, so $k^2+1\le n\le (k+1)^2$. +If $n\le k^2+k$, then $\pos(n)=(k,c)$ with $c=n-k^2-1 + (near (pos n).2).filterMap fun j => + if (i, j) = pos n then none else some (val i j) + +def a (n : ℕ) : ℤ := + if n.Prime then -1 else (((neighbours n).filter fun m => m.Prime).length : ℤ) + +def statement : Prop := + (∀ n : ℕ, 1 ≤ n → a n < 6) ∧ (∀ n : ℕ, 1 ≤ n → (a n = 5 ↔ n = 6)) +\end{lstlisting} +Here \texttt{val}, \texttt{pos} and \texttt{near} are the functions of the same names above, \texttt{neighbours n} is the list $L(\pos(n))$, \texttt{a} is the function $a$ of Definition~\ref{def:a} (with values in $\Z$), and \texttt{statement} is Theorem~\ref{thm:main}. + +\subsection*{Encoding} +The array is encoded by the closed formula $\val$, not by simulating its growth, and Lemma~\ref{lem:bij} (proved in the statement file) shows that it places every positive integer in exactly one cell, so that ``the cell of $n$'' is $\pos(n)$. +The ``adjacent grid cells'' of the entry are the Minesweeper neighbours: all cells at king-move distance~$1$, including the diagonal ones, cut off at the top row and the left column, where the grid ends. +The two conjectures are stated over the whole range $n\ge1$ of the sequence; \texttt{a 0} is a junk value that does not occur in the statement. +The truncated subtractions in \texttt{val} and \texttt{pos} are exact where they are used, by Lemma~\ref{lem:bij}. +The third conjecture is recorded separately in the statement file as the definition \decl{statement_four_unbounded}, which says that for every $N$ there is $n\ge N$ with $a(n)=4$; it is not part of \decl{statement}. + +\subsection*{Check against the OEIS data} +The statement file proves by kernel evaluation (\texttt{decide +kernel}) two data checks. +The theorem \decl{val_data} states that the values $\val(0,d),\val(1,d-1),\dots,\val(d,0)$ for $d=0,\dots,10$ are the first $66$ listed terms of A060734 (the array read by antidiagonals downwards), and that the $6\times6$ corner of $\val$ is the array printed in the example of A326407 and in the introduction. +The theorem \decl{a_data} states that $a(1),\dots,a(81)$ are the $81$ listed terms of A326407. +In the fidelity review, which found the statement faithful and made no edits, a referee also rebuilt the array in Python by growing it row by row and column by column, found agreement with $\val$ on a $60\times60$ grid, and reproduced the $81$ listed terms independently. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A326407.lean}; the Lean names of the lemmas are given in brackets. + +\begin{lemma}[Checkerboard parity, \decl{val_mod_two}]\label{lem:parity} +For all $i,j\in\N$ we have $\val(i,j)\equiv i+j+1\pmod 2$. +In particular $\val(i,j)$ is even if and only if $i+j$ is odd. +\end{lemma} + +\begin{proof} +Since $x^2=x\cdot x\equiv x\pmod 2$ for every $x\in\N$ (\decl{mul_self_mod_two}), we get, if $i\le j$, from $\val(i,j)+i=(j+1)^2$ that $\val(i,j)\equiv (j+1)^2-i\equiv j+1+i$, and, if $i>j$, that $\val(i,j)=i^2+1+j\equiv i+1+j$. +\end{proof} + +\begin{lemma}[\decl{val_eq_two}]\label{lem:two} +If $\val(i,j)=2$, then $(i,j)=(1,0)$. +\end{lemma} + +\begin{proof} +We have $\lfloor\sqrt{1}\rfloor=1$ and $2\le1^2+1$, so $\pos(2)=(1,0)$. +By Lemma~\ref{lem:bij}, $(i,j)=\pos(\val(i,j))=\pos(2)=(1,0)$. +(In Lean, $\pos(2)=(1,0)$ is obtained by kernel evaluation.) +\end{proof} + +\begin{corollary}[\decl{not_prime_val}]\label{cor:np} +If $i+j$ is odd and $(i,j)\ne(1,0)$, then $\val(i,j)$ is not prime. +\end{corollary} + +\begin{proof} +A prime is $2$ or odd. +By Lemma~\ref{lem:two}, $\val(i,j)\ne2$, and by Lemma~\ref{lem:parity}, $\val(i,j)$ is even. +\end{proof} + +We call a cell $(i,j)$ with $i+j$ odd and $(i,j)\ne(1,0)$ \emph{excluded}. +Since $\kappa(r,c)$ is the sum over the entries $x$ of $L(r,c)$ of $1$ if $x$ is prime and $0$ otherwise, Corollary~\ref{cor:np} gives +\begin{equation}\label{eq:count} + \kappa(r,c)\le |L(r,c)|-e, +\end{equation} +whenever $e$ distinct neighbouring cells of $(r,c)$ are excluded. + +\begin{lemma}[\decl{count_le}]\label{lem:count} +If $(r,c)\ne(2,1)$, then $\kappa(r,c)\le4$. +\end{lemma} + +\begin{proof} +We distinguish whether $r$ and $c$ are $0$ or successors, as in the Lean proof. + +\emph{The corner $(0,0)$.} +Here $L(0,0)=(4,2,3)$ has three entries, so $\kappa(0,0)\le3$ (in fact $\kappa(0,0)=2$; the Lean proof evaluates this directly). + +\emph{Row $0$: $(r,c)=(0,t+1)$.} +The neighbouring cells are $(0,t)$, $(0,t+2)$, $(1,t)$, $(1,t+1)$, $(1,t+2)$. +If $t$ is even, $(1,t+2)$ is excluded: $1+t+2$ is odd and its column is not $0$. +If $t$ is odd, $(0,t)$ and $(0,t+2)$ are excluded: their coordinate sums $t$ and $t+2$ are odd and they lie in row $0$. +By \eqref{eq:count}, $\kappa(0,t+1)\le 5-1=4$. + +\emph{Column $0$: $(r,c)=(s+1,0)$.} +The neighbouring cells are $(s,0)$, $(s,1)$, $(s+1,1)$, $(s+2,0)$, $(s+2,1)$. +If $s$ is even, $(s,1)$ is excluded: $s+1$ is odd and its column is $1$. +If $s$ is odd, $(s+1,1)$ and $(s+2,0)$ are excluded: both coordinate sums equal $s+2$, which is odd, the first cell lies in column $1$, and the second in row $s+2\ge3$. +By \eqref{eq:count}, $\kappa(s+1,0)\le4$. + +\emph{Interior cells: $(r,c)=(s+1,t+1)$.} +If $s=t=0$, the cell is $(1,1)$, holding $3$, with $L(1,1)=(1,4,9,2,8,5,6,7)$, so $\kappa(1,1)=3$ (evaluated directly in Lean). +Otherwise the eight neighbouring cells split into the four orthogonal ones +\[ + (s,t+1),\quad (s+1,t),\quad (s+1,t+2),\quad (s+2,t+1), +\] +whose coordinate sums are $\equiv s+t+1\pmod2$, and the four diagonal ones +\[ + (s,t),\quad (s,t+2),\quad (s+2,t),\quad (s+2,t+2), +\] +whose coordinate sums are $\equiv s+t\pmod2$. +If $s+t$ is even, the four orthogonal cells have odd coordinate sums; the cells $(s,t+1)$, $(s+1,t+2)$ and $(s+2,t+1)$ have column $\ge1$, so only $(s+1,t)$ could be $(1,0)$, and it is $(1,0)$ only if $s=t=0$, which we have excluded. +If $s+t$ is odd, the four diagonal cells have odd coordinate sums; the cells $(s,t+2)$, $(s+2,t)$ and $(s+2,t+2)$ have row or column $\ge2$, so only $(s,t)$ could be $(1,0)$, and $(s,t)=(1,0)$ would mean $(r,c)=(2,1)$, which is excluded by hypothesis. +In both cases four neighbouring cells are excluded, and \eqref{eq:count} gives $\kappa(s+1,t+1)\le8-4=4$. +\end{proof} + +In Lean, each case other than the cells $(0,0)$ and $(1,1)$ unfolds $L(r,c)$ into an explicit list of values $\val(i,j)$, rewrites the number of prime entries as a sum of indicators by \decl{len_filter_cons} (avoiding the nested case splits produced by unfolding \texttt{List.filter}), sets the indicators of the excluded cells to $0$ by Corollary~\ref{cor:np} (its side conditions are discharged by \texttt{omega}), and checks \eqref{eq:count} with \texttt{split\_ifs <;> omega}. + +\begin{lemma}[\decl{a_six}]\label{lem:six} +$\pos(6)=(2,1)$, $\kappa(2,1)=5$ and $a(6)=5$. +\end{lemma} + +\begin{proof} +We have $\lfloor\sqrt5\rfloor=2$ and $6\le2^2+2$, so $\pos(6)=(2,6-4-1)=(2,1)$. +The neighbouring cells of $(2,1)$ hold +\[ + L(2,1)=(2,3,8,5,7,10,11,12), +\] +of which exactly $2,3,5,7,11$ are prime. +Since $6$ is not prime, $a(6)=\kappa(2,1)=5$. +\end{proof} + +In Lean, $a(6)=5$ is proved by kernel evaluation (\texttt{decide +kernel}) of the definition, including $\pos(6)$, the list \texttt{neighbours 6} and the primality of its entries. + +\begin{proof}[Proof of Theorems~\ref{thm:main} and~\ref{thm:cells}] +Theorem~\ref{thm:cells} is Lemmas~\ref{lem:count} and~\ref{lem:six}. +Let $n\ge1$ with $n\ne6$ (Lean: \decl{a_le_four}). +If $n$ is prime, then $a(n)=-1\le4$. +Otherwise $a(n)=\kappa(\pos(n))$. +If $\pos(n)$ were $(2,1)$, Lemma~\ref{lem:bij} would give $n=\val(2,1)=6$; hence $\pos(n)\ne(2,1)$, and $a(n)\le4$ by Lemma~\ref{lem:count}. +Together with $a(6)=5$ (Lemma~\ref{lem:six}) this gives $a(n)<6$ for every $n\ge1$, and $a(n)=5$ if and only if $n=6$. +\end{proof} + +\begin{remark}[The third conjecture]\label{rem:four} +The value $4$ occurs, for instance $a(12)=4$, and the entry conjectures that it occurs infinitely often. +We do not address this, and the parity argument says nothing about it. +It concerns prime constellations: if $v\ne6$ is even and its cell $(r,c)$ has $r,c\ge1$, then by the case ``$s+t$ odd'' of Lemma~\ref{lem:count} the diagonal neighbours of $(r,c)$ are non-prime, so $a(v)=4$ forces all four orthogonal neighbours to be prime. +These include the cells of $v\pm1$: by the description of the hooks, $m$ and $m+1$ occupy orthogonally adjacent cells unless $m=(k+1)^2$ with $k\ge1$, and then $m$ lies in row~$0$ and $m+1$ in column~$0$. +So for such $v$, $a(v)=4$ implies that $v-1$ and $v+1$ are twin primes. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in the file \path{lean/Math0/Frontier/OEIS/A326407.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. +It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A326407.lean} (Section~\ref{sec:statement}; SHA-256 \texttt{32bef0c0\ldots c912e}, unchanged since the fidelity review) and the audit commands in \path{lean/Math0/Audit.lean}. +The main declaration is \decl{Math0.Frontier.A326407.result}, of type \decl{Math0.Statements.A326407.statement}. +Its auxiliary declarations are private: the list \texttt{nb r c} $=L(r,c)$ (with \texttt{neighbours n = nb (pos n).1 (pos n).2} by \texttt{rfl}), the helper lemmas \decl{mul_self_mod_two} and \decl{len_filter_cons}, the lemmas named in Section~\ref{sec:proof}, and +\begin{lstlisting} +private theorem count_le (r c : ℕ) (h : ¬ (r = 2 ∧ c = 1)) : + ((nb r c).filter fun m => m.Prime).length ≤ 4 +private theorem a_le_four {n : ℕ} (hn : 1 ≤ n) (h6 : n ≠ 6) : a n ≤ 4 +\end{lstlisting} +The theorem \texttt{result : statement} follows from \decl{a_six} and \decl{a_le_four} by a case split on $n=6$ and \texttt{omega}, as in the last proof of Section~\ref{sec:proof}; the file ends with +\begin{lstlisting} +#math0_settles Math0.Frontier.A326407.result Math0.Statements.A326407.statement +\end{lstlisting} +The finite computations (the cells $(0,0)$ and $(1,1)$ in \decl{count_le}, the value $\pos(2)=(1,0)$ in \decl{val_eq_two}, and \decl{a_six}) use \texttt{decide +kernel}, which evaluates a decision procedure in the Lean kernel, and the value $\val(2,1)=6$ in \decl{a_le_four} is checked by \texttt{decide}; no \texttt{native\_decide}, \texttt{sorry}, \texttt{set\_option} or added axiom occurs in either file. + +\subsection*{Audit} +The command \texttt{\#math0\_settles} (in \path{lean/Math0/Audit.lean}) fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} introduced by \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata annotations, with no unfolding. +Running \texttt{lake env lean Math0/Frontier/OEIS/A326407.lean} in the directory \path{lean} prints +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A326407.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A326407.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A326407.result' proves 'Math0.Statements.A326407.statement' +\end{lstlisting} +so \decl{result} proves the statement (it does not refute it) and depends only on the three standard axioms. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib cache, builds all math0 results with \texttt{lake build} (re-running every audit command) and checks that the pinned dependencies are unmodified. +To check this result alone, run \texttt{lake build Math0.Statements.OEIS.A326407} (this re-runs \decl{val_data} and \decl{a_data}) and \texttt{lake env lean Math0/Frontier/OEIS/A326407.lean} in \path{lean}. + +{\small +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171 [cs.AI], 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A060734} +The OEIS Foundation Inc., \url{https://oeis.org/A060734}, entry by F.~Ellermann, Apr.~23, 2001. + +\bibitem{A326407} +The OEIS Foundation Inc., \url{https://oeis.org/A326407}, entry by W.~Tatkiewicz, Oct.~2, 2019; revision \#27, Mar.~20, 2020. + +\bibitem{A326408} +The OEIS Foundation Inc., \url{https://oeis.org/A326408}, entry by W.~Tatkiewicz, Oct.~4, 2019. + +\bibitem{A326409} +The OEIS Foundation Inc., \url{https://oeis.org/A326409}, entry by W.~Tatkiewicz, Oct.~7, 2019. + +\bibitem{A327893} +The OEIS Foundation Inc., \url{https://oeis.org/A327893}, entry by M.~De Vlieger, Oct.~9, 2019. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a326602/README.md b/results/oeis-a326602/README.md new file mode 100644 index 0000000..0ab3d95 --- /dev/null +++ b/results/oeis-a326602/README.md @@ -0,0 +1,52 @@ +# A326602: a(n) is odd iff n is a square + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Sequences and series +**Source problem:** OEIS A326602 +**Date:** 2026-10-18 + +## Result + +Let A(x) = Sum_{n>=0} (x^(2n-1)+1)^n x^n / (1+x^(2n+1))^(n+1) in Z[[x]] (the n=0 summand is 1/(1+x)), and let a(n) = [x^(2n)] A(x). Then for every n >= 0, a(n) is odd if and only if n is a perfect square (n = k^2 for some k >= 0, so 0 counts as a square). + +## Assessment + +The proof expands each summand using the binomial theorem and the series for (1+y)^-(n+1). Modulo 2 it rewrites the coefficient of x^N as a sum of trinomial coefficients T(n,m,i) over triples with n+m+2nm = N+2i. Both the weight and the condition are symmetric in n and m, so the off-diagonal terms cancel in pairs. Each diagonal term is a multiple of a central binomial coefficient, so it is even except when i = n, which forces N = 2n^2. The whole argument fits in about a page, and it is a direct adaptation of the involution proof for the cross-referenced entry A323557, which that entry already cites; the manuscript itself calls it a fairly routine adaptation. + +*Follows from:* The involution/parity method already used for the cross-referenced sibling A323557: Ralf Stephan's comment of Jun 01 2026 in that entry, the AlphaProof Nexus Lean file, and Adamczewski, arXiv:2608.11941, Appendix A. Fried's proof for A325046 uses the same idea. The new proof also uses the standard fact that the central binomial coefficient C(2k,k) is even for k >= 1. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A326602](https://oeis.org/A326602) as [`Math0.Statements.A326602.statement`](../../lean/Math0/Statements/OEIS/A326602.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A326602.lean`](../../lean/Math0/Frontier/OEIS/A326602.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: A326602 (G.f.: Sum_{n>=0} (x^(2n-1)+1)^n x^n/(1+x^(2n+1))^(n+1), an even function; a(n) = [x^(2n)]): "a(n) is odd iff n is square (conjecture)." (_Paul D. Hanna_, Aug 08 2019). Same family: A323689 (Sum (x^n+i)^n/(1+i x^n)^(n+1)): "Odd terms occur only at n = k^2 for k >= 0 (conjecture);" (Hanna, Feb 14 2019); A323675 (Sum x^n (x^n+i)^n/(1+i x^(n+1))^(n+1)): "It appears that odd terms occur only at n*(n+1)" (Hanna, Feb 10 2019); A323690 (Sum (x^(n+1)+i)^n/(1+i x^n)^(n+1)): "the first column consists of all the odd terms" (triangle rows start at n(n+1)) (Hanna, Feb 13 2019). + +Referees: No prior resolution of A326602 found. +- OEIS A326602 (local mirror and upstream oeisdata) is still at revision #19, Aug 11 2019, and still says "a(n) is odd iff n is square (conjecture)". No later edits or proof links. + +Closest prior work (same involution or parity method, different sequences): +- A323557 (odd terms only at n(n+1)): proved by AlphaProof Nexus (github.com/google-deepmind/alphaproof-nexus-results, APNOutputs/OEIS/oeis_323557_conjecture_0.lean) and in T. Adamczewski, "OEIS Open: How many conjectures can language models turn into theorems?", arXiv:2608.11941, Appendix A. Also R. Stephan's comment of Jun 01 2026 on A323557. +- A325046: S. Fried, "Proof of a conjecture stated in A325046" (OEIS a325046.pdf, 2025), and "Further proofs of conjectures from the OEIS", arXiv:2607.24832, Sec. 3.8 / Thm 50. + +Neither arXiv paper mentions A326602, and A326602 is absent from google-deepmind/formal-conjectures, so it was not in the Tsoukalas et al. or OEIS Open benchmark sets. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a326602, + author = {{math0}}, + title = {{A326602: a(n) is odd iff n is a square}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a326602}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a326602/paper.pdf b/results/oeis-a326602/paper.pdf new file mode 100644 index 0000000..973bd12 Binary files /dev/null and b/results/oeis-a326602/paper.pdf differ diff --git a/results/oeis-a326602/paper.tex b/results/oeis-a326602/paper.tex new file mode 100644 index 0000000..03e657e --- /dev/null +++ b/results/oeis-a326602/paper.tex @@ -0,0 +1,385 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\hypersetup{pdftitle={Hanna's parity conjecture for OEIS A326602}, pdfauthor={math0}} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,scoped,rw,split_ifs}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∑}{{$\sum$}}1 {∈}{{$\in$}}1 + {∀}{{$\forall$}}1 {↔}{{$\leftrightarrow$}}1 {∧}{{$\wedge$}}1 {←}{{$\leftarrow$}}1 + {·}{{$\cdot$}}1 {≤}{{$\le$}}1 {¬}{{$\neg$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} +\newtheorem{example}[theorem]{Example} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\F}{\mathbb{F}_2} +\newcommand{\ZX}{\mathbb{Z}[[x]]} +\newcommand{\co}[1]{[x^{#1}]} + +\title[Hanna's parity conjecture for OEIS A326602]{The coefficient of $x^{2n}$ in $\sum_{k\ge 0}(x^{2k-1}+1)^k x^k/(1+x^{2k+1})^{k+1}$ is odd if and only if $n$ is a perfect square} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Let $A(x)=\sum_{k\ge0}(x^{2k-1}+1)^k x^k/(1+x^{2k+1})^{k+1}$ in $\ZX$ and let $a(n)$ be the coefficient of $x^{2n}$ in $A(x)$; this is OEIS A326602. +We prove the conjecture recorded by Paul D.~Hanna in 2019 that $a(n)$ is odd if and only if $n$ is a perfect square; the same argument also gives $A(x)\equiv\sum_{k\ge0}x^{2k^2}\pmod 2$ coefficientwise. +The proof writes each coefficient modulo $2$ as a sum of trinomial coefficients over a finite set of triples, cancels these terms in pairs by an involution, and uses the evenness of central binomial coefficients; the same strategy was used earlier for the sibling sequences A323557 and A325046, and our result is an adaptation of it. +To our knowledge the result is new: the entry still lists the statement as a conjecture, and we found no proof in the literature. +The proof of the conjecture is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, in which $a(n)$ is proved equal to the coefficient of the $x$-adically convergent series and checked by the kernel against the $68$ listed terms; this statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +In 2019 Paul D.~Hanna contributed to the OEIS several power series, defined by sums such as $\sum_{n\ge0}x^n(1+x^n)^n/(1+x^{n+1})^{n+1}$ (A323557 \cite{A323557}), whose coefficients appear to be odd only on a sparse set of exponents: only at the pronic numbers $n(n+1)$ for A323557 and A325046 \cite{A325046}, and at squares or pronic numbers for the Gaussian-integer variants A323689, A323675 and A323690 \cite{A323689,A323675,A323690}. +The sequence studied here, A326602 \cite{A326602}, contributed by Hanna on August~8, 2019, and listed as a variant of A323557, has the generating function +\[ + A(x)=\sum_{n\ge0}\frac{(x^{2n-1}+1)^n\,x^n}{(1+x^{2n+1})^{n+1}}=1+3x^2+2x^6+9x^8-12x^{10}+8x^{12}+\cdots, +\] +an even function according to the entry, and $a(n)$ is the coefficient of $x^{2n}$. The entry states ``a(n) is odd iff n is square (conjecture)''. + +\subsection*{Result} +We prove the conjecture (Theorem~\ref{thm:main}); the same argument shows that $A(x)\equiv\sum_{k\ge0}x^{2k^2}\pmod 2$ coefficientwise (Corollary~\ref{cor:strong}). +The coefficient of $x^N$ in $A(x)$ is a signed sum of products $\binom ni\binom{n+j}{j}$. Substituting $m=i+j$ turns it, modulo $2$, into a sum of trinomial coefficients $T(n,m,i)=(n+m-i)!/(i!\,(n-i)!\,(m-i)!)$ over the triples $(n,i,m)$ with $n+m+2nm=N+2i$. Both the weight and the condition are symmetric in $n$ and $m$, so the off-diagonal terms cancel in pairs; on the diagonal $T(n,n,i)$ is a multiple of the central binomial coefficient $\binom{2(n-i)}{n-i}$, hence even unless $i=n$, which forces $N=2n^2$. + +\subsection*{Prior work and status} +For A323557, Ralf Stephan recorded in the entry on June~1, 2026, that the conjecture was proved by an autonomous AI agent, with a Lean file in the AlphaProof Nexus results repository \cite{APN}, by an involution on triples that preserves each term modulo~$2$ and whose fixed points contribute even terms except at positions $n(n+1)$; the entry also cites \cite[Appendix~A]{Ad} for the proof. +For A325046, Sela Fried noted in the entry on December~17, 2025, that the conjecture is true, with a proof in \cite{Fr25}; see also \cite[Section~3.8, Theorem~50]{Fr} and \cite[Appendix~A]{Ad}. The repository \cite{APN} also has a Lean proof for A325046, by an involution whose fixed points carry the weights $\binom nk\binom{2n-k}{n-k}$, even for $k=0} (x^(2*n-1) + 1)^n * x^n / (1 + x^(2*n+1))^(n+1), an even function.|\\ +\verb|G.f. A(x) = Sum_{n>=0} a(n)*x^(2*n), where [...]|\\ +\verb|a(n) is odd iff n is square (conjecture).| +\end{quote} +The entry, including this conjecture, was contributed by \emph{Paul D.~Hanna}, Aug.~08, 2019. + +\begin{theorem}\label{thm:main} +For every integer $n\ge0$, $a(n)$ is odd if and only if $n=k^2$ for some integer $k\ge0$. +\end{theorem} + +Theorem~\ref{thm:main} is exactly the formal statement below and is what the Lean proof establishes; Corollary~\ref{cor:strong}, its extension to all coefficients of $A$, is proved on paper only. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A326602.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{dcf51cfe\ldots 1459137}) before any proof attempt. Its main declarations are, verbatim except that docstrings, proofs and some auxiliary lemmas are omitted: +\begin{lstlisting} +namespace Math0.Statements.A326602 +open PowerSeries +noncomputable def summand (n : ℕ) : PowerSeries ℤ := + (X ^ (2 * n - 1) + 1) ^ n * X ^ n * invOfUnit ((1 + X ^ (2 * n + 1)) ^ (n + 1)) 1 +theorem summand_spec (n : ℕ) : + (1 + X ^ (2 * n + 1)) ^ (n + 1) * summand n = (X ^ (2 * n - 1) + 1) ^ n * X ^ n +noncomputable def A : PowerSeries ℤ := + mk fun N => ∑ n ∈ Finset.range (N + 1), coeff N (summand n) +open scoped PowerSeries.WithPiTopology in +theorem hasSum_summand : HasSum summand A +def binom (n k : ℕ) : ℕ := n.descFactorial k / k.factorial +def term (N m i : ℕ) : ℤ := + if (2 * m - 1) * i + m ≤ N ∧ (N - ((2 * m - 1) * i + m)) % (2 * m + 1) = 0 then + (-1) ^ ((N - ((2 * m - 1) * i + m)) / (2 * m + 1)) * + ((binom m i * binom (m + (N - ((2 * m - 1) * i + m)) / (2 * m + 1)) + ((N - ((2 * m - 1) * i + m)) / (2 * m + 1)) : ℕ) : ℤ) + else 0 +def iBound (N m : ℕ) : ℕ := min m ((N - m) / (2 * m - 1)) +def coeffA (N : ℕ) : ℤ := + ∑ m ∈ Finset.range (N + 1), ∑ i ∈ Finset.range (iBound N m + 1), term N m i +def a (n : ℕ) : ℤ := coeffA (2 * n) +theorem a_eq_coeff (n : ℕ) : a n = coeff (2 * n) A +def statement : Prop := + ∀ n : ℕ, Odd (a n) ↔ IsSquare n +end Math0.Statements.A326602 +\end{lstlisting} +The encoding follows Definition~\ref{def:main}. \texttt{summand n} is $f_n$, with the inverse of $(1+X^{2n+1})^{n+1}$ given by Mathlib's \decl{invOfUnit}; \decl{summand_spec} proves that it really is the quotient. For $n=0$ the natural-number subtraction gives $2\cdot0-1=0$, which is harmless because the factor is raised to the power $0$. \decl{A} is defined coefficientwise as $\sum_{n\le N}\co Nf_n$; the lemma \decl{coeff_summand_of_lt} (not shown) proves $\co Nf_n=0$ for $N0$. +(c) With $m=i+j$ we have $n+m-i=n+j$ and $n+m-2i=n+j-i$. By $\binom{a}{b}\binom{b}{c}=\binom ac\binom{a-c}{b-c}$ with $a=n+j$, $b=n$, $c=i$, and $\binom{n+j}{n}=\binom{n+j}{j}$, we get $\binom ni\binom{n+j}j=\binom{n+j}{i}\binom{n+j-i}{n-i}=T(n,i+j,i)$. +(d) $\binom{n+m-2i}{n-i}=\binom{n+m-2i}{m-i}$, since $(n-i)+(m-i)=n+m-2i$. +\end{proof} + +\subsection{Reduction modulo \texorpdfstring{$2$}{2} to a sum over triples} +For $N\ge0$ let +\[ + S(N)=\bigl\{(n,i,m)\in\{0,\dots,N\}^3:\ i\le n,\ i\le m,\ n+m+2nm=N+2i\bigr\}. +\] +(The bound by $N$ is in fact implied by the other conditions; it makes the finiteness explicit.) + +\begin{lemma}\label{lem:termcast} +Let $N\ge0$ and $0\le i\le n$. Then +\[ + t(N,n,i)\equiv\sum_{\substack{0\le m\le N\\ i\le m,\ n+m+2nm=N+2i}}T(n,m,i). +\] +\end{lemma} + +\begin{proof} +Suppose $N=e(n,i)+(2n+1)j$ with $j\ge0$, and put $m=i+j$. By Lemma~\ref{lem:arith}(a), $n+m+2nm=N+2i$; clearly $i\le m$; and $m\le N$, because $i\le e(n,i)$ and $j\le(2n+1)j$. By Lemma~\ref{lem:arith}(b), $m$ is the only index satisfying the conditions of the sum, so the sum equals $T(n,i+j,i)=\binom ni\binom{n+j}{j}$ by Lemma~\ref{lem:arith}(c), and this is congruent to $t(N,n,i)=(-1)^j\binom ni\binom{n+j}j$. +Otherwise $t(N,n,i)=0$, and the sum is empty: if some $m\ge i$ satisfied $n+m+2nm=N+2i$, then with $j=m-i$ Lemma~\ref{lem:arith}(a) would give $N=e(n,i)+(2n+1)j$. +\end{proof} + +\begin{lemma}\label{lem:coeffcast} +For every $N\ge0$, $\displaystyle \co NA=\texttt{coeffA}(N)\equiv\sum_{(n,i,m)\in S(N)}T(n,m,i)$. +\end{lemma} + +\begin{proof} +By Lemmas~\ref{lem:formula} and~\ref{lem:termcast}, $\co NA$ is congruent to the sum of $T(n,m,i)$ over $n\le N$, $i\le n$ and $m\le N$ with $i\le m$ and $n+m+2nm=N+2i$. Since $n\le N$, the range $i\le n$ may be replaced by $i\le N$ together with the condition $i\le n$; the result is the sum over $S(N)$. +\end{proof} + +For example, $S(2)=\{(0,0,2),(2,0,0),(1,1,1)\}$, each with weight $T=1$; these triples account for the coefficient $1$ of $x^2$ in each of $f_0$, $f_2$ and $f_1$, and indeed $a(1)=3$. + +\subsection{The involution} +\begin{lemma}\label{lem:involution} +For every $N\ge0$, +\[ + \sum_{(n,i,m)\in S(N)}T(n,m,i)\equiv\sum_{\substack{(n,i,m)\in S(N)\\ n=m}}T(n,n,i). +\] +\end{lemma} + +\begin{proof} +The conditions defining $S(N)$ are symmetric in $n$ and $m$, so $\sigma(n,i,m)=(m,i,n)$ is an involution of $S(N)$ that preserves the set $S'(N)$ of triples with $n\ne m$ and has no fixed points in it. By Lemma~\ref{lem:arith}(d), $T(\sigma(x))=T(x)$ for $x\in S(N)$, writing $T(x)=T(n,m,i)$ for $x=(n,i,m)$. Hence $S'(N)$ is partitioned into pairs $\{x,\sigma(x)\}$, each contributing $2T(x)\equiv0$, and the sum over $S'(N)$ is even. +\end{proof} + +\subsection{The diagonal} +\begin{lemma}\label{lem:diag} +Let $N\ge0$ and $(n,i,n)\in S(N)$. If $i 3, a(p)=2*p. If p is a Mersenne prime, a(p+1)=2*p. Conjecture: these are the only cases where a(n)>n.' + +Referees: G. Kaplan and D. Levy, "GCD of truncated rows in Pascal's triangle", Integers 4 (2004), #A14 (https://math.colgate.edu/~integers/e14/e14.pdf). Theorem 4 with Theorem 7 at t=1 (h(n,1)=1 for n>=4), or equivalently Theorem 9, gives g(n,2) = lcm(g(n-1,1), g(n,1)) = A014963(n)*A014963(n-1). This proves the A328202 formula in 2004, before the 2019 OEIS conjecture, and the paper's Table 2 matches the sequence data. Also relevant: H. Joris, C. Oestreicher and J. Steinig, "The greatest common divisor of certain sets of binomial coefficients", J. Number Theory 21 (1985) 101-119, which gives a general formula for gcd{C(n,k): r<=k<=s} (not checked directly). Background: Ram (1909) for the g(n,1) case. The OEIS entry (rev #46, Oct 10 2026) still labels the formula "(conjecture)" and does not cite these papers. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a328202, + author = {{math0}}, + title = {{The gcd of the interior binomial coefficients of row n equals Λ-exp(n)·Λ-exp(n−1) (A328202, Maiga's conjecture)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a328202}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a328202/paper.pdf b/results/oeis-a328202/paper.pdf new file mode 100644 index 0000000..043844f Binary files /dev/null and b/results/oeis-a328202/paper.pdf differ diff --git a/results/oeis-a328202/paper.tex b/results/oeis-a328202/paper.tex new file mode 100644 index 0000000..df0c633 --- /dev/null +++ b/results/oeis-a328202/paper.tex @@ -0,0 +1,350 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℝ}{{$\mathbb{R}$}}1 {∀}{{$\forall$}}1 {→}{{$\to$}}1 + {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {¬}{{$\neg$}}1 {∣}{{$\mid$}}1 {≡}{{$\equiv$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\vp}{v_p} + +\title[The gcd of truncated rows of Pascal's triangle (OEIS A328202)]{The greatest common divisor of $\binom{n}{2},\dots,\binom{n}{n-2}$ equals $e^{\Lambda(n)}e^{\Lambda(n-1)}$: a formal proof of Maiga's formula for OEIS A328202} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 25, 2026} + +\begin{document} +\begin{abstract} +For $n\ge4$ let $a(n)=\gcd\{\binom nk:2\le k\le n-2\}$, the greatest common divisor of row $n$ of Pascal's triangle with the entries $1$ and $n$ removed (OEIS A328202). +We prove that $a(n)=L(n)\,L(n-1)$ for every $n\ge4$, where $L(m)=e^{\Lambda(m)}$ equals $p$ if $m$ is a power of the prime $p$ and $1$ otherwise (OEIS A014963); this identity was recorded in the OEIS as a conjecture by Jon Maiga in 2019. +The result is not new: it follows from Theorems~4 and~7 of Kaplan and Levy (2004), whose paper predates the conjecture and is not cited in the OEIS entry, which still labels the formula a conjecture. We give a short self-contained proof, based on Kummer's theorem for $\binom{p^t}{k}$ and Lucas's congruence, and formalize it; to our knowledge this is the first formal proof of the result. +The proof is verified in Lean~4 with Mathlib against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the listed terms of A328202 and A014963. +\end{abstract} +\maketitle + +\section{Introduction} + +The sequence A328202 of the OEIS \cite{A328202}, contributed by Joel Kaufmann on October~7, 2019, has offset $4$ and is described as ``the greatest common divisor of all the numbers in row $n$ of Pascal's triangle excluding $1$ and $n$''. For example, row $8$ is $1,8,28,56,70,56,28,8,1$, and $\gcd(28,56,70)=14$, so $a(8)=14$; the data section lists $a(4),\dots,a(78)$, beginning $6,10,5,7,14,6,3,11,11,13,13,1,2,34$. +On October~8, 2019, Jon Maiga added to the entry the formula +\begin{equation}\label{eq:maiga} + a(n)=\mathrm{A014963}(n)\cdot\mathrm{A014963}(n-1), +\end{equation} +labelled as a conjecture, where A014963 \cite{A014963} is the exponential of the von Mangoldt function: $\mathrm{A014963}(m)=e^{\Lambda(m)}$ is the prime $p$ if $m$ is a power $p^t$ ($t\ge1$) of $p$, and $1$ otherwise. For $n=8$ this reads $14=2\cdot 7$. +The entry also contains comments of Robert Israel (October~16, 2019): $p\mid a(p^k)$ and $p\mid a(p^k+1)$ for every prime $p$ and $k\ge1$; $a(p)=2p$ for a Fermat prime $p>3$ and $a(p+1)=2p$ for a Mersenne prime $p$; and the conjecture that these are the only cases with $a(n)>n$. A comment of Chai Wah Wu (October~9, 2026) notes that $\gcd(n,a(n))=1$ if $n$ is not a prime power, by Ram's theorem. In the current revision of the entry (\#46, October~10, 2026), \eqref{eq:maiga} is still labelled ``(conjecture)''. + +We prove \eqref{eq:maiga} for every $n\ge4$ (Theorem~\ref{thm:main}), with a proof verified in Lean~4. + +\subsection*{Prior work and status} +The identity \eqref{eq:maiga} is a known theorem. We credit the literature as follows. +\begin{itemize} +\item Ram \cite{Ram} determined in 1909 the greatest common divisor of the full interior row, $\gcd\{\binom nk:1\le k\le n-1\}=L(n)$ for $n\ge2$; the comment of Chai Wah Wu in A328202 refers to this result as Ram's theorem. +\item Kaplan and Levy \cite{KL} study $g(n,t)=\gcd\bigl(\binom nt,\binom n{t+1},\dots,\binom n{n-t}\bigr)$, so that $a(n)=g(n,2)$. Their Theorem~4 is the formula $g(n,1)=L(n)$ for $n\ge2$. They set $h(n,t)=g(n,t+1)/\operatorname{lcm}(g(n-1,t),g(n,t))$ for $n\ge2$ and $0\le t<\lfloor n/2\rfloor$ (their Notation~6, an integer by their Theorem~5), and their main result, Theorem~7, applied with $t=1$ gives $h(n,1)=1$ for all $n\ge4$ (the integer $1$ has no prime factors). Hence +\[ + a(n)=g(n,2)=\operatorname{lcm}\bigl(g(n-1,1),g(n,1)\bigr)=\operatorname{lcm}\bigl(L(n-1),L(n)\bigr)=L(n)L(n-1)\qquad(n\ge4), +\] +the last step because $L(n)\mid n$ and $L(n-1)\mid n-1$ are coprime. The same follows from their Theorem~9 with $t=1$. Their Table~2 lists $g(n,2)=6,10,5,7,14,6$ for $n=4,\dots,9$, in agreement with A328202. Their proofs use Kummer's theorem on carries \cite{Kummer}. +\item Joris, Oestreicher and Steinig \cite{JOS} study the greatest common divisor of the binomial coefficients $\binom nk$ with $k$ in an interval $r\le k\le s$; according to later work citing it, they give an explicit general formula for this gcd, which would contain \eqref{eq:maiga} as the case $r=2$, $s=n-2$. We have not been able to consult this paper and have not checked its formula, so we do not know whether it states \eqref{eq:maiga} explicitly. +\end{itemize} +The paper \cite{KL} appeared fifteen years before the conjecture was recorded, and neither \cite{KL} nor \cite{JOS} is cited in the OEIS entry. The math0 referees found no formalization of the result in Lean or Mathlib. We therefore classify the present work as the \emph{first formal proof of a known result}. + +Our proof (Section~\ref{sec:proof}) works one prime at a time and avoids base-$p$ digits: it uses the $p$-adic valuation of $\binom{p^t}{k}$, the congruence $\binom{p^tm}{p^t}\equiv m\pmod p$ (from Lucas's theorem \cite{Lucas}), Pascal's rule and $(N+1)\binom Nj=(j+1)\binom{N+1}{j+1}$. Israel's conjecture follows by a short argument that we did not formalize (Remark~\ref{rem:israel}). + +\section{Statement}\label{sec:statement} + +\begin{definition}\label{def:main} +For $m\ge1$ let $L(m)=p$ if $m=p^t$ for a prime $p$ and an integer $t\ge1$, and $L(m)=1$ otherwise; thus $L(m)=e^{\Lambda(m)}$, where $\Lambda$ is the von Mangoldt function. For $n\ge4$ let $a(n)=\gcd\{\binom nk : 2\le k\le n-2\}$. +\end{definition} + +For $n\ge4$ the entries of row $n$ equal to $1$ or $n$ are exactly $\binom n0=\binom nn=1$ and $\binom n1=\binom n{n-1}=n$, since $\binom nk\ge\binom n2=n(n-1)/2>n$ for $2\le k\le n-2$. So $a(n)$ is the sequence A328202. The FORMULA section of the entry \cite{A328202} contains, verbatim: +\begin{quote} +{\small\texttt{a(n) = A014963(n) * A014963(n - 1) (conjecture).\\ - \_Jon Maiga\_, Oct 08 2019}} +\end{quote} +The name of A014963 \cite{A014963} (offset $1$) is ``Exponential of Mangoldt function M(n): a(n) = 1 unless n is a prime or prime power, in which case a(n) = that prime.'' + +\begin{theorem}\label{thm:main} +For every integer $n\ge4$, +\[ + \gcd\Bigl\{\binom nk : 2\le k\le n-2\Bigr\}=L(n)\,L(n-1). +\] +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A328202.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{4021583e\ldots ca08f}) before any proof attempt. Its definitions and main statement read, verbatim (import, comments, docstrings, blank lines, \texttt{set\_option} lines, all theorems and the secondary definition \decl{statementIsrael} omitted): +\begin{lstlisting} +namespace Math0.Statements.A328202 +def a (n : ℕ) : ℕ := (Finset.Icc 2 (n - 2)).gcd (Nat.choose n) +def expMangoldt (m : ℕ) : ℕ := if IsPrimePow m then m.minFac else 1 +def statement : Prop := + ∀ n : ℕ, 4 ≤ n → a n = expMangoldt n * expMangoldt (n - 1) +end Math0.Statements.A328202 +\end{lstlisting} +Here \texttt{(Finset.Icc 2 (n - 2)).gcd (Nat.choose n)} is the greatest common divisor of $\binom nk$ over $2\le k\le n-2$, which is $a(n)$ by the discussion above. (The programs in the OEIS entry take the gcd over $2\le k\le n/2$, or $2\le k\le\lfloor (n+1)/2\rfloor$ in the PARI program; by the symmetry $\binom nk=\binom n{n-k}$ this is the same set of numbers.) Mathlib's \decl{IsPrimePow m} means $m=p^t$ with $p$ prime and $t\ge1$, and then \decl{m.minFac}, the least prime factor of $m$, is $p$; so \decl{expMangoldt} is $L$. Since $n\ge4$, the truncated subtractions $n-1$ and $n-2$ are exact, the range $2\le k\le n-2$ is nonempty, and the statement covers the whole range $n\ge4$ of the sequence with no extra hypotheses. The values of \decl{a} for $n<4$ play no role. + +The statement file also proves three facts that tie the definitions to their sources: +\begin{lstlisting} +theorem a_data : (List.range 75).map (fun i => a (i + 4)) = [6, 10, 5, 7, 14, ...] +theorem expMangoldt_data : (List.range 95).map (fun i => expMangoldt (i + 1)) = [...] +theorem cast_expMangoldt (m : ℕ) : + (expMangoldt m : ℝ) = Real.exp (ArithmeticFunction.vonMangoldt m) +\end{lstlisting} +In \decl{a_data} the list (elided here) is the complete data section $a(4),\dots,a(78)$ of A328202, and \decl{expMangoldt_data} compares \decl{expMangoldt} with all $95$ terms listed in A014963, for $m=1,\dots,95$. Both are proved by \texttt{decide +kernel}, that is, by evaluating the definitions in the Lean kernel (about four seconds for \decl{a_data}). The lemma \decl{cast_expMangoldt} identifies \decl{expMangoldt} with $e^{\Lambda}$ for Mathlib's von Mangoldt function. +The file also records Israel's conjecture as a separate proposition \decl{statementIsrael}; it is not the target of this work and is not proved in Lean. + +\section{Proof}\label{sec:proof} + +The proof follows \path{lean/Math0/Frontier/OEIS/A328202.lean}; the Lean name of each step is given in brackets. Throughout, $p$ denotes a prime and $v_p$ the $p$-adic valuation. We use two classical facts from Mathlib: the identity +\begin{equation}\label{eq:absorb} + (N+1)\binom Nj=\binom{N+1}{j+1}(j+1)\qquad(N,j\ge0) +\end{equation} +(\decl{Nat.add_one_mul_choose_eq}), and Pascal's rule $\binom{N+1}{j+1}=\binom Nj+\binom N{j+1}$. + +\begin{lemma}[Kummer for prime powers; \decl{not_sq_dvd_choose}]\label{lem:kummer} +Let $t\ge0$ and $1\le k\le p^t$. Then $v_p\binom{p^t}{k}=t-v_p(k)$. In particular, if $v_p(k)\ge t-1$, then $p^2\nmid\binom{p^t}k$. +\end{lemma} + +\begin{proof} +Write $N=p^t$. Then +\[ + \binom Nk=\frac{N(N-1)\cdots(N-k+1)}{k!}=\frac Nk\prod_{j=1}^{k-1}\frac{N-j}{j}. +\] +For $1\le j\le k-1N_0$ there is no term at all, matching $\binom{N_0}{K_0}=0$.) +We prove the lemma by induction on $t$. For $t=0$, $\binom m1=m$. For the step, apply \eqref{eq:lucas} with $N=p^{t+1}m$ and $K=p^{t+1}$: here $N\bmod p=K\bmod p=0$, $\lfloor N/p\rfloor=p^tm$ and $\lfloor K/p\rfloor=p^t$, so $\binom{p^{t+1}m}{p^{t+1}}\equiv\binom00\binom{p^tm}{p^t}\equiv m\pmod p$ by the induction hypothesis. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main} (\decl{result})] +Fix $n\ge4$ and put $g=a(n)$ and $\ell=L(n)L(n-1)$. By definition of the gcd, +\begin{equation}\label{eq:gdiv} + g\mid\binom nk\qquad\text{for all }2\le k\le n-2 . +\end{equation} +We show $\ell\mid g$ and $g\mid\ell$; then $g=\ell$. + +\emph{Step 1: $\ell\mid g$.} Let $2\le k\le n-2$. By Lemma~\ref{lem:lower}, $L(n)\mid\binom nk$ and $L(n-1)\mid\binom nk$, and these two numbers are coprime by Lemma~\ref{lem:L}, so $\ell\mid\binom nk$. As this holds for every $k$ in the range, $\ell$ divides the gcd $g$. + +\emph{Step 2: $g\mid\ell$.} It suffices to show that $p^e\mid g$ implies $p^e\mid\ell$ for every prime $p$ and every $e\ge0$ (Mathlib's \decl{Nat.dvd_iff_prime_pow_dvd_dvd}). For $e=0$ this is trivial, so let $e\ge1$ and $p^e\mid g$; in particular $p\mid g$. We record two observations. +\begin{enumerate} +\item[(i)] If $p\mid\ell$ and $p^2\nmid g$, then $p^e\mid\ell$. Indeed $p^2\nmid g$ forces $e\le1$, so $p^e\mid p\mid\ell$. +\item[(ii)] $p\mid n$ or $p\mid n-1$. Indeed, \eqref{eq:absorb} with $N=n-1$, $j=1$ reads $n(n-1)=2\binom n2$, and $p\mid g\mid\binom n2$ by \eqref{eq:gdiv}. +\end{enumerate} + +\emph{Case A: $p\mid n$.} Write $n=p^tm$ with $p\nmid m$; then $t\ge1$ (because $p\mid n$) and $m\ge1$. + +\emph{Case A1: $m=1$}, i.e.\ $n=p^t$. Then $L(n)=p$ by Lemma~\ref{lem:L}, so $p\mid\ell$, and by (i) it suffices to show $p^2\nmid g$. We exhibit $k_0$ with $2\le k_0\le n-2$ and $p^2\nmid\binom n{k_0}$; then $p^2\nmid g$ by \eqref{eq:gdiv}. +If $t=1$, take $k_0=2$: it lies in the range because $n\ge4$, and $2\le p=p^t$ and $v_p(2)\ge0=t-1$, so $p^2\nmid\binom p2$ by Lemma~\ref{lem:kummer}. +If $t\ge2$, take $k_0=p^{t-1}$. Then $k_0\ge p\ge2$ and $k_0+2\le 2k_0\le pk_0=n$, so $k_0$ lies in the range; moreover $v_p(k_0)=t-1$, so $p^2\nmid\binom{p^t}{k_0}$ by Lemma~\ref{lem:kummer}. + +\emph{Case A2: $m\ge2$.} This case is impossible. Take $k_0=p^t$. Then $k_0\ge p\ge2$ and $k_0+2\le2p^t\le mp^t=n$, so $p\mid g\mid\binom n{p^t}=\binom{p^tm}{p^t}$ by \eqref{eq:gdiv}, contradicting Lemma~\ref{lem:lucas}. + +\emph{Case B: $p\mid n-1$.} Write $n-1=p^tm$ with $p\nmid m$; again $t\ge1$ and $m\ge1$. Note that $p\nmid p^tm+1=n$, since $p\mid p^tm$. + +\emph{Case B1: $m=1$}, i.e.\ $n-1=p^t$. Then $L(n-1)=p$, so $p\mid\ell$, and by (i) it suffices to show $p^2\nmid g$. Take $k_0=p^{t-1}+1\ge2$. It lies in the range: if $t=1$ then $k_0=2$ and $k_0+2=4\le n$; if $t\ge2$ then $p^{t-1}\ge2$ and $p^t\ge2p^{t-1}$, so $k_0+2=p^{t-1}+3\le 2p^{t-1}+1\le p^t+1=n$. By \eqref{eq:absorb} with $N=p^t$ and $j=p^{t-1}$, we have $(p^t+1)\binom{p^t}{p^{t-1}}=\binom{n}{k_0}(p^{t-1}+1)$. +Suppose $p^2\mid g$. Then $p^2\mid\binom n{k_0}$ by \eqref{eq:gdiv}, so $p^2$ divides the left-hand side. As $p\nmid p^t+1$, the numbers $p^2$ and $p^t+1$ are coprime, hence $p^2\mid\binom{p^t}{p^{t-1}}$. This contradicts Lemma~\ref{lem:kummer}, since $v_p(p^{t-1})=t-1$. Hence $p^2\nmid g$. + +\emph{Case B2: $m\ge2$.} This case is impossible. Take $k_0=p^t+1\ge2$; then $k_0+2=p^t+3\le 2p^t+1\le mp^t+1=n$, because $p^t\ge2$. By \eqref{eq:absorb} with $N=p^tm$ and $j=p^t$, we have $(p^tm+1)\binom{p^tm}{p^t}=\binom n{k_0}(p^t+1)$. +Since $p\mid g\mid\binom n{k_0}$, the prime $p$ divides the left-hand side, hence divides $p^tm+1$ or $\binom{p^tm}{p^t}$. The first is impossible because $p\mid p^tm$, and the second contradicts Lemma~\ref{lem:lucas}. + +By (ii), Cases A and B are exhaustive, and in every case that can occur we have shown $p^e\mid\ell$. Hence $g\mid\ell$, and with Step~1, $g=\ell$. +\end{proof} + +\begin{remark}[Israel's conjecture; not formalized]\label{rem:israel} +Theorem~\ref{thm:main} implies the conjecture of Israel recorded in A328202 (the ``only if'' direction below), together with the two facts he states before it (the ``if'' direction): for $n\ge4$, $a(n)>n$ holds if and only if $n$ is a Fermat prime $>3$ or $n-1$ is a Mersenne prime. Indeed, if at most one of $n$, $n-1$ is a prime power, then $a(n)$ equals $1$, $L(n)\le n$ or $L(n-1)\le n-1$, so $a(n)\le n$. If both are prime powers, one of them is even, hence a power of $2$, and $a(n)=2p$ where the other one is $p^s$ with $p$ an odd prime. If $s\ge2$ then $2p3$ (a prime of the form $2^r+1$ has $r$ a power of $2$), or $n-1=p=2^r-1$ is a Mersenne prime; in both cases $a(n)=2p>n$. Conversely, if $n$ is a Fermat prime $>3$ or $n-1$ is a Mersenne prime, then $n$ and $n-1$ are both prime powers, the odd one is a prime $p$, and $a(n)=2p>n$. This deduction is not part of the Lean development, and the proposition \decl{statementIsrael} of the statement file is not proved there. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A328202.lean} in the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A328202.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A328202.result}, of type \decl{Math0.Statements.A328202.statement}. The auxiliary lemmas, all private, correspond to Lemmas~\ref{lem:kummer}--\ref{lem:lucas}; their statements read, verbatim (proofs and docstrings omitted): +\begin{lstlisting} +private lemma expMangoldt_dvd_self (m : ℕ) : expMangoldt m ∣ m +private lemma expMangoldt_prime_pow {p t : ℕ} (hp : p.Prime) (ht : t ≠ 0) : + expMangoldt (p ^ t) = p +private lemma expMangoldt_dvd_choose (n k : ℕ) (hk0 : k ≠ 0) (hkn : k ≠ n) : + expMangoldt n ∣ n.choose k +private lemma expMangoldt_pred_dvd_choose (n k : ℕ) (hk : 2 ≤ k) (hkn : k + 2 ≤ n) : + expMangoldt (n - 1) ∣ n.choose k +private lemma not_sq_dvd_choose {p t k : ℕ} (hp : p.Prime) (hk0 : k ≠ 0) (hk : k ≤ p ^ t) + (hf : t - 1 ≤ k.factorization p) : ¬ p ^ 2 ∣ (p ^ t).choose k +private lemma choose_pow_mul_modEq {p m : ℕ} (hp : p.Prime) : + ∀ t : ℕ, (p ^ t * m).choose (p ^ t) ≡ m [MOD p] +private lemma not_dvd_choose_pow_mul {p m t : ℕ} (hp : p.Prime) (hm : ¬ p ∣ m) : + ¬ p ∣ (p ^ t * m).choose (p ^ t) +theorem result : statement +\end{lstlisting} +The proof of \decl{result} follows Section~\ref{sec:proof} case by case; the decompositions $n=p^tm$ and $n-1=p^tm$ come from \decl{Nat.exists_eq_pow_mul_and_not_dvd}, and the range conditions on $k_0$ are closed by \texttt{omega} and \texttt{nlinarith}. The proof file contains no \texttt{decide}, \texttt{native\_decide}, \texttt{sorry} or \texttt{set\_option}. + +\subsection*{Audit} +The file ends with the command +\begin{lstlisting} +#math0_settles Math0.Frontier.A328202.result Math0.Statements.A328202.statement +\end{lstlisting} +defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself. It fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (rejecting \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically \decl{statement} or its negation, up to metadata, with no unfolding. Running \texttt{lake env lean Math0/Frontier/OEIS/A328202.lean} in the directory \path{lean} prints +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A328202.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A328202.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A328202.result' proves 'Math0.Statements.A328202.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}. The repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use: the statement is a math0 formalization of an OEIS conjecture. +To reproduce, run \path{scripts/verify.sh} from the repository root. It fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. Once its dependencies are built, the single file can also be checked with the \texttt{lake env lean} command above. + +{\small +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171 [cs.AI], 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{JOS} +H.~Joris, C.~Oestreicher, and J.~Steinig, \emph{The greatest common divisor of certain sets of binomial coefficients}, J. Number Theory \textbf{21} (1985), no.~1, 101--119. + +\bibitem{KL} +G.~Kaplan and D.~Levy, \emph{GCD of truncated rows in Pascal's triangle}, Integers \textbf{4} (2004), \#A14. \url{https://math.colgate.edu/~integers/e14/e14.pdf}. + +\bibitem{Kummer} +E.~E. Kummer, \emph{\"Uber die Erg\"anzungss\"atze zu den allgemeinen Reciprocit\"atsgesetzen}, J. Reine Angew. Math.\ \textbf{44} (1852), 93--146. + +\bibitem{Lucas} +\'E.~Lucas, \emph{Th\'eorie des fonctions num\'eriques simplement p\'eriodiques}, Amer. J. Math.\ \textbf{1} (1878), 184--240 and 289--321. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A014963} +The OEIS Foundation Inc., Entry A014963 in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A014963}. + +\bibitem{A328202} +The OEIS Foundation Inc., Entry A328202 in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A328202} (revision \#46, October~10, 2026). + +\bibitem{Ram} +B.~Ram, \emph{Common factors of $\frac{n!}{m!\,(n-m)!}$ $(m=1,2,\dots,n-1)$}, J. Indian Math. Club \textbf{1} (1909), 39--43. + +\end{thebibliography} +} +\end{document} diff --git a/results/oeis-a332010/README.md b/results/oeis-a332010/README.md new file mode 100644 index 0000000..52d406f --- /dev/null +++ b/results/oeis-a332010/README.md @@ -0,0 +1,52 @@ +# A332010: the average first letter of one-descent derangements has denominator 2^(n-2) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A332010 +**Date:** 2026-10-19 + +## Result + +For every n ≥ 2, take the derangements of {1, ..., n} (in one-line notation) that have exactly one descent. The average of their first letters, written in lowest terms, has denominator 2^(n-2). This is Kagey's conjecture T(n,1) = 2^(n-2) in OEIS A332010. + +## Assessment + +A permutation with exactly one descent is sorted(A) followed by sorted(complement of A). Checking fixed points run by run shows it is a derangement exactly when 1 is not in A and n is in A. That gives 2^(n-2) such derangements, and their first letter is min A. Summing min A over these sets gives 3*2^(n-2) - 1, which is odd, so the reduced denominator is 2^(n-2). This is a half-page counting argument built on a textbook description of one-descent permutations, and the count itself already follows from A219836. It needs no new idea. + +*Follows from:* Standard fact that a permutation with one descent is an increasing word on a set A followed by an increasing word on its complement (a Grassmannian permutation). A219836 already implies the count 2^(n-2). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A332010](https://oeis.org/A332010) as [`Math0.Statements.A332010.statement`](../../lean/Math0/Statements/OEIS/A332010.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A332010.lean`](../../lean/Math0/Frontier/OEIS/A332010.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: T(n, 1) = 2^(n-2)." (A332010, entry by Peter Kagey, Feb 04 2020) + +Referees: No prior resolution found. +- OEIS A332010 and A332009 (Peter Kagey, Feb 04 2020; last edits Mar 30 2024) still state "Conjecture: T(n,1) = 2^(n-2)" and "Conjecture: T(n,1) = A083329(n-1)", with no proof recorded in comments or %E lines. I checked both the local mirror and raw.githubusercontent oeisdata. +- Related known facts: + - A219836 (Callan 2012; links to Fu–Lin–Zeng arXiv:1507.05184 and Alexandersson arXiv:2609.07325) gives a recurrence implying there are 2^(n-2) derangements with one descent. That is only the unreduced denominator. + - M. Conger, arXiv math/0508112, proves E[π(1) | des = k] = k+1 over all permutations; this is the analogue for all permutations that the A332010 comment cites. + - Kagey, arXiv:2112.05281, treats expected π(1) given k-cycles and does not address derangements by descents. + - Eriksen–Freij–Wästlund, arXiv:0811.1925 / EJC 16 (2009) R32, and Han–Xin (2007) cover derangements with prescribed descent sets, with no first-letter averages. +- Searches of Math StackExchange, arXiv and SeqFan found nothing. MathOverflow was not reachable through the search tool. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a332010, + author = {{math0}}, + title = {{A332010: the average first letter of one-descent derangements has denominator 2^(n-2)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a332010}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a332010/paper.pdf b/results/oeis-a332010/paper.pdf new file mode 100644 index 0000000..dc570c8 Binary files /dev/null and b/results/oeis-a332010/paper.pdf differ diff --git a/results/oeis-a332010/paper.tex b/results/oeis-a332010/paper.tex new file mode 100644 index 0000000..9fe9dd9 --- /dev/null +++ b/results/oeis-a332010/paper.tex @@ -0,0 +1,353 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,rw,constructor,by_contra,set,apply}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 + {∃}{{$\exists$}}1 {∈}{{$\in$}}1 {∉}{{$\notin$}}1 + {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {¬}{{$\neg$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 + {↔}{{$\leftrightarrow$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {≠}{{$\ne$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\cD}{\mathcal{D}} +\newcommand{\des}{\operatorname{des}} + +\title[Derangements with one descent]{The average first letter of derangements with one descent has denominator $2^{n-2}$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 19, 2026} + +\begin{document} +\begin{abstract} +For $n\ge2$ let $T(n,1)$ be the denominator, in lowest terms, of the average first letter of the derangements of $\{1,\dots,n\}$ with exactly one descent; these numbers form the first column of the triangle A332010 of the OEIS, contributed by Peter Kagey in 2020. +We prove Kagey's conjecture, recorded in that entry, that $T(n,1)=2^{n-2}$: the derangements in question are exactly the $2^{n-2}$ words $s\,n\,1\,\bar s$, where $s$ is the increasing word on a subset of $\{2,\dots,n-1\}$ and $\bar s$ the increasing word on its complement, and their first letters sum to $3\cdot2^{n-2}-1$, which is coprime to $2^{n-2}$ (it is odd for $n\ge3$). +To our knowledge this is the first proof of the conjecture; the argument is elementary and also gives the companion conjecture for the numerators in A332009. +The theorem is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry (not part of the formal-conjectures repository), whose definitions are kernel-checked against the first $25$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +For $n\ge1$ we write a permutation of $[n]=\{1,\dots,n\}$ in one-line notation, as the word $w=w_1w_2\cdots w_n$ of its values. It is a \emph{derangement} if $w_i\ne i$ for every $i$, and $i\in\{1,\dots,n-1\}$ is a \emph{descent} of $w$ if $w_i>w_{i+1}$; let $\des(w)$ be the number of descents. The entry A332010 of the OEIS \cite{A332010}, contributed by Peter Kagey on February~4, 2020, is the irregular triangle (offset $2$) +\[ + T(n,k)=\text{denominator, in lowest terms, of }\ \frac{1}{|\cD_{n,k}|}\sum_{w\in\cD_{n,k}}w_1, +\] +where $\cD_{n,k}$ is the set of derangements $w$ of $[n]$ with $\des(w)=k$; row $n\ge2$ consists of $T(n,1),\dots,T(n,n-1)$ for even $n$ and $T(n,1),\dots,T(n,n-2)$ for odd $n$. The numerators form the companion entry A332009 \cite{A332009}. For example, $\cD_{4,1}=\{2341,2413,3412,4123\}$ and the average first letter is $11/4$, so $T(4,1)=4$. + +The comments of A332010 contain the conjecture $T(n,1)=2^{n-2}$, and those of A332009 the conjecture that the corresponding numerator is $A083329(n-1)$, where $A083329(j)=3\cdot2^{j-1}-1$ for $j\ge1$ \cite{A083329}. We prove both (Theorem~\ref{thm:main} and Corollary~\ref{cor:num}); only the first is formalized. The idea is simple: a word with distinct letters and one descent is the concatenation of two increasing runs, and in a derangement the letter $1$ cannot lie in the first run (it would sit at position $1$) and the letter $n$ cannot lie in the second run (it would sit at position $n$). + +\subsection*{Prior work and status} +The analogous denominators for all permutations are all $1$, as the entry remarks: the expected first letter of a permutation of $[n]$ with $k$ descents is $k+1$, a result of Conger \cite{Conger}. Kagey's later paper \cite{Kagey} studies the expected value of the letters of permutations with a given number of $k$-cycles and does not treat derangements by descents. The number of derangements of $[n]$ with $k$ descents is the triangle A219836 of David Callan \cite{A219836}; its recurrence gives $|\cD_{n,1}|=2^{n-2}$, which is the denominator \emph{before} reduction, and the entry links related work of Fu, Lin and Zeng \cite{FLZ} and of Alexandersson \cite{Alexandersson}. Derangements with prescribed descent sets were enumerated by Han and Xin \cite{HanXin} and by Eriksen, Freij and W\"astlund \cite{EFW}; we found no treatment of the first letter there. + +Both conjectures are still marked ``Conjecture'' in the current revisions of A332010 (\#17) and A332009 (\#18), dated March~30, 2024, in the copy of the OEIS database used by math0 (October~17, 2026), where no other entry refers to either sequence. The math0 referees' searches (arXiv, Mathematics Stack Exchange, the SeqFan list, and the papers above) found no proof; MathOverflow could not be searched. We therefore classify the result as new. The argument is short and elementary, and we do not claim that the description of one-descent derangements (Propositions~\ref{prop:words}--\ref{prop:converse}) is new; what we did not find is any proof of the conjecture. + +\section{Statement}\label{sec:statement} + +\begin{theorem}\label{thm:main} +Let $n\ge2$. Then \textup{(1)} $|\cD_{n,1}|=2^{n-2}$; \textup{(2)} $\sum_{w\in\cD_{n,1}}w_1=3\cdot2^{n-2}-1$; and \textup{(3)} the average first letter of the elements of $\cD_{n,1}$ is $(3\cdot2^{n-2}-1)/2^{n-2}=3-2^{2-n}$, a fraction in lowest terms; in particular $T(n,1)=2^{n-2}$. +\end{theorem} + +The formal statement is the last assertion, $T(n,1)=2^{n-2}$; parts (1) and (2) are proved in Lean as intermediate steps. + +\begin{corollary}[A332009; not formalized]\label{cor:num} +For $n\ge2$ the numerator of the average first letter of $\cD_{n,1}$ in lowest terms is $3\cdot2^{n-2}-1=A083329(n-1)$. +\end{corollary} + +The name of A332010 \cite{A332010} reads, verbatim, ``\texttt{Irregular triangle of denominators of the average value of the first letter over all derangements of {\char123}1, 2, ..., n{\char125} with k descents.}'', and its comments contain, verbatim, ``\texttt{Even-indexed rows have length n - 1; odd-indexed rows have length n - 2.}'' and +\begin{quote} +\texttt{Conjecture: T(n, 1) = 2\^{}(n-2).} +\end{quote} +The comment is unsigned; the revision history of the entry shows that it was part of Peter Kagey's original submission of February~4, 2020. It gives no range of $n$; we read it for every row $n\ge2$ of the triangle. The companion comment in A332009 reads ``\texttt{Conjecture: T(n, 1) = A083329(n - 1).}'' + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A332010.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{4e58e0c3\ldots 7cd}) before any proof attempt. Its definitions and the statement read, verbatim (omitting the import, comments and docstrings, blank lines, the theorems, and the auxiliary definitions \decl{derB}, \decl{desB}, \decl{DC} and \decl{rowC} used only for the kernel data check described below): +\begin{lstlisting} +namespace Math0.Statements.A332010 +def IsDerangement (w : List ℕ) : Prop := ∀ (i : ℕ) (h : i < w.length), w[i] ≠ i + 1 +instance : DecidablePred IsDerangement := fun w => by unfold IsDerangement; infer_instance +def des (w : List ℕ) : ℕ := (w.zip w.tail).countP fun p => p.2 < p.1 +def ders (n k : ℕ) : List (List ℕ) := + (List.range' 1 n).permutations.filter fun w => decide (IsDerangement w) && des w == k +def avgFirstLetter (E : List (List ℕ)) : ℚ := + (((E.map fun w => w.headD 0).sum : ℕ) : ℚ) / ((E.length : ℕ) : ℚ) +def avgFirst (n k : ℕ) : ℚ := avgFirstLetter (ders n k) +def T (n k : ℕ) : ℕ := (avgFirst n k).den +def rowLen (n : ℕ) : ℕ := if n % 2 = 0 then n - 1 else n - 2 +def row (n : ℕ) : List ℕ := (List.range (rowLen n)).map fun j => T n (j + 1) +def statement : Prop := ∀ n : ℕ, 2 ≤ n → T n 1 = 2 ^ (n - 2) +end Math0.Statements.A332010 +\end{lstlisting} +Words are lists of natural numbers; \texttt{w[i]} is the letter at the $0$-based index $i$, i.e.\ at position $i+1$, so \decl{IsDerangement} is the derangement condition. \texttt{List.permutations} lists each rearrangement of $[1,\dots,n]$ (\texttt{List.range' 1 n}) once, \decl{des} counts the adjacent pairs $(w_i,w_{i+1})$ with $w_{i+1} row (i + 2)) = + [1, 2, 4, 1, 1, 8, 3, 4, 16, 104, 40, 24, 1, 32, 392, 896, 480, 54, 64, 152, 308, 1496, 63, + 108, 1] := by + simp only [row_eq_rowC] + decide +kernel +\end{lstlisting} +Since \texttt{List.permutations} uses well-founded recursion, which the kernel does not evaluate efficiently, the check goes through a copy \decl{rowC} of \decl{row} that enumerates words with the structurally recursive \texttt{List.permutations'} and uses recursive tests \decl{derB} and \decl{desB}, proved equal to \decl{IsDerangement} and \decl{des} (\decl{derB_one}, \decl{desB_eq}); its word lists are permutations of \texttt{ders n k} (\decl{ders_perm}), which changes neither count nor sum (\decl{avgFirstLetter_perm}), whence \decl{row_eq_rowC}. Thus the kernel evaluates rows $2$ to $8$ (row $8$ runs through all $8!=40320$ words) and matches the first $25$ listed terms, including $T(n,1)=2^{n-2}$ for $2\le n\le8$; rows $9$ to $11$ are out of its reach. The theorem \decl{example_T41} checks the worked example of the entry ($\cD_{4,1}$, the average $11/4$, and $T(4,1)=4$). + +\section{Proof}\label{sec:proof} + +We follow the Lean file \path{lean/Math0/Frontier/OEIS/A332010.lean}; each step names the corresponding declaration. Words are finite sequences of natural numbers, $|u|$ is the length of $u$, juxtaposition is concatenation, and \emph{increasing} means strictly increasing. Positions are numbered from $1$. + +\begin{definition}\label{def:free} +Let $p\ge0$. A word $u=u_1\cdots u_\ell$ is \emph{free at $p$} if $u_j\ne p+j-1$ for $1\le j\le\ell$; that is, placed at positions $p,p+1,\dots,p+\ell-1$, no letter of $u$ is at its own position. +\end{definition} + +In Lean this is \texttt{derB u p = true}, where \texttt{derB [] p = true} and \texttt{derB (x :: xs) p = (x != p \&\& derB xs (p + 1))}. A word is a derangement if and only if it is free at $1$ (\decl{derB_one}), and $uv$ is free at $p$ if and only if $u$ is free at $p$ and $v$ is free at $p+|u|$ (\decl{derB_append}). + +\begin{lemma}[\decl{derB_of_lower}, \decl{lower_of_derB}]\label{lem:lower} +Let $u$ be an increasing word and $p\ge0$. \textup{(1)} If every letter of $u$ is $>p$, then $u$ is free at $p$. \textup{(2)} If every letter of $u$ is $\ge p$ and $u$ is free at $p$, then every letter of $u$ is $>p$. +\end{lemma} + +\begin{proof} +(1) Since $u$ is an increasing sequence of integers, $u_j\ge u_1+j-1>p+j-1$. (2) We have $u_1\ge p$ and $u_1\ne p$, so $u_1>p$, and $u_j\ge u_1$ for all $j$. In Lean both parts are proved by induction along $u$, passing from $p$ to $p+1$ for the tail. +\end{proof} + +\begin{lemma}[\decl{derB_of_upper}, \decl{upper_of_derB}]\label{lem:upper} +Let $u=u_1\cdots u_\ell$ be an increasing word, $p\ge0$, and $q=p+\ell-1$ the last position of $u$ when placed at $p$. \textup{(1)} If every letter of $u$ is $x$, so $x\,u'\,a$ is increasing, and $w=(x\,u')\,a\,b\,v$. +\end{proof} + +Fix $m\ge0$ and let $R_m=2\,3\cdots(m+1)$ be the increasing word on $\{2,\dots,m+1\}$ (\texttt{List.range' 2 m}). The subwords (sublists) of $R_m$ are exactly the increasing words with letters in $\{2,\dots,m+1\}$, one for each subset; Mathlib's \texttt{List.sublists'} lists the $2^m$ of them, each once. + +\begin{definition}[\decl{word}, \decl{words}]\label{def:word} +For a sublist $s$ of $R_m$ let $\bar s$ be the sublist of $R_m$ formed by the letters not in $s$, and +\[ + W_m(s)=s\,(m+2)\,1\,\bar s . +\] +Let $\mathcal W_m$ be the list of the words $W_m(s)$, with $s$ running over the sublists of $R_m$. +\end{definition} + +For $m=2$ the sublists $\emptyset,2,3,23$ give $4123$, $2413$, $3412$, $2341$, the four words of the example in A332010. + +\begin{proposition}[\decl{word_mem_ders}]\label{prop:words} +For every sublist $s$ of $R_m$, $W_m(s)$ is a derangement of $[m+2]$ with exactly one descent. +\end{proposition} + +\begin{proof} +Write $v=\bar s$, so $W=W_m(s)=s\,(m+2)\,1\,v$. The words $s$ and $v$ are increasing, their letters lie in $\{2,\dots,m+1\}$, and each element of $\{2,\dots,m+1\}$ is a letter of exactly one of them. Hence $W$ has distinct letters and its set of letters is $[m+2]$, so $W$ is a rearrangement of $1\,2\cdots(m+2)$ (\texttt{List.perm\_ext\_iff\_of\_nodup}); comparing lengths, $|s|+|v|=m$. + +\emph{No fixed point.} By \decl{derB_append}, $W$ is free at $1$ if and only if: $s$ is free at $1$, which holds by Lemma~\ref{lem:lower}(1) since its letters are $\ge2$; the letter $m+2$ is not at position $|s|+1\le m+1$; the letter $1$ is not at position $|s|+2\ge2$; and $v$ is free at $|s|+3$. For the last condition, $v$ occupies positions $|s|+3,\dots,|s|+2+|v|=m+2$ and its letters are $\le m+11$, and Lemma~\ref{lem:upper}(2) that every letter of $Q$ is $1$ and $ 1, T(n,2) = A000071(n+2) = F(n+2) - 1; +(2) for n ≥ 2, T(n,n-1) = A339252(n-2), where a(0)=1, a(1)=4, a(2)=11, a(m+3)=4a(m+2)-4a(m+1); +(3) for n ≥ 3, T(n,n-2) = A339254(n-3), where a(0..4)=1,7,24,70,193 and a(m+5)=6a(m+4)-12a(m+3)+8a(m+2); +(4) for n ≥ 4, T(n,n-3) = A339029(n-4), the coefficients of (1+4x-20x^2+8x^3+33x^4-4x^5-33x^6)/(1-2x)^4. + +## Assessment + +The height-2 conjecture comes down to one observation: the second-row bricks pick distinct positions among the b+1 positions above a base of b bricks. That gives a diagonal binomial sum, which is a textbook Fibonacci identity. For heights n-1, n-2 and n-3 the excess over one brick per row is at most 3. Then only 13 translation-normalized row states can occur, and a single brick over a single brick always has exactly 2 placements. So the count is a finite transfer-matrix recursion whose solutions are 2^h times polynomials of degree at most 3, checked by induction against a finite table. These are standard enumerative techniques that need no new idea, and once the state space is written down the proof is a finite computation matched to closed forms already recorded in the cross-referenced entries. + +*Follows from:* Height 2: a diagonal binomial sum, T(n,2) = sum_b C(b+1, n-b), which equals F(n+2)-1 by the standard Fibonacci identity (Luschny already noted the binomial-triangle link in A339494). Near-diagonals: the standard row-by-row transfer-matrix recursion on translation-normalized rows, compared with the closed forms 2^h times a polynomial already recorded in A339252, A339254 and A339029. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A333650](https://oeis.org/A333650) as [`Math0.Statements.A333650.statement`](../../lean/Math0/Statements/OEIS/A333650.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A333650.lean`](../../lean/Math0/Frontier/OEIS/A333650.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C A333650 Conjecture: For n > 1, T(n,2) = A000071(n+2). [entry author _Peter Kagey_, Mar 31 2020]; Conjecture: T(n,n-1) = A339252(n-2). - _Peter Kagey_, Nov 21 2020; Conjecture: T(n,n-2) = A339254(n-3). - _Peter Luschny_, Nov 29 2020; Conjecture: T(n,n-3) = A339029(n-4). - _Peter Luschny_, Dec 01 2020 (summarised by Luschny as T(2n+k, n+k) = d_n(n+k-1), k>=1, 0<=n<=3). + +Referees: OEIS A333650 (Kagey, Mar 2020; conjectures by Kagey Nov 21 2020 and Luschny Nov 29 / Dec 1 2020; still marked Conjecture as of revision #68, Aug 12 2022). A339494 (Luschny, Dec 2020): unproved remark that towers of height <=2 by base size form the binomial triangle C(k,n-k) (A030528), whose row sums are Fibonacci numbers, which is essentially the height-2 argument. A339495 assumes the height-2 formula. A339252, A339254, A339029: closed forms of the target sequences only. Definition of domino towers: A264746, A320314; Bona, Handbook of Enumerative Combinatorics, pp. 25-27; Gouyou-Beauchamps & Viennot 1988; Bétréma & Penaud 1993; Zeilberger arXiv:1208.2258. Related papers with no height enumeration: Ekhad & Zeilberger arXiv:1212.4105; T. M. Brown, Convex Domino Towers (JIS 2017, arXiv:1608.01562) and k-omino towers (arXiv:1608.01563); A. Haupt, S-omino towers (JIS 2021, arXiv:1810.10428); Ardila arXiv:1409.2562. Math StackExchange 2949131 and 3659431 (Kagey): symmetric towers and the 4^(n-1) variant only. No prior proof or counterexample of any of the four conjectures found. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a333650, + author = {{math0}}, + title = {{Domino towers of height 2 and of height n-1, n-2, n-3 (A333650): all four Kagey/Luschny conjectures}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a333650}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a333650/paper.pdf b/results/oeis-a333650/paper.pdf new file mode 100644 index 0000000..d187e1a Binary files /dev/null and b/results/oeis-a333650/paper.pdf differ diff --git a/results/oeis-a333650/paper.tex b/results/oeis-a333650/paper.tex new file mode 100644 index 0000000..4adef8e --- /dev/null +++ b/results/oeis-a333650/paper.tex @@ -0,0 +1,400 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{booktabs} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,rw}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {∈}{{$\in$}}1 {≠}{{$\ne$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {→}{{$\to$}}1 {∧}{{$\wedge$}}1 + {∑}{{$\sum$}}1 {×}{{$\times$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 + {⟦}{{$[\![$}}1 {⟧}{{$]\!]$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\supp}{\operatorname{supp}} +\newcommand{\ways}{\operatorname{ways}} +\newcommand{\nrm}{\operatorname{nrm}} +\newcommand{\St}{\mathcal{S}} + +\title[Domino towers by height (OEIS A333650)]{Domino towers of height $2$ and of height $n-1$, $n-2$, $n-3$: proof of the four conjectures in OEIS A333650} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 19, 2026} + +\begin{document} +\begin{abstract} +Let $T(n,k)$ be the number of domino towers with $n$ bricks and $k$ rows (OEIS A333650). +We prove the four conjectures recorded in that entry by P.~Kagey and P.~Luschny in 2020: $T(n,2)=F_{n+2}-1$ for $n\ge2$, and $T(n,n-1)$, $T(n,n-2)$, $T(n,n-3)$ are the terms of index $n-2$, $n-3$, $n-4$ of the sequences A339252, A339254, A339029. +For the near-diagonals, the row-by-row recursion on rows normalized up to translation closes on thirteen states, each counted by $2^h$ times an explicit polynomial of degree at most $3$ in the number $h$ of remaining rows. +To our knowledge the near-diagonal identities are new (the height-two case is elementary and was in effect observed by Luschny); the entry still lists all four as conjectures. +The theorem is verified in Lean~4 against a frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry and checked against its data; it is not part of formal-conjectures. +\end{abstract} +\maketitle + +\section{Introduction} + +A \emph{domino tower} is a stack of bricks of width $2$ and height $1$ in the plane, arranged in rows so that (1) each row is offset from the row below by half a brick, (2) the bottom row is contiguous, and (3) each brick above the bottom row is supported from below by at least half a brick (this is the definition in A264746 and A320314 \cite{A264746}, by Kagey). As in A333650, stability is not required, towers are counted up to translation, and mirror images are different. +There are $3^{n-1}$ domino towers with $n$ bricks; the count goes back to the theory of directed animals with a compact source \cite{GBV,BP} (see Zeilberger \cite{Z} and Bóna's \emph{Handbook} \cite[pp.~25--27]{Bona}). Towers of other pieces, and convex towers, are counted in \cite{EZ,Br1,Br2,Ha}. + +The OEIS entry A333650 \cite{A333650}, created by Peter Kagey on March~31, 2020, refines $3^{n-1}$ by height: $T(n,k)$ is the number of domino towers with $n$ bricks and $k$ rows. It lists rows $1$--$10$ (rows up to $18$ in a b-file), states $T(n,1)=1$ and $T(n,n)=2^{n-1}$, and records four conjectures (quoted in Section~\ref{sec:statement}): $T(n,2)=\mathrm{A000071}(n+2)$ (Kagey), $T(n,n-1)=\mathrm{A339252}(n-2)$ (Kagey), $T(n,n-2)=\mathrm{A339254}(n-3)$ and $T(n,n-3)=\mathrm{A339029}(n-4)$ (Luschny). We prove all four (Theorem~\ref{thm:main}). + +\subsection*{Method} +For height two, $T(n,2)=\sum_b\binom{b+1}{n-b}$, a diagonal binomial sum. For a tower with $n$ bricks and $n-e$ rows ($e$ bricks beyond one per row), the recursion over rows normalized up to translation involves thirteen states when $e\le3$, each counted by $2^h$ times an explicit polynomial in the number $h$ of remaining rows; the right-hand sequences have the same closed forms. + +\subsection*{Status and prior work} +All four statements are still marked ``Conjecture'' in A333650 (revision \#68, August~12, 2022). +The entries A339252, A339254, A339029 \cite{A339252} define the right-hand sequences by recurrences or a generating function and record their closed forms (Corollary~\ref{cor:closed}; for A339252 by K.~Ryde, for A339254 by S.~Spezia), but they do not connect them to towers. +For height two, Luschny remarks in A339494 \cite{A339494} (December 2020) that the towers of height at most $2$, classified by base size, form ``the binomial triangle $C(k, n-k)$ without the first column, triangle A030528'', which ``highlights the connection between the Pascal triangle and the Fibonacci numbers''; a formula in A339495 \cite{A339494} presupposes conjecture (1). This is essentially our argument for (1), but no proof is recorded. +The math0 referees found no proof or counterexample of any of the four conjectures: the works on domino towers they read \cite{GBV,BP,Z,Bona,EZ,Br1,Br2,Ha} count towers by bricks, base size or convexity, not by height; Kagey's questions on Mathematics Stack Exchange concern symmetric towers and towers without the half-brick offset \cite{K1}; and web searches for the polynomials of Corollary~\ref{cor:closed} and for SeqFan discussions found nothing beyond the OEIS entries themselves. +We therefore classify the result as \emph{new}, the height-two case being elementary. +A333650 is not among the OEIS statements of formal-conjectures \cite{FC}. Its remark that A038622 ``appears to give'' the counts by base size is not treated here. + +\section{Statement}\label{sec:statement} + +The COMMENTS section of A333650 \cite{A333650} contains, verbatim: +\begin{quote}\small\ttfamily +Conjecture: For n > 1, T(n,2) = A000071(n+2).\\ +Conjecture: T(n,n-1) = A339252(n-2). - \_Peter Kagey\_, Nov 21 2020\\ +Conjecture: T(n,n-2) = A339254(n-3). - \_Peter Luschny\_, Nov 29 2020\\ +Conjecture: T(n,n-3) = A339029(n-4). - \_Peter Luschny\_, Dec 01 2020 +\end{quote} +and Luschny's summary (December~1, 2020) $T(2n+k,n+k)=d_n(n+k-1)$ for $k\ge1$, $0\le n\le3$, with explicit $d_n$ (Corollary~\ref{cor:closed}). The first conjecture is unsigned, hence by convention by the entry's author, Kagey (March~31, 2020). +The entry's definition reads: ``$T(n,k)$ gives the number of domino towers of height $k$ consisting of $n$ bricks. The towers must have a contiguous base of bricks, and each brick must be at least half supported below by another brick. The stacks do not need to be stable.'' The offset is $1$, so $1\le k\le n$. + +\begin{definition}\label{def:tower} +Positions are measured in half bricks: a brick with left end $x\in\Z$ occupies $[x,x+2)$. Let $B_b=\{0,2,\dots,2b-2\}$. A \emph{tower of height $k$ with $n$ bricks} is a sequence $(L_0,\dots,L_{k-1})$ of finite subsets of $\Z$ (the left ends of the bricks of row $i$, row $0$ at the bottom) such that +(a) every $L_i$ is nonempty; +(b) $L_0=B_b$ for some $b\ge1$; +(c) $|x-y|\ge2$ for distinct $x,y$ in the same row; +(d) $x\equiv i\pmod 2$ for $x\in L_i$; +(e) for every $x\in L_{i+1}$ there is $y\in L_i$ with $|x-y|\le1$ (so the bricks overlap in length $2-|x-y|\ge1$); +(f) $\sum_i|L_i|=n$. +$T(n,k)$ is the number of towers of height $k$ with $n$ bricks. +\end{definition} +Let $F_m$ be the Fibonacci numbers ($F_0=0$, $F_1=1$), and let $a_1,a_2,a_3\colon\N\to\Z$ be A339252, A339254, A339029 (offset $0$): +\begin{gather*} +a_1(0),a_1(1),a_1(2)=1,4,11,\quad a_1(m+3)=4a_1(m+2)-4a_1(m+1);\\ +a_2(0),\dots,a_2(4)=1,7,24,70,193,\quad a_2(m+5)=6a_2(m+4)-12a_2(m+3)+8a_2(m+2);\\ +\textstyle\sum_{m\ge0}a_3(m)x^m=(1+4x-20x^2+8x^3+33x^4-4x^5-33x^6)/(1-2x)^4 . +\end{gather*} + +\begin{theorem}\label{thm:main} +(1) $T(n,2)=F_{n+2}-1$ for $n\ge2$.\quad (2) $T(n,n-1)=a_1(n-2)$ for $n\ge2$.\quad (3) $T(n,n-2)=a_2(n-3)$ for $n\ge3$.\quad (4) $T(n,n-3)=a_3(n-4)$ for $n\ge4$. +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A333650.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{20320a51\ldots b96302}) before any proof attempt. Its definitions read (verbatim; the import, comments, docstrings, blank lines, and all lemmas and auxiliary definitions omitted): +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +namespace Math0.Statements.A333650 +open Finset +def base (b : ℕ) : Finset ℤ := (range b).image fun j : ℕ => 2 * (j : ℤ) +def IsTower (n k : ℕ) (t : List (Finset ℤ)) : Prop := + t.length = k ∧ (∀ L ∈ t, L.Nonempty) ∧ + (∃ b, 0 < b ∧ t.head? = some (base b)) ∧ + (∀ L ∈ t, ∀ x ∈ L, ∀ y ∈ L, x ≠ y → 2 ≤ |x - y|) ∧ + (∀ (i : ℕ) (hi : i < t.length), ∀ x ∈ t[i], Even (x - i)) ∧ + (∀ (i : ℕ) (hi : i + 1 < t.length), ∀ x ∈ t[i + 1], ∃ y ∈ t[i], |x - y| ≤ 1) ∧ + (t.map Finset.card).sum = n +noncomputable def T (n k : ℕ) : ℕ := {t | IsTower n k t}.ncard +def A000071 (n : ℕ) : ℤ := (Nat.fib n : ℤ) - 1 +def A339252 : ℕ → ℤ + | 0 => 1 + | 1 => 4 + | 2 => 11 + | n + 3 => 4 * A339252 (n + 2) - 4 * A339252 (n + 1) +def A339254 : ℕ → ℤ + | 0 => 1 + | 1 => 7 + | 2 => 24 + | 3 => 70 + | 4 => 193 + | n + 5 => 6 * A339254 (n + 4) - 12 * A339254 (n + 3) + 8 * A339254 (n + 2) +open PowerSeries in +noncomputable def A339029 (n : ℕ) : ℤ := + coeff n ((1 + 4 * X - 20 * X ^ 2 + 8 * X ^ 3 + 33 * X ^ 4 - 4 * X ^ 5 - 33 * X ^ 6 : ℤ⟦X⟧) * + invOfUnit ((1 - 2 * X) ^ 4) 1) +def statement_col2 : Prop := + ∀ n : ℕ, 1 < n → (T n 2 : ℤ) = A000071 (n + 2) +def statement_diag1 : Prop := + ∀ n : ℕ, 2 ≤ n → (T n (n - 1) : ℤ) = A339252 (n - 2) +def statement_diag2 : Prop := + ∀ n : ℕ, 3 ≤ n → (T n (n - 2) : ℤ) = A339254 (n - 3) +def statement_diag3 : Prop := + ∀ n : ℕ, 4 ≤ n → (T n (n - 3) : ℤ) = A339029 (n - 4) +def statement : Prop := + statement_col2 ∧ statement_diag1 ∧ statement_diag2 ∧ statement_diag3 +end Math0.Statements.A333650 +\end{lstlisting} +\texttt{IsTower n k t} is Definition~\ref{def:tower} for $t=[L_0,\dots,L_{k-1}]$, with (d) as \texttt{Even (x - i)}. +The half-brick offset is forced by the data: if a brick could also sit exactly on another, then $T(2,2)=3$, not the listed $2$. +\decl{T_eq_Tc} proves that $T$ equals a computable count \decl{Tc} (the row recursion of Section~\ref{sec:rec}), so the set of towers is finite and \texttt{ncard} is not the junk value $0$; with \decl{a_spec}, \decl{a_data} checks all $55$ listed terms (rows $1$--$10$) by \texttt{decide +kernel}, i.e.\ by evaluation in the kernel. +The right-hand sequences use their own OEIS definitions; \decl{A339029_eq} identifies A339029 with a computable sequence \decl{A339029rec} given by the recurrence read off from $(1-2x)^4$, and data lemmas check $40$, $32$, $30$, $29$ listed terms of A000071, A339252, A339254, A339029. +Values are compared in $\Z$. Conjectures (2)--(4) state no range; they are read for every $n$ at which the index on the right is a natural number. \decl{statement_check} verifies the four identities for $n\le10$ by \texttt{decide +kernel}. Luschny's summary is not formalized separately. + +\section{Proof}\label{sec:proof} + +\subsection{The row recursion}\label{sec:rec} +For finite $L\subseteq\Z$ let $\supp L=(L-1)\cup(L+1)$, the positions available to bricks resting on $L$. The statement file defines +\[ +\ways(L,0,m)=[m=0],\qquad \ways(L,h+1,m)=\sum_{j=1}^{m-h}\ \sum_{L'\subseteq\supp L,\ |L'|=j}\ways(L',h,m-j) +\] +($m-h$ truncated at $0$), and proves that $\ways(L,h,m)$ counts the sequences $(L_1,\dots,L_h)$ of nonempty sets with $L_1\subseteq\supp L$, $L_{i+1}\subseteq\supp L_i$ and $\sum|L_i|=m$ (the bound $j\le m-h$ holds because the other $h$ sets need $h$ elements). In particular $\ways(L,h,m)=0$ if $m= 1 and a(m) < a(n) for all 1 <= m < n) if and only if n = 2^k for some k >= 0. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A334592](https://oeis.org/A334592) as [`Math0.Statements.A334592.statement`](../../lean/Math0/Statements/OEIS/A334592.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A334592.lean`](../../lean/Math0/Frontier/OEIS/A334592.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C A334592 Conjecture: Records occur at powers of two. (entry by _Peter Kagey_, May 07 2020) + +Referees: The key fact is published. H. Harborth, "Solution of Steinhaus's problem with plus and minus signs", J. Combin. Theory Ser. A 12 (1972) 253-259, is credited with observing that the minimum weight of a nonzero binary Steinhaus triangle of size n is n. J. M. Brunat and M. Maureso prove it in "Small and large weights in Steinhaus triangles" (arXiv:1707.06698, 2017), Theorem 4.4: for n >= 4, w1 = n and W1 = {1^n, 10^(n-1), 0^(n-1)1}. Their extended abstract is "Extreme weights in Steinhaus triangles", Electron. Notes Discrete Math. 54 (2016) 349-354. The A334592 record conjecture is an immediate corollary: a(n) <= T(L) - L = T(L-1) = a(2^(L-1)). The OEIS entries A334592 and A334593 (local mirror, still at #19 / #22 from May 2020) have no %E note marking the conjecture resolved. The MathOverflow thread q/359138 linked from the entry could not be fetched. Other sources seen: arXiv:1702.03236 (Chappelon, periodic balanced binary triangles) and arXiv:2508.05159 (balanced Steinhaus triangles, which mentions Chang 1983 on the smallest weights). + +## Citation + +```bibtex +@misc{math0:oeis-a334592, + author = {{math0}}, + title = {{Records of the XOR-triangle zero count A334592 are exactly the powers of two}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a334592}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a334595/README.md b/results/oeis-a334595/README.md new file mode 100644 index 0000000..653e59c --- /dev/null +++ b/results/oeis-a334595/README.md @@ -0,0 +1,52 @@ +# A334595: a(n) = 1 iff n is a power of two, and the records occur exactly at 1 and 2^k + 1 + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A334595 +**Date:** 2026-10-24 + +## Result + +Let a(n) be the number obtained as follows. Write n in binary, most significant bit first. Build the XOR-triangle whose first row is that bit string; each later row is the pairwise XOR of adjacent entries of the row above. Read the right side of the triangle from the top-right corner downward, and interpret it as a binary numeral with the first entry as the most significant bit. Then: +(1) For n >= 1, a(n) = 1 if and only if n is a power of two. +(2) The record positions are exactly {1} together with {2^k + 1 : k >= 1}. Here n >= 1 is a record position when a(n) > a(m) for every 1 <= m < n. + +## Assessment + +Reverse the row, so that the right diagonal becomes the left diagonal. The digits of a(n) are then the GF(2) binomial transform of the bits of n. That transform is a classical involution, and A334727 already records it for this family. So a is a bijection on L-bit strings with a(n) < 2^L. Both conjectures then come down to working out three explicit preimages, of 1, of 2^L-1 and of 2^L-2, which takes about a page of elementary argument. No new idea was needed. The length of the Lean formalization does not make the mathematics substantial. + +*Follows from:* The classical fact that the binomial transform over GF(2) (the Pascal matrix mod 2) is an involution. This is the self-inverse XOR binomial transform of A099884, and also the self-inverse permutation stated in the sibling entry A334727, which gives the left-diagonal version of A334595. Reading the right diagonal of a row is the same as reading the left diagonal of the reversed row. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A334595](https://oeis.org/A334595) as [`Math0.Statements.A334595.statement`](../../lean/Math0/Statements/OEIS/A334595.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A334595.lean`](../../lean/Math0/Frontier/OEIS/A334595.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: Records occur at 1 and at 2^n + 1. / Conjecture: a(n) = 1 if and only if n is a power of two. (_Peter Kagey_, May 07 2020) + +Referees: I found no earlier proof or counterexample for either A334595 conjecture. +- OEIS A334595 (Peter Kagey, May 2020): unchanged since revision #18 (May 09 2020), with both statements still labeled "Conjecture". +- MathOverflow 359138, "Number triangle" (user DSM, with answers by YCor and Ilya Bogdanov): treats the boundary operator φ_k with φ_k^3 = 1 and counts rotationally symmetric triangles (A334556/A334596). It does not address records or a(n) = 1. +- OEIS A334727 (Rémy Sigrist, 2020): states that the left-diagonal map is a self-inverse permutation. +- Paul D. Hanna's XOR binomial transform entries (OEIS A099884, A099900, A099902): note that the transform is self-inverse. +These are the known ingredients that make the result elementary. Web searches of SeqFan, arXiv, MathOverflow and Math StackExchange found no resolution. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a334595, + author = {{math0}}, + title = {{A334595: a(n) = 1 iff n is a power of two, and the records occur exactly at 1 and 2^k + 1}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a334595}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a334595/paper.pdf b/results/oeis-a334595/paper.pdf new file mode 100644 index 0000000..e01bbff Binary files /dev/null and b/results/oeis-a334595/paper.pdf differ diff --git a/results/oeis-a334595/paper.tex b/results/oeis-a334595/paper.tex new file mode 100644 index 0000000..1613b51 --- /dev/null +++ b/results/oeis-a334595/paper.tex @@ -0,0 +1,353 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,apply}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {→}{{$\to$}}1 + {←}{{$\leftarrow$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {≠}{{$\ne$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1 {▸}{{$\triangleright$}}1 {∈}{{$\in$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{▸}{\ensuremath{\triangleright}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} +\newtheorem{example}[theorem]{Example} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\rev}{\operatorname{rev}} +\newcommand{\hd}{\operatorname{hd}} +\newcommand{\lst}{\operatorname{last}} +\newcommand{\tl}{\operatorname{tail}} +\newcommand{\len}[1]{\lvert #1\rvert} + +\title[The value $1$ and the records of OEIS A334595]{Right diagonals of binary XOR-triangles: OEIS A334595 takes the value $1$ exactly at the powers of two, and its records occur exactly at $1$ and at $2^k+1$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the number whose binary digits, most significant first, are the entries on the right side of the XOR-triangle whose top row is the binary expansion of $n$, read downwards from the upper right corner (OEIS A334595). +We prove the two conjectures that Peter Kagey recorded in this entry in 2020: for $n\ge1$, $a(n)=1$ if and only if $n$ is a power of two, and the record positions of $a$ are exactly $1$ and the numbers $2^k+1$ with $k\ge1$, where $a(2^k+1)=2^{k+1}-2$. +The proof rests on the classical fact that the binomial transform over $\mathrm{GF}(2)$ is an involution; we found no earlier proof of either conjecture and classify the result as new, although the argument is elementary. +The theorem is verified in Lean~4 with Mathlib against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before any proof attempt, whose definitions are checked by the kernel against the $70$ terms listed in the entry. +\end{abstract} +\maketitle + +\section{Introduction} + +An \emph{XOR-triangle} is an inverted $0$--$1$ triangle obtained by choosing a top row and letting every entry of each later row be the XOR of the two entries above it (the rule that generates Pascal's triangle modulo~$2$). +The OEIS sequence A334595 \cite{A334595}, contributed by Peter Kagey on May~7, 2020, takes as top row the binary expansion of $n$ and reads the right side of the triangle, from the upper right corner downwards, as a binary number $a(n)$. For $n=19=10011_2$ the rows are $10011$, $1010$, $111$, $00$, $0$, the right side is $10100$, and $a(19)=20$. The sequence begins $1,1,2,1,6,3,4,1,14,4,11,2,13,7,8,1,30,\dots$ (offset $1$). +The entry states two conjectures, without separate attribution and hence due to its author: the records of $a$ occur at $1$ and at $2^n+1$, and $a(n)=1$ if and only if $n$ is a power of two. +We prove both (Theorem~\ref{thm:main}). + +Since XOR is commutative, the right side of the triangle of a row is the left side of the triangle of the reversed row. So the binary digits of $a(n)$, most significant first, are the letters of $D(c)$, where $c$ lists the binary digits of $n$, least significant first, and $D$ sends a word to the left side of its XOR-triangle. This $D$ is the binomial transform over $\mathrm{GF}(2)$, and it is an involution (Proposition~\ref{prop:inv}). Hence $a$ is injective on numbers with a fixed number $L$ of binary digits, and three explicit computations of $D$, together with the bound $a(n)<2^L$, settle both conjectures. + +\subsection*{Status and prior work} +In the copy of the OEIS data that we used, A334595 is at revision \#18 (May~9, 2020), and both statements are still labeled ``Conjecture''; it is still the current revision in October 2026. +The entry links a MathOverflow question of user DSM \cite{MO}, which is also linked from A334556 and A334596 \cite{A334556,A334596} (Kagey, 2020), the entries that list and count the numbers generating rotationally symmetric XOR-triangles. +According to the math0 referees, the answers to that question (by YCor and by Ilya Bogdanov) study a linear operator $\varphi_k$ over $\mathrm{GF}(2)$ taking the top row of a triangle to one of its sides, with $\varphi_k^3=1$, in order to count rotationally symmetric triangles; they do not address the records of A334595 or the set where $a(n)=1$. +The ingredient that makes the result elementary is classical: Paul D.~Hanna's entry A099884 \cite{A099884} (2004) defines the ``XOR binomial transform'' of a sequence as the diagonal of its XOR difference triangle and states that it is self-inverse, and in the sibling entry A334727 \cite{A334727} Rémy Sigrist (May~9, 2020) notes that the analogous sequence for the \emph{left} diagonal is a self-inverse permutation of the nonnegative integers, which is the same involution, applied to the digits read from the most significant end. +The math0 referees found no proof or counterexample for either conjecture in the OEIS, on MathOverflow, Mathematics Stack Exchange, arXiv, or the SeqFan list. To our knowledge the result is therefore new, but it is an easy consequence of known facts. + +\section{Statement}\label{sec:statement} + +For $n\ge1$ let $L=L(n)$ be the number of binary digits of $n$ and $T_0=b_0b_1\cdots b_{L-1}$ its binary expansion, most significant bit first. For $1\le r x ^^^ y) row row.tail +def triangle (row : List ℕ) : List (List ℕ) := + (List.range row.length).map (fun r => xorRow^[r] row) +def rightDiag (row : List ℕ) : List ℕ := (triangle row).map (fun r => r.getLastD 0) +def a (n : ℕ) : ℕ := Nat.ofDigits 2 (rightDiag (binExp n)).reverse +def IsRecord (n : ℕ) : Prop := + 1 ≤ n ∧ ∀ m : ℕ, 1 ≤ m → m < n → a m < a n +def statement_records : Prop := + ∀ n : ℕ, IsRecord n ↔ (n = 1 ∨ ∃ k : ℕ, 1 ≤ k ∧ n = 2 ^ k + 1) +def statement_powTwo : Prop := + ∀ n : ℕ, 1 ≤ n → (a n = 1 ↔ ∃ k : ℕ, n = 2 ^ k) +def statement : Prop := + statement_records ∧ statement_powTwo +end Math0.Statements.A334595 +\end{lstlisting} +Here \texttt{Nat.digits 2 n} lists the binary digits of $n$, least significant first, so \decl{binExp} is the expansion $T_0$; \texttt{Nat.ofDigits 2 l} is $\sum_i l_i2^i$; and \texttt{\^{}\^{}\^{}} is bitwise XOR on $\N$, which is XOR on $\{0,1\}$. Thus \decl{triangle} lists the rows $T_0,\dots,T_{L-1}$ (all nonempty, so the default $0$ of \decl{getLastD} is never used), \decl{rightDiag} is $d_0\cdots d_{L-1}$, and \decl{a} reverses it so that $d_0$ is the most significant bit, exactly as the PARI program of the entry (by Michel Marcus) does. The value \texttt{a 0 = 0} is not a term and is excluded by the hypotheses $1\le n$, $1\le m$; \decl{IsRecord} is the strict record notion over the offset-$1$ range. +The statement file also proves, by \texttt{decide +kernel}, the data checks \decl{triangle_19} and \decl{a_19} (the rows of the triangle of $19$, its right diagonal \texttt{[1, 0, 1, 0, 0]} and \texttt{a 19 = 20}, as in the worked example of the entry) and \decl{a_data}, which states that \texttt{(List.range 70).map (fun i => a (i + 1))} equals the list of the $70$ terms given in the entry. With \texttt{decide +kernel} the kernel itself evaluates these equalities of lists of natural numbers, without trusting compiled code. The checks are not used in the proof; they guard against a mis-encoded definition. + +\section{Proof}\label{sec:proof} + +The proof follows \path{lean/Math0/Frontier/OEIS/A334595.lean}; we give the Lean name of each step. + +\subsection*{Notation} +A \emph{word} is a finite list $w=w_0w_1\cdots w_{\ell-1}$ of natural numbers, of length $\len w=\ell$; $\varepsilon$ is the empty word, juxtaposition is concatenation, and $x^m$ consists of $m$ copies of $x$. We write $\hd(w)=w_0$ and $\lst(w)=w_{\ell-1}$ for $\ell\ge1$, $\tl(w)=w_1\cdots w_{\ell-1}$ (with $\tl(\varepsilon)=\varepsilon$), and $\rev(w)=w_{\ell-1}\cdots w_0$. A \emph{bit word} has all letters in $\{0,1\}$. +Let $\oplus$ be bitwise XOR on $\N$. We use only that $\oplus$ is commutative and associative, that $x\oplus x=0$ and $0\oplus x=x$, and that $x\oplus y\in\{0,1\}$ for $x,y\in\{0,1\}$ (\decl{Nat.xor_lt_two_pow}). +Let $\nu(w)=\sum_{i<\len w}w_i2^i$ (\texttt{Nat.ofDigits 2}), let $c(n)$ be the binary digits of $n$, least significant first (\texttt{Nat.digits 2 n}), and $L(n)=\len{c(n)}$. Then $c(n)$ is a bit word, $\nu(c(n))=n$ (\decl{Nat.ofDigits_digits}), and $c(n)$ is empty for $n=0$ and ends with $1$ for $n\ge1$. We use the following facts from Mathlib: +(F1) if $w$ is a bit word whose last letter (if any) is nonzero, then $c(\nu(w))=w$ (\decl{Nat.digits_ofDigits}); +(F2) if $w$ is a bit word, then $\nu(w)<2^{\len w}$ (\decl{Nat.ofDigits_lt_base_pow_length}); +(F3) if $v,w$ are bit words with $\len v=\len w$ and $\nu(v)=\nu(w)$, then $v=w$ (\decl{Nat.ofDigits_inj_of_len_eq}); +(F4) $i2^{j+1}+1$, take $m=2^{j+1}+1$, so that $1\le ma(m)=2^{j+2}-2$, and Lemma~\ref{lem:basic}(ii) gives $a(n)<2^{L(n)}=2^{j+2}$. Hence $a(n)=2^{j+2}-1=2^{L(n)}-1$, which contradicts Corollary~\ref{cor:values}(iv). +\end{itemize} + +\emph{These positions are records.} The position $n=1$ is a record because there is no $m$ with $1\le m<1$. Let $n=2^k+1$ with $k\ge1$ and write $k=j+1$. Then $a(n)=2^{j+2}-2=2\cdot2^{j+1}-2\ge2^{j+1}\ge2$ by Corollary~\ref{cor:values}(ii), since $2^{j+1}\ge2$. Let $1\le m (xorRow\^{}[r] c).headD 0)}, whose default value $0$ is never used. The proof file uses no \texttt{decide}, \texttt{native\_decide} or \texttt{set\_option}. + +\subsection*{Audit} +The file ends with the command \texttt{\#math0\_settles}, applied to \decl{result} and \decl{statement}. This command, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which rejects \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} introduced by \texttt{native\_decide}, and any custom axiom; and (3) the type of \decl{result} is syntactically the constant \decl{statement} or its negation, up to metadata, with no unfolding. Running \texttt{lake env lean Math0/Frontier/OEIS/A334595.lean} in the directory \path{lean} prints +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A334595.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A334595.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A334595.result' proves 'Math0.Statements.A334595.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The single file is checked by the command above in about two minutes. + +{\small +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{MO} +MathOverflow user DSM, \emph{Number triangle}, MathOverflow question 359138 (May~2, 2020), \url{https://mathoverflow.net/q/359138}. + +\bibitem{A099884} +The OEIS Foundation Inc., \url{https://oeis.org/A099884}, entry by P.~D. Hanna (October~28, 2004). + +\bibitem{A334556} +The OEIS Foundation Inc., \url{https://oeis.org/A334556}, entry by P.~Kagey (May~6, 2020). + +\bibitem{A334595} +The OEIS Foundation Inc., \url{https://oeis.org/A334595}, entry by P.~Kagey (May~7, 2020), PARI program by M.~Marcus; revision \#18, May~9, 2020. + +\bibitem{A334596} +The OEIS Foundation Inc., \url{https://oeis.org/A334596}, entry by P.~Kagey (May~7, 2020). + +\bibitem{A334727} +The OEIS Foundation Inc., \url{https://oeis.org/A334727}, entry by R.~Sigrist (May~9, 2020). + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a334603/README.md b/results/oeis-a334603/README.md new file mode 100644 index 0000000..94f18ff --- /dev/null +++ b/results/oeis-a334603/README.md @@ -0,0 +1,51 @@ +# The period of 1/11^n is 2 * 11^(n-1) + +**Classification:** First formal proof of a known result +**Area:** Number theory +**Source problem:** OEIS A334603 +**Date:** 2026-10-18 + +## Result + +For every n >= 1, the period of the decimal expansion of 1/11^n is 2 * 11^(n-1). Equivalently, the multiplicative order of 10 modulo 11^n is 2 * 11^(n-1). This is the FORMULA conjecture of OEIS A334603. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A334603](https://oeis.org/A334603) as [`Math0.Statements.A334603.statement`](../../lean/Math0/Statements/OEIS/A334603.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A334603.lean`](../../lean/Math0/Frontier/OEIS/A334603.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Comment: "Conjecture proposed by the authors in References page 205: if p is a prime with gcd(p,30) = 1 and if the period of 1/p is m then the period of 1/p^n is m*p^(n-1)." Formula: "a(n) = 2 * 11^(n-1) [conjectured, see comments]." (_Bernard Schott_, May 07 2020) + +Referees: The result is classical; no formalization of this specific statement was found. + +Classical theory: Gauss, Disquisitiones Arithmeticae (1801), on orders modulo p^n and on periods of decimal fractions with prime-power denominators (Arts. 85-89, 312-318). Standard elementary number theory texts (Ireland-Rosen; Niven-Zuckerman-Montgomery) state the lifting lemma: if p is odd and a^{ord_p a} = 1 + p*c with p ∤ c, then ord_{p^n}(a) = p^{n-1} * ord_p(a). Mathlib's ZMod.orderOf_one_add_mul_prime is that lemma for 1 + p*a. + +Explicit decimal-period statements: +- K. A. Ross, "Repeating Decimals: A Period Piece", Mathematics Magazine 83 (2010), 33-45. If n is the largest exponent with period(1/p^n) = period(1/p), then period(1/p^a) = period(1/p) * p^(a-n) for a > n. For p = 11, period(1/121) = 22 ≠ 2, so n = 1. +- S. Yao and A. Toyohara, "The length of the repeating decimal", arXiv:2507.01295 (2025), Theorem 2.1: l_{p^n} = p^{n-(m_p+1)} * l_p, where m_p = v_p((10^{l_p} - 1)/p). For p = 11 this gives m = v_11(9) = 0, so l_{11^n} = 2*11^(n-1). +- Wikipedia, "Repeating decimal": the period of 1/p^2 is usually p*T_p, with the only known exceptions 3, 487 and 56598313. +- OEIS A045616 (primes with 10^(p-1) ≡ 1 mod p^2) lists exactly these exceptions, and 11 is not among them. +- John D. Cook, "Reciprocals of prime powers" (blog, 2021-09-28) checks 1/121 explicitly: period 22. + +In the OEIS itself, A055272 has a Sep 2026 comment by E. Rodríguez proving the analogous 7^n case with the same lifting argument. + +Side note: the general conjecture of De Koninck and Mercier quoted in the A334603 comments (not the formalized statement) is false at p = 487. + +Sources: https://arxiv.org/abs/2507.01295 ; https://en.wikipedia.org/wiki/Repeating_decimal ; https://www.johndcook.com/blog/2021/09/28/reciprocals-of-prime-powers/ ; https://oeis.org/A045616 (read from the local mirror) + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a334603, + author = {{math0}}, + title = {{The period of 1/11^n is 2 * 11^(n-1)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a334603}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a334603/paper.pdf b/results/oeis-a334603/paper.pdf new file mode 100644 index 0000000..bb828ad Binary files /dev/null and b/results/oeis-a334603/paper.pdf differ diff --git a/results/oeis-a334603/paper.tex b/results/oeis-a334603/paper.tex new file mode 100644 index 0000000..d88d2a0 --- /dev/null +++ b/results/oeis-a334603/paper.tex @@ -0,0 +1,396 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,apply,push_cast,absurd}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {→}{{$\to$}}1 + {←}{{$\leftarrow$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {≠}{{$\ne$}}1 {≡}{{$\equiv$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1 {∣}{{$\mid$}}1 {∈}{{$\in$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\ord}{\operatorname{ord}} +\newcommand{\per}{\operatorname{per}} + +\title[The decimal period of $1/11^n$]{The decimal expansion of $1/11^n$ has period $2\cdot 11^{n-1}$: a formal proof of the conjectured formula in OEIS A334603} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +We prove that for every $n\ge1$ the multiplicative order of $10$ modulo $11^n$, which is the period of the decimal expansion of $1/11^n$, equals $2\cdot 11^{n-1}$. +This is the formula $a(n)=2\cdot11^{n-1}$ that the OEIS entry A334603 (B.~Schott, 2020) records as conjectured. +The result is a special case of the classical lifting theorem for multiplicative orders modulo powers of an odd prime, applied to $10^2=1+11\cdot 9$ with $11\nmid 9$, so it is not new; our contribution is a machine-checked proof, to our knowledge the first formal proof of this statement. +The proof is verified in Lean~4 with Mathlib against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before any proof attempt, and whose definitions are checked by the kernel against the terms listed in the OEIS. +\end{abstract} +\maketitle + +\section{Introduction} + +For an integer $m>1$ with $\gcd(m,10)=1$, the decimal expansion of $1/m$ is purely periodic, and its period (the length of its shortest repeating block) is the multiplicative order $\ord_m(10)$ of $10$ modulo $m$ (Remark~\ref{rem:period} below). +The OEIS sequence A334603 \cite{A334603}, contributed by Bernard Schott on May~7, 2020, with more terms by Giovanni Resta, lists the periods $a(n)$ of $1/11^n$ for $n\ge1$: +\[ + 2,\ 22,\ 242,\ 2662,\ 29282,\ 322102,\ \dots +\] +The entry records the formula $a(n)=2\cdot11^{n-1}$ as conjectured, with reference to a more general conjecture that it attributes to De Koninck and Mercier \cite[Probl\`eme~346]{DKM}: if $p$ is a prime with $\gcd(p,30)=1$ and the period of $1/p$ is $m$, then the period of $1/p^n$ is $mp^{n-1}$. +We prove the formula for $p=11$ (Theorem~\ref{thm:main}) and verify the proof in Lean~4. + +\subsection*{Prior work and status} +The formula is an instance of a classical fact about multiplicative orders modulo powers of an odd prime $p$: if $\ell=\ord_p(b)$ and $b^\ell=1+pc$ with $p\nmid c$, then $\ord_{p^n}(b)=\ell\,p^{n-1}$ for every $n\ge1$. +The theory of residues modulo prime powers goes back to Gauss \cite[Art.~82 ff.]{Gauss}, whose Section~VI also treats the conversion of fractions into decimals \cite[Art.~312 ff.]{Gauss}. +The key step, that an element $1+pc$ with $p\nmid c$ has order exactly $p^{n-1}$ modulo $p^n$, is the standard lemma used to prove that $(\Z/p^n\Z)^\times$ is cyclic (see, e.g., \cite[Ch.~4]{IR} and \cite[\S2.8]{NZM}). +For $p=11$ and $b=10$ one has $\ell=2$ and $10^2=1+11\cdot9$ with $11\nmid 9$, which gives $\ord_{11^n}(10)=2\cdot11^{n-1}$. +In the language of decimal expansions, Yao and Toyohara \cite[Theorem~2.1]{YT} state the general result as $l_{p^n}=p^{\,n-(m_p+1)}\,l_p$ for $n>m_p+1$ (and $l_{p^n}=l_p$ for $n\le m_p+1$), where $l_p$ is the period of $1/p$ and $m_p$ is the exponent of $p$ in the integer $c_p=(10^{l_p}-1)/p$ formed by the repeating block of $1/p$; for $p=11$ one has $c_{11}=9$, $m_{11}=0$ and $l_{11}=2$. +Ross \cite{Ross} discusses repeating decimals with prime-power denominators, and Cook \cite{Cook} checks the period $22$ of $1/121$ explicitly. +In the OEIS, a comment of September~5, 2026 by Eiver Rodr\'iguez in A055272 \cite{A055272} proves the analogous statement for $1/7^n$ by the analogous lifting argument. + +The label ``conjectured'' in A334603 therefore does not mark an open problem, and we claim no mathematical novelty. +The math0 referees found no previous formalization of this statement; A334603 does not occur in the formal-conjectures repository \cite{FC}. +The essential ingredient, the order of $1+pa$ modulo $p^{k+1}$, is already in Mathlib \cite{Mathlib} as \decl{ZMod.orderOf_one_add_mul_prime}. +We classify the result as a known result whose formal proof given here is, to our knowledge, the first. + +\begin{remark}[the general conjecture; its refutation is not formalized]\label{rem:general} +The general conjecture quoted in A334603 is false. +The prime $p=487$ satisfies $\gcd(487,30)=1$ and $10^{486}\equiv1\pmod{487^2}$; it is one of the three known primes with $10^{p-1}\equiv1\pmod{p^2}$, namely $3$, $487$ and $56598313$ \cite{A045616}. +Since $\ord_{487}(10)=486$, both $1/487$ and $1/487^2$ have period $486$, whereas the conjecture predicts $486\cdot487$ for $1/487^2$. +This is exactly the case $p\mid c$ excluded in the lifting theorem above. +We checked these values numerically; they are not part of the Lean development. +The math0 statement file encodes the general conjecture as a separate proposition \decl{statement_general}, which this paper does not address. +\end{remark} + +\section{Statement}\label{sec:statement} + +\begin{definition}\label{def:per} +For $m\ge1$ with $\gcd(m,10)=1$ let $\per(m)$ be the least $k\ge1$ with $10^k\equiv1\pmod m$, that is, $\per(m)=\ord_m(10)$. It exists by Euler's theorem, since $10^{\varphi(m)}\equiv1\pmod m$. +\end{definition} + +\begin{remark}\label{rem:period} +Let $m>1$ with $\gcd(m,10)=1$. If $10^k\equiv1\pmod m$ with $k\ge1$, then $c=(10^k-1)/m$ is an integer and $1/m=c/(10^k-1)=\sum_{j\ge1}c\cdot10^{-jk}$, so the decimal expansion of $1/m$ is purely periodic with period $k$ (the block is the $k$-digit string of $c$ with leading zeros). +Conversely, if the digits of $1/m$ are periodic with period $k$ from position $s+1$ on, then $10^s/m$ and $10^{s+k}/m$ have the same fractional part, so $m\mid 10^s(10^k-1)$ and hence $m\mid 10^k-1$. +So the least period of the expansion of $1/m$ is $\per(m)$. +For example, $1/121=0.\overline{0082644628099173553719}$ has period $22$, as in the example of the OEIS entry. +\end{remark} + +\begin{theorem}\label{thm:main} +For every $n\ge1$, +\[ + \ord_{11^n}(10)=2\cdot 11^{\,n-1}. +\] +Equivalently, the decimal expansion of $1/11^n$ has period $2\cdot11^{n-1}$. +\end{theorem} + +\subsection*{The OEIS conjecture} +The entry A334603 \cite{A334603} (revision \#31, November~19, 2023, in the copy of the OEIS data we used) is named, verbatim, +\begin{quote}\small\texttt{Period of the fraction 1/11\^{}n for n >= 1.}\end{quote} +has offset $1$, and is authored by \emph{Bernard Schott, May 07 2020}. Its COMMENTS section reads, verbatim, +\begin{quote}\small\texttt{Conjecture proposed by the authors in References page 205: if p is a prime with gcd(p,30) = 1 and if the period of 1/p is m then the period of 1/p\^{}n is m*p\^{}(n-1).}\end{quote} +where the reference is \cite{DKM}, and its FORMULA section contains, verbatim, +\begin{quote}\small\texttt{a(n) = 2 * 11\^{}(n-1) [conjectured, see comments].}\end{quote} +Theorem~\ref{thm:main} is this FORMULA conjecture. The entry's Mathematica program (G.~Resta) and PARI program (M.~Marcus) compute $\ord_{11^n}(10)$, as \texttt{MultiplicativeOrder[10, 11\^{}n]} and \texttt{znorder(Mod(10, 11\^{}n))}. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A334603.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{c38de193\ldots 7c4b}) before any proof attempt. The definitions and the statement read as follows (verbatim; the import, the module docstring, all other doc comments, blank lines and all other declarations are omitted): +\begin{lstlisting} +namespace Math0.Statements.A334603 +theorem exists_pow_modEq_one {m : ℕ} (h : Nat.Coprime 10 m) : + ∃ k, 0 < k ∧ 10 ^ k ≡ 1 [MOD m] := by + have hm : m ≠ 0 := by + rintro rfl + exact absurd (Nat.coprime_zero_right 10 |>.1 h) (by norm_num) + exact ⟨Nat.totient m, Nat.totient_pos.2 (Nat.pos_of_ne_zero hm), Nat.ModEq.pow_totient h⟩ +def period (m : ℕ) : ℕ := + if h : Nat.Coprime 10 m then Nat.find (exists_pow_modEq_one h) else 0 +def a (n : ℕ) : ℕ := period (11 ^ n) +def statement : Prop := ∀ n : ℕ, 1 ≤ n → a n = 2 * 11 ^ (n - 1) +end Math0.Statements.A334603 +\end{lstlisting} +For $m$ coprime to $10$, \texttt{period m} is \decl{Nat.find} applied to the predicate $0 a (i + 1))} is the list of the $20$ listed terms $2,22,\dots,122318180896829092582$ of A334603. A naive search for the least $k$ is infeasible for $a(20)\approx1.2\cdot10^{20}$, so the proof uses an order certificate: by Lemma~\ref{lem:crit} below, $\per(11^{i+1})=L$ with $L=2\cdot11^i$ follows from $10^L\equiv1$, $10^{L/2}\not\equiv1$ and, for $i\ge1$, $10^{L/11}\not\equiv1\pmod{11^{i+1}}$ (\decl{period_eq_of_cert} and \decl{prime_dvd_two_mul_pow}). These congruences, for $0\le i<20$, form the lemma \decl{cert_data}, which is proved by \texttt{decide +kernel}: the kernel evaluates a binary modular exponentiation \decl{powMod}, defined by structural recursion on a fuel argument and proved equal to $b^e \bmod m$ (\decl{powMod_eq}), using its built-in arbitrary-precision arithmetic on natural-number literals. The final list comparison is again \texttt{decide +kernel}. +The lemma \decl{period_data} checks \texttt{period m} against the $35$ terms of A051626 \cite{A051626} (period of the decimal expansion of $1/m$) with $3\le m\le 90$ and $\gcd(m,10)=1$, by a kernel-evaluated Boolean test \decl{checkPeriod} that checks $10^L\equiv1$ and $10^k\not\equiv1$ for all $01$ has a prime factor $q$; then $q\mid L$ and $d\mid L/q$, so $x^{L/q}=1$, a contradiction. Hence $d=L$. +\end{proof} + +The prime divisors of $2\cdot11^k$ are among $2$ and $11$ (\decl{prime_dvd_two_mul_pow}, statement file): a prime dividing $2\cdot 11^k$ divides $2$ or $11^k$, hence equals $2$ or $11$. + +\begin{proposition}[\decl{orderOf_ten}]\label{prop:ten} +For every $k\ge0$, the element $10$ has order $2\cdot 11^k$ in $R_k$. +\end{proposition} + +\begin{proof} +Let $L=2\cdot11^k\ge1$. We verify the hypotheses of Lemma~\ref{lem:crit} for $x=10$ in $R_k$. + +First, $10^L=(10^2)^{11^k}=1$, because $10^2$ has order $11^k$ by Lemma~\ref{lem:hundred}. + +Next let $q$ be a prime dividing $L$; then $q=2$ or $q=11$. + +\emph{Case $q=2$.} Then $L/2=11^k$ is odd, as a power of an odd number, so $10^{L/2}\ne1$ by Lemma~\ref{lem:odd}. + +\emph{Case $q=11$.} If $k=0$, then $L=2$ and $11\nmid L$, so this case does not occur. If $k=k'+1$, then $L/11=2\cdot11^{k'}$ and $10^{L/11}=(10^2)^{11^{k'}}$. By Lemma~\ref{lem:hundred} the order of $10^2$ in $R_k$ is $11^{k}=11^{k'+1}$, and $0<11^{k'}<11^{k'+1}$. A power $y^e$ with $0 norm_num at hqL + | succ k => + rw [show 2 * 11 ^ (k + 1) / 11 = 2 * 11 ^ k by rw [pow_succ]; omega, pow_mul] + apply pow_ne_one_of_lt_orderOf (by positivity) + rw [orderOf_hundred] + exact Nat.pow_lt_pow_right (by norm_num) (Nat.lt_succ_self k) +theorem result : statement := by + intro n hn + obtain ⟨k, rfl⟩ : ∃ k, n = k + 1 := ⟨n - 1, by omega⟩ + rw [a, period_eq_orderOf (Nat.Coprime.pow_right _ (by norm_num)), orderOf_ten, + Nat.add_sub_cancel] +end Math0.Frontier.A334603 +#math0_settles Math0.Frontier.A334603.result Math0.Statements.A334603.statement +\end{lstlisting} +The identity $10^2=1+11\cdot 9$ in $R_k$ is proved by \texttt{push\_cast} and \texttt{norm\_num}. The proof file uses \texttt{decide} only for small closed facts ($\neg(11\mid9)$ in $\Z$, $10=-1$ and $-1\ne1$ in $\Z/11\Z$, and the oddness of $11$), and uses no \texttt{native\_decide} and no \texttt{set\_option}. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which rejects \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} introduced by \texttt{native\_decide}, and any custom axiom; and (3) the type of \decl{result} is syntactically the constant \decl{statement} or its negation, up to metadata, with no unfolding. Running \texttt{lake env lean Math0/Frontier/OEIS/A334603.lean} in the directory \path{lean} prints +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A334603.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A334603.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A334603.result' proves 'Math0.Statements.A334603.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (which re-runs every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. +The single file can be checked with the command above (about a minute on our machine). + +{\small +\begin{thebibliography}{99} + +\bibitem{Cook} +J.~D. Cook, \emph{Reciprocals of prime powers}, blog post, September~28, 2021, \url{https://www.johndcook.com/blog/2021/09/28/reciprocals-of-prime-powers/}. + +\bibitem{DKM} +J.-M. De Koninck and A.~Mercier, \emph{1001 Probl\`emes en Th\'eorie Classique des Nombres}, Ellipses, Paris, 2004; Probl\`eme~346, pp.~50 and 204--205. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Gauss} +C.~F. Gauss, \emph{Disquisitiones Arithmeticae}, Fleischer, Leipzig, 1801. English translation by A.~A. Clarke, Yale University Press, New Haven, 1966. + +\bibitem{IR} +K.~Ireland and M.~Rosen, \emph{A Classical Introduction to Modern Number Theory}, 2nd ed., Graduate Texts in Mathematics \textbf{84}, Springer, New York, 1990. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{NZM} +I.~Niven, H.~S. Zuckerman, and H.~L. Montgomery, \emph{An Introduction to the Theory of Numbers}, 5th ed., Wiley, New York, 1991. + +\bibitem{Ross} +K.~A. Ross, \emph{Repeating decimals: a period piece}, Math. Mag.\ \textbf{83} (2010), no.~1, 33--45, \url{https://doi.org/10.4169/002557010X479974}. + +\bibitem{YT} +S.~Yao and A.~Toyohara, \emph{The length of the repeating decimal}, arXiv:2507.01295, 2025. + +\bibitem{A045616} +The OEIS Foundation Inc., \url{https://oeis.org/A045616} (primes $p$ with $10^{p-1}\equiv1\pmod{p^2}$), entry by H.~Richter. + +\bibitem{A051626} +The OEIS Foundation Inc., \url{https://oeis.org/A051626} (period of the decimal representation of $1/n$), entry by J.~Lowell. + +\bibitem{A055272} +The OEIS Foundation Inc., \url{https://oeis.org/A055272} (first differences of $7^n$), entry by B.~E. Williams; comment by E.~Rodr\'iguez (September~5, 2026). + +\bibitem{A334603} +The OEIS Foundation Inc., \url{https://oeis.org/A334603}, entry by B.~Schott (May~7, 2020), more terms by G.~Resta; revision \#31, November~19, 2023. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a335012/README.md b/results/oeis-a335012/README.md new file mode 100644 index 0000000..f7355f2 --- /dev/null +++ b/results/oeis-a335012/README.md @@ -0,0 +1,45 @@ +# Repunit residues: a(n) = n - 1 exactly for long period primes + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Number theory +**Source problem:** OEIS A335012 +**Date:** 2026-10-18 + +## Result + +For n >= 1 let a(n) be the number of distinct values R_k mod n for 1 <= k <= n, where R_k = (10^k - 1)/9 is the k-th repunit. Then a(n) = n - 1 if and only if n is a long period prime (A006883): n is prime and either n = 2 or the multiplicative order of 10 modulo n is n - 1. + +## Assessment + +The proof is an elementary argument of about a page. If n is even or a multiple of 5, every repunit is odd, or is 1 mod 5, so too few residues are hit. For gcd(n,10)=1 the residues are purely periodic with period L = min{k : n | R_k}. When 3 does not divide n, L = ord_n(10) <= phi(n), and L = n-1 forces n to be prime. When 3 divides n, R_k ≡ k (mod 3) forces 3 | L, while n-1 ≡ 2 (mod 3). The main case, gcd(n,30)=1, is essentially Israel's comment in the entry, and the cases of multiples of 2, 3 and 5 are quick standard observations, so a competent number theorist would find the whole proof quickly. + +*Follows from:* Robert Israel's comment in A335012 itself, a(n) = A084680(n) (the order of 10 mod n) when gcd(n,30)=1, together with ord_n(10) <= phi(n) <= n-1 (equality forcing n prime), and the standard congruence R_k ≡ k (mod 3). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A335012](https://oeis.org/A335012) as [`Math0.Statements.A335012.statement`](../../lean/Math0/Statements/OEIS/A335012.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A335012.lean`](../../lean/Math0/Frontier/OEIS/A335012.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: a(n) = n-1 if and only if n is a long period prime (A006883), that is, n is a prime and the decimal expansion of 1/n has period n-1. (entry by _Sen-Peng Eu_, May 19 2020) + +Referees: OEIS A335012 (Sen-Peng Eu, May 19 2020): the current revision #31 (Mar 12 2026) still lists this as a conjecture, with no %E line recording a resolution. In the same entry, Robert Israel's comment (Jun 25 2020) gives a(n) = A084680(n), the order of 10 mod n, when gcd(n,30) = 1. That implicitly settles the coprime-to-30 case but not n divisible by 2, 3 or 5. Cross-references: A006883 (long period primes, including 2) and A084680; neither mentions a proof. Background only: https://en.wikipedia.org/wiki/Repunit (pigeonhole argument that some repunit is a multiple of n; R_k ≡ k mod 3), https://en.wikipedia.org/wiki/Full_reptend_prime, https://mathworld.wolfram.com/FullReptendPrime.html. Web searches of arXiv, MathOverflow, Math StackExchange, SeqFan and the Google index found no earlier proof or counterexample. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a335012, + author = {{math0}}, + title = {{Repunit residues: a(n) = n - 1 exactly for long period primes}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a335012}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a335012/paper.pdf b/results/oeis-a335012/paper.pdf new file mode 100644 index 0000000..27d2c53 Binary files /dev/null and b/results/oeis-a335012/paper.pdf differ diff --git a/results/oeis-a335012/paper.tex b/results/oeis-a335012/paper.tex new file mode 100644 index 0000000..acf46a7 --- /dev/null +++ b/results/oeis-a335012/paper.tex @@ -0,0 +1,383 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{textcomp} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {↔}{{$\leftrightarrow$}}1 + {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\DeclareMathOperator{\ord}{ord} + +\title[Repunit residues and long period primes]{The repunits $R_1,\dots,R_n$ leave exactly $n-1$ distinct residues modulo $n$ if and only if $n$ is a long period prime} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +For $n\ge1$ let $a(n)$ be the number of distinct remainders of the repunits $R_k=(10^k-1)/9$, $1\le k\le n$, upon division by $n$; this is OEIS A335012. +We prove the conjecture recorded in that entry by Sen-Peng Eu (2020) that $a(n)=n-1$ if and only if $n$ is a long period prime, that is, $n$ is prime and the decimal expansion of $1/n$ has period $n-1$ (OEIS A006883, which includes $2$). +The proof is elementary: it uses the periodicity of repunits modulo $n$, the congruence $R_k\equiv k\pmod 3$, and Euler's theorem. +To our knowledge it is the first complete proof; the OEIS entry still lists the statement as a conjecture, and the case $\gcd(n,30)=1$ follows readily from a formula stated without proof by Robert Israel in the same entry. +The theorem is verified in Lean~4 with Mathlib against a statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the listed OEIS terms; this statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +For $k\ge0$ let $R_k=(10^k-1)/9$ be the $k$-th repunit, so $R_1=1$, $R_2=11$, $R_3=111$, and so on (OEIS A002275 \cite{A002275}). +The sequence A335012 of the OEIS \cite{A335012}, submitted by Sen-Peng Eu on May~19, 2020, has offset $1$ and is defined by +\[ + a(n)=\#\{\,R_k \bmod n \;:\; 1\le k\le n\,\}, +\] +the ``number of different remainders when the first $n$ terms of $1, 11, 111, 1111, \dots$ are divided by $n$''. +For example $a(4)=2$, since $1,11,111,1111$ leave the remainders $1,3,3,3$ modulo $4$. +The sequence begins +\[ + 1, 1, 3, 2, 1, 3, 6, 3, 9, 1, 2, 4, 6, 6, 3, 4, 16, 9, 18, 2, 6, 2, 22, \dots +\] +Since there are only $n$ residues modulo $n$, $a(n)\le n$. + +A prime $p$ is a \emph{long period prime} if the decimal expansion of $1/p$ has period $p-1$ (OEIS A006883 \cite{A006883}). +By the convention stated in A006883, $2$ is a long period prime, because $1/2=0.5000\ldots$ is eventually periodic with period $1=2-1$; the related sequence A001913 \cite{A001913} of full reptend primes, the primes with primitive root $10$, omits $2$. +For a prime $p\notin\{2,5\}$ the period of $1/p$ equals the multiplicative order $\ord_p(10)$ of $10$ modulo $p$ \cite[Ch.~IX]{HW}, so $p$ is a long period prime exactly when $10$ is a primitive root modulo $p$ (see also \cite{MW}). +Throughout, for $n\ge1$, $\ord_n(10)$ denotes the least $m\ge1$ with $10^m\equiv1\pmod n$; it exists if and only if $\gcd(n,10)=1$, and when it does not exist an equation $\ord_n(10)=n-1$ is regarded as false (this agrees with Mathlib's convention, see Section~\ref{sec:statement}). +The primes $3$ and $5$ are not long period primes, since $1/3$ and $1/5$ have period $1$. +The long period primes begin $2,7,17,19,23,29,47,59,61,97,\dots$, and the values of $a$ listed above have $a(n)=n-1$ exactly at $n=2,7,17,19,23$. +The COMMENTS section of A335012 contains the following conjecture, which we prove. + +\begin{theorem}\label{thm:main} +For every integer $n\ge1$, $a(n)=n-1$ if and only if $n$ is a long period prime, that is, $n$ is prime and either $n=2$ or $\ord_n(10)=n-1$. +\end{theorem} + +We prove Theorem~\ref{thm:main} in Section~\ref{sec:proof} and verify it in Lean~4 (Section~\ref{sec:lean}). + +\subsection*{Status and prior work} +The current revision of A335012 (revision \#31, March~12, 2026) still states the claim as a conjecture, and the entry has no extension line recording a proof or a counterexample. +The nearest earlier result is a comment by Robert Israel in the same entry, dated June~25, 2020: if $\gcd(n,30)=1$ then $a(n)$ equals A084680$(n)$ \cite{A084680}, the multiplicative order of $10$ modulo $n$. +The comment is stated without proof. +Combined with $\ord_n(10)\le\varphi(n)\le n-1$ for $n\ge2$, where equality throughout forces $n$ to be prime, it gives Theorem~\ref{thm:main} for $\gcd(n,30)=1$ (see Remark~\ref{rem:israel}, where we derive Israel's formula from the lemmas of Section~\ref{sec:proof}). +It says nothing about $n$ divisible by $2$, $3$ or $5$. +Multiples of $2$ and $5$ are easy to exclude; multiples of $3$ need the congruence $R_k\equiv k\pmod 3$. +The ingredients are standard (for instance, the pigeonhole argument showing that some repunit is divisible by any $n$ coprime to $10$, and $R_k\equiv k\pmod 3$), and the cross-referenced entries A006883 and A084680 do not mention a proof. +The math0 referees searched arXiv, MathOverflow, Mathematics Stack Exchange, the SeqFan mailing list and the general web, and found no earlier proof or counterexample. +The statement is not among the OEIS statements of the formal-conjectures repository \cite{FC} at the commit pinned by math0. +We therefore classify Theorem~\ref{thm:main} as a \emph{new result}, with the caveat that the argument is elementary and that its main case is essentially contained in Israel's comment; what is new is the treatment of the multiples of $2$, $3$ and $5$ and the complete proof of both directions. +The entry also records, in an unsigned comment, that $a(n)=n$ if and only if $n$ is a power of $3$; we do not address that statement. + +\section{Statement}\label{sec:statement} + +The COMMENTS section of A335012 \cite{A335012} contains, verbatim: +\begin{quote}\raggedright +{\small\texttt{Conjecture: a(n) = n-1 if and only if n is a long period prime (A006883), that is, n is a prime and the decimal expansion of 1/n has period n-1.}} +\end{quote} +The comment carries no separate signature, so we attribute it to the author of the entry, Sen-Peng Eu (May~19, 2020). +Theorem~\ref{thm:main} is this conjecture, read for every index $n\ge1$ of the sequence and with long period primes as defined in A006883, including $2$. + +\subsection*{Lean formalization} +The statement was formalized by math0 in the file +\path{lean/Math0/Statements/OEIS/A335012.lean}, which was reviewed for fidelity and frozen (SHA-256 \texttt{954d748d\ldots dbf31}) before any proof attempt. +Its declarations are, verbatim except that the copyright header, the \texttt{import} line, docstrings and blank lines are omitted and the proof of \decl{isLongPeriodPrimeB_iff} is replaced by \texttt{...}: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +namespace Math0.Statements.A335012 +def a (n : ℕ) : ℕ := ((Finset.Icc 1 n).image (fun k => ((10 ^ k - 1) / 9) % n)).card +theorem a_data : (List.range 81).map (fun i => a (i + 1)) = + [1, 1, 3, 2, 1, 3, 6, 3, 9, 1, 2, 4, 6, 6, 3, 4, 16, 9, 18, 2, 6, 2, 22, 5, 2, 6, 27, 7, 28, 3, + 15, 5, 6, 16, 6, 10, 3, 18, 6, 3, 5, 6, 21, 3, 9, 22, 46, 6, 42, 2, 48, 7, 13, 27, 2, 8, 18, + 28, 58, 4, 60, 15, 18, 6, 6, 6, 33, 17, 66, 6, 35, 11, 8, 3, 4, 19, 6, 6, 13, 4, 81] := by + decide +kernel +def IsLongPeriodPrime (p : ℕ) : Prop := + p.Prime ∧ (p = 2 ∨ orderOf (10 : ZMod p) = p - 1) +def isLongPeriodPrimeB (p : ℕ) : Bool := + decide p.Prime && (p == 2 || (10 ^ (p - 1) % p == 1 % p && + (List.range' 1 (p - 2)).all fun m => 10 ^ m % p != 1 % p)) +theorem isLongPeriodPrimeB_iff (p : ℕ) : isLongPeriodPrimeB p = true ↔ IsLongPeriodPrime p := by + ... +theorem isLongPeriodPrime_data : + (List.range 270).filter isLongPeriodPrimeB = + [2, 7, 17, 19, 23, 29, 47, 59, 61, 97, 109, 113, 131, 149, 167, 179, 181, 193, 223, 229, + 233, 257, 263, 269] := by + decide +kernel +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → (a n = n - 1 ↔ IsLongPeriodPrime n) +end Math0.Statements.A335012 +\end{lstlisting} + +\subsection*{How the definitions encode the OEIS entry} +\begin{itemize} +\item \emph{The sequence.} In \decl{a}, the term \texttt{(10 \^{} k - 1) / 9} is computed in $\N$ with truncated subtraction and floor division; since $10^k\ge1$ and $9\mid 10^k-1$, it equals $R_k$ exactly (this is the lemma \decl{rep_eq} of the proof file). Thus \texttt{a n} is the number of elements of the image of $k\mapsto R_k \bmod n$ on $\{1,\dots,n\}$, which is the definition of A335012 and agrees with the PARI program \texttt{\#Set(vector(n, k, (10\^{}k-1)/9) \% n)} and the Maple programs of the entry. The theorem \decl{a_data} checks, by evaluation in the Lean kernel, that \texttt{a} reproduces all $81$ listed terms $a(1),\dots,a(81)$. +\item \emph{Long period primes.} \decl{IsLongPeriodPrime} says that $p$ is prime and either $p=2$ or $10$ has order $p-1$ in $\Z/p\Z$. For primes $p\notin\{2,5\}$ this is the period condition, as recalled in the introduction. For $p=5$ we have $10=0$ in $\Z/5\Z$, and Mathlib's \decl{orderOf x} is $0$ by convention when no positive power of \texttt{x} equals $1$, so the condition reads $0=4$ and fails; this correctly excludes $5$. For $p=2$ the same convention gives \texttt{orderOf (10 : ZMod 2) = 0}, which is why the disjunct $p=2$ is needed. For $p=3$ the order is $1\ne2$, so $3$ is excluded. These are the same conventions as the Maple program and the alternative Mathematica program of A006883, which test, for primes $p$, whether $p=2$ or $\ord_p(10)=p-1$. As a check, \decl{isLongPeriodPrime_data} shows by kernel evaluation that the numbers below $270$ satisfying the Boolean test \decl{isLongPeriodPrimeB} are exactly the first $24$ listed terms of A006883, and \decl{isLongPeriodPrimeB_iff} proves that this Boolean test is equivalent to \decl{IsLongPeriodPrime}. +\item \emph{Range.} The statement quantifies over all $n\ge1$, the index range of A335012. The hypothesis $1\le n$ is necessary: \texttt{a 0 = 0 = 0 - 1} in $\N$ while $0$ is not prime, so the statement would be false at $n=0$. It adds no other hypotheses. +\end{itemize} + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A335012.lean}; with each step we give the name of the corresponding Lean declaration. +Following that file, we define the repunits recursively by +\[ + R_0=0,\qquad R_{k+1}=10R_k+1\qquad(k\ge0) +\] +(\decl{rep}). For an integer $x$ and $n\ge1$ we write $x \bmod n\in\{0,\dots,n-1\}$ for the remainder of $x$ upon division by $n$. + +\begin{lemma}[\decl{nine_rep}, \decl{rep_eq}, \decl{a_eq}, \decl{rep_add}, \decl{rep_mod_three}, \decl{rep_mod_two}, \decl{rep_mod_five}]\label{lem:basic} +For all $k,m\ge0$: +\begin{enumerate} +\item $9R_k+1=10^k$; hence $(10^k-1)/9=R_k$, and $a(n)=\#\{R_k\bmod n: 1\le k\le n\}$ for every $n$; +\item $R_{m+k}=10^kR_m+R_k$; +\item $R_k\equiv k\pmod 3$; +\item if $k\ge1$, then $R_k\equiv1\pmod 2$ and $R_k\equiv 1\pmod 5$. +\end{enumerate} +\end{lemma} + +\begin{proof} +(1) By induction on $k$: $9R_{k+1}+1=10(9R_k+1)=10^{k+1}$. +(2) By induction on $k$: the case $k=0$ is $R_m=R_m$, and $R_{m+k+1}=10R_{m+k}+1=10^{k+1}R_m+(10R_k+1)$. +(3) By induction: $R_{k+1}=10R_k+1\equiv R_k+1\pmod 3$. +(4) $R_k=10R_{k-1}+1\equiv1\pmod{10}$. +\end{proof} + +\begin{lemma}[\decl{modEq_of_dvd_rep}, \decl{dvd_rep_of_modEq}]\label{lem:div} +Let $n\ge1$ and $m\ge0$. If $n\mid R_m$, then $10^m\equiv1\pmod n$. Conversely, if $\gcd(n,3)=1$ and $10^m\equiv1\pmod n$, then $n\mid R_m$. +\end{lemma} + +\begin{proof} +By Lemma~\ref{lem:basic}(1), $10^m-1=9R_m$. If $n\mid R_m$ then $n\mid 10^m-1$. Conversely, if $10^m\equiv1\pmod n$ then $n\mid 9R_m$; since $\gcd(n,3)=1$ we have $\gcd(n,9)=1$, and hence $n\mid R_m$. +\end{proof} + +In Lean the order of $10$ is taken in the ring \texttt{ZMod n}; the lemma \decl{zmod_pow_iff} translates $10^m=1$ in $\Z/n\Z$ into $10^m\equiv1\pmod n$. + +\begin{lemma}[periodicity; \decl{exists_small}, \decl{a_le_of_dvd}]\label{lem:per} +Let $n,m\ge1$ with $n\mid R_m$. Then for every $k\ge1$ there is $j$ with $1\le j\le m$ and $R_j\equiv R_k\pmod n$. Consequently $a(n)\le m$. +\end{lemma} + +\begin{proof} +By strong induction on $k$. If $k\le m$ take $j=k$. If $k>m$, then $1\le k-m 0 + | k + 1 => 10 * rep k + 1 +private lemma forward {n : ℕ} (hn : 1 ≤ n) (ha : a n = n - 1) : IsLongPeriodPrime n := by + ... +private lemma backward {p : ℕ} (hp : IsLongPeriodPrime p) : a p = p - 1 := by + ... +theorem result : statement := fun _ hn => ⟨forward hn, backward⟩ +end Math0.Frontier.A335012 +#math0_settles Math0.Frontier.A335012.result Math0.Statements.A335012.statement +\end{lstlisting} +The proof file uses no \texttt{sorry}, \texttt{native\_decide} or \texttt{set\_option}. Its only proofs by evaluation are \texttt{decide +kernel} for $a(1)=1$ and $a(2)=1$, and one \texttt{decide} for $10^1=1$ in \texttt{ZMod 3}; both tactics produce proofs checked by the kernel and add no axioms. Euler's theorem (\decl{Nat.ModEq.pow_totient}), the fact that $\varphi(n)=n-1$ if and only if $n$ is prime, for $n\ge1$ (\decl{Nat.totient_eq_iff_prime}), and the basic properties of \decl{orderOf} come from Mathlib. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata, with no unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A335012.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A335012.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A335012.result' proves 'Math0.Statements.A335012.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. Once its imports are built, the single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A335012.lean} in the directory \path{lean}. + +{\small +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{HW} +G.~H. Hardy and E.~M. Wright, \emph{An Introduction to the Theory of Numbers}, 6th ed., revised by D.~R. Heath-Brown and J.~H. Silverman, Oxford University Press, 2008. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{MW} +E.~W. Weisstein, \emph{Full Reptend Prime}, MathWorld -- A Wolfram Web Resource, \url{https://mathworld.wolfram.com/FullReptendPrime.html}. + +\bibitem{A001913} +The OEIS Foundation Inc., \url{https://oeis.org/A001913} (full reptend primes: primes with primitive root 10), entry by N.~J.~A. Sloane. + +\bibitem{A002275} +The OEIS Foundation Inc., \url{https://oeis.org/A002275} (repunits), entry by N.~J.~A. Sloane. + +\bibitem{A006883} +The OEIS Foundation Inc., \url{https://oeis.org/A006883} (long period primes), entry by R.~Munafo. + +\bibitem{A084680} +The OEIS Foundation Inc., \url{https://oeis.org/A084680} (order of 10 modulo $n$), entry by L.~Beedassy (2003). + +\bibitem{A335012} +The OEIS Foundation Inc., \url{https://oeis.org/A335012}, entry by S.-P. Eu (May 19, 2020); comment by R.~Israel (June 25, 2020); revision \#31, Mar.~12, 2026. + +\end{thebibliography} +} +\end{document} diff --git a/results/oeis-a338885/README.md b/results/oeis-a338885/README.md new file mode 100644 index 0000000..30e7a37 --- /dev/null +++ b/results/oeis-a338885/README.md @@ -0,0 +1,50 @@ +# A338885: the smallest number in row 655 is 104, not A228286(655) = 115 + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A338885 +**Date:** 2026-10-18 + +## Result + +Kagey's conjecture in OEIS A338885 says that for every n ≥ 2, the smallest k for which a diagonal lattice rectangle (integer vertices, no side parallel to the x-axis) lies in the n X k box [0,n]×[0,k] and touches all four of its sides is A228286(n) = min{x + y*z : x, y, z ≥ 1, x*y + z = n}. This is false. For n = 655, the value k = 104 is in the row, but A228286(655) = 115 ≥ 105. So A228286(655) is not the least element of row 655. + +## Assessment + +The conjecture is refuted by one counterexample, n = 655, found by a direct search. The row minimum there is 104, from an explicit lattice rectangle, while A228286(655) = 115; the lower bound is a finite check over about 2400 pairs (x, y). The only setup is the observation that the side vectors' coordinates satisfy a+b = n, c+d = k and ab = cd, which takes a few lines, and after that the search is mechanical (I reproduced it independently: counterexamples at n = 655, 845, 909 and 1019 below 1100). The counterexample is an ordinary row of the triangle and falls within the conjecture's intended meaning, so the result is not literal-only, but no new mathematical idea was needed. + +*Follows from:* Finite computer search, using the elementary parametrization that k is in row n iff n = a+b, k = c+d and ab = cd for positive a, b, c, d (the explicit rectangle with vertices (4,0),(655,42),(651,104),(0,62); 4*651 = 42*62 = 2604) + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A338885](https://oeis.org/A338885) as [`Math0.Statements.A338885.statement`](../../lean/Math0/Statements/OEIS/A338885.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A338885.lean`](../../lean/Math0/Frontier/OEIS/A338885.lean) refutes (proves the negation of) it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: The smallest number in the n-th row is A228286(n)." (entry by _Peter Kagey_, Nov 14 2020; a second conjecture in the same entry, "The largest number in the n-th row is A033638(n)", is true; see approach) + +Referees: I found no prior resolution. +- OEIS A338885 (Kagey, Nov 14 2020): I checked both the local mirror and the latest raw oeisdata version (rev #22, Sep 11 2021). The conjecture is still listed, with no counterexample noted, and the b-file covers only rows 2..101. +- Cross-references (local mirror): A228286, A228287, A228288, A338886, A338887, A033638, A085582, A113751. None of them mentions a resolution. +- Code Golf SE question 213754 "Rectangles in rectangles", read via the Stack Exchange API: neither the answers nor the comments mention the conjecture. +- Web searches (OEIS/A338885, Kagey, SeqFan, the min x+yz / ab+cd formulations, ARML 2013) turned up nothing relevant. +- Independent computation: n = 655 is the smallest counterexample (row min 104 vs A228286 = 115). Further counterexamples are at n = 845, 909 and 1019 for n <= 1200. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a338885, + author = {{math0}}, + title = {{A338885: the smallest number in row 655 is 104, not A228286(655) = 115}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a338885}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a338885/paper.pdf b/results/oeis-a338885/paper.pdf new file mode 100644 index 0000000..612a0e0 Binary files /dev/null and b/results/oeis-a338885/paper.pdf differ diff --git a/results/oeis-a338885/paper.tex b/results/oeis-a338885/paper.tex new file mode 100644 index 0000000..33a7964 --- /dev/null +++ b/results/oeis-a338885/paper.tex @@ -0,0 +1,374 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,at,by_contra,only}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, upquote=true, + literate={∈}{{$\in$}}1 {ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 + {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {↔}{{$\leftrightarrow$}}1 + {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {≠}{{$\ne$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {×}{{$\times$}}1 {·}{{$\cdot$}}1 + {₀}{{$_0$}}1 {₁}{{$_1$}}1 {₂}{{$_2$}}1 + {…}{{$\ldots$}}1 {¬}{{$\neg$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{…}{\ensuremath{\ldots}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\R}{\mathcal{R}} +\newcommand{\Aa}{\operatorname{A228286}} + +\title[A counterexample to a conjecture in OEIS A338885]{A diagonal lattice rectangle touching all four sides of a $655\times 104$ box: a counterexample to Kagey's conjecture on the smallest entries of OEIS A338885} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +For $n\ge2$ let $\R(n)$ be the set of positive integers $k$ such that some rectangle with integer vertices and no side parallel to the $x$-axis lies in the box $[0,n]\times[0,k]$ and touches all four of its sides; these sets are the rows of the OEIS triangle A338885. In 2020 P.~Kagey conjectured that $\min\R(n)=\Aa(n)$, where $\Aa(n)=\min\{x+yz: x,y,z\ge1,\ xy+z=n\}$. We show that the conjecture is false: the rectangle with vertices $(4,0)$, $(655,42)$, $(651,104)$, $(0,62)$ shows $104\in\R(655)$, while every value $x+yz$ with $xy+z=655$ is at least $105$ (in fact $\Aa(655)=115$). To our knowledge the counterexample is new; it is the result of a short computation, and the conjecture is still listed as open in the OEIS. The refutation is checked in Lean~4 against a statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the listed data; this statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +A \emph{diagonal lattice rectangle} is a rectangle whose vertices lie in $\Z^2$ and none of whose sides is parallel to the $x$-axis. The OEIS entry A338885, contributed by Peter Kagey on November~14, 2020 \cite{A338885}, is the irregular triangle whose $n$-th row ($n\ge2$) lists, in increasing order, all $k$ such that a diagonal lattice rectangle touches all four sides of an $n\times k$ rectangle. The rows begin +\[ + \R(2)=\{2\},\quad \R(3)=\{3\},\quad \R(4)=\{4,5\},\quad \R(5)=\{4,5,7\},\quad \R(6)=\{6,9,10\},\ \dots +\] +The row lengths form A338886 \cite{A338886}, and the entry links Kagey's table of the first $100$ rows and a Code Golf Stack Exchange challenge on the same question \cite{CGSE}. The entry contains two conjectures, about the smallest and the largest number in each row. The first one compares the row minimum with the sequence A228286 \cite{A228286}, contributed by Andy Niedermaier on August~19, 2013: +\[ + \Aa(n)=\min\{x+yz : x,y,z\in\Z_{\ge1},\ xy+z=n\}\qquad(n\ge2). +\] +According to a comment in that entry, one term of A228286 was the subject of a problem in the Team Round of the 2013 ARML contest. + +In this note we show that the first conjecture is false (Theorem~\ref{thm:main}). By computation, the smallest counterexample is $n=655$, where $\min\R(655)=104$ and $\Aa(655)=115$. The reason is visible in the parametrization of Section~\ref{sec:remarks}: the elements of $\R(n)$ are the numbers $pr+qs$ with $pq+rs=n$ and $p,q,r,s\ge1$, and $\Aa(n)$ is the minimum over the quadruples with an entry equal to~$1$. The element $104$ of $\R(655)$ comes from $655=2\cdot2+21\cdot31$, that is, $(p,q,r,s)=(2,2,21,31)$. + +\subsection*{Status and prior work} +The conjecture is stated without a counterexample in the current revision~\#22 of A338885 (September~11, 2021); the math0 referees compared this revision with the local mirror of the OEIS data and found them identical. The entry's table covers only rows $2$ to $101$, all below the first counterexample. The referees also checked the cross-referenced entries A228286, A228287, A228288, A338886, A338887, A033638, A085582 and A113751, and the answers and comments of the Code Golf question \cite{CGSE}; none of them mentions a resolution. Web searches (arXiv, MathOverflow, Mathematics Stack Exchange, the SeqFan mailing list, the OEIS wiki) found no proof or counterexample. The conjecture is not among the OEIS statements of the formal-conjectures repository \cite{FC}. We therefore classify the result as \emph{new}. The caveat is that the counterexample is found by a straightforward search, so others may have observed it without recording it. + +The second conjecture of the entry, that $\max\R(n)$ equals A033638$(n)=\lfloor n^2/4\rfloor+1$ \cite{A033638}, is true and elementary (Remark~\ref{rem:max}); it is not the subject of this note. + +\section{Statement}\label{sec:statement} + +Throughout, the \emph{$n\times k$ box} is $B_{n,k}=[0,n]\times[0,k]\subset\mathbb{R}^2$. + +\begin{definition}\label{def:row} +For integers $n\ge2$ and $k\ge0$, write $k\in\R(n)$ if there are $P_0=(x_0,y_0)\in\Z^2$ and $u=(u_1,u_2)$, $v=(v_1,v_2)\in\Z^2$ such that +\begin{enumerate} +\item $u\cdot v=u_1v_1+u_2v_2=0$ and $u_2\ne0$, $v_2\ne0$; +\item the four points $P_0$, $P_0+u$, $P_0+u+v$, $P_0+v$ lie in $B_{n,k}$; +\item each of the lines $x=0$, $x=n$, $y=0$, $y=k$ contains one of these four points. +\end{enumerate} +\end{definition} + +Every rectangle with integer vertices is $\{P_0+su+tv: s,t\in[0,1]\}$ for a corner $P_0\in\Z^2$ and nonzero perpendicular side vectors $u,v\in\Z^2$, and its sides are parallel to $u$ or to~$v$. So $u_2,v_2\ne0$ says exactly that no side is parallel to the $x$-axis; it also forces $u,v\ne0$, so the rectangle is non-degenerate. Squares are allowed; for example $\R(2)=\{2\}$ comes from the square with vertices $(1,0),(2,1),(1,2),(0,1)$. A convex polygon lies in the box if and only if its vertices do, and if it lies in the box, it meets the side on the line $x=0$ if and only if the minimum of the linear function $(x,y)\mapsto x$ over the polygon is $0$. This minimum is attained at a vertex, and the same holds for the other three sides. So (2) and (3) say exactly that the rectangle lies in the $n\times k$ box and touches all four of its sides, and $\R(n)$ is the $n$-th row of A338885. + +The comment section of A338885 contains, verbatim: +\begin{quote} +\texttt{Conjecture: The smallest number in the n-th row is A228286(n).} +\end{quote} +The entry, including this comment, is by Peter Kagey, November~14, 2020. + +\begin{conjecture}[Kagey]\label{conj} +For every $n\ge2$, $\Aa(n)$ is the least element of $\R(n)$. +\end{conjecture} + +\begin{theorem}\label{thm:main} +$104\in\R(655)$ and $\Aa(655)\ge105$. In particular, Conjecture~\ref{conj} is false. +\end{theorem} + +In fact $\Aa(655)=115$ and $\min\R(655)=104$, and $655$ is the smallest counterexample (Proposition~\ref{prop:comp}); these facts are computations that are not formalized. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A338885.lean}. It was reviewed for fidelity and frozen (SHA-256 \texttt{c2422329\ldots a45e84db}) before any proof attempt. The definitions on which the statement depends, the set \texttt{A228286Set} used in the proof, and the statement itself are, verbatim except that docstrings are omitted (the computational definitions \texttt{inRowB}, \texttt{row}, \texttt{flatAux} and \decl{a}, used only for the data check, are described below): +\begin{lstlisting} +namespace Math0.Statements.A338885 + +def InBox (n k : ℕ) (p : ℤ × ℤ) : Prop := + 0 ≤ p.1 ∧ p.1 ≤ n ∧ 0 ≤ p.2 ∧ p.2 ≤ k + +def vertices (x₀ y₀ u₁ u₂ v₁ v₂ : ℤ) : List (ℤ × ℤ) := + [(x₀, y₀), (x₀ + u₁, y₀ + u₂), (x₀ + u₁ + v₁, y₀ + u₂ + v₂), (x₀ + v₁, y₀ + v₂)] + +def InRow (n k : ℕ) : Prop := + ∃ x₀ y₀ u₁ u₂ v₁ v₂ : ℤ, + -- the sides `u` and `v` are perpendicular (so the parallelogram is a rectangle) + u₁ * v₁ + u₂ * v₂ = 0 ∧ + -- no side is parallel to the x-axis + u₂ ≠ 0 ∧ v₂ ≠ 0 ∧ + -- the rectangle lies in the box + (∀ p ∈ vertices x₀ y₀ u₁ u₂ v₁ v₂, InBox n k p) ∧ + -- it touches the sides `x = 0`, `x = n`, `y = 0`, `y = k` + (∃ p ∈ vertices x₀ y₀ u₁ u₂ v₁ v₂, p.1 = 0) ∧ + (∃ p ∈ vertices x₀ y₀ u₁ u₂ v₁ v₂, p.1 = n) ∧ + (∃ p ∈ vertices x₀ y₀ u₁ u₂ v₁ v₂, p.2 = 0) ∧ + (∃ p ∈ vertices x₀ y₀ u₁ u₂ v₁ v₂, p.2 = k) + +def A228286Set (n : ℕ) : Set ℕ := + {m | ∃ x y z : ℕ, 0 < x ∧ 0 < y ∧ 0 < z ∧ x * y + z = n ∧ m = x + y * z} + +def A228286List (n : ℕ) : List ℕ := + (List.range' 1 (n - 1)).flatMap fun x => (List.range' 1 (n - 1)).filterMap fun y => + if x * y < n then some (x + y * (n - x * y)) else none + +def A228286 (n : ℕ) : ℕ := (A228286List n).min?.getD 0 + +def statement : Prop := + ∀ n : ℕ, 2 ≤ n → IsLeast {k : ℕ | InRow n k} (A228286 n) +\end{lstlisting} +Here \texttt{IsLeast S m} means $m\in S$ and $m\le s$ for all $s\in S$. The file also proves the following facts (proofs omitted, data lists abbreviated). In it, \texttt{row n} is the list of all $k\le\lfloor n^2/4\rfloor+1$ that pass a Boolean test for the existence of $0 a (i + 2)) = + [2, 3, 4, 5, 4, 5, 7, 6, 9, 10, 5, 7, 8, 11, 13, …, 14, 15, 17, 20, 22, 23] +theorem mem_A228286List (n m : ℕ) : m ∈ A228286List n ↔ m ∈ A228286Set n +theorem isLeast_A228286 {n : ℕ} (hn : 2 ≤ n) : IsLeast (A228286Set n) (A228286 n) +theorem A228286_data : (List.range 70).map (fun i => A228286 (i + 2)) = + [2, 3, 4, 4, 6, 5, 7, 6, 6, 7, 9, 7, …, 16, 16, 18, 17, 23, 21, 25, 17] +\end{lstlisting} + +\emph{Encoding.} \texttt{InRow n k} is Definition~\ref{def:row} with $P_0=(x_0,y_0)$; the list \decl{vertices} is $P_0,P_0+u,P_0+u+v,P_0+v$, and all coordinates are integers, so no truncated subtraction or division occurs in it. \texttt{A228286Set n} is the set $\{x+yz: x,y,z\ge1,\ xy+z=n\}$ from the OEIS definition. \texttt{A228286 n} is the minimum of an explicit finite list, and \decl{isLeast_A228286} proves that for $n\ge2$ it is the least element of \texttt{A228286Set n}; the truncated subtraction \texttt{n - x * y} in \decl{A228286List} is guarded by \texttt{x * y < n}. Both sequences have offset~$2$, and \decl{statement} quantifies over all $n\ge2$ with no further hypothesis. + +\emph{Data check.} The theorems \decl{a_data} and \decl{A228286_data} are proved by \texttt{decide +kernel}. They check all $71$ listed terms of A338885 (rows $2$ to $12$ and the listed beginning of row~$13$) and all $70$ listed terms of A228286, $\Aa(2),\dots,\Aa(71)$. By \decl{mem_row} and \decl{row_sorted}, the list \texttt{row n} is the increasing enumeration of the set of all $k$ with \texttt{InRow n k}, so the first check compares the geometric definition, not a formula, with the OEIS data. The referees compared both lists with the entries by script, and one referee compared the rows computed from the parametrization of \decl{inRow_iff_param} with Kagey's table of the first $100$ rows; all agree. + +\section{Proof}\label{sec:proof} + +The proof has two parts: an explicit rectangle, and a finite search that bounds $\Aa(655)$ from below. It does not compute $\Aa(655)$: an attempt to evaluate \texttt{A228286 655}, whose list ranges over $654^2\approx4.3\cdot10^5$ pairs $(x,y)$, with \texttt{decide +kernel} did not finish (the process was killed after about seven minutes, probably for lack of memory). + +\begin{lemma}[\decl{inRow_655_104}]\label{lem:witness} +$104\in\R(655)$. +\end{lemma} + +\begin{proof} +Take $P_0=(4,0)$, $u=(651,42)$ and $v=(-4,62)$. Then $u\cdot v=651\cdot(-4)+42\cdot62=-2604+2604=0$, and $u_2=42\ne0$, $v_2=62\ne0$. The four vertices are +\[ + P_0=(4,0),\quad P_0+u=(655,42),\quad P_0+u+v=(651,104),\quad P_0+v=(0,62), +\] +all in $[0,655]\times[0,104]$. The lines $x=0$, $x=655$, $y=0$, $y=104$ contain $(0,62)$, $(655,42)$, $(4,0)$, $(651,104)$, respectively. +\end{proof} + +In Lean, the proof supplies $(x_0,y_0,u_1,u_2,v_1,v_2)=(4,0,651,42,-4,62)$ and the four touching vertices, and \texttt{simp} and \texttt{norm\_num} check the conditions. + +\begin{lemma}[\decl{search}]\label{lem:search} +For all integers $1\le x,y\le104$ with $xy<655$, +\[ + x+y\,(655-xy)\ge105 . +\] +\end{lemma} + +\begin{proof} +This is a finite check of the $2391$ pairs $(x,y)$ in the range; the smallest value of $x+y(655-xy)$ among them is $115$. In Lean the statement is +\begin{lstlisting} +private theorem search : ∀ x < 105, ∀ y < 105, 0 < x → 0 < y → x * y < 655 → + 105 ≤ x + y * (655 - x * y) := by + decide +kernel +\end{lstlisting} +The bounded quantifiers, implications and inequalities have decidability instances from the core library. With \texttt{decide +kernel}, type-checking the proof requires the kernel itself to reduce the resulting Boolean to \texttt{true}, which it does by evaluating all $105\cdot105=11025$ cases $x,y\in\{0,\dots,104\}$ (those with $x=0$, $y=0$ or $xy\ge655$ hold because a hypothesis fails), using its arbitrary-precision arithmetic on natural-number literals. Unlike \texttt{native\_decide}, no compiled code is trusted. +\end{proof} + +\begin{lemma}[\decl{ge_of_mem}]\label{lem:lower} +If $x,y,z\ge1$ and $xy+z=655$, then $x+yz\ge105$. +\end{lemma} + +\begin{proof} +Suppose $m=x+yz\le104$. Then $x\le m\le104$, and since $z\ge1$, $y\le yz\le m\le104$. Moreover $xy=655-z<655$ and $z=655-xy$. Lemma~\ref{lem:search} gives $m=x+y(655-xy)\ge105$, a contradiction. +\end{proof} + +In Lean the hypothesis is \texttt{m ∈ A228286Set 655}; the arithmetic steps are done by \decl{Nat.le_mul_of_pos_right} and \texttt{omega}. + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +The first claim is Lemma~\ref{lem:witness}. For the second, $\Aa(655)\in\{x+yz:x,y,z\ge1,\ xy+z=655\}$ by \decl{isLeast_A228286} (with $n=655\ge2$), so $\Aa(655)\ge105$ by Lemma~\ref{lem:lower}. Now suppose the conjecture held. Then for $n=655$, $\Aa(655)$ is a lower bound of $\R(655)$, and $104\in\R(655)$ gives $\Aa(655)\le104$, a contradiction. The Lean proof is, verbatim: +\begin{lstlisting} +theorem result : ¬ statement := by + intro h + have hle : A228286 655 ≤ 104 := (h 655 (by norm_num)).2 inRow_655_104 + have hge : 105 ≤ A228286 655 := ge_of_mem (isLeast_A228286 (by norm_num)).1 + omega +\end{lstlisting} +Here \texttt{(h 655 \_).2} is the lower-bound half of \texttt{IsLeast}; the membership half is not used. +\end{proof} + +\subsection{Further remarks (not formalized)}\label{sec:remarks} + +The following facts explain the counterexample. Apart from the parametrization of \decl{inRow_iff_param} and the bound \decl{le_of_inRow}, they are not part of the Lean development. + +\begin{lemma}\label{lem:param} +For $n\ge2$, +\[ + \R(n)=\{c+d: a,b,c,d\ge1,\ a+b=n,\ ab=cd\}=\{pr+qs: p,q,r,s\ge1,\ pq+rs=n\}. +\] +\end{lemma} + +\begin{proof} +The first equality is \decl{inRow_iff_param}. Given a rectangle as in Definition~\ref{def:row}, put $a=|u_1|$, $b=|v_1|$, $c=|u_2|$, $d=|v_2|$. The $x$-coordinates of the vertices range over an interval of length $|u_1|+|v_1|$, and by (2) and (3) this interval is $[0,n]$; so $a+b=n$, and likewise $c+d=k$. From $u_1v_1=-u_2v_2\ne0$ we get $a,b\ge1$ and $ab=cd$. Conversely, given $a,b,c,d$, the corner $P_0=(b,0)$ with $u=(a,c)$ and $v=(-b,d)$ has vertices $(b,0)$, $(n,c)$, $(a,k)$, $(0,d)$ and $u\cdot v=cd-ab=0$. Lemma~\ref{lem:witness} is this construction with $(a,b,c,d)=(651,4,42,62)$. + +For the second equality, let $ab=cd$, put $p=\gcd(a,c)$ and write $a=pq$, $c=pr$ with $\gcd(q,r)=1$. Then $qb=rd$, so $r\mid b$; writing $b=rs$ gives $d=qs$. Hence $n=pq+rs$ and $k=pr+qs$. Conversely $(a,b,c,d)=(pq,rs,pr,qs)$ satisfies $ab=cd$. +\end{proof} + +The representation $(p,q,r,s)\mapsto(pq+rs,\,pr+qs)$ is invariant under $(p,q,r,s)\mapsto(q,p,s,r)$ and $(p,q,r,s)\mapsto(s,r,q,p)$, which together move any entry to any position. With $s=1$, $(p,q,r)=(y,x,z)$ gives $pq+rs=xy+z$ and $pr+qs=x+yz$. Hence +\[ + \{x+yz:x,y,z\ge1,\ xy+z=n\}=\{pr+qs:pq+rs=n,\ \min(p,q,r,s)=1\}\subseteq\R(n), +\] +so $\Aa(n)\in\R(n)$ and $\min\R(n)\le\Aa(n)$ for every $n\ge2$. Conjecture~\ref{conj} is therefore equivalent to the claim that, for every $n$, the minimum of $pr+qs$ subject to $pq+rs=n$ is attained at a quadruple containing a~$1$. For $n=655$, the identity $655=2\cdot2+21\cdot31$ gives $(p,q,r,s)=(2,2,21,31)$ and $pr+qs=42+62=104$. + +\begin{proposition}[computation]\label{prop:comp} +$\Aa(655)=115$, attained for example at $(x,y,z)=(6,109,1)$ and $(31,21,4)$. The row $\R(655)$ begins $104,115,121,125,135,137$. Among $2\le n\le2000$, $\min\R(n)\ne\Aa(n)$ holds exactly for the following nine values of~$n$: +\[ +\begin{array}{c|ccccccccc} + n & 655 & 845 & 909 & 1019 & 1229 & 1435 & 1439 & 1759 & 1931\\ \hline + \min\R(n) & 104 & 116 & 149 & 128 & 140 & 160 & 152 & 168 & 176\\ + \Aa(n) & 115 & 130 & 153 & 131 & 149 & 161 & 181 & 173 & 197 +\end{array} +\] +\end{proposition} + +We computed these values by exhaustive search in Python, using Lemma~\ref{lem:param} for $\min\R(n)$. They agree with the referees' independent computations, which found the same counterexamples up to $n=1500$; the value $\Aa(655)=115$ also agrees with Kagey's table of A228286 \cite{A228286}. None of this is formally verified, and Theorem~\ref{thm:main} does not depend on it. + +\begin{remark}[The largest entry]\label{rem:max} +The second conjecture of A338885 states that the largest number in row $n$ is A033638$(n)=\lfloor n^2/4\rfloor+1$. By Lemma~\ref{lem:param}, if $k=c+d\in\R(n)$ then $c+d\le cd+1=ab+1\le\lfloor n^2/4\rfloor+1$, because $(c-1)(d-1)\ge0$ and $ab\le(a+b)^2/4$; this upper bound is the theorem \decl{le_of_inRow} of the statement file. It is attained by $(a,b,c,d)=(\lfloor n/2\rfloor,\lceil n/2\rceil,1,\lfloor n/2\rfloor\lceil n/2\rceil)$. Only the upper bound is formalized; we make no claim about the novelty of this observation. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in the file \path{lean/Math0/Frontier/OEIS/A338885.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A338885.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is +\begin{center} +\texttt{Math0.Frontier.A338885.result :\ ¬ Math0.Statements.A338885.statement}. +\end{center} +The auxiliary declarations \decl{search}, \decl{ge_of_mem} and \decl{inRow_655_104} are private; they are Lemmas~\ref{lem:search}, \ref{lem:lower} and~\ref{lem:witness}. The only proof by \texttt{decide +kernel} in the proof file is the search of Lemma~\ref{lem:search}; the data checks of the statement file are not used by the proof. + +\subsection*{Audit} +The file ends with +\begin{lstlisting} +#math0_settles Math0.Frontier.A338885.result Math0.Statements.A338885.statement +\end{lstlisting} +This command is defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself. It fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, which rejects \decl{sorryAx}, the axioms \decl{Lean.ofReduceBool} and \decl{Lean.trustCompiler} introduced by \decl{native_decide}, and custom axioms; and (3) the type of \decl{result} is syntactically the statement or its negation, after removing metadata annotations and with no unfolding. Running \texttt{lake env lean Math0/Frontier/OEIS/A338885.lean} in the directory \path{lean} reports: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A338885.statement' depends on axioms [] +math0 audit: 'Math0.Frontier.A338885.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A338885.result' refutes 'Math0.Statements.A338885.statement' +\end{lstlisting} +Neither file contains \texttt{sorry}, \texttt{admit}, \texttt{native\_decide}, \texttt{axiom} or \texttt{set\_option}. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}. The repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. To reproduce, run \path{scripts/verify.sh} from the repository root; it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (which re-runs every audit command), and checks that the pinned dependencies are unmodified. To check this result alone, run \texttt{lake build Math0.Statements.OEIS.A338885} (including the data checks, about $45$ seconds) and then \texttt{lake env lean Math0/Frontier/OEIS/A338885.lean} in the directory \path{lean}. + +\begin{thebibliography}{99} + +\bibitem{CGSE} +P.~Kagey, \emph{Rectangles in rectangles}, Code Golf Stack Exchange, question 213754, October 2020, \url{https://codegolf.stackexchange.com/q/213754}. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A033638} +The OEIS Foundation Inc., \url{https://oeis.org/A033638}, Quarter-squares plus 1. + +\bibitem{A228286} +The OEIS Foundation Inc., \url{https://oeis.org/A228286}, entry by A.~Niedermaier (2013). + +\bibitem{A338885} +The OEIS Foundation Inc., \url{https://oeis.org/A338885}, entry by P.~Kagey (2020). + +\bibitem{A338886} +The OEIS Foundation Inc., \url{https://oeis.org/A338886}, entry by P.~Kagey (2020). + +\end{thebibliography} + +\end{document} diff --git a/results/oeis-a341761/README.md b/results/oeis-a341761/README.md new file mode 100644 index 0000000..ad74d0c --- /dev/null +++ b/results/oeis-a341761/README.md @@ -0,0 +1,45 @@ +# The subword complexity polynomial S(n,x) has leading coefficient n(n+1)/2 (A341761, Guo's conjecture) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A341761 +**Date:** 2026-10-24 + +## Result + +For a word w, complexity(w) is the number of distinct nonempty factors (contiguous subwords) of w. Let S(n,x) be the sum of complexity(w) over all x^n words w of length n on an alphabet of x letters. For every n >= 0 there is a polynomial P in Q[X] with P(x) = S(n,x) for every natural number x, and the coefficient of x^n in P is n(n+1)/2. + +## Assessment + +The proof groups words by which positions carry equal letters, so S(n,x) becomes a sum of c(p) times falling factorials of x, and only the pattern with all letters distinct reaches degree n. A word with n distinct letters has n(n+1)/2 distinct factors, which settles it. Put another way, once S(n,x) is known to be a polynomial of degree at most n (as Guo already noted), its leading coefficient is the limit of the expected complexity as x grows, and almost every word then has distinct letters. This is a standard argument of a few lines that a competent combinatorialist would find right away, and the paper itself calls it elementary. Proving the conjecture as stated is what the author intended, so the result is not literal-only. + +*Follows from:* Standard grouping of words by equality pattern (set partition of positions), giving S(n,x) = sum over patterns p of c(p)·x(x-1)...(x-k(p)+1). This is the same falling-factorial reasoning behind Guo's own remark in his linked blog post that S(n,x) is a polynomial of degree at most n. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A341761](https://oeis.org/A341761) as [`Math0.Statements.A341761.statement`](../../lean/Math0/Statements/OEIS/A341761.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A341761.lean`](../../lean/Math0/Frontier/OEIS/A341761.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: the coefficient of x^n in S(n,x) is n*(n+1)/2. (Shiyao Guo, entry author, Feb 19 2021) + +Referees: OEIS A341761 (Shiyao Guo, 2021; still labelled "Conjecture" in rev #33, Mar 2024), cross-referenced with OEIS A340885. Shiyao Guo (Mivik), "On the Expected Subword Complexity of Random Words", https://mivik.moe/2021/research/expected-subword-complexity-en/, and the Chinese version https://mivik.moe/2021/research/expected-subword-complexity/ (updated 2026-03-26, still calls it an unproven conjecture). Related work that does not settle it: S. Janson, S. Lonardi, W. Szpankowski, "On average sequence complexity", TCS 326 (2004); I. Gheorghiciuc, M. D. Ward, "On correlation polynomials and subword complexity", DMTCS Proc. AH (AofA 2007), https://dmtcs.episciences.org/3553; Ahmadi and Ward, "Asymptotic Analysis of the kth Subword Complexity" (Entropy, 2020); Ivanko (Trudy IMM UrO RAN, 2008). I found no prior proof. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a341761, + author = {{math0}}, + title = {{The subword complexity polynomial S(n,x) has leading coefficient n(n+1)/2 (A341761, Guo's conjecture)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a341761}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a341761/paper.pdf b/results/oeis-a341761/paper.pdf new file mode 100644 index 0000000..9aaefec Binary files /dev/null and b/results/oeis-a341761/paper.pdf differ diff --git a/results/oeis-a341761/paper.tex b/results/oeis-a341761/paper.tex new file mode 100644 index 0000000..48d4cf3 --- /dev/null +++ b/results/oeis-a341761/paper.tex @@ -0,0 +1,359 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {↔}{{$\leftrightarrow$}}1 {→}{{$\to$}}1 {∈}{{$\in$}}1 {≠}{{$\ne$}}1 {∧}{{$\wedge$}}1 + {∑}{{$\sum$}}1 {·}{{$\cdot$}}1 {α}{{$\alpha$}}1 {≃}{{$\simeq$}}1 {↪}{{$\hookrightarrow$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{≃}{\ensuremath{\simeq}} +\newunicodechar{↪}{\ensuremath{\hookrightarrow}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} +\newtheorem{example}[theorem]{Example} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\Fac}{\mathcal{F}} +\newcommand{\Fix}{\operatorname{Fix}} +\newcommand{\ff}[2]{#1^{\underline{#2}}} +\newcommand{\coeff}[2]{[#1]\,#2} + +\title[The leading coefficient of the subword complexity polynomial]{The subword complexity polynomial $S(n,x)$ has leading coefficient $n(n+1)/2$: a proof of Guo's conjecture (OEIS A341761)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +For a finite word $w$ let $c(w)$, the subword complexity of $w$, be the number of distinct nonempty factors (contiguous subwords) of $w$, and let $S(n,x)$ be the sum of $c(w)$ over the $x^n$ words $w$ of length $n$ over an alphabet with $x$ letters. +In OEIS A341761, Shiyao Guo conjectured in 2021 that the coefficient of $x^n$ in the polynomial $S(n,x)$ is $n(n+1)/2$. +We prove this by grouping words according to which positions carry equal letters: $S(n,x)=\sum_p c(p)\,x(x-1)\cdots(x-k(p)+1)$ over the equality patterns $p$, where $k(p)$ is the number of distinct letters, and only the pattern with $n$ distinct letters contributes to $x^n$. +The argument is elementary; we found no earlier proof in the literature and report the result as new, settling the conjecture as stated. +The proof, including the polynomiality of $S(n,\cdot)$, is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry; the kernel checks that statement's definition of $S$ against rows $0$--$5$ of the OEIS data. +\end{abstract} +\maketitle + +\section{Introduction} + +A \emph{factor} of a word $w=w_1w_2\cdots w_n$ is a contiguous subword $w_iw_{i+1}\cdots w_j$ with $1\le i\le j\le n$. The \emph{subword complexity} $c(w)$ is the number of distinct nonempty factors of $w$; for example $c(aba)=5$, the factors being $a,b,ab,ba,aba$. For $n,x\ge0$ let $S(n,x)=\sum_{w\in A_x^n}c(w)$, where $A_x$ is an alphabet with $x$ letters. For $x\ge1$, $S(n,x)/x^n$ is the expected subword complexity of a uniformly random word of length $n$ over $A_x$. + +The OEIS entry A341761 \cite{A341761}, submitted by Shiyao Guo on February~19, 2021, is the triangle whose row $n$ lists the coefficients of $S(n,x)$ as a polynomial in $x$, constant term first: +$0;\ 0,1;\ 0,-1,3;\ 0,0,-3,6;\ 0,-1,1,-6,10;\ \dots$ +The entry states, without proof, that $S(n,x)$ has degree $n$ and constant coefficient $0$, and it contains the conjecture that the coefficient of $x^n$ is $n(n+1)/2$. The companion entry A340885 \cite{A340885} lists $S(n,2)$. In a blog post \cite{Guo}, Guo computes these polynomials (written $F_n(m)$ there) for $n\le 60$ by grouping candidate factors according to their autocorrelation, notes that $F_n$ is a polynomial of degree at most $n$, and lists $[x^n]F_n(x)=n(n+1)/2$ with the remark ``This is a conjecture.'' The entry links a table of rows $0$--$60$. + +We prove the conjecture (Theorem~\ref{thm:main}), via an explicit expansion of $S(n,x)$ in falling factorials of $x$ (Proposition~\ref{prop:formula}). + +\subsection*{Prior work and status} +The conjecture is still labelled ``Conjecture'' in the current revision of A341761 (\#33, March~20, 2024). Guo's blog post \cite{Guo}, in its English and Chinese versions (updated March~26, 2026), still calls it a conjecture; it justifies $\deg F_n\le n$ in one line but gives no argument for the leading coefficient. The average subword complexity of random words has been studied by Janson, Lonardi and Szpankowski \cite{JLS} (the average number of distinct substrings of a random text of length $n$ over a $k$-letter alphabet), Ivanko \cite{Ivanko} (an explicit approximation over a finite alphabet), Gheorghiciuc and Ward \cite{GW} (the expected number of distinct factors of a fixed length, via correlation polynomials) and Ahmadi and Ward \cite{AW} (its asymptotics for binary memoryless sources). These works concern the behaviour as the word length grows, for a fixed alphabet or source; as far as the math0 referees could determine, none addresses the coefficients of $S(n,x)$ as a polynomial in the alphabet size. The referees' searches (arXiv, Mathematics Stack Exchange, Chinese-language sources, general web search) found neither a proof nor a counterexample; the SeqFan mailing-list archive could not be searched directly. + +We therefore report the result as new. We stress that it is elementary. Once one knows that $S(n,\cdot)$ is a polynomial of degree at most $n$ (which Guo notes), its coefficient of $x^n$ equals $\lim_{x\to\infty}S(n,x)/x^n$, and a uniformly random word of length $n$ has pairwise distinct letters with probability $x(x-1)\cdots(x-n+1)/x^n\to1$; such a word has $n(n+1)/2$ distinct factors (Lemma~\ref{lem:nodup}). Specialists may regard the statement as evident; we found no recorded proof. +The Lean proof establishes Theorem~\ref{thm:main}, including the existence of the polynomial, and on the way the formula of Proposition~\ref{prop:formula}. Remark~\ref{rem:entry} is proved on paper only. + +\section{Statement}\label{sec:statement} + +The COMMENTS section of A341761 \cite{A341761} reads, in part (verbatim): +\begin{quote} +{\small\raggedright\texttt{S(n,x) is the sum of subword complexities (number of nonempty distinct subwords) of all words of length n and an alphabet with size x.}\\ +\texttt{[\dots]}\\ +\texttt{Conjecture: the coefficient of x\^{}n in S(n,x) is n*(n+1)/2.}\par} +\end{quote} +These lines carry no separate signature; they belong to the original submission, whose author line reads \texttt{\_Shiyao Guo\_, Feb 19 2021}. + +\begin{theorem}\label{thm:main} +For every $n\ge0$ there is a polynomial $P_n\in\Q[X]$ with $P_n(x)=S(n,x)$ for every $x\in\N$, and the coefficient of $X^n$ in $P_n$ is $n(n+1)/2$. +\end{theorem} +Such a polynomial is unique, since two polynomials over $\Q$ that agree on $\N$ are equal (\decl{poly_unique} below); so Theorem~\ref{thm:main} is a statement about \emph{the} polynomial $S(n,x)$. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A341761.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{827988f4\ldots faf23}) before any proof attempt. Its definitions and the statement read (verbatim; header, import, docstrings, proofs, one helper lemma and the data-check declarations omitted): +\begin{lstlisting} +namespace Math0.Statements.A341761 +open Polynomial +def factors {α : Type*} [DecidableEq α] (w : List α) : Finset (List α) := + (w.tails.flatMap fun t => t.inits.tail).toFinset +theorem mem_factors {α : Type*} [DecidableEq α] (w u : List α) : + u ∈ factors w ↔ u ≠ [] ∧ u <:+: w +def complexity {α : Type*} [DecidableEq α] (w : List α) : ℕ := (factors w).card +def S (n x : ℕ) : ℕ := ∑ w : Fin n → Fin x, complexity (List.ofFn w) +theorem poly_unique (P Q : ℚ[X]) (h : ∀ x : ℕ, P.eval (x : ℚ) = Q.eval (x : ℚ)) : P = Q +def statement : Prop := + ∀ n : ℕ, ∃ P : ℚ[X], (∀ x : ℕ, P.eval (x : ℚ) = (S n x : ℚ)) ∧ + P.coeff n = (n : ℚ) * (n + 1) / 2 +end Math0.Statements.A341761 +\end{lstlisting} +The encoding is as follows. +\begin{enumerate} +\item \emph{Factors.} \texttt{factors w} is the set of nonempty prefixes of the suffixes of $w$, and \decl{mem_factors} proves that it consists exactly of the nonempty lists $u$ that are contiguous infixes of $w$ (\texttt{<:+:} is Mathlib's infix relation). ``Subword'' in the entry means a contiguous factor: the entry's example lists the complexities $3,5,5,5,5,5,5,3$ of the binary words of length~$3$, and $c(aba)=5$ excludes the scattered subsequence $aa$. \texttt{complexity w} is the number of these factors, i.e.\ $c(w)$. +\item \emph{$S(n,x)$.} The words of length $n$ over an alphabet of size $x$ are the maps $\mathtt{Fin}\ n\to\mathtt{Fin}\ x$, turned into lists by \texttt{List.ofFn}; thus $S(0,x)=0$ (the empty word has complexity $0$) and $S(n,0)=0$ for $n\ge1$, consistent with the entry. +\item \emph{The polynomial.} ``The coefficient of $x^n$ in $S(n,x)$'' is read as the coefficient of $X^n$ in a polynomial $P\in\Q[X]$ that agrees with $S(n,\cdot)$ on $\N$. By \decl{poly_unique}, two polynomials over $\Q$ agreeing on $\N$ are equal, so such a $P$ is unique, and the existential quantifier adds only the polynomiality that the entry asserts. Coefficients are rational, so no integrality is assumed; $n(n+1)/2$ is computed in $\Q$. +\end{enumerate} + +\subsection*{Check against the OEIS data} +The statement file also defines the triangle and checks it against the entry, through the following declarations (verbatim; proofs, auxiliary lemmas, and the definitions of \decl{interp}, \decl{a}, and of the list \texttt{words x n} of all words of length $n$ over \texttt{Fin x} omitted): +\begin{lstlisting} +def Sw (n x : ℕ) : ℕ := ((words x n).map complexity).sum +theorem S_eq_Sw : S = Sw +def row (n : ℕ) : List ℚ := interp ((List.range (n + 1)).map fun x => (S n x : ℚ)) +theorem rows_data : (List.range 6).map row = + [[0], [0, 1], [0, -1, 3], [0, 0, -3, 6], [0, -1, 1, -6, 10], [0, 2, -6, 4, -10, 15]] +theorem a_data : (List.range 21).map (fun i => a (i + 0)) = + [0, 0, 1, 0, -1, 3, 0, 0, -3, 6, 0, -1, 1, -6, 10, 0, 2, -6, 4, -10, 15] +\end{lstlisting} +Here \decl{interp} computes, by Newton's forward-difference formula $P(x)=\sum_{k\le n}\Delta^kv_0\binom xk$ over $\Q$, the coefficients of the polynomial of degree at most $n$ through the values $v_x=S(n,x)$, $x=0,\dots,n$; this recovers the coefficients of $S(n,x)$ given the entry's claim that its degree is $n$, and \decl{a} reads the rows in order (offset $0$). Through \decl{S_eq_Sw}, \decl{rows_data} is proved by \texttt{decide +kernel}: the kernel enumerates all $x^n$ words for $x\le n\le5$, computes their complexities and interpolates (about 90 seconds of CPU time); \decl{a_data} then confirms the first $21$ terms of the OEIS data. The theorem we prove refers only to $S$; the data check anchors the definition of $S$ to the entry independently of the conjecture. Outside Lean, the formula of Proposition~\ref{prop:formula}, evaluated over all equality patterns with $n\le10$, reproduces all $66$ terms of the OEIS data section (rows $0$--$10$). + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A341761.lean}; Lean names are given in brackets. \emph{Notation.} For $n\in\N$ let $[n]=\{0,1,\dots,n-1\}$. A word of length $n$ over a set $A$ is a map $w\colon[n]\to A$, identified with the list $w(0)w(1)\cdots w(n-1)$. We write $\Fac(u)$ for the set of distinct nonempty factors of a word $u$, so $c(u)=|\Fac(u)|$. For a map $f\colon A\to B$, $f(u)$ denotes the letterwise image of $u$. For $x,k\in\N$ let $\ff xk=x(x-1)\cdots(x-k+1)$ (\texttt{Nat.descFactorial}; it is $0$ if $k>x$), and let $\ff Xk=X(X-1)\cdots(X-k+1)\in\Q[X]$ (\texttt{descPochhammer ℚ k}). + +\subsection{Equality patterns} + +\begin{definition}[\decl{pat}] +For $w\colon[n]\to A$ and $i\in[n]$ let $\pi_w(i)=\min\{j\in[n]: w(j)=w(i)\}$, the first position carrying the letter $w(i)$. A map $p\colon[n]\to[n]$ is a \emph{pattern} if $\pi_p=p$. For a pattern $p$ let $\Fix(p)=\{i: p(i)=i\}$ and $k(p)=|\Fix(p)|$ (\decl{nfix}). +\end{definition} + +\begin{lemma}[\decl{pat_spec}, \decl{pat_eq_iff}, \decl{pat_congr}, \decl{pat_pat}, \decl{pat_idem_apply}, \decl{pat_id}]\label{lem:pat} +Let $w\colon[n]\to A$. +\begin{enumerate} +\item $w(\pi_w(i))=w(i)$ for all $i$. +\item $\pi_w(i)=\pi_w(j)$ if and only if $w(i)=w(j)$. +\item If $v\colon[n]\to B$ satisfies $w(i)=w(j)\Leftrightarrow v(i)=v(j)$ for all $i,j$, then $\pi_v=\pi_w$. +\item $\pi_w$ is a pattern. +\item If $p$ is a pattern, then $p(p(i))=p(i)$ for all $i$. The identity map of $[n]$ is a pattern. +\end{enumerate} +\end{lemma} + +\begin{proof} +(1) The minimum is taken over a set that contains $i$, and it belongs to that set. +(2) If $\pi_w(i)=\pi_w(j)$, then $w(i)=w(\pi_w(i))=w(\pi_w(j))=w(j)$ by (1). If $w(i)=w(j)$, the two sets whose minima define $\pi_w(i)$ and $\pi_w(j)$ coincide. +(3) For each $i$ the sets $\{j:w(j)=w(i)\}$ and $\{j:v(j)=v(i)\}$ coincide. +(4) By (2), $\pi_w$ and $w$ satisfy the hypothesis of (3), so $\pi_{\pi_w}=\pi_w$. +(5) Applying (1) to $w=p$ gives $p(\pi_p(i))=p(i)$, and $\pi_p=p$. For the identity, (1) gives $\pi_{\mathrm{id}}(i)=\mathrm{id}(\pi_{\mathrm{id}}(i))=\mathrm{id}(i)=i$. +\end{proof} + +\subsection{Complexity depends only on the pattern} + +\begin{lemma}[\decl{complexity_map}, \decl{map_injOn_lists}]\label{lem:map} +Let $u$ be a word over $A$ and let $f\colon A\to B$ be injective on the set of letters of $u$. Then $c(f(u))=c(u)$. +\end{lemma} + +\begin{proof} +We show that $v\mapsto f(v)$ is a bijection from $\Fac(u)$ onto $\Fac(f(u))$. The image $f(v)$ of a factor $v$ of $u$ is a factor of $f(u)$, nonempty if $v$ is. Conversely, every factor of $f(u)$ has the form $f(v)$ for a factor $v$ of $u$ (Mathlib's \texttt{List.infix\_map\_iff}), and $v$ is nonempty if $f(v)$ is. So $\Fac(f(u))=\{f(v):v\in\Fac(u)\}$. The letters of every $v\in\Fac(u)$ are letters of $u$. If $f(v)=f(v')$ for $v,v'\in\Fac(u)$, then $v$ and $v'$ have the same length and, $f$ being injective on the letters of $u$, the same letter at each position; so $v=v'$ (by induction on the lists in Lean). +\end{proof} + +\begin{lemma}[\decl{complexity_pat}]\label{lem:cpat} +For every word $w\colon[n]\to A$, $c(w)=c(\pi_w)$, where $\pi_w$ is regarded as a word over $[n]$. +\end{lemma} + +\begin{proof} +By Lemma~\ref{lem:pat}(1), $w=w\circ\pi_w$; that is, the word $w$ is the letterwise image of the word $\pi_w$ under the map $w\colon[n]\to A$. The letters of $\pi_w$ are the positions $\pi_w(i)$, and $w$ is injective on them: if $w(\pi_w(i))=w(\pi_w(j))$, then $w(i)=w(j)$ by Lemma~\ref{lem:pat}(1), hence $\pi_w(i)=\pi_w(j)$ by Lemma~\ref{lem:pat}(2). Now apply Lemma~\ref{lem:map}. +\end{proof} + +\subsection{Counting the words with a given pattern} + +\begin{lemma}[\decl{fiberEquiv}, \decl{card_fiber}]\label{lem:fiber} +Let $x\in\N$ and let $p\colon[n]\to[n]$. +\begin{enumerate} +\item If $p$ is a pattern, the number of words $w\colon[n]\to[x]$ with $\pi_w=p$ is $\ff x{k(p)}$. +\item If $p$ is not a pattern, there is no word $w$ with $\pi_w=p$. +\end{enumerate} +\end{lemma} + +\begin{proof} +(1) Let $W_p=\{w\colon[n]\to[x] : \pi_w=p\}$ and let $E$ be the set of injective maps $\Fix(p)\to[x]$. For $w\in W_p$ let $\rho(w)$ be the restriction of $w$ to $\Fix(p)$. It is injective: if $i,j\in\Fix(p)$ and $w(i)=w(j)$, then $p(i)=\pi_w(i)=\pi_w(j)=p(j)$ by Lemma~\ref{lem:pat}(2), so $i=p(i)=p(j)=j$. For $e\in E$ let $\sigma(e)=e\circ p$, which is defined because $p(i)\in\Fix(p)$ by Lemma~\ref{lem:pat}(5). Since $e$ is injective, $\sigma(e)(i)=\sigma(e)(j)$ if and only if $p(i)=p(j)$, so $\pi_{\sigma(e)}=\pi_p=p$ by Lemma~\ref{lem:pat}(3); thus $\sigma(e)\in W_p$. The maps are mutually inverse: $\sigma(\rho(w))(i)=w(p(i))=w(\pi_w(i))=w(i)$ by Lemma~\ref{lem:pat}(1), and $\rho(\sigma(e))(i)=e(p(i))=e(i)$ for $i\in\Fix(p)$. Hence $|W_p|=|E|$, and the number of injections from a $k$-element set into an $x$-element set is $\ff xk$ (Mathlib's \texttt{Fintype.card\_embedding\_eq}). +(2) If $\pi_w=p$, then $\pi_p=\pi_{\pi_w}=\pi_w=p$ by Lemma~\ref{lem:pat}(4). +\end{proof} + +\begin{proposition}[\decl{S_eq}]\label{prop:formula} +For all $n,x\in\N$, +\[ + S(n,x)=\sum_{p\ \text{pattern}} c(p)\,\ff x{k(p)}, +\] +the sum running over the patterns $p\colon[n]\to[n]$. +\end{proposition} + +\begin{proof} +Partition the words $w\colon[n]\to[x]$ according to $\pi_w$ (\texttt{Finset.sum\_fiberwise}). By Lemma~\ref{lem:cpat}, every word $w$ with $\pi_w=p$ has $c(w)=c(p)$. So the words with $\pi_w=p$ contribute $c(p)$ times their number, which is $\ff x{k(p)}$ if $p$ is a pattern and $0$ otherwise, by Lemma~\ref{lem:fiber}. +\end{proof} + +For example, the five patterns for $n=3$ correspond to $aaa,aab,aba,abb,abc$, with $(k,c)=(1,3),(2,5),(2,5),(2,5),(3,6)$, so $S(3,x)=3x+15\,x(x-1)+6\,x(x-1)(x-2)=6x^3-3x^2$, which is row $3$ of the triangle. + +\subsection{Words with distinct letters} + +\begin{lemma}[\decl{complexity_nodup}, \decl{card_inits_tail}]\label{lem:nodup} +If $u$ is a word of length $m$ with pairwise distinct letters, then $c(u)=m(m+1)/2$. +\end{lemma} + +\begin{proof} +We prove $2c(u)=m(m+1)$ by induction on $u$. The empty word has no nonempty factors. Let $u=au'$ where $a$ does not occur in $u'$, the letters of $u'$ are pairwise distinct, and $u'$ has length $m'$. Since the suffixes of $u$ are $u$ itself and the suffixes of $u'$, the definition of \texttt{factors} gives $\Fac(u)=\Pi\cup\Fac(u')$, where $\Pi$ is the set of nonempty prefixes of $u$. The union is disjoint: every element of $\Pi$ begins with $a$, while every factor of $u'$ consists of letters of $u'$. The $m'+1$ nonempty prefixes of $u$ have different lengths, so $|\Pi|=m'+1$. Hence $2c(u)=2(m'+1)+m'(m'+1)=(m'+1)(m'+2)$. +\end{proof} + +\subsection{Proof of Theorem~\ref{thm:main}} +Fix $n$ and set +\[ + P_n=\sum_{p\ \text{pattern}} c(p)\,\ff X{k(p)}\in\Q[X]. +\] +(In Lean the sum runs over all $p\colon\mathtt{Fin}\ n\to\mathtt{Fin}\ n$, with summand $0$ when $p$ is not a pattern.) For $x\in\N$ we have $\ff Xk(x)=\ff xk$ (\texttt{descPochhammer\_eval\_eq\_descFactorial}), so $P_n(x)=S(n,x)$ by Proposition~\ref{prop:formula}. + +For the coefficient of $X^n$, recall that $\ff Xk$ is monic of degree $k$ (\texttt{monic\_descPochhammer}, \texttt{descPochhammer\_natDegree}). If $p$ is a pattern other than the identity, then $p(i)\ne i$ for some $i$, so $\Fix(p)$ is a proper subset of $[n]$, $k(p) w j = w i).min' ⟨i, by simp⟩ +private def nfix {n : ℕ} (p : Fin n → Fin n) : ℕ := (univ.filter fun i => p i = i).card +theorem result : statement := by + intro n + refine ⟨∑ p : Fin n → Fin n, if pat p = p then + C (complexity (List.ofFn p) : ℚ) * descPochhammer ℚ (nfix p) else 0, ?_, ?_⟩ + -- (evaluation at x : ℕ via S_eq; coefficient of X^n via Finset.sum_eq_single id) +\end{lstlisting} +Neither file uses \texttt{sorry}, \texttt{native\_decide} or custom axioms. + +\subsection*{Audit} +The file ends with the command \texttt{\#math0\_settles} applied to \decl{result} and \decl{statement}. This command, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (so no \texttt{sorry}, \texttt{native\_decide} or custom axiom); and (3) the type of \decl{result} is syntactically \decl{statement} or $\neg$\,\decl{statement}, up to metadata annotations, with no unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A341761.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A341761.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A341761.result' proves 'Math0.Statements.A341761.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; formal-conjectures \cite{FC} is pinned at commit \texttt{c77fdd4} but not used here, as the statement is a math0 formalization of an OEIS conjecture. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, rebuilds all math0 results (re-running every audit command) and checks that the pinned dependencies are unmodified. The proof file alone is checked by \texttt{lake env lean Math0/Frontier/OEIS/A341761.lean} in \path{lean/} (about $15$ seconds of CPU time once the statement file is built). + +{\footnotesize +\begin{thebibliography}{99} + +\bibitem{AW} +L.~Ahmadi and M.~D. Ward, \emph{Asymptotic analysis of the $k$th subword complexity}, Entropy \textbf{22} (2020), no.~2, 207, \url{https://doi.org/10.3390/e22020207}. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171 [cs.AI], 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{GW} +I.~Gheorghiciuc and M.~D. Ward, \emph{On correlation polynomials and subword complexity}, in: 2007 Conference on Analysis of Algorithms (AofA 07), Discrete Math. Theor. Comput. Sci. Proc. \textbf{AH} (2007), 1--18, \url{https://doi.org/10.46298/dmtcs.3553}. + +\bibitem{Guo} +S.~Guo (Mivik), \emph{On the expected subword complexity of random words}, blog post, January~30, 2021, updated March~26, 2026, \url{https://mivik.moe/2021/research/expected-subword-complexity-en/} (Chinese version: \texttt{.../expected-subword-complexity/}); linked from A341761 via \texttt{mivik.gitee.io}. + +\bibitem{Ivanko} +E.~E. Ivanko, \emph{Exact approximation of average subword complexity of finite random words over finite alphabet}, Trudy Inst. Mat. i Mekh. UrO RAN \textbf{14} (2008), no.~4, 185--189. + +\bibitem{JLS} +S.~Janson, S.~Lonardi, and W.~Szpankowski, \emph{On average sequence complexity}, Theoret. Comput. Sci. \textbf{326} (2004), 213--227. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A340885} +The OEIS Foundation Inc., \emph{Sum of subword complexity (number of nonempty distinct subwords) of all binary strings of length $n$}, entry A340885 (S.~Guo, 2021) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A340885}. + +\bibitem{A341761} +The OEIS Foundation Inc., \emph{Triangle read by rows in which row $n$ is the coefficients of the subword complexity polynomial $S(n,x)$}, entry A341761 (S.~Guo, 2021) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A341761}; revision \#33, March~20, 2024. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a342645/README.md b/results/oeis-a342645/README.md new file mode 100644 index 0000000..ed56de8 --- /dev/null +++ b/results/oeis-a342645/README.md @@ -0,0 +1,49 @@ +# A342645: diagonals of the eventual Mahonian-column polynomials + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A342645 +**Date:** 2026-10-29 + +## Result + +For x ≥ n, the number M(x,n) of permutations of x letters with major index n is a polynomial P_n(x) of degree ≤ n. Let T(n,k) = n!·[x^k]P_n(x). The triangle is computed by Newton interpolation of M(x,n) at x = n,…,2n. + +(Diagonals) For every m ≥ 0 there is Q ∈ ℚ[X] with deg Q = 2m and leading coefficient |A290030(m)/A053657(m+1)| such that T(n,n−m) = Q(n) for every n ≥ m. Here A290030(m) is the x^m-coefficient of the numerator L·B_m^(x) of Nørlund's polynomial B_m^(x) = m![t^m](t/(e^t−1))^x, where L is the least common denominator of its coefficients. A053657(m+1) = ∏_p p^{Σ_k ⌊m/((p−1)p^k)⌋}. + +(Formulas) T(n,n) = 1; T(n,n−1) = (n²−3n)/2; T(n,n−2) = (3n⁴−22n³+21n²−2n)/24; T(n,n−3) = (n⁶−13n⁵+37n⁴+13n³−134n²+96n)/48. Each holds for every n at which the left side is an entry of the triangle. + +## Assessment + +Expanding the known column polynomial into falling factorials gives T(n,k) = sum_j e_j n(n-1)...(n-j+1) c(n-j,k). The term j of T(n,n-m) then has degree 2m-j by the classical Stirling-polynomial fact, so the degree is 2m and the leading coefficient 1/(2^m m!) comes from j=0. Putting in e_0..e_3 = 1,-1,-1,0 and the closed forms of c(N,N-r) for r ≤ 3 gives the four formulas. Matching 1/(2^m m!) with |A290030(m)/A053657(m+1)| follows directly from the Chabert-Cahen primitivity statement recorded in A053657. The whole argument is about a page of standard material. The 2500-line Lean proof re-derives the Norlund denominators from von Staudt-Clausen and Adams' theorem, but that is formalization effort, not new mathematics. + +*Follows from:* The column formula P_n(x) = sum_j e_j C(x+n-j-1, n-j), with e_j the pentagonal-number coefficients of prod(1-q^i). It is in Mike Earnest's MSE answer linked from the entry and in Netto and Knuth (TAOCP 3, Sec. 5.1.1). The Stirling polynomial fact that c(N,N-r) is a polynomial of degree 2r with leading coefficient 1/(2^r r!) (Graham-Knuth-Patashnik (6.44), Jordan, Gessel-Stanley 1978). The A053657 comment citing Chabert-Cahen that (t/(e^t-1))^x = sum_n P(n,x) t^n/A053657(n+1) with P(n,x) primitive in Z[x]. With the leading x-coefficient (-1/2)^m/m! of [t^m](t/(e^t-1))^x, this gives |A290030(m)/A053657(m+1)| = 1/(2^m m!). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A342645](https://oeis.org/A342645) as [`Math0.Statements.A342645.statement`](../../lean/Math0/Statements/OEIS/A342645.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A342645.lean`](../../lean/Math0/Frontier/OEIS/A342645.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C A342645 Conjecture: For each m, T(n,n-m) is a polynomial of degree 2m whose leading coefficient is abs(A290030(m)/A053657(m+1)). %F Conjectures: T(n,n) = 1. T(n,n-1) = (-3n + n^2)/2. T(n,n-2) = (-2n + 21n^2 - 22n^3 + 3n^4)/24. T(n,n-3) = (96n - 134n^2 + 13n^3 + 37n^4 - 13n^5 + n^6)/48. (Peter Kagey, Mar 17 2021) + +Referees: The conjecture itself has no prior resolution that I found. OEIS A342645 (Kagey, Mar 17 2021; last edit #25, Aug 12 2022) still states both conjectures, and the local mirror equals upstream oeisdata. Known ingredients: +(1) The column polynomial via Euler's pentagonal expansion: E. Netto, Lehrbuch der Combinatorik (p. 96); D. Knuth, TAOCP Vol. 3, Sec. 5.1.1; Mike Earnest, MSE answer https://math.stackexchange.com/a/4065913 (linked in the entry); also G. Hegedus, arXiv:1002.2054, Thm 1.4. +(2) Stirling polynomials: c(N,N-k) is a polynomial of degree 2k with leading coefficient 1/(2^k k!) (C. Jordan, Calculus of Finite Differences; I. Gessel and R. Stanley, Stirling polynomials, JCTA 24 (1978)); s(n,n-k) = C(n-1,k) B_k^(n). +(3) Denominators of Norlund polynomials: J.-L. Chabert, Integer-valued polynomials on prime numbers and logarithm power expansion, Eur. J. Combin. 28 (2007) 754-761; A. Adelberg, Discrete Math. 204 (1999), Cor. 3; F. Bencherif, Sur une propriete des polynomes de Norlund, Actes CIRM 2(2) (2010) 71-77, Lemma 1 (d_n B_n^(x) is primitive in Z[x], with d_n = M_n/n! = A001898(n) and M_n = A053657(n+1)). Together with the OEIS A053657 comment a(n) = (n-1)!*A001898(n-1) (Bala, citing Chabert-Cahen), this already gives |A290030(m)/A053657(m+1)| = 1/(2^m m!). +Not found: any source combining these into the diagonal polynomiality of A342645 or its four FORMULA identities, on arXiv, OEIS, MSE search results, or SeqFan search results. MSE pages could not be fetched directly from this machine. + +## Citation + +```bibtex +@misc{math0:oeis-a342645, + author = {{math0}}, + title = {{A342645: diagonals of the eventual Mahonian-column polynomials}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a342645}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a342992/README.md b/results/oeis-a342992/README.md new file mode 100644 index 0000000..5394f48 --- /dev/null +++ b/results/oeis-a342992/README.md @@ -0,0 +1,54 @@ +# Every n not divisible by 5 has a multiple with only prime digits (A342992) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Sequences and series +**Source problem:** OEIS A342992 +**Date:** 2026-10-20 + +## Result + +For every integer n >= 1 with 5 not dividing n, there is some k such that k*n is positive and every decimal digit of k*n is prime (in {2,3,5,7}). Equivalently, a(n) > 0 for A342992 (Sariyar's conjecture). + +## Assessment + +Write n = 2^e m with m odd and coprime to 10. Take a block of L = phi(m)(e+1) digits from {2,3} that is divisible by 2^L; this is the textbook digit-by-digit induction recorded in A053316. Concatenating m copies of the block gives a number divisible by both 2^e and m, by Euler's theorem. Both steps are standard olympiad techniques and the whole argument fits in well under a page. The work is not new mathematics; it is mainly noticing that these known pieces apply directly to Sariyar's conjecture. + +*Follows from:* The classical block lemma (OEIS A053316, Bottomley 2000; a {2,3} variant of the 1971 All-Union Olympiad problem A053312): for every j there is a j-digit number with digits 2 and 3 that is divisible by 2^j. Combine it with Euler's theorem 10^phi(m) ≡ 1 (mod m) for m coprime to 10, and repeat the block m times, as in the IMO Shortlist 1994 N7 solution. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A342992](https://oeis.org/A342992) as [`def statement`](../../lean/Math0/Statements/OEIS/A342992.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A342992.lean`](../../lean/Math0/Frontier/OEIS/A342992.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: a(n) > 0 for all n that are not divisible by 5." (A342992, entry by _Metin Sariyar_, Apr 13 2021. Corneth added that a(625k) = 0.) + +Referees: No prior explicit proof of the A342992 conjecture was found. The entry still lists it as a conjecture (#60, Apr 22 2021) with no later %E edits. + +Closest prior material: +(1) OEIS A078239 (Murthy 2002; Robert Israel, Feb 2018). Comment: "Besides multiples of 10, 625 and its odd multiples have a(n)=0". Its Maple program implicitly assumes a prime-digit multiple exists for every n with 10∤n and 625∤n. This is an unproved assertion. A078250 (Howroyd, 2024) repeats the comment. +(2) OEIS A053316 (Henry Bottomley, Mar 2000; formula corrected by Israel, 2019): an n-digit number with digits 2 and 3 that is divisible by 2^n. This is exactly the proof's block lemma. The digits-{1,2} version is A053312, the 1971 All-Union olympiad problem (cut-the-knot.org/arithmetic/DivisibilityFromSovietMO.shtml). +(3) IMO Shortlist 1994 N7, "wobbly numbers" (prase.cz/kalva/short/soln/sh94n7.html): the same technique of combining a 2-power block with the coprime-to-10 part by repetition. +(4) Galperin & Reid, "Multiples Without Large Digits", Amer. Math. Monthly 126 (2019), as cited by John D. Cook (johndcook.com/blog/2025/12/16/multiples-with-no-large-digits/), with the citation's page numbers disputed by a reader comment. It covers digits 1–5 and does not imply this result. +(5) C. W. Wu, "Pigeonholes and repunits", Amer. Math. Monthly 121 (2014): the related {0,1} case. + +The result is elementary and folklore-adjacent, but no source states or proves it for prime digits or for digits {2,3}. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a342992, + author = {{math0}}, + title = {{Every n not divisible by 5 has a multiple with only prime digits (A342992)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a342992}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a342992/paper.pdf b/results/oeis-a342992/paper.pdf new file mode 100644 index 0000000..cdc38a7 Binary files /dev/null and b/results/oeis-a342992/paper.pdf differ diff --git a/results/oeis-a342992/paper.tex b/results/oeis-a342992/paper.tex new file mode 100644 index 0000000..2a5120f --- /dev/null +++ b/results/oeis-a342992/paper.tex @@ -0,0 +1,322 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,rw,constructor,by_contra}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {∈}{{$\in$}}1 + {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {¬}{{$\neg$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 + {↔}{{$\leftrightarrow$}}1 {≤}{{$\le$}}1 {≡}{{$\equiv$}}1 {∣}{{$\mid$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1 {∘}{{$\circ$}}1 {≠}{{$\ne$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\val}{\operatorname{val}} + +\title[Sariyar's conjecture for OEIS A342992]{Every positive integer not divisible by $5$ has a multiple with only prime digits: Sariyar's conjecture for OEIS A342992} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + +\begin{document} +\begin{abstract} +For $n\ge1$ let $a(n)$ be the smallest $k$ such that all decimal digits of $kn$ are prime, or $0$ if there is no such $k$; this is the sequence A342992 of the OEIS, contributed by Metin Sariyar in 2021. +We prove the conjecture stated in the entry that $a(n)>0$ whenever $5\nmid n$. The proof gives more: every such $n$ has a positive multiple whose decimal digits are all $2$ or $3$. Writing $n=2^em$ with $m$ odd, a block of $L=\varphi(m)(e+1)$ digits from $\{2,3\}$ that is divisible by $2^L$, repeated $m$ times, is divisible by $n$. +To our knowledge this is the first proof of the conjecture; the argument is elementary and both of its ingredients are classical. +The conjecture, in the form $a(n)>0$, is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before the proof attempt, whose definitions are checked by the kernel against all $81$ listed terms; this statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +The sequence A342992 of the OEIS \cite{A342992}, contributed by Metin Sariyar on April~13, 2021, with offset $1$, is +\[ + a(n)=\begin{cases}\min\{k\ge1: \text{every decimal digit of } kn \text{ lies in } \{2,3,5,7\}\} & \text{if such } k \text{ exist},\\ 0 & \text{otherwise}.\end{cases} +\] +The entry lists $a(1),\dots,a(81)$, beginning $2,1,1,8,1,12,1,4,3,0$; for example $a(4)=8$ because $8\cdot4=32$, and the largest listed term is $a(81)=93$. A multiple of $10$ ends in the digit $0$, so $a(n)=0$ when $10\mid n$. The entry's first comment states that $a(n)=0$ also for $n=625,1875,3125,4375,\dots$, ``because no such k has been found yet for these numbers'', and its second comment is Sariyar's conjecture: +\begin{quote} +\emph{$a(n)>0$ for all $n$ that are not divisible by $5$.} +\end{quote} +On April~21, 2021, David A.~Corneth added that $a(625k)=0$ for all $k\ge1$, because the last four digits of a multiple of $625$ always contain a nonprime digit. We prove Sariyar's conjecture (Theorem~\ref{thm:main}); the proof shows that the digits can even be taken from $\{2,3\}$ (Proposition~\ref{prop:23}). + +\subsection*{Method} +Write $n=2^em$ with $m$ odd; then $\gcd(m,10)=1$. A digit-by-digit induction gives, for every $j$, a $j$-digit number with digits in $\{2,3\}$ that is divisible by $2^j$. Take such a block $N$ of length $L=\varphi(m)(e+1)$, where $\varphi$ is Euler's totient function. Then $2^e\mid N$, and $10^L\equiv1\pmod m$ by Euler's theorem, so the number formed by $m$ copies of the block is congruent to $mN\equiv0$ modulo $m$ and is still divisible by $2^e$; hence it is divisible by $n$. + +\subsection*{Prior work} +Both ingredients are classical. The sequence A053316 \cite{A053316} of Henry Bottomley (March~6, 2000; formula corrected by Robert Israel, 2019) consists of the $n$-digit numbers with digits $2$ and $3$ that are divisible by $2^n$, and its recurrence is the induction of Lemma~\ref{lem:block} below. The analogous statement for the digits $1$ and $2$ (A053312 \cite{A053312}, also Bottomley's) was a problem of the 1971 All-Union (Soviet) Mathematical Olympiad, as recorded in A126933 \cite{A126933} with the reference \cite{TT}, and in \cite{Bog}. Combining a block divisible by a power of $2$ with the part of $n$ coprime to $10$ by repeating the block is the method of the solution of Problem~N7 of the 1994 IMO Shortlist (``wobbly numbers'') in \cite{IMO94}; there the number of copies is chosen so that a power of $10$ is $\equiv1$ modulo a suitable multiple of that part, and the repeated block is written as a product with a geometric sum. + +The closely related sequence A078239 \cite{A078239} (Amarnath Murthy, 2002) is the smallest multiple of $n$ using only prime digits, i.e.\ $n\cdot a(n)$. On February~12, 2018, Robert Israel added the comment ``Besides multiples of 10, 625 and its odd multiples have a(n)=0'', together with a Maple program that returns $0$ exactly when $10\mid n$ or $625\mid n$ and otherwise searches without a bound; the program thus presupposes, without proof, that every other $n$ has a prime-digit multiple. The PARI program in A342992 itself (Michel Marcus, April~21, 2021) makes the same presupposition: it returns $0$ exactly when $10\mid n$ or $625\mid n$ and otherwise searches without a bound. Andrew Howroyd repeated Israel's comment in A078250 \cite{A078250} in 2024. In Remark~\ref{rem:zeros} we note that the method of this paper, with a second block, proves this presupposition, so that $a(n)=0$ holds exactly when $10\mid n$ or $625\mid n$; this remark is not formalized. For digits $1,\dots,5$, a result attributed to a 2019 item in the \emph{American Mathematical Monthly} and discussed in \cite{Cook} gives a multiple of every $n$ with $10\nmid n$; it does not imply the present result. + +\subsection*{Status} +The statement is still marked ``Conjecture'' in A342992; the current revision (\#60, April~22, 2021) has no later edits. We read the entry in the copy of the OEIS database used by math0, dated October~17, 2026, in which no other entry refers to A342992. The math0 referees' web searches (OEIS, arXiv, MathOverflow, Mathematics Stack Exchange, AoPS, SeqFan, Prime Curios) found no proof. The statement has no file in the formal-conjectures repository \cite{FC} at the commit pinned by math0. We therefore classify the result as new, with the caveat that it is an easy consequence of the classical lemmas above and may be known as folklore. + +\section{Statement}\label{sec:statement} + +For a finite list $w=(w_0,\dots,w_{L-1})$ of natural numbers put $\val(w)=\sum_{i=0}^{L-1}w_i10^i$ and $|w|=L$. Every $X\ge1$ has a unique \emph{digit list}, the list $w$ with entries in $\{0,\dots,9\}$, last entry $w_{L-1}\ne0$, and $\val(w)=X$; read from left to right the digits of $X$ are $w_{L-1},\dots,w_0$. The digit list of $0$ is empty. We write $u\mathbin{+\!\!+}v$ for concatenation of lists, so that +\begin{equation}\label{eq:append} + \val(u\mathbin{+\!\!+}v)=\val(u)+10^{|u|}\val(v). +\end{equation} +In particular $u\mathbin{+\!\!+}(d)$ is $u$ with $d$ placed as a new \emph{leading} digit. + +The name of A342992 \cite{A342992} reads, verbatim: +\begin{quote}\raggedright +{\small\texttt{Smallest k such that k*n contains only prime digits, or 0 if no such k exists.}} +\end{quote} +and the COMMENTS section contains, verbatim (the entry's author line is \texttt{\_Metin Sariyar\_, Apr 13 2021}; the comment is unsigned): +\begin{quote} +{\small\texttt{Conjecture: a(n) > 0 for all n that are not divisible by 5.}} +\end{quote} + +\begin{theorem}\label{thm:main} +Let $n\ge1$ with $5\nmid n$. Then $a(n)>0$; that is, there is $k\ge1$ such that every decimal digit of $kn$ is prime. +\end{theorem} + +The proof gives the following stronger statement, which implies Theorem~\ref{thm:main} because $2$ and $3$ are prime. + +\begin{proposition}\label{prop:23} +Let $n\ge1$ with $5\nmid n$. Then there is $k\ge1$ such that every decimal digit of $kn$ is $2$ or $3$. +\end{proposition} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A342992.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{d47836b6\ldots 54d7}) before any proof attempt. Its main definitions and the statement read, verbatim (the import, comments and docstrings, blank lines, the decidability instance, the computable definitions \decl{primeDigitsB} and \decl{aSearch} used for the data check, and all theorems are omitted; the main theorems are listed below): +\begin{lstlisting} +namespace Math0.Statements.A342992 +def PrimeDigits (m : ℕ) : Prop := 0 < m ∧ ∀ d ∈ Nat.digits 10 m, d.Prime +open Classical in +noncomputable def a (n : ℕ) : ℕ := + if h : ∃ k, PrimeDigits (k * n) then Nat.find h else 0 +def statement : Prop := ∀ n : ℕ, 1 ≤ n → ¬ 5 ∣ n → 0 < a n +end Math0.Statements.A342992 +\end{lstlisting} +Here \texttt{Nat.digits 10 m} is the digit list of $m$ defined above. A digit $d<10$ is prime exactly when $d\in\{2,3,5,7\}$, so \texttt{PrimeDigits m} says that $m$ is positive and all its decimal digits are prime. The condition $0 a (i + 1)) = + [2, 1, 1, 8, 1, 12, 1, 4, 3, 0, 2, 6, 4, 18, 5, 2, 15, 4, 3, 0, 12, 1, 1, 3, 1, 2, 1, 9, 8, + 0, 12, 1, 1, 8, 1, 2, 1, 14, 7, 0, 13, 6, 54, 8, 5, 7, 5, 49, 15, 0, 5, 1, 1, 43, 1, 42, 1, + 4, 43, 0, 12, 6, 4, 43, 5, 42, 5, 4, 8, 0, 5, 1, 1, 3, 1, 7, 1, 74, 3, 0, 93] := by + rw [show (fun i => a (i + 1)) = a ∘ (fun i => i + 1) from rfl, ← List.map_map] + exact map_a_eq_of_aSearch (B := 100) (by decide +kernel) +\end{lstlisting} +By \decl{a_pos_iff}, \decl{statement} is equivalent to: every $n\ge1$ with $5\nmid n$ has a positive multiple all of whose decimal digits are prime; so the value $0$ of \decl{a} cannot be reached in an unintended way. To compare \decl{a} with the OEIS data, the computable function \texttt{aSearch n B} returns \texttt{some 0} if $n>0$ and $n\equiv0\pmod{10}$, and otherwise the least $k0$ and every digit of $kn$ is prime; we find one whose digits are all $2$ or $3$, which proves Proposition~\ref{prop:23}. + +\emph{Decomposition.} Write $n=2^em$ with $m$ odd (\decl{Nat.exists_eq_pow_mul_and_not_dvd}). Then $m\ge1$ since $n\ge1$, and $5\nmid m$ since $m\mid n$. Hence $\gcd(10,m)=1$ and $\varphi(m)\ge1$. + +\emph{The block.} Let $L=\varphi(m)(e+1)$, and let $w$ be the list of Lemma~\ref{lem:block} with $j=L$; put $N=\val(w)$. By Euler's theorem (\decl{Nat.ModEq.pow_totient}), $10^{\varphi(m)}\equiv1\pmod m$, hence $10^L=\bigl(10^{\varphi(m)}\bigr)^{e+1}\equiv1\pmod m$. Since $\varphi(m)\ge1$ we have $e\le L$, so $2^e\mid2^L\mid N$. + +\emph{Repetition.} Let $X=\val(w^{m})$. Lemma~\ref{lem:rep} with $D=2^e$ and $t=m$ gives $X\equiv mN\equiv0\pmod m$ and $2^e\mid X$. As $m$ is odd, $\gcd(2^e,m)=1$, so $n=2^em\mid X$ (\decl{Nat.Coprime.mul_dvd_of_dvd_of_dvd}). + +\emph{Digits.} Every entry of $w^{m}$ is an entry of $w$, so it is $2$ or $3$. In particular all entries are less than $10$ and the last entry is nonzero, so $w^{m}$ is the digit list of $X$ (\decl{Nat.digits_ofDigits}). Since $m\ge1$, $w^m=w\mathbin{+\!\!+}w^{m-1}$ has length at least $L\ge1$, so it is nonempty; as the digit list of $0$ is empty, $X>0$. + +\emph{Conclusion.} Put $k=X/n$. Then $kn=X>0$, and every digit of $kn$ is $2$ or $3$, hence prime. By \decl{a_pos_iff}, $a(n)>0$. +\end{proof} + +\begin{remark}[Example] +For $n=6$ we have $e=1$, $m=3$, $\varphi(3)=2$ and $L=4$. The block is $3232=2^4\cdot202$, and three copies give $X=323232323232=6\cdot53872053872$. The construction is far from minimal: $a(6)=12$, with $12\cdot6=72$. +\end{remark} + +\begin{remark}[The zeros of A342992; not formalized]\label{rem:zeros} +For $n\ge1$, $a(n)=0$ if and only if $10\mid n$ or $625\mid n$. This determines the zeros of A342992 and of A078239, and proves the presupposition of Israel's comment and program in A078239 \cite{A078239} and of the PARI program in A342992 \cite{A342992}. + +If $10\mid n$, every positive multiple of $n$ ends in $0$. If $625\mid n$ and $X$ is a positive multiple of $n$, then $X\bmod 10^4\in\{625i:0\le i\le15\}$; written with four digits these residues are $0000$, $0625$, $1250$, $1875$, $2500$, $3125$, $3750$, $4375$, $5000$, $5625$, $6250$, $6875$, $7500$, $8125$, $8750$, $9375$, and each contains one of the digits $0,1,4,6,8,9$. If $X\ge1000$, these four digits are the last four digits of $X$; if $X<1000$, then $X=625$, which contains $6$. This is Corneth's argument \cite{A342992}. + +Conversely, let $10\nmid n$ and $625\nmid n$. If $5\nmid n$, apply Theorem~\ref{thm:main}. Otherwise $n$ is odd and $n=5^fm$ with $1\le f\le3$ and $\gcd(m,10)=1$. Let $w$ be the digit list of the number formed by $\varphi(m)$ copies of $375$, so $|w|=3\varphi(m)$, $10^{|w|}\equiv1\pmod m$, and $125\mid\val(w)$ because $\val(w)\equiv375\pmod{1000}$. Lemma~\ref{lem:rep} with $D=125$ and $t=m$ shows that $X=\val(w^m)$, the number formed by $m\varphi(m)$ copies of $375$, is divisible by $125$ and by $m$, hence, as $\gcd(125,m)=1$, by $125m$ and by $n$; its digits $3,7,5$ are prime. + +This remark is not part of the Lean development. We checked it numerically for all $n<6000$ by a breadth-first search over residues modulo $n$, and checked the two constructions directly for smaller ranges. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in the file \path{lean/Math0/Frontier/OEIS/A342992.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A342992.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A342992.result}, of type \decl{Math0.Statements.A342992.statement}, which is Theorem~\ref{thm:main}. The multiple of Proposition~\ref{prop:23} is constructed inside the proof of \decl{result}, but Proposition~\ref{prop:23} is not stated as a separate Lean theorem, so the audit below certifies Theorem~\ref{thm:main} only. Lemmas~\ref{lem:block} and~\ref{lem:rep} are the private declarations \decl{exists_block} and \decl{rep_props}. Their statements, the head of the main theorem, and the last line of the file read, verbatim: +\begin{lstlisting} +private lemma exists_block (j : ℕ) : ∃ l : List ℕ, l.length = j ∧ (∀ d ∈ l, d = 2 ∨ d = 3) ∧ + 2 ^ j ∣ Nat.ofDigits 10 l := by +private lemma rep_props (l : List ℕ) (m D : ℕ) (hm : 10 ^ l.length ≡ 1 [MOD m]) + (hD : D ∣ Nat.ofDigits 10 l) (t : ℕ) : + Nat.ofDigits 10 (List.replicate t l).flatten ≡ t * Nat.ofDigits 10 l [MOD m] ∧ + D ∣ Nat.ofDigits 10 (List.replicate t l).flatten := by +theorem result : statement := by + intro n hn h5 + rw [a_pos_iff] + obtain ⟨e, m, hm2, rfl⟩ := Nat.exists_eq_pow_mul_and_not_dvd (by omega : n ≠ 0) 2 (by decide) +#math0_settles Math0.Frontier.A342992.result Math0.Statements.A342992.statement +\end{lstlisting} +Here \texttt{Nat.ofDigits 10 l} is $\val(l)$. The proof file uses no \texttt{native\_decide}, \texttt{sorry} or \texttt{set\_option}; its only uses of \texttt{decide} check that $2\ne1$ and that $5$ is odd. The data checks in the statement file use \texttt{decide +kernel}, which evaluates in the kernel and adds no axioms; the statement file compiles in about seven seconds. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata annotations and without unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\tiny] +math0 audit: 'Math0.Statements.A342992.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A342992.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A342992.result' proves 'Math0.Statements.A342992.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The two files can also be checked individually with \texttt{lake env lean} in the directory \path{lean}. + +{\small\raggedright +\begin{thebibliography}{99} + +\bibitem{Bog} +A.~Bogomolny, \emph{A problem of divisibility by $2^n$}, Cut The Knot, \url{https://www.cut-the-knot.org/arithmetic/DivisibilityFromSovietMO.shtml}. + +\bibitem{Cook} +J.~D. Cook, \emph{Multiples with no large digits}, blog post, December~16, 2025, \url{https://www.johndcook.com/blog/2025/12/16/multiples-with-no-large-digits/}. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171 [cs.AI], 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{IMO94} +J.~Scholes, \emph{35th IMO 1994 shortlist, Problem N7}, problem and solution, 2002, \url{https://prase.cz/kalva/short/soln/sh94n7.html}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A053312} +The OEIS Foundation Inc., \url{https://oeis.org/A053312}, entry by H.~Bottomley (March~6, 2000). + +\bibitem{A053316} +The OEIS Foundation Inc., \url{https://oeis.org/A053316}, entry by H.~Bottomley (March~6, 2000); formula corrected by R.~Israel (October~27, 2019). + +\bibitem{A078239} +The OEIS Foundation Inc., \url{https://oeis.org/A078239}, entry by A.~Murthy (November~23, 2002); comment, program and more terms by R.~Israel (February~12, 2018). + +\bibitem{A078250} +The OEIS Foundation Inc., \url{https://oeis.org/A078250}, entry by A.~Murthy (November~24, 2002); comment and terms by A.~Howroyd (September~17, 2024). + +\bibitem{A126933} +The OEIS Foundation Inc., \url{https://oeis.org/A126933}, entry by G.~Leversha (March~18, 2007). + +\bibitem{A342992} +The OEIS Foundation Inc., \url{https://oeis.org/A342992}, entry by M.~Sariyar (April~13, 2021); comment by D.~A. Corneth (April~21, 2021); revision \#60. + +\bibitem{TT} +J.~B. Tabov and P.~J. Taylor, \emph{Methods of Problem Solving, Book~1}, Australian Mathematics Trust, 1996. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a344710/README.md b/results/oeis-a344710/README.md new file mode 100644 index 0000000..389c856 --- /dev/null +++ b/results/oeis-a344710/README.md @@ -0,0 +1,36 @@ +# A344710: non-obtuse lattice triangles with sides >= sqrt(n) have |det| > (sqrt 3 / 2) n + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A344710 +**Date:** 2026-10-18 + +## Result + +For every n >= 1, let a(n) be the least value of |det(B-A, C-A)| (twice the area) over lattice triangles ABC in Z^2 that are non-degenerate and non-obtuse and have all three squared side lengths >= n. Then sqrt(3/4) * n < a(n). This is Waldmann's conjectured inequality in OEIS A344710. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A344710](https://oeis.org/A344710) as [`Math0.Statements.A344710.statement`](../../lean/Math0/Statements/OEIS/A344710.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A344710.lean`](../../lean/Math0/Frontier/OEIS/A344710.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Formula: "a(n) > sqrt(3/4)*n (conjectured)." Comment: "Conjectured next terms (from the conjectured inequality a(n) > sqrt(3/4)*n) are a(50,...,64) ?= 45, 48, 48, 52, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56." (entry by _Jonathan F. Waldmann_, May 26 2021). A344845 has the same inequality a(n) > sqrt(3/4)*m (conjectured), by the same author, May 29 2021. + +Referees: A. Mazel, I. Stuhl, Y. Suhov, "High-density hard-core model on Z^2 and norm equations in ring Z[...]", arXiv:1909.11648 (v1 25 Sep 2019; v3 22 Jun 2023). Lemma 3.4.4, eq. (3.1): sqrt(3)D^2/2 < S(D) < sqrt(3)D^2/2 + sqrt(2)D. S(D) is twice the minimal area of non-obtuse Z^2-triangles with sides >= D, so A344710(n) = S(sqrt n). The paper calls the lower bound "obvious". D. Krachun, "Triangles on Z^2 and sliding phenomenon" / "Extreme Gibbs measures for high-density hard-core model on Z^2", arXiv:1912.07566 (Dec 2019 / Jun 2020). Definition 2.1 gives the same S(D) for all D > 0, and Theorem 2 gives S(D) = (sqrt3/2)D^2 + O(D^{4/5}). The underlying inequality is the classical one: a non-obtuse triangle with all sides >= D has area >= (sqrt3/4)D^2, since area = (1/2)ab sin C with the largest angle C in [60,90] degrees. Equality would need an equilateral lattice triangle, and Z^2 has none. OEIS A344710 and A344845 (local mirror and GitHub, revisions #84/#52 of Feb 2022) still list the inequality as conjectured. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a344710, + author = {{math0}}, + title = {{A344710: non-obtuse lattice triangles with sides >= sqrt(n) have |det| > (sqrt 3 / 2) n}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a344710}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a344710/paper.pdf b/results/oeis-a344710/paper.pdf new file mode 100644 index 0000000..6b6c3e9 Binary files /dev/null and b/results/oeis-a344710/paper.pdf differ diff --git a/results/oeis-a344710/paper.tex b/results/oeis-a344710/paper.tex new file mode 100644 index 0000000..a63918b --- /dev/null +++ b/results/oeis-a344710/paper.tex @@ -0,0 +1,373 @@ +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℝ}{{$\mathbb{R}$}}1 {∧}{{$\wedge$}}1 + {×}{{$\times$}}1 {∈}{{$\in$}}1 {→}{{$\to$}}1 {∃}{{$\exists$}}1 {∀}{{$\forall$}}1 + {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {↔}{{$\leftrightarrow$}}1 {√}{{$\surd$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\R}{\mathbb{R}} +\DeclareMathOperator{\dett}{det_2} + +\title[Non-obtuse lattice triangles (OEIS A344710)]{Non-obtuse lattice triangles with no side shorter than $\sqrt{n}$ have doubled area greater than $\frac{\sqrt3}{2}\,n$: Waldmann's inequality for OEIS A344710} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +For $n\ge1$ let $a(n)$ be twice the smallest area of a non-obtuse triangle with vertices in $\Z^2$ and no side shorter than $\sqrt n$; this is the sequence A344710 of the OEIS. +We prove that $a(n)>\sqrt{3/4}\,n$ for every $n\ge1$, the inequality recorded as conjectured in the entry by J.~F. Waldmann (2021). +The proof combines the identity $16\,\mathrm{area}^2=2XY+2YZ+2ZX-X^2-Y^2-Z^2$ for the squared side lengths $X,Y,Z$ with the bound $(X+Y-Z)^2\le XY$, valid when $Z$ is the largest of them and the triangle is non-obtuse, and it excludes equality by the irrationality of $\sqrt3$. +The result is not new: it follows directly from the formula $\mathrm{area}=\frac12 bc\sin\alpha$, and in the equivalent form $S(D)>\frac{\sqrt3}{2}D^2$ it is stated, and called obvious, in a 2019 paper of Mazel, Stuhl and Suhov on the hard-core model on $\Z^2$; the OEIS entry still lists it as a conjecture. +Our contribution is, to our knowledge, the first formal proof: it is verified in Lean~4 with Mathlib against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before any proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +The OEIS entry A344710 \cite{A344710}, created by Jonathan F. Waldmann on May~26, 2021, has the name +\begin{quote} +a(n)/2 is the smallest possible area of a non-obtuse triangle with coordinates in Z\^{}2 and no side shorter than sqrt(n). +\end{quote} +It has offset $1$ and lists the $49$ terms +\[ +1,2,4,4,5,8,8,8,9,10,12,12,12,15,15,15,15,18,20,20,23,23,23,23,23,24,28,\dots,45 +\] +for $n=1,\dots,49$. For example, $a(4)=4$, attained by the right isosceles triangle with vertices $(0,0),(2,0),(0,2)$. +Its FORMULA section contains the line ``\texttt{a(n) > sqrt(3/4)*n (conjectured).}'', and the companion entry A344845 \cite{A344845} (same author, May~29, 2021), in which the shortest side has length exactly $\sqrt m$ for $m$ a sum of two squares \cite{A001481}, records the same inequality as conjectured. +An equilateral triangle of side $\sqrt n$ has doubled area $\frac{\sqrt3}{2}n=\sqrt{3/4}\,n$, so the conjecture says that lattice triangles cannot do as well as the equilateral one. +We prove it (Theorem~\ref{thm:main}). + +\subsection*{Prior work and status} +We do not claim the result as new. +For a non-obtuse triangle with largest angle $\gamma$ and adjacent sides $b,c\ge\sqrt n$ one has $\pi/3\le\gamma\le\pi/2$, hence $2\,\mathrm{area}=bc\sin\gamma\ge\frac{\sqrt3}{2}n$, and equality would require an equilateral triangle, which cannot have its vertices in $\Z^2$. This is the classical argument; our proof (Section~\ref{sec:proof}) is an algebraic form of it, see Remark~\ref{rem:geom}. + +The quantity $a(n)$ itself was studied before the OEIS entry was created. +Mazel, Stuhl and Suhov \cite{MSS}, in their work on the high-density hard-core model on $\Z^2$ with Euclidean exclusion distance $D$ (arXiv, first version September~2019), consider the problem of minimizing the area of a $\Z^2$-triangle with side lengths at least $D$ and angles at most $\pi/2$ \cite[(2.1)]{MSS}, and write $S(D)$ for twice the minimal area; they assume throughout that $D^2$ is a sum of two squares. For such $n=D^2$ one therefore has $a(n)=S(\sqrt n)$. This loses nothing: squared distances in $\Z^2$ are sums of two squares, so $a(n)=a(n')$ for the least sum of two squares $n'\ge n$ (cf.\ the second comment of A344710), and a lower bound $\frac{\sqrt3}{2}n'$ for $a(n')$ gives the bound $\frac{\sqrt3}{2}n$ for $a(n)$. +Their Lemma~3.4.4 states +\[ + \tfrac{\sqrt3}{2}D^20$ \cite[Definition~2.1]{Kr}, so that $a(n)=S(\sqrt n)$ for all $n\ge1$, and proves $S(D)=\frac{\sqrt3}{2}D^2+O(D^{4/5})$ \cite[Theorem~2]{Kr}. Thus $a(n)=\frac{\sqrt3}{2}n+O(n^{2/5})$, and the constant $\frac{\sqrt3}{2}$ in Theorem~\ref{thm:main} cannot be improved. +Mazel, Stuhl and Suhov also solve the disk-packing problem on $\Z^2$ for disks of diameter $D$ (their Lemma~3.5 gives the maximal density $1/S(D)$); this is the packing problem behind the sequence $b(n)$ discussed in the comments of A344710, which we do not treat here. +Neither paper is cited in A344710 or A344845, and both entries (revisions \#84 and \#52, February~16, 2022) still mark the inequality as conjectured. It is not among the statements of the formal-conjectures repository \cite{FC} at the commit pinned by math0 (\texttt{c77fdd4}). +We therefore classify the result as the first formal proof, to our knowledge, of a known result. + +\subsection*{Method} +Write $X,Y,Z$ for the squared side lengths and $D$ for twice the signed area. The Lagrange identity gives $4D^2=4XY-(X+Y-Z)^2$; if $Z$ is the largest of the three and the triangle is non-obtuse then $0\le X+Y-Z\le\min(X,Y)$, so $4D^2\ge3XY\ge3n^2$ (Lemmas~\ref{lem:id}--\ref{lem:sym}). Equality $4D^2=3n^2$ with $n\ge1$ would make $\sqrt3$ rational (Lemma~\ref{lem:irr}). + +\section{Statement}\label{sec:statement} + +For $A,B,C\in\Z^2$ and $n\in\N$ put +\[ + \dett(A,B,C)=\det(B-A,\,C-A),\qquad |PQ|^2=(P_1-Q_1)^2+(P_2-Q_2)^2 , +\] +so that $|\dett(A,B,C)|$ is twice the area of the triangle $ABC$. The angle of $ABC$ at $A$ is at most $\pi/2$ if and only if $(B-A)\cdot(C-A)\ge0$, and similarly at $B$ and $C$. + +\begin{definition}\label{def:adm} +A triple $(A,B,C)$ of points of $\Z^2$ is \emph{$n$-admissible} if $\dett(A,B,C)\ne0$, the three squared side lengths $|AB|^2,|BC|^2,|CA|^2$ are at least $n$, and +\[ + (B-A)\cdot(C-A)\ge0,\qquad (C-B)\cdot(A-B)\ge0,\qquad (A-C)\cdot(B-C)\ge0 . +\] +Let $a(n)$ be the least value of $|\dett(A,B,C)|$ over all $n$-admissible triples. +\end{definition} + +The right isosceles triangle $(0,0),(n+1,0),(0,n+1)$ is $n$-admissible, so the minimum exists. Thus $a(n)/2$ is the smallest area of a non-obtuse lattice triangle with no side shorter than $\sqrt n$, which is the definition of A344710. + +\begin{theorem}\label{thm:main} +For every integer $n\ge1$, +\[ + a(n)>\sqrt{3/4}\;n=\tfrac{\sqrt3}{2}\,n ,\qquad\text{equivalently}\qquad 4a(n)^2>3n^2 . +\] +\end{theorem} + +The conjecture appears in the FORMULA section of A344710 \cite{A344710} as the line +\begin{quote} +{\small\texttt{a(n) > sqrt(3/4)*n (conjectured).}} +\end{quote} +This line is unsigned; the entry's author is Jonathan F. Waldmann (May~26, 2021), and its last revision (\#84) is dated February~16, 2022. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A344710.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{4f0e6940\ldots 6fdf74}, recorded in \path{lean/Math0/Statements/FROZEN.sha256}) before any proof attempt. Its definitions read as follows (verbatim; the copyright header, the import, docstrings, blank lines, the decidability instance, the bounded search used for the data check and all theorems are omitted): +\begin{lstlisting} +namespace Math0.Statements.A344710 +def det2 (A B C : ℤ × ℤ) : ℤ := (B.1 - A.1) * (C.2 - A.2) - (C.1 - A.1) * (B.2 - A.2) +def dist2 (P Q : ℤ × ℤ) : ℤ := (P.1 - Q.1) * (P.1 - Q.1) + (P.2 - Q.2) * (P.2 - Q.2) +def dotAt (V P Q : ℤ × ℤ) : ℤ := (P.1 - V.1) * (Q.1 - V.1) + (P.2 - V.2) * (Q.2 - V.2) +def IsValid (n : ℕ) (A B C : ℤ × ℤ) : Prop := + det2 A B C ≠ 0 ∧ + (n : ℤ) ≤ dist2 A B ∧ (n : ℤ) ≤ dist2 B C ∧ (n : ℤ) ≤ dist2 C A ∧ + 0 ≤ dotAt A B C ∧ 0 ≤ dotAt B C A ∧ 0 ≤ dotAt C A B +def areas (n : ℕ) : Set ℕ := + {k | ∃ A B C : ℤ × ℤ, IsValid n A B C ∧ (det2 A B C).natAbs = k} +noncomputable def a (n : ℕ) : ℕ := sInf (areas n) +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → Real.sqrt (3 / 4) * (n : ℝ) < (a n : ℝ) +end Math0.Statements.A344710 +\end{lstlisting} +Here \decl{det2}, \decl{dist2} and \texttt{dotAt V P Q} $=(P-V)\cdot(Q-V)$ are $\dett$, the squared distance and the dot product at a vertex, and \decl{IsValid} is Definition~\ref{def:adm}. \texttt{sInf} on $\N$ is the least element of a nonempty set (and $0$ for the empty set), so the junk value cannot occur once \decl{areas}~$n$ is shown to be nonempty. The file proves, among others (statements shown, proofs omitted): +\begin{lstlisting} +theorem nonObtuse_iff (A B C : ℤ × ℤ) : + (0 ≤ dotAt A B C ∧ 0 ≤ dotAt B C A ∧ 0 ≤ dotAt C A B) ↔ + 2 * max (dist2 A B) (max (dist2 B C) (dist2 C A)) ≤ + dist2 A B + dist2 B C + dist2 C A +theorem areas_nonempty (n : ℕ) : (areas n).Nonempty +theorem isLeast_a (n : ℕ) : IsLeast (areas n) (a n) +theorem aRegion_data : (List.range 49).map (fun i => aRegion (i + 1)) = data +theorem a_data_le : ∀ i < 49, a (i + 1) ≤ data.getD i 0 +\end{lstlisting} +The lemma \decl{nonObtuse_iff} shows that the angle condition is the criterion +\[ + 2\max\{|AB|^2,|BC|^2,|CA|^2\}\le|AB|^2+|BC|^2+|CA|^2 +\] +given in the first comment of the entry. The lemma \decl{areas_nonempty} uses the right isosceles triangle with legs $n+1$, and \decl{isLeast_a} states that \decl{a}~$n$ is the least element of \decl{areas}~$n$. +The non-collinearity condition $\dett\ne0$ is not an extra restriction for $n\ge1$: three collinear points that are pairwise distinct have an angle $\pi$, and two coincident points give a side of length $0$. +The statement is the FORMULA line with $n$ ranging over the offset range $n\ge1$; $3/4$ is real division, and no hypotheses are added. + +\subsection*{Data check} +Since the minimum defining \decl{a} ranges over all triples of points of $\Z^2$, \decl{a} is not computable as written. The statement file therefore defines a helper \texttt{aRegion n}, the least $|\dett(A,B,C)|$ over $n$-admissible triples with $A=(0,0)$, $C$ in the annulus $n\le|P|^2\le\lfloor5n/4\rfloor+2$ and $B$ in the part $0\le y\le x$ of that annulus (the search described in the comments of the entry, slightly widened). The lemma \decl{aRegion_data}, proved by \texttt{decide +kernel} (evaluation in the kernel, which adds no axioms), states that \texttt{aRegion} reproduces all $49$ listed terms, and \decl{a_data_le} transfers this to $a(n)\le$ listed term for $n=1,\dots,49$. The matching lower bound $a(n)\ge$ listed term would require that the search region always contains an optimal triangle; this is not proved in Lean. An independent check is given in Remark~\ref{rem:search}. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A344710.lean}; the name of the Lean declaration is given with each step. Throughout, +\[ + Q(X,Y,Z)=2XY+2YZ+2ZX-X^2-Y^2-Z^2 , +\] +a symmetric polynomial. For a triple $(A,B,C)$ we write +\[ + X=|AB|^2,\qquad Y=|CA|^2,\qquad Z=|BC|^2,\qquad D=\dett(A,B,C). +\] + +\begin{lemma}\label{lem:id} +For all $A,B,C\in\Z^2$, +\begin{gather*} + 2(B-A)\cdot(C-A)=X+Y-Z,\qquad 2(C-B)\cdot(A-B)=X+Z-Y,\\ + 2(A-C)\cdot(B-C)=Y+Z-X,\qquad 4D^2=Q(X,Y,Z). +\end{gather*} +\end{lemma} + +\begin{proof} +Put $u=B-A$ and $v=C-A$. Then $X=|u|^2$, $Y=|v|^2$ and $Z=|u-v|^2=X+Y-2\,u\cdot v$, which is the first identity; the other two follow in the same way at the vertices $B$ and $C$. With $D=\det(u,v)$, the Lagrange identity $|u|^2|v|^2=(u\cdot v)^2+\det(u,v)^2$ gives +\[ + 4D^2=4XY-(2\,u\cdot v)^2=4XY-(X+Y-Z)^2=Q(X,Y,Z). +\] +In Lean all four identities are polynomial identities in the six coordinates and are proved by \texttt{ring} (inside \decl{det_sq_ge}). +\end{proof} + +\begin{lemma}[\decl{heron_bound_of_max}]\label{lem:max} +Let $X,Y,Z,n\in\Z$ with $0\le n\le X$, $n\le Y$, $0\le X+Y-Z$, $X\le Z$ and $Y\le Z$. Then $Q(X,Y,Z)\ge3n^2$. +\end{lemma} + +\begin{proof} +Put $s=X+Y-Z$. Then $0\le s$, $s\le X$ (because $Y\le Z$) and $s\le Y$ (because $X\le Z$). Since $0\le s\le X$ and $0\le s\le Y$, we get $s^2\le XY$. Also $0\le n\le X$ and $n\le Y$ give $n^2\le XY$. Expanding, +\[ + Q(X,Y,Z)=4XY-s^2\ge 3XY\ge 3n^2 . +\] +In Lean the two products are bounded by \texttt{mul\_le\_mul}, and \texttt{nlinarith} combines them: $Q-3n^2=(XY-s^2)+3(XY-n^2)$. (The intermediate bound $Q\ge3XY$ is not stated separately in Lean.) +\end{proof} + +\begin{lemma}[\decl{heron_bound}]\label{lem:sym} +Let $X,Y,Z,n\in\Z$ with $0\le n$, $n\le X$, $n\le Y$, $n\le Z$ and +\[ + 0\le X+Y-Z,\qquad 0\le X+Z-Y,\qquad 0\le Y+Z-X . +\] +Then $Q(X,Y,Z)\ge3n^2$. +\end{lemma} + +\begin{proof} +If $Z$ is the largest of $X,Y,Z$, apply Lemma~\ref{lem:max} to $(X,Y,Z)$. If $Y$ is the largest, apply it to $(X,Z,Y)$, using $0\le X+Z-Y$; if $X$ is the largest, apply it to $(Y,Z,X)$, using $0\le Y+Z-X$. Since $Q$ is symmetric, each case gives $Q(X,Y,Z)\ge3n^2$. In Lean the case distinction is made by nested case splits on \texttt{le\_total}. +\end{proof} + +\begin{lemma}[\decl{det_sq_ge}]\label{lem:det} +If $(A,B,C)$ is $n$-admissible, then $3n^2\le4\,\dett(A,B,C)^2$. +\end{lemma} + +\begin{proof} +By admissibility $X,Y,Z\ge n\ge0$, and by Lemma~\ref{lem:id} the three dot product conditions say $X+Y-Z\ge0$, $X+Z-Y\ge0$ and $Y+Z-X\ge0$. Lemma~\ref{lem:sym} gives $Q(X,Y,Z)\ge3n^2$, and $Q(X,Y,Z)=4D^2$ by Lemma~\ref{lem:id}. +\end{proof} + +\begin{lemma}[\decl{four_sq_ne_three_sq}]\label{lem:irr} +There are no $m,n\in\N$ with $n\ge1$ and $4m^2=3n^2$. +\end{lemma} + +\begin{proof} +Suppose $4m^2=3n^2$ with $n\ge1$. Then $(2m)^2=3n^2$, and taking square roots in $\R$ gives $\sqrt3\,n=2m$, so $\sqrt3=2m/n\in\mathbb{Q}$. This contradicts the irrationality of $\sqrt3$, which Mathlib provides as \texttt{Nat.Prime.irrational\_sqrt} for the prime $3$. +(Alternatively: $m\ne0$ since $3n^2>0$, and then the $3$-adic valuation of $4m^2$ is even while that of $3n^2$ is odd.) +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main} (\decl{result})] +Let $n\ge1$. By \decl{isLeast_a}, $a(n)$ belongs to the set of values $|\dett(A,B,C)|$, so there is an $n$-admissible triple $(A,B,C)$ with $|\dett(A,B,C)|=a(n)$. By Lemma~\ref{lem:det}, $3n^2\le4a(n)^2$, and by Lemma~\ref{lem:irr} the two sides differ. Hence +\[ + 3n^2<4a(n)^2 . +\] +In particular $a(n)>0$, since otherwise $3n^2<0$. As $n\ge0$ we have $\sqrt{3/4}\,n=\sqrt{3/4}\,\sqrt{n^2}=\sqrt{\tfrac34n^2}$, and for $a(n)>0$ the inequality $\sqrt{\tfrac34n^2}= 1, let a(n) be the largest number of squares you can choose on an n x n board so that no two chosen squares are exactly two steps apart in the same row or in the same column. Then a(n) = n^2/2 if n ≡ 0 (mod 4), a(n) = (n^2+1)/2 if n is odd, and a(n) = n^2/2 + 2 if n ≡ 2 (mod 4). (This is Yang Hong's conjecture in OEIS A348484.) + +## Assessment + +The proof needs two observations. First, split the cells by row and column parity, so the "two apart" graph becomes four ordinary grid graphs. Second, use the textbook fact that an r x s grid graph has independence number ceil(rs/2): a checkerboard gives the lower bound and a domino tiling with at most one monomino gives the upper bound. Adding up the four grids gives the conjectured values directly. The lower-bound construction was already in the entry as Mathar's comment, and the whole argument fits in well under a page. The manuscript itself calls the result elementary. Writing the pairing as an involution on the board is a convenience for the Lean proof, not a new mathematical idea. + +*Follows from:* The matching lower bound is already in the entry: R. J. Mathar's comment gives the 2x2-block checkerboard construction and a g.f. whose coefficients are the conjectured values. The upper bound follows from the standard fact that the grid graph P_r x P_s has independence number ceil(rs/2), which is proved by tiling it with dominoes plus at most one monomino. Split the cells by (i mod 2, j mod 2). The "two steps apart" graph is then a disjoint union of four grid graphs whose sides are ceil(n/2) or floor(n/2). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A348484](https://oeis.org/A348484) as [`Math0.Statements.A348484.statement`](../../lean/Math0/Statements/OEIS/A348484.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A348484.lean`](../../lean/Math0/Frontier/OEIS/A348484.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A348484 Conjectures: a(n) = n^2/2 for n == 0 (mod 4). a(n) = (n^2 + 1)/2 for n == 1 or 3 (mod 4). a(n) = n^2/2 + 2 for n == 2 (mod 4). (Entry by _Yang Hong_, Oct 20 2021; last edit #33, Dec 06 2022.) + +Referees: OEIS A348484 (Yang Hong, Oct 20 2021; latest revision #33, Dec 06 2022) still marks the formulas as "Conjectures". R. J. Mathar's Dec 2022 comment gives a 2×2-block checkerboard construction. Its g.f. -x(1+2x-2x^2+2x^3+x^4)/((1+x)(1+x^2)(x-1)^3) matches the conjectured values, but he states it only as a lower bound. Cross-reference: A048716 (the 1-D row condition, k AND 4k = 0). I found no published or online proof of the upper bound on arXiv, Math StackExchange, MathOverflow, SeqFan or general web search. The result does follow directly from the standard fact that a grid graph P_a□P_b has independence number ⌈ab/2⌉, because the "two apart" graph is a disjoint union of four such grids. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a348484, + author = {{math0}}, + title = {{A348484: no two squares two steps apart; the conjectured formula holds}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a348484}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a348484/paper.pdf b/results/oeis-a348484/paper.pdf new file mode 100644 index 0000000..635f0e6 Binary files /dev/null and b/results/oeis-a348484/paper.pdf differ diff --git a/results/oeis-a348484/paper.tex b/results/oeis-a348484/paper.tex new file mode 100644 index 0000000..271cb25 --- /dev/null +++ b/results/oeis-a348484/paper.tex @@ -0,0 +1,385 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,split_ifs}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {↔}{{$\leftrightarrow$}}1 + {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 + {≥}{{$\ge$}}1 {≠}{{$\ne$}}1 {∈}{{$\in$}}1 {×}{{$\times$}}1 {⟨}{{$\langle$}}1 + {⟩}{{$\rangle$}}1 {←}{{$\leftarrow$}}1 {²}{{$^2$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Fix}{\operatorname{Fix}} +\newcommand{\B}{B_n} + +\title[No two squares two steps apart in a row or column]{The maximum number of squares of an $n\times n$ board with no two exactly two steps apart in a row or column: Yang Hong's conjecture for OEIS A348484} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the largest number of squares of an $n\times n$ chessboard that can be chosen so that no two chosen squares lie in the same row at column distance exactly $2$, or in the same column at row distance exactly $2$ (OEIS A348484). +We prove the formulas conjectured in that entry: $a(n)=n^2/2$ for $n\equiv0\pmod 4$, $a(n)=(n^2+1)/2$ for odd $n$, and $a(n)=n^2/2+2$ for $n\equiv2\pmod4$; equivalently $2a(n)=n^2+\varepsilon(n)$ with $\varepsilon(n)=0,1,4,1$ for $n\equiv0,1,2,3\pmod 4$. +The matching lower bounds come from a $2\times2$-block checkerboard already described in the entry by R.~J. Mathar; the new part is the upper bound, obtained from an explicit involution of the board that pairs squares two steps apart and has exactly $\varepsilon(n)$ fixed points. +To our knowledge this is a new result, although an elementary one: it also follows from the independence number of grid graphs, and the OEIS entry still lists the formulas as conjectures. +The theorem is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against all ten listed terms; this statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +The OEIS sequence A348484 \cite{A348484}, contributed by Yang Hong on October~20, 2021, gives the maximum number $a(n)$ of squares of an $n\times n$ chessboard that can be chosen so that no two chosen squares are \emph{two steps apart}, that is, in the same row with columns differing by exactly $2$, or in the same column with rows differing by exactly $2$ (Definition~\ref{def:main}). +Its listed terms are $1,4,5,8,13,20,25,32,41,52$ for $n=1,\dots,10$. +The entry's FORMULA section records three conjectured formulas, one for each residue class of $n$ modulo $4$ with odd $n$ combined (Section~\ref{sec:statement}). +We prove them for every $n\ge1$ (Theorem~\ref{thm:main}). + +\subsection*{Prior work} +On December~3, 2022, R.~J. Mathar added a comment to the entry: the sequence with generating function +\[ + \frac{-x\,(1+2x-2x^2+2x^3+x^4)}{(1+x)(1+x^2)(x-1)^3} +\] +``is a lower bound for a(n) achieved by packing 2x2 squares with 1's and 2x2 squares with 0's in a checkerboard pattern into the chessboard.'' +Its coefficients are exactly the conjectured values (Mathar's configuration, with the corner block filled with $1$'s, is the set $S_0$ of Definition~\ref{def:colour}, whose size is computed in Proposition~\ref{prop:key} and Lemma~\ref{lem:A}). +So the conjectured formulas were known to be lower bounds; the comment does not address an upper bound. +The only cross-reference of the entry is A048716 \cite{A048716}, the numbers $k$ with $k \mathbin{\mathrm{AND}} 4k=0$: a single row, read as the binary number $k=\sum_{j\in\text{row}}2^j$, contains no two squares two steps apart exactly when $k$ belongs to A048716. +In revision \#33 (December~6, 2022), which the referees found to be the current one, the formulas are still labelled ``Conjectures'', the keyword \texttt{more} is set, and no proof is recorded. +The math0 referees found no proof of the upper bound on arXiv, MathOverflow, Mathematics Stack Exchange, the SeqFan mailing list, or in a general web search, and no other OEIS entry that cites A348484. +The statement is not among the OEIS statements of the formal-conjectures repository \cite{FC}. + +We therefore classify the result as \emph{new}, with a caveat: it is elementary. +The ``two steps apart'' graph on the board is a disjoint union of four grid graphs, and the result follows from the standard fact that the grid graph $P_r\mathbin{\square}P_s$ has independence number $\lceil rs/2\rceil$; see Remark~\ref{rem:grid}, where we also explain how our proof is this argument written without coordinates on the four grids. + +\section{Statement}\label{sec:statement} + +\begin{definition}\label{def:main} +Let $n\ge0$, and let $\B=\{0,\dots,n-1\}^2$ be the set of squares of the $n\times n$ board, $(i,j)$ lying in row $i$ and column $j$. Squares $c=(i,j)$ and $d=(i',j')$ are \emph{two steps apart} if +\[ + \bigl(i=i'\ \text{and}\ |j-j'|=2\bigr)\quad\text{or}\quad\bigl(j=j'\ \text{and}\ |i-i'|=2\bigr). +\] +A set $S\subseteq\B$ is \emph{admissible} if no two of its squares are two steps apart, and $a(n)$ is the largest size of an admissible set (the empty set is admissible, so $a(n)$ is well defined; $a(0)=0$). +\end{definition} + +The entry A348484 \cite{A348484}, authored by Yang Hong (October~20, 2021), has offset $1$ and name ``Maximum number of squares on an n X n chessboard such that no two are two steps apart horizontally or vertically.'' +Its FORMULA section (revision \#33, December~6, 2022) contains the following unsigned lines, verbatim: +\begin{quote} +{\small\texttt{Conjectures:}\\ +\texttt{a(n) = n\^{}2/2 for n == 0 (mod 4).}\\ +\texttt{a(n) = (n\^{}2 + 1)/2 for n == 1 or 3 (mod 4).}\\ +\texttt{a(n) = n\^{}2/2 + 2 for n == 2 (mod 4).}} +\end{quote} + +\begin{theorem}\label{thm:main} +For every $n\ge1$: $a(n)=n^2/2$ if $n\equiv0\pmod4$, $a(n)=(n^2+1)/2$ if $n\equiv1$ or $3\pmod4$, and $a(n)=n^2/2+2$ if $n\equiv2\pmod4$. Equivalently, for every $n\ge1$, +\[ + 2a(n)=n^2+\varepsilon(n),\qquad \varepsilon(n)=\begin{cases}0,& n\equiv0\pmod 4,\\ 1,& n\equiv1\text{ or }3\pmod4,\\ 4,& n\equiv2\pmod4.\end{cases} +\] +\end{theorem} + +The identity $2a(n)=n^2+\varepsilon(n)$ also holds, trivially, for $n=0$, and the proof in Section~\ref{sec:proof} does not use $n\ge1$; the theorem, like the formal statement below, concerns $n\ge1$ only, matching the offset of the entry. + +\subsection*{Lean formalization} +The statement was formalized by math0 in the file \path{lean/Math0/Statements/OEIS/A348484.lean}, and was reviewed for fidelity and frozen (SHA-256 \texttt{6dc8c7d5\ldots 1a045c66}) before any proof attempt. +Its definitions and the statement are, verbatim except that the file header (copyright notice and \texttt{import Mathlib}), docstrings, blank lines and the data-check definitions and lemmas discussed below are omitted: +\begin{lstlisting} +namespace Math0.Statements.A348484 +def TwoApart {n : ℕ} (c d : Fin n × Fin n) : Prop := + (c.1 = d.1 ∧ (c.2.val + 2 = d.2.val ∨ d.2.val + 2 = c.2.val)) ∨ + (c.2 = d.2 ∧ (c.1.val + 2 = d.1.val ∨ d.1.val + 2 = c.1.val)) +instance {n : ℕ} (c d : Fin n × Fin n) : Decidable (TwoApart c d) := + inferInstanceAs (Decidable (_ ∨ _)) +def Admissible {n : ℕ} (S : Finset (Fin n × Fin n)) : Prop := + ∀ c ∈ S, ∀ d ∈ S, ¬ TwoApart c d +instance {n : ℕ} (S : Finset (Fin n × Fin n)) : Decidable (Admissible S) := + inferInstanceAs (Decidable (∀ c ∈ S, ∀ d ∈ S, ¬ TwoApart c d)) +def a (n : ℕ) : ℕ := + ((Finset.univ : Finset (Finset (Fin n × Fin n))).filter Admissible).sup Finset.card +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + (n % 4 = 0 → a n = n ^ 2 / 2) ∧ + (n % 4 = 1 ∨ n % 4 = 3 → a n = (n ^ 2 + 1) / 2) ∧ + (n % 4 = 2 → a n = n ^ 2 / 2 + 2) +end Math0.Statements.A348484 +\end{lstlisting} +A square is an element of \texttt{Fin n × Fin n} (row, column), and \decl{TwoApart} is Definition~\ref{def:main} with $|x-y|=2$ written as $x+2=y\lor y+2=x$. +\texttt{a n} is the supremum of the cardinalities of all admissible subsets of the board, i.e.\ their maximum, since $\emptyset$ is admissible. +The statement quantifies over all $n\ge1$, matching the offset. +In it, \texttt{/} is division in $\N$, which is exact in each case ($n^2$ is even for even $n$, $n^2+1$ is even for odd $n$), so the three clauses mean the same as the entry's rational expressions; the three hypotheses cover every residue of $n$ modulo $4$. + +The reading of ``two steps apart horizontally or vertically'' is confirmed by the entry's examples: for $n=2$ all four squares are chosen, so diagonal neighbours are allowed; the $n=4$ example \texttt{1100/1100/0011/0011} contains squares two steps apart diagonally; and the $n=5$ example row \texttt{11001} contains squares three and four steps apart in a row. + +\subsection*{Data check} +The definition of \decl{a} enumerates all $2^{n^2}$ subsets of the board, so the kernel can evaluate it directly only for very small $n$. The statement file proves +\begin{lstlisting} +theorem a_eq_of_cert {n v : ℕ} (S : Finset (Fin n × Fin n)) (hS : Admissible S) + (hcard : S.card = v) (lab : Fin n × Fin n → ℕ) (hlt : ∀ c, lab c < v) + (hfib : ∀ c d, lab c = lab d → c = d ∨ TwoApart c d) : a n = v +theorem a_data : (List.range 10).map (fun i => a (i + 1)) = + [1, 4, 5, 8, 13, 20, 25, 32, 41, 52] +\end{lstlisting} +The lemma \decl{a_eq_of_cert} is a general certificate principle: an admissible set of $v$ squares gives $a(n)\ge v$, and a labelling of the squares by labels $i$, so $f(i)=i+2$ and $i\bmod4\in\{0,1\}$; hence $\lfloor i/2\rfloor$ is even. Likewise $\lfloor j/2\rfloor$ is even, so $\chi(c)=0$. +\end{proof} + +\begin{proposition}[\decl{key}]\label{prop:key} +\begin{enumerate} +\item Every admissible $T\subseteq\B$ satisfies $2|T|\le n^2+|\Fix\sigma|$. +\item $S_0$ is admissible and $2|S_0|\ge n^2+|\Fix\sigma|$. +\end{enumerate} +Consequently $a(n)=|S_0|$ and $2a(n)=n^2+|\Fix\sigma|$. +\end{proposition} + +\begin{proof} +(1) Let $T$ be admissible and $\sigma(T)=\{\sigma(c):c\in T\}$; then $|\sigma(T)|=|T|$ by Lemma~\ref{lem:sigma}(1). We claim $T\cap\sigma(T)\subseteq\Fix\sigma$. Let $c\in T\cap\sigma(T)$, say $c=\sigma(d)$ with $d\in T$. If $\sigma(d)\ne d$, then $d$ and $\sigma(d)=c$ are two squares of $T$ that are two steps apart, by Lemma~\ref{lem:sigma}(3), contradicting admissibility. Hence $\sigma(d)=d$, so $c=d$ and $\sigma(c)=c$. By inclusion--exclusion, +\[ + 2|T|=|T|+|\sigma(T)|=|T\cup\sigma(T)|+|T\cap\sigma(T)|\le n^2+|\Fix\sigma|. +\] + +(2) Two squares of $S_0$ have the same colour, so by Lemma~\ref{lem:colour}(1) they are not two steps apart; thus $S_0$ is admissible. +Let $c\in S_1$. Then $\sigma(c)\ne c$ by Lemma~\ref{lem:colour}(2), so $c$ and $\sigma(c)$ are two steps apart (Lemma~\ref{lem:sigma}(3)) and $\chi(\sigma(c))\ne\chi(c)=1$, i.e.\ $\sigma(c)\in S_0$. Moreover $\sigma(c)\notin\Fix\sigma$: otherwise $c=\sigma(\sigma(c))=\sigma(c)$ would be fixed, and fixed squares lie in $S_0$. Hence $\sigma(S_1)$ and $\Fix\sigma$ are disjoint subsets of $S_0$ (Lemma~\ref{lem:colour}(2)), and since $\sigma$ is injective, +\[ + n^2-|S_0|+|\Fix\sigma|=|S_1|+|\Fix\sigma|=|\sigma(S_1)|+|\Fix\sigma|\le|S_0|. +\] + +For the consequence: $a(n)\ge|S_0|$ because $S_0$ is admissible, and every admissible $T$ satisfies $2|T|\le n^2+|\Fix\sigma|\le2|S_0|$ by (1) and (2), so $a(n)=|S_0|$. Applying (1) to $T=S_0$ and combining with (2) gives $2|S_0|=n^2+|\Fix\sigma|$. +\end{proof} + +\begin{lemma}[\decl{card_fix}, \decl{card_A}]\label{lem:A} +Let $A_n=\{j\in\{0,\dots,n-1\}: f(j)\ge n\}$. Then $\Fix\sigma=A_n\times A_n$, and +\[ + A_n=\emptyset,\quad \{n-1\},\quad\{n-2,n-1\},\quad\{n-2\}\qquad\text{for } n\equiv0,1,2,3\pmod4 +\] +respectively. Hence $|A_n|=0,1,2,1$ and $|\Fix\sigma|=|A_n|^2=\varepsilon(n)$. +\end{lemma} + +\begin{proof} +The first claim is Lemma~\ref{lem:sigma}(2). Let $0\le j ?_, fun h13 => ?_, fun h2 => ?_⟩ + · rw [if_pos h0] at h; omega + · rw [if_neg (by omega), if_neg (by omega)] at h; omega + · rw [if_neg (by omega), if_pos h2] at h; omega +end Math0.Frontier.A348484 +#math0_settles Math0.Frontier.A348484.result Math0.Statements.A348484.statement +\end{lstlisting} +The counting in \decl{key} uses the Mathlib lemmas \decl{Finset.card_image_of_injective}, \decl{Finset.card_union_add_card_inter} (inclusion--exclusion in part (1)), \decl{Finset.card_filter_add_card_filter_not} ($|S_0|+|S_1|=n^2$), \decl{Finset.card_union_of_disjoint} and \decl{Finset.card_le_card}; \decl{card_fix} uses \decl{Finset.card_product}, and \decl{card_A} uses \decl{Finset.card_eq_zero}, \decl{Finset.card_eq_one}, \decl{Finset.card_eq_two}. Arithmetic side goals, including those with $\bmod$ and division by constants, are closed by the decision procedure \texttt{omega}. +The proof is uniform in $n$: it uses no \texttt{decide}, no \texttt{native\_decide}, no \texttt{set\_option}, and none of the data-check lemmas of the statement file. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the constant \decl{statement} or its negation, up to metadata, with no unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A348484.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A348484.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A348484.result' proves 'Math0.Statements.A348484.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. +After \texttt{lake build Math0.Statements.OEIS.A348484}, the single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A348484.lean} in the directory \path{lean} (about $15$ seconds on our machine). + +{\small +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A048716} +The OEIS Foundation Inc., \emph{Entry A048716: Numbers $k$ such that ($k$ AND $4*k$) $=0$, where AND is bitwise-and} (A.~Karttunen, March~30, 1999), The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A048716}. + +\bibitem{A348484} +The OEIS Foundation Inc., \emph{Entry A348484: Maximum number of squares on an $n\times n$ chessboard such that no two are two steps apart horizontally or vertically} (Yang Hong, October~20, 2021; revision \#33, December~6, 2022), The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A348484}. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a350499/README.md b/results/oeis-a350499/README.md new file mode 100644 index 0000000..4543dab --- /dev/null +++ b/results/oeis-a350499/README.md @@ -0,0 +1,39 @@ +# Kurkov's recursion computes the free cumulants (A350499) + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A350499 +**Date:** 2026-10-29 + +## Result + +Take indeterminate moments m_1, m_2, ... over Z, and set m_0 = 1. Let M(x) = x + m_1 x^2 + m_2 x^3 + ..., let W = M^<-1> be its compositional inverse, and let C(x) = x / W(x) = sum c_n x^n, so c_n are the free cumulants. Kurkov's array is defined by R(1,k) = m_k and, for n > 1, R(n,k) = R(n-1,k+1) - sum_{j=1}^{n-1} R(j,k) R(n-j,1). Claim: R(n,1) = c_n for every n >= 1, as an identity in Z[m_1, m_2, ...]. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A350499](https://oeis.org/A350499) as [`Math0.Statements.A350499.statement`](../../lean/Math0/Statements/OEIS/A350499.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A350499.lean`](../../lean/Math0/Frontier/OEIS/A350499.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: free cumulants in terms of the free moments are R(n,1) for n > 0 where R(n,k) = R(n-1,k+1) - Sum_{j=1..n-1} R(j,k)*R(n-j,1) for n > 1, k > 0 with R(1,k) = m_k for k > 0. - _Mikhail Kurkov_, Mar 30 2025 + +Referees: The conjecture is an immediate special case of the free-cumulant "products as arguments" formula, using the identification R(n,k) = κ_n(a^k, a, …, a): +- R. Speicher, "Multiplicative functions on the lattice of non-crossing partitions and free convolution", Math. Ann. 298 (1994) 611–628. This contains the case where one argument is a product. +- B. Krawczyk and R. Speicher, "Combinatorics of free cumulants", J. Combin. Theory Ser. A 90 (2000) 267–292, arXiv:math/9905094, Theorem 2.2. +- A. Nica and R. Speicher, Lectures on the Combinatorics of Free Probability, LMS Lecture Note Series 335, CUP 2006, Theorem 11.12. + +Applying the formula to κ_{n−1}(a^k·a, a, …, a) gives Kurkov's recursion directly. + +No explicit prior proof of Kurkov's formulation was found. OEIS A350499 (%I #63, Apr 04 2025; same in the current oeisdata) still lists it as "Conjecture … – Mikhail Kurkov, Mar 30 2025". The related entries A134264 and A133437 and the entry's own links (Copeland's blog, MathOverflow 412573, Zhou arXiv:1405.5296) do not address it. + +## Citation + +```bibtex +@misc{math0:oeis-a350499, + author = {{math0}}, + title = {{Kurkov's recursion computes the free cumulants (A350499)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a350499}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a350557/README.md b/results/oeis-a350557/README.md new file mode 100644 index 0000000..8d3e5cb --- /dev/null +++ b/results/oeis-a350557/README.md @@ -0,0 +1,48 @@ +# Signed A350557 is the matrix inverse of A350512, proved + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A350557 +**Date:** 2026-10-26 + +## Result + +Let T be the A350557 triangle: T(n,0) = (2n)!/(2^n n!) = (2n-1)!!, and for 1 ≤ k ≤ n, T(n,k) = (2n-1)!! · Σ_{i=k}^{n} C(i-1,k-1)/(2i-1)!!. Set T(n,k) = 0 for k > n. Let L be the A350512 triangle: L(n,0) = 1, and for 1 ≤ k ≤ n, L(n,k) = C(n-1,k-1)(2k(n-k)+n)/k. Set L(n,k) = 0 for k > n. Define M(n,k) = (-1)^(n-k) T(n,k). Then M and L are inverse lower-triangular matrices: for all n, j ≥ 0, Σ_{k=0}^{n} L(n,k) M(k,j) = [n=j] and Σ_{k=0}^{n} M(n,k) L(k,j) = [n=j]. This is Werner Schulte's 2022 conjecture. + +## Assessment + +The proof brings in a bidiagonal matrix A with entries 1 and 2n-1. Then A*M = B, where B is a shifted signed Pascal matrix, and this is just the recurrence for T already stated in the A350557 entry. B*L = A follows from a one-line Pascal decomposition of A350512 plus ordinary binomial inversion. Cancelling the unitriangular A gives M*L = I, and L*M = I follows because the matrices are square. That is about a page of standard triangle and binomial-inversion manipulation, and it uses formulas already in the two entries. No new idea is needed, and the referees themselves call it elementary. + +*Follows from:* The recurrence T(n,k) = C(n-1,k-1) + (2n-1)T(n-1,k), already listed as a formula in A350557, together with A350512's column g.f. (1+2kx)x^k/(1-x)^(k+1) (equivalently L(n+1,j) = (2j+1)C(n,j) + C(n,j-1)) and standard binomial (Pascal) inversion. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A350557](https://oeis.org/A350557) as [`Math0.Statements.A350557.statement`](../../lean/Math0/Statements/OEIS/A350557.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A350557.lean`](../../lean/Math0/Frontier/OEIS/A350557.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A350557 Conjecture: M(n,k) = (-1)^(n-k) * T(n,k) is matrix inverse of A350512. (Werner Schulte, entry author, Jan 2022) + +Referees: No prior resolution found. Sources checked: +(1) OEIS A350557 and A350512, in both the local mirror and the current raw.githubusercontent oeisdata. The conjecture is still marked open, there are no %E lines, and neither entry has been edited since Jan 18 2022. Across the full mirror, no other entry cross-references A350557 or A350512. I also read A286286, A249349 and A103450. +(2) google-deepmind/formal-conjectures (local checkout from Oct 2026): neither sequence is formalized. +(3) google-deepmind/alphaproof-nexus-results (Tsoukalas et al., arXiv:2605.22763): A350557 is not among the APNOutputs/OEIS files, and the paper does not mention it. +(4) Adamczewski, "OEIS Open" (arXiv:2608.11941): its appendix of resolved conjectures does not include A350557. +(5) "Further proofs of conjectures from the OEIS" (arXiv:2607.24832) and S. Fried, "Proofs of some conjectures from the OEIS" (arXiv:2410.07237): A350557 is not mentioned in either. +(6) Web searches for the A-numbers, the defining formulas, the column g.f. (1+2kx)x^k/(1-x)^(k+1), and Schulte together with the inverse: the only hit is the OEIS page, which still states the claim as a conjecture. +The result is mathematically elementary (a recurrence plus binomial inversion), but there is no published or recorded proof, so I classify it as a new result. + +## Citation + +```bibtex +@misc{math0:oeis-a350557, + author = {{math0}}, + title = {{Signed A350557 is the matrix inverse of A350512, proved}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a350557}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a350900/README.md b/results/oeis-a350900/README.md new file mode 100644 index 0000000..8bc775b --- /dev/null +++ b/results/oeis-a350900/README.md @@ -0,0 +1,52 @@ +# OEIS A350900: Schulte's gcd-ratio double sum is a Dirichlet convolution + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A350900 +**Date:** 2026-10-24 + +## Result + +Let a(f; n) = Sum_{i=1..n} Sum_{k=1..n} f(gcd(i,n)/gcd(gcd(i,k),n)). Then: (1) for every complex arithmetic function f and every n > 0, a(f; n) = ((f·φ) * A057660)(n), where f·φ is the pointwise product with Euler's totient, * is Dirichlet convolution, and A057660(m) = Sum_{k=1..m} m/gcd(m,k). (2) If f is multiplicative, so is a(f; ·). (3) For n > 0, the row sum Sum_{k=1..n} T(n,k) of the A350900 triangle T(n,k) = Sum_{i=1..n} gcd(i,n)/gcd(gcd(i,k),n) equals a(id; n). (4) For n > 0, that row sum equals (A002618 * A057660)(n), where A002618(n) = n·φ(n). + +## Assessment + +Set g = gcd(i,n). The summand depends on i only through g, and its dependence on k has period g. Apply Cesàro's identity once to group the i, use periodicity to collapse the k-sum to one period, apply Cesàro's identity again, and re-index the divisors. This gives a(f;n) = ((f*phi) * 1 * (id*phi))(n), and 1 * (id*phi) is A057660 by its own %F line. Multiplicativity then follows from standard closure properties, and the row-sum parts follow by exchanging the sums and taking f = id. The whole argument fits in under a page of standard gcd-sum manipulation, and the manuscript itself calls it routine. + +*Follows from:* Cesàro's identity Sum_{k=1..n} F(gcd(k,n)) = Sum_{d|n} F(d) phi(n/d) (Tóth's gcd-sum survey, JIS 2010), together with the formula A057660(n) = Sum_{d|n} d*phi(d), which is already in cross-referenced entry A057660. Part (4) was already stated as a formula in A373059. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A350900](https://oeis.org/A350900) as [`Math0.Statements.A350900.statement`](../../lean/Math0/Statements/OEIS/A350900.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A350900.lean`](../../lean/Math0/Frontier/OEIS/A350900.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: Let f be an arbitrary arithmetic function. Define for n > 0 the sequence a(f; n) = Sum_{i=1..n, k=1..n} f(gcd(i,n)/gcd(gcd(i,k),n)); a(f; n) equals Dirichlet convolution of f(n)*A000010(n) and A057660(n); if f is multiplicative, then a(f; n) is multiplicative; row sums of this triangle use f(n) = n (see formula section). Also %F: Conjecture: Row sums equal Dirichlet convolution of A002618 and A057660. (Werner Schulte, Jan 21 2022) + +Referees: I did not query oeis.org; OEIS entries were read from the local mirror dated 2026-10-17. +- A350900 (Werner Schulte, Jan 21 2022; last edit #13, May 24 2024): both claims are still labeled "Conjecture", and no %E line records a proof. +- A373059 (Seiichi Manyama, May 21 2024; "Row sums of A350900"): states a(n) = Sum_{d|n} phi(n/d)(n/d) sigma_2(d^2)/sigma(d^2) = (A002618*A057660)(n) without proof or conjecture label. Amiram Eldar (May 27 2024) added the multiplicative formula and the Dirichlet g.f. zeta(s)zeta(s-2)^2/zeta(s-1)^2. This is a prior unproved assertion of part 4. +- Related OEIS identities, also without proof: A350156 (Schulte, the analogous claim for f(n/gcd(i,k,n))); A371492, A371628, A373060, A373061, A372962, A372964, A372968 (Manyama, May 2024; sums of gcd(x_1,n)/gcd(x_1,...,x_k,n)). +- A057660 (= Sum_{d|n} d*phi(d)). +- Classical background: Cesaro's identity; L. Toth, "A survey of gcd-sum functions", JIS 13 (2010) 10.8.1; O. Bordelles, "A Multidimensional Cesaro Type Identity and Applications", JIS 18 (2015) 15.3.7; P. Bala, "GCD sum theorems. Two Multivariable Cesaro Type Identities" (A368743 attachment; I could not retrieve its text). +- Checked and not relevant: S. Fried, "Further proofs of conjectures from the OEIS", arXiv:2607.24832 (A350900 is not among its sequences); D. Himane, NNTDM 31 (2025) (a different Schulte conjecture, about A006472). +No prior proof or counterexample of the A350900 conjecture was found. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a350900, + author = {{math0}}, + title = {{OEIS A350900: Schulte's gcd-ratio double sum is a Dirichlet convolution}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a350900}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a350900/paper.pdf b/results/oeis-a350900/paper.pdf new file mode 100644 index 0000000..e3b1dcb Binary files /dev/null and b/results/oeis-a350900/paper.pdf differ diff --git a/results/oeis-a350900/paper.tex b/results/oeis-a350900/paper.tex new file mode 100644 index 0000000..1329c92 --- /dev/null +++ b/results/oeis-a350900/paper.tex @@ -0,0 +1,359 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,ext}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℂ}{{$\mathbb{C}$}}1 {∀}{{$\forall$}}1 {→}{{$\to$}}1 + {←}{{$\leftarrow$}}1 {∧}{{$\wedge$}}1 {≤}{{$\le$}}1 {∑}{{$\sum$}}1 {∈}{{$\in$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {∣}{{$\mid$}}1 {ζ}{{$\zeta$}}1 {•}{{$\bullet$}}1 + {·}{{$\cdot$}}1 {↑}{{$\uparrow$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{ζ}{\ensuremath{\zeta}} +\newunicodechar{•}{\ensuremath{\bullet}} +\newunicodechar{↑}{\ensuremath{\uparrow}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\C}{\mathbb{C}} +\newcommand{\idf}{\mathrm{id}} +\newcommand{\A}[1]{\mathrm{A#1}} + +\title[Schulte's gcd-ratio double sum (OEIS A350900)]{The sum of $f(\gcd(i,n)/\gcd(i,k,n))$ over $1\le i,k\le n$ is the Dirichlet convolution of $f\varphi$ and A057660 (Schulte's conjecture in OEIS A350900)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +For an arithmetic function $f$ and $n\ge1$ let $a(f;n)$ be the sum of $f(\gcd(i,n)/\gcd(i,k,n))$ over $1\le i,k\le n$. +We prove the conjecture recorded by Werner Schulte in OEIS A350900 in 2022: $a(f;n)$ is the Dirichlet convolution of $f\varphi$ with A057660, where $\A{057660}(m)=\sum_{k=1}^{m}m/\gcd(m,k)$; consequently $a(f;\cdot)$ is multiplicative whenever $f$ is, and the row sums of the triangle A350900 are the Dirichlet convolution of $\A{002618}(n)=n\varphi(n)$ and A057660. +The proof is elementary and rests on Ces\`aro's classical identity. +To our knowledge no proof has been published, and the OEIS still lists the statement as a conjecture, although the row-sum formula had been recorded without proof in A373059; we classify the result as new, but a specialist would regard the argument as routine. +The theorem is verified in Lean~4 with Mathlib against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the OEIS data. +\end{abstract} +\maketitle + +\section{Introduction} + +The OEIS entry A350900 \cite{A350900}, contributed by Werner Schulte on January~21, 2022, is the triangle +\[ + T(n,k)=\sum_{i=1}^{n}\frac{\gcd(i,n)}{\gcd(\gcd(i,k),n)}\qquad(1\le k\le n), +\] +read by rows: $1;\ 3,2;\ 5,5,3;\ 8,5,8,4;\ \dots$. In the COMMENTS section Schulte replaces the ratio $\gcd(i,n)/\gcd(\gcd(i,k),n)$ by its image under an arbitrary arithmetic function $f$ and sums over both indices, defining +\begin{equation}\label{eq:aF} + a(f;n)=\sum_{i=1}^{n}\sum_{k=1}^{n}f\!\left(\frac{\gcd(i,n)}{\gcd(\gcd(i,k),n)}\right)\qquad(n\ge1). +\end{equation} +He conjectured that $a(f;n)$ is the Dirichlet convolution of $f\varphi$ with A057660 \cite{A057660}, the sequence $\A{057660}(m)=\sum_{k=1}^{m}m/\gcd(m,k)$; that $a(f;\cdot)$ is multiplicative when $f$ is; and, in the FORMULA section, that the row sums of the triangle are the Dirichlet convolution of $\A{002618}(n)=n\varphi(n)$ \cite{A002618} and A057660. The exact text is quoted in Section~\ref{sec:statement}. We prove all of it (Theorem~\ref{thm:main}). + +\emph{Method.} With $g=\gcd(i,n)$ we have $\gcd(\gcd(i,k),n)=\gcd(g,k)$, which has period $g\mid n$ in $k$. Grouping $k$ by $\gcd(g,k)$ within one period, and $i$ by $\gcd(i,n)$, uses Ces\`aro's identity +\begin{equation}\label{eq:cesaro} + \sum_{k=1}^{n}F(\gcd(k,n))=\sum_{d\mid n}F(d)\,\varphi(n/d), +\end{equation} +see formula~(22) in Section~2 of T\'oth's survey \cite{To} and Lemma~1 of Bordell\`es \cite{Bo}. The result is $a(f;n)=\bigl((f\varphi)*\mathbf 1*(\idf\varphi)\bigr)(n)$, and the same identity gives $\A{057660}=\mathbf 1*(\idf\varphi)$. + +\subsection*{Status and prior work} +In A350900 (revision \#13, May~24, 2024, read from a local OEIS mirror of October~17, 2026, and still the current revision on oeis.org on October~25, 2026) both statements are still labeled ``Conjecture''. +The row sums form A373059 \cite{A373059} (S.~Manyama, May~21, 2024), whose FORMULA section states, without proof and without a conjecture label, $\sum_{d\mid n}\varphi(n/d)(n/d)\,\sigma_2(d^2)/\sigma(d^2)$; since $\A{057660}(d)=\sigma_2(d^2)/\sigma(d^2)$ (a formula of Labos Elemer, 2001, recorded in A057660), this is part~(4) of Theorem~\ref{thm:main}. A.~Eldar added there (May~27, 2024) the values at prime powers and the Dirichlet series $\zeta(s)\zeta(s-2)^2/\zeta(s-1)^2$, which also follows from part~(4) (Remark~\ref{rem:dgf}). +Schulte's A350156 \cite{A350156} makes the analogous statement for $f(n/\gcd(\gcd(i,k),n))$, and Manyama's sequences such as A373060 \cite{A373060} (May~2024) concern sums of $\gcd(x_1,n)/\gcd(x_1,\dots,x_r,n)$ over $1\le x_1,\dots,x_r\le n$ (here $r=3$); the OEIS gives formulas for these sequences without proof. +Multivariable generalizations of \eqref{eq:cesaro} are studied by Bordell\`es \cite{Bo} and in a note of P.~Bala attached to A368743 \cite{Bala}. Bala states $\sum_{k_1,\dots,k_r=1}^{n}f(n/\gcd(k_1,\dots,k_r,n))=\sum_{d\mid n}f(d)J_r(d)$, with $J_r$ Jordan's totient, and proves it for $r=2$, remarking that this case is Schulte's statement in A350156. The case $r=1$, which he records as the companion of \eqref{eq:cesaro}, is $\sum_{k=1}^{g}f(g/\gcd(k,g))=\sum_{e\mid g}f(e)\varphi(e)$. This is the computation in Step~3 of Lemma~\ref{lem:core}, and Bala lists A057660 as its case $f=\idf$ (Lemma~\ref{lem:A057660}). His note does not treat the ratio $\gcd(i,n)/\gcd(i,k,n)$ or A350900. +The math0 referees found no proof or counterexample in the OEIS, on arXiv (Fried's paper \cite{Fr} proving OEIS conjectures does not treat A350900), on SeqFan, the OEIS wiki, or in the gcd-sum literature \cite{To,Bo,Bala}; the statement is not in formal-conjectures \cite{FC} at the commit we use. +We therefore classify the result as new, with two caveats: part~(4) was already asserted in A373059, and parts~(1)--(2) follow from \eqref{eq:cesaro} in a few lines, so they may well be known to specialists. + +\section{Statement}\label{sec:statement} + +An \emph{arithmetic function} with values in a commutative semiring $R$ is a map $f\colon\N\to R$ with $f(0)=0$ (Mathlib's convention; the value at $0$ never enters \eqref{eq:aF}, since the argument of $f$ there is at least $1$). The \emph{Dirichlet convolution} is $(f*g)(n)=\sum_{de=n}f(d)g(e)$, so $(f*g)(0)=0$; the \emph{pointwise product} is $(fg)(n)=f(n)g(n)$; $f$ is \emph{multiplicative} if $f(1)=1$ and $f(mn)=f(m)f(n)$ whenever $\gcd(m,n)=1$. We write $\mathbf 1$ for the function with $\mathbf 1(n)=1$ for $n\ge1$, $\idf(n)=n$, and $\varphi$ for Euler's totient. We extend \eqref{eq:aF} by $a(f;0)=0$, so that $a(f;\cdot)$ is an arithmetic function. + +The COMMENTS and FORMULA sections of A350900 \cite{A350900} contain, verbatim: +\begin{quote}\footnotesize\raggedright +\texttt{Conjecture: Let f be an arbitrary arithmetic function. Define for n > 0 the sequence a(f; n) = Sum\_\char`\{i=1..n, k=1..n{\char`\}} f(gcd(i,n)/gcd(gcd(i,k),n)); a(f; n) equals Dirichlet convolution of f(n)*A000010(n) and A057660(n); if f is multiplicative, then a(f; n) is multiplicative; row sums of this triangle use f(n) = n (see formula section).} + +\texttt{Conjecture: Row sums equal Dirichlet convolution of A002618 and A057660.} +\end{quote} +Neither line carries its own attribution; both date from the entry's creation by Werner Schulte on January~21, 2022 (its author line). Here A000010 is $\varphi$. + +\begin{theorem}\label{thm:main} +Let $\A{057660}(m)=\sum_{k=1}^{m}m/\gcd(m,k)$ and $\A{002618}(m)=m\varphi(m)$. +\begin{enumerate} +\item For every arithmetic function $f\colon\N\to\C$ and every $n\ge1$, +\[ a(f;n)=\bigl((f\varphi)*\A{057660}\bigr)(n)=\sum_{d\mid n}f(d)\varphi(d)\,\A{057660}(n/d). \] +\item If $f\colon\N\to\C$ is multiplicative, then so is $a(f;\cdot)$. +\item For every $n\ge1$, $\sum_{k=1}^{n}T(n,k)=a(\idf;n)$. +\item For every $n\ge1$, $\sum_{k=1}^{n}T(n,k)=(\A{002618}*\A{057660})(n)$. +\end{enumerate} +\end{theorem} +Part~(3) is the reading of ``row sums of this triangle use f(n) = n''; it is immediate, but it is part of the conjecture's text. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A350900.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{814a4e45\ldots 9fb09b}) before any proof attempt. Its definitions and the statement read as follows (verbatim; the copyright comment, the import, the module docstring, docstrings, section headers, blank lines, the sequence \decl{a} with its index map \decl{pos}, the test function \decl{fTest} and all theorems are omitted): +\begin{lstlisting} +namespace Math0.Statements.A350900 +open ArithmeticFunction +def T (n k : ℕ) : ℕ := + ∑ i ∈ Finset.Icc 1 n, Nat.gcd i n / Nat.gcd (Nat.gcd i k) n +def phi : ArithmeticFunction ℕ := ⟨Nat.totient, Nat.totient_zero⟩ +def A057660 (m : ℕ) : ℕ := ∑ k ∈ Finset.Icc 1 m, m / Nat.gcd m k +def A057660Fn : ArithmeticFunction ℕ := ⟨A057660, by simp [A057660]⟩ +def A002618 (n : ℕ) : ℕ := n * Nat.totient n +def A002618Fn : ArithmeticFunction ℕ := ⟨A002618, by simp [A002618]⟩ +def aF {R : Type*} [AddCommMonoid R] (f : ArithmeticFunction R) (n : ℕ) : R := + ∑ i ∈ Finset.Icc 1 n, ∑ k ∈ Finset.Icc 1 n, f (Nat.gcd i n / Nat.gcd (Nat.gcd i k) n) +def aFun {R : Type*} [AddCommMonoid R] (f : ArithmeticFunction R) : ArithmeticFunction R := + ⟨aF f, by simp [aF]⟩ +def statement : Prop := + (∀ f : ArithmeticFunction ℂ, ∀ n : ℕ, 0 < n → + aF f n = (f.pmul (phi : ArithmeticFunction ℂ) * (A057660Fn : ArithmeticFunction ℂ)) n) ∧ + (∀ f : ArithmeticFunction ℂ, f.IsMultiplicative → (aFun f).IsMultiplicative) ∧ + (∀ n : ℕ, 0 < n → + ((∑ k ∈ Finset.Icc 1 n, T n k : ℕ) : ℂ) = + aF ((ArithmeticFunction.id : ArithmeticFunction ℕ) : ArithmeticFunction ℂ) n) ∧ + (∀ n : ℕ, 0 < n → ∑ k ∈ Finset.Icc 1 n, T n k = (A002618Fn * A057660Fn) n) +end Math0.Statements.A350900 +\end{lstlisting} +The four conjuncts are parts (1)--(4) of Theorem~\ref{thm:main}. +\decl{ArithmeticFunction R} is Mathlib's type of maps $\N\to R$ vanishing at $0$, with Dirichlet convolution \texttt{*}, pointwise product \decl{pmul} and \decl{IsMultiplicative} as defined above; an ascription such as \texttt{(phi : ArithmeticFunction ℂ)} applies the coercion $g\mapsto(n\mapsto(g(n):\C))$. The division in \decl{T} and \decl{aF} is exact, since $\gcd(\gcd(i,k),n)$ divides $\gcd(i,n)$, and \decl{T}, \decl{A057660} and \decl{A002618} transcribe the NAME lines of the three OEIS entries, not conjectured formulas. Reading ``arbitrary arithmetic function'' as complex-valued is the most general natural reading; the proof works over any commutative semiring (Lemma~\ref{lem:main}). +The statement file checks the encoding against the OEIS data by evaluation in the kernel (\texttt{decide +kernel}): \decl{T_data} reproduces the $12$ listed rows of the triangle, \decl{a_data} the $78$ listed terms of A350900 read by rows (offset $1$), \decl{A057660_data} the $52$ listed terms of A057660, and \decl{A002618_data} the first $20$ terms of A002618. Two further sanity checks confirm part~(4) for $n\le12$ (\decl{statement_check_rows}) and the identity of part~(1) for $n\le12$ with the non-multiplicative test function $f(m)=2m+(m\bmod 3)$ computed in $\N$ (\decl{statement_check_aF}). + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A350900.lean}; the corresponding Lean declaration is named with each step. Throughout, $M$ is a commutative additive monoid, $R$ a commutative semiring, and for $c\in\N$, $x\in M$ we write $c\cdot x$ for the $c$-fold sum. We use $\gcd(0,n)=n$. + +\begin{lemma}[\decl{sum_Icc_eq_sum_range}]\label{lem:shift} +Let $F\colon\N\to M$ and $n\ge0$ with $F(0)=F(n)$. Then $\sum_{k=1}^{n}F(k)=\sum_{k=0}^{n-1}F(k)$. +\end{lemma} + +\begin{proof} +Both sides are empty for $n=0$. For $n=m+1$, the left side is $\sum_{k=0}^{m-1}F(k+1)+F(m+1)$ and the right side is $F(0)+\sum_{k=0}^{m-1}F(k+1)$. +\end{proof} + +\begin{lemma}[Ces\`aro; \decl{sum_range_gcd}]\label{lem:cesaro} +Let $n\ge1$ and $G\colon\N\to M$. Then +\[ \sum_{i=0}^{n-1}G(\gcd(n,i))=\sum_{d\mid n}\varphi(n/d)\cdot G(d). \] +\end{lemma} + +\begin{proof} +Group the terms by the value of $\gcd(n,i)$, a divisor of $n$ (\decl{Finset.sum_fiberwise_of_maps_to}). For $d\mid n$, the $i\in[0,n)$ with $\gcd(n,i)=d$ are the $i=dj$ with $0\le j3$ the Dirichlet series of $\A{002618}=\idf\varphi$ is $\zeta(s-2)/\zeta(s-1)$ and, by Lemma~\ref{lem:A057660}, that of A057660 is $\zeta(s)\zeta(s-2)/\zeta(s-1)$. Part~(4) therefore gives the Dirichlet series $\zeta(s)\zeta(s-2)^2/\zeta(s-1)^2$ for the row sums, as recorded by Eldar in A373059 \cite{A373059}. This consequence is not formalized. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A350900.lean} in the math0 repository, \url{https://github.com/Foundation-0/math0}; it imports the frozen statement file and \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A350900.result}, of type \decl{Math0.Statements.A350900.statement}. The private lemmas are named in Section~\ref{sec:proof}, plus \decl{sum_Icc_eq_sum_range_succ}, \decl{phi_apply} and \decl{phi_mult}. The statement of \decl{main} and the end of the file are, verbatim except that the proof of \decl{main}, docstrings, blank lines and the last 14 lines of the proof of \decl{result} (marked \texttt{-{}- ...}; the three remaining parts, as in Section~\ref{sec:proof}) are omitted: +\begin{lstlisting} +private lemma main {R : Type*} [CommSemiring R] (f : ArithmeticFunction R) (n : ℕ) + (hn : 0 < n) : + aF f n = (f.pmul (phi : ArithmeticFunction R) * (A057660Fn : ArithmeticFunction R)) n +theorem result : statement := by + refine ⟨fun f n hn => main f n hn, fun f hf => ?_, fun n _ => ?_, fun n hn => ?_⟩ -- ... +end Math0.Frontier.A350900 +#math0_settles Math0.Frontier.A350900.result Math0.Statements.A350900.statement +\end{lstlisting} +The proof file uses no \texttt{decide}, \texttt{native\_decide} or \texttt{set\_option}; it involves no finite computation and does not use the data checks of the statement file. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (i) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (ii) \decl{statement} and \decl{result} depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (excluding \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and (iii) the type of \decl{result} is syntactically \decl{statement} or its negation, up to metadata, with no unfolding. It reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A350900.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A350900.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A350900.result' proves 'Math0.Statements.A350900.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, not used here. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib cache, builds all math0 results with \texttt{lake build} (re-running every audit), checks that the pinned dependencies are unmodified, and reports the number of passed statement checks. The single file is checked by \texttt{lake env lean Math0/Frontier/OEIS/A350900.lean} in \path{lean/} (under a minute on our machine, once the statement file is built). + +{\footnotesize +\begin{thebibliography}{99} + +\bibitem{Bala} +P.~Bala, \emph{GCD sum theorems. Two multivariable Ces\`aro type identities}, note attached to OEIS A368743, January 2024, \url{https://oeis.org/A368743/a368743.pdf}. + +\bibitem{Bo} +O.~Bordell\`es, \emph{A multidimensional Ces\`aro type identity and applications}, J. Integer Seq.\ \textbf{18} (2015), Article~15.3.7. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Fr} +S.~Fried, \emph{Further proofs of conjectures from the OEIS}, arXiv:2607.24832, 2026. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput.\ Sci.\ \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{To} +L.~T\'oth, \emph{A survey of gcd-sum functions}, J. Integer Seq.\ \textbf{13} (2010), Article~10.8.1. + +\bibitem{A002618} +The OEIS Foundation Inc., \url{https://oeis.org/A002618} ($n\varphi(n)$), entry by N.~J.~A. Sloane. + +\bibitem{A057660} +The OEIS Foundation Inc., \url{https://oeis.org/A057660}, entry by H.~Gould (2000). + +\bibitem{A350156} +The OEIS Foundation Inc., \url{https://oeis.org/A350156}, entry by W.~Schulte (January~19, 2022). + +\bibitem{A350900} +The OEIS Foundation Inc., \url{https://oeis.org/A350900}, entry and conjecture by W.~Schulte (January~21, 2022); revision \#13, May~24, 2024. + +\bibitem{A373059} +The OEIS Foundation Inc., \url{https://oeis.org/A373059} (row sums of A350900), entry by S.~Manyama (May~21, 2024), with formulas by A.~Eldar (May~27, 2024); revision \#19. + +\bibitem{A373060} +The OEIS Foundation Inc., \url{https://oeis.org/A373060}, entry by S.~Manyama (May~21, 2024). + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a351743/README.md b/results/oeis-a351743/README.md new file mode 100644 index 0000000..e993583 --- /dev/null +++ b/results/oeis-a351743/README.md @@ -0,0 +1,49 @@ +# A351743: from n = 139 the sequence is affine in 42-blocks, which proves Sycamore's, Sigrist's and the A355149 conjectures + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Sequences and series +**Source problem:** OEIS A351743 +**Date:** 2026-10-20 + +## Result + +Let a(1)=1 and let a(n+1) be the greatest divisor of s(n)=a(1)+...+a(n) that is prime to a(n) (OEIS A351743; s is A355149). Then: +(1) a(n)=1 for infinitely many n, and a(n)=2 for infinitely many n (Sycamore). +(2) a(2(n+21)-1) = a(2n-1) for all n >= 70 (Sigrist). +(3) There is a 21-periodic integer sequence b with a(2(n+21)) = 3645 a(2n) + b(n) for all n >= 70 (Sigrist). +(4) There is a 42-periodic integer sequence c with s(n+42) = 3645 s(n) + c(n) for all n >= 138 (A355149 conjecture). + +## Assessment + +The proof writes a and s on each 42-term block as affine functions of Y_m = (3645^m-1)/3644. The 42 coefficient rows come from the computed data, and Sigrist's conjectures already describe this shape. Each of the 42 steps of the recursion is then shown to hold for every value of the parameter, using two elementary gcd lemmas and a finite check of small divisibility and coprimality facts. Together with a direct computation of the first 139 terms, this proves all four conjectures. This is the standard way to certify an eventually periodic or affine pattern in a recursively defined sequence, and once the ansatz is set up it reduces to a finite computation. No new idea was needed, even though the conjectures had stayed open since 2022. + +*Follows from:* Sigrist's own conjectured formulas in A351743 (%F) and A355149 (%F), which already describe the block structure; the proof makes that structure an explicit affine ansatz in Y_m = (3645^m-1)/3644 and checks it by a finite computation. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A351743](https://oeis.org/A351743) as [`Math0.Statements.A351743.statement`](../../lean/Math0/Statements/OEIS/A351743.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A351743.lean`](../../lean/Math0/Frontier/OEIS/A351743.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: A351743 (a(1)=1; a(n+1) = greatest divisor of s(n) prime to a(n), s = partial sums): "Conjecture: a(n)=1 occurs infinitely many times, and therefore so does a(n)=2." (_David James Sycamore_, Jun 07 2022) and "Conjectures from _Rémy Sigrist_, Jun 20 2022: (Start) - a(2*(n+21)-1) = a(2*n-1) for n >= 70, - a(2*(n+21)) = 3645*a(2*n) + b(n) for n >= 70 (where b is 21-periodic). (End)". A355149 (partial sums of A351743): "Conjecture: a(n + 42) = 3645*a(n) + b(n) for n >= 138 (where b is 42-periodic)." + +Referees: OEIS A351743 (David James Sycamore, Jun 07 2022) states the conjecture that 1 and 2 occur infinitely often. Its formula section, from Rémy Sigrist on Jun 20 2022, adds the conjectures a(2(n+21)-1) = a(2n-1) and a(2(n+21)) = 3645 a(2n) + b(n), both for n >= 70. OEIS A355149 (De Vlieger, Sigrist and Sycamore, Jun 21 2022; last edit #11 Nov 17 2022) states the conjecture s(n+42) = 3645 s(n) + b(n) for n >= 138. Both entries still list these as open conjectures in the current oeisdata. The only other entry that cites them is A357735, which has nothing on them. I searched the full text of S. Fried's OEIS-conjecture papers (arXiv:2410.07237; J. Integer Seq. 28 (2025) 25.4.3; J. Integer Seq. 29 (2026) 26.1.8; arXiv:2607.24832) and none mentions these sequences. Searches of the web, arXiv, MathOverflow/MSE and SeqFan found no proof or counterexample. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a351743, + author = {{math0}}, + title = {{A351743: from n = 139 the sequence is affine in 42-blocks, which proves Sycamore's, Sigrist's and the A355149 conjectures}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a351743}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a351743/paper.pdf b/results/oeis-a351743/paper.pdf new file mode 100644 index 0000000..1cf5040 Binary files /dev/null and b/results/oeis-a351743/paper.pdf differ diff --git a/results/oeis-a351743/paper.tex b/results/oeis-a351743/paper.tex new file mode 100644 index 0000000..2711d38 --- /dev/null +++ b/results/oeis-a351743/paper.tex @@ -0,0 +1,399 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\scriptsize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {→}{{$\to$}}1 {∧}{{$\wedge$}}1 {≤}{{$\le$}}1 {∣}{{$\mid$}}1 {∑}{{$\sum$}}1 + {∈}{{$\in$}}1 {×}{{$\times$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\cp}{\operatorname{cp}} + +\title[The affine 42-block structure of OEIS A351743]{From $n=139$ on, OEIS A351743 is affine in blocks of length $42$: proof of the conjectures of Sycamore and Sigrist} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + +\begin{document} +\begin{abstract} +Let $a(1)=1$ and let $a(n+1)$ be the greatest divisor of $s(n)=a(1)+\dots+a(n)$ that is prime to $a(n)$; this is OEIS A351743, and $s$ is A355149. +We prove that there are explicit natural numbers $P_i,Q_i,R_i,U_i$ ($0\le i<42$) with $a(139+42m+i)=P_iY_m+Q_i$ and $s(139+42m+i)=R_iY_m+U_i$ for all $m\ge0$, where $Y_m=(3645^m-1)/3644$. +This proves the four conjectures recorded in the two entries in 2022: $1$ and $2$ occur infinitely often (D.~J. Sycamore); $a(2(n+21)-1)=a(2n-1)$ and $a(2(n+21))=3645\,a(2n)+b(n)$ with $b$ $21$-periodic, for $n\ge70$ (R.~Sigrist); and $s(n+42)=3645\,s(n)+c(n)$ with $c$ $42$-periodic, for $n\ge138$ (A355149). +To our knowledge the result is new; both entries still list these as conjectures. +The proof is verified in Lean~4 against a frozen, fidelity-reviewed statement that math0 formalized from the OEIS entries (not part of the formal-conjectures repository). +\end{abstract} +\maketitle + +\section{Introduction} + +The sequence A351743 of the OEIS \cite{A351743}, contributed by David James Sycamore on June~7, 2022, is defined by +\[ + a(1)=1,\qquad a(n+1)=\text{the greatest divisor of } s(n) \text{ that is prime to } a(n)\quad(n\ge1), +\] +where $s(n)=a(1)+\dots+a(n)$. It begins $1,1,2,1,5,2,3,5,4,3,1,28,1,57,2,\dots$, and the partial sums $s(n)$ form A355149 \cite{A355149} (M.~De Vlieger, R.~Sigrist and D.~J. Sycamore, June~21, 2022). +Equivalently, $a(n+1)$ is $s(n)$ with every prime power $p^k\,\|\,s(n)$, $p\mid a(n)$, removed; as $a(n)\mid s(n)$, $a(n+1)=1$ exactly when $s(n)$ and $a(n)$ have the same prime divisors. +Sycamore conjectured that $1$, and hence $2$, occur infinitely often in $a$; R.~Sigrist conjectured on June~20, 2022 that $a(2(n+21)-1)=a(2n-1)$ and $a(2(n+21))=3645\,a(2n)+b(n)$ with $b$ $21$-periodic, for $n\ge70$; and A355149 records the conjecture $s(n+42)=3645\,s(n)+b(n)$ with $b$ $42$-periodic, for $n\ge138$ (the exact wording is quoted in Section~\ref{sec:statement}). +We prove all four (Theorem~\ref{thm:main}). They follow from an exact description of the sequence from $n=139$ on (Theorem~\ref{thm:block}): on the $m$-th block of $42$ consecutive indices, $a$ and $s$ are affine functions of $Y_m=(3645^m-1)/3644$. +In particular, for odd $n\ge139$ the terms $a(n)$ are $42$-periodic with values in $\{1,\dots,5\}$ (eight $1$'s and five $2$'s per period), while for even $n$ they grow by a factor of about $3645=3^6\cdot5$ per block. + +\subsection*{Method} +We exhibit $42$ quadruples $(P_i,Q_i,R_i,U_i)$ (Table~\ref{tab:rows}) such that the recursion $(a(n),s(n))\mapsto(a(n+1),s(n+1))$ maps $(P_iW+Q_i,\,R_iW+U_i)$ to the pair of the next quadruple for \emph{every} $W\in\N$, and the last one to the first one at $3645W+1$. Each step follows from Lemma~\ref{lem:cp} and finitely many facts about explicit integers, checked by the Lean kernel; the first $139$ terms are computed directly. As the steps hold for all $W$, no $p$-adic information on $3645^m-1$ is needed. + +\subsection*{Status and prior work} +As of October~2026, A351743 (revision \#43, June~20, 2022) and A355149 (revision \#11, November~17, 2022) still list all four statements as conjectures. Apart from A355149, the only OEIS entry citing A351743 is A357735 \cite{A357735}, which says nothing about them. +The math0 referees found no mention of A351743, A355149, $3645$ or Sycamore in the full text of S.~Fried's papers proving OEIS conjectures \cite{Fr24,Fr25,Fr26,Fr26b}, and no proof or counterexample on the web, arXiv, MathOverflow, Mathematics Stack Exchange or the SeqFan list; the statements are not in the formal-conjectures repository \cite{FC}. +We therefore classify the result as \emph{new}; the structure we prove is the one Sigrist observed numerically, and our contribution is a (computer-assisted) proof that it persists. + +\section{Statement}\label{sec:statement} + +\subsection*{The conjectures} +The A351743 entry \cite{A351743} contains the following lines, verbatim (we omit the A-number after each line tag): +\begin{quote}\raggedright\frenchspacing +{\footnotesize\texttt{\%N a(1)=1. Thereafter, a(n+1) is the greatest divisor of s(n) which is prime to a(n), where s(n) is the n-th partial sum.}\\ +\texttt{\%C Conjecture: a(n)=1 occurs infinitely many times, and therefore so does a(n)=2.}\\ +\texttt{\%F Conjectures from \_R\'emy Sigrist\_, Jun 20 2022: (Start)}\\ +\texttt{\%F - a(2*(n+21)-1) = a(2*n-1) for n >= 70,}\\ +\texttt{\%F - a(2*(n+21)) = 3645*a(2*n) + b(n) for n >= 70 (where b is 21-periodic).}\\ +\texttt{\%F (End)}} +\end{quote} +The entry is by \texttt{\_David James Sycamore\_, Jun 07 2022}; the COMMENTS conjecture is unsigned, so we attribute it to him. The A355149 entry \cite{A355149}, ``Partial sums of A351743'', with offset $1$, contains: +\begin{quote}\raggedright\frenchspacing +{\footnotesize\texttt{\%F Conjecture: a(n + 42) = 3645*a(n) + b(n) for n >= 138 (where b is 42-periodic).}} +\end{quote} +Here \texttt{a} is our $s$; we rename this $b$ to $c$. + +\begin{theorem}\label{thm:main} +Let $a$ and $s$ be as in the introduction. Then: +\begin{enumerate} +\item[(i)] $a(n)=1$ for infinitely many $n$, and $a(n)=2$ for infinitely many $n$; +\item[(ii)] $a(2(n+21)-1)=a(2n-1)$ for every $n\ge70$; +\item[(iii)] $a(2(n+21))=3645\,a(2n)+b(n)$ for all $n\ge70$, for some $b\colon\N\to\Z$ with $b(n+21)=b(n)$; +\item[(iv)] $s(n+42)=3645\,s(n)+c(n)$ for all $n\ge138$, for some $c\colon\N\to\Z$ with $c(n+42)=c(n)$. +\end{enumerate} +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A351743.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{41c82d15\ldots 47d3}) before any proof attempt. Its definitions, verbatim (import, docstrings, comments, blank lines and theorems omitted): +\begin{lstlisting} +namespace Math0.Statements.A351743 +def strip : ℕ → ℕ → ℕ → ℕ + | 0, w, _ => w + | fuel + 1, w, v => if Nat.gcd w v = 1 then w else strip fuel (w / Nat.gcd w v) v +def coprimePart (w v : ℕ) : ℕ := strip w w v +def step (p : ℕ × ℕ) : ℕ × ℕ := + match p with + | (x, y) => + match coprimePart y x with + | z => (z, y + z) +def state (n : ℕ) : ℕ × ℕ := step^[n] (1, 1) +def a : ℕ → ℕ + | 0 => 0 + | n + 1 => (state n).1 +def s (n : ℕ) : ℕ := ∑ k ∈ Finset.Icc 1 n, a k +def sycamore : Prop := + {n : ℕ | a n = 1}.Infinite ∧ {n : ℕ | a n = 2}.Infinite +def sigristOdd : Prop := + ∀ n : ℕ, 70 ≤ n → a (2 * (n + 21) - 1) = a (2 * n - 1) +def sigristEven : Prop := + ∃ b : ℕ → ℤ, (∀ n, b (n + 21) = b n) ∧ + ∀ n : ℕ, 70 ≤ n → (a (2 * (n + 21)) : ℤ) = 3645 * (a (2 * n) : ℤ) + b n +def partialSums : Prop := + ∃ c : ℕ → ℤ, (∀ n, c (n + 42) = c n) ∧ + ∀ n : ℕ, 138 ≤ n → (s (n + 42) : ℤ) = 3645 * (s n : ℤ) + c n +def statement : Prop := + sycamore ∧ sigristOdd ∧ sigristEven ∧ partialSums +end Math0.Statements.A351743 +\end{lstlisting} +Here \decl{a} has the OEIS offset $1$; \texttt{a 0 = 0} is a junk value that no conjecture reaches (and it is neither $1$ nor $2$), and \texttt{s n} is literally $\sum_{k=1}^n a(k)$. As in the entry's PARI program, \texttt{coprimePart w v} divides $w$ by $\gcd(w,v)$ until this gcd is $1$ (the fuel $w$ suffices, as each division at least halves $w$), and \texttt{state n} is $(a(n+1),s(n+1))$. The file proves, among others (proofs omitted): +\begin{lstlisting} +theorem coprimePart_isGreatest (w v : ℕ) (hw : 0 < w) : + IsGreatest {d | d ∣ w ∧ Nat.Coprime d v} (coprimePart w v) +theorem a_one : a 1 = 1 +theorem a_succ_isGreatest (n : ℕ) (hn : 1 ≤ n) : + IsGreatest {d | d ∣ s n ∧ Nat.Coprime d (a n)} (a (n + 1)) +\end{lstlisting} +The theorems \decl{a_one} and \decl{a_succ_isGreatest} are the OEIS definition word for word and determine $a(n)$ for all $n\ge1$. Three theorems proved by \texttt{decide +kernel} compare with the OEIS data: \decl{a_data} checks all $67$ listed terms of A351743, \decl{s_data} all $50$ listed terms of A355149, and \decl{a_example} the values $a(150),\dots,a(153)=473394,1,2840365,2$ of the entry's last example. +The four conjectures are encoded literally. In \decl{sigristOdd} the truncated subtraction is harmless, since $2n-1\ge139$. The periodic sequences are integer-valued, since their signs are not specified, and the relations are stated in $\Z$. ``$b$ is $21$-periodic'' is read as $b(n+21)=b(n)$ for all $n\in\N$; this is equivalent to periodicity for $n\ge70$, since only the values at $n\ge70$ enter and they extend backwards periodically. Thus \decl{sigristEven} says exactly that $a(2(n+21))-3645\,a(2n)$ depends only on $n\bmod21$ for $n\ge70$; likewise for $c$ in \decl{partialSums}. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A351743.lean}; we give the names of the corresponding Lean declarations. +For $w\ge1$ and $v\ge0$ let $\cp(w,v)$ be the greatest divisor of $w$ prime to $v$ (\decl{coprimePart}), and for $(x,y)\in\N^2$, $y\ge1$, put $T(x,y)=(\cp(y,x),\ y+\cp(y,x))$ (\decl{step}). By definition, $(a(n+1),s(n+1))=T^n(1,1)$ for all $n\ge0$ (\decl{state}, \decl{state_snd}). + +\subsection{Two arithmetic lemmas} + +\begin{lemma}[\decl{cp_eq}]\label{lem:cp} +Let $d,e\ge1$ and $v,k\ge0$. If $\gcd(d,v)=1$ and $e\mid v^k$, then $\cp(de,v)=d$. +\end{lemma} + +\begin{proof} +The number $d$ divides $de$ and is prime to $v$. Conversely, let $x\mid de$ with $\gcd(x,v)=1$. Then $\gcd(x,v^k)=1$, hence $\gcd(x,e)=1$ because $e\mid v^k$, and so $x\mid d$ and $x\le d$. Thus $d$ is the greatest element of $\{x: x\mid de,\ \gcd(x,v)=1\}$, which is $\cp(de,v)$ by \decl{coprimePart_isGreatest}. +\end{proof} + +\begin{lemma}[\decl{cop_lin}]\label{lem:lin} +Let $L,M,g,K,k,W\ge0$. If $g\mid L$, $\gcd(M,g)=1$ and $K\mid g^k$, then $\gcd(LW+M,K)=1$. +\end{lemma} + +\begin{proof} +Since $LW+M\equiv M\pmod g$, we have $\gcd(LW+M,g)=\gcd(M,g)=1$, hence $\gcd(LW+M,g^k)=1$, and $K\mid g^k$ gives the claim. +\end{proof} + +\subsection{Rows and certified steps} +A \emph{row} is a quadruple $r=(P,Q,R,U)\in\N^4$. For $W\in\N$ put $F_r(W)=(PW+Q,\ RW+U)$ (\decl{F}). +For rows $r=(P,Q,R,U)$ and $r'=(P',Q',R',U')$ we consider two kinds of certificates. + +\begin{definition}[\decl{GoodSmall}, \decl{GoodBig}]\label{def:good} +\emph{(S)} A \emph{small step} from $r$ to $r'$ with parameters $(e,g,k)$ means: +$P=0$, $R=eP'$, $U=eQ'$, $e\mid Q^k$, $g\mid P'$, $\gcd(Q',g)=1$, $Q\mid g^k$, $e\ge1$, $Q'\ge1$, $R'=R+P'$ and $U'=U+Q'$. + +\emph{(B)} A \emph{big step} from $r$ to $r'$ with parameters $(\lambda,f,g,h,k)$ means: +$P'=0$, $R=\lambda P$, $U=\lambda Q$, $\lambda=Q'f$, $h\mid P$, $h\mid Q$, $f\mid h^k$, $g\mid P$, $\gcd(Q,g)=1$, $Q'\mid g^k$, $Q'\ge1$, $Q\ge1$, $f\ge1$, $R'=R$ and $U'=U+Q'$. +\end{definition} + +In a small step the current term $a(n)=Q$ is a constant, and $s(n)=e\cdot a(n+1)$ where $e$ is built from the primes of $Q$. In a big step $s(n)=\lambda\,a(n)$ for a constant $\lambda$, and the next term is the constant $Q'$. + +\begin{lemma}[\decl{step_small}, \decl{step_big}, \decl{step_good}]\label{lem:step} +If there is a small or a big step from $r$ to $r'$, then $T(F_r(W))=F_{r'}(W)$ for every $W\in\N$. +\end{lemma} + +\begin{proof} +\emph{Small step.} Since $P=0$, $F_r(W)=(Q,\ RW+U)$ and $RW+U=e\,(P'W+Q')$. Here $P'W+Q'\ge Q'\ge1$, $e\ge1$ and $e\mid Q^k$, and $\gcd(P'W+Q',Q)=1$ by Lemma~\ref{lem:lin} (with $L=P'$, $M=Q'$, $K=Q$). Lemma~\ref{lem:cp} gives $\cp(RW+U,Q)=P'W+Q'$. The new partial sum is $RW+U+P'W+Q'=(R+P')W+(U+Q')=R'W+U'$. + +\emph{Big step.} Put $v=PW+Q\ge Q\ge1$. Then $RW+U=\lambda v=Q'\cdot(fv)$. Since $h\mid P$ and $h\mid Q$ we have $h\mid v$, so $f\mid h^k\mid v^k$ and $fv\mid v^{k+1}$. By Lemma~\ref{lem:lin} (with $L=P$, $M=Q$, $K=Q'$), $\gcd(v,Q')=1$. Lemma~\ref{lem:cp} with $d=Q'$ and $e=fv\ge1$ gives $\cp(RW+U,v)=Q'=P'W+Q'$, since $P'=0$. The new partial sum is $RW+U+Q'=R'W+U'$. +\end{proof} + +\subsection{The table} +Let $r_i=(P_i,Q_i,R_i,U_i)$, $0\le i\le41$, be the rows of Table~\ref{tab:rows} (\decl{rows}). For the shift $\sigma(P,Q,R,U)=(3645P,\ P+Q,\ 3645R,\ R+U)$ (\decl{shift}) we have $F_{\sigma(r)}(W)=F_r(3645W+1)$ for all $W$ (\decl{F_shift}). Let $r'_i=r_{i+1}$ for $i<41$ and $r'_{41}=\sigma(r_0)=(0,\,3,\,4191876044100,\,1150350171)$ (\decl{nextRow}). + +\begin{lemma}[\decl{good_all}]\label{lem:table} +For every $i<42$ there is a step from $r_i$ to $r'_i$ with the parameters of Table~\ref{tab:rows}: a small step (S) for even $i$ and a big step (B) for odd $i$, in both cases with $k=4$. +\end{lemma} + +\begin{proof} +Each condition is an equality, divisibility, gcd value or inequality between explicit natural numbers below $5\cdot10^{12}$ (the powers $Q^4,g^4,h^4$ are at most $15^4$). In Lean, $\forall i<42,\ \mathrm{Good}(r_i,r'_i,\mathrm{cert}_i)$ is proved by \texttt{decide +kernel}: the kernel evaluates the decision procedure, using its built-in arithmetic on numerals. +\end{proof} + +\begin{table}[t] +\centering +\scriptsize +\setlength{\tabcolsep}{3.2pt} +\begin{tabular}{rrrrrrcrrrrrrrrr} +\multicolumn{6}{c}{even $i$: $P_i=0$, small step (S)} && \multicolumn{9}{c}{odd $i$: big step (B)}\\ +$i$ & $Q_i$ & $R_i$ & $U_i$ & $e$ & $g$ && $i$ & $P_i$ & $Q_i$ & $R_i$ & $U_i$ & $\lambda$ & $f$ & $g$ & $h$\\\hline +0 & 3 & 1150034580 & 315591 & 3 & 3 && 1 & 383344860 & 105197 & 1533379440 & 420788 & 4 & 1 & 2 & 1 \\ +2 & 4 & 1533379440 & 420792 & 8 & 2 && 3 & 191672430 & 52599 & 1725051870 & 473391 & 9 & 9 & 1 & 3 \\ +4 & 1 & 1725051870 & 473392 & 1 & 1 && 5 & 1725051870 & 473392 & 3450103740 & 946784 & 2 & 2 & 1 & 2 \\ +6 & 1 & 3450103740 & 946785 & 1 & 1 && 7 & 3450103740 & 946785 & 6900207480 & 1893570 & 2 & 1 & 2 & 15 \\ +8 & 2 & 6900207480 & 1893572 & 4 & 2 && 9 & 1725051870 & 473393 & 8625259350 & 2366965 & 5 & 1 & 5 & 1 \\ +10 & 5 & 8625259350 & 2366970 & 5 & 5 && 11 & 1725051870 & 473394 & 10350311220 & 2840364 & 6 & 6 & 1 & 6 \\ +12 & 1 & 10350311220 & 2840365 & 1 & 1 && 13 & 10350311220 & 2840365 & 20700622440 & 5680730 & 2 & 1 & 2 & 5 \\ +14 & 2 & 20700622440 & 5680732 & 4 & 2 && 15 & 5175155610 & 1420183 & 25875778050 & 7100915 & 5 & 1 & 5 & 1 \\ +16 & 5 & 25875778050 & 7100920 & 5 & 5 && 17 & 5175155610 & 1420184 & 31050933660 & 8521104 & 6 & 2 & 3 & 2 \\ +18 & 3 & 31050933660 & 8521107 & 3 & 3 && 19 & 10350311220 & 2840369 & 41401244880 & 11361476 & 4 & 1 & 2 & 1 \\ +20 & 4 & 41401244880 & 11361480 & 8 & 2 && 21 & 5175155610 & 1420185 & 46576400490 & 12781665 & 9 & 9 & 1 & 15 \\ +22 & 1 & 46576400490 & 12781666 & 1 & 1 && 23 & 46576400490 & 12781666 & 93152800980 & 25563332 & 2 & 2 & 1 & 2 \\ +24 & 1 & 93152800980 & 25563333 & 1 & 1 && 25 & 93152800980 & 25563333 & 186305601960 & 51126666 & 2 & 1 & 2 & 3 \\ +26 & 2 & 186305601960 & 51126668 & 4 & 2 && 27 & 46576400490 & 12781667 & 232882002450 & 63908335 & 5 & 1 & 5 & 1 \\ +28 & 5 & 232882002450 & 63908340 & 5 & 5 && 29 & 46576400490 & 12781668 & 279458402940 & 76690008 & 6 & 6 & 1 & 6 \\ +30 & 1 & 279458402940 & 76690009 & 1 & 1 && 31 & 279458402940 & 76690009 & 558916805880 & 153380018 & 2 & 1 & 2 & 1 \\ +32 & 2 & 558916805880 & 153380020 & 4 & 2 && 33 & 139729201470 & 38345005 & 698646007350 & 191725025 & 5 & 5 & 1 & 5 \\ +34 & 1 & 698646007350 & 191725026 & 1 & 1 && 35 & 698646007350 & 191725026 & 1397292014700 & 383450052 & 2 & 2 & 1 & 6 \\ +36 & 1 & 1397292014700 & 383450053 & 1 & 1 && 37 & 1397292014700 & 383450053 & 2794584029400 & 766900106 & 2 & 1 & 2 & 1 \\ +38 & 2 & 2794584029400 & 766900108 & 4 & 2 && 39 & 698646007350 & 191725027 & 3493230036750 & 958625135 & 5 & 1 & 5 & 1 \\ +40 & 5 & 3493230036750 & 958625140 & 5 & 5 && 41 & 698646007350 & 191725028 & 4191876044100 & 1150350168 & 6 & 2 & 3 & 2 \\ +\end{tabular} +\caption{The rows $r_i=(P_i,Q_i,R_i,U_i)$, $0\le i\le 41$, with $a(139+42m+i)=P_iY_m+Q_i$ and $s(139+42m+i)=R_iY_m+U_i$ (left: even $i$, where $P_i=0$; right: odd $i$), and the parameters of the step $r_i\to r'_i$ (Definition~\ref{def:good}; $k=4$ throughout). These are the lists \texttt{rows} and \texttt{certs} of the Lean file.}\label{tab:rows} +\end{table} + +\subsection{The block theorem} + +\begin{theorem}[\decl{key}, \decl{a_form}, \decl{s_form}]\label{thm:block} +Let $Y_0=0$ and $Y_{m+1}=3645\,Y_m+1$, so that $Y_m=(3645^m-1)/3644$. For all $m\ge0$ and $0\le i\le41$, +\[ + a(139+42m+i)=P_iY_m+Q_i,\qquad s(139+42m+i)=R_iY_m+U_i . +\] +\end{theorem} + +\begin{proof} +Equivalently, $T^{138+42m+i}(1,1)=F_{r_i}(Y_m)$. We prove this by induction on $m$, and for each $m$ by induction on $i$. + +\emph{Base.} $T^{138}(1,1)=(a(139),s(139))=(3,315591)=F_{r_0}(0)$ (\decl{state_base}: \texttt{decide +kernel} evaluates the $138$ steps in the kernel; the partial sums involved are at most $s(139)=315591$). + +\emph{From $i$ to $i+1$, for $i<41$.} By the induction hypothesis and Lemmas~\ref{lem:step} and~\ref{lem:table} with $W=Y_m$, +$T^{138+42m+i+1}(1,1)=T(F_{r_i}(Y_m))=F_{r_{i+1}}(Y_m)$. + +\emph{From block $m$ to block $m+1$.} Since $138+42(m+1)=(138+42m+41)+1$, Lemmas~\ref{lem:step} and~\ref{lem:table} and \decl{F_shift} give $T^{138+42(m+1)}(1,1)=T(F_{r_{41}}(Y_m))=F_{\sigma(r_0)}(Y_m)=F_{r_0}(3645Y_m+1)=F_{r_0}(Y_{m+1})$. +\end{proof} + +By Table~\ref{tab:rows}, $P_i=0$ for every even $i$ (\decl{row_even_const}, checked by \texttt{decide}), with +\[ + (Q_0,Q_2,\dots,Q_{40})=(3,4,1,1,2,5,1,2,5,3,4,1,1,2,5,1,2,1,1,2,5), +\] +whereas $P_i>0$ and $s(n)=\lambda_i\,a(n)$ with $\lambda_i\in\{2,4,5,6,9\}$ for odd $i$. +For instance $a(150)=Q_{11}=473394$, $a(151)=Q_{12}=1$, $a(152)=Q_{13}=2840365$ and $a(153)=Q_{14}=2$ are the values in the last example of the OEIS entry. + +\subsection{Proof of Theorem~\ref{thm:main}} + +\emph{(i)} (\decl{one_inf}, \decl{two_inf}.) As $r_4=(0,1,\dots)$ and $r_8=(0,2,\dots)$, Theorem~\ref{thm:block} gives $a(143+42m)=1$ and $a(147+42m)=2$ for all $m\ge0$. + +\emph{(ii)} (\decl{odd_part}.) Let $n\ge70$. Then $2n-1\ge139$, so $2n-1=139+42m+i$ with $m\ge0$ and $0\le i<42$, and $i$ is even because $2n-1$ and $139$ are odd. Then $2(n+21)-1=139+42(m+1)+i$, and by Theorem~\ref{thm:block} and $P_i=0$ both $a(2n-1)$ and $a(2(n+21)-1)$ equal $Q_i$. + +\emph{(iii)} (\decl{even_part}.) For $j<42$ put $\delta_a(j)=P_j+Q_j-3645\,Q_j\in\Z$ (\decl{dA}), and let $b(n)=\delta_a((2(n\bmod 21)+29)\bmod 42)$, so that $b(n+21)=b(n)$. Let $n\ge70$ and write $2n=139+42m+i$ with $m\ge0$ and $0\le i<42$. Since $-139\equiv29\pmod{42}$ and $2n\equiv2(n\bmod21)\pmod{42}$, we have $i=(2(n\bmod21)+29)\bmod42$, so $b(n)=\delta_a(i)$. As $2(n+21)=139+42(m+1)+i$ and $Y_{m+1}=3645Y_m+1$, +\[ + a(2(n+21))=P_i(3645Y_m+1)+Q_i=3645\,(P_iY_m+Q_i)+P_i+Q_i-3645\,Q_i=3645\,a(2n)+b(n). +\] + +\emph{(iv)} (\decl{sums_part}.) For $j<42$ put $\delta_s(j)=R_j+U_j-3645\,U_j\in\Z$ (\decl{dS}), and define $c(n)=\delta_s((n+29)\bmod42)$; then $c(n+42)=c(n)$. +For $n\ge139$ write $n=139+42m+i$ with $0\le i<42$; then $i=(n+29)\bmod42$, and exactly as in (iii), $s(n+42)=R_i(3645Y_m+1)+U_i=3645\,s(n)+c(n)$. +For $n=138$: Theorem~\ref{thm:block} with $m=0$ gives $s(139)=U_0=315591$, $a(139)=Q_0=3$ and $s(180)=U_{41}=1150350168$, so $s(138)=315588$; and $c(138)=\delta_s(41)=31908$, and indeed $3645\cdot315588+31908=1150350168=s(180)$. \qed + +\begin{remark}[sharpness; not formalized]\label{rem:sharp} +The thresholds are optimal: $a(179)=5\ne101=a(137)$, $a(180)-3645\,a(138)\ne a(222)-3645\,a(180)$ and $s(179)-3645\,s(137)\ne s(221)-3645\,s(179)$, so (ii)--(iv) fail with thresholds $69,69,137$ (checked in Python, also by the math0 referees). +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A351743.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}, which imports the frozen statement file (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A351743.result} of type \decl{Math0.Statements.A351743.statement}. The auxiliary declarations of this file named in Section~\ref{sec:proof}, including Theorem~\ref{thm:block}, are \texttt{private}. Kernel computations (\decl{good_all}, \decl{state_base} by \texttt{decide +kernel}; small \texttt{decide}/\texttt{rfl} steps) add no axioms; there is no \texttt{native\_decide}, \texttt{sorry}, \texttt{axiom} or \texttt{set\_option}. + +\subsection*{Audit} +The file ends with the command +\begin{lstlisting} +#math0_settles Math0.Frontier.A351743.result Math0.Statements.A351743.statement +\end{lstlisting} +which is used for statements that math0 formalizes itself. It fails unless (1) \decl{statement} is a universe-monomorphic definition of type \texttt{Prop}; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (rejecting \decl{sorryAx}, \decl{Lean.ofReduceBool} from \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation (up to metadata, no unfolding). It reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A351743.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A351743.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A351743.result' proves 'Math0.Statements.A351743.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; formal-conjectures \cite{FC} is pinned at commit \texttt{c77fdd4} but not used here. +To reproduce, run \path{scripts/verify.sh} from the repository root; it fetches the Mathlib cache, rebuilds all math0 results with \texttt{lake build} (re-running every audit) and checks that the pinned dependencies are unmodified. This file alone: \texttt{lake env lean Math0/Frontier/OEIS/A351743.lean} in \path{lean} (under two minutes on our machine). + +{\footnotesize +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Fr24} +S.~Fried, \emph{Proofs of some conjectures from the OEIS}, arXiv:2410.07237, 2024. + +\bibitem{Fr25} +S.~Fried, \emph{Proofs of several conjectures from the OEIS}, J. Integer Seq.\ \textbf{28} (2025), Article~25.4.3. + +\bibitem{Fr26} +S.~Fried, \emph{Proofs of ten conjectures from the OEIS}, J. Integer Seq.\ \textbf{29} (2026), Article~26.1.8. + +\bibitem{Fr26b} +S.~Fried, \emph{Further proofs of conjectures from the OEIS}, arXiv:2607.24832, 2026. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A351743} +The OEIS Foundation Inc., \url{https://oeis.org/A351743}, entry by D.~J. Sycamore (June~7, 2022), with conjectures by D.~J. Sycamore and R.~Sigrist; revision \#43, June~20, 2022. + +\bibitem{A355149} +The OEIS Foundation Inc., \url{https://oeis.org/A355149}, entry by M.~De Vlieger, R.~Sigrist and D.~J. Sycamore (June~21, 2022); revision \#11, Nov.~17, 2022. + +\bibitem{A357735} +The OEIS Foundation Inc., \url{https://oeis.org/A357735}, entry by D.~J. Sycamore (Oct.~11, 2022). + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a354571/README.md b/results/oeis-a354571/README.md new file mode 100644 index 0000000..b6b97dc --- /dev/null +++ b/results/oeis-a354571/README.md @@ -0,0 +1,50 @@ +# Even and odd legs with odd prime factors ≡ 3 (mod 4): a(n)/n → π (A354571, A354570) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A354571 +**Date:** 2026-10-20 + +## Result + +A354571 lists the even legs k of primitive Pythagorean triangles in increasing order, each repeated once per triangle. A leg is included when every odd prime factor of k is ≡ 3 (mod 4) and k has at least one odd prime factor. A354570 lists the odd legs k in the same way, for k whose prime factors are all ≡ 3 (mod 4). Selle's conjecture says that a(n)/n → π for A354571 and A354570(n)/n → π. The formal `statement` is the conjunction of these two limits, with each sequence read as the n-th term of the list where k appears #legTriangles(k) times. + +## Assessment + +The proof counts primitive triangles with a given leg using coprime factorizations, which gives the classical multiplicity 2^(omega-1). That reduces both counting functions to the summatory function of a multiplicative weight g, whose Dirichlet series is (1-2^-s)zeta(s)/L(s,chi_4). The Wiener–Ikehara (or Delange) theorem, together with L(1,chi_4) = pi/4 and the fact that L(s,chi_4) has no zeros on Re s = 1, then gives S(N) ~ 2N/pi. A short dyadic summation and the inversion from the counting function to the n-th term finish the proof. Each step is a textbook application of standard analytic number theory, and the manuscript itself calls it routine. Most of the work went into formalization: Wiener–Ikehara had to be proved from scratch in Lean. That effort does not make the mathematics substantial. + +*Follows from:* Classical count of primitive Pythagorean triangles with a given leg (2^(omega-1) coprime factorizations), combined with the Wiener–Ikehara / Delange Tauberian theorem applied to sum_{m odd, all p|m ≡ 3 mod 4} 2^omega(m) m^-s = (1-2^-s) zeta(s)/L(s,chi_4), with L(1,chi_4) = pi/4 and L(s,chi_4) ≠ 0 on Re s = 1. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A354571](https://oeis.org/A354571) as [`Math0.Statements.A354571.statement`](../../lean/Math0/Statements/OEIS/A354571.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A354571.lean`](../../lean/Math0/Frontier/OEIS/A354571.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: lim_{n->oo} a(n)/n = Pi. Also, lim_{n->oo} A354570(n)/n = Pi." (Lothar Selle, Jun 04 2022; same text in A354570) + +Referees: No prior resolution found. +- OEIS A354571 and A354570 (Lothar Selle, Jun 2022; last edited Aug 2022) still state lim a(n)/n = Pi as a conjecture. Checked in the local mirror and in upstream raw.githubusercontent.com/oeis/oeisdata. +- Selle, "Kleines Handbuch Pythagoreische Zahlentripel" (BoD 2022), ch. 2.3.10, is cited only for the equality of the two limits; I could not access the book. +- Related unproved Selle conjectures appear in A120427, A120890 and A354569. +- Web searches (arXiv, MathOverflow, Math.SE, SeqFan) found no proof or counterexample. +- The underlying asymptotic is a standard consequence of Wiener–Ikehara/Delange applied to (1-2^-s)zeta(s)/L(s,chi4), using L(1,chi4) = pi/4. D. N. Lehmer (Amer. J. Math. 22, 1900) treats similar Pythagorean counting asymptotics, but not this restricted case. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a354571, + author = {{math0}}, + title = {{Even and odd legs with odd prime factors ≡ 3 (mod 4): a(n)/n → π (A354571, A354570)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a354571}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a354571/paper.pdf b/results/oeis-a354571/paper.pdf new file mode 100644 index 0000000..9e7cc3c Binary files /dev/null and b/results/oeis-a354571/paper.pdf differ diff --git a/results/oeis-a354571/paper.tex b/results/oeis-a354571/paper.tex new file mode 100644 index 0000000..c772634 --- /dev/null +++ b/results/oeis-a354571/paper.tex @@ -0,0 +1,380 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{textcomp} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℝ}{{$\mathbb{R}$}}1 {∀}{{$\forall$}}1 + {∃}{{$\exists$}}1 {→}{{$\to$}}1 {∧}{{$\wedge$}}1 {∑}{{$\sum$}}1 {∈}{{$\in$}}1 + {↔}{{$\leftrightarrow$}}1 {×}{{$\times$}}1 {≡}{{$\equiv$}}1 {²}{{$^2$}}1 {π}{{$\pi$}}1 + {∞}{{$\infty$}}1 {≥}{{$\ge$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {…}{{$\dots$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} +\emergencystretch=3em + +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\code}[1]{\texttt{#1}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\R}{\mathbb{R}} +\newcommand{\C}{\mathbb{C}} +\newcommand{\cO}{\mathcal{O}} +\newcommand{\one}{\mathbf{1}} +\newcommand{\re}{\operatorname{Re}} +\newcommand{\wE}{w_{\mathrm E}} +\newcommand{\wO}{w_{\mathrm O}} +\newcommand{\FE}{F_{\mathrm E}} +\newcommand{\FO}{F_{\mathrm O}} + +\title[Selle's conjecture for OEIS A354570 and A354571]{Legs of primitive Pythagorean triangles whose odd prime factors are all congruent to $3$ modulo $4$: a proof that $a(n)/n\to\pi$ for OEIS A354570 and A354571} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} +\hypersetup{pdftitle={Legs of primitive Pythagorean triangles whose odd prime factors are all congruent to 3 modulo 4: a proof that a(n)/n -> pi for OEIS A354570 and A354571},pdfauthor={math0}} + +\begin{document} +\begin{abstract} +OEIS A354571 lists, in increasing order and with multiplicity, the even legs $k$ of primitive Pythagorean triangles such that every odd prime factor of $k$ is $\equiv3\pmod 4$ and $k$ has an odd prime factor; A354570 does the same for the odd legs all of whose prime factors are $\equiv3\pmod4$. We prove Lothar Selle's 2022 conjecture that both sequences satisfy $a(n)/n\to\pi$, by counting triangles through coprime factorizations and applying a Wiener--Ikehara theorem to $(1-2^{-s})\zeta(s)/L(s,\chi_4)$. We found no earlier proof and classify the result as new, with the caveat that it is a routine consequence of classical analytic number theory. The theorem, including the Tauberian theorem, is verified in Lean~4 with Mathlib against a statement formalized by math0 from the OEIS entries, reviewed for fidelity and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +A \emph{primitive Pythagorean triangle} (PPT) is a triple $(x,y,z)$ of positive integers with $x^2+y^2=z^2$ and $\gcd(x,y,z)=1$; $x$ and $y$ are its legs, and exactly one of them is even. For $k\ge1$ let $t(k)$ be the number of pairs $(b,c)$ such that $(b,k,c)$ is a PPT, i.e.\ the number of PPTs having $k$ as a leg, each triangle counted once. The OEIS entries A354571 \cite{A354571} and A354570 \cite{A354570}, contributed by Lothar Selle in June 2022, are the ``Ordered even leg lengths k (listed with multiplicity) of primitive Pythagorean triangles such that all odd prime factors of k are congruent to 3 (mod 4) and at least one prime factor is odd'', namely $12,12,24,24,28,28,36,\dots$ ($12$ occurs twice because of $(5,12,13)$ and $(12,35,37)$), and the ``Ordered odd leg lengths k (listed with multiplicity) of primitive Pythagorean triangles such that all prime factors of k are congruent to 3 (mod 4)'', namely $3,7,9,11,19,21,21,\dots$; both have offset $1$. The COMMENTS section of A354571 (entry by Selle, June~4, 2022) reads +\begin{quote} +``Conjecture: lim\_\{n-\textgreater{}oo\} a(n)/n = Pi. Also, lim\_\{n-\textgreater{}oo\} A354570(n)/n = Pi.'' +\end{quote} +and A354570 contains the same comment with the two sequences exchanged. We prove both limits. + +\subsection*{Prior work and status} +Asymptotic counts of PPTs go back to D.~N.~Lehmer \cite{Leh} (e.g.\ the number with hypotenuse at most $N$ is $\sim N/(2\pi)$). Lehmer also studied sums over the integers all of whose prime factors lie in prescribed residue classes (for instance all $\equiv1\pmod4$), a question treated in general by Landau \cite{La}; the referees found no treatment in \cite{Leh} of the restricted counts considered here. The entries cite Selle's book \cite{Se} for the sequences (chapters~2.3.3 and~2.2.1) and refer to its chapter~2.3.10 ``for identity of'' the limit for the other sequence; the referees read this as concerning the \emph{equality} of the two limits, not their value. Neither we nor the referees could consult the book. In the current revisions (A354571 \#41, A354570 \#54, both August 2022) the limits are still stated as conjectures, and the math0 referees found no proof or counterexample in the related OEIS entries or by web searches (arXiv, MathOverflow, Math StackExchange, SeqFan). Related conjectures of Selle in A120427, A120890 and A354569 are not addressed here. We therefore classify Theorem~\ref{thm:main} as a \emph{new result}, with a caveat on its depth: the key asymptotic $\sum_{n\le N}g(n)\sim(2/\pi)N$ (Proposition~\ref{prop:S}) is a standard consequence of the Wiener--Ikehara theorem \cite{Ik,Wi} or of Delange's generalization \cite{De} (see \cite{Ko}), and an expert would regard the result as routine. + +\section{Statement}\label{sec:statement} + +\begin{theorem}\label{thm:main} +Let $a(n)$ and $a'(n)$ $(n\ge1)$ be the $n$-th terms of A354571 and A354570. Then $a(n)/n\to\pi$ and $a'(n)/n\to\pi$ as $n\to\infty$. +\end{theorem} + +Theorem~\ref{thm:main} is the content of the Lean \decl{statement} below. On the way (Section~\ref{sec:proof}) we show that for each of the two sequences the number of terms $\le N$, counted with multiplicity, is $N/\pi+o(N)$; for a nondecreasing sequence this is equivalent to the limit. + +\subsection*{The Lean statement} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A354571.lean}, reviewed for fidelity against the OEIS entries, and frozen (SHA-256 \texttt{8b6ac74e\ldots 8ca9ee}) before any proof attempt. Its definitions and the statement are, verbatim (namespace \decl{Math0.Statements.A354571}; blank lines, two \code{Decidable} instances, the lemmas, and all docstrings but the last are omitted): +\begin{lstlisting} +def IsPPT (x y z : ℕ) : Prop := + 0 < x ∧ 0 < y ∧ x ^ 2 + y ^ 2 = z ^ 2 ∧ Nat.gcd (Nat.gcd x y) z = 1 +def cand (k d : ℕ) : ℕ × ℕ := ((k ^ 2 / d - d) / 2, (k ^ 2 / d - d) / 2 + d) +def legTriangles (k : ℕ) : Finset (ℕ × ℕ) := + ((Finset.range k).filter (fun d => IsPPT (cand k d).1 k (cand k d).2)).image (cand k) +def CondE (k : ℕ) : Prop := + (∀ p ∈ k.primeFactors, Odd p → p % 4 = 3) ∧ ∃ p ∈ k.primeFactors, Odd p +def CondO (k : ℕ) : Prop := ∀ p ∈ k.primeFactors, p % 4 = 3 +def wE (k : ℕ) : ℕ := if Even k ∧ CondE k then (legTriangles k).card else 0 +def wO (k : ℕ) : ℕ := if Odd k ∧ CondO k then (legTriangles k).card else 0 +def numLE (w : ℕ → ℕ) (k : ℕ) : ℕ := ∑ j ∈ Finset.range (k + 1), w j +noncomputable def nthTerm (w : ℕ → ℕ) (n : ℕ) : ℕ := sInf {k | n ≤ numLE w k} +noncomputable def a (n : ℕ) : ℕ := nthTerm wE n +noncomputable def a354570 (n : ℕ) : ℕ := nthTerm wO n +/-- Conjecture (Selle, A354571 and A354570): `a(n)/n → π` and `A354570(n)/n → π` as `n → ∞`. -/ +def statement : Prop := + Filter.Tendsto (fun n : ℕ => (a n : ℝ) / n) Filter.atTop (nhds Real.pi) ∧ + Filter.Tendsto (fun n : ℕ => (a354570 n : ℝ) / n) Filter.atTop (nhds Real.pi) +\end{lstlisting} + +\subsection*{How the Lean definitions encode the entries} +\code{IsPPT b k c} says that $(b,k,c)$ is a PPT with hypotenuse $c$. The set \code{legTriangles k} is computed by a search over $d=c-by$, and $x=y$ with $\gcd(x,y)=1$ forces $N=1$. +\end{proof} + +\begin{lemma}[\code{card\_leg\_odd}, \code{leg\_two\_mul\_odd}, \code{card\_leg\_even}]\label{lem:legs} +\leavevmode +\begin{enumerate} +\item[(a)] If $k$ is odd, $t(k)=U_<(k^2)$, via $(b,c)\mapsto(c-b,c+b)$ with inverse $(d,e)\mapsto\bigl(\tfrac{e-d}2,\tfrac{e+d}2\bigr)$. +\item[(b)] If $n$ is odd, $t(2n)=0$. +\item[(c)] If $n\ge2$ is even, $t(2n)=U_<(n^2)$, via $(b,c)\mapsto\bigl(\tfrac{c-b}2,\tfrac{c+b}2\bigr)$ with inverse $(d,e)\mapsto{}$\linebreak[2]${(e-d,e+d)}$. +\end{enumerate} +\end{lemma} + +\begin{proof} +(a) If $(b,k,c)$ is a PPT, then $(c-b)(c+b)=k^2$ with $c-b1$, and multiplying Dirichlet series turns Lemma~\ref{lem:linear} into $L(g,s)L(s,\chi_4)=L(s,\chi_0)$ there (\code{LSeries\_identity}). We use Mathlib's Dirichlet $L$-functions: $L(s,\chi_4)$ is entire and does not vanish on $\re s\ge1$ (\decl{LFunction_ne_zero_of_one_le_re}), and $(s-1)L(s,\chi_0)$ extends to an entire function $T(s)$ with $T(1)=\prod_{p\mid4}(1-p^{-1})=\tfrac12$. + +\begin{lemma}[\texttt{LFunction\_\(\chi\)C\_one}]\label{lem:L1} +$L(1,\chi_4)=\pi/4$. +\end{lemma} + +\begin{proof} +For real $\sigma>1$, $L(\sigma,\chi_4)=\sum_{m\ge0}u_\sigma(m)$ with $u_\sigma(m)=(4m+1)^{-\sigma}-(4m+3)^{-\sigma}\ge0$. For $1\le\sigma\le2$, with $\alpha=4m+1$ and $\beta=\alpha+2$, Bernoulli's inequality $(\alpha/\beta)^\sigma\ge1-2\sigma/\beta$ gives $u_\sigma(m)=\alpha^{-\sigma}(1-(\alpha/\beta)^\sigma)\le4/(\alpha\beta)\le4/(m+1)^2$. By dominated convergence, $\sum_mu_\sigma(m)\to\sum_m\bigl(\frac1{4m+1}-\frac1{4m+3}\bigr)=\frac\pi4$ (Leibniz) as $\sigma\to1^+$, and $L(s,\chi_4)$ is continuous at $1$. +\end{proof} + +\begin{lemma}[\code{HH\_one}, \code{continuousOn\_G}, \code{G\_eq}]\label{lem:G} +Let $H(s)=T(s)/(s\,L(s,\chi_4))$, $G(s)=(H(s)-H(1))/(s-1)$ for $s\ne1$ and $G(1)=H'(1)$. Then $H(1)=2/\pi$, $G$ is continuous on $\{\re s\ge1\}$, and $L(g,s)/s-(2/\pi)/(s-1)=G(s)$ for $\re s>1$. +\end{lemma} + +\begin{proof} +$H$ is holomorphic on the open set $\{s\ne0,\ L(s,\chi_4)\ne0\}\supseteq\{\re s\ge1\}$, hence so is $G$ (Mathlib's \code{dslope H 1}) by the removable singularity theorem. $H(1)=\frac12/\frac\pi4$ by Lemma~\ref{lem:L1}. For $\re s>1$, $L(g,s)=T(s)/((s-1)L(s,\chi_4))$, i.e.\ $L(g,s)/s=H(s)/(s-1)$. +\end{proof} + +\subsection{A Tauberian theorem} + +\begin{theorem}[\code{Tauber.tauberian}]\label{thm:tauber} +Let $a_n\ge0$ $(n\ge1)$ and $M\ge0$ with $A(N)=\sum_{n=1}^Na_n\le MN$ for all $N$. Let $c\ge0$ and let $G:\C\to\C$ be continuous on $\{\re s\ge1\}$ with $\sum_na_nn^{-s}/s-c/(s-1)=G(s)$ for $\re s>1$. Then $A(N)/N\to c$. +\end{theorem} + +\begin{proof} +Put $A(x)=\sum_{1\le n\le x}a_n$ for $x\in\R$ and $B(v)=e^{-v}A(e^v)$; $A$ is nondecreasing and $0\le B\le M$. + +\emph{Step 1} (\code{laplace\_repr}). Partial summation gives $\sum_na_nn^{-s}=s\int_1^\infty A(x)x^{-s-1}dx$ (\decl{LSeries_eq_mul_integral_of_nonneg}); substituting $x=e^v$ yields +\begin{equation}\label{eq:laplace} + G(s)=\int_0^\infty(B(v)-c)\,e^{-(s-1)v}\,dv\qquad(\re s>1). +\end{equation} + +\emph{Step 2} (Fej\'er kernel). For $L>0$ let $\varphi_L(t)=\max(0,1-|t|/L)$ and $\Phi_L(u)=\int_\R\varphi_L(t)e^{iut}dt$, which equals $L$ at $u=0$ and $2(1-\cos Lu)/(Lu^2)$ otherwise (\code{fourier\_phi}). Hence $0\le\Phi_L(u)\le\min(L,4/(Lu^2))$, and $\Phi_L(u)\ge L/2$ for $|u|\le1/L$ (as $1-\cos x\ge x^2/2-5x^4/96$ for $|x|\le1$). So $\Phi_L$ is integrable, $K_L:=\int_\R\Phi_L\ge1$, and for $\delta>0$, $\tau_L(\delta):=\int_{|u|>\delta}\Phi_L\le\int_\R\frac{8\,du}{L(\delta^2+u^2)}=\frac{8\pi}{L\delta}$. (In fact $K_L=2\pi$; only $K_L\ge1$ is used.) + +\emph{Step 3} (\code{fubini\_identity}, \code{limit\_identity}). Fix $L>0$, $y\in\R$. For $\varepsilon>0$, inserting \eqref{eq:laplace} at $s=1+\varepsilon+it$ and applying Fubini (the integrand is bounded by $(M+|c|)\varphi_L(t)e^{-\varepsilon v}$) gives $\int_\R\varphi_L(t)G(1+\varepsilon+it)e^{iyt}dt=\int_0^\infty(B(v)-c)e^{-\varepsilon v}\Phi_L(y-v)\,dv$. As $\varepsilon\to0^+$, dominated convergence applies on both sides ($G$ is bounded on the compact set $[1,2]\times[-L,L]$; the right integrand is bounded by $(M+|c|)\Phi_L(y-v)$), so +\begin{equation}\label{eq:J} + \int_0^\infty(B(v)-c)\,\Phi_L(y-v)\,dv=\int_\R\varphi_L(t)\,G(1+it)\,e^{iyt}\,dt . +\end{equation} + +\emph{Step 4} (\code{J\_tendsto}, \code{tail\_tendsto}, \code{I\_tendsto}). As $t\mapsto\varphi_L(t)G(1+it)$ is continuous with compact support, \eqref{eq:J} tends to $0$ as $y\to\infty$ by the Riemann--Lebesgue lemma. For $y>0$, $\int_{-\infty}^0\Phi_L(y-v)\,dv\le\tau_L(y/2)\le16\pi/(Ly)$, so $\int_0^\infty\Phi_L(y-v)\,dv\to K_L$. Therefore +\begin{equation}\label{eq:I} + I_L(y):=\int_0^\infty B(v)\,\Phi_L(y-v)\,dv\ \longrightarrow\ cK_L\qquad(y\to\infty). +\end{equation} + +\emph{Step 5} (\code{upper\_bound}, \code{lower\_bound}). Let $\delta>0$. As $A$ is nondecreasing, $B(v)\ge e^{-2\delta}B(y)$ on $[y,y+2\delta]$ and $B(v)\le e^{2\delta}B(y)$ on $[y-2\delta,y]$. Restricting $I_L(y+\delta)$ to $|y+\delta-v|\le\delta$, and splitting $I_L(y-\delta)$ according to $|y-\delta-v|\le\delta$ or $>\delta$ (with $B\le M$ on the second part), we get, for $y>0$, +\begin{equation}\label{eq:sandwich} + e^{-2\delta}B(y)\bigl(K_L-\tau_L(\delta)\bigr)\le I_L(y+\delta),\qquad I_L(y-\delta)\le e^{2\delta}B(y)K_L+M\tau_L(\delta). +\end{equation} + +\emph{Step 6} (\code{tendsto\_Bf}). Put $\eta=8\pi/(L\delta)$, so $\tau_L(\delta)\le\eta\le\eta K_L$. Given $c'>c$, choose $\delta$ with $e^{2\delta}cc'$. Hence $B(y)\to c$, and $B(\log N)=A(N)/N$. +\end{proof} + +\subsection{Conclusion} + +\begin{proposition}[\code{SN\_tendsto}]\label{prop:S} +$S(N)/N\to2/\pi$. +\end{proposition} + +\begin{proof} +Apply Theorem~\ref{thm:tauber} with $a_n=g(n)$, $M=2$ (Lemma~\ref{lem:linear}), $c=2/\pi$ and $G$ from Lemma~\ref{lem:G}. +\end{proof} + +By Lemma~\ref{lem:reduce}, $\FO(N)/N=(S(N)-1)/(2N)\to1/\pi$ (\code{wO\_tendsto}). + +\begin{lemma}[\code{Fin1.dyadic}]\label{lem:dyadic} +If $R:\N\to\R$, $R(0)=0$, $0\le R(m)\le Cm$ and $R(m)/m\to\lambda$, then $J^{-1}\sum_{i\ge0}R(\lfloor J/2^i\rfloor)\to2\lambda$. +\end{lemma} + +\begin{proof} +For fixed $q\ge1$, $\lfloor J/q\rfloor/J\to1/q$ and $\lfloor J/q\rfloor\to\infty$, so $R(\lfloor J/q\rfloor)/J\to\lambda/q$. The $i$-th term is at most $C2^{-i}$, and dominated convergence for series gives the limit $\sum_i\lambda2^{-i}$. +\end{proof} + +Here $0\le R(M)\le2M$ and $R(M)/M\to2/\pi$, so Lemmas~\ref{lem:reduce} and~\ref{lem:dyadic} give $E(J)/J\to4/\pi$ and $\FE(N)/N=E(\lfloor N/4\rfloor)/N\to1/\pi$ (\code{EE\_tendsto}, \code{wE\_tendsto}). This is the counting form of Theorem~\ref{thm:main} mentioned in Section~\ref{sec:statement}. (Numerically, not as part of the proof, the referees found $\FO(10^7)/10^7\approx0.31832$ and $\FE(10^7)/10^7\approx0.31834$.) + +\begin{lemma}[\code{nth\_limit}]\label{lem:inverse} +Let $w:\N\to\N$, $F(N)=\sum_{j\le N}w(j)$ unbounded with $F(N)/N\to\lambda>0$, and $\nu(n)=\min\{k:F(k)\ge n\}$. Then $\nu(n)/n\to1/\lambda$. +\end{lemma} + +\begin{proof} +If $n>F(K)$ then $\nu(n)>K$, so $\nu(n)\to\infty$. For $\nu(n)\ge1$, $F(\nu(n)-1)= 0, a(n) = 1 when n = 2*4^k - 1 or n = 2*4^k - 2. In other words, s(n) is an integer for those n. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A355076](https://oeis.org/A355076) as [`Math0.Statements.A355076.statement`](../../lean/Math0/Statements/OEIS/A355076.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A355076.lean`](../../lean/Math0/Frontier/OEIS/A355076.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: a(n) = 1 for n of the form 2*4^k - 1 or 2*4^k - 2 for some k >= 0. (entry by _Rémy Sigrist_, Jun 18 2022) + +Referees: - **Row-sum theorem (the key ingredient):** K. Siddharth Choudary and A. Satyanarayana Reddy, "Calkin-Wilf tree", arXiv:2003.13466 [math.CO], Mar 2020, accepted in Resonance. Theorem 1.1, Part 11: the sum of all elements in level n (root at level 1) is 3·2^{n−2} − 1/2, proved by induction. +- **Earlier statement of the same fact:** OEIS A052940, comment by Carl Najafi (Jul 10 2011): 3·2^n − 1 is the numerator of the sum of terms at the n-th level of the Calkin-Wilf tree. +- **Classical facts:** OEIS A002487 records a(2^k) = 1 and a(2^k − 1) = k (Adamchuk comment), and that a(n)/a(n+1) enumerates the rationals (Stern; N. Calkin and H. Wilf, "Recounting the rationals", Amer. Math. Monthly 107 (2000)). +- **The conjecture itself:** OEIS A355076 (R. Sigrist, Jun 18 2022, rev. #11) is still listed as a conjecture with no %E edits. A355075 is the matching numerators entry. I found no explicit resolution anywhere; the result follows immediately from the Choudary–Reddy row sum plus the classical facts above. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a355076, + author = {{math0}}, + title = {{Integer partial sums of the Calkin-Wilf ratios fusc(k)/fusc(k+1) at n = 2*4^k-1 and 2*4^k-2 (A355076)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a355076}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a355076/paper.pdf b/results/oeis-a355076/paper.pdf new file mode 100644 index 0000000..e8478be Binary files /dev/null and b/results/oeis-a355076/paper.pdf differ diff --git a/results/oeis-a355076/paper.tex b/results/oeis-a355076/paper.tex new file mode 100644 index 0000000..5ceafc9 --- /dev/null +++ b/results/oeis-a355076/paper.tex @@ -0,0 +1,367 @@ +% math0 manuscript template. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, keepspaces=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {→}{{$\to$}}1 {∨}{{$\vee$}}1 {≤}{{$\le$}}1 {∈}{{$\in$}}1 {∑}{{$\sum$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\Z}{\mathbb{Z}} +\DeclareMathOperator{\fusc}{fusc} +\DeclareMathOperator{\den}{den} + +\title[Integer partial sums of $\fusc(k)/\fusc(k+1)$ (OEIS A355076)]{The partial sums of $\fusc(k)/\fusc(k+1)$ are integers at $n=2\cdot4^k-1$ and $n=2\cdot4^k-2$: a proof of the conjecture in OEIS A355076} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Let $\fusc$ be Stern's diatomic sequence and $s(n)=\sum_{k=0}^{n}\fusc(k)/\fusc(k+1)$. We prove the conjecture in OEIS A355076 (R.~Sigrist, 2022) that the denominator of $s(n)$ is $1$, that is, $s(n)$ is an integer, for every $n$ of the form $2\cdot4^k-1$ or $2\cdot4^k-2$ with $k\ge0$; in fact $s(2\cdot4^k-1)=3\cdot4^k-k-2$ and $s(2\cdot4^k-2)=3\cdot4^k-3k-3$. +The proof rests on the closed form $\sum_{k<2^M}\fusc(k)/\fusc(k+1)=(3\cdot2^M-3-M)/2$, which follows by summation from the known value $(3\cdot2^m-1)/2$ of the sum of the $m$-th row of the Calkin--Wilf tree (proved by K.~S.~Choudary and A.~S.~Reddy in 2020; its numerator $3\cdot2^m-1$ was recorded by C.~Najafi in OEIS A052940 in 2011). +The conjecture is thus an immediate consequence of published results, and we classify this note as the first formal proof of a known result. +The proof is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the listed terms of A355076 and A002487, and which was reviewed for fidelity and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +Stern's diatomic sequence \cite{Stern}, called $\fusc$ by Dijkstra \cite{Dijkstra}, is OEIS A002487 \cite{A002487}: $\fusc(0)=0$, $\fusc(1)=1$, $\fusc(2n)=\fusc(n)$ and $\fusc(2n+1)=\fusc(n)+\fusc(n+1)$, with first terms $0,1,1,2,1,3,2,3,1,4,\dots$. The ratios $x_j=\fusc(j)/\fusc(j+1)$, $j\ge1$, list every positive rational number exactly once, in reduced form \cite{Stern,CW}. Calkin and Wilf \cite{CW} showed that they are the breadth-first enumeration of the Calkin--Wilf tree, the complete binary tree with root $1/1$ in which a vertex $a/b$ has left child $a/(a+b)$ and right child $(a+b)/b$; level $m$ of the tree (root at level $0$) consists of the $x_j$ with $2^m\le j<2^{m+1}$. We also set $x_0=0$. For background see the survey \cite{Northshield}. + +The OEIS entry A355076 \cite{A355076}, created by R\'emy Sigrist on June~18, 2022, lists the denominators of the partial sums $s(n)=\sum_{k=0}^{n}x_k$; A355075 \cite{A355075} lists the numerators. For instance $s(4)=0+1+\frac12+2+\frac13=\frac{23}6$. The entry conjectures that $s(n)$ is an integer for $n=2\cdot4^k-1$ and $n=2\cdot4^k-2$; the listed terms $a(0),\dots,a(52)$ equal $1$ exactly at $n=0,1,6,7,30,31$. The current revision of the entry (\#11, June~19, 2022; checked in October 2026) still states the conjecture without a proof or a reference. + +\subsection*{Prior work} +The conjecture follows at once from three known facts. (1) \emph{Row sums}: the sum of level $m$ of the Calkin--Wilf tree is $(3\cdot2^m-1)/2$. Its numerator was recorded by Carl Najafi in a comment of July~10, 2011 on OEIS A052940 \cite{A052940}, a sequence with $a(0)=1$ and $a(n)=3\cdot2^n-1$ for $n\ge1$, which the comment describes as the ``numerator of the sum of terms at the $n$-th level of the Calkin--Wilf tree''; the comment states neither the denominator nor a proof. The formula was proved by Choudary and Reddy \cite[Theorem~1.1, Part~11]{CR} in the form $3\cdot2^{n-2}-\frac12$, with the root at level~$1$; their inductive proof pairs each vertex $a/b$ of a level with its reciprocal $b/a$, which lies on the same level \cite[Theorem~1.1, Part~4]{CR}, and our proof uses the same pairing. (2) \emph{Row symmetry}: each row $\fusc(2^m),\dots,\fusc(2^{m+1})$ is a palindrome, as recorded in A002487 in a comment by Alexander Adamchuk (October~10, 2006) \cite{A002487}; this is equivalent to the reciprocal symmetry of the levels. (3) \emph{Extreme values}: $\fusc(2^M)=1$ and $\fusc(2^M-1)=M$, also in Adamchuk's comment. + +Summing (1) over the levels $0,\dots,M-1$ gives $s(2^M-1)=(3\cdot2^M-3-M)/2$, an integer for odd $M$, and subtracting the last term $x_{2^M-1}=M$ given by (3) handles $n=2^M-2$. We found no place where this deduction is recorded or connected with A355076, and the referees of this note found no resolution of the conjecture in the OEIS or elsewhere. Thus the conjecture had not been settled in print, but all of its mathematical content is in the results above, and we classify the result as known. + +The conjecture is not among the OEIS statements of the formal-conjectures repository \cite{FC} (checked at commit \texttt{c77fdd4}), and the referees found no formalization of the Calkin--Wilf row sums in Lean or Mathlib. What this note adds is a self-contained proof that follows a kernel-checked Lean proof of a frozen formal statement of the conjecture (Section~\ref{sec:lean}); to our knowledge this is the first formal proof of the statement. + +\section{Statement}\label{sec:statement} + +\begin{definition}\label{def:main} +Let $\fusc\colon\N\to\N$ be determined by $\fusc(0)=0$, $\fusc(1)=1$ and, for all $n\in\N$, $\fusc(2n)=\fusc(n)$ and $\fusc(2n+1)=\fusc(n)+\fusc(n+1)$. For $j\in\N$ let $x_j=\fusc(j)/\fusc(j+1)\in\Q$, let $s(n)=\sum_{k=0}^{n}x_k$, and let $a(n)=\den s(n)\ge1$ be the denominator of $s(n)$ in lowest terms. +\end{definition} + +These equations determine $\fusc$: at every argument $\ge2$ they express $\fusc$ through values at smaller arguments, and for $n=0$ they read $\fusc(0)=\fusc(0)$ and $\fusc(1)=\fusc(0)+\fusc(1)$, which are consistent with the initial values. By Lemma~\ref{lem:pos} below, $\fusc(j+1)>0$, so $x_j$ is well defined. The entry's name and its conjecture, stated in the FORMULA section by the entry's author R\'emy Sigrist (June~18, 2022) \cite{A355076}, read verbatim: +\begin{quote}\raggedright +\textsc{Name}: \texttt{a(n) is the denominator of Sum\_\char123k = 0..n\char125\ fusc(k)/fusc(k+1) (where fusc is Stern's diatomic series A002487).}\\[2pt] +\textsc{Formula}: \texttt{Conjecture: a(n) = 1 for n of the form 2*4\char94k - 1 or 2*4\char94k - 2 for some k >= 0.} +\end{quote} + +\begin{theorem}\label{thm:main} +For every $n\in\N$ such that $n=2\cdot4^k-1$ or $n=2\cdot4^k-2$ for some $k\in\N$, we have $a(n)=1$; that is, $s(n)$ is an integer. +\end{theorem} + +The proof gives the values explicitly: $s(2\cdot4^k-1)=3\cdot4^k-k-2$ and $s(2\cdot4^k-2)=3\cdot4^k-3k-3$ for every $k\ge0$ (Proposition~\ref{prop:values}). For example, $s(6)=0+1+\frac12+2+\frac13+\frac32+\frac23=6$ and $s(7)=s(6)+x_7=6+3=9$, the case $k=1$. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A355076.lean}, reviewed for fidelity, and frozen before any proof attempt (SHA-256 hash beginning \texttt{e42856b0}). Its definitions and the statement are reproduced verbatim below, except that the copyright comment, the line \texttt{import Mathlib}, docstrings, blank lines, the lemmas \decl{fuscAux_eq_fuscAux}, \decl{fuscAux_succ} and \decl{fuscAux_eq_fusc}, and the proofs of \decl{fusc_even} and \decl{fusc_odd} are omitted. +\begin{lstlisting} +namespace Math0.Statements.A355076 +def fuscAux : ℕ → ℕ → ℕ + | 0, _ => 0 + | fuel + 1, n => + if n ≤ 1 then n + else if n % 2 = 0 then fuscAux fuel (n / 2) + else fuscAux fuel (n / 2) + fuscAux fuel (n / 2 + 1) +def fusc (n : ℕ) : ℕ := fuscAux (n + 1) n +theorem fusc_zero : fusc 0 = 0 := by decide +kernel +theorem fusc_one : fusc 1 = 1 := by decide +kernel +theorem fusc_even (n : ℕ) : fusc (2 * n) = fusc n +theorem fusc_odd (n : ℕ) : fusc (2 * n + 1) = fusc n + fusc (n + 1) +theorem fusc_data : (List.range 92).map fusc = + [0, 1, 1, 2, 1, 3, 2, 3, 1, 4, 3, 5, 2, 5, 3, 4, 1, 5, 4, 7, 3, 8, 5, 7, 2, 7, 5, 8, 3, 7, + 4, 5, 1, 6, 5, 9, 4, 11, 7, 10, 3, 11, 8, 13, 5, 12, 7, 9, 2, 9, 7, 12, 5, 13, 8, 11, 3, + 10, 7, 11, 4, 9, 5, 6, 1, 7, 6, 11, 5, 14, 9, 13, 4, 15, 11, 18, 7, 17, 10, 13, 3, 14, 11, + 19, 8, 21, 13, 18, 5, 17, 12, 19] := by + decide +kernel +def a (n : ℕ) : ℕ := + (∑ k ∈ Finset.range (n + 1), ((fusc k : ℚ) / (fusc (k + 1) : ℚ))).den +theorem a_data : (List.range 53).map a = + [1, 1, 2, 2, 6, 3, 1, 1, 4, 12, 60, 60, 12, 4, 2, 2, 10, 20, 140, 420, 840, 840, 840, 840, + 840, 840, 420, 140, 20, 5, 1, 1, 6, 30, 90, 180, 1980, 13860, 13860, 13860, 13860, 27720, + 360360, 72072, 72072, 72072, 8008, 8008, 72072, 72072, 72072, 360360, 27720] := by + decide +kernel +def statement : Prop := + ∀ n : ℕ, (∃ k : ℕ, n = 2 * 4 ^ k - 1 ∨ n = 2 * 4 ^ k - 2) → a n = 1 +end Math0.Statements.A355076 +\end{lstlisting} + +Mathlib has no $\fusc$, so \texttt{fusc} is computed by the defining recursion with a fuel parameter, which makes it structurally recursive and lets the kernel evaluate it. With fuel $n+1$ the fuel never runs out, since the recursive calls are on $\lfloor n/2\rfloor0$, Lean's convention $x/0=0$ plays no role. The statement is the conjecture read literally. Since $2\cdot4^k\ge2$, the truncated subtractions in $\N$ are exact; $k=0$ gives $n=1$ and $n=0$. Like the OEIS formula, it asserts only one direction (see Remark~\ref{rem:converse}). + +The theorems \decl{fusc_data} and \decl{a_data}, proved by \texttt{decide +kernel}, check that the definitions reproduce the $92$ terms of A002487 and all $53$ terms of A355076 listed in the OEIS; the fidelity reviewer also compared both lists with the OEIS data. + +\section{Proof}\label{sec:proof} + +We follow the Lean proof; each lemma is labelled with the name of the corresponding private Lean lemma. The proof uses only the four defining equations of $\fusc$ (in Lean, \decl{fusc_zero}, \decl{fusc_one}, \decl{fusc_even}, \decl{fusc_odd}, together with the base cases $\fusc(0)=0$, $\fusc(1)=1$ and $\fusc(2)=1$, which the kernel also evaluates directly; see Section~\ref{sec:lean}). + +\begin{lemma}[\decl{fusc_pos}]\label{lem:pos} +$\fusc(n)>0$ for every $n\ge1$. +\end{lemma} + +\begin{proof} +Strong induction on $n$. If $n=2k$, then $1\le k0$. If $n=1$, then $\fusc(n)=1$. If $n=2k+1$ with $k\ge1$, then $\fusc(n)=\fusc(k)+\fusc(k+1)\ge\fusc(k)>0$, since $1\le k0$, and $g_i=x_{2(N+i)}$ by Lemma~\ref{lem:children}. + +\begin{lemma}[\decl{row_left_sum}]\label{lem:left} +$\sum_{i=0}^{N-1}g_i=N/2=2^m/2$. +\end{lemma} + +\begin{proof} +As $D_i>0$, $g_i+f_i=1$ for each $i$, so $\sum_{i= 0, a(n) = 1 if and only if n > 0 and n = 2^m - 2 for some m >= 0 (equivalently, n+2 = 2^{t+2} for some t >= 0). + +## Assessment + +By symmetry, the claim reduces to two parity facts: T(n,0) is even for n>=1, and T(n,1) is odd exactly when n+2 is a power of 2. Both come out of a standard technique. Reduce the row recurrence already stated in A355320 modulo 2. There 1+X^4=(1+X^2)^2 and X^3+X^5=X^3(1+X^2), so the recurrence has an explicit binomial closed form (a sum over compositions of n). The coefficient parities then follow from Lucas's theorem (equivalently, Kummer's carry criterion) by a short carry argument. The whole argument is about a page of elementary mod-2 polynomial algebra and binomial parity, the kind of thing a competent combinatorialist would find quickly. The conjecture most likely stayed open because the entry is obscure, not because it is hard. + +*Follows from:* The row-polynomial recurrence R_{n+1}=(1+X^4)R_n+(X^3+X^5)R_{n-1} given in A355320 (%F and PARI code), reduced mod 2 using 1+X^4=(1+X^2)^2, combined with Lucas's theorem for p=2. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A355339](https://oeis.org/A355339) as [`Math0.Statements.A355339.statement`](../../lean/Math0/Statements/OEIS/A355339.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A355339.lean`](../../lean/Math0/Frontier/OEIS/A355339.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F Conjecture: a(n) = 1 iff n > 0 and n belongs to A000918. (Rémy Sigrist, Jun 29 2022) + +Referees: - OEIS A355339 (Rémy Sigrist, Jun 29 2022): the conjecture is in %F and is still unresolved at revision #10, with no %E extensions (checked in the local mirror and upstream oeisdata on GitHub). +- OEIS A355320 (the triangle; its %F gives T(n,0)=A096609(n) and T(n,1)=A096610(n), but nothing on parity). +- OEIS A096608–A096612 (Kimberling 2004, Catalan knight paths in the right half-plane), A096587, A361292, A000918, A002605: no parity results. +- J.-L. Baril, N. Hassler, S. Kirgizov, J. L. Ramírez, "Grand zigzag knight's paths", arXiv:2402.04851 (ECA 2024): its only parity remark (Remark 3.2) concerns zigzag path counts being even when n ≡ k (mod 2), not this conjecture. +- J.-L. Baril, J. L. Ramírez, "Knight's paths towards Catalan numbers", arXiv:2206.12087: nothing on parity. +- Web searches of arXiv, MathOverflow/MSE, SeqFan and general sources found no prior proof or counterexample. +- No formalization in google-deepmind formal-conjectures. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a355339, + author = {{math0}}, + title = {{A355339: the central even run of the knight-move triangle has length 1 iff n = 2^m - 2}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a355339}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a355339/paper.pdf b/results/oeis-a355339/paper.pdf new file mode 100644 index 0000000..859a15d Binary files /dev/null and b/results/oeis-a355339/paper.pdf differ diff --git a/results/oeis-a355339/paper.tex b/results/oeis-a355339/paper.tex new file mode 100644 index 0000000..eee6b08 --- /dev/null +++ b/results/oeis-a355339/paper.tex @@ -0,0 +1,386 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,rw,constructor,by_contra,push_cast,exact_mod_cast}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\scriptsize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {∈}{{$\in$}}1 + {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {¬}{{$\neg$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 + {↔}{{$\leftrightarrow$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {≠}{{$\ne$}}1 {≡}{{$\equiv$}}1 {∣}{{$\mid$}}1 + {×}{{$\times$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\F}{\mathbb{F}_2} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\tsub}{\mathbin{\dot{-}}} +\newcommand{\co}[2]{[X^{#1}]\,#2} + +\title[Sigrist's conjecture for OEIS A355339]{The central block of even entries in row $n$ of the knight-move triangle has length one exactly when $n=2^m-2$ with $m\ge2$: a proof of Sigrist's conjecture for OEIS A355339} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 19, 2026} + + +\begin{document} +\begin{abstract} +Let $T(n,k)$ be the number of lattice paths from $(0,0)$ to $(n,k)$ with steps $(1,\pm2)$ and $(2,\pm1)$, so that row $n$ of the triangle A355320 of the OEIS is $T(n,-2n),\dots,T(n,2n)$, and let $a(n)$ (A355339) be the length of the maximal block of consecutive even entries of row $n$ containing $T(n,0)$, with $a(0)=0$. +We prove the conjecture recorded by R\'emy Sigrist in A355339 in 2022 that $a(n)=1$ if and only if $n=2^m-2$ for some $m\ge2$. +To do so we show that $T(n,0)$ is even for every $n\ge1$ and that $T(n,1)$ is odd exactly when $n+2$ is a power of $2$ at least $4$, using a closed form for the row polynomials over $\F$ and Lucas's theorem; to our knowledge this is the first proof of the conjecture. +The theorem is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before the proof attempt, whose definitions are checked by the kernel against the $91$ listed terms of A355320 and the $77$ listed terms of A355339. +\end{abstract} +\maketitle + +\section{Introduction} + +A \emph{Catalan knight} in the sense of Kimberling \cite{A096587} moves from $(x,y)$ to one of $(x+1,y\pm2)$, $(x+2,y\pm1)$. For $n\ge0$ and $k\in\Z$ let $T(n,k)$ be the number of Catalan knight paths from $(0,0)$ to $(n,k)$; in the terminology of Baril, Hassler, Kirgizov and Ram\'irez \cite{BHKR} these are the grand knight's paths of size $n$ and altitude $k$. Since $|y|\le 2x$ along such a path, $T(n,k)=0$ for $|k|>2n$, and decomposing a path according to its last step gives $T(0,0)=1$ and +\begin{equation}\label{eq:rec} + T(n,k)=T(n-1,k-2)+T(n-1,k+2)+T(n-2,k-1)+T(n-2,k+1)\qquad(n\ge1), +\end{equation} +where $T(-1,\cdot)=0$. Kimberling's triangle A096608 \cite{A096608} (2004) lists the right halves $0\le k\le 2n$ of the rows, and Sigrist's triangle A355320 \cite{A355320} (June~28, 2022) lists the full rows $-2n\le k\le 2n$, defined directly by \eqref{eq:rec}. + +On June~29, 2022, Sigrist contributed A355339 \cite{A355339}: $a(n)$ is the number of central even terms in row $n$ of A355320, that is, the size of the maximal block of consecutive even entries $T(n,k)$ containing $k=0$ (and $0$ if $T(n,0)$ is odd), with $a(0)=0$. For example, row $4$ is $1,0,0,3,4,3,1,\mathbf{6},\mathbf{8},\mathbf{6},1,3,4,3,0,0,1$, so $a(4)=3$. +The entry conjectures that $a(n)=1$ if and only if $n>0$ and $n$ belongs to A000918 \cite{A000918}, the sequence $2^m-2$; that is, the central block is a single entry exactly for $n=2,6,14,30,62,\dots$. We prove this (Theorem~\ref{thm:main}). The proof rests on the following parity facts. + +\begin{theorem}\label{thm:parity} +For all $n\ge0$ and $k\in\Z$: \textup{(1)} $T(n,-k)=T(n,k)$; \textup{(2)} if $n\ge1$, then $T(n,0)$ is even; \textup{(3)} $T(n,1)$ is odd if and only if $n+2=2^{j}$ for some $j\ge2$. +\end{theorem} + +Part (1) is recorded in A355320, and (2), (3) concern $T(n,0)=\text{A096609}(n)$ and $T(n,1)=\text{A096610}(n)$. By (2) and (1), for $n\ge1$ the central block is a single entry if and only if $T(n,1)$ is odd. +To prove (2) and (3), we reduce row $n$ modulo $2$ to a polynomial $F_n\in\F[X]$ and show that $F_n=\sum_{p+q=n}\binom pq X^{3q}(1+X^2)^{2p-q}$. For $T(n,0)$ only central binomial coefficients occur, and these are even; for $T(n,1)$, Lucas's theorem \cite{Lucas} shows that only the term $p=q$ can be odd. + +\subsection*{Status and prior work} +The statement is still marked ``Conjecture'' in A355339, whose current revision (\#10, June~29, 2022) dates from the day the entry was created (we read it in math0's copy of the OEIS database; the referees also checked the upstream OEIS data repository). The related entries A355320, A096587, A096608--A096612, A361292, A000918 and A002605 contain no parity results for $T(n,0)$ or $T(n,1)$. +Baril and Ram\'irez \cite{BR} showed that zigzag knight's paths (whose steps alternate up and down) of a given length ending on the $x$-axis are counted by Catalan numbers, and Baril, Hassler, Kirgizov and Ram\'irez \cite{BHKR} studied grand zigzag knight's paths. The only parity statement in \cite{BHKR} that we are aware of, Remark~3.2, says that the number of grand zigzag knight's paths ending at $(n,k)\ne(0,0)$ with $n\equiv k\pmod2$ is even; zigzag paths form a proper subfamily of the paths counted by $T(n,k)$, so this does not bear on the conjecture. +The referees' web searches (arXiv, MathOverflow, Mathematics Stack Exchange, the SeqFan list and general search engines) found no proof or counterexample, and the statement has no file in the formal-conjectures repository \cite{FC}. +We therefore classify the result as new. The argument is elementary, and we cannot exclude that it was known privately. + +\section{Statement}\label{sec:statement} + +\begin{definition}\label{def:T} +Define $T\colon\N\times\Z\to\N$ by $T(0,0)=1$, $T(n,k)=0$ for $|k|>2n$, and \eqref{eq:rec} for $n\ge1$, $|k|\le2n$, with $T(-1,\cdot)=0$. (Then \eqref{eq:rec} holds for all $n\ge1$, $k\in\Z$.) +For $n\ge1$ let $R(n)$ be the largest $r\in\{0,\dots,2n+1\}$ such that $T(n,0),T(n,1),\dots,T(n,r-1)$ are all even, and let $L(n)$ be defined in the same way with $T(n,0),T(n,-1),\dots,T(n,-(r-1))$. Put $a(0)=0$ and, for $n\ge1$, $a(n)=0$ if $R(n)=0$ and $a(n)=L(n)+R(n)-1$ otherwise. +\end{definition} + +If $T(n,0)$ is even, $a(n)$ is the size of the maximal block $\{-(L(n)-1),\dots,R(n)-1\}$ of consecutive positions around $0$ with even entries. +The name of A355339 \cite{A355339} reads, verbatim, ``\texttt{a(n) is the number of central even terms in the n-th row of triangle A355320; a(0) = 0.}'', and its FORMULA section, in the entry as contributed by R\'emy Sigrist on June~29, 2022, reads, verbatim: +\begin{quote} +{\small\texttt{Conjecture: a(n) = 1 iff n > 0 and n belongs to A000918.}} +\end{quote} +The name of A355320 \cite{A355320} gives $T(0,0)=1$, and its FORMULA section states \eqref{eq:rec} for $n>0$, with $T$ extended by $0$ outside $-2n\le k\le 2n$; this is Definition~\ref{def:T}. The sequence A000918 \cite{A000918} is ``\texttt{a(n) = 2\^{}n - 2}'' with offset $0$, with terms $-1,0,2,6,14,\dots$. + +\begin{theorem}[Sigrist's conjecture]\label{thm:main} +For every $n\ge0$, $a(n)=1$ if and only if $n>0$ and $n=2^m-2$ for some integer $m\ge0$. +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A355339.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{ea5b1be9\ldots 4226b}) before any proof attempt. Its definitions and the statement read, verbatim (the import, comments and docstrings, blank lines and all theorems are omitted): +\begin{lstlisting} +namespace Math0.Statements.A355339 +def addL : List ℕ → List ℕ → List ℕ + | [], l => l + | x :: xs, [] => x :: xs + | x :: xs, y :: ys => (x + y) :: addL xs ys +def step (pq : List ℕ × List ℕ) : List ℕ × List ℕ := + (pq.2, addL (addL pq.2 (List.replicate 4 0 ++ pq.2)) + (addL (List.replicate 3 0 ++ pq.1) (List.replicate 5 0 ++ pq.1))) +def rowPair (n : ℕ) : List ℕ × List ℕ := step^[n] ([], [1]) +def row (n : ℕ) : List ℕ := (rowPair n).2 +def entry (r : List ℕ) (m : ℕ) (k : ℤ) : ℕ := + if 0 ≤ k + 2 * m then r.getD (k + 2 * m).toNat 0 else 0 +def T (n : ℕ) (k : ℤ) : ℕ := entry (row n) n k +def a (n : ℕ) : ℕ := + if n = 0 then 0 else + let r := row n + let right := (((List.range (2 * n + 1)).map fun k : ℕ => entry r n k).takeWhile + fun x => x % 2 == 0).length + let left := (((List.range (2 * n + 1)).map fun k : ℕ => entry r n (-k)).takeWhile + fun x => x % 2 == 0).length + if right = 0 then 0 else left + right - 1 +def statement : Prop := + ∀ n : ℕ, a n = 1 ↔ (0 < n ∧ ∃ m : ℕ, (n : ℤ) = 2 ^ m - 2) +end Math0.Statements.A355339 +\end{lstlisting} +Row $n$ is stored as the list \texttt{row n} of its $4n+1$ entries, with $T(n,k)$ at position $k+2n$; \texttt{entry r n k} reads position $k+2n$ of \texttt{r} and returns $0$ outside the list. The map \texttt{step} sends (row $n-1$, row $n$) to (row $n$, row $n+1$), starting from row $-1$ (empty) and row $0$. Position $k+2n+2$ of row $n+1$ receives positions $k+2n+2$ and $k+2n-2$ of row $n$ (list shifts $0$ and $4$), that is $T(n,k+2)$ and $T(n,k-2)$, and positions $k+2n-1$ and $k+2n-3$ of row $n-1$ (shifts $3$ and $5$), that is $T(n-1,k+1)$ and $T(n-1,k-1)$; this is the recurrence $R_{n+1}=(1+X^4)R_n+(X^3+X^5)R_{n-1}$ of the PARI program in A355320. In \decl{a}, \texttt{right} and \texttt{left} are $R(n)$ and $L(n)$ (\texttt{takeWhile} takes the longest prefix of even values). Membership in A000918 is written in $\Z$, so $2^m-2$ is not truncated, and the statement covers all $n\ge0$ without further hypotheses. + +The statement file proves that \decl{T} satisfies the defining equations of Definition~\ref{def:T}, which determine it by induction on $n$: \decl{T_zero_zero} ($T(0,0)=1$), \decl{T_eq_zero} ($T(n,k)=0$ for $2n<|k|$), \decl{T_one} ($T(1,k)=T(0,k-2)+T(0,k+2)$) and \decl{T_add_two} (\eqref{eq:rec} for $T(n+2,k)$, every $k\in\Z$). The theorem \decl{a_eq} restates \decl{a} with \texttt{T n k} in place of \texttt{entry r n k} (by \texttt{rfl}). The theorems \decl{T_data} and \decl{a_data}, proved by \texttt{decide +kernel}, state that the values $T(n,k)$ for $0\le n\le 6$ are the $91$ listed terms of A355320 and that $a(0),\dots,a(76)$ are the $77$ listed terms of A355339. Independent Python computations by the reviewers agree with Sigrist's b-file of A355339 for $n\le 8192$ (they are not part of the formal proof). + +\section{Proof}\label{sec:proof} + +We follow the Lean file \path{lean/Math0/Frontier/OEIS/A355339.lean}; each step names the corresponding declaration. Throughout, $\binom pq=0$ for $q>p$, $x\tsub y=\max(x-y,0)$ on $\N$, and $\co{m}{P}$ is the coefficient of $X^m$ in $P$. All polynomials are in $\F[X]$, and an integer is identified with its image in $\F$. + +\subsection{\texorpdfstring{Row $0$ and symmetry}{Row 0 and symmetry}} + +\begin{lemma}[\decl{T0}, \decl{T_symm}]\label{lem:symm} +$T(0,k)=[k=0]$, and $T(n,-k)=T(n,k)$ for all $n\ge0$, $k\in\Z$. +\end{lemma} + +\begin{proof} +The first claim is \decl{T_zero_zero} and \decl{T_eq_zero}. Symmetry follows by two-step induction on $n$: rows $0$ and $1$ are symmetric ($T(1,k)=[k=\pm2]$), and by the induction hypothesis the four terms $T(n+1,-k\mp2)$, $T(n,-k\mp1)$ of \eqref{eq:rec} for $T(n+2,-k)$ equal the four terms $T(n+1,k\pm2)$, $T(n,k\pm1)$ for $T(n+2,k)$. +\end{proof} + +\subsection{\texorpdfstring{Row polynomials over $\mathbb{F}_2$}{Row polynomials over F2}} +Define $F_n\in\F[X]$ (\decl{Fp}) by $F_0=1$, $F_1=1+X^4$ and $F_{n+2}=(1+X^4)F_{n+1}+(X^3+X^5)F_n$. + +\begin{lemma}[\decl{T_shift}, \decl{T_coeff}]\label{lem:coeff} +For all $n,m\in\N$, $T(n,m-2n)\equiv\co{m}{F_n}\pmod 2$. +\end{lemma} + +\begin{proof} +For $j,m\in\N$ we have $T(n,m-2n-j)=T\bigl(n,(m-j)-2n\bigr)$ if $j\le m$, and $T(n,m-2n-j)=0$ if $j>m$, since then $m-2n-j<-2n$ (\decl{T_shift}). +We use two-step induction on $n$. For $n=0$, $T(0,m)=[m=0]=\co{m}{1}$. For $n=1$, $T(1,m-2)=T(0,m-4)+T(0,m)=[m=4]+[m=0]=\co{m}{(1+X^4)}$. For $n+2$, put $k=m-2(n+2)$; then $k-2=m-2(n+1)-4$, $k+2=m-2(n+1)$, $k-1=m-2n-5$ and $k+1=m-2n-3$, so by \eqref{eq:rec}, the shift rule and the induction hypothesis, modulo $2$, +\[ + T(n+2,k)\equiv \co{m}{F_{n+1}}+[m\ge4]\,\co{m-4}{F_{n+1}}+[m\ge5]\,\co{m-5}{F_n}+[m\ge3]\,\co{m-3}{F_n}, +\] +which is the coefficient of $X^m$ in $(1+X^4)F_{n+1}+(X^3+X^5)F_n=F_{n+2}$. +\end{proof} + +\subsection{\texorpdfstring{A closed form for $F_n$}{A closed form for F\_n}} + +\begin{lemma}[\decl{hsum_rec}]\label{lem:hsum} +Let $S$ be a commutative semiring, $A,B\in S$, and $h_n=\sum_{p+q=n}\binom pq A^pB^q$ (\decl{hsum}). Then $h_0=1$, $h_1=A$ and $h_{n+2}=A\,h_{n+1}+AB\,h_n$ for all $n\ge0$. +\end{lemma} + +\begin{proof} +The values of $h_0,h_1$ are immediate. In $h_{n+2}$ the term $p=0$ vanishes, so $h_{n+2}=\sum_{p+q=n+1}\binom{p+1}{q}A^{p+1}B^q$. By Pascal's rule, $\binom{p+1}{0}=\binom p0$ and $\binom{p+1}{q+1}=\binom pq+\binom p{q+1}$; hence +\[ + h_{n+2}=\sum_{p+q=n+1}\binom pqA^{p+1}B^q+\sum_{p+q=n}\binom pqA^{p+1}B^{q+1}=A\,h_{n+1}+AB\,h_n.\qedhere +\] +\end{proof} + +\begin{lemma}[\decl{one_add_X4}, \decl{Fp_mul}, \decl{Fp_closed}]\label{lem:closed} +Let $v=1+X^2$. Then $F_nv^n=h_n(v^3,X^3)$ for all $n\ge0$, and +$F_n=\sum_{p+q=n}\binom pq X^{3q}\,v^{\,2p\tsub q}$. +\end{lemma} + +\begin{proof} +In $\F[X]$ we have $1+X^4=(1+X^2)^2-2X^2=v^2$, and $X^3+X^5=X^3v$. So $G_n=F_nv^n$ satisfies $G_0=1$, $G_1=v^2\cdot v=v^3$ and +\[ + G_{n+2}=v^2F_{n+1}v^{n+2}+X^3vF_nv^{n+2}=v^3G_{n+1}+v^3X^3G_n, +\] +which are the initial values and the recurrence of $h_n(v^3,X^3)$ in Lemma~\ref{lem:hsum}. +For the closed form, a term with $q>p$ vanishes, and for $q\le p$ we have $3p=(2p-q)+n$, so $\binom pqX^{3q}v^{2p-q}\cdot v^n=\binom pq(v^3)^p(X^3)^q$. Hence both sides of the claimed identity, multiplied by $v^n$, equal $h_n(v^3,X^3)$, and $v^n$ can be cancelled because $\F[X]$ is an integral domain and $v\ne0$. +\end{proof} + +\begin{lemma}[\decl{vpow_coeff}, \decl{Fp_coeff}]\label{lem:fcoeff} +For $e,j\in\N$, $\co{j}{v^e}=\binom{e}{j/2}$ if $j$ is even and $0$ if $j$ is odd. Hence, for all $n,m\in\N$, in $\F$, +\begin{equation}\label{eq:coeff} + \co{m}{F_n}=\sum_{p+q=n}\binom pq\,\varepsilon_m(p,q),\qquad + \varepsilon_m(p,q)=\begin{cases}\binom{2p\tsub q}{(m-3q)/2}&\text{if }3q\le m\text{ and }2\mid m-3q,\\ 0&\text{otherwise.}\end{cases} +\end{equation} +\end{lemma} + +\begin{proof} +$v^e=\sum_i\binom eiX^{2i}$ (in Lean, $v^e$ is the image of $(1+X)^e$ under $X\mapsto X^2$, \decl{Polynomial.expand}). The formula follows from Lemma~\ref{lem:closed}, since $\co{m}{(X^{3q}P)}=\co{m-3q}{P}$ if $3q\le m$ and $0$ otherwise. +\end{proof} + +\subsection{Two binomial parity lemmas} +We use Lucas's theorem \cite{Lucas} for the prime $2$ (\decl{lucas2}, from Mathlib's \decl{Choose.choose_modEq_choose_mod_mul_choose_div_nat}), +\begin{equation}\label{eq:lucas} + \tbinom NK\equiv\tbinom{N\bmod2}{K\bmod2}\tbinom{\lfloor N/2\rfloor}{\lfloor K/2\rfloor}\pmod 2, +\end{equation} +and the fact that $\binom{2c}{c}=2\binom{2c-1}{c-1}$ is even for $c\ge1$ (\decl{Nat.two_dvd_centralBinom_of_one_le}). + +\begin{lemma}[\decl{oddC}]\label{lem:oddC} +For $b\ge0$, $\binom{2b+1}{b}$ is odd if and only if $b+1$ is a power of $2$. +\end{lemma} + +\begin{proof} +Strong induction on $b$. By \eqref{eq:lucas}, $\binom{2b+1}{b}\equiv\binom{1}{b\bmod2}\binom{b}{\lfloor b/2\rfloor}=\binom{b}{\lfloor b/2\rfloor}$. +If $b=0$, this is $1$ and $b+1=2^0$. +If $b=2c$ with $c\ge1$, this is $\binom{2c}{c}$, which is even, and $b+1\ge3$ is odd, so not a power of $2$. +If $b=2c+1$, this is $\binom{2c+1}{c}$, which by induction is odd if and only if $c+1=2^t$ for some $t$, that is, if and only if $b+1=2(c+1)$ is a power of $2$ (note $b+1\ne 2^0$). +\end{proof} + +\begin{lemma}[\decl{dzero}]\label{lem:dzero} +Let $t,D,q\ge0$. If $\binom{D+q}{q}$ is odd and $2D+q+1=2^t$, then $D=0$. +\end{lemma} + +\begin{proof} +Induction on $t$. If $t=0$, then $2D+q+1=1$ forces $D=0$. Let $2D+q+1=2^{t+1}$; then $q=2q'+1$ is odd. If $D$ were odd, $D+q$ would be even and \eqref{eq:lucas} would give the factor $\binom01=0$. Hence $D=2D'$, and \eqref{eq:lucas} gives $\binom{D+q}{q}\equiv\binom11\binom{D'+q'}{q'}$, so $\binom{D'+q'}{q'}$ is odd. Moreover $2(2D'+q'+1)=2D+q+1=2^{t+1}$, so $2D'+q'+1=2^t$, and the induction hypothesis gives $D'=0$. +\end{proof} + +\subsection{\texorpdfstring{The entries $T(n,0)$ and $T(n,1)$}{The entries T(n,0) and T(n,1)}} + +\begin{proposition}[\decl{term_even}, \decl{T0_even}]\label{prop:T0} +For $n\ge1$, $T(n,0)$ is even. +\end{proposition} + +\begin{proof} +By Lemma~\ref{lem:coeff}, $T(n,0)\equiv\co{2n}{F_n}$; we show that every term of \eqref{eq:coeff} with $m=2n$ vanishes. Let $p+q=n$. If $pq$. Then $3q\le2n+1$, and $2n+1-3q=(2p-q)+1$. If this is odd, $\varepsilon_{2n+1}(p,q)=0$. Otherwise $2p-q=2c+1$ is odd and $\varepsilon_{2n+1}(p,q)=\binom{2c+1}{c+1}=\binom{2c+1}{c}$. +Suppose both $\binom pq$ and $\binom{2c+1}{c}$ were odd. By Lemma~\ref{lem:oddC}, $c+1=2^t$ for some $t$. Put $D=p-q\ge1$; then $\binom{D+q}{q}=\binom pq$ is odd and $2D+q+1=2p-q+1=2c+2=2^{t+1}$, so Lemma~\ref{lem:dzero} gives $D=0$, a contradiction. + +\emph{$n$ odd.} Then $p+q=n$ forces $p\ne q$, so all terms vanish and $T(n,1)$ is even; and $n+2$ is odd, hence not of the form $2^{t+2}$. + +\emph{$n=2q$ even.} Only the term $(p,q)=(q,q)$ remains; here $\binom qq=1$, $3q\le 4q+1$ and $2n+1-3q=q+1$. +If $q=2c$ is even, then $q+1$ is odd, the term is $0$ and $T(n,1)$ is even; and $n+2=4c+2\equiv2\pmod4$ is not of the form $2^{t+2}$. +If $q=2c+1$ is odd, then $(q+1)/2=c+1$ and $2q\tsub q=2c+1$, so $T(n,1)\equiv\binom{2c+1}{c+1}=\binom{2c+1}{c}$, which by Lemma~\ref{lem:oddC} is odd if and only if $c+1=2^t$ for some $t$, that is, if and only if $n+2=4(c+1)=2^{t+2}$. +\end{proof} + +Lemma~\ref{lem:symm} and Propositions~\ref{prop:T0} and~\ref{prop:T1} prove Theorem~\ref{thm:parity}. + +\subsection{\texorpdfstring{The run length and the proof of Theorem~\ref{thm:main}}{The run length and the proof of Theorem 3}} + +\begin{lemma}[\decl{range_map}, \decl{tw}, \decl{run_one}, \decl{a_one_iff}]\label{lem:run} +For $n\ge1$, $a(n)=1$ if and only if $T(n,1)$ is odd. +\end{lemma} + +\begin{proof} +Since $n\ge1$, the lists $T(n,0),T(n,1),\dots,T(n,2n)$ and $T(n,0),T(n,-1),\dots,T(n,-2n)$ have at least two entries, and their first entry $T(n,0)$ is even by Proposition~\ref{prop:T0}. So $R(n),L(n)\ge1$, $a(n)=L(n)+R(n)-1$, and $a(n)=1$ if and only if $L(n)=R(n)=1$. Finally, $R(n)=1$ if and only if $T(n,1)$ is odd, and $L(n)=1$ if and only if $T(n,-1)$ is odd, which is the same condition by Lemma~\ref{lem:symm}. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +For $n=0$ both sides are false, as $a(0)=0$. Let $n\ge1$. By Lemma~\ref{lem:run} and Proposition~\ref{prop:T1}, $a(n)=1$ if and only if $n+2=2^{t+2}$ for some $t\ge0$. If $n+2=2^{t+2}$, take $m=t+2$. Conversely, if $n=2^m-2$ in $\Z$ with $n>0$, then $m\ne0$ (else $n=-1$) and $m\ne1$ (else $n=0$), so $m=t+2$ and $n+2=2^{t+2}$. +\end{proof} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in the file \path{lean/Math0/Frontier/OEIS/A355339.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A355339.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main theorem is \decl{Math0.Frontier.A355339.result}, of type \decl{Math0.Statements.A355339.statement}; the auxiliary declarations of the proof file named in Section~\ref{sec:proof} are private. The proof file uses no \texttt{decide}, \texttt{native\_decide}, \texttt{sorry} or \texttt{set\_option}. The data checks \decl{T_zero_zero}, \decl{T_data} and \decl{a_data} in the statement file use \texttt{decide +kernel}, which evaluates in the kernel and adds no axioms. + +\subsection*{Audit} +The proof file ends with \texttt{\#math0\_settles result statement} (with full names). This command, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (so no \decl{sorryAx}, \texttt{native\_decide} or custom axiom); and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata annotations and without unfolding. Here it reports +\begin{lstlisting}[basicstyle=\ttfamily\tiny] +math0 audit: 'Math0.Statements.A355339.statement' depends on axioms [propext] +math0 audit: 'Math0.Frontier.A355339.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A355339.result' proves 'Math0.Statements.A355339.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. Checking the proof file alone with \texttt{lake env lean} takes about $15$ seconds on our machine. + +{\footnotesize\raggedright +\begin{thebibliography}{99} + +\bibitem{BR} +J.-L.~Baril and J.~L.~Ram\'irez, \emph{Knight's paths towards Catalan numbers}, arXiv:2206.12087 [math.CO], 2022. + +\bibitem{BHKR} +J.-L.~Baril, N.~Hassler, S.~Kirgizov, and J.~L.~Ram\'irez, \emph{Grand zigzag knight's paths}, Enumer. Comb. Appl. \textbf{5}:1 (2025), Article \#S2R6, \url{https://doi.org/10.54550/ECA2025V5S1R6}; arXiv:2402.04851 [math.CO]. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171 [cs.AI], 2026. + +\bibitem{Lucas} +\'E.~Lucas, \emph{Th\'eorie des fonctions num\'eriques simplement p\'eriodiques}, Amer. J. Math. \textbf{1} (1878), 184--240, 289--321. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proc.\ 9th ACM SIGPLAN Int.\ Conf.\ on Certified Programs and Proofs (CPP 2020), 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A000918} +The OEIS Foundation Inc., \url{https://oeis.org/A000918}, entry by N.~J.~A. Sloane. + +\bibitem{A096587} +The OEIS Foundation Inc., \url{https://oeis.org/A096587}, entry by C.~Kimberling (June~28, 2004). + +\bibitem{A096608} +The OEIS Foundation Inc., \url{https://oeis.org/A096608}, entry by C.~Kimberling (June~29, 2004). + +\bibitem{A355320} +The OEIS Foundation Inc., \url{https://oeis.org/A355320}, entry by R.~Sigrist (June~28, 2022). + +\bibitem{A355339} +The OEIS Foundation Inc., \url{https://oeis.org/A355339}, entry and conjecture by R.~Sigrist (June~29, 2022), rev.~\#10. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a355360/README.md b/results/oeis-a355360/README.md new file mode 100644 index 0000000..83500c9 --- /dev/null +++ b/results/oeis-a355360/README.md @@ -0,0 +1,57 @@ +# Columns 1 and 2 of the theta-series triangle A355360 are P(x)^3 and 2P(x)^6 + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A355360 +**Date:** 2026-10-29 + +## Result + +Let A(x,y) = sum_m a_m(y) x^m be the series (a_m in Z[y]) computed by the entry's recursion a_0 = 1, a_{m+1} = y a_m - [x^{m+1}] F(a_0 + ... + a_m x^m). Here F(B) = sum_{n in Z} (-1)^n x^{n(n+1)/2} B^n = sum_{n>=0} (-1)^n x^{n(n+1)/2} (B^n - B^{-(n+1)}), and this recursion is the unique solution of x y A = F(A). Let T(n,k) = [x^n y^k] A. Then for every n >= 0: +- T(n+1, 1) = A000716(n), the number of partitions of n into parts of 3 kinds; +- T(n+2, 2) = 2 * A023005(n), twice the number of partitions of n into parts of 6 kinds. +Equivalently, the y- and y^2-coefficients of A are x P^3 and 2 x^2 P^6, where P = prod_{k>=1} 1/(1-x^k). These are Hanna's conjectures (C.1) and (C.2). + +## Assessment + +Put A = 1+u. Formula (3) of the entry turns into x*y*(1+u)^2 = u*G(1+u), where G(A) = prod(1-x^n)(1-x^n A)(1-x^n/A). G is invariant under A -> 1/A and G(1) = P^{-3}, so G(1+u) = P^{-3}(1 + O(u^2)). Comparing the y and y^2 coefficients then gives u = xyP^3 + 2(xyP^3)^2 + O(y^3). Pairing n with -1-n and applying Jacobi's cube identity gives the same few-line computation. The Lean proof is long only because it proves Jacobi's identity from scratch and checks the PARI-style recursion; that is formalization effort, not a new mathematical idea. + +*Follows from:* The entry's own formula (3), x*y*A*P = prod_{n>=1}(1 - x^n*A)(1 - x^(n-1)/A) (Jacobi triple product), or equivalently Jacobi's classical identity prod(1-x^k)^3 = sum_{n>=0} (-1)^n (2n+1) x^{n(n+1)/2} + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A355360](https://oeis.org/A355360) as [`Math0.Statements.A355360.statement`](../../lean/Math0/Statements/OEIS/A355360.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A355360.lean`](../../lean/Math0/Frontier/OEIS/A355360.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C A355360 Conjectures. (C.1) Column 1 equals A000716, the number of partitions into parts of 3 kinds. (C.2) Column 2 equals twice A023005, the number of partitions into parts of 6 kinds. (Paul D. Hanna, Jul 19 2022) + +Referees: OEIS A355360: Paul D. Hanna, Jul 19 2022. Last edit %I #7 Jul 20 2022, in both the local mirror and raw.githubusercontent oeisdata main. It has no %E lines and (C.1)/(C.2) are still labeled "Conjectures." + +Related entries: +- A355350: same column conjectures, still open. +- A355870: column-1 conjecture, still open. +- A354650: asserts column 1 = A000716 for a different theta table, with no proof given. It cites arXiv:2609.32264 (LANTERN), which is about relation-mining and does not cover these entries. +- A355361 through A355365: asymptotics only. + +Not covered in: +- the epoch-research/LeanOpenProblems-results metadata and runs (arXiv:2608.11941; Tsoukalas et al., arXiv:2605.22763); +- google-deepmind/formal-conjectures (FormalConjectures/OEIS/355360.lean returns 404); +- S. Fried's arXiv:2410.07237, JIS 28 (2025) no. 4, JIS 29 (2026) Article 26.1.8, and arXiv:2607.24832 (that paper covers A355372, not A355360). + +Web searches of MathOverflow, Math StackExchange, SeqFan and arXiv found no proof or counterexample. The underlying tool, Jacobi's identity prod (1-q^k)^3 = sum (-1)^n (2n+1) q^{n(n+1)/2}, is classical. + +## Citation + +```bibtex +@misc{math0:oeis-a355360, + author = {{math0}}, + title = {{Columns 1 and 2 of the theta-series triangle A355360 are P(x)^3 and 2P(x)^6}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a355360}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a356360/README.md b/results/oeis-a356360/README.md new file mode 100644 index 0000000..a4c09df --- /dev/null +++ b/results/oeis-a356360/README.md @@ -0,0 +1,45 @@ +# A356360: the continued-fraction denominators are 1 or prime + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Number theory +**Source problem:** OEIS A356360 +**Date:** 2026-10-20 + +## Result + +For n >= 3, let a(n) be the denominator, in lowest terms, of the continued fraction 1/(2 - 3/(3 - 4/(4 - ... ((n-1) - n/(n+1))))). Then every a(n) is 1 or a prime. This is the conjecture Mohammed Bouras stated in OEIS A356360 (2022). + +## Assessment + +The gcd formula already in the entry gives a(n) | 2n-1 at once, so the prime case is immediate. The composite case needs only that an odd composite c = 2m+3 with m >= 4 divides m!, a textbook Wilson-style lemma with a short case split on whether c = p^2. Together with checking n = 3, 4, 5 directly, the whole argument fits in under a page and uses no new idea. The longer Lean development is formalization effort and does not make the mathematics deeper. + +*Follows from:* The closed form and gcd formula already in the entry, a(n) = (2n-1)/gcd(2n-1, A051403(n-2)+A051403(n-3)), proved as Theorem 1.1 of Bouras's linked paper. Combined with A051403(j) = (j+2)*A003422(j+1)/2, this reduces the question to the elementary fact that an odd composite 2m+3 with m >= 4 divides m!. The same denominator-of-factorial pattern appears in A145737 (Detlefs: a(n) = denominator(n!*3n(n+1)/(2(2n+1))) = 2n+1 if prime, else 1). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A356360](https://oeis.org/A356360) as [`Math0.Statements.A356360.statement`](../../lean/Math0/Statements/OEIS/A356360.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A356360.lean`](../../lean/Math0/Frontier/OEIS/A356360.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: A356360: "Conjecture: The sequence contains only 1's and the primes." (_Mohammed Bouras_, Oct 15 2022). The same sentence appears in A369797 (Feb 2024), A370726 (Feb 2024) and A372763 ('Conjecture 1', May 2024). A372761: "Conjecture 1: Except for 4, the sequence contains only 1's and the primes." A362086: "Conjecture: Except for 9, every term of this sequence is either a prime or 1." A363482: "Conjecture: Except for 49, every term of this sequence is either a prime or 1." (all by Bouras) + +Referees: OEIS A356360 (mirror 2026-10-17, rev #31 Aug 2024): still marked "Conjecture". It has an unproved comment "Same as A128059(n), A145737(n-1), A097302(n-2) for n>5", and its formula "a(n)=2n-1 if prime else 1 (n != 5)" is labeled "From the conjecture". M. Bouras, "The Distribution Of Prime Numbers And The Continued Fractions", Zenodo doi:10.5281/zenodo.7212512 (2022; also viXra 2209.0101): proves only the closed form (Thm 1.1) and states Conjecture 3.1, verified to n=10000. M. Bouras, "A New Primes-Generating Sequence", arXiv:2509.09745 (2025), Table 2 (k=1 row = A356360): observation only, no proof. Bouras slides, Zenodo 10992128: "Conjecture 2", no proof. AlphaProof Nexus results / formal-conjectures auto_oeis THEOREM_MAPPING and T. Adamczewski, "OEIS Open", arXiv:2608.11941: A356360 is not included; only the sibling A372761 Conj. 2 was resolved. Related but distinct: A356247 conjectures proved by B. Cloitre (2025, OEIS attachment). No prior proof or counterexample found. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a356360, + author = {{math0}}, + title = {{A356360: the continued-fraction denominators are 1 or prime}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a356360}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a356360/paper.pdf b/results/oeis-a356360/paper.pdf new file mode 100644 index 0000000..72de94b Binary files /dev/null and b/results/oeis-a356360/paper.pdf differ diff --git a/results/oeis-a356360/paper.tex b/results/oeis-a356360/paper.tex new file mode 100644 index 0000000..952e3c7 --- /dev/null +++ b/results/oeis-a356360/paper.tex @@ -0,0 +1,407 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,by_cases,subst,right,left}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {≠}{{$\ne$}}1 {→}{{$\to$}}1 {∨}{{$\vee$}}1 {∧}{{$\wedge$}}1 + {¬}{{$\neg$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1 {…}{{$\ldots$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{…}{\ensuremath{\ldots}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Q}{\mathbb{Q}} +\DeclareMathOperator{\den}{den} +\DeclareMathOperator{\cf}{cf} + +\title[Denominators of a continued fraction (OEIS A356360)]{Every denominator of $1/(2-3/(3-4/(\cdots(n-1)-n/(n+1))))$ is $1$ or a prime} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + +\begin{document} +\begin{abstract} +For $n\ge3$ let $a(n)$ be the denominator, in lowest terms, of the finite continued fraction $1/(2-3/(3-4/(\cdots(n-1)-n/(n+1))))$; this is the OEIS sequence A356360. +We prove the conjecture of M.~Bouras (2022), recorded in that entry, that every term is $1$ or a prime. +The proof combines a closed form for the continued fraction, with denominator $2(2n-1)$, with the elementary fact that an odd composite number $2m+3$ with $m\ge4$ divides $m!$; for $n\ge6$ it shows that $a(n)=1$ when $2n-1$ is composite and that $a(n)$ divides $2n-1$ when $2n-1$ is prime. +To our knowledge this is a new result: the entry still lists the statement as a conjecture and we found no proof in the literature, although the argument is short and the structure behind it is visible in formulas recorded in the entry. +The proof is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, checked against its $82$ listed terms, and reviewed for fidelity and frozen before any proof attempt; the statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +The OEIS entry A356360 \cite{A356360}, created by M.~Bouras on October~15, 2022, is the sequence of denominators of the finite continued fractions +\[ + \cfrac{1}{2-\cfrac{3}{3-\cfrac{4}{\ddots\;(n-1)-\cfrac{n}{n+1}}}}\qquad(n\ge3), +\] +which begins $5,7,3,11,13,1,17,19,1,23,1,1,29,31,\dots$. The entry conjectures that the sequence contains only $1$'s and primes. We prove this (Theorem~\ref{thm:main}). + +Bouras contributed several sequences of this kind with a different innermost term, among them $n+2$, $n+3$, $n+4$, $n+5$ (A369797, A370726, A372761, A372763 \cite{A369797,A370726,A372761,A372763}) and $-1$, $-2$, $-3$, $-4$, $-5$ (A356247, A363102, A362086, A363347, A363482 \cite{A356247,A363102,A362086,A363347,A363482}), each with a conjecture that the terms are $1$ or prime, in some cases with one exceptional value. We address only A356360 (for McEachen's further conjectures in the entry, see Remark~\ref{rem:exact}). + +\subsection*{Prior work} +Bouras's paper \cite{Bz} (also posted as viXra:2209.0101) proves a closed form for this continued fraction (its Theorem~1.1) and states the primality property as its Conjecture~3.1, checked for $n\le10000$. The closed form appears in the entry as a formula in terms of A051403 \cite{A051403} (see Section~\ref{sec:closed}), together with the resulting gcd formula for $a(n)$, and C.~W.~Wu's program in the entry (2024) computes $a(n)$ in this way. Bouras's slides \cite{Bslides} state the primality property as a conjecture, and his preprint \cite{Barxiv} lists A356360 as the case $k=1$ of a family of sequences (Table~2) and records the property as an observation, without proof. The entry also contains an unsigned comment that the sequence is the ``Same as A128059(n), A145737(n-1) and A097302(n-2) for n $>$ 5'', given without proof or reference, and the formula ``From the conjecture: Except for n = 5, a(n)= 2n - 1 if 2n-1 is prime, 1 otherwise.'' The current revision of the entry (\#31, August~6, 2024) still records the primality property as a conjecture. + +For the sister sequences: the conjectures of A356247 (innermost term $-1$) are proved in a note of B.~Cloitre \cite{Cloitre}, according to a 2025 comment in that entry. The conjecture that A363102 (innermost term $-2$) contains only $1$'s and primes is marked as solved in the formal-conjectures repository \cite{FC}, with a formal proof found by the methods of Tsoukalas et al.\ \cite{Tsoukalas}; T.~Adamczewski gives a proof sketch in \cite[Appendix~A]{Ad}, and the AlphaProof Nexus outputs \cite{APN} contain a Lean file for it. Conjectures~1 and~2 of A363347 (innermost term $-4$), the first of which is the corresponding $1$-or-prime statement, were proved by an autonomous AI agent with a Lean proof \cite{APN}, according to a 2026 comment in that entry \cite{A363347}; see also \cite[Appendix~A]{Ad}. Conjecture~2 of A372761 (innermost term $n+4$; a different statement, about which primes occur) was proved by an autonomous AI agent with a Lean proof \cite{APN}, according to a 2026 comment in that entry \cite{A372761}; see also \cite[Appendix~A]{Ad}. That comment describes a proof which, like ours, starts from a closed form of the continued fraction with a factorial-sum numerator over $2(5n-4)$. The conjectures of A362086 and A363482 were proved, with Lean proofs, in the math0 project \cite{M0A362086,M0A363482}. +For A356360 itself we found no proof or counterexample. The sequence has no file in the formal-conjectures repository \cite{FC} at the pinned commit \texttt{c77fdd4}; it is not among the AlphaProof Nexus outputs \cite{APN,Tsoukalas} or the conjectures treated in Epoch AI's OEIS Open study \cite{Ad}; and searches of arXiv, MathOverflow, Mathematics Stack Exchange and the SeqFan list found no proof. We therefore classify Theorem~\ref{thm:main} as a \emph{new result}, with caveats: the argument is elementary, the closed form is due to Bouras, the same strategy (a closed form, then divisibility properties of factorials) has been applied by others to sister sequences, and the comment and formulas quoted above suggest that contributors to the entry understood the structure of the sequence, so the result may have been known informally. We are not aware of a written proof. + +\section{Statement}\label{sec:statement} + +For $q\in\Q$ we write $\den q\ge1$ for its denominator in lowest terms. + +\begin{definition}\label{def:a} +For an integer $k\ge2$ and $t\in\Q\setminus\{0\}$ put $s_k(t)=k-(k+1)/t$. For $n\ge3$ let $t_n=n+1$ and $t_k=s_k(t_{k+1})$ for $k=n-1,\dots,2$, and put +\[ + \cf(n)=1/t_2=1/\bigl(2-3/(3-4/(\cdots(n-1)-n/(n+1)))\bigr),\qquad a(n)=\den\cf(n). +\] +\end{definition} + +That no $t_k$ vanishes is part of Lemma~\ref{lem:closed} below. For example $\cf(3)=1/(2-3/4)=4/5$, $\cf(4)=11/7$ and $\cf(5)=11/3$, so $a(3)=5$, $a(4)=7$ and $a(5)=3$. +The OEIS entry \cite{A356360} (offset $3$) is named ``Denominator of the continued fraction 1/(2-3/(3-4/(4-5/(...(n-1)-n/(n+1)))))'' and contains the comment, verbatim, +\begin{quote} +\texttt{Conjecture: The sequence contains only 1's and the primes.} +\end{quote} +which is unsigned and hence due to the author of the entry, Mohammed Bouras, October~15, 2022. + +\begin{theorem}\label{thm:main} +For every $n\ge3$, $a(n)=1$ or $a(n)$ is prime. +\end{theorem} + +The theorem reads the conjecture as ``every term is $1$ or a prime''; it does not claim that every prime occurs. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A356360.lean}, reviewed for fidelity and frozen (SHA-256 prefix \texttt{be296be3}) before any proof attempt. Its content is, verbatim except that the copyright header, the line \texttt{import Mathlib} and the docstrings are omitted: +\begin{lstlisting} +namespace Math0.Statements.A356360 + +def step (k : ℕ) (t : ℚ) : ℚ := (k : ℚ) - ((k : ℚ) + 1) / t + +def cf (n : ℕ) : ℚ := 1 / (List.range' 2 (n - 2)).foldr step ((n : ℚ) + 1) + +def a (n : ℕ) : ℕ := (cf n).den + +example : cf 3 = 4 / 5 ∧ cf 4 = 11 / 7 ∧ cf 5 = 11 / 3 := by decide +kernel + +theorem a_data : (List.range 82).map (fun i => a (i + 3)) = + [5, 7, 3, 11, 13, 1, 17, 19, 1, 23, 1, 1, 29, 31, 1, 1, 37, 1, 41, 43, 1, 47, 1, 1, 53, 1, + 1, 59, 61, 1, 1, 67, 1, 71, 73, 1, 1, 79, 1, 83, 1, 1, 89, 1, 1, 1, 97, 1, 101, 103, 1, + 107, 109, 1, 113, 1, 1, 1, 1, 1, 1, 127, 1, 131, 1, 1, 137, 139, 1, 1, 1, 1, 149, 151, 1, + 1, 157, 1, 1, 163, 1, 167] := by + decide +kernel + +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → a n = 1 ∨ (a n).Prime + +end Math0.Statements.A356360 +\end{lstlisting} +\texttt{step k t} is $s_k(t)$. For $n\ge3$, \texttt{List.range' 2 (n - 2)} is the list $[2,3,\dots,n-1]$, and the right fold of \decl{step} over it, starting at $n+1$, is \texttt{step 2 (step 3 (...(step (n-1) (n+1))))}, i.e.\ $t_2$. So \texttt{cf n} is $\cf(n)$, and \texttt{a n} is its reduced denominator \decl{Rat.den}, which is positive. This is the definition in the name of the entry, not the closed form or the gcd formula listed there. The statement quantifies over $n\ge3$, the offset of the entry, and has no further hypotheses; values of \texttt{a n} for $n<3$ are never used. +Lean defines $q/0=0$, which would change the value if some $t_k$ vanished; this never happens, since all $t_k$ are positive by Lemma~\ref{lem:closed} (the docstring of the statement file gives a separate argument: $t_k>k(k-2)/(k-1)\ge0$). +The definitions are checked against the entry by kernel evaluation (\texttt{decide +kernel}): \decl{a_data} states that $(a(3),\dots,a(84))$ is the list of all $82$ terms in the data section of the entry, and the \texttt{example} confirms $\cf(3)=4/5$, $\cf(4)=11/7$, $\cf(5)=11/3$. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A356360.lean} (Section~\ref{sec:lean}); the Lean names of the lemmas are given in brackets. Throughout we use, for $m\ge0$ and $x\in\Q$, +\[ + S_m=\sum_{k=0}^{m-1}k!,\qquad M_m(x)=(m+1)x-m(m+2),\qquad H_m(x)=s_2(s_3(\cdots s_{m+1}(x)\cdots)), +\] +so $S_0=0$, $S_{m+1}=S_m+m!$ and $H_0(x)=x$; $S_m$ is the left factorial $!m$ (A003422 \cite{A003422}). In Lean, $H_m(x)$ is \texttt{(List.range' 2 m).foldr step x}. If $n=m+2\ge3$, then $\cf(n)=1/H_m(n+1)$. + +\subsection{The closed form}\label{sec:closed} + +\begin{lemma}\label{lem:peel} +Let $m\ge0$ and $x\in\Q\setminus\{0\}$. Then $H_{m+1}(x)=H_m(s_{m+2}(x))$ and +\[ + M_m\bigl(s_{m+2}(x)\bigr)=\frac{M_{m+1}(x)}{x}=\frac{(m+2)x-(m+1)(m+3)}{x}. +\] +\end{lemma} + +\begin{proof} +The first identity holds because $[2,\dots,m+2]$ is $[2,\dots,m+1]$ followed by $m+2$, so $m+2$ is the innermost level (in Lean: \decl{List.range'_concat} and \decl{List.foldr_append}). For the second, +$(m+1)\bigl(m+2-\tfrac{m+3}{x}\bigr)-m(m+2)=(m+2)-\tfrac{(m+1)(m+3)}{x}$. +\end{proof} + +\begin{lemma}[\decl{closed}]\label{lem:closed} +Let $m\ge0$ and $x\in\Q$ with $M=M_m(x)>0$. Then every argument $t$ at which some $s_k$ is evaluated in $H_m(x)$ is positive, $S_mM+(m+2)\,m!>0$, and +\[ + H_m(x)=\frac{2M}{S_m M+(m+2)\,m!}. +\] +\end{lemma} + +\begin{proof} +Induction on $m$, for all $x$ at once. For $m=0$ there is no evaluation, $M=x$ and the right side is $2x/2=x=H_0(x)$. +Let $M'=M_{m+1}(x)=(m+2)x-(m+1)(m+3)>0$. Then $(m+2)x>(m+1)(m+3)>0$, so $x>0$. Put $x'=s_{m+2}(x)$. By Lemma~\ref{lem:peel}, $H_{m+1}(x)=H_m(x')$ and $M_m(x')=M'/x>0$, so the induction hypothesis applies to $x'$: the arguments in $H_m(x')$ are positive, and so are all arguments in $H_{m+1}(x)$, the remaining one being $x$. Multiplying numerator and denominator by $x>0$, +\[ + H_{m+1}(x)=\frac{2M'/x}{S_mM'/x+(m+2)\,m!}=\frac{2M'}{S_mM'+(m+2)\,m!\,x}. +\] +Finally $S_{m+1}M'+(m+3)(m+1)!=S_mM'+m!\bigl(M'+(m+1)(m+3)\bigr)=S_mM'+(m+2)\,m!\,x$, which is positive. +\end{proof} + +\begin{corollary}[\decl{cf_eq}]\label{cor:cf} +For every $m\ge0$, +\[ + \cf(m+2)=\frac{S_m(2m+3)+(m+2)\,m!}{2(2m+3)},\quad\text{i.e.}\quad \cf(n)=\frac{S_{n-2}(2n-1)+n\,(n-2)!}{2(2n-1)}\ \ (n\ge2). +\] +\end{corollary} + +\begin{proof} +For $x=n+1=m+3$ we have $M_m(x)=(m+1)(m+3)-m(m+2)=2m+3>0$; apply Lemma~\ref{lem:closed} and take reciprocals. +\end{proof} + +For $m=1,2,3$ this gives $8/10$, $22/14$ and $66/18$, in accordance with the values above. +Corollary~\ref{cor:cf} is the first formula of the entry, whose source \cite{Bz} proves a closed form for the continued fraction (its Theorem~1.1). Indeed, by a formula of G.~Detlefs in A051403 \cite{A051403}, $A051403(j)=(j+2)S_{j+1}/2$, so +\[ + A051403(m)+A051403(m-1)=\tfrac12\bigl((m+2)(S_m+m!)+(m+1)S_m\bigr)=\tfrac12\bigl(S_m(2m+3)+(m+2)\,m!\bigr), +\] +and Corollary~\ref{cor:cf} becomes $\cf(n)=(A051403(n-2)+A051403(n-3))/(2n-1)$. This identification is not part of the formal proof, which uses only the definition. + +\subsection{Arithmetic lemmas} + +\begin{lemma}[\decl{two_dvd_S}]\label{lem:even} +$S_m$ is even for every $m\ge2$. +\end{lemma} + +\begin{proof} +$S_2=2$, and $S_{m+1}=S_m+m!$ with $m!$ even for $m\ge2$. +\end{proof} + +\begin{lemma}[\decl{mul_dvd_factorial}]\label{lem:ab} +If $05$, as the comment quoted in the introduction asserts. This remark is not part of the Lean development, which proves only Theorem~\ref{thm:main}. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is the file \path{lean/Math0/Frontier/OEIS/A356360.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A356360.result}, of type \decl{Math0.Statements.A356360.statement}. The private declarations are \decl{S} (the sum $S_m$) and those named in Section~\ref{sec:proof}: \decl{closed} (Lemma~\ref{lem:closed}, which includes Lemma~\ref{lem:peel}), \decl{cf_eq}, \decl{two_dvd_S}, \decl{mul_dvd_factorial}, \decl{composite_dvd} and \decl{main}. In \decl{main}, the prime case uses Mathlib's \decl{Rat.den_dvd} (the denominator of $K/c$ divides $c$) and the composite case uses \decl{Rat.den_div_natCast_eq_one_iff}. The final proof reads, verbatim: +\begin{lstlisting} +theorem result : statement := by + intro n hn + obtain ⟨m, rfl⟩ : ∃ m, n = m + 2 := ⟨n - 2, by omega⟩ + rcases (show m = 1 ∨ m = 2 ∨ m = 3 ∨ 4 ≤ m by omega) with h | h | h | h + · subst h; right; rw [show a (1 + 2) = 5 by decide +kernel]; norm_num + · subst h; right; rw [show a (2 + 2) = 7 by decide +kernel]; norm_num + · subst h; right; rw [show a (3 + 2) = 3 by decide +kernel]; norm_num + · exact main m h +\end{lstlisting} + +\subsection*{Kernel computation} +With \texttt{decide +kernel} the Lean kernel evaluates the continued fraction in exact rational arithmetic and compares the reduced denominator with the claimed value. This proves \decl{a_data} and the \texttt{example} in the statement file ($n=3,\dots,84$; about $12$ seconds), and $a(3)=5$, $a(4)=7$, $a(5)=3$ in the proof file; the primality of $5$, $7$, $3$ is proved by \texttt{norm\_num}, and the base case $2\mid S_2$ of \decl{two_dvd_S} by \texttt{decide}. Neither file uses \texttt{native\_decide} (which would add the axiom \decl{Lean.ofReduceBool}) or \texttt{sorry}, and the proof file sets no options. + +\subsection*{Audit} +The file ends with the command \texttt{\#math0\_settles} applied to \decl{Math0.Frontier.A356360.result} and \decl{Math0.Statements.A356360.statement}. This command, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) the statement is a definition of type \texttt{Prop} without universe parameters; (2) the statement and the result depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (so no \decl{sorryAx}, \decl{Lean.ofReduceBool} or custom axiom); and (3) the type of the result is syntactically the statement or its negation, up to metadata annotations, with no unfolding. Running \texttt{lake env lean Math0/Frontier/OEIS/A356360.lean} in \path{lean/} prints +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A356360.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A356360.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A356360.result' proves 'Math0.Statements.A356360.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib cache, rebuilds all math0 results with \texttt{lake build} (re-running every audit command) and checks that the pinned dependencies are unmodified. + +\begin{thebibliography}{99} + +\bibitem{Ad} +T.~Adamczewski, \emph{OEIS Open: How many conjectures can language models turn into theorems?}, arXiv:2608.11941 [cs.AI], 2026. + +\bibitem{Bz} +M.~Bouras, \emph{The distribution of prime numbers and the continued fractions}, Zenodo, 2022, \url{https://doi.org/10.5281/zenodo.7212512}. + +\bibitem{Bslides} +M.~Bouras, \emph{The distribution of prime numbers and continued fractions}, slides, Zenodo, 2024 (version~v10 of a record dated 2022), \url{https://doi.org/10.5281/zenodo.10992128}. + +\bibitem{Barxiv} +M.~Bouras, \emph{A new primes-generating sequence}, arXiv:2509.09745 [math.GM], 2025. + +\bibitem{Cloitre} +B.~Cloitre, \emph{On the sequence A356247}, 2025, note attached to OEIS A356247, \url{https://oeis.org/A356247/a356247_1.pdf}. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171 [cs.AI], 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{APN} +Google DeepMind, \emph{AlphaProof Nexus results}, \url{https://github.com/google-deepmind/alphaproof-nexus-results}. + +\bibitem{M0A362086} +math0, \emph{Apart from $9$, every denominator of $1/(2-3/(3-4/(\cdots(n-1)-n/(-3))))$ is $1$ or a prime}, manuscript and Lean proof, 2026, \url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a362086}. + +\bibitem{M0A363482} +math0, \emph{Apart from $49$, every denominator of $1/(2-3/(3-4/(\cdots(n-1)-n/(-5))))$ is $1$ or a prime}, manuscript and Lean proof, 2026, \url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a363482}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Tsoukalas} +G.~Tsoukalas et al., \emph{Advancing mathematics research with AI-driven formal proof search}, arXiv:2605.22763 [cs.AI], 2026. + +\bibitem{A003422} +The OEIS Foundation Inc., \url{https://oeis.org/A003422} (left factorials). + +\bibitem{A051403} +The OEIS Foundation Inc., \url{https://oeis.org/A051403}. + +\bibitem{A104275} +The OEIS Foundation Inc., \url{https://oeis.org/A104275}. + +\bibitem{A145737} +The OEIS Foundation Inc., \url{https://oeis.org/A145737}. + +\bibitem{A356247} +The OEIS Foundation Inc., \url{https://oeis.org/A356247}, entry by M.~Bouras (2022). + +\bibitem{A356360} +The OEIS Foundation Inc., \url{https://oeis.org/A356360}, entry by M.~Bouras (2022). + +\bibitem{A362086} +The OEIS Foundation Inc., \url{https://oeis.org/A362086}, entry by M.~Bouras (2023). + +\bibitem{A363102} +The OEIS Foundation Inc., \url{https://oeis.org/A363102}, entry by M.~Bouras (2023). + +\bibitem{A363347} +The OEIS Foundation Inc., \url{https://oeis.org/A363347}, entry by M.~Bouras (2023). + +\bibitem{A363482} +The OEIS Foundation Inc., \url{https://oeis.org/A363482}, entry by M.~Bouras (2023). + +\bibitem{A369797} +The OEIS Foundation Inc., \url{https://oeis.org/A369797}, entry by M.~Bouras (2024). + +\bibitem{A370726} +The OEIS Foundation Inc., \url{https://oeis.org/A370726}, entry by M.~Bouras (2024). + +\bibitem{A372761} +The OEIS Foundation Inc., \url{https://oeis.org/A372761}, entry by M.~Bouras (2024). + +\bibitem{A372763} +The OEIS Foundation Inc., \url{https://oeis.org/A372763}, entry by M.~Bouras (2024). + +\end{thebibliography} + +\end{document} diff --git a/results/oeis-a357216/README.md b/results/oeis-a357216/README.md new file mode 100644 index 0000000..14de883 --- /dev/null +++ b/results/oeis-a357216/README.md @@ -0,0 +1,47 @@ +# Internal n-gons in a regular n-gon: triple points occur only for n = 3, 4, 6, and otherwise there are n k^2 + 1 regions (Shannon's A357216 conjecture) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A357216 +**Date:** 2026-10-18 + +## Result + +Take the regular n-gon with vertices V_j = exp(2πij/n). Divide each side into k+1 equal parts. For m = 1..k, the m-th internal n-gon joins the m-th division points of consecutive sides. Its side (j, m-1) is the segment from the m-th division point of side j to the m-th division point of side j+1. The statement has two parts. +(1) For n >= 3, some k gives a point lying on three distinct drawn sides if and only if n is 3, 4 or 6. +(2) For n = 5 and for every n >= 7 and every k >= 0, the open polygon minus all n*k drawn sides has exactly n*k^2 + 1 connected components. + +## Assessment + +The proof first notes that two chords can only cross if they cut off the same corner or adjacent corners. So any triple point involves just four consecutive vertices, and in an affine frame these depend only on u = 2cos(2*pi/n). With every chord parameter rational, the condition for three chords to meet is linear in u with a nonzero rational coefficient, so u would be rational, which Niven's theorem rules out for n = 5 and n >= 7. Explicit rational triple points for n = 3, 4, 6, and the standard count (a chord crossed at p distinct interior points adds p + 1 regions) giving n*k^2 + 1, complete the proof. The whole argument is about a page of elementary coordinate geometry plus a classical theorem. The long Lean file reflects the effort of formalizing the topology, not a hard mathematical idea. + +*Follows from:* Niven's theorem (cos(2*pi/n) is rational only for n = 1, 2, 3, 4, 6), combined with the Euler-formula count of regions already cited in the entry's %F line (T = edges - vertices + 1). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A357216](https://oeis.org/A357216) as [`Math0.Statements.A357216.statement`](../../lean/Math0/Statements/OEIS/A357216.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A357216.lean`](../../lean/Math0/Frontier/OEIS/A357216.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C Conjecture: the only n-gons that contain non-simple intersections are the 3-gon (triangle), 4-gon (square), and 6-gon (hexagon). %F Conjectured formula for all columns for n >= 7: T(n,k) = n*k^2 + 1. %F Conjectured formula for all rows except for n = 3, 4, 6: T(n,k) = n*k^2 + 1. (Scott R. Shannon, Sep 18 2022; the same conjecture appears in A357235 (vertices n*k^2+n) and A357254 (edges 2n*k^2+n)) + +Referees: I found no prior resolution. The OEIS entries A357216, A357235 and A357254 (Scott R. Shannon, Sep 2022, last revised Sep 21 2022, no %E lines) still list both claims as conjectures, in the local mirror and the current GitHub oeisdata. The related entries for the triangle (A356984, with Talmon Silver's classification for n = 3 only), the square (A357058) and the hexagon (A357196) give no general proof. arXiv API searches for "A357216" and "internal n-gons" returned nothing. Web searches covering MathOverflow, Math StackExchange, SeqFan and Google-Scholar-style queries found only the OEIS entries themselves. Sela Fried, "Proofs of some Conjectures from the OEIS" (arXiv:2410.07237) is unrelated. The key tool, Niven's theorem (cos(2*pi/n) is rational only for n = 1, 2, 3, 4, 6), is classical. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a357216, + author = {{math0}}, + title = {{Internal n-gons in a regular n-gon: triple points occur only for n = 3, 4, 6, and otherwise there are n k^2 + 1 regions (Shannon's A357216 conjecture)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a357216}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a357216/paper.pdf b/results/oeis-a357216/paper.pdf new file mode 100644 index 0000000..3fed000 Binary files /dev/null and b/results/oeis-a357216/paper.pdf differ diff --git a/results/oeis-a357216/paper.tex b/results/oeis-a357216/paper.tex new file mode 100644 index 0000000..4391df6 --- /dev/null +++ b/results/oeis-a357216/paper.tex @@ -0,0 +1,322 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℂ}{{$\mathbb{C}$}}1 {ℕ}{{$\mathbb{N}$}}1 {ℝ}{{$\mathbb{R}$}}1 {ℤ}{{$\mathbb{Z}$}}1 + {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {→}{{$\to$}}1 {↔}{{$\leftrightarrow$}}1 + {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {∈}{{$\in$}}1 + {×}{{$\times$}}1 {⋃}{{$\bigcup$}}1 {¬}{{$\neg$}}1 {…}{{$\ldots$}}1 + {₁}{{$_1$}}1 {₂}{{$_2$}}1 {₃}{{$_3$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\C}{\mathbb{C}} +\newcommand{\re}{\operatorname{Re}} +\newcommand{\im}{\operatorname{Im}} + +\title[Internal $n$-gons in a regular $n$-gon (OEIS A357216)]{Internal $n$-gons in a regular $n$-gon: three sides are concurrent only for $n=3,4,6$, and otherwise there are $nk^2+1$ regions} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Divide each side of a regular $n$-gon into $k+1$ equal parts and, for $\mu=1,\dots,k$, join the $\mu$-th division points of consecutive sides; this draws $k$ internal $n$-gons. We prove the two conjectures that S.~R. Shannon stated in 2022 in OEIS A357216: for $n\ge3$, some $k$ produces a point lying on three of the $nk$ drawn sides if and only if $n\in\{3,4,6\}$; and for $n=5$ and every $n\ge7$ the drawing cuts the polygon into exactly $nk^2+1$ regions, for every $k\ge0$. A point on three sides would force a relation $\alpha W+\beta=0$ with rational $\alpha\ne0$, $\beta$, where $W=1+2\cos(2\pi/n)$, which Niven's theorem excludes for $n=5$ and $n\ge7$. To our knowledge the result is new; both conjectures are still listed as open in the OEIS. The proof is checked in Lean~4 with Mathlib against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before any proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +Let $n\ge3$ and $k\ge0$. Divide each side of a regular $n$-gon into $k+1$ equal parts. For $\mu=1,\dots,k$ the $\mu$-th division points of the $n$ sides are the vertices of a smaller regular $n$-gon, the $\mu$-th \emph{internal $n$-gon}. The OEIS entry A357216 \cite{A357216}, contributed by Scott R.~Shannon on September~18, 2022, tabulates the number $T(n,k)$ of regions into which the $k$ internal $n$-gons cut the outer one; A357235 \cite{A357235} and A357254 \cite{A357254} count vertices and edges, and the rows $n=3,4,6$ are A356984, A357058 and A357196 \cite{A356984,A357058,A357196}. Shannon's extended table covers $3\le n\le 50$, $0\le k\le75$. If no three drawn segments pass through a common point, Euler's formula gives $nk^2+1$ regions; for $n=3,4,6$ the table falls below this value (for example $T(3,5)=70<76$, $T(4,5)=93<101$, $T(6,9)=475<487$). The three entries conjecture that only the triangle, the square and the hexagon have such \emph{non-simple intersections}, and A357216 conjectures $T(n,k)=nk^2+1$ for all other $n$. We prove both conjectures (Theorem~\ref{thm:main}); the main tool is Niven's theorem \cite{Niven}. + +\subsection*{Status and prior work} +A357216, A357235 and A357254 (last revised September~21, 2022) state the conjectures with no report of a proof. A356984 contains Talmon Silver's classification of the intersection points for the triangle only; A357058 and A357196 list values of $k$ that give non-simple intersections for the square (the even ones) and the hexagon, without a general argument. The math0 referees' searches (arXiv, MathOverflow, Mathematics Stack Exchange, SeqFan, the web) found only the OEIS entries, and the conjectures are not in formal-conjectures \cite{FC}. We therefore classify the result as \emph{new}; the argument is short and may exist somewhere unrecorded. + +\section{Statement}\label{sec:statement} + +Throughout, $n\ge3$, $k\ge0$, indices of vertices are taken modulo $n$, and +\[ +V_j=e^{2\pi i j/n},\qquad D_{j,\mu}=V_j+\tfrac{\mu}{k+1}\,(V_{j+1}-V_j),\qquad t_\mu=\tfrac{\mu}{k+1}. +\] +The polygon is $P=\operatorname{conv}\{V_0,\dots,V_{n-1}\}\subset\C=\mathbb{R}^2$ and $U=\operatorname{int}P$. For $0\le j= 7: T(n,k) = n*k\^{}2 + 1.}\\ +\texttt{Conjectured formula for all rows except for n = 3, 4, 6: T(n,k) = n*k\^{}2 + 1.} +\end{quote} +all by Scott R.~Shannon, September~18, 2022. + +\begin{theorem}\label{thm:main} +(1) For $n\ge3$, some $k\ge0$ admits a point lying on three distinct chords if and only if $n\in\{3,4,6\}$. +(2) If $n=5$ or $n\ge7$, then for every $k\ge0$ the set $U\setminus\bigcup_{j,\mu}C_{j,\mu}$ has exactly $nk^2+1$ connected components. +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A357216.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{0b6d1419\ldots 2635391}) before any proof attempt. Its geometric definitions and the statement are, verbatim except that docstrings are omitted: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +namespace Math0.Statements.A357216 +noncomputable def vertex (n j : ℕ) : ℂ := Complex.exp (2 * Real.pi * Complex.I * j / n) +noncomputable def divPt (n k j m : ℕ) : ℂ := + vertex n j + ((m : ℂ) / ((k : ℂ) + 1)) * (vertex n (j + 1) - vertex n j) +noncomputable def chord (n k : ℕ) (c : Fin n × Fin k) : Set ℂ := + segment ℝ (divPt n k (c.1 : ℕ) ((c.2 : ℕ) + 1)) (divPt n k ((c.1 : ℕ) + 1) ((c.2 : ℕ) + 1)) +noncomputable def polygon (n : ℕ) : Set ℂ := + convexHull ℝ (Set.range fun j : Fin n => vertex n j) +noncomputable def regionSet (n k : ℕ) : Set ℂ := + interior (polygon n) \ ⋃ c : Fin n × Fin k, chord n k c +noncomputable def regions (n k : ℕ) : ℕ := + Nat.card (ConnectedComponents (regionSet n k)) +def HasNonSimpleIntersection (n k : ℕ) : Prop := + ∃ p : ℂ, ∃ c₁ c₂ c₃ : Fin n × Fin k, c₁ ≠ c₂ ∧ c₁ ≠ c₃ ∧ c₂ ≠ c₃ ∧ + p ∈ chord n k c₁ ∧ p ∈ chord n k c₂ ∧ p ∈ chord n k c₃ +def statement : Prop := + (∀ n : ℕ, 3 ≤ n → ((∃ k : ℕ, HasNonSimpleIntersection n k) ↔ (n = 3 ∨ n = 4 ∨ n = 6))) ∧ + (∀ n k : ℕ, (n = 5 ∨ 7 ≤ n) → regions n k = n * k ^ 2 + 1) +\end{lstlisting} +\emph{Encoding.} \texttt{vertex n j} is $V_j$, \texttt{divPt n k j m} is $D_{j,m}$, and the chord indexed by $c=(j,\mu-1)\in\texttt{Fin n}\times\texttt{Fin k}$ is $C_{j,\mu}$; since $V_n=V_0$, the chord with $j=n-1$ ends on side~$0$. \texttt{regions n k} counts the components of $U$ minus all chords, which is $T(n,k)$. \decl{HasNonSimpleIntersection} needs no interiority condition: a point on three distinct chords lies in $U$, because the only points of a chord outside $U$ are its endpoints (Lemma~\ref{lem:line}(d)) and each division point is an endpoint of only two chords (Lemma~\ref{lem:divpt}). The comment is read as an equivalence, which includes the existence of non-simple intersections for $n=3,4,6$ that the data show; the two formulas together say $T(n,k)=nk^2+1$ for $n=5$ and $n\ge7$ and all $k\ge0$. + +\emph{Data check.} The statement file also defines a computable table \decl{T} (an exact computation in $\mathbb{Z}[2\cos(2\pi/n)]$ that uses the rotational symmetry) and its antidiagonal reading \decl{a} with offset~$3$, and proves by \texttt{decide +kernel} (\decl{a_data}, about $35$ seconds of kernel time) that \decl{a} reproduces all $66$ listed terms. The identity \texttt{T n k = regions n k} is the intended meaning of \decl{T} but is \emph{not} proved in Lean; \decl{statement} does not mention \decl{T}. Outside Lean, a Python transcription of \decl{T} and a referee's floating-point computation from the geometric definition both reproduce the entry's $195$-value example table ($n\le15$, $k\le14$). + +\section{Proof}\label{sec:proof} + +\subsection{Counting components cut out by lines} + +A function $f:\C\to\mathbb{R}$ is \emph{affine} if $f(z+r(w-z))=f(z)+r(f(w)-f(z))$ for all $z,w\in\C$, $r\in\mathbb{R}$. + +\begin{proposition}[\decl{count_general}]\label{prop:count} +Let $U\subseteq\C$ be nonempty, open and convex, and let $f_0,\dots,f_{N-1}$ be continuous affine functions. Suppose that for each $i0\}$. The set $\{y\in U: f_i(y)f_i(z)>0\ \forall i0\})$. Then $\sigma_{N+1}(U_{N+1})$ is the disjoint union of $\{\sigma\cup\{N\}:\sigma\in R_+\}$ and $R_-$, of size $|R_+\cup R_-|+|R_+\cap R_-|$. If $z\in U_N$, $f_N(z)=0$ and $f_N(w)\ne0$ (by (ii)), then for small $\varepsilon$ the points $z\pm\varepsilon(w-z)$ lie in the neighbourhood of Step~1, and $f_N$ has both signs on them. Hence $R_+\cup R_-=\sigma_N(U_N)$ and $\sigma_N(U_N\cap\{f_N=0\})\subseteq R_+\cap R_-$; conversely, if $\sigma\in R_+\cap R_-$, the zero of $f_N$ on a segment joining points of the fibre of $\sigma$ with $f_N>0$ and $f_N<0$ lies in that convex fibre. So $|\sigma_{N+1}(U_{N+1})|=|\sigma_N(U_N)|+|\sigma_N(U_N\cap\{f_N=0\})|$. + +\emph{Step 3 (\decl{sgn1_count}).} By (i), $U_N\cap\{f_N=0\}=\{\gamma_N(r):00\}$ takes exactly $|Z|+1$ values on $(0,1)\setminus Z$: by the intermediate value theorem $s$ is constant on root-free intervals, in particular on $(\max Z,1)$, and this value is new, because some $c_j+rd_j$ with $d_j\ne0$ changes sign at $\max Z$. Since $\sigma_N(\gamma_N(r))=s(r)$, Step~2 adds $1+\rho_N$ components, and induction on $N$ from $|\sigma_0(U_0)|=1$ proves the claim. +\end{proof} + +\subsection{Corner frames} +Put $\varphi=\pi/n$. For a corner $V_C$, the vectors $V_{C-1}-V_C$, $V_{C+1}-V_C$ are linearly independent over $\mathbb{R}$, so every $z\in\C$ is uniquely $z=V_C+x(V_{C-1}-V_C)+y(V_{C+1}-V_C)$. The \emph{frame coordinates} $x=x_C(z)$, $y=y_C(z)$ are continuous and affine; explicitly, with $w=\overline{V_C}z$, $x+y=(1-\re w)/(1-\cos2\varphi)$ and $y-x=\im w/\sin2\varphi$ (\decl{fx}, \decl{fy}, \decl{recon}). Put +\[ +X(a)=\frac{\sin(a\varphi)\sin((a-1)\varphi)}{\sin\varphi\,\sin2\varphi},\quad +Y(a)=\frac{\sin(a\varphi)\sin((a+1)\varphi)}{\sin\varphi\,\sin2\varphi},\quad W=1+2\cos\tfrac{2\pi}{n}. +\] + +\begin{lemma}[\decl{fx_vertex}, \decl{XY_range}, \decl{Y_pos_range}]\label{lem:frame} +(1) For every integer $a$, $x_C(V_{C+a})=X(a)$ and $y_C(V_{C+a})=Y(a)$; $X$ and $Y$ have period $n$. +(2) $(X,Y)$ equals $(0,0)$, $(0,1)$, $(1,0)$, $(1,W)$, $(W,1)$ at $a=0,1,-1,2,-2$. +(3) If $a\not\equiv0\pmod n$ then $X(a),Y(a)\ge0$ and $X(a)+Y(a)\ge1$; if also $a\not\equiv-1$, then $Y(a)>0$. In particular $W\ge0$, and $Y(a)\ge0$ for all $a$. +\end{lemma} + +\begin{proof} +(1) For $w=e^{2ia\varphi}$, double-angle formulas give $x+y=\sin^2(a\varphi)/\sin^2\varphi$ and $y-x=\sin(2a\varphi)/\sin2\varphi$, and sum-to-product formulas give the same for $X(a)+Y(a)$ and $Y(a)-X(a)$. Replacing $a$ by $a+n$ flips the sign of two sine factors. (2) is direct; for $a=\pm2$ note $\sin3\varphi/\sin\varphi=3-4\sin^2\varphi=1+2\cos2\varphi$. (3) By periodicity assume $1\le a\le n-1$. Then $a\varphi\in[\varphi,\pi-\varphi]$ and $(a\pm1)\varphi\in[0,\pi]$, so all sines are $\ge0$, $\sin(a\varphi)\ge\sin\varphi>0$, and $X+Y=\sin^2(a\varphi)/\sin^2\varphi\ge1$. If $a\le n-2$ then $(a+1)\varphi<\pi$ and $Y(a)>0$. Finally $W=X(-2)$. +\end{proof} + +\begin{lemma}[\decl{polygon_sub}, \decl{interior_pos}, \decl{tri_interior}]\label{lem:polygon} +For every corner $C$: (a) $P\subseteq\{x_C\ge0,\ y_C\ge0\}$; (b) $x_C(z)>0$ and $y_C(z)>0$ for $z\in U$; (c) $\{x_C>0,\ y_C>0,\ x_C+y_C<1\}\subseteq U$. In particular $U$ is a nonempty open convex set. +\end{lemma} + +\begin{proof} +(a) The vertices satisfy the inequalities by Lemma~\ref{lem:frame}, and the right side is convex. (b) $x_C(z+e(V_C-V_{C-1}))=x_C(z)-e$, and for small $e>0$ this point is in $P$, so $x_C(z)\ge e$ by (a); similarly for $y_C$ with $V_C-V_{C+1}$. (c) Such a point is $(1-x-y)V_C+xV_{C-1}+yV_{C+1}\in P$, and the set is open. +\end{proof} + +\subsection{Chords and their lines} +Fix $k$ and a chord $c=(j,\mu)$, $t=t_\mu\in(0,1)$. By Lemma~\ref{lem:frame}(2), in the frame at the corner $V_{j+1}$ the endpoints $D_{j,\mu}$, $D_{j+1,\mu}$ have coordinates $(1-t,0)$ and $(0,t)$, so $\gamma_c(r)=D_{j,\mu}+r(D_{j+1,\mu}-D_{j,\mu})$ has coordinates $((1-t)(1-r),\,tr)$ and lies on the zero set of the affine function +\[ +F_c(z)=t\,x_{j+1}(z)+(1-t)\,y_{j+1}(z)-t(1-t). +\] + +\begin{lemma}[\decl{gam_interior}, \decl{line_inter}, \decl{mem_chord_iff}]\label{lem:line} +(a) $\gamma_c(r)\in U$ for $00$; put $r=y/t>0$; then $F_c(z)=0$ gives $x=(1-t)(1-r)$, so $r<1$, and $z=\gamma_c(r)$ because frame coordinates determine the point. (c) and (d) follow. +\end{proof} + +For a second chord $e=(j',\mu')$ with $s=t_{\mu'}$ put $\Phi_{c,e}(r)=F_e(\gamma_c(r))$. Since $W\ge0$, the numbers +\[ +a(s,t)=(1-t)\bigl(sW+(1-s)^2\bigr)+ts^2,\qquad b(s,t)=(1-t)(1-s)^2+t\bigl(s^2+(1-s)W\bigr) +\] +are positive for $s,t\in(0,1)$ (\decl{aP_pos}, \decl{bM_pos}). + +\begin{lemma}[\decl{pair_same}, \decl{pair_next}, \decl{pair_prev}, \decl{pair_far}]\label{lem:pairs} +For $0\le r\le1$: +(a) if $j'=j$, then $\Phi_{c,e}(r)=(t-s)(r-s)$; +(b) if $j'\equiv j+1$, then $\Phi_{c,e}(r)=(1-r)\,a(s,t)+r\,s(s-t)$; +(c) if $j\equiv j'+1$, then $\Phi_{c,e}(r)=(1-r)(1-s)(t-s)+r\,b(s,t)$; +(d) otherwise $\Phi_{c,e}(r)>0$. +\end{lemma} + +\begin{proof} +Let $G(a)=F_e(V_{j'+1+a})=sX(a)+(1-s)Y(a)-s(1-s)$. Since $\gamma_c(r)=(1-r)[(1-t)V_j+tV_{j+1}]+r[(1-t)V_{j+1}+tV_{j+2}]$ and $F_e$ is affine, +\[ +\Phi_{c,e}(r)=(1-r)\bigl[(1-t)G(\delta-1)+tG(\delta)\bigr]+r\bigl[(1-t)G(\delta)+tG(\delta+1)\bigr],\qquad \delta=j-j' +\] +(\decl{Fl_gam_master}). By Lemma~\ref{lem:frame}(2), $G(-2)=sW+(1-s)^2$, $G(-1)=s^2$, $G(0)=-s(1-s)$, $G(1)=(1-s)^2$, $G(2)=s^2+(1-s)W$, and substitution gives (a)--(c). In case (d), $\delta-1,\delta,\delta+1\not\equiv0$, and for $a\not\equiv0$ Lemma~\ref{lem:frame}(3) gives $G(a)\ge\min(s,1-s)(X(a)+Y(a))-s(1-s)\ge\min(s,1-s)-s(1-s)>0$. +\end{proof} + +\begin{corollary}[\decl{cls}]\label{cor:cls} +If $c\ne e$, $0t$, and $(1-r)(1-s)(t-s)+rb(s,t)=0$. +\end{corollary} + +\begin{proof} +In case (a) of Lemma~\ref{lem:pairs}, $t\ne s$ because $\mu\ne\mu'$. In case (b) with $s\ge t$, and in case (c) with $s\le t$, $\Phi_{c,e}(r)>0$. Case (d) is excluded. +\end{proof} + +\subsection{\texorpdfstring{No triple points for $n=5$ and $n\ge7$}{No triple points for n = 5 and n >= 7}} + +\begin{lemma}[\decl{W_irr}, \decl{I1}, \decl{I2}]\label{lem:irr} +Let $n=5$ or $n\ge7$. Then $W\notin\Q$. Consequently, for all $t,s,\rho\in\{t_1,\dots,t_k\}$, +\[ +(1-\rho)\,a(s,t)+\rho\,s(s-t)\ne0\qquad\text{and}\qquad(1-\rho)(1-s)(t-s)+\rho\,b(s,t)\ne0 . +\] +\end{lemma} + +\begin{proof} +If $W$ were rational, so would be $\cos(2\pi/n)$, and by Niven's theorem (Mathlib's \decl{niven}) it would lie in $\{0,\pm\frac12,\pm1\}$. But $\cos(2\pi/5)\in(0,\frac12)$ because $2\pi/5\in(\pi/3,\pi/2)$, and $\cos(2\pi/n)\in(\frac12,1)$ for $n\ge7$ because $2\pi/n\in(0,\pi/3)$. The two expressions are affine in $W$ with rational coefficients; the coefficients of $W$ are $(1-\rho)(1-t)s\ne0$ and $\rho t(1-s)\ne0$. If either expression vanished, $W$ would be rational. +\end{proof} + +\begin{proposition}[\decl{no_triple}]\label{prop:notriple} +Let $n=5$ or $n\ge7$. No point of $U$ is a zero of $F_{c_1}$, $F_{c_2}$, $F_{c_3}$ for three distinct chords $c_i=(j_i,\mu_i)$. +\end{proposition} + +\begin{proof} +Suppose $p$ is one, and write $t_i=t_{\mu_i}$. By Lemma~\ref{lem:line}(b), $p=\gamma_{c_1}(r_1)=\gamma_{c_2}(r_2)$ with $r_1,r_2\in(0,1)$. Apply Corollary~\ref{cor:cls} to the pairs $(c_1,c_2)$ and $(c_1,c_3)$ at $r_1$. +(S),(S): $j_2=j_3=j_1$ and $t_2=r_1=t_3$, so $c_2=c_3$. (S),(N): $r_1=t_2$ and $(1-t_2)a(t_3,t_1)+t_2t_3(t_3-t_1)=0$, contradicting Lemma~\ref{lem:irr}; the cases (S),(P), (N),(S) and (P),(S) are the same with the roles exchanged. (N),(N): $j_2=j_3\equiv j_1+1$. For the pair $(c_2,c_3)$ at $r_2$ only (S) is possible, so $r_2=t_3$; for $(c_2,c_1)$ only (P) is possible (as $n\ge3$), so $(1-t_3)(1-t_1)(t_2-t_1)+t_3b(t_1,t_2)=0$, contradicting Lemma~\ref{lem:irr}. (P),(P): symmetrically $j_2=j_3$, $r_2=t_3$, and (N) for $(c_2,c_1)$ gives $(1-t_3)a(t_1,t_2)+t_3t_1(t_1-t_2)=0$, a contradiction. (N),(P) or (P),(N): $j_3-j_2\equiv\pm2$, which is not $\equiv0,\pm1$ as $n\ge5$, so no case of Corollary~\ref{cor:cls} applies to $(c_2,c_3)$ at $r_2$. +\end{proof} + +\subsection{Part (1) of Theorem~\ref{thm:main}} + +\begin{lemma}[\decl{divPt_inj}]\label{lem:divpt} +If $D_{\sigma,\mu}=D_{\sigma',\mu'}$ with $0\le\sigma,\sigma'0$ by Lemma~\ref{lem:frame}(3): $Y(a)>0$ if $a\not\equiv-1$, and otherwise $a-1\equiv-2\not\equiv0,-1$ and $Y(a-1)>0$. So $\sigma=\sigma'$, and $x(D_{\sigma,\mu})=1-\mu/(k+1)$ gives $\mu=\mu'$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}(1)] +Let $n\ge3$, $n\notin\{3,4,6\}$, so $n=5$ or $n\ge7$, and suppose $p$ lies on three distinct chords $c_i=(j_i,\mu_i)$ (\decl{no_nonsimple}). If $p\in U$, then $F_{c_i}(p)=0$ by Lemma~\ref{lem:line}(c), contradicting Proposition~\ref{prop:notriple}. Otherwise, by Lemma~\ref{lem:line}(d), $p=D_{\sigma_i,\mu_i}$ with $\sigma_i\in\{j_i,j_i+1\}$ for each $i$. By Lemma~\ref{lem:divpt} all $\mu_i$ are equal and all $\sigma_i$ equal one $\sigma$; then the $j_i$ are pairwise distinct elements of $\{\sigma,\sigma-1\}$, which is impossible. + +Conversely (\decl{triple_exists}): if $\mu_1\ne\mu_2$ and $(1-t_{\mu_2})a(t_{\mu_3},t_{\mu_1})+t_{\mu_2}t_{\mu_3}(t_{\mu_3}-t_{\mu_1})=0$, then $p=\gamma_{(0,\mu_1)}(t_{\mu_2})\in U$ lies on $C_{0,\mu_1}$, on $C_{0,\mu_2}$ by Lemma~\ref{lem:pairs}(a) and on $C_{1,\mu_3}$ by Lemma~\ref{lem:pairs}(b), using Lemma~\ref{lem:line}(c). Here $W=0,1,2$ for $n=3,4,6$, and the equation holds for +\begin{center} +\begin{tabular}{cccccc} +$n$ & $k$ & $(\mu_1,\mu_2,\mu_3)$ & $(t_{\mu_1},t_{\mu_2},t_{\mu_3})$ & $a(t_{\mu_3},t_{\mu_1})$ & $t_{\mu_3}(t_{\mu_3}-t_{\mu_1})$\\\hline +$3$ & $5$ & $(3,5,2)$ & $(1/2,\,5/6,\,1/3)$ & $5/18$ & $-1/18$\\ +$4$ & $5$ & $(4,5,3)$ & $(2/3,\,5/6,\,1/2)$ & $5/12$ & $-1/12$\\ +$6$ & $9$ & $(5,9,2)$ & $(1/2,\,9/10,\,1/5)$ & $27/50$ & $-3/50$ +\end{tabular} +\end{center} +as $\frac16\cdot\frac5{18}=\frac56\cdot\frac1{18}$, $\frac16\cdot\frac5{12}=\frac56\cdot\frac1{12}$, $\frac1{10}\cdot\frac{27}{50}=\frac9{10}\cdot\frac3{50}$ (\decl{triple3}, \decl{triple4}, \decl{triple6}). +\end{proof} + +\subsection{Part (2) of Theorem~\ref{thm:main}} +Let $n=5$ or $n\ge7$. Order the chords by $i=n(\mu-1)+j$, $0\le i0$ in case (b) and positive in case (d), and $\Phi_{c,e}(1)=b(s,t)>0$ in case (c). + +\begin{lemma}[\decl{roots_count}]\label{lem:roots} +For the chord $c=(j,\mu)$ with index $i$, $\rho_i=2(\mu-1)$. +\end{lemma} + +\begin{proof} +An earlier chord $e=(j',\mu')$ has $\mu'\le\mu$. By Corollary~\ref{cor:cls}, its line meets $\gamma_c((0,1))$ only in case (S), at $r=t_{\mu'}$ with $\mu'<\mu$, or in case (N), with $j'\equiv j+1$ and $\mu'<\mu$, at the unique root $r=a/(a+s(t-s))\in(0,1)$ of the affine function in (N); case (P) needs $\mu'>\mu$. Conversely all chords $(j,\mu')$ and $(j+1,\mu')$ with $\mu'<\mu$ are earlier (their indices are $=1} s(j) z^j be its convolution triangle. Define polynomials R(n,k) in Z[x] by R(1,k) = s(k) and R(n,k) = R(n-1,k+1) + x*R(n-1,1)*R(1,k) for n > 1. Then for every n > 0 the row polynomial sum_{k=0}^{n} T_s(n,k) x^k equals x*R(n,1). In particular (s = Bell numbers) the row polynomials of A357583 are x*R(n,1) with R(1,k) = Bell(k). Both parts of the frozen statement (the Bell case and the case of an arbitrary integer sequence) are proved. + +## Assessment + +The proof guesses the closed form R(n,k) = sum_j s(k+j) E(n-1-j), where E(n) are the row polynomials, and checks it by a one-line induction. The step uses only the standard recursion E(n) = x*sum_j s(j) E(n-j), which is just the row generating function 1/(1 - xA(z)) of a convolution triangle. Setting k = 1 then gives x*R(n,1) = E(n) at once. A competent mathematician would find this in well under a page, and the general-sequence case is no harder than the Bell case, so the result is routine even though the conjecture had stood open on OEIS. + +*Follows from:* The standard bivariate generating function of a convolution (Riordan/PMatrix) triangle, sum_n E_n(x) z^n = 1/(1 - x A(z)) with A(z) = sum_{j>=1} s(j) z^j, which gives the row-polynomial recursion E(n) = x * sum_j s(j) E(n-j). That recursion is the PMatrix construction of A357368, and the referee notes record P(n,x) = x*sum a(n-k) P(k,x) there. Unrolling Kurkov's recursion gives the closed form R(n,k) = sum_{j=0}^{n-1} s(k+j) E(n-1-j). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A357583](https://oeis.org/A357583) as [`Math0.Statements.A357583.statement`](../../lean/Math0/Statements/OEIS/A357583.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A357583.lean`](../../lean/Math0/Frontier/OEIS/A357583.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: row polynomials are x*R(n,1) for n > 0 where R(n,k) = R(n-1,k+1) + x*R(n-1,1)*R(1,k) for n > 1, k > 0 with R(1,k) = Bell(k) for k > 0. The same recursion seems to work for self-convolution of any other sequence. - _Mikhail Kurkov_, Apr 05 2025 + +Referees: I found no prior resolution. +- The OEIS entries A357583 and A340991 are unchanged upstream since Apr 06 2025 (#10 and #24) and still say "Conjecture" (Mikhail Kurkov, Apr 05 2025). +- A357368, by P. Luschny, defines the convolution-triangle (PMatrix) terminology and gives the row-polynomial recursion P(n,x)=x Σ a(n-k) P(k,x), but not Kurkov's R recursion. +- Kurkov's sibling conjectures of the same shape are still open on OEIS: A350499, A263634, A356145, A055356. +- Neither entry is in google-deepmind/formal-conjectures, which is the corpus behind the Tsoukalas et al. dataset and Epoch's OEIS Open benchmark (arXiv 2608.11941). +- Sela Fried's arXiv 2607.24832 and 2410.07237 do not mention either entry. +- Searches of arXiv, MathOverflow and GitHub (including the-omega-institute/trureturing) found nothing on this recursion. + +Relevant background: D. E. Knuth, "Convolution polynomials" (arXiv:math/9207221), on the convolution-triangle framework. + +## Citation + +```bibtex +@misc{math0:oeis-a357583, + author = {{math0}}, + title = {{Kurkov's recursion for the row polynomials of convolution triangles holds}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a357583}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a362086/README.md b/results/oeis-a362086/README.md new file mode 100644 index 0000000..9d4aba7 --- /dev/null +++ b/results/oeis-a362086/README.md @@ -0,0 +1,51 @@ +# OEIS A362086: every denominator of 1/(2-3/(3-4/(...(n-1)-n/(-3)))) except 9 is 1 or a prime + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Number theory +**Source problem:** OEIS A362086 +**Date:** 2026-10-18 + +## Result + +For n >= 3 let a(n) be the reduced denominator of 1/(2 - 3/(3 - 4/(4 - ... ((n-1) - n/(-3))))), evaluated in Q from the inside out. Then for every n >= 3 with a(n) != 9, a(n) is 1 or a prime. (Mohammed Bouras's conjecture; the value 9 occurs at n = 5.) + +## Assessment + +The closed form for the unreduced fraction is essentially the gcd formula already listed in the entry. It reduces the denominator to N/gcd(N, 3(n-1)(n-3)!) with N = n^2+n-3, which is roughly n^2. The rest is the standard template from the solved sibling sequences: a prime p up to n-3 that survives in the denominator must divide N to a higher power than it divides (n-3)!, and this is impossible because of size, apart from a small N = 3p^2 case. Prime factors above n must be at least n+1, so at most one fits, and the cases n < 36 are a finite check. The argument is about a page and a direct adaptation of known proofs, with no new idea, so it is routine. + +*Follows from:* The entry's own formula a(n) = (n^2+n-3)/gcd(n^2+n-3, 3*A051403(n-3) + n*A051403(n-4)), with A051403 written in left factorials (its %F), combined with the factorial-valuation and size argument already used for the sibling conjectures A363102 (Adamczewski, arXiv:2608.11941, Appendix A), A356247 (Cloitre) and A363482. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A362086](https://oeis.org/A362086) as [`Math0.Statements.A362086.statement`](../../lean/Math0/Statements/OEIS/A362086.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A362086.lean`](../../lean/Math0/Frontier/OEIS/A362086.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: Except for 9, every term of this sequence is either a prime or 1. (Mohammed Bouras, May 28 2023) + +Referees: OEIS A362086 (local mirror, revision #35, May 09 2024): "Conjecture: Except for 9, every term of this sequence is either a prime or 1." No proof is recorded. Related prior work, none of which settles A362086: +- M. Bouras, "A New Primes-Generating Sequence", arXiv:2509.09745 (2025). Lists A362086 in its Table 1 family; the primality property is stated only as a conjecture. +- B. Cloitre, "On the sequence A356247" (2025), OEIS attachment a356247_1.pdf. Proves Conjectures 1-3 for the innermost -1 analogue, A356247. +- T. Adamczewski, "OEIS Open: How many conjectures can language models turn into theorems?", arXiv:2608.11941 (2026), together with the AlphaProof Nexus Lean files oeis_363347_conjecture_2.lean and oeis_a363102_conjecture_1.lean. Proves the analogues for innermost -2 (A363102) and -4 (A363347). +A362086 appears in neither the alphaproof-nexus-results repository nor the epoch-research LeanOpenProblems and LeanOpenProblems-results repositories. Searches of arXiv, MathOverflow and Math StackExchange found no proof or counterexample. + +Reading note (fidelity pass, 29 Oct 2026): the statement exempts every term equal to 9. Read strictly, the conjecture exempts only the single term a(5) = 9, which also needs the value 9 to occur only once. That holds for n < 1200 by exact computation but is not part of the Lean result. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a362086, + author = {{math0}}, + title = {{OEIS A362086: every denominator of 1/(2-3/(3-4/(...(n-1)-n/(-3)))) except 9 is 1 or a prime}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a362086}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a362086/paper.pdf b/results/oeis-a362086/paper.pdf new file mode 100644 index 0000000..e8b9b82 Binary files /dev/null and b/results/oeis-a362086/paper.pdf differ diff --git a/results/oeis-a362086/paper.tex b/results/oeis-a362086/paper.tex new file mode 100644 index 0000000..118a0bc --- /dev/null +++ b/results/oeis-a362086/paper.tex @@ -0,0 +1,407 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,by_cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {→}{{$\to$}}1 {∨}{{$\vee$}}1 {¬}{{$\neg$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1 {…}{{$\ldots$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{…}{\ensuremath{\ldots}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\lf}{\mathop{!}} +\DeclareMathOperator{\den}{den} +\DeclareMathOperator{\cf}{cf} + +\title[Denominators of a continued fraction (OEIS A362086)]{Apart from $9$, every denominator of $1/(2-3/(3-4/(\cdots(n-1)-n/(-3))))$ is $1$ or a prime} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +For $n\ge3$ let $a(n)$ be the denominator, in lowest terms, of the finite continued fraction $1/(2-3/(3-4/(\cdots(n-1)-n/(-3))))$; this is the OEIS sequence A362086. +We prove the conjecture of M.~Bouras (2023) that every term other than $9$ is $1$ or a prime, and the argument shows that $a(5)=9$ is the only composite term. +The proof derives the closed form $a(n)=N/\gcd\bigl(N,3(n-1)(n-3)!\bigr)$ with $N=n^2+n-3$ from the convergents of the continued fraction, studies the least prime factor of $a(n)$ for $n\ge36$, and reads off the cases $n\le35$ from the listed terms. +To our knowledge this is a new result: the entry records the conjecture without a proof, the analogous conjectures for the endpoints $-1$, $-2$, $-4$ and $-5$ were settled earlier, and our argument adapts the one used for the endpoint $-5$. +The proof is verified in Lean~4 against a statement that math0 formalized from the OEIS entry and checked against its $57$ listed terms; the statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +In 2022--2023 M.~Bouras contributed to the OEIS five sequences of denominators of the finite continued fractions $1/(2-3/(3-4/(\cdots(n-1)-n/(-c))))$, $c=1,\dots,5$: A356247, A363102, A362086, A363347 and A363482 \cite{A356247,A363102,A362086,A363347,A363482}. By the formulas in these entries the unreduced denominator is $n^2+(c-2)n-c$, and each entry conjectures that the reduced denominators are $1$ or prime, with at most one exceptional value; see also \cite{Bslides,Barxiv}. +For $c=3$ the unreduced denominator is $N=n^2+n-3$, and the entry A362086, created by Bouras on May~28, 2023, states: ``Conjecture: Except for 9, every term of this sequence is either a prime or 1.'' +We prove this conjecture (Theorem~\ref{thm:main}); we do not address the entry's further conjecture, due to B.~McEachen, on record values. + +\subsection*{Prior work} +For $c=1$, the conjectures of A356247 are proved in a note of B.~Cloitre \cite{Cloitre}, according to a 2025 comment in that entry. +For $c=2$, the conjecture that A363102 contains only $1$'s and primes is marked as solved in the formal-conjectures repository \cite{FC}, with a formal proof found by the methods of Tsoukalas et al.\ \cite{Tsoukalas}; T.~Adamczewski gives a proof sketch in \cite[Appendix~A]{Ad}, and the AlphaProof Nexus outputs \cite{APN} contain a Lean file for it. +For $c=4$, Conjectures~1 and~2 of A363347 were proved by an AI agent (AlphaProof Nexus) \cite{APN}; see also \cite[Appendix~A]{Ad}. Conjecture~2 of A363347 is also marked as solved in formal-conjectures \cite{FC}, with a formal proof found by the methods of \cite{Tsoukalas}. +For $c=5$, the conjecture of A363482 (exceptional value $49$) was proved, with a Lean proof, in the math0 project \cite{M0A363482}. + +For $c=3$ the math0 referees found no proof. The current revision of A362086 (\#35, May~9, 2024) records the conjecture but no proof, and Bouras's preprint \cite{Barxiv} lists A362086 in the family $n^2+(k-2)n-k$ of its Table~1 and states the primality property only as a conjecture. The sequence has no file in formal-conjectures \cite{FC} (at the pinned commit \texttt{c77fdd4}), and the referees found it neither among the AlphaProof Nexus outputs \cite{APN} nor in Epoch AI's LeanOpenProblems repositories. Searches of arXiv, MathOverflow and Mathematics Stack Exchange found no proof or counterexample. +We therefore classify Theorem~\ref{thm:main} as a \emph{new result}, with two caveats. First, the method is not new: the proof is an adaptation of the math0 proof for $c=5$ \cite{M0A363482}, which in turn follows the template of the $c=2$ proof in \cite[Appendix~A]{Ad} (a closed form for the unreduced fraction, then bounds on the powers of small primes dividing factorials). Second, the referees could not read Cloitre's note \cite{Cloitre}, so we cannot exclude that it treats a general endpoint $-c$; the entry A356247 describes it only as a proof of that entry's conjectures, and A362086 carries no reference to it. + +\section{Statement}\label{sec:statement} + +For $q\in\Q$ we write $\den q\ge1$ for its denominator in lowest terms. + +\begin{definition}\label{def:a} +For an integer $k\ge2$ and $t\in\Q\setminus\{0\}$ put $s_k(t)=k-(k+1)/t$. For $n\ge3$ let $t_n=-3$ and $t_k=s_k(t_{k+1})$ for $k=n-1,\dots,2$, and put +\[ + \cf(n)=1/t_2=1/\bigl(2-3/(3-4/(\cdots(n-1)-n/(-3)))\bigr),\qquad a(n)=\den\cf(n). +\] +\end{definition} + +That no $t_k$ vanishes is shown in Proposition~\ref{prop:closed} (for $n=3$, $t_2=s_2(-3)=3$). For example $\cf(3)=1/3$, $\cf(4)=13/17$, $\cf(5)=13/9$ and $\cf(6)=41/13$. +The OEIS entry \cite{A362086} (offset $3$) is named ``Denominator of the continued fraction 1/(2-3/(3-4/(4-5/(...(n-1)-n/(-3)))))'', gives the first three examples, and contains the comment, verbatim, +\begin{quote} +\texttt{Conjecture: Except for 9, every term of this sequence is either a prime or 1.} +\end{quote} +which is unsigned and hence due to the author of the entry, Mohammed Bouras, May~28, 2023. + +\begin{theorem}\label{thm:main} +For every $n\ge3$ with $a(n)\ne9$, $a(n)=1$ or $a(n)$ is prime. +\end{theorem} + +\begin{corollary}\label{cor:9} +For $n\ge3$, $a(n)$ is composite if and only if $n=5$; in particular $a(n)=9$ only for $n=5$. +\end{corollary} + +So the two readings of ``Except for 9'' (an exception for the value $9$, or for the term $a(5)$) are equivalent. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A362086.lean}, reviewed for fidelity and frozen (SHA-256 prefix \texttt{e9131261}) before any proof attempt. Its definitions and statement are, verbatim except that docstrings are omitted: +\begin{lstlisting} +namespace Math0.Statements.A362086 + +def step (k : ℕ) (t : ℚ) : ℚ := (k : ℚ) - ((k : ℚ) + 1) / t + +def cf (n : ℕ) : ℚ := 1 / (List.range' 2 (n - 2)).foldr step (-3) + +def a (n : ℕ) : ℕ := (cf n).den + +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → a n ≠ 9 → a n = 1 ∨ (a n).Prime + +end Math0.Statements.A362086 +\end{lstlisting} +\texttt{step k t} is $s_k(t)$. For $n\ge3$, \texttt{List.range' 2 (n - 2)} is the list $[2,3,\dots,n-1]$, and the right fold of \decl{step} over it, starting at $-3$, is \texttt{step 2 (step 3 (...(step (n-1) (-3))))}, i.e.\ $t_2$. So \texttt{cf n} is $\cf(n)$, and \texttt{a n} is its reduced denominator \decl{Rat.den}, which is positive. This is the definition in the name of the entry, not the gcd formula listed there. The statement quantifies over $n\ge3$, the offset of the entry, and reads ``Except for 9'' as an exception for the value $9$; values of \texttt{a n} for $n<3$ are never used. +Lean defines $q/0=0$, which would change the value if some $t_k$ vanished; this never happens: $t_n=-3$, and for $n\ge4$ Proposition~\ref{prop:closed} gives $t_k\ge k-2>0$ for $3\le k\le n-1$ and $t_2>0$ (for $n=3$, $t_2=3$). The formal proof evaluates the fold under the same bounds (Lemma~\ref{lem:conv}). +The same file checks the definitions against the entry by kernel evaluation (\texttt{decide +kernel}): the theorem \decl{a_data} states that $(a(3),\dots,a(59))$ is the list $[3,17,9,13,53,\dots,367,263,131]$ of all $57$ terms in the data section of the entry, and an \texttt{example} confirms the entry's examples $\cf(3)=1/3$, $\cf(4)=13/17$, $\cf(5)=13/9$. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A362086.lean} (Section~\ref{sec:lean}). Throughout, $x=n-3\ge0$, +\[ + N=x^2+7x+9=n^2+n-3,\qquad M=3(x+2)\,x!=3(n-1)(n-3)!, +\] +and $\lf m=\sum_{i=0}^{m-1}i!$ is the left factorial (A003422 \cite{A003422}; the notation is Kurepa's \cite{Kurepa}). Thus $\lf0=0$, $\lf1=1$, $\lf2=2$ and $\lf(m+1)=\lf m+m!$; as $m!$ is even for $m\ge2$, $\lf m$ is even for every $m\ge2$. + +\subsection{Convergents and the closed form} +For $m\ge0$ define the linear polynomials +\[ + P_m(t)=2\bigl((m+2)t-(m+1)(m+3)\bigr),\qquad Q_m(t)=(m+2)\lf(m+1)\,t-(m+1)(m+3)\lf m, +\] +and, where defined, $G_m(t)=s_2(s_3(\cdots s_{m+2}(t)\cdots))$. Thus $G_0=s_2$ and $G_{m+1}(t)=G_m(s_{m+3}(t))$. + +\begin{lemma}\label{lem:step} +For $m\ge0$ and $t\ne0$, $\;t\,P_m(s_{m+3}(t))=P_{m+1}(t)$ and $t\,Q_m(s_{m+3}(t))=Q_{m+1}(t)$. +\end{lemma} + +\begin{proof} +Put $s=s_{m+3}(t)$, so $ts=(m+3)t-(m+4)$. Then +\begin{align*} + tP_m(s)&=2\bigl((m+2)((m+3)t-(m+4))-(m+1)(m+3)t\bigr)\\ + &=2\bigl((m+3)t-(m+2)(m+4)\bigr)=P_{m+1}(t),\\ + tQ_m(s)&=(m+3)\bigl[(m+2)\lf(m+1)-(m+1)\lf m\bigr]t-(m+2)(m+4)\lf(m+1)=Q_{m+1}(t), +\end{align*} +because $(m+2)\lf(m+1)-(m+1)\lf m=\lf m+(m+2)\,m!=\lf(m+1)+(m+1)!=\lf(m+2)$. +\end{proof} + +\begin{lemma}\label{lem:conv} +Let $m\ge0$ and $t\in\Q$ with $t\ge m+1$. Then $G_m(t)$ is defined, the argument of each $s_k$ $(2\le k\le m+2)$ occurring in it is at least $k-1$, $Q_m(t)>0$, and $G_m(t)=P_m(t)/Q_m(t)$. +\end{lemma} + +\begin{proof} +$Q_m$ has positive leading coefficient and $Q_m(m+1)=(m+1)\bigl[(m+2)\,m!-\lf m\bigr]>0$, since $\lf m\le m\cdot(m-1)!=m!$ for $m\ge1$ and $\lf0=0$; hence $Q_m(t)>0$. +The rest is by induction on $m$. For $m=0$, $t\ge1$ and $G_0(t)=2-3/t=(2t-3)/t=P_0(t)/Q_0(t)$, as $P_0(t)=2(2t-3)$ and $Q_0(t)=2t$. +For the step let $t\ge m+2$. Then $(m+4)/t\le(m+4)/(m+2)\le2$, so $s=s_{m+3}(t)\ge m+1$. By the induction hypothesis $G_{m+1}(t)=G_m(s)$ is defined, with the stated bounds on the arguments, and by Lemma~\ref{lem:step} +\[ + G_{m+1}(t)=\frac{P_m(s)}{Q_m(s)}=\frac{tP_m(s)}{tQ_m(s)}=\frac{P_{m+1}(t)}{Q_{m+1}(t)}.\qedhere +\] +\end{proof} + +In Lean, $P_m(t)/Q_m(t)$ is \texttt{F m t}, and Lemmas~\ref{lem:step} and~\ref{lem:conv} are \decl{F_step} and \decl{fold_eq_F}; the positivity of $Q_m$ is not needed there, as with $q/0=0$ we have $(ta)/(tb)=a/b$ for all $a,b$ when $t\ne0$. + +\begin{proposition}\label{prop:closed} +Let $x\ge1$, i.e.\ $n\ge4$. Then $t_k\ge k-2>0$ for $3\le k\le n-1$, $t_2=2N/(N\cdot{\lf x}+M)>0$, and +\[ + \cf(x+3)=\frac{N\cdot\lf x+3(x+2)\,x!}{2N}. +\] +\end{proposition} + +\begin{proof} +Let $n=x+3$ and $u=t_{n-1}=s_{x+2}(-3)=(x+2)+(x+3)/3\ge x$. Lemma~\ref{lem:conv} with $m=x-1$ gives the bounds on $t_3,\dots,t_{n-1}$ and $t_2=G_{x-1}(u)=P_{x-1}(u)/Q_{x-1}(u)$. Lemma~\ref{lem:step} with $m=x-1$ and $t=-3$ gives $-3P_{x-1}(u)=P_x(-3)$ and $-3Q_{x-1}(u)=Q_x(-3)$, and +\begin{align*} + P_x(-3)&=2\bigl(-3(x+2)-(x+1)(x+3)\bigr)=-2N,\\ + Q_x(-3)&=-3(x+2)\bigl(\lf x+x!\bigr)-(x+1)(x+3)\lf x=-\bigl(N\cdot{\lf x}+M\bigr). +\end{align*} +So $t_2=2N/(N\cdot{\lf x}+M)>0$, and $\cf(x+3)=1/t_2$ is as stated. +\end{proof} + +For $x=1,2,3$ the formula gives $26/34$, $78/54$ and $246/78$, in accordance with the examples; it also holds for $x=0$, where it gives $6/18=1/3$, but the formal proof does not need this case. +In Lean, Proposition~\ref{prop:closed} is \decl{cf_closed}, stated with $x=y+1$. + +\subsection{The reduced denominator} + +\begin{proposition}\label{prop:den} +$N$ is odd, and for $x\ge2$, $a(x+3)=N/\gcd(N,M)$. +\end{proposition} + +\begin{proof} +$N=x(x+1)+6x+9$ with $x(x+1)$ even. For $x\ge2$ both $\lf x$ and $x!$ are even, so $N\cdot{\lf x}+M=2X$ with $X\in\N$, and $\cf(x+3)=X/N$ by Proposition~\ref{prop:closed}. Hence $a(x+3)=N/\gcd(N,X)$, and since $N$ is odd, +$\gcd(N,X)=\gcd(N,2X)=\gcd(N,M+\lf x\cdot N)=\gcd(N,M)$. +\end{proof} + +In Lean these are \decl{N_odd} and \decl{a_eq}; the latter is stated for $x\ge3$, which is all that is used. +The entry also gives the formula $a(n)=N/\gcd\bigl(N,3\,A051403(n-3)+n\,A051403(n-4)\bigr)$, where $A051403(m)=(m+2)\lf(m+1)/2$ \cite{A051403}. Since $3\,A051403(x)+(x+3)\,A051403(x-1)=X$, the proof above also confirms this formula for $n\ge5$; this identification is not part of the formal proof. + +\subsection{Three arithmetic lemmas} +These lemmas are also used in \cite{M0A363482}; we include their short proofs. + +\begin{lemma}\label{lem:fact} +For integers $q\ge1$ and $k\ge0$, $q^k\mid(qk)!$. +\end{lemma} + +\begin{proof} +Induction on $k$: $(q(k+1))!=q(k+1)\cdot(qk+q-1)!$, where $q\mid q(k+1)$ and $(qk)!\mid(qk+q-1)!$. +\end{proof} + +\begin{lemma}[lifting]\label{lem:lift} +Let $N\ge1$ and $M,q\in\N$, put $g=\gcd(N,M)$ and $d=N/g$, and suppose $q\mid d$. Then for every $j\ge0$, $q^j\mid M$ implies $q^{j+1}\mid N$. +\end{lemma} + +\begin{proof} +Note $N=gd$. For $j=0$, $q\mid d\mid N$. If the claim holds for $j$ and $q^{j+1}\mid M$, then $q^j\mid M$, so $q^{j+1}\mid N$; hence $q^{j+1}\mid\gcd(N,M)=g$, and $q^{j+2}=q^{j+1}\cdot q\mid gd=N$. +\end{proof} + +\begin{lemma}\label{lem:bound} +If $q\ge3$, $j\ge3$ and $qj\ge34$, then $(qj+4)^2(3q+4)^2$. +If $j=4$ then $q\ge9$, and $q^4\ge81q^2>32q^2\ge16(q+1)^2=(4q+4)^2$. +If $j=5$ then $q\ge7$, and $q^5\ge343q^2>36q^2\ge(5q+4)^2$. +For $j\ge6$ we induct on $j$, for any $q\ge3$: $q^6\ge81q^2>64q^2\ge(6q+4)^2$, and if $(qj+4)^20$, $d\mid N$, $x!\mid M$, and +\[ + (x+3)^24N$, which is absurd. So $1\le m\le4$, and $m\ne2,4$ as $N$ is odd. If $m=1$, then $(x+3)^227$, $p\ne3$, and $3\mid M$ by the definition of $M$; since also $p\mid M$, the distinct primes $3$ and $p$ give $3p\mid M$. Also $3p\mid N$, hence $3p\mid g$; write $g=3ph$. Then $3p\cdot p=N=gd=3p\cdot hd$ gives $p=hd$, so $d\mid p$ and $d=p$ is prime. + +\emph{Case (C): $p>x$.} We have +\[ + N=(x+1)(x+6)+3,\quad N+1=(x+2)(x+5),\quad N+3=(x+3)(x+4). +\] +So if $x+i$ divided $N$ for some $i\in\{1,2,3\}$, it would divide $3$, $1$ or $3$ respectively, which is impossible as $x+1\ge34$. Hence every divisor of $N$ exceeding $x$ is at least $x+4$; in particular $p\ge x+4$. Suppose $d\ne p$, and let $r=d/p$. Then $r\ne1$, and $r\ne0$ as $d\ne0$. The least prime factor $q$ of $r$ divides $d$, so $q\ge p$ by minimality of $p$. Hence $r\ge q\ge p\ge x+4$ and $d=pr\ge(x+4)^2>N\ge d$, a contradiction. So $d=p$ is prime. +\end{proof} + +\begin{remark}\label{rem:9} +For $x=2$ ($n=5$) we have $N=27=3^3$, $M=24=2^3\cdot3$, $g=3$ and $d=9$: the least prime factor $p=3=x+1$ of $d$ exceeds $x$, and the step ``$x+1\mid3$ is impossible'' of Case~(C) fails. In Case~(B) the factor $3$ of $M$, which comes from the endpoint $-3$, is what makes the case $N=3p^2$ harmless. The threshold $x\ge33$ is chosen for convenience in Cases~(A) and~(B). +\end{remark} + +\subsection{Proof of Theorem~\ref{thm:main} and Corollary~\ref{cor:9}} +Let $n\ge3$. If $n\ge36$, then $x=n-3\ge33$, and $a(n)=N/\gcd(N,M)$ is $1$ or prime by Propositions~\ref{prop:den} and~\ref{prop:main}. If $3\le n\le35$, then $a(n)$ is one of the first $33$ entries of the list in \decl{a_data}, which equals $(a(3),\dots,a(59))$ by kernel computation; each of its $57$ entries is $9$, $1$ or a prime (the largest is $2753$). This proves Theorem~\ref{thm:main}. The only entry of the list that is neither $1$ nor prime is $a(5)=9$, which gives Corollary~\ref{cor:9}; it is not a separate Lean theorem, but follows at once from \decl{a_eq}, \decl{main} and \decl{a_data}.\qed + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is the file \path{lean/Math0/Frontier/OEIS/A362086.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A362086.result}, of type \decl{Math0.Statements.A362086.statement}. Besides the private declarations named in Section~\ref{sec:proof}, the file contains \decl{lf}, \decl{lf_succ}, \decl{two_dvd_lf} (left factorial), \decl{fold_concat} (peeling off the innermost level of the fold), \decl{pow_dvd_fact}, \decl{pow_step}, \decl{bound6}, \decl{bound} (Lemmas~\ref{lem:fact}--\ref{lem:bound}), \decl{not_dvd_aux}, \decl{main} (Proposition~\ref{prop:main}) and \decl{small} (the cases $3\le n<60$, from \decl{a_data}; only $n<36$ is used). Here \decl{main} states that $N/\gcd(N,M)$ is $1$ or prime for $x\ge33$, and the final proof reads, verbatim: +\begin{lstlisting} +theorem result : statement := by + intro n hn h9 + by_cases hsmall : n < 36 + · exact small n hn (by omega) h9 + · obtain ⟨x, rfl⟩ : ∃ x, n = x + 3 := ⟨n - 3, by omega⟩ + rw [a_eq x (by omega)] + exact main x (by omega) +\end{lstlisting} + +\subsection*{Kernel computation} +In the statement file, \decl{a_data} and the examples are proved by \texttt{decide +kernel}: the Lean kernel evaluates the continued fractions for $n=3,\dots,59$ in exact rational arithmetic and compares the reduced denominators with the $57$ OEIS terms (about $6$ seconds of kernel time). In the proof file, \decl{small} rewrites with \decl{a_data} and discharges the $57$ claims ``$v\ne9\Rightarrow v=1\lor v$ prime'' with \decl{norm_num}, whose primality extension produces proof terms that the kernel checks; the base case $2\mid\lf2$ of \decl{two_dvd_lf} is closed by \texttt{decide}. Neither file uses \texttt{native\_decide} (which would add the axiom \decl{Lean.ofReduceBool}) or \texttt{sorry}, and the proof file sets no options. + +\subsection*{Audit} +The file ends with the command \texttt{\#math0\_settles} applied to \decl{result} and \decl{statement}. This command, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (so no \decl{sorryAx}, \decl{Lean.ofReduceBool} or custom axiom); and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata annotations, with no unfolding. Running \texttt{lake env lean Math0/Frontier/OEIS/A362086.lean} in \path{lean/} prints +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A362086.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A362086.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A362086.result' proves 'Math0.Statements.A362086.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib cache, rebuilds all math0 results with \texttt{lake build} (re-running every audit command) and checks that the pinned dependencies are unmodified. + +\begin{thebibliography}{99} + +\bibitem{Ad} +T.~Adamczewski, \emph{OEIS Open: How many conjectures can language models turn into theorems?}, arXiv:2608.11941 [cs.AI], 2026. + +\bibitem{Bslides} +M.~Bouras, \emph{The distribution of prime numbers and continued fractions}, slides, 2022, \url{https://doi.org/10.5281/zenodo.10992128}. + +\bibitem{Barxiv} +M.~Bouras, \emph{A new primes-generating sequence}, arXiv:2509.09745 [math.GM], 2025. + +\bibitem{Cloitre} +B.~Cloitre, \emph{On the sequence A356247}, 2025, note attached to OEIS A356247, \url{https://oeis.org/A356247/a356247_1.pdf}. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171 [cs.AI], 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{APN} +Google DeepMind, \emph{AlphaProof Nexus results}, GitHub repository \path{google-deepmind/alphaproof-nexus-results}. + +\bibitem{Kurepa} +\DJ.~Kurepa, \emph{On the left factorial function $!n$}, Math. Balkanica \textbf{1} (1971), 147--153. + +\bibitem{M0A363482} +math0, \emph{Apart from $49$, every denominator of $1/(2-3/(3-4/(\cdots(n-1)-n/(-5))))$ is $1$ or a prime}, manuscript and Lean proof, 2026, \url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a363482}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Tsoukalas} +G.~Tsoukalas et al., \emph{Advancing mathematics research with AI-driven formal proof search}, arXiv:2605.22763 [cs.AI], 2026. + +\bibitem{A003422} +The OEIS Foundation Inc., \url{https://oeis.org/A003422} (left factorials). + +\bibitem{A051403} +The OEIS Foundation Inc., \url{https://oeis.org/A051403}. + +\bibitem{A356247} +The OEIS Foundation Inc., \url{https://oeis.org/A356247}, entry by M.~Bouras (2022). + +\bibitem{A362086} +The OEIS Foundation Inc., \url{https://oeis.org/A362086}, entry by M.~Bouras (2023). + +\bibitem{A363102} +The OEIS Foundation Inc., \url{https://oeis.org/A363102}, entry by M.~Bouras (2023). + +\bibitem{A363347} +The OEIS Foundation Inc., \url{https://oeis.org/A363347}, entry by M.~Bouras (2023). + +\bibitem{A363482} +The OEIS Foundation Inc., \url{https://oeis.org/A363482}, entry by M.~Bouras (2023). + +\end{thebibliography} + +\end{document} diff --git a/results/oeis-a363482/README.md b/results/oeis-a363482/README.md new file mode 100644 index 0000000..5411d5d --- /dev/null +++ b/results/oeis-a363482/README.md @@ -0,0 +1,59 @@ +# OEIS A363482: apart from 49, every denominator of 1/(2-3/(3-4/(...(n-1)-n/(-5)))) is 1 or a prime + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Number theory +**Source problem:** OEIS A363482 +**Date:** 2026-10-18 + +## Result + +For n >= 3 let t_n = -5 and t_k = k - (k+1)/t_{k+1} for k = n-1, ..., 2. Let a(n) be the denominator, in lowest terms, of 1/t_2 = 1/(2-3/(3-4/(...(n-1)-n/(-5)))). Then for every n >= 3, either a(n) = 49, or a(n) = 1, or a(n) is prime. This is Bouras' conjecture (2023). The value 49 occurs only at n = 6. + +## Assessment + +The closed form for the reduced denominator, a(n) = N/gcd(N, 5(n-1)(n-3)!) with N = n^2+3n-5, is essentially the formula already in the entry, and it comes from a standard convergent recurrence. From there the proof is about a page of elementary number theory, and it is the same argument already published for the sibling sequence A363102 (endpoint -2) and its relatives. If a prime p <= n-3 divides a(n), Legendre's bound forces a high power of p to divide N, which is too big except in a small case (N = 3p^2) that is easy to handle. Any prime factor above n-3 is in fact at least n+2, because N + c factors for c = 0, 1, 5, 7, and since N < (n+2)^2 there is room for only one such factor. The cases n <= 35 are a finite check. The manuscript itself says it adapts the existing template, so no new idea was needed. + +*Follows from:* The entry's own formula a(n) = (n^2+3n-5)/gcd(n^2+3n-5, 5*A051403(n-3)+n*A051403(n-4)), which reduces to N/gcd(N, 5(n-1)(n-3)!), combined with the p-adic/Legendre-bound template of Adamczewski's proof of the sibling conjecture A363102 (arXiv:2608.11941, Appendix A, linked from cross-reference A363102). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A363482](https://oeis.org/A363482) as [`Math0.Statements.A363482.statement`](../../lean/Math0/Statements/OEIS/A363482.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A363482.lean`](../../lean/Math0/Frontier/OEIS/A363482.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: Except for 49, every term of this sequence is either a prime or 1. (Mohammed Bouras, Jun 04 2023; 'The conjecture holds through n=10000' - Bill McEachen, Jul 08 2025) + +Referees: No prior resolution of A363482 found. Sources checked: +- OEIS A363482 (local mirror, identical to upstream oeisdata #29, Jul 13 2025): conjecture plus a numerical check to n = 10000 (McEachen), no proof. +- Bouras, "A New Primes-Generating Sequence", arXiv:2509.09745 (2025): lists A363482 as the k=5 case of n^2+(k-2)n-k, with observations only. +- Epoch OEIS Open benchmark (github.com/epoch-research/LeanOpenProblems-results, metadata/oeis/conjectures.json): A363482 is absent. +- google-deepmind/formal-conjectures: no A363482 file. +- google-deepmind/alphaproof-nexus-results: no A363482 file. + +Related prior results on sibling sequences: +- A363102 (endpoint -2) proved: T. Adamczewski, "OEIS Open: How many conjectures can language models turn into theorems?", arXiv:2608.11941 (2026), Appendix A; also AlphaProof Nexus oeis_a363102_conjecture_1.lean. +- A356247 (endpoint -1) proved: B. Cloitre, "On the sequence A356247" (2025, OEIS-hosted PDF a356247_1.pdf; not readable here). +- A363347 (endpoint -4) conjectures 1-2 proved: AlphaProof Nexus oeis_363347_conjecture_2.lean; Adamczewski, arXiv:2608.11941. + +The proof here follows the same template as the A363102 proof. + +Reading note (fidelity pass, 29 Oct 2026): the statement exempts every term equal to 49. Read strictly, the conjecture exempts only the single term a(6) = 49, which also needs the value 49 to occur only once. That holds for n < 1200 by exact computation but is not part of the Lean result. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a363482, + author = {{math0}}, + title = {{OEIS A363482: apart from 49, every denominator of 1/(2-3/(3-4/(...(n-1)-n/(-5)))) is 1 or a prime}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a363482}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a363482/paper.pdf b/results/oeis-a363482/paper.pdf new file mode 100644 index 0000000..a213ca2 Binary files /dev/null and b/results/oeis-a363482/paper.pdf differ diff --git a/results/oeis-a363482/paper.tex b/results/oeis-a363482/paper.tex new file mode 100644 index 0000000..eed615a --- /dev/null +++ b/results/oeis-a363482/paper.tex @@ -0,0 +1,406 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,by_cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℚ}{{$\mathbb{Q}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {→}{{$\to$}}1 {∨}{{$\vee$}}1 {¬}{{$\neg$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {·}{{$\cdot$}}1 {…}{{$\ldots$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{…}{\ensuremath{\ldots}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Q}{\mathbb{Q}} +\newcommand{\lf}{\mathop{!}} +\DeclareMathOperator{\den}{den} +\DeclareMathOperator{\cf}{cf} + +\title[Denominators of a continued fraction (OEIS A363482)]{Apart from $49$, every denominator of $1/(2-3/(3-4/(\cdots(n-1)-n/(-5))))$ is $1$ or a prime} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +For $n\ge3$ let $a(n)$ be the denominator, in lowest terms, of the finite continued fraction $1/(2-3/(3-4/(\cdots(n-1)-n/(-5))))$; this is the OEIS sequence A363482. +We prove the conjecture of M.~Bouras (2023) that every term other than $49$ is $1$ or a prime; the argument also shows that $a(6)=49$ is the only composite term. +The proof derives the closed form $a(n)=N/\gcd\bigl(N,5(n-1)(n-3)!\bigr)$ with $N=n^2+3n-5$ from the convergents of the continued fraction, and then studies the least prime factor of $a(n)$ for $n\ge36$; the cases $n\le35$ are read off from the listed terms. +To our knowledge this is a new result: the entry records the conjecture together with a numerical check up to $n=10000$; the analogous conjectures for the endpoints $-1$, $-2$ and $-4$ were settled earlier, and our method follows the template used for the endpoint $-2$. +The proof is verified in Lean~4 against a statement that math0 formalized from the OEIS entry and checked against its $61$ listed terms; the statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +In 2022--2023 M.~Bouras contributed to the OEIS five sequences of denominators of the finite continued fractions $1/(2-3/(3-4/(\cdots(n-1)-n/(-c))))$, $c=1,\dots,5$: A356247, A363102, A362086, A363347 and A363482 \cite{A356247,A363102,A362086,A363347,A363482}. The unreduced denominator is $n^2+(c-2)n-c$, and each entry conjectures that the reduced denominators are $1$ or prime, with at most one exceptional value; see also \cite{Bslides,Barxiv}. +For $c=5$ the unreduced denominator is $N=n^2+3n-5$, and the entry A363482, created by Bouras on June~4, 2023, states: ``Conjecture: Except for 49, every term of this sequence is either a prime or 1.'' +In July 2025 B.~McEachen added that the conjecture holds through $n=10000$ \cite{A363482}. + +\subsection*{Prior work} +For $c=1$, the conjectures of A356247 are proved in a note of B.~Cloitre \cite{Cloitre}, according to a 2025 comment in the entry. +For $c=2$, the conjecture that A363102 contains only $1$'s and primes is marked as solved in the formal-conjectures repository \cite{FC}, with a formal proof found by the methods of Tsoukalas et al.\ \cite{Tsoukalas}; T.~Adamczewski gives a proof sketch in \cite[Appendix~A]{Ad}, and the AlphaProof Nexus outputs \cite{APN} contain a Lean file for it. +For $c=4$, Conjectures~1 and~2 of A363347 were proved by an AI agent (AlphaProof Nexus) \cite{APN}; see also \cite[Appendix~A]{Ad}. +The case $c=3$ (A362086, with exceptional value $9$) was, as far as we know, open when this proof was found; math0 has since settled it by an adaptation of the present proof, with a separate Lean proof \cite{M0A362086}. + +For $c=5$ the math0 referees found no proof. The current revision of A363482 (\#29, July~13, 2025) records only the conjecture and the numerical check. Bouras's preprint \cite{Barxiv} lists A363482 as the case $k=5$ of the family $n^2+(k-2)n-k$, with observations but no proof. The sequence is not among the $492$ conjectures of the OEIS Open benchmark \cite{Ad}, and has no file in formal-conjectures \cite{FC} or among the AlphaProof Nexus outputs \cite{APN}. Searches of arXiv, MathOverflow, Mathematics Stack Exchange and the SeqFan list found nothing further. +We therefore classify Theorem~\ref{thm:main} as a \emph{new result}, with two caveats. First, the method is not new: according to the referees, the proof for A363102 in \cite[Appendix~A]{Ad} follows the same template (a closed form for the unreduced fraction, then bounds on the powers of small primes dividing factorials). Second, the referees could not read Cloitre's note \cite{Cloitre}, so we cannot exclude that it treats a general endpoint $-c$; the entry A356247 describes it only as a proof of that entry's conjectures. +Corollary~\ref{cor:49} shows moreover that $a(6)=49=7^2$ is the only composite term; Remark~\ref{rem:49} explains where it comes from. + +\section{Statement}\label{sec:statement} + +For $q\in\Q$ we write $\den q\ge1$ for its denominator in lowest terms. + +\begin{definition}\label{def:a} +For an integer $k\ge2$ and $t\in\Q\setminus\{0\}$ put $s_k(t)=k-(k+1)/t$. For $n\ge3$ let $t_n=-5$ and $t_k=s_k(t_{k+1})$ for $k=n-1,\dots,2$, and put +\[ + \cf(n)=1/t_2=1/\bigl(2-3/(3-4/(\cdots(n-1)-n/(-5)))\bigr),\qquad a(n)=\den\cf(n). +\] +\end{definition} + +That no $t_k$ vanishes is shown in Proposition~\ref{prop:closed} (for $n=3$, $t_2=13/5$). For example $\cf(3)=5/13$, $\cf(4)=19/23$, $\cf(5)=11/7$ and $\cf(6)=173/49$. +The OEIS entry \cite{A363482} (offset $3$) is named ``Denominator of the continued fraction 1/(2-3/(3-4/(4-5/(...(n-1)-n/(-5)))))'', gives the first three examples, and contains the comment, verbatim, +\begin{quote} +\texttt{Conjecture: Except for 49, every term of this sequence is either a prime or 1.} +\end{quote} +which is unsigned and hence due to the author of the entry, Mohammed Bouras, June~4, 2023. + +\begin{theorem}\label{thm:main} +For every $n\ge3$ with $a(n)\ne49$, $a(n)=1$ or $a(n)$ is prime. +\end{theorem} + +\begin{corollary}\label{cor:49} +For $n\ge3$, $a(n)$ is composite if and only if $n=6$; in particular $a(n)=49$ only for $n=6$. +\end{corollary} + +So the two readings of ``Except for 49'' (an exception for the value $49$, or for the term $a(6)$) are equivalent. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A363482.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{55497908\ldots f9886e5ef}) before any proof attempt. Its definitions and statement read as follows (verbatim; docstrings and the data checks described below are omitted): +\begin{lstlisting} +namespace Math0.Statements.A363482 + +def step (k : ℕ) (t : ℚ) : ℚ := (k : ℚ) - ((k : ℚ) + 1) / t + +def cf (n : ℕ) : ℚ := 1 / (List.range' 2 (n - 2)).foldr step (-5) + +def a (n : ℕ) : ℕ := (cf n).den + +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → a n ≠ 49 → a n = 1 ∨ (a n).Prime + +end Math0.Statements.A363482 +\end{lstlisting} +\texttt{step k t} is $s_k(t)$. For $n\ge3$, \texttt{List.range' 2 (n - 2)} is the list $[2,3,\dots,n-1]$, and the right fold of \decl{step} over it, starting at $-5$, is \texttt{step 2 (step 3 (...(step (n-1) (-5))))}, i.e.\ $t_2$. So \texttt{cf n} is $\cf(n)$, and \texttt{a n} is its reduced denominator \decl{Rat.den}. The statement quantifies over $n\ge3$, the offset of the entry, and reads ``Except for 49'' as an exception for the value $49$; values of \texttt{a n} for $n<3$ are never used. +Lean defines $q/0=0$, which would change the value if some $t_k$ vanished; this never happens, because the induction by which the formal proof evaluates the fold (Lemma~\ref{lem:conv}) carries the bounds $t_k\ge k-2>0$. +The file also checks the definitions against the entry by kernel evaluation (\texttt{decide +kernel}): the lemma \decl{a_data} states that $(a(3),\dots,a(63))$ is the list of all $61$ listed terms $13,23,7,49,13,83,\dots,557,1,4153$, and an \texttt{example} confirms $\cf(3)=5/13$, $\cf(4)=19/23$, $\cf(5)=11/7$. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A363482.lean} (Section~\ref{sec:lean}). Throughout, $x=n-3\ge0$, +\[ + N=x^2+9x+13=n^2+3n-5,\qquad M=5(x+2)\,x!=5(n-1)(n-3)!, +\] +and $\lf m=\sum_{i=0}^{m-1}i!$ is the left factorial (A003422 \cite{A003422}; the notation is Kurepa's \cite{Kurepa}). Thus $\lf0=0$, $\lf1=1$, $\lf2=2$ and $\lf(m+1)=\lf m+m!$; as $m!$ is even for $m\ge2$, $\lf m$ is even for every $m\ge2$. + +\subsection{Convergents and the closed form} +For $m\ge0$ define the linear polynomials +\[ + P_m(t)=2\bigl((m+2)t-(m+1)(m+3)\bigr),\qquad Q_m(t)=(m+2)\lf(m+1)\,t-(m+1)(m+3)\lf m, +\] +and, where defined, $G_m(t)=s_2(s_3(\cdots s_{m+2}(t)\cdots))$. Thus $G_0=s_2$ and $G_{m+1}(t)=G_m(s_{m+3}(t))$. + +\begin{lemma}\label{lem:step} +For $m\ge0$ and $t\ne0$, $\;t\,P_m(s_{m+3}(t))=P_{m+1}(t)$ and $t\,Q_m(s_{m+3}(t))=Q_{m+1}(t)$. +\end{lemma} + +\begin{proof} +Put $s=s_{m+3}(t)$, so $ts=(m+3)t-(m+4)$. Then +$tP_m(s)=2\bigl((m+2)((m+3)t-(m+4))-(m+1)(m+3)t\bigr)=2\bigl((m+3)t-(m+2)(m+4)\bigr)=P_{m+1}(t)$, and +\[ + tQ_m(s)=(m+3)\bigl[(m+2)\lf(m+1)-(m+1)\lf m\bigr]t-(m+2)(m+4)\lf(m+1)=Q_{m+1}(t), +\] +because $(m+2)\lf(m+1)-(m+1)\lf m=\lf m+(m+2)\,m!=\lf(m+1)+(m+1)!=\lf(m+2)$. +\end{proof} + +\begin{lemma}\label{lem:conv} +Let $m\ge0$ and $t\in\Q$ with $t\ge m+1$. Then $G_m(t)$ is defined, the argument of each $s_k$ $(2\le k\le m+2)$ occurring in it is at least $k-1$, $Q_m(t)>0$, and $G_m(t)=P_m(t)/Q_m(t)$. +\end{lemma} + +\begin{proof} +$Q_m$ has positive leading coefficient and $Q_m(m+1)=(m+1)\bigl[(m+2)\,m!-\lf m\bigr]>0$, since $\lf m\le m\cdot(m-1)!=m!$ for $m\ge1$ and $\lf0=0$; hence $Q_m(t)>0$. +The rest is by induction on $m$. For $m=0$, $t\ge1$ and $G_0(t)=2-3/t=(2t-3)/t=P_0(t)/Q_0(t)$, as $P_0(t)=2(2t-3)$ and $Q_0(t)=2t$. +For the step let $t\ge m+2$. Then $(m+4)/t\le(m+4)/(m+2)\le2$, so $s=s_{m+3}(t)\ge m+1$. By the induction hypothesis $G_{m+1}(t)=G_m(s)$ is defined, with the stated bounds on the arguments, and by Lemma~\ref{lem:step} +\[ + G_{m+1}(t)=\frac{P_m(s)}{Q_m(s)}=\frac{tP_m(s)}{tQ_m(s)}=\frac{P_{m+1}(t)}{Q_{m+1}(t)}.\qedhere +\] +\end{proof} + +In Lean, $P_m(t)/Q_m(t)$ is \texttt{F m t}, and Lemmas~\ref{lem:step} and~\ref{lem:conv} are \decl{F_step} and \decl{fold_eq_F}. The positivity of $Q_m$ is not needed there, since with $q/0=0$ the identity $(ta)/(tb)=a/b$ holds for all $a,b$ when $t\ne0$. + +\begin{proposition}\label{prop:closed} +Let $x\ge1$, i.e.\ $n\ge4$. Then $t_k\ge k-2>0$ for $3\le k\le n-1$, $t_2=2N/(N\cdot{\lf x}+M)>0$, and +\[ + \cf(x+3)=\frac{N\cdot\lf x+5(x+2)\,x!}{2N}. +\] +\end{proposition} + +\begin{proof} +Let $n=x+3$ and $u=t_{n-1}=s_{x+2}(-5)=(x+2)+(x+3)/5\ge x$. Lemma~\ref{lem:conv} with $m=x-1$ gives the bounds on $t_3,\dots,t_{n-1}$ and $t_2=G_{x-1}(u)=P_{x-1}(u)/Q_{x-1}(u)$. Lemma~\ref{lem:step} with $m=x-1$ and $t=-5$ gives $-5P_{x-1}(u)=P_x(-5)$ and $-5Q_{x-1}(u)=Q_x(-5)$, and +\begin{align*} + P_x(-5)&=2\bigl(-5(x+2)-(x+1)(x+3)\bigr)=-2N,\\ + Q_x(-5)&=-5(x+2)\bigl(\lf x+x!\bigr)-(x+1)(x+3)\lf x=-\bigl(N\cdot{\lf x}+M\bigr). +\end{align*} +So $t_2=2N/(N\cdot{\lf x}+M)>0$, and $\cf(x+3)=1/t_2$ is as stated. +\end{proof} + +For $x=1,2,3$ the formula gives $38/46$, $110/70$ and $346/98$, in accordance with the examples. + +\subsection{The reduced denominator} + +\begin{proposition}\label{prop:den} +$N$ is odd, and for $x\ge2$, $a(x+3)=N/\gcd(N,M)$. +\end{proposition} + +\begin{proof} +$N=x(x+1)+2(4x+6)+1$ with $x(x+1)$ even. For $x\ge2$ both $\lf x$ and $x!$ are even, so $N\cdot{\lf x}+M=2X$ with $X\in\N$, and $\cf(x+3)=X/N$ by Proposition~\ref{prop:closed}. Hence $a(x+3)=N/\gcd(N,X)$, and since $N$ is odd, +$\gcd(N,X)=\gcd(N,2X)=\gcd(N,M+\lf x\cdot N)=\gcd(N,M)$. +\end{proof} + +In Lean these are \decl{N_odd} and \decl{a_eq}; the latter is stated for $x\ge3$, which is all that is used. +The entry also gives the formula $a(n)=N/\gcd\bigl(N,5\,A051403(n-3)+n\,A051403(n-4)\bigr)$, where $A051403(m)=(m+2)\lf(m+1)/2$ \cite{A051403}. Since $5\,A051403(x)+(x+3)\,A051403(x-1)=X$, the proof above also confirms this formula for $n\ge5$; this identification is not part of the formal proof. + +\subsection{Three arithmetic lemmas} + +\begin{lemma}\label{lem:fact} +For integers $q\ge1$ and $k\ge0$, $q^k\mid(qk)!$. +\end{lemma} + +\begin{proof} +Induction on $k$: $(q(k+1))!=q(k+1)\cdot(qk+q-1)!$, where $q\mid q(k+1)$ and $(qk)!\mid(qk+q-1)!$. +\end{proof} + +\begin{lemma}[lifting]\label{lem:lift} +Let $N\ge1$ and $M,q\in\N$, put $g=\gcd(N,M)$ and $d=N/g$, and suppose $q\mid d$. Then for every $j\ge0$, $q^j\mid M$ implies $q^{j+1}\mid N$. +\end{lemma} + +\begin{proof} +Note $N=gd$. For $j=0$, $q\mid d\mid N$. If the claim holds for $j$ and $q^{j+1}\mid M$, then $q^j\mid M$, so $q^{j+1}\mid N$; hence $q^{j+1}\mid\gcd(N,M)=g$, and $q^{j+2}=q^{j+1}\cdot q\mid gd=N$. +\end{proof} + +\begin{lemma}\label{lem:bound} +If $q\ge3$, $j\ge3$ and $qj\ge34$, then $(qj+4)^2(3q+4)^2$. +If $j=4$ then $q\ge9$, and $q^4\ge81q^2>32q^2\ge16(q+1)^2=(4q+4)^2$. +If $j=5$ then $q\ge7$, and $q^5\ge343q^2>36q^2\ge(5q+4)^2$. +For $j\ge6$ we induct on $j$, for any $q\ge3$: $q^6\ge81q^2>64q^2\ge(6q+4)^2$, and if $(qj+4)^20$, $d\mid N$, $x!\mid M$, and $N<(x+5)^2$, since $(x+5)^2-N=x+12$. Suppose $d\ne1$, and let $p$ be the least prime factor of $d$. Then $p\mid N$, so $p\ge3$ as $N$ is odd. + +\emph{Case (A): $2p\le x$.} Let $k=\lfloor x/p\rfloor\ge2$. Since $pk\le x$, Lemma~\ref{lem:fact} gives $p^k\mid(pk)!\mid x!\mid M$, so $p^{k+1}\mid N$ by Lemma~\ref{lem:lift}, and $p^{k+1}\le N$. Moreover $x4N$, which is absurd. So $1\le m\le4$, and $m\ne2,4$ as $N$ is odd. If $m=1$, then $(x+4)^2=N-(x-3)x\ge33$, $p\ge17$, so $3$ and $p$ are distinct primes not exceeding $x$, and $3p\mid x!\mid M$. Also $3p\mid N$, hence $3p\mid g$; write $g=3ph$. Then $3p\cdot p=N=gd=3p\cdot hd$ gives $p=hd$, so $d\mid p$ and $d=p$ is prime. + +\emph{Case (C): $p>x$.} We have +\[ + N=(x+1)(x+8)+5,\quad N+1=(x+2)(x+7),\quad N+5=(x+3)(x+6),\quad N+7=(x+4)(x+5). +\] +So if $x+i$ divided $N$ for some $i\in\{1,2,3,4\}$, it would divide $5$, $1$, $5$ or $7$ respectively, which is impossible as $x+1\ge34$. Hence every divisor of $N$ exceeding $x$ is at least $x+5$; in particular $p\ge x+5$. Suppose $d\ne p$, and let $r=d/p$. Then $r\ne1$, and $r\ne0$ as $d\ne0$. The least prime factor $q$ of $r$ divides $d$, so $q\ge p$ by minimality of $p$. Hence $r\ge q\ge p\ge x+5$ and $d=pr\ge(x+5)^2>N\ge d$, a contradiction. So $d=p$ is prime. +\end{proof} + +\begin{remark}\label{rem:49} +For $x=3$ ($n=6$) we have $N=49$, $M=150$ and $d=49$: here $p=7=x+4$ divides $N+7=(x+4)(x+5)$, and the step ``$x+4\mid7$ is impossible'' of Case~(C) fails. The threshold $x\ge33$ is chosen for convenience in Cases~(A) and~(B). +\end{remark} + +\subsection{Proof of Theorem~\ref{thm:main} and Corollary~\ref{cor:49}} +Let $n\ge3$. If $n\ge36$, then $x=n-3\ge33$, and $a(n)=N/\gcd(N,M)$ is $1$ or prime by Propositions~\ref{prop:den} and~\ref{prop:main}. If $3\le n\le35$, then $a(n)$ is one of the first $33$ entries of the list in \decl{a_data}, which equals $(a(3),\dots,a(63))$ by kernel computation; each of its $61$ entries is $49$, $1$ or a prime (the largest is $4153$). This proves Theorem~\ref{thm:main}. Moreover the only entry of the list that is neither $1$ nor prime is $a(6)=49$, which gives Corollary~\ref{cor:49}. The corollary is not a separate Lean theorem, but it follows at once from the formalized lemmas \decl{a_eq}, \decl{main} and \decl{a_data}.\qed + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is the file \path{lean/Math0/Frontier/OEIS/A363482.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A363482.result}, of type \decl{Math0.Statements.A363482.statement}. The private auxiliary declarations follow Section~\ref{sec:proof}: \decl{lf}, \decl{lf_succ}, \decl{two_dvd_lf} (left factorial); \decl{fold_concat}, \decl{F}, \decl{F_step}, \decl{fold_eq_F}, \decl{cf_closed} (Lemmas~\ref{lem:step}, \ref{lem:conv} and Proposition~\ref{prop:closed}, the last with $x=y+1$); \decl{N_odd}, \decl{a_eq} (Proposition~\ref{prop:den}); \decl{pow_dvd_fact}, \decl{pow_step}, \decl{bound6}, \decl{bound} (Lemmas~\ref{lem:fact}--\ref{lem:bound}); \decl{not_dvd_aux}, \decl{main} (Proposition~\ref{prop:main}); and \decl{small} (the cases $3\le n<64$, from \decl{a_data}). The statement of \decl{main} and the final proof read, verbatim: +\begin{lstlisting} +private lemma main (x : ℕ) (hx : 33 ≤ x) : + (x^2+9*x+13) / Nat.gcd (x^2+9*x+13) (5*(x+2)*x.factorial) = 1 ∨ + ((x^2+9*x+13) / Nat.gcd (x^2+9*x+13) (5*(x+2)*x.factorial)).Prime := by + +theorem result : statement := by + intro n hn h49 + by_cases hsmall : n < 36 + · exact small n hn (by omega) h49 + · obtain ⟨x, rfl⟩ : ∃ x, n = x + 3 := ⟨n - 3, by omega⟩ + rw [a_eq x (by omega)] + exact main x (by omega) +\end{lstlisting} + +\subsection*{Kernel computation} +The only finite computations are these. In the statement file, \decl{a_data} and the worked examples are proved by \texttt{decide +kernel}: the Lean kernel evaluates the continued fractions for $n=3,\dots,63$ in exact rational arithmetic and compares the reduced denominators with the $61$ OEIS terms. In the proof file, \decl{small} rewrites with \decl{a_data} and discharges the $61$ claims ``$v\ne49\Rightarrow v=1\lor v$ prime'' with \decl{norm_num}, whose primality extension produces proof terms that the kernel checks; the base case $2\mid\lf2$ of \decl{two_dvd_lf} is closed by \texttt{decide}. Neither file uses \texttt{native\_decide} (which would add the axiom \decl{Lean.ofReduceBool}) or \texttt{sorry}, and the proof file sets no options. With Mathlib and the statement file already built, checking the proof file takes under a minute on our machine. + +\subsection*{Audit} +The file ends with the command \texttt{\#math0\_settles} applied to \decl{result} and \decl{statement}. This command, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, \decl{Lean.ofReduceBool}, \decl{Lean.trustCompiler} and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata annotations, with no unfolding. Running \texttt{lake env lean Math0/Frontier/OEIS/A363482.lean} in \path{lean/} prints +\begin{lstlisting} +math0 audit: 'Math0.Statements.A363482.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A363482.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A363482.result' proves 'Math0.Statements.A363482.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. + +\begin{thebibliography}{99} + +\bibitem{Ad} +T.~Adamczewski, \emph{OEIS Open: How many conjectures can language models turn into theorems?}, arXiv:2608.11941 [cs.AI], 2026. + +\bibitem{Bslides} +M.~Bouras, \emph{The distribution of prime numbers and continued fractions}, Zenodo, 2022, \url{https://doi.org/10.5281/zenodo.10992128}. + +\bibitem{Barxiv} +M.~Bouras, \emph{A new primes-generating sequence}, arXiv:2509.09745 [math.GM], 2025. + +\bibitem{Cloitre} +B.~Cloitre, \emph{On the sequence A356247}, 2025, note attached to OEIS A356247, \url{https://oeis.org/A356247/a356247_1.pdf}. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{APN} +Google DeepMind, \emph{AlphaProof Nexus results}, \url{https://github.com/google-deepmind/alphaproof-nexus-results}; for A363347 see \path{APNOutputs/OEIS/oeis_363347_conjecture_2.lean}. + +\bibitem{Kurepa} +\DJ.~Kurepa, \emph{On the left factorial function $!n$}, Math. Balkanica \textbf{1} (1971), 147--153. + +\bibitem{M0A362086} +math0, \emph{Apart from $9$, every denominator of $1/(2-3/(3-4/(\cdots(n-1)-n/(-3))))$ is $1$ or a prime}, manuscript and Lean proof, 2026, \url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a362086}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Tsoukalas} +G.~Tsoukalas et al., \emph{Advancing mathematics research with AI-driven formal proof search}, arXiv:2605.22763, 2026. + +\bibitem{A003422} +The OEIS Foundation Inc., \url{https://oeis.org/A003422} (left factorials). + +\bibitem{A051403} +The OEIS Foundation Inc., \url{https://oeis.org/A051403}. + +\bibitem{A356247} +The OEIS Foundation Inc., \url{https://oeis.org/A356247}, entry by M.~Bouras (2022). + +\bibitem{A362086} +The OEIS Foundation Inc., \url{https://oeis.org/A362086}, entry by M.~Bouras (2023). + +\bibitem{A363102} +The OEIS Foundation Inc., \url{https://oeis.org/A363102}, entry by M.~Bouras (2023). + +\bibitem{A363347} +The OEIS Foundation Inc., \url{https://oeis.org/A363347}, entry by M.~Bouras (2023). + +\bibitem{A363482} +The OEIS Foundation Inc., \url{https://oeis.org/A363482}, entry by M.~Bouras (2023), with a table of $a(n)$ for $3\le n\le10000$ by B.~McEachen. + +\end{thebibliography} + +\end{document} diff --git a/results/oeis-a363609/README.md b/results/oeis-a363609/README.md new file mode 100644 index 0000000..d80bd10 --- /dev/null +++ b/results/oeis-a363609/README.md @@ -0,0 +1,52 @@ +# A363609: a(k^3) = 6k(k+2), the cube is the optimal polycube of k^3 dice + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A363609 +**Date:** 2026-10-19 + +## Result + +Each standard die has opposite faces summing to 7, all dice have the same chirality, and each die may take any of its 24 rotations. Build a face-connected polycube from n dice. A face is visible when the neighbouring cell is empty; faces underneath and faces facing an internal cavity also count. a(n) is the least possible number of visible pips. Claim: for every k > 1, a(k^3) = 6(k+2)k. + +## Assessment + +The value 6k(k+2) splits as surface area 6k^2 plus 12k. That second term counts the pairs of perpendicular exposed faces on the cube. The proof matches this split. First it checks a finite inequality for one die: the pips shown are at least the number of exposed faces plus the number of exposed perpendicular pairs. Then it bounds the faces by projections and Loomis-Whitney, as in the known surface-area result (A193416). It bounds the perpendicular pairs by taking an extreme cell in each slice, then uses |P| <= l1*l2*l3 and AM-GM. The edge term is a neat observation, but it is a direct analogue of the standard projection argument. The whole proof fits in about a page and uses only standard tools, so a competent mathematician working on the problem would likely find it quickly. + +*Follows from:* Discrete Loomis-Whitney inequality (Loomis and Whitney 1949), the standard projection bound behind A193416's a(n^3)=6n^2, and AM-GM, together with a 64-case finite check per die + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A363609](https://oeis.org/A363609) as [`def statement`](../../lean/Math0/Statements/OEIS/A363609.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A363609.lean`](../../lean/Math0/Frontier/OEIS/A363609.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A363609 Conjecture: a(k^3) = 6*(k+2)*k for k > 1. (Unattributed formula line. Entry by _Matt Donahoe_, Jun 11 2023; last edit #45, Sep 03 2023.) + +Referees: I found no prior resolution. +- OEIS A363609, by Matt Donahoe, Jun 11 2023 (revision #45, Sep 03 2023): the local mirror is identical to oeis/oeisdata main on GitHub, and it still states the formula as "Conjecture: a(k^3) = 6*(k+2)*k for k > 1". +- Michael S. Branicky's formulas in the same entry, Jun 11 and Jun 15 2023: these give only upper bounds and loose bounds. +- Donahoe's program, https://github.com/mdonahoe/oeis/blob/main/A363609/dice.py, with its out.txt: a heuristic search over box-plus-slab layouts, with no optimality proof. +- OEIS A193416, minimum surface area of polycubes: the unweighted analogue, a(n^3) = 6n^2. +- AMC 10A 2002 Problem 18 (https://artofproblemsolving.com/wiki/index.php/2002_AMC_10A_Problems/Problem_18): computes the minimum for the 3x3x3 cube alone, 90. It does not show that the cube is optimal among all polycubes. +- Loomis and Whitney, Bull. AMS 55 (1949) 961-962: the classical inequality behind the projection step. +- Searches of arXiv, MathOverflow, Math StackExchange, Puzzling and SeqFan turned up no proof and no counterexample. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a363609, + author = {{math0}}, + title = {{A363609: a(k^3) = 6k(k+2), the cube is the optimal polycube of k^3 dice}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a363609}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a363609/paper.pdf b/results/oeis-a363609/paper.pdf new file mode 100644 index 0000000..fc16d90 Binary files /dev/null and b/results/oeis-a363609/paper.pdf differ diff --git a/results/oeis-a363609/paper.tex b/results/oeis-a363609/paper.tex new file mode 100644 index 0000000..4c84136 --- /dev/null +++ b/results/oeis-a363609/paper.tex @@ -0,0 +1,361 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, + literate={∑}{{$\sum$}}1 {∈}{{$\in$}}1 {∉}{{$\notin$}}1 {ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 + {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {∧}{{$\wedge$}}1 {≤}{{$\le$}}1 {→}{{$\to$}}1 + {×}{{$\times$}}1 {²}{{$^2$}}1 {³}{{$^3$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\D}{\mathcal{D}} +\newcommand{\LB}{\mathrm{LB}} +\newcommand{\ind}[1]{[\,#1\,]} + +\title[A polycube of $k^3$ dice shows at least $6k(k+2)$ pips]{For $k\ge2$, a face-connected polycube of $k^3$ standard dice shows at least $6k(k+2)$ pips, with equality for the cube (OEIS A363609)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 19, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the least total number of pips that can be visible on a face-connected polycube built from $n$ standard dice, where a face of a die is visible unless it is glued to another die (OEIS A363609). We prove the conjecture recorded in that entry: $a(k^3)=6k(k+2)$ for every $k\ge2$, so the $k\times k\times k$ cube is optimal among all polycubes with $k^3$ cells. The lower bound combines a per-die inequality (a die shows at least as many pips as it has exposed faces plus exposed pairs of perpendicular faces) with projection counts and a slice-wise discrete Loomis--Whitney inequality; it does not use connectivity. The math0 referees found no earlier resolution, and we classify the result as new. The proof is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, reviewed for fidelity and frozen before the proof attempt; the Lean kernel checks its definitions against the entry's data, exactly for the first seven terms and as upper bounds for all $57$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +A standard die carries $1,\dots,6$ pips on its six faces, with opposite faces summing to $7$. Glue $n$ such dice face to face into a face-connected polycube and count the pips on all faces that are not glued to another die, including the bottom faces. The sequence A363609 \cite{A363609}, contributed by Matt Donahoe on June~11, 2023, lists the least possible count $a(n)$ for $n=1,\dots,57$: +\[ +21,30,40,40,51,52,54,48,60,62,65,60,\dots,90\ (n=27),\dots +\] +The entry's formula section contains the line \texttt{Conjecture: a(k\^{}3) = 6*(k+2)*k for k > 1.} For the cube $[0,k)^3$ the value $6k(k+2)$ is attained: turn the $8$ corner dice to show $1,2,3$, the $12(k-2)$ edge dice to show $1,2$ and the $6(k-2)^2$ face dice to show $1$, for a total of $48+36(k-2)+6(k-2)^2=6k(k+2)$. The content of the conjecture is the matching lower bound over all polycubes with $k^3$ cells. + +\subsection*{Prior work} +The entry links a Python program by Donahoe \cite{Don}, which the referees describe as a heuristic search over layouts consisting of a box, a rectangular partial layer and a row; it does not prove optimality. M.~S.~Branicky added two formulas to the entry in June 2023: the upper bound $a(ijk)\le 48+2((i-2)(j-2)+(i-2)(k-2)+(j-2)(k-2))+12(i+j+k-6)$ for $i,j,k>1$, which for $i=j=k$ is the cube count above, and two-sided bounds $\mathrm{lb}(n)\le a(n)\le\mathrm{ub}(n)$ in terms of the minimum surface area A193416 \cite{A193416}. These do not settle the conjecture. The value $90$ for the $3\times3\times3$ cube appears as a contest exercise (AMC~10A 2002, Problem~18 \cite{AMC}); it concerns the cube alone, not optimality among polycubes. The unweighted analogue is A193416, the minimum surface area of a polycube with $n$ cells, for which the entry records $a(n^3)=6n^2$ (C.~R.~Greathouse~IV, 2011); the lower bound $6n^2$ follows from the Loomis--Whitney inequality \cite{LW} as in Section~\ref{sec:proj}. The math0 referees found the conjecture still stated as open in the current revision (\#45, September~3, 2023) of A363609 and found no proof or counterexample in searches of arXiv, MathOverflow, Mathematics Stack Exchange, Puzzling Stack Exchange and SeqFan. A discussion that is not indexed cannot be excluded, but on this evidence the result is new. + +Besides the classical projection bound for the surface area, our proof of the conjecture (Theorem~\ref{thm:main}) uses an \emph{edge term}: a die shows at least one extra pip for each pair of perpendicular exposed faces, and every slice of the polycube has a cell with two prescribed perpendicular faces exposed. The proof is formalized in Lean~4 with Mathlib (Section~\ref{sec:lean}). + +\section{Statement}\label{sec:statement} + +Write $e_1,e_2,e_3$ for the standard basis of $\Z^3$ and $\D=\{\pm e_1,\pm e_2,\pm e_3\}$. A cell $q\in\Z^3$ is the unit cube $q+[0,1]^3$; its six faces have outer normals $d\in\D$. Two directions $d,e\in\D$ are \emph{perpendicular} if $e\ne\pm d$. + +\begin{definition}\label{def:main} +A \emph{polycube} is a finite set $P\subset\Z^3$ that is face-connected: any two cells of $P$ are joined by a chain of cells of $P$ in which consecutive cells differ by an element of $\D$. An \emph{orientation} is a pair $o=(u,v)$ of perpendicular $u,v\in\D$; a die in orientation $o$ shows $\pi_o(d)$ pips on its face with normal $d$, where +\[ +\pi_o(u)=1,\quad \pi_o(v)=2,\quad \pi_o(u\times v)=3,\quad \pi_o(-u\times v)=4,\quad \pi_o(-v)=5,\quad \pi_o(-u)=6. +\] +For a polycube $P$ and orientations $o=(o_q)_{q\in P}$, the number of visible pips is +\[ +V(P,o)=\sum_{q\in P}\ \sum_{d\in\D,\ q+d\notin P}\pi_{o_q}(d), +\] +and $a(n)$ is the minimum of $V(P,o)$ over all polycubes $P$ with $|P|=n$ and all $o$. +\end{definition} + +There are $6\cdot4=24$ orientations, the rotations of one die; opposite faces sum to $7$, and $1,2,3$ form a right-handed frame, so all dice have the same chirality. A reflection of a whole configuration replaces every die by its mirror image, so the other chirality gives the same minimum. + +\begin{theorem}\label{thm:main} +For every integer $k\ge2$, $a(k^3)=6k(k+2)$. +\end{theorem} + +\subsection*{The OEIS entry} +The entry A363609 \cite{A363609} (author Matt Donahoe, June~11, 2023; revision \#45, September~3, 2023) has the name ``Minimum sum of the visible pips on a polycube made from n dice.'', offset $1$, the comment ``This sequence is calculated using standard six-sided dice of the same chirality. Opposite sides sum to seven.'' and the example ``For n = 2, two dice are conjoined to hide both their 6-pip faces, so a(2) = 30.'' Its formula section contains, verbatim and without attribution, the line +\begin{quote}\raggedright +\texttt{Conjecture: a(k\^{}3) = 6*(k+2)*k for k > 1.} +\end{quote} +Theorem~\ref{thm:main} is this conjecture. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A363609.lean}, reviewed for fidelity and frozen (SHA-256 \texttt{aec2c052\ldots 245afe}) before any proof attempt; it is not part of the formal-conjectures repository \cite{FC}. Its definitions and the statement are, verbatim except that docstrings and the certification section are omitted: +\begin{lstlisting} +namespace Math0.Statements.A363609 +open Finset +abbrev Cell := ℤ × ℤ × ℤ +def dirs : Finset Cell := {(1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0, -1)} +def dot (u v : Cell) : ℤ := u.1 * v.1 + u.2.1 * v.2.1 + u.2.2 * v.2.2 +def cross (u v : Cell) : Cell := + (u.2.1 * v.2.2 - u.2.2 * v.2.1, u.2.2 * v.1 - u.1 * v.2.2, u.1 * v.2.1 - u.2.1 * v.1) +def IsOrientation (o : Cell × Cell) : Prop := o.1 ∈ dirs ∧ o.2 ∈ dirs ∧ dot o.1 o.2 = 0 +def pips (o : Cell × Cell) (d : Cell) : ℕ := + if d = o.1 then 1 else if d = o.2 then 2 else if d = cross o.1 o.2 then 3 + else if d = -cross o.1 o.2 then 4 else if d = -o.2 then 5 else if d = -o.1 then 6 else 0 +def visiblePips (P : Finset Cell) (o : Cell → Cell × Cell) : ℕ := + ∑ c ∈ P, ∑ d ∈ dirs, if c + d ∈ P then 0 else pips (o c) d +def Adj (P : Finset Cell) (u v : Cell) : Prop := u ∈ P ∧ v ∈ P ∧ v - u ∈ dirs +def FaceConnected (P : Finset Cell) : Prop := + ∀ x ∈ P, ∀ y ∈ P, Relation.ReflTransGen (Adj P) x y +def totals (n : ℕ) : Set ℕ := + {t | ∃ P : Finset Cell, P.card = n ∧ FaceConnected P ∧ + ∃ o : Cell → Cell × Cell, (∀ c ∈ P, IsOrientation (o c)) ∧ visiblePips P o = t} +noncomputable def a (n : ℕ) : ℕ := sInf (totals n) +def statement : Prop := ∀ k : ℕ, 1 < k → a (k ^ 3) = 6 * (k + 2) * k +end Math0.Statements.A363609 +\end{lstlisting} +The encoding matches Definition~\ref{def:main}. \decl{dirs} is $\D$, \decl{IsOrientation} says that $u,v\in\D$ are perpendicular, and \decl{pips} is $\pi_o$. The face of $c\in P$ with normal $d$ counts iff $c+d\notin P$, so all six faces of a single die count and $a(1)=21$. A face towards an enclosed empty cell also counts; this agrees with the data, since under the other reading the $3\times3\times3$ cube without its centre would give $a(26)\le90$, whereas the entry lists $a(26)=93$. (See also Remark~\ref{rem:extra}.) \texttt{totals n} is the set of all values $V(P,o)$ and \texttt{a n} its infimum in $\N$. For $n\ge1$ the set is nonempty (a row of $n$ cells is a polycube), so the infimum is a minimum; the value \texttt{a 0} is not part of the sequence and is excluded by $k>1$. The statement involves no truncated subtraction or division. + +The statement file checks the definitions against the data by kernel computation (\texttt{decide +kernel}). The theorem \decl{a_data} gives the exact values $a(1),\dots,a(7)=21,30,40,40,51,52,54$, by a certified enumeration of all polycubes with at most $6$ cells up to the $48$ lattice symmetries ($1,1,2,7,23,112$ representatives) and of all their one-cell extensions. The theorem \decl{a_le_data} gives $a(n)\le$ the listed value for all $57$ listed terms, via kernel-checked witness polycubes. Unformalized exhaustive enumerations run during review reproduced the numbers of fixed polycubes (A001931 \cite{A001931}) and the listed values up to $a(9)$ or $a(10)$. + +\section{Proof}\label{sec:proof} + +The proof follows \path{lean/Math0/Frontier/OEIS/A363609.lean}; Section~\ref{sec:lean} lists the corresponding declarations. Throughout, $P\subset\Z^3$ is finite and $q=(q_1,q_2,q_3)$ denotes a cell. + +\subsection{Reduction to one die at a time} +For $q\in P$ let $E_P(q)=\{d\in\D: q+d\notin P\}$ be the set of exposed directions. For $E\subseteq\D$ let $f(E)=\min_o\sum_{d\in E}\pi_o(d)$, the minimum over the $24$ orientations, and put +\[ +\LB(P)=\sum_{q\in P}f(E_P(q)). +\] + +\begin{lemma}\label{lem:reduce} +For every $n$: if $P_0$ is a polycube with $|P_0|=n$ and $\LB(P_0)\le\LB(P)$ for every polycube $P$ with $|P|=n$, then $a(n)=\LB(P_0)$. +\end{lemma} + +\begin{proof} +For fixed $P$ the term of $V(P,o)$ for the cell $q$ depends only on $o_q$, so $V(P,o)\ge\LB(P)$ for every $o$, with equality when each $o_q$ is chosen to minimize $\sum_{d\in E_P(q)}\pi_{o_q}(d)$. Hence $\LB(P_0)$ is a value of $V$ and is at most every value of $V$ on polycubes with $n$ cells. +\end{proof} + +For $E\subseteq\D$ let $p(E)$ be the number of unordered pairs $\{d,e\}\subseteq E$ of perpendicular directions. + +\begin{lemma}\label{lem:die} +For every $E\subseteq\D$, $f(E)\ge|E|+p(E)$, with equality if $E$ contains no two opposite directions. +\end{lemma} + +\begin{proof} +Fix an orientation. The faces in $E$ show distinct numbers of pips, and two opposite faces show $7$ together. Let $r$ be the number of opposite pairs $\{d,-d\}\subseteq E$ and $s=|E|-2r$ the number of remaining faces of $E$; these lie in $s$ further opposite pairs, so $r+s\le3$, and they show $s$ distinct positive numbers. Hence the pips on $E$ total at least $7r+s(s+1)/2$, while $|E|+p(E)=(2r+s)+\binom{2r+s}{2}-r$. For $r=0$ both sides equal $s(s+1)/2$. The remaining cases are $(r,s)=(1,0),(1,1),(1,2),(2,0),(2,1),(3,0)$, where the two sides are $7\ge2$, $8\ge5$, $10\ge9$, $14\ge8$, $15\ge13$ and $21\ge18$. + +If $r=0$, the $s\le3$ faces of $E$ are mutually perpendicular. Choosing $u,v$ among them (in the right order, so that $u\times v$ is the third one when $s=3$) puts $1,\dots,s$ on them, so $f(E)\le s(s+1)/2=|E|+p(E)$. +\end{proof} + +In Lean, $f$ is evaluated by the kernel on all $64$ subsets $E$ (minimum over the $24$ orientations), giving a table \decl{tabF}; the inequality and the equality case are then checked on that table by \texttt{decide}. For $d\in\D$ and perpendicular $d,e\in\D$ let +\[ +N_d(P)=\#\{q\in P: q+d\notin P\},\qquad N_{d,e}(P)=\#\{q\in P: q+d\notin P,\ q+e\notin P\}. +\] +Summing Lemma~\ref{lem:die} over $q\in P$ gives +\begin{equation}\label{eq:LBE} +\LB(P)\ \ge\ \sum_{d\in\D}N_d(P)+\sum_{\{d,e\}}N_{d,e}(P), +\end{equation} +the second sum running over the $12$ unordered pairs of perpendicular directions. + +\subsection{Projections and slices}\label{sec:proj} +For $i\in\{1,2,3\}$ let $A_i$ be the number of points of the projection of $P$ that forgets the coordinate $q_i$, and let $\ell_i=\#\{q_i:q\in P\}$ be the number of occupied slices orthogonal to $e_i$. + +\begin{lemma}\label{lem:faces} +$N_{\pm e_i}(P)\ge A_i$ for every $i$. +\end{lemma} + +\begin{proof} +Let $d=se_i$ with $s=\pm1$, and let $\rho$ be the projection forgetting $q_i$. For each point $w\in\rho(P)$ choose $m\in P\cap\rho^{-1}(w)$ with $sm_i$ maximal. Then $m+d$ lies in the same fibre and has a larger value of $sq_i$, so $m+d\notin P$. Thus $\rho$ maps $\{q\in P:q+d\notin P\}$ onto $\rho(P)$. +\end{proof} + +\begin{lemma}\label{lem:edges} +Let $\{i,j,l\}=\{1,2,3\}$ and $s,t\in\{\pm1\}$. Then $N_{se_i,te_j}(P)\ge\ell_l$. +\end{lemma} + +\begin{proof} +For each occupied value $z$ of $q_l$ choose $m\in P$ with $m_l=z$ such that $(sm_i,tm_j)$ is lexicographically maximal. The cells $m+se_i$ and $m+te_j$ have $l$-th coordinate $z$; the first has a larger value of $sq_i$, the second the same value of $sq_i$ and a larger value of $tq_j$. Both exceed $(sm_i,tm_j)$ lexicographically, so neither lies in $P$. Thus $q\mapsto q_l$ maps $\{q\in P:q+se_i\notin P,\ q+te_j\notin P\}$ onto the set of occupied values. +\end{proof} + +Each axis carries two directions and each of the three pairs of axes carries four perpendicular pairs of directions, so \eqref{eq:LBE} and Lemmas~\ref{lem:faces} and~\ref{lem:edges} give +\begin{equation}\label{eq:proj} +\LB(P)\ \ge\ 2(A_1+A_2+A_3)+4(\ell_1+\ell_2+\ell_3). +\end{equation} + +\begin{lemma}\label{lem:slices} +If $|P|=k^3$, then $\ell_1+\ell_2+\ell_3\ge3k$. +\end{lemma} + +\begin{proof} +$P$ is contained in the product of its three coordinate sets, so $k^3\le\ell_1\ell_2\ell_3$. By the AM--GM inequality $27\ell_1\ell_2\ell_3\le(\ell_1+\ell_2+\ell_3)^3$, hence $(3k)^3\le(\ell_1+\ell_2+\ell_3)^3$. +\end{proof} + +\begin{lemma}[slice-wise Loomis--Whitney]\label{lem:LW} +For every $k\in\N$, $4k|P|\le(A_3+k^2)(A_1+A_2)$. In particular, if $|P|=k^3$ then $A_1+A_2+A_3\ge3k^2$. +\end{lemma} + +\begin{proof} +For an occupied value $z$ of $q_3$ let $P_z=\{q\in P:q_3=z\}$, $m_z=|P_z|$, and let $\alpha_z,\beta_z$ be the sizes of the projections of $P_z$ forgetting $q_1$ and $q_2$, respectively. These projections keep $q_3$, so the projections of $P$ split by the value of $q_3$ and $\sum_z\alpha_z=A_1$, $\sum_z\beta_z=A_2$, $\sum_z m_z=|P|$. In $P_z$ a cell is determined by $(q_1,q_2)$, so $m_z\le A_3$; it is also determined by its two projections, so $m_z\le\alpha_z\beta_z$. Hence, using $4A_3k^2\le(A_3+k^2)^2$ and $4\alpha_z\beta_z\le(\alpha_z+\beta_z)^2$, +\[ +(4km_z)^2=4k^2\cdot4m_z^2\le(4A_3k^2)(4\alpha_z\beta_z)\le\bigl((A_3+k^2)(\alpha_z+\beta_z)\bigr)^2, +\] +so $4km_z\le(A_3+k^2)(\alpha_z+\beta_z)$. Summing over $z$ gives the first claim. If $|P|=k^3$, put $u=A_3+k^2$ and $v=A_1+A_2$; then $16k^4\le4uv\le(u+v)^2$, so $u+v\ge4k^2$. +\end{proof} + +The classical Loomis--Whitney inequality \cite{LW}, applied to the union of the unit cubes of $P$, gives the discrete form $|P|^2\le A_1A_2A_3$; with AM--GM it gives the same consequence. The form above, in which $\sqrt{A_3}$ is replaced by the AM--GM bound $(A_3+k^2)/(2k)$, avoids square roots. + +\begin{proposition}\label{prop:lower} +If $P\subset\Z^3$ is finite with $|P|=k^3$, then $\LB(P)\ge6k(k+2)$. +\end{proposition} + +\begin{proof} +By \eqref{eq:proj} and Lemmas~\ref{lem:slices} and~\ref{lem:LW}, $\LB(P)\ge2\cdot3k^2+4\cdot3k=6k^2+12k$. +\end{proof} + +\subsection{The cube} + +\begin{proposition}\label{prop:cube} +Let $k\ge2$ and $Q_k=\{0,\dots,k-1\}^3$. Then $Q_k$ is a polycube with $k^3$ cells and $\LB(Q_k)=6k(k+2)$. +\end{proposition} + +\begin{proof} +Every cell of $Q_k$ is joined to the origin inside $Q_k$ by moving along the first, then the second, then the third axis, so $Q_k$ is face-connected. For $q\in Q_k$ the direction $e_i$ is exposed iff $q_i=k-1$, and $-e_i$ iff $q_i=0$; as $k\ge2$, no two opposite directions are exposed. Put $u(x)=\ind{x=k-1}+\ind{x=0}\in\{0,1\}$ and $X_i=u(q_i)$. By the equality case of Lemma~\ref{lem:die}, $f(E_{Q_k}(q))=X_1+X_2+X_3+X_1X_2+X_1X_3+X_2X_3$, that is, +\[ +f(E_{Q_k}(q))+1+X_1X_2X_3=(1+X_1)(1+X_2)(1+X_3). +\] +A product of functions of one coordinate each sums over $Q_k$ to the product of the one-dimensional sums, and $\sum_{x=0}^{k-1}u(x)=2$. Summing over $q\in Q_k$ therefore gives $\LB(Q_k)+k^3+2^3=(k+2)^3$, so $\LB(Q_k)=6k^2+12k$. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +Let $k\ge2$. By Proposition~\ref{prop:cube}, $Q_k$ is a polycube with $k^3$ cells and $\LB(Q_k)=6k(k+2)$, and by Proposition~\ref{prop:lower} every polycube $P$ with $k^3$ cells has $\LB(P)\ge6k(k+2)$. Lemma~\ref{lem:reduce} gives $a(k^3)=6k(k+2)$. +\end{proof} + +\begin{remark}\label{rem:extra} +The following observations are not part of the formal development. +(1) Connectivity of $P$ is used only for the upper bound. +(2) Lemma~\ref{lem:die} holds for any labelling of a die with opposite faces summing to $7$, so the argument does not depend on chirality. +(3) Every face counted in Lemmas~\ref{lem:faces} and~\ref{lem:edges} sees infinity along a straight ray that avoids $P$, so these lemmas and \eqref{eq:LBE} remain valid when only faces facing the unbounded component of the complement are counted. Hence Theorem~\ref{thm:main} also holds if faces towards an enclosed cavity are not counted. +(4) For general $n$, the inequality $|P|^2\le A_1A_2A_3$ \cite{LW}, $|P|\le\ell_1\ell_2\ell_3$, AM--GM and \eqref{eq:proj} give $a(n)\ge6n^{2/3}+12n^{1/3}$, with equality for $n=k^3$, $k\ge2$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A363609.lean} in the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A363609.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is +\begin{lstlisting} +theorem result : statement +\end{lstlisting} +in the namespace \decl{Math0.Frontier.A363609}, so \decl{Math0.Frontier.A363609.result} has type exactly \decl{Math0.Statements.A363609.statement}. From the statement file the proof uses \decl{fmin_exposed} (the value $f(E_P(q))$ is the table entry \decl{tabF} at the six exposure flags, proved by kernel evaluation of the minimum over the $24$ orientations), \decl{LB_mem_totals} and \decl{a_eq_of} (together Lemma~\ref{lem:reduce}). The private auxiliary declarations of the proof file correspond to Section~\ref{sec:proof} as follows: \decl{tabF_lower} and \decl{tabF_upper} are Lemma~\ref{lem:die}, as $64$-case checks of the table by \texttt{decide}; \decl{E1}, \decl{E2} and \decl{LB_ge_E} are $N_d$, $N_{d,e}$ and \eqref{eq:LBE}; \decl{card_image_le_E1} and \decl{card_image_le_E2} are Lemmas~\ref{lem:faces} and~\ref{lem:edges} for an abstract projection and height function (via \decl{Finset.exists_max_image}, with the key \decl{toLex} in the second); \decl{LB_ge_proj} is \eqref{eq:proj}; \decl{amgm3} and \decl{sum3_ge} are Lemma~\ref{lem:slices}; \decl{slice_arith}, \decl{loomis} and \decl{sum2_ge} are Lemma~\ref{lem:LW}; \decl{LB_lower} is Proposition~\ref{prop:lower}; and \decl{cube}, \decl{card_cube}, \decl{mem_cube}, \decl{line}, \decl{cube_conn}, \decl{sum_cube_mul} and \decl{LB_cube} give Proposition~\ref{prop:cube}. Apart from small kernel-checked facts about the six directions, the only kernel computations the proof relies on are these two checks and, in the statement file, the evaluation of \decl{tabF} (\decl{fmin_sel}, by \texttt{decide +kernel}). \texttt{sorry}, \texttt{native\_decide} and \texttt{set\_option} do not occur in either file. + +\subsection*{Audit} +The file ends with the command +\begin{lstlisting} +#math0_settles Math0.Frontier.A363609.result Math0.Statements.A363609.statement +\end{lstlisting} +from \path{lean/Math0/Audit.lean}. It fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this excludes \decl{sorryAx}, \texttt{native\_decide} and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation, after removing metadata annotations, with no unfolding. On this file it reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A363609.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A363609.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A363609.result' proves 'Math0.Statements.A363609.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. To reproduce, run \path{scripts/verify.sh} from the repository root; it fetches the Mathlib cache, builds all math0 results with \texttt{lake build} (re-running every audit command) and checks that the pinned dependencies are unmodified. The single file is checked by \texttt{lake env lean Math0/Frontier/OEIS/A363609.lean} in \path{lean}, in about $16$ seconds once the statement module (whose kernel data checks take a few minutes) is built. + +\begin{thebibliography}{99} + +\bibitem{AMC} +Art of Problem Solving, \emph{2002 AMC 10A Problems/Problem 18}, \url{https://artofproblemsolving.com/wiki/index.php/2002_AMC_10A_Problems/Problem_18}. + +\bibitem{Don} +M.~Donahoe, \emph{Python program for A363609}, \url{https://github.com/mdonahoe/oeis/blob/main/A363609/dice.py}. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{LW} +L.~H. Loomis and H.~Whitney, \emph{An inequality related to the isoperimetric inequality}, Bull. Amer. Math. Soc. \textbf{55} (1949), 961--962. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{A001931} +The OEIS Foundation Inc., \url{https://oeis.org/A001931} (number of fixed 3-dimensional polycubes with $n$ cells). + +\bibitem{A193416} +The OEIS Foundation Inc., \url{https://oeis.org/A193416} (minimum surface area of polycubes with volume $n$), entry by J.~Barajas Martin (2011). + +\bibitem{A363609} +The OEIS Foundation Inc., \url{https://oeis.org/A363609}, entry by M.~Donahoe (2023). + +\end{thebibliography} + +\end{document} diff --git a/results/oeis-a367119/README.md b/results/oeis-a367119/README.md new file mode 100644 index 0000000..0215348 --- /dev/null +++ b/results/oeis-a367119/README.md @@ -0,0 +1,46 @@ +# Edges of the all-chords graph of a triangle with n general-position points per side (A367119) + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A367119 +**Date:** 2026-10-20 + +## Result + +Take the equilateral triangle with corners 0, 1 and 1/2 + (√3/2)i. Let B be the three corners together with exactly n points in the relative interior of each side, and no other points. Draw the segment between every pair of distinct points of B; pairs on a common side give pieces of that side. Assume general position: no interior point of the triangle lies on three pairwise distinct drawn segments. Form the planar graph whose vertices are the points of B together with every point where two drawn segments meet in a single point. Two distinct vertices are adjacent when they lie on a common drawn segment and no vertex lies strictly between them. Then for every n ≥ 0 this graph has (3/2)(3n^4 + 4n^3 + 3n^2 + 4n + 2) edges. This was conjectured by Shannon and Sloane for OEIS A367119. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A367119](https://oeis.org/A367119) as [`Math0.Statements.A367119.statement`](../../lean/Math0/Statements/OEIS/A367119.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A367119.lean`](../../lean/Math0/Frontier/OEIS/A367119.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F Conjecture: a(n) = (3/2)*(3*n^4 + 4*n^3 + 3*n^2 + 4*n + 2). (Scott R. Shannon and N. J. A. Sloane, Nov 05 2023) + +Referees: OEIS sources (read from the local mirror and checked against GitHub oeisdata main): +- A367119 (Shannon and Sloane, Nov 05 2023): the edge formula is still marked "Conjecture"; last edited Nov 09 2023. +- A367117: "Theorem: a(n) = (3/4)*(n+1)*(3*n^3+n^2+4)" for the vertex count of the same configuration. This is the key prior result, since the edge formula follows from it by degree counting: E = 2V + 3(n^2−1). +- A213827: "a(n) = (A367177 [sic, i.e. A367117](n) − 3*(n+1))/3 – Shannon & Sloane, Nov 09 2023". This is the interior-crossing count n^2(n+1)(3n+1)/4 per side-orbit. +- A367183 (Nov 13 2023): T(3,k) = A367117(k) appears apart from its "Conjectured" rows. +- A365929: Sloane's proof (Nov 07 2023) of the crossing count for the corner-free triangle variant. +- A366932 and A367015: the analogous edge and region conjectures, marked "now a theorem" by Sloane on Dec 31 2025. +- A392261, A392282, A392228 (Shannon and Sloane, Jan 2026): Shannon's attached proof (a392261.txt) of the general vertex, edge and region formulas for k general points per side of a regular n-gon without corners. The local mirror holds only a git-lfs pointer and the file could not be fetched; oeis.org was not queried, as instructed. +- A367190 and A366253: the triangle row (n=3) with corners is listed as a conjecture. + +Web searches (arXiv, Math StackExchange, general) found no paper or post that explicitly proves the A367119 or A367118 conjecture. The general method is the classical Euler-formula and crossing-count argument for chord arrangements (Moser's circle problem; Poonen–Rubinstein, arXiv math/9508209). + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a367119, + author = {{math0}}, + title = {{Edges of the all-chords graph of a triangle with n general-position points per side (A367119)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a367119}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a367119/paper.pdf b/results/oeis-a367119/paper.pdf new file mode 100644 index 0000000..5b24f49 Binary files /dev/null and b/results/oeis-a367119/paper.pdf differ diff --git a/results/oeis-a367119/paper.tex b/results/oeis-a367119/paper.tex new file mode 100644 index 0000000..7f60210 --- /dev/null +++ b/results/oeis-a367119/paper.tex @@ -0,0 +1,305 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + noncomputable,private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℂ}{{$\mathbb{C}$}}1 {ℕ}{{$\mathbb{N}$}}1 {ℝ}{{$\mathbb{R}$}}1 {ℚ}{{$\mathbb{Q}$}}1 + {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {→}{{$\to$}}1 {↔}{{$\leftrightarrow$}}1 + {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {∈}{{$\in$}}1 {∉}{{$\notin$}}1 + {∩}{{$\cap$}}1 {∪}{{$\cup$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {¬}{{$\neg$}}1 + {₁}{{$_1$}}1 {₂}{{$_2$}}1 {₃}{{$_3$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\C}{\mathbb{C}} +\newcommand{\re}{\operatorname{Re}} +\newcommand{\im}{\operatorname{Im}} +\newcommand{\inter}{\operatorname{int}} +\newcommand{\lean}[1]{{\upshape[#1]}} + +\title[Edges of the all-chords graph of a triangle (OEIS A367119)]{The all-chords graph of a triangle with $n$ points in general position on each side has $\tfrac32(3n^4+4n^3+3n^2+4n+2)$ edges} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + + +\begin{document} +\begin{abstract} +Place $n$ points in the relative interior of each side of an equilateral triangle, join every pair of the $3n+3$ boundary points (corners included) by a segment, and assume that no interior point lies on three segments. We prove that the resulting planar graph has $\frac32(3n^4+4n^3+3n^2+4n+2)$ edges for every $n\ge0$ and every such placement, as conjectured by S.~R. Shannon and N.~J.~A. Sloane in OEIS A367119 (2023), by counting the $3n(n+1)$ chords and the $\frac34n^2(n+1)(3n+1)$ crossing pairs of chords. The formula also follows in one line from the vertex count that the companion entry A367117 states as a theorem, so we classify the result as the first formal proof of a known result. The proof, including the geometric facts behind the count, is verified in Lean~4 with Mathlib against a statement that math0 formalized from the OEIS entry and froze after a fidelity review, before any proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +Place $n$ points in the relative interior of each side of an equilateral triangle $\Delta$ and join every pair of the $3n+3$ boundary points (corners included) by a segment. Pairs on a common side give pieces of that side; every other pair gives a \emph{chord} through the interior. If no interior point of $\Delta$ lies on three of the segments (general position), the drawing is a planar graph whose vertices are the boundary points and the crossing points of chords. The OEIS entries A367117, A367118 and A367119 \cite{A367117,A367118,A367119}, contributed by Scott R.~Shannon and N.~J.~A. Sloane on November~5, 2023, count its vertices, regions and edges, and A367119 conjectures that there are $\frac32(3n^4+4n^3+3n^2+4n+2)$ edges. We prove this for every placement in general position (Theorem~\ref{thm:main}), so the count does not depend on the placement, as the entry presupposes. + +\subsection*{Prior work and status} +A367119 (last revised November~9, 2023) and A367118 still list the edge and region formulas as conjectures, and so does the edge table A367190 \cite{A367190} for its triangle row. The vertex entry A367117, however, states as a theorem (without an argument) that there are $V(n)=\frac34(n+1)(3n^3+n^2+4)$ vertices, the table A367183 \cite{A367183} lists this row outside its conjectured rows, and a formula of Shannon and Sloane in A213827 \cite{A213827} (November~9, 2023) equates $n^2(n+1)(3n+1)/4$ with $(V(n)-3(n+1))/3$, a third of the interior crossings (it cites A367177, evidently a typo for A367117). The edge formula follows from $V(n)$ in one line: a chord carrying $m$ crossings is cut into $m+1$ edges, the boundary into $3n+3$ edges, and there are $3n(n+1)$ chords, so $E=3(n+1)+3n(n+1)+2(V-3n-3)=2V+3(n^2-1)$. +For the variant in which the corners are not endpoints of chords, Sloane proved the crossing count in A365929 \cite{A365929} (November~7, 2023) and marked the edge and region formulas of A366932 and A367015 \cite{A366932,A367015} as theorems (December~31, 2025); A392261, A392282, A392228 (January 2026) treat $k$ points per side of a regular $n$-gon, corners excluded, with a proof by Shannon attached to A392261 \cite{A392261} that we did not consult. Counting crossings of chords in general position by $4$-subsets of endpoints is classical; Poonen and Rubinstein \cite{PR} treat the non-generic case of the diagonals of a regular polygon. The math0 referees' searches (arXiv, Mathematics Stack Exchange, the web) found no source that explicitly proves the A367119 conjecture, and it is not in formal-conjectures \cite{FC}. +Since the formula is an immediate consequence of the vertex count recorded in A367117, we classify the result as the \emph{first formal proof of a known result}. Starting from the geometric definitions, the Lean proof also covers what the count takes for granted: chords cross exactly when their endpoints interleave, crossing points on a chord are distinct, and the sides carry no vertices besides the boundary points. + +\section{Statement}\label{sec:statement} + +Write $[p,q]$ and $(p,q)$ for closed and open segments in $\C=\mathbb{R}^2$. Let $c_0=0$, $c_1=1$, $c_2=\frac12+\frac{\sqrt3}{2}i$ (indices modulo~$3$), $\Delta=\operatorname{conv}\{c_0,c_1,c_2\}$, $S_j=[c_j,c_{j+1}]$ and $S_j^\circ=(c_j,c_{j+1})$. + +\begin{definition}\label{def:graph} +Let $n\ge0$. A \emph{placement} of $n$ points per side is a finite set $B\subset\C$ with $c_0,c_1,c_2\in B$, $B\subseteq S_0\cup S_1\cup S_2$ and $|B\cap S_j^\circ|=n$ for $j=0,1,2$. The \emph{drawn segments} are the $[p,q]$ with $p\ne q$ in $B$. $B$ is in \emph{general position} if no point of $\inter\Delta$ lies on three pairwise distinct drawn segments. The \emph{vertex set} $V(B)$ consists of the points of $B$ and every $z$ with $s\cap t=\{z\}$ for two drawn segments $s,t$. In the graph $G(B)$ on $\C$, distinct $u,v$ are adjacent if $u,v\in V(B)$, some drawn segment contains both, and $V(B)\cap(u,v)=\emptyset$. $E(B)$ is the number of edges of $G(B)$. +\end{definition} + +The entry A367119 \cite{A367119} has offset $0$ and $36$ listed terms $3, 24, 153, 588, 1635, 3708,\dots,7015788$. Its name, first comment and conjecture (Shannon and Sloane, November~5, 2023) read verbatim: +\begin{quote}\scriptsize\raggedright +\texttt{Place n points in general position on each side of an equilateral triangle, and join every pair of the 3*n+3 boundary points by a chord; sequence gives number of edges in the resulting planar graph.}\\ +\texttt{"In general position" implies that the internal lines (or chords) only have simple intersections. There is no interior point where three or more chords meet.}\\ +\texttt{Conjecture: a(n) = (3/2)*(3*n\^{}4 + 4*n\^{}3 + 3*n\^{}2 + 4*n + 2).} +\end{quote} + +\begin{theorem}\label{thm:main} +For every $n\ge0$ and every placement $B$ of $n$ points per side in general position, $E(B)=\frac32\bigl(3n^4+4n^3+3n^2+4n+2\bigr)$. +\end{theorem} + +\subsection*{Lean formalization} +The statement file \path{lean/Math0/Statements/OEIS/A367119.lean} (SHA-256 \texttt{0972bcc5\ldots 415bc4}) was written by math0, reviewed for fidelity and frozen before any proof attempt. Its definitions and statement read verbatim (namespace \decl{Math0.Statements.A367119}; docstrings and the computable part omitted): +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +noncomputable def corner : Fin 3 → ℂ := ![0, 1, ⟨1 / 2, Real.sqrt 3 / 2⟩] +noncomputable def triangle : Set ℂ := convexHull ℝ (Set.range corner) +def IsPlacement (n : ℕ) (B : Finset ℂ) : Prop := + (∀ j : Fin 3, corner j ∈ B) ∧ + (∀ z ∈ B, ∃ j : Fin 3, z ∈ segment ℝ (corner j) (corner (j + 1))) ∧ + (∀ j : Fin 3, ((B : Set ℂ) ∩ openSegment ℝ (corner j) (corner (j + 1))).ncard = n) +def drawn (B : Finset ℂ) : Set (Set ℂ) := + {s | ∃ p ∈ B, ∃ q ∈ B, p ≠ q ∧ s = segment ℝ p q} +def GeneralPosition (B : Finset ℂ) : Prop := + ∀ z ∈ interior triangle, ∀ s₁ ∈ drawn B, ∀ s₂ ∈ drawn B, ∀ s₃ ∈ drawn B, + z ∈ s₁ → z ∈ s₂ → z ∈ s₃ → s₁ = s₂ ∨ s₁ = s₃ ∨ s₂ = s₃ +def vertices (B : Finset ℂ) : Set ℂ := + (B : Set ℂ) ∪ {z | ∃ s ∈ drawn B, ∃ t ∈ drawn B, s ∩ t = {z}} +def planarGraph (B : Finset ℂ) : SimpleGraph ℂ := + SimpleGraph.fromRel fun u v => + u ∈ vertices B ∧ v ∈ vertices B ∧ (∃ s ∈ drawn B, u ∈ s ∧ v ∈ s) ∧ + ∀ w ∈ vertices B, w ∉ openSegment ℝ u v +noncomputable def edges (B : Finset ℂ) : ℕ := (planarGraph B).edgeSet.ncard +def statement : Prop := + ∀ (n : ℕ) (B : Finset ℂ), IsPlacement n B → GeneralPosition B → + (edges B : ℚ) = 3 / 2 * (3 * n ^ 4 + 4 * n ^ 3 + 3 * n ^ 2 + 4 * n + 2) +\end{lstlisting} +\emph{Encoding.} \texttt{corner j} is $c_j$ (\texttt{Fin 3} arithmetic makes side $2$ run from $c_2$ to $c_0$); the other definitions are those of Definition~\ref{def:graph}. \texttt{SimpleGraph.fromRel} symmetrizes the relation and removes loops; the edge set is finite, so \texttt{ncard} has no junk value. General position is the entry's comment read literally (a drawn segment through an interior point is a chord by Lemma~\ref{lem:chords}(e), so it concerns chords only), and $s\cap t=\{z\}$ keeps the points of overlapping pieces of a side out of the vertex set. The conclusion is an identity in $\mathbb{Q}$ for all $n\ge0$, matching the offset. It does not assert that general placements exist; they do (not formalized): the concurrence of three given chords at an interior point forces a polynomial equation in the positions of the $3n$ non-corner points that is not identically satisfied, since three such chords have six distinct endpoints and moving a non-corner one along its side breaks the concurrence; so a generic placement is in general position. + +\emph{Data check.} The statement file defines a computable model \texttt{a}: it numbers the boundary points $0,\dots,3n+2$ cyclically with corner $j$ at $j(n+1)$, takes as chords the pairs not on a common closed side, lets two chords cross when their endpoints interleave, and sets $\texttt{a}(n)=(3n+3)+\sum_{\text{chords }c}(1+\#\{\text{chords crossing }c\})$. The theorem \decl{a_data} checks $\texttt{a}(0),\dots,\texttt{a}(10)$ against the first eleven listed terms by \texttt{decide +kernel} (axiom: \decl{propext} only). The identity $\texttt{a}(n)=E(B)$ for placements in general position is not proved in Lean (it follows from Proposition~\ref{prop:edges} and Lemma~\ref{lem:chords}(c),(d), which are), and \decl{statement} does not use \texttt{a}. The formula agrees with all $36$ listed terms, and the referees' exact rational simulation of Definition~\ref{def:graph} on random placements gave $3,24,153,588,1635,3708$ for $n\le5$. + +\section{Proof}\label{sec:proof} + +We follow \path{lean/Math0/Frontier/OEIS/A367119.lean}; brackets give the corresponding (private) Lean declarations. For $p,q,z\in\C$ let $D(p,q,z)=\re(q-p)\im(z-p)-\im(q-p)\re(z-p)$; it is affine in $z$ and vanishes on $[p,q]$ \lean{\decl{D_comb}, \decl{D_of_mem_segment}}. + +\begin{lemma}\label{lem:D} +Let $p,q,r,s\in\C$. +(a) \lean{\decl{seg_inter_sub}} If $D(p,q,r)\ne0$, then $[p,q]\cap[r,s]$ has at most one point. +(b) \lean{\decl{crossPt_mem}} If $D(p,q,r)D(p,q,s)<0$ and $D(r,s,p)D(r,s,q)<0$, then $(p,q)\cap(r,s)\ne\emptyset$. +(c) \lean{\decl{seg_pos}, \decl{seg_neg}} If $D(p,q,r)$, $D(p,q,s)$ are both positive or both negative, $D(p,q,\cdot)$ has no zero on $[r,s]$. +\end{lemma} + +\begin{proof} +(a) $(1-\lambda)r+\lambda s\in[p,q]$ forces $(1-\lambda)D(p,q,r)+\lambda D(p,q,s)=0$, an affine equation in $\lambda$ that is not identically zero. (b) With $\alpha=D(p,q,r)$, $\beta=D(p,q,s)$, the point $X=(\alpha s-\beta r)/(\alpha-\beta)$ has positive coefficients on $r,s$, and a direct computation using $D(r,s,q)-D(r,s,p)=\alpha-\beta$ writes it with the positive coefficients $D(r,s,q)/(\alpha-\beta)$, $-D(r,s,p)/(\alpha-\beta)$ on $p,q$. (c) On $[r,s]$, $D(p,q,\cdot)$ takes convex combinations of its values at $r$ and $s$. +\end{proof} + +For $t\in[0,3)$ let $P(t)=x(t)+i\sqrt3\,y(t)$, where $(x,y)(t)$ is $(t,0)$ for $t\le1$, $\bigl(\frac{3-t}2,\frac{t-1}2\bigr)$ for $10$, then $z\in\inter\Delta$. +(e) \lean{\decl{exists_T}} If $B$ is a placement of $n$ points per side and $T=\theta(B)$, then $T\subset[0,3)$, $B=P(T)$, $0,1,2\in T$, $|T\cap I_j|=n$, $|T|=3n+3$ and $|T\cap\Sigma_j|=n+2$. +\end{lemma} + +\begin{proof} +(a)--(c) are computations; $\im P(t)=0$ exactly when $t\le1$, and $\re P(t)=(3-t)/2$ for $t>1$. (d) The numbers $\frac{2}{\sqrt3}\bigl(D(c_1,c_2,z),D(c_2,c_0,z),D(c_0,c_1,z)\bigr)$ sum to $1$ and are the barycentric coordinates of $z$; the set where all are positive is open and lies in $\Delta$. (e) By (b) each $z\in B$ is $P(t)$ with $t=\theta(z)\in[0,3)$; the corners give $0,1,2\in T$; $B\cap S_j^\circ=P(T\cap I_j)$ and (a) give $|T\cap I_j|=n$; and $T=\{0,1,2\}\sqcup\bigsqcup_j(T\cap I_j)$, while $T\cap\Sigma_j$ is $T\cap I_j$ plus two corner parameters. +\end{proof} + +From now on $B$ is a placement in general position and $T=\theta(B)$. A \emph{chord} is a pair $(a,b)$ with $a0$. +(b) \lean{\decl{E_sign}, \decl{P_not_mem_seg}} If $(a,b)$ is a chord and $t\in[0,3)\setminus\{a,b\}$, then $D(P(a),P(b),P(t))$ is negative if $a0$ at one of them, as $a,b$ are not both in $\Sigma_j$; so it is $>0$ on $(P(a),P(b))$. Apply Lemma~\ref{lem:param}(d); the sides lie on the zero lines. +(b) Some endpoint of $d$ is not an endpoint of $c$; by Lemma~\ref{lem:orient}(b) it lies off the line of $c$, and Lemma~\ref{lem:D}(a) applies. +(c) By Lemma~\ref{lem:orient}(b), interleaving puts $P(e),P(f)$ strictly on opposite sides of the line of $c$, and $P(a),P(b)$ on opposite sides of the line of $d$. Apply Lemma~\ref{lem:D}(b), then (b). +(d) Let $z$ be a common point. If $c,d$ share an endpoint $P(u)$, the other endpoint of $d$ is off the line of $c$, so $z=P(u)$ by Lemma~\ref{lem:D}(a), but $P(u)\notin(P(a),P(b))$. If they share no endpoint and do not interleave, then $e,f$ both lie in $(a,b)$ or both outside $[a,b]$, so $D(P(a),P(b),\cdot)$ has the same strict sign at $P(e)$, $P(f)$ (Lemma~\ref{lem:orient}(b)) and no zero on $[P(e),P(f)]$ (Lemma~\ref{lem:D}(c)), contradicting $D(P(a),P(b),z)=0$. +(e) holds as the sides are convex, and (f) follows from Lemma~\ref{lem:param}(b). (g) Pull back along $\lambda\mapsto p+\lambda(q-p)$: two real intervals whose interiors contain $\zeta$ share $[\zeta,\zeta+\varepsilon]$ for some $\varepsilon>0$. +\end{proof} + +For a chord $c$ let $\kappa(c)$ be the number of chords interleaving with $c$. + +\begin{proposition}\label{prop:vertices} +(a) \lean{\decl{V_chord}, \decl{VC_card}} For a chord $c=(a,b)$, $V(B)\cap[P(a),P(b)]=\{P(a),P(b)\}\cup\{X(c,d): d\text{ interleaves }c\}$, a set of exactly $2+\kappa(c)$ points. +(b) \lean{\decl{V_side}, \decl{VS_card}} $V(B)\cap S_j=P(T\cap\Sigma_j)$, a set of $n+2$ points. +\end{proposition} + +\begin{proof} +(a) The endpoints are in $B$, and $X(c,d)$ is a vertex since $\{X(c,d)\}=[P(a),P(b)]\cap[P(e),P(f)]$. Conversely, let $z\in V(B)\cap[P(a),P(b)]$, $z\ne P(a),P(b)$. Then $z\in(P(a),P(b))\subset\inter\Delta$, and $z\notin B$ by Lemma~\ref{lem:orient}(b), so $\{z\}=s\cap t$ for drawn segments $s\ne t$ (a drawn segment has two points). General position at $z$, applied to $[P(a),P(b)]$, $s$, $t$, shows that one of $s,t$ is $[P(a),P(b)]$; the other contains $z$, so by Lemma~\ref{lem:chords}(e),(a) it is the segment of a chord $d\ne c$, and by Lemma~\ref{lem:chords}(d),(c) $d$ interleaves $c$ and $z=X(c,d)$. +The points $X(c,d)$ lie in the open segment, so they differ from the endpoints, and $P(a)\ne P(b)$. If $X(c,d)=X(c,d')$ with $d\ne d'$, this interior point lies on the segments of $c,d,d'$, which are pairwise distinct by Lemma~\ref{lem:chords}(b) \lean{\decl{seg_ne}}, contradicting general position. +(b) The points of $B$ on $S_j$ are vertices and form $P(T\cap\Sigma_j)$, of size $n+2$. Conversely, let $z\in V(B)\cap S_j$, $z\notin B$, so $\{z\}=s\cap t$ for drawn segments $s,t$ and $z$ lies in the open segment of each. By Lemma~\ref{lem:chords}(a),(e), $s\subseteq S_k$ and $t\subseteq S_{k'}$. If $k=k'$, Lemma~\ref{lem:chords}(g) gives a second point of $s\cap t$; if $k\ne k'$, then $z$ is a corner by Lemma~\ref{lem:chords}(f), so $z\in B$. Both are impossible. +\end{proof} + +\begin{proposition}[\decl{edgeSet_eq}, \decl{EF_card}, \decl{edges_eq}]\label{prop:edges} +Call distinct $u,v$ in a finite set $F\subset\C$ \emph{consecutive} if $F\cap(u,v)=\emptyset$. The edge set of $G(B)$ is the disjoint union, over the sides $S_j$ and the chord segments $M$, of the sets of consecutive pairs of $V(B)\cap S_j$ and of $V(B)\cap M$. Hence +\[ +E(B)=\sum_{j=0}^2\bigl((n+2)-1\bigr)+\sum_{c}\bigl(\kappa(c)+1\bigr)=3(n+1)+\#\{\text{chords}\}+\sum_c\kappa(c). +\] +\end{proposition} + +\begin{proof} +Let $M$ be a side or a chord segment and $F_M=V(B)\cap M$. As $M$ is convex, a pair $\{u,v\}\subseteq M$ is an edge exactly when it is a consecutive pair of $F_M$ \lean{\decl{consF_iff}}. Every edge lies on a drawn segment, hence on some $M$ (Lemma~\ref{lem:chords}(e)), and every $M$ is drawn. The families are disjoint since an edge has two points: distinct chord segments share at most one point (Lemma~\ref{lem:chords}(b)), two sides share one corner (Lemma~\ref{lem:chords}(f)), and $S_j$ meets the segment of a chord $(a,b)$ only in its endpoints (Lemma~\ref{lem:chords}(a)), which are not both on $S_j$. A nonempty finite subset of a nondegenerate segment, pulled back to reals $\lambda_1<\dots<\lambda_k$ along an affine parametrization, has exactly the $k-1$ consecutive pairs $\{\lambda_i,\lambda_{i+1}\}$ \lean{\decl{consF_card}, \decl{consR_card}}. Proposition~\ref{prop:vertices} gives the sizes. +\end{proof} + +\begin{lemma}\label{lem:count} +(a) \lean{\decl{chords_card}} There are exactly $3n(n+1)$ chords. +(b) \lean{\decl{diag_iff}} Let $0\le wy\ge2$ when $w=0$; if $x,z\in\Sigma_2$, then $x>0$ forces $x\ge2$, so $y\in\Sigma_2$. (In Lean these checks go through a monotone region index $\rho:[0,3)\to\{0,\dots,5\}$ and \texttt{omega}.) +(c) Interleaving is symmetric and irreflexive, so $\sum_c\kappa(c)=2N$, where $N$ counts the pairs of chords $(w,y),(x,z)$ with $w 0 and T(n,0) = 0^n. Let A229580(n) be the number of colorings of the n X 2 array with colors 0..2 that have exactly one mistake and introduce colors in row-major 0..2 order. Here the array is connected horizontally and antidiagonally, and a mistake is an edge whose two ends have the same color. Then for every k ≥ 0, |Σ_{j=0}^{k} T(k+j,k)| = A229580(k+1). Both sides equal 1 for k = 0 and (2k+1)·2^(2k-1) for k ≥ 1. + +## Assessment + +The proof has two easy parts. First, the terms with n < k vanish, so the column sum is 2(-1)^k times an alternating binomial sum. That sum is one coefficient of an explicit polynomial and comes to -(2k+1)4^(k-1), which is a few lines of standard generating-function or finite-difference work. Second, the array graph is just a path on 2n cells taken in row-major order. Counting 3-colourings of it with exactly one monochromatic edge, up to relabelling the colours, gives (2n-1)*3*2^(2n-2)/6. This matches the closed form already listed in A229580. Each step is textbook material and the whole argument fits in well under a page, so the result is routine. The length of the Lean formalization does not change that. + +*Follows from:* The closed form A229580(n) = (2n-1)*2^(2n-3) is already listed in A229580 (Barbosa/Hillier, given without proof). The column sum is the standard alternating binomial sum Sum_n (-1)^n C(N,n) C(2n+1,2k), read off as a coefficient of (1+X)(1-(1+X)^2)^N = -(1+X) X^N (X+2)^N (equivalently, the N-th finite difference of a polynomial of degree N+1). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A368846](https://oeis.org/A368846) as [`Math0.Statements.A368846.statement`](../../lean/Math0/Statements/OEIS/A368846.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed before the proof, and CI checks that this order holds and that the frozen hash never changes. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A368846.lean`](../../lean/Math0/Frontier/OEIS/A368846.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C A368846 Conjecture: |Sum_{j=0..k} T(k + j, k)| = A229580(k + 1) for k >= 0. (_Peter Luschny_, Jan 07 2024) + +Referees: No prior proof or counterexample found. Checked: the A368846 entry (local mirror and the current oeisdata GitHub raw file, both rev #26, Feb 17 2025, still "Conjecture", no %E). A229580: closed form (2n-1)*2^(2n-3) credited to Gerson W. Barbosa/Gerald Hillier, 2018, given without proof; the recurrence and g.f. are marked "Empirical". OEIS entries citing A229580 (A383608, A385601, A386227 by Navarrete, 2025) and A368846 (A368847, A368848, A369134, A369135, A369120). T. Curtright, arXiv:2401.00586 and arXiv:2502.09633; T. Curtright and C. Vignat, arXiv:2504.18998 (they discuss diagonals of the inverse matrix, not column sums of M, and call combinatorial interpretations an open question). Blair–Flórez–Mukherjee, arXiv:2203.13205, is linked from A229580; I read only its link, not the paper. Web searches on arXiv, MSE, MathOverflow and SeqFan topics found nothing. + +## Citation + +```bibtex +@misc{math0:oeis-a368846, + author = {{math0}}, + title = {{Diagonal sums of A368846 equal A229580 (Luschny's conjecture)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a368846}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a369366/README.md b/results/oeis-a369366/README.md new file mode 100644 index 0000000..abc677a --- /dev/null +++ b/results/oeis-a369366/README.md @@ -0,0 +1,45 @@ +# The least number of inequivalent cells of a (6k+5)-iamond is 3(k+1) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A369366 +**Date:** 2026-10-20 + +## Result + +For every k >= 0, the least number of inequivalent cells over all polyiamonds with n = 6k+5 cells is 3(k+1). Two cells of P are equivalent when a symmetry of the triangular grid maps P onto itself and one cell to the other. This is Exley's conjecture in OEIS A369366, a(6k+5) = 3(k+1). + +## Assessment + +The lower bound was already argued in the entry's own comment. The only missing part was a polyiamond that reaches the bound. The obvious candidate works: a straight row of 2m+1 triangles is symmetric under the mirror through its middle cell, so it has at most m+1 classes, which is 3(k+1) when n = 6k+5. Both halves are a few lines of elementary symmetry counting, and the paper itself calls them elementary. The Lean work is careful, but the mathematics needed no new idea. + +*Follows from:* Exley's own comment in A369366, which already sketches the lower bound a(6k+5) >= ceiling(n/2) = 3(k+1) (an odd n rules out half-turns, and n = 2 mod 3 rules out 3-fold rotations). The matching upper bound comes from the straight row of 6k+5 triangles, which has one mirror symmetry. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A369366](https://oeis.org/A369366) as [`def statement`](../../lean/Math0/Statements/OEIS/A369366.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A369366.lean`](../../lean/Math0/Frontier/OEIS/A369366.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %C A369366 Conjecture: a(6k+5) = 3(k+1) for all k >= 0. Observed for k = 0, 1, 2 (n = 5, 11, 17). The next test case is a(23), predicted to be 12. (From _Peter Exley_, Apr 07 2026) + +Referees: OEIS A369366 (local mirror revision #14, Apr 14 2026, identical to oeisdata main): Exley's comment of Apr 07 2026 states the conjecture and already proves the lower bound a(6k+5) >= 3(k+1) (no rotations are possible when n = 6k+5, so |G_max| = 2). No upper-bound construction or full proof appears in the entry or its %E history. Cross-references checked: A369365, A369367, A369363, A369364, A367758, A367759, A373637, A376798, A376799. The only related proof is Mason and von Brömssen's formula proof for the polyomino analog A367758 (square lattice, a different problem). Exley's linked GitHub repo github.com/pexley-math/oeis-A369366 and the account page return 404 and could not be inspected. Web searches (arXiv, general web) found no prior resolution. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a369366, + author = {{math0}}, + title = {{The least number of inequivalent cells of a (6k+5)-iamond is 3(k+1)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a369366}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a369366/paper.pdf b/results/oeis-a369366/paper.pdf new file mode 100644 index 0000000..3617ad5 Binary files /dev/null and b/results/oeis-a369366/paper.pdf differ diff --git a/results/oeis-a369366/paper.tex b/results/oeis-a369366/paper.tex new file mode 100644 index 0000000..5825842 --- /dev/null +++ b/results/oeis-a369366/paper.tex @@ -0,0 +1,364 @@ +% math0 manuscript template. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{tikz} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, keepspaces=true, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 + {∃}{{$\exists$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {∈}{{$\in$}}1 + {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {×}{{$\times$}}1 {α}{{$\alpha$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\C}{\mathcal{C}} +\newcommand{\G}{\mathcal{G}} +\newcommand{\Stab}{\operatorname{Stab}} +\newcommand{\cls}{\operatorname{N}} + +\title[Inequivalent cells of $(6k+5)$-iamonds]{The least number of inequivalent cells in a polyiamond with $6k+5$ cells} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + +\begin{document} +\begin{abstract} +OEIS A369366 lists the least number $a(n)$ of inequivalent cells in a polyiamond with $n$ cells, two cells being equivalent when a symmetry of the polyiamond maps one to the other. We prove Peter Exley's conjecture that $a(6k+5)=3(k+1)$ for all $k\ge0$; the entry reports it as observed only for $k=0,1,2$. The lower bound is a coordinate version of the argument in Exley's own comment, and the bound is attained by the straight row of $6k+5$ triangles. Both halves are elementary; we classify the note as a new result, whose new content is the matching construction and a complete proof. The proof is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, checked in the kernel against the first eight listed terms, reviewed for fidelity and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +A \emph{polyiamond} with $n$ cells is an edge-connected set of $n$ triangles of the regular triangular tiling of the plane, holes allowed (A000577 \cite{A000577}). Two cells of a polyiamond $P$ are \emph{equivalent} if some isometry of the plane maps $P$ onto itself and one cell to the other. The OEIS sequence A369366 \cite{A369366}, contributed by Pontus von Brömssen on January~22, 2024, is the least number $a(n)$ of inequivalent cells in a polyiamond with $n$ cells, with data $1,1,2,2,3,1,3,3,3,3,6,2,4,4,4,4,9,2,5,6$ for $n=1,\dots,20$ ($a(18)$ by John Mason, 2024; $a(19),a(20)$ by Peter Exley, 2026). Related entries are A369365 \cite{A369365} (free rooted polyiamonds), A369367 \cite{A369367} (the number of polyiamonds attaining $a(n)$), and the analogues for polyominoes, polyhexes and polycubes, A367758 \cite{A367758}, A369363 and A376798. In a comment of April~7, 2026, Exley wrote (verbatim): +\begin{quote}\raggedright\small +\texttt{For n = 6k+5, no rotational symmetry is possible (n = 2 mod 3 blocks 3-fold rotation; n odd blocks 180-degree rotation), giving |G\_max| = 2 and a(6k+5) >= ceiling(n/2) = 3(k+1).} [\dots]\\[2pt] +\texttt{Conjecture: a(6k+5) = 3(k+1) for all k >= 0. Observed for k = 0, 1, 2 (n = 5, 11, 17). The next test case is a(23), predicted to be 12.} +\end{quote} + +\subsection*{Prior work} +Exley's comment thus contains the lower bound $a(6k+5)\ge3(k+1)$ with a sketch of its proof. The math0 referees read the entry at revision \#14 (April~14, 2026) and its edit history: it gives no construction attaining the bound for general $k$. The entry links a repository of Exley's code \cite{Exley}, which the referees could not inspect (HTTP 404). The cross-referenced entries A369365, A369367, A369363, A369364, A367758, A367759, A373637, A376798 and A376799 contain no proof for polyiamonds; the only related proof is Mason and von Brömssen's proof of a closed formula for the polyomino analogue A367758 \cite{MvB}, a different problem on the square lattice. Searches of arXiv and the general web found no resolution of the conjecture, and it is not among the statements of formal-conjectures \cite{FC} (commit \texttt{c77fdd4}). + +\subsection*{Contribution} +We prove the conjecture (Theorem~\ref{thm:main}). The lower bound (Proposition~\ref{prop:lower}) proves the bound of Exley's comment in integer coordinates, for every set of $6k+5$ cells, connected or not. For the upper bound we observe that the straight row of $2m+1$ triangles has a mirror symmetry exchanging its $j$-th and $(2m-j)$-th cells, so it has at most $m+1$ classes (Proposition~\ref{prop:upper}). Both steps are elementary. The proof is checked in Lean~4 (Section~\ref{sec:lean}). In particular $a(23)=12$, as Exley predicted. + +\section{Statement}\label{sec:statement} + +We use the integer coordinates of the formal statement. For $x\in\Z^3$ put $\sigma(x)=x_1+x_2+x_3$ and $\|x\|_1=|x_1|+|x_2|+|x_3|$. + +\begin{definition}\label{def:main} +(1) The \emph{cells} are the points of $\C=\{x\in\Z^3:\sigma(x)\in\{0,1\}\}$; cells $x,y$ are \emph{adjacent} if $\|x-y\|_1=1$. A \emph{polyiamond with $n$ cells} is a set $P\subseteq\C$ with $|P|=n$ in which any two cells are joined by a chain of cells of $P$, consecutive cells being adjacent. + +(2) Let $\Pi$ be the group of the six coordinate permutations of $\Z^3$. A \emph{grid symmetry} is a triple $g=(\pi,\varepsilon,t)$ with $\pi\in\Pi$, $\varepsilon\in\{1,-1\}$, $t\in\Z^3$, and $\sigma(t)=0$ if $\varepsilon=1$, $\sigma(t)=1$ if $\varepsilon=-1$; it acts by $g(x)=\varepsilon\,\pi(x)+t$. Let $\G$ be the set of grid symmetries. + +(3) For finite $P\subseteq\Z^3$ let $\Stab(P)=\{g\in\G: g(P)=P\}$. Write $c\sim_P d$ if $g(c)=d$ for some $g\in\Stab(P)$. Let $\cls(P)$ be the number of classes of $\sim_P$ on $P$, and $a(n)=\min\{\cls(P): P\text{ a polyiamond with $n$ cells}\}$. +\end{definition} + +\begin{theorem}[Exley's conjecture]\label{thm:main} +For every integer $k\ge0$, $a(6k+5)=3(k+1)$. +\end{theorem} + +\subsection*{Encoding} +The tiling is cut by three families of parallel lines. A triangle is labelled by the indices $(x_1,x_2,x_3)$ of the strips of the three families that contain it, shifted so that $\sigma(x)=0$ for one orientation of triangles and $\sigma(x)=1$ for the other. Each point of $\C$ labels exactly one triangle, and two triangles share an edge exactly when they are separated by one grid line and lie in the same strips of the other two families, that is, when $\|x-y\|_1=1$. The coordinate permutations exchange the line families, $x\mapsto -x+(\text{const})$ is a half-turn, and the translations of the tiling are the $t\in\Z^3$ with $\sigma(t)=0$; so $\G$ is the symmetry group $p6m$ of the tiling. The entry's equivalence uses all symmetries of the polyiamond, reflections included (``free'' rooted polyiamonds in A369365). This gives the same classes: an isometry of the plane mapping a polyiamond onto itself maps its corners, which are vertices of the tiling, to corners and edge directions at a corner to edge directions, so it is a symmetry of the tiling. + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A369366.lean}, reviewed for fidelity, and frozen before any proof attempt (SHA-256 hash beginning \texttt{3bce9518}). Its definitions and the statement read as follows, verbatim except that comments, docstrings, the proof of \decl{a_data} and all lemmas and auxiliary definitions between \decl{a} and \decl{a_data} are omitted: +\begin{lstlisting} +namespace Math0.Statements.A369366 +abbrev Pt := ℤ × ℤ × ℤ +def sumC (x : Pt) : ℤ := x.1 + x.2.1 + x.2.2 +def IsCell (x : Pt) : Prop := sumC x = 0 ∨ sumC x = 1 +def Adj (x y : Pt) : Prop := |y.1 - x.1| + |y.2.1 - x.2.1| + |y.2.2 - x.2.2| = 1 +def perm {α : Type} (s : Fin 6) (x : α × α × α) : α × α × α := + match s.val with + | 0 => (x.1, x.2.1, x.2.2) + | 1 => (x.1, x.2.2, x.2.1) + | 2 => (x.2.1, x.1, x.2.2) + | 3 => (x.2.1, x.2.2, x.1) + | 4 => (x.2.2, x.1, x.2.1) + | _ => (x.2.2, x.2.1, x.1) +def lin (s : Fin 6) (neg : Bool) (x : Pt) : Pt := if neg then -perm s x else perm s x +def tReq (neg : Bool) : ℤ := if neg then 1 else 0 +structure Isom where + s : Fin 6 + neg : Bool + t : Pt + ht : sumC t = tReq neg +def Isom.app (g : Isom) (x : Pt) : Pt := lin g.s g.neg x + g.t +def Step (P : Finset Pt) (u v : Pt) : Prop := u ∈ P ∧ v ∈ P ∧ Adj u v +def IsConnected (P : Finset Pt) : Prop := + ∀ x ∈ P, ∀ y ∈ P, Relation.ReflTransGen (Step P) x y +def IsPolyiamond (n : ℕ) (P : Finset Pt) : Prop := + P.card = n ∧ (∀ x ∈ P, IsCell x) ∧ IsConnected P +def Equivalent (P : Finset Pt) (c d : Pt) : Prop := + ∃ g : Isom, P.image g.app = P ∧ g.app c = d +open Classical in +noncomputable def cls (P : Finset Pt) (c : Pt) : Finset Pt := P.filter (Equivalent P c) +noncomputable def numClasses (P : Finset Pt) : ℕ := (P.image (cls P)).card +noncomputable def a (n : ℕ) : ℕ := + sInf {m | ∃ P : Finset Pt, IsPolyiamond n P ∧ numClasses P = m} +theorem a_data : (List.range 8).map (fun i => a (i + 1)) = [1, 1, 2, 2, 3, 1, 3, 3] +def statement : Prop := ∀ k : ℕ, a (6 * k + 5) = 3 * (k + 1) +end Math0.Statements.A369366 +\end{lstlisting} +Here \decl{Isom} is $\G$ (\texttt{neg = true} means $\varepsilon=-1$), \decl{Equivalent} is $\sim_P$ (proved to be an equivalence relation in the file), \texttt{cls P c} is the class of $c$, and \texttt{numClasses P} $=\cls(P)$ counts the distinct classes. \texttt{a n} is an infimum in $\N$ over a set that is nonempty for $n\ge1$ (it contains $\cls(T_n)$ of Section~\ref{sec:upper}), so the convention $\inf\emptyset=0$ plays no role. The statement is the conjecture for all $k\ge0$, with no further hypotheses. + +The theorem \decl{a_data} checks the listed terms $a(1),\dots,a(8)$. As \decl{a} is not computable, the file defines an enumeration \decl{aComp} of polyiamonds up to grid symmetry and proves $a(n)=$ \texttt{aComp n} for $n\ge1$ (\decl{a_eq_aComp}, using only soundness and completeness of the enumeration and the invariance of \decl{numClasses} under $\G$); the values are then computed by \texttt{decide +kernel}, in about a minute. Later terms are not checked in the kernel, since each further term roughly triples the cost. The fidelity reviewer recomputed in Python, on the same encoding, the numbers of free polyiamonds with $n\le13$ cells (matching A000577) and $a(1),\dots,a(13)$ (matching the data); a referee recomputed $a(1),\dots,a(12)$ with a geometric model of the tiling. + +\section{Proof}\label{sec:proof} + +We follow the Lean proof; Lean names are given in brackets. The statement file proves the facts about $\G$ that we use. Each $\pi\in\Pi$ is additive and preserves $\sigma$ and $\|\cdot\|_1$. Each $g\in\G$ is a bijection of $\Z^3$ that maps $\C$ to $\C$ and preserves adjacency. $\G$ is closed under composition and inverses: +\[ + (\pi,\varepsilon,t)\circ(\pi',\varepsilon',t')=(\pi\pi',\varepsilon\varepsilon',\varepsilon\pi(t')+t),\qquad (\pi,\varepsilon,t)^{-1}=(\pi^{-1},\varepsilon,-\varepsilon\pi^{-1}(t)). +\] +Hence so is $\Stab(P)$. For finite $P$, $g(P)\subseteq P$ already gives $g(P)=P$. Let $\Pi^+=\{\mathrm{id},\rho,\rho^2\}$, where $\rho(x_1,x_2,x_3)=(x_2,x_3,x_1)$, be the even permutations (indices $0,3,4$ of \decl{perm}) and $\Pi^-$ the three transpositions (indices $1,2,5$). Geometrically, the symmetries with $\varepsilon=1$ preserve the orientation of every cell (translations, $\pm120^\circ$ rotations, and reflections and glide reflections with $\pi\in\Pi^-$). Those with $\varepsilon=-1$ exchange the two orientations (half-turns, $\pm60^\circ$ rotations, and the remaining reflections and glide reflections). The proofs below do not use this dictionary. + +\subsection{Lower bound} + +\begin{lemma}[\decl{neg_eq_false}]\label{lem:neg} +Let $P\subseteq\Z^3$ be finite with $|P|$ odd, and $g=(\pi,\varepsilon,t)\in\Stab(P)$. Then $\varepsilon=1$. +\end{lemma} + +\begin{proof} +If $\varepsilon=-1$, then $\sigma(g(x))=-\sigma(\pi x)+\sigma(t)=1-\sigma(x)$ for all $x$. As $g$ permutes $P$, $S=\sum_{x\in P}\sigma(x)$ satisfies $S=\sum_{x\in P}\sigma(g(x))=\sum_{x\in P}(1-\sigma(x))=|P|-S$, so $|P|=2S$ is even. +\end{proof} + +\begin{lemma}[\decl{rot3_cube}, \decl{rot3_fix}]\label{lem:rot3} +Let $g=(\pi,1,t)\in\G$ with $\pi\in\{\rho,\rho^2\}$. Then (1) $g(g(g(x)))=x$ for all $x\in\Z^3$, and (2) $g$ fixes at most one cell. +\end{lemma} + +\begin{proof} +(1) As $\pi$ is additive, $g^3(x)=\pi^3(x)+\pi^2(t)+\pi(t)+t$. Here $\pi^3=\mathrm{id}$, and since $\pi$ permutes the coordinates cyclically, each coordinate of $\pi^2(t)+\pi(t)+t$ is $\sigma(t)=0$. +(2) If $x,y\in\C$ are fixed, then $\pi(x-y)=(g(x)-t)-(g(y)-t)=x-y$. A vector fixed by a cyclic shift has equal coordinates, so $x-y=(d,d,d)$ and $3d=\sigma(x)-\sigma(y)\in\{-1,0,1\}$. Hence $d=0$. (In Lean: a case split on $\pi$, then \texttt{omega}.) +\end{proof} + +\begin{lemma}[\decl{no_rot3}]\label{lem:norot3} +If $P\subseteq\C$ is finite with $|P|\equiv2\pmod3$, then $\Stab(P)$ contains no $(\pi,1,t)$ with $\pi\in\{\rho,\rho^2\}$. +\end{lemma} + +\begin{proof} +Such a $g$ restricts to $f\colon P\to P$ with $f^3=\mathrm{id}_P$ (Lemma~\ref{lem:rot3}(1)). If a self-map $f$ of a finite set satisfies $f^{p^r}=\mathrm{id}$ with $p$ prime, then $f$ is a bijection whose orbits have size $1$ or a positive power of $p$, so the size of the set is congruent modulo $p$ to the number of fixed points (Mathlib's \decl{Equiv.Perm.card_fixedPoints_modEq}, here with $p=3$, $r=1$). By Lemma~\ref{lem:rot3}(2), $f$ has at most one fixed point, so $|P|\equiv0$ or $1\pmod3$, a contradiction. +\end{proof} + +\begin{lemma}[\decl{rot_trivial}]\label{lem:rot} +Let $P\subseteq\C$ be finite with $|P|\equiv5\pmod 6$ and $g=(\pi,\varepsilon,t)\in\Stab(P)$ with $\pi\in\Pi^+$. Then $g$ is the identity of $\Z^3$. +\end{lemma} + +\begin{proof} +$\varepsilon=1$ by Lemma~\ref{lem:neg}, and $\pi\notin\{\rho,\rho^2\}$ by Lemma~\ref{lem:norot3}, as $|P|\equiv2\pmod3$. So $g(x)=x+t$, and since $g$ permutes $P$, $\sum_{x\in P}x=\sum_{x\in P}g(x)=\sum_{x\in P}x+|P|\,t$. Hence $t=0$, as $P\neq\emptyset$. (In Lean this is the statement file's centroid lemma \decl{t_eq_of_sym}: $t=(s-\varepsilon\pi(s))/|P|$, componentwise, for $g\in\Stab(P)$ and $s=\sum_{x\in P}x$.) +\end{proof} + +\begin{lemma}[\decl{three}, \decl{card_cls_le}]\label{lem:three} +Let $P\subseteq\C$ be finite with $|P|\equiv5\pmod6$. (1) If $c\sim_P d$ and $c\sim_P e$, then $d=c$, $e=c$ or $d=e$. (2) Every class of $\sim_P$ has at most two elements. +\end{lemma} + +\begin{proof} +(1) Let $d=g(c)$, $e=h(c)$ with $g,h\in\Stab(P)$, with permutation parts $\pi_g,\pi_h$. If $\pi_g\in\Pi^+$, then $d=c$ by Lemma~\ref{lem:rot}; likewise $e=c$ if $\pi_h\in\Pi^+$. Otherwise $\pi_g,\pi_h\in\Pi^-$, and $k=h\circ g^{-1}\in\Stab(P)$ has the even permutation part $\pi_h\pi_g^{-1}$ (\decl{mulTab_inv_even}, nine cases checked by \texttt{decide}). By Lemma~\ref{lem:rot}, $k=\mathrm{id}$, so $e=h(c)=k(g(c))=d$. +(2) Three distinct cells $x,y,z$ of one class satisfy $x\sim_P y$ and $x\sim_P z$, and (1) with $c=x$ gives a contradiction. +\end{proof} + +\begin{proposition}[\decl{lower}]\label{prop:lower} +If $P\subseteq\C$ is finite with $|P|\equiv5\pmod6$, then $|P|\le2\,\cls(P)$. In particular $\cls(P)\ge3k+3$ if $|P|=6k+5$. +\end{proposition} + +\begin{proof} +The $\cls(P)$ classes partition $P$ and have at most two elements each (Lemma~\ref{lem:three}). In Lean this is \decl{Finset.card_le_mul_card_image} for $c\mapsto$ \texttt{cls P c}. If $|P|=6k+5$, then $2\cls(P)\ge6k+5$, so $\cls(P)\ge3k+3$. +\end{proof} + +Compared with Exley's sketch: Lemma~\ref{lem:neg} excludes all symmetries that exchange the two cell orientations, half-turns included. Lemmas~\ref{lem:rot3} and~\ref{lem:norot3} exclude the $120^\circ$ rotations, and Lemma~\ref{lem:three} replaces the claim $|G_{\max}|=2$. + +\subsection{Upper bound}\label{sec:upper} + +For $j\in\N$ let $s_j=(\lceil j/2\rceil,-\lfloor j/2\rfloor,0)$ (\decl{stripCell}) and $T_n=\{s_j:0\le jm$, then $s_j\sim s_{2m-j}$ with $2m-j= 1, row n has exactly as many elements as the Zeckendorf representation of n has terms. In the formal statement, (T n).length = (Nat.zeckendorf n).length. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A373345](https://oeis.org/A373345) as [`Math0.Statements.A373345.statement`](../../lean/Math0/Statements/OEIS/A373345.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A373345.lean`](../../lean/Math0/Frontier/OEIS/A373345.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %Y A373345 Cf. A007895 (conjectured row lengths) ... (Paolo Xausa, Jun 01 2024). Likewise %Y A373557 Cf. ... A007895 (conjectured row lengths) (Paolo Xausa, Jun 09 2024). + +Referees: OEIS A371176 (Mikhail Kurkov, 2024): the formula a(n) = b(n)*A001316(b(n))/2 with b(n) = A048679(n), and the recursion a(n) = 2^(A072649(n)-1) + [c(n)>0]*2*a(c(n)), were present by Apr 20 2024 (oeisdata commit 6ea59dd), before the A373345 conjecture of Jun 1 2024. Both were stated without proof and imply popcount(A371176(n)) = A007895(n). Kurkov's comment of Oct 21 2024 states the explicit Zeckendorf-rewriting description of A371176(n). +H. V. Chu, "The Fibonacci Sequence and Schreier-Zeckendorf Sets", J. Integer Sequences 22 (2019), Art. 19.6.5 (arXiv:1906.10962), Theorem 3: a cardinality-preserving bijection between Schreier sets and Zeckendorf sets, which also preserves colex/binary order. +GitHub issue the-omega-institute/trureturing #9050 ("Research: full Schreier-Zeckendorf row-length identity (OEIS A373345)", by AlyciaBHZ, Sep 20 2026; confirmed when the manuscript was checked) presents the identity as an elementary consequence of Chu's bijection, as paper mathematics with no Lean formalization. +Background only: A. Bird, "Jozef Schreier, Schreier sets and the Fibonacci sequence", Out Of The Norm blog, 2012, gives the binary ordering and the R/S block recursion but does not mention Zeckendorf. H. V. Chu, arXiv:2606.21865 (2026), is a survey and does not state the identity. +No prior Lean formalization found. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a373345, + author = {{math0}}, + title = {{Row lengths of the Schreier-set triangle A373345 are A007895 (number of Zeckendorf summands)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a373345}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a373345/paper.pdf b/results/oeis-a373345/paper.pdf new file mode 100644 index 0000000..d4ab1d8 Binary files /dev/null and b/results/oeis-a373345/paper.pdf differ diff --git a/results/oeis-a373345/paper.tex b/results/oeis-a373345/paper.tex new file mode 100644 index 0000000..f746c09 --- /dev/null +++ b/results/oeis-a373345/paper.tex @@ -0,0 +1,351 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,rw,at,apply}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {↔}{{$\leftrightarrow$}}1 + {¬}{{$\neg$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 + {∧}{{$\wedge$}}1 {∨}{{$\vee$}}1 {·}{{$\cdot$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\IsTerm}{\mathrm{Term}} +\newcommand{\Bits}{\mathrm{B}} +\newcommand{\low}{\mathrm{low}} + +\title[Row lengths of the Schreier-set triangle A373345]{The $n$-th Schreier set in binary order has as many elements as the Zeckendorf representation of $n$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 25, 2026} + +\begin{document} +\begin{abstract} +A finite nonempty set $S$ of positive integers is a Schreier set if $|S|\le\min S$. List the Schreier sets in increasing order of the integer $\sum_{s\in S}2^{s-1}$; these integers form OEIS A371176, and the sets themselves are the rows of the triangle OEIS A373345. +We prove that for every $n\ge1$ the $n$-th Schreier set has exactly as many elements as the Zeckendorf representation of $n$ has terms, which is the conjecture ``A007895 (conjectured row lengths)'' recorded by Paolo Xausa in A373345. +The identity is known in substance: it follows from Chu's cardinality-preserving bijection between Schreier sets and Zeckendorf sets (2019) and from formulas stated without proof by Kurkov in A371176 before the conjecture was posed, and an informal proof was posted in September 2026. We therefore classify this note as the first formal proof of a known result. +The proof is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against all $91$ listed terms of A373345. +\end{abstract} +\maketitle + +\section{Introduction} + +Schreier sets were introduced by J.~Schreier \cite{Schreier} in a counterexample in the theory of weak convergence; a finite nonempty set $S\subset\Z_{>0}$ is a \emph{Schreier set} if $|S|\le\min S$. +Encoding $S$ by the integer $e(S)=\sum_{s\in S}2^{s-1}$, whose binary expansion has its ones exactly at the $1$-based positions $s\in S$, one has $|S|=w(e(S))$ and $\min S=\nu(e(S))$, where $w(k)$ is the binary weight of $k$ (OEIS A000120) and $\nu(k)=v_2(2k)$ is the ruler function (A001511). +Hence the codes of Schreier sets are exactly the positive integers $k$ with $w(k)\le\nu(k)$. This is the sequence A371176 \cite{A371176} (Mikhail Kurkov, March 14, 2024), $1,2,4,6,8,10,12,16,\dots$; the correspondence with Schreier sets, and with the ordering of Schreier sets described in a 2012 blog post of A.~Bird \cite{Bird}, was pointed out in comments by M.~Marcus and M.~S.~Branicky on May 31, 2024. +The triangle A373345 \cite{A373345} (Paolo Xausa, June 1, 2024) lists in row $n$ the elements of the Schreier set encoded by the $n$-th term of A371176, in decreasing order: the rows start $\{1\},\{2\},\{3\},\{3,2\},\{4\},\{4,2\},\{4,3\},\{5\},\dots$ +Its CROSSREFS section names A007895 \cite{A007895}, the number of terms in the Zeckendorf representation of $n$, as the ``conjectured row lengths''. We prove this conjecture (Theorem~\ref{thm:main}). + +\subsection*{Prior work and status} +The identity is not new in substance; we credit the earlier work as precisely as we can. +\begin{itemize} +\item \emph{Kurkov's formulas in A371176.} Revision \#14 of A371176 (April 20, 2024), which predates A373345, already contains, among other unproved formulas, the recursion +$a(n)=2^{A072649(n)-1}+[r(n)>0]\cdot2\,a(r(n))$ (written there with $c(n)$ for $r(n)$), where $a$ is A371176, $r(n)=A066628(n)$ is $n$ minus the largest Fibonacci number $\le n$, and $A072649(n)=p+1$ for $F_{p+2}\le n0$; the Zeckendorf count obeys the same recursion, so the formula implies the conjecture at once. The same revision also contains the formula $a(n)=b(n)\,A001316(b(n))/2$ with $b(n)=A048679(n)$; as $A001316(m)=2^{w(m)}$, and $b(n)$ is obtained from the binary form of the Zeckendorf representation of $n$ (the fibbinary number A003714$(n)$) by the rewriting $01\to1$, which keeps the number of ones, this too gives $w(a(n))=w(b(n))=A007895(n)$. A later comment of Kurkov (October 21, 2024) describes $a(n)$ explicitly by rewriting the Zeckendorf representation of $n$. All of these are stated without proof in the entry. +\item \emph{Chu's bijection.} H.~V.~Chu \cite{Chu} proved that the weak-Schreier subsets of $\{1,\dots,n\}$ (those with $\min S\ge|S|$, together with $\emptyset$) and the subsets without two consecutive integers are equinumerous (Theorem~3), by the explicit map $\{t_1<\dots0$ and $w(k)\le v_2(2k)$, and let $a(1)0$, $\mathtt{zeckendorf}\,m=g::\mathtt{zeckendorf}(m-F_g)$ with $g=\mathtt{greatestFib}\,m$ the largest index with $F_g\le m$; Mathlib proves (\decl{Nat.zeckendorfEquiv}) that it is the unique strictly decreasing list of indices $\ge2$, with adjacent entries differing by at least $2$, whose Fibonacci numbers sum to $m$, so its length is $z(m)=A007895(m)$. Row $n$ ($n\ge1$) is matched with $A007895(n)$; matching it with the first listed term $A007895(0)=0$ would fail already for row~$1$. + +The statement file anchors these definitions to the OEIS data. Since \texttt{Nat.nth}, \texttt{Nat.bitIndices} and \texttt{Nat.zeckendorf} are not suitable for kernel evaluation, it defines computable versions (a bounded search \texttt{code i} for the $i$-th term, a bit list \texttt{bitPos}, a fuel-bounded greedy Zeckendorf \texttt{zeckAux}) and proves them equal to the definitions above; it then checks the data with \texttt{decide +kernel}. The relevant theorems are (statements verbatim, proofs and the long data lists omitted): +\begin{lstlisting} +theorem code_eq_nth (i : ℕ) : code i = Nat.nth IsTerm i +theorem row_eq_T (n : ℕ) : row n = T n +theorem a_eq (m : ℕ) : a m = ((List.range m).flatMap (fun i => T (i + 1))).getD (m - 1) 0 +theorem a_data : (List.range 91).map (fun i => a (i + 1)) = [1, 2, 3, 3, 2, 4, ...] +theorem code_data : (List.range 42).map code = [1, 2, 4, 6, 8, 10, 12, 16, ...] +theorem statement_check : ∀ n, 1 ≤ n → n ≤ 42 → (T n).length = (Nat.zeckendorf n).length +\end{lstlisting} +Here \texttt{a m} is the $m$-th entry of the flattened triangle $T(1)\mathbin{+\!\!+}T(2)\mathbin{+\!\!+}\cdots$ (\decl{a_eq}). \decl{a_data} reproduces all $91$ listed terms of A373345 (rows $1$ to $42$), \decl{code_data} the first $42$ terms of A371176, and \decl{statement_check} the claimed identity for $n\le42$, as a check of the alignment of rows with A007895. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A373345.lean}; we give each lemma with the name of the corresponding private declaration. Throughout, $c(k)=\#\{j0$. +\end{lemma} + +\begin{proof} +Induction on $p$. For $p=0$, $j=0$ and $\Bits(1)=[0]$. For $p+1$, write $j=2j'$ or $j=2j'+1$ with $j'<2^p$. Then $2^{p+1}+2j'=2(2^p+j')$, so $\Bits(2^{p+1}+2j')=(\Bits(j')\mathbin{+\!\!+}[p])+1=\Bits(2j')\mathbin{+\!\!+}[p+1]$ by the induction hypothesis; the odd case is the same with $0$ prepended. +\end{proof} + +\begin{lemma}[\decl{isTerm_iff}]\label{lem:term} +For $k\ne0$, $k$ is a term if and only if $w(k)\le\low(k)+1$. +\end{lemma} + +\begin{proof} +This is \decl{padicValNat_two_mul} of the statement file: writing $k=2^v(2m+1)$, one has $v_2(2k)=v+1$ and $\low(k)=v$. +\end{proof} + +\begin{lemma}[\decl{isTerm_two_pow_add_even}, \decl{not_isTerm_two_pow_add_odd}]\label{lem:structure} +Let $p,i\ge0$. +\begin{enumerate} +\item If $2i<2^p$, then $2^p+2i$ is a term if and only if $i=0$ or $i$ is a term. +\item If $2i+1<2^p$, then $2^p+2i+1$ is not a term. +\end{enumerate} +\end{lemma} + +\begin{proof} +(1) If $i=0$, then $w(2^p)=1\le p+1=v_2(2^{p+1})$, so $2^p$ is a term (\decl{isTerm_two_pow}). If $i>0$, write $\Bits(i)=b::\ell$. By Lemma~\ref{lem:bits}, $\Bits(2^p+2i)=(b+1)::(\ell+1)\mathbin{+\!\!+}[p]$, so $w(2^p+2i)=|\ell|+2$ and $\low(2^p+2i)=b+1$. By Lemma~\ref{lem:term} the condition for $2^p+2i$ is $|\ell|+2\le b+2$, which is the condition $|\ell|+1\le b+1$ for $i$. +(2) $\Bits(2^p+2i+1)=0::(\Bits(i)+1)\mathbin{+\!\!+}[p]$ has length at least $2$ and first entry $0$, and $2>0+1$. +\end{proof} + +\begin{lemma}[\decl{count_two_pow_add}]\label{lem:count} +If $2i\le2^p$, then $c(2^p+2i)=c(2^p)+c(i)+[i\ne0]$. +\end{lemma} + +\begin{proof} +Induction on $i$; the case $i=0$ is trivial. Let $2(i+1)\le2^p$, so $2i+1<2^p$. By definition of $c$ and the induction hypothesis, +\[ +c(2^p+2i+2)=c(2^p)+c(i)+[i\ne0]+[2^p+2i\text{ is a term}]+[2^p+2i+1\text{ is a term}], +\] +while $c(2^p)+c(i+1)+1=c(2^p)+c(i)+[i\text{ is a term}]+1$. The last bracket on the first line is $0$ by Lemma~\ref{lem:structure}(2). If $i=0$, the first line is $c(2^p)+0+0+1+0$ and the second $c(2^p)+0+0+1$, since $0$ is not a term. If $i\ne0$, the first line is $c(2^p)+c(i)+1+[i\text{ is a term}]$ by Lemma~\ref{lem:structure}(1), which is the second. +\end{proof} + +\begin{lemma}[\decl{count_two_pow}]\label{lem:fib} +For every $p\ge0$, $c(2^p)+1=F_{p+2}$. +\end{lemma} + +\begin{proof} +We prove $c(2^p)+1=F_{p+2}$ and $c(2^{p+1})+1=F_{p+3}$ together, by induction on $p$. For $p=0$: $c(1)=0$ since $0$ is not a term, and $c(2)=1$ since $1$ is a term; $F_2=1$, $F_3=2$. For the step, Lemma~\ref{lem:count} with $p+1$ in place of $p$ and $i=2^p$ gives $c(2^{p+2})=c(2^{p+1})+c(2^p)+1$, hence $c(2^{p+2})+1=F_{p+3}+F_{p+2}=F_{p+4}$. +\end{proof} + +Since the terms below $2^p$ are the codes of the Schreier sets contained in $\{1,\dots,p\}$, Lemma~\ref{lem:fib} is the known count of these sets (cf.\ \cite{Chu,Bird}). + +\begin{lemma}[\decl{zeckendorf_fib_add}]\label{lem:zeck} +If $m0$. Then $F_{p+2}\le Nb$ for all $b$. Hence (\decl{Nat.nth_mem_of_infinite}, \decl{Nat.count_nth_of_infinite}) $k=\mathtt{Nat.nth\ IsTerm}\,(n-1)=a(n)$ is a term with $c(k)=n-1$. The length of $T(n)$ is the length of $\Bits(k)$, i.e.\ $w(k)$, and by Proposition~\ref{prop:main} $w(k)=\zeta(c(k)+1)=\zeta(n)$ for $n\ge1$. +\end{proof} + +\begin{remark}[Kurkov's recursion]\label{rem:kurkov} +The proof of Proposition~\ref{prop:main} shows more: if $k=a(n)$ has top bit $p$, then $F_{p+2}\le n0]\cdot2a(r(n))$ quoted in the introduction, with $r(n)=n'$. The Lean file does not state this recursion as a separate declaration. +\end{remark} + +\begin{remark}[A second proof via Chu's bijection; not formalized]\label{rem:chu} +Order finite sets of positive integers colexicographically, $S\prec S'$ if $\max(S\triangle S')\in S'$; this is the order of the codes $e(S)$, and also the lexicographic order of the decreasing sequences of elements, a proper prefix coming first. For a Schreier set with elements $s_1>s_2>\dots>s_r$, Chu's map \cite{Chu} is $f(S)=\{s_1,s_2-1,\dots,s_r-(r-1)\}$. Since $s_r\ge r$, $f(S)$ is a set of positive integers with gaps $\ge2$, and $f$ is a bijection from Schreier sets onto nonempty sets without two consecutive integers, with inverse adding $j-1$ to the $j$-th largest element. It preserves cardinality and maximum, and it preserves the lexicographic order of decreasing sequences, since at the first position $j$ where two sequences differ both entries are lowered by $j-1$. Both families are ordered with finitely many predecessors for each element, so $f$ maps the $n$-th Schreier set to the $n$-th nonempty set $Z_n$ without consecutive integers. Finally, $Z\mapsto\sum_{z\in Z}F_{z+1}$ is the Zeckendorf bijection onto $\N$ (with $\emptyset\mapsto0$), and it is increasing for $\prec$ because $\sum_{z\in Z}F_{z+1}= 1, row n has as many elements as there are terms in the Zeckendorf representation of n. Equivalently, popcount(A371176(n)) = A007895(n). + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A373359](https://oeis.org/A373359) as [`Math0.Statements.A373359.statement`](../../lean/Math0/Statements/OEIS/A373359.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A373359.lean`](../../lean/Math0/Frontier/OEIS/A373359.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %Y A373359 Cf. A007895 (conjectured row lengths), A373346 (row sums), A373347. (_Paolo Xausa_, Jun 04 2024; the same 'conjectured row lengths' cross-reference appears in A373345 and A373579) + +Referees: - OEIS A373359 and A373345 (Paolo Xausa, Jun 2024): "A007895 (conjectured row lengths)". Local mirror and upstream are unchanged. +- OEIS A371176 (Mikhail Kurkov, Mar 14 2024): + - formula a(n) = 2^(A072649(n)-1) + [c(n)>0]*2*a(c(n)) with c = A066628; + - formula a(n) = b(n)*A001316(b(n))/2 with b = A048679; + - Kurkov comment of Oct 21 2024: A371176(n) is the Zeckendorf representation of n with the 01->1 rewrite and k-1 zeros appended. Each implies popcount(A371176(n)) = A007895(n). +- A007895 formula a(n) = A000120(A003714(n)) (Zumkeller 2005). +- GitHub issue the-omega-institute/trureturing #9050 (Sep 20 2026): https://github.com/the-omega-institute/trureturing/issues/9050. An informal proof of the A373345/A373359 row-length identity, via Chu's bijection plus order preservation and via Bird's recursive blocks. +- H. V. Chu, "The Fibonacci Sequence and Schreier-Zeckendorf Sets", J. Integer Seq. 22 (2019), Art. 19.6.5 (arXiv:1906.10962): the bijection between Schreier sets and Zeckendorf sets. +- A. Bird, "Jozef Schreier, Schreier sets and the Fibonacci sequence", Out Of The Norm blog, May 13 2012: binary ordering of Schreier sets and |M_n| = F_n. +- H. V. Chu, arXiv:2606.21865 (2026), a survey that does not state the binary-rank theorem. +- I found no prior Lean or other formal proof. + +## Citation + +```bibtex +@misc{math0:oeis-a373359, + author = {{math0}}, + title = {{A373359: Schreier-set row lengths equal the Zeckendorf weight A007895}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a373359}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a375522/README.md b/results/oeis-a375522/README.md new file mode 100644 index 0000000..30f7eaa --- /dev/null +++ b/results/oeis-a375522/README.md @@ -0,0 +1,45 @@ +# A375522: S2(n) - S1(n) = 1 fails at n = 42 (the difference is 5) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Number theory +**Source problem:** OEIS A375522 +**Date:** 2026-10-18 + +## Result + +Let p_k be the k-th prime. Define s(0) = 0 and s(k) = s(k-1) + 1/(p_k b(k)), where b(k) = 1 + floor(1/((1 - s(k-1)) p_k)) (this is A375781). Write s(n) = S1(n)/S2(n) in lowest terms (S2 = A375522, S1 = A375521). Sigrist and Sloane conjectured that S2(n) - S1(n) = 1 for every n >= 1 except n = 4 and n = 6. This is false: S2(42) - S1(42) = 5. Lean: theorem result : ¬ statement. + +## Assessment + +The conjecture is refuted by one computed value: S2(42) - S1(42) = 5. Note that S2(42) has about 4*10^11 digits, so it cannot be computed directly. The only idea needed is a standard one. The difference S2(n) - S1(n) is the small numerator of the remainder 1 - s(n), and it depends only on the huge denominator modulo small numbers, so you track that denominator modulo a large smooth modulus and account for the precision lost when you cancel the gcd at each step. That bookkeeping lemma takes about a page and is elementary. Once it is set up, the result is a finite computation, so the work is routine, although the counterexample is real and was out of reach of the authors' direct computation up to n = 34. + +*Follows from:* The entry's own recursion (its Maple/Mathematica programs), run as a finite computation modulo a smooth modulus such as (190!)^2. If 1 - s(n-1) = 1/D, then 1 - s(n) = m/(D(D+m)) with m = p_n - (D mod p_n). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A375522](https://oeis.org/A375522) as [`Math0.Statements.A375522.statement`](../../lean/Math0/Statements/OEIS/A375522.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A375522.lean`](../../lean/Math0/Frontier/OEIS/A375522.lean) refutes (proves the negation of) it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: The differences S2(n) - S1(n) are surprisingly small: for n = 1,2,...,34 the values S2(n) - S1(n) are: 1, 1, 1, 2, 1, 2, 1, 1, ..., 1 suggesting the conjecture that they are always 1 except for n = 4 and 6 (compare the Theorem in A374983). (Rémy Sigrist and N. J. A. Sloane, Aug 30 2024) + +Referees: The conjecture is in OEIS A375522 (R. Sigrist and N. J. A. Sloane, Aug 30 2024; comment added Aug 31 2024; current revision #25, Apr 22 2025). It is restated as still open ("it seems") in A375528 (Sloane, Sep/Oct 2024). Related: A375521, A375781, A374983/A375516 (harmonic analogue, proved by Sigrist), and Sloane, "A Nasty Surprise in a Sequence and Other OEIS Stories", Rutgers Experimental Math Seminar, Oct 10 2024 (slides list these sequences and a general Conjecture 4, with no counterexample). Sigrist and Sloane, "Dampening Down a Divergent Series", is still cited on OEIS as a manuscript in preparation. No prior counterexample or proof turned up in the OEIS histories, arXiv (e.g. Fried arXiv:2607.24832 does not cover it), web searches, or google-deepmind/formal-conjectures. The SeqFan archive could not be reached. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a375522, + author = {{math0}}, + title = {{A375522: S2(n) - S1(n) = 1 fails at n = 42 (the difference is 5)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a375522}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a375522/paper.pdf b/results/oeis-a375522/paper.pdf new file mode 100644 index 0000000..c1bade1 Binary files /dev/null and b/results/oeis-a375522/paper.pdf differ diff --git a/results/oeis-a375522/paper.tex b/results/oeis-a375522/paper.tex new file mode 100644 index 0000000..037ba8d --- /dev/null +++ b/results/oeis-a375522/paper.tex @@ -0,0 +1,393 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{booktabs} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + upquote=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℚ}{{$\mathbb{Q}$}}1 + {→}{{$\to$}}1 {≠}{{$\ne$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 {⌊}{{$\lfloor$}}1 {⌋}{{$\rfloor$}}1 {∑}{{$\sum$}}1 + {…}{{$\dots$}}1 {·}{{$\cdot$}}1 {×}{{$\times$}}1 {∣}{{$\mid$}}1 {⟨}{{$\langle$}}1 + {⟩}{{$\rangle$}}1 {≡}{{$\equiv$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{…}{\ensuremath{\dots}} +\newunicodechar{é}{\'e} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} +\DeclareMathOperator{\num}{num} +\DeclareMathOperator{\den}{den} +\newcommand{\fl}[1]{\left\lfloor #1\right\rfloor} + +\title[A counterexample to a conjecture in OEIS A375522]{The greedy prime-reciprocal sums of OEIS A375781:\\ $S_2(42)-S_1(42)=5$, refuting a conjecture of Sigrist and Sloane} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Let $p_k$ be the $k$-th prime, let $b(k)$ (OEIS A375781) be the least positive integer keeping $s(k)=\sum_{j\le k}1/(p_j\,b(j))$ below $1$, and write $s(n)=S_1(n)/S_2(n)$ in lowest terms (A375521, A375522). +Sigrist and Sloane conjectured that $S_2(n)-S_1(n)=1$ for all $n\ge1$ except $n=4,6$, having checked $n\le 34$. +We show that $S_2(42)-S_1(42)=5$, so the conjecture is false; to our knowledge this is a new result. As $S_2(42)$ has about $3.9\cdot 10^{11}$ decimal digits, the proof tracks the numerator of $1-s(n)$ exactly and its denominator only modulo a shrinking modulus, with a lemma certifying each step. +The proof is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, checked against the OEIS data and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +Since $\sum_k 1/p_k$ diverges, one can ask how much each term must be damped to keep the partial sums below~$1$. Rémy Sigrist's sequence A375781 \cite{OEISrel} is the lexicographically earliest sequence of positive integers $b(1),b(2),\dots$ with $s(n)=\sum_{k=1}^{n}1/(p_k\,b(k))<1$ for all $n\ge1$, where $p_k$ is the $k$-th prime. It begins $1,1,2,3,5,89,39304,46994541278,\dots$ and grows doubly exponentially. +Sigrist and Sloane wrote $s(n)=S_1(n)/S_2(n)$ in lowest terms; $S_1$ and $S_2$ are A375521 \cite{OEISrel} and A375522 \cite{A375522}. +In A375522 they reported that $S_2(n)-S_1(n)$ equals $1$ for $1\le n\le 34$, except at $n=4$ and $n=6$, where it equals~$2$, and conjectured that this pattern continues for all~$n$ (Section~\ref{sec:statement}). +Equivalently, the remainder $1-s(n)$ is a unit fraction for every $n\ge1$ except $n=4,6$. + +The conjecture is modelled on a theorem about the harmonic series. For the analogous greedy sequence A374663, with $k$ in place of $p_k$, Sigrist proved that every remainder $1-s(n)$ with $n>1$ is the reciprocal of an integer \cite{OEISrel,SigristProof}. +In A375528 \cite{OEISrel}, the analogue for the lucky numbers, Sloane writes that for the primes ``it seems that all partial sums except for $n = 4$ and $6$ have this property''. +The sequences are discussed in Sloane's talk at the Rutgers Experimental Mathematics Seminar \cite{SloaneTalk}; the slides list them and give no counterexample. They also state a more general conjecture (Conjecture~4 there): for such dampened series there are a constant $c$ and integers $e_n$ with $s(n)=(e_n-c)/e_n$ for all sufficiently large~$n$. Our result does not decide that conjecture. +The entries A374663 and A376048 \cite{OEISrel} cite a manuscript in preparation by Sigrist and Sloane, \emph{Dampening Down a Divergent Series} \cite{SiSl}. + +\subsection*{Result and status} +We prove that $S_2(42)-S_1(42)=5$ (Theorem~\ref{thm:main}), so the conjecture is false. +The math0 referees found no earlier counterexample or proof in the revision histories of A375522 and the related entries above, the slides of \cite{SloaneTalk}, arXiv (the recent collection \cite{Fried} of proofs of OEIS conjectures does not treat these sequences), web searches, or the formal-conjectures repository \cite{FC}, which does not contain this conjecture. The archive of the SeqFan mailing list could not be reached and was not searched. With that caveat, we classify the result as \emph{new}. + +The difficulty is size. If $1-s(n-1)=1/D$, then $1-s(n)=(p_n-r)/\bigl(D(D+p_n-r)\bigr)$ with $r=D\bmod p_n$ (Remark~\ref{rem:unit}), so the denominators roughly square at each step: $S_2(20)$ has $92406$ decimal digits, and $S_2(42)$ has about $3.9\cdot10^{11}$ digits. We never compute $S_2(42)$. Instead we track the small numerator $u_n$ of $1-s(n)$ exactly and the denominator only modulo a modulus that shrinks at each step (Lemma~\ref{lem:mod}); the Lean kernel runs and checks this computation. +Numerical computations outside the formal proof show that $n=42$ is the smallest counterexample, and that further counterexamples occur at $n=50$ (difference $3$), $n=56$ and $n=59$ (difference $5$ in both cases), with no others for $n\le 70$. + +\section{Statement}\label{sec:statement} + +\subsection{The sequences} +Let $p_k$ denote the $k$-th prime ($p_1=2$). For $x\in\Q$ let $\num(x)\in\Z$ and $\den(x)\in\N_{>0}$ be its numerator and denominator in lowest terms. Define $s(0)=0$ and, for $n\ge1$, +\begin{equation}\label{eq:rec} + b(n)=1+\fl{\frac{1}{(1-s(n-1))\,p_n}},\qquad s(n)=s(n-1)+\frac{1}{p_n\,b(n)}. +\end{equation} +By Lemma~\ref{lem:T} below, $0<1-s(n)\le 1$ for all~$n$, so \eqref{eq:rec} is well defined. +For $c\in\N_{>0}$, $s(n-1)+1/(p_nc)<1$ if and only if $c>1/((1-s(n-1))p_n)$, i.e.\ $c\ge b(n)$; as every admissible prefix extends, $b$ is the lexicographically earliest admissible sequence, the OEIS definition of A375781. Put $S_1(n)=\num(s(n))$ and $S_2(n)=\den(s(n))$. + +\begin{theorem}\label{thm:main} +$S_2(42)-S_1(42)=5$. +\end{theorem} + +\begin{corollary}\label{cor:main} +The following statement is false: for every $n\ge1$ with $n\ne4$ and $n\ne6$, $S_2(n)-S_1(n)=1$. +\end{corollary} + +\subsection{The OEIS conjecture} +The conjecture is a comment in A375522 \cite{A375522}, an entry by Rémy Sigrist and N.~J.~A. Sloane dated Aug 30 2024 (revision \#25, Apr 22 2025). It reads verbatim: +\begin{quote}\small +Let S(n) = Sum\_\{k = 1..n\} 1 / (k*A375781(k)) = S1(n)/S2(n) when reduced to lowest terms, where S1(n) = A375521(n), S2(n) = the present sequence. +The differences S2(n) - S1(n) are surprisingly small: for n = 1,2,...,34 the values S2(n) - S1(n) are: +1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +suggesting the conjecture that they are always 1 except for n = 4 and 6 (compare the Theorem in A374983). +\end{quote} +The entry's name and this comment write $1/(k\cdot\mathrm{A375781}(k))$. The data, the worked example ($0/1, 1/2, 5/6, 14/15,\dots$) and the Maple, Mathematica and Python programs of A375521, A375522 and A375781 all use $1/(p_k\cdot\mathrm{A375781}(k))$. With $k$ read literally the first sum would already be $1/(1\cdot1)=1$, contradicting $S_2(1)=2$. So ``$k$'' is a typo for $\mathrm{prime}(k)$, and \eqref{eq:rec} is exactly the recursion in the entries' Maple and Mathematica programs. + +\subsection{The Lean statement} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A375522.lean} (namespace \decl{Math0.Statements.A375522}). It was reviewed for fidelity and frozen (SHA-256 \texttt{3eec79b4\dots ced342}) before any proof attempt. The primes are computed by a bounded search (docstrings omitted): +\begin{lstlisting} +def firstPrimeFrom : ℕ → ℕ → ℕ + | 0, _ => 0 + | fuel + 1, q => if q.Prime then q else firstPrimeFrom fuel (q + 1) +def nextPrime (m : ℕ) : ℕ := firstPrimeFrom (m + 2) (m + 1) +def primeAt : ℕ → ℕ + | 0 => 2 + | i + 1 => nextPrime (primeAt i) +def prime (k : ℕ) : ℕ := primeAt (k - 1) +\end{lstlisting} +The sums, the three sequences and the statement are (verbatim): +\begin{lstlisting} +/-- `s n = ∑_{k = 1..n} 1 / (prime k * b k)` with the greedy +`b k = 1 + ⌊1 / ((1 - s (k - 1)) * prime k)⌋` (A375781), `s 0 = 0`. -/ +def s : ℕ → ℚ + | 0 => 0 + | n + 1 => s n + 1 / ((prime (n + 1) : ℚ) * + ((1 + ⌊1 / ((1 - s n) * (prime (n + 1) : ℚ))⌋ : ℤ) : ℚ)) + +/-- A375781: `b n = 1 + floor(1/((1 - s(n-1)) * prime(n)))` for `n ≥ 1`. -/ +def b (n : ℕ) : ℤ := 1 + ⌊1 / ((1 - s (n - 1)) * (prime n : ℚ))⌋ + +/-- A375521: `S1 n`, the numerator of `s n` in lowest terms. -/ +def S1 (n : ℕ) : ℤ := (s n).num + +/-- A375522: `a n = S2 n`, the denominator of `s n = ∑_{k = 1..n} 1 / (prime k * A375781 k)` +in lowest terms. -/ +def a (n : ℕ) : ℕ := (s n).den + +/-- Conjecture (Sigrist and Sloane, 2024): for every `n ≥ 1` other than `n = 4` and `n = 6`, +`S2(n) - S1(n) = 1`, i.e. `s n = 1 - 1 / a n`. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → n ≠ 4 → n ≠ 6 → (a n : ℤ) - S1 n = 1 +\end{lstlisting} + +\subsection{How the encoding matches the OEIS} +\emph{Primes.} The file proves \decl{primeAt_eq_nth}: \texttt{primeAt i = Nat.nth Nat.Prime i}, using Bertrand's postulate (Mathlib's \decl{Nat.exists_prime_lt_and_le_two_mul}) to guarantee a prime in the search window $m+1,\dots,2m+2$. So \texttt{prime k} is Mathlib's $k$-th prime $p_k$ for $k\ge1$; \texttt{prime 0} is never used. +\emph{Sums.} \decl{s} is the recursion \eqref{eq:rec} over $\Q$ with \decl{Int.floor}; the lemma \decl{s_succ} (proved by \texttt{rfl}) states $s(n+1)=s(n)+1/(p_{n+1}\,b(n+1))$. +\emph{Fractions.} A Mathlib rational is stored in lowest terms with a positive denominator, so \texttt{S1 n} and \texttt{a n} are $S_1(n)$ and $S_2(n)$, with OEIS offset~$0$. The difference is taken in $\Z$, so truncated subtraction in $\N$ plays no role. +\emph{Range.} The comment concerns $n\ge1$ (at $n=0$ the difference is $1$ anyway). +\emph{Data.} The kernel checks, by \texttt{decide +kernel}, that the definitions reproduce all $11$ listed terms of A375522 (\decl{a_data}), A375521 (\decl{S1_data}) and A375781 (\decl{b_data}), and that the differences for $n=1,\dots,24$ are $1,1,1,2,1,2,1,1,\dots,1$, as in the comment (\decl{diff_data}). This also confirms the reading of ``$k$'' as $\mathrm{prime}(k)$. + +Corollary~\ref{cor:main} is the Lean theorem \decl{Math0.Frontier.A375522.result}, whose type is \texttt{¬ statement}. Theorem~\ref{thm:main} is not a separate exported Lean declaration. It follows from the private lemmas \decl{diff_eq}, \decl{T_spec}, \decl{mrun_spec} and \decl{mrun_42} of Section~\ref{sec:proof}, which are kernel-checked in the same file and combined in the proof of \decl{result}. + +\section{Proof}\label{sec:proof} + +Throughout, $R_n=1-s(n)$, and for integers $m$ and $M>0$, $m\bmod M\in[0,M)$ denotes the least nonnegative residue. + +\subsection{Reduction to the remainder} + +\begin{lemma}[\decl{diff_eq}]\label{lem:diff} +For every $n$, $S_2(n)-S_1(n)=\num(R_n)$. +\end{lemma} +\begin{proof} +For $x\in\Q$ we have $\den(1-x)=\den(x)$, since $1-x=(\den x-\num x)/\den x$ and $\gcd(\den x-\num x,\den x)=\gcd(\num x,\den x)=1$. Hence +$\num(1-x)=(1-x)\den(1-x)=(1-x)\den(x)=\den(x)-\num(x)$. Take $x=s(n)$. +\end{proof} + +\begin{lemma}[\decl{rat_step}]\label{lem:step} +Let $u,D,p$ be positive integers and $R=u/D$ (not necessarily in lowest terms). Write $D=upq+r$ with $q=\fl{D/(up)}$ and $0\le r0$ and $Dp(q+1)/g$. +\end{lemma} +\begin{proof} +We have $1/(Rp)=D/(up)$, whose floor is $q$, and $u/D-1/(p(q+1))=(up(q+1)-D)/(Dp(q+1))$ with $up(q+1)-D=up-r\ge1$. The last claim holds because, for positive integers $N$ and $M$, the fraction $N/M$ in lowest terms is $(N/\gcd(N,M))/(M/\gcd(N,M))$; in Lean this is \decl{Rat.num_mkRat} and \decl{Rat.den_mkRat}. +\end{proof} + +Let $\tau_p(u,D)$ denote the pair $\bigl((up-r)/g,\;Dp(q+1)/g\bigr)$ of Lemma~\ref{lem:step} (Lean: \decl{tstep}). Define $(u_0,D_0)=(1,1)$ and $(u_n,D_n)=\tau_{p_n}(u_{n-1},D_{n-1})$ (Lean: \decl{T}). + +\begin{lemma}[\decl{T_spec}]\label{lem:T} +For every $n$, $\num(R_n)=u_n$, $\den(R_n)=D_n$ and $u_n>0$. In particular $00$ by the induction hypothesis. Lemma~\ref{lem:step} gives $\num(R_n)=u_n>0$ and $\den(R_n)=D_n$. Moreover $R_n\le R_{n-1}\le 1$. The last assertion follows from Lemma~\ref{lem:diff}. +\end{proof} + +\begin{remark}\label{rem:unit} +Suppose $u_{n-1}=1$, write $D=D_{n-1}$, $p=p_n$, $r=D\bmod p$, and put $m=p-r$. Then $p(q+1)=D+m$, so $1-s(n)=m/(D(D+m))$. Since $D(D+m)\equiv D^2\pmod m$, +\[ + u_n=\frac{m}{\gcd(m,D^2)},\qquad D_n=\frac{D(D+m)}{\gcd(m,D^2)}. +\] +Hence $u_n=1$ if and only if $(p_n-r)\mid D_{n-1}^2$, and $D_n\ge D_{n-1}^2/p_n$. The Lean proof does not use this remark. +\end{remark} + +\subsection{A certified modular simulation} +For a prime $p$ and a triple $(u,d,X)\in\N^3$, where $d$ stands for a residue of the true denominator modulo~$X$, put +\[ + \nu=up-(d\bmod up),\quad \delta=d\,p\,\bigl(\fl{d/(up)}+1\bigr),\quad \gamma=\gcd(\nu,\delta),\quad X'=\fl{\fl{X/u}/\gamma}, +\] +and define $\mu_p(u,d,X)=\bigl(\nu/\gamma,\ (\delta/\gamma)\bmod X',\ X'\bigr)$ (Lean: \decl{mstep}). +The step is \emph{checked} if $\mathrm{ok}_p(u,d,X)$ holds, meaning that $up>0$, $up\mid X$ and $\nu\mid \fl{X/u}$ (Lean: \decl{mok}). + +\begin{lemma}[\decl{mstep_spec}]\label{lem:mod} +Let $p,u,D,d,X\in\N$ with $\mathrm{ok}_p(u,d,X)$ and $D\equiv d\pmod X$. Then the first component of $\tau_p(u,D)$ equals $\nu/\gamma$, and the second component of $\tau_p(u,D)$ is congruent to $\delta/\gamma$, hence to $(\delta/\gamma)\bmod X'$, modulo $X'$. +\end{lemma} +\begin{proof} +Write $X=upk$. Then $\fl{X/u}=pk$, and the hypothesis says $\nu\mid pk$. +(a) Since $up\mid X$ and $D\equiv d\pmod X$, we have $D\bmod up=d\bmod up=:r$. So the true unreduced numerator $up-(D\bmod up)$ equals $\nu=up-r$. +(b) Write $D=upq_1+r$ and $d=upq_2+r$. Then $upk=X$ divides $d-D=up(q_2-q_1)$, hence $k\mid q_2-q_1$. Write $d-D=upkc$ and $q_2-q_1=ke$ with $c,e\in\Z$. +(c) Let $\delta_t=Dp(q_1+1)$ be the true unreduced denominator. Then $\delta=dp(q_2+1)$, and +\[ + \delta-\delta_t=p\bigl[(d-D)(q_2+1)+D(q_2-q_1)\bigr]=pk\bigl[upc\,(q_2+1)+De\bigr], +\] +so $\delta_t\equiv\delta\pmod{pk}$. +(d) Since $\nu\mid pk$, also $\delta_t\equiv\delta\pmod\nu$, so $\gcd(\nu,\delta_t)=\gcd(\nu,\delta)=\gamma$. The true step therefore divides by the same $\gamma$, and its first component is $\nu/\gamma$ by Lemma~\ref{lem:step}. +(e) Since $\gamma$ divides $\nu$, it divides $pk$, and it also divides $\delta_t$ and $\delta$. Cancelling $\gamma$ in $\delta_t\equiv\delta\pmod{pk}$ gives $\delta_t/\gamma\equiv\delta/\gamma\pmod{pk/\gamma}$, and $pk/\gamma=X'$. +\end{proof} + +Fix $X_0\in\N$. The \emph{checked run} is $\rho_0=(1,1,X_0)$, and $\rho_n=\mu_{p_n}(\rho_{n-1})$ if $\rho_{n-1}$ is defined and $\mathrm{ok}_{p_n}(\rho_{n-1})$ holds; otherwise $\rho_n$ is undefined (Lean: \decl{mrun}, with values in \texttt{Option}). + +\begin{lemma}[\decl{mrun_spec}]\label{lem:run} +If $\rho_n=(u,d,X)$ is defined, then $u_n=u$ and $D_n\equiv d\pmod X$. +\end{lemma} +\begin{proof} +Induction on $n$; for $n=0$, $(u_0,D_0)=(1,1)$. If $\rho_n$ is defined, then $\rho_{n-1}=(u,d,X)$ is defined, $\mathrm{ok}_{p_n}(u,d,X)$ holds, and by induction $u_{n-1}=u$ and $D_{n-1}\equiv d\pmod X$. Lemma~\ref{lem:mod} with $D=D_{n-1}$ gives the claim for $(u_n,D_n)=\tau_{p_n}(u,D_{n-1})$. +\end{proof} + +\subsection{The computation} + +\begin{proposition}[\decl{mrun_42}]\label{prop:run} +For $X_0=(190!)^2$, the checked run $\rho_{42}$ is defined and its first component is~$5$. +\end{proposition} + +This is a finite computation carried out by the Lean kernel (Section~\ref{sec:lean}). The modulus $X_0$ has $2339$ bits. Each step divides it by $u_{n-1}\gamma$, and after $42$ steps it still has $2157$ bits; no intermediate number exceeds about $4700$ bits. +Table~\ref{tab:run} records the run: for each step, the residue $r=D_{n-1}\bmod u_{n-1}p_n$, the unreduced numerator $\nu$, and the cancelled factor $\gamma$. By Lemma~\ref{lem:mod}(a),(d) these are the true values, and $u_n=\nu/\gamma$. + +\begin{table}[tbp] +\centering\footnotesize +\setlength{\tabcolsep}{3.6pt} +\begin{tabular}{rrrrr@{\hspace{1.6em}}rrrrr@{\hspace{1.6em}}rrrrr} +\toprule +$n$ & $p_n$ & $r$ & $\nu$ & $\gamma$ & $n$ & $p_n$ & $r$ & $\nu$ & $\gamma$ & $n$ & $p_n$ & $r$ & $\nu$ & $\gamma$\\ +\midrule +1 & 2 & 1 & 1 & 1 & 15 & 47 & 39 & 8 & 8 & 29 & 109 & 9 & 100 & 100\\ +2 & 3 & 2 & 1 & 1 & 16 & 53 & 20 & 33 & 33 & 30 & 113 & 57 & 56 & 56\\ +3 & 5 & 1 & 4 & 4 & 17 & 59 & 29 & 30 & 30 & 31 & 127 & 104 & 23 & 23\\ +\textbf{4} & 7 & 1 & 6 & 3 & 18 & 61 & 15 & 46 & 46 & 32 & 131 & 0 & 131 & 131\\ +5 & 11 & 17 & 5 & 5 & 19 & 67 & 66 & 1 & 1 & 33 & 137 & 27 & 110 & 110\\ +\textbf{6} & 13 & 11 & 2 & 1 & 20 & 71 & 19 & 52 & 52 & 34 & 139 & 132 & 7 & 7\\ +7 & 17 & 33 & 1 & 1 & 21 & 73 & 17 & 56 & 56 & 35 & 149 & 57 & 92 & 92\\ +8 & 19 & 17 & 2 & 2 & 22 & 79 & 45 & 34 & 34 & 36 & 151 & 23 & 128 & 128\\ +9 & 23 & 15 & 8 & 8 & 23 & 83 & 79 & 4 & 4 & 37 & 157 & 52 & 105 & 105\\ +10 & 29 & 1 & 28 & 28 & 24 & 89 & 0 & 89 & 89 & 38 & 163 & 38 & 125 & 125\\ +11 & 31 & 28 & 3 & 3 & 25 & 97 & 4 & 93 & 93 & 39 & 167 & 36 & 131 & 131\\ +12 & 37 & 11 & 26 & 26 & 26 & 101 & 0 & 101 & 101 & 40 & 173 & 0 & 173 & 173\\ +13 & 41 & 21 & 20 & 20 & 27 & 103 & 0 & 103 & 103 & 41 & 179 & 178 & 1 & 1\\ +14 & 43 & 22 & 21 & 21 & 28 & 107 & 3 & 104 & 104 & \textbf{42} & 181 & 56 & 125 & 25\\ +\bottomrule +\end{tabular} +\caption{The checked run from $X_0=(190!)^2$: $r=D_{n-1}\bmod u_{n-1}p_n$, $\nu=u_{n-1}p_n-r$, $\gamma=\gcd(\nu,\delta)$, $u_n=\nu/\gamma$. Here $u_n=1$ except at the steps in bold ($u_4=u_6=2$, $u_{42}=5$). The Lean theorem records only $u_{42}=5$; the table was recomputed in Python.} +\label{tab:run} +\end{table} + +\emph{Step $42$ by hand.} The run gives $u_{41}=1$, and its modulus $X_{41}$ is divisible by $181\cdot 5^3$; its residue yields $D_{41}\equiv56\pmod{181}$ and $D_{41}\equiv5\pmod{125}$. So $r=56$ and $m=\nu=125$, and by Remark~\ref{rem:unit}, $u_{42}=125/\gcd(125,D_{41}^2)$. Since $5\parallel D_{41}$, $\gcd(125,D_{41}^2)=25$ and $u_{42}=5$. By contrast, at step $38$ the same $\nu=125$ cancels completely, because $5^2\mid D_{37}$. + +\begin{proof}[Proof of Theorem~\ref{thm:main} and Corollary~\ref{cor:main}] +By Lemma~\ref{lem:T}, $S_2(42)-S_1(42)=u_{42}$. By Proposition~\ref{prop:run} and Lemma~\ref{lem:run}, $u_{42}=5$. Since $42\ge1$, $42\ne4$ and $42\ne6$, while $5\ne1$, the statement of Corollary~\ref{cor:main} fails at $n=42$. +\end{proof} + +The Lean proof of \decl{result} follows this route: it specializes \decl{statement} to $n=42$, rewrites with \decl{diff_eq} and \decl{T_spec} to get $u_{42}=1$, and then uses \decl{mrun_42} and \decl{mrun_spec} to get $u_{42}=5$, a contradiction. + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +In the math0 repository (\url{https://github.com/Foundation-0/math0}), the proof is in \path{lean/Math0/Frontier/OEIS/A375522.lean}, namespace \decl{Math0.Frontier.A375522}, and the main theorem is \decl{Math0.Frontier.A375522.result}. The private auxiliary declarations are named in Section~\ref{sec:proof} next to the corresponding definitions and lemmas. Verbatim excerpts (docstrings omitted): +\begin{lstlisting} +private def X0 : ℕ := Nat.factorial 190 ^ 2 + +private theorem mrun_42 : (mrun X0 42).map (·.1) = some 5 := by + decide +kernel + +#math0_settles Math0.Frontier.A375522.result Math0.Statements.A375522.statement +\end{lstlisting} + +\subsection*{Kernel computation} +Proposition~\ref{prop:run} is proved by \texttt{decide +kernel}: the Lean kernel reduces the decision procedure to \texttt{true}, computing $190!$, the primes $p_1,\dots,p_{42}$ via the statement file's \decl{prime}, and all $42$ steps and checks with its built-in arbitrary-precision arithmetic on natural-number literals. No compiled code is trusted; the file uses no \decl{native_decide} (which would add the axiom \decl{Lean.ofReduceBool}), \texttt{sorry}, \texttt{axiom} or \texttt{set\_option}. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a universe-monomorphic definition of type \texttt{Prop}; (2) \decl{statement} depends only on the axioms \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, so it cannot hide a \texttt{sorry}; (3) the type of \decl{result} is, up to metadata and with no unfolding, either \texttt{statement} or \texttt{¬ statement}; and (4) \decl{result} also depends only on those three axioms. On this file it reports: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A375522.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A375522.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A375522.result' refutes 'Math0.Statements.A375522.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. To reproduce, run \path{scripts/verify.sh} from the repository root; it builds all math0 results with \texttt{lake build} (re-running every audit command) and checks that the pinned dependencies are unmodified. The single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A375522.lean} in \path{lean/}; this took about one minute of wall-clock time on our machine. +Two math0 referees reimplemented the run in Python, with $X_0=(190!)^2$ and with other starting moduli up to $(2000!)^4$, and obtained identical results. + +\begin{thebibliography}{99} + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Fried} +S.~Fried, \emph{Further proofs of conjectures from the OEIS}, arXiv:2607.24832, 2026. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A375522} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, entry A375522 (R.~Sigrist and N.~J.~A. Sloane), revision \#25, Apr 22 2025, \url{https://oeis.org/A375522}. + +\bibitem{OEISrel} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, entries A375521 (R.~Sigrist and N.~J.~A. Sloane), A374663, A374983 and A375781 (R.~Sigrist), A375516, A375528 and A376048 (N.~J.~A. Sloane), at \url{https://oeis.org/}. + +\bibitem{SigristProof} +R.~Sigrist, \emph{Proof of Theorem} (in A374983), Aug 26 2024, revised Sep 01 2024, \url{https://oeis.org/A374983/a374983.txt}. + +\bibitem{SiSl} +R.~Sigrist and N.~J.~A. Sloane, \emph{Dampening Down a Divergent Series}, manuscript in preparation, September 2024 (cited in OEIS A374663 and A376048). + +\bibitem{SloaneTalk} +N.~J.~A. Sloane, \emph{A Nasty Surprise in a Sequence and Other OEIS Stories}, Experimental Mathematics Seminar, Rutgers University, Oct 10 2024. Video: \url{https://www.youtube.com/watch?v=3RAYoaKMckM}; slides: \url{https://sites.math.rutgers.edu/~zeilberg/expmath/sloane85BD.pdf}. + +\end{thebibliography} + +\end{document} diff --git a/results/oeis-a386538/README.md b/results/oeis-a386538/README.md new file mode 100644 index 0000000..8e03906 --- /dev/null +++ b/results/oeis-a386538/README.md @@ -0,0 +1,57 @@ +# A386538: moving the circle's center off the grid enlarges the max lattice polygon (counterexample at n = 7) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A386538 +**Date:** 2026-10-18 + +## Result + +Conjecture (OEIS A386538, Felix Huber): for every n ≥ 0, the largest area of a polygon with vertices on Z^2 inside the closed disk of radius n is the same whether the disk's center is a grid point or any point of the plane. In the frozen encoding: for all n : ℕ, ⨆_{c ∈ ℝ²} vol(conv(Z² ∩ B(c, n))) = vol(conv(Z² ∩ B(0, n))). We prove the negation. At n = 7 with center c0 = (5/12, 5/24), the convex hull of the lattice points in B(c0, 7) has area at least 277/2 = 138.5. The convex hull for the center 0 has area at most 3457/25 = 138.28; its true value is 138 = a(7). + +## Assessment + +The conjecture is refuted by one explicit counterexample. With radius 7 and centre (5/12, 5/24), the lattice points in the disk have a convex hull of area 281/2, which beats a(7) = 138. Finding it took only a search over rational centres with exact hull areas, and checking it means comparing the areas of two explicit lattice polygons, a 12-gon and a 15-gon. No new idea was needed, and the extra work in Lean (trapezoid decompositions and measure-theory bookkeeping) does not change that. This is the conjecture as the author meant it, not a degenerate case, so it is genuinely settled, but the mathematics is routine. + +*Follows from:* Direct finite search: exact convex-hull area computation of the lattice points in disks of radius n around rational centres, compared with a(7)=138 from the entry's own data. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A386538](https://oeis.org/A386538) as [`Math0.Statements.A386538.statement`](../../lean/Math0/Statements/OEIS/A386538.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A386538.lean`](../../lean/Math0/Frontier/OEIS/A386538.lean) refutes (proves the negation of) it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: The maximum possible area of a polygon within the circle would be the same if only the vertices but not the center were fixed on grid points." (entry by _Felix Huber_, Aug 05 2025). The same conjecture appears for ellipses in A386539, which has T(n,n) = A386538(n). + +Referees: Sources checked: +- Local OEIS mirror and raw.githubusercontent.com/oeis/oeisdata, A386538: #23, Aug 19 2025, no %E lines. A386539: #19, Aug 19 2025. +- Entries that cite A386538/A386539: A398490, A396223, A391113. None addresses the conjecture. +- Cross-references read: A066643, A123690, A125228, A288247, A322106, A322107, A357577, A108126. None resolves it. A123690 and A295344 concern lattice-point counts with an off-grid center, not polygon areas. +- Web searches for the A386538 number, the entry's wording, Felix Huber plus counterexample, SeqFan, and MathOverflow/Math.SE on convex hulls of lattice points in a shifted disk. + +Related but not resolving: +- J. Zhao, "The Largest Circle Enclosing n Lattice Points", https://arxiv.org/abs/2505.06234, and its sequel https://arxiv.org/pdf/2609.16081 +- Bárány–Larman and Balog–Deshouillers on the integer convex hull of a disk (vertex counts, origin-centered only), e.g. https://www.renyi.hu/~barany/cikkek/73.pdf + +No prior proof or counterexample found. + +OEIS data (found in the fidelity pass of 29 Oct 2026 and recomputed exactly): with the centre on a grid point, the largest polygon is the convex hull of the grid points in the disk. Its area differs from the listed terms at n = 13, 17, 18, 22, 23 (516, 888, 990, 1498, 1628, against the listed 512, 880, 986, 1490, 1624). The entry's Maple and Mathematica programs use a shortcut that does not compute this area. The counterexample at n = 7, where the listed a(7) = 138 is correct, is unaffected. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a386538, + author = {{math0}}, + title = {{A386538: moving the circle's center off the grid enlarges the max lattice polygon (counterexample at n = 7)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a386538}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a386538/paper.pdf b/results/oeis-a386538/paper.pdf new file mode 100644 index 0000000..bd7228a Binary files /dev/null and b/results/oeis-a386538/paper.pdf differ diff --git a/results/oeis-a386538/paper.tex b/results/oeis-a386538/paper.tex new file mode 100644 index 0000000..fe68c93 --- /dev/null +++ b/results/oeis-a386538/paper.tex @@ -0,0 +1,401 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{booktabs} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,unfold,rw,at}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {ℝ}{{$\mathbb{R}$}}1 + {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 {∧}{{$\wedge$}}1 {≤}{{$\le$}}1 + {⨆}{{$\bigsqcup$}}1 {×}{{$\times$}}1 {¬}{{$\neg$}}1 {⊆}{{$\subseteq$}}1 + {∈}{{$\in$}}1 {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {²}{{$^2$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{⨆}{\ensuremath{\bigsqcup}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\R}{\mathbb{R}} +\newcommand{\N}{\mathbb{N}} +\DeclareMathOperator{\conv}{conv} +\newcommand{\vol}{\lambda} + +\title[A non-lattice center enlarges the largest lattice polygon in a disk]{Moving the center off the lattice enlarges the largest lattice polygon in a disk of radius $7$: a counterexample to a conjecture in OEIS A386538} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +For $n\ge0$ let $a(n)$ (OEIS A386538) be the largest area of a polygon whose vertices are points of $\Z^2$ and which lies in a closed disk of radius $n$ centered at a point of $\Z^2$; it equals the area of the convex hull of the lattice points in that disk. +In 2025 F.~Huber conjectured that this maximum does not increase when the center of the disk is allowed to be an arbitrary point of the plane. +We show that the conjecture fails at $n=7$: for the center $(5/12,5/24)$ the convex hull of the lattice points in the disk of radius $7$ has area $281/2$, whereas $a(7)=138$; the formal proof establishes the lower bound $277/2$ for the former area and the upper bound $3457/25$ for the latter, which suffices. +To our knowledge this is a new, if elementary, result: the conjecture is still stated as open in the OEIS, and we found no earlier counterexample. +The refutation is verified in Lean~4 against a frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry; this statement is not part of the formal-conjectures repository. +\end{abstract} +\maketitle + +\section{Introduction} + +For $c\in\R^2$ and $r\ge0$ let $L(c,r)=\{(x,y)\in\Z^2:(x-c_1)^2+(y-c_2)^2\le r^2\}$ be the set of lattice points in the closed disk of radius $r$ around $c$, and let $\vol$ denote Lebesgue measure on $\R^2$. +The OEIS sequence A386538, contributed by Felix Huber on August~5, 2025 \cite{A386538}, is defined as the maximum possible area of a polygon within a circle of radius $n$ whose center and vertices lie on points of the unit square grid. +Every polygon with vertices in the finite set $L(0,n)$ lies in its convex hull, and the hull is itself such a polygon (it lies in the disk because the disk is convex), so +\[ + a(n)=\vol\bigl(\conv L(0,n)\bigr),\qquad (a(n))_{n\ge0}=0,2,8,24,42,74,104,138,186,\dots +\] +The entry conjectures that the maximum would be the same if only the vertices, but not the center, were required to be grid points; that is, $\vol(\conv L(c,n))\le a(n)$ for every $c\in\R^2$. +The companion entry A386539 \cite{A386539}, by the same author, states the same conjecture for axis-parallel ellipses with integer semi-axes $n\ge k$; its diagonal $T(n,n)$ is A386538. + +\subsection*{Result} +The conjecture is false. At $n=7$ and $c_0=(5/12,5/24)$ the hull of $L(c_0,7)$ is a $15$-gon of area $281/2$, while $a(7)=138$ (Remark~\ref{rem:exact}). The formal proof (Theorem~\ref{thm:main}) shows $\vol(\conv L(0,7))\le 3457/25=138.28$ and $\vol(\conv L(c_0,7))\ge 277/2=138.5$. A finite search over centers finds further counterexamples at $n=8,12,14$ (Remark~\ref{rem:more}). + +\subsection*{Prior work and status} +It is known that moving the center off the lattice can increase the \emph{number} of lattice points covered by a disk of given radius; see A123690 and A295344 \cite{A123690,A295344}. This makes the counterexample unsurprising, but the conjecture concerns the area of the hull, a different quantity. The integer convex hull $\conv(\Z^d\cap rB^d)$ of an origin-centered ball has been studied for its numbers of vertices and faces by Balog and B\'ar\'any \cite{BB} and Balog and Deshouillers \cite{BD} in the plane and by B\'ar\'any and Larman \cite{BL} in all dimensions; these works do not compare different centers. Zhao \cite{Zhao1,Zhao2} studies the largest circles enclosing exactly $n$ interior lattice points, again a counting question. +The entry A386538 (revision~\#23, August~19, 2025) still states the conjecture without comment, and so does A386539 (revision~\#19). The math0 referees also read the OEIS entries citing these two sequences (A391113, A396223, A398490) and the cross-referenced entries, and searched the web, SeqFan, MathOverflow and Mathematics Stack Exchange; they found no counterexample or discussion of the conjecture. It is not among the OEIS statements of the formal-conjectures repository \cite{FC}. +We therefore classify the result as new. It is elementary: the counterexample is an explicit center, and the proof compares two explicit polygons. + +\section{Statement}\label{sec:statement} + +The conjecture is stated in the COMMENTS section of A386538 (F.~Huber, Aug.~05, 2025), verbatim: +\begin{quote} +\texttt{Conjecture: The maximum possible area of a polygon within the circle would be the same if only the vertices but not the center were fixed on grid points.} +\end{quote} + +\begin{conjecture}[Huber \cite{A386538}]\label{conj} +For every $n\in\N$, $\sup_{c\in\R^2}\vol(\conv L(c,n))=\vol(\conv L(0,n))$. +\end{conjecture} + +Since $c=0$ is allowed, this is equivalent to $\vol(\conv L(c,n))\le\vol(\conv L(0,n))$ for all $c$ and $n$. A lattice-point center may be taken to be the origin because translations by lattice vectors preserve $\Z^2$ and areas. + +\begin{theorem}\label{thm:main} +Let $c_0=(5/12,5/24)$. Then +$\vol(\conv L(0,7))\le\frac{3457}{25}<\frac{277}{2}\le\vol(\conv L(c_0,7))$. +Consequently $\sup_{c}\vol(\conv L(c,7))>\vol(\conv L(0,7))$, and Conjecture~\ref{conj} is false. +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A386538.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{9fb23f8d\ldots b1ef2f1}) before any proof attempt. The definitions it uses are, verbatim except that docstrings are omitted: +\begin{lstlisting} +namespace Math0.Statements.A386538 +open MeasureTheory + +def latticeDisk (c : ℝ × ℝ) (r : ℝ) : Set (ℝ × ℝ) := + {p | ∃ x y : ℤ, p = ((x : ℝ), (y : ℝ)) ∧ ((x : ℝ) - c.1) ^ 2 + ((y : ℝ) - c.2) ^ 2 ≤ r ^ 2} + +noncomputable def maxArea (c : ℝ × ℝ) (r : ℝ) : ENNReal := + volume (convexHull ℝ (latticeDisk c r)) + +def statement : Prop := + ∀ n : ℕ, (⨆ c : ℝ × ℝ, maxArea c n) = maxArea 0 n + +end Math0.Statements.A386538 +\end{lstlisting} +Here \texttt{latticeDisk c r} is $L(c,r)\subseteq\R\times\R$, with the boundary of the disk included, as $a(1)=2$ requires (the square with vertices $(\pm1,0),(0,\pm1)$). \texttt{maxArea c r} is $\vol(\conv L(c,r))\in[0,\infty]$, for the Lebesgue (product) measure on $\R\times\R$; degenerate hulls have measure $0$, as $a(0)=0$ requires. The radius $n\in\N$ is cast to $\R$, and $\bigsqcup$ is the supremum in $[0,\infty]$. So \decl{statement} is Conjecture~\ref{conj}, for all $n\ge0$ (the entry's offset). + +\subsection*{Check against the OEIS data} +The statement uses no computable function, but the statement file also defines a computable \texttt{a~:~ℕ~→~ℕ}: it lists the points of $L(0,n)$ in lexicographic order, computes their convex hull by Andrew's monotone chain algorithm, and halves the shoelace sum. Three lemmas, each proved by \texttt{decide +kernel} (the kernel itself evaluates \decl{a}), check it against the entry: \decl{a_data} checks the listed terms $a(0),\dots,a(12)=0,2,8,24,42,74,104,138,186,240,304,362,424$; \decl{a_data_more} checks the listed $a(n)$ for $n=14,15,16,19,20,21,24,25$; and \decl{a_13} checks $a(13)=516$. That \texttt{a n} equals \texttt{maxArea 0 n} is not proved in Lean; the refutation uses only \decl{maxArea}. + +\begin{remark}[The listed terms from $a(13)$ on]\label{rem:data} +The entry lists $a(13)=512$, but the convex $20$-gon with vertices $(\pm13,0)$, $(\pm12,\pm5)$, $(\pm10,\pm8)$, $(\pm8,\pm10)$, $(\pm5,\pm12)$, $(0,\pm13)$ lies in the closed disk of radius $13$ (all its vertices except $(\pm10,\pm8)$ and $(\pm8,\pm10)$, where $x^2+y^2=164$, lie on the boundary circle); it is the convex hull of $L(0,13)$ and has area $516$. The listed data come from the formula $4n+4\sum_{x=1}^n y_x-2\,\#\{y_1,\dots,y_n\}$, $y_x=\lfloor\sqrt{n^2-x^2}\rfloor$, in the entry's programs; for $13\le n\le48$ they equal the true maximum only for $n=14,15,16,19,20,21,24,25$ and are smaller otherwise (math0 computations). At $n=7$ all readings give $138$. +\end{remark} + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file. Both bounds compare the hulls with finite unions of trapezoids whose areas are computed by Fubini's theorem. The Lean names of the auxiliary (private) declarations are given in brackets. + +\subsection{Trapezoids} +For reals $a186$ at $(7/16,7/16)$), $n=12$ ($431>424$ at $(7/16,3/8)$) and $n=14$ ($1191/2>594$ at $(23/48,11/48)$), besides $n=7$; for $n\le6$ and $n=9,10,11,13$ none was found on this grid, which is not a proof that none exists. Since $T(7,7)=a(7)$, the same example refutes the conjecture of A386539 for $n=k=7$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A386538.lean} of the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main theorem is \decl{Math0.Frontier.A386538.result} of type \texttt{¬ Math0.Statements.A386538.statement}; its proof is a \texttt{calc} chain following the display in Section~\ref{sec:final}, combined with \decl{le_iSup} at $c_0$ and the case $n=7$ of the hypothesis. The auxiliary declarations are private and named in Section~\ref{sec:proof}. + +\subsection*{Kernel computation} +The only finite computation is the lemma behind Lemma~\ref{lem:check0}: +\begin{lstlisting} +private lemma check0 : ∀ i : ℕ, i < 15 → ∀ j : ℕ, j < 15 → + ((i : ℤ) - 7) ^ 2 + ((j : ℤ) - 7) ^ 2 ≤ 49 → + ∀ h ∈ H0, h.1 * ((i : ℤ) - 7) + h.2.1 * ((j : ℤ) - 7) ≤ h.2.2 := by + decide +kernel +\end{lstlisting} +With \texttt{decide +kernel} the Lean kernel itself evaluates the decision procedure for this bounded statement to \decl{true}; no compiled code is trusted, and \decl{native_decide} (which would add the axiom \decl{Lean.ofReduceBool}) is not used. All other steps, including the $24$ disk memberships and the trapezoid areas, are proved by ordinary tactics and Mathlib lemmas. The file sets no options and compiles in under a minute, much of it spent loading Mathlib. + +\subsection*{Audit} +The file ends with \texttt{\#math0\_settles result statement} (fully qualified names). This command (\path{lean/Math0/Audit.lean}) fails unless (1) \decl{statement} is a universe-monomorphic definition of type \texttt{Prop}; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (rejecting \decl{sorryAx}, \decl{Lean.ofReduceBool} and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation, with no unfolding. It reports +\begin{lstlisting} +math0 audit: 'Math0.Statements.A386538.statement' depends on axioms + [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A386538.result' depends on axioms + [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A386538.result' refutes + 'Math0.Statements.A386538.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it builds all math0 results with \texttt{lake build}, re-running every audit command, and checks that the pinned dependencies are unmodified. The single file is checked by \texttt{lake env lean Math0/Frontier/OEIS/A386538.lean} in the directory \path{lean}. + +\begin{thebibliography}{99} +\small + +\bibitem{BB} +A.~Balog and I.~B\'ar\'any, \emph{On the convex hull of the integer points in a disc}, in: Discrete and Computational Geometry (J.~E. Goodman, R.~Pollack, W.~Steiger, eds.), DIMACS Ser. Discrete Math. Theoret. Comput. Sci. \textbf{6}, Amer. Math. Soc., Providence, RI, 1991, 39--44. + +\bibitem{BD} +A.~Balog and J.-M.~Deshouillers, \emph{On some convex lattice polytopes}, in: Number Theory in Progress, Vol.~2 (K.~Gy\H{o}ry, H.~Iwaniec, J.~Urbanowicz, eds.), de Gruyter, Berlin, 1999, 591--606. + +\bibitem{BL} +I.~B\'ar\'any and D.~G.~Larman, \emph{The convex hull of the integer points in a large ball}, Math. Ann. \textbf{312} (1998), 167--181. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A123690} +The OEIS Foundation Inc., \url{https://oeis.org/A123690}, entry by H.~Pfoertner (2006). + +\bibitem{A295344} +The OEIS Foundation Inc., \url{https://oeis.org/A295344}, entry by A.~Weso\l owski (2017). + +\bibitem{A386538} +The OEIS Foundation Inc., \url{https://oeis.org/A386538}, entry by F.~Huber (2025). + +\bibitem{A386539} +The OEIS Foundation Inc., \url{https://oeis.org/A386539}, entry by F.~Huber (2025). + +\bibitem{Zhao1} +J.~Zhao, \emph{The largest circle enclosing $n$ lattice points}, arXiv:2505.06234, 2025. + +\bibitem{Zhao2} +J.~Zhao, \emph{Largest circle enclosing exactly $n$ interior lattice points.~II}, arXiv:2609.16081, 2026. + +\end{thebibliography} + +\end{document} diff --git a/results/oeis-a386655/README.md b/results/oeis-a386655/README.md new file mode 100644 index 0000000..bf3b774 --- /dev/null +++ b/results/oeis-a386655/README.md @@ -0,0 +1,49 @@ +# A386655 modulo 6 is eventually periodic with pattern [1, 0, 3, 0, 3, 2] + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Sequences and series +**Source problem:** OEIS A386655 +**Date:** 2026-10-24 + +## Result + +Let a(n) = sum_{k=0..n} C(n,k) 2^(k(k+1)) (2^k - (n-k))^(n-k-1), where the k = n term is read as 2^(n^2) and 0^0 = 1. Then for every n >= 6, a(n) mod 6 equals the entry with index (n-6) mod 6 of [1, 0, 3, 0, 3, 2]. Equivalently, a(n) mod 6 = 1, 0, 3, 0, 3, 2 for n ≡ 0, 1, 2, 3, 4, 5 (mod 6). (Paul D. Hanna's conjecture, OEIS A386655.) + +## Assessment + +The proof starts from the explicit sum formula already given in the entry and works modulo 2 and modulo 3 separately. Modulo 2 only the k=0 term survives, which is immediate. Modulo 3, writing 2 = -1 and using Fermat's little theorem makes each summand a 6-periodic function of n-k. Such a function can be written with C(m,j), j <= 2, and (-1)^m, and a standard binomial-transform identity then gives a(n) = 1-n^2 or n^2-n mod 3; CRT finishes. This is an elementary argument of about a page, the kind of residue computation a competent mathematician would carry out quickly, so it is routine. The scout had already outlined it before the proof attempt. + +*Follows from:* The entry's explicit formula a(n) = Sum_{k=0..n} C(n,k) 2^(k(k+1)) (2^k-(n-k))^(n-k-1), combined with Fermat's little theorem mod 2 and mod 3 and the standard identity Sum_m C(n,m) C(m,j) x^m = C(n,j) x^j (1+x)^(n-j). + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A386655](https://oeis.org/A386655) as [`Math0.Statements.A386655.statement`](../../lean/Math0/Statements/OEIS/A386655.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A386655.lean`](../../lean/Math0/Frontier/OEIS/A386655.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: A386655 (E.g.f.: Sum_{n>=0} (2^n*x + LambertW(x))^n / n!): "Conjecture: for n >= 6, a(n) (mod 6) equals [1, 0, 3, 0, 3, 2] repeating." (_Paul D. Hanna_, Aug 23 2025). Analogues: A386656 (q=3) [4,3,2,1,0,1], A386657 (q=4) [1,2,3,2,3,4], A386658 (q=5) [4,3,0,3,0,5]. + +Referees: I found no earlier resolution. +- OEIS A386655 (local mirror and current GitHub oeisdata, revision #14, Aug 24 2025) still states the mod-6 claim as a conjecture by Paul D. Hanna, with no %E edit or proof note. +- The cross-referenced sister entries A386656, A386657 and A386658 (q = 3, 4, 5) state analogous mod-6 conjectures, none marked proved. The related entry A386648 also has an open mod-6 conjecture. +- Web searches turned up only OEIS pages (e.g. https://oeis.org/A386648, https://oeis.org/A136524) and no paper, arXiv preprint, MathOverflow/Math StackExchange post or SeqFan message proving or refuting the A386655 conjecture. +- The classical tool used is the expansion e^(cW(x)) = Sum_k c(c-k)^(k-1) x^k/k! (the tree-function/Lambert W identity), together with Fermat's little theorem and the binomial-transform identity Sum_m C(n,m)C(m,j)x^m = C(n,j)x^j(1+x)^(n-j). + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a386655, + author = {{math0}}, + title = {{A386655 modulo 6 is eventually periodic with pattern [1, 0, 3, 0, 3, 2]}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a386655}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a386655/paper.pdf b/results/oeis-a386655/paper.pdf new file mode 100644 index 0000000..5e9bfd0 Binary files /dev/null and b/results/oeis-a386655/paper.pdf differ diff --git a/results/oeis-a386655/paper.tex b/results/oeis-a386655/paper.tex new file mode 100644 index 0000000..acf1752 --- /dev/null +++ b/results/oeis-a386655/paper.tex @@ -0,0 +1,439 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{booktabs} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,unfold,rw,at,generalize,interval_cases,push_cast}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∑}{{$\sum$}}1 + {∈}{{$\in$}}1 {≤}{{$\le$}}1 {→}{{$\to$}}1 {⊢}{{$\vdash$}}1 {←}{{$\leftarrow$}}1 + {∧}{{$\wedge$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{⊢}{\ensuremath{\vdash}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +\raggedbottom +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\F}{\mathbb{F}} + +\title[Hanna's mod-6 conjecture for OEIS A386655]{The coefficients of $\sum_{m\ge0}(2^mx+W(x))^m/m!$ modulo $6$: a proof of Hanna's conjecture for OEIS A386655} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +Let $a(n)$ be the sequence OEIS A386655, whose exponential generating function is $\sum_{m\ge0}(2^mx+W(x))^m/m!$, where $W$ is the Lambert $W$ series; equivalently $a(n)=\sum_{k=0}^{n}\binom nk2^{k(k+1)}(2^k-(n-k))^{n-k-1}$. +We prove Paul D.~Hanna's conjecture from that entry: for $n\ge6$, the residues of $a(n)$ modulo $6$ are $1,0,3,0,3,2$ repeating with period $6$, starting at $n=6$. +The proof is elementary: modulo $2$ only one summand survives, and modulo $3$ Fermat's little theorem makes each summand with $n-k\ge2$, apart from the binomial factor, depend only on $(n-k)\bmod6$ and the parity of $n$, after which a binomial-transform identity gives $a(n)\equiv1-n^2$ ($n$ even) and $a(n)\equiv n^2-n$ ($n$ odd) modulo $3$ for $n\ge3$. +To our knowledge this is a new result: the OEIS entry still lists the statement as a conjecture, and we found no recorded proof. +The proof is verified in Lean~4 with Mathlib against a frozen statement that math0 formalized from the OEIS entry and reviewed for fidelity before the proof attempt; its definition is checked by the kernel against the listed terms and against a direct evaluation of the generating function. +\end{abstract} +\maketitle + +\section{Introduction} + +Let $W(x)=\sum_{k\ge1}(-1)^{k-1}k^{k-1}x^k/k!$ be the Lambert $W$ series \cite{CGHJK}, the unique formal power series with $W(0)=0$ and $W(x)e^{W(x)}=x$. +The OEIS entry A386655 \cite{A386655}, contributed by Paul D.~Hanna on August~23, 2025, is the sequence $a(n)$, $n\ge0$, defined by +\begin{equation}\label{eq:egf} + \sum_{n\ge0}a(n)\frac{x^n}{n!}=\sum_{m\ge0}\frac{(2^mx+W(x))^m}{m!}. +\end{equation} +Since $2^mx+W(x)$ has zero constant term, the $m$-th summand is $O(x^m)$ and the right-hand side is a well-defined formal power series. +The entry lists $a(0),\dots,a(12)=1,3,23,708,82677,39043808,\dots$ and the explicit formula +\begin{equation}\label{eq:formula} + a(n)=\sum_{k=0}^{n}\binom nk\,2^{k(k+1)}\,\bigl(2^k-(n-k)\bigr)^{n-k-1}, +\end{equation} +in which the summand $k=n$, whose exponent is $-1$, equals $2^{n^2}$ (Section~\ref{sec:encoding}). +Its comments contain the following conjecture, which we prove. + +\begin{theorem}\label{thm:main} +For every $n\ge6$, +\[ + a(n)\bmod 6=\begin{cases}1,&n\equiv0\pmod 6,\\0,&n\equiv1,3\pmod6,\\3,&n\equiv2,4\pmod6,\\2,&n\equiv5\pmod6.\end{cases} +\] +\end{theorem} + +Since $6\equiv0\pmod6$, the period that starts at $n=6$ has the same phase as $n\bmod6$, so this is the conjecture ``$[1,0,3,0,3,2]$ repeating from $n=6$''. +We prove it modulo $2$ and modulo $3$ separately (Section~\ref{sec:proof}); modulo $3$, each summand of \eqref{eq:formula} is $\binom nk$ times a combination of $\binom{n-k}{j}$ and $(-1)^{n-k}\binom{n-k}{j}$, $j\le2$ (with one correction for odd $n$), and the sum is evaluated with the identity $\sum_m\binom nm\binom mj x^m=\binom njx^j(1+x)^{n-j}$. + +\subsection*{Status and prior work} +The current revision of A386655 (\#14, August~24, 2025) still states the claim as a conjecture of Hanna and contains no note of a proof. +On the same day Hanna contributed the entries A386656, A386657 and A386658 \cite{A386656,A386657,A386658}, in which $2^m$ in \eqref{eq:egf} is replaced by $3^m$, $4^m$ and $5^m$; each states an analogous conjecture for $n\ge6$, with the repeating residues $[4,3,2,1,0,1]$, $[1,2,3,2,3,4]$ and $[4,3,0,3,0,5]$ respectively. +The earlier entry A386648 \cite{A386648} (Hanna, August~12, 2025), cross-referenced from all four, has a similar conjecture modulo $6$; none of these entries records a proof. +The web searches of the math0 literature referees turned up only the OEIS pages themselves, and no paper, arXiv preprint, MathOverflow or Mathematics Stack Exchange post, or SeqFan message proving or refuting the conjecture for A386655; the conjecture is also not in the formal-conjectures repository \cite{FC} at the commit pinned by math0. +We therefore classify Theorem~\ref{thm:main} as a new result, with the caveat that the argument is elementary and may have been found without being recorded. +We do not treat the conjectures of A386648 and A386656--A386658; we expect the method to apply to the last three but have not carried this out. + +\section{Statement}\label{sec:statement} + +\subsection*{The OEIS conjecture} +The COMMENTS section of A386655 contains, verbatim, +\begin{quote} +\footnotesize\texttt{Conjecture: for n >= 6, a(n) (mod 6) equals [1, 0, 3, 0, 3, 2] repeating.} +\end{quote} +The comment carries no separate attribution; according to the revision history it was part of the entry as first submitted by Paul D.~Hanna on August~23, 2025. +The entry has offset $0$. + +\subsection*{Lean statement} +The statement is the definition \decl{Math0.Statements.A386655.statement} in the math0 statement file \path{lean/Math0/Statements/OEIS/A386655.lean}, which was reviewed for fidelity and frozen (SHA-256 \texttt{282e8203\ldots7c5019}) before any proof attempt. +The definitions it uses, and the statement itself, read verbatim (docstrings omitted; namespace \decl{Math0.Statements.A386655}): +\begin{lstlisting} +def binom (n k : ℕ) : ℕ := n.descFactorial k / k.factorial + +def term (n k : ℕ) : ℤ := + if k = n then 2 ^ (n * n) + else (binom n k : ℤ) * 2 ^ (k * (k + 1)) * ((2 : ℤ) ^ k - ((n - k : ℕ) : ℤ)) ^ (n - k - 1) + +def a (n : ℕ) : ℤ := ∑ k ∈ Finset.range (n + 1), term n k + +def statement : Prop := + ∀ n : ℕ, 6 ≤ n → a n % 6 = ([1, 0, 3, 0, 3, 2] : List ℤ).getD ((n - 6) % 6) 0 +\end{lstlisting} +Here \texttt{binom} is the binomial coefficient, written via the descending factorial so that the kernel evaluates it quickly, and the file proves \texttt{binom n k = n.choose k} (\decl{binom_eq_choose}). +The values are integers because the bases $2^k-(n-k)$ can be negative; \texttt{\%} on $\Z$ is \texttt{Int.emod}, so \texttt{a n \% 6} lies in $\{0,\dots,5\}$, and $a(n)\ge0$ in any case. +For $n\ge6$ the subtraction $n-6$ does not truncate, $(n-6)\bmod6=n\bmod6<6$, and so the default value $0$ of \texttt{getD} is never used. +Thus \decl{statement} is Theorem~\ref{thm:main}, with $a$ given by \eqref{eq:formula}. + +\subsection*{Encoding and checks against the OEIS data}\label{sec:encoding} +The definition \eqref{eq:egf} involves the series $W$, which Mathlib does not provide, so the statement file defines $a$ by the explicit formula \eqref{eq:formula}, which the entry lists (it is also the entry's first PARI program). +The formula follows from \eqref{eq:egf}; we recall the derivation. +Expanding binomially and putting $m=j+i$, +\[ + \sum_{m\ge0}\frac{(2^mx+W)^m}{m!}=\sum_{j,i\ge0}\frac{(2^{j+i}x)^j}{j!}\,\frac{W^i}{i!} + =\sum_{j\ge0}2^{j^2}\frac{x^j}{j!}\,e^{2^jW(x)}, +\] +which is formula (2) of the entry. +By the Lagrange inversion formula, applied to $W=x\,e^{-W}$, for every constant $c$ and $k\ge1$, +\[ + k!\,[x^k]\,e^{cW(x)}=(k-1)!\,[w^{k-1}]\,c\,e^{cw}e^{-kw}=c\,(c-k)^{k-1}, +\] +and the constant term of $e^{cW}$ is $1$; the entry states this expansion in its example section. +Taking $c=2^j$ and collecting the coefficient of $x^n/n!$ gives \eqref{eq:formula}, where the summand with $k=j simp only [List.getD_cons_zero, List.getD_cons_succ] at h3 ⊢ <;> omega + +end Math0.Frontier.A386655 + +#math0_settles Math0.Frontier.A386655.result Math0.Statements.A386655.statement +\end{lstlisting} +Here \decl{a_mod3} and \decl{a_mod2} are Proposition~\ref{prop:mod3} and Lemma~\ref{lem:mod2}, stated in \texttt{ZMod 3} and \texttt{ZMod 2}. +The argument is formalized for general $n$; the only computations are the finitely many identities in $\F_3$ and $\F_2$ above, closed by \texttt{decide} and evaluated by the kernel. +The file uses no \texttt{sorry}, \texttt{native\_decide}, \texttt{set\_option} or custom axioms, and compiles in under a minute of CPU time. + +\subsection*{Audit} +The command \texttt{\#math0\_settles} (\path{lean/Math0/Audit.lean}) fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} use no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} of \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation, up to metadata, with no unfolding. +Running \texttt{lake env lean Math0/Frontier/OEIS/A386655.lean} in the directory \path{lean} prints\par\nobreak\noindent +\begin{minipage}{\linewidth} +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A386655.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A386655.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A386655.result' proves 'Math0.Statements.A386655.statement' +\end{lstlisting} +\end{minipage} +so \decl{result} proves the statement using only the three standard axioms. + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. +To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib cache, builds all math0 results with \texttt{lake build} (re-running every audit), and checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified. +To check this result alone, run \texttt{lake build Math0.Statements.OEIS.A386655} (about two minutes, mostly kernel data checks) and then the command above, in the directory \path{lean}. + +{\footnotesize +\begin{thebibliography}{99} + +\bibitem{CGHJK} +R.~M. Corless, G.~H. Gonnet, D.~E.~G. Hare, D.~J. Jeffrey, and D.~E. Knuth, \emph{On the Lambert $W$ function}, Adv. Comput. Math. \textbf{5} (1996), no.~4, 329--359. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A386648} +The OEIS Foundation Inc., \url{https://oeis.org/A386648}, entry by P.~D. Hanna, Aug.~12, 2025. + +\bibitem{A386655} +The OEIS Foundation Inc., \url{https://oeis.org/A386655} (e.g.f.\ $\sum_{n\ge0}(2^nx+\mathrm{LambertW}(x))^n/n!$), entry by P.~D. Hanna, Aug.~23, 2025; revision \#14, Aug.~24, 2025. + +\bibitem{A386656} +The OEIS Foundation Inc., \url{https://oeis.org/A386656} (the case $3^n$), entry by P.~D. Hanna, Aug.~23, 2025. + +\bibitem{A386657} +The OEIS Foundation Inc., \url{https://oeis.org/A386657} (the case $4^n$), entry by P.~D. Hanna, Aug.~23, 2025. + +\bibitem{A386658} +The OEIS Foundation Inc., \url{https://oeis.org/A386658} (the case $5^n$), entry by P.~D. Hanna, Aug.~23, 2025. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a388724/README.md b/results/oeis-a388724/README.md new file mode 100644 index 0000000..1cbf7c9 --- /dev/null +++ b/results/oeis-a388724/README.md @@ -0,0 +1,36 @@ +# Column sums of strictly superdiagonal reversed partitions by maximum are A000245 + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A388724 +**Date:** 2026-10-25 + +## Result + +Let T(n,k) be the number of reversed integer partitions y = (y_1 <= ... <= y_m) of n (positive parts, weakly increasing, sum n) that are strictly superdiagonal (y_i > i for all i) and have maximum part k. Then for every k >= 1, sum_n T(n,k) = A000245(k-1), where A000245(0) = 0 and A000245(K) = 3(2K)!/((K+2)!(K-1)!) for K >= 1. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A388724](https://oeis.org/A388724) as [`Math0.Statements.A388724.statement`](../../lean/Math0/Statements/OEIS/A388724.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A388724.lean`](../../lean/Math0/Frontier/OEIS/A388724.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: Conjecture: Column sums are A000245. - _Gus Wiseman_, Sep 24 2025 + +Referees: OEIS A388724 (rev #12, Oct 06 2025; the conjecture is still listed and no %E resolution is recorded). M. Archibald, A. Blecher, S. Elizalde, A. Knopfmacher, "Subdiagonal and superdiagonal partitions", Afrika Matematika 36:77 (2025), doi:10.1007/s13370-025-01282-0. Theorem 2.3 and its proof give a bijection from superdiagonal weakly increasing partitions with largest part m to pairs (P in D_m, 0 ≤ h < final E-run length of P), plus the generating function for fixed largest part. Theorem 2.2's proof gives a bijection from partitions with k parts and largest part s to the ballot paths B_{k-1,s}. Combined with the shift y_i -> y_i - 1 and the classical identity sum over D_m of final descent length = A000245(m) (E. Deutsch, "Dyck path enumeration", Discrete Math. 204 (1999); the A000245 comment by Homberger on total returns), or with Catalan-triangle row sums (A009766, which has A000245 as a diagonal), this yields the conjecture immediately. No explicit prior statement or proof of the column-sum identity was found on OEIS, arXiv, MathOverflow, Math StackExchange or the web. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a388724, + author = {{math0}}, + title = {{Column sums of strictly superdiagonal reversed partitions by maximum are A000245}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a388724}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a388724/paper.pdf b/results/oeis-a388724/paper.pdf new file mode 100644 index 0000000..590cda3 Binary files /dev/null and b/results/oeis-a388724/paper.pdf differ diff --git a/results/oeis-a388724/paper.tex b/results/oeis-a388724/paper.tex new file mode 100644 index 0000000..249627e --- /dev/null +++ b/results/oeis-a388724/paper.tex @@ -0,0 +1,345 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {∈}{{$\in$}}1 + {∧}{{$\wedge$}}1 {∑ᶠ}{{$\sum^{\mathrm{f}}$}}2 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{ᶠ}{\ensuremath{^{\mathrm{f}}}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +\allowdisplaybreaks +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\def\UrlFont{\normalfont\ttfamily}} +\newcommand{\G}{\mathcal{G}} +\newcommand{\lb}{\char123} +\newcommand{\rb}{\char125} + +\title[Column sums of OEIS A388724]{Strictly superdiagonal reversed partitions with largest part $k$ are counted by $\mathrm{A000245}(k-1)$: a formal proof of Wiseman's conjecture for OEIS A388724} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 25, 2026} + +\begin{document} +\begin{abstract} +Let $T(n,k)$ be the number of integer partitions of $n$ whose parts, listed in weakly increasing order as $y_1\le\dots\le y_m$, satisfy $y_i>i$ for all $i$ and have largest part $k$ (OEIS A388724). +We prove that $\sum_{n}T(n,k)=\mathrm{A000245}(k-1)$ for every $k\ge1$, where $\mathrm{A000245}(0)=0$ and $\mathrm{A000245}(K)=3(2K)!/((K+2)!\,(K-1)!)$ for $K\ge1$; this is the conjecture ``Column sums are A000245'' posted by Gus Wiseman in the entry in September 2025. +The proof counts such sequences with entries in a prescribed interval by splitting off the first entry, which produces Catalan's triangle, and evaluates one entry of that triangle by the ballot formula. +The conjecture is still listed as open in the OEIS, but it follows quickly from bijections of Archibald, Blecher, Elizalde and Knopfmacher (2025) and classical Dyck-path counts, so we classify our result as the first formal proof of a known result. +It is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against all $78$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +A finite sequence $(y_1,\dots,y_m)$ is \emph{strictly superdiagonal} if $y_i>i$ for $i=1,\dots,m$. A \emph{reversed partition} of $n$ is a partition of $n$ with its parts listed in weakly increasing order. The OEIS entry A388724 \cite{A388724}, submitted by Gus Wiseman on September~24, 2025, is the triangle +\[ + T(n,k)=\#\{\text{strictly superdiagonal reversed partitions of $n$ with maximum $k$}\},\qquad 0\le k\le n . +\] +The entry contains the line ``Conjecture: Column sums are A000245.'', where A000245 \cite{A000245} is $0,1,3,9,28,90,297,\dots$, given by $3(2n)!/((n+2)!(n-1)!)$ for $n\ge1$. Since a part $y_m=k$ forces $mi$ for all $i$ and $y_m=k$, is $\mathrm{A000245}(k-1)$.} We prove this for all $k\ge1$ (Theorem~\ref{thm:main}), with a Lean proof of the full statement. + +\subsection*{Prior work and status} +\begin{itemize} +\item \emph{The OEIS entry.} In revision \#12 of A388724 (October~6, 2025), which is still the latest revision in October 2026, the conjecture is stated and no proof is recorded. The entry also contains a generating function for the triangle, a PARI program and a b-file of rows $0$ to $100$ by John Tyler Rascoe (October~4, 2025), but no proof of the conjecture. +\item \emph{A short derivation from published results.} Archibald, Blecher, Elizalde and Knopfmacher \cite{ABEK} study \emph{superdiagonal} weakly increasing partitions, $y_i\ge i$. Subtracting $1$ from every part maps the strictly superdiagonal reversed partitions with largest part $k$ bijectively onto the superdiagonal weakly increasing partitions with largest part $k-1$ (all parts stay positive since $y_i-1\ge i$). In the proof of their Theorem~2.3, a superdiagonal weakly increasing partition with largest part $m$ corresponds to a pair $(P,h)$, where $P$ is a Dyck path of semilength $m$ and $0\le h<\ell(P)$, with $\ell(P)$ the length of the final run of east steps of $P$. So the column sum is $\sum_{P}\ell(P)$ over Dyck paths of semilength $k-1$, and this total is classically $\mathrm{A000245}(k-1)$: reversing a path turns $\ell(P)$ into the height of its first peak, which has the same distribution as the number of returns to the axis (a comment of E.~Deutsch in A033184 \cite{A033184}; see also his paper \cite{Deutsch}), and by a comment of C.~Homberger in A000245 \cite{A000245} the total number of returns over all Dyck paths of semilength $n$ is $\mathrm{A000245}(n)$. Alternatively, in the proof of their Theorem~2.2, the partitions with $r$ parts and largest part $s$ correspond to ballot paths ending at $(r-1,s)$; these are counted by entries of Catalan's triangle A009766 \cite{A009766}, and summing over $r$ gives $C_{s+1}-C_s=\mathrm{A000245}(s)$, where $C_s$ is the $s$-th Catalan number. This derivation was pointed out by the math0 literature referee; we have not formalized it. The paper \cite{ABEK} appeared on April~7, 2025, before the conjecture was posted. +\item The math0 referees found no explicit statement or proof of the column-sum identity in the OEIS, arXiv, MathOverflow, Mathematics Stack Exchange or elsewhere on the web. +\end{itemize} +As the identity is in substance a corollary of known results, we classify our result as the \emph{first formal proof of a known result}. Our proof is self-contained: it uses only the definition of $T$, a recursion on the first entry, and binomial identities. + +\section{Statement}\label{sec:statement} + +The entry A388724 \cite{A388724} (offset $0$, keywords \texttt{nonn,tabl}) has the name ``Triangle read by rows where T(n,k) is the number of strictly superdiagonal reversed integer partitions of n with maximum k.'', the comment ``A sequence (y\_1, ..., y\_k) is strictly superdiagonal iff y\_i \textgreater{} i for all i = 1..k.'', and, in its FORMULA section, verbatim: +\begin{quote}\raggedright +\texttt{Conjecture: Column sums are A000245.} +\end{quote} +The line carries no signature of its own; the revision history of the entry shows that it was added by the author of the entry, Gus Wiseman, in revision \#2 (September~24, 2025). The entry A000245 \cite{A000245} (N.~J.~A. Sloane, offset $0$) has the name ``a(n) = 3*(2*n)!/((n+2)!*(n-1)!).'' and data $0,1,3,9,28,90,\dots$. + +\begin{theorem}\label{thm:main} +For $n,k\ge0$ let $T(n,k)$ be the number of finite sequences $y=(y_1,\dots,y_m)$, $m\ge0$, of positive integers with $y_1\le\dots\le y_m$, $y_1+\dots+y_m=n$, $y_i>i$ for $i=1,\dots,m$, and $\max_i y_i=k$ (so $m\ge1$). Let $\mathrm{A000245}(0)=0$ and $\mathrm{A000245}(K)=\dfrac{3\,(2K)!}{(K+2)!\,(K-1)!}$ for $K\ge1$. Then for every $k\ge1$, +\[ + \sum_{n\ge0}T(n,k)=\mathrm{A000245}(k-1), +\] +where the sum is finite since $T(n,k)=0$ for $n>k(k-1)$. +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A388724.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{62a9cf37\ldots 798e04}) before any proof attempt. Its definitions and the statement read as follows (verbatim; we omit the import, comments, blank lines, the line \texttt{open Finset}, a \texttt{DecidablePred} instance for \decl{StrictlySuperdiagonal}, all theorems, and the definitions \decl{rowOf}, \decl{a}, \decl{gen} and \decl{Tc} used for the data checks described below): +\begin{lstlisting} +namespace Math0.Statements.A388724 +def IsRevPartition (n : ℕ) (y : List ℕ) : Prop := + (∀ x ∈ y, 0 < x) ∧ y.Pairwise (· ≤ ·) ∧ y.sum = n +def StrictlySuperdiagonal (y : List ℕ) : Prop := ∀ i (h : i < y.length), i + 1 < y[i] +noncomputable def T (n k : ℕ) : ℕ := + {y : List ℕ | IsRevPartition n y ∧ StrictlySuperdiagonal y ∧ y.max? = some k}.ncard +def A000245 (n : ℕ) : ℕ := + if n = 0 then 0 else 3 * (2 * n).factorial / ((n + 2).factorial * (n - 1).factorial) +def statement : Prop := ∀ k : ℕ, 1 ≤ k → ∑ᶠ n, T n k = A000245 (k - 1) +end Math0.Statements.A388724 +\end{lstlisting} + +\emph{Encoding.} A partition of $n$ is represented by the unique list of its parts in weakly increasing order (\texttt{List.Pairwise (· ≤ ·)}), so \decl{IsRevPartition} is the set of reversed partitions of $n$; the empty list is the partition of $0$. Lists are $0$-indexed, so \texttt{i + 1 < y[i]} for $ii$ for $1\le i\le m$. ``Maximum $k$'' is \texttt{y.max?\ = some k}; the empty list has no maximum and is never counted, in agreement with the listed $T(0,0)=0$ and with the Mathematica program of the entry. \texttt{Set.ncard} is the cardinality of a finite set ($0$ for an infinite one); this set is finite by \decl{T_eq_Tc} below. In \decl{A000245} the division is exact, and the value at $0$ is the listed term $0$. The column sum is the \texttt{finsum} $\sum^{\mathrm f}_n T(n,k)$, which is the ordinary sum when the support is finite (and $0$ otherwise); the statement file proves \decl{T_eq_zero_of_lt}: $T(n,k)=0$ for $n>k(k-1)$, and \decl{colSum_eq}: $\sum^{\mathrm f}_nT(n,k)=\sum_{n=0}^{k(k-1)}T(n,k)$, so the sum is an honest finite sum. Column $0$ is identically zero, and the alignment $k\mapsto k-1$ is the only one compatible with the listed values ($\mathrm{A000245}(1)=1\neq0=\sum_nT(n,1)$); the statement claims nothing about column $0$. + +\emph{Data checks.} The statement file defines a fuel-bounded generator \decl{gen} of weakly increasing lists with given sum and lower bound, proves it correct and complete (\decl{mem_gen}) and free of repetitions (\decl{nodup_gen}), and deduces \decl{T_eq_Tc}: $T(n,k)$ equals the length \decl{Tc} of a filtered list. Through this lemma, \texttt{decide +kernel} checks that the triangle read by rows (\decl{a}) reproduces all $78$ listed terms of A388724 (rows $0$ to $11$; \decl{a_data}), that \decl{A000245} reproduces the first $28$ listed terms of A000245 (\decl{A000245_data}), and that the statement holds for $k=1,\dots,5$ (\decl{statement_check}), the last as a transcription check only. + +\section{Proof}\label{sec:proof} + +The proof follows \path{lean/Math0/Frontier/OEIS/A388724.lean}; the names of the corresponding Lean declarations are given in parentheses. All sequences below are finite sequences of nonnegative integers, the empty sequence included, and we write $x\in y$ if $x$ is an entry of $y$. + +\begin{definition} +For $k,\ell\ge0$ let $\G(k,\ell)$ be the set of weakly increasing sequences $y=(y_1,\dots,y_m)$, $m\ge0$, with $y_i>i$ for all $i$ and $\ell\le y_i\le k$ for all $i$ (\decl{Good}~$\ell$~$k$), and let $N(k,\ell)=|\G(k,\ell)|$ (\decl{N}). +\end{definition} + +Since $y_m>m$, every nonempty $y\in\G(k,\ell)$ has length $mc$ and $\operatorname{SD}_{c+1}(t)$; thus $\operatorname{SD}_c(y)$ says that $y_i>i-1+c$ for all $i$ (\decl{SD_iff}), and $\operatorname{SD}_1$ is strict superdiagonality. + +\subsection{Reduction to counting sequences} + +\begin{lemma}[\decl{colSum_card}]\label{lem:colsum} +For every $k\ge0$, $\sum_nT(n,k)=\bigl|\{y\in\G(k,0): k\in y\}\bigr|$. +\end{lemma} + +\begin{proof} +Let $F_k=\{y\in\G(k,0):k\in y\}$. For a sequence $y$ and $n\ge0$, the conditions defining $T(n,k)$ hold if and only if $y\in F_k$ and $y_1+\dots+y_m=n$: positivity of the parts follows from $y_i>i\ge1$, and $\max y=k$ means that $k\in y$ and all entries are at most $k$. So $T(n,k)$ is the size of the fibre over $n$ of the map $y\mapsto\sum_iy_i$ on the finite set $F_k$. The support of $n\mapsto T(n,k)$ is contained in the image of this map, and the sum of the sizes of all fibres is $|F_k|$. +\end{proof} + +\subsection{Counting by the first entry} +For a sequence $t=(t_1,\dots,t_r)$ write $t+1=(t_1+1,\dots,t_r+1)$, and write $j\cdot s$ for the sequence with first entry $j$ followed by $s$. + +\begin{lemma}[\decl{enum}, \decl{mem_enum}, \decl{nodup_enum}, \decl{N_succ}]\label{lem:enum} +$\G(0,\ell)=\{()\}$ for every $\ell$. For $k\ge0$, the map $(j,t)\mapsto j\cdot(t+1)$ is a bijection from +\[ + \{(j,t):\ \max(\ell,2)\le j\le k+1,\ t\in\G(k,j-1)\} +\] +onto the set of nonempty sequences in $\G(k+1,\ell)$. Consequently $N(0,\ell)=1$ and +\begin{equation}\label{eq:Nrec} + N(k+1,\ell)=1+\sum_{j=\max(\ell,2)}^{k+1}N(k,j-1). +\end{equation} +\end{lemma} + +\begin{proof} +A nonempty $y\in\G(0,\ell)$ would satisfy $11$ and $s_i>i+1$ for all $i$, i.e.\ $t_i>i$; in Lean, $\operatorname{SD}_{c+1}(t+1)\iff\operatorname{SD}_c(t)$ (\decl{SD_map}); +\item $y$ is weakly increasing if and only if $t$ is weakly increasing and $t_i\ge j-1$ for all $i$; +\item given these, $\ell\le y_i\le k+1$ for all $i$ if and only if $\ell\le j\le k+1$ and $t_i\le k$ for all $i$ (the bound $t_i+1\ge j\ge\ell$ is automatic). +\end{itemize} +Hence $j\cdot(t+1)\in\G(k+1,\ell)$ if and only if $\max(\ell,2)\le j\le k+1$ and $t\in\G(k,j-1)$. Conversely every nonempty $y\in\G(k+1,\ell)$ has the form $j\cdot s$ with $s_i\ge j\ge2$, so it is $j\cdot(t+1)$ with $t=s-1$ (\decl{map_sub_add}). The map is injective, since $j$ is the first entry and $t\mapsto t+1$ is injective. + +In Lean, \decl{enum}~$k$~$\ell$ is \texttt{[[]]} for $k=0$, and for $k+1$ it is the empty list followed, for $j=\max(\ell,2),\dots,k+1$, by the lists $j\cdot(t+1)$, $t\in{}$\decl{enum}~$k$~$(j-1)$. By the argument above its members are the elements of $\G(k,\ell)$ (\decl{mem_enum}) and it has no repetitions (\decl{nodup_enum}); $N(k,\ell)$ is its length, and \eqref{eq:Nrec} is read off from its shape (\decl{N_succ}). +\end{proof} + +\begin{corollary}\label{cor:N} +For all $k,\ell\ge0$: +\begin{enumerate} +\item[(a)] $N(k+1,\ell)=N(k+1,2)$ if $\ell\le2$, and $N(k,1)=N(k,0)$ \quad(\decl{N_low}, \decl{N_one}); +\item[(b)] $N(k+1,\ell)=1$ if $\ell\ge k+2$ \quad(\decl{N_top}); +\item[(c)] $N(k+1,\ell)=N(k+1,\ell+1)+N(k,\ell-1)$ if $2\le\ell\le k+1$ \quad(\decl{N_rec}). +\end{enumerate} +\end{corollary} + +\begin{proof} +(a) If $\ell\le2$ then $\max(\ell,2)=2$ in \eqref{eq:Nrec}; for $k=0$ in the second claim, $N(0,1)=N(0,0)=1$. (b) The sum in \eqref{eq:Nrec} is empty. (c) For $\ell\ge2$ the sum in \eqref{eq:Nrec} runs over $\ell\le j\le k+1$; splitting off the term $j=\ell$ leaves the sum for $\ell+1$. +\end{proof} + +\subsection{Catalan's triangle} +For $k,s\ge0$ put $A(k,s)=N(k,k+1-s)$ (\decl{A}; truncated subtraction, but we only use $s\le k$). Thus $A(k,s)$ counts the sequences in $\G(k,k+1-s)$, whose entries lie in $[k+1-s,k]$. + +\begin{lemma}\label{lem:A} +For all $k,s\ge0$: +\begin{enumerate} +\item[(a)] $A(k,0)=1$ \quad(\decl{A_zero}); +\item[(b)] $A(k+1,s+1)=A(k+1,s)+A(k,s+1)$ if $s+1\le k$ \quad(\decl{A_rec}); +\item[(c)] $A(k+1,k+1)=A(k+1,k)$ \quad(\decl{A_diag}). +\end{enumerate} +\end{lemma} + +\begin{proof} +(a) $A(0,0)=N(0,1)=1$, and $A(k+1,0)=N(k+1,k+2)=1$ by Corollary~\ref{cor:N}(b). (b) Apply Corollary~\ref{cor:N}(c) with $\ell=k+1-s$, which satisfies $2\le\ell\le k+1$: it reads $N(k+1,k+1-s)=N(k+1,k+2-s)+N(k,k-s)$, which is (b). (c) $A(k+1,k+1)=N(k+1,1)=N(k+1,2)=A(k+1,k)$ by Corollary~\ref{cor:N}(a). +\end{proof} + +\begin{proposition}[\decl{A_closed}]\label{prop:ballot} +For all $n,m\ge0$ with $m+1\le n$, +\[ + A(n,m+1)+\binom{n+m+1}{m}=\binom{n+m+1}{m+1}. +\] +\end{proposition} + +So $A(n,s)=\binom{n+s}{s}-\binom{n+s}{s-1}$ for $0\le s\le n$ (with $s=0$ from Lemma~\ref{lem:A}(a)), which are the entries of Catalan's triangle A009766 \cite{A009766}. + +\begin{proof} +Induction on $n$; for $n=0$ there is nothing to prove. Assume the claim for $n$ (for all admissible $m$) and prove it for $n+1$ by induction on $m$, where $m+1\le n+1$. + +\emph{Case $m=0$}: we need $A(n+1,1)=n+1$. If $n=0$, $A(1,1)=A(1,0)=1$ by Lemma~\ref{lem:A}(c),(a). If $n\ge1$, Lemma~\ref{lem:A}(b) with $s=0$ gives $A(n+1,1)=A(n+1,0)+A(n,1)=1+n$, using the outer hypothesis $A(n,1)+1=n+1$. + +\emph{Case $m+1$ with $m+2\le n$} (generic step). By Lemma~\ref{lem:A}(b), $A(n+1,m+2)=A(n+1,m+1)+A(n,m+2)$. The inner hypothesis gives $A(n+1,m+1)=\binom{n+m+2}{m+1}-\binom{n+m+2}{m}$ and the outer one gives $A(n,m+2)=\binom{n+m+2}{m+2}-\binom{n+m+2}{m+1}$. Adding $\binom{n+m+3}{m+1}=\binom{n+m+2}{m}+\binom{n+m+2}{m+1}$ (Pascal's rule) gives $A(n+1,m+2)+\binom{n+m+3}{m+1}=\binom{n+m+2}{m+1}+\binom{n+m+2}{m+2}=\binom{n+m+3}{m+2}$. + +\emph{Case $m+1$ with $n=m+1$} (diagonal step). By Lemma~\ref{lem:A}(c), $A(m+2,m+2)=A(m+2,m+1)$, and the inner hypothesis gives $A(m+2,m+1)+\binom{2m+3}{m}=\binom{2m+3}{m+1}$. By Pascal's rule and the symmetry $\binom{2m+3}{m+2}=\binom{2m+3}{m+1}$, +\[ + \binom{2m+4}{m+1}=\binom{2m+3}{m}+\binom{2m+3}{m+1},\qquad \binom{2m+4}{m+2}=2\binom{2m+3}{m+1}, +\] +so $A(m+2,m+2)+\binom{2m+4}{m+1}=2\binom{2m+3}{m+1}=\binom{2m+4}{m+2}$. (Lean: \texttt{Nat.choose\_succ\_succ'}, \texttt{Nat.choose\_symm\_half}, \texttt{omega}.) +\end{proof} + +\begin{lemma}[\decl{A000245_eq}]\label{lem:fact} +Let $j,x\ge0$ with $x+\binom{2j+4}{j}=\binom{2j+4}{j+1}$. Then $\mathrm{A000245}(j+2)=x$. +\end{lemma} + +\begin{proof} +From $\binom{2j+4}{j+1}(j+1)!\,(j+3)!=(2j+4)!$ and $\binom{2j+4}{j}\,j!\,(j+4)!=(2j+4)!$ we get, computing in $\mathbb Z$, +\[ + x\,(j+4)!\,(j+1)!=(j+4)\,(2j+4)!-(j+1)\,(2j+4)!=3\,(2j+4)!. +\] +Hence the exact quotient $3(2j+4)!/((j+4)!\,(j+1)!)$, which is $\mathrm{A000245}(j+2)$ by definition, equals $x$. +\end{proof} + +\subsection{Proof of Theorem~\ref{thm:main}} +Write $k=K+1$ and $S=\bigl|\{y\in\G(K+1,0):K+1\in y\}\bigr|$; by Lemma~\ref{lem:colsum} we must show $S=\mathrm{A000245}(K)$. The sequences in $\G(K+1,0)$ that do not contain $K+1$ are exactly the elements of $\G(K,0)$, so (\decl{card_split}) +\[ + S+N(K,0)=N(K+1,0). +\] +If $K=0$, then $N(1,0)=N(0,0)=1$ (evaluated by \texttt{rfl}), so $S=0=\mathrm{A000245}(0)$. Let $K\ge1$. By Corollary~\ref{cor:N}(a), (c) with $\ell=2$, and (a) again, +\[ + N(K+1,0)=N(K+1,2)=N(K+1,3)+N(K,1)=N(K+1,3)+N(K,0), +\] +so $S=N(K+1,3)=A(K+1,K-1)$. If $K=1$ this is $A(2,0)=1=\mathrm{A000245}(1)$ (Lemma~\ref{lem:A}(a); the value $\mathrm{A000245}(1)=1$ is evaluated by \texttt{decide}). If $K=j+2$, Proposition~\ref{prop:ballot} with $n=j+3$, $m=j$ gives $A(j+3,j+1)+\binom{2j+4}{j}=\binom{2j+4}{j+1}$, and Lemma~\ref{lem:fact} with $x=A(j+3,j+1)$ gives $S=\mathrm{A000245}(j+2)$. \qed + +\begin{remark} +For $k\ge2$ the proof shows that $\sum_nT(n,k)=N(k,3)$, the number of sequences in $\G(k,3)$, the empty one included. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A388724.lean} in the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A388724.lean} and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A388724.result} \texttt{: statement}, followed by the command +\begin{lstlisting} +#math0_settles Math0.Frontier.A388724.result Math0.Statements.A388724.statement +\end{lstlisting} +All auxiliary declarations in the proof file are private; their names are given with the corresponding results in Section~\ref{sec:proof}. Neither file uses \texttt{sorry}, \texttt{native\_decide}, custom axioms, \texttt{implemented\_by}, \texttt{extern} or \texttt{set\_option}. The proof evaluates only a few small closed terms by computation, such as $N(1,0)=N(0,0)=1$ (\texttt{rfl}) and $\mathrm{A000245}(1)=1$ (\texttt{decide}); it does not use the data checks of the statement file. + +\subsection*{Audit} +The command \texttt{\#math0\_settles} (in \path{lean/Math0/Audit.lean}, for statements that math0 formalizes itself) fails unless \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; \decl{statement} and \decl{result} depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \texttt{sorry}, \texttt{native\_decide} and custom axioms); and the type of \decl{result} is syntactically \decl{statement} or $\neg$\,\decl{statement}, up to metadata, with no unfolding. Running \texttt{lake env lean Math0/Frontier/OEIS/A388724.lean} in \path{lean/} reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A388724.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A388724.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A388724.result' proves 'Math0.Statements.A388724.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib cache, builds all math0 results with \texttt{lake build} (re-running every audit command) and checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified. + +{\footnotesize +\begin{thebibliography}{99} + +\bibitem{ABEK} +M.~Archibald, A.~Blecher, S.~Elizalde, and A.~Knopfmacher, \emph{Subdiagonal and superdiagonal partitions}, Afrika Matematika \textbf{36} (2025), no.~2, Article~77, \url{https://doi.org/10.1007/s13370-025-01282-0}. + +\bibitem{Deutsch} +E.~Deutsch, \emph{Dyck path enumeration}, Discrete Math. \textbf{204} (1999), 167--202, \url{https://doi.org/10.1016/S0012-365X(98)00371-9}. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A000245} +The OEIS Foundation Inc., \emph{$a(n)=3(2n)!/((n+2)!\,(n-1)!)$}, entry A000245 (N.~J.~A. Sloane) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A000245}. + +\bibitem{A009766} +The OEIS Foundation Inc., \emph{Catalan's triangle $T(n,k)$ (read by rows)}, entry A009766 (W.~Meeussen) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A009766}. + +\bibitem{A033184} +The OEIS Foundation Inc., \emph{Catalan triangle A009766 transposed}, entry A033184 (C.~G. Bower) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A033184}. + +\bibitem{A388724} +The OEIS Foundation Inc., \emph{Triangle read by rows where $T(n,k)$ is the number of strictly superdiagonal reversed integer partitions of $n$ with maximum $k$}, entry A388724 (G.~Wiseman, 2025) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A388724}; revision \#12, October~6, 2025. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a392943/README.md b/results/oeis-a392943/README.md new file mode 100644 index 0000000..f5e0a04 --- /dev/null +++ b/results/oeis-a392943/README.md @@ -0,0 +1,47 @@ +# No primitive Heronian triangle has integer circumradius + +**Classification:** First formal proof of a known result +**Area:** Discrete geometry +**Source problem:** OEIS A392943 +**Date:** 2026-10-19 + +## Result + +Let x, y, z be positive integers satisfying the strict triangle inequalities, with gcd(x, y, z) = 1, and let K be a natural number with 16K^2 = (x+y+z)(-x+y+z)(x-y+z)(x+y-z), i.e. K is the area. Then there is no natural number R with 4KR = xyz. In other words, no primitive Heronian triangle has integer circumradius. This is Felix Huber's conjecture in OEIS A392943. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A392943](https://oeis.org/A392943) as [`Math0.Statements.A392943.statement`](../../lean/Math0/Statements/OEIS/A392943.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A392943.lean`](../../lean/Math0/Frontier/OEIS/A392943.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: There is no primitive Heronian triangle with integer circumradius." (entry by _Felix Huber_, Feb 04 2026) + +Referees: Ronald van Luijk, "The diameter of the circumcircle of a Heron triangle", Elemente der Mathematik 63 (2008), 118–121. The relevant parts are: +- Theorem 2, (4)⇒(5): if gcd(a,b,c,d) = 1, every prime divisor of the circumdiameter d is ≡ 1 mod 4. +- Corollary 5: for a prime p ≢ 1 mod 4, p^{v_p(d)} divides gcd(a,b,c). +- Proof of Theorem 1: it states explicitly that a Heron triangle with integer circumradius has all sides even. + +Earlier related work: +- A.-V. Kramer & F. Luca, "Some remarks on Heron triangles", Acta Acad. Paedagog. Agriensis Sect. Mat. (N.S.) 27 (2000) 25–38. Shows no power of 2 is the circumradius of a Heron triangle. +- M. Aassila, "Some results on Heron triangles", Elem. Math. 56 (2001) 143–146. + +Also related, with full text not checked: E. Read, "Integer triangles with integer circumradii", Math. Gazette 107 (2023) 241–248. + +OEIS A392943 (Huber, Feb 2026) cites none of these, and no proof has been added to the entry. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a392943, + author = {{math0}}, + title = {{No primitive Heronian triangle has integer circumradius}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a392943}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a392943/paper.pdf b/results/oeis-a392943/paper.pdf new file mode 100644 index 0000000..5a559ba Binary files /dev/null and b/results/oeis-a392943/paper.pdf differ diff --git a/results/oeis-a392943/paper.tex b/results/oeis-a392943/paper.tex new file mode 100644 index 0000000..d652e9f --- /dev/null +++ b/results/oeis-a392943/paper.tex @@ -0,0 +1,325 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,rw,ring,linear_combination,by_contra}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {→}{{$\to$}}1 {←}{{$\leftarrow$}}1 {≠}{{$\ne$}}1 {∧}{{$\wedge$}}1 {∣}{{$\mid$}}1 + {≤}{{$\le$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1 {₀}{{$_0$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Q}{\mathbb{Q}} + +\title[Heronian triangles with integer circumradius]{No primitive Heronian triangle has an integer circumradius (OEIS A392943)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 19, 2026} + +\begin{document} +\begin{abstract} +We prove that no primitive Heronian triangle (integer sides with greatest common divisor $1$ and integer area) has an integer circumradius, which is the conjecture recorded by Felix Huber in OEIS A392943 in February 2026; more precisely, every triangle with integer sides and integer circumradius has three even sides. +The result is not new: it follows from R.~van Luijk's 2008 characterization of the circumdiameters of Heron triangles, whose proof states explicitly that a Heron triangle with integer circumradius has even sides. Our proof is a short self-contained argument modulo $4$, and we classify this note as the first formal proof of a known result. +The conjecture, in the form with integer area as in the OEIS entry, is verified in Lean~4 against a statement that math0 formalized from the entry, reviewed for fidelity and frozen before the proof attempt; the definitions of the entry's sequence built on the same notions are checked by the Lean kernel against the first $30$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +A \emph{Heronian} (or Heron) triangle is a triangle whose side lengths $a,b,c$ and whose area $K$ are integers; it is \emph{primitive} if $\gcd(a,b,c)=1$. Heron's formula +\begin{equation}\label{eq:heron} + 16K^2=P(a,b,c)\coloneqq(a+b+c)(-a+b+c)(a-b+c)(a+b-c) +\end{equation} +expresses the area through the sides, and the circumradius is +\begin{equation}\label{eq:circ} + R=\frac{abc}{4K}. +\end{equation} +For example, the triangle $(3,4,5)$ is Heronian with $K=6$ and $R=5/2$, while its double $(6,8,10)$ has $K=24$ and $R=5$. + +The OEIS sequence A392942 \cite{A392942} lists the semiperimeters of the triangles with integer sides, integer area and integer circumradius ($12,24,30,36,40,\dots$), and A392943 \cite{A392943} counts, for the $n$-th such semiperimeter, the triangles (up to congruence) with that semiperimeter. Both entries were contributed by Felix Huber on February~4, 2026. The entry A392943 contains the comment ``Conjecture: There is no primitive Heronian triangle with integer circumradius.'' All triangles given as examples in the two entries, namely $(30,30,48)$, $(24,70,74)$, $(28,60,80)$, $(42,56,70)$ and $(14,30,40)$, have three even sides. The entries contain no proof and no reference for the conjecture. + +\subsection*{Prior work} +The conjecture is a consequence of published results. A.-V.~Kramer and F.~Luca \cite[Proposition~6]{KL} proved that the set of positive integers $k$ that are the circumradius of a Heron triangle has asymptotic density $1$, and that no Heron triangle has a circumradius that is a power of $2$ or a power of a prime $p\equiv 11\pmod{12}$. The case of primes $p\equiv11\pmod{12}$ was also stated as a conjecture by M.~Aassila \cite{Aa}, as recorded in \cite{vL}; Aassila's paper appeared in 2001, after \cite{KL}, and was later marked as retracted by Elemente der Mathematik, whose editorial board noted its strong similarity to \cite{KL}. + +R.~van Luijk \cite{vL} proved that a positive integer $k$ is the circumradius of a Heron triangle if and only if it is the circumdiameter of a Heron triangle, if and only if $k$ has a prime divisor $p\equiv1\pmod 4$ \cite[Theorem~1]{vL}. The key step is the implication (4)$\Rightarrow$(5) of his Theorem~2: if a triangle has integer sides $a,b,c$ and integer circumdiameter $d$ with $\gcd(a,b,c,d)=1$, then $d>1$ and every prime divisor of $d$ is $\equiv1\pmod4$. Its Corollary~5 states that if an integer $d$ is the circumdiameter of a triangle with integer sides $a,b,c$ and $p\not\equiv1\pmod 4$ is prime, then $p^{v_p(d)}$ divides $\gcd(a,b,c)$. The proof of the implication (1)$\Rightarrow$(2) of Theorem~1 in \cite{vL} begins: ``let $a$, $b$, and $c$ be the sides of a Heron triangle with circumradius $k$. Then the circumdiameter $2k$ is even and by Corollary~5, so are $a$, $b$, and $c$.'' This is exactly the statement that no primitive Heronian triangle has an integer circumradius. Van Luijk's argument rests on the identity $(4K)^2+(a^2+b^2-c^2)^2=4a^2b^2$ and on the fact that $p^{2m}\mid s^2+t^2$ forces $p^m\mid s$ and $p^m\mid t$ for primes $p\not\equiv1\pmod4$ \cite[Lemma~4]{vL}. He also shows that a triangle with integer sides and rational area is Heronian \cite[Lemma~3]{vL}; by \eqref{eq:circ}, a triangle with integer sides and integer circumradius therefore has integer area automatically. E.~Read \cite{Read} has more recently studied integer triangles with integer circumradii; the publicly available extract of that article notes that integer area is necessary for an integer circumradius, and we have not consulted its full text. + +Neither OEIS entry cites these works, the conjecture is not among the OEIS statements of the formal-conjectures repository \cite{FC} (checked at commit \texttt{c77fdd4}), and we are not aware of an earlier formal proof. + +\subsection*{This note} +We give a self-contained proof that integer circumradius forces all sides to be even (Lemma~\ref{lem:key} and Remark~\ref{rem:general}). It is a weak form of the case $p=2$ of van Luijk's Corollary~5 (we obtain $2\mid\gcd(a,b,c)$ rather than $2^{v_2(2R)}\mid\gcd(a,b,c)$), proved directly from Heron's formula by an argument modulo $4$. We classify the result as \emph{a known result, formalized here for the first time}: the mathematics has been available since 2008, and the contribution of this note is a written resolution of the OEIS conjecture that is linked to the literature, together with a kernel-checked proof of a frozen formal statement. + +\section{Statement}\label{sec:statement} + +The name of A392943 \cite{A392943} is, verbatim, ``a(n) is the number of integer-sided triangles whose area and circumradius are integers, and whose semiperimeter equals A392942(n).'' The entry is authored by Felix Huber and dated February~4, 2026, and its COMMENTS section contains, verbatim, the following comment: +\begin{quote}\raggedright +\texttt{Conjecture: There is no primitive Heronian triangle with integer circumradius.} +\end{quote} + +\begin{conjecture}[Huber \cite{A392943}]\label{conj} +If a triangle has integer sides $a,b,c$ with $\gcd(a,b,c)=1$ and integer area, then its circumradius is not an integer. +\end{conjecture} + +\begin{theorem}\label{thm:main} +Let $x,y,z$ be positive integers with $x0$, so $K>0$. Since $K>0$, the circumradius $xyz/(4K)$ is an integer if and only if $4KR=xyz$ for some integer $R$, and such an $R$ is positive, so quantifying over $R\in\N$ loses nothing. Primitivity is $\gcd(x,\gcd(y,z))=1$. No hypotheses are added, and the hypotheses are satisfiable (by $(3,4,5)$ with $K=6$), so the statement is not vacuous. + +The statement file also defines the two sequences from the same notions and checks them against the OEIS data. The predicate \texttt{IsGood x y z} is \texttt{IsTriangle x y z} together with the existence of $K,R\in\N$ with \texttt{HasArea x y z K} and $4KR=xyz$, matching the name of the entry and the Maple test of the entry (\texttt{issqr(f)} and $xyz\equiv0\pmod{4\sqrt f}$, with $f=P/16$). The function \texttt{count s} counts the triangles $x\le y\le z$ with $x+y+z=2s$ satisfying \decl{IsGood}, using the loop bounds of the Maple program, and \decl{count_eq_card} proves that it equals the cardinality of the corresponding finite set of triples. The lemma \decl{even_perimeter} shows that a triangle with integer sides and integer area has even perimeter, so no triangle is lost by taking the semiperimeter $s$ to be a natural number. The term \texttt{A392942 n} is computed by a search over $s\le 12n$ (every positive multiple of $12$ is a semiperimeter, by the triangles $(6m,8m,10m)$), and \decl{A392942_eq_nth} proves that for $n\ge1$ it is the $n$-th smallest semiperimeter, \texttt{Nat.nth IsSemiperimeter (n - 1)}, matching offset $1$. Finally +\begin{lstlisting} +def a (n : ℕ) : ℕ := count (A392942 n) + +theorem a_data : (List.range 30).map (fun i => a (i + 1)) = + [1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 3, 2, 1, 1, 2, 1, 1, 4, 2, 2, 3, 2, 3, 1, 2, + 2] := by + decide +kernel +\end{lstlisting} +so the Lean kernel itself evaluates $a(1),\dots,a(30)$ and compares them with the first $30$ of the $88$ listed terms of A392943 (these involve the semiperimeters up to $A392942(30)=156$). For speed, the kernel evaluates a Boolean test \decl{goodB}, which combines a quadratic-residue sieve with \decl{Nat.sqrt}; the file proves \decl{goodB_iff}, i.e.\ that \texttt{goodB x y z = true} if and only if \texttt{IsGood x y z}. An independent Python computation by the math0 reviewers, which is not part of the formal verification, reproduced all $88$ listed terms of A392943 and all $56$ listed terms of A392942 from the same definition. The sequence definitions do not enter \decl{statement}; they tie the notions \decl{IsTriangle}, \decl{heron16} and \decl{HasArea} used by \decl{statement} to the OEIS data. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A392943.lean}. It consists of one lemma, \decl{two_dvd_of_heron} (Lemma~\ref{lem:key}), and the main theorem \decl{result}. We write $P(a,b,c)$ for the polynomial in \eqref{eq:heron}, now with $a,b,c$ in $\Z$. + +\begin{lemma}\label{lem:identity} +For all integers $a,b,c$, with $D=b^2+c^2-a^2$, +\[ + P(a,b,c)=4b^2c^2-D^2 . +\] +Moreover $P$ is symmetric: $P(a,b,c)=P(b,a,c)=P(c,a,b)$. +\end{lemma} + +\begin{proof} +Grouping the factors, $P(a,b,c)=\bigl((b+c)^2-a^2\bigr)\bigl(a^2-(b-c)^2\bigr)=\bigl(2bc+D\bigr)\bigl(2bc-D\bigr)$. The second claim holds because the four factors of $P(b,a,c)$ and of $P(c,a,b)$ are a permutation of the four factors of $P(a,b,c)$. +\end{proof} + +\begin{lemma}\label{lem:sq} +Let $u,v\in\Z$. If $u^2\mid v^2$, then $u\mid v$. +\end{lemma} + +\begin{proof} +If $u=0$, then $v^2=0$ and $v=0$. Otherwise let $g=\gcd(u,v)>0$ and write $u=gu'$, $v=gv'$ with $\gcd(u',v')=1$. Then $u'^2\mid v'^2$, and $u'^2$ is coprime to $v'^2$, so $u'^2=1$ and $u=\pm g$ divides $v$. +\end{proof} + +\begin{lemma}\label{lem:key} +Let $a,b,c,R\in\Z$ with $b\ne0$, $c\ne0$ and +\begin{equation}\label{eq:hyp} + P(a,b,c)\,R^2=(abc)^2 . +\end{equation} +Then $a$ is even. +\end{lemma} + +\begin{proof} +Let $D=b^2+c^2-a^2$. By Lemma~\ref{lem:identity} and \eqref{eq:hyp}, +\[ + (bc)^2(4R^2-a^2)-(RD)^2=R^2\bigl(4b^2c^2-D^2\bigr)-(abc)^2=R^2P(a,b,c)-(abc)^2=0, +\] +so +\begin{equation}\label{eq:h1} + (bc)^2(4R^2-a^2)=(RD)^2 . +\end{equation} +Hence $(bc)^2\mid(RD)^2$, and by Lemma~\ref{lem:sq} there is $m\in\Z$ with $RD=bc\,m$. Substituting into \eqref{eq:h1} gives $(bc)^2(4R^2-a^2)=(bc)^2m^2$. Since $bc\ne0$, we may cancel $(bc)^2$ and obtain +\begin{equation}\label{eq:h3} + a^2+m^2=4R^2 . +\end{equation} +Suppose that $a$ is odd. Then $a^2\equiv1\pmod4$. If $m=2j$ is even, then $m^2=4j^2$ and $a^2+m^2\equiv1\pmod4$; if $m$ is odd, then $m^2\equiv1\pmod 4$ and $a^2+m^2\equiv2\pmod4$. Both contradict \eqref{eq:h3}, whose right-hand side is divisible by $4$. Hence $a$ is even. +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +Let $x,y,z,K,R\in\N$ satisfy the hypotheses, and suppose $4KR=xyz$. Of the hypothesis \decl{IsTriangle} only $x,y,z>0$ is used. In $\Z$ we have +\[ + P(x,y,z)\,R^2=16K^2R^2=(4KR)^2=(xyz)^2 . +\] +The integers $x,y,z$ are nonzero, so Lemma~\ref{lem:key} applies to $(a,b,c)=(x,y,z)$ and gives $2\mid x$. By the symmetry in Lemma~\ref{lem:identity}, $P(y,x,z)R^2=(yxz)^2$ and $P(z,x,y)R^2=(zxy)^2$, so Lemma~\ref{lem:key} applied to $(y,x,z)$ and to $(z,x,y)$ gives $2\mid y$ and $2\mid z$. Therefore $2$ divides $\gcd(x,\gcd(y,z))=1$, a contradiction. +\end{proof} + +\begin{remark}\label{rem:general} +The proof does not use the triangle inequalities, and it uses the integrality of the area only through the identity $P(x,y,z)R^2=(xyz)^2$. For any triangle with integer sides $a,b,c$ and integer circumradius $R$, the (real) area $K>0$ satisfies \eqref{eq:heron} and \eqref{eq:circ}, so $P(a,b,c)R^2=16K^2R^2=(abc)^2$, and Lemma~\ref{lem:key}, applied three times as above, shows that $a$, $b$ and $c$ are all even. Lemma~\ref{lem:key} is formalized in this generality (for arbitrary integers $a,b,c,R$ with $b,c\neq 0$); only the final theorem is stated with $K\in\N$, as in the OEIS conjecture. Geometrically, if $A$ is the angle opposite the side $a$, then $a=2R\sin A$ by the law of sines and $D=2bc\cos A$ by the law of cosines, so $m=RD/(bc)=2R\cos A$ and \eqref{eq:h3} is $\sin^2A+\cos^2A=1$ multiplied by $4R^2$. Van Luijk's Corollary~5 \cite{vL} gives the stronger conclusion that $2^{v_2(2R)}$ divides $\gcd(a,b,c)$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A392943.lean} in the math0 repository, \url{https://github.com/Foundation-0/math0}. It imports the frozen statement file \path{lean/Math0/Statements/OEIS/A392943.lean} (Section~\ref{sec:statement}) and the audit commands in \path{lean/Math0/Audit.lean}. The main declaration is \decl{Math0.Frontier.A392943.result}, whose type is exactly \decl{Math0.Statements.A392943.statement}. The only auxiliary declaration is Lemma~\ref{lem:key}; its statement and proof are, verbatim: +\begin{lstlisting} +private theorem two_dvd_of_heron (a b c R : ℤ) (hb : b ≠ 0) (hc : c ≠ 0) + (h : (a + b + c) * (-a + b + c) * (a - b + c) * (a + b - c) * R ^ 2 = (a * b * c) ^ 2) : + 2 ∣ a := by + have h1 : (b * c) ^ 2 * (4 * R ^ 2 - a ^ 2) = (R * (b ^ 2 + c ^ 2 - a ^ 2)) ^ 2 := by + linear_combination h + have hdvd : (b * c) ^ 2 ∣ (R * (b ^ 2 + c ^ 2 - a ^ 2)) ^ 2 := ⟨_, h1.symm⟩ + obtain ⟨m, hm⟩ := (Int.pow_dvd_pow_iff (by norm_num)).1 hdvd + have hbc : (b * c) ^ 2 ≠ 0 := pow_ne_zero _ (mul_ne_zero hb hc) + have h2 : (b * c) ^ 2 * (4 * R ^ 2 - a ^ 2) = (b * c) ^ 2 * m ^ 2 := by + rw [h1, hm]; ring + have h3 : a ^ 2 + m ^ 2 = 4 * R ^ 2 := by + have := mul_left_cancel₀ hbc h2 + linear_combination -this + by_contra hodd + have ha : Odd a := Int.not_even_iff_odd.1 (fun he => hodd (even_iff_two_dvd.1 he)) + have ha2 : a ^ 2 % 4 = 1 := Int.sq_mod_four_eq_one_of_odd ha + have h4 : (a ^ 2 + m ^ 2) % 4 = 0 := by rw [h3]; simp + rcases Int.even_or_odd m with ⟨j, rfl⟩ | hm' + · have hm2 : (j + j) ^ 2 = 4 * (j ^ 2) := by ring + rw [hm2] at h4 + omega + · have hm2 : m ^ 2 % 4 = 1 := Int.sq_mod_four_eq_one_of_odd hm' + omega +\end{lstlisting} +The steps correspond to the proof of Lemma~\ref{lem:key}: \texttt{h1} is \eqref{eq:h1}, obtained by \texttt{linear\_combination}, which checks with \texttt{ring} that the difference of the two sides of \texttt{h1} equals the difference of the two sides of \texttt{h} (this is Lemma~\ref{lem:identity}); Lemma~\ref{lem:sq} is the core Lean lemma \decl{Int.pow_dvd_pow_iff}; \texttt{h3} is \eqref{eq:h3}, obtained by cancelling with \texttt{mul\_left\_cancel}$_0$; and the final case analysis modulo $4$ uses Mathlib's \decl{Int.sq_mod_four_eq_one_of_odd} and the decision procedure \texttt{omega}. The proof of \decl{result} follows the proof of Theorem~\ref{thm:main}: it casts $4KR=xyz$ to $\Z$, derives $P(x,y,z)R^2=(xyz)^2$ by rewriting with \decl{HasArea} and \texttt{ring}, obtains the two permuted hypotheses by \texttt{linear\_combination}, applies \decl{two_dvd_of_heron} three times, casts the three divisibilities back to $\N$, and concludes with \decl{Nat.dvd_gcd} and \texttt{omega}. The proof performs no large computation; \texttt{native\_decide}, \texttt{sorry} and \texttt{set\_option} do not occur. The kernel evaluation with \texttt{decide +kernel} occurs only in the data lemma \decl{a_data} of the statement file, which \decl{result} does not use. + +\subsection*{Audit} +The file ends with the command +\begin{lstlisting} +#math0_settles Math0.Frontier.A392943.result Math0.Statements.A392943.statement +\end{lstlisting} +defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself. It fails unless (1) \decl{statement} is a definition of type \texttt{Prop} without universe parameters; (2) \decl{statement} and \decl{result} depend on no axioms other than \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (this rejects \decl{sorryAx}, the axiom \decl{Lean.ofReduceBool} introduced by \texttt{native\_decide}, and custom axioms); and (3) the type of \decl{result} is syntactically the statement or its negation, after removing metadata annotations, with no unfolding. On this file it reports +\begin{lstlisting} +math0 audit: 'Math0.Statements.A392943.statement' depends on axioms [propext] +math0 audit: 'Math0.Frontier.A392943.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A392943.result' proves 'Math0.Statements.A392943.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; the repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. To reproduce, run \path{scripts/verify.sh} from the repository root: it fetches the Mathlib build cache, builds all math0 results with \texttt{lake build} (re-running every audit command), checks that the pinned \texttt{formal\_conjectures} and \texttt{mathlib} checkouts are unmodified, and reports the number of passed statement checks. The single file can be checked with \texttt{lake env lean Math0/Frontier/OEIS/A392943.lean} in the directory \path{lean}; once the statement module is built, this needs well under a minute of CPU time, most of it spent loading the imported Mathlib modules (between about $6$ and $15$ seconds of user time in our runs). Building the statement module itself is dominated by the kernel check of \decl{a_data}, which takes well under a minute. + +\begin{thebibliography}{99} + +\bibitem{Aa} +M.~Aassila, \emph{Some results on Heron triangles}, Elem. Math. \textbf{56} (2001), no.~4, 143--146, \url{https://doi.org/10.1007/PL00000549}. Retracted by the editorial board of Elemente der Mathematik. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An open and evolving benchmark for verified discovery in mathematics}, arXiv:2605.13171, 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{KL} +A.-V.~Kramer and F.~Luca, \emph{Some remarks on Heron triangles}, Acta Acad. Paedagog. Agriensis Sect. Mat. (N.S.) \textbf{27} (2000), 25--38. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Read} +E.~Read, \emph{Integer triangles with integer circumradii}, Math. Gaz. \textbf{107} (2023), no.~569, 241--248, \url{https://doi.org/10.1017/mag.2023.55}. + +\bibitem{vL} +R.~van Luijk, \emph{The diameter of the circumcircle of a Heron triangle}, Elem. Math. \textbf{63} (2008), no.~3, 118--121, \url{https://doi.org/10.4171/EM/96}. + +\bibitem{A392942} +The OEIS Foundation Inc., \url{https://oeis.org/A392942}, entry by F.~Huber (2026). + +\bibitem{A392943} +The OEIS Foundation Inc., \url{https://oeis.org/A392943}, entry by F.~Huber (2026). + +\end{thebibliography} + +\end{document} diff --git a/results/oeis-a393794/README.md b/results/oeis-a393794/README.md new file mode 100644 index 0000000..0203172 --- /dev/null +++ b/results/oeis-a393794/README.md @@ -0,0 +1,45 @@ +# The 1089-trick map has two 9-digit fixed points (A393794 uniqueness conjecture is false) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Sequences and series +**Source problem:** OEIS A393794 +**Date:** 2026-10-18 + +## Result + +Let rev(m) be the decimal reversal of m (leading zeros dropped), and let T(x) = D + rev(D) with D = |x - rev(x)|. Havenaar's conjecture in A393794 says that for every n >= 1, a(n) = 110*(10^(n+1) - 1) is the only fixed point of T with exactly n+4 decimal digits. This is false. For n = 5, x = 108910890 has 9 digits and satisfies T(x) = x, but x is not a(5) = 109999890. + +## Assessment + +The refutation is one explicit 9-digit number whose fixed-point property is checked by a few lines of arithmetic. Where it comes from is immediate from the entry itself: the entry's proof uses only 9k = rev(k), and it points to A001232, whose listed data includes the non-primitive term 10891089. Extending this to every n >= 5 (using 1089 0...0 1089) is equally elementary. The number had also already appeared in the conjecturer's own computational output and in Almirantis-Li. No new idea was needed, so this is routine. + +*Follows from:* The entry's own proof that T(a(n)) = a(n) works for any k with 9k = rev(k): rev(10k) = 9k, so D = k and T(10k) = 10k. Cross-reference A001232 lists such k, including the non-primitive term 10891089 (its 5th term; Hasler's comment there describes the concatenated terms 1089 0...0 1089). This gives 10*10891089 = 108910890, a second 9-digit fixed point. A direct exhaustive search of 9-digit numbers also finds it. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A393794](https://oeis.org/A393794) as [`Math0.Statements.A393794.statement`](../../lean/Math0/Statements/OEIS/A393794.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A393794.lean`](../../lean/Math0/Frontier/OEIS/A393794.lean) refutes (proves the negation of) it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "a(n) is the unique fixed point of the 1089-trick map T among all (n+4)-digit numbers (verified exhaustively for n = 1..4; conjectured for all n >= 1)." (comment in A393794, entry by _Remco Havenaar_, Feb 27 2026; the entry names the sequence 'Fixed points of the 1089-trick map' and gives a(n) = 110*(10^(n+1)-1)) + +Referees: OEIS A393794 (Havenaar, Feb 27 2026; #19, Mar 10 2026, no correction as of GitHub oeisdata mirror). OEIS A001232 (numbers k with 9k = rev k; includes non-primitive 10891089; structure theorem by D. W. Wilson 1997 and M. F. Hasler 2022), from which 10*A001232 ⊂ Fix(T) follows trivially. R. Havenaar, SYNTRIAD/digit-dynamics GitHub repo (initial commit 2026-03-09): papers/paper_A.tex still states the uniqueness conjecture, while data/results_export.json experiment id 10 (truc_1089, 7-digit domain, 2026-02-25) lists 108910890 among T's fixed points without remark. Neither source states the contradiction. Y. Almirantis and W. Li, arXiv:2408.02527 and arXiv:2410.11784 (Fibonacci Quart. 64 (2026) 281-310) study the related two-option reversal map Phi, with Phi(Phi(x)) = T(x) in the relevant range; arXiv:2410.11784, which predates the conjecture, lists 108910890 twice: in Table 2 as part of the 2-cycle {10891089, 108910890} of Phi, and in Appendix A.2 among the outputs of the two-step 1089 trick on eight-digit numbers; it does not consider the fixed points of T. OEIS A124074 (S. Dumortier, 2006) studies a variant of Phi whose example already shows the 2-cycle 1089 -> 10890 -> 1089. No published refutation found: this is the first explicit refutation, and it is mathematically elementary. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a393794, + author = {{math0}}, + title = {{The 1089-trick map has two 9-digit fixed points (A393794 uniqueness conjecture is false)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a393794}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a393794/paper.pdf b/results/oeis-a393794/paper.pdf new file mode 100644 index 0000000..b01f8c3 Binary files /dev/null and b/results/oeis-a393794/paper.pdf differ diff --git a/results/oeis-a393794/paper.tex b/results/oeis-a393794/paper.tex new file mode 100644 index 0000000..e69d15d --- /dev/null +++ b/results/oeis-a393794/paper.tex @@ -0,0 +1,353 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage[T1]{fontenc} +\usepackage{lmodern} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + upquote=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {→}{{$\to$}}1 {≠}{{$\ne$}}1 {≤}{{$\le$}}1 {≥}{{$\ge$}}1 + {∀}{{$\forall$}}1 {¬}{{$\neg$}}1 {∧}{{$\wedge$}}1 {…}{{$\dots$}}1 {·}{{$\cdot$}}1 + {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} +\newunicodechar{…}{\ensuremath{\dots}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\N}{\mathbb{N}} +\DeclareMathOperator{\rev}{rev} +\newcommand{\len}{\ell} +\newcommand{\xs}{x_{\ast}} + +\title[A counterexample to a conjecture in OEIS A393794]{A second nine-digit fixed point of the 1089-trick map,\\ refuting a uniqueness conjecture in OEIS A393794} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Let $\rev(m)$ denote the decimal reversal of $m$ (leading zeros dropped) and let $T(x)=D+\rev(D)$ with $D=|x-\rev(x)|$ be the 1089-trick map. +In OEIS A393794, Havenaar conjectured that for every $n\ge1$ the number $a(n)=110\,(10^{n+1}-1)$ is the only fixed point of $T$ with exactly $n+4$ decimal digits. +We show that $108910890$ is a nine-digit fixed point of $T$ different from $a(5)=109999890$, so the conjecture is false; the counterexample is ten times the term $10891089$ of A001232, and an elementary argument, not formalized, shows that the same construction gives a second $(n+4)$-digit fixed point for every $n\ge5$. +To our knowledge this is the first explicit refutation, although the argument is elementary and the number had already been computed without being connected to the conjecture: it is listed among the fixed points of $T$ in the conjecturer's own computational data, and, as one element of a $2$-cycle of a closely related reversal map, in a 2024 paper of Almirantis and Li. +The refutation is verified in Lean~4 against a statement that math0 formalized from the OEIS entry, checked against the OEIS data, reviewed for fidelity and frozen before the proof attempt. +\end{abstract} +\maketitle + +\section{Introduction} + +For $m\in\N$ let $\rev(m)$ be the number whose decimal digits are those of $m$ in reverse order, with leading zeros of the result dropped (OEIS A004086 \cite{OEISrel}); for example $\rev(10890)=9801$. +The \emph{1089-trick map} is +\[ + T(x)=D+\rev(D),\qquad D=|x-\rev(x)| . +\] +The name alludes to the classical puzzle in which a three-digit number whose first and last digits differ is replaced by the difference $D$ of it and its reversal, written with three digits, and then $D$ is added to its own reversal; the result is always $1089$. +The map $T$ applies the same two operations to numbers of any length, but without padding. + +In OEIS A393794 \cite{A393794}, Remco Havenaar (February 27, 2026) lists the numbers +\[ + a(n)=110\,(10^{n+1}-1)\qquad(n\ge1):\quad 10890,\ 109890,\ 1099890,\ 10999890,\ 109999890,\ \dots, +\] +whose decimal digits are $1,0,9^{\,n-1},8,9,0$. The entry proves that each $a(n)$ is a fixed point of $T$ and conjectures that it is the \emph{only} fixed point of $T$ with $n+4$ digits, having verified this exhaustively for $n=1,\dots,4$. +The same family and the same conjecture appear in Havenaar's manuscript \cite{HavenaarPaper}, in the repository linked from the entry \cite{HavenaarRepo}: writing $k=n+4$ for the number of digits, its Remark ``Uniqueness per digit count'' reads (with $n_k=a(k-4)$ and $\mathcal{D}_{10}^k$ the set of $k$-digit numbers) ``Exhaustive computation for $k = 5, 6, 7, 8$ confirms that $n_k$ is the \emph{unique} fixed point of~$T$ in $\mathcal{D}_{10}^k$. We conjecture that this holds for all $k \geq 5$,'' and the question is repeated in the manuscript's list of open problems. + +Both sources relate $a(n)$ to OEIS A001232 \cite{A001232}, the numbers $k>0$ with $9k=\rev(k)$: $1089$, $10989$, $109989$, $1099989$, $10891089$, \dots. They observe that $a(n)/10=11\,(10^{n+1}-1)$ is a \emph{primitive} term of A001232, that is, one whose digits are $1,0,9^{\,n-1},8,9$. The structure of A001232 is classical. D.~W. Wilson (1997) showed that its terms are the numbers $99m$ in which $m$ is a palindrome over the digits $0,1$ with no isolated digit, so that there are $F_{\lfloor j/2\rfloor-1}$ terms with $j\ge4$ digits ($F_i$ the Fibonacci numbers); M.~F. Hasler (2022) described the terms as symmetric concatenations of primitive terms separated by blocks of zeros (both results are recorded in \cite{A001232}). Sloane's survey \cite{Sloane2178} treats the more general question of which numbers are multiplied by a constant when their digits are reversed. +Almirantis and Li \cite{AL1,AL2} study the iteration of the two-option reversal map $\Phi(y)=y-\rev(y)$ if $\rev(y)\rev(x)$ and $D=x-\rev(x)$ satisfies $\rev(D)\ge D$, then $\Phi(\Phi(x))=T(x)$. In \cite[Corollary~3.3]{AL2} they show that if $\rev(y)=9y$ then $y$ and $10y$ form a $2$-cycle of $\Phi$, which is the computation in Lemma~\ref{lem:A001232} below, and their Table~2 lists the $2$-cycle $\{10891089,\,108910890\}$. The variant of $\Phi$ that also subtracts when $\rev(y)=y$, and so sends palindromes to $0$, is the map of OEIS A124074 \cite{A124074}, contributed by S.~Dumortier in 2006, whose example already exhibits the $2$-cycle $1089\to10890\to1089$. Section~2 of \cite{AL2} also studies the two steps of the 1089 trick for numbers of any length, that is, the values $T(y)$ for $y>\rev(y)$ such that $y-\rev(y)$ has as many digits as $y$, and its Appendix~A.2 lists $108910890$ among these values for eight-digit $y$. Neither paper considers the fixed points of $T$, and \cite{AL2} predates the conjecture of A393794. (Corollary, table and appendix numbers refer to the arXiv version of \cite{AL2}.) + +\subsection*{Result and status} +We show (Theorem~\ref{thm:main}) that $\xs=108910890$ is a nine-digit fixed point of $T$ with $\xs\ne a(5)=109999890$, so the conjecture fails at $n=5$. It is the smallest failure, since the conjecture holds for $n\le4$ by the exhaustive checks of \cite{A393794}, which the math0 referees repeated. The witness is $\xs=10\cdot 10891089$, ten times the smallest non-primitive term of A001232, and Lemma~\ref{lem:A001232} explains why: ten times any term of A001232 is a fixed point of $T$. The same construction gives a second fixed point with $n+4$ digits for every $n\ge5$ (Proposition~\ref{prop:family}). + +A393794 contains no correction or comment noting a counterexample: revision \#19 (March 10, 2026) was still the current revision when we checked \url{https://oeis.org/A393794} in October 2026. The math0 referees found no refutation on arXiv or elsewhere on the web. A393794 is not part of the formal-conjectures repository \cite{FC}. +We note, however, that the number $108910890$ had already been computed. It is listed, without comment, among the fixed points of $T$ in a results file of Havenaar's repository \cite{HavenaarRepo} (file \path{data/results_export.json}, experiment~10, time-stamped February 25, 2026, which iterates $T$ from all $9\cdot10^6$ seven-digit starting values). It also appears twice in \cite{AL2}, which predates the conjecture: in Table~2, as the larger element of a $2$-cycle of the map $\Phi$ described above, and in Appendix~A.2, among the outputs of the two-step 1089 trick on eight-digit numbers. In none of these places is it connected with the conjecture. With these caveats we classify the result as new; mathematically it is elementary. + +\section{Statement}\label{sec:statement} + +\subsection{The theorem} +For $x\in\N$ let $\len(x)$ be the number of decimal digits of $x$, with $\len(0)=0$; thus $\len(x)=L\ge1$ if and only if $10^{L-1}\le x<10^{L}$. Let $\rev$, $T$ and $a(n)$ be as in the introduction, and put +\[ + \xs=108910890 . +\] + +\begin{theorem}\label{thm:main} +$\len(\xs)=9$, $T(\xs)=\xs$, and $\xs\ne a(5)=109999890$. +\end{theorem} + +\begin{corollary}\label{cor:main} +The following statement is false: for every $n\ge1$, $\len(a(n))=n+4$, $T(a(n))=a(n)$, and every $x\in\N$ with $\len(x)=n+4$ and $T(x)=x$ equals $a(n)$. +\end{corollary} + +The first two clauses of Corollary~\ref{cor:main} hold for every $n\ge1$ (Lemma~\ref{lem:an}), so it is the uniqueness clause that fails. + +\subsection{The OEIS conjecture} +The conjecture is the first comment of A393794 \cite{A393794}, an entry by Remco Havenaar dated February 27, 2026 (revision \#19, March 10, 2026). The entry is named ``Fixed points of the 1089-trick map T(n) = |n - reverse(n)| + reverse(|n - reverse(n)|)'', has offset~$1$ and formula ``\texttt{a(n) = 110*(10\^{}(n+1) - 1)}'', and the comment reads verbatim: +\begin{quote}\small +a(n) is the unique fixed point of the 1089-trick map T among all (n+4)-digit numbers (verified exhaustively for n = 1..4; conjectured for all n >= 1). +\end{quote} +The entry's example ``10890 - 09801 = 1089; 1089 + 9801 = 10890'' shows that reversal drops leading zeros: with $\rev(1089)$ padded to five digits, $98010$, the example would fail. + +\subsection{The Lean statement} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A393794.lean} (namespace \decl{Math0.Statements.A393794}). It was reviewed for fidelity and frozen (SHA-256 \texttt{3c0423ef\dots ae69a}) before any proof attempt. Its definitions and the statement are (verbatim): +\begin{lstlisting} +/-- `reverse(m)` (A004086): the number whose decimal digits are those of `m` in reverse order +(leading zeros of the result are dropped). -/ +def rev (m : ℕ) : ℕ := Nat.ofDigits 10 (Nat.digits 10 m).reverse + +/-- The 1089-trick map `T(x) = |x - reverse(x)| + reverse(|x - reverse(x)|)`. -/ +def T (x : ℕ) : ℕ := Nat.dist x (rev x) + rev (Nat.dist x (rev x)) + +/-- A393794: `a(n) = 110 * (10^(n+1) - 1)` (`n ≥ 1`), the fixed points `10890, 109890, +1099890, …` of the 1089-trick map `T` listed in the entry; `a(n)` has `n + 4` digits. -/ +def a (n : ℕ) : ℕ := 110 * (10 ^ (n + 1) - 1) + +/-- Conjecture (Havenaar, A393794): for every `n ≥ 1`, `a(n)` is the unique fixed point of the +1089-trick map `T` among all `(n + 4)`-digit numbers. -/ +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + (Nat.digits 10 (a n)).length = n + 4 ∧ T (a n) = a n ∧ + ∀ x : ℕ, (Nat.digits 10 x).length = n + 4 → T x = x → x = a n +\end{lstlisting} + +\subsection{How the encoding matches the OEIS} +\emph{Reversal.} Mathlib's \texttt{Nat.digits 10 m} is the list of decimal digits of $m$, least significant first, with no trailing zeros (so \texttt{Nat.digits 10 0} is empty), and \texttt{Nat.ofDigits 10 L} evaluates $\sum_i L_i10^i$. Reversing the list and evaluating it gives the digits of $m$ read backwards, and any zeros that become leading zeros contribute nothing. So \decl{rev} is A004086, and the kernel confirms \texttt{rev 10890 = 9801} in agreement with the entry's example. +\emph{The map.} \texttt{Nat.dist x y} is $|x-y|$, so truncated subtraction on $\N$ plays no role in \decl{T}. +\emph{The sequence.} \decl{a} is the entry's formula with offset $1$. As $10^{n+1}\ge1$, the subtraction does not truncate. The entry's data, its Mathematica and Python programs, and its proof that $T(a(n))=a(n)$ all use this formula. The name, read as ``$a(n)$ is the $n$-th positive fixed point of $T$'', gives an equivalent conjecture: under the conjecture, the positive fixed points with at least five digits are exactly the $a(n)$, and \decl{least_fixed_point} below shows there is none with fewer digits; conversely, under the other reading the only $(n+4)$-digit fixed point must be $a(n)$, which is one by Lemma~\ref{lem:an}. The formula reading is used because defining $a(n)$ as the $n$-th fixed point would build the conjectured uniqueness into the definition. +\emph{Digit length.} ``$(n+4)$-digit'' is \texttt{(Nat.digits 10 x).length = n + 4}, i.e.\ $\len(x)=n+4$. This excludes the trivial fixed point $T(0)=0$. +\emph{Range.} The comment says ``conjectured for all n >= 1'', and the statement adds no other hypotheses. The two conjuncts asserting that $a(n)$ has $n+4$ digits and is fixed are part of the meaning of ``$a(n)$ is the unique fixed point''; they are true (Lemma~\ref{lem:an}). +\emph{Data.} The statement file proves, each by \texttt{decide +kernel}: that $a(1),\dots,a(18)$ are the $18$ listed terms $10890,\dots,1099999999999999999890$ (\decl{a_data}); that $T$ fixes each of them (\decl{T_data}); that $a(i+1)$ has $i+5$ digits for $i<18$ (\decl{digits_data}); and that $10890=a(1)$ is the least positive fixed point of $T$, by checking every $x<10890$ (\decl{least_fixed_point}). + +Corollary~\ref{cor:main} is the Lean theorem \decl{Math0.Frontier.A393794.result}, whose type is \texttt{¬ statement}. Theorem~\ref{thm:main} is the private lemma \decl{witness} in the same file (Section~\ref{sec:lean}). Lemmas~\ref{lem:A001232} and~\ref{lem:an} and Proposition~\ref{prop:family} below are not formalized. + +\section{Proof}\label{sec:proof} + +\subsection{The witness} +\begin{proof}[Proof of Theorem~\ref{thm:main}] +Since $10^8\le\xs<10^9$, we have $\len(\xs)=9$. The decimal digits of $\xs$ are $1,0,8,9,1,0,8,9,0$; read backwards they are $0,9,8,0,1,9,8,0,1$, and dropping the leading zero gives +\[ + \rev(\xs)=98019801 . +\] +As $\xs>\rev(\xs)$, +\[ + D=|\xs-\rev(\xs)|=108910890-98019801=10891089 . +\] +The digits of $D$ are $1,0,8,9,1,0,8,9$, so $\rev(D)=98019801$ (here no zero is dropped), and +\[ + T(\xs)=D+\rev(D)=10891089+98019801=108910890=\xs . +\] +Finally $a(5)=110\,(10^6-1)=110\cdot999999=109999890\ne\xs$. +\end{proof} + +In Lean, the three facts of Theorem~\ref{thm:main} form a single proposition, the lemma \decl{witness}, which is closed by \texttt{decide +kernel}. Its second conjunct, \texttt{T 108910890 = 108910890}, is decided by evaluating the definitions: the kernel computes \texttt{Nat.digits 10 108910890} $=[0,9,8,0,1,9,8,0,1]$, reverses it to $[1,0,8,9,1,0,8,9,0]$, and evaluates $\sum_i L_i10^i=98019801$, exactly as in the proof above. The other two conjuncts are evaluated the same way. + +\begin{proof}[Proof of Corollary~\ref{cor:main}] +Suppose the statement holds. Apply it with $n=5$, which satisfies $n\ge1$, and take the uniqueness clause with $x=\xs$. By Theorem~\ref{thm:main}, $\len(\xs)=9=5+4$ and $T(\xs)=\xs$, so $\xs=a(5)$. This contradicts $\xs\ne a(5)$. +\end{proof} + +The Lean proof of \decl{result} is exactly this: it introduces the hypothesis \texttt{h : statement}, destructures \decl{witness} into \texttt{hlen}, \texttt{hT} and \texttt{hne}, discharges $1\le5$ by \texttt{norm\_num}, and applies \texttt{hne} to the third component of \texttt{h 5}, instantiated at $x=108910890$. + +\subsection{Where the counterexample comes from} +The rest of this section is not part of the Lean development. It explains the witness and shows that the conjecture fails for every $n\ge5$. + +\begin{lemma}\label{lem:A001232} +If $k\ge1$ and $9k=\rev(k)$, then $T(10k)=10k$ and $\len(10k)=\len(k)+1$. +\end{lemma} +\begin{proof} +If the decimal string of $k$ is $s$, then that of $10k$ is $s0$. Its reversal is $0$ followed by the reversal of $s$, which, once leading zeros are dropped, is the number $\rev(k)$. Hence $\rev(10k)=\rev(k)=9k$, and $D=|10k-9k|=k$. Then $\rev(D)=9k$ and $T(10k)=k+9k=10k$. The digit count is clear. +\end{proof} + +The same computation appears in \cite[Corollary~3.3]{AL2}, phrased as the statement that $k$ and $10k$ form a $2$-cycle of the map $\Phi$ of the introduction. + +\begin{lemma}[A393794]\label{lem:an} +For every $n\ge1$, $\len(a(n))=n+4$ and $T(a(n))=a(n)$. +\end{lemma} +\begin{proof} +Let $R=10^{n+1}-1$ and $k=11R=10^{n+2}+(10^{n+1}-11)$. As $10^{n+1}-11$ has the $n+1$ digits $9^{\,n-1},8,9$, the digits of $k$ are $1,0,9^{\,n-1},8,9$. Similarly $9k=99R=98\cdot10^{n+1}+(10^{n+1}-99)$, and $10^{n+1}-99$, written with $n+1$ digits, is $9^{\,n-1},0,1$; so $9k$ has digits $9,8,9^{\,n-1},0,1$, which are those of $k$ reversed, and $9k=\rev(k)$. Lemma~\ref{lem:A001232} applies to $k$, and $10k=110R=a(n)$ has $\len(k)+1=n+4$ digits. +\end{proof} + +This is the proof given in the entry \cite{A393794}, rearranged. The witness $\xs$ arises in the same way from $k=10891089=1089\cdot10001$, which satisfies $9k=98019801=\rev(k)$. + +\begin{proposition}\label{prop:family} +For every $n\ge5$, the number $x_n=10890\,(10^{n-1}+1)$ has $n+4$ digits, satisfies $T(x_n)=x_n$, and is different from $a(n)$. In particular $x_5=\xs$. +\end{proposition} +\begin{proof} +Put $m=n-1\ge4$ and $k=1089\,(10^m+1)=1089\cdot10^m+1089$. As $1089<10^4\le10^m$, the decimal string of $k$ is $1089\,0^{m-4}\,1089$, with $m+4$ digits. Its reversal is $9801\,0^{m-4}\,9801$, that is, $\rev(k)=9801\cdot10^m+9801=9k$. By Lemma~\ref{lem:A001232}, $x_n=10k$ is a fixed point of $T$ with $m+5=n+4$ digits. Finally +\[ + a(n)-x_n=\bigl(11000\cdot10^{n-1}-110\bigr)-\bigl(10890\cdot10^{n-1}+10890\bigr)=110\,(10^{n-1}-100)>0 . +\] +\end{proof} + +So the uniqueness claim, which holds for $n\le4$ by exhaustive search, fails for every $n\ge5$. + +\begin{remark}\label{rem:count} +By Lemma~\ref{lem:A001232} and Wilson's description of A001232 quoted in the introduction, the number of fixed points of $T$ with $n+4$ digits is at least $F_{\lfloor (n+3)/2\rfloor-1}$, which is $2$ for $n=5,6$ and tends to infinity with $n$. +Exhaustive searches run by the math0 referees (one in C over all $x<10^{10}$) found exactly the positive fixed points +\[ + 10890,\ 109890,\ 1099890,\ 10999890,\ 108910890,\ 109999890,\ 1089010890,\ 1099999890, +\] +which are ten times the terms of A001232 below $10^9$. We do not know whether every positive fixed point of $T$ is of this form. +These searches also show that the data of A393794, read as the list of all fixed points of $T$ suggested by the entry's name, omit $108910890$ between $a(4)$ and $a(5)$. +\end{remark} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +In the math0 repository (\url{https://github.com/Foundation-0/math0}), the proof is in \path{lean/Math0/Frontier/OEIS/A393794.lean}, namespace \decl{Math0.Frontier.A393794}. The main theorem is \decl{Math0.Frontier.A393794.result}, with the private lemma \decl{witness}. The statement is \decl{Math0.Statements.A393794.statement} in \path{lean/Math0/Statements/OEIS/A393794.lean}. The proof file, after its imports and module docstring, is (verbatim): +\begin{lstlisting} +namespace Math0.Frontier.A393794 +open Math0.Statements.A393794 + +/-- `108910890` has 9 digits, is fixed by `T`, and differs from `a 5` (kernel-checked). -/ +private theorem witness : + (Nat.digits 10 108910890).length = 5 + 4 ∧ T 108910890 = 108910890 ∧ + 108910890 ≠ a 5 := by + decide +kernel + +/-- The conjecture fails at `n = 5`: `108910890` is a second 9-digit fixed point of `T`. -/ +theorem result : ¬ statement := by + intro h + obtain ⟨hlen, hT, hne⟩ := witness + exact hne ((h 5 (by norm_num)).2.2 108910890 hlen hT) + +end Math0.Frontier.A393794 + +#math0_settles Math0.Frontier.A393794.result Math0.Statements.A393794.statement +\end{lstlisting} + +\subsection*{Kernel computation} +The tactic \texttt{decide +kernel} asks the Lean kernel to reduce the \texttt{Decidable} instance of the proposition in \decl{witness} to \texttt{true}. The kernel unfolds the definitions of \decl{Nat.digits}, \decl{List.reverse}, \decl{Nat.ofDigits}, \decl{Nat.dist}, \decl{rev}, \decl{T} and \decl{a}, using its built-in arbitrary-precision arithmetic on natural-number literals for the divisions, remainders, sums, products and comparisons. No compiled code is trusted: the file uses no \texttt{native\_decide} (which would add the axiom \decl{Lean.ofReduceBool}), and it contains no \texttt{sorry}, \texttt{axiom} or \texttt{set\_option}. The same mechanism proves the data checks \decl{a_data}, \decl{T_data}, \decl{digits_data} and \decl{least_fixed_point} in the statement file. + +\subsection*{Audit} +The command \texttt{\#math0\_settles}, defined in \path{lean/Math0/Audit.lean} for statements that math0 formalizes itself, fails unless (1) \decl{statement} is a universe-monomorphic definition of type \texttt{Prop}; (2) \decl{statement} depends only on the axioms \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound}, so it cannot hide a \texttt{sorry}; (3) the type of \decl{result} is, up to metadata annotations and with no unfolding, either \texttt{statement} or \texttt{¬ statement}; and (4) \decl{result} also depends only on those three axioms. On this file it reports: +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A393794.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A393794.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A393794.result' refutes 'Math0.Statements.A393794.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}. The repository also pins formal-conjectures \cite{FC} at commit \texttt{c77fdd4}, which this result does not use. To reproduce, run \path{scripts/verify.sh} from the repository root. It builds all math0 results with \texttt{lake build}, which re-runs every audit command, and checks that the pinned dependencies are unmodified. To check this file alone once its imports are built (for example by \texttt{lake build}), run \texttt{lake env lean Math0/Frontier/OEIS/A393794.lean} in \path{lean/}; this used under a minute of CPU time on our machine. +The math0 referees also recomputed $\rev(\xs)$, $D$, $\rev(D)$, $T(\xs)$ and $a(5)$ independently in Python. + +\begin{thebibliography}{99} + +\bibitem{AL1} +Y.~Almirantis and W.~Li, \emph{Rich dynamical behaviors from a digital reversal operation}, arXiv:2408.02527, 2024. + +\bibitem{AL2} +Y.~Almirantis and W.~Li, \emph{Extending the 1089 attractor to any number of digits and any number of steps}, Fibonacci Quart. \textbf{64} (2026), no.~2, 281--310; arXiv:2410.11784 (2024). + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171, 2026. \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{HavenaarPaper} +R.~Havenaar, \emph{Fixed Points of Digit-Operation Pipelines in Arbitrary Bases: Algebraic Structure and Five Infinite Families}, manuscript, SYNTRIAD Research, 2026, file \path{papers/paper_A.tex} in \cite{HavenaarRepo}. (Cited in A393794 as \emph{Fixed Points of Digit-Operation Dynamical Systems: Algebraic Structure and Five Infinite Families}.) + +\bibitem{HavenaarRepo} +R.~Havenaar, \emph{SYNTRIAD Digit-Dynamics Discovery Engine}, GitHub repository, \url{https://github.com/SYNTRIAD/digit-dynamics} (accessed October 2026). + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{A393794} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, entry A393794 (R.~Havenaar), \emph{Fixed points of the 1089-trick map}, revision \#19, March 10, 2026, \url{https://oeis.org/A393794}. + +\bibitem{A001232} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, entry A001232 (N.~J.~A. Sloane and S.~Plouffe), \emph{Numbers k such that 9*k = (k written backwards), k > 0}, with contributions by D.~W. Wilson (1997) and M.~F. Hasler (2022), revision \#124, July 28, 2026, \url{https://oeis.org/A001232}. + +\bibitem{A124074} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, entry A124074 (S.~Dumortier, 2006), \emph{Consider the map that sends a number m to m - reverse(m) if that is nonnegative, otherwise to m + reverse(m). Sequence gives those numbers that reach a nonzero cycle under repeated application of this map}, \url{https://oeis.org/A124074}. + +\bibitem{OEISrel} +The OEIS Foundation Inc., \emph{The On-Line Encyclopedia of Integer Sequences}, entry A004086 (N.~J.~A. Sloane), \emph{Read n backwards}, \url{https://oeis.org/A004086}. + +\bibitem{Sloane2178} +N.~J.~A. Sloane, \emph{2178 and all that}, Fibonacci Quart. \textbf{52} (2014), no.~2, 99--120; arXiv:1307.0453. + +\end{thebibliography} + +\end{document} diff --git a/results/oeis-a394981/README.md b/results/oeis-a394981/README.md new file mode 100644 index 0000000..a5f2cc3 --- /dev/null +++ b/results/oeis-a394981/README.md @@ -0,0 +1,43 @@ +# Bar tilings of the smallest-perimeter rectangle: a(n+1) = 4 a(n) for odd n >= 3 (A394981) + +**Classification:** New result (conjecture settled; no earlier resolution found) +**Difficulty (independent assessment):** routine +**Area:** Discrete geometry +**Source problem:** OEIS A394981 +**Date:** 2026-10-20 + +## Result + +Let a(n) be the number of tilings, counted up to the symmetries of the rectangle, of the rows(n) x cols(n) rectangle by the n bars 1x1, 1x2, ..., 1xn, each used exactly once. Here rows(n) = floor((n+1)/2) and cols(n) = (n(n+1)/2)/rows(n). For n = 2m+1 the rectangle is (m+1) x (2m+1), and for n = 2m+2 it is (m+1) x (2m+3). In Lean, a(n) is the frozen bitmask-search definition: it sums the stabilizer sizes of all tilings found by the search and divides by the order of the symmetry group (Burnside). Claim (A394981 conjecture, read for odd n >= 3): for every odd n >= 3, a(n+1) = 4 a(n). The literal case n = 1 fails, a(2) = 1 != 4 = 4 a(1), and the statement excludes it. + +## Assessment + +The proof is short and elementary, about a page of informal argument. Because all bar lengths differ, no tiling has a nontrivial symmetry, so a(n) is a quarter of the raw tiling count. Every bar longer than half the width must lie horizontally, and these bars take one row each, so they all cover the middle column. A case split on where bar m+1 sits divides the larger rectangle's tilings into four classes. Deleting one or two middle or edge columns gives a bijection from each class to the tilings of the smaller rectangle. This pigeonhole and column-deletion argument would come quickly to a competent combinatorialist. The 2400-line Lean file reflects the work of formalizing it, not the difficulty of the mathematics. The proof needs the hypothesis n >= 3 because the identity fails at n = 1. That case is a degenerate exception, and the intended conjecture is fully settled. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A394981](https://oeis.org/A394981) as [`def statement`](../../lean/Math0/Statements/OEIS/A394981.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A394981.lean`](../../lean/Math0/Frontier/OEIS/A394981.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A394981 Conjecture: If n is odd, then a(n+1) = 4*a(n). (Unattributed formula line. Entry by _Gary Yane_, Apr 08 2026; a(1)-a(2) corrected by _Pontus von Brömssen_, May 13 2026.) + +Referees: The OEIS A394981 entry (Gary Yane, Apr 08 2026; a(1)-a(2) corrected by Pontus von Brömssen, May 13 2026; revision #42, May 16 2026, the same in the local mirror and upstream oeisdata) still states the identity as a conjecture, with keyword "more" and no proof reference. No other OEIS entry cites it. Cross-references A254414/A254458/A254607/A329279 are unrelated counts. Searches found no proof or counterexample on arXiv, MathOverflow, Math StackExchange, SeqFan or the general web. Nearest work, all on a different problem: arXiv:2606.05439, Blanco, Dougherty-Bliss, Ter-Saakov and Zeilberger, "In How Many Ways can a Rectangle be Rectangled?" (tilings by bars of any length); arXiv:2607.29369, Martinez (L-tetromino tilings). + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a394981, + author = {{math0}}, + title = {{Bar tilings of the smallest-perimeter rectangle: a(n+1) = 4 a(n) for odd n >= 3 (A394981)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a394981}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a394981/paper.pdf b/results/oeis-a394981/paper.pdf new file mode 100644 index 0000000..567f16f Binary files /dev/null and b/results/oeis-a394981/paper.pdf differ diff --git a/results/oeis-a394981/paper.tex b/results/oeis-a394981/paper.tex new file mode 100644 index 0000000..13db21a --- /dev/null +++ b/results/oeis-a394981/paper.tex @@ -0,0 +1,331 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + bif,private}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, + breaklines=true, keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, + frame=single, extendedchars=true, inputencoding=utf8, upquote=true, + literate={ℕ}{{$\mathbb{N}$}}1 {∀}{{$\forall$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 + {×}{{$\times$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\code}[1]{\texttt{#1}} +\newcommand{\T}{\mathcal{T}} +\newcommand{\Sm}{S_m} +\newcommand{\Bm}{B_m} + +\title[Bar tilings and OEIS A394981]{Tilings of a rectangle by the bars $1\times1,\dots,1\times n$: a proof that $a(n+1)=4a(n)$ for odd $n\ge3$ in OEIS A394981} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 20, 2026} + + +\begin{document} +\begin{abstract} +OEIS A394981 counts the tilings, up to the symmetries of the rectangle, of the rectangle with short side $\lfloor (n+1)/2\rfloor$ and area $n(n+1)/2$ by the bars $1\times1,\dots,1\times n$, each used once. We prove the conjecture in the entry that $a(n+1)=4a(n)$ for odd $n$, for every odd $n\ge3$; at $n=1$ it fails, as $a(1)=a(2)=1$. For $n\ge3$ no tiling has a nontrivial symmetry, so $a(n)$ is a quarter of the number $R(n)$ of all tilings, and the tilings of the $(m+1)\times(2m+3)$ rectangle split into four classes, each in bijection with the tilings of the $(m+1)\times(2m+1)$ rectangle. The entry still lists the identity as a conjecture and we found no earlier proof, so we classify the result as new. It is verified in Lean~4 against a statement formalized by math0 from the entry, reviewed for fidelity and frozen before the proof attempt, whose definition of $a(n)$ is checked by the kernel against the first nine terms. +\end{abstract} +\maketitle + +\section{Introduction} + +Sequence A394981 of the OEIS \cite{A394981}, contributed by Gary Yane on April~8, 2026, is defined as follows: ``Given a set of n rectangular tiles, \{1 X 1, 1 X 2, 1 X 3, 1 X 4, ..., 1 X n\}, then a(n) is the number of tilings up to symmetry of the rectangle having smallest possible perimeter with area n*(n+1)/2 using all n tiles.'' A comment fixes the rectangle: for $n=8$ it is $4\times9$, and ``the short side of the rectangle has length floor((n+1)/2)''. (The $6\times6$ square has smaller perimeter but cannot contain the $1\times8$ bar.) So the rectangle is $(m+1)\times(2m+1)$ for $n=2m+1$ and $(m+1)\times(2m+3)$ for $n=2m+2$. The entry has offset $1$ and lists $20$ terms, $1,1,1,4,10,40,112,448,1360,5440,17728,70912,\dots$; $a(1)$ and $a(2)$ were corrected by Pontus von Brömssen on May~13, 2026. Its FORMULA section contains the unattributed line +\begin{quote} +``Conjecture: If n is odd, then a(n+1) = 4*a(n).'' +\end{quote} +Read literally this includes $n=1$, where it fails: the $1\times1$ square has one tiling, and the two tilings of the $1\times3$ rectangle (bar $1$ then bar $2$, or bar $2$ then bar $1$) are mirror images, so $a(1)=a(2)=1$. All listed pairs $n=3,5,\dots,19$ satisfy it. We prove it for every odd $n\ge3$ (Theorem~\ref{thm:main}). + +\subsection*{Status and prior work} +The current revision of the entry (\#42, May~16, 2026) still marks the identity as a conjecture, has the keyword ``more'', and records no proof. The math0 referees found no other OEIS entry citing A394981, and no proof or counterexample on arXiv, MathOverflow, Mathematics Stack Exchange, SeqFan or the web. The cross-referenced entries count different objects: tilings of rectangles by bars of unlimited supply (A254414, with its cases A254458 and A254607, by A.~P. Heinz \cite{A254414}) and tilings of the $2n\times2n$ square by $1\times n$ bars (A329279 \cite{A329279} by J.~Bowermaster). Recent work on related enumerations concerns different problems: Blanco, Dougherty-Bliss, Ter-Saakov and Zeilberger \cite{BDTZ} count tilings of grids by width-one strips of arbitrary lengths, with weights, and Martinez \cite{Ma} enumerates tilings by L-tetrominoes. We therefore classify the result as \emph{new}; the proof is elementary. + +\section{Statement}\label{sec:statement} + +\begin{definition}\label{def:tiling} +The $r\times c$ \emph{rectangle} is the set of cells $(i,j)$, $0\le i ℕ) 0 (fun i m => m + (2 ^ c - 1) * 2 ^ (i * w)) r +def starts (free s k : ℕ) : ℕ := + Nat.rec (motive := fun _ => ℕ) free + (fun t acc => Nat.land acc (Nat.shiftRight free ((t + 1) * s))) (k - 1) +def sumBits (g : ℕ → ℕ) (fuel : ℕ) : ℕ → ℕ := + Nat.rec (motive := fun _ => ℕ → ℕ) (fun _ => 0) + (fun _ ih X => + bif Nat.beq X 0 then 0 else g (X - Nat.land X (X - 1)) + ih (Nat.land X (X - 1))) fuel +def search (w N L : ℕ) (f : ℕ → ℕ) : ℕ → ℕ → ℕ → ℕ := + Nat.rec (motive := fun _ => ℕ → ℕ → ℕ) + (fun free lab => bif Nat.beq free 0 then f lab else 0) + (fun k ih free lab => + sumBits (fun x => ih (free - barAt x 1 1 (k + 1)) (lab + (k + 1) * barAt x L 1 (k + 1))) + N (starts free 1 (k + 1)) + + bif Nat.ble 1 k then + sumBits (fun x => ih (free - barAt x 1 w (k + 1)) (lab + (k + 1) * barAt x L w (k + 1))) + N (starts free w (k + 1)) + else 0) +def field (L lab p : ℕ) : ℕ := Nat.land (Nat.shiftRight lab (L * p)) (2 ^ L - 1) +def otherSymmetries (r c : ℕ) : List (ℕ × ℕ → ℕ × ℕ) := + [fun p => (r - 1 - p.1, p.2), fun p => (p.1, c - 1 - p.2), + fun p => (r - 1 - p.1, c - 1 - p.2)] ++ + (if r = c then + [fun p => (p.2, p.1), fun p => (c - 1 - p.2, r - 1 - p.1), fun p => (p.2, r - 1 - p.1), + fun p => (c - 1 - p.2, p.1)] + else []) +def fixes (r c w L : ℕ) (g : ℕ × ℕ → ℕ × ℕ) (lab : ℕ) : Bool := + Nat.rec (motive := fun _ => Bool) true + (fun i ih => + Nat.rec (motive := fun _ => Bool) true + (fun j ihj => + Nat.beq (field L lab ((g (i, j)).1 * w + (g (i, j)).2)) (field L lab (i * w + j)) && + ihj) c && + ih) r +def stabCount (r c w L : ℕ) (lab : ℕ) : ℕ := + 1 + List.rec (motive := fun _ => ℕ) 0 + (fun g _ ih => (bif fixes r c w L g lab then 1 else 0) + ih) (otherSymmetries r c) +def a (n : ℕ) : ℕ := + let r := rows n + let c := cols n + let w := c + 1 + search w (r * w) n (stabCount r c w n) n (rectMask r c w) 0 / + (1 + (otherSymmetries r c).length) +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → Odd n → a (n + 1) = 4 * a n +\end{lstlisting} + +\subsection*{How the Lean definitions encode the entry} +\code{rows} and \code{cols} are $r_n$ and $c_n$ (\decl{rect_data} and \decl{area_data} check the shapes and areas for $n\le20$). Cell $(i,j)$ has index $iw+j$ with $w=c+1$; the padding index $iw+c$ is never a cell, and sets of cells are bitmasks (\code{rectMask r c w} is the rectangle). \code{barAt}~$2^q$~$1$~$s$~$k$ is the bitmask of the cells $q,q+s,\dots,q+(k-1)s$ (\decl{barAt_eq}), and bit $q$ of \code{starts free s k} is set if and only if they are all free (\decl{testBit_starts}): a horizontal placement for $s=1$, as a run cannot pass a padding index, and a vertical one for $s=w$. \code{sumBits g N X} sums $g(2^q)$ over the set bits $q$ of $X$ when $X$ has at most $N$ set bits, which holds here as all set bits are below $N=rw$. \code{search} places the bars $n,\dots,1$ in turn at every placement inside the free cells (vertically only for length $\ge2$), writes each length into the $n$-bit fields of its cells in \code{lab}, and adds \code{f lab} if no cell is left free. \code{field} reads a label, \code{otherSymmetries} lists $G_{r,c}\setminus\{\mathrm{id}\}$, \code{fixes} tests $\lambda_T\circ g=\lambda_T$, and \code{stabCount} is the stabilizer order; so \code{a n} is \eqref{eq:a}. The theorem \decl{a_data} checks $a(1),\dots,a(9)=1,1,1,4,10,40,112,448,1360$ in the kernel (\texttt{decide +kernel}), and \decl{literal_fails_at_one} checks $a(2)\ne4a(1)$. Not kernel-checked: \texttt{\#eval} gives $a(10)=5440$ and $a(11)=17728$, and an independent Python enumeration gives the listed $a(1),\dots,a(10)$. The only change from the literal conjecture is the hypothesis $3\le n$. + +\section{Proof}\label{sec:proof} + +\subsection{From the search to tilings} +For a set $S$ of cells and $w=c+1$ write $\langle S\rangle=\sum_{(i,j)\in S}2^{iw+j}$. + +\begin{lemma}[\decl{search_eq}, \decl{field_cell}, \decl{rectMask_eq}]\label{lem:search} +Let $r,c,n\ge1$, $w=c+1$ and $f:\mathbb N\to\mathbb N$. Then +$\code{search}\ w\ (rw)\ n\ f\ n\ (\code{rectMask}\ r\ c\ w)\ 0=\sum_{T\in\T(r,c,n)}f(\Lambda_T)$, where $\Lambda_T=\sum_{(i,j)}\lambda_T(i,j)\,2^{n(iw+j)}$, and $\code{field}\ n\ \Lambda_T\ (iw+j)=\lambda_T(i,j)$ for every cell $(i,j)$. +\end{lemma} + +\begin{proof} +We have $\code{rectMask}\ r\ c\ w=\langle\text{rectangle}\rangle$. By induction on $k$, for every set $S$ of cells and every $\ell$, $\code{search}\ w\ (rw)\ n\ f\ k\ \langle S\rangle\ \ell$ is the sum of $f\bigl(\ell+\sum_{k'\le k}k'\sum_{(i,j)\in T(k')}2^{n(iw+j)}\bigr)$ over the assignments $T$ of fitting placements to the bars $1,\dots,k$ that partition $S$. For $k=0$ both sides are $f(\ell)$ if $S=\emptyset$, else $0$. For the step, \code{search} sums over the set bits $q=iw+j$ ($jm,\end{cases}\qquad + \pi(b)=\begin{cases}b-e,&b\le m+e,\\ m,&m+em+e+\delta.\end{cases} +\] +Then $\pi\circ\iota=\mathrm{id}$, and the columns of $\Bm$ missed by $\iota$ are $\{0,m+2\}$, $\{m+1,2m+2\}$ and $\{m+1,m+2\}$ in the three cases. In $V_0$, $V_1$ let $s\in\{0,2m+2\}$ be the column of bar $m+1$. + +\begin{lemma}[\decl{bV_long}, \decl{bV_avd}, \decl{bH_long}, \decl{bH_avd}]\label{lem:avoid} +(1) If $T\in V_0\cup V_1$, every long bar $K$ is at some $(i,j,\mathrm h)$ with $e\le j\le m+em$ (\decl{inBar_mvF}, \decl{inBar_lgF}). For short bars this holds because, by Lemma~\ref{lem:avoid}(1), a short bar lies in a block of columns that $\pi$ translates rigidly; a long bar $k+1$ at start $j$ occupies the columns $j,\dots,j+k$ with $e\le j\le m+e=1, and E2(j+1,i) = (2j+1-i)E2(j,i-1) + (i+1)E2(j,i). Let T(n,k) = sum_{j=0}^n (-1)^{n-j} C(n,j) E2(j,n-k), the triangle A395454, and let P_m(t) = sum_{k=0}^m T(m,k) t^k be its row polynomials in the entry's numbering (P_0 = 1, P_1 = 0, P_2 = 2t, ...). Then for every m >= 2, in Z[t], +P_m = (m-1)(1+t) P_{m-1} + (t - t^2) P'_{m-1} + 2(m-1) t P_{m-2}. +Equivalently, with the rows counted from 1 (P1(n) = P_{n-1}), for every n >= 3: P1(n) = (n - 2t + nt - 2) P1(n-1) + (t - t^2) P1'(n-1) + t(2n-4) P1(n-2). This is Alexandersson's conjecture in the form fixed by the frozen statement. + +## Assessment + +The proof takes the standard recurrence for the reversed second-order Eulerian polynomials, applies it inside the alternating binomial transform (Pascal's rule and k*C(n,k) = n*C(n-1,k-1)), and then compares coefficients term by term. Altogether this is about a page of index bookkeeping, and the paper itself calls the argument routine. The result proves the reading the author evidently meant, with rows counted from 1 (an off-by-one in the indexing). That reading reduces at t=1 to the A053871 recurrence. The literal offset-0 reading fails trivially at n=2. No new idea or construction was needed. + +*Follows from:* The standard differential recurrence for second-order Eulerian polynomials, E_{j+1}(x) = (1+2jx)E_j(x) + x(1-x)E_j'(x). This is a direct reformulation of the triangle recurrence in A201637 and Graham-Knuth-Patashnik Section 6.2. It is pushed through the alternating binomial transform that defines A395454 using Pascal's rule. + +*How this was judged:* an independent assessor agent, asked to judge the difficulty of the mathematics and not to inflate it, rated it **routine**. Routine means a short or standard argument, a consequence of material already in the OEIS entry, its cross-references or the literature, or a finite search; substantial means a non-standard idea or a long argument that does not follow readily from such material. (2026-10-26) + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A395454](https://oeis.org/A395454) as [`Math0.Statements.A395454.statement`](../../lean/Math0/Statements/OEIS/A395454.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A395454.lean`](../../lean/Math0/Frontier/OEIS/A395454.lean) proves it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: %F A395454 Conjecture: Let P(n) be the generating polynomial (in t) of row n. Then P(n) = (n - 2*t + n*t - 2)*P(n-1) + (t - t^2)*P'(n-1) + t*(2*n-4)*P(n-2). - Per W. Alexandersson, Jun 27 2026 + +Referees: No earlier resolution found. Closest related work: +- S.-M. Ma and Y.-N. Yeh, "Eulerian polynomials, Stirling permutations of the second kind and perfect matchings," Electron. J. Combin. 24(4) (2017) #P4.27, arXiv:1607.01311. Its Thm 17 is an analogous recurrence for Stirling-derangement polynomials by cycle ascent plateaus (a different family). Its Cor 18 is the A053871 row-sum recurrence. Its Prop 9 implies that A395454 row n is the distribution of n - casc over Stirling derangements. +- G.-H. Duh, Y.-C. R. Lin, S.-M. Ma and Y.-N. Yeh, arXiv:1612.07391 (2016). +- S.-M. Ma, S. Kitaev, J. Yeh and Y.-N. Yeh, arXiv:2601.20665 (2026). +- S. Fried, "Further proofs of conjectures from the OEIS," arXiv:2607.24832 (2026). Does not cover A395454. + +OEIS A395454 (#30, Oct 14 2026; Luschny's entry, Alexandersson's conjecture of Jun 27 2026) still lists the formula as a conjecture, with no proof recorded in any comment, %E line or link. Read with the entry's offset-0 numbering the formula is false; read with rows counted from 1 it holds. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a395454, + author = {{math0}}, + title = {{Alexandersson's recurrence for the row polynomials of A395454 holds (rows counted from 1)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a395454}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a395454/paper.pdf b/results/oeis-a395454/paper.pdf new file mode 100644 index 0000000..7838d0e Binary files /dev/null and b/results/oeis-a395454/paper.pdf differ diff --git a/results/oeis-a395454/paper.tex b/results/oeis-a395454/paper.tex new file mode 100644 index 0000000..e4fb2c5 --- /dev/null +++ b/results/oeis-a395454/paper.tex @@ -0,0 +1,362 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,noncomputable,rw,ring,push_cast}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∃}{{$\exists$}}1 + {¬}{{$\neg$}}1 {→}{{$\to$}}1 {≤}{{$\le$}}1 {∈}{{$\in$}}1 + {∑}{{$\sum$}}1 {·}{{$\cdot$}}1 {⟨}{{$\langle$}}1 {⟩}{{$\rangle$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\Et}{E_2} +\newcommand{\tP}{\widetilde P} + +\title[Alexandersson's recurrence for OEIS A395454]{A differential recurrence for the alternating binomial transform of the second-order Eulerian polynomials (OEIS A395454)} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 24, 2026} + +\begin{document} +\begin{abstract} +Let $P_m(t)=\sum_{k=0}^{m}T(m,k)t^k$ be the row polynomials of the triangle OEIS A395454, $T(n,k)=\sum_{j=0}^{n}(-1)^{n-j}\binom nj\Et(j,n-k)$, where $\Et(j,i)$ are the second-order Eulerian numbers. +We prove that $P_m=(m-1)(1+t)P_{m-1}+(t-t^2)P_{m-1}'+2(m-1)t\,P_{m-2}$ in $\Z[t]$ for every $m\ge2$. +This is the recurrence conjectured by Per W. Alexandersson in the OEIS entry (June 2026) when the rows are counted from~$1$; with the entry's own numbering from~$0$ the formula as written fails already at row~$2$ (and, as we show on paper, for every $n\ge2$). +We found no earlier proof, so we classify the result as new, although the argument is a short computation with reversed second-order Eulerian polynomials and their binomial transform. +The result is verified in Lean~4 against the frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against all $55$ listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +The second-order Eulerian numbers $\Et(n,k)$, in the indexing of Graham, Knuth and Patashnik \cite[\S6.2]{GKP} and of the OEIS entry A201637 \cite{A201637}, are given by $\Et(0,k)=[k=0]$ and, for $n\ge1$ and $k\ge0$, +\begin{equation}\label{eq:E2} + \Et(n,k)=(2n-1-k)\,\Et(n-1,k-1)+(k+1)\,\Et(n-1,k),\qquad \Et(n-1,-1)=0 . +\end{equation} +The first rows are $(1)$, $(1,0)$, $(1,2,0)$, $(1,8,6,0)$. In April 2026 Peter Luschny added to the OEIS the triangle A395454 \cite{A395454}, +\[ + T(n,k)=\sum_{j=0}^{n}\binom{-j-1}{-n-1}\Et(j,n-k)\qquad(0\le k\le n), +\] +where the binomial coefficient at negative integers is understood as in Maple; for $0\le j\le n$ it equals $(-1)^{n-j}\binom nj$, so +\begin{equation}\label{eq:T} + T(n,k)=\sum_{j=0}^{n}(-1)^{n-j}\binom nj\Et(j,n-k). +\end{equation} +Thus the reversed rows of A395454 are the alternating binomial transform of the rows of A201637. The rows of A395454 begin $(1)$, $(0,0)$, $(0,2,0)$, $(0,6,2,0)$, $(0,24,34,2,0)$; their sums $1,0,2,8,60,544,\dots$ form A053871 \cite{A053871}, defined by $a(n)=2(n-1)\bigl(a(n-1)+a(n-2)\bigr)$, $a(0)=1$, $a(1)=0$. +On June~27, 2026 Per W. Alexandersson added to the entry a conjectured three-term differential recurrence for the row polynomials (Section~\ref{sec:statement}). The current revision (\#30, October~14, 2026) still labels it a conjecture and records no proof. +With the entry's numbering of the rows from~$0$ the formula is false, already for row~$2$; with the rows counted from~$1$, which is evidently what the author's $P(n)$ refers to, it holds. This is our main result (Theorem~\ref{thm:main}). + +\subsection*{Prior work} +The math0 referees found no earlier proof or refutation (searching OEIS cross-references, arXiv and the web). The closest work we know of is by Ma and Yeh \cite{MY} on Stirling permutations of the second kind and Stirling derangements, enumerated by cycle ascent plateaus and cycles. We use the numbering of the arXiv version; its Proposition~9, Theorem~17 and Corollary~18 are Proposition~4, Theorem~11 and Corollary~12 of the journal version. Their Theorem~17 is a recurrence of the same shape for the Stirling derangement polynomials, which we denote $D_n(x,q)$ (their $R_n(x,q)$) to avoid a clash with our $R_j$ in Section~\ref{sec:proof}: +$D_{n+1}=2nxD_n+2x(1-x)\,\partial_xD_n+2nxq\,D_{n-1}$ for $n\ge1$. It concerns a different family (at $q=1$, $D_3=4x+4x^2$, whereas $P_3=6t+2t^2$); compare Remark~\ref{rem:reversed}. Their Corollary~18 shows that the numbers of Stirling derangements satisfy the recurrence and initial values of A053871, so they are the row sums of A395454 (see Corollary~\ref{cor:literal}). A referee observed that their Proposition~9 and binomial inversion over fixed points suggest that $P_n(t)$ is the distribution of $n-\mathrm{casc}$ over Stirling derangements of order~$n$ (checked for $n=2,3$); we have not verified this further and do not use it. +The related papers \cite{DLMY,MKYY} do not treat this triangle or recurrence, nor does Fried's recent collection of proofs of OEIS conjectures \cite{Fried}. +Our proof is routine: a differential recurrence for the reversed second-order Eulerian polynomials (a reformulation of \eqref{eq:E2}) is transported through the binomial transform \eqref{eq:T}; the result is new only in that we found no written proof. + +\section{Statement}\label{sec:statement} + +The FORMULA section of A395454 \cite{A395454} contains, verbatim, the line +\begin{quote} +{\small\raggedright\texttt{Conjecture: Let P(n) be the generating polynomial (in t) of row n. Then P(n) = (n - 2*t + n*t - 2)*P(n-1) + (t - t\^{}2)*P'(n-1) + t*(2*n-4)*P(n-2). - \_Per W. Alexandersson\_, Jun 27 2026}\par} +\end{quote} +Here $P'$ is the derivative in $t$, and $n-2t+nt-2=(n-2)(1+t)$. +For $m\ge0$ let $P_m(t)=\sum_{k=0}^{m}T(m,k)t^k\in\Z[t]$ be the generating polynomial of the row with index $m$ in the entry's numbering (offset~$0$), so $P_0=1$, $P_1=0$, $P_2=2t$, $P_3=6t+2t^2$, $P_4=24t+34t^2+2t^3$. + +\subsection*{The reading of the conjecture} +If $P(n)$ is taken to be $P_n$, the formula is false: at $n=2$ its right-hand side is $0\cdot P_1+(t-t^2)P_1'+0\cdot P_0=0$, while $P_2=2t$; at $n=3$ it gives $4t$ instead of $6t+2t^2$ (see also Corollary~\ref{cor:literal}). If $P(n)$ is the polynomial $\tP(n)=P_{n-1}$ of the $n$-th row counted from~$1$, the formula holds. Exact computations by the math0 fidelity reviewer found the literal reading false for $2\le n\le19$ and the shifted one true for $3\le n\le20$; the row sums confirm the shift, since at $t=1$ the conjecture is the recurrence of A053871 moved by one index. The math0 statement therefore formalizes the shifted reading for $n\ge3$, where $\tP(n),\tP(n-1),\tP(n-2)$ are all rows (at $n=2$ it is $0=0$); the literal reading is recorded separately and refuted. + +\begin{theorem}\label{thm:main} +For every integer $m\ge2$, in $\Z[t]$, +\begin{equation}\label{eq:main} + P_m=(m-1)(1+t)\,P_{m-1}+(t-t^2)\,P_{m-1}'+2(m-1)t\,P_{m-2}. +\end{equation} +Equivalently (put $m=n-1$), with $\tP(n)=P_{n-1}$, for every $n\ge3$, +\[ + \tP(n)=(n-2t+nt-2)\,\tP(n-1)+(t-t^2)\,\tP'(n-1)+t(2n-4)\,\tP(n-2). +\] +\end{theorem} + +\begin{corollary}[not formalized]\label{cor:literal} +Let $a(m)=P_m(1)$. Then $a(m)=2(m-1)\bigl(a(m-1)+a(m-2)\bigr)$ for $m\ge2$, so $a$ is A053871. Moreover, for every $n\ge2$ the literal reading $P_n=(n-2)(1+t)P_{n-1}+(t-t^2)P_{n-1}'+2(n-2)t\,P_{n-2}$ is false. +\end{corollary} + +\begin{proof} +Put $t=1$ in \eqref{eq:main}; with $a(0)=1$, $a(1)=0$ this is A053871. Induction gives $a(m)\ge0$, so $a(2)=2$ and $a(m)\ge2(m-1)a(m-1)>0$ for $m\ge3$; thus $a(k)>0$ for $k\ne1$. Subtracting the literal right-hand side from \eqref{eq:main} at $m=n$ leaves $(1+t)P_{n-1}+2tP_{n-2}$, whose value at $t=1$ is $2\bigl(a(n-1)+a(n-2)\bigr)>0$, because at most one of $n-1$, $n-2$ equals $1$. +\end{proof} + +\begin{remark}[reversed form; not formalized]\label{rem:reversed} +Let $Q_n(x)=x^nP_n(1/x)=\sum_{i=0}^{n}T(n,n-i)x^i=\sum_{j=0}^{n}(-1)^{n-j}\binom nj\sum_i\Et(j,i)x^i$. Taking $m=n+1$ in \eqref{eq:main}, substituting $t=1/x$ and multiplying by $x^{n+1}$ gives +$Q_{n+1}=2nx\,(Q_n+Q_{n-1})+x(1-x)\,Q_n'$ for $n\ge1$, with $Q_1=0$ and $Q_2=2x$. At $q=1$ the recurrence of \cite[Theorem~17]{MY} has the same initial values $D_1=0$, $D_2=2x$ and differs from this one only in the coefficient of the derivative term, $2x(1-x)$ instead of $x(1-x)$. +\end{remark} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A395454.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{99c82099\ldots 6646d}) before the proof was written. The definitions and the statement read as follows, inside \texttt{namespace Math0.Statements.A395454} with \texttt{open Polynomial} (verbatim; header, docstrings, theorems and the variant \decl{statement_literal} omitted): +\begin{lstlisting} +def E2 : ℕ → ℕ → ℤ + | 0, 0 => 1 + | 0, _ + 1 => 0 + | n + 1, 0 => E2 n 0 + | n + 1, k + 1 => + (2 * ((n : ℤ) + 1) - 1 - ((k : ℤ) + 1)) * E2 n k + ((k : ℤ) + 1 + 1) * E2 n (k + 1) +def T (n k : ℕ) : ℤ := + ∑ j ∈ Finset.range (n + 1), (-1) ^ (n - j) * (n.choose j : ℤ) * E2 j (n - k) +def a (i : ℕ) : ℤ := + ((List.range (i + 1)).flatMap fun n => (List.range (n + 1)).map (T n)).getD i 0 +noncomputable def P (n : ℕ) : ℤ[X] := + ∑ k ∈ Finset.range (n + 1), C (T n k) * X ^ k +noncomputable def P1 (n : ℕ) : ℤ[X] := P (n - 1) +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → + P1 n = ((n : ℤ[X]) - 2 * X + (n : ℤ[X]) * X - 2) * P1 (n - 1) + + (X - X ^ 2) * derivative (P1 (n - 1)) + + X * (2 * (n : ℤ[X]) - 4) * P1 (n - 2) +\end{lstlisting} +\emph{Encoding.} \decl{E2} is \eqref{eq:E2}, stated for row $n+1$ and computed in $\Z$. \decl{T} is \eqref{eq:T}, Maple's $\binom{-j-1}{-n-1}$ being replaced by $(-1)^{n-j}\binom nj$; it is used only for $k\le n$, where $n-k$ is exact. \decl{a} is the triangle read by rows (the OEIS sequence, offset~$0$). \decl{P}~$n$ is $P_n\in\Z[X]$ ($X=t$), \decl{derivative} is the formal derivative, and \decl{P1}~$n=P_{n-1}=\tP(n)$. The coefficients are cast to $\Z[X]$, and for $n\ge3$ the natural-number subtractions in the indices are exact. \decl{statement_literal} is the same formula with \decl{P} for \decl{P1}, for $n\ge2$. + +\emph{Checks against the data.} The statement file proves \decl{E2_data}, stating that the values \texttt{E2 n k} for $0\le k\le n\le8$ are rows $0,\dots,8$ of A201637 ($45$ terms, written out), and \decl{a_data}, stating that \texttt{(List.range 55).map (fun i => a (i + 0))} is the literal list of all $55$ terms in the DATA section of A395454 (rows $0,\dots,9$). Both are proved by \texttt{decide +kernel}: the kernel evaluates the closed left-hand side by unfolding the definitions and compares it with the literal list. This anchors \decl{E2}, \decl{T} and \decl{a} to the OEIS data independently of the conjecture. Finally, \decl{not_statement_literal}\,: $\neg$\,\decl{statement_literal} compares coefficients of $t$ at $n=2$, using \decl{P_one}\,: \texttt{P 1 = 0} and \decl{P_two}\,: \texttt{P 2 = C 2 * X}. + +\section{Proof}\label{sec:proof} + +The proof follows the Lean file \path{lean/Math0/Frontier/OEIS/A395454.lean}; the Lean names of the corresponding declarations are given in brackets. All polynomials lie in $\Z[t]$, the prime denotes the formal derivative $d/dt$, and we write $u=-t$. + +\begin{lemma}[\decl{E2_eq_zero}, \decl{E2_succ_zero}, \decl{E2_succ_succ}]\label{lem:E2} +For all $j,i\ge0$: $\Et(j,i)=0$ if $i>j$; $\Et(j+1,0)=\Et(j,0)$; and +$\Et(j+1,i+1)=(2j-i)\,\Et(j,i)+(i+2)\,\Et(j,i+1)$. +\end{lemma} + +\begin{proof} +The last two are the defining clauses of \decl{E2}, with simplified coefficients. The first follows by induction on $j$: $\Et(0,i)=0$ for $i\ge1$, and if $i+1>j+1$ then $i>j$ and $i+1>j$, so both terms of $\Et(j+1,i+1)$ vanish. +\end{proof} + +\begin{lemma}[\decl{XX_deriv_pow}, \decl{XX_deriv_negpow}]\label{lem:deriv} +For every $k\ge0$, $(t-t^2)(t^k)'=k\,(t^k-t^{k+1})$ and $(t-t^2)(u^k)'=k(1-t)\,u^k$. +\end{lemma} +\begin{proof} +Both sides vanish for $k=0$; for $k\ge1$, $(t-t^2)kt^{k-1}=k(t^k-t^{k+1})$ and $-(t-t^2)ku^{k-1}=k(1-t)u^k$. +\end{proof} + +For $j\ge0$ define the \emph{reversed second-order Eulerian polynomial} [\decl{R}] +\[ + R_j(t)=\sum_{i=0}^{j}\Et(j,i)\,t^{j-i}, +\] +so $R_0=1$, $R_1=t$, $R_2=t^2+2t$, $R_3=t^3+8t^2+6t$. + +\begin{lemma}[\decl{R_rhs}, \decl{R_succ}]\label{lem:R} +For every $j\ge0$, $R_{j+1}=\bigl(j+(j+1)t\bigr)R_j+(t-t^2)R_j'$. +\end{lemma} + +\begin{proof} +For $i\le j$, Lemma~\ref{lem:deriv} with $k=j-i$ gives $\bigl(j+(j+1)t\bigr)t^{j-i}+(t-t^2)(t^{j-i})'=(2j-i)t^{j-i}+(i+1)t^{j-i+1}$. Hence the right-hand side equals +\begin{equation}\label{eq:Rrhs} + \sum_{i=0}^{j}(2j-i)\Et(j,i)\,t^{j-i}+\sum_{i=0}^{j}(i+1)\Et(j,i)\,t^{j-i+1}. +\end{equation} +On the left, split off the term $i=0$ of $R_{j+1}=\sum_{i=0}^{j+1}\Et(j+1,i)t^{j+1-i}$ and write the others with index $i+1$, $0\le i\le j$. By Lemma~\ref{lem:E2}, +\[ + R_{j+1}=\sum_{i=0}^{j}(2j-i)\Et(j,i)\,t^{j-i}+\Bigl(\sum_{i=0}^{j}(i+2)\Et(j,i+1)\,t^{j-i}+\Et(j,0)\,t^{j+1}\Bigr). +\] +The first sum is the first sum in \eqref{eq:Rrhs}. In the bracket the term $i=j$ vanishes, since $\Et(j,j+1)=0$ (Lemma~\ref{lem:E2}); shifting the index of the remaining terms by one, the bracket becomes $\sum_{i=1}^{j}(i+1)\Et(j,i)t^{j-i+1}+1\cdot\Et(j,0)t^{j+1}$, which is the second sum in \eqref{eq:Rrhs}. +\end{proof} + +Next define the binomial transform [\decl{S}] +\[ + S_n=\sum_{j=0}^{n}\binom nj u^{\,n-j}R_j\qquad(n\ge0). +\] + +\begin{lemma}[\decl{S_term}, \decl{P_eq_S}]\label{lem:PS} +For every $n\ge0$, $P_n=S_n$. +\end{lemma} + +\begin{proof} +Let $0\le j\le n$. Since $(n-j)+(j-i)=n-i$ for $i\le j$, +\[ + \binom nj u^{n-j}R_j=\sum_{i=0}^{j}(-1)^{n-j}\binom nj\Et(j,i)\,t^{n-i}=\sum_{i=0}^{n}(-1)^{n-j}\binom nj\Et(j,i)\,t^{n-i}, +\] +where the sum may be extended to $i\le n$ because $\Et(j,i)=0$ for $i>j$ (Lemma~\ref{lem:E2}). Summing over $j$ and exchanging the two finite sums, +\[ + S_n=\sum_{i=0}^{n}\Bigl(\sum_{j=0}^{n}(-1)^{n-j}\binom nj\Et(j,i)\Bigr)t^{n-i} + =\sum_{k=0}^{n}\Bigl(\sum_{j=0}^{n}(-1)^{n-j}\binom nj\Et(j,n-k)\Bigr)t^{k}=\sum_{k=0}^{n}T(n,k)t^k, +\] +by the reflection $i=n-k$ of the range $\{0,\dots,n\}$ (\texttt{Finset.sum\_range\_reflect}) and \eqref{eq:T}. +\end{proof} + +The recurrence for $S_n$ is proved by writing every quantity as a sum over $0\le j\le n+1$ of multiples of $\binom{n+1}{j}u^{n+1-j}R_j$ and $\binom{n+1}{j}u^{n+1-j}R_{j+1}$. + +\begin{lemma}[\decl{S_succ}, \decl{S_deriv}, \decl{S_mul}]\label{lem:S3} +For every $n\ge0$: +\begin{align*} + &\text{(a)}\quad S_{n+1}=\sum_{j=0}^{n}\binom nj\bigl(u^{n-j}R_{j+1}+u^{n-j+1}R_j\bigr);\\ + &\text{(b)}\quad (t-t^2)S_n'=\sum_{j=0}^{n}\binom nj\Bigl((n-j)(1-t)\,u^{n-j}R_j+u^{n-j}\bigl(R_{j+1}-(j+(j+1)t)R_j\bigr)\Bigr);\\ + &\text{(c)}\quad (n+1)\,u\,S_n=\sum_{j=0}^{n+1}\binom{n+1}{j}(n+1-j)\,u^{n+1-j}R_j . +\end{align*} +\end{lemma} + +\begin{proof} +(a) In $S_{n+1}=\sum_{j=0}^{n+1}\binom{n+1}{j}u^{n+1-j}R_j$ split off $j=0$ and write the other terms with index $j+1$, $0\le j\le n$. By Pascal's rule $\binom{n+1}{j+1}=\binom nj+\binom n{j+1}$, +\[ + S_{n+1}=\sum_{j=0}^{n}\binom nj u^{n-j}R_{j+1}+\Bigl(\sum_{j=0}^{n}\binom n{j+1}u^{n-j}R_{j+1}+u^{n+1}R_0\Bigr). +\] +In the bracket the term $j=n$ vanishes ($\binom n{n+1}=0$); shifting the index of the others, the bracket is $\sum_{j=0}^{n}\binom nj u^{n-j+1}R_j$. + +(b) Differentiate termwise with the product rule, $(u^{n-j}R_j)'=(u^{n-j})'R_j+u^{n-j}R_j'$, and multiply by $t-t^2$. Lemma~\ref{lem:deriv} with $k=n-j$ handles the first term, and Lemma~\ref{lem:R}, in the form $(t-t^2)R_j'=R_{j+1}-(j+(j+1)t)R_j$, the second. + +(c) The term $j=n+1$ on the right is $0$. For $j\le n$, $(n+1)\binom nj=(n+1-j)\binom{n+1}j$ (\texttt{Nat.choose\_mul\_succ\_eq}) and $u\cdot u^{n-j}=u^{n+1-j}$, so the remaining terms agree with those of $(n+1)uS_n$. +\end{proof} + +\begin{proposition}[\decl{S_rec}]\label{prop:Srec} +For every $n\ge0$, +\[ + S_{n+2}=(n+1)(1+t)\,S_{n+1}+(t-t^2)\,S_{n+1}'+2(n+1)t\,S_n . +\] +\end{proposition} + +\begin{proof} +Write $2(n+1)tS_n=-2\,(n+1)uS_n$. Apply Lemma~\ref{lem:S3}(a) (with $n+1$ in place of $n$) to the left-hand side, the definition of $S_{n+1}$ to the first term on the right, Lemma~\ref{lem:S3}(b) (with $n+1$) to the second and Lemma~\ref{lem:S3}(c) to the third. Every quantity is now a sum over $0\le j\le n+1$, and it suffices to compare the summands. Fix $j$, put $K=n+1-j$, and divide by $\binom{n+1}{j}$. The summand on the left is $u^KR_{j+1}+u^{K+1}R_j=u^KR_{j+1}-t\,u^KR_j$, and on the right it is +\[ + u^K\Bigl(R_{j+1}+\bigl[(n+1)(1+t)+K(1-t)-j-(j+1)t-2K\bigr]R_j\Bigr). +\] +The terms with $R_{j+1}$ agree, and since $n+1=j+K$ the bracket equals $(j+K)(1+t)+K-Kt-j-jt-t-2K=-t$. (In Lean: \texttt{Nat.cast\_sub} for $K$, then \texttt{ring}.) +\end{proof} + +\begin{proof}[Proof of Theorem~\ref{thm:main}] +Let $n\ge3$ and write $n=m+3$ with $m\ge0$. Then $\tP(n)=P_{m+2}$, $\tP(n-1)=P_{m+1}$, $\tP(n-2)=P_m$, and by Lemma~\ref{lem:PS} these equal $S_{m+2}$, $S_{m+1}$, $S_m$. The coefficients of the conjecture are $n-2t+nt-2=(m+1)(1+t)$ and $t(2n-4)=2(m+1)t$, so the claimed identity is Proposition~\ref{prop:Srec} with $m$ in place of $n$. Replacing $m+2$ by $m$ gives \eqref{eq:main}. +\end{proof} + +\section{Machine verification}\label{sec:lean} + +\subsection*{Files and declarations} +The proof is in \path{lean/Math0/Frontier/OEIS/A395454.lean} in the math0 repository, \url{https://github.com/Foundation-0/math0}; it imports the frozen statement file (Section~\ref{sec:statement}) and \path{lean/Math0/Audit.lean}. The main declaration \decl{Math0.Frontier.A395454.result} has type \decl{Math0.Statements.A395454.statement}; the private auxiliary declarations are named in brackets in Section~\ref{sec:proof}. As there, \decl{result} writes $n=m+3$, rewrites the three \texttt{P1} terms with \decl{P_eq_S}, applies \decl{S_rec}~\texttt{m} and ends with \texttt{push\_cast; ring}. Neither file uses \texttt{sorry}, \texttt{native\_decide}, custom axioms or \texttt{set\_option}; the statement file uses \texttt{decide +kernel} only for its data checks and for the values of \decl{T} used in \decl{P_one} and \decl{P_two}. + +\subsection*{Audit} +The file ends with \texttt{\#math0\_settles} \decl{Math0.Frontier.A395454.result} \decl{Math0.Statements.A395454.statement}. This command (\path{lean/Math0/Audit.lean}) fails unless (1) \decl{statement} is a \texttt{Prop}-valued definition without universe parameters; (2) both declarations depend on no axioms besides \decl{propext}, \decl{Classical.choice} and \decl{Quot.sound} (so no \decl{sorryAx}, \texttt{native\_decide} or custom axioms); and (3) the type of \decl{result} is syntactically \decl{statement} or $\neg$\,\decl{statement}, up to metadata, with no unfolding. It reports +\begin{lstlisting}[basicstyle=\ttfamily\scriptsize] +math0 audit: 'Math0.Statements.A395454.statement' depends on axioms [Classical.choice, Quot.sound, propext] +math0 audit: 'Math0.Frontier.A395454.result' depends on axioms [Classical.choice, Quot.sound, propext] +math0 statement check: 'Math0.Frontier.A395454.result' proves 'Math0.Statements.A395454.statement' +\end{lstlisting} + +\subsection*{Toolchain and reproduction} +We use Lean~4 \cite{Lean4} \texttt{v4.33.1} and Mathlib \cite{Mathlib} \texttt{v4.33.1}, pinned in \path{lean/}; formal-conjectures \cite{FC} is pinned at commit \texttt{c77fdd4} but not used here. Running \path{scripts/verify.sh} from the repository root fetches the Mathlib cache, rebuilds all results with \texttt{lake build} (re-running every audit), checks that the pinned dependencies are unmodified, and counts the passed statement checks. The single file is checked by \texttt{lake env lean Math0/Frontier/OEIS/A395454.lean} in \path{lean/}. + +{\footnotesize +\begin{thebibliography}{99} + +\bibitem{DLMY} +G.-H. Duh, Y.-C.~R. Lin, S.-M. Ma, and Y.-N. Yeh, \emph{Stirling permutations, marked permutations and Stirling derangements}, arXiv:1612.07391 [math.CO], 2016. + +\bibitem{FC} +M.~Firsching, P.~Lezeau, S.~Mercuri, M.~Z. Horv\'ath, Y.~Dillies, C.~S\"onne, E.~Wieser, F.~Zhang, T.~Hubert, B.~Ag\"uera y Arcas, and P.~Kohli, \emph{Formal Conjectures: An Open and Evolving Benchmark for Verified Discovery in Mathematics}, arXiv:2605.13171 [cs.AI], 2026. Repository: \url{https://github.com/google-deepmind/formal-conjectures}. + +\bibitem{Fried} +S.~Fried, \emph{Further proofs of conjectures from the OEIS}, arXiv:2607.24832 [math.GM], 2026. + +\bibitem{GKP} +R.~L. Graham, D.~E. Knuth, and O.~Patashnik, \emph{Concrete Mathematics: A Foundation for Computer Science}, 2nd ed., Addison-Wesley, Reading, MA, 1994. + +\bibitem{Lean4} +L.~de Moura and S.~Ullrich, \emph{The Lean 4 theorem prover and programming language}, in: Automated Deduction -- CADE 28, Lecture Notes in Comput. Sci. \textbf{12699}, Springer, 2021, 625--635. + +\bibitem{MKYY} +S.-M. Ma, S.~Kitaev, J.~Yeh, and Y.-N. Yeh, \emph{Eulerian-type polynomials over matchings and matching permutations}, arXiv:2601.20665 [math.CO], 2026. + +\bibitem{MY} +S.-M. Ma and Y.-N. Yeh, \emph{Eulerian polynomials, Stirling permutations of the second kind and perfect matchings}, Electron. J. Combin. \textbf{24}(4) (2017), \#P4.27, \url{https://doi.org/10.37236/7288}; arXiv:1607.01311. + +\bibitem{Mathlib} +The mathlib Community, \emph{The Lean mathematical library}, in: Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs (CPP 2020), ACM, 2020, 367--381. + +\bibitem{A053871} +The OEIS Foundation Inc., entry A053871 (C.~Moore and C.~G. Bower, 2000) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A053871}. + +\bibitem{A201637} +The OEIS Foundation Inc., \emph{Triangle of second-order Eulerian numbers}, entry A201637 (P.~Luschny, 2012) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A201637}. + +\bibitem{A395454} +The OEIS Foundation Inc., entry A395454 (P.~Luschny, 2026; conjecture by P.~W. Alexandersson, June~27, 2026) in The On-Line Encyclopedia of Integer Sequences, \url{https://oeis.org/A395454}; revision \#30, October~14, 2026. + +\end{thebibliography} +} + +\end{document} diff --git a/results/oeis-a397315/README.md b/results/oeis-a397315/README.md new file mode 100644 index 0000000..870c224 --- /dev/null +++ b/results/oeis-a397315/README.md @@ -0,0 +1,42 @@ +# A397315: a 14-point blackout of the 5 x 8 grid refutes T(n,m) = n + m + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Discrete geometry +**Source problem:** OEIS A397315 +**Date:** 2026-10-18 + +## Result + +Pemmasani's conjecture in OEIS A397315 says this. Let T(n,k) be the largest number of points that can be blacked out of the grid {0..k-1} x {0..n-1} so that every lattice rectangle (tilted rectangles included) is still determined by its set of visible vertices. Then T(n,m) = n + m whenever min(n,m) >= 4, except T(4,4) = 7 and T(4,5) = T(5,4) = 8. We prove the negation. The 5 x 8 grid (n = 5, k = 8) has a valid blackout of 14 points, so T(5,8) >= 14, which is more than the predicted 5 + 8 = 13. + +## Verification + +The statement was formalized by math0 (not by a third party) from the conjecture in [OEIS A397315](https://oeis.org/A397315) as [`Math0.Statements.A397315.statement`](../../lean/Math0/Statements/OEIS/A397315.lean). Its definitions are checked by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and froze it (by hash) before any proof attempt. The statement and its frozen hash were committed together with the proof, so the order (freeze, then proof) is recorded only in the pipeline's logs, not in the git history. Its fidelity to the OEIS text is a judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below for comparison. The Lean file [`lean/Math0/Frontier/OEIS/A397315.lean`](../../lean/Math0/Frontier/OEIS/A397315.lean) refutes (proves the negation of) it; the final command `#math0_settles` checks that our theorem's type is exactly the statement or its negation and that both use no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +Conjecture as stated in OEIS: "Conjecture: T(n,m) = n+m whenever min(n,m) >= 4, except T(4,4) = 7 and T(4,5) = 8 (verified on seven cells through 6 X 6)." (entry by _Arjun Pemmasani_, Sep 02 2026; comment in the entry, which was last revised Sep 12 2026) + +Referees: The refutation is in Arjun Pemmasani's GitHub repository "Kagey-Problems" (https://github.com/apemm/Kagey-Problems), which the OEIS entry A397315 links in its %H line. These are the files that record it: +- kagey-problems/problem001/data/ledger.md, "Outcomes, part 2 (2026-10-17)", commit 45b175b, 2026-10-17: blackout(5,8) = 14 and blackout(6,8) = 15. The 5 x 8 maximum blackouts form one orbit of 4. +- The JIS paper draft kagey-problems/problem001/jis/pemmasani.tex, file sections/sec07_five.tex. Its Theorem "the guess fails" states f(5,8) = 14 and f(6,8) = 15. Theorem "five rows" states f(5,m) = m+6 for every m >= 8. +- The Lean proof kagey-problems/lean/KageyProblems/Problem001/Kernel.lean, theorem kfvalue_5_8 (f(5,8) = 14, kernel-checked), commit 8df4162, 2026-10-18. CollarBoards.lean has fval_five: f(5,m) = m+6 for m >= 8. +- kagey-problems/problem001/README.md says: "The guess f = h+m for both sides at least 4 fails at 5 x 8 and 6 x 8." + +The source problem is Peter Kagey's Open Problem Collection, Problem 001 (https://peterkagey.com/problems/001/); his page lists no values. The companion entry A399580 has nothing on 5 x 8. Neither OEIS entry, in the local mirror or on GitHub (#38 and #24), has been updated with the refutation yet. + +## Manuscript + +[paper.pdf](paper.pdf) ([source](paper.tex)) + +## Citation + +```bibtex +@misc{math0:oeis-a397315, + author = {{math0}}, + title = {{A397315: a 14-point blackout of the 5 x 8 grid refutes T(n,m) = n + m}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeis-a397315}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeis-a397315/paper.pdf b/results/oeis-a397315/paper.pdf new file mode 100644 index 0000000..8a152bb Binary files /dev/null and b/results/oeis-a397315/paper.pdf differ diff --git a/results/oeis-a397315/paper.tex b/results/oeis-a397315/paper.tex new file mode 100644 index 0000000..c43af78 --- /dev/null +++ b/results/oeis-a397315/paper.tex @@ -0,0 +1,342 @@ +% math0 manuscript. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{url} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} +\usepackage{booktabs} +\usepackage{tikz} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases, + private,unfold,rw,at}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\footnotesize, columns=fullflexible, keepspaces=true, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8, + literate={ℕ}{{$\mathbb{N}$}}1 {ℤ}{{$\mathbb{Z}$}}1 {∀}{{$\forall$}}1 {∧}{{$\wedge$}}1 + {∨}{{$\vee$}}1 {≤}{{$\le$}}1 {≠}{{$\ne$}}1 {×}{{$\times$}}1 {¬}{{$\neg$}}1 + {→}{{$\to$}}1 {·}{{$\cdot$}}1} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\newtheorem{conjecture}[theorem]{Conjecture} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\emergencystretch=3em +% Lean identifiers in running text (breakable at dots and underscores). +\expandafter\def\expandafter\UrlBreaks\expandafter{\UrlBreaks\do\_\do\.} +\DeclareUrlCommand\decl{\urlstyle{tt}} +\newcommand{\Z}{\mathbb{Z}} +\newcommand{\N}{\mathbb{N}} +\newcommand{\G}{G_{n,k}} +\newcommand{\Rc}{\mathcal{R}} +\newcommand{\Bs}{B^{*}} +\newcommand{\Lr}{L_{\mathrm{r}}} + +\title[A 14-point blackout of the $5\times8$ grid]{A valid $14$-point blackout of the $5\times 8$ grid: the conjecture $T(n,m)=n+m$ of OEIS A397315 fails at $(5,8)$} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{October 18, 2026} + +\begin{document} +\begin{abstract} +Let $T(n,k)$ (OEIS A397315) be the largest number of points of an $n\times k$ grid of points that can be blacked out so that every rectangle with all four vertices on grid points, tilted ones included, is determined by its set of visible vertices. +A.~Pemmasani conjectured in 2026 that $T(n,m)=n+m$ whenever $\min(n,m)\ge4$, apart from $T(4,4)=7$ and $T(4,5)=8$. +We exhibit $14$ points of the $5\times8$ grid whose removal leaves the $364$ rectangles of the grid with pairwise distinct sets of visible vertices, so $T(5,8)\ge14>13$ and the conjecture is false. +The result is known: on October~17, 2026, Pemmasani recorded $T(5,8)=14$ in the repository linked from the entry, and on October~18, 2026 a Lean proof of $T(5,8)=14$ appeared there; this note is an independent formal proof of a known result. +Our refutation is verified in Lean~4 against a frozen, fidelity-reviewed statement that math0 formalized from the OEIS entry, whose definitions are checked by the kernel against the first ten listed terms. +\end{abstract} +\maketitle + +\section{Introduction} + +Problem~001 of Peter Kagey's Open Problem Collection \cite{Kagey} asks how many points of a rectangular grid of points can be blacked out while every rectangle whose four vertices are grid points remains identifiable from its visible vertices. The OEIS entry A397315, contributed by Arjun Pemmasani on September~2, 2026 \cite{A397315}, tabulates the answer $T(n,k)$ for the $n\times k$ grid, $n,k\ge2$, by antidiagonals; the companion entry A399580 \cite{A399580}, by the same author, counts the maximum blackouts. The $45$ listed terms cover the antidiagonals $n+k\le12$. The comments of A397315 state $T(2,m)=m+1$ for $m\ge3$, with reference to the linked repository, and two conjectures: $T(3,m)=m+2$ for $m\ge3$, and the one quoted in Section~\ref{sec:statement}, that $T(n,m)=n+m$ whenever $\min(n,m)\ge4$, with two exceptions. All listed cells with $\min(n,k)\ge4$ agree with it. + +\subsection*{Result} +The second conjecture fails on the next antidiagonal: the $5\times 8$ grid has a valid blackout of $14$ points (Theorem~\ref{thm:main}, Figure~\ref{fig:witness}), so $T(5,8)\ge14$, whereas the conjecture predicts $T(5,8)=13$. + +\subsection*{Prior work and status} +The entry links Pemmasani's GitHub repository \cite{Pem}, which, as the math0 referees found, already contains the refutation. The ledger \path{kagey-problems/problem001/data/ledger.md}, section ``Outcomes, part~2 (2026-10-17)'' (commit \texttt{45b175b}, October~17, 2026), records \texttt{blackout(5,8) = 14} and \texttt{blackout(5,9) = 15}, against the predicted $13$ and $14$, also \texttt{blackout(6,8) = 15}, and that the maximum blackouts of the $5\times8$ grid form one orbit of size~$4$ under the symmetries of the grid. The paper draft \path{kagey-problems/problem001/jis/pemmasani.tex} states, with $f$ for $T$, $f(5,8)=14$ and $f(6,8)=15$ (theorem ``the guess fails'') and $f(5,m)=m+6$ for every $m\ge8$ (theorem ``five rows''). The Lean file \path{kagey-problems/lean/KageyProblems/Problem001/Kernel.lean} (commit \texttt{8df4162}, October~18, 2026) contains a kernel-checked theorem \texttt{kfvalue\_5\_8} stating $f(5,8)=14$, and \path{CollarBoards.lean} (added in commit \texttt{a46acfd}, later on October~18, 2026) contains \texttt{fval\_five}, $f(5,m)=m+6$ for $m\ge8$. The referees also observed that our blackout is the image of Pemmasani's maximum blackout $S_8$ under the reflection $y\mapsto4-y$. At the time of writing, neither OEIS entry (A397315, revision~\#38 of September~12, 2026; A399580, revision~\#24) has been updated with the refutation, and A397315 still states the conjecture. The conjecture is not among the statements of the formal-conjectures repository \cite{FC}. +Our witness was found by a SAT search in the math0 pipeline, and our Lean proof was written without use of Pemmasani's files. Since a Lean proof of the stronger statement $T(5,8)=14$ already exists, we classify this note as an \emph{independent formal proof of a known result}. We prove only $T(5,8)\ge14$, which suffices for the refutation. + +\begin{figure}[ht] +\centering +\begin{tikzpicture}[scale=0.55] + \foreach \x in {0,...,7} \foreach \y in {0,...,4} \draw (\x,\y) circle (0.16); + \foreach \p in {(0,1),(0,4),(1,0),(1,1),(2,0),(2,3),(3,0),(4,0),(5,1),(5,2),(6,2),(6,3),(7,3),(7,4)} + \fill \p circle (0.2); + \foreach \x in {0,...,7} \node[below] at (\x,-0.3) {\scriptsize $\x$}; + \foreach \y in {0,...,4} \node[left] at (-0.3,\y) {\scriptsize $\y$}; + \node at (8.2,0) {\small $x$}; + \node at (0,5.0) {\small $y$}; +\end{tikzpicture} +\caption{The blackout $\Bs$ (filled) in $G_{5,8}=\{0,\dots,7\}\times\{0,\dots,4\}$.}\label{fig:witness} +\end{figure} + +\section{Statement}\label{sec:statement} + +\subsection*{Definitions} +Following the programs in the entry, the $n\times k$ grid is $\G=\{0,\dots,k-1\}\times\{0,\dots,n-1\}\subseteq\Z^2$. A \emph{rectangle} of $\G$ is a set $\{a,b,c,d\}$ where $a,b,c\in\G$ are pairwise distinct, $(a-b)\cdot(c-b)=0$, and $d=a+c-b\in\G$; let $\Rc_{n,k}$ be the set of rectangles. A set $B\subseteq\G$ is a \emph{valid blackout} if $R\mapsto R\setminus B$ is injective on $\Rc_{n,k}$, and $T(n,k)$ is the largest size of a valid blackout (the empty set is valid). +Here $d\notin\{a,b,c\}$: $d=a$ forces $c=b$, $d=c$ forces $a=b$, and $d=b$ gives $0=(a-b)\cdot(c-b)=-|a-b|^2$. So $a,b,c,d$ are the vertices, in cyclic order, of a non-degenerate rectangle with a right angle at $b$, and conversely every rectangle with vertices in $\G$ (axis-parallel or tilted, squares included) arises in this way. + +\subsection*{The conjecture} +The conjecture is stated in the COMMENTS section of A397315 (entry by A.~Pemmasani, September~2, 2026; revision~\#38 of September~12, 2026), verbatim: +\begin{quote} +\texttt{Conjecture: T(n,m) = n+m whenever min(n,m) >= 4, except T(4,4) = 7 and T(4,5) = 8 (verified on seven cells through 6 X 6).} +\end{quote} +Since $T$ is symmetric (transpose the grid) and the entry lists $T(5,4)=8$, the exception $T(4,5)=8$ is read as covering $(5,4)$ as well. + +\begin{conjecture}[Pemmasani \cite{A397315}]\label{conj} +For all $n,m$ with $\min(n,m)\ge4$: $T(4,4)=7$, $T(4,5)=T(5,4)=8$, and $T(n,m)=n+m$ otherwise. +\end{conjecture} + +The cell $(5,8)$ is not exceptional, so under every reading of the exceptions the conjecture predicts $T(5,8)=13$. + +\begin{theorem}\label{thm:main} +The set +\begin{align*} + \Bs=\{&(0,1),(0,4),(1,0),(1,1),(2,0),(2,3),(3,0),\\ + &(4,0),(5,1),(5,2),(6,2),(6,3),(7,3),(7,4)\} +\end{align*} +is a valid blackout of $G_{5,8}$. Hence $T(5,8)\ge14>5+8$, and Conjecture~\ref{conj} is false. +\end{theorem} + +\subsection*{Lean formalization} +The statement was formalized by math0 in \path{lean/Math0/Statements/OEIS/A397315.lean}, reviewed for fidelity, and frozen (SHA-256 \texttt{81afd722\ldots39eba61c5d}) before any proof attempt. The definitions on which \decl{statement} depends are, verbatim except that docstrings and blank lines are omitted: +\begin{lstlisting} +namespace Math0.Statements.A397315 +def pt (n i : ℕ) : ℤ × ℤ := (((i / n : ℕ) : ℤ), ((i % n : ℕ) : ℤ)) +def inGrid (n k : ℕ) (p : ℤ × ℤ) : Bool := + decide (0 ≤ p.1) && decide (p.1 < k) && decide (0 ≤ p.2) && decide (p.2 < n) +def idx (n : ℕ) (p : ℤ × ℤ) : ℕ := p.1.toNat * n + p.2.toNat +def rectMask? (n k a b c : ℕ) : Option ℕ := + let A := pt n a + let B := pt n b + let C := pt n c + let D := A + C - B + if a ≠ b ∧ b ≠ c ∧ a ≠ c ∧ (A.1 - B.1) * (C.1 - B.1) + (A.2 - B.2) * (C.2 - B.2) = 0 ∧ + inGrid n k D = true then + some (2 ^ a ||| 2 ^ b ||| 2 ^ c ||| 2 ^ idx n D) + else none +def rects (n k : ℕ) : List ℕ := + ((List.range (n * k)).flatMap fun a => (List.range (n * k)).flatMap fun b => + (List.range (n * k)).filterMap fun c => rectMask? n k a b c).eraseDups +def visible (R B : ℕ) : ℕ := Nat.xor R (Nat.land R B) +def notMem (x : ℕ) (l : List ℕ) : Bool := l.rec true fun y _ ih => !(Nat.beq x y) && ih +def pairwiseDistinct (l : List ℕ) : Bool := l.rec true fun x xs ih => notMem x xs && ih +def isValidBlackout (n k B : ℕ) : Bool := pairwiseDistinct ((rects n k).map (visible · B)) +def card : ℕ → ℕ → ℕ + | 0, _ => 0 + | len + 1, B => B % 2 + card len (B / 2) +def T (n k : ℕ) : ℕ := + ((List.range (2 ^ (n * k))).filter (isValidBlackout n k)).foldr + (fun B m => max (card (n * k) B) m) 0 +def statement : Prop := + ∀ n m : ℕ, 4 ≤ min n m → + T n m = if n = 4 ∧ m = 4 then 7 + else if (n = 4 ∧ m = 5) ∨ (n = 5 ∧ m = 4) then 8 + else n + m +end Math0.Statements.A397315 +\end{lstlisting} +\emph{Encoding.} The point $(x,y)\in\G$ has index $nx+y\in\{0,\dots,nk-1\}$, and \texttt{pt n i} $=(\lfloor i/n\rfloor, i\bmod n)$ inverts this numbering; a set $S$ of points is the bitmask $\sum_{(x,y)\in S}2^{nx+y}$. For indices $a,b,c$, \texttt{rectMask?} tests the conditions of the definition, with the dot product computed in $\Z$, and returns the mask of $\{a,b,c,d\}$. The list \texttt{rects n k} collects these masks over all ordered triples and erases duplicates (each rectangle arises from exactly $8$ triples: $b$ is any vertex and $a,c$ are its two neighbours, in either order), so it lists $\Rc_{n,k}$ once each. \texttt{visible R B} $=R\oplus(R\wedge B)$ is the mask of $R\setminus B$, and \texttt{pairwiseDistinct} decides \texttt{List.Nodup} (Lemma~\ref{lem:pd}), so \texttt{isValidBlackout n k B} says that $B$ is a valid blackout. \texttt{card (n*k) B} counts the $1$ bits of $B$ below position $nk$, and \texttt{T n k} maximizes it over the valid masks $B<2^{nk}$; this is $T(n,k)$, and \decl{statement} is Conjecture~\ref{conj}. + +\emph{Check against the OEIS data.} The statement file also defines the antidiagonal reading order \texttt{cell} and the sequence \texttt{a} with the entry's offset~$2$. Ten theorems \texttt{T\_2\_2}, \dots, \texttt{T\_5\_2}, each proved by \texttt{decide +kernel}, evaluate $T$ from the definition on the first ten cells (at most $2^{12}$ candidate blackouts each), and \decl{a_data} assembles them: the terms $4,4,4,5,5,5,6,6,6,6$ agree with the entry. During formalization and fidelity review, Python transcriptions of the same encoding reproduced the first $15$ listed terms (among them $T(4,4)=7$) and $T(4,5)=T(5,4)=8$, and a referee's exact MaxSAT computation reproduced $13$ listed values, among them $T(5,5)=10$, $T(6,6)=12$ and $T(5,7)=12$. + +\section{Proof}\label{sec:proof} + +The proof follows \path{lean/Math0/Frontier/OEIS/A397315.lean}; names of private auxiliary declarations are given in brackets. Throughout, $n=5$, $k=8$, and points are identified with their indices $0,\dots,39$. In indices, the blackout and its mask [\texttt{Bw}] are +\[ + \Bs=\{1,4,5,6,10,13,15,20,26,27,32,33,38,39\},\qquad B_w=\textstyle\sum_{i\in\Bs}2^i=837721039986<2^{40}. +\] +Evaluating \texttt{isValidBlackout 5 8 Bw} directly in the kernel exhausts memory (evaluating \texttt{rectMask?} alone on the $40^3$ triples took about $219$\,s and $3.9$\,GB). The proof therefore replaces \texttt{rectMask?} by a natural-number version and splits the check into a covering step and an injectivity step. + +\begin{lemma}[\decl{rectMask_eq}]\label{lem:fast} +For $i\in\N$ write $i_x=\lfloor i/n\rfloor$, $i_y=i\bmod n$, and let $\dot-$ be truncated subtraction. For all $n,k,a,b,c\in\N$, \texttt{rectMask?\ n k a b c} equals \texttt{fastMask n k a b c}, defined as \texttt{some}$(2^a\mid 2^b\mid 2^c\mid 2^{\delta})$, $\delta=(a_x+c_x\dot-b_x)\,n+(a_y+c_y\dot-b_y)$, if $a,b,c$ are pairwise distinct and +\begin{gather} + a_xc_x+b_x^2+a_yc_y+b_y^2=a_xb_x+b_xc_x+a_yb_y+b_yc_y,\label{eq:dot}\\ + b_x\le a_x+c_x f c \&\& ih) m} evaluates to \texttt{true}, then $f(c)=\texttt{true}$ for all $c 1 has b^n ≡ b^{a(n)} (mod n) for all b (OEIS A051903) + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Number theory +**Source problem:** OEIS 51903 +**Date:** 2026-10-17 + +## Result + +Let a(n) be the largest exponent in the prime factorization of n (OEIS A051903; a(1) = 0). Thomas Ordowski (Dec 2019) asked: are there odd numbers n with a(n) > 1 and b^n ≡ b^{a(n)} (mod n) for every natural number b? The upstream formal statement says such an n exists. We prove its negation: there is no odd n with a(n) > 1 such that b^n ≡ b^{a(n)} (mod n) for all b ∈ ℕ. + +## Verification + +The Lean file [`lean/Math0/OEIS/OeisA51903_conjecture2.lean`](../../lean/Math0/OEIS/OeisA51903_conjecture2.lean) refutes (proves the negation of) the upstream statement [`OeisA51903.conjecture2`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/OEIS/51903.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research open`). Its final command `#math0_refutes` checks that our theorem's type is syntactically identical to the upstream statement (negated) and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +OEIS A051903 comments: Thomas Ordowski, Dec 02 2019, posed questions (*), (**) and (***). Ansh Mishra, Sep 30 2026, added "Answer to (**): No. Answer to (***): Yes. See Mishra and Senthilkumar (2026)". Ansh Mishra and Aryan Senthilkumar, "On Two Questions of Ordowski about the Largest Exponent in a Prime Factorization", Zenodo preprint, 2026-09-30, https://zenodo.org/records/23064142 (doi:10.5281/zenodo.23064142). It includes Lean 4 / Mathlib proofs, `A051903Core.not_conj2` and `OeisA51903.conjecture2_solved`, of the negation of OeisA51903.conjecture2 using only the standard axioms. That paper credits T. Adamczewski, fc-review-results (https://github.com/tadamcz/fc-review-results, runs of 11, 21 and 23 Sep 2026, entry OEIS/51903), with answering (**) negatively by the same p^(e-1) | e argument and with a Lean proof. The upstream formal_conjectures docstring of OeisA51903.conjecture1 also gives the same divisibility argument, with φ in place of λ. - OEIS A051903, comments by T. Ordowski (Dec 02 2019) stating problems (*), (**) and (***). Comment "Answer to (**): No. Answer to (***): Yes. See Mishra and Senthilkumar (2026)" by Ansh Mishra (Sep 30 2026), approved as revision #152 on Oct 11 2026. https://oeis.org/A051903 and https://oeis.org/history?seq=A051903 + +(Abridged.) + +## Citation + +```bibtex +@misc{math0:oeisa51903-conjecture2, + author = {{math0}}, + title = {{No odd n with a(n) > 1 has b^n ≡ b^{a(n)} (mod n) for all b (OEIS A051903)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeisa51903-conjecture2}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/results/oeisa51903-conjecture3/README.md b/results/oeisa51903-conjecture3/README.md new file mode 100644 index 0000000..23c4588 --- /dev/null +++ b/results/oeisa51903-conjecture3/README.md @@ -0,0 +1,38 @@ +# An odd n with a(n) > 1 and 2^n ≡ 2^{a(n)} (mod n), where a(n) is the largest prime exponent of n (OEIS A051903, Ordowski) + +**Classification:** Independent formal proof (an implying Lean proof already exists elsewhere) +**Area:** Number theory +**Source problem:** OEIS 51903 +**Date:** 2026-10-17 + +## Result + +Let a(n) be the largest exponent in the prime factorization of n (OEIS A051903). Ordowski (Dec 2019) asked whether some odd n has a(n) > 1 and 2^n ≡ 2^{a(n)} (mod n). The answer is yes. The formal statement is ∃ n : ℕ, Odd n ∧ 1 < a n ∧ 2 ^ n ≡ 2 ^ (a n) [MOD n], with a n defined as the foldr max of the multiplicities over n.primeFactorsList. The witness is n = 9687963167864344937 = 7 · 631 · 881 · 3511² · 201961. + +## Verification + +The Lean file [`lean/Math0/OEIS/OeisA51903_conjecture3.lean`](../../lean/Math0/OEIS/OeisA51903_conjecture3.lean) proves the upstream statement [`OeisA51903.conjecture3`](https://github.com/google-deepmind/formal-conjectures/blob/c77fdd446d23539302aa73bcfae4a9fa962b8382/FormalConjectures/OEIS/51903.lean) (formal-conjectures at commit `c77fdd4`, upstream category `research open`). Its final command `#math0_proves` checks that our theorem's type is syntactically identical to the upstream statement and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`. + +## Notes + +- OEIS A051903, https://oeis.org/A051903: + - Thomas Ordowski's comment of Dec 02 2019 poses questions (*), (**) and (***). + - Ansh Mishra's comment of Sep 30 2026 reads "Answer to (**): No. Answer to (***): Yes. See Mishra and Senthilkumar (2026)." +- A. Mishra and A. Senthilkumar, "On Two Questions of Ordowski about the Largest Exponent in a Prime Factorization", Zenodo preprint, 2026-09-30, doi:10.5281/zenodo.23064142, https://zenodo.org/records/23064142. + - It gives the same witness n0 = 9687963167864344937 = 7·631·881·3511²·201961, proves that n0 is minimal, and includes Lean 4 proofs of OeisA51903.conjecture2 (negative) and conjecture3 (positive) against the unmodified formal-conjectures file. The relevant files are lean/DMSolutions/OEIS_A051903/{Core,Solution,CheckAnswer}.lean and logs/lean_check.log. +- F. G. Dorais and D. Klyve, "A Wieferich prime search up to 6.7×10^15", J. Integer Seq. 14 (2011). The minimality argument relies on this search. +- T. Adamczewski, tadamcz/fc-review-results (entry OEIS/51903). The Zenodo README cites it as prior work: an earlier negative answer to (**), with (***) still regarded as open as of 2026-09-23. + +(Abridged.) + +## Citation + +```bibtex +@misc{math0:oeisa51903-conjecture3, + author = {{math0}}, + title = {{An odd n with a(n) > 1 and 2^n ≡ 2^{a(n)} (mod n), where a(n) is the largest prime exponent of n (OEIS A051903, Ordowski)}}, + howpublished = {\url{https://github.com/Foundation-0/math0/tree/main/results/oeisa51903-conjecture3}}, + note = {Produced by Claude (Anthropic); Lean-verified}, + year = {2026} +} +``` diff --git a/review/fidelity/README.md b/review/fidelity/README.md new file mode 100644 index 0000000..93894bb --- /dev/null +++ b/review/fidelity/README.md @@ -0,0 +1,37 @@ +# Fidelity review packets + +math0 formalizes the OEIS conjectures of its frontier track itself, so whether each Lean statement says what the OEIS author meant is a judgement, not a machine check. Each statement was reviewed by an agent before it was frozen. These packets come from a second, adversarial pass (29 Oct 2026) over all 110 statements, written so that people can check them in batches of ten. They are not a human review. The Lean excerpts were copied by the agent and may abridge long definitions; the linked frozen file is authoritative, and its hash is listed in [`FROZEN.sha256`](../../lean/Math0/Statements/FROZEN.sha256). + +**Outcome of the pass:** 72 faithful, 38 faithful with notes, 0 questionable, 0 unfaithful; 0 major and 15 minor points. + +## Minor points, to look at first + +- [A090905](packet-02.md) (minor): The Lean triangle requires each row to be at least as long as the previous row (k ≥ len n). This bound comes from De Vlieger's 2016 Mathematica program. Murthy's name of the sequence ("every row product is a multiple of the previous") does not state it; the unbounded variant is A381901. The bound turns out not to matter. Rows 1..28 are identical with or without it. Moreover, once the proved statement holds, the largest prime B_n of row n forces the next row to have length at least 2B_n - 2B_{n-1}, and that is ≥ len(n) = 2B_{n-1} - 2B_{n-2}. I checked this inequality for all Bertrand primes up to index 38, and it follows from Nagura beyond that. So the bound is never binding, and the two triangles coincide for every n. +- [A093726](packet-02.md) (minor): The truth value depends on which reading of a(n) is used. The name says 'numerator of the imaginary part of the convergents'. Lean uses Im(Numerator(c_n)) = lcm(den Re, den Im)·Im(c_n), as in the program Im[Numerator[...]]. I checked numerically that the two readings first differ at n = 42 (then at 84 and 126). Under the literal-name reading the conjectured identity is false at n = 42: reduced num Im(c_42) = 18854485653829, while d·Im(c_42) = 245108313499777, with d = A093727(42) = 329919304636610. The Lean reading is the defensible one. It is the reading of the program, of He's own examples written as (A093725(n)+a(n)*i)/A093727(n), and of the only sense in which a(n)/A093727(n) is a natural quantity (Im c_n). A reviewer should still know that the alternative reading would give a counterexample rather than a proof. +- [A175385](packet-04.md) (minor): The data check pins only the numerators of S(n), not the denominators (A175386), and the conjecture is a statement about the denominator being 1. This does not affect fidelity, because S is a literal, non-truncating transcription of the sum, and I confirmed the denominators match A175386 for n = 1..25. +- [A188474](packet-05.md) (minor): The index is deliberately shifted from the literal "A137398(n+1)" to A137398(n+2). The reason is that A137398's offset was corrected in 2021: the old offset was 0, and the current one is 1. The listed numbers fix the shift unambiguously, since the row sums 1,2,7,22,74 are A137398's terms from the second on. The literal reading in today's offset is false at n = 0 (1 ≠ 0). This is the intended reading, but the Lean text departs from the verbatim OEIS text, so a reviewer should confirm it. +- [A215010](packet-05.md) (minor): 'Simple convex polygon with equal interior angles' is encoded through the edge-vector characterization: positive sides, sum of s_k * zeta^k = 0, zeta = exp(2*pi*i/N), N >= 3. It is not encoded as a geometric definition. The refutation needs only the direction 'predicate implies a genuine polygon', and that direction holds: positive sides whose direction turns by 2*pi/N at each vertex, with total turning 2*pi, form a strictly convex simple polygon with every interior angle (N-2)*pi/N. The data check validates the predicate only at N = 6. I numerically confirmed the decagon witness (1,4,5,8,9,2,3,6,7,10) used by the result: |sum| ~ 5e-15. +- [A281000](packet-06.md) (minor): Conjecture (2) is not well defined as written: A103365 has offset 1, so the k = 0 term uses A103365(0). With only the shift A103365(k) -> A103365(k+1) it is false at n = 1 (sum 3 + 3 = 6; I recomputed this). The file instead reads (-1)^k·A103365(k) as A103365(k+1), which equals (-1)^k·|A103365(k+1)|. This is an editorial correction, not the literal text. It does not change the strength of the statement: in this reading (2) is the k = 0 column of T·T^{-1} = I, so it follows from conj3. The other plausible true readings, such as Σ T(n,k)(2k+1)Cat(k)·b(n+1-k) = 0^n (row 0 of U·T), also follow from conj3. The conjunction is therefore equivalent to (1) ∧ (3), which are transcribed faithfully. +- [A308121](packet-07.md) (minor): Reading choice on the range: the OEIS text says 'If n is odd', which includes n = 1, but the Lean statement requires 1 < n. At n = 1 the literal claim fails under any reading: row 1 = [0] has odd length and no halves, and row 2 = [1] is not a rearrangement of [0]. For odd n ≥ 3, φ(n) is even, so the halves are well defined. The file documents this exclusion, and it is the only reading under which the conjecture is meaningful. Still, the result settles the conjecture for odd n > 1 and not the literal 'all odd n' wording, which is (trivially) false at n = 1. A reviewer should accept this reading explicitly. +- [A357216](packet-10.md) (minor): The kernel data check validates the computable T, not the geometric `regions` and `HasNonSimpleIntersection` that `statement` actually uses, and T = regions is not proved. A mistake in the topological encoding would not be caught by a_data. By reading, the encoding is literal and sound: open convex hull minus closed segments, Nat.card of the connected components, and k = 0 gives 1. Distinct chord indices give distinct, non-collinear segments, because a line meets the convex boundary in only 2 points. Also, the proved equality regions n k = n k^2 + 1 rules out a degenerate definition for n = 5 and n ≥ 7. +- [A362086](packet-10.md) (minor): 'Except for 9' is encoded as exempting every n with a n = 9. On a strict reading, the author is excepting the single term a(5) = 9. The Lean statement is therefore formally weaker by the claim 'the value 9 occurs only once', since a second 9 would refute the strict reading but not the Lean statement. The gap does not matter in practice. Exact computation shows 9 occurs only at n = 5 for 3 ≤ n < 1200. Using the closed form a(n) = N/gcd(N, 3(n-1)(n-3)!) with N = n^2+n-3 (which I checked against exact evaluation for n < 400), 9 | a(n) needs v_3(N) ≥ 3 + v_3((n-3)!), which is impossible for n ≥ 15 or so. The index reading (n = 9) is untenable, because a(5) = 9 is not prime. +- [A363482](packet-10.md) (minor): 'Except for 49' is encoded as exempting every n with a n = 49. On a strict reading, the author is excepting the single term a(6) = 49, so the Lean statement is weaker by 'the value 49 occurs only once'. The gap does not matter in practice. Exact computation shows 49 occurs only at n = 6 for 3 ≤ n < 1200. Using the closed form a(n) = N/gcd(N, 5(n-1)(n-3)!) with N = n^2+3n-5 (which I checked for n < 400), 49 | a(n) needs v_7(N) ≥ 2 + v_7(5(n-1)(n-3)!), which fails for all n beyond about 50 because of size. The catalog summary itself states that 49 occurs only at n = 6. +- [A363609](packet-10.md) (minor): Faces that face an enclosed cavity count as visible. The file justifies this by the listed a(26) = 93: under the other reading, the 3×3×3 cube minus its centre would give ≤ 90. But Donahoe's dice.py only searches box-plus-slab layouts and never builds a cavity, so the data are weak evidence either way. The Lean reading matches the author's convention that every exposed face counts, bottom faces included (a(1) = 21), so it is the natural one. Under the other reading, the Lean result gives only a(k^3) ≤ 6k(k+2), not equality. The projection-type lower bound plausibly also holds there, but that is not part of this statement. +- [A367119](packet-10.md) (minor): The kernel data check is on the computable surrogate `a`, which is not linked to `edges`. So the geometric statement's definitions (vertices, adjacency, placement, general position) are validated only by inspection and by my numerical check, not by a kernel-checked term. On inspection they are correct: chords cannot overlap; side pieces overlapping on a common side are excluded from the vertices by the `s ∩ t = {z}` clause; consecutive boundary points give the 3n+3 side edges; and n = 0 gives 3. +- [A386538](packet-11.md) (minor): Several listed terms from a(13) on are smaller than the true maximum area. The author's Maple/Mathematica program, 4n + 4*Sum floor(sqrt(n^2-x^2)) - 2*#distinct y, is not the convex-hull area for n >= 13; for example it gives 512 at n = 13, where the 20-gon on the circle has area 516. The Lean follows the entry's name (the maximum), not the program. This does not affect the result: the counterexample is at n = 7, where the listed a(7) = 138 equals the true maximum. I recomputed exactly that the center-0 hull has area 138 and that the hull for center (5/12, 5/24) has area 281/2. +- [A394981](packet-11.md) (minor): The literal conjecture ('if n is odd') includes n = 1, but the entry's corrected data give a(2) = 1 ≠ 4 = 4·a(1). The statement restricts to odd n ≥ 3, and literal_fails_at_one kernel-checks the failure at n = 1. This is a deliberate weakening of the literal text, needed because the literal text is false at its first instance. It is the evident intent: the pattern holds for every listed pair n = 3, ..., 19. A reviewer should accept that n = 1 is a degenerate exception (1-row rectangles, after the May 2026 data correction) and not part of what the author meant. +- [A395454](packet-11.md) (minor): Index shift: the statement does not take 'row n' in the entry's offset-0 numbering. Read that way the recurrence is false at n = 2, since the RHS is 0 (P_1 = 0) while P_2 = 2t, and it fails at every n tested. The frozen statement uses P(n) := row n-1, i.e. rows counted from 1. Of the readings I checked, this is the only nearby one that makes the formula true; reversing the row polynomials or dividing by t both fail at once. It almost certainly reflects the author's 1-based row indexing. Still, it is an interpretive reindexing, not the literal text, and a human reviewer should approve it. The proof settles the shifted claim, which is the only meaningful version. + +## Packets + +- [Packet 01](packet-01.md): A001040, A005590, A022445, A057566, A057566b, A060693, A062887, A071685, A073642, A075855 +- [Packet 02](packet-02.md): A081200, A083020, A086004, A090905, A091817, A092054, A093726, A097154, A106505, A113676 +- [Packet 03](packet-03.md): A115026, A116184, A119936, A120069, A121750, A123710, A124526, A126127, A127752, A127755 +- [Packet 04](packet-04.md): A127767, A129455, A132616, A141412, A144637, A160848, A172164, A175385, A176206, A178295 +- [Packet 05](packet-05.md): A182617, A188474, A195249, A201060, A209802, A211343, A215010, A223395, A229159, A242396 +- [Packet 06](packet-06.md): A249434, A262957, A265210, A265649, A267486, A270668, A275815, A278212, A281000, A294512 +- [Packet 07](packet-07.md): A300789, A308107, A308121, A308222, A308359, A320099, A323695, A326407, A326602, A328202 +- [Packet 08](packet-08.md): A332010, A333650, A334592, A334595, A334603, A335012, A338885, A341761, A342645, A342992 +- [Packet 09](packet-09.md): A344710, A348484, A350499, A350557, A350900, A351743, A354571, A355076, A355339, A355360 +- [Packet 10](packet-10.md): A356360, A357216, A357583, A362086, A363482, A363609, A367119, A368846, A369366, A373345 +- [Packet 11](packet-11.md): A373359, A375522, A386538, A386655, A388724, A392943, A393794, A394981, A395454, A397315 diff --git a/review/fidelity/packet-01.md b/review/fidelity/packet-01.md new file mode 100644 index 0000000..fd930e0 --- /dev/null +++ b/review/fidelity/packet-01.md @@ -0,0 +1,395 @@ +# Fidelity review packet 01 of 11 + +Prepared on 29 Oct 2026 by an adversarial reviewing agent, not by a person. It is meant to make a human review of these statements quick: for each one it quotes the OEIS conjecture and the frozen Lean statement, restates the Lean in plain words, and lists anything a reviewer should look at. See [the index](README.md). + +Statements in this packet: A001040, A005590, A022445, A057566, A057566b, A060693, A062887, A071685, A073642, A075855. + +## A001040: Kurkov's rook-tour conjecture for A001040: 2·n!·a(n) counts opposite-line Hamiltonian paths of K_n □ K_2 + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a001040](../../results/oeis-a001040/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A001040.lean`](../../lean/Math0/Statements/OEIS/A001040.lean). + +**The conjecture as stated in OEIS** + +> %C A001040 Conjecture: 2*n!*a(n) is the number of open tours by a rook on an (n X 2) chessboard which ends at the opposite line of length n. - _Mikhail Kurkov_, Nov 19 2019 +> (Sequence: %N a(n+1) = n*a(n) + a(n-1) with a(0)=0, a(1)=1; %O 0,4. Rev #140, Oct 15 2026, identical in the local mirror and in current GitHub oeisdata.) + +**The frozen Lean statement** + +```lean +def a : ℕ → ℕ + | 0 => 0 + | 1 => 1 + | n + 2 => (n + 1) * a (n + 1) + a n + +def RookMove {n : ℕ} (p q : Fin n × Fin 2) : Prop := + p ≠ q ∧ (p.1 = q.1 ∨ p.2 = q.2) + +def IsOpenTour (n : ℕ) (l : List (Fin n × Fin 2)) : Prop := + l.Nodup ∧ (∀ s, s ∈ l) ∧ l.IsChain RookMove + +def EndsOnOppositeLine {n : ℕ} (l : List (Fin n × Fin 2)) : Prop := + ∃ s ∈ l.head?, ∃ t ∈ l.getLast?, s.2 ≠ t.2 + +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + {l : List (Fin n × Fin 2) | IsOpenTour n l ∧ EndsOnOppositeLine l}.ncard = 2 * n ! * a n +``` + +**What the Lean statement says** + +Let a(0)=0, a(1)=1, a(m+1)=m·a(m)+a(m−1). Take the board with squares (i,c), i in {0..n−1}, c in {0,1}. Two distinct squares are adjacent when they share i or share c (the graph K_n □ K_2; a move can be any distance along a line). Count the sequences that list every square exactly once with consecutive squares adjacent (directed Hamiltonian paths, so a path and its reversal both count) and whose first and last squares have different c. For every n ≥ 1 this count is 2·n!·a(n). + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 24 listed terms a(0..23) against the recursion, which pins down a. tours_card_small kernel-checks the tour counts 2, 4, 36, 480 for n = 1..4 through the Finset `tours n`, proved equal to the set in the statement by ncard_eq_card_tours. These match 2·n!·a(n). These counts also pin down the model. I recomputed under alternative readings: a rook that cannot pass over visited squares gives 2, 4, 16, 72, and one-step moves give 2, 4, 8, 12, so both are ruled out at n = 3. Reading tours as undirected would give 1 at n = 1. Taking 'open' to mean 'the ends are not a rook move apart' would give 0 at n = 1. The reading also agrees with A096121, the total count that Kurkov's conjecture refines: its comment says the rook 'may intersect its own path', and its data 2, 8, 60, 816, 17520, 550080 equal 2·n!·(A001040(n)+A001053(n)), the opposite-line count plus Kurkov's same-line count. + +**Points for the reviewer** + +- *Note.* The statement makes three reading choices: directed tours, 'open' meaning a Hamiltonian path rather than a cycle, and a rook allowed to pass over squares. The OEIS text does not spell these out, but the n = 1, 3, 4 counts force them, and they match A096121's definition and data. Kurkov's companion conjecture in A001053 counts tours that 'start and end at the same line', which would be identically 0 under the 'ends not rook-adjacent' reading of 'open'. That supports the path reading. +- *Note.* At n = 2 the board is 2×2, so 'lines of length n' and the short rows both have length 2, and the Lean picks the c-lines. By transpose symmetry the count is the same either way. +- *Note.* The range is n ≥ 1. n = 0 is trivial (tours_zero gives 0, and 2·0!·a(0) = 0), so nothing is lost. Set.ncard returns a junk value 0 on infinite sets, but ncard_eq_card_tours identifies the set with a finite Finset, so no junk value arises. + +## A005590: Zeros of a(3n) for the signed Stern sequence A005590 are exactly the fibbinary numbers + +Verdict of the pre-review: **faithful**. Result: [oeis-a005590](../../results/oeis-a005590/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A005590.lean`](../../lean/Math0/Statements/OEIS/A005590.lean). + +**The conjecture as stated in OEIS** + +> %F A005590 Conjecture: a(3n)=0 iff n in A003714. - _Ralf Stephan_, May 02 2003 +> (Sequence: %N a(0) = 0, a(1) = 1, a(2n) = a(n), a(2n+1) = a(n+1) - a(n); %O 0,10. A003714: fibbinary numbers, '... Also numbers whose binary representation contains no two adjacent 1's', %O 0,3, first term 0. Rev #97, Nov 05 2025, unchanged on GitHub.) + +**The frozen Lean statement** + +```lean +def aux : ℕ → ℕ → ℤ + | 0, _ => 0 + | fuel + 1, n => + if n ≤ 1 then (n : ℤ) + else if n % 2 = 0 then aux fuel (n / 2) + else aux fuel (n / 2 + 1) - aux fuel (n / 2) + +def a (n : ℕ) : ℤ := aux (n + 1) n + +def IsFibbinary (n : ℕ) : Prop := + ∀ i : ℕ, ¬ (n.testBit i = true ∧ n.testBit (i + 1) = true) + +def statement : Prop := + ∀ n : ℕ, a (3 * n) = 0 ↔ IsFibbinary n +``` + +**What the Lean statement says** + +Let a : ℕ → ℤ satisfy a(0)=0, a(1)=1, a(2n)=a(n), a(2n+1)=a(n+1)−a(n). For every n ≥ 0, a(3n) = 0 if and only if no two adjacent binary digits of n are both 1. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 105 listed terms a(0..104). The theorems a_zero, a_one, a_even and a_odd prove that the fuelled definition satisfies the OEIS defining equations for every n. Those equations determine the sequence, so the fuel cannot cut the recursion off. fibbinary_data kernel-checks that IsFibbinary selects exactly the 61 listed terms of A003714 up to 264. Both definitions are therefore pinned down, not just matched on samples. + +**Points for the reviewer** + +- *Note.* n = 0 is included: a(0) = 0, and 0 is the first term of A003714 (offset 0). This matches the literal claim. +- *Note.* A003714 is encoded through its 'no two adjacent 1's in binary' description rather than the Zeckendorf-image description. The entry itself gives both and they define the same set; the 61-term check agrees. + +## A022445: The generating function of A022445 (closed self-avoiding walks in the strip {0,1,2} x Z) + +Verdict of the pre-review: **faithful**. Result: [oeis-a022445](../../results/oeis-a022445/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A022445.lean`](../../lean/Math0/Statements/OEIS/A022445.lean). + +**The conjecture as stated in OEIS** + +> %F A022445 G.f.: (-6*x^7+10*x^6-18*x^5+27*x^4-14*x^3+10*x^2-4*x+1) / ((1+x^2)^2*(1-2*x)^2) (conjectured). - _Ralf Stephan_, Apr 28 2004 +> (Sequence: %N Number of self-avoiding closed walks (from 0 to 0) of length 2n in the strip {0, 1, 2} X Z of the square lattice Z X Z; %O 0,3; data 1,0,4,10,34,94,222,... (29 terms). Rev #10, May 16 2019, unchanged on GitHub.) + +**The frozen Lean statement** + +```lean +def step : Fin 4 → ℤ × ℤ := ![(1, 0), (-1, 0), (0, 1), (0, -1)] +def vertex {m : ℕ} (t : Fin m → Fin 4) (i : ℕ) : ℤ × ℤ := + ∑ j : Fin m, if (j : ℕ) < i then step (t j) else 0 +def InStrip (v : ℤ × ℤ) : Prop := 0 ≤ v.1 ∧ v.1 ≤ 2 +def IsClosedSAW {m : ℕ} (t : Fin m → Fin 4) : Prop := + (∀ i < m + 1, InStrip (vertex t i)) ∧ vertex t m = 0 ∧ + (∀ j < m, ∀ i < j, vertex t i ≠ vertex t j) ∧ + (∀ j < m, ∀ i < j, s(vertex t i, vertex t (i + 1)) ≠ s(vertex t j, vertex t (j + 1))) +def a (n : ℕ) : ℕ := Fintype.card {t : Fin (2 * n) → Fin 4 // IsClosedSAW t} + +open PowerSeries in +def statement : Prop := + PowerSeries.mk (fun n => (a n : ℤ)) * ((1 + X ^ 2) ^ 2 * (1 - 2 * X) ^ 2) = + -6 * X ^ 7 + 10 * X ^ 6 - 18 * X ^ 5 + 27 * X ^ 4 - 14 * X ^ 3 + 10 * X ^ 2 - 4 * X + 1 +``` + +**What the Lean statement says** + +Let a(n) be the number of step sequences of length 2n on the square lattice with these properties. The walk starts at (0,0), every vertex has first coordinate in {0,1,2}, and the walk returns to (0,0). Vertices 0..2n−1 are pairwise distinct, and no edge is used twice. The empty walk counts, and each polygon through the origin counts once per direction. Then (Σ a(n) xⁿ)·(1+x²)²(1−2x)² = 1 − 4x + 10x² − 14x³ + 27x⁴ − 18x⁵ + 10x⁶ − 6x⁷ in ℤ[[x]]. Since the denominator has constant term 1, this says Σ a(n) xⁿ equals the stated rational function. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks a(0..9) = 1, 0, 4, 10, 34, 94, 222, 516, 1202, 2738 through a DFS evaluator proved equal to `a` for all n (a_eq_aFast). These terms pin the model. a(0) = 1 requires counting the empty walk. a(1) = 0 requires excluding the back-and-forth walks of length 2. a(2) = 4 requires the origin on the boundary column (a middle-column origin gives 8, which is A022444) and counting walks with direction. listed_satisfy_gf checks that all 29 listed terms satisfy the transcribed numerator and denominator, which tests the transcription only. Together with the proved result, it implies that the definition reproduces all 29 listed terms. + +**Points for the reviewer** + +- *Note.* The generating-function identity is stated with the denominator cleared. The denominator is a unit in ℤ⟦X⟧ (constant term 1), so this is equivalent to the quotient form in the OEIS. The numerator and denominator are transcribed exactly. +- *Note.* The edge-distinctness clause only matters for length 2, where it excludes 0→v→0. That exclusion is forced by the listed a(1) = 0. + +## A057566: Layman's floor formula for collinear triples in a 3 × n grid (A057566), as printed until its October 2026 correction, fails at n = 24 + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a057566](../../results/oeis-a057566/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A057566.lean`](../../lean/Math0/Statements/OEIS/A057566.lean). + +**The conjecture as stated in OEIS** + +> %F A057566 Conjecture: a(n) = 5*floor((2n^3 - 3n^2 - n)/24) + floor((2(n-1)^3 - 3(n-1)^2 - (n-1))/24) + n, which fits all of the listed terms. +> (Text as of rev #27, Feb 22 2024, in the local mirror. The line is unsigned; the entry is by _John W. Layman_, Oct 04 2000. %N Number of collinear triples in a 3 X n rectangular grid; %O 0,3. OEIS replaced this line with a corrected formula on Oct 21 2026, rev #30.) + +**The frozen Lean statement** + +```lean +def grid (n : ℕ) : Finset (ℕ × ℕ) := Finset.range 3 ×ˢ Finset.range n +def cross (p q r : ℕ × ℕ) : ℤ := + ((q.1 : ℤ) - p.1) * ((r.2 : ℤ) - p.2) - ((q.2 : ℤ) - p.2) * ((r.1 : ℤ) - p.1) +def IsCollinear (s : Finset (ℕ × ℕ)) : Prop := ∀ p ∈ s, ∀ q ∈ s, ∀ r ∈ s, cross p q r = 0 +def a (n : ℕ) : ℕ := ((grid n).powersetCard 3 |>.filter IsCollinear).card + +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → (a n : ℤ) = + 5 * ⌊(2 * (n : ℚ) ^ 3 - 3 * (n : ℚ) ^ 2 - (n : ℚ)) / 24⌋ + + ⌊(2 * ((n : ℚ) - 1) ^ 3 - 3 * ((n : ℚ) - 1) ^ 2 - ((n : ℚ) - 1)) / 24⌋ + n +(The result proved is ¬ statement.) +``` + +**What the Lean statement says** + +Let a(n) be the number of 3-element subsets of {0,1,2}×{0,…,n−1} whose points lie on a common line. Claim: for every n ≥ 3, a(n) = 5⌊(2n³−3n²−n)/24⌋ + ⌊(2(n−1)³−3(n−1)²−(n−1))/24⌋ + n. The project proves this claim false. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks a(0..24) = 0, 1, 2, 8, …, 5578, 6360 through fastA, which is proved equal to `a` for all n. This pins down 'collinear triple' as an unordered 3-subset; ordered triples would give 6 times as many. It also fixes the decisive term a(24) = 6360, where the formula gives 6365. I recomputed both values independently: 3·C(24,3)+24+2⌊23²/4⌋ = 6360, and the formula gives 5·1079+946+24 = 6365. The formula fails at every n from 24 to at least 199. + +**Points for the reviewer** + +- *Note.* The statement restricts n to n ≥ 3, while the OEIS line gives no range and the offset is 0. Because the result refutes the statement, this restriction makes the result stronger. The counterexample n = 24 lies in every reasonable range, and both floor arguments are positive there, so floor, truncation and integer division agree. The restriction only avoids a spurious refutation at n = 0, 1, where the literal true-floor reading gives −1 and −4. Read with truncation, the formula matches a(0..23). +- *Note.* What is refuted is the formula as printed before OEIS's Oct 21 2026 correction. The printed polynomial differs from the corrected one by n−3 in the numerator, which is not a typo-level slip. The printed formula fits exactly a(0..23) (read with truncation) and fails from n = 24 on, which is consistent with Layman fitting the terms listed in 2000. So the refutation settles what the author wrote. The catalogue title and summary say plainly that this is the superseded text, and the corrected formula is handled separately as A057566b. +- *Note.* The OEIS %F line is unsigned. Attributing it to Layman, the author of the entry, as of Oct 04 2000 is an inference. + +## A057566b: The corrected floor formula for collinear triples in a 3 x n grid (OEIS A057566) holds for all n + +Verdict of the pre-review: **faithful**. Result: [oeis-a057566b](../../results/oeis-a057566b/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A057566b.lean`](../../lean/Math0/Statements/OEIS/A057566b.lean). + +**The conjecture as stated in OEIS** + +> %F A057566 Conjecture: a(n) = 5*floor((2n^3 - 3n^2 - 2n + 3)/24) + floor((2(n-1)^3 - 3(n-1)^2 - 2(n-1) + 3)/24) + n, which fits all of the listed terms. [Corrected by _Alper Ferudun_, Oct 21 2026] +> (Rev #30, Oct 22 2026. The scratchpad live copy is identical to current GitHub oeisdata. %N Number of collinear triples in a 3 X n rectangular grid; %O 0,3; original conjecture by _John W. Layman_, Oct 04 2000.) + +**The frozen Lean statement** + +```lean +def grid (n : ℕ) : Finset (ℕ × ℕ) := Finset.range 3 ×ˢ Finset.range n +def cross (p q r : ℕ × ℕ) : ℤ := + ((q.1 : ℤ) - p.1) * ((r.2 : ℤ) - p.2) - ((q.2 : ℤ) - p.2) * ((r.1 : ℤ) - p.1) +def IsCollinear (s : Finset (ℕ × ℕ)) : Prop := ∀ p ∈ s, ∀ q ∈ s, ∀ r ∈ s, cross p q r = 0 +def a (n : ℕ) : ℕ := ((grid n).powersetCard 3 |>.filter IsCollinear).card + +def statement : Prop := + ∀ n : ℕ, (a n : ℤ) = + 5 * ⌊(2 * (n : ℚ) ^ 3 - 3 * (n : ℚ) ^ 2 - 2 * (n : ℚ) + 3) / 24⌋ + + ⌊(2 * ((n : ℚ) - 1) ^ 3 - 3 * ((n : ℚ) - 1) ^ 2 - 2 * ((n : ℚ) - 1) + 3) / 24⌋ + n +``` + +**What the Lean statement says** + +Let a(n) be the number of 3-element collinear subsets of {0,1,2}×{0,…,n−1}. For every n ≥ 0, with true floors and n−1 = −1 when n = 0: a(n) = 5⌊(2n³−3n²−2n+3)/24⌋ + ⌊(2(n−1)³−3(n−1)²−2(n−1)+3)/24⌋ + n. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks a(0..24), the same evaluator and data as A057566, which pins down unordered collinear 3-subsets. numer_nonneg proves that 2m³−3m²−2m+3 = (m−1)(m+1)(2m−3) ≥ 0 for all integers m ≥ −1, so the claim does not depend on the floor convention. I checked independently that the formula equals 3·C(n,3)+n+2⌊(n−1)²/4⌋ for n = 0..4999, including n = 0, 1, 2 (0, 1, 2). + +**Points for the reviewer** + +- *Note.* The range is all n ≥ 0, the full offset range, with true floors. Since every floor argument is nonnegative, truncation and integer division give the same claim, and statement_iff_ediv records the integer-division form. This is the strongest literal reading. +- *Note.* The grid is 3 rows × n columns. Transposing does not change the number of collinear triples, so the orientation is immaterial. + +## A060693: Schulte's alternating quadratic sum over the Schröder-peaks triangle (A060693) + +Verdict of the pre-review: **faithful**. Result: [oeis-a060693](../../results/oeis-a060693/README.md) (known-result-already-formalized). Frozen statement: [`lean/Math0/Statements/OEIS/A060693.lean`](../../lean/Math0/Statements/OEIS/A060693.lean). + +**The conjecture as stated in OEIS** + +> %F A060693: "Conjecture: Sum_{k=0..n} (-1)^k*T(n,k)*(n+1-k)^2 = 1+n+n^2. - _Werner Schulte_, Jan 11 2017". Entry definition (%N, offset 0, keyword tabl): "Triangle (0 <= k <= n) read by rows: T(n, k) is the number of Schröder paths from (0,0) to (2n,0) having k peaks." Deutsch's comment: "Schroeder paths (i.e., consisting of steps U=(1,1), D=(1,-1), H=(2,0) and never going below the x-axis) from (0,0) to (2n,0), having k peaks. Example: T(2,1)=3 because we have UU*DD, U*DH and HU*D, the peaks being shown by *." (Local mirror %I #147, Oct 04 2026.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, ∑ k ∈ Finset.range (n + 1), (-1 : ℤ) ^ k * (T n k : ℤ) * ((n : ℤ) + 1 - k) ^ 2 = + 1 + (n : ℤ) + (n : ℤ) ^ 2 + +-- dependencies +inductive Step | U | D | H +def Step.dx : Step → ℕ | U => 1 | D => 1 | H => 2 +def Step.dy : Step → ℤ | U => 1 | D => -1 | H => 0 +def width (p : List Step) : ℕ := (p.map Step.dx).sum +def height (p : List Step) : ℤ := (p.map Step.dy).sum +def IsSchroderPath (n : ℕ) (p : List Step) : Prop := + width p = 2 * n ∧ height p = 0 ∧ ∀ q ∈ p.inits, 0 ≤ height q +def peaks (p : List Step) : ℕ := (p.zip p.tail).count (U, D) +def words : ℕ → List (List Step) + | 0 => [[]] | 1 => [[U], [D]] + | m + 2 => (words (m + 1)).map (U :: ·) ++ (words (m + 1)).map (D :: ·) ++ (words m).map (H :: ·) +def schroderPaths (n : ℕ) : Finset (List Step) := (words (2 * n)).toFinset.filter (IsSchroderPath n) +def T (n k : ℕ) : ℕ := ((schroderPaths n).filter (fun p => peaks p = k)).card +``` + +**What the Lean statement says** + +For every integer n ≥ 0, let T(n,k) be the number of lattice paths from (0,0) to (2n,0) with steps (1,1), (1,-1), (2,0) that never go below the x-axis and contain exactly k occurrences of an up-step immediately followed by a down-step. Then the integer sum over k = 0..n of (-1)^k · T(n,k) · (n+1-k)^2 equals 1 + n + n^2. + +**What the kernel checks against the OEIS data** + +T_data kernel-checks rows n = 0..9 of the triangle plus T(10,0) = 16796 (all 56 listed terms); a_data checks the same 56 terms as the flattened sequence a 0..a 55. Both go through a dynamic program, but T_eq_Tfast proves Tfast = T for all n, k, so the values are values of the stated definition. T_eq_ncard restates T as the cardinality of {p | IsSchroderPath n p ∧ peaks p = k}. statement_check confirms the identity for n ≤ 12 (sanity check only). T is defined directly by the entry's combinatorial definition, not reverse-engineered from the data. The data also pin down the conventions: what counts as a peak (only UD, not UH or HD), the H step having width 2, and the non-negativity condition. + +**Points for the reviewer** + +- *Note.* The arithmetic is in ℤ, so n+1-k is not truncated. For k ≤ n it is positive anyway. The sum range k = 0..n and the range n ≥ 0 (including the trivial n = 0 case) match the conjecture exactly. +- *Note.* Non-negativity is checked only at the vertices (prefixes) of the path. This is correct because the path is straight between vertices: an H step stays at the same height, and U/D steps change the height by one. + +## A062887: Odd descending-by-2 multiples exist exactly when 125 does not divide 2n+1 (A062887) + +Verdict of the pre-review: **faithful**. Result: [oeis-a062887](../../results/oeis-a062887/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A062887.lean`](../../lean/Math0/Statements/OEIS/A062887.lean). + +**The conjecture as stated in OEIS** + +> %C A062887: "Conjecture: The only numbers n for which a(n)=0 are those for which 2*n+1 is divisible by 125. - _Sean A. Irvine_, Apr 14 2023". Entry definition (%N, offset 0, Amarnath Murthy, Jun 28 2001): "Smallest multiple of 2n+1 with the property that its digits are odd and each digit is two less (mod 10) than the previous digit, or 0 if no such number exists." (Local mirror #12, Apr 14 2023.) + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n : ℕ, a n = 0 ↔ 125 ∣ 2 * n + 1 + +-- dependencies +def IsDesc2 (N : ℕ) : Prop := + 0 < N ∧ (∀ d ∈ Nat.digits 10 N, Odd d) ∧ + (Nat.digits 10 N).reverse.IsChain (fun prev next => next + 2 ≡ prev [MOD 10]) + +open Classical in +noncomputable def a (n : ℕ) : ℕ := + if h : ∃ N, IsDesc2 N ∧ 2 * n + 1 ∣ N then Nat.find h else 0 +``` + +**What the Lean statement says** + +Call a positive integer N admissible if all of its decimal digits are odd and, reading left to right, each digit is 2 less (mod 10) than the one before it. Let a(n) be the least admissible multiple of 2n+1, or 0 if there is none. Then for every n ≥ 0, a(n) = 0 if and only if 125 divides 2n+1. Because admissible numbers are positive, this is the same as: 2n+1 has no admissible multiple if and only if 125 | 2n+1. + +**What the kernel checks against the OEIS data** + +a_data proves a(0..25) equal all 26 listed terms, up to 753197531975319753, for the noncomputable a. It uses a bounded search aSearch with B = 18 digits. The lemma a_eq_of_aSearch proves that a search hit is the true Nat.find minimum: isDesc2_ofDigits_gen and exists_gen_of_isDesc2 characterize the admissible numbers exactly, and any smaller admissible number has no more digits. example_975 checks the entry's example 975 = 13·75. The data pin the definition down well. Single-digit numbers count (a(1..4) = 3, 5, 7, 9), the digits descend left to right (319, not 913), and 2n+1 itself counts as a multiple (a(0) = 1). + +**Points for the reviewer** + +- *Note.* "The only numbers n for which a(n)=0 are those for which ..." is read as a set equality (iff). A strict one-way reading would be a(n) = 0 ⇒ 125 | 2n+1. The extra direction, 125 | 2n+1 ⇒ a(n) = 0, is an elementary finite check: an admissible number with 3 or more digits ends in 975, 753, 531, 319 or 197, none of which is divisible by 125. So the iff contains the substantive direction and adds only a trivially true one. No material difference. +- *Note.* The requirement N > 0 in IsDesc2 is needed and correct. Without it, Nat.digits 10 0 = [] would make 0 vacuously admissible and Nat.find would return 0. With it, a n = 0 holds exactly when no admissible multiple exists, which matches the entry's "0 if no such number exists". + +## A071685: Reverse-divisor numbers are 1, 12, 78 or 89 mod 100 (A071685, Dale's conjecture) + +Verdict of the pre-review: **faithful**. Result: [oeis-a071685](../../results/oeis-a071685/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A071685.lean`](../../lean/Math0/Statements/OEIS/A071685.lean). + +**The conjecture as stated in OEIS** + +> %C A071685: "Conjecture: every term mod 100 is equal to 1, 12, 78, or 89. - _Harvey P. Dale_, Dec 13 2017". Entry definition (%N, offset 1, Labos Elemer, Jun 03 2002): "Non-palindromic numbers n, not divisible by 10, such that either n divides R(n) or R(n) divides n, where R(n) is the digit-reversal of n." (Local mirror #39, Nov 05 2025.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, IsTerm n → n % 100 = 1 ∨ n % 100 = 12 ∨ n % 100 = 78 ∨ n % 100 = 89 + +-- dependencies +def R (n : ℕ) : ℕ := Nat.ofDigits 10 (Nat.digits 10 n).reverse +def IsTerm (n : ℕ) : Prop := R n ≠ n ∧ ¬ 10 ∣ n ∧ (n ∣ R n ∨ R n ∣ n) +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) -- used only in the data check +``` + +**What the Lean statement says** + +Let R(n) be the decimal digit reversal of n, with leading zeros dropped. Take any natural number n with R(n) ≠ n, 10 ∤ n, and either n | R(n) or R(n) | n. Then n mod 100 is one of 1, 12, 78, 89. + +**What the kernel checks against the OEIS data** + +term_iff proves, with kernel scans backed by soundness lemmas, that for n < 10^7 IsTerm n holds exactly when n is one of the 16 listed terms 1089, …, 9899901. a_data derives a(1..16) from this. So the predicate is pinned down completely below 10^7, including the entry's exclusions: palindromes such as 12021, and multiples of 10 such as 8380 and 8400 fail IsTerm. R_examples checks R 1089 = 9801, R 8712 = 2178, R 12021 = 12021, R 8380 = 838, and also R 120 = 21 and R 0 = 0. The listed terms of 8 or more digits (10891089, …) are not checked, but the predicate is the entry's definition verbatim. + +**Points for the reviewer** + +- *Note.* The statement quantifies over the predicate IsTerm, not over a(i) = Nat.nth IsTerm (i-1). These are equivalent: the terms of the sequence are exactly the n with IsTerm n. The predicate form even avoids any dependence on the sequence being infinite. +- *Note.* "Non-palindromic" is encoded as R n ≠ n. For n not divisible by 10, R(n) has the same digit list reversed, so this coincides with the digit-palindrome definition. Multiples of 10 are excluded separately anyway. + +## A073642: Yanev's identity for A073642 (sum of the positions of the 1-bits) + +Verdict of the pre-review: **faithful**. Result: [oeis-a073642](../../results/oeis-a073642/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A073642.lean`](../../lean/Math0/Statements/OEIS/A073642.lean). + +**The conjecture as stated in OEIS** + +> %F A073642: "Conjecture: a(n) = (3*A011371(n) - Sum_{k=1..n} A007814(k)^2)/2 for n > 0. - _Velin Yanev_, Sep 09 2017". Entry definition (%N, offset 0): "Replace 2^k in the binary representation of n with k (i.e., if n = 2^b + 2^c + 2^d + ... then a(n) = b + c + d + ...)." A011371 (offset 0): "a(n) = n minus (number of 1's in binary expansion of n). Also highest power of 2 dividing n!." A007814 (offset 1): "Exponent of highest power of 2 dividing n, a.k.a. ... the 2-adic valuation of n." (Local mirror A073642 #121, Jul 05 2026.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 0 < n → + (a n : ℚ) = (3 * (A011371 n : ℚ) - ∑ k ∈ Finset.Icc 1 n, (A007814 k : ℚ) ^ 2) / 2 + +-- dependencies +def a (n : ℕ) : ℕ := (Nat.bitIndices n).sum +def A011371 (n : ℕ) : ℕ := n - (Nat.digits 2 n).count 1 +def A007814 (n : ℕ) : ℕ := padicValNat 2 n +``` + +**What the Lean statement says** + +For every n ≥ 1, let a(n) be the sum of the exponents in the binary expansion of n, s(n) the number of 1-bits of n, and v₂(k) the 2-adic valuation of k. Then a(n) = (3·(n − s(n)) − Σ_{k=1}^{n} v₂(k)²) / 2, computed in the rationals. + +**What the kernel checks against the OEIS data** + +a_data checks all 88 listed terms a(0..87). a_sum_two_pow proves structurally that a(Σ_{i∈s} 2^i) = Σ_{i∈s} i for every finite set s, which is the entry's definition exactly. A011371_data checks all 73 listed terms of A011371 (n = 0..72), and A011371_eq_padicValNat_factorial proves A011371 n = v₂(n!), the second description. A007814_data checks all 111 listed terms of A007814 (k = 1..111). rhs_data checks that 3·A011371(n) − Σ_{k≤n} A007814(k)² = 2·a(n) for n = 1..87. This is a sanity check, not part of the statement. Together these fully pin down all three definitions. + +**Points for the reviewer** + +- *Note.* "/2" is read as exact division in ℚ. This is at least as strong as any integer or floor reading: it also asserts that the numerator is even. So the result implies every reasonable reading. +- *Note.* A011371 uses natural-number subtraction n − (number of 1-bits), which never truncates because there are at most n ones. A007814 0 = padicValNat 2 0 = 0 is a junk value, but it is never used because the sum runs over Icc 1 n. The range n > 0 matches the conjecture. + +## A075855: The longest path on the black squares of an even chessboard has (n^2-n+2)/2 squares (A075855) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a075855](../../results/oeis-a075855/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A075855.lean`](../../lean/Math0/Statements/OEIS/A075855.lean). + +**The conjecture as stated in OEIS** + +> %F A075855 (Jon Perry, Oct 15 2002; edited by Dean Hickerson, Oct 25 2002): "For n odd, a(n)=(n-1)^2/2+1. For n even, it is conjectured that a(n)=(n^2-n+2)/2 (it is easy to show this is a lower bound)." Entry definition (%N, offset 1): "Maximum number of black squares on an n X n chessboard (with a black square in at least one corner) that can be covered by a single path, traveling only to adjacent black squares." Data: 1,2,3,7,9,16,19,29,33. (Local mirror #11, Aug 20 2025.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → Even n → a n = (n ^ 2 - n + 2) / 2 + +-- dependencies +def IsBlack (n : ℕ) (c : ℕ × ℕ) : Prop := c.1 < n ∧ c.2 < n ∧ (c.1 + c.2) % 2 = 0 +def Adj (c d : ℕ × ℕ) : Prop := + c ≠ d ∧ c.1 ≤ d.1 + 1 ∧ d.1 ≤ c.1 + 1 ∧ c.2 ≤ d.2 + 1 ∧ d.2 ≤ c.2 + 1 +def IsBoardPath (n : ℕ) (l : List (ℕ × ℕ)) : Prop := + (∀ c ∈ l, IsBlack n c) ∧ l.Nodup ∧ l.IsChain Adj +-- a is an exhaustive DFS (abridged): +def a (n : ℕ) : ℕ := lmax (cells n) fun c => dfs n (n * n) c (1 <<< idx n c) + 1 +-- proved characterization: +theorem a_spec (n : ℕ) : IsGreatest {k | ∃ l, IsBoardPath n l ∧ l.length = k} (a n) +``` + +**What the Lean statement says** + +For every even n ≥ 2, colour square (i,j) of the n×n board (0 ≤ i,j < n) black when i+j is even, so corner (0,0) is black. Consider sequences of pairwise distinct black squares in which consecutive squares touch. For black squares this means they are diagonal neighbours. The maximum length of such a sequence is (n² − n + 2)/2 = 2m² − m + 1, where n = 2m. a_spec establishes that the Lean a n is exactly this maximum, so the statement does not depend on the search code. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks the exact values a(1..6) = 1, 2, 3, 7, 9, 16. a_data_lower kernel-checks explicit paths, giving only lower bounds 19 ≤ a 7, 29 ≤ a 8, 33 ≤ a 9. The exact values 19, 29, 33 come from an outside-Lean search and are not in the kernel. a_spec proves that a n is the greatest path length for all n, so the search is tied to the definition. The exact terms fix the key conventions. a(3) = 3 rules out revisiting squares, which would give 5. a(2) = 2 confirms diagonal moves; with edge-only adjacency every value would be 1. a(3) = 3 also fixes the colouring for odd n: corners black, since with the other colouring the 4 black squares of the 3×3 board form a 4-cycle and give 4. + +**Points for the reviewer** + +- *Note.* The start square is unrestricted. The parenthetical "with a black square in at least one corner" is read as fixing the colouring, not as requiring the path to start at a corner. I checked by brute force (outside Lean) that both readings give the same values for n ≤ 7. For even n the two readings also coincide given the result: corner-start paths are a subset, so the upper bound transfers. The lower-bound path in the frontier proof (Frontier/OEIS/A075855.lean, snake starting from strip 0 left to right) and the n = 8 witness in a_data_lower both start at (0,0). No material difference. +- *Note.* Only the even case, which the entry marks as conjectured, is stated. The odd-case formula, which the entry asserts as fact, is not part of the statement. This matches the conjecture's scope. The range 1 ≤ n with Even n means n ≥ 2. The ℕ arithmetic is exact: n² ≥ n, and n² − n + 2 = n(n−1) + 2 is even. +- *Note.* The data check is weaker for n ≥ 7: only lower bounds are kernel-checked, so for the even case only a(2), a(4), a(6) are exact in the kernel and a(8) ≥ 29 is a bound. This is a limit of the sanity check, not a definitional gap, because a_spec proves a n equals the definition for every n. diff --git a/review/fidelity/packet-02.md b/review/fidelity/packet-02.md new file mode 100644 index 0000000..7ecd390 --- /dev/null +++ b/review/fidelity/packet-02.md @@ -0,0 +1,390 @@ +# Fidelity review packet 02 of 11 + +Prepared on 29 Oct 2026 by an adversarial reviewing agent, not by a person. It is meant to make a human review of these statements quick: for each one it quotes the OEIS conjecture and the frozen Lean statement, restates the Lean in plain words, and lists anything a reviewer should look at. See [the index](README.md). + +Statements in this packet: A081200, A083020, A086004, A090905, A091817, A092054, A093726, A097154, A106505, A113676. + +## A081200: Collinear 5-point sets in the grid {0,…,4}^n number (7^n − 5^n)/2 (Hardin's conjecture, A081200) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a081200](../../results/oeis-a081200/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A081200.lean`](../../lean/Math0/Statements/OEIS/A081200.lean). + +**The conjecture as stated in OEIS** + +> %C A081200 Conjecture (verified up to a(9)): Number of collinear 5-tuples of points in a 5 X 5 X 5 X ... n-dimensional cubic grid. - _Ron Hardin_, May 24 2010 +> (%N: 6th binomial transform of (0,1,0,1,0,1,...), A000035. Offset 0.) + +**The frozen Lean statement** + +```lean +def binomialTransform (m : ℕ) (b : ℕ → ℕ) (n : ℕ) : ℕ := + ∑ k ∈ Finset.range (n + 1), n.choose k * m ^ (n - k) * b k +def A000035 (k : ℕ) : ℕ := k % 2 +def a (n : ℕ) : ℕ := binomialTransform 6 A000035 n +def toReal (n : ℕ) (x : Fin n → Fin 5) : Fin n → ℝ := fun i => ((x i : ℕ) : ℝ) + +def statement : Prop := + ∀ n : ℕ, + {s : Finset (Fin n → Fin 5) | + s.card = 5 ∧ Collinear ℝ (toReal n '' (s : Set (Fin n → Fin 5)))}.ncard = a n +``` + +**What the Lean statement says** + +For every n ≥ 0, the number of 5-element subsets of the grid {0,1,2,3,4}^n, viewed in R^n, that lie on a single real line equals sum_{k=0}^{n} C(n,k) 6^(n-k) (k mod 2), i.e. the 6th binomial transform of 0,1,0,1,... (which is (7^n - 5^n)/2). + +**What the kernel checks against the OEIS data** + +a_data: kernel-checks all 23 listed terms a(0..22) against the binomial-transform definition, so the sequence side is fully pinned (and equals the OEIS %N definition, not a closed form). There is no kernel check of the counting side. I brute-forced it independently: the count is 1 for n=1 and 12 for n=2, matching a(1), a(2). It also matches the classical ((k+2)^n - k^n)/2 count of lines for k=5. Unordered sets are the only reading that fits a(1)=1, since ordered 5-tuples would give 120. + +**Points for the reviewer** + +- *Note.* "5-tuples" is read as unordered 5-element sets. The data forces this reading (a(1)=1, a(2)=12). In a 5^n grid, a collinear set of 5 distinct points must be a full grid line, so Collinear ℝ (vector span of rank at most 1) matches the intended notion. +- *Note.* The statement also covers n = 0, which Hardin's "n-dimensional grid" probably did not intend. There the grid is one point, the count is 0 and a(0) = 0, so the extra case is true and harmless. Set.ncard is applied to a set of Finsets of a finite type, so it is a genuine count, not a junk 0. + +## A083020: 3^(3^18) + 2 is divisible by 31^2, so Hilliard's squarefree conjecture (A083020) fails + +Verdict of the pre-review: **faithful**. Result: [oeis-a083020](../../results/oeis-a083020/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A083020.lean`](../../lean/Math0/Statements/OEIS/A083020.lean). + +**The conjecture as stated in OEIS** + +> %C A083020 Conjecture: These numbers have no repeating factors or 3^(3^n) + 2 is squarefree. +> (%N: Irregular triangle read by row of the prime factors of 3^(3^n) + 2. Offset 0. Entry by _Cino Hilliard_, May 31 2003; the comment carries no separate attribution.) + +**The frozen Lean statement** + +```lean +def N (n : ℕ) : ℕ := 3 ^ (3 ^ n) + 2 +def row (n : ℕ) : List ℕ := Nat.primeFactorsList (N n) + +def statement : Prop := + ∀ n : ℕ, Squarefree (3 ^ (3 ^ n) + 2) + +(also proved: statement_iff : statement ↔ ∀ n, (row n).Nodup) +``` + +**What the Lean statement says** + +For every n ≥ 0, the number 3^(3^n) + 2 is squarefree (no prime square divides it). + +**What the kernel checks against the OEIS data** + +row_data proves rows 0..4 of the triangle by Lucas/Pratt certificates (5; 29; 5·31·127; 11·693236134999; 5·15679·2372959·5945531·3312453269·121032673159). a_data checks a(0..12). N5_data checks that the 116-digit listed term equals 3^243+2, but its primality is not proved. row6_data checks that row 6 begins 5, 31. The data only serves to confirm N n = 3^(3^n)+2 and the row indexing. The statement itself uses the closed form directly, so nothing in it depends on the data. The result (¬ statement) uses n = 18, p = 31. I confirmed independently that (3^(3^18) + 2) mod 961 = 0. It is also the smallest n with p^2 | N(n) over primes p < 2000. + +**Points for the reviewer** + +- *Note.* "These numbers have no repeating factors" could be misread as "no prime appears twice anywhere in the sequence". That reading is already false from the listed data (5 appears in rows 0, 2, 4 and 6). The author's own "or 3^(3^n)+2 is squarefree" fixes the meaning as per-row squarefreeness. statement_iff shows this is the same as no repeated prime within a row. +- *Note.* The range n ≥ 0 matches the triangle's offset 0 (row 0 is 3^1+2 = 5). The refutation uses n = 18, which is well inside any reasonable range, so the range choice cannot affect the result. + +## A086004: There are no 5-Rotation Cycle Primes (A086004, Conjecture 2) + +Verdict of the pre-review: **faithful**. Result: [oeis-a086004](../../results/oeis-a086004/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A086004.lean`](../../lean/Math0/Statements/OEIS/A086004.lean). + +**The conjecture as stated in OEIS** + +> %C A086004 Conjecture 2: There are no 5-Rotation Cycle Primes. +> (Entry by _Chuck Seggelin_, Jul 07 2003. Context in the entry: %N "Primes which remain prime after one and after two and after three applications of the rotate-and-add operation of A086002"; "Note: Have not yet found any 4-Rotation Cycle Primes."; Chai Wah Wu, Aug 20 2015: "4-Rotation Cycle Primes exist and are listed in A261458" — A261458 = primes which remain prime after one, two, three and four applications.) + +**The frozen Lean statement** + +```lean +def rot (n : ℕ) : ℕ := + let d := (Nat.digits 10 n).length + let l := d / 2 + let h := d - l + n % 10 ^ l * 10 ^ h + n / 10 ^ l % 10 ^ (h - l) * 10 ^ l + n / 10 ^ h +def rotAdd (n : ℕ) : ℕ := n + rot n +def IsRotationCyclePrime (k p : ℕ) : Prop := + p.Prime ∧ ∀ j, 1 ≤ j → j ≤ k → (rotAdd^[j] p).Prime + +def statement : Prop := + ∀ p : ℕ, ¬ IsRotationCyclePrime 5 p +``` + +**What the Lean statement says** + +Let rot(n) swap the block of the first floor(d/2) decimal digits of n with the block of the last floor(d/2) digits, where d is the digit count and the centre digit stays in place when d is odd. Let f(n) = n + rot(n). Then no prime p has f(p), f(f(p)), f^3(p), f^4(p) and f^5(p) all prime. + +**What the kernel checks against the OEIS data** + +rot_examples checks the A086002 examples (rot 1234 = 3412, rot 12345 = 45312) and the A086003/A086004 chain 12917 → 30829 → 60659 → 120319. It also checks the 11-digit A261458 chain 10010905789 → … → 126399526399. rot_eq_rotDigits_data checks the arithmetic rot against a digit-list version for all n < 2000 and on the example numbers. a_data checks a(1..13), all listed terms below 10^8, using a kernel scan that proves the 3-Rotation Cycle Primes below 1530000 are exactly those 13. Independently, I compared the Lean formula with the entry's Mathematica rot on 200,000 random numbers of up to 15 digits and they always agreed. Together these pin rot and the k-step notion. + +**Points for the reviewer** + +- *Note.* The term "k-Rotation Cycle Prime" is never defined explicitly in the entry. The Lean reading is: p prime, and f^j(p) prime for every j = 1..k. Several things support it: the name of A086004 ("remain prime after one and after two and after three applications") alongside the note about 4-Rotation Cycle Primes, Wu's identification of 4-Rotation Cycle Primes with A261458 ("after one, two, three and four applications"), and the fact that a_data reproduces A086004 as the k=3 case. I see no other plausible reading. +- *Note.* Leading zeros produced by rotation are handled the way Mathematica's FromDigits handles them: rot(1203) = 312. A055642(0)=1 differs from (Nat.digits 10 0).length = 0, but only primes and their images matter, and those are all ≥ 2. + +## A090905: A090905: every row ends at twice the largest prime of the previous row (Murthy's conjecture proved) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a090905](../../results/oeis-a090905/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A090905.lean`](../../lean/Math0/Statements/OEIS/A090905.lean). + +**The conjecture as stated in OEIS** + +> %C A090905 Conjecture: For n > 4 the last term of the n-th group is 2p where p is the largest prime in the (n-1)th group. And these are the Bertrand primes. +> (Entry by _Amarnath Murthy_, Dec 13 2003. %N: Left side of irregular triangle of natural numbers in which every row product is a multiple of the previous. Offset 1. Example rows (1),(2),(3,4),(5,6,7,8),(9..14),(15..26). Mathematica by Michael De Vlieger, Dec 15 2016, searches the next row length starting from the previous length.) + +**The frozen Lean statement** + +```lean +def search (P s : ℕ) : ℕ → ℕ → ℕ → ℕ + | 0, k, _ => k + | fuel + 1, k, Q => if P ∣ Q then k else search P s fuel (k + 1) ((s + k) * Q) +def next (r : ℕ × ℕ) : ℕ × ℕ := + (r.1 + r.2, + search (r.1.ascFactorial r.2) (r.1 + r.2) (r.1 + r.2) r.2 ((r.1 + r.2).ascFactorial r.2)) +def row (n : ℕ) : ℕ × ℕ := next^[n - 1] (1, 1) +def a (n : ℕ) : ℕ := (row n).1 +def len (n : ℕ) : ℕ := (row n).2 +def last (n : ℕ) : ℕ := a n + len n - 1 +def bertrand (n : ℕ) : ℕ := (fun b => Nat.findGreatest Nat.Prime (2 * b - 1))^[n - 1] 2 +(len_succ_isLeast: len (n+1) is the least k ≥ len n with (a n).ascFactorial (len n) ∣ (a (n+1)).ascFactorial k) + +def statement : Prop := + ∀ n : ℕ, 4 < n → ∃ p : ℕ, + IsGreatest {q : ℕ | q.Prime ∧ a (n - 1) ≤ q ∧ q ≤ last (n - 1)} p ∧ + last n = 2 * p ∧ p = bertrand (n - 1) +``` + +**What the Lean statement says** + +Split 1, 2, 3, … into consecutive blocks. Block 1 is (1). Each later block starts right after the previous one, and its length is the least k, with k at least the previous block's length, such that the product of the previous block divides the product of the new block. Then for every n > 4: block n-1 contains a largest prime p, the last element of block n equals 2p, and p equals the (n-1)-th Bertrand prime B_{n-1}, where B_1 = 2 and B_{k+1} is the largest prime < 2B_k. + +**What the kernel checks against the OEIS data** + +a_data checks a(1..18) (first terms of the rows), len_data checks 17 row lengths against A090906, and bertrand_data checks 13 terms of A006992. len_succ_isLeast proves that the computable search really returns the least admissible length. Independently, I recomputed rows 1..28 with a prime-valuation method. They reproduce the listed a(1..28), and they are identical whether the length search starts at k = 1 or at k = len(n). I also checked that all 34 listed terms satisfy a(n+1) - 1 = 2·B_{n-1} for n = 5..33. In other words, the listed data are consistent with what the proved statement forces. + +**Points for the reviewer** + +- *Minor.* The Lean triangle requires each row to be at least as long as the previous row (k ≥ len n). This bound comes from De Vlieger's 2016 Mathematica program. Murthy's name of the sequence ("every row product is a multiple of the previous") does not state it; the unbounded variant is A381901. The bound turns out not to matter. Rows 1..28 are identical with or without it. Moreover, once the proved statement holds, the largest prime B_n of row n forces the next row to have length at least 2B_n - 2B_{n-1}, and that is ≥ len(n) = 2B_{n-1} - 2B_{n-2}. I checked this inequality for all Bertrand primes up to index 38, and it follows from Nagura beyond that. So the bound is never binding, and the two triangles coincide for every n. +- *Note.* "And these are the Bertrand primes" is encoded as p = A006992(n-1). Given the first two conjuncts for all n > 4, this third conjunct follows by induction from B_4 = 7. Since last(n-1) = 2B_{n-2} is not prime, the largest prime of block n-1 is the largest prime ≤ 2B_{n-2} - 1, which is B_{n-1}. The conjunct therefore neither strengthens nor weakens the statement. A looser reading ("each p is some Bertrand prime") would also be implied. Indexing works out: n=5 gives p=7=B_4 and last(5)=14. +- *Note.* IsGreatest asserts that block n-1 contains a prime, which the phrase "the largest prime in the (n-1)th group" takes for granted. n > 4 matches the conjecture: n = 4 fails, since last(4) = 8 ≠ 2·3. last uses truncated subtraction, but len ≥ 1 always, so it never truncates. + +## A091817: Quet's integrality conjecture for A091817 holds + +Verdict of the pre-review: **faithful**. Result: [oeis-a091817](../../results/oeis-a091817/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A091817.lean`](../../lean/Math0/Statements/OEIS/A091817.lean). + +**The conjecture as stated in OEIS** + +> %C A091817 _Leroy Quet_ conjectures that the terms are always integral. This is true for p < 3*10^4. [Entry: Mohammed Bouayoun and _Ralf Stephan_, Mar 07 2004; %N (2*numerator(H(p-3)) -3*denominator(H(p-3)))/p with H(m) = 1 + 1/2 + 1/3 + ...+ 1/m; %O 1,3; PARI: forprime(p=3,100,...); %F a(n) = (2*A001008(p-3) - 3*A002805(p-3))/p, p prime >= 5.] + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → ∃ z : ℤ, a n = (z : ℚ) + +where +def H (m : ℕ) : ℚ := ((List.range m).map (fun k => (1 : ℚ) / ((k : ℚ) + 1))).sum +def term (p : ℕ) : ℚ := (2 * (H (p - 3)).num - 3 * ((H (p - 3)).den : ℤ) : ℚ) / (p : ℚ) +def a (n : ℕ) : ℚ := term (primeAt n) +-- primeAt 0 = 2, primeAt (i+1) = nextPrime (primeAt i) (bounded Bertrand search); proved primeAt i = Nat.nth Nat.Prime i +``` + +**What the Lean statement says** + +For every odd prime p (p = 3, 5, 7, 11, ...), write the harmonic number H(p-3) = 1 + 1/2 + ... + 1/(p-3) in lowest terms as N/D with D > 0 (H(0) = 0/1). Then the rational number (2N - 3D)/p is an integer; that is, p divides 2N - 3D. + +**What the kernel checks against the OEIS data** + +a_data checks all 18 listed terms, a 1 through a 18 (p = 3, ..., 67), including the sign of a(1) = -1, by decide +kernel. A separate example checks primeAt 1..4 = 3, 5, 7, 11. primeAt_eq_nth proves primeAt is Nat.nth Nat.Prime for every index, so the indexing is pinned beyond the data. With 18 exact, rapidly growing values checked, numerator, denominator and offset are fully pinned. + +**Points for the reviewer** + +- *Note.* The %F line says 'p prime >= 5', but the data and the PARI program start at p = 3 (a(1) = -1). The Lean statement covers every n >= 1, i.e. all primes p >= 3. This only adds the trivially true p = 3 case, so it is not weaker than the conjecture. n = 0 (p = 2, where the value -3/2 is not an integer and p-3 truncates to 0) is correctly excluded. +- *Note.* Natural-number subtraction p - 3 never truncates for p >= 3. Rat.num and Rat.den are in lowest terms with a positive denominator, which matches PARI's numerator and denominator. + +## A092054: Convergents of [1; 1/2, 1/3, ..., 1/n]: numerator + denominator = 2^(v2(n!) + v2((n+1)!)) (A092054) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a092054](../../results/oeis-a092054/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A092054.lean`](../../lean/Math0/Statements/OEIS/A092054.lean). + +**The conjecture as stated in OEIS** + +> %F A092054 It appears that a(n) = Sum_{k=1..n} A001511(floor((k+1)/2)). Equivalently, a(n) = 2n + 1 - A000120(n) - A000120(n+1) = A011371(n) + A011371(n+1). - _Franklin T. Adams-Watters_, Feb 02 2006 +> (%N by _Paul D. Hanna_, Feb 19 2004: Base-2 logarithm of the sum of numerator and denominator of the convergents of the continued fraction expansion [1; 1/2, 1/3, 1/4, ..., 1/n, ...]. Offset 1. %C/%F also assert A001902(n) + A092053(n) = 2^a(n).) + +**The frozen Lean statement** + +```lean +def cfEval : List ℚ → ℚ + | [] => 0 + | [x] => x + | x :: y :: ys => x + 1 / cfEval (y :: ys) +def conv (n : ℕ) : ℚ := cfEval ((List.range n).map fun k => 1 / ((k : ℚ) + 1)) +def num (n : ℕ) : ℕ := (conv n).num.natAbs +def den (n : ℕ) : ℕ := (conv n).den +def a (n : ℕ) : ℕ := Nat.log 2 (num n + den n) +def ruler (m : ℕ) : ℕ := padicValNat 2 (2 * m) +def binWeight (m : ℕ) : ℕ := (Nat.digits 2 m).sum +def A011371 (m : ℕ) : ℕ := m - binWeight m + +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + 2 ^ a n = num n + den n ∧ + a n = ∑ k ∈ Finset.Icc 1 n, ruler ((k + 1) / 2) ∧ + (a n : ℤ) = 2 * (n : ℤ) + 1 - (binWeight n : ℤ) - (binWeight (n + 1) : ℤ) ∧ + a n = A011371 n + A011371 (n + 1) +``` + +**What the Lean statement says** + +For every n ≥ 1, write the rational number 1 + 1/(1/2 + 1/(1/3 + … + 1/(1/n))) in lowest terms as p/q. Then p + q is a power of 2, namely 2^e with e = floor(log2(p+q)). Moreover e = sum_{k=1..n} (1 + v2(floor((k+1)/2))) = 2n + 1 - s2(n) - s2(n+1) = (n - s2(n)) + (n+1 - s2(n+1)), where s2 is the binary digit sum. + +**What the kernel checks against the OEIS data** + +conv_four checks the entry's example 45/19. num_data checks num(1..24) = A001902(1..24), the reduced numerators (A001902 has offset 0, and the indices line up). den_data checks den(1..25) = A092053(1..25). a_data checks all 67 listed terms a(1..67). ruler_data, binWeight_data and A011371_data check the helper sequences against their OEIS terms. Together these pin the lowest-terms convergent reading, the floor-log definition and the helpers. Independently, I checked in exact arithmetic for n = 1..399 that p+q is a power of 2 and that all four expressions agree. + +**Points for the reviewer** + +- *Note.* The first conjunct, 2^a(n) = num + den, is not part of Adams-Watters's formula. It is Hanna's power-of-2 claim, stated in the entry's %C/%F. The Lean a is the floor of log2, which is also what the entry's PARI program computes. Under the entry's real-logarithm definition, "a(n) = f(n)" already implies num + den = 2^f(n), so adding the conjunct is the faithful real-log reading. Under the floor-log reading it is a strengthening. Since the result proves the statement, the proof covers both readings. +- *Note.* The two "Equivalently" forms are included as extra conjuncts. They are identities in n and do not depend on the convergents. Writing m = ceil(k/2), the sum of A001511(m) up to M equals 2M - s2(M), and A011371(m) = m - s2(m). I verified the identity algebraically for even and odd n, so these conjuncts add no strength. The middle form is computed in ℤ, which avoids truncated subtraction. A011371 uses ℕ subtraction but never truncates, because binWeight m ≤ m. + +## A093726: Imaginary parts of the convergents of [1+i; 1+i, 1+i, ...] are A317974(n+1)/A138573(n) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a093726](../../results/oeis-a093726/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A093726.lean`](../../lean/Math0/Statements/OEIS/A093726.lean). + +**The conjecture as stated in OEIS** + +> %F: "Conjecture: a(n)/A093727(n) = A317974(n+1)/A138573(n). - _Zhuorui He_, Jun 16 2026". Context: %N "Given the infinite continued fraction (1+i)+1/((1+i)+1/((1+i)+...)), where i is the square root of (-1), this is the numerator of the imaginary part of the convergents." %t "Table[ Im[ Numerator[ FromContinuedFraction[ Table[1 + I, {n}]]]], {n, 30}]". %e (He): "(1+i)+1/((1+i)+1/((1+i)+1/(1+i))) = (6+3*i)/4, so A093725(4)=6, a(4)=3 and A093727(4)=4." Offset 1; %E "Definition corrected by and a(29)-a(30) from _Zhuorui He_, Jun 16 2026". Rev #13 (Jun 20 2026); this is still the current version on GitHub oeisdata main. + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + (a n : ℚ) / (A093727 n : ℚ) = (A317974 (n + 1) : ℚ) / (A138573 n : ℚ) + +where (abridged): +def gadd (z w : ℚ × ℚ) : ℚ × ℚ := (z.1 + w.1, z.2 + w.2) +def ginv (z : ℚ × ℚ) : ℚ × ℚ := (z.1 / (z.1*z.1 + z.2*z.2), -z.2 / (z.1*z.1 + z.2*z.2)) +def cfValue : List (ℚ × ℚ) → ℚ × ℚ | [] => (0,0) | [x] => x | x :: xs => gadd x (ginv (cfValue xs)) +def conv (n : ℕ) : ℚ × ℚ := cfValue (List.replicate n (1, 1)) +def gden (z : ℚ × ℚ) : ℕ := Nat.lcm z.1.den z.2.den +def gnumIm (z : ℚ × ℚ) : ℤ := z.2.num * ((gden z / z.2.den : ℕ) : ℤ) +def a (n : ℕ) : ℤ := gnumIm (conv n) +def A093727 (n : ℕ) : ℕ := gden (conv n) +def A317974 : ℕ → ℤ | 0 => 0 | 1 => 0 | 2 => 1 | 3 => 1 | n+4 => 2*(A317974 (n+3) + A317974 (n+2) + A317974 (n+1)) - A317974 n +def A138573 : ℕ → ℤ | 0 => 0 | 1 => 1 | 2 => 2 | 3 => 5 | n+4 => 2*A138573 (n+3) + 2*A138573 (n+2) + 2*A138573 (n+1) - A138573 n +``` + +**What the Lean statement says** + +Let c_n be the finite continued fraction (1+i) + 1/((1+i) + 1/(... + 1/(1+i))) with n partial quotients 1+i (a Gaussian rational). Write c_n = (X + Y i)/d, where d = lcm(den Re c_n, den Im c_n) is the least positive integer with d c_n a Gaussian integer. Then a(n) = Y = d·Im(c_n) and A093727(n) = d, so a(n)/A093727(n) is exactly Im(c_n). Let u = 0,0,1,1,... and v = 0,1,2,5,... (offset 0), both continued by w(m) = 2(w(m-1)+w(m-2)+w(m-3)) - w(m-4). The claim is that for every n >= 1, Im(c_n) = u(n+1)/v(n) as rational numbers. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 30 listed terms a(1..30). A093727_data checks all 28 listed terms of A093727. A317974_data and A138573_data check 20 listed terms each (n = 0..19). These pin A317974 and A138573, which are defined by their own OEIS recurrences anyway. For a and A093727 they confirm the Mathematica Numerator/Denominator reading. They do NOT tell it apart from the literal-name reading 'reduced numerator of Im(c_n)': the two agree on n <= 41 and first differ at n = 42, so the choice between them rests on the program and the examples, not on the data. + +**Points for the reviewer** + +- *Minor.* The truth value depends on which reading of a(n) is used. The name says 'numerator of the imaginary part of the convergents'. Lean uses Im(Numerator(c_n)) = lcm(den Re, den Im)·Im(c_n), as in the program Im[Numerator[...]]. I checked numerically that the two readings first differ at n = 42 (then at 84 and 126). Under the literal-name reading the conjectured identity is false at n = 42: reduced num Im(c_42) = 18854485653829, while d·Im(c_42) = 245108313499777, with d = A093727(42) = 329919304636610. The Lean reading is the defensible one. It is the reading of the program, of He's own examples written as (A093725(n)+a(n)*i)/A093727(n), and of the only sense in which a(n)/A093727(n) is a natural quantity (Im c_n). A reviewer should still know that the alternative reading would give a counterexample rather than a proof. +- *Note.* Under these definitions a(n)/A093727(n) = Im(c_n) exactly (gnumIm/gden = z.2.num/z.2.den). So the statement is 'Im(c_n) = A317974(n+1)/A138573(n) for all n >= 1'. It is an equality of ratios only. It does not claim a(n) = A317974(n+1) or A093727(n) = A138573(n); those fail, e.g. A093727(5) = 15 but A138573(5) = 45. +- *Note.* A093727's OEIS name still carries the old garbled continued fraction '(1+i)+((1+i)/(1+i)+...)'. Lean follows its program (Denominator of FromContinuedFraction[Table[1+I,{n}]]) and all 28 listed terms, which agree with the corrected A093726 name. +- *Note.* There are no junk-value issues. The range is n >= 1, matching offset 1 of A093726 and A093727. A093727(n) >= 1, and A138573(n) >= 1 for n >= 1, so Lean's x/0 = 0 never fires. ginv is only applied to nonzero convergents (Re c_n >= 1). Offsets of A317974 and A138573 (both 0) match OEIS. + +## A097154: The only fixed points of reverse(x) - maxdigit(x) are 0 and 89 + +Verdict of the pre-review: **faithful**. Result: [oeis-a097154](../../results/oeis-a097154/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A097154.lean`](../../lean/Math0/Statements/OEIS/A097154.lean). + +**The conjecture as stated in OEIS** + +> %C: "a(89)=-1 because 89 is the first number that will not reach zero: 98-9=89. It is conjectured that 0 and 89 are the only fixed points of f. See A097155 for numbers that reach 89." (entry by _Jason Earls_, Aug 01 2004; the comment is unsigned). %N: "Number of iterations of f(x) = reverse(x) - maxdigit(x) needed to reach zero, or -1 if zero is never reached, where maxdig(n) is the largest digit of n." The same sentence is in A097155 and A097157. Rev #4 (Dec 15 2017); unchanged on GitHub main. + +**The frozen Lean statement** + +```lean +def rev (x : ℕ) : ℕ := Nat.ofDigits 10 (Nat.digits 10 x).reverse +def maxDigit (x : ℕ) : ℕ := (Nat.digits 10 x).foldr max 0 +def f (x : ℕ) : ℕ := rev x - maxDigit x + +def statement : Prop := + ∀ x : ℕ, f x = x ↔ x = 0 ∨ x = 89 +``` + +**What the Lean statement says** + +For a nonnegative integer x, let rev(x) be the number whose decimal digits are those of x in reverse order (trailing zeros of x become dropped leading zeros, rev 0 = 0). Let maxdig(x) be the largest decimal digit of x (maxdig 0 = 0), and f(x) = rev(x) - maxdig(x). Then for every nonnegative integer x, f(x) = x if and only if x = 0 or x = 89. + +**What the kernel checks against the OEIS data** + +f_examples kernel-checks the entry's example orbit 12 -> 19 -> 82 -> 20 -> 0, f(0) = 0, rev 89 = 98, maxDigit 89 = 9 and f(89) = 89. a_data kernel-checks all 127 listed terms a(1..127) of A097154, including a(89) = -1. a_spec proves that the bounded search used for computability equals the unbounded 'least k with f^[k] n = 0, else -1'. This pins rev (including trailing-zero handling, e.g. 20 -> 0, 100 -> 0), maxDigit and f well. + +**Points for the reviewer** + +- *Note.* Natural-number subtraction in f never truncates: maxDigit_le_rev is proved and f_eq_int restates f with integer subtraction. So f is the entry's map on the nonnegative integers, and f(x) is never negative there. Reversal matches the Mathematica in A097155 (FromDigits[Reverse[IntegerDigits[n]]]). +- *Note.* 'Fixed points' is read literally as f(x) = x, with both directions of the iff and 0 included, as the text says. A broader possible intent, that every orbit ends at 0 or 89 (no other cycles), is not formalized and is not settled by the result. I checked numerically that f has no cycles other than {0} and {89} among x < 10^7, so nothing in the data separates the two readings, but the wording 'only fixed points' supports the literal one. + +## A106505: A106505: common sides of A/2A primitive triangles are periodic mod 8, so a(n+5) = a(n) + 8 + +Verdict of the pre-review: **faithful**. Result: [oeis-a106505](../../results/oeis-a106505/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A106505.lean`](../../lean/Math0/Statements/OEIS/A106505.lean). + +**The conjecture as stated in OEIS** + +> %F: "Conjecture: for n>2, a(n+5) = a(n) + 8. - _Ralf Stephan_, Nov 16 2010." %N (Lekraj Beedassy, May 04 2005): "Ordered and uniqued length of side common to the two angles, one being the double of the other, of a primitive integer-sided triangle." %F: "Values s^2 - r^2, where r= 3. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 67 listed terms (5, 7, ..., 111, 112) by a kernel-decided filter of IsSide over [0, 113), via the proved equivalence of IsSide with y^2 = x(x+c) (isDoubleAngleTriangle_iff, isSide_iff). This pins IsSide exactly on [0, 113). example_33 checks the entry's two triangles with common side 33. + +**Points for the reviewer** + +- *Note.* Lean formalizes the geometric name, not the %F parametrization s^2 - r^2 (r < s < 2r, gcd(r,s) = 1). The two give the same set. Primitivity plus y^2 = x(x+c) forces gcd(x, x+c) = 1, so x = r^2 and x+c = s^2. The triangle inequality c < x + y is equivalent to s < 2r. I also checked numerically that both equal {odd c >= 5} ∪ {8m : m >= 2} for c < 600. +- *Note.* Range and offset are faithful. Offset 1 is handled by Nat.nth (n-1), and the hypothesis n > 2 matches 'for n>2'. The identity genuinely fails at n = 1, 2 (a(6) = 15 ≠ 13, a(7) = 16 ≠ 15). Nat.nth's junk value 0 for a finite set would make the statement false, not vacuous. + +## A113676: The Golomb-row triangle A113676 and Levine's sequence A014644 + +Verdict of the pre-review: **faithful**. Result: [oeis-a113676](../../results/oeis-a113676/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A113676.lean`](../../lean/Math0/Statements/OEIS/A113676.lean). + +**The conjecture as stated in OEIS** + +> %C: "Conjecture: a(n) for n>1 gives first differences of Lionel Levine's sequence A014644(n) for n>=3." %C: "Conjecture: Final elements of the rows form A014644 except for duplicate 2." (entry by _Floor van Lamoen_ and _Paul D. Hanna_, Nov 06 2005). %N: "Number of elements of rows of Golomb's sequence A001462, with one less 2, interpreted as triangle: Start with first row 1. The row sum of row n-1 gives the number of elements taken from A001642 (one less 2) of row n." %e: rows 1; 2; 3,3; 4,4,4,5,5,5. Offset 1. Rev #9 (Mar 05 2025); unchanged on GitHub main. + +**The frozen Lean statement** + +```lean +def statement : Prop := + (∀ n : ℕ, 2 ≤ n → (a n : ℤ) = (A014644 (n + 2) : ℤ) - (A014644 (n + 1) : ℤ)) ∧ + ((row 1).getLast? = some (A014644 1) ∧ + ∀ n : ℕ, 2 ≤ n → (row n).getLast? = some (A014644 (n + 1))) + +where (abridged): +def golombAux : ℕ → List ℕ | 0 => [1, 2, 2] | m + 1 => golombAux m ++ List.replicate ((golombAux m).getD (m + 2) 0) (m + 3) +def golomb : ℕ → ℕ | 0 => 0 | n + 1 => (golombAux n).getD n 0 +def H (j : ℕ) : ℕ := if j ≤ 1 then golomb j else golomb (j + 1) +def rowEnd : ℕ → ℕ | 0 => 0 | 1 => 1 | n + 2 => rowEnd (n + 1) + ((List.range' (rowEnd n + 1) (rowEnd (n + 1) - rowEnd n)).map H).sum +def row (n : ℕ) : List ℕ := (List.range' (rowEnd (n - 1) + 1) (rowEnd n - rowEnd (n - 1))).map H +def a (n : ℕ) : ℕ := (row n).length +def levineAux : List ℕ → ℕ → List ℕ | [], _ => [] | c :: l, i => List.replicate c i ++ levineAux l (i + 1) +def levineRow : ℕ → List ℕ | 0 => [] | 1 => [1, 1] | k + 2 => levineAux (levineRow (k + 1)) 1 +def A014644 (k : ℕ) : ℕ := (levineRow k).getLastD 0 +``` + +**What the Lean statement says** + +Let G be Golomb's sequence (G(1) = 1, nondecreasing, n occurs G(n) times), and let H = 1, 2, 3, 3, 4, 4, 4, ... be G with one 2 removed. Cut H into consecutive rows: row 1 has 1 term, and row n+1 has as many terms as the sum of row n. Let a(n) be the length of row n. Levine's array starts with row [1,1], and each next row lists i repeated c_i times for i = 1, 2, ..., where c_i is the i-th term of the current row. L(k) is the last term of row k. Claim (1): for every n >= 2, a(n) = L(n+2) - L(n+1), as integers. Claim (2): the last term of row 1 is L(1), and for every n >= 2 the last term of row n exists and equals L(n+1). + +**What the kernel checks against the OEIS data** + +golomb_data checks all 84 listed terms of A001462. rows_example checks the four rows shown in the entry. a_data checks all 9 listed terms of A113676 (a(9) = 4362192095 via a proved weighted-sum shortcut). rowLast_data checks that the last elements of rows 1..7 are 1, 2, 3, 5, 11, 38, 272. A014644_data checks the first 11 terms of A014644. Together these pin the triangle, Golomb and Levine definitions and the index shift in claim (1). Only a(n) = A014644(n+2) - A014644(n+1) fits a(2) = 1 = 3 - 2; the shift A014644(n+1) - A014644(n) would give 0. + +**Points for the reviewer** + +- *Note.* The name's 'A001642' is read as the typo it is for A001462, and the example rows confirm this. Deleting either of the two equal 2s gives the same H. +- *Note.* Levine's array is built left to right: i repeated c_i times in increasing i, as in A014643/A014644 and the A014644 Mathematica program. The right-to-left variant (A011784: 1, 2, 2, 3, 4, 7, 14, ...) is not used. The A014644 data (1, 2, 2, 3, 5, 11, 38, 272, ...) fixes this choice. +- *Note.* 'Except for duplicate 2' is formalized as row 1 -> A014644(1) and row n -> A014644(n+1) for n >= 2. getLast? = some also forces every row n >= 1 to be nonempty, which makes the claim slightly stronger than needed (fine for a proof). Claim (1) is in ℤ, so there is no truncated subtraction, and it covers n >= 2 only, as in 'for n>1'; a(1) = 1 is correctly excluded. diff --git a/review/fidelity/packet-03.md b/review/fidelity/packet-03.md new file mode 100644 index 0000000..dc46de0 --- /dev/null +++ b/review/fidelity/packet-03.md @@ -0,0 +1,379 @@ +# Fidelity review packet 03 of 11 + +Prepared on 29 Oct 2026 by an adversarial reviewing agent, not by a person. It is meant to make a human review of these statements quick: for each one it quotes the OEIS conjecture and the frozen Lean statement, restates the Lean in plain words, and lists anything a reviewer should look at. See [the index](README.md). + +Statements in this packet: A115026, A116184, A119936, A120069, A121750, A123710, A124526, A126127, A127752, A127755. + +## A115026: A115026 has a term greater than 370: a(119) = 371 + +Verdict of the pre-review: **faithful**. Result: [oeis-a115026](../../results/oeis-a115026/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A115026.lean`](../../lean/Math0/Statements/OEIS/A115026.lean). + +**The conjecture as stated in OEIS** + +> %C A115026 Conjecture: no term is greater than 370. - _Harvey P. Dale_, Jun 08 2022 [Entry: %N Limiting value of n under iteration of "sum of the digits raised to the power of the number of digits of n" (A101337). %C Iterate A101337 starting at n until reaching a constant value (like 370) or a cycle (like 160, 217, 352, 160, ...). In the latter case, a(n) takes the smallest value in the cycle (e.g., a(59) = 160). %O 1,2; _Sergio Pimentel_, Feb 24 2006] + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → a n ≤ 370 + +where +def F (m : ℕ) : ℕ := ((Nat.digits 10 m).map (· ^ (Nat.digits 10 m).length)).sum +def limitCycle (n : ℕ) : Set ℕ := {m | (∃ k, F^[k] n = m) ∧ ∃ p, 0 < p ∧ F^[p] m = m} +def a (n : ℕ) : ℕ := + let y := meet (fuel n) (F n) (F (F n)) -- Floyd tortoise/hare + cycleMin y (fuel n) (F y) y -- minimum around the cycle of y +-- fuel n = (max n (70*9^70) + 2)^2 +theorem a_spec (n : ℕ) : a n ∈ limitCycle n ∧ ∀ m ∈ limitCycle n, a n ≤ m +``` + +**What the Lean statement says** + +Let F(m) be the sum of the d^L over the decimal digits d of m, where L is the number of digits of m. For every n >= 1, the orbit n, F(n), F(F(n)), ... eventually enters a cycle (possibly a fixed point). The statement claims that the smallest element of that cycle is at most 370. + +**What the kernel checks against the OEIS data** + +a_data checks all 65 listed terms a 1 through a 65 by decide +kernel. These include the fixed-point value 370, small fixed points 1..9, and the genuine cycle case a(59) = 160. Beyond the data, a_spec proves for every n that a n is exactly the minimum of the periodic part of the orbit, so the definition is pinned for all n, not only on the checked terms. F matches A101337 ('Sum of (each digit of n raised to the power (number of digits in n))'): the exponent is the digit count of the current iterate, as the entry's example 89 -> 145 -> 190 -> 730 -> 370 requires. + +**Points for the reviewer** + +- *Note.* The conjecture is false in a trivial way: 371 = 3^3+7^3+1^3 is a narcissistic number, so a(371) = 371. The smallest counterexample is a(119) = 371 (119 -> 731 -> 371), which the result uses. The Lean statement is the literal 'every term <= 370' over the full offset-1 range, so a single term > 370 refutes exactly what Dale wrote. There is no reading of 'no term is greater than 370' under which a(119) = 371 is not a counterexample. +- *Note.* n = 0 (where F 0 = 0) is excluded by 1 <= n, matching offset 1. Orbits of n >= 1 never reach 0. + +## A116184: A116184: Adamchuk's conjectures on 37^3 dividing the numerator of sum_{k=1}^{36} 1/k^n + +Verdict of the pre-review: **faithful**. Result: [oeis-a116184](../../results/oeis-a116184/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A116184.lean`](../../lean/Math0/Statements/OEIS/A116184.lean). + +**The conjecture as stated in OEIS** + +> %C (_Alexander Adamchuk_, Apr 08 2007, entry author; comment unsigned): "... Conjecture: All terms of the arithmetic progression 3+36k belong to a(n). Prime terms in a(n) are {3, 37, 73, 443, 739, 887, 1109, ...}. It appears that all primes in a(n) that are greater than 37 are of the form 37k-1. ..." %N: "Numbers n such that 37^3 divides the numerator of generalized harmonic number H(36,n) = Sum[ 1/k^n, {k,1,36} ]." Offset 1. Rev #6 (Feb 16 2025); unchanged on GitHub main. + +**The frozen Lean statement** + +```lean +def statement : Prop := + (∀ k : ℕ, IsTerm (3 + 36 * k)) ∧ + (∀ p : ℕ, p.Prime → 37 < p → IsTerm p → ∃ k : ℕ, p = 37 * k - 1) + +where: +def H (n : ℕ) : ℚ := ∑ k ∈ Finset.Icc (1 : ℕ) 36, 1 / ((k : ℚ) ^ n) +def IsTerm (n : ℕ) : Prop := (37 ^ 3 : ℤ) ∣ (H n).num +(a n := Nat.nth IsTerm (n - 1) is defined but not used in the statement; exists_a_eq_iff proves that for x ≠ 0, x is some a(m) with m >= 1 iff IsTerm x.) +``` + +**What the Lean statement says** + +Let H(n) = sum_{k=1}^{36} 1/k^n, an exact rational number, and call n a term if 37^3 divides the numerator of H(n) in lowest terms. Claim (a): 3 + 36k is a term for every integer k >= 0. Claim (b): every prime p > 37 that is a term satisfies p = 37k - 1 for some natural k, i.e. p ≡ -1 (mod 37). + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 53 listed terms (3, 37, ..., 975) by a kernel-decided filter of IsTerm over [0, 976). This uses isTerm_iff_check, proved because gcd(37, 36!) = 1, and coeffs_eq, which is also kernel-checked. It pins the predicate exactly on [0, 976). not_isTerm_zero shows that 0, outside the sequence's domain, is not a term. + +**Points for the reviewer** + +- *Note.* The statement is the conjunction of the explicitly labelled 'Conjecture' (the 3+36k progression) and the hedged 'It appears that ...' claim about primes. Proving the conjunction settles both. The quoted list of prime terms {3, 37, 73, 443, ...} and the separate 37^4 remark are data observations and are not formalized. +- *Note.* 'Belongs to a(n)' is expressed through IsTerm instead of membership in the range of a. These are equivalent for nonzero x (exists_a_eq_iff), and 3+36k ≠ 0. Natural subtraction in 37k - 1 is harmless: k = 0 gives 0, which is not a prime > 37, and for k >= 1 it is the true value. 'Numerator' is Rat.num in lowest terms, as Mathematica's Numerator is. k ranges over k >= 0, which includes the term 3. + +## A119936: The row-LCM of denominators of the cube of the mean matrix is n · lcm(1..n)² + +Verdict of the pre-review: **faithful**. Result: [oeis-a119936](../../results/oeis-a119936/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A119936.lean`](../../lean/Math0/Statements/OEIS/A119936.lean). + +**The conjecture as stated in OEIS** + +> %F A119936 a(n)/n^3 = A027451(n) = A002944(n)^2 (the second equation is a conjecture). [_Wolfdieter Lang_, Jul 20 2006; entry #22, Nov 05 2019, identical in the mirror and on GitHub main.] Context: %N "Least common multiple (LCM) of denominators of the rows of the triangle of rationals A119935/A119932."; %C "The triangle of rationals is the matrix cube of the matrix with elements a(i,j) = 1/i if j <= i, 0 if j > i."; %F "a(n) = lcm_{m=1..n} seq(A119932(n,m)), n >= 1."; offset 1. A027451 = "First diagonal of A027447" (A027447 = rows of A^3 written over the least common denominator); A002944 = "a(n) = LCM(1,2,...,n) / n". + +**The frozen Lean statement** + +```lean +def A (i j : ℕ) : ℚ := if j ≤ i then 1 / (i : ℚ) else 0 +def Amat (N : ℕ) : Matrix (Fin N) (Fin N) ℚ := Matrix.of fun i j => A ((i : ℕ) + 1) ((j : ℕ) + 1) +def r (n m : ℕ) : ℚ := if h : 1 ≤ m ∧ m ≤ n then (Amat n ^ 3) ⟨n - 1, by omega⟩ ⟨m - 1, by omega⟩ else 0 +def a (n : ℕ) : ℕ := (Finset.Icc 1 n).lcm fun m => (r n m).den +def lcmUpTo (n : ℕ) : ℕ := (Finset.Icc 1 n).lcm id +def A002944 (n : ℕ) : ℕ := lcmUpTo n / n + +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → (a n : ℚ) / (n : ℚ) ^ 3 = ((A002944 n : ℕ) : ℚ) ^ 2 +``` + +**What the Lean statement says** + +Let A be the infinite lower-triangular matrix with A(i,j) = 1/i for j ≤ i and 0 otherwise. Let r(n,m) be the (n,m) entry of A^3, and let a(n) be the lcm of the reduced denominators of r(n,1), ..., r(n,n). Then for every n ≥ 1, a(n)/n^3 = (lcm(1..n)/n)^2 (equivalently, as statement_iff proves, a(n) = n·lcm(1..n)^2). + +**What the kernel checks against the OEIS data** + +a_data checks all 19 listed terms a(1..19) of A119936. triangle_num_data and triangle_den_data check the 37 listed numerators (A119935) and 32 listed denominators (A119932) of the triangle r read by rows. A002944_data checks the 31 listed terms of A002944. All are decide +kernel. Together they pin down the matrix, the row-LCM and A002944. A027451 is not encoded separately: it is replaced by a(n)/n^3, which is the entry's own first (non-conjectural) equation. + +**Points for the reviewer** + +- *Note.* The conjecture is literally A027451(n) = A002944(n)^2. The Lean statement replaces A027451(n) by a(n)/n^3, which is the entry's own unconjectured first equation. It holds by definition: A027447 writes row n of A^3 over the least common denominator a(n), and the diagonal entry of A^3 is 1/n^3, so A027451(n) = a(n)/n^3. The substitution is correct, but a reviewer should know A027451's data is not checked directly. Its listed terms (1,1,4,9,144,...) do agree with (lcm(1..n)/n)^2. +- *Note.* Natural division in A002944 n = lcmUpTo n / n is exact for n ≥ 1 (A002944_mul), and n = 0 is excluded. The equation is stated in ℚ, so there is no truncation issue. statement_iff gives the integer form a(n) = n·lcm(1..n)^2, which I confirmed independently on all 19 listed terms. + +## A120069: Denominators of Sum C(k)/4^(k-1): Groux's and Staunton's conjectures (A120069) + +Verdict of the pre-review: **faithful**. Result: [oeis-a120069](../../results/oeis-a120069/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A120069.lean`](../../lean/Math0/Statements/OEIS/A120069.lean). + +**The conjecture as stated in OEIS** + +> %F A120069 Conjecture: a(n) = denominator(Catalan(n)/4^(n-1)). - _Groux Roland_, Dec 11 2010 +> %F A120069 Conjecture: a(n) = 2^(A283208(n)-2). - _Alexander Staunton_, Feb 28 2026 +> [Entry #30, Mar 10 2026, identical on GitHub main.] Context: a(n) = denominator(r(n)), r(n) = Sum_{k=1..n} C(k)/2^(2*(k-1)) in lowest terms, C = A000108; offset 1. A283208 (offset 0): "a(n) is the least nonnegative integer such that 2^a(n) (2n+1)/(n+1) c(2n) is a nonnegative integer, where c(2n) = c(2n-1) = Pochhammer(1/2,n)/(n!)". + +**The frozen Lean statement** + +```lean +def r (n : ℕ) : ℚ := ∑ k ∈ Finset.Icc 1 n, (catalan k : ℚ) / 2 ^ (2 * (k - 1)) +def a (n : ℕ) : ℕ := (r n).den +def pochhammer (x : ℚ) (n : ℕ) : ℚ := ∏ i ∈ Finset.range n, (x + i) +def vietoris (n : ℕ) : ℚ := pochhammer (1 / 2) n / (n.factorial : ℚ) +def w (n : ℕ) : ℚ := (2 * n + 1) / (n + 1) * vietoris n +def IsNatExp (n e : ℕ) : Prop := ∃ m : ℕ, (2 : ℚ) ^ e * w n = m +def A283208 (n : ℕ) : ℕ := Nat.find ⟨2 * n, isNatExp_two_mul n⟩ + +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + a n = ((catalan n : ℚ) / 4 ^ (n - 1)).den ∧ + (a n : ℚ) = (2 : ℚ) ^ ((A283208 n : ℤ) - 2) +``` + +**What the Lean statement says** + +For every n ≥ 1, let a(n) be the reduced denominator of Σ_{k=1}^{n} C_k/4^{k-1}, with C_k the Catalan numbers. Then (i) a(n) equals the reduced denominator of C_n/4^{n-1}, and (ii) a(n) = 2^{e(n)-2}, where e(n) is the least e ≥ 0 such that 2^e·(2n+1)/(n+1)·(1/2)_n/n! is a nonnegative integer. The exponent is an integer, so it is not truncated. + +**What the kernel checks against the OEIS data** + +a_data checks all 27 listed terms a(1..27) of A120069 (kernel, through the proven-equal catFast). A283208_data checks all 63 listed terms A283208(0..62) against the comment's definition (kernel). Both definitions are pinned down. The index alignment (A120069 at offset 1 and A283208 at offset 0, both evaluated at the same n) agrees with the data: a(1)=1=2^(2-2), a(2)=2=2^(3-2), a(3)=16=2^(6-2). I re-checked both conjectured identities independently on all 27 listed terms. + +**Points for the reviewer** + +- *Note.* The statement is the conjunction of two separate conjectures (Groux 2010 and Staunton 2026). A proof settles both. A disproof of the conjunction would not say which one fails, but the catalog mode is settles-proves, so this does not matter here. +- *Note.* Staunton's exponent A283208(n)-2 is taken in ℤ. Because A283208(n) ≥ 2 for all n ≥ 1 (A283208(1) = 2 and the sequence increases), this matches the intended natural-number reading exactly. Using ℤ does not weaken the statement. + +## A121750: Mathar's order-6 recurrence for A121750 (even-length columns in deco polyominoes) holds for all n >= 7 + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a121750](../../results/oeis-a121750/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A121750.lean`](../../lean/Math0/Statements/OEIS/A121750.lean). + +**The conjecture as stated in OEIS** + +> %F A121750 Conjecture D-finite with recurrence a(n) +(-n-2)*a(n-1) +(-n^2+4*n-2)*a(n-2) +(n^3-3*n^2-4*n+11)*a(n-3) -(n-1)*(n^2-11*n+26)*a(n-4) +(-n^3+5*n^2+7*n-43)*a(n-5) +(n-3)*(n-5)^2*a(n-6)=0. - _R. J. Mathar_, Jul 26 2022 +> [Entry #13, Aug 20 2024, identical on GitHub main.] %N: "Number of columns of even length in all deco polyominoes of height n. A deco polyomino is a directed column-convex polyomino in which the height, measured along the diagonal, is attained only in the last column." Offset 1 (_Emeric Deutsch_, Aug 20 2006). + +**The frozen Lean statement** + +```lean +def IsDeco (n : ℕ) (cs : List (ℕ × ℕ)) : Prop := + cs ≠ [] ∧ (∀ c ∈ cs, c.1 ≤ c.2) ∧ (∀ c ∈ cs.head?, c.1 = 0) ∧ + (∀ i (h : i + 1 < cs.length), cs[i].1 ≤ cs[i + 1].1 ∧ cs[i + 1].1 ≤ cs[i].2) ∧ + (∀ i (h : i < cs.length), i + cs[i].2 + 1 ≤ n) ∧ + (∃ i, ∃ h : i < cs.length, i + cs[i].2 + 1 = n) ∧ + (∀ i (h : i < cs.length), i + cs[i].2 + 1 = n → i + 1 = cs.length) +def tails ... ; def decos : ℕ → List (List (ℕ × ℕ)) | 0 => [] | n + 1 => tails n 0 -- mem_decos: cs ∈ decos n ↔ IsDeco n cs; nodup_decos +def evenCols (cs : List (ℕ × ℕ)) : ℕ := cs.countP fun c => (c.2 + 1 - c.1) % 2 == 0 +def a (n : ℕ) : ℕ := ((decos n).map evenCols).sum + +def statement : Prop := + ∀ n : ℕ, 7 ≤ n → + (a n : ℤ) + (-(n : ℤ) - 2) * a (n - 1) + (-(n : ℤ) ^ 2 + 4 * n - 2) * a (n - 2) + + ((n : ℤ) ^ 3 - 3 * n ^ 2 - 4 * n + 11) * a (n - 3) - + ((n : ℤ) - 1) * ((n : ℤ) ^ 2 - 11 * n + 26) * a (n - 4) + + (-(n : ℤ) ^ 3 + 5 * n ^ 2 + 7 * n - 43) * a (n - 5) + + ((n : ℤ) - 3) * ((n : ℤ) - 5) ^ 2 * a (n - 6) = 0 +``` + +**What the Lean statement says** + +Encode a polyomino as a nonempty list of columns (b_i, t_i) with b_i ≤ t_i, b_0 = 0, and b_i ≤ b_{i+1} ≤ t_i (directed and column-convex, with the source at the origin). Call it deco of height n if max_i(i + t_i) + 1 = n and that maximum is reached only at the last column. Let a(n) be the total number of even-length columns (t-b+1 even) over all deco polyominoes of height n. Then for every n ≥ 7, a(n) - (n+2)a(n-1) + (-n^2+4n-2)a(n-2) + (n^3-3n^2-4n+11)a(n-3) - (n-1)(n^2-11n+26)a(n-4) + (-n^3+5n^2+7n-43)a(n-5) + (n-3)(n-5)^2 a(n-6) = 0, computed in ℤ. + +**What the kernel checks against the OEIS data** + +Direct enumeration in the kernel: a_data_direct checks a(1..6); decos_length_data_direct checks the counts 1!,...,6!; triangle_data checks rows 1-6 of A121748 (the distribution by number of even columns). Through the proven-equal DP (a_eq_aDP), a_data checks all 19 listed terms a(1..19) and decos_length_data checks n! deco polyominoes for n = 1..19. recurrence_data checks the transcribed recurrence for n = 7..19. Together these strongly pin down the encoding: the diagonal height, directedness and the 'only in the last column' condition all affect the n! counts and the A121748 rows. I recomputed independently that the recurrence vanishes on the OEIS data for n = 7..19. + +**Points for the reviewer** + +- *Note.* The translation from cell-set polyominoes up to translation to column lists, with 'height along the diagonal' read as the number of anti-diagonals x+y = const met, is argued only in the prose docstring and not proved. The kernel checks above (n! counts for 19 heights, 6 rows of A121748, 19 terms) make a wrong encoding that still matched all of them very unlikely. +- *Note.* Mathar gives no range. n ≥ 7 is the largest range for which every a(n-6) is a term (offset 1), so this is the strongest natural reading, and it holds on the data from n = 7. With natural subtraction, n-6 ≥ 1, so there is no truncation. (For the record: the recurrence would also hold at n = 6 if one set a(0) = 1, but a(0) is not a term and Lean's a 0 = 0 is never used.) + +## A123710: A123710: the rows of inv(floor(n/k)) with four nonzero entries are 6 and the proper prime powers + +Verdict of the pre-review: **faithful**. Result: [oeis-a123710](../../results/oeis-a123710/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A123710.lean`](../../lean/Math0/Statements/OEIS/A123710.lean). + +**The conjecture as stated in OEIS** + +> %F A123710 a(n) = A025475(n) for n>2 (conjectured). - _M. F. Hasler_, Feb 12 2012 +> [Entry #27, Sep 05 2025, identical on GitHub main.] %N: "Indices k such that 4 = A123709(k) = number of nonzero terms in row k of triangle A123706." %C: "Triangle A123706 is the matrix inverse of triangle A010766, where A010766(n,k) = [n/k]." Offset 1. A025475 (offset 1): "1 and the prime powers p^m where m >= 2, thus excluding the primes." + +**The frozen Lean statement** + +```lean +def floorMat (N : ℕ) : Matrix (Fin N) (Fin N) ℤ := Matrix.of fun i j => ((((i : ℕ) + 1) / ((j : ℕ) + 1) : ℕ) : ℤ) +noncomputable def A123706 (n k : ℕ) : ℤ := + if h : 1 ≤ k ∧ k ≤ n then (floorMat n)⁻¹ ⟨n - 1, by omega⟩ ⟨k - 1, by omega⟩ else 0 +noncomputable def A123709 (n : ℕ) : ℕ := #{k ∈ Icc 1 n | A123706 n k ≠ 0} +def IsTerm (n : ℕ) : Prop := A123709 n = 4 +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) +def IsA025475 (m : ℕ) : Prop := m = 1 ∨ ∃ p k : ℕ, p.Prime ∧ 2 ≤ k ∧ m = p ^ k +noncomputable def A025475 (n : ℕ) : ℕ := Nat.nth IsA025475 (n - 1) + +def statement : Prop := + ∀ n : ℕ, 2 < n → a n = A025475 n +``` + +**What the Lean statement says** + +Let F be the lower-triangular integer matrix F(n,k) = ⌊n/k⌋ and T = F^{-1}. Let R(n) be the number of nonzero entries T(n,k), 1 ≤ k ≤ n. List the n with R(n) = 4 in increasing order as a(1), a(2), .... List 1 and the prime powers p^m with m ≥ 2 in increasing order as b(1), b(2), .... Then a(n) = b(n) for every n ≥ 3. If there were fewer than n indices with R = 4, Nat.nth would make a(n) = 0 and the statement would be false, as the conjecture would be. + +**What the kernel checks against the OEIS data** + +A123706_data checks all 113 listed terms of A123706 (rows 1-14 and part of row 15). A123709_data checks all 76 listed terms of A123709. a_data checks the first 21 of the 52 listed terms of A123710 (all terms ≤ 512). A025475_data checks the first 21 listed terms of A025475. All are decide +kernel, using the proven-equal back-substitution T (Tmat_eq_inv proves it is the inverse of every truncation). The definitions of the triangle, the row count and both index sequences are pinned down, including the exceptional a(2) = 6 and the offset alignment (A025475(1) = 1 and A025475(2) = 4 against a(1) = 4 and a(2) = 6, so equality starts exactly at n = 3). + +**Points for the reviewer** + +- *Note.* Only 21 of the 52 listed A123710 terms are kernel-checked, because of the back-substitution cost up to 512. The defining ingredients (A123706 and A123709) are checked on all their listed terms, so this does not leave the definition underdetermined. +- *Note.* Matrix.inv over ℤ is Mathlib's adjugate-based inverse, which is a junk value when the determinant is not a unit. Here det = 1, and Tmat_eq_inv proves the computed rows are the true two-sided inverse of every truncation, so no junk values occur. + +## A124526: Hanna's conjecture A124418(n,k) = k! * A124526(n,k) (partitions with k mixed-parity blocks) proved + +Verdict of the pre-review: **faithful**. Result: [oeis-a124526](../../results/oeis-a124526/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A124526.lean`](../../lean/Math0/Statements/OEIS/A124526.lean). + +**The conjecture as stated in OEIS** + +> %C A124526 A124418(n,k) = k!*T(n,k) (conjecture). [_Paul D. Hanna_, Nov 08 2006; entry #14, Nov 02 2020, identical on GitHub main.] Here T(n,k) = A049020([n/2],k)*A049020([(n+1)/2],k), "Row n has 1+floor(n/2) terms", offset 0, A049020(n,k) = Sum_{i=0..n} S2(n,i)*C(i,k). The same conjecture is in A124418 %F: "Conjecture: T(n,k) = k!*A049020([n/2],k)*A049020([(n+1)/2],k) ... - _Paul D. Hanna_, Nov 08 2006". A124418 %N: "T(n,k) is the number of partitions of the set {1,2,...,n} having exactly k blocks that contain both odd and even entries (0<=k<=floor(n/2))." + +**The frozen Lean statement** + +```lean +def A049020 (m k : ℕ) : ℕ := ∑ i ∈ range (m + 1), Nat.stirlingSecond m i * Nat.choose i k +def T (n k : ℕ) : ℕ := A049020 (n / 2) k * A049020 ((n + 1) / 2) k +def IsMixed (b : Finset ℕ) : Prop := (∃ x ∈ b, Odd x) ∧ (∃ x ∈ b, Even x) +def A124418 (n k : ℕ) : ℕ := + (univ.filter fun P : Finpartition (Icc 1 n) => (P.parts.filter IsMixed).card = k).card + +def statement : Prop := + ∀ n k : ℕ, k ≤ n / 2 → A124418 n k = k.factorial * T n k +``` + +**What the Lean statement says** + +For all n ≥ 0 and 0 ≤ k ≤ ⌊n/2⌋, the number of set partitions of {1,...,n} with exactly k blocks that contain both an odd and an even element equals k!·B(⌊n/2⌋,k)·B(⌊(n+1)/2⌋,k), where B(m,k) = Σ_{i=0}^{m} S2(m,i)·C(i,k) and S2 is the Stirling number of the second kind. + +**What the kernel checks against the OEIS data** + +T_data and a_data check all 16 listed rows and all 72 listed terms of A124526 (kernel). rhs_data checks that k!·T(n,k) reproduces all 49 listed terms of A124418 (this checks only the transcription of the right-hand side). A124418_data checks the combinatorial definition directly only on rows n = 0..3 ([1],[1],[1,1],[2,3]), because enumerating Finpartition is doubly exponential. The right-hand side is thoroughly pinned down. The left-hand side is pinned down only weakly by data, but its definition is a literal three-line transcription: Finpartition (Icc 1 n) is exactly the set partitions of {1..n} into nonempty blocks, and IsMixed is 'contains an odd and an even entry'. + +**Points for the reviewer** + +- *Note.* The combinatorial side A124418 is kernel-checked against OEIS only for n ≤ 3 (6 values). Its fidelity therefore rests on reading the short definition (Finpartition of Icc 1 n, count of IsMixed parts), which I read as correct, rather than on data. +- *Note.* The range k ≤ ⌊n/2⌋ matches the index range of both triangles. Outside it both sides are 0 anyway: there are only ⌊n/2⌋ even elements, and A049020(m,k) = 0 for k > m. So the restriction does not weaken the statement. A049020 uses Mathlib's Nat.stirlingSecond rather than the quoted alternating-sum closed form, which is the same function, and it is confirmed on all 72 terms. + +## A126127: A126127: Israel's conjectured bivariate g.f. of the inverse square of A061554 holds + +Verdict of the pre-review: **faithful**. Result: [oeis-a126127](../../results/oeis-a126127/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A126127.lean`](../../lean/Math0/Statements/OEIS/A126127.lean). + +**The conjecture as stated in OEIS** + +> %F A126127 G.f. as triangle (conjectured): (1-x)*(1-x+x^2)/(1-x*y+3*x^2-x^3*y+x^4). - _Robert Israel_, Jul 07 2019 +> (Context: name "Inverse square of A061554."; %F "Given M = Pascal's triangle with descending row terms, (A061554); A126127 = M^(-2)."; offset 0, keywords tabl,sign; Maple: T:= Matrix(20,20,(n,k) -> binomial(n-1, floor((n)/2 - (-1)^(n-k)*(k)/2)), shape=triangular[lower]): A:= T^(-2).) + +**The frozen Lean statement** + +```lean +def statement : Prop := + gf = (1 - X 0) * (1 - X 0 + X 0 ^ 2) * + (1 - X 0 * X 1 + 3 * X 0 ^ 2 - X 0 ^ 3 * X 1 + X 0 ^ 4 : MvPowerSeries (Fin 2) ℚ)⁻¹ + +with + def M (n k : ℕ) : ℤ := if k ≤ n then (n.choose ((n - k) / 2) : ℤ) else 0 + Minv n k := row n of N computed by forward substitution N(n,k) = [k = n] - Σ_{j n (via nextRow/invRows lists) + def T (n k : ℕ) : ℤ := ∑ j ∈ range (n + 1), Minv n j * Minv j k + noncomputable def gf : MvPowerSeries (Fin 2) ℚ := fun m => if m 1 ≤ m 0 then (T (m 0) (m 1) : ℚ) else 0 +Proved helpers: Nmat_eq_inv (L×L truncation of Minv = (Mmat L)⁻¹), T_spec (Tmat L = Mmat L ^ (-2 : ℤ) for every L), coeff_gf, statement_iff (equivalent to gf * den = (1 - X 0) * (1 - X 0 + X 0 ^ 2)). +``` + +**What the Lean statement says** + +Let M be the infinite lower-triangular integer matrix M(n,k) = C(n, floor((n-k)/2)) for 0 ≤ k ≤ n (0 above the diagonal), and let T = M^(-2) (proved to agree with the inverse-square of every finite leading block). Then the bivariate formal power series Σ_{n≥0} Σ_{k=0}^{n} T(n,k) x^n y^k (x marks the row, y the column) equals (1-x)(1-x+x^2)·(1 - xy + 3x^2 - x^3 y + x^4)^(-1) in Q[[x,y]]. Equality of whole series, so it also says the right side has no coefficients above the diagonal (k > n). + +**What the kernel checks against the OEIS data** + +a_data (decide +kernel): all 66 listed terms a(0..65) = rows 0..10 of the triangle, read by rows via pos (pos_spec proves pos(n(n+1)/2+k) = (n,k)). The definition of T is not only data-pinned: T_spec proves T = M^(-2) for every truncation, and M is the closed form for A061554 read as a triangle (Barry/Bala formula, equivalent to the entry's Maple program). M is not checked directly against A061554 terms, but the unipotent square root of M^2 is unique, so the 66 T-terms pin M on rows 0..10. I also checked independently (sympy, 16 rows) that the series expansion with x = row variable matches M^(-2), and that the swapped orientation (y = row) does not. So the encoded orientation is the only one consistent with the data. + +**Points for the reviewer** + +- *Note.* A061554 is primarily a square array read by antidiagonals. The encoding uses its triangle reading, T(n,k) = binomial(n, floor((n-k)/2)), which the A126127 formula ('Pascal's triangle with descending row terms') and Maple program clearly intend. This is correct, but it is a choice a reviewer may want to confirm. +- *Note.* The g.f. is stated over Q with the formal inverse of a series whose constant term is 1 (statement_iff gives the cleared-denominator form). T is an integer triangle cast to Q, which is harmless. +- *Note.* Catalog metadata only, not the statement: the catalog's 'area' is 'Discrete geometry', which does not fit (this is combinatorics / Riordan arrays). + +## A127752: A127752 mod 2 is the first Feigenbaum symbolic sequence A035263 + +Verdict of the pre-review: **faithful**. Result: [oeis-a127752](../../results/oeis-a127752/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A127752.lean`](../../lean/Math0/Statements/OEIS/A127752.lean). + +**The conjecture as stated in OEIS** + +> %C A127752 a(n) mod 2 is first Feigenbaum symbolic sequence A035263 (conjecture). [Paul Barry, Jan 28 2007] +> %C A127752 The conjecture is true at least up to 2048 first terms. (But please note the different indexing, here 0-based.) - _Antti Karttunen_, Sep 29 2018 +> (Name: "Row sums of inverse of number triangle A(n,k) = 1/(3n+1) if k <= n <= 2k, 0 otherwise."; offset 0. A035263: "Trajectory of 1 under the morphism 0 -> 11, 1 -> 10", offset 1.) + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n : ℕ, a n % 2 = (A035263 (n + 1) : ℤ) + +with + def A (n k : ℕ) : ℚ := if k ≤ n ∧ n ≤ 2 * k then 1 / (3 * n + 1 : ℚ) else 0 + def next (l : List ℤ) : ℤ := 3 * l.length + 1 - ∑ j ∈ range l.length, if l.length ≤ 2 * j then l.getD j 0 else 0 + def vals : ℕ → List ℤ | 0 => [] | n + 1 => vals n ++ [next (vals n)] + def a (n : ℕ) : ℤ := (vals (n + 1)).getD n 0 -- a_rec: a n = 3n+1 - Σ_{j [1] | k + 1 => (word k).flatMap sigma + def A035263 (n : ℕ) : ℕ := (word n).getD (n - 1) 0 +Proved helpers: a_spec (a i = Σ_j (Amat N)⁻¹ i j for every N and i < N), word_length, word_prefix, A035263_eq. +``` + +**What the Lean statement says** + +Let A be the infinite lower-triangular rational matrix with A(n,k) = 1/(3n+1) when k ≤ n ≤ 2k and 0 otherwise, and let a(n) (n ≥ 0) be the n-th row sum of its inverse. The proof shows this equals the row sum of the inverse of every finite leading block, and that it is an integer. Let w be the infinite fixed point, starting from 1, of the morphism 0 → 11, 1 → 10, with letters numbered from 1. Then for every n ≥ 0, a(n) mod 2 equals the (n+1)-th letter of w. + +**What the kernel checks against the OEIS data** + +a_data (decide +kernel): all 106 listed terms a(0..105). A035263_data (decide +kernel): all 105 listed terms of A035263(1..105). Both definitions are pinned: a_spec proves a is the row-sum vector of the inverse of every truncation, and the morphic word is the unique fixed point (word_prefix / A035263_eq). The data also confirm the index shift: a mod 2 = 1,0,1,1,1,0,1,0,... = A035263(1),A035263(2),..., while the unshifted reading fails at n = 1 (a(1) = 4 is even, A035263(1) = 1). I independently checked the parity identity in Python up to n = 3000. + +**Points for the reviewer** + +- *Note.* Index shift a(n) mod 2 = A035263(n+1): a(n) has offset 0 and A035263 has offset 1. Karttunen's note in the entry asks for exactly this shift, and it is the only alignment consistent with the data. +- *Note.* 'mod 2' is Int.emod, which always returns 0 or 1. a(n) is positive (keyword nonn), so there is no sign issue anyway. +- *Note.* Catalog metadata only: the catalog's 'area' is 'Discrete geometry', which does not fit. + +## A127755: The inverse of the triangle 1/n! [k ≤ n ≤ 2k] is an integer triangle + +Verdict of the pre-review: **faithful**. Result: [oeis-a127755](../../results/oeis-a127755/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A127755.lean`](../../lean/Math0/Statements/OEIS/A127755.lean). + +**The conjecture as stated in OEIS** + +> %C A127755 It is conjectured that this is an integer triangle. Row sums are A127756. [Paul Barry, Jan 28 2007] +> (Name: "Inverse of number triangle A(n,k) = 1/n! if k <= n <= 2k, 0 otherwise."; offset 0, keywords sign,tabl.) + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n k : ℕ, k ≤ n → ∃ z : ℤ, T n k = z + +with + def A (n k : ℕ) : ℚ := if k ≤ n ∧ n ≤ 2 * k then 1 / (n.factorial : ℚ) else 0 + T n k : ℚ := forward substitution T(n,k) = n! · ([n = k] - Σ_{j n (via nextRow/rows lists; T_spec) +Proved helpers: inv_Amat ((Amat N)⁻¹ = Tmat N for every N), statement_iff_matrix (statement ↔ ∀ N i j, ∃ z : ℤ, (Amat N)⁻¹ i j = z). +``` + +**What the Lean statement says** + +Let A be the infinite lower-triangular rational matrix with A(n,k) = 1/n! when k ≤ n ≤ 2k and 0 otherwise, and let T be its inverse, which is lower triangular and is proved to be the inverse of every finite leading block. Then every entry T(n,k) with 0 ≤ k ≤ n is an integer. Equivalently, for every N, all entries of the inverse of the N×N leading block of A are integers. + +**What the kernel checks against the OEIS data** + +a_data (decide +kernel): all 64 listed terms (rows 0..9 plus the first 9 entries of row 10), using the reading by rows given by rowOf. rows_data (decide +kernel): the 13 example rows 0..12. The definition is pinned by proof, not just by data: inv_Amat proves T is Mathlib's inverse of every truncation of A, and A is transcribed literally from the name. + +**Points for the reviewer** + +- *Note.* Only the first sentence of the comment is a conjecture. 'Row sums are A127756' is a cross-reference and is correctly left out. +- *Note.* The OEIS-sequence function a : ℕ → ℚ is used only for the data check and does not appear in statement. +- *Note.* Catalog metadata only: the catalog's 'area' is 'Discrete geometry', which does not fit. diff --git a/review/fidelity/packet-04.md b/review/fidelity/packet-04.md new file mode 100644 index 0000000..70e8a9e --- /dev/null +++ b/review/fidelity/packet-04.md @@ -0,0 +1,388 @@ +# Fidelity review packet 04 of 11 + +Prepared on 29 Oct 2026 by an adversarial reviewing agent, not by a person. It is meant to make a human review of these statements quick: for each one it quotes the OEIS conjecture and the frozen Lean statement, restates the Lean in plain words, and lists anything a reviewer should look at. See [the index](README.md). + +Statements in this packet: A127767, A129455, A132616, A141412, A144637, A160848, A172164, A175385, A176206, A178295. + +## A127767: The inverse of the 1/Catalan band triangle (A127767) has integer entries + +Verdict of the pre-review: **faithful**. Result: [oeis-a127767](../../results/oeis-a127767/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A127767.lean`](../../lean/Math0/Statements/OEIS/A127767.lean). + +**The conjecture as stated in OEIS** + +> %C A127767 It is conjectured that all elements of the triangle are integers. [Paul Barry, Jan 28 2007] +> (Name: "Inverse of number triangle A(n,k) = 1/C(n) if k <= n <= 2k, 0 otherwise, where C(n) = A000108(n)."; offset 0, keywords sign,tabl; PARI by Michel Marcus uses (i+1)/binomial(2*i,i) = 1/C(i).) + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n k : ℕ, k ≤ n → ∃ z : ℤ, T n k = z + +with + def cat : ℕ → ℕ | 0 => 1 | n + 1 => cat n * (2 * (2 * n + 1)) / (n + 2) -- cat_eq_catalan: cat n = catalan n + def A (n k : ℕ) : ℚ := if k ≤ n ∧ n ≤ 2 * k then 1 / (cat n : ℚ) else 0 + T n k : ℚ := forward substitution T(n,k) = C(n) · ([n = k] - Σ_{j n (T_spec) +Proved helpers: inv_Amat ((Amat N)⁻¹ = Tmat N for every N), statement_iff_matrix. +``` + +**What the Lean statement says** + +Let C(n) be the Catalan numbers, and let A be the infinite lower-triangular rational matrix with A(n,k) = 1/C(n) when k ≤ n ≤ 2k and 0 otherwise. Let T be its inverse, which is proved to be the inverse of every finite leading block. Then every entry T(n,k) with 0 ≤ k ≤ n is an integer. + +**What the kernel checks against the OEIS data** + +a_data (decide +kernel): all 66 listed terms (rows 0..10). rows_data (decide +kernel): the same rows as lists. cat is proved equal to Mathlib's catalan for all n (cat_eq_catalan), so the integer-division recursion cannot be a junk value. inv_Amat proves T is the inverse of every truncation, so the definitions are pinned by proof, not only by the checked terms. + +**Points for the reviewer** + +- *Note.* cat uses natural-number division in its recursion. This is harmless, because cat_eq_catalan proves it equals Mathlib's catalan for every n. +- *Note.* Catalog metadata only: the catalog's 'area' is 'Discrete geometry', which does not fit. + +## A129455: The triple-gcd Pascal triangle A129455: T(n,k) is an integer, divisible by C(n,k), and T(n,k)/C(n,k) is a sixth power + +Verdict of the pre-review: **faithful**. Result: [oeis-a129455](../../results/oeis-a129455/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A129455.lean`](../../lean/Math0/Statements/OEIS/A129455.lean). + +**The conjecture as stated in OEIS** + +> %C A129455 It appears that the T(n,k) are always integers. This would follow from the conjectured prime factorization given in A129454. Calculation suggests that the binomial coefficients C(n,k) divide T(n,k) and that T(n,k)/C(n,k) are perfect sixth powers. [Peter Bala, Apr 16 2007] +> (Name: "An analog of Pascal's triangle based on A129454. T(n, k) = A129454(n+1)/(A129454(n-k+1)*A129454(k+1))."; offset 0. A129454 (offset 0): a(n) = Product{i=1..n-1} Product{j=1..n-1} Product{k=1..n-1} gcd(i,j,k), with a(n) = 1 for n ≤ 2.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n k : ℕ, k ≤ n → + A129454 (n - k + 1) * A129454 (k + 1) ∣ A129454 (n + 1) ∧ + n.choose k ∣ T n k ∧ + ∃ m : ℕ, T n k / n.choose k = m ^ 6 + +with + def A129454 (n : ℕ) : ℕ := + ∏ i ∈ Finset.Icc 1 (n - 1), ∏ j ∈ Finset.Icc 1 (n - 1), ∏ k ∈ Finset.Icc 1 (n - 1), Nat.gcd (Nat.gcd i j) k + def T (n k : ℕ) : ℕ := A129454 (n + 1) / (A129454 (n - k + 1) * A129454 (k + 1)) +``` + +**What the Lean statement says** + +Let G(m) = Π_{i,j,l=1..m} gcd(i,j,l), so G(0) = 1, and set T(n,k) = G(n)/(G(k)·G(n-k)). For all 0 ≤ k ≤ n: (1) G(k)·G(n-k) divides G(n), so T(n,k) is an exact integer; (2) the binomial coefficient C(n,k) divides T(n,k); (3) T(n,k)/C(n,k) is m^6 for some natural number m. Natural-number division appears only in T and in T/C(n,k), and both are exact because of (1) and (2), which are asserted in the same conjunction. + +**What the kernel checks against the OEIS data** + +A129454_data (decide +kernel): the first 10 terms of A129454 (n = 0..9). This checks the empty-product convention for n = 0, 1, 2 and the gcd product. a_data (decide +kernel): all 45 listed terms of A129455 (rows 0..8). statement_check (decide +kernel): all three claims hold for rows n ≤ 8, with explicit sixth roots. A129454 and T are literal transcriptions of the OEIS formulas, so the data check confirms the transcription rather than replacing a definition. + +**Points for the reviewer** + +- *Note.* T uses ℕ division. This is sound only because divisibility (1) is a conjunct of the statement, and likewise (2) makes T/C(n,k) in (3) exact. Since the statement is proved, all three hold with exact quotients. n - k is used only under k ≤ n, so truncated subtraction never fires. +- *Note.* 'perfect sixth power' allows m = 0 (and m = 1). T(n,k) ≥ 1, so the quotient is never 0, and the boundary entries T(n,0)/C(n,0) = 1 = 1^6 are correctly counted as sixth powers. +- *Note.* Bala's remark that integrality 'would follow from the conjectured prime factorization given in A129454' is an explanation and is correctly not encoded. The A129454 factorization conjecture is a separate claim and is not settled by this statement. +- *Note.* Catalog metadata only: the catalog's 'area' is 'Discrete geometry', which does not fit. + +## A132616: Irwin's nested sums give column 0 of the triangle A132615 (A132616) + +Verdict of the pre-review: **faithful**. Result: [oeis-a132616](../../results/oeis-a132616/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A132616.lean`](../../lean/Math0/Statements/OEIS/A132616.lean). + +**The conjecture as stated in OEIS** + +> %F A132616 From _Benedict W. J. Irwin_, Nov 29 2016: (Start) Conjecture: a(n) is described by a series of nested sums, a(2) = Sum_{i=1..1} 1, a(3) = Sum_{i=1..1+2} Sum_{j=1..i} 1, a(4) = Sum_{i=1..1+4} Sum_{j=1..i+2} Sum_{k=1..j} 1, a(5) = Sum_{i=1..1+6} Sum_{j=1..i+4} Sum_{k=1..j+2} Sum_{l=1..k} 1, and so on, where 2, 4, 6,... are the even numbers. (End) +> [Entry: %N Column 0 of triangle A132615, offset 0, Paul D. Hanna Aug 24 2007. A132615 %N: Triangle T, read by rows, where row n+1 of T = row n of T^(2n-1) with appended '1' for n>=0 with T(0,0)=1.] + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n : ℕ, 2 ≤ n → a n = nest (n - 1) 1 + +def tri : (n : ℕ) → Matrix (Fin (n + 1)) (Fin (n + 1)) ℕ + | 0 => 1 + | n + 1 => Matrix.of fun i j => + if hi : (i : ℕ) ≤ n then + if hj : (j : ℕ) ≤ n then tri n ⟨i, _⟩ ⟨j, _⟩ else 0 + else + if hj : (j : ℕ) ≤ n then (tri n ^ (2 * n - 1)) (Fin.last n) ⟨j, _⟩ else 1 +def T (n k : ℕ) : ℕ := if h : k ≤ n then tri n (Fin.last n) ⟨k, _⟩ else 0 +def a (n : ℕ) : ℕ := T n 0 +def nest : ℕ → ℕ → ℕ + | 0, _ => 1 + | m + 1, c => ∑ i ∈ Icc 1 (c + 2 * m), nest m i +``` + +**What the Lean statement says** + +Build a lower-triangular matrix of naturals row by row: row 0 is [1]; row n+1 is row n of the (2n-1)-th power of the triangle built so far (exponent 0 when n = 0), followed by a 1 on the diagonal. Let a(n) be the entry in row n, column 0. Define nest(0,c) = 1 and nest(m+1,c) = sum over i = 1..c+2m of nest(m,i). Claim: for every n >= 2, a(n) = nest(n-1, 1), i.e. a(n) equals the (n-1)-fold nested sum Sum_{i1=1..1+2(n-2)} Sum_{i2=1..i1+2(n-3)} ... Sum_{i_{n-1}=1..i_{n-2}} 1. + +**What the kernel checks against the OEIS data** + +T_data: all 55 listed terms of A132615 (rows 0..9) by decide +kernel. a_data: all 19 listed terms a(0..18) of A132616 by decide +kernel. nest_two..nest_five: rfl proofs that nest(n-1,1) is literally Irwin's displayed expression for n = 2,3,4,5. statement_check: identity for 2 <= n <= 12 by kernel. The triangle data (55 terms, incl. row 1 = [1,1] which tests the n=0 exponent handling) pin the definition of T; the rfl lemmas pin the 'and so on' pattern of nest against the four displayed cases. + +**Points for the reviewer** + +- *Note.* For n = 0 the OEIS exponent 2n-1 = -1 (row 0 of T^-1); Lean's truncated subtraction gives exponent 0. Both give row 0 = [1], hence row 1 = [1,1]; documented in the file and confirmed by T_data. No effect elsewhere since 2n-1 >= 1 for n >= 1. +- *Note.* Range n >= 2 matches Irwin's displayed formulas (which start at a(2)); the identity also holds trivially at n = 0, 1 (nest 0 1 = 1 = a(0) = a(1)), so nothing is lost. The generalization 'and so on' is encoded as nest, which also coincides with Somos's two-argument program a(n,k) in the entry (a(n,k) = nest(n-1,k)). +- *Note.* Catalogue field area = 'Discrete geometry' does not fit this matrix/combinatorics entry (catalogue metadata only, not the statement). + +## A141412: Denominators of Curtz's polynomials are Farhi's d(n+1,k+1) (A141412, Marcus's conjecture) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a141412](../../results/oeis-a141412/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A141412.lean`](../../lean/Math0/Statements/OEIS/A141412.lean). + +**The conjecture as stated in OEIS** + +> %F A141412 Conjecture: T(n, k) = d(n+1, k+1), with d(n,k) = denominator(A000254(n, k)*k!/n!) where A000254 are the unsigned Stirling numbers of the 1st kind. See d(n,k) in Farhi link. - _Michel Marcus_, Oct 18 2018 +> [Entry: %N Triangle c(n,k) of the denominators of coefficients [x^k] P(n,x) of the polynomials P(n,x) of A129891; Maple: P(0,x)=1, P(n,x) = (-1)^n/(n+1) + x*add((-1)^i/(i+1)*P(n-1-i,x), i=0..n-1); offset 0, tabl; Paul Curtz Aug 04 2008.] + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n k : ℕ, k ≤ n → T n k = d (n + 1) (k + 1) + +noncomputable def P : ℕ → ℚ[X] + | 0 => 1 + | n + 1 => C ((-1) ^ (n + 1) / (((n + 1 : ℕ) : ℚ) + 1)) + + X * ∑ i ∈ Finset.range (n + 1), C ((-1) ^ i / ((i : ℚ) + 1)) * P (n - i) +def c : ℕ → ℕ → ℚ + | 0, 0 => 1 + | 0, _ + 1 => 0 + | n + 1, 0 => (-1) ^ (n + 1) / (((n + 1 : ℕ) : ℚ) + 1) + | n + 1, k + 1 => ∑ i ∈ Finset.range (n + 1), (-1) ^ i / ((i : ℚ) + 1) * c (n - i) k +theorem coeff_P (n k : ℕ) : (P n).coeff k = c n k +def T (n k : ℕ) : ℕ := (c n k).den +def d (n k : ℕ) : ℕ := + ((Nat.stirlingFirst n k : ℚ) * (Nat.factorial k : ℚ) / (Nat.factorial n : ℚ)).den +``` + +**What the Lean statement says** + +Let P(0,x) = 1 and P(n+1,x) = (-1)^(n+1)/(n+2) + x * sum_{i=0..n} (-1)^i/(i+1) * P(n-i,x) over Q. Let T(n,k) be the reduced denominator of the coefficient of x^k in P(n,x). Let d(n,k) be the reduced denominator of c(n,k)*k!/n!, where c(n,k) is the unsigned Stirling number of the first kind. Claim: for all 0 <= k <= n, T(n,k) = d(n+1,k+1). + +**What the kernel checks against the OEIS data** + +T_data: all 78 listed terms (rows 0..11) of A141412 by decide +kernel, via the computable coefficient recursion c, which coeff_P proves equal to the coefficients of the literal polynomial recursion P. This pins T. There is no kernel data check of d against values, but d is a direct closed form; Mathlib's Nat.stirlingFirst is the unsigned recurrence s(n+1,k+1) = n*s(n,k+1) + s(n,k). I independently checked in Python that T(n,k) = d(n+1,k+1) for all 0 <= k <= n <= 29 with these definitions. + +**Points for the reviewer** + +- *Note.* Marcus writes 'A000254(n,k)', but A000254 is a one-index sequence. The file reads it as the two-index unsigned Stirling numbers of the first kind, following Marcus's own words 'A000254 are the unsigned Stirling numbers of the 1st kind' and G. C. Greubel's programs in the same entry (Denominator[(k+1)!*StirlingS1[n+1,k+1]/(n+1)!]; the sign does not affect the denominator). This is the only reasonable reading. +- *Note.* Range 0 <= k <= n is the triangle's index range; for k > n both sides are den(0) = 1 anyway. Catalogue classification is 'known-result-first-formalization' (Flajolet–Gourdon–Salvy eq. (6) gives it), which fits. Catalogue area 'Discrete geometry' is a metadata mislabel. + +## A144637: A144637: (1/18) 6^n a(n)/n! is odd iff n = 2^k with k >= 1 + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a144637](../../results/oeis-a144637/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A144637.lean`](../../lean/Math0/Statements/OEIS/A144637.lean). + +**The conjecture as stated in OEIS** + +> %F A144637 From _Peter Bala_, Feb 19 2026: (Start) ... (1/18)*A(6*x) = x^2 - 6*x^3 + 33*x^4 - 162*x^5 + 630*x^6 - 972*x^7 - 14499*x^8 + ... appears to be an integral series and satisfies the algebraic equation 36*y(x)^3 + 3*y(x)^2 + (1 + 6*x)*y(x) = x^2. Conjecture: (1/18)*6^(n)*a(n)/n! is odd iff n = 2^k for k >= 1. (End) +> [Entry: %N Column 2 of triangle in A144633, offset 0. A144633: 'take the triangle in A144385, write it as an (infinite) upper triangular square matrix, invert it and transpose it.' A144385: T(n,k) = number of partitions of [1..k] into exactly n blocks of size 1, 2 or 3.] + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, (∃ m : ℤ, Odd m ∧ y n = (m : ℚ)) ↔ ∃ k : ℕ, 1 ≤ k ∧ n = 2 ^ k + +def y (n : ℕ) : ℚ := (1 / 18) * 6 ^ n * (a n : ℚ) / (n.factorial : ℚ) +def a (n : ℕ) : ℤ := T n 2 +-- S n k = A144385 via row recurrence S(n+1,k) = S(n,k-1) + (k-1)S(n,k-2) + (k-1)(k-2)/2 S(n,k-3), row 0 = [1] +-- T n k (A144633) via forward substitution: T(n,k) = [n=k] - Σ_{j= 0, y(n) is an odd integer if and only if n = 2^k for some k >= 1. + +**What the kernel checks against the OEIS data** + +S_data: all 70 listed terms of A144385 (rows 0..6); S_zero/S_succ prove the recurrence for all n,k. T_data: all 55 listed terms of A144633 (rows 0..9). Tmat_eq proves T is the transposed inverse (not just matching data). a_data: all 23 listed terms a(0..22). y_data: y(0..8) = 0,0,1,-6,33,-162,630,-972,-14499, matching Bala's displayed series. All kernel-checked; definitions are pinned down. + +**Points for the reviewer** + +- *Note.* 'Odd' is read as 'is an odd integer'. Bala separately says y(n) 'appears to be' integral, and that integrality claim is not part of the statement. Under a looser reading of odd rationals (2-adic units), the iff could differ only if some y(n) were non-integral. Every y(n) is in fact an integer (y = x^2 - 6xy - 3y^2 - 36y^3 has integer coefficients; the proof establishes this), so the readings agree. +- *Note.* Range n >= 0 matches the offset. At n = 0, 1 we have y = 0 (not odd), and 1 = 2^0 is excluded by k >= 1, consistent with the conjecture. Catalogue area 'Discrete geometry' is a metadata mislabel. + +## A160848: Barker's order-20 recurrence for the lines through an 8 x n grid holds + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a160848](../../results/oeis-a160848/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A160848.lean`](../../lean/Math0/Statements/OEIS/A160848.lean). + +**The conjecture as stated in OEIS** + +> %F A160848 Conjectures from _Colin Barker_, Dec 25 2017: (Start) G.f.: x*(1 + 66*x + 132*x^2 + 304*x^3 + 492*x^4 + 771*x^5 + 1003*x^6 + 1273*x^7 + 1390*x^8 + 1480*x^9 + 1374*x^10 + 1241*x^11 + 971*x^12 + 739*x^13 + 476*x^14 + 296*x^15 + 140*x^16 + 74*x^17 + 17*x^18 + 8*x^19 + 8*x^20) / ((1 - x)^3*(1 + x)*(1 - x + x^2)*(1 + x^2)*(1 + x + x^2)*(1 + x + x^2 + x^3 + x^4)*(1 + x + x^2 + x^3 + x^4 + x^5 + x^6)). a(n) = -a(n-2) + a(n-5) + a(n-6) + 2*a(n-7) + a(n-8) + a(n-9) - a(n-11) - a(n-12) - 2*a(n-13) - a(n-14) - a(n-15) + a(n-18) + a(n-20) for n>21. (End) +> [Entry: %N Number of lines through at least 2 points of an 8 X n grid of points; offset 0; Seppo Mustonen May 28 2009.] + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 21 < n → Recurrence (fun m => (a m : ℤ)) n + +def Recurrence (f : ℕ → ℤ) (n : ℕ) : Prop := + f n = -f (n - 2) + f (n - 5) + f (n - 6) + 2 * f (n - 7) + f (n - 8) + f (n - 9) + - f (n - 11) - f (n - 12) - 2 * f (n - 13) - f (n - 14) - f (n - 15) + f (n - 18) + f (n - 20) +def pt (i : ℕ) : ℤ × ℤ := (((i / 8 : ℕ) : ℤ), ((i % 8 : ℕ) : ℤ)) +def Collinear3 (p q r : ℤ × ℤ) : Prop := + (q.1 - p.1) * (r.2 - p.2) = (q.2 - p.2) * (r.1 - p.1) +def lineThrough (n i j : ℕ) : Finset ℕ := + (Finset.range (8 * n)).filter fun k => Collinear3 (pt i) (pt j) (pt k) +def a (n : ℕ) : ℕ := + (((Finset.range (8 * n) ×ˢ Finset.range (8 * n)).filter fun ij => ij.1 ≠ ij.2).image + fun ij => lineThrough n ij.1 ij.2).card +-- (statement_gf, the g.f. form, is also defined but is not the settled declaration) +``` + +**What the Lean statement says** + +Let a(n) be the number of distinct lines in the plane that pass through at least two points of the grid {0..n-1} x {0..7}, counted as the number of distinct sets of grid points cut out by the lines through two distinct grid points. Claim: for every n > 21, a(n) = -a(n-2) + a(n-5) + a(n-6) + 2a(n-7) + a(n-8) + a(n-9) - a(n-11) - a(n-12) - 2a(n-13) - a(n-14) - a(n-15) + a(n-18) + a(n-20), with values in Z. + +**What the kernel checks against the OEIS data** + +a_data: all 41 listed terms a(0..40) by decide +kernel (through aFast, proved equal to a for every n by a_eq_aFast). recurrence_data: the listed terms satisfy the recurrence for 22 <= n <= 40. The 41 terms (including a(1) = 1, a(2) = 66) pin down the line-counting definition. + +**Points for the reviewer** + +- *Note.* Barker's block contains two conjectures, the g.f. and the order-20 recurrence. The settled statement is the recurrence. statement_gf is defined in the file but not settled. This loses nothing: I checked that Barker's denominator expands to 1 + x^2 - x^5 - x^6 - 2x^7 - x^8 - x^9 + x^11 + x^12 + 2x^13 + x^14 + x^15 - x^18 - x^20, the recurrence's characteristic polynomial, and that (listed a) * D reproduces exactly x * N(x) through x^21 and gives 0 for x^22..x^40. So the recurrence for n > 21 plus the kernel-checked a(0..21) implies the g.f. identity. +- *Note.* Truncated subtraction: for n > 21 every index n-k (k <= 20) is >= 2, so no junk. The grid is oriented n x 8 rather than 8 x n, which gives a congruent point set and the same count. For n = 0 the grid is empty and a(0) = 0, matching the data. + +## A172164: A172164: the second differences of the Theodorus-spiral turns are always 18, 19, 20 or 21 + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a172164](../../results/oeis-a172164/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A172164.lean`](../../lean/Math0/Statements/OEIS/A172164.lean). + +**The conjecture as stated in OEIS** + +> %C A172164 Conjecture : The terms are only 18,19,20,21 (From the first thousand turns, there are 2,3% of 18, 36,5% of 19, 46,2% of 20 and 15% of 21). No period found. Probably due to Pi transcendence. [_Sébastien Dumortier_, Jan 27 2010] +> [Entry: %N Differences between numbers of triangles entirely contained in two consecutive turns of Pythagoras's snail (Theodorus spiral); offset 2; %e In the first turn, 16 triangles are complete. In the 2nd turn, there are 36 triangles completely included. The difference is 20. %F The second forward difference of A072895 (R. G. Wilson v).] + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n : ℕ, 2 ≤ n → a n = 18 ∨ a n = 19 ∨ a n = 20 ∨ a n = 21 + +noncomputable def S (k : ℕ) : ℝ := ∑ i ∈ range k, arctan (1 / √((i : ℝ) + 1)) +def turnTriangles (n : ℕ) : Set ℕ := + {i | 1 ≤ i ∧ 2 * π * ((n : ℝ) - 1) ≤ S (i - 1) ∧ S i ≤ 2 * π * n} +noncomputable def c (n : ℕ) : ℕ := (turnTriangles n).ncard +noncomputable def a (n : ℕ) : ℤ := (c n : ℤ) - c (n - 1) +``` + +**What the Lean statement says** + +Let S(k) = sum_{i=1..k} arctan(1/sqrt(i)), the total central angle of the first k triangles of the Theodorus spiral (triangle i has legs sqrt(i) and 1). Triangle i >= 1 occupies the angle interval [S(i-1), S(i)]. Let c(n) be the number of triangles i >= 1 with 2pi(n-1) <= S(i-1) and S(i) <= 2pi n, i.e. lying entirely in the closed n-th turn. The set is proved finite, so ncard is a genuine count. Claim: for every n >= 2, the integer c(n) - c(n-1) lies in {18, 19, 20, 21}. + +**What the kernel checks against the OEIS data** + +crossing proves S(K n) < 2pi n < S(K n + 1) for n = 1..70 by a kernel-checked rigorous interval computation; Kseq's first 42 entries equal the listed terms of A137515. From this, c_one_two gives c(1) = 16 and c(2) = 36 (the entry's example), and a_data proves all 69 listed terms a(2..70) against the real-number definition. This pins down the turn and triangle conventions (starting ray, closed sectors, which turn counts as first) on the data range. + +**Points for the reviewer** + +- *Note.* Turn boundaries are taken as closed intervals. This can only matter if some S(k) equals 2pi n exactly, which the interval check rules out for n <= 70 and which almost certainly never happens. If it did, the 'entirely contained' count (the entry's name, which Lean follows) and the '%F second forward difference of A072895' (strict >) could differ at that n. Since the result proves the Lean form for all n, this does not change what is settled in substance. +- *Note.* 'The terms are only 18,19,20,21' is formalized as 'every term lies in {18,19,20,21}'. Reading it as 'the set of values is exactly {18,..,21}' adds only that each value occurs, which a_data already witnesses: a(8) = 18, a(3) = 19, a(2) = 20, a(7) = 21. The percentages, 'no period' and 'Pi transcendence' remarks are observations and are correctly left out. Range n >= 2 matches offset 2, and the subtraction is done in Z, so it is not truncated. + +## A175385: ∑_{i=1..n} C(2n-i-1, i-1)/i is never an integer for n > 1 (A175385) + +Verdict of the pre-review: **faithful**. Result: [oeis-a175385](../../results/oeis-a175385/README.md) (known-result-already-formalized). Frozen statement: [`lean/Math0/Statements/OEIS/A175385.lean`](../../lean/Math0/Statements/OEIS/A175385.lean). + +**The conjecture as stated in OEIS** + +> %C A175385 We conjecture that Sum_{i=1..n} ((1/i)*C(2n-i-1,i-1)) is not an integer for n>1. [_Vladimir Shevelev_, _Zak Seidov_, Apr 24 2010; %N a(n) = numerator of Sum_{i=1..n} binomial(2n-i-1,i-1)/i; %O 1,2] + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 1 < n → ¬ ∃ k : ℤ, S n = (k : ℚ) + +where +def S (n : ℕ) : ℚ := + ∑ i ∈ Finset.Icc 1 n, ((Nat.choose (2 * n - i - 1) (i - 1) : ℕ) : ℚ) / (i : ℚ) +def a (n : ℕ) : ℕ := (S n).num.natAbs +``` + +**What the Lean statement says** + +For every integer n >= 2, the rational number S(n) = sum over i = 1..n of C(2n-i-1, i-1)/i is not an integer. + +**What the kernel checks against the OEIS data** + +a_data checks the numerators a 1 through a 27 (all 27 listed terms of A175385) by decide +kernel. The denominators (A175386), which are what the conjecture is actually about, are not kernel-checked in the frozen file. I checked independently that the literal definition gives denominators 1, 2, 6, 4, 5, 4, 7, 8, 18, ..., matching A175386, and that 2n*S(n) = L_{2n} - 1 for n < 60. The definition is a literal transcription in Q. For 1 <= i <= n, the subtractions 2n-i-1 (= (2n-i)-1 >= n-1) and i-1 never truncate, and i >= 1 rules out division by zero. So checking numerators only is not a real gap. + +**Points for the reviewer** + +- *Minor.* The data check pins only the numerators of S(n), not the denominators (A175386), and the conjecture is a statement about the denominator being 1. This does not affect fidelity, because S is a literal, non-truncating transcription of the sum, and I confirmed the denominators match A175386 for n = 1..25. +- *Note.* The range is n > 1 (n >= 2), exactly as stated. n = 1, where S(1) = 1, is correctly excluded. There is no extra hypothesis or index shift. + +## A176206: Divisors of the terms of row n of A176206 are the parts of the partitions of n + +Verdict of the pre-review: **faithful**. Result: [oeis-a176206](../../results/oeis-a176206/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A176206.lean`](../../lean/Math0/Statements/OEIS/A176206.lean). + +**The conjecture as stated in OEIS** + +> %C A176206 From _Omar E. Pol_, Nov 23 2020: ... "Conjecture: all divisors of all terms in row n are also all parts of all partitions of n." (Entry: "Irregular triangle T(n,k) (n >= 1, k >= 1) read by rows: row n has length A000070(n-1) and every column k gives the positive integers." Comment: "Row n contains a decreasing sequence where n-k is repeated A000041(k) times, k = 0..n-1." Worked example for n = 5: divisors of row 5 and parts of all partitions of 5 are both "twelve 1's, four 2's, two 3's, one 4 and one 5". Offset 1.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + (row n : Multiset ℕ).bind (fun t => t.divisors.val) = + (Finset.univ : Finset n.Partition).val.bind (fun π => π.parts) + +-- dependencies +def p (k : ℕ) : ℕ := Fintype.card (Nat.Partition k) +def rowOf (f : ℕ → ℕ) (n : ℕ) : List ℕ := + (List.range n).flatMap fun k => List.replicate (f k) (n - k) +def row (n : ℕ) : List ℕ := rowOf p n +``` + +**What the Lean statement says** + +For every n ≥ 1, let row n be the list in which n−k appears p(k) times for k = 0,…,n−1 (p is the partition function). Take the multiset of all divisors of all entries of row n, with each entry contributing each of its divisors once. This multiset equals the multiset of all parts of all partitions of n, with each partition contributing all of its parts with multiplicity. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 94 listed terms of the flattened triangle (rows 1–7 and the first 19 terms of row 8) through p = pb (proved equal). This pins `row` completely. row_five_divisors kernel-checks the left-hand side for n = 5 against the entry's worked example. The right-hand side (the multiset of parts over Nat.Partition n) is not kernel-checked for any n. It is plain Mathlib, though, and a Python check confirms the identity under these definitions for n ≤ 25 (n ≤ 14 by enumerating the partitions directly). + +**Points for the reviewer** + +- *Note.* The conjecture is read as an equality of multisets, which is what the worked example for n = 5 says. This is stronger than the set reading, which is trivial (both sides are {1,…,n}), and implies it. So the reading is not weaker than intended. +- *Note.* Only the left-hand side has a kernel data check (n = 5). The right-hand side is Mathlib's Nat.Partition with no custom encoding, so the risk is low. +- *Note.* Metadata only: the catalog tags this partition/divisor identity as area "Discrete geometry". That does not affect fidelity. + +## A178295: A178295: collinear 4-subsets of {0,...,4}^n number 9^n/2 + 3*7^n/2 - 2*5^n (Mathar's conjecture, all three formulas) + +Verdict of the pre-review: **faithful**. Result: [oeis-a178295](../../results/oeis-a178295/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A178295.lean`](../../lean/Math0/Statements/OEIS/A178295.lean). + +**The conjecture as stated in OEIS** + +> %F A178295 Conjecture: a(n) = 9^n/2+3*7^n/2-2*5^n. a(n)= +21*a(n-1) -143*a(n-2) +315*a(n-3). G.f.: x*(-5+41*x)/((9*x-1)*(7*x-1)*(5*x-1)). [_R. J. Mathar_, May 24 2010] (Name: "Number of collinear point 4-tuples in a 5 X 5 X 5 X... n-dimensional cubic grid." Offset 0, data 0,5,64,629,5632,...) + +**The frozen Lean statement** + +```lean +def statement : Prop := + (∀ n : ℕ, (a n : ℚ) = 9 ^ n / 2 + 3 * 7 ^ n / 2 - 2 * 5 ^ n) ∧ + (∀ n : ℕ, 3 ≤ n → + (a n : ℤ) = 21 * (a (n - 1) : ℤ) - 143 * (a (n - 2) : ℤ) + 315 * (a (n - 3) : ℤ)) ∧ + PowerSeries.mk (fun n => (a n : ℚ)) = + PowerSeries.X * (-5 + 41 * PowerSeries.X) * + ((9 * PowerSeries.X - 1) * (7 * PowerSeries.X - 1) * (5 * PowerSeries.X - 1))⁻¹ + +-- dependencies +abbrev Pt (n : ℕ) := Fin n → Fin 5 +def coord {n : ℕ} (p : Pt n) (i : Fin n) : ℤ := ((p i : ℕ) : ℤ) +def Coll3 {n : ℕ} (p q r : Pt n) : Prop := + ∀ i j : Fin n, (coord q i - coord p i) * (coord r j - coord p j) = + (coord q j - coord p j) * (coord r i - coord p i) +def IsCollinear {n : ℕ} (s : Finset (Pt n)) : Prop := + ∀ p ∈ s, ∀ q ∈ s, ∀ r ∈ s, Coll3 p q r +def a (n : ℕ) : ℕ := + ((Finset.univ : Finset (Pt n)).powersetCard 4 |>.filter IsCollinear).card +``` + +**What the Lean statement says** + +Let a(n) be the number of 4-element sets of points of {0,…,4}^n that lie on one line of ℝ^n (isCollinear_iff_collinear proves the minor condition equals Mathlib's Collinear ℝ). Then three things hold. (1) For every n ≥ 0, a(n) = 9^n/2 + 3·7^n/2 − 2·5^n, computed in ℚ. (2) For every n ≥ 3, a(n) = 21a(n−1) − 143a(n−2) + 315a(n−3), computed in ℤ. (3) As formal power series over ℚ, Σ a(n)xⁿ = x(−5+41x)·((9x−1)(7x−1)(5x−1))⁻¹. The denominator has constant term −1, so the inverse is the true inverse (genFun_iff). + +**What the kernel checks against the OEIS data** + +a_data kernel-checks a(0), a(1), a(2) = 0, 5, 64 through fastA (proved equal to a). a(1) = 5 = C(5,4) rules out ordered tuples (that would give 120), and a(2) = 64 fixes collinearity in the plane. a(3) = 629 is not kernel-checked. I recomputed a(1..3) = 5, 64, 629 in Python from the Lean definition (4-subsets with vanishing minors), and they match the data. closedForm_data and recurrence_data check only the transcription of the formulas against the 10 listed terms, not a. + +**Points for the reviewer** + +- *Note.* "Point 4-tuples" is read as unordered 4-sets of distinct points. a(1) = 5 and a(2) = 64 force this reading, and a(3) = 629 matches it (checked outside the kernel). Lines meeting the grid in 4 or more points have directions in {0,±1}^n, so this reading gives exactly (9^n−5^n)/2 + 3(7^n−5^n)/2, which is the conjectured closed form. The reading matches the formula's intent. +- *Note.* The statement is the conjunction of all three formulas, so it is at least as strong as the closed form alone. There is no truncated subtraction: the closed form is over ℚ and the recurrence is over ℤ with n ≥ 3. The n = 0 case (one point, a(0) = 0) is included, consistent with offset 0. diff --git a/review/fidelity/packet-05.md b/review/fidelity/packet-05.md new file mode 100644 index 0000000..887f961 --- /dev/null +++ b/review/fidelity/packet-05.md @@ -0,0 +1,401 @@ +# Fidelity review packet 05 of 11 + +Prepared on 29 Oct 2026 by an adversarial reviewing agent, not by a person. It is meant to make a human review of these statements quick: for each one it quotes the OEIS conjecture and the frozen Lean statement, restates the Lean in plain words, and lists anything a reviewer should look at. See [the index](README.md). + +Statements in this packet: A182617, A188474, A195249, A201060, A209802, A211343, A215010, A223395, A229159, A242396. + +## A182617: The toothpick spiral around n hexagonal cells (A182617): a(n) = 2n + ceil(sqrt(12n - 3)) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a182617](../../results/oeis-a182617/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A182617.lean`](../../lean/Math0/Statements/OEIS/A182617.lean). + +**The conjecture as stated in OEIS** + +> %F A182617 Conjecture: a(n) = 2*n + ceiling(sqrt(12*n - 3)), for n > 0. - _Vincenzo Librandi_, Sep 20 2017 (Name: "Number of toothpicks in a toothpick spiral around n cells on hexagonal net." Comments: a cell is "ON" if its 6 vertices are covered by toothpicks; the walk spirals round the centre hexagon (5 edges), then steps out and goes round each successive ring; "interrupt counting the total number of toothpicks each time one of the hexagons has six vertices covered." Offset 0, a(0)=0, a(1)=5, a(2)=9, a(3)=12.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 0 < n → a n = 2 * n + ⌈Real.sqrt (12 * (n : ℝ) - 3)⌉₊ + +-- dependencies (abridged) +abbrev Pt := ℤ × ℤ +def nbrs (v : Pt) : Pt × Pt × Pt := + if (v.1 + v.2) % 2 = 0 then ((v.1 + 1, v.2), (v.1, v.2 + 1), (v.1 - 1, v.2)) + else ((v.1 + 1, v.2), (v.1 - 1, v.2), (v.1, v.2 - 1)) +def turns (p v : Pt) : Pt × Pt := + let (n0, n1, n2) := nbrs v + if p = n0 then (n2, n1) else if p = n1 then (n0, n2) else (n1, n0) +def step : List Pt → List Pt + | v :: p :: rest => let w := v :: p :: rest; let (l, r) := turns p v + if l ∉ w then l :: w else if r ∉ w then r :: w else w + | w => w +def walk : ℕ → List Pt + | 0 => [(0, 0)] + | t + 1 => step^[t] [(1, 0), (0, 0)] +def cellVerts (c : Pt) : List Pt := [(c.1, c.2), (c.1 + 1, c.2), (c.1 + 2, c.2), + (c.1, c.2 + 1), (c.1 + 1, c.2 + 1), (c.1 + 2, c.2 + 1)] +def onCells (w : List Pt) : Finset Pt := + w.toFinset.filter (fun c => (c.1 + c.2) % 2 = 0 ∧ ∀ u ∈ cellVerts c, u ∈ w) +def onCount (t : ℕ) : ℕ := (onCells (walk t)).card +def a (n : ℕ) : ℕ := + ((List.range (6 * n + 1)).find? (fun t => n ≤ onCount t)).getD (6 * n + 1) +``` + +**What the Lean statement says** + +Model the hexagonal net as the brick-wall graph on ℤ² and its hexagonal cells as 2×1 bricks. A self-avoiding walk starts with the edge (0,0)→(1,0). At each vertex it turns left if that neighbour is unvisited, and otherwise turns right. A cell is ON once all six of its vertices have been visited. a(n) is the least number t of walk edges (toothpicks) after which at least n cells are ON, with the search capped at 6n (returning 6n+1 beyond the cap). The claim is that for every n ≥ 1, a(n) = 2n + ⌈√(12n−3)⌉. statement_iff proves this equivalent to the same claim with "least t" taken with no cap. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 40 listed terms a(0..39). That covers cell rings 0–3 completely (37 cells) and the start of ring 4, which pins the walk rule, the cell model and the "least t" reading on the listed range. I also simulated the Lean walk independently in Python. It never gets stuck, it never turns two cells ON with one toothpick (so "least t with ≥ n ON" is exactly the moment the n-th cell turns ON), and it matches 2n + ⌈√(12n−3)⌉ for every 1 ≤ n ≤ 29,700. + +**Points for the reviewer** + +- *Note.* The spiral is the formalizer's operationalization of a verbal description: brick-wall coordinates plus a greedy rule ("left if unvisited, else right"). The brick faces are exactly the hexagons of the net, and the left/right turns are computed correctly from the counterclockwise neighbour order. The 40 kernel-checked terms and the simulation to n ≈ 29,700 strongly support that this is the intended spiral. A reviewer should still know that the theorem is about this explicit model, as the catalog summary says ("encoded as in Math0.Statements.A182617"). +- *Note.* The 6n search cap cannot create a spurious proof. For n ≥ 1 the conjectured value is ≤ 6n (proved in statement_iff), so a capped-out value of 6n+1 would make the statement false, not vacuously true. ⌈√(12n−3)⌉₊ is the ordinary ceiling because 12n−3 > 0 for n ≥ 1. The range n > 0 matches the conjecture. + +## A188474: The row sums of the generalized Deutsch triangle A188474 are A137398 + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a188474](../../results/oeis-a188474/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A188474.lean`](../../lean/Math0/Statements/OEIS/A188474.lean). + +**The conjecture as stated in OEIS** + +> %C A188474 Row sums are A137398(n+1) (conjecture). Diagonal sums are A188476. [_Paul Barry_, Apr 01 2011] (%F A188474 T(n,k)=sum{j=0..n-k+1, (j/(n+2-j))*C(n+2-j,n-k+1)*C(n+2-j,k+1)*2^(j-1)}. Offset 0, tabl. A137398 is now offset 1 with data 0,1,2,7,22,74,252,...; its %E: "Offset, a(15), a(18) corrected by and more terms from _Georg Fischer_, Jun 07 2021".) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, ∑ k ∈ range (n + 1), T n k = (A137398 (n + 2) : ℚ) + +-- dependencies +def T (n k : ℕ) : ℚ := + ∑ j ∈ range (n - k + 2), + (j : ℚ) / ((n : ℚ) + 2 - j) * ((n + 2 - j).choose (n - k + 1) : ℚ) * + ((n + 2 - j).choose (k + 1) : ℚ) * (2 : ℚ) ^ ((j : ℤ) - 1) +def A137398 (m : ℕ) : ℕ := + ((List.range (2 * m)).sublistsLen m).countP fun p => + let q := (List.range (2 * m)).filter (· ∉ p) + decide (0 ∈ p ∧ ∀ i < m, + ¬ ((p.set i (q.getD i 0)).Pairwise (· < ·) ∧ (q.set i (p.getD i 0)).Pairwise (· < ·))) +``` + +**What the Lean statement says** + +Let T(n,k) = Σ_{j=0}^{n−k+1} (j/(n+2−j))·C(n+2−j, n−k+1)·C(n+2−j, k+1)·2^{j−1}, computed exactly in ℚ. Let A(m) be the number of length-m subsequences p of (0,1,…,2m−1) with 0 ∈ p for which no index i < m has the following property: swapping p(i) with q(i), where q is the complementary subsequence, leaves both p and q strictly increasing. The claim is that for every n ≥ 0, Σ_{k=0}^{n} T(n,k) = A(n+2). + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 66 listed triangle terms (rows 0–10), which pins T. A137398_data kernel-checks A137398(1..6) = 0,1,2,7,22,74 from the combinatorial definition. rowSum_data kernel-checks row sums n = 0..10 = 1,2,7,…,142278, the A137398 terms from the second on, which fixes the index shift. statement_check verifies the statement for n ≤ 4. Independently, a Python brute force of the Lean A137398 definition matches the OEIS data for m ≤ 11, and the row sums of T equal A137398(n+2) (OEIS data) for every n ≤ 27. All T(n,k) are integers for n < 30. + +**Points for the reviewer** + +- *Minor.* The index is deliberately shifted from the literal "A137398(n+1)" to A137398(n+2). The reason is that A137398's offset was corrected in 2021: the old offset was 0, and the current one is 1. The listed numbers fix the shift unambiguously, since the row sums 1,2,7,22,74 are A137398's terms from the second on. The literal reading in today's offset is false at n = 0 (1 ≠ 0). This is the intended reading, but the Lean text departs from the verbatim OEIS text, so a reviewer should confirm it. +- *Note.* A137398 is encoded through its combinatorial name, reading "monotonic" as strictly increasing. Barry most likely matched the numbers or the g.f. instead. The two agree on everything checked: 6 terms in the kernel and 11 in Python. The reading of "monotonic" is forced for m ≥ 3 and fixed by a(2) = 1 at m = 2. A proof from the combinatorial definition is at least as strong as one about the numbers, so this is not weaker than intended. +- *Note.* Only the first sentence of the comment is formalized. "Diagonal sums are A188476" is the definition of A188476, not a conjecture, so excluding it is correct. There are no junk values in T: n+2−j ≥ k+1 ≥ 1 on the summation range, the natural subtraction n+2−j is exact, and 2^(j−1) with j = 0 is multiplied by j = 0. +- *Note.* Metadata only: the catalog tags this Riordan-type triangle identity as area "Discrete geometry". + +## A195249: 3 × 3 lower triangles with neighbours differing by at most two: a(n) = 1047 n - 1459 for n > 2 (A195249) + +Verdict of the pre-review: **faithful**. Result: [oeis-a195249](../../results/oeis-a195249/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A195249.lean`](../../lean/Math0/Statements/OEIS/A195249.lean). + +**The conjecture as stated in OEIS** + +> %F A195249 Empirical: a(n) = 1047*n - 1459 for n>2. [R. H. Hardin, Sep 13 2011] (Name: "Number of lower triangles of a 3 X 3 0..n array with each element differing from all of its diagonal, vertical, antidiagonal and horizontal neighbors by two or less." Offset 1. Also in %F: "Conjectures from _Colin Barker_, May 06 2018: G.f.: x*(64 + 601*x + 288*x^2 + 94*x^3) / (1 - x)^2. a(n) = 2*a(n-1) - a(n-2) for n>4.") + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n : ℕ, 2 < n → (a n : ℤ) = 1047 * n - 1459 + +-- dependencies +def cell : Fin 6 → ℕ × ℕ := ![(0, 0), (1, 0), (1, 1), (2, 0), (2, 1), (2, 2)] +def Adj (p q : ℕ × ℕ) : Prop := + p ≠ q ∧ p.1 ≤ q.1 + 1 ∧ q.1 ≤ p.1 + 1 ∧ p.2 ≤ q.2 + 1 ∧ q.2 ≤ p.2 + 1 +def near (x y : ℕ) : Prop := x ≤ y + 2 ∧ y ≤ x + 2 +def Valid (v : Fin 6 → ℕ) : Prop := ∀ i j : Fin 6, Adj (cell i) (cell j) → near (v i) (v j) +def a (n : ℕ) : ℕ := + ∑ x0 ∈ range (n + 1), ∑ x1 ∈ range (n + 1), ∑ x2 ∈ range (n + 1), ∑ x3 ∈ range (n + 1), + ∑ x4 ∈ range (n + 1), ∑ x5 ∈ range (n + 1), if Valid ![x0, x1, x2, x3, x4, x5] then 1 else 0 +(Barker's g.f. and recurrence are separate defs statementBarkerGF / statementBarkerRec, not part of `statement`.) +``` + +**What the Lean statement says** + +Fill the six cells (i,j), j ≤ i < 3, of the lower triangle of a 3×3 array with integers in {0,…,n}. Call a filling valid if any two distinct cells whose row indices and column indices each differ by at most 1 (king-adjacent) hold entries differing by at most 2. The claim is that for every n ≥ 3, the number of valid fillings is 1047n − 1459, as an equality in ℤ. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 38 listed terms a(1..38) through the pruned evaluator aL (proved equal to a). a_small evaluates a(1) = 64 and a(2) = 729 directly from the definition. image_cell and cell_injective confirm the six positions, and valid_iff makes the ten adjacent pairs explicit. Thirty-six of the checked terms lie in the range n > 2, so any other adjacency or triangle shape would show up as a different slope or intercept. The definitions are pinned. + +**Points for the reviewer** + +- *Note.* Only Hardin's formula is in `statement`. Barker's g.f. and recurrence are recorded as separate Props. Both follow from Hardin's formula together with a(1) = 64 and a(2) = 729, which are kernel-checked (the g.f. coefficients give 64, 729, 1682, 2729, then slope 1047). Settling `statement` therefore leaves no part of the entry's conjectural content unsettled. +- *Note.* Only adjacencies inside the triangle are constrained, which is the natural reading of counting "lower triangles". The range n > 2 and the integer target 1047n − 1459 in ℤ match the text exactly, with no truncated subtraction. + +## A201060: Repdigits with repdigit digital product are repunits from a(16) = 1111 on (A201060) + +Verdict of the pre-review: **faithful**. Result: [oeis-a201060](../../results/oeis-a201060/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A201060.lean`](../../lean/Math0/Statements/OEIS/A201060.lean). + +**The conjecture as stated in OEIS** + +> %C A201060 Conjecture: a(n) is repunit for n >= 16. (_Jaroslav Krizek_, Nov 26 2011). Name: "Repdigit numbers with repdigit digital product." Offset 1; data 0,1,2,...,9,11,22,33,111,222,1111,11111,...,1111111111111111111 (31 terms). Local mirror (#11, Mar 30 2012) is identical to oeisdata main. + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n : ℕ, 16 ≤ n → IsRepunit (a n) + +where +def IsRepdigit (m : ℕ) : Prop := ∀ x ∈ Nat.digits 10 m, ∀ y ∈ Nat.digits 10 m, x = y +def digitProd (m : ℕ) : ℕ := if m = 0 then 0 else (Nat.digits 10 m).prod +def IsTerm (m : ℕ) : Prop := IsRepdigit m ∧ IsRepdigit (digitProd m) +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) +def IsRepunit (m : ℕ) : Prop := ∀ d ∈ Nat.digits 10 m, d = 1 +``` + +**What the Lean statement says** + +List, in increasing order and starting at index 1, the natural numbers m (0 included) all of whose decimal digits are equal and whose product of decimal digits (taken to be 0 for m = 0) also has all decimal digits equal. Then for every index n >= 16, the n-th number in this list has all decimal digits equal to 1. + +**What the kernel checks against the OEIS data** + +a_data checks all 31 listed terms a(1..31) in the kernel. It shows that the repdigits below 10^19 are exactly 0 and rep d k (isRepdigit_iff_mem_repList), filters them, and transfers the result to Nat.nth (map_nth_eq_of_filter). infinite_isTerm proves the set is infinite, so Nat.nth is the genuine increasing enumeration. The check confirms the offset (a 1 = 0, a 16 = 1111), that 0 counts as a repdigit, and the digit-product convention. IsRepunit is not data-checked, but it is a direct transcription. + +**Points for the reviewer** + +- *Note.* digitProd 0 = 0, not the empty product 1. Both values are repdigits, so the sequence does not change, and a_data confirms a(1) = 0. +- *Note.* IsRepunit 0 holds vacuously because Nat.digits 10 0 = []. This cannot matter: a n >= a 16 = 1111 for n >= 16, and a is strictly increasing because the set is infinite. +- *Note.* Since every repunit is a term, the statement amounts to saying that no repdigit d...d (2 <= d <= 9) with >= 4 digits has a repdigit digit product d^k. That is the intended content, and the Lean statement is exactly 'all terms from index 16 on are repunits', with no extra hypotheses. + +## A209802: Positivity of the exponential Mertens function (A209802) + +Verdict of the pre-review: **faithful**. Result: [oeis-a209802](../../results/oeis-a209802/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A209802.lean`](../../lean/Math0/Statements/OEIS/A209802.lean). + +**The conjecture as stated in OEIS** + +> %C A209802 Analog of Mertens's function, A002321; conjecture: a(n) > 0. [_Reinhard Zumkeller_, Mar 13 2012; %N Partial sums of exponential Möbius function, A166234; %O 1,2. A166234: Multiplicative, a(p^e) = mu(e) for any prime power p^e (e>=1)] + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n : ℕ, 1 ≤ n → 0 < a n + +where +def muE (n : ℕ) : ℤ := n.factorization.prod fun _ e => moebius e +def a (n : ℕ) : ℤ := ∑ k ∈ Icc 1 n, muE k +``` + +**What the Lean statement says** + +Let mu_e be the multiplicative function with mu_e(p^e) = mu(e) for every prime power p^e with e >= 1, so mu_e(1) = 1. Then for every n >= 1, the partial sum mu_e(1) + ... + mu_e(n) is strictly positive. + +**What the kernel checks against the OEIS data** + +muE_data checks the 91 listed terms of A166234. a_data checks all 72 listed terms of A209802, and a_ten_hundred checks a(10) = 4 and a(100) = 34 from the Greathouse comment. All run by decide +kernel through a trial-division copy aC that is proved equal to a (a_eq_aC), so the checks apply to the frozen definition itself. The muE data include the zero value at 16 = 2^4 (mu(4) = 0) and negative values at squares, so mu applied to exponents is pinned. + +**Points for the reviewer** + +- *Note.* a is Z-valued, so there is no truncation, and the empty sum a 0 = 0 is excluded by 1 <= n, matching offset 1. muE 0 = 1 is junk but is never used, since the sum runs over Icc 1 n. The statement is exactly 'a(n) > 0 for every term'. + +## A211343: A211343: positive entries are smallest parts of consecutive-part partitions; last positive column is A109814(n) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a211343](../../results/oeis-a211343/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A211343.lean`](../../lean/Math0/Statements/OEIS/A211343.lean). + +**The conjecture as stated in OEIS** + +> %C A211343 From _Omar E. Pol_, Apr 30 2017: (Start) Conjecture 1: T(n,k) is the smallest part of the partition of n into k consecutive parts, if T(n,k) > 0. Conjecture 2: the last positive integer in the row n is in the column A109814(n). (End). Name: "Triangle read by rows: T(n,k), n >= 1, k >= 1, in which column k lists the positive integers interleaved with k-1 zeros, and the first element of column k is in row k(k+1)/2." A109814: "a(n) is the largest k such that n can be written as sum of k consecutive positive integers." + +**The frozen Lean statement** + +```lean +def statement : Prop := + (∀ n k : ℕ, 1 ≤ n → InRow n k → 0 < T n k → + (∃ p : n.Partition, HasConsecutiveParts k p) ∧ + ∀ p : n.Partition, HasConsecutiveParts k p → IsLeast {x | x ∈ p.parts} (T n k)) ∧ + (∀ n : ℕ, 1 ≤ n → IsGreatest {k | InRow n k ∧ 0 < T n k} (A109814 n)) + +where +def column (k j : ℕ) : ℕ := if j % k = 0 then j / k + 1 else 0 +def InRow (n k : ℕ) : Prop := 1 ≤ k ∧ k * (k + 1) / 2 ≤ n +def T (n k : ℕ) : ℕ := if InRow n k then column k (n - k * (k + 1) / 2) else 0 +def HasConsecutiveParts {n : ℕ} (k : ℕ) (p : n.Partition) : Prop := + ∃ m, p.parts = (Multiset.range k).map (fun i => m + i) +def IsConsecSumBdd (n k : ℕ) : Prop := ∃ m ∈ Finset.Icc 1 n, ∑ i ∈ Finset.range k, (m + i) = n +def A109814 (n : ℕ) : ℕ := Nat.findGreatest (IsConsecSumBdd n) n +``` + +**What the Lean statement says** + +Let T(n,k), for k >= 1 and k(k+1)/2 <= n, be ((n - k(k+1)/2)/k) + 1 when k divides n - k(k+1)/2, and 0 otherwise. (1) For every n >= 1 and every such k with T(n,k) > 0, n has a partition into the k consecutive parts m, m+1, ..., m+k-1, and T(n,k) is the smallest part of every such partition. (2) For every n >= 1, the largest k with k(k+1)/2 <= n and T(n,k) > 0 equals A109814(n), the largest k such that n is a sum of k consecutive positive integers. + +**What the kernel checks against the OEIS data** + +a_data checks all 94 listed terms (rows 1..24) of the flattened triangle in the kernel, and row_data checks the same rows row by row against the %e example. A109814_data checks the first 40 listed A109814 terms. A109814_isGreatest proves that, for n >= 1, the bounded findGreatest equals the unbounded OEIS definition. Together these pin down T (including column start rows and zero interleaving) and A109814. HasConsecutiveParts is not data-checked, but it is a direct transcription; positivity of parts comes from Nat.Partition. + +**Points for the reviewer** + +- *Note.* Conjecture 1 is encoded only in the stated direction: T(n,k) > 0 implies a k-consecutive-part partition exists with smallest part T(n,k). The converse (T(n,k) = 0 implies no such partition) is not claimed. This follows the wording 'if T(n,k) > 0'. +- *Note.* 'The partition' is read as existence plus 'every such partition has smallest part T(n,k)'. This is equivalent to the uniqueness-flavoured reading, because a partition into k consecutive parts is determined by n and k. +- *Note.* Conjecture 2 is read as 'A109814(n) is the greatest column of row n with a positive entry'. That matches 'the last positive integer in the row n is in the column A109814(n)'. T's junk value 0 outside the triangle is never used, because InRow is required everywhere. + +## A215010: An equiangular decagon with sides in arithmetic progression (A215010) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a215010](../../results/oeis-a215010/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A215010.lean`](../../lean/Math0/Statements/OEIS/A215010.lean). + +**The conjecture as stated in OEIS** + +> %C A215010 Conjecture: hexagons are the only simple convex polygons with equal interior angles with such property, due to the fact that cos(Pi/3) = 1/2. [_Robin Garcia_, Jul 31 2012; %N Integer side lengths in arithmetic progression of simple convex hexagons with equal interior angles. Sequence gives the values of m for sides of lengths t+m*d, counterclockwise, for the two primitive solutions. %e t = d = 1 gives (1, 6, 2, 4, 3, 5) and (1, 6, 3, 2, 5, 4)] + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ (N t d : ℕ), 1 ≤ d → ∀ σ : Equiv.Perm (Fin N), + IsEquiangularPolygon N (fun k => t + (σ k : ℕ) * d) → N = 6 + +where +noncomputable def edgeDir (N k : ℕ) : ℂ := Complex.exp (2 * Real.pi * Complex.I * k / N) +def IsEquiangularPolygon (N : ℕ) (s : Fin N → ℕ) : Prop := + 3 ≤ N ∧ (∀ k, 0 < s k) ∧ ∑ k : Fin N, (s k : ℂ) * edgeDir N k = 0 +``` + +**What the Lean statement says** + +Suppose N >= 3, t >= 0 and d >= 1 are integers, and the N numbers t, t+d, ..., t+(N-1)d, all positive, are arranged in some order as consecutive side lengths s_0, ..., s_{N-1}. If the edge vectors s_k * exp(2*pi*i*k/N) sum to zero, so that these sides close up into an equiangular convex N-gon, then N = 6. + +**What the kernel checks against the OEIS data** + +a_data checks all 12 listed terms by computing the closing orderings m of 0..5 for N = 6 (via hexCloses), keeping those in the normal form m0 = 0, m1 > m5, in lexicographic order. primitiveSolutions_length shows there are exactly 2. hexCloses_iff proves that hexCloses is equivalent to the closing condition of IsEquiangularPolygon at N = 6, and an example checks the entry's hexagon (1,6,2,4,3,5) against IsEquiangularPolygon. The data therefore pin the N = 6 case of the polygon predicate and the reading 'm is a permutation of 0..N-1'. They do not test the predicate for N != 6, the case the refutation uses (N = 10). The general-N predicate is the standard characterization, justified in the docstring but not proved in the file. + +**Points for the reviewer** + +- *Minor.* 'Simple convex polygon with equal interior angles' is encoded through the edge-vector characterization: positive sides, sum of s_k * zeta^k = 0, zeta = exp(2*pi*i/N), N >= 3. It is not encoded as a geometric definition. The refutation needs only the direction 'predicate implies a genuine polygon', and that direction holds: positive sides whose direction turns by 2*pi/N at each vertex, with total turning 2*pi, form a strictly convex simple polygon with every interior angle (N-2)*pi/N. The data check validates the predicate only at N = 6. I numerically confirmed the decagon witness (1,4,5,8,9,2,3,6,7,10) used by the result: |sum| ~ 5e-15. +- *Note.* 'Such property' is read as: the side lengths are the N terms t + m*d, m = 0..N-1, of an integer arithmetic progression, in some order. The entry's own m-lists (permutations of 0..5) support this reading. Requiring the sides in progression order would make the property impossible for every N, so that reading cannot be the intended one. d >= 1 rightly excludes d = 0, under which regular polygons would make the conjecture trivially false and a refutation vacuous. Negative d is equivalent to reading the polygon in the other direction, and t >= 1 is forced by positivity. Restricting to natural t and d only narrows the universal claim, so a counterexample in N also refutes the integer version. +- *Note.* The refuting witness (N = 10, t = d = 1, sides a permutation of 1..10) lies squarely inside the author's setting. The known theorem (Ball 2002; Woeginger, Amer. Math. Monthly 2013; OEIS A118887) says such polygons exist exactly when N has at least two distinct prime factors. So the result refutes the conjecture as meant, not some degenerate reading. + +## A223395: A223395: walks on the 4 x 4 grid graph satisfy Hardin's recurrence, Barker's g.f. and closed form + +Verdict of the pre-review: **faithful**. Result: [oeis-a223395](../../results/oeis-a223395/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A223395.lean`](../../lean/Math0/Statements/OEIS/A223395.lean). + +**The conjecture as stated in OEIS** + +> %F A223395 Empirical: a(n) = 3*a(n-1) + 2*a(n-2) - 4*a(n-3). (R. H. Hardin, Mar 19 2013) %F A223395 Conjectures from _Colin Barker_, Aug 20 2018: (Start) G.f.: 8*x*(2 - 3*x^2) / ((1 - x)*(1 - 2*x - 4*x^2)). a(n) = (8 + (11-5*sqrt(5))*(1-sqrt(5))^n + (1+sqrt(5))^n*(11+5*sqrt(5))) / 5. (End). Name: "4 X 4 square grid graph coloring a rectangular array: number of n X 1 0..15 arrays where 0..15 label nodes of the square grid graph and every array movement to a horizontal or vertical neighbor moves along an edge of this graph." Offset 1. + +**The frozen Lean statement** + +```lean +def statementRec : Prop := + ∀ n : ℕ, 4 ≤ n → (a n : ℤ) = 3 * a (n - 1) + 2 * a (n - 2) - 4 * a (n - 3) +def statementGF : Prop := + (1 - PowerSeries.X) * (1 - 2 * PowerSeries.X - 4 * PowerSeries.X ^ 2) * + PowerSeries.mk (fun n => if n = 0 then (0 : ℤ) else a n) = + 8 * PowerSeries.X * (2 - 3 * PowerSeries.X ^ 2) +def statementClosedForm : Prop := + ∀ n : ℕ, 1 ≤ n → (a n : ℝ) = + (8 + (11 - 5 * Real.sqrt 5) * (1 - Real.sqrt 5) ^ n + + (1 + Real.sqrt 5) ^ n * (11 + 5 * Real.sqrt 5)) / 5 +def statement : Prop := statementRec ∧ statementGF ∧ statementClosedForm + +where +def Adj (i j : Fin 16) : Prop := + (i.val / 4 = j.val / 4 ∧ (i.val % 4 + 1 = j.val % 4 ∨ j.val % 4 + 1 = i.val % 4)) ∨ + (i.val % 4 = j.val % 4 ∧ (i.val / 4 + 1 = j.val / 4 ∨ j.val / 4 + 1 = i.val / 4)) +def Valid {n : ℕ} (f : Fin n → Fin 16) : Prop := ∀ i j : Fin n, i.val + 1 = j.val → Adj (f i) (f j) +def a (n : ℕ) : ℕ := Fintype.card {f : Fin n → Fin 16 // Valid f} +``` + +**What the Lean statement says** + +Let a(n) be the number of sequences of n nodes of the 4x4 grid graph in which each pair of consecutive nodes is joined by an edge (that is, walks with n vertices). Then (i) a(n) = 3a(n-1) + 2a(n-2) - 4a(n-3) for every n >= 4. (ii) In Z[[x]], (1-x)(1-2x-4x^2) * sum_{n>=1} a(n) x^n = 8x(2-3x^2). (iii) a(n) = (8 + (11-5√5)(1-√5)^n + (1+√5)^n(11+5√5))/5 for every n >= 1. + +**What the kernel checks against the OEIS data** + +adj_iff_entry checks in the kernel that Adj equals the neighbour list printed in the entry's EXAMPLE section (so the graph has no loops and the labelling matches). a_data checks all 24 listed terms a(1..24) through the transfer-matrix version aL, which a_eq_ancomputes is proved equal to a for every n (a_eq_aL). a(1)=16 and a(2)=48 confirm that loops are excluded and walks are directed. The definitions are fully pinned down. + +**Points for the reviewer** + +- *Note.* Hardin's recurrence gives no range. The Lean statement takes n >= 4, the first n for which a(n-3) is a term at offset 1. Natural-number subtraction is safe here, and the identity is stated in Z. +- *Note.* The g.f. is read as sum_{n>=1} a(n) x^n, masking the junk a 0 = 1. The denominator is cleared, which is an equivalent form since its constant term is 1, making it a unit in Z[[x]]. The coefficients match Barker's text exactly. +- *Note.* statement is the conjunction of all three claims, which is the strongest reading. Given the 24 checked terms, the three are mutually equivalent, so a proof settles each one. + +## A229159: Every odd prime is a side of a Heronian triangle (A229159) + +Verdict of the pre-review: **faithful**. Result: [oeis-a229159](../../results/oeis-a229159/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A229159.lean`](../../lean/Math0/Statements/OEIS/A229159.lean). + +**The conjecture as stated in OEIS** + +> %C A229159 "Conjecture: for all prime p > 2 there exists an integer-sided triangle with integer area where at least one side is of length p." (_Michel Lagneau_, Sep 17 2013; entry name: "Smallest integer areas of integer-sided triangles where at least one side is of length prime(n).", offset 1, a(1)=0) + +**The frozen Lean statement** + +```lean +def IsIntTriangle (x y z A : ℕ) : Prop := + x < y + z ∧ y < x + z ∧ z < x + y ∧ + 16 * (A : ℤ) ^ 2 = + ((x : ℤ) + y + z) * (-(x : ℤ) + y + z) * ((x : ℤ) - y + z) * ((x : ℤ) + y - z) + +def statement : Prop := + ∀ p : ℕ, p.Prime → 2 < p → + ∃ x y z A : ℕ, IsIntTriangle x y z A ∧ (x = p ∨ y = p ∨ z = p) + +(Auxiliary, not used by statement: areas m = {A | ∃ x y z, IsIntTriangle x y z A ∧ (x = m ∨ y = m ∨ z = m)}, prime n = Nat.nth Nat.Prime (n - 1), a n = sInf (areas (prime n)).) +``` + +**What the Lean statement says** + +For every prime p > 2 there are natural numbers x, y, z, A such that x, y, z satisfy the strict triangle inequalities (a non-degenerate triangle, so all sides are at least 1), the Heron identity 16A^2 = (x+y+z)(-x+y+z)(x-y+z)(x+y-z) holds over the integers (that is, the area is the natural number A), and one of x, y, z equals p. + +**What the kernel checks against the OEIS data** + +a_one proves a(1) = 0 by hand (no Heronian triangle has a side of length 2). table_ok/a_table/a_data kernel-check a(1..19) = 0, 6, 6, 42, 66, 24, 36, 114, 966, 60, 930, 114, 126, 1290, 4230, 90, 1770, 330, 2814. Each value has a witness triangle and a certified exhaustive lower-bound search (lbCheck, proved sound by scan_spec/lbCheck_spec), so the check really determines the minimum. oeis_errata proves a(20) ≤ 11928, a(25) ≤ 396, a(29) ≤ 330, a(32) ≤ 6288 and a(40) ≤ 2970, all below the listed values. These checks run through `a`, which is built from the same IsIntTriangle the statement uses, so they pin down the triangle/area predicate, including the exclusion of degenerate triangles that a(1) = 0 requires. The statement itself does not mention `a`. + +**Points for the reviewer** + +- *Note.* The conjecture is a pure existence claim and the Lean statement matches it exactly: the same quantifier, the same range p > 2, and 'at least one side' encoded as x = p ∨ y = p ∨ z = p. Requiring non-degenerate triangles agrees with the entry's a(1) = 0. Dropping that requirement would not change the content, since (p, p, 2p) would then also satisfy the claim trivially. +- *Note.* The claim follows at once from the classical right triangle (p, (p^2-1)/2, (p^2+1)/2), whose area p(p^2-1)/4 is an integer for odd p. The catalogue correctly classes it as a known result. +- *Note.* Several listed OEIS terms (a(20), a(25), a(29), a(32), a(40)) are not minimal: the Maple program only searches sides up to 500 and returns the first triangle it finds. This affects the listed data only, not the conjecture, and it is why the kernel data check stops at n = 19. + +## A242396: Stephan's conjectured g.f. for A242396 is false (first failure at n = 97) + +Verdict of the pre-review: **faithful**. Result: [oeis-a242396](../../results/oeis-a242396/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A242396.lean`](../../lean/Math0/Statements/OEIS/A242396.lean). + +**The conjecture as stated in OEIS** + +> %F A242396 G.f., conjectured: (-2*x^14 + 4*x^13 + 2*x^12 + 2*x^11 + 2*x^10 + 2*x^9 + 2*x^8 + 4*x^7 + 2*x^6 + 2*x^5 + 2*x^4 + 2*x^3 + 2*x^2 + 4*x)/(x^14 - x^13 - x + 1). - _Ralf Stephan_, May 18 2014. (Also: %F Asymptotics from g.f.: a(n) ~ 30/13 * n. - _Ralf Stephan_, May 18 2014.) Name: "Number of rows of equilateral triangles (sides length = 1) that intersect the circumference of a circle of radius n centered at (0,0) or (1/2,0)." Offset 1. Author's Small Basic program: r6 = n*sin(30°)/(√3/2); a = 4*round(r6) if frac(r6) > 0.5 else 2*(2*round(r6)+1). + +**The frozen Lean statement** + +```lean +open PowerSeries in +def statement : Prop := + PowerSeries.mk (fun n => if n = 0 then (0 : ℤ) else a n) * (X ^ 14 - X ^ 13 - X + 1) = + -2 * X ^ 14 + 4 * X ^ 13 + 2 * X ^ 12 + 2 * X ^ 11 + 2 * X ^ 10 + 2 * X ^ 9 + 2 * X ^ 8 + + 4 * X ^ 7 + 2 * X ^ 6 + 2 * X ^ 5 + 2 * X ^ 4 + 2 * X ^ 3 + 2 * X ^ 2 + 4 * X + +where +def RowMeets (c : ℝ) (n : ℕ) (j : ℤ) : Prop := + ∃ x y : ℝ, (x - c) ^ 2 + y ^ 2 = (n : ℝ) ^ 2 ∧ (j : ℝ) * (√3 / 2) ≤ y ∧ y ≤ ((j : ℝ) + 1) * (√3 / 2) +def MeetsInt (n : ℕ) (j : ℤ) : Prop := + (j ≤ 0 ∨ 3 * j ^ 2 ≤ 4 * (n : ℤ) ^ 2) ∧ (0 ≤ j + 1 ∨ 3 * (j + 1) ^ 2 ≤ 4 * (n : ℤ) ^ 2) +def a (n : ℕ) : ℕ := + ((Finset.range (4 * n + 5)).filter (fun i : ℕ => MeetsInt n ((i : ℤ) - (2 * n + 2)))).card +-- theorem a_eq_ncard (c : ℝ) (n : ℕ) : a n = {j : ℤ | RowMeets c n j}.ncard +-- (statement_asymptotic, a(n) ~ 30/13 n, is defined separately and is NOT part of statement) +``` + +**What the Lean statement says** + +Let a(n) be the number of integers j such that the closed horizontal strip j·√3/2 <= y <= (j+1)·√3/2 meets the circle of radius n centred on the x-axis. a_eq_ncard proves this count is independent of the centre's x-coordinate, and it equals 2⌊2n/√3⌋ + 2. The statement asserts the power-series identity (sum_{n>=1} a(n) x^n)·(x^14 - x^13 - x + 1) = -2x^14 + 4x^13 + 2x^12 + ... + 2x^2 + 4x in Z[[x]], which is equivalent to sum a(n) x^n = N(x)/D(x). The result proves this identity false. + +**What the kernel checks against the OEIS data** + +a_data checks all 61 listed terms a(1..61) in the kernel. a_eq_ncard proves that a n is the number of rows of the closed strip tiling that meet the circle centred at (c,0), for every real c (so for both (0,0) and (1/2,0)). The data does not reach the refuting index: the g.f. fits all 61 terms, and the first failure is at n = 97, where a(97) = 226 and the g.f. predicts 224. So fidelity beyond the data rests on the definition itself. I checked independently that the Lean count equals 2⌊2n/√3⌋+2 and equals the author's Small Basic program for every n (algebraically; numerically for n <= 399 with no mismatch), and that the g.f. coefficients first disagree at n = 97 (then 110, 123, ...). + +**Points for the reviewer** + +- *Note.* The refutation is at n = 97, beyond the 61 data terms, so the data check alone cannot pin it down. It does not depend on a Lean-only artefact, however: the Lean a(n) = 2⌊2n/√3⌋+2 coincides for every n with the author's own program (4·round(n/√3) if frac(n/√3) > 1/2, else 4·round(n/√3)+2). The values at n = 83, 84, 96, 97 are far from any floating-point rounding threshold (2·84/√3 = 96.995, 2·97/√3 = 112.006). +- *Note.* The geometric choices are fixed by the program and the sibling entries A242394/A242395: horizontal rows of height √3/2 with a boundary line through the centre, and closed strips. Closed vs open strips is immaterial for n >= 1 because 2n/√3 is irrational (no tangency). The centre ambiguity '(0,0) or (1/2,0)' is harmless, since the count is proved independent of the centre's x-coordinate. +- *Note.* Only the g.f. is formalized in statement. The derived claim 'a(n) ~ 30/13 n' is recorded separately as statement_asymptotic and is not refuted by the result. It is also false, since a(n) ~ (4/√3) n ≈ 2.3094 n versus 30/13 ≈ 2.3077, but it is a consequence of the g.f. rather than a separate conjecture. +- *Note.* The g.f. is read with offset 1 (sum_{n>=1} a(n) x^n, junk a 0 = 2 masked). The numerator is divisible by x and reproduces a(1) = 4, so this reading is correct. Clearing the denominator (constant term 1, a unit in Z[[x]]) is equivalent. In any case the true sequence is not eventually of the form a(n+13) = a(n) + 30 under any offset. diff --git a/review/fidelity/packet-06.md b/review/fidelity/packet-06.md new file mode 100644 index 0000000..60527fb --- /dev/null +++ b/review/fidelity/packet-06.md @@ -0,0 +1,425 @@ +# Fidelity review packet 06 of 11 + +Prepared on 29 Oct 2026 by an adversarial reviewing agent, not by a person. It is meant to make a human review of these statements quick: for each one it quotes the OEIS conjecture and the frozen Lean statement, restates the Lean in plain words, and lists anything a reviewer should look at. See [the index](README.md). + +Statements in this packet: A249434, A262957, A265210, A265649, A267486, A270668, A275815, A278212, A281000, A294512. + +## A249434: A249151(k) = k exactly when k + 1 is prime (Karttunen's conjecture, A249434/A249151) + +Verdict of the pre-review: **faithful**. Result: [oeis-a249434](../../results/oeis-a249434/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A249434.lean`](../../lean/Math0/Statements/OEIS/A249434.lean). + +**The conjecture as stated in OEIS** + +> %C A249434 It seems that A006093 gives all those k for which A249151(k) = k. If that is true, then this is a disjoint union of A006093 and A249429. (_Antti Karttunen_, Nov 02 2014). Also %Y A249434 Subsequences: A006093 (conjectured), A249429, ...; and in A249151: "A006093 seems to give all such k, that a(k) = k." A249151 (offset 0): "Largest m such that m! divides the product of elements on row n of Pascal's triangle". A006093: a(n) = prime(n) - 1. A249429: n with A249151(n) > n. + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ k : ℕ, IsGreatest {m : ℕ | m ! ∣ rowProd k} k ↔ (k + 1).Prime + +where +def rowProd (n : ℕ) : ℕ := ∏ j ∈ range (n + 1), n.choose j +-- theorem statement_iff : statement ↔ ∀ k : ℕ, A249151 k = k ↔ (k + 1).Prime +-- def A249151 (n : ℕ) : ℕ := lastFact (rowProd n) (rowProd n) 0 (A249151_isGreatest: it is the greatest m with m! ∣ rowProd n) +``` + +**What the Lean statement says** + +For every natural number k >= 0, k is the largest m such that m! divides the product C(k,0)·C(k,1)·...·C(k,k) if and only if k+1 is prime. In other words, the fixed points of A249151 are exactly the numbers p-1 with p prime. + +**What the kernel checks against the OEIS data** + +a_data checks all 81 listed A249434 terms (a(1..81), all terms <= 256) in the kernel, using a proved recurrence for rowProd. A249151_data checks the first 81 terms of A249151, which pins down rowProd and the 'largest m' notion (A249151_isGreatest, A249151_eq_iff). A006093 is encoded as {k | (k+1).Prime}, which is definitional. I also checked numerically that the iff holds for k < 200. + +**Points for the reviewer** + +- *Note.* 'A006093 gives all those k for which A249151(k) = k' is read as the set equality {k | A249151(k) = k} = A006093 (both inclusions). A purely literal reading could be just {fixed points} ⊆ A006093. The two-sided reading is what the author meant: the follow-up 'disjoint union of A006093 and A249429' (A249434 = {A249151 >= k}, A249429 = {A249151 > k}) and the %Y 'Subsequences: A006093 (conjectured)' both need A006093 ⊆ {fixed points}. The Lean statement is the stronger form, so the proof settles either reading. +- *Note.* k = 0 is included. A249151(0) = 1 ≠ 0 and 1 is not prime, so k = 0 satisfies both sides consistently. 0 belongs to A249429, not A006093, which matches. + +## A262957: A262957: Israel's b(n), c(n) are coprime integers and a(n) = b(n) + +Verdict of the pre-review: **faithful**. Result: [oeis-a262957](../../results/oeis-a262957/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A262957.lean`](../../lean/Math0/Statements/OEIS/A262957.lean). + +**The conjecture as stated in OEIS** + +> %C A262957 From _Robert Israel_, Dec 22 2015: (Start) +> a(n) is the numerator of b(n)/c(n) where +> b(1) = 2, b(2) = 3, c(1) = 3, c(2) = 5, +> b(n+1) = (((-1)^n*(n-1)+n*(n+2))*b(n) - (1+(-1)^n*(n+1))*b(n-1))/(n-(-1)^n), +> c(n+1) = (((-1)^n*(n-1)+n*(n+2))*c(n) - (1+(-1)^n*(n+1))*c(n-1))/(n-(-1)^n). +> Conjecture: b(n) and c(n) are coprime for all n, so that a(n) = b(n). +> I have verified this for n <= 10000. (End) +> [Entry: "Numerators of the n-th iteration of the alternating continued fraction formed from the positive integers, starting with (1 - ...)", offset 1, _Mohamed Sabba_, Nov 19 2015; examples 1-1/(2+1)=2/3, 1-1/(2+1/(3-1))=3/5, ... Mirror rev #80 (Mar 04 2025) is identical to current GitHub oeisdata.] + +**The frozen Lean statement** + +```lean +def cf (n : ℕ) : ℚ := + (List.range' 1 (n + 1)).foldr (fun (k : ℕ) (t : ℚ) => (k : ℚ) + (-1) ^ k / t) 1 +def a (n : ℕ) : ℕ := (cf n).num.natAbs +def step (m : ℕ) (u v : ℚ) : ℚ := + (((-1) ^ m * ((m : ℚ) - 1) + (m : ℚ) * ((m : ℚ) + 2)) * v + - (1 + (-1) ^ m * ((m : ℚ) + 1)) * u) / ((m : ℚ) - (-1) ^ m) +def israelPair (x₁ x₂ : ℚ) : ℕ → ℚ × ℚ + | 0 => (x₁, x₂) + | n + 1 => let p := israelPair x₁ x₂ n; (p.2, step (n + 2) p.1 p.2) +def b (n : ℕ) : ℚ := (israelPair 2 3 (n - 1)).1 +def c (n : ℕ) : ℚ := (israelPair 3 5 (n - 1)).1 + +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + ∃ p q : ℤ, b n = (p : ℚ) ∧ c n = (q : ℚ) ∧ Int.gcd p q = 1 ∧ + ((a n : ℕ) : ℚ) = b n +``` + +**What the Lean statement says** + +Let cf(n) be the rational number 1 - 1/(2 + 1/(3 - 1/(4 + ... (n+1) + (-1)^(n+1)/1))), using the integers 1..n+1, the sign after k being (-1)^k and the innermost tail 1, and let a(n) be |numerator| of cf(n) in lowest terms. Let b, c be the rational sequences with b(1)=2, b(2)=3, c(1)=3, c(2)=5 and, for m >= 2, x(m+1) = ((( -1)^m (m-1) + m(m+2)) x(m) - (1 + (-1)^m (m+1)) x(m-1)) / (m - (-1)^m). Claim: for every n >= 1, b(n) and c(n) are integers, gcd(b(n), c(n)) = 1, and a(n) = b(n). + +**What the kernel checks against the OEIS data** + +a_data: a(1..22) equal all 22 listed terms (decide +kernel), which pins cf (the continued fraction with integers 1..n+1, alternating signs, inner tail 1) to the entry's examples and PARI program. bc_data: (b(n), c(n)) for n = 1..6 equal (2,3),(3,5),(19,33),(64,111),(538,933),(2833,4913), i.e. the first terms of A262957/A263295, checking the indexing of the recurrence (x(m+1) = step m x(m-1) x(m), applied for m >= 2). b and c are literal transcriptions of the displayed recurrence, so the data check is adequate. I also checked independently (exact rationals) for n < 300 that b, c are integers, coprime, a(n) = b(n), and cf(n) = b(n)/c(n). + +**Points for the reviewer** + +- *Note.* Integrality of b(n), c(n) is asserted explicitly (the recurrence divides, so the terms are a priori rational). This is implicit in calling them coprime, and it makes the statement stronger, not weaker. +- *Note.* The statement asserts coprimality and the stated consequence a(n) = b(n), but not Israel's premise cf(n) = b(n)/c(n) (equivalently c(n) = A263295(n)). Because b and c are defined literally by the recurrence, the coprimality claim is exactly Israel's conjecture. The premise itself is outside the conjecture sentence. It holds numerically for n < 300. +- *Note.* Range n >= 1 matches the recurrence's indexing. The junk values b 0, c 0 are never used. The divisor m - (-1)^m is nonzero for every m >= 2 where the step is applied, and every intermediate value of cf is >= 1, so Lean's x/0 = 0 never intervenes. + +## A265210: Ternary digits of 2^n: column k has least period 2*3^(k-1) and balanced digits for k ≥ 2 + +Verdict of the pre-review: **faithful**. Result: [oeis-a265210](../../results/oeis-a265210/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A265210.lean`](../../lean/Math0/Statements/OEIS/A265210.lean). + +**The conjecture as stated in OEIS** + +> %C A265210 Conjecture 1: The sequence in column k is periodic, with period p(k) = 2*3^(k-1) = A008776(k-1), k >= 1, and in which the numbers 0,1,2 appear with equal frequency, for each k>1. +> [Entry: "Irregular triangle read by rows in which row n lists the base 3 digits of 2^n in reverse order, n >= 0.", offset 0, _L. Edson Jeffery_, Dec 04 2015; rev #18, unchanged on GitHub.] + +**The frozen Lean statement** + +```lean +def row (n : ℕ) : List ℕ := Nat.digits 3 (2 ^ n) +def T (n k : ℕ) : ℕ := (row n).getD (k - 1) 0 +def IsColPeriod (k q : ℕ) : Prop := + ∀ n : ℕ, k ≤ (row n).length → T (n + q) k = T n k +def p (k : ℕ) : ℕ := 2 * 3 ^ (k - 1) + +def statement : Prop := + ∀ k : ℕ, 1 ≤ k → + (IsColPeriod k (p k) ∧ ∀ q : ℕ, 0 < q → q < p k → ¬ IsColPeriod k q) ∧ + (2 ≤ k → ∀ m : ℕ, k ≤ (row m).length → ∀ d e : ℕ, d < 3 → e < 3 → + ((Finset.Ico m (m + p k)).filter (fun n => T n k = d)).card = + ((Finset.Ico m (m + p k)).filter (fun n => T n k = e)).card) +``` + +**What the Lean statement says** + +Let T(n,k) be the k-th base-3 digit of 2^n counted from the least significant end (the digit at 3^(k-1)). Column k consists of the rows n for which 2^n has at least k ternary digits. For every k >= 1: (a) shifting by p(k) = 2*3^(k-1) rows preserves column k (T(n+p(k),k) = T(n,k) whenever row n lies in column k), and no smaller positive shift q does, so p(k) is the least period. (b) For k >= 2, every block of p(k) consecutive rows m, ..., m+p(k)-1 (starting at a row m in column k) contains the digits 0, 1 and 2 equally often in column k. + +**What the kernel checks against the OEIS data** + +a_data checks all 84 listed terms (rows 0..15) from row n = Nat.digits 3 (2^n) (least significant digit first, i.e. 'reverse order'). row_example checks example rows 13, 14 and 15. col1_data, col2_data and col3_data check where columns 1, 2 and 3 start (rows 0, 2, 4) and their first values. sanity_small_columns checks p(2)=6 and p(3)=18 as periods on 40 rows, and balanced digit counts [2,2,2] and [6,6,6] in the first period. The definitions are literal, so these checks pin them down. + +**Points for the reviewer** + +- *Note.* 'Periodic, with period p(k)' is read as p(k) being the least period: it is a period and no 0 < q < p(k) is one. This is stronger than 'p(k) is a period', so a proof settles both readings. +- *Note.* 'Equal frequency' is read as equal counts of 0, 1 and 2 in every window of p(k) consecutive column entries. Together with the periodicity conjunct, this is equivalent to equal asymptotic frequencies (1/3 each), so it is not a weaker reading. +- *Note.* Column k starts at the first row with at least k digits. Periodicity is asserted only on rows that have an entry in column k, so the getD default 0 is never used. This matches 'the sequence in column k' read as a sequence from its first entry. The periodicity part is asserted for all k >= 1 and the balance part for k >= 2, as in the text. + +## A265649: A265649: both of Werner Schulte's closed forms hold + +Verdict of the pre-review: **faithful**. Result: [oeis-a265649](../../results/oeis-a265649/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A265649.lean`](../../lean/Math0/Statements/OEIS/A265649.lean). + +**The conjecture as stated in OEIS** + +> %F A265649 Conjecture: T(n,k) = 2^(n-k)*(n-k)!*binomial(n,k)*(Sum_{j=0..n-k} (-1/4)^j* binomial(2*j+k,j)*binomial(n,j+k)). +> %F A265649 Conjecture: T(n,k) = (-1)^k*Sum_{j=0..n-1} A001497(n-1,j)*A021009(j+1,k). +> [Both in the FORMULA section of the entry by _Werner Schulte_, Dec 11 2015 (no separate attribution on these lines). Name: T(0,0)=1, T(n,k)=0 for k<0 or k>n, T(n,k) = T(n-1,k-1) + (2*n-1+k)*T(n-1,k) for n>0, 0<=k<=n; offset 0. Rev #40 (Mar 11 2024), unchanged on GitHub.] + +**The frozen Lean statement** + +```lean +def T : ℕ → ℕ → ℕ + | 0, 0 => 1 + | 0, _ + 1 => 0 + | n + 1, 0 => (2 * (n + 1) - 1 + 0) * T n 0 + | n + 1, k + 1 => T n k + (2 * (n + 1) - 1 + (k + 1)) * T n (k + 1) +def A001497 (n m : ℕ) : ℚ := + if m ≤ n then ((2 * n - m).factorial : ℚ) / ((m.factorial : ℚ) * ((n - m).factorial : ℚ) * 2 ^ (n - m)) else 0 +def A021009 (n m : ℕ) : ℚ := + if m ≤ n then (-1) ^ m * (n.factorial : ℚ) * (n.choose m : ℚ) / (m.factorial : ℚ) else 0 + +def statement : Prop := + (∀ n k : ℕ, k ≤ n → + (T n k : ℚ) = 2 ^ (n - k) * ((n - k).factorial : ℚ) * (n.choose k : ℚ) * + ∑ j ∈ Finset.range (n - k + 1), + (-1 / 4 : ℚ) ^ j * ((2 * j + k).choose j : ℚ) * (n.choose (j + k) : ℚ)) ∧ + (∀ n k : ℕ, 1 ≤ n → k ≤ n → + (T n k : ℚ) = (-1) ^ k * ∑ j ∈ Finset.range n, A001497 (n - 1) j * A021009 (j + 1) k) +``` + +**What the Lean statement says** + +Let T be the triangle with T(0,0)=1, T(0,k)=0 for k>0, T(n,0) = (2n-1)T(n-1,0) and T(n,k) = T(n-1,k-1) + (2n-1+k)T(n-1,k) for n >= 1. Then (1) for all 0 <= k <= n, T(n,k) = 2^(n-k)(n-k)! C(n,k) Σ_{j=0}^{n-k} (-1/4)^j C(2j+k,j) C(n,j+k), as rationals. (2) For all n >= 1 and 0 <= k <= n, T(n,k) = (-1)^k Σ_{j=0}^{n-1} B(n-1,j) L(j+1,k), where B(n,m) = (2n-m)!/(m!(n-m)!2^(n-m)) and L(n,m) = (-1)^m n! C(n,m)/m! for m <= n, both 0 otherwise. + +**What the kernel checks against the OEIS data** + +a_data and T_data check all 55 listed terms of A265649 (rows 0..9). A001497_data checks all 55 listed terms of A001497. A021009_data checks all 47 listed terms of A021009. The Lean closed forms are verbatim the first %F lines of those entries, which hold for all n. statement₁_check and statement₂_check verify both identities for n <= 12 in the kernel. T is a literal transcription of the defining recurrence (natural subtraction 2(n+1)-1 is never truncated). T_eq_zero_of_lt proves T(n,k)=0 for k>n. The definitions are pinned down. + +**Points for the reviewer** + +- *Note.* Conjecture 2 is asserted only for n >= 1. This is forced: A001497(n-1,j) has no meaning at n = 0, and the empty sum would give 0 ≠ T(0,0) = 1. +- *Note.* Both identities are asserted only for 0 <= k <= n, the entries of the tabl triangle. For k > n both sides vanish anyway (C(n,k) = 0, resp. A021009(j+1,k) = 0 for j+1 <= n < k), so nothing is lost. +- *Note.* (n-k) in Conjecture 1 is a genuine difference because k <= n. (-1/4)^j and all sums are in ℚ, so there is no natural-number division or truncation. + +## A267486: O'Sullivan's Gaussian-polynomial / Chebyshev representation conjecture (A267486), proved + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a267486](../../results/oeis-a267486/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A267486.lean`](../../lean/Math0/Statements/OEIS/A267486.lean). + +**The conjecture as stated in OEIS** + +> %C A267486 Conjecture: More generally, the Gaussian polynomial [2*n+m+1-(m mod 2),m]_q = Sum_{k=0..g(m;n)} a(m;n,k)*(1+q^2)^k*q^(g(m;n)-k), for m >= 0, n >= 0, where g(m;n) = m*n if m is odd and (2*n+1)*m/2 if m is even, and the tabf array entries a(m;n,k) are the coefficients of the g.f. for the row n polynomials G(m;n,x) = (d^m/dt^m)G(m;n,t,x)/m!|_{t=0}, with G(m;n,t,x) = (1+t)*Product_{k=1..n+(m - m (mod 2))/2}(1 + t^2 + 2*t*T(k,x/2) (Chebyshev's T-polynomials). Hence a(m;n,k) = [x^k]G(m;n,x), for k=0..g(m;n). The present entry is the instance m = 2. (Thanks to _Wolfdieter Lang_ for clarifying the text on the general prescription of a(m;n,k).) +> [Entry by _Stephen O'Sullivan_, Jan 15 2016; rev #23 (May 30 2026), unchanged on GitHub. Name: coefficients of [2n+7,6]_q in the basis (1+q^2)^k q^(g-k), g = 6n+3.] + +**The frozen Lean statement** + +```lean +noncomputable def gaussBinom : ℕ → ℕ → ℤ[X] + | _, 0 => 1 + | 0, _ + 1 => 0 + | N + 1, m + 1 => gaussBinom N m + X ^ (m + 1) * gaussBinom N (m + 1) +def g (m n : ℕ) : ℕ := if m % 2 = 1 then m * n else (2 * n + 1) * m / 2 +noncomputable def chebHalf (k : ℕ) : ℚ[X] := (Chebyshev.T ℚ k).comp (C (1 / 2 : ℚ) * X) +noncomputable def Gt (m n : ℕ) : ℚ[X][X] := + (1 + X) * ∏ k ∈ Finset.Icc 1 (n + (m - m % 2) / 2), (1 + X ^ 2 + 2 * X * C (chebHalf k)) +noncomputable def G (m n : ℕ) : ℚ[X] := + C ((m.factorial : ℚ)⁻¹) * (derivative^[m] (Gt m n)).eval 0 + +def statement : Prop := + ∀ m n : ℕ, + (G m n).natDegree ≤ g m n ∧ + (gaussBinom (2 * n + m + 1 - m % 2) m).map (Int.castRingHom ℚ) = + ∑ k ∈ Finset.range (g m n + 1), C ((G m n).coeff k) * (1 + X ^ 2) ^ k * X ^ (g m n - k) +``` + +**What the Lean statement says** + +For all m, n >= 0: let N = n + ⌊m/2⌋ and let G(m;n,x) be (1/m!) times the m-th t-derivative at t = 0 (that is, the t^m coefficient) of (1+t) ∏_{k=1}^{N} (1 + t^2 + 2t T_k(x/2)), where T_k is the Chebyshev polynomial of the first kind. Let g = mn for odd m and (2n+1)m/2 for even m. Then G(m;n,x) has x-degree at most g, and the Gaussian binomial [2n+m+1-(m mod 2), m]_q (defined by the q-Pascal rule) equals Σ_{k=0}^{g} ([x^k]G(m;n,x)) (1+q^2)^k q^(g-k) in ℚ[q]. + +**What the kernel checks against the OEIS data** + +a_data (80 listed terms, rows 0..4) and row_exact (zero remainder, row length 6n+4) check the entry's own sequence. That sequence is computed from the Gaussian polynomial [2n+7,6]_q by triangular elimination, not from G, and `statement` does not use it. The statement's own objects are checked by G_two_zero (G(2;0) = 1 + x), G_six_zero (G(6;0) = -1 - 2x + x^2 + x^3 = row 0 of the data), gaussBinom_four_two, gaussBinom_five_two_mul (q-Pascal against the product formula), g_six and the chebHalf identities. These are literal transcriptions of standard objects, so the checks suffice. I also checked independently with sympy that the identity and degree bound hold for m = 0..7, n = 0..3, and that G(6;n,x) reproduces data rows n = 0, 1, 2. + +**Points for the reviewer** + +- *Note.* The entry is internally inconsistent: the comment says 'The present entry is the instance m = 2', but the name, data and Maple program are the m = 6 instance ([2n+7,6]_q, product to n+3). The %F line and the Mathematica program use Product_{i=1..n+1}, which matches neither the data nor the general formula at m = 6. The Lean formalizes the general conjecture for all m, n as written, so these slips do not affect the statement. Its m = 6 instance reproduces the data. +- *Note.* The extra conjunct natDegree(G m n) <= g(m;n) encodes 'a(m;n,k) ... for k=0..g(m;n)' (the row has no terms beyond x^g). It is a strengthening of the bare identity, which by itself would say nothing about higher coefficients of G. +- *Note.* There are no degenerate readings: 2n+m+1-(m mod 2) never truncates, (2n+1)m/2 is exact for even m, g-k is a true difference for k <= g, and m = 0 gives the true trivial case [2n+1,0]_q = 1. + +## A270668: Mathar's generating function for column 3 of A270668 (domino tilings of (4k+1)x5 boards with central hole) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a270668](../../results/oeis-a270668/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A270668.lean`](../../lean/Math0/Statements/OEIS/A270668.lean). + +**The conjecture as stated in OEIS** + +> %F A270668 Conjectured g.f. for column 3: ( -1 -4*x +543*x^2 -6238*x^3 +17032*x^4 -6238*x^5 +543*x^6 -4*x^7 -x^8 ) / ( (x-1) *(x^2-7*x+1) *(x^2-23*x+1) *(x^4 -161*x^3 +576*x^2 -161*x +1) ). - _R. J. Mathar_, Mar 23 2016 +> [Entry: "Triangle read by rows: The number of domino tilings of the (2n+1) X (2m+1) board with a central free square.", 'Arrangements obtained by rotations and flips are counted as distinct.', offset 0, tabl, _R. J. Mathar_, Mar 21 2016. Rev #23 (Apr 13 2016), unchanged on GitHub.] + +**The frozen Lean statement** + +```lean +def IsDomino (d : Finset Cell) : Prop := + ∃ i j : ℕ, d = {(i, j), (i, j + 1)} ∨ d = {(i, j), (i + 1, j)} +def IsTiling (S : Finset Cell) (D : Finset (Finset Cell)) : Prop := + (∀ d ∈ D, IsDomino d ∧ d ⊆ S) ∧ ∀ x ∈ S, ∃! d, d ∈ D ∧ x ∈ d +def board (r c : ℕ) : Finset Cell := range r ×ˢ range c +def region (n m : ℕ) : Finset Cell := (board (2 * n + 1) (2 * m + 1)).erase (n, m) +noncomputable def T (n m : ℕ) : ℕ := {D | IsTiling (region n m) D}.ncard +noncomputable def num : ℚ⟦X⟧ := + -1 - 4 * X + 543 * X ^ 2 - 6238 * X ^ 3 + 17032 * X ^ 4 - 6238 * X ^ 5 + 543 * X ^ 6 - 4 * X ^ 7 - X ^ 8 +noncomputable def den : ℚ⟦X⟧ := + (X - 1) * (X ^ 2 - 7 * X + 1) * (X ^ 2 - 23 * X + 1) * (X ^ 4 - 161 * X ^ 3 + 576 * X ^ 2 - 161 * X + 1) + +def statement : Prop := + PowerSeries.mk (fun k => (T (2 * k) 2 : ℚ)) = num * den⁻¹ +(Cell := ℕ × ℕ; the file also proves statement_iff: statement ↔ mk(T(2k,2)) * den = num.) +``` + +**What the Lean statement says** + +Let c_k be the number of domino tilings of the (4k+1) x 5 rectangle with its central cell removed, counting tilings as sets of dominoes (so rotations and reflections are distinct). For k = 0 this is the 1 x 5 strip without its middle cell, so c_0 = 1. Then, as formal power series over ℚ, Σ_{k>=0} c_k x^k = (-1 - 4x + 543x^2 - 6238x^3 + 17032x^4 - 6238x^5 + 543x^6 - 4x^7 - x^8) / ((x-1)(x^2-7x+1)(x^2-23x+1)(x^4-161x^3+576x^2-161x+1)). The denominator has constant term -1, so the inverse is genuine. + +**What the kernel checks against the OEIS data** + +a_data checks all 36 listed terms (rows 0..7) through the transfer-matrix Tc, and T_eq_Tc is proved for all n, m. The set-theoretic tiling count T is therefore tied to the data, not just the computable proxy. column_data checks T(2k,2) = 1, 196, 31329, 4941729 for k = 0..3, which are the first four coefficients of the conjectured g.f. I independently recomputed T(2k,2) for k = 0..8 by a profile DP and expanded num/den. All nine coefficients agree (…, 777852100, 122398521025, …), so the Lean reading of 'column 3' is the one the g.f. describes. + +**Points for the reviewer** + +- *Note.* Reading choice: 'column 3' is taken as m = 2 (third column, 0-based index 2; 5-wide boards). The g.f. is taken as Σ_k T(2k,2) x^k over the even rows only. The odd rows are 0 by colouring, and the statement says nothing about them. This is the only reading matching the g.f.'s expansion (the m = 3 column 75272, ... does not match), and I confirmed agreement through k = 8. +- *Note.* The constant term T(0,2) = 1 (the 1 x 5 strip) lies outside the triangle (m > n) but comes from the same definition. By transposition it equals T(2,0) = 1, which is in the triangle, so it agrees with how a transfer-matrix g.f. for 5-wide boards would be indexed. +- *Note.* Tilings are counted as Finsets of dominoes with exact cover, so tilings related by symmetry are distinct, as the entry requires. ncard is justified by the proved finiteness, so there is no junk 0 from an infinite set. + +## A275815: A275815: Jones's conjecture a(n) = 8(n-2)^2 for n >= 6 holds + +Verdict of the pre-review: **faithful**. Result: [oeis-a275815](../../results/oeis-a275815/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A275815.lean`](../../lean/Math0/Statements/OEIS/A275815.lean). + +**The conjecture as stated in OEIS** + +> %F A275815 Conjecture: a(n) = 8(n-2)^2 for n >= 6. - _Alec Jones_, Nov 16 2016 +> (Entry name: "Maximum total number of possible moves that any number of queens of the same color can make on an n X n chessboard." Offset 1. Entry unchanged on GitHub oeisdata, #43 Jul 11 2021.) + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n : ℕ, 6 ≤ n → a n = 8 * (n - 2) ^ 2 + +where +def board (n : ℕ) : Finset (ℕ × ℕ) := Finset.range n ×ˢ Finset.range n +def isEmptySquare (n : ℕ) (S : Finset (ℕ × ℕ)) (x y : ℤ) : Bool := + decide (0 ≤ x ∧ x < n ∧ 0 ≤ y ∧ y < n ∧ (x.toNat, y.toNat) ∉ S) +def rayMoves (n : ℕ) (S : Finset (ℕ × ℕ)) (p : ℕ × ℕ) (d : ℤ × ℤ) : ℕ := + ((List.range' 1 n).takeWhile fun t => + isEmptySquare n S (p.1 + t * d.1) (p.2 + t * d.2)).length +def queenDirs : List (ℤ × ℤ) := + [(1, 1), (1, -1), (-1, 1), (-1, -1), (1, 0), (-1, 0), (0, 1), (0, -1)] +def totalMoves (n : ℕ) (S : Finset (ℕ × ℕ)) : ℕ := + ∑ p ∈ S, (queenDirs.map (rayMoves n S p)).sum +def a (n : ℕ) : ℕ := (board n).powerset.sup (totalMoves n) +``` + +**What the Lean statement says** + +For every n >= 6: over all sets S of squares of the n x n board (one queen on each square of S), the maximum of the total number of moves is exactly 8(n-2)^2, where a queen's moves are the squares reachable along any of its 8 lines by passing only through empty squares and stopping on an empty square (no capture, no jumping), and the total sums this count over all queens of S. + +**What the kernel checks against the OEIS data** + +a_data: kernel computes a(1), a(2), a(3) = 0, 4, 17 exactly (first three listed terms). example3: the entry's 3x3 example (A3, A2, B1, C3) gives per-queen counts 3,4,5,5 and total 17. a_ge_data (via witness_spec): explicit placements give exactly the listed values for 4 <= n <= 12, so a(n) >= A275815(n) there (lower bounds only). The exact values a(2)=4 and a(3)=17 pin down the move semantics: blocking by own pieces, no landing on occupied squares, per-queen summation (e.g. allowing moves onto occupied squares would give a(2)=12). Upper bounds are kernel-checked only for n <= 3, but the definition is a literal transcription of the entry's name, so this is not a gap in the definitions. + +**Points for the reviewer** + +- *Note.* The values for n >= 4 are checked only as lower bounds (the kernel cannot run the 2^(n^2) search). The definition is a direct transcription of the entry's name, and the exact values at n = 2, 3 rule out the plausible alternative move rules, so the definition is still adequately pinned. +- *Note.* a 0 = 0 and natural-number subtraction in (n - 2) are both harmless: the statement requires n >= 6. + +## A278212: Kagey's conjecture for A278212: a(n) = floor(A275815(n)/2), via exact bishop and queen maxima from flow (LP-dual) certificates + +Verdict of the pre-review: **faithful**. Result: [oeis-a278212](../../results/oeis-a278212/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A278212.lean`](../../lean/Math0/Statements/OEIS/A278212.lean). + +**The conjecture as stated in OEIS** + +> %C A278212 Conjecture: a(n) = floor(A275815(n)/2). - _Peter Kagey_, Nov 24 2016 +> (A278212: "Maximum total number of possible moves that any number of bishops of the same color can make on an n X n chessboard.", offset 1; A275815: same for queens, offset 1. Entry unchanged on GitHub oeisdata, #36 Nov 19 2023.) + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n : ℕ, 1 ≤ n → a n = queenMax n / 2 + +where (board, isEmptySquare, rayMoves as in A275815) +def bishopDirs : List (ℤ × ℤ) := [(1, 1), (1, -1), (-1, 1), (-1, -1)] +def queenDirs : List (ℤ × ℤ) := + [(1, 1), (1, -1), (-1, 1), (-1, -1), (1, 0), (-1, 0), (0, 1), (0, -1)] +def totalMoves (dirs : List (ℤ × ℤ)) (n : ℕ) (S : Finset (ℕ × ℕ)) : ℕ := + ∑ p ∈ S, (dirs.map (rayMoves n S p)).sum +def a (n : ℕ) : ℕ := (board n).powerset.sup (totalMoves bishopDirs n) +def queenMax (n : ℕ) : ℕ := (board n).powerset.sup (totalMoves queenDirs n) +``` + +**What the Lean statement says** + +For every n >= 1, the maximum total number of moves of a set of bishops on an n x n board equals the floor of half the maximum total number of moves of a set of queens on the same board. Pieces move only through and onto empty squares along their lines (bishops: 4 diagonals; queens: 8 directions). Both maxima are defined from scratch by exhaustive search over all placements, not by any conjectured formula. + +**What the kernel checks against the OEIS data** + +a_data: a(1), a(2), a(3) = 0, 2, 8 exactly. queenMax_data: queenMax(1), queenMax(2), queenMax(3) = 0, 4, 17 exactly. bishopWitness_spec / a_ge_data and queenWitness_spec / queenMax_ge_data: explicit placements, including the entry's own n = 5 bishop example, reach the listed values for 4 <= n <= 10, so these are lower bounds only. The exact a(2) = 2 settles the reading of 'same color' as pieces of one side: if the bishops had to stand on squares of one color, a(2) would be 1. + +**Points for the reviewer** + +- *Note.* 'Same color' could be misread as bishops standing on squares of one color. The kernel-checked a(2) = 2 and the entry's n = 5 example, which uses both square colors, both confirm the file's reading (pieces of one side). +- *Note.* The catalogued proof does not fix queenMax(4), queenMax(5) or queenMax(6) exactly (each is 'X or X+1'), but floor(./2) takes the same value either way. The statement asks only for the floor identity, so the result settles exactly the conjecture. +- *Note.* A275815 is encoded as queenMax, the true sequence defined from its own definition, not Jones's formula 8(n-2)^2. The statement is therefore Kagey's conjecture itself and does not depend on A275815's conjecture. + +## A281000: Schulte's conjectures on A281000, T(n,k) = C(2n+1,2k+1)·Cat(n-k): antidiagonal sums and matrix inverse + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a281000](../../results/oeis-a281000/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A281000.lean`](../../lean/Math0/Statements/OEIS/A281000.lean). + +**The conjecture as stated in OEIS** + +> %F A281000 Conjectures: +> %F A281000 (1) Antidiagonal sums equal A001003(n+1); +> %F A281000 (2) Sum_{k=0..n} (-1)^k*T(n,k)*(2*k+1)*A000108(k)*A103365(k) = A000007(n); +> %F A281000 (3) Matrix inverse equals T(n,k)*A103365(n+1-k). +> (Werner Schulte, Jan 12 2017; T(n,k) = binomial(2*n+1, 2*k+1)*binomial(2*n-2*k, n-k)/(n+1-k), 0 <= k <= n, offset 0. A103365 has offset 1: 1, -1, 2, -7, 39, ... Entries unchanged on GitHub oeisdata.) + +**The frozen Lean statement** + +```lean +def statement : Prop := conj1 ∧ conj2 ∧ conj3 + +def conj1 : Prop := + ∀ n : ℕ, ∑ k ∈ Finset.range (n / 2 + 1), T (n - k) k = A001003 (n + 1) +def conj2 : Prop := + ∀ n : ℕ, ∑ k ∈ Finset.range (n + 1), + (T n k : ℤ) * (2 * k + 1) * (catalan k : ℤ) * A103365 (k + 1) = (0 : ℤ) ^ n +def conj3 : Prop := + ∀ N : ℕ, (Matrix.of fun i j : Fin N => (T i j : ℚ))⁻¹ = + Matrix.of fun i j : Fin N => (T i j : ℚ) * (A103365 ((i : ℕ) + 1 - (j : ℕ)) : ℚ) + +def T (n k : ℕ) : ℕ := + Nat.choose (2 * n + 1) (2 * k + 1) * Nat.choose (2 * n - 2 * k) (n - k) / (n + 1 - k) +def narayana (n k : ℕ) : ℕ := Nat.choose (n - 1) (k - 1) * Nat.choose n (k - 1) / k +def A001003 (n : ℕ) : ℕ := + if n = 0 then 1 else ∑ j ∈ Finset.Icc 1 n, 2 ^ (j - 1) * narayana n j +def invNarayanaCol : ℕ → List ℤ -- forward substitution, b(n) = [n=1] - Σ_{j n), N(n,j) the Narayana numbers, s(n) the little Schroeder numbers (s(0)=1, s(n) = Σ_{j=1..n} 2^{j-1} N(n,j)), and b the first column of the inverse of the Narayana matrix (b(1)=1, b(2)=-1, b(3)=2, ...). Then (1) for all n >= 0, Σ_{k=0..⌊n/2⌋} T(n-k,k) = s(n+1); (2) for all n >= 0, Σ_{k=0..n} T(n,k)(2k+1)Cat(k)·b(k+1) = [n=0]; (3) for every N, the inverse over Q of the N x N leading block of T is the N x N leading block of U(n,k) = T(n,k)·b(n+1-k). + +**What the kernel checks against the OEIS data** + +a_data: all 55 listed terms of the triangle (rows 0-9). A001003_data: all 26 listed little Schroeder numbers. A103365_data: all 20 listed terms of A103365, signs included. conj1_check (n <= 24), conj2_check (n <= 15) and conj3_check (entries of T·U for n,k <= 14) are sanity checks of the transcription. These checks pin down every auxiliary definition and the index alignment of (1) (1 = s(1), 3 = s(2), 10+1 = s(3)). I independently recomputed that the literal shift with (-1)^k kept gives 1, 6, 60, 910, ... instead of 0^n. + +**Points for the reviewer** + +- *Minor.* Conjecture (2) is not well defined as written: A103365 has offset 1, so the k = 0 term uses A103365(0). With only the shift A103365(k) -> A103365(k+1) it is false at n = 1 (sum 3 + 3 = 6; I recomputed this). The file instead reads (-1)^k·A103365(k) as A103365(k+1), which equals (-1)^k·|A103365(k+1)|. This is an editorial correction, not the literal text. It does not change the strength of the statement: in this reading (2) is the k = 0 column of T·T^{-1} = I, so it follows from conj3. The other plausible true readings, such as Σ T(n,k)(2k+1)Cat(k)·b(n+1-k) = 0^n (row 0 of U·T), also follow from conj3. The conjunction is therefore equivalent to (1) ∧ (3), which are transcribed faithfully. +- *Note.* A001003 is defined by Cloitre's Narayana-sum formula, not by any of its combinatorial definitions. This is a classical identity (s(n) = Σ 2^{j-1} N(n,j)) and all 26 listed terms are kernel-checked, so the definition is right for all n. +- *Note.* conj3 uses Mathlib's ⁻¹, which returns 0 for singular matrices. Every leading block of T is lower unitriangular (T(n,n) = 1, T(n,k) = 0 for k > n), so the inverse is the honest one. The junk value A103365 0 = 0 and the truncated n+1-k are reached only where T(i,j) = 0. +- *Note.* The statement bundles three separate conjectures into one conjunction. That is fine here, because the result proves the conjunction and therefore each conjecture. + +## A294512: Lang's conjecture a(n) = A250400(n+1)/(n+1) for A294512 fails at n = 164 + +Verdict of the pre-review: **faithful**. Result: [oeis-a294512](../../results/oeis-a294512/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A294512.lean`](../../lean/Math0/Statements/OEIS/A294512.lean). + +**The conjecture as stated in OEIS** + +> %F A294512 a(n) = A250400(n+1)/(n+1), n >= 0. [conjecture]. +> (Entry by _Wolfdieter Lang_, Nov 01 2017. a(n) = denominator(V(3,1;n)), V(3,1;n) = Sum_{k=0..n} 1/((k + 1)*(3*k + 1)); offset 0. A250400: "Numerator of the harmonic mean of the first n octagonal numbers", offset 1, PARI numerator(n / sum(k=1..n, 1/(3k^2-2k))). Lang's companion comment in A250401 says "[assuming that n+1 divides A250400(n+1) to give A294512(n) for n >= 0]". Entry unchanged on GitHub oeisdata, #13 Nov 12 2017.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, (A250400 (n + 1) : ℚ) / ((n : ℚ) + 1) = (a n : ℚ) + +def V (n : ℕ) : ℚ := ∑ k ∈ Finset.range (n + 1), 1 / (((k : ℚ) + 1) * (3 * (k : ℚ) + 1)) +def a (n : ℕ) : ℕ := (V n).den +def octagonal (j : ℕ) : ℕ := j * (3 * j - 2) +def harmonicMean (m : ℕ) : ℚ := (m : ℚ) / ∑ j ∈ Finset.Icc 1 m, 1 / (octagonal j : ℚ) +def A250400 (m : ℕ) : ℕ := (harmonicMean m).num.natAbs +``` + +**What the Lean statement says** + +For every n >= 0, let a(n) be the reduced denominator of Σ_{k=0..n} 1/((k+1)(3k+1)) and A250400(n+1) the reduced numerator of (n+1)/Σ_{j=1..n+1} 1/(j(3j-2)). The statement says the rational number A250400(n+1)/(n+1) equals a(n). (math0 refutes it: it fails at n = 164.) + +**What the kernel checks against the OEIS data** + +a_data: all 23 listed terms of A294512. A250400_data: all 20 listed terms of A250400. octagonal_data: 0, 1, 8, 21, 40. The definitions are exact transcriptions of the entries' own Mathematica and PARI programs. The counterexample n = 164 lies beyond the listed data, so the refutation rests on these definitions, which match the entries exactly rather than only on the checked terms. I independently recomputed (exact rationals, n < 400) that the only failure in that range is n = 164, where gcd(165, num V(164)) = 11 and A250400(165) = 15·a(164). + +**Points for the reviewer** + +- *Note.* The conjecture holds exactly when n+1 is coprime to the numerator of V(n), since A250400(n+1) = (n+1)·a(n)/gcd(n+1, num V(n)). At n = 164, 165 does not divide A250400(165) = 15·a(164). The refutation therefore holds whether '/' is read as an exact rational quotient (the file's reading), as natural-number floor division (floor(a/11) ≠ a), or as a claim that n+1 divides A250400(n+1) (Lang's own reading in A250401). It is not an artifact of the division convention. +- *Note.* A250400 takes Int.natAbs of the numerator, which is harmless because the harmonic mean of positive numbers is positive. n = 164 is inside the stated range n >= 0, so the failure is a genuine counterexample, not a degenerate case. diff --git a/review/fidelity/packet-07.md b/review/fidelity/packet-07.md new file mode 100644 index 0000000..7396654 --- /dev/null +++ b/review/fidelity/packet-07.md @@ -0,0 +1,378 @@ +# Fidelity review packet 07 of 11 + +Prepared on 29 Oct 2026 by an adversarial reviewing agent, not by a person. It is meant to make a human review of these statements quick: for each one it quotes the OEIS conjecture and the frozen Lean statement, restates the Lean in plain words, and lists anything a reviewer should look at. See [the index](README.md). + +Statements in this packet: A300789, A308107, A308121, A308222, A308359, A320099, A323695, A326407, A326602, A328202. + +## A300789: Domino-tileable Young diagrams are exactly the colour-balanced ones (A300789) + +Verdict of the pre-review: **faithful**. Result: [oeis-a300789](../../results/oeis-a300789/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A300789.lean`](../../lean/Math0/Statements/OEIS/A300789.lean). + +**The conjecture as stated in OEIS** + +> %C A300789 "This sequence is conjectured to be the Heinz numbers of integer partitions in which the odd parts appear as many times in even as in odd positions." (_Gus Wiseman_, Mar 12 2018; name: "Heinz numbers of integer partitions whose Young diagram can be tiled by dominos.", offset 1; "The Heinz number of an integer partition (y_1,...,y_k) is prime(y_1)*...*prime(y_k).") + +**The frozen Lean statement** + +```lean +def parts (k : ℕ) : List ℕ := (k.primeFactorsList.map Nat.primeCounting).reverse +def youngDiagram (y : List ℕ) : Set (ℕ × ℕ) := {c | c.1 < y.length ∧ c.2 < y.getD c.1 0} +def IsDomino (d : Set (ℕ × ℕ)) : Prop := ∃ i j : ℕ, d = {(i, j), (i + 1, j)} ∨ d = {(i, j), (i, j + 1)} +def DominoTileable (S : Set (ℕ × ℕ)) : Prop := + ∃ D : Set (Set (ℕ × ℕ)), (∀ d ∈ D, IsDomino d) ∧ D.PairwiseDisjoint id ∧ ⋃₀ D = S +def IsTerm (k : ℕ) : Prop := 0 < k ∧ DominoTileable (youngDiagram (parts k)) +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) +def OddPartsBalanced (y : List ℕ) : Prop := + ((Finset.range y.length).filter fun i => Even (i + 1) ∧ Odd (y.getD i 0)).card = + ((Finset.range y.length).filter fun i => Odd (i + 1) ∧ Odd (y.getD i 0)).card +def IsConjTerm (k : ℕ) : Prop := 0 < k ∧ OddPartsBalanced (parts k) +noncomputable def b (n : ℕ) : ℕ := Nat.nth IsConjTerm (n - 1) + +def statement : Prop := ∀ n : ℕ, 1 ≤ n → a n = b n +``` + +**What the Lean statement says** + +Write each k ≥ 1 as the Heinz number of the partition whose parts are the prime indices of k (π(p) for each prime factor p, with multiplicity), listed in weakly decreasing order. Let a(n) be the n-th smallest such k whose Young diagram can be partitioned into disjoint dominoes (1×2 or 2×1). Let b(n) be the n-th smallest such k whose partition has as many odd parts in even positions as in odd positions (positions 1..m). The statement says a(n) = b(n) for every n ≥ 1. Both predicates require k > 0, so this is equivalent to: for every k ≥ 1, the Young diagram is domino-tileable iff the odd parts are balanced between even and odd positions. + +**What the kernel checks against the OEIS data** + +a_data and b_data kernel-check all 63 listed terms (1, 3, 4, …, 131) for both a and b, by a kernel-checked List.filter over 0..131 transferred to Nat.nth (map_nth_eq_of_filter). Tileability is decided by tileL, which isTerm_iff_isTermB proves equivalent to the set-theoretic DominoTileable, so the check is on the real definition. parts_example checks the entry's %e list of partitions for the first 15 terms, which pins down `parts` (π indexing with prime(1)=2, multiplicity, decreasing order). The definitions are pinned down well. + +**Points for the reviewer** + +- *Note.* Positions are counted with the parts in decreasing order. The entry's Maple and Mathematica programs use increasing order. Reversing a list of length m maps position i to m+1-i, which either keeps every parity (m odd) or swaps every parity (m even). The equality of the two counts is symmetric, so the condition is the same in both orders. +- *Note.* 'This sequence is conjectured to be [those] Heinz numbers' is encoded as equality of the two increasing enumerations a(n) = b(n) for all n ≥ 1. Both predicates exclude 0, so this equality is equivalent to equality of the two sets of terms, whether or not the sets are infinite. It therefore captures both directions of the intended characterization. +- *Note.* The Young diagram uses the English convention with rows y_1 ≥ y_2 ≥ …. Domino tileability does not depend on the drawing convention. + +## A308107: A308107: Barker's rational generating function and order-15 recurrence for the sum of smallest sides of scalene integer triangles + +Verdict of the pre-review: **faithful**. Result: [oeis-a308107](../../results/oeis-a308107/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A308107.lean`](../../lean/Math0/Statements/OEIS/A308107.lean). + +**The conjecture as stated in OEIS** + +> %F A308107 Conjectures from _Colin Barker_, May 13 2019: (Start) +> %F A308107 G.f.: x^9*(2 + 2*x + 2*x^2 + x^3) / ((1 - x)^4*(1 + x)^3*(1 + x^2)^2*(1 + x + x^2)^2). +> %F A308107 a(n) = -a(n-1) + 2*a(n-3) + 4*a(n-4) + 2*a(n-5) - a(n-6) - 5*a(n-7) - 5*a(n-8) - a(n-9) + 2*a(n-10) + 4*a(n-11) + 2*a(n-12) - a(n-14) - a(n-15) for n>15. +> %F A308107 (End) +> (Entry: "Sum of the smallest side lengths of all integer-sided scalene triangles with perimeter n.", _Wesley Ivan Hurt_, May 13 2019, offset 1. Entry unchanged on GitHub oeisdata, #14 Sep 12 2021.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + (PowerSeries.mk (fun n => (a n : ℚ)) = + X ^ 9 * (2 + 2 * X + 2 * X ^ 2 + X ^ 3) * + ((1 - X) ^ 4 * (1 + X) ^ 3 * (1 + X ^ 2) ^ 2 * (1 + X + X ^ 2) ^ 2)⁻¹) ∧ + (∀ n : ℕ, 15 < n → + (a n : ℤ) = -(a (n - 1) : ℤ) + 2 * (a (n - 3) : ℤ) + 4 * (a (n - 4) : ℤ) + + 2 * (a (n - 5) : ℤ) - (a (n - 6) : ℤ) - 5 * (a (n - 7) : ℤ) - 5 * (a (n - 8) : ℤ) - + (a (n - 9) : ℤ) + 2 * (a (n - 10) : ℤ) + 4 * (a (n - 11) : ℤ) + 2 * (a (n - 12) : ℤ) - + (a (n - 14) : ℤ) - (a (n - 15) : ℤ)) + +def a (n : ℕ) : ℕ := + ∑ t ∈ (Finset.range (n + 1) ×ˢ Finset.range (n + 1) ×ˢ Finset.range (n + 1)).filter + (fun t : ℕ × ℕ × ℕ => t.1 < t.2.1 ∧ t.2.1 < t.2.2 ∧ t.2.2 < t.1 + t.2.1 ∧ + t.1 + t.2.1 + t.2.2 = n), + t.1 +``` + +**What the Lean statement says** + +Let a(n) be the sum of k over all integer triples k < i < j with j < k + i and k + i + j = n, that is, the sum of the smallest sides of all scalene integer triangles of perimeter n (a(0) = 0). Then (1) Σ_{n>=0} a(n) x^n equals x^9(2+2x+2x^2+x^3)/((1-x)^4(1+x)^3(1+x^2)^2(1+x+x^2)^2) as formal power series over Q, and (2) for every n > 15 the stated order-15 linear recurrence holds in Z. + +**What the kernel checks against the OEIS data** + +a_data: all 61 listed terms a(1..61), computed through aFast, which a_eq_aFast proves equal to a for every n. The check is therefore about the stated definition. recurrence_data: the listed terms satisfy the recurrence for 16 <= n <= 61 (a transcription check). den_eq: the stated denominator expands to the recurrence's characteristic polynomial. genFun_iff: the g.f. clause is equivalent to A(x)·D(x) = x^9(2+2x+2x^2+x^3), because constantCoeff D = 1. The definition matches the entry's double-sum formula term for term: i from k+1 to floor((n-k-1)/2) gives i < j, and sign(floor((i+k)/(j+1))) = 1 iff j < i+k. I also checked the g.f. against a brute-force a(n) for n < 150. + +**Points for the reviewer** + +- *Note.* The value a(0) = 0 is outside the offset but harmless: the g.f. has zero constant term, and the recurrence for n > 15 uses only indices >= 1. +- *Note.* The order-15 recurrence follows from the g.f., since the numerator has degree 12 < 15. The conjunction is therefore exactly as strong as the g.f. claim, which matches Barker's pair of conjectures. + +## A308121: A308121: for odd n > 1, row 2n is row n with its halves swapped + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a308121](../../results/oeis-a308121/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A308121.lean`](../../lean/Math0/Statements/OEIS/A308121.lean). + +**The conjecture as stated in OEIS** + +> %C A308121 From _Charlie Neder_, Jun 05 2019: "Conjecture: If n is odd, then row 2n can be obtained from row n by interchanging the first and second halves." (Entry by _Jamie Morken_, May 13 2019: "Irregular triangle read by rows: T(n,k) = A109395(n)*k-A076512(n)*A038566(n,k).", offset 1, "Row n has length A000010(n).") + +**The frozen Lean statement** + +```lean +def totatives (n : ℕ) : List ℕ := (List.range' 1 n).filter (fun r => Nat.Coprime r n) +def A109395 (n : ℕ) : ℕ := ((Nat.totient n : ℚ) / n).den +def A076512 (n : ℕ) : ℤ := ((Nat.totient n : ℚ) / n).num +def T (n k : ℕ) : ℤ := (A109395 n : ℤ) * k - A076512 n * ((totatives n).getD (k - 1) 0 : ℕ) +def row (n : ℕ) : List ℤ := (List.range (Nat.totient n)).map (fun i => T n (i + 1)) + +def statement : Prop := + ∀ n : ℕ, Odd n → 1 < n → + ∃ A B : List ℤ, row n = A ++ B ∧ A.length = B.length ∧ row (2 * n) = B ++ A +``` + +**What the Lean statement says** + +For n ≥ 1, let r_1 < … < r_φ(n) be the integers in [1, n] coprime to n. Let φ(n)/n = u/v in lowest terms. Define row n as the integer list (v·k − u·r_k), k = 1..φ(n). The claim: for every odd n > 1, row n splits into two halves A, B of equal length (row n = A ++ B), and row 2n equals B ++ A. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks that rows 1..15 concatenated equal all 72 listed terms (%S/%T/%U). T_210_2 checks the entry's worked example T(210,2) = 35·2 − 8·11 = −18, which exercises the signed (ℤ) values and the reduced fraction at a composite n. statement_check_7 and statement_check_15 check rows 7/14 and 15/30 explicitly. The listed rows include non-squarefree and composite n (4, 6, 8, 9, 10, 12, 14, 15), so the num/den-of-reduced-fraction definitions of A076512/A109395 and the A038566 row convention (row 1 = [1]) are pinned down. + +**Points for the reviewer** + +- *Minor.* Reading choice on the range: the OEIS text says 'If n is odd', which includes n = 1, but the Lean statement requires 1 < n. At n = 1 the literal claim fails under any reading: row 1 = [0] has odd length and no halves, and row 2 = [1] is not a rearrangement of [0]. For odd n ≥ 3, φ(n) is even, so the halves are well defined. The file documents this exclusion, and it is the only reading under which the conjecture is meaningful. Still, the result settles the conjecture for odd n > 1 and not the literal 'all odd n' wording, which is (trivially) false at n = 1. A reviewer should accept this reading explicitly. +- *Note.* A109395 and A076512 are defined literally as Rat.den and Rat.num of φ(n)/n, as their OEIS names and comments say (A076512: 'Numerator of phi(n)/n', formula A000010/A009195). The getD default 0 in T is never reached, because row only uses k ≤ φ(n) = length of totatives n. + +## A308222: Perimeters of primitive Heronian isosceles triangles: A308222(n) = 2 · A096033(n + 2) + +Verdict of the pre-review: **faithful**. Result: [oeis-a308222](../../results/oeis-a308222/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A308222.lean`](../../lean/Math0/Statements/OEIS/A308222.lean). + +**The conjecture as stated in OEIS** + +> %F A308222 "a(n) = 2*A096033(n+2) (conjectured)." (Entry by _Peter Kagey_, May 16 2019; name: "Numbers that are the perimeter of a primitive Heronian isosceles triangle.", offset 1; comment: "A primitive Heronian triangle is a triangle with integer sides and area, where the side lengths do not share a common divisor." A096033: "Difference between leg and hypotenuse in primitive Pythagorean triangles.", offset 1: 1, 2, 8, 9, 18, …) + +**The frozen Lean statement** + +```lean +def heron (x y z : ℤ) : ℤ := (x + y + z) * (-x + y + z) * (x - y + z) * (x + y - z) +def IsHeronian (x y z : ℕ) : Prop := + x < y + z ∧ y < x + z ∧ z < x + y ∧ ∃ A : ℕ, 16 * (A : ℤ) ^ 2 = heron x y z +def IsPrimitive (x y z : ℕ) : Prop := Nat.gcd (Nat.gcd x y) z = 1 +def IsIsosceles (x y z : ℕ) : Prop := x = y ∨ y = z ∨ x = z +def IsPerimeter (P : ℕ) : Prop := + ∃ x y z : ℕ, IsHeronian x y z ∧ IsPrimitive x y z ∧ IsIsosceles x y z ∧ x + y + z = P +noncomputable def a (n : ℕ) : ℕ := Nat.nth IsPerimeter (n - 1) +def IsLegHypDiff (d : ℕ) : Prop := + ∃ x y z : ℕ, 0 < x ∧ 0 < y ∧ x ^ 2 + y ^ 2 = z ^ 2 ∧ Nat.gcd x y = 1 ∧ z = x + d +noncomputable def A096033 (n : ℕ) : ℕ := Nat.nth IsLegHypDiff (n - 1) + +def statement : Prop := ∀ n : ℕ, 1 ≤ n → a n = 2 * A096033 (n + 2) +``` + +**What the Lean statement says** + +Let a(n) be the n-th smallest number P (offset 1, each value counted once) that is the perimeter of a non-degenerate triangle with natural-number sides, gcd of the three sides equal to 1, integer area (16A^2 = Heron product for some natural A), and two equal sides. Let D(n) be the n-th smallest d (offset 1) such that some primitive Pythagorean triple (x, y, z), with x, y ≥ 1 and gcd(x, y) = 1, has z = x + d. The claim: a(n) = 2·D(n+2) for all n ≥ 1, i.e. the set of perimeters equals twice the set of leg–hypotenuse differences other than 1 and 2. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 46 listed terms of A308222 (16, …, 3136) through a decision procedure (perimB) that perimB_iff proves equivalent to IsPerimeter. A096033_data kernel-checks the 52 listed terms of A096033 (1, 2, 8, 9, 18, …, 1849), using legHypB, which isLegHypDiff_iff/legHypB_iff prove equivalent to the definition. Together these pin down both definitions and the index shift: A096033(3) = 8 gives 16 = a(1), and A096033(4) = 9 gives 18 = a(2). + +**Points for the reviewer** + +- *Note.* Equilateral triangles count as isosceles here, but none has integer area, so this changes nothing. 'Primitive' is gcd(gcd(x,y),z) = 1, which matches the entry's comment. Perimeters arising from several triangles (e.g. 50) are counted once, which matches the listed data. +- *Note.* A096033 is encoded by its defining property (difference between a leg and the hypotenuse of a primitive Pythagorean triangle), not by Weimholt's characterization (odd squares and 2j^2). The characterization is proved in the file only for decidability. The statement is a pointwise equality of two increasing enumerations, which is equivalent to the set identity above. + +## A308359: Fixed polyominoes with n cells and width n-2: T(n,n-2) = 8n^2 - 51n + 86 (A308359) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a308359](../../results/oeis-a308359/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A308359.lean`](../../lean/Math0/Statements/OEIS/A308359.lean). + +**The conjecture as stated in OEIS** + +> %F A308359 "Conjecture: T(n,n-2) = 8*n^2 - 51*n + 86 for n >= 5." (Entry by _R. J. Mathar_, May 22 2019; name: "Triangle T(n,w) read by rows: the number of fixed polyominoes with n cells and width w of the convex hull.", offset 1; comment: "The sequence counts the fixed n-ominoes with prescribed bounding box width w and variable height w <= h <= n.") + +**The frozen Lean statement** + +```lean +def Adj (p q : ℕ × ℕ) : Prop := + (p.1 = q.1 ∧ (p.2 + 1 = q.2 ∨ q.2 + 1 = p.2)) ∨ (p.2 = q.2 ∧ (p.1 + 1 = q.1 ∨ q.1 + 1 = p.1)) +def Step (S : Finset (ℕ × ℕ)) (p q : ℕ × ℕ) : Prop := p ∈ S ∧ q ∈ S ∧ Adj p q +def IsConnected (S : Finset (ℕ × ℕ)) : Prop := + ∀ p ∈ S, ∀ q ∈ S, Relation.ReflTransGen (Step S) p q +def IsPoly (n w : ℕ) (S : Finset (ℕ × ℕ)) : Prop := + S.card = n ∧ (∃ p ∈ S, p.1 = 0) ∧ (∃ p ∈ S, p.2 = 0) ∧ S.sup Prod.fst + 1 = w ∧ IsConnected S +noncomputable def T (n w : ℕ) : ℕ := {S : Finset (ℕ × ℕ) | IsPoly n w S}.ncard + +def statement : Prop := + ∀ n : ℕ, 5 ≤ n → (T n (n - 2) : ℤ) = 8 * (n : ℤ) ^ 2 - 51 * n + 86 +``` + +**What the Lean statement says** + +For every n ≥ 5, the number of n-cell edge-connected sets of grid cells, taken up to translation (each normalized to have min column 0 and min row 0) and spanning exactly n − 2 columns, with no condition on the number of rows, equals 8n^2 − 51n + 86 (compared in ℤ). + +**What the kernel checks against the OEIS data** + +a_data kernel-checks the first 23 listed terms (rows 1..6, then T(7,1) = 1 and T(7,2) = 66), including T(5,3) = 31 and T(6,4) = 68, the conjecture's n = 5 and n = 6 values. Every count goes through the computable Tbox, which T_eq_Tbox proves equal to the ncard definition (it also shows the set is finite, so ncard is not a junk 0), with connectivity decided by a flood fill proved equivalent to IsConnected. Independently, I enumerated fixed polyominoes by brute force (Python, column-span width, unrestricted height). This reproduces all 66 listed terms (rows 1..11), including T(n,n−2) = 31, 68, 121, 190, 275, 376, 493 for n = 5..11, each equal to 8n^2 − 51n + 86. The definitions are pinned down. + +**Points for the reviewer** + +- *Note.* The entry's comment says the height ranges over w ≤ h ≤ n, but the entry contradicts this: T(3,3) = 1, T(n,n−1) = 4n−8 ('width n-1 and height 2'), and the row sums equal A001168. Under the comment's reading, T(n,n−2) would be 0 for n ≥ 6, because height ≤ n+1−w = 3 < n−2. So the Lean choice of unrestricted height is the only reading consistent with the data, and it reproduces every listed term. The choice between width and height does not matter, since transposition gives the same counts. +- *Note.* The truncated subtraction n − 2 is harmless because n ≥ 5. The right side is computed in ℤ, so it is not truncated. The 'width of the convex hull' of a union of unit squares equals the column span max x − min x + 1, which is what IsPoly encodes (min x = 0). + +## A320099: Kagey's order-10 recurrence for no-leaf subgraphs of the 5 × n grid holds + +Verdict of the pre-review: **faithful**. Result: [oeis-a320099](../../results/oeis-a320099/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A320099.lean`](../../lean/Math0/Statements/OEIS/A320099.lean). + +**The conjecture as stated in OEIS** + +> %F A320099 Conjecture: a(n) = 103*a(n-1) + 1063*a(n-2) - 1873*a(n-3) - 20274*a(n-4) + 44071*a(n-5) - 10365*a(n-6) - 20208*a(n-7) + 5959*a(n-8) + 2300*a(n-9) - 500*a(n-10) for n > 10. (Entry and conjecture by _Peter Kagey_, Oct 05 2018; rev #20, Jun 09 2019, unchanged upstream.) Definition: %N Number of no-leaf subgraphs of the 5 X n grid. %C Also, the number of ways to lay unit-length matchsticks on a 5 X n grid of points in such a way that no end is "orphaned". %O 1,2 + +**The frozen Lean statement** + +```lean +abbrev grid (n : ℕ) : SimpleGraph (Fin 5 × Fin n) := pathGraph 5 □ pathGraph n +def deg {n : ℕ} (S : Finset (Sym2 (Fin 5 × Fin n))) (v : Fin 5 × Fin n) : ℕ := #{e ∈ S | v ∈ e} +def a (n : ℕ) : ℕ := #{S ∈ (grid n).edgeFinset.powerset | ∀ v, deg S v ≠ 1} + +def statement : Prop := + ∀ n : ℕ, 10 < n → + (a n : ℤ) = 103 * (a (n - 1) : ℤ) + 1063 * (a (n - 2) : ℤ) - 1873 * (a (n - 3) : ℤ) + - 20274 * (a (n - 4) : ℤ) + 44071 * (a (n - 5) : ℤ) - 10365 * (a (n - 6) : ℤ) + - 20208 * (a (n - 7) : ℤ) + 5959 * (a (n - 8) : ℤ) + 2300 * (a (n - 9) : ℤ) + - 500 * (a (n - 10) : ℤ) +``` + +**What the Lean statement says** + +Let G_n be the grid graph on the 5-by-n array of points (two points adjacent iff they agree in one coordinate and differ by 1 in the other). Let a(n) be the number of edge subsets S of G_n such that no vertex lies on exactly one edge of S. Then for every integer n > 10, a(n) = 103a(n-1) + 1063a(n-2) - 1873a(n-3) - 20274a(n-4) + 44071a(n-5) - 10365a(n-6) - 20208a(n-7) + 5959a(n-8) + 2300a(n-9) - 500a(n-10), as an identity of integers. + +**What the kernel checks against the OEIS data** + +a_data checks all 15 listed terms a(1..15) (index i+1, matching offset 1) with decide +kernel. It goes through a_eq_T and a_eq_fastA, which prove for every n that a n equals the (noH,noH) entry of T^n for the 32x32 column transfer matrix, so the check is on the actual definition `a`, not on a separate evaluator. statement_check_listed verifies the recurrence at n = 11..15. I compared the Lean list with the OEIS %S/%T/%U data by script: identical (15/15). The data pins down the definition. a(1) = 1 rules out readings where subgraphs may drop vertices (that would give 32 for the empty edge set) and readings where '5 X n grid' means 5 x n cells (6 x (n+1) points). a(2) = 50 and the remaining terms confirm the 'no degree-1 vertex' edge-set count. + +**Points for the reviewer** + +- *Note.* 'Subgraph' is encoded as a spanning edge subset (all vertices kept, isolated vertices allowed). That is the matchstick reading in the entry's comment, and a(1) = 1 together with all 15 terms forces it, so this is not an interpretive gap. +- *Note.* a 0 = 1 (the empty grid) is a junk value outside offset 1. It is never used, because n > 10 makes every index n-k with 1 <= k <= 10 an exact natural subtraction that is >= 1. The range 'n > 10' and all ten coefficients, with their signs, match the OEIS text exactly. + +## A323695: Odd terms of A323695 occur only at n = k(k+2) + +Verdict of the pre-review: **faithful**. Result: [oeis-a323695](../../results/oeis-a323695/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A323695.lean`](../../lean/Math0/Statements/OEIS/A323695.lean). + +**The conjecture as stated in OEIS** + +> %C A323695 Odd terms occur only at n = k*(k+2) for k >= 0 (conjecture); (_Paul D. Hanna_, Feb 23 2019; rev #24, Dec 15 2024, unchanged upstream.) Definition: %N G.f.: Sum_{n>=0} x^n * (1 - x^(n+1))^n / (1 + x^(n+1))^(n+1). %O 0,3. (The FORMULA section separately lists, without the word conjecture: 'a(n*(n+2)) = 1 (mod 2) for n >= 0.') + +**The frozen Lean statement** + +```lean +noncomputable def summand (m : ℕ) : PowerSeries ℤ := + X ^ m * (1 - X ^ (m + 1)) ^ m * invOfUnit ((1 + X ^ (m + 1)) ^ (m + 1)) 1 +noncomputable def A : PowerSeries ℤ := + mk fun N => ∑ m ∈ Finset.range (N + 1), coeff N (summand m) +-- HasSum summand A proved (hasSum_summand) +def a (N : ℕ) : ℤ := coeffA N -- explicit binomial formula; theorem a_eq_coeff : a N = coeff N A + +def statement : Prop := + ∀ n : ℕ, Odd (a n) → ∃ k : ℕ, n = k * (k + 2) +``` + +**What the Lean statement says** + +Let a(N) be the integer coefficient of x^N in the formal power series sum over m >= 0 of x^m (1 - x^(m+1))^m / (1 + x^(m+1))^(m+1), for N >= 0. For every N >= 0, if a(N) is odd then N = k(k+2) for some integer k >= 0 (equivalently, N+1 is a perfect square). + +**What the kernel checks against the OEIS data** + +a_data checks all 121 listed terms a(0..120) (index i+0, matching offset 0) with decide +kernel. `a` is a computable explicit formula, but a_eq_coeff proves a N = coeff N A for every N, and hasSum_summand proves that A is the X-adic sum of the OEIS summands, so the data check is a sanity check rather than what fixes the definition. I compared with the OEIS data by script: identical (121/121), signs included. + +**Points for the reviewer** + +- *Note.* The statement covers only the stated direction, odd => n = k(k+2), which is exactly what 'occur only at' says. The converse, a(k(k+2)) odd, appears in the entry's FORMULA section, not marked as a conjecture. It is not part of `statement`, so the result does not certify it, although the catalogued proof method (a(n) ≡ d(n+1) mod 2) would give it. +- *Note.* The summand inverse uses invOfUnit with unit 1, which is valid because (1+X^(m+1))^(m+1) has constant coefficient 1 (summand_spec proves the defining identity). k ranges over ℕ, matching 'k >= 0'. Odd on ℤ handles the negative terms correctly (e.g. -3, -93). + +## A326407: Prime-Minesweeper on the A060734 array: a(n) < 6, and a(n) = 5 only at n = 6 + +Verdict of the pre-review: **faithful**. Result: [oeis-a326407](../../results/oeis-a326407/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A326407.lean`](../../lean/Math0/Statements/OEIS/A326407.lean). + +**The conjecture as stated in OEIS** + +> %C A326407 a(n) < 6 (conjectured). %C A326407 a(n) = 5 for n={6} (conjectured). [%C A326407 Set of n such that a(n) = 4 is unbounded (conjectured). — not targeted] (_Witold Tatkiewicz_, Oct 02 2019; rev #27, Mar 20 2020, unchanged upstream.) Definition: %N Minesweeper sequence of positive integers arranged on a 2D grid along a square array that grows by alternately adding a row at its bottom edge and a column at its right edge. %C Place positive integers on a 2D grid starting with 1 in the top left corner and continue along an increasing square array as in A060734. Replace each prime with -1 and each nonprime with the number of primes in adjacent grid cells around them. %O 1,1 + +**The frozen Lean statement** + +```lean +def val (r c : ℕ) : ℕ := if r ≤ c then (c + 1) ^ 2 - r else r ^ 2 + 1 + c +def pos (n : ℕ) : ℕ × ℕ := ... -- inverse of val; pos_val, val_pos proved +def near (x : ℕ) : List ℕ := if x = 0 then [0, 1] else [x - 1, x, x + 1] +def neighbours (n : ℕ) : List ℕ := + (near (pos n).1).flatMap fun i => + (near (pos n).2).filterMap fun j => + if (i, j) = pos n then none else some (val i j) +def a (n : ℕ) : ℤ := + if n.Prime then -1 else (((neighbours n).filter fun m => m.Prime).length : ℤ) + +def statement : Prop := + (∀ n : ℕ, 1 ≤ n → a n < 6) ∧ (∀ n : ℕ, 1 ≤ n → (a n = 5 ↔ n = 6)) +``` + +**What the Lean statement says** + +Write the positive integers into the infinite quadrant array whose cell (row r, column c), both 0-indexed, holds (c+1)^2 - r if r <= c and r^2 + 1 + c if r > c. Every positive integer occupies exactly one cell. For n >= 1 let a(n) = -1 if n is prime, and otherwise the number of primes among the up to 8 king-move neighbours of n's cell that lie in the quadrant. Claim: (i) a(n) < 6 for all n >= 1, and (ii) for n >= 1, a(n) = 5 holds if and only if n = 6. + +**What the kernel checks against the OEIS data** + +a_data checks all 81 listed terms a(1..81) (index i+1, matching offset 1) with decide +kernel. I compared with the OEIS data by script: identical (81/81). val_data checks `val` against the 66 listed A060734 terms (antidiagonals read downward) and against the 6x6 example array in the entry. pos_val and val_pos prove that val is a bijection from ℕ×ℕ onto the positive integers. Together these pin the layout. The data also pins king-move adjacency: a(1) = 2 needs the diagonal neighbour 3, and a(6) = 5 needs the diagonals 2 and 12/10. It also pins the treatment of border cells: cells outside the quadrant are absent, as with the zero padding in the entry's Mathematica program. + +**Points for the reviewer** + +- *Note.* Scope: `statement` is the conjunction of the first two conjectures only. The entry's third conjecture (the set of n with a(n) = 4 is unbounded) is recorded separately as `statement_four_unbounded` and is not settled. The catalogue title scopes the result correctly; any summary saying 'the A326407 conjectures are settled' would overstate it. +- *Note.* 'a(n) = 5 for n={6}' is read as {n >= 1 : a(n) = 5} = {6}, an iff, which is the natural reading of the set notation. The direction a(6) = 5 is also fixed by the data. a 0 is a junk value (pos 0 = (0,0), giving 2) and is excluded by 1 <= n. The inequality a(n) < 6 holds trivially at primes (-1), which agrees with the OEIS convention. + +## A326602: A326602: a(n) is odd iff n is a square + +Verdict of the pre-review: **faithful**. Result: [oeis-a326602](../../results/oeis-a326602/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A326602.lean`](../../lean/Math0/Statements/OEIS/A326602.lean). + +**The conjecture as stated in OEIS** + +> %F A326602 a(n) is odd iff n is square (conjecture). (_Paul D. Hanna_, Aug 08 2019; rev #19, Aug 11 2019, unchanged upstream.) Definition: %N G.f.: Sum_{n>=0} (x^(2*n-1) + 1)^n * x^n / (1 + x^(2*n+1))^(n+1), an even function. %F G.f. A(x) = Sum_{n>=0} a(n)*x^(2*n). %O 0,2 + +**The frozen Lean statement** + +```lean +noncomputable def summand (n : ℕ) : PowerSeries ℤ := + (X ^ (2 * n - 1) + 1) ^ n * X ^ n * invOfUnit ((1 + X ^ (2 * n + 1)) ^ (n + 1)) 1 +noncomputable def A : PowerSeries ℤ := + mk fun N => ∑ n ∈ Finset.range (N + 1), coeff N (summand n) +-- HasSum summand A proved (hasSum_summand) +def a (n : ℕ) : ℤ := coeffA (2 * n) -- theorem a_eq_coeff : a n = coeff (2 * n) A + +def statement : Prop := + ∀ n : ℕ, Odd (a n) ↔ IsSquare n +``` + +**What the Lean statement says** + +Let A(x) be the formal power series over ℤ given by the sum over m >= 0 of (x^(2m-1) + 1)^m x^m / (1 + x^(2m+1))^(m+1), where the m = 0 summand is 1/(1+x). Let a(n) be the coefficient of x^(2n) in A. Then for every n >= 0, a(n) is odd if and only if n = k^2 for some integer k >= 0 (so n = 0 counts as a square). + +**What the kernel checks against the OEIS data** + +a_data checks all 68 listed terms a(0..67) (index i+0, matching offset 0) with decide +kernel. I compared with the OEIS data by script: identical (68/68), signs included. a_eq_coeff proves a n = coeff (2n) A for every n, and hasSum_summand proves A is the sum of the OEIS summands, so the definition is fixed by proof and the data is a cross-check. coeffA_odd_data checks that the odd-index coefficients 1, 3, ..., 79 vanish, a sanity check of 'even function'. + +**Points for the reviewer** + +- *Note.* At m = 0 the OEIS factor (x^(-1)+1)^0 involves a negative exponent. In Lean, 2*0-1 truncates to 0, giving (X^0+1)^0 = 1. Both equal 1 because the outer exponent is 0, so the truncated subtraction does no harm. For m >= 1 the subtraction is exact. +- *Note.* Evenness of A is checked only for the first 40 odd coefficients, not proved. It plays no role, because a(n) is defined, as in the entry ('A(x) = Sum a(n) x^(2n)', PARI polcoeff(A,2*n)), as the x^(2n) coefficient. IsSquare on ℕ counts 0 as a square, consistent with a(0) = 1 being odd and with the entry's list of odd terms starting at a(0^2). + +## A328202: The gcd of the interior binomial coefficients of row n equals Λ-exp(n)·Λ-exp(n−1) (A328202, Maiga's conjecture) + +Verdict of the pre-review: **faithful**. Result: [oeis-a328202](../../results/oeis-a328202/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A328202.lean`](../../lean/Math0/Statements/OEIS/A328202.lean). + +**The conjecture as stated in OEIS** + +> %F A328202 a(n) = A014963(n) * A014963(n - 1) (conjecture). - _Jon Maiga_, Oct 08 2019. Definition (entry by _Joel Kaufmann_, Oct 07 2019): %N a(n) is the greatest common divisor of all the numbers in row n of Pascal's triangle excluding 1 and n. %O 4,1. (Upstream differs from the local mirror only in the %K keyword 'changed'; text identical.) [Also in the entry, not targeted: %C (Robert Israel, Oct 16 2019) 'If p is a Fermat prime > 3, a(p)=2*p. If p is a Mersenne prime, a(p+1)=2*p. Conjecture: these are the only cases where a(n)>n.'] + +**The frozen Lean statement** + +```lean +def a (n : ℕ) : ℕ := (Finset.Icc 2 (n - 2)).gcd (Nat.choose n) +def expMangoldt (m : ℕ) : ℕ := if IsPrimePow m then m.minFac else 1 +-- theorem cast_expMangoldt : (expMangoldt m : ℝ) = Real.exp (ArithmeticFunction.vonMangoldt m) + +def statement : Prop := + ∀ n : ℕ, 4 ≤ n → a n = expMangoldt n * expMangoldt (n - 1) +``` + +**What the Lean statement says** + +For every integer n >= 4, the gcd of the binomial coefficients C(n,k) with 2 <= k <= n-2 equals L(n)·L(n-1). Here L(m) = p if m is a power p^t (t >= 1) of a prime p, and L(m) = 1 otherwise. + +**What the kernel checks against the OEIS data** + +a_data checks all 75 listed terms a(4..78) (index i+4, matching offset 4) with decide +kernel. I compared with the OEIS data by script: identical (75/75). expMangoldt_data checks the 95 listed terms A014963(1..95), and cast_expMangoldt proves expMangoldt = exp ∘ Λ (Mathlib's von Mangoldt function) for all m. Both definitions are therefore fixed by proof or by direct definition, and the data agrees. + +**Points for the reviewer** + +- *Note.* 'Excluding 1 and n' is encoded positionally, dropping k = 0, 1, n-1, n. For n >= 4 every C(n,k) with 2 <= k <= n-2 is >= n(n-1)/2 > n, so the value-based reading gives the same set. The entry's own example ('remove the first and last 2 numbers') and its programs (k = 2..n/2) agree with the encoding. +- *Note.* Scope: Robert Israel's separate conjecture in the same entry (a(n) > n only at Fermat primes > 3 and at n = Mersenne prime + 1) is recorded as `statementIsrael` and is not part of `statement`. The result certifies only Maiga's formula, which is what the catalogue title claims. a n for n < 4 is junk (e.g. gcd over the empty set = 0) and is excluded by 4 <= n. n-1 is an exact subtraction. Catalogue classification: known result (Kaplan–Levy 2004), first formalization. This is not a fidelity issue. diff --git a/review/fidelity/packet-08.md b/review/fidelity/packet-08.md new file mode 100644 index 0000000..14c981e --- /dev/null +++ b/review/fidelity/packet-08.md @@ -0,0 +1,413 @@ +# Fidelity review packet 08 of 11 + +Prepared on 29 Oct 2026 by an adversarial reviewing agent, not by a person. It is meant to make a human review of these statements quick: for each one it quotes the OEIS conjecture and the frozen Lean statement, restates the Lean in plain words, and lists anything a reviewer should look at. See [the index](README.md). + +Statements in this packet: A332010, A333650, A334592, A334595, A334603, A335012, A338885, A341761, A342645, A342992. + +## A332010: A332010: the average first letter of one-descent derangements has denominator 2^(n-2) + +Verdict of the pre-review: **faithful**. Result: [oeis-a332010](../../results/oeis-a332010/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A332010.lean`](../../lean/Math0/Statements/OEIS/A332010.lean). + +**The conjecture as stated in OEIS** + +> %C A332010 Conjecture: T(n, 1) = 2^(n-2). (entry by _Peter Kagey_, Feb 04 2020; name: "Irregular triangle of denominators of the average value of the first letter over all derangements of {1, 2, ..., n} with k descents."; offset 2,2; keyword tabf). Text unchanged in the live oeisdata (rev #17, Mar 30 2024). + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n : ℕ, 2 ≤ n → T n 1 = 2 ^ (n - 2) + +with +def IsDerangement (w : List ℕ) : Prop := ∀ (i : ℕ) (h : i < w.length), w[i] ≠ i + 1 +def des (w : List ℕ) : ℕ := (w.zip w.tail).countP fun p => p.2 < p.1 +def ders (n k : ℕ) : List (List ℕ) := + (List.range' 1 n).permutations.filter fun w => decide (IsDerangement w) && des w == k +def avgFirstLetter (E : List (List ℕ)) : ℚ := + (((E.map fun w => w.headD 0).sum : ℕ) : ℚ) / ((E.length : ℕ) : ℚ) +def avgFirst (n k : ℕ) : ℚ := avgFirstLetter (ders n k) +def T (n k : ℕ) : ℕ := (avgFirst n k).den +``` + +**What the Lean statement says** + +For every n ≥ 2, list the permutations of {1,...,n} in one-line notation that have no fixed point (w_i ≠ i for every position i) and exactly one descent (exactly one i with w_i > w_{i+1}). Take the average of their first letters as a rational number. In lowest terms its denominator is 2^(n-2). + +**What the kernel checks against the OEIS data** + +a_data kernel-checks the first 25 listed terms (rows n = 2..8 of the triangle, all columns k up to the row length), through a structurally recursive copy (rowC) that is proved equal to the real definition (row_eq_rowC: mem/nodup of the enumeration, derB_one, desB_eq, permutation invariance of the average). example_T41 checks the worked example: the derangements of 4 letters with one descent are exactly [2,3,4,1],[2,4,1,3],[3,4,1,2],[4,1,2,3], the average is 11/4 and T(4,1) = 4. That covers the whole definition (derangement test, descent count, first letter, reduced denominator) across 7 rows and many k, so the definitions are pinned down. Terms 26-50 (rows 9-11) are not kernel-checked. My independent brute force gives T(n,1) = 2^(n-2) for n = 2..9, including T(9,1) = 128, the listed term 26. + +**Points for the reviewer** + +- *Note.* The range n ≥ 2 is the full set of rows (offset 2), and n - 2 is exact there. The junk case (no derangement with k descents, 0/0 = 0, den = 1) never arises for k = 1 and n ≥ 2, because [2,3,...,n,1] is a derangement with exactly one descent. The statement is not weakened. +- *Note.* Only rows 2-8 (25 of the 50 listed terms) are kernel-checked. The definition is a direct transcription of the entry's name and is exercised on 7 rows and every column, so the risk is negligible. rowLen (row length, taken from the entry's comment) appears only in the data check, never in `statement`. +- *Note.* Catalogue metadata only, not the Lean statement: the area is "Discrete geometry", but this is permutation enumeration (combinatorics). + +## A333650: Domino towers of height 2 and of height n-1, n-2, n-3 (A333650): all four Kagey/Luschny conjectures + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a333650](../../results/oeis-a333650/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A333650.lean`](../../lean/Math0/Statements/OEIS/A333650.lean). + +**The conjecture as stated in OEIS** + +> %C A333650 Conjecture: For n > 1, T(n,2) = A000071(n+2). [_Peter Kagey_, Mar 31 2020, entry author] +> %C A333650 Conjecture: T(n,n-1) = A339252(n-2). - _Peter Kagey_, Nov 21 2020 +> %C A333650 Conjecture: T(n,n-2) = A339254(n-3). - _Peter Luschny_, Nov 29 2020 +> %C A333650 Conjecture: T(n,n-3) = A339029(n-4). - _Peter Luschny_, Dec 01 2020 +> (Luschny's Dec 01 2020 summary: T(2*n + k, n + k) = d_{n}(n + k - 1) for k >= 1 and 0 <= n <= 3, with explicit d_0..d_3.) Name: "Triangle read by rows: T(n,k) gives the number of domino towers of height k consisting of n bricks." Comment: "The towers must have a contiguous base of bricks, and each brick must be at least half supported below by another brick. The stacks do not need to be stable." Offset 1. Unchanged in the live oeisdata (rev #68, Aug 12 2022). + +**The frozen Lean statement** + +```lean +def statement : Prop := + statement_col2 ∧ statement_diag1 ∧ statement_diag2 ∧ statement_diag3 +def statement_col2 : Prop := ∀ n : ℕ, 1 < n → (T n 2 : ℤ) = A000071 (n + 2) +def statement_diag1 : Prop := ∀ n : ℕ, 2 ≤ n → (T n (n - 1) : ℤ) = A339252 (n - 2) +def statement_diag2 : Prop := ∀ n : ℕ, 3 ≤ n → (T n (n - 2) : ℤ) = A339254 (n - 3) +def statement_diag3 : Prop := ∀ n : ℕ, 4 ≤ n → (T n (n - 3) : ℤ) = A339029 (n - 4) + +with (abridged) +def base (b : ℕ) : Finset ℤ := (range b).image fun j : ℕ => 2 * (j : ℤ) +def IsTower (n k : ℕ) (t : List (Finset ℤ)) : Prop := + t.length = k ∧ (∀ L ∈ t, L.Nonempty) ∧ + (∃ b, 0 < b ∧ t.head? = some (base b)) ∧ + (∀ L ∈ t, ∀ x ∈ L, ∀ y ∈ L, x ≠ y → 2 ≤ |x - y|) ∧ + (∀ (i : ℕ) (hi : i < t.length), ∀ x ∈ t[i], Even (x - i)) ∧ + (∀ (i : ℕ) (hi : i + 1 < t.length), ∀ x ∈ t[i + 1], ∃ y ∈ t[i], |x - y| ≤ 1) ∧ + (t.map Finset.card).sum = n +noncomputable def T (n k : ℕ) : ℕ := {t | IsTower n k t}.ncard +def A000071 (n : ℕ) : ℤ := (Nat.fib n : ℤ) - 1 +def A339252 : ℕ → ℤ | 0 => 1 | 1 => 4 | 2 => 11 | n + 3 => 4 * A339252 (n + 2) - 4 * A339252 (n + 1) +def A339254 : ℕ → ℤ | 0 => 1 | 1 => 7 | 2 => 24 | 3 => 70 | 4 => 193 + | n + 5 => 6 * A339254 (n + 4) - 12 * A339254 (n + 3) + 8 * A339254 (n + 2) +noncomputable def A339029 (n : ℕ) : ℤ := coeff n ((1 + 4X - 20X^2 + 8X^3 + 33X^4 - 4X^5 - 33X^6 : ℤ⟦X⟧) * invOfUnit ((1 - 2X)^4) 1) +``` + +**What the Lean statement says** + +A tower is a stack of k nonempty layers of bricks of length 2 (in half-brick units), up to horizontal translation. The bottom layer is b ≥ 1 bricks side by side. Layer i is staggered by i half-bricks (brick-wall pattern, so no brick sits exactly on top of another). Every brick above the bottom overlaps a brick of the layer directly below by exactly half a brick. T(n,k) counts such towers with n bricks and k layers, and mirror images count as different. The claims are: (1) for n ≥ 2, T(n,2) = F(n+2) - 1; (2) for n ≥ 2, T(n,n-1) = A339252(n-2), where A339252 is 1, 4, 11 and then a(m) = 4a(m-1) - 4a(m-2); (3) for n ≥ 3, T(n,n-2) = A339254(n-3), where A339254 is 1, 7, 24, 70, 193 and then a(m) = 6a(m-1) - 12a(m-2) + 8a(m-3); (4) for n ≥ 4, T(n,n-3) = A339029(n-4), the coefficients of (1+4x-20x^2+8x^3+33x^4-4x^5-33x^6)/(1-2x)^4. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 55 listed terms (rows 1-10) through T_eq_Tc (T equals a computable layer-by-layer count, proved). The four right-hand sequences are encoded by their own OEIS %N definitions and kernel-checked against their listed data (A000071: 40 terms with offset 1; A339252: 32 terms; A339254: 30; A339029: 29, via a recurrence proved equal to the power-series definition). statement_check verifies all four identities for n ≤ 10. Ten full rows, which include T(n,n) = 2^(n-1) and row sums 3^(n-1), pin down the tower model, in particular the staggering. My independent Python recomputation of the same model also reproduces row 11 of the entry's %e table (1, 232, 1916, ..., 1024), which is not in DATA, and all four identities up to n = 14. + +**Points for the reviewer** + +- *Note.* The brick-wall staggering (layer-i left ends ≡ i mod 2) is not spelled out in the entry's wording. It is an interpretive choice, but a forced one: without it T(2,2) = 3 and T(n,n) = 3^(n-1), against the listed T(2,2) = 2 and the stated T(n,n) = 2^(n-1). It also matches the cited literature (Gouyou-Beauchamps–Viennot, Bétréma–Penaud, Zeilberger) and the entry's picture for T(3,2) = 4. +- *Note.* Conjectures 2-4 state no range. The file takes the largest range in which the right-hand index is a natural number (n ≥ 2, 3, 4). That is wider than Luschny's d_n summary, which covers only n ≥ 3, 5, 7 for these diagonals. The extra small cases T(2,1) = T(3,1) = T(4,1) = 1 = a(0) are true and kernel-checked by statement_check, so the wider range strengthens the statement without changing what it settles. +- *Note.* Luschny's closed-form summary T(2n+k, n+k) = d_n(n+k-1) is not formalized separately. Through the closed forms recorded in A339252, A339254 and A339029 it reformulates the same three diagonal conjectures, and its n = 0 case is T(k,k) = 2^(k-1), which the entry lists in FORMULA, not as a conjecture. The file says this explicitly. +- *Note.* Values are cast to ℤ because the right-hand sequences are ℤ-valued. A000071(n+2) = F(n+2) - 1 ≥ 1 for n ≥ 1, so there is no sign or truncation issue. All natural-number subtractions (n-1, n-2, n-3, n-2, n-3, n-4) are exact in the stated ranges. + +## A334592: Records of the XOR-triangle zero count A334592 are exactly the powers of two + +Verdict of the pre-review: **faithful**. Result: [oeis-a334592](../../results/oeis-a334592/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A334592.lean`](../../lean/Math0/Statements/OEIS/A334592.lean). + +**The conjecture as stated in OEIS** + +> %C A334592 Conjecture: Records occur at powers of two. (entry by _Peter Kagey_, May 07 2020; name: "Number of zeros in XOR-triangle with first row generated from the binary expansion of n."; offset 1). Unchanged in the live oeisdata (rev #19, May 09 2020). + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, IsRecord n ↔ ∃ k : ℕ, n = 2 ^ k + +with +def IsRecord (n : ℕ) : Prop := 1 ≤ n ∧ ∀ m : ℕ, 1 ≤ m → m < n → a m < a n +def a (n : ℕ) : ℕ := ((xorTriangle (binary n)).map (List.count false)).sum +def xorTriangle (r : List Bool) : List (List Bool) := rows r.length r +def rows : ℕ → List Bool → List (List Bool) | 0, _ => [] | k + 1, r => r :: rows k (xorRow r) +def xorRow (r : List Bool) : List Bool := List.zipWith xor r r.tail +def binary (n : ℕ) : List Bool := (bitsLE n n).reverse -- proved = reverse of Nat.digits 2 n, 1 ↦ true +``` + +**What the Lean statement says** + +Let a(n), for n ≥ 1, be the number of 0 entries in the triangle whose top row is the binary expansion of n (most significant bit first). Each later row is the XOR of adjacent pairs of the row above, down to a single entry. Call n ≥ 1 a record if a(n) > a(m) for every 1 ≤ m < n. Then n is a record if and only if n = 2^k for some k ≥ 0. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 77 listed terms a(1..77), and triangle_53 / a_53 check the entry's worked triangle for n = 53 (a(53) = 9). binary_eq_digits proves the hand-rolled binary expansion equals the reversed Nat.digits. With 77 terms and an explicit triangle, the definition is pinned down. + +**Points for the reviewer** + +- *Note.* Records are strict (a(n) > all earlier terms), the usual OEIS convention, and n = 1 counts as a record (1 = 2^0). The choice matters: with non-strict records, n = 2^k - 1 (k ≥ 2) would also be records (a(3) = a(2), a(7) = a(4), a(15) = a(8), ...; I confirmed this up to 2^16) and the conjecture would be false. The strict reading is the only one under which the author's statement holds. +- *Note.* "Records occur at powers of two" is formalized as a biconditional (record ⇔ power of two). That is stronger than the one-direction reading (every record is a power of two), which is also given as statement_weak and implied by statement. Proving the iff settles both readings. + +## A334595: A334595: a(n) = 1 iff n is a power of two, and the records occur exactly at 1 and 2^k + 1 + +Verdict of the pre-review: **faithful**. Result: [oeis-a334595](../../results/oeis-a334595/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A334595.lean`](../../lean/Math0/Statements/OEIS/A334595.lean). + +**The conjecture as stated in OEIS** + +> %C A334595 Conjecture: Records occur at 1 and at 2^n + 1. +> %C A334595 Conjecture: a(n) = 1 if and only if n is a power of two. +> (entry by _Peter Kagey_, May 07 2020; name: "Binary interpretation of the right diagonal of the XOR-triangle with first row generated from the binary expansion of n."; offset 1). Unchanged in the live oeisdata (rev #18, May 09 2020). + +**The frozen Lean statement** + +```lean +def statement : Prop := statement_records ∧ statement_powTwo +def statement_records : Prop := + ∀ n : ℕ, IsRecord n ↔ (n = 1 ∨ ∃ k : ℕ, 1 ≤ k ∧ n = 2 ^ k + 1) +def statement_powTwo : Prop := + ∀ n : ℕ, 1 ≤ n → (a n = 1 ↔ ∃ k : ℕ, n = 2 ^ k) + +with +def IsRecord (n : ℕ) : Prop := 1 ≤ n ∧ ∀ m : ℕ, 1 ≤ m → m < n → a m < a n +def binExp (n : ℕ) : List ℕ := (Nat.digits 2 n).reverse +def xorRow (row : List ℕ) : List ℕ := List.zipWith (fun x y => x ^^^ y) row row.tail +def triangle (row : List ℕ) : List (List ℕ) := (List.range row.length).map (fun r => xorRow^[r] row) +def rightDiag (row : List ℕ) : List ℕ := (triangle row).map (fun r => r.getLastD 0) +def a (n : ℕ) : ℕ := Nat.ofDigits 2 (rightDiag (binExp n)).reverse +``` + +**What the Lean statement says** + +For n ≥ 1, write n in binary (most significant bit first) and build the XOR-triangle with that top row. Take the last entry of each row, top to bottom, and read the resulting bit string as a binary number with the top entry as the most significant bit. Call that number a(n). Claim (1): with n ≥ 1 a record when a(n) > a(m) for all 1 ≤ m < n, the records are exactly n = 1 and n = 2^k + 1 for k ≥ 1 (3, 5, 9, 17, ...). Claim (2): for n ≥ 1, a(n) = 1 if and only if n is a power of two (2^k, k ≥ 0). + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 70 listed terms a(1..70). triangle_19 and a_19 check the entry's worked example (n = 19: the triangle 10011/1010/111/00/0, right side 10100, a(19) = 20). The top-right entry is read as the MSB, matching the PARI program (Vecrev of v indexed by row length). The definition is pinned down. + +**Points for the reviewer** + +- *Note.* In "2^n + 1" the file takes the exponent as k ≥ 1 and uses strict records. With strict records n = 2 = 2^0 + 1 is not a record (a(2) = a(1) = 1), so excluding k = 0 is required for the conjecture to be true. The alternative natural reading (non-strict records, k ≥ 0) gives the same content: I checked up to 2^16 that the non-strict records are exactly the strict ones plus n = 2. The choice does not change what is settled. +- *Note.* Both conjectures are formalized as biconditionals over n ≥ 1, the strongest reading. "Records occur at 1 and at 2^n+1" becomes "the record set equals {1} ∪ {2^k+1 : k ≥ 1}", which implies both one-directional readings. "Power of two" includes 1 = 2^0, and a(1) = 1 is consistent with that. The junk value a(0) = 0 is excluded by 1 ≤ n in both parts. +- *Note.* Catalogue metadata only: the area is "Discrete geometry" for a binary/XOR-triangle (combinatorics on words) result. + +## A334603: The period of 1/11^n is 2 * 11^(n-1) + +Verdict of the pre-review: **faithful**. Result: [oeis-a334603](../../results/oeis-a334603/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A334603.lean`](../../lean/Math0/Statements/OEIS/A334603.lean). + +**The conjecture as stated in OEIS** + +> %F A334603 a(n) = 2 * 11^(n-1) [conjectured, see comments]. +> %C A334603 Conjecture proposed by the authors in References page 205: if p is a prime with gcd(p,30) = 1 and if the period of 1/p is m then the period of 1/p^n is m*p^(n-1). +> (entry by _Bernard Schott_, May 07 2020; name: "Period of the fraction 1/11^n for n >= 1."; offset 1). Unchanged in the live oeisdata (rev #31, Nov 19 2023). + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ n : ℕ, 1 ≤ n → a n = 2 * 11 ^ (n - 1) + +with +theorem exists_pow_modEq_one {m : ℕ} (h : Nat.Coprime 10 m) : ∃ k, 0 < k ∧ 10 ^ k ≡ 1 [MOD m] +def period (m : ℕ) : ℕ := + if h : Nat.Coprime 10 m then Nat.find (exists_pow_modEq_one h) else 0 +def a (n : ℕ) : ℕ := period (11 ^ n) + +(also defined but NOT the settled statement: +def statement_general : Prop := + ∀ p n : ℕ, p.Prime → Nat.gcd p 30 = 1 → 1 ≤ n → period (p ^ n) = period p * p ^ (n - 1)) +``` + +**What the Lean statement says** + +For every n ≥ 1, the least k ≥ 1 with 10^k ≡ 1 (mod 11^n), that is, the multiplicative order of 10 modulo 11^n, equals 2·11^(n-1). Since 11^n is coprime to 10, 1/11^n has a purely periodic decimal expansion, and this order is its minimal period. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 20 listed terms a(1..20) = 2·11^(n-1) with an order certificate (10^L ≡ 1 and 10^(L/q) ≢ 1 for each prime q | L, by verified binary exponentiation). period_data checks `period` against 35 terms of A051626 (period of 1/m, 3 ≤ m ≤ 90, gcd(m,10) = 1), including non-prime moduli (9, 21, 27, 49, 81, ...). period_eq_orderOf proves period m = orderOf (10 : ZMod m) for m coprime to 10. The definition is pinned down. + +**Points for the reviewer** + +- *Note.* The settled statement is the sequence-specific FORMULA-line conjecture (the case p = 11), not the general De Koninck–Mercier conjecture quoted in the COMMENTS. That general claim is defined as statement_general, is not proved, and is false: p = 487 has gcd(487,30) = 1 and period(1/487^2) = period(1/487). This is the right target, since the formula line is what this entry conjectures ("conjectured, see comments"). A reader should still not take "settles A334603" to mean the comment's general conjecture. The catalogue notes already flag that it is false at 487. +- *Note.* Junk values of `period` (0 for m not coprime to 10; 1 for m = 1, where A051626 has 0) are unreachable: n ≥ 1 gives m = 11^n ≥ 11, coprime to 10. n - 1 is exact for n ≥ 1, which is the full offset range. +- *Note.* This is a classical result (lifting the order from p to p^n when 10^(p-1) ≢ 1 mod p^2; 11 is not a base-10 Wieferich prime). The catalogue correctly labels it known-result-first-formalization. + +## A335012: Repunit residues: a(n) = n - 1 exactly for long period primes + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a335012](../../results/oeis-a335012/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A335012.lean`](../../lean/Math0/Statements/OEIS/A335012.lean). + +**The conjecture as stated in OEIS** + +> %C A335012 Conjecture: a(n) = n-1 if and only if n is a long period prime (A006883), that is, n is a prime and the decimal expansion of 1/n has period n-1. [entry by _Sen-Peng Eu_, May 19 2020; name: "Number of different remainders when the first n terms of 1, 11, 111, 1111, ... are divided by n.", offset 1. Local mirror equals upstream oeisdata (#31, Mar 12 2026).] + +**The frozen Lean statement** + +```lean +def a (n : ℕ) : ℕ := ((Finset.Icc 1 n).image (fun k => ((10 ^ k - 1) / 9) % n)).card + +def IsLongPeriodPrime (p : ℕ) : Prop := + p.Prime ∧ (p = 2 ∨ orderOf (10 : ZMod p) = p - 1) + +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → (a n = n - 1 ↔ IsLongPeriodPrime n) +``` + +**What the Lean statement says** + +For every integer n ≥ 1, let a(n) be the number of distinct residues mod n of the repunits R_1, ..., R_n, where R_k = (10^k - 1)/9. Then a(n) = n - 1 holds exactly when n is prime and either n = 2 or 10 has multiplicative order n - 1 modulo n. + +**What the kernel checks against the OEIS data** + +a_data checks all 81 listed terms a(1..81) with decide +kernel, and the definition is the entry's PARI/Maple program verbatim, so a is pinned down. isLongPeriodPrime_data checks, through the proven-equivalent Boolean isLongPeriodPrimeB (isLongPeriodPrimeB_iff), that the predicate selects exactly the first 24 terms of A006883 below 270 (2, 7, 17, ..., 269). That pins the predicate's handling of 2, 3 and 5. I also checked numerically that (a(n) = n-1) ⟺ IsLongPeriodPrime(n) for all n < 1500. + +**Points for the reviewer** + +- *Note.* 2 counts as a long period prime. That follows A006883, which includes 2 by an explicit comment (1/2 = 0.5000..., period 1), and its Maple program (p = 2 or ord_p(10) = p-1). Since a(2) = 1 = 2-1, excluding 2 would make the conjecture trivially false, so including it is the reading the author meant. +- *Note.* "Decimal period of 1/n is n-1" is encoded as ord_n(10) = n-1. This is equivalent for primes other than 2 and 5. For p = 5, Mathlib gives orderOf (0 : ZMod 5) = 0 ≠ 4, which matches the true period 1 ≠ 4. For p = 3, ord = 1 ≠ 2, which also matches. +- *Note.* The range is n ≥ 1, the entry's offset, and both directions of the iff are encoded. Without the hypothesis, n = 0 would hold vacuously via truncated subtraction (0 - 1 = 0), so the hypothesis is correct and loses nothing. + +## A338885: A338885: the smallest number in row 655 is 104, not A228286(655) = 115 + +Verdict of the pre-review: **faithful**. Result: [oeis-a338885](../../results/oeis-a338885/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A338885.lean`](../../lean/Math0/Statements/OEIS/A338885.lean). + +**The conjecture as stated in OEIS** + +> %C A338885 Conjecture: The smallest number in the n-th row is A228286(n). [entry by _Peter Kagey_, Nov 14 2020; name: "Irregular triangle read by rows in which the n-th row lists all numbers k such that there exists a diagonal lattice rectangle touching all four sides of an n X k rectangle."; "A diagonal lattice rectangle is a rectangle with integer coordinates and no side parallel to the x-axis."; offset 2. A228286: "Smallest x + y*z, given x*y + z = n (for positive integers x, y, z).", offset 2. Mirror equals upstream (#22, Sep 11 2021).] + +**The frozen Lean statement** + +```lean +def InBox (n k : ℕ) (p : ℤ × ℤ) : Prop := 0 ≤ p.1 ∧ p.1 ≤ n ∧ 0 ≤ p.2 ∧ p.2 ≤ k +def vertices (x₀ y₀ u₁ u₂ v₁ v₂ : ℤ) : List (ℤ × ℤ) := + [(x₀, y₀), (x₀ + u₁, y₀ + u₂), (x₀ + u₁ + v₁, y₀ + u₂ + v₂), (x₀ + v₁, y₀ + v₂)] +def InRow (n k : ℕ) : Prop := + ∃ x₀ y₀ u₁ u₂ v₁ v₂ : ℤ, u₁ * v₁ + u₂ * v₂ = 0 ∧ u₂ ≠ 0 ∧ v₂ ≠ 0 ∧ + (∀ p ∈ vertices x₀ y₀ u₁ u₂ v₁ v₂, InBox n k p) ∧ + (∃ p ∈ vertices .., p.1 = 0) ∧ (∃ p ∈ vertices .., p.1 = n) ∧ + (∃ p ∈ vertices .., p.2 = 0) ∧ (∃ p ∈ vertices .., p.2 = k) +def A228286List (n : ℕ) : List ℕ := (List.range' 1 (n - 1)).flatMap fun x => + (List.range' 1 (n - 1)).filterMap fun y => if x * y < n then some (x + y * (n - x * y)) else none +def A228286 (n : ℕ) : ℕ := (A228286List n).min?.getD 0 + +def statement : Prop := + ∀ n : ℕ, 2 ≤ n → IsLeast {k : ℕ | InRow n k} (A228286 n) + +(Settled negatively: Frontier result : ¬ statement, via n = 655, k = 104.) +``` + +**What the Lean statement says** + +For every n ≥ 2, consider the k such that some rectangle with integer vertices, perpendicular sides and no horizontal side lies in the box [0,n]×[0,k] and has a vertex on each of the four lines x=0, x=n, y=0, y=k. The least such k equals min{x + y·z : x, y, z ≥ 1, x·y + z = n}. + +**What the kernel checks against the OEIS data** + +a_data checks the 71 listed terms (rows 2–12 complete and the start of row 13) with decide +kernel. These are computed from the list row n, and the proven theorem mem_row says row n contains exactly the k with InRow n k. The geometric InRow is itself proven equivalent (inRow_iff_param) to: n = a+b, k = c+d, ab = cd with a, b, c, d > 0. A228286_data checks 70 listed terms of A228286, and isLeast_A228286 proves that the computed A228286 n is the true minimum of the defining set for n ≥ 2. So both sides are pinned to the entries' definitions, not only to the data. I recomputed independently: A228286(655) = 115, the minimum of row 655 is 104, and the counterexamples below 1100 are 655, 845, 909 and 1019. + +**Points for the reviewer** + +- *Note.* This is a refutation, so the frozen statement must not be stronger than the conjecture. It is not: IsLeast {k | InRow n k} (A228286 n) is exactly "the smallest number in row n is A228286(n)". The counterexample is an explicit rectangle (4,0), (655,42), (651,104), (0,62): its sides (651,42) and (-4,62) are perpendicular and neither is horizontal. It puts 104 < 115 in row 655, so the conjecture fails under any reasonable reading of "touching all four sides". +- *Note.* Row 655 lies beyond the b-file (rows 2..101), so the counterexample rests on the geometric definition, not on listed data. That definition matches the entry's example: row 6 = 6, 9, 10, with width n and height k. + +## A341761: The subword complexity polynomial S(n,x) has leading coefficient n(n+1)/2 (A341761, Guo's conjecture) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a341761](../../results/oeis-a341761/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A341761.lean`](../../lean/Math0/Statements/OEIS/A341761.lean). + +**The conjecture as stated in OEIS** + +> %C A341761 Conjecture: the coefficient of x^n in S(n,x) is n*(n+1)/2. [entry by _Shiyao Guo_, Feb 19 2021; "S(n,x) is the sum of subword complexities (number of nonempty distinct subwords) of all words of length n and an alphabet with size x."; "The degree of S(n,x) is n."; offset 0. Mirror equals upstream (#33, Mar 20 2024).] + +**The frozen Lean statement** + +```lean +def factors {α} [DecidableEq α] (w : List α) : Finset (List α) := + (w.tails.flatMap fun t => t.inits.tail).toFinset -- proven: u ∈ factors w ↔ u ≠ [] ∧ u <:+: w +def complexity (w : List α) : ℕ := (factors w).card +def S (n x : ℕ) : ℕ := ∑ w : Fin n → Fin x, complexity (List.ofFn w) + +def statement : Prop := + ∀ n : ℕ, ∃ P : ℚ[X], (∀ x : ℕ, P.eval (x : ℚ) = (S n x : ℚ)) ∧ + P.coeff n = (n : ℚ) * (n + 1) / 2 +``` + +**What the Lean statement says** + +For every n ≥ 0, let S(n,x) be the total, over all x^n words of length n on an x-letter alphabet, of the number of distinct nonempty contiguous subwords. There is a rational polynomial P with P(x) = S(n,x) for every natural x, including x = 0, and its x^n coefficient is n(n+1)/2. Such a P is unique (poly_unique). + +**What the kernel checks against the OEIS data** + +rows_data checks rows n = 0..5 of the triangle with decide +kernel, by Newton interpolation of S(n,0..n), and a_data checks the 21 terms a(0..20). This pins down "subword = contiguous factor": the subsequence version would give different values from n = 3 on, e.g. S(3,2) ≠ 36. The entry's example (complexities 3,5,5,5,5,5,5,3 for length 3 over 2 letters) also fixes it. Row 6 is not kernel-checked (too many words); I recomputed it independently by brute force as [0,-2,10,-18,10,-15,21], which matches OEIS. + +**Points for the reviewer** + +- *Note.* The existential packs in polynomiality of S(n,·) on all of ℕ, including x = 0 where S(n,0) = 0 for n ≥ 1. This is at least as strong as the conjecture, which presupposes polynomiality, and P is unique, so no weaker reading is possible. +- *Note.* The statement does not also assert deg P = n. The entry states that as a fact, not as part of the conjecture, and "the coefficient of x^n" is well defined regardless of degree. Nothing is lost. +- *Note.* The kernel data check covers only rows 0–5. The definition is the literal one, so this is not a weakness of fidelity. + +## A342645: A342645: diagonals of the eventual Mahonian-column polynomials + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a342645](../../results/oeis-a342645/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A342645.lean`](../../lean/Math0/Statements/OEIS/A342645.lean). + +**The conjecture as stated in OEIS** + +> %C A342645 Conjecture: For each m, T(n,n-m) is a polynomial of degree 2m whose leading coefficient is abs(A290030(m)/A053657(m+1)). +> %F A342645 Conjectures: +> %F A342645 T(n,n) = 1. +> %F A342645 T(n,n-1) = (-3n + n^2)/2. +> %F A342645 T(n,n-2) = (-2n + 21n^2 - 22n^3 + 3n^4)/24. +> %F A342645 T(n,n-3) = (96n - 134n^2 + 13n^3 + 37n^4 - 13n^5 + n^6)/48. +> [entry by _Peter Kagey_, Mar 17 2021; name: "Triangle read by rows: T(n,k) gives n! times the coefficient of x^k in the polynomial that describes the number of permutations on x letters with major index n."; offset 0. Mirror equals upstream (#25, Aug 12 2022).] + +**The frozen Lean statement** + +```lean +-- mahonian x n = [q^n] ∏_{i (mahonian (n + i) n : ℤ) +def Trow (n : ℕ) : List ℤ := newton n 0 (diffHeads (n + 1) (column n)) + -- coefficients of n!·P_n, P_n = interpolant of degree ≤ n through (x, mahonian x n), x = n..2n +def T (n k : ℕ) : ℤ := (Trow n).getD k 0 +def A290030 (n : ℕ) : ℤ := ((lcmDen (norlund n) : ℚ) * (norlund n).getD n 0).num + -- norlund n = coefficient list in x of B_n^(x) = n![t^n](t/(e^t-1))^x +def A053657 (n : ℕ) : ℕ := ∏ p ∈ (Finset.range (n + 1)).filter Nat.Prime, + p ^ (∑ k ∈ Finset.range n, (n - 1) / ((p - 1) * p ^ k)) + +def statementDiagonals : Prop := + ∀ m : ℕ, ∃ Q : ℚ[X], Q.degree = ((2 * m : ℕ) : WithBot ℕ) ∧ + Q.leadingCoeff = |(A290030 m : ℚ) / (A053657 (m + 1) : ℚ)| ∧ + ∀ n : ℕ, m ≤ n → (T n (n - m) : ℚ) = Q.eval (n : ℚ) +def statementFormulas : Prop := + (∀ n, T n n = 1) ∧ + (∀ n, 1 ≤ n → (T n (n-1) : ℚ) = (-3n + n^2)/2) ∧ + (∀ n, 2 ≤ n → (T n (n-2) : ℚ) = (-2n + 21n^2 - 22n^3 + 3n^4)/24) ∧ + (∀ n, 3 ≤ n → (T n (n-3) : ℚ) = (96n - 134n^2 + 13n^3 + 37n^4 - 13n^5 + n^6)/48) [all in ℚ] +def statement : Prop := statementDiagonals ∧ statementFormulas +``` + +**What the Lean statement says** + +Let M(x,n) be the Mahonian number, the coefficient of q^n in ∏_{i %C A342992 Conjecture: a(n) > 0 for all n that are not divisible by 5. [entry by _Metin Sariyar_, Apr 13 2021; name: "Smallest k such that k*n contains only prime digits, or 0 if no such k exists."; offset 1. Mirror equals upstream (#60, Apr 22 2021).] + +**The frozen Lean statement** + +```lean +def PrimeDigits (m : ℕ) : Prop := 0 < m ∧ ∀ d ∈ Nat.digits 10 m, d.Prime + +noncomputable def a (n : ℕ) : ℕ := + if h : ∃ k, PrimeDigits (k * n) then Nat.find h else 0 + +def statement : Prop := ∀ n : ℕ, 1 ≤ n → ¬ 5 ∣ n → 0 < a n +``` + +**What the Lean statement says** + +Every positive integer n not divisible by 5 has a positive multiple whose decimal digits all lie in {2, 3, 5, 7}. Equivalently, the least k with k·n having only prime digits exists and is nonzero. + +**What the kernel checks against the OEIS data** + +a_data checks all 81 listed terms a(1..81) with decide +kernel, through aSearch with bound 100, which the theorem a_eq_of_aSearch proves sound for both the minimality and the "0 when 10 | n" cases. a_four checks the entry's example a(4) = 8. This pins down the definition, including that k starts at 1 and that 0 is excluded as a digit string. a_pos_iff proves that 0 < a n ⟺ ∃ k, PrimeDigits (k·n). As an extra check, a BFS over residues finds a prime-digit multiple for every n < 3000 with 5 ∤ n. + +**Points for the reviewer** + +- *Note.* PrimeDigits requires m > 0, so the empty digit list of 0 cannot satisfy it vacuously. As a result k = 0 never qualifies, and a(n) > 0 is exactly the existence of a prime-digit multiple. This matches the entry's intent and its PARI program, which starts at k = 1. +- *Note.* The hypothesis 1 ≤ n is redundant (5 | 0), and the condition 5 ∤ n is the author's, a sufficient condition only. The 625k exceptions in Corneth's comment are all divisible by 5 and do not interact with the statement. +- *Note.* Catalog metadata only: upstream.decl for this entry is "def statement", not the qualified name "Math0.Statements.A342992.statement" that the other entries use. Cosmetic; the frontier file proves `result : statement` against the frozen file. diff --git a/review/fidelity/packet-09.md b/review/fidelity/packet-09.md new file mode 100644 index 0000000..f8f488e --- /dev/null +++ b/review/fidelity/packet-09.md @@ -0,0 +1,454 @@ +# Fidelity review packet 09 of 11 + +Prepared on 29 Oct 2026 by an adversarial reviewing agent, not by a person. It is meant to make a human review of these statements quick: for each one it quotes the OEIS conjecture and the frozen Lean statement, restates the Lean in plain words, and lists anything a reviewer should look at. See [the index](README.md). + +Statements in this packet: A344710, A348484, A350499, A350557, A350900, A351743, A354571, A355076, A355339, A355360. + +## A344710: A344710: non-obtuse lattice triangles with sides >= sqrt(n) have |det| > (sqrt 3 / 2) n + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a344710](../../results/oeis-a344710/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A344710.lean`](../../lean/Math0/Statements/OEIS/A344710.lean). + +**The conjecture as stated in OEIS** + +> FORMULA: "a(n) > sqrt(3/4)*n (conjectured)." Name: "a(n)/2 is the smallest possible area of a non-obtuse triangle with coordinates in Z^2 and no side shorter than sqrt(n)." Offset 1. Entry by _Jonathan F. Waldmann_, May 26 2021 (revision #84, Feb 16 2022; the mirror and current GitHub oeisdata are identical). Related COMMENT: "Conjectured next terms (from the conjectured inequality a(n) > sqrt(3/4)*n) are a(50,...,64) ?= 45, 48, 48, 52, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56." + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → Real.sqrt (3 / 4) * (n : ℝ) < (a n : ℝ) + +where +def det2 (A B C : ℤ × ℤ) : ℤ := (B.1 - A.1) * (C.2 - A.2) - (C.1 - A.1) * (B.2 - A.2) +def dist2 (P Q : ℤ × ℤ) : ℤ := (P.1 - Q.1) * (P.1 - Q.1) + (P.2 - Q.2) * (P.2 - Q.2) +def dotAt (V P Q : ℤ × ℤ) : ℤ := (P.1 - V.1) * (Q.1 - V.1) + (P.2 - V.2) * (Q.2 - V.2) +def IsValid (n : ℕ) (A B C : ℤ × ℤ) : Prop := + det2 A B C ≠ 0 ∧ + (n : ℤ) ≤ dist2 A B ∧ (n : ℤ) ≤ dist2 B C ∧ (n : ℤ) ≤ dist2 C A ∧ + 0 ≤ dotAt A B C ∧ 0 ≤ dotAt B C A ∧ 0 ≤ dotAt C A B +def areas (n : ℕ) : Set ℕ := {k | ∃ A B C : ℤ × ℤ, IsValid n A B C ∧ (det2 A B C).natAbs = k} +noncomputable def a (n : ℕ) : ℕ := sInf (areas n) +(plus proved: areas_nonempty, isLeast_a : IsLeast (areas n) (a n), nonObtuse_iff linking the dot-product test to the entry's 2*max ≤ sum criterion) +``` + +**What the Lean statement says** + +For every n ≥ 1, let a(n) be the least value of |det(B−A, C−A)| (twice the area) over all triples of lattice points A, B, C in Z² that are not collinear, have all three squared side lengths ≥ n, and have all three angles ≤ 90° (dot product at each vertex ≥ 0). Then a(n) > (√3/2)·n, with √(3/4) computed in the reals. + +**What the kernel checks against the OEIS data** + +Two kernel-checked facts. aRegion_data: a computable search aRegion n (A = (0,0), B in the first octant, C in the annulus n ≤ |C|² ≤ 5n/4+2, same IsValid predicate) equals all 49 listed terms. a_data_le: a(n) ≤ listed term for n = 1..49 (via a_le_aRegion). The check is one-sided for a itself: no lower bound a(n) ≥ listed term is proved, because the optimality of the search region is not proved. It still tests IsValid itself. For example, requiring strictly acute angles would raise a(4) above 4, and dropping the angle condition would lower several terms, so either change would break aRegion_data. The definition of a is a direct sInf over all valid triangles, and isLeast_a shows it is a true minimum. + +**Points for the reviewer** + +- *Note.* The data check pins a(n) only from above (a(n) ≤ listed term). Equality with the listed data is shown only for the restricted search aRegion, whose region is not proved to contain an optimum. The definition is a literal transcription of the name, so this does not affect fidelity, but the data do not independently confirm a(n) from below. +- *Note.* Strict vs non-strict makes no difference: √(3/4)·n is irrational for n ≥ 1 and a(n) is an integer. Real.sqrt (3/4) is elaborated in ℝ (0.75), so there is no ℕ-division junk. The non-collinearity conjunct is redundant for n ≥ 1, since a collinear triple with pairwise distances ≥ 1 has an obtuse (180°) angle at the middle point. +- *Note.* The comment's 'conjectured next terms a(50..64)' are not formalized. That is reasonable, because they are guesses that combine the inequality with constructions and are not a separate claim of the author. The inequality itself is classical: a non-obtuse triangle with all sides ≥ D has area ≥ (√3/4)D², and Z² has no equilateral triangle. So the settled statement is elementary, which bears on novelty, not fidelity. + +## A348484: A348484: no two squares two steps apart; the conjectured formula holds + +Verdict of the pre-review: **faithful**. Result: [oeis-a348484](../../results/oeis-a348484/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A348484.lean`](../../lean/Math0/Statements/OEIS/A348484.lean). + +**The conjecture as stated in OEIS** + +> FORMULA: "Conjectures: a(n) = n^2/2 for n == 0 (mod 4). a(n) = (n^2 + 1)/2 for n == 1 or 3 (mod 4). a(n) = n^2/2 + 2 for n == 2 (mod 4)." Name: "Maximum number of squares on an n X n chessboard such that no two are two steps apart horizontally or vertically." Offset 1. Entry by _Yang Hong_, Oct 20 2021 (revision #33, Dec 06 2022; mirror and current GitHub identical). + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + (n % 4 = 0 → a n = n ^ 2 / 2) ∧ + (n % 4 = 1 ∨ n % 4 = 3 → a n = (n ^ 2 + 1) / 2) ∧ + (n % 4 = 2 → a n = n ^ 2 / 2 + 2) + +where +def TwoApart {n : ℕ} (c d : Fin n × Fin n) : Prop := + (c.1 = d.1 ∧ (c.2.val + 2 = d.2.val ∨ d.2.val + 2 = c.2.val)) ∨ + (c.2 = d.2 ∧ (c.1.val + 2 = d.1.val ∨ d.1.val + 2 = c.1.val)) +def Admissible {n : ℕ} (S : Finset (Fin n × Fin n)) : Prop := ∀ c ∈ S, ∀ d ∈ S, ¬ TwoApart c d +def a (n : ℕ) : ℕ := ((Finset.univ : Finset (Finset (Fin n × Fin n))).filter Admissible).sup Finset.card +``` + +**What the Lean statement says** + +For n ≥ 1, let a(n) be the largest size of a set of cells of the n×n board containing no two cells in the same row whose columns differ by exactly 2, and no two cells in the same column whose rows differ by exactly 2. Then a(n) = n²/2 when 4 | n, a(n) = (n²+1)/2 when n is odd, and a(n) = n²/2 + 2 when n ≡ 2 (mod 4). The ℕ divisions are exact in each case. + +**What the kernel checks against the OEIS data** + +a_data proves a(1..10) = 1,4,5,8,13,20,25,32,41,52 (all 10 listed terms) in the kernel. Each value is proved by a two-sided certificate: an admissible witness set of that size, and a labelling with v labels in which equal labels force equal or two-apart cells (sound upper bound, lemma a_eq_of_cert). a_small re-checks a(1..3) by brute force from the definition. This pins the reading of 'two steps apart'. I brute-forced the alternatives for n = 1..6: taxicab distance exactly 2 gives 1,2,3,6,9,12; Chebyshev distance exactly 2 gives 1,4,4,4,9,16; offset (±2,±2) gives 1,4,7,8,16,24. Only the encoded rook-distance-exactly-2 reading gives 1,4,5,8,13,20. + +**Points for the reviewer** + +- *Note.* The ℕ divisions n^2/2 and (n^2+1)/2 are exact in their residue classes, so they match the entry's rational expressions. n = 0 is excluded, as the offset requires. The three implications cover every n ≥ 1, so the conjecture is not weakened. + +## A350499: Kurkov's recursion computes the free cumulants (A350499) + +Verdict of the pre-review: **faithful**. Result: [oeis-a350499](../../results/oeis-a350499/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A350499.lean`](../../lean/Math0/Statements/OEIS/A350499.lean). + +**The conjecture as stated in OEIS** + +> FORMULA: "Conjecture: free cumulants in terms of the free moments are R(n,1) for n > 0 where R(n,k) = R(n-1,k+1) - Sum_{j=1..n-1} R(j,k)*R(n-j,1) for n > 1, k > 0 with R(1,k) = m_k for k > 0. - _Mikhail Kurkov_, Mar 30 2025". Free cumulants per the entry: "O.g.f.: C(x) = 1 + c_1 x + c_2 x^2 + ... = x / (x + m_1 x^2 + m_2 x^3 + m_3 x^4 + ...)^(-1) = x / M^(-1)(x) ..." (entry by _Tom Copeland_, Jan 01 2022; revision #63, Apr 04 2025; mirror and current GitHub identical). + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 0 < n → R (fun k => (MvPolynomial.X k : MvPolynomial ℕ ℤ)) n 1 = freeCumulant n + +where (abridged) +noncomputable def mom (k : ℕ) : MvPolynomial ℕ ℤ := if k = 0 then 1 else MvPolynomial.X k +noncomputable def M : PowerSeries (MvPolynomial ℕ ℤ) := PowerSeries.mk fun i => if i = 0 then 0 else mom (i - 1) +noncomputable def Minv := M.substInvOfIsUnit isUnit_coeff_one_M -- two-sided compositional inverse +noncomputable def Cgf := invOfUnit (PowerSeries.mk fun n => coeff (n + 1) Minv) 1 -- C = x / Minv (Cgf_mul_Minv : Cgf * Minv = X) +noncomputable def freeCumulant (n : ℕ) : MvPolynomial ℕ ℤ := coeff n Cgf +def R {A : Type*} [CommRing A] (m : ℕ → A) : ℕ → ℕ → A + | 0, _ => 0 + | 1, k => m k + | n + 2, k => R m (n + 1) (k + 1) - ∑ j : Fin (n + 1), R m (j + 1) k * R m (n + 1 - j) 1 +(proved: R_one : R m 1 k = m k; R_rec : 1 < n → R m n k = R m (n-1) (k+1) - ∑ j ∈ Finset.Icc 1 (n-1), R m j k * R m (n-j) 1) +``` + +**What the Lean statement says** + +In the polynomial ring Z[m_1, m_2, …], let M(x) = x + m_1x² + m_2x³ + ⋯ and let M^⟨−1⟩ be its compositional inverse. Let c_n be the coefficient of xⁿ in C(x) = x / M^⟨−1⟩(x). Define R(1,k) = m_k and, for n > 1, R(n,k) = R(n−1,k+1) − Σ_{j=1}^{n−1} R(j,k)·R(n−j,1). Then R(n,1) = c_n for every n ≥ 1, as an identity of polynomials. + +**What the kernel checks against the OEIS data** + +a_data checks all 66 listed terms, which are the unsigned coefficients of c_1..c_8 in Abramowitz–Stegun order. The partition order is itself checked against 99 terms of A036036. cumulant_examples checks the signed coefficients of c_1..c_5 against the entry's EXAMPLE section. The computable T is proved equal to |coeff of freeCumulant n| (T_eq_coeff, ev_cumPoly), so these checks bear on the noncomputable freeCumulant used in the statement. Together they pin freeCumulant down, and the definition is literally the entry's o.g.f. Kurkov's array is pinned by the proved lemmas R_one and R_rec, which state the entry's clauses literally with ℕ indices. These clauses determine R(n,k) for all n ≥ 1 by induction, whatever the junk value R(0,k) = 0 is. The data do not test R, which is fine because R is the object of the conjecture. + +**Points for the reviewer** + +- *Note.* The identity is stated in Z[m_1, m_2, …] with indeterminate moments. That is the universal case, and it implies the identity for any moment sequence in any commutative ring, which is the natural reading of 'free cumulants in terms of the free moments'. +- *Note.* The junk values R(0,k) = 0 and R(1,0) = X 0 are never reached from R(n,1) with n ≥ 1, because the recursion only increases k and uses n−j ≥ 1 and j ≥ 1. The entry's normalization m_0 = 1 enters only through M(x) = x + m_1x² + ⋯, as in the entry. The entry's c_n agree with the standard free cumulants, since the derived relation C(M(x)) = M(x)/x is the standard moment–cumulant functional equation. + +## A350557: Signed A350557 is the matrix inverse of A350512, proved + +Verdict of the pre-review: **faithful**. Result: [oeis-a350557](../../results/oeis-a350557/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A350557.lean`](../../lean/Math0/Statements/OEIS/A350557.lean). + +**The conjecture as stated in OEIS** + +> FORMULA: "Conjecture: M(n,k) = (-1)^(n-k) * T(n,k) is matrix inverse of A350512." Name: "Triangle T(n,k) read by rows with T(n,0) = (2*n)! / (2^n * n!) for n >= 0 and T(n,k) = (Sum_{i=k..n} binomial(i-1,k-1) * 2^i * i! / (2*i)!) * (2*n)! / (2^n * n!) for 0 < k <= n." Entry by _Werner Schulte_, Jan 05 2022 (revision #8, Jan 18 2022). A350512 name: "Triangle read by rows with T(n,0) = 1 for n >= 0 and T(n,k) = binomial(n-1,k-1)*(2*k*(n-k) + n)/k for 0 < k <= n." (Schulte; revision #17, Jan 18 2022). Mirror and current GitHub identical for both. + +**The frozen Lean statement** + +```lean +def statement : Prop := + (∀ n j : ℕ, ∑ k ∈ Finset.range (n + 1), L n k * M k j = if n = j then 1 else 0) ∧ + (∀ n j : ℕ, ∑ k ∈ Finset.range (n + 1), M n k * L k j = if n = j then 1 else 0) + +where +def T (n k : ℕ) : ℚ := + if n < k then 0 + else if k = 0 then ((2 * n).factorial : ℚ) / (2 ^ n * n.factorial) + else (∑ i ∈ Finset.Icc k n, + ((i - 1).choose (k - 1) : ℚ) * 2 ^ i * i.factorial / (2 * i).factorial) * + (2 * n).factorial / (2 ^ n * n.factorial) +def L (n k : ℕ) : ℚ := + if n < k then 0 + else if k = 0 then 1 + else ((n - 1).choose (k - 1) : ℚ) * (2 * k * (n - k : ℕ) + n) / k +def M (n k : ℕ) : ℚ := (-1) ^ (n - k) * T n k +``` + +**What the Lean statement says** + +Let T be the A350557 triangle and L the A350512 triangle, both computed in ℚ from their defining formulas and extended by 0 above the diagonal. Let M(n,k) = (−1)^{n−k} T(n,k). Then the infinite lower-triangular matrices L and M are two-sided inverses: for all n, j ≥ 0, Σ_{k=0}^{n} L(n,k)M(k,j) = [n=j] and Σ_{k=0}^{n} M(n,k)L(k,j) = [n=j]. + +**What the kernel checks against the OEIS data** + +T_data checks all 45 listed terms of A350557 (rows 0..8) as exact rationals. L_data checks all 66 listed terms of A350512 (rows 0..10). a_data checks the row-reading of A350557 with offset 0. Together these pin both triangles, including the ℚ divisions and the exact ℕ subtractions (i−1, k−1, n−k with k ≥ 1 and k ≤ n). statement_check confirms both identities for n, j < 12, which is a sanity check of the transcription. + +**Points for the reviewer** + +- *Note.* The statement requires both L·M = I and M·L = I. For lower-triangular matrices with unit diagonal, either one implies the other, so this is equivalent to 'M is the matrix inverse of L', not a strengthening. Finite sums are legitimate because both matrices are lower triangular. +- *Note.* In (−1)^(n−k) the natural subtraction truncates only when k > n, where T(n,k) = 0, so the junk value never matters. + +## A350900: OEIS A350900: Schulte's gcd-ratio double sum is a Dirichlet convolution + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a350900](../../results/oeis-a350900/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A350900.lean`](../../lean/Math0/Statements/OEIS/A350900.lean). + +**The conjecture as stated in OEIS** + +> COMMENT: "Conjecture: Let f be an arbitrary arithmetic function. Define for n > 0 the sequence a(f; n) = Sum_{i=1..n, k=1..n} f(gcd(i,n)/gcd(gcd(i,k),n)); a(f; n) equals Dirichlet convolution of f(n)*A000010(n) and A057660(n); if f is multiplicative, then a(f; n) is multiplicative; row sums of this triangle use f(n) = n (see formula section)." FORMULA: "Conjecture: Row sums equal Dirichlet convolution of A002618 and A057660." Name: "Triangle read by rows: T(n, k) = Sum_{i=1..n} gcd(i,n) / gcd(gcd(i,k),n) for 1 <= k <= n." Entry by _Werner Schulte_, Jan 21 2022 (revision #13, May 24 2024; mirror and current GitHub identical). + +**The frozen Lean statement** + +```lean +def statement : Prop := + (∀ f : ArithmeticFunction ℂ, ∀ n : ℕ, 0 < n → + aF f n = (f.pmul (phi : ArithmeticFunction ℂ) * (A057660Fn : ArithmeticFunction ℂ)) n) ∧ + (∀ f : ArithmeticFunction ℂ, f.IsMultiplicative → (aFun f).IsMultiplicative) ∧ + (∀ n : ℕ, 0 < n → + ((∑ k ∈ Finset.Icc 1 n, T n k : ℕ) : ℂ) = + aF ((ArithmeticFunction.id : ArithmeticFunction ℕ) : ArithmeticFunction ℂ) n) ∧ + (∀ n : ℕ, 0 < n → ∑ k ∈ Finset.Icc 1 n, T n k = (A002618Fn * A057660Fn) n) + +where +def T (n k : ℕ) : ℕ := ∑ i ∈ Finset.Icc 1 n, Nat.gcd i n / Nat.gcd (Nat.gcd i k) n +def phi : ArithmeticFunction ℕ := ⟨Nat.totient, Nat.totient_zero⟩ +def A057660 (m : ℕ) : ℕ := ∑ k ∈ Finset.Icc 1 m, m / Nat.gcd m k (A057660Fn its ArithmeticFunction) +def A002618 (n : ℕ) : ℕ := n * Nat.totient n (A002618Fn its ArithmeticFunction) +def aF {R} [AddCommMonoid R] (f : ArithmeticFunction R) (n : ℕ) : R := + ∑ i ∈ Finset.Icc 1 n, ∑ k ∈ Finset.Icc 1 n, f (Nat.gcd i n / Nat.gcd (Nat.gcd i k) n) +def aFun f : ArithmeticFunction R := ⟨aF f, _⟩ +``` + +**What the Lean statement says** + +Let a(f;n) = Σ_{i=1}^{n} Σ_{k=1}^{n} f(gcd(i,n)/gcd(gcd(i,k),n)). The statement has four parts. (1) For every complex-valued arithmetic function f and every n ≥ 1, a(f;n) = Σ_{de=n} f(d)φ(d)·A057660(e), where A057660(m) = Σ_{k=1}^{m} m/gcd(m,k). (2) If f is multiplicative (f(1) = 1 and f(mn) = f(m)f(n) for coprime m, n), so is n ↦ a(f;n). (3) For n ≥ 1, the row sum Σ_{k=1}^{n} T(n,k) of the triangle T(n,k) = Σ_i gcd(i,n)/gcd(gcd(i,k),n) equals a(id;n). (4) For n ≥ 1, that row sum equals the Dirichlet convolution of A002618(n) = nφ(n) with A057660, evaluated at n. + +**What the kernel checks against the OEIS data** + +T_data and a_data check all 78 listed terms of A350900 (rows 1..12), which pins T and the exact ℕ division. A057660_data checks 52 listed terms of A057660 and A002618_data checks 20 terms of A002618, so the referenced sequences are pinned. The definitions are the OEIS names, and φ is Mathlib's totient. statement_check_rows confirms part 4 for n ≤ 12, and statement_check_aF confirms the identity of part 1 for one non-multiplicative test function and n ≤ 12. Both are transcription sanity checks. + +**Points for the reviewer** + +- *Note.* 'Arbitrary arithmetic function' is read as ArithmeticFunction ℂ, which forces f(0) = 0. f is never evaluated at 0, since its argument is ≥ 1 on the sum's range and Dirichlet convolution uses only positive divisors, so nothing is lost. Part 1 is linear in the values of f with integer coefficients, so the ℂ version implies it for any additive-group-valued f. Part 2 is stated only for ℂ-valued multiplicative f, which is the standard meaning. +- *Note.* Part 3 reads 'row sums of this triangle use f(n) = n' as the identity rowsum(n) = a(id;n). That identity holds by exchanging the finite sums, so this part is trivially true. It is the most natural reading of a loosely worded clause, and part 4 (the FORMULA-section conjecture) carries the substantive row-sum claim. +- *Note.* aFun f is a(f;·) with value 0 at n = 0 (empty sum). Mathlib's IsMultiplicative imposes nothing beyond n ≥ 1 that could fail here, so 'a(f;n) is multiplicative' for n > 0 is captured faithfully. + +## A351743: A351743: from n = 139 the sequence is affine in 42-blocks, which proves Sycamore's, Sigrist's and the A355149 conjectures + +Verdict of the pre-review: **faithful**. Result: [oeis-a351743](../../results/oeis-a351743/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A351743.lean`](../../lean/Math0/Statements/OEIS/A351743.lean). + +**The conjecture as stated in OEIS** + +> A351743 %N (offset 1): "a(1)=1. Thereafter, a(n+1) is the greatest divisor of s(n) which is prime to a(n), where s(n) is the n-th partial sum." +> A351743 %C (unsigned line; entry by _David James Sycamore_, Jun 07 2022): "Conjecture: a(n)=1 occurs infinitely many times, and therefore so does a(n)=2." +> A351743 %F: "Conjectures from _Rémy Sigrist_, Jun 20 2022: (Start) - a(2*(n+21)-1) = a(2*n-1) for n >= 70, - a(2*(n+21)) = 3645*a(2*n) + b(n) for n >= 70 (where b is 21-periodic). (End)" +> A355149 ("Partial sums of A351743", offset 1; _Michael De Vlieger_, _Rémy Sigrist_ and _David James Sycamore_, Jun 21 2022) %F: "Conjecture: a(n + 42) = 3645*a(n) + b(n) for n >= 138 (where b is 42-periodic)." +> (Upstream oeisdata main is identical to the mirror: A351743 #43, A355149 #11.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + sycamore ∧ sigristOdd ∧ sigristEven ∧ partialSums + +def sycamore : Prop := + {n : ℕ | a n = 1}.Infinite ∧ {n : ℕ | a n = 2}.Infinite +def sigristOdd : Prop := + ∀ n : ℕ, 70 ≤ n → a (2 * (n + 21) - 1) = a (2 * n - 1) +def sigristEven : Prop := + ∃ b : ℕ → ℤ, (∀ n, b (n + 21) = b n) ∧ + ∀ n : ℕ, 70 ≤ n → (a (2 * (n + 21)) : ℤ) = 3645 * (a (2 * n) : ℤ) + b n +def partialSums : Prop := + ∃ c : ℕ → ℤ, (∀ n, c (n + 42) = c n) ∧ + ∀ n : ℕ, 138 ≤ n → (s (n + 42) : ℤ) = 3645 * (s n : ℤ) + c n + +-- definitions (abridged) +def strip : ℕ → ℕ → ℕ → ℕ -- divide w by gcd(w,v) while gcd ≠ 1, with fuel + | 0, w, _ => w + | fuel + 1, w, v => if Nat.gcd w v = 1 then w else strip fuel (w / Nat.gcd w v) v +def coprimePart (w v : ℕ) : ℕ := strip w w v +def step (p : ℕ × ℕ) : ℕ × ℕ := match p with | (x, y) => match coprimePart y x with | z => (z, y + z) +def state (n : ℕ) : ℕ × ℕ := step^[n] (1, 1) +def a : ℕ → ℕ | 0 => 0 | n + 1 => (state n).1 +def s (n : ℕ) : ℕ := ∑ k ∈ Finset.Icc 1 n, a k +-- proved in the file: a_one : a 1 = 1; +-- a_succ_isGreatest (n ≥ 1) : IsGreatest {d | d ∣ s n ∧ Nat.Coprime d (a n)} (a (n + 1)) +``` + +**What the Lean statement says** + +Let a(1) = 1 and, for n ≥ 1, let a(n+1) be the largest d with d | s(n) and gcd(d, a(n)) = 1, where s(n) = a(1) + ... + a(n). The statement asserts all four of the following. (i) a(n) = 1 for infinitely many n, and a(n) = 2 for infinitely many n. (ii) For every n ≥ 70, a(2n+41) = a(2n-1). (iii) There is an integer sequence b with b(n+21) = b(n) for all n such that a(2n+42) = 3645·a(2n) + b(n) for every n ≥ 70. (iv) There is an integer sequence c with c(n+42) = c(n) for all n such that s(n+42) = 3645·s(n) + c(n) for every n ≥ 138. + +**What the kernel checks against the OEIS data** + +a_one and a_succ_isGreatest prove that `a` satisfies the OEIS definition for every n ≥ 1, which determines the sequence. Kernel checks: a_data covers all 67 listed terms a(1..67), s_data all 50 listed terms of A355149 (s(1..50)), and a_example the values a(150..153) = 473394, 1, 2840365, 2 from the entry's last example. The definitions are pinned down, so the data checks are only sanity checks. + +**Points for the reviewer** + +- *Note.* The statement is the conjunction of four separate conjectures (Sycamore's, Sigrist's two, and the A355149 one). The catalogue mode is settles-proves, so proving the conjunction proves each of them. A disproof would not have said which one fails, but that case does not arise here. +- *Note.* 'b is 21-periodic' and 'b is 42-periodic' are encoded as existential ℤ-valued sequences that are periodic on all of ℕ, constrained only for n ≥ 70 and n ≥ 138 respectively. This is equivalent to the literal reading: the differences are integers automatically, and a sequence periodic from some point on extends backwards periodically. Sigrist's b(n) is indexed by n, period 21, as in the text. +- *Note.* a 0 = 0 is a junk value. It plays no role: 0 is in neither {n | a n = 1} nor {n | a n = 2}, and the formulas only use indices 2n-1 ≥ 139, 2n ≥ 140 and s(n) with n ≥ 138. The natural-number subtraction 2*n - 1 is exact for n ≥ 70. +- *Note.* Sycamore's 'and therefore so does a(n)=2' is encoded as a second conjunct ({n | a n = 2}.Infinite), not as an implication. Since the statement is proved, this is the stronger and correct reading. + +## A354571: Even and odd legs with odd prime factors ≡ 3 (mod 4): a(n)/n → π (A354571, A354570) + +Verdict of the pre-review: **faithful**. Result: [oeis-a354571](../../results/oeis-a354571/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A354571.lean`](../../lean/Math0/Statements/OEIS/A354571.lean). + +**The conjecture as stated in OEIS** + +> A354571 %N (offset 1): "Ordered even leg lengths k (listed with multiplicity) of primitive Pythagorean triangles such that all odd prime factors of k are congruent to 3 (mod 4) and at least one prime factor is odd." +> A354571 %C (unsigned line; entry by _Lothar Selle_, Jun 04 2022): "Conjecture: lim_{n->oo} a(n)/n = Pi. Also, lim_{n->oo} A354570(n)/n = Pi." +> A354570 %N (offset 1; _Lothar Selle_, Jun 03 2022): "Ordered odd leg lengths k (listed with multiplicity) of primitive Pythagorean triangles such that all prime factors of k are congruent to 3 (mod 4)." with %C "Conjecture: lim_{n->oo} a(n)/n = Pi. Also, lim_{n->oo} A354571(n)/n = Pi." +> (Upstream oeisdata main is identical to the mirror: A354571 #41, A354570 #54.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + Filter.Tendsto (fun n : ℕ => (a n : ℝ) / n) Filter.atTop (nhds Real.pi) ∧ + Filter.Tendsto (fun n : ℕ => (a354570 n : ℝ) / n) Filter.atTop (nhds Real.pi) + +-- definitions (abridged) +def IsPPT (x y z : ℕ) : Prop := 0 < x ∧ 0 < y ∧ x ^ 2 + y ^ 2 = z ^ 2 ∧ Nat.gcd (Nat.gcd x y) z = 1 +def legTriangles (k : ℕ) : Finset (ℕ × ℕ) := ... -- proved: (b, c) ∈ legTriangles k ↔ IsPPT b k c +def CondE (k : ℕ) : Prop := (∀ p ∈ k.primeFactors, Odd p → p % 4 = 3) ∧ ∃ p ∈ k.primeFactors, Odd p +def CondO (k : ℕ) : Prop := ∀ p ∈ k.primeFactors, p % 4 = 3 +def wE (k : ℕ) : ℕ := if Even k ∧ CondE k then (legTriangles k).card else 0 +def wO (k : ℕ) : ℕ := if Odd k ∧ CondO k then (legTriangles k).card else 0 +def numLE (w : ℕ → ℕ) (k : ℕ) : ℕ := ∑ j ∈ Finset.range (k + 1), w j +noncomputable def nthTerm (w : ℕ → ℕ) (n : ℕ) : ℕ := sInf {k | n ≤ numLE w k} +noncomputable def a (n : ℕ) : ℕ := nthTerm wE n +noncomputable def a354570 (n : ℕ) : ℕ := nthTerm wO n +``` + +**What the Lean statement says** + +For a positive integer k, let N(k) be the number of primitive Pythagorean triangles that have k as a leg (pairs (b, c) with b > 0, b² + k² = c², gcd(b, k, c) = 1). Form the increasing list in which each even k appears N(k) times, when every odd prime factor of k is ≡ 3 (mod 4) and k has at least one odd prime factor; let a(n) be its n-th term (n ≥ 1). Form the increasing list in which each odd k whose prime factors are all ≡ 3 (mod 4) appears N(k) times; let A354570(n) be its n-th term. The statement asserts that a(n)/n → π and A354570(n)/n → π as n → ∞, as real limits. + +**What the kernel checks against the OEIS data** + +mem_legTriangles proves, for every k, that legTriangles k is exactly the set of primitive triangles with leg k. So the multiplicity is pinned down for all k, not only on the checked range. a_spec and a354570_spec, together with the proofs that both lists are infinite, show that nthTerm gives the genuine n-th term. Kernel checks: a_data covers all 58 listed terms of A354571 (multiplicities such as 12×2 and 84×4 included), and a354570_data all 60 listed terms of A354570 (21×2, 33×2 and so on included). + +**Points for the reviewer** + +- *Note.* 'Listed with multiplicity' is read as the number of primitive triangles having k as a leg. For even k the other leg is necessarily odd, so k is the even leg; for odd k it is the odd leg. This matches the entries' examples (12 from (5,12,13) and (12,35,37); 21 from (20,21,29) and (21,220,221)) and all listed data. +- *Note.* a 0 = a354570 0 = 0, and the division by n = 0 gives a junk value at n = 0. Neither affects a limit along atTop. +- *Note.* Both limits from Selle's sentence (the A354571 one and the 'Also' A354570 one) are included as a conjunction. The result proves both. + +## A355076: Integer partial sums of the Calkin-Wilf ratios fusc(k)/fusc(k+1) at n = 2*4^k-1 and 2*4^k-2 (A355076) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a355076](../../results/oeis-a355076/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A355076.lean`](../../lean/Math0/Statements/OEIS/A355076.lean). + +**The conjecture as stated in OEIS** + +> A355076 %N (offset 0): "a(n) is the denominator of Sum_{k = 0..n} fusc(k)/fusc(k+1) (where fusc is Stern's diatomic series A002487)." +> A355076 %F (unsigned line; entry by _Rémy Sigrist_, Jun 18 2022): "Conjecture: a(n) = 1 for n of the form 2*4^k - 1 or 2*4^k - 2 for some k >= 0." +> A002487 %N: "Stern's diatomic series (or Stern-Brocot sequence): a(0) = 0, a(1) = 1; for n > 0: a(2*n) = a(n), a(2*n+1) = a(n) + a(n+1)." +> (Upstream oeisdata main is identical to the mirror, #11.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, (∃ k : ℕ, n = 2 * 4 ^ k - 1 ∨ n = 2 * 4 ^ k - 2) → a n = 1 + +-- definitions +def fuscAux : ℕ → ℕ → ℕ + | 0, _ => 0 + | fuel + 1, n => + if n ≤ 1 then n + else if n % 2 = 0 then fuscAux fuel (n / 2) + else fuscAux fuel (n / 2) + fuscAux fuel (n / 2 + 1) +def fusc (n : ℕ) : ℕ := fuscAux (n + 1) n +def a (n : ℕ) : ℕ := + (∑ k ∈ Finset.range (n + 1), ((fusc k : ℚ) / (fusc (k + 1) : ℚ))).den +-- proved: fusc_zero, fusc_one, fusc_even (fusc (2n) = fusc n), fusc_odd (fusc (2n+1) = fusc n + fusc (n+1)) +``` + +**What the Lean statement says** + +Let fusc be Stern's diatomic sequence. For n ≥ 0, let a(n) be the reduced denominator of the rational number Σ_{k=0}^{n} fusc(k)/fusc(k+1). The statement asserts that for every k ≥ 0, a(2·4^k − 1) = 1 and a(2·4^k − 2) = 1, i.e. the partial sum is an integer at n = 0, 1, 6, 7, 30, 31, 126, 127, ... + +**What the kernel checks against the OEIS data** + +fusc_zero, fusc_one, fusc_even and fusc_odd prove the A002487 recursion for all n, which determines fusc. fusc_data checks the 92 listed terms of A002487. a_data checks all 53 listed terms a(0..52), including the 1's at n = 0, 1, 6, 7, 30, 31 and the non-1 values elsewhere. Rat.den is the reduced denominator, as in the PARI `denominator`. Together these pin the definitions down. + +**Points for the reviewer** + +- *Note.* The statement covers one direction only: if n has the form 2·4^k − 1 or 2·4^k − 2, then a(n) = 1. This is exactly the OEIS wording. It does not claim that these are the only n with a(n) = 1. My Python check to n = 9000 finds a(n) = 1 exactly at n ∈ {0, 1, 6, 7, 30, 31, 126, 127, 510, 511, 2046, 2047, 8190, 8191}, so an 'iff' reading would also fit the data. However, the same author writes 'iff' explicitly when he means it (e.g. A355339), and he does not do so here. The one-directional reading is therefore the natural one, and the result does not cover the converse. +- *Note.* The truncated subtraction is harmless: 2·4^k ≥ 2, so 2*4^k - 1 and 2*4^k - 2 are exact (k = 0 gives n = 1 and n = 0). Division by zero cannot occur, since fusc(k+1) ≥ 1 for all k ≥ 0. + +## A355339: A355339: the central even run of the knight-move triangle has length 1 iff n = 2^m - 2 + +Verdict of the pre-review: **faithful**. Result: [oeis-a355339](../../results/oeis-a355339/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A355339.lean`](../../lean/Math0/Statements/OEIS/A355339.lean). + +**The conjecture as stated in OEIS** + +> A355339 %N (offset 0): "a(n) is the number of central even terms in the n-th row of triangle A355320; a(0) = 0." +> A355339 %F (unsigned line; entry by _Rémy Sigrist_, Jun 29 2022): "Conjecture: a(n) = 1 iff n > 0 and n belongs to A000918." +> A000918 %N (offset 0): "a(n) = 2^n - 2." +> A355320 %N: "Irregular triangle T(n, k), n >= 0, -2*n <= k <= 2*n, read by rows; T(0, 0) = 1; for n > 0, T(n, k) is the sum of all terms in previous rows at one knight's move away." with %F "T(n, k) = T'(n-1, k-2) + T'(n-1, k+2) + T'(n-2, k-1) + T'(n-2, k+1) for n > 0 (where T' extends T with 0's outside its domain of definition)." +> A355339 PARI: max(0, 2*valuation(r >> (2*n), 2)-1). +> (Upstream oeisdata main is identical to the mirror, #10.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, a n = 1 ↔ (0 < n ∧ ∃ m : ℕ, (n : ℤ) = 2 ^ m - 2) + +-- definitions (abridged) +def step (pq : List ℕ × List ℕ) : List ℕ × List ℕ := + (pq.2, addL (addL pq.2 (List.replicate 4 0 ++ pq.2)) + (addL (List.replicate 3 0 ++ pq.1) (List.replicate 5 0 ++ pq.1))) +def rowPair (n : ℕ) : List ℕ × List ℕ := step^[n] ([], [1]) +def row (n : ℕ) : List ℕ := (rowPair n).2 +def entry (r : List ℕ) (m : ℕ) (k : ℤ) : ℕ := if 0 ≤ k + 2 * m then r.getD (k + 2 * m).toNat 0 else 0 +def T (n : ℕ) (k : ℤ) : ℕ := entry (row n) n k +def a (n : ℕ) : ℕ := + if n = 0 then 0 else + let r := row n + let right := (((List.range (2 * n + 1)).map fun k : ℕ => entry r n k).takeWhile fun x => x % 2 == 0).length + let left := (((List.range (2 * n + 1)).map fun k : ℕ => entry r n (-k)).takeWhile fun x => x % 2 == 0).length + if right = 0 then 0 else left + right - 1 +-- proved: T_zero_zero, T_eq_zero (|k| > 2n), T_one, T_add_two (the knight-move recurrence for all k ∈ ℤ) +``` + +**What the Lean statement says** + +Let T(n,k) (n ≥ 0, k ∈ ℤ) be defined by T(0,0) = 1, T(n,k) = 0 for |k| > 2n, and T(n,k) = T(n−1,k−2) + T(n−1,k+2) + T(n−2,k−1) + T(n−2,k+1), where rows with negative index are zero. Let a(0) = 0. For n ≥ 1, let a(n) be the length of the maximal run of consecutive even entries T(n,k) that contains k = 0, or 0 if T(n,0) is odd. The statement asserts that for every n ≥ 0, a(n) = 1 if and only if n ≥ 1 and n = 2^m − 2 for some m ≥ 0, i.e. n ∈ {2, 6, 14, 30, ...}. + +**What the kernel checks against the OEIS data** + +T_zero_zero, T_eq_zero, T_one and T_add_two prove that T satisfies the A355320 definition (the recurrence with zero extension) for all n and k, which determines T. T_data checks the 91 listed terms of A355320 (rows 0–6). a_data checks all 77 listed terms a(0..76), including the 1's at n = 2, 6, 14, 30, 62 and many values > 1 that exercise the run-length reading. The run-length reading is also confirmed by the entry's example (parenthesized central blocks) and by its PARI program (2·valuation − 1 for the symmetric rows). + +**Points for the reviewer** + +- *Note.* 'Number of central even terms' is encoded as left + right − 1, the run of evens to the left and right of k = 0 sharing the center. The PARI program computes 2·right − 1. The two agree because the rows are symmetric (A355320 %F: T(n,−k) = T(n,k)), but that symmetry is not proved in the statement file. They also agree on all 77 checked terms. +- *Note.* Membership in A000918 is encoded in ℤ as (n : ℤ) = 2^m − 2 with m : ℕ. This includes the terms −1 and 0, which are excluded by n > 0 as in the OEIS text. The 'iff' is encoded as a genuine ↔ for every n ≥ 0, and a(0) = 0 is imposed literally. + +## A355360: Columns 1 and 2 of the theta-series triangle A355360 are P(x)^3 and 2P(x)^6 + +Verdict of the pre-review: **faithful**. Result: [oeis-a355360](../../results/oeis-a355360/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A355360.lean`](../../lean/Math0/Statements/OEIS/A355360.lean). + +**The conjecture as stated in OEIS** + +> A355360 %N (offset 0, tabl): "G.f. A(x,y) satisfies: x*y*A(x,y) = Sum_{n=-oo..+oo} (-1)^n * x^(n*(n+1)/2) * A(x,y)^n, with coefficients T(n,k) of x^n*y^k in A(x,y) given as a triangle read by rows." +> A355360 %C (unsigned lines; entry by _Paul D. Hanna_, Jul 19 2022): "Conjectures. (C.1) Column 1 equals A000716, the number of partitions into parts of 3 kinds. (C.2) Column 2 equals twice A023005, the number of partitions into parts of 6 kinds." +> %e: "in which column 1 appears to equal A000716, the coefficients in P(x)^3, and column 2 appears to equal twice A023005, the coefficients in P(x)^6". +> (Upstream oeisdata main is identical to the mirror, #7.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + (∀ n : ℕ, T (n + 1) 1 = A000716 n) ∧ (∀ n : ℕ, T (n + 2) 2 = 2 * A023005 n) + +-- definitions (abridged; Poly = List ℤ (coeffs in y), Ser = List Poly (coeffs in x)) +def thetaCoeff (B : Ser) (m : ℕ) : Poly := -- [x^m] Σ_{n≥0} (-1)^n x^{n(n+1)/2} (B^n - B^{-(n+1)}) + let L := m + 1 + let Binv := sinv L B + ((List.range L).foldl (fun (st : Poly × Ser × Ser) n => + let t := n * (n + 1) / 2 + if t ≤ m then + (padd st.1 (pscale ((-1) ^ n) (padd (st.2.1.getD (m - t) []) (pscale (-1) (st.2.2.getD (m - t) [])))), + smul L st.2.1 B, smul L st.2.2 Binv) + else st) ([], [[1]], Binv)).1 +def coeffs : ℕ → Ser + | 0 => [[1]] + | m + 1 => let B := coeffs m; B ++ [padd (0 :: B.getD m []) (pscale (-1) (thetaCoeff B (m + 1)))] +def T (n k : ℕ) : ℤ := ((coeffs n).getD n []).getD k 0 +def p (m : ℕ) : ℕ := Fintype.card (Nat.Partition m) +def partitionsOfKinds (j n : ℕ) : ℕ := ∑ f ∈ Finset.Nat.antidiagonalTuple j n, ∏ i, p (f i) +def A000716 (n : ℕ) : ℕ := partitionsOfKinds 3 n +def A023005 (n : ℕ) : ℕ := partitionsOfKinds 6 n +``` + +**What the Lean statement says** + +Let A(x,y) = Σ_m a_m(y) x^m, with a_m ∈ ℤ[y], be given by a_0 = 1 and a_{m+1} = y·a_m − [x^{m+1}] F(a_0 + a_1 x + ... + a_m x^m), where F(B) = Σ_{n∈ℤ} (−1)^n x^{n(n+1)/2} B^n. This is the unique power-series solution of x·y·A = F(A). Let T(n,k) = [x^n y^k] A. The statement asserts that for every n ≥ 0, T(n+1, 1) equals the number of partitions of n into parts of 3 kinds (= [x^n] P(x)^3), and T(n+2, 2) equals twice the number of partitions of n into parts of 6 kinds (= 2·[x^n] P(x)^6). Equivalently, the y- and y²-coefficients of A are x·P³ and 2x²·P⁶. + +**What the kernel checks against the OEIS data** + +a_data checks all 66 DATA terms (rows 0–10), and T_example_rows checks rows 11 and 12 from the EXAMPLE section, 91 triangle entries in all. A000716_data checks 10 terms of A000716 and A023005_data 6 terms of A023005 (via p_eq_pb, proved). statement_check verifies the column alignment for 10 and 6 values. The recursion `coeffs` is literally the entry's PARI program (new coefficient = [x^m](x y A − F(A)) with that coefficient set to 0). With 91 matching entries a wrong definition is implausible, but see the note. + +**Points for the reviewer** + +- *Note.* T is defined by the coefficient recursion, which is the entry's PARI program, not as the coefficients of a series proved in the statement file to satisfy x·y·A = F(A). The equivalence is argued only in the docstring, and the argument is correct: order x^0 forces a_0 = 1, and at order x^m only the n = −1 term −A^{−1} sees a_m, contributing +a_m. Since the OEIS data were generated by this same program and 13 rows match, this is not a fidelity risk. +- *Note.* The column alignment is T(n+1,1) = A000716(n) and T(n+2,2) = 2·A023005(n): column k starts at the diagonal entry T(k,k), and the targets have offset 0. The entry's EXAMPLE section displays exactly this alignment (column 1 = 1, 3, 9, 22, ... against P³ = 1 + 3x + 9x² + ...). The entries T(0,1), T(0,2) and T(1,2), which lie outside the triangle, are correctly not included. +- *Note.* 'Partitions into parts of j kinds' is defined as a sum over j-tuples (n_1, ..., n_j) with Σ n_i = n of Π p(n_i), which is the coefficient of x^n in P(x)^j. This is the g.f. given in both A000716 and A023005, and it is checked on their first listed terms. diff --git a/review/fidelity/packet-10.md b/review/fidelity/packet-10.md new file mode 100644 index 0000000..382d726 --- /dev/null +++ b/review/fidelity/packet-10.md @@ -0,0 +1,403 @@ +# Fidelity review packet 10 of 11 + +Prepared on 29 Oct 2026 by an adversarial reviewing agent, not by a person. It is meant to make a human review of these statements quick: for each one it quotes the OEIS conjecture and the frozen Lean statement, restates the Lean in plain words, and lists anything a reviewer should look at. See [the index](README.md). + +Statements in this packet: A356360, A357216, A357583, A362086, A363482, A363609, A367119, A368846, A369366, A373345. + +## A356360: A356360: the continued-fraction denominators are 1 or prime + +Verdict of the pre-review: **faithful**. Result: [oeis-a356360](../../results/oeis-a356360/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A356360.lean`](../../lean/Math0/Statements/OEIS/A356360.lean). + +**The conjecture as stated in OEIS** + +> %N Denominator of the continued fraction 1/(2-3/(3-4/(4-5/(...(n-1)-n/(n+1))))). %C Conjecture: The sequence contains only 1's and the primes. (%A _Mohammed Bouras_, Oct 15 2022; offset 3; entry rev #31, Aug 06 2024, identical in the local mirror and current GitHub oeisdata.) + +**The frozen Lean statement** + +```lean +def step (k : ℕ) (t : ℚ) : ℚ := (k : ℚ) - ((k : ℚ) + 1) / t +def cf (n : ℕ) : ℚ := 1 / (List.range' 2 (n - 2)).foldr step ((n : ℚ) + 1) +def a (n : ℕ) : ℕ := (cf n).den + +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → a n = 1 ∨ (a n).Prime +``` + +**What the Lean statement says** + +For every natural number n ≥ 3, start with t = n+1 and, for k = n-1, n-2, ..., 2 in turn, replace t by k - (k+1)/t (exact rational arithmetic, with Lean's convention x/0 = 0). Let c = 1/t. Then the denominator of c in lowest terms is either 1 or a prime number. + +**What the kernel checks against the OEIS data** + +`example : cf 3 = 4/5 ∧ cf 4 = 11/7 ∧ cf 5 = 11/3` and `theorem a_data`, which checks a 3, ..., a 84 against all 82 listed terms. Both are kernel-checked with decide +kernel. I compared the Lean list with the %S/%T/%U lines of the entry and they match exactly. The definition is a literal transcription of the %N formula, and these checks fix the reduced-denominator reading (for example a(8) = 1 because the value is an integer). + +**Points for the reviewer** + +- *Note.* Junk values: if some tail of the fraction were 0, Lean's x/0 = 0 would give a junk value. If the outermost tail were 0, cf = 0 and a n = 1, so the claim would hold trivially at that n. The docstring rules this out by induction: every tail t_k exceeds u_k = k(k-2)/(k-1) ≥ 0. I also checked by exact arithmetic that no tail vanishes for 3 ≤ n < 1200. The definition therefore agrees with the real continued fraction for every n ≥ 3. +- *Note.* The statement covers only the %C conjecture, read as 'every term is 1 or prime' (a subset claim; it does not say every prime occurs). That reading is the right one, because 2 never occurs (a(n) divides 2n-1). It does not include the stronger %F line 'From the conjecture: Except for n = 5, a(n) = 2n-1 if 2n-1 is prime, 1 otherwise', nor McEachen's separate 2024 conjecture that all odd primes after 11 appear in order. Neither is the conjecture targeted here. + +## A357216: Internal n-gons in a regular n-gon: triple points occur only for n = 3, 4, 6, and otherwise there are n k^2 + 1 regions (Shannon's A357216 conjecture) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a357216](../../results/oeis-a357216/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A357216.lean`](../../lean/Math0/Statements/OEIS/A357216.lean). + +**The conjecture as stated in OEIS** + +> %N Table read by antidiagonals: T(n,k) (n >= 3, k >= 0) is the number of regions in an n-gon when k internal n-gons are drawn between the n*k points that divide each side into k+1 equal parts. %C Conjecture: the only n-gons that contain non-simple intersections are the 3-gon (triangle), 4-gon (square), and 6-gon (hexagon). %F Conjectured formula for all columns for n >= 7: T(n,k) = n*k^2 + 1. %F Conjectured formula for all rows except for n = 3, 4, 6: T(n,k) = n*k^2 + 1. (%A _Scott R. Shannon_, Sep 18 2022; the conjecture lines are unsigned, so they are the author's; rev #23, Sep 21 2022, unchanged upstream.) + +**The frozen Lean statement** + +```lean +noncomputable def vertex (n j : ℕ) : ℂ := Complex.exp (2 * Real.pi * Complex.I * j / n) +noncomputable def divPt (n k j m : ℕ) : ℂ := + vertex n j + ((m : ℂ) / ((k : ℂ) + 1)) * (vertex n (j + 1) - vertex n j) +noncomputable def chord (n k : ℕ) (c : Fin n × Fin k) : Set ℂ := + segment ℝ (divPt n k (c.1 : ℕ) ((c.2 : ℕ) + 1)) (divPt n k ((c.1 : ℕ) + 1) ((c.2 : ℕ) + 1)) +noncomputable def polygon (n : ℕ) : Set ℂ := + convexHull ℝ (Set.range fun j : Fin n => vertex n j) +noncomputable def regionSet (n k : ℕ) : Set ℂ := + interior (polygon n) \ ⋃ c : Fin n × Fin k, chord n k c +noncomputable def regions (n k : ℕ) : ℕ := + Nat.card (ConnectedComponents (regionSet n k)) +def HasNonSimpleIntersection (n k : ℕ) : Prop := + ∃ p : ℂ, ∃ c₁ c₂ c₃ : Fin n × Fin k, c₁ ≠ c₂ ∧ c₁ ≠ c₃ ∧ c₂ ≠ c₃ ∧ + p ∈ chord n k c₁ ∧ p ∈ chord n k c₂ ∧ p ∈ chord n k c₃ + +def statement : Prop := + (∀ n : ℕ, 3 ≤ n → ((∃ k : ℕ, HasNonSimpleIntersection n k) ↔ (n = 3 ∨ n = 4 ∨ n = 6))) ∧ + (∀ n k : ℕ, (n = 5 ∨ 7 ≤ n) → regions n k = n * k ^ 2 + 1) + +(Abridged: the file also defines a computable T n k by exact arithmetic in Z[2cos(2π/n)], and the sequence a, which reads T by antidiagonals. These are used only for the data check, not by `statement`.) +``` + +**What the Lean statement says** + +Take the regular n-gon with vertices V_j = exp(2πij/n). For m = 1..k, let P_{j,m} be the point m/(k+1) of the way from V_j to V_{j+1}. The drawn segments are [P_{j,m}, P_{j+1,m}] for j = 0..n-1 and m = 1..k: the m-th internal n-gon joins the m-th points of consecutive sides, all counted in the same direction. (1) For every n ≥ 3, there is some k and some point of the plane lying on three distinct drawn segments if and only if n is 3, 4 or 6. (2) For n = 5 and every n ≥ 7, and every k ≥ 0, the open n-gon minus all n·k segments has exactly n·k^2 + 1 connected components. + +**What the kernel checks against the OEIS data** + +`theorem a_data` (decide +kernel) checks all 66 listed terms, which are antidiagonals n+k = 3..13. I compared the Lean list with the OEIS data and they match exactly. The check runs on the computable T, not on `regions` or `HasNonSimpleIntersection`, and the link T n k = regions n k is stated in the docstring but not proved. The kernel check therefore confirms the chord construction, which T shares (same index m on consecutive sides, boundary positions j(k+1)+m), but it does not formally pin down the topological definitions used in `statement`. The docstring also reports Python and floating-point cross-checks: the 195 EXAMPLE values for n = 3..15 and k = 0..14, and T(3,5)=70<76, T(4,5)=93<101 and T(6,9)=475<487 as the first triple-point deficits. + +**Points for the reviewer** + +- *Minor.* The kernel data check validates the computable T, not the geometric `regions` and `HasNonSimpleIntersection` that `statement` actually uses, and T = regions is not proved. A mistake in the topological encoding would not be caught by a_data. By reading, the encoding is literal and sound: open convex hull minus closed segments, Nat.card of the connected components, and k = 0 gives 1. Distinct chord indices give distinct, non-collinear segments, because a line meets the convex boundary in only 2 points. Also, the proved equality regions n k = n k^2 + 1 rules out a degenerate definition for n = 5 and n ≥ 7. +- *Note.* Construction reading: the m-th internal n-gon joins the m-th division points of consecutive sides, counted in the same direction, so each internal n-gon is a rotated, scaled copy of the outer one. For odd n this is the only rotationally symmetric pairing that closes up into n-gons, and the data (via T) confirm it. The polygon is taken to be regular, which is implicit in Shannon's sequences and images (for example T(5,20) = 2001 = 5·400+1). +- *Note.* A 'non-simple intersection' is encoded as a point on three or more distinct internal-polygon sides. The outer polygon's sides are not counted as lines. At each division point exactly two chords meet the outer side, so counting the side would make every n-gon non-simple and contradict the conjecture. No third chord can pass through a division point, because chord interiors lie in the open polygon. +- *Note.* Part (1) is an iff. Besides the conjecture's 'only' direction, it also asserts that n = 3, 4, 6 do have triple points for some k. That is supported by the data deficits and only strengthens the statement. Part (2) is exactly the union of the two %F conjectures: 'all columns for n >= 7' and 'all rows except n = 3, 4, 6', which also covers n = 5. Both are taken for all k ≥ 0. + +## A357583: Kurkov's recursion for the row polynomials of convolution triangles holds + +Verdict of the pre-review: **faithful**. Result: [oeis-a357583](../../results/oeis-a357583/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A357583.lean`](../../lean/Math0/Statements/OEIS/A357583.lean). + +**The conjecture as stated in OEIS** + +> %N Triangle read by rows. Convolution triangle of the Bell numbers. %F Conjecture: row polynomials are x*R(n,1) for n > 0 where R(n,k) = R(n-1,k+1) + x*R(n-1,1)*R(1,k) for n > 1, k > 0 with R(1,k) = Bell(k) for k > 0. The same recursion seems to work for self-convolution of any other sequence. - _Mikhail Kurkov_, Apr 05 2025 (Entry by _Peter Luschny_, Oct 05 2022, offset 0; rev #10, Apr 06 2025, unchanged upstream. The same conjecture appears in A340991, whose %N reads 'Triangle T(n,k) whose k-th column is the k-fold self-convolution of the primes', with %F T(n,k) = [x^n] (Sum_{j>=1} prime(j)*x^j)^k.) + +**The frozen Lean statement** + +```lean +def pad (s : ℕ → R) (j : ℕ) : R := if j = 0 then 0 else s j +def convT (s : ℕ → R) : ℕ → ℕ → R + | n, 0 => if n = 0 then 1 else 0 + | n, k + 1 => ∑ p ∈ Finset.HasAntidiagonal.antidiagonal n, pad s p.1 * convT s p.2 k +def T (n k : ℕ) : ℕ := convT Nat.bell n k +noncomputable def R (s : ℕ → ℤ) : ℕ → ℕ → ℤ[X] + | 0, _ => 0 + | 1, k => C (s k) + | n + 2, k => R s (n + 1) (k + 1) + X * R s (n + 1) 1 * R s 1 k +def bellZ (k : ℕ) : ℤ := (Nat.bell k : ℤ) +noncomputable def rowPoly (s : ℕ → ℤ) (n : ℕ) : ℤ[X] := + ∑ k ∈ Finset.range (n + 1), C (convT s n k) * X ^ k + +def statement : Prop := + (∀ n : ℕ, 0 < n → + ∑ k ∈ Finset.range (n + 1), C (T n k : ℤ) * X ^ k = X * R bellZ n 1) ∧ + (∀ s : ℕ → ℤ, ∀ n : ℕ, 0 < n → rowPoly s n = X * R s n 1) +``` + +**What the Lean statement says** + +For a sequence s, let T_s(n,k) be the coefficient of z^n in (s(1)z + s(2)z^2 + ...)^k; the value s(0) plays no role. Define integer polynomials in x by R_s(1,k) = s(k) and R_s(n,k) = R_s(n-1,k+1) + x·R_s(n-1,1)·R_s(1,k) for n ≥ 2. (1) For s = the Bell numbers and every n ≥ 1, the sum of T(n,k)x^k over k = 0..n equals x·R(n,1). (2) The same identity holds for every integer sequence s and every n ≥ 1. + +**What the kernel checks against the OEIS data** + +`theorem T_data` checks all 11 listed rows n = 0..10 (66 entries). `theorem a_data` checks the 66 terms read by rows, a 0, ..., a 65. Both are kernel-checked (decide +kernel, via the proved rewrite T = Tfast), and the Lean list matches the OEIS data exactly. These checks pin down convT and pad for the Bell case: T(n,1) = Bell(n), and Bell(0) is not used. `convT_eq_coeff` proves convT s n k = [z^n](gf s)^k for every s, which pins down the general triangle. R has no kernel check, but it transcribes the recursion literally. I checked the identity by hand for n ≤ 3 (Bell case) and numerically for n ≤ 8 with a random integer sequence. + +**Points for the reviewer** + +- *Note.* The second sentence ('the same recursion seems to work for self-convolution of any other sequence') is read as: for every s : ℕ → ℤ, the convolution triangle T_s(n,k) = [z^n](Σ_{j≥1} s(j)z^j)^k has row polynomials x·R_s(n,1), where R_s(1,k) = s(k). This matches A357368's PMatrix terminology and A340991's 'k-th column is the k-fold self-convolution'. Because s ranges over all integer sequences, it also covers 0-based or shifted conventions by relabelling. The identity is polynomial in the s(j), so the integer case implies it over any commutative ring. If anything, the formal version is at least as strong as any narrower reading. +- *Note.* Junk values: R s 0 k = 0, and R at k = 0, are never reached starting from R s n 1 with n ≥ 1. Since n > 0 is required, the n = 0 row (polynomial 1 versus x·R(0,1) = 0) is correctly excluded. +- *Note.* Catalog metadata, not the statement: the catalog entry's area is 'Discrete geometry'. It should be combinatorics or enumerative combinatorics. + +## A362086: OEIS A362086: every denominator of 1/(2-3/(3-4/(...(n-1)-n/(-3)))) except 9 is 1 or a prime + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a362086](../../results/oeis-a362086/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A362086.lean`](../../lean/Math0/Statements/OEIS/A362086.lean). + +**The conjecture as stated in OEIS** + +> %N Denominator of the continued fraction 1/(2-3/(3-4/(4-5/(...(n-1)-n/(-3))))). %C Conjecture: Except for 9, every term of this sequence is either a prime or 1. (%A _Mohammed Bouras_, May 28 2023; offset 3; rev #35, May 09 2024, unchanged upstream. %e: for n=3, 1/(2 - 3/(-3)) = 1/3, so a(3)=3; n=4: 13/17; n=5: 13/9.) + +**The frozen Lean statement** + +```lean +def step (k : ℕ) (t : ℚ) : ℚ := (k : ℚ) - ((k : ℚ) + 1) / t +def cf (n : ℕ) : ℚ := 1 / (List.range' 2 (n - 2)).foldr step (-3) +def a (n : ℕ) : ℕ := (cf n).den + +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → a n ≠ 9 → a n = 1 ∨ (a n).Prime +``` + +**What the Lean statement says** + +For every n ≥ 3, start with t = -3 and, for k = n-1 down to 2, replace t by k - (k+1)/t (rational arithmetic, with x/0 = 0). Let a(n) be the reduced denominator of 1/t. Then for every n ≥ 3, if a(n) is not 9, a(n) is 1 or a prime. + +**What the kernel checks against the OEIS data** + +`example : cf 3 = 1/3 ∧ cf 4 = 13/17 ∧ cf 5 = 13/9`, which matches the three %e examples exactly, and `theorem a_data`, which checks all 57 listed terms a 3, ..., a 59. Both are kernel-checked, and the Lean list matches the OEIS data exactly. The definition transcribes %N literally, and the examples fix the shape: the innermost level is (n-1) - n/(-3), and for n = 3 it is the single level 2 - 3/(-3). + +**Points for the reviewer** + +- *Minor.* 'Except for 9' is encoded as exempting every n with a n = 9. On a strict reading, the author is excepting the single term a(5) = 9. The Lean statement is therefore formally weaker by the claim 'the value 9 occurs only once', since a second 9 would refute the strict reading but not the Lean statement. The gap does not matter in practice. Exact computation shows 9 occurs only at n = 5 for 3 ≤ n < 1200. Using the closed form a(n) = N/gcd(N, 3(n-1)(n-3)!) with N = n^2+n-3 (which I checked against exact evaluation for n < 400), 9 | a(n) needs v_3(N) ≥ 3 + v_3((n-3)!), which is impossible for n ≥ 15 or so. The index reading (n = 9) is untenable, because a(5) = 9 is not prime. +- *Note.* Junk values: no tail vanishes. t_{n-1} = (n-1)+n/3 ≥ 2, the later tails stay positive down to t_3, and t_2 ≠ 0 because the closed-form numerator 3·A051403(n-3)+n·A051403(n-4) is positive. I checked by exact arithmetic that no tail vanishes for 3 ≤ n < 1200. A vanishing t_2 would have made a n = 1 trivially. The definition therefore matches the true continued fraction for all n ≥ 3. + +## A363482: OEIS A363482: apart from 49, every denominator of 1/(2-3/(3-4/(...(n-1)-n/(-5)))) is 1 or a prime + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a363482](../../results/oeis-a363482/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A363482.lean`](../../lean/Math0/Statements/OEIS/A363482.lean). + +**The conjecture as stated in OEIS** + +> %N Denominator of the continued fraction 1/(2-3/(3-4/(4-5/(...(n-1)-n/(-5))))). %C Conjecture: Except for 49, every term of this sequence is either a prime or 1. (%A _Mohammed Bouras_, Jun 04 2023; offset 3; rev #29, Jul 13 2025, unchanged upstream. %e: n=3: 5/13, n=4: 19/23, n=5: 11/7. McEachen, Jul 08 2025: 'The conjecture holds through n=10000.') + +**The frozen Lean statement** + +```lean +def step (k : ℕ) (t : ℚ) : ℚ := (k : ℚ) - ((k : ℚ) + 1) / t +def cf (n : ℕ) : ℚ := 1 / (List.range' 2 (n - 2)).foldr step (-5) +def a (n : ℕ) : ℕ := (cf n).den + +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → a n ≠ 49 → a n = 1 ∨ (a n).Prime +``` + +**What the Lean statement says** + +For every n ≥ 3, start with t = -5 and, for k = n-1 down to 2, replace t by k - (k+1)/t (rational arithmetic, with x/0 = 0). Let a(n) be the reduced denominator of 1/t. Then for every n ≥ 3, if a(n) is not 49, a(n) is 1 or a prime. + +**What the kernel checks against the OEIS data** + +`example : cf 3 = 5/13 ∧ cf 4 = 19/23 ∧ cf 5 = 11/7`, which matches the three %e examples, and `theorem a_data`, which checks all 61 listed terms a 3, ..., a 63 (including a 6 = 49 and a 12 = 1). Both are kernel-checked, and the Lean list matches the OEIS data exactly. The definition transcribes %N literally. + +**Points for the reviewer** + +- *Minor.* 'Except for 49' is encoded as exempting every n with a n = 49. On a strict reading, the author is excepting the single term a(6) = 49, so the Lean statement is weaker by 'the value 49 occurs only once'. The gap does not matter in practice. Exact computation shows 49 occurs only at n = 6 for 3 ≤ n < 1200. Using the closed form a(n) = N/gcd(N, 5(n-1)(n-3)!) with N = n^2+3n-5 (which I checked for n < 400), 49 | a(n) needs v_7(N) ≥ 2 + v_7(5(n-1)(n-3)!), which fails for all n beyond about 50 because of size. The catalog summary itself states that 49 occurs only at n = 6. +- *Note.* Junk values: t_{n-1} = (n-1)+n/5 > 0, the later tails are positive down to t_3, and t_2 ≠ 0 because the closed-form numerator 5·A051403(n-3)+n·A051403(n-4) is positive. I checked by exact arithmetic that no tail vanishes for 3 ≤ n < 1200. Lean's x/0 = 0 therefore never comes into play for n ≥ 3. + +## A363609: A363609: a(k^3) = 6k(k+2), the cube is the optimal polycube of k^3 dice + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a363609](../../results/oeis-a363609/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A363609.lean`](../../lean/Math0/Statements/OEIS/A363609.lean). + +**The conjecture as stated in OEIS** + +> %F A363609 Conjecture: a(k^3) = 6*(k+2)*k for k > 1. (Unattributed formula line; entry by _Matt Donahoe_, Jun 11 2023, rev #45 Sep 03 2023. Name: "Minimum sum of the visible pips on a polycube made from n dice." Comment: "This sequence is calculated using standard six-sided dice of the same chirality. Opposite sides sum to seven." Offset 1. Example: "For n = 2, two dice are conjoined to hide both their 6-pip faces, so a(2) = 30.") + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ k : ℕ, 1 < k → a (k ^ 3) = 6 * (k + 2) * k + +-- dependencies (verbatim, abridged to the definitional core) +abbrev Cell := ℤ × ℤ × ℤ +def dirs : Finset Cell := {(1, 0, 0), (-1, 0, 0), (0, 1, 0), (0, -1, 0), (0, 0, 1), (0, 0, -1)} +def IsOrientation (o : Cell × Cell) : Prop := o.1 ∈ dirs ∧ o.2 ∈ dirs ∧ dot o.1 o.2 = 0 +def pips (o : Cell × Cell) (d : Cell) : ℕ := + if d = o.1 then 1 else if d = o.2 then 2 else if d = cross o.1 o.2 then 3 + else if d = -cross o.1 o.2 then 4 else if d = -o.2 then 5 else if d = -o.1 then 6 else 0 +def visiblePips (P : Finset Cell) (o : Cell → Cell × Cell) : ℕ := + ∑ c ∈ P, ∑ d ∈ dirs, if c + d ∈ P then 0 else pips (o c) d +def Adj (P : Finset Cell) (u v : Cell) : Prop := u ∈ P ∧ v ∈ P ∧ v - u ∈ dirs +def FaceConnected (P : Finset Cell) : Prop := ∀ x ∈ P, ∀ y ∈ P, Relation.ReflTransGen (Adj P) x y +def totals (n : ℕ) : Set ℕ := + {t | ∃ P : Finset Cell, P.card = n ∧ FaceConnected P ∧ + ∃ o : Cell → Cell × Cell, (∀ c ∈ P, IsOrientation (o c)) ∧ visiblePips P o = t} +noncomputable def a (n : ℕ) : ℕ := sInf (totals n) +``` + +**What the Lean statement says** + +Place one die in each cell of a finite face-connected set P of unit cubes in Z^3. Each die is independently given one of the 24 rotations of a fixed right-handed die (1 on u, 2 on v, 3 on u×v, and 7−k opposite the k-face). A face of a die counts if the neighbouring cell in that direction is not in P (this includes bottom faces and faces facing an enclosed empty cell). a(n) is the least possible total of counted pips over all such n-cell polycubes and all orientations. Claim: for every integer k ≥ 2, a(k^3) = 6k(k+2). + +**What the kernel checks against the OEIS data** + +wits_ok / a_le_data: for every one of the 57 listed terms a(1..57), a kernel-checked face-connected witness polycube attains the listed value, so a(n) ≤ listed value. a_data: kernel-checked exhaustive enumeration (up to the 48 cube symmetries) gives the exact values a(1..7) = 21, 30, 40, 40, 51, 52, 54. These pin down that all six faces count (a(1) = 21), that opposite faces sum to 7 (a(2) = 30), face-connectivity, and the per-die minimisation. For n = k^3 only upper bounds are checked (a(8) ≤ 48, a(27) ≤ 90). Neither chirality nor the cavity convention is pinned, since no polycube with ≤ 7 cells encloses a cavity. + +**Points for the reviewer** + +- *Minor.* Faces that face an enclosed cavity count as visible. The file justifies this by the listed a(26) = 93: under the other reading, the 3×3×3 cube minus its centre would give ≤ 90. But Donahoe's dice.py only searches box-plus-slab layouts and never builds a cavity, so the data are weak evidence either way. The Lean reading matches the author's convention that every exposed face counts, bottom faces included (a(1) = 21), so it is the natural one. Under the other reading, the Lean result gives only a(k^3) ≤ 6k(k+2), not equality. The projection-type lower bound plausibly also holds there, but that is not part of this statement. +- *Note.* Every die uses the same right-handed numbering. The entry says only "same chirality". Reflecting the whole configuration swaps the chiralities and keeps the pip total, so the minimum is the same either way. +- *Note.* The data values come from a heuristic search, so the Lean a(n) (a true minimum over all polycubes) could in principle fall below a listed term for some n. This does not affect the k^3 statement, whose upper bound comes from the cube. + +## A367119: Edges of the all-chords graph of a triangle with n general-position points per side (A367119) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a367119](../../results/oeis-a367119/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A367119.lean`](../../lean/Math0/Statements/OEIS/A367119.lean). + +**The conjecture as stated in OEIS** + +> %F A367119 Conjecture: a(n) = (3/2)*(3*n^4 + 4*n^3 + 3*n^2 + 4*n + 2). (_Scott R. Shannon_ and _N. J. A. Sloane_, Nov 05 2023; rev #14 Nov 09 2023.) Name: "Place n points in general position on each side of an equilateral triangle, and join every pair of the 3*n+3 boundary points by a chord; sequence gives number of edges in the resulting planar graph." Comment: "'In general position' implies that the internal lines (or chords) only have simple intersections. There is no interior point where three or more chords meet." Offset 0. + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ (n : ℕ) (B : Finset ℂ), IsPlacement n B → GeneralPosition B → + (edges B : ℚ) = 3 / 2 * (3 * n ^ 4 + 4 * n ^ 3 + 3 * n ^ 2 + 4 * n + 2) + +-- dependencies (verbatim) +noncomputable def corner : Fin 3 → ℂ := ![0, 1, ⟨1 / 2, Real.sqrt 3 / 2⟩] +noncomputable def triangle : Set ℂ := convexHull ℝ (Set.range corner) +def IsPlacement (n : ℕ) (B : Finset ℂ) : Prop := + (∀ j : Fin 3, corner j ∈ B) ∧ + (∀ z ∈ B, ∃ j : Fin 3, z ∈ segment ℝ (corner j) (corner (j + 1))) ∧ + (∀ j : Fin 3, ((B : Set ℂ) ∩ openSegment ℝ (corner j) (corner (j + 1))).ncard = n) +def drawn (B : Finset ℂ) : Set (Set ℂ) := {s | ∃ p ∈ B, ∃ q ∈ B, p ≠ q ∧ s = segment ℝ p q} +def GeneralPosition (B : Finset ℂ) : Prop := + ∀ z ∈ interior triangle, ∀ s₁ ∈ drawn B, ∀ s₂ ∈ drawn B, ∀ s₃ ∈ drawn B, + z ∈ s₁ → z ∈ s₂ → z ∈ s₃ → s₁ = s₂ ∨ s₁ = s₃ ∨ s₂ = s₃ +def vertices (B : Finset ℂ) : Set ℂ := (B : Set ℂ) ∪ {z | ∃ s ∈ drawn B, ∃ t ∈ drawn B, s ∩ t = {z}} +def planarGraph (B : Finset ℂ) : SimpleGraph ℂ := + SimpleGraph.fromRel fun u v => + u ∈ vertices B ∧ v ∈ vertices B ∧ (∃ s ∈ drawn B, u ∈ s ∧ v ∈ s) ∧ + ∀ w ∈ vertices B, w ∉ openSegment ℝ u v +noncomputable def edges (B : Finset ℂ) : ℕ := (planarGraph B).edgeSet.ncard +``` + +**What the Lean statement says** + +Fix the equilateral triangle with corners 0, 1 and 1/2 + (√3/2)i. Let B be the three corners plus exactly n points in the open interior of each side, and nothing else. Draw the segment between every pair of distinct points of B. Assume that no point of the open triangle lies on three distinct drawn segments. The vertices of the graph are B together with every point where two drawn segments meet in exactly one point. The edges join two vertices that lie on a common drawn segment with no vertex strictly between them. Claim: for every n ≥ 0 and every such B, the number of edges is (3/2)(3n^4 + 4n^3 + 3n^2 + 4n + 2). + +**What the kernel checks against the OEIS data** + +a_data checks a 0, …, a 10 = 3, 24, 153, 588, 1635, 3708, 7329, 13128, 21843, 34320, 51513 in the kernel. Here `a` is a combinatorial surrogate: 3n+3 boundary edges plus the sum over interior chords of (1 + number of interleaving chords). The file states but does not prove that a n = edges B, so the kernel check does not pin down the geometric definitions used in `statement`. As an independent check, I computed the geometric definition exactly (rational arithmetic, random side points on an affine image of the triangle, vertices = B ∪ singleton intersections, edges = consecutive vertex pairs on drawn segments) for n = 0..4. It gives 3, 24, 153, 588, 1635, which agree with the data and the formula. + +**Points for the reviewer** + +- *Minor.* The kernel data check is on the computable surrogate `a`, which is not linked to `edges`. So the geometric statement's definitions (vertices, adjacency, placement, general position) are validated only by inspection and by my numerical check, not by a kernel-checked term. On inspection they are correct: chords cannot overlap; side pieces overlapping on a common side are excluded from the vertices by the `s ∩ t = {z}` clause; consecutive boundary points give the 3n+3 side edges; and n = 0 gives 3. +- *Note.* "General position" is read exactly as the entry's comment: no three distinct drawn segments meet at an interior point. Since this is the weakest reading and the statement quantifies over all such B, the statement is at least as strong as intended. General-position placements exist for every n (generic points), so the statement is not vacuous, though the file does not prove this. +- *Note.* The entry presupposes that the edge count does not depend on B. The Lean statement asserts the formula for every admissible B, which is the right reading. + +## A368846: Diagonal sums of A368846 equal A229580 (Luschny's conjecture) + +Verdict of the pre-review: **faithful**. Result: [oeis-a368846](../../results/oeis-a368846/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A368846.lean`](../../lean/Math0/Statements/OEIS/A368846.lean). + +**The conjecture as stated in OEIS** + +> %C A368846 Conjecture: |Sum_{j=0..k} T(k + j, k)| = A229580(k + 1) for k >= 0. (_Peter Luschny_, Jan 07 2024; rev #26 Feb 17 2025.) Name: "Triangle read by rows: T(n, k) = (-1)^(n + k)*2*binomial(2*k - 1, n)* binomial(2*n + 1, 2*k) for k > 0, and k^n for k = 0." Offset 0. A229580 (R. H. Hardin, offset 1): "Number of defective 3-colorings of an n X 2 0..2 array connected horizontally and antidiagonally with exactly one mistake, and colors introduced in row-major 0..2 order." + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ k : ℕ, |∑ j ∈ Finset.range (k + 1), T (k + j) k| = (A229580 (k + 1) : ℤ) + +-- dependencies (verbatim) +def T (n k : ℕ) : ℤ := + if k = 0 then 0 ^ n + else (-1) ^ (n + k) * 2 * ((2 * k - 1).choose n : ℤ) * ((2 * n + 1).choose (2 * k) : ℤ) +abbrev Cell (n : ℕ) := Fin n × Fin 2 +def Cell.rank {n : ℕ} (p : Cell n) : ℕ := 2 * p.1.val + p.2.val +def IsEdge {n : ℕ} (p q : Cell n) : Prop := + (p.1 = q.1 ∧ p.2 = 0 ∧ q.2 = 1) ∨ (p.1.val + 1 = q.1.val ∧ p.2 = 1 ∧ q.2 = 0) +def mistakes {n : ℕ} (c : Cell n → Fin 3) : ℕ := + (Finset.univ.filter fun e : Cell n × Cell n => IsEdge e.1 e.2 ∧ c e.1 = c e.2).card +def ColorsInOrder {n : ℕ} (c : Cell n → Fin 3) : Prop := + ∀ p : Cell n, c p ≠ 0 → ∃ q : Cell n, q.rank < p.rank ∧ (c q).val + 1 = (c p).val +def A229580 (n : ℕ) : ℕ := + (Finset.univ.filter fun c : Cell n → Fin 3 => mistakes c = 1 ∧ ColorsInOrder c).card +``` + +**What the Lean statement says** + +Let T(n,k) = (−1)^(n+k)·2·C(2k−1,n)·C(2n+1,2k) for k ≥ 1, and T(n,0) = 0^n (so T(0,0) = 1). Let A229580(m) count the 3-colourings of an m-row, 2-column array whose colour word, read in row-major order, is a restricted growth word (one representative per relabelling of colours), and which have exactly one monochromatic edge. The edges are the horizontal ones (i,0)–(i,1) and the antidiagonal ones (i,1)–(i+1,0). Claim: for every k ≥ 0, |T(k,k) + T(k+1,k) + … + T(2k,k)| = A229580(k+1), as integers. + +**What the kernel checks against the OEIS data** + +a_data checks all 55 listed terms of the triangle (rows 0..9) in the kernel, which pins T, including T(0,0) = 1 and the sign. A229580_data checks A229580(1..3) = 1, 6, 40 from the colouring definition. sum_data shows that the left-hand side for k = 0..21 equals the 22 listed terms of A229580. statement_check confirms the full equation with the Lean A229580 for k = 0, 1, 2. The data do not distinguish antidiagonal from diagonal edges, but this does not affect the count: either way the graph is a path on the 2n cells, and the restricted-growth condition picks one colouring per orbit of colour permutations whatever the cell order. The entry's first example solution (0 1 / 0 0 / 1 0) confirms the antidiagonal reading. + +**Points for the reviewer** + +- *Note.* Only A229580(1..3) are kernel-checked against the colouring definition, since larger n are too slow. The definition is robust, though: ColorsInOrder is equivalent to the row-major word being a restricted growth word, and the n×2 orientation (n rows, 2 columns) is fixed by the entry's 3×2 examples and the value 40. +- *Note.* T is evaluated only at (k+j, k) with 0 ≤ j ≤ k, which lies inside the triangle. The natural-number subtraction 2k−1 is used only for k ≥ 1, so it never truncates. + +## A369366: The least number of inequivalent cells of a (6k+5)-iamond is 3(k+1) + +Verdict of the pre-review: **faithful**. Result: [oeis-a369366](../../results/oeis-a369366/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A369366.lean`](../../lean/Math0/Statements/OEIS/A369366.lean). + +**The conjecture as stated in OEIS** + +> %C A369366 Conjecture: a(6k+5) = 3(k+1) for all k >= 0. Observed for k = 0, 1, 2 (n = 5, 11, 17). The next test case is a(23), predicted to be 12. (From _Peter Exley_, Apr 07 2026; rev #14 Apr 14 2026.) Name: "Least number of inequivalent cells in a polyiamond with n cells." Comment: "Equivalently, a(n) is the least number of free rooted (or pointed) polyiamonds (A369365) corresponding to a given polyiamond with n cells." Offset 1. + +**The frozen Lean statement** + +```lean +def statement : Prop := ∀ k : ℕ, a (6 * k + 5) = 3 * (k + 1) + +-- dependencies (verbatim, abridged) +abbrev Pt := ℤ × ℤ × ℤ +def sumC (x : Pt) : ℤ := x.1 + x.2.1 + x.2.2 +def IsCell (x : Pt) : Prop := sumC x = 0 ∨ sumC x = 1 +def Adj (x y : Pt) : Prop := |y.1 - x.1| + |y.2.1 - x.2.1| + |y.2.2 - x.2.2| = 1 +-- perm s : the 6 coordinate permutations; lin s neg x := if neg then -perm s x else perm s x +structure Isom where s : Fin 6; neg : Bool; t : Pt; ht : sumC t = tReq neg -- tReq neg = if neg then 1 else 0 +def Isom.app (g : Isom) (x : Pt) : Pt := lin g.s g.neg x + g.t +def IsConnected (P : Finset Pt) : Prop := ∀ x ∈ P, ∀ y ∈ P, Relation.ReflTransGen (Step P) x y +def IsPolyiamond (n : ℕ) (P : Finset Pt) : Prop := P.card = n ∧ (∀ x ∈ P, IsCell x) ∧ IsConnected P +def Equivalent (P : Finset Pt) (c d : Pt) : Prop := ∃ g : Isom, P.image g.app = P ∧ g.app c = d +noncomputable def cls (P : Finset Pt) (c : Pt) : Finset Pt := P.filter (Equivalent P c) +noncomputable def numClasses (P : Finset Pt) : ℕ := (P.image (cls P)).card +noncomputable def a (n : ℕ) : ℕ := sInf {m | ∃ P : Finset Pt, IsPolyiamond n P ∧ numClasses P = m} +``` + +**What the Lean statement says** + +Label the triangles of the triangular grid by integer triples with coordinate sum 0 or 1; two triangles share an edge exactly when their labels differ by ±1 in one coordinate. A polyiamond with n cells is an edge-connected set of n triangles (holes allowed). Two of its cells are equivalent if some symmetry of the grid (translations, rotations by multiples of 60°, and reflections: the full p6m group) maps the polyiamond onto itself and one cell to the other. a(n) is the least number of equivalence classes over all n-cell polyiamonds. Claim: for every k ≥ 0, a(6k+5) = 3(k+1). + +**What the kernel checks against the OEIS data** + +a_eq_aComp proves that `a` equals a kernel-computable enumeration of free polyiamonds up to grid symmetry, for all n ≥ 1. a_data then checks a(1..8) = 1, 1, 2, 2, 3, 1, 3, 3 in the kernel. These values pin down that reflections are included (with rotations only, a(5) would be 5, not 3), that adjacency is by edges, and the grid model (a(6) = 1 for the hexagon). a(11) and a(17), the k = 1, 2 cases, are not kernel-checked. + +**Points for the reviewer** + +- *Note.* The 12 point-group maps (6 coordinate permutations × ±) together with translations of coordinate sum 0 (or 1 for the negated maps) are exactly the symmetries of the triangular grid, and adjacency is invariant under them. The file's remark that plane isometries preserving a polyiamond are grid symmetries justifies using grid symmetries instead of arbitrary isometries. +- *Note.* a 0 = 0 (empty polyiamond) is a junk value outside the offset; the statement only evaluates a at 6k+5 ≥ 5. + +## A373345: Row lengths of the Schreier-set triangle A373345 are A007895 (number of Zeckendorf summands) + +Verdict of the pre-review: **faithful**. Result: [oeis-a373345](../../results/oeis-a373345/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A373345.lean`](../../lean/Math0/Statements/OEIS/A373345.lean). + +**The conjecture as stated in OEIS** + +> %Y A373345 Cf. A007895 (conjectured row lengths), A072649 (first column), A373346 (row sums), A373347. (_Paolo Xausa_, Jun 01 2024; rev #45 Sep 13 2024.) Name: "Irregular triangle read by rows where row n lists (in decreasing order) the elements of the Schreier set encoded by A371176(n)." Comment: "Each term k of A371176 can be put into a one-to-one correspondence with a Schreier set by interpreting the 1-based position of the ones in the binary expansion of k (where position 1 corresponds to the least significant bit) as the elements of the corresponding Schreier set." Offset 1. A371176: "Numbers k such that A000120(k) <= A001511(k)." A007895 (offset 0): "Number of terms in the Zeckendorf representation of n." + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → (T n).length = (Nat.zeckendorf n).length + +-- dependencies (verbatim) +def IsTerm (k : ℕ) : Prop := 0 < k ∧ k.bitIndices.length ≤ padicValNat 2 (2 * k) +noncomputable def A371176 (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) +noncomputable def T (n : ℕ) : List ℕ := ((A371176 n).bitIndices.map (· + 1)).reverse +``` + +**What the Lean statement says** + +Let A371176 be the increasing list of positive integers k whose binary weight is at most the 2-adic valuation of 2k, and let A371176(n) be its n-th term (n ≥ 1). Row n of the triangle is the list of 1-based positions of the 1-bits of A371176(n), in decreasing order. Claim: for every n ≥ 1, the length of row n (the binary weight of A371176(n)) equals the number of terms in the Zeckendorf representation of n (the length of Mathlib's Nat.zeckendorf n). + +**What the kernel checks against the OEIS data** + +a_data checks all 91 listed terms (rows 1..42) of the flattened triangle in the kernel. code_data checks the first 42 terms of A371176 = 1, 2, 4, 6, 8, 10, 12, 16, …, 160. statement_check confirms the claimed equality for n = 1..42, which fixes the alignment of row n with A007895(n), not A007895(n−1). These checks are tied to the noncomputable definitions by proved equalities (code_eq_nth, row_eq_T, zeckAux_eq), and they pin the definitions of A371176 (including the exclusion of k = 0) and of the rows. + +**Points for the reviewer** + +- *Note.* The conjecture appears only as a cross-reference ("A007895 (conjectured row lengths)"). The Lean reading, row n has A007895(n) elements for n ≥ 1, is the only alignment consistent with the data (row 1 = {1} has length 1 = A007895(1), while A007895(0) = 0), and it covers all rows. +- *Note.* Nat.nth IsTerm is total and genuine here, because IsTerm holds for every power of two, so the set is infinite. The guard 0 < k correctly excludes k = 0, which A371176 omits. diff --git a/review/fidelity/packet-11.md b/review/fidelity/packet-11.md new file mode 100644 index 0000000..0f5fe61 --- /dev/null +++ b/review/fidelity/packet-11.md @@ -0,0 +1,369 @@ +# Fidelity review packet 11 of 11 + +Prepared on 29 Oct 2026 by an adversarial reviewing agent, not by a person. It is meant to make a human review of these statements quick: for each one it quotes the OEIS conjecture and the frozen Lean statement, restates the Lean in plain words, and lists anything a reviewer should look at. See [the index](README.md). + +Statements in this packet: A373359, A375522, A386538, A386655, A388724, A392943, A393794, A394981, A395454, A397315. + +## A373359: A373359: Schreier-set row lengths equal the Zeckendorf weight A007895 + +Verdict of the pre-review: **faithful**. Result: [oeis-a373359](../../results/oeis-a373359/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A373359.lean`](../../lean/Math0/Statements/OEIS/A373359.lean). + +**The conjecture as stated in OEIS** + +> %Y A373359 Cf. A007895 (conjectured row lengths), A373346 (row sums), A373347. (Paolo Xausa, Jun 04 2024; entry rev #23, Jun 22 2024, the same on the live GitHub copy). Definition: "Irregular triangle read by rows where row n lists (in increasing order) the elements of the Schreier set encoded by A371176(n)." (offset 1). A371176: "Numbers k such that A000120(k) <= A001511(k)." (offset 1). A007895: "Number of terms in the Zeckendorf representation of n" (offset 0). + +**The frozen Lean statement** + +```lean +def IsTerm (k : ℕ) : Prop := 0 < k ∧ k.bitIndices.length ≤ padicValNat 2 (2 * k) +noncomputable def A371176 (n : ℕ) : ℕ := Nat.nth IsTerm (n - 1) +noncomputable def T (n : ℕ) : List ℕ := (A371176 n).bitIndices.map (· + 1) +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → (T n).length = (Nat.zeckendorf n).length +``` + +**What the Lean statement says** + +List the positive integers k whose number of 1-bits is at most v_2(2k), i.e. at most one more than the index of the lowest 1-bit, in increasing order: 1, 2, 4, 6, 8, ... Let c_n be the n-th of these (n >= 1). The claim is that for every n >= 1, the number of 1-bits of c_n (the size of the set of 1-based bit positions of c_n) equals the number of terms in the Zeckendorf representation of n. + +**What the kernel checks against the OEIS data** + +a_data checks all 91 listed terms of the flattened triangle (rows 1-42), and a_eq ties the computable flattening to T. code_data checks the first 42 terms of A371176 (1, 2, 4, 6, 8, ..., 160). statement_check verifies the claimed equality for n = 1..42 against Mathlib's Nat.zeckendorf, via zeckAux_eq. The bridging lemmas (bitPos_eq_bitIndices, isTermB_iff, code_eq_nth, row_eq_T) are proved, not assumed. Together these pin down the encoding (LSB = position 1), the ordering, the offset, and the alignment row n <-> A007895(n). + +**Points for the reviewer** + +- *Note.* Alignment: row n is matched with A007895(n), not with the n-th listed term A007895(n-1). This is the only alignment the data allows: row lengths 1,1,1,2,1,2,2,1,2,2,2,3 equal A007895(1..12), and row 1 = {1} rules out A007895(0) = 0. The k = 0 / empty Schreier set is excluded, as in A371176 (positive integers). Including it would add the true case 0 = A007895(0) anyway. +- *Note.* The condition popcount(k) <= v_2(2k) is the Schreier condition |X| <= min X under the LSB-first encoding. This matches the entry's example table (6 = 110_2 -> {2,3}; 28 -> {3,4,5}) and the Mathematica program (DigitCount <= IntegerExponent + 1). + +## A375522: A375522: S2(n) - S1(n) = 1 fails at n = 42 (the difference is 5) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a375522](../../results/oeis-a375522/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A375522.lean`](../../lean/Math0/Statements/OEIS/A375522.lean). + +**The conjecture as stated in OEIS** + +> %C A375522 Let S(n) = Sum_{k = 1..n} 1 / (k*A375781(k)) = S1(n)/S2(n) when reduced to lowest terms, where S1(n) = A375521(n), S2(n) = the present sequence. +> %C A375522 The differences S2(n) - S1(n) are surprisingly small: for n = 1,2,...,34 the values S2(n) - S1(n) are: +> %C A375522 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +> %C A375522 suggesting the conjecture that they are always 1 except for n = 4 and 6 (compare the Theorem in A374983). +> (Rémy Sigrist and N. J. A. Sloane, Aug 30 2024; rev #25, Apr 22 2025, unchanged on live GitHub.) + +**The frozen Lean statement** + +```lean +def prime (k : ℕ) : ℕ := primeAt (k - 1) -- proved = Nat.nth Nat.Prime (k-1) +def s : ℕ → ℚ + | 0 => 0 + | n + 1 => s n + 1 / ((prime (n + 1) : ℚ) * + ((1 + ⌊1 / ((1 - s n) * (prime (n + 1) : ℚ))⌋ : ℤ) : ℚ)) +def S1 (n : ℕ) : ℤ := (s n).num +def a (n : ℕ) : ℕ := (s n).den +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → n ≠ 4 → n ≠ 6 → (a n : ℤ) - S1 n = 1 +``` + +**What the Lean statement says** + +Let p_k be the k-th prime. Set s(0) = 0 and s(k) = s(k-1) + 1/(p_k * b_k), where b_k = 1 + floor(1/((1 - s(k-1)) p_k)) is the least positive integer that keeps the sum below 1. Write s(n) in lowest terms as S1(n)/S2(n). The claim is that for every n >= 1 other than 4 and 6, S2(n) - S1(n) = 1. The result proves the negation. + +**What the kernel checks against the OEIS data** + +a_data checks all 11 listed terms of A375522 (n = 0..10). S1_data checks all 11 listed terms of A375521. b_data checks all 11 listed terms of A375781. diff_data checks S2(n) - S1(n) for n = 1..24 against the comment's list: 2 at n = 4 and 6, 1 elsewhere. primeAt_eq_nth proves the prime function is Mathlib's nth prime. With three independent sequences checked, the recursion, the primes and the offsets are pinned down. + +**Points for the reviewer** + +- *Note.* The entry's name and comment write 1/(k*A375781(k)), but the Lean uses 1/(prime(k)*A375781(k)). This is correct: A375781's own definition, every program in the entry, and the listed data all use prime(k), and the literal reading would give s(1) = 1. The data checks force the prime reading. +- *Note.* The Lean statement encodes only the 'always 1 except possibly at n = 4, 6' part, not that n = 4 and 6 really are exceptions (diff_data checks those separately). The statement is therefore weaker than the full conjecture. For a refutation (result : ¬ statement) this costs nothing: a counterexample at some n other than 4 and 6 (n = 42 per the catalogue) refutes the conjecture as worded. + +## A386538: A386538: moving the circle's center off the grid enlarges the max lattice polygon (counterexample at n = 7) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a386538](../../results/oeis-a386538/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A386538.lean`](../../lean/Math0/Statements/OEIS/A386538.lean). + +**The conjecture as stated in OEIS** + +> %C A386538 Conjecture: The maximum possible area of a polygon within the circle would be the same if only the vertices but not the center were fixed on grid points. (Felix Huber, Aug 05 2025; rev #23, Aug 19 2025, unchanged on live GitHub.) Definition: "a(n) is the maximum possible area of a polygon within a circle of radius n, where both the center and the vertices lie on points of a unit square grid." (offset 0) + +**The frozen Lean statement** + +```lean +def latticeDisk (c : ℝ × ℝ) (r : ℝ) : Set (ℝ × ℝ) := + {p | ∃ x y : ℤ, p = ((x : ℝ), (y : ℝ)) ∧ ((x : ℝ) - c.1) ^ 2 + ((y : ℝ) - c.2) ^ 2 ≤ r ^ 2} +noncomputable def maxArea (c : ℝ × ℝ) (r : ℝ) : ENNReal := + volume (convexHull ℝ (latticeDisk c r)) +def statement : Prop := + ∀ n : ℕ, (⨆ c : ℝ × ℝ, maxArea c n) = maxArea 0 n +``` + +**What the Lean statement says** + +For every n >= 0, take the convex hull of the integer lattice points in the closed disk of radius n with center c. The claim is that the supremum of its Lebesgue area over all centers c in R^2 equals the area when the center is the origin. Equivalently, no center does better than a lattice-point center. The result proves the negation. + +**What the kernel checks against the OEIS data** + +a_data checks the listed a(0..12), a_data_more checks the listed a(14), a(15), a(16), a(19), a(20), a(21), a(24), a(25), and a_13 shows a(13) = 516 although 512 is listed. All of these are about a computable function `a` (monotone-chain hull plus shoelace formula at center 0). `a` is NOT proved equal to maxArea 0 n, so the kernel checks do not tie the statement's own definitions (latticeDisk, maxArea) to the data. Those definitions are a direct transcription, checked against the data only through the informal claim that `a` computes them. + +**Points for the reviewer** + +- *Minor.* Several listed terms from a(13) on are smaller than the true maximum area. The author's Maple/Mathematica program, 4n + 4*Sum floor(sqrt(n^2-x^2)) - 2*#distinct y, is not the convex-hull area for n >= 13; for example it gives 512 at n = 13, where the 20-gon on the circle has area 516. The Lean follows the entry's name (the maximum), not the program. This does not affect the result: the counterexample is at n = 7, where the listed a(7) = 138 equals the true maximum. I recomputed exactly that the center-0 hull has area 138 and that the hull for center (5/12, 5/24) has area 281/2. +- *Note.* 'Only the vertices but not the center fixed on grid points' is read as: the center is free and we take the supremum over it. The other readings are 'for every center the maximum is the same', 'for every off-grid center', or 'no off-grid center does better'. Each of them is implied by the sup reading or contradicted by the same witness, so the refutation settles every one of them. +- *Note.* Polygon area is taken as the area of the convex hull. Every polygon with vertices in a finite set S lies in conv(S), and conv(S) is itself a polygon with vertices in S inside the disk. Closed vs open disk does not affect the witness: I checked that no lattice point lies exactly on the circle of radius 7 around (5/12, 5/24). The closed disk is needed for the grid-center values (a(1) = 2). + +## A386655: A386655 modulo 6 is eventually periodic with pattern [1, 0, 3, 0, 3, 2] + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a386655](../../results/oeis-a386655/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A386655.lean`](../../lean/Math0/Statements/OEIS/A386655.lean). + +**The conjecture as stated in OEIS** + +> %C A386655 Conjecture: for n >= 6, a(n) (mod 6) equals [1, 0, 3, 0, 3, 2] repeating. (Paul D. Hanna, Aug 23 2025; rev #14, Aug 24 2025, unchanged on live GitHub.) Definition: "E.g.f.: Sum_{n>=0} (2^n*x + LambertW(x))^n / n!." (offset 0); the entry also lists the formula a(n) = Sum_{k=0..n} binomial(n,k) * 2^(k*(k+1)) * (2^k - (n-k))^(n-k-1). + +**The frozen Lean statement** + +```lean +def term (n k : ℕ) : ℤ := + if k = n then 2 ^ (n * n) + else (binom n k : ℤ) * 2 ^ (k * (k + 1)) * ((2 : ℤ) ^ k - ((n - k : ℕ) : ℤ)) ^ (n - k - 1) +def a (n : ℕ) : ℤ := ∑ k ∈ Finset.range (n + 1), term n k +def statement : Prop := + ∀ n : ℕ, 6 ≤ n → a n % 6 = ([1, 0, 3, 0, 3, 2] : List ℤ).getD ((n - 6) % 6) 0 +``` + +**What the Lean statement says** + +Let a(n) = Sum_{k=0..n} C(n,k) 2^{k(k+1)} (2^k - (n-k))^{n-k-1}, where the k = n term is read as 2^{n^2} and 0^0 = 1 (binom is proved equal to Nat.choose). The claim is that for every n >= 6, a(n) mod 6 (least nonnegative residue) is 1, 0, 3, 0, 3, 2 according as n ≡ 0, 1, 2, 3, 4, 5 (mod 6). + +**What the kernel checks against the OEIS data** + +a_data checks all 13 listed terms (n = 0..12). a_eq_egf checks in the kernel that the explicit formula equals a literal truncated-e.g.f. evaluation of Sum_m (2^m x + W(x))^m/m! for n = 0..16. Here W comes from fixed-point iteration, and lambertW_spec checks W e^W = x up to x^16 and the coefficients 0, 1, -2, 9, -64, ... statement_data checks the residue pattern for n = 6..12. The checks pin the formula, the k = n convention, the LambertW branch/sign and the alignment of the pattern (a(6) ≡ 1). + +**Points for the reviewer** + +- *Note.* The definition is the explicit sum from the entry's FORMULA section, not the e.g.f. in the name. The two agree for all n by a classical identity: expand by the binomial theorem to Sum_j 2^{j^2} e^{2^j W} x^j/j!, then use e^{cW} = Sum_k c(c-k)^{k-1} x^k/k!. The k = n convention 2^{n^2} matches the k = 0 term of that expansion. The equivalence is not proved in Lean and is kernel-checked only up to n = 16; it is mathematically standard and not a conjectural formula. +- *Note.* The threshold n >= 6 is the author's. The pattern really does fail earlier: the residues for n = 0..5 are 1, 3, 5, 0, 3, 2. The Lean matches the stated range. + +## A388724: Column sums of strictly superdiagonal reversed partitions by maximum are A000245 + +Verdict of the pre-review: **faithful**. Result: [oeis-a388724](../../results/oeis-a388724/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A388724.lean`](../../lean/Math0/Statements/OEIS/A388724.lean). + +**The conjecture as stated in OEIS** + +> %F A388724 Conjecture: Column sums are A000245. (Gus Wiseman, Sep 24 2025; rev #12, Oct 06 2025, unchanged on live GitHub.) Definition: "Triangle read by rows where T(n,k) is the number of strictly superdiagonal reversed integer partitions of n with maximum k." with "A sequence (y_1, ..., y_k) is strictly superdiagonal iff y_i > i for all i = 1..k." (offset 0, tabl). A000245: a(n) = 3*(2*n)!/((n+2)!*(n-1)!), data 0, 1, 3, 9, 28, 90, ... + +**The frozen Lean statement** + +```lean +def IsRevPartition (n : ℕ) (y : List ℕ) : Prop := + (∀ x ∈ y, 0 < x) ∧ y.Pairwise (· ≤ ·) ∧ y.sum = n +def StrictlySuperdiagonal (y : List ℕ) : Prop := ∀ i (h : i < y.length), i + 1 < y[i] +noncomputable def T (n k : ℕ) : ℕ := + {y : List ℕ | IsRevPartition n y ∧ StrictlySuperdiagonal y ∧ y.max? = some k}.ncard +def A000245 (n : ℕ) : ℕ := + if n = 0 then 0 else 3 * (2 * n).factorial / ((n + 2).factorial * (n - 1).factorial) +def statement : Prop := ∀ k : ℕ, 1 ≤ k → ∑ᶠ n, T n k = A000245 (k - 1) +``` + +**What the Lean statement says** + +For k >= 1, count the weakly increasing lists (y_1 <= ... <= y_m) of positive integers with y_i > i for every i and largest entry exactly k, of any sum. The claim is that this count equals A000245(k-1) = 3(2k-2)!/((k+1)!(k-2)!), with value 0 when k = 1. The finsum over n is an honest finite sum: T(n,k) = 0 for n > k(k-1) is proved. + +**What the kernel checks against the OEIS data** + +a_data checks all 78 listed terms (rows 0..11) through the proved bridge T_eq_Tc, an enumeration of partitions proved complete and duplicate-free. A000245_data checks 28 listed terms of A000245. statement_check verifies column sums 0, 1, 3, 9, 28 for k = 1..5. I independently recomputed the column sums for k = 0..10 (0, 0, 1, 3, 9, 28, 90, 297, 1001, 3432, 11934), which agree with A000245(k-1) for k >= 1. + +**Points for the reviewer** + +- *Note.* Alignment: the column sums for k = 0, 1, 2, ... are 0, 0, 1, 3, 9, 28, ..., so 'Column sums are A000245' can only mean column k sums to A000245(k-1). Column 0, which is identically 0, is left out of the claim. This is the only alignment consistent with the values, and nothing substantive is lost. +- *Note.* The empty partition of 0 is counted in no column (max? = none), matching T(0,0) = 0 and Mathematica's Max[] = -Infinity. Columns sum over all n, and T(n,k) = 0 for n < k, so this agrees with summing over the triangle's column n >= k. + +## A392943: No primitive Heronian triangle has integer circumradius + +Verdict of the pre-review: **faithful**. Result: [oeis-a392943](../../results/oeis-a392943/README.md) (known-result-first-formalization). Frozen statement: [`lean/Math0/Statements/OEIS/A392943.lean`](../../lean/Math0/Statements/OEIS/A392943.lean). + +**The conjecture as stated in OEIS** + +> %C A392943 Conjecture: There is no primitive Heronian triangle with integer circumradius. (entry by _Felix Huber_, Feb 04 2026; revision #5, Feb 08 2026, unchanged upstream) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ x y z K R : ℕ, IsTriangle x y z → HasArea x y z K → Nat.gcd x (Nat.gcd y z) = 1 → + 4 * K * R ≠ x * y * z + +where +def IsTriangle (x y z : ℕ) : Prop := + 0 < x ∧ 0 < y ∧ 0 < z ∧ x < y + z ∧ y < x + z ∧ z < x + y +def heron16 (x y z : ℕ) : ℤ := + ((x : ℤ) + y + z) * (-x + y + z) * (x - y + z) * (x + y - z) +def HasArea (x y z K : ℕ) : Prop := + 16 * (K : ℤ) ^ 2 = heron16 x y z +``` + +**What the Lean statement says** + +Take positive integers x, y, z satisfying the strict triangle inequalities, with gcd(x, y, z) = 1, and a natural number K with 16K^2 = (x+y+z)(-x+y+z)(x-y+z)(x+y-z), i.e. K is the (integer) area. Then no natural number R satisfies 4KR = xyz, i.e. the circumradius xyz/(4K) is not an integer. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks a(1..30) (of 88 listed terms), via count/A392942, which go through IsGood = IsTriangle ∧ ∃ K R, HasArea ∧ 4KR = xyz (goodB_iff is proved). So the same IsTriangle/HasArea/heron16 that the statement uses are exercised on real data (e.g. (30,30,48) with area 432 and R = 25 is counted). The statement itself does not use a, count or A392942. Its definitions are a direct transcription of Heron's formula and R = xyz/(4K), so the data check is extra assurance, not the main evidence. + +**Points for the reviewer** + +- *Note.* Degenerate cases are harmless. Under IsTriangle, heron16 > 0, so any K with HasArea is positive and unique, and R = 0 gives 0 ≠ xyz automatically. All arithmetic is in ℤ, so there is no truncated subtraction. +- *Note.* 'Primitive Heronian' is encoded as integer sides, integer area and gcd(x,y,z) = 1, which is the standard meaning. Integer circumradius is ∃ R ∈ ℕ, 4KR = xyz, which is exact because K > 0. Scaled triangles such as (6,8,10) (gcd 2, R = 5) are correctly excluded by the gcd hypothesis. +- *Note.* The catalog records this as a known result (van Luijk 2008: a Heron triangle with integer circumradius has all sides even). That is consistent with the statement as encoded. + +## A393794: The 1089-trick map has two 9-digit fixed points (A393794 uniqueness conjecture is false) + +Verdict of the pre-review: **faithful**. Result: [oeis-a393794](../../results/oeis-a393794/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A393794.lean`](../../lean/Math0/Statements/OEIS/A393794.lean). + +**The conjecture as stated in OEIS** + +> %C A393794 a(n) is the unique fixed point of the 1089-trick map T among all (n+4)-digit numbers (verified exhaustively for n = 1..4; conjectured for all n >= 1). Name: "Fixed points of the 1089-trick map T(n) = |n - reverse(n)| + reverse(|n - reverse(n)|)." %F a(n) = 110*(10^(n+1) - 1). (_Remco Havenaar_, Feb 27 2026; #19, Mar 10 2026, unchanged upstream) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 1 ≤ n → + (Nat.digits 10 (a n)).length = n + 4 ∧ T (a n) = a n ∧ + ∀ x : ℕ, (Nat.digits 10 x).length = n + 4 → T x = x → x = a n + +where +def rev (m : ℕ) : ℕ := Nat.ofDigits 10 (Nat.digits 10 m).reverse +def T (x : ℕ) : ℕ := Nat.dist x (rev x) + rev (Nat.dist x (rev x)) +def a (n : ℕ) : ℕ := 110 * (10 ^ (n + 1) - 1) +``` + +**What the Lean statement says** + +Let rev(m) be the decimal reversal of m (leading zeros of the result dropped), and T(x) = |x - rev x| + rev(|x - rev x|). For every n ≥ 1, the number 110·(10^(n+1) - 1) has exactly n+4 decimal digits and is fixed by T, and every (n+4)-digit x with T(x) = x equals it. + +**What the kernel checks against the OEIS data** + +a_data checks all 18 listed terms. T_data checks that T fixes each of them. digits_data checks that a(i+1) has i+5 digits. least_fixed_point checks that 10890 is the least positive fixed point of T. Together these pin down T's reversal convention: an unpadded reversal of D is needed. With D padded to 5 digits, T(10890) = 1089 + 98010 = 99099 ≠ 10890, so the padded variant fails T_data. The entry's worked example ('1089 + 9801 = 10890') uses the unpadded reversal as well. Taking a from the closed formula, not 'the n-th fixed point', matches the data and both programs, and avoids a circular statement. + +**Points for the reviewer** + +- *Note.* The statement adds two conjuncts, 'a n has n+4 digits' and 'T(a n) = a n', to the uniqueness clause. Both are true; the entry proves T(110R) = 110R. Negating the conjunction is therefore equivalent to refuting uniqueness. The frozen result does exactly that: it applies the uniqueness clause at n = 5 to x = 108910890. +- *Note.* Independent check: 108910890 has 9 digits (n = 5). rev = 98019801, the difference is 10891089, its reversal is 98019801, and the sum is 108910890. So it is a fixed point other than a(5) = 109999890. It is 10·10891089, a non-primitive term of A001232. The entry's own comment points at such terms when it calls a(n)/10 the 'primitive' A001232 terms. The uniqueness claim nonetheless says 'unique among all (n+4)-digit numbers', so this counterexample answers the conjecture as worded and as meant. Nothing in the entry restricts the claim to primitive terms. + +## A394981: Bar tilings of the smallest-perimeter rectangle: a(n+1) = 4 a(n) for odd n >= 3 (A394981) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a394981](../../results/oeis-a394981/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A394981.lean`](../../lean/Math0/Statements/OEIS/A394981.lean). + +**The conjecture as stated in OEIS** + +> %F A394981 Conjecture: If n is odd, then a(n+1) = 4*a(n). (unattributed formula line; entry by _Gary Yane_, Apr 08 2026; a(1)-a(2) corrected by _Pontus von Brömssen_, May 13 2026; #42, May 16 2026, unchanged upstream). Name: number of tilings up to symmetry of the rectangle having smallest possible perimeter with area n(n+1)/2 using all n tiles 1 X 1, ..., 1 X n. Comment: '...the short side of the rectangle has length floor((n+1)/2)' (n=8: 4 X 9). + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → Odd n → a (n + 1) = 4 * a n + +where (abridged) +def rows (n : ℕ) : ℕ := (n + 1) / 2 +def cols (n : ℕ) : ℕ := n * (n + 1) / 2 / rows n +def a (n : ℕ) : ℕ := + let r := rows n; let c := cols n; let w := c + 1 + search w (r * w) n (stabCount r c w n) n (rectMask r c w) 0 / + (1 + (otherSymmetries r c).length) +-- search: places tiles n, n-1, ..., 1 (each horizontally, or vertically if length ≥ 2) at every placement +-- inside the free cells (padded row bitmask), requires no free cell at the end, and sums stabCount of the +-- resulting labelling; stabCount = 1 + #{non-identity symmetries g of the r×c rectangle with label∘g = label}; +-- otherSymmetries = the 2 axis reflections + half-turn (+ the 4 extra square symmetries when r = c). +``` + +**What the Lean statement says** + +Let a(n) be the number of orbits, under the symmetry group of the rectangle, of tilings of the floor((n+1)/2) × (n(n+1)/2)/floor((n+1)/2) rectangle (that is, ((n+1)/2) × n for odd n and (n/2) × (n+1) for even n) by the n bars 1×1, 1×2, ..., 1×n, each used exactly once. The orbits are counted with Burnside's lemma. The claim is that for every odd n ≥ 3, a(n+1) = 4·a(n). + +**What the kernel checks against the OEIS data** + +a_data kernel-checks a(1..9) = 1,1,1,4,10,40,112,448,1360, which match the listed terms. rect_data and area_data check the rectangle shapes and areas for n ≤ 20; for example the n = 8 rectangle is 4×9, as in the comment. The data pin down the 'up to symmetry' convention: for n = 4 the raw count would be 16, not 4. They also pin the 1×1 bar being placed only once and the bars being distinguishable. The data cover the conjectured pairs n = 3, 5, 7. a(10) and a(11) agree with #eval only, not the kernel. + +**Points for the reviewer** + +- *Minor.* The literal conjecture ('if n is odd') includes n = 1, but the entry's corrected data give a(2) = 1 ≠ 4 = 4·a(1). The statement restricts to odd n ≥ 3, and literal_fails_at_one kernel-checks the failure at n = 1. This is a deliberate weakening of the literal text, needed because the literal text is false at its first instance. It is the evident intent: the pattern holds for every listed pair n = 3, ..., 19. A reviewer should accept that n = 1 is a degenerate exception (1-row rectangles, after the May 2026 data correction) and not part of what the author meant. +- *Note.* The rectangle is fixed by the comment's formula (short side floor((n+1)/2)), not by minimising the perimeter over all factorisations. The two agree with the intended reading: the 1×n bar needs a side ≥ n, and the least such divisor L of n(n+1)/2 is n (odd n) or n+1 (even n). This is also what excludes the 6×6 square for n = 8, as the comment says. +- *Note.* The symmetry group is the full symmetry group of the rectangle (order 4, or order 8 for the 1×1 square), as 'up to symmetry' suggests, and the data confirm it. Burnside's integer division is exact. + +## A395454: Alexandersson's recurrence for the row polynomials of A395454 holds (rows counted from 1) + +Verdict of the pre-review: **faithful-with-notes**. Result: [oeis-a395454](../../results/oeis-a395454/README.md) (new-result). Frozen statement: [`lean/Math0/Statements/OEIS/A395454.lean`](../../lean/Math0/Statements/OEIS/A395454.lean). + +**The conjecture as stated in OEIS** + +> %F A395454 Conjecture: Let P(n) be the generating polynomial (in t) of row n. Then P(n) = (n - 2*t + n*t - 2)*P(n-1) + (t - t^2)*P'(n-1) + t*(2*n-4)*P(n-2). - _Per W. Alexandersson_, Jun 27 2026. (Entry by _Peter Luschny_, Apr 23 2026, offset 0, rows displayed as [0] 1; [1] 0, 0; [2] 0, 2, 0; ... ; upstream #30 differs from the mirror only by dropping the 'changed' keyword.) + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n : ℕ, 3 ≤ n → + P1 n = ((n : ℤ[X]) - 2 * X + (n : ℤ[X]) * X - 2) * P1 (n - 1) + + (X - X ^ 2) * derivative (P1 (n - 1)) + + X * (2 * (n : ℤ[X]) - 4) * P1 (n - 2) + +where +def E2 : ℕ → ℕ → ℤ -- second-order Eulerian numbers A201637 + | 0, 0 => 1 | 0, _ + 1 => 0 | n + 1, 0 => E2 n 0 + | n + 1, k + 1 => (2 * ((n : ℤ) + 1) - 1 - ((k : ℤ) + 1)) * E2 n k + ((k : ℤ) + 1 + 1) * E2 n (k + 1) +def T (n k : ℕ) : ℤ := ∑ j ∈ Finset.range (n + 1), (-1) ^ (n - j) * (n.choose j : ℤ) * E2 j (n - k) +noncomputable def P (n : ℕ) : ℤ[X] := ∑ k ∈ Finset.range (n + 1), C (T n k) * X ^ k +noncomputable def P1 (n : ℕ) : ℤ[X] := P (n - 1) +(statement_literal, with P in place of P1 and n ≥ 2, is recorded and refuted: not_statement_literal.) +``` + +**What the Lean statement says** + +Let T(n,k) = Σ_{j=0..n} (-1)^{n-j} C(n,j) E2(j, n-k), where E2 is the second-order Eulerian triangle, and let P_m(t) = Σ_{k=0..m} T(m,k) t^k (so P_0 = 1, P_1 = 0, P_2 = 2t, P_3 = 6t + 2t^2, ...). Then for every n ≥ 3, P_{n-1} = (n - 2 - 2t + nt)·P_{n-2} + (t - t^2)·P'_{n-2} + t(2n-4)·P_{n-3} in Z[t]. In the entry's own numbering (m = n-1 ≥ 2) this reads P_m = (m-1)(1+t)P_{m-1} + (t - t^2)P'_{m-1} + 2(m-1)t·P_{m-2}. In other words, the recurrence holds with the rows counted from 1. + +**What the kernel checks against the OEIS data** + +a_data kernel-checks all 55 listed terms (rows 0..9), including the zero entries, and E2_data checks rows 0..8 of A201637. This fully pins the triangle T, including the reading of Maple's binomial(-j-1, -n-1) = (-1)^(n-j) C(n,j). P, P' and the coefficients follow the formula's text. The recurrence itself is not kernel-checked for small n. In an independent Python check, the shifted reading holds for n = 3..29 and the literal reading fails at every n = 2..19. By hand: n = 4 gives (2+2t)(2t) + (t - t^2)·2 = 6t + 2t^2, which is row 3. + +**Points for the reviewer** + +- *Minor.* Index shift: the statement does not take 'row n' in the entry's offset-0 numbering. Read that way the recurrence is false at n = 2, since the RHS is 0 (P_1 = 0) while P_2 = 2t, and it fails at every n tested. The frozen statement uses P(n) := row n-1, i.e. rows counted from 1. Of the readings I checked, this is the only nearby one that makes the formula true; reversing the row polynomials or dividing by t both fail at once. It almost certainly reflects the author's 1-based row indexing. Still, it is an interpretive reindexing, not the literal text, and a human reviewer should approve it. The proof settles the shifted claim, which is the only meaningful version. +- *Note.* The range n ≥ 3 loses nothing. In the shifted reading, n = 2 holds trivially (both sides are 0, and the P1(0) term has coefficient 2n-4 = 0). All coefficients (n-2, 2n-4) are integers in Z[X], so there is no truncated subtraction. P1(n-2) for n ≥ 3 never reaches a junk index. + +## A397315: A397315: a 14-point blackout of the 5 x 8 grid refutes T(n,m) = n + m + +Verdict of the pre-review: **faithful**. Result: [oeis-a397315](../../results/oeis-a397315/README.md) (known-result-already-formalized). Frozen statement: [`lean/Math0/Statements/OEIS/A397315.lean`](../../lean/Math0/Statements/OEIS/A397315.lean). + +**The conjecture as stated in OEIS** + +> %C A397315 Conjecture: T(n,m) = n+m whenever min(n,m) >= 4, except T(4,4) = 7 and T(4,5) = 8 (verified on seven cells through 6 X 6). (_Arjun Pemmasani_, Sep 02 2026; #38, Sep 12 2026, unchanged upstream.) Name: T(n,k) = maximum number of points that can be blacked out of an n X k grid of points so that every rectangle with all four vertices on grid points (tilted rectangles included) is uniquely identifiable from its set of visible vertices; n, k >= 2. Comment: injectivity of R -> C(R) \ S. + +**The frozen Lean statement** + +```lean +def statement : Prop := + ∀ n m : ℕ, 4 ≤ min n m → + T n m = if n = 4 ∧ m = 4 then 7 + else if (n = 4 ∧ m = 5) ∨ (n = 5 ∧ m = 4) then 8 + else n + m + +where (abridged) +def pt (n i : ℕ) : ℤ × ℤ := (((i / n : ℕ) : ℤ), ((i % n : ℕ) : ℤ)) -- grid {0..k-1}×{0..n-1} +def rectMask? (n k a b c : ℕ) : Option ℕ := -- some {a,b,c,d} iff a,b,c distinct, (A-B)·(C-B) = 0, D = A+C-B in grid +def rects (n k : ℕ) : List ℕ := (all such vertex-set bitmasks over a,b,c < n*k).eraseDups +def visible (R B : ℕ) : ℕ := Nat.xor R (Nat.land R B) -- R \ B +def isValidBlackout (n k B : ℕ) : Bool := pairwiseDistinct ((rects n k).map (visible · B)) +def T (n k : ℕ) : ℕ := + ((List.range (2 ^ (n * k))).filter (isValidBlackout n k)).foldr (fun B m => max (card (n * k) B) m) 0 +``` + +**What the Lean statement says** + +For the grid {0..k-1} × {0..n-1}, call a rectangle any 4-point vertex set {a, b, c, a+c-b} of grid points with a, b, c distinct and a right angle at b. This includes tilted rectangles and squares. T(n,k) is the largest size of a set B of grid points such that distinct rectangles R ≠ R' always have R \ B ≠ R' \ B. The claim is that for all n, m ≥ 4, T(n,m) = n + m, except T(4,4) = 7 and T(4,5) = T(5,4) = 8. + +**What the kernel checks against the OEIS data** + +T_2_2 ... T_5_2 kernel-check the first 10 terms (4,4,4,5,5,5,6,6,6,6; grids of at most 12 points), and cell_data checks the antidiagonal order. These cells all have min(n,k) ≤ 3, so none lies in the conjecture's range. They also do not distinguish 'tilted rectangles included' from 'axis-parallel only': my Python check gives the same values 5, 6, 6, 6 for 3×3, 3×4, 4×3 and 2×5 either way. The tilted-rectangle condition is instead certified by inspection: the Lean rectMask? is a line-by-line transcription of the entry's Python and PARI programs (all ordered triples with a right angle at b and the fourth vertex in the grid). A Python transcription reportedly reproduces 15 terms. + +**Points for the reviewer** + +- *Note.* The exception 'T(4,5) = 8' is read symmetrically, as also covering T(5,4). This is forced: T is symmetric under transposition, and the entry's own data list T(5,4) = 8. The literal one-cell reading would contradict the data and would be trivially false at (5,4). The refutation sits at (5,8), away from both exceptional cells, so this reading does not affect the outcome. +- *Note.* The kernel data check reaches no cell with min(n,m) ≥ 4 and does not separate tilted from axis-parallel rectangles. Fidelity of T rests on the definition matching the entry's programs, which it does on inspection. The catalog notes that the author's own repository records T(5,8) = 14, which agrees with the frozen result (T(5,8) ≥ 14 > 13). +- *Note.* The statement asserts the conjecture for all n, m ≥ 4, which is the author's range, with no finite cutoff. The parenthetical 'verified on seven cells through 6 X 6' is evidence, not a restriction, and it is correctly left out. diff --git a/scripts/check_freeze.py b/scripts/check_freeze.py new file mode 100755 index 0000000..5917919 --- /dev/null +++ b/scripts/check_freeze.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 +"""Checks on the statements that math0 formalizes itself (lean/Math0/Statements/). + +1. Every file listed in FROZEN.sha256 still has its frozen hash. +2. With --base REF: FROZEN.sha256 is append-only. Every line it had at REF is still present, + unchanged, so a frozen statement cannot be edited together with its hash. +3. Every catalog result whose statement math0 formalized has its statement listed in FROZEN.sha256. +4. With --base REF --order: for each such result that is new since REF, the commit that added the + statement's FROZEN.sha256 line is a strict ancestor of the commit that added the proof file. + That is, the statement was committed, and could be reviewed, before the proof existed in the + repository. Results listed in FROZEN_WITH_PROOF.txt are exempt: they were frozen by the + pipeline before 2026-10-26 but committed together with their proofs, so git cannot show the order. +""" +import argparse, hashlib, json, os, subprocess, sys + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +STMT_DIR = 'lean/Math0/Statements' +FROZEN = f'{STMT_DIR}/FROZEN.sha256' +LEGACY = f'{STMT_DIR}/FROZEN_WITH_PROOF.txt' + + +def git(*args): + return subprocess.run(['git', '-C', ROOT, *args], capture_output=True, text=True) + + +def parse(text): + out = {} + for line in text.splitlines(): + if line.strip(): + h, path = line.split() + out[path] = h + return out + + +def first_commit(args): + r = git('log', '--reverse', '--format=%H', *args) + commits = r.stdout.split() + return commits[0] if commits else None + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument('--base', help='git ref to compare against (e.g. origin/main)') + ap.add_argument('--order', action='store_true', help='also check freeze-before-proof order') + a = ap.parse_args() + errors = [] + frozen_text = open(os.path.join(ROOT, FROZEN)).read() + frozen = parse(frozen_text) + + # 1. hashes + for path, h in frozen.items(): + p = os.path.join(ROOT, STMT_DIR, path) + if not os.path.exists(p): + errors.append(f'{path}: listed in FROZEN.sha256 but missing') + elif hashlib.sha256(open(p, 'rb').read()).hexdigest() != h: + errors.append(f'{path}: changed since it was frozen') + + # 2. append-only + base_frozen = {} + if a.base: + if git('rev-parse', '--verify', '--quiet', a.base + '^{commit}').returncode != 0: + print(f'note: base {a.base} not found; skipping comparisons against it') + a.base = None + else: + r = git('show', f'{a.base}:{FROZEN}') + base_frozen = parse(r.stdout) if r.returncode == 0 else {} + for path, h in base_frozen.items(): + if frozen.get(path) != h: + errors.append(f'{path}: its FROZEN.sha256 line changed or was removed since {a.base}') + + # 3. every math0-formalized statement is frozen + cat = json.load(open(os.path.join(ROOT, 'catalog.json')))['results'] + legacy = set(open(os.path.join(ROOT, LEGACY)).read().split()) + ours = [e for e in cat if e.get('statement_origin') == 'math0'] + for e in ours: + rel = os.path.relpath(e['upstream']['file'], STMT_DIR) + if rel not in frozen: + errors.append(f"{e['id']}: statement {rel} is not listed in FROZEN.sha256") + + # 4. freeze before proof + if a.order and a.base: + checked = 0 + for e in ours: + rel = os.path.relpath(e['upstream']['file'], STMT_DIR) + if rel in base_frozen or rel in legacy or rel not in frozen: + continue + line = f'{frozen[rel]} {rel}' + fc = first_commit(['-S', line, '--', FROZEN]) + pc = first_commit(['--diff-filter=A', '--', e['lean_file']]) + if not fc or not pc: + errors.append(f"{e['id']}: cannot find the commits that froze the statement and added the proof") + elif fc == pc or git('merge-base', '--is-ancestor', fc, pc).returncode != 0: + errors.append(f"{e['id']}: statement frozen in {fc[:9]}, which is not a strict ancestor " + f"of the proof commit {pc[:9]}") + else: + checked += 1 + print(f'freeze-before-proof order verified for {checked} new result(s)') + + for err in errors: + print('error:', err) + if errors: + sys.exit(1) + print(f'OK: {len(frozen)} frozen statements unchanged; {len(ours)} results use them') + + +if __name__ == '__main__': + main() diff --git a/scripts/gen_contents.py b/scripts/gen_contents.py new file mode 100755 index 0000000..df28fd8 --- /dev/null +++ b/scripts/gen_contents.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python3 +"""Generate CONTENTS.md and results//README.md from catalog.json. + +catalog.json is the single source of truth for what math0 claims. Every entry points at a Lean +file whose final command (#math0_proves / #math0_refutes / #math0_answers) is re-checked by CI. +""" +import json +import os +import subprocess +import sys + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +REPO_URL = "https://github.com/Foundation-0/math0" +FC_URL = "https://github.com/google-deepmind/formal-conjectures" + +def _tracked_papers(): + """Manuscripts committed to the repository. An untracked paper.pdf is a draft that has not + passed proofreading yet, so it is not linked.""" + try: + out = subprocess.run(["git", "ls-files", "--", "results/*/paper.pdf"], cwd=ROOT, + capture_output=True, text=True, check=True).stdout.split() + except (OSError, subprocess.CalledProcessError): + return None + return {path.split("/")[1] for path in out} + + +TRACKED_PAPERS = _tracked_papers() + + +def has_paper(slug): + if not os.path.exists(os.path.join(ROOT, "results", slug, "paper.pdf")): + return False + return TRACKED_PAPERS is None or slug in TRACKED_PAPERS + + +CLASS_LABEL = { + "new-result": "New result (conjecture settled; no earlier resolution found)", + "known-result-first-formalization": "First formal proof of a known result", + "known-result-already-formalized": "Independent formal proof (an implying Lean proof already exists elsewhere)", + "misformalization": "Misformalization found (upstream statement does not match the problem)", +} +VERB = { + "proves": "proves", + "refutes": "refutes (proves the negation of)", + "answers": "answers", + "refutes_every_answer": "refutes, for every possible value of its unknown,", + "settles-proves": "proves", + "settles-refutes": "refutes (proves the negation of)", +} + + +MODE_NOTE = { + "proves": "", + "refutes": " (negated)", + "answers": " with its unknown replaced by an explicit value", + "refutes_every_answer": " negated and universally quantified over the unknown", + "settles-proves": "", + "settles-refutes": " (negated)", +} + + +def upstream_link(e): + u = e["upstream"] + if e.get("statement_origin") == "math0": + return f"[`{u['decl']}`]({u['file']}) (math0, from {e['source']})" + return f"[`{u['decl']}`]({FC_URL}/blob/{u['commit']}/{u['file']})" + + +LEGACY_FREEZE = set(open(os.path.join(ROOT, "lean", "Math0", "Statements", "FROZEN_WITH_PROOF.txt")).read().split()) + + +def freeze_text(e): + rel = os.path.relpath(e["upstream"]["file"], "lean/Math0/Statements") + if rel in LEGACY_FREEZE: + return ("The statement and its frozen hash were committed together with the proof, so the order " + "(freeze, then proof) is recorded only in the pipeline's logs, not in the git history.") + return ("The statement and its frozen hash were committed before the proof, and CI checks that this " + "order holds and that the frozen hash never changes.") + + +def verification_text(e): + u = e["upstream"] + if e.get("statement_origin") == "math0": + return ( + f"The statement was formalized by math0 (not by a third party) from the conjecture in " + f"[{e['source']}]({e['source_url']}) as [`{u['decl']}`](../../{u['file']}). Its definitions are checked " + "by the kernel against the OEIS data. A separate agent reviewed it for fidelity to the OEIS text and " + f"froze it (by hash) before any proof attempt. {freeze_text(e)} Its fidelity to the OEIS text is a " + "judgement, not a machine check, so the conjecture as stated in OEIS is quoted in the notes below " + "for comparison. The Lean file " + f"[`{e['lean_file']}`](../../{e['lean_file']}) {VERB[e['mode']]} it; the final command `#math0_settles` checks that " + "our theorem's type is exactly the statement or its negation and that both use no axioms beyond " + "`propext`, `Classical.choice` and `Quot.sound`." + ) + return ( + f"The Lean file [`{e['lean_file']}`](../../{e['lean_file']}) {VERB[e['mode']]} the upstream statement " + f"{upstream_link(e)} (formal-conjectures at commit `{u['commit'][:7]}`, upstream category " + f"`{u['category']}`). Its final command `#math0_{e['mode']}` checks that our theorem's type is " + f"syntactically identical to the upstream statement{MODE_NOTE[e['mode']]} " + "and that the proof uses no axioms beyond `propext`, `Classical.choice` and `Quot.sound`." + ) + + +ROUTINE_MEANS = ("a short or standard argument, a consequence of material already in the OEIS entry, its " + "cross-references or the literature, or a finite search") + + +def assessment_text(a): + out = a["justification"] + if a["follows_from"]: + out += f"\n\n*Follows from:* {a['follows_from']}" + if a["literal_only"] and a["intended_status"]: + out += f"\n\n*Literal reading:* {a['intended_status']}" + out += ("\n\n*How this was judged:* an independent assessor agent, asked to judge the difficulty of the " + f"mathematics and not to inflate it, rated it **{a['depth']}**. Routine means {ROUTINE_MEANS}; " + "substantial means a non-standard idea or a long argument that does not follow readily from such material. " + + ("A second assessor, asked to show it is routine, " + ("agreed it is substantial." if a["depth"] == "substantial" else "found it routine.") + if a["challenged"] else "") + + (f" *Revised:* {a['revision']}" if a.get("revision") else "") + + f" ({a['date']})") + return out + + +def result_readme(e): + u = e["upstream"] + lines = [ + f"# {e['title']}", + "", + f"**Classification:** {CLASS_LABEL[e['classification']]} ", + ] + ([f"**Difficulty (independent assessment):** {e['assessment']['depth']}" + + (", settles the conjecture only as literally stated" if e['assessment']['literal_only'] else "") + " "] + if e.get("assessment") else []) + [ + f"**Area:** {e['area']} ", + f"**Source problem:** {e['source']} ", + f"**Date:** {e['date']}", + "", + "## Result", + "", + e["summary"], + "", + ] + if e.get("assessment"): + lines += ["## Assessment", "", assessment_text(e["assessment"]), ""] + lines += [ + "## Verification", + "", + verification_text(e), + "", + ] + if e.get("notes"): + lines += ["## Notes", "", e["notes"], ""] + if has_paper(e["slug"]): + lines += ["## Manuscript", "", "[paper.pdf](paper.pdf) ([source](paper.tex))", ""] + lines += [ + "## Citation", + "", + "```bibtex", + f"@misc{{math0:{e['slug']},", + " author = {{math0}},", + f" title = {{{{{e['title']}}}}},", + f" howpublished = {{\\url{{{REPO_URL}/tree/main/results/{e['slug']}}}}},", + f" note = {{Produced by Claude (Anthropic); Lean-verified}},", + f" year = {{{e['date'][:4]}}}", + "}", + "```", + "", + ] + return "\n".join(lines) + + +SHORT = { + "new-result": "new results", + "known-result-first-formalization": "first formal proofs of known results", + "known-result-already-formalized": "independent formal proofs", + "misformalization": "misformalization reports", +} + + +def assessment_summary(group): + sub = sum(1 for e in group if e.get("assessment", {}).get("depth") == "substantial") + rou = sum(1 for e in group if e.get("assessment", {}).get("depth") == "routine") + pend = len(group) - sub - rou + return (f"An independent assessor judged the difficulty of each of these: {sub} substantial and {rou} routine " + f"({ROUTINE_MEANS})" + (f"; {pend} not yet assessed" if pend else "") + ". " + "Most of these conjectures had stayed open for lack of attention, not because they were hard; " + "each result page gives the assessor's reasons.") + + +def write_highlights(entries, counts): + """Refresh the generated block between the HIGHLIGHTS markers in RESULTS.md.""" + path = os.path.join(ROOT, "RESULTS.md") + text = open(path).read() + start, end = "", "" + if start not in text or end not in text: + return + lines = [ + start, + f"**{len(entries)} verified results.** " + + ", ".join(f"{v} {SHORT[k]}" for k, v in counts.items() if v) + + ". Full list: [CONTENTS.md](CONTENTS.md).", + "", + "New results: OEIS conjectures settled, each checked by the Lean kernel, with no earlier proof or " + "counterexample found by an independent novelty referee. " + + assessment_summary([e for e in entries if e["classification"] == "new-result"]), + "", + ] + new = [e for e in entries if e["classification"] == "new-result"] + new.sort(key=lambda e: e.get("assessment", {}).get("depth") != "substantial") + for e in new: + paper = f" ([paper](results/{e['slug']}/paper.pdf))" if has_paper(e["slug"]) else "" + depth = e.get("assessment", {}).get("depth") + tag = " (substantial)" if depth == "substantial" else "" + lines.append(f"* [{e['title']}](results/{e['slug']}/README.md){tag}{paper}") + lines.append(end) + pre, rest = text.split(start, 1) + post = rest.split(end, 1)[1] + open(path, "w").write(pre + "\n".join(lines) + post) + + +def main(): + cat = json.load(open(os.path.join(ROOT, "catalog.json"))) + entries = sorted(cat["results"], key=lambda e: (list(CLASS_LABEL).index(e["classification"]), e["area"], e["title"])) + for e in entries: + d = os.path.join(ROOT, "results", e["slug"]) + os.makedirs(d, exist_ok=True) + open(os.path.join(d, "README.md"), "w").write(result_readme(e)) + counts = {k: sum(e["classification"] == k for e in entries) for k in CLASS_LABEL} + out = [ + "# Contents", + "", + f"**{len(entries)} results, every one checked by the Lean kernel against a fixed statement:** " + f"{sum(e.get('statement_origin') != 'math0' for e in entries)} against statements published by a third party " + "(formal-conjectures), and " + f"{sum(e.get('statement_origin') == 'math0' for e in entries)} against statements that math0 formalized from " + "OEIS and froze before the proof.", + "", + "| Classification | Count |", + "|---|---|", + ] + [f"| {CLASS_LABEL[k]} | {v} |" for k, v in counts.items()] + [""] + for k in CLASS_LABEL: + group = [e for e in entries if e["classification"] == k] + if not group: + continue + assessed = k == "new-result" + out += [f"## {CLASS_LABEL[k]}", ""] + if assessed: + out += [assessment_summary(group), ""] + out += ["| # | Result | Area | Upstream statement | Lean |" + (" Difficulty |" if assessed else ""), + "|---|---|---|---|---|" + ("---|" if assessed else "")] + for i, e in enumerate(group, 1): + out.append( + f"| {i} | [{e['title']}](results/{e['slug']}/README.md) | {e['area']} | {upstream_link(e)} " + f"| [{os.path.basename(e['lean_file'])}]({e['lean_file']}) |" + + (f" {e['assessment']['depth'] if e.get('assessment') else 'not yet assessed'} |" if assessed else "") + ) + out.append("") + open(os.path.join(ROOT, "CONTENTS.md"), "w").write("\n".join(out)) + write_highlights(entries, counts) + print(f"wrote CONTENTS.md and {len(entries)} result pages") + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/gen_root.py b/scripts/gen_root.py new file mode 100755 index 0000000..89dd96f --- /dev/null +++ b/scripts/gen_root.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Regenerate lean/Math0.lean so that it imports every result listed in catalog.json.""" +import json +import os + +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +cat = json.load(open(os.path.join(ROOT, "catalog.json"))) +mods = sorted(e["lean_file"][len("lean/"):-len(".lean")].replace("/", ".") for e in cat["results"]) +header = """/- +Copyright 2026 The math0 Authors. Licensed under the Apache License, Version 2.0. +-/ +import Math0.Audit +""" +doc = """ +/-! +# math0 + +Root module: imports every verified result. Building it re-runs every audit (`#math0_proves`, +`#math0_refutes`, `#math0_answers`), so `lake build` fails on any `sorry`, non-standard axiom, or +mismatch with the upstream statement. +-/ +""" +# Every statement math0 has frozen, including those that no result settles yet, so that CI +# compiles each of them as soon as it is committed. +frozen = [l.split()[1] for l in open(os.path.join(ROOT, "lean", "Math0", "Statements", "FROZEN.sha256")) if l.strip()] +stmts = sorted("Math0.Statements." + p[:-len(".lean")].replace("/", ".") for p in frozen) +with open(os.path.join(ROOT, "lean", "Math0", "Statements.lean"), "w") as f: + f.write(header.replace("import Math0.Audit\n", "") + "".join(f"import {m}\n" for m in stmts) + """ +/-! +# Frozen statements + +Imports every statement listed in `Math0/Statements/FROZEN.sha256`: the conjectures that math0 +formalized itself, each fidelity-reviewed and frozen before any proof attempt. Some are not yet +settled by any result. +-/ +""") +with open(os.path.join(ROOT, "lean", "Math0.lean"), "w") as f: + f.write(header + "import Math0.Statements\n" + "".join(f"import {m}\n" for m in mods) + doc) +print(f"Math0.lean imports {len(mods)} results; Math0/Statements.lean imports {len(stmts)} frozen statements") diff --git a/scripts/test_audit.sh b/scripts/test_audit.sh new file mode 100755 index 0000000..c519e2c --- /dev/null +++ b/scripts/test_audit.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# Tests for the audit commands in lean/Math0/Audit.lean. +# Every file in tests/audit/fail must be rejected with the message named on its first line +# ("-- expect: "); every file in tests/audit/pass must compile. +# Requires a built Math0.Audit (lake build Math0.Audit). Usage: scripts/test_audit.sh +set -uo pipefail +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$ROOT/lean" +status=0 +for f in "$ROOT"/tests/audit/fail/*.lean; do + expect="$(head -1 "$f" | sed -n 's/^-- expect: //p')" + if [ -z "$expect" ]; then echo "FAIL $f: no '-- expect:' line"; status=1; continue; fi + if out="$(lake env lean "$f" 2>&1)"; then + echo "FAIL $(basename "$f"): accepted, but it should be rejected"; status=1 + elif ! grep -qF "$expect" <<<"$out"; then + echo "FAIL $(basename "$f"): rejected without '$expect':"; echo "$out" | head -5; status=1 + else + echo "ok $(basename "$f") is rejected ($expect)" + fi +done +for f in "$ROOT"/tests/audit/pass/*.lean; do + if out="$(lake env lean "$f" 2>&1)"; then + echo "ok $(basename "$f") is accepted" + else + echo "FAIL $(basename "$f"): rejected:"; echo "$out" | head -10; status=1 + fi +done +exit $status diff --git a/scripts/verify.sh b/scripts/verify.sh new file mode 100755 index 0000000..b5b8a57 --- /dev/null +++ b/scripts/verify.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Rebuild every math0 result and re-run every audit. +# Requires elan (https://github.com/leanprover/elan). +# Usage: scripts/verify.sh [--clean] [--expect N] +# --clean delete lean/.lake/build first, so every math0 module is elaborated and checked by the +# kernel in this run instead of being replayed from an earlier build +# --expect N fail unless exactly N distinct statement checks ran (one per catalog result) +# MATH0_BATCH (default 2) is how many math0 modules are built at once: the heaviest proof files need +# up to 8 GB of memory each. +set -euo pipefail +clean=0 +expect="" +while [ $# -gt 0 ]; do + case "$1" in + --clean) clean=1; shift ;; + --expect) expect="$2"; shift 2 ;; + *) echo "usage: $0 [--clean] [--expect N]" >&2; exit 2 ;; + esac +done +batch="${MATH0_BATCH:-2}" +cd "$(dirname "$0")/../lean" +lake exe cache get +if [ "$clean" = 1 ]; then rm -rf .lake/build; fi +log="$(mktemp)" +# The audit, then every frozen statement, then every result, a few modules at a time. +mapfile -t mods < <(echo Math0.Audit; sed -n 's/^import //p' Math0/Statements.lean; + sed -n 's/^import //p' Math0.lean | grep -v -x -e Math0.Audit -e Math0.Statements) +for ((i = 0; i < ${#mods[@]}; i += batch)); do + lake build "${mods[@]:i:batch}" 2>&1 | tee -a "$log" +done +lake build 2>&1 | tee -a "$log" # the root modules, which only import what is already built +# The upstream statement source must be the pristine pinned checkout. +for pkg in formal_conjectures mathlib; do + if [ -n "$(git -C ".lake/packages/$pkg" status --porcelain)" ]; then + echo "error: .lake/packages/$pkg has local modifications" >&2 + exit 1 + fi +done +# A module built in an earlier batch is replayed by later ones, so count distinct checks. +checks=$(grep -o "math0 statement check: .*" "$log" | sort -u | wc -l) +if [ -n "$expect" ] && [ "$checks" != "$expect" ]; then + echo "error: expected $expect statement checks, found $checks" >&2 + exit 1 +fi +echo "OK: build succeeded; ${checks} statement checks passed (only propext, Classical.choice, Quot.sound allowed)." diff --git a/templates/paper.tex b/templates/paper.tex new file mode 100644 index 0000000..74f7048 --- /dev/null +++ b/templates/paper.tex @@ -0,0 +1,101 @@ +% math0 manuscript template. Build with: latexmk -pdf paper.tex +\documentclass[11pt]{amsart} +\usepackage[margin=1.1in]{geometry} +\usepackage{amsmath,amssymb,amsthm,mathtools} +\usepackage{hyperref} +\usepackage{xcolor} +\usepackage{listings} +\usepackage{newunicodechar} + +\lstdefinelanguage{lean}{ + keywords={theorem,lemma,def,abbrev,example,fun,by,have,show,from,let,in,if,then,else,match,with, + namespace,end,open,import,section,variable,instance,structure,where,calc,obtain,intro,exact, + refine,rcases,rintro,simp,omega,decide,norm_num,linarith,nlinarith,positivity,induction,cases}, + sensitive=true, comment=[l]{--}, morecomment=[s]{/-}{-/}, string=[b]"} +\lstset{language=lean, basicstyle=\ttfamily\small, columns=fullflexible, breaklines=true, + keywordstyle=\color{blue!60!black}\bfseries, commentstyle=\color{gray}, frame=single, + extendedchars=true, inputencoding=utf8} +% Unicode commonly found in Lean sources. +\newunicodechar{ℕ}{\ensuremath{\mathbb{N}}} +\newunicodechar{ℤ}{\ensuremath{\mathbb{Z}}} +\newunicodechar{ℚ}{\ensuremath{\mathbb{Q}}} +\newunicodechar{ℝ}{\ensuremath{\mathbb{R}}} +\newunicodechar{ℂ}{\ensuremath{\mathbb{C}}} +\newunicodechar{∀}{\ensuremath{\forall}} +\newunicodechar{∃}{\ensuremath{\exists}} +\newunicodechar{→}{\ensuremath{\to}} +\newunicodechar{←}{\ensuremath{\leftarrow}} +\newunicodechar{↔}{\ensuremath{\leftrightarrow}} +\newunicodechar{↦}{\ensuremath{\mapsto}} +\newunicodechar{¬}{\ensuremath{\neg}} +\newunicodechar{∧}{\ensuremath{\wedge}} +\newunicodechar{∨}{\ensuremath{\vee}} +\newunicodechar{≤}{\ensuremath{\le}} +\newunicodechar{≥}{\ensuremath{\ge}} +\newunicodechar{≠}{\ensuremath{\ne}} +\newunicodechar{∈}{\ensuremath{\in}} +\newunicodechar{∉}{\ensuremath{\notin}} +\newunicodechar{⊆}{\ensuremath{\subseteq}} +\newunicodechar{∩}{\ensuremath{\cap}} +\newunicodechar{∪}{\ensuremath{\cup}} +\newunicodechar{∑}{\ensuremath{\sum}} +\newunicodechar{∏}{\ensuremath{\prod}} +\newunicodechar{⟨}{\ensuremath{\langle}} +\newunicodechar{⟩}{\ensuremath{\rangle}} +\newunicodechar{·}{\ensuremath{\cdot}} +\newunicodechar{∘}{\ensuremath{\circ}} +\newunicodechar{⁻}{\ensuremath{^{-}}} +\newunicodechar{¹}{\ensuremath{^{1}}} +\newunicodechar{²}{\ensuremath{^{2}}} +\newunicodechar{₀}{\ensuremath{_{0}}} +\newunicodechar{₁}{\ensuremath{_{1}}} +\newunicodechar{₂}{\ensuremath{_{2}}} +\newunicodechar{α}{\ensuremath{\alpha}} +\newunicodechar{β}{\ensuremath{\beta}} +\newunicodechar{ε}{\ensuremath{\varepsilon}} +\newunicodechar{δ}{\ensuremath{\delta}} +\newunicodechar{π}{\ensuremath{\pi}} +\newunicodechar{σ}{\ensuremath{\sigma}} +\newunicodechar{φ}{\ensuremath{\varphi}} +\newunicodechar{∞}{\ensuremath{\infty}} +\newunicodechar{⌊}{\ensuremath{\lfloor}} +\newunicodechar{⌋}{\ensuremath{\rfloor}} +\newunicodechar{⌈}{\ensuremath{\lceil}} +\newunicodechar{⌉}{\ensuremath{\rceil}} +\newunicodechar{∣}{\ensuremath{\mid}} +\newunicodechar{≡}{\ensuremath{\equiv}} +\newunicodechar{×}{\ensuremath{\times}} +\newunicodechar{⧸}{\ensuremath{/}} +\newunicodechar{‖}{\ensuremath{\|}} +\newunicodechar{√}{\ensuremath{\surd}} +\newunicodechar{∅}{\ensuremath{\emptyset}} +\newunicodechar{⦃}{\ensuremath{\{\!|}} +\newunicodechar{⦄}{\ensuremath{|\!\}}} +\newunicodechar{𝓝}{\ensuremath{\mathcal{N}}} +\newunicodechar{≫}{\ensuremath{\gg}} +\newunicodechar{≪}{\ensuremath{\ll}} + +\theoremstyle{plain} +\newtheorem{theorem}{Theorem} +\newtheorem{lemma}[theorem]{Lemma} +\newtheorem{proposition}[theorem]{Proposition} +\newtheorem{corollary}[theorem]{Corollary} +\theoremstyle{definition} +\newtheorem{definition}[theorem]{Definition} +\newtheorem{remark}[theorem]{Remark} + +\title{TITLE} +\author{math0} +\address{Produced by Claude (an AI model developed by Anthropic) in the math0 project} +\date{DATE} + +\begin{document} +\begin{abstract} +ABSTRACT +\end{abstract} +\maketitle + +\section{Statement} +\section{Proof} +\section{Machine verification} +\end{document} diff --git a/tests/audit/fail/custom_axiom.lean b/tests/audit/fail/custom_axiom.lean new file mode 100644 index 0000000..0ce0409 --- /dev/null +++ b/tests/audit/fail/custom_axiom.lean @@ -0,0 +1,5 @@ +-- expect: math0 audit failed +import Math0.Audit +axiom cheat : False +theorem t : 1 = 2 := cheat.elim +#math0_audit t diff --git a/tests/audit/fail/native_decide.lean b/tests/audit/fail/native_decide.lean new file mode 100644 index 0000000..da4e63c --- /dev/null +++ b/tests/audit/fail/native_decide.lean @@ -0,0 +1,4 @@ +-- expect: math0 audit failed +import Math0.Audit +theorem t : 2 + 2 = 4 := by native_decide +#math0_audit t diff --git a/tests/audit/fail/proves_defeq_not_syntactic.lean b/tests/audit/fail/proves_defeq_not_syntactic.lean new file mode 100644 index 0000000..a1dc182 --- /dev/null +++ b/tests/audit/fail/proves_defeq_not_syntactic.lean @@ -0,0 +1,7 @@ +-- expect: math0 statement check failed +import Math0.Audit +-- Definitionally equal but not syntactically equal types are rejected: no unfolding. +def double (n : Nat) : Nat := 2 * n +theorem upstream : ∀ n : Nat, double n = 2 * n := sorry +theorem ours : ∀ n : Nat, 2 * n = 2 * n := fun _ => rfl +#math0_proves ours upstream diff --git a/tests/audit/fail/proves_weaker_statement.lean b/tests/audit/fail/proves_weaker_statement.lean new file mode 100644 index 0000000..eba9c5a --- /dev/null +++ b/tests/audit/fail/proves_weaker_statement.lean @@ -0,0 +1,6 @@ +-- expect: math0 statement check failed +import Math0.Audit +-- Upstream statements are theorems proved by `sorry`; only their types matter. +theorem upstream : ∀ n : Nat, n < 2 * n + 1 := sorry +theorem ours : ∀ n : Nat, n ≤ 2 * n + 1 := fun n => by omega +#math0_proves ours upstream diff --git a/tests/audit/fail/proves_with_sorry.lean b/tests/audit/fail/proves_with_sorry.lean new file mode 100644 index 0000000..1df3eda --- /dev/null +++ b/tests/audit/fail/proves_with_sorry.lean @@ -0,0 +1,5 @@ +-- expect: math0 audit failed +import Math0.Audit +theorem upstream : ∀ n : Nat, n + 0 = n := sorry +theorem ours : ∀ n : Nat, n + 0 = n := sorry +#math0_proves ours upstream diff --git a/tests/audit/fail/refutes_wrong_polarity.lean b/tests/audit/fail/refutes_wrong_polarity.lean new file mode 100644 index 0000000..4b12b72 --- /dev/null +++ b/tests/audit/fail/refutes_wrong_polarity.lean @@ -0,0 +1,5 @@ +-- expect: math0 statement check failed +import Math0.Audit +theorem upstream : ∀ n : Nat, n + 0 = n := sorry +theorem ours : ∀ n : Nat, n + 0 = n := fun _ => rfl +#math0_refutes ours upstream diff --git a/tests/audit/fail/settles_other_prop.lean b/tests/audit/fail/settles_other_prop.lean new file mode 100644 index 0000000..e1dc906 --- /dev/null +++ b/tests/audit/fail/settles_other_prop.lean @@ -0,0 +1,6 @@ +-- expect: math0 statement check failed +import Math0.Audit +def statement : Prop := ∀ n : Nat, n + 0 = n +-- Proving the unfolded body is not accepted: the type must be exactly `statement` or `¬ statement`. +theorem result : ∀ n : Nat, n + 0 = n := fun _ => rfl +#math0_settles result statement diff --git a/tests/audit/fail/settles_sorry_result.lean b/tests/audit/fail/settles_sorry_result.lean new file mode 100644 index 0000000..d7114d7 --- /dev/null +++ b/tests/audit/fail/settles_sorry_result.lean @@ -0,0 +1,5 @@ +-- expect: math0 audit failed +import Math0.Audit +def statement : Prop := ∀ n : Nat, n + 0 = n +theorem result : statement := sorry +#math0_settles result statement diff --git a/tests/audit/fail/settles_sorry_statement.lean b/tests/audit/fail/settles_sorry_statement.lean new file mode 100644 index 0000000..e8832ff --- /dev/null +++ b/tests/audit/fail/settles_sorry_statement.lean @@ -0,0 +1,6 @@ +-- expect: math0 audit failed +import Math0.Audit +-- A statement that hides a `sorry` is rejected even if the result itself is sorry-free. +def statement : Prop := sorry +theorem result : statement := sorry +#math0_settles result statement diff --git a/tests/audit/fail/settles_theorem_not_def.lean b/tests/audit/fail/settles_theorem_not_def.lean new file mode 100644 index 0000000..508bddb --- /dev/null +++ b/tests/audit/fail/settles_theorem_not_def.lean @@ -0,0 +1,5 @@ +-- expect: math0 statement check failed +import Math0.Audit +theorem statement : True := trivial +theorem result : True := trivial +#math0_settles result statement diff --git a/tests/audit/fail/sorry_proof.lean b/tests/audit/fail/sorry_proof.lean new file mode 100644 index 0000000..f7ce7d8 --- /dev/null +++ b/tests/audit/fail/sorry_proof.lean @@ -0,0 +1,4 @@ +-- expect: math0 audit failed +import Math0.Audit +theorem t : 1 + 1 = 2 := sorry +#math0_audit t diff --git a/tests/audit/pass/all_commands.lean b/tests/audit/pass/all_commands.lean new file mode 100644 index 0000000..96f89d0 --- /dev/null +++ b/tests/audit/pass/all_commands.lean @@ -0,0 +1,22 @@ +import Math0.Audit +-- Each audit command accepts a correct, sorry-free result. +theorem upstream : ∀ n : Nat, n + 0 = n := sorry +theorem ours : ∀ n : Nat, n + 0 = n := fun _ => rfl +#math0_proves ours upstream +theorem upstreamFalse : ∀ n : Nat, n + 1 = n := sorry +theorem oursNeg : ¬ ∀ n : Nat, n + 1 = n := fun h => by simpa using h 0 +#math0_refutes oursNeg upstreamFalse +def statement : Prop := ∀ n : Nat, n + 0 = n +theorem result : statement := fun _ => rfl +#math0_settles result statement +def statement2 : Prop := ∀ n : Nat, n + 1 = n +theorem result2 : ¬ statement2 := fun h => by simpa using h 0 +#math0_settles result2 statement2 +def answer : Nat := sorry +theorem upstreamAns : answer = 4 := sorry +def ourAnswer : Nat := 4 +theorem oursAns : ourAnswer = 4 := rfl +#math0_answers oursAns upstreamAns with answer := ourAnswer +theorem upstreamBad : answer + 1 = answer := sorry +theorem oursEvery : ∀ a : Nat, ¬ (a + 1 = a) := fun a h => by omega +#math0_refutes_every_answer oursEvery upstreamBad with answer