(* This program is free software; you can redistribute it and/or      *)
(* modify it under the terms of the GNU Lesser General Public License *)
(* as published by the Free Software Foundation; either version 2.1   *)
(* of the License, or (at your option) any later version.             *)
(*                                                                    *)
(* This program is distributed in the hope that it will be useful,    *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of     *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *)
(* GNU General Public License for more details.                       *)
(*                                                                    *)
(* You should have received a copy of the GNU Lesser General Public   *)
(* License along with this program; if not, write to the Free         *)
(* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *)
(* 02110-1301 USA                                                     *)


(** In this file, we prove properties about hedges.
    These properties are in section 6.1 of the paper
    "On Bisimulations for the Spi-Calculus" by J. Borgström
    and U. Nestmann.
    However, we consider here an extended message language. *)

(** Author: Sébastien Briais (sebastien.briais@epfl.ch) *)

Unset Standard Proposition Elimination Names.

(** We assume to have a (countably infinite) set of names. *)
Hypothesis Nam : Set.

(** We define three operators for building messages. *)
Inductive op : Set :=
  | Pub : op
  | Priv : op
  | Hash : op.

(** Equality of operators is decidable. *)
Lemma op_eq_dec : forall o1 o2 : op, {o1 = o2} + {o1 <> o2}.
simple destruct o1; simple destruct o2; try auto;
 try (right; red in |- *; intro; inversion H).
Qed.

(** The inversion of an operator. *)
Definition inv_op (o : op) : op :=
  match o with
  | Pub => Priv
  | Priv => Pub
  | _ => o
  end.

(** A message is either a name, or an encrypted message, 
    or a pair of messages, or an operator applied to a message. *)
Inductive Msg : Set :=
  | MNam : Nam -> Msg
  | MEnc : Msg -> Msg -> Msg
  | MPair : Msg -> Msg -> Msg
  | Mop : op -> Msg -> Msg.

(** Inversion of a message. This is to manage public/private keys. *)
Definition inv (M : Msg) : Msg :=
  match M with
  | Mop op M => Mop (inv_op op) M
  | _ => M
  end.

(** The inversion is involutive. *)
Lemma inv_invol : forall M : Msg, inv (inv M) = M.
(* Goal: forall M : Msg, @eq Msg (inv (inv M)) M *)
simple induction M; simpl in |- *; trivial.
(* Goal: forall (o : op) (m : Msg) (_ : @eq Msg (inv (inv m)) m), @eq Msg (Mop (inv_op (inv_op o)) m) (Mop o m) *)
simple destruct o; simpl in |- *; trivial.
Qed.

(** A hedge is a set of pairs of message. *)
Definition hedge := Msg -> Msg -> Prop.

Require Import Classical_Prop.

(** In classical logic, it is possible to say if (M,N) is in h or not. *)
Lemma hedge_mem_dec : forall (h : hedge) (M N : Msg), h M N \/ ~ h M N.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (h M N) (not (h M N)) *)
apply (classic (h M N)).
Qed.

(** g is included in h iff whenever (M,N) is in g then (M,N) is in h *)
Definition inclusion (g h : hedge) := forall M N : Msg, g M N -> h M N.

(** g = h iff g is included in h and h is included in g *)
Definition equal (g h : hedge) := inclusion g h /\ inclusion h g.

(** inclusion is reflexive, ... *)
Lemma inclusion_refl : forall h : hedge, inclusion h h.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: le_h g h *)
trivial.
Qed.

(** ...transitive, ... *)
Lemma inclusion_trans :
 forall f g h : hedge, inclusion f g -> inclusion g h -> inclusion f h.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (reduce g) m2 m0 *)
(* Goal: forall (m m0 : Msg) (_ : h (MPair m m0) N) (_ : and (g (MPair m m0) N) match N with | MNam n => True | MEnc m1 m2 => True | MPair N1 N2 => or (not (synthesis g m N1)) (not (synthesis g m0 N2)) | Mop o m1 => True end), and (h (MPair m m0) N) match N with | MNam n => True | MEnc m1 m2 => True | MPair N1 N2 => or (not (synthesis h m N1)) (not (synthesis h m0 N2)) | Mop o m1 => True end *)
(* Goal: forall (o : op) (m : Msg) (_ : h (Mop o m) N) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
apply H0.
(* Goal: le_h g h *)
apply H; trivial.
Qed.

(** ...and antisymmetric: inclusion is an order! *)
Lemma inclusion_antisym :
 forall f g : hedge, inclusion f g -> inclusion g f -> equal f g.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** equality is reflexive, ... *)
Lemma equal_refl : forall h : hedge, equal h h.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: and (inclusion h h) (inclusion h h) *)
split; apply inclusion_refl.
Qed.

(** ...symmetric, ... *)
Lemma equal_sym : forall g h : hedge, equal g h -> equal h g.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** ...and transitive: equality is an equivalence relation! *)
Lemma equal_trans : forall f g h : hedge, equal f g -> equal g h -> equal f h.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
elim H0.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
split; apply inclusion_trans with g; trivial.
Qed.

(** union and intersection of hedges *)
Definition union (g h : hedge) (M N : Msg) := g M N \/ h M N.
Definition inter (g h : hedge) (M N : Msg) := g M N /\ h M N.

(** union is symmetric *)
Lemma union_sym : forall g h : hedge, equal (union g h) (union h g).
(* Goal: inclusion (inter g h) (union g h) *)
unfold union in |- *.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** intersection is symmetric *)
Lemma inter_sym : forall g h : hedge, equal (inter g h) (inter h g).
(* Goal: inclusion (inter g h) (fun M N : Msg => or (g M N) (h M N)) *)
unfold inter in |- *.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** g is included in the union of g and h *)
Lemma hedge_left_union : forall g h : hedge, inclusion g (union g h).
(* Goal: inclusion (inter g h) (union g h) *)
unfold union in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** h is included in the union of g and h *)
Lemma hedge_right_union : forall g h : hedge, inclusion h (union g h).
(* Goal: inclusion (inter g h) (union g h) *)
unfold union in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** the intersection of g and h is included in g *)
Lemma inter_hedge_left : forall g h : hedge, inclusion (inter g h) g.
(* Goal: inclusion (inter g h) (fun M N : Msg => or (g M N) (h M N)) *)
unfold inter in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** the intersection of g and h is included in h *)
Lemma inter_hedge_right : forall g h : hedge, inclusion (inter g h) h.
(* Goal: inclusion (inter g h) (fun M N : Msg => or (g M N) (h M N)) *)
unfold inter in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** if f is included in h and g is included in h then 
    the union of f and g is included in h *)
Lemma union_intro :
 forall f g h : hedge,
 inclusion f h -> inclusion g h -> inclusion (union f g) h.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: inclusion (inter g h) (union g h) *)
unfold union in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: h M N *)
case H1.
(* Goal: inclusion (synthesis (synthesis h)) (synthesis h) *)
apply H.
(* Goal: synthesis (reduce g) m2 m0 *)
(* Goal: forall (m m0 : Msg) (_ : h (MPair m m0) N) (_ : and (g (MPair m m0) N) match N with | MNam n => True | MEnc m1 m2 => True | MPair N1 N2 => or (not (synthesis g m N1)) (not (synthesis g m0 N2)) | Mop o m1 => True end), and (h (MPair m m0) N) match N with | MNam n => True | MEnc m1 m2 => True | MPair N1 N2 => or (not (synthesis h m N1)) (not (synthesis h m0 N2)) | Mop o m1 => True end *)
(* Goal: forall (o : op) (m : Msg) (_ : h (Mop o m) N) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
apply H0.
Qed.

(** the intersection of g and h is included into the union of g and h *)
Lemma inter_inclusion_union :
 forall g h : hedge, inclusion (inter g h) (union g h).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (inter g h) (union g h) *)
unfold union in |- *.
(* Goal: inclusion (inter g h) (fun M N : Msg => or (g M N) (h M N)) *)
unfold inter in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** The synthesis S(h) of h : it contains all the messages
    that can be synthetised by the hedge. *)
Inductive synthesis (h : hedge) : hedge :=
  | SynInc : forall M N : Msg, h M N -> synthesis h M N
  | SynEnc :
      forall M N K L : Msg,
      synthesis h M N -> synthesis h K L -> synthesis h (MEnc M K) (MEnc N L)
  | SynPair :
      forall M1 N1 M2 N2 : Msg,
      synthesis h M1 N1 ->
      synthesis h M2 N2 -> synthesis h (MPair M1 M2) (MPair N1 N2)
  | SynOp :
      forall (o : op) (M N : Msg),
      synthesis h M N -> synthesis h (Mop o M) (Mop o N).

(** If (M,N) is in S(h) and M is a name then (M,N) is in h *)
Theorem nam_left_syn :
 forall (h : hedge) (a : Nam) (N : Msg),
 synthesis h (MNam a) N -> h (MNam a) N.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg (Mop o0 N0) (Mop (inv_op o) N) *)
inversion H.
(* Goal: le_h g h *)
trivial.
Qed.

(** If (M,N) is in S(h) and N is a name then (M,N) is in h *)
Theorem nam_right_syn :
 forall (h : hedge) (M : Msg) (b : Nam),
 synthesis h M (MNam b) -> h M (MNam b).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg (Mop o0 N0) (Mop (inv_op o) N) *)
inversion H.
(* Goal: le_h g h *)
trivial.
Qed.

(** h is included in S(h) *)
Lemma h_incl_syn : forall h : hedge, inclusion h (synthesis h).
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: le_h g h *)
trivial.
Qed.

(** g <= h if S(g) is included in S(h) *)
Definition le_h (g h : hedge) := inclusion (synthesis g) (synthesis h).

(** g ~ h if g <= h and h <= g *)
Definition equiv_h (g h : hedge) := le_h g h /\ le_h h g.

(** <= is reflexive, ... *)
Lemma le_h_refl : forall h : hedge, le_h h h.
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion (synthesis h) (synthesis h) *)
apply inclusion_refl.
Qed.

(** ... transitive, ... *)
Lemma le_h_trans : forall f g h : hedge, le_h f g -> le_h g h -> le_h f h.
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
apply inclusion_trans with (synthesis g); trivial.
Qed.

(** and 'antysymmetric' for ~ *)
Lemma le_h_antisym : forall g h : hedge, le_h g h -> le_h h g -> equiv_h g h.
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** ~ is reflexive, ... *)
Lemma equiv_refl : forall h : hedge, equiv_h h h.
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: and (le_h h h) (le_h h h) *)
split; apply le_h_refl.
Qed.

(** ...transitive, ... *)
Lemma equiv_h_trans :
 forall f g h : hedge, equiv_h f g -> equiv_h g h -> equiv_h f h.
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
elim H0.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
split; apply le_h_trans with g; trivial.
Qed.

(** ...and symmetric. *)
Lemma equiv_h_sym : forall g h : hedge, equiv_h g h -> equiv_h h g.
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** if g <= h then g is included in S(h) *)
Lemma le_h_impl_incl_syn :
 forall g h : hedge, le_h g h -> inclusion g (synthesis h).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
apply inclusion_trans with (synthesis g); trivial.
(* Goal: inclusion h (synthesis h) *)
apply h_incl_syn.
Qed.

(** if g is included in S(h) then g <= h *)
Lemma incl_syn_impl_le_h :
 forall g h : hedge, inclusion g (synthesis h) -> le_h g h.
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
induction  H0
 as
  [M
   N
   H0|
   M
   N
   K
   L
   H0_1
   HrecH0_1
   H0_0
   HrecH0_0|
   M1
   N1
   M2
   N2
   H0_1
   HrecH0_1
   H0_0
   HrecH0_0|
   o
   M
   N
   H0
   HrecH0].
(* Goal: le_h g h *)
apply H; trivial.
(* Goal: le_h g h *)
apply SynEnc; trivial.
(* Goal: le_h g h *)
apply SynPair; trivial.
(* Goal: le_h g h *)
apply SynOp; trivial.
Qed.

(** g <= h iff g is included in S(h) *)
Theorem le_h_iff_incl_syn :
 forall g h : hedge, le_h g h <-> inclusion g (synthesis h).
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: inclusion g (synthesis h) *)
(* Goal: inclusion (transpose (synthesis h)) (synthesis (transpose h)) *)
apply le_h_impl_incl_syn.
(* Goal: le_h (transpose g) (transpose h) *)
apply incl_syn_impl_le_h.
Qed.

(** if g is included in h then g <= h *)
Theorem inclusion_impl_le_h : forall g h : hedge, inclusion g h -> le_h g h.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h (transpose g) (transpose h) *)
apply incl_syn_impl_le_h.
(* Goal: le_h g h *)
apply inclusion_trans with h; trivial.
(* Goal: inclusion h (synthesis h) *)
apply h_incl_syn.
Qed.

(** if g = h then g ~ h *)
Lemma equal_impl_equiv_h : forall g h : hedge, equal g h -> equiv_h g h.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: le_h g h *)
apply inclusion_impl_le_h; trivial.
(* Goal: le_h g h *)
apply inclusion_impl_le_h; trivial.
Qed.

(** if f <= h and g <= h then (union f g) <= h *)
Theorem le_h_le_h_impl_union_le_h :
 forall f g h : hedge, le_h f h -> le_h g h -> le_h (union f g) h.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h (transpose g) (transpose h) *)
apply incl_syn_impl_le_h.
(* Goal: le_h g h *)
apply union_intro; apply le_h_impl_incl_syn; trivial.
Qed.

(** if g1 <= h1 and g2 <= h2 then (union g1 g2) <= (union h1 h2) *)
Theorem le_h_le_h_impl_le_h_union :
 forall g1 g2 h1 h2 : hedge,
 le_h g1 h1 -> le_h g2 h2 -> le_h (union g1 g2) (union h1 h2).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h (union (irreducible h) g) (irreducible (union h g)) *)
(* Goal: le_h (irreducible (irreducible (union h g))) (irreducible (union h g)) *)
(* Goal: le_h (irreducible (union h g)) (irreducible (union (irreducible h) g)) *)
apply le_h_le_h_impl_union_le_h.
(* Goal: le_h g h *)
apply le_h_trans with h1; trivial.
(* Goal: le_h h1 (union h1 h2) *)
(* Goal: le_h g2 (union h1 h2) *)
apply inclusion_impl_le_h; apply hedge_left_union.
(* Goal: le_h g h *)
apply le_h_trans with h2; trivial.
(* Goal: le_h h2 (union h1 h2) *)
apply inclusion_impl_le_h; apply hedge_right_union.
Qed.

(** we define how to analyse 'one time' a hedge h:
    all the pairs are splitted and the encrypted messages
    are decrypted if the keys are in the synthesis of h *)
Inductive analysis (h : hedge) : hedge :=
  | AnaInc : forall M N : Msg, h M N -> analysis h M N
  | AnaSplitL :
      forall M1 M2 N1 N2 : Msg,
      analysis h (MPair M1 M2) (MPair N1 N2) -> analysis h M1 N1
  | AnaSplitR :
      forall M1 M2 N1 N2 : Msg,
      analysis h (MPair M1 M2) (MPair N1 N2) -> analysis h M2 N2
  | AnaDec :
      forall M N K L : Msg,
      analysis h (MEnc M K) (MEnc N L) ->
      synthesis h (inv K) (inv L) -> analysis h M N.

(** if g is included in h then (analysis g) is included in (analysis h) *)
Lemma inclusion_analysis_inclusion :
 forall g h : hedge, inclusion g h -> inclusion (analysis g) (analysis h).
(* Goal: forall (g h : hedge) (_ : inclusion g h), inclusion (analysis g) (analysis h) *)
intros g h.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
induction  H0
 as
  [M N H0| M1 M2 N1 N2 H0 HrecH0| M1 M2 N1 N2 H0 HrecH0| M N K L H0 HrecH0 H1].
(* Goal: analysis h M N *)
apply AnaInc.
(* Goal: le_h g h *)
apply H; trivial.
(* Goal: analysis h M1 N1 *)
(* Goal: analysis h M2 N2 *)
(* Goal: analysis h M N *)
apply (AnaSplitL h M1 M2 N1 N2).
(* Goal: le_h g h *)
trivial.
(* Goal: analysis h M2 N2 *)
(* Goal: analysis h M N *)
apply (AnaSplitR h M1 M2 N1 N2).
(* Goal: le_h g h *)
trivial.
(* Goal: analysis h M N *)
apply (AnaDec h M N K L).
(* Goal: le_h g h *)
trivial.
(* Goal: synthesis h (inv K) (inv L) *)
generalize (inclusion_impl_le_h g h H).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
Qed.

(** We define an infinite sequence (analysis_seq h n) where the n-th term
    is the n-th analysis of h *)
Fixpoint analysis_seq (h : hedge) (n : nat) {struct n} : hedge :=
  match n with
  | O => h
  | S n => analysis (analysis_seq h n)
  end.

Require Import Arith.

(** the n-th analysis of h is included in the (n+1)-th analysis of h *)
Lemma analysis_seq_grow_S :
 forall (n : nat) (h : hedge),
 inclusion (analysis_seq h n) (analysis_seq h (S n)).
(* Goal: forall (n : nat) (h : hedge), inclusion (analysis_seq h n) (analysis_seq h (S n)) *)
simple induction n.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
apply AnaInc; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis h M N *)
apply AnaInc.
(* Goal: le_h g h *)
trivial.
Qed.

(** the n-th analysis of h is included in the (n+p)-th analysis of h *)
Lemma analysis_seq_grows :
 forall (p n : nat) (h : hedge),
 inclusion (analysis_seq h n) (analysis_seq h (p + n)).
(* Goal: forall (p n : nat) (h : hedge), inclusion (analysis_seq h n) (analysis_seq h (Init.Nat.add p n)) *)
simple induction p.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (synthesis h) (synthesis h) *)
apply inclusion_refl.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_seq h n0) (analysis_seq h (Init.Nat.add (S n) n0)) *)
replace (S n + n0) with (S (n + n0)); try auto with arith.
(* Goal: le_h g h *)
apply inclusion_trans with (analysis_seq h (n + n0)); trivial.
(* Goal: inclusion (analysis_seq h (Init.Nat.add n n0)) (analysis_seq h (S (Init.Nat.add n n0))) *)
apply analysis_seq_grow_S.
Qed.

(** if n <= m then 
    the n-th analysis of h is included in the m-th analysis of h *)
Lemma analysis_seq_increase :
 forall (n m : nat) (h : hedge),
 n <= m -> inclusion (analysis_seq h n) (analysis_seq h m).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_seq h n) (analysis_seq h m) *)
