(* preDTA produit *)
Fixpoint preDTA_produit_l (a : ad) (s : state) (d : preDTA) {struct d} :
preDTA :=
match d with
| M0 => M0 state
| M1 a' s' => M1 state (iad_conv a a') (s_produit s s')
| M2 s0 s1 =>
match a with
| N0 =>
M2 state
(M2 state (preDTA_produit_l N0 s s0)
(preDTA_produit_l N0 s s1)) (M0 state)
| Npos p =>
match p with
| xH =>
M2 state (M0 state)
(M2 state (preDTA_produit_l N0 s s0)
(preDTA_produit_l N0 s s1))
| xO p' =>
M2 state
(M2 state (preDTA_produit_l (Npos p') s s0)
(preDTA_produit_l (Npos p') s s1))
(M0 state)
| xI p' =>
M2 state (M0 state)
(M2 state (preDTA_produit_l (Npos p') s s0)
(preDTA_produit_l (Npos p') s s1))
end
end
end.
Fixpoint preDTA_produit_r (a : ad) (s : state) (d : preDTA) {struct d} :
preDTA :=
match d with
| M0 => M0 state
| M1 a' s' => M1 state (iad_conv a' a) (s_produit s' s)
| M2 s0 s1 =>
match a with
| N0 =>
M2 state (M2 state (preDTA_produit_r N0 s s0) (M0 state))
(M2 state (preDTA_produit_r N0 s s1) (M0 state))
| Npos p =>
match p with
| xH =>
M2 state (M2 state (M0 state) (preDTA_produit_r N0 s s0))
(M2 state (M0 state) (preDTA_produit_r N0 s s1))
| xO p' =>
M2 state
(M2 state (preDTA_produit_r (Npos p') s s0) (M0 state))
(M2 state (preDTA_produit_r (Npos p') s s1) (M0 state))
| xI p' =>
M2 state
(M2 state (M0 state) (preDTA_produit_r (Npos p') s s0))
(M2 state (M0 state) (preDTA_produit_r (Npos p') s s1))
end
end
end.
Fixpoint preDTA_produit (d0 d1 : preDTA) {struct d1} : preDTA :=
match d0, d1 with
| M0, M0 => M0 state
| M0, M1 a1 s1 => M0 state
| M0, M2 s10 s11 => M0 state
| M1 a0 s0, M0 => M0 state
| M1 a0 s0, M1 a1 s1 => preDTA_produit_l a0 s0 (M1 state a1 s1)
| M1 a0 s0, M2 s10 s11 => preDTA_produit_l a0 s0 (M2 state s10 s11)
| M2 s00 s01, M0 => M0 state
| M2 s00 s01, M1 a1 s1 => preDTA_produit_r a1 s1 (M2 state s00 s01)
| M2 s00 s01, M2 s10 s11 =>
M2 state (M2 state (preDTA_produit s00 s10) (preDTA_produit s00 s11))
(M2 state (preDTA_produit s01 s10) (preDTA_produit s01 s11))
end.
Definition predta_produit_0d_def (d : preDTA) : Prop :=
forall (a : ad) (s : state) (a0 a1 : ad) (s0 s1 : state),
MapGet state (M1 state a s) a0 = Some s0 ->
MapGet state d a1 = Some s1 ->
MapGet state (preDTA_produit_l a s d) (iad_conv a0 a1) =
Some (s_produit s0 s1).

(* Specifications: *)
Lemma predta_produit_0_0 : predta_produit_0d_def (M0 state).
Lemma predta_produit_0_1 :
forall (a : ad) (a0 : state), predta_produit_0d_def (M1 state a a0).
Lemma predta_produit_0_2 :
forall m : preDTA,
predta_produit_0d_def m ->
forall m0 : preDTA,
predta_produit_0d_def m0 -> predta_produit_0d_def (M2 state m m0).
Lemma predta_produit_0_3 : forall m : preDTA, predta_produit_0d_def m.
Lemma predta_produit_0 :
forall (a : ad) (s : state) (d : preDTA) (a0 a1 : ad) (s0 s1 : state),
MapGet state (M1 state a s) a0 = Some s0 ->
MapGet state d a1 = Some s1 ->
MapGet state (preDTA_produit_l a s d) (iad_conv a0 a1) =
Some (s_produit s0 s1).