| Terms.Node l -> "(" ^ String.concat " " (List.map ppfot l) ^ ")"
    ;;
 
-   let mk_predicate hole_type amount ft p vl =
+   let mk_predicate hole_type amount ft p1 vl =
     let rec aux t p = 
       match p with
       | [] -> NCic.Rel 1
           | Terms.Var _ -> 
                prerr_endline ("term: " ^ ppfot ft);            
                prerr_endline ("path: " ^ String.concat "," 
-                 (List.map string_of_int p));
+                 (List.map string_of_int p1));
                assert false
           | Terms.Node l -> 
               let l = 
               in            
               NCic.Appl l
     in
-      NCic.Lambda("x", hole_type, aux ft (List.rev p))
+      NCic.Lambda("x", hole_type, aux ft (List.rev p1))
     ;;
 
   let mk_proof (bag : NCic.term Terms.bag) mp steps =
           NCic.Prod ("x"^string_of_int i, NCic.Implicit `Type, t))
        t vl  
     in
+    let get_literal id =
+      let _, lit, vl, proof = Terms.M.find id bag in
+      let lit =match lit with 
+          | Terms.Predicate t -> assert false 
+          | Terms.Equation (l,r,ty,_) -> 
+              Terms.Node [ Terms.Leaf eqP; ty; l; r]
+      in
+       lit, vl, proof
+    in
     let rec aux ongoal seen = function
       | [] -> NCic.Rel 1
       | id :: tl ->
           let amount = List.length seen in
-          let _, lit, vl, proof = Terms.M.find id bag in
-          let lit = 
-            match lit with 
-            | Terms.Predicate t -> assert false 
-            | Terms.Equation (l,r,ty,_) -> 
-                 Terms.Node [ Terms.Leaf eqP; ty; l; r]
-          in
+          let lit,vl,proof = get_literal id in
           if not ongoal && id = mp then
-            (assert (vl = []);  
+            ((*prerr_endline ("Reached meeting point, id=" ^ (string_of_int id));*)
+            assert (vl = []);  
              NCic.LetIn ("clause_" ^ string_of_int id, 
                 extract amount vl lit, 
                 (NCic.Appl [eq_refl;NCic.Implicit `Type;NCic.Implicit `Term]),
                 aux true ((id,([],lit))::seen) (id::tl)))
           else
           match proof with
-          | Terms.Exact _ when tl=[] -> aux ongoal seen tl
+          | Terms.Exact _ when tl=[] ->
+             (* prerr_endline ("Exact (tl=[]) for " ^ (string_of_int id));*)
+             aux ongoal seen tl
           | Terms.Step _ when tl=[] -> assert false
-          | Terms.Exact ft -> 
+          | Terms.Exact ft ->
+             (* prerr_endline ("Exact for " ^ (string_of_int id));*)
                NCic.LetIn ("clause_" ^ string_of_int id, 
                  close_with_forall vl (extract amount vl lit),
                  close_with_lambdas vl (extract amount vl ft),
                    ((id,(List.map (fun x -> Terms.Var x) vl,lit))::seen) tl)
           | Terms.Step (_, id1, id2, dir, pos, subst) ->
               let id, id1 = if ongoal then id1,id else id,id1 in
+             let lit,vl,_ = get_literal id in
               let proof_of_id id = 
                 let vars = List.rev (vars_of id seen) in
                 let args = List.map (Subst.apply_subst subst) vars in
                 let args = List.map (extract amount vl) args in
-                NCic.Appl (NCic.Rel (List.length vl + position id seen) :: args)
+               let rel_for_id = NCic.Rel (List.length vl + position id seen) in
+                 if args = [] then rel_for_id              
+                  else NCic.Appl (rel_for_id::args)
               in
               let p_id1 = proof_of_id id1 in
               let p_id2 = proof_of_id id2 in
                       extract amount vl (Subst.apply_subst subst r)
                   | _ -> assert false
                 in
+                 (*prerr_endline "mk_predicate :";
+                 if ongoal then prerr_endline "ongoal=true"
+                 else prerr_endline "ongoal=false";
+                 prerr_endline ("id=" ^ string_of_int id);
+                 prerr_endline ("id1=" ^ string_of_int id1);
+                 prerr_endline ("id2=" ^ string_of_int id2);
+                 prerr_endline ("Positions :" ^
+                                  (String.concat ", "
+                                     (List.map string_of_int pos)));*)
                 mk_predicate 
                   id2_ty amount (Subst.apply_subst subst id1_ty) pos vl,
                 id2_ty,
                   l,r,eq_ind
               in
                NCic.LetIn ("clause_" ^ string_of_int id, 
-                 close_with_forall vl (extract amount vl lit),
+                 (*close_with_forall vl (extract amount vl lit)*) NCic.Implicit `Type,
                  close_with_lambdas vl
                    (NCic.Appl [ eq_ind ; hole_type; l; pred; p_id1; r; p_id2 ]),
                  aux ongoal 
 
 
 let nparamod rdb metasenv subst context t table =
   let nb_iter = ref 200 in
-  prerr_endline "========================================";
   let module C = struct
     let metasenv = metasenv
     let subst = subst
           bag, maxvar, g_current::g_actives,
          (PassiveSet.union new_goals g_passives)
     in
-      prerr_endline
+      debug
        (Printf.sprintf "Number of active goals : %d"
           (List.length g_actives));
-      prerr_endline
+      debug
        (Printf.sprintf "Number of passive goals : %d"
           (PassiveSet.cardinal g_passives));
   
          | None -> assert false
          | Some (current, passives) -> 
              debug ("Selected fact : " ^ Pp.pp_unit_clause current);
-              match Sup.keep_simplified current actives bag with
+              match Sup.keep_simplified current actives bag maxvar with
              (* match Sup.one_pass_simplification current actives bag with *)
                | None -> aux_simplify passives
                | Some x -> x,passives
       PassiveSet.union new_clauses passives,
       PassiveSet.union new_goals g_passives
     in
-      prerr_endline
+      debug
        (Printf.sprintf "Number of actives : %d" (List.length (fst actives)));
-      prerr_endline
+      debug
        (Printf.sprintf "Number of passives : %d"
           (PassiveSet.cardinal passives));
       given_clause bag maxvar actives passives g_actives g_passives
         in
         let esteps = 
           S.topological_sort (C.elements (snd (all i))) 
-           (fun i -> C.elements (snd (all i)))
+           (fun i -> C.elements (C.union (snd (all i)) (fst (all i)) ))
         in
         let gsteps = 
           S.topological_sort (C.elements (fst (all i))) 
            (fun i -> C.elements (fst (all i)))
         in
         let gsteps = List.rev gsteps in
-        esteps@gsteps
+        esteps@(i::gsteps)
       in
-      prerr_endline "YES!";
-      prerr_endline "Proof:"; 
-      List.iter (fun x -> 
-              prerr_endline (Pp.pp_unit_clause (Terms.M.find x bag))) l;
+      debug "YES!";
+      debug ("Meeting point : " ^ (string_of_int i));
+      debug "Proof:"; 
+      (*List.iter (fun x -> prerr_endline (string_of_int x);
+              prerr_endline (Pp.pp_unit_clause (Terms.M.find x bag))) l; *)
       let proofterm = B.mk_proof bag i l in
-      prerr_endline
-       (NCicPp.ppterm ~metasenv:C.metasenv ~subst:C.subst ~context:C.context
-         proofterm); 
-      let _metasenv, _subst, _proofterm, _prooftype = 
-        NCicRefiner.typeof rdb C.metasenv C.subst C.context proofterm None
+       prerr_endline (NCicPp.ppterm ~metasenv:C.metasenv
+                        ~subst:C.subst ~context:C.context proofterm);
+      let metasenv, subst, proofterm, _prooftype = 
+        NCicRefiner.typeof 
+          (rdb#set_coerc_db NCicCoercion.empty_db) 
+          C.metasenv C.subst C.context proofterm None
       in
-      prerr_endline "REFINED!";
-      ()
-  | Failure _ -> prerr_endline "FAILURE";
+      proofterm, metasenv, subst
+  | Failure _ -> prerr_endline "FAILURE"; assert false
 ;;
 
       | _ -> false
     ;;
 
-    let is_subsumed ~unify (id, lit, vl, _) table =
+    let build_new_clause bag maxvar filter rule t subst vl id id2 pos dir =
+      let maxvar, vl, relocsubst = Utils.relocate maxvar vl in
+      let subst = Subst.concat relocsubst subst in
+      match build_clause bag filter rule t subst vl id id2 pos dir with
+      | Some (bag, c) -> Some ((bag, maxvar), c)
+      | None -> None
+    ;;
+
+
+    let fold_build_new_clause bag maxvar id rule filter res =
+      let (bag, maxvar), res =
+       HExtlib.filter_map_acc 
+         (fun (bag, maxvar) (t,subst,vl,id2,pos,dir) ->
+            build_new_clause bag maxvar filter rule t subst vl id id2 pos dir)
+         (bag, maxvar) res
+      in
+       bag, maxvar, res
+    ;;
+
+    let is_subsumed ~unify bag maxvar (id, lit, vl, _) table =
       match lit with
       | Terms.Predicate _ -> assert false
       | Terms.Equation (l,r,ty,_) -> 
           let lcands = retrieve table l in
           let rcands = retrieve table r in
           let f b c = 
-            let dir, l, r, vl = 
+            let id, dir, l, r, vl = 
               match c with
-              | (d, (_,Terms.Equation (l,r,ty,_),vl,_))-> d, l, r, vl
+              | (d, (id,Terms.Equation (l,r,ty,_),vl,_))-> id, d, l, r, vl
               |_ -> assert false 
             in 
-            let l, r = if (dir = Terms.Left2Right) = b then l,r else r,l in
-            Terms.Node [ Terms.Leaf B.eqP; ty; l; r ], vl
+           let reverse = (dir = Terms.Left2Right) = b in
+            let l, r, proof_rewrite_dir = if reverse then l,r,Terms.Left2Right
+           else r,l, Terms.Right2Left in
+            (id,proof_rewrite_dir,Terms.Node [ Terms.Leaf B.eqP; ty; l; r ], vl)
           in
           let cands1 = List.map (f true) (IDX.ClauseSet.elements lcands) in
           let cands2 = List.map (f false) (IDX.ClauseSet.elements rcands) in
           let t = Terms.Node [ Terms.Leaf B.eqP; ty; l; r ] in
          let locked_vars = if unify then [] else vl in
-            List.exists 
-              (fun (c, vl1) ->
-                try ignore(Unif.unification (vl@vl1) locked_vars c t); true
-                with FoUnif.UnificationFailure _ -> false)
-              (cands1 @ cands2)
+         let rec aux = function
+           | [] -> None
+           | (id2,dir,c,vl1)::tl ->
+               try
+                 let subst,vl1 = Unif.unification (vl@vl1) locked_vars c t in
+                 let id_t = Terms.Node [ Terms.Leaf B.eqP; ty; r; r ] in
+                   build_new_clause bag maxvar (fun _ -> true)
+                     Terms.Superposition id_t subst [] id id2 [2] dir 
+               with FoUnif.UnificationFailure _ -> aux tl
+         in
+           aux (cands1 @ cands2)
     ;;
 
     (* demodulate and check for subsumption *)
-    let simplify table bag clause = 
+    let simplify table maxvar bag clause = 
       let bag, clause = demodulate bag clause table in
       if is_identity_clause clause then None
       else
-        if is_subsumed ~unify:false clause table then None
-        else Some (bag, clause)
+        match is_subsumed ~unify:false bag maxvar clause table with
+         | None -> Some (bag, clause)
+         | Some _ -> None
     ;;
 
-    let one_pass_simplification new_clause (alist,atable) bag =
-      match simplify atable bag new_clause with
+    let one_pass_simplification new_clause (alist,atable) bag maxvar =
+      match simplify atable maxvar bag new_clause with
        | None -> None (* new_clause has been discarded *)
        | Some (bag, clause) ->
            let ctable = IDX.index_unit_clause IDX.DT.empty clause in
            let bag, alist, atable = 
              List.fold_left 
                (fun (bag, alist, atable as acc) c ->
-                  match simplify ctable bag c with
+                  match simplify ctable maxvar bag c with
                     |None -> acc (* an active clause as been discarded *)
                     |Some (bag, c1) ->
                        bag, c :: alist, IDX.index_unit_clause atable c)
              Some (clause, bag, (alist,atable))
     ;;
 
-    let simplification_step ~new_cl cl (alist,atable) bag new_clause =
+    let simplification_step ~new_cl cl (alist,atable) bag maxvar new_clause =
       let atable1 =
        if new_cl then atable else
        IDX.index_unit_clause atable cl
        (* Simplification of new_clause with :      *
         * - actives and cl if new_clause is not cl *
         * - only actives otherwise                 *)
-       match simplify atable1 bag new_clause with
+       match simplify atable1 maxvar bag new_clause with
          | None -> (Some cl, None) (* new_clause has been discarded *)
          | Some (bag, clause) ->
              (* Simplification of each active clause with clause *
              let bag, newa, alist, atable = 
                List.fold_left 
                  (fun (bag, newa, alist, atable as acc) c ->
-                    match simplify ctable bag c with
+                    match simplify ctable maxvar bag c with
                       |None -> acc (* an active clause as been discarded *)
                       |Some (bag, c1) ->
                            if (c1 == c) then 
                  (Some cl, Some (clause, (alist,atable), newa, bag))
                else
                  (* if new_clause is not cl, we simplify cl with clause *)
-                 match simplify ctable bag cl with
+                 match simplify ctable maxvar bag cl with
                    | None ->
                        (* cl has been discarded *)
                        (None, Some (clause, (alist,atable), newa, bag))
                        (Some cl1, Some (clause, (alist,atable), newa, bag))
     ;;
 
-    let keep_simplified cl (alist,atable) bag =
+    let keep_simplified cl (alist,atable) bag maxvar =
       let rec keep_simplified_aux ~new_cl cl (alist,atable) bag newc =
        if new_cl then
-         match simplification_step ~new_cl cl (alist,atable) bag cl with
+         match simplification_step ~new_cl cl (alist,atable) bag maxvar cl with
            | (None, _) -> assert false
            | (Some _, None) -> None
            | (Some _, Some (clause, (alist,atable), newa, bag)) ->
            | [] -> Some (cl, bag, (alist,atable))
            | hd::tl ->
                match simplification_step ~new_cl cl
-                 (alist,atable) bag hd with
+                 (alist,atable) bag maxvar hd with
                  | (None,None) -> assert false
                  | (Some _,None) ->
                      keep_simplified_aux ~new_cl cl (alist,atable) bag tl
     (* this is like simplify but raises Success *)
     let simplify_goal maxvar table bag clause = 
       let bag, clause = demodulate bag clause table in
-      if (is_identity_clause clause) || (is_subsumed ~unify:true clause table)
+      if (is_identity_clause clause)
       then raise (Success (bag, maxvar, clause))
-      else bag, clause
+      else match is_subsumed ~unify:true bag maxvar clause table with
+       | None -> bag, clause
+       | Some ((bag,maxvar),c) -> 
+           debug "Goal subsumed";
+           raise (Success (bag,maxvar,c))
     ;;
 
     (* =================== inference ===================== *)
         (IDX.ClauseSet.elements cands)
     ;;
 
-    let build_new_clause bag maxvar filter rule t subst vl id id2 pos dir =
-      let maxvar, vl, relocsubst = Utils.relocate maxvar vl in
-      let subst = Subst.concat relocsubst subst in
-      match build_clause bag filter rule t subst vl id id2 pos dir with
-      | Some (bag, c) -> Some ((bag, maxvar), c)
-      | None -> None
-    ;;
-
-
-    let fold_build_new_clause bag maxvar id rule filter res =
-      let (bag, maxvar), res =
-       HExtlib.filter_map_acc 
-         (fun (bag, maxvar) (t,subst,vl,id2,pos,dir) ->
-            build_new_clause bag maxvar filter rule t subst vl id id2 pos dir)
-         (bag, maxvar) res
-      in
-       bag, maxvar, res
-    ;;
-
     (* Superposes selected equation with equalities in table *)
     let superposition_with_table bag maxvar (id,selected,vl,_) table =
       match selected with 
             (fun _ -> true)
             (all_positions [3] 
               (fun x -> Terms.Node [ Terms.Leaf B.eqP; ty; l; x ])
-              r (superposition table vl))          
+              r (superposition table vl))
       | Terms.Equation (l,r,ty,Terms.Gt) ->
           fold_build_new_clause bag maxvar id Terms.Superposition
             (fun _ -> true)
        debug "Another superposition";
       let new_clauses = new_clauses @ additional_new_clauses in
       let bag, new_clauses = 
-        HExtlib.filter_map_acc (simplify atable) bag new_clauses
+        HExtlib.filter_map_acc (simplify atable maxvar) bag new_clauses
       in
        debug "Demodulated new clauses";
       bag, maxvar, (alist, atable), new_clauses
     ;;
 
   end
-
-
-