cut (exists p : nat, m = p + n).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
elim H0.
(* Goal: forall (x : nat) (_ : @eq nat m (Init.Nat.add x n)), inclusion (analysis_seq h n) (analysis_seq h m) *)
(* Goal: @ex nat (fun p : nat => @eq nat m (Init.Nat.add p n)) *)
intro p.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion (analysis_seq h n) (analysis_seq h m) *)
(* Goal: @ex nat (fun p : nat => @eq nat m (Init.Nat.add p n)) *)
rewrite H1.
(* Goal: inclusion (analysis_seq h O) (analysis_seq h (Init.Nat.add n O)) *)
(* Goal: forall (h' : hedge) (_ : and (inclusion h h') (stable_analysis h')), inclusion (analysis_seq h n) h' *)
apply analysis_seq_grows.
(* Goal: @ex nat (fun p : nat => @eq nat m (Init.Nat.add p n)) *)
exists (m - n).
(* Goal: @eq nat m (Init.Nat.add (Init.Nat.sub m n) n) *)
rewrite plus_comm.
(* Goal: @eq nat m (Nat.add n (Init.Nat.sub m n)) *)
apply le_plus_minus.
(* Goal: le_h g h *)
trivial.
Qed.

(** reduce remove from h all the redundancy: a pair (M,N) is kept
   in (reduce h) iff it cannot be 'strictly' synthetised by h *)
Definition reduce (h : hedge) (M N : Msg) :=
  h M N /\
  match M with
  | MEnc M' K =>
      match N with
      | MEnc N' L => ~ synthesis h M' N' \/ ~ synthesis h K L
      | _ => True
      end
  | MPair M1 M2 =>
      match N with
      | MPair N1 N2 => ~ synthesis h M1 N1 \/ ~ synthesis h M2 N2
      | _ => True
      end
  | Mop opM M' =>
      match N with
      | Mop opN N' => opM <> opN \/ ~ synthesis h M' N'
      | _ => True
      end
  | _ => True
  end.

(** (reduce h) is included in h *)
Lemma red_incl_h : forall h : hedge, inclusion (reduce h) h.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall _ : reduce h N M, reduce (fun M N : Msg => h N M) M N *)
unfold reduce in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** h <= (reduce h) *)
Lemma h_le_h_red : forall h : hedge, le_h h (reduce h).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall (M N : Msg) (_ : synthesis h M N), synthesis (reduce h) M N *)
simple induction M.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: @eq Msg (Mop o0 N0) (Mop (inv_op o) N) *)
inversion H.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: forall (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (m0 : Msg) (_ : forall (N : Msg) (_ : synthesis h m0 N), synthesis (reduce h) m0 N) (N : Msg) (_ : synthesis h (MEnc m m0) N), synthesis (reduce h) (MEnc m m0) N *)
(* Goal: forall (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (m0 : Msg) (_ : forall (N : Msg) (_ : synthesis h m0 N), synthesis (reduce h) m0 N) (N : Msg) (_ : synthesis h (MPair m m0) N), synthesis (reduce h) (MPair m m0) N *)
(* Goal: forall (o : op) (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (Mop o m) N), synthesis (reduce h) (Mop o m) N *)
intro M'.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (MEnc M' m) N), synthesis (reduce h) (MEnc M' m) N *)
(* Goal: forall (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (m0 : Msg) (_ : forall (N : Msg) (_ : synthesis h m0 N), synthesis (reduce h) m0 N) (N : Msg) (_ : synthesis h (MPair m m0) N), synthesis (reduce h) (MPair m m0) N *)
(* Goal: forall (o : op) (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (Mop o m) N), synthesis (reduce h) (Mop o m) N *)
intro K.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall (N : Msg) (_ : synthesis h (Mop oM M') N), synthesis (reduce h) (Mop oM M') N *)
simple destruct N.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: and (h (MEnc M' K) (MEnc N' L)) (or (not (synthesis h M' N')) (not (synthesis h K L))) *)
(* Goal: forall _ : not (synthesis h M' N'), synthesis (reduce h) (MEnc M' K) (MEnc N' L) *)
(* Goal: forall (m m0 : Msg) (_ : synthesis h (MEnc M' K) (MPair m m0)), synthesis (reduce h) (MEnc M' K) (MPair m m0) *)
(* Goal: forall (o : op) (m : Msg) (_ : synthesis h (MEnc M' K) (Mop o m)), synthesis (reduce h) (MEnc M' K) (Mop o m) *)
(* Goal: forall (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (m0 : Msg) (_ : forall (N : Msg) (_ : synthesis h m0 N), synthesis (reduce h) m0 N) (N : Msg) (_ : synthesis h (MPair m m0) N), synthesis (reduce h) (MPair m m0) N *)
(* Goal: forall (o : op) (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (Mop o m) N), synthesis (reduce h) (Mop o m) N *)
inversion H1.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: forall (m m0 : Msg) (_ : synthesis h (MEnc M' K) (MEnc m m0)), synthesis (reduce h) (MEnc M' K) (MEnc m m0) *)
(* Goal: forall (m m0 : Msg) (_ : synthesis h (MEnc M' K) (MPair m m0)), synthesis (reduce h) (MEnc M' K) (MPair m m0) *)
(* Goal: forall (o : op) (m : Msg) (_ : synthesis h (MEnc M' K) (Mop o m)), synthesis (reduce h) (MEnc M' K) (Mop o m) *)
(* Goal: forall (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (m0 : Msg) (_ : forall (N : Msg) (_ : synthesis h m0 N), synthesis (reduce h) m0 N) (N : Msg) (_ : synthesis h (MPair m m0) N), synthesis (reduce h) (MPair m m0) N *)
(* Goal: forall (o : op) (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (Mop o m) N), synthesis (reduce h) (Mop o m) N *)
intros N' L.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (reduce h) (Mop oN M') (Mop oN N') *)
(* Goal: forall _ : not (@eq op oM oN), synthesis (reduce h) (Mop oM M') (Mop oN N') *)
case (hedge_mem_dec (synthesis h) M' N').
(* Goal: forall _ : synthesis h M' N', synthesis (reduce h) (MEnc M' K) (MEnc N' L) *)
(* Goal: forall _ : not (synthesis h M' N'), synthesis (reduce h) (MEnc M' K) (MEnc N' L) *)
(* Goal: forall (m m0 : Msg) (_ : synthesis h (MEnc M' K) (MPair m m0)), synthesis (reduce h) (MEnc M' K) (MPair m m0) *)
(* Goal: forall (o : op) (m : Msg) (_ : synthesis h (MEnc M' K) (Mop o m)), synthesis (reduce h) (MEnc M' K) (Mop o m) *)
(* Goal: forall (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (m0 : Msg) (_ : forall (N : Msg) (_ : synthesis h m0 N), synthesis (reduce h) m0 N) (N : Msg) (_ : synthesis h (MPair m m0) N), synthesis (reduce h) (MPair m m0) N *)
(* Goal: forall (o : op) (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (Mop o m) N), synthesis (reduce h) (Mop o m) N *)
case (hedge_mem_dec (synthesis h) K L).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_seq h (Nat.max n1 n2)) (MEnc M K) (MEnc N L) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (MPair M1 M2) (MPair N1 N2)) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (Mop o M) (Mop o N)) *)
apply SynEnc.
(* Goal: le_h g h *)
apply H; trivial.
(* Goal: le_h g h *)
apply H0; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: and (h (MEnc M' K) (MEnc N' L)) (or (not (synthesis h M' N')) (not (synthesis h K L))) *)
(* Goal: forall _ : not (synthesis h M' N'), synthesis (reduce h) (MEnc M' K) (MEnc N' L) *)
(* Goal: forall (m m0 : Msg) (_ : synthesis h (MEnc M' K) (MPair m m0)), synthesis (reduce h) (MEnc M' K) (MPair m m0) *)
(* Goal: forall (o : op) (m : Msg) (_ : synthesis h (MEnc M' K) (Mop o m)), synthesis (reduce h) (MEnc M' K) (Mop o m) *)
(* Goal: forall (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (m0 : Msg) (_ : forall (N : Msg) (_ : synthesis h m0 N), synthesis (reduce h) m0 N) (N : Msg) (_ : synthesis h (MPair m m0) N), synthesis (reduce h) (MPair m m0) N *)
(* Goal: forall (o : op) (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (Mop o m) N), synthesis (reduce h) (Mop o m) N *)
inversion H1.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
split; tauto.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H1; tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H1; tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H1; tauto.
(* Goal: forall (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (m0 : Msg) (_ : forall (N : Msg) (_ : synthesis h m0 N), synthesis (reduce h) m0 N) (N : Msg) (_ : synthesis h (MPair m m0) N), synthesis (reduce h) (MPair m m0) N *)
(* Goal: forall (o : op) (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (Mop o m) N), synthesis (reduce h) (Mop o m) N *)
intro M1.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (MPair M1 m) N), synthesis (reduce h) (MPair M1 m) N *)
(* Goal: forall (o : op) (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (Mop o m) N), synthesis (reduce h) (Mop o m) N *)
intro M2.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall (N : Msg) (_ : synthesis h (Mop oM M') N), synthesis (reduce h) (Mop oM M') N *)
simple destruct N.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H1; tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H1; tauto.
(* Goal: forall (m m0 : Msg) (_ : synthesis h (MPair M1 M2) (MPair m m0)), synthesis (reduce h) (MPair M1 M2) (MPair m m0) *)
(* Goal: forall (o : op) (m : Msg) (_ : synthesis h (MPair M1 M2) (Mop o m)), synthesis (reduce h) (MPair M1 M2) (Mop o m) *)
(* Goal: forall (o : op) (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (Mop o m) N), synthesis (reduce h) (Mop o m) N *)
intros N1 N2.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis (reduce h) (MPair M1 M2) (MPair N1 N2) *)
(* Goal: forall (o : op) (m : Msg) (_ : synthesis h (MPair M1 M2) (Mop o m)), synthesis (reduce h) (MPair M1 M2) (Mop o m) *)
(* Goal: forall (o : op) (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (Mop o m) N), synthesis (reduce h) (Mop o m) N *)
case (hedge_mem_dec (synthesis h) M1 N1).
(* Goal: forall _ : synthesis h M1 N1, synthesis (reduce h) (MPair M1 M2) (MPair N1 N2) *)
(* Goal: forall _ : not (synthesis h M1 N1), synthesis (reduce h) (MPair M1 M2) (MPair N1 N2) *)
(* Goal: forall (o : op) (m : Msg) (_ : synthesis h (MPair M1 M2) (Mop o m)), synthesis (reduce h) (MPair M1 M2) (Mop o m) *)
(* Goal: forall (o : op) (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (Mop o m) N), synthesis (reduce h) (Mop o m) N *)
case (hedge_mem_dec (synthesis h) M2 N2).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_seq h (Nat.max n1 n2)) (MPair M1 M2) (MPair N1 N2) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (Mop o M) (Mop o N)) *)
apply SynPair.
(* Goal: le_h g h *)
apply H; trivial.
(* Goal: le_h g h *)
apply H0; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H1; tauto.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H1; tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H1; tauto.
(* Goal: forall (o : op) (m : Msg) (_ : forall (N : Msg) (_ : synthesis h m N), synthesis (reduce h) m N) (N : Msg) (_ : synthesis h (Mop o m) N), synthesis (reduce h) (Mop o m) N *)
intros oM M'.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall (N : Msg) (_ : synthesis h (Mop oM M') N), synthesis (reduce h) (Mop oM M') N *)
simple destruct N.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H0; tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H0; tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H0; tauto.
(* Goal: forall (o : op) (m : Msg) (_ : synthesis h (Mop oM M') (Mop o m)), synthesis (reduce h) (Mop oM M') (Mop o m) *)
intros oN N'.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis (reduce h) (Mop oM M') (Mop oN N') *)
case (op_eq_dec oM oN).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: not (synthesis h m0 m) *)
(* Goal: forall _ : not (@eq op o0 o), or (not (@eq op o0 o)) (not (synthesis h m0 m)) *)
rewrite e in H0.
(* Goal: h (Mop o0 m0) (Mop o m) *)
(* Goal: forall _ : not (@eq op o0 o), h (Mop o0 m0) (Mop o m) *)
rewrite e.
(* Goal: synthesis (reduce h) (Mop oN M') (Mop oN N') *)
(* Goal: forall _ : not (@eq op oM oN), synthesis (reduce h) (Mop oM M') (Mop oN N') *)
case (hedge_mem_dec (synthesis h) M' N').
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis (analysis_seq h n) (Mop o M) (Mop o N) *)
apply SynOp.
(* Goal: le_h g h *)
apply H; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
unfold reduce in |- *; simpl in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H0; tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: forall _ : reduce h N M, reduce (fun M N : Msg => h N M) M N *)
unfold reduce in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
inversion H0; tauto.
Qed.

(** (reduce h) ~ h *)
Lemma h_equiv_h_red : forall h : hedge, equiv_h h (reduce h).
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: le_h h (reduce h) *)
apply h_le_h_red.
(* Goal: le_h (irreducible h) h *)
apply inclusion_impl_le_h.
(* Goal: inclusion (reduce (analysis_def h)) (analysis_def h) *)
(* Goal: stable_analysis (analysis_def h) *)
apply red_incl_h.
Qed.

(** if g is included in h and h <= g 
    then (reduce g) is included in (reduce h) *)
Lemma inclusion_le_h_reduce_inclusion :
 forall g h : hedge,
 inclusion g h -> le_h h g -> inclusion (reduce g) (reduce h).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall _ : reduce h N M, reduce (fun M N : Msg => h N M) M N *)
unfold reduce in |- *.
(* Goal: forall (g h : hedge) (_ : forall (M N : Msg) (_ : g M N), h M N) (_ : forall (M N : Msg) (_ : synthesis h M N), synthesis g M N) (M N : Msg) (_ : and (g M N) match M with | MNam n => True | MEnc M' K => match N with | MNam n => True | MEnc N' L => or (not (synthesis g M' N')) (not (synthesis g K L)) | MPair m m0 => True | Mop o m => True end | MPair M1 M2 => match N with | MNam n => True | MEnc m m0 => True | MPair N1 N2 => or (not (synthesis g M1 N1)) (not (synthesis g M2 N2)) | Mop o m => True end | Mop opM M' => match N with | MNam n => True | MEnc m m0 => True | MPair m m0 => True | Mop opN N' => or (not (@eq op opM opN)) (not (synthesis g M' N')) end end), and (h M N) match M with | MNam n => True | MEnc M' K => match N with | MNam n => True | MEnc N' L => or (not (synthesis h M' N')) (not (synthesis h K L)) | MPair m m0 => True | Mop o m => True end | MPair M1 M2 => match N with | MNam n => True | MEnc m m0 => True | MPair N1 N2 => or (not (synthesis h M1 N1)) (not (synthesis h M2 N2)) | Mop o m => True end | Mop opM M' => match N with | MNam n => True | MEnc m m0 => True | MPair m m0 => True | Mop opN N' => or (not (@eq op opM opN)) (not (synthesis h M' N')) end end *)
intros g h H H0.
(* Goal: forall (M N : Msg) (_ : analysis h N M), analysis (fun M0 N0 : Msg => h N0 M0) M N *)
intros M N.
(* Goal: forall (_ : and (g M N) match M with | MNam n => True | MEnc M' K => match N with | MNam n => True | MEnc N' L => or (not (synthesis g M' N')) (not (synthesis g K L)) | MPair m m0 => True | Mop o m => True end | MPair M1 M2 => match N with | MNam n => True | MEnc m m0 => True | MPair N1 N2 => or (not (synthesis g M1 N1)) (not (synthesis g M2 N2)) | Mop o m => True end | Mop opM M' => match N with | MNam n => True | MEnc m m0 => True | MPair m m0 => True | Mop opN N' => or (not (@eq op opM opN)) (not (synthesis g M' N')) end end) (_ : synthesis h M N), h M N *)
case M.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
elim H1; auto.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
case N; intros; elim H1; auto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
split; auto.
(* Goal: or (not (synthesis h m1 m)) (not (synthesis h m2 m0)) *)
(* Goal: forall (o : op) (m : Msg) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
case H3.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
intro; left; red in |- *; intro; apply H4; auto.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
intro; right; red in |- *; intro; apply H4; auto.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
case N; intros; elim H1; auto.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
split; auto.
(* Goal: or (not (synthesis h m1 m)) (not (synthesis h m2 m0)) *)
(* Goal: forall (o : op) (m : Msg) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
case H3.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
intro; left; red in |- *; intro; apply H4; auto.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
intro; right; red in |- *; intro; apply H4; auto.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
case N; intros; elim H1; auto.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
split; auto.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case H3; try tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
right; red in |- *; intro; apply H4; auto.
Qed.

Lemma equal_reduce_equal :
 forall g h : hedge, equal g h -> equal (reduce g) (reduce h).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: inclusion (reduce (analysis_def (reduce (analysis_def h)))) (reduce (analysis_def h)) *)
apply inclusion_le_h_reduce_inclusion.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
apply inclusion_impl_le_h; tauto.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
apply inclusion_le_h_reduce_inclusion; try tauto.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
apply inclusion_impl_le_h; tauto.
Qed.

(** if (reduce g) is included in h and h <= (reduce g) 
    then (reduce g) is included in (reduce h) *)
Lemma inclusion_le_h_impl_inclusion_red :
 forall g h : hedge,
 inclusion (reduce g) h ->
 le_h h (reduce g) -> inclusion (reduce g) (reduce h).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: match N with | MNam n => True | MEnc M' K => match M with | MNam n => True | MEnc N' L => or (not (synthesis h M' N')) (not (synthesis h K L)) | MPair m m0 => True | Mop o m => True end | MPair M1 M2 => match M with | MNam n => True | MEnc m m0 => True | MPair N1 N2 => or (not (synthesis h M1 N1)) (not (synthesis h M2 N2)) | Mop o m => True end | Mop opM M' => match M with | MNam n => True | MEnc m m0 => True | MPair m m0 => True | Mop opN N' => or (not (@eq op opM opN)) (not (synthesis h M' N')) end end *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
generalize H1.
(* Goal: forall _ : reduce g M N, reduce h M N *)
generalize (H M N H1).
(* Goal: forall _ : reduce h N M, reduce (fun M N : Msg => h N M) M N *)
unfold reduce in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case M; try tauto.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case N; try tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
elim H3.
(* Goal: le_h g h *)
split; trivial.
(* Goal: or (not (synthesis h m1 m)) (not (synthesis h m2 m0)) *)
(* Goal: forall (o : op) (m : Msg) (_ : h (Mop o m) N) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
case H5.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall _ : not (synthesis h m1 m), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall _ : not (synthesis h m2 m0), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis h m0 m))), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
left.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: False *)
apply H6.
(* Goal: synthesis g m0 m *)
generalize (inclusion_impl_le_h (reduce g) g (red_incl_h g)).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (irreducible h) M N *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
apply H8.
(* Goal: synthesis (reduce g) m2 m0 *)
(* Goal: forall (m m0 : Msg) (_ : h (MPair m m0) N) (_ : and (g (MPair m m0) N) match N with | MNam n => True | MEnc m1 m2 => True | MPair N1 N2 => or (not (synthesis g m N1)) (not (synthesis g m0 N2)) | Mop o m1 => True end), and (h (MPair m m0) N) match N with | MNam n => True | MEnc m1 m2 => True | MPair N1 N2 => or (not (synthesis h m N1)) (not (synthesis h m0 N2)) | Mop o m1 => True end *)
(* Goal: forall (o : op) (m : Msg) (_ : h (Mop o m) N) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
apply H0.
(* Goal: le_h g h *)
trivial.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
right; red in |- *; intro; apply H6.
(* Goal: synthesis g m0 m *)
generalize (inclusion_impl_le_h (reduce g) g (red_incl_h g)).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (irreducible h) M N *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
apply H8.
(* Goal: synthesis (reduce g) m2 m0 *)
(* Goal: forall (m m0 : Msg) (_ : h (MPair m m0) N) (_ : and (g (MPair m m0) N) match N with | MNam n => True | MEnc m1 m2 => True | MPair N1 N2 => or (not (synthesis g m N1)) (not (synthesis g m0 N2)) | Mop o m1 => True end), and (h (MPair m m0) N) match N with | MNam n => True | MEnc m1 m2 => True | MPair N1 N2 => or (not (synthesis h m N1)) (not (synthesis h m0 N2)) | Mop o m1 => True end *)
(* Goal: forall (o : op) (m : Msg) (_ : h (Mop o m) N) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
apply H0.
(* Goal: le_h g h *)
trivial.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case N; try tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
split; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
elim H3; intros.
(* Goal: or (not (synthesis h m1 m)) (not (synthesis h m2 m0)) *)
(* Goal: forall (o : op) (m : Msg) (_ : h (Mop o m) N) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
case H5.
(* Goal: False *)
left; red in |- *; intro; apply H6.
(* Goal: synthesis g m0 m *)
generalize (inclusion_impl_le_h (reduce g) g (red_incl_h g)).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold inclusion in |- *; auto.
(* Goal: False *)
right; red in |- *; intro; apply H6.
(* Goal: synthesis g m0 m *)
generalize (inclusion_impl_le_h (reduce g) g (red_incl_h g)).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold inclusion in |- *; auto.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case N; try tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
split; trivial.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
elim H3.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case H5; try tauto.
(* Goal: forall _ : not (synthesis h m0 m), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
right.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: False *)
apply H6.
(* Goal: synthesis g m0 m *)
generalize (inclusion_impl_le_h (reduce g) g (red_incl_h g)).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold inclusion in |- *; auto.
Qed.

(** reduce is idempotent *)
Lemma reduce_idempotent :
 forall h : hedge, equal (reduce h) (reduce (reduce h)).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion (reduce (analysis_def h)) (analysis_def h) *)
(* Goal: stable_analysis (analysis_def h) *)
split; try apply red_incl_h.
(* Goal: inclusion (reduce (analysis_def h)) (reduce (analysis_def (reduce (analysis_def h)))) *)
apply inclusion_le_h_impl_inclusion_red.
(* Goal: inclusion (synthesis h) (synthesis h) *)
apply inclusion_refl.
(* Goal: le_h g g *)
apply le_h_refl.
Qed.

(** if (reduce g) ~ h then (reduce g) is included in h *)
Lemma red_equiv_impl_red_incl :
 forall g h : hedge, equiv_h (reduce g) h -> inclusion (reduce g) h.
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: h M N *)
generalize (le_h_impl_incl_syn (reduce g) h H1).
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: h M N *)
generalize (H3 M N H0).
(* Goal: forall _ : synthesis h M N, h M N *)
generalize H0.
(* Goal: forall _ : reduce h N M, reduce (fun M N : Msg => h N M) M N *)
unfold reduce in |- *.
(* Goal: forall (_ : and (g M N) match M with | MNam n => True | MEnc M' K => match N with | MNam n => True | MEnc N' L => or (not (synthesis g M' N')) (not (synthesis g K L)) | MPair m m0 => True | Mop o m => True end | MPair M1 M2 => match N with | MNam n => True | MEnc m m0 => True | MPair N1 N2 => or (not (synthesis g M1 N1)) (not (synthesis g M2 N2)) | Mop o m => True end | Mop opM M' => match N with | MNam n => True | MEnc m m0 => True | MPair m m0 => True | Mop opN N' => or (not (@eq op opM opN)) (not (synthesis g M' N')) end end) (_ : synthesis h M N), h M N *)
case M.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
apply nam_left_syn; trivial.
(* Goal: forall (o : op) (m : Msg) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end) (_ : synthesis h (Mop o m) N), h (Mop o m) N *)
case N.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
apply nam_right_syn; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
elim H4.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg (Mop o N) (Mop o0 N0) *)
inversion H5.
(* Goal: le_h g h *)
trivial.
(* Goal: h (Mop o m0) (Mop o m) *)
(* Goal: forall _ : not (@eq op o0 o), h (Mop o0 m0) (Mop o m) *)
case H7.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
cut False; try tauto.
(* Goal: False *)
(* Goal: forall (o : op) (m m0 m1 : Msg) (_ : and (g (MPair m0 m1) (Mop o m)) True) (_ : synthesis h (MPair m0 m1) (Mop o m)), h (MPair m0 m1) (Mop o m) *)
(* Goal: forall (o : op) (m : Msg) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end) (_ : synthesis h (Mop o m) N), h (Mop o m) N *)
apply H14.
generalize
 (le_h_trans h (reduce g) g H2
    (inclusion_impl_le_h (reduce g) g (red_incl_h g))).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
