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