Zulip Chat Archive
Stream: mathlib4
Topic: fixing maxPowDiv
Cookie Guy (Feb 02 2026 at 05:01):
So I was working on a proof which required me to calculate various p-adic valuations. Sadly, p-adic valuations are noncomputable, butthankfully, mathlib provides padicValNat.maxPowDiv_eq_multiplicity ... : p.maxPowDiv n = multiplicity p n
however, even after rewriting to maxPowDiv, lean still doesnt seem to work nicely with it, for example
lean cant prove example : Nat.maxPowDiv 5 125 = 3 := by rfl, looking into maxPowDiv, I see the definition
def maxPowDiv (p n : ℕ) : ℕ :=
go 0 p n
where go (k p n : ℕ) : ℕ :=
if 1 < p ∧ 0 < n ∧ n % p = 0 then
go (k+1) p (n / p)
else
k
termination_by n
decreasing_by apply Nat.div_lt_self <;> tauto
it seems that the decreasing_by proof makes it a bit less to reduce in the kernel, so as an experiment, i try giving it fuel instead
def maxPowDiv' (p n : ℕ) : ℕ := go n 0 p n
where go (fuel : ℕ) (k p n : ℕ) : ℕ :=
match fuel with
| 0 => k
| fuel' + 1 =>
if 1 < p ∧ 0 < n ∧ n % p = 0 then
go fuel' (k + 1) p (n / p)
else
k
and suddenly we can do
example : maxPowDiv' 5 125 = 3 := by rfl
I am wondering if there is no reason apart from deprecation to not change to this definition for its nicer kernel properties?
Yury G. Kudryashov (Feb 02 2026 at 05:05):
I have a branch that tries to migrate to a similar definition, but I have no time to polish it for a review.
Yury G. Kudryashov (Feb 02 2026 at 05:06):
Let me open a draft PR.
Yury G. Kudryashov (Feb 02 2026 at 05:08):
See #34711
Yury G. Kudryashov (Feb 02 2026 at 05:14):
Do you want to take over that PR? If yes, then probably the way to go is to create a branch in your fork based on my PR, then open a PR to master, and mention my PR.
Cookie Guy (Feb 02 2026 at 05:17):
Ok, that sounds good.
I was also thinking about creating a simproc for padicValNat to reduce using maxPowDvd, so let me work on creating that too
Yury G. Kudryashov (Feb 02 2026 at 05:27):
We use norm_num for simplifying functions about numbers.
Yury G. Kudryashov (Feb 02 2026 at 05:28):
I.e., you should probably write a norm_num plugin instead of a simproc.
Yury G. Kudryashov (Feb 02 2026 at 06:26):
But the first PR should include just #34711 + cleanup:
- make linters happy (probably, by removing some
simpattrs) - add missing docstrings, if any
- restore old defs and lemmas, probably as deprecated aliases.
Any work on meta code for computing padicValNat should go into a PR stacked on top of the first one.
Yuyang Zhao (Feb 02 2026 at 06:58):
After lean4#7965 fuel is no longer needed.
Yuyang Zhao (Feb 02 2026 at 07:02):
import Mathlib
attribute [local semireducible] Nat.maxPowDiv.go
example : Nat.maxPowDiv 5 125 = 3 := by rfl
Yury G. Kudryashov (Feb 02 2026 at 15:18):
I wrote #34711 before that, then I was too lazy to adjust the proofs to a non-fuel def.
Yury G. Kudryashov (Feb 03 2026 at 06:08):
@Cookie Guy Are you going to work on this? If no, then I may have a go next weekend.
Yury G. Kudryashov (Feb 20 2026 at 20:04):
How can I check (other than @[semireducible] being accepted w/o a warning) that lean4#7965 worked on a definition? Is it visible in the #print output?
Yury G. Kudryashov (Feb 20 2026 at 20:17):
Answering myself by looking at the source: it uses WellFounded.Nat.fix instead of a generic well-founded fixpoint function.
Last updated: Feb 28 2026 at 14:05 UTC