src/HOL/Tools/ATP/reduce_axiomsN.ML
author paulson
Sat, 15 Jul 2006 15:26:50 +0200
changeset 20132 de3c295000b2
parent 19448 72dab71cb11e
child 20153 6ff5d35749b0
permissions -rw-r--r--
Replaced a-lists by tables to improve efficiency
paulson@19208
     1
(* Authors: Jia Meng, NICTA and Lawrence C Paulson, Cambridge University Computer Laboratory
paulson@19208
     2
   ID: $Id$
paulson@19208
     3
   Filtering strategies *)
paulson@19208
     4
mengj@18791
     5
structure ReduceAxiomsN =
mengj@18791
     6
struct
mengj@18791
     7
paulson@19315
     8
val pass_mark = ref 0.6;
paulson@19337
     9
val convergence = ref 2.4;   (*Higher numbers allow longer inference chains*)
paulson@19337
    10
val follow_defs = ref true;  (*Follow definitions. Makes problems bigger.*)
mengj@18791
    11
paulson@19337
    12
fun log_weight2 (x:real) = 1.0 + 2.0/Math.ln (x+1.0);
paulson@19337
    13
paulson@19337
    14
(*The default seems best in practice. A constant function of one ignores
paulson@19337
    15
  the constant frequencies.*)
paulson@19337
    16
val weight_fn = ref log_weight2;
paulson@19334
    17
mengj@18791
    18
paulson@19231
    19
(*Including equality in this list might be expected to stop rules like subset_antisym from
paulson@19231
    20
  being chosen, but for some reason filtering works better with them listed.*)
paulson@19208
    21
val standard_consts =
paulson@19315
    22
  ["Trueprop","==>","all","Ex","op &","op |","Not","All","op -->",
paulson@19315
    23
   "op =","==","True","False"];
mengj@18791
    24
mengj@18791
    25
mengj@19009
    26
(*** constants with types ***)
mengj@19009
    27
paulson@19231
    28
(*An abstraction of Isabelle types*)
mengj@19009
    29
datatype const_typ =  CTVar | CType of string * const_typ list
mengj@19009
    30
paulson@19208
    31
fun uni_type (CType(con1,args1)) (CType(con2,args2)) = con1=con2 andalso uni_types args1 args2
paulson@19208
    32
  | uni_type (CType _) CTVar = true
mengj@19009
    33
  | uni_type CTVar CTVar = true
mengj@19009
    34
  | uni_type CTVar _ = false
paulson@19208
    35
and uni_types [] [] = true
paulson@19208
    36
  | uni_types (a1::as1) (a2::as2) = uni_type a1 a2 andalso uni_types as1 as2;
mengj@19009
    37
paulson@20132
    38
(*Is there a unifiable constant?*)
paulson@20132
    39
fun uni_mem gctab (c,c_typ) =
paulson@20132
    40
  case Symtab.lookup gctab c of
paulson@20132
    41
      NONE => false
paulson@20132
    42
    | SOME ctyps_list => exists (uni_types c_typ) ctyps_list;
paulson@20132
    43
  
mengj@19009
    44
paulson@19231
    45
fun const_typ_of (Type (c,typs)) = CType (c, map const_typ_of typs) 
paulson@19231
    46
  | const_typ_of (TFree _) = CTVar
paulson@19231
    47
  | const_typ_of (TVar _) = CTVar
mengj@19009
    48
mengj@19009
    49
paulson@19315
    50
fun const_with_typ thy (c,typ) = 
paulson@19212
    51
    let val tvars = Sign.const_typargs thy (c,typ)
paulson@19315
    52
    in (c, map const_typ_of tvars) end
paulson@19315
    53
    handle TYPE _ => (c,[]);   (*Variable (locale constant): monomorphic*)   
mengj@19009
    54
paulson@20132
    55
fun add_const_typ_table ((c,ctyps), tab) =
paulson@20132
    56
  case Symtab.lookup tab c of
paulson@20132
    57
      NONE => Symtab.update (c, [ctyps]) tab
paulson@20132
    58
    | SOME [] => tab  (*ignore!*)
paulson@20132
    59
    | SOME ctyps_list => Symtab.update (c, ctyps ins ctyps_list) tab;
paulson@20132
    60
paulson@19315
    61
(*Free variables are counted, as well as constants, to handle locales*)
paulson@20132
    62
fun add_term_consts_typs_rm thy (Const(c, typ), tab) =
paulson@20132
    63
      add_const_typ_table (const_with_typ thy (c,typ), tab) 
paulson@20132
    64
  | add_term_consts_typs_rm thy (Free(c, typ), tab) =
paulson@20132
    65
      add_const_typ_table (const_with_typ thy (c,typ), tab) 
paulson@20132
    66
  | add_term_consts_typs_rm thy (t $ u, tab) =
