]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/paramodulation/saturation.ml
fixed a bug (status not reset properly between calls), tried some other
[helm.git] / helm / ocaml / paramodulation / saturation.ml
1 open Inference;;
2 open Utils;;
3
4
5 (* set to false to disable paramodulation inside auto_tac *)
6 let connect_to_auto = true;;
7
8
9 (* profiling statistics... *)
10 let infer_time = ref 0.;;
11 let forward_simpl_time = ref 0.;;
12 let forward_simpl_new_time = ref 0.;;
13 let backward_simpl_time = ref 0.;;
14 let passive_maintainance_time = ref 0.;;
15
16 (* limited-resource-strategy related globals *)
17 let processed_clauses = ref 0;; (* number of equalities selected so far... *)
18 let time_limit = ref 0.;; (* in seconds, settable by the user... *)
19 let start_time = ref 0.;; (* time at which the execution started *)
20 let elapsed_time = ref 0.;;
21 (* let maximal_weight = ref None;; *)
22 let maximal_retained_equality = ref None;;
23
24 (* equality-selection related globals *)
25 let use_fullred = ref true;;
26 let weight_age_ratio = ref (* 5 *) 4;; (* settable by the user *)
27 let weight_age_counter = ref !weight_age_ratio;;
28 let symbols_ratio = ref (* 0 *) 3;;
29 let symbols_counter = ref 0;;
30
31 (* non-recursive Knuth-Bendix term ordering by default *)
32 Utils.compare_terms := Utils.nonrec_kbo;; 
33
34 (* statistics... *)
35 let derived_clauses = ref 0;;
36 let kept_clauses = ref 0;;
37
38 (* index of the greatest Cic.Meta created - TODO: find a better way! *)
39 let maxmeta = ref 0;;
40
41 (* varbiables controlling the search-space *)
42 let maxdepth = ref 3;;
43 let maxwidth = ref 3;;
44
45
46 type result =
47   | ParamodulationFailure
48   | ParamodulationSuccess of Inference.proof option * environment
49 ;;
50
51 type goal = proof * Cic.metasenv * Cic.term;;
52
53 type theorem = Cic.term * Cic.term * Cic.metasenv;;
54
55
56 (*
57 let symbols_of_equality (_, (_, left, right), _, _) =
58   TermSet.union (symbols_of_term left) (symbols_of_term right)
59 ;;
60 *)
61
62 let symbols_of_equality ((_, _, (_, left, right, _), _, _) as equality) =
63   let m1 = symbols_of_term left in
64   let m = 
65     TermMap.fold
66       (fun k v res ->
67          try
68            let c = TermMap.find k res in
69            TermMap.add k (c+v) res
70          with Not_found ->
71            TermMap.add k v res)
72       (symbols_of_term right) m1
73   in
74 (*   Printf.printf "symbols_of_equality %s:\n" *)
75 (*     (string_of_equality equality); *)
76 (*   TermMap.iter (fun k v -> Printf.printf "%s: %d\n" (CicPp.ppterm k) v) m; *)
77 (*   print_newline (); *)
78   m
79 ;;
80
81
82 module OrderedEquality = struct
83   type t = Inference.equality
84
85   let compare eq1 eq2 =
86     match meta_convertibility_eq eq1 eq2 with
87     | true -> 0
88     | false ->
89         let w1, _, (ty, left, right, _), _, a = eq1
90         and w2, _, (ty', left', right', _), _, a' = eq2 in
91 (*         let weight_of t = fst (weight_of_term ~consider_metas:false t) in *)
92 (*         let w1 = (weight_of ty) + (weight_of left) + (weight_of right) *)
93 (*         and w2 = (weight_of ty') + (weight_of left') + (weight_of right') in *)
94         match Pervasives.compare w1 w2 with
95         | 0 ->
96             let res = (List.length a) - (List.length a') in
97             if res <> 0 then res else (
98               try
99                 let res = Pervasives.compare (List.hd a) (List.hd a') in
100                 if res <> 0 then res else Pervasives.compare eq1 eq2
101               with Failure "hd" -> Pervasives.compare eq1 eq2
102 (*               match a, a' with *)
103 (*               | (Cic.Meta (i, _)::_), (Cic.Meta (j, _)::_) -> *)
104 (*                   let res = Pervasives.compare i j in *)
105 (*                   if res <> 0 then res else Pervasives.compare eq1 eq2 *)
106 (*               | _, _ -> Pervasives.compare eq1 eq2 *)
107             )
108         | res -> res
109 end
110
111 module EqualitySet = Set.Make(OrderedEquality);;
112
113
114 let select env goals passive (active, _) =
115   processed_clauses := !processed_clauses + 1;
116
117   let goal =
118     match (List.rev goals) with (_, goal::_)::_ -> goal | _ -> assert false
119   in
120   
121   let (neg_list, neg_set), (pos_list, pos_set), passive_table = passive in
122   let remove eq l =
123     List.filter (fun e -> e <> eq) l
124   in
125   if !weight_age_ratio > 0 then
126     weight_age_counter := !weight_age_counter - 1;
127   match !weight_age_counter with
128   | 0 -> (
129       weight_age_counter := !weight_age_ratio;
130       match neg_list, pos_list with
131       | hd::tl, pos ->
132           (* Negatives aren't indexed, no need to remove them... *)
133           (Negative, hd),
134           ((tl, EqualitySet.remove hd neg_set), (pos, pos_set), passive_table)
135       | [], hd::tl ->
136           let passive_table =
137             Indexing.remove_index passive_table hd
138 (*             if !use_fullred then Indexing.remove_index passive_table hd *)
139 (*             else passive_table *)
140           in
141           (Positive, hd),
142           (([], neg_set), (tl, EqualitySet.remove hd pos_set), passive_table)
143       | _, _ -> assert false
144     )
145   | _ when (!symbols_counter > 0) && (EqualitySet.is_empty neg_set) -> (
146       symbols_counter := !symbols_counter - 1;
147       let cardinality map =
148         TermMap.fold (fun k v res -> res + v) map 0
149       in
150 (*       match active with *)
151 (*       | (Negative, e)::_ -> *)
152 (*           let symbols = symbols_of_equality e in *)
153       let symbols =
154         let _, _, term = goal in
155         symbols_of_term term
156       in
157           let card = cardinality symbols in
158           let foldfun k v (r1, r2) = 
159             if TermMap.mem k symbols then
160               let c = TermMap.find k symbols in
161               let c1 = abs (c - v) in
162               let c2 = v - c1 in
163               r1 + c2, r2 + c1
164             else
165               r1, r2 + v
166           in
167           let f equality (i, e) =
168             let common, others =
169               TermMap.fold foldfun (symbols_of_equality equality) (0, 0)
170             in
171             let c = others + (abs (common - card)) in
172             if c < i then (c, equality)
173 (*             else if c = i then *)
174 (*               match OrderedEquality.compare equality e with *)
175 (*               | -1 -> (c, equality) *)
176 (*               | res -> (i, e) *)
177             else (i, e)
178           in
179           let e1 = EqualitySet.min_elt pos_set in
180           let initial =
181             let common, others = 
182               TermMap.fold foldfun (symbols_of_equality e1) (0, 0)
183             in
184             (others + (abs (common - card))), e1
185           in
186           let _, current = EqualitySet.fold f pos_set initial in
187 (*           Printf.printf "\nsymbols-based selection: %s\n\n" *)
188 (*             (string_of_equality ~env current); *)
189           let passive_table =
190             Indexing.remove_index passive_table current
191 (*             if !use_fullred then Indexing.remove_index passive_table current *)
192 (*             else passive_table *)
193           in
194           (Positive, current),
195           (([], neg_set),
196            (remove current pos_list, EqualitySet.remove current pos_set),
197            passive_table)
198 (*       | _ -> *)
199 (*           let current = EqualitySet.min_elt pos_set in *)
200 (*           let passive_table = *)
201 (*             Indexing.remove_index passive_table current *)
202 (* (\*             if !use_fullred then Indexing.remove_index passive_table current *\) *)
203 (* (\*             else passive_table *\) *)
204 (*           in *)
205 (*           let passive = *)
206 (*             (neg_list, neg_set), *)
207 (*             (remove current pos_list, EqualitySet.remove current pos_set), *)
208 (*             passive_table *)
209 (*           in *)
210 (*           (Positive, current), passive *)
211     )
212   | _ ->
213       symbols_counter := !symbols_ratio;
214       let set_selection set = EqualitySet.min_elt set in
215       if EqualitySet.is_empty neg_set then
216         let current = set_selection pos_set in
217         let passive =
218           (neg_list, neg_set),
219           (remove current pos_list, EqualitySet.remove current pos_set),
220           Indexing.remove_index passive_table current
221 (*           if !use_fullred then Indexing.remove_index passive_table current *)
222 (*           else passive_table *)
223         in
224         (Positive, current), passive
225       else
226         let current = set_selection neg_set in
227         let passive =
228           (remove current neg_list, EqualitySet.remove current neg_set),
229           (pos_list, pos_set),
230           passive_table
231         in
232         (Negative, current), passive
233 ;;
234
235
236 let make_passive neg pos =
237   let set_of equalities =
238     List.fold_left (fun s e -> EqualitySet.add e s) EqualitySet.empty equalities
239   in
240   let table =
241       List.fold_left (fun tbl e -> Indexing.index tbl e)
242         (Indexing.empty_table ()) pos
243 (*     if !use_fullred then *)
244 (*       List.fold_left (fun tbl e -> Indexing.index tbl e) *)
245 (*         (Indexing.empty_table ()) pos *)
246 (*     else *)
247 (*       Indexing.empty_table () *)
248   in
249   (neg, set_of neg),
250   (pos, set_of pos),
251   table
252 ;;
253
254
255 let make_active () =
256   [], Indexing.empty_table () 
257 ;;
258
259
260 let add_to_passive passive (new_neg, new_pos) =
261   let (neg_list, neg_set), (pos_list, pos_set), table = passive in
262   let ok set equality = not (EqualitySet.mem equality set) in
263   let neg = List.filter (ok neg_set) new_neg
264   and pos = List.filter (ok pos_set) new_pos in
265   let table =
266       List.fold_left (fun tbl e -> Indexing.index tbl e) table pos
267 (*     if !use_fullred then *)
268 (*       List.fold_left (fun tbl e -> Indexing.index tbl e) table pos *)
269 (*     else *)
270 (*       table *)
271   in
272   let add set equalities =
273     List.fold_left (fun s e -> EqualitySet.add e s) set equalities
274   in
275   (neg @ neg_list, add neg_set neg),
276   (pos_list @ pos, add pos_set pos),
277   table
278 ;;
279
280
281 let passive_is_empty = function
282   | ([], _), ([], _), _ -> true
283   | _ -> false
284 ;;
285
286
287 let size_of_passive ((_, ns), (_, ps), _) =
288   (EqualitySet.cardinal ns) + (EqualitySet.cardinal ps)
289 ;;
290
291
292 let size_of_active (active_list, _) =
293   List.length active_list
294 ;;
295
296
297 let prune_passive howmany (active, _) passive =
298   let (nl, ns), (pl, ps), tbl = passive in
299   let howmany = float_of_int howmany
300   and ratio = float_of_int !weight_age_ratio in
301   let round v =
302     let t = ceil v in 
303     int_of_float (if t -. v < 0.5 then t else v)
304   in
305   let in_weight = round (howmany *. ratio /. (ratio +. 1.))
306   and in_age = round (howmany /. (ratio +. 1.)) in 
307   debug_print
308     (lazy (Printf.sprintf "in_weight: %d, in_age: %d\n" in_weight in_age));
309   let symbols, card =
310     match active with
311     | (Negative, e)::_ ->
312         let symbols = symbols_of_equality e in
313         let card = TermMap.fold (fun k v res -> res + v) symbols 0 in
314         Some symbols, card
315     | _ -> None, 0
316   in
317   let counter = ref !symbols_ratio in
318   let rec pickw w ns ps =
319     if w > 0 then
320       if not (EqualitySet.is_empty ns) then
321         let e = EqualitySet.min_elt ns in
322         let ns', ps = pickw (w-1) (EqualitySet.remove e ns) ps in
323         EqualitySet.add e ns', ps
324       else if !counter > 0 then
325         let _ =
326           counter := !counter - 1;
327           if !counter = 0 then counter := !symbols_ratio
328         in
329         match symbols with
330         | None ->
331             let e = EqualitySet.min_elt ps in
332             let ns, ps' = pickw (w-1) ns (EqualitySet.remove e ps) in
333             ns, EqualitySet.add e ps'
334         | Some symbols ->
335             let foldfun k v (r1, r2) =
336               if TermMap.mem k symbols then
337                 let c = TermMap.find k symbols in
338                 let c1 = abs (c - v) in
339                 let c2 = v - c1 in
340                 r1 + c2, r2 + c1
341               else
342                 r1, r2 + v
343             in
344             let f equality (i, e) =
345               let common, others =
346                 TermMap.fold foldfun (symbols_of_equality equality) (0, 0)
347               in
348               let c = others + (abs (common - card)) in
349               if c < i then (c, equality)
350               else (i, e)
351             in
352             let e1 = EqualitySet.min_elt ps in
353             let initial =
354               let common, others = 
355                 TermMap.fold foldfun (symbols_of_equality e1) (0, 0)
356               in
357               (others + (abs (common - card))), e1
358             in
359             let _, e = EqualitySet.fold f ps initial in
360             let ns, ps' = pickw (w-1) ns (EqualitySet.remove e ps) in
361             ns, EqualitySet.add e ps'
362       else
363         let e = EqualitySet.min_elt ps in
364         let ns, ps' = pickw (w-1) ns (EqualitySet.remove e ps) in
365         ns, EqualitySet.add e ps'        
366     else
367       EqualitySet.empty, EqualitySet.empty
368   in
369 (*   let in_weight, ns = pickw in_weight ns in *)
370 (*   let _, ps = pickw in_weight ps in *)
371   let ns, ps = pickw in_weight ns ps in
372   let rec picka w s l =
373     if w > 0 then
374       match l with
375       | [] -> w, s, []
376       | hd::tl when not (EqualitySet.mem hd s) ->
377           let w, s, l = picka (w-1) s tl in
378           w, EqualitySet.add hd s, hd::l
379       | hd::tl ->
380           let w, s, l = picka w s tl in
381           w, s, hd::l
382     else
383       0, s, l
384   in
385   let in_age, ns, nl = picka in_age ns nl in
386   let _, ps, pl = picka in_age ps pl in
387   if not (EqualitySet.is_empty ps) then
388 (*     maximal_weight := Some (weight_of_equality (EqualitySet.max_elt ps)); *)
389     maximal_retained_equality := Some (EqualitySet.max_elt ps); 
390   let tbl =
391     EqualitySet.fold
392       (fun e tbl -> Indexing.index tbl e) ps (Indexing.empty_table ())
393 (*     if !use_fullred then *)
394 (*       EqualitySet.fold *)
395 (*         (fun e tbl -> Indexing.index tbl e) ps (Indexing.empty_table ()) *)
396 (*     else *)
397 (*       tbl *)
398   in
399   (nl, ns), (pl, ps), tbl  
400 ;;
401
402
403 let infer env sign current (active_list, active_table) =
404   let new_neg, new_pos = 
405     match sign with
406     | Negative ->
407         let maxm, res = 
408           Indexing.superposition_left !maxmeta env active_table current in
409         maxmeta := maxm;
410         res, [] 
411     | Positive ->
412         let maxm, res =
413           Indexing.superposition_right !maxmeta env active_table current in
414         maxmeta := maxm;
415         let rec infer_positive table = function
416           | [] -> [], []
417           | (Negative, equality)::tl ->
418               let maxm, res =
419                 Indexing.superposition_left !maxmeta env table equality in
420               maxmeta := maxm;
421               let neg, pos = infer_positive table tl in
422               res @ neg, pos
423           | (Positive, equality)::tl ->
424               let maxm, res =
425                 Indexing.superposition_right !maxmeta env table equality in
426               maxmeta := maxm;
427               let neg, pos = infer_positive table tl in
428               neg, res @ pos
429         in
430         let curr_table = Indexing.index (Indexing.empty_table ()) current in
431         let neg, pos = infer_positive curr_table active_list in
432         neg, res @ pos
433   in
434   derived_clauses := !derived_clauses + (List.length new_neg) +
435     (List.length new_pos);
436   match !maximal_retained_equality with
437   | None -> new_neg, new_pos
438   | Some eq ->
439       (* if we have a maximal_retained_equality, we can discard all equalities
440          "greater" than it, as they will never be reached...  An equality is
441          greater than maximal_retained_equality if it is bigger
442          wrt. OrderedEquality.compare and it is less similar than
443          maximal_retained_equality to the current goal *)
444       let symbols, card =
445         match active_list with
446         | (Negative, e)::_ ->
447             let symbols = symbols_of_equality e in
448             let card = TermMap.fold (fun k v res -> res + v) symbols 0 in
449             Some symbols, card
450         | _ -> None, 0
451       in
452       let new_pos = 
453         match symbols with
454         | None ->
455             List.filter (fun e -> OrderedEquality.compare e eq <= 0) new_pos
456         | Some symbols ->
457             let filterfun e =
458               if OrderedEquality.compare e eq <= 0 then
459                 true
460               else
461                 let foldfun k v (r1, r2) =
462                   if TermMap.mem k symbols then
463                     let c = TermMap.find k symbols in
464                     let c1 = abs (c - v) in
465                     let c2 = v - c1 in
466                     r1 + c2, r2 + c1
467                   else
468                     r1, r2 + v
469                 in
470                 let initial =
471                   let common, others =
472                     TermMap.fold foldfun (symbols_of_equality eq) (0, 0) in
473                   others + (abs (common - card))
474                 in
475                 let common, others =
476                   TermMap.fold foldfun (symbols_of_equality e) (0, 0) in
477                 let c = others + (abs (common - card)) in
478                 if c < initial then true else false 
479             in
480             List.filter filterfun new_pos
481       in
482       new_neg, new_pos
483 ;;
484
485
486 let contains_empty env (negative, positive) =
487   let metasenv, context, ugraph = env in
488   try
489     let found =
490       List.find
491         (fun (w, proof, (ty, left, right, ordering), m, a) ->
492            fst (CicReduction.are_convertible context left right ugraph))
493         negative
494     in
495     true, Some found
496   with Not_found ->
497     false, None
498 ;;
499
500
501 let forward_simplify env (sign, current) ?passive (active_list, active_table) =
502   let pl, passive_table =
503     match passive with
504     | None -> [], None
505     | Some ((pn, _), (pp, _), pt) ->
506         let pn = List.map (fun e -> (Negative, e)) pn
507         and pp = List.map (fun e -> (Positive, e)) pp in
508         pn @ pp, Some pt
509   in
510   let all = if pl = [] then active_list else active_list @ pl in
511
512   (*   let rec find_duplicate sign current = function *)
513 (*     | [] -> false *)
514 (*     | (s, eq)::tl when s = sign -> *)
515 (*         if meta_convertibility_eq current eq then true *)
516 (*         else find_duplicate sign current tl *)
517 (*     | _::tl -> find_duplicate sign current tl *)
518 (*   in *)
519
520 (*   let res =  *)
521 (*     if sign = Positive then *)
522 (*       Indexing.subsumption env active_table current *)
523 (*     else *)
524 (*       false *)
525 (*   in *)
526 (*   if res then *)
527 (*     None *)
528 (*   else *)
529   
530   let demodulate table current = 
531     let newmeta, newcurrent =
532       Indexing.demodulation_equality !maxmeta env table sign current in
533     maxmeta := newmeta;
534     if is_identity env newcurrent then
535       if sign = Negative then Some (sign, newcurrent)
536       else None
537     else
538       Some (sign, newcurrent)
539   in
540   let res =
541     let res = demodulate active_table current in
542     match res with
543     | None -> None
544     | Some (sign, newcurrent) ->
545         match passive_table with
546         | None -> res
547         | Some passive_table -> demodulate passive_table newcurrent
548   in
549   match res with
550   | None -> None
551   | Some (Negative, c) ->
552       let ok = not (
553         List.exists
554           (fun (s, eq) -> s = Negative && meta_convertibility_eq eq c)
555           all)
556       in
557       if ok then res else None
558   | Some (Positive, c) ->
559       if Indexing.in_index active_table c then
560         None
561       else
562         match passive_table with
563         | None -> res
564         | Some passive_table ->
565             if Indexing.in_index passive_table c then None
566             else res
567
568 (*   | Some (s, c) -> if find_duplicate s c all then None else res *)
569
570 (*         if s = Utils.Negative then *)
571 (*           res *)
572 (*         else *)
573 (*           if Indexing.subsumption env active_table c then *)
574 (*             None *)
575 (*           else ( *)
576 (*             match passive_table with *)
577 (*             | None -> res *)
578 (*             | Some passive_table -> *)
579 (*                 if Indexing.subsumption env passive_table c then *)
580 (*                   None *)
581 (*                 else *)
582 (*                   res *)
583 (*           ) *)
584
585 (*         let pred (sign, eq) = *)
586 (*           if sign <> s then false *)
587 (*           else subsumption env c eq *)
588 (*         in *)
589 (*         if List.exists pred all then None *)
590 (*         else res *)
591 ;;
592
593 type fs_time_info_t = {
594   mutable build_all: float;
595   mutable demodulate: float;
596   mutable subsumption: float;
597 };;
598
599 let fs_time_info = { build_all = 0.; demodulate = 0.; subsumption = 0. };;
600
601
602 let forward_simplify_new env (new_neg, new_pos) ?passive active =
603   let t1 = Unix.gettimeofday () in
604
605   let active_list, active_table = active in
606   let pl, passive_table =
607     match passive with
608     | None -> [], None
609     | Some ((pn, _), (pp, _), pt) ->
610         let pn = List.map (fun e -> (Negative, e)) pn
611         and pp = List.map (fun e -> (Positive, e)) pp in
612         pn @ pp, Some pt
613   in
614   let all = active_list @ pl in
615   
616   let t2 = Unix.gettimeofday () in
617   fs_time_info.build_all <- fs_time_info.build_all +. (t2 -. t1);
618   
619   let demodulate sign table target =
620     let newmeta, newtarget =
621       Indexing.demodulation_equality !maxmeta env table sign target in
622     maxmeta := newmeta;
623     newtarget
624   in
625 (*   let f sign' target (sign, eq) = *)
626 (*     if sign <> sign' then false *)
627 (*     else subsumption env target eq  *)
628 (*   in *)
629
630   let t1 = Unix.gettimeofday () in
631
632   let new_neg, new_pos =
633     let new_neg = List.map (demodulate Negative active_table) new_neg
634     and new_pos = List.map (demodulate Positive active_table) new_pos in
635     match passive_table with
636     | None -> new_neg, new_pos
637     | Some passive_table ->
638         List.map (demodulate Negative passive_table) new_neg,
639         List.map (demodulate Positive passive_table) new_pos
640   in
641
642   let t2 = Unix.gettimeofday () in
643   fs_time_info.demodulate <- fs_time_info.demodulate +. (t2 -. t1);
644
645   let new_pos_set =
646     List.fold_left
647       (fun s e ->
648          if not (Inference.is_identity env e) then
649            if EqualitySet.mem e s then s
650            else EqualitySet.add e s
651          else s)
652       EqualitySet.empty new_pos
653   in
654   let new_pos = EqualitySet.elements new_pos_set in
655
656   let subs =
657     match passive_table with
658     | None ->
659         (fun e -> not (fst (Indexing.subsumption env active_table e)))
660     | Some passive_table ->
661         (fun e -> not ((fst (Indexing.subsumption env active_table e)) ||
662                          (fst (Indexing.subsumption env passive_table e))))
663   in
664
665   let t1 = Unix.gettimeofday () in
666
667 (*   let new_neg, new_pos = *)
668 (*     List.filter subs new_neg, *)
669 (*     List.filter subs new_pos *)
670 (*   in *)
671
672 (*   let new_neg, new_pos =  *)
673 (*     (List.filter (fun e -> not (List.exists (f Negative e) all)) new_neg, *)
674 (*      List.filter (fun e -> not (List.exists (f Positive e) all)) new_pos) *)
675 (*   in *)
676
677   let t2 = Unix.gettimeofday () in
678   fs_time_info.subsumption <- fs_time_info.subsumption +. (t2 -. t1);
679
680   let is_duplicate =
681     match passive_table with
682     | None ->
683         (fun e -> not (Indexing.in_index active_table e))
684     | Some passive_table ->
685         (fun e ->
686            not ((Indexing.in_index active_table e) ||
687                   (Indexing.in_index passive_table e)))
688   in
689   new_neg, List.filter is_duplicate new_pos
690
691 (*   new_neg, new_pos *)
692
693 (*   let res = *)
694 (*     (List.filter (fun e -> not (List.exists (f Negative e) all)) new_neg, *)
695 (*      List.filter (fun e -> not (List.exists (f Positive e) all)) new_pos) *)
696 (*   in *)
697 (*   res *)
698 ;;
699
700
701 let backward_simplify_active env new_pos new_table min_weight active =
702   let active_list, active_table = active in
703   let active_list, newa = 
704     List.fold_right
705       (fun (s, equality) (res, newn) ->
706          let ew, _, _, _, _ = equality in
707          if ew < min_weight then
708            (s, equality)::res, newn
709          else
710            match forward_simplify env (s, equality) (new_pos, new_table) with
711            | None -> res, newn
712            | Some (s, e) ->
713                if equality = e then
714                  (s, e)::res, newn
715                else 
716                  res, (s, e)::newn)
717       active_list ([], [])
718   in
719   let find eq1 where =
720     List.exists (fun (s, e) -> meta_convertibility_eq eq1 e) where
721   in
722   let active, newa =
723     List.fold_right
724       (fun (s, eq) (res, tbl) ->
725          if List.mem (s, eq) res then
726            res, tbl
727          else if (is_identity env eq) || (find eq res) then (
728            res, tbl
729          ) (* else if (find eq res) then *)
730 (*            res, tbl *)
731          else
732            (s, eq)::res, if s = Negative then tbl else Indexing.index tbl eq)
733       active_list ([], Indexing.empty_table ()),
734     List.fold_right
735       (fun (s, eq) (n, p) ->
736          if (s <> Negative) && (is_identity env eq) then (
737            (n, p)
738          ) else
739            if s = Negative then eq::n, p
740            else n, eq::p)
741       newa ([], [])
742   in
743   match newa with
744   | [], [] -> active, None
745   | _ -> active, Some newa
746 ;;
747
748
749 let backward_simplify_passive env new_pos new_table min_weight passive =
750   let (nl, ns), (pl, ps), passive_table = passive in
751   let f sign equality (resl, ress, newn) =
752     let ew, _, _, _, _ = equality in
753     if ew < min_weight then
754 (*       let _ = debug_print (lazy (Printf.sprintf "OK: %d %d" ew min_weight)) in *)
755       equality::resl, ress, newn
756     else
757       match forward_simplify env (sign, equality) (new_pos, new_table) with
758       | None -> resl, EqualitySet.remove equality ress, newn
759       | Some (s, e) ->
760           if equality = e then
761             equality::resl, ress, newn
762           else
763             let ress = EqualitySet.remove equality ress in
764             resl, ress, e::newn
765   in
766   let nl, ns, newn = List.fold_right (f Negative) nl ([], ns, [])
767   and pl, ps, newp = List.fold_right (f Positive) pl ([], ps, []) in
768   let passive_table =
769     List.fold_left
770       (fun tbl e -> Indexing.index tbl e) (Indexing.empty_table ()) pl
771   in
772   match newn, newp with
773   | [], [] -> ((nl, ns), (pl, ps), passive_table), None
774   | _, _ -> ((nl, ns), (pl, ps), passive_table), Some (newn, newp)
775 ;;
776
777
778 let backward_simplify env new' ?passive active =
779   let new_pos, new_table, min_weight =
780     List.fold_left
781       (fun (l, t, w) e ->
782          let ew, _, _, _, _ = e in
783          (Positive, e)::l, Indexing.index t e, min ew w)
784       ([], Indexing.empty_table (), 1000000) (snd new')
785   in
786   let active, newa =
787     backward_simplify_active env new_pos new_table min_weight active in
788   match passive with
789   | None ->
790       active, (make_passive [] []), newa, None
791   | Some passive ->
792       let passive, newp =
793         backward_simplify_passive env new_pos new_table min_weight passive in
794       active, passive, newa, newp
795 ;;
796
797
798 let get_selection_estimate () =
799   elapsed_time := (Unix.gettimeofday ()) -. !start_time;
800 (*   !processed_clauses * (int_of_float (!time_limit /. !elapsed_time)) *)
801   int_of_float (
802     ceil ((float_of_int !processed_clauses) *.
803             ((!time_limit (* *. 2. *)) /. !elapsed_time -. 1.)))
804 ;;
805
806
807 let make_goals goal =
808   let active = []
809   and passive = [0, [goal]] in
810   active, passive
811 ;;
812
813
814 let make_theorems theorems =
815   theorems, []
816 (*   let active = [] *)
817 (*   and passive = theorems in *)
818 (*   active, passive *)
819 ;;
820
821
822 let activate_goal (active, passive) =
823   match passive with
824   | goal_conj::tl -> true, (goal_conj::active, tl)
825   | [] -> false, (active, passive)
826 ;;
827
828
829 let activate_theorem (active, passive) =
830   match passive with
831   | theorem::tl -> true, (theorem::active, tl)
832   | [] -> false, (active, passive)
833 ;;
834
835   
836 let simplify_goal env goal ?passive (active_list, active_table) =
837   let pl, passive_table =
838     match passive with
839     | None -> [], None
840     | Some ((pn, _), (pp, _), pt) ->
841         let pn = List.map (fun e -> (Negative, e)) pn
842         and pp = List.map (fun e -> (Positive, e)) pp in
843         pn @ pp, Some pt
844   in
845   let all = if pl = [] then active_list else active_list @ pl in
846
847   let demodulate table goal = 
848     let newmeta, newgoal =
849       Indexing.demodulation_goal !maxmeta env table goal in
850     maxmeta := newmeta;
851     goal != newgoal, newgoal
852   in
853   let changed, goal =
854     match passive_table with
855     | None -> demodulate active_table goal
856     | Some passive_table ->
857         let changed, goal = demodulate active_table goal in
858         let changed', goal = demodulate passive_table goal in
859         (changed || changed'), goal
860   in
861 (*   let _ = *)
862 (*     let p, _, t = goal in *)
863 (*     debug_print *)
864 (*       (lazy *)
865 (*          (Printf.sprintf "Goal after demodulation: %s, %s" *)
866 (*             (string_of_proof p) (CicPp.ppterm t))) *)
867 (*   in *)
868   changed, goal
869 ;;
870
871
872 let simplify_goals env goals ?passive active =
873   let a_goals, p_goals = goals in
874   let p_goals = 
875     List.map
876       (fun (d, gl) ->
877          let gl =
878            List.map (fun g -> snd (simplify_goal env g ?passive active)) gl in
879          d, gl)
880       p_goals
881   in
882   let goals =
883     List.fold_left
884       (fun (a, p) (d, gl) ->
885          let changed = ref false in
886          let gl =
887            List.map
888              (fun g ->
889                 let c, g = simplify_goal env g ?passive active in
890                 changed := !changed || c; g) gl in
891          if !changed then (a, (d, gl)::p) else ((d, gl)::a, p))
892       ([], p_goals) a_goals
893   in
894   goals
895 ;;
896
897
898 let simplify_theorems env theorems ?passive (active_list, active_table) =
899   let pl, passive_table =
900     match passive with
901     | None -> [], None
902     | Some ((pn, _), (pp, _), pt) ->
903         let pn = List.map (fun e -> (Negative, e)) pn
904         and pp = List.map (fun e -> (Positive, e)) pp in
905         pn @ pp, Some pt
906   in
907   let all = if pl = [] then active_list else active_list @ pl in
908   let a_theorems, p_theorems = theorems in
909   let demodulate table theorem =
910     let newmeta, newthm =
911       Indexing.demodulation_theorem !maxmeta env table theorem in
912     maxmeta := newmeta;
913     theorem != newthm, newthm
914   in
915   let foldfun table (a, p) theorem =
916     let changed, theorem = demodulate table theorem in
917     if changed then (a, theorem::p) else (theorem::a, p)
918   in
919   let mapfun table theorem = snd (demodulate table theorem) in
920   match passive_table with
921   | None ->
922       let p_theorems = List.map (mapfun active_table) p_theorems in
923       List.fold_left (foldfun active_table) ([], p_theorems) a_theorems
924 (*       List.map (demodulate active_table) theorems *)
925   | Some passive_table ->
926       let p_theorems = List.map (mapfun active_table) p_theorems in
927       let p_theorems, a_theorems =
928         List.fold_left (foldfun active_table) ([], p_theorems) a_theorems in
929       let p_theorems = List.map (mapfun passive_table) p_theorems in
930       List.fold_left (foldfun passive_table) ([], p_theorems) a_theorems
931 (*       let theorems = List.map (demodulate active_table) theorems in *)
932 (*       List.map (demodulate passive_table) theorems *)
933 ;;
934
935
936 let apply_equality_to_goal env equality goal =
937   let module C = Cic in
938   let module HL = HelmLibraryObjects in
939   let module I = Inference in
940   let metasenv, context, ugraph = env in
941   let _, proof, (ty, left, right, _), metas, args = equality in
942   let eqterm =
943     C.Appl [C.MutInd (LibraryObjects.eq_URI (), 0, []); ty; left; right] in
944   let gproof, gmetas, gterm = goal in
945   try
946     let subst, metasenv', _ =
947       let menv = metasenv @ metas @ gmetas in
948       Inference.unification menv context eqterm gterm ugraph
949     in
950     let newproof =
951       match proof with
952       | I.BasicProof t -> I.BasicProof (CicMetaSubst.apply_subst subst t)
953       | I.ProofBlock (s, uri, nt, t, pe, p) ->
954           I.ProofBlock (subst @ s, uri, nt, t, pe, p)
955       | _ -> assert false
956     in
957     let newgproof =
958       let rec repl = function
959         | I.ProofGoalBlock (_, gp) -> I.ProofGoalBlock (newproof, gp)
960         | I.NoProof -> newproof
961         | I.BasicProof p -> newproof
962         | I.SubProof (t, i, p) -> I.SubProof (t, i, repl p)
963         | _ -> assert false
964       in
965       repl gproof
966     in
967     true, subst, newgproof
968   with CicUnification.UnificationFailure _ ->
969     false, [], I.NoProof
970 ;;
971
972
973 (*
974 let apply_to_goal env theorems active (depth, goals) =
975   let _ =
976     debug_print ("apply_to_goal: " ^ (string_of_int (List.length goals)))
977   in
978   let metasenv, context, ugraph = env in
979   let goal = List.hd goals in
980   let proof, metas, term = goal in
981 (*   debug_print *)
982 (*     (Printf.sprintf "apply_to_goal with goal: %s" (CicPp.ppterm term)); *)
983   let newmeta = CicMkImplicit.new_meta metasenv [] in
984   let metasenv = (newmeta, context, term)::metasenv @ metas in
985   let irl = CicMkImplicit.identity_relocation_list_for_metavariable context in
986   let status =
987     ((None, metasenv, Cic.Meta (newmeta, irl), term), newmeta)
988   in
989   let rec aux = function
990     | [] -> false, [] (* goals *) (* None *)
991     | (theorem, thmty, _)::tl ->
992         try
993           let subst_in, (newproof, newgoals) =
994             PrimitiveTactics.apply_tac_verbose ~term:theorem status
995           in
996           if newgoals = [] then
997             let _, _, p, _ = newproof in
998             let newp =
999               let rec repl = function
1000                 | Inference.ProofGoalBlock (_, gp) ->
1001                     Inference.ProofGoalBlock (Inference.BasicProof p, gp)
1002                 | Inference.NoProof -> Inference.BasicProof p
1003                 | Inference.BasicProof _ -> Inference.BasicProof p
1004                 | Inference.SubProof (t, i, p2) ->
1005                     Inference.SubProof (t, i, repl p2)
1006                 | _ -> assert false
1007               in
1008               repl proof
1009             in
1010             true, [[newp, metas, term]] (* Some newp *)
1011           else if List.length newgoals = 1 then
1012             let _, menv, p, _ = newproof in
1013             let irl =
1014               CicMkImplicit.identity_relocation_list_for_metavariable context
1015             in
1016             let goals =
1017               List.map
1018                 (fun i ->
1019                    let _, _, ty = CicUtil.lookup_meta i menv in
1020                    let proof =
1021                      Inference.SubProof
1022                        (p, i, Inference.BasicProof (Cic.Meta (i, irl)))
1023                    in (proof, menv, ty))
1024                 newgoals
1025             in
1026             let res, others = aux tl in
1027             if res then (true, others) else (false, goals::others)
1028           else
1029             aux tl
1030         with ProofEngineTypes.Fail msg ->
1031           (*     debug_print ("FAIL!!:" ^ msg); *)
1032           aux tl
1033   in
1034   let r, l =
1035     if Inference.term_is_equality term then
1036       let rec appleq = function
1037         | [] -> false, []
1038         | (Positive, equality)::tl ->
1039             let ok, _, newproof = apply_equality_to_goal env equality goal in
1040             if ok then true, [(depth, [newproof, metas, term])] else appleq tl
1041         | _::tl -> appleq tl
1042       in
1043       let al, _ = active in
1044       appleq al
1045     else
1046       false, []
1047   in
1048   if r = true then r, l else
1049     let r, l = aux theorems in
1050     if r = true then
1051       r, List.map (fun l -> (depth+1, l)) l
1052     else
1053       r, (depth, goals)::(List.map (fun l -> (depth+1, l)) l)
1054 ;;
1055 *)
1056
1057
1058 let new_meta () =
1059   incr maxmeta; !maxmeta
1060 ;;
1061
1062
1063 let apply_to_goal env theorems active goal =
1064   let metasenv, context, ugraph = env in
1065   let proof, metas, term = goal in
1066   debug_print
1067     (lazy
1068        (Printf.sprintf "apply_to_goal with goal: %s"
1069           (* (string_of_proof proof)  *)(CicPp.ppterm term)));
1070   let status =
1071     let irl =
1072       CicMkImplicit.identity_relocation_list_for_metavariable context in
1073     let proof', newmeta =
1074       let rec get_meta = function
1075         | SubProof (t, i, _) -> t, i
1076         | ProofGoalBlock (_, p) -> get_meta p
1077         | _ ->
1078             let n = new_meta () in (* CicMkImplicit.new_meta metasenv [] in *)
1079             Cic.Meta (n, irl), n
1080       in
1081       get_meta proof
1082     in
1083 (*     let newmeta = CicMkImplicit.new_meta metasenv [] in *)
1084     let metasenv = (newmeta, context, term)::metasenv @ metas in
1085     ((None, metasenv, Cic.Meta (newmeta, irl), term), newmeta)
1086 (*     ((None, metasenv, proof', term), newmeta) *)
1087   in
1088   let rec aux = function
1089     | [] -> `No (* , [], [] *)
1090     | (theorem, thmty, _)::tl ->
1091         try
1092           let subst, (newproof, newgoals) =
1093             PrimitiveTactics.apply_tac_verbose_with_subst ~term:theorem status
1094           in
1095           if newgoals = [] then
1096             let _, _, p, _ = newproof in
1097             let newp =
1098               let rec repl = function
1099                 | Inference.ProofGoalBlock (_, gp) ->
1100                     Inference.ProofGoalBlock (Inference.BasicProof p, gp)
1101                 | Inference.NoProof -> Inference.BasicProof p
1102                 | Inference.BasicProof _ -> Inference.BasicProof p
1103                 | Inference.SubProof (t, i, p2) ->
1104                     Inference.SubProof (t, i, repl p2)
1105                 | _ -> assert false
1106               in
1107               repl proof
1108             in
1109             let _, m = status in
1110             let subst = List.filter (fun (i, _) -> i = m) subst in
1111 (*             debug_print *)
1112 (*               (lazy *)
1113 (*                  (Printf.sprintf "m = %d\nsubst = %s\n" *)
1114 (*                     m (print_subst subst))); *)
1115             `Ok (subst, [newp, metas, term])
1116           else
1117             let _, menv, p, _ = newproof in
1118             let irl =
1119               CicMkImplicit.identity_relocation_list_for_metavariable context
1120             in
1121             let goals =
1122               List.map
1123                 (fun i ->
1124                    let _, _, ty = CicUtil.lookup_meta i menv in
1125                    let p' =
1126                      let rec gp = function
1127                        | SubProof (t, i, p) ->
1128                            SubProof (t, i, gp p)
1129                        | ProofGoalBlock (sp1, sp2) ->
1130 (*                            SubProof (p, i, sp) *)
1131                            ProofGoalBlock (sp1, gp sp2)
1132 (*                            gp sp *)
1133                        | BasicProof _
1134                        | NoProof ->
1135                            SubProof (p, i, BasicProof (Cic.Meta (i, irl)))
1136                        | ProofSymBlock (s, sp) ->
1137                            ProofSymBlock (s, gp sp)
1138                        | ProofBlock (s, u, nt, t, pe, sp) ->
1139                            ProofBlock (s, u, nt, t, pe, gp sp)
1140 (*                        | _ -> assert false *)
1141                      in gp proof
1142                    in
1143                    debug_print
1144                      (lazy
1145                         (Printf.sprintf "new sub goal: %s"
1146                            (* (string_of_proof p')  *)(CicPp.ppterm ty)));
1147                    (p', menv, ty))
1148                 newgoals
1149             in
1150             let goals =
1151               let weight t =
1152                 let w, m = weight_of_term t in
1153                 w + 2 * (List.length m)
1154               in
1155               List.sort
1156                 (fun (_, _, t1) (_, _, t2) ->
1157                    Pervasives.compare (weight t1) (weight t2))
1158                 goals
1159             in
1160 (*             debug_print *)
1161 (*               (lazy *)
1162 (*                  (Printf.sprintf "\nGoOn with subst: %s" (print_subst subst))); *)
1163             let best = aux tl in
1164             match best with
1165             | `Ok (_, _) -> best
1166             | `No -> `GoOn ([subst, goals])
1167             | `GoOn sl(* , subst', goals' *) ->
1168 (*                 if (List.length goals') < (List.length goals) then best *)
1169 (*                 else `GoOn, subst, goals *)
1170                 `GoOn ((subst, goals)::sl)
1171         with ProofEngineTypes.Fail msg ->
1172           aux tl
1173   in
1174   let r, s, l =
1175     if Inference.term_is_equality term then
1176       let rec appleq = function
1177         | [] -> false, [], []
1178         | (Positive, equality)::tl ->
1179             let ok, s, newproof = apply_equality_to_goal env equality goal in
1180             if ok then true, s, [newproof, metas, term] else appleq tl
1181         | _::tl -> appleq tl
1182       in
1183       let al, _ = active in
1184       appleq al
1185     else
1186       false, [], []
1187   in
1188   if r = true then `Ok (s, l) else aux theorems
1189 ;;
1190
1191
1192 let apply_to_goal_conj env theorems active (depth, goals) =
1193   let rec aux = function
1194     | goal::tl ->
1195         let propagate_subst subst (proof, metas, term) =
1196 (*           debug_print *)
1197 (*             (lazy *)
1198 (*                (Printf.sprintf "\npropagate_subst:\n%s\n%s, %s\n" *)
1199 (*                   (print_subst subst) (string_of_proof proof) *)
1200 (*                   (CicPp.ppterm term))); *)
1201           let rec repl = function
1202             | NoProof -> NoProof
1203             | BasicProof t ->
1204                 BasicProof (CicMetaSubst.apply_subst subst t)
1205             | ProofGoalBlock (p, pb) ->
1206 (*                 debug_print (lazy "HERE"); *)
1207                 let pb' = repl pb in
1208                 ProofGoalBlock (p, pb')
1209             | SubProof (t, i, p) ->
1210                 let t' = CicMetaSubst.apply_subst subst t in
1211 (*                 debug_print *)
1212 (*                   (lazy *)
1213 (*                      (Printf.sprintf *)
1214 (*                         "SubProof %d\nt = %s\nsubst = %s\nt' = %s\n" *)
1215 (*                         i (CicPp.ppterm t) (print_subst subst) *)
1216 (*                         (CicPp.ppterm t'))); *)
1217                 let p = repl p in
1218                 SubProof (t', i, p)
1219             | ProofSymBlock (ens, p) -> ProofSymBlock (ens, repl p)
1220             | ProofBlock (s, u, nty, t, pe, p) ->
1221                 ProofBlock (subst @ s, u, nty, t, pe, p)
1222           in (repl proof, metas, term)
1223         in
1224         let r = apply_to_goal env theorems active goal in (
1225           match r with
1226           | `No -> `No (depth, goals)
1227           | `GoOn sl (* (subst, gl) *) ->
1228 (*               let tl = List.map (propagate_subst subst) tl in *)
1229 (*               debug_print (lazy "GO ON!!!"); *)
1230               let l =
1231                 List.map
1232                   (fun (s, gl) ->
1233                      (depth+1, gl @ (List.map (propagate_subst s) tl))) sl
1234               in
1235 (*               debug_print *)
1236 (*                 (lazy *)
1237 (*                    (Printf.sprintf "%s\n" *)
1238 (*                       (String.concat "; " *)
1239 (*                          (List.map *)
1240 (*                             (fun (s, gl) -> *)
1241 (*                                (Printf.sprintf "[%s]" *)
1242 (*                                   (String.concat "; " *)
1243 (*                                      (List.map *)
1244 (*                                         (fun (p, _, g) -> *)
1245 (*                                            (Printf.sprintf "<%s, %s>" *)
1246 (*                                               (string_of_proof p) *)
1247 (*                                               (CicPp.ppterm g))) gl)))) l)))); *)
1248               `GoOn l (* (depth+1, gl @ tl) *)
1249           | `Ok (subst, gl) ->
1250               if tl = [] then
1251 (*                 let _ = *)
1252 (*                   let p, _, t = List.hd gl in *)
1253 (*                   debug_print *)
1254 (*                     (lazy *)
1255 (*                        (Printf.sprintf "OK: %s, %s\n" *)
1256 (*                           (string_of_proof p) (CicPp.ppterm t))) *)
1257 (*                 in *)
1258                 `Ok (depth, gl)
1259               else
1260                 let p, _, _ = List.hd gl in
1261                 let subproof =
1262                   let rec repl = function
1263                     | SubProof (_, _, p) -> repl p
1264                     | ProofGoalBlock (p1, p2) ->
1265                         ProofGoalBlock (repl p1, repl p2)
1266                     | p -> p
1267                   in
1268                   build_proof_term (repl p)
1269                 in
1270                 let i = 
1271                   let rec get_meta = function
1272                     | SubProof (_, i, p) -> max i (get_meta p)
1273                     | ProofGoalBlock (_, p) -> get_meta p
1274                     | _ -> -1 (* assert false *)
1275                   in
1276                   get_meta p
1277                 in
1278                 let subst =
1279                   let _, (context, _, _) = List.hd subst in
1280                   [i, (context, subproof, Cic.Implicit None)]
1281                 in
1282                 let tl = List.map (propagate_subst subst) tl in
1283                 `GoOn ([depth+1, tl])
1284         )
1285     | _ -> assert false
1286   in
1287   debug_print
1288     (lazy
1289        (Printf.sprintf "apply_to_goal_conj (%d, [%s])"
1290           depth
1291           (String.concat "; "
1292              (List.map (fun (_, _, t) -> CicPp.ppterm t) goals))));
1293   if depth > !maxdepth || (List.length goals) > !maxwidth then (
1294     debug_print
1295       (lazy (Printf.sprintf "Pruning because depth = %d, width = %d"
1296                depth (List.length goals)));
1297     `No (depth, goals)
1298   ) else
1299     aux goals
1300 ;;
1301
1302
1303 module OrderedGoals = struct
1304   type t = int * (Inference.proof * Cic.metasenv * Cic.term) list
1305
1306   let compare g1 g2 =
1307     let d1, l1 = g1
1308     and d2, l2 = g2 in
1309     let r = d2 - d1 in
1310     if r <> 0 then r
1311     else let r = (List.length l1) - (List.length l2) in
1312     if r <> 0 then r
1313     else
1314       let res = ref 0 in
1315       let _ = 
1316         List.exists2
1317           (fun (_, _, t1) (_, _, t2) ->
1318              let r = Pervasives.compare t1 t2 in
1319              if r <> 0 then (
1320                res := r;
1321                true
1322              ) else
1323                false) l1 l2
1324       in !res
1325 (*       let res = Pervasives.compare g1 g2 in *)
1326 (*       let _ = *)
1327 (*         let print_goals (d, gl) =  *)
1328 (*           let gl' = List.map (fun (_, _, t) -> CicPp.ppterm t) gl in *)
1329 (*           Printf.sprintf "%d, [%s]" d (String.concat "; " gl') *)
1330 (*         in *)
1331 (*         debug_print *)
1332 (*           (lazy *)
1333 (*              (Printf.sprintf "comparing g1:%s and g2:%s, res: %d\n" *)
1334 (*                 (print_goals g1) (print_goals g2) res)) *)
1335 (*       in *)
1336 (*       res *)
1337 end
1338
1339 module GoalsSet = Set.Make(OrderedGoals);;
1340
1341
1342 exception SearchSpaceOver;;
1343
1344
1345 let apply_to_goals env is_passive_empty theorems active goals =
1346   debug_print (lazy "\n\n\tapply_to_goals\n\n");
1347   let add_to set goals =
1348     List.fold_left (fun s g -> GoalsSet.add g s) set goals 
1349   in
1350   let rec aux set = function
1351     | [] ->
1352         debug_print (lazy "HERE!!!");
1353         if is_passive_empty then raise SearchSpaceOver else false, set
1354     | goals::tl ->
1355         let res = apply_to_goal_conj env theorems active goals in
1356         match res with
1357         | `Ok newgoals ->
1358             let _ =
1359               let d, p, t =
1360                 match newgoals with
1361                 | (d, (p, _, t)::_) -> d, p, t
1362                 | _ -> assert false
1363               in
1364               debug_print
1365                 (lazy
1366                    (Printf.sprintf "\nOK!!!!\ndepth: %d\nProof: %s\ngoal: %s\n"
1367                       d (string_of_proof p) (CicPp.ppterm t)))
1368             in
1369             true, GoalsSet.singleton newgoals
1370         | `GoOn newgoals ->
1371 (*             let print_set set msg =  *)
1372 (*               debug_print *)
1373 (*                 (lazy *)
1374 (*                    (Printf.sprintf "%s:\n%s" msg *)
1375 (*                       (String.concat "\n" *)
1376 (*                          (GoalsSet.fold *)
1377 (*                             (fun (d, gl) l -> *)
1378 (*                                let gl' = *)
1379 (*                                  List.map (fun (_, _, t) -> CicPp.ppterm t) gl *)
1380 (*                                in *)
1381 (*                                let s = *)
1382 (*                                  Printf.sprintf "%d, [%s]" d *)
1383 (*                                    (String.concat "; " gl') *)
1384 (*                                in *)
1385 (*                                s::l) set [])))) *)
1386 (*             in *)
1387
1388 (*             let r, s = *)
1389 (*               try aux set tl with SearchSpaceOver -> false, GoalsSet.empty *)
1390 (*             in  *)
1391 (*             if r then *)
1392 (*               r, s *)
1393 (*             else  *)
1394             
1395             let set' = add_to set (goals::tl) in
1396 (*             print_set set "SET BEFORE"; *)
1397 (*             let n = GoalsSet.cardinal set in *)
1398             let set' = add_to set' newgoals in
1399 (*             print_set set "SET AFTER"; *)
1400 (*             let m = GoalsSet.cardinal set in *)
1401 (*             if n < m then *)
1402             false, set'
1403 (*             else *)
1404 (*               let _ = print_set set "SET didn't change" in *)
1405 (*               aux set tl *)
1406         | `No newgoals ->
1407             aux set tl
1408 (*             let set = add_to set (newgoals::goals::tl) in *)
1409 (*             let res, set = aux set tl in *)
1410 (*             res, set *)
1411   in
1412   let n = List.length goals in
1413   let res, goals = aux (add_to GoalsSet.empty goals) goals in
1414   let goals = GoalsSet.elements goals in
1415   debug_print (lazy "\n\tapply_to_goals end\n");
1416   let m = List.length goals in
1417   if m = n && is_passive_empty then
1418     raise SearchSpaceOver
1419   else
1420     res, goals
1421 ;;
1422
1423
1424 let apply_goal_to_theorems dbd env theorems active goals =
1425 (*   let theorems, _ = theorems in *)
1426   let context_hyp, library_thms = theorems in
1427   let thm_uris =
1428     List.fold_left
1429       (fun s (u, _, _, _) -> UriManager.UriSet.add u s)
1430       UriManager.UriSet.empty library_thms
1431   in
1432   let a_goals, p_goals = goals in
1433   let goal = List.hd a_goals in
1434   let rec aux = function
1435     | [] -> false, (a_goals, p_goals)
1436     | theorem::tl ->
1437         let res = apply_to_goal_conj env [theorem] active goal in
1438         match res with
1439         | `Ok newgoals ->
1440             true, ([newgoals], [])
1441         | `No _ ->
1442             aux tl
1443 (*             false, (a_goals, p_goals) *)
1444         | `GoOn newgoals ->
1445             let res, (ag, pg) = aux tl in
1446             if res then
1447               res, (ag, pg)
1448             else
1449               let newgoals =
1450                 List.filter
1451                   (fun (d, gl) ->
1452                      (d <= !maxdepth) && (List.length gl) <= !maxwidth)
1453                   newgoals in
1454               let p_goals = newgoals @ pg in
1455               let p_goals =
1456                 List.stable_sort
1457                   (fun (d1, l1) (d2, l2) -> (List.length l1) - (List.length l2))
1458                   p_goals
1459               in
1460               res, (ag, p_goals)
1461   in
1462   let theorems =
1463 (*     let ty = *)
1464 (*       match goal with *)
1465 (*       | (_, (_, _, t)::_) -> t *)
1466 (*       | _ -> assert false *)
1467 (*     in *)
1468 (*     if CicUtil.is_meta_closed ty then *)
1469 (*       let _ =  *)
1470 (*         debug_print (lazy (Printf.sprintf "META CLOSED: %s" (CicPp.ppterm ty))) *)
1471 (*       in *)
1472 (*       let metasenv, context, ugraph = env in *)
1473 (*       let uris = *)
1474 (*         MetadataConstraints.sigmatch ~dbd (MetadataConstraints.signature_of ty) *)
1475 (*       in *)
1476 (*       let uris = List.sort (fun (i, _) (j, _) -> Pervasives.compare i j) uris in *)
1477 (*       let uris = *)
1478 (*         List.filter *)
1479 (*           (fun u -> UriManager.UriSet.mem u thm_uris) (List.map snd uris) *)
1480 (*       in *)
1481 (*       List.map *)
1482 (*         (fun u -> *)
1483 (*            let t = CicUtil.term_of_uri u in *)
1484 (*            let ty, _ = CicTypeChecker.type_of_aux' metasenv context t ugraph in *)
1485 (*            (t, ty, [])) *)
1486 (*         uris *)
1487 (*     else *)
1488     List.map (fun (_, t, ty, m) -> (t, ty, m)) library_thms
1489   in
1490   aux (context_hyp @ theorems)
1491 ;;
1492
1493
1494 let apply_theorem_to_goals env theorems active goals =
1495   let a_goals, p_goals = goals in
1496   let theorem = List.hd (fst theorems) in
1497   let theorems = [theorem] in
1498   let rec aux p = function
1499     | [] -> false, ([], p)
1500     | goal::tl ->
1501         let res = apply_to_goal_conj env theorems active goal in
1502         match res with
1503         | `Ok newgoals -> true, ([newgoals], [])
1504         | `No _ -> aux p tl
1505         | `GoOn newgoals -> aux (newgoals @ p) tl
1506   in
1507   let ok, (a, p) = aux p_goals a_goals in
1508   if ok then
1509     ok, (a, p)
1510   else
1511     let p_goals =
1512       List.stable_sort
1513         (fun (d1, l1) (d2, l2) ->
1514            let r = d2 - d1 in
1515            if r <> 0 then r
1516            else let r = (List.length l1) - (List.length l2) in
1517            if r <> 0 then r
1518            else
1519              let res = ref 0 in
1520              let _ = 
1521                List.exists2
1522                  (fun (_, _, t1) (_, _, t2) ->
1523                     let r = Pervasives.compare t1 t2 in
1524                     if r <> 0 then (res := r; true) else false) l1 l2
1525              in !res)
1526         p
1527     in
1528     ok, (a_goals, p_goals)
1529 ;;
1530
1531
1532 let rec given_clause dbd env goals theorems passive active =
1533   let goals = simplify_goals env goals active in
1534   let ok, goals = activate_goal goals in
1535 (*   let theorems = simplify_theorems env theorems active in *)
1536   if ok then
1537     let ok, goals = apply_goal_to_theorems dbd env theorems active goals in
1538     if ok then
1539       let proof =
1540         match (fst goals) with
1541         | (_, [proof, _, _])::_ -> Some proof
1542         | _ -> assert false
1543       in
1544       ParamodulationSuccess (proof, env)
1545     else
1546       given_clause_aux dbd env goals theorems passive active
1547   else
1548 (*     let ok', theorems = activate_theorem theorems in *)
1549     let ok', theorems = false, theorems in
1550     if ok' then
1551       let ok, goals = apply_theorem_to_goals env theorems active goals in
1552       if ok then
1553         let proof =
1554           match (fst goals) with
1555           | (_, [proof, _, _])::_ -> Some proof
1556           | _ -> assert false
1557         in
1558         ParamodulationSuccess (proof, env)
1559       else
1560         given_clause_aux dbd env goals theorems passive active
1561     else
1562       if (passive_is_empty passive) then ParamodulationFailure
1563       else given_clause_aux dbd env goals theorems passive active
1564
1565 and given_clause_aux dbd env goals theorems passive active = 
1566   let time1 = Unix.gettimeofday () in
1567
1568   let selection_estimate = get_selection_estimate () in
1569   let kept = size_of_passive passive in
1570   let passive =
1571     if !time_limit = 0. || !processed_clauses = 0 then
1572       passive
1573     else if !elapsed_time > !time_limit then (
1574       debug_print (lazy (Printf.sprintf "Time limit (%.2f) reached: %.2f\n"
1575                            !time_limit !elapsed_time));
1576       make_passive [] []
1577     ) else if kept > selection_estimate then (
1578       debug_print
1579         (lazy (Printf.sprintf ("Too many passive equalities: pruning..." ^^
1580                                  "(kept: %d, selection_estimate: %d)\n")
1581                  kept selection_estimate));
1582       prune_passive selection_estimate active passive
1583     ) else
1584       passive
1585   in
1586
1587   let time2 = Unix.gettimeofday () in
1588   passive_maintainance_time := !passive_maintainance_time +. (time2 -. time1);
1589
1590   kept_clauses := (size_of_passive passive) + (size_of_active active);
1591     
1592 (* (\*   let goals = simplify_goals env goals active in *\) *)
1593 (* (\*   let theorems = simplify_theorems env theorems active in  *\) *)
1594 (*   let is_passive_empty = passive_is_empty passive in *)
1595 (*   try *)
1596 (*     let ok, goals = false, [] in (\* apply_to_goals env is_passive_empty theorems active goals in *\) *)
1597 (*     if ok then *)
1598 (*       let proof = *)
1599 (*         match goals with *)
1600 (*         | (_, [proof, _, _])::_ -> Some proof *)
1601 (*         | _ -> assert false *)
1602 (*       in *)
1603 (*       ParamodulationSuccess (proof, env) *)
1604 (*     else *)
1605   match passive_is_empty passive with
1606   | true -> (* ParamodulationFailure *)
1607       given_clause dbd env goals theorems passive active
1608   | false ->
1609       let (sign, current), passive = select env (fst goals) passive active in
1610       let time1 = Unix.gettimeofday () in
1611       let res = forward_simplify env (sign, current) ~passive active in
1612       let time2 = Unix.gettimeofday () in
1613       forward_simpl_time := !forward_simpl_time +. (time2 -. time1);
1614       match res with
1615       | None ->
1616           given_clause dbd env goals theorems passive active
1617       | Some (sign, current) ->
1618           if (sign = Negative) && (is_identity env current) then (
1619             debug_print
1620               (lazy (Printf.sprintf "OK!!! %s %s" (string_of_sign sign)
1621                        (string_of_equality ~env current)));
1622             let _, proof, _, _, _  = current in
1623             ParamodulationSuccess (Some proof (* current *), env)
1624           ) else (            
1625             debug_print
1626               (lazy "\n================================================");
1627             debug_print (lazy (Printf.sprintf "selected: %s %s"
1628                                  (string_of_sign sign)
1629                                  (string_of_equality ~env current)));
1630
1631             let t1 = Unix.gettimeofday () in
1632             let new' = infer env sign current active in
1633             let t2 = Unix.gettimeofday () in
1634             infer_time := !infer_time +. (t2 -. t1);
1635             
1636             let res, goal' = contains_empty env new' in
1637             if res then
1638               let proof =
1639                 match goal' with
1640                 | Some goal -> let _, proof, _, _, _ = goal in Some proof
1641                 | None -> None
1642               in
1643               ParamodulationSuccess (proof (* goal *), env)
1644             else 
1645               let t1 = Unix.gettimeofday () in
1646               let new' = forward_simplify_new env new' active in
1647               let t2 = Unix.gettimeofday () in
1648               let _ =
1649                 forward_simpl_new_time :=
1650                   !forward_simpl_new_time +. (t2 -. t1)
1651               in
1652               let active =
1653                 match sign with
1654                 | Negative -> active
1655                 | Positive ->
1656                     let t1 = Unix.gettimeofday () in
1657                     let active, _, newa, _ =
1658                       backward_simplify env ([], [current]) active
1659                     in
1660                     let t2 = Unix.gettimeofday () in
1661                     backward_simpl_time :=
1662                       !backward_simpl_time +. (t2 -. t1);
1663                     match newa with
1664                     | None -> active
1665                     | Some (n, p) ->
1666                         let al, tbl = active in
1667                         let nn = List.map (fun e -> Negative, e) n in
1668                         let pp, tbl =
1669                           List.fold_right
1670                             (fun e (l, t) ->
1671                                (Positive, e)::l,
1672                                Indexing.index tbl e)
1673                             p ([], tbl)
1674                         in
1675                         nn @ al @ pp, tbl
1676               in
1677 (*               let _ = *)
1678 (*                 Printf.printf "active:\n%s\n" *)
1679 (*                   (String.concat "\n" *)
1680 (*                      ((List.map *)
1681 (*                          (fun (s, e) -> (string_of_sign s) ^ " " ^ *)
1682 (*                             (string_of_equality ~env e)) (fst active)))); *)
1683 (*                 print_newline (); *)
1684 (*               in *)
1685 (*               let _ = *)
1686 (*                 match new' with *)
1687 (*                 | neg, pos -> *)
1688 (*                     Printf.printf "new':\n%s\n" *)
1689 (*                       (String.concat "\n" *)
1690 (*                          ((List.map *)
1691 (*                              (fun e -> "Negative " ^ *)
1692 (*                                 (string_of_equality ~env e)) neg) @ *)
1693 (*                             (List.map *)
1694 (*                                (fun e -> "Positive " ^ *)
1695 (*                                   (string_of_equality ~env e)) pos))); *)
1696 (*                     print_newline (); *)
1697 (*               in *)
1698               match contains_empty env new' with
1699               | false, _ -> 
1700                   let active =
1701                     let al, tbl = active in
1702                     match sign with
1703                     | Negative -> (sign, current)::al, tbl
1704                     | Positive ->
1705                         al @ [(sign, current)], Indexing.index tbl current
1706                   in
1707                   let passive = add_to_passive passive new' in
1708                   let (_, ns), (_, ps), _ = passive in
1709 (*                   Printf.printf "passive:\n%s\n" *)
1710 (*                     (String.concat "\n" *)
1711 (*                        ((List.map (fun e -> "Negative " ^ *)
1712 (*                                      (string_of_equality ~env e)) *)
1713 (*                            (EqualitySet.elements ns)) @ *)
1714 (*                           (List.map (fun e -> "Positive " ^ *)
1715 (*                                        (string_of_equality ~env e)) *)
1716 (*                              (EqualitySet.elements ps)))); *)
1717 (*                   print_newline (); *)
1718                   given_clause dbd env goals theorems passive active
1719               | true, goal ->
1720                   let proof =
1721                     match goal with
1722                     | Some goal ->
1723                         let _, proof, _, _, _ = goal in Some proof
1724                     | None -> None
1725                   in
1726                   ParamodulationSuccess (proof (* goal *), env)
1727           )
1728 (*   with SearchSpaceOver -> *)
1729 (*     ParamodulationFailure *)
1730 ;;
1731
1732
1733 let rec given_clause_fullred dbd env goals theorems passive active =
1734   let goals = simplify_goals env goals ~passive active in
1735   let ok, goals = activate_goal goals in
1736 (*   let theorems = simplify_theorems env theorems ~passive active in *)
1737   if ok then
1738     let _ =
1739       let print_goals goals = 
1740         (String.concat "\n"
1741            (List.map
1742               (fun (d, gl) ->
1743                  let gl' =
1744                    List.map
1745                      (fun (p, _, t) ->
1746                         (* (string_of_proof p) ^ ", " ^ *) (CicPp.ppterm t)) gl
1747                  in
1748                  Printf.sprintf "%d: %s" d (String.concat "; " gl')) goals))
1749       in
1750       debug_print
1751         (lazy
1752            (Printf.sprintf "\ngoals = \nactive\n%s\npassive\n%s\n"
1753               (print_goals (fst goals)) (print_goals (snd goals))))
1754     in
1755     let ok, goals = apply_goal_to_theorems dbd env theorems active goals in
1756     if ok then
1757       let proof =
1758         match (fst goals) with
1759         | (_, [proof, _, _])::_ -> Some proof
1760         | _ -> assert false
1761       in
1762       ParamodulationSuccess (proof, env)
1763     else
1764       given_clause_fullred_aux dbd env goals theorems passive active
1765   else
1766 (*     let ok', theorems = activate_theorem theorems in *)
1767 (*     if ok' then *)
1768 (*       let ok, goals = apply_theorem_to_goals env theorems active goals in *)
1769 (*       if ok then *)
1770 (*         let proof = *)
1771 (*           match (fst goals) with *)
1772 (*           | (_, [proof, _, _])::_ -> Some proof *)
1773 (*           | _ -> assert false *)
1774 (*         in *)
1775 (*         ParamodulationSuccess (proof, env) *)
1776 (*       else *)
1777 (*         given_clause_fullred_aux env goals theorems passive active *)
1778 (*     else *)
1779       if (passive_is_empty passive) then ParamodulationFailure
1780       else given_clause_fullred_aux dbd env goals theorems passive active
1781     
1782 and given_clause_fullred_aux dbd env goals theorems passive active =
1783   let time1 = Unix.gettimeofday () in
1784   
1785   let selection_estimate = get_selection_estimate () in
1786   let kept = size_of_passive passive in
1787   let passive =
1788     if !time_limit = 0. || !processed_clauses = 0 then
1789       passive
1790     else if !elapsed_time > !time_limit then (
1791       debug_print (lazy (Printf.sprintf "Time limit (%.2f) reached: %.2f\n"
1792                            !time_limit !elapsed_time));
1793       make_passive [] []
1794     ) else if kept > selection_estimate then (
1795       debug_print
1796         (lazy (Printf.sprintf ("Too many passive equalities: pruning..." ^^
1797                                  "(kept: %d, selection_estimate: %d)\n")
1798                  kept selection_estimate));
1799       prune_passive selection_estimate active passive
1800     ) else
1801       passive
1802   in
1803
1804   let time2 = Unix.gettimeofday () in
1805   passive_maintainance_time := !passive_maintainance_time +. (time2 -. time1);
1806     
1807   kept_clauses := (size_of_passive passive) + (size_of_active active);
1808
1809 (*   try *)
1810 (*     let ok, goals = apply_to_goals env is_passive_empty theorems active goals in *)
1811 (*     if ok then *)
1812 (*       let proof = *)
1813 (*         match goals with *)
1814 (*         | (_, [proof, _, _])::_ -> Some proof *)
1815 (*         | _ -> assert false *)
1816 (*       in *)
1817 (*       ParamodulationSuccess (proof, env) *)
1818 (*     else *)
1819 (*       let _ = *)
1820 (*         debug_print *)
1821 (*           (lazy ("new_goals: " ^ (string_of_int (List.length goals)))); *)
1822 (*         debug_print *)
1823 (*           (lazy *)
1824 (*              (String.concat "\n" *)
1825 (*                 (List.map *)
1826 (*                    (fun (d, gl) -> *)
1827 (*                       let gl' = *)
1828 (*                         List.map *)
1829 (*                           (fun (p, _, t) -> *)
1830 (*                              (\* (string_of_proof p) ^ ", " ^ *\) (CicPp.ppterm t)) gl *)
1831 (*                       in *)
1832 (*                       Printf.sprintf "%d: %s" d (String.concat "; " gl')) *)
1833 (*                    goals))); *)
1834 (*       in *)
1835   match passive_is_empty passive with
1836   | true -> (* ParamodulationFailure *)
1837       given_clause_fullred dbd env goals theorems passive active        
1838   | false ->
1839       let (sign, current), passive = select env (fst goals) passive active in
1840       let time1 = Unix.gettimeofday () in
1841       let res = forward_simplify env (sign, current) ~passive active in
1842       let time2 = Unix.gettimeofday () in
1843       forward_simpl_time := !forward_simpl_time +. (time2 -. time1);
1844       match res with
1845       | None ->
1846           given_clause_fullred dbd env goals theorems passive active
1847       | Some (sign, current) ->
1848           if (sign = Negative) && (is_identity env current) then (
1849             debug_print
1850               (lazy (Printf.sprintf "OK!!! %s %s" (string_of_sign sign)
1851                        (string_of_equality ~env current)));
1852             let _, proof, _, _, _ = current in 
1853             ParamodulationSuccess (Some proof (* current *), env)
1854           ) else (
1855             debug_print
1856               (lazy "\n================================================");
1857             debug_print (lazy (Printf.sprintf "selected: %s %s"
1858                                  (string_of_sign sign)
1859                                  (string_of_equality ~env current)));
1860
1861             let t1 = Unix.gettimeofday () in
1862             let new' = infer env sign current active in
1863             let t2 = Unix.gettimeofday () in
1864             infer_time := !infer_time +. (t2 -. t1);
1865
1866             let active =
1867               if is_identity env current then active
1868               else
1869                 let al, tbl = active in
1870                 match sign with
1871                 | Negative -> (sign, current)::al, tbl
1872                 | Positive ->
1873                     al @ [(sign, current)], Indexing.index tbl current
1874             in
1875             let rec simplify new' active passive =
1876               let t1 = Unix.gettimeofday () in
1877               let new' = forward_simplify_new env new' ~passive active in
1878               let t2 = Unix.gettimeofday () in
1879               forward_simpl_new_time :=
1880                 !forward_simpl_new_time +. (t2 -. t1);
1881               let t1 = Unix.gettimeofday () in
1882               let active, passive, newa, retained =
1883                 backward_simplify env new' ~passive active in
1884               let t2 = Unix.gettimeofday () in
1885               backward_simpl_time := !backward_simpl_time +. (t2 -. t1);
1886               match newa, retained with
1887               | None, None -> active, passive, new'
1888               | Some (n, p), None
1889               | None, Some (n, p) ->
1890                   let nn, np = new' in
1891                   simplify (nn @ n, np @ p) active passive
1892               | Some (n, p), Some (rn, rp) ->
1893                   let nn, np = new' in
1894                   simplify (nn @ n @ rn, np @ p @ rp) active passive
1895             in
1896             let active, passive, new' = simplify new' active passive in
1897
1898             let k = size_of_passive passive in
1899             if k < (kept - 1) then
1900               processed_clauses := !processed_clauses + (kept - 1 - k);
1901             
1902             let _ =
1903               debug_print
1904                 (lazy
1905                    (Printf.sprintf "active:\n%s\n"
1906                       (String.concat "\n"
1907                          ((List.map
1908                              (fun (s, e) -> (string_of_sign s) ^ " " ^
1909                                 (string_of_equality ~env e))
1910                              (fst active))))))
1911             in
1912             let _ =
1913               match new' with
1914               | neg, pos ->
1915                   debug_print
1916                     (lazy
1917                        (Printf.sprintf "new':\n%s\n"
1918                           (String.concat "\n"
1919                              ((List.map
1920                                  (fun e -> "Negative " ^
1921                                     (string_of_equality ~env e)) neg) @
1922                                 (List.map
1923                                    (fun e -> "Positive " ^
1924                                       (string_of_equality ~env e)) pos)))))
1925             in
1926             match contains_empty env new' with
1927             | false, _ -> 
1928                 let passive = add_to_passive passive new' in
1929 (*                 let (_, ns), (_, ps), _ = passive in *)
1930 (*                 Printf.printf "passive:\n%s\n" *)
1931 (*                   (String.concat "\n" *)
1932 (*                      ((List.map (fun e -> "Negative " ^ *)
1933 (*                                    (string_of_equality ~env e)) *)
1934 (*                          (EqualitySet.elements ns)) @ *)
1935 (*                         (List.map (fun e -> "Positive " ^ *)
1936 (*                                      (string_of_equality ~env e)) *)
1937 (*                            (EqualitySet.elements ps)))); *)
1938 (*                 print_newline (); *)
1939                 given_clause_fullred dbd env goals theorems passive active
1940             | true, goal ->
1941                 let proof =
1942                   match goal with
1943                   | Some goal -> let _, proof, _, _, _ = goal in Some proof
1944                   | None -> None
1945                 in
1946                 ParamodulationSuccess (proof (* goal *), env)
1947           )
1948 (*   with SearchSpaceOver -> *)
1949 (*     ParamodulationFailure *)
1950 ;;
1951
1952
1953 (* let given_clause_ref = ref given_clause;; *)
1954
1955 let main dbd full term metasenv ugraph =
1956   let module C = Cic in
1957   let module T = CicTypeChecker in
1958   let module PET = ProofEngineTypes in
1959   let module PP = CicPp in
1960   let proof = None, (1, [], term)::metasenv, C.Meta (1, []), term in
1961   let status = PET.apply_tactic (PrimitiveTactics.intros_tac ()) (proof, 1) in
1962   let proof, goals = status in
1963   let goal' = List.nth goals 0 in
1964   let _, metasenv, meta_proof, _ = proof in
1965   let _, context, goal = CicUtil.lookup_meta goal' metasenv in
1966   let eq_indexes, equalities, maxm = find_equalities context proof in
1967   let lib_eq_uris, library_equalities, maxm =
1968     find_library_equalities dbd context (proof, goal') (maxm+2)
1969   in
1970   maxmeta := maxm+2; (* TODO ugly!! *)
1971   let irl = CicMkImplicit.identity_relocation_list_for_metavariable context in
1972   let new_meta_goal, metasenv, type_of_goal =
1973     let _, context, ty = CicUtil.lookup_meta goal' metasenv in
1974     Printf.printf "\n\nTIPO DEL GOAL: %s\n" (CicPp.ppterm ty);
1975     print_newline ();
1976     Cic.Meta (maxm+1, irl),
1977     (maxm+1, context, ty)::metasenv,
1978     ty
1979   in
1980 (*   let new_meta_goal = Cic.Meta (goal', irl) in *)
1981   let env = (metasenv, context, ugraph) in
1982   let theorems =
1983     if full then
1984       let theorems = find_library_theorems dbd env (proof, goal') lib_eq_uris in
1985       let context_hyp = find_context_hypotheses env eq_indexes in
1986       context_hyp, theorems
1987     else
1988       let refl_equal =
1989         let us = UriManager.string_of_uri (LibraryObjects.eq_URI ()) in
1990         UriManager.uri_of_string (us ^ "#xpointer(1/1/1)")
1991       in
1992       let t = CicUtil.term_of_uri refl_equal in
1993       let ty, _ = CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in
1994       [], [(refl_equal, t, ty, [])]
1995   in
1996   let _ =
1997     debug_print
1998       (lazy
1999          (Printf.sprintf
2000             "Theorems:\n-------------------------------------\n%s\n"
2001             (String.concat "\n"
2002                (List.map
2003                   (fun (_, t, ty, _) ->
2004                      Printf.sprintf
2005                        "Term: %s, type: %s" (CicPp.ppterm t) (CicPp.ppterm ty))
2006                   (snd theorems)))))
2007   in
2008   try
2009     let goal = Inference.BasicProof new_meta_goal, [], goal in
2010 (*     let term_equality = equality_of_term new_meta_goal goal in *)
2011 (*     let _, meta_proof, (eq_ty, left, right, ordering), _, _ = term_equality in *)
2012 (*     if is_identity env term_equality then *)
2013 (*       let proof = *)
2014 (*         Cic.Appl [Cic.MutConstruct (\* reflexivity *\) *)
2015 (*                     (HelmLibraryObjects.Logic.eq_URI, 0, 1, []); *)
2016 (*                   eq_ty; left] *)
2017 (*       in *)
2018 (*       let _ =  *)
2019 (*         Printf.printf "OK, found a proof!\n"; *)
2020 (*         let names = names_of_context context in *)
2021 (*         print_endline (PP.pp proof names) *)
2022 (*       in *)
2023 (*       () *)
2024 (*     else *)
2025       let equalities =
2026         let equalities = equalities @ library_equalities in
2027         debug_print
2028           (lazy 
2029              (Printf.sprintf "equalities:\n%s\n"
2030                 (String.concat "\n"
2031                    (List.map string_of_equality equalities))));
2032         debug_print (lazy "SIMPLYFYING EQUALITIES...");
2033         let rec simpl e others others_simpl =
2034           let active = others @ others_simpl in
2035           let tbl =
2036             List.fold_left
2037               (fun t (_, e) -> Indexing.index t e)
2038               (Indexing.empty_table ()) active
2039           in
2040           let res = forward_simplify env e (active, tbl) in
2041           match others with
2042           | hd::tl -> (
2043               match res with
2044               | None -> simpl hd tl others_simpl
2045               | Some e -> simpl hd tl (e::others_simpl)
2046             )
2047           | [] -> (
2048               match res with
2049               | None -> others_simpl
2050               | Some e -> e::others_simpl
2051             )
2052         in
2053         match equalities with
2054         | [] -> []
2055         | hd::tl ->
2056             let others = List.map (fun e -> (Positive, e)) tl in
2057             let res =
2058               List.rev (List.map snd (simpl (Positive, hd) others []))
2059             in
2060             debug_print
2061               (lazy
2062                  (Printf.sprintf "equalities AFTER:\n%s\n"
2063                     (String.concat "\n"
2064                        (List.map string_of_equality res))));
2065             res
2066       in
2067       let active = make_active () in
2068       let passive = make_passive [] (* [term_equality] *) equalities in
2069       Printf.printf "\ncurrent goal: %s\n"
2070         (let _, _, g = goal in CicPp.ppterm g);
2071 (*         (string_of_equality ~env term_equality); *)
2072       Printf.printf "\ncontext:\n%s\n" (PP.ppcontext context);
2073       Printf.printf "\nmetasenv:\n%s\n" (print_metasenv metasenv);
2074       Printf.printf "\nequalities:\n%s\n"
2075         (String.concat "\n"
2076            (List.map
2077               (string_of_equality ~env)
2078               (equalities @ library_equalities)));
2079       print_endline "--------------------------------------------------";
2080       let start = Unix.gettimeofday () in
2081       print_endline "GO!";
2082       start_time := Unix.gettimeofday ();
2083 (*       let res = *)
2084 (*         (if !use_fullred then given_clause_fullred else given_clause) *)
2085 (*           env [0, [goal]] theorems passive active *)
2086 (*       in *)
2087       let res =
2088         let goals = make_goals goal in
2089 (*         and theorems = make_theorems theorems in *)
2090         (if !use_fullred then given_clause_fullred else given_clause)
2091           dbd env goals theorems passive active
2092       in
2093       let finish = Unix.gettimeofday () in
2094       let _ =
2095         match res with
2096         | ParamodulationFailure ->
2097             Printf.printf "NO proof found! :-(\n\n"
2098         | ParamodulationSuccess (Some proof (* goal *), env) ->
2099 (*             let proof = Inference.build_proof_term goal in          *)
2100             let proof = Inference.build_proof_term proof in
2101             Printf.printf "OK, found a proof!\n";
2102             (* REMEMBER: we have to instantiate meta_proof, we should use
2103                apply  the "apply" tactic to proof and status 
2104             *)
2105             let names = names_of_context context in
2106             print_endline (PP.pp proof names);
2107             let newmetasenv =
2108               List.fold_left
2109                 (fun m (_, _, _, menv, _) -> m @ menv) metasenv equalities
2110             in
2111             let _ =
2112 (*               Printf.printf "OK, found a proof!\n"; *)
2113 (*               (\* REMEMBER: we have to instantiate meta_proof, we should use *)
2114 (*                  apply  the "apply" tactic to proof and status  *)
2115 (*               *\) *)
2116 (*               let names = names_of_context context in *)
2117 (*               print_endline (PP.pp proof names); *)
2118               try
2119                 let ty, ug =
2120                   CicTypeChecker.type_of_aux' newmetasenv context proof ugraph
2121                 in
2122 (*                 Printf.printf "OK, found a proof!\n"; *)
2123 (*                 (\* REMEMBER: we have to instantiate meta_proof, we should use *)
2124 (*                    apply  the "apply" tactic to proof and status  *)
2125 (*                 *\) *)
2126 (*                 let names = names_of_context context in *)
2127 (*                 print_endline (PP.pp proof names); *)
2128                 (*           print_endline (PP.ppterm proof); *)
2129                 
2130                 print_endline (string_of_float (finish -. start));
2131                 Printf.printf
2132                   "\nGOAL was: %s\nPROOF has type: %s\nconvertible?: %s\n\n"
2133                   (CicPp.pp type_of_goal names) (CicPp.pp ty names)
2134                   (string_of_bool
2135                      (fst (CicReduction.are_convertible
2136                              context type_of_goal ty ug)));
2137               with e ->
2138                 Printf.printf "\nEXCEPTION!!! %s\n" (Printexc.to_string e);
2139                 Printf.printf "MAXMETA USED: %d\n" !maxmeta;
2140                 print_endline (string_of_float (finish -. start));
2141             in
2142             ()
2143               
2144         | ParamodulationSuccess (None, env) ->
2145             Printf.printf "Success, but no proof?!?\n\n"
2146       in
2147       Printf.printf ("infer_time: %.9f\nforward_simpl_time: %.9f\n" ^^
2148                        "forward_simpl_new_time: %.9f\n" ^^
2149                        "backward_simpl_time: %.9f\n")
2150         !infer_time !forward_simpl_time !forward_simpl_new_time
2151         !backward_simpl_time;
2152       Printf.printf "passive_maintainance_time: %.9f\n"
2153         !passive_maintainance_time;
2154       Printf.printf "    successful unification/matching time: %.9f\n"
2155         !Indexing.match_unif_time_ok;
2156       Printf.printf "    failed unification/matching time: %.9f\n"
2157         !Indexing.match_unif_time_no;
2158       Printf.printf "    indexing retrieval time: %.9f\n"
2159         !Indexing.indexing_retrieval_time;
2160       Printf.printf "    demodulate_term.build_newtarget_time: %.9f\n"
2161         !Indexing.build_newtarget_time;
2162       Printf.printf "derived %d clauses, kept %d clauses.\n"
2163         !derived_clauses !kept_clauses;
2164   with exc ->
2165     print_endline ("EXCEPTION: " ^ (Printexc.to_string exc));
2166     raise exc
2167 ;;
2168
2169
2170 let default_depth = !maxdepth
2171 and default_width = !maxwidth;;
2172
2173 let reset_refs () =
2174   maxmeta := 0;
2175   symbols_counter := 0;
2176   weight_age_counter := !weight_age_ratio;
2177   processed_clauses := 0;
2178   start_time := 0.;
2179   elapsed_time := 0.;
2180   maximal_retained_equality := None;
2181   infer_time := 0.;
2182   forward_simpl_time := 0.;
2183   forward_simpl_new_time := 0.;
2184   backward_simpl_time := 0.;
2185   passive_maintainance_time := 0.;
2186   derived_clauses := 0;
2187   kept_clauses := 0;
2188 ;;
2189
2190 let saturate
2191     dbd ?(full=false) ?(depth=default_depth) ?(width=default_width) status = 
2192   let module C = Cic in
2193   reset_refs ();
2194   Indexing.init_index ();
2195   maxdepth := depth;
2196   maxwidth := width;
2197   let proof, goal = status in
2198   let goal' = goal in
2199   let uri, metasenv, meta_proof, term_to_prove = proof in
2200   let _, context, goal = CicUtil.lookup_meta goal' metasenv in
2201   let eq_indexes, equalities, maxm = find_equalities context proof in
2202   let new_meta_goal, metasenv, type_of_goal =
2203     let irl =
2204       CicMkImplicit.identity_relocation_list_for_metavariable context in
2205     let _, context, ty = CicUtil.lookup_meta goal' metasenv in
2206     debug_print
2207       (lazy (Printf.sprintf "\n\nTIPO DEL GOAL: %s\n" (CicPp.ppterm ty)));
2208     Cic.Meta (maxm+1, irl),
2209     (maxm+1, context, ty)::metasenv,
2210     ty
2211   in
2212   let ugraph = CicUniv.empty_ugraph in
2213   let env = (metasenv, context, ugraph) in
2214   let goal = Inference.BasicProof new_meta_goal, [], goal in
2215   let res, time = 
2216     let lib_eq_uris, library_equalities, maxm =
2217       find_library_equalities dbd context (proof, goal') (maxm+2)
2218     in
2219     maxmeta := maxm+2;
2220     let equalities =
2221       let equalities = equalities @ library_equalities in
2222       debug_print
2223         (lazy
2224            (Printf.sprintf "equalities:\n%s\n"
2225               (String.concat "\n"
2226                  (List.map string_of_equality equalities))));
2227       debug_print (lazy "SIMPLYFYING EQUALITIES...");
2228       let rec simpl e others others_simpl =
2229         let active = others @ others_simpl in
2230         let tbl =
2231           List.fold_left
2232             (fun t (_, e) -> Indexing.index t e)
2233             (Indexing.empty_table ()) active
2234         in
2235         let res = forward_simplify env e (active, tbl) in
2236         match others with
2237         | hd::tl -> (
2238             match res with
2239             | None -> simpl hd tl others_simpl
2240             | Some e -> simpl hd tl (e::others_simpl)
2241           )
2242         | [] -> (
2243             match res with
2244             | None -> others_simpl
2245             | Some e -> e::others_simpl
2246           )
2247       in
2248       match equalities with
2249       | [] -> []
2250       | hd::tl ->
2251           let others = List.map (fun e -> (Positive, e)) tl in
2252           let res =
2253             List.rev (List.map snd (simpl (Positive, hd) others []))
2254           in
2255           debug_print
2256             (lazy
2257                (Printf.sprintf "equalities AFTER:\n%s\n"
2258                   (String.concat "\n"
2259                      (List.map string_of_equality res))));
2260           res
2261     in
2262     let theorems =
2263       if full then
2264 (*         let refl_eq = *)
2265 (*           let u = eq_XURI () in *)
2266 (*           let t = CicUtil.term_of_uri u in *)
2267 (*           let ty, _ = *)
2268 (*             CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in *)
2269 (*           (t, ty, []) *)
2270 (*         in *)
2271 (*         let le_S = *)
2272 (*           let u = UriManager.uri_of_string *)
2273 (*             "cic:/matita/nat/orders/le.ind#xpointer(1/1/2)" in *)
2274 (*           let t = CicUtil.term_of_uri u in *)
2275 (*           let ty, _ = *)
2276 (*             CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in *)
2277 (*           (t, ty, []) *)
2278 (*         in *)
2279 (*         let thms = refl_eq::le_S::[] in *)
2280           let thms = find_library_theorems dbd env (proof, goal') lib_eq_uris in
2281         let context_hyp = find_context_hypotheses env eq_indexes in
2282 (*         context_hyp @ thms *)
2283         (context_hyp, thms)
2284       else
2285         let refl_equal =
2286           let us = UriManager.string_of_uri (LibraryObjects.eq_URI ()) in
2287           UriManager.uri_of_string (us ^ "#xpointer(1/1/1)")
2288         in
2289         let t = CicUtil.term_of_uri refl_equal in
2290         let ty, _ = CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in
2291         [], [(refl_equal, t, ty, [])]
2292     in
2293     let _ =
2294       debug_print
2295         (lazy
2296            (Printf.sprintf
2297               "Theorems:\n-------------------------------------\n%s\n"
2298               (String.concat "\n"
2299                  (List.map
2300                     (fun (_, t, ty, _) ->
2301                        Printf.sprintf
2302                          "Term: %s, type: %s"
2303                          (CicPp.ppterm t) (CicPp.ppterm ty))
2304                     (snd theorems)))))
2305     in
2306     let active = make_active () in
2307     let passive = make_passive [(* term_equality *)] equalities in
2308     let start = Unix.gettimeofday () in
2309 (*     let res = given_clause_fullred env [0, [goal]] theorems passive active in *)
2310     let res =
2311       let goals = make_goals goal in
2312 (*       and theorems = make_theorems theorems in *)
2313         given_clause_fullred dbd env goals theorems passive active
2314     in
2315     let finish = Unix.gettimeofday () in
2316     (res, finish -. start)
2317   in
2318   match res with
2319   | ParamodulationSuccess (Some proof (* goal *), env) ->
2320       debug_print (lazy "OK, found a proof!");
2321 (*       let proof = Inference.build_proof_term goal in          *)
2322       let proof = Inference.build_proof_term proof in
2323       let names = names_of_context context in
2324       let newmetasenv =
2325         let i1 =
2326           match new_meta_goal with
2327           | C.Meta (i, _) -> i | _ -> assert false
2328         in
2329         List.filter (fun (i, _, _) -> i <> i1 && i <> goal') metasenv
2330       in
2331       let newstatus =
2332         try
2333           let ty, ug =
2334             CicTypeChecker.type_of_aux' newmetasenv context proof ugraph
2335           in
2336           debug_print (lazy (CicPp.pp proof [](* names *)));
2337           debug_print
2338             (lazy
2339                (Printf.sprintf
2340                   "\nGOAL was: %s\nPROOF has type: %s\nconvertible?: %s\n"
2341                   (CicPp.pp type_of_goal names) (CicPp.pp ty names)
2342                   (string_of_bool
2343                      (fst (CicReduction.are_convertible
2344                              context type_of_goal ty ug)))));
2345           let equality_for_replace i t1 =
2346             match t1 with
2347             | C.Meta (n, _) -> n = i
2348             | _ -> false
2349           in
2350           let real_proof =
2351             ProofEngineReduction.replace
2352               ~equality:equality_for_replace
2353               ~what:[goal'] ~with_what:[proof]
2354               ~where:meta_proof
2355           in
2356           debug_print
2357             (lazy
2358                (Printf.sprintf "status:\n%s\n%s\n%s\n%s\n"
2359                   (match uri with Some uri -> UriManager.string_of_uri uri
2360                    | None -> "")
2361                   (print_metasenv newmetasenv)
2362                   (CicPp.pp real_proof [](* names *))
2363                   (CicPp.pp term_to_prove names)));
2364           ((uri, newmetasenv, real_proof, term_to_prove), [])
2365         with CicTypeChecker.TypeCheckerFailure _ ->
2366           debug_print (lazy "THE PROOF DOESN'T TYPECHECK!!!");
2367           debug_print (lazy (CicPp.pp proof names));
2368           raise (ProofEngineTypes.Fail
2369                    "Found a proof, but it doesn't typecheck")
2370       in
2371       debug_print (lazy (Printf.sprintf "\nTIME NEEDED: %.9f" time));
2372       newstatus          
2373   | _ ->
2374       raise (ProofEngineTypes.Fail "NO proof found")
2375 ;;
2376
2377 (* dummy function called within matita to trigger linkage *)
2378 let init () = ();;
2379
2380
2381 (* UGLY SIDE EFFECT... *)
2382 if connect_to_auto then ( 
2383   AutoTactic.paramodulation_tactic := saturate;
2384   AutoTactic.term_is_equality := Inference.term_is_equality;
2385 );;
2386