Skip to content

Commit 133756f

Browse files
feat: reshape SimpleGraph.ball to open balls per Zulip consensus
Redesign GraphBall.lean: definition uses strict `<` (matching Metric.ball), giving ball_top = connectedComponent.supp. Core API trimmed to 1 def + 7 lemmas for upstream PR; convenience lemmas kept below section marker. Rename ball_comm → mem_ball_comm. Submit Aristotle Batch 1 (flowerEdge_card, edgeSrc_ne_edgeTgt). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7ad61cd commit 133756f

7 files changed

Lines changed: 233 additions & 73 deletions

File tree

CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,8 @@ copyright headers on all `.lean` files.
170170
| `FlowerLog.lean` | Log identities + squeeze bounds | Proved |
171171
| `FlowerDimension.lean` | Headline theorem (squeeze limit) | Proved |
172172
| `FlowerLogRatio.lean` | HasLogRatioDimension definition | Definition only |
173-
| `GraphBall.lean` | SimpleGraph.ball (upstream candidate, 12 lemmas) | Proved |
174-
| `PathGraphDist.lean` | pathGraph distance (F2 building block) | Sorry stubs |
173+
| `GraphBall.lean` | SimpleGraph.ball open metric balls (upstream candidate) | Proved |
174+
| `PathGraphDist.lean` | pathGraph distance (upstream candidate) | Proved |
175175
| `FlowerConstruction.lean` | F2 bridge sketch (structured gadgets) | Sorry stubs |
176176
| `Verify.lean` | Axiom dashboard | Proved |
177177

FdFormal/GraphBall.lean

Lines changed: 90 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,44 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Nelson Spence
55
-/
66
import Mathlib.Combinatorics.SimpleGraph.Metric
7-
import Mathlib.Combinatorics.SimpleGraph.Finite
87

98
set_option relaxedAutoImplicit false
109
set_option autoImplicit false
1110

1211
/-!
1312
# Metric balls for simple graphs
1413
15-
This file defines the metric ball `SimpleGraph.ball` using the extended
16-
distance `SimpleGraph.edist`. Using `edist` (rather than `dist`) ensures
17-
that disconnected vertices, which are at distance `⊤`, are correctly
18-
excluded from finite-radius balls.
14+
This file defines the open metric ball `SimpleGraph.ball` using the extended
15+
distance `SimpleGraph.edist`, following the convention of `Metric.ball`.
16+
17+
Using strict inequality (`<`) gives the natural property that `ball c ⊤`
18+
equals the support of the connected component containing `c`.
1919
2020
## Main definitions
2121
22-
- `SimpleGraph.ball` — the set of vertices within extended distance `r`
23-
of a center vertex
22+
- `SimpleGraph.ball` — the set of vertices within extended distance strictly
23+
less than `r` of a center vertex
2424
2525
## Main statements
2626
2727
- `SimpleGraph.mem_ball` — membership characterization
28+
- `SimpleGraph.ball_zero` — the zero-radius ball is empty
29+
- `SimpleGraph.ball_one` — the unit ball is `{c}`
30+
- `SimpleGraph.ball_top` — the `⊤`-radius ball is the connected component
2831
- `SimpleGraph.ball_mono` — monotonicity in radius
29-
- `SimpleGraph.ball_zero` — the zero-radius ball is `{c}`
30-
- `SimpleGraph.ball_top` — the `⊤`-radius ball is `Set.univ`
31-
- `SimpleGraph.ball_comm` — `v ∈ G.ball c r ↔ c ∈ G.ball v r`
32-
- `SimpleGraph.ball_anti` — supergraphs have larger balls
32+
- `SimpleGraph.center_mem_ball` — center belongs to any positive-radius ball
33+
- `SimpleGraph.mem_ball_comm` — membership is symmetric in center and point
34+
35+
## Implementation notes
36+
37+
The definition uses `ℕ∞` radius to match `SimpleGraph.edist`. For finite
38+
`n : ℕ`, `G.ball c (n + 1)` is the closed ball of radius `n` in the usual
39+
sense (vertices at distance `≤ n`), since `edist c v < n + 1 ↔ edist c v ≤ n`
40+
for natural numbers.
41+
42+
## References
43+
44+
* `Mathlib.Combinatorics.SimpleGraph.Metric`
3345
3446
## Tags
3547
@@ -40,80 +52,104 @@ namespace SimpleGraph
4052

