]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/ng_paramodulation/paramod.ml
0dafc864e215df8985e938b8edf4958de74e29b3
[helm.git] / helm / software / components / ng_paramodulation / paramod.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: orderings.ml 9869 2009-06-11 22:52:38Z denes $ *)
13
14 let debug s = prerr_endline s ;;
15 let debug _ = ();;
16
17 let monster = 100;;
18     
19 module Paramod (B : Terms.Blob) = struct
20   type szsontology = 
21     | Unsatisfiable of (B.t Terms.bag * int * int list) list
22     | GaveUp 
23     | Error of string 
24     | Timeout of int * B.t Terms.bag
25   exception Stop of szsontology
26   type bag = B.t Terms.bag * int
27   module Pp = Pp.Pp (B) 
28   module FU = FoUnif.Founif(B) 
29   module IDX = Index.Index(B) 
30   module Sup = Superposition.Superposition(B) 
31   module Utils = FoUtils.Utils(B) 
32   module WeightOrderedPassives =
33       struct
34         type t = B.t Terms.passive_clause
35         let compare = Utils.compare_passive_clauses_weight
36       end
37
38   module AgeOrderedPassives =
39       struct
40         type t = B.t Terms.passive_clause
41         let compare = Utils.compare_passive_clauses_age
42       end
43   
44   module WeightPassiveSet = Set.Make(WeightOrderedPassives)
45   module AgePassiveSet = Set.Make(AgeOrderedPassives)
46
47   let add_passive_clause ?(no_weight=false) (passives_w,passives_a) cl =
48     let cl = if no_weight then (0,cl)
49     else Utils.mk_passive_clause cl in
50     WeightPassiveSet.add cl passives_w, AgePassiveSet.add cl passives_a
51   ;;
52
53   let add_passive_goal ?(no_weight=false) (passives_w,passives_a) g =
54     let g = if no_weight then (0,g)
55     else Utils.mk_passive_goal g in
56     WeightPassiveSet.add g passives_w, AgePassiveSet.add g passives_a
57   ;;
58
59   let remove_passive_clause (passives_w,passives_a) cl =
60     let passives_w = WeightPassiveSet.remove cl passives_w in
61     let passives_a = AgePassiveSet.remove cl passives_a in
62       passives_w,passives_a
63   ;;
64
65   let add_passive_clauses ?(no_weight=false)
66       (passives_w,passives_a) new_clauses =
67     let new_clauses_w,new_clauses_a =
68       List.fold_left (add_passive_clause ~no_weight)
69       (WeightPassiveSet.empty,AgePassiveSet.empty) new_clauses
70     in
71       (WeightPassiveSet.union new_clauses_w passives_w,
72        AgePassiveSet.union new_clauses_a passives_a)
73   ;;
74
75   let add_passive_goals ?(no_weight=false)
76       (passives_w,passives_a) new_clauses =
77     let new_clauses_w,new_clauses_a =
78       List.fold_left (add_passive_goal ~no_weight)
79       (WeightPassiveSet.empty,AgePassiveSet.empty) new_clauses
80     in
81       (WeightPassiveSet.union new_clauses_w passives_w,
82        AgePassiveSet.union new_clauses_a passives_a)
83   ;;
84
85   let is_passive_set_empty (passives_w,passives_a) =
86     if (WeightPassiveSet.is_empty passives_w) then begin
87       assert (AgePassiveSet.is_empty passives_a); true
88     end else begin
89       assert (not (AgePassiveSet.is_empty passives_a)); false
90     end
91   ;;
92
93   let passive_set_cardinal (passives_w,_) = WeightPassiveSet.cardinal passives_w
94   
95   let passive_empty_set =
96     (WeightPassiveSet.empty,AgePassiveSet.empty)
97   ;;
98
99   let pick_min_passive ~use_age (passives_w,passives_a) =
100     if use_age then AgePassiveSet.min_elt passives_a
101     else WeightPassiveSet.min_elt passives_w
102   ;;
103
104   let mk_clause bag maxvar (t,ty) =
105     let (proof,ty) = B.saturate t ty in
106     let c, maxvar = Utils.mk_unit_clause maxvar ty proof in
107     let bag, c = Terms.add_to_bag c bag in
108     (bag, maxvar), c
109   ;;
110   
111   let mk_passive (bag,maxvar) = mk_clause bag maxvar;;
112   let mk_goal (bag,maxvar) = mk_clause bag maxvar;;
113
114   (* TODO : global age over facts and goals (without comparing weights) *)
115   let select ~use_age passives g_passives =
116     if is_passive_set_empty passives then begin
117       if (is_passive_set_empty g_passives) then
118         raise (Stop GaveUp) (* we say we are incomplete *)
119       else
120        let g_cl = pick_min_passive ~use_age:use_age g_passives in
121         (true,g_cl,passives,remove_passive_clause g_passives g_cl)
122     end
123     else let cl = pick_min_passive ~use_age:use_age passives in
124       if is_passive_set_empty g_passives then
125         (false,cl,remove_passive_clause passives cl,g_passives)
126       else
127         let g_cl = pick_min_passive ~use_age:use_age g_passives in
128         let (id1,_,_,_),(id2,_,_,_) = snd cl, snd g_cl in
129         let cmp = if use_age then id1 <= id2
130         else fst cl <= fst g_cl
131         in
132           if cmp then
133             (false,cl,remove_passive_clause passives cl,g_passives)
134           else
135             (true,g_cl,passives,remove_passive_clause g_passives g_cl)
136   ;;
137
138   let backward_infer_step bag maxvar actives passives
139                           g_actives g_passives g_current =
140     (* superposition left, simplifications on goals *)
141       debug "infer_left step...";
142       let bag, maxvar, new_goals = 
143         Sup.infer_left bag maxvar g_current actives 
144       in
145         debug "Performed infer_left step";
146         bag, maxvar, actives, passives, g_current::g_actives,
147     (add_passive_goals g_passives new_goals)
148   ;;
149
150   let forward_infer_step bag maxvar actives passives g_actives
151                          g_passives current =
152     (* forward step *)
153     
154     (* e = select P           *
155      * e' = demod A e         *
156      * A' = demod [e'] A      *
157      * A'' = A' + e'          *
158      * e'' = fresh e'         *
159      * new = supright e'' A'' *
160      * new'= demod A'' new    *
161      * P' = P + new'          *)
162     debug "Forward infer step...";
163     let bag, maxvar, actives, new_clauses = 
164       Sup.infer_right bag maxvar current actives 
165     in
166       debug "Demodulating goals with actives...";
167       (* keep goals demodulated w.r.t. actives and check if solved *)
168       let bag, g_actives = 
169         List.fold_left 
170           (fun (bag,acc) c -> 
171              match 
172                Sup.simplify_goal ~no_demod:false maxvar (snd actives) bag acc c
173              with
174                | None -> bag, acc
175                | Some (bag,c) -> bag,c::acc)
176           (bag,[]) g_actives 
177       in
178       let ctable = IDX.index_unit_clause IDX.DT.empty current in
179       let bag, maxvar, new_goals = 
180         List.fold_left 
181           (fun (bag,m,acc) g -> 
182              let bag, m, ng = Sup.infer_left bag m g ([current],ctable) in
183                bag,m,ng@acc) 
184           (bag,maxvar,[]) g_actives 
185       in
186     bag, maxvar, actives,
187     add_passive_clauses passives new_clauses, g_actives,
188     add_passive_goals g_passives new_goals
189   ;;
190  
191   let rec given_clause ~noinfer 
192     bag maxvar iterno max_steps timeout 
193     actives passives g_actives g_passives 
194   =
195     let iterno = iterno + 1 in
196     if iterno = max_steps then raise (Stop (Timeout (maxvar,bag)));
197     (* timeout check: gettimeofday called only if timeout set *)
198     if timeout <> None &&
199       (match timeout with
200       | None -> assert false
201       | Some timeout -> Unix.gettimeofday () > timeout) then
202         if noinfer then
203           begin
204             debug 
205               ("Last chance: all is indexed " ^ string_of_float
206                 (Unix.gettimeofday()));
207             let maxgoals = 100 in
208             ignore(List.fold_left 
209               (fun (acc,i) x -> 
210                  if i < maxgoals then
211                  ignore(Sup.simplify_goal ~no_demod:true 
212                           maxvar (snd actives) bag acc x)
213                  else
214                    ();
215                  x::acc,i+1)
216               ([],0) g_actives);
217             raise (Stop (Timeout (maxvar,bag)))
218           end
219         else if false then (* activates last chance strategy *)
220           begin
221            debug("Last chance: "^string_of_float (Unix.gettimeofday()));
222            given_clause ~noinfer:true bag maxvar iterno max_steps 
223              (Some (Unix.gettimeofday () +. 20.))
224              actives passives g_actives g_passives;
225            raise (Stop (Timeout (maxvar,bag)));
226           end
227         else raise (Stop (Timeout (maxvar,bag)));
228
229     let use_age = iterno mod 5 = 0 in
230
231     let rec aux_select bag passives g_passives =
232       let backward,(weight,current),passives,g_passives =
233         select ~use_age:false passives g_passives
234       in
235         if use_age && weight > monster then
236           let bag,cl = Terms.add_to_bag current bag in
237             if backward then
238               aux_select bag passives (add_passive_clause g_passives cl)
239             else
240               aux_select bag (add_passive_clause passives cl) g_passives
241         else
242         if backward then
243           let _ = debug ("Selected goal : " ^ Pp.pp_unit_clause current) in
244          match 
245            if noinfer then 
246              if weight > monster then None else Some (bag,current)
247            else 
248              Sup.simplify_goal 
249                ~no_demod:false maxvar (snd actives) bag g_actives current 
250          with
251             | None -> aux_select bag passives g_passives
252             | Some (bag,g_current) ->
253                if noinfer then 
254                  let g_actives = g_current :: g_actives in 
255                  bag,maxvar,actives,passives,g_actives,g_passives
256                else
257                  backward_infer_step bag maxvar actives passives
258                    g_actives g_passives g_current
259         else
260           let _ = debug ("Selected fact : " ^ Pp.pp_unit_clause current) in
261           (*let is_orphan = Sup.orphan_murder bag (fst actives) current in*)
262           match 
263             if noinfer then 
264               if weight > monster then bag,None 
265               else  bag, Some (current,actives)
266             else if Sup.orphan_murder bag (fst actives) current then
267               let _ = debug "Orphan murdered" in
268               let bag = Terms.replace_in_bag (current,true) bag in
269                 bag, None
270             else Sup.keep_simplified current actives bag maxvar
271           with
272         (*match Sup.one_pass_simplification current actives bag maxvar with*)
273               | bag,None -> aux_select bag passives g_passives
274               | bag,Some (current,actives) ->
275 (*                    if is_orphan then prerr_endline
276                       ("WRONG discarded: " ^ (Pp.pp_unit_clause current));
277                   List.iter (fun x ->
278                                prerr_endline (Pp.pp_unit_clause x))
279                     (fst actives);*)
280
281 (*                  List.iter (fun (id,_,_,_) -> let (cl,d) =
282                              Terms.M.find id bag in 
283                              if d then prerr_endline
284                                ("WRONG discarded: " ^ (Pp.pp_unit_clause cl)))
285                     (current::fst actives);*)
286                   if noinfer then
287                     let actives = 
288                       current::fst actives,
289                       IDX.index_unit_clause (snd actives) current
290                     in
291                     bag,maxvar,actives,passives,g_actives,g_passives
292                   else
293                     forward_infer_step bag maxvar actives passives
294                       g_actives g_passives current
295     in
296     
297
298       (*prerr_endline "Active table :"; 
299        (List.iter (fun x -> prerr_endline (Pp.pp_unit_clause x))
300           (fst actives)); *)
301
302     let bag,maxvar,actives,passives,g_actives,g_passives =      
303       aux_select bag passives g_passives
304     in
305       debug
306         (Printf.sprintf "Number of active goals : %d"
307            (List.length g_actives));
308       debug
309         (Printf.sprintf "Number of passive goals : %d"
310            (passive_set_cardinal g_passives));
311       debug
312         (Printf.sprintf "Number of actives : %d" (List.length (fst actives)));
313       debug
314         (Printf.sprintf "Number of passives : %d"
315            (passive_set_cardinal passives));
316       given_clause ~noinfer
317         bag maxvar iterno max_steps timeout 
318         actives passives g_actives g_passives
319   ;;
320
321   let paramod ~max_steps ?timeout (bag,maxvar) ~g_passives ~passives =
322     let initial_timestamp = Unix.gettimeofday () in
323     let passives =
324       add_passive_clauses ~no_weight:true passive_empty_set passives
325     in
326     let g_passives =
327       add_passive_goals ~no_weight:true passive_empty_set g_passives
328     in
329     let g_actives = [] in
330     let actives = [], IDX.DT.empty in
331     try 
332      given_clause ~noinfer:false
333       bag maxvar 0 max_steps timeout actives passives g_actives g_passives
334     with 
335     | Sup.Success (bag, _, (i,_,_,_)) ->
336         let l =
337           let rec traverse ongoal (accg,acce) i =
338             match Terms.get_from_bag i bag with
339               | (id,_,_,Terms.Exact _),_ ->
340                   if ongoal then [i],acce else
341                     if (List.mem i acce) then accg,acce else accg,acce@[i]
342               | (_,_,_,Terms.Step (_,i1,i2,_,_,_)),_ ->
343                   if (not ongoal) && (List.mem i acce) then accg,acce
344                   else
345                     let accg,acce = 
346                       traverse false (traverse ongoal (accg,acce) i1) i2
347                     in
348                       if ongoal then i::accg,acce else accg,i::acce
349           in
350           let gsteps,esteps = traverse true ([],[]) i in
351             (List.rev esteps)@gsteps
352         in
353 (*        List.iter (fun id -> let (cl,d) =
354                        Terms.M.find id bag in 
355                     if d then prerr_endline (Pp.pp_unit_clause cl)) l;*)
356         prerr_endline 
357           (Printf.sprintf "Found proof, %fs" 
358             (Unix.gettimeofday() -. initial_timestamp));
359         (* 
360         prerr_endline "Proof:"; 
361         List.iter (fun x ->
362           prerr_endline (Pp.pp_unit_clause (fst(Terms.M.find x bag)))) l;
363         *)
364         Unsatisfiable [ bag, i, l ]
365     | Stop (Unsatisfiable _) -> Error "stop bug solution found!"
366     | Stop o -> o
367   ;;
368
369 end