Zulip Chat Archive
Stream: Is there code for X?
Topic: Walk.support is injective
Daniel Weber (Aug 31 2024 at 15:58):
Is this theorem in Mathlib?
import Mathlib
lemma SimpleGraph.Walk.support_injective {V : Type*} {G : SimpleGraph V} {u v : V} :
Function.Injective (support (G := G) (v := v) (u := u)) := by
sorry
if not, what would be the easiest way to prove it?
Daniel Weber (Aug 31 2024 at 16:25):
I'm also looking for
theorem support_append' {u v w : V} (p : G.Walk u v) (p' : G.Walk v w) :
(p.append p').support = p.support.dropLast ++ p'.support
I managed to prove it, but it's really long and ugly
Rida Hamadani (Sep 02 2024 at 15:16):
Daniel Weber said:
Is this theorem in Mathlib?
import Mathlib lemma SimpleGraph.Walk.support_injective {V : Type*} {G : SimpleGraph V} {u v : V} : Function.Injective (support (G := G) (v := v) (u := u)) := by sorry
if not, what would be the easiest way to prove it?
It is not, my first thought is intro w w' h
followed by cases w
.
Vincent Beffara (Sep 02 2024 at 15:44):
That works and is ugly, but is not that long:
import Mathlib
lemma SimpleGraph.Walk.support_injective {V : Type*} {G : SimpleGraph V} {u v : V} :
Function.Injective (support (G := G) (v := v) (u := u)) := by
intro w1 w2 h
induction w2 with
| nil =>
rwa [← SimpleGraph.Walk.nil_iff_eq_nil, SimpleGraph.Walk.nil_iff_support_eq]
| cons h' p ih =>
cases w1 with
| nil =>
rw [support_nil, support_cons, support_eq_cons] at h
cases h
| cons h'' p'' =>
simp at h
have hhh := h
rw [p.support_eq_cons, p''.support_eq_cons] at hhh
simp at hhh
rcases hhh with ⟨rfl, -⟩
rw [ih h]
Rida Hamadani (Sep 02 2024 at 16:14):
Nice! Slightly shorter (but still not good looking):
import Mathlib
lemma SimpleGraph.Walk.support_injective {V : Type*} {G : SimpleGraph V} {u v : V} :
Function.Injective (support (G := G) (v := v) (u := u)) := by
intro w1 w2 h
induction w2 with
| nil =>
rwa [← SimpleGraph.Walk.nil_iff_eq_nil, SimpleGraph.Walk.nil_iff_support_eq]
| cons h' p ih =>
cases w1 with
| nil =>
simpa [support_ne_nil] using h.symm
| cons h'' p'' =>
have := (List.cons_inj_right _).mp h
rw [p.support_eq_cons, p''.support_eq_cons] at this
aesop
Vincent Beffara (Sep 02 2024 at 16:19):
import Mathlib
lemma SimpleGraph.Walk.support_injective {V : Type*} {G : SimpleGraph V} {u v : V} :
Function.Injective (support (G := G) (v := v) (u := u)) := by
intro w1 w2 h
induction w2 with
| nil =>
rwa [← SimpleGraph.Walk.nil_iff_eq_nil, SimpleGraph.Walk.nil_iff_support_eq]
| cons h' p ih =>
cases w1 with
| nil =>
rw [support_nil, support_cons, support_eq_cons] at h
cases h
| cons h'' p'' =>
have := h
simp at h ; rw [p.support_eq_cons, p''.support_eq_cons] at h
aesop
Hiding DTT hell behing aesop
is a good trick.
Rida Hamadani (Sep 02 2024 at 16:45):
I tried making it look mathlib-y:
import Mathlib
open SimpleGraph Walk
lemma support_injective {V : Type*} {G : SimpleGraph V} {u v : V} :
Function.Injective (@support V G v u) := by
intro w₁ w₂ h
induction w₂ with
| nil => rwa [← nil_iff_eq_nil, nil_iff_support_eq]
| cons _ p₁ =>
cases w₁ with
| nil => simpa using h.symm
| cons _ p₂ =>
have := p₁.support_eq_cons ▸ p₂.support_eq_cons ▸ (List.cons_inj_right _).mp h
aesop
This feels like a useful addition to Walk.lean
! Would you like to PR it?
Vincent Beffara (Sep 02 2024 at 20:28):
I would think that this is not the right way to do it. Rather, I would like to have a type for walks without specified endpoints (this is generally useful to have), with its appropriate induction principle (if it's true for any nil walk and anytime one adds a step, it is always true), and then state inductivity on that type (where it is true and follows in a nicer way by induction) and deduce that version by restriction.
Rida Hamadani (Sep 03 2024 at 01:15):
Oh yes, that would be nice!
Vincent Beffara (Sep 03 2024 at 07:38):
Something like this:
import Mathlib
open SimpleGraph
variable {V : Type*} {u v : V} {G : SimpleGraph V}
structure Walk' (G : SimpleGraph V) where
a : V
b : V
w : G.Walk a b
def cons' (w : Walk' G) (h : G.Adj u w.a) : Walk' G where
a := u
b := w.b
w := Walk.cons h w.w
theorem induct (P : Walk' G → Prop)
(h0 : ∀ {v}, P ⟨v, v, Walk.nil⟩)
(h1 : ∀ w : Walk' G, ∀ {u}, ∀ (h : G.Adj u w.a), P w → P (cons' w h)) :
∀ w : Walk' G, P w := by
rintro ⟨a, b, w⟩
induction w with
| nil => exact h0
| cons h p ih => exact h1 ⟨_, _, p⟩ h ih
theorem inject (w1 w2 : Walk' G) (h : w1.w.support = w2.w.support) : w1 = w2 := by
let P (w : Walk' G) := ∀ w', w.w.support = w'.w.support → w = w'
refine induct P ?_ ?_ w1 w2 h
· rintro v ⟨a, b, w⟩
cases w with
| nil => aesop
| cons h p =>
have := p.support_ne_nil
simp
aesop
· rintro w u h1 h2 ⟨a, b, w'⟩ h3
cases w' with
| nil => simp [cons'] at h3
| cons h p =>
simp [cons'] at h3
rcases h3 with ⟨rfl, h3⟩
cases h2 ⟨_, _, p⟩ h3
simp [cons']
lemma SimpleGraph.Walk.support_injective {V : Type*} {G : SimpleGraph V} {u v : V} :
Function.Injective (support (G := G) (v := v) (u := u)) := by
intro w1 w2 h
have := inject ⟨_, _, w1⟩ ⟨_, _, w2⟩ h
aesop
Rida Hamadani (Sep 03 2024 at 07:42):
If anybody ends up working on this, I wonder if it is a good idea to let w
be of type Option (G.Walk u v)
, as suggested by Kyle here.
Vincent Beffara (Sep 03 2024 at 11:54):
I missed that discussion, what would be the point?
Kyle Miller (Sep 03 2024 at 14:55):
@Rida Hamadani I wouldn't do the Option
thing here, since you want Walk'
to represent the type of walks-without-specified-endpoints. The Option
idea is only for having an object that represents edist values, and I'm not sure it's worth developing all that theory. Maybe someone someday will decide it will simplify their work with edists.
Rida Hamadani (Sep 03 2024 at 14:58):
Kyle Miller said:
Rida Hamadani I wouldn't do the
Option
thing here, since you wantWalk'
to represent the type of walks-without-specified-endpoints. TheOption
idea is only for having an object that represents edist values, and I'm not sure it's worth developing all that theory. Maybe someone someday will decide it will simplify their work with edists.
But wouldn't it make sense to have this to simplify edist
of Walk'
?
Kyle Miller (Sep 03 2024 at 15:10):
import Mathlib
open SimpleGraph
variable {V : Type*} {G : SimpleGraph V}
theorem support_append' {u v w : V} (p : G.Walk u v) (p' : G.Walk v w) :
(p.append p').support = p.support.dropLast ++ p'.support := by
induction p with
| nil => simp
| cons _ p ih =>
rw [Walk.cons_append, Walk.support_cons, ih, Walk.support_cons,
List.dropLast_cons_of_ne_nil, List.cons_append]
apply Walk.support_ne_nil
Kyle Miller (Sep 03 2024 at 15:20):
The injectivity theorem just needs a missing support
lemma, and it's not so bad:
import Mathlib
open SimpleGraph
variable {V : Type*} {G : SimpleGraph V}
lemma SimpleGraph.Walk.fst_eq_of_support_eq {u v u' v' : V} {p : G.Walk u v} {p' : G.Walk u' v'}
(h : p.support = p'.support) : u = u' := by
cases p <;> cases p' <;> simp at h <;> simp [h]
lemma SimpleGraph.Walk.support_injective {u v : V} :
Function.Injective (fun (p : G.Walk u v) ↦ p.support) := by
intro p q
induction p with
| nil => cases q <;> simp
| cons _ p' ih =>
cases q with
| nil => simp
| cons _ q' =>
simp only [support_cons, List.cons.injEq, true_and]
intro h
cases Walk.fst_eq_of_support_eq h
cases ih h
rfl
Kyle Miller (Sep 03 2024 at 15:21):
Well, I guess that's longer than what you all already found, but still, we should have this support lemma.
Kyle Miller (Sep 03 2024 at 15:22):
I would strongly suggest writing fun (p : G.Walk u v) ↦ p.support
rather than support (G := G) (v := v) (u := u)
, since the latter isn't so clear (it's not immediately clear what it's a function of)
Last updated: May 02 2025 at 03:31 UTC