Zulip Chat Archive

Stream: maths

Topic: Geometric group theory


Yaël Dillies (Jul 21 2022 at 15:28):

@Georgi Kocharyan, @Rémi Bottinelli, @Laurent Bartholdi, @Jim Fowler, let's coordinate in this thread.

Yaël Dillies (Jul 21 2022 at 15:29):

I just refactored marked groups to be type synonyms (rather than classes). I am now copying over Georgi's material and adapting it to the new paradigm.

Rémi Bottinelli (Jul 21 2022 at 15:57):

Wow, that's contentful!
Personally, I'd like to try and cover the ends of graphs first, and use that as a stepping stone for the ends of groups hopefully; and Bass-Serre at some point in the near future.
Other than that I'd be happy to collaborate on whatever should come first, but there is some (a lot of) getting up to speed for me I see (even more so after seeing your transformation up there!).

[Re ends of graphs: I have some code here but it's very messy and I have a feeling it's not headed in the right direction; I'd welcome some coaching on the coding side!]

(I'm heading off for today)

Heather Macbeth (Jul 21 2022 at 16:01):

Link to other threads:

https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/Word.20metric.20on.20group.20--.20a.20new.20attempt

https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/Geometric.20Group.20Theory.20coordination.20.3F

Yaël Dillies (Jul 21 2022 at 18:36):

#15594 for group seminorms.

Rémi Bottinelli (Jul 22 2022 at 06:19):

Is it all-right if I bring my file on nets and separated subsets here?

Yaël Dillies (Jul 22 2022 at 07:59):

Please do!

Rémi Bottinelli (Jul 22 2022 at 11:56):

Done. The theorem therein might be useful when/if one wants to show that from a quasi-isometry one can get a bilipschitz bijection between nets contained in the spaces.

Rémi Bottinelli (Jul 22 2022 at 12:01):

By the way, about quasi-isometries: Is it worth it to also define coarsely Lipschitz maps and closeness for two maps into a metric space and have equivalence between all possible notions of equivalences, or should one stick to only talking about quasi-isometries for now?
One definition I liked was: X and Y are QI if there exists a pair f:X ->Y, g:Y->X, both coarsely Lipschitz, and such that both f o g and g o f are close to the identity.

here I've got stuff about close maps and coarse Lipschitz maps.

Rémi Bottinelli (Jul 23 2022 at 11:11):

Would it make sense to set up some variation of a roadmap.txt file with a list of goals and subgoals and who is working on what?

Anand Rao (Jul 23 2022 at 11:37):

I have been following this and related threads for a while and would also like to contribute to building geometric group theory in mathlib. I have a nearly complete proof of the fact that the Cayley graph is connected (modulo two very easy sorrys), and I would like to push the changes to the geometric-group-theory branch. Can I please have write access to the non-master branches of mathlib? My GitHub username is 0art0. Thanks!

Kevin Buzzard (Jul 23 2022 at 11:57):

@maintainers

Markus Himmel (Jul 23 2022 at 11:59):

@Anand Rao I sent you an invitation

Anand Rao (Jul 23 2022 at 12:11):

Got it, thanks. I have pushed my code.

Rémi Bottinelli (Jul 23 2022 at 12:40):

I've been trying to make some progress on my code for ends of graphs, and am getting sort of lost starting from here.
The point is that I want to show that given any finite set of vertices and infinite connected component outside this set, I can define an end that corresponds to this component. My problem is that I have to do some transports along equalities for it to make sense, and I feel like I'm not going in the right direction.

For instance, the definition extend_along_fam seems quite complicated, and the lemma extend_along_const needs transport even just to get correctly stated.
I believe I'm missing some theoretical/technical aspect here.

Any idea on how I should proceed to make sense of this all? I'd welcome some structuring insights too!

Kyle Miller (Jul 23 2022 at 17:28):

I'm not sure it would simplify anything, but I thought I'd mention we now have docs#simple_graph.subgraph.delete_verts so you can define

def simple_graph.connected_outside (G : simple_graph V) (s : set V) : Prop :=
(( : G.subgraph).delete_verts s).coe.connected

and if you have s : finset V you can write G.connected_outside s. (This definition means "G as a subgraph itself, once you delete the vertices from s, it is connected.")

Kyle Miller (Jul 23 2022 at 17:33):

For ends of graphs, I imagined that one might take the poset of finite sets, which is closed under intersections, then define an inverse system over finite sets s of the types ((⊤ : G.subgraph).delete_verts s).coe.connected_component. The limit of this inverse system consists of the ends.

We have a theorem that if these types are always finite and nonempty then this limit is nonempty too (docs#nonempty_sections_of_fintype_inverse_system) so in that case you'd have the graph has at least one end.

I'm not sure how good this definition of ends would be to work with, but it at least wouldn't be too much work to set up. (Modulo some missing API around delete_verts and connected_component.)

Rémi Bottinelli (Jul 24 2022 at 04:32):

Thanks! I'm wary of swapping out my constructions for the alternatives you provided though since as of now, my definitions do sort of work… but yeah, the inverse system theorem is a nice tool.

Rémi Bottinelli (Jul 24 2022 at 07:02):

Would you go with something like this ?

import data.set.finite
import data.sym.sym2
import combinatorics.simple_graph.basic
import combinatorics.simple_graph.connectivity
import topology.metric_space.basic
import data.setoid.partition
import category_theory.functor.basic

open function
open finset
open set
open classical
open simple_graph.walk
open relation

universes u v w



noncomputable theory

--local attribute [instance] prop_decidable

namespace simple_graph


variables  {V : Type u}
           (G : simple_graph V)

section ends

def conn_comp_outside (s : finset V) : Type u :=
(( : G.subgraph).delete_verts s).coe.connected_component

lemma conn_comp_outside.finite [locally_finite G] [preconnected G] (s : finset V) :
  fintype (conn_comp_outside G s) := sorry

lemma conn_comp_outside.nonempty  [locally_finite G] [preconnected G] (Ginf : (@set.univ V).infinite) (s : finset V) :
  nonempty (conn_comp_outside G s) := sorry

def conn_comp_outside.to_set (s : finset V) (c : conn_comp_outside G s) : set V :=
  { v : V |  (p:v  s), (( : G.subgraph).delete_verts s).coe.connected_component_mk (⟨v,by {simp,exact p}⟩) = c }

lemma conn_comp_outside_back_unique {s t : finset V} (h : s  t) :
 c : conn_comp_outside G t,
  ∃! d : conn_comp_outside G s,
    (conn_comp_outside.to_set G t c)  (conn_comp_outside.to_set G s d) := sorry

def conn_comp_outside_back {s t : finset V} (h : s  t) (c : conn_comp_outside G t) : conn_comp_outside G s :=
  classical.some (exists_of_exists_unique (conn_comp_outside_back_unique G h c))

def conn_comp_outside_back.iff {s t : finset V} (h : s  t) (c : conn_comp_outside G t) (d : conn_comp_outside G s):
  conn_comp_outside_back G h c = d  (conn_comp_outside.to_set G t c)  (conn_comp_outside.to_set G s d) :=
begin
  split,
  { rintro equ, induction equ, exact (exists_of_exists_unique (conn_comp_outside_back_unique G h c)).some_spec},
  { exact unique_of_exists_unique (conn_comp_outside_back_unique G h c) (exists_of_exists_unique (conn_comp_outside_back_unique G h c)).some_spec},
end

lemma conn_comp_outside_back.refl (s : finset V) (c : conn_comp_outside G s) :
  conn_comp_outside_back G (finset.subset.refl s) c = c :=
unique_of_exists_unique
  (conn_comp_outside_back_unique G (finset.subset.refl s) c)
  (classical.some_spec (exists_of_exists_unique (conn_comp_outside_back_unique G (finset.subset.refl s) c)))
  (set.subset.refl (conn_comp_outside.to_set G s c))

lemma conn_comp_outside_back.comm  {r s t : finset V} (k : r  s) (h : s  t) (c : conn_comp_outside G t) :
  conn_comp_outside_back G k (conn_comp_outside_back G h c) = conn_comp_outside_back G (k.trans h) c :=
unique_of_exists_unique
  (conn_comp_outside_back_unique G (k.trans h) c)
  ((exists_of_exists_unique (conn_comp_outside_back_unique G h c)).some_spec.trans
     (exists_of_exists_unique (conn_comp_outside_back_unique G k (conn_comp_outside_back G h c))).some_spec)
  (classical.some_spec (exists_of_exists_unique (conn_comp_outside_back_unique G (k.trans h) c)))


-- def ends_system := category_theory.functor.mk (conn_comp_outside G) (conn_comp_outside_back G)


end ends

end simple_graph

Rémi Bottinelli (Jul 24 2022 at 07:10):

mmh, or I might as well take a hybrid approach: sticking with my version of connected components, but then using the inverse systems machinery…

Rémi Bottinelli (Jul 24 2022 at 07:12):

@Kyle Miller Do we have lemmas stating that the sections of your functor over an inverse system are in bijection with the sections over a suitably cofinite subsystem?

Rémi Bottinelli (Jul 24 2022 at 11:17):

Well, after cleaning up my code a bit here I think I'll stay with the elementary approach I took until now. I'll leave the surjectivity of ends onto connected components alone while I try to attack Hopf-Freudenthal and come back to it afterwards, hopefully with a clearer mind. The inverse system approach is probably better all things compared, but in the end you still have to deal with pretty much the same things, and my elementary approach is easier for me still.

Georgi Kocharyan (Jul 24 2022 at 13:10):

I asked in another thread but would I be able to get writing access on the branch? I have a bunch of stuff on svarcmilnor i'd like to push! my github is GregorSamsa42

Kevin Buzzard (Jul 24 2022 at 13:52):

@maintainers

Bryan Gin-ge Chen (Jul 24 2022 at 14:10):

Invite sent! https://github.com/leanprover-community/mathlib/invitations

Kyle Miller (Jul 24 2022 at 15:44):

Rémi Bottinelli said:

Kyle Miller Do we have lemmas stating that the sections of your functor over an inverse system are in bijection with the sections over a suitably cofinite subsystem?

I haven't seen that in mathlib, and I presume it doesn't exist yet (but maybe I just haven't found it).

It's fine continuing with an elementary approach to get a better understanding of formalization issues -- that limit nonemptiness lemma started out that way as a first project, until it eventually morphed into a specialization of a statement about cofiltered limits of nonempty compact hausdorff spaces.

Anand Rao (Jul 25 2022 at 12:59):

@Rémi Bottinelli I think the following strategy (inspired heavily by the equivalence of different characterisations of ends described on Wikipedia) may work for getting a lower bound on the number of ends:

  • To show that the number of ends of an infinite graph is bounded below by the number of infinite connected components, it suffices to show that every infinite connected graph GG has at least one end.
  • Since "infinite" is defined as "not finite" in mathlib, it should be fairly easy to show the existence of arbitrarily large paths in the graph GG. Consequently, it should be possible to show the existence of a ray RR (i.e., a semi-infinite path, which can be described concretely as an embedding of N\mathbb{N}, considered as a graph, into GG).
  • To finally construct the end, we define its value on a finite set of vertices KK to be the unique connected component of G\KG \backslash K containing infinitely many vertices of RR.
  • More concretely, the set {n:NR(n)K}\{n : \mathbb{N} \vert R(n) \in K\} is finite, and has an upper bound mm. The value of the end of KK can be defined to be the connected component of R(m+1)R(m+1). It can be proved as a theorem that the ray R(n):=R((m+1)+n)R'(n) := R((m + 1) + n) is contained entirely within this connected component.

Rémi Bottinelli (Jul 25 2022 at 13:49):

Mmh, I was aiming for an adaptation of the proof in the stacks project here to my specific case.
The problem I foresee with the infinite ray approach is that it's not so immediate to construct the equivalence between ends as equivalence classes of rays and as limits.

Anand Rao (Jul 25 2022 at 14:27):

The proof I outlined actually uses the definition of ends described in your code - as a function that takes in a finite set KK of the graph and returns a connected component of G\KG \backslash K and satisfying the consistency condition on subsets (I should have mentioned this earlier).

The definition of ends as equivalence classes of rays is not necessary here, and only the existence of a single ray in an infinite connected graph is required.

The inverse limit approach is fine too, and I may also contribute to the proof.

Rémi Bottinelli (Jul 25 2022 at 14:32):

That's good to hear!

Rémi Bottinelli (Jul 25 2022 at 14:35):

I've worked some more, and have a rough outline of the proof of Hopf-Freudenthal.

There are now plenty of missing pieces:

  • The surjectivity of the eval map is the big one.
  • The fact that taking a finite set of vertices, one can extend it so that it is both connected, and all connected components outside of this finite set are infinite. (that's used in one of the preliminary lemmas towards Hopf-Freudenthal)
  • The fact that applying an automorphism sends connected components to connected components, etc (should be easy with enough simple_graph-fu).
  • Lots of small things for which I'm not good enough with lean to figure out efficiently.

But all in all, I think I'm getting to something viable.
The next step is probably to sort of clean up the structure a bit, reorganize as necessary, and then fill out the sorrys.
@Anand Rao: What do you think of that plan?

(I'm heading off for today!)

Anand Rao (Jul 25 2022 at 14:47):

Sounds good! I will try to familiarise myself with the code a bit more soon. I will start with some of the easier sorrys.

Rémi Bottinelli (Jul 26 2022 at 08:47):

@Kyle Miller I have a few questions about simple_graph if I may:

First, would the following lemmas fit in the api:

lemma walk.mem_support_iff_exists_append  {V : Type u} {G : simple_graph V} {u v w : V} {p : G.walk u v} :
  w  p.support   (q : G.walk u w) (r : G.walk w v), p = q.append r := sorry

lemma walk.support_append_subset_left {V : Type u} {G : simple_graph V} {u v w : V} (p : G.walk u v) (q : G.walk v w) :
  p.support  (p.append q).support := by simp only [walk.support_append,list.subset_append_left]

lemma walk.support_append_subset_right {V : Type u} {G : simple_graph V} {u v w : V} (p : G.walk u v) (q : G.walk v w) :
  q.support  (p.append q).support := by {
    rw walk.support_append,
    induction q,
    {simp only [support_nil, list.tail_cons, list.append_nil, list.cons_subset, end_mem_support, list.nil_subset, and_self],},
    {simp only [support_cons, list.tail_cons, list.cons_subset, list.mem_append, end_mem_support, true_or, list.subset_append_right,and_self],},
  }

Second, is there a nice way to deal with walks and their images via an automorphism and such?
Finally, is there something like lemma {V : Type *} {G : simple_graph V} [locally_finite G] [preconnected G] (v : V) (n : nat) : (ball v n).finite := sorry ?

Kyle Miller (Jul 26 2022 at 09:04):

@Rémi Bottinelli Yes, these would be nice to have. The first one seems like it might be more convenient in many cases than using take_until and drop_until manually.

-- right after `walk.take_spec`?
lemma walk.mem_support_iff_exists_append {V : Type u} {G : simple_graph V} {u v w : V} {p : G.walk u v} :
  w  p.support   (q : G.walk u w) (r : G.walk w v), p = q.append r :=
begin
  classical,
  split,
  { exact λ h, _, _, (p.take_spec h).symm },
  { rintro q, r, rfl⟩,
    simp, },
end

-- right after `walk.mem_support_append_iff`?

lemma walk.subset_support_append_left {V : Type u} {G : simple_graph V} {u v w : V} (p : G.walk u v) (q : G.walk v w) :
  p.support  (p.append q).support :=
by simp [walk.support_append, list.subset_append_left]

lemma walk.subset_support_append_right {V : Type u} {G : simple_graph V} {u v w : V} (p : G.walk u v) (q : G.walk v w) :
  q.support  (p.append q).support :=
by { intro h, simp { contextual := tt } }

Rémi Bottinelli (Jul 26 2022 at 09:07):

Shall I just copy, insert, and do a PR?

Kyle Miller (Jul 26 2022 at 09:38):

@Rémi Bottinelli The function for mapping walks over a graph equivalence has some dependent type complexity, and I'm not really sure the best way to deal with it. Here's most of one possibility:

protected def equiv (f : G g G') {u v : V} : G.walk u v  G'.walk (f u) (f v) :=
{ to_fun := walk.map (f : G g G'),
  inv_fun := λ p, by { convert p.map (f.symm : G' g G); simp },
  left_inv := begin
    intro p,
    induction p with _ _ _ _ _ _ ih,
    { simp,
      have :  {a b} {h : a = b}, cast (by rw h) (nil : G.walk a a) = (nil : G.walk b b),
      { rintros _ _ rfl, refl, },
      apply this,
      simp, },
    { simp, simp at ih,
      have :  {a a' b b' c c'} (ha : a = a') (hb : b = b') (hc : c = c')
        {he : G.adj a b} {p : G.walk b c},
        cast (by rw [ha, hc]) (cons he p)
          = cons (cast (by rw [ha, hb]) he : G.adj a' b') (cast (by rw [hb, hc]) p : G.walk b' c'),
      { rintros _ _ _ _ _ _ rfl rfl rfl _ _, refl },
      rw this,
      { congr' },
      all_goals { simp }, },
  end,
  right_inv := begin
    sorry
  end }

Kyle Miller (Jul 26 2022 at 09:41):

Rémi Bottinelli said:

Finally, is there something like lemma {V : Type *} {G : simple_graph V} [locally_finite G] [preconnected G] (v : V) (n : nat) : (ball v n).finite := sorry ?

The "walks of a given length" section of simple_graph/connectivity could be generalized to this situation. I think you can drop the preconnected assumption.

Rémi Bottinelli (Jul 26 2022 at 09:44):

Ah, yeah, right, I was thinking of something else for the preconnected assumption: namely that in this case the graph is countable.

Rémi Bottinelli (Jul 26 2022 at 09:45):

Could elaborate on the use of contextual := tt ? The docs aren't very helpful as far as I could find.

Kyle Miller (Jul 26 2022 at 09:46):

There's a little bit at https://leanprover-community.github.io/extras/simp.html

When it simplifies a -> b, it simplifies b with a added as a simp lemma.

Rémi Bottinelli (Jul 26 2022 at 09:50):

Thanks, I'm sort of mystified that you made the append_right version shorter than the append_left one, given that it's not as direct as far as I understood.

Kyle Miller (Jul 26 2022 at 09:52):

Here's a locally finite version:

variables (G) [locally_finite G] [decidable_rel G.adj] [decidable_eq V]

/-- The `finset` of length-`n` walks from `u` to `v`.
This is used to give `{p : G.walk u v | p.length = n}` a `fintype` instance, and it
can also be useful as a recursive description of this set when `V` is finite.

See `simple_graph.coe_finset_walk_length_eq` for the relationship between this `finset` and
the set of length-`n` walks. -/
def finset_walk_length : Π (n : ) (u v : V), finset (G.walk u v)
| 0 u v := if h : u = v
           then by { subst u, exact {walk.nil} }
           else 
| (n+1) u v := (G.neighbor_finset u).attach.bUnion (λ (w : G.neighbor_finset u),
                  have h : G.adj u w := by simpa using w.2,
                  (finset_walk_length n w v).map λ p, walk.cons h p, λ p q, by simp⟩)

lemma coe_finset_walk_length_eq (n : ) (u v : V) :
  (G.finset_walk_length n u v : set (G.walk u v)) = {p : G.walk u v | p.length = n} :=
begin
  induction n with n ih generalizing u v,
  { obtain rfl | huv := eq_or_ne u v;
    simp [finset_walk_length, set_walk_length_zero_eq_of_ne, *], },
  { simp only [finset_walk_length, set_walk_length_succ_eq,
      finset.coe_bUnion, finset.mem_coe, finset.mem_univ, set.Union_true],
    ext p,
    simp only [set.mem_Union, finset.mem_coe, set.mem_image, set.mem_set_of_eq],
    simp only [mem_neighbor_finset, finset.mem_attach, finset.mem_map, embedding.coe_fn_mk, exists_prop, exists_true_left,
  subtype.exists],
    dsimp,
    congr',
    ext w,
    congr',
    ext huw,
    congr',
    ext p',
    simp only [set.ext_iff, finset.mem_coe, set.mem_set_of_eq] at ih,
    simp [ih],
    rintro rfl,
    refl, },
end

Kyle Miller (Jul 26 2022 at 09:53):

The proof of coe_finset_walk_length_eq isn't pretty -- I was just trying to get it to work quickly

Kyle Miller (Jul 26 2022 at 09:54):

If you wanted to PR this sort of generalization (with a nicer proof), that'd be great! If not, I'll get around to it at some point.

Kyle Miller (Jul 26 2022 at 09:56):

Rémi Bottinelli said:

I'm sort of mystified that you made the append_right version shorter than the append_left one

You can actually use the append_right proof for append_left too, but I left it since your proof was a simp only. It's too bad that walk.support_append has that asymmetry...

Rémi Bottinelli (Jul 26 2022 at 09:58):

right, I originally planned it by way of enough reverses, but it felt ugly.

Rémi Bottinelli (Jul 26 2022 at 10:04):

As for contributing to the ball and other lemmas, I hope to do at some point. But I also would like to sort of stay focused on my ends code for now, and every little things takes lots of time still, so it may not be so soon.

Rémi Bottinelli (Jul 26 2022 at 10:05):

PR here: https://github.com/leanprover-community/mathlib/pull/15687

Rémi Bottinelli (Jul 26 2022 at 10:09):

I made your simp into simp only since I believe it's what should be done but maybe I was mistaken. I also made the two subset lemmas into @[simp].

Rémi Bottinelli (Jul 26 2022 at 10:21):

huh, I don't understand why the bulid fails :(

Kyle Miller (Jul 26 2022 at 10:25):

@Rémi Bottinelli Here's the finite ball. It's intended to go right after fintype_set_walk_length.

def ball_finset : Π (n : ) (u : V), finset V
| 0 u := {u}
| (n+1) u := {u}  (G.neighbor_finset u).bUnion (λ w, ball_finset n w)

lemma coe_ball_finset_eq (n : ) (u : V) :
  (G.ball_finset n u : set V) = {v : V |  (p : G.walk u v), p.length  n} :=
begin
  induction n with n ih generalizing u,
  { simp [ball_finset], },
  { ext v,
    simp [ball_finset],
    split,
    { rintro (rfl | h),
      { use walk.nil,
        simp, },
      { obtain w, huw, h := h,
        have := congr_arg (λ (s : set V), v  s) (ih w),
        simp [h] at this,
        obtain p, h := this,
        use [walk.cons huw p],
        simp [h, nat.succ_eq_add_one], } },
    { rintro p, h⟩,
      cases p,
      { simp },
      { right,
        use [p_v, p_h],
        have := congr_arg (λ (s : set V), v  s) (ih p_v),
        simp at this,
        rw this,
        use p_p,
        simpa [nat.succ_eq_add_one] using h, } } },
end

def ball {V : Type u} (G : simple_graph V) [locally_finite G] (u : V) (n : ) : set V :=
{v : V |  (p : G.walk u v), p.length  n}

lemma ball_finite {V : Type u} {G : simple_graph V} [locally_finite G]
  (u : V) (n : ) : (G.ball u n).finite :=
begin
  classical,
  rw [ball,  coe_ball_finset_eq],
  apply set.to_finite,
end

Kyle Miller (Jul 26 2022 at 10:28):

Rémi Bottinelli said:

huh, I don't understand why the bulid fails :(

I just retriggered the linting job. Sometimes things fail for no discernible reason.

Kyle Miller (Jul 26 2022 at 10:31):

It might be easier to prove that set is finite by induction on n more directly than by going through finsets. The algorithm I wrote for ball_finset is really bad -- it doesn't need to be exponential like that -- so it's not useful having that as a computable definition.

Rémi Bottinelli (Jul 26 2022 at 10:36):

and it might make sense to use the induced metric directly, so that the balls really are the metric ball, I guess?

Kyle Miller (Jul 26 2022 at 10:46):

Ah, that's where connected comes in, for simple_graph.dist to be meaningful here.

Yaël Dillies (Jul 26 2022 at 23:56):

I just opened #15705 for multiplicative normed groups.

Rémi Bottinelli (Jul 27 2022 at 04:53):

@Kyle Miller thanks for correcting the PR :) Can you tell me how you knew what made the linter unhappy ? I ran scripts/lint-style.sh but that didn't spot anything iirc.

Kyle Miller (Jul 27 2022 at 05:13):

Once the linter finally ran, it gave some error messages that you can see inline in the code view on GitHub. It's derived from this output: https://github.com/leanprover-community/mathlib/runs/7518225899?check_suite_focus=true

/- The `dup_namespace` linter reports: -/
/- DUPLICATED NAMESPACES IN NAME: -/
-- combinatorics/simple_graph/connectivity.lean
#check @simple_graph.walk.walk.subset_support_append_left /- The namespace `walk` is duplicated in the name -/
Error: simple_graph.walk.walk.subset_support_append_left - The namespace `walk` is duplicated in the name
... etc. ...

Rémi Bottinelli (Jul 27 2022 at 05:15):

Ah, thanks, I tried to see the output on the first run but somehow it seemed to be empty. Is there a way to do it locally?

Alex J. Best (Jul 27 2022 at 13:11):

You can add #lint to the end of every file you touch to see the output, make sure you remove it before committing though!

Georgi Kocharyan (Jul 27 2022 at 14:31):

My proof of svarc-milnor is now (virtually) complete, along with an example that proves Z quasi-isometric to R.
It relies on a few easy lemmas about marked_group which i've added to the file now (I think most should be one liners, but my knowledge doesn't suffice).
If anyone is bored you're welcome to have a look at them :)

Rémi Bottinelli (Jul 28 2022 at 10:27):

We're making some progress on the Freundenthal-Hopf theorem, but have some trouble dealing with instances/typeclasses, as typically shown here. How should I proceed to assume throughout (without the need to reference it explicitely) that my graph is locally finite and preconnected?
In the same vein, under the hypotheses, I would like to assume everywhere that a specific set is finite (as shown here but the instance doesn't "take", it seems.

Yaël Dillies (Jul 28 2022 at 10:43):

Are you writing instances that depend on a locally_finite assumption? If not, I would stick with passing it around explicitly.

Rémi Bottinelli (Jul 28 2022 at 10:46):

I am, yeah: I need locally_finite G to say that removing a finite set of vertices yield a finite number of connected components.

Rémi Bottinelli (Jul 28 2022 at 10:47):

That's the type inf_ro_components G K. I'd like to have [fintype (inf_ro_components G K)] everywhere (well, once I actually prove it).

Yaël Dillies (Jul 28 2022 at 10:47):

Yes but again do you need to go through typeclass inference for this?

Rémi Bottinelli (Jul 28 2022 at 10:50):

Mmh, I admit I don't understand the question: I'm not sure what typeclass inference is. Maybe it's time to look at the docs instead of blindly swapping out () for [] and see what sticks

Yaël Dillies (Jul 28 2022 at 10:53):

Basically you shouldn't treat TC inference as a big theorem bookkeeper. Instead (at least for Prop-valued stuff), it should be used for assumptions that are derived structurally (typically, p ∧ q ∨ r will be decidable because p, q, r is).

Rémi Bottinelli (Jul 28 2022 at 10:57):

Mmh, I see, and what's the rationale for this? "structurally derived" theorems are easier for lean to understand/bookkeep?

Yaël Dillies (Jul 28 2022 at 11:23):

TC inference is not meant to nor can be used as a SMT solver.

Rémi Bottinelli (Jul 28 2022 at 11:24):

Alright, thanks! I'll try and look at the docs in a bit more depth.

Rémi Bottinelli (Jul 28 2022 at 13:53):

Isn't gen_norm_le_one in marked_group wrong for exactly the reason @Laurent Bartholdi mentionned above: a generator might be mapped to the identity ?

Kyle Miller (Jul 28 2022 at 15:40):

For what it's worth, my motivation for slipping in locally_finite was to support different limiting arguments on subgraphs, for instance defining ends of graphs or lifting properties about finite graphs to infinite graphs (like how you can lift the 4-color theorem of finite planar graphs to infinite planar graphs).

Generally you'd be looking at the instances [locally_finite G] giving [locally_finite (G.delete_verts s)] or [locally_finite (G.induce s)] (or however those graphs are written), and you won't be doing any algebraic manipulation of G itself -- it's being used more like a type than a term, so to speak.

That's not to say I knew what I was doing back when I slipped it in, but given what I've learned in the meantime I think locally_finiteinstances are still justifiable for this application.

Rémi Bottinelli (Jul 28 2022 at 15:45):

Actually, locally_finite is not the worst offender here (lean seems to like it being an instance well enough), but preconnected G and the diverse fintype X are.

Junyan Xu (Jul 28 2022 at 23:45):

Kyle Miller said:

Rémi Bottinelli The function for mapping walks over a graph equivalence has some dependent type complexity, and I'm not really sure the best way to deal with it. Here's most of one possibility:

I've made a definitionally better version of the walk equiv but unfortunately it requires a re-definition of simple_graph.walk:

import combinatorics.simple_graph.basic

universes u v
namespace simple_graph
variables {V : Type u} {V' : Type v} {G : simple_graph V} {G' : simple_graph V'}

inductive walk (G : simple_graph V) : V  V  Type u
| nil {u v : V} (h : u = v) : walk u v
| cons {u} (v) {w} (h : G.adj u v) (p : walk v w) : walk u w

def walk.map (f : G g G') : Π {u v : V} {u' v' : V'} (hu : f u = u') (hv : f v = v'),
  G.walk u v  G'.walk u' v'
| u v u' v' hu hv (walk.nil h) := walk.nil (by rw [ hu, h, hv])
| u v u' v' hu hv (walk.cons w h p) := walk.cons (f w) (hu  f.map_adj h) (walk.map rfl hv p)

protected def walk.equiv (f : G g G') {u v : V} {u' v' : V'} (hu : f u = u') (hv : f v = v') :
  G.walk u v  G'.walk u' v' :=
{ to_fun := walk.map (f : G g G') hu hv,
  inv_fun := walk.map (f.symm : G' g G) (by simp [ hu]) (by simp [ hv]),
  left_inv := λ p, begin
    induction p with _ _ _ _ _ _ ih generalizing u',
    { refl },
    { change walk.cons _ _ _ = _, congr' 1,
      { simp }, { conv_rhs { rw  p_ih hv rfl }, congr; simp } },
  end,
  right_inv := λ p, begin
    induction p with _ _ _ _ _ _ ih generalizing u,
    { refl },
    { change walk.cons _ _ _ = _, congr' 1,
      { simp }, { conv_rhs { rw  @p_ih hv (f.symm p_v) (by simp) }, congr; simp } },
  end }

protected def walk.equiv' (f : G g G') {u v : V} : G.walk u v  G'.walk (f u) (f v) :=
walk.equiv f rfl rfl

end simple_graph

Junyan Xu (Jul 28 2022 at 23:47):

I'm not sure if allowing equality in walk.nil is really necessary; we may use eq.rec (walk.nil ...), and if f (g v) = v definitionally then it would compute to walk.nil ....

Kyle Miller (Jul 29 2022 at 16:24):

@Junyan Xu That's a good idea. There's a trick that lets us avoid needing to modify the inductive type itself that is theoretically equivalent, which is to add in a copy function:

def walk.copy (p : G.walk u v) (hu : u = u') (hv : v = v') : G.walk u' v' :=
by { subst hu, subst hv, exact p }

Then the modified inductive type corresponds to wrapping constructors with this copy function.

With this and some accompanying lemmas, the left_inv and right_inv proofs are simp (in my code below it's longer because there are still some missing lemmas).

import combinatorics.simple_graph.connectivity

variables {V : Type*} {G : simple_graph V} {V' : Type*} {G' : simple_graph V'}
variables {V'' : Type*} {G'' : simple_graph V''}
variables {u v w u' v' w' u'' v'' w'' : V}

namespace simple_graph

def walk.copy (p : G.walk u v) (hu : u = u') (hv : v = v') : G.walk u' v' :=
by { subst hu, subst hv, exact p }

@[simp] lemma walk.copy_rfl_rfl (p : G.walk u v) (hu : u = u) (hv : v = v) :
  p.copy hu hv = p := rfl

@[simp]
lemma walk.copy_copy (p : G.walk u v)
  (hu : u = u') (hv : v = v') (hu' : u' = u'') (hv' : v' = v'') :
  (p.copy hu hv).copy hu' hv' = p.copy (hu.trans hu') (hv.trans hv') :=
by { subst_vars, refl }

@[simp]
lemma walk.copy_nil (hu : u = u') : (walk.nil : G.walk u u).copy hu hu = walk.nil :=
by { subst_vars, refl }

lemma walk.copy_cons (h : G.adj u v) (p : G.walk v w) (hu : u = u') (hw : w = w') :
  (walk.cons h p).copy hu hw = walk.cons (by { subst hu, exact h }) (p.copy rfl hw) :=
by { subst_vars, refl }

@[simp]
lemma walk.cons_copy (h : G.adj u v) (p : G.walk v' w') (hv : v' = v) (hw : w' = w) :
  walk.cons h (p.copy hv hw) = (walk.cons (by { subst hv, exact h }) p).copy rfl hw :=
by { subst_vars, refl }

@[simp]
lemma walk.map_copy (f : G g G') (p : G.walk u v) (hu : u = u') (hv : v = v') :
  (p.copy hu hv).map f = (p.map f).copy (by subst hu) (by subst hv) :=
begin
  induction p with _ _ _ _ _ _ ih generalizing u' v',
  { subst_vars, refl, },
  { rw [walk.copy_cons],
    simp only [walk.map],
    rw [walk.copy_cons, ih], }
end

lemma walk.map_map (f : G g G') (f' : G' g G'') (p : G.walk u v) :
  (p.map f).map f' = p.map (f'.comp f) := by { induction p; simp [*] }

@[simp] lemma walk.map_id (p : G.walk u v) : p.map hom.id = p := by { induction p; simp [*] }

lemma walk.map_of_eq {f : G g G'} (f' : G g G') (h : f = f') (p : G.walk u v) :
  p.map f = (p.map f').copy (by rw h) (by rw h) :=
by { subst_vars, refl }

protected def walk.equiv (f : G g G') :
  G.walk u v  G'.walk (f u) (f v) :=
{ to_fun := walk.map (f : G g G'),
  inv_fun := λ p, (p.map (f.symm : G' g G)).copy (by simp) (by simp),
  left_inv := λ p, begin
    simp [walk.map_map],
    rw walk.map_of_eq hom.id, swap, { ext, simp },
    simp,
  end,
  right_inv := λ p, begin
    simp [walk.map_map],
    rw walk.map_of_eq hom.id, swap, { ext, simp },
    simp,
  end }

end simple_graph

Kyle Miller (Jul 29 2022 at 16:26):

This is somewhat like manipulating sigma types, however with this you get constant definitional control over the endpoints of walks, which is quite nice!

Junyan Xu (Jul 29 2022 at 16:28):

If you #print walk.copy you see it's just eq.rec (eq.rec p hv) hu though and not of the form nil or cons. If hu and hv are not defeqs it doesn't compute/reduce.

Kyle Miller (Jul 29 2022 at 16:31):

I almost wrote it as eq.rec directly, but I thought using subst was clearer.

Kyle Miller (Jul 29 2022 at 16:32):

That's true they don't reduce, however having a custom eq.rec means it's easier to write all the supporting simp lemmas, which is a point I forgot to mention explicitly.

Junyan Xu (Jul 29 2022 at 16:33):

Yeah eq_to_hom is also secretely an eq.rec...

Kyle Miller (Jul 29 2022 at 16:33):

This lets us deal with the "evilness" of rewriting morphisms(/functors):

lemma walk.map_of_eq {f : G g G'} (f' : G g G') (h : f = f') (p : G.walk u v) :
  p.map f = (p.map f').copy (by rw h) (by rw h)

Kyle Miller (Jul 29 2022 at 16:34):

The idea is that the simp normal form for copy is to be the outermost thing in an expression, so that way copy_copy merges them, and eventually you can (hopefully) eliminate them completely.

Kyle Miller (Jul 29 2022 at 16:38):

Unlike for category theory, this evilness is a necessary evil since we aren't working with vertices up to isomorphism, but actually up to equality. There are no higher morphisms to save us.

Georgi Kocharyan (Aug 01 2022 at 06:48):

Rémi Bottinelli said:

Isn't gen_norm_le_one in marked_group wrong for exactly the reason Laurent Bartholdi mentionned above: a generator might be mapped to the identity ?

uh yes true, the version for subsets is right but I forgot to change the original version (the name le_one is correct though ^^)

Rémi Bottinelli (Aug 02 2022 at 08:02):

Hey, so we've been working on Freudenthal-Hopf with @Anand Rao for a while, and are getting sort of stuck/unsure about how to architect things. The "pure graph theoretical" part is mostly done, with a few sorries, but to prove the surjectivity of ends onto infinite connected components, we finally decided on using the lemma from mathlib about finite nonempty filtered inverse systems, and this cascaded into wanting to define ends really as limits, rather than as our own type, and then noticing that most of our code really should be stated in this more general setting. The code is here if anyone wants to chime in with some feedback. I believe the correct way wrt mathlib would be to have as much general stuff out of our code as possible, but it seems there is a pretty heavy infrastructure code to this.

Rémi Bottinelli (Sep 05 2022 at 08:36):

OK, after some more work here, we're planning on merging our work with the geometric-group-theory branch: anybody minds?

We're close to having:

  • Ends for (locally finite, connected) graphs in ends_limit_construction.lean.
  • A slightly modified statement of Freudenthal-Hopf in Freudenthal_Hopf.lean.
  • A notion of "coarse maps" of graphs and closeness for such maps, in order to have functoriality of ends in functoriality.lean.
  • The fact that quasi-isometries of graphs yield bijections of ends (again, slightly modified to match our definitions).
  • Plenty of sorrys peppered around, but mostly stuff that we feel should be easy from (eventual) mathlib lemmas.
  • The set of connected components outside of a finite set is defined in comp_out.lean: we took a kind of hybrid approach: defining the connected components outside of K as (G.remove_verts K).connected_component made coercions sort of unmanageable.
    Instead, we define a subgraph on the same vertex set that deconnects all of K, and then we just look at the components disjoint from K.
    This worked well enough for us.

The plan now is to do some cleanup and reorganization of the files, and then merge, assuming that's OK with people.

Rémi Bottinelli (Sep 06 2022 at 06:43):

And now I want to start working on Bass-Serre theory, and for this I'd welcome some opinions:

As far as I could find, there is essentially no code for presentations of groupoids in mathlib: the closest is the code for Nielsen-Schreier.
Does it make sense to start this low down the hierarchy and actually take the time to define presentations of groupoids, and then go up again via Higgins' paper, to, eventually, start working on Bass-Serre, or is a hands-on approach (maybe even forsaking groupoids) more reasonable?

The paper Presentations of groupoids… actually has Nielsen-Schreier and Kurosh as applications, which makes me believe that it might not be a bad idea to start here: we can already get non-trivial stuff from that approach, and in any case, I guess presentations of groupoids might prove useful more generally than for Bass-Serre?

Yaël Dillies (Sep 06 2022 at 08:02):

By the way, I am still reorganising norms to defin multiplicative normed groups. It's taking ages.

Antoine Labelle (Sep 06 2022 at 18:18):

I think that presentations of groupoids would definitely be useful by itself, independantly of Bass-Serre theory.

Rémi Bottinelli (Sep 09 2022 at 12:33):

OK, I imported our work into the geometric-group-theory branch.
@Yaël Dillies before doing the (manual) import, I tried running leanproject rebase on the ggt branch, but the rebase failed because of a duplicate definition of seminorm (or something like that). I expect that is because you had a preliminary definition locally in the ggt branch and you're now comitting bits on master. Can I safely remove the local definition?

Yaël Dillies (Sep 09 2022 at 12:34):

I think so, but what definition is it exactly?

Rémi Bottinelli (Sep 09 2022 at 12:35):

oh, maybe I misread the error:

> leanproject rebase
Checking out master...
Pulling...
`get-mathlib-cache` is for projects which depend on mathlib, not for mathlib itself. Running `get-cache` instead.
Looking for mathlib oleans for 75cc1ae964
  locally...
  Found local mathlib oleans
Using matching cache
Applying cache
  files extracted: 2674 [00:14, 179.97/s]
Checking out geometric-group-theory...
Rebasing...
Cmd('git') failed due to: exit code(1)
  cmdline: git rebase master
  stdout: 'Auto-merging src/analysis/seminorm.lean
CONFLICT (content): Merge conflict in src/analysis/seminorm.lean'
error: could not apply 8bbccf027f... use type synonyms, group seminorms
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 8bbccf027f... use type synonyms, group seminorms'

Yaël Dillies (Sep 09 2022 at 12:38):

Ah yes, that's different. You will have to fix conflicts by hand. I can do it if you promise me not to touch the branch for the next half hour

Rémi Bottinelli (Sep 09 2022 at 12:39):

Alright, informing @Anand Rao too, thanks!

Yaël Dillies (Sep 09 2022 at 12:44):

Done!

Rémi Bottinelli (Sep 09 2022 at 12:44):

quick half hour, thanks a lot!

Antoine Chambert-Loir (Sep 13 2022 at 05:54):

Rémi Bottinelli said:

And now I want to start working on Bass-Serre theory, and for this I'd welcome some opinions:

As far as I could find, there is essentially no code for presentations of groupoids in mathlib: the closest is the code for Nielsen-Schreier; but category_theory.path_category and category_theory.quotient should provide good building blocks.
Does it make sense to start this low down the hierarchy and actually take the time to define presentations of groupoids, and then go up again via Higgins' paper, to, eventually, start working on Bass-Serre, or is a hands-on approach (maybe even forsaking groupoids) more reasonable?

The paper Presentations of groupoids… actually has Nielsen-Schreier and Kurosh as applications, which makes me believe that it might not be a bad idea to start here: we can already get non-trivial stuff from that approach, and in any case, I guess presentations of groupoids might prove useful more generally than for Bass-Serre?

Chapter IV of Bourbaki's Topologie algébrique has another result on these lines, which looks more general than Higgins, at least it is framed in terms of coequalizers of groupoids. With applications to the van Kampen theorem where they give formulas that I do not think exist at other places.

Rémi Bottinelli (Sep 15 2022 at 15:30):

I'll take things slow and start with trying to mimick the subgroup API for subgroupoids

Yaël Dillies (Sep 15 2022 at 17:08):

Can't you just use subobject C where C is a groupoid ?

Kyle Miller (Sep 15 2022 at 17:38):

@Yaël Dillies I imagine that word "just" is standing in for various design tradeoffs and how you imagine subobjects working in general. Would you mind elaborating? (That's docs#category_theory.subobject correct?)

Kyle Miller (Sep 15 2022 at 17:43):

It seems to me that it's easier to work with explicit subsets rather than isomorphism classes of monomorphisms, sort of like how for simple graphs we can represent a subgraph as a subset of vertices and a sub-relation. Maybe it's workable building up API around category_theory.subobject for concrete categories, to let you ignore the quotient in practice.

Yaël Dillies (Sep 15 2022 at 17:51):

That wasn't a rhetorical question! What I have in mind, in decreasing order of preference and increasing of boilerplate, is:

  1. We can just use subobject C and its API
  2. We can just use subobject C but we need specific API
  3. We introduce a new structure for subgroupoids, show its equivalence to subobject C and use the subobject API through that equivalence
  4. We introduce a new structure for subgroupoids, show its equivalence to subobject C and transfer the subobject API through that equivalence
  5. We introduce a new structure for subgroupoids, build its API separately, and possibly show its equivalence to subobject C
  6. We introduce a new structure for subgroupoids that's not equivalent to subobject C, and build its API separately

Rémi Bottinelli (Sep 15 2022 at 17:58):

uh, I was heading in this direction. which I now understand not to be ideal.

Rémi Bottinelli (Sep 15 2022 at 17:59):

But both groups and graphs are sort of following this pattern, so I thought I was safe. Aren't I?

Kyle Miller (Sep 15 2022 at 18:46):

@Rémi Bottinelli That's a nice encoding trick you have, where the existence of an identity arrow corresponds to whether an object is present in the subgroupoid. I wonder if it would make sense, though, to introduce subquiver and have subgroupoid extend that? Or maybe you keep it the same but have it extend docs#wide_subquiver? (I'm not sure if this leads to any issues.)

Kyle Miller (Sep 15 2022 at 18:50):

I think Yael's suggestion is reasonable but more on the speculative end of things -- @Yaël Dillies Do we have much experience in mathlib with defining subobjects using docs#category_theory.subobject? I think we understand how to create subobjects using custom structures fairly well.

Adam Topaz (Sep 15 2022 at 20:06):

Using docs#category_theory.subobject is great if all you care about is the lattice structure of the type of subobjects, but I think making a custom structure is a better approach whenever you want to work with actual elements of the subobject.

Rémi Bottinelli (Sep 16 2022 at 10:17):

What would subquiver bring to the table? I think in that case we would lose the "trick" you're refering to, right?

Rémi Bottinelli (Sep 16 2022 at 13:19):

(deleted)

Rémi Bottinelli (Sep 22 2022 at 10:24):

I'm working on the free groupoid and have a question:
I've defined a custom inductive type of "words" on my initial quiver as here but there is also quiver.path and quiver.symmetrify.
The problem with using quiver.path and quiver.symmetrify is mostly that I have to deal with the type synonym introduced by quiver.symmetrify.

Should I work with what's already here anyway?

Junyan Xu (Sep 23 2022 at 02:14):

Just wanna let you geometric group theory folks know about the amenable group PRs (Zulip discussion); maybe you would be interested in helping reviewing them? The code looks like it needs to go through a lot of revisions, but firstly we need to make some design decisions. The references listed in the PRs are:

Yaël Dillies (Oct 06 2022 at 22:13):

Heads up that #15705 is in, so we now can PR marked groups and such!

Rémi Bottinelli (Oct 09 2022 at 07:27):

Great! For now I'm busy trying to deal with groupoids and eventually Bass-Serre hopefully.
There was a discussion about marked groups perhaps not being the best place to start with the geometry of groups: is there a consensus on that?

By the way, I noticed I'm starting to use quivers quite extensively, and will probably use them to do graph theory: say talk about the existence of maximal trees, etc. There already was [has_reverse] on quivers, and I added [has_involutive_reverse] and now I feel this is dangerously close to simply talking of graphs.
Would it make sense to take this as an opportunity to make this the official definition of "unoriented multigraph" ? (opinion, @Kyle Miller ?)

Yaël Dillies (Oct 09 2022 at 07:28):

Do you know about #16100?

Rémi Bottinelli (Oct 09 2022 at 07:29):

I didn't, no! hum, this makes my stuff quite redundant… Why not base it on quivers?

Yaël Dillies (Oct 09 2022 at 07:30):

There are several reasons, really. But I think both approaches are viable.

Rémi Bottinelli (Oct 09 2022 at 07:32):

I like using quivers since it allows a natural "symmetrization", and you have fewer equalities to deal with I'm used to it already, in some sense… I assume changing the implementation of multigraphs isn't acceptable? What do you recommend I do, then?

Yaël Dillies (Oct 09 2022 at 07:33):

#16100 is just experimental, but I do not believe your "there are fewer equalities to deal with". Multigraphs are so that you should never need defeq on the type of edges.

Rémi Bottinelli (Oct 09 2022 at 07:38):

I see, yeah. I wanted to use the "Serre" definition of graphs to begin with, but after looking at what they do in Bass-Serre, it's always orientation-preserving actions (and the involution on edges has no fixed points), meaning you can just choose an orientation and be done with it: hence quivers.

Rémi Bottinelli (Oct 10 2022 at 05:31):

OK, so what's the way forward with this, and how can I help it making progress?

Note also that the quiver definition make the passage to categories very easy but with this custom definition you need to add more glue code as far as I can see.

Rémi Bottinelli (Oct 10 2022 at 13:39):

Something else I'd like to get some opinions on: I need to talk about "free products" and quotients of groupoids. My first instinct was to define this by hand, but actually I see that there is code for Cats and Groupoids talking about limits and such, and I'm wondering how much of the existing tooling I should/can use.

  • If I'm not mistaken, I can take limits/colimits in Cats and they'll actually also define limits/colimits in Groupoids (that's a general mathematical statement, not talking about mathlib).
  • On the other hand, I actually don't see that Cats has coequalizers in mathlib, is that right?
  • Also, I'm wondering if defining those construction via "the category of …" will involve much more boilerplate than defining them by hand.

So, in short, where should I draw the line, and what's the correct way to proceed here?

Junyan Xu (Oct 10 2022 at 16:42):

Limits in Cat was done by Joseph Hua in this thread back in February, but was added to mathlib by @Scott Morrison in March in #12979, maybe using a different approach, I didn't check. I'm pretty sure we don't have colimits yet, given that category_theory.category.Cat.limit has no siblings in the same directory.

Scott Morrison (Oct 10 2022 at 23:03):

(Sorry, I had completely missed Joseph's thread, I think.)

Rémi Bottinelli (Oct 11 2022 at 11:04):

As an aside, there is something I don't totally get with the organization of mathlib.
What does the organization wrt "what should be included in what order using which construction" look like?
This might be a bit naive of my part, but it feels like it's some kind of a big soup of people contributing what they feel like and reviewers accepting on a case-by-case basis without much "long-term"/organizational thought. I'd expect to see some kind of hierarchy of subjects, with working groups deciding on the design and strategy of the subject in a way that makes it harder for people to work blindly on something that will be useless or already worked on. I don't want to spit in the soup, and am very grateful to everyone involved for the coaching and help in getting stuff included, but I'm wondering if these is some margin for streamlining of the process?

Yaël Dillies (Oct 11 2022 at 11:11):

Have you seen https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/mathlib.20organization ?

Rémi Bottinelli (Oct 11 2022 at 11:22):

I have, but missed the "teams" part.
It's indeed part of what I'm talking about, but doesn't seem to cover a more involved hierarchy of subjects and plans as for how to cover them, does it? Is having such a specified plan just too ambitious and bureaucratic, and a risk of killing the "organic" flow mathlib is currently working with?

Andrew Yang (Oct 11 2022 at 11:26):

I'd think that the current canonical answer to "How to prevent oneself from working blindly on something that will be useless or already worked on" is to ask on zulip before starting.

Scott Morrison (Oct 12 2022 at 00:01):

I think the answer is mostly that the "long-term organizational thought" doesn't actually come to much without someone able/willing to write the code, and so we mostly prefer to let mathlib grow organically according to what people actually want to write.

We're mostly extremely liberal on what counts as "appropriate to mathlib", with occasional exceptions.

That said, I think there is a lot of "organizational planning" that happens off in branches, and during the PR process. It's not at all unusual that it takes several developments of the same material before it actually makes it into mathlib.

Jireh Loreaux (Oct 12 2022 at 02:37):

Perhaps they are underutilized, but we also have projects on GitHub for this sort of thing.

Rémi Bottinelli (Oct 20 2022 at 09:59):

Hey, so I've finally managed to get the quotient construction for groupoids working, and thus presentations.
My construction for the quotient is perhaps unorthodox, in that (as said above) I first quotient by the isotropy groups only, which means no collapsing of vertices, and then quotient by what remains, which is always graph_like i.e. has at most one edge between two vertices.

I'd be thankful if someone could have a look at the code here and tell me if it's worth cleaning up to make a PR, of if this approach is considered too dirty.


Last updated: Dec 20 2023 at 11:08 UTC