Theory HaltingProblems_K_H
subsection ‹Undecidability of Halting Problems›
theory HaltingProblems_K_H
imports
SimpleGoedelEncoding
SemiIdTM
TuringReducible
begin
subsubsection ‹A locale for variations of the Halting Problem›
text ‹
The following locale assumes that there is an injective coding function ‹t2c›
from Turing machines to natural numbers. In this locale, we will show that the
Special Halting Problem K1 and the General Halting Problem H1 are not Turing decidable.
›
locale hpk =
fixes t2c :: "tprog0 ⇒ nat"
assumes
t2c_inj: "inj t2c"
begin
text ‹The function @{term tm_to_nat} is a witness that the locale hpk is inhabited.›
interpretation tm_to_nat: hpk "tm_to_nat :: tprog0 ⇒ nat"
proof unfold_locales
show "inj tm_to_nat" by (rule inj_tm_to_nat)
qed
text ‹We define the function @{term c2t} as the unique inverse of the
injective function @{term t2c}.
›
definition c2t :: "nat ⇒ instr list"
where
"c2t = (λn. if (∃p. t2c p = n)
then (THE p. t2c p = n)
else (SOME p. True) )"
lemma t2c_inj': "inj_on t2c {x. True}"
by (auto simp add: t2c_inj )
lemma c2t_comp_t2c_eq: "c2t (t2c p) = p"
proof -
have "∀p∈{x. True}. c2t (t2c p) = p"
proof (rule encode_decode_A_eq[OF t2c_inj'])
show "c2t = (λw. if ∃t∈{x. True}. t2c t = w then THE t. t ∈ {x. True} ∧ t2c t = w else SOME t. t ∈ {x. True})"
by (auto simp add: c2t_def)
qed
then show ?thesis by auto
qed
subsubsection ‹Undecidability of the Special Halting Problem K1›
definition K1 :: "(nat list) set"
where
"K1 ≡ {nl. (∃n. nl = [n] ∧ TMC_has_num_res (c2t n) [n]) }"
text ‹Assuming the existence of a Turing Machine K1D1, which is able to decide the set K1,
we derive a contradiction using the machine @{term "tm_semi_id_eq0"}.
Thus, we show that the {\em Special Halting Problem K1} is not Turing decidable.
\label{sec_K1_H1}
The proof uses a diagonal argument.
›
lemma mk_composable_decider_K1D1:
assumes "∃K1D1'. (∀nl.
(nl ∈ K1 ⟶TMC_yields_num_res K1D1' nl (1::nat))
∧ (nl ∉ K1 ⟶TMC_yields_num_res K1D1' nl (0::nat) ))"
shows "∃K1D1'. (∀nl. composable_tm0 K1D1' ∧
(nl ∈ K1 ⟶TMC_yields_num_res K1D1' nl (1::nat))
∧ (nl ∉ K1 ⟶TMC_yields_num_res K1D1' nl (0::nat) ))"
proof -
from assms have
"∃K1D1'. (∀nl.
(nl ∈ K1 ⟶⦃λtap. tap = ([], <nl>)⦄ K1D1' ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc,Oc] @ Bk ↑ l)⦄)
∧ (nl ∉ K1 ⟶⦃λtap. tap = ([], <nl>)⦄ K1D1' ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc] @ Bk ↑ l)⦄) )"
unfolding TMC_yields_num_res_unfolded_into_Hoare_halt
by (simp add: tape_of_nat_def)
then obtain K1D1' where
"(∀nl.
(nl ∈ K1 ⟶ ⦃λtap. tap = ([], <nl>)⦄ K1D1' ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc, Oc] @ Bk ↑ l)⦄)
∧ (nl ∉ K1 ⟶ ⦃λtap. tap = ([], <nl>)⦄ K1D1' ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc] @ Bk ↑ l)⦄))"
by blast
then have "composable_tm0 (mk_composable0 K1D1') ∧ (∀nl.
(nl ∈ K1 ⟶ ⦃λtap. tap = ([], <nl>)⦄ mk_composable0 K1D1' ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc, Oc] @ Bk ↑ l)⦄)
∧ (nl ∉ K1 ⟶ ⦃λtap. tap = ([], <nl>)⦄ mk_composable0 K1D1' ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc] @ Bk ↑ l)⦄))"
using Hoare_halt_tm_impl_Hoare_halt_mk_composable0 composable_tm0_mk_composable0 by blast
then have "composable_tm0 (mk_composable0 K1D1') ∧ (∀nl.
(nl ∈ K1 ⟶ TMC_yields_num_res (mk_composable0 K1D1') nl (1::nat) )
∧ (nl ∉ K1 ⟶ TMC_yields_num_res (mk_composable0 K1D1') nl (0::nat) ))"
unfolding TMC_yields_num_res_unfolded_into_Hoare_halt
by (simp add: tape_of_nat_def)
then show ?thesis by auto
qed
lemma res_1_fed_into_tm_semi_id_eq0_loops:
assumes "composable_tm0 D"
and "TMC_yields_num_res D nl (1::nat)"
shows "TMC_loops (D |+| tm_semi_id_eq0) nl"
unfolding TMC_loops_def
proof
fix stp
show "¬ is_final (steps0 (1, [], <nl::nat list>) (D |+| tm_semi_id_eq0) stp)"
using assms tm_semi_id_eq0_loops''
Hoare_plus_unhalt Hoare_unhalt_def
tape_of_nat_def tape_of_list_def
TMC_yields_num_res_unfolded_into_Hoare_halt
by simp
qed
lemma loops_imp_has_no_res: "TMC_loops tm [n] ⟹ ¬ TMC_has_num_res tm [n]"
proof -
assume "TMC_loops tm [n]"
then show "¬ TMC_has_num_res tm [n]"
using TMC_has_num_res_iff TMC_loops_def
by blast
qed
lemma yields_res_imp_has_res: "TMC_yields_num_res tm [n] (m::nat) ⟹ TMC_has_num_res tm [n]"
proof -
assume "TMC_yields_num_res tm [n] (m::nat)"
then show "TMC_has_num_res tm [n]"
by (metis TMC_has_num_res_iff TMC_yields_num_res_def is_finalI)
qed
lemma res_0_fed_into_tm_semi_id_eq0_yields_0:
assumes "composable_tm0 D"
and "TMC_yields_num_res D nl (0::nat)"
shows "TMC_yields_num_res (D |+| tm_semi_id_eq0) nl 0"
unfolding TMC_yields_num_res_unfolded_into_Hoare_halt
using assms Hoare_plus_halt tm_semi_id_eq0_halts''
tape_of_nat_def tape_of_list_def
TMC_yields_num_res_unfolded_into_Hoare_halt
by simp
lemma existence_of_decider_K1D1_for_K1_imp_False:
assumes major: "∃K1D1'. (∀nl.
(nl ∈ K1 ⟶TMC_yields_num_res K1D1' nl (1::nat))
∧ (nl ∉ K1 ⟶TMC_yields_num_res K1D1' nl (0::nat) ))"
shows False
proof -
from major have
"∃K1D1'. (∀nl. composable_tm0 K1D1' ∧
(nl ∈ K1 ⟶ TMC_yields_num_res K1D1' nl (1::nat))
∧ (nl ∉ K1 ⟶ TMC_yields_num_res K1D1' nl (0::nat) ))"
by (rule mk_composable_decider_K1D1)
then obtain K1D1 where
w_K1D1: "∀nl. composable_tm0 K1D1 ∧
(nl ∈ K1 ⟶ TMC_yields_num_res K1D1 nl (1::nat))
∧ (nl ∉ K1 ⟶ TMC_yields_num_res K1D1 nl (0::nat) )"
by blast
define tm_contra where "tm_contra = K1D1 |+| tm_semi_id_eq0"
have c2t_comp_t2c_eq_for_tm_contra: "c2t (t2c tm_contra) = tm_contra"
by (auto simp add: c2t_comp_t2c_eq)
show False
proof (cases "[t2c tm_contra] ∈ K1")
case True
from ‹[t2c tm_contra] ∈ K1› and w_K1D1
have "TMC_yields_num_res K1D1 [t2c tm_contra] (1::nat)"
by auto
then have "TMC_loops tm_contra [t2c tm_contra]"
using res_1_fed_into_tm_semi_id_eq0_loops w_K1D1 tm_contra_def
by blast
then have "¬(TMC_has_num_res tm_contra [t2c tm_contra])"
using loops_imp_has_no_res by blast
then have "¬(TMC_has_num_res (c2t (t2c tm_contra))) [t2c tm_contra]"
by (auto simp add: c2t_comp_t2c_eq_for_tm_contra)
then have "[t2c tm_contra] ∉ K1"
by (auto simp add: K1_def)
with ‹[t2c tm_contra] ∈ K1› show False by auto
next
case False
from ‹[t2c tm_contra] ∉ K1› and w_K1D1
have "TMC_yields_num_res K1D1 [t2c tm_contra] (0::nat)"
by auto
then have "TMC_yields_num_res tm_contra [t2c tm_contra] (0::nat)"
using res_0_fed_into_tm_semi_id_eq0_yields_0 w_K1D1 tm_contra_def
by auto
then have "TMC_has_num_res tm_contra [t2c tm_contra]"
using yields_res_imp_has_res by blast
then have "TMC_has_num_res (c2t (t2c tm_contra)) [t2c tm_contra]"
by (auto simp add: c2t_comp_t2c_eq_for_tm_contra)
then have "[t2c tm_contra] ∈ K1"
by (auto simp add: K1_def)
with ‹[t2c tm_contra] ∉ K1› show False by auto
qed
qed
subsubsection ‹The Special Halting Problem K1 is reducible to the General Halting Problem H1›
text ‹The proof is by reduction of ‹K1› to ‹H1›.
›
definition H1 :: "(nat list) set"
where
"H1 ≡ {nl. (∃n m. nl = [n,m] ∧ TMC_has_num_res (c2t n) [m]) }"
lemma NilNotIn_K1: "[] ∉ K1"
unfolding K1_def
using CollectD list.simps(3) by auto
lemma NilNotIn_H1: "[] ∉ H1"
unfolding H1_def
using CollectD list.simps(3) by auto
lemma tm_strong_copy_total_correctness_Nil':
"length nl = 0 ⟹ TMC_yields_num_list_res tm_strong_copy nl []"
unfolding TMC_yields_num_list_res_unfolded_into_Hoare_halt
proof -
assume "length nl = 0"
then have "⦃λtap. tap = ([], <nl::nat list>) ⦄ tm_strong_copy ⦃λtap. tap = ([Bk,Bk,Bk,Bk],[]) ⦄"
using tm_strong_copy_total_correctness_Nil by simp
then have F1: "⦃λtap. tap = ([], <nl>)⦄ tm_strong_copy ⦃λtap. tap = (Bk ↑ 4, <[]> @ Bk ↑ 0)⦄"
by (metis One_nat_def Suc_1 ‹length nl = 0›
append_Nil length_0_conv numeral_4_eq_4 numeral_eqs_upto_12(2)
replicate_0 replicate_Suc tape_of_list_empty)
show "⦃λtap. tap = ([], <nl::nat list>)⦄
tm_strong_copy
⦃λtap. ∃k l. tap = (Bk ↑ k, <[]::nat list> @ Bk ↑ l)⦄"
proof (rule Hoare_haltI)
fix l::"cell list"
fix r::"cell list"
assume "(l, r) = ([], <nl::nat list>)"
show "∃n. is_final (steps0 (1, l, r) tm_strong_copy n) ∧
(λtap. ∃k l. tap = (Bk ↑ k, <[]::nat list> @ Bk ↑ l)) holds_for steps0 (1, l, r) tm_strong_copy n"
by (smt (verit) F1 Hoare_haltE ‹(l, r) = ([], <nl>)› holds_for.elims(2) holds_for.simps)
qed
qed
lemma tm_strong_copy_total_correctness_len_eq_1':
"length nl = 1 ⟹ TMC_yields_num_list_res tm_strong_copy nl [hd nl, hd nl]"
unfolding TMC_yields_num_list_res_unfolded_into_Hoare_halt
proof -
assume "length nl = 1"
then show "⦃λtap. tap = ([], <nl::nat list>) ⦄
tm_strong_copy
⦃ λtap. ∃k l. tap = (Bk ↑ k, <[hd nl, hd nl]> @ Bk ↑ l) ⦄"
using tm_strong_copy_total_correctness_len_eq_1 by simp
qed
lemma tm_strong_copy_total_correctness_len_gt_1':
"1 < length nl ⟹ TMC_yields_num_list_res tm_strong_copy nl [hd nl]"
unfolding TMC_yields_num_list_res_unfolded_into_Hoare_halt
proof -
assume "1 < length nl"
then have "⦃λtap. tap = ([], <nl::nat list>) ⦄
tm_strong_copy
⦃ λtap. ∃l. tap = ([Bk,Bk], <[hd nl]> @ Bk ↑ l) ⦄"
using tm_strong_copy_total_correctness_len_gt_1 by simp
then show "⦃λtap. tap = ([], <nl::nat list>) ⦄
tm_strong_copy
⦃ λtap. ∃k l. tap = (Bk ↑ k, <[hd nl]> @ Bk ↑ l) ⦄"
by (smt (verit, ccfv_threshold) Hoare_haltE Hoare_haltI One_nat_def Pair_inject Pair_inject holds_for.elims(2)
holds_for.simps is_final.elims(2) replicate.simps(1) replicate.simps(2))
qed
theorem turing_reducible_K1_H1: "turing_reducible K1 H1"
unfolding turing_reducible_unfolded_into_TMC_yields_condition
proof -
have "∀nl::nat list. ∃ml::nat list.
TMC_yields_num_list_res tm_strong_copy nl ml ∧ (nl ∈ K1 ⟷ ml ∈ H1)"
proof
fix nl::"nat list"
have "length nl = 0 ∨ length nl = 1 ∨ 1 < length nl"
by arith
then
show "∃ml. TMC_yields_num_list_res tm_strong_copy nl ml ∧ (nl ∈ K1) = (ml ∈ H1)"
proof
assume "length nl = 0"
then have "TMC_yields_num_list_res tm_strong_copy nl []"
by (rule tm_strong_copy_total_correctness_Nil')
moreover have "(nl ∈ K1) = ([] ∈ H1)"
using NilNotIn_H1 NilNotIn_K1 ‹length nl = 0› length_0_conv by blast
ultimately
show "∃ml. TMC_yields_num_list_res tm_strong_copy nl ml ∧ (nl ∈ K1) = (ml ∈ H1)" by blast
next
assume "length nl = 1 ∨ 1 < length nl"
then show "∃ml. TMC_yields_num_list_res tm_strong_copy nl ml ∧ (nl ∈ K1) = (ml ∈ H1)"
proof
assume "1 < length nl"
then have "TMC_yields_num_list_res tm_strong_copy nl [hd nl]"
by (rule tm_strong_copy_total_correctness_len_gt_1')
moreover have "(nl ∈ K1) = ([hd nl] ∈ H1)"
using H1_def K1_def ‹1 < length nl› by auto
ultimately
show "∃ml. TMC_yields_num_list_res tm_strong_copy nl ml ∧ (nl ∈ K1) = (ml ∈ H1)" by blast
next
assume "length nl = 1"
then have "TMC_yields_num_list_res tm_strong_copy nl [hd nl, hd nl]"
by (rule tm_strong_copy_total_correctness_len_eq_1')
moreover have "(nl ∈ K1) = ([hd nl, hd nl] ∈ H1)"
by (smt (verit) CollectD Cons_eq_append_conv H1_def K1_def One_nat_def ‹length nl = 1›
append_Cons diff_Suc_1 hd_Cons_tl length_0_conv length_tl list.inject
mem_Collect_eq not_Cons_self2 self_append_conv2 zero_neq_one)
ultimately
show "∃ml. TMC_yields_num_list_res tm_strong_copy nl ml ∧ (nl ∈ K1) = (ml ∈ H1)" by blast
qed
qed
qed
then show "∃tm. ∀nl. ∃ml. TMC_yields_num_list_res tm nl ml ∧ (nl ∈ K1) = (ml ∈ H1)"
by auto
qed
subsubsection ‹Corollaries about the undecidable sets K1 and H1›
corollary not_Turing_decidable_K1: "¬(turing_decidable K1)"
proof
assume "turing_decidable K1"
then have "(∃D. (∀nl.
(nl ∈ K1 ⟶TMC_yields_num_res D nl (1::nat))
∧ (nl ∉ K1 ⟶TMC_yields_num_res D nl (0::nat) )))"
by (auto simp add: turing_decidable_unfolded_into_TMC_yields_conditions
tape_of_nat_def)
with existence_of_decider_K1D1_for_K1_imp_False show False
by blast
qed
corollary not_Turing_decidable_H1: "¬turing_decidable H1"
proof (rule turing_reducible_AB_and_non_decA_imp_non_decB)
show "turing_reducible K1 H1"
by (rule turing_reducible_K1_H1)
next
show "¬ turing_decidable K1"
by (rule not_Turing_decidable_K1)
qed
subsubsection ‹Proof variant: The special Halting Problem K1 is not Turing Decidable›
text‹Assuming the existence of a Turing Machine K1D0, which is able to decide the set K1,
we derive a contradiction using the machine @{term "tm_semi_id_gt0"}.
Thus, we show that the {\em Special Halting Problem K1} is not Turing decidable.
The proof uses a diagonal argument.
\label{sec_K1_v}›
lemma existence_of_decider_K1D0_for_K1_imp_False:
assumes "∃K1D0'. (∀nl.
(nl ∈ K1 ⟶TMC_yields_num_res K1D0' nl (0::nat))
∧ (nl ∉ K1 ⟶TMC_yields_num_res K1D0' nl (1::nat) ))"
shows False
proof -
from assms have
"∃K1D0'. (∀nl.
(nl ∈ K1 ⟶⦃λtap. tap = ([], <nl>)⦄ K1D0' ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc] @ Bk ↑ l)⦄)
∧ (nl ∉ K1 ⟶⦃λtap. tap = ([], <nl>)⦄ K1D0' ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc, Oc] @ Bk ↑ l)⦄) )"
unfolding TMC_yields_num_res_unfolded_into_Hoare_halt
by (simp add: tape_of_nat_def)
then obtain K1D0' where
"(∀nl.
(nl ∈ K1 ⟶ ⦃λtap. tap = ([], <nl>)⦄ K1D0' ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc] @ Bk ↑ l)⦄)
∧ (nl ∉ K1 ⟶ ⦃λtap. tap = ([], <nl>)⦄ K1D0' ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc, Oc] @ Bk ↑ l)⦄))"
by blast
then have "composable_tm0 (mk_composable0 K1D0') ∧ (∀nl.
(nl ∈ K1 ⟶ ⦃λtap. tap = ([], <nl>)⦄ mk_composable0 K1D0' ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc] @ Bk ↑ l)⦄)
∧ (nl ∉ K1 ⟶ ⦃λtap. tap = ([], <nl>)⦄ mk_composable0 K1D0' ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc, Oc] @ Bk ↑ l)⦄))"
using Hoare_halt_tm_impl_Hoare_halt_mk_composable0 composable_tm0_mk_composable0 by blast
then have "∃K1D0. composable_tm0 K1D0 ∧ (∀nl.
(nl ∈ K1 ⟶ ⦃λtap. tap = ([], <nl>)⦄ K1D0 ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc] @ Bk ↑ l)⦄)
∧ (nl ∉ K1 ⟶ ⦃λtap. tap = ([], <nl>)⦄ K1D0 ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc, Oc] @ Bk ↑ l)⦄))"
by blast
then obtain K1D0 where w_K1D0: "composable_tm0 K1D0 ∧ (∀nl.
(nl ∈ K1 ⟶ ⦃λtap. tap = ([], <nl>)⦄ K1D0 ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc] @ Bk ↑ l)⦄)
∧ (nl ∉ K1 ⟶ ⦃λtap. tap = ([], <nl>)⦄ K1D0 ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc, Oc] @ Bk ↑ l)⦄))"
by blast
define tm_contra where "tm_contra = K1D0 |+| tm_semi_id_gt0"
then have c2t_comp_t2c_TM_eq_for_tm_contra: "c2t (t2c tm_contra) = tm_contra"
by (auto simp add: c2t_comp_t2c_eq)
show False
proof (cases "[t2c tm_contra] ∈ K1")
case True
from ‹[t2c tm_contra] ∈ K1› and w_K1D0 have
"⦃λtap. tap = ([], <[t2c tm_contra]>)⦄ K1D0 ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc] @ Bk ↑ l)⦄"
by auto
then have
"⦃λtap. tap = ([], <[t2c tm_contra]>)⦄ tm_contra ↑"
unfolding tm_contra_def
proof (rule Hoare_plus_unhalt)
show "⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc] @ Bk ↑ l)⦄ tm_semi_id_gt0 ↑"
by (rule tm_semi_id_gt0_loops'')
next
from w_K1D0 show "composable_tm0 K1D0" by auto
qed
then have
"⦃λtap. tap = ([], <[t2c tm_contra]>)⦄ c2t (t2c tm_contra) ↑"
by (auto simp add: c2t_comp_t2c_TM_eq_for_tm_contra)
then have "¬⦃λtap. tap = ([], <[t2c tm_contra]>)⦄ c2t (t2c tm_contra) ⦃ λtap. (∃k n l. tap = (Bk ↑ k, <n::nat> @ Bk ↑ l)) ⦄"
using Hoare_halt_impl_not_Hoare_unhalt by blast
then have "¬( TMC_has_num_res (c2t (t2c tm_contra)) [t2c tm_contra])"
by (auto simp add: TMC_has_num_res_def)
then have "[t2c tm_contra] ∉ K1"
by (auto simp add: K1_def)
with ‹[t2c tm_contra] ∈ K1› show False by auto
next
case False
from ‹[t2c tm_contra] ∉ K1› and w_K1D0 have
"⦃λtap. tap = ([], <[t2c tm_contra]>)⦄ K1D0 ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc, Oc] @ Bk ↑ l)⦄"
by auto
then have
"⦃λtap. tap = ([], <[t2c tm_contra]>)⦄ tm_contra ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc, Oc] @ Bk ↑ l)⦄"
unfolding tm_contra_def
proof (rule Hoare_plus_halt)
show "⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc, Oc] @ Bk ↑ l)⦄ tm_semi_id_gt0 ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc, Oc] @ Bk ↑ l)⦄"
by (rule tm_semi_id_gt0_halts'')
next
from w_K1D0 show "composable_tm0 K1D0" by auto
qed
then have
"⦃λtap. tap = ([], <[t2c tm_contra]>)⦄ c2t (t2c tm_contra) ⦃λtap. ∃k l. tap = (Bk ↑ k, [Oc, Oc] @ Bk ↑ l)⦄"
by (auto simp add: c2t_comp_t2c_TM_eq_for_tm_contra)
then have
" TMC_has_num_res (c2t (t2c tm_contra)) [t2c tm_contra]"
by (auto simp add: Hoare_halt_with_OcOc_imp_std_tap tape_of_nat_def)
then have "[t2c tm_contra] ∈ K1"
by (auto simp add: K1_def)
with ‹[t2c tm_contra] ∉ K1› show False by auto
qed
qed
end
end