]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/tactics/paramodulation/saturation.ml
fix for distro
[helm.git] / helm / software / components / tactics / paramodulation / saturation.ml
1 (* Copyright (C) 2005, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://cs.unibo.it/helm/.
24  *)
25
26 (* $Id$ *)
27
28 open Inference;;
29 open Utils;;
30
31 let check_table t l =
32   List.fold_left
33     (fun b (_,eq) -> b && (Indexing.in_index t eq)) true l
34
35
36 (* set to false to disable paramodulation inside auto_tac *)
37 let connect_to_auto = true;;
38
39
40 (* profiling statistics... *)
41 let infer_time = ref 0.;;
42 let forward_simpl_time = ref 0.;;
43 let forward_simpl_new_time = ref 0.;;
44 let backward_simpl_time = ref 0.;;
45 let passive_maintainance_time = ref 0.;;
46
47 (* limited-resource-strategy related globals *)
48 let processed_clauses = ref 0;; (* number of equalities selected so far... *)
49 let time_limit = ref 0.;; (* in seconds, settable by the user... *)
50 let start_time = ref 0.;; (* time at which the execution started *)
51 let elapsed_time = ref 0.;;
52 (* let maximal_weight = ref None;; *)
53 let maximal_retained_equality = ref None;;
54
55 (* equality-selection related globals *)
56 let use_fullred = ref true;;
57 let weight_age_ratio = ref 4 (* 5 *);; (* settable by the user *)
58 let weight_age_counter = ref !weight_age_ratio ;;
59 let symbols_ratio = ref 0 (* 3 *);;
60 let symbols_counter = ref 0;;
61
62 (* non-recursive Knuth-Bendix term ordering by default *)
63 (* Utils.compare_terms := Utils.rpo;; *)
64 (* Utils.compare_terms := Utils.nonrec_kbo;; *)
65 (* Utils.compare_terms := Utils.ao;; *)
66
67 (* statistics... *)
68 let derived_clauses = ref 0;;
69 let kept_clauses = ref 0;;
70
71 (* index of the greatest Cic.Meta created - TODO: find a better way! *)
72 let maxmeta = ref 0;;
73
74 (* varbiables controlling the search-space *)
75 let maxdepth = ref 3;;
76 let maxwidth = ref 3;;
77
78 let test eq = false
79 (*
80   let (_,(_,_,(ty,left,right,_),m1)) = eq in
81   let actual = 
82     (Inference.metas_of_term left)@(Inference.metas_of_term right) 
83   in
84   let m = List.filter (fun (i, _, _) -> List.mem i actual) m1 in
85     m <> m1
86 ;; *)
87
88 type result =
89   | ParamodulationFailure
90   | ParamodulationSuccess of (Inference.proof * Cic.metasenv) option
91 ;;
92
93 type goal = proof * Cic.metasenv * Cic.term;;
94
95 type theorem = Cic.term * Cic.term * Cic.metasenv;;
96
97 let symbols_of_equality (_, _, (_, left, right, _), _) =
98   let m1 = symbols_of_term left in
99   let m = 
100     TermMap.fold
101       (fun k v res ->
102          try
103            let c = TermMap.find k res in
104            TermMap.add k (c+v) res
105          with Not_found ->
106            TermMap.add k v res)
107       (symbols_of_term right) m1
108   in
109   m
110 ;;
111
112 (* griggio *)
113 module OrderedEquality = struct 
114   type t = Inference.equality
115
116   let compare eq1 eq2 =
117     match meta_convertibility_eq eq1 eq2 with
118     | true -> 0
119     | false ->
120         let w1, _, (ty, left, right, _), m1 = eq1
121         and w2, _, (ty', left', right', _), m2 = eq2 in
122         match Pervasives.compare w1 w2 with
123         | 0 -> 
124             let res = (List.length m1) - (List.length m2) in 
125             if res <> 0 then res else Pervasives.compare eq1 eq2
126         | res -> res 
127 end 
128
129 (*
130 module OrderedEquality = struct
131   type t = Inference.equality
132
133   let minor eq =
134     let w, _, (ty, left, right, o), _ = eq in
135       match o with
136          | Lt -> Some left
137          | Le -> assert false
138          | Gt -> Some right
139          | Ge -> assert false
140          | Eq 
141          | Incomparable -> None
142              
143   let compare eq1 eq2 =
144     let w1, _, (ty, left, right, o1), m1 = eq1
145     and w2, _, (ty', left', right', o2), m2 = eq2 in
146       match Pervasives.compare w1 w2 with
147         | 0 ->
148             (match minor eq1, minor eq2 with
149               | Some t1, Some t2 ->
150                   fst (Utils.weight_of_term t1) - fst (Utils.weight_of_term t2)
151               | Some _, None -> -1
152               | None, Some _ -> 1
153               | _,_ -> 
154                   (List.length m2) - (List.length m1) )
155         | res ->  res
156   
157   let compare eq1 eq2 =
158     match compare eq1 eq2 with
159         0 -> Pervasives.compare eq1 eq2
160       | res -> res 
161 end 
162 *)
163
164 module EqualitySet = Set.Make(OrderedEquality);;
165
166 exception Empty_list;;
167
168 let passive_is_empty = function
169   | ([], _), ([], _), _ -> true
170   | _ -> false
171 ;;
172
173
174 let size_of_passive ((_, ns), (_, ps), _) =
175   (EqualitySet.cardinal ns) + (EqualitySet.cardinal ps)
176 ;;
177
178
179 let size_of_active (active_list, _) =
180   List.length active_list
181 ;;
182
183 let age_factor = 0.01;;
184
185 let min_elt weight l =
186   fst
187   (match l with
188       [] -> raise Empty_list
189     | a::tl -> 
190         let wa = float_of_int (weight a) in
191         let x = ref 0. in
192         List.fold_left
193           (fun (current,w) arg ->
194             x:=!x +. 1.;
195             let w1 = weight arg in
196             let wa = (float_of_int w1) +. !x *. age_factor in
197             if wa < w then (arg,wa) else (current,w))
198           (a,wa) tl)
199 ;;
200
201 (* 
202 let compare eq1 eq2 =
203   let w1, _, (ty, left, right, _), m1, _ = eq1 in
204   let w2, _, (ty', left', right', _), m2, _ = eq2 in
205   match Pervasives.compare w1 w2 with
206     | 0 -> (List.length m1) - (List.length m2)
207     | res -> res
208 ;;
209 *)
210
211 (**
212    selects one equality from passive. The selection strategy is a combination
213    of weight, age and goal-similarity
214 *)
215 let rec select env goals passive (active, _) =
216   processed_clauses := !processed_clauses + 1;
217   let goal =
218     match (List.rev goals) with (_, goal::_)::_ -> goal | _ -> assert false
219   in
220   let (neg_list, neg_set), (pos_list, pos_set), passive_table = passive in
221   let remove eq l =
222     List.filter (fun e -> e <> eq) l
223   in
224   if !weight_age_ratio > 0 then
225     weight_age_counter := !weight_age_counter - 1;
226   match !weight_age_counter with
227   | 0 -> (
228       weight_age_counter := !weight_age_ratio;
229       match neg_list, pos_list with
230       | hd::tl, pos ->
231           (* Negatives aren't indexed, no need to remove them... *)
232           (Negative, hd),
233           ((tl, EqualitySet.remove hd neg_set), (pos, pos_set), passive_table)
234       | [], (hd:EqualitySet.elt)::tl ->
235           let passive_table =
236             Indexing.remove_index passive_table hd
237           in  (Positive, hd),
238           (([], neg_set), (tl, EqualitySet.remove hd pos_set), passive_table)
239       | _, _ -> assert false
240     )
241   | _ when (!symbols_counter > 0) && (EqualitySet.is_empty neg_set) -> 
242      (symbols_counter := !symbols_counter - 1;
243       let cardinality map =
244         TermMap.fold (fun k v res -> res + v) map 0
245       in
246       let symbols =
247         let _, _, term = goal in
248         symbols_of_term term
249       in
250       let card = cardinality symbols in
251       let foldfun k v (r1, r2) = 
252         if TermMap.mem k symbols then
253           let c = TermMap.find k symbols in
254           let c1 = abs (c - v) in
255           let c2 = v - c1 in
256           r1 + c2, r2 + c1
257         else
258           r1, r2 + v
259       in
260       let f equality (i, e) =
261         let common, others =
262           TermMap.fold foldfun (symbols_of_equality equality) (0, 0)
263         in
264         let c = others + (abs (common - card)) in
265         if c < i then (c, equality)
266         else (i, e)
267       in
268       let e1 = EqualitySet.min_elt pos_set in
269       let initial =
270         let common, others = 
271           TermMap.fold foldfun (symbols_of_equality e1) (0, 0)
272         in
273         (others + (abs (common - card))), e1
274       in
275       let _, current = EqualitySet.fold f pos_set initial in
276       let passive_table =
277         Indexing.remove_index passive_table current
278       in
279       (Positive, current),
280       (([], neg_set),
281        (remove current pos_list, EqualitySet.remove current pos_set),
282        passive_table)
283     )
284   | _ ->
285       symbols_counter := !symbols_ratio;
286       let set_selection set = EqualitySet.min_elt set in 
287       (* let set_selection l = min_elt (fun (w,_,_,_) -> w) l in *)
288       if EqualitySet.is_empty neg_set then
289         let current = set_selection pos_set in
290         let passive =
291           (neg_list, neg_set),
292           (remove current pos_list, EqualitySet.remove current pos_set),
293           Indexing.remove_index passive_table current
294         in
295         (Positive, current), passive
296       else
297         let current = set_selection neg_set in
298         let passive =
299           (remove current neg_list, EqualitySet.remove current neg_set),
300           (pos_list, pos_set),
301           passive_table
302         in
303         (Negative, current), passive
304 ;;
305
306
307 (* initializes the passive set of equalities *)
308 let make_passive neg pos =
309   let set_of equalities =
310     List.fold_left (fun s e -> EqualitySet.add e s) EqualitySet.empty equalities
311   in
312   let table =
313       List.fold_left (fun tbl e -> Indexing.index tbl e) Indexing.empty pos
314   in
315   (neg, set_of neg),
316   (pos, set_of pos),
317   table
318 ;;
319
320
321 let make_active () =
322   [], Indexing.empty
323 ;;
324
325
326 (* adds to passive a list of equalities: new_neg is a list of negative
327    equalities, new_pos a list of positive equalities *)
328 let add_to_passive passive (new_neg, new_pos) =
329   let (neg_list, neg_set), (pos_list, pos_set), table = passive in
330   let ok set equality = not (EqualitySet.mem equality set) in
331   let neg = List.filter (ok neg_set) new_neg
332   and pos = List.filter (ok pos_set) new_pos in
333   let table = 
334      List.fold_left (fun tbl e -> Indexing.index tbl e) table pos 
335   in
336   let add set equalities =
337     List.fold_left (fun s e -> EqualitySet.add e s) set equalities
338   in
339   (neg @ neg_list, add neg_set neg),
340   (pos_list @ pos, add pos_set pos),
341   table
342 ;;
343
344
345 (* removes from passive equalities that are estimated impossible to activate
346    within the current time limit *)
347 let prune_passive howmany (active, _) passive =
348   let (nl, ns), (pl, ps), tbl = passive in
349   let howmany = float_of_int howmany
350   and ratio = float_of_int !weight_age_ratio in
351   let round v =
352     let t = ceil v in 
353     int_of_float (if t -. v < 0.5 then t else v)
354   in
355   let in_weight = round (howmany *. ratio /. (ratio +. 1.))
356   and in_age = round (howmany /. (ratio +. 1.)) in 
357   debug_print
358     (lazy (Printf.sprintf "in_weight: %d, in_age: %d\n" in_weight in_age));
359   let symbols, card =
360     match active with
361     | (Negative, e)::_ ->
362         let symbols = symbols_of_equality e in
363         let card = TermMap.fold (fun k v res -> res + v) symbols 0 in
364         Some symbols, card
365     | _ -> None, 0
366   in
367   let counter = ref !symbols_ratio in
368   let rec pickw w ns ps =
369     if w > 0 then
370       if not (EqualitySet.is_empty ns) then
371         let e = EqualitySet.min_elt ns in
372         let ns', ps = pickw (w-1) (EqualitySet.remove e ns) ps in
373         EqualitySet.add e ns', ps
374       else if !counter > 0 then
375         let _ =
376           counter := !counter - 1;
377           if !counter = 0 then counter := !symbols_ratio
378         in
379         match symbols with
380         | None ->
381             let e = EqualitySet.min_elt ps in
382             let ns, ps' = pickw (w-1) ns (EqualitySet.remove e ps) in
383             ns, EqualitySet.add e ps'
384         | Some symbols ->
385             let foldfun k v (r1, r2) =
386               if TermMap.mem k symbols then
387                 let c = TermMap.find k symbols in
388                 let c1 = abs (c - v) in
389                 let c2 = v - c1 in
390                 r1 + c2, r2 + c1
391               else
392                 r1, r2 + v
393             in
394             let f equality (i, e) =
395               let common, others =
396                 TermMap.fold foldfun (symbols_of_equality equality) (0, 0)
397               in
398               let c = others + (abs (common - card)) in
399               if c < i then (c, equality)
400               else (i, e)
401             in
402             let e1 = EqualitySet.min_elt ps in
403             let initial =
404               let common, others = 
405                 TermMap.fold foldfun (symbols_of_equality e1) (0, 0)
406               in
407               (others + (abs (common - card))), e1
408             in
409             let _, e = EqualitySet.fold f ps initial in
410             let ns, ps' = pickw (w-1) ns (EqualitySet.remove e ps) in
411             ns, EqualitySet.add e ps'
412       else
413         let e = EqualitySet.min_elt ps in
414         let ns, ps' = pickw (w-1) ns (EqualitySet.remove e ps) in
415         ns, EqualitySet.add e ps'        
416     else
417       EqualitySet.empty, EqualitySet.empty
418   in
419   let ns, ps = pickw in_weight ns ps in
420   let rec picka w s l =
421     if w > 0 then
422       match l with
423       | [] -> w, s, []
424       | hd::tl when not (EqualitySet.mem hd s) ->
425           let w, s, l = picka (w-1) s tl in
426           w, EqualitySet.add hd s, hd::l
427       | hd::tl ->
428           let w, s, l = picka w s tl in
429           w, s, hd::l
430     else
431       0, s, l
432   in
433   let in_age, ns, nl = picka in_age ns nl in
434   let _, ps, pl = picka in_age ps pl in
435   if not (EqualitySet.is_empty ps) then
436     maximal_retained_equality := Some (EqualitySet.max_elt ps); 
437   let tbl =
438     EqualitySet.fold
439       (fun e tbl -> Indexing.index tbl e) ps Indexing.empty
440   in
441   (nl, ns), (pl, ps), tbl  
442 ;;
443
444
445 (** inference of new equalities between current and some in active *)
446 let infer env sign current (active_list, active_table) =
447   let (_,c,_) = env in 
448   if Utils.debug_metas then
449     (ignore(Indexing.check_target c current "infer1");
450      ignore(List.map (function (_,current) -> Indexing.check_target c current "infer2") active_list)); 
451   let new_neg, new_pos = 
452     match sign with
453     | Negative ->
454         let maxm, res = 
455           Indexing.superposition_left !maxmeta env active_table current in
456           if Utils.debug_metas then
457             ignore(List.map 
458                      (function current -> 
459                         Indexing.check_target c current "sup-1") res);
460         maxmeta := maxm;
461         res, [] 
462     | Positive ->
463         let maxm, res =
464           Indexing.superposition_right !maxmeta env active_table current in
465           if Utils.debug_metas then
466             ignore(List.map 
467                      (function current -> 
468                         Indexing.check_target c current "sup0") res);
469           maxmeta := maxm;
470         let rec infer_positive table = function
471           | [] -> [], []
472           | (Negative, equality)::tl ->
473               let maxm, res =
474                 Indexing.superposition_left !maxmeta env table equality in
475               maxmeta := maxm;
476               if Utils.debug_metas then 
477                 ignore(List.map 
478                          (function current -> 
479                             Indexing.check_target c current "supl") res);
480               let neg, pos = infer_positive table tl in
481               res @ neg, pos
482           | (Positive, equality)::tl ->
483               let maxm, res =
484                 Indexing.superposition_right !maxmeta env table equality in
485               maxmeta := maxm;
486                 if Utils.debug_metas then
487                   ignore
488                     (List.map 
489                        (function current -> 
490                           Indexing.check_target c current "sup2") res);
491               let neg, pos = infer_positive table tl in
492               neg, res @ pos
493         in
494         let maxm, copy_of_current = Inference.fix_metas !maxmeta current in
495         maxmeta := maxm;
496         let curr_table = Indexing.index Indexing.empty current in
497         let neg, pos = 
498           infer_positive curr_table ((sign,copy_of_current)::active_list) 
499         in
500           if Utils.debug_metas then 
501             ignore(List.map 
502                      (function current -> 
503                         Indexing.check_target c current "sup3") pos);
504         neg, res @ pos
505   in
506   derived_clauses := !derived_clauses + (List.length new_neg) +
507     (List.length new_pos);
508   match !maximal_retained_equality with
509   | None -> 
510       if Utils.debug_metas then 
511         (ignore(List.map 
512                  (function current -> 
513                     Indexing.check_target c current "sup4") new_pos);
514         ignore(List.map 
515                  (function current -> 
516                     Indexing.check_target c current "sup5") new_neg));
517       new_neg, new_pos
518   | Some eq ->
519       ignore(assert false);
520       (* if we have a maximal_retained_equality, we can discard all equalities
521          "greater" than it, as they will never be reached...  An equality is
522          greater than maximal_retained_equality if it is bigger
523          wrt. OrderedEquality.compare and it is less similar than
524          maximal_retained_equality to the current goal *)
525       let symbols, card =
526         match active_list with
527         | (Negative, e)::_ ->
528             let symbols = symbols_of_equality e in
529             let card = TermMap.fold (fun k v res -> res + v) symbols 0 in
530             Some symbols, card
531         | _ -> None, 0
532       in
533       let new_pos = 
534         match symbols with
535         | None ->
536             List.filter (fun e -> OrderedEquality.compare e eq <= 0) new_pos
537         | Some symbols ->
538             let filterfun e =
539               if OrderedEquality.compare e eq <= 0 then
540                 true
541               else
542                 let foldfun k v (r1, r2) =
543                   if TermMap.mem k symbols then
544                     let c = TermMap.find k symbols in
545                     let c1 = abs (c - v) in
546                     let c2 = v - c1 in
547                     r1 + c2, r2 + c1
548                   else
549                     r1, r2 + v
550                 in
551                 let initial =
552                   let common, others =
553                     TermMap.fold foldfun (symbols_of_equality eq) (0, 0) in
554                   others + (abs (common - card))
555                 in
556                 let common, others =
557                   TermMap.fold foldfun (symbols_of_equality e) (0, 0) in
558                 let c = others + (abs (common - card)) in
559                 if c < initial then true else false 
560             in
561             List.filter filterfun new_pos
562       in
563         new_neg, new_pos
564 ;;
565
566
567 let contains_empty env (negative, positive) =
568   let metasenv, context, ugraph = env in
569   try
570     let found =
571       List.find
572         (fun (w, proof, (ty, left, right, ordering), m) ->
573            fst (CicReduction.are_convertible context left right ugraph))
574         negative
575     in
576     true, Some found
577   with Not_found ->
578     false, None
579 ;;
580
581
582 (** simplifies current using active and passive *)
583 let forward_simplify env (sign, current) ?passive (active_list, active_table) =
584   let _, context, _ = env in
585   let pl, passive_table =
586     match passive with
587     | None -> [], None
588     | Some ((pn, _), (pp, _), pt) ->
589         let pn = List.map (fun e -> (Negative, e)) pn
590         and pp = List.map (fun e -> (Positive, e)) pp in
591         pn @ pp, Some pt
592   in
593   let all =  if pl = [] then active_list else active_list @ pl in 
594   
595   let demodulate table current = 
596     let newmeta, newcurrent =
597       Indexing.demodulation_equality !maxmeta env table sign current in
598     maxmeta := newmeta;
599     if is_identity env newcurrent then
600       if sign = Negative then Some (sign, newcurrent)
601       else (
602 (*         debug_print  *)
603 (*           (lazy *)
604 (*              (Printf.sprintf "\ncurrent was: %s\nnewcurrent is: %s\n" *)
605 (*                 (string_of_equality current) *)
606 (*                 (string_of_equality newcurrent))); *)
607 (*         debug_print *)
608 (*           (lazy *)
609 (*              (Printf.sprintf "active is: %s" *)
610 (*                 (String.concat "\n"  *)
611 (*                    (List.map (fun (_, e) -> (string_of_equality e)) active_list)))); *)
612         None
613       )
614     else
615       Some (sign, newcurrent)
616   in
617   let rec demod current =
618     if Utils.debug_metas then
619       ignore (Indexing.check_target context current "demod0");
620     let res = demodulate active_table current in
621       if Utils.debug_metas then
622         ignore ((function None -> () | Some (_,x) -> 
623                    ignore (Indexing.check_target context x "demod1");()) res);
624     match res with
625     | None -> None
626     | Some (sign, newcurrent) ->
627         match passive_table with
628         | None -> res
629         | Some passive_table -> 
630             match demodulate passive_table newcurrent with
631               | None -> None
632               | Some (sign,newnewcurrent) -> 
633                   if newcurrent <> newnewcurrent then 
634                     demod newnewcurrent
635                   else Some (sign,newnewcurrent)
636   in 
637   let res = demod current in
638   match res with
639   | None -> None
640   | Some (Negative, c) ->
641       let ok = not (
642         List.exists
643           (fun (s, eq) -> s = Negative && meta_convertibility_eq eq c)
644           all)
645       in
646       if ok then res else None
647   | Some (Positive, c) ->
648       if Indexing.in_index active_table c then
649         None
650       else
651         match passive_table with
652         | None -> 
653             if Indexing.subsumption env active_table c = None then
654               res
655             else
656               None
657         | Some passive_table ->
658             if Indexing.in_index passive_table c then None
659             else 
660               if Indexing.subsumption env active_table c = None then
661                 if Indexing.subsumption env passive_table c = None then
662                   res 
663                 else
664                   None
665               else
666                 None
667 ;;
668
669 type fs_time_info_t = {
670   mutable build_all: float;
671   mutable demodulate: float;
672   mutable subsumption: float;
673 };;
674
675 let fs_time_info = { build_all = 0.; demodulate = 0.; subsumption = 0. };;
676
677
678 (** simplifies new using active and passive *)
679 let forward_simplify_new env (new_neg, new_pos) ?passive active =
680   if Utils.debug_metas then
681     begin
682       let m,c,u = env in
683         ignore(List.map 
684                  (fun current -> 
685                     Indexing.check_target c current "forward new neg") new_neg);
686         ignore(List.map 
687         (fun current -> Indexing.check_target c current "forward new pos") 
688       new_pos;)
689     end;
690   let t1 = Unix.gettimeofday () in
691
692   let active_list, active_table = active in
693   let pl, passive_table =
694     match passive with
695     | None -> [], None
696     | Some ((pn, _), (pp, _), pt) ->
697         let pn = List.map (fun e -> (Negative, e)) pn
698         and pp = List.map (fun e -> (Positive, e)) pp in
699         pn @ pp, Some pt
700   in
701   
702   let t2 = Unix.gettimeofday () in
703   fs_time_info.build_all <- fs_time_info.build_all +. (t2 -. t1);
704   
705   let demodulate sign table target =
706     let newmeta, newtarget =
707       Indexing.demodulation_equality !maxmeta env table sign target in
708     maxmeta := newmeta;
709     newtarget
710   in
711   let t1 = Unix.gettimeofday () in
712
713   let new_neg, new_pos =
714     let new_neg = List.map (demodulate Negative active_table) new_neg
715     and new_pos = List.map (demodulate Positive active_table) new_pos in
716       new_neg,new_pos  
717 (* PROVA 
718     match passive_table with
719     | None -> new_neg, new_pos
720     | Some passive_table ->
721         List.map (demodulate Negative passive_table) new_neg,
722         List.map (demodulate Positive passive_table) new_pos *)
723   in
724
725   let t2 = Unix.gettimeofday () in
726   fs_time_info.demodulate <- fs_time_info.demodulate +. (t2 -. t1);
727
728   let new_pos_set =
729     List.fold_left
730       (fun s e ->
731          if not (Inference.is_identity env e) then
732            if EqualitySet.mem e s then s
733            else EqualitySet.add e s
734          else s)
735       EqualitySet.empty new_pos
736   in
737   let new_pos = EqualitySet.elements new_pos_set in
738
739   let subs =
740     match passive_table with
741     | None ->
742         (fun e -> (Indexing.subsumption env active_table e = None))
743     | Some passive_table ->
744         (fun e -> ((Indexing.subsumption env active_table e = None) &&
745                          (Indexing.subsumption env passive_table e = None)))
746   in
747 (*   let t1 = Unix.gettimeofday () in *)
748 (*   let t2 = Unix.gettimeofday () in *)
749 (*   fs_time_info.subsumption <- fs_time_info.subsumption +. (t2 -. t1); *)
750   let is_duplicate =
751     match passive_table with
752     | None ->
753         (fun e -> not (Indexing.in_index active_table e))
754     | Some passive_table ->
755         (fun e ->
756            not ((Indexing.in_index active_table e) ||
757                   (Indexing.in_index passive_table e)))
758   in
759   new_neg, List.filter subs (List.filter is_duplicate new_pos)
760 ;;
761
762
763 (** simplifies a goal with equalities in active and passive *)  
764 let rec simplify_goal env goal ?passive (active_list, active_table) =
765   let pl, passive_table =
766     match passive with
767     | None -> [], None
768     | Some ((pn, _), (pp, _), pt) ->
769         let pn = List.map (fun e -> (Negative, e)) pn
770         and pp = List.map (fun e -> (Positive, e)) pp in
771         pn @ pp, Some pt
772   in
773
774   let demodulate table goal = 
775     let newmeta, newgoal =
776       Indexing.demodulation_goal !maxmeta env table goal in
777     maxmeta := newmeta;
778     goal <> newgoal, newgoal
779   in
780   let changed, goal =
781     match passive_table with
782     | None -> demodulate active_table goal
783     | Some passive_table ->
784         let changed, goal = demodulate active_table goal in
785         let changed', goal = demodulate passive_table goal in
786         (changed || changed'), goal
787   in
788   changed,
789   if not changed then 
790     goal 
791   else 
792     snd (simplify_goal env goal ?passive (active_list, active_table)) 
793 ;;
794
795
796 let simplify_goals env goals ?passive active =
797   let a_goals, p_goals = goals in
798   let p_goals = 
799     List.map
800       (fun (d, gl) ->
801          let gl =
802            List.map (fun g -> snd (simplify_goal env g ?passive active)) gl in
803          d, gl)
804       p_goals
805   in
806   let goals =
807     List.fold_left
808       (fun (a, p) (d, gl) ->
809          let changed = ref false in
810          let gl =
811            List.map
812              (fun g ->
813                 let c, g = simplify_goal env g ?passive active in
814                 changed := !changed || c; g) gl in
815          if !changed then (a, (d, gl)::p) else ((d, gl)::a, p))
816       ([], p_goals) a_goals
817   in
818   goals
819 ;;
820
821
822 (** simplifies active usign new *)
823 let backward_simplify_active env new_pos new_table min_weight active =
824   let active_list, active_table = active in
825   let active_list, newa = 
826     List.fold_right
827       (fun (s, equality) (res, newn) ->
828          let ew, _, _, _ = equality in
829          if ew < min_weight then
830            (s, equality)::res, newn
831          else
832            match forward_simplify env (s, equality) (new_pos, new_table) with
833            | None -> res, newn
834            | Some (s, e) ->
835                if equality = e then
836                  (s, e)::res, newn
837                else 
838                  res, (s, e)::newn)
839       active_list ([], [])
840   in
841   let find eq1 where =
842     List.exists (fun (s, e) -> meta_convertibility_eq eq1 e) where
843   in
844   let active, newa =
845     List.fold_right
846       (fun (s, eq) (res, tbl) ->
847          if List.mem (s, eq) res then
848            res, tbl
849          else if (is_identity env eq) || (find eq res) then (
850            res, tbl
851          ) 
852          else
853            (s, eq)::res, if s = Negative then tbl else Indexing.index tbl eq)
854       active_list ([], Indexing.empty),
855     List.fold_right
856       (fun (s, eq) (n, p) ->
857          if (s <> Negative) && (is_identity env eq) then (
858            (n, p)
859          ) else
860            if s = Negative then eq::n, p
861            else n, eq::p)
862       newa ([], [])
863   in
864   match newa with
865   | [], [] -> active, None
866   | _ -> active, Some newa
867 ;;
868
869
870 (** simplifies passive using new *)
871 let backward_simplify_passive env new_pos new_table min_weight passive =
872   let (nl, ns), (pl, ps), passive_table = passive in
873   let f sign equality (resl, ress, newn) =
874     let ew, _, _, _ = equality in
875     if ew < min_weight then
876       equality::resl, ress, newn
877     else
878       match forward_simplify env (sign, equality) (new_pos, new_table) with
879       | None -> resl, EqualitySet.remove equality ress, newn
880       | Some (s, e) ->
881           if equality = e then
882             equality::resl, ress, newn
883           else
884             let ress = EqualitySet.remove equality ress in
885             resl, ress, e::newn
886   in
887   let nl, ns, newn = List.fold_right (f Negative) nl ([], ns, [])
888   and pl, ps, newp = List.fold_right (f Positive) pl ([], ps, []) in
889   let passive_table =
890     List.fold_left
891       (fun tbl e -> Indexing.index tbl e) Indexing.empty pl
892   in
893   match newn, newp with
894   | [], [] -> ((nl, ns), (pl, ps), passive_table), None
895   | _, _ -> ((nl, ns), (pl, ps), passive_table), Some (newn, newp)
896 ;;
897
898
899 let backward_simplify env new' ?passive active =
900   let new_pos, new_table, min_weight =
901     List.fold_left
902       (fun (l, t, w) e ->
903          let ew, _, _, _ = e in
904          (Positive, e)::l, Indexing.index t e, min ew w)
905       ([], Indexing.empty, 1000000) (snd new')
906   in
907   let active, newa =
908     backward_simplify_active env new_pos new_table min_weight active in
909   match passive with
910   | None ->
911       active, (make_passive [] []), newa, None
912   | Some passive ->
913      active, passive, newa, None
914 (* prova
915       let passive, newp =
916         backward_simplify_passive env new_pos new_table min_weight passive in
917       active, passive, newa, newp *)
918 ;;
919
920
921 let close env new' given =
922   let new_pos, new_table, min_weight =
923     List.fold_left
924       (fun (l, t, w) e ->
925          let ew, _, _, _ = e in
926          (Positive, e)::l, Indexing.index t e, min ew w)
927       ([], Indexing.empty, 1000000) (snd new')
928   in
929   List.fold_left
930     (fun (n,p) (s,c) ->
931        let neg,pos = infer env s c (new_pos,new_table) in
932          neg@n,pos@p)
933     ([],[]) given 
934 ;;
935
936 let is_commutative_law eq =
937   let w, proof, (eq_ty, left, right, order), metas = snd eq in
938     match left,right with
939         Cic.Appl[f1;Cic.Meta _ as a1;Cic.Meta _ as b1], 
940         Cic.Appl[f2;Cic.Meta _ as a2;Cic.Meta _ as b2] ->
941           f1 = f2 && a1 = b2 && a2 = b1
942       | _ -> false
943 ;;
944
945 let prova env new' active = 
946   let given = List.filter is_commutative_law (fst active) in
947   let _ =
948     debug_print
949       (lazy
950          (Printf.sprintf "symmetric:\n%s\n"
951             (String.concat "\n"
952                ((List.map
953                    (fun (s, e) -> (string_of_sign s) ^ " " ^
954                       (string_of_equality ~env e))
955                    (given)))))) in
956     close env new' given
957 ;;
958
959 (* returns an estimation of how many equalities in passive can be activated
960    within the current time limit *)
961 let get_selection_estimate () =
962   elapsed_time := (Unix.gettimeofday ()) -. !start_time;
963   (*   !processed_clauses * (int_of_float (!time_limit /. !elapsed_time)) *)
964   int_of_float (
965     ceil ((float_of_int !processed_clauses) *.
966             ((!time_limit (* *. 2. *)) /. !elapsed_time -. 1.)))
967 ;;
968
969
970 (** initializes the set of goals *)
971 let make_goals goal =
972   let active = []
973   and passive = [0, [goal]] in
974   active, passive
975 ;;
976
977
978 (** initializes the set of theorems *)
979 let make_theorems theorems =
980   theorems, []
981 ;;
982
983
984 let activate_goal (active, passive) =
985   if active = [] then
986     match passive with
987     | goal_conj::tl -> true, (goal_conj::active, tl)
988     | [] -> false, (active, passive)
989   else  
990     true, (active,passive)
991 ;;
992
993
994 let activate_theorem (active, passive) =
995   match passive with
996   | theorem::tl -> true, (theorem::active, tl)
997   | [] -> false, (active, passive)
998 ;;
999
1000
1001
1002 let simplify_theorems env theorems ?passive (active_list, active_table) =
1003   let pl, passive_table =
1004     match passive with
1005     | None -> [], None
1006     | Some ((pn, _), (pp, _), pt) ->
1007         let pn = List.map (fun e -> (Negative, e)) pn
1008         and pp = List.map (fun e -> (Positive, e)) pp in
1009         pn @ pp, Some pt
1010   in
1011   let a_theorems, p_theorems = theorems in
1012   let demodulate table theorem =
1013     let newmeta, newthm =
1014       Indexing.demodulation_theorem !maxmeta env table theorem in
1015     maxmeta := newmeta;
1016     theorem != newthm, newthm
1017   in
1018   let foldfun table (a, p) theorem =
1019     let changed, theorem = demodulate table theorem in
1020     if changed then (a, theorem::p) else (theorem::a, p)
1021   in
1022   let mapfun table theorem = snd (demodulate table theorem) in
1023   match passive_table with
1024   | None ->
1025       let p_theorems = List.map (mapfun active_table) p_theorems in
1026       List.fold_left (foldfun active_table) ([], p_theorems) a_theorems
1027   | Some passive_table ->
1028       let p_theorems = List.map (mapfun active_table) p_theorems in
1029       let p_theorems, a_theorems =
1030         List.fold_left (foldfun active_table) ([], p_theorems) a_theorems in
1031       let p_theorems = List.map (mapfun passive_table) p_theorems in
1032       List.fold_left (foldfun passive_table) ([], p_theorems) a_theorems
1033 ;;
1034
1035
1036 let rec simpl env e others others_simpl =
1037   let active = others @ others_simpl in
1038   let tbl =
1039     List.fold_left
1040       (fun t (_, e) -> Indexing.index t e)
1041       Indexing.empty active
1042   in
1043   let res = forward_simplify env e (active, tbl) in
1044     match others with
1045       | hd::tl -> (
1046           match res with
1047             | None -> simpl env hd tl others_simpl
1048             | Some e -> simpl env hd tl (e::others_simpl)
1049         )
1050       | [] -> (
1051           match res with
1052             | None -> others_simpl
1053             | Some e -> e::others_simpl
1054         )
1055 ;;
1056
1057 let simplify_equalities env equalities =
1058   debug_print
1059     (lazy 
1060        (Printf.sprintf "equalities:\n%s\n"
1061           (String.concat "\n"
1062              (List.map string_of_equality equalities))));
1063   debug_print (lazy "SIMPLYFYING EQUALITIES...");
1064   match equalities with
1065     | [] -> []
1066     | hd::tl ->
1067         let others = List.map (fun e -> (Positive, e)) tl in
1068         let res =
1069           List.rev (List.map snd (simpl env (Positive, hd) others []))
1070         in
1071           debug_print
1072             (lazy
1073                (Printf.sprintf "equalities AFTER:\n%s\n"
1074                   (String.concat "\n"
1075                      (List.map string_of_equality res))));
1076           res
1077 ;;
1078
1079 (*
1080 (* applies equality to goal to see if the goal can be closed *)
1081 let apply_equality_to_goal env equality goal =
1082   let module C = Cic in
1083   let module HL = HelmLibraryObjects in
1084   let module I = Inference in
1085   let metasenv, context, ugraph = env in
1086   let _, proof, (ty, left, right, _), metas = equality in
1087   let eqterm =
1088     C.Appl [C.MutInd (LibraryObjects.eq_URI (), 0, []); ty; left; right] in
1089   let gproof, gmetas, gterm = goal in
1090 (*   debug_print *)
1091 (*     (lazy *)
1092 (*        (Printf.sprintf "APPLY EQUALITY TO GOAL: %s, %s" *)
1093 (*           (string_of_equality equality) (CicPp.ppterm gterm))); *)
1094   try
1095     let subst, metasenv', _ =
1096       Inference.unification metas gmetas context eqterm gterm ugraph
1097     in
1098     let newproof =
1099       match proof with
1100       | I.BasicProof (subst',t) -> I.BasicProof (subst@subst',t)
1101       | I.ProofBlock (s, uri, nt, t, pe, p) ->
1102           I.ProofBlock (subst @ s, uri, nt, t, pe, p)
1103       | _ -> assert false
1104     in
1105     let newgproof =
1106       let rec repl = function
1107         | I.ProofGoalBlock (_, gp) -> I.ProofGoalBlock (newproof, gp)
1108         | I.NoProof -> newproof
1109         | I.BasicProof _ -> newproof
1110         | I.SubProof (t, i, p) -> 
1111             prerr_endline "SUBPROOF!";
1112             I.SubProof (t, i, repl p)
1113         | _ -> assert false
1114       in
1115       repl gproof
1116     in
1117     true, (subst:Inference.substitution), newgproof
1118   with CicUnification.UnificationFailure _ ->
1119     false, [], I.NoProof
1120 ;;
1121
1122
1123
1124 let new_meta metasenv =
1125   let m = CicMkImplicit.new_meta metasenv [] in
1126   incr maxmeta;
1127   while !maxmeta <= m do incr maxmeta done;
1128   !maxmeta
1129 ;;
1130
1131
1132 (* applies a theorem or an equality to goal, returning a list of subgoals or
1133    an indication of failure *)
1134 let apply_to_goal env theorems ?passive active goal =
1135   let metasenv, context, ugraph = env in
1136   let proof, metas, term = goal in
1137   (*   debug_print *)
1138   (*     (lazy *)
1139   (*        (Printf.sprintf "apply_to_goal with goal: %s" *)
1140   (*           (\* (string_of_proof proof)  *\)(CicPp.ppterm term))); *)
1141   let status =
1142     let irl =
1143       CicMkImplicit.identity_relocation_list_for_metavariable context in
1144     let proof', newmeta =
1145       let rec get_meta = function
1146         | SubProof (t, i, p) ->
1147             let t', i' = get_meta p in
1148             if i' = -1 then t, i else t', i'
1149         | ProofGoalBlock (_, p) -> get_meta p
1150         | _ -> Cic.Implicit None, -1
1151       in
1152       let p, m = get_meta proof in
1153       if m = -1 then
1154         let n = new_meta (metasenv @ metas) in
1155         Cic.Meta (n, irl), n
1156       else
1157         p, m
1158     in
1159     let metasenv = (newmeta, context, term)::metasenv @ metas in
1160     let bit = new_meta metasenv, context, term in 
1161     let metasenv' = bit::metasenv in
1162     ((None, metasenv', Cic.Meta (newmeta, irl), term), newmeta)
1163   in
1164   let rec aux = function
1165     | [] -> `No
1166     | (theorem, thmty, _)::tl ->
1167         try
1168           let subst, (newproof, newgoals) =
1169             PrimitiveTactics.apply_tac_verbose_with_subst ~term:theorem status
1170           in
1171           if newgoals = [] then
1172             let _, _, p, _ = newproof in
1173             let newp =
1174               let rec repl = function
1175                 | Inference.ProofGoalBlock (_, gp) ->
1176                     Inference.ProofGoalBlock (Inference.BasicProof ([],p), gp)
1177                 | Inference.NoProof -> Inference.BasicProof ([],p)
1178                 | Inference.BasicProof _ -> Inference.BasicProof ([],p)
1179                 | Inference.SubProof (t, i, p2) ->
1180                     Inference.SubProof (t, i, repl p2)
1181                 | _ -> assert false
1182               in
1183               repl proof
1184             in
1185             let _, m = status in
1186             let subst = List.filter (fun (i, _) -> i = m) subst in
1187             `Ok (subst, [newp, metas, term])
1188           else
1189             let _, menv, p, _ = newproof in
1190             let irl =
1191               CicMkImplicit.identity_relocation_list_for_metavariable context
1192             in
1193             let goals =
1194               List.map
1195                 (fun i ->
1196                    let _, _, ty = CicUtil.lookup_meta i menv in
1197                    let p' =
1198                      let rec gp = function
1199                        | SubProof (t, i, p) ->
1200                            SubProof (t, i, gp p)
1201                        | ProofGoalBlock (sp1, sp2) ->
1202                            ProofGoalBlock (sp1, gp sp2)
1203                        | BasicProof _
1204                        | NoProof ->
1205                            SubProof (p, i, BasicProof ([],Cic.Meta (i, irl)))
1206                        | ProofSymBlock (s, sp) ->
1207                            ProofSymBlock (s, gp sp)
1208                        | ProofBlock (s, u, nt, t, pe, sp) ->
1209                            prerr_endline "apply_to_goal!";
1210                            ProofBlock (s, u, nt, t, pe, gp sp)
1211                      in gp proof
1212                    in
1213                    (p', menv, ty))
1214                 newgoals
1215             in
1216             let goals =
1217               let weight t =
1218                 let w, m = weight_of_term t in
1219                 w + 2 * (List.length m)
1220               in
1221               List.sort
1222                 (fun (_, _, t1) (_, _, t2) ->
1223                    Pervasives.compare (weight t1) (weight t2))
1224                 goals
1225             in
1226             let best = aux tl in
1227             match best with
1228             | `Ok (_, _) -> best
1229             | `No -> `GoOn ([subst, goals])
1230             | `GoOn sl -> `GoOn ((subst, goals)::sl)
1231         with ProofEngineTypes.Fail msg ->
1232           aux tl
1233   in
1234   let r, s, l =
1235     if Inference.term_is_equality term then
1236       let rec appleq_a = function
1237         | [] -> false, [], []
1238         | (Positive, equality)::tl ->
1239             let ok, s, newproof = apply_equality_to_goal env equality goal in
1240             if ok then true, s, [newproof, metas, term] else appleq_a tl
1241         | _::tl -> appleq_a tl
1242       in
1243       let rec appleq_p = function
1244         | [] -> false, [], []
1245         | equality::tl ->
1246             let ok, s, newproof = apply_equality_to_goal env equality goal in
1247             if ok then true, s, [newproof, metas, term] else appleq_p tl
1248       in
1249       let al, _ = active in
1250       match passive with
1251       | None -> appleq_a al
1252       | Some (_, (pl, _), _) ->
1253           let r, s, l = appleq_a al in if r then r, s, l else appleq_p pl
1254     else
1255       false, [], []
1256   in
1257   if r = true then `Ok ((s:Cic.substitution),l) else aux theorems
1258 ;;
1259
1260
1261 (* sorts a conjunction of goals in order to detect earlier if it is
1262    unsatisfiable. Non-predicate goals are placed at the end of the list *)
1263 let sort_goal_conj (metasenv, context, ugraph) (depth, gl) =
1264   let gl = 
1265     List.stable_sort
1266       (fun (_, e1, g1) (_, e2, g2) ->
1267          let ty1, _ =
1268            CicTypeChecker.type_of_aux' (e1 @ metasenv) context g1 ugraph 
1269          and ty2, _ =
1270            CicTypeChecker.type_of_aux' (e2 @ metasenv) context g2 ugraph
1271          in
1272          let prop1 =
1273            let b, _ =
1274              CicReduction.are_convertible context (Cic.Sort Cic.Prop) ty1 ugraph
1275            in
1276            if b then 0 else 1
1277          and prop2 =
1278            let b, _ =
1279              CicReduction.are_convertible context (Cic.Sort Cic.Prop) ty2 ugraph
1280            in
1281            if b then 0 else 1
1282          in
1283          if prop1 = 0 && prop2 = 0 then
1284            let e1 = if Inference.term_is_equality g1 then 0 else 1
1285            and e2 = if Inference.term_is_equality g2 then 0 else 1 in
1286            e1 - e2
1287          else
1288            prop1 - prop2)
1289       gl
1290   in
1291   (depth, gl)
1292 ;;
1293
1294
1295 let is_meta_closed goals =
1296   List.for_all (fun (_, _, g) -> CicUtil.is_meta_closed g) goals
1297 ;;
1298
1299
1300 (* applies a series of theorems/equalities to a conjunction of goals *)
1301 let rec apply_to_goal_conj env theorems ?passive active (depth, goals) =
1302   let aux (goal, r) tl =
1303     let propagate_subst subst (proof, metas, term) =
1304       let rec repl = function
1305         | NoProof -> NoProof 
1306         | BasicProof (subst',t) ->
1307             BasicProof (subst@subst',t)
1308         | ProofGoalBlock (p, pb) ->
1309             let pb' = repl pb in
1310             ProofGoalBlock (p, pb')
1311         | SubProof (t, i, p) ->
1312             let t' = Inference.apply_subst subst t in
1313             let p = repl p in
1314             SubProof (t', i, p)
1315         | ProofSymBlock (ens, p) -> ProofSymBlock (ens, repl p)
1316         | ProofBlock (s, u, nty, t, pe, p) ->
1317             ProofBlock (subst @ s, u, nty, t, pe, p)
1318       in (repl proof, metas, term)
1319     in
1320     (* let r = apply_to_goal env theorems ?passive active goal in *) (
1321       match r with
1322       | `No -> `No (depth, goals)
1323       | `GoOn sl ->
1324           let l =
1325             List.map
1326               (fun (s, gl) ->
1327                  let tl = List.map (propagate_subst s) tl in
1328                  sort_goal_conj env (depth+1, gl @ tl)) sl
1329           in
1330           `GoOn l
1331       | `Ok (subst, gl) ->
1332           if tl = [] then
1333             `Ok (depth, gl)
1334           else
1335             let p, _, _ = List.hd gl in
1336             let subproof =
1337               let rec repl = function
1338                 | SubProof (_, _, p) -> repl p
1339                 | ProofGoalBlock (p1, p2) ->
1340                     ProofGoalBlock (repl p1, repl p2)
1341                 | p -> p
1342               in
1343               build_proof_term (repl p)
1344             in
1345             let i = 
1346               let rec get_meta = function
1347                 | SubProof (_, i, p) ->
1348                     let i' = get_meta p in
1349                     if i' = -1 then i else i'
1350 (*                         max i (get_meta p) *)
1351                 | ProofGoalBlock (_, p) -> get_meta p
1352                 | _ -> -1
1353               in
1354               get_meta p
1355             in
1356             let subst =
1357               let _, (context, _, _) = List.hd subst in
1358               [i, (context, subproof, Cic.Implicit None)]
1359             in
1360             let tl = List.map (propagate_subst subst) tl in
1361             let conj = sort_goal_conj env (depth(* +1 *), tl) in
1362             `GoOn ([conj])
1363     )
1364   in
1365   if depth > !maxdepth || (List.length goals) > !maxwidth then 
1366     `No (depth, goals)
1367   else
1368     let rec search_best res = function
1369       | [] -> res
1370       | goal::tl ->
1371           let r = apply_to_goal env theorems ?passive active goal in
1372           match r with
1373           | `Ok _ -> (goal, r)
1374           | `No -> search_best res tl
1375           | `GoOn l ->
1376               let newres = 
1377                 match res with
1378                 | _, `Ok _ -> assert false
1379                 | _, `No -> goal, r
1380                 | _, `GoOn l2 ->
1381                     if (List.length l) < (List.length l2) then goal, r else res
1382               in
1383               search_best newres tl
1384     in
1385     let hd = List.hd goals in
1386     let res = hd, (apply_to_goal env theorems ?passive active hd) in
1387     let best =
1388       match res with
1389       | _, `Ok _ -> res
1390       | _, _ -> search_best res (List.tl goals)
1391     in
1392     let res = aux best (List.filter (fun g -> g != (fst best)) goals) in
1393     match res with
1394     | `GoOn ([conj]) when is_meta_closed (snd conj) &&
1395         (List.length (snd conj)) < (List.length goals)->
1396         apply_to_goal_conj env theorems ?passive active conj
1397     | _ -> res
1398 ;;
1399
1400
1401 (*
1402 module OrderedGoals = struct
1403   type t = int * (Inference.proof * Cic.metasenv * Cic.term) list
1404
1405   let compare g1 g2 =
1406     let d1, l1 = g1
1407     and d2, l2 = g2 in
1408     let r = d2 - d1 in
1409     if r <> 0 then r
1410     else let r = (List.length l1) - (List.length l2) in
1411     if r <> 0 then r
1412     else
1413       let res = ref 0 in
1414       let _ = 
1415         List.exists2
1416           (fun (_, _, t1) (_, _, t2) ->
1417              let r = Pervasives.compare t1 t2 in
1418              if r <> 0 then (
1419                res := r;
1420                true
1421              ) else
1422                false) l1 l2
1423       in !res
1424 end
1425
1426 module GoalsSet = Set.Make(OrderedGoals);;
1427
1428
1429 exception SearchSpaceOver;;
1430 *)
1431
1432
1433 (*
1434 let apply_to_goals env is_passive_empty theorems active goals =
1435   debug_print (lazy "\n\n\tapply_to_goals\n\n");
1436   let add_to set goals =
1437     List.fold_left (fun s g -> GoalsSet.add g s) set goals 
1438   in
1439   let rec aux set = function
1440     | [] ->
1441         debug_print (lazy "HERE!!!");
1442         if is_passive_empty then raise SearchSpaceOver else false, set
1443     | goals::tl ->
1444         let res = apply_to_goal_conj env theorems active goals in
1445         match res with
1446         | `Ok newgoals ->
1447             let _ =
1448               let d, p, t =
1449                 match newgoals with
1450                 | (d, (p, _, t)::_) -> d, p, t
1451                 | _ -> assert false
1452               in
1453               debug_print
1454                 (lazy
1455                    (Printf.sprintf "\nOK!!!!\ndepth: %d\nProof: %s\ngoal: %s\n"
1456                       d (string_of_proof p) (CicPp.ppterm t)))
1457             in
1458             true, GoalsSet.singleton newgoals
1459         | `GoOn newgoals ->
1460             let set' = add_to set (goals::tl) in
1461             let set' = add_to set' newgoals in
1462             false, set'
1463         | `No newgoals ->
1464             aux set tl
1465   in
1466   let n = List.length goals in
1467   let res, goals = aux (add_to GoalsSet.empty goals) goals in
1468   let goals = GoalsSet.elements goals in
1469   debug_print (lazy "\n\tapply_to_goals end\n");
1470   let m = List.length goals in
1471   if m = n && is_passive_empty then
1472     raise SearchSpaceOver
1473   else
1474     res, goals
1475 ;;
1476 *)
1477
1478
1479 (* sorts the list of passive goals to minimize the search for a proof (doesn't
1480    work that well yet...) *)
1481 let sort_passive_goals goals =
1482   List.stable_sort
1483     (fun (d1, l1) (d2, l2) ->
1484        let r1 = d2 - d1 
1485        and r2 = (List.length l1) - (List.length l2) in
1486        let foldfun ht (_, _, t) = 
1487          let _ = List.map (fun i -> Hashtbl.replace ht i 1) (metas_of_term t)
1488          in ht
1489        in
1490        let m1 = Hashtbl.length (List.fold_left foldfun (Hashtbl.create 3) l1)
1491        and m2 = Hashtbl.length (List.fold_left foldfun (Hashtbl.create 3) l2)
1492        in let r3 = m1 - m2 in
1493        if r3 <> 0 then r3
1494        else if r2 <> 0 then r2 
1495        else r1)
1496     (*          let _, _, g1 = List.hd l1 *)
1497 (*          and _, _, g2 = List.hd l2 in *)
1498 (*          let e1 = if Inference.term_is_equality g1 then 0 else 1 *)
1499 (*          and e2 = if Inference.term_is_equality g2 then 0 else 1 *)
1500 (*          in let r4 = e1 - e2 in *)
1501 (*          if r4 <> 0 then r3 else r1) *)
1502     goals
1503 ;;
1504
1505
1506 let print_goals goals = 
1507   (String.concat "\n"
1508      (List.map
1509         (fun (d, gl) ->
1510            let gl' =
1511              List.map
1512                (fun (p, _, t) ->
1513                   (* (string_of_proof p) ^ ", " ^ *) (CicPp.ppterm t)) gl
1514            in
1515            Printf.sprintf "%d: %s" d (String.concat "; " gl')) goals))
1516 ;;
1517
1518
1519 (* tries to prove the first conjunction in goals with applications of
1520    theorems/equalities, returning new sub-goals or an indication of success *)
1521 let apply_goal_to_theorems dbd env theorems ?passive active goals =
1522   let theorems, _ = theorems in
1523   let a_goals, p_goals = goals in
1524   let goal = List.hd a_goals in
1525   let not_in_active gl =
1526     not
1527       (List.exists
1528          (fun (_, gl') ->
1529             if (List.length gl) = (List.length gl') then
1530               List.for_all2 (fun (_, _, g1) (_, _, g2) -> g1 = g2) gl gl'
1531             else
1532               false)
1533          a_goals)
1534   in
1535   let aux theorems =
1536     let res = apply_to_goal_conj env theorems ?passive active goal in
1537     match res with
1538     | `Ok newgoals ->
1539         true, ([newgoals], [])
1540     | `No _ ->
1541         false, (a_goals, p_goals)
1542     | `GoOn newgoals ->
1543         let newgoals =
1544           List.filter
1545             (fun (d, gl) ->
1546                (d <= !maxdepth) && (List.length gl) <= !maxwidth &&
1547                  not_in_active gl)
1548             newgoals in
1549         let p_goals = newgoals @ p_goals in
1550         let p_goals = sort_passive_goals p_goals in
1551         false, (a_goals, p_goals)
1552   in
1553   aux theorems
1554 ;;
1555
1556
1557 let apply_theorem_to_goals env theorems active goals =
1558   let a_goals, p_goals = goals in
1559   let theorem = List.hd (fst theorems) in
1560   let theorems = [theorem] in
1561   let rec aux p = function
1562     | [] -> false, ([], p)
1563     | goal::tl ->
1564         let res = apply_to_goal_conj env theorems active goal in
1565         match res with
1566         | `Ok newgoals -> true, ([newgoals], [])
1567         | `No _ -> aux p tl
1568         | `GoOn newgoals -> aux (newgoals @ p) tl
1569   in
1570   let ok, (a, p) = aux p_goals a_goals in
1571   if ok then
1572     ok, (a, p)
1573   else
1574     let p_goals =
1575       List.stable_sort
1576         (fun (d1, l1) (d2, l2) ->
1577            let r = d2 - d1 in
1578            if r <> 0 then r
1579            else let r = (List.length l1) - (List.length l2) in
1580            if r <> 0 then r
1581            else
1582              let res = ref 0 in
1583              let _ = 
1584                List.exists2
1585                  (fun (_, _, t1) (_, _, t2) ->
1586                     let r = Pervasives.compare t1 t2 in
1587                     if r <> 0 then (res := r; true) else false) l1 l2
1588              in !res)
1589         p
1590     in
1591     ok, (a_goals, p_goals)
1592 ;;
1593
1594 (* given-clause algorithm with lazy reduction strategy *)
1595 let rec given_clause dbd env goals theorems passive active =
1596   let goals = simplify_goals env goals active in
1597   let ok, goals = activate_goal goals in
1598   (*   let theorems = simplify_theorems env theorems active in *)
1599   if ok then
1600     let ok, goals = apply_goal_to_theorems dbd env theorems active goals in
1601     if ok then
1602       let proof =
1603         match (fst goals) with
1604         | (_, [proof, _, _])::_ -> Some proof
1605         | _ -> assert false
1606       in
1607       ParamodulationSuccess (proof, env)
1608     else
1609       given_clause_aux dbd env goals theorems passive active
1610   else
1611 (*     let ok', theorems = activate_theorem theorems in *)
1612     let ok', theorems = false, theorems in
1613     if ok' then
1614       let ok, goals = apply_theorem_to_goals env theorems active goals in
1615       if ok then
1616         let proof =
1617           match (fst goals) with
1618           | (_, [proof, _, _])::_ -> Some proof
1619           | _ -> assert false
1620         in
1621         ParamodulationSuccess (proof, env)
1622       else
1623         given_clause_aux dbd env goals theorems passive active
1624     else
1625       if (passive_is_empty passive) then ParamodulationFailure
1626       else given_clause_aux dbd env goals theorems passive active
1627
1628 and given_clause_aux dbd env goals theorems passive active = 
1629   let _,context,_ = env in
1630   let time1 = Unix.gettimeofday () in
1631  
1632   let selection_estimate = get_selection_estimate () in
1633   let kept = size_of_passive passive in
1634   let passive =
1635     if !time_limit = 0. || !processed_clauses = 0 then
1636       passive
1637     else if !elapsed_time > !time_limit then (
1638       debug_print (lazy (Printf.sprintf "Time limit (%.2f) reached: %.2f\n"
1639                            !time_limit !elapsed_time));
1640       make_passive [] []
1641     ) else if kept > selection_estimate then (
1642       debug_print
1643         (lazy (Printf.sprintf ("Too many passive equalities: pruning..." ^^
1644                                  "(kept: %d, selection_estimate: %d)\n")
1645                  kept selection_estimate));
1646       prune_passive selection_estimate active passive
1647     ) else
1648       passive
1649   in
1650
1651   let time2 = Unix.gettimeofday () in
1652   passive_maintainance_time := !passive_maintainance_time +. (time2 -. time1);
1653
1654   kept_clauses := (size_of_passive passive) + (size_of_active active);
1655   match passive_is_empty passive with
1656   | true -> (* ParamodulationFailure *)
1657       given_clause dbd env goals theorems passive active
1658   | false ->
1659       let (sign, current), passive = select env (fst goals) passive active in
1660       let names = List.map (HExtlib.map_option (fun (name,_) -> name)) context in 
1661       prerr_endline ("Selected = " ^ 
1662                        (CicPp.pp (Inference.term_of_equality current) names));
1663       let time1 = Unix.gettimeofday () in
1664       let res = forward_simplify env (sign, current) ~passive active in
1665       let time2 = Unix.gettimeofday () in
1666       forward_simpl_time := !forward_simpl_time +. (time2 -. time1);
1667       match res with
1668       | None ->
1669           given_clause dbd env goals theorems passive active
1670       | Some (sign, current) ->
1671           if (sign = Negative) && (is_identity env current) then (
1672             debug_print
1673               (lazy (Printf.sprintf "OK!!! %s %s" (string_of_sign sign)
1674                        (string_of_equality ~env current)));
1675             let _, proof, _, _ = current in
1676             ParamodulationSuccess (Some proof, env)
1677           ) else (           
1678             debug_print
1679               (lazy "\n================================================");
1680             debug_print (lazy (Printf.sprintf "selected: %s %s"
1681                                  (string_of_sign sign)
1682                                  (string_of_equality ~env current)));
1683
1684             let t1 = Unix.gettimeofday () in
1685             let new' = infer env sign current active in
1686             let t2 = Unix.gettimeofday () in
1687             infer_time := !infer_time +. (t2 -. t1);
1688             
1689             let res, goal' = contains_empty env new' in
1690             if res then
1691               let proof =
1692                 match goal' with
1693                 | Some goal -> let _, proof, _, _ = goal in Some proof
1694                 | None -> None
1695               in
1696               ParamodulationSuccess (proof, env)
1697             else 
1698               let t1 = Unix.gettimeofday () in
1699               let new' = forward_simplify_new env new' active in
1700               let t2 = Unix.gettimeofday () in
1701               let _ =
1702                 forward_simpl_new_time :=
1703                   !forward_simpl_new_time +. (t2 -. t1)
1704               in
1705               let active =
1706                 match sign with
1707                 | Negative -> active
1708                 | Positive ->
1709                     let t1 = Unix.gettimeofday () in
1710                     let active, _, newa, _ =
1711                       backward_simplify env ([], [current]) active
1712                     in
1713                     let t2 = Unix.gettimeofday () in
1714                     backward_simpl_time :=
1715                       !backward_simpl_time +. (t2 -. t1);
1716                     match newa with
1717                     | None -> active
1718                     | Some (n, p) ->
1719                         let al, tbl = active in
1720                         let nn = List.map (fun e -> Negative, e) n in
1721                         let pp, tbl =
1722                           List.fold_right
1723                             (fun e (l, t) ->
1724                                (Positive, e)::l,
1725                                Indexing.index tbl e)
1726                             p ([], tbl)
1727                         in
1728                         nn @ al @ pp, tbl
1729               in
1730               match contains_empty env new' with
1731               | false, _ -> 
1732                   let active =
1733                     let al, tbl = active in
1734                     match sign with
1735                     | Negative -> (sign, current)::al, tbl
1736                     | Positive ->
1737                         al @ [(sign, current)], Indexing.index tbl current
1738                   in
1739                   let passive = add_to_passive passive new' in
1740                   given_clause dbd env goals theorems passive active
1741               | true, goal ->
1742                   let proof =
1743                     match goal with
1744                     | Some goal ->
1745                         let _, proof, _, _ = goal in Some proof
1746                     | None -> None
1747                   in
1748                   ParamodulationSuccess (proof, env)
1749           )
1750 ;;
1751 *)
1752
1753 let check_if_goal_is_subsumed env (proof,menv,ty) table =
1754   match ty with
1755   | Cic.Appl[Cic.MutInd(uri,_,_);eq_ty;left;right] 
1756     when UriManager.eq uri (LibraryObjects.eq_URI ()) ->
1757       (let goal_equation = 0,proof,(eq_ty,left,right,Eq),menv in
1758       match Indexing.subsumption env table goal_equation with
1759       | Some (subst, (_,p,_,m)) ->
1760           let p = Inference.apply_subst subst (Inference.build_proof_term p) in
1761           let newp =
1762             let rec repl = function
1763               | Inference.ProofGoalBlock (_, gp) ->
1764                   Inference.ProofGoalBlock (Inference.BasicProof ([],p), gp)
1765               | Inference.NoProof -> Inference.BasicProof ([],p)
1766               | Inference.BasicProof _ -> Inference.BasicProof ([],p)
1767               | Inference.SubProof (t, i, p2) ->
1768                   Inference.SubProof (t, i, repl p2)
1769               | _ -> assert false
1770             in
1771             repl proof
1772           in
1773           Some (newp,Inference.apply_subst_metasenv subst m @ menv)
1774       | None -> None)
1775   | _ -> None
1776 ;;
1777
1778 let counter = ref 0
1779
1780 (** given-clause algorithm with full reduction strategy *)
1781 let rec given_clause_fullred dbd env goals theorems passive active =
1782 (*
1783   let table,list = active in
1784     assert (check_table list table);
1785 *)
1786   let goals = simplify_goals env goals ~passive active in 
1787   let _,context,_ = env in
1788   let ok, goals = activate_goal goals in
1789 (*   let theorems = simplify_theorems env theorems ~passive active in *)
1790   if ok then
1791     let names = List.map (HExtlib.map_option (fun (name,_) -> name)) context in 
1792     let _, _, t = List.hd (snd (List.hd (fst goals))) in
1793     let _ = prerr_endline ("goal activated = " ^ (CicPp.pp t names)) in
1794 (*     let _ = *)
1795 (*       debug_print *)
1796 (*         (lazy *)
1797 (*            (Printf.sprintf "\ngoals = \nactive\n%s\npassive\n%s\n" *)
1798 (*               (print_goals (fst goals)) (print_goals (snd goals)))); *)
1799 (*       let current = List.hd (fst goals) in *)
1800 (*       let p, _, t = List.hd (snd current) in *)
1801 (*       debug_print *)
1802 (*         (lazy *)
1803 (*            (Printf.sprintf "goal activated:\n%s\n%s\n" *)
1804 (*               (CicPp.ppterm t) (string_of_proof p))); *)
1805 (*     in *)
1806     let ok, proof =
1807       (* apply_goal_to_theorems dbd env theorems ~passive active goals in *)
1808       let iseq uri = UriManager.eq uri (LibraryObjects.eq_URI ()) in
1809       match (fst goals) with
1810         | (_, [proof, m, Cic.Appl[Cic.MutInd(uri,_,ens);eq_ty;left;right]])::_ 
1811             when left = right && iseq uri -> 
1812             let p =
1813               Cic.Appl [Cic.MutConstruct (* reflexivity *)
1814                         (LibraryObjects.eq_URI (), 0, 1, []);eq_ty; left]
1815             in
1816             let newp =
1817               let rec repl = function
1818                 | Inference.ProofGoalBlock (_, gp) ->
1819                     Inference.ProofGoalBlock (Inference.BasicProof ([],p), gp)
1820                 | Inference.NoProof -> Inference.BasicProof ([],p)
1821                 | Inference.BasicProof _ -> Inference.BasicProof ([],p)
1822                 | Inference.SubProof (t, i, p2) ->
1823                     Inference.SubProof (t, i, repl p2)
1824                 | _ -> assert false
1825               in
1826               repl proof
1827             in true, Some (newp,m)
1828         | (_, [proof,m,ty])::_ ->
1829             (match check_if_goal_is_subsumed env (proof,m,ty) (snd active) with
1830             | None -> false,None
1831             | Some (newproof,m) ->
1832                 prerr_endline "Proof found by subsumption!";
1833                 true, Some (newproof,m))
1834         | _ -> false, None
1835     in 
1836     if ok then
1837       ( prerr_endline "esco qui";
1838         let active = 
1839           List.filter test (fst active) in
1840         let s = Printf.sprintf "actives:\n%s\n"
1841           (String.concat "\n"
1842              ((List.map
1843                  (fun (s, e) -> (string_of_sign s) ^ " " ^
1844                     (string_of_equality ~env e))
1845                  active)))
1846         in prerr_endline s;
1847         let passive = 
1848           List.filter 
1849             (fun x -> test (1,x))
1850             (let x,y,_ = passive in (fst x)@(fst y)) in
1851         let p = Printf.sprintf "passives:\n%s\n"
1852           (String.concat "\n"
1853              ((List.map
1854                  (fun e -> 
1855                     (string_of_equality ~env e))
1856                  passive)))
1857         in prerr_endline p;
1858         (*
1859         let s = Printf.sprintf "actives:\n%s\n"
1860           (String.concat "\n"
1861              ((List.map
1862                  (fun (s, e) -> (string_of_sign s) ^ " " ^
1863                     (string_of_equality ~env e))
1864                  (fst active)))) in
1865         let sp = Printf.sprintf "passives:\n%s\n"
1866           (String.concat "\n"
1867              (List.map
1868                 (string_of_equality ~env)
1869                 (let x,y,_ = passive in (fst x)@(fst y)))) in
1870           prerr_endline s;
1871           prerr_endline sp; *)
1872       ParamodulationSuccess (proof))
1873     else
1874       given_clause_fullred_aux dbd env goals theorems passive active
1875   else
1876 (*     let ok', theorems = activate_theorem theorems in *)
1877 (*     if ok' then *)
1878 (*       let ok, goals = apply_theorem_to_goals env theorems active goals in *)
1879 (*       if ok then *)
1880 (*         let proof = *)
1881 (*           match (fst goals) with *)
1882 (*           | (_, [proof, _, _])::_ -> Some proof *)
1883 (*           | _ -> assert false *)
1884 (*         in *)
1885 (*         ParamodulationSuccess (proof, env) *)
1886 (*       else *)
1887 (*         given_clause_fullred_aux env goals theorems passive active *)
1888 (*     else *)
1889       if (passive_is_empty passive) then ParamodulationFailure
1890       else given_clause_fullred_aux dbd env goals theorems passive active
1891     
1892 and given_clause_fullred_aux dbd env goals theorems passive active =
1893   prerr_endline (string_of_int !counter ^ 
1894                  " MAXMETA: " ^ string_of_int !maxmeta ^ 
1895                  " LOCALMAX: " ^ string_of_int !Indexing.local_max ^
1896                  " #ACTIVES: " ^ string_of_int (size_of_active active) ^
1897                  " #PASSIVES: " ^ string_of_int (size_of_passive passive));
1898   incr counter;
1899 (*  if !counter mod 10 = 0 then
1900     begin
1901       let size = HExtlib.estimate_size (passive,active) in
1902       let sizep = HExtlib.estimate_size (passive) in
1903       let sizea = HExtlib.estimate_size (active) in
1904       let (l1,s1),(l2,s2), t = passive in 
1905       let sizetbl = HExtlib.estimate_size t in
1906       let sizel = HExtlib.estimate_size (l1,l2) in
1907       let sizes = HExtlib.estimate_size (s1,s2) in
1908
1909       prerr_endline ("SIZE: " ^ string_of_int size);        
1910       prerr_endline ("SIZE P: " ^ string_of_int sizep);        
1911       prerr_endline ("SIZE A: " ^ string_of_int sizea);        
1912       prerr_endline ("SIZE TBL: " ^ string_of_int sizetbl ^ 
1913                        " SIZE L: " ^ string_of_int sizel ^ 
1914                        " SIZE S:" ^ string_of_int sizes);
1915     end;*)
1916 (*
1917   if (size_of_active active) mod 50 = 0 then
1918     (let s = Printf.sprintf "actives:\n%s\n"
1919       (String.concat "\n"
1920          ((List.map
1921              (fun (s, e) -> (string_of_sign s) ^ " " ^
1922                 (string_of_equality ~env e))
1923              (fst active)))) in
1924      let sp = Printf.sprintf "passives:\n%s\n"
1925       (String.concat "\n"
1926          (List.map
1927              (string_of_equality ~env)
1928              (let x,y,_ = passive in (fst x)@(fst y)))) in
1929       prerr_endline s;
1930       prerr_endline sp); *)
1931   let time1 = Unix.gettimeofday () in
1932   let (_,context,_) = env in
1933   let selection_estimate = get_selection_estimate () in
1934   let kept = size_of_passive passive in
1935   let passive =
1936     if !time_limit = 0. || !processed_clauses = 0 then
1937       passive
1938     else if !elapsed_time > !time_limit then (
1939       debug_print (lazy (Printf.sprintf "Time limit (%.2f) reached: %.2f\n"
1940                            !time_limit !elapsed_time));
1941       make_passive [] []
1942     ) else if kept > selection_estimate then (
1943       debug_print
1944         (lazy (Printf.sprintf ("Too many passive equalities: pruning..." ^^
1945                                  "(kept: %d, selection_estimate: %d)\n")
1946                  kept selection_estimate));
1947       prune_passive selection_estimate active passive
1948     ) else
1949       passive
1950   in
1951
1952   let time2 = Unix.gettimeofday () in
1953   passive_maintainance_time := !passive_maintainance_time +. (time2 -. time1);
1954   
1955   kept_clauses := (size_of_passive passive) + (size_of_active active);
1956   match passive_is_empty passive with
1957   | true -> (* ParamodulationFailure *)
1958       given_clause_fullred dbd env goals theorems passive active        
1959   | false ->
1960       let (sign, current), passive = select env (fst goals) passive active in
1961       prerr_endline 
1962         ("Selected = " ^ (string_of_sign sign) ^ " " ^ 
1963            string_of_equality ~env current);
1964 (* ^ 
1965            (let w,p,(t,l,r,o),m = current in
1966            " size w: " ^ string_of_int (HExtlib.estimate_size w)^
1967            " size p: " ^ string_of_int (HExtlib.estimate_size p)^
1968            " size t: " ^ string_of_int (HExtlib.estimate_size t)^
1969            " size l: " ^ string_of_int (HExtlib.estimate_size l)^
1970            " size r: " ^ string_of_int (HExtlib.estimate_size r)^
1971            " size o: " ^ string_of_int (HExtlib.estimate_size o)^
1972            " size m: " ^ string_of_int (HExtlib.estimate_size m)^
1973            " size m-c: " ^ string_of_int 
1974              (HExtlib.estimate_size (List.map (fun (x,_,_) -> x) m)))) *)
1975       let time1 = Unix.gettimeofday () in
1976       let res = forward_simplify env (sign, current) ~passive active in
1977       let time2 = Unix.gettimeofday () in
1978       forward_simpl_time := !forward_simpl_time +. (time2 -. time1);
1979       match res with
1980       | None ->
1981           (* weight_age_counter := !weight_age_counter + 1; *)
1982           given_clause_fullred dbd env goals theorems passive active
1983       | Some (sign, current) ->
1984           if test (sign, current) then
1985             (prerr_endline 
1986               ("Simplified = " ^ (string_of_sign sign) ^ " " ^ 
1987              string_of_equality ~env current);
1988              let active = fst active in
1989              let s = Printf.sprintf "actives:\n%s\n"
1990                (String.concat "\n"
1991              ((List.map
1992                  (fun (s, e) -> (string_of_sign s) ^ " " ^
1993                     (string_of_equality ~env e))
1994                  active)))
1995              in prerr_endline s;
1996                assert false);
1997           if (sign = Negative) && (is_identity env current) then (
1998             debug_print
1999               (lazy (Printf.sprintf "OK!!! %s %s" (string_of_sign sign)
2000                        (string_of_equality ~env current)));
2001             let _, proof, _, m = current in 
2002             ParamodulationSuccess (Some (proof, m))
2003           ) else (
2004             debug_print
2005               (lazy "\n================================================");
2006             debug_print (lazy (Printf.sprintf "selected: %s %s"
2007                                  (string_of_sign sign)
2008                                  (string_of_equality ~env current)));
2009
2010             let t1 = Unix.gettimeofday () in
2011             let new' = infer env sign current active in
2012             let _ =
2013               match new' with
2014               | neg, pos ->
2015                   debug_print
2016                     (lazy
2017                        (Printf.sprintf "new' (senza semplificare):\n%s\n"
2018                           (String.concat "\n"
2019                              ((List.map
2020                                  (fun e -> "Negative " ^
2021                                     (string_of_equality ~env e)) neg) @
2022                                 (List.map
2023                                    (fun e -> "Positive " ^
2024                                       (string_of_equality ~env e)) pos)))))
2025             in
2026             let t2 = Unix.gettimeofday () in
2027             infer_time := !infer_time +. (t2 -. t1);
2028             let active =
2029               if is_identity env current then active
2030               else
2031                 let al, tbl = active in
2032                 match sign with
2033                 | Negative -> (sign, current)::al, tbl
2034                 | Positive ->
2035                     al @ [(sign, current)], Indexing.index tbl current
2036             in
2037             let rec simplify new' active passive =
2038               let t1 = Unix.gettimeofday () in
2039               let new' = forward_simplify_new env new'~passive active in
2040               let t2 = Unix.gettimeofday () in
2041               forward_simpl_new_time :=
2042                 !forward_simpl_new_time +. (t2 -. t1);
2043               let t1 = Unix.gettimeofday () in
2044               let active, passive, newa, retained =
2045                 backward_simplify env new' ~passive  active in
2046               
2047               let t2 = Unix.gettimeofday () in
2048                 backward_simpl_time := !backward_simpl_time +. (t2 -. t1);
2049               match newa, retained with
2050               | None, None -> active, passive, new'
2051               | Some (n, p), None
2052               | None, Some (n, p) ->
2053                   let nn, np = new' in
2054                     if Utils.debug_metas then
2055                       begin
2056                         List.iter 
2057                           (fun x->Indexing.check_target context x "simplify1")
2058                           n;
2059                         List.iter 
2060                           (fun x->Indexing.check_target context x "simplify2")
2061                           p
2062                       end;
2063                     simplify (nn @ n, np @ p) active passive
2064               | Some (n, p), Some (rn, rp) ->
2065                   let nn, np = new' in
2066                   simplify (nn @ n @ rn, np @ p @ rp) active passive
2067             in
2068             let active, _, new' = simplify new' active passive in
2069 (* pessima prova 
2070             let new1 = prova env new' active in
2071             let new' = (fst new') @ (fst new1), (snd new') @ (snd new1) in
2072             let _ =
2073               match new1 with
2074               | neg, pos ->
2075                   debug_print
2076                     (lazy
2077                        (Printf.sprintf "new1:\n%s\n"
2078                           (String.concat "\n"
2079                              ((List.map
2080                                  (fun e -> "Negative " ^
2081                                     (string_of_equality ~env e)) neg) @
2082                                 (List.map
2083                                    (fun e -> "Positive " ^
2084                                       (string_of_equality ~env e)) pos)))))
2085             in
2086 end prova *)
2087             let k = size_of_passive passive in
2088             if k < (kept - 1) then
2089               processed_clauses := !processed_clauses + (kept - 1 - k);
2090             
2091             let _ =
2092               debug_print
2093                 (lazy
2094                    (Printf.sprintf "active:\n%s\n"
2095                       (String.concat "\n"
2096                          ((List.map
2097                              (fun (s, e) -> (string_of_sign s) ^ " " ^
2098                                 (string_of_equality ~env e))
2099                              (fst active))))))
2100             in
2101             let _ =
2102               match new' with
2103               | neg, pos ->
2104                   debug_print
2105                     (lazy
2106                        (Printf.sprintf "new':\n%s\n"
2107                           (String.concat "\n"
2108                              ((List.map
2109                                  (fun e -> "Negative " ^
2110                                     (string_of_equality ~env e)) neg) @
2111                                 (List.map
2112                                    (fun e -> "Positive " ^
2113                                       (string_of_equality ~env e)) pos)))))
2114             in
2115             match contains_empty env new' with
2116             | false, _ -> 
2117                 let passive = add_to_passive passive new' in
2118                 given_clause_fullred dbd env goals theorems passive active
2119             | true, goal ->
2120                 let proof =
2121                   match goal with
2122                   | Some goal -> let _, proof, _, env = goal in Some (proof,env)
2123                   | None -> None
2124                 in
2125                 ParamodulationSuccess proof
2126           )
2127   
2128 ;;
2129
2130 let profiler0 = HExtlib.profile "P/Saturation.given_clause_fullred"
2131
2132 let given_clause_fullred dbd env goals theorems passive active =
2133   profiler0.HExtlib.profile 
2134     (given_clause_fullred dbd env goals theorems passive) active
2135   
2136
2137 let rec saturate_equations env goal accept_fun passive active =
2138   elapsed_time := Unix.gettimeofday () -. !start_time;
2139   if !elapsed_time > !time_limit then
2140     (active, passive)
2141   else
2142     let (sign, current), passive = select env [1, [goal]] passive active in
2143     let res = forward_simplify env (sign, current) ~passive active in
2144     match res with
2145     | None ->
2146         saturate_equations env goal accept_fun passive active
2147     | Some (sign, current) ->
2148         assert (sign = Positive);
2149         debug_print
2150           (lazy "\n================================================");
2151         debug_print (lazy (Printf.sprintf "selected: %s %s"
2152                              (string_of_sign sign)
2153                              (string_of_equality ~env current)));
2154         let new' = infer env sign current active in
2155         let active =
2156           if is_identity env current then active
2157           else
2158             let al, tbl = active in
2159             al @ [(sign, current)], Indexing.index tbl current
2160         in
2161         let rec simplify new' active passive =
2162           let new' = forward_simplify_new env new' ~passive active in
2163           let active, passive, newa, retained =
2164             backward_simplify env new' ~passive active in
2165           match newa, retained with
2166           | None, None -> active, passive, new'
2167           | Some (n, p), None
2168           | None, Some (n, p) ->
2169               let nn, np = new' in
2170               simplify (nn @ n, np @ p) active passive
2171           | Some (n, p), Some (rn, rp) ->
2172               let nn, np = new' in
2173               simplify (nn @ n @ rn, np @ p @ rp) active passive
2174         in
2175         let active, passive, new' = simplify new' active passive in
2176         let _ =
2177           debug_print
2178             (lazy
2179                (Printf.sprintf "active:\n%s\n"
2180                   (String.concat "\n"
2181                      ((List.map
2182                          (fun (s, e) -> (string_of_sign s) ^ " " ^
2183                             (string_of_equality ~env e))
2184                          (fst active))))))
2185         in
2186         let _ =
2187           match new' with
2188           | neg, pos ->
2189               debug_print
2190                 (lazy
2191                    (Printf.sprintf "new':\n%s\n"
2192                       (String.concat "\n"
2193                          ((List.map
2194                              (fun e -> "Negative " ^
2195                                 (string_of_equality ~env e)) neg) @
2196                             (List.map
2197                                (fun e -> "Positive " ^
2198                                   (string_of_equality ~env e)) pos)))))
2199         in
2200         let new' = match new' with _, pos -> [], List.filter accept_fun pos in
2201         let passive = add_to_passive passive new' in
2202         saturate_equations env goal accept_fun passive active
2203 ;;
2204   
2205
2206
2207
2208 let main dbd full term metasenv ugraph =
2209   let module C = Cic in
2210   let module T = CicTypeChecker in
2211   let module PET = ProofEngineTypes in
2212   let module PP = CicPp in
2213   let proof = None, (1, [], term)::metasenv, C.Meta (1, []), term in
2214   let status = PET.apply_tactic (PrimitiveTactics.intros_tac ()) (proof, 1) in
2215   let proof, goals = status in
2216   let goal' = List.nth goals 0 in
2217   let _, metasenv, meta_proof, _ = proof in
2218   let _, context, goal = CicUtil.lookup_meta goal' metasenv in
2219   let eq_indexes, equalities, maxm = find_equalities context proof in
2220   let lib_eq_uris, library_equalities, maxm =
2221
2222     find_library_equalities dbd context (proof, goal') (maxm+2)
2223   in
2224   let library_equalities = List.map snd library_equalities in
2225   maxmeta := maxm+2; (* TODO ugly!! *)
2226   let irl = CicMkImplicit.identity_relocation_list_for_metavariable context in
2227   let new_meta_goal, metasenv, type_of_goal =
2228     let _, context, ty = CicUtil.lookup_meta goal' metasenv in
2229     debug_print
2230       (lazy
2231          (Printf.sprintf "\n\nTIPO DEL GOAL: %s\n\n" (CicPp.ppterm ty)));
2232     Cic.Meta (maxm+1, irl),
2233     (maxm+1, context, ty)::metasenv,
2234     ty
2235   in
2236   let env = (metasenv, context, ugraph) in
2237   let t1 = Unix.gettimeofday () in
2238   let theorems =
2239     if full then
2240       let theorems = find_library_theorems dbd env (proof, goal') lib_eq_uris in
2241       let context_hyp = find_context_hypotheses env eq_indexes in
2242       context_hyp @ theorems, []
2243     else
2244       let refl_equal =
2245         let us = UriManager.string_of_uri (LibraryObjects.eq_URI ()) in
2246         UriManager.uri_of_string (us ^ "#xpointer(1/1/1)")
2247       in
2248       let t = CicUtil.term_of_uri refl_equal in
2249       let ty, _ = CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in
2250       [(t, ty, [])], []
2251   in
2252   let t2 = Unix.gettimeofday () in
2253   debug_print
2254     (lazy
2255        (Printf.sprintf "Time to retrieve theorems: %.9f\n" (t2 -. t1)));
2256   let _ =
2257     debug_print
2258       (lazy
2259          (Printf.sprintf
2260             "Theorems:\n-------------------------------------\n%s\n"
2261             (String.concat "\n"
2262                (List.map
2263                   (fun (t, ty, _) ->
2264                      Printf.sprintf
2265                        "Term: %s, type: %s" (CicPp.ppterm t) (CicPp.ppterm ty))
2266                   (fst theorems)))))
2267   in
2268   (*try*)
2269     let goal = Inference.BasicProof ([],new_meta_goal), [], goal in
2270     let equalities = simplify_equalities env 
2271       (equalities@library_equalities) in 
2272     let active = make_active () in
2273     let passive = make_passive [] equalities in
2274     Printf.printf "\ncurrent goal: %s\n"
2275       (let _, _, g = goal in CicPp.ppterm g);
2276     Printf.printf "\ncontext:\n%s\n" (PP.ppcontext context);
2277     Printf.printf "\nmetasenv:\n%s\n" (print_metasenv metasenv);
2278     Printf.printf "\nequalities:\n%s\n"
2279       (String.concat "\n"
2280          (List.map
2281             (string_of_equality ~env) equalities));
2282 (*             (equalities @ library_equalities))); *)
2283       print_endline "--------------------------------------------------";
2284       let start = Unix.gettimeofday () in
2285       print_endline "GO!";
2286       start_time := Unix.gettimeofday ();
2287       let res =
2288         let goals = make_goals goal in
2289         (if !use_fullred then given_clause_fullred else given_clause_fullred)
2290           dbd env goals theorems passive active
2291       in
2292       let finish = Unix.gettimeofday () in
2293       let _ =
2294         match res with
2295         | ParamodulationFailure ->
2296             Printf.printf "NO proof found! :-(\n\n"
2297         | ParamodulationSuccess (Some (proof, env)) ->
2298             let proof = Inference.build_proof_term proof in
2299             Printf.printf "OK, found a proof!\n";
2300             (* REMEMBER: we have to instantiate meta_proof, we should use
2301                apply  the "apply" tactic to proof and status 
2302             *)
2303             let names = names_of_context context in
2304             print_endline (PP.pp proof names);
2305             let newmetasenv =
2306               List.fold_left
2307                 (fun m (_, _, _, menv) -> m @ menv) metasenv equalities
2308             in
2309             let _ =
2310               (*try*)
2311                 let ty, ug =
2312                   CicTypeChecker.type_of_aux' newmetasenv context proof ugraph
2313                 in
2314                 print_endline (string_of_float (finish -. start));
2315                 Printf.printf
2316                   "\nGOAL was: %s\nPROOF has type: %s\nconvertible?: %s\n\n"
2317                   (CicPp.pp type_of_goal names) (CicPp.pp ty names)
2318                   (string_of_bool
2319                      (fst (CicReduction.are_convertible
2320                              context type_of_goal ty ug)));
2321               (*with e ->
2322                 Printf.printf "\nEXCEPTION!!! %s\n" (Printexc.to_string e);
2323                 Printf.printf "MAXMETA USED: %d\n" !maxmeta;
2324                 print_endline (string_of_float (finish -. start));*)
2325             in
2326             ()
2327               
2328         | ParamodulationSuccess None ->
2329             Printf.printf "Success, but no proof?!?\n\n"
2330       in
2331         if Utils.time then
2332           begin
2333             prerr_endline 
2334               ((Printf.sprintf ("infer_time: %.9f\nforward_simpl_time: %.9f\n" ^^
2335                        "forward_simpl_new_time: %.9f\n" ^^
2336                        "backward_simpl_time: %.9f\n")
2337               !infer_time !forward_simpl_time !forward_simpl_new_time
2338               !backward_simpl_time) ^
2339               (Printf.sprintf "beta_expand_time: %.9f\n"
2340                  !Indexing.beta_expand_time) ^
2341               (Printf.sprintf "passive_maintainance_time: %.9f\n"
2342                  !passive_maintainance_time) ^
2343               (Printf.sprintf "    successful unification/matching time: %.9f\n"
2344                  !Indexing.match_unif_time_ok) ^
2345               (Printf.sprintf "    failed unification/matching time: %.9f\n"
2346                  !Indexing.match_unif_time_no) ^
2347               (Printf.sprintf "    indexing retrieval time: %.9f\n"
2348                  !Indexing.indexing_retrieval_time) ^
2349               (Printf.sprintf "    demodulate_term.build_newtarget_time: %.9f\n"
2350                  !Indexing.build_newtarget_time) ^
2351               (Printf.sprintf "derived %d clauses, kept %d clauses.\n"
2352                  !derived_clauses !kept_clauses)) 
2353             end
2354 (*
2355   with exc ->
2356     print_endline ("EXCEPTION: " ^ (Printexc.to_string exc));
2357     raise exc
2358 *)
2359 ;;
2360
2361
2362 let default_depth = !maxdepth
2363 and default_width = !maxwidth;;
2364
2365 let reset_refs () =
2366   maxmeta := 0;
2367   Indexing.local_max := 100;
2368   symbols_counter := 0;
2369   weight_age_counter := !weight_age_ratio;
2370   processed_clauses := 0;
2371   start_time := 0.;
2372   elapsed_time := 0.;
2373   maximal_retained_equality := None;
2374   infer_time := 0.;
2375   forward_simpl_time := 0.;
2376   forward_simpl_new_time := 0.;
2377   backward_simpl_time := 0.;
2378   passive_maintainance_time := 0.;
2379   derived_clauses := 0;
2380   kept_clauses := 0;
2381   Indexing.beta_expand_time := 0.;
2382   Inference.metas_of_proof_time := 0.;
2383 ;;
2384
2385 let saturate 
2386     dbd ?(full=false) ?(depth=default_depth) ?(width=default_width) status = 
2387   let module C = Cic in
2388   reset_refs ();
2389   Indexing.init_index ();
2390   counter := 0;
2391   maxdepth := depth;
2392   maxwidth := width;
2393 (*  CicUnification.unif_ty := false;*)
2394   let proof, goal = status in
2395   let goal' = goal in
2396   let uri, metasenv, meta_proof, term_to_prove = proof in
2397   let _, context, goal = CicUtil.lookup_meta goal' metasenv in
2398   prerr_endline ("CTX: " ^ string_of_int (HExtlib.estimate_size context));
2399   let eq_indexes, equalities, maxm = find_equalities context proof in
2400   let new_meta_goal, metasenv, type_of_goal =
2401     let irl =
2402       CicMkImplicit.identity_relocation_list_for_metavariable context in
2403     let _, context, ty = CicUtil.lookup_meta goal' metasenv in
2404     debug_print
2405       (lazy (Printf.sprintf "\n\nTIPO DEL GOAL: %s\n" (CicPp.ppterm ty)));
2406     Cic.Meta (maxm+1, irl),
2407     (maxm+1, context, ty)::metasenv,
2408     ty
2409   in
2410   let ugraph = CicUniv.empty_ugraph in
2411   let env = (metasenv, context, ugraph) in 
2412   let goal = Inference.BasicProof ([],new_meta_goal), [], goal in
2413   let res, time =
2414     let t1 = Unix.gettimeofday () in
2415     let lib_eq_uris, library_equalities, maxm =
2416       find_library_equalities dbd context (proof, goal') (maxm+2)
2417     in
2418     let library_equalities = List.map snd library_equalities in
2419     let t2 = Unix.gettimeofday () in
2420     maxmeta := maxm+2;
2421     let equalities = simplify_equalities env (equalities@library_equalities) in 
2422     debug_print
2423       (lazy
2424          (Printf.sprintf "Time to retrieve equalities: %.9f\n" (t2 -. t1)));
2425     let t1 = Unix.gettimeofday () in
2426     let theorems =
2427       if full then
2428         let thms = find_library_theorems dbd env (proof, goal') lib_eq_uris in
2429         let context_hyp = find_context_hypotheses env eq_indexes in
2430         context_hyp @ thms, []
2431       else
2432         let refl_equal =
2433           let us = UriManager.string_of_uri (LibraryObjects.eq_URI ()) in
2434           UriManager.uri_of_string (us ^ "#xpointer(1/1/1)")
2435         in
2436         let t = CicUtil.term_of_uri refl_equal in
2437         let ty, _ = CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in
2438         [(t, ty, [])], []
2439     in
2440     let t2 = Unix.gettimeofday () in
2441     let _ =
2442       debug_print
2443         (lazy
2444            (Printf.sprintf
2445               "Theorems:\n-------------------------------------\n%s\n"
2446               (String.concat "\n"
2447                  (List.map
2448                     (fun (t, ty, _) ->
2449                        Printf.sprintf
2450                          "Term: %s, type: %s"
2451                          (CicPp.ppterm t) (CicPp.ppterm ty))
2452                     (fst theorems)))));
2453       debug_print
2454         (lazy
2455            (Printf.sprintf "Time to retrieve theorems: %.9f\n" (t2 -. t1)));
2456     in
2457     let active = make_active () in
2458     let passive = make_passive [] equalities in
2459     let start = Unix.gettimeofday () in
2460     let res =
2461       let goals = make_goals goal in
2462       given_clause_fullred dbd env goals theorems passive active
2463     in
2464     let finish = Unix.gettimeofday () in
2465     (res, finish -. start)
2466   in
2467   match res with
2468   | ParamodulationSuccess (Some (proof, proof_menv)) ->
2469       debug_print (lazy "OK, found a proof!");
2470       let proof = Inference.build_proof_term proof in
2471       let equality_for_replace i t1 =
2472         match t1 with
2473         | C.Meta (n, _) -> n = i
2474         | _ -> false
2475       in
2476       let proof_menv, what, with_what = 
2477         let irl = 
2478           CicMkImplicit.identity_relocation_list_for_metavariable context
2479         in
2480         List.fold_left 
2481           (fun (acc1,acc2,acc3) (i,_,ty) -> 
2482             (i,context,ty)::acc1, 
2483             (Cic.Meta(i,[]))::acc2, 
2484             (Cic.Meta(i,irl)) ::acc3) 
2485           ([],[],[]) proof_menv 
2486       in
2487       let proof = ProofEngineReduction.replace_lifting
2488               ~equality:(=)
2489               ~what ~with_what
2490               ~where:proof
2491       in
2492       (* prerr_endline (CicPp.ppterm proof); *)
2493       let names = names_of_context context in
2494       let newmetasenv =
2495         let i1 =
2496           match new_meta_goal with
2497           | C.Meta (i, _) -> i | _ -> assert false
2498         in
2499         List.filter (fun (i, _, _) -> i <> i1 && i <> goal') metasenv
2500       in
2501       let newmetasenv = newmetasenv@proof_menv in
2502       let newstatus =
2503         try
2504           let ty, ug =
2505             CicTypeChecker.type_of_aux' newmetasenv context proof ugraph
2506           in
2507           debug_print (lazy (CicPp.pp proof [](* names *)));
2508           debug_print
2509             (lazy
2510                (Printf.sprintf
2511                   "\nGOAL was: %s\nPROOF has type: %s\nconvertible?: %s\n"
2512                   (CicPp.pp type_of_goal names) (CicPp.pp ty names)
2513                   (string_of_bool
2514                      (fst (CicReduction.are_convertible
2515                              context type_of_goal ty ug)))));
2516           let real_proof =
2517             ProofEngineReduction.replace
2518               ~equality:equality_for_replace
2519               ~what:[goal'] ~with_what:[proof]
2520               ~where:meta_proof
2521           in
2522           debug_print
2523             (lazy
2524                (Printf.sprintf "status:\n%s\n%s\n%s\n%s\n"
2525                   (match uri with Some uri -> UriManager.string_of_uri uri
2526                    | None -> "")
2527                   (print_metasenv newmetasenv)
2528                   (CicPp.pp real_proof [](* names *))
2529                   (CicPp.pp term_to_prove names)));
2530           ((uri, newmetasenv, real_proof, term_to_prove), 
2531             List.map (fun (i,_,_) -> i) proof_menv)
2532         with CicTypeChecker.TypeCheckerFailure _ ->
2533           debug_print (lazy "THE PROOF DOESN'T TYPECHECK!!!");
2534           debug_print (lazy (CicPp.pp proof names));
2535           raise (ProofEngineTypes.Fail
2536                   (lazy "Found a proof, but it doesn't typecheck"))
2537       in
2538       let tall = fs_time_info.build_all in
2539       let tdemodulate = fs_time_info.demodulate in
2540       let tsubsumption = fs_time_info.subsumption in
2541       if Utils.time then
2542         begin
2543           prerr_endline (
2544             (Printf.sprintf "\nTIME NEEDED: %.9f" time) ^
2545               (Printf.sprintf "\ntall: %.9f" tall) ^
2546               (Printf.sprintf "\ntdemod: %.9f" tdemodulate) ^
2547               (Printf.sprintf "\ntsubsumption: %.9f" tsubsumption) ^
2548               (Printf.sprintf "\ninfer_time: %.9f" !infer_time) ^
2549               (Printf.sprintf "\nbeta_expand_time: %.9f\n"
2550                  !Indexing.beta_expand_time) ^
2551               (Printf.sprintf "\nmetas_of_proof: %.9f\n"
2552                  !Inference.metas_of_proof_time) ^
2553               (Printf.sprintf "\nforward_simpl_times: %.9f" !forward_simpl_time) ^
2554               (Printf.sprintf "\nforward_simpl_new_times: %.9f" 
2555                  !forward_simpl_new_time) ^
2556               (Printf.sprintf "\nbackward_simpl_times: %.9f" !backward_simpl_time) ^
2557               (Printf.sprintf "\npassive_maintainance_time: %.9f" 
2558                  !passive_maintainance_time))
2559         end;
2560       newstatus          
2561   | _ ->
2562       raise (ProofEngineTypes.Fail (lazy "NO proof found"))
2563 ;;
2564
2565 (* dummy function called within matita to trigger linkage *)
2566 let init () = ();;
2567
2568
2569 let retrieve_and_print dbd term metasenv ugraph = 
2570   let module C = Cic in
2571   let module T = CicTypeChecker in
2572   let module PET = ProofEngineTypes in
2573   let module PP = CicPp in
2574   let proof = None, (1, [], term)::metasenv, C.Meta (1, []), term in
2575   let status = PET.apply_tactic (PrimitiveTactics.intros_tac ()) (proof, 1) in
2576   let proof, goals = status in
2577   let goal' = List.nth goals 0 in
2578   let uri, metasenv, meta_proof, term_to_prove = proof in
2579   let _, context, goal = CicUtil.lookup_meta goal' metasenv in
2580   let eq_indexes, equalities, maxm = find_equalities context proof in
2581   let new_meta_goal, metasenv, type_of_goal =
2582     let irl =
2583       CicMkImplicit.identity_relocation_list_for_metavariable context in
2584     let _, context, ty = CicUtil.lookup_meta goal' metasenv in
2585     debug_print
2586       (lazy (Printf.sprintf "\n\nTIPO DEL GOAL: %s\n" (CicPp.ppterm ty)));
2587     Cic.Meta (maxm+1, irl),
2588     (maxm+1, context, ty)::metasenv,
2589     ty
2590   in
2591   let ugraph = CicUniv.empty_ugraph in
2592   let env = (metasenv, context, ugraph) in
2593   let t1 = Unix.gettimeofday () in
2594   let lib_eq_uris, library_equalities, maxm =
2595     find_library_equalities dbd context (proof, goal') (maxm+2) in
2596   let t2 = Unix.gettimeofday () in
2597   maxmeta := maxm+2;
2598   let equalities = (* equalities @ *) library_equalities in
2599   debug_print
2600      (lazy
2601         (Printf.sprintf "\n\nequalities:\n%s\n"
2602            (String.concat "\n"
2603               (List.map 
2604           (fun (u, e) ->
2605 (*                  Printf.sprintf "%s: %s" *)
2606                    (UriManager.string_of_uri u)
2607 (*                    (string_of_equality e) *)
2608                      )
2609           equalities))));
2610   debug_print (lazy "RETR: SIMPLYFYING EQUALITIES...");
2611   let rec simpl e others others_simpl =
2612     let (u, e) = e in
2613     let active = List.map (fun (u, e) -> (Positive, e))
2614       (others @ others_simpl) in
2615     let tbl =
2616       List.fold_left
2617         (fun t (_, e) -> Indexing.index t e)
2618         Indexing.empty active
2619     in
2620     let res = forward_simplify env (Positive, e) (active, tbl) in
2621     match others with
2622         | hd::tl -> (
2623             match res with
2624               | None -> simpl hd tl others_simpl
2625               | Some e -> simpl hd tl ((u, (snd e))::others_simpl)
2626           )
2627         | [] -> (
2628             match res with
2629               | None -> others_simpl
2630               | Some e -> (u, (snd e))::others_simpl
2631           ) 
2632   in
2633   let _equalities =
2634     match equalities with
2635       | [] -> []
2636       | hd::tl ->
2637           let others = tl in (* List.map (fun e -> (Positive, e)) tl in *)
2638           let res =
2639             List.rev (simpl (*(Positive,*) hd others [])
2640           in
2641             debug_print
2642               (lazy
2643                  (Printf.sprintf "\nequalities AFTER:\n%s\n"
2644                     (String.concat "\n"
2645                        (List.map
2646                           (fun (u, e) ->
2647                              Printf.sprintf "%s: %s"
2648                                (UriManager.string_of_uri u)
2649                                (string_of_equality e)
2650                           )
2651                           res))));
2652             res in
2653     debug_print
2654       (lazy
2655          (Printf.sprintf "Time to retrieve equalities: %.9f\n" (t2 -. t1)))
2656 ;;
2657
2658
2659 let main_demod_equalities dbd term metasenv ugraph =
2660   let module C = Cic in
2661   let module T = CicTypeChecker in
2662   let module PET = ProofEngineTypes in
2663   let module PP = CicPp in
2664   let proof = None, (1, [], term)::metasenv, C.Meta (1, []), term in
2665   let status = PET.apply_tactic (PrimitiveTactics.intros_tac ()) (proof, 1) in
2666   let proof, goals = status in
2667   let goal' = List.nth goals 0 in
2668   let _, metasenv, meta_proof, _ = proof in
2669   let _, context, goal = CicUtil.lookup_meta goal' metasenv in
2670   let eq_indexes, equalities, maxm = find_equalities context proof in
2671   let lib_eq_uris, library_equalities, maxm =
2672     find_library_equalities dbd context (proof, goal') (maxm+2)
2673   in
2674   let library_equalities = List.map snd library_equalities in
2675   maxmeta := maxm+2; (* TODO ugly!! *)
2676   let irl = CicMkImplicit.identity_relocation_list_for_metavariable context in
2677   let new_meta_goal, metasenv, type_of_goal =
2678     let _, context, ty = CicUtil.lookup_meta goal' metasenv in
2679     debug_print
2680       (lazy
2681          (Printf.sprintf "\n\nTRYING TO INFER EQUALITIES MATCHING: %s\n\n"
2682             (CicPp.ppterm ty)));
2683     Cic.Meta (maxm+1, irl),
2684     (maxm+1, context, ty)::metasenv,
2685     ty
2686   in
2687   let env = (metasenv, context, ugraph) in
2688   (*try*)
2689     let goal = Inference.BasicProof ([],new_meta_goal), [], goal in
2690     let equalities = simplify_equalities env (equalities@library_equalities) in
2691     let active = make_active () in
2692     let passive = make_passive [] equalities in
2693     Printf.printf "\ncontext:\n%s\n" (PP.ppcontext context);
2694     Printf.printf "\nmetasenv:\n%s\n" (print_metasenv metasenv);
2695     Printf.printf "\nequalities:\n%s\n"
2696       (String.concat "\n"
2697          (List.map
2698             (string_of_equality ~env) equalities));
2699     print_endline "--------------------------------------------------";
2700     print_endline "GO!";
2701     start_time := Unix.gettimeofday ();
2702     if !time_limit < 1. then time_limit := 60.;    
2703     let ra, rp =
2704       saturate_equations env goal (fun e -> true) passive active
2705     in
2706
2707     let initial =
2708       List.fold_left (fun s e -> EqualitySet.add e s)
2709         EqualitySet.empty equalities
2710     in
2711     let addfun s e = 
2712       if not (EqualitySet.mem e initial) then EqualitySet.add e s else s
2713     in
2714
2715     let passive =
2716       match rp with
2717       | (n, _), (p, _), _ ->
2718           EqualitySet.elements (List.fold_left addfun EqualitySet.empty p)
2719     in
2720     let active =
2721       let l = List.map snd (fst ra) in
2722       EqualitySet.elements (List.fold_left addfun EqualitySet.empty l)
2723     in
2724     Printf.printf "\n\nRESULTS:\nActive:\n%s\n\nPassive:\n%s\n"
2725        (String.concat "\n" (List.map (string_of_equality ~env) active)) 
2726      (*  (String.concat "\n"
2727          (List.map (fun e -> CicPp.ppterm (term_of_equality e)) active)) *)
2728 (*       (String.concat "\n" (List.map (string_of_equality ~env) passive)); *)
2729       (String.concat "\n"
2730          (List.map (fun e -> CicPp.ppterm (term_of_equality e)) passive));
2731     print_newline ();
2732 (*
2733   with e ->
2734     debug_print (lazy ("EXCEPTION: " ^ (Printexc.to_string e)))
2735 *)
2736 ;;
2737
2738 let demodulate_tac ~dbd ~pattern ((proof,goal) as initialstatus) = 
2739   let module I = Inference in
2740   let curi,metasenv,pbo,pty = proof in
2741   let metano,context,ty = CicUtil.lookup_meta goal metasenv in
2742   let eq_indexes, equalities, maxm = I.find_equalities context proof in
2743   let lib_eq_uris, library_equalities, maxm =
2744     I.find_library_equalities dbd context (proof, goal) (maxm+2) in
2745   if library_equalities = [] then prerr_endline "VUOTA!!!";
2746   let irl = CicMkImplicit.identity_relocation_list_for_metavariable context in
2747   let library_equalities = List.map snd library_equalities in
2748   let goalterm = Cic.Meta (metano,irl) in
2749   let initgoal = Inference.BasicProof ([],goalterm), [], ty in
2750   let env = (metasenv, context, CicUniv.empty_ugraph) in
2751   let equalities = simplify_equalities env (equalities@library_equalities) in   
2752   let table = 
2753     List.fold_left 
2754       (fun tbl eq -> Indexing.index tbl eq) 
2755       Indexing.empty equalities 
2756   in
2757   let newmeta,(newproof,newmetasenv, newty) = Indexing.demodulation_goal 
2758     maxm (metasenv,context,CicUniv.empty_ugraph) table initgoal 
2759   in
2760   if newmeta != maxm then
2761     begin
2762       let opengoal = Cic.Meta(maxm,irl) in
2763       let proofterm = 
2764         Inference.build_proof_term ~noproof:opengoal newproof in
2765         let extended_metasenv = (maxm,context,newty)::metasenv in
2766         let extended_status = 
2767           (curi,extended_metasenv,pbo,pty),goal in
2768         let (status,newgoals) = 
2769           ProofEngineTypes.apply_tactic 
2770             (PrimitiveTactics.apply_tac ~term:proofterm)
2771             extended_status in
2772         (status,maxm::newgoals)
2773     end
2774   else if newty = ty then
2775     raise (ProofEngineTypes.Fail (lazy "no progress"))
2776   else ProofEngineTypes.apply_tactic 
2777     (ReductionTactics.simpl_tac ~pattern) 
2778     initialstatus
2779 ;;
2780
2781 let demodulate_tac ~dbd ~pattern = 
2782   ProofEngineTypes.mk_tactic (demodulate_tac ~dbd ~pattern)
2783 ;;