cut False; try tauto.
(* Goal: False *)
(* Goal: forall (o : op) (m m0 m1 : Msg) (_ : and (g (MPair m0 m1) (Mop o m)) True) (_ : synthesis h (MPair m0 m1) (Mop o m)), h (MPair m0 m1) (Mop o m) *)
(* Goal: forall (o : op) (m : Msg) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end) (_ : synthesis h (Mop o m) N), h (Mop o m) N *)
apply H14.
generalize
 (le_h_trans h (reduce g) g H2
    (inclusion_impl_le_h (reduce g) g (red_incl_h g))).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
inversion H5; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
inversion H5; trivial.
(* Goal: forall (o : op) (m : Msg) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end) (_ : synthesis h (Mop o m) N), h (Mop o m) N *)
case N.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
inversion H5; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
inversion H5; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
inversion H5; trivial.
(* Goal: analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
elim H4.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: h (MPair m1 m2) (MPair m m0) *)
(* Goal: forall (o : op) (m m0 m1 : Msg) (_ : and (g (MPair m0 m1) (Mop o m)) True) (_ : synthesis h (MPair m0 m1) (Mop o m)), h (MPair m0 m1) (Mop o m) *)
(* Goal: forall (o : op) (m : Msg) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end) (_ : synthesis h (Mop o m) N), h (Mop o m) N *)
case H13.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N1 N2) N *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MEnc M K), @eq Msg (MPair N1 N2) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MPair M0 M3), @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
cut False.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: False *)
(* Goal: forall (o : op) (m m0 m1 : Msg) (_ : and (g (MPair m0 m1) (Mop o m)) True) (_ : synthesis h (MPair m0 m1) (Mop o m)), h (MPair m0 m1) (Mop o m) *)
(* Goal: forall (o : op) (m : Msg) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end) (_ : synthesis h (Mop o m) N), h (Mop o m) N *)
apply H14.
generalize
 (le_h_trans h (reduce g) g H2
    (inclusion_impl_le_h (reduce g) g (red_incl_h g))).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
cut False; try tauto.
(* Goal: False *)
(* Goal: forall (o : op) (m m0 m1 : Msg) (_ : and (g (MPair m0 m1) (Mop o m)) True) (_ : synthesis h (MPair m0 m1) (Mop o m)), h (MPair m0 m1) (Mop o m) *)
(* Goal: forall (o : op) (m : Msg) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end) (_ : synthesis h (Mop o m) N), h (Mop o m) N *)
apply H14.
generalize
 (le_h_trans h (reduce g) g H2
    (inclusion_impl_le_h (reduce g) g (red_incl_h g))).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold inclusion in |- *; auto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
inversion H5; trivial.
(* Goal: forall (o : op) (m : Msg) (_ : and (g (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis g m N')) end) (_ : synthesis h (Mop o m) N), h (Mop o m) N *)
case N.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
inversion H5; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
inversion H5; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
inversion H5; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
elim H4.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (@eq op o0 o)) (not (synthesis h m0 m)) *)
case (op_eq_dec o0 o).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: h (Mop o0 m0) (Mop o m) *)
(* Goal: forall _ : not (@eq op o0 o), h (Mop o0 m0) (Mop o m) *)
rewrite e.
(* Goal: h (Mop o m0) (Mop o m) *)
(* Goal: forall _ : not (@eq op o0 o), h (Mop o0 m0) (Mop o m) *)
rewrite e in H5.
(* Goal: le_h g h *)
inversion H5; trivial.
(* Goal: h (Mop o m0) (Mop o m) *)
(* Goal: forall _ : not (@eq op o0 o), h (Mop o0 m0) (Mop o m) *)
case H7.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
cut False; try tauto.
(* Goal: False *)
(* Goal: forall _ : not (@eq op o0 o), h (Mop o0 m0) (Mop o m) *)
apply H12.
generalize
 (le_h_trans h (reduce g) g H2
    (inclusion_impl_le_h (reduce g) g (red_incl_h g))).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: le_h g h *)
inversion H5; trivial.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** if g <= h then (reduce g) <= (reduce h) *)
Lemma red_stable_le_h :
 forall g h : hedge, le_h g h -> le_h (reduce g) (reduce h).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h (reduce g) (reduce h) *)
apply le_h_trans with h.
(* Goal: le_h g h *)
apply le_h_trans with g; trivial.
(* Goal: le_h (irreducible h) h *)
apply inclusion_impl_le_h.
(* Goal: inclusion (reduce (analysis_def h)) (analysis_def h) *)
(* Goal: stable_analysis (analysis_def h) *)
apply red_incl_h.
(* Goal: le_h h (reduce h) *)
apply h_le_h_red.
Qed.

(** h is stable under analysis iff (analysis h) is included in h *)
Definition stable_analysis (h : hedge) := inclusion (analysis h) h.

(** if h is stable under analysis then h = (analysis h) (i.e. h is analysed) *)
Lemma stable_closed :
 forall h : hedge, stable_analysis h -> equal h (analysis h).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall (h : hedge) (_ : stable_analysis h), stable_analysis (transpose h) *)
unfold stable_analysis in |- *.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: le_h g h *)
split; trivial.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis h M N *)
apply AnaInc.
(* Goal: le_h g h *)
trivial.
Qed.

(** if h is stable under analysis then (analysis h) is stable under analysis *)
Lemma stable_impl_ana_stable :
 forall h : hedge, stable_analysis h -> stable_analysis (analysis h).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (h : hedge) (_ : stable_analysis h), stable_analysis (transpose h) *)
unfold stable_analysis in |- *.
(* Goal: inclusion (analysis (analysis h)) (analysis h) *)
apply inclusion_analysis_inclusion.
(* Goal: le_h g h *)
unfold stable_analysis in H; trivial.
Qed.

(** if the n-th analysis of h is stable under analysis 
    then so are the (n+p)-th analysis of h *)
Lemma stable_ana_stable :
 forall (h : hedge) (n : nat),
 stable_analysis (analysis_seq h n) ->
 forall p : nat, stable_analysis (analysis_seq h (p + n)).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
induction  p as [| p Hrecp].
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: le_h g h *)
trivial.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: stable_analysis (analysis (analysis_seq h (Init.Nat.add p n))) *)
apply stable_impl_ana_stable.
(* Goal: le_h g h *)
trivial.
Qed.

(** if the n-th analysis of h is stable under analysis
    then all the following analysis are equal to the n-th analysis *)
Lemma stable_ana_const :
 forall (h : hedge) (n : nat),
 stable_analysis (analysis_seq h n) ->
 forall p : nat, equal (analysis_seq h n) (analysis_seq h (p + n)).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
induction  p as [| p Hrecp].
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: equal (analysis_seq h n) (analysis_seq h n) *)
(* Goal: equal (analysis_seq h n) (analysis_seq h (Init.Nat.add (S p) n)) *)
apply equal_refl.
(* Goal: equal (analysis_seq h n) (analysis_seq h (Init.Nat.add (S p) n)) *)
apply equal_trans with (analysis_seq h (p + n)).
(* Goal: le_h g h *)
trivial.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: equal (analysis_seq h (Init.Nat.add p n)) (analysis (analysis_seq h (Init.Nat.add p n))) *)
apply stable_closed.
(* Goal: stable_analysis (analysis_seq h (Init.Nat.add p n)) *)
apply stable_ana_stable.
(* Goal: le_h g h *)
trivial.
Qed.

(** h could be an analysis of g iff g is included in h and
    h is stable under analysis *)
Definition analysis_cond (g h : hedge) := inclusion g h /\ stable_analysis h.

(** if h could be an analysis of g then 
    h contains the n-th analysis of g for all n *)
Lemma analysis_seq_incl_analysis_cond :
 forall g h : hedge,
 analysis_cond g h -> forall n : nat, inclusion (analysis_seq g n) h.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
induction  n as [| n Hrecn].
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: inclusion h (analysis_def h) *)
unfold analysis_cond in H.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: inclusion (analysis (analysis_seq g n)) h *)
generalize (inclusion_analysis_inclusion (analysis_seq g n) h Hrecn).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: le_h g h *)
apply inclusion_trans with (analysis h); trivial.
(* Goal: inclusion h (analysis_def h) *)
unfold analysis_cond in H.
(* Goal: inclusion (analysis h) h *)
unfold stable_analysis in H.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** h is an analysis of g if h could be an analysis of g and 
   if for all other candidates h' which could be an analysis of g, 
   h is included in h' *)
Definition is_analysis (g h : hedge) :=
  analysis_cond g h /\
  (forall h' : hedge, analysis_cond g h' -> inclusion h h').

(** if h is an analysis of g 
    then h contains the n-th analysis of g for all n *)
Lemma analysis_seq_incl_analysis :
 forall g h : hedge,
 is_analysis g h -> forall n : nat, inclusion (analysis_seq g n) h.
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_seq h n) h' *)
apply analysis_seq_incl_analysis_cond.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** if h is an analysis of g and h' is an analysis of g
    then h = h' (and so h is the analysis of g) *)
Lemma analysis_unique :
 forall g h h' : hedge, is_analysis g h -> is_analysis g h' -> equal h h'.
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
elim H0.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: le_h g h *)
apply H4; trivial.
(* Goal: le_h g h *)
apply H2; trivial.
Qed.

(** if h is the analysis of g and h' is the analysis of h
    then h' is the analysis of g *)
Lemma analysis_trans :
 forall g h h' : hedge,
 is_analysis g h -> is_analysis h h' -> is_analysis g h'.
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
elim H0.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: transpose h M N *)
elim H1.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
elim H3.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: le_h g h *)
split; trivial.
(* Goal: le_h g h *)
apply inclusion_trans with h; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion h' h'0 *)
apply inclusion_trans with h.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
apply H2.
(* Goal: le_h g h *)
split; trivial.
(* Goal: inclusion (synthesis h) (synthesis h) *)
apply inclusion_refl.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
apply H4; tauto.
Qed.

(** if h is the analysis of g and h' is the analysis of h
    then h = h' *)
Lemma analysis_analysed :
 forall g h h' : hedge, is_analysis g h -> is_analysis h h' -> equal h h'.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
apply analysis_unique with g; trivial.
(* Goal: le_h g h *)
apply analysis_trans with h; trivial.
Qed.

(** if the n-th analysis of h is stable under analysis
    then the n-th analysis of h is the analysis of h *)
Lemma analysis_seq_approx_analysis :
 forall (h : hedge) (n : nat),
 stable_analysis (analysis_seq h n) -> is_analysis h (analysis_seq h n).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: le_h g h *)
split; trivial.
(* Goal: inclusion h (analysis_seq h n) *)
(* Goal: forall (h' : hedge) (_ : and (inclusion h h') (stable_analysis h')), inclusion (analysis_seq h n) h' *)
apply inclusion_trans with (analysis_seq h 0).
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: inclusion (synthesis h) (synthesis h) *)
apply inclusion_refl.
(* Goal: inclusion (analysis_seq h O) (analysis_seq h n) *)
(* Goal: forall (h' : hedge) (_ : and (inclusion h h') (stable_analysis h')), inclusion (analysis_seq h n) h' *)
replace n with (n + 0); try auto with arith.
(* Goal: inclusion (analysis_seq h O) (analysis_seq h (Init.Nat.add n O)) *)
(* Goal: forall (h' : hedge) (_ : and (inclusion h h') (stable_analysis h')), inclusion (analysis_seq h n) h' *)
apply analysis_seq_grows.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_seq h n) h' *)
apply analysis_seq_incl_analysis_cond.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: le_h g h *)
trivial.
Qed.

(** we define the analysis A(h) of h as being 
    the infinite union of the sequence (analysis_seq h) *)
Definition analysis_def (h : hedge) (M N : Msg) :=
  exists n : nat, analysis_seq h n M N.

Require Import Max.

(** technical lemma required to show that the analysis of h
    is indeed the analysis of h *)
Lemma synthesis_analysis_seq :
 forall (h : hedge) (M N : Msg),
 synthesis (analysis_def h) M N ->
 exists n : nat, synthesis (analysis_seq h n) M N.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (M N : Msg) (_ : analysis_def h M N), h' M N *)
