]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/ng_paramodulation/paramod.ml
Implemented orphan murder test (clauses are not discarded for now)
[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 Sup.simplify_goal maxvar (snd actives) bag acc c with
143                | None -> bag, acc
144                | Some (bag,c) -> bag,c::acc)
145           (bag,[]) g_actives 
146       in
147       let ctable = IDX.index_unit_clause IDX.DT.empty current in
148       let bag, maxvar, new_goals = 
149         List.fold_left 
150           (fun (bag,m,acc) g -> 
151              let bag, m, ng = Sup.infer_left bag m g
152                ([current],ctable) in
153                bag,m,ng@acc) 
154           (bag,maxvar,[]) g_actives 
155       in
156         bag, maxvar, actives,
157     add_passive_clauses passives new_clauses, g_actives,
158     add_passive_clauses g_passives new_goals
159   ;;
160  
161   let rec given_clause 
162     bag maxvar iterno max_steps timeout 
163     actives passives g_actives g_passives 
164   =
165     let iterno = iterno + 1 in
166     if iterno = max_steps then       
167       raise (Failure ("No iterations left !",bag,maxvar,iterno));
168     (* timeout check: gettimeofday called only if timeout set *)
169     (match timeout with
170     | None -> ()
171     | Some timeout ->
172         if Unix.gettimeofday () > timeout then
173           raise (Failure ("Timeout !",bag,maxvar,iterno)));
174
175     let use_age = iterno mod 10 = 0 in
176
177     let rec aux_select bag passives g_passives =
178       let backward,current,passives,g_passives =
179         select ~use_age:false passives g_passives
180       in
181         if backward then
182          match Sup.simplify_goal maxvar (snd actives) bag g_actives current with
183             | None -> aux_select bag passives g_passives
184             | Some (bag,g_current) ->
185                 backward_infer_step bag maxvar actives passives
186                   g_actives g_passives g_current
187         else
188           (* debug ("Selected fact : " ^ Pp.pp_unit_clause current); *)
189           match Sup.keep_simplified current actives bag maxvar with
190         (*  match Sup.one_pass_simplification current actives bag maxvar with*)
191               | bag,None -> aux_select bag passives g_passives
192               | bag,Some (current,actives) ->
193                   forward_infer_step bag maxvar actives passives
194                                      g_actives g_passives current
195     in
196     
197     (* prerr_endline "Bag :"; prerr_endline (Pp.pp_bag bag);
198       prerr_endline "Active table :"; 
199        (List.iter (fun x -> prerr_endline (Pp.pp_unit_clause x))
200           (fst actives)); *)
201
202     let bag,maxvar,actives,passives,g_actives,g_passives =      
203       aux_select bag passives g_passives
204     in
205       debug
206         (Printf.sprintf "Number of active goals : %d"
207            (List.length g_actives));
208       debug
209         (Printf.sprintf "Number of passive goals : %d"
210            (passive_set_cardinal g_passives));
211       debug
212         (Printf.sprintf "Number of actives : %d" (List.length (fst actives)));
213       debug
214         (Printf.sprintf "Number of passives : %d"
215            (passive_set_cardinal passives));
216       given_clause 
217         bag maxvar iterno max_steps timeout 
218         actives passives g_actives g_passives
219   ;;
220
221   let paramod ~max_steps ?timeout (bag,maxvar) ~g_passives ~passives =
222     let initial_timestamp = Unix.gettimeofday () in
223     let passives =
224       add_passive_clauses ~no_weight:true passive_empty_set passives
225     in
226     let g_passives =
227       add_passive_clauses ~no_weight:true passive_empty_set g_passives
228     in
229     let g_actives = [] in
230     let actives = [], IDX.DT.empty in
231     try 
232      given_clause 
233       bag maxvar 0 max_steps timeout actives passives g_actives g_passives
234     with 
235     | Sup.Success (bag, _, (i,_,_,_)) ->
236         let l =
237           let rec traverse ongoal (accg,acce) i =
238             match Terms.M.find i bag with
239               | (id,_,_,Terms.Exact _),_ ->
240                 if ongoal then [i],acce else
241                   if (List.mem i acce) then accg,acce else accg,acce@[i]
242               | (_,_,_,Terms.Step (_,i1,i2,_,_,_)),_ ->
243                 if (not ongoal) && (List.mem i acce) then accg,acce
244                 else
245                     let accg,acce = 
246                     traverse false (traverse ongoal (accg,acce) i1) i2
247                   in
248                     if ongoal then i::accg,acce else accg,i::acce
249           in
250           let gsteps,esteps = traverse true ([],[]) i in
251             (List.rev esteps)@gsteps
252         in
253         prerr_endline 
254           (Printf.sprintf "Found proof, %fs" 
255             (Unix.gettimeofday() -. initial_timestamp));
256         (* 
257         prerr_endline "Proof:"; 
258         List.iter (fun x ->
259           prerr_endline (Pp.pp_unit_clause (fst(Terms.M.find x bag)))) l;
260         *)
261         [ bag, i, l ]
262     | Failure (msg,_bag,_maxvar,iterno) -> 
263         prerr_endline msg;
264         prerr_endline (Printf.sprintf "FAILURE in %d iterations" iterno); 
265         []
266   ;;
267
268 end