Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

[Merged by Bors] - feat(combinatorics/simple_graph/connected): support of connected components #18442

Closed
0art0 wants to merge 32 commits intoleanprover-community:masterfrom
bottine:0art0/simple_graph/component.supp
Closed

[Merged by Bors] - feat(combinatorics/simple_graph/connected): support of connected components #18442
0art0 wants to merge 32 commits intoleanprover-community:masterfrom
bottine:0art0/simple_graph/component.supp

Conversation

@0art0
Copy link
Copy Markdown
Collaborator

@0art0 0art0 commented Feb 14, 2023

Co-authored-by: Rémi Bottinelli remi.bottinelli@bluewin.ch


Some basic API around the definition of the "support" of a connected component of a graph. The support consists of the set of vertices in a given component. This can be a convenient definition in certain situations.

Open in Gitpod

@0art0 0art0 requested a review from a team as a code owner February 14, 2023 16:37
@0art0 0art0 added awaiting-review The author would like community review of the PR t-combinatorics Combinatorics labels Feb 14, 2023
@YaelDillies
Copy link
Copy Markdown
Collaborator

Did you mean to give this PR a proper name?


/-- The set of vertices in a connected component of a graph. -/
def connected_component.supp (C : G.connected_component) :=
{ v | G.connected_component_mk v = C }
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{ v | G.connected_component_mk v = C }
G.connected_component_mk ⁻¹' {C}

is another, possibly more convenient, way to put it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were considering it before making the PR, but decided to stick with the more verbose notation.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the original notation: I feel it's a bit more transparent; e.g. when C := G.connected_component_mk v, membership is clear rfl while with the other notation you have (well, at least I do) to think to convince yourself that it unfolds to a rfl.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In one of my branches I had written connected_component_mk ⁻¹' {c} directly, but since we're developing this API for the support of a connected component, I'm happy with { v | G.connected_component_mk v = C }.

@bottine bottine changed the title 0art0/simple graph/component.supp feat(combinatorics.simple_graph.connected): support of connected components Feb 15, 2023
@0art0
Copy link
Copy Markdown
Collaborator Author

0art0 commented Feb 15, 2023

Sorry for not updating the name of the PR earlier.

@YaelDillies YaelDillies changed the title feat(combinatorics.simple_graph.connected): support of connected components feat(combinatorics/simple_graph/connected): support of connected components Feb 15, 2023
@bottine
Copy link
Copy Markdown
Collaborator

bottine commented Feb 15, 2023

I think we'll need to close the PR and open a new one eventually since the branch is wrong, and can't be changed in an existing PR.

@bottine bottine requested a review from YaelDillies February 15, 2023 10:54
h.elim (λ p, ⟨p.map f⟩)

