(* File: niMinimal.v  (last edited on 27/10/2000) (c) Klaus Weich  *)

Require Export Forces_NGamma.
Require Export Derivable_Tools.


Definition nminimal (work : nf_list) (ds : disjs) (ni : nested_imps)
  (ai : atomic_imps) (a : atoms) (context : flist) :=
  forall (c : form) (k : kripke_tree),
  Is_Monotone_kripke_tree k ->
  forces_ngamma work ds ni ai a k -> In c context -> forces_t k c.



(*********************************************************************)

Lemma nminimal_derivable_forces :
 forall (work : nf_list) (ds : disjs) (ni : nested_imps) 
   (ai : atomic_imps) (a : atoms) (context : flist) 
   (k : kripke_tree),
 Is_Monotone_kripke_tree k ->
 forces_ngamma work ds ni ai a k ->
 nminimal work ds ni ai a context ->
 forall c : form, Derivable context c -> forces_t k c.
(* Goal: forall (work : nf_list) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (context : flist) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma work ds ni ai a k) (_ : nminimal work ds ni ai a context) (c : form) (_ : Derivable context c), forces_t k c *)
intros work ds ni ai a context k k_is_mon k_forces_ngamma mon c der_c.
(* Goal: forces_t k c *)
elim der_c; clear der_c.
(* Goal: forall (t : proof_term) (_ : derives context t c), forces_t k c *)
intros t der_t.
(* Goal: forces_t k c *)
apply soundness_t with t context; try assumption.
(* Goal: forall (c : form) (_ : @In form c context), forces_t k c *)
intros c0 in_c0.
(* Goal: forces_t k c0 *)
apply mon; assumption.
Qed.



(*********************************************************************)



Lemma nminimal_eqv :
 forall (work : nf_list) (ds : disjs) (ni1 ni2 : nested_imps)
   (ai : atomic_imps) (a : atoms) (context : flist),
 eqv_ni ni1 ni2 ->
 nminimal work ds ni1 ai a context -> nminimal work ds ni2 ai a context.
(* Goal: forall (work : nf_list) (ds : disjs) (ni1 ni2 : nested_imps) (ai : atomic_imps) (a : atoms) (context : flist) (_ : eqv_ni ni1 ni2) (_ : nminimal work ds ni1 ai a context), nminimal work ds ni2 ai a context *)
intros work ds ni1 ni2 ai a context eq12 mon.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma work ds ni2 ai a k) (_ : @In form c context), forces_t k c *)
intros c k k_is_mon k_forces in_a.
(* Goal: forces_t k c0 *)
apply mon; try assumption.
(* Goal: forces_ngamma work ds ni1 ai a k *)
apply forces_ngamma_eqv with ni2; assumption.
Qed.



(************************************************************************)





Lemma nminimal_shift_work_ds :
 forall (i j : Int) (work : nf_list) (ds : disjs) (ni : nested_imps)
   (ai : atomic_imps) (a : atoms) (context : flist),
 nminimal (NDisj i j :: work) ds ni ai a context ->
 nminimal work ((i, j) :: ds) ni ai a context.
(* Goal: forall (i j : Int) (work : nf_list) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (context : flist) (_ : nminimal (@cons normal_form (NDisj i j) work) ds ni ai a context), nminimal work (@cons (prod Int Int) (@pair Int Int i j) ds) ni ai a context *)
intros i j work ds ni ai a context mon.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma work ds ni ai a' k) (_ : @In form c context), forces_t k c *)
intros c k k_is_mon k_forces_ngamma in_a.
(* Goal: forces_t k c0 *)
apply mon; try assumption.
(* Goal: forces_ngamma (@cons normal_form (NDisj i j) work) ds ni ai a k *)
apply forces_ngamma_shift_ds_work; assumption.
Qed.


Lemma nminimal_shift_work_ni :
 forall (x : nested_imp) (work : nf_list) (ds : disjs) 
   (ni : nested_imps) (ai : atomic_imps) (a : atoms) 
   (context : flist),
 nminimal (NImp_NF (nested_imp2nimp x) :: work) ds ni ai a context ->
 nminimal work ds (x :: ni) ai a context.