paulson@20132
    67
      add_term_consts_typs_rm thy (t, add_term_consts_typs_rm thy (u, tab))
paulson@20132
    68
  | add_term_consts_typs_rm thy (Abs(_,_,t), tab) = add_term_consts_typs_rm thy (t, tab)
paulson@20132
    69
  | add_term_consts_typs_rm thy (_, tab) = tab;
mengj@19009
    70
paulson@20132
    71
(*The empty list here indicates that the constant is being ignored*)
paulson@20132
    72
fun add_standard_const (s,tab) = Symtab.update (s,[]) tab;
mengj@19009
    73
paulson@20132
    74
val null_const_tab : const_typ list list Symtab.table = 
paulson@20132
    75
    foldl add_standard_const Symtab.empty standard_consts;
paulson@20132
    76
paulson@20132
    77
fun get_goal_consts_typs thy cs = foldl (add_term_consts_typs_rm thy) null_const_tab cs;
mengj@19009
    78
paulson@19212
    79
paulson@19231
    80
(**** Constant / Type Frequencies ****)
paulson@19212
    81
paulson@19231
    82
local
paulson@19231
    83
paulson@19231
    84
fun cons_nr CTVar = 0
paulson@19231
    85
  | cons_nr (CType _) = 1;
paulson@19231
    86
paulson@19231
    87
in
paulson@19231
    88
paulson@19231
    89
fun const_typ_ord TU =
paulson@19231
    90
  case TU of
paulson@19231
    91
    (CType (a, Ts), CType (b, Us)) =>
paulson@19231
    92
      (case fast_string_ord(a,b) of EQUAL => dict_ord const_typ_ord (Ts,Us) | ord => ord)
paulson@19231
    93
  | (T, U) => int_ord (cons_nr T, cons_nr U);
paulson@19231
    94
paulson@19231
    95
end;
paulson@19231
    96
paulson@19231
    97
structure CTtab = TableFun(type key = const_typ list val ord = dict_ord const_typ_ord);
paulson@19231
    98
mengj@19355
    99
fun count_axiom_consts thy ((thm,_), tab) = 
paulson@19315
   100
  let fun count_const (a, T, tab) =
paulson@19315
   101
	let val (c, cts) = const_with_typ thy (a,T)
paulson@19315
   102
	    val cttab = Option.getOpt (Symtab.lookup tab c, CTtab.empty)
paulson@19315
   103
	    val n = Option.getOpt (CTtab.lookup cttab cts, 0)
paulson@19315
   104
	in 
paulson@19315
   105
	    Symtab.update (c, CTtab.update (cts, n+1) cttab) tab
paulson@19315
   106
	end
paulson@19315
   107
      fun count_term_consts (Const(a,T), tab) = count_const(a,T,tab)
paulson@19315
   108
	| count_term_consts (Free(a,T), tab) = count_const(a,T,tab)
paulson@19231
   109
	| count_term_consts (t $ u, tab) =
paulson@19231
   110
	    count_term_consts (t, count_term_consts (u, tab))
paulson@19231
   111
	| count_term_consts (Abs(_,_,t), tab) = count_term_consts (t, tab)
paulson@19231
   112
	| count_term_consts (_, tab) = tab
mengj@19355
   113
  in  count_term_consts (prop_of thm, tab)  end;
paulson@19212
   114
mengj@19009
   115
mengj@19009
   116
(******** filter clauses ********)
mengj@19009
   117
paulson@19231
   118
fun const_weight ctab (c, cts) =
paulson@19231
   119
  let val pairs = CTtab.dest (Option.valOf (Symtab.lookup ctab c))
