Skip to content

Commit a0a9035

Browse files
feat: scaffold fd-formalization repo
Lean 4 + Mathlib project for formalizing the (u,v)-flower analytical dimension formula d_B = ln(u+v)/ln(u) from Rozenfeld et al. (NJP 2007). Proof spine: FlowerGraph -> FlowerCounts -> FlowerDiameter -> FlowerDimension. Zero axioms target. GraphBall.lean is an upstream Mathlib candidate using edist (not dist) for correct handling of disconnected graphs. Includes: lakefile.toml, CI workflow (SHA-pinned), pre-commit hooks, copyright checker, mathlib-playbook conventions, debt tracker. Builds clean with `lake build --wfail` against Mathlib v4.28.0. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 79b10fa commit a0a9035

17 files changed

Lines changed: 723 additions & 17 deletions
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Lean CI
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
8+
env:
9+
ELAN_HOME: /home/runner/.elan
10+
11+
jobs:
12+
build:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
steps:
17+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
18+
19+
- name: Install elan and toolchain
20+
run: |
21+
curl -sSf https://raw.githubusercontent.com/leanprover/elan/917c18d0ad52f649c2603dc8b973f5b9fa5f8f43/elan-init.sh | sh -s -- -y --default-toolchain none
22+
echo "${ELAN_HOME}/bin" >> "${GITHUB_PATH}"
23+
export PATH="${ELAN_HOME}/bin:${PATH}"
24+
elan --version
25+
elan show
26+
27+
- name: Cache Lake build artifacts
28+
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
29+
with:
30+
path: .lake
31+
key: lake-${{ hashFiles('lean-toolchain', 'lakefile.toml', 'lake-manifest.json') }}
32+
restore-keys: lake-
33+
34+
- name: Get Mathlib cache
35+
run: lake exe cache get || true
36+
37+
- name: Build (fail on sorry)
38+
run: lake build --wfail
39+
40+
- name: Lint (Mathlib environment linters)
41+
run: lake lint
42+
43+
- name: Check for sorry contamination
44+
run: |
45+
echo "Checking axiom dependencies..."
46+
touch FdFormal/Verify.lean
47+
lake env lean FdFormal/Verify.lean 2>&1 | tee verify_output.txt
48+
if grep -q "sorryAx" verify_output.txt; then
49+
echo "FATAL: sorryAx found in verified theorems!"
50+
exit 1
51+
fi
52+
echo "No sorry contamination detected."

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/.lake
2+
/lake-packages
3+
4+
/build
5+
/archive
6+
/docs/internal

.pre-commit-config.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v6.0.0
4+
hooks:
5+
- id: trailing-whitespace
6+
- id: end-of-file-fixer
7+
- id: check-merge-conflict
8+
- repo: local
9+
hooks:
10+
- id: check-copyright
11+
name: Mathlib copyright header (Lean files)
12+
entry: scripts/check-copyright.sh
13+
language: script
14+
files: \.lean$
15+
exclude: \.lake/

FdFormal.lean

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/-
2+
Copyright (c) 2026 Nelson Spence. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Nelson Spence
5+
-/
6+
import FdFormal.GraphBall
7+
import FdFormal.FlowerGraph
8+
import FdFormal.FlowerCounts
9+
import FdFormal.FlowerDiameter
10+
import FdFormal.FlowerDimension
11+
import FdFormal.Verify