4153
variable {V : Type*} (G : SimpleGraph V)
4254

43-
/-! ### Definition and membership -/
44-
45-
/-- The closed ball of radius `r` around vertex `c` in the graph extended metric. -/
55+
/-- The open ball of radius `r` around vertex `c` in the graph extended metric. -/
4656
def ball (c : V) (r : ℕ∞) : Set V :=
47-
{v | G.edist c v r}
57+
{v | G.edist c v < r}
4858

4959
variable {G}
5060

5161
@[simp]
5262
theorem mem_ball {c v : V} {r : ℕ∞} :
53-
v ∈ G.ball c r ↔ G.edist c v r :=
63+
v ∈ G.ball c r ↔ G.edist c v < r :=
5464
Iff.rfl
5565

56-
theorem edist_le_of_mem_ball {c v : V} {r : ℕ∞} (h : v ∈ G.ball c r) :
57-
G.edist c v ≤ r :=
58-
h
59-
60-
/-! ### Radius extremes -/
66+
@[simp]
67+
theorem ball_zero {c : V} : G.ball c 0 = ∅ := by
68+
ext v; simp [ball]
6169

6270
@[simp]
63-
theorem ball_zero {c : V} : G.ball c 0 = {c} := by
71+
theorem ball_one {c : V} : G.ball c 1 = {c} := by
6472
ext v
65-
simp [ball, nonpos_iff_eq_zero]
73+
simp only [mem_ball, Set.mem_singleton_iff]
74+
constructor
75+
· intro h
76+
have h0 : G.edist c v = 0 := by
77+
have hne : G.edist c v ≠ ⊤ := ne_top_of_lt h
78+
lift G.edist c v to ℕ using hne with d
79+
have : d < 1 := by exact_mod_cast h
80+
exact_mod_cast (show d = 0 from by omega)
81+
exact (edist_eq_zero_iff.mp h0).symm
82+
· rintro rfl; simp
6683

6784
@[simp]
68-
theorem ball_top {c : V} : G.ball c ⊤ = Set.univ := by
85+
theorem ball_top {c : V} :
86+
G.ball c ⊤ = (G.connectedComponentMk c).supp := by
6987
ext v
70-
simp [ball]
71-
72-
/-! ### Monotonicity -/
88+
simp only [mem_ball, ConnectedComponent.mem_supp_iff]
89+
constructor
90+
· intro h
91+
exact (ConnectedComponent.eq.mpr
92+
(reachable_of_edist_ne_top (ne_top_of_lt h))).symm
93+
· intro h
94+
exact lt_top_iff_ne_top.mpr
95+
(edist_ne_top_iff_reachable.mpr (ConnectedComponent.eq.mp h.symm))
7396

7497
/-- Balls are monotone in the radius. -/
7598
theorem ball_mono {c : V} {r₁ r₂ : ℕ∞} (h : r₁ ≤ r₂) :
7699
G.ball c r₁ ⊆ G.ball c r₂ :=
77-
fun _ hv ↦ le_trans hv h
78-
79-
/-- Supergraphs have larger or equal balls. -/
80-
@[gcongr]
81-
theorem ball_anti {G' : SimpleGraph V} {c : V} {r : ℕ∞} (h : G ≤ G') :
82-
G.ball c r ⊆ G'.ball c r :=
83-
fun _ hv ↦ le_trans (edist_anti h) hv
100+
fun _ hv ↦ lt_of_lt_of_le hv h
84101

