Theory BinInduct

Up to index of Isabelle/HOL/Bits

theory BinInduct
imports Main
begin

header {* Integers as an Inductive Datatype *}

theory BinInduct imports Main begin

subsection {* Inductive property of BIT *}

consts Numerals :: "int set"
inductive Numerals
intros
  Numerals_Pls: "Numeral.Pls ∈ Numerals"
  Numerals_Min: "Numeral.Min ∈ Numerals"
  Numerals_B0: "z ∈ Numerals ==> z BIT bit.B0 ∈ Numerals"
  Numerals_B1: "z ∈ Numerals ==> z BIT bit.B1 ∈ Numerals"

lemma Numerals_succ: "z ∈ Numerals ==> Numeral.succ z ∈ Numerals"
by (erule Numerals.induct, simp_all add: Numerals.intros)

lemma Numerals_pred: "z ∈ Numerals ==> Numeral.pred z ∈ Numerals"
by (erule Numerals.induct, simp_all add: Numerals.intros)

lemma Numerals_uminus: "z ∈ Numerals ==> uminus z ∈ Numerals"
by (erule Numerals.induct, simp_all add: Numerals.intros Numerals_pred)

lemma Numerals_int: "int n ∈ Numerals"
apply (induct "n")
apply (simp add: Numerals_Pls [unfolded Numeral.Pls_def])
apply (drule Numerals_succ [unfolded Numeral.succ_def])
apply (simp add: add_commute)
done

lemma mem_Numerals: "z ∈ Numerals"
by (induct "z") (simp_all only: Numerals_int Numerals_uminus)

lemma BIT_induct [case_names Pls Min B0 B1]:
  assumes Pls: "P Numeral.Pls"
  assumes Min: "P Numeral.Min"
  assumes B0: "!!x. [|P x; x ≠ Numeral.Pls|] ==> P (x BIT bit.B0)"
  assumes B1: "!!x. [|P x; x ≠ Numeral.Min|] ==> P (x BIT bit.B1)"
  shows "P x"
apply (induct x rule: Numerals.induct [OF mem_Numerals])
apply (rule Pls)
apply (rule Min)
apply (case_tac "z = Numeral.Pls", simp)
apply (erule (1) B0)
apply (case_tac "z = Numeral.Min", simp)
apply (erule (1) B1)
done

subsection {* Injectivity of BIT *}

lemma BIT_inject: "x BIT a = y BIT b ==> x = y ∧ a = b"
apply (drule_tac f="number_of :: int => int" in arg_cong)
apply (case_tac "a", case_tac [!] "b")
apply (simp_all add: succ_def pred_def)
apply (simp_all add: number_of_is_id iszero_def)
done

lemma BIT_eq: "(x BIT a = y BIT b) = (x = y ∧ a = b)"
by (safe dest!: BIT_inject)

lemma BIT_eq_Pls: "(w BIT b = Numeral.Pls) = (w = Numeral.Pls ∧ b = bit.B0)"
by (subst Pls_0_eq [symmetric], simp only: BIT_eq)

lemma BIT_eq_Min: "(w BIT b = Numeral.Min) = (w = Numeral.Min ∧ b = bit.B1)"
by (subst Min_1_eq [symmetric], simp only: BIT_eq)

lemma Pls_eq_BIT: "(Numeral.Pls = w BIT b) = (w = Numeral.Pls ∧ b = bit.B0)"
by (subst eq_commute, rule BIT_eq_Pls)

lemma Min_eq_BIT: "(Numeral.Min = w BIT b) = (w = Numeral.Min ∧ b = bit.B1)"
by (subst eq_commute, rule BIT_eq_Min)

lemma Min_neq_Pls: "Numeral.Min ≠ Numeral.Pls"
by (unfold Min_def Pls_def) simp

lemma Pls_neq_Min: "Numeral.Pls ≠ Numeral.Min"
by (unfold Min_def Pls_def) simp

lemmas bin_injects [simp] =
  BIT_eq BIT_eq_Pls BIT_eq_Min Pls_eq_BIT Min_eq_BIT Min_neq_Pls Pls_neq_Min

lemma BIT_exhausts: "∃w b. x = w BIT b"
apply (induct x rule: BIT_induct)
apply (fast intro: Pls_0_eq [symmetric] Min_1_eq [symmetric])+
done

definition
  div2 :: "int => int" where
  "div2 x = (THE w. ∃b. x = w BIT b)"

definition
  lsb :: "int => bit" where
  "lsb x = (THE b. ∃w. x = w BIT b)"

lemma div2_BIT [simp]: "div2 (w BIT b) = w"
by (unfold div2_def, rule the_equality, fast, simp)