(* Goal: forall (x : nested_imp) (work : nf_list) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (context : flist) (_ : nminimal (@cons normal_form (NImp_NF (nested_imp2nimp x)) work) ds ni ai a context), nminimal work ds (@cons nested_imp x ni) ai a context *)
intros x work ds ni ai a context mon.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma work ds ni ai a' k) (_ : @In form c context), forces_t k c *)
intros c k k_is_mon k_forces_ngamma in_a.
(* Goal: forces_t k c0 *)
apply mon; try assumption.
(* Goal: forces_ngamma (@cons normal_form (NImp_NF (nested_imp2nimp x)) work) ds ni ai a k *)
apply forces_ngamma_shift_ni_work; assumption.
Qed.





Lemma nminimal_shift_work_ai_new :
 forall (i : Int) (b : normal_form) (work : nf_list) 
   (ds : disjs) (ni : nested_imps) (ai ai' : atomic_imps) 
   (a : atoms) (context : flist),
 (forall bs : nf_list, LOOKUP nf_list i ai bs -> False) ->
 EQUIV_INS nf_list i (cons b) nf_nil ai ai' ->
 nminimal (AImp i b :: work) ds ni ai a context ->
 nminimal work ds ni ai' a context.
(* Goal: forall (i : Int) (b : normal_form) (work : nf_list) (ds : disjs) (ni : nested_imps) (ai ai' : atomic_imps) (a : atoms) (context : flist) (_ : forall (bs : nf_list) (_ : LOOKUP nf_list i ai bs), False) (_ : EQUIV_INS nf_list i (@cons normal_form b) nf_nil ai ai') (_ : nminimal (@cons normal_form (AImp i b) work) ds ni ai a context), nminimal work ds ni ai' a context *)
intros i b work ds ni ai ai' a context lookup equiv_ins mon.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma work ds ni ai a' k) (_ : @In form c context), forces_t k c *)
intros c k k_is_mon k_forces_ngamma in_a.
(* Goal: forces_t k c0 *)
apply mon; try assumption.
(* Goal: forces_ngamma (@cons normal_form (AImp i b) work) ds ni ai a k *)
apply forces_ngamma_shift_ai_work_new with ai'; assumption.
Qed.


Lemma nminimal_shift_work_ai_old :
 forall (i : Int) (b : normal_form) (work : nf_list) 
   (ds : disjs) (ni : nested_imps) (bs : nf_list) (ai ai' : atomic_imps)
   (a : atoms) (context : flist),
 LOOKUP nf_list i ai bs ->
 EQUIV_INS nf_list i (cons b) nf_nil ai ai' ->
 nminimal (AImp i b :: work) ds ni ai a context ->
 nminimal work ds ni ai' a context.
(* Goal: forall (i : Int) (b : normal_form) (work : nf_list) (ds : disjs) (ni : nested_imps) (bs : nf_list) (ai ai' : atomic_imps) (a : atoms) (context : flist) (_ : LOOKUP nf_list i ai bs) (_ : EQUIV_INS nf_list i (@cons normal_form b) nf_nil ai ai') (_ : nminimal (@cons normal_form (AImp i b) work) ds ni ai a context), nminimal work ds ni ai' a context *)
intros i b work ds ni bs ai ai' a context notlookup equiv_ins mon.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma work ds ni ai a' k) (_ : @In form c context), forces_t k c *)
intros c k k_is_mon k_forces_ngamma in_a.
(* Goal: forces_t k c0 *)
apply mon; try assumption.
(* Goal: forces_ngamma (@cons normal_form (AImp i b) work) ds ni ai a k *)
apply forces_ngamma_shift_ai_work_old with bs ai'; assumption.
Qed.




Lemma nminimal_shift_work_a :
 forall (i : Int) (work : nf_list) (ds : disjs) (ni : nested_imps)
   (ai : atomic_imps) (a a' : atoms) (context : flist),
 EQUIV_INS unit i (fun _ : unit => tt) tt a a' ->
 nminimal (NAtom i :: work) ds ni ai a context ->
 nminimal work ds ni ai a' context.
(* Goal: forall (i : Int) (work : nf_list) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a a' : atoms) (context : flist) (_ : EQUIV_INS unit i (fun _ : unit => tt) tt a a') (_ : nminimal (@cons normal_form (NAtom i) work) ds ni ai a context), nminimal work ds ni ai a' context *)
intros i work ds ni ai a a' context equiv_ins mon.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma work ds ni ai a' k) (_ : @In form c context), forces_t k c *)
intros c k k_is_mon k_forces_ngamma in_a.
(* Goal: forces_t k c0 *)
apply mon; try assumption.
(* Goal: forces_ngamma (@cons normal_form (NAtom i) work) ds ni ai a k *)
apply forces_ngamma_shift_a_work with a'; assumption.
Qed.



