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.

Lemma MITM_WDFA_ES_step_spec tm x:
match MITM_WDFA_ES_step tm x with
| Some ls =>
forall st0,
In_MITM_WDFA_ES st0 x ->
exists n st1 x1,
Steps Σ tm (1 + n) st0 st1 /\ In_MITM_WDFA_ES st1 x1 /\ In x1 ls
| None => True
end.