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)).

Lemma MITM_WDFA_ES_filter_spec es es0 ls:
In_MITM_WDFA_ES es0 es ->
In es ls ->
exists es', In_MITM_WDFA_ES es0 es' /\ In es' (MITM_WDFA_ES_filter ls).