(* File: In_NGamma.v  (last edited on 27/10/2000) (c) Klaus Weich  *)
(*******************************************************************)
(* The left hand side Gamma of a sequent consists of               *)
(*     work : a list of (arbitray) normalforms                     *)
(*            (to be inserted in the following structures)         *)
(*     ds: a list of disjunctions                                  *)
(*     ni: a list of decorated and undecorated nested implications *)
(*     ai: an AVL tree of atomic implications                      *)
(*     a: an AVL tree of atoms                                     *)
(*******************************************************************)
Require Export Kripke_Trees.
Require Export Normal_Forms.
(************************************************************)
(* disjunctions are stored as pairs of Int's                *)
Definition disj := (Int * Int)%type.
Definition disjs := list disj.
Definition DNil := nil (A:=disj).
Definition disj2form (x : disj) :=
match x with
| (i, j) => OrF (Atom i) (Atom j)
end.
Definition disj2nform (x : disj) := match x with
| (i, j) => NDisj i j
end.
Definition disjs2forms (ds : disjs) := map disj2form ds.
Definition disjs2nforms (ds : disjs) := map disj2nform ds.
(*****************************************************************)
(* Nested implications are stored either as a nimp or as a       *)
(* nimp and a counter-model                                      *)
Inductive nested_imp : Set :=
| Undecorated : nimp -> nested_imp
| Decorated : nimp -> kripke_tree -> nested_imp.
Definition nested_imp2nimp (ni : nested_imp) :=
match ni with
| Undecorated ni => ni
| Decorated ni _ => ni
end.
Definition nested_imp2form (x : nested_imp) := nimp2form (nested_imp2nimp x).
Definition nested_imp2nform (x : nested_imp) := NImp_NF (nested_imp2nimp x).
Definition nested_imps := list nested_imp.
Definition NNil := nil (A:=nested_imp).
Definition nested_imps2forms (ni : nested_imps) := map nested_imp2form ni.
Definition nested_imps2nforms (ni : nested_imps) := map nested_imp2nform ni.
Definition nested_imps2nimps (ni : nested_imps) := map nested_imp2nimp ni.
intros ni1 ni2.
elim ni1; clear ni1.
simpl in |- *; trivial.
intros x ni1 ih.
simpl in |- *.
rewrite ih; trivial.
Qed.
intros ni; elim ni; clear ni.
simpl in |- *; trivial.
intros x ni ih.
simpl in |- *.
rewrite ih; trivial.
Qed.
(************************************************************************)
(* Atomic implactions are stored in AVL Trees ai over lists of normal   *)
(* clauses.                                                             *)
(* For the node with the key field=i and with the data field=bs,        *)
(* we define that, for each b in bs, (Imp (Atom i) b) is in ai.         *)
Definition atomic_imps := AVL nf_list.
Definition AI_Nil := AVL_NIL nf_list.
(************************************************************************)
(* Atoms are stored in AVL Trees ai over unit.                          *)
(* For the node with the key field=i,                                   *)
(* we define that (Atom i) is in ai.                                    *)
(* (Definition in Kripke_Trees.v                                        *)
(************************************************************************)
(* The formulae on the left-hand side of the sequent are given by:      *)
Inductive in_ngamma (work : nf_list) (ds : disjs) (ni : nested_imps)
(ai : atomic_imps) (a : atoms) : normal_form -> Set :=
| In_Work :
forall (n : nat) (c : normal_form),
my_nth normal_form n work c -> in_ngamma work ds ni ai a c
| In_Disjs :
forall (n : nat) (i j : Int),
my_nth disj n ds (i, j) -> in_ngamma work ds ni ai a (NDisj i j)
| In_Nested_Imps :
forall (n : nat) (x : nimp),
my_nth nimp n (nested_imps2nimps ni) x ->
in_ngamma work ds ni ai a (NImp_NF x)
| In_Atomic_Imps :
forall (i : Int) (b : normal_form) (n : nat) (bs : nf_list),
LOOKUP nf_list i ai bs ->
my_nth normal_form n bs b -> in_ngamma work ds ni ai a (AImp i b)
| In_Atoms :
forall i : Int,
LOOKUP unit i a tt -> in_ngamma work ds ni ai a (NAtom i).
(********************************************************************)
intros c0 work ds ni ai a c in_ngamma0.
elim in_ngamma0; clear in_ngamma0 c.
intros n a0 nth; apply In_Work with (S n); apply My_NthS; assumption.
intros n i j nth; apply In_Disjs with n; assumption.
intros n x nth; apply In_Nested_Imps with n; assumption.
intros i b n bs lookup nth; apply In_Atomic_Imps with n bs; assumption.
intros i lookup; apply In_Atoms; assumption.
Qed.
intros c work ds ni ai a.
apply In_Work with 0.
apply My_NthO.
Qed.
intros bs work ds ni ai a c in_ngamma0.
elim in_ngamma0; clear in_ngamma0 c.
intros n c0 nth.
apply In_Work with (length bs + n); apply nth_app1; assumption.
intros n i j nth; apply In_Disjs with n; assumption.
intros n x nth; apply In_Nested_Imps with n; assumption.
intros i b n bs' lookup nth; apply In_Atomic_Imps with n bs'; assumption.
intros i lookup; apply In_Atoms; assumption.
Qed.
intros bs work ds ni ai a c in_ngamma0.
elim in_ngamma0; clear in_ngamma0 c.
intros n c0 nth.
elim (inv_nth_app normal_form n bs work c0 nth); clear nth.
intros nth0; right; exists n; assumption.
intros n' nth1; left; apply In_Work with n'; assumption.
intros n i j nth; left; apply In_Disjs with n; assumption.
intros n x nth; left; apply In_Nested_Imps with n; assumption.
intros i b n bs' lookup nth; left; apply In_Atomic_Imps with n bs';
assumption.
intros i lookup; left; apply In_Atoms; assumption.
Qed.
intros c0 work ds ni ai a c in_ngamma0.
elim in_ngamma0; clear in_ngamma0 c.
intros n; case n; clear n.
intros a0 nth; right; inversion_clear nth; trivial.
intros n c1 nth; left; apply In_Work with n; inversion_clear nth; assumption.
intros n i j nth; left; apply In_Disjs with n; assumption.
intros n x nth; left; apply In_Nested_Imps with n; assumption.
intros i b n bs lookup nth; left; apply In_Atomic_Imps with n bs; assumption.
intros i lookup; left; apply In_Atoms; assumption.
Qed.
intros work i j ds ni ai a c in_ngamma0.
elim in_ngamma0; clear in_ngamma0 c.
intros n c0 nth; apply In_Work with n; assumption.
intros n i' j' nth; apply In_Disjs with (S n); apply My_NthS; assumption.
intros n x nth; apply In_Nested_Imps with n; assumption.
intros i' b n bs lookup nth; apply In_Atomic_Imps with n bs; assumption.
intros i' lookup; apply In_Atoms; assumption.
Qed.
intros work i j ds ni ai a.
apply In_Disjs with 0.
apply My_NthO.
Qed.
intros work i j ds ni ai a c in_ngamma0.
elim in_ngamma0; clear in_ngamma0 c.
intros n c0 nth; left; apply In_Work with n; assumption.
intros n; case n; clear n.
intros i' j' nth; right; inversion_clear nth; trivial.
intros n i' j' nth; left; apply In_Disjs with n; inversion_clear nth;
assumption.
intros n x nth; left; apply In_Nested_Imps with n; assumption.
intros i' b n bs lookup nth; left; apply In_Atomic_Imps with n bs; assumption.
intros i' lookup; left; apply In_Atoms; assumption.
Qed.
intros work ds x ni ai a c in_ngamma0.
elim in_ngamma0; clear in_ngamma0 c.
intros n c0 nth; apply In_Work with n; assumption.
intros n i j nth; apply In_Disjs with n; assumption.
intros n x' nth; apply In_Nested_Imps with (S n).
simpl in |- *; apply My_NthS; assumption.
intros i' b n bs lookup nth; apply In_Atomic_Imps with n bs; assumption.
intros i' lookup; apply In_Atoms; assumption.
Qed.
intros work ds x ni ai a.
apply In_Nested_Imps with 0; simpl in |- *; apply My_NthO.
Qed.
intros work ds x ni ai a c in_ngamma0.
elim in_ngamma0; clear in_ngamma0 c.
intros n c1 nth; left; apply In_Work with n; assumption.
intros n i' j' nth; left; apply In_Disjs with n; assumption.
intros n; case n; clear n.
intros x' nth; right; inversion_clear nth; trivial.
intros n x' nth; left; apply In_Nested_Imps with n; inversion_clear nth;
assumption.
intros i' b n bs lookup nth; left; apply In_Atomic_Imps with n bs; assumption.
intros i' lookup; left; apply In_Atoms; assumption.
Qed.
intros work ds x ni1 ni2 ai a.
apply In_Nested_Imps with (n := length ni1) (x := nested_imp2nimp x).
rewrite (nested_imps2nimps_app ni1 (x :: ni2)).
rewrite (nested_imps2nimps_length ni1).
rewrite <- (plus_O (length (nested_imps2nimps ni1))).
apply nth_app1.
simpl in |- *; apply My_NthO.
Qed.
intros work ds x ni1 ni2 ai a c in_ngamma0.
elim in_ngamma0; clear in_ngamma0 c.
intros n c0 nth; apply In_Work with n; assumption.
intros n i j nth; apply In_Disjs with n; assumption.
intros n x0 nth.
elim (inv_nth_app nimp n (nested_imps2nimps ni1) (nested_imps2nimps ni2) x0).
intros nth'; apply In_Nested_Imps with n.
rewrite (nested_imps2nimps_app ni1 (x :: ni2)).
apply nth_app0; assumption.
intros n' nth'; apply In_Nested_Imps with (length ni1 + S n').
rewrite (nested_imps2nimps_app ni1 (x :: ni2)).
rewrite (nested_imps2nimps_length ni1).
apply nth_app1.
simpl in |- *; apply My_NthS; assumption.
rewrite <- (nested_imps2nimps_app ni1 ni2); assumption.
intros i b n bs lookup nth; apply In_Atomic_Imps with n bs; assumption.
intros i lookup; apply In_Atoms; assumption.
Qed.

Lemma in_ngamma_ni_x_ni_rev :
forall (work : nf_list) (ds : disjs) (x : nested_imp)
(ni1 ni2 : nested_imps) (ai : atomic_imps) (a : atoms)
(c : normal_form),
in_ngamma work ds (ni1 ++ x :: ni2) ai a c ->
in_ngamma work ds (ni1 ++ ni2) ai a c + {c = NImp_NF (nested_imp2nimp x)}.