lemma div2_Pls [simp]: "div2 Numeral.Pls = Numeral.Pls"
by (subst Pls_0_eq [symmetric], rule div2_BIT)

lemma div2_Min [simp]: "div2 Numeral.Min = Numeral.Min"
by (subst Min_1_eq [symmetric], rule div2_BIT)

lemma lsb_BIT [simp]: "lsb (w BIT b) = b"
by (unfold lsb_def, rule the_equality, fast, simp)

lemma lsb_Pls [simp]: "lsb Numeral.Pls = bit.B0"
by (subst Pls_0_eq [symmetric], rule lsb_BIT)

lemma lsb_Min [simp]: "lsb Numeral.Min = bit.B1"
by (subst Min_1_eq [symmetric], rule lsb_BIT)

lemma div2_BIT_lsb: "(div2 x) BIT (lsb x) = x"
by (induct x rule: BIT_induct) simp_all

lemmas div2_lsb_simps =
  div2_BIT div2_Pls div2_Min
  lsb_BIT lsb_Pls lsb_Min
  div2_BIT_lsb

lemma wf_div2: "wf {(div2 w, w) |w. w ≠ Numeral.Pls ∧ w ≠ Numeral.Min}"
 apply (rule wfUNIVI, simp (no_asm_use))
 apply (rename_tac "z", induct_tac "z" rule: BIT_induct)
    apply (drule spec, erule mp, simp)
   apply (drule spec, erule mp, simp)
  apply (drule spec, erule mp, simp)
 apply (drule spec, erule mp, simp)
done

subsection {* Testing bit positions *}

consts getbit :: "int => nat => bit"

primrec
  "getbit x 0 = lsb x"
  "getbit x (Suc n) = getbit (div2 x) n"

lemma getbit_Pls: "getbit Numeral.Pls n = bit.B0"
by (induct n) simp_all

lemma getbit_Min: "getbit Numeral.Min n = bit.B1"
by (induct n) simp_all

lemma getbit_Pls_rev:
   "(∀n. getbit x n = bit.B0) ==> x = Numeral.Pls"
proof (induct x rule: BIT_induct)
  case Pls
  show ?case by simp
next
  case Min
  thus ?case by (simp add: getbit_Min)
next
  case (B0 z)
  have "∀n. getbit (z BIT bit.B0) (Suc n) = bit.B0" using B0(3) by fast
  hence "∀n. getbit z n = bit.B0" by simp
  hence "z = Numeral.Pls" by (rule B0(1))
  thus ?case by simp
next
  case (B1 z)
  have "getbit (z BIT bit.B1) 0 = bit.B0" using B1(3) by fast
  thus ?case by simp
qed

lemma getbit_Min_rev:
   "(∀n. getbit x n = bit.B1) ==> x = Numeral.Min"
proof (induct x rule: BIT_induct)
  case Pls
  thus ?case by (simp add: getbit_Pls)
next
  case Min
  show ?case by simp
next
  case (B0 z)
  have "getbit (z BIT bit.B0) 0 = bit.B1" using B0(3) by fast
  thus ?case by simp
next
  case (B1 z)
  have "∀n. getbit (z BIT bit.B1) (Suc n) = bit.B1" using B1(3) by fast
  hence "∀n. getbit z n = bit.B1" by simp
  hence "z = Numeral.Min" by (rule B1(1))
  thus ?case by simp
qed

lemma getbit_ext: "!!x. ∀n. getbit x n = getbit y n ==> (x::int) = y"
proof (induct y rule: BIT_induct)
  case Pls
  hence "∀n. getbit x n = bit.B0" by (simp add: getbit_Pls)
  thus ?case by (rule getbit_Pls_rev)
next
  case Min
  hence "∀n. getbit x n = bit.B1" by (simp add: getbit_Min)
  thus ?case by (rule getbit_Min_rev)
next
  case (B0 z)
  have "∀n. getbit x (Suc n) = getbit (z BIT bit.B0) (Suc n)"
    using B0(3) by fast
  hence "∀n. getbit (div2 x) n = getbit z n" by simp
  hence 1: "div2 x = z" by (rule B0(1))
  have "getbit x 0 = getbit (z BIT bit.B0) 0" using B0(3) by fast
  hence 2: "lsb x = bit.B0" by simp
  from 1 2 have "div2 x BIT lsb x = z BIT bit.B0" by simp
  thus "x = z BIT bit.B0" by (simp only: div2_BIT_lsb)
