CentraleSupélec LMF, UMR CNRS 9021 Département informatique Laboratoire Méthodes Formelles Bât Breguet, 3 rue Joliot-Curie Bât 650 Ada Lovelace, Université Paris Sud 91190 Gif-sur-Yvette, France Rue Noetzlin, 91190 Gif-sur-Yvette, France
Preuve de l'équivalence des définitions du PGCD

Document présentant la preuve.

Théorie Isabelle de cette preuve :

section ‹ Introduction ›
text ‹
This Isabelle theory presents a proof of the equivalence of the \emph{natural} definition
of the Greatest Common Divisor for integers (as a common divisor that is greater than all
other common divisors),
and the definition on rings (as a common divisor that is divided by all other common divisors).

We finally show the equivalence between our definitions of the GCD using predicates, and the
functional definition in Isabelle, which relies on Euclid's algorithm.
›

theory IntGCD
imports Main

begin

section ‹ Common divisors ›
text ‹
We define a predicate for characterizing common divisors of two integers, and prove some
theorems that will be needed for proving properties of the GCD.
›
definition common_div :: ‹int ⇒ int ⇒ int ⇒ bool›
where
‹common_div a b p ≡ p dvd a ∧ p dvd b›

lemma common_div_comm:
‹common_div a b p = common_div b a p›
using common_div_def by blast

text ‹
Two integers have 0 as common divisor only if one of them is 0:
›
lemma cdiv_0: ‹common_div a b 0 ⟷ a = 0 ∧ b = 0›
using common_div_def by simp

text ‹
Common divisors are not changed by absolute values:
›
theorem common_div_abs:
‹common_div a b d = common_div ¦a¦ ¦b¦ d›
using common_div_def by simp

text ‹
The common divisors of $$a$$ and $$b$$ are the common divisors of $$a-b$$ and $$b$$.
This theorem is the basis of the proof of the equivalence of the two definitions of the GCD.
›
lemma common_div_ab_dir:
assumes ‹common_div a b p›
shows   ‹common_div (a - b) b p›
proof -
from assms and dvd_def
obtain ka where ‹a = p * ka› unfolding common_div_def by blast
moreover from assms and dvd_def
obtain kb where ‹b = p * kb› unfolding common_div_def by blast
ultimately have ‹a - b = (ka - kb) * p› by algebra
hence ‹p dvd (a - b)› by simp
moreover from assms have ‹p dvd b› using common_div_def by simp
ultimately show ?thesis using common_div_def by simp
qed

lemma common_div_ab_rev:
assumes ‹common_div (a - b) b p›
shows   ‹common_div a b p›
proof -
from assms and dvd_def
obtain ka where ‹(a - b) = p * ka› unfolding common_div_def by blast
moreover from assms and dvd_def
obtain kb where ‹b = p * kb› unfolding common_div_def by blast
ultimately have ‹a = (ka + kb) * p› by algebra
hence ‹p dvd a› by simp
moreover from assms have ‹p dvd b› using common_div_def by simp
ultimately show ?thesis using common_div_def by simp
qed

theorem common_div_ab:‹common_div a b p = common_div (a - b) b p›
using common_div_ab_dir and common_div_ab_rev by blast

theorem common_div_ba:‹common_div a b p = common_div a (b - a) p›
using common_div_ab and common_div_comm by simp

section ‹ Greatest common divisor, defined on order ›
text ‹
Here we define the greatest common divisor using the order on integers.
We define a predicate for identifying upper bounds of all common divisors:
›

definition no_greater_div :: ‹int ⇒ int ⇒ int ⇒ bool›
where
‹no_greater_div a b g ≡ ∀p. common_div a b p ⟶ p ≤ g›

text ‹
Such an upper bound is always strictly positive:
›
lemma greater_div_pos: ‹no_greater_div a b g ⟹ g > 0›
proof -
assume h:‹no_greater_div a b g›
have ‹1 dvd a› by simp
moreover have ‹1 dvd b› by simp
ultimately have ‹common_div a b 1› using common_div_def by simp
with h have ‹g ≥ 1› using no_greater_div_def by simp
thus ?thesis by simp
qed

theorem greater_div_abs:
‹no_greater_div a b g = no_greater_div ¦a¦ ¦b¦ g›
proof
assume h:‹no_greater_div a b g›
{
fix p assume ‹common_div ¦a¦ ¦b¦ p›
with common_div_abs have ‹common_div a b p› by simp
with h have ‹p ≤ g› using no_greater_div_def by simp
}
thus ‹no_greater_div ¦a¦ ¦b¦ g› using no_greater_div_def by simp
next
assume h:‹no_greater_div ¦a¦ ¦b¦ g›
{
fix p assume ‹common_div a b p›
with common_div_abs have ‹common_div ¦a¦ ¦b¦ p› by simp
with h have ‹p ≤ g› using no_greater_div_def by simp
}
thus ‹no_greater_div a b g› using no_greater_div_def by simp
qed

