Zulip Chat Archive
Stream: new members
Topic: multiset : convert prod of pow to pow of sum
Antoine Chambert-Loir (Jan 04 2022 at 09:42):
Does this exist somewhere in Mathlib ? Should it be added ?
import tactic
variables {M : Type*} [comm_monoid M]
lemma multiset.prod_pow_eq_pow_sum {m : multiset ℕ} {a : M} :
  (multiset.map (λ n, a^n) m).prod = a ^ (m.sum) :=
multiset.induction_on m (by simp) (λ n m h, by simp [h,pow_add])
Two questions by the way:
1) multiset.sum requires that one works in a comm_monoid (for obvious reasons), but here all objects involved belong to the commutative submonoid generated by a, so something should work for any monoid M, but what?
2) I expected to be able to use multiset.prod_hom. If M is a monoid, what is mathematically a member of ℕ →* M ?
Yaël Dillies (Jan 04 2022 at 09:42):
Might #10907 help? (I don't think so, because you're going from additive to multiplicative and those new lemmas each stay in the same world)
Eric Wieser (Jan 04 2022 at 09:46):
docs#powers_hom is the closest monoid_hom
Eric Wieser (Jan 04 2022 at 09:46):
Is docs#multiset.noncomm_prod the generalization you were looking for?
Antoine Chambert-Loir (Jan 04 2022 at 09:59):
Yes, it should be part of that, but I don't manage to make this work.
(On the other hand, I am really appalled at the idea that multiplicative \nat \to* Mis not a morphism from \nat as a multiplicative monoid to M.)
Eric Wieser (Jan 04 2022 at 10:05):
What do mean by "ℕ as a multiplicative monoid" if not multiplicative ℕ? Do you just mean ℕ?
Johan Commelin (Jan 04 2022 at 10:06):
@Antoine Chambert-Loir Don't you just want ℕ →* M?
Johan Commelin (Jan 04 2022 at 10:07):
multiplicative ℕ is the monoid of symbols {x^n | n ∈ ℕ}. With multiplication x^m * x^n = x^(m+n).
Johan Commelin (Jan 04 2022 at 10:07):
Or maybe I'm misunderstanding what you want...
Kevin Buzzard (Jan 04 2022 at 10:20):
multiplicative nat means "treat nat as a monoid with group law which is mathematically + but now which is written with notation *"
Antoine Chambert-Loir (Jan 04 2022 at 10:25):
If you talk to me of “ℕ as a multiplicative monoid”, I will understand nonnegative integers with product.
Antoine Chambert-Loir (Jan 04 2022 at 10:29):
I had tried Johan's suggestion, but I got this:
lemma test {m : multiset ℕ} {f : ℕ →* M}  :  (multiset.map f m).prod = f (m.sum) :=
begin
  rw multiset.prod_hom ,
-- needs to prove ⇑f m.prod = ⇑f m.sum
sorry,
end
Yaël Dillies (Jan 04 2022 at 10:29):
refl!
Kevin Buzzard (Jan 04 2022 at 10:29):
"ℕ as a multiplicative monoid' is just called ℕ in mathlib
Kevin Buzzard (Jan 04 2022 at 10:31):
No not refl, this lemma looks false to me
Kevin Buzzard (Jan 04 2022 at 10:31):
->* means "preserves multiplication"
Kevin Buzzard (Jan 04 2022 at 10:32):
multiplicative X means "turn this additive monoid into a multiplicative monoid by defining multiplication to be addition"
Johan Commelin (Jan 04 2022 at 10:32):
• ℕ is a monoid and an add_monoid.
• multiplicative ℕ is the additive monoid ℕ, but viewed as multiplicative monoid, so with notation *.
• additive ℕ is the multiplicative monoid ℕ, but viewed as additive monoid, so with notation +.
Damiano Testa (Jan 04 2022 at 10:36):
I am not sure if this will help, but multiplicative ℕis Lean's way of dealing with, for instance, the submonoid of  generated by .  The submonoid is isomorphic to , but the group operation is multiplication.
I hope that this helps!
Antoine Chambert-Loir (Jan 04 2022 at 10:49):
This is irrelevant to my question, but how does one summonℕ as a monoid with multiplication of integers ?
Yaël Dillies (Jan 04 2022 at 10:50):
docs#nat.comm_monoid (assuming you mean multiplication of naturals, not multiplication of integers)
Johan Commelin (Jan 04 2022 at 10:51):
@Antoine Chambert-Loir By doing nothing. That's the default.
Johan Commelin (Jan 04 2022 at 10:52):
In informal maths, we infer a lot about what's going on, by choosing suggestive notation. You can quickly drive someone crazy by using ▸ and ↑ as the two binary operations in a random ring.
Johan Commelin (Jan 04 2022 at 10:52):
To counter this, in mathlib you can only use * and + for ring operations.
Johan Commelin (Jan 04 2022 at 10:52):
This is unfortunate, because it means you cannot use ∘ for endomorphism rings.
Johan Commelin (Jan 04 2022 at 10:53):
But in practice, this seems to be only a minor downside.
Johan Commelin (Jan 04 2022 at 10:55):
The other two downsides are:
- you have to develop the theory of monoids and groups twice: once for *and once for+. But the tacticto_additivetakes care of the duplication, so it's not a very big problem
- you cannot have group/monoid homomorphisms G → HifGuses*-notation andHuses+-notation. This is where the "switch notation" type wrappersadditiveandmultiplicativecome in. Because you can have a*-preserving monoid homG →* multiplicative H.
Johan Commelin (Jan 04 2022 at 10:55):
Altogether, I find this philosophically very unsatisfactory. But in practice it works very well.
Johan Commelin (Jan 04 2022 at 10:56):
I've spent many hours dreaming about a better way to tackle the issue. But if you try to do the "mathematically" correct thing, I can never save the nice notation that we have now. And giving up + and * seems too big a price to pay.
Johan Commelin (Jan 04 2022 at 10:57):
So, long story short. By default + on ℕ means the addition you are used to. And * means the multiplication that you expect.
Johan Commelin (Jan 04 2022 at 10:57):
And Lean can handle both at the same time, because it has two duplicated hierarchies of semigroups/monoids/groups: one for + and one for *.
Stuart Presnell (Jan 04 2022 at 11:22):
And, importantly here, when you’re using nat in a way that uses its multiplicative structure you can just write nat and Lean knows what you mean — right?
Stuart Presnell (Jan 04 2022 at 11:24):
i.e. you don’t write something like (nat, *, 1)
Antoine Chambert-Loir (Jan 04 2022 at 11:31):
OK. I understand that  if I talk about multiplicative \nat (as a monoid), I get natural numbers and the law is addition written *, while if a talk about \nat (again as a monoid), I get natural numbers with multiplication denoted *.
Antoine Chambert-Loir (Jan 04 2022 at 11:33):
@Johan Commelin What I find unsatisfactory is the use of the adjective multiplicative to mean the opposite of what (I believe) we (I) would say in math. Otherwise, I think I understand the issues you describe.
Antoine Chambert-Loir (Jan 04 2022 at 11:34):
Maybe multiplicativelyand additivelywould be better. But I'm nothing here to revert terminology.
Johan Commelin (Jan 04 2022 at 11:45):
@Antoine Chambert-Loir That makes sense.
Johan Commelin (Jan 04 2022 at 11:45):
I guess, in a context where a type doesn't have both notations yet, it would be less confusing. Say, you have some abstract additive group G. Then multiplicative G is probably unambiguous.
Eric Wieser (Jan 04 2022 at 15:46):
What's going on here?
import algebra.big_operators.basic
import algebra.group_power.lemmas
variables {α : Type*} [comm_monoid α]
lemma prod_pow_eq_pow_sum {m : multiset ℕ} {a : α} :
  (multiset.map (λ n, a^n) m).prod = a ^ m.sum :=
