Skip to content

Commit 69ebb74

Browse files
committed
perf(Algebra/IsPrimePow): speed up decidability for Nat IsPrimePow (#30093)
Previously, this decidability instance was defined using `isPrimePow_nat_iff_bounded`, which (as I understand it) means that it undertook a search over all pairs `p, k` of numbers below `n` until it finds one where `p` is prime, and `p^k = n`, or else loops through all possibilities. This PR creates a new theorem which instead searches over possible values of the exponent first, bounding the search at the binary logarithm of `n`, and then a further theorem which uses `n.minFac` for `p`. This massively reduces the time for large `n`. In principle this could be made polynomial time, if we were to compute the putative prime factor for each `k` by taking the `k`th root and checking primality with AKS. But until that is implemented, this seems like a fine improvement.
1 parent 12fc3da commit 69ebb74

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

Mathlib/Algebra/IsPrimePow.lean

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Authors: Bhavik Mehta
66
import Mathlib.Algebra.Order.Ring.Nat
77
import Mathlib.Order.Nat
88
import Mathlib.Data.Nat.Prime.Basic
9+
import Mathlib.Data.Nat.Log
10+
import Mathlib.Data.Nat.Prime.Pow
911

1012
/-!
1113
# Prime powers
@@ -76,8 +78,37 @@ theorem isPrimePow_nat_iff_bounded (n : ℕ) :
7678
conv => { lhs; rw [← (pow_one p)] }
7779
exact Nat.pow_le_pow_right hp.one_lt.le hk
7880

81+
theorem isPrimePow_nat_iff_bounded_log (n : ℕ) :
82+
IsPrimePow n
83+
↔ ∃ k : ℕ, k ≤ Nat.log 2 n ∧ 0 < k ∧ ∃ p : ℕ, p ≤ n ∧ n = p ^ k ∧ p.Prime := by
84+
rw [isPrimePow_nat_iff]
85+
constructor
86+
· rintro ⟨p, k, hp', hk', rfl⟩
87+
refine ⟨k, ?_, hk', ⟨p, Nat.le_pow hk', rfl, hp'⟩⟩
88+
· calc
89+
k = Nat.log 2 (2 ^ k) := by simp
90+
_ ≤ Nat.log 2 (p ^ k) := Nat.log_mono Nat.one_lt_two Nat.AtLeastTwo.prop
91+
(Nat.pow_le_pow_left (Nat.Prime.two_le hp') k)
92+
· rintro ⟨k, hk, hk', ⟨p, hp, rfl, hp'⟩⟩
93+
exact ⟨p, k, hp', hk', rfl⟩
94+
95+
theorem isPrimePow_nat_iff_bounded_log_minFac (n : ℕ) :
96+
IsPrimePow n
97+
↔ ∃ k : ℕ, k ≤ Nat.log 2 n ∧ 0 < k ∧ n = n.minFac ^ k := by
98+
rw [isPrimePow_nat_iff_bounded_log]
99+
obtain rfl | h := eq_or_ne n 1
100+
· simp
101+
constructor
102+
· rintro ⟨k, hkle, hk_pos, p, hle, heq, hprime⟩
103+
refine ⟨k, hkle, hk_pos, ?_⟩
104+
rw [heq, hprime.pow_minFac hk_pos.ne']
105+
· rintro ⟨k, hkle, hk_pos, heq⟩
106+
refine ⟨k, hkle, hk_pos, n.minFac, Nat.minFac_le ?_, heq, ?_⟩
107+
· grind [Nat.minFac_prime_iff, nonpos_iff_eq_zero, Nat.log_zero_right, lt_self_iff_false]
108+
· grind [Nat.minFac_prime_iff]
109+
79110
instance {n : ℕ} : Decidable (IsPrimePow n) :=
80-
decidable_of_iff' _ (isPrimePow_nat_iff_bounded n)
111+
decidable_of_iff' _ (isPrimePow_nat_iff_bounded_log_minFac n)
81112

82113
theorem IsPrimePow.dvd {n m : ℕ} (hn : IsPrimePow n) (hm : m ∣ n) (hm₁ : m ≠ 1) : IsPrimePow m := by
83114
grind [isPrimePow_nat_iff, Nat.dvd_prime_pow, Nat.pow_eq_one]

0 commit comments

Comments
 (0)