85-
/-! ### Center and symmetry -/
86-
87-
/-- The center vertex belongs to any ball around it. -/
88-
theorem center_mem_ball {c : V} {r : ℕ∞} :
102+
/-- The center vertex belongs to any ball of positive radius. -/
103+
theorem center_mem_ball {c : V} {r : ℕ∞} (hr : 0 < r) :
89104
c ∈ G.ball c r := by
90-
simp [ball]
91-
92-
theorem ball_nonempty {c : V} {r : ℕ∞} : (G.ball c r).Nonempty :=
93-
⟨c, center_mem_ball⟩
105+
simp [ball, hr]
94106

95107
/-- Ball membership is symmetric in center and point. -/
96-
theorem ball_comm {c v : V} {r : ℕ∞} :
108+
theorem mem_ball_comm {c v : V} {r : ℕ∞} :
97109
v ∈ G.ball c r ↔ c ∈ G.ball v r := by
98110
simp [ball, edist_comm]
99111

100-
/-! ### Adjacency -/
112+
/-! ### Convenience lemmas (not in first upstream PR) -/
101113

102-
theorem ball_one_eq {c : V} :
103-
G.ball c 1 = {v | G.edist c v 1} :=
104-
rfl
114+
theorem edist_lt_of_mem_ball {c v : V} {r : ℕ∞} (h : v ∈ G.ball c r) :
115+
G.edist c v < r :=
116+
h
105117

106-
theorem adj_of_mem_ball_one {c v : V} (h : v ∈ G.ball c 1) (hne : c ≠ v) :
107-
G.Adj c v := by
108-
rw [mem_ball] at h
109-
exact (edist_le_one_iff_adj_or_eq.mp h).resolve_right hne
118+
theorem ball_nonempty {c : V} {r : ℕ∞} (hr : 0 < r) : (G.ball c r).Nonempty :=
119+
⟨c, center_mem_ball hr⟩
110120

111-
/-! ### Triangle inequality -/
121+
/-- Supergraphs have larger or equal balls. -/
122+
@[gcongr]
123+
theorem ball_anti {G' : SimpleGraph V} {c : V} {r : ℕ∞} (h : G ≤ G') :
124+
G.ball c r ⊆ G'.ball c r :=
125+
fun _ hv ↦ lt_of_le_of_lt (edist_anti h) hv
126+
127+
/-- Vertices adjacent to `c` are in the ball of radius 2. -/
128+
theorem mem_ball_of_adj {c v : V} (h : G.Adj c v) :
129+
v ∈ G.ball c 2 := by
130+
simp only [mem_ball]
131+
have h1 : (1 : ℕ∞) < 2 := by exact_mod_cast (show (1 : ℕ) < 2 from by omega)
132+
exact lt_of_le_of_lt (edist_le_one_iff_adj_or_eq.mpr (Or.inl h)) h1
133+
134+
theorem adj_of_mem_ball_two {c v : V} (h : v ∈ G.ball c 2) (hne : c ≠ v) :
135+
G.Adj c v := by
136+
simp only [mem_ball] at h
137+
have hle : G.edist c v ≤ 1 := by
138+
have hne_top : G.edist c v ≠ ⊤ := ne_top_of_lt h
139+
lift G.edist c v to ℕ using hne_top with d
140+
have : d < 2 := by exact_mod_cast h
141+
exact_mod_cast (show d ≤ 1 from by omega)
142+
exact (edist_le_one_iff_adj_or_eq.mp hle).resolve_right hne
112143

113144
/-- If `v ∈ ball c r₁` and `w ∈ ball v r₂`, then `w ∈ ball c (r₁ + r₂)`. -/
114145
theorem mem_ball_of_mem_ball_of_mem_ball {c v w : V} {r₁ r₂ : ℕ∞}
115146
(hv : v ∈ G.ball c r₁) (hw : w ∈ G.ball v r₂) :
116-
w ∈ G.ball c (r₁ + r₂) :=
117-
le_trans G.edist_triangle (add_le_add hv hw)
147+
w ∈ G.ball c (r₁ + r₂) := by
148+
simp only [mem_ball] at *
149+
have hw_ne : G.edist v w ≠ ⊤ := ne_top_of_lt hw
150+
calc G.edist c w
151+
≤ G.edist c v + G.edist v w := G.edist_triangle
152+
_ < r₁ + G.edist v w := (ENat.add_lt_add_iff_right hw_ne).mpr hv
153+
_ ≤ r₁ + r₂ := by gcongr
118154

