Zulip Chat Archive
Stream: new members
Topic: Prove decidable statement by evaluation
Jack Valmadre (Sep 09 2023 at 15:01):
Hi! For a proof that I'm writing, I need to prove that a list of numbers are prime:
def nums := [2, 3, 5, 7, 13, 23, 43, 83, 163, 317, 631, 1259, 2503, 4001]
I can check this myself using:
#eval to_bool (list.all₂ nat.prime nums)
Is there a way to turn this into a proof by evaluation?
lemma nums_prime : list.all₂ nat.prime nums := ??
Alex J. Best (Sep 09 2023 at 15:14):
Looks like you are using lean 3 which is now end of life, I definitely recommend you switch to lean 4 which has lots of nice new features (including some that would probably make answering this easier).
That said if you want to prove numbers prime its better to use the dedicated norm_num extension rather than try and have the kernel do it.
import tactic
import data.nat.prime
import data.nat.prime_norm_num
def nums := [2, 3, 5, 7, 13, 23, 43, 83, 163, 317, 631, 1259, 2503, 4001]
#eval to_bool (list.all₂ nat.prime nums)
lemma nums_prime : list.all₂ nat.prime nums :=
begin
rw nums,
norm_num,
end
Bolton Bailey (Sep 09 2023 at 21:25):
You can see how this was done for the proof of Bertrand's postulate in docs#Nat.bertrand. (This list of primes looks suspiciously similar to yours, so beware of spoilers).
Jack Valmadre (Sep 10 2023 at 01:13):
Thank you! norm_num
with import data.nat.prime_norm_num
worked perfectly. I'll move to Lean 4. And thanks for the spoiler warning - that's exactly the theorem that I'm proving as an exercise :)
Jack Valmadre (Sep 10 2023 at 02:34):
Do you know if there is something similar for list.sorted
? It works with #eval to_bool ...
but neither of these worked:
import tactic
import data.list
def nums := [2, 3, 5, 7, 13, 23, 43, 83, 163, 317, 631, 1259, 2503, 4001]
#eval to_bool (list.sorted nat.lt nums)
lemma sorted_nums : list.sorted nat.lt nums :=
begin
rw nums,
norm_num, -- slow (n^2?); does not evaluate inequalities
sorry,
end
lemma eq_insertion_sort_nums : nums = list.insertion_sort nat.lt nums :=
begin
rw nums,
simp,
norm_num, -- failed to simplify
end
I think I need norm_num.eval_ineq
with expr.lt
but I'm not sure how to use it.
Jack Valmadre (Sep 10 2023 at 03:08):
Update: I was able to solve it using refl
although it does seem a bit slow. Is this an acceptable way to do it? (Had to switch from lt
to le
to have total ordering for list.sorted_insertion_sort
)
lemma nums_eq_insertion_sort_self : nums = list.insertion_sort nat.le nums :=
begin
rw nums,
refl,
end
lemma sorted_nums : list.sorted nat.le nums :=
begin
rw nums_eq_insertion_sort_self,
apply list.sorted_insertion_sort,
end
Kevin Buzzard (Sep 10 2023 at 07:02):
Doing anything new in lean 3 is not really an acceptable way to do it any more
Jack Valmadre (Sep 10 2023 at 08:43):
OK, sounds good. Thanks for the responses!
Kevin Buzzard (Sep 10 2023 at 08:48):
More precisely, I mean "nobody is going to be motivated to work on fixing something which is slow in Lean 3" because there is an obvious fix for this.
Jack Valmadre (Sep 10 2023 at 08:53):
Ah ok, makes sense, thank you!
Jack Valmadre (Sep 11 2023 at 21:16):
Hi! I'm now trying to do the same thing in Lean 4: I would like to prove List.All₂ Nat.Prime nums
where nums
is a list of 14 primes. #eval decide ...
is fast but proving with norm_num
times out (even after importing Mathlib.Tactic.NormNum.Prime
). Is there an easy way to achieve this? Thanks!
import Mathlib.Data.List.Defs
import Mathlib.Data.Nat.Prime
import Mathlib.Tactic.NormNum
import Mathlib.Tactic.NormNum.Prime
def nums := [2, 3, 5, 7, 13, 23, 43, 83, 163, 317, 631, 1259, 2503, 4001]
-- Fast
#eval decide (List.All₂ Nat.Prime nums)
-- Fast
lemma largest : Nat.Prime 4001 := by norm_num
-- Slow (maximum number of heartbeats (200000) has been reached)
lemma allPrimeNums : List.All₂ Nat.Prime nums := by
rw [nums]
norm_num
Kevin Buzzard (Sep 11 2023 at 21:19):
simp
is timing out, it seems.
lemma allPrimeNums : List.All₂ Nat.Prime nums := by
simp [nums] -- deterministic timeout
Mario Carneiro (Sep 11 2023 at 21:20):
I think it is using decide
Mario Carneiro (Sep 11 2023 at 21:20):
this works:
lemma allPrimeNums : List.All₂ Nat.Prime nums := by
simp (config := {decide := false}) only [nums, List.All₂]
norm_num1
simp
Kevin Buzzard (Sep 11 2023 at 21:23):
This doesn't:
lemma not_largest : Nat.Prime 317 := by norm_num -- timeout
Mario Carneiro (Sep 11 2023 at 21:24):
here's a slightly more manual version:
lemma allPrimeNums : List.All₂ Nat.Prime nums := by
iterate 13 refine ⟨by norm_num1, ?_⟩
simp; norm_num1
Kevin Buzzard (Sep 11 2023 at 21:24):
lemma allPrimeNums : List.All₂ Nat.Prime nums := by
simp (config := {decide := false})
constructor; norm_num
constructor; norm_num
constructor; norm_num
constructor; norm_num
constructor; norm_num
constructor; norm_num
constructor; norm_num
constructor; norm_num
constructor; norm_num
constructor; sorry -- ignore 317
constructor; norm_num
constructor; norm_num
constructor; norm_num
norm_num
Damiano Testa (Sep 11 2023 at 21:24):
317 is the new 37...
Kevin Buzzard (Sep 11 2023 at 21:25):
norm_num1
does 317 shrug
Damiano Testa (Sep 11 2023 at 21:25):
I see a pattern here.
Mario Carneiro (Sep 11 2023 at 21:27):
By the way, this list of primes looks familiar: are you aware that mathlib has a proof of Bertrand's postulate?
Kevin Buzzard (Sep 11 2023 at 21:28):
Indeed Jack is: https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/Prove.20decidable.20statement.20by.20evaluation/near/390081954
Mario Carneiro (Sep 11 2023 at 21:29):
It appears that for the numbers less than 317
, the proof generated by norm_num looks like of_eq_true (eq_true_of_decide (Eq.refl true))
, and for the ones greater than it it produces
of_eq_true
(eq_true
(Mathlib.Meta.NormNum.isNat_prime_2 (Mathlib.Meta.NormNum.isNat_ofNat ℕ (Eq.refl 631)) (Eq.refl true)
(Mathlib.Meta.NormNum.isNat_minFac_4 (Mathlib.Meta.NormNum.IsNat.raw_refl 631)
(Mathlib.Meta.NormNum.minFacHelper_2 (Eq.refl 27)
(Mathlib.Meta.NormNum.not_prime_mul_of_ble 5 5 25 (Eq.refl 25) (Eq.refl false) (Eq.refl false))
...
In other words, simp is using decide sometimes and just giving up and letting norm_num core have a shot when it gets too hard
Mario Carneiro (Sep 11 2023 at 21:30):
and 317
seems to be just on the edge where decide
thinks it can take it but it can't really
Damiano Testa (Sep 11 2023 at 21:53):
Btw, for numbers of the form 311...17
, every third one is divisible by 3
, the next one is divisible by 37
, of the remaining ones, 317
is prime and then they are all composite at least until 311111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111117
, although a formal proof of this fact is lacking.
Jack Valmadre (Sep 11 2023 at 21:57):
Thanks very much! That's interesting! I'll use the config := {decide := false}
and norm_num1
approach :+1:
Kevin Buzzard (Sep 11 2023 at 22:04):
311111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111117
is prime.
Richard Copley (Sep 11 2023 at 22:13):
The next two primes in the sequence are (28/9)(10^692-1)+9 and (28/9)(10^1805-1)+9.
Mario Carneiro (Sep 11 2023 at 22:16):
#7112 (sadly not a prime) implements norm_num (config := ...)
so you should be able to do this with just norm_num (config := {decide := false}) [nums, List.All₂]
Last updated: Dec 20 2023 at 11:08 UTC