Section MITMWFAR_0.
Hypothesis n_l:nat.
Hypothesis n_r:nat.
Definition U_l := nat_n n_l.
Definition U_r := nat_n n_r.
Definition U0_l := nat_n_O n_l.
Definition U0_r := nat_n_O n_r.
Definition U_l_enc := nat_n_enc n_l.
Definition U_r_enc := nat_n_enc n_r.
Definition U_l_enc_inj := nat_n_enc_inj n_l.
Definition U_r_enc_inj := nat_n_enc_inj n_r.
Definition U_l_list := nat_n_list n_l.
Definition U_r_list := nat_n_list n_r.
Hypothesis wdfa_l:U_l->Σ->(U_l*Z).
Hypothesis wdfa_r:U_r->Σ->(U_r*Z).
Hypothesis wdfa_l_0: wdfa_0 U_l U0_l wdfa_l.
Hypothesis wdfa_r_0: wdfa_0 U_r U0_r wdfa_r.
Hypothesis wdfa_sgn_l:Dir->U_l->bool.
Hypothesis wdfa_sgn_r:Dir->U_r->bool.
Hypothesis wdfa_sgn_l_closed: wdfa_sgn_closed U_l wdfa_l wdfa_sgn_l.
Hypothesis wdfa_sgn_r_closed: wdfa_sgn_closed U_r wdfa_r wdfa_sgn_r.
Definition wdfa_sgn_l_spec := wdfa_sgn_spec U_l U0_l wdfa_l wdfa_sgn_l wdfa_sgn_l_closed.
Definition wdfa_sgn_r_spec := wdfa_sgn_spec U_r U0_r wdfa_r wdfa_sgn_r wdfa_sgn_r_closed.
Definition Z_enc(x:Z):positive :=
match x with
| Z0 => xH
| Zpos x0 => xI x0
| Zneg x0 => xO x0
end.
Definition oDir_to_Z(x:option Dir) :=
match x with
| None => Z0
| Some x0 => Dir_to_Z x0
end.
Definition MITM_WDFA_ES := (U_l*U_r*Σ*St*Z*(option Dir))%type.
Definition MITM_WDFA_ES_enc:MITM_WDFA_ES->positive :=
(pair_enc (pair_enc (pair_enc (pair_enc (pair_enc U_l_enc U_r_enc) Σ_enc) St_enc) Z_enc) (option_enc Dir_enc)).
Definition In_MITM_WDFA_ES(es:ExecState Σ)(es1:MITM_WDFA_ES):Prop :=
exists es0:ListES,
es = ListES_toES es0 /\
let (l0,r0,m0,s0):=es0 in
let '(l1,r1,m1,s1,d1,g1):=es1 in
exists (dl:Z) (dr:Z) (c1:N),
(d1+(oDir_to_Z g1)*(Z.of_N c1) = dl+dr)%Z /\
WDFA_match U_l U0_l wdfa_l l0 = (l1,dl) /\
WDFA_match U_r U0_r wdfa_r r0 = (r1,dr) /\
m0 = m1 /\
s0 = s1.
Definition MITM_WDFA_InitES:MITM_WDFA_ES :=
(U0_l,U0_r,Σ0,St0,Z0,None).
Definition MITM_WDFA_ES_good(es:MITM_WDFA_ES):bool :=
let '(l1,r1,m1,s1,d1,g1):=es in
negb (
((d1>?0 &&& (oDir_to_Z g1)>=?0)%Z&&&(wdfa_sgn_l Dneg l1)&&&(wdfa_sgn_r Dneg r1)) |||
((d1<?0 &&& (oDir_to_Z g1)<=?0)%Z&&&(wdfa_sgn_l Dpos l1)&&&(wdfa_sgn_r Dpos r1))).
Hypothesis max_d:Z.
Definition MITM_WDFA_ES_simplify(es:MITM_WDFA_ES):list MITM_WDFA_ES :=
let '(l1,r1,m1,s1,d1,g):=es in
match g with
| None =>
if ((Z.abs d1) >=? max_d)%Z then
match d1 with
| Zpos _ => (l1,r1,m1,s1,d1,Some Dpos)::nil
| Zneg _ => (l1,r1,m1,s1,d1,Some Dneg)::nil
| Z0 => es::nil
end
else es::nil
| Some g0 =>
match ((Z.abs d1) - max_d)%Z with
| Zpos _ => (l1,r1,m1,s1,(d1-(oDir_to_Z g))%Z,g)::nil
| Zneg _ => (l1,r1,m1,s1,d1,None)::(l1,r1,m1,s1,(d1+(oDir_to_Z g))%Z,g)::nil
| Z0 => es::nil
end
end.
Definition MITM_WDFA_ES_filter(ls:list MITM_WDFA_ES):list MITM_WDFA_ES :=
concat (map MITM_WDFA_ES_simplify (filter MITM_WDFA_ES_good ls)).
Definition pop_l := (WDFA_pop U_l U_l_enc U_l_list wdfa_l).
Definition pop_r := (WDFA_pop U_r U_r_enc U_r_list wdfa_r).
Definition MITM_WDFA_ES_step(tm:TM Σ)(es:MITM_WDFA_ES):option (list MITM_WDFA_ES) :=
let '(l1,r1,m1,s1,d1,g1):=es in
match tm s1 m1 with
| None => None
| Some {| nxt:=s2; dir:=d2; out:=m2 |} =>
Some
match d2 with
| Dpos =>
let (l1',dl):=wdfa_l l1 m2 in
MITM_WDFA_ES_filter
(map (fun x => let '(r1',m3,dr):=x in (l1',r1',m3,s2,(d1+dl-dr)%Z,g1)) (pop_r r1))
| Dneg =>
let (r1',dr):=wdfa_r r1 m2 in
MITM_WDFA_ES_filter
(map (fun x => let '(l1',m3,dl):=x in (l1',r1',m3,s2,(d1+dr-dl)%Z,g1)) (pop_l l1))
end
end.
Definition MITM_WDFA_ES_decider0:nat->HaltDecider :=
(T_decider _ MITM_WDFA_ES_enc MITM_WDFA_InitES MITM_WDFA_ES_step).
Definition MITM_WDFA_ES_decider0_spec :=
(T_decider_spec _ _ MITM_WDFA_ES_enc_inj In_MITM_WDFA_ES _ In_MITM_WDFA_InitES _ MITM_WDFA_ES_step_spec).
End MITMWFAR_0.
Definition make_wdfa(f:nat->Σ->(nat*Z))(n:nat)(u:nat_n n)(i:Σ) :=
let (u0,a):=(f (nat_n_to_nat _ u) i) in
(nat_n_from_nat n u0,a).
Definition WDFA_from_list(ls:list(nat*Z*nat*Z))(x:nat)(i:Σ):nat*Z :=
let '(a0,a1,b0,b1) := nth x ls (O,Z0,O,Z0) in
match i with
| Σ0 => (a0,a1)
| Σ1 => (b0,b1)
end.
Definition MITM_WDFA_verifier
(max_d:Z)
(n_l:nat)(wdfa_l:nat->Σ->(nat*Z))
(n_r:nat)(wdfa_r:nat->Σ->(nat*Z))
(n:nat)
(tm:TM Σ):HaltDecideResult :=
let wdfa_l':=make_wdfa wdfa_l n_l in
let wdfa_r':=make_wdfa wdfa_r n_r in
let wdfa_sgn_l:=wdfa_sgn_rec (nat_n n_l) (nat_n_enc n_l) (nat_n_list n_l) n wdfa_l' in
let wdfa_sgn_r:=wdfa_sgn_rec (nat_n n_r) (nat_n_enc n_r) (nat_n_list n_r) n wdfa_r' in
if
(wdfa_0_dec (nat_n n_l) (nat_n_O n_l) (nat_n_enc n_l) wdfa_l') &&&
(wdfa_0_dec (nat_n n_r) (nat_n_O n_r) (nat_n_enc n_r) wdfa_r') &&&
(wdfa_sgn_closed_dec (nat_n n_l) (nat_n_enc n_l) (nat_n_list n_l) wdfa_l' wdfa_sgn_l) &&&
(wdfa_sgn_closed_dec (nat_n n_r) (nat_n_enc n_r) (nat_n_list n_r) wdfa_r' wdfa_sgn_r)
then
MITM_WDFA_ES_decider0 n_l n_r wdfa_l' wdfa_r' wdfa_sgn_l wdfa_sgn_r max_d n tm
else
Result_Unknown.

Lemma MITM_WDFA_verifier_spec max_d n_l wdfa_l n_r wdfa_r n:
HaltDecider_WF (N.to_nat BB) (MITM_WDFA_verifier max_d n_l wdfa_l n_r wdfa_r n).