group_theory.nielsen_schreierMathlib.GroupTheory.FreeGroup.NielsenSchreier

This file has been ported!

Changes since the initial port

The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.

Changes in mathlib3

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(no changes)

(last sync)

Changes in mathlib3port

mathlib3
mathlib3port
Diff
@@ -6,7 +6,7 @@ Authors: David Wärn
 import CategoryTheory.Action
 import Combinatorics.Quiver.Arborescence
 import Combinatorics.Quiver.ConnectedComponent
-import GroupTheory.IsFreeGroup
+import GroupTheory.FreeGroup.IsFreeGroup
 
 #align_import group_theory.nielsen_schreier from "leanprover-community/mathlib"@"2ed2c6310e6f1c5562bdf6bfbda55ebbf6891abe"
 
@@ -202,7 +202,7 @@ def loopOfHom {a b : G} (p : a ⟶ b) : End (root' T) :=
 #align is_free_groupoid.spanning_tree.loop_of_hom IsFreeGroupoid.SpanningTree.loopOfHom
 -/
 
-/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (e «expr ∈ » wide_subquiver_symmetrify[quiver.wide_subquiver_symmetrify] T a b) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:642:2: warning: expanding binder collection (e «expr ∈ » wide_subquiver_symmetrify[quiver.wide_subquiver_symmetrify] T a b) -/
 #print IsFreeGroupoid.SpanningTree.loopOfHom_eq_id /-
 /-- Turning an edge in the spanning tree into a loop gives the indentity loop. -/
 theorem loopOfHom_eq_id {a b : Generators G} (e) (_ : e ∈ wideSubquiverSymmetrify T a b) :
Diff
@@ -309,7 +309,7 @@ theorem path_nonempty_of_hom {G} [Groupoid.{u, u} G] [IsFreeGroupoid G] {a b : G
 /-- Given a connected free groupoid, its generating quiver is rooted-connected. -/
 instance generators_connected (G) [Groupoid.{u, u} G] [IsConnected G] [IsFreeGroupoid G] (r : G) :
     RootedConnected (symgen r) :=
-  ⟨fun b => path_nonempty_of_hom (CategoryTheory.nonempty_hom_of_connected_groupoid r b)⟩
+  ⟨fun b => path_nonempty_of_hom (CategoryTheory.nonempty_hom_of_preconnected_groupoid r b)⟩
 #align is_free_groupoid.generators_connected IsFreeGroupoid.generators_connected
 -/
 
Diff
@@ -239,7 +239,7 @@ def functorOfMonoidHom {X} [Monoid X] (f : End (root' T) →* X) : G ⥤ Categor
     group at the root is freely generated by loops coming from generating arrows
     in the complement of the tree. -/
 def endIsFree : IsFreeGroup (End (root' T)) :=
-  IsFreeGroup.ofUniqueLift ((wideSubquiverEquivSetTotal <| wideSubquiverSymmetrify T)ᶜ : Set _)
+  IsFreeGroup.of_unique_lift ((wideSubquiverEquivSetTotal <| wideSubquiverSymmetrify T)ᶜ : Set _)
     (fun e => loopOfHom T (of e.val.Hom))
     (by
       intro X _ f
@@ -328,7 +328,7 @@ end IsFreeGroupoid
 /-- The Nielsen-Schreier theorem: a subgroup of a free group is free. -/
 instance subgroupIsFreeOfIsFree {G : Type u} [Group G] [IsFreeGroup G] (H : Subgroup G) :
     IsFreeGroup H :=
-  IsFreeGroup.ofMulEquiv (endMulEquivSubgroup H)
+  IsFreeGroup.of_mulEquiv (endMulEquivSubgroup H)
 #align subgroup_is_free_of_is_free subgroupIsFreeOfIsFree
 -/
 
Diff
@@ -3,10 +3,10 @@ Copyright (c) 2021 David Wärn. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: David Wärn
 -/
-import Mathbin.CategoryTheory.Action
-import Mathbin.Combinatorics.Quiver.Arborescence
-import Mathbin.Combinatorics.Quiver.ConnectedComponent
-import Mathbin.GroupTheory.IsFreeGroup
+import CategoryTheory.Action
+import Combinatorics.Quiver.Arborescence
+import Combinatorics.Quiver.ConnectedComponent
+import GroupTheory.IsFreeGroup
 
 #align_import group_theory.nielsen_schreier from "leanprover-community/mathlib"@"2ed2c6310e6f1c5562bdf6bfbda55ebbf6891abe"
 
@@ -202,7 +202,7 @@ def loopOfHom {a b : G} (p : a ⟶ b) : End (root' T) :=
 #align is_free_groupoid.spanning_tree.loop_of_hom IsFreeGroupoid.SpanningTree.loopOfHom
 -/
 
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (e «expr ∈ » wide_subquiver_symmetrify[quiver.wide_subquiver_symmetrify] T a b) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (e «expr ∈ » wide_subquiver_symmetrify[quiver.wide_subquiver_symmetrify] T a b) -/
 #print IsFreeGroupoid.SpanningTree.loopOfHom_eq_id /-
 /-- Turning an edge in the spanning tree into a loop gives the indentity loop. -/
 theorem loopOfHom_eq_id {a b : Generators G} (e) (_ : e ∈ wideSubquiverSymmetrify T a b) :
Diff
@@ -2,17 +2,14 @@
 Copyright (c) 2021 David Wärn. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: David Wärn
-
-! This file was ported from Lean 3 source module group_theory.nielsen_schreier
-! leanprover-community/mathlib commit 2ed2c6310e6f1c5562bdf6bfbda55ebbf6891abe
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathbin.CategoryTheory.Action
 import Mathbin.Combinatorics.Quiver.Arborescence
 import Mathbin.Combinatorics.Quiver.ConnectedComponent
 import Mathbin.GroupTheory.IsFreeGroup
 
+#align_import group_theory.nielsen_schreier from "leanprover-community/mathlib"@"2ed2c6310e6f1c5562bdf6bfbda55ebbf6891abe"
+
 /-!
 # The Nielsen-Schreier theorem
 
@@ -205,7 +202,7 @@ def loopOfHom {a b : G} (p : a ⟶ b) : End (root' T) :=
 #align is_free_groupoid.spanning_tree.loop_of_hom IsFreeGroupoid.SpanningTree.loopOfHom
 -/
 
-/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (e «expr ∈ » wide_subquiver_symmetrify[quiver.wide_subquiver_symmetrify] T a b) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (e «expr ∈ » wide_subquiver_symmetrify[quiver.wide_subquiver_symmetrify] T a b) -/
 #print IsFreeGroupoid.SpanningTree.loopOfHom_eq_id /-
 /-- Turning an edge in the spanning tree into a loop gives the indentity loop. -/
 theorem loopOfHom_eq_id {a b : Generators G} (e) (_ : e ∈ wideSubquiverSymmetrify T a b) :
Diff
@@ -97,6 +97,7 @@ namespace IsFreeGroupoid
 
 attribute [instance] quiver_generators
 
+#print IsFreeGroupoid.ext_functor /-
 /-- Two functors from a free groupoid to a group are equal when they agree on the generating
 quiver. -/
 @[ext]
@@ -106,6 +107,7 @@ theorem ext_functor {G} [Groupoid.{v} G] [IsFreeGroupoid G] {X : Type v} [Group
   let ⟨_, _, u⟩ := @unique_lift G _ _ X _ fun (a b : Generators G) (e : a ⟶ b) => g.map (of e)
   trans (u _ h) (u _ fun _ _ _ => rfl).symm
 #align is_free_groupoid.ext_functor IsFreeGroupoid.ext_functor
+-/
 
 #print IsFreeGroupoid.actionGroupoidIsFree /-
 /-- An action groupoid over a free group is free. More generally, one could show that the groupoid
@@ -325,9 +327,11 @@ instance endIsFreeOfConnectedFree {G} [Groupoid G] [IsConnected G] [IsFreeGroupo
 
 end IsFreeGroupoid
 
+#print subgroupIsFreeOfIsFree /-
 /-- The Nielsen-Schreier theorem: a subgroup of a free group is free. -/
 instance subgroupIsFreeOfIsFree {G : Type u} [Group G] [IsFreeGroup G] (H : Subgroup G) :
     IsFreeGroup H :=
   IsFreeGroup.ofMulEquiv (endMulEquivSubgroup H)
 #align subgroup_is_free_of_is_free subgroupIsFreeOfIsFree
+-/
 
Diff
@@ -203,7 +203,7 @@ def loopOfHom {a b : G} (p : a ⟶ b) : End (root' T) :=
 #align is_free_groupoid.spanning_tree.loop_of_hom IsFreeGroupoid.SpanningTree.loopOfHom
 -/
 
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (e «expr ∈ » wide_subquiver_symmetrify[quiver.wide_subquiver_symmetrify] T a b) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (e «expr ∈ » wide_subquiver_symmetrify[quiver.wide_subquiver_symmetrify] T a b) -/
 #print IsFreeGroupoid.SpanningTree.loopOfHom_eq_id /-
 /-- Turning an edge in the spanning tree into a loop gives the indentity loop. -/
 theorem loopOfHom_eq_id {a b : Generators G} (e) (_ : e ∈ wideSubquiverSymmetrify T a b) :
Diff
@@ -62,7 +62,7 @@ open scoped Classical
 
 universe v u
 
-/- ./././Mathport/Syntax/Translate/Command.lean:229:11: unsupported: unusual advanced open style -/
+/- ./././Mathport/Syntax/Translate/Command.lean:230:11: unsupported: unusual advanced open style -/
 open CategoryTheory CategoryTheory.ActionCategory CategoryTheory.SingleObj Quiver
 
 #print IsFreeGroupoid.Generators /-
Diff
@@ -144,7 +144,7 @@ instance actionGroupoidIsFree {G A : Type u} [Group G] [IsFreeGroup G] [MulActio
         · convert hE _ _ _; rfl
         · rfl
       apply functor.hext
-      · intro ; apply Unit.ext
+      · intro; apply Unit.ext
       · refine' action_category.cases _; intros
         simp only [← this, uncurry_map, curry_apply_left, coe_back, hom_of_pair.val]
 #align is_free_groupoid.action_groupoid_is_free IsFreeGroupoid.actionGroupoidIsFree
@@ -298,7 +298,7 @@ theorem path_nonempty_of_hom {G} [Groupoid.{u, u} G] [IsFreeGroupoid G] {a b : G
   let f : G → X := fun g => FreeGroup.of (weakly_connected_component.mk g)
   let F : G ⥤ CategoryTheory.SingleObj X := single_obj.difference_functor f
   change F.map p = ((CategoryTheory.Functor.const G).obj ()).map p
-  congr ; ext
+  congr; ext
   rw [functor.const_obj_map, id_as_one, difference_functor_map, mul_inv_eq_one]
   apply congr_arg FreeGroup.of
   apply (weakly_connected_component.eq _ _).mpr
Diff
@@ -58,7 +58,7 @@ free group, free groupoid, Nielsen-Schreier
 
 noncomputable section
 
-open Classical
+open scoped Classical
 
 universe v u
 
Diff
@@ -97,12 +97,6 @@ namespace IsFreeGroupoid
 
 attribute [instance] quiver_generators
 
-/- warning: is_free_groupoid.ext_functor -> IsFreeGroupoid.ext_functor is a dubious translation:
-lean 3 declaration is
-  forall {G : Type.{u2}} [_inst_1 : CategoryTheory.Groupoid.{u1, u2} G] [_inst_2 : IsFreeGroupoid.{u1, u2} G _inst_1] {X : Type.{u1}} [_inst_3 : Group.{u1} X] (f : CategoryTheory.Functor.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3)))) (g : CategoryTheory.Functor.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3)))), (forall (a : IsFreeGroupoid.Generators.{u2, u1} G _inst_1) (b : IsFreeGroupoid.Generators.{u2, u1} G _inst_1) (e : Quiver.Hom.{succ u1, u2} (IsFreeGroupoid.Generators.{u2, u1} G _inst_1) (IsFreeGroupoid.quiverGenerators.{u1, u2} G _inst_1 _inst_2) a b), Eq.{succ u1} (Quiver.Hom.{succ u1, 0} (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.CategoryStruct.toQuiver.{u1, 0} (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.Category.toCategoryStruct.{u1, 0} (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3))))) (CategoryTheory.Functor.obj.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3))) f ((fun (this : G) => this) a)) (CategoryTheory.Functor.obj.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3))) f b)) (CategoryTheory.Functor.map.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3))) f ((fun (this : G) => this) a) b (IsFreeGroupoid.of.{u1, u2} G _inst_1 _inst_2 a b e)) (CategoryTheory.Functor.map.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3))) g ((fun (this : G) => this) a) b (IsFreeGroupoid.of.{u1, u2} G _inst_1 _inst_2 a b e))) -> (Eq.{succ (max u1 u2)} (CategoryTheory.Functor.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3)))) f g)
-but is expected to have type
-  forall {G : Type.{u1}} [_inst_1 : CategoryTheory.Groupoid.{u2, u1} G] [_inst_2 : IsFreeGroupoid.{u2, u1} G _inst_1] {X : Type.{u2}} [_inst_3 : Group.{u2} X] (f : CategoryTheory.Functor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3)))) (g : CategoryTheory.Functor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3)))), (forall (a : IsFreeGroupoid.Generators.{u1, u2} G _inst_1) (b : IsFreeGroupoid.Generators.{u1, u2} G _inst_1) (e : Quiver.Hom.{succ u2, u1} (IsFreeGroupoid.Generators.{u1, u2} G _inst_1) (IsFreeGroupoid.quiverGenerators.{u2, u1} G _inst_1 _inst_2) a b), Eq.{succ u2} (Quiver.Hom.{succ u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.CategoryStruct.toQuiver.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.Category.toCategoryStruct.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))))) (Prefunctor.obj.{succ u2, succ u2, u1, 0} G (CategoryTheory.CategoryStruct.toQuiver.{u2, u1} G (CategoryTheory.Category.toCategoryStruct.{u2, u1} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1))) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.CategoryStruct.toQuiver.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.Category.toCategoryStruct.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))))) (CategoryTheory.Functor.toPrefunctor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))) f) ([mdata let_fun:1 (fun (this : G) => this) a])) (Prefunctor.obj.{succ u2, succ u2, u1, 0} G (CategoryTheory.CategoryStruct.toQuiver.{u2, u1} G (CategoryTheory.Category.toCategoryStruct.{u2, u1} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1))) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.CategoryStruct.toQuiver.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.Category.toCategoryStruct.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))))) (CategoryTheory.Functor.toPrefunctor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))) f) b)) (Prefunctor.map.{succ u2, succ u2, u1, 0} G (CategoryTheory.CategoryStruct.toQuiver.{u2, u1} G (CategoryTheory.Category.toCategoryStruct.{u2, u1} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1))) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.CategoryStruct.toQuiver.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.Category.toCategoryStruct.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))))) (CategoryTheory.Functor.toPrefunctor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))) f) ([mdata let_fun:1 (fun (this : G) => this) a]) b (IsFreeGroupoid.of.{u2, u1} G _inst_1 _inst_2 a b e)) (Prefunctor.map.{succ u2, succ u2, u1, 0} G (CategoryTheory.CategoryStruct.toQuiver.{u2, u1} G (CategoryTheory.Category.toCategoryStruct.{u2, u1} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1))) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.CategoryStruct.toQuiver.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.Category.toCategoryStruct.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))))) (CategoryTheory.Functor.toPrefunctor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))) g) ([mdata let_fun:1 (fun (this : G) => this) a]) b (IsFreeGroupoid.of.{u2, u1} G _inst_1 _inst_2 a b e))) -> (Eq.{max (succ u2) (succ u1)} (CategoryTheory.Functor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3)))) f g)
-Case conversion may be inaccurate. Consider using '#align is_free_groupoid.ext_functor IsFreeGroupoid.ext_functorₓ'. -/
 /-- Two functors from a free groupoid to a group are equal when they agree on the generating
 quiver. -/
 @[ext]
