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

(* Specifications: *)
Lemma in_ngamma_cons_work_tail : forall (c0 : normal_form) (work : nf_list) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (c : normal_form), in_ngamma work ds ni ai a c -> in_ngamma (c0 :: work) ds ni ai a c.
Lemma in_ngamma_cons_work_head : forall (c : normal_form) (work : nf_list) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms), in_ngamma (c :: work) ds ni ai a c.
Lemma in_ngamma_work_app1 : forall (bs work : nf_list) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (c : normal_form), in_ngamma work ds ni ai a c -> in_ngamma (bs ++ work) ds ni ai a c.
Lemma in_ngamma_work_app_rev : forall (bs work : nf_list) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (c : normal_form), in_ngamma (bs ++ work) ds ni ai a c -> in_ngamma work ds ni ai a c + {n : nat | my_nth normal_form n bs c}.
Lemma in_ngamma_cons_work_rev : forall (c0 : normal_form) (work : nf_list) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (c : normal_form), in_ngamma (c0 :: work) ds ni ai a c -> in_ngamma work ds ni ai a c + {c = c0}.
Lemma in_ngamma_cons_ds_tail : forall (work : nf_list) (i j : Int) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (c : normal_form), in_ngamma work ds ni ai a c -> in_ngamma work ((i, j) :: ds) ni ai a c.
Lemma in_ngamma_cons_ds_head : forall (work : nf_list) (i j : Int) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms), in_ngamma work ((i, j) :: ds) ni ai a (NDisj i j).
Lemma in_ngamma_cons_ds_rev : forall (work : nf_list) (i j : Int) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (c : normal_form), in_ngamma work ((i, j) :: ds) ni ai a c -> in_ngamma work ds ni ai a c + {c = NDisj i j}.
Lemma in_ngamma_cons_ni_tail : forall (work : nf_list) (ds : disjs) (x : nested_imp) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (c : normal_form), in_ngamma work ds ni ai a c -> in_ngamma work ds (x :: ni) ai a c.
Lemma in_ngamma_cons_ni_head : forall (work : nf_list) (ds : disjs) (x : nested_imp) (ni : nested_imps) (ai : atomic_imps) (a : atoms), in_ngamma work ds (x :: ni) ai a (NImp_NF (nested_imp2nimp x)).
Lemma in_ngamma_cons_ni_rev : forall (work : nf_list) (ds : disjs) (x : nested_imp) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (c : normal_form), in_ngamma work ds (x :: ni) ai a c -> in_ngamma work ds ni ai a c + {c = NImp_NF (nested_imp2nimp x)}.
Lemma in_ngamma_ni_x_ni_head : forall (work : nf_list) (ds : disjs) (x : nested_imp) (ni1 ni2 : nested_imps) (ai : atomic_imps) (a : atoms), in_ngamma work ds (ni1 ++ x :: ni2) ai a (NImp_NF (nested_imp2nimp x)).
Lemma in_ngamma_ni_x_ni_tail : 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 ++ ni2) ai a c -> in_ngamma work ds (ni1 ++ x :: ni2) ai a c.
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)}.
Lemma in_ngamma_ni_eq : forall (work : nf_list) (ds : disjs) (ni ni' : nested_imps) (ai : atomic_imps) (a : atoms) (c : normal_form), nested_imps2nimps ni = nested_imps2nimps ni' -> in_ngamma work ds ni ai a c -> in_ngamma work ds ni' ai a c.
Lemma in_ngamma_ins_ai_tail : forall (work : nf_list) (ds : disjs) (ni : nested_imps) (i : Int) (b : normal_form) (ai ai' : atomic_imps) (a : atoms) (c : normal_form), EQUIV_INS nf_list i (cons b) nf_nil ai ai' -> in_ngamma work ds ni ai a c -> in_ngamma work ds ni ai' a c.
Lemma in_ngamma_ins_ai_head_new : forall (work : nf_list) (ds : disjs) (ni : nested_imps) (i : Int) (b : normal_form) (ai ai' : atomic_imps) (a : atoms), (forall bs : nf_list, LOOKUP nf_list i ai bs -> False) -> EQUIV_INS nf_list i (cons b) nf_nil ai ai' -> in_ngamma work ds ni ai' a (AImp i b).
Lemma in_ngamma_ins_ai_head_old : forall (work : nf_list) (ds : disjs) (ni : nested_imps) (i : Int) (b : normal_form) (bs : nf_list) (ai ai' : atomic_imps) (a : atoms), LOOKUP nf_list i ai bs -> EQUIV_INS nf_list i (cons b) nf_nil ai ai' -> in_ngamma work ds ni ai' a (AImp i b).
Lemma in_ngamma_ins_ai_rev : forall (work : nf_list) (ds : disjs) (ni : nested_imps) (i : Int) (b : normal_form) (ai ai' : atomic_imps) (a : atoms) (c : normal_form), EQUIV_INS nf_list i (cons b) nf_nil ai ai' -> in_ngamma work ds ni ai' a c -> in_ngamma work ds ni ai a c + {c = AImp i b}.
Lemma in_ngamma_del_ai_tail : forall (work : nf_list) (ds : disjs) (ni : nested_imps) (i : Int) (ai ai' : atomic_imps) (a : atoms) (c : normal_form), EQUIV_DEL nf_list i ai' ai -> in_ngamma work ds ni ai a c -> in_ngamma work ds ni ai' a c.