(* Copyright (C) 2000-2002, HELM Team. * * This file is part of HELM, an Hypertextual, Electronic * Library of Mathematics, developed at the Computer Science * Department, University of Bologna, Italy. * * HELM is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * HELM is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HELM; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, * MA 02111-1307, USA. * * For details, see the HELM World-Wide-Web page, * http://cs.unibo.it/helm/. *) (*********************************************************************) (* *) (* PROJECT HELM *) (* *) (* Andrea Asperti, Matteo Selmi *) (* 1/04/2004 *) (* *) (* *) (*********************************************************************) (* the file contains: - functions executing must, just and only constraints on the mysql data base; - the general function cmatch for retrieving all statements matching a given conclusion *) type count_condition = NIL | EQ of int | GT of int ;; let main_conclusion = "'http://www.cs.unibo.it/helm/schemas/schema-helm#MainConclusion'" ;; let in_conclusion = "'http://www.cs.unibo.it/helm/schemas/schema-helm#InConclusion'" ;; let escape = Str.global_replace (Str.regexp_string "\'") "\\'";; let get_inconcl (conn:Mysql.dbd) uri = let uri = escape uri in let query = "select h_occurrence from refObj where source='"^uri^ "' and (h_position="^main_conclusion^" or h_position="^in_conclusion^")" in prerr_endline query; let result = Mysql.exec conn query in (* now we transform the result in a set *) let f a = match (Array.to_list a) with [Some uri] -> uri | _ -> assert false in let result = Mysql.map ~f:f result in List.fold_left (fun set uri -> NewConstraints.StringSet.add uri set) NewConstraints.StringSet.empty result ;; let test_only (conn:Mysql.dbd) only u = let inconcl = get_inconcl conn u in NewConstraints.StringSet.subset inconcl only ;; let rec exec_must (conn:Mysql.dbd) (l:MQGTypes.r_obj list) (cc:count_condition) = let add_must (n,from,where) (pos,uri) = match pos with `MainHypothesis _ -> assert false | `MainConclusion None -> let refObjn = "refObj" ^ (string_of_int n) in let new_must = [ refObjn^".h_occurrence = '" ^ uri ^ "'"; refObjn^".h_position = " ^ main_conclusion] in let where' = if n = 0 then new_must@where else (refObjn^".source = refObj" ^ (string_of_int (n-1)) ^ ".source")::new_must@where in (n+1,("refObj as "^refObjn)::from,where') | `MainConclusion(Some(d)) -> let refObjn = "refObj" ^ (string_of_int n) in let new_must = [ refObjn^".h_occurrence = '" ^ uri ^ "'"; refObjn^".h_position = " ^ main_conclusion; refObjn^".h_depth = " ^ (string_of_int d)] in let where' = if n = 0 then new_must@where else (refObjn^".source = refObj" ^ (string_of_int (n-1)) ^ ".source")::new_must@where in (n+1,("refObj as "^refObjn)::from,where') | `InHypothesis -> assert false | `InConclusion -> let refObjn = "refObj" ^ (string_of_int n) in let new_must = [ refObjn^".h_occurrence = '" ^ uri ^ "'"; refObjn^".h_position = " ^ in_conclusion] in let where' = if n = 0 then new_must@where else (refObjn^".source = refObj" ^ (string_of_int (n-1)) ^ ".source")::new_must@where in (n+1,("refObj as "^refObjn)::from,where') | `InBody -> assert false in let (_,from,where) = List.fold_left add_must (0,[],[]) l in let from,where = (match cc with NIL -> from, where | EQ n -> "no_inconcl_aux"::from, ("no=" ^ (string_of_int n)):: ("no_inconcl_aux.source = refObj0.source")::where | GT n -> "no_inconcl_aux"::from, ("no>" ^ (string_of_int n)):: ("no_inconcl_aux.source = refObj0.source")::where) in let from = String.concat "," from in let where = String.concat " and " where in let query = "select refObj0.source from " ^ from ^ " where " ^ where in prerr_endline query; Mysql.exec conn query ;; let (must_of_prefix m s):MQGTypes.r_obj list = let s' = List.map (fun u -> (`InConclusion, u)) s in (`MainConclusion None,m)::s' ;; (* takes a list of lists and returns the list of all elements without repetitions *) let union l = let rec drop_repetitions = function [] -> [] | [a] -> [a] | u1::u2::l when u1 = u2 -> drop_repetitions (u2::l) | u::l -> u::(drop_repetitions l) in drop_repetitions (List.sort Pervasives.compare (List.concat l)) ;; let critical_value = 6;; let just_factor = 3;; let cmatch (conn:Mysql.dbd) t = let eq,constants = NewConstraints.constants_of t in (* the type of eq is not counted in constants_no *) let constants_no = if eq then (NewConstraints.StringSet.cardinal constants) else (NewConstraints.StringSet.cardinal constants) in if (constants_no > critical_value) then let prefixes = NewConstraints.prefixes just_factor t in (match prefixes with Some main, all_concl -> (* NewConstraints.pp_prefixes all_concl; *) (* in some cases, max_prefix_length could be less than n *) let max_prefix_length = match all_concl with [] -> assert false | (max,_)::_ -> max in let maximal_prefixes = let rec filter res = function [] -> res | (n,s)::l when n = max_prefix_length -> filter ((n,s)::res) l | _::_-> res in filter [] all_concl in let greater_than :(int*string) list= let all = union (List.map (fun (m,s) -> (let res = exec_must conn (must_of_prefix main s) (GT (m+1)) in let f a = match (Array.to_list a) with (* we tag the uri with m+1, for sorting purposes *) [Some uri] -> (m+1,uri) | _ -> assert false in Mysql.map ~f:f res)) maximal_prefixes) in List.filter (function (_,uri) -> test_only conn constants uri) all in let equal_to = List.concat (List.map (fun (m,s) -> (let res = exec_must conn (must_of_prefix main s) (EQ (m+1)) in let f a = match (Array.to_list a) with (* we tag the uri with m, for sorting purposes *) [Some uri] -> (m,uri) | _ -> assert false in Mysql.map ~f:f res)) all_concl) in greater_than @ equal_to | _, _ -> []) else if constants_no = 0 then [] else (* in this case we compute all prefixes, and we do not need to apply the only constraints *) let prefixes = NewConstraints.prefixes constants_no t in (match prefixes with Some main, all_concl -> List.concat (List.map (fun (m,s) -> (let res = exec_must conn (must_of_prefix main s) (EQ (m+1)) in let f a = match (Array.to_list a) with (* we tag the uri with m, for sorting purposes *) [Some uri] -> (m,uri) | _ -> assert false in Mysql.map ~f:f res)) all_concl) | _, _ -> []) ;;