Theory States_Proof
section "Big + Small Proofs"
theory States_Proof
imports States_Aux Big_Proof Small_Proof
begin
lemmas state_splits = idle.splits common_state.splits small_state.splits big_state.splits
lemmas invar_steps = Big_Proof.invar_step Common_Proof.invar_step Small_Proof.invar_step
lemma invar_list_big_first:
"invar states ⟹ list_big_first states = list_current_big_first states"
using app_rev
by(cases states)(auto split: prod.splits)
lemma step_lists [simp]: "invar states ⟹ lists (step states) = lists states"
proof(induction states rule: lists.induct)
case (1 dir currentB big auxB count currentS small auxS)
then show ?case
proof(induction
"(States dir (Big1 currentB big auxB count) (Small1 currentS small auxS))"
rule: step_states.induct)
case 1
then show ?case
by(cases currentB) auto
next
case ("2_1" count')
then have "0 < size big"
by(cases currentB) auto
then have big_not_empty: "Stack_Aux.list big ≠ []"
by (simp add: Stack_Proof.size_not_empty Stack_Proof.list_empty)
with "2_1" show ?case
using
take_rev_step[of "Stack_Aux.list big" count' auxB]
Stack_Proof.list_empty[symmetric, of small]
apply (cases currentB)
by(auto simp: first_hd funpow_swap1 take_rev_step simp del: take_rev_def)
qed
next
case ("2_1" dir common small)
then show ?case
using step_list_Small2[of small]
by(auto split: small_state.splits)
next
case ("2_2" dir big current auxS big newS count)
then show ?case
using step_list_Small2[of "Small2 current auxS big newS count"]
by auto
next
case ("2_3" dir big common)
then show ?case
by auto
qed
lemma step_lists_current [simp]:
"invar states ⟹ lists_current (step states) = lists_current states"
by(induction states rule: step_states.induct)(auto split: current.splits)
lemma push_big: "lists (States dir big small) = (big', small')
⟹ lists (States dir (Big.push x big) small) = (x # big', small')"
proof(induction "States dir (Big.push x big) small" rule: lists.induct)
case 1
then show ?case
proof(induction x big rule: Big.push.induct)
case 1
then show ?case
by auto
next
case (2 x current big aux count)
then show ?case
by(cases current) auto
qed
next
case "2_1"
then show ?case
by(cases big) auto
qed auto
lemma push_small_lists: "
invar (States dir big small)
⟹ lists (States dir big (Small.push x small)) = (big', x # small') ⟷
lists (States dir big small) = (big', small')"
apply(induction "States dir big (Small.push x small)" rule: lists.induct)
by (auto split: current.splits small_state.splits)
lemma list_small_big: "
list_small_first (States dir big small) = list_current_small_first (States dir big small) ⟷
list_big_first (States dir big small) = list_current_big_first (States dir big small)"
using app_rev
by(auto split: prod.splits)
lemma list_big_first_pop_big [simp]: "⟦
invar (States dir big small);
0 < size big;
Big.pop big = (x, big')⟧
⟹ x # list_big_first (States dir big' small) = list_big_first (States dir big small)"
by(induction "States dir big small" rule: lists.induct)(auto split: prod.splits)
lemma list_current_big_first_pop_big [simp]: "⟦
invar (States dir big small);
0 < size big;
Big.pop big = (x, big')⟧
⟹ x # list_current_big_first (States dir big' small) =
list_current_big_first (States dir big small)"
by auto
lemma lists_big_first_pop_big: "⟦
invar (States dir big small);
0 < size big;
Big.pop big = (x, big')⟧
⟹ list_big_first (States dir big' small) = list_current_big_first (States dir big' small)"
by (metis invar_list_big_first list_big_first_pop_big list_current_big_first_pop_big list.sel(3))
lemma lists_small_first_pop_big: "⟦
invar (States dir big small);
0 < size big;
Big.pop big = (x, big')⟧
⟹ list_small_first (States dir big' small) = list_current_small_first (States dir big' small)"
by (meson lists_big_first_pop_big list_small_big)
lemma list_small_first_pop_small [simp]: "⟦
invar (States dir big small);
0 < size small;
Small.pop small = (x, small')⟧
⟹ x # list_small_first (States dir big small') = list_small_first (States dir big small)"
proof(induction "States dir big small" rule: lists.induct)
case (1 currentB big auxB count currentS small auxS)
then show ?case
by(cases currentS)(auto simp: Cons_eq_appendI)
next
case ("2_1" common)
then show ?case
proof(induction small rule: Small.pop.induct)
case (1 common)
then show ?case
by(cases "Common.pop common")(auto simp: Cons_eq_appendI)
next
case 2
then show ?case by auto
next
case 3
then show ?case
by(cases "Common.pop common")(auto simp: Cons_eq_appendI)
qed
next
case ("2_2" current)
then show ?case
by(induction current rule: Current.pop.induct)
(auto simp: first_hd rev_take Suc_diff_le)
next
case ("2_3" common)
then show ?case
by(cases "Common.pop common")(auto simp: Cons_eq_appendI)
qed
lemma list_current_small_first_pop_small [simp]: "⟦
invar (States dir big small);
0 < size small;
Small.pop small = (x, small')⟧
⟹ x # list_current_small_first (States dir big small') =
list_current_small_first (States dir big small)"
by auto
lemma lists_small_first_pop_small: "⟦
invar (States dir big small);
0 < size small;
Small.pop small = (x, small')⟧
⟹ list_small_first (States dir big small') = list_current_small_first (States dir big small')"
by (metis (no_types, opaque_lifting) invar_states.simps list.sel(3)
list_current_small_first_pop_small list_small_first_pop_small)
lemma invars_pop_big: "⟦
invar (States dir big small);
0 < size big;
Big.pop big = (x, big')⟧
⟹ invar big' ∧ invar small"
by(auto simp: Big_Proof.invar_pop)
lemma invar_pop_big_aux: "⟦
invar (States dir big small);
0 < size big;
Big.pop big = (x, big')⟧
⟹ (case (big', small) of
(Big1 _ big _ count, Small1 (Current _ _ old remained) small _) ⇒
size big - count = remained - size old ∧ count ≥ size small
| (_, Small1 _ _ _) ⇒ False
| (Big1 _ _ _ _, _) ⇒ False
| _ ⇒ True
)"
by(auto split: big_state.splits small_state.splits prod.splits)
lemma invar_pop_big: "⟦
invar (States dir big small);
0 < size big;
Big.pop big = (x, big')⟧
⟹ invar (States dir big' small)"
using invars_pop_big[of dir big small x big']
lists_small_first_pop_big[of dir big small x big']
invar_pop_big_aux[of dir big small x big']
by auto
lemma invars_pop_small: "⟦
invar (States dir big small);
0 < size small;
Small.pop small = (x, small')⟧
⟹ invar big ∧ invar small'"
by(auto simp: Small_Proof.invar_pop)
lemma invar_pop_small_aux: "⟦
invar (States dir big small);
0 < size small;
Small.pop small = (x, small')⟧
⟹ (case (big, small') of
(Big1 _ big _ count, Small1 (Current _ _ old remained) small _) ⇒
size big - count = remained - size old ∧ count ≥ size small
| (_, Small1 _ _ _) ⇒ False
| (Big1 _ _ _ _, _) ⇒ False
| _ ⇒ True
)"
proof(induction small rule: Small.pop.induct)
case 1
then show ?case
by(auto split: big_state.splits small_state.splits prod.splits)
next
case (2 current)
then show ?case
proof(induction current rule: Current.pop.induct)
case 1
then show ?case
by(auto split: big_state.splits)
next
case 2
then show ?case
by(auto split: big_state.splits)
qed
next
case 3
then show ?case
by(auto split: big_state.splits)
qed
lemma invar_pop_small: "⟦
invar (States dir big small);
0 < size small;
Small.pop small = (x, small')
⟧ ⟹ invar (States dir big small')"
using invars_pop_small[of dir big small x small']
lists_small_first_pop_small[of dir big small x small']
invar_pop_small_aux[of dir big small x small']
by fastforce
lemma invar_push_big: "invar (States dir big small) ⟹ invar (States dir (Big.push x big) small)"
proof(induction x big arbitrary: small rule: Big.push.induct)
case 1
then show ?case
by(auto simp: Common_Proof.invar_push)
next
case (2 x current big aux count)
then show ?case
by(cases current)(auto split: prod.splits small_state.splits)
qed
lemma invar_push_small: "invar (States dir big small)
⟹ invar (States dir big (Small.push x small))"
proof(induction x small arbitrary: big rule: Small.push.induct)
case (1 x state)
then show ?case
by(auto simp: Common_Proof.invar_push split: big_state.splits)
next
case (2 x current small auxS)
then show ?case
by(induction x current rule: Current.push.induct)(auto split: big_state.splits)
next
case (3 x current auxS big newS count)
then show ?case
by(induction x current rule: Current.push.induct)(auto split: big_state.splits)
qed
lemma step_invars:"⟦invar states; step states = States dir big small⟧ ⟹ invar big ∧ invar small"
proof(induction states rule: step_states.induct)
case (1 dir currentB big' auxB currentS small' auxS)
with Big_Proof.invar_step have "invar (Big1 currentB big' auxB 0)"
by auto
with 1 have invar_big: "invar big"
using Big_Proof.invar_step[of "Big1 currentB big' auxB 0"]
by auto
from 1 have invar_small: "invar small"
using Stack_Proof.list_empty_size[of small']
by(cases currentS) auto
from invar_small invar_big show ?case
by simp
next
case ("2_1" dir current big aux count small)
then show ?case
using Big_Proof.invar_step[of "Big1 current big aux (Suc count)"]
Small_Proof.invar_step[of small]
by simp
next
case "2_2"
then show ?case
by(auto simp: Common_Proof.invar_step Small_Proof.invar_step)
next
case ("2_3" dir big current auxS big' newS count)
then show ?case
using Big_Proof.invar_step[of big]
Small_Proof.invar_step[of "Small2 current auxS big' newS count"]
by auto
next
case "2_4"
then show ?case
by(auto simp: Common_Proof.invar_step Big_Proof.invar_step)
qed
lemma step_lists_small_first: "invar states ⟹
list_small_first (step states) = list_current_small_first (step states)"
using step_lists_current step_lists invar_states.elims(2)
by fastforce
lemma invar_step_aux: "invar states ⟹(case step states of
(States _ (Big1 _ big _ count) (Small1 (Current _ _ old remained) small _)) ⇒
size big - count = remained - size old ∧ count ≥ size small
| (States _ _ (Small1 _ _ _)) ⇒ False
| (States _ (Big1 _ _ _ _) _) ⇒ False
| _ ⇒ True
)"
proof(induction states rule: step_states.induct)
case ("2_1" dir current big aux count small)
then show ?case
proof(cases small)
case (Small1 current small auxS)
with "2_1" show ?thesis
using Stack_Proof.size_empty[symmetric, of small]
by(auto split: current.splits)
qed auto
qed (auto split: big_state.splits small_state.splits)
lemma invar_step: "invar (states :: 'a states) ⟹ invar (step states)"
using invar_step_aux[of states] step_lists_small_first[of states]
by(cases "step states")(auto simp: step_invars)
lemma step_consistent [simp]:
"⟦⋀states. invar (states :: 'a states) ⟹ P (step states) = P states; invar states⟧
⟹ P states = P ((step ^^n) states)"
by(induction n arbitrary: states)
(auto simp: States_Proof.invar_step funpow_swap1)
lemma step_consistent_2:
"⟦⋀states. ⟦invar (states :: 'a states); P states⟧ ⟹ P (step states); invar states; P states⟧
⟹ P ((step ^^n) states)"
by(induction n arbitrary: states)
(auto simp: States_Proof.invar_step funpow_swap1)
lemma size_ok'_Suc: "size_ok' states (Suc steps) ⟹ size_ok' states steps"
by(induction states steps rule: size_ok'.induct) auto
lemma size_ok'_decline: "size_ok' states x ⟹ x ≥ y ⟹ size_ok' states y"
by(induction states x rule: size_ok'.induct) auto
lemma remaining_steps_0 [simp]: "⟦invar (states :: 'a states); remaining_steps states = 0⟧
⟹ remaining_steps (step states) = 0"
by(induction states rule: step_states.induct)
(auto split: current.splits small_state.splits)
lemma remaining_steps_0': "⟦invar (states :: 'a states); remaining_steps states = 0⟧
⟹ remaining_steps ((step ^^ n) states) = 0"
by(induction n arbitrary: states)(auto simp: invar_step funpow_swap1)
lemma remaining_steps_decline_Suc:
"⟦invar (states :: 'a states); 0 < remaining_steps states⟧
⟹ Suc (remaining_steps (step states)) = remaining_steps states"
proof(induction states rule: step_states.induct)
case 1
then show ?case
by(auto simp: max_def split: big_state.splits small_state.splits current.splits)
next
case ("2_1" _ _ _ _ _ small)
then show ?case
by(cases small)(auto split: current.splits)
next
case ("2_2" dir big small)
then show ?case
proof(cases small)
case (Small2 current auxS big newS count)
with "2_2" show ?thesis
using Stack_Proof.size_empty_2[of big]
by(cases current) auto
qed auto
next
case ("2_3" dir big current auxS big' newS count)
then show ?case
proof(induction big)
case Big1
then show ?case by auto
next
case Big2
then show ?case
using Stack_Proof.size_empty_2[of big']
by(cases current) auto
qed
next
case ("2_4" _ big)
then show ?case
by(cases big) auto
qed
lemma remaining_steps_decline_sub [simp]: "invar (states :: 'a states)
⟹ remaining_steps (step states) = remaining_steps states - 1"
using Suc_sub[of "remaining_steps (step states)" "remaining_steps states"]
by(cases "0 < remaining_steps states") (auto simp: remaining_steps_decline_Suc)
lemma remaining_steps_decline: "invar (states :: 'a states)
⟹ remaining_steps (step states) ≤ remaining_steps states"
using remaining_steps_decline_sub[of states] by auto
lemma remaining_steps_decline_n_steps [simp]:
"⟦invar (states :: 'a states); remaining_steps states ≤ n⟧
⟹ remaining_steps ((step ^^ n) states) = 0"
by(induction n arbitrary: states)(auto simp: funpow_swap1 invar_step)
lemma remaining_steps_n_steps_plus [simp]:
"⟦n ≤ remaining_steps states; invar (states :: 'a states)⟧
⟹ remaining_steps ((step ^^ n) states) + n = remaining_steps states"
by(induction n arbitrary: states)(auto simp: funpow_swap1 invar_step)
lemma remaining_steps_n_steps_sub [simp]: "invar (states :: 'a states)
⟹ remaining_steps ((step ^^ n) states) = remaining_steps states - n"
by(induction n arbitrary: states)(auto simp: funpow_swap1 invar_step)
lemma step_size_new_small [simp]:
"⟦invar (States dir big small); step (States dir big small) = States dir' big' small'⟧
⟹ size_new small' = size_new small"
proof(induction "States dir big small" rule: step_states.induct)
case 1
then show ?case
by auto
next
case "2_1"
then show ?case
by(auto split: small_state.splits)
next
case "2_2"
then show ?case
by(auto split: small_state.splits current.splits)
next
case "2_3"
then show ?case
by(auto split: current.splits)
next
case "2_4"
then show ?case
by auto
qed
lemma step_size_new_small_2 [simp]:
"invar states ⟹ size_new_small (step states) = size_new_small states"
by(cases states; cases "step states") auto
lemma step_size_new_big [simp]:
"⟦invar (States dir big small); step (States dir big small) = States dir' big' small'⟧
⟹ size_new big' = size_new big"
proof(induction "States dir big small" rule: step_states.induct)
case 1
then show ?case
by(auto split: current.splits)
next
case "2_1"
then show ?case
by auto
next
case "2_2"
then show ?case
by auto
next
case "2_3"
then show ?case
by(auto split: big_state.splits)
next
case "2_4"
then show ?case
by(auto split: big_state.splits)
qed
lemma step_size_new_big_2 [simp]:
"invar states ⟹ size_new_big (step states) = size_new_big states"
by(cases states; cases "step states") auto
lemma step_size_small [simp]:
"⟦invar (States dir big small); step (States dir big small) = States dir' big' small'⟧
⟹ size small' = size small"
proof(induction "States dir big small" rule: step_states.induct)
case "2_3"
then show ?case
by(auto split: current.splits)
qed auto
lemma step_size_small_2 [simp]:
"invar states ⟹ size_small (step states) = size_small states"
by(cases states; cases "step states") auto
lemma step_size_big [simp]:
"⟦invar (States dir big small); step (States dir big small) = States dir' big' small'⟧
⟹ size big' = size big"
proof(induction "States dir big small" rule: step_states.induct)
case 1
then show ?case
by(auto split: current.splits)
next
case "2_1"
then show ?case
by(auto split: small_state.splits current.splits)
next
case "2_2"
then show ?case
by(auto split: small_state.splits current.splits)
next
case "2_3"
then show ?case
by(auto split: current.splits big_state.splits)
next
case "2_4"
then show ?case
by(auto split: big_state.splits)
qed
lemma step_size_big_2 [simp]:
"invar states ⟹ size_big (step states) = size_big states"
by(cases states; cases "step states") auto
lemma step_size_ok_1: "⟦
invar (States dir big small);
step (States dir big small) = States dir' big' small';
size_new big + remaining_steps (States dir big small) + 2 ≤ 3 * size_new small
⟧ ⟹ size_new big' + remaining_steps (States dir' big' small') + 2 ≤ 3 * size_new small'"
using step_size_new_small step_size_new_big remaining_steps_decline
by (smt (verit, ccfv_SIG) add.commute le_trans nat_add_left_cancel_le)
lemma step_size_ok_2: "⟦
invar (States dir big small);
step (States dir big small) = States dir' big' small';
size_new small + remaining_steps (States dir big small) + 2 ≤ 3 * size_new big
⟧ ⟹ size_new small' + remaining_steps (States dir' big' small') + 2 ≤ 3 * size_new big'"
using remaining_steps_decline step_size_new_small step_size_new_big
by (smt (verit, best) add_le_mono le_refl le_trans)
lemma step_size_ok_3: "⟦
invar (States dir big small);
step (States dir big small) = States dir' big' small';
remaining_steps (States dir big small) + 1 ≤ 4 * size small
⟧ ⟹ remaining_steps (States dir' big' small') + 1 ≤ 4 * size small'"
using remaining_steps_decline step_size_small
by (metis Suc_eq_plus1 Suc_le_mono le_trans)
lemma step_size_ok_4: "⟦
invar (States dir big small);
step (States dir big small) = States dir' big' small';
remaining_steps (States dir big small) + 1 ≤ 4 * size big
⟧ ⟹ remaining_steps (States dir' big' small') + 1 ≤ 4 * size big'"
using remaining_steps_decline step_size_big
by (metis (no_types, lifting) add_mono_thms_linordered_semiring(3) order.trans)
lemma step_size_ok: "⟦invar states; size_ok states⟧ ⟹ size_ok (step states)"
using step_size_ok_1 step_size_ok_2 step_size_ok_3 step_size_ok_4
by (smt (verit) invar_states.elims(1) size_ok'.elims(3) size_ok'.simps)
lemma step_n_size_ok: "⟦invar states; size_ok states⟧ ⟹ size_ok ((step ^^ n) states)"
using step_consistent_2[of size_ok states n] step_size_ok by blast
lemma step_push_size_small [simp]: "⟦
invar (States dir big small);
step (States dir big (Small.push x small)) = States dir' big' small'
⟧ ⟹ size small' = Suc (size small)"
using
invar_push_small[of dir big small x]
step_size_small[of dir big "Small.push x small" dir' big' small']
size_push[of small x]
by simp
lemma step_push_size_new_small [simp]: "⟦
invar (States dir big small);
step (States dir big (Small.push x small)) = States dir' big' small'
⟧ ⟹ size_new small' = Suc (size_new small)"
using
invar_push_small[of dir big small x]
step_size_new_small[of dir big "Small.push x small" dir' big' small']
size_new_push[of small x]
by simp
lemma step_push_size_big [simp]: "⟦
invar (States dir big small);
step (States dir (Big.push x big) small) = States dir' big' small'
⟧ ⟹ size big' = Suc (size big)"
using
invar_push_big[of dir big small x]
Big_Proof.size_push[of big]
step_size_big[of dir "Big.push x big" small dir' big' small']
by simp
lemma step_push_size_new_big [simp]: "⟦
invar (States dir big small);
step (States dir (Big.push x big) small) = States dir' big' small'
⟧ ⟹ size_new big' = Suc (size_new big)"
using
invar_push_big[of dir big small x]
step_size_new_big[of dir "Big.push x big" small dir' big' small']
Big_Proof.size_new_push[of big x]
by simp
lemma step_pop_size_big [simp]: "⟦
invar (States dir big small);
0 < size big;
Big.pop big = (x, bigP);
step (States dir bigP small) = States dir' big' small'
⟧ ⟹ Suc (size big') = size big"
using
invar_pop_big[of dir big small x bigP]
step_size_big[of dir bigP small dir' big' small']
Big_Proof.size_pop[of big x bigP]
by simp
lemma step_pop_size_new_big [simp]: "⟦
invar (States dir big small);
0 < size big; Big.pop big = (x, bigP);
step (States dir bigP small) = States dir' big' small'
⟧ ⟹ Suc (size_new big') = size_new big"
using
invar_pop_big[of dir big small x bigP]
Big_Proof.size_size_new[of big]
step_size_new_big[of dir bigP small dir' big' small']
Big_Proof.size_new_pop[of big x bigP]
by simp
lemma step_n_size_small [simp]: "⟦
invar (States dir big small);
(step ^^ n) (States dir big small) = States dir' big' small'
⟧ ⟹ size small' = size small"
using step_consistent[of size_small "States dir big small" n]
by simp
lemma step_n_size_big [simp]:
"⟦invar (States dir big small); (step ^^ n) (States dir big small) = States dir' big' small'⟧
⟹ size big' = size big"
using step_consistent[of size_big "States dir big small" n]
by simp
lemma step_n_size_new_small [simp]:
"⟦invar (States dir big small); (step ^^ n) (States dir big small) = States dir' big' small'⟧
⟹ size_new small' = size_new small"
using step_consistent[of size_new_small "States dir big small" n]
by simp
lemma step_n_size_new_big [simp]:
"⟦invar (States dir big small); (step ^^ n) (States dir big small) = States dir' big' small'⟧
⟹ size_new big' = size_new big"
using step_consistent[of size_new_big "States dir big small" n]
by simp
lemma step_n_push_size_small [simp]: "⟦
invar (States dir big small);
(step ^^ n) (States dir big (Small.push x small)) = States dir' big' small'
⟧ ⟹ size small' = Suc (size small)"
using step_n_size_small invar_push_small Small_Proof.size_push
by (metis invar_states.simps)
lemma step_n_push_size_new_small [simp]: "⟦
invar (States dir big small);
(step ^^ n) (States dir big (Small.push x small)) = States dir' big' small'
⟧ ⟹ size_new small' = Suc (size_new small)"
by (metis Small_Proof.size_new_push invar_states.simps invar_push_small step_n_size_new_small)
lemma step_n_push_size_big [simp]: "⟦
invar (States dir big small);
(step ^^ n) (States dir (Big.push x big) small) = States dir' big' small'
⟧ ⟹ size big' = Suc (size big)"
by (metis Big_Proof.size_push invar_states.simps invar_push_big step_n_size_big)
lemma step_n_push_size_new_big [simp]: "⟦
invar (States dir big small);
(step ^^ n) (States dir (Big.push x big) small) = States dir' big' small'
⟧ ⟹ size_new big' = Suc (size_new big)"
by (metis Big_Proof.size_new_push invar_states.simps invar_push_big step_n_size_new_big)
lemma step_n_pop_size_small [simp]: "⟦
invar (States dir big small);
0 < size small;
Small.pop small = (x, smallP);
(step ^^ n) (States dir big smallP) = States dir' big' small'
⟧ ⟹ Suc (size small') = size small"
using invar_pop_small size_pop step_n_size_small
by (metis (no_types, opaque_lifting) invar_states.simps)
lemma step_n_pop_size_new_small [simp]: "⟦
invar (States dir big small);
0 < size small;
Small.pop small = (x, smallP);
(step ^^ n) (States dir big smallP) = States dir' big' small'
⟧ ⟹ Suc (size_new small') = size_new small"
using invar_pop_small size_new_pop step_n_size_new_small size_size_new
by (metis (no_types, lifting) invar_states.simps)
lemma step_n_pop_size_big [simp]: "⟦
invar (States dir big small);
0 < size big; Big.pop big = (x, bigP);
(step ^^ n) (States dir bigP small) = States dir' big' small'
⟧ ⟹ Suc (size big') = size big"
using invar_pop_big Big_Proof.size_pop step_n_size_big
by fastforce
lemma step_n_pop_size_new_big: "⟦
invar (States dir big small);
0 < size big; Big.pop big = (x, bigP);
(step ^^ n) (States dir bigP small) = States dir' big' small'
⟧ ⟹ Suc (size_new big') = size_new big"
using invar_pop_big Big_Proof.size_new_pop step_n_size_new_big Big_Proof.size_size_new
by (metis (no_types, lifting) invar_states.simps)
lemma remaining_steps_push_small [simp]: "invar (States dir big small)
⟹ remaining_steps (States dir big small) =
remaining_steps (States dir big (Small.push x small))"
by(induction x small rule: Small.push.induct)(auto split: current.splits)
lemma remaining_steps_pop_small:
"⟦invar (States dir big small); 0 < size small; Small.pop small = (x, smallP)⟧
⟹ remaining_steps (States dir big smallP) ≤ remaining_steps (States dir big small)"
proof(induction small rule: Small.pop.induct)
case 1
then show ?case
by(auto simp: Common_Proof.remaining_steps_pop max.coboundedI2 split: prod.splits)
next
case (2 current small auxS)
then show ?case
by(induction current rule: Current.pop.induct)(auto split: big_state.splits)
next
case (3 current auxS big newS count)
then show ?case
by(induction current rule: Current.pop.induct) auto
qed
lemma remaining_steps_pop_big:
"⟦invar (States dir big small); 0 < size big; Big.pop big = (x, bigP)⟧
⟹ remaining_steps (States dir bigP small) ≤ remaining_steps (States dir big small)"
proof(induction big rule: Big.pop.induct)
case (1 state)
then show ?case
proof(induction state rule: Common.pop.induct)
case (1 current idle)
then show ?case
by(cases idle)(auto split: small_state.splits)
next
case (2 current aux new moved)
then show ?case
by(induction current rule: Current.pop.induct)(auto split: small_state.splits)
qed
next
case (2 current big aux count)
then show ?case
proof(induction current rule: Current.pop.induct)
case 1
then show ?case
by(auto split: small_state.splits current.splits)
next
case 2
then show ?case
by(auto split: small_state.splits current.splits)
qed
qed
lemma remaining_steps_push_big [simp]: "invar (States dir big small)
⟹ remaining_steps (States dir (Big.push x big) small) =
remaining_steps (States dir big small)"
by(induction x big rule: Big.push.induct)(auto split: small_state.splits current.splits)
lemma step_4_remaining_steps_push_big [simp]: "⟦
invar (States dir big small);
4 ≤ remaining_steps (States dir big small);
(step^^4) (States dir (Big.push x big) small) = States dir' big' small'⟧
⟹ remaining_steps (States dir' big' small') = remaining_steps (States dir big small) - 4"
by (metis invar_push_big remaining_steps_n_steps_sub remaining_steps_push_big )
lemma step_4_remaining_steps_push_small [simp]: "⟦
invar (States dir big small);
4 ≤ remaining_steps (States dir big small);
(step^^4) (States dir big (Small.push x small)) = States dir' big' small'
⟧ ⟹ remaining_steps (States dir' big' small') = remaining_steps (States dir big small) - 4"
by (metis invar_push_small remaining_steps_n_steps_sub remaining_steps_push_small)
lemma step_4_remaining_steps_pop_big: "⟦
invar (States dir big small);
0 < size big;
Big.pop big = (x, bigP);
4 ≤ remaining_steps (States dir bigP small);
(step^^4) (States dir bigP small) = States dir' big' small'
⟧ ⟹ remaining_steps (States dir' big' small') ≤ remaining_steps (States dir big small) - 4"
by (metis add_le_imp_le_diff invar_pop_big remaining_steps_pop_big remaining_steps_n_steps_plus)
lemma step_4_remaining_steps_pop_small: "⟦
invar (States dir big small);
0 < size small;
Small.pop small = (x, smallP);
4 ≤ remaining_steps (States dir big smallP);
(step^^4) (States dir big smallP) = States dir' big' small'
⟧ ⟹ remaining_steps (States dir' big' small') ≤ remaining_steps (States dir big small) - 4"
by (metis add_le_imp_le_diff invar_pop_small remaining_steps_n_steps_plus remaining_steps_pop_small)
lemma step_4_pop_small_size_ok_1: "⟦
invar (States dir big small);
0 < size small;
Small.pop small = (x, smallP);
4 ≤ remaining_steps (States dir big smallP);
(step^^4) (States dir big smallP) = States dir' big' small';
remaining_steps (States dir big small) + 1 ≤ 4 * size small
⟧ ⟹ remaining_steps (States dir' big' small') + 1 ≤ 4 * size small'"
by (smt (verit, ccfv_SIG) add.left_commute add.right_neutral add_le_cancel_left distrib_left_numeral dual_order.trans invar_pop_small le_add_diff_inverse2 mult.right_neutral plus_1_eq_Suc remaining_steps_n_steps_sub remaining_steps_pop_small step_n_pop_size_small)
lemma step_4_pop_big_size_ok_1: "⟦
invar (States dir big small);
0 < size big; Big.pop big = (x, bigP);
4 ≤ remaining_steps (States dir bigP small);
(step^^4) (States dir bigP small) = States dir' big' small';
remaining_steps (States dir big small) + 1 ≤ 4 * size small
⟧ ⟹ remaining_steps (States dir' big' small') + 1 ≤ 4 * size small'"
by (smt (verit, ccfv_SIG) add_leE add_le_cancel_right invar_pop_big order_trans remaining_steps_pop_big step_n_size_small remaining_steps_n_steps_plus)
lemma step_4_pop_small_size_ok_2: "⟦
invar (States dir big small);
0 < size small;
Small.pop small = (x, smallP);
4 ≤ remaining_steps (States dir big smallP);
(step^^4) (States dir big smallP) = States dir' big' small';
remaining_steps (States dir big small) + 1 ≤ 4 * size big
⟧ ⟹ remaining_steps (States dir' big' small') + 1 ≤ 4 * size big'"
by (smt (z3) add.commute add_leE invar_pop_small le_add_diff_inverse2 nat_add_left_cancel_le remaining_steps_n_steps_sub step_n_size_big remaining_steps_pop_small)
lemma step_4_pop_big_size_ok_2:
assumes
"invar (States dir big small)"
"0 < size big"
"Big.pop big = (x, bigP)"
"remaining_steps (States dir bigP small) ≥ 4"
"((step ^^ 4) (States dir bigP small)) = States dir' big' small'"
"remaining_steps (States dir big small) + 1 ≤ 4 * size big"
shows
"remaining_steps (States dir' big' small') + 1 ≤ 4 * size big'"
proof -
from assms have "remaining_steps (States dir bigP small) + 1 ≤ 4 * size big"
by (meson add_le_cancel_right order.trans remaining_steps_pop_big)
with assms show ?thesis
by (smt (z3) Suc_diff_le Suc_eq_plus1 add_mult_distrib2 diff_diff_add diff_is_0_eq invar_pop_big mult_numeral_1_right numerals(1) plus_1_eq_Suc remaining_steps_n_steps_sub step_n_pop_size_big)
qed
lemma step_4_pop_small_size_ok_3:
assumes
"invar (States dir big small)"
"0 < size small"
"Small.pop small = (x, smallP)"
"remaining_steps (States dir big smallP) ≥ 4"
"((step ^^ 4) (States dir big smallP)) = States dir' big' small'"
"size_new small + remaining_steps (States dir big small) + 2 ≤ 3 * size_new big"
shows
"size_new small' + remaining_steps (States dir' big' small') + 2 ≤ 3 * size_new big'"
by (smt (verit, best) add_leD2 add_mono_thms_linordered_semiring(1) add_mono_thms_linordered_semiring(3) assms(1) assms(2) assms(3) assms(4) assms(5) assms(6) invar_pop_small le_add2 le_add_diff_inverse order_trans plus_1_eq_Suc remaining_steps_n_steps_sub remaining_steps_pop_small step_n_pop_size_new_small step_n_size_new_big)
lemma step_4_pop_big_size_ok_3_aux: "⟦
0 < size big;
4 ≤ remaining_steps (States dir big small);
size_new small + remaining_steps (States dir big small) + 2 ≤ 3 * size_new big
⟧ ⟹ size_new small + (remaining_steps (States dir big small) - 4) + 2 ≤ 3 * (size_new big - 1)"
by linarith
lemma step_4_pop_big_size_ok_3:
assumes
"invar (States dir big small)"
"0 < size big"
"Big.pop big = (x, bigP) "
"remaining_steps (States dir bigP small) ≥ 4"
"((step ^^ 4) (States dir bigP small)) = (States dir' big' small')"
"size_new small + remaining_steps (States dir big small) + 2 ≤ 3 * size_new big"
shows
"size_new small' + remaining_steps (States dir' big' small') + 2 ≤ 3 * size_new big'"
proof-
from assms
have "size_new small + (remaining_steps (States dir big small) - 4) + 2 ≤ 3 * (size_new big - 1)"
by (meson dual_order.trans remaining_steps_pop_big step_4_pop_big_size_ok_3_aux)
then
have "size_new small + remaining_steps (States dir' big' small') + 2 ≤ 3 * (size_new big - 1)"
by (smt (verit, ccfv_SIG) add_le_mono assms(1) assms(2) assms(3) assms(4) assms(5) dual_order.trans le_antisym less_or_eq_imp_le nat_less_le step_4_remaining_steps_pop_big)
with assms show ?thesis
by (metis diff_Suc_1 invar_pop_big step_n_size_new_small step_n_pop_size_new_big)
qed
lemma step_4_pop_small_size_ok_4_aux: "⟦
0 < size small;
4 ≤ remaining_steps (States dir big small);
size_new big + remaining_steps (States dir big small) + 2 ≤ 3 * size_new small
⟧ ⟹ size_new big + (remaining_steps (States dir big small) - 4) + 2 ≤ 3 * (size_new small - 1)"
by linarith
lemma step_4_pop_small_size_ok_4:
assumes
"invar (States dir big small)"
"0 < size small"
"Small.pop small = (x, smallP)"
"remaining_steps (States dir big smallP) ≥ 4"
"((step ^^ 4) (States dir big smallP)) = (States dir' big' small')"
"size_new big + remaining_steps (States dir big small) + 2 ≤ 3 * size_new small"
shows
"size_new big' + remaining_steps (States dir' big' small') + 2 ≤ 3 * size_new small'"
proof-
from assms step_4_pop_small_size_ok_4_aux
have "size_new big + (remaining_steps (States dir big small) - 4) + 2 ≤ 3 * (size_new small - 1)"
by (smt (verit, best) add_leE le_add_diff_inverse remaining_steps_pop_small)
with assms
have "size_new big + remaining_steps (States dir' big' small') + 2 ≤ 3 * (size_new small - 1)"
by (smt (verit, best) add_le_cancel_left add_mono_thms_linordered_semiring(3) diff_le_mono invar_pop_small order_trans remaining_steps_n_steps_sub remaining_steps_pop_small)
with assms show ?thesis
by (metis diff_Suc_1 invar_pop_small step_n_size_new_big step_n_pop_size_new_small)
qed
lemma step_4_pop_big_size_ok_4_aux: "⟦
0 < size big;
4 ≤ remaining_steps (States dir big small);
size_new big + remaining_steps (States dir big small) + 2 ≤ 3 * size_new small
⟧ ⟹ size_new big - 1 + (remaining_steps (States dir big small) - 4) + 2 ≤ 3 * size_new small"
by linarith
lemma step_4_pop_big_size_ok_4:
assumes
"invar (States dir big small)"
"0 < size big "
"Big.pop big = (x, bigP)"
"remaining_steps (States dir bigP small) ≥ 4"
"((step ^^ 4) (States dir bigP small)) = (States dir' big' small')"
"size_new big + remaining_steps (States dir big small) + 2 ≤ 3 * size_new small"
shows
"size_new big' + remaining_steps (States dir' big' small') + 2 ≤ 3 * size_new small'"
proof -
from assms step_4_pop_big_size_ok_4_aux
have "(size_new big - 1) + (remaining_steps (States dir big small) - 4) + 2 ≤ 3 * size_new small"
by linarith
with assms
have "(size_new big - 1) + remaining_steps (States dir' big' small') + 2 ≤ 3 * size_new small"
by (meson add_le_mono dual_order.eq_iff order_trans step_4_remaining_steps_pop_big)
with assms show ?thesis
by (metis diff_Suc_1 invar_pop_big step_n_size_new_small step_n_pop_size_new_big)
qed
lemma step_4_push_small_size_ok_1: "⟦
invar (States dir big small);
4 ≤ remaining_steps (States dir big small);
(step^^4) (States dir big (Small.push x small)) = States dir' big' small';
remaining_steps (States dir big small) + 1 ≤ 4 * size small
⟧ ⟹ remaining_steps (States dir' big' small') + 1 ≤ 4 * size small'"
by (smt (z3) add.commute add_leD1 add_le_mono le_add1 le_add_diff_inverse2 mult_Suc_right nat_1_add_1 numeral_Bit0 step_n_push_size_small step_4_remaining_steps_push_small)
lemma step_4_push_big_size_ok_1: "⟦
invar (States dir big small);
4 ≤ remaining_steps (States dir big small);
(step^^4) (States dir (Big.push x big) small) = States dir' big' small';
remaining_steps (States dir big small) + 1 ≤ 4 * size small
⟧ ⟹ remaining_steps (States dir' big' small') + 1 ≤ 4 * size small'"
by (smt (verit, ccfv_SIG) Nat.le_diff_conv2 add_leD2 invar_push_big le_add1 le_add_diff_inverse2 remaining_steps_n_steps_sub remaining_steps_push_big step_n_size_small)
lemma step_4_push_small_size_ok_2: "⟦
invar (States dir big small);
4 ≤ remaining_steps (States dir big small);
(step^^4) (States dir big (Small.push x small)) = States dir' big' small';
remaining_steps (States dir big small) + 1 ≤ 4 * size big
⟧ ⟹ remaining_steps (States dir' big' small') + 1 ≤ 4 * size big'"
by (metis (full_types) Suc_diff_le Suc_eq_plus1 invar_push_small less_Suc_eq_le less_imp_diff_less step_4_remaining_steps_push_small step_n_size_big)
lemma step_4_push_big_size_ok_2: "⟦
invar (States dir big small);
4 ≤ remaining_steps (States dir big small);
(step^^4) (States dir (Big.push x big) small) = States dir' big' small';
remaining_steps (States dir big small) + 1 ≤ 4 * size big
⟧ ⟹ remaining_steps (States dir' big' small') + 1 ≤ 4 * size big'"
by (smt (verit, ccfv_SIG) add.commute add_diff_cancel_left' add_leD1 add_le_mono invar_push_big mult_Suc_right nat_le_iff_add one_le_numeral remaining_steps_n_steps_sub remaining_steps_push_big step_n_push_size_big)
lemma step_4_push_small_size_ok_3_aux: "⟦
4 ≤ remaining_steps (States dir big small);
size_new small + remaining_steps (States dir big small) + 2 ≤ 3 * size_new big
⟧ ⟹ Suc (size_new small) + (remaining_steps (States dir big small) - 4) + 2 ≤ 3 * size_new big"
using distrib_left dual_order.trans le_add_diff_inverse2 by force
lemma step_4_push_small_size_ok_3: "⟦
invar (States dir big small);
4 ≤ remaining_steps (States dir big small);
(step^^4) (States dir big (Small.push x small)) = States dir' big' small';
size_new small + remaining_steps (States dir big small) + 2 ≤ 3 * size_new big
⟧ ⟹ size_new small' + remaining_steps (States dir' big' small') + 2 ≤ 3 * size_new big'"
using step_n_size_new_big step_n_push_size_new_small step_4_remaining_steps_push_small
by (metis invar_push_small step_4_push_small_size_ok_3_aux)
lemma step_4_push_big_size_ok_3_aux: "⟦
4 ≤ remaining_steps (States dir big small);
size_new small + remaining_steps (States dir big small) + 2 ≤ 3 * size_new big
⟧ ⟹ size_new small + (remaining_steps (States dir big small) - 4) + 2 ≤ 3 * Suc (size_new big)"
using distrib_left dual_order.trans le_add_diff_inverse2 by force
lemma step_4_push_big_size_ok_3: "⟦
invar (States dir big small);
4 ≤ remaining_steps (States dir big small);
(step^^4) (States dir (Big.push x big) small) = States dir' big' small';
size_new small + remaining_steps (States dir big small) + 2 ≤ 3 * size_new big
⟧ ⟹ size_new small' + remaining_steps (States dir' big' small') + 2 ≤ 3 * size_new big'"
by (metis invar_push_big remaining_steps_n_steps_sub remaining_steps_push_big step_4_push_big_size_ok_3_aux step_n_push_size_new_big step_n_size_new_small)
lemma step_4_push_small_size_ok_4_aux: "⟦
4 ≤ remaining_steps (States dir big small);
size_new big + remaining_steps (States dir big small) + 2 ≤ 3 * size_new small
⟧ ⟹ size_new big + (remaining_steps (States dir big small) - 4) + 2 ≤ 3 * Suc (size_new small)"
using distrib_left dual_order.trans le_add_diff_inverse2 by force
lemma step_4_push_small_size_ok_4: "⟦
invar (States dir big small);
4 ≤ remaining_steps (States dir big small);
(step^^4) (States dir big (Small.push x small)) = States dir' big' small';
size_new big + remaining_steps (States dir big small) + 2 ≤ 3 * size_new small
⟧ ⟹ size_new big' + remaining_steps (States dir' big' small') + 2 ≤ 3 * size_new small'"
by (metis invar_push_small step_n_size_new_big step_n_push_size_new_small step_4_remaining_steps_push_small step_4_push_small_size_ok_4_aux)
lemma step_4_push_big_size_ok_4_aux: "⟦
4 ≤ remaining_steps (States dir big small);
size_new big + remaining_steps (States dir big small) + 2 ≤ 3 * size_new small
⟧ ⟹ Suc (size_new big) + (remaining_steps (States dir big small) - 4) + 2 ≤ 3 * size_new small"
using distrib_left dual_order.trans le_add_diff_inverse2 by force
lemma step_4_push_big_size_ok_4: "⟦
invar (States dir big small);
4 ≤ remaining_steps (States dir big small);
(step^^4) (States dir (Big.push x big) small) = States dir' big' small';
size_new big + remaining_steps (States dir big small) + 2 ≤ 3 * size_new small
⟧ ⟹ size_new big' + remaining_steps (States dir' big' small') + 2 ≤ 3 * size_new small'"
by (metis invar_push_big remaining_steps_n_steps_sub remaining_steps_push_big step_4_push_big_size_ok_4_aux step_n_push_size_new_big step_n_size_new_small)
lemma step_4_push_small_size_ok: "⟦
invar (States dir big small);
4 ≤ remaining_steps (States dir big small);
size_ok (States dir big small)
⟧ ⟹ size_ok ((step^^4) (States dir big (Small.push x small)))"
using step_4_push_small_size_ok_1 step_4_push_small_size_ok_2 step_4_push_small_size_ok_3 step_4_push_small_size_ok_4
by (smt (verit) size_ok'.elims(3) size_ok'.simps)
lemma step_4_push_big_size_ok: "⟦
invar (States dir big small);
4 ≤ remaining_steps (States dir big small);
size_ok (States dir big small)
⟧ ⟹ size_ok ((step^^4) (States dir (Big.push x big) small))"
using step_4_push_big_size_ok_1 step_4_push_big_size_ok_2 step_4_push_big_size_ok_3 step_4_push_big_size_ok_4
by (smt (verit) size_ok'.elims(3) size_ok'.simps)
lemma step_4_pop_small_size_ok: "⟦
invar (States dir big small);
0 < size small;
Small.pop small = (x, smallP);
4 ≤ remaining_steps (States dir big smallP);
size_ok (States dir big small)
⟧ ⟹ size_ok ((step^^4) (States dir big smallP))"
by (smt (verit) size_ok'.elims(3) size_ok'.simps step_4_pop_small_size_ok_1 step_4_pop_small_size_ok_2 step_4_pop_small_size_ok_3 step_4_pop_small_size_ok_4)
lemma step_4_pop_big_size_ok: "⟦
invar (States dir big small);
0 < size big; Big.pop big = (x, bigP);
4 ≤ remaining_steps (States dir bigP small);
size_ok (States dir big small)
⟧ ⟹ size_ok ((step^^4) (States dir bigP small))"
using step_4_pop_big_size_ok_1 step_4_pop_big_size_ok_2 step_4_pop_big_size_ok_3 step_4_pop_big_size_ok_4
by (smt (verit) size_ok'.elims(3) size_ok'.simps)
lemma size_ok_size_small: "size_ok (States dir big small) ⟹ 0 < size small"
by auto
lemma size_ok_size_big: "size_ok (States dir big small) ⟹ 0 < size big"
by auto
lemma size_ok_size_new_small: "size_ok (States dir big small) ⟹ 0 < size_new small"
by auto
lemma size_ok_size_new_big: "size_ok (States dir big small) ⟹ 0 < size_new big"
by auto
lemma step_size_ok': "⟦invar states; size_ok' states n⟧ ⟹ size_ok' (step states) n"
by (smt (verit, ccfv_SIG) size_ok'.elims(2) size_ok'.elims(3) step_size_big step_size_new_big step_size_new_small step_size_small)
lemma step_same: "step (States dir big small) = States dir' big' small' ⟹ dir = dir'"
by(induction "States dir big small" rule: step_states.induct) auto
lemma step_n_same: "(step^^n) (States dir big small) = States dir' big' small' ⟹ dir = dir'"
proof(induction n arbitrary: big small big' small')
case 0
then show ?case
by simp
next
case (Suc n)
obtain big'' small'' where "step (States dir big small) = States dir big'' small''"
by (metis states.exhaust step_same)
with Suc show ?case
by(auto simp: funpow_swap1)
qed
lemma step_listL: "invar states ⟹ listL (step states) = listL states"
proof(induction states rule: listL.induct)
case (1 big small)
then have "list_small_first (States Left big small) =
Small_Aux.list_current small @ rev (Big_Aux.list_current big)"
by auto
then have "list_small_first (step (States Left big small)) =
Small_Aux.list_current small @ rev (Big_Aux.list_current big)"
using 1 step_lists by fastforce
then have "listL (step (States Left big small)) =
Small_Aux.list_current small @ rev (Big_Aux.list_current big)"
by (smt (verit, ccfv_SIG) "1" invar_states.elims(2) States_Proof.invar_step listL.simps(1) step_same)
with 1 show ?case
by auto
next
case (2 big small)
then have a: "list_big_first (States Right big small) =
Big_Aux.list_current big @ rev (Small_Aux.list_current small)"
using invar_list_big_first[of "States Right big small"]
by auto
then have "list_big_first (step (States Right big small)) =
Big_Aux.list_current big @ rev (Small_Aux.list_current small)"
using 2 step_lists by fastforce
then have "listL (step (States Right big small)) =
Big_Aux.list_current big @ rev (Small_Aux.list_current small)"
by (metis(full_types) listL.cases listL.simps(2) step_same)
with 2 show ?case
using a by force
qed
lemma step_n_listL: "invar states ⟹ listL ((step^^n) states) = listL states"
using step_consistent[of listL states] step_listL
by metis
lemma listL_remaining_steps:
assumes
"listL states = []"
"0 < remaining_steps states"
"invar states"
"size_ok states"
shows
"False"
proof(cases states)
case (States dir big small)
with assms show ?thesis
using Small_Proof.list_current_size size_ok_size_small
by(cases dir; cases "lists (States dir big small)") auto
qed
lemma invar_step_n: "invar (states :: 'a states) ⟹ invar ((step^^n) states)"
by (simp add: invar_step step_consistent_2)
lemma step_n_size_ok': "⟦invar states; size_ok' states x⟧ ⟹ size_ok' ((step ^^ n) states) x"
proof(induction n arbitrary: states x)
case 0
then show ?case by auto
next
case Suc
then show ?case
using invar_step_n step_size_ok'
by fastforce
qed
lemma size_ok_steps: "⟦
invar states;
size_ok' states (remaining_steps states - n)
⟧ ⟹ size_ok ((step ^^ n) states)"
by (simp add: step_n_size_ok')
lemma remaining_steps_idle: "invar states
⟹ remaining_steps states = 0 ⟷ (
case states of
States _ (Big2 (Common.Idle _ _)) (Small3 (Common.Idle _ _)) ⇒ True
| _ ⇒ False) "
by(cases states)
(auto split: big_state.split small_state.split common_state.split current.splits)
lemma remaining_steps_idle':
"⟦invar (States dir big small); remaining_steps (States dir big small) = 0⟧
⟹ ∃big_current big_idle small_current small_idle. States dir big small =
States dir
(Big2 (common_state.Idle big_current big_idle))
(Small3 (common_state.Idle small_current small_idle))"
using remaining_steps_idle[of "States dir big small"]
by(cases big; cases small) (auto split!: common_state.splits)
end