text ‹
The GCD is a common divisor which is an upper bound of the common divisors:
›
definition is_gcd :: ‹int ⇒ int ⇒ int ⇒ bool›
where
‹is_gcd a b g ≡ common_div a b g ∧ no_greater_div a b g›

text ‹
We now derive properties of the GCD from properties of divisors.
›
lemma gcd_comm: ‹is_gcd a b g = is_gcd b a g›
using is_gcd_def and common_div_def and no_greater_div_def by auto

lemma gcd_pos: ‹is_gcd a b g ⟹ g > 0›
using is_gcd_def and greater_div_pos by blast

lemma gcd_neq_zero:
assumes ‹is_gcd a b g›
shows   ‹g ≠ 0›
using gcd_pos[OF assms] by simp

lemma gcd_a0:
assumes ‹a ≠ 0›
shows   ‹is_gcd a 0 ¦a¦›
proof -
from dvd_imp_le_int[OF assms] have ‹∀p. p dvd a ∧ p dvd 0 ⟶ ¦p¦ ≤ ¦a¦›
by simp
hence ‹no_greater_div a 0 ¦a¦› unfolding no_greater_div_def and common_div_def
by auto
thus ?thesis using abs_div is_gcd_def common_div_def by simp
qed

lemma gcd_0b:
assumes ‹b ≠ 0›
shows   ‹is_gcd 0 b ¦b¦›
using assms and gcd_a0 and gcd_comm by auto

lemma gcd_self:
assumes ‹a ≠ 0›
shows   ‹is_gcd a a ¦a¦›
proof -
from dvd_imp_le_int[OF assms] have ‹∀p. p dvd a ∧ p dvd a ⟶ ¦p¦ ≤ ¦a¦›
by simp
hence ‹no_greater_div a a ¦a¦› unfolding no_greater_div_def and common_div_def
by auto
moreover from abs_div have ‹common_div a a ¦a¦› using common_div_def by simp
ultimately show ?thesis using is_gcd_def by simp
qed

lemma gcd_abs:
‹is_gcd a b g = is_gcd ¦a¦ ¦b¦ g›
using is_gcd_def and common_div_abs and greater_div_abs by simp

theorem gcd_ab:‹is_gcd a b g = is_gcd (a - b) b g›
using is_gcd_def no_greater_div_def common_div_ab by simp

theorem gcd_ba:‹is_gcd a b g = is_gcd a (b - a) g›
using  gcd_ab and gcd_comm by simp

text ‹
With the definition of the GCD based on the order on integers, the GCD is unique.
›
lemma gcd_unique:
assumes ‹is_gcd a b g›
and     ‹is_gcd a b g'›
shows   ‹g = g'›
proof -
from assms(1) have ‹∀p. common_div a b p ⟶ p ≤ g›
using is_gcd_def and no_greater_div_def by simp
moreover from assms(2) have ‹common_div a b g'›
using is_gcd_def by simp
ultimately have 1:‹g' ≤ g› by simp
from assms(2) have ‹∀p. common_div a b p ⟶ p ≤ g'›
using is_gcd_def and no_greater_div_def by simp
moreover from assms(1) have ‹common_div a b g› using is_gcd_def by simp
ultimately have 2:‹g ≤ g'› by simp
from 1 and 2 show ?thesis by simp
qed

section ‹ Greatest common divisor, ring definition ›
text ‹
We now define the greatest common divisor as one which is divided by all other common divisors.
We keep the positive one, so that this definition match the previous one.
›
definition is_gcd_div :: ‹int ⇒ int ⇒ int ⇒ bool›
where
‹is_gcd_div a b g ≡ (g > 0) ∧ common_div a b g
∧ (∀p. common_div a b p ⟶ p dvd g)›

text ‹
With this definition, the GCD cannot be null. Although the GCD of 0 and 0 is 0 using the ring
definition of the GCD, this makes no sense with regard to the definition based on the order on
integers: any integer is a common divisor of 0 and 0, so there is no greatest one.
›
lemma gcd_div_neq_zero:‹is_gcd_div a b g ⟹ g ≠ 0›
using is_gcd_div_def by simp

