Zulip Chat Archive

Stream: Is there code for X?

Topic: Submonoid formed by the units


Xavier Xarles (Feb 16 2024 at 12:06):

Given a Monoid, how can one construct the Submonoid formed by the elements that have inverse? The Units are not a Submonoid, but something else...

Yaël Dillies (Feb 16 2024 at 12:11):

cc @Wrenna Robson

Wrenna Robson (Feb 16 2024 at 12:15):

So I think this is (\top : Submonoid M).units.ofUnits

Wrenna Robson (Feb 16 2024 at 12:16):

Or equivalently, actually, (\top : Subgroup M\times).ofUnits

Wrenna Robson (Feb 16 2024 at 12:16):

(not on pc, can't add proper symbols)

Wrenna Robson (Feb 16 2024 at 12:17):

But given a subgroup of units, ofUnits gives you the corresponding submonoid, and you want the subgroup of all units.

Wrenna Robson (Feb 16 2024 at 12:17):

If you want the subgroup of units corresponding to a given submonoid, that's what Submonoid.units is for

Eric Wieser (Feb 16 2024 at 13:01):

Is this also Units.coeHom.mrange?

Wrenna Robson (Feb 16 2024 at 13:01):

Well that's as a set, but yeah I think so

Eric Wieser (Feb 16 2024 at 13:02):

docs#MonoidHom.mrange disagrees with you

Wrenna Robson (Feb 16 2024 at 13:02):

Oh lol

Wrenna Robson (Feb 16 2024 at 13:02):

Then yes

Eric Wieser (Feb 16 2024 at 13:02):

Whoops, I meant mrange

Wrenna Robson (Feb 16 2024 at 13:02):

Ahhhhh

Wrenna Robson (Feb 16 2024 at 13:03):

Yeah

Eric Wieser (Feb 16 2024 at 13:03):

But range is a subgroup, not a set

Wrenna Robson (Feb 16 2024 at 13:04):

Yeah ofUnits is essentially just the image of coeHom so that sounds correct

Xavier Xarles (Feb 16 2024 at 22:04):

How do you feel about adding something like this in the Mathlib.GroupTheory.Submonoid.Units?

import Mathlib.GroupTheory.Submonoid.Units

variable {M : Type*}
variable [CommMonoid M]

theorem mem_ofUnits_of_top_iff_isUnit (x:M) :  x  Subgroup.ofUnits   IsUnit x := by
  rw [Subgroup.mem_ofUnits_iff_exists_isUnit]
  exact exists_iff_of_forall fun _ => trivial

Wrenna Robson (Feb 16 2024 at 22:05):

Yeah we should probably have that.

Wrenna Robson (Feb 16 2024 at 22:05):

I'm wondering if there's any other analogous things that need adding

Wrenna Robson (Feb 16 2024 at 22:08):

We have one direction of it, it seems

Wrenna Robson (Feb 16 2024 at 22:08):

Subgroup.isUnit_of_mem_ofUnits

Wrenna Robson (Feb 16 2024 at 22:09):

Ah.

Wrenna Robson (Feb 16 2024 at 22:10):

And Subgroup.mem_ofUnits_of_isUnit_of_unit_mem is the other direction

Wrenna Robson (Feb 16 2024 at 22:10):

Or is once you consider everything is mem_top

Wrenna Robson (Feb 16 2024 at 22:11):

But your proof is also good

Wrenna Robson (Feb 16 2024 at 22:14):

Oh! Also, answering your original question again: it's also IsUnit.submonoid

Wrenna Robson (Feb 16 2024 at 22:15):

The table at the top of Submonoid/Units would say this, if it worked

Wrenna Robson (Feb 16 2024 at 22:16):

Yeah if you want the units as a submonoid of a monoid, use IsUnit.submonoid

Wrenna Robson (Feb 16 2024 at 22:22):

If you want the units as a submonoid of the monoid in which a submonoid lies, then that is S.units.ofUnits

Wrenna Robson (Feb 16 2024 at 22:23):

I guess Subgroup.ofUnits \top = IsUnit.submonoid M might be useful to have!

Wrenna Robson (Feb 16 2024 at 22:27):

Subgroup.ofUnits_top

Wrenna Robson (Feb 16 2024 at 22:30):

Yes, I think that would be good to have. We could also have the lemma you mention, which is naturally a consequence

Xavier Xarles (Feb 16 2024 at 22:32):

I don't like the proof, but something like this?

import Mathlib.GroupTheory.Submonoid.Units

variable {M : Type*}[CommMonoid M]

theorem Subgroup.ofUnits_top : Subgroup.ofUnits  = IsUnit.submonoid M := by
  refine Submonoid.ext ?h
  simp_rw [IsUnit.mem_submonoid_iff,Subgroup.mem_ofUnits_iff_exists_isUnit]
  exact fun x => exists_iff_of_forall fun _ => trivial

Wrenna Robson (Feb 16 2024 at 22:33):

Yes, precisely.

Eric Wieser (Feb 16 2024 at 22:38):

A shorter proof:

import Mathlib.GroupTheory.Submonoid.Units

variable {M : Type*} [Monoid M]

theorem Units.mrange_coeHom : MonoidHom.mrange (Units.coeHom M) = IsUnit.submonoid M := rfl

theorem Subgroup.ofUnits_top : Subgroup.ofUnits  = IsUnit.submonoid M := (MonoidHom.mrange_eq_map _).symm

Wrenna Robson (Feb 16 2024 at 22:40):

Very nice

Wrenna Robson (Feb 16 2024 at 22:42):

Units.mrange_coeHom wants to be in a different file

Xavier Xarles (Feb 16 2024 at 23:03):

I really don't get how can the proof be so shorter, and using a result that doesn't seem related...

Wrenna Robson (Feb 16 2024 at 23:03):

Well, ofUnits is by definition (coeHom M).map

Wrenna Robson (Feb 16 2024 at 23:05):

So the LHS is map, by definition. And it turns out in fact IsUnit.submonoid is defeq to mrange

Wrenna Robson (Feb 16 2024 at 23:06):

That's more surprising maybe

Wrenna Robson (Feb 16 2024 at 23:13):

Oh this does mean that Submonoid.units (IsUnit.submonoid M) = \top as well

Wrenna Robson (Feb 16 2024 at 23:13):

If we don't have that too, we should

Wrenna Robson (Feb 16 2024 at 23:14):

call it Submonoid.units_isUnit_eq_top or something

Wrenna Robson (Feb 16 2024 at 23:17):

(it's an immediate consequence of the above, given the Galois insertion)

Wrenna Robson (Feb 16 2024 at 23:35):

@Yaël Dillies how do I say "the lattice of subgroups of units is equivalent to the lattice of submonoids contained in IsUnit.subMonoid, with the units/ofUnits Galois Coinsertion defining the maps across"?

Yaël Dillies (Feb 16 2024 at 23:39):

Subgroup (Units M) o~= {s : Submonoid M // s <= IsUnit.submonoid}?

Wrenna Robson (Feb 16 2024 at 23:48):

Cool! I don't know if we tend to have theorems like that.

Yaël Dillies (Feb 17 2024 at 00:01):

Probably we have at least one direction

Eric Wieser (Feb 17 2024 at 00:11):

Isn't that just a special case of Subgroup M o~= {s : Submonoid N // s <= mrange f} or similar?

Wrenna Robson (Feb 17 2024 at 00:12):

Hmm, perhaps!

Wrenna Robson (Feb 17 2024 at 00:12):

Is that true for arbitrary f?

Wrenna Robson (Feb 17 2024 at 00:13):

ofUnits is just map, but units needed a little more to it, so it would seem surprising to me if it came out of that.

Xavier Xarles (Feb 18 2024 at 11:21):

It seems that we don't have

import Mathlib.Algebra.Group.Units

variable {M:Type*}

lemma IsUnit.exists_inv [Monoid M] {a : M}(h : IsUnit a) :
     b, (a * b = 1)  (b * a = 1) := by
  rcases h with ⟨⟨a, b, hab,hba⟩, rfl
  exact b,  hab, hba⟩⟩

theorem isUnit_iff_exists [Monoid M] {a : M} : IsUnit a 
     b, (a * b = 1)  (b * a = 1) :=
  fun h => IsUnit.exists_inv h , fun b, hab,hba => by use _, b, hab,hba 

Eric Wieser (Feb 18 2024 at 11:25):

I think that's probably because you never need those lemmas

Xavier Xarles (Feb 18 2024 at 11:26):

May be. Although I discovered because I need them...

Eric Wieser (Feb 18 2024 at 11:26):

It's usually more convenient to keep a Unit around than to unpack it into the val and inv

Xavier Xarles (Feb 18 2024 at 11:27):

In fact I need the other way: if I have such a b, then a is a Unit.

Eric Wieser (Feb 18 2024 at 11:29):

Can you share your context?

Damiano Testa (Feb 18 2024 at 11:29):

There are results around docs#isUnit_iff_exists_inv

Jireh Loreaux (Feb 18 2024 at 14:58):

If you actually have a b, you can easily just build a term of Units directly, and even use the lift tactic to turn a itself into a unit.

Junyan Xu (Feb 18 2024 at 15:48):

IsUnit a ↔ (∃ b, a * b = 1) ∧ (∃ c, c * a = 1) is probably more useful ...

Wrenna Robson (Feb 18 2024 at 15:49):

Why?

Junyan Xu (Feb 18 2024 at 15:52):

It's not just a rephrasing of the definition (i.e. you can't get it by permuting arguments of the constructors), instead you need associativity to prove the reverse direction.

Xavier Xarles (Feb 19 2024 at 11:30):

So, how do you feel about this result?

import Mathlib.GroupTheory.Submonoid.Units
variable {M : Type*} [Monoid M]

theorem isUnit_iff_exists_both_units  (a:M): IsUnit a  ( b, a * b = 1)  ( c, c * a = 1):= by
constructor <;> intro h
· rcases h with ⟨⟨a, b, hab,hba⟩, rfl
  exact Exists.intro b hab, Exists.intro b hba
· let b,hab := h.1
  let c,hca := h.2
  have beqc: b = c:= by
    calc
      b = 1*b := (one_mul b).symm
      _ = (c*a)*b := congrFun (congrArg HMul.hMul (id hca.symm)) b
      _ = c*(a*b) := mul_assoc c a b
      _ = c*1:= congrArg (HMul.hMul c) hab
      _ = c := mul_one c
  rw [beqc] at hca
  use _, b, hab,hca

Wrenna Robson (Feb 19 2024 at 11:31):

Junyan Xu said:

It's not just a rephrasing of the definition (i.e. you can't get it by permuting arguments of the constructors), instead you need associativity to prove the reverse direction.

Hmm. Yeah I suppose it being both directions is the interesting bit.

Wrenna Robson (Feb 19 2024 at 11:32):

Xavier Xarles said:

So, how do you feel about this result?

import Mathlib.GroupTheory.Submonoid.Units
variable {M : Type*} [Monoid M]

theorem isUnit_iff_exists_both_units  (a:M): IsUnit a  ( b, a * b = 1)  ( c, c * a = 1):= by
constructor <;> intro h
· rcases h with ⟨⟨a, b, hab,hba⟩, rfl
  exact Exists.intro b hab, Exists.intro b hba
· let b,hab := h.1
  let c,hca := h.2
  have beqc: b = c:= by
    calc
      b = 1*b := (one_mul b).symm
      _ = (c*a)*b := congrFun (congrArg HMul.hMul (id hca.symm)) b
      _ = c*(a*b) := mul_assoc c a b
      _ = c*1:= congrArg (HMul.hMul c) hab
      _ = c := mul_one c
  rw [beqc] at hca
  use _, b, hab,hca

It feels like in many ways we should have a defined predicate for "IsLeftUnit" but it's good.

Eric Wieser (Feb 19 2024 at 11:43):

That golfs to

theorem isUnit_iff_exists_both_units  (a : M) : IsUnit a  ( b, a * b = 1)  ( c, c * a = 1):= by
  constructor
  · rintro ⟨⟨a, b, hab, hba⟩, rfl
    exact ⟨⟨b, hab⟩, b, hba⟩⟩
  · rintro ⟨⟨b, hab⟩, c, hca⟩⟩
    suffices b = c from ⟨⟨a, b, hab, this  hca⟩, rfl
    calc
      b = 1*b := (one_mul b).symm
      _ = (c*a)*b := congrArg (· * b) hca.symm
      _ = c*(a*b) := mul_assoc c a b
      _ = c*1 := congrArg (c * ·) hab
      _ = c := mul_one c

Damiano Testa (Feb 19 2024 at 12:28):

Or you could use regular elements:

theorem isUnit_iff_exists_both_units  (a : M) : IsUnit a  ( b, a * b = 1)  ( c, c * a = 1):= by
  constructor
  · rintro ⟨⟨a, b, hab, hba⟩, rfl
    exact ⟨⟨b, hab⟩, b, hba⟩⟩
  · rintro ⟨⟨b, hab⟩, c, hca⟩⟩
    suffices b = c from ⟨⟨a, b, hab, this  hca⟩, rfl
    have : IsRegular a := isLeftRegular_of_mul_eq_one _›, isRightRegular_of_mul_eq_one _›⟩
    exact this.right (this.left (by simp [ mul_assoc, *]))

Kevin Buzzard (Feb 19 2024 at 18:51):

You can also use docs#left_inv_eq_right_inv

Kevin Buzzard (Feb 19 2024 at 19:52):

This is the only interesting theorem I know about monoids :-)


Last updated: May 02 2025 at 03:31 UTC