Skip to content

Commit 2675050

Browse files
committed
chore(Combinatorics/SimpleGraph): remove sndOfNotNil (#16352)
Readd the refactorings to sndOfNotNil and tail The changes in 17b10a9 were accidentally reverted in 5025874 This PR reintroduces the changes. The patch applied cleanly, except for some small conflict in `Hamiltonian.lean` which I fixed.
1 parent 7c21c72 commit 2675050

File tree

5 files changed

+100
-63
lines changed

5 files changed

+100
-63
lines changed

Mathlib/Combinatorics/SimpleGraph/Acyclic.lean

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,12 @@ lemma IsTree.card_edgeFinset [Fintype V] [Fintype G.edgeSet] (hG : G.IsTree) :
170170
· exact (congrArg (·.fst) h)
171171
· have h1 : ((f a).firstDart <| not_nil_of_ne (by simpa using ha)).snd = b :=
172172
congrArg (·.snd) h
173-
have h3 := congrArg length (hf' _ (((f _).tail _).copy h1 rfl) ?_)
174-
· rw [length_copy, ← add_left_inj 1, length_tail_add_one] at h3
173+
have h3 := congrArg length (hf' _ ((f _).tail.copy h1 rfl) ?_)
174+
· rw [length_copy, ← add_left_inj 1,
175+
length_tail_add_one (not_nil_of_ne (by simpa using ha))] at h3
175176
omega
176177
· simp only [ne_eq, eq_mp_eq_cast, id_eq, isPath_copy]
177-
exact (hf _).tail _
178+
exact (hf _).tail (not_nil_of_ne (by simpa using ha))
178179
case surj =>
179180
simp only [mem_edgeFinset, Finset.mem_compl, Finset.mem_singleton, Sym2.forall, mem_edgeSet]
180181
intros x y h
@@ -188,7 +189,7 @@ lemma IsTree.card_edgeFinset [Fintype V] [Fintype G.edgeSet] (hG : G.IsTree) :
188189
length_cons, length_nil] at h'
189190
simp [Nat.le_zero, Nat.one_ne_zero] at h'
190191
rw [← hf' _ (.cons h.symm (f x)) ((cons_isPath_iff _ _).2 ⟨hf _, fun hy => ?contra⟩)]
191-
· rfl
192+
· simp only [firstDart_toProd, getVert_cons_succ, getVert_zero, Prod.swap_prod_mk]
192193
case contra =>
193194
suffices (f x).takeUntil y hy = .cons h .nil by
194195
rw [← take_spec _ hy] at h'

Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ theorem toSubgraph_adj_getVert {u v} (w : G.Walk u v) {i : ℕ} (hi : i < w.leng
189189
| nil => cases hi
190190
| cons hxy i' ih =>
191191
cases i
192-
· simp only [Walk.toSubgraph, Walk.getVert_zero, zero_add, cons_getVert_succ, Subgraph.sup_adj,
192+
· simp only [Walk.toSubgraph, Walk.getVert_zero, zero_add, getVert_cons_succ, Subgraph.sup_adj,
193193
subgraphOfAdj_adj, true_or]
194-
· simp only [Walk.toSubgraph, cons_getVert_succ, Subgraph.sup_adj, subgraphOfAdj_adj, Sym2.eq,
194+
· simp only [Walk.toSubgraph, getVert_cons_succ, Subgraph.sup_adj, subgraphOfAdj_adj, Sym2.eq,
195195
Sym2.rel_iff', Prod.mk.injEq, Prod.swap_prod_mk]
196196
right
197197
exact ih (Nat.succ_lt_succ_iff.mp hi)
@@ -211,7 +211,7 @@ theorem toSubgraph_adj_iff {u v u' v'} (w : G.Walk u v) :
211211
cases hadj with
212212
| inl hl =>
213213
use 0
214-
simp only [Walk.getVert_zero, zero_add, cons_getVert_succ]
214+
simp only [Walk.getVert_zero, zero_add, getVert_cons_succ]
215215
refine ⟨?_, by simp only [length_cons, Nat.zero_lt_succ]⟩
216216
simp only [Sym2.eq, Sym2.rel_iff', Prod.mk.injEq, Prod.swap_prod_mk]
217217
cases hl with
@@ -220,7 +220,7 @@ theorem toSubgraph_adj_iff {u v u' v'} (w : G.Walk u v) :
220220
| inr hr =>
221221
obtain ⟨i, hi⟩ := (toSubgraph_adj_iff _).mp hr
222222
use i + 1
223-
simp only [cons_getVert_succ]
223+
simp only [getVert_cons_succ]
224224
constructor
225225
· exact hi.1
226226
· simp only [Walk.length_cons, add_lt_add_iff_right, Nat.add_lt_add_right hi.2 1]

Mathlib/Combinatorics/SimpleGraph/Hamiltonian.lean

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ end
6767

6868
/-- A hamiltonian cycle is a cycle that visits every vertex once. -/
6969
structure IsHamiltonianCycle (p : G.Walk a a) extends p.IsCycle : Prop :=
70-
isHamiltonian_tail : (p.tail toIsCycle.not_nil).IsHamiltonian
70+
isHamiltonian_tail : p.tail.IsHamiltonian
7171

7272
variable {p : G.Walk a a}
7373

@@ -84,22 +84,23 @@ lemma IsHamiltonianCycle.map {H : SimpleGraph β} (f : G →g H) (hf : Bijective
8484
intro x
8585
rcases p with (_ | ⟨y, p⟩)
8686
· cases hp.ne_nil rfl
87-
simp only [support_cons, List.count_cons, beq_iff_eq, List.head_cons, hf.injective.eq_iff,
88-
add_tsub_cancel_right]
87+
simp only [map_cons, getVert_cons_succ, tail_cons_eq, support_copy,support_map]
88+
rw [List.count_map_of_injective _ _ hf.injective, ← support_copy, ← tail_cons_eq]
8989
exact hp.isHamiltonian_tail _
9090

9191
lemma isHamiltonianCycle_isCycle_and_isHamiltonian_tail :
92-
p.IsHamiltonianCycle ↔ ∃ h : p.IsCycle, (p.tail h.not_nil).IsHamiltonian :=
92+
p.IsHamiltonianCycle ↔ p.IsCyclep.tail.IsHamiltonian :=
9393
fun ⟨h, h'⟩ ↦ ⟨h, h'⟩, fun ⟨h, h'⟩ ↦ ⟨h, h'⟩⟩
9494

9595
lemma isHamiltonianCycle_iff_isCycle_and_support_count_tail_eq_one :
9696
p.IsHamiltonianCycle ↔ p.IsCycle ∧ ∀ a, (support p).tail.count a = 1 := by
97-
simp only [isHamiltonianCycle_isCycle_and_isHamiltonian_tail, IsHamiltonian, support_tail,
98-
exists_prop]
97+
simp (config := { contextual := true }) [isHamiltonianCycle_isCycle_and_isHamiltonian_tail,
98+
IsHamiltonian, support_tail, IsCycle.not_nil, exists_prop]
9999

100100
/-- A hamiltonian cycle visits every vertex. -/
101101
lemma IsHamiltonianCycle.mem_support (hp : p.IsHamiltonianCycle) (b : α) :
102-
b ∈ p.support := List.mem_of_mem_tail <| support_tail p _ ▸ hp.isHamiltonian_tail.mem_support _
102+
b ∈ p.support :=
103+
List.mem_of_mem_tail <| support_tail p hp.1.not_nil ▸ hp.isHamiltonian_tail.mem_support _
103104

104105
/-- The length of a hamiltonian cycle is the number of vertices. -/
105106
lemma IsHamiltonianCycle.length_eq [Fintype α] (hp : p.IsHamiltonianCycle) :
@@ -110,11 +111,11 @@ lemma IsHamiltonianCycle.length_eq [Fintype α] (hp : p.IsHamiltonianCycle) :
110111

111112
lemma IsHamiltonianCycle.count_support_self (hp : p.IsHamiltonianCycle) :
112113
p.support.count a = 2 := by
113-
rw [support_eq_cons, List.count_cons_self, ← support_tail, hp.isHamiltonian_tail]
114+
rw [support_eq_cons, List.count_cons_self, ← support_tail _ hp.1.not_nil, hp.isHamiltonian_tail]
114115

115116
lemma IsHamiltonianCycle.support_count_of_ne (hp : p.IsHamiltonianCycle) (h : a ≠ b) :
116117
p.support.count b = 1 := by
117-
rw [← cons_support_tail p, List.count_cons_of_ne h.symm, hp.isHamiltonian_tail]
118+
rw [← cons_support_tail p hp.1.not_nil, List.count_cons_of_ne h.symm, hp.isHamiltonian_tail]
118119

119120
end Walk
120121

Mathlib/Combinatorics/SimpleGraph/Path.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ theorem cons_isCycle_iff {u v : V} (p : G.Walk v u) (h : G.Adj u v) :
249249
have : p.support.Nodup → p.edges.Nodup := edges_nodup_of_support_nodup
250250
tauto
251251

252-
lemma IsPath.tail {p : G.Walk u v} (hp : p.IsPath) (hp' : ¬ p.Nil) : (p.tail hp').IsPath := by
252+
lemma IsPath.tail {p : G.Walk u v} (hp : p.IsPath) (hp' : ¬ p.Nil) : p.tail.IsPath := by
253253
rw [Walk.isPath_def] at hp ⊢
254254
rw [← cons_support_tail _ hp', List.nodup_cons] at hp
255255
exact hp.2

Mathlib/Combinatorics/SimpleGraph/Walk.lean

Lines changed: 80 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -177,16 +177,21 @@ theorem adj_getVert_succ {u v} (w : G.Walk u v) {i : ℕ} (hi : i < w.length) :
177177
· simp [getVert, hxy]
178178
· exact ih (Nat.succ_lt_succ_iff.1 hi)
179179

180+
lemma getVert_cons_one {u v w} (q : G.Walk v w) (hadj : G.Adj u v) :
181+
(q.cons hadj).getVert 1 = v := by
182+
have : (q.cons hadj).getVert 1 = q.getVert 0 := rfl
183+
simpa [getVert_zero] using this
184+
180185
@[simp]
181-
lemma cons_getVert_succ {u v w n} (p : G.Walk v w) (h : G.Adj u v) :
186+
lemma getVert_cons_succ {u v w n} (p : G.Walk v w) (h : G.Adj u v) :
182187
(p.cons h).getVert (n + 1) = p.getVert n := rfl
183188

184-
lemma cons_getVert {u v w n} (p : G.Walk v w) (h : G.Adj u v) (hn : n ≠ 0) :
189+
lemma getVert_cons {u v w n} (p : G.Walk v w) (h : G.Adj u v) (hn : n ≠ 0) :
185190
(p.cons h).getVert n = p.getVert (n - 1) := by
186191
obtain ⟨i, hi⟩ : ∃ (i : ℕ), i.succ = n := by
187192
use n - 1; exact Nat.succ_pred_eq_of_ne_zero hn
188193
rw [← hi]
189-
simp only [Nat.succ_eq_add_one, cons_getVert_succ, Nat.add_sub_cancel]
194+
simp only [Nat.succ_eq_add_one, getVert_cons_succ, Nat.add_sub_cancel]
190195

191196
@[simp]
192197
theorem cons_append {u v w x : V} (h : G.Adj u v) (p : G.Walk v w) (q : G.Walk w x) :
@@ -754,6 +759,9 @@ lemma nil_iff_support_eq {p : G.Walk v w} : p.Nil ↔ p.support = [v] := by
754759
lemma nil_iff_length_eq {p : G.Walk v w} : p.Nil ↔ p.length = 0 := by
755760
cases p <;> simp
756761

762+
lemma not_nil_iff_lt_length {p : G.Walk v w} : ¬ p.Nil ↔ 0 < p.length := by
763+
cases p <;> simp
764+
757765
lemma not_nil_iff {p : G.Walk v w} :
758766
¬ p.Nil ↔ ∃ (u : V) (h : G.Adj v u) (q : G.Walk u w), p = cons h q := by
759767
cases p <;> simp [*]
@@ -778,61 +786,77 @@ lemma notNilRec_cons {motive : {u w : V} → (p : G.Walk u w) → ¬ p.Nil → S
778786
motive (q.cons h) Walk.not_nil_cons) (h' : G.Adj u v) (q' : G.Walk v w) :
779787
@Walk.notNilRec _ _ _ _ _ cons _ _ = cons h' q' := by rfl
780788

781-
/-- The second vertex along a non-nil walk. -/
782-
def sndOfNotNil (p : G.Walk v w) (hp : ¬ p.Nil) : V :=
783-
p.notNilRec (@fun _ u _ _ _ => u) hp
789+
@[simp] lemma adj_getVert_one {p : G.Walk v w} (hp : ¬ p.Nil) :
790+
G.Adj v (p.getVert 1) := by
791+
simpa using adj_getVert_succ p (by simpa [not_nil_iff_lt_length] using hp : 0 < p.length)
784792

785-
@[simp] lemma adj_sndOfNotNil {p : G.Walk v w} (hp : ¬ p.Nil) :
786-
G.Adj v (p.sndOfNotNil hp) :=
787-
p.notNilRec (fun h _ => h) hp
793+
/-- The walk obtained by removing the first `n` darts of a walk. -/
794+
def drop {u v : V} (p : G.Walk u v) (n : ℕ) : G.Walk (p.getVert n) v :=
795+
match p, n with
796+
| .nil, _ => .nil
797+
| p, 0 => p.copy (getVert_zero p).symm rfl
798+
| .cons h q, (n + 1) => (q.drop n).copy (getVert_cons_succ _ h).symm rfl
788799

789800
/-- The walk obtained by removing the first dart of a non-nil walk. -/
790-
def tail (p : G.Walk u v) (hp : ¬ p.Nil) : G.Walk (p.sndOfNotNil hp) v :=
791-
p.notNilRec (fun _ q => q) hp
801+
def tail (p : G.Walk u v) : G.Walk (p.getVert 1) v := p.drop 1
802+
803+
@[simp]
804+
lemma tail_cons_nil (h : G.Adj u v) : (Walk.cons h .nil).tail = .nil := by rfl
805+
806+
lemma tail_cons_eq (h : G.Adj u v) (p : G.Walk v w) :
807+
(p.cons h).tail = p.copy (getVert_zero p).symm rfl := by
808+
match p with
809+
| .nil => rfl
810+
| .cons h q => rfl
792811

793812
/-- The first dart of a walk. -/
794813
@[simps]
795814
def firstDart (p : G.Walk v w) (hp : ¬ p.Nil) : G.Dart where
796815
fst := v
797-
snd := p.sndOfNotNil hp
798-
adj := p.adj_sndOfNotNil hp
816+
snd := p.getVert 1
817+
adj := p.adj_getVert_one hp
799818

800819
lemma edge_firstDart (p : G.Walk v w) (hp : ¬ p.Nil) :
801-
(p.firstDart hp).edge = s(v, p.sndOfNotNil hp) := rfl
820+
(p.firstDart hp).edge = s(v, p.getVert 1) := rfl
802821

803822
variable {x y : V} -- TODO: rename to u, v, w instead?
804823

805-
@[simp] lemma cons_tail_eq (p : G.Walk x y) (hp : ¬ p.Nil) :
806-
cons (p.adj_sndOfNotNil hp) (p.tail hp) = p :=
807-
p.notNilRec (fun _ _ => rfl) hp
824+
lemma cons_tail_eq (p : G.Walk x y) (hp : ¬ p.Nil) :
825+
cons (p.adj_getVert_one hp) p.tail = p := by
826+
cases p with
827+
| nil => simp only [nil_nil, not_true_eq_false] at hp
828+
| cons h q =>
829+
simp only [getVert_cons_succ, tail_cons_eq, cons_copy, copy_rfl_rfl]
808830

809831
@[simp] lemma cons_support_tail (p : G.Walk x y) (hp : ¬p.Nil) :
810-
x :: (p.tail hp).support = p.support := by
811-
rw [← support_cons, cons_tail_eq]
832+
x :: p.tail.support = p.support := by
833+
rw [← support_cons, cons_tail_eq _ hp]
812834

813835
@[simp] lemma length_tail_add_one {p : G.Walk x y} (hp : ¬ p.Nil) :
814-
(p.tail hp).length + 1 = p.length := by
815-
rw [← length_cons, cons_tail_eq]
836+
p.tail.length + 1 = p.length := by
837+
rw [← length_cons, cons_tail_eq _ hp]
816838

817839
@[simp] lemma nil_copy {x' y' : V} {p : G.Walk x y} (hx : x = x') (hy : y = y') :
818840
(p.copy hx hy).Nil = p.Nil := by
819841
subst_vars; rfl
820842

821-
@[simp] lemma support_tail (p : G.Walk v v) (hp) :
822-
(p.tail hp).support = p.support.tail := by
843+
@[simp] lemma support_tail (p : G.Walk v v) (hp : ¬ p.Nil) :
844+
p.tail.support = p.support.tail := by
823845
rw [← cons_support_tail p hp, List.tail_cons]
824846

825847
@[simp]
826848
lemma tail_cons {t u v} (p : G.Walk u v) (h : G.Adj t u) :
827-
(p.cons h).tail not_nil_cons = p := by
828-
unfold Walk.tail; simp only [notNilRec_cons]
849+
(p.cons h).tail = p.copy (getVert_zero p).symm rfl := by
850+
match p with
851+
| .nil => rfl
852+
| .cons h q => rfl
829853

830-
lemma tail_support_eq_support_tail (p : G.Walk u v) (hnp : ¬p.Nil) :
831-
(p.tail hnp).support = p.support.tail :=
832-
p.notNilRec (by
833-
intro u v w huv q
834-
unfold Walk.tail
835-
simp only [notNilRec_cons, Walk.support_cons, List.tail_cons]) hnp
854+
lemma support_tail_of_not_nil (p : G.Walk u v) (hnp : ¬p.Nil) :
855+
p.tail.support = p.support.tail := by
856+
match p with
857+
| .nil => simp only [nil_nil, not_true_eq_false] at hnp
858+
| .cons h q =>
859+
simp only [tail_cons, getVert_cons_succ, support_copy, support_cons, List.tail_cons]
836860

837861
/-! ### Walk decompositions -/
838862

@@ -1008,17 +1032,23 @@ theorem exists_boundary_dart {u v : V} (p : G.Walk u v) (S : Set V) (uS : u ∈
10081032
exact ⟨d, List.Mem.tail _ hd, hcd⟩
10091033
· exact ⟨⟨(x, y), a⟩, List.Mem.head _, uS, h⟩
10101034

1011-
lemma getVert_tail {u v n} (p : G.Walk u v) (hnp: ¬ p.Nil) :
1012-
(p.tail hnp).getVert n = p.getVert (n + 1) :=
1013-
p.notNilRec (fun _ _ ↦ by simp only [tail_cons, cons_getVert_succ]) hnp
1014-
1015-
@[simp]
1016-
lemma cons_sndOfNotNil (q : G.Walk v w) (hadj : G.Adj u v) :
1017-
(q.cons hadj).sndOfNotNil not_nil_cons = v := by
1018-
unfold sndOfNotNil; simp only [notNilRec_cons]
1019-
1020-
lemma getVert_one (p : G.Walk u v) (hnp : ¬ p.Nil) : p.getVert 1 = p.sndOfNotNil hnp :=
1021-
p.notNilRec (fun _ _ ↦ by simp only [cons_getVert_succ, getVert_zero, cons_sndOfNotNil]) hnp
1035+
@[simp] lemma getVert_copy {u v w x : V} (p : G.Walk u v) (i : ℕ) (h : u = w) (h' : v = x) :
1036+
(p.copy h h').getVert i = p.getVert i := by
1037+
subst_vars
1038+
match p, i with
1039+
| .nil, _ =>
1040+
rw [getVert_of_length_le _ (by simp only [length_nil, Nat.zero_le] : nil.length ≤ _)]
1041+
rw [getVert_of_length_le _ (by simp only [length_copy, length_nil, Nat.zero_le])]
1042+
| .cons hadj q, 0 => simp only [copy_rfl_rfl, getVert_zero]
1043+
| .cons hadj q, (n + 1) => simp only [copy_cons, getVert_cons_succ]; rfl
1044+
1045+
@[simp] lemma getVert_tail {u v n} (p : G.Walk u v) (hnp: ¬ p.Nil) :
1046+
p.tail.getVert n = p.getVert (n + 1) := by
1047+
match p with
1048+
| .nil => rfl
1049+
| .cons h q =>
1050+
simp only [getVert_cons_succ, tail_cons_eq, getVert_cons]
1051+
exact getVert_copy q n (getVert_zero q).symm rfl
10221052

10231053
/-- Given a walk `w` and a node in the support, there exists a natural `n`, such that given node
10241054
is the `n`-th node (zero-indexed) in the walk. In addition, `n` is at most the length of the path.
@@ -1045,13 +1075,18 @@ theorem mem_support_iff_exists_getVert {u v w : V} {p : G.Walk v w} :
10451075
rw [@nil_iff_length_eq]
10461076
have : 1 ≤ p.length := by omega
10471077
exact Nat.not_eq_zero_of_lt this
1048-
rw [← tail_support_eq_support_tail _ hnp]
1078+
rw [← support_tail_of_not_nil _ hnp]
10491079
rw [mem_support_iff_exists_getVert]
10501080
use n - 1
1051-
simp only [Nat.sub_le_iff_le_add, length_tail_add_one, getVert_tail]
1052-
have : n - 1 + 1 = n := by omega
1081+
simp only [Nat.sub_le_iff_le_add]
1082+
rw [getVert_tail _ hnp, length_tail_add_one hnp]
1083+
have : (n - 1 + 1) = n:= by omega
10531084
rwa [this]
10541085
termination_by p.length
1086+
decreasing_by
1087+
· simp_wf
1088+
rw [@Nat.lt_iff_add_one_le]
1089+
rw [length_tail_add_one hnp]
10551090

10561091
end Walk
10571092

0 commit comments

Comments
 (0)