Lemma nminimal_shift_work_ni_x_ni :
 forall (x : nested_imp) (work : nf_list) (ds : disjs)
   (ni1 ni2 : nested_imps) (ai : atomic_imps) (a : atoms) 
   (context : flist),
 nminimal (NImp_NF (nested_imp2nimp x) :: work) ds (ni1 ++ ni2) ai a context ->
 nminimal work ds (ni1 ++ x :: ni2) ai a context.
(* Goal: forall (x : nested_imp) (work : nf_list) (ds : disjs) (ni1 ni2 : nested_imps) (ai : atomic_imps) (a : atoms) (context : flist) (_ : nminimal work ds (@app nested_imp ni1 (@cons nested_imp x ni2)) ai a context), nminimal (@cons normal_form (NImp_NF (nested_imp2nimp x)) work) ds (@app nested_imp ni1 ni2) ai a context *)
intros x work ds ni1 ni2 ai a context min.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma (@app normal_form bs work) ds ni ai' a k) (_ : @In form c context), forces_t k c *)
intros c k k_is_mon k_forces_ngamma in_c.
(* Goal: forces_t k c0 *)
apply min; try assumption.
(* Goal: forces_ngamma (@cons normal_form (NImp_NF (nested_imp2nimp x)) work) ds (@app nested_imp ni1 ni2) ai a k *)
apply forces_ngamma_shift_ni_x_ni_work; assumption.
Qed.


Lemma nminimal_shift_ni_x_ni_work :
 forall (x : nested_imp) (work : nf_list) (ds : disjs)
   (ni1 ni2 : nested_imps) (ai : atomic_imps) (a : atoms) 
   (context : flist),
 nminimal work ds (ni1 ++ x :: ni2) ai a context ->
 nminimal (NImp_NF (nested_imp2nimp x) :: work) ds (ni1 ++ ni2) ai a context.
(* Goal: forall (x : nested_imp) (work : nf_list) (ds : disjs) (ni1 ni2 : nested_imps) (ai : atomic_imps) (a : atoms) (context : flist) (_ : nminimal work ds (@app nested_imp ni1 (@cons nested_imp x ni2)) ai a context), nminimal (@cons normal_form (NImp_NF (nested_imp2nimp x)) work) ds (@app nested_imp ni1 ni2) ai a context *)
intros x work ds ni1 ni2 ai a context min.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma (@app normal_form bs work) ds ni ai' a k) (_ : @In form c context), forces_t k c *)
intros c k k_is_mon k_forces_ngamma in_c.
(* Goal: forces_t k c0 *)
apply min; try assumption.
(* Goal: forces_ngamma work ds (@app nested_imp ni1 (@cons nested_imp x ni2)) ai a k *)
apply forces_ngamma_shift_work_ni_x_ni; assumption.
Qed.




(********************************************************************)


Lemma nminimal_cons_work_strength :
 forall (b c : normal_form) (work : nf_list) (ds : disjs) 
   (ni : nested_imps) (ai : atomic_imps) (a : atoms) 
   (context : flist),
 (forall k : kripke_tree,
  Is_Monotone_kripke_tree k ->
  forces_ngamma (c :: work) ds ni ai a k -> forces_t k (nf2form b)) ->
 nminimal (b :: work) ds ni ai a context ->
 nminimal (c :: work) ds ni ai a context.
(* Goal: forall (b c : normal_form) (work : nf_list) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (context : flist) (_ : forall (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_t k (nf2form c)), forces_t k (nf2form b)) (_ : nminimal (@cons normal_form b work) ds ni ai a context), nminimal (@cons normal_form c work) ds ni ai a context *)
intros b c work ds ni ai a context forces_cb minimal.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c0 : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma (@cons normal_form c work) ds ni ai a k) (_ : @In form c0 (@cons form (nf2form c) context)), forces_t k c0 *)
intros c0 k k_is_mon k_forces_ngamma in_c0.
(* Goal: forces_t k c0 *)
apply minimal; try assumption.
(* Goal: forces_ngamma (@cons normal_form (NDisj i j) work) ds ni ai a k *)
apply forces_ngamma_cons_work_weak with c; try assumption.
(* Goal: forall _ : forces_t k (nf2form c), forces_t k (nf2form b) *)
intros forces_c.
(* Goal: forces_t k (nf2form b) *)
apply forces_cb; assumption.
Qed.


