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