119155
end SimpleGraph

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ This is the ground truth formula that [navi-fractal](https://github.com/Project-
3434

3535
| Declaration | File | Topic | Mathlib status |
3636
|-------------|------|-------|----------------|
37-
| `SimpleGraph.ball` + 11 lemmas | `GraphBall` | Metric ball via `edist` (basic API, 12 lemmas) | No `SimpleGraph.ball` in Mathlib |
37+
| `SimpleGraph.ball` + 7 core lemmas | `GraphBall` | Open metric ball via `edist` (8 core + convenience lemmas) | No `SimpleGraph.ball` in Mathlib; PR ready to open |
3838

3939
## Axiom boundary
4040

@@ -60,7 +60,7 @@ lake build --wfail # fail on any sorry or warning
6060

6161
```
6262
FdFormal/
63-
GraphBall.lean — SimpleGraph.ball via edist, 12 lemmas (upstream candidate)
63+
GraphBall.lean — SimpleGraph.ball (open ball via edist), 8 core + convenience lemmas (upstream candidate)
6464
FlowerGraph.lean — Hub vertices and structural helpers
6565
FlowerCounts.lean — Exact edge/vertex count formulas, bounds, monotonicity
6666
FlowerDiameter.lean — Hub-distance scaling L_g = u^g, cast identities

ROADMAP.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ Supporting infrastructure (monotonicity, cast identities, log helpers) is
2424
in `FlowerCounts`, `FlowerDiameter`, and `FlowerLog`. Leaf lemmas are proved
2525
via a combination of human authoring and Aristotle automated proof search.
2626

27-
**Upstream contribution:** `GraphBall.lean` defines `SimpleGraph.ball` via
28-
`edist` and contains 12 proved lemmas (membership, monotonicity, radius
29-
extremes, center membership, symmetry, adjacency, triangle inequality).
30-
A draft Mathlib PR is prepared (`docs/internal/pr-mathlib-ball-draft.md`);
31-
must post to Zulip before opening. Need to check overlap with PR #33077
32-
(`SetRel.ball` by Yael Dillies).
27+
**Upstream contribution:** `GraphBall.lean` defines `SimpleGraph.ball` as an
28+
open ball via `edist` (strict `<`, not ``). Reshaped per Zulip discussion and
29+
auditor feedback: 1 def + 7 core lemmas (`mem_ball`, `ball_zero`, `ball_one`,
30+
`ball_top`, `ball_mono`, `center_mem_ball`, `mem_ball_comm`) form the upstream
31+
PR; convenience lemmas kept in-repo.
32+
Import simplified to `Mathlib.Combinatorics.SimpleGraph.Metric`.
33+
`ball_top` now gives connected-component support. PR ready to open.
3334

3435
### Next
3536

@@ -49,7 +50,7 @@ construction sketch with five layers:
4950
- Layer 1: `FlowerEdge u v g` (recursive edge index type) and
5051
`FlowerVert u v g` (hubs + sigma of internal vertices by generation).
5152
- Layer 2: `edgeEndpoints` via recursive gadget resolution, plus
52-
`edgeSrc_ne_edgeTgt` (sorry stub).
53+
`edgeSrc_ne_edgeTgt` (sorry stub; submitted to Aristotle Batch 1).
5354
- Layer 3: `flowerGraph'` as a `SimpleGraph` on `FlowerVert`, with
5455
`flowerAdj'` defined by edge existence.
5556
- Layer 4: Distance proof via upper bound (exhibited walk of length `u^g`)
@@ -60,6 +61,9 @@ construction sketch with five layers:
6061
giving the final `flowerGraph_dist_hubs` bridge statement.
6162
- Projection map `FlowerVert.project` is defined (not sorry).
6263

64+
**Aristotle Batch 1** submitted: `flowerEdge_card` and `edgeSrc_ne_edgeTgt`
65+
(running, results pending). These are leaf lemmas for Layers 1 and 2.
66+
6367
Building block: `PathGraphDist.lean` provides fully proved lemmas for
6468
`SimpleGraph.pathGraph` distance (`pathGraph_dist`, `pathGraph_dist_zero_last`,
6569
`pathGraph_edist_zero_last`). These have no Mathlib counterpart and are a

debt.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
`GadgetPos`, `LocalEdge`, recursive `FlowerEdge` edge indices,
1212
`edgeEndpoints` resolution, `FlowerVert` with hub embedding, `flowerGraph'`
1313
as `SimpleGraph`, projection map for lower bound, and `flowerGraph_dist_hubs`
14-
as the F2 bridge target. Several sorry stubs remain (irreflexivity,
14+
as the F2 bridge target. 8 sorry stubs remain (irreflexivity,
1515
connectivity, walk/distance bounds, vertex card, final transport).
16+
Aristotle Batch 1 submitted for `flowerEdge_card` and `edgeSrc_ne_edgeTgt`
17+
(running, results pending).
1618
*(FlowerConstruction.lean, FlowerGraph.lean)*
1719

1820
- [ ] **Log-ratio dimension bridge** — Prove `HasLogRatioDimension` for the
@@ -22,13 +24,13 @@
2224

2325
### Upstream candidates
2426

25-
- [ ] **SimpleGraph.ball PR**Clean up GraphBall.lean for Mathlib PR.
26-
Now has 12 lemmas (expanded API): `mem_ball`, `edist_le_of_mem_ball`,
27-
`ball_zero`, `ball_top`, `ball_mono`, `ball_anti`, `center_mem_ball`,
28-
`nonempty_ball`, `ball_comm`, `ball_one_eq`, `adj_of_mem_ball_one`,
29-
`mem_ball_of_mem_ball_of_mem_ball`. Watch PR #33077 (Yael Dillies,
30-
SetRel.ball) for potential overlap. Key reviewer: Rida Hamadani.
31-
*(GraphBall.lean)*
27+
- [ ] **SimpleGraph.ball PR**Reshaped per Zulip discussion and auditor
28+
feedback: open ball (`<` not ``), 1 def + 7 core lemmas (`mem_ball`,
29+
`ball_zero`, `ball_one`, `ball_top`, `ball_mono`, `center_mem_ball`,
30+
`mem_ball_comm`). `ball_top` gives connected-component
31+
support. Import simplified to `Mathlib.Combinatorics.SimpleGraph.Metric`.
32+
Convenience lemmas kept in-repo for project use. **Ready to open PR.**
33+
Key reviewer: Rida Hamadani. *(GraphBall.lean)*
3234

3335
- [ ] **GraphBall finite cardinality lemmas**`card_ball_mono` etc. require
3436
`[Fintype V]`. Separated from base definition by design. *(GraphBall.lean)*
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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+
/-
7+
Aristotle Batch 1 — Leaf: edgeSrc_ne_edgeTgt
8+
Target: Source ≠ target for every edge in the flower construction.
9+
Strategy: induction on g, case analysis on local edge positions.
10+
Base case: hub0 ≠ hub1. Step: gadget resolution preserves distinctness.
11+
-/
12+
import Mathlib.Tactic
13+
14+
set_option relaxedAutoImplicit false
15+
set_option autoImplicit false
16+
17+
/-! ## Layer 0: Local replacement gadget -/
18+
19+
inductive GadgetPos (u v : ℕ)
20+
| src
21+
| tgt
22+
| short (i : Fin (u - 1))
23+
| long (j : Fin (v - 1))
24+
25+
abbrev LocalEdge (u v : ℕ) := Fin u ⊕ Fin v
26+
27+
def localSrc (u v : ℕ) : LocalEdge u v → GadgetPos u v
28+
| .inl ⟨0, _⟩ => .src
29+
| .inl ⟨i + 1, h⟩ => .short ⟨i, by omega⟩
30+
| .inr ⟨0, _⟩ => .src
31+
| .inr ⟨j + 1, h⟩ => .long ⟨j, by omega⟩
32+
33+
def localTgt (u v : ℕ) : LocalEdge u v → GadgetPos u v
34+
| .inl i => if h : i.val + 1 = u then .tgt else .short ⟨i.val, by omega⟩
35+
| .inr j => if h : j.val + 1 = v then .tgt else .long ⟨j.val, by omega⟩
36+
37+
/-! ## Layer 1: Types -/
38+
39+
def FlowerEdge (u v : ℕ) : ℕ → Type
40+
| 0 => Unit
41+
| g + 1 => FlowerEdge u v g × LocalEdge u v
42+
43+
instance instFintypeFlowerEdge (u v g : ℕ) : Fintype (FlowerEdge u v g) := by
44+
induction g with
45+
| zero => exact inferInstanceAs (Fintype Unit)
46+
| succ g ih => exact inferInstanceAs (Fintype (_ × _))
47+
48+
def FlowerVert (u v : ℕ) (g : ℕ) : Type :=
49+
Fin 2 ⊕ Σ (k : Fin g), FlowerEdge u v k.val × (Fin (u - 1) ⊕ Fin (v - 1))
50+
51+
def FlowerVert.hub0 (u v g : ℕ) : FlowerVert u v g := .inl 0
52+
def FlowerVert.hub1 (u v g : ℕ) : FlowerVert u v g := .inl 1
53+
54+
def FlowerVert.embed (u v g : ℕ) : FlowerVert u v g → FlowerVert u v (g + 1)
55+
| .inl h => .inl h
56+
| .inr ⟨k, e, pos⟩ => .inr ⟨k.castSucc, e, pos⟩
57+
58+
/-! ## Layer 2: Edge endpoints -/
59+
60+
def edgeEndpoints (u v : ℕ) :
61+
(g : ℕ) → FlowerEdge u v g → FlowerVert u v g × FlowerVert u v g
62+
| 0, () => (.hub0 u v 0, .hub1 u v 0)
63+
| g + 1, (parent, localE) =>
64+
let (pSrc, pTgt) := edgeEndpoints u v g parent
65+
let resolve : GadgetPos u v → FlowerVert u v (g + 1) := fun
66+
| .src => FlowerVert.embed u v g pSrc
67+
| .tgt => FlowerVert.embed u v g pTgt
68+
| .short i => .inr ⟨⟨g, Nat.lt_succ_of_le le_rfl⟩, parent, .inl i⟩
69+
| .long j => .inr ⟨⟨g, Nat.lt_succ_of_le le_rfl⟩, parent, .inr j⟩
70+
(resolve (localSrc u v localE), resolve (localTgt u v localE))
71+
72+
def edgeSrc (u v g : ℕ) (e : FlowerEdge u v g) : FlowerVert u v g :=
73+
(edgeEndpoints u v g e).1
74+
75+
def edgeTgt (u v g : ℕ) (e : FlowerEdge u v g) : FlowerVert u v g :=
76+
(edgeEndpoints u v g e).2
77+
78+
/-! ## Helper: local source ≠ local target -/
79+
80+
/-- Within a single gadget, source and target positions are always distinct
81+
when `1 < u`. This is the key inductive step helper. -/
82+
theorem localSrc_ne_localTgt (u v : ℕ) (hu : 1 < u) (e : LocalEdge u v) :
83+
localSrc u v e ≠ localTgt u v e := by
84+
sorry
85+
86+
/-- Source ≠ target for every edge. -/
87+
theorem edgeSrc_ne_edgeTgt (u v g : ℕ) (hu : 1 < u) (e : FlowerEdge u v g) :
88+
edgeSrc u v g e ≠ edgeTgt u v g e := by
89+
sorry

0 commit comments

Comments
 (0)