]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/tactics/metadataQuery.ml
bugfix: handle overflow in powerset cardinality
[helm.git] / helm / ocaml / tactics / metadataQuery.ml
1 (* Copyright (C) 2004, 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://helm.cs.unibo.it/
24  *)
25
26 open Printf
27
28 module Constr = MetadataConstraints
29
30 let locate ~(dbh:Dbi.connection) name =
31   let query =
32     dbh#prepare (sprintf "SELECT source FROM %s WHERE value = \"%s\""
33       MetadataTypes.name_tbl name)
34   in
35   query#execute [];
36   List.map (function [`String s] -> s | _ -> assert false) (query#fetchall ())
37
38 let match_term ~(dbh:Dbi.connection) ty =
39   let constraints =
40     List.map MetadataTypes.constr_of_metadata
41       (MetadataExtractor.compute ~body:None ~ty)
42   in
43   Constr.at_least ~dbh constraints
44
45 let nonvar s =
46   let len = String.length s in
47   let suffix = String.sub s (len-4) 4 in
48   not (suffix  = ".var")
49
50 let ( ** ) x y = int_of_float ((float_of_int x) ** (float_of_int y))
51
52 let signature_of_hypothesis context =
53   List.fold_left
54     (fun set hyp ->
55       match hyp with
56       | None -> set
57       | Some (_, Cic.Decl t)
58       | Some (_, Cic.Def (t, _)) ->
59           Constr.StringSet.union set (Constr.constants_of t))
60     Constr.StringSet.empty context
61
62 let intersect l1 l2 =
63   let set1 = List.fold_right Constr.StringSet.add l1 Constr.StringSet.empty in
64   let set2 = List.fold_right Constr.StringSet.add l2 Constr.StringSet.empty in
65   Constr.StringSet.elements (Constr.StringSet.inter set1 set2)
66
67 let filter_uris_forward ~dbh (main, constants) uris =
68   let main_uris =
69     match main with
70     | None -> []
71     | Some (main, types) -> main :: types
72   in
73   let full_signature =
74     List.fold_right Constr.StringSet.add main_uris constants
75   in
76   List.filter (Constr.at_most ~dbh ~where:`Statement full_signature) uris
77
78 let filter_uris_backward ~dbh signature uris =
79   let siguris =
80     List.map snd (MetadataConstraints.sigmatch ~dbh ~where:`Statement signature)
81   in
82   intersect uris siguris
83
84 let compare_goal_list proof goal1 goal2 =
85   let _,metasenv,_,_ = proof in
86   let (_, ey1, ty1) = CicUtil.lookup_meta goal1 metasenv in
87   let (_, ey2, ty2) =  CicUtil.lookup_meta goal2 metasenv in
88   let ty_sort1 = CicTypeChecker.type_of_aux' metasenv ey1 ty1 in
89   let ty_sort2 = CicTypeChecker.type_of_aux' metasenv ey2 ty2 in
90   let prop1 =
91     if CicReduction.are_convertible ey1 (Cic.Sort Cic.Prop) ty_sort1 then 0
92     else 1
93   in
94   let prop2 =
95     if CicReduction.are_convertible ey2 (Cic.Sort Cic.Prop) ty_sort2 then 0
96     else 1
97   in
98   prop1 - prop2
99
100 let hint ~(dbh:Dbi.connection) ?signature ((proof, goal) as status) =
101   let (_, metasenv, _, _) = proof in
102   let (_, context, ty) = CicUtil.lookup_meta goal metasenv in
103   let (uris, (main, sig_constants)) =
104     match signature with
105     | Some signature -> (Constr.sigmatch ~dbh signature, signature)
106     | None -> (Constr.cmatch' ~dbh ty, Constr.signature_of ty)
107   in
108   let uris = List.filter nonvar (List.map snd uris) in
109   let types_constants =
110     match main with
111     | None -> Constr.StringSet.empty
112     | Some (main, types) ->
113         List.fold_right Constr.StringSet.add (main :: types)
114           Constr.StringSet.empty
115   in
116   let hyp_constants =
117     Constr.StringSet.diff (signature_of_hypothesis context) types_constants
118   in
119   let other_constants = Constr.StringSet.union sig_constants hyp_constants in
120   let uris = 
121     let pow = 2 ** (Constr.StringSet.cardinal other_constants) in
122     if ((List.length uris < pow) or (pow <= 0))
123     then begin
124       prerr_endline "MetadataQuery: large sig, falling back to old method";
125       filter_uris_forward ~dbh (main, other_constants) uris
126     end else
127       filter_uris_backward ~dbh (main, other_constants) uris
128   in
129 prerr_endline "URIS";
130 List.iter prerr_endline uris;
131   let rec aux = function
132     | [] -> []
133     | uri :: tl ->
134         (let status' =
135             try
136               let (proof, goal_list) =
137                 ProofEngineTypes.apply_tactic
138                   (PrimitiveTactics.apply_tac ~term:(CicUtil.term_of_uri uri))
139                   status
140               in
141               let goal_list =
142                 List.stable_sort (compare_goal_list proof) goal_list
143               in
144               Some (uri, (proof, goal_list))
145             with ProofEngineTypes.Fail _ -> None
146           in
147           match status' with
148           | None -> aux tl
149           | Some status' ->
150               prerr_endline ("HO APPLICATO " ^ uri);
151               status' :: aux tl)
152   in
153   aux uris
154