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