section ‹ Proof of the equivalence of the two definitions ›
text ‹
We can now show that both definitions of the GCD are equivalent.
Showing that being the GCD with the ring definition implies being the GCD
with the order definition is straightforward:
›
lemma gcd_div_inf:
assumes ‹is_gcd_div a b g›
shows   ‹is_gcd a b g›
proof -
from assms have 1:‹common_div a b g› using is_gcd_div_def by simp
from assms have 2:‹∀p. common_div a b p ⟶ p dvd g›
using is_gcd_div_def by simp
from assms have 3:‹g > 0› using is_gcd_div_def by simp
have ‹∀p. common_div a b p ⟶ p ≤ g›
proof -
{
fix p assume h:‹common_div a b p›
with 2 have dp:‹p dvd g› by simp
from 3 have ‹¦g¦ = g› and ‹g ≠ 0› by simp+
with zdvd_imp_le[OF dp] have ‹p ≤ g› by simp
}
thus ?thesis by auto
qed
thus ?thesis using 1 and is_gcd_def and no_greater_div_def by simp
qed

text ‹
The other way is more difficult. We use induction on natural numbers with an upper bound on
the sum of the absolute values, and use the fact that @{prop ‹is_gcd (a - b) b g = is_gcd a b g›}
›
lemma cdiv_div_gcd:
‹(¦a¦ + ¦b¦ > 0) ∧ (nat (¦a¦ + ¦b¦) ≤ Suc n) ∧ is_gcd ¦a¦ ¦b¦ g
⟹ (∀p. common_div ¦a¦ ¦b¦ p ⟶ p dvd g)›
proof (induction n arbitrary: a b)
case 0
hence pos:‹¦a¦ + ¦b¦ > 0›
and leq1:‹¦a¦ + ¦b¦ ≤ 1›
and gcd:‹is_gcd ¦a¦ ¦b¦ g› by auto
show ?case
proof (cases ‹a = 0›)
case True (* a = 0 *)
with leq1 and pos have ‹¦b¦ = 1› by simp
moreover with this have ‹g = 1›
using gcd_0b[of ‹¦b¦›] and a = 0 and gcd and gcd_unique by simp
ultimately show ?thesis using common_div_def by simp
next
case False (* a ≠ 0 *)
with leq1 have ‹¦a¦ = 1› and ‹b = 0› by auto
moreover with this have ‹g = 1›
using gcd_a0[of ‹¦a¦›] and ¬a = 0 and gcd and gcd_unique by simp
ultimately show ?thesis using common_div_def by simp
qed
next
case (Suc k)
from Suc.prems have
1:‹nat (¦a¦ + ¦b¦) ≤ Suc (Suc k)› and
2:‹is_gcd ¦a¦ ¦b¦ g› and 3:‹¦a¦ + ¦b¦ > 0› by auto
show ?case
proof (cases ‹nat (¦a¦ + ¦b¦) ≤ Suc k›)
case True
thus ?thesis using Suc.IH and 2 and 3 by simp
next
case False
with 1 have ab:‹nat (¦a¦ + ¦b¦) = Suc (Suc k)› by simp
show ?thesis
proof (cases ‹¦a¦ ≥ ¦b¦›)
case True (* ¦a¦ ≥ ¦b¦ *)
show ?thesis
proof (cases ‹¦b¦ = 0›)
case True (* ¦b¦ = 0 *)
with ab have ‹¦a¦ ≠ 0› by simp
with ¦b¦ = 0 and 2 and gcd_a0[of ‹¦a¦›] and gcd_unique
have ‹g = ¦a¦› by simp
thus ?thesis using common_div_def by simp
next
case False (* ¦b¦ ≠ 0 *)
with ab have ‹nat (¦a¦ - ¦b¦ + ¦b¦) ≤ Suc k›
using ¦a¦ ≥ ¦b¦ by simp
moreover from 2 and gcd_ab have ‹is_gcd (¦a¦ - ¦b¦) ¦b¦ g›
by simp
moreover from ¦b¦ ≠ 0 and ¦a¦ ≥ ¦b¦ have ‹¦a¦ + ¦b¦ - ¦b¦ > 0›
by simp
ultimately show ?thesis
using Suc.IH[of ‹¦a¦ - ¦b¦› ‹¦b¦›] and ¦a¦ ≥ ¦b¦ and common_div_ab
by simp
qed
next
case False (* ¦a¦ < ¦b¦ *)
show ?thesis
proof (cases ‹¦a¦ = 0›)
case True
with ab have ‹¦b¦ ≠ 0› by simp
with True and 2 and gcd_0b[of ‹¦b¦›] and gcd_unique
have ‹g = ¦b¦› by simp
thus ?thesis using common_div_def by simp
next
case False
with ab have ‹nat (¦a¦ + ¦b¦ - ¦a¦) ≤ Suc k›
using ¬ ¦a¦ ≥ ¦b¦ by simp
moreover from 2 and ¬ ¦a¦ ≥ ¦b¦ and gcd_ba
have ‹is_gcd ¦a¦ (¦b¦ - ¦a¦) g› by simp
moreover from ¦a¦ ≠ 0 and ¬ ¦a¦ ≥ ¦b¦
have ‹¦a¦ + ¦b¦ - ¦a¦ > 0› by simp
ultimately show ?thesis
using Suc.IH[of ‹¦a¦› ‹¦b¦ - ¦a¦›] and ¬ ¦a¦ ≥ ¦b¦
and common_div_ba by simp
qed
qed
qed
qed

