Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
c6ec473
feat(Data/Sym/Sym2): `fromRel` equivalence with `Sigma` over a `Quoti…
SnirBroshi Feb 6, 2026
4980ed5
feat(Combinatorics/SimpleGraph/Acyclic): a graph is a tree iff it's a…
SnirBroshi Feb 6, 2026
cf038ba
`RelHom.ofLE` docstring
SnirBroshi Feb 6, 2026
68b3331
replace `Equiv.sigmaQuot` with `Equiv.sigmaFiberEquiv` and tag `simps`
SnirBroshi Feb 6, 2026
c29bf8b
make the type of `q` explicit in `Sigma` binders
SnirBroshi Feb 6, 2026
7437183
replace `subst` with `rfl` in `rcases`
SnirBroshi Feb 6, 2026
9e8cadc
generalize to fibers
SnirBroshi Feb 7, 2026
353130b
no need to \comp in the quotients version because we got rid of the p…
SnirBroshi Feb 7, 2026
294e917
improve `Symmetric.comap` + `Subtype.val` spelling
SnirBroshi Feb 7, 2026
e1df04b
cosmetic changes
SnirBroshi Feb 7, 2026
c996f86
Merge branch 'master' into feature/sym2-fromrel-ndrec-and-equiv-quot
SnirBroshi Feb 14, 2026
88e2969
Merge branch 'master' into feature/simple-graph/tree-iff-acyclic-and-…
SnirBroshi Feb 14, 2026
7c870cf
fix merge
SnirBroshi Feb 14, 2026
1b2c614
"every" → "an"
SnirBroshi Feb 14, 2026
26389a6
remove redundant `<|`
SnirBroshi Feb 14, 2026
73086cf
Merge branch 'master' into feature/sym2-fromrel-ndrec-and-equiv-quot
SnirBroshi Feb 16, 2026
87bad13
fix after the signature of `Sym2.hrec` changed in master
SnirBroshi Feb 16, 2026
ad81eb8
Merge branch 'master' into feature/simple-graph/tree-iff-acyclic-and-…
SnirBroshi Mar 1, 2026
0f9476f
Merge branch 'feature/sym2-fromrel-ndrec-and-equiv-quot' into feature…
SnirBroshi Mar 2, 2026
eee507f
fix because `grind` broke somehow
SnirBroshi Mar 2, 2026
32ebd1a
might as well
SnirBroshi Mar 2, 2026
0ea71f5
Merge branch 'master' into feature/sym2-fromrel-ndrec-and-equiv-quot
SnirBroshi Mar 20, 2026
856c74a
Merge branch 'feature/sym2-fromrel-ndrec-and-equiv-quot' into feature…
SnirBroshi Mar 20, 2026
be182cb
`IsTree.IsAcyclic` is deprecated
SnirBroshi Mar 20, 2026
54e21b2
Merge branch 'master' into feature/sym2-fromrel-ndrec-and-equiv-quot
SnirBroshi Apr 16, 2026
c277057
use `fromRelNdrec` in bipartite graphs, see comment:
SnirBroshi Apr 16, 2026
d19d07d
Merge branch 'master' into feature/sym2-fromrel-ndrec-and-equiv-quot
SnirBroshi Apr 28, 2026
f02f013
make `z` explicit to avoid hidden pretty-prints
SnirBroshi Apr 29, 2026
b57791d
add simp lemmas, changed `sigmaQuotientFromRel` proof to avoid `Quot`…
SnirBroshi Apr 29, 2026
fa03e4b
update docstring of `sigmaFiberFromRel`
SnirBroshi Apr 30, 2026
3461c62
Merge branch 'master' into feature/simple-graph/tree-iff-acyclic-and-…
SnirBroshi May 30, 2026
7443c51
Merge branch 'master' into feature/sym2-fromrel-ndrec-and-equiv-quot
SnirBroshi Jun 2, 2026
9bc5dd6
`dsimp` is now redundant
SnirBroshi Jun 2, 2026
4c2f32c
Merge branch 'feature/sym2-fromrel-ndrec-and-equiv-quot' into feature…
SnirBroshi Jun 2, 2026
9e3daec
strange fixes
SnirBroshi Jun 2, 2026
bc79940
Merge remote-tracking branch 'upstream/master' into feature/sym2-from…
SnirBroshi Jun 11, 2026
058fa64
Merge branch 'feature/sym2-fromrel-ndrec-and-equiv-quot' into feature…
SnirBroshi Jun 11, 2026
66da04f
Merge branch 'master' into feature/simple-graph/tree-iff-acyclic-and-…
SnirBroshi Jun 15, 2026
5c98360
`Nat.card G.edgeSet` -> `G.edgeSet.ncard`
SnirBroshi Jun 15, 2026
2ebd30d
`G.edgeSet.ncard + 1 = Nat.card V` in a finite tree
SnirBroshi Jun 15, 2026
16a5dad
Merge branch 'master' into feature/simple-graph/tree-iff-acyclic-and-…
SnirBroshi Jun 16, 2026
e952ebd
`card_edgeSet` -> `ncard_edgeSet` in names
SnirBroshi Jun 18, 2026
fbff91b
delete `card_vert_le_ncard_edgeSet_isAcyclic`
SnirBroshi Jun 18, 2026
ea26511
rename `card_vert_le_ncard_edgeSet_exists_isCycle` -> `exists_isCycle…
SnirBroshi Jun 18, 2026
43c05db
more name fixes
SnirBroshi Jun 18, 2026
87fd089
`Quot.mk G.Reachable` -> `G.connectedComponentMk`
SnirBroshi Jun 18, 2026
f60f58a
`IsTree.ncard_edgeSet_add_one` follows directly from the finset version
SnirBroshi Jun 18, 2026
fc3fa5a
golf `isTree_iff_isAcyclic_and_ncard_edgeSet_add_one_eq_card`
SnirBroshi Jun 18, 2026
7eabf4a
Apply suggestions from code review
SnirBroshi Jul 11, 2026
50081fe
Merge branch 'master' into feature/simple-graph/tree-iff-acyclic-and-…
SnirBroshi Jul 11, 2026
8846957
more docstring periods
SnirBroshi Jul 11, 2026
f2906dc
small golf to `ncard_edgeSet_add_card_connectedComponent`
SnirBroshi Jul 11, 2026
8379122
extract the summations of connected component sizes to lemmas
SnirBroshi Jul 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 52 additions & 3 deletions Mathlib/Combinatorics/SimpleGraph/Acyclic.lean
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/-
Copyright (c) 2022 Kyle Miller. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kyle Miller
Authors: Kyle Miller, Snir Broshi
-/
module