unfold analysis_def in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
induction  H
 as
  [M
   N
   H|
   M
   N
   K
   L
   H1
   HrecH1
   H0
   HrecH0|
   M1
   N1
   M2
   N2
   H1
   HrecH1
   H0
   HrecH0|
   o
   M
   N
   H
   HrecH].
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (x : nat) (_ : analysis_seq h x M N), h' M N *)
intro n.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (Mop o M) (Mop o N)) *)
exists n.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: le_h g h *)
trivial.
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (MEnc M K) (MEnc N L)) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (MPair M1 M2) (MPair N1 N2)) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (Mop o M) (Mop o N)) *)
elim HrecH1.
(* Goal: forall (x : nat) (_ : analysis_seq h x (MEnc M K) (MEnc N L)), @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
intro n1.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (MEnc M K) (MEnc N L)) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (MPair M1 M2) (MPair N1 N2)) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (Mop o M) (Mop o N)) *)
elim HrecH0.
(* Goal: forall (x : nat) (_ : synthesis (analysis_seq h x) (inv K) (inv L)), @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
intro n2.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (MPair M1 M2) (MPair N1 N2)) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (Mop o M) (Mop o N)) *)
exists (max n1 n2).
(* Goal: synthesis (analysis_seq h (Nat.max n1 n2)) (MEnc M K) (MEnc N L) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (MPair M1 M2) (MPair N1 N2)) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (Mop o M) (Mop o N)) *)
apply SynEnc.
generalize
 (inclusion_impl_le_h (analysis_seq h n1) (analysis_seq h (max n1 n2))
    (analysis_seq_increase n1 (max n1 n2) h (le_max_l n1 n2))).
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold le_h in |- *; auto.
generalize
 (inclusion_impl_le_h (analysis_seq h n2) (analysis_seq h (max n1 n2))
    (analysis_seq_increase n2 (max n1 n2) h (le_max_r n1 n2))).
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold le_h in |- *; auto.
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (MEnc M K) (MEnc N L)) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (MPair M1 M2) (MPair N1 N2)) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (Mop o M) (Mop o N)) *)
elim HrecH0; elim HrecH1.
(* Goal: forall (x : nat) (_ : analysis_seq h x (MEnc M K) (MEnc N L)), @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
intro n1.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall (x : nat) (_ : synthesis (analysis_seq h x) (inv K) (inv L)), @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
intro n2.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (MPair M1 M2) (MPair N1 N2)) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (Mop o M) (Mop o N)) *)
exists (max n1 n2).
(* Goal: synthesis (analysis_seq h (Nat.max n1 n2)) (MPair M1 M2) (MPair N1 N2) *)
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (Mop o M) (Mop o N)) *)
apply SynPair.
generalize
 (inclusion_impl_le_h (analysis_seq h n1) (analysis_seq h (max n1 n2))
    (analysis_seq_increase n1 (max n1 n2) h (le_max_l n1 n2))).
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold le_h in |- *; auto.
generalize
 (inclusion_impl_le_h (analysis_seq h n2) (analysis_seq h (max n1 n2))
    (analysis_seq_increase n2 (max n1 n2) h (le_max_r n1 n2))).
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold le_h in |- *; auto.
(* Goal: @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
elim HrecH.
(* Goal: forall (x : nat) (_ : analysis_seq h x M N), h' M N *)
intro n.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex nat (fun n : nat => synthesis (analysis_seq h n) (Mop o M) (Mop o N)) *)
exists n.
(* Goal: synthesis (analysis_seq h n) (Mop o M) (Mop o N) *)
apply SynOp.
(* Goal: le_h g h *)
trivial.
Qed.

(** A(h) is indeed the analysis of h: 
    it shows that for all h the analysis of h exists *)
Lemma analysis_is_analysis : forall h : hedge, is_analysis h (analysis_def h).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (M N : Msg) (_ : analysis_def h M N), h' M N *)
unfold analysis_def in |- *.
(* Goal: @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: stable_analysis (analysis_def h) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
exists 0.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: le_h g h *)
trivial.
(* Goal: forall (h : hedge) (_ : stable_analysis h), stable_analysis (transpose h) *)
unfold stable_analysis in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (M N : Msg) (_ : analysis_def h M N), h' M N *)
unfold analysis_def in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
induction  H
 as [M N H| M1 M2 N1 N2 H HrecH| M1 M2 N1 N2 H HrecH| M N K L H HrecH H0].
(* Goal: le_h g h *)
trivial.
(* Goal: @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
elim HrecH.
(* Goal: forall (x : nat) (_ : analysis_seq h x M N), h' M N *)
intro n.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex nat (fun n : nat => analysis_seq h n M2 N2) *)
(* Goal: @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
exists (S n).
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: analysis (analysis_seq h n) M1 N1 *)
(* Goal: @ex nat (fun n : nat => analysis_seq h n M2 N2) *)
(* Goal: @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
apply (AnaSplitL (analysis_seq h n) M1 M2 N1 N2).
(* Goal: analysis h M N *)
apply AnaInc.
(* Goal: le_h g h *)
trivial.
(* Goal: @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
elim HrecH.
(* Goal: forall (x : nat) (_ : analysis_seq h x M N), h' M N *)
intro n.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex nat (fun n : nat => analysis_seq h n M2 N2) *)
(* Goal: @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
exists (S n).
(* Goal: analysis_seq h (S n) M2 N2 *)
(* Goal: @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
apply (AnaSplitR (analysis_seq h n) M1 M2 N1 N2).
(* Goal: le_h g h *)
apply AnaInc; trivial.
(* Goal: @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
elim HrecH.
(* Goal: forall (x : nat) (_ : analysis_seq h x (MEnc M K) (MEnc N L)), @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
intro n1.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
generalize (synthesis_analysis_seq h (inv K) (inv L) H0).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
elim H2.
(* Goal: forall (x : nat) (_ : synthesis (analysis_seq h x) (inv K) (inv L)), @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
intro n2.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex nat (fun n : nat => analysis_seq h n M N) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
exists (S (max n1 n2)).
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: analysis (analysis_seq h (Nat.max n1 n2)) M N *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
apply (AnaDec (analysis_seq h (max n1 n2)) M N K L).
(* Goal: analysis h M N *)
apply AnaInc.
(* Goal: analysis_seq h (Nat.max n1 n2) (MEnc M K) (MEnc N L) *)
(* Goal: synthesis (analysis_seq h (Nat.max n1 n2)) (inv K) (inv L) *)
(* Goal: forall (h' : hedge) (_ : analysis_cond h h'), inclusion (analysis_def h) h' *)
generalize (analysis_seq_increase n1 (max n1 n2) h (le_max_l n1 n2)).
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold inclusion in |- *; auto.
generalize
 (inclusion_impl_le_h (analysis_seq h n2) (analysis_seq h (max n1 n2))
    (analysis_seq_increase n2 (max n1 n2) h (le_max_r n1 n2))).
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold le_h in |- *; auto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (M N : Msg) (_ : analysis_def h M N), h' M N *)
unfold analysis_def in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
elim H0.
(* Goal: forall (x : nat) (_ : analysis_seq h x M N), h' M N *)
intro n.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: h' M N *)
generalize (analysis_seq_incl_analysis_cond h h' H n).
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold inclusion in |- *; auto.
Qed.

(** the irreducibles I(h) of h is (reduce (A(h))) *)
Definition irreducible (h : hedge) := reduce (analysis_def h).

(** here follows three lemma that make clear 
    the definition of the irreducibles of h *)
Lemma irreducible_enc :
 forall (h : hedge) (M N K L : Msg),
 irreducible h (MEnc M K) (MEnc N L) <->
 analysis_def h (MEnc M K) (MEnc N L) /\
 (~ synthesis (analysis_def h) M N \/ ~ synthesis (analysis_def h) K L).
(* Goal: forall (h : hedge) (M N K L : Msg), iff (irreducible h (MEnc M K) (MEnc N L)) (and (analysis_def h (MEnc M K) (MEnc N L)) (or (not (synthesis (analysis_def h) M N)) (not (synthesis (analysis_def h) K L)))) *)
intros h M N K L.
(* Goal: forall h : hedge, equal (irreducible (transpose h)) (transpose (irreducible h)) *)
unfold irreducible in |- *.
(* Goal: forall _ : reduce h N M, reduce (fun M N : Msg => h N M) M N *)
unfold reduce in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

Lemma irreducible_op :
 forall (h : hedge) (oM oN : op) (M N : Msg),
 irreducible h (Mop oM M) (Mop oN N) <->
 analysis_def h (Mop oM M) (Mop oN N) /\
 (oM <> oN \/ ~ synthesis (analysis_def h) M N).
(* Goal: forall h : hedge, equal (irreducible (transpose h)) (transpose (irreducible h)) *)
unfold irreducible in |- *.
(* Goal: forall _ : reduce h N M, reduce (fun M N : Msg => h N M) M N *)
unfold reduce in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

Lemma irreducible_pair :
 forall (h : hedge) (M1 N1 M2 N2 : Msg),
 ~ irreducible h (MPair M1 M2) (MPair N1 N2).
(* Goal: forall h : hedge, equal (irreducible (transpose h)) (transpose (irreducible h)) *)
unfold irreducible in |- *.
(* Goal: forall _ : reduce h N M, reduce (fun M N : Msg => h N M) M N *)
unfold reduce in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: not (synthesis h m m1) *)
(* Goal: forall _ : not (synthesis (transpose h) m2 m0), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
red in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
cut (analysis_def h M1 N1 /\ analysis_def h M2 N2).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
elim H2.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
case H1; intro H5; apply H5; trivial.
(* Goal: le_h g h *)
apply SynInc; trivial.
(* Goal: le_h g h *)
apply SynInc; trivial.
(* Goal: and (analysis_def h M1 N1) (analysis_def h M2 N2) *)
cut (is_analysis h (analysis_def h)); try apply analysis_is_analysis.
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
elim H2.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
elim H3.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (analysis_def h M1 N1) (analysis_def h M2 N2) *)
unfold stable_analysis in H6.
(* Goal: and (analysis_def h M1 N1) (analysis_def h M2 N2) *)
unfold inclusion in H6.
(* Goal: False *)
split; apply H6.
(* Goal: le_h g h *)
apply (AnaSplitL (analysis_def h) M1 M2 N1 N2); apply AnaInc; trivial.
(* Goal: le_h g h *)
apply (AnaSplitR (analysis_def h) M1 M2 N1 N2); apply AnaInc; trivial.
Qed.

(** h is irreducible iff h = I(h) *)
Definition is_irreducible (h : hedge) := equal h (irreducible h).

(** h <= A(h) *)
Theorem h_le_h_ana_h : forall h : hedge, le_h h (analysis_def h).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: le_h (irreducible h) h *)
apply inclusion_impl_le_h.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
generalize (analysis_is_analysis h).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion h (analysis_def h) *)
unfold is_analysis in H.
(* Goal: inclusion h (analysis_def h) *)
unfold analysis_cond in H.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** A(h) ~ I(h) *)
Theorem ana_h_equiv_irr_h :
 forall h : hedge, equiv_h (analysis_def h) (irreducible h).
(* Goal: forall h : hedge, equal (irreducible (transpose h)) (transpose (irreducible h)) *)
unfold irreducible in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: equiv_h h (reduce h) *)
(* Goal: equiv_h h (irreducible h) *)
apply h_equiv_h_red.
Qed.

(** h <= I(h) *)
Theorem h_le_h_irr_h : forall h : hedge, le_h h (irreducible h).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: le_h (irreducible g) (irreducible h) *)
apply le_h_trans with (analysis_def h).
(* Goal: le_h h (analysis_def h) *)
(* Goal: le_h (analysis_def h) h *)
(* Goal: equiv_h (analysis_def h) (irreducible h) *)
apply h_le_h_ana_h.
(* Goal: synthesis h M N *)
generalize (ana_h_equiv_irr_h h).
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** A(I(h)) is included in A(h) *)
Lemma ana_irr_incl_ana :
 forall h : hedge, inclusion (analysis_def (irreducible h)) (analysis_def h).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion (analysis_def (irreducible h)) (analysis_def h) *)
generalize (analysis_is_analysis (irreducible h)).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
apply H1.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: forall h : hedge, equal (irreducible (transpose h)) (transpose (irreducible h)) *)
unfold irreducible in |- *.
(* Goal: inclusion (reduce (analysis_def h)) (analysis_def h) *)
(* Goal: stable_analysis (analysis_def h) *)
apply red_incl_h.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
generalize (analysis_is_analysis h).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** I(I(h)) is included in I(h) *)
Lemma irr_irr_incl_irr :
 forall h : hedge, inclusion (irreducible (irreducible h)) (irreducible h).
(* Goal: forall h : hedge, equal (irreducible (transpose h)) (transpose (irreducible h)) *)
unfold irreducible in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion (reduce (analysis_def (reduce (analysis_def h)))) (reduce (analysis_def h)) *)
apply inclusion_le_h_reduce_inclusion.
(* Goal: le_h (analysis_def h) (analysis_def (reduce (analysis_def h))) *)
replace (reduce (analysis_def h)) with (irreducible h).
(* Goal: inclusion (analysis_def (irreducible h)) (analysis_def h) *)
(* Goal: le_h (analysis_def h) (reduce (analysis_def h)) *)
apply ana_irr_incl_ana.
(* Goal: forall h : hedge, equal (irreducible (transpose h)) (transpose (irreducible h)) *)
unfold irreducible in |- *.
(* Goal: le_h g h *)
trivial.
(* Goal: le_h (analysis_def h) (analysis_def (reduce (analysis_def h))) *)
replace (reduce (analysis_def h)) with (irreducible h).
(* Goal: le_h (analysis_def h) (analysis_def (irreducible h)) *)
(* Goal: @eq (forall (_ : Msg) (_ : Msg), Prop) (irreducible h) (reduce (analysis_def h)) *)
apply le_h_trans with (irreducible h).
(* Goal: le_h (analysis_def h) (irreducible h) *)
generalize ana_h_equiv_irr_h.
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
elim (H h); tauto.
(* Goal: le_h h (analysis_def h) *)
(* Goal: le_h (analysis_def h) h *)
(* Goal: equiv_h (analysis_def h) (irreducible h) *)
apply h_le_h_ana_h.
(* Goal: forall h : hedge, equal (irreducible (transpose h)) (transpose (irreducible h)) *)
unfold irreducible in |- *.
(* Goal: le_h g h *)
trivial.
Qed.

(* I(h) is included in I(I(h)) *)
Lemma irr_incl_irr_irr :
 forall h : hedge, inclusion (irreducible h) (irreducible (irreducible h)).
(* Goal: forall h : hedge, equal (irreducible (transpose h)) (transpose (irreducible h)) *)
unfold irreducible in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (reduce (analysis_def h)) (reduce (analysis_def (reduce (analysis_def h)))) *)
apply inclusion_le_h_impl_inclusion_red.
(* Goal: inclusion (reduce (analysis_def h)) (analysis_def (reduce (analysis_def h))) *)
(* Goal: le_h (analysis_def (reduce (analysis_def h))) (reduce (analysis_def h)) *)
generalize (analysis_is_analysis (reduce (analysis_def h))).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: le_h (irreducible g) (irreducible h) *)
apply le_h_trans with (analysis_def h).
(* Goal: le_h (irreducible h) h *)
apply inclusion_impl_le_h.
(* Goal: le_h (analysis_def h) (reduce (analysis_def h)) *)
fold (irreducible h) in |- *.
(* Goal: inclusion (analysis_def (irreducible h)) (analysis_def h) *)
(* Goal: le_h (analysis_def h) (reduce (analysis_def h)) *)
apply ana_irr_incl_ana.
(* Goal: le_h (analysis_def h) (reduce (analysis_def h)) *)
fold (irreducible h) in |- *.
(* Goal: le_h (analysis_def h) (irreducible h) *)
generalize ana_h_equiv_irr_h.
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
elim (H h); auto.
Qed.

(** I(h) is irreducible *)
Theorem irreducible_is_irreducible :
 forall h : hedge, is_irreducible (irreducible h).
(* Goal: forall (h : hedge) (_ : is_irreducible h), is_irreducible (transpose h) *)
unfold is_irreducible in |- *.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (inclusion (irreducible h) (irreducible (irreducible h))) (inclusion (irreducible (irreducible h)) (irreducible h)) *)
generalize (irr_incl_irr_irr h).
(* Goal: forall _ : inclusion (irreducible h) (irreducible (irreducible h)), and (inclusion (irreducible h) (irreducible (irreducible h))) (inclusion (irreducible (irreducible h)) (irreducible h)) *)
generalize (irr_irr_incl_irr h).
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** if g ~ h and g is irreducible then g is included in h *)
Theorem equiv_irr_impl_incl :
 forall g h : hedge, equiv_h g h -> is_irreducible g -> inclusion g h.
(* Goal: forall (h : hedge) (_ : is_irreducible h), is_irreducible (transpose h) *)
unfold is_irreducible in |- *.
(* Goal: forall h : hedge, equal (irreducible (transpose h)) (transpose (irreducible h)) *)
unfold irreducible in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion g h *)
apply inclusion_trans with (reduce (analysis_def g)).
(* Goal: inclusion g (reduce (analysis_def g)) *)
(* Goal: inclusion (reduce (analysis_def g)) h *)
unfold equal in H0.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: inclusion (reduce h) (irreducible h) *)
apply red_equiv_impl_red_incl.
(* Goal: equiv_h (reduce (analysis_def g)) h *)
apply equiv_h_trans with g.
(* Goal: equiv_h (reduce (analysis_def g)) g *)
(* Goal: equiv_h g h *)
apply equal_impl_equiv_h.
(* Goal: equal (transpose (irreducible h)) (irreducible (transpose h)) *)
apply equal_sym.
(* Goal: le_h g h *)
trivial.
(* Goal: le_h g h *)
trivial.
Qed.

(** if g ~ h, g is irreducible and h is irreducible then g = h *)
Theorem equiv_irr_irr_impl_equal :
 forall g h : hedge,
 equiv_h g h -> is_irreducible g -> is_irreducible h -> equal g h.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: le_h g h *)
apply equiv_irr_impl_incl; trivial.
(* Goal: le_h g h *)
apply equiv_irr_impl_incl; trivial.
(* Goal: le_h g h *)
apply equiv_h_sym; trivial.
Qed.

(** h <= (analysis h) *)
Lemma h_le_h_analysis : forall h : hedge, le_h h (analysis h).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: le_h (irreducible h) h *)
apply inclusion_impl_le_h.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis h M N *)
apply AnaInc.
(* Goal: le_h g h *)
trivial.
Qed.

(** S(S(h)) = S(h) *)
Lemma synthesis_idempotent :
 forall h : hedge, equal (synthesis h) (synthesis (synthesis h)).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
apply SynInc; trivial.
(* Goal: inclusion (synthesis (synthesis h)) (synthesis h) *)
generalize (incl_syn_impl_le_h (synthesis h) h).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (synthesis (synthesis h)) (synthesis h) *)
apply H.
(* Goal: inclusion (synthesis h) (synthesis h) *)
apply inclusion_refl.
Qed.

(** if h is stable under analysis then so is S(h) *)
Lemma stable_ana_impl_stable_syn_ana :
 forall h : hedge, stable_analysis h -> stable_analysis (synthesis h).
(* Goal: forall (h : hedge) (_ : stable_analysis h), stable_analysis (transpose h) *)
unfold stable_analysis in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
induction  H0
 as
  [M N H0| M1 M2 N1 N2 H0 HrecH0| M1 M2 N1 N2 H0 HrecH0| M N K L H0 HrecH0 H1];
(* Goal: le_h g h *)
 trivial.
(* Goal: le_h g h *)
inversion HrecH0; trivial.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: inclusion (synthesis (synthesis h)) (synthesis h) *)
apply H.
(* Goal: analysis h M1 N1 *)
(* Goal: analysis h M2 N2 *)
(* Goal: analysis h M N *)
apply (AnaSplitL h M1 M2 N1 N2).
(* Goal: le_h g h *)
apply AnaInc; trivial.
(* Goal: le_h g h *)
inversion HrecH0; trivial.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: inclusion (synthesis (synthesis h)) (synthesis h) *)
apply H.
(* Goal: analysis h M2 N2 *)
(* Goal: analysis h M N *)
apply (AnaSplitR h M1 M2 N1 N2).
(* Goal: le_h g h *)
apply AnaInc; trivial.
(* Goal: le_h g h *)
inversion HrecH0; trivial.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: inclusion (synthesis (synthesis h)) (synthesis h) *)
apply H.
(* Goal: le_h g h *)
apply (AnaDec h M N K L); trivial.
(* Goal: le_h g h *)
apply AnaInc; trivial.
(* Goal: synthesis h M N *)
generalize (synthesis_idempotent h).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (fun M N : Msg => h N M) m0 m *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
elim H5.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
apply H7; trivial.
Qed.

(** if g <= h then A(g) <= A(h) *)
Lemma le_h_ana_le_h :
 forall g h : hedge, le_h g h -> le_h (analysis_def g) (analysis_def h).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h (analysis_def g) (analysis_def h) *)
generalize (le_h_impl_incl_syn g h H).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: le_h (transpose g) (transpose h) *)
apply incl_syn_impl_le_h.
(* Goal: analysis_def g M' N0 *)
generalize (analysis_is_analysis g).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: transpose h M N *)
elim H1.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: False *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H3.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: inclusion g (synthesis (analysis_def h)) *)
(* Goal: stable_analysis (synthesis (analysis_def h)) *)
apply inclusion_trans with (synthesis h).
(* Goal: le_h g h *)
trivial.
(* Goal: inclusion (synthesis h) (synthesis (analysis_def h)) *)
(* Goal: stable_analysis (synthesis (analysis_def h)) *)
generalize h_le_h_ana_h.
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: le_h g h *)
trivial.
(* Goal: stable_analysis (synthesis (analysis_def h)) *)
apply stable_ana_impl_stable_syn_ana.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
generalize (analysis_is_analysis h).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** if g <= h then I(g) <= I(h) *)
Theorem le_h_irr_le_h :
 forall g h : hedge, le_h g h -> le_h (irreducible g) (irreducible h).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h (irreducible g) (irreducible h) *)
apply le_h_trans with (analysis_def h).
(* Goal: le_h (irreducible g) (analysis_def h) *)
(* Goal: le_h (analysis_def h) (irreducible h) *)
apply le_h_trans with (analysis_def g).
(* Goal: synthesis (irreducible g) M' N0 *)
generalize (ana_h_equiv_irr_h g).
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
unfold equiv_h in |- *; tauto.
(* Goal: le_h g h *)
apply le_h_ana_le_h; trivial.
(* Goal: synthesis h M N *)
generalize (ana_h_equiv_irr_h h).
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
unfold equiv_h in |- *; tauto.
Qed.

(** if g ~ h then I(g) = I(h) *)
Theorem equiv_h_impl_irr_unique :
 forall g h : hedge, equiv_h g h -> equal (irreducible g) (irreducible h).
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: equal (irreducible (union (irreducible h) g)) (irreducible (union h g)) *)
apply equiv_irr_irr_impl_equal; try apply irreducible_is_irreducible.
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
elim H; intros.
(* Goal: le_h g h *)
split; apply le_h_irr_le_h; trivial.
Qed.

(** I(union I(h) g) = I(union h g) *)
Theorem update_irr :
 forall g h : hedge,
 equal (irreducible (union (irreducible h) g)) (irreducible (union h g)).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: equal (irreducible (union (irreducible h) g)) (irreducible (union h g)) *)
apply equiv_irr_irr_impl_equal; try apply irreducible_is_irreducible.
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: le_h (irreducible (union (irreducible h) g)) (irreducible (union h g)) *)
(* Goal: le_h (irreducible (union h g)) (irreducible (union (irreducible h) g)) *)
apply le_h_trans with (irreducible (irreducible (union h g))).
(* Goal: le_h (irreducible (union h g)) (irreducible (union (irreducible h) g)) *)
apply le_h_irr_le_h.
(* Goal: le_h (union (irreducible h) g) (irreducible (union h g)) *)
(* Goal: le_h (irreducible (irreducible (union h g))) (irreducible (union h g)) *)
(* Goal: le_h (irreducible (union h g)) (irreducible (union (irreducible h) g)) *)
apply le_h_le_h_impl_union_le_h.
(* Goal: le_h (irreducible (union h g)) (irreducible (union (irreducible h) g)) *)
apply le_h_irr_le_h.
(* Goal: le_h (irreducible h) h *)
apply inclusion_impl_le_h.
(* Goal: inclusion h (union h g) *)
(* Goal: le_h g (irreducible (union h g)) *)
(* Goal: le_h (irreducible (irreducible (union h g))) (irreducible (union h g)) *)
(* Goal: le_h (irreducible (union h g)) (irreducible (union (irreducible h) g)) *)
apply hedge_left_union.
(* Goal: le_h g (irreducible (union h g)) *)
(* Goal: le_h (irreducible (irreducible (union h g))) (irreducible (union h g)) *)
(* Goal: le_h (irreducible (union h g)) (irreducible (union (irreducible h) g)) *)
apply le_h_trans with (irreducible g).
(* Goal: le_h h (irreducible h) *)
(* Goal: le_h g g *)
apply h_le_h_irr_h.
(* Goal: le_h (irreducible (union h g)) (irreducible (union (irreducible h) g)) *)
apply le_h_irr_le_h.
(* Goal: le_h (irreducible h) h *)
apply inclusion_impl_le_h.
(* Goal: inclusion g (union h g) *)
(* Goal: le_h (irreducible (irreducible (union h g))) (irreducible (union h g)) *)
(* Goal: le_h (irreducible (union h g)) (irreducible (union (irreducible h) g)) *)
apply hedge_right_union.
(* Goal: le_h (irreducible (irreducible (union h g))) (irreducible (union h g)) *)
(* Goal: le_h (irreducible (union h g)) (irreducible (union (irreducible h) g)) *)
generalize (irreducible_is_irreducible (union h g)).
(* Goal: forall (h : hedge) (_ : is_irreducible h), is_irreducible (transpose h) *)
unfold is_irreducible in |- *.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h (irreducible h) h *)
apply inclusion_impl_le_h.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: le_h (irreducible (union h g)) (irreducible (union (irreducible h) g)) *)
apply le_h_irr_le_h.
(* Goal: le_h (union h g) (union (irreducible h) g) *)
apply le_h_le_h_impl_le_h_union. 
(* Goal: le_h h (irreducible h) *)
(* Goal: le_h g g *)
apply h_le_h_irr_h.
(* Goal: le_h g g *)
apply le_h_refl.
Qed.

(** we define afterwards the notion of left consistency: we define first several predicates on hedges *)

(** if (M,N) is in h and M is a name then N is a name *)
Definition name_left_name (h : hedge) :=
  forall M N : Msg,
  h M N -> forall a : Nam, M = MNam a -> exists b : Nam, N = MNam b.

(** if (M,N) and (M',N') are in h and M = M' then N = N' *)
Definition injective_left (h : hedge) :=
  forall M N : Msg, h M N -> forall M' N' : Msg, h M' N' -> M = M' -> N = N'.

(** if op(M) is in the left projection of h then M is not in the left projection of S(h) *)
Definition op_synthesis_left (h : hedge) :=
  forall (o : op) (M N : Msg),
  h M N ->
  forall M' : Msg, M = Mop o M' -> forall N' : Msg, ~ synthesis h M' N'.

(** if {M}K is in the left projection of h then either M or K are not in the left projection of S(h) *)
Definition enc_synthesis_left (h : hedge) :=
  forall M N : Msg,
  h M N ->
  forall M' K : Msg,
  M = MEnc M' K ->
  forall N' L : Msg, ~ synthesis h M' N' \/ ~ synthesis h K L.

(** the left projection of h does not contain any pair *)
Definition pair_free_left (h : hedge) :=
  forall M1 M2 N : Msg, ~ h (MPair M1 M2) N.

