lean2/library/theories/number_theory/bezout.lean

102 lines
3.6 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2015 William Peterson. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: William Peterson, Jeremy Avigad
Extended gcd, Bezout's theorem, chinese remainder theorem.
-/
import data.nat.div data.int .primes
/- Bezout's theorem -/
section Bezout
open nat int
open eq.ops well_founded decidable prod
private definition pair_nat.lt : × × → Prop := measure pr₂
private definition pair_nat.lt.wf : well_founded pair_nat.lt := intro_k (measure.wf pr₂) 20
local attribute pair_nat.lt.wf [instance]
local infixl `≺`:50 := pair_nat.lt
private definition gcd.lt.dec (x y₁ : ) : (succ y₁, x mod succ y₁) ≺ (x, succ y₁) :=
!nat.mod_lt (succ_pos y₁)
private definition egcd_rec_f (z : ) : × := λ s t, (t, s - t * z)
definition egcd.F : Π (p₁ : × ), (Π p₂ : × , p₂ ≺ p₁ → × ) → ×
| (x, y) := nat.cases_on y
(λ f, (1, 0) )
(λ y₁ (f : Π p₂, p₂ ≺ (x, succ y₁) → × ),
let bz := f (succ y₁, x mod succ y₁) !gcd.lt.dec in
prod.cases_on bz (egcd_rec_f (x div succ y₁)))
definition egcd (x y : ) := fix egcd.F (pair x y)
theorem egcd_zero (x : ) : egcd x 0 = (1, 0) :=
well_founded.fix_eq egcd.F (x, 0)
theorem egcd_succ (x y : ) :
egcd x (succ y) = prod.cases_on (egcd (succ y) (x mod succ y)) (egcd_rec_f (x div succ y)) :=
well_founded.fix_eq egcd.F (x, succ y)
theorem egcd_of_pos (x : ) {y : } (ypos : y > 0) :
let erec := egcd y (x mod y), u := pr₁ erec, v := pr₂ erec in
egcd x y = (v, u - v * (x div y)) :=
obtain y' (yeq : y = succ y'), from exists_eq_succ_of_pos ypos,
by rewrite [yeq, egcd_succ, -prod.eta (egcd _ _)]
theorem egcd_prop (x y : ) : (pr₁ (egcd x y)) * x + (pr₂ (egcd x y)) * y = gcd x y :=
gcd.induction x y
(take m, by rewrite [egcd_zero, ▸*, int.mul_zero, int.one_mul])
(take m n,
assume npos : 0 < n,
assume IH,
begin
let H := egcd_of_pos m npos, esimp at H,
rewrite [H, ▸*, gcd_rec, -IH, add.comm (#int _ * _), -of_nat_mod, ↑modulo],
rewrite [*int.mul_sub_right_distrib, *int.mul_sub_left_distrib, *mul.left_distrib],
rewrite [sub_add_eq_add_sub, *sub_eq_add_neg, int.add.assoc, of_nat_div, *int.mul.assoc]
end)
theorem Bezout_aux (x y : ) : ∃ a b : , a * x + b * y = gcd x y :=
exists.intro _ (exists.intro _ (egcd_prop x y))
theorem Bezout (x y : ) : ∃ a b : , a * x + b * y = gcd x y :=
obtain a' b' (H : a' * nat_abs x + b' * nat_abs y = gcd x y), from !Bezout_aux,
begin
existsi (a' * sign x),
existsi (b' * sign y),
rewrite [*int.mul.assoc, -*abs_eq_sign_mul, -*of_nat_nat_abs],
apply H
end
end Bezout
namespace nat
open int
theorem dvd_or_dvd_of_dvd_mul_of_prime {p x y : } (pp : prime p) (H : p x * y) :
p x p y :=
decidable.by_cases
(assume Hpx : p x, or.inl Hpx)
(assume Hnpx : ¬ p x,
have cpx : coprime p x, from coprime_of_prime_of_not_dvd pp Hnpx,
obtain (a b : ) (Hab : a * p + b * x = gcd p x), from !Bezout_aux,
assert H1 : a * p * y + b * x * y = y,
by rewrite [-int.mul.right_distrib, Hab, ↑coprime at cpx, cpx, int.one_mul],
have H2 : p y,
begin
apply dvd_of_of_nat_dvd_of_nat,
rewrite [-H1],
apply int.dvd_add,
{apply int.dvd_mul_of_dvd_left,
apply int.dvd_mul_of_dvd_right,
apply int.dvd.refl},
{rewrite int.mul.assoc,
apply int.dvd_mul_of_dvd_right,
apply of_nat_dvd_of_nat_of_dvd H}
end,
or.inr H2)
end nat