(** ** Definition of single-tape Turing Machines  *)
(** Adopted definitions from the formalization of Multitape Turing Machines taken from Asperti, Riciotti "Formalizing Turing Machines" and accompanying Matita foramlisation *)
Variable sig : finType.
Global Instance eq_dec_sig: eq_dec sig.
(* *** Definition of a Sigletape Turing Machine *)
Record sTM : Type :=
{
states : finType; (* states of the TM *)
trans : states * (option sig) -> states * ((option sig) * move); (* the transition function *)
start: states; (* the start state *)
halt : states -> bool (* decidable subset of halting states *)
}.
(* Definition of tape movements *)
Definition tape_move_right :=
fun (t : tape) =>
match t with
niltape => niltape
| rightof _ _ =>t
| leftof a rs => midtape  [ ] a rs
| midtape ls a rs =>
match rs with
[]  => rightof  a ls
| a0 :: rs0 => midtape (a::ls) a0 rs0
end
end.
Definition tape_move_left :=
fun (t : tape) =>
match t with
niltape => niltape
| leftof _ _ => t
| rightof a ls => midtape ls a [ ]
| midtape ls a rs =>
match ls with
[] => leftof a rs
| a0 :: ls0 => midtape ls0 a0 (a::rs)
end
end.
Definition tape_move := fun (t : tape) (m : move) =>
match m with  R => tape_move_right t | L => tape_move_left t | N => t end.
(* Writing on the tape *)
Definition tape_write := fun (t : tape) (s : option sig) =>
match s with
None => t
| Some s0 => midtape (left t) s0 (right t)
end.
(** A single step of the machine *)
Definition tape_move_mono := fun (t : tape) (mv : option sig * move) =>
tape_move (tape_write t (fst mv)) (snd mv).
(* *** Configurations of TM *)
Record mconfig (states:finType) : Type :=
mk_mconfig
{
cstate : states;
ctape : tape
}.
Instance eq_dec_conf (s: finType): eq_dec (mconfig s).
(* *** Machine execution *)
Definition step :=
fun (M:sTM) (c:mconfig (states M)) =>
let (news,action) := trans (cstate c, current (ctape c))
in mk_mconfig news (tape_move_mono (ctape c) action).
(* Initial configuration *)
Definition initc := fun (M : sTM) tape =>
mk_mconfig (@start M) tape.
(* Run the machine i steps until it halts *)
(* Returns None iff the maschine does not halt within i steps *)
Definition loop (A:Type) := fix l n (f:A -> A) (p : A -> bool) a {struct n}:=
if p a then Some a  else
match n with
O => None
| S m => l m f p (f a)
end.
Definition loopM := fun (M :sTM) (i : nat) cin =>
loop i (@step M) (fun c => halt (cstate c)) cin.
(* *** Definition of Reachability *)
Definition TMterminates (M: sTM) (start: mconfig (states M)) :=
exists i outc, loopM i start = Some outc.

Lemma loop_step_not A f p (a : A) i out:
loop i f p (f a) = out -> (p a = false) -> (loop (S i) f p a = out).