paulson@19231
   120
      fun add ((cts',m), n) = if uni_types cts cts' then m+n else n
paulson@19231
   121
  in  List.foldl add 0 pairs  end;
paulson@19231
   122
paulson@19231
   123
fun add_ct_weight ctab ((c,T), w) =
paulson@19231
   124
  w + !weight_fn (real (const_weight ctab (c,T)));
paulson@19212
   125
paulson@19212
   126
fun consts_typs_weight ctab =
paulson@19212
   127
    List.foldl (add_ct_weight ctab) 0.0;
paulson@19212
   128
paulson@19231
   129
(*Relevant constants are weighted according to frequency, 
paulson@19231
   130
  but irrelevant constants are simply counted. Otherwise, Skolem functions,
paulson@19231
   131
  which are rare, would harm a clause's chances of being picked.*)
paulson@19315
   132
fun clause_weight ctab gctyps consts_typs =
paulson@20132
   133
    let val rel = filter (uni_mem gctyps) consts_typs
paulson@19231
   134
        val rel_weight = consts_typs_weight ctab rel
mengj@19009
   135
    in
paulson@19231
   136
	rel_weight / (rel_weight + real (length consts_typs - length rel))
mengj@19009
   137
    end;
paulson@19315
   138
    
paulson@20132
   139
fun add_consts_with_typs (c,[]) cpairs = cpairs
paulson@20132
   140
  | add_consts_with_typs (c, ctyps_list) cpairs =
paulson@20132
   141
      foldl (fn (ctyps,cpairs) => (c,ctyps)::cpairs) cpairs ctyps_list;
paulson@20132
   142
paulson@20132
   143
fun consts_typs_of_term thy t = 
paulson@20132
   144
  let val tab = add_term_consts_typs_rm thy (t, null_const_tab)
paulson@20132
   145
  in  Symtab.fold add_consts_with_typs tab []  end;
paulson@20132
   146
mengj@19355
   147
fun pair_consts_typs_axiom thy (thm,name) =
mengj@19355
   148
    ((thm,name), (consts_typs_of_term thy (prop_of thm)));
mengj@19009
   149
paulson@19321
   150
exception ConstFree;
paulson@19321
   151
fun dest_ConstFree (Const aT) = aT
paulson@19321
   152
  | dest_ConstFree (Free aT) = aT
paulson@19321
   153
  | dest_ConstFree _ = raise ConstFree;
paulson@19321
   154
paulson@19321
   155
(*Look for definitions of the form f ?x1 ... ?xn = t, but not reversed.*)
mengj@19355
   156
fun defines thy (thm,(name,n)) gctypes =
mengj@19355
   157
    let val tm = prop_of thm
paulson@19448
   158
	fun defs lhs rhs =
paulson@19448
   159
            let val (rator,args) = strip_comb lhs
mengj@19355
   160
		val ct = const_with_typ thy (dest_ConstFree rator)
paulson@20132
   161
            in  forall is_Var args andalso 
paulson@20132
   162
                term_varnames rhs subset term_varnames lhs andalso
paulson@20132
   163
                uni_mem gctypes ct 
paulson@19448
   164
            end
paulson@19448
   165
	    handle ConstFree => false
mengj@19355
   166
    in    
paulson@19448
   167
	case tm of Const ("Trueprop",_) $ (Const("op =",_) $ lhs $ rhs) => 
paulson@19448
   168
		   defs lhs rhs andalso
mengj@19355
   169
		   (Output.debug ("Definition found: " ^ name ^ "_" ^ Int.toString n); true)
mengj@19355
   170
		 | _ => false
paulson@20132
   171
    end;
paulson@19321
   172
paulson@19337
   173
fun relevant_clauses thy ctab p rel_consts =
paulson@19337
   174
  let fun relevant (newrels,rejects) []  =
paulson@19337
   175
	    if null newrels then [] 
paulson@19337
   176
	    else 
paulson@20132
   177
	      let val new_consts = List.concat (map #2 newrels)
paulson@20132
   178
	          val rel_consts' = foldl add_const_typ_table rel_consts new_consts
paulson@19337
   179
                  val newp = p + (1.0-p) / !convergence
paulson@19337
   180
	      in Output.debug ("found relevant: " ^ Int.toString (length newrels));
paulson@19337
   181
                 newrels @ relevant_clauses thy ctab newp rel_consts' rejects
paulson@19337
   182
	      end
mengj@19355
   183
	| relevant (newrels,rejects) ((ax as (clsthm,consts_typs)) :: axs) =
paulson@19337
   184
	    let val weight = clause_weight ctab rel_consts consts_typs
paulson@19337
   185
	    in
mengj@19355
   186
	      if p <= weight orelse (!follow_defs andalso defines thy clsthm rel_consts)
paulson@19337
   187
	      then relevant (ax::newrels, rejects) axs
paulson@19337
   188
	      else relevant (newrels, ax::rejects) axs
paulson@19337
   189
	    end
paulson@19337
   190
    in  Output.debug ("relevant_clauses: " ^ Real.toString p);
paulson@19337
   191
        relevant ([],[]) end;
paulson@19337
   192
	
paulson@19337
   193
     
paulson@19315
   194
fun relevance_filter_aux thy axioms goals = 
paulson@19315
   195
  let val const_tab = List.foldl (count_axiom_consts thy) Symtab.empty axioms
paulson@19231
   196
      val goals_consts_typs = get_goal_consts_typs thy goals
paulson@19337
   197
      val rels = relevant_clauses thy const_tab (!pass_mark) goals_consts_typs 
paulson@19334
   198
                   (map (pair_consts_typs_axiom thy) axioms)
paulson@19231
   199
  in
paulson@19334
   200
      Output.debug ("Total relevant: " ^ Int.toString (length rels));
paulson@19334
   201
      rels
paulson@19231
   202
  end;
mengj@19009
   203
paulson@19315
   204
fun relevance_filter thy axioms goals =
paulson@19337
   205
  if !pass_mark < 0.1 then axioms
paulson@19337
   206
  else map #1 (relevance_filter_aux thy axioms goals);
mengj@19009
   207
    
mengj@18791
   208
mengj@18791
   209
end;