Zulip Chat Archive

Stream: PR reviews

Topic: !4#3333 Data.ZMod.Quotient


Mauricio Collares (May 17 2023 at 16:23):

Parts of !4#3333 are massively complicated by the fact that we cannot make MulOpposite semireducible any more (as was done in mathlib3 via a local attribute). I just pushed a commit that manually re-does some of the MulEquivs there, but I don't know if that's the right approach. Feel free to just revert the commit if it is the wrong approach.

Mauricio Collares (May 17 2023 at 16:30):

I meant to post this in the mathlib4 stream, since this is not ready for review

Kevin Buzzard (May 17 2023 at 16:41):

docs4#MulOpposite

Mauricio Collares (May 17 2023 at 16:42):

Thanks. Also meant to say "semireducible" in the original message, fixed now.

Kevin Buzzard (May 17 2023 at 16:42):

Yeah, I was going to say "it's a structure, which has the same effect as being irreducible". So is the issue that the mathlib3 version abused definitional equality?

Mauricio Collares (May 17 2023 at 16:42):

Yes, locally

Kevin Buzzard (May 17 2023 at 16:43):

I have some Lean time now -- can you give me an example of something which is painful? I'd be interested to see.

Mauricio Collares (May 17 2023 at 16:44):

There are two rfl proofs in Data.ZMod.Quotient that don't work anymore (zpowersQuotientStabilizerEquiv_symm_apply, orbitZpowersEquiv_symm_apply). Those should be good examples. Or you can look at zpowersQuotientStabilizerEquiv before my last commit there.

Mauricio Collares (May 17 2023 at 16:48):

https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/two.20different.20quotients.20by.20subgroup (the whole thread) is related

Eric Wieser (May 17 2023 at 17:42):

So is the issue that the mathlib3 version abused definitional equality?

Or that it shouldn't have been irreducible in the first place; docs#add_opposite never was.

Mauricio Collares (May 17 2023 at 17:43):

Both are irreducible in mathlib4 at the moment

Eric Wieser (May 17 2023 at 17:44):

Worse, they're structures, right?

Eric Wieser (May 17 2023 at 17:45):

I don't remember the motivation, but maybe it's now moot after lean4#2210 landed and we can revert it?

Mauricio Collares (May 17 2023 at 17:55):

This was done in !4#1036. I quite like them as structures conceptually speaking, though. I wonder how many other files break, hopefully not many. My uneducated impression was that there's a lot of missing API on interactions between MulOpposite/AddOpposite and Multiplicative/Additive. There's discussion at https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Order.2EGaloisConnection

Eric Wieser (May 17 2023 at 17:56):

It's specifically this quotient stuff where the defeq is needed

Eric Wieser (May 17 2023 at 17:57):

Here's a way to write that definition that might help preserve the defeqs we want:

  by
    letI f := zmultiplesQuotientStabilizerEquiv (Additive.ofMul a) b
    refine ((QuotientGroup.toQuotientAddGroup _).trans ?_).trans (AddEquiv.toMultiplicative f)
    refine AddEquiv.toMultiplicative ?_
    sorry

Eric Wieser (May 17 2023 at 18:01):

Specifically, this is the missing piece:

instance Normal.toAddSubgroup {G} [Group G] (S : Subgroup G) [Normal S] :
    AddSubgroup.Normal (Subgroup.toAddSubgroup S) :=
  sorry

def QuotientGroup.toQuotientAddGroup {G} [Group G] (S : Subgroup G) [Normal S] :
    G  S ≃* Multiplicative (Additive G  Subgroup.toAddSubgroup S) :=
sorry

Kevin Buzzard (May 17 2023 at 18:01):

How does one make the Subgroup of Multiplicative G corresponding to s : AddSubgroup G?
Edit: aah, you just told me!

Eric I don't follow your claim that defeq is _needed_. Why can't we just have a bunch of canonical isomorphisms? I'm pretty sure we already have the isomorphism G/M -> G/N coming from an equality M=N.

Eric Wieser (May 17 2023 at 18:01):

In lean3 those types were true by definition

Eric Wieser (May 17 2023 at 18:02):

Kevin, it's not _needed_ per se; but it was very convenient. Indeed, the isomorphism we're missing is the one I give above

Eric Wieser (May 17 2023 at 18:02):

I guess by "needed" what I mean is "structure eta alone is not enough to keep the defeqs we had in Lean 3"

