Fact map_symb_sigma A :
List.map symb (List.map sigma A) = List.map sym A.
(* Automation for rewrite_step_halt Lemma. ListInv mainly eliminates contradictory assumptions while state_inv also solves cases *)
Ltac listInv :=
cbn in *;
match goal with
| [H: sym _ = sym _ |- _ ] => inv H
| [H: [] = _ ::_  |- _ ] => inv H
| [H: _::_ = _::_ |- _ ] => inv H
| [H: []++ _ = _ |- _ ] => rewrite app_nil_l in H
| [H: _ ++[] = _ |- _ ] => rewrite app_nil_r in H
| [H: _ = []++ _ |- _ ] => rewrite app_nil_l in H
| [H: _ = _ ++[] |- _ ] => rewrite app_nil_r in H
| [H: [] = List.map sym ?L |- _ ] => destruct L eqn: ?
| [H: List.rev ?L = [] |- _] => apply rev_nil in H
| [H: _ ++ _::_ = [] |- _ ] => symmetry in H; now apply app_cons_not_nil in H
| [H: [] = List.map _ (List.rev (_) ++ ?e) |- _ ] =>
apply map_app in H; now apply app_cons_not_nil in H
| [H: _ ++ [#] = List.map sym (List.rev _ ++ ?e) |- _ ] =>
rewrite map_app in H; let E:= fresh "E" in apply last_app_eq in H as [_ E]; inv E
| [H: ?x ++ [_] = #::(List.map sym ?L) |- _ ] => destruct x eqn: ?
| [H: _ ++ [#] = List.map sym (List.rev ?L) |- _ ] => destruct L eqn: ?
| [H: _ ++ [sym _] = List.map sym (List.rev ?L) |- _ ] => destruct L eqn:?
| [H: _ ++ [sym _] = List.map sym (_ ++ [_]) |- _ ] =>
rewrite map_app in H; apply last_app_eq in H as [? ?]
| [H: ?A ++ _::_ = _::_ |- _ ] => destruct A eqn: ?
end; subst.
Ltac rep_listInv := repeat listInv.
Ltac confeq :=
unfold step; unfold mk_srconf;
match goal with
| [ |- (_::_ = _::_) /\ _ ] => split
| [ |- (_::_ = _::_)] => reflexivity
| [H: ctape _ = _ |- (_ = _) /\ _ ] => rewrite H
| [H: trans(_,_) = _ |- _ ] => rewrite H
| [H: _ |- mk_mconfig _ _ = mk_mconfig _  _ /\ _ ] => split
| [ |- mk_mconfig _ _ = mk_mconfig _ _ ] => reflexivity
| [H: (?q,_) el list_prod not_halting_states _ |- halt ?q = false ] =>
apply in_prod_iff in H as [? _]; now apply not_halting
| [H: _ el not_halting_states |- halt _ = false] => now apply not_halting
end; subst; cbn in *; try now rewrite !map_app, <- !app_assoc.
Ltac rep_confeq := repeat confeq.
Ltac state_inv :=
unfold get_rules_right in *;
match goal with
|[H: ?x ++ ?z::(state ?q)::?y = ?a::(?A++(state _ )::_) |- _] =>
cbn in H; change (x++z::state q::y) with (x++[z]++(state q)::y) in H; rewrite app_assoc in H;
rewrite app_comm_cons in H; eapply state_eqlist in H as [? [? ?]]
|[H: ?x ++ state _ :: ?y = state _ ::_ |- _ = _ /\ _ ] =>
apply state_eqlist with (A:= x) (B:= y) (C:= []) in H as [? [? ?]]
|[H: ?x ++ ?z::state ?q :: ?y = state _ ::_ |- _ = _ /\ _ ] =>
change (x++z::state q::y) with (x++[z]++state q::y) in H; rewrite app_assoc in H;
apply state_eqlist with (A:=x++[z]) (B:= y) (C:= []) in H as [? [? ?]]
|[H: ?x ++(state _ )::?y = ?a::(?A ++ (state _ )::_) |- _ ] =>
cbn in H; rewrite app_comm_cons in H; eapply state_eqlist in H as [? [? ?]]
|[H: (_,_) el List.map _ _ |- (_ = _) /\ _] => apply in_map_iff in H as [? [? ?]]
|[H: (_,_) = (_,_) |- _ ] => inv H
|[H: _ |- exists E F, [] = _ /\ [#;$] = _ ] => exists [],[hash; dollar]; now split
|[H: _ |- exists E F, [] = _ /\ #::sym ?e::List.map sym ?L++[$] = _ ] =>
exists [],(hash::sigma e::List.map sigma L++[dollar]); split; auto; cbn;
rewrite map_app, map_symb_sigma; now cbn
|[H: _ |- exists E F, #::(List.map sym ?A) = _ /\ [$] = _ ] =>
exists (hash::(List.map sigma A)), [dollar]; split; auto; cbn;
rewrite !map_app, map_symb_sigma; now cbn
|[H: _ |- exists E F, #::(List.map sym ?A) = _ /\ sym ?e::(List.map sym ?L)++[$] = _ ] =>
exists (hash::(List.map sigma A)), (sigma e::(List.map sigma L)++[dollar]);
split; cbn; try rewrite map_app; now rewrite map_symb_sigma
end.
Ltac solve_inv := repeat (state_inv || confeq || listInv).

(* Specifications: *)
Lemma rewrite_step_halt (c1: conf) y:
rew' TMrules (mk_srconf c1) y -> (y = (mk_srconf (step c1)) /\ (halt (cstate c1) = false)).
Lemma rewrite_steps_halt (c1: conf) y:
rewt' TMrules (mk_srconf c1) y -> exists c2, y = (mk_srconf c2).
Theorem reach_rewrite (c1 c2:conf):
reach c1 c2 <-> rewt' TMrules (mk_srconf c1) (mk_srconf c2).