@@ -331,12 +325,6 @@ instance endIsFreeOfConnectedFree {G} [Groupoid G] [IsConnected G] [IsFreeGroupo
 
 end IsFreeGroupoid
 
-/- warning: subgroup_is_free_of_is_free -> subgroupIsFreeOfIsFree is a dubious translation:
-lean 3 declaration is
-  forall {G : Type.{u1}} [_inst_1 : Group.{u1} G] [_inst_2 : IsFreeGroup.{u1} G _inst_1] (H : Subgroup.{u1} G _inst_1), IsFreeGroup.{u1} (coeSort.{succ u1, succ (succ u1)} (Subgroup.{u1} G _inst_1) Type.{u1} (SetLike.hasCoeToSort.{u1, u1} (Subgroup.{u1} G _inst_1) G (Subgroup.setLike.{u1} G _inst_1)) H) (Subgroup.toGroup.{u1} G _inst_1 H)
-but is expected to have type
-  forall {G : Type.{u1}} [_inst_1 : Group.{u1} G] [_inst_2 : IsFreeGroup.{u1} G _inst_1] (H : Subgroup.{u1} G _inst_1), IsFreeGroup.{u1} (Subtype.{succ u1} G (fun (x : G) => Membership.mem.{u1, u1} G (Subgroup.{u1} G _inst_1) (SetLike.instMembership.{u1, u1} (Subgroup.{u1} G _inst_1) G (Subgroup.instSetLikeSubgroup.{u1} G _inst_1)) x H)) (Subgroup.toGroup.{u1} G _inst_1 H)
-Case conversion may be inaccurate. Consider using '#align subgroup_is_free_of_is_free subgroupIsFreeOfIsFreeₓ'. -/
 /-- The Nielsen-Schreier theorem: a subgroup of a free group is free. -/
 instance subgroupIsFreeOfIsFree {G : Type u} [Group G] [IsFreeGroup G] (H : Subgroup G) :
     IsFreeGroup H :=
Diff
@@ -147,14 +147,11 @@ instance actionGroupoidIsFree {G A : Type u} [Group G] [IsFreeGroup G] [MulActio
         apply uF'
         intro e
         ext
-        · convert hE _ _ _
-          rfl
+        · convert hE _ _ _; rfl
         · rfl
       apply functor.hext
-      · intro
-        apply Unit.ext
-      · refine' action_category.cases _
-        intros
+      · intro ; apply Unit.ext
+      · refine' action_category.cases _; intros
         simp only [← this, uncurry_map, curry_apply_left, coe_back, hom_of_pair.val]
 #align is_free_groupoid.action_groupoid_is_free IsFreeGroupoid.actionGroupoidIsFree
 -/
@@ -220,8 +217,7 @@ theorem loopOfHom_eq_id {a b : Generators G} (e) (_ : e ∈ wideSubquiverSymmetr
   by
   rw [loop_of_hom, ← category.assoc, is_iso.comp_inv_eq, category.id_comp]
   cases H
-  · rw [tree_hom_eq T (path.cons default ⟨Sum.inl e, H⟩), hom_of_path]
-    rfl
+  · rw [tree_hom_eq T (path.cons default ⟨Sum.inl e, H⟩), hom_of_path]; rfl
   · rw [tree_hom_eq T (path.cons default ⟨Sum.inr e, H⟩), hom_of_path]
     simp only [is_iso.inv_hom_id, category.comp_id, category.assoc, tree_hom]
 #align is_free_groupoid.spanning_tree.loop_of_hom_eq_id IsFreeGroupoid.SpanningTree.loopOfHom_eq_id
@@ -267,15 +263,12 @@ def endIsFree : IsFreeGroup (End (root' T)) :=
         suffices ∀ {a} (p : Path (root' T) a), F'.map (hom_of_path T p) = 1 by
           simp only [this, tree_hom, comp_as_mul, inv_as_inv, loop_of_hom, inv_one, mul_one,
             one_mul, functor.map_inv, functor.map_comp]
-        intro a p
-        induction' p with b c p e ih
+        intro a p; induction' p with b c p e ih
         · rw [hom_of_path, F'.map_id, id_as_one]
         rw [hom_of_path, F'.map_comp, comp_as_mul, ih, mul_one]
         rcases e with ⟨e | e, eT⟩
-        · rw [hF']
-          exact dif_pos (Or.inl eT)
-        · rw [F'.map_inv, inv_as_inv, inv_eq_one, hF']
-          exact dif_pos (Or.inr eT)
+        · rw [hF']; exact dif_pos (Or.inl eT)
+        · rw [F'.map_inv, inv_as_inv, inv_eq_one, hF']; exact dif_pos (Or.inr eT)
       · intro E hE
         ext
         suffices (functor_of_monoid_hom T E).map x = F'.map x by
Diff
@@ -171,7 +171,6 @@ variable {G : Type u} [Groupoid.{u} G] [IsFreeGroupoid G]
 /-- The root of `T`, except its type is `G` instead of the type synonym `T`. -/
 private def root' : G :=
   show T from root T
-#align is_free_groupoid.spanning_tree.root' is_free_groupoid.spanning_tree.root'
 
 #print IsFreeGroupoid.SpanningTree.homOfPath /-
 -- this has to be marked noncomputable, see issue #451.
@@ -298,7 +297,6 @@ end SpanningTree
 private def symgen {G : Type u} [Groupoid.{v} G] [IsFreeGroupoid G] :
     G → Symmetrify (Generators G) :=
   id
-#align is_free_groupoid.symgen is_free_groupoid.symgen
 
 #print IsFreeGroupoid.path_nonempty_of_hom /-
 /-- If there exists a morphism `a → b` in a free groupoid, then there also exists a zigzag
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: David Wärn
 
 ! This file was ported from Lean 3 source module group_theory.nielsen_schreier
-! leanprover-community/mathlib commit 1bda4fc53de6ade5ab9da36f2192e24e2084a2ce
+! leanprover-community/mathlib commit 2ed2c6310e6f1c5562bdf6bfbda55ebbf6891abe
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -16,6 +16,9 @@ import Mathbin.GroupTheory.IsFreeGroup
 /-!
 # The Nielsen-Schreier theorem
 
+> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
+> Any changes to this file require a corresponding PR to mathlib4.
+
 This file proves that a subgroup of a free group is itself free.
 
 ## Main result
Diff
@@ -62,6 +62,7 @@ universe v u
 /- ./././Mathport/Syntax/Translate/Command.lean:229:11: unsupported: unusual advanced open style -/
 open CategoryTheory CategoryTheory.ActionCategory CategoryTheory.SingleObj Quiver
 
+#print IsFreeGroupoid.Generators /-
 /-- `is_free_groupoid.generators G` is a type synonym for `G`. We think of this as
 the vertices of the generating quiver of `G` when `G` is free. We can't use `G` directly,
 since `G` already has a quiver instance from being a groupoid. -/
@@ -69,7 +70,9 @@ since `G` already has a quiver instance from being a groupoid. -/
 def IsFreeGroupoid.Generators (G) [Groupoid G] :=
   G
 #align is_free_groupoid.generators IsFreeGroupoid.Generators
+-/
 
+#print IsFreeGroupoid /-
 /-- A groupoid `G` is free when we have the following data:
  - a quiver on `is_free_groupoid.generators G` (a type synonym for `G`)
  - a function `of` taking a generating arrow to a morphism in `G`
@@ -85,11 +88,18 @@ class IsFreeGroupoid (G) [Groupoid.{v} G] where
     ∀ {X : Type v} [Group X] (f : Labelling (IsFreeGroupoid.Generators G) X),
       ∃! F : G ⥤ CategoryTheory.SingleObj X, ∀ (a b) (g : a ⟶ b), F.map (of g) = f g
 #align is_free_groupoid IsFreeGroupoid
+-/
 
 namespace IsFreeGroupoid
 
 attribute [instance] quiver_generators
 
+/- warning: is_free_groupoid.ext_functor -> IsFreeGroupoid.ext_functor is a dubious translation:
+lean 3 declaration is
+  forall {G : Type.{u2}} [_inst_1 : CategoryTheory.Groupoid.{u1, u2} G] [_inst_2 : IsFreeGroupoid.{u1, u2} G _inst_1] {X : Type.{u1}} [_inst_3 : Group.{u1} X] (f : CategoryTheory.Functor.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3)))) (g : CategoryTheory.Functor.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3)))), (forall (a : IsFreeGroupoid.Generators.{u2, u1} G _inst_1) (b : IsFreeGroupoid.Generators.{u2, u1} G _inst_1) (e : Quiver.Hom.{succ u1, u2} (IsFreeGroupoid.Generators.{u2, u1} G _inst_1) (IsFreeGroupoid.quiverGenerators.{u1, u2} G _inst_1 _inst_2) a b), Eq.{succ u1} (Quiver.Hom.{succ u1, 0} (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.CategoryStruct.toQuiver.{u1, 0} (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.Category.toCategoryStruct.{u1, 0} (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3))))) (CategoryTheory.Functor.obj.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3))) f ((fun (this : G) => this) a)) (CategoryTheory.Functor.obj.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3))) f b)) (CategoryTheory.Functor.map.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3))) f ((fun (this : G) => this) a) b (IsFreeGroupoid.of.{u1, u2} G _inst_1 _inst_2 a b e)) (CategoryTheory.Functor.map.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3))) g ((fun (this : G) => this) a) b (IsFreeGroupoid.of.{u1, u2} G _inst_1 _inst_2 a b e))) -> (Eq.{succ (max u1 u2)} (CategoryTheory.Functor.{u1, u1, u2, 0} G (CategoryTheory.Groupoid.toCategory.{u1, u2} G _inst_1) (CategoryTheory.SingleObj.{u1} X) (CategoryTheory.SingleObj.category.{u1} X (DivInvMonoid.toMonoid.{u1} X (Group.toDivInvMonoid.{u1} X _inst_3)))) f g)
+but is expected to have type
+  forall {G : Type.{u1}} [_inst_1 : CategoryTheory.Groupoid.{u2, u1} G] [_inst_2 : IsFreeGroupoid.{u2, u1} G _inst_1] {X : Type.{u2}} [_inst_3 : Group.{u2} X] (f : CategoryTheory.Functor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3)))) (g : CategoryTheory.Functor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3)))), (forall (a : IsFreeGroupoid.Generators.{u1, u2} G _inst_1) (b : IsFreeGroupoid.Generators.{u1, u2} G _inst_1) (e : Quiver.Hom.{succ u2, u1} (IsFreeGroupoid.Generators.{u1, u2} G _inst_1) (IsFreeGroupoid.quiverGenerators.{u2, u1} G _inst_1 _inst_2) a b), Eq.{succ u2} (Quiver.Hom.{succ u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.CategoryStruct.toQuiver.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.Category.toCategoryStruct.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))))) (Prefunctor.obj.{succ u2, succ u2, u1, 0} G (CategoryTheory.CategoryStruct.toQuiver.{u2, u1} G (CategoryTheory.Category.toCategoryStruct.{u2, u1} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1))) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.CategoryStruct.toQuiver.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.Category.toCategoryStruct.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))))) (CategoryTheory.Functor.toPrefunctor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))) f) ([mdata let_fun:1 (fun (this : G) => this) a])) (Prefunctor.obj.{succ u2, succ u2, u1, 0} G (CategoryTheory.CategoryStruct.toQuiver.{u2, u1} G (CategoryTheory.Category.toCategoryStruct.{u2, u1} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1))) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.CategoryStruct.toQuiver.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.Category.toCategoryStruct.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))))) (CategoryTheory.Functor.toPrefunctor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))) f) b)) (Prefunctor.map.{succ u2, succ u2, u1, 0} G (CategoryTheory.CategoryStruct.toQuiver.{u2, u1} G (CategoryTheory.Category.toCategoryStruct.{u2, u1} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1))) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.CategoryStruct.toQuiver.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.Category.toCategoryStruct.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))))) (CategoryTheory.Functor.toPrefunctor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))) f) ([mdata let_fun:1 (fun (this : G) => this) a]) b (IsFreeGroupoid.of.{u2, u1} G _inst_1 _inst_2 a b e)) (Prefunctor.map.{succ u2, succ u2, u1, 0} G (CategoryTheory.CategoryStruct.toQuiver.{u2, u1} G (CategoryTheory.Category.toCategoryStruct.{u2, u1} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1))) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.CategoryStruct.toQuiver.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.Category.toCategoryStruct.{u2, 0} (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))))) (CategoryTheory.Functor.toPrefunctor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3))) g) ([mdata let_fun:1 (fun (this : G) => this) a]) b (IsFreeGroupoid.of.{u2, u1} G _inst_1 _inst_2 a b e))) -> (Eq.{max (succ u2) (succ u1)} (CategoryTheory.Functor.{u2, u2, u1, 0} G (CategoryTheory.Groupoid.toCategory.{u2, u1} G _inst_1) (CategoryTheory.SingleObj.{u2} X) (CategoryTheory.SingleObj.category.{u2} X (DivInvMonoid.toMonoid.{u2} X (Group.toDivInvMonoid.{u2} X _inst_3)))) f g)
+Case conversion may be inaccurate. Consider using '#align is_free_groupoid.ext_functor IsFreeGroupoid.ext_functorₓ'. -/
 /-- Two functors from a free groupoid to a group are equal when they agree on the generating
 quiver. -/
 @[ext]