text ‹
We can now remove the condition used to make the induction on $$n$$:
›
lemma common_div_gcd:
assumes ‹a ≠ 0 ∨ b ≠ 0›
and     ‹is_gcd ¦a¦ ¦b¦ g›
shows   ‹(∀p. common_div ¦a¦ ¦b¦ p ⟶ p dvd g)›
proof -
from assms(1) have 1:‹¦a¦ + ¦b¦ > 0› by auto
have ‹nat (¦a¦ + ¦b¦) ≤ Suc (nat (¦a¦ + ¦b¦))› by simp
with assms and 1 have
‹(¦a¦ + ¦b¦ > 0) ∧ (nat (¦a¦ + ¦b¦) ≤ Suc (nat (¦a¦ + ¦b¦))) ∧ is_gcd ¦a¦ ¦b¦ g›
by blast
from cdiv_div_gcd[OF this] show ?thesis .
qed

text ‹
Therefore, we have the equivalence of the two definitions when $$a$$ and $$b$$ are not both null:
›
lemma gcd_inf_div:
assumes ‹is_gcd a b g›
and     ‹a ≠ 0 ∨ b ≠ 0›
shows   ‹is_gcd_div a b g›
proof -
from assms(1) have ‹is_gcd ¦a¦ ¦b¦ g› using gcd_abs by simp
with assms(2) and common_div_gcd
have ‹(∀p. common_div ¦a¦ ¦b¦ p ⟶ p dvd g)› by simp
hence ‹(∀p. common_div a b p ⟶ p dvd g)› using common_div_abs by simp
moreover from assms(1) have ‹common_div a b g› using is_gcd_def by simp
moreover from assms(1) have ‹g > 0› using gcd_pos by simp
ultimately show ?thesis using is_gcd_div_def by simp
qed

theorem gcd_inf_div_eq:
assumes ‹a ≠ 0 ∨ b ≠ 0›
shows   ‹is_gcd a b g = is_gcd_div a b g›
using assms and gcd_div_inf and gcd_inf_div by blast

text ‹
The condition on the simultaneous nullity of $$a$$ and $$b$$ comes from the fact that
there is no GCD of 0 and 0 with the definiton based on the order on integers:
›
lemma any_common_div_0:‹common_div 0 0 d›
proof -
have ‹d dvd 0› by simp
thus ?thesis using common_div_def by simp
qed

theorem ‹¬(∃g. no_greater_div 0 0 g)›
proof
assume ‹∃g. no_greater_div 0 0 g›
from this obtain g where ngd:‹no_greater_div 0 0 g› by blast
from any_common_div_0[of ‹g+1›] have ‹common_div 0 0 (g+1)› .
with ngd have ‹g+1 ≤ g› using no_greater_div_def by blast
thus False by simp
qed

text ‹
Finally, we prove that our definition of the GCD matches the definition
of the $$\mathop{gcd}$$ function in Isabelle.
›

lemma gcdfunc_imp_gcd_div:
assumes ‹a ≠ 0 ∨ b ≠ 0›
and     ‹g = gcd a b›
shows   ‹is_gcd_div a b g›
using assms common_div_def is_gcd_div_def by auto

theorem gcd_func_is_gcd_div:
assumes ‹a ≠ 0 ∨ b ≠ 0›
shows   ‹(g = gcd a b) = is_gcd_div a b g›
proof
assume ‹is_gcd_div a b g›
hence h:‹is_gcd a b g› using gcd_inf_div_eq[OF assms] by simp
let ?g' = ‹gcd a b›
from assms and gcdfunc_imp_gcd_div have ‹is_gcd_div a b ?g'› by simp
hence ‹is_gcd a b ?g'› using gcd_inf_div_eq[OF assms] by simp
from gcd_unique[OF this h] show ‹g = ?g'› ..