Expand Down Expand Up @@ -343,6 +343,12 @@ lemma IsTree.card_edgeFinset [Fintype V] [Fintype G.edgeSet] (hG : G.IsTree) :
refine (hG.existsUnique_path _ _).unique ((hf _).takeUntil _) ?_
simp [h.ne]

theorem IsTree.ncard_edgeSet_add_one [Finite V] (hG : G.IsTree) :
G.edgeSet.ncard + 1 = Nat.card V := by
have := Fintype.ofFinite V
have := Fintype.ofFinite G.edgeSet
simpa [edgeFinset] using hG.card_edgeFinset

/-- A minimally connected graph is a tree. -/
lemma isTree_of_minimal_connected (h : Minimal Connected G) : IsTree G := by
rw [isTree_iff, and_iff_right h.prop, isAcyclic_iff_forall_adj_isBridge]
Expand Down Expand Up @@ -466,6 +472,23 @@ lemma Connected.exists_isTree_le (h : G.Connected) : ∃ T ≤ G, IsTree T := by
obtain ⟨F, hF⟩ := G.exists_isAcyclic_reachable_eq_le_of_le_of_isAcyclic bot_le isAcyclic_bot
grind [IsTree, Connected, preconnected_iff_reachable_eq_top]

theorem connected_iff_card_connectedComponent_eq_one :

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 it possible to move this to Connectivity/Connected.lean?

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.

