@@ -182,9 +182,137 @@ begin
182
182
simp,
183
183
end
184
184
185
- instance : decidable_pred (squarefree : ℕ → Prop )
186
- | 0 := is_false not_squarefree_zero
187
- | (n + 1 ) := decidable_of_iff _ (squarefree_iff_nodup_factors (nat.succ_ne_zero n)).symm
185
+ theorem squarefree_iff_prime_squarefree {n : ℕ} : squarefree n ↔ ∀ x, prime x → ¬ x * x ∣ n :=
186
+ squarefree_iff_irreducible_sq_not_dvd_of_exists_irreducible ⟨_, prime_two⟩
187
+
188
+ /-- Assuming that `n` has no factors less than `k`, returns the smallest prime `p` such that
189
+ `p^2 ∣ n`. -/
190
+ def min_sq_fac_aux : ℕ → ℕ → option ℕ
191
+ | n k :=
192
+ if h : n < k * k then none else
193
+ have nat.sqrt n + 2 - (k + 2 ) < nat.sqrt n + 2 - k,
194
+ by { rw nat.add_sub_add_right, exact nat.min_fac_lemma n k h },
195
+ if k ∣ n then
196
+ let n' := n / k in
197
+ have nat.sqrt n' + 2 - (k + 2 ) < nat.sqrt n + 2 - k, from
198
+ lt_of_le_of_lt (nat.sub_le_sub_right
199
+ (nat.add_le_add_right (nat.sqrt_le_sqrt $ nat.div_le_self _ _) _) _) this ,
200
+ if k ∣ n' then some k else min_sq_fac_aux n' (k + 2 )
201
+ else min_sq_fac_aux n (k + 2 )
202
+ using_well_founded {rel_tac :=
203
+ λ _ _, `[exact ⟨_, measure_wf (λ ⟨n, k⟩, nat.sqrt n + 2 - k)⟩]}
204
+
205
+ /-- Returns the smallest prime factor `p` of `n` such that `p^2 ∣ n`, or `none` if there is no
206
+ such `p` (that is, `n` is squarefree). See also `squarefree_iff_min_sq_fac`. -/
207
+ def min_sq_fac (n : ℕ) : option ℕ :=
208
+ if 2 ∣ n then
209
+ let n' := n / 2 in
210
+ if 2 ∣ n' then some 2 else min_sq_fac_aux n' 3
211
+ else min_sq_fac_aux n 3
212
+
213
+ /-- The correctness property of the return value of `min_sq_fac`.
214
+ * If `none`, then `n` is squarefree;
215
+ * If `some d`, then `d` is a minimal square factor of `n` -/
216
+ def min_sq_fac_prop (n : ℕ) : option ℕ → Prop
217
+ | none := squarefree n
218
+ | (some d) := prime d ∧ d * d ∣ n ∧ ∀ p, prime p → p * p ∣ n → d ≤ p
219
+
220
+ theorem min_sq_fac_prop_div (n) {k} (pk : prime k) (dk : k ∣ n) (dkk : ¬ k * k ∣ n)
221
+ {o} (H : min_sq_fac_prop (n / k) o) : min_sq_fac_prop n o :=
222
+ begin
223
+ have : ∀ p, prime p → p*p ∣ n → k*(p*p) ∣ n := λ p pp dp,
224
+ have _ := (coprime_primes pk pp).2 (λ e, by { subst e, contradiction }),
225
+ (coprime_mul_iff_right.2 ⟨this , this ⟩).mul_dvd_of_dvd_of_dvd dk dp,
226
+ cases o with d,
227
+ { rw [min_sq_fac_prop, squarefree_iff_prime_squarefree] at H ⊢,
228
+ exact λ p pp dp, H p pp ((dvd_div_iff dk).2 (this _ pp dp)) },
229
+ { obtain ⟨H1, H2, H3⟩ := H,
230
+ simp only [dvd_div_iff dk] at H2 H3,
231
+ exact ⟨H1, dvd_trans (dvd_mul_left _ _) H2, λ p pp dp, H3 _ pp (this _ pp dp)⟩ }
232
+ end
233
+
234
+ theorem min_sq_fac_aux_has_prop : ∀ {n : ℕ} k, 0 < n → ∀ i, k = 2 *i+3 →
235
+ (∀ m, prime m → m ∣ n → k ≤ m) → min_sq_fac_prop n (min_sq_fac_aux n k)
236
+ | n k := λ n0 i e ih, begin
237
+ rw min_sq_fac_aux,
238
+ by_cases h : n < k*k; simp [h],
239
+ { refine squarefree_iff_prime_squarefree.2 (λ p pp d, _),
240
+ have := ih p pp (dvd_trans ⟨_, rfl⟩ d),
241
+ have := nat.mul_le_mul this this ,
242
+ exact not_le_of_lt h (le_trans this (le_of_dvd n0 d)) },
243
+ have k2 : 2 ≤ k, { subst e, exact dec_trivial },
244
+ have k0 : 0 < k := lt_of_lt_of_le dec_trivial k2,
245
+ have IH : ∀ n', n' ∣ n → ¬ k ∣ n' → min_sq_fac_prop n' (n'.min_sq_fac_aux (k + 2 )),
246
+ { intros n' nd' nk,
247
+ have hn' := le_of_dvd n0 nd',
248
+ refine
249
+ have nat.sqrt n' - k < nat.sqrt n + 2 - k, from
250
+ lt_of_le_of_lt (nat.sub_le_sub_right (nat.sqrt_le_sqrt hn') _) (nat.min_fac_lemma n k h),
251
+ @min_sq_fac_aux_has_prop n' (k+2 ) (pos_of_dvd_of_pos nd' n0)
252
+ (i+1 ) (by simp [e, left_distrib]) (λ m m2 d, _),
253
+ cases nat.eq_or_lt_of_le (ih m m2 (dvd_trans d nd')) with me ml,
254
+ { subst me, contradiction },
255
+ apply (nat.eq_or_lt_of_le ml).resolve_left, intro me,
256
+ rw [← me, e] at d, change 2 * (i + 2 ) ∣ n' at d,
257
+ have := ih _ prime_two (dvd_trans (dvd_of_mul_right_dvd d) nd'),
258
+ rw e at this , exact absurd this dec_trivial },
259
+ have pk : k ∣ n → prime k,
260
+ { refine λ dk, prime_def_min_fac.2 ⟨k2, le_antisymm (min_fac_le k0) _⟩,
261
+ exact ih _ (min_fac_prime (ne_of_gt k2)) (dvd_trans (min_fac_dvd _) dk) },
262
+ split_ifs with dk dkk,
263
+ { exact ⟨pk dk, (nat.dvd_div_iff dk).1 dkk, λ p pp d, ih p pp (dvd_trans ⟨_, rfl⟩ d)⟩ },
264
+ { specialize IH (n/k) (div_dvd_of_dvd dk) dkk,
265
+ exact min_sq_fac_prop_div _ (pk dk) dk (mt (nat.dvd_div_iff dk).2 dkk) IH },
266
+ { exact IH n (dvd_refl _) dk }
267
+ end
268
+ using_well_founded {rel_tac :=
269
+ λ _ _, `[exact ⟨_, measure_wf (λ ⟨n, k⟩, nat.sqrt n + 2 - k)⟩]}
270
+
271
+ theorem min_sq_fac_has_prop (n : ℕ) : min_sq_fac_prop n (min_sq_fac n) :=
272
+ begin
273
+ dunfold min_sq_fac, split_ifs with d2 d4,
274
+ { exact ⟨prime_two, (dvd_div_iff d2).1 d4, λ p pp _, pp.two_le⟩ },
275
+ { cases nat.eq_zero_or_pos n with n0 n0, { subst n0, cases d4 dec_trivial },
276
+ refine min_sq_fac_prop_div _ prime_two d2 (mt (dvd_div_iff d2).2 d4) _,
277
+ refine min_sq_fac_aux_has_prop 3 (nat.div_pos (le_of_dvd n0 d2) dec_trivial) 0 rfl _,
278
+ refine λ p pp dp, succ_le_of_lt (lt_of_le_of_ne pp.two_le _),
279
+ rintro rfl, contradiction },
280
+ { cases nat.eq_zero_or_pos n with n0 n0, { subst n0, cases d2 dec_trivial },
281
+ refine min_sq_fac_aux_has_prop _ n0 0 rfl _,
282
+ refine λ p pp dp, succ_le_of_lt (lt_of_le_of_ne pp.two_le _),
283
+ rintro rfl, contradiction },
284
+ end
285
+
286
+ theorem min_sq_fac_prime {n d : ℕ} (h : n.min_sq_fac = some d) : prime d :=
287
+ by { have := min_sq_fac_has_prop n, rw h at this , exact this.1 }
288
+
289
+ theorem min_sq_fac_dvd {n d : ℕ} (h : n.min_sq_fac = some d) : d * d ∣ n :=
290
+ by { have := min_sq_fac_has_prop n, rw h at this , exact this.2 .1 }
291
+
292
+ theorem min_sq_fac_le_of_dvd {n d : ℕ} (h : n.min_sq_fac = some d)
293
+ {m} (m2 : 2 ≤ m) (md : m * m ∣ n) : d ≤ m :=
294
+ begin
295
+ have := min_sq_fac_has_prop n, rw h at this ,
296
+ have fd := min_fac_dvd m,
297
+ exact le_trans
298
+ (this.2 .2 _ (min_fac_prime $ ne_of_gt m2) (dvd_trans (mul_dvd_mul fd fd) md))
299
+ (min_fac_le $ lt_of_lt_of_le dec_trivial m2),
300
+ end
301
+
302
+ lemma squarefree_iff_min_sq_fac {n : ℕ} :
303
+ squarefree n ↔ n.min_sq_fac = none :=
304
+ begin
305
+ have := min_sq_fac_has_prop n,
306
+ split; intro H,
307
+ { cases n.min_sq_fac with d, {refl},
308
+ cases squarefree_iff_prime_squarefree.1 H _ this.1 this.2 .1 },
309
+ { rwa H at this }
310
+ end
311
+
312
+ instance : decidable_pred (squarefree : ℕ → Prop ) :=
313
+ λ n, decidable_of_iff' _ squarefree_iff_min_sq_fac
314
+
315
+ theorem squarefree_two : squarefree 2 := by rw squarefree_iff_nodup_factors; norm_num
188
316
189
317
open unique_factorization_monoid
190
318
@@ -295,3 +423,184 @@ squarefree_iff_irreducible_sq_not_dvd_of_exists_irreducible
295
423
⟨2 , (irreducible_iff_nat_prime _).2 prime_two⟩
296
424
297
425
end nat
426
+
427
+ /-! ### Square-free prover -/
428
+
429
+ open norm_num
430
+
431
+ namespace tactic
432
+ namespace norm_num
433
+
434
+ /-- A predicate representing partial progress in a proof of `squarefree`. -/
435
+ def squarefree_helper (n k : ℕ) : Prop :=
436
+ 0 < k → (∀ m, nat.prime m → m ∣ bit1 n → bit1 k ≤ m) → squarefree (bit1 n)
437
+
438
+ lemma squarefree_bit10 (n : ℕ) (h : squarefree_helper n 1 ) :
439
+ squarefree (bit0 (bit1 n)) :=
440
+ begin
441
+ refine @nat.min_sq_fac_prop_div _ _ nat.prime_two two_dvd_bit0 _ none _,
442
+ { rw [bit0_eq_two_mul (bit1 n), mul_dvd_mul_iff_left (@two_ne_zero ℕ _ _)],
443
+ exact nat.not_two_dvd_bit1 _ },
444
+ { rw [bit0_eq_two_mul, nat.mul_div_right _ (dec_trivial:0 <2 )],
445
+ refine h dec_trivial (λ p pp dp, nat.succ_le_of_lt (lt_of_le_of_ne pp.two_le _)),
446
+ rintro rfl, exact nat.not_two_dvd_bit1 _ dp }
447
+ end
448
+
449
+ lemma squarefree_bit1 (n : ℕ) (h : squarefree_helper n 1 ) :
450
+ squarefree (bit1 n) :=
451
+ begin
452
+ refine h dec_trivial (λ p pp dp, nat.succ_le_of_lt (lt_of_le_of_ne pp.two_le _)),
453
+ rintro rfl, exact nat.not_two_dvd_bit1 _ dp
454
+ end
455
+
456
+ lemma squarefree_helper_0 {k} (k0 : 0 < k)
457
+ {p : ℕ} (pp : nat.prime p) (h : bit1 k ≤ p) : bit1 (k + 1 ) ≤ p ∨ bit1 k = p :=
458
+ begin
459
+ rcases lt_or_eq_of_le h with (hp:_+1 ≤_) | hp,
460
+ { rw [bit1, bit0_eq_two_mul] at hp, change 2 *(_+1 ) ≤ _ at hp,
461
+ rw [bit1, bit0_eq_two_mul],
462
+ refine or.inl (lt_of_le_of_ne hp _), unfreezingI { rintro rfl },
463
+ exact nat.not_prime_mul dec_trivial (lt_add_of_pos_left _ k0) pp },
464
+ { exact or.inr hp }
465
+ end
466
+
467
+ lemma squarefree_helper_1 (n k k' : ℕ) (e : k + 1 = k')
468
+ (hk : nat.prime (bit1 k) → ¬ bit1 k ∣ bit1 n)
469
+ (H : squarefree_helper n k') : squarefree_helper n k :=
470
+ λ k0 ih, begin
471
+ subst e,
472
+ refine H (nat.succ_pos _) (λ p pp dp, _),
473
+ refine (squarefree_helper_0 k0 pp (ih p pp dp)).resolve_right (λ hp, _),
474
+ subst hp, cases hk pp dp
475
+ end
476
+
477
+ lemma squarefree_helper_2 (n k k' c : ℕ) (e : k + 1 = k')
478
+ (hc : bit1 n % bit1 k = c) (c0 : 0 < c)
479
+ (h : squarefree_helper n k') : squarefree_helper n k :=
480
+ begin
481
+ refine squarefree_helper_1 _ _ _ e (λ _, _) h,
482
+ refine mt _ (ne_of_gt c0), intro e₁,
483
+ rwa [← hc, ← nat.dvd_iff_mod_eq_zero],
484
+ end
485
+
486
+ lemma squarefree_helper_3 (n n' k k' c : ℕ) (e : k + 1 = k')
487
+ (hn' : bit1 n' * bit1 k = bit1 n)
488
+ (hc : bit1 n' % bit1 k = c) (c0 : 0 < c)
489
+ (H : squarefree_helper n' k') : squarefree_helper n k :=
490
+ λ k0 ih, begin
491
+ subst e,
492
+ have k0' : 0 < bit1 k := bit1_pos (nat.zero_le _),
493
+ have dn' : bit1 n' ∣ bit1 n := ⟨_, hn'.symm⟩,
494
+ have dk : bit1 k ∣ bit1 n := ⟨_, ((mul_comm _ _).trans hn').symm⟩,
495
+ have : bit1 n / bit1 k = bit1 n',
496
+ { rw [← hn', nat.mul_div_cancel _ k0'] },
497
+ have k2 : 2 ≤ bit1 k := nat.succ_le_succ (bit0_pos k0),
498
+ have pk : (bit1 k).prime,
499
+ { refine nat.prime_def_min_fac.2 ⟨k2, le_antisymm (nat.min_fac_le k0') _⟩,
500
+ exact ih _ (nat.min_fac_prime (ne_of_gt k2)) (dvd_trans (nat.min_fac_dvd _) dk) },
501
+ have dkk' : ¬ bit1 k ∣ bit1 n', {rw [nat.dvd_iff_mod_eq_zero, hc], exact ne_of_gt c0},
502
+ have dkk : ¬ bit1 k * bit1 k ∣ bit1 n, {rwa [← nat.dvd_div_iff dk, this ]},
503
+ refine @nat.min_sq_fac_prop_div _ _ pk dk dkk none _,
504
+ rw this , refine H (nat.succ_pos _) (λ p pp dp, _),
505
+ refine (squarefree_helper_0 k0 pp (ih p pp $ dvd_trans dp dn')).resolve_right (λ e, _),
506
+ subst e, contradiction
507
+ end
508
+
509
+ lemma squarefree_helper_4 (n k k' : ℕ) (e : bit1 k * bit1 k = k')
510
+ (hd : bit1 n < k') : squarefree_helper n k :=
511
+ begin
512
+ cases nat.eq_zero_or_pos n with h h,
513
+ { subst n, exact λ _ _, squarefree_one },
514
+ subst e,
515
+ refine λ k0 ih, irreducible.squarefree (nat.prime_def_le_sqrt.2 ⟨bit1_lt_bit1.2 h, _⟩),
516
+ intros m m2 hm md,
517
+ obtain ⟨p, pp, hp⟩ := nat.exists_prime_and_dvd m2,
518
+ have := (ih p pp (dvd_trans hp md)).trans
519
+ (le_trans (nat.le_of_dvd (lt_of_lt_of_le dec_trivial m2) hp) hm),
520
+ rw nat.le_sqrt at this ,
521
+ exact not_le_of_lt hd this
522
+ end
523
+
524
+ lemma not_squarefree_mul (a aa b n : ℕ) (ha : a * a = aa) (hb : aa * b = n)
525
+ (h₁ : 1 < a) : ¬ squarefree n :=
526
+ by { rw [← hb, ← ha], exact λ H, ne_of_gt h₁ (nat.is_unit_iff.1 $ H _ ⟨_, rfl⟩) }
527
+
528
+ /-- Given `e` a natural numeral and `a : nat` with `a^2 ∣ n`, return `⊢ ¬ squarefree e`. -/
529
+ meta def prove_non_squarefree (e : expr) (n a : ℕ) : tactic expr := do
530
+ let ea := reflect a,
531
+ let eaa := reflect (a*a),
532
+ c ← mk_instance_cache `(nat),
533
+ (c, p₁) ← prove_lt_nat c `(1 ) ea,
534
+ let b := n / (a*a), let eb := reflect b,
535
+ (c, eaa, pa) ← prove_mul_nat c ea ea,
536
+ (c, e', pb) ← prove_mul_nat c eaa eb,
537
+ guard (e' =ₐ e),
538
+ return $ `(@not_squarefree_mul).mk_app [ea, eaa, eb, e, pa, pb, p₁]
539
+
540
+ /-- Given `en`,`en1 := bit1 en`, `n1` the value of `en1`, `ek`,
541
+ returns `⊢ squarefree_helper en ek`. -/
542
+ meta def prove_squarefree_aux : ∀ (ic : instance_cache) (en en1 : expr) (n1 : ℕ)
543
+ (ek : expr) (k : ℕ), tactic expr
544
+ | ic en en1 n1 ek k := do
545
+ let k1 := bit1 k,
546
+ let ek1 := `(bit1:ℕ→ℕ).mk_app [ek],
547
+ if n1 < k1*k1 then do
548
+ (ic, ek', p₁) ← prove_mul_nat ic ek1 ek1,
549
+ (ic, p₂) ← prove_lt_nat ic en1 ek',
550
+ pure $ `(squarefree_helper_4).mk_app [en, ek, ek', p₁, p₂]
551
+ else do
552
+ let c := n1 % k1,
553
+ let k' := k+1 , let ek' := reflect k',
554
+ (ic, p₁) ← prove_succ ic ek ek',
555
+ if c = 0 then do
556
+ let n1' := n1 / k1,
557
+ let n' := n1' / 2 , let en' := reflect n',
558
+ let en1' := `(bit1:ℕ→ℕ).mk_app [en'],
559
+ (ic, _, pn') ← prove_mul_nat ic en1' ek1,
560
+ let c := n1' % k1,
561
+ guard (c ≠ 0 ),
562
+ (ic, ec, pc) ← prove_div_mod ic en1' ek1 tt,
563
+ (ic, p₀) ← prove_pos ic ec,
564
+ p₂ ← prove_squarefree_aux ic en' en1' n1' ek' k',
565
+ pure $ `(squarefree_helper_3).mk_app [en, en', ek, ek', ec, p₁, pn', pc, p₀, p₂]
566
+ else do
567
+ (ic, ec, pc) ← prove_div_mod ic en1 ek1 tt,
568
+ (ic, p₀) ← prove_pos ic ec,
569
+ p₂ ← prove_squarefree_aux ic en en1 n1 ek' k',
570
+ pure $ `(squarefree_helper_2).mk_app [en, ek, ek', ec, p₁, pc, p₀, p₂]
571
+
572
+ /-- Given `n > 0` a squarefree natural numeral, returns `⊢ squarefree n`. -/
573
+ meta def prove_squarefree (en : expr) (n : ℕ) : tactic expr :=
574
+ match match_numeral en with
575
+ | match_numeral_result.one := pure `(@squarefree_one ℕ _)
576
+ | match_numeral_result.bit0 en1 := match match_numeral en1 with
577
+ | match_numeral_result.one := pure `(nat.squarefree_two)
578
+ | match_numeral_result.bit1 en := do
579
+ ic ← mk_instance_cache `(ℕ),
580
+ p ← prove_squarefree_aux ic en en1 (n / 2 ) `(1 :ℕ) 1 ,
581
+ pure $ `(squarefree_bit10).mk_app [en, p]
582
+ | _ := failed
583
+ end
584
+ | match_numeral_result.bit1 en' := do
585
+ ic ← mk_instance_cache `(ℕ),
586
+ p ← prove_squarefree_aux ic en' en n `(1 :ℕ) 1 ,
587
+ pure $ `(squarefree_bit1).mk_app [en', p]
588
+ | _ := failed
589
+ end
590
+
591
+ /-- Evaluates the `prime` and `min_fac` functions. -/
592
+ @[norm_num] meta def eval_squarefree : expr → tactic (expr × expr)
593
+ | `(squarefree (%%e : ℕ)) := do
594
+ n ← e.to_nat,
595
+ match n with
596
+ | 0 := false_intro `(@not_squarefree_zero ℕ _ _)
597
+ | 1 := true_intro `(@squarefree_one ℕ _)
598
+ | _ := match n.min_sq_fac with
599
+ | some d := prove_non_squarefree e n d >>= false_intro
600
+ | none := prove_squarefree e n >>= true_intro
601
+ end
602
+ end
603
+ | _ := failed
604
+
605
+ end norm_num
606
+ end tactic
0 commit comments