(*  Pour un chemin de la forme (cons x w) il existe un etat 		*)
(*  intermediaire.							*)

(*---
Lemma chemin_A2_cons_inv : (q,dA:Ensf)(w:Word)(e1,e2,x:Elt)
  (chemin_A2 q dA (cons x w) e2 e1) -> (<Elt>Ex ([e:Elt](
     (chemin_A2 q dA (cons x nil) e e1) /\ (chemin_A2 q dA w e2 e)
  ))).
Intros.
Elim H.
Intros.
Cut (Chemin e0 e2 q dA (cons x w)); Auto.
Intro.
Cut (<Elt> Ex ([e:Elt]
      	  (chemin e e2 q dA w) /\ (dans e0 q) /\ (dans x alph)
   	  /\ (dans (couple e0 (couple x e)) dA)) ); Auto.
Intro Ht; Elim Ht; Clear Ht.
Intros e Ht; Elim Ht; Clear Ht.
Intros H3 Ht; Elim Ht; Clear Ht.
Intros H4 Ht; Elim Ht; Clear Ht.
Intros H5 H6.
Exists e.
Split.
2:Apply chemin_A2_un; Auto.
2:Apply (inmonoid_cons_inv alph w x); Auto.
Cut (chemin e0 e q dA (cons x nil)); Auto.
Apply (chemin_cons e e q dA nil e0 x); Auto.
Apply chemin_nil; Auto.
Apply (dans_e1_q q dA w e e2); Auto.

Intros.
Elim H1.
Intros e0' Ht; Elim Ht; Clear Ht. 
Intros H4 H5.
Exists e0'.
Split; Auto.
Apply chemin_A2_deux with e; Auto.
Save.

Lemma chemin_A_cons_inv : (q,dA:Ensf)(w:Word)(e1,e2,x:Elt)
  (chemin_A e1 e2 q dA (cons x w)) -> (<Elt>Ex ([e:Elt](
     (chemin_A e1 e q dA (cons x nil)) /\ (chemin_A e e2 q dA w)
  ))).
Goal.
Cut (<Elt>Ex ([e:Elt](
     (chemin_A2 q dA (cons x nil) e e1) /\ (chemin_A2 q dA w e2 e)
  ))).
2:Apply chemin_A2_cons_inv; Auto.
Intro Ht; Elim Ht; Clear Ht.
Intros e Ht; Elim Ht; Clear Ht.
Intros H0 H1.
Exists e.
Auto.
Save.
---*)

(*  De meme on definit reconnait_A...  					*)

Definition reconnait_A (q qd qa d : Ensf) (w : Word) : Prop :=
  inmonoid alph w /\
  (exists e1 : Elt,
     (exists e2 : Elt, dans e1 qd /\ dans e2 qa /\ chemin_A q d e1 e2 w)).(*  									*)
(*  A partir d'une relation de transition asynchrone dA construisons	*)
(*  la relation synchrone d correspondante. On elimine les transitions	*)
(*  avec epsilon en disant :						*)
(*     dans (e,a,e') d  <->  (chemin_A e e' q dA (cons a nil))		*)
(*									*)

Definition est_dans_d2 (q dA : Ensf) (e y : Elt) : Prop :=
  match y return Prop with
  | natural n =>
      (* natural *)  False
      (* couple  *) 
  | couple a e' => chemin_A q dA e e' (cons a nil)
      (* up      *) 
  | up e => False
      (* word    *) 
  | word w => False
  end.Definition est_dans_d (q dA : Ensf) (x : Elt) : Prop :=
  match x return Prop with
  | natural n =>
      (* natural *)  False
      (* couple  *) 
  | couple e y => est_dans_d2 q dA e y
      (* up      *) 
  | up e => False
      (* word    *) 
  | word w => False
  end.Definition sync_d (q dA : Ensf) : Ensf :=
  tq (est_dans_d q dA) (prodcart q (prodcart alph q)).Definition sync_qa (q qaA dA : Ensf) : Ensf :=
  union qaA
    (tq
       (fun e : Elt => exists e' : Elt, dans e' qaA /\ chemin_A q dA e e' nil)
       q).

(* Specifications: *)
Lemma inclus_qaA_qa : forall q qaA dA : Ensf, inclus qaA (sync_qa q qaA dA).
Lemma nouvx_dans_qa : forall (q qaA dA : Ensf) (e : Elt), dans e q -> (exists e' : Elt, dans e' qaA /\ chemin_A q dA e e' nil) -> dans e (sync_qa q qaA dA).
Lemma sync_d_def : forall (e1 e2 x : Elt) (q dA : Ensf), dans x alph -> chemin_A q dA e1 e2 (cons x nil) -> dans (couple e1 (couple x e2)) (sync_d q dA).
Lemma sync_d_def2 : forall (e1 e2 x : Elt) (q dA : Ensf), dans x alph -> dans (couple e1 (couple x e2)) (sync_d q dA) -> chemin_A q dA e1 e2 (cons x nil).
Lemma trans_dA_d : forall (q dA : Ensf) (e0 e x : Elt), dans e0 q -> dans x alph -> dans e q -> dans (couple e0 (couple x e)) dA -> dans (couple e0 (couple x e)) (sync_d q dA).
Lemma automateA_automate : forall q qd qaA dA : Ensf, automate_A q qd qaA dA -> automate q qd (sync_qa q qaA dA) (sync_d q dA).
Lemma epsilon_chemin : forall (q qaA dA : Ensf) (w : Word) (e1 e e2 : Elt), chemin e e2 q (sync_d q dA) w -> dans (couple e1 (couple epsilon e)) dA -> dans e2 (sync_qa q qaA dA) -> dans e1 q -> exists e2' : Elt, chemin e1 e2' q (sync_d q dA) w /\ dans e2' (sync_qa q qaA dA).
Lemma cheminA_chemin : forall q qd qaA dA : Ensf, automate_A q qd qaA dA -> forall (w : Word) (e1 e2 : Elt), chemin_A q dA e1 e2 w -> dans e2 qaA -> exists e2' : Elt, chemin e1 e2' q (sync_d q dA) w /\ dans e2' (sync_qa q qaA dA).
Lemma reconnaitA_reconnait : forall (q qd qaA dA : Ensf) (w : Word), automate_A q qd qaA dA -> reconnait_A q qd qaA dA w -> reconnait q qd (sync_qa q qaA dA) (sync_d q dA) w.
Lemma chemin_cheminA : forall q qd qaA dA : Ensf, automate_A q qd qaA dA -> forall (w : Word) (e1 e2 : Elt), chemin e1 e2 q (sync_d q dA) w -> chemin_A q dA e1 e2 w.
Lemma reconnait_reconnaitA : forall (q qd qaA dA : Ensf) (w : Word), automate_A q qd qaA dA -> reconnait q qd (sync_qa q qaA dA) (sync_d q dA) w -> reconnait_A q qd qaA dA w.
Lemma async_is_sync : forall q qd qaA dA : Ensf, automate_A q qd qaA dA -> exists d : Ensf, (exists qa : Ensf, automate q qd qa d /\ eqwordset (reconnait_A q qd qaA dA) (reconnait q qd qa d)).
Lemma Recislang : forall q qd qa d : Ensf, automate q qd qa d -> islanguage alph (reconnait q qd qa d).