Section NFA_NonHalt.
Hypothesis nfa_h0:
forall {i0},
nfa None i0 None = true.
Hypothesis nfa_h:
forall {s0 u0 i0},
tm s0 i0 = None ->
nfa (Some (s0,u0)) i0 None = true.
Hypothesis nfa_r:
forall {s0 u0 i0 s1 i1},
tm s0 i0 = Some {| nxt:= s1; out:=i1; dir:=Dpos |} ->
nfa (Some (s0,u0)) i0 (Some (s1,dfa u0 i1)) = true.
Hypothesis nfa_l:
forall {s0 i0 s1 u1 i1 i2 su2 su3},
tm s0 i0 = Some {| nxt:= s1; out:=i1; dir:=Dneg |} ->
nfa (Some (s1,u1)) i2 su2 = true ->
nfa su2 i1 su3 = true ->
nfa (Some (s0,dfa u1 i2)) i0 su3 = true.
Hypothesis dfa_0:
dfa U0 Σ0 = U0.
Inductive NFA_match: (option (St*U))->Word->Prop :=
| NFA_match_O: NFA_match None nil
| NFA_match_S v0 v1 i w: nfa v0 i v1 = true -> NFA_match v1 w -> NFA_match v0 (i::w)
.
Definition makeES' (l0 r0:Word)(m0:Σ)(s0:St):ExecState Σ :=
(s0,make_tape' half_tape_all0 l0 m0 r0 half_tape_all0).
Fixpoint DFA_match(w:Word):U :=
match w with
| nil => U0
| h::t => dfa (DFA_match t) h
end.
Definition ES_matched(l0 r0:Word)(m0:Σ)(s0:St):Prop :=
exists n0,
NFA_match (Some (s0,DFA_match l0)) ((m0::r0)++(repeat Σ0 n0)).
Hypothesis nfa_acc_0: nfa_acc (Some (St0,U0)) = true.
Hypothesis nfa_acc_h: nfa_acc None = false.
Hypothesis nfa_acc_closed:
forall {su0 su1},
nfa su0 Σ0 su1 = true ->
nfa_acc su0 = true ->
nfa_acc su1 = true.
End NFA_NonHalt.
Definition StU_list :=
concat (map (fun s => map (fun u => (s,u)) U_list) St_list).
Definition oStU_list :=
None::(map Some StU_list).
Definition forallb_U f :=
forallb f U_list.
Definition forallb_oStU f :=
forallb f oStU_list.
Definition nfa_h0_dec:bool :=
forallb_Σ (fun i0 => nfa None i0 None).
Definition nfa_h_dec:bool :=
forallb_St (fun s0 =>
forallb_U (fun u0 =>
forallb_Σ (fun i0 =>
match tm s0 i0 with
| None => nfa (Some (s0,u0)) i0 None
| _ => true
end))).
Definition nfa_r_dec:bool :=
forallb_St (fun s0 =>
forallb_U (fun u0 =>
forallb_Σ (fun i0 =>
match tm s0 i0 with
| Some {| nxt:= s1; out:=i1; dir:=Dpos |} =>
nfa (Some (s0,u0)) i0 (Some (s1,dfa u0 i1))
| _ => true
end))).
Definition nfa_l_dec:bool :=
forallb_St (fun s0 =>
forallb_Σ (fun i0 =>
match tm s0 i0 with
| Some {| nxt:= s1; out:=i1; dir:=Dneg |} =>
forallb_U (fun u1 =>
forallb_Σ (fun i2 =>
forallb_oStU (fun su2 =>
forallb_oStU (fun su3 =>
if nfa (Some (s1,u1)) i2 su2 then
if nfa su2 i1 su3 then nfa (Some (s0,dfa u1 i2)) i0 su3 else true else true
))))
| _ => true
end)).
Definition dfa_0_dec:=
U_eqb (dfa U0 Σ0) U0.
Definition nfa_acc_0_dec:=
nfa_acc (Some (St0,U0)).
Definition nfa_acc_h_dec:=
negb (nfa_acc None).
Definition nfa_acc_closed_dec :=
forallb_oStU (fun su0 =>
forallb_oStU (fun su1 =>
if nfa su0 Σ0 su1 then
if nfa_acc su0 then nfa_acc su1 else true
else true
)).
Definition all_cond_dec :=
nfa_h0_dec &&&
nfa_h_dec &&&
nfa_r_dec &&&
nfa_l_dec &&&
dfa_0_dec &&&
nfa_acc_0_dec &&&
nfa_acc_h_dec &&&
nfa_acc_closed_dec.
End verifyNFA.
Definition pair_enc{T1 T2}(T1_enc:T1->positive)(T2_enc:T2->positive):(T1*T2)->positive :=
fun x =>
let (x1,x2):=x in
enc_pair (T1_enc x1,T2_enc x2).
Definition option_enc{T}(T_enc:T->positive):(option T)->positive :=
fun x =>
match x with
| None => xH
| Some x0 => (Pos.succ (T_enc x0))
end.
Definition StU_enc: (St*U)->positive := pair_enc St_enc U_enc.
Definition oStU := option (St*U).
Definition oStU_enc: oStU->positive := option_enc StU_enc.
Definition nfa_entry := (oStU*Σ*oStU)%type.
Definition nfa_entry_enc := pair_enc (pair_enc oStU_enc Σ_enc) oStU_enc.
Definition nfa_t := PositiveMap.tree unit.
Definition nfa_ins(x:nfa_entry)(s:nfa_t):nfa_t :=
PositiveMap.add (nfa_entry_enc x) tt s.
Definition nfa_at(x:nfa_entry)(s:nfa_t):bool :=
match PositiveMap.find (nfa_entry_enc x) s with
| Some _ => true
| None => false
end.
Definition nfa_ins'(x:nfa_entry)(s:nfa_t*bool):(nfa_t*bool) :=
let (s0,flag):=s in
(nfa_ins x s0,flag&&&nfa_at x s0).
Fixpoint for_loop{T}{S}(f:S->T->S)(ls:list T)(s:S):S :=
match ls with
| nil => s
| h::t => for_loop f t (f s h)
end.
Definition for_Dir{S} f:S->S := for_loop f Dir_list.
Definition for_Σ{S} f:S->S := for_loop f Σ_list.
Definition for_St{S} f:S->S := for_loop f St_list.
Definition for_U{S} f:S->S := for_loop f U_list.
Definition for_oStU{S} f:S->S := for_loop f oStU_list.
Definition nfa_h0_rec:nfa_t->nfa_t :=
for_Σ (fun (s:nfa_t) i0 => nfa_ins ((None,i0,None)) s).
Definition nfa_h_rec:nfa_t->nfa_t :=
for_St (fun s s0 =>
for_U (fun s u0 =>
for_Σ (fun s i0 =>
match tm s0 i0 with
| None => nfa_ins ((Some (s0,u0),i0,None)) s
| _ => s
end
) s) s).
Definition nfa_r_rec:nfa_t->nfa_t :=
for_St (fun s s0 =>
for_Σ (fun s i0 =>
match tm s0 i0 with
| Some {| nxt:= s1; out:=i1; dir:=Dpos |} =>
for_U (fun s u0 => nfa_ins ((Some (s0,u0)),i0,(Some (s1,dfa u0 i1))) s) s
| _ => s
end) s).
Definition nfa_l_rec:(nfa_t*bool)->(nfa_t*bool) :=
for_St (fun s s0 =>
for_Σ (fun s i0 =>
match tm s0 i0 with
| Some {| nxt:= s1; out:=i1; dir:=Dneg |} =>
for_U (fun s u1 =>
for_Σ (fun s i2 =>
for_oStU (fun (s:nfa_t*bool) su2 =>
let (nfa,flag):=s in
if nfa_at (Some (s1,u1),i2,su2) nfa then
for_oStU (fun (s:nfa_t*bool) su3 =>
let (nfa,flag):=s in
if nfa_at (su2,i1,su3) nfa then
nfa_ins' ((Some (s0,dfa u1 i2)),i0,su3) s
else s
) s
else s
) s) s) s
| _ => s
end) s).
Fixpoint do_until0{T}(f:T->(T*bool))(n:nat)(x:T):T :=
match n with
| O => x
| S n0 =>
let (x',flag):=(f x) in
if flag then x' else (do_until0 f n0 x')
end.
Definition do_until{T}(f:T->(T*bool)):T->T :=
do_until0 f maxT.
Definition nfa_rec:nfa_t :=
do_until (fun s => nfa_l_rec (s,true)) (nfa_r_rec (nfa_h_rec (nfa_h0_rec (PositiveMap.empty _)))).
Definition nfa_acc_t := PositiveMap.tree unit.
Definition nfa_acc_ins(x:oStU)(s:nfa_acc_t):nfa_acc_t := PositiveMap.add (oStU_enc x) tt s.
Definition nfa_acc_at(x:oStU)(s:nfa_acc_t):bool :=
match PositiveMap.find (oStU_enc x) s with
| Some _ => true
| None => false
end.
Definition nfa_acc_ins'(x:oStU)(s:nfa_acc_t*bool):(nfa_acc_t*bool) :=
let (s0,flag):=s in
(nfa_acc_ins x s0,flag&&&nfa_acc_at x s0).
Definition nfa_acc_0_rec:nfa_acc_t->nfa_acc_t :=
nfa_acc_ins (Some (St0,U0)).
Definition nfa_acc_closed_rec(nfa:nfa_t):((nfa_acc_t*bool))->((nfa_acc_t*bool)) :=
for_oStU (fun s su0 =>
for_oStU (fun (s:(nfa_acc_t*bool)) su1 =>
let (nfa_acc,flag):=s in
if nfa_at (su0,Σ0,su1) nfa then
if nfa_acc_at su0 nfa_acc then (nfa_acc_ins' su1 (nfa_acc,flag)) else s
else s) s).
Definition nfa_acc_rec(nfa:nfa_t):nfa_acc_t :=
do_until (fun s => nfa_acc_closed_rec nfa (s,true)) (nfa_acc_0_rec (PositiveMap.empty _)).
Definition dfa_nfa_decider :=
let nfa := nfa_rec in
let nfa_acc := nfa_acc_rec nfa in
if all_cond_dec (fun x1 x2 x3 => nfa_at (x1,x2,x3) nfa) (fun x => nfa_acc_at x nfa_acc) then Result_NonHalt
else Result_Unknown.
End genNFA.

Lemma dfa_nfa_decider_spec:
HaltDecider_WF (N.to_nat BB) dfa_nfa_decider.