Lemma nminimal_cons_work_weak :
 forall (b c : normal_form) (work : nf_list) (ds : disjs) 
   (ni : nested_imps) (ai : atomic_imps) (a : atoms) 
   (context : flist),
 (forall k : kripke_tree,
  Is_Monotone_kripke_tree k ->
  forces_t k (nf2form c) -> forces_t k (nf2form b)) ->
 nminimal (b :: work) ds ni ai a context ->
 nminimal (c :: work) ds ni ai a context.
(* Goal: forall (b c : normal_form) (work : nf_list) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (context : flist) (_ : forall (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_t k (nf2form c)), forces_t k (nf2form b)) (_ : nminimal (@cons normal_form b work) ds ni ai a context), nminimal (@cons normal_form c work) ds ni ai a context *)
intros b c work ds ni ai a context forces_cb minimal.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c0 : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma (@cons normal_form c work) ds ni ai a k) (_ : @In form c0 (@cons form (nf2form c) context)), forces_t k c0 *)
intros c0 k k_is_mon k_forces_ngamma in_c0.
(* Goal: forces_t k c0 *)
apply minimal; try assumption.
(* Goal: forces_ngamma (@cons normal_form (NDisj i j) work) ds ni ai a k *)
apply forces_ngamma_cons_work_weak with c; try assumption.
(* Goal: forall _ : forces_t k (nf2form c), forces_t k (nf2form b) *)
intros forces_c.
(* Goal: forces_t k (nf2form b) *)
apply forces_cb; assumption.
Qed.




