(* algorithme de calcul d'intersection : calcul de l'état produit *)

(* calcul d'une prec_list produit *)

Fixpoint pl_produit_0 (a : ad) (la pl : prec_list) 
 (n : nat) {struct n} : prec_list -> prec_list :=
  fun l : prec_list =>
  match n with
  | O => prec_empty
  | S m =>
      match pl with
      | prec_empty => l
      | prec_cons a0 la0 ls0 =>
          prec_cons (iad_conv a a0) (pl_produit_1 la m la0)
            (pl_produit_0 a la ls0 m l)
      end
  end
 
 with pl_produit_1 (pl0 : prec_list) (n : nat) {struct n} :
 prec_list -> prec_list :=
  fun pl1 : prec_list =>
  match n with
  | O => prec_empty
  | S m =>
      match pl0, pl1 with
      | prec_empty, prec_empty => prec_empty
      | prec_empty, prec_cons a1 la1 ls1 => prec_empty
      | prec_cons a0 la0 ls0, prec_empty => prec_empty
      | prec_cons a0 la0 ls0, prec_cons a1 la1 ls1 =>
          pl_produit_0 a0 la0 (prec_cons a1 la1 ls1) m
            (pl_produit_1 ls0 m (prec_cons a1 la1 ls1))
      end
  end.Fixpoint pl_card (pl : prec_list) : nat :=
  match pl with
  | prec_empty => 1
  | prec_cons a la ls => S (pl_card la + pl_card ls)
  end.(* terminaison des fonctions précédantes *)

Definition pl_essence (pl0 pl1 : prec_list) : nat :=
  pl_card pl0 + pl_card pl1.Definition pl_produit (pl0 pl1 : prec_list) : prec_list :=
  pl_produit_1 pl0 (pl_essence pl0 pl1) pl1.

(* Specifications: *)
Lemma pl_card_0 : forall pl : prec_list, 1 <= pl_card pl.
Lemma pl_ess_aux_0 : forall pl : prec_list, 1 <= pl_card pl.
Lemma pl_ess_aux_1 : forall (a : ad) (la ls : prec_list), S (pl_card la) <= pl_card (prec_cons a la ls).
Lemma pl_ess_aux_2 : forall (a : ad) (la ls : prec_list), S (pl_card ls) <= pl_card (prec_cons a la ls).
Lemma pl_ess_invar_0 : forall pl0 pl1 : prec_list, 1 <= pl_essence pl0 pl1.
Lemma pl_ess_invar_1 : forall (a a' : ad) (la ls la' ls' : prec_list), S (pl_essence la (prec_cons a' la' ls')) <= pl_essence (prec_cons a la ls) (prec_cons a' la' ls').
Lemma pl_ess_invar_2 : forall (a a' : ad) (la ls la' ls' : prec_list), S (pl_essence ls (prec_cons a' la' ls')) <= pl_essence (prec_cons a la ls) (prec_cons a' la' ls').
Lemma pl_ess_invar_3 : forall (a' : ad) (la la' ls' : prec_list), S (pl_essence la la') <= pl_essence la (prec_cons a' la' ls').
Lemma pl_ess_invar_4 : forall (a' : ad) (la la' ls' : prec_list), S (pl_essence la ls') <= pl_essence la (prec_cons a' la' ls').
Lemma pl_ess_invar_5 : forall pl0 pl1 : prec_list, 2 <= pl_essence pl0 pl1.