next
  case (B1 z)
  have "∀n. getbit x (Suc n) = getbit (z BIT bit.B1) (Suc n)"
    using B1(3) by fast
  hence "∀n. getbit (div2 x) n = getbit z n" by simp
  hence 1: "div2 x = z" by (rule B1(1))
  have "getbit x 0 = getbit (z BIT bit.B1) 0" using B1(3) by fast
  hence 2: "lsb x = bit.B1" by simp
  from 1 2 have "div2 x BIT lsb x = z BIT bit.B1" by simp
  thus "x = z BIT bit.B1" by (simp only: div2_BIT_lsb)
qed

lemma expand_getbit_eq:
  "((x::int) = y) = (∀n. getbit x n = getbit y n)"
by (safe intro!: getbit_ext)

end

Inductive property of BIT

lemma Numerals_succ:

  z ∈ Numerals ==> Numeral.succ z ∈ Numerals

lemma Numerals_pred:

  z ∈ Numerals ==> Numeral.pred z ∈ Numerals

lemma Numerals_uminus:

  z ∈ Numerals ==> - z ∈ Numerals

lemma Numerals_int:

  int n ∈ Numerals

lemma mem_Numerals:

  z ∈ Numerals

lemma BIT_induct:

  [| P Numeral.Pls; P Numeral.Min;
     !!x. [| P x; x ≠ Numeral.Pls |] ==> P (x BIT bit.B0);
     !!x. [| P x; x ≠ Numeral.Min |] ==> P (x BIT bit.B1) |]
  ==> P x

Injectivity of BIT

lemma BIT_inject:

  x BIT a = y BIT b ==> x = ya = b

lemma BIT_eq:

  (x BIT a = y BIT b) = (x = ya = b)

lemma BIT_eq_Pls:

  (w BIT b = Numeral.Pls) = (w = Numeral.Pls ∧ b = bit.B0)

lemma BIT_eq_Min:

  (w BIT b = Numeral.Min) = (w = Numeral.Min ∧ b = bit.B1)

lemma Pls_eq_BIT:

  (Numeral.Pls = w BIT b) = (w = Numeral.Pls ∧ b = bit.B0)

lemma Min_eq_BIT:

  (Numeral.Min = w BIT b) = (w = Numeral.Min ∧ b = bit.B1)

lemma Min_neq_Pls:

  Numeral.Min ≠ Numeral.Pls

lemma Pls_neq_Min:

  Numeral.Pls ≠ Numeral.Min

lemma bin_injects:

  (x BIT a = y BIT b) = (x = ya = b)
  (w BIT b = Numeral.Pls) = (w = Numeral.Pls ∧ b = bit.B0)
  (w BIT b = Numeral.Min) = (w = Numeral.Min ∧ b = bit.B1)
  (Numeral.Pls = w BIT b) = (w = Numeral.Pls ∧ b = bit.B0)
  (Numeral.Min = w BIT b) = (w = Numeral.Min ∧ b = bit.B1)
  Numeral.Min ≠ Numeral.Pls
  Numeral.Pls ≠ Numeral.Min

lemma BIT_exhausts:

w b. x = w BIT b

lemma div2_BIT:

  div2 (w BIT b) = w

lemma div2_Pls:

  div2 Numeral.Pls = Numeral.Pls

lemma div2_Min:

  div2 Numeral.Min = Numeral.Min

lemma lsb_BIT:

  lsb (w BIT b) = b

lemma lsb_Pls:

  lsb Numeral.Pls = bit.B0

lemma lsb_Min:

  lsb Numeral.Min = bit.B1

lemma div2_BIT_lsb:

  div2 x BIT lsb x = x

lemma div2_lsb_simps:

  div2 (w BIT b) = w
  div2 Numeral.Pls = Numeral.Pls
  div2 Numeral.Min = Numeral.Min
  lsb (w BIT b) = b
  lsb Numeral.Pls = bit.B0
  lsb Numeral.Min = bit.B1
  div2 x BIT lsb x = x

lemma wf_div2:

  wf {(div2 w, w) |w. w ≠ Numeral.Pls ∧ w ≠ Numeral.Min}

Testing bit positions

lemma getbit_Pls:

  getbit Numeral.Pls n = bit.B0

lemma getbit_Min:

  getbit Numeral.Min n = bit.B1

lemma getbit_Pls_rev:

n. getbit x n = bit.B0 ==> x = Numeral.Pls

lemma getbit_Min_rev:

n. getbit x n = bit.B1 ==> x = Numeral.Min

lemma getbit_ext:

n. getbit x n = getbit y n ==> x = y

lemma expand_getbit_eq:

  (x = y) = (∀n. getbit x n = getbit y n)