]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/paramodulation/saturation.ml
fixes (mainly) to demodulation and meta_convertibility
[helm.git] / helm / ocaml / paramodulation / saturation.ml
1 open Inference;;
2 open Utils;;
3
4 type result =
5   | Failure
6   | Success of Cic.term option * environment
7 ;;
8
9
10 type equality_sign = Negative | Positive;;
11
12 let string_of_sign = function
13   | Negative -> "Negative"
14   | Positive -> "Positive"
15 ;;
16
17
18 module OrderedEquality =
19 struct
20   type t = Inference.equality
21
22   let compare eq1 eq2 =
23     match meta_convertibility_eq eq1 eq2 with
24     | true -> 0
25     | false ->
26         let _, (ty, left, right), _, _ = eq1
27         and _, (ty', left', right'), _, _ = eq2 in
28         let weight_of t = fst (weight_of_term ~consider_metas:false t) in
29         let w1 = (weight_of ty) + (weight_of left) + (weight_of right)
30         and w2 = (weight_of ty') + (weight_of left') + (weight_of right') in
31         match Pervasives.compare w1 w2 with
32         | 0 -> Pervasives.compare eq1 eq2
33         | res -> res
34 end
35
36 module EqualitySet = Set.Make(OrderedEquality);;
37
38
39 let weight_age_ratio = ref 0;; (* settable by the user from the command line *)
40 let weight_age_counter = ref !weight_age_ratio;;
41
42 let set_selection = ref (fun set -> EqualitySet.min_elt set);;
43
44 let select env passive =
45   let (neg_list, neg_set), (pos_list, pos_set) = passive in
46   if !weight_age_ratio > 0 then
47     weight_age_counter := !weight_age_counter - 1;
48   match !weight_age_counter with
49   | 0 -> (
50       weight_age_counter := !weight_age_ratio;
51       match neg_list, pos_list with
52       | hd::tl, pos ->
53           (Negative, hd), ((tl, EqualitySet.remove hd neg_set), (pos, pos_set))
54       | [], hd::tl ->
55           (Positive, hd), (([], neg_set), (tl, EqualitySet.remove hd pos_set))
56       | _, _ -> assert false
57     )
58   | _ ->
59       let remove eq l =
60         List.filter (fun e -> not (e = eq)) l
61       in
62       if EqualitySet.is_empty neg_set then
63         let current = !set_selection pos_set in
64         let passive =
65           (neg_list, neg_set),
66           (remove current pos_list, EqualitySet.remove current pos_set)
67         in
68         (Positive, current), passive
69       else
70         let current = !set_selection neg_set in
71         let passive =
72           (remove current neg_list, EqualitySet.remove current neg_set),
73           (pos_list, pos_set)
74         in
75         (Negative, current), passive
76 ;;
77
78
79 let make_passive neg pos =
80   let set_of equalities =
81     List.fold_left (fun s e -> EqualitySet.add e s) EqualitySet.empty equalities
82   in
83   (neg, set_of neg), (pos, set_of pos)
84 ;;
85
86
87 let add_to_passive passive (new_neg, new_pos) =
88   let (neg_list, neg_set), (pos_list, pos_set) = passive in
89   let ok set equality = not (EqualitySet.mem equality set) in
90   let neg = List.filter (ok neg_set) new_neg
91   and pos = List.filter (ok pos_set) new_pos in
92   let add set equalities =
93     List.fold_left (fun s e -> EqualitySet.add e s) set equalities
94   in
95   (neg @ neg_list, add neg_set neg), (pos_list @ pos, add pos_set pos)
96 ;;
97
98
99 let passive_is_empty = function
100   | ([], _), ([], _) -> true
101   | _ -> false
102 ;;
103
104
105 (* TODO: find a better way! *)
106 let maxmeta = ref 0;;
107
108 let infer env sign current active =
109   let rec infer_negative current = function
110     | [] -> [], []
111     | (Negative, _)::tl -> infer_negative current tl
112     | (Positive, equality)::tl ->
113         let res = superposition_left env current equality in
114         let neg, pos = infer_negative current tl in
115         res @ neg, pos
116
117   and infer_positive current = function
118     | [] -> [], []
119     | (Negative, equality)::tl ->
120         let res = superposition_left env equality current in
121         let neg, pos = infer_positive current tl in
122         res @ neg, pos
123     | (Positive, equality)::tl ->
124         let maxm, res = superposition_right !maxmeta env current equality in
125         let maxm, res' = superposition_right maxm env equality current in
126         maxmeta := maxm;
127         let neg, pos = infer_positive current tl in
128
129 (*         Printf.printf "risultato di superposition_right: %s %s\n%s\n\n" *)
130 (*           (string_of_equality ~env current) (string_of_equality ~env equality) *)
131 (*           (String.concat "\n" (List.map (string_of_equality ~env) res)); *)
132 (*         Printf.printf "risultato di superposition_right: %s %s\n%s\n\n" *)
133 (*           (string_of_equality ~env equality) (string_of_equality ~env current) *)
134 (*           (String.concat "\n" (List.map (string_of_equality ~env) res')); *)
135         
136         neg, res @ res' @ pos
137   in
138   match sign with
139   | Negative -> infer_negative current active
140   | Positive -> infer_positive current active
141 ;;
142
143
144 let contains_empty env (negative, positive) =
145   let metasenv, context, ugraph = env in
146   try
147     let (proof, _, _, _) =
148       List.find
149         (fun (proof, (ty, left, right), m, a) ->
150            fst (CicReduction.are_convertible context left right ugraph))
151         negative
152     in
153     true, Some proof
154   with Not_found ->
155     false, None
156 ;;
157
158
159 let forward_simplify env (sign, current) active =
160   (* first step, remove already present equalities *)
161   let duplicate =
162     let rec aux = function
163       | [] -> false
164       | (s, eq)::tl when s = sign ->
165           if meta_convertibility_eq current eq then true
166           else aux tl
167       | _::tl -> aux tl
168     in
169     aux active
170   in
171   if duplicate then
172     None
173   else
174     let rec aux env (sign, current) = function
175       | [] -> Some (sign, current)
176       | (Negative, _)::tl -> aux env (sign, current) tl
177       | (Positive, equality)::tl ->
178           let newmeta, current =
179             demodulation !maxmeta env current equality in
180           maxmeta := newmeta;
181           if is_identity env current then
182             None
183           else
184             aux env (sign, current) tl
185     in
186     aux env (sign, current) active
187 ;;
188
189
190 let forward_simplify_new env (new_neg, new_pos) active =
191   let remove_identities equalities =
192     let ok eq = not (is_identity env eq) in
193     List.filter ok equalities
194   in
195   let rec simpl active target =
196     match active with
197     | [] -> target
198     | (Negative, _)::tl -> simpl tl target
199     | (Positive, source)::tl ->
200         let newmeta, target = demodulation !maxmeta env target source in
201         maxmeta := newmeta;
202         if is_identity env target then target
203         else simpl tl target
204   in
205   let new_neg = List.map (simpl active) new_neg
206   and new_pos = List.map (simpl active) new_pos in
207   new_neg, remove_identities new_pos
208 ;;
209
210
211 let backward_simplify env (sign, current) active =
212   match sign with
213   | Negative -> active
214   | Positive ->
215       let active = 
216         List.map
217           (fun (s, equality) ->
218              (*            match s with *)
219              (*            | Negative -> s, equality *)
220              (*            | Positive -> *)
221              let newmeta, equality =
222                demodulation !maxmeta env equality current in
223              maxmeta := newmeta;
224              s, equality)
225           active
226       in
227       let active =
228         List.filter (fun (s, eq) -> not (is_identity env eq)) active
229       in
230       let find eq1 where =
231         List.exists (fun (s, e) -> meta_convertibility_eq eq1 e) where
232       in
233       List.fold_right
234         (fun (s, eq) res -> if find eq res then res else (s, eq)::res)
235         active []
236 ;;
237
238
239 let rec given_clause env passive active =
240   match passive_is_empty passive with
241   | true -> Failure
242   | false ->
243 (*       Printf.printf "before select\n"; *)
244       let (sign, current), passive = select env passive in
245 (*       Printf.printf "before simplification: sign: %s\ncurrent: %s\n\n" *)
246 (*         (string_of_sign sign) (string_of_equality ~env current); *)
247       match forward_simplify env (sign, current) active with
248       | None when sign = Negative ->
249           Printf.printf "OK!!! %s %s" (string_of_sign sign)
250             (string_of_equality ~env current);
251           print_newline ();
252           let proof, _, _, _ = current in
253           Success (Some proof, env)
254       | None ->
255 (*           Printf.printf "avanti... %s %s" (string_of_sign sign) *)
256 (*             (string_of_equality ~env current); *)
257 (*           print_newline (); *)
258           given_clause env passive active
259       | Some (sign, current) ->
260 (*           Printf.printf "selected: %s %s" *)
261 (*             (string_of_sign sign) (string_of_equality ~env current); *)
262 (*           print_newline (); *)
263
264           let new' = infer env sign current active in
265
266           let new' = forward_simplify_new env new' active in
267           
268           let active =
269             backward_simplify env (sign, current) active
270 (*             match new' with *)
271 (*             | [], [] -> backward_simplify env (sign, current) active *)
272 (*             | _ -> active *)
273           in
274
275           print_endline "\n================================================";
276           let _ =
277             Printf.printf "active:\n%s\n"
278               (String.concat "\n"
279                  ((List.map
280                      (fun (s, e) -> (string_of_sign s) ^ " " ^
281                         (string_of_equality ~env e)) active)));
282             print_newline ();
283           in
284
285 (*           let _ = *)
286 (*             match new' with *)
287 (*             | neg, pos -> *)
288 (*                 Printf.printf "new':\n%s\n" *)
289 (*                   (String.concat "\n" *)
290 (*                      ((List.map *)
291 (*                          (fun e -> "Negative " ^ *)
292 (*                             (string_of_equality ~env e)) neg) @ *)
293 (*                         (List.map *)
294 (*                            (fun e -> "Positive " ^ *)
295 (*                               (string_of_equality ~env e)) pos))); *)
296 (*                 print_newline (); *)
297 (*           in                 *)
298           match contains_empty env new' with
299           | false, _ -> 
300               let active =
301                 match sign with
302                 | Negative -> (sign, current)::active
303                 | Positive -> active @ [(sign, current)]
304               in
305               let passive = add_to_passive passive new' in
306               given_clause env passive active
307           | true, proof ->
308               Success (proof, env)
309 ;;
310
311
312 let get_from_user () =
313   let dbd = Mysql.quick_connect
314     ~host:"localhost" ~user:"helm" ~database:"mowgli" () in
315   let rec get () =
316     match read_line () with
317     | "" -> []
318     | t -> t::(get ())
319   in
320   let term_string = String.concat "\n" (get ()) in
321   let env, metasenv, term, ugraph =
322     List.nth (Disambiguate.Trivial.disambiguate_string dbd term_string) 0
323   in
324   term, metasenv, ugraph
325 ;;
326
327
328 let main () =
329   let module C = Cic in
330   let module T = CicTypeChecker in
331   let module PET = ProofEngineTypes in
332   let module PP = CicPp in
333   let term, metasenv, ugraph = get_from_user () in
334   let proof = None, (1, [], term)::metasenv, C.Meta (1, []), term in
335   let proof, goals =
336     PET.apply_tactic (PrimitiveTactics.intros_tac ()) (proof, 1) in
337   let goal = List.nth goals 0 in
338   let _, metasenv, meta_proof, _ = proof in
339   let _, context, goal = CicUtil.lookup_meta goal metasenv in
340   let equalities, maxm = find_equalities context proof in
341   maxmeta := maxm; (* TODO ugly!! *)
342   let env = (metasenv, context, ugraph) in
343   try
344     let term_equality = equality_of_term meta_proof goal in
345     let meta_proof, (eq_ty, left, right), _, _ = term_equality in
346     let active = [] in
347     let passive = make_passive [term_equality] equalities in
348     Printf.printf "\ncurrent goal: %s ={%s} %s\n"
349       (PP.ppterm left) (PP.ppterm eq_ty) (PP.ppterm right);
350     Printf.printf "\ncontext:\n%s\n" (PP.ppcontext context);
351     Printf.printf "\nmetasenv:\n%s\n" (print_metasenv metasenv);
352     Printf.printf "\nequalities:\n";
353     List.iter
354       (function (_, (ty, t1, t2), _, _) ->
355          let w1 = weight_of_term t1 in
356          let w2 = weight_of_term t2 in
357          let res = nonrec_kbo t1 t2 in
358          Printf.printf "{%s}: %s<%s> %s %s<%s>\n" (PP.ppterm ty)
359            (PP.ppterm t1) (string_of_weight w1)
360            (string_of_comparison res)
361            (PP.ppterm t2) (string_of_weight w2))
362       equalities;
363     print_endline "--------------------------------------------------";
364     let start = Sys.time () in
365     print_endline "GO!";
366     let res = given_clause env passive active in
367     let finish = Sys.time () in
368     match res with
369     | Failure ->
370         Printf.printf "NO proof found! :-(\n\n"
371     | Success (Some proof, env) ->
372         Printf.printf "OK, found a proof!:\n%s\n%.9f\n" (PP.ppterm proof)
373           (finish -. start);
374     | Success (None, env) ->
375         Printf.printf "Success, but no proof?!?\n\n"
376   with exc ->
377     print_endline ("EXCEPTION: " ^ (Printexc.to_string exc));
378 ;;
379
380
381 let configuration_file = ref "../../gTopLevel/gTopLevel.conf.xml";;
382
383 let _ =
384   let set_ratio v = weight_age_ratio := v; weight_age_counter := v
385   and set_sel () = set_selection := (fun s -> EqualitySet.max_elt s)
386   and set_conf f = configuration_file := f
387   in
388   Arg.parse [
389     "-r", Arg.Int set_ratio, "Weight-Age equality selection ratio";
390
391     "-i", Arg.Unit set_sel,
392     "Inverse selection (select heaviest equalities before)";
393
394     "-c", Arg.String set_conf, "Configuration file (for the db connection)";
395   ] (fun a -> ()) "Usage:"
396 in
397 Helm_registry.load_from !configuration_file;
398 main ()