@@ -100,6 +110,7 @@ theorem ext_functor {G} [Groupoid.{v} G] [IsFreeGroupoid G] {X : Type v} [Group
   trans (u _ h) (u _ fun _ _ _ => rfl).symm
 #align is_free_groupoid.ext_functor IsFreeGroupoid.ext_functor
 
+#print IsFreeGroupoid.actionGroupoidIsFree /-
 /-- An action groupoid over a free group is free. More generally, one could show that the groupoid
 of elements over a free groupoid is free, but this version is easier to prove and suffices for our
 purposes.
@@ -143,6 +154,7 @@ instance actionGroupoidIsFree {G A : Type u} [Group G] [IsFreeGroup G] [MulActio
         intros
         simp only [← this, uncurry_map, curry_apply_left, coe_back, hom_of_pair.val]
 #align is_free_groupoid.action_groupoid_is_free IsFreeGroupoid.actionGroupoidIsFree
+-/
 
 namespace SpanningTree
 
@@ -158,6 +170,7 @@ private def root' : G :=
   show T from root T
 #align is_free_groupoid.spanning_tree.root' is_free_groupoid.spanning_tree.root'
 
+#print IsFreeGroupoid.SpanningTree.homOfPath /-
 -- this has to be marked noncomputable, see issue #451.
 -- It might be nicer to define this in terms of `compose_path`
 /-- A path in the tree gives a hom, by composition. -/
@@ -165,30 +178,40 @@ noncomputable def homOfPath : ∀ {a : G}, Path (root T) a → (root' T ⟶ a)
   | _, path.nil => 𝟙 _
   | a, path.cons p f => hom_of_path p ≫ Sum.recOn f.val (fun e => of e) fun e => inv (of e)
 #align is_free_groupoid.spanning_tree.hom_of_path IsFreeGroupoid.SpanningTree.homOfPath
+-/
 
+#print IsFreeGroupoid.SpanningTree.treeHom /-
 /-- For every vertex `a`, there is a canonical hom from the root, given by the path in the tree. -/
 def treeHom (a : G) : root' T ⟶ a :=
   homOfPath T default
 #align is_free_groupoid.spanning_tree.tree_hom IsFreeGroupoid.SpanningTree.treeHom
+-/
 
+#print IsFreeGroupoid.SpanningTree.treeHom_eq /-
 /-- Any path to `a` gives `tree_hom T a`, since paths in the tree are unique. -/
 theorem treeHom_eq {a : G} (p : Path (root T) a) : treeHom T a = homOfPath T p := by
   rw [tree_hom, Unique.default_eq]
 #align is_free_groupoid.spanning_tree.tree_hom_eq IsFreeGroupoid.SpanningTree.treeHom_eq
+-/
 
+#print IsFreeGroupoid.SpanningTree.treeHom_root /-
 @[simp]
 theorem treeHom_root : treeHom T (root' T) = 𝟙 _ :=
   -- this should just be `tree_hom_eq T path.nil`, but Lean treats `hom_of_path` with suspicion.
     trans
     (treeHom_eq T Path.nil) rfl
 #align is_free_groupoid.spanning_tree.tree_hom_root IsFreeGroupoid.SpanningTree.treeHom_root
+-/
 
+#print IsFreeGroupoid.SpanningTree.loopOfHom /-
 /-- Any hom in `G` can be made into a loop, by conjugating with `tree_hom`s. -/
 def loopOfHom {a b : G} (p : a ⟶ b) : End (root' T) :=
   treeHom T a ≫ p ≫ inv (treeHom T b)
 #align is_free_groupoid.spanning_tree.loop_of_hom IsFreeGroupoid.SpanningTree.loopOfHom
+-/
 
 /- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (e «expr ∈ » wide_subquiver_symmetrify[quiver.wide_subquiver_symmetrify] T a b) -/
+#print IsFreeGroupoid.SpanningTree.loopOfHom_eq_id /-
 /-- Turning an edge in the spanning tree into a loop gives the indentity loop. -/
 theorem loopOfHom_eq_id {a b : Generators G} (e) (_ : e ∈ wideSubquiverSymmetrify T a b) :
     loopOfHom T (of e) = 𝟙 (root' T) :=
@@ -200,7 +223,9 @@ theorem loopOfHom_eq_id {a b : Generators G} (e) (_ : e ∈ wideSubquiverSymmetr
   · rw [tree_hom_eq T (path.cons default ⟨Sum.inr e, H⟩), hom_of_path]
     simp only [is_iso.inv_hom_id, category.comp_id, category.assoc, tree_hom]
 #align is_free_groupoid.spanning_tree.loop_of_hom_eq_id IsFreeGroupoid.SpanningTree.loopOfHom_eq_id
+-/
 
+#print IsFreeGroupoid.SpanningTree.functorOfMonoidHom /-
 /-- Since a hom gives a loop, any homomorphism from the vertex group at the root
     extends to a functor on the whole groupoid. -/
 @[simps]
@@ -216,7 +241,9 @@ def functorOfMonoidHom {X} [Monoid X] (f : End (root' T) →* X) : G ⥤ Categor
     rw [comp_as_mul, ← f.map_mul]
     simp only [is_iso.inv_hom_id_assoc, loop_of_hom, End.mul_def, category.assoc]
 #align is_free_groupoid.spanning_tree.functor_of_monoid_hom IsFreeGroupoid.SpanningTree.functorOfMonoidHom
+-/
 
+#print IsFreeGroupoid.SpanningTree.endIsFree /-
 /-- Given a free groupoid and an arborescence of its generating quiver, the vertex
     group at the root is freely generated by loops coming from generating arrows
     in the complement of the tree. -/
@@ -260,6 +287,7 @@ def endIsFree : IsFreeGroup (End (root' T)) :=
         · rw [loop_of_hom_eq_id T e h, ← End.one_def, E.map_one]
         · exact hE ⟨⟨a, b, e⟩, h⟩)
 #align is_free_groupoid.spanning_tree.End_is_free IsFreeGroupoid.SpanningTree.endIsFree
+-/
 
 end SpanningTree
 
@@ -269,6 +297,7 @@ private def symgen {G : Type u} [Groupoid.{v} G] [IsFreeGroupoid G] :
   id
 #align is_free_groupoid.symgen is_free_groupoid.symgen
 
+#print IsFreeGroupoid.path_nonempty_of_hom /-
 /-- If there exists a morphism `a → b` in a free groupoid, then there also exists a zigzag
 from `a` to `b` in the generating quiver. -/
 theorem path_nonempty_of_hom {G} [Groupoid.{u, u} G] [IsFreeGroupoid G] {a b : G} :
@@ -287,22 +316,33 @@ theorem path_nonempty_of_hom {G} [Groupoid.{u, u} G] [IsFreeGroupoid G] {a b : G
   apply (weakly_connected_component.eq _ _).mpr
   exact ⟨hom.to_path (Sum.inr e)⟩
 #align is_free_groupoid.path_nonempty_of_hom IsFreeGroupoid.path_nonempty_of_hom
+-/
 
+#print IsFreeGroupoid.generators_connected /-
 /-- Given a connected free groupoid, its generating quiver is rooted-connected. -/
 instance generators_connected (G) [Groupoid.{u, u} G] [IsConnected G] [IsFreeGroupoid G] (r : G) :
     RootedConnected (symgen r) :=
   ⟨fun b => path_nonempty_of_hom (CategoryTheory.nonempty_hom_of_connected_groupoid r b)⟩
 #align is_free_groupoid.generators_connected IsFreeGroupoid.generators_connected
+-/
 
+#print IsFreeGroupoid.endIsFreeOfConnectedFree /-
 /-- A vertex group in a free connected groupoid is free. With some work one could drop the
 connectedness assumption, by looking at connected components. -/
 instance endIsFreeOfConnectedFree {G} [Groupoid G] [IsConnected G] [IsFreeGroupoid G] (r : G) :
     IsFreeGroup (End r) :=
   SpanningTree.endIsFree <| geodesicSubtree (symgen r)
 #align is_free_groupoid.End_is_free_of_connected_free IsFreeGroupoid.endIsFreeOfConnectedFree
+-/
 
 end IsFreeGroupoid
 
+/- warning: subgroup_is_free_of_is_free -> subgroupIsFreeOfIsFree is a dubious translation:
+lean 3 declaration is
+  forall {G : Type.{u1}} [_inst_1 : Group.{u1} G] [_inst_2 : IsFreeGroup.{u1} G _inst_1] (H : Subgroup.{u1} G _inst_1), IsFreeGroup.{u1} (coeSort.{succ u1, succ (succ u1)} (Subgroup.{u1} G _inst_1) Type.{u1} (SetLike.hasCoeToSort.{u1, u1} (Subgroup.{u1} G _inst_1) G (Subgroup.setLike.{u1} G _inst_1)) H) (Subgroup.toGroup.{u1} G _inst_1 H)
+but is expected to have type
+  forall {G : Type.{u1}} [_inst_1 : Group.{u1} G] [_inst_2 : IsFreeGroup.{u1} G _inst_1] (H : Subgroup.{u1} G _inst_1), IsFreeGroup.{u1} (Subtype.{succ u1} G (fun (x : G) => Membership.mem.{u1, u1} G (Subgroup.{u1} G _inst_1) (SetLike.instMembership.{u1, u1} (Subgroup.{u1} G _inst_1) G (Subgroup.instSetLikeSubgroup.{u1} G _inst_1)) x H)) (Subgroup.toGroup.{u1} G _inst_1 H)
+Case conversion may be inaccurate. Consider using '#align subgroup_is_free_of_is_free subgroupIsFreeOfIsFreeₓ'. -/
 /-- The Nielsen-Schreier theorem: a subgroup of a free group is free. -/
 instance subgroupIsFreeOfIsFree {G : Type u} [Group G] [IsFreeGroup G] (H : Subgroup G) :
     IsFreeGroup H :=
Diff
@@ -59,7 +59,7 @@ open Classical
 
 universe v u
 
-/- ./././Mathport/Syntax/Translate/Command.lean:224:11: unsupported: unusual advanced open style -/
+/- ./././Mathport/Syntax/Translate/Command.lean:229:11: unsupported: unusual advanced open style -/
 open CategoryTheory CategoryTheory.ActionCategory CategoryTheory.SingleObj Quiver
 
 /-- `is_free_groupoid.generators G` is a type synonym for `G`. We think of this as
Diff
@@ -235,7 +235,7 @@ def endIsFree : IsFreeGroup (End (root' T)) :=
           rw [functor.map_End_apply, this, hF']
           exact dif_neg h
         intros
-        suffices ∀ {a} (p : path (root' T) a), F'.map (hom_of_path T p) = 1 by
+        suffices ∀ {a} (p : Path (root' T) a), F'.map (hom_of_path T p) = 1 by
           simp only [this, tree_hom, comp_as_mul, inv_as_inv, loop_of_hom, inv_one, mul_one,
             one_mul, functor.map_inv, functor.map_comp]
         intro a p
Diff
@@ -188,7 +188,7 @@ def loopOfHom {a b : G} (p : a ⟶ b) : End (root' T) :=
   treeHom T a ≫ p ≫ inv (treeHom T b)
 #align is_free_groupoid.spanning_tree.loop_of_hom IsFreeGroupoid.SpanningTree.loopOfHom
 
-/- ./././Mathport/Syntax/Translate/Basic.lean:628:2: warning: expanding binder collection (e «expr ∈ » wide_subquiver_symmetrify[quiver.wide_subquiver_symmetrify] T a b) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (e «expr ∈ » wide_subquiver_symmetrify[quiver.wide_subquiver_symmetrify] T a b) -/
 /-- Turning an edge in the spanning tree into a loop gives the indentity loop. -/
 theorem loopOfHom_eq_id {a b : Generators G} (e) (_ : e ∈ wideSubquiverSymmetrify T a b) :
     loopOfHom T (of e) = 𝟙 (root' T) :=
Diff
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: David Wärn
 
 ! This file was ported from Lean 3 source module group_theory.nielsen_schreier
-! leanprover-community/mathlib commit 56adee5b5eef9e734d82272918300fca4f3e7cef
+! leanprover-community/mathlib commit 1bda4fc53de6ade5ab9da36f2192e24e2084a2ce
 ! Please do not edit these lines, except to modify the commit id
 ! if you have ported upstream changes.
 -/
@@ -100,7 +100,7 @@ theorem ext_functor {G} [Groupoid.{v} G] [IsFreeGroupoid G] {X : Type v} [Group
   trans (u _ h) (u _ fun _ _ _ => rfl).symm
 #align is_free_groupoid.ext_functor IsFreeGroupoid.ext_functor
 
-/-- An action groupoid over a free froup is free. More generally, one could show that the groupoid
+/-- An action groupoid over a free group is free. More generally, one could show that the groupoid
 of elements over a free groupoid is free, but this version is easier to prove and suffices for our
 purposes.
 

Changes in mathlib4

mathlib3
mathlib4
chore: classify porting notes referring to missing linters (#12098)

Reference the newly created issues #12094 and #12096, as well as the pre-existing #5171. Change all references to #10927 to #5171. Some of these changes were not labelled as "porting note"; change this for good measure.

Diff
@@ -63,7 +63,7 @@ open CategoryTheory CategoryTheory.ActionCategory CategoryTheory.SingleObj Quive
 /-- `IsFreeGroupoid.Generators G` is a type synonym for `G`. We think of this as
 the vertices of the generating quiver of `G` when `G` is free. We can't use `G` directly,
 since `G` already has a quiver instance from being a groupoid. -/
--- Porting note: @[nolint has_nonempty_instance]
+-- Porting note(#5171): @[nolint has_nonempty_instance]
 @[nolint unusedArguments]
 def IsFreeGroupoid.Generators (G) [Groupoid G] :=
   G
chore: scope open Classical (#11199)

We remove all but one open Classicals, instead preferring to use open scoped Classical. The only real side-effect this led to is moving a couple declarations to use Exists.choose instead of Classical.choose.

The first few commits are explicitly labelled regex replaces for ease of review.

Diff
@@ -52,7 +52,7 @@ free group, free groupoid, Nielsen-Schreier
 
 noncomputable section
 
-open Classical
+open scoped Classical
 
 universe v u
 
chore: generalize theorems from IsConnected to IsPreconnected (#10713)
Diff
@@ -291,7 +291,7 @@ theorem path_nonempty_of_hom {G} [Groupoid.{u, u} G] [IsFreeGroupoid G] {a b : G
 /-- Given a connected free groupoid, its generating quiver is rooted-connected. -/
 instance generators_connected (G) [Groupoid.{u, u} G] [IsConnected G] [IsFreeGroupoid G] (r : G) :
     RootedConnected (symgen r) :=
-  ⟨fun b => path_nonempty_of_hom (CategoryTheory.nonempty_hom_of_connected_groupoid r b)⟩
+  ⟨fun b => path_nonempty_of_hom (CategoryTheory.nonempty_hom_of_preconnected_groupoid r b)⟩
 #align is_free_groupoid.generators_connected IsFreeGroupoid.generators_connected
 
 /-- A vertex group in a free connected groupoid is free. With some work one could drop the
chore(*): rename FunLike to DFunLike (#9785)

This prepares for the introduction of a non-dependent synonym of FunLike, which helps a lot with keeping #8386 readable.

This is entirely search-and-replace in 680197f combined with manual fixes in 4145626, e900597 and b8428f8. The commands that generated this change:

sed -i 's/\bFunLike\b/DFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\btoFunLike\b/toDFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/import Mathlib.Data.DFunLike/import Mathlib.Data.FunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\bHom_FunLike\b/Hom_DFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean     
sed -i 's/\binstFunLike\b/instDFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\bfunLike\b/instDFunLike/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean
sed -i 's/\btoo many metavariables to apply `fun_like.has_coe_to_fun`/too many metavariables to apply `DFunLike.hasCoeToFun`/g' {Archive,Counterexamples,Mathlib,test}/**/*.lean

Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>

Diff
@@ -120,7 +120,7 @@ instance actionGroupoidIsFree {G A : Type u} [Group G] [IsFreeGroup G] [MulActio
     refine' ⟨uncurry F' _, _, _⟩
     · suffices SemidirectProduct.rightHom.comp F' = MonoidHom.id _ by
         -- Porting note: `MonoidHom.ext_iff` has been deprecated.
-        exact FunLike.ext_iff.mp this
+        exact DFunLike.ext_iff.mp this
       apply IsFreeGroup.ext_hom (fun x ↦ ?_)
       rw [MonoidHom.comp_apply, hF']
       rfl
feat: change IsFreeGroup to a Prop (#7698)

Currently, the class IsFreeGroup contains data (namely, a specific set of generators). This is bad, as there are many sets of generators in a free group, and changing sets of generators happens all the time in geometric group theory. We switch to a design in which

  • we define FreeGroupBasis, following the definition and API of bases of vector spaces. Most existing API around IsFreeGroup is transferred to lemmas taking a free group basis as a variable.
  • The typeclass IsFreeGroup is Prop-valued, and requires only the existence of a free group basis.
Diff
@@ -121,7 +121,7 @@ instance actionGroupoidIsFree {G A : Type u} [Group G] [IsFreeGroup G] [MulActio
     · suffices SemidirectProduct.rightHom.comp F' = MonoidHom.id _ by
         -- Porting note: `MonoidHom.ext_iff` has been deprecated.
         exact FunLike.ext_iff.mp this
-      ext
+      apply IsFreeGroup.ext_hom (fun x ↦ ?_)
       rw [MonoidHom.comp_apply, hF']
       rfl
     · rintro ⟨⟨⟩, a : A⟩ ⟨⟨⟩, b⟩ ⟨e, h : IsFreeGroup.of e • a = b⟩
@@ -222,7 +222,7 @@ def functorOfMonoidHom {X} [Monoid X] (f : End (root' T) →* X) : G ⥤ Categor
 /-- Given a free groupoid and an arborescence of its generating quiver, the vertex
     group at the root is freely generated by loops coming from generating arrows
     in the complement of the tree. -/
-def endIsFree : IsFreeGroup (End (root' T)) :=
+lemma endIsFree : IsFreeGroup (End (root' T)) :=
   IsFreeGroup.ofUniqueLift ((wideSubquiverEquivSetTotal <| wideSubquiverSymmetrify T)ᶜ : Set _)
     (fun e => loopOfHom T (of e.val.hom))
     (by
refactor: Create FreeGroup folder in GroupTheory (#7334)
Diff
@@ -6,7 +6,7 @@ Authors: David Wärn
 import Mathlib.CategoryTheory.Action
 import Mathlib.Combinatorics.Quiver.Arborescence
 import Mathlib.Combinatorics.Quiver.ConnectedComponent
-import Mathlib.GroupTheory.IsFreeGroup
+import Mathlib.GroupTheory.FreeGroup.IsFreeGroup
 
 #align_import group_theory.nielsen_schreier from "leanprover-community/mathlib"@"1bda4fc53de6ade5ab9da36f2192e24e2084a2ce"
 
chore: script to replace headers with #align_import statements (#5979)

Open in Gitpod

Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>

Diff
@@ -2,17 +2,14 @@
 Copyright (c) 2021 David Wärn. All rights reserved.
 Released under Apache 2.0 license as described in the file LICENSE.
 Authors: David Wärn
-
-! This file was ported from Lean 3 source module group_theory.nielsen_schreier
-! leanprover-community/mathlib commit 1bda4fc53de6ade5ab9da36f2192e24e2084a2ce
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
 -/
 import Mathlib.CategoryTheory.Action
 import Mathlib.Combinatorics.Quiver.Arborescence
 import Mathlib.Combinatorics.Quiver.ConnectedComponent
 import Mathlib.GroupTheory.IsFreeGroup
 
+#align_import group_theory.nielsen_schreier from "leanprover-community/mathlib"@"1bda4fc53de6ade5ab9da36f2192e24e2084a2ce"
+
 /-!
 # The Nielsen-Schreier theorem
 
chore: remove occurrences of semicolon after space (#5713)

This is the second half of the changes originally in #5699, removing all occurrences of ; after a space and implementing a linter rule to enforce it.

In most cases this 2-character substring has a space after it, so the following command was run first:

find . -type f -name "*.lean" -exec sed -i -E 's/ ; /; /g' {} \;

The remaining cases were few enough in number that they were done manually.

Diff
@@ -284,7 +284,7 @@ theorem path_nonempty_of_hom {G} [Groupoid.{u, u} G] [IsFreeGroupoid G] {a b : G
   let f : G → X := fun g => FreeGroup.of (WeaklyConnectedComponent.mk g)
   let F : G ⥤ CategoryTheory.SingleObj.{u} (X : Type u) := SingleObj.differenceFunctor f
   change (F.map p) = ((@CategoryTheory.Functor.const G _ _ (SingleObj.category X)).obj ()).map p
-  congr ; ext
+  congr; ext
   rw [Functor.const_obj_map, id_as_one, differenceFunctor_map, @mul_inv_eq_one _ _ (f _)]
   apply congr_arg FreeGroup.of
   apply (WeaklyConnectedComponent.eq _ _).mpr
chore: fix many typos (#4535)

Run codespell Mathlib and keep some suggestions.

Diff
@@ -194,7 +194,7 @@ def loopOfHom {a b : G} (p : a ⟶ b) : End (root' T) :=
   treeHom T a ≫ p ≫ inv (treeHom T b)
 #align is_free_groupoid.spanning_tree.loop_of_hom IsFreeGroupoid.SpanningTree.loopOfHom
 
-/-- Turning an edge in the spanning tree into a loop gives the indentity loop. -/
+/-- Turning an edge in the spanning tree into a loop gives the identity loop. -/
 theorem loopOfHom_eq_id {a b : Generators G} (e) (H : e ∈ wideSubquiverSymmetrify T a b) :
     loopOfHom T (of e) = 𝟙 (root' T) := by
   rw [loopOfHom, ← Category.assoc, IsIso.comp_inv_eq, Category.id_comp]
feat: port GroupTheory.NielsenSchreier (#3981)

Dependencies 8 + 388

389 files ported (98.0%)
151504 lines ported (98.0%)
Show graph

The unported dependencies are