FdFormal/FlowerCounts.lean

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/-
2+
Copyright (c) 2026 Nelson Spence. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Nelson Spence
5+
-/
6+
import FdFormal.FlowerGraph
7+
import Mathlib.Tactic
8+
9+
set_option relaxedAutoImplicit false
10+
set_option autoImplicit false
11+
12+
/-!
13+
# Flower Graph Exact Counts
14+
15+
Exact formulas for the edge and vertex counts of (u,v)-flower graphs
16+
at generation `g`. With `w = u + v`:
17+
18+
- **Edges:** `E_g = w^g`
19+
- **Vertices:** `(w - 1) * N_g = (w - 2) * w^g + w`
20+
21+
These are proved by induction on `g` from the construction rule:
22+
each edge is replaced by two parallel paths of lengths `u` and `v`,
23+
contributing `(u - 1) + (v - 1) = w - 2` new internal vertices per
24+
edge and multiplying the edge count by `w`.
25+
26+
## Main statements
27+
28+
- `flower_edge_count` — `E_g = w^g`
29+
- `flower_vertex_count` — `(w - 1) * N_g = (w - 2) * w^g + w`
30+
31+
## References
32+
33+
- [Rozenfeld2007] §2, construction and counting formulas.
34+
-/
35+
36+
-- TODO: State and prove edge_count and vertex_count once FlowerGraph
37+
-- construction is defined.
38+
--
39+
-- The edge count E_g = w^g follows directly: each edge produces w
40+
-- new edges (u edges on the short path + v edges on the long path).
41+
--
42+
-- The vertex count uses the recurrence:
43+
-- N_{g+1} = N_g + (w - 2) * E_g
44+
-- = N_g + (w - 2) * w^g
45+
-- with N_0 = 2 (two hub vertices connected by a single edge).
46+
-- Solving: (w-1) * N_g = (w-2) * w^g + w.
47+
--
48+
-- Real-valued wrappers for the headline theorem:
49+
-- def V_count_real (u v g : ℕ) : ℝ := (N_g : ℝ)
50+
-- Cast early, prove positivity lemmas here.

FdFormal/FlowerDiameter.lean

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/-
2+
Copyright (c) 2026 Nelson Spence. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Nelson Spence
5+
-/
6+
import FdFormal.FlowerGraph
7+
import Mathlib.Tactic
8+
9+
set_option relaxedAutoImplicit false
10+
set_option autoImplicit false
11+
12+
/-!
13+
# Flower Graph Diameter Scaling
14+
15+
The diameter of the (u,v)-flower at generation `g` scales as `u^g`
16+
for `u > 1`. The shortest path between the two hub vertices traverses
17+
the shorter parallel path (of length `u`) at each generation, giving
18+
`L_g = u^g`.
19+
20+
## Main statements
21+
22+
- `flower_diam_eq` — `L_g = u^g` (or asymptotic bound if exact
23+
formula requires parity analysis)
24+
25+
## Implementation notes
26+
27+
The exact diameter formula `L_g = u^g` holds because:
28+
1. The two original hubs are at distance `u^g` (the short path
29+
recurses through `g` generations).
30+
2. No pair of vertices can be farther apart (the long path of
31+
length `v^g` between hubs provides an alternative route, but
32+
`u ≤ v` means internal vertices on the long path are closer
33+
to a hub than the hub-to-hub distance).
34+
35+
For the headline theorem, we need `Real.log L_g / g → Real.log u`,
36+
which follows from `L_g = u^g` and `Real.log (u^g) = g * Real.log u`.
37+
38+
## References
39+
40+
- [Rozenfeld2007] §2, diameter analysis.
41+
-/
42+
43+
-- TODO: State and prove diameter formula once FlowerGraph is defined.
44+
--
45+
-- Real-valued wrapper:
46+
-- def L_diam_real (u v g : ℕ) : ℝ := (L_g : ℝ)
47+
-- Cast early, prove positivity (L_g > 0 for g ≥ 1, u > 1).

