]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/ng_paramodulation/superposition.ml
New age selection
[helm.git] / helm / software / components / ng_paramodulation / superposition.ml
1 (*
2     ||M||  This file is part of HELM, an Hypertextual, Electronic        
3     ||A||  Library of Mathematics, developed at the Computer Science     
4     ||T||  Department, University of Bologna, Italy.                     
5     ||I||                                                                
6     ||T||  HELM is free software; you can redistribute it and/or         
7     ||A||  modify it under the terms of the GNU General Public License   
8     \   /  version 2 or (at your option) any later version.      
9      \ /   This software is distributed as is, NO WARRANTY.     
10       V_______________________________________________________________ *)
11
12 (* $Id: index.mli 9822 2009-06-03 15:37:06Z tassi $ *)
13
14 module Superposition (B : Terms.Blob) = 
15   struct
16     module IDX = Index.Index(B)
17     module Unif = FoUnif.Founif(B)
18     module Subst = FoSubst 
19     module Order = Orderings.Orderings(B)
20     module Utils = FoUtils.Utils(B)
21     module Pp = Pp.Pp(B)
22     
23     exception Success of B.t Terms.bag * int * B.t Terms.unit_clause
24
25     let debug s = prerr_endline s;;
26     let debug _ = ();;
27
28     let rec list_first f = function
29       | [] -> None
30       | x::tl -> match f x with Some _ as x -> x | _ -> list_first f tl
31     ;;
32
33     let first_position pos ctx t f =
34       let inject_pos pos ctx = function
35         | None -> None
36         | Some (a,b,c,d,e) -> Some(ctx a,b,c,d,e,pos)
37       in
38       let rec aux pos ctx = function
39       | Terms.Leaf _ as t -> inject_pos pos ctx (f t)
40       | Terms.Var _ -> None
41       | Terms.Node l as t->
42           match f t with
43           | Some _ as x -> inject_pos pos ctx x
44           | None ->
45               let rec first pre post = function
46                 | [] -> None
47                 | t :: tl -> 
48                      let newctx = fun x -> ctx (Terms.Node (pre@[x]@post)) in
49                      match aux (List.length pre :: pos) newctx t with
50                      | Some _ as x -> x
51                      | None -> 
52                          if post = [] then None (* tl is also empty *)
53                          else first (pre @ [t]) (List.tl post) tl
54               in
55                 first [] (List.tl l) l 
56       in
57         aux pos ctx t
58     ;;
59                                      
60     let all_positions pos ctx t f =
61       let rec aux pos ctx = function
62       | Terms.Leaf _ as t -> f t pos ctx 
63       | Terms.Var _ -> []
64       | Terms.Node l as t-> 
65           let acc, _, _ = 
66             List.fold_left
67             (fun (acc,pre,post) t -> (* Invariant: pre @ [t] @ post = l *)
68                 let newctx = fun x -> ctx (Terms.Node (pre@[x]@post)) in
69                 let acc = aux (List.length pre :: pos) newctx t @ acc in
70                 if post = [] then acc, l, []
71                 else acc, pre @ [t], List.tl post)
72              (f t pos ctx, [], List.tl l) l
73           in
74            acc
75       in
76         aux pos ctx t
77     ;;
78
79     let parallel_positions bag pos ctx id t f =
80       let rec aux bag pos ctx id = function
81       | Terms.Leaf _ as t -> f bag t pos ctx id
82       | Terms.Var _ as t -> bag,t,id
83       | Terms.Node l as t->
84           let bag,t,id1 = f bag t pos ctx id in
85             if id = id1 then
86               let bag, l, _, id = 
87                 List.fold_left
88                   (fun (bag,pre,post,id) t ->
89                      let newctx = fun x -> ctx (Terms.Node (pre@[x]@post)) in
90                      let newpos = (List.length pre)::pos in
91                      let bag,newt,id = aux bag newpos newctx id t in
92                        if post = [] then bag, pre@[newt], [], id
93                        else bag, pre @ [newt], List.tl post, id)
94                   (bag, [], List.tl l, id) l
95               in
96                 bag, Terms.Node l, id
97             else bag,t,id1
98       in
99         aux bag pos ctx id t
100     ;;
101
102     let vars_of_term t =
103       let rec aux acc = function
104         | Terms.Leaf _ -> acc
105         | Terms.Var i -> if (List.mem i acc) then acc else i::acc
106         | Terms.Node l -> List.fold_left aux acc l
107       in aux [] t
108     ;;
109     
110     let build_clause bag filter rule t subst vl id id2 pos dir =
111       let proof = Terms.Step(rule,id,id2,dir,pos,subst) in
112       let t = Subst.apply_subst subst t in
113       if filter t then
114         let literal = 
115           match t with
116           | Terms.Node [ Terms.Leaf eq ; ty; l; r ] when B.eq B.eqP eq ->
117                let o = Order.compare_terms l r in
118                Terms.Equation (l, r, ty, o)
119           | t -> Terms.Predicate t
120         in
121         let bag, uc = 
122           Terms.add_to_bag (0, literal, vars_of_term t, proof) bag
123         in
124         Some (bag, uc)
125       else
126         ((*prerr_endline ("Filtering: " ^ Pp.pp_foterm t);*)None)
127     ;;
128       
129     
130     (* ============ simplification ================= *)
131
132     let demod table varlist subterm =
133       let cands = IDX.DT.retrieve_generalizations table subterm in
134       list_first
135         (fun (dir, (id,lit,vl,_)) ->
136            match lit with
137            | Terms.Predicate _ -> assert false
138            | Terms.Equation (l,r,_,o) ->
139                let side, newside = if dir=Terms.Left2Right then l,r else r,l in
140                try 
141                  let subst, varlist = 
142                    Unif.unification (varlist@vl) varlist subterm side 
143                  in
144                  let side = Subst.apply_subst subst side in
145                  let newside = Subst.apply_subst subst newside in
146                  if o = Terms.Incomparable then
147                    let o = Order.compare_terms newside side in
148                    (* Riazanov, pp. 45 (ii) *)
149                    if o = Terms.Lt then
150                      Some (newside, subst, varlist, id, dir)
151                    else 
152                      ((*prerr_endline ("Filtering: " ^ 
153                         Pp.pp_foterm side ^ " =(< || =)" ^ 
154                         Pp.pp_foterm newside ^ " coming from " ^ 
155                         Pp.pp_unit_clause uc );*)None)
156                  else
157                    Some (newside, subst, varlist, id, dir)
158                with FoUnif.UnificationFailure _ -> None)
159         (IDX.ClauseSet.elements cands)
160     ;;
161
162     let demodulate_once_old ~jump_to_right bag (id, literal, vl, pr) table =
163       match literal with
164       | Terms.Predicate t -> assert false
165       | Terms.Equation (l,r,ty,_) ->
166         let left_position = if jump_to_right then None else
167           first_position [2]
168             (fun x -> Terms.Node [ Terms.Leaf B.eqP; ty; x; r ]) l
169             (demod table vl)
170         in
171         match left_position with
172           | Some (newt, subst, varlist, id2, dir, pos) ->
173               begin
174                 match build_clause bag (fun _ -> true) Terms.Demodulation 
175                   newt subst varlist id id2 pos dir
176                 with
177                   | None -> assert false
178                   | Some x -> Some (x,false)
179               end
180           | None ->
181               match first_position
182                 [3] (fun x -> Terms.Node [ Terms.Leaf B.eqP; ty; l; x ]) r
183                 (demod table vl)
184               with
185                 | None -> None
186                 | Some (newt, subst, varlist, id2, dir, pos) ->
187                     match build_clause bag (fun _ -> true)
188                       Terms.Demodulation newt subst varlist id id2 pos dir
189                     with
190                         | None -> assert false
191                         | Some x -> Some (x,true)
192     ;;
193
194     let parallel_demod table vl bag t pos ctx id =
195       match demod table vl t with
196         | None -> (bag,t,id)
197         | Some (newside, subst, vl, id2, dir) ->
198             match build_clause bag (fun _ -> true)
199               Terms.Demodulation (ctx newside) subst vl id id2 pos dir
200             with
201               | None -> assert false
202               | Some (bag,(id,_,_,_)) ->
203                     (bag,newside,id)
204     ;;
205
206     let demodulate_once ~jump_to_right bag (id, literal, vl, pr) table =
207       match literal with
208       | Terms.Predicate t -> assert false
209       | Terms.Equation (l,r,ty,_) ->
210           let bag,l,id1 = if jump_to_right then (bag,l,id) else
211             parallel_positions bag [2]
212               (fun x -> Terms.Node [ Terms.Leaf B.eqP; ty; x; r ]) id l
213               (parallel_demod table vl)
214           in
215           let jump_to_right = id1 = id in
216           let bag,r,id2 =
217             parallel_positions bag [3]
218               (fun x -> Terms.Node [ Terms.Leaf B.eqP; ty; l; x ]) id1 r
219               (parallel_demod table vl)
220           in
221             if id = id2 then None
222             else
223               let cl,_,_ = Terms.get_from_bag id2 bag in
224                 Some ((bag,cl),jump_to_right)
225     ;;
226
227     let rec demodulate ~jump_to_right bag clause table =
228       match demodulate_once ~jump_to_right bag clause table with
229       | None -> bag, clause
230       | Some ((bag, clause),r) -> demodulate ~jump_to_right:r
231           bag clause table
232     ;;
233
234     let rec demodulate_old ~jump_to_right bag clause table =
235       match demodulate_once_old ~jump_to_right bag clause table with
236         | None -> bag, clause
237         | Some ((bag, clause),r) -> demodulate_old ~jump_to_right:r
238           bag clause table
239     ;;
240
241     let are_alpha_eq cl1 cl2 =
242       let get_term (_,lit,_,_) =
243         match lit with
244           | Terms.Predicate _ -> assert false
245           | Terms.Equation (l,r,ty,_) ->
246               Terms.Node [Terms.Leaf B.eqP; ty; l ; r]
247       in
248         try ignore(Unif.alpha_eq (get_term cl1) (get_term cl2)) ; true
249         with FoUnif.UnificationFailure _ -> false
250     ;;
251
252     let demodulate bag clause table =
253 (*      let (bag1,c1), (_,c2) =*)
254         demodulate ~jump_to_right:false bag clause table
255 (*      demodulate_old ~jump_to_right:false bag clause table*)
256 (*      in
257         if are_alpha_eq c1 c2 then bag1,c1
258         else begin
259           prerr_endline (Pp.pp_unit_clause c1);
260           prerr_endline (Pp.pp_unit_clause c2);
261           prerr_endline "Bag :";
262           prerr_endline (Pp.pp_bag bag1);
263           assert false
264         end*)
265     ;;
266
267     (* move away *)
268     let is_identity_clause ~unify = function
269       | _, Terms.Equation (_,_,_,Terms.Eq), _, _ -> true
270       | _, Terms.Equation (l,r,_,_), vl, proof when unify ->
271           (try ignore(Unif.unification vl [] l r); true
272           with FoUnif.UnificationFailure _ -> false)
273       | _, Terms.Equation (_,_,_,_), _, _ -> false
274       | _, Terms.Predicate _, _, _ -> assert false        
275     ;;
276
277     let build_new_clause bag maxvar filter rule t subst vl id id2 pos dir =
278       let maxvar, vl, relocsubst = Utils.relocate maxvar vl in
279       let subst = Subst.concat relocsubst subst in
280       match build_clause bag filter rule t subst vl id id2 pos dir with
281       | Some (bag, c) -> Some ((bag, maxvar), c)
282       | None -> None
283     ;;
284
285     let fold_build_new_clause bag maxvar id rule filter res =
286       let (bag, maxvar), res =
287        HExtlib.filter_map_acc 
288          (fun (bag, maxvar) (t,subst,vl,id2,pos,dir) ->
289             build_new_clause bag maxvar filter rule t subst vl id id2 pos dir)
290          (bag, maxvar) res
291       in
292        bag, maxvar, res
293     ;;
294
295     
296     let rewrite_eq ~unify l r ty vl table =
297       let retrieve = if unify then IDX.DT.retrieve_unifiables
298       else IDX.DT.retrieve_generalizations in
299       let lcands = retrieve table l in
300       let rcands = retrieve table r in
301       let f b c = 
302         let id, dir, l, r, vl = 
303           match c with
304             | (d, (id,Terms.Equation (l,r,ty,_),vl,_))-> id, d, l, r, vl
305             |_ -> assert false 
306         in 
307         let reverse = (dir = Terms.Left2Right) = b in
308         let l, r, proof_rewrite_dir = if reverse then l,r,Terms.Left2Right
309         else r,l, Terms.Right2Left in
310           (id,proof_rewrite_dir,Terms.Node [ Terms.Leaf B.eqP; ty; l; r ], vl)
311       in
312       let cands1 = List.map (f true) (IDX.ClauseSet.elements lcands) in
313       let cands2 = List.map (f false) (IDX.ClauseSet.elements rcands) in
314       let t = Terms.Node [ Terms.Leaf B.eqP; ty; l; r ] in
315       let locked_vars = if unify then [] else vl in
316       let rec aux = function
317         | [] -> None
318         | (id2,dir,c,vl1)::tl ->
319             try
320               let subst,vl1 = Unif.unification (vl@vl1) locked_vars c t in
321               Some (id2, dir, subst)
322             with FoUnif.UnificationFailure _ -> aux tl
323       in
324         aux (cands1 @ cands2)
325     ;;
326
327     let is_subsumed ~unify bag maxvar (id, lit, vl, _) table =
328       match lit with
329       | Terms.Predicate _ -> assert false
330       | Terms.Equation (l,r,ty,_) -> 
331           match rewrite_eq ~unify l r ty vl table with
332             | None -> None
333             | Some (id2, dir, subst) ->
334                 let id_t = Terms.Node [ Terms.Leaf B.eqP; ty; r; r ] in
335                   build_new_clause bag maxvar (fun _ -> true)
336                     Terms.Superposition id_t subst [] id id2 [2] dir 
337     ;;
338     (* id refers to a clause proving contextl l = contextr r *)
339
340     let rec deep_eq ~unify l r ty pos contextl contextr table acc =
341       match acc with 
342       | None -> None
343       | Some(bag,maxvar,(id,lit,vl,p),subst) -> 
344           let l = Subst.apply_subst subst l in 
345           let r = Subst.apply_subst subst r in 
346             try 
347               let subst1,vl1 = Unif.unification vl [] l r in
348               let lit = 
349                 match lit with Terms.Predicate _ -> assert false
350                   | Terms.Equation (l,r,ty,o) -> 
351                      Terms.Equation (FoSubst.apply_subst subst1 l,
352                        FoSubst.apply_subst subst1 r, ty, o)
353               in
354                 Some(bag,maxvar,(id,lit,vl1,p),Subst.concat subst1 subst)
355             with FoUnif.UnificationFailure _ -> 
356               match rewrite_eq ~unify l r ty vl table with
357               | Some (id2, dir, subst1) ->
358                   let newsubst = Subst.concat subst1 subst in
359                   let id_t = 
360                     FoSubst.apply_subst newsubst
361                       (Terms.Node[Terms.Leaf B.eqP;ty;contextl r;contextr r]) 
362                   in
363                     (match 
364                       build_new_clause bag maxvar (fun _ -> true)
365                         Terms.Superposition id_t 
366                           subst1 [] id id2 (pos@[2]) dir 
367                     with
368                     | Some ((bag, maxvar), c) -> 
369                         Some(bag,maxvar,c,newsubst)
370                     | None -> assert false)
371               | None ->
372                   match l,r with 
373                   | Terms.Node (a::la), Terms.Node (b::lb) when 
374                       a = b && List.length la = List.length lb ->
375                       let acc,_,_,_ =
376                         List.fold_left2 
377                           (fun (acc,pre,postl,postr) a b -> 
378                              let newcl = 
379                               fun x -> contextl(Terms.Node (pre@(x::postl))) in
380                              let newcr = 
381                               fun x -> contextr(Terms.Node (pre@(x::postr))) in
382                              let newpos = List.length pre::pos in
383                              let footail l =
384                                if l = [] then [] else List.tl l in
385                                (deep_eq ~unify a b ty 
386                                  newpos newcl newcr table acc,pre@[b],
387                                  footail postl, footail postr))
388                           (acc,[a],List.tl la,List.tl lb) la lb
389                       in acc
390                   | _,_ -> None
391     ;;
392
393     let rec orphan_murder bag acc i =
394       match Terms.get_from_bag i bag with
395         | (_,_,_,Terms.Exact _),discarded,_ -> (discarded,acc)
396         | (_,_,_,Terms.Step (_,i1,i2,_,_,_)),true,_ -> (true,acc)
397         | (_,_,_,Terms.Step (_,i1,i2,_,_,_)),false,_ ->
398             if (List.mem i acc) then (false,acc)
399             else match orphan_murder bag acc i1 with
400               | (true,acc) -> (true,acc)
401               | (false,acc) ->
402                   let (res,acc) = orphan_murder bag acc i2 in
403                   if res then res,acc else res,i::acc
404     ;;
405
406     let orphan_murder bag actives cl =
407       let (id,_,_,_) = cl in
408       let actives = List.map (fun (i,_,_,_) -> i) actives in
409       let (res,_) = orphan_murder bag actives id in
410         if res then debug "Orphan murdered"; res
411     ;;
412
413     (* demodulate and check for subsumption *)
414     let simplify table maxvar bag clause = 
415       if is_identity_clause ~unify:false clause then bag,None
416       (* else if orphan_murder bag actives clause then bag,None *)
417       else let bag, clause = demodulate bag clause table in
418       if is_identity_clause ~unify:false clause then bag,None
419       else
420         match is_subsumed ~unify:false bag maxvar clause table with
421           | None -> bag, Some clause
422           | Some _ -> bag, None
423     ;;
424
425     let simplify table maxvar bag clause =
426       match simplify table maxvar bag clause with
427         | bag, None ->
428             let (id,_,_,_) = clause in
429             let (_,_,iter) = Terms.get_from_bag id bag in
430             Terms.replace_in_bag (clause,true,iter) bag, None
431         | bag, Some clause -> bag, Some clause
432     (*let (id,_,_,_) = clause in
433             if orphan_murder bag clause then
434               Terms.M.add id (clause,true) bag, Some clause
435             else bag, Some clause*)
436     ;;
437
438     let one_pass_simplification new_clause (alist,atable) bag maxvar =
439       match simplify atable maxvar bag new_clause with
440         | bag,None -> bag,None (* new_clause has been discarded *)
441         | bag,(Some clause) ->
442             let ctable = IDX.index_unit_clause IDX.DT.empty clause in
443             let bag, alist, atable = 
444               List.fold_left 
445                 (fun (bag, alist, atable) c ->
446                    match simplify ctable maxvar bag c with
447                      |bag,None -> (bag,alist,atable)
448                         (* an active clause as been discarded *)
449                      |bag,Some c1 ->
450                         bag, c :: alist, IDX.index_unit_clause atable c)
451                 (bag,[],IDX.DT.empty) alist
452             in
453               bag, Some (clause, (alist,atable))
454     ;;
455
456     let simplification_step ~new_cl cl (alist,atable) bag maxvar new_clause =
457       let atable1 =
458         if new_cl then atable else
459         IDX.index_unit_clause atable cl
460       in
461         (* Simplification of new_clause with :      *
462          * - actives and cl if new_clause is not cl *
463          * - only actives otherwise                 *)
464         match
465           simplify atable1 maxvar bag new_clause with
466           | bag,None -> bag,(Some cl, None) (* new_clause has been discarded *)
467           | bag,Some clause ->
468               (* Simplification of each active clause with clause *
469                * which is the simplified form of new_clause       *)
470               let ctable = IDX.index_unit_clause IDX.DT.empty clause in
471               let bag, newa, alist, atable = 
472                 List.fold_left 
473                   (fun (bag, newa, alist, atable) c ->
474                      match simplify ctable maxvar bag c with
475                        |bag,None -> (bag, newa, alist, atable)
476                           (* an active clause as been discarded *)
477                        |bag,Some c1 ->
478                             if (c1 == c) then 
479                               bag, newa, c :: alist,
480                             IDX.index_unit_clause atable c
481                             else
482                               bag, c1 :: newa, alist, atable)             
483                   (bag,[],[],IDX.DT.empty) alist
484               in
485                 if new_cl then
486                   bag, (Some cl, Some (clause, (alist,atable), newa))
487                 else
488                   (* if new_clause is not cl, we simplify cl with clause *)
489                   match simplify ctable maxvar bag cl with
490                     | bag,None ->
491                         (* cl has been discarded *)
492                         bag,(None, Some (clause, (alist,atable), newa))
493                     | bag,Some cl1 ->
494                         bag,(Some cl1, Some (clause, (alist,atable), newa))
495     ;;
496
497     let keep_simplified cl (alist,atable) bag maxvar =
498       let rec keep_simplified_aux ~new_cl cl (alist,atable) bag newc =
499         if new_cl then
500           match simplification_step ~new_cl cl (alist,atable) bag maxvar cl with
501             | _,(None, _) -> assert false
502             | bag,(Some _, None) -> bag,None
503             | bag,(Some _, Some (clause, (alist,atable), newa)) ->
504                 keep_simplified_aux ~new_cl:(cl!=clause) clause (alist,atable)
505                   bag (newa@newc)
506         else
507           match newc with
508             | [] -> bag, Some (cl, (alist,atable))
509             | hd::tl ->
510                 match simplification_step ~new_cl cl
511                   (alist,atable) bag maxvar hd with
512                   | _,(None,None) -> assert false
513                   | bag,(Some _,None) ->
514                       keep_simplified_aux ~new_cl cl (alist,atable) bag tl
515                   | bag,(None, Some _) -> bag,None
516                   | bag,(Some cl1, Some (clause, (alist,atable), newa)) ->
517                       let alist,atable =
518                         (clause::alist, IDX.index_unit_clause atable clause)
519                       in
520                         keep_simplified_aux ~new_cl:(cl!=cl1) cl1 (alist,atable)
521                           bag (newa@tl)
522       in
523         keep_simplified_aux ~new_cl:true cl (alist,atable) bag []
524     ;;
525
526     (* this is like simplify but raises Success *)
527     let simplify_goal ~no_demod maxvar table bag g_actives clause = 
528       let bag, clause = 
529         if no_demod then bag, clause else demodulate bag clause table 
530       in
531       if List.exists (are_alpha_eq clause) g_actives then None else
532       if (is_identity_clause ~unify:true clause)
533       then raise (Success (bag, maxvar, clause))
534       else   
535         let (id,lit,vl,_) = clause in 
536         if vl = [] then Some (bag,clause)
537         else
538          let l,r,ty = 
539            match lit with
540              | Terms.Equation(l,r,ty,_) -> l,r,ty
541              | _ -> assert false 
542          in
543          match deep_eq ~unify:true l r ty [] (fun x -> x) (fun x -> x) 
544            table (Some(bag,maxvar,clause,Subst.id_subst)) with
545          | None -> Some (bag,clause)
546          | Some (bag,maxvar,cl,subst) -> 
547              prerr_endline "Goal subsumed";
548              raise (Success (bag,maxvar,cl))
549 (*
550       else match is_subsumed ~unify:true bag maxvar clause table with
551         | None -> Some (bag, clause)
552         | Some ((bag,maxvar),c) -> 
553             prerr_endline "Goal subsumed";
554             raise (Success (bag,maxvar,c))
555 *) 
556     ;;
557
558     (* =================== inference ===================== *)
559
560     (* this is OK for both the sup_left and sup_right inference steps *)
561     let superposition table varlist subterm pos context =
562       let cands = IDX.DT.retrieve_unifiables table subterm in
563       HExtlib.filter_map
564         (fun (dir, (id,lit,vl,_ (*as uc*))) ->
565            match lit with
566            | Terms.Predicate _ -> assert false
567            | Terms.Equation (l,r,_,o) ->
568                let side, newside = if dir=Terms.Left2Right then l,r else r,l in
569                try 
570                  let subst, varlist = 
571                    Unif.unification (varlist@vl) [] subterm side 
572                  in
573                  if o = Terms.Incomparable then
574                    let side = Subst.apply_subst subst side in
575                    let newside = Subst.apply_subst subst newside in
576                    let o = Order.compare_terms side newside in
577                    (* XXX: check Riazanov p. 33 (iii) *)
578                    if o <> Terms.Lt && o <> Terms.Eq then  
579                      Some (context newside, subst, varlist, id, pos, dir)
580                    else 
581                      ((*prerr_endline ("Filtering: " ^ 
582                         Pp.pp_foterm side ^ " =(< || =)" ^ 
583                         Pp.pp_foterm newside);*)None)
584                  else
585                    Some (context newside, subst, varlist, id, pos, dir)
586                with FoUnif.UnificationFailure _ -> None)
587         (IDX.ClauseSet.elements cands)
588     ;;
589
590     (* Superposes selected equation with equalities in table *)
591     let superposition_with_table bag maxvar (id,selected,vl,_) table =
592       match selected with 
593       | Terms.Predicate _ -> assert false
594       | Terms.Equation (l,r,ty,Terms.Lt) ->
595           fold_build_new_clause bag maxvar id Terms.Superposition
596             (fun _ -> true)
597             (all_positions [3] 
598               (fun x -> Terms.Node [ Terms.Leaf B.eqP; ty; l; x ])
599               r (superposition table vl))
600       | Terms.Equation (l,r,ty,Terms.Gt) ->
601           fold_build_new_clause bag maxvar id Terms.Superposition
602             (fun _ -> true)
603             (all_positions [2] 
604               (fun x -> Terms.Node [ Terms.Leaf B.eqP; ty; x; r ])
605               l (superposition table vl))
606       | Terms.Equation (l,r,ty,Terms.Incomparable) -> 
607           fold_build_new_clause bag maxvar id Terms.Superposition
608             (function (* Riazanov: p.33 condition (iv) *)
609               | Terms.Node [Terms.Leaf eq; ty; l; r ] when B.eq B.eqP eq -> 
610                   Order.compare_terms l r <> Terms.Eq
611               | _ -> assert false)
612             ((all_positions [3] 
613                (fun x -> Terms.Node [ Terms.Leaf B.eqP; ty; l; x ])
614                r (superposition table vl)) @         
615              (all_positions [2] 
616                (fun x -> Terms.Node [ Terms.Leaf B.eqP; ty; x; r ])
617                l (superposition table vl)))
618       | _ -> assert false
619     ;;
620
621     (* the current equation is normal w.r.t. demodulation with atable
622      * (and is not the identity) *)
623     let infer_right bag maxvar current (alist,atable) = 
624       (* We demodulate actives clause with current until all *
625        * active clauses are reduced w.r.t each other         *)
626       (* let bag, (alist,atable) = keep_simplified (alist,atable) bag [current] in *)
627       let ctable = IDX.index_unit_clause IDX.DT.empty current in
628       (* let bag, (alist, atable) = 
629         let bag, alist = 
630           HExtlib.filter_map_acc (simplify ctable) bag alist
631         in
632         bag, (alist, List.fold_left IDX.index_unit_clause IDX.DT.empty alist)
633       in*)
634         debug "Simplified active clauses with fact";
635       (* We superpose active clauses with current *)
636       let bag, maxvar, new_clauses =
637         List.fold_left 
638           (fun (bag, maxvar, acc) active ->
639              let bag, maxvar, newc = 
640                superposition_with_table bag maxvar active ctable 
641              in
642              bag, maxvar, newc @ acc)
643           (bag, maxvar, []) alist
644       in
645         debug "First superpositions";
646         (* We add current to active clauses so that it can be *
647          * superposed with itself                             *)
648       let alist, atable = 
649         current :: alist, IDX.index_unit_clause atable current
650       in
651         debug "Indexed";
652       let fresh_current, maxvar = Utils.fresh_unit_clause maxvar current in
653         (* We need to put fresh_current into the bag so that all *
654          * variables clauses refer to are known.                 *)
655       let bag, fresh_current = Terms.add_to_bag fresh_current bag in
656         (* We superpose current with active clauses *)
657       let bag, maxvar, additional_new_clauses =
658         superposition_with_table bag maxvar fresh_current atable 
659       in
660         debug "Another superposition";
661       let new_clauses = new_clauses @ additional_new_clauses in
662         debug (Printf.sprintf "Demodulating %d clauses"
663                  (List.length new_clauses));
664       let bag, new_clauses = 
665         HExtlib.filter_map_monad (simplify atable maxvar) bag new_clauses
666       in
667         debug "Demodulated new clauses";
668       bag, maxvar, (alist, atable), new_clauses
669     ;;
670
671     let infer_left bag maxvar goal (_alist, atable) =
672         (* We superpose the goal with active clauses *)
673      if (match goal with (_,_,[],_) -> true | _ -> false) then bag, maxvar, []
674      else
675       let bag, maxvar, new_goals =      
676         superposition_with_table bag maxvar goal atable 
677       in
678         debug "Superposed goal with active clauses";
679         (* We simplify the new goals with active clauses *)
680       let bag, new_goals = 
681         List.fold_left
682          (fun (bag, acc) g -> 
683             match simplify_goal ~no_demod:false maxvar atable bag [] g with
684               | None -> assert false
685               | Some (bag,g) -> bag,g::acc)
686          (bag, []) new_goals
687       in
688         debug "Simplified new goals with active clauses";
689       bag, maxvar, List.rev new_goals
690     ;;
691
692   end