lemma iso.reachable_iff {G : simple_graph V} {G' : simple_graph V'}
{φ : G ≃g G'} {u v : V} : G.reachable u v ↔ G'.reachable (φ u) (φ v) :=
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would turn this one around

{φ : G ≃g G'} {u v : V} : G.reachable u v ↔ G'.reachable (φ u) (φ v) :=
⟨reachable.map φ.to_hom, λ r, (φ.left_inv u) ▸ (φ.left_inv v) ▸ (r.map φ.symm.to_hom)⟩

lemma iso.reachable_iff' {G : simple_graph V} {G' : simple_graph V'}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can look at order_iso.symm_apply_le for a better naming convention.


section connected_component
variables {G}
variables {G} {V'} {G'} {G''}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following is valid syntax

Suggested change
variables {G} {V'} {G'} {G''}
variables {V' G G' G''}

by { refine C.ind _, exact (λ _, rfl), }

@[simp] lemma connected_component.iso_image_comp_eq_map_iff_eq_comp
{φ : G ≃g G'} {v : V} {C : G.connected_component} :
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can pull a few more variables out

Suggested change
{φ : G ≃g G'} {v : V} {C : G.connected_component} :
{C : G.connected_component} :

exact ((h v).mp (reachable.refl _)),
end

lemma connected_component.supp_inj {C D : G.connected_component} : C.supp = D.supp ↔ C = D :=
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
lemma connected_component.supp_inj {C D : G.connected_component} : C.supp = D.supp ↔ C = D :=
@[simp] lemma connected_component.supp_inj {C D : G.connected_component} : C.supp = D.supp ↔ C = D :=

left_inv := λ v, subtype.ext_val (φ.to_equiv.left_inv ↑v),
right_inv := λ v, subtype.ext_val (φ.to_equiv.right_inv ↑v), }

lemma connected_component.connected :
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
lemma connected_component.connected :
protected lemma connected_component.connected :

@0art0
Copy link
Copy Markdown
Collaborator Author

0art0 commented Feb 17, 2023

I will close this PR and open another one directly on mathlib, as @bottine suggested.

@0art0
Copy link
Copy Markdown
Collaborator Author

0art0 commented Feb 17, 2023

Somehow the CI has started working on this branch (after my tinkering around with git push). I'll leave things the way they are.

Copy link
Copy Markdown
Collaborator

@kmill kmill left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of my comments are minor, and if they're addressed I'd be happy with merging these parts. There is one major comment, which is I think we should exclude connected_component.connected from this PR.

It shouldn't be that bad to develop the theory to properly support this lemma, but it'll be enough work that I do not want it to hold up getting the rest merged.

Comment on lines +1410 to +1415
begin
rw [←φ.left_inv u, ←φ.right_inv v],
simp only [equiv.inv_fun_as_coe, equiv.to_fun_as_coe, rel_iso.coe_fn_to_equiv,
rel_iso.symm_apply_apply],
rw [iso.reachable_iff],
end
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
begin
rw [←φ.left_inv u, ←φ.right_inv v],
simp only [equiv.inv_fun_as_coe, equiv.to_fun_as_coe, rel_iso.coe_fn_to_equiv,
rel_iso.symm_apply_apply],
rw [iso.reachable_iff],
end
by rw [← iso.reachable_iff, rel_iso.apply_symm_apply]


lemma connected_component_mk_eq_of_adj (G : simple_graph V) {v w : V}
(a : G.adj v w) : G.connected_component_mk v = G.connected_component_mk w :=
connected_component.eq.mpr a.reachable
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for G to be explicit here? If not, could you please make it be implicit?

Also, I think the proof would be nicer as connected_component.sound a.reachable.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Further, you could leverage dot notation on adj.

Comment on lines +1540 to +1545
(G'.connected_component_mk (φ v)) = C.map φ.to_hom ↔ (G.connected_component_mk v) = C :=
begin
refine C.ind (λ u, _),
simp only [connected_component.map_mk, connected_component.eq],
exact iso.reachable_iff,
end
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure to use the coercion for φ rather than φ.to_hom. There are some extraneous parenthesis as well, and note that you can combine the last two lines of the proof (you can squeeze it if you want).

Suggested change
(G'.connected_component_mk (φ v)) = C.map φ.to_hom ↔ (G.connected_component_mk v) = C :=
begin
refine C.ind (λ u, _),
simp only [connected_component.map_mk, connected_component.eq],
exact iso.reachable_iff,
end
G'.connected_component_mk (φ v) = C.map φ ↔ G.connected_component_mk v = C :=
begin
refine C.ind (λ u, _),
simp [iso.reachable_iff],
end


@[simp] lemma connected_component.iso_inv_image_comp_eq_iff_eq_map
{C : G.connected_component} :
G.connected_component_mk (φ.symm v') = C ↔ G'.connected_component_mk v' = C.map φ :=
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
G.connected_component_mk (φ.symm v') = C ↔ G'.connected_component_mk v' = C.map φ :=
G.connected_component_mk (φ.symm v') = C ↔ G'.connected_component_mk v' = C.map φ :=

The last two lines of the proof can be merged as simp [iso.symm_apply_reachable]

Comment on lines +1559 to +1560
{ to_fun := connected_component.map φ.to_hom,
inv_fun := connected_component.map φ.symm.to_hom,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{ to_fun := connected_component.map φ.to_hom,
inv_fun := connected_component.map φ.symm.to_hom,
{ to_fun := connected_component.map φ,
inv_fun := connected_component.map φ.symm,


/-- The set of vertices in a connected component of a graph. -/
def connected_component.supp (C : G.connected_component) :=
{ v | G.connected_component_mk v = C }
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In one of my branches I had written connected_component_mk ⁻¹' {c} directly, but since we're developing this API for the support of a connected component, I'm happy with { v | G.connected_component_mk v = C }.

Comment on lines +1572 to +1578
begin
refine connected_component.ind₂ _,
intros v w h,
simp only [set.ext_iff, connected_component.eq, set.mem_set_of_eq, connected_component.supp] at
h ⊢,
exact ((h v).mp (reachable.refl _)),
end
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's perhaps less of a technical proof? In any case, I think the last line would be nice.

Suggested change
begin
refine connected_component.ind₂ _,
intros v w h,
simp only [set.ext_iff, connected_component.eq, set.mem_set_of_eq, connected_component.supp] at
h ⊢,
exact ((h v).mp (reachable.refl _)),
end
begin
refine connected_component.ind₂ _,
intros v w,
simp only [connected_component.supp, set.ext_iff, connected_component.eq, set.mem_set_of_eq],
intro h,
rw [reachable_comm, h],
end

v ∈ C.supp ↔ G.connected_component_mk v = C := iff.rfl

lemma connected_component_mk_mem (G : simple_graph V) {v : V} :
v ∈ G.connected_component_mk v := by { exact rfl, }
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe G should be implicit?

Just to nitpick, you can do this:

Suggested change
v ∈ G.connected_component_mk v := by { exact rfl, }
v ∈ G.connected_component_mk v := by exact rfl

Comment on lines +1600 to +1601
{ to_fun := λ v, ⟨φ.to_fun v.val, connected_component.iso_image_comp_eq_map_iff_eq_comp.mpr v.prop⟩,
inv_fun := λ v', ⟨φ.inv_fun v', connected_component.iso_inv_image_comp_eq_iff_eq_map.mpr v'.prop⟩,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tested this, but these should work, and it would be preferred:

Suggested change
{ to_fun := λ v, ⟨φ.to_fun v.val, connected_component.iso_image_comp_eq_map_iff_eq_comp.mpr v.prop⟩,
inv_fun := λ v', ⟨φ.inv_fun v', connected_component.iso_inv_image_comp_eq_iff_eq_map.mpr v'.prop⟩,
{ to_fun := λ v, ⟨φ v, connected_component.iso_image_comp_eq_map_iff_eq_comp.mpr v.prop⟩,
inv_fun := λ v', ⟨φ.symm v', connected_component.iso_inv_image_comp_eq_iff_eq_map.mpr v'.prop⟩,

rintro ⟨u,hu⟩ ⟨w,hw⟩,
simp only [connected_component.eq, set.mem_set_of_eq] at hu hw,
exact this (reachable.trans hu $ reachable.symm hw).some hu hw,
end
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this lemma is ready for the library. To do it right, we should have supporting theory for relating walks in G.induce s to walks whose support is contained in s.

I started writing


def induce_lift (s : set V) : Π {v w : V} (p : G.walk v w) (h : ∀ u, u ∈ p.support → u ∈ s),
  (G.induce s).walk ⟨v, h v p.start_mem_support⟩ ⟨w, h w p.end_mem_support⟩
| _ _ walk.nil _ := walk.nil
| _ _ (walk.cons' u v w ha p) h :=
  let p' := induce_lift p (λ x hx, h x (by simp [hx]))
  in walk.cons (by exact ha) p'

but fleshing everything out would take some time. Would you be ok with removing the lemma for now?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review! I agree having a more general theory for mapping walks back and forth would be better (this is how we handled it before), but at the same time the lemma works as-is and can be made to use this API when it gets there…
Since it's needed to make progress on Freudenthal-Hopf, I'd rather have it there, but I understand if you don't want to introduce "half-baked" results in simple_graph.*. Your call in any case :)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get that it works as-is, but at least for now it seems somewhat out of place from the rest of the PR.

I'm dusting off some things I have in a branch to make use of what you have here. I've said it before, but I suspect a number of things are cleaner through subgraphs rather than induced graphs (or at least, if you want to work with induced graphs, they can follow from facts about subgraphs).

In the meantime, would you be ok keeping this lemma in your Freudenthal-Hopf project?

Copy link
Copy Markdown
Collaborator

@bottine bottine Feb 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, works for me :) (I'm not doing any changes (yet?) since @0art0 might want to pitch in first and/or do the changes themselves).

@bottine
Copy link
Copy Markdown
Collaborator

bottine commented Mar 1, 2023

Also, I guess you'll have to do a synchronization mathlib4 PR for this one, since connectivity.lean has been ported in the meantime. If possible, I propose to have one PR to also synchronize #18410 and #18454 if that's allowed.

@bors
Copy link
Copy Markdown

bors bot commented Mar 1, 2023

Merge conflict.

@kmill
Copy link
Copy Markdown
Collaborator

kmill commented Mar 1, 2023

@bottine Regarding mathlib4 synchronization, for now my plan was to do them myself, collecting multiple mathlib3 PRs and updating mathlib4 in batches. But if you need something sooner go ahead.

Once every file in combinatorics/simple_graph is ported, I think we'll have to say that only mathlib4 simple graph PRs will be accepted.

@0art0
Copy link
Copy Markdown
Collaborator Author

0art0 commented Mar 2, 2023

There were a few issues left that I couldn't fix yesterday. I have now integrated the changes from #18410 into this PR. I noticed that there was some overlap between the PRs - connected_component.iso in this PR was iso.connected_component_equiv definition from the other PR. I have adopted the latter terminology, but I can stick to the former if that seems better.

@bottine
Copy link
Copy Markdown
Collaborator

bottine commented Mar 2, 2023

@0art0 Thanks! Indeed, the iso.connected_component_equiv terminology was decided after a suggestion/review from Kyle, so I expect it's the correct choice, see this thread.

@bottine
Copy link
Copy Markdown
Collaborator

bottine commented Mar 2, 2023

@bottine Regarding mathlib4 synchronization, for now my plan was to do them myself, collecting multiple mathlib3 PRs and updating mathlib4 in batches. But if you need something sooner go ahead.

Once every file in combinatorics/simple_graph is ported, I think we'll have to say that only mathlib4 simple graph PRs will be accepted.

That's very good to hear! I hate doing sync PRs, so if you can take care of it and we can just work on mathlib4 asap, that's doubly good news.

@bottine
Copy link
Copy Markdown
Collaborator

bottine commented Mar 2, 2023

@kmill This

@[simp] lemma iso_image_comp_eq_map_iff_eq_comp
  {C : G.connected_component} :
  G'.connected_component_mk (φ v) = C.map (↑(↑φ : G ↪g G'))  ↔ (G.connected_component_mk v) = C :=
begin
  refine C.ind (λ u, _),
  simp only [iso.reachable_iff, connected_component.map_mk,
    rel_embedding.coe_coe_fn, rel_iso.coe_coe_fn, connected_component.eq],
end

pleases the linter, but it's a bit ugly. Any alternative?

@bottine bottine requested a review from a team as a code owner March 2, 2023 13:52
@bottine bottine requested a review from kmill March 2, 2023 15:51
@bottine
Copy link
Copy Markdown
Collaborator

bottine commented Mar 3, 2023

Shall we ask bors to merge this now?

@kim-em kim-em added the modifies-synchronized-file This PR touches a files that has already been ported to mathlib4, and may need a synchronization PR. label Mar 28, 2023
@kim-em
Copy link
Copy Markdown
Collaborator

kim-em commented Mar 28, 2023

@kmill could you take another look at this?

@kmill
Copy link
Copy Markdown
Collaborator

kmill commented Mar 28, 2023

bors r+

bors bot pushed a commit that referenced this pull request Mar 28, 2023
…onents (#18442)

Co-authored-by: Rémi Bottinelli <remi.bottinelli@bluewin.ch>
 


Co-authored-by: ART <anand.rao.art@gmail.com>
Co-authored-by: Anand Rao <18333981+0art0@users.noreply.github.com>
@bors
Copy link
Copy Markdown

bors bot commented Mar 28, 2023

Pull request successfully merged into master.

Build succeeded:

@bors bors bot changed the title feat(combinatorics/simple_graph/connected): support of connected components [Merged by Bors] - feat(combinatorics/simple_graph/connected): support of connected components Mar 28, 2023
@bors bors bot closed this Mar 28, 2023
Parcly-Taxel added a commit to leanprover-community/mathlib4 that referenced this pull request Apr 20, 2023
bors bot pushed a commit to leanprover-community/mathlib4 that referenced this pull request Apr 20, 2023
kbuzzard pushed a commit to leanprover-community/mathlib4 that referenced this pull request Apr 22, 2023
kim-em pushed a commit to leanprover-community/mathlib4 that referenced this pull request May 10, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

awaiting-review The author would like community review of the PR modifies-synchronized-file This PR touches a files that has already been ported to mathlib4, and may need a synchronization PR. t-combinatorics Combinatorics

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants