Theory RegisterMachineSimulation
subsection ‹Simulation of a Register Machine›
theory RegisterMachineSimulation
imports RegisterMachineProperties "Digit_Expansions.Binary_Operations"
begin
definition B :: "nat ⇒ nat" where
"(B c) = 2^(Suc c)"
definition "RLe c p b q l = (∑t = 0..q. b^t * R c p l t)"
definition "SKe c p b q k = (∑t = 0..q. b^t * S c p k t)"
definition "ZLe c p b q l = (∑t = 0..q. b^t * Z c p l t)"
fun sum_radd :: "program ⇒ register ⇒ (nat ⇒ nat) ⇒ nat"
where "sum_radd p l f = (∑k = 0..length p-1. if isadd (p!k) ∧ l = modifies (p!k) then f k else 0)"
abbreviation sum_radd_abbrev (‹∑R+ _ _ _› [999, 999, 999] 1000)
where "(∑R+ p l f) ≡ (sum_radd p l f)"
fun sum_rsub :: "program ⇒ register ⇒ (nat ⇒ nat) ⇒ nat"
where "sum_rsub p l f = (∑k = 0..length p-1. if issub (p!k) ∧ l = modifies (p!k) then f k else 0)"
abbreviation sum_rsub_abbrev (‹∑R- _ _ _ › [999, 999, 999] 1000)
where "(∑R- p l f) ≡ (sum_rsub p l f)"
fun sum_sadd :: "program ⇒ state ⇒ (nat ⇒ nat) ⇒ nat"
where "sum_sadd p d f = (∑k = 0..length p-1. if isadd (p!k) ∧ d = goes_to (p!k) then f k else 0)"
abbreviation sum_sadd_abbrev (‹∑S+ _ _ _ › [999, 999, 999] 1000)
where "(∑S+ p d f) ≡ (sum_sadd p d f)"
fun sum_ssub_nzero :: "program ⇒ state ⇒ (nat ⇒ nat) ⇒ nat"
where "sum_ssub_nzero p d f = (∑k = 0..length p-1. if issub (p!k) ∧ d = goes_to (p!k) then f k else 0)"
abbreviation sum_ssub_nzero_abbrev (‹∑S- _ _ _ › [999, 999, 999] 1000)
where "(∑S- p d f) ≡ (sum_ssub_nzero p d f)"
fun sum_ssub_zero :: "program ⇒ state ⇒ (nat ⇒ nat) ⇒ nat"
where "sum_ssub_zero p d f = (∑k = 0..length p-1. if issub (p!k) ∧ d = goes_to_alt (p!k) then f k else 0)"
abbreviation sum_ssub_zero_abbrev (‹∑S0 _ _ _ › [999, 999, 999] 1000)
where "(∑S0 p d f) ≡ (sum_ssub_zero p d f)"
declare sum_radd.simps[simp del]
declare sum_rsub.simps[simp del]
declare sum_sadd.simps[simp del]
declare sum_ssub_nzero.simps[simp del]
declare sum_ssub_zero.simps[simp del]
text ‹Special sum cong lemmas›
lemma sum_sadd_cong:
assumes "∀k. k ≤ length p-1 ∧ isadd (p!k) ∧ l = goes_to (p!k) ⟶ f k = g k"
shows "∑S+ p l f = ∑S+ p l g"
unfolding sum_sadd.simps
by (rule sum.cong, simp) (rule if_cong, simp_all add: assms)
lemma sum_ssub_nzero_cong:
assumes "∀k. k ≤ length p - 1 ∧ issub (p!k) ∧ l = goes_to (p!k) ⟶ f k = g k"
shows "∑S- p l f = ∑S- p l g"
unfolding sum_ssub_nzero.simps
by (rule sum.cong, simp) (rule if_cong, simp_all add: assms)
lemma sum_ssub_zero_cong:
assumes "∀k. k ≤ length p - 1 ∧ issub (p!k) ∧ l = goes_to_alt (p!k) ⟶ f k = g k"
shows "∑S0 p l f = ∑S0 p l g"
unfolding sum_ssub_zero.simps
by (rule sum.cong, simp) (rule if_cong, simp_all add: assms)
lemma sum_radd_cong:
assumes "∀k. k ≤ length p - 1 ∧ isadd (p!k) ∧ l = modifies (p!k) ⟶ f k = g k"
shows "∑R+ p l f = ∑R+ p l g"
unfolding sum_radd.simps
by (rule sum.cong, simp) (rule if_cong, simp_all add: assms)
lemma sum_rsub_cong:
assumes "∀k. k ≤ length p - 1 ∧ issub (p!k) ∧ l = modifies (p!k) ⟶ f k = g k"
shows "∑R- p l f = ∑R- p l g"
unfolding sum_rsub.simps
by (rule sum.cong, simp) (rule if_cong, simp_all add: assms)
text ‹Properties and simple lemmas›
lemma RLe_equivalent: "RL c p b q l = RLe c p b q l"
by (induction q arbitrary: c) (auto simp add: RLe_def R_def RL.simps(1) RL_simp)
lemma SKe_equivalent: "SK c p b q k = SKe c p b q k"
by (induction q arbitrary: c) (auto simp add: SKe_def S_def SK.simps(1) S2_def SK_simp)
lemma ZLe_equivalent: "ZL c p b q l = ZLe c p b q l"
by (induction q arbitrary: c) (auto simp add: ZLe_def ZL.simps(1) R_def Z2_def Z_def ZL_simp)
lemma sum_radd_distrib: "a * (∑R+ p l f) = (∑R+ p l (λk. a * f k))"
by (auto simp add: sum_radd.simps sum_distrib_left; smt mult_is_0 sum.cong)
lemma sum_rsub_distrib: "a * (∑R- p l f) = (∑R- p l (λk. a * f k))"
by (auto simp add: sum_rsub.simps sum_distrib_left; smt mult_is_0 sum.cong)
lemma sum_sadd_distrib: "a * (∑S+ p d f) = (∑S+ p d (λk. a * f k))" for a
by (auto simp add: sum_sadd.simps sum_distrib_left; smt mult_is_0 sum.cong)
lemma sum_ssub_nzero_distrib: "a * (∑S- p d f) = (∑S- p d (λk. a * f k))" for a
by (auto simp add: sum_ssub_nzero.simps sum_distrib_left; smt mult_is_0 sum.cong)
lemma sum_ssub_zero_distrib: "a * (∑S0 p d f) = (∑S0 p d (λk. a * f k))" for a
by (auto simp add: sum_ssub_zero.simps sum_distrib_left; smt mult_is_0 sum.cong)
lemma sum_distrib:
fixes SX :: "program ⇒ nat ⇒ (nat ⇒ nat) ⇒ nat"
and p :: program
assumes SX_simps: "⋀h. SX p x h = (∑k = 0..length p-1. if g x k then h k else 0)"
shows "SX p x h1 + SX p x h2 = SX p x (λk. h1 k + h2 k)"
by (subst SX_simps)+ (auto simp: sum.distrib[symmetric] intro: sum.cong)
lemma sum_commutative:
fixes SX :: "program ⇒ nat ⇒ (nat ⇒ nat) ⇒ nat"
and p :: program
assumes SX_simps: "⋀h. SX p x h = (∑k = 0..length p-1. if g x k then h k else 0)"
shows "(∑t=0..q::nat. SX p x (λk. f k t))
= (SX p x (λk. ∑t=0..q. f k t))"
proof (induction q)
case 0
then show ?case by (auto)
next
case (Suc q)
have SX_add: "SX p x h1 + SX p x h2 = SX p x (λk. h1 k + h2 k)" for h1 h2
by (subst sum_distrib[where ?h1.0 = "h1"]) (auto simp: SX_simps) +
have h1: "(∑t≤(Suc q). SX p x (λk. f k t)) = SX p x (λk. f k (Suc q)) + sum (λt. SX p x (λk. f k t)) {0..q}"
by (auto simp add: sum.atLeast0_atMost_Suc add.commute atMost_atLeast0)
also have h2: "... = SX p x (λk. f k (Suc q)) + SX p x (λk. sum (f k){0..q})"
using Suc.IH Suc.prems by auto
also have h3: "... = SX p x (λk. sum (f k) {0..(Suc q)})"
by (subst SX_add) (auto simp: atLeast0_atMost_Suc)
finally show ?case using Suc.IH by (simp add: atMost_atLeast0)
qed
lemma sum_radd_commutative: "(∑t=0..(q::nat). ∑R+ p l (λk. f k t)) = (∑R+ p l (λk. ∑t=0..q. f k t))"
by (rule sum_commutative sum_radd.simps) +
lemma sum_rsub_commutative: "(∑t=0..(q::nat). ∑R- p l (λk. f k t)) = (∑R- p l (λk. ∑t=0..q. f k t))"
by (rule sum_commutative sum_rsub.simps) +
lemma sum_sadd_commutative: "(∑t=0..(q::nat). ∑S+ p l (λk. f k t)) = (∑S+ p l (λk. ∑t=0..q. f k t))"
by (rule sum_commutative sum_sadd.simps) +
lemma sum_ssub_nzero_commutative: "(∑t=0..(q::nat). ∑S- p l (λk. f k t)) = (∑S- p l (λk. ∑t=0..q. f k t))"
by (rule sum_commutative sum_ssub_nzero.simps) +
lemma sum_ssub_zero_commutative: "(∑t=0..(q::nat). ∑S0 p l (λk. f k t)) = (∑S0 p l (λk. ∑t=0..q. f k t))"
by (rule sum_commutative sum_ssub_zero.simps) +
lemma sum_int: "c ≤ a + b ⟹ int(a + b - c) = int(a) + int(b) - int(c)"
by (simp add: SMT.int_plus)
lemma ZLe_bounded: "b > 2 ⟹ ZLe c p b q l < b ^ (Suc q)"
using Z_bounded ZLe_def
proof (induction q)
case 0
then show ?case by (simp add: Z_bounded ZLe_def Z_def)
next
case (Suc q)
have "ZLe c p b (Suc q) l = b ^ (Suc q) * Z c p l (Suc q) + ZLe c p b q l"
by (auto simp: ZLe_def)
also have "ZLe c p b q l < b ^ (Suc q)" using Suc.IH
by (auto simp: ZLe_def Z_def Suc.prems(1))
also have "b ^ (Suc q) * Z c p l (Suc q) ≤ b ^ (Suc q)" using Suc.prems(1)
by (auto simp: Z_def)
finally have "ZLe c p b (Suc q) l < 2 * b ^ (Suc q)"
by auto
also have "... < b ^ Suc (Suc q)"
using Suc.prems(1) by auto
finally show ?case by simp
qed
lemma SKe_bounded: "b > 2 ⟹ SKe c p b q k < b ^ (Suc q)"
proof (induction q)
case 0
then show ?case by (auto simp add: SKe_def S_bounded S_def)
next
case (Suc q)
have "SKe c p b (Suc q) k = b ^ (Suc q) * S c p k (Suc q) + SKe c p b q k"
by (auto simp: SKe_def)
also have "SKe c p b q k < b ^ (Suc q)" using Suc.IH
by (auto simp: Suc.prems(1))
also have "b ^ (Suc q) * S c p k (Suc q) ≤ b ^ (Suc q)" using Suc.prems(1)
by (auto simp: S_def)
finally have "SKe c p b (Suc q) k < 2 * b ^ (Suc q)"
by auto
also have "... < b ^ Suc (Suc q)"
using Suc.prems(1) by auto
finally show ?case by simp
qed
lemma mult_to_bitAND:
assumes cells_bounded: "cells_bounded ic p c"
and "c > 1"
and "b = B c"
shows "(∑t=0..q. b^t * (Z ic p l t * S ic p k t))
= ZLe ic p b q l && SKe ic p b q k"
proof (induction q arbitrary: ic p c l k)
case 0
then show ?case using S_bounded Z_bounded
by (auto simp add: SKe_def ZLe_def bitAND_single_bit_mult_equiv)
next
case (Suc q)
have b4: "b > 2" using assms(2-3) apply (auto simp add: B_def)
by (metis One_nat_def Suc_less_eq2 lessI numeral_2_eq_2 power_gt1)
have ske: "SKe ic p b q k < b ^ (Suc q)" using SKe_bounded b4 by auto
have zle: "ZLe ic p b q l < b ^ (Suc q)" using ZLe_bounded b4 by auto
have ih: "(∑t = 0..q. b ^ t * (Z ic p l t * S ic p k t)) = ZLe ic p b q l && SKe ic p b q k"
using Suc.IH by auto
have "(∑t = 0..Suc q. b ^ t * (Z ic p l t * S ic p k t))
= b ^(Suc q) * (Z ic p l (Suc q) * S ic p k (Suc q)) + (∑t = 0..q. b ^ t * (Z ic p l t * S ic p k t))"
by (auto simp: sum.atLeast0_atMost_Suc add.commute)
also have "... = b ^ (Suc q) * (Z ic p l (Suc q) * S ic p k (Suc q)) + (ZLe ic p b q l && SKe ic p b q k)"
by (auto simp add: ih)
also have "... = b ^ (Suc q) * (Z ic p l (Suc q) && S ic p k (Suc q)) + (ZLe ic p b q l && SKe ic p b q k)"
using bitAND_single_bit_mult_equiv S_bounded Z_bounded by (auto)
also have "... = (b ^(Suc q) * Z ic p l (Suc q) + ZLe ic p b q l) && (b ^ (Suc q) * S ic p k (Suc q) + SKe ic p b q k)"
using bitAND_linear ske zle
by (auto) (smt B_def assms(3) bitAND_linear mult.commute power_Suc power_mult)
also have "... = (ZLe ic p b (Suc q) l && SKe ic p b (Suc q) k)"
by (auto simp: ZLe_def SKe_def add.commute)
finally show ?case by simp
qed
lemma sum_bt:
fixes b q :: nat
assumes "b > 2"
shows "(∑t = 0..q. b^t) < b ^ (Suc q)"
using assms
proof (induction q, auto)
fix qb :: nat
assume "sum ((^) b) {0..qb} < b * b ^ qb"
then have f1: "sum ((^) b) {0..qb} < b ^ Suc qb"
by fastforce
have "b ^ Suc qb * 2 < b ^ Suc (Suc qb)"
using assms by force
then have "2 * b ^ Suc qb < b ^ Suc (Suc qb)"
by simp
then have "b ^ Suc qb + sum ((^) b) {0..qb} < b ^ Suc (Suc qb)"
using f1 by linarith
then show "sum ((^) b) {0..qb} + b * b ^ qb < b * (b * b ^ qb)"
by simp
qed
lemma mult_to_bitAND_state:
assumes cells_bounded: "cells_bounded ic p c"
and c: "c > 1"
and b: "b = B c"
shows "(∑t=0..q. b^t * ((1 - Z ic p l t) * S ic p k t))
= ((∑t = 0..q. b^t) - ZLe ic p b q l) && SKe ic p b q k"
proof (induction q arbitrary: ic p c l k)
case 0
show ?case using Z_def S_def ZLe_def SKe_def by auto
next
case (Suc q)
have b4: "b > 2" using assms(2-3) apply (auto simp add: B_def)
by (metis One_nat_def Suc_less_eq2 lessI numeral_2_eq_2 power_gt1)
have ske: "SKe ic p b q k < b ^ (Suc q)" using SKe_bounded b4 by auto
have zle: "ZLe ic p b q l < b ^ (Suc q)" using ZLe_bounded b4 by auto
define cst where "cst ≡ Suc q"
define e where "e ≡ ∑t = 0..Suc q. b^t"
have "(∑t = 0..q. b^t) < b ^ (Suc q)"
using sum_bt b4 by auto
hence zle2: "(∑t = 0..q. b^t) - ZLe ic p b q l < b ^ (Suc q)"
using less_imp_diff_less by blast
have "(∑t = 0..x. b^t) - ZLe ic p b x l = (∑t=0..x. b^t - b^t * Z ic p l t)" for x
unfolding ZLe_def
using Z_bounded sum_subtractf_nat[where ?f = "(^) b" and ?g = "λt. b ^ t * Z ic p l t"]
by auto
hence aux_sum: "(∑t = 0..x. b^t) - ZLe ic p b x l = (∑t=0..x. b^t * (1 - Z ic p l t))" for x
using diff_Suc_1 diff_mult_distrib2 by auto
have aux1: "b ^(Suc q) * (1 - Z ic p l (Suc q)) + (∑t=0..q. b^t * (1 - Z ic p l t))
= (∑t = 0..cst. b ^ t * (1 - Z ic p l t))"
by (auto simp: sum.atLeast0_atMost_Suc cst_def)
also have aux2: "... = (∑t = 0..cst. b ^ t) - ZLe ic p b cst l"
unfolding e_def ZLe_def using aux_sum[of "cst"]
by (auto simp: ZLe_def)
finally have aux_add_sub:
"(b ^(Suc q) * (1 - Z ic p l (Suc q)) + ((∑t = 0..q. b^t) - ZLe ic p b q l))
= (e - ZLe ic p b (Suc q) l)"
by (auto simp: cst_def e_def aux_sum)
hence ih: "(∑t = 0..q. b ^ t * ((1 - Z ic p l t) * S ic p k t))
= (∑t = 0..q. b^t) - ZLe ic p b q l && SKe ic p b q k"
using Suc[of "ic" "p" "l" "k"] by auto
have "(∑t = 0..Suc q. b ^ t * ((1 - Z ic p l t) * S ic p k t))
= (∑t = 0.. q. b ^ t * ((1 - Z ic p l t) * S ic p k t))
+ b^(Suc q) * ((1 - Z ic p l (Suc q)) * S ic p k (Suc q))"
by (auto cong: sum.cong)
also have "... = ((∑t = 0..q. b^t) - ZLe ic p b q l && SKe ic p b q k)
+ b^(Suc q) * ((1 - Z ic p l (Suc q)) * S ic p k (Suc q))"
using ih by auto
also have "... = ((∑t = 0..q. b^t) - ZLe ic p b q l && SKe ic p b q k)
+ b^(Suc q) * ((1 - Z ic p l (Suc q)) && S ic p k (Suc q))"
using bitAND_single_bit_mult_equiv by (simp add: S_def)
also have "... = (b ^(Suc q) * (1 - Z ic p l (Suc q)) + ((∑t = 0..q. b^t) - ZLe ic p b q l))
&& (b ^ (Suc q) * S ic p k (Suc q) + SKe ic p b q k)"
using bitAND_linear ske zle2 B_def b
by (smt add_ac(2) mult_ac(2) bitAND_linear power.simps(2) power_mult power_mult_distrib)
also have "... = (e - ZLe ic p b (Suc q) l && SKe ic p b (Suc q) k)"
using SKe_def aux_add_sub by (auto simp: add.commute)
finally show ?case by (auto simp: e_def)
qed
end