Section QE_Mixin.
Variable F : Field.type.
Implicit Type f : formula F.
Variable proj : nat -> seq (term F) * seq (term F) -> formula F.
(* proj is the elimination of a single existential quantifier *)
(* The elimination projector is well_formed. *)
Definition wf_QE_proj :=
forall i bc (bc_i := proj i bc),
dnf_rterm bc -> qf_form bc_i && rformula bc_i.
(* The elimination projector is valid *)
Definition valid_QE_proj :=
forall i bc (ex_i_bc := ('exists 'X_i, dnf_to_form [:: bc])%T) e,
dnf_rterm bc -> reflect (holds e ex_i_bc) (qf_eval e (proj i bc)).
Hypotheses (wf_proj : wf_QE_proj) (ok_proj : valid_QE_proj).
Let elim_aux f n := foldr Or False (map (proj n) (qf_to_dnf f false)).
Fixpoint quantifier_elim f :=
match f with
| f1 /\ f2 => (quantifier_elim f1) /\ (quantifier_elim f2)
| f1 \/ f2 => (quantifier_elim f1) \/ (quantifier_elim f2)
| f1 ==> f2 => (~ quantifier_elim f1) \/ (quantifier_elim f2)
| ~ f => ~ quantifier_elim f
| ('exists 'X_n, f) => elim_aux (quantifier_elim f) n
| ('forall 'X_n, f) => ~ elim_aux (~ quantifier_elim f) n
| _ => f
end%T.

Lemma quantifier_elim_wf f :
let qf := quantifier_elim f in rformula f -> qf_form qf && rformula qf.