-- multiset.induction_on m (by simp) (λ n m h, by simp [h,pow_add])
begin
  have := @multiset.prod_hom (multiplicative ℕ) α _ _ (m.map multiplicative.of_add) _,
  swap,
  convert powers_hom α a,  -- exact fails
  dunfold multiplicative.mul_one_class has_one.one,  -- fails without this
  refl,
  sorry
end
Why do I have to unfold has_one.one to get lean to see the instances are equal?
Eric Wieser (Jan 04 2022 at 15:55):
Kevin Buzzard (Jan 04 2022 at 16:37):
ext, refl works after the convert, so this is something to do with equality of structures. If you make the terms involved directly then it seems to work fine:
example : true :=
begin
  let X : mul_one_class.{0} (multiplicative.{0} nat) :=
    @monoid.to_mul_one_class.{0}
      (multiplicative.{0} nat)
      (@comm_monoid.to_monoid.{0} (multiplicative.{0} nat) (@multiplicative.comm_monoid.{0} nat nat.add_comm_monoid)),
  let Y : mul_one_class.{0} (multiplicative.{0} nat) :=
    @multiplicative.mul_one_class.{0} nat (@add_monoid.to_add_zero_class.{0} nat nat.add_monoid),
  let Z : mul_one_class.{0} (multiplicative.{0} nat) := @mul_one_class.mk.{0} (multiplicative.{0} nat)
  (@coe_fn.{1 1} (equiv.{1 1} nat (multiplicative.{0} nat))
     (λ (_x : equiv.{1 1} nat (multiplicative.{0} nat)), nat → multiplicative.{0} nat)
     (@equiv.has_coe_to_fun.{1 1} nat (multiplicative.{0} nat))
     (@multiplicative.of_add.{0} nat)
     (@has_zero.zero.{0} nat
        (@add_zero_class.to_has_zero.{0} nat (@add_monoid.to_add_zero_class.{0} nat nat.add_monoid))))
  (@has_mul.mul.{0} (multiplicative.{0} nat)
     (@multiplicative.has_mul.{0} nat
        (@add_zero_class.to_has_add.{0} nat (@add_monoid.to_add_zero_class.{0} nat nat.add_monoid))))
  (@multiplicative.mul_one_class._proof_1.{0} nat (@add_monoid.to_add_zero_class.{0} nat nat.add_monoid))
  (@multiplicative.mul_one_class._proof_2.{0} nat (@add_monoid.to_add_zero_class.{0} nat nat.add_monoid)),
  have h1 : X = Z,
    refl,
  have h2 : Y = Z,
    refl,
  have h3 : X = Y,
    refl,
  trivial,
end
Eric Wieser (Jan 04 2022 at 16:48):
Reid's diagnosis in the other thread is that this is an elaborator bug
Last updated: May 02 2025 at 03:31 UTC