Zulip Chat Archive
Stream: mathlib4
Topic: PNat powers in a semigroup
Scott Carnahan (Nov 28 2023 at 21:00):
I was hoping to apply strictly positive integer powers to a semigroup M
(or positive integer scalar multiples in an AddSemigroup
M
), but there seems to be a can of worms here.
I could write a [Pow M ℕ+]
(or [SMul ℕ+ M]
) instance using the existing definition of semigroup, but I run into an instance diamond with Pi types. The problem seems to be that powers in a product of semigroups (which has a semigroup instance) is not defeq to component-wise powers. This is the same problem (described in Mathlib.Algebra.Group.Defs) that led to the inclusion of ℕ powers into the definition of monoid.
One solution is to add PNat powers to the definition of semigroup. This clears up the diamond, but leads to another problem: monoids extend semigroups, so with the existing definition of monoid, we would have both ℕ+ powers and ℕ powers. If we wanted a [Pow M ℕ+]
instance from anything with [Pow M ℕ]
structure (this seems reasonable to me), this could lead to another diamond, unless we make the powers defeq.
Does this mean we need the monoid npow
to use the semigroup pnpow
somehow? I am inexperienced with instances and diamonds, so I don't see a good way out of this mess.
Eric Wieser (Nov 28 2023 at 21:07):
Scott Carnahan said:
If we wanted a
[Pow M ℕ+]
instance from anything with[Pow M ℕ]
structure (this seems reasonable to me)
This doesn't sound reasonable to me; we don't have anything analogous for Int
and Nat
powers. In general constructing data in a "backwards" way in typeclass search is a bad idea, and almost always leads to diamonds.
Riccardo Brasca (Nov 28 2023 at 21:12):
What we want is a theorem saying the two powers are compatible. And this will always hold.
Kevin Buzzard (Nov 28 2023 at 21:19):
I thought that @Jireh Loreaux has been saying for at least a year that we need to refactor semigroup
to add a field pnpow
?
Floris van Doorn (Nov 28 2023 at 21:19):
I know @Jireh Loreaux was also thinking about doing this, and started with this on branch#j-loreaux/ppow.
I am a bit worried about performance issues, and that the definition of group will contain 3 power operations...
Riccardo Brasca (Nov 28 2023 at 21:20):
Yes, this is not the first time the conversation pops up...
Eric Wieser (Nov 28 2023 at 21:41):
@Floris van Doorn: meanwhile for non-commutative (smul) cases I'm looking at doubling the number of power operations... So unless we let AddMonoid
and Monoid
diverge in terms of a 1:1 field mapping, they'll end up even bigger
Kevin Buzzard (Nov 28 2023 at 21:46):
Did the "add nsmul and zsmul to groups" PR give us a performance hit?
Jireh Loreaux (Nov 28 2023 at 22:04):
Yes, I did start on this on branch#j-loreaux/ppow, but it was causing performance issues, and I never finished getting it compiling (I can't remember how much was left to do). It's possible that it could be revived and those performance issues would go away because of more recent performance upgrades to master.
Jireh Loreaux (Nov 28 2023 at 22:05):
Also, we'll probably want the Pow M ℕ+
to be embedded in Mul
, not Semigroup
to allow for non-associative multiplications which are nevertheless power associative (we could have a mixin class IsPowAssoc
for that possibly). Likewise, we'll probably want to move Pow M ℕ
from Monoid
to MulOneClass
.
Jireh Loreaux (Nov 28 2023 at 22:05):
Ultimately though, I am worried about the sustainability of this approach. NormedField
and LinearOrderedField
in particular are absurdly large with this approach and with Eric's suggestions for non-commutativity, which I think are likely necessary.
Scott Carnahan (Nov 28 2023 at 22:50):
It's nice to see that someone else is working on it. I had tried the Pow M ℕ+
instance for semigroups in #8618 but I guess it needs to be deleted.
Floris van Doorn (Nov 28 2023 at 23:34):
Actually, I like the mixin approach, with the class [PNatPowAssoc M]
. Just leave out the instance instance [Semigroup M] : Pow M ℕ+
.
Does that scale? Are there diamond issues with that? I don't see any on first glance.
The main downside I see is that you have to write [Semigroup M] [Pow M ℕ+] [PNatPowAssoc M]
to talk about "semigroup with its power operation on ℕ+
". However, this will probably an uncommon enough operation that I don't think that is a huge problem. The main advantage is that we don't have to add more superfluous fields to the whole algebraic hierarchy.
Thoughts?
Kevin Buzzard (Nov 28 2023 at 23:36):
If "the main downside" is something which we can probably cover up with some coding hackery then this sounds great! Would this have worked for nsmul and zsmul? If not then what's the catch?
Floris van Doorn (Nov 28 2023 at 23:56):
I don't see a reason why it wouldn't work, but that is of course different than "this actually works". A difference is that nsmul and zmul will be used more often, so you more often have to write extra things.
Eric Wieser (Nov 29 2023 at 00:08):
A difference is that nsmul and zmul will be used more often, so you more often have to write extra things.
This is ultimately the tradeoff with many of these diamonds; either you have to add "obvious" fields to every instance of some basic algebraic structure, or every caller has to add extra "obvious" assumptions when they need them.
Note that using [AddCommGroup A] [Module Int A]
instead of adding zsmul
would not have worked, unless we were also willing to give up the [Semiring R] : Module R R
instance (otherwise we'd still get a diamond for Module Int Int
.
Jireh Loreaux (Nov 29 2023 at 00:49):
That's not the mixin approach I was suggesting. Instead, I meant that the data would be available from Mul
, including the Pow
instance, but the useful lemmas would only apply in the presence of an IsPowAssoc
instance.
Floris van Doorn (Nov 29 2023 at 02:35):
As a test, I refactored everything until Module.Basic
(except abel
) using my suggested approach, but for integer powers and integer smuls. This is in branch#group_pow_mixin. I'm quite sure this is doable for all of mathlib, if we want it. It makes some things a bit more verbose: you have to add some superfluous type-classes, like
[AddCommGroup M] [SMul ℤ M] [ZSMul M]
whenever you want to use the scalar multiplication with ℤ
. On all concrete types and type constructors, you have to add these as instances (though it is barely more work than the status quo, since usually you gave the zpow
field in the Group
instance. But we have fewer fields in DivInvMonoid
(and hence in all classes extending it).
We get the instance [AddCommGroup M] [SMul ℤ M] [ZSMul M] : Module ℤ M
, and this does not lead to any diamond issues:
example : Semiring.toModule (R := ℤ) = AddCommGroup.intModule ℤ := by
with_reducible_and_instances rfl -- works
I'm wondering how it would affect performance. I think it would be an improvement, but I don't know how much. Is there a way to test that without fixing all of mathlib?
Jireh Loreaux (Nov 29 2023 at 02:45):
But to actually get the lemmas we need a LawfulPow
class right?
Jireh Loreaux (Nov 29 2023 at 02:49):
Oh sorry, that's your ZPow
.
Jireh Loreaux (Nov 29 2023 at 18:27):
I have to say that I like this a lot, assuming it actually helps with performance, which is still TBD. Although I wonder whether it might not be better to make ZPow M
extend Pow M ℤ
instead. I don't think that would be problematic, and it would reduce clutter in statements.
Jireh Loreaux (Nov 29 2023 at 18:30):
@Floris van Doorn one way to test it which might be easier: instead of trying to pull zpow
out, we could try, starting from the same commit on master, adding ppow
in both ways. Although this may not serve as a realistic comparison.
Jireh Loreaux (Nov 29 2023 at 18:34):
The mixin approach has another advantage: due to the import hierarchy of low-level files, adding the ppow
field to Semigroup
had to look like:
ppow : ∀ n : ℕ, 0 < n → G → G := ppowRec
as opposed to the more natural
ppow : ℕ+ → G → G := ppowRec
because I couldn't import PNat
into Algebra.Group.Defs
.
With mixins, you can just declare them later.
Yaël Dillies (Nov 30 2023 at 00:23):
Sorry, why can't we just reuse pow
here?
Yaël Dillies (Nov 30 2023 at 00:23):
You can always send 0
to id
, as a junk value.
Yaël Dillies (Nov 30 2023 at 00:24):
Or is the problem somehow occurring for semigroups which are only sometimes monoids?
Eric Wieser (Nov 30 2023 at 08:10):
Yaël Dillies said:
You can always send
0
toid
, as a junk value.
If you do this, then you can't write Semigroup.ext without adding a meaningless assumption about junk values
Yaël Dillies (Nov 30 2023 at 08:40):
Out of all possible concerns being able to write Semigroup.ext
is definitely not the one I would have put forward.
Eric Wieser (Nov 30 2023 at 09:04):
I mean, it was the first thing that came to mind that expressed "semigroups would no longer be uniquely determined by their multiplication"
Jireh Loreaux (Dec 01 2023 at 04:29):
There's no reason to provide a junk value. The issue is only that the type signature doesn't look as clean as would be ideal, but that's a minor issue.
Floris van Doorn (Dec 01 2023 at 09:30):
Jireh Loreaux said:
There's no reason to provide a junk value. The issue is only that the type signature doesn't look as clean as would be ideal, but that's a minor issue.
We can always have a PNat.Defs
file where we define PNat
but do little else, and import this in Algebra.Group.Defs
.
Last updated: Dec 20 2023 at 11:08 UTC