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