@@ -8,6 +8,7 @@ import data.nat.sqrt
8
8
import data.nat.gcd
9
9
import algebra.group_power
10
10
import tactic.wlog
11
+ import tactic.norm_num
11
12
12
13
/-!
13
14
# Prime numbers
@@ -589,7 +590,7 @@ namespace primes
589
590
instance : has_repr nat.primes := ⟨λ p, repr p.val⟩
590
591
instance : inhabited primes := ⟨⟨2 , prime_two⟩⟩
591
592
592
- instance coe_nat : has_coe nat.primes ℕ := ⟨subtype.val⟩
593
+ instance coe_nat : has_coe nat.primes ℕ := ⟨subtype.val⟩
593
594
594
595
theorem coe_nat_inj (p q : nat.primes) : (p : ℕ) = (q : ℕ) → p = q :=
595
596
λ h, subtype.eq h
@@ -599,3 +600,170 @@ end primes
599
600
instance monoid.prime_pow {α : Type *} [monoid α] : has_pow α primes := ⟨λ x p, x^p.val⟩
600
601
601
602
end nat
603
+
604
+ /-! ### Primality prover -/
605
+
606
+ namespace tactic
607
+ namespace norm_num
608
+ open norm_num
609
+
610
+ lemma not_prime_helper (a b n : ℕ)
611
+ (h : a * b = n) (h₁ : 1 < a) (h₂ : 1 < b) : ¬ nat.prime n :=
612
+ by rw ← h; exact nat.not_prime_mul h₁ h₂
613
+
614
+ lemma is_prime_helper (n : ℕ)
615
+ (h₁ : 1 < n) (h₂ : nat.min_fac n = n) : nat.prime n :=
616
+ nat.prime_def_min_fac.2 ⟨h₁, h₂⟩
617
+
618
+ lemma min_fac_bit0 (n : ℕ) : nat.min_fac (bit0 n) = 2 :=
619
+ by simp [nat.min_fac_eq, show 2 ∣ bit0 n, by simp [bit0_eq_two_mul n]]
620
+
621
+ /-- A predicate representing partial progress in a proof of `min_fac`. -/
622
+ def min_fac_helper (n k : ℕ) : Prop :=
623
+ 0 < k ∧ bit1 k ≤ nat.min_fac (bit1 n)
624
+
625
+ theorem min_fac_helper.n_pos {n k : ℕ} (h : min_fac_helper n k) : 0 < n :=
626
+ nat.pos_iff_ne_zero.2 $ λ e,
627
+ by rw e at h; exact not_le_of_lt (nat.bit1_lt h.1 ) h.2
628
+
629
+ lemma min_fac_ne_bit0 {n k : ℕ} : nat.min_fac (bit1 n) ≠ bit0 k :=
630
+ by rw bit0_eq_two_mul; exact λ e, absurd
631
+ ((nat.dvd_add_iff_right (by simp [bit0_eq_two_mul n])).2
632
+ (dvd_trans ⟨_, e⟩ (nat.min_fac_dvd _)))
633
+ dec_trivial
634
+
635
+ lemma min_fac_helper_0 (n : ℕ) (h : 0 < n) : min_fac_helper n 1 :=
636
+ begin
637
+ refine ⟨zero_lt_one, lt_of_le_of_ne _ min_fac_ne_bit0.symm⟩,
638
+ refine @lt_of_le_of_ne ℕ _ _ _ (nat.min_fac_pos _) _,
639
+ intro e,
640
+ have := nat.min_fac_prime _,
641
+ { rw ← e at this , exact nat.not_prime_one this },
642
+ { exact ne_of_gt (nat.bit1_lt h) }
643
+ end
644
+
645
+ lemma min_fac_helper_1 {n k k' : ℕ} (e : k + 1 = k')
646
+ (np : nat.min_fac (bit1 n) ≠ bit1 k)
647
+ (h : min_fac_helper n k) : min_fac_helper n k' :=
648
+ begin
649
+ rw ← e,
650
+ refine ⟨nat.succ_pos _,
651
+ (lt_of_le_of_ne (lt_of_le_of_ne _ _ : k+1 +k < _)
652
+ min_fac_ne_bit0.symm : bit0 (k+1 ) < _)⟩,
653
+ { rw add_right_comm, exact h.2 },
654
+ { rw add_right_comm, exact np.symm }
655
+ end
656
+
657
+ lemma min_fac_helper_2 (n k k' : ℕ) (e : k + 1 = k')
658
+ (np : ¬ nat.prime (bit1 k)) (h : min_fac_helper n k) : min_fac_helper n k' :=
659
+ begin
660
+ refine min_fac_helper_1 e _ h,
661
+ intro e₁, rw ← e₁ at np,
662
+ exact np (nat.min_fac_prime $ ne_of_gt $ nat.bit1_lt h.n_pos)
663
+ end
664
+
665
+ lemma min_fac_helper_3 (n k k' c : ℕ) (e : k + 1 = k')
666
+ (nc : bit1 n % bit1 k = c) (c0 : 0 < c)
667
+ (h : min_fac_helper n k) : min_fac_helper n k' :=
668
+ begin
669
+ refine min_fac_helper_1 e _ h,
670
+ refine mt _ (ne_of_gt c0), intro e₁,
671
+ rw [← nc, ← nat.dvd_iff_mod_eq_zero, ← e₁],
672
+ apply nat.min_fac_dvd
673
+ end
674
+
675
+ lemma min_fac_helper_4 (n k : ℕ) (hd : bit1 n % bit1 k = 0 )
676
+ (h : min_fac_helper n k) : nat.min_fac (bit1 n) = bit1 k :=
677
+ by rw ← nat.dvd_iff_mod_eq_zero at hd; exact
678
+ le_antisymm (nat.min_fac_le_of_dvd (nat.bit1_lt h.1 ) hd) h.2
679
+
680
+ lemma min_fac_helper_5 (n k k' : ℕ) (e : bit1 k * bit1 k = k')
681
+ (hd : bit1 n < k') (h : min_fac_helper n k) : nat.min_fac (bit1 n) = bit1 n :=
682
+ begin
683
+ refine (nat.prime_def_min_fac.1 (nat.prime_def_le_sqrt.2
684
+ ⟨nat.bit1_lt h.n_pos, _⟩)).2 ,
685
+ rw ← e at hd,
686
+ intros m m2 hm md,
687
+ have := le_trans h.2 (le_trans (nat.min_fac_le_of_dvd m2 md) hm),
688
+ rw nat.le_sqrt at this ,
689
+ exact not_le_of_lt hd this
690
+ end
691
+
692
+ /-- Given `e` a natural numeral and `d : nat` a factor of it, return `⊢ ¬ prime e`. -/
693
+ meta def prove_non_prime (e : expr) (n d₁ : ℕ) : tactic expr :=
694
+ do let e₁ := reflect d₁,
695
+ c ← mk_instance_cache `(nat),
696
+ (c, p₁) ← prove_lt_nat c `(1 ) e₁,
697
+ let d₂ := n / d₁, let e₂ := reflect d₂,
698
+ (c, e', p) ← prove_mul_nat c e₁ e₂,
699
+ guard (e' =ₐ e),
700
+ (c, p₂) ← prove_lt_nat c `(1 ) e₂,
701
+ return $ `(not_prime_helper).mk_app [e₁, e₂, e, p, p₁, p₂]
702
+
703
+ /-- Given `a`,`a1 := bit1 a`, `n1` the value of `a1`, `b` and `p : min_fac_helper a b`,
704
+ returns `(c, ⊢ min_fac a1 = c)`. -/
705
+ meta def prove_min_fac_aux (a a1 : expr) (n1 : ℕ) :
706
+ instance_cache → expr → expr → tactic (instance_cache × expr × expr)
707
+ | ic b p := do
708
+ k ← b.to_nat,
709
+ let k1 := bit1 k,
710
+ let b1 := `(bit1:ℕ→ℕ).mk_app [b],
711
+ if n1 < k1*k1 then do
712
+ (ic, e', p₁) ← prove_mul_nat ic b1 b1,
713
+ (ic, p₂) ← prove_lt_nat ic a1 e',
714
+ return (ic, a1, `(min_fac_helper_5).mk_app [a, b, e', p₁, p₂, p])
715
+ else let d := k1.min_fac in
716
+ if to_bool (d < k1) then do
717
+ let k' := k+1 , let e' := reflect k',
718
+ (ic, p₁) ← prove_succ ic b e',
719
+ p₂ ← prove_non_prime b1 k1 d,
720
+ prove_min_fac_aux ic e' $ `(min_fac_helper_2).mk_app [a, b, e', p₁, p₂, p]
721
+ else do
722
+ let nc := n1 % k1,
723
+ (ic, c, pc) ← prove_div_mod ic a1 b1 tt,
724
+ if nc = 0 then
725
+ return (ic, b1, `(min_fac_helper_4).mk_app [a, b, pc, p])
726
+ else do
727
+ (ic, p₀) ← prove_pos ic c,
728
+ let k' := k+1 , let e' := reflect k',
729
+ (ic, p₁) ← prove_succ ic b e',
730
+ prove_min_fac_aux ic e' $ `(min_fac_helper_3).mk_app [a, b, e', c, p₁, pc, p₀, p]
731
+
732
+ /-- Given `a` a natural numeral, returns `(b, ⊢ min_fac a = b)`. -/
733
+ meta def prove_min_fac (ic : instance_cache) (e : expr) : tactic (instance_cache × expr × expr) :=
734
+ match match_numeral e with
735
+ | match_numeral_result.zero := return (ic, `(2 :ℕ), `(nat.min_fac_zero))
736
+ | match_numeral_result.one := return (ic, `(1 :ℕ), `(nat.min_fac_one))
737
+ | match_numeral_result.bit0 e := return (ic, `(2 ), `(min_fac_bit0).mk_app [e])
738
+ | match_numeral_result.bit1 e := do
739
+ n ← e.to_nat,
740
+ c ← mk_instance_cache `(nat),
741
+ (c, p) ← prove_pos c e,
742
+ let a1 := `(bit1:ℕ→ℕ).mk_app [e],
743
+ prove_min_fac_aux e a1 (bit1 n) c `(1 ) (`(min_fac_helper_0).mk_app [e, p])
744
+ | _ := failed
745
+ end
746
+
747
+ /-- Evaluates the `prime` and `min_fac` functions. -/
748
+ @[norm_num] meta def eval_prime : expr → tactic (expr × expr)
749
+ | `(nat.prime %%e) := do
750
+ n ← e.to_nat,
751
+ match n with
752
+ | 0 := false_intro `(nat.not_prime_zero)
753
+ | 1 := false_intro `(nat.not_prime_one)
754
+ | _ := let d₁ := n.min_fac in
755
+ if d₁ < n then prove_non_prime e n d₁ >>= false_intro
756
+ else do
757
+ let e₁ := reflect d₁,
758
+ c ← mk_instance_cache `(nat),
759
+ (c, p₁) ← prove_lt_nat c `(1 ) e₁,
760
+ (c, e₁, p) ← prove_min_fac c e,
761
+ true_intro $ `(is_prime_helper).mk_app [e, p₁, p]
762
+ end
763
+ | `(nat.min_fac %%e) := do
764
+ ic ← mk_instance_cache `(ℕ),
765
+ prod.snd <$> prove_min_fac ic e
766
+ | _ := failed
767
+
768
+ end norm_num
769
+ end tactic
0 commit comments