Zulip Chat Archive
Stream: Is there code for X?
Topic: Transferring a walk to a subgraph
Snir Broshi (Oct 22 2025 at 18:09):
Is there an easy way of transferring a walk to a subgraphs of a graph, given that the edges of the walk are contained in the subgraph?
import Mathlib
namespace SimpleGraph.Walk
variable {V : Type*} {G : SimpleGraph V} {u v : V} (w : G.Walk u v)
theorem snd_mem_edges (hnil : ¬w.Nil) : s(u, w.snd) ∈ w.edges := sorry
theorem penultimate_mem_edges (hnil : ¬w.Nil) : s(w.penultimate, v) ∈ w.edges := sorry
def transferSubgraph (hnil : ¬w.Nil) {G' : G.Subgraph} (hw : ∀ e ∈ w.edges, e ∈ G'.edgeSet) :
G'.coe.Walk
⟨u, G'.mem_verts_of_mem_edge (hw _ <| w.snd_mem_edges hnil) ⟨_, rfl⟩⟩
⟨v, G'.mem_verts_of_mem_edge (hw _ <| w.penultimate_mem_edges hnil) ⟨w.penultimate, by simp⟩⟩
:= sorry
docs#SimpleGraph.Walk.transfer requires the graphs to have the same vertex set, and #30590 targets induced subgraphs only.
Shreyas Srinivas (Oct 22 2025 at 18:45):
I would suggest working entirely in Subgraphs.
Snir Broshi (Oct 22 2025 at 19:06):
Shreyas Srinivas said:
I would suggest working entirely in Subgraphs.
How? Transferring between 2 subgraphs also seems hard.
Jakub Nowak (Oct 22 2025 at 19:49):
This generalization might be useful to have.
def SimpleGraph.Walk.backward_map {V : Type u} {V' : Type v} {G : SimpleGraph V} {G' : SimpleGraph V'} (f : G' ↪g G) {u v : V'} (p : G.Walk (f u) (f v)) (h : ∀ w ∈ p.support, { w' // w = f w' }) : G'.Walk u v
transferSubgraph should follow from this.
Snir Broshi (Oct 22 2025 at 20:37):
It needs the fact that edges are in the smaller graph, not just vertices.
Although I'm having trouble getting the subgraph version from it:
import Mathlib
namespace SimpleGraph.Walk
variable {V V' : Type*} {G : SimpleGraph V} {G' : SimpleGraph V'} {u v : V} (w : G.Walk u v)
theorem snd_mem_edges (hnil : ¬w.Nil) : s(u, w.snd) ∈ w.edges := sorry
theorem penultimate_mem_edges (hnil : ¬w.Nil) : s(w.penultimate, v) ∈ w.edges := sorry
def transferSubgraph (hnil : ¬w.Nil) {G' : G.Subgraph}
(hw : ∀ e ∈ w.edges, e ∈ G'.edgeSet) : G'.coe.Walk
⟨u, G'.mem_verts_of_mem_edge (hw _ <| w.snd_mem_edges hnil) ⟨_, rfl⟩⟩
⟨v, G'.mem_verts_of_mem_edge (hw _ <| w.penultimate_mem_edges hnil) ⟨w.penultimate, by simp⟩⟩
:= sorry
def comap (f : G ↪g G') (w' : G'.Walk (f u) (f v))
(h : ∀ e' ∈ w'.edges, { e // e ∈ G.edgeSet ∧ e' = e.map f }) :
G.Walk u v
:= sorry
def transferSubgraph' {G' : G.Subgraph} {u v : G'.verts} (w : G.Walk u v)
(hw : ∀ e ∈ w.edges, e ∈ G'.edgeSet) : G'.coe.Walk u v
:= w.comap G'.hom sorry
Jakub Nowak (Oct 22 2025 at 21:19):
Ah yes, my mistake, I didn't use subgraph API much. Subgraph is Copy, not an Embedding.
Jakub Nowak (Oct 22 2025 at 21:21):
So something like this:
def comap (f : G.Copy G') (w' : G'.Walk (f u) (f v))
(h : ∀ e' ∈ w'.edges, { e // e ∈ G.edgeSet ∧ e' = e.map f }) :
G.Walk u v :=
sorry
def transferSubgraph' {G : G'.Subgraph} {u v : G.verts} (w : G'.Walk u v)
(hw : ∀ e ∈ w.edges, e ∈ G'.edgeSet) : G.coe.Walk u v :=
comap G.coeCopy w sorry
Snir Broshi (Oct 23 2025 at 01:33):
I think having this will solve things:
def mapToSubgraph (w : G.Walk u v) : w.toSubgraph.coe.Walk
⟨_, w.start_mem_verts_toSubgraph⟩
⟨_, w.end_mem_verts_toSubgraph⟩
:= sorry
Then we can .map the result with any f : w.toSubgraph.coe →g G which is pretty similar to the hw hypothesis.
Snir Broshi (Oct 23 2025 at 16:56):
Success: #30826
Snir Broshi (Oct 24 2025 at 03:28):
The original transferToSubgraph successfully implemented using mapToSubgraph:
(but with 3 sorried lemmas)
import Mathlib
namespace SimpleGraph.Walk
variable {V V' : Type*} {G : SimpleGraph V} {G' : SimpleGraph V'} {u v v' : V} (w : G.Walk u v)
theorem snd_mem_edges (hnil : ¬w.Nil) : s(u, w.snd) ∈ w.edges := sorry
theorem penultimate_mem_edges (hnil : ¬w.Nil) : s(w.penultimate, v) ∈ w.edges := sorry
def containingEdge (hnil : ¬w.Nil) (hsupp : v' ∈ w.support) : { e // e ∈ w.edges ∧ v' ∈ e } := sorry
/-- Map a walk to its own subgraph. -/
def mapToSubgraph {u v : V} : ∀ w : G.Walk u v, w.toSubgraph.coe.Walk
⟨_, w.start_mem_verts_toSubgraph⟩ ⟨_, w.end_mem_verts_toSubgraph⟩
| nil => nil
| cons .. =>
let h : cons .. |>.toSubgraph.Adj .. := (le_sup_left : _ ≤ Walk.toSubgraph _).right rfl
let h : cons .. |>.toSubgraph.coe.Adj ⟨_, h.fst_mem⟩ ⟨_, h.snd_mem⟩ := h
cons h <| mapToSubgraph _ |>.map <| Subgraph.inclusion le_sup_right
/-- Transfer a non-nil walk to a subgraph that contains all of its edges. -/
def transferToSubgraph (hnil : ¬w.Nil) {G' : G.Subgraph}
(hw : ∀ e ∈ w.edges, e ∈ G'.edgeSet) : G'.coe.Walk
⟨u, G'.mem_verts_of_mem_edge (hw _ <| w.snd_mem_edges hnil) ⟨_, rfl⟩⟩
⟨v, G'.mem_verts_of_mem_edge (hw _ <| w.penultimate_mem_edges hnil) ⟨w.penultimate, by simp⟩⟩
:=
let f : w.toSubgraph.coe →g G'.coe := {
toFun v' := ⟨v', let e := w.containingEdge hnil <| w.mem_verts_toSubgraph.mp v'.prop
Subgraph.mem_verts_of_mem_edge (hw _ e.prop.left) e.prop.right⟩
map_rel' h := hw _ <| w.mem_edges_toSubgraph.mp (h : s(_, _) ∈ _)
}
w.mapToSubgraph.map f
Last updated: Dec 20 2025 at 21:32 UTC