Lemma nminimal_shift_work_ai_weak :
 forall (i : Int) (bs work : nf_list) (ds : disjs) 
   (ni : nested_imps) (ai ai' : atomic_imps) (a : atoms) 
   (context : flist),
 LOOKUP nf_list i ai bs ->
 EQUIV_DEL nf_list i ai ai' ->
 nminimal work ds ni ai a context ->
 nminimal (bs ++ work) ds ni ai' a context.
(* Goal: forall (i : Int) (bs work : nf_list) (ds : disjs) (ni : nested_imps) (ai ai' : atomic_imps) (a : atoms) (context : flist) (_ : LOOKUP nf_list i ai bs) (_ : EQUIV_DEL nf_list i ai ai') (_ : nminimal work ds ni ai a context), nminimal (@app normal_form bs work) ds ni ai' a context *)
intros i bs work ds ni ai ai' a context lookup equiv_del min.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma (@app normal_form bs work) ds ni ai' a k) (_ : @In form c context), forces_t k c *)
intros c k k_is_mon k_forces_ngamma in_c.
(* Goal: forces_t k c0 *)
apply min; try assumption.
(* Goal: forces_ngamma work ds ni ai a k *)
apply forces_ngamma_del_ai_rev with i bs ai'; try assumption.
(* Goal: forall (n : nat) (b : normal_form) (_ : my_nth normal_form n bs b), forces_t k (nf2form (AImp i b)) *)
(* Goal: forces_ngamma work ds ni ai' a k *)
intros n b nth.
(* Goal: forces_t k (nf2form (AImp i b)) *)
(* Goal: forces_ngamma work ds ni ai' a k *)
simpl in |- *; apply forces_b__forces_a_imp_b_t; try assumption.
(* Goal: forces_t k (nf2form c) *)
(* Goal: forces_t k c0 *)
apply k_forces_ngamma.
(* Goal: in_ngamma (@app normal_form bs work) ds ni ai' a b *)
(* Goal: forces_ngamma work ds ni ai' a k *)
apply In_Work with n.
(* Goal: my_nth normal_form n (@app normal_form bs work) b *)
(* Goal: forces_ngamma work ds ni ai' a k *)
apply nth_app0; assumption.
(* Goal: forces_ngamma work ds ni ai' a k *)
apply forces_ngamma_app_work_tail with bs; assumption.
Qed.



Lemma nminimal_shift_ds_work_context :
 forall (work : nf_list) (c : normal_form) (i j : Int) 
   (ds : disjs) (ni : nested_imps) (ai : atomic_imps) 
   (a : atoms) (context : flist),
 (forall k : kripke_tree,
  Is_Monotone_kripke_tree k ->
  forces_t k (nf2form c) -> forces_t k (OrF (Atom i) (Atom j))) ->
 nminimal work ((i, j) :: ds) ni ai a context ->
 nminimal (c :: work) ds ni ai a (nf2form c :: context).
(* Goal: forall (work : nf_list) (c : normal_form) (i j : Int) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (context : flist) (_ : forall (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_t k (nf2form c)), forces_t k (OrF (Atom i) (Atom j))) (_ : nminimal work (@cons (prod Int Int) (@pair Int Int i j) ds) ni ai a context), nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
intros work c i j ds ni ai a context forces_ij mon.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c0 : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma (@cons normal_form c work) ds ni ai a k) (_ : @In form c0 (@cons form (nf2form c) context)), forces_t k c0 *)
intros c0 k k_is_mon k_forces_ngamma in_context.
(* Goal: forces_t k c0 *)
inversion_clear in_context.
(* Goal: forces_t k c0 *)
(* Goal: forces_t k c0 *)
 rewrite <- H; clear H c0.
(* Goal: forces_t k (nf2form c) *)
(* Goal: forces_t k c0 *)
apply k_forces_ngamma.
(* Goal: in_ngamma (@cons normal_form c work) ds ni ai a c *)
(* Goal: forces_t k c0 *)
apply in_ngamma_cons_work_head.
(* Goal: forces_t k c0 *)
apply mon; try assumption.
(* Goal: forces_ngamma work (@cons (prod Int Int) (@pair Int Int i j) ds) ni ai a k *)
apply forces_ngamma_shift_work_ds.
(* Goal: forces_ngamma (@cons normal_form (NDisj i j) work) ds ni ai a k *)
apply forces_ngamma_cons_work_weak with c; try assumption.
(* Goal: forall _ : forces_t k (nf2form c), forces_t k (nf2form (NDisj i j)) *)
intro forces_c.
(* Goal: forces_t k (nf2form (NDisj i j)) *)
apply forces_ij; assumption.
Qed.


Lemma nminimal_cons_work_cons_context :
 forall (c : normal_form) (work : nf_list) (ds : disjs) 
   (ni : nested_imps) (ai : atomic_imps) (a : atoms) 
   (context : flist),
 nminimal work ds ni ai a context ->
 nminimal (c :: work) ds ni ai a (nf2form c :: context).
(* Goal: forall (c : normal_form) (work : nf_list) (ds : disjs) (ni : nested_imps) (ai : atomic_imps) (a : atoms) (context : flist) (_ : nminimal work ds ni ai a context), nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
intros c work ds ni ai a context min.
(* Goal: nminimal (@cons normal_form c work) ds ni ai a (@cons form (nf2form c) context) *)
unfold nminimal in |- *.
(* Goal: forall (c0 : form) (k : kripke_tree) (_ : Is_Monotone_kripke_tree k) (_ : forces_ngamma (@cons normal_form c work) ds ni ai a k) (_ : @In form c0 (@cons form (nf2form c) context)), forces_t k c0 *)
intros c0 k k_is_mon k_forces_ngamma in_c0.
(* Goal: forces_t k c0 *)
inversion_clear in_c0.
(* Goal: forces_t k c0 *)
(* Goal: forces_t k c0 *)
 rewrite <- H.
(* Goal: forces_t k (nf2form c) *)
(* Goal: forces_t k c0 *)
apply k_forces_ngamma.
(* Goal: in_ngamma (@cons normal_form c work) ds ni ai a c *)
(* Goal: forces_t k c0 *)
apply in_ngamma_cons_work_head.
(* Goal: forces_t k c0 *)
apply min; try assumption.
(* Goal: forces_ngamma work ds ni ai a k *)
apply forces_ngamma_cons_work_tail with c.
(* Goal: forces_ngamma (@cons normal_form c work) ds ni ai a k *)
assumption.
Qed.