FdFormal/FlowerDimension.lean

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/-
2+
Copyright (c) 2026 Nelson Spence. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Nelson Spence
5+
-/
6+
import FdFormal.FlowerCounts
7+
import FdFormal.FlowerDiameter
8+
import Mathlib.Analysis.SpecialFunctions.Log.Basic
9+
import Mathlib.Tactic
10+
11+
set_option relaxedAutoImplicit false
12+
set_option autoImplicit false
13+
14+
/-!
15+
# Fractal Dimension of (u,v)-Flower Graphs
16+
17+
The fractal dimension of the (u,v)-flower family (for `1 < u`, `u ≤ v`)
18+
is `d_B = Real.log (u + v) / Real.log u`.
19+
20+
This is derived from the exact growth laws:
21+
- `|V_g|` grows like `(u+v)^g` (from `FlowerCounts`)
22+
- `L_g = u^g` (from `FlowerDiameter`)
23+
24+
So `Real.log |V_g| / Real.log L_g` → `Real.log (u+v) / Real.log u`
25+
as `g → ∞`.
26+
27+
## Main statements
28+
29+
- `flower_dimension` — the headline theorem:
30+
`Filter.Tendsto (fun g ↦ Real.log (V_count_real u v g) /
31+
Real.log (L_diam_real u v g))
32+
Filter.atTop (nhds (Real.log (u + v) / Real.log u))`
33+
34+
## Implementation notes
35+
36+
Counts and diameters are cast to `ℝ` via explicit wrapper definitions
37+
(`V_count_real`, `L_diam_real`) defined in `FlowerCounts` and
38+
`FlowerDiameter`. This avoids implicit coercion fights.
39+
40+
The proof uses:
41+
- `Real.log_pow` — `Real.log (x ^ n) = n * Real.log x`
42+
- `Real.log_pos` — `1 < x → 0 < Real.log x`
43+
- `Filter.Tendsto` for the limit statement
44+
45+
The u = 1 case is excluded by hypothesis (`1 < u`). The source
46+
treatment identifies u = 1 as transfractal with infinite d_B.
47+
48+
## References
49+
50+
- [Rozenfeld2007] Theorem 1, fractal dimension formula.
51+
- [Spence2026] navi-fractal calibration against this formula.
52+
-/
53+
54+
-- TODO: State and prove flower_dimension once FlowerCounts and
55+
-- FlowerDiameter provide the exact formulas.
56+
--
57+
-- Proof sketch:
58+
-- Real.log (V_count_real u v g) / Real.log (L_diam_real u v g)
59+
-- = Real.log (C * (u+v)^g) / Real.log (u^g) [by FlowerCounts]
60+
-- = Real.log (C * (u+v)^g) / (g * Real.log u) [by log_pow]
61+
-- = (Real.log C + g * Real.log (u+v)) / (g * Real.log u) [by log_mul]
62+
-- → Real.log (u+v) / Real.log u as g → ∞ [C term vanishes]

FdFormal/FlowerGraph.lean

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/-
2+
Copyright (c) 2026 Nelson Spence. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Nelson Spence
5+
-/
6+
import Mathlib.Combinatorics.SimpleGraph.Basic
7+
import Mathlib.Tactic
8+
9+
set_option relaxedAutoImplicit false
10+
set_option autoImplicit false
11+
12+
/-!
13+
# (u,v)-Flower Graph Construction
14+
15+
Recursive construction of the (u,v)-flower network family from
16+
Rozenfeld, Havlin & ben-Avraham (NJP 2007).
17+
18+
## Construction rule
19+
20+
At each generation, every edge is replaced by two parallel paths of
21+
lengths `u` and `v` (with `1 < u` and `u ≤ v`). The case `u = 1`
22+
produces transfractal (small-world) networks with infinite box-counting
23+
dimension and is excluded from this formalization.
24+
25+
## Main definitions
26+
27+
- `FlowerGraph` — the (u,v)-flower at generation `g`
28+
29+
## Implementation notes
30+
31+
Uses a custom recursive vertex type rather than quotient-identification.
32+
The vertex type grows with each generation as new intermediate vertices
33+
are inserted along subdivided edges. Hub vertices from generation 0 are
34+
tracked through the recursion.
35+
36+
The representation prioritizes proof tractability over computational
37+
efficiency — boring wins in Lean.
38+
39+
## References
40+
41+
- [Rozenfeld2007] Rozenfeld, Havlin & ben-Avraham, "Fractal and
42+
transfractal recursive scale-free nets," NJP 9:175 (2007).
43+
-/
44+
45+
-- TODO: Define FlowerGraph construction.
46+
-- The key design decision is the vertex type representation.
47+
-- Options considered:
48+
-- (a) Fin-indexed: FlowerGraph on Fin (V_count u v g)
49+
-- (b) Inductive vertex type with generation tags
50+
-- (c) Sigma type: Σ (e : edges of gen g-1), Fin (path_len - 1)
51+
--
52+
-- Option (a) is simplest for Fintype instances but hardest for
53+
-- tracking hub identity across generations.
54+
-- Option (c) is closest to the mathematical construction but
55+
-- requires careful handling of hub merging.
56+
--
57+
-- This file will be filled in during implementation.