(** if ({M}K,N') is in h and (inv K) is in the left projection of S(h) then N' = {N}L, (inv K,inv L) is in S(h) and (M,N) is in S(h) *)
Definition enc_analysis_left (h : hedge) :=
  forall M N : Msg,
  h M N ->
  forall M' K : Msg,
  M = MEnc M' K ->
  forall L : Msg,
  synthesis h (inv K) (inv L) ->
  exists N' : Msg, N = MEnc N' L /\ synthesis h M' N'.

(** if (M,N) is in h and (inv M,N') is in h then N'=(inv N) *)
Definition injective_inv_left (h : hedge) :=
  forall M N : Msg,
  h M N -> forall M' N' : Msg, h M' N' -> M' = inv M -> N' = inv N.

(** left consistency of h *)
Definition is_left_consistent (h : hedge) : Prop :=
  name_left_name h /\
  injective_left h /\
  op_synthesis_left h /\
  pair_free_left h /\
  enc_synthesis_left h /\ enc_analysis_left h /\ injective_inv_left h.

Definition weak_left_consistent (h : hedge) :=
  name_left_name h /\
  injective_left h /\
  op_synthesis_left h /\
  pair_free_left h /\ enc_synthesis_left h /\ enc_analysis_left h.

Theorem inj_left_syn :
 forall h : hedge,
 injective_left h ->
 enc_synthesis_left h ->
 op_synthesis_left h -> pair_free_left h -> injective_left (synthesis h).
(* Goal: forall _ : injective_left (synthesis h), @eq Msg N' N0 *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
unfold injective_left in |- *.
(* Goal: enc_synthesis_left g *)
(* Goal: enc_analysis_left g *)
unfold enc_synthesis_left in |- *.
(* Goal: op_synthesis_left g *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
unfold op_synthesis_left in |- *.
(* Goal: pair_free_left g *)
(* Goal: and (enc_synthesis_left g) (enc_analysis_left g) *)
unfold pair_free_left in |- *.
(* Goal: forall (h : hedge) (_ : injective_left h) (_ : enc_synthesis_left h) (_ : op_synthesis_left h) (_ : pair_free_left h) (_ : injective_inv_left h), injective_inv_left (synthesis h) *)
intro h.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall (M N : Msg) (_ : synthesis h M N) (M' N' : Msg) (_ : synthesis h M' N') (_ : @eq Msg M M'), @eq Msg N N' *)
intros M N H3.
induction  H3
 as
  [M
   N
   H3|
   M
   N
   K
   L
   H3_1
   HrecH3_1
   H3_0
   HrecH3_0|
   M1
   N1
   M2
   N2
   H3_1
   HrecH3_1
   H3_0
   HrecH3_0|
   o
   M
   N
   H3
   HrecH3]; intros M' N' H4;
 [ induction  H4
    as
     [M0
      N0
      H4|
      M0
      N0
      K
      L
      H4_1
      HrecH4_1
      H4_0
      HrecH4_0|
      M1
      N1
      M2
      N2
      H4_1
      HrecH4_1
      H4_0
      HrecH4_0|
      o
      M0
      N0
      H4
      HrecH4]
 | induction  H4
    as
     [M0
      N0
      H3|
      M0
      N0
      K0
      L0
      H4_1
      HrecH4_1
      H4_0
      HrecH4_0|
      M1
      N1
      M2
      N2
      H4_1
      HrecH4_1
      H4_0
      HrecH4_0|
      o
      M0
      N0
      H4
      HrecH4]
 | induction  H4
    as
     [M
      N
      H3|
      M
      N
      K
      L
      H4_1
      HrecH4_1
      H4_0
      HrecH4_0|
      M0
      N0
      M3
      N3
      H4_1
      HrecH4_1
      H4_0
      HrecH4_0|
      o
      M
      N
      H4
      HrecH4]
 | induction  H4
    as
     [M0
      N0
      H4|
      M0
      N0
      K
      L
      H4_1
      HrecH4_1
      H4_0
      HrecH4_0|
      M1
      N1
      M2
      N2
      H4_1
      HrecH4_1
      H4_0
      HrecH4_0|
      o0
      M0
      N0
      H4
      HrecH4] ].
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N N0 *)
(* Goal: forall _ : @eq Msg M (MEnc M0 K), @eq Msg N (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg M (MPair M1 M2), @eq Msg N (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg M (Mop o M0), @eq Msg N (Mop o N0) *)
(* Goal: forall _ : @eq Msg (MEnc M K) M0, @eq Msg (MEnc N L) N0 *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MEnc M0 K0), @eq Msg (MEnc N L) (MEnc N0 L0) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MPair M1 M2), @eq Msg (MEnc N L) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (Mop o M0), @eq Msg (MEnc N L) (Mop o N0) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) M, @eq Msg (MPair N1 N2) N *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MEnc M K), @eq Msg (MPair N1 N2) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MPair M0 M3), @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
exact (H M N H3 M0 N0 H4 H5).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg M (MPair M1 M2), @eq Msg N (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg M (Mop o M0), @eq Msg N (Mop o N0) *)
(* Goal: forall _ : @eq Msg (MEnc M K) M0, @eq Msg (MEnc N L) N0 *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MEnc M0 K0), @eq Msg (MEnc N L) (MEnc N0 L0) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MPair M1 M2), @eq Msg (MEnc N L) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (Mop o M0), @eq Msg (MEnc N L) (Mop o N0) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) M, @eq Msg (MPair N1 N2) N *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MEnc M K), @eq Msg (MPair N1 N2) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MPair M0 M3), @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
cut (~ synthesis h M0 N0 \/ ~ synthesis h K L).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case H5; intro H6; red in H6; tauto.
(* Goal: or (not (synthesis h M0 N0)) (not (synthesis h K L)) *)
(* Goal: forall _ : @eq Msg M (MPair M1 M2), @eq Msg N (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg M (Mop o M0), @eq Msg N (Mop o N0) *)
(* Goal: forall _ : @eq Msg (MEnc M K) M0, @eq Msg (MEnc N L) N0 *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MEnc M0 K0), @eq Msg (MEnc N L) (MEnc N0 L0) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MPair M1 M2), @eq Msg (MEnc N L) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (Mop o M0), @eq Msg (MEnc N L) (Mop o N0) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) M, @eq Msg (MPair N1 N2) N *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MEnc M K), @eq Msg (MPair N1 N2) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MPair M0 M3), @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
apply (H0 M N H3 M0 K H4).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg M (Mop o M0), @eq Msg N (Mop o N0) *)
(* Goal: forall _ : @eq Msg (MEnc M K) M0, @eq Msg (MEnc N L) N0 *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MEnc M0 K0), @eq Msg (MEnc N L) (MEnc N0 L0) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MPair M1 M2), @eq Msg (MEnc N L) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (Mop o M0), @eq Msg (MEnc N L) (Mop o N0) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) M, @eq Msg (MPair N1 N2) N *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MEnc M K), @eq Msg (MPair N1 N2) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MPair M0 M3), @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
rewrite H4 in H3.
(* Goal: @eq Msg (MPair N1 N2) N *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MEnc M K), @eq Msg (MPair N1 N2) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MPair M0 M3), @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
cut False.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: le_h g h *)
apply (H2 M1 M2 N); trivial.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N (Mop o N0) *)
(* Goal: forall _ : @eq Msg (MEnc M K) M0, @eq Msg (MEnc N L) N0 *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MEnc M0 K0), @eq Msg (MEnc N L) (MEnc N0 L0) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MPair M1 M2), @eq Msg (MEnc N L) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (Mop o M0), @eq Msg (MEnc N L) (Mop o N0) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) M, @eq Msg (MPair N1 N2) N *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MEnc M K), @eq Msg (MPair N1 N2) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MPair M0 M3), @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
cut (~ synthesis h M0 N0).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: le_h g h *)
apply (H1 o M N H3 M0 H5); trivial.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MEnc N L) N0 *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MEnc M0 K0), @eq Msg (MEnc N L) (MEnc N0 L0) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MPair M1 M2), @eq Msg (MEnc N L) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (Mop o M0), @eq Msg (MEnc N L) (Mop o N0) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) M, @eq Msg (MPair N1 N2) N *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MEnc M K), @eq Msg (MPair N1 N2) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MPair M0 M3), @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
cut (~ synthesis h M N \/ ~ synthesis h K L).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case H5; intro H6; red in H6; tauto.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
apply (H0 M0 N0 H3 M K); auto.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
inversion H3.
(* Goal: @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
rewrite (HrecH3_1 M0 N0 H4_1 H5).
(* Goal: @eq Msg (MEnc N0 L) (MEnc N0 L0) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (MPair M1 M2), @eq Msg (MEnc N L) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (Mop o M0), @eq Msg (MEnc N L) (Mop o N0) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) M, @eq Msg (MPair N1 N2) N *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MEnc M K), @eq Msg (MPair N1 N2) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MPair M0 M3), @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
rewrite (HrecH3_0 K0 L0 H4_0 H6).
(* Goal: le_h g h *)
trivial.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
inversion H3.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
inversion H3.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N1 N2) N *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MEnc M K), @eq Msg (MPair N1 N2) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MPair M0 M3), @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
rewrite <- H4 in H3.
(* Goal: @eq Msg (MPair N1 N2) N *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MEnc M K), @eq Msg (MPair N1 N2) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MPair M0 M3), @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
cut False.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: False *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MEnc M K), @eq Msg (MPair N1 N2) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (MPair M0 M3), @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
apply (H2 M1 M2 N H3).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
inversion H3.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
inversion H3.
(* Goal: @eq Msg (MPair N1 N2) (MPair N0 N3) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (Mop o M), @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
rewrite (HrecH3_1 M0 N0 H4_1 H5).
(* Goal: le_h g h *)
rewrite (HrecH3_0 M3 N3 H4_0 H6); trivial.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N1 N2) (Mop o N) *)
(* Goal: forall _ : @eq Msg (Mop o M) M0, @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
inversion H3.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o N) N0 *)
(* Goal: forall _ : @eq Msg (Mop o M) (MEnc M0 K), @eq Msg (Mop o N) (MEnc N0 L) *)
(* Goal: forall _ : @eq Msg (Mop o M) (MPair M1 M2), @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
cut (~ synthesis h M N).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
apply (H1 o M0 N0 H4 M); auto.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
inversion H4.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o N) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
inversion H4.
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
case (op_eq_dec o o0).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall _ : @eq Msg (Mop o M) (Mop o0 M0), @eq Msg (Mop o N) (Mop o0 N0) *)
(* Goal: forall (_ : not (@eq op o o0)) (_ : @eq Msg (Mop o M) (Mop o0 M0)), @eq Msg (Mop o N) (Mop o0 N0) *)
rewrite <- e.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o N) (Mop o0 N0) *)
inversion H5.
(* Goal: @eq Msg (Mop o N) (Mop o N0) *)
(* Goal: forall (_ : not (@eq op o o0)) (_ : @eq Msg (Mop o M) (Mop o0 M0)), @eq Msg (Mop o N) (Mop o0 N0) *)
rewrite (HrecH3 M0 N0 H4 H7).
(* Goal: le_h g h *)
trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg (Mop o N) (Mop o0 N0) *)
inversion H5.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

Theorem inj_inv_left_syn :
 forall h : hedge,
 injective_left h ->
 enc_synthesis_left h ->
 op_synthesis_left h ->
 pair_free_left h -> injective_inv_left h -> injective_inv_left (synthesis h).
(* Goal: forall (h : hedge) (_ : injective_left h) (_ : enc_synthesis_left h) (_ : op_synthesis_left h) (_ : pair_free_left h) (_ : injective_inv_left h), injective_inv_left (synthesis h) *)
intro h.
(* Goal: forall (_ : injective_left h) (_ : enc_synthesis_left h) (_ : op_synthesis_left h) (_ : pair_free_left h) (_ : injective_inv_left h), injective_inv_left (synthesis h) *)
intros H0 H1 H2 H3 H4.
(* Goal: injective_inv_left (synthesis h) *)
generalize (inj_left_syn h H0 H1 H2 H3).
(* Goal: forall _ : injective_left (synthesis h), injective_inv_left (synthesis h) *)
intro H4bis.
(* Goal: injective_inv_left (synthesis h) *)
unfold injective_left in H0.
(* Goal: injective_inv_left (synthesis h) *)
unfold enc_synthesis_left in H1.
(* Goal: injective_inv_left (synthesis h) *)
unfold op_synthesis_left in H2.
(* Goal: injective_inv_left (synthesis h) *)
unfold pair_free_left in H3.
(* Goal: injective_inv_left (synthesis h) *)
unfold injective_inv_left in H4.
(* Goal: injective_inv_left (synthesis h) *)
unfold injective_left in H4bis.
(* Goal: forall _ : injective_inv_left (synthesis h), @eq Msg N' (inv N) *)
unfold injective_inv_left in |- *.
(* Goal: forall (M N : Msg) (_ : synthesis h M N) (M' N' : Msg) (_ : synthesis h M' N') (_ : @eq Msg M' (inv M)), @eq Msg N' (inv N) *)
intros M N H5.
induction  H5
 as
  [M
   N
   H|
   M
   N
   K
   L
   H5_1
   HrecH5_1
   H5_0
   HrecH5_0|
   M1
   N1
   M2
   N2
   H5_1
   HrecH5_1
   H5_0
   HrecH5_0|
   o
   M
   N
   H5
   HrecH5]; intros M' N' H6;
 [ induction  H6
    as
     [M0
      N0
      H5|
      M0
      N0
      K
      L
      H6_1
      HrecH6_1
      H6_0
      HrecH6_0|
      M1
      N1
      M2
      N2
      H6_1
      HrecH6_1
      H6_0
      HrecH6_0|
      o
      M0
      N0
      H6
      HrecH6]
 | induction  H6
    as
     [M0
      N0
      H|
      M0
      N0
      K0
      L0
      H6_1
      HrecH6_1
      H6_0
      HrecH6_0|
      M1
      N1
      M2
      N2
      H6_1
      HrecH6_1
      H6_0
      HrecH6_0|
      o
      M0
      N0
      H6
      HrecH6]
 | induction  H6
    as
     [M
      N
      H|
      M
      N
      K
      L
      H6_1
      HrecH6_1
      H6_0
      HrecH6_0|
      M0
      N0
      M3
      N3
      H6_1
      HrecH6_1
      H6_0
      HrecH6_0|
      o
      M
      N
      H6
      HrecH6]
 | induction  H6
    as
     [M0
      N0
      H|
      M0
      N0
      K
      L
      H6_1
      HrecH6_1
      H6_0
      HrecH6_0|
      M1
      N1
      M2
      N2
      H6_1
      HrecH6_1
      H6_0
      HrecH6_0|
      o0
      M0
      N0
      H6
      HrecH6] ].
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N0 (inv N) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv M), @eq Msg (MEnc N0 L) (inv N) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv M), @eq Msg (MPair N1 N2) (inv N) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv M), @eq Msg (Mop o N0) (inv N) *)
(* Goal: forall _ : @eq Msg M0 (inv (MEnc M K)), @eq Msg N0 (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
apply (H4 M N H M0 N0 H5 H6). 
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MEnc N0 L) (inv N) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv M), @eq Msg (MPair N1 N2) (inv N) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv M), @eq Msg (Mop o N0) (inv N) *)
(* Goal: forall _ : @eq Msg M0 (inv (MEnc M K)), @eq Msg N0 (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
cut (M = inv (MEnc M0 K)).
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case (H1 M N H M0 K H6 N0 L); intro; tauto.
(* Goal: @eq Msg M (inv (Mop o M0)) *)
(* Goal: forall _ : @eq Msg M0 (inv (MEnc M K)), @eq Msg N0 (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
rewrite H5.
symmetry  in |- *.
(* Goal: @eq Msg (inv (inv L)) L *)
apply inv_invol.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N1 N2) (inv N) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv M), @eq Msg (Mop o N0) (inv N) *)
(* Goal: forall _ : @eq Msg M0 (inv (MEnc M K)), @eq Msg N0 (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
cut (M = inv (MPair M1 M2)).
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N1 N2) (inv N) *)
(* Goal: @eq Msg M (inv (MPair M1 M2)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv M), @eq Msg (Mop o N0) (inv N) *)
(* Goal: forall _ : @eq Msg M0 (inv (MEnc M K)), @eq Msg N0 (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
rewrite H6 in H.
(* Goal: @eq Msg (MPair N1 N2) (inv N) *)
(* Goal: @eq Msg M (inv (MPair M1 M2)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv M), @eq Msg (Mop o N0) (inv N) *)
(* Goal: forall _ : @eq Msg M0 (inv (MEnc M K)), @eq Msg N0 (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
generalize (H3 M1 M2 N).
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: @eq Msg M (inv (Mop o M0)) *)
(* Goal: forall _ : @eq Msg M0 (inv (MEnc M K)), @eq Msg N0 (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
rewrite H5.
symmetry  in |- *.
(* Goal: @eq Msg (inv (inv L)) L *)
apply inv_invol.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o N0) (inv N) *)
(* Goal: forall _ : @eq Msg M0 (inv (MEnc M K)), @eq Msg N0 (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
cut (M = inv (Mop o M0)).
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o N0) (inv N) *)
(* Goal: @eq Msg M (inv (Mop o M0)) *)
(* Goal: forall _ : @eq Msg M0 (inv (MEnc M K)), @eq Msg N0 (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
generalize (H2 (inv_op o) M N H M0 H7 N0).
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: @eq Msg M (inv (Mop o M0)) *)
(* Goal: forall _ : @eq Msg M0 (inv (MEnc M K)), @eq Msg N0 (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
rewrite H5.
symmetry  in |- *.
(* Goal: @eq Msg (inv (inv L)) L *)
apply inv_invol.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall _ : @eq Msg M0 (MEnc M K), @eq Msg N0 (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
cut (synthesis h M0 N0).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N0 (MEnc N L) *)
(* Goal: synthesis h M0 N0 *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
cut (synthesis h (MEnc M K) (MEnc N L)).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N0 (MEnc N L) *)
(* Goal: synthesis h (MEnc M K) (MEnc N L) *)
(* Goal: synthesis h M0 N0 *)
(* Goal: forall _ : @eq Msg (MEnc M0 K0) (inv (MEnc M K)), @eq Msg (MEnc N0 L0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
apply (H4bis M0 N0 H5 (MEnc M K) (MEnc N L) H7 H6).
(* Goal: le_h g h *)
apply SynEnc; trivial.
(* Goal: le_h g h *)
apply SynInc; trivial.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o0 N0) (Mop (inv_op o) N) *)
inversion H.
(* Goal: @eq Msg (MEnc N0 L0) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
cut (synthesis h (MEnc M0 K0) (MEnc N0 L0)); try (apply SynEnc; trivial).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MEnc N0 L0) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
cut (synthesis h (MEnc M K) (MEnc N L)); try (apply SynEnc; trivial).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MEnc N0 L0) (MEnc N L) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (MEnc M K)), @eq Msg (MPair N1 N2) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg (Mop o M0) (inv (MEnc M K)), @eq Msg (Mop o N0) (inv (MEnc N L)) *)
(* Goal: forall _ : @eq Msg M (inv (MPair M1 M2)), @eq Msg N (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
apply (H4bis (MEnc M0 K0) (MEnc N0 L0) H5 (MEnc M K) (MEnc N L) H8 H).
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o0 N0) (Mop (inv_op o) N) *)
inversion H.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o0 N0) (Mop (inv_op o) N) *)
inversion H.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall _ : @eq Msg M (MPair M1 M2), @eq Msg N (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
cut (synthesis h M N); try (apply SynInc; trivial).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N0 N3) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
cut (synthesis h (MPair M1 M2) (MPair N1 N2)); try (apply SynPair; trivial).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (MEnc M K) (inv (MPair M1 M2)), @eq Msg (MEnc N L) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (MPair M0 M3) (inv (MPair M1 M2)), @eq Msg (MPair N0 N3) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
apply (H4bis M N H5 (MPair M1 M2) (MPair N1 N2) H6 H7).
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o0 N0) (Mop (inv_op o) N) *)
inversion H.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N0 N3) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
cut (synthesis h (MPair M1 M2) (MPair N1 N2)); try (apply SynPair; trivial).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N0 N3) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
cut (synthesis h (MPair M0 M3) (MPair N0 N3)); try (apply SynPair; trivial).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (MPair N0 N3) (MPair N1 N2) *)
(* Goal: forall _ : @eq Msg (Mop o M) (inv (MPair M1 M2)), @eq Msg (Mop o N) (inv (MPair N1 N2)) *)
(* Goal: forall _ : @eq Msg M0 (inv (Mop o M)), @eq Msg N0 (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
apply (H4bis (MPair M0 M3) (MPair N0 N3) H6 (MPair M1 M2) (MPair N1 N2) H5 H).
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o0 N0) (Mop (inv_op o) N) *)
inversion H.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall _ : @eq Msg M0 (Mop (inv_op o) M), @eq Msg N0 (Mop (inv_op o) N) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
cut (synthesis h M0 N0); try (apply SynInc; trivial).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
cut (synthesis h (Mop (inv_op o) M) (Mop (inv_op o) N));
 try (apply SynOp; trivial).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N0 (Mop (inv_op o) N) *)
(* Goal: forall _ : @eq Msg (MEnc M0 K) (inv (Mop o M)), @eq Msg (MEnc N0 L) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (MPair M1 M2) (inv (Mop o M)), @eq Msg (MPair N1 N2) (inv (Mop o N)) *)
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
apply (H4bis M0 N0 H6 (Mop (inv_op o) M) (Mop (inv_op o) N) H7 H8).
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o0 N0) (Mop (inv_op o) N) *)
inversion H.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o0 N0) (Mop (inv_op o) N) *)
inversion H.
(* Goal: forall _ : @eq Msg (Mop o0 M0) (inv (Mop o M)), @eq Msg (Mop o0 N0) (inv (Mop o N)) *)
simpl in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg (Mop o0 N0) (Mop (inv_op o) N) *)
inversion H.
(* Goal: @eq Msg (Mop (inv_op o) N0) (Mop (inv_op o) N) *)
cut (N0 = N).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: le_h g h *)
rewrite H7; trivial.
(* Goal: @eq Msg N0 N *)
apply (H4bis M0 N0 H6 M N H5 H9).
Qed.

