@@ -12,19 +12,36 @@ set_option autoImplicit false
1212/-!
1313# Distance in path graphs
1414
15- **Status: Stub.** Statements are frozen; proofs are pending (submitted to
16- Aristotle automated prover).
17-
1815The graph distance between vertices `i` and `j` in `pathGraph (n + 1)`
19- equals `|i - j|`. These lemmas are building blocks for distance proofs
20- in recursive graph constructions.
16+ equals the absolute difference `|i - j|`. These lemmas fill a gap in
17+ Mathlib's `pathGraph` API (which has adjacency and connectivity but no
18+ distance results) and serve as building blocks for distance proofs in
19+ recursive graph constructions.
20+
21+ Proof strategies discovered by Aristotle (Harmonic) automated proof search,
22+ rewritten into human-owned form.
23+
24+ ## Main definitions
25+
26+ None — this file provides only lemmas about existing Mathlib definitions.
2127
2228## Main statements
2329
30+ - `SimpleGraph.pathGraph_edist` — `edist i j = |i.val - j.val|`
2431- `SimpleGraph.pathGraph_dist` — `dist i j = |i.val - j.val|`
2532- `SimpleGraph.pathGraph_dist_zero_last` — `dist 0 (Fin.last n) = n`
2633- `SimpleGraph.pathGraph_edist_zero_last` — `edist 0 (Fin.last n) = n`
2734
35+ ## Implementation notes
36+
37+ The key step is constructing a walk of length `|i - j|` by induction on the
38+ target vertex, then showing no shorter walk exists via a triangle-inequality
39+ argument on `Fin.val`. The `edist` result follows by `le_antisymm` on `iInf`.
40+
41+ ## References
42+
43+ None — fills a gap in Mathlib's `SimpleGraph.Hasse` / `SimpleGraph.Metric` API.
44+
2845## Tags
2946
3047path graph, graph distance, Hasse diagram
@@ -34,26 +51,92 @@ namespace SimpleGraph
3451
3552/-! ### Walk construction -/
3653
54+ /-- Walk from `0` to any vertex `i` in `pathGraph (n + 1)`, of length `i.val`. -/
55+ private theorem pathGraph_walk_from_zero {n : ℕ} (i : Fin (n + 1 )) :
56+ ∃ w : (pathGraph (n + 1 )).Walk 0 i, w.length = i.val := by
57+ induction i using Fin.inductionOn with
58+ | zero => exact ⟨.nil, rfl⟩
59+ | succ i ih =>
60+ obtain ⟨w, hw⟩ := ih
61+ have hadj : (pathGraph (n + 1 )).Adj i.castSucc i.succ := by
62+ rw [pathGraph_adj]; left; simp [Fin.val_succ, Fin.val_castSucc]
63+ exact ⟨w.append (.cons hadj .nil), by simp [hw]⟩
64+
3765/-- There is a walk of length `n` from `0` to `Fin.last n` in `pathGraph (n + 1)`. -/
3866theorem pathGraph_exists_walk_zero_last (n : ℕ) :
39- ∃ w : (pathGraph (n + 1 )).Walk 0 (Fin.last n), w.length = n := by
40- sorry
67+ ∃ w : (pathGraph (n + 1 )).Walk 0 (Fin.last n), w.length = n :=
68+ (pathGraph_walk_from_zero (Fin.last n)).imp fun _ h ↦ by simpa [Fin.val_last] using h
69+
70+ /-! ### Walk bounds -/
71+
72+ /-- Walk from `i` to `j` of length `j.val - i.val` when `i.val ≤ j.val`. -/
73+ private theorem pathGraph_walk_le {n : ℕ} {i j : Fin (n + 1 )} (hij : i.val ≤ j.val) :
74+ ∃ w : (pathGraph (n + 1 )).Walk i j, w.length = j.val - i.val := by
75+ induction j using Fin.inductionOn with
76+ | zero =>
77+ have hi : i = 0 := by ext; exact Nat.le_zero.mp hij
78+ exact hi ▸ ⟨.nil, by simp⟩
79+ | succ j ih =>
80+ by_cases h : i.val ≤ j.val
81+ · obtain ⟨w, hw⟩ := ih h
82+ have hadj : (pathGraph (n + 1 )).Adj j.castSucc j.succ := by
83+ rw [pathGraph_adj]; left; simp [Fin.val_succ, Fin.val_castSucc]
84+ exact ⟨w.append (.cons hadj .nil), by simp [hw]; omega⟩
85+ · have hval : j.succ.val = j.val + 1 := Fin.val_succ j
86+ have hi : i = j.succ := Fin.ext (by omega)
87+ subst hi; exact ⟨.nil, by simp⟩
88+
89+ /-- Any walk in `pathGraph` has length ≥ the index difference between endpoints.
90+ Each step changes the index by exactly 1, so `|i - j|` steps are needed. -/
91+ private theorem pathGraph_walk_length_ge {n : ℕ} {i j : Fin (n + 1 )}
92+ (p : (pathGraph (n + 1 )).Walk i j) :
93+ (if i.val ≤ j.val then j.val - i.val else i.val - j.val) ≤ p.length := by
94+ induction p with
95+ | nil => simp
96+ | @cons u v w hadj p ih =>
97+ have : u.val + 1 = v.val ∨ v.val + 1 = u.val := by
98+ rw [pathGraph_adj] at hadj; exact hadj
99+ simp only [Walk.length_cons]
100+ split_ifs at ih ⊢ <;> omega
101+
102+ /-! ### Extended distance formula -/
103+
104+ /-- Extended distance in a path graph equals the absolute difference of indices. -/
105+ theorem pathGraph_edist {n : ℕ} (i j : Fin (n + 1 )) :
106+ (pathGraph (n + 1 )).edist i j =
107+ ↑(if i.val ≤ j.val then j.val - i.val else i.val - j.val) := by
108+ -- Exhibit an optimal walk
109+ obtain ⟨w, hw⟩ : ∃ w : (pathGraph (n + 1 )).Walk i j,
110+ w.length = if i.val ≤ j.val then j.val - i.val else i.val - j.val := by
111+ split_ifs with hij
112+ · exact pathGraph_walk_le hij
113+ · obtain ⟨w', hw'⟩ := pathGraph_walk_le (show j.val ≤ i.val by omega)
114+ exact ⟨w'.reverse, by rw [Walk.length_reverse, hw']⟩
115+ apply le_antisymm
116+ · -- Upper: edist ≤ walk length = target
117+ calc (pathGraph (n + 1 )).edist i j
118+ ≤ ↑w.length := edist_le w
119+ _ = _ := by exact_mod_cast hw
120+ · -- Lower: target ≤ every walk length → target ≤ iInf
121+ simp only [edist]
122+ exact le_iInf fun w' ↦ by exact_mod_cast pathGraph_walk_length_ge w'
41123
42124/-! ### Distance formula -/
43125
44126/-- Distance in a path graph equals the absolute difference of indices. -/
45127theorem pathGraph_dist {n : ℕ} (i j : Fin (n + 1 )) :
46- (pathGraph (n + 1 )).dist i j = if i.val ≤ j.val then j.val - i.val else i.val - j.val := by
47- sorry
128+ (pathGraph (n + 1 )).dist i j =
129+ if i.val ≤ j.val then j.val - i.val else i.val - j.val := by
130+ simp only [SimpleGraph.dist, pathGraph_edist, ENat.toNat_coe]
48131
49132/-- Distance from `0` to `Fin.last n` in `pathGraph (n + 1)` is `n`. -/
50133theorem pathGraph_dist_zero_last (n : ℕ) :
51134 (pathGraph (n + 1 )).dist (0 : Fin (n + 1 )) (Fin.last n) = n := by
52- sorry
135+ rw [pathGraph_dist]; simp [Fin.val_last]
53136
54137/-- The extended distance from `0` to `Fin.last n` in `pathGraph (n + 1)` is `n`. -/
55138theorem pathGraph_edist_zero_last (n : ℕ) :
56139 (pathGraph (n + 1 )).edist (0 : Fin (n + 1 )) (Fin.last n) = n := by
57- sorry
140+ rw [pathGraph_edist]; simp [Fin.val_last]
58141
59142end SimpleGraph
0 commit comments