theory GCDInClass
imports Main
begin
fun gcd :: "nat \ nat \ nat" where
"gcd m 0 = m" |
"gcd 0 n = n" |
"gcd m n = (if m < n then gcd m (n - m) else gcd (m - n) n)"
thm gcd.induct
definition divisible_by :: "nat \ nat \ bool" ("_ | _" [80,80] 79) where
"divisible_by m n \ (\ k. m = n * k)"
declare divisible_by_def[simp]
definition isGCD :: "nat \ nat \ nat \ bool" where
"isGCD k m n \ m|k \ n|k \ (\ k'. m|k' \ n|k' \ k|k')"
declare isGCD_def[simp]
lemma gcd_diff:
assumes MN: "m \ n"
and G:"isGCD k m (n - m)"
shows "isGCD k m n"
proof -
from G have mk: "m|k" and nmk: "(n-m)|k"
and gk: "\ k'. m|k' \ (n-m)|k' \ k|k'" by auto
from mk obtain k1 where mkk1: "m = k * k1" by auto
from nmk obtain k2 where nmkk2: "n-m = k * k2" by auto
from nmkk2 MN have "n = m + k * k2" by simp
with mkk1 have "n = (k1 * k) + (k2 * k)" by simp
hence "n = (k1 + k2) * k" using add_mult_distrib by simp
hence nk: "n|k" by simp
have kg_mn: "\ k'. m|k' \ n|k' \ k|k'"
proof clarify
fix k' assume mkp: "m|k'" and nkp: "n|k'"
from nkp obtain k3 where nkpk3: "n = k' * k3" by auto
from mkp obtain k4 where mkpk3: "m = k' * k4" by auto
from nkpk3 mkpk3 have "n - m = (k' * k3) - (k' * k4)" by auto
hence "n - m = (k3 * k') - (k4 * k')"
using nat_mult_commute[of k' k3] nat_mult_commute[of k' k4] by simp
hence "n - m = (k3 - k4) * k'" using diff_mult_distrib by simp
hence "(n - m)|k'" by simp
with mkp gk show "k|k'" by simp
qed
from mk nk kg_mn show "isGCD k m n" by simp
qed
theorem "isGCD (gcd m n) m n"
proof (induct rule: gcd.induct)
fix m show "isGCD (gcd m 0) m 0" by simp
next
fix v
have "Suc v = (Suc v) * 1" by simp
hence "\ k. Suc v = (Suc v) * k" by (rule exI)
hence "Suc v | gcd 0 (Suc v)" by simp
thus "isGCD (gcd 0 (Suc v)) 0 (Suc v)" by simp
next
fix va v
let ?m = "Suc va" and ?n = "Suc v"
assume IH1: "?m < ?n \ isGCD (gcd ?m (?n - ?m)) ?m (?n - ?m)"
and IH2: "\ ?m < ?n \ isGCD (gcd (?m - ?n) ?n) (?m - ?n) ?n"
show "isGCD (gcd ?m ?n) ?m ?n"
proof (cases "?m < ?n")
assume MN: "?m < ?n"
from MN IH1 have 1: "isGCD (gcd ?m (?n - ?m)) ?m (?n - ?m)" by blast
from 1 MN have 3: "isGCD (gcd ?m ?n) ?m (?n - ?m)" by simp
from MN have 4: "?m \ ?n" by simp
from 4 3 show "isGCD (gcd ?m ?n) ?m ?n" by (rule gcd_diff)
next
assume notMN: "\ (?m < ?n)"
from notMN IH2 have 1: "isGCD (gcd (?m - ?n) ?n) (?m - ?n) ?n" by blast
from 1 notMN have 2: "isGCD (gcd ?m ?n) ?n (?m - ?n)" by simp
from notMN have 3: "?n \ ?m" by simp
from 3 2 have "isGCD (gcd ?m ?n) ?n ?m" by (rule gcd_diff)
from this show "isGCD (gcd ?m ?n) ?m ?n" by simp
qed
qed
end