text‹
this section we devise some simple yet useful Turing machines. We have
fully analyzed the empty TM, where start and halting state coincide, in
lemmas~@{thm [source] computes_Nil_empty}, @{thm [source] Nil_tm}, and @{thm
source] transforms_Nil}. The next more complex TMs are those with exactly one
. They represent TMs with two states: the halting state and the start
where the action happens. This action might last for one step only, or the
may stay in this state for longer; for example, it can move a tape head
to the next blank symbol. We will also start using the @{text ";;"}
to combine some of the one-command TMs. ›
text‹
Turing machines we are going to construct throughout this section and
the entire article are really families of Turing machines that usually
parameterized by tape indices. ›
type_synonym tapeidx = nat
text‹
this article, names of commands are prefixed with @{text cmd_} and
of Turing machines with @{text tm_}. Usually for a TM named @{term tm_foo}
is a lemma @{text tm_foo_tm} stating that it really is a Turing machine and
lemma @{text transforms_tm_fooI} describing its semantics and running time. The
usually receives a @{text transforms_intros} attribute for use with our
method.
@{term "tm_foo"} comprises more than two TMs we will typically analyze the
and running time in a locale named @{text "turing_machine_foo"}. The
example of this is @{term tm_equals} in
~\ref{s:tm-elementary-comparing}.
it comes to running times, we will have almost no scruples simplifying
bounds to have the form $a + b\cdot n^c$ for some constants $a, b, c$,
if this means, for example, bounding $n \log n$ by $n^2$. ›
subsection‹Clean tapes›
text‹
of our Turing machines will not change the start symbol in the first cell
a tape nor will they write the start symbol anywhere else. The only
are machines that simulate arbitrary other machines. We call tapes
have the start symbol only in the first cell \emph{clean tapes}. ›
definition clean_tape :: "tape ==> bool"where "clean_tape tp ≡∀i. fst tp i = ▹⟷ i = 0"
lemma clean_tapeI: assumes"∧i. fst tp i = ▹⟷ i = 0" shows"clean_tape tp" unfolding clean_tape_def using assms by simp
lemma clean_tapeI': assumes"fst tp 0 = ▹"and"∧i. i > 0 ==> fst tp i ≠▹" shows"clean_tape tp" unfolding clean_tape_def using assms by auto
text‹
clean configuration is one with only clean tapes. ›
definition clean_config :: "config ==> bool"where "clean_config cfg ≡ (∀j<||cfg||. ∀i. (cfg <:> j) i = ▹⟷ i = 0)"
lemma clean_config_tapes: "clean_config cfg = (∀tp∈set (snd cfg). clean_tape tp)" using clean_config_def clean_tape_def by (metis in_set_conv_nth)
lemma clean_configI: assumes"∧j i. j < length tps ==> fst (tps ! j) i = ▹⟷ i = 0" shows"clean_config (q, tps)" unfolding clean_config_def using assms by simp
lemma clean_configI': assumes"∧tp i. tp ∈ set tps ==> fst tp i = ▹⟷ i = 0" shows"clean_config (q, tps)" using clean_configI assms by simp
lemma clean_configI'': assumes"∧tp. tp ∈ set tps ==> (fst tp 0 = ▹∧ (∀i>0. fst tp i ≠▹))" shows"clean_config (q, tps)" using clean_configI' assms by blast
lemma clean_configE: assumes"clean_config (q, tps)" shows"∧j i. j < length tps ==> fst (tps ! j) i = ▹⟷ i = 0" using clean_config_def assms by simp
lemma clean_configE': assumes"clean_config (q, tps)" shows"∧tp i. tp ∈ set tps ==> fst tp i = ▹⟷ i = 0" using clean_configE assms by (metis in_set_conv_nth)
lemma clean_contents_proper [simp]: "proper_symbols zs ==> clean_tape (⌊zs⌋, q)" using clean_tape_def contents_def proper_symbols_ne1 by simp
lemma contents_clean_tape': "proper_symbols zs ==> fst tp = ⌊zs⌋==> clean_tape tp" using contents_def clean_tape_def by (simp add: nat_neq_iff)
text‹
more lemmas about @{const contents}: ›
lemma contents_append_blanks: "⌊ys @ replicate m ◻⌋ = ⌊ys⌋" proof fix i
consider "i = 0"
| "0 < i ∧ i ≤ length ys"
| "length ys < i ∧ i ≤ length ys + m"
| "length ys + m < i" by linarith thenshow"⌊ys @ replicate m ◻⌋ i = ⌊ys⌋ i" proof (cases) case1 thenshow ?thesis by simp next case2 thenshow ?thesis using contents_inbounds by (metis (no_types, opaque_lifting) Suc_diff_1 Suc_le_eq le_add1 le_trans length_append nth_append) next case3 thenshow ?thesis by (smt (verit) Suc_diff_Suc add_diff_inverse_nat contents_def diff_Suc_1 diff_commute leD less_one
less_or_eq_imp_le nat_add_left_cancel_le not_less_eq nth_append nth_replicate) next case4 thenshow ?thesis by simp qed qed
lemma contents_append_update: assumes"length ys = m" shows"⌊ys @ [v] @ zs⌋(Suc m := w) = ⌊ys @ [w] @ zs⌋" proof fix i
consider "i = 0"
| "0 < i ∧ i < Suc m"
| "i = Suc m"
| "i > Suc m ∧ i ≤ Suc m + length zs"
| "i > Suc m + length zs" by linarith thenshow"(⌊ys @ [v] @ zs⌋(Suc m := w)) i = ⌊ys @ [w] @ zs⌋ i"
(is"?l = ?r") proof (cases) case1 thenshow ?thesis by simp next case2 thenhave"?l = (ys @ [v] @ zs) ! (i - 1)" using assms contents_inbounds by simp thenhave *: "?l = ys ! (i - 1)" using2 assms by (metis Suc_diff_1 Suc_le_lessD less_Suc_eq_le nth_append) have"?r = (ys @ [w] @ zs) ! (i - 1)" using2 assms contents_inbounds by simp thenhave"?r = ys ! (i - 1)" using2 assms by (metis Suc_diff_1 Suc_le_lessD less_Suc_eq_le nth_append) thenshow ?thesis using * by simp next case3 thenshow ?thesis using assms by auto next case4 thenhave"?l = (ys @ [v] @ zs) ! (i - 1)" using assms contents_inbounds by simp thenhave"?l = ((ys @ [v]) @ zs) ! (i - 1)" by simp thenhave *: "?l = zs ! (i - 1 - Suc m)" using4 assms by (metis diff_Suc_1 length_append_singleton less_imp_Suc_add not_add_less1 nth_append) thenhave"?r = (ys @ [w] @ zs) ! (i - 1)" using4 assms contents_inbounds by simp thenhave"?r = ((ys @ [w]) @ zs) ! (i - 1)" by simp thenhave"?r = zs ! (i - 1 - Suc m)" using4 assms by (metis diff_Suc_1 length_append_singleton less_imp_Suc_add not_add_less1 nth_append) thenshow ?thesis using * by simp next case5 thenshow ?thesis using assms by simp qed qed
lemma contents_snoc: "⌊ys⌋(Suc (length ys) := w) = ⌊ys @ [w]⌋" proof fix i
consider "i = 0" | "0 < i ∧ i ≤ length ys" | "i = Suc (length ys)" | "i > Suc (length ys)" by linarith thenshow"(⌊ys⌋(Suc (length ys) := w)) i = ⌊ys @ [w]⌋ i" proof (cases) case1 thenshow ?thesis by simp next case2 thenshow ?thesis by (smt (verit, ccfv_SIG) contents_def diff_Suc_1 ex_least_nat_less fun_upd_apply leD le_Suc_eq
length_append_singleton less_imp_Suc_add nth_append) next case3 thenshow ?thesis by simp next case4 thenshow ?thesis by simp qed qed
text‹
next command makes the heads on all tapes from a set $J$ of tapes move one
to the right. ›
definition cmd_right_many :: "tapeidx set ==> command"where "cmd_right_many J ≡ λrs. (1, map (λi. (rs ! i, if i ∈ J then Right else Stay)) [0..<length rs])"
lemma turing_command_right_many: "turing_command k 1 G (cmd_right_many J)" by (auto simp add: cmd_right_many_def)
lemma sem_cmd_right_many: "sem (cmd_right_many J) (0, tps) = (1, map (λj. if j ∈ J then tps ! j |+| 1 else tps ! j) [0..<length tps])" proof show"fst (sem (cmd_right_many J) (0, tps)) = fst (1, map (λj. if j ∈ J then tps ! j |+| 1 else tps ! j) [0..<length tps])" using cmd_right_many_def sem_fst by simp have"snd (sem (cmd_right_many J) (0, tps)) = map (λj. if j ∈ J then tps ! j |+| 1 else tps ! j) [0..<length tps]"
(is"?lhs = ?rhs") proof (rule nth_equalityI) show"length ?lhs = length ?rhs" using turing_command_right_many sem_num_tapes2' by (metis (no_types, lifting) diff_zero length_map length_upt snd_conv) thenhave len: "length ?lhs = length tps" by simp show"?lhs ! j = ?rhs ! j"if"j < length ?lhs"for j proof (cases "j ∈ J") case True let ?rs = "read tps" have"length ?rs = length tps" using read_length by simp moreoverhave"sem (cmd_right_many J) (0, tps) <!> j = act (cmd_right_many J ?rs [!] j) (tps ! j)" using cmd_right_many_def sem_snd that True len by auto moreoverhave"?rhs ! j = tps ! j |+| 1" using that len True by simp ultimatelyshow ?thesis using that act_Right cmd_right_many_def True len by simp next case False let ?rs = "read tps" have"length ?rs = length tps" using read_length by simp moreoverhave"sem (cmd_right_many J) (0, tps) <!> j = act (cmd_right_many J ?rs [!] j) (tps ! j)" using cmd_right_many_def sem_snd that False len by auto moreoverhave"?rhs ! j = tps ! j" using that len False by simp ultimatelyshow ?thesis using that act_Stay cmd_right_many_def False len by simp qed qed thenshow"snd (sem (cmd_right_many J) (0, tps)) = snd (1, map (λj. if j ∈ J then tps ! j |+| 1 else tps ! j) [0..<length tps])" by simp qed
lemma tm_right_many_tm: "k ≥ 2 ==> G ≥ 4 ==> turing_machine k G (tm_right_many J)" unfolding tm_right_many_def using turing_command_right_many by auto
lemma transforms_tm_right_manyI [transforms_intros]: assumes"t = Suc 0" and"tps' = map (λj. if j ∈ J then tps ! j |+| 1 else tps ! j) [0..<length tps]" shows"transforms (tm_right_many J) tps t tps'" proof - have"exe (tm_right_many J) (0, tps) = (1, map (λj. if j ∈ J then tps ! j |+| 1 else tps ! j) [0..<length tps])" unfolding tm_right_many_def using sem_cmd_right_many by (simp add: exe_lt_length) thenhave"execute (tm_right_many J) (0, tps) (Suc 0) = (1, map (λj. if j ∈ J then tps ! j |+| 1 else tps ! j) [0..<length tps])" by simp thenhave"transits (tm_right_many J) (0, tps) (Suc 0) (1, map (λj. if j ∈ J then tps ! j |+| 1 else tps ! j) [0..<length tps])" using transitsI by blast thenhave"transforms (tm_right_many J) tps (Suc 0) (map (λj. if j ∈ J then tps ! j |+| 1 else tps ! j) [0..<length tps])" by (simp add: tm_right_many_def transforms_def) thenshow ?thesis using assms by (simp add: tm_right_many_def transforms_def) qed
subsection‹Copying and translating tape contents›
text‹
Turing machines in this section scan a tape $j_1$ and copy the symbols to
tape $j_2$. Scanning can be performed in either direction, and ``copying''
include mapping the symbols. ›
subsubsection‹Copying and translating from one tape to another›
text‹
next predicate is true iff.\ on the given tape the next symbol from the set
H$ of symbols is exactly $n$ cells to the right from the current head position.
, a command that moves the tape head right until it finds a symbol from $H$
$n$ steps and moves the head $n$ cells right. ›
definition rneigh :: "tape ==> symbol set ==> nat ==> bool"where "rneigh tp H n ≡ fst tp (snd tp + n) ∈ H ∧ (∀n' < n. fst tp (snd tp + n') ∉ H)"
lemma rneighI: assumes"fst tp (snd tp + n) ∈ H"and"∧n'. n' < n ==> fst tp (snd tp + n') ∉ H" shows"rneigh tp H n" using assms rneigh_def by simp
text‹
analogous predicate for moving to the left: ›
definition lneigh :: "tape ==> symbol set ==> nat ==> bool"where "lneigh tp H n ≡ fst tp (snd tp - n) ∈ H ∧ (∀n' < n. fst tp (snd tp - n') ∉ H)"
lemma lneighI: assumes"fst tp (snd tp - n) ∈ H"and"∧n'. n' < n ==> fst tp (snd tp - n') ∉ H" shows"lneigh tp H n" using assms lneigh_def by simp
text‹
next command scans tape $j_1$ rightward until it reaches a symbol from the
$H$. While doing so it copies the symbols, after applying a mapping $f$, to
$j_2$. ›
definition cmd_trans_until :: "tapeidx ==> tapeidx ==> symbol set ==> (symbol ==> symbol) ==> command"where "cmd_trans_until j1 j2 H f ≡ λrs. if rs ! j1 ∈ H then (1, map (λr. (r, Stay)) rs) else (0, map (λi. (if i = j2 then f (rs ! j1) else rs ! i, if i = j1 ∨ i = j2 then Right else Stay)) [0..<length rs])"
text‹
analogous command for moving to the left: ›
definition cmd_ltrans_until :: "tapeidx ==> tapeidx ==> symbol set ==> (symbol ==>symbol) ==> command"where "cmd_ltrans_until j1 j2 H f ≡ λrs. if rs ! j1 ∈ H then (1, map (λr. (r, Stay)) rs) else (0, map (λi. (if i = j2 then f (rs ! j1) else rs ! i, if i = j1 ∨ i = j2 then Left else Stay)) [0..<length rs])"
lemma proper_cmd_trans_until: "proper_command k (cmd_trans_until j1 j2 H f)" using cmd_trans_until_def by simp
lemma proper_cmd_ltrans_until: "proper_command k (cmd_ltrans_until j1 j2 H f)" using cmd_ltrans_until_def by simp
lemma sem_cmd_trans_until_1: assumes"j1 < k"and"length tps = k"and"(0, tps) <.> j1 ∈ H" shows"sem (cmd_trans_until j1 j2 H f) (0, tps) = (1, tps)" using cmd_trans_until_def tapes_at_read read_length assms act_Stay by (intro semI[OF proper_cmd_trans_until]) auto
lemma sem_cmd_ltrans_until_1: assumes"j1 < k"and"length tps = k"and"(0, tps) <.> j1 ∈ H" shows"sem (cmd_ltrans_until j1 j2 H f) (0, tps) = (1, tps)" using cmd_ltrans_until_def tapes_at_read read_length assms act_Stay by (intro semI[OF proper_cmd_ltrans_until]) auto
definition tm_trans_until :: "tapeidx ==> tapeidx ==> symbol set ==> (symbol ==> symbol) ==> machine"where "tm_trans_until j1 j2 H f ≡ [cmd_trans_until j1 j2 H f]"
definition tm_ltrans_until :: "tapeidx ==> tapeidx ==> symbol set ==> (symbol ==> symbol) ==> machine"where "tm_ltrans_until j1 j2 H f ≡ [cmd_ltrans_until j1 j2 H f]"
lemma tm_trans_until_tm: assumes"0 < j2"and"j1 < k"and"j2 < k"and"∀h<G. f h < G"and"k ≥ 2"and"G ≥ 4" shows"turing_machine k G (tm_trans_until j1 j2 H f)" unfolding tm_trans_until_def cmd_trans_until_def using assms turing_machine_def by auto
lemma tm_ltrans_until_tm: assumes"0 < j2"and"j1 < k"and"j2 < k"and"∀h<G. f h < G"and"k ≥ 2"and"G ≥ 4" shows"turing_machine k G (tm_ltrans_until j1 j2 H f)" unfolding tm_ltrans_until_def cmd_ltrans_until_def using assms turing_machine_def by auto
text‹
$tp_1$ and $tp_2$ be two tapes with head positions $i_1$ and $i_2$,
. The next function describes the result of overwriting the symbols
positions $i_2, \dots, i_2 + n - 1$ on tape $tp_2$ by the symbols at
$i_1, \dots, i_1 + n - 1$ on tape $tp_1$ after applying a symbol map
f$. ›
definition transplant :: "tape ==> tape ==> (symbol ==> symbol)==> nat ==> tape"where "transplant tp1 tp2 f n ≡ (λi. if snd tp2 ≤ i ∧ i < snd tp2 + n then f (fst tp1 (snd tp1 + i - snd tp2)) else fst tp2 i, snd tp2 + n)"
text‹
analogous function for moving to the left while copying: ›
definition ltransplant :: "tape ==> tape ==> (symbol ==> symbol)==> nat ==> tape"where "ltransplant tp1 tp2 f n ≡ (λi. if snd tp2 - n < i ∧ i ≤ snd tp2 then f (fst tp1 (snd tp1 + i - snd tp2)) else fst tp2 i, snd tp2 - n)"
lemma transplant_0: "transplant tp1 tp2 f 0 = tp2" unfolding transplant_def by standard auto
lemma ltransplant_0: "ltransplant tp1 tp2 f 0 = tp2" unfolding ltransplant_def by standard auto
lemma transplant_upd: "transplant tp1 tp2 f n |:=| (f ( |.| (tp1 |+| n))) |+| 1 = transplant tp1 tp2 f (Suc n)" unfolding transplant_def by auto
lemma ltransplant_upd: assumes"n < snd tp2" shows"ltransplant tp1 tp2 f n |:=| (f ( |.| (tp1 |-| n))) |-| 1 = ltransplant tp1 tp2 f (Suc n)" unfolding ltransplant_def using assms by fastforce
lemma tapes_ltransplant_upd: assumes"t < tps :#: j2"and"t < tps :#: j1"and"j1 < k"and"j2 < k"and"length tps = k" and"tps' = tps[j1 := tps ! j1 |-| t, j2 := ltransplant (tps ! j1) (tps ! j2) f t]" shows"tps'[j1 := tps' ! j1 |-| 1, j2 := tps' ! j2 |:=| (f (tps' :.: j1)) |-| 1] = tps[j1 := tps ! j1 |-| Suc t, j2 := ltransplant (tps ! j1) (tps ! j2) f (Suc t)]"
(is"?lhs = ?rhs") proof (rule nth_equalityI) show1: "length ?lhs = length ?rhs" using assms by simp have len: "length ?lhs = k" using assms by simp show"?lhs ! j = ?rhs ! j"if"j < length ?lhs"for j proof - have"j < k" using len that by simp show ?thesis proof (cases "j ≠ j1 ∧ j ≠ j2") case True thenshow ?thesis using assms by simp next case j1j2: False show ?thesis proof (cases "j1 = j2") case True thenhave j: "j = j1""j = j2" using j1j2 by simp_all have"tps' ! j1 = ltransplant (tps ! j1) (tps ! j2) f t" using j assms that by simp thenhave *: "snd (tps' ! j1) = snd (tps ! j1) - t" using j ltransplant_def by simp thenhave"fst (tps' ! j1) = (λi. if snd (tps ! j2) - t < i ∧ i ≤ snd (tps ! j2) then f (fst (tps ! j1) (snd (tps ! j1) + i - snd (tps ! j2))) else fst (tps ! j2) i)" using j ltransplant_def assms by auto thenhave"fst (tps' ! j1) = (λi. if snd (tps ! j1) - t < i ∧ i ≤ snd (tps ! j1) then f (fst (tps ! j1) (snd (tps ! j1) + i - snd (tps ! j1))) else fst (tps ! j1) i)" using j by auto thenhave"fst (tps' ! j1) (snd (tps ! j1) - t) = fst (tps ! j1) (snd (tps ! j1) - t)" by simp thenhave"tps' :.: j1 = fst (tps ! j1) (snd (tps ! j1) - t)" using * by simp thenhave"?lhs ! j = (ltransplant (tps ! j1) (tps ! j2) f t) |:=| (f ( |.| (tps ! j1 |-| t))) |-| 1" using assms(6) j that by simp thenhave"?lhs ! j = (ltransplant (tps ! j1) (tps ! j2) f (Suc t))" using ltransplant_upd assms(1) by simp moreoverhave"?rhs ! j = ltransplant (tps ! j1) (tps ! j2) f (Suc t)" using assms(6) that j by simp ultimatelyshow ?thesis by simp next case j1_neq_j2: False thenshow ?thesis proof (cases "j = j1") case True thenhave"?lhs ! j = tps' ! j1 |-| 1" using assms j1_neq_j2 by simp thenhave"?lhs ! j = (tps ! j1 |-| t) |-| 1" using assms j1_neq_j2 by simp moreoverhave"?rhs ! j = tps ! j1 |-| Suc t" using True assms j1_neq_j2 by simp ultimatelyshow ?thesis by simp next case False thenhave j: "j = j2" using j1j2 by simp thenhave"?lhs ! j = tps' ! j2 |:=| (f (tps' :.: j1)) |-| 1" using assms by simp thenhave"?lhs ! j = (ltransplant (tps ! j1) (tps ! j2) f t) |:=| (f (tps' :.: j1)) |-| 1" using assms by simp thenhave"?lhs ! j = (ltransplant (tps ! j1) (tps ! j2) f (Suc t))" using ltransplant_def assms ltransplant_upd by (smt (verit) j1_neq_j2 nth_list_update_eq nth_list_update_neq) moreoverhave"?rhs ! j = ltransplant (tps ! j1) (tps ! j2) f (Suc t)" using assms(6) that j by simp ultimatelyshow ?thesis by simp qed qed qed qed qed
lemma execute_tm_trans_until_less: assumes"j1 < k"and"j2 < k"and"length tps = k"and"rneigh (tps ! j1) H n"and"t ≤ n" shows"execute (tm_trans_until j1 j2 H f) (0, tps) t = (0, tps[j1 := tps ! j1 |+| t, j2 := transplant (tps ! j1) (tps ! j2) f t])" using assms(5) proof (induction t) case0 thenshow ?case using transplant_0 by simp next case (Suc t) thenhave"t < n"by simp let ?M = "tm_trans_until j1 j2 H f" have"execute ?M (0, tps) (Suc t) = exe ?M (execute ?M (0, tps) t)" by simp alsohave"... = exe ?M (0, tps[j1 := tps ! j1 |+| t, j2 := transplant (tps ! j1) (tps ! j2) f t])"
(is"_ = exe ?M (0, ?tps)") using Suc by simp alsohave"... = (0, ?tps[j1 := ?tps ! j1 |+| 1, j2 := ?tps ! j2 |:=| (f (?tps :.: j1)) |+| 1])" proof (rule exe_tm_trans_until_2[where ?k=k]) show"j1 < k" using assms(1) . show"length (tps[j1 := tps ! j1 |+| t, j2 := transplant (tps ! j1) (tps ! j2) f t]) = k" using assms by simp show"(0, tps[j1 := tps ! j1 |+| t, j2 := transplant (tps ! j1) (tps ! j2) f t]) <.> j1 ∉ H" using assms transplant_def rneigh_def ‹t < n› by (smt (verit) fst_conv length_list_update less_not_refl2 nth_list_update_eq nth_list_update_neq snd_conv) qed finallyshow ?case using assms transplant_upd by auto
(smt (verit) add.commute fst_conv transplant_def transplant_upd less_not_refl2 list_update_overwrite list_update_swap
nth_list_update_eq nth_list_update_neq plus_1_eq_Suc snd_conv) qed
lemma execute_tm_ltrans_until_less: assumes"j1 < k"and"j2 < k"and"length tps = k" and"lneigh (tps ! j1) H n" and"t ≤ n" and"n ≤ tps :#: j1" and"n ≤ tps :#: j2" shows"execute (tm_ltrans_until j1 j2 H f) (0, tps) t = (0, tps[j1 := tps ! j1 |-| t, j2 := ltransplant (tps ! j1) (tps ! j2) f t])" using assms(5) proof (induction t) case0 thenshow ?case using ltransplant_0 by simp next case (Suc t) thenhave"t < n" by simp have1: "t < tps :#: j2" using assms(7) Suc by simp have2: "t < tps :#: j1" using assms(6) Suc by simp let ?M = "tm_ltrans_until j1 j2 H f"
define tps' where"tps' = tps[j1 := tps ! j1 |-| t, j2 := ltransplant (tps ! j1) (tps ! j2) f t]" have"execute ?M (0, tps) (Suc t) = exe ?M (execute ?M (0, tps) t)" by simp alsohave"... = exe ?M (0, tps')" using Suc tps'_defby simp alsohave"... = (0, tps'[j1 := tps' ! j1 |-| 1, j2 := tps' ! j2 |:=| (f (tps' :.: j1)) |-| 1])" proof (rule exe_tm_ltrans_until_2[where ?k=k]) show"j1 < k" using assms(1) . show"length tps' = k" using assms tps'_defby simp show"(0, tps') <.> j1 ∉ H" using assms ltransplant_def tps'_def lneigh_def ‹t < n› by (smt (verit) fst_conv length_list_update less_not_refl2 nth_list_update_eq nth_list_update_neq snd_conv) qed finallyshow ?case using tapes_ltransplant_upd[OF 12 assms(1,2,3) tps'_def] by simp qed
lemma execute_tm_trans_until: assumes"j1 < k"and"j2 < k"and"length tps = k"and"rneigh (tps ! j1) H n" shows"execute (tm_trans_until j1 j2 H f) (0, tps) (Suc n) = (1, tps[j1 := tps ! j1 |+| n, j2 := transplant (tps ! j1) (tps ! j2) f n])" proof - let ?M = "tm_trans_until j1 j2 H f" have"execute ?M (0, tps) (Suc n) = exe ?M (execute ?M (0, tps) n)" by simp alsohave"... = exe ?M (0, tps[j1 := tps ! j1 |+| n, j2 := transplant (tps ! j1) (tps ! j2) f n])" using execute_tm_trans_until_less[where ?t=n] assms by simp alsohave"... = (1, tps[j1 := tps ! j1 |+| n, j2 := transplant (tps ! j1) (tps ! j2) f n])"
(is"_ = (1, ?tps)") proof - have"length ?tps = k" using assms(3) by simp moreoverhave"(0, ?tps) <.> j1 ∈ H" using rneigh_def transplant_def assms by (smt (verit) fst_conv length_list_update less_not_refl2 nth_list_update_eq nth_list_update_neq snd_conv) ultimatelyshow ?thesis using exe_tm_trans_until_1 assms by simp qed finallyshow ?thesis by simp qed
lemma execute_tm_ltrans_until: assumes"j1 < k"and"j2 < k"and"length tps = k" and"lneigh (tps ! j1) H n" and"n ≤ tps :#: j1" and"n ≤ tps :#: j2" shows"execute (tm_ltrans_until j1 j2 H f) (0, tps) (Suc n) = (1, tps[j1 := tps ! j1 |-| n, j2 := ltransplant (tps ! j1) (tps ! j2) f n])" proof - let ?M = "tm_ltrans_until j1 j2 H f" have"execute ?M (0, tps) (Suc n) = exe ?M (execute ?M (0, tps) n)" by simp alsohave"... = exe ?M (0, tps[j1 := tps ! j1 |-| n, j2 := ltransplant (tps ! j1) (tps ! j2) f n])" using execute_tm_ltrans_until_less[where ?t=n] assms by simp alsohave"... = (1, tps[j1 := tps ! j1 |-| n, j2 := ltransplant (tps ! j1) (tps ! j2) f n])"
(is"_ = (1, ?tps)") proof - have"length ?tps = k" using assms(3) by simp moreoverhave"(0, ?tps) <.> j1 ∈ H" using lneigh_def ltransplant_def assms by (smt (verit, ccfv_threshold) fst_conv length_list_update less_not_refl nth_list_update_eq nth_list_update_neq snd_conv) ultimatelyshow ?thesis using exe_tm_ltrans_until_1 assms by simp qed finallyshow ?thesis by simp qed
lemma transits_tm_trans_until: assumes"j1 < k"and"j2 < k"and"length tps = k"and"rneigh (tps ! j1) H n" shows"transits (tm_trans_until j1 j2 H f) (0, tps) (Suc n) (1, tps[j1 := tps ! j1 |+| n, j2 := transplant (tps ! j1) (tps ! j2) f n])" using execute_tm_trans_until[OF assms] transitsI[of _ _ "Suc n" _ "Suc n"] by blast
lemma transforms_tm_trans_until: assumes"j1 < k"and"j2 < k"and"length tps = k"and"rneigh (tps ! j1) H n" shows"transforms (tm_trans_until j1 j2 H f) tps (Suc n) (tps[j1 := tps ! j1 |+| n, j2 := transplant (tps ! j1) (tps ! j2) f n])" using tm_trans_until_def transforms_def transits_tm_trans_until[OF assms] by simp
lemma transforms_tm_ltrans_until: assumes"j1 < k"and"j2 < k"and"length tps = k" and"lneigh (tps ! j1) H n" and"n ≤ tps :#: j1" and"n ≤ tps :#: j2" shows"transforms (tm_ltrans_until j1 j2 H f) tps (Suc n) (tps[j1 := tps ! j1 |-| n, j2 := ltransplant (tps ! j1) (tps ! j2) f n])" using tm_ltrans_until_def transforms_def transits_tm_ltrans_until[OF assms] by simp
corollary transforms_tm_trans_untilI [transforms_intros]: assumes"j1 < k"and"j2 < k"and"length tps = k" and"rneigh (tps ! j1) H n" and"t = Suc n" and"tps' = tps[j1 := tps ! j1 |+| n, j2 := transplant (tps ! j1) (tps ! j2) f n]" shows"transforms (tm_trans_until j1 j2 H f) tps t tps'" using transforms_tm_trans_until[OF assms(1-4)] assms(5,6) by simp
corollary transforms_tm_ltrans_untilI [transforms_intros]: assumes"j1 < k"and"j2 < k"and"length tps = k" and"lneigh (tps ! j1) H n" and"n ≤ tps :#: j1" and"n ≤ tps :#: j2" and"t = Suc n" and"tps' = tps[j1 := tps ! j1 |-| n, j2 := ltransplant (tps ! j1) (tps ! j2) f n]" shows"transforms (tm_ltrans_until j1 j2 H f) tps t tps'" using transforms_tm_ltrans_until[OF assms(1-6)] assms(7,8) by simp
subsubsection‹Copying one tape to another›
text‹
we set the symbol map $f$ in @{const tm_trans_until} to the identity
, we get a Turing machine that simply makes a copy. ›
definition tm_cp_until :: "tapeidx ==> tapeidx ==> symbol set ==> machine"where "tm_cp_until j1 j2 H ≡ tm_trans_until j1 j2 H id"
lemma id_symbol: "∀h<G. (id :: symbol ==> symbol) h < G" by simp
lemma tm_cp_until_tm: assumes"0 < j2"and"j1 < k"and"j2 < k"and"G ≥ 4" shows"turing_machine k G (tm_cp_until j1 j2 H)" unfolding tm_cp_until_def using tm_trans_until_tm id_symbol assms turing_machine_def bysimp
abbreviation implant :: "tape ==> tape ==> nat ==> tape"where "implant tp1 tp2 n ≡ transplant tp1 tp2 id n"
lemma implant: "implant tp1 tp2 n = (λi. if snd tp2 ≤ i ∧ i < snd tp2 + n then fst tp1 (snd tp1 + i - snd tp2) else fst tp2 i, snd tp2 + n)" using transplant_def by auto
lemma implantI: assumes"tp' = (λi. if snd tp2 ≤ i ∧ i < snd tp2 + n then fst tp1 (snd tp1 + i - snd tp2) else fst tp2 i, snd tp2 + n)" shows"implant tp1 tp2 n = tp'" using implant assms by simp
lemma fst_snd_pair: "fst t = a ==> snd t = b ==> t = (a, b)" by auto
lemma implantI': assumes"fst tp' = (λi. if snd tp2 ≤ i ∧ i < snd tp2 + n then fst tp1 (snd tp1 + i - snd tp2) else fst tp2 i)" and"snd tp' = snd tp2 + n" shows"implant tp1 tp2 n = tp'" using implantI fst_snd_pair[OF assms] by simp
lemma implantI'': assumes"∧i. snd tp2 ≤ i ∧ i < snd tp2 + n ==> fst tp' i = fst tp1 (snd tp1 + i - snd tp2)" and"∧i. i < snd tp2 ==> fst tp' i = fst tp2 i" and"∧i. snd tp2 + n ≤ i ==> fst tp' i = fst tp2 i" assumes"snd tp' = snd tp2 + n" shows"implant tp1 tp2 n = tp'" using assms implantI' by (meson linorder_le_less_linear)
lemma implantI''': assumes"∧i. i2 ≤ i ∧ i < i2 + n ==> ys i = ys1 (i1 + i - i2)" and"∧i. i < i2 ==> ys i = ys2 i" and"∧i. i2 + n ≤ i ==> ys i = ys2 i" assumes"i = i2 + n" shows"implant (ys1, i1) (ys2, i2) n = (ys, i)" using assms implantI'' by auto
lemma implant_self: "implant tp tp n = tp |+| n" unfolding transplant_def by auto
lemma implant_contents: assumes"i > 0"and"n + (i - 1) ≤ length xs" shows"implant (⌊xs⌋, i) (⌊ys⌋, Suc (length ys)) n = (⌊ys @ (take n (drop (i - 1) xs))⌋, Suc (length ys) + n)"
(is"?lhs = ?rhs") proof - have lhs: "?lhs = (λj. if Suc (length ys) ≤ j ∧ j < Suc (length ys) + n then ⌊xs⌋ (i + j - Suc (length ys)) else ⌊ys⌋ j, Suc (length ys) + n)" using implant by auto let ?zs = "ys @ (take n (drop (i - 1) xs))" have lenzs: "length ?zs = length ys + n" using assms by simp have fst_rhs: "fst ?rhs = (λj. if j = 0 then 1 else if j ≤ length ys + n then ?zs ! (j - 1) else 0)" using assms by auto
have"(λj. if Suc (length ys) ≤ j ∧ j < Suc (length ys) + n then ⌊xs⌋ (i + j - Suc (length ys)) else ⌊ys⌋ j) = (λj. if j = 0 then 1 else if j ≤ length ys + n then ?zs ! (j - 1) else 0)"
(is"?l = ?r") proof fix j
consider "j = 0"
| "j > 0 ∧ j ≤ length ys"
| "j > length ys ∧ j ≤ length ys + n"
| "j > length ys + n" by linarith thenshow"?l j = ?r j" proof (cases) case1 thenshow ?thesis by simp next case2 thenshow ?thesis using assms contents_def by (smt (verit) Suc_diff_1 less_trans_Suc not_add_less1 not_le not_less_eq_eq nth_append) next case3 thenhave"?r j = ?zs ! (j - 1)" by simp alsohave"... = take n (drop (i - 1) xs) ! (j - 1 - length ys)" using3 lenzs by (metis add.right_neutral diff_is_0_eq le_add_diff_inverse not_add_less2 not_le not_less_eq nth_append plus_1_eq_Suc) alsohave"... = take n (drop (i - 1) xs) ! (j - Suc (length ys))" by simp alsohave"... = xs ! (i - 1 + j - Suc (length ys))" using3 assms by auto alsohave"... = ⌊xs⌋ (i + j - Suc (length ys))" using assms contents_def 3by auto alsohave"... = ?l j" using3by simp finallyhave"?r j = ?l j" . thenshow ?thesis by simp next case4 thenshow ?thesis by simp qed qed thenshow ?thesis using lhs fst_rhs by simp qed
subsubsection‹Moving to the next specific symbol›
text‹
a tape to itself means just moving to the right. ›
definition tm_right_until :: "tapeidx ==> symbol set ==> machine"where "tm_right_until j H ≡ tm_cp_until j j H"
text‹
a tape to itself does not change the tape. So this is a Turing machine
for the input tape $j = 0$, unlike @{const tm_cp_until} where
target tape cannot, in general, be the input tape. ›
lemma tm_right_until_tm: assumes"j < k"and"k ≥ 2"and"G ≥ 4" shows"turing_machine k G (tm_right_until j H)" unfolding tm_right_until_def tm_cp_until_def tm_trans_until_def cmd_trans_until_def using assms turing_machine_def by auto
text‹
way to specialize @{const tm_trans_until} and @{const tm_ltrans_until}
to have a constant function $f$. ›
definition tm_const_until :: "tapeidx ==> tapeidx ==> symbol set ==> symbol ==> machine"where "tm_const_until j1 j2 H h ≡ tm_trans_until j1 j2 H (λ_. h)"
lemma tm_const_until_tm: assumes"0 < j2"and"j1 < k"and"j2 < k"and"h < G"and"k ≥ 2"and"G ≥ 4" shows"turing_machine k G (tm_const_until j1 j2 H h)" unfolding tm_const_until_def using tm_trans_until_tm assms turing_machine_def by metis
text‹
with our fantasy names ending in \emph{-plant}, we name the operation
{term constplant}. ›
abbreviation constplant :: "tape ==> symbol ==> nat ==> tape"where "constplant tp2 h n ≡ transplant (λ_. 0, 0) tp2 (λ_. h) n"
lemma constplant_transplant: "constplant tp2 h n = transplant tp1 tp2 (λ_. h) n" using transplant_def by simp
lemma constplant: "constplant tp2 h n = (λi. if snd tp2 ≤ i ∧ i < snd tp2 + n then h else fst tp2 i, snd tp2 + n)" using transplant_def by simp
lemma transforms_tm_const_untilI [transforms_intros]: assumes"j1 < k"and"j2 < k"and"length tps = k" and"rneigh (tps ! j1) H n" and"t = Suc n" and"tps' = tps[j1 := tps ! j1 |+| n, j2 := constplant (tps ! j2) h n]" shows"transforms (tm_const_until j1 j2 H h) tps t tps'" unfolding tm_const_until_def using transforms_tm_trans_untilI assms constplant_transplant by metis
definition tm_lconst_until :: "tapeidx ==> tapeidx ==> symbol set ==> symbol ==> machine"where "tm_lconst_until j1 j2 H h ≡ tm_ltrans_until j1 j2 H (λ_. h)"
lemma tm_lconst_until_tm: assumes"0 < j2"and"j1 < k"and"j2 < k"and"h < G"and"k ≥ 2"and"G ≥ 4" shows"turing_machine k G (tm_lconst_until j1 j2 H h)" unfolding tm_lconst_until_def using tm_ltrans_until_tm assms turing_machine_def by metis
abbreviation lconstplant :: "tape ==> symbol ==> nat ==> tape"where "lconstplant tp2 h n ≡ ltransplant (λ_. 0, 0) tp2 (λ_. h) n"
lemma lconstplant_ltransplant: "lconstplant tp2 h n = ltransplant tp1 tp2 (λ_. h) n" using ltransplant_def by simp
lemma lconstplant: "lconstplant tp2 h n = (λi. if snd tp2 - n < i ∧ i ≤ snd tp2 then h else fst tp2 i, snd tp2 - n)" using ltransplant_def by simp
lemma transforms_tm_lconst_untilI [transforms_intros]: assumes"0 < j2"and"j1 < k"and"j2 < k"and"length tps = k" and"lneigh (tps ! j1) H n" and"n ≤ tps :#: j1" and"n ≤ tps :#: j2" and"t = Suc n" and"tps' = tps[j1 := tps ! j1 |-| n, j2 := lconstplant (tps ! j2) h n]" shows"transforms (tm_lconst_until j1 j2 H h) tps t tps'" unfolding tm_lconst_until_def using transforms_tm_ltrans_untilI assms lconstplant_ltransplant by metis
subsection‹Writing single symbols›
text‹
next command writes a fixed symbol $h$ to tape $j$. It does not move a tape
. ›
definition cmd_write :: "tapeidx ==> symbol ==> command"where "cmd_write j h rs ≡ (1, map (λi. (if i = j then h else rs ! i, Stay)) [0..<length rs])"
lemma sem_cmd_write: "sem (cmd_write j h) (0, tps) = (1, tps[j := tps ! j |:=| h])" using cmd_write_def read_length act_Stay by (intro semI) auto
definition tm_write :: "tapeidx ==> symbol ==> machine"where "tm_write j h ≡ [cmd_write j h]"
lemma tm_write_tm: assumes"0 < j"and"j < k"and"h < G"and"G ≥ 4" shows"turing_machine k G (tm_write j h)" unfolding tm_write_def cmd_write_def using assms turing_machine_def by auto
lemma transforms_tm_writeI [transforms_intros]: assumes"tps' = tps[j := tps ! j |:=| h]" shows"transforms (tm_write j h) tps 1 tps'" unfolding tm_write_def using sem_cmd_write exe_lt_length assms tm_write_def transits_def transforms_def by auto
text‹
next command writes the symbol to tape $j_2$ that results from applying a
$f$ to the symbol read from tape $j_1$. It does not move any tape heads. ›
definition cmd_trans2 :: "tapeidx ==> tapeidx ==> (symbol ==> symbol) ==> command"where "cmd_trans2 j1 j2 f rs ≡ (1, map (λi. (if i = j2 then f (rs ! j1) else rs ! i, Stay)) [0..<length rs])"
lemma tm_trans2_tm: assumes"j1 < k"and"0 < j2"and"j2 < k"and"∀h < G. f h < G"and"k ≥ 2"and"G ≥ 4" shows"turing_machine k G (tm_trans2 j1 j2 f)" unfolding tm_trans2_def cmd_trans2_def using assms turing_machine_def by auto
lemma tm_trans_tm: assumes"0 < j"and"j < k"and"∀h < G. f h < G"and"G ≥ 4" shows"turing_machine k G (tm_trans j f)" unfolding tm_trans_def using tm_trans2_tm assms by simp
text‹
next command is like the previous one, except it also moves the tape head to
right. ›
definition cmd_rtrans :: "tapeidx ==> (symbol ==> symbol) ==> command"where "cmd_rtrans j f rs ≡ (1, map (λi. (if i = j then f (rs ! i) else rs ! i, if i = j then Right else Stay)) [0..<length rs])"
lemma tm_rtrans_tm: assumes"0 < j"and"j < k"and"∀h<G. f h < G"and"k ≥ 2"and"G ≥ 4" shows"turing_machine k G (tm_rtrans j f)" unfolding tm_rtrans_def cmd_rtrans_def using assms turing_machine_def by auto
text‹
next command writes a fixed symbol $h$ to all tapes in the set $J$. ›
definition cmd_write_many :: "tapeidx set ==> symbol ==> command"where "cmd_write_many J h rs ≡ (1, map (λi. (if i ∈ J then h else rs ! i, Stay)) [0..<length rs])"
lemma proper_cmd_write_many: "proper_command k (cmd_write_many J h)" unfolding cmd_write_many_def by auto
lemma sem_cmd_write_many: shows"sem (cmd_write_many J h) (0, tps) = (1, map (λj. if j ∈ J then tps ! j |:=| h else tps ! j) [0..<length tps])" using cmd_write_many_def read_length act_Stay by (intro semI[OF proper_cmd_write_many]) auto
definition tm_write_many :: "tapeidx set ==> symbol ==> machine"where "tm_write_many J h ≡ [cmd_write_many J h]"
lemma tm_write_many_tm: assumes"0 ∉ J"and"∀j∈J. j < k"and"h < G"and"k ≥ 2"and"G ≥ 4" shows"turing_machine k G (tm_write_many J h)" unfolding tm_write_many_def cmd_write_many_def using assms turing_machine_def by auto
lemma exe_tm_write_many: "exe (tm_write_many J h) (0, tps) = (1, map (λj. if j ∈ J then tps ! j |:=| h else tps ! j) [0..<length tps])" unfolding tm_write_many_def using sem_cmd_write_many exe_lt_length by simp
lemma execute_tm_write_many: "execute (tm_write_many J h) (0, tps) 1 = (1, map (λj. if j ∈ J then tps ! j |:=| h else tps ! j) [0..<length tps])" using exe_tm_write_many by simp
lemma transforms_tm_write_many: "transforms (tm_write_many J h) tps 1 (map (λj. if j ∈ J then tps ! j |:=| h else tps ! j) [0..<length tps])" using execute_tm_write_many transits_def transforms_def tm_write_many_def by auto
lemma transforms_tm_write_manyI [transforms_intros]: assumes"∀j∈J. j < k" and"length tps = k" and"length tps' = k" and"∧j. j ∈ J ==> tps' ! j = tps ! j |:=| h" and"∧j. j < k ==> j ∉ J ==> tps' ! j = tps ! j" shows"transforms (tm_write_many J h) tps 1 tps'" proof - have"tps' = map (λj. if j ∈ J then tps ! j |:=| h else tps ! j) [0..<length tps]" using assms by (intro nth_equalityI) simp_all thenshow ?thesis using assms transforms_tm_write_many by auto qed
subsection‹Writing a symbol multiple times›
text‹
this section we devise a Turing machine that writes the symbol sequence
h^m$ with a hard-coded symbol $h$ and number $m$ to a tape. The resulting
is defined by the next operation: ›
definition overwrite :: "tape ==> symbol ==> nat ==> tape"where "overwrite tp h m ≡ (λi. if snd tp ≤ i ∧ i < snd tp + m then h else fst tp i, snd tp + m)"
lemma overwrite_0: "overwrite tp h 0 = tp" proof - have"snd (overwrite tp h 0) = snd tp" unfolding overwrite_def by simp moreoverhave"fst (overwrite tp h 0) = fst tp" unfolding overwrite_def by auto ultimatelyshow ?thesis using prod_eqI by blast qed
lemma overwrite_upd: "(overwrite tp h t) |:=| h |+| 1 = overwrite tp h (Suc t)" using overwrite_def by auto
lemma overwrite_upd': assumes"j < length tps"and"tps' = tps[j := overwrite (tps ! j) h t]" shows"(tps[j := overwrite (tps ! j) h t])[j := tps' ! j |:=| h |+| 1] = tps[j := overwrite (tps ! j) h (Suc t)]" using assms overwrite_upd by simp
text‹
next command writes the symbol $h$ to the tape $j$ and moves the tape head
the right. ›
definition cmd_char :: "tapeidx ==> symbol ==> command"where "cmd_char j z = cmd_rtrans j (λ_. z)"
lemma turing_command_char: assumes"0 < j"and"j < k"and"h < G" shows"turing_command k 1 G (cmd_char j h)" unfolding cmd_char_def cmd_rtrans_def using assms by auto
definition tm_char :: "tapeidx ==> symbol ==> machine"where "tm_char j z ≡ [cmd_char j z]"
lemma tm_char_tm: assumes"0 < j"and"j < k"and"G ≥ 4"and"z < G" shows"turing_machine k G (tm_char j z)" using assms turing_command_char tm_char_def by auto
lemma sem_cmd_char: assumes"j < length tps" shows"sem (cmd_char j h) (0, tps) = (1, tps[j := tps ! j |:=| h |+| 1])" using cmd_char_def cmd_rtrans_def tapes_at_read read_length assms act_Right by (intro semI) auto
text‹
next TM is a sequence of $m$ @{const cmd_char} commands properly relocated.
writes a sequence of $m$ times the symbol $h$ to tape $j$. ›
definition tm_write_repeat :: "tapeidx ==> symbol ==> nat ==> machine"where "tm_write_repeat j h m ≡ map (λi. relocate_cmd i (cmd_char j h)) [0..<m]"
lemma tm_write_repeat_tm: assumes"0 < j"and"j < k"and"h < G"and"k ≥ 2"and"G ≥ 4" shows"turing_machine k G (tm_write_repeat j h m)" proof let ?M = "tm_write_repeat j h m" show"2 ≤ k"and"4 ≤ G" using assms(4,5) . show"turing_command k (length ?M) G (?M ! i)"if"i < length ?M"for i proof - have"?M ! i = relocate_cmd i (cmd_char j h)" using that tm_write_repeat_def by simp thenhave"turing_command k (1 + i) G (?M ! i)" using assms turing_command_char turing_command_relocate_cmd by metis thenshow ?thesis using turing_command_mono that by simp qed qed
lemma exe_tm_write_repeat: assumes"j < length tps"and"q < m" shows"exe (tm_write_repeat j h m) (q, tps) = (Suc q, tps[j := tps ! j |:=| h |+| 1])" using sem_cmd_char assms sem sem_relocate_cmd tm_write_repeat_def by (auto simp add: exe_lt_length)
lemma execute_tm_write_repeat: assumes"j < length tps"and"t ≤ m" shows"execute (tm_write_repeat j h m) (0, tps) t = (t, tps[j := overwrite (tps ! j) h t])" using assms(2) proof (induction t) case0 thenshow ?caseusing overwrite_0 by simp next case (Suc t) thenhave"t < m"by simp have"execute (tm_write_repeat j h m) (0, tps) (Suc t) = exe (tm_write_repeat j h m) (execute (tm_write_repeat j h m) (0, tps) t)" by simp alsohave"... = exe (tm_write_repeat j h m) (t, tps[j := overwrite (tps ! j) h t])" using Suc by simp alsohave"... = (Suc t, tps[j := overwrite (tps ! j) h (Suc t)])" using `t < m` exe_tm_write_repeat assms overwrite_upd' by simp finallyshow ?case . qed
lemma transforms_tm_write_repeatI [transforms_intros]: assumes"j < length tps"and"tps' = tps[j := overwrite (tps ! j) h m]" shows"transforms (tm_write_repeat j h m) tps m tps'" using assms execute_tm_write_repeat transits_def transforms_def tm_write_repeat_def byauto
subsection‹Moving to the start of the tape›
text‹
next command moves the head on tape $j$ to the left until it reaches
symbol from the set $H$: ›
definition cmd_left_until :: "symbol set ==> tapeidx ==> command"where "cmd_left_until H j rs ≡ if rs ! j ∈ H then (1, map (λr. (r, Stay)) rs) else (0, map (λi. (rs ! i, if i = j then Left else Stay)) [0..<length rs])"
lemma sem_cmd_left_until_1: assumes"j < k"and"length tps = k"and"(0, tps) <.> j ∈ H" shows"sem (cmd_left_until H j) (0, tps) = (1, tps)" using cmd_left_until_def tapes_at_read read_length assms act_Stay by (intro semI) auto
lemma sem_cmd_left_until_2: assumes"j < k"and"length tps = k"and"(0, tps) <.> j ∉ H" shows"sem (cmd_left_until H j) (0, tps) = (0, tps[j := tps ! j |-| 1])" using cmd_left_until_def tapes_at_read read_length assms act_Stay act_Left by (intro semI) auto
definition tm_left_until :: "symbol set ==> tapeidx ==> machine"where "tm_left_until H j ≡ [cmd_left_until H j]"
lemma tm_left_until_tm: assumes"k ≥ 2"and"G ≥ 4" shows"turing_machine k G (tm_left_until H j)" unfolding tm_left_until_def cmd_left_until_def using assms turing_machine_def by auto
text‹ \emph{begin tape} for a set of symbols has one of these symbols only in cell
. It generalizes the concept of clean tapes, where the set of symbols is \{\triangleright\}$. ›
definition begin_tape :: "symbol set ==> tape ==> bool"where "begin_tape H tp ≡∀i. fst tp i ∈ H ⟷ i = 0"
lemma begin_tapeI: assumes"fst tp 0 ∈ H"and"∧i. i > 0 ==> fst tp i ∉ H" shows"begin_tape H tp" unfolding begin_tape_def using assms by auto
lemma exe_tm_left_until_1: assumes"j < length tps"and"(0, tps) <.> j ∈ H" shows"exe (tm_left_until H j) (0, tps) = (1, tps)" using tm_left_until_def assms exe_lt_length sem_cmd_left_until_1 by auto
lemma exe_tm_left_until_2: assumes"j < length tps"and"(0, tps) <.> j ∉ H" shows"exe (tm_left_until H j) (0, tps) = (0, tps[j := tps ! j |-| 1])" using tm_left_until_def assms exe_lt_length sem_cmd_left_until_2 by auto
text‹
do not show the semantics of @{const tm_left_until} for the general case, but
for when applied to begin tapes. ›
lemma execute_tm_left_until_less: assumes"j < length tps"and"begin_tape H (tps ! j)"and"t ≤ tps :#: j" shows"execute (tm_left_until H j) (0, tps) t = (0, tps[j := tps ! j |-| t])" using assms(3) proof (induction t) case0 thenshow ?caseby simp next case (Suc t) thenhave"fst (tps ! j) (snd (tps ! j) - t) ∉ H" using assms begin_tape_def by simp thenhave neq_0: "fst (tps ! j |-| t) (snd (tps ! j |-| t)) ∉ H" by simp have"execute (tm_left_until H j) (0, tps) (Suc t) = exe (tm_left_until H j) (execute (tm_left_until H j) (0, tps) t)" by simp alsohave"... = exe (tm_left_until H j) (0, tps[j := tps ! j |-| t])" using Suc by simp alsohave"... = (0, tps[j := tps ! j |-| (Suc t)])" using neq_0 exe_tm_left_until_2 assms by simp finallyshow ?caseby simp qed
lemma execute_tm_left_until: assumes"j < length tps"and"begin_tape H (tps ! j)" shows"execute (tm_left_until H j) (0, tps) (Suc (tps :#: j)) = (1, tps[j := tps ! j |#=| 0])" using assms begin_tape_def exe_tm_left_until_1 execute_tm_left_until_less by simp
lemma transits_tm_left_until: assumes"j < length tps"and"begin_tape H (tps ! j)" shows"transits (tm_left_until H j) (0, tps) (Suc (tps :#: j)) (1, tps[j := tps ! j |#=| 0])" using execute_imp_transits[OF execute_tm_left_until[OF assms]] by simp
lemma transforms_tm_left_until: assumes"j < length tps"and"begin_tape H (tps ! j)" shows"transforms (tm_left_until H j) tps (Suc (tps :#: j)) (tps[j := tps ! j |#=| 0])" using tm_left_until_def transforms_def transits_tm_left_until[OF assms] by simp
text‹
most common case is $H = \{\triangleright\}$, which means the Turing machine
the tape head left to the closest start symbol. On clean tapes it moves
tape head to the leftmost cell of the tape. ›
text‹
next Turing machine is the first instance in which we use the $;;$ operator
concrete Turing machines. It is also the first time we use the proof method
{method tform} for @{const transforms}. The TM performs a ``carriage return''
a clean tape, that is, it moves to the first non-start symbol. ›
lemma tm_cr_tm: "k ≥ 2 ==> G ≥ 4 ==> turing_machine k G (tm_cr j)" using turing_machine_sequential_turing_machine by (simp add: tm_cr_def tm_right_tm tm_start_tm)
text‹
next Turing machine overwrites all but the start symbol with blanks. It
performs a carriage return and then writes blanks until it reaches a
. This only works as intended if there are no gaps, that is, blanks between
-blank symbols. ›
text‹
Turing machine in this section writes a hard-coded symbol sequence to a
. It is like @{const tm_write_repeat} except with an arbitrary symbol
. ›
fun tm_print :: "tapeidx ==> symbol list ==> machine"where "tm_print j [] = []" | "tm_print j (z # zs) = tm_char j z ;; tm_print j zs"
lemma tm_print_tm: assumes"0 < j"and"j < k"and"G ≥ 4"and"∀i<length zs. zs ! i < G" shows"turing_machine k G (tm_print j zs)" using assms(4) proof (induction zs) case Nil thenshow ?case using assms by auto next case (Cons z zs) thenhave"turing_machine k G (tm_char j z)" using assms tm_char_tm by auto thenshow ?case using assms Cons by fastforce qed
text‹
result of writing the symbols @{term zs} to a tape @{term tp}: ›
definition inscribe :: "tape ==> symbol list ==> tape"where "inscribe tp zs ≡ (λi. if snd tp ≤ i ∧ i < snd tp + length zs then zs ! (i - snd tp) else fst tp i, snd tp + length zs)"
lemma inscribe_Nil: "inscribe tp [] = tp" proof - have"(λi. if snd tp ≤ i ∧ i < snd tp then [] ! (i - snd tp) else fst tp i) = fst tp" by auto thenshow ?thesis unfolding inscribe_def by simp qed
lemma inscribe_Cons: "inscribe ((fst tp)(snd tp := z), Suc (snd tp)) zs = inscribe tp (z # zs)" using inscribe_def by auto
lemma inscribe_contents: "inscribe (⌊ys⌋, Suc (length ys)) zs = (⌊ys @ zs⌋, Suc (length ys + length zs))"
(is"?lhs = ?rhs") proof show"snd ?lhs = snd ?rhs" using inscribe_def contents_def by simp show"fst ?lhs = fst ?rhs" proof fix i :: nat
consider "i = 0"
| "0 < i ∧ i < Suc (length ys)"
| "Suc (length ys) ≤ i ∧ i < Suc (length ys + length zs)"
| "Suc (length ys + length zs) ≤ i" by linarith thenshow"fst ?lhs i = fst ?rhs i" proof (cases) case1 thenshow ?thesis using inscribe_def contents_def by simp next case2 thenhave"fst ?lhs i = ⌊ys⌋ i" using inscribe_def by simp thenhave lhs: "fst ?lhs i = ys ! (i - 1)" using2 contents_def by simp have"fst ?rhs i = (ys @ zs) ! (i - 1)" using2 contents_def by simp thenhave"fst ?rhs i = ys ! (i - 1)" using2by (metis Suc_diff_1 not_less_eq nth_append) thenshow ?thesis using lhs by simp next case3 thenshow ?thesis using contents_def inscribe_def by (smt (verit, del_insts) One_nat_def add.commute diff_Suc_eq_diff_pred fst_conv length_append less_Suc0
less_Suc_eq_le less_diff_conv2 nat.simps(3) not_less_eq nth_append plus_1_eq_Suc snd_conv) next case4 thenshow ?thesis using contents_def inscribe_def by simp qed qed qed
lemma inscribe_contents_Nil: "inscribe (⌊[]⌋, Suc 0) zs = (⌊zs⌋, Suc (length zs))" using inscribe_def contents_def by auto
lemma transforms_tm_print: assumes"j < length tps" shows"transforms (tm_print j zs) tps (length zs) (tps[j := inscribe (tps ! j) zs])" using assms proof (induction zs arbitrary: tps) case Nil thenshow ?case using inscribe_Nil transforms_Nil by simp next case (Cons z zs) have"transforms (tm_char j z ;; tm_print j zs) tps (length (z # zs)) (tps[j := inscribe (tps ! j) (z # zs)])" proof (tform tps: Cons) let ?tps = "tps[j := tps ! j |:=| z |+| 1]" have"transforms (tm_print j zs) ?tps (length zs) (?tps[j := inscribe (?tps ! j) zs])" using Cons by (metis length_list_update) moreoverhave"(?tps[j := inscribe (?tps ! j) zs]) = (tps[j := inscribe (tps ! j) (z # zs)])" using inscribe_Cons Cons.prems by simp ultimatelyshow"transforms (tm_print j zs) ?tps (length zs) (tps[j := inscribe (tps ! j) (z # zs)])" by simp qed thenshow"transforms (tm_print j (z # zs)) tps (length (z # zs)) (tps[j := inscribe (tps ! j) (z # zs)])" by simp qed
subsection‹Setting the tape contents to a symbol sequence›
text‹
following Turing machine erases the tape, then prints a hard-coded
sequence, and then performs a carriage return. It thus sets
tape contents to the symbol sequence. ›
subsection‹Comparing two tapes\label{s:tm-elementary-comparing}›
text‹
next Turing machine compares the contents of two tapes $j_1$ and $j_2$ and
to tape $j_3$ either a @{text 1} or a @{text ◻} depending on whether the
are equal or not. The next command does all the work. It scans both tapes
to right and halts if it encounters a blank on both tapes, which means the
are equal, or two different symbols, which means the tapes are unequal. It
works for contents without blanks. ›
definition cmd_cmp :: "tapeidx ==> tapeidx ==> tapeidx ==> command"where "cmd_cmp j1 j2 j3 rs ≡ if rs ! j1 ≠ rs ! j2 then (1, map (λi. (if i = j3 then ◻ else rs ! i, Stay)) [0..<length rs]) else if rs ! j1 = ◻∨ rs ! j2 = ◻ then (1, map (λi. (if i = j3 then 1 else rs ! i, Stay)) [0..<length rs]) else (0, map (λi. (rs ! i, if i = j1 ∨ i = j2 then Right else Stay)) [0..<length rs])"
lemma tm_cmp_tm: assumes"k ≥ 2"and"j3 > 0"and"G ≥ 4" shows"turing_machine k G (tm_cmp j1 j2 j3)" unfolding tm_cmp_def cmd_cmp_def using assms turing_machine_def by auto
lemma transforms_tm_cmpI [transforms_intros]: fixes tps :: "tape list" assumes"length tps = k" and"j1 ≠ j2"and"j2 ≠ j3"and"j1 ≠ j3"and"j1 < k"and"j2 < k"and"j3 < k" and"proper_symbols xs" and"proper_symbols ys" and"tps ! j1 = (⌊xs⌋, 1)" and"tps ! j2 = (⌊ys⌋, 1)" and"t = Suc (min (length xs) (length ys))" and"b = (if xs = ys then 1 else ◻)" and"m = (if xs = ys then Suc (length xs) else (LEAST m. m ≤ Suc (min (length xs) (length ys)) ∧⌊xs⌋ m ≠⌊ys⌋ m))" and"tps' = tps[j1 := (⌊xs⌋, m), j2 := (⌊ys⌋, m), j3 := tps ! j3 |:=| b]" shows"transforms (tm_cmp j1 j2 j3) tps t tps'" proof (cases "xs = ys") case True thenhave m: "m = Suc (length xs)" using assms(14) by simp have"execute (tm_cmp j1 j2 j3) (0, tps) (Suc (length xs)) = (1, tps[j1 := tps ! j1 |+| length xs, j2 := tps ! j2 |+| length xs, j3 := tps ! j3 |:=| 1])" using execute_tm_cmp_eq assms True by blast thenhave"execute (tm_cmp j1 j2 j3) (0, tps) m = (1, tps[j1 := tps ! j1 |+| (m - 1), j2 := tps ! j2 |+| (m - 1), j3 := tps ! j3 |:=| b])" using m assms(13) True diff_Suc_1 by simp moreoverhave"m ≤ t" using True assms(12) m by simp ultimatelyshow ?thesis using transitsI tm_cmp_def transforms_def assms True by (metis (no_types, lifting) One_nat_def add.commute diff_Suc_1 fst_conv list.size(3) list.size(4) plus_1_eq_Suc snd_conv) next case False thenhave m: "m = (LEAST m. m ≤ Suc (min (length xs) (length ys)) ∧⌊xs⌋ m ≠⌊ys⌋ m)" using assms(14) by simp thenhave"execute (tm_cmp j1 j2 j3) (0, tps) m = (1, tps[j1 := tps ! j1 |+| (m - 1), j2 := tps ! j2 |+| (m - 1), j3 := tps ! j3 |:=| ◻])" using False assms execute_tm_cmp_neq by blast thenhave"execute (tm_cmp j1 j2 j3) (0, tps) m = (1, tps[j1 := tps ! j1 |+| (m - 1), j2 := tps ! j2 |+| (m - 1), j3 := tps ! j3 |:=| b])" using False by (simp add: assms(13)) moreoverhave"m ≤ t" using ex_contents_neq[OF assms(8,9)] False assms(12) m by (metis (mono_tags, lifting) LeastI) ultimatelyshow ?thesis using transitsI tm_cmp_def transforms_def assms False by (metis (no_types, lifting) One_nat_def Suc_eq_plus1 Suc_pred add.commute execute.simps(1)
fst_eqD list.size(3) list.size(4) not_gr0 numeral_One snd_conv zero_neq_numeral) qed
text‹
next Turing machine extends @{const tm_cmp} by a carriage return on tapes
j_1$ and $j_2$, ensuring that the next command finds the tape heads in a
-specified position. This makes the TM easier to reuse. ›
lemma tm_equals_tm: assumes"k ≥ 2"and"j3 > 0"and"G ≥ 4" shows"turing_machine k G (tm_equals j1 j2 j3)" unfolding tm_equals_def using tm_cmp_tm tm_cr_tm assms by simp
text‹
analyze the behavior of @{const tm_equals} inside a locale. This is how we
typically proceed for Turing machines that are composed of more than two
. The locale is parameterized by the TM's parameters, which in the present
means the three tape indices $j_1$, $j_2$, and $j_3$. Inside the locale
TM is decomposed such that proofs of @{const transforms} only involve two
combined by one of the three control structures (sequence, branch, loop).
the current example we have three TMs named @{term tm1}, @{term tm2}, @{term
}, where @{term tm3} is just @{const tm_equals}. Furthermore there will be \emph{tm1}, \emph{tm2}, \emph{tm3} describing, in terms of @{const
}, the behavior of the respective TMs. For this we define three tape
@{term tps1}, @{term tps2}, @{term tps3}.
naming scheme creates many name clashes for things that only have a single
. That is the reason for the encapsulation in a locale.
this locale is interpreted, just once in lemma~@{text
}, to prove the semantics and running time of @{const
}.
null ›
locale turing_machine_equals = fixes j1 j2 j3 :: tapeidx begin
context fixes tps0 :: "tape list"and k t b :: nat and xs ys :: "symbol list" assumes jk [simp]: "length tps0 = k""j1 ≠ j2""j2 ≠ j3""j1 ≠ j3""j1 < k""j2 < k""j3 < k" and proper: "proper_symbols xs""proper_symbols ys" and t: "t = Suc (min (length xs) (length ys))" and b: "b = (if xs = ys then 3 else 0)" assumes tps0: "tps0 ! j1 = (⌊xs⌋, 1)" "tps0 ! j2 = (⌊ys⌋, 1)" begin
definition"m ≡ (if xs = ys then Suc (length xs) else (LEAST m. m ≤ Suc (min (length xs) (length ys)) ∧⌊xs⌋ m ≠⌊ys⌋ m))"
lemma m_gr_0: "m > 0" proof - have"⌊xs⌋ m ≠⌊ys⌋ m"if"xs ≠ ys" using ex_contents_neq LeastI_ex m_def proper that by (metis (mono_tags, lifting)) thenshow"m > 0" using m_def by (metis contents_at_0 gr0I less_Suc_eq_0_disj) qed
lemma m_le_t: "m ≤ t" proof (cases "xs = ys") case True thenshow ?thesis using t m_def by simp next case False thenhave"m ≤ Suc (min (length xs) (length ys))" using ex_contents_neq False proper m_def by (metis (mono_tags, lifting) LeastI_ex) thenshow ?thesis using t by simp qed
definition"tps1 ≡ tps0[j1 := (⌊xs⌋, m), j2 := (⌊ys⌋, m), j3 := tps0 ! j3 |:=| b]"
lemma tm1 [transforms_intros]: "transforms tm1 tps0 t tps1" unfolding tm1_def proof (tform tps: tps0 tps1_def m_def b time: t) show"proper_symbols xs""proper_symbols ys" using proper by simp_all qed
lemma tm3: assumes"ttt = 2 * t + m + 4" shows"transforms tm3 tps0 ttt tps3" unfolding tm3_def proof (tform tps: tps2_def tps3_def) have *: "tps2 ! j2 = (⌊ys⌋, m)" using tps2_def by (simp add: nth_list_update_neq') thenshow"clean_tape (tps2 ! j2)" using clean_contents_proper proper(2) by simp show"ttt = 2 * t + 2 + (tps2 :#: j2 + 2)" using assms * by simp show"tps3 = tps2[j2 := tps2 ! j2 |#=| 1]" unfolding tps3_def tps2_def by (simp add: list_update_swap[of j2]) qed
definition"tps3' ≡ tps0[j3 := tps0 ! j3 |:=| b]"
lemma tm3': "transforms tm3 tps0 (3 * min (length xs) (length ys) + 7) tps3'" proof - have"tps3' = tps3" using tps3'_def tps3_def tps0 jk by (metis list_update_id) thenshow ?thesis using m_le_t tm3 transforms_monotone t by simp qed
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.