]> matita.cs.unibo.it Git - helm.git/blob - components/tactics/paramodulation/saturation.ml
matitaprover
[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 -> Indexing.index t e)
749       Indexing.empty active
750   in
751   let res = forward_simplify eq_uri env e (active, tbl) in
752     match others with
753       | hd::tl -> (
754           match res with
755             | None -> simpl eq_uri env hd tl others_simpl
756             | Some e -> simpl eq_uri env hd tl (e::others_simpl)
757         )
758       | [] -> (
759           match res with
760             | None -> others_simpl
761             | Some e -> e::others_simpl
762         )
763 ;;
764
765 let simplify_equalities eq_uri env equalities =
766   Utils.debug_print
767     (lazy 
768        (Printf.sprintf "equalities:\n%s\n"
769           (String.concat "\n"
770              (List.map Equality.string_of_equality equalities))));
771   Utils.debug_print (lazy "SIMPLYFYING EQUALITIES...");
772   match equalities with
773     | [] -> []
774     | hd::tl ->
775         let res =
776           List.rev (simpl eq_uri env hd tl [])
777         in
778           Utils.debug_print
779             (lazy
780                (Printf.sprintf "equalities AFTER:\n%s\n"
781                   (String.concat "\n"
782                      (List.map Equality.string_of_equality res))));
783           res
784 ;;
785
786 let print_goals goals = 
787   (String.concat "\n"
788      (List.map
789         (fun (d, gl) ->
790            let gl' =
791              List.map
792                (fun (p, _, t) ->
793                   (* (string_of_proof p) ^ ", " ^ *) (CicPp.ppterm t)) gl
794            in
795            Printf.sprintf "%d: %s" d (String.concat "; " gl')) goals))
796 ;;
797               
798 let pp_goal_set msg goals names = 
799   let active_goals, passive_goals = goals in
800   prerr_endline ("////" ^ msg);
801   prerr_endline ("ACTIVE G: " ^
802     (String.concat "\n " (List.map (fun (_,_,g) -> CicPp.pp g names)
803     active_goals)));
804   prerr_endline ("PASSIVE G: " ^
805     (String.concat "\n " (List.map (fun (_,_,g) -> CicPp.pp g names)
806     passive_goals)))
807 ;;
808
809 let check_if_goal_is_subsumed ((_,ctx,_) as env) table (goalproof,menv,ty) =
810   let names = Utils.names_of_context ctx in
811   match ty with
812   | Cic.Appl[Cic.MutInd(uri,_,_);eq_ty;left;right] 
813     when LibraryObjects.is_eq_URI uri ->
814       (let goal_equation = 
815          Equality.mk_equality
816            (0,Equality.Exact (Cic.Implicit None),(eq_ty,left,right,Utils.Eq),menv) 
817       in
818 (*      match Indexing.subsumption env table goal_equation with*)
819        match Indexing.unification env table goal_equation with 
820         | Some (subst, equality, swapped ) ->
821 (*
822             prerr_endline 
823              ("GOAL SUBSUMED IS: "^Equality.string_of_equality goal_equation ~env);
824             prerr_endline 
825              ("GOAL IS SUBSUMED BY: "^Equality.string_of_equality equality ~env);
826             prerr_endline ("SUBST:"^Subst.ppsubst ~names subst);
827 *)
828             let (_,p,(ty,l,r,_),m,id) = Equality.open_equality equality in
829             let cicmenv = Subst.apply_subst_metasenv subst (m @ menv) in
830             let p =
831               if swapped then
832                 Equality.symmetric eq_ty l id uri m
833               else
834                 p
835             in
836             Some (goalproof, p, id, subst, cicmenv)
837         | None -> None)
838   | _ -> None
839 ;;
840
841 let check_if_goal_is_identity env = function
842   | (goalproof,m,Cic.Appl[Cic.MutInd(uri,_,ens);eq_ty;left;right]) 
843     when left = right && LibraryObjects.is_eq_URI uri ->
844       let reflproof = Equality.Exact (Equality.refl_proof uri eq_ty left) in
845       Some (goalproof, reflproof, 0, Subst.empty_subst,m)
846   | (goalproof,m,Cic.Appl[Cic.MutInd(uri,_,ens);eq_ty;left;right]) 
847     when LibraryObjects.is_eq_URI uri ->
848     (let _,context,_ = env in
849     try 
850      let s,m,_ = 
851        Inference.unification m m context left right CicUniv.empty_ugraph 
852      in
853       let reflproof = Equality.Exact (Equality.refl_proof uri eq_ty left) in
854       let m = Subst.apply_subst_metasenv s m in
855       Some (goalproof, reflproof, 0, s,m)
856     with _ -> None)
857   | _ -> None
858 ;;                              
859     
860 let rec check goal = function
861   | [] -> None
862   | f::tl ->
863       match f goal with
864       | None -> check goal tl
865       | (Some p) as ok  -> ok
866 ;;
867   
868 let simplify_goal_set env goals active = 
869   let active_goals, passive_goals = goals in 
870   let find (_,_,g) where =
871     List.exists (fun (_,_,g1) -> Equality.meta_convertibility g g1) where
872   in
873     (* prova:tengo le passive semplificate 
874   let passive_goals = 
875     List.map (fun g -> snd (simplify_goal env g active)) passive_goals 
876   in *)
877     List.fold_left
878       (fun (acc_a,acc_p) goal -> 
879         match simplify_goal env goal active with 
880         | changed, g -> 
881             if changed then 
882               if find g acc_p then acc_a,acc_p else acc_a,g::acc_p
883             else
884               if find g acc_a then acc_a,acc_p else g::acc_a,acc_p)
885       ([],passive_goals) active_goals
886 ;;
887
888 let check_if_goals_set_is_solved env active goals =
889   let active_goals, passive_goals = goals in
890   List.fold_left 
891     (fun proof goal ->
892       match proof with
893       | Some p -> proof
894       | None -> 
895           check goal [
896             check_if_goal_is_identity env;
897             check_if_goal_is_subsumed env (snd active)])
898 (* provare active and passive?*)
899     None active_goals
900 ;;
901
902 let infer_goal_set env active goals = 
903   let active_goals, passive_goals = goals in
904   let rec aux = function
905     | [] -> active_goals, []
906     | hd::tl ->
907         let changed,selected = simplify_goal env hd active in
908 (*
909         if changed then
910           prerr_endline ("--------------- goal semplificato");
911 *)
912         let (_,_,t1) = selected in
913         let already_in = 
914           List.exists (fun (_,_,t) -> Equality.meta_convertibility t t1) 
915               active_goals
916         in
917         if already_in then 
918              aux tl
919           else
920             let passive_goals = tl in
921             let new_passive_goals =
922               if Utils.metas_of_term t1 = [] then passive_goals
923               else 
924                 let newmaxmeta,new' = 
925                    Indexing.superposition_left env (snd active) selected
926                    !maxmeta 
927                 in
928                 maxmeta := newmaxmeta;
929                 passive_goals @ new'
930             in
931             selected::active_goals, new_passive_goals
932   in 
933   aux passive_goals
934 ;;
935
936 let infer_goal_set_with_current env current goals active = 
937   let active_goals, passive_goals = 
938     simplify_goal_set env goals active
939   in
940   let l,table,_  = build_table [current] in
941   active_goals, 
942   List.fold_left 
943     (fun acc g ->
944       let newmaxmeta, new' = Indexing.superposition_left env table g !maxmeta in
945       maxmeta := newmaxmeta;
946       acc @ new')
947     passive_goals active_goals
948 ;;
949
950 let ids_of_goal g = 
951   let p,_,_ = g in
952   let ids = List.map (fun _,_,i,_,_ -> i) p in
953   ids
954 ;;
955
956 let ids_of_goal_set (ga,gp) =
957   List.flatten (List.map ids_of_goal ga) @
958   List.flatten (List.map ids_of_goal gp)
959 ;;
960
961 let size_of_goal_set_a (l,_) = List.length l;;
962 let size_of_goal_set_p (_,l) = List.length l;;
963       
964 let pp_goals label goals context = 
965   let names = Utils.names_of_context context in
966   List.iter                 
967     (fun _,_,g -> 
968       prerr_endline 
969         (Printf.sprintf  "Current goal: %s = %s\n" label (CicPp.pp g names))) 
970     (fst goals);
971   List.iter                 
972     (fun _,_,g -> 
973       prerr_endline 
974         (Printf.sprintf  "PASSIVE goal: %s = %s\n" label (CicPp.pp g names))) 
975       (snd goals);
976 ;;
977
978 let print_status iterno goals active passive =
979   print_endline 
980     (Printf.sprintf "\n%d #ACTIVES: %d #PASSIVES: %d #GOALSET: %d(%d)"
981       iterno (size_of_active active) (size_of_passive passive)
982       (size_of_goal_set_a goals) (size_of_goal_set_p goals)) 
983 ;;
984
985 (** given-clause algorithm with full reduction strategy: NEW implementation *)
986 (* here goals is a set of goals in OR *)
987 let given_clause 
988   eq_uri ((_,context,_) as env) goals theorems passive active max_iterations max_time
989
990   let initial_time = Unix.gettimeofday () in
991   let iterations_left iterno = 
992     let now = Unix.gettimeofday () in
993     let time_left = max_time -. now in
994     let time_spent_until_now = now -. initial_time in
995     let iteration_medium_cost = 
996       time_spent_until_now /. (float_of_int iterno)
997     in
998     let iterations_left = time_left /. iteration_medium_cost in
999     int_of_float iterations_left 
1000   in
1001   let rec step goals theorems passive active iterno =
1002     if iterno > max_iterations then
1003       (ParamodulationFailure "No more iterations to spend")
1004     else if Unix.gettimeofday () > max_time then
1005       (ParamodulationFailure "No more time to spend")
1006     else
1007       let _ = 
1008 (*         print_status iterno goals active passive  *)
1009         Printf.printf ".%!";
1010       in
1011       (* PRUNING OF PASSIVE THAT WILL NEVER BE PROCESSED *) 
1012       let passive =
1013         let selection_estimate = iterations_left iterno in
1014         let kept = size_of_passive passive in
1015         if kept > selection_estimate then 
1016           begin
1017             (*Printf.eprintf "Too many passive equalities: pruning...";
1018             prune_passive selection_estimate active*) passive
1019           end
1020         else
1021           passive
1022       in
1023       kept_clauses := (size_of_passive passive) + (size_of_active active);
1024       let goals = infer_goal_set env active goals 
1025       in
1026       match check_if_goals_set_is_solved env active goals with
1027       | Some p -> 
1028           print_endline 
1029             (Printf.sprintf "\nFound a proof in: %f\n" 
1030               (Unix.gettimeofday() -. initial_time));
1031           ParamodulationSuccess p
1032       | None -> 
1033           (* SELECTION *)
1034           if passive_is_empty passive then
1035             if no_more_passive_goals goals then 
1036               ParamodulationFailure "No more passive equations/goals"
1037               (*maybe this is a success! *)
1038             else
1039               step goals theorems passive active (iterno+1)
1040           else
1041             begin
1042               (* COLLECTION OF GARBAGED EQUALITIES *)
1043               if iterno mod 40 = 0 then
1044                 begin
1045                   print_status iterno goals active passive;
1046                   let active = List.map Equality.id_of (fst active) in
1047                   let passive = List.map Equality.id_of (fst passive) in
1048                   let goal = ids_of_goal_set goals in
1049                   Equality.collect active passive goal
1050                 end;
1051               let current, passive = select env goals passive in
1052               (* SIMPLIFICATION OF CURRENT *)
1053 (*
1054               prerr_endline
1055                     ("Selected : " ^ 
1056                       Equality.string_of_equality ~env  current);
1057 *)
1058               let res = 
1059                 forward_simplify eq_uri env current active 
1060               in
1061               match res with
1062               | None -> step goals theorems passive active (iterno+1)
1063               | Some current ->
1064                   (* GENERATION OF NEW EQUATIONS *)
1065 (*                   prerr_endline "infer"; *)
1066                   let new' = infer eq_uri env current active in
1067 (*                   prerr_endline "infer goal"; *)
1068 (*
1069       match check_if_goals_set_is_solved env active goals with
1070       | Some p -> 
1071           prerr_endline 
1072             (Printf.sprintf "Found a proof in: %f\n" 
1073               (Unix.gettimeofday() -. initial_time));
1074           ParamodulationSuccess p
1075       | None -> 
1076 *)
1077                   let active = 
1078                       let al, tbl = active in
1079                       al @ [current], Indexing.index tbl current
1080                   in
1081                   let goals = 
1082                     infer_goal_set_with_current env current goals active 
1083                   in
1084                   (* FORWARD AND BACKWARD SIMPLIFICATION *)
1085 (*                   prerr_endline "fwd/back simpl"; *)
1086                   let rec simplify new' active passive head =
1087                     let new' = 
1088                       forward_simplify_new eq_uri env new' active 
1089                     in
1090                     let active, newa, retained, pruned =
1091                       backward_simplify eq_uri env new' active 
1092                     in
1093                     let passive = 
1094                       List.fold_left filter_dependent passive pruned 
1095                     in
1096                     match newa, retained with
1097                     | None, None -> active, passive, new', head
1098                     | Some p, None 
1099                     | None, Some p -> simplify (new' @ p) active passive head
1100                     | Some p, Some rp -> 
1101                         simplify (new' @ p @ rp) active passive (head @ p)
1102                   in
1103                   let active, passive, new', head = 
1104                     simplify new' active passive []
1105                   in
1106 (*                   prerr_endline "simpl goal with new"; *)
1107                   let goals = 
1108                     let a,b,_ = build_table new' in
1109 (*                     let _ = <:start<simplify_goal_set new>> in *)
1110                     let rc = simplify_goal_set env goals (a,b) in
1111 (*                     let _ = <:stop<simplify_goal_set new>> in *)
1112                     rc
1113                   in
1114                   let passive = add_to_passive passive new' head in
1115                   step goals theorems passive active (iterno+1)
1116             end
1117   in
1118     step goals theorems passive active 1
1119 ;;
1120
1121 let rec saturate_equations eq_uri env goal accept_fun passive active =
1122   elapsed_time := Unix.gettimeofday () -. !start_time;
1123   if !elapsed_time > !time_limit then
1124     (active, passive)
1125   else
1126     let current, passive = select env ([goal],[]) passive in
1127     let res = forward_simplify eq_uri env current active in
1128     match res with
1129     | None ->
1130         saturate_equations eq_uri env goal accept_fun passive active
1131     | Some current ->
1132         Utils.debug_print (lazy (Printf.sprintf "selected: %s"
1133                              (Equality.string_of_equality ~env current)));
1134         let new' = infer eq_uri env current active in
1135         let active =
1136           if Equality.is_identity env current then active
1137           else
1138             let al, tbl = active in
1139             al @ [current], Indexing.index tbl current
1140         in
1141         (* alla fine new' contiene anche le attive semplificate!
1142          * quindi le aggiungo alle passive insieme alle new *)
1143         let rec simplify new' active passive =
1144           let new' = forward_simplify_new eq_uri env new' active in
1145           let active, newa, retained, pruned =
1146             backward_simplify eq_uri env new' active in
1147           let passive = 
1148             List.fold_left filter_dependent passive pruned in
1149           match newa, retained with
1150           | None, None -> active, passive, new'
1151           | Some p, None
1152           | None, Some p -> simplify (new' @ p) active passive
1153           | Some p, Some rp -> simplify (new' @ p @ rp) active passive
1154         in
1155         let active, passive, new' = simplify new' active passive in
1156         let _ =
1157           Utils.debug_print
1158             (lazy
1159                (Printf.sprintf "active:\n%s\n"
1160                   (String.concat "\n"
1161                      (List.map
1162                          (fun e -> Equality.string_of_equality ~env e)
1163                          (fst active)))))
1164         in
1165         let _ =
1166           Utils.debug_print
1167             (lazy
1168                (Printf.sprintf "new':\n%s\n"
1169                   (String.concat "\n"
1170                      (List.map
1171                          (fun e -> "Negative " ^
1172                             (Equality.string_of_equality ~env e)) new'))))
1173         in
1174         let new' = List.filter accept_fun new' in
1175         let passive = add_to_passive passive new' [] in
1176         saturate_equations eq_uri env goal accept_fun passive active
1177 ;;
1178   
1179 let default_depth = !maxdepth
1180 and default_width = !maxwidth;;
1181
1182 let reset_refs () =
1183   maxmeta := 0;
1184   symbols_counter := 0;
1185   weight_age_counter := !weight_age_ratio;
1186   processed_clauses := 0;
1187   start_time := 0.;
1188   elapsed_time := 0.;
1189   maximal_retained_equality := None;
1190   infer_time := 0.;
1191   forward_simpl_time := 0.;
1192   forward_simpl_new_time := 0.;
1193   backward_simpl_time := 0.;
1194   passive_maintainance_time := 0.;
1195   derived_clauses := 0;
1196   kept_clauses := 0;
1197   Equality.reset ();
1198 ;;
1199
1200 let eq_of_goal = function
1201   | Cic.Appl [Cic.MutInd(uri,0,_);_;_;_] when LibraryObjects.is_eq_URI uri ->
1202       uri
1203   | _ -> raise (ProofEngineTypes.Fail (lazy ("The goal is not an equality ")))
1204 ;;
1205
1206 let eq_and_ty_of_goal = function
1207   | Cic.Appl [Cic.MutInd(uri,0,_);t;_;_] when LibraryObjects.is_eq_URI uri ->
1208       uri,t
1209   | _ -> raise (ProofEngineTypes.Fail (lazy ("The goal is not an equality ")))
1210 ;;
1211
1212 let saturate 
1213     caso_strano 
1214     dbd ?(full=false) ?(depth=default_depth) ?(width=default_width) status = 
1215   let module C = Cic in
1216   reset_refs ();
1217   Indexing.init_index ();
1218   maxdepth := depth;
1219   maxwidth := width;
1220 (*  CicUnification.unif_ty := false;*)
1221   let proof, goalno = status in
1222   let uri, metasenv, meta_proof, term_to_prove = proof in
1223   let _, context, type_of_goal = CicUtil.lookup_meta goalno metasenv in
1224   let eq_uri = eq_of_goal type_of_goal in 
1225   let cleaned_goal = Utils.remove_local_context type_of_goal in
1226   Utils.set_goal_symbols cleaned_goal;
1227   let names = Utils.names_of_context context in
1228   let eq_indexes, equalities, maxm = Inference.find_equalities context proof in
1229   let ugraph = CicUniv.empty_ugraph in
1230   let env = (metasenv, context, ugraph) in 
1231   let goal = [], List.filter (fun (i,_,_)->i<>goalno) metasenv, cleaned_goal in
1232   let res, time =
1233     let t1 = Unix.gettimeofday () in
1234     let lib_eq_uris, library_equalities, maxm =
1235       Inference.find_library_equalities caso_strano dbd context (proof, goalno) (maxm+2)
1236     in
1237     let library_equalities = List.map snd library_equalities in
1238     let t2 = Unix.gettimeofday () in
1239     maxmeta := maxm+2;
1240     let equalities = 
1241       simplify_equalities eq_uri env (equalities@library_equalities) 
1242     in 
1243     Utils.debug_print
1244       (lazy
1245          (Printf.sprintf "Time to retrieve equalities: %.9f\n" (t2 -. t1)));
1246     let t1 = Unix.gettimeofday () in
1247     let theorems =
1248       if full then
1249         let thms = Inference.find_library_theorems dbd env (proof, goalno) lib_eq_uris in
1250         let context_hyp = Inference.find_context_hypotheses env eq_indexes in
1251         context_hyp @ thms, []
1252       else
1253         let refl_equal = LibraryObjects.eq_refl_URI ~eq:eq_uri in
1254         let t = CicUtil.term_of_uri refl_equal in
1255         let ty, _ = CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in
1256         [(t, ty, [])], []
1257     in
1258     let t2 = Unix.gettimeofday () in
1259     let _ =
1260       Utils.debug_print
1261         (lazy
1262            (Printf.sprintf
1263               "Theorems:\n-------------------------------------\n%s\n"
1264               (String.concat "\n"
1265                  (List.map
1266                     (fun (t, ty, _) ->
1267                        Printf.sprintf
1268                          "Term: %s, type: %s"
1269                          (CicPp.ppterm t) (CicPp.ppterm ty))
1270                     (fst theorems)))));
1271       Utils.debug_print
1272         (lazy
1273            (Printf.sprintf "Time to retrieve theorems: %.9f\n" (t2 -. t1)));
1274     in
1275     let active = make_active () in
1276     let passive = make_passive equalities in
1277     let start = Unix.gettimeofday () in
1278     let res =
1279 (*
1280       let goals = make_goals goal in
1281       given_clause_fullred dbd env goals theorems passive active
1282 *)
1283       let goals = make_goal_set goal in
1284       let max_iterations = 10000 in
1285       let max_time = Unix.gettimeofday () +.  600. (* minutes *) in
1286       given_clause 
1287         eq_uri env goals theorems passive active max_iterations max_time 
1288     in
1289     let finish = Unix.gettimeofday () in
1290     (res, finish -. start)
1291   in
1292   match res with
1293   | ParamodulationFailure s ->
1294       raise (ProofEngineTypes.Fail (lazy ("NO proof found: " ^ s)))
1295   | ParamodulationSuccess 
1296     (goalproof,newproof,subsumption_id,subsumption_subst, proof_menv) ->
1297       print_endline "Proof:";
1298       print_endline 
1299         (Equality.pp_proof names goalproof newproof subsumption_subst
1300           subsumption_id type_of_goal);
1301 (*       prerr_endline "ENDOFPROOFS"; *)
1302 (*
1303       prerr_endline ("max weight: " ^ 
1304         (string_of_int (Equality.max_weight goalproof newproof)));
1305 *)
1306       (* generation of the CIC proof *)
1307       let side_effects = 
1308         List.filter (fun i -> i <> goalno)
1309           (ProofEngineHelpers.compare_metasenvs 
1310             ~newmetasenv:metasenv ~oldmetasenv:proof_menv)
1311       in
1312       let goal_proof, side_effects_t = 
1313         let initial = Equality.add_subst subsumption_subst newproof in
1314         Equality.build_goal_proof 
1315           eq_uri goalproof initial type_of_goal side_effects
1316           context proof_menv
1317       in
1318 (*       prerr_endline ("PROOF: " ^ CicPp.pp goal_proof names); *)
1319       let goal_proof = Subst.apply_subst subsumption_subst goal_proof in
1320       let metas_still_open_in_proof = Utils.metas_of_term goal_proof in
1321 (*prerr_endline (CicPp.pp goal_proof names);*)
1322       (* ?? *)
1323       let goal_proof = (* Subst.apply_subst subsumption_subst *) goal_proof in
1324       let side_effects_t = 
1325         List.map (Subst.apply_subst subsumption_subst) side_effects_t
1326       in
1327       (* replacing fake mets with real ones *)
1328 (*       prerr_endline "replacing metas..."; *)
1329       let irl=CicMkImplicit.identity_relocation_list_for_metavariable context in
1330       let goal_proof_menv, what, with_what,free_meta = 
1331         List.fold_left 
1332           (fun (acc1,acc2,acc3,uniq) (i,_,ty) -> 
1333              match uniq with
1334                | Some m -> 
1335                    acc1, (Cic.Meta(i,[]))::acc2, m::acc3, uniq
1336                | None ->
1337                    [i,context,ty], (Cic.Meta(i,[]))::acc2, 
1338                    (Cic.Meta(i,irl)) ::acc3,Some (Cic.Meta(i,irl))) 
1339           ([],[],[],None) 
1340           (List.filter 
1341            (fun (i,_,_) -> List.mem i metas_still_open_in_proof) 
1342            proof_menv)
1343       in
1344       let replace where = 
1345         (* we need this fake equality since the metas of the hypothesis may be
1346          * with a real local context *)
1347         ProofEngineReduction.replace_lifting 
1348           ~equality:(fun x y -> 
1349             match x,y with Cic.Meta(i,_),Cic.Meta(j,_) -> i=j | _-> false)
1350           ~what ~with_what ~where
1351       in
1352       let goal_proof = replace goal_proof in
1353         (* ok per le meta libere... ma per quelle che c'erano e sono rimaste? 
1354          * what mi pare buono, sostituisce solo le meta farlocche *)
1355       let side_effects_t = List.map replace side_effects_t in
1356       let free_metas = 
1357         List.filter (fun i -> i <> goalno)
1358           (ProofEngineHelpers.compare_metasenvs 
1359             ~oldmetasenv:metasenv ~newmetasenv:goal_proof_menv)
1360       in
1361 (* prerr_endline ("freemetas: " ^ String.concat "," (List.map string_of_int
1362  * free_metas) ); *)
1363       (* check/refine/... build the new proof *)
1364       let replaced_goal = 
1365         ProofEngineReduction.replace
1366           ~what:side_effects ~with_what:side_effects_t
1367           ~equality:(fun i t -> match t with Cic.Meta(j,_)->j=i|_->false)
1368           ~where:type_of_goal
1369       in
1370       let subst_side_effects,real_menv,_ = 
1371         let fail t s = raise (ProofEngineTypes.Fail (lazy (t^Lazy.force s))) in
1372         let free_metas_menv = 
1373           List.map (fun i -> CicUtil.lookup_meta i goal_proof_menv) free_metas
1374         in
1375         try
1376           CicUnification.fo_unif_subst [] context (metasenv @ free_metas_menv)
1377            replaced_goal type_of_goal CicUniv.empty_ugraph
1378         with
1379         | CicUnification.UnificationFailure s
1380         | CicUnification.Uncertain s 
1381         | CicUnification.AssertFailure s -> 
1382             fail "Maybe the local context of metas in the goal was not an IRL" s
1383       in
1384       let final_subst = 
1385         (goalno,(context,goal_proof,type_of_goal))::subst_side_effects
1386       in
1387 (* prerr_endline ("MENVreal_menv: " ^ CicMetaSubst.ppmetasenv [] real_menv); *)
1388       let _ = 
1389         try
1390           CicTypeChecker.type_of_aux' real_menv context goal_proof
1391             CicUniv.empty_ugraph
1392         with 
1393         | CicUtil.Meta_not_found _ 
1394         | CicTypeChecker.TypeCheckerFailure _ 
1395         | CicTypeChecker.AssertFailure _ 
1396         | Invalid_argument "list_fold_left2" as exn ->
1397             prerr_endline "THE PROOF DOES NOT TYPECHECK!";
1398             prerr_endline (CicPp.pp goal_proof names); 
1399             prerr_endline "THE PROOF DOES NOT TYPECHECK!";
1400             raise exn
1401       in
1402       let proof, real_metasenv = 
1403         ProofEngineHelpers.subst_meta_and_metasenv_in_proof
1404           proof goalno (CicMetaSubst.apply_subst final_subst) real_menv
1405       in
1406       let open_goals = 
1407         match free_meta with Some(Cic.Meta(m,_)) when m<>goalno ->[m] | _ ->[] 
1408       in
1409 (*
1410       Printf.eprintf 
1411         "GOALS APERTI: %s\nMETASENV PRIMA:\n%s\nMETASENV DOPO:\n%s\n" 
1412           (String.concat ", " (List.map string_of_int open_goals))
1413           (CicMetaSubst.ppmetasenv [] metasenv)
1414           (CicMetaSubst.ppmetasenv [] real_metasenv);
1415 *)
1416       print_endline (Printf.sprintf "\nTIME NEEDED: %8.2f" time);
1417       proof, open_goals
1418 ;;
1419
1420 let main _ _ _ _ _ = () ;;
1421
1422 let retrieve_and_print dbd term metasenv ugraph = 
1423   let module C = Cic in
1424   let module T = CicTypeChecker in
1425   let module PET = ProofEngineTypes in
1426   let module PP = CicPp in
1427   let proof = None, (1, [], term)::metasenv, C.Meta (1, []), term in
1428   let status = PET.apply_tactic (PrimitiveTactics.intros_tac ()) (proof, 1) in
1429   let proof, goals = status in
1430   let goal' = List.nth goals 0 in
1431   let uri, metasenv, meta_proof, term_to_prove = proof in
1432   let _, context, type_of_goal = CicUtil.lookup_meta goal' metasenv in
1433   let eq_uri = eq_of_goal type_of_goal in 
1434   let eq_indexes, equalities, maxm = Inference.find_equalities context proof in
1435   let ugraph = CicUniv.empty_ugraph in
1436   let env = (metasenv, context, ugraph) in
1437   let t1 = Unix.gettimeofday () in
1438   let lib_eq_uris, library_equalities, maxm =
1439     Inference.find_library_equalities false dbd context (proof, goal') (maxm+2) in
1440   let t2 = Unix.gettimeofday () in
1441   maxmeta := maxm+2;
1442   let equalities = (* equalities @ *) library_equalities in
1443   Utils.debug_print
1444      (lazy
1445         (Printf.sprintf "\n\nequalities:\n%s\n"
1446            (String.concat "\n"
1447               (List.map 
1448           (fun (u, e) ->
1449 (*                  Printf.sprintf "%s: %s" *)
1450                    (UriManager.string_of_uri u)
1451 (*                    (string_of_equality e) *)
1452                      )
1453           equalities))));
1454   Utils.debug_print (lazy "RETR: SIMPLYFYING EQUALITIES...");
1455   let rec simpl e others others_simpl =
1456     let (u, e) = e in
1457     let active = (others @ others_simpl) in
1458     let tbl =
1459       List.fold_left
1460         (fun t (_, e) -> Indexing.index t e)
1461         Indexing.empty active
1462     in
1463     let res = forward_simplify eq_uri env e (active, tbl) in
1464     match others with
1465         | hd::tl -> (
1466             match res with
1467               | None -> simpl hd tl others_simpl
1468               | Some e -> simpl hd tl ((u, e)::others_simpl)
1469           )
1470         | [] -> (
1471             match res with
1472               | None -> others_simpl
1473               | Some e -> (u, e)::others_simpl
1474           ) 
1475   in
1476   let _equalities =
1477     match equalities with
1478       | [] -> []
1479       | hd::tl ->
1480           let others = tl in (* List.map (fun e -> (Utils.Positive, e)) tl in *)
1481           let res =
1482             List.rev (simpl (*(Positive,*) hd others [])
1483           in
1484             Utils.debug_print
1485               (lazy
1486                  (Printf.sprintf "\nequalities AFTER:\n%s\n"
1487                     (String.concat "\n"
1488                        (List.map
1489                           (fun (u, e) ->
1490                              Printf.sprintf "%s: %s"
1491                                (UriManager.string_of_uri u)
1492                                (Equality.string_of_equality e)
1493                           )
1494                           res))));
1495             res in
1496     Utils.debug_print
1497       (lazy
1498          (Printf.sprintf "Time to retrieve equalities: %.9f\n" (t2 -. t1)))
1499 ;;
1500
1501
1502 let main_demod_equalities dbd term metasenv ugraph =
1503   let module C = Cic in
1504   let module T = CicTypeChecker in
1505   let module PET = ProofEngineTypes in
1506   let module PP = CicPp in
1507   let proof = None, (1, [], term)::metasenv, C.Meta (1, []), term in
1508   let status = PET.apply_tactic (PrimitiveTactics.intros_tac ()) (proof, 1) in
1509   let proof, goals = status in
1510   let goal' = List.nth goals 0 in
1511   let _, metasenv, meta_proof, _ = proof in
1512   let _, context, goal = CicUtil.lookup_meta goal' metasenv in
1513   let eq_uri = eq_of_goal goal in 
1514   let eq_indexes, equalities, maxm = Inference.find_equalities context proof in
1515   let lib_eq_uris, library_equalities, maxm =
1516     Inference.find_library_equalities false dbd context (proof, goal') (maxm+2)
1517   in
1518   let library_equalities = List.map snd library_equalities in
1519   maxmeta := maxm+2; (* TODO ugly!! *)
1520   let irl = CicMkImplicit.identity_relocation_list_for_metavariable context in
1521   let new_meta_goal, metasenv, type_of_goal =
1522     let _, context, ty = CicUtil.lookup_meta goal' metasenv in
1523     Utils.debug_print
1524       (lazy
1525          (Printf.sprintf "\n\nTRYING TO INFER EQUALITIES MATCHING: %s\n\n"
1526             (CicPp.ppterm ty)));
1527     Cic.Meta (maxm+1, irl),
1528     (maxm+1, context, ty)::metasenv,
1529     ty
1530   in
1531   let env = (metasenv, context, ugraph) in
1532   (*try*)
1533     let goal = [], [], goal 
1534     in
1535     let equalities = 
1536       simplify_equalities eq_uri env (equalities@library_equalities) 
1537     in
1538     let active = make_active () in
1539     let passive = make_passive equalities in
1540     Printf.printf "\ncontext:\n%s\n" (PP.ppcontext context);
1541     Printf.printf "\nmetasenv:\n%s\n" (Utils.print_metasenv metasenv);
1542     Printf.printf "\nequalities:\n%s\n"
1543       (String.concat "\n"
1544          (List.map
1545             (Equality.string_of_equality ~env) equalities));
1546     print_endline "--------------------------------------------------";
1547     print_endline "GO!";
1548     start_time := Unix.gettimeofday ();
1549     if !time_limit < 1. then time_limit := 60.;    
1550     let ra, rp =
1551       saturate_equations eq_uri env goal (fun e -> true) passive active
1552     in
1553
1554     let initial =
1555       List.fold_left (fun s e -> EqualitySet.add e s)
1556         EqualitySet.empty equalities
1557     in
1558     let addfun s e = 
1559       if not (EqualitySet.mem e initial) then EqualitySet.add e s else s
1560     in
1561
1562     let passive =
1563       match rp with
1564       | p, _ ->
1565           EqualitySet.elements (List.fold_left addfun EqualitySet.empty p)
1566     in
1567     let active =
1568       let l = fst ra in
1569       EqualitySet.elements (List.fold_left addfun EqualitySet.empty l)
1570     in
1571     Printf.printf "\n\nRESULTS:\nActive:\n%s\n\nPassive:\n%s\n"
1572        (String.concat "\n" (List.map (Equality.string_of_equality ~env) active)) 
1573      (*  (String.concat "\n"
1574          (List.map (fun e -> CicPp.ppterm (term_of_equality e)) active)) *)
1575 (*       (String.concat "\n" (List.map (string_of_equality ~env) passive)); *)
1576       (String.concat "\n"
1577          (List.map 
1578            (fun e -> CicPp.ppterm (Equality.term_of_equality eq_uri e)) 
1579           passive));
1580     print_newline ();
1581 (*
1582   with e ->
1583     Utils.debug_print (lazy ("EXCEPTION: " ^ (Printexc.to_string e)))
1584 *)
1585 ;;
1586
1587 let demodulate_tac ~dbd ((proof,goal)(*s initialstatus*)) = 
1588   let curi,metasenv,pbo,pty = proof in
1589   let metano,context,ty = CicUtil.lookup_meta goal metasenv in
1590   let eq_uri = eq_of_goal ty in 
1591   let eq_indexes, equalities, maxm = 
1592     Inference.find_equalities context proof 
1593   in
1594   let lib_eq_uris, library_equalities, maxm =
1595     Inference.find_library_equalities false dbd context (proof, goal) (maxm+2) in
1596   if library_equalities = [] then prerr_endline "VUOTA!!!";
1597   let irl = CicMkImplicit.identity_relocation_list_for_metavariable context in
1598   let library_equalities = List.map snd library_equalities in
1599   let initgoal = [], [], ty in
1600   let env = (metasenv, context, CicUniv.empty_ugraph) in
1601   let equalities = 
1602     simplify_equalities eq_uri env (equalities@library_equalities) 
1603   in   
1604   let table = 
1605     List.fold_left 
1606       (fun tbl eq -> Indexing.index tbl eq) 
1607       Indexing.empty equalities 
1608   in
1609   let changed,(newproof,newmetasenv, newty) = 
1610     Indexing.demodulation_goal 
1611       (metasenv,context,CicUniv.empty_ugraph) table initgoal 
1612   in
1613   if changed then
1614     begin
1615       let opengoal = Equality.Exact (Cic.Meta(maxm,irl)) in
1616       let proofterm,_ = 
1617         Equality.build_goal_proof 
1618           eq_uri newproof opengoal ty [] context metasenv
1619       in
1620         let extended_metasenv = (maxm,context,newty)::metasenv in
1621         let extended_status = 
1622           (curi,extended_metasenv,pbo,pty),goal in
1623         let (status,newgoals) = 
1624           ProofEngineTypes.apply_tactic 
1625             (PrimitiveTactics.apply_tac ~term:proofterm)
1626             extended_status in
1627         (status,maxm::newgoals)
1628     end
1629   else (* if newty = ty then *)
1630     raise (ProofEngineTypes.Fail (lazy "no progress"))
1631   (*else ProofEngineTypes.apply_tactic 
1632     (ReductionTactics.simpl_tac
1633       ~pattern:(ProofEngineTypes.conclusion_pattern None)) initialstatus*)
1634 ;;
1635
1636 let demodulate_tac ~dbd = ProofEngineTypes.mk_tactic (demodulate_tac ~dbd);;
1637
1638 let rec find_in_ctx i name = function
1639   | [] -> raise (ProofEngineTypes.Fail (lazy ("Hypothesis not found: " ^ name)))
1640   | Some (Cic.Name name', _)::tl when name = name' -> i
1641   | _::tl -> find_in_ctx (i+1) name tl
1642 ;;
1643
1644 let rec position_of i x = function
1645   | [] -> assert false
1646   | j::tl when j <> x -> position_of (i+1) x tl
1647   | _ -> i
1648 ;;
1649
1650 (* Syntax: 
1651  *   auto superposition target = NAME 
1652  *     [table = NAME_LIST] [demod_table = NAME_LIST] [subterms_only]
1653  *
1654  *  - if table is omitted no superposition will be performed
1655  *  - if demod_table is omitted no demodulation will be prformed
1656  *  - subterms_only is passed to Indexing.superposition_right
1657  *
1658  *  lists are coded using _ (example: H_H1_H2)
1659  *)
1660
1661 let superposition_tac ~target ~table ~subterms_only ~demod_table status = 
1662   reset_refs();
1663   Indexing.init_index ();
1664   let proof,goalno = status in 
1665   let curi,metasenv,pbo,pty = proof in
1666   let metano,context,ty = CicUtil.lookup_meta goalno metasenv in
1667   let eq_uri,tty = eq_and_ty_of_goal ty in
1668   let env = (metasenv, context, CicUniv.empty_ugraph) in
1669   let names = Utils.names_of_context context in
1670   let eq_index, equalities, maxm = Inference.find_equalities context proof in
1671   let eq_what = 
1672     let what = find_in_ctx 1 target context in
1673     List.nth equalities (position_of 0 what eq_index)
1674   in
1675   let eq_other = 
1676     if table <> "" then
1677       let other = 
1678         let others = Str.split (Str.regexp "_") table in 
1679         List.map (fun other -> find_in_ctx 1 other context) others 
1680       in
1681       List.map 
1682         (fun other -> List.nth equalities (position_of 0 other eq_index)) 
1683         other 
1684     else
1685       []
1686   in
1687   let index = List.fold_left Indexing.index Indexing.empty eq_other in
1688   let maxm, eql = 
1689     if table = "" then maxm,[eq_what] else 
1690     Indexing.superposition_right 
1691       ~subterms_only eq_uri maxm env index eq_what
1692   in
1693   prerr_endline ("Superposition right:");
1694   prerr_endline ("\n eq: " ^ Equality.string_of_equality eq_what ~env);
1695   prerr_endline ("\n table: ");
1696   List.iter (fun e -> prerr_endline ("  " ^ Equality.string_of_equality e ~env)) eq_other;
1697   prerr_endline ("\n result: ");
1698   List.iter (fun e -> prerr_endline (Equality.string_of_equality e ~env)) eql;
1699   prerr_endline ("\n result (cut&paste): ");
1700   List.iter 
1701     (fun e -> 
1702       let t = Equality.term_of_equality eq_uri e in
1703       prerr_endline (CicPp.pp t names)) 
1704   eql;
1705   prerr_endline ("\n result proofs: ");
1706   List.iter (fun e -> 
1707     prerr_endline (let _,p,_,_,_ = Equality.open_equality e in
1708     let s = match p with Equality.Exact _ -> Subst.empty_subst | Equality.Step (s,_) -> s in
1709     Subst.ppsubst s ^ "\n" ^ 
1710     CicPp.pp (Equality.build_proof_term eq_uri [] 0 p) names)) eql;
1711   if demod_table <> "" then
1712     begin
1713       let eql = 
1714         if eql = [] then [eq_what] else eql
1715       in
1716       let demod = 
1717         let demod = Str.split (Str.regexp "_") demod_table in 
1718         List.map (fun other -> find_in_ctx 1 other context) demod 
1719       in
1720       let eq_demod = 
1721         List.map 
1722           (fun demod -> List.nth equalities (position_of 0 demod eq_index)) 
1723           demod 
1724       in
1725       let table = List.fold_left Indexing.index Indexing.empty eq_demod in
1726       let maxm,eql = 
1727         List.fold_left 
1728           (fun (maxm,acc) e -> 
1729             let maxm,eq = 
1730               Indexing.demodulation_equality eq_uri maxm env table e
1731             in
1732             maxm,eq::acc) 
1733           (maxm,[]) eql
1734       in
1735       let eql = List.rev eql in
1736       prerr_endline ("\n result [demod]: ");
1737       List.iter 
1738         (fun e -> prerr_endline (Equality.string_of_equality e ~env)) eql;
1739       prerr_endline ("\n result [demod] (cut&paste): ");
1740       List.iter 
1741         (fun e -> 
1742           let t = Equality.term_of_equality eq_uri e in
1743           prerr_endline (CicPp.pp t names)) 
1744       eql;
1745     end;
1746   proof,[goalno]
1747 ;;
1748
1749 let get_stats () = "" 
1750 (*
1751   <:show<Saturation.>> ^ Indexing.get_stats () ^ Inference.get_stats () ^
1752   Equality.get_stats ()
1753 ;;
1754 *)
1755