FdFormal/GraphBall.lean

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/-
2+
Copyright (c) 2026 Nelson Spence. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Nelson Spence
5+
-/
6+
import Mathlib.Combinatorics.SimpleGraph.Metric
7+
import Mathlib.Combinatorics.SimpleGraph.Finite
8+
9+
set_option relaxedAutoImplicit false
10+
set_option autoImplicit false
11+
12+
/-!
13+
# Graph Balls via Extended Distance
14+
15+
Defines the metric ball on a `SimpleGraph` using `edist` (not `dist`),
16+
so that disconnected vertices are correctly excluded (they have
17+
`edist = ⊤`, not `dist = 0`).
18+
19+
## Main definitions
20+
21+
- `SimpleGraph.ball` — the set of vertices within extended distance `r`
22+
of a center vertex `c`
23+
24+
## Main statements
25+
26+
- `SimpleGraph.mem_ball` — membership characterization
27+
- `SimpleGraph.ball_mono` — monotonicity in radius
28+
29+
## Implementation notes
30+
31+
This file is designed as an upstream Mathlib candidate. It has no
32+
project-specific imports. The definition and basic API work on
33+
arbitrary vertex types; finiteness lemmas requiring `[Fintype V]`
34+
are separated into their own section.
35+
36+
## References
37+
38+
- Mathlib `SimpleGraph.Metric` for `edist`
39+
-/
40+
41+
namespace SimpleGraph
42+
43+
variable {V : Type*} (G : SimpleGraph V)
44+
45+
/-- The ball of radius `r` around vertex `c` in the graph metric.
46+
Uses `edist` so that unreachable vertices (at distance `⊤`) are
47+
correctly excluded. -/
48+
def ball (c : V) (r : ℕ∞) : Set V :=
49+
{v | G.edist c v ≤ r}
50+
51+
@[simp]
52+
theorem mem_ball {c : V} {v : V} {r : ℕ∞} :
53+
v ∈ G.ball c r ↔ G.edist c v ≤ r :=
54+
Iff.rfl
55+
56+
theorem ball_mono {c : V} {r₁ r₂ : ℕ∞} (h : r₁ ≤ r₂) :
57+
G.ball c r₁ ⊆ G.ball c r₂ :=
58+
fun _ hv ↦ le_trans hv h
59+
60+
theorem center_mem_ball {c : V} {r : ℕ∞} :
61+
c ∈ G.ball c r := by
62+
simp [ball, SimpleGraph.edist_self]
63+
64+
/-! ### Finiteness lemmas
65+
66+
These require `[Fintype V]` or similar finiteness assumptions. -/
67+
68+
section Finite
69+
70+
variable [Fintype V] [DecidableEq V] [DecidableRel G.Adj]
71+
72+
-- TODO: card_ball_mono, card_ball_nonneg, etc.
73+
-- These will be proved once the ball API is exercised by FlowerScaling.
74+
75+
end Finite
76+
77+
end SimpleGraph

0 commit comments

Comments
 (0)