]> matita.cs.unibo.it Git - helm.git/blob - components/tactics/paramodulation/saturation.ml
b50e0a49f09fdafdaea42c51db772a880a58422c
[helm.git] / components / tactics / paramodulation / saturation.ml
1 (* Copyright (C) 2005, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://cs.unibo.it/helm/.
24  *)
25
26 let _profiler = <:profiler<_profiler>>;;
27
28 (* $Id$ *)
29
30 open Inference;;
31 open Utils;;
32
33 (* set to false to disable paramodulation inside auto_tac *)
34 let connect_to_auto = true;;
35
36
37 (* profiling statistics... *)
38 let infer_time = ref 0.;;
39 let forward_simpl_time = ref 0.;;
40 let forward_simpl_new_time = ref 0.;;
41 let backward_simpl_time = ref 0.;;
42 let passive_maintainance_time = ref 0.;;
43
44 (* limited-resource-strategy related globals *)
45 let processed_clauses = ref 0;; (* number of equalities selected so far... *)
46 let time_limit = ref 0.;; (* in seconds, settable by the user... *)
47 let start_time = ref 0.;; (* time at which the execution started *)
48 let elapsed_time = ref 0.;;
49 (* let maximal_weight = ref None;; *)
50 let maximal_retained_equality = ref None;;
51
52 (* equality-selection related globals *)
53 let use_fullred = ref true;;
54 let weight_age_ratio = ref 6 (* 5 *);; (* settable by the user *)
55 let weight_age_counter = ref !weight_age_ratio ;;
56 let symbols_ratio = ref 0 (* 3 *);;
57 let symbols_counter = ref 0;;
58
59 (* non-recursive Knuth-Bendix term ordering by default *)
60 (* Utils.compare_terms := Utils.rpo;; *)
61 (* Utils.compare_terms := Utils.nonrec_kbo;; *)
62 (* Utils.compare_terms := Utils.ao;; *)
63
64 (* statistics... *)
65 let derived_clauses = ref 0;;
66 let kept_clauses = ref 0;;
67
68 (* index of the greatest Cic.Meta created - TODO: find a better way! *)
69 let maxmeta = ref 0;;
70
71 (* varbiables controlling the search-space *)
72 let maxdepth = ref 3;;
73 let maxwidth = ref 3;;
74
75 type new_proof = 
76   Equality.goal_proof * Equality.proof * int * Subst.substitution * Cic.metasenv
77 type result =
78   | ParamodulationFailure of string
79   | ParamodulationSuccess of new_proof
80 ;;
81
82 type goal = Equality.goal_proof * Cic.metasenv * Cic.term;;
83
84 type theorem = Cic.term * Cic.term * Cic.metasenv;;
85
86 let symbols_of_equality equality = 
87   let (_, _, (_, left, right, _), _,_) = Equality.open_equality equality in
88   let m1 = symbols_of_term left in
89   let m = 
90     TermMap.fold
91       (fun k v res ->
92          try
93            let c = TermMap.find k res in
94            TermMap.add k (c+v) res
95          with Not_found ->
96            TermMap.add k v res)
97       (symbols_of_term right) m1
98   in
99   m
100 ;;
101
102 (* griggio *)
103 module OrderedEquality = struct 
104   type t = Equality.equality
105
106   let compare eq1 eq2 =
107     match Equality.meta_convertibility_eq eq1 eq2 with
108     | true -> 0
109     | false -> 
110         let w1, _, (ty,left, right, _), m1,_ = Equality.open_equality eq1 in
111         let w2, _, (ty',left', right', _), m2,_ = Equality.open_equality eq2 in
112         match Pervasives.compare w1 w2 with
113         | 0 -> 
114             let res = (List.length m1) - (List.length m2) in 
115             if res <> 0 then res else 
116               Equality.compare eq1 eq2
117         | res -> res 
118 end 
119
120 module EqualitySet = Set.Make(OrderedEquality);;
121
122 exception Empty_list;;
123
124 let passive_is_empty = function
125   | ([], _), _ -> true
126   | _ -> false
127 ;;
128
129
130 let size_of_passive ((passive_list, ps), _) = List.length passive_list
131 (* EqualitySet.cardinal ps *)
132 ;;
133
134
135 let size_of_active (active_list, _) = List.length active_list
136 ;;
137
138 let age_factor = 0.01;;
139
140 (**
141    selects one equality from passive. The selection strategy is a combination
142    of weight, age and goal-similarity
143 *)
144
145 let rec select env (goals,_) passive =
146   processed_clauses := !processed_clauses + 1;
147   let goal =
148     match (List.rev goals) with goal::_ -> goal | _ -> assert false
149   in
150   let (pos_list, pos_set), passive_table = passive in
151   let remove eq l = List.filter (fun e -> Equality.compare e eq <> 0) l in
152   if !weight_age_ratio > 0 then
153     weight_age_counter := !weight_age_counter - 1;
154   match !weight_age_counter with
155   | 0 -> (
156       weight_age_counter := !weight_age_ratio;
157       let rec skip_giant pos_list pos_set passive_table =
158         match pos_list with
159           | (hd:EqualitySet.elt)::tl ->
160               let w,_,_,_,_ = Equality.open_equality hd in
161               let passive_table =
162                 Indexing.remove_index passive_table hd
163               in 
164               let pos_set = EqualitySet.remove hd pos_set in
165                 if w < 500 then
166                   hd, ((tl, pos_set), passive_table)
167                 else
168                   (prerr_endline ("\n\n\nGIANT SKIPPED: "^string_of_int w^"\n\n\n");
169                   skip_giant tl pos_set passive_table)
170           | _ -> assert false
171       in
172         skip_giant pos_list pos_set passive_table)
173   | _ when (!symbols_counter > 0) -> 
174      (symbols_counter := !symbols_counter - 1;
175       let cardinality map =
176         TermMap.fold (fun k v res -> res + v) map 0
177       in
178       let symbols =
179         let _, _, term = goal in
180         symbols_of_term term
181       in
182       let card = cardinality symbols in
183       let foldfun k v (r1, r2) = 
184         if TermMap.mem k symbols then
185           let c = TermMap.find k symbols in
186           let c1 = abs (c - v) in
187           let c2 = v - c1 in
188           r1 + c2, r2 + c1
189         else
190           r1, r2 + v
191       in
192       let f equality (i, e) =
193         let common, others =
194           TermMap.fold foldfun (symbols_of_equality equality) (0, 0)
195         in
196         let c = others + (abs (common - card)) in
197         if c < i then (c, equality)
198         else (i, e)
199       in
200       let e1 = EqualitySet.min_elt pos_set in
201       let initial =
202         let common, others = 
203           TermMap.fold foldfun (symbols_of_equality e1) (0, 0)
204         in
205         (others + (abs (common - card))), e1
206       in
207       let _, current = EqualitySet.fold f pos_set initial in
208       let passive_table =
209         Indexing.remove_index passive_table current
210       in
211         current,
212       ((remove current pos_list, EqualitySet.remove current pos_set),
213        passive_table))
214   | _ ->
215       symbols_counter := !symbols_ratio;
216       let current = EqualitySet.min_elt pos_set in
217       let passive_table =
218         Indexing.remove_index passive_table current
219       in
220         current, 
221       ((remove current pos_list, EqualitySet.remove current pos_set),
222       passive_table)
223 ;;
224
225 let filter_dependent passive id =
226   prerr_endline ("+++++++++++++++passives "^
227                    ( string_of_int (size_of_passive passive)));
228   let (pos_list, pos_set), passive_table = passive in
229   let passive =
230     List.fold_right
231       (fun eq ((list,set),table) ->
232          if Equality.depend eq id then
233            (let _,_,_,_,id_eq = Equality.open_equality eq in
234               if id_eq = 9228 then 
235                 prerr_endline ("\n\n--------filtering "^(string_of_int id_eq));
236            ((list, 
237              EqualitySet.remove eq set),
238             Indexing.remove_index table eq))
239          else 
240               ((eq::list, set),table))
241       pos_list (([],pos_set),passive_table) in
242   prerr_endline ("+++++++++++++++passives "^
243                    ( string_of_int (size_of_passive passive)));  
244   passive
245 ;;
246
247
248 (* initializes the passive set of equalities *)
249 let make_passive pos =
250   let set_of equalities =
251     List.fold_left (fun s e -> EqualitySet.add e s) EqualitySet.empty equalities
252   in
253   let table =
254       List.fold_left (fun tbl e -> Indexing.index tbl e) Indexing.empty pos
255   in
256   (pos, set_of pos),
257   table
258 ;;
259
260
261 let make_active () =
262   [], Indexing.empty
263 ;;
264
265
266 (* adds to passive a list of equalities new_pos *)
267 let add_to_passive passive new_pos =
268   let (pos_list, pos_set), table = passive in
269   let ok set equality = not (EqualitySet.mem equality set) in
270   let pos = List.filter (ok pos_set) new_pos in
271   let table = 
272      List.fold_left (fun tbl e -> Indexing.index tbl e) table pos 
273   in
274   let add set equalities =
275     List.fold_left (fun s e -> EqualitySet.add e s) set equalities
276   in
277   (pos_list @ pos, add pos_set pos),
278   table
279 ;;
280
281 (* TODO *)
282 (* removes from passive equalities that are estimated impossible to activate
283    within the current time limit *)
284 let prune_passive howmany (active, _) passive =
285   let (pl, ps), tbl = passive in
286   let howmany = float_of_int howmany
287   and ratio = float_of_int !weight_age_ratio in
288   let round v =
289     let t = ceil v in 
290     int_of_float (if t -. v < 0.5 then t else v)
291   in
292   let in_weight = round (howmany *. ratio /. (ratio +. 1.))
293   and in_age = round (howmany /. (ratio +. 1.)) in 
294   debug_print
295     (lazy (Printf.sprintf "in_weight: %d, in_age: %d\n" in_weight in_age));
296   let counter = ref !symbols_ratio in
297   let rec pickw w ps =
298     if w > 0 then
299       if !counter > 0 then
300         let _ =
301           counter := !counter - 1;
302           if !counter = 0 then counter := !symbols_ratio in
303         let e = EqualitySet.min_elt ps in
304         let ps' = pickw (w-1) (EqualitySet.remove e ps) in
305           EqualitySet.add e ps'
306       else
307         let e = EqualitySet.min_elt ps in
308         let ps' = pickw (w-1) (EqualitySet.remove e ps) in
309         EqualitySet.add e ps'        
310     else
311       EqualitySet.empty
312   in
313   let ps = pickw in_weight ps in
314   let rec picka w s l =
315     if w > 0 then
316       match l with
317       | [] -> w, s, []
318       | hd::tl when not (EqualitySet.mem hd s) ->
319           let w, s, l = picka (w-1) s tl in
320           w, EqualitySet.add hd s, hd::l
321       | hd::tl ->
322           let w, s, l = picka w s tl in
323           w, s, hd::l
324     else
325       0, s, l
326   in
327   let _, ps, pl = picka in_age ps pl in
328   if not (EqualitySet.is_empty ps) then
329     maximal_retained_equality := Some (EqualitySet.max_elt ps); 
330   let tbl =
331     EqualitySet.fold
332       (fun e tbl -> Indexing.index tbl e) ps Indexing.empty
333   in
334   (pl, ps), tbl  
335 ;;
336
337
338 (** inference of new equalities between current and some in active *)
339 let infer eq_uri env current (active_list, active_table) =
340   let (_,c,_) = env in 
341   if Utils.debug_metas then
342     (ignore(Indexing.check_target c current "infer1");
343      ignore(List.map (function current -> Indexing.check_target c current "infer2") active_list)); 
344   let new_pos = 
345       let maxm, copy_of_current = Equality.fix_metas !maxmeta current in
346         maxmeta := maxm;
347       let active_table =  Indexing.index active_table copy_of_current in
348       let _ = <:start<current contro active>> in
349       let maxm, res =
350         Indexing.superposition_right eq_uri !maxmeta env active_table current 
351       in
352       let _ = <:stop<current contro active>> in
353       if Utils.debug_metas then
354         ignore(List.map 
355                  (function current -> 
356                     Indexing.check_target c current "sup0") res);
357       maxmeta := maxm;
358       let rec infer_positive table = function
359         | [] -> []
360         | equality::tl ->
361             let maxm, res =
362               Indexing.superposition_right 
363                 ~subterms_only:true eq_uri !maxmeta env table equality 
364             in
365               maxmeta := maxm;
366               if Utils.debug_metas then
367                 ignore
368                   (List.map 
369                      (function current -> 
370                         Indexing.check_target c current "sup2") res);
371               let pos = infer_positive table tl in
372               res @ pos
373       in
374 (*
375       let maxm, copy_of_current = Equality.fix_metas !maxmeta current in
376         maxmeta := maxm;
377 *)
378       let curr_table = Indexing.index Indexing.empty current in
379       let _ = <:start<active contro current>> in
380       let pos = infer_positive curr_table ((*copy_of_current::*)active_list) in
381       let _ = <:stop<active contro current>> in
382       if Utils.debug_metas then 
383         ignore(List.map 
384                  (function current -> 
385                     Indexing.check_target c current "sup3") pos);
386       res @ pos
387   in
388   derived_clauses := !derived_clauses + (List.length new_pos);
389   match !maximal_retained_equality with
390     | None -> new_pos
391     | Some eq ->
392       ignore(assert false);
393       (* if we have a maximal_retained_equality, we can discard all equalities
394          "greater" than it, as they will never be reached...  An equality is
395          greater than maximal_retained_equality if it is bigger
396          wrt. OrderedEquality.compare and it is less similar than
397          maximal_retained_equality to the current goal *)
398         List.filter (fun e -> OrderedEquality.compare e eq <= 0) new_pos
399 ;;
400
401 let check_for_deep_subsumption env active_table eq =
402   let _,_,(eq_ty, left, right, order),metas,id = Equality.open_equality eq in
403   let check_subsumed deep l r = 
404     let eqtmp = 
405       Equality.mk_tmp_equality(0,(eq_ty,l,r,Utils.Incomparable),metas)in
406     match Indexing.subsumption env active_table eqtmp with
407     | None -> false
408     | Some _ -> true        
409   in 
410   let rec aux b (ok_so_far, subsumption_used) t1 t2  = 
411     match t1,t2 with
412       | t1, t2 when not ok_so_far -> ok_so_far, subsumption_used
413       | t1, t2 when subsumption_used -> t1 = t2, subsumption_used
414       | Cic.Appl (h1::l),Cic.Appl (h2::l') ->
415           let rc = check_subsumed b t1 t2 in 
416             if rc then 
417               true, true
418             else if h1 = h2 then
419               (try 
420                  List.fold_left2 
421                    (fun (ok_so_far, subsumption_used) t t' -> 
422                       aux true (ok_so_far, subsumption_used) t t')
423                    (ok_so_far, subsumption_used) l l'
424                with Invalid_argument _ -> false,subsumption_used)
425             else
426               false, subsumption_used
427     | _ -> false, subsumption_used 
428   in
429   fst (aux false (true,false) left right)
430 ;;
431
432 (* buttare via sign *)
433
434 (** simplifies current using active and passive *)
435 let forward_simplify 
436   eq_uri env (sign,current) ?passive (active_list, active_table) 
437 =
438   let _, context, _ = env in
439   let passive_table =
440     match passive with
441     | None -> None
442     | Some ((_, _), pt) -> Some pt
443   in
444   let demodulate table current = 
445     let newmeta, newcurrent =
446       Indexing.demodulation_equality eq_uri !maxmeta env table sign current in
447     maxmeta := newmeta;
448     if Equality.is_identity env newcurrent then
449       None
450     else
451       Some newcurrent
452   in
453   let rec demod current =
454     if Utils.debug_metas then
455       ignore (Indexing.check_target context current "demod0");
456     let res = demodulate active_table current in
457       if Utils.debug_metas then
458         ignore ((function None -> () | Some x -> 
459                    ignore (Indexing.check_target context x "demod1");()) res);
460     match res with
461     | None -> None
462     | Some newcurrent ->
463         match passive_table with
464         | None -> res
465         | Some passive_table -> 
466             match demodulate passive_table newcurrent with
467               | None -> None
468               | Some newnewcurrent -> 
469                   if Equality.compare newcurrent newnewcurrent <> 0 then 
470                     demod newnewcurrent
471                   else Some newnewcurrent
472   in 
473   let res = demod current in
474   match res with
475   | None -> None
476   | Some c ->
477       if Indexing.in_index active_table c then
478         None
479       else
480         match passive_table with
481         | None -> 
482             if check_for_deep_subsumption env active_table c then
483               None
484             else 
485               res
486 (*
487             if Indexing.subsumption env active_table c = None then
488               res
489             else
490               None
491 *)
492         | Some passive_table ->
493             if Indexing.in_index passive_table c then None
494             else 
495               if check_for_deep_subsumption env active_table c then
496                 None
497               else 
498 (*              if Indexing.subsumption env active_table c = None then*)
499                 (match Indexing.subsumption env passive_table c with
500                 | None -> res
501                 | Some (_,c',_) -> 
502                     None
503                     (*prerr_endline "\n\nPESCO DALLE PASSIVE LA PIU' GENERALE\n\n";
504                     Some c'*))
505 (*
506               else
507                 None
508 *)
509 ;;
510
511 (** simplifies new using active and passive *)
512 let forward_simplify_new eq_uri env new_pos ?passive active =
513   if Utils.debug_metas then
514     begin
515       let m,c,u = env in
516         ignore(List.map 
517         (fun current -> Indexing.check_target c current "forward new pos") 
518       new_pos;)
519     end;
520   let active_list, active_table = active in
521   let passive_table =
522     match passive with
523     | None -> None
524     | Some ((_, _), pt) -> Some pt
525   in
526   let demodulate sign table target =
527     let newmeta, newtarget =
528       Indexing.demodulation_equality eq_uri !maxmeta env table sign target 
529     in
530     maxmeta := newmeta;
531     newtarget
532   in
533   (* we could also demodulate using passive. Currently we don't *)
534   let new_pos =
535     List.map (demodulate Positive active_table) new_pos 
536   in
537   let new_pos_set =
538     List.fold_left
539       (fun s e ->
540          if not (Equality.is_identity env e) then
541            EqualitySet.add e s
542          else s)
543       EqualitySet.empty new_pos
544   in
545   let new_pos = EqualitySet.elements new_pos_set in
546
547   let subs =
548     match passive_table with
549     | None ->
550         (fun e -> (Indexing.subsumption env active_table e = None))
551     | Some passive_table ->
552         (fun e -> ((Indexing.subsumption env active_table e = None) &&
553                          (Indexing.subsumption env passive_table e = None)))
554   in
555   let is_duplicate =
556     match passive_table with
557     | None ->
558         (fun e -> not (Indexing.in_index active_table e))
559     | Some passive_table ->
560         (fun e ->
561            not ((Indexing.in_index active_table e) ||
562                   (Indexing.in_index passive_table e)))
563   in
564     List.filter subs (List.filter is_duplicate new_pos)
565 ;;
566
567
568 (** simplifies a goal with equalities in active and passive *)  
569 let rec simplify_goal env goal ?passive (active_list, active_table) =
570   let passive_table =
571     match passive with
572     | None -> None
573     | Some ((_, _), pt) -> Some pt
574   in
575   let demodulate table goal = Indexing.demodulation_goal env table goal in
576   let changed, goal =
577     match passive_table with
578     | None -> demodulate active_table goal
579     | Some passive_table ->
580         let changed, goal = demodulate active_table goal in
581 (*        let changed', goal = demodulate passive_table goal in*)
582         (changed (*|| changed'*)), goal
583   in
584   changed,
585   if not changed then 
586     goal 
587   else 
588     snd (simplify_goal env goal ?passive (active_list, active_table)) 
589 ;;
590
591
592 let simplify_goals env goals ?passive active =
593   let a_goals, p_goals = goals in
594   let p_goals = 
595     List.map
596       (fun g -> snd (simplify_goal env g ?passive active))
597       p_goals
598   in
599   let a_goals = 
600     List.map
601       (fun g -> snd (simplify_goal env g ?passive active))
602       a_goals
603   in
604   a_goals, p_goals
605 ;;
606
607
608 (** simplifies active usign new *)
609 let backward_simplify_active eq_uri env new_pos new_table min_weight active =
610   let active_list, active_table = active in
611   let active_list, newa, pruned = 
612     List.fold_right
613       (fun equality (res, newn,pruned) ->
614          let ew, _, _, _,id = Equality.open_equality equality in
615          if ew < min_weight then
616            equality::res, newn,pruned
617          else
618            match 
619              forward_simplify 
620                eq_uri env (Utils.Positive, equality) (new_pos, new_table) 
621            with
622            | None -> res, newn, id::pruned
623            | Some e ->
624                if Equality.compare equality e = 0 then
625                  e::res, newn, pruned
626                else 
627                  res, e::newn, pruned)
628       active_list ([], [],[])
629   in
630   let find eq1 where =
631     List.exists (Equality.meta_convertibility_eq eq1) where
632   in
633   let id_of_eq eq = 
634     let _, _, _, _,id = Equality.open_equality eq in id
635   in
636   let ((active1,pruned),tbl), newa =
637     List.fold_right
638       (fun eq ((res,pruned), tbl) ->
639          if List.mem eq res then
640            (res, (id_of_eq eq)::pruned),tbl 
641          else if (Equality.is_identity env eq) || (find eq res) then (
642            (res, (id_of_eq eq)::pruned),tbl
643          ) 
644          else
645            (eq::res,pruned), Indexing.index tbl eq)
646       active_list (([],pruned), Indexing.empty),
647     List.fold_right
648       (fun eq p ->
649          if (Equality.is_identity env eq) then p
650          else eq::p)
651       newa []
652   in
653   match newa with
654   | [] -> (active1,tbl), None, pruned 
655   | _ -> (active1,tbl), Some newa, pruned
656 ;;
657
658
659 (** simplifies passive using new *)
660 let backward_simplify_passive eq_uri env new_pos new_table min_weight passive =
661   let (pl, ps), passive_table = passive in
662   let f sign equality (resl, ress, newn) =
663     let ew, _, _, _ , _ = Equality.open_equality equality in
664     if ew < min_weight then
665       equality::resl, ress, newn
666     else
667       match 
668         forward_simplify eq_uri env (sign, equality) (new_pos, new_table) 
669       with
670       | None -> resl, EqualitySet.remove equality ress, newn
671       | Some e ->
672           if equality = e then
673             equality::resl, ress, newn
674           else
675             let ress = EqualitySet.remove equality ress in
676               resl, ress, e::newn
677   in
678   let pl, ps, newp = List.fold_right (f Positive) pl ([], ps, []) in
679   let passive_table =
680     List.fold_left
681       (fun tbl e -> Indexing.index tbl e) Indexing.empty pl
682   in
683   match newp with
684   | [] -> ((pl, ps), passive_table), None
685   |  _ -> ((pl, ps), passive_table), Some (newp)
686 ;;
687
688 let build_table equations =
689     List.fold_left
690       (fun (l, t, w) e ->
691          let ew, _, _, _ , _ = Equality.open_equality e in
692          e::l, Indexing.index t e, min ew w)
693       ([], Indexing.empty, 1000000) equations
694 ;;
695   
696
697 let backward_simplify eq_uri env new' ?passive active =
698   let new_pos, new_table, min_weight = build_table new' in
699 (*
700     List.fold_left
701       (fun (l, t, w) e ->
702          let ew, _, _, _ , _ = Equality.open_equality e in
703          e::l, Indexing.index t e, min ew w)
704       ([], Indexing.empty, 1000000) new'
705   in
706 *)
707   let active, newa, pruned =
708     backward_simplify_active eq_uri env new_pos new_table min_weight active 
709   in
710   match passive with
711   | None ->
712       active, (make_passive []), newa, None, pruned
713   | Some passive ->
714      active, passive, newa, None, pruned
715 (* prova
716       let passive, newp =
717         backward_simplify_passive env new_pos new_table min_weight passive in
718       active, passive, newa, newp *)
719 ;;
720
721 let close eq_uri env new' given =
722   let new_pos, new_table, min_weight =
723     List.fold_left
724       (fun (l, t, w) e ->
725          let ew, _, _, _ , _ = Equality.open_equality e in
726          e::l, Indexing.index t e, min ew w)
727       ([], Indexing.empty, 1000000) (snd new')
728   in
729   List.fold_left
730     (fun p c ->
731        let pos = infer eq_uri env c (new_pos,new_table) in
732          pos@p)
733     [] given 
734 ;;
735
736 let is_commutative_law eq =
737   let w, proof, (eq_ty, left, right, order), metas , _ = 
738     Equality.open_equality eq 
739   in
740     match left,right with
741         Cic.Appl[f1;Cic.Meta _ as a1;Cic.Meta _ as b1], 
742         Cic.Appl[f2;Cic.Meta _ as a2;Cic.Meta _ as b2] ->
743           f1 = f2 && a1 = b2 && a2 = b1
744       | _ -> false
745 ;;
746
747 let prova eq_uri env new' active = 
748   let given = List.filter is_commutative_law (fst active) in
749   let _ =
750     debug_print
751       (lazy
752          (Printf.sprintf "symmetric:\n%s\n"
753             (String.concat "\n"
754                (List.map
755                   (fun e -> Equality.string_of_equality ~env e)
756                    given)))) in
757     close eq_uri env new' given
758 ;;
759
760 (* returns an estimation of how many equalities in passive can be activated
761    within the current time limit *)
762 let get_selection_estimate () =
763   elapsed_time := (Unix.gettimeofday ()) -. !start_time;
764   (*   !processed_clauses * (int_of_float (!time_limit /. !elapsed_time)) *)
765   int_of_float (
766     ceil ((float_of_int !processed_clauses) *.
767             ((!time_limit (* *. 2. *)) /. !elapsed_time -. 1.)))
768 ;;
769
770
771 (** initializes the set of goals *)
772 let make_goals goal =
773   let active = []
774   and passive = [0, [goal]] in
775   active, passive
776 ;;
777
778 let make_goal_set goal = 
779   ([],[goal]) 
780 ;;
781
782 (** initializes the set of theorems *)
783 let make_theorems theorems =
784   theorems, []
785 ;;
786
787
788 let activate_goal (active, passive) =
789   if active = [] then
790     match passive with
791     | goal_conj::tl -> true, (goal_conj::active, tl)
792     | [] -> false, (active, passive)
793   else  
794     true, (active,passive)
795 ;;
796
797
798 let activate_theorem (active, passive) =
799   match passive with
800   | theorem::tl -> true, (theorem::active, tl)
801   | [] -> false, (active, passive)
802 ;;
803
804
805
806 let simplify_theorems env theorems ?passive (active_list, active_table) =
807   let pl, passive_table =
808     match passive with
809     | None -> [], None
810     | Some ((pn, _), (pp, _), pt) ->
811         let pn = List.map (fun e -> (Negative, e)) pn
812         and pp = List.map (fun e -> (Positive, e)) pp in
813         pn @ pp, Some pt
814   in
815   let a_theorems, p_theorems = theorems in
816   let demodulate table theorem =
817     let newmeta, newthm =
818       Indexing.demodulation_theorem !maxmeta env table theorem in
819     maxmeta := newmeta;
820     theorem != newthm, newthm
821   in
822   let foldfun table (a, p) theorem =
823     let changed, theorem = demodulate table theorem in
824     if changed then (a, theorem::p) else (theorem::a, p)
825   in
826   let mapfun table theorem = snd (demodulate table theorem) in
827   match passive_table with
828   | None ->
829       let p_theorems = List.map (mapfun active_table) p_theorems in
830       List.fold_left (foldfun active_table) ([], p_theorems) a_theorems
831   | Some passive_table ->
832       let p_theorems = List.map (mapfun active_table) p_theorems in
833       let p_theorems, a_theorems =
834         List.fold_left (foldfun active_table) ([], p_theorems) a_theorems in
835       let p_theorems = List.map (mapfun passive_table) p_theorems in
836       List.fold_left (foldfun passive_table) ([], p_theorems) a_theorems
837 ;;
838
839
840 let rec simpl eq_uri env e others others_simpl =
841   let active = others @ others_simpl in
842   let tbl =
843     List.fold_left
844       (fun t e -> Indexing.index t e)
845       Indexing.empty active
846   in
847   let res = forward_simplify eq_uri env (Positive,e) (active, tbl) in
848     match others with
849       | hd::tl -> (
850           match res with
851             | None -> simpl eq_uri env hd tl others_simpl
852             | Some e -> simpl eq_uri env hd tl (e::others_simpl)
853         )
854       | [] -> (
855           match res with
856             | None -> others_simpl
857             | Some e -> e::others_simpl
858         )
859 ;;
860
861 let simplify_equalities eq_uri env equalities =
862   debug_print
863     (lazy 
864        (Printf.sprintf "equalities:\n%s\n"
865           (String.concat "\n"
866              (List.map Equality.string_of_equality equalities))));
867   debug_print (lazy "SIMPLYFYING EQUALITIES...");
868   match equalities with
869     | [] -> []
870     | hd::tl ->
871         let res =
872           List.rev (simpl eq_uri env hd tl [])
873         in
874           debug_print
875             (lazy
876                (Printf.sprintf "equalities AFTER:\n%s\n"
877                   (String.concat "\n"
878                      (List.map Equality.string_of_equality res))));
879           res
880 ;;
881
882 let print_goals goals = 
883   (String.concat "\n"
884      (List.map
885         (fun (d, gl) ->
886            let gl' =
887              List.map
888                (fun (p, _, t) ->
889                   (* (string_of_proof p) ^ ", " ^ *) (CicPp.ppterm t)) gl
890            in
891            Printf.sprintf "%d: %s" d (String.concat "; " gl')) goals))
892 ;;
893               
894 let check_if_goal_is_subsumed ((_,ctx,_) as env) table (goalproof,menv,ty) =
895 (*
896   let names = names_of_context ctx in
897   Printf.eprintf "check_goal_subsumed: %s\n" (CicPp.pp ty names);
898 *)
899   match ty with
900   | Cic.Appl[Cic.MutInd(uri,_,_);eq_ty;left;right] 
901     when LibraryObjects.is_eq_URI uri ->
902       (let goal_equation = 
903          Equality.mk_equality
904            (0,Equality.Exact (Cic.Implicit None),(eq_ty,left,right,Eq),menv) 
905       in
906 (*      match Indexing.subsumption env table goal_equation with*)
907        match Indexing.unification env table goal_equation with 
908         | Some (subst, equality, swapped ) ->
909             prerr_endline 
910               ("GOAL SUBSUMED BY: " ^ Equality.string_of_equality equality);
911             prerr_endline ("SUBST:" ^ Subst.ppsubst subst);
912             let (_,p,(ty,l,r,_),m,id) = Equality.open_equality equality in
913             let cicmenv = Subst.apply_subst_metasenv subst (m @ menv) in
914             let p =
915               if swapped then
916                 Equality.symmetric eq_ty l id uri m
917               else
918                 p
919             in
920             Some (goalproof, p, id, subst, cicmenv)
921         | None -> None)
922   | _ -> None
923 ;;
924
925 let check_if_goal_is_identity env = function
926   | (goalproof,m,Cic.Appl[Cic.MutInd(uri,_,ens);eq_ty;left;right]) 
927     when left = right && LibraryObjects.is_eq_URI uri ->
928       let reflproof = Equality.Exact (Equality.refl_proof uri eq_ty left) in
929       Some (goalproof, reflproof, 0, Subst.empty_subst,m)
930   | (goalproof,m,Cic.Appl[Cic.MutInd(uri,_,ens);eq_ty;left;right]) 
931     when LibraryObjects.is_eq_URI uri ->
932     (let _,context,_ = env in
933     try 
934      let s,m,_ = 
935        Inference.unification m m context left right CicUniv.empty_ugraph 
936      in
937       let reflproof = Equality.Exact (Equality.refl_proof uri eq_ty left) in
938       let m = Subst.apply_subst_metasenv s m in
939       Some (goalproof, reflproof, 0, s,m)
940     with _ -> None)
941   | _ -> None
942 ;;                              
943     
944 let rec check goal = function
945   | [] -> None
946   | f::tl ->
947       match f goal with
948       | None -> check goal tl
949       | (Some p) as ok  -> ok
950 ;;
951   
952 let simplify_goal_set env goals passive active = 
953   let active_goals, passive_goals = goals in 
954   let find (_,_,g) where =
955     List.exists (fun (_,_,g1) -> Equality.meta_convertibility g g1) where
956   in
957   let simplified =
958     List.fold_left
959       (fun acc goal -> 
960         match simplify_goal env goal ~passive active with 
961         | _, g -> if find g acc then acc else g::acc)
962       (* active_goals active_goals *)
963       [] active_goals
964   in
965   if List.length active_goals <>  List.length simplified then
966     prerr_endline "SEMPLIFICANDO HO SCARTATO...";
967   (simplified,passive_goals)
968         (*
969   HExtlib.list_uniq ~eq:(fun (_,_,t1) (_,_,t2) -> t1 = t2)
970     (List.sort (fun (_,_,t1) (_,_,t2) -> compare t1 t1)
971       ((*goals @*) simplified))
972       *)
973 ;;
974
975 let check_if_goals_set_is_solved env active goals =
976   let active_goals, passive_goals = goals in 
977   List.fold_left 
978     (fun proof goal ->
979       match proof with
980       | Some p -> proof
981       | None -> 
982           check goal [
983             check_if_goal_is_identity env;
984             check_if_goal_is_subsumed env (snd active)])
985     None active_goals
986 ;;
987
988 let infer_goal_set env active goals = 
989   let active_goals, passive_goals = goals in
990   let rec aux = function
991     | [] -> goals
992     | ((_,_,t1) as hd)::tl when 
993        not (List.exists 
994              (fun (_,_,t) -> Equality.meta_convertibility t t1) 
995              active_goals)
996        -> 
997         let selected = hd in
998         let passive_goals = tl in
999         let _,_,ty = selected in 
1000         let new' = 
1001           if CicUtil.is_meta_closed ty then
1002             []
1003           else
1004             Indexing.superposition_left env (snd active) selected 
1005         in
1006         selected::active_goals, passive_goals @ new'
1007     | _::tl -> aux tl
1008   in 
1009   aux passive_goals
1010 ;;
1011
1012 let infer_goal_set_with_current env current goals = 
1013   let active_goals, passive_goals = goals in
1014   let _,table,_ = build_table [current] in
1015   active_goals,
1016   List.fold_left 
1017     (fun acc g ->
1018       let new' = Indexing.superposition_left env table g in
1019       acc @ new')
1020     passive_goals active_goals
1021 ;;
1022
1023
1024
1025 let size_of_goal_set_a (l,_) = List.length l;;
1026 let size_of_goal_set_p (_,l) = List.length l;;
1027
1028 (** given-clause algorithm with full reduction strategy: NEW implementation *)
1029 (* here goals is a set of goals in OR *)
1030 let given_clause 
1031   eq_uri ((_,context,_) as env) goals theorems passive active max_iterations max_time
1032
1033   let names = names_of_context context in
1034   let initial_time = Unix.gettimeofday () in
1035   let iterations_left iterno = 
1036     let now = Unix.gettimeofday () in
1037     let time_left = max_time -. now in
1038     let time_spent_until_now = now -. initial_time in
1039     let iteration_medium_cost = 
1040       time_spent_until_now /. (float_of_int iterno)
1041     in
1042     let iterations_left = time_left /. iteration_medium_cost in
1043     int_of_float iterations_left 
1044   in
1045   let rec step goals theorems passive active iterno =
1046     if iterno > max_iterations then
1047       (ParamodulationFailure "No more iterations to spend")
1048     else if Unix.gettimeofday () > max_time then
1049       (ParamodulationFailure "No more time to spend")
1050     else
1051       let _ = prerr_endline "simpl goal with active" in
1052       let _ = <:start<simplify goal set active>> in
1053       let goals = simplify_goal_set env goals passive active in  
1054       let _ = <:stop<simplify goal set active>> in
1055       match check_if_goals_set_is_solved env active goals with
1056       | Some p -> 
1057           prerr_endline 
1058             (Printf.sprintf "Found a proof in: %f\n" 
1059               (Unix.gettimeofday() -. initial_time));
1060 (*          assert false;*)
1061           ParamodulationSuccess p
1062       | None -> 
1063           prerr_endline 
1064             (Printf.sprintf "%d #ACTIVES: %d #PASSIVES: %d #GOALSET: %d(%d)\n"
1065             iterno (size_of_active active) (size_of_passive passive)
1066             (size_of_goal_set_a goals) (size_of_goal_set_p goals));
1067           (* PRUNING OF PASSIVE THAT WILL NEVER BE PROCESSED *)  
1068           let passive =
1069             let selection_estimate = iterations_left iterno in
1070             let kept = size_of_passive passive in
1071             if kept > selection_estimate then 
1072               begin
1073                 (*Printf.eprintf "Too many passive equalities: pruning...";
1074                 prune_passive selection_estimate active*) passive
1075               end
1076             else
1077               passive
1078           in
1079           kept_clauses := (size_of_passive passive) + (size_of_active active);
1080           (* SELECTION *)
1081           if passive_is_empty passive then
1082             ParamodulationFailure "No more passive"(*maybe this is a success! *)
1083           else
1084             begin
1085               let goals = infer_goal_set env active goals in
1086               let current, passive = select env goals passive in
1087               let _,_,goaltype = List.hd (fst goals) in                
1088               prerr_endline (Printf.sprintf  "Current goal = %s\n"
1089                 (CicPp.pp goaltype names));
1090               prerr_endline (Printf.sprintf  "Selected = %s\n"
1091                 (Equality.string_of_equality ~env current));
1092               (* SIMPLIFICATION OF CURRENT *)
1093               let res = 
1094                 forward_simplify eq_uri env (Positive, current) active 
1095               in
1096               match res with
1097               | None -> step goals theorems passive active (iterno+1)
1098               | Some current ->
1099                   (* GENERATION OF NEW EQUATIONS *)
1100                   prerr_endline "infer";
1101                   let new' = infer eq_uri env current active in
1102                   prerr_endline "infer goal";
1103                   let goals = infer_goal_set_with_current env current goals in
1104                   let active = 
1105                       let al, tbl = active in
1106                       al @ [current], Indexing.index tbl current
1107                   in
1108                   (* FORWARD AND BACKWARD SIMPLIFICATION *)
1109                   prerr_endline "fwd/back simpl";
1110                   let rec simplify new' active passive =
1111                     let new' = 
1112                       forward_simplify_new eq_uri env new' ~passive active 
1113                     in
1114                     let active, passive, newa, retained, pruned =
1115                       backward_simplify eq_uri env new' ~passive  active 
1116                     in
1117                     let passive = 
1118                       List.fold_left filter_dependent passive pruned 
1119                     in
1120                     match newa, retained with
1121                     | None, None -> active, passive, new'
1122                     | Some p, None 
1123                     | None, Some p -> simplify (new' @ p) active passive
1124                     | Some p, Some rp -> simplify (new' @ p @ rp) active passive
1125                   in
1126                   let active, passive, new' = simplify new' active passive in
1127                   prerr_endline "simpl goal with new";
1128                   let goals = 
1129                     let a,b,_ = build_table new' in
1130                     let _ = <:start<simplify_goal_set new>> in
1131                     let rc = simplify_goal_set env goals passive (a,b) in
1132                     let _ = <:stop<simplify_goal_set new>> in
1133                     rc
1134                   in
1135                   let passive = add_to_passive passive new' in
1136                   step goals theorems passive active (iterno+1)
1137             end
1138   in
1139     step goals theorems passive active 1
1140 ;;
1141
1142 let rec saturate_equations eq_uri env goal accept_fun passive active =
1143   elapsed_time := Unix.gettimeofday () -. !start_time;
1144   if !elapsed_time > !time_limit then
1145     (active, passive)
1146   else
1147     let current, passive = select env ([goal],[]) passive in
1148     let res = forward_simplify eq_uri env (Positive, current) ~passive active in
1149     match res with
1150     | None ->
1151         saturate_equations eq_uri env goal accept_fun passive active
1152     | Some current ->
1153         debug_print (lazy (Printf.sprintf "selected: %s"
1154                              (Equality.string_of_equality ~env current)));
1155         let new' = infer eq_uri env current active in
1156         let active =
1157           if Equality.is_identity env current then active
1158           else
1159             let al, tbl = active in
1160             al @ [current], Indexing.index tbl current
1161         in
1162         let rec simplify new' active passive =
1163           let new' = forward_simplify_new eq_uri env new' ~passive active in
1164           let active, passive, newa, retained, pruned =
1165             backward_simplify eq_uri env new' ~passive active in
1166           let passive = 
1167             List.fold_left filter_dependent passive pruned in
1168           match newa, retained with
1169           | None, None -> active, passive, new'
1170           | Some p, None
1171           | None, Some p -> simplify (new' @ p) active passive
1172           | Some p, Some rp -> simplify (new' @ p @ rp) active passive
1173         in
1174         let active, passive, new' = simplify new' active passive in
1175         let _ =
1176           debug_print
1177             (lazy
1178                (Printf.sprintf "active:\n%s\n"
1179                   (String.concat "\n"
1180                      (List.map
1181                          (fun e -> Equality.string_of_equality ~env e)
1182                          (fst active)))))
1183         in
1184         let _ =
1185           debug_print
1186             (lazy
1187                (Printf.sprintf "new':\n%s\n"
1188                   (String.concat "\n"
1189                      (List.map
1190                          (fun e -> "Negative " ^
1191                             (Equality.string_of_equality ~env e)) new'))))
1192         in
1193         let new' = List.filter accept_fun new' in
1194         let passive = add_to_passive passive new' in
1195         saturate_equations eq_uri env goal accept_fun passive active
1196 ;;
1197   
1198 let main dbd full term metasenv ugraph = ()
1199 (*
1200 let main dbd full term metasenv ugraph =
1201   let module C = Cic in
1202   let module T = CicTypeChecker in
1203   let module PET = ProofEngineTypes in
1204   let module PP = CicPp in
1205   let proof = None, (1, [], term)::metasenv, C.Meta (1, []), term in
1206   let status = PET.apply_tactic (PrimitiveTactics.intros_tac ()) (proof, 1) in
1207   let proof, goals = status in
1208   let goal' = List.nth goals 0 in
1209   let _, metasenv, meta_proof, _ = proof in
1210   let _, context, goal = CicUtil.lookup_meta goal' metasenv in
1211   let eq_indexes, equalities, maxm = find_equalities context proof in
1212   let lib_eq_uris, library_equalities, maxm =
1213
1214     find_library_equalities dbd context (proof, goal') (maxm+2)
1215   in
1216   let library_equalities = List.map snd library_equalities in
1217   maxmeta := maxm+2; (* TODO ugly!! *)
1218   let irl = CicMkImplicit.identity_relocation_list_for_metavariable context in
1219   let new_meta_goal, metasenv, type_of_goal =
1220     let _, context, ty = CicUtil.lookup_meta goal' metasenv in
1221     debug_print
1222       (lazy
1223          (Printf.sprintf "\n\nTIPO DEL GOAL: %s\n\n" (CicPp.ppterm ty)));
1224     Cic.Meta (maxm+1, irl),
1225     (maxm+1, context, ty)::metasenv,
1226     ty
1227   in
1228   let env = (metasenv, context, ugraph) in
1229   let t1 = Unix.gettimeofday () in
1230   let theorems =
1231     if full then
1232       let theorems = find_library_theorems dbd env (proof, goal') lib_eq_uris in
1233       let context_hyp = find_context_hypotheses env eq_indexes in
1234       context_hyp @ theorems, []
1235     else
1236       let refl_equal =
1237         let us = UriManager.string_of_uri (LibraryObjects.eq_URI ()) in
1238         UriManager.uri_of_string (us ^ "#xpointer(1/1/1)")
1239       in
1240       let t = CicUtil.term_of_uri refl_equal in
1241       let ty, _ = CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in
1242       [(t, ty, [])], []
1243   in
1244   let t2 = Unix.gettimeofday () in
1245   debug_print
1246     (lazy
1247        (Printf.sprintf "Time to retrieve theorems: %.9f\n" (t2 -. t1)));
1248   let _ =
1249     debug_print
1250       (lazy
1251          (Printf.sprintf
1252             "Theorems:\n-------------------------------------\n%s\n"
1253             (String.concat "\n"
1254                (List.map
1255                   (fun (t, ty, _) ->
1256                      Printf.sprintf
1257                        "Term: %s, type: %s" (CicPp.ppterm t) (CicPp.ppterm ty))
1258                   (fst theorems)))))
1259   in
1260   (*try*)
1261     let goal = 
1262       ([],Equality.BasicProof (Equality.empty_subst ,new_meta_goal)), [], goal 
1263     in
1264     let equalities = simplify_equalities env 
1265       (equalities@library_equalities) in 
1266     let active = make_active () in
1267     let passive = make_passive equalities in
1268     Printf.printf "\ncurrent goal: %s\n"
1269       (let _, _, g = goal in CicPp.ppterm g);
1270     Printf.printf "\ncontext:\n%s\n" (PP.ppcontext context);
1271     Printf.printf "\nmetasenv:\n%s\n" (print_metasenv metasenv);
1272     Printf.printf "\nequalities:\n%s\n"
1273       (String.concat "\n"
1274          (List.map
1275             (Equality.string_of_equality ~env) equalities));
1276 (*             (equalities @ library_equalities))); *)
1277       print_endline "--------------------------------------------------";
1278       let start = Unix.gettimeofday () in
1279       print_endline "GO!";
1280       start_time := Unix.gettimeofday ();
1281       let res =
1282         let goals = make_goals goal in
1283         (if !use_fullred then given_clause_fullred else given_clause_fullred)
1284           dbd env goals theorems passive active
1285       in
1286       let finish = Unix.gettimeofday () in
1287       let _ =
1288         match res with
1289         | ParamodulationFailure ->
1290             Printf.printf "NO proof found! :-(\n\n"
1291         | ParamodulationSuccess (Some ((cicproof,cicmenv),(proof, env))) ->
1292             Printf.printf "OK, found a proof!\n";
1293             let oldproof = Equation.build_proof_term proof in
1294             let newproof,_,newenv,_ = 
1295                 CicRefine.type_of_aux' 
1296                   cicmenv context cicproof CicUniv.empty_ugraph
1297             in
1298             (* REMEMBER: we have to instantiate meta_proof, we should use
1299                apply  the "apply" tactic to proof and status 
1300             *)
1301             let names = names_of_context context in
1302             prerr_endline "OLD PROOF";
1303             print_endline (PP.pp proof names);
1304             prerr_endline "NEW PROOF";
1305             print_endline (PP.pp newproof names);
1306             let newmetasenv =
1307               List.fold_left
1308                 (fun m eq -> 
1309                   let (_, _, _, menv,_) = Equality.open_equality eq in 
1310                   m @ menv) 
1311               metasenv equalities
1312             in
1313             let _ =
1314               (*try*)
1315                 let ty, ug =
1316                   CicTypeChecker.type_of_aux' newmetasenv context proof ugraph
1317                 in
1318                 print_endline (string_of_float (finish -. start));
1319                 Printf.printf
1320                   "\nGOAL was: %s\nPROOF has type: %s\nconvertible?: %s\n\n"
1321                   (CicPp.pp type_of_goal names) (CicPp.pp ty names)
1322                   (string_of_bool
1323                      (fst (CicReduction.are_convertible
1324                              context type_of_goal ty ug)));
1325               (*with e ->
1326                 Printf.printf "\nEXCEPTION!!! %s\n" (Printexc.to_string e);
1327                 Printf.printf "MAXMETA USED: %d\n" !maxmeta;
1328                 print_endline (string_of_float (finish -. start));*)
1329             in
1330             ()
1331               
1332         | ParamodulationSuccess None ->
1333             Printf.printf "Success, but no proof?!?\n\n"
1334       in
1335         if Utils.time then
1336           begin
1337             prerr_endline 
1338               ((Printf.sprintf ("infer_time: %.9f\nforward_simpl_time: %.9f\n" ^^
1339                        "forward_simpl_new_time: %.9f\n" ^^
1340                        "backward_simpl_time: %.9f\n")
1341               !infer_time !forward_simpl_time !forward_simpl_new_time
1342               !backward_simpl_time) ^
1343               (Printf.sprintf "passive_maintainance_time: %.9f\n"
1344                  !passive_maintainance_time) ^
1345               (Printf.sprintf "    successful unification/matching time: %.9f\n"
1346                  !Indexing.match_unif_time_ok) ^
1347               (Printf.sprintf "    failed unification/matching time: %.9f\n"
1348                  !Indexing.match_unif_time_no) ^
1349               (Printf.sprintf "    indexing retrieval time: %.9f\n"
1350                  !Indexing.indexing_retrieval_time) ^
1351               (Printf.sprintf "    demodulate_term.build_newtarget_time: %.9f\n"
1352                  !Indexing.build_newtarget_time) ^
1353               (Printf.sprintf "derived %d clauses, kept %d clauses.\n"
1354                  !derived_clauses !kept_clauses)) 
1355             end
1356 (*
1357   with exc ->
1358     print_endline ("EXCEPTION: " ^ (Printexc.to_string exc));
1359     raise exc
1360 *)
1361 ;;
1362 *)
1363
1364 let default_depth = !maxdepth
1365 and default_width = !maxwidth;;
1366
1367 let reset_refs () =
1368   maxmeta := 0;
1369   symbols_counter := 0;
1370   weight_age_counter := !weight_age_ratio;
1371   processed_clauses := 0;
1372   start_time := 0.;
1373   elapsed_time := 0.;
1374   maximal_retained_equality := None;
1375   infer_time := 0.;
1376   forward_simpl_time := 0.;
1377   forward_simpl_new_time := 0.;
1378   backward_simpl_time := 0.;
1379   passive_maintainance_time := 0.;
1380   derived_clauses := 0;
1381   kept_clauses := 0;
1382   Equality.reset ();
1383 ;;
1384
1385 let eq_of_goal = function
1386   | Cic.Appl [Cic.MutInd(uri,0,_);_;_;_] when LibraryObjects.is_eq_URI uri ->
1387       uri
1388   | _ -> raise (ProofEngineTypes.Fail (lazy ("The goal is not an equality ")))
1389 ;;
1390
1391 let saturate 
1392     dbd ?(full=false) ?(depth=default_depth) ?(width=default_width) status = 
1393   let module C = Cic in
1394   reset_refs ();
1395   Indexing.init_index ();
1396   maxdepth := depth;
1397   maxwidth := width;
1398 (*  CicUnification.unif_ty := false;*)
1399   let proof, goalno = status in
1400   let uri, metasenv, meta_proof, term_to_prove = proof in
1401   let _, context, type_of_goal = CicUtil.lookup_meta goalno metasenv in
1402   let eq_uri = eq_of_goal type_of_goal in 
1403   let names = names_of_context context in
1404   let eq_indexes, equalities, maxm = find_equalities context proof in
1405   let ugraph = CicUniv.empty_ugraph in
1406   let env = (metasenv, context, ugraph) in 
1407   let goal = [], List.filter (fun (i,_,_)->i<>goalno) metasenv, type_of_goal in
1408   let res, time =
1409     let t1 = Unix.gettimeofday () in
1410     let lib_eq_uris, library_equalities, maxm =
1411       find_library_equalities dbd context (proof, goalno) (maxm+2)
1412     in
1413     let library_equalities = List.map snd library_equalities in
1414     let t2 = Unix.gettimeofday () in
1415     maxmeta := maxm+2;
1416     let equalities = 
1417       simplify_equalities eq_uri env (equalities@library_equalities) 
1418     in 
1419     debug_print
1420       (lazy
1421          (Printf.sprintf "Time to retrieve equalities: %.9f\n" (t2 -. t1)));
1422     let t1 = Unix.gettimeofday () in
1423     let theorems =
1424       if full then
1425         let thms = find_library_theorems dbd env (proof, goalno) lib_eq_uris in
1426         let context_hyp = find_context_hypotheses env eq_indexes in
1427         context_hyp @ thms, []
1428       else
1429         let refl_equal = LibraryObjects.eq_refl_URI ~eq:eq_uri in
1430         let t = CicUtil.term_of_uri refl_equal in
1431         let ty, _ = CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in
1432         [(t, ty, [])], []
1433     in
1434     let t2 = Unix.gettimeofday () in
1435     let _ =
1436       debug_print
1437         (lazy
1438            (Printf.sprintf
1439               "Theorems:\n-------------------------------------\n%s\n"
1440               (String.concat "\n"
1441                  (List.map
1442                     (fun (t, ty, _) ->
1443                        Printf.sprintf
1444                          "Term: %s, type: %s"
1445                          (CicPp.ppterm t) (CicPp.ppterm ty))
1446                     (fst theorems)))));
1447       debug_print
1448         (lazy
1449            (Printf.sprintf "Time to retrieve theorems: %.9f\n" (t2 -. t1)));
1450     in
1451     let active = make_active () in
1452     let passive = make_passive equalities in
1453     let start = Unix.gettimeofday () in
1454     let res =
1455 (*
1456       let goals = make_goals goal in
1457       given_clause_fullred dbd env goals theorems passive active
1458 *)
1459       let goals = make_goal_set goal in
1460       let max_iterations = 10000 in
1461       let max_time = Unix.gettimeofday () +.  600. (* minutes *) in
1462       given_clause 
1463         eq_uri env goals theorems passive active max_iterations max_time 
1464     in
1465     let finish = Unix.gettimeofday () in
1466     (res, finish -. start)
1467   in
1468   match res with
1469   | ParamodulationFailure s ->
1470       raise (ProofEngineTypes.Fail (lazy ("NO proof found: " ^ s)))
1471   | ParamodulationSuccess 
1472     (goalproof,newproof,subsumption_id,subsumption_subst, proof_menv) ->
1473       prerr_endline "OK, found a proof!";
1474       prerr_endline 
1475         (Equality.pp_proof names goalproof newproof subsumption_subst
1476           subsumption_id type_of_goal);
1477       prerr_endline (CicMetaSubst.ppmetasenv [] proof_menv);
1478       prerr_endline "ENDOFPROOFS";
1479       (* generation of the CIC proof *)
1480       let side_effects = 
1481         List.filter (fun i -> i <> goalno)
1482           (ProofEngineHelpers.compare_metasenvs 
1483             ~newmetasenv:metasenv ~oldmetasenv:proof_menv)
1484       in
1485       let goal_proof, side_effects_t = 
1486         let initial = Equality.add_subst subsumption_subst newproof in
1487         Equality.build_goal_proof 
1488           eq_uri goalproof initial type_of_goal side_effects
1489       in
1490       let goal_proof = Subst.apply_subst subsumption_subst goal_proof in
1491       let metas_still_open_in_proof = Utils.metas_of_term goal_proof in
1492 (*prerr_endline (CicPp.pp goal_proof names);*)
1493       (* ?? *)
1494       let goal_proof = (* Subst.apply_subst subsumption_subst *) goal_proof in
1495       let side_effects_t = 
1496         List.map (Subst.apply_subst subsumption_subst) side_effects_t
1497       in
1498       (* replacing fake mets with real ones *)
1499       prerr_endline "replacing metas...";
1500       let irl=CicMkImplicit.identity_relocation_list_for_metavariable context in
1501       let goal_proof_menv, what, with_what,free_meta = 
1502         List.fold_left 
1503           (fun (acc1,acc2,acc3,uniq) (i,_,ty) -> 
1504              match uniq with
1505                | Some m -> 
1506                    acc1, (Cic.Meta(i,[]))::acc2, m::acc3, uniq
1507                | None ->
1508                    [i,context,ty], (Cic.Meta(i,[]))::acc2, 
1509                    (Cic.Meta(i,irl)) ::acc3,Some (Cic.Meta(i,irl))) 
1510           ([],[],[],None) 
1511           (List.filter 
1512            (fun (i,_,_) -> List.mem i metas_still_open_in_proof) 
1513            proof_menv)
1514       in
1515       let replace where = 
1516         (* we need this fake equality since the metas of the hypothesis may be
1517          * with a real local context *)
1518         ProofEngineReduction.replace_lifting 
1519           ~equality:(fun x y -> 
1520             match x,y with Cic.Meta(i,_),Cic.Meta(j,_) -> i=j | _-> false)
1521           ~what ~with_what ~where
1522       in
1523       let goal_proof = replace goal_proof in
1524         (* ok per le meta libere... ma per quelle che c'erano e sono rimaste? 
1525          * what mi pare buono, sostituisce solo le meta farlocche *)
1526       let side_effects_t = List.map replace side_effects_t in
1527       let free_metas = 
1528         List.filter (fun i -> i <> goalno)
1529           (ProofEngineHelpers.compare_metasenvs 
1530             ~oldmetasenv:metasenv ~newmetasenv:goal_proof_menv)
1531       in
1532 prerr_endline ("freemetas: " ^ String.concat "," (List.map string_of_int free_metas) );
1533       (* check/refine/... build the new proof *)
1534       let replaced_goal = 
1535         ProofEngineReduction.replace
1536           ~what:side_effects ~with_what:side_effects_t
1537           ~equality:(fun i t -> match t with Cic.Meta(j,_)->j=i|_->false)
1538           ~where:type_of_goal
1539       in
1540       let subst_side_effects,real_menv,_ = 
1541         let fail t s = raise (ProofEngineTypes.Fail (lazy (t^Lazy.force s))) in
1542         let free_metas_menv = 
1543           List.map (fun i -> CicUtil.lookup_meta i goal_proof_menv) free_metas
1544         in
1545         try
1546           CicUnification.fo_unif_subst [] context (metasenv @ free_metas_menv)
1547            replaced_goal type_of_goal CicUniv.empty_ugraph
1548         with
1549         | CicUnification.UnificationFailure s
1550         | CicUnification.Uncertain s 
1551         | CicUnification.AssertFailure s -> 
1552             fail "Maybe the local context of metas in the goal was not an IRL" s
1553       in
1554       let final_subst = 
1555         (goalno,(context,goal_proof,type_of_goal))::subst_side_effects
1556       in
1557 prerr_endline ("MENVreal_menv: " ^ CicMetaSubst.ppmetasenv [] real_menv);
1558       let _ = 
1559         try
1560           CicTypeChecker.type_of_aux' real_menv context goal_proof
1561             CicUniv.empty_ugraph
1562         with 
1563         | CicUtil.Meta_not_found _ 
1564         | CicTypeChecker.TypeCheckerFailure _ 
1565         | CicTypeChecker.AssertFailure _ 
1566         | Invalid_argument "list_fold_left2" as exn ->
1567             prerr_endline "THE PROOF DOES NOT TYPECHECK!";
1568             prerr_endline (CicPp.pp goal_proof names); 
1569             prerr_endline "THE PROOF DOES NOT TYPECHECK!";
1570             raise exn
1571       in
1572       let proof, real_metasenv = 
1573         ProofEngineHelpers.subst_meta_and_metasenv_in_proof
1574           proof goalno (CicMetaSubst.apply_subst final_subst) real_menv
1575       in
1576       let open_goals = 
1577         match free_meta with Some(Cic.Meta(m,_)) when m<>goalno ->[m] | _ ->[] 
1578       in
1579       Printf.eprintf 
1580         "GOALS APERTI: %s\nMETASENV PRIMA:\n%s\nMETASENV DOPO:\n%s\n" 
1581           (String.concat ", " (List.map string_of_int open_goals))
1582           (CicMetaSubst.ppmetasenv [] metasenv)
1583           (CicMetaSubst.ppmetasenv [] real_metasenv);
1584       prerr_endline (Printf.sprintf "\nTIME NEEDED: %8.2f" time);
1585       proof, open_goals
1586 ;;
1587
1588 let retrieve_and_print dbd term metasenv ugraph = 
1589   let module C = Cic in
1590   let module T = CicTypeChecker in
1591   let module PET = ProofEngineTypes in
1592   let module PP = CicPp in
1593   let proof = None, (1, [], term)::metasenv, C.Meta (1, []), term in
1594   let status = PET.apply_tactic (PrimitiveTactics.intros_tac ()) (proof, 1) in
1595   let proof, goals = status in
1596   let goal' = List.nth goals 0 in
1597   let uri, metasenv, meta_proof, term_to_prove = proof in
1598   let _, context, type_of_goal = CicUtil.lookup_meta goal' metasenv in
1599   let eq_uri = eq_of_goal type_of_goal in 
1600   let eq_indexes, equalities, maxm = find_equalities context proof in
1601   let ugraph = CicUniv.empty_ugraph in
1602   let env = (metasenv, context, ugraph) in
1603   let t1 = Unix.gettimeofday () in
1604   let lib_eq_uris, library_equalities, maxm =
1605     find_library_equalities dbd context (proof, goal') (maxm+2) in
1606   let t2 = Unix.gettimeofday () in
1607   maxmeta := maxm+2;
1608   let equalities = (* equalities @ *) library_equalities in
1609   debug_print
1610      (lazy
1611         (Printf.sprintf "\n\nequalities:\n%s\n"
1612            (String.concat "\n"
1613               (List.map 
1614           (fun (u, e) ->
1615 (*                  Printf.sprintf "%s: %s" *)
1616                    (UriManager.string_of_uri u)
1617 (*                    (string_of_equality e) *)
1618                      )
1619           equalities))));
1620   debug_print (lazy "RETR: SIMPLYFYING EQUALITIES...");
1621   let rec simpl e others others_simpl =
1622     let (u, e) = e in
1623     let active = List.map (fun (u, e) -> (Positive, e))
1624       (others @ others_simpl) in
1625     let tbl =
1626       List.fold_left
1627         (fun t (_, e) -> Indexing.index t e)
1628         Indexing.empty active
1629     in
1630     let res = forward_simplify eq_uri env (Positive, e) (active, tbl) in
1631     match others with
1632         | hd::tl -> (
1633             match res with
1634               | None -> simpl hd tl others_simpl
1635               | Some e -> simpl hd tl ((u, e)::others_simpl)
1636           )
1637         | [] -> (
1638             match res with
1639               | None -> others_simpl
1640               | Some e -> (u, e)::others_simpl
1641           ) 
1642   in
1643   let _equalities =
1644     match equalities with
1645       | [] -> []
1646       | hd::tl ->
1647           let others = tl in (* List.map (fun e -> (Positive, e)) tl in *)
1648           let res =
1649             List.rev (simpl (*(Positive,*) hd others [])
1650           in
1651             debug_print
1652               (lazy
1653                  (Printf.sprintf "\nequalities AFTER:\n%s\n"
1654                     (String.concat "\n"
1655                        (List.map
1656                           (fun (u, e) ->
1657                              Printf.sprintf "%s: %s"
1658                                (UriManager.string_of_uri u)
1659                                (Equality.string_of_equality e)
1660                           )
1661                           res))));
1662             res in
1663     debug_print
1664       (lazy
1665          (Printf.sprintf "Time to retrieve equalities: %.9f\n" (t2 -. t1)))
1666 ;;
1667
1668
1669 let main_demod_equalities dbd term metasenv ugraph =
1670   let module C = Cic in
1671   let module T = CicTypeChecker in
1672   let module PET = ProofEngineTypes in
1673   let module PP = CicPp in
1674   let proof = None, (1, [], term)::metasenv, C.Meta (1, []), term in
1675   let status = PET.apply_tactic (PrimitiveTactics.intros_tac ()) (proof, 1) in
1676   let proof, goals = status in
1677   let goal' = List.nth goals 0 in
1678   let _, metasenv, meta_proof, _ = proof in
1679   let _, context, goal = CicUtil.lookup_meta goal' metasenv in
1680   let eq_uri = eq_of_goal goal in 
1681   let eq_indexes, equalities, maxm = find_equalities context proof in
1682   let lib_eq_uris, library_equalities, maxm =
1683     find_library_equalities dbd context (proof, goal') (maxm+2)
1684   in
1685   let library_equalities = List.map snd library_equalities in
1686   maxmeta := maxm+2; (* TODO ugly!! *)
1687   let irl = CicMkImplicit.identity_relocation_list_for_metavariable context in
1688   let new_meta_goal, metasenv, type_of_goal =
1689     let _, context, ty = CicUtil.lookup_meta goal' metasenv in
1690     debug_print
1691       (lazy
1692          (Printf.sprintf "\n\nTRYING TO INFER EQUALITIES MATCHING: %s\n\n"
1693             (CicPp.ppterm ty)));
1694     Cic.Meta (maxm+1, irl),
1695     (maxm+1, context, ty)::metasenv,
1696     ty
1697   in
1698   let env = (metasenv, context, ugraph) in
1699   (*try*)
1700     let goal = [], [], goal 
1701     in
1702     let equalities = 
1703       simplify_equalities eq_uri env (equalities@library_equalities) 
1704     in
1705     let active = make_active () in
1706     let passive = make_passive equalities in
1707     Printf.printf "\ncontext:\n%s\n" (PP.ppcontext context);
1708     Printf.printf "\nmetasenv:\n%s\n" (print_metasenv metasenv);
1709     Printf.printf "\nequalities:\n%s\n"
1710       (String.concat "\n"
1711          (List.map
1712             (Equality.string_of_equality ~env) equalities));
1713     print_endline "--------------------------------------------------";
1714     print_endline "GO!";
1715     start_time := Unix.gettimeofday ();
1716     if !time_limit < 1. then time_limit := 60.;    
1717     let ra, rp =
1718       saturate_equations eq_uri env goal (fun e -> true) passive active
1719     in
1720
1721     let initial =
1722       List.fold_left (fun s e -> EqualitySet.add e s)
1723         EqualitySet.empty equalities
1724     in
1725     let addfun s e = 
1726       if not (EqualitySet.mem e initial) then EqualitySet.add e s else s
1727     in
1728
1729     let passive =
1730       match rp with
1731       | (p, _), _ ->
1732           EqualitySet.elements (List.fold_left addfun EqualitySet.empty p)
1733     in
1734     let active =
1735       let l = fst ra in
1736       EqualitySet.elements (List.fold_left addfun EqualitySet.empty l)
1737     in
1738     Printf.printf "\n\nRESULTS:\nActive:\n%s\n\nPassive:\n%s\n"
1739        (String.concat "\n" (List.map (Equality.string_of_equality ~env) active)) 
1740      (*  (String.concat "\n"
1741          (List.map (fun e -> CicPp.ppterm (term_of_equality e)) active)) *)
1742 (*       (String.concat "\n" (List.map (string_of_equality ~env) passive)); *)
1743       (String.concat "\n"
1744          (List.map 
1745            (fun e -> CicPp.ppterm (Equality.term_of_equality eq_uri e)) 
1746           passive));
1747     print_newline ();
1748 (*
1749   with e ->
1750     debug_print (lazy ("EXCEPTION: " ^ (Printexc.to_string e)))
1751 *)
1752 ;;
1753
1754 let demodulate_tac ~dbd ~pattern ((proof,goal)(*s initialstatus*)) = 
1755   let module I = Inference in
1756   let curi,metasenv,pbo,pty = proof in
1757   let metano,context,ty = CicUtil.lookup_meta goal metasenv in
1758   let eq_uri = eq_of_goal ty in 
1759   let eq_indexes, equalities, maxm = 
1760     Inference.find_equalities context proof 
1761   in
1762   let lib_eq_uris, library_equalities, maxm =
1763     I.find_library_equalities dbd context (proof, goal) (maxm+2) in
1764   if library_equalities = [] then prerr_endline "VUOTA!!!";
1765   let irl = CicMkImplicit.identity_relocation_list_for_metavariable context in
1766   let library_equalities = List.map snd library_equalities in
1767   let initgoal = [], [], ty in
1768   let env = (metasenv, context, CicUniv.empty_ugraph) in
1769   let equalities = 
1770     simplify_equalities eq_uri env (equalities@library_equalities) 
1771   in   
1772   let table = 
1773     List.fold_left 
1774       (fun tbl eq -> Indexing.index tbl eq) 
1775       Indexing.empty equalities 
1776   in
1777   let changed,(newproof,newmetasenv, newty) = 
1778     Indexing.demodulation_goal 
1779       (metasenv,context,CicUniv.empty_ugraph) table initgoal 
1780   in
1781   if changed then
1782     begin
1783       let opengoal = Equality.Exact (Cic.Meta(maxm,irl)) in
1784       let proofterm,_ = 
1785         Equality.build_goal_proof eq_uri newproof opengoal ty [] 
1786       in
1787         let extended_metasenv = (maxm,context,newty)::metasenv in
1788         let extended_status = 
1789           (curi,extended_metasenv,pbo,pty),goal in
1790         let (status,newgoals) = 
1791           ProofEngineTypes.apply_tactic 
1792             (PrimitiveTactics.apply_tac ~term:proofterm)
1793             extended_status in
1794         (status,maxm::newgoals)
1795     end
1796   else (* if newty = ty then *)
1797     raise (ProofEngineTypes.Fail (lazy "no progress"))
1798   (*else ProofEngineTypes.apply_tactic 
1799     (ReductionTactics.simpl_tac ~pattern) 
1800     initialstatus*)
1801 ;;
1802
1803 let demodulate_tac ~dbd ~pattern = 
1804   ProofEngineTypes.mk_tactic (demodulate_tac ~dbd ~pattern)
1805 ;;
1806
1807 let get_stats () = 
1808   <:show<Saturation.>> ^ Indexing.get_stats () ^ Inference.get_stats ();;
1809