src/HOL/Tools/ATP/reduce_axiomsN.ML
author paulson
Thu Mar 23 10:05:03 2006 +0100 (2006-03-23)
changeset 19321 30b5bb35dd33
parent 19315 b218cc3d1bb4
child 19334 96ca738055a6
permissions -rw-r--r--
detection of definitions of relevant constants
     1 (* Authors: Jia Meng, NICTA and Lawrence C Paulson, Cambridge University Computer Laboratory
     2    ID: $Id$
     3    Filtering strategies *)
     4 
     5 structure ReduceAxiomsN =
     6 struct
     7 
     8 val pass_mark = ref 0.6;
     9 val reduction_factor = ref 1.0;
    10 
    11 (*Whether all "simple" unit clauses should be included*)
    12 val add_unit = ref false;
    13 val unit_pass_mark = ref 0.0;
    14 
    15 
    16 (*Including equality in this list might be expected to stop rules like subset_antisym from
    17   being chosen, but for some reason filtering works better with them listed.*)
    18 val standard_consts =
    19   ["Trueprop","==>","all","Ex","op &","op |","Not","All","op -->",
    20    "op =","==","True","False"];
    21 
    22 
    23 (*** unit clauses ***)
    24 datatype clause_kind = Unit_neq | Unit_geq | Other
    25 
    26 
    27 fun literals_of_term args (Const ("Trueprop",_) $ P) = literals_of_term args P
    28   | literals_of_term args (Const ("op |",_) $ P $ Q) = 
    29     literals_of_term (literals_of_term args P) Q
    30   | literals_of_term args P = P::args;
    31 
    32 fun is_ground t = (term_vars t = []) andalso (term_frees t = []);
    33 
    34 fun eq_clause_type (P,Q) = 
    35     if ((is_ground P) orelse (is_ground Q)) then Unit_geq else Other;
    36 
    37 fun unit_clause_type (Const ("op =",_) $ P $ Q) = eq_clause_type (P,Q)
    38   | unit_clause_type _ = Unit_neq;
    39 
    40 fun clause_kind tm = 
    41     case literals_of_term [] tm of
    42         [lit] => unit_clause_type lit
    43       | _ => Other;
    44 
    45 (*** constants with types ***)
    46 
    47 (*An abstraction of Isabelle types*)
    48 datatype const_typ =  CTVar | CType of string * const_typ list
    49 
    50 fun uni_type (CType(con1,args1)) (CType(con2,args2)) = con1=con2 andalso uni_types args1 args2
    51   | uni_type (CType _) CTVar = true
    52   | uni_type CTVar CTVar = true
    53   | uni_type CTVar _ = false
    54 and uni_types [] [] = true
    55   | uni_types (a1::as1) (a2::as2) = uni_type a1 a2 andalso uni_types as1 as2;
    56 
    57 
    58 fun uni_constants (c1,ctp1) (c2,ctp2) = (c1=c2) andalso uni_types ctp1 ctp2;
    59 
    60 fun uni_mem _ [] = false
    61   | uni_mem (c,c_typ) ((c1,c_typ1)::ctyps) =
    62       uni_constants (c1,c_typ1) (c,c_typ) orelse uni_mem (c,c_typ) ctyps;
    63 
    64 fun const_typ_of (Type (c,typs)) = CType (c, map const_typ_of typs) 
    65   | const_typ_of (TFree _) = CTVar
    66   | const_typ_of (TVar _) = CTVar
    67 
    68 
    69 fun const_with_typ thy (c,typ) = 
    70     let val tvars = Sign.const_typargs thy (c,typ)
    71     in (c, map const_typ_of tvars) end
    72     handle TYPE _ => (c,[]);   (*Variable (locale constant): monomorphic*)   
    73 
    74 (*Free variables are counted, as well as constants, to handle locales*)
    75 fun add_term_consts_typs_rm thy (Const(c, typ)) cs =
    76       if (c mem standard_consts) then cs 
    77       else const_with_typ thy (c,typ) ins cs
    78   | add_term_consts_typs_rm thy (Free(c, typ)) cs =
    79       const_with_typ thy (c,typ) ins cs
    80   | add_term_consts_typs_rm thy (t $ u) cs =
    81       add_term_consts_typs_rm thy t (add_term_consts_typs_rm thy u cs)
    82   | add_term_consts_typs_rm thy (Abs(_,_,t)) cs = add_term_consts_typs_rm thy t cs
    83   | add_term_consts_typs_rm thy _ cs = cs;
    84 
    85 fun consts_typs_of_term thy t = add_term_consts_typs_rm thy t [];
    86 
    87 fun get_goal_consts_typs thy cs = foldl (op union) [] (map (consts_typs_of_term thy) cs)
    88 
    89 
    90 (**** Constant / Type Frequencies ****)
    91 
    92 
    93 local
    94 
    95 fun cons_nr CTVar = 0
    96   | cons_nr (CType _) = 1;
    97 
    98 in
    99 
   100 fun const_typ_ord TU =
   101   case TU of
   102     (CType (a, Ts), CType (b, Us)) =>
   103       (case fast_string_ord(a,b) of EQUAL => dict_ord const_typ_ord (Ts,Us) | ord => ord)
   104   | (T, U) => int_ord (cons_nr T, cons_nr U);
   105 
   106 end;
   107 
   108 structure CTtab = TableFun(type key = const_typ list val ord = dict_ord const_typ_ord);
   109 
   110 fun count_axiom_consts thy ((t,_), tab) = 
   111   let fun count_const (a, T, tab) =
   112 	let val (c, cts) = const_with_typ thy (a,T)
   113 	    val cttab = Option.getOpt (Symtab.lookup tab c, CTtab.empty)
   114 	    val n = Option.getOpt (CTtab.lookup cttab cts, 0)
   115 	in 
   116 	    Symtab.update (c, CTtab.update (cts, n+1) cttab) tab
   117 	end
   118       fun count_term_consts (Const(a,T), tab) = count_const(a,T,tab)
   119 	| count_term_consts (Free(a,T), tab) = count_const(a,T,tab)
   120 	| count_term_consts (t $ u, tab) =
   121 	    count_term_consts (t, count_term_consts (u, tab))
   122 	| count_term_consts (Abs(_,_,t), tab) = count_term_consts (t, tab)
   123 	| count_term_consts (_, tab) = tab
   124   in  count_term_consts (t, tab)  end;
   125 
   126 
   127 (******** filter clauses ********)
   128 
   129 (*The default ignores the constant-count and gives the old Strategy 3*)
   130 val weight_fn = ref (fn x : real => 1.0);
   131 
   132 fun const_weight ctab (c, cts) =
   133   let val pairs = CTtab.dest (Option.valOf (Symtab.lookup ctab c))
   134       fun add ((cts',m), n) = if uni_types cts cts' then m+n else n
   135   in  List.foldl add 0 pairs  end;
   136 
   137 fun add_ct_weight ctab ((c,T), w) =
   138   w + !weight_fn (real (const_weight ctab (c,T)));
   139 
   140 fun consts_typs_weight ctab =
   141     List.foldl (add_ct_weight ctab) 0.0;
   142 
   143 (*Relevant constants are weighted according to frequency, 
   144   but irrelevant constants are simply counted. Otherwise, Skolem functions,
   145   which are rare, would harm a clause's chances of being picked.*)
   146 fun clause_weight ctab gctyps consts_typs =
   147     let val rel = filter (fn s => uni_mem s gctyps) consts_typs
   148         val rel_weight = consts_typs_weight ctab rel
   149     in
   150 	rel_weight / (rel_weight + real (length consts_typs - length rel))
   151     end;
   152     
   153 fun relevant_clauses ctab rel_axs [] (addc,tmpc) keep =
   154       if null addc orelse null tmpc 
   155       then (addc @ rel_axs @ keep, tmpc)   (*termination!*)
   156       else relevant_clauses ctab addc tmpc ([],[]) (rel_axs @ keep)
   157   | relevant_clauses ctab rel_axs ((clstm,(consts_typs,w))::e_axs) (addc,tmpc) keep =
   158       let fun clause_weight_ax (_,(refconsts_typs,wa)) =
   159               wa * clause_weight ctab refconsts_typs consts_typs;
   160           val weight' = List.foldl Real.max w (map clause_weight_ax rel_axs)
   161 	  val e_ax' = (clstm, (consts_typs,weight'))
   162       in
   163 	if !pass_mark <= weight' 
   164 	then relevant_clauses ctab rel_axs e_axs (e_ax'::addc, tmpc) keep
   165 	else relevant_clauses ctab rel_axs e_axs (addc, e_ax'::tmpc) keep
   166       end;
   167 
   168 fun pair_consts_typs_axiom thy (tm,name) =
   169     ((tm,name), (consts_typs_of_term thy tm));
   170 
   171 (*Unit clauses other than non-trivial equations can be included subject to
   172   a separate (presumably lower) mark. *)
   173 fun good_unit_clause ((t,_), (_,w)) = 
   174      !unit_pass_mark <= w andalso
   175      (case clause_kind t of
   176 	  Unit_neq => true
   177 	| Unit_geq => true
   178 	| Other => false);
   179 	
   180 fun axiom_ord ((_,(_,w1)), (_,(_,w2))) = Real.compare (w2,w1);
   181 
   182 fun showconst (c,cttab) = 
   183       List.app (fn n => Output.debug (Int.toString n ^ " occurrences of " ^ c))
   184 	        (map #2 (CTtab.dest cttab))
   185 
   186 fun show_cname (name,k) = name ^ "__" ^ Int.toString k;
   187 
   188 fun showax ((_,cname), (_,w)) = 
   189     Output.debug ("Axiom " ^ show_cname cname ^ " has weight " ^ Real.toString w)
   190 	      
   191 exception ConstFree;
   192 fun dest_ConstFree (Const aT) = aT
   193   | dest_ConstFree (Free aT) = aT
   194   | dest_ConstFree _ = raise ConstFree;
   195 
   196 (*Look for definitions of the form f ?x1 ... ?xn = t, but not reversed.*)
   197 fun defines thy (tm,(name,n)) gctypes =
   198   let fun defs hs =
   199         let val (rator,args) = strip_comb hs
   200             val ct = const_with_typ thy (dest_ConstFree rator)
   201         in  forall is_Var args andalso uni_mem ct gctypes  end
   202         handle ConstFree => false
   203   in    
   204     case tm of Const ("Trueprop",_) $ (Const("op =",_) $ lhs $ _) => 
   205           defs lhs andalso
   206           (Output.debug ("Definition found: " ^ name ^ "_" ^ Int.toString n); true)
   207       | _ => false
   208   end
   209 
   210 fun relevance_filter_aux thy axioms goals = 
   211   let val const_tab = List.foldl (count_axiom_consts thy) Symtab.empty axioms
   212       val goals_consts_typs = get_goal_consts_typs thy goals
   213       fun relevant [] (rels,nonrels) = (rels,nonrels)
   214 	| relevant ((clstm,consts_typs)::axs) (rels,nonrels) =
   215 	    let val weight = clause_weight const_tab goals_consts_typs consts_typs
   216 		val ccc = (clstm, (consts_typs,weight))
   217 	    in
   218 	      if !pass_mark <= weight orelse defines thy clstm goals_consts_typs
   219 	      then relevant axs (ccc::rels, nonrels)
   220 	      else relevant axs (rels, ccc::nonrels)
   221 	    end
   222       val (rel_clauses,nrel_clauses) =
   223 	  relevant (map (pair_consts_typs_axiom thy) axioms) ([],[]) 
   224       val (rels,nonrels) = relevant_clauses const_tab rel_clauses nrel_clauses ([],[]) []
   225       val max_filtered = floor (!reduction_factor * real (length rels))
   226       val rels' = Library.take(max_filtered, Library.sort axiom_ord rels)
   227   in
   228       if !Output.show_debug_msgs then
   229 	   (List.app showconst (Symtab.dest const_tab);
   230 	    List.app showax rels)
   231       else ();
   232       if !add_unit then (filter good_unit_clause nonrels) @ rels'
   233       else rels'
   234   end;
   235 
   236 fun relevance_filter thy axioms goals =
   237   map #1 (relevance_filter_aux thy axioms goals);
   238     
   239 
   240 end;