Skip to content

feat: NSMul/NPow type class#38036

Open
JovanGerb wants to merge 15 commits intoleanprover-community:masterfrom
JovanGerb:Jovan-NSMul
Open

feat: NSMul/NPow type class#38036
JovanGerb wants to merge 15 commits intoleanprover-community:masterfrom
JovanGerb:Jovan-NSMul

Conversation

@JovanGerb
Copy link
Copy Markdown
Contributor

@JovanGerb JovanGerb commented Apr 14, 2026

This PR is adds NSMul, NPow, ZSMul and ZPow classes for the nsmul, npow, zsmul, zpow data fields.

This has a few advantages:

  • If you first declare a SMul instance, then you don't need to manually write nsmul := (· • ·) and zsmul := (· • ·) . For Pow, the extra benefit is that inferring the instance is preferred over the default field npowRecAuto. So this helps avoid accidental diamonds.
  • If you first declare a SMul instance on a type synonym, then inferInstanceAs will infer the nsmul field from the SMul instance. This makes it easier to avoid diamonds on type synonyms like Matrix and MonoidAlgebra.
  • The not-yet-merged instance diamond linter will be able to detect cases where the NSMul and SMul classes do not agree.

In the process of making this PR, I have identified two existing NPow diamonds:

  • In Mathlib.Algebra.Order.Positive.Field, there were two conflicting NPow instances.
  • For Fin, there are two conflicting NPow instances. I have overwritten the one in core lean with the one from mathlib that is more computationally efficient.

TODO: the same for QSMul and NNQSMul.


Open in Gitpod

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 14, 2026

PR summary 4fceb4697e

Import changes for modified files

No significant changes to the import graph

Import changes for all files
Files Import difference

Declarations diff

+ NPow
+ NPow.ofPow
+ NPow.toPow
+ NSMul
+ ZPow
+ ZPow.ofPow
+ ZPow.toPow
+ ZSMul
+ instance (n : ℕ) [NeZero n] : HPow (Fin n) ℕ (Fin n)
+ instance (n : ℕ) [NeZero n] : Pow (Fin n) ℕ
+ instance {A : Type*} [SMulZeroClass A R] : SMul A R[M]
- DivInvMonoid.toZPow
- Monoid.toPow
- SubNegMonoid.toZSMul
-++- addGroup

You can run this locally as follows
## summary with just the declaration names:
./scripts/pr_summary/declarations_diff.sh <optional_commit>

## more verbose report:
./scripts/pr_summary/declarations_diff.sh long <optional_commit>

The doc-module for scripts/pr_summary/declarations_diff.sh contains some details about this script.


Decrease in tech debt: (relative, absolute) = (1.04, 0.03)
Current number Change Type
6219 1 backward.isDefEq.respectTransparency
795 -2 backward.privateInPublic
412 -1 backward.privateInPublic.warn
46 -1 dsimp +instances

Current commit dcf7b585bf
Reference commit 4fceb4697e

You can run this locally as

./scripts/reporting/technical-debt-metrics.sh pr_summary
  • The relative value is the weighted sum of the differences with weight given by the inverse of the current value of the statistic.
  • The absolute value is the relative value divided by the total sum of the inverses of the current values (i.e. the weighted average of the differences).

@JovanGerb JovanGerb added the WIP Work in progress label Apr 14, 2026
@eric-wieser
Copy link
Copy Markdown
Member

Could you elaborate on the benefit here?

@eric-wieser
Copy link
Copy Markdown
Member

  • If you first declare a SMul instance, then you don't need to manually write nsmul := (· • ·) and zsmul := (· • ·) .

This can also be achieved with [toNatSMul : SMul Nat A] as a field.

@JovanGerb
Copy link
Copy Markdown
Contributor Author

JovanGerb commented Apr 14, 2026

Sure, but then you lose the ability to write nsmul := ..., and instead you have to write some awkward toNSMul := ⟨...⟩

Comment thread Mathlib/Algebra/Group/Defs.lean Outdated
@[to_additive] instance addCommMonoid : AddCommMonoid R[M] :=
fast_instance% { (inferInstance : AddCommMonoid <| M →₀ R) with
nsmul n x := x.mapRange (n • ·) (smul_zero _) }
inferInstanceAs <| AddCommMonoid <| M →₀ R
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened to fast_instance%?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the great thing: inferInstanceAs will automatically fill in the nsmul field using the smul that was was declared above. (Recall that inferInstanceAs and fast_instance% do the same kind of instance normalization). Previously, we had to awkwardly declare the nsmul field in order to avoid diamond.

I think this should also answer your other question: yes we do need to infer NSMul instances from SMul instances, for example here.

@JovanGerb
Copy link
Copy Markdown
Contributor Author

!bench

@leanprover-radar
Copy link
Copy Markdown