Not without import changes as it doesn't import Nat.card. It is imported in Connectivity/Subgraph.lean and Connectivity/EdgeConnectivity.lean, but they also seem weird.

#40624 will fix the import issues, but no one commented on it yet.

G.Connected ↔ Nat.card G.ConnectedComponent = 1 := by
have : G.ConnectedComponent = Quotient G.reachableSetoid := rfl
simp_rw [connected_iff, preconnected_iff_reachable_eq_top, Nat.card_eq_one_iff_unique, this,
nonempty_quotient_iff, Quotient.subsingleton_iff, reachableSetoid, Setoid.mk_eq_top]

variable (G) in
theorem sum_connectedComponent_ncard_supp [Finite V] [Fintype G.ConnectedComponent] :
∑ c : G.ConnectedComponent, c.supp.ncard = Nat.card V := by
rw [Nat.card_congr G.verticesEquivSigmaConnectedComponent, Nat.card_sigma]
rfl

variable (G) in
theorem sum_connectedComponent_ncard_edgeSet [Finite V] [Fintype G.ConnectedComponent] :
∑ c : G.ConnectedComponent, c.toSimpleGraph.edgeSet.ncard = G.edgeSet.ncard := by
simpa [Nat.card_sigma] using Nat.card_congr G.edgeSetEquivSigmaConnectedComponent.symm

/-- Every connected graph on `n` vertices has at least `n-1` edges. -/
lemma Connected.card_vert_le_card_edgeSet_add_one (h : G.Connected) :
Nat.card V ≤ Nat.card G.edgeSet + 1 := by
Expand All @@ -481,15 +504,41 @@ lemma isTree_iff_connected_and_card [Finite V] :
G.IsTree ↔ G.Connected ∧ Nat.card G.edgeSet + 1 = Nat.card V := by
have := Fintype.ofFinite V
classical
refine ⟨fun h ↦ ⟨h.connected, by simpa [edgeFinset] using h.card_edgeFinset⟩,
fun ⟨h₁, h₂⟩ ↦ ⟨h₁, ?_⟩⟩
refine ⟨fun h ↦ ⟨h.connected, h.ncard_edgeSet_add_one⟩, fun ⟨h₁, h₂⟩ ↦ ⟨h₁, ?_⟩⟩
simp_rw [isAcyclic_iff_forall_adj_isBridge]
refine fun x y h ↦ by_contra fun hbr ↦
(h₁.connected_delete_edge_of_not_isBridge hbr).card_vert_le_card_edgeSet_add_one.not_gt ?_
rw [Nat.card_eq_fintype_card, ← edgeFinset_card, ← h₂, Nat.card_eq_fintype_card,
← edgeFinset_card, add_lt_add_iff_right]
exact Finset.card_lt_card <| by simpa [deleteEdges, edgeFinset]

/-- An acyclic graph on `n` vertices with `c` connected components has exactly `n - c` edges. -/
theorem IsAcyclic.ncard_edgeSet_add_card_connectedComponent [Finite V] (h : G.IsAcyclic) :

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 think the naming is fine, but sometimes while naming we are using the plural connectedComponents such as colorable_iff_forall_connectedComponents, and sometimes not, what do you think is best?

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.

The only uses of the plural seem to be what you mentioned and homOfConnectedComponents. I think colorable_iff_forall_connectedComponents is a typo, and homOfConnectedComponents is probably fine since it's a def.

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.

Good point, fixed in #41648.

