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