Eric Wieser (May 17 2023 at 18:03):

Whereas for almost all other uses of MulOpposite, the defeqs we had in Lean3 are still around

Kevin Buzzard (May 17 2023 at 18:10):

The instance shouldn't be hard; as for the def, I feel like we should have a construction (Additive G \equiv+ A) \equiv (G \equiv* Multiplicative A), and this would I think help with it.

Eric Wieser (May 17 2023 at 18:11):

We have that, it's docs4#AddEquiv.toMultiplicative'

Eric Wieser (May 17 2023 at 18:11):

I'm pretty sure we already have the isomorphism G/M -> G/N coming from an equality M=N.

I agree, but I can't find it. Do you remember what it's called?

Kevin Buzzard (May 17 2023 at 18:11):

My suggestion has better notation ;-)

Eric Wieser (May 17 2023 at 18:12):

You mean it has the parens on both sides?

Kevin Buzzard (May 17 2023 at 18:14):

docs4#QuotientGroup.quotientMulEquivOfEq for the equality. No I just meant that I used A for an additive group.

Eric Wieser (May 17 2023 at 18:16):

QuotientGroup.toQuotientAddGroup will need to be an implemention of that function from scratch, with tweaked types

Eric Wieser (May 17 2023 at 18:17):

Hmm, maybe this whole problem goes away if we make MulOpposite and AddOpposite the same structure under the hood...

Kevin Buzzard (May 17 2023 at 18:18):

You are a Lean guru if you can guess the error I get from

import Mathlib.GroupTheory.QuotientGroup
import Mathlib.Algebra.Hom.Equiv.TypeTags

open Subgroup

instance Normal.toAddSubgroup {G} [Group G] (S : Subgroup G) [Normal S] :
    AddSubgroup.Normal (Subgroup.toAddSubgroup S) :=
  sorry

def QuotientGroup.toQuotientAddGroup {G} [Group G] (S : Subgroup G) [Normal S] :
    G  S ≃* Multiplicative (Additive G  Subgroup.toAddSubgroup S) :=
by convert AddEquiv.toMultiplicative' (AddEquiv.refl _)

Kevin Buzzard (May 17 2023 at 18:19):

Eric Wieser (May 17 2023 at 18:20):

error: nice try?

Kevin Buzzard (May 17 2023 at 18:21):

kind of

Eric Wieser (May 17 2023 at 18:21):

Yeah ok that's not on the list of things I expected

Eric Wieser (May 17 2023 at 18:21):

But it's going to ask you to prove that MulOpposite G = AddOpposite (Additive G), and that defeq broke

Kevin Buzzard (May 17 2023 at 18:22):

I'm confused about why opposites have got anything to do with anything.

Eric Wieser (May 17 2023 at 18:22):

Because the quotient is defined by the action by the opposite group (right multiplication)

Eric Wieser (May 17 2023 at 18:22):

So deep down there is an existential quantifying over MulOpposite

Kevin Buzzard (May 17 2023 at 18:23):

I was hoping Additive (G ⧸ S) = (Additive G ⧸ (Subgroup.toAddSubgroup S)) would be rfl

Eric Wieser (May 17 2023 at 18:24):

It's not, but it was in Lean 3 before we made MulOpposite a structure. That's the problem.

Kevin Buzzard (May 17 2023 at 18:25):

I guess this is an artificial hope anyway; really we should be writing down the isomorphisms, right?

Eric Wieser (May 17 2023 at 18:26):

Well, it depends where the threshold for "defeq abuse is ok" is

Eric Wieser (May 17 2023 at 18:26):

Eric Wieser said:

Hmm, maybe this whole problem goes away if we make MulOpposite and AddOpposite the same structure under the hood...

I'm trying this in https://github.com/leanprover-community/mathlib4/pull/4050

Kevin Buzzard (May 17 2023 at 18:41):

(I restarted Lean and the problem I posted went away)

Kevin Buzzard (May 17 2023 at 18:41):

(deleted)

Eric Wieser (May 17 2023 at 18:44):

(does your deleted code work?)

Kevin Buzzard (May 17 2023 at 18:45):

import Mathlib.GroupTheory.QuotientGroup
import Mathlib.Algebra.Hom.Equiv.TypeTags

open Subgroup