(** the transposition of h is the hedge where all the pairs (M,N) are reversed in (N,M) *)
Definition transpose (h : hedge) (M N : Msg) := h N M.

(** h is consistent if h is left consistent and if (transpose h) is left consistent (h is right consistent) *)
Definition is_consistent (h : hedge) :=
  is_left_consistent h /\ is_left_consistent (transpose h).

Definition no_pairs (h : hedge) :=
  forall M1 M2 N1 N2 : Msg, ~ h (MPair M1 M2) (MPair N1 N2).

Definition no_syn_ops (h : hedge) :=
  forall (o : op) (M N : Msg), h (Mop o M) (Mop o N) -> ~ synthesis h M N.

Definition no_syn_cyph (h : hedge) :=
  forall M N K L : Msg,
  h (MEnc M K) (MEnc N L) -> ~ synthesis h M N \/ ~ synthesis h K L.

Definition cyph_dec (h : hedge) :=
  forall M N K L : Msg,
  h (MEnc M K) (MEnc N L) -> synthesis h (inv K) (inv L) -> synthesis h M N.

(** we show in the following that a hedge is irreducible iff it satisfies these conditions *)
Definition cond_irr (h : hedge) :=
  no_pairs h /\ no_syn_ops h /\ no_syn_cyph h /\ cyph_dec h.

Lemma left_consistent_impl_cond_irr_strong :
 forall h : hedge,
 name_left_name h /\
 injective_left h /\
 op_synthesis_left h /\
 pair_free_left h /\ enc_synthesis_left h /\ enc_analysis_left h ->
 cond_irr h.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: transpose h M N *)
elim H1.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
elim H3.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (fun M N : Msg => h N M) m0 m *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
elim H5.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h M N *)
elim H7.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (h : hedge) (_ : is_irreducible h), cond_irr h *)
unfold cond_irr in |- *.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: no_pairs h *)
(* Goal: and (no_syn_ops h) (and (no_syn_cyph h) (cyph_dec h)) *)
unfold no_pairs in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: not (h (MPair M1 M2) (MPair N1 N2)) *)
(* Goal: and (no_syn_ops h) (and (no_syn_cyph h) (cyph_dec h)) *)
unfold pair_free_left in H6.
(* Goal: not (synthesis h m m1) *)
(* Goal: forall _ : not (synthesis (transpose h) m2 m0), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
red in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: and (no_syn_ops h) (and (no_syn_cyph h) (cyph_dec h)) *)
apply (H6 M1 M2 (MPair N1 N2)).
(* Goal: le_h g h *)
trivial.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: no_syn_ops h *)
(* Goal: and (no_syn_cyph h) (cyph_dec h) *)
unfold op_synthesis_left in H4.
(* Goal: no_syn_ops h *)
(* Goal: and (no_syn_cyph h) (cyph_dec h) *)
unfold no_syn_ops in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
apply (H4 o (Mop o M) (Mop o N)); trivial.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: no_syn_cyph h *)
(* Goal: cyph_dec h *)
unfold no_syn_cyph in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (synthesis h M N)) (not (synthesis h K L)) *)
(* Goal: cyph_dec h *)
unfold enc_synthesis_left in H8.
(* Goal: le_h g h *)
apply (H8 (MEnc M K) (MEnc N L)); trivial.
(* Goal: cyph_dec h *)
unfold cyph_dec in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h M N *)
unfold enc_analysis_left in H9.
(* Goal: synthesis h M N *)
generalize (H9 (MEnc M K) (MEnc N L) H10 M K).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h M N *)
cut (exists N' : Msg, MEnc N L = MEnc N' L /\ synthesis h M N').
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N' (inv N) *)
elim H13.
(* Goal: forall (x : Msg) (_ : and (@eq Msg N (MEnc x L)) (synthesis h M' x)), @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
intro N'.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis h M N *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N L) (MEnc N' L)) (synthesis h M N')) *)
elim H14.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
inversion H15; trivial.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
apply H12; auto.
Qed.

Lemma left_consistent_impl_cond_irr :
 forall h : hedge, is_left_consistent h -> cond_irr h.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: cond_irr h *)
apply left_consistent_impl_cond_irr_strong.
(* Goal: and (name_left_name h) (and (injective_left h) (and (op_synthesis_left h) (and (pair_free_left h) (and (enc_synthesis_left h) (enc_analysis_left h))))) *)
unfold is_left_consistent in H.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** a consistent hedge satisfies the conditions above *)
Lemma consistent_impl_cond_irr :
 forall h : hedge, is_consistent h -> cond_irr h.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : is_consistent h) (_ : le_h g h), is_consistent g *)
unfold is_consistent in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: cond_irr h *)
apply left_consistent_impl_cond_irr.
(* Goal: le_h g h *)
trivial.
Qed.

Lemma cond_irr_impl_le_h_ana :
 forall h : hedge, cond_irr h -> le_h (analysis_def h) h.
(* Goal: forall (h : hedge) (_ : is_irreducible h), cond_irr h *)
unfold cond_irr in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h (transpose g) (transpose h) *)
apply incl_syn_impl_le_h.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
generalize (analysis_is_analysis h).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
elim H0.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
apply H2.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: le_h g h *)
trivial.
(* Goal: forall (h : hedge) (_ : stable_analysis h), stable_analysis (transpose h) *)
unfold stable_analysis in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
induction  H3
 as
  [M N H3| M1 M2 N1 N2 H3 HrecH3| M1 M2 N1 N2 H3 HrecH3| M N K L H3 HrecH3 H4];
(* Goal: le_h g h *)
 trivial.
(* Goal: le_h g h *)
inversion HrecH3; trivial.
(* Goal: and (h (MPair m1 m2) (MPair m m0)) (or (not (synthesis h m1 m)) (not (synthesis h m2 m0))) *)
(* Goal: forall (o : op) (m : Msg) (_ : h (Mop o m) N), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
unfold no_pairs in H.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h M2 N2 *)
(* Goal: synthesis h M N *)
generalize (H7 M1 M2 N1 N2).
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: le_h g h *)
inversion HrecH3; trivial.
(* Goal: and (h (MPair m1 m2) (MPair m m0)) (or (not (synthesis h m1 m)) (not (synthesis h m2 m0))) *)
(* Goal: forall (o : op) (m : Msg) (_ : h (Mop o m) N), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
unfold no_pairs in H.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h M2 N2 *)
(* Goal: synthesis h M N *)
generalize (H7 M1 M2 N1 N2).
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: synthesis h M N *)
generalize (synthesis_idempotent h).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (fun M N : Msg => h N M) m0 m *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
elim H5.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h M N *)
unfold inclusion in H7.
(* Goal: synthesis h M N *)
generalize (H7 (inv K) (inv L) H4).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis h M N *)
unfold cyph_dec in H.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h M N *)
elim H10.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def h M N *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
elim H12.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
inversion HrecH3; trivial.
(* Goal: le_h g h *)
apply (H14 M N K L); trivial.
Qed.

Lemma cond_irr_impl_equiv_h_irr :
 forall h : hedge, cond_irr h -> equiv_h h (irreducible h).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: equiv_h h (irreducible h) *)
apply equiv_h_trans with (analysis_def h).
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: le_h h (analysis_def h) *)
(* Goal: le_h (analysis_def h) h *)
(* Goal: equiv_h (analysis_def h) (irreducible h) *)
apply h_le_h_ana_h.
(* Goal: le_h g h *)
apply cond_irr_impl_le_h_ana; trivial.
(* Goal: equiv_h (analysis_def h) (irreducible h) *)
apply ana_h_equiv_irr_h.
Qed.

(** if h satisfies cond_irr then I(h) is included in h *)
Lemma cond_irr_impl_irr_incl_h :
 forall h : hedge, cond_irr h -> inclusion (irreducible h) h.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (irreducible h) h *)
apply equiv_irr_impl_incl.
(* Goal: equiv_h (reduce h) h *)
(* Goal: equiv_h h (irreducible h) *)
apply equiv_h_sym.
(* Goal: equiv_h h (irreducible h) *)
apply cond_irr_impl_equiv_h_irr.
(* Goal: le_h g h *)
trivial.
(* Goal: is_irreducible (irreducible h) *)
apply irreducible_is_irreducible.
Qed.

Lemma cond_irr_impl_stable_reduce :
 forall h : hedge, cond_irr h -> equal h (reduce h).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: inclusion (reduce (analysis_def h)) (analysis_def h) *)
(* Goal: stable_analysis (analysis_def h) *)
split; try apply red_incl_h.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (M N : Msg) (_ : analysis h N M), analysis (fun M0 N0 : Msg => h N0 M0) M N *)
intros M N.
(* Goal: forall _ : reduce h N M, reduce (fun M N : Msg => h N M) M N *)
unfold reduce in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case M; try tauto.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case N; try tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: not (synthesis h m0 m) *)
(* Goal: forall _ : not (@eq op o0 o), or (not (@eq op o0 o)) (not (synthesis h m0 m)) *)
unfold cond_irr in H.
(* Goal: and (h (MEnc m1 m2) (MEnc m m0)) (or (not (synthesis h m1 m)) (not (synthesis h m2 m0))) *)
(* Goal: forall (m m0 : Msg) (_ : h (MPair m m0) N), and (h (MPair m m0) N) match N with | MNam n => True | MEnc m1 m2 => True | MPair N1 N2 => or (not (synthesis h m N1)) (not (synthesis h m0 N2)) | Mop o m1 => True end *)
(* Goal: forall (o : op) (m : Msg) (_ : h (Mop o m) N), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
unfold no_syn_cyph in H.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
elim H2.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
elim H4.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
split; trivial.
(* Goal: le_h g h *)
apply H5; trivial.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case N; try tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: not (synthesis h m0 m) *)
(* Goal: forall _ : not (@eq op o0 o), or (not (@eq op o0 o)) (not (synthesis h m0 m)) *)
unfold cond_irr in H.
(* Goal: and (h (MPair m1 m2) (MPair m m0)) (or (not (synthesis h m1 m)) (not (synthesis h m2 m0))) *)
(* Goal: forall (o : op) (m : Msg) (_ : h (Mop o m) N), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
unfold no_pairs in H.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (h (MPair m1 m2) (MPair m m0)) (or (not (synthesis h m1 m)) (not (synthesis h m2 m0))) *)
(* Goal: forall (o : op) (m : Msg) (_ : h (Mop o m) N), and (h (Mop o m) N) match N with | MNam n => True | MEnc m0 m1 => True | MPair m0 m1 => True | Mop opN N' => or (not (@eq op o opN)) (not (synthesis h m N')) end *)
generalize (H1 m1 m2 m m0).
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case N; try tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
split; trivial.
(* Goal: or (not (@eq op o0 o)) (not (synthesis h m0 m)) *)
case (op_eq_dec o0 o).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall _ : not (synthesis h m0 m), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
right.
(* Goal: not (synthesis h m0 m) *)
(* Goal: forall _ : not (@eq op o0 o), or (not (@eq op o0 o)) (not (synthesis h m0 m)) *)
rewrite e in H0.
(* Goal: not (synthesis h m0 m) *)
(* Goal: forall _ : not (@eq op o0 o), or (not (@eq op o0 o)) (not (synthesis h m0 m)) *)
unfold cond_irr in H.
(* Goal: not (synthesis h m0 m) *)
(* Goal: forall _ : not (@eq op o0 o), or (not (@eq op o0 o)) (not (synthesis h m0 m)) *)
unfold no_syn_ops in H.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
elim H2; intros.
(* Goal: not (synthesis h m0 m) *)
(* Goal: forall _ : not (@eq op o0 o), or (not (@eq op o0 o)) (not (synthesis h m0 m)) *)
apply (H3 o).
(* Goal: le_h g h *)
trivial.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** if h satisfies cond_irr then h is included in I(h) *)
Lemma cond_irr_impl_h_incl_irr :
 forall h : hedge, cond_irr h -> inclusion h (irreducible h).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion h (irreducible h) *)
apply inclusion_trans with (reduce h).
(* Goal: inclusion h (reduce h) *)
(* Goal: inclusion (reduce h) (irreducible h) *)
generalize (cond_irr_impl_stable_reduce h H).
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
unfold equal in |- *; tauto.
(* Goal: inclusion (reduce h) (irreducible h) *)
apply red_equiv_impl_red_incl.
(* Goal: equiv_h (reduce h) (irreducible h) *)
apply equiv_h_trans with h.
(* Goal: equiv_h (reduce h) h *)
(* Goal: equiv_h h (irreducible h) *)
apply equiv_h_sym.
(* Goal: equiv_h h (reduce h) *)
(* Goal: equiv_h h (irreducible h) *)
apply h_equiv_h_red.
(* Goal: equiv_h h (irreducible h) *)
apply cond_irr_impl_equiv_h_irr.
(* Goal: le_h g h *)
trivial.
Qed.

(** if h satisfies cond_irr then h is irreducible *)
Lemma cond_irr_impl_irreducible :
 forall h : hedge, cond_irr h -> is_irreducible h.
(* Goal: forall (h : hedge) (_ : is_irreducible h), is_irreducible (transpose h) *)
unfold is_irreducible in |- *.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: le_h g h *)
apply cond_irr_impl_h_incl_irr; trivial.
(* Goal: le_h g h *)
apply cond_irr_impl_irr_incl_h; trivial.
Qed.

(** if h is irreducible then h satisfies cond_irr *)
Lemma irreducible_impl_cond_irr :
 forall h : hedge, is_irreducible h -> cond_irr h.
(* Goal: forall (h : hedge) (_ : is_irreducible h), cond_irr h *)
unfold cond_irr in |- *.
(* Goal: forall (h : hedge) (_ : is_irreducible h), is_irreducible (transpose h) *)
unfold is_irreducible in |- *.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: no_pairs h *)
(* Goal: and (no_syn_ops h) (and (no_syn_cyph h) (cyph_dec h)) *)
unfold no_pairs in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: not (synthesis h m m1) *)
(* Goal: forall _ : not (synthesis (transpose h) m2 m0), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
red in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: and (no_syn_ops h) (and (no_syn_cyph h) (cyph_dec h)) *)
apply (irreducible_pair h M1 N1 M2 N2).
(* Goal: le_h g h *)
apply H0; trivial.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: no_syn_ops h *)
(* Goal: and (no_syn_cyph h) (cyph_dec h) *)
unfold no_syn_ops in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: not (synthesis h m m1) *)
(* Goal: forall _ : not (synthesis (transpose h) m2 m0), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
red in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: and (no_syn_cyph h) (cyph_dec h) *)
generalize (irreducible_op h o o M N).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
elim H4.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: False *)
(* Goal: and (no_syn_cyph h) (cyph_dec h) *)
generalize (H0 (Mop o M) (Mop o N) H2).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: and (no_syn_cyph h) (cyph_dec h) *)
generalize (H5 H7).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: and (no_syn_cyph h) (cyph_dec h) *)
elim H8.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: False *)
(* Goal: and (no_syn_cyph h) (cyph_dec h) *)
case H10.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: and (no_syn_cyph h) (cyph_dec h) *)
apply H11.
(* Goal: synthesis (analysis_def h) (inv K) (inv L) *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
generalize (h_le_h_ana_h h).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: no_syn_cyph h *)
(* Goal: cyph_dec h *)
unfold no_syn_cyph in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (synthesis h M N)) (not (synthesis h K L)) *)
(* Goal: cyph_dec h *)
generalize (irreducible_enc h M N K L).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
elim H3.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (synthesis h M N)) (not (synthesis h K L)) *)
(* Goal: cyph_dec h *)
generalize (H4 (H0 (MEnc M K) (MEnc N L) H2)).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: or (not (synthesis h M N)) (not (synthesis h K L)) *)
(* Goal: cyph_dec h *)
elim H6.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (synthesis h M N)) (not (synthesis h K L)) *)
(* Goal: cyph_dec h *)
case H8.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall _ : not (synthesis h m1 m), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall _ : not (synthesis h m2 m0), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis h m0 m))), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
left.
(* Goal: not (synthesis h m m1) *)
(* Goal: forall _ : not (synthesis (transpose h) m2 m0), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
red in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: cyph_dec h *)
apply H9.
(* Goal: synthesis (analysis_def h) (inv K) (inv L) *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
generalize (h_le_h_ana_h h).
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold le_h in |- *; unfold inclusion in |- *; auto.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall _ : not (synthesis h m0 m), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
right.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: False *)
(* Goal: cyph_dec h *)
apply H9.
(* Goal: synthesis (analysis_def h) (inv K) (inv L) *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
generalize (h_le_h_ana_h h).
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold le_h in |- *; unfold inclusion in |- *; auto.
(* Goal: cyph_dec h *)
unfold cyph_dec in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h M N *)
generalize (H0 (MEnc M K) (MEnc N L) H2).
(* Goal: forall h : hedge, equal (irreducible (transpose h)) (transpose (irreducible h)) *)
unfold irreducible in |- *.
(* Goal: forall _ : reduce h N M, reduce (fun M N : Msg => h N M) M N *)
unfold reduce in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
elim H4.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h M N *)
generalize (ana_h_equiv_irr_h h).
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h M N *)
elim H7.
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h M N *)
cut (inclusion (synthesis (irreducible h)) (synthesis h)).
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h M N *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
apply H10.
(* Goal: synthesis (irreducible h) M N *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
unfold inclusion in H8.
(* Goal: synthesis (irreducible h) M N *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
apply H8.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
generalize (analysis_is_analysis h).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg N' (inv N) *)
elim H11.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def h M N *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
elim H12.
(* Goal: forall (h : hedge) (_ : stable_analysis h), stable_analysis (transpose h) *)
unfold stable_analysis in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @ex Nam (fun b : Nam => @eq Msg N (MNam b)) *)
(* Goal: and (injective_left g) (and (op_synthesis_left g) (and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)))) *)
unfold inclusion in H15.
(* Goal: analysis_def h M N *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
apply H15.
(* Goal: analysis (analysis_def h) M N *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
apply (AnaDec (analysis_def h) M N K L).
(* Goal: le_h g h *)
apply AnaInc; trivial.
(* Goal: synthesis (analysis_def h) (inv K) (inv L) *)
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
generalize (h_le_h_ana_h h).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: inclusion (synthesis (irreducible h)) (synthesis h) *)
fold (le_h (irreducible h) h) in |- *.
(* Goal: le_h (irreducible h) h *)
apply inclusion_impl_le_h.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** h is irreducible iff it satisfies cond_irr *)
Theorem irreducible_iff_cond_irr :
 forall h : hedge, cond_irr h <-> is_irreducible h.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: is_irreducible h *)
apply cond_irr_impl_irreducible.
(* Goal: forall _ : is_irreducible h, cond_irr h *)
apply irreducible_impl_cond_irr.
Qed.

(** a consistent hedge is irreducible *)
Theorem consistent_impl_irreducible :
 forall h : hedge, is_consistent h -> is_irreducible h.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: is_irreducible h *)
apply cond_irr_impl_irreducible.
(* Goal: cond_irr h *)
apply consistent_impl_cond_irr.
(* Goal: le_h g h *)
trivial.
Qed.

(** if g ~ h, g is consistent and h is consistent then g = h *)
Theorem equiv_consistent_consistent_equal :
 forall g h : hedge,
 equiv_h g h -> is_consistent g -> is_consistent h -> equal g h.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
apply equiv_irr_irr_impl_equal; try apply consistent_impl_irreducible;
(* Goal: le_h g h *)
 trivial.
Qed.

(** if g is included in h then (transpose g) is included in (transpose h) *)
Lemma inclusion_transpose_inclusion :
 forall g h : hedge, inclusion g h -> inclusion (transpose g) (transpose h).
(* Goal: forall (M N : Msg) (_ : h M N), transpose (analysis_def (transpose h)) M N *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
unfold transpose in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
apply H; trivial.
Qed.

(** if g = h then (transpose g)=(transpose h) *)
Lemma equal_transpose_equal :
 forall g h : hedge, equal g h -> equal (transpose g) (transpose h).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
apply inclusion_transpose_inclusion; tauto.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
apply inclusion_transpose_inclusion; tauto.
Qed.

(** transposition is involutive *)
Lemma transpose_invol : forall h : hedge, equal h (transpose (transpose h)).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (M N : Msg) (_ : h M N), transpose (analysis_def (transpose h)) M N *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
unfold transpose in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** (transpose S(h))=S(transpose h) *)
Lemma synthesis_transpose_transpose_synthesis :
 forall h : hedge, equal (synthesis (transpose h)) (transpose (synthesis h)).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: forall (M N : Msg) (_ : h M N), transpose (analysis_def (transpose h)) M N *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
