Zulip Chat Archive

Stream: Is there code for X?

Topic: Create elements of fundamental group(oid) from paths


Miguel Marco (May 22 2024 at 21:17):

As an exercise, I have been trying to prove Seifert-VanKampen theorem, and got stuck at a point where I need to create elements of the fundamental group from closed paths. I got lost in the abstraction layers behind the FundamentalGroup construction (If i get it correctly, it formed by invertible morphisms in a topological category). But this definition is meant to encapsulate equivalence classes of closed paths.

So, given X : Type [TopologicalSpace X], x : Xand P : Path x x, is there a direct way to get a term of FundamentalGroup x?

Kevin Buzzard (May 22 2024 at 21:20):

Can you go all the way with your question and write a #mwe ?

Miguel Marco (May 22 2024 at 21:24):

I think this reflects the point where I am stuck:

import Mathlib.AlgebraicTopology.FundamentalGroupoid.FundamentalGroup

variable (X : Type) [TopologicalSpace X] (x : X)

def path_to_fundamental_group : Path x x  FundamentalGroup X x := by
  apply?

I just get apply? didn't find any relevant lemmas

Adam Topaz (May 22 2024 at 21:24):

import Mathlib

variable (X : Type*) [TopologicalSpace X]

noncomputable
example {x : X} (γ : Path x x) : FundamentalGroup X x :=
  .fromPath (X := TopCat.of X) <| .mk _ γ

Miguel Marco (May 22 2024 at 21:28):

Thanks... it is a bit confusing for me. What does the (X := TopCat.of X) part do? it changes Xto be a topological category on the fly?

Adam Topaz (May 22 2024 at 21:29):

docs#FundamentalGroup.fromPath expects a term of docs#TopCat and I'm just telling lean to use TopCat.of X explicitly.

Miguel Marco (May 22 2024 at 21:29):

So it would work also without the X := part?

Adam Topaz (May 22 2024 at 21:30):

no

Adam Topaz (May 22 2024 at 21:30):

if you dont want the X := you could do this:

import Mathlib

noncomputable
example (X : TopCat) {x : X} (γ : Path x x) : FundamentalGroup X x :=
  .fromPath <| .mk _ γ

Miguel Marco (May 22 2024 at 21:36):

I am more confused now. Never saw an assigment used as argument before.

So, strictly speaking, the type of the function I want should be Path x x → FundamentalGroup (TopCat.of X) x right?

Adam Topaz (May 22 2024 at 21:37):

yes, this works as well:

import Mathlib

variable (X : Type*) [TopologicalSpace X]

noncomputable
example {x : X} (γ : Path x x) : FundamentalGroup (TopCat.of X) x :=
  .fromPath <| .mk _ γ

Adam Topaz (May 22 2024 at 21:38):

the (X := ...) isn't really an assignment. It's syntax to explicitly specify one of the named variables (X in this case).

Adam Topaz (May 22 2024 at 21:39):

More precisely, this := means something different than the := in, say, def f := 0.

Miguel Marco (May 22 2024 at 21:41):

Oh, I see. So the elaborator understands that FundamentalGroup X x means actually FundamentalGroup (TopCat.of X) x?

Filippo A. E. Nuccio (May 23 2024 at 07:51):

Some part of the library expects "true" topological spaces while some part of it expects objects in the category of topological spaces. Hopefully there is a nice way back-and-forth. Explicitly, you can do

#check FundamentalGroup -- FundamentalGroup.{u} (X : Type u) [TopologicalSpace X] (x : X) : Type u

to see that FundamentalGroup expects a topological space (and a point in it), while

#check FundamentalGroup.fromPath -- FundamentalGroup.fromPath.{u_1} {X : TopCat} {x : ↑X} (p : Homotopic.Quotient x x) : FundamentalGroup (↑X) x

tells you that FundamentalGroup.fromPath expects an object in the category of topological spaces. Given a (X : Type*) [TopologicalSpace X] you can construct an object in the latter by doing TopCat.of X. But the library knows that given an object in this category, there is a coercion to Types creating a type with a topology, i.e a toplogical space:

variable (X : Type*) [TopologicalSpace X]

#check ((TopCat.of X) : Type _) -- ↑(TopCat.of X) : Type u_1

Moreover, lean is clever enough to understand that this "new" topological space is the old one, and in particular their fundamental groups are equal:

variable (x : X)

example : FundamentalGroup X x = FundamentalGroup (TopCat.of X) x := rfl

Back to your example, you can define your function as follows (it is a bit verbose, but I hope it helps understanding what is going on):

noncomputable
def path_to_fundamental_group : Path x x  FundamentalGroup X x := by
  intro p
  let P : Path.Homotopic.Quotient x x := p
  exact @FundamentalGroup.fromPath (TopCat.of X) x P

Filippo A. E. Nuccio (May 23 2024 at 07:52):

What Adam was doing is the very same thing, I have just unravelled the definitions and used tactic mode rather than term mode.

Riccardo Brasca (May 23 2024 at 08:15):

Also, do we have some documentation about the notation .fromPath? I know it works, but TBH I don't know exactly what Lean is doing here (is it just looking for all possible name before the dot and guessing the right one?)

Damiano Testa (May 23 2024 at 08:18):

I think that it uses Type-information to fill in: it knows to expect a FundamentalGroup and tries that. I do not think that it tries something else.

In particular, if the type information is missing, that "anonymous dot-notation" would not work. At least, I think so!

Yaël Dillies (May 23 2024 at 08:19):

Does it not unfold any definitions? Dot notation does that

Riccardo Brasca (May 23 2024 at 08:20):

Ah yes,

import Mathlib

variable (X : Type*) [TopologicalSpace X]

noncomputable
def foo.bar {x : X} (γ : Path x x) : FundamentalGroup X x :=
  .fromPath (X := .of X) <| .mk _ γ

example {x : X} (γ : Path x x) : FundamentalGroup X x :=
  .bar X γ --invalid dotted identifier notation, unknown identifier `CategoryTheory.Aut.bar` from expected type
  --FundamentalGroup X x

Damiano Testa (May 23 2024 at 08:20):

Yaël Dillies said:

Does it not unfold any definitions? Dot notation does that

I am not sure, but I think that "anonymous dot" is stricter than "usual dot".


Last updated: May 02 2025 at 03:31 UTC