instance Normal.toAddSubgroup {G} [Group G] (S : Subgroup G) [Normal S] :
    AddSubgroup.Normal (Subgroup.toAddSubgroup S) where
  conj_mem := Normal.conj_mem (H := S) inferInstance

def QuotientGroup.toQuotientAddGroup {G} [Group G] (S : Subgroup G) [Normal S] :
    G  S ≃* Multiplicative (Additive G  toAddSubgroup S) :=
AddEquiv.toMultiplicative' sorry

Works fine (and is not slow as previously claimed)

Eric Wieser (May 17 2023 at 18:46):

Sure, but the sorry is just as hard as the original

Eric Wieser (May 17 2023 at 18:46):

(that instance should definitely be added to mathlib btw)

Kevin Buzzard (May 17 2023 at 18:47):

It doesn't have a mix of additive and multiplicative though, so it feels like progress.

Kevin Buzzard (May 17 2023 at 18:48):

Is it expected that I write toAddsubgroup S and Lean prettyprints it as the awful ↑(RelIso.toRelEmbedding toAddSubgroup).toEmbedding S?

Eric Wieser (May 17 2023 at 18:51):

!4#4050 works, and lets rfl close the sorry

Kevin Buzzard (May 17 2023 at 18:52):

docs4#Opposite

Kevin Buzzard (May 17 2023 at 18:53):

Why not just use Opposite?

Eric Wieser (May 17 2023 at 18:53):

Because I don't know whether we want Opposite to be defeq to MulOpposite

Kevin Buzzard (May 17 2023 at 18:54):

But you do think that we want AddOpposite to be defeq to MulOpposite??

Kevin Buzzard (May 17 2023 at 18:54):

Usually at this point you start going on about diamonds and semirings

Kevin Buzzard (May 17 2023 at 18:55):

It's certainly a hilarious fix though!

Eric Wieser (May 17 2023 at 18:55):

Yes, because we have Multiplicative X = Additive X right now, and it's weird to have that be true but not Multiplicative (AddOpposite X) = Additive (MulOpposite X)

Eric Wieser (May 17 2023 at 18:56):

It's a trade off between having "abuse" of defeqs and having to write lots of really stupid boilerplate

Eric Wieser (May 17 2023 at 18:56):

Until the abuse starts causing harm, the easier choice is to put off the boilerplate until it's really needed

Kevin Buzzard (May 17 2023 at 18:57):

With the advent of lean4#2210 I am a bit confused about which of def thing_which_bijects_with_X (X : Type) := X and structure thing_which_bijects_with_X (X : Type) := { random_name : X} we prefer nowadays.

Eric Wieser (May 17 2023 at 18:58):

The former is still a lot more convenient for avoiding boilerplate, which is why docs4#OrderDual still uses it

Kevin Buzzard (May 17 2023 at 18:59):

What's wrong with boilerplate? I should think ChatGPT could write it all by now anyway

Eric Wieser (May 17 2023 at 19:07):

Stuff like QuotientGroup.toQuotientAddGroup is fine, but it's nice when the stupid boilerplate can be proved by rfl

Kevin Buzzard (May 17 2023 at 21:12):

The "category theory" proof of Additive G ⧸ toAddSubgroup S ≃+ Additive (G ⧸ S) has the disadvantage that it uses the first isomorphism theorem (the isomorphism is induced from the surjection G -> G/S, additivised) so the inverse is noncomputable. I don't know how serious that problem is.

Kevin Buzzard (May 17 2023 at 21:12):

What the heck is going on here BTW? I have an obscure error:

import Mathlib.GroupTheory.QuotientGroup
import Mathlib.Algebra.Hom.Equiv.TypeTags

open Subgroup

instance Normal.toAddSubgroup {G} [Group G] (S : Subgroup G) [Normal S] :
    AddSubgroup.Normal (Subgroup.toAddSubgroup S) where
  conj_mem := Normal.conj_mem (H := S) inferInstance