unfold transpose in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
induction  H
 as
  [M
   N
   H|
   M
   N
   K
   L
   H1
   HrecH1
   H0
   HrecH0|
   M1
   N1
   M2
   N2
   H1
   HrecH1
   H0
   HrecH0|
   o
   M
   N
   H
   HrecH].
(* Goal: le_h g h *)
apply SynInc; trivial.
(* Goal: le_h g h *)
apply SynEnc; trivial.
(* Goal: le_h g h *)
apply SynPair; trivial.
(* Goal: le_h g h *)
apply SynOp; trivial.
(* Goal: forall (M N : Msg) (_ : h M N), transpose (analysis_def (transpose h)) M N *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
unfold transpose in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
induction  H
 as
  [M
   N
   H|
   M
   N
   K
   L
   H1
   HrecH1
   H0
   HrecH0|
   M1
   N1
   M2
   N2
   H1
   HrecH1
   H0
   HrecH0|
   o
   M
   N
   H
   HrecH].
(* Goal: le_h g h *)
apply SynInc; trivial.
(* Goal: le_h g h *)
apply SynEnc; trivial.
(* Goal: le_h g h *)
apply SynPair; trivial.
(* Goal: le_h g h *)
apply SynOp; trivial.
Qed.

(** if g <= h then (transpose g) <= (transpose h) *)
Lemma le_h_transpose_le_h :
 forall g h : hedge, le_h g h -> le_h (transpose g) (transpose h).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h (transpose g) (transpose h) *)