G.edgeSet.ncard + Nat.card G.ConnectedComponent = Nat.card V := by
have := Fintype.ofFinite G.ConnectedComponent
rw [← sum_connectedComponent_ncard_edgeSet, ← G.sum_connectedComponent_ncard_supp,
← Fintype.card_eq_nat_card, Fintype.card_eq_sum_ones, ← Finset.sum_add_distrib]
simp_rw [h.isTree_connectedComponent _ |>.ncard_edgeSet_add_one]
rfl

/-- An acyclic graph on `n` vertices has at most `n - 1` edges. -/
theorem IsAcyclic.ncard_edgeSet_add_one_le_card [Finite V] [Nonempty V] (h : G.IsAcyclic) :
G.edgeSet.ncard + 1 ≤ Nat.card V := by
grind [h.ncard_edgeSet_add_card_connectedComponent, Nat.card_pos]

/-- A graph on `n` vertices with at least `n` edges has a cycle. -/
theorem exists_isCycle_of_card_le [Finite V] [Nonempty V]
(h : Nat.card V ≤ G.edgeSet.ncard) : ∃ (v : V) (c : G.Walk v v), c.IsCycle := by
suffices ¬G.IsAcyclic by grind [IsAcyclic]
apply mt IsAcyclic.ncard_edgeSet_add_one_le_card
lia

/-- A graph on `n` vertices is a tree iff it is acyclic and has exactly `n - 1` edges. -/
theorem isTree_iff_isAcyclic_and_ncard_edgeSet_add_one_eq_card [Finite V] :
G.IsTree ↔ G.IsAcyclic ∧ G.edgeSet.ncard + 1 = Nat.card V := by
refine ⟨fun h ↦ ⟨h.isAcyclic, h.ncard_edgeSet_add_one⟩, fun ⟨h, _⟩ ↦ ⟨?_, h⟩⟩
grind [connected_iff_card_connectedComponent_eq_one, h.ncard_edgeSet_add_card_connectedComponent]

/-- The minimum degree of all vertices in a nontrivial tree is one. -/
lemma IsTree.minDegree_eq_one_of_nontrivial (h : G.IsTree) [Fintype V] [Nontrivial V]
[DecidableRel G.Adj] : G.minDegree = 1 := by
Expand Down
13 changes: 13 additions & 0 deletions Mathlib/Combinatorics/SimpleGraph/Connectivity/Connected.lean
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,19 @@ theorem maximal_connected_induce_iff (s : Set V) :

end ConnectedComponent

variable (G) in
/-- The vertices of a graph are partitioned among its connected components. -/
@[simps!]
def verticesEquivSigmaConnectedComponent : V ≃ Σ c : G.ConnectedComponent, c :=
.symm <| .sigmaFiberEquiv G.connectedComponentMk

variable (G) in
/-- The edges of a graph are partitioned among its connected components. -/
@[simps!]
def edgeSetEquivSigmaConnectedComponent :
G.edgeSet ≃ Σ c : G.ConnectedComponent, c.toSimpleGraph.edgeSet :=
.sigmaQuotFromRel G.symm <| .ofLE fun _ _ ↦ Adj.reachable

/-- Given graph homomorphisms from each connected component of `G` to `H`, this is the graph
homomorphism from `G` to `H`. -/
@[simps]
Expand Down
5 changes: 5 additions & 0 deletions Mathlib/Order/RelIso/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ protected def id (r : α → α → Prop) : r →r r :=
protected def comp (g : s →r t) (f : r →r s) : r →r t :=
⟨fun x => g (f x), fun h => g.2 (f.2 h)⟩

/-- The identity relation homomorphism between subrelations. -/
@[simps]
protected def ofLE {r' : α → α → Prop} (le : r ≤ r') : r →r r' :=
⟨id, @le⟩

theorem comp_assoc (h : r →r s) (g : s →r t) (f : t →r u) :
(f.comp g).comp h = f.comp (g.comp h) := rfl

Expand Down
Loading