def foo {G} [Group G] (S : Subgroup G) [Normal S] :
    Additive G  toAddSubgroup S ≃+ Additive (G  S) :=
  (QuotientAddGroup.quotientAddEquivOfEq sorry : Additive G  toAddSubgroup S ≃+ Additive G  _).trans
  (QuotientAddGroup.quotientKerEquivOfSurjective
    (MonoidHom.toAdditive (QuotientGroup.mk' S) : Additive G →+ Additive (G  S)) sorry)
/-
IR check failed at 'foo._rarg', error: unknown declaration 'QuotientAddGroup.quotientKerEquivOfSurjective'
-/

#check QuotientAddGroup.quotientKerEquivOfSurjective -- works fine

Edit: fixed by marking foo noncomputable. That's a pretty weird way to tell me to do that :-/

Kevin Buzzard (May 17 2023 at 21:46):

Here's what I imagine the "category theory philosophy" proof looks like:

import Mathlib.GroupTheory.QuotientGroup
import Mathlib.Algebra.Hom.Equiv.TypeTags
import Mathlib.Tactic

open Subgroup MonoidHom

instance Normal.toAddSubgroup {G} [Group G] (S : Subgroup G) [Normal S] :
    AddSubgroup.Normal (Subgroup.toAddSubgroup S) where
  conj_mem := Normal.conj_mem (H := S) inferInstance

lemma lemma1 {G H : Type _} [Group G] [Group H] (φ : G →* H) :
    Function.Surjective (toAdditive φ)  Function.Surjective φ := Iff.rfl

lemma lemma2 {G} [Group G] (S : Subgroup G) [Normal S] :
    toAddSubgroup S = AddMonoidHom.ker (toAdditive (QuotientGroup.mk' S)) := by
  sorry

noncomputable def foo {G} [Group G] (S : Subgroup G) [Normal S] :
    Additive G  toAddSubgroup S ≃+ Additive (G  S) :=
  (QuotientAddGroup.quotientAddEquivOfEq (lemma2 S) : Additive G  toAddSubgroup S ≃+ Additive G  _).trans
  (QuotientAddGroup.quotientKerEquivOfSurjective
    (MonoidHom.toAdditive (QuotientGroup.mk' S) : Additive G →+ Additive (G  S)) $
    QuotientGroup.mk'_surjective S)

-- at least this part is computable
example {G} [Group G] (S T : Subgroup G) [Normal S] [Normal T] (h : S = T) (g : G) :
  QuotientGroup.quotientMulEquivOfEq h (QuotientGroup.mk g) = QuotientGroup.mk g := rfl

noncomputable def QuotientGroup.toQuotientAddGroup {G} [Group G] (S : Subgroup G) [Normal S] :
    G  S ≃* Multiplicative (Additive G  toAddSubgroup S) :=
AddEquiv.toMultiplicative' (foo S).symm

Still one sorry to go

Kevin Buzzard (May 17 2023 at 22:04):

lemma lemma2 {G} [Group G] (S : Subgroup G) [Normal S] :
    toAddSubgroup S = AddMonoidHom.ker (toAdditive (QuotientGroup.mk' S)) := by
  ext g
  exact SetLike.ext_iff.1 (QuotientGroup.ker_mk' S).symm g -- more defeq abuse

So I'm moaning about defeq abuse on the one hand and then using it on the other :-/

Eric Wieser (May 17 2023 at 22:16):

IMO it's totally unreasonable for these stupid isomorphisms to be non-computable, when in lean3 it was "the identity"

Eric Wieser (May 17 2023 at 22:17):

(for those who don't care about computability: this also has a lousy defeq in the reverse direction)

Eric Wieser (May 17 2023 at 22:18):

I'll cleanup my AddOpposite = MulOpposite PR tomorrow, which should optimistically remove all the hacks from this port

Kevin Buzzard (May 17 2023 at 22:19):

Why not go the whole hog and let's go back to AddOpposite X := X?

Kevin Buzzard (May 17 2023 at 22:37):

I guess a strongly related question is "now we can't switch between irreducible and semireducible at will, do we want always irreducible or always semireducible".

Eric Wieser (May 18 2023 at 09:24):

I've restarted !4#3333 at !4#4074 and the port was trivial after !4#4050

Alex J. Best (May 18 2023 at 21:28):

I don't have time to read this thread right now unfortunately so maybe you have all already solved this issue, but I had a go at removing the relevant local attribute in mathlib3 by being a lot more explicit at various equivs in https://github.com/leanprover-community/mathlib/tree/alexjbest/bye-semired feel free to adopt it if its helpful

Eric Wieser (May 18 2023 at 21:32):

My preference would be to merge !4#4050 (which restores the Lean3 behavior we need for this file), and consider a larger refactor post-port


Last updated: Dec 20 2023 at 11:08 UTC