apply incl_syn_impl_le_h.
(* Goal: inclusion (transpose g) (synthesis (transpose h)) *)
apply inclusion_trans with (transpose (synthesis h)).
(* Goal: inclusion (transpose (analysis_def h)) (transpose (transpose (analysis_def (transpose h)))) *)
(* Goal: inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
apply inclusion_transpose_inclusion.
(* Goal: inclusion g (synthesis h) *)
(* Goal: inclusion (transpose (synthesis h)) (synthesis (transpose h)) *)
apply le_h_impl_incl_syn.
(* Goal: le_h g h *)
trivial.
(* Goal: synthesis (fun M N : Msg => h N M) (inv L) (inv K) *)
generalize (synthesis_transpose_transpose_synthesis h).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

Lemma irr_le_h_left_consistent_impl_left_consistent_weak :
 forall g h : hedge,
 is_irreducible g ->
 is_left_consistent h -> le_h g h -> weak_left_consistent g.
(* Goal: forall h : hedge, iff (and (and (name_left_name h) (and (injective_left h) (and (op_synthesis_left h) (and (pair_free_left h) (and (enc_synthesis_left h) (enc_analysis_left h)))))) (injective_inv_left h)) (is_left_consistent h) *)
unfold is_left_consistent in |- *.
(* Goal: forall h : hedge, iff (and (weak_left_consistent h) (injective_inv_left h)) (is_left_consistent h) *)
unfold weak_left_consistent in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
elim H0; intros.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
elim H3; intros.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
elim H5; intros.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
elim H7; intros.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
elim H9; intros.
(* Goal: @eq Msg N' N0 *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
generalize (inj_left_syn h H4 H10 H6 H8).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: name_left_name g *)
(* Goal: and (injective_left g) (and (op_synthesis_left g) (and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)))) *)
unfold name_left_name in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
generalize (le_h_impl_incl_syn g h H1).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex Nam (fun b : Nam => @eq Msg N (MNam b)) *)
(* Goal: and (injective_left g) (and (op_synthesis_left g) (and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)))) *)
unfold inclusion in H15.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
generalize (H15 M N H13).
(* Goal: forall _ : synthesis h M N, @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
rewrite H14.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @ex Nam (fun b : Nam => @eq Msg N (MNam b)) *)
(* Goal: and (injective_left g) (and (op_synthesis_left g) (and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)))) *)
generalize (nam_left_syn h a N H16).
(* Goal: forall _ : h (MNam a) N, @ex Nam (fun b : Nam => @eq Msg N (MNam b)) *)
(* Goal: and (injective_left g) (and (op_synthesis_left g) (and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)))) *)
rewrite <- H14.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex Nam (fun b : Nam => @eq Msg N (MNam b)) *)
(* Goal: and (injective_left g) (and (op_synthesis_left g) (and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)))) *)
unfold name_left_name in H2.
(* Goal: @ex Nam (fun b : Nam => @eq Msg N (MNam b)) *)
(* Goal: and (injective_left g) (and (op_synthesis_left g) (and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)))) *)
apply (H2 M N H17 a H14).
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: forall _ : injective_left (synthesis h), @eq Msg N' N0 *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
unfold injective_left in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
generalize (le_h_impl_incl_syn g h H1).
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
generalize (H16 M N H13).
(* Goal: forall _ : synthesis h M N, @eq Msg N N' *)
(* Goal: and (op_synthesis_left g) (and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g))) *)
generalize (H16 M' N' H14).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg L L0 *)
(* Goal: enc_analysis_left g *)
unfold injective_left in H12.
(* Goal: @eq Msg N N' *)
(* Goal: and (op_synthesis_left g) (and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g))) *)
apply (H12 M N H18 M' N' H17 H15).
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: op_synthesis_left g *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
unfold op_synthesis_left in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
generalize (le_h_impl_incl_syn g h H1).
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
generalize (H15 M N H13).
(* Goal: forall _ : synthesis h M N, @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
rewrite H14.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
inversion H16.
(* Goal: not (synthesis g M' N') *)
(* Goal: not (synthesis g M' N') *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
unfold op_synthesis_left in H6.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
rewrite <- H14 in H17.
(* Goal: not (synthesis g M' N') *)
(* Goal: not (synthesis g M' N') *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
generalize (H6 o M N H17 M' H14).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: not (synthesis h m m1) *)
(* Goal: forall _ : not (synthesis (transpose h) m2 m0), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
red in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: not (synthesis g M' N') *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
apply (H20 N').
(* Goal: @eq Msg N' (inv N) *)
unfold le_h in H1.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold inclusion in H1; auto.
(* Goal: not (synthesis h m m1) *)
(* Goal: forall _ : not (synthesis (transpose h) m2 m0), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
red in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg N' (inv N) *)
unfold le_h in H1.
(* Goal: @eq Msg N' (inv N) *)
unfold inclusion in H1.
(* Goal: False *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
generalize (H1 M' N' H21).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: forall _ : not (synthesis (analysis_def g) K L0), or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
cut (N' = N0).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: @eq Msg N' N0 *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
rewrite <- H23 in H18.
(* Goal: synthesis g M' N0 *)
rewrite H14 in H13.
(* Goal: False *)
(* Goal: @eq Msg N' N0 *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
rewrite <- H18 in H13.
(* Goal: False *)
(* Goal: @eq Msg N' N0 *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
generalize (irreducible_op g).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: False *)
(* Goal: @eq Msg N' N0 *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
elim (H24 o o M' N').
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis g M' N0 *)
unfold is_irreducible in H.
(* Goal: synthesis g M' N0 *)
unfold equal in H.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: False *)
(* Goal: @eq Msg N' N0 *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
generalize (H25 (H27 (Mop o M') (Mop o N') H13)).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: @eq Msg N' N0 *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
elim H29.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case H31; try tauto.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: @eq Msg N' N0 *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
apply H32.
(* Goal: synthesis (irreducible g) M' N0 *)
generalize (h_le_h_ana_h g).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold inclusion in |- *; auto.
(* Goal: @eq Msg N' N0 *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
generalize (inj_left_syn h H4 H10 H6 H8).
(* Goal: forall _ : injective_left (synthesis h), @eq Msg N' N0 *)
(* Goal: and (pair_free_left g) (and (enc_synthesis_left g) (enc_analysis_left g)) *)
unfold injective_left in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
apply (H23 M' N' H22 M' N0 H20); trivial.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: pair_free_left g *)
(* Goal: and (enc_synthesis_left g) (enc_analysis_left g) *)
unfold pair_free_left in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: not (synthesis h m m1) *)
(* Goal: forall _ : not (synthesis (transpose h) m2 m0), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
red in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
generalize (le_h_impl_incl_syn g h H1).
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: False *)
(* Goal: and (enc_synthesis_left g) (enc_analysis_left g) *)
generalize (H14 (MPair M1 M2) N H13).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: and (enc_synthesis_left g) (enc_analysis_left g) *)
inversion H15.
(* Goal: False *)
(* Goal: False *)
(* Goal: and (enc_synthesis_left g) (enc_analysis_left g) *)
unfold pair_free_left in H8.
(* Goal: le_h g h *)
apply (H8 M1 M2 N); trivial.
(* Goal: False *)
(* Goal: and (enc_synthesis_left g) (enc_analysis_left g) *)
rewrite <- H19 in H13.
(* Goal: False *)
(* Goal: and (enc_synthesis_left g) (enc_analysis_left g) *)
generalize (irreducible_pair g M1 N1 M2 N2).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
apply H21.
(* Goal: synthesis g M' N0 *)
unfold is_irreducible in H.
(* Goal: synthesis g M' N0 *)
unfold equal in H.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: enc_synthesis_left g *)
(* Goal: enc_analysis_left g *)
unfold enc_synthesis_left in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
generalize (le_h_impl_incl_syn g h H1).
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
generalize (H15 M N H13).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
rewrite H14 in H16.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
inversion H16.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
rewrite <- H14 in H17.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
unfold enc_synthesis_left in H10.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
generalize (H10 M N H17 M' K H14).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
case (H20 N' L).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall _ : not (synthesis h m1 m), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall _ : not (synthesis h m2 m0), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis h m0 m))), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
left.
(* Goal: not (synthesis h m m1) *)
(* Goal: forall _ : not (synthesis (transpose h) m2 m0), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
red in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
apply H21.
(* Goal: @eq Msg N' (inv N) *)
unfold le_h in H1.
(* Goal: @eq Msg N' (inv N) *)
unfold inclusion in H1.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: forall _ : not (synthesis h m0 m), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
right.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: False *)
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
apply H21.
(* Goal: @eq Msg N' (inv N) *)
unfold le_h in H1.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold inclusion in H1; auto.
(* Goal: synthesis g M' N0 *)
rewrite H14 in H13.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
rewrite <- H20 in H13.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
elim (irreducible_enc g M' N0 K L0).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis g M' N0 *)
unfold is_irreducible in H.
(* Goal: synthesis g M' N0 *)
unfold equal in H.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
elim (H22 (H24 (MEnc M' K) (MEnc N0 L0) H13)).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
case H27.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall _ : not (synthesis h m1 m), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall _ : not (synthesis h m2 m0), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis h m0 m))), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
left.
(* Goal: not (synthesis h m m1) *)
(* Goal: forall _ : not (synthesis (transpose h) m2 m0), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
red in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: forall _ : not (synthesis (analysis_def g) K L0), or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
cut (N' = N0).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: enc_analysis_left g *)
apply H28.
(* Goal: synthesis (analysis_def g) K L0 *)
(* Goal: @eq Msg L L0 *)
(* Goal: enc_analysis_left g *)
rewrite <- H30.
(* Goal: synthesis (irreducible g) M' N0 *)
generalize (h_le_h_ana_h g).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: @eq Msg N' (inv N) *)
unfold le_h in H1.
(* Goal: @eq Msg N' (inv N) *)
unfold inclusion in H1.
(* Goal: @eq Msg N' N0 *)
(* Goal: forall _ : not (synthesis (analysis_def g) K L0), or (not (synthesis g M' N')) (not (synthesis g K L)) *)
(* Goal: enc_analysis_left g *)
generalize (H1 M' N' H29).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg L L0 *)
(* Goal: enc_analysis_left g *)
unfold injective_left in H12.
(* Goal: le_h g h *)
apply (H12 M' N' H30 M' N0 H19); trivial.
(* Goal: forall _ : not (synthesis h m0 m), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
right.
(* Goal: not (synthesis h m m1) *)
(* Goal: forall _ : not (synthesis (transpose h) m2 m0), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
red in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: enc_analysis_left g *)
apply H28.
(* Goal: synthesis g (inv K) (inv L0) *)
cut (L = L0).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis (analysis_def g) K L0 *)
(* Goal: @eq Msg L L0 *)
(* Goal: enc_analysis_left g *)
rewrite <- H30.
(* Goal: synthesis (irreducible g) M' N0 *)
generalize (h_le_h_ana_h g).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold inclusion in |- *; auto.
(* Goal: @eq Msg N' (inv N) *)
unfold le_h in H1.
(* Goal: @eq Msg N' (inv N) *)
unfold inclusion in H1.
(* Goal: @eq Msg L L0 *)
(* Goal: enc_analysis_left g *)
generalize (H1 K L H29).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg L L0 *)
(* Goal: enc_analysis_left g *)
unfold injective_left in H12.
(* Goal: le_h g h *)
apply (H12 K L H30 K L0 H21); trivial.
(* Goal: enc_analysis_left g *)
unfold enc_analysis_left in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
generalize (le_h_impl_incl_syn g h H1).
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
generalize (H16 M N H13).
(* Goal: forall _ : synthesis h M N, @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
rewrite H14.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
inversion H17.
(* Goal: @eq Msg N' (inv N) *)
unfold le_h in H1.
(* Goal: @eq Msg N' (inv N) *)
unfold inclusion in H1.
(* Goal: @eq Msg L L0 *)
(* Goal: synthesis g M' N0 *)
generalize (H1 (inv K) (inv L) H15).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N' (inv N) *)
elim H11.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
unfold enc_analysis_left in H22.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
rewrite <- H14 in H18.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
elim (H22 M N H18 M' K H14 L H21).
(* Goal: forall (x : Msg) (_ : and (@eq Msg N (MEnc x L)) (synthesis h M' x)), @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
intro N'.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg N (MEnc N' L)) (synthesis g M' N')) *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
exists N'.
(* Goal: and (@eq Msg N (MEnc N' L)) (synthesis g M' N') *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
elim H24.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
split; trivial.
(* Goal: synthesis g M' N0 *)
rewrite H14 in H13.
(* Goal: synthesis g M' N' *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
rewrite H25 in H13.
(* Goal: synthesis g M' N' *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
elim (irreducible_enc g M' N' K L).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis g M' N0 *)
unfold is_irreducible in H.
(* Goal: synthesis g M' N0 *)
unfold equal in H.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis g M' N' *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
elim (H27 (H29 (MEnc M' K) (MEnc N' L) H13)).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (irreducible g) M' N0 *)
generalize (ana_h_equiv_irr_h g).
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis g M' N' *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
elim H33.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis g M' N' *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
unfold le_h in H34.
(* Goal: synthesis g M' N' *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
unfold inclusion in H34.
(* Goal: synthesis g M' N0 *)
fold (inclusion (irreducible g) g) in H30.
(* Goal: synthesis g M' N0 *)
generalize (inclusion_impl_le_h (irreducible g) g H30).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis (irreducible g) M' N0 *)
apply H36.
(* Goal: synthesis (irreducible g) M' N' *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
apply H34.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: analysis_def g M' N0 *)
generalize (analysis_is_analysis g).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def g M' N' *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
elim H37.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def g M' N0 *)
elim H38.
(* Goal: forall (h : hedge) (_ : stable_analysis h), stable_analysis (transpose h) *)
unfold stable_analysis in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def g M' N' *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
apply H41.
(* Goal: analysis (analysis_def g) M' N' *)
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
apply (AnaDec (analysis_def g) M' N' K L).
(* Goal: le_h g h *)
apply AnaInc; trivial.
(* Goal: synthesis (irreducible g) M' N0 *)
generalize (h_le_h_ana_h g).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
unfold inclusion in |- *; auto.
(* Goal: @ex Msg (fun N' : Msg => and (@eq Msg (MEnc N0 L0) (MEnc N' L)) (synthesis g M' N')) *)
exists N0.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: synthesis g (inv K) (inv L0) *)
cut (L = L0).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: le_h g h *)
rewrite H23; trivial.
(* Goal: @eq Msg N' (inv N) *)
unfold le_h in H1.
(* Goal: @eq Msg N' (inv N) *)
unfold inclusion in H1.
(* Goal: @eq Msg L L0 *)
(* Goal: synthesis g M' N0 *)
generalize (H1 (inv K) (inv L) H15).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
elim H11; intros.
(* Goal: @eq Msg L L0 *)
(* Goal: synthesis g M' N0 *)
generalize (inj_inv_left_syn h H4 H10 H6 H8 H25).
(* Goal: forall _ : injective_inv_left (synthesis h), @eq Msg N' (inv N) *)
unfold injective_inv_left in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg L L0 *)
(* Goal: synthesis g M' N0 *)
generalize (H26 K L0 H22 (inv K) (inv L) H23).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
cut (inv K = inv K); trivial.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg L L0 *)
(* Goal: synthesis g M' N0 *)
generalize (H27 H28).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg L L0 *)
(* Goal: synthesis g M' N0 *)
cut (inv (inv L) = inv (inv L0)).
(* Goal: forall _ : @eq Msg L (inv (inv L0)), @eq Msg L L0 *)
(* Goal: @eq Msg (inv (inv L)) (inv (inv L0)) *)
(* Goal: synthesis g M' N0 *)
rewrite inv_invol.
(* Goal: forall _ : @eq Msg L (inv (inv L0)), @eq Msg L L0 *)
(* Goal: @eq Msg (inv (inv L)) (inv (inv L0)) *)
(* Goal: synthesis g M' N0 *)
rewrite inv_invol.
(* Goal: le_h g h *)
trivial.
(* Goal: le_h g h *)
rewrite H29; trivial.
(* Goal: synthesis g M' N0 *)
generalize H.
(* Goal: forall (h : hedge) (_ : is_irreducible h), is_irreducible (transpose h) *)
unfold is_irreducible in |- *.
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis g M' N0 *)
elim H23.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis g M' N0 *)
rewrite H14 in H13. 
(* Goal: synthesis g M' N0 *)
rewrite <- H21 in H13.
(* Goal: synthesis g M' N0 *)
generalize (irreducible_enc g).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis g M' N0 *)
elim (H26 M' N0 K L0).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis g M' N0 *)
unfold is_irreducible in H.
(* Goal: synthesis g M' N0 *)
unfold equal in H.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis g M' N0 *)
elim (H27 (H29 (MEnc M' K) (MEnc N0 L0) H13)).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis g M' N0 *)
fold (inclusion (irreducible g) g) in H30.
(* Goal: synthesis g M' N0 *)
generalize (inclusion_impl_le_h (irreducible g) g H30).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis g M' N0 *)
apply H33.
(* Goal: synthesis (irreducible g) M' N0 *)
generalize (h_le_h_ana_h g).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (irreducible g) M' N0 *)
generalize (ana_h_equiv_irr_h g).
(* Goal: forall _ : equiv_h (analysis_def g) (irreducible g), synthesis (irreducible g) M' N0 *)
unfold equiv_h in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis (irreducible g) M' N0 *)
elim H35.
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (irreducible g) M' N0 *)
apply H36.
(* Goal: synthesis (analysis_def g) M' N0 *)
apply SynInc.
(* Goal: analysis_def g M' N0 *)
generalize (analysis_is_analysis g).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def g M' N0 *)
elim H38.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def g M' N0 *)
elim H39.
(* Goal: forall (h : hedge) (_ : stable_analysis h), stable_analysis (transpose h) *)
unfold stable_analysis in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def g M' N0 *)
apply H42.
(* Goal: analysis (analysis_def g) M' N0 *)
apply (AnaDec (analysis_def g) M' N0 K L0).
(* Goal: le_h g h *)
apply AnaInc; trivial.
(* Goal: synthesis (analysis_def g) (inv K) (inv L0) *)
apply H37.
(* Goal: synthesis (irreducible g) (inv K) (inv L0) *)
fold (inclusion g (irreducible g)) in H29.
(* Goal: synthesis (irreducible g) (inv K) (inv L0) *)
generalize (inclusion_impl_le_h g (irreducible g) H29).
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (irreducible g) (inv K) (inv L0) *)
apply H43.
(* Goal: synthesis g (inv K) (inv L0) *)
cut (L = L0).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis g (inv K) (inv L0) *)
(* Goal: @eq Msg L L0 *)
rewrite <- H44.
(* Goal: le_h g h *)
trivial.
(* Goal: match N with | MNam n => True | MEnc M' K => match M with | MNam n => True | MEnc N' L => or (not (synthesis h M' N')) (not (synthesis h K L)) | MPair m m0 => True | Mop o m => True end | MPair M1 M2 => match M with | MNam n => True | MEnc m m0 => True | MPair N1 N2 => or (not (synthesis h M1 N1)) (not (synthesis h M2 N2)) | Mop o m => True end | Mop opM M' => match M with | MNam n => True | MEnc m m0 => True | MPair m m0 => True | Mop opN N' => or (not (@eq op opM opN)) (not (synthesis h M' N')) end end *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
generalize H1.
(* Goal: forall _ : le_h g h, @eq Msg L L0 *)
unfold le_h in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg L L0 *)
generalize (H44 (inv K) (inv L) H15).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N' (inv N) *)
elim H11.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg L L0 *)
generalize (inj_inv_left_syn h H4 H10 H6 H8 H47).
(* Goal: forall _ : injective_inv_left (synthesis h), @eq Msg N' (inv N) *)
unfold injective_inv_left in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg L L0 *)
generalize (H48 K L0 H22 (inv K) (inv L) H45).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: le_h g h *)
cut (inv K = inv K); trivial.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg L L0 *)
generalize (H49 H50).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg L L0 *)
rewrite <- inv_invol.
(* Goal: @eq Msg L (inv (inv L0)) *)
rewrite <- H51.
symmetry  in |- *.
(* Goal: @eq Msg (inv (inv L)) L *)
apply inv_invol.
Qed.

Lemma weak_left_consistent_inj_inv_left_iff_left_consistent :
 forall h : hedge,
 weak_left_consistent h /\ injective_inv_left h <-> is_left_consistent h.
(* Goal: forall h : hedge, iff (and (weak_left_consistent h) (injective_inv_left h)) (is_left_consistent h) *)
unfold weak_left_consistent in |- *.
(* Goal: forall h : hedge, iff (and (and (name_left_name h) (and (injective_left h) (and (op_synthesis_left h) (and (pair_free_left h) (and (enc_synthesis_left h) (enc_analysis_left h)))))) (injective_inv_left h)) (is_left_consistent h) *)
unfold is_left_consistent in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** if g <= h, g is irreducible and h is left consistent then g is left consistent *)
Theorem irr_le_h_left_consistent_impl_left_consistent :
 forall g h : hedge,
 is_irreducible g -> is_left_consistent h -> le_h g h -> is_left_consistent g.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: is_left_consistent g *)
generalize (irr_le_h_left_consistent_impl_left_consistent_weak g h H H0 H1).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: is_left_consistent g *)
elim (weak_left_consistent_inj_inv_left_iff_left_consistent g).
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: False *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H3.
(* Goal: le_h g h *)
split; trivial.
(* Goal: forall _ : injective_inv_left (synthesis h), @eq Msg N' (inv N) *)
unfold injective_inv_left in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg N' (inv N) *)
unfold is_left_consistent in H0.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
elim H0.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg N' (inv N) *)
elim H9.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg N' (inv N) *)
elim H11.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg N' (inv N) *)
elim H13.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg N' (inv N) *)
elim H15.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg N' (inv N) *)
unfold le_h in H1.
(* Goal: @eq Msg N' (inv N) *)
unfold inclusion in H1.
(* Goal: @eq Msg N' (inv N) *)
generalize (H1 M N (SynInc g M N H5)).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N' (inv N) *)
generalize (H1 M' N' (SynInc g M' N' H6)).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: @eq Msg N' (inv N) *)
elim H17.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg N' (inv N) *)
generalize (inj_inv_left_syn h H10 H16 H12 H14 H21).
(* Goal: forall _ : injective_inv_left (synthesis h), @eq Msg N' (inv N) *)
unfold injective_inv_left in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: @eq Msg N' (inv N) *)
apply (H22 M N H18 M' N' H19 H7).
Qed.

(** some lemma about transposition and operation on hedges *)
Lemma reduce_transpose_transpose_reduce :
 forall h : hedge, equal (reduce (transpose h)) (transpose (reduce h)).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (M N : Msg) (_ : h M N), transpose (analysis_def (transpose h)) M N *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
unfold transpose in |- *.
(* Goal: forall (M N : Msg) (_ : analysis h N M), analysis (fun M0 N0 : Msg => h N0 M0) M N *)
intros M N.
(* Goal: forall _ : reduce h N M, reduce (fun M N : Msg => h N M) M N *)
unfold reduce in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: le_h g h *)
trivial.
(* Goal: match N with | MNam n => True | MEnc M' K => match M with | MNam n => True | MEnc N' L => or (not (synthesis h M' N')) (not (synthesis h K L)) | MPair m m0 => True | Mop o m => True end | MPair M1 M2 => match M with | MNam n => True | MEnc m m0 => True | MPair N1 N2 => or (not (synthesis h M1 N1)) (not (synthesis h M2 N2)) | Mop o m => True end | Mop opM M' => match M with | MNam n => True | MEnc m m0 => True | MPair m m0 => True | Mop opN N' => or (not (@eq op opM opN)) (not (synthesis h M' N')) end end *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
generalize H1.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case M; try tauto; case N; try tauto.
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
fold (transpose h) in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
case H2.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall _ : not (synthesis h m1 m), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall _ : not (synthesis h m2 m0), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis h m0 m))), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
left.
(* Goal: not (synthesis h m m1) *)
(* Goal: forall _ : not (synthesis (transpose h) m2 m0), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (m m0 m1 m2 : Msg) (_ : or (not (synthesis (fun M N : Msg => h N M) m1 m)) (not (synthesis (fun M N : Msg => h N M) m2 m0))), or (not (synthesis h m m1)) (not (synthesis h m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis (fun M N : Msg => h N M) m0 m))), or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
red in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: False *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H3.
(* Goal: synthesis (fun M N : Msg => h N M) (inv L) (inv K) *)
generalize (synthesis_transpose_transpose_synthesis h).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (fun M N : Msg => h N M) m0 m *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
elim H5.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (fun M N : Msg => h N M) m0 m *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H7.
(* Goal: forall (M N : Msg) (_ : h M N), transpose (analysis_def (transpose h)) M N *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
unfold transpose in |- *.
(* Goal: le_h g h *)
trivial.
(* Goal: forall _ : not (synthesis h m0 m), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
right.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: False *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H3.
(* Goal: synthesis (fun M N : Msg => h N M) (inv L) (inv K) *)
generalize (synthesis_transpose_transpose_synthesis h).
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold equal in |- *; unfold inclusion in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis (fun M N : Msg => h N M) m0 m *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
elim H5.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (fun M N : Msg => h N M) m0 m *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H7.
(* Goal: le_h g h *)
unfold transpose in |- *; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
case H2.
(* Goal: forall _ : not (synthesis h m1 m), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall _ : not (synthesis h m2 m0), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis h m0 m))), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
left.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: synthesis (fun M N : Msg => h N M) (inv L) (inv K) *)
generalize (synthesis_transpose_transpose_synthesis h).
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold equal in |- *; unfold inclusion in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
elim H5; intros.
(* Goal: False *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H3.
(* Goal: synthesis (fun M N : Msg => h N M) m0 m *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H7.
(* Goal: le_h g h *)
unfold transpose in |- *; trivial.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall _ : not (synthesis h m0 m), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
right.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: False *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H3.
(* Goal: synthesis (fun M N : Msg => h N M) (inv L) (inv K) *)
generalize (synthesis_transpose_transpose_synthesis h).
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold equal in |- *; unfold inclusion in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
elim H5; intros.
(* Goal: synthesis (fun M N : Msg => h N M) m0 m *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H7.
(* Goal: le_h g h *)
unfold transpose in |- *; trivial.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (@eq op o o0)) (not (synthesis h m m0)) *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
case H2.
(* Goal: forall _ : not (synthesis h m1 m), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall _ : not (synthesis h m2 m0), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis h m0 m))), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
left.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: False *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H3.
(* Goal: le_h g h *)
rewrite H4; trivial.
(* Goal: forall _ : not (synthesis h m0 m), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
right.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: False *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H3.
(* Goal: synthesis (fun M N : Msg => h N M) (inv L) (inv K) *)
generalize (synthesis_transpose_transpose_synthesis h).
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold equal in |- *; unfold inclusion in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis (fun M N : Msg => h N M) m0 m *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
elim H5.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (fun M N : Msg => h N M) m0 m *)
(* Goal: inclusion (transpose (reduce h)) (reduce (transpose h)) *)
apply H7.
(* Goal: le_h g h *)
unfold transpose in |- *; trivial.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (M N : Msg) (_ : analysis h N M), analysis (fun M0 N0 : Msg => h N0 M0) M N *)
intros M N.
(* Goal: forall (M N : Msg) (_ : h M N), transpose (analysis_def (transpose h)) M N *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
unfold transpose in |- *.
(* Goal: forall _ : reduce h N M, reduce (fun M N : Msg => h N M) M N *)
unfold reduce in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
split; try tauto.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis (fun M N : Msg => h N M) (inv L) (inv K) *)
generalize (synthesis_transpose_transpose_synthesis h).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: transpose h M N *)
elim H1.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: synthesis h (inv L) (inv K) *)
(* Goal: forall (M N : Msg) (_ : analysis h N M), analysis (fun M0 N0 : Msg => h N0 M0) M N *)
unfold transpose in H2.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
case N; try tauto; case M; try tauto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
case H4.
(* Goal: forall _ : not (synthesis h m1 m), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall _ : not (synthesis h m2 m0), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis h m0 m))), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
left.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: analysis_def (fun M N : Msg => h N M) N M *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
apply H5.
(* Goal: le_h g h *)
apply H2; trivial.
(* Goal: forall _ : not (synthesis h m0 m), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
right.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: analysis_def (fun M N : Msg => h N M) N M *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
apply H5.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
case H4.
(* Goal: forall _ : not (synthesis h m1 m), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall _ : not (synthesis h m2 m0), or (not (synthesis (fun M N : Msg => h N M) m m1)) (not (synthesis (fun M N : Msg => h N M) m0 m2)) *)
(* Goal: forall (o : op) (m : Msg) (o0 : op) (m0 : Msg) (_ : or (not (@eq op o0 o)) (not (synthesis h m0 m))), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
left.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
apply H5; auto.
(* Goal: forall _ : not (synthesis h m0 m), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
right.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: analysis_def (fun M N : Msg => h N M) N M *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
apply H5.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
case H4.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
left; auto.
(* Goal: forall _ : not (synthesis h m0 m), or (not (@eq op o o0)) (not (synthesis (fun M N : Msg => h N M) m m0)) *)
right.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
red in |- *; intro.
(* Goal: analysis_def (fun M N : Msg => h N M) N M *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
apply H5.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
Qed.

Lemma analysis_transpose_transpose_analysis :
 forall h : hedge, equal (analysis (transpose h)) (transpose (analysis h)).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: forall (M N : Msg) (_ : h M N), transpose (analysis_def (transpose h)) M N *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
unfold transpose in |- *.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: forall (M N : Msg) (_ : analysis h N M), analysis (fun M0 N0 : Msg => h N0 M0) M N *)
intros M N.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
induction  H
 as [M N H| M1 M2 N1 N2 H HrecH| M1 M2 N1 N2 H HrecH| M N K L H HrecH H0].
(* Goal: le_h g h *)
apply AnaInc; trivial.
(* Goal: analysis h N1 M1 *)
(* Goal: analysis h N2 M2 *)
(* Goal: analysis h N M *)
(* Goal: forall (M N : Msg) (_ : analysis h N M), analysis (fun M0 N0 : Msg => h N0 M0) M N *)
apply (AnaSplitL h N1 N2 M1 M2).
(* Goal: le_h g h *)
trivial.
(* Goal: analysis h N2 M2 *)
(* Goal: analysis h N M *)
(* Goal: forall (M N : Msg) (_ : analysis h N M), analysis (fun M0 N0 : Msg => h N0 M0) M N *)
apply (AnaSplitR h N1 N2 M1 M2).
(* Goal: le_h g h *)
trivial.
(* Goal: analysis h N M *)
(* Goal: forall (M N : Msg) (_ : analysis h N M), analysis (fun M0 N0 : Msg => h N0 M0) M N *)
apply (AnaDec h N M L K).
(* Goal: le_h g h *)
trivial.
(* Goal: synthesis (fun M N : Msg => h N M) (inv L) (inv K) *)
generalize (synthesis_transpose_transpose_synthesis h).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: transpose h M N *)
elim H1.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis h (inv L) (inv K) *)
(* Goal: forall (M N : Msg) (_ : analysis h N M), analysis (fun M0 N0 : Msg => h N0 M0) M N *)
unfold transpose in H2.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: forall (M N : Msg) (_ : analysis h N M), analysis (fun M0 N0 : Msg => h N0 M0) M N *)
intros M N.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
induction  H
 as [M N H| M1 M2 N1 N2 H HrecH| M1 M2 N1 N2 H HrecH| M N K L H HrecH H0].
(* Goal: le_h g h *)
apply AnaInc; trivial.
(* Goal: le_h g h *)
apply (AnaSplitL (fun M N : Msg => h N M) N1 N2 M1 M2); trivial.
(* Goal: le_h g h *)
apply (AnaSplitR (fun M N : Msg => h N M) N1 N2 M1 M2); trivial.
(* Goal: le_h g h *)
apply (AnaDec (fun M N : Msg => h N M) N M L K); trivial.
(* Goal: synthesis (fun M N : Msg => h N M) (inv L) (inv K) *)
generalize (synthesis_transpose_transpose_synthesis h).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: transpose h M N *)
elim H1.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: synthesis (fun M N : Msg => h N M) (inv L) (inv K) *)
unfold transpose in H3.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
Qed.

Lemma stable_impl_transpose_stable :
 forall h : hedge, stable_analysis h -> stable_analysis (transpose h).
(* Goal: forall (h : hedge) (_ : stable_analysis h), stable_analysis (transpose h) *)
unfold stable_analysis in |- *.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: transpose h M N *)
generalize (analysis_transpose_transpose_analysis h).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: transpose h M N *)
elim H1.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: transpose h M N *)
generalize (H2 M N H0).
(* Goal: forall (M N : Msg) (_ : h M N), transpose (analysis_def (transpose h)) M N *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
unfold transpose in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
Qed.

Lemma ana_transpose_incl_transpose_ana :
 forall h : hedge,
 inclusion (analysis_def (transpose h)) (transpose (analysis_def h)).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
generalize (analysis_is_analysis (transpose h)).
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
generalize (analysis_is_analysis h).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
elim H0.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
apply H2.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (M N : Msg) (_ : h M N), transpose (analysis_def (transpose h)) M N *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
unfold transpose in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
elim H4.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (_ : forall (M N : Msg) (_ : h M N), analysis_def h M N) (_ : stable_analysis (analysis_def h)), analysis_def h N M *)
(* Goal: stable_analysis (transpose (analysis_def h)) *)
auto.
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
apply stable_impl_transpose_stable.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

Lemma transpose_ana_transpose_incl_ana :
 forall h : hedge,
 inclusion (transpose (analysis_def (transpose h))) (analysis_def h).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion (transpose (analysis_def (transpose h))) (analysis_def h) *)
apply inclusion_trans with (transpose (transpose (analysis_def h))).
(* Goal: inclusion (transpose (analysis_def h)) (transpose (transpose (analysis_def (transpose h)))) *)
(* Goal: inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
apply inclusion_transpose_inclusion.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
(* Goal: inclusion (transpose (analysis_def h)) (analysis_def (transpose h)) *)
apply ana_transpose_incl_transpose_ana.
(* Goal: inclusion (transpose (transpose (analysis_def h))) (analysis_def h) *)
generalize (transpose_invol (analysis_def h)).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

Lemma ana_incl_transpose_ana_transpose :
 forall h : hedge,
 inclusion (analysis_def h) (transpose (analysis_def (transpose h))).
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
generalize (analysis_is_analysis h).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
elim H.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
apply H1.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
generalize (analysis_is_analysis (transpose h)).
(* Goal: forall _ : is_analysis (transpose h) (analysis_def (transpose h)), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold is_analysis in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
elim H2.
(* Goal: forall (_ : analysis_cond (transpose h) (analysis_def (transpose h))) (_ : forall (h' : hedge) (_ : analysis_cond (transpose h) h'), inclusion (analysis_def (transpose h)) h'), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold analysis_cond in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
elim H3.
(* Goal: forall (_ : inclusion (transpose h) (analysis_def (transpose h))) (_ : stable_analysis (analysis_def (transpose h))), and (inclusion h (transpose (analysis_def (transpose h)))) (stable_analysis (transpose (analysis_def (transpose h)))) *)
unfold inclusion in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: forall (M N : Msg) (_ : h M N), transpose (analysis_def (transpose h)) M N *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
unfold transpose in |- *.
(* Goal: forall (M N : Msg) (_ : h M N), analysis_def (fun M0 N0 : Msg => h N0 M0) N M *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
unfold transpose in H5.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: analysis_def (fun M N : Msg => h N M) N M *)
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
apply H5.
(* Goal: le_h g h *)
trivial.
(* Goal: stable_analysis (transpose (analysis_def (transpose h))) *)
apply stable_impl_transpose_stable.
(* Goal: le_h g h *)
trivial.
Qed.

(** A(transpose h)=transpose A(h) *)
Lemma ana_transpose_transpose_ana :
 forall h : hedge,
 equal (analysis_def (transpose h)) (transpose (analysis_def h)).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: inclusion (analysis_def (transpose h)) (transpose (analysis_def h)) *)
(* Goal: inclusion (transpose (analysis_def h)) (analysis_def (transpose h)) *)
apply ana_transpose_incl_transpose_ana.
apply
 inclusion_trans with (transpose (transpose (analysis_def (transpose h)))).
(* Goal: inclusion (transpose (analysis_def h)) (transpose (transpose (analysis_def (transpose h)))) *)
(* Goal: inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
apply inclusion_transpose_inclusion.
(* Goal: inclusion (analysis_def h) (transpose (analysis_def (transpose h))) *)
(* Goal: inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
apply ana_incl_transpose_ana_transpose.
(* Goal: inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
generalize (transpose_invol (analysis_def (transpose h))).
(* Goal: forall _ : equal (analysis_def (transpose h)) (transpose (transpose (analysis_def (transpose h)))), inclusion (transpose (transpose (analysis_def (transpose h)))) (analysis_def (transpose h)) *)
unfold equal in |- *.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
Qed.

(** I(transpose h)=transpose I(h) *)
Lemma irr_transpose_transpose_irr :
 forall h : hedge,
 equal (irreducible (transpose h)) (transpose (irreducible h)).
(* Goal: forall h : hedge, equal (irreducible (transpose h)) (transpose (irreducible h)) *)
unfold irreducible in |- *.
(* Goal: forall h : hedge, equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
intro.
(* Goal: equal (reduce (analysis_def (transpose h))) (transpose (reduce (analysis_def h))) *)
apply equal_trans with (reduce (transpose (analysis_def h))).
(* Goal: equal (reduce (analysis_def (transpose h))) (reduce (transpose (analysis_def h))) *)
(* Goal: equal (reduce (transpose (analysis_def h))) (transpose (reduce (analysis_def h))) *)
apply equal_reduce_equal.
(* Goal: equal (analysis_def (transpose h)) (transpose (analysis_def h)) *)
(* Goal: equal (reduce (transpose (analysis_def h))) (transpose (reduce (analysis_def h))) *)
apply ana_transpose_transpose_ana.
(* Goal: equal (reduce (transpose (analysis_def h))) (transpose (reduce (analysis_def h))) *)
apply reduce_transpose_transpose_reduce.
Qed.

(** if h is irreducible then (transpose h) is irreducible *)
Lemma is_irreducible_transpose_is_irreducible :
 forall h : hedge, is_irreducible h -> is_irreducible (transpose h).
(* Goal: forall (h : hedge) (_ : is_irreducible h), is_irreducible (transpose h) *)
unfold is_irreducible in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: equal (transpose h) (irreducible (transpose h)) *)
apply equal_trans with (transpose (irreducible h)).
(* Goal: equal (transpose h) (transpose (irreducible h)) *)
(* Goal: equal (transpose (irreducible h)) (irreducible (transpose h)) *)
apply equal_transpose_equal.
(* Goal: le_h g h *)
trivial.
(* Goal: equal (transpose (irreducible h)) (irreducible (transpose h)) *)
apply equal_sym.
(* Goal: equal (irreducible (transpose h)) (transpose (irreducible h)) *)
apply irr_transpose_transpose_irr.
Qed.

(** if g <= h, g is irreducible and h is consistent then g is consistent *)
Theorem irr_le_h_consistent_impl_consistent :
 forall g h : hedge,
 is_irreducible g -> is_consistent h -> le_h g h -> is_consistent g.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : is_consistent h) (_ : le_h g h), is_consistent g *)
unfold is_consistent in |- *.
(* Goal: forall (g h : hedge) (_ : is_irreducible g) (_ : and (is_left_consistent h) (is_left_consistent (transpose h))) (_ : le_h g h), and (is_left_consistent g) (is_left_consistent (transpose g)) *)
intros.
(* Goal: and (is_left_consistent g) (is_left_consistent (transpose g)) *)
split.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
apply irr_le_h_left_consistent_impl_left_consistent with h; tauto.
(* Goal: is_left_consistent (transpose g) *)
apply irr_le_h_left_consistent_impl_left_consistent with (transpose h).
(* Goal: le_h g h *)
apply is_irreducible_transpose_is_irreducible; trivial.
(* Goal: is_left_consistent (transpose h) *)
(* Goal: le_h (transpose g) (transpose h) *)
tauto.
(* Goal: le_h (transpose g) (transpose h) *)
apply le_h_transpose_le_h.
(* Goal: le_h g h *)
trivial.
Qed.
