(* side conditions *)
Definition pure_atom_gt1 a (l: list pure_atom) :=
  match l with b :: _ => pure_atom_gt a b | _ => true end.Definition pure_atom_geq1 a (l: list pure_atom) :=
  match l with b :: _ => pure_atom_geq a b | _ => true end.(* "superpose" applies "sp" from L-R and R-L, thus returning all new
   clauses derivable from clauses "c" and "d" under the proof rules *)
Definition superpose (c d : clause) l0 : list clause := sp c d (sp d c l0).(* clause simplification -- the following proof rules simplify clauses
   "in place".  that is, either a newly generated clause is simplified before
   entering the clause database for the first time or an existing clause is
   replaced by its simplified form, e.g., when it is rewritten by a newly
   derived positive unit clause (demodulation). *)
Definition rewrite_by s t atm :=
  match atm with Eqv u v =>
    if expr_eq s u then if expr_eq s v then norm_pure_atom (Eqv t t)
                        else norm_pure_atom (Eqv t v)
    else if expr_eq s v then norm_pure_atom (Eqv u t)
         else atm
  end.(*begin hide*)
(* filter tautological clauses *)

(* Function taut_aux (n p : pure_atom) (arg: list pure_atom * list pure_atom) *)
(*    {measure (fun arg => length (fst arg) + length (snd arg)) arg} : bool := *)
(*  match pure_atom_cmp n p with *)
(*  | Lt => match arg with *)
(*              | (n'::nl', pl) => taut_aux n' p (nl',pl) *)
(*              | _ => false *)
(*              end *)
(*  | Eq => true *)
(*  | Gt => match arg with  *)
(*               | (nl, p'::pl') => taut_aux n p' (nl,pl') *)
(*               | _ => false *)
(*               end *)
(*  end. *)
(*  Proof.  *)
(*    intros; subst; simpl; omega. *)
(*    intros; subst; simpl; omega. *)
(*  Defined. *)

(* Definition not_taut (c: clause) := *)
(*   match c with *)
(*   | PureClause (n::neg) (p::pos) _ _ => negb (taut_aux n p (neg,pos)) *)
(*   | _ => true *)
(*   end. *)
(*end hide*)

(* for some reason, this version of not_taut when extracted runs faster
   than the one above *)
Definition not_taut (c: clause) :=
  negb (match c with
        | PureClause neg pos _ _ =>
          existsb (fun a => existsb (fun b =>
                     pure_atom_eq a b) pos) neg ||
          existsb (fun a =>
            match a with Eqv e1 e2 => expr_eq e1 e2 end) pos
        | _ => false end).(* rewrite "c" by any positive unit clauses in "l". delete resolved atoms
   from the resulting clause. Argument l is sorted so no need to sort here.
 *)
Definition simplify (l : list clause) (c : clause) : clause :=
  delete_resolved (fold_left (fun d c => demodulate c d) l c).(* derive all possible inferences from clause "c" and clauses "l", simplifying
   any resulting clauses using facts in "l" *)
Definition infer_list (c : clause) (l : list clause) : list clause :=
  print_inferred_list (filter not_taut (map (simplify l)
    (fold_left (fun l0 d => superpose c d l0) l nil))).(*begin hide*)
(* VERSION 0:
Definition mem_add (x: M.elt) (s: M.t) : option M.t :=
 if M.mem x s then None else Some (M.add x s).
Lemma mem_add_spec:
    forall x s, mem_add x s = if M.mem x s then None else Some (M.add x s).
Proof. auto. Qed.
Opaque mem_add.
 END VERSION 0 *)
(*end hide*)
(* VERSION 1: *)
Definition mem_add := M.mem_add.

(* Specifications: *)
Lemma mem_add_spec: forall x s, mem_add x s = if M.mem x s then None else Some (M.add x s).