Section WDFA_sgn.
Hypothesis wdfa_sgn: Dir->U->bool.
Definition wdfa_sgn_closed:=
forall d0 u0,
wdfa_sgn d0 u0 = true ->
forall u1 i0 d1,
wdfa u1 i0 = (u0,d1) ->
((d1*(Dir_to_Z d0)>=0)%Z /\
wdfa_sgn d0 u1 = true).
Definition wdfa_sgn_closed_dec :=
forallb_Dir (fun d0 =>
forallb_U (fun u0 =>
if wdfa_sgn d0 u0 then
forallb_U (fun u1 =>
forallb_Σ (fun i0 =>
let (u0',d1) := wdfa u1 i0 in
if U_eqb u0' u0 then
(d1*(Dir_to_Z d0) >=? 0)%Z &&&
wdfa_sgn d0 u1
else true))
else true)).
End WDFA_sgn.
Definition wdfa_sgn_t := PositiveMap.tree unit.
Definition wdfa_sgn_ins(x:U)(s:wdfa_sgn_t):wdfa_sgn_t :=
PositiveMap.add (U_enc x) tt s.
Definition wdfa_sgn_at(x:U)(s:wdfa_sgn_t):bool :=
match PositiveMap.find (U_enc x) s with
| Some _ => true
| None => false
end.
Definition wdfa_sgn_ins'(x:U)(s:wdfa_sgn_t*bool):(wdfa_sgn_t*bool) :=
let (s0,flag):=s in
(wdfa_sgn_ins x s0,flag&&&wdfa_sgn_at x s0).
Definition wdfa_sgn_rec0(d0:Dir) :=
for_U (fun s u0 =>
for_Σ (fun s i0 =>
let (u1,d1):=wdfa u0 i0 in
if (d1*(Dir_to_Z d0)>=?0)%Z &&& (negb (wdfa_sgn_at u0 (fst s))) then s
else wdfa_sgn_ins' u1 s) s).
Definition wdfa_sgn_rec1(d0:Dir) :=
do_until (fun s => wdfa_sgn_rec0 d0 (s,true)) (PositiveMap.empty _).
Definition wdfa_sgn_rec: Dir->U->bool :=
let spos := wdfa_sgn_rec1 Dpos in
let sneg := wdfa_sgn_rec1 Dneg in
fun d0 =>
match d0 with
| Dpos => fun u0 => negb (wdfa_sgn_at u0 spos)
| Dneg => fun u0 => negb (wdfa_sgn_at u0 sneg)
end.
End WDFA.
End dfa_nfa_decider.
Inductive nat_n:nat->Set :=
| nat_n_O n: nat_n n
| nat_n_S n: nat_n n -> nat_n (S n)
.
Fixpoint nat_n_list(n:nat):list (nat_n n).
destruct n as [|n0].
- apply ((nat_n_O O)::nil).
- apply ((nat_n_O (S n0))::(map (fun x => nat_n_S n0 x) (nat_n_list n0))).
Defined.
Fixpoint nat_n_to_nat(n:nat)(x:nat_n n):nat.
destruct x as [|x0].
- apply O.
- apply (S (nat_n_to_nat x0 x)).
Defined.
Fixpoint nat_n_from_nat(n:nat)(x:nat):nat_n n.
destruct x as [|x0].
- apply nat_n_O.
- destruct n as [|n0].
+ apply nat_n_O.
+ apply nat_n_S.
apply (nat_n_from_nat n0 x0).
Defined.
Definition nat_n_enc(n:nat)(x:nat_n n):positive := Pos.of_succ_nat (nat_n_to_nat n x).
Definition make_dfa(f:nat->Σ->nat)(n:nat)(u:nat_n n)(i:Σ) :=
nat_n_from_nat n (f (nat_n_to_nat _ u) i).
Definition dfa_nfa_verifier(n:nat)(f:nat->Σ->nat):HaltDecider :=
fun tm => (dfa_nfa_decider (nat_n n) (nat_n_O n) (nat_n_enc n) (nat_n_list n) 1000000 (make_dfa f n) tm).

Lemma dfa_nfa_verifier_spec n f:
HaltDecider_WF (N.to_nat BB) (dfa_nfa_verifier n f).