leanprover-radar commented Apr 15, 2026

Benchmark results for 12eaeea against 0446312 are in. There are significant results. @JovanGerb

  • 🟥 build//instructions: +319.8G (+0.19%)

Large changes (1✅, 4🟥)

  • 🟥 build/module/Mathlib.Analysis.CStarAlgebra.Fuglede//instructions: +20.8G (+40.83%)
  • 🟥 build/module/Mathlib.Analysis.SpecialFunctions.Log.Deriv//instructions: +9.1G (+13.23%)
  • 🟥 build/module/Mathlib.CategoryTheory.Triangulated.TriangleShift//instructions: +39.1G (+21.23%)
  • 🟥 build/module/Mathlib.NumberTheory.Harmonic.GammaDeriv//instructions: +8.4G (+23.20%)
  • build/module/Mathlib.RingTheory.Polynomial.UniversalFactorizationRing//instructions: -47.0G (-16.88%)

Medium changes (16✅, 10🟥)

Too many entries to display here. View the full report on radar instead.

Small changes (39✅, 69🟥)

Too many entries to display here. View the full report on radar instead.

@JovanGerb
Copy link
Copy Markdown
Contributor Author

!bench

@leanprover-radar
Copy link
Copy Markdown

leanprover-radar commented Apr 15, 2026

Benchmark results for 604ad3b against 0446312 are in. There are significant results. @JovanGerb

  • 🟥 build//instructions: +320.1G (+0.19%)

Large changes (1✅, 4🟥)

  • 🟥 build/module/Mathlib.Analysis.CStarAlgebra.Fuglede//instructions: +20.8G (+40.81%)
  • 🟥 build/module/Mathlib.Analysis.SpecialFunctions.Log.Deriv//instructions: +9.1G (+13.21%)
  • 🟥 build/module/Mathlib.CategoryTheory.Triangulated.TriangleShift//instructions: +39.1G (+21.19%)
  • 🟥 build/module/Mathlib.NumberTheory.Harmonic.GammaDeriv//instructions: +8.4G (+23.24%)
  • build/module/Mathlib.RingTheory.Polynomial.UniversalFactorizationRing//instructions: -47.1G (-16.90%)

Medium changes (16✅, 11🟥)

Too many entries to display here. View the full report on radar instead.

Small changes (38✅, 68🟥)

Too many entries to display here. View the full report on radar instead.

@JovanGerb
Copy link
Copy Markdown
Contributor Author

It's curious how some files sped up while others slowed down. Maybe this change made some instances better - hence the speedup. But because of the extra extends, the structures are now a bit bigger, and hence unification takes longer (due to the exponentially slow unification thingy)

@JovanGerb
Copy link
Copy Markdown
Contributor Author

!bench

@leanprover-radar
Copy link
Copy Markdown

leanprover-radar commented Apr 20, 2026

Benchmark results for dcf7b58 against 4fceb46 are in. There are significant results. @JovanGerb

  • 🟥 build//instructions: +319.9G (+0.18%)

Large changes (1✅, 4🟥)

  • 🟥 build/module/Mathlib.Analysis.CStarAlgebra.Fuglede//instructions: +20.8G (+40.83%)
  • 🟥 build/module/Mathlib.Analysis.SpecialFunctions.Log.Deriv//instructions: +9.1G (+13.25%)
  • 🟥 build/module/Mathlib.CategoryTheory.Triangulated.TriangleShift//instructions: +38.3G (+20.71%)
  • 🟥 build/module/Mathlib.NumberTheory.Harmonic.GammaDeriv//instructions: +8.3G (+23.04%)
  • build/module/Mathlib.RingTheory.Polynomial.UniversalFactorizationRing//instructions: -50.3G (-16.96%)

Medium changes (14✅, 16🟥)

Too many entries to display here. View the full report on radar instead.

Small changes (42✅, 69🟥)

Too many entries to display here. View the full report on radar instead.

@JovanGerb JovanGerb removed the WIP Work in progress label Apr 21, 2026

Note that `MulOpposite.smul` is provided in an earlier file as it is needed to
provide the `AddMonoid.nsmul` and `AddCommGroup.zsmul` fields.
provide the `NSMul.nsmul` and `AddCommGroup.zsmul` fields.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be

Suggested change
provide the `NSMul.nsmul` and `AddCommGroup.zsmul` fields.
provide the `NSMul.nsmul` and `ZSMul.zsmul` fields.


Note that `MulOpposite.smul` is provided in an earlier file as it is needed to
provide the `AddMonoid.nsmul` and `AddCommGroup.zsmul` fields.
provide the `NSMul.nsmul` and `AddCommGroup.zsmul` fields.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
provide the `NSMul.nsmul` and `AddCommGroup.zsmul` fields.
provide the `NSMul.nsmul` and `ZSMul.zsmul` fields.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants