src/HOL/Tools/refute.ML
changeset 34120 f9920a3ddf50
parent 34017 ef2776c89799
child 34974 18b41bba42b5
equal deleted inserted replaced
34086:ff8b2ac0134c 34120:f9920a3ddf50
    43   val set_default_param  : (string * string) -> theory -> theory
    43   val set_default_param  : (string * string) -> theory -> theory
    44   val get_default_param  : theory -> string -> string option
    44   val get_default_param  : theory -> string -> string option
    45   val get_default_params : theory -> (string * string) list
    45   val get_default_params : theory -> (string * string) list
    46   val actual_params      : theory -> (string * string) list -> params
    46   val actual_params      : theory -> (string * string) list -> params
    47 
    47 
    48   val find_model : theory -> params -> term -> bool -> unit
    48   val find_model : theory -> params -> term list -> term -> bool -> unit
    49 
    49 
    50   (* tries to find a model for a formula: *)
    50   (* tries to find a model for a formula: *)
    51   val satisfy_term   : theory -> (string * string) list -> term -> unit
    51   val satisfy_term :
       
    52     theory -> (string * string) list -> term list -> term -> unit
    52   (* tries to find a model that refutes a formula: *)
    53   (* tries to find a model that refutes a formula: *)
    53   val refute_term : theory -> (string * string) list -> term -> unit
    54   val refute_term :
    54   val refute_goal : theory -> (string * string) list -> thm -> int -> unit
    55     theory -> (string * string) list -> term list -> term -> unit
       
    56   val refute_goal :
       
    57     Proof.context -> (string * string) list -> thm -> int -> unit
    55 
    58 
    56   val setup : theory -> theory
    59   val setup : theory -> theory
    57 
    60 
    58 (* ------------------------------------------------------------------------- *)
    61 (* ------------------------------------------------------------------------- *)
    59 (* Additional functions used by Nitpick (to be factored out)                 *)
    62 (* Additional functions used by Nitpick (to be factored out)                 *)
   151 (* "maxvars"     int     If >0, use at most 'maxvars' Boolean variables      *)
   154 (* "maxvars"     int     If >0, use at most 'maxvars' Boolean variables      *)
   152 (*                       when transforming the term into a propositional     *)
   155 (*                       when transforming the term into a propositional     *)
   153 (*                       formula.                                            *)
   156 (*                       formula.                                            *)
   154 (* "maxtime"     int     If >0, terminate after at most 'maxtime' seconds.   *)
   157 (* "maxtime"     int     If >0, terminate after at most 'maxtime' seconds.   *)
   155 (* "satsolver"   string  SAT solver to be used.                              *)
   158 (* "satsolver"   string  SAT solver to be used.                              *)
       
   159 (* "no_assms"    bool    If "true", assumptions in structured proofs are     *)
       
   160 (*                       not considered.                                     *)
   156 (* "expect"      string  Expected result ("genuine", "potential", "none", or *)
   161 (* "expect"      string  Expected result ("genuine", "potential", "none", or *)
   157 (*                       "unknown")                                          *)
   162 (*                       "unknown").                                         *)
   158 (* ------------------------------------------------------------------------- *)
   163 (* ------------------------------------------------------------------------- *)
   159 
   164 
   160   type params =
   165   type params =
   161     {
   166     {
   162       sizes    : (string * int) list,
   167       sizes    : (string * int) list,
   163       minsize  : int,
   168       minsize  : int,
   164       maxsize  : int,
   169       maxsize  : int,
   165       maxvars  : int,
   170       maxvars  : int,
   166       maxtime  : int,
   171       maxtime  : int,
   167       satsolver: string,
   172       satsolver: string,
       
   173       no_assms : bool,
   168       expect   : string
   174       expect   : string
   169     };
   175     };
   170 
   176 
   171 (* ------------------------------------------------------------------------- *)
   177 (* ------------------------------------------------------------------------- *)
   172 (* interpretation: a term's interpretation is given by a variable of type    *)
   178 (* interpretation: a term's interpretation is given by a variable of type    *)
   358 
   364 
   359   (* theory -> (string * string) list -> params *)
   365   (* theory -> (string * string) list -> params *)
   360 
   366 
   361   fun actual_params thy override =
   367   fun actual_params thy override =
   362   let
   368   let
       
   369     (* (string * string) list * string -> bool *)
       
   370     fun read_bool (parms, name) =
       
   371       case AList.lookup (op =) parms name of
       
   372         SOME "true" => true
       
   373       | SOME "false" => false
       
   374       | SOME s => error ("parameter " ^ quote name ^
       
   375         " (value is " ^ quote s ^ ") must be \"true\" or \"false\"")
       
   376       | NONE   => error ("parameter " ^ quote name ^
       
   377           " must be assigned a value")
   363     (* (string * string) list * string -> int *)
   378     (* (string * string) list * string -> int *)
   364     fun read_int (parms, name) =
   379     fun read_int (parms, name) =
   365       case AList.lookup (op =) parms name of
   380       case AList.lookup (op =) parms name of
   366         SOME s => (case Int.fromString s of
   381         SOME s => (case Int.fromString s of
   367           SOME i => i
   382           SOME i => i
   383     val maxsize   = read_int (allparams, "maxsize")
   398     val maxsize   = read_int (allparams, "maxsize")
   384     val maxvars   = read_int (allparams, "maxvars")
   399     val maxvars   = read_int (allparams, "maxvars")
   385     val maxtime   = read_int (allparams, "maxtime")
   400     val maxtime   = read_int (allparams, "maxtime")
   386     (* string *)
   401     (* string *)
   387     val satsolver = read_string (allparams, "satsolver")
   402     val satsolver = read_string (allparams, "satsolver")
       
   403     val no_assms = read_bool (allparams, "no_assms")
   388     val expect = the_default "" (AList.lookup (op =) allparams "expect")
   404     val expect = the_default "" (AList.lookup (op =) allparams "expect")
   389     (* all remaining parameters of the form "string=int" are collected in *)
   405     (* all remaining parameters of the form "string=int" are collected in *)
   390     (* 'sizes'                                                            *)
   406     (* 'sizes'                                                            *)
   391     (* TODO: it is currently not possible to specify a size for a type    *)
   407     (* TODO: it is currently not possible to specify a size for a type    *)
   392     (*       whose name is one of the other parameters (e.g. 'maxvars')   *)
   408     (*       whose name is one of the other parameters (e.g. 'maxvars')   *)
   393     (* (string * int) list *)
   409     (* (string * int) list *)
   394     val sizes     = map_filter
   410     val sizes     = map_filter
   395       (fn (name, value) => Option.map (pair name) (Int.fromString value))
   411       (fn (name, value) => Option.map (pair name) (Int.fromString value))
   396       (filter (fn (name, _) => name<>"minsize" andalso name<>"maxsize"
   412       (filter (fn (name, _) => name<>"minsize" andalso name<>"maxsize"
   397         andalso name<>"maxvars" andalso name<>"maxtime"
   413         andalso name<>"maxvars" andalso name<>"maxtime"
   398         andalso name<>"satsolver") allparams)
   414         andalso name<>"satsolver" andalso name<>"no_assms") allparams)
   399   in
   415   in
   400     {sizes=sizes, minsize=minsize, maxsize=maxsize, maxvars=maxvars,
   416     {sizes=sizes, minsize=minsize, maxsize=maxsize, maxvars=maxvars,
   401       maxtime=maxtime, satsolver=satsolver, expect=expect}
   417       maxtime=maxtime, satsolver=satsolver, no_assms=no_assms, expect=expect}
   402   end;
   418   end;
   403 
   419 
   404 
   420 
   405 (* ------------------------------------------------------------------------- *)
   421 (* ------------------------------------------------------------------------- *)
   406 (* TRANSLATION HOL -> PROPOSITIONAL LOGIC, BOOLEAN ASSIGNMENT -> MODEL       *)
   422 (* TRANSLATION HOL -> PROPOSITIONAL LOGIC, BOOLEAN ASSIGNMENT -> MODEL       *)
  1116 (* find_model: repeatedly calls 'interpret' with appropriate parameters,     *)
  1132 (* find_model: repeatedly calls 'interpret' with appropriate parameters,     *)
  1117 (*             applies a SAT solver, and (in case a model is found) displays *)
  1133 (*             applies a SAT solver, and (in case a model is found) displays *)
  1118 (*             the model to the user by calling 'print_model'                *)
  1134 (*             the model to the user by calling 'print_model'                *)
  1119 (* thy       : the current theory                                            *)
  1135 (* thy       : the current theory                                            *)
  1120 (* {...}     : parameters that control the translation/model generation      *)
  1136 (* {...}     : parameters that control the translation/model generation      *)
       
  1137 (* assm_ts   : assumptions to be considered unless "no_assms" is specified   *)
  1121 (* t         : term to be translated into a propositional formula            *)
  1138 (* t         : term to be translated into a propositional formula            *)
  1122 (* negate    : if true, find a model that makes 't' false (rather than true) *)
  1139 (* negate    : if true, find a model that makes 't' false (rather than true) *)
  1123 (* ------------------------------------------------------------------------- *)
  1140 (* ------------------------------------------------------------------------- *)
  1124 
  1141 
  1125   (* theory -> params -> Term.term -> bool -> unit *)
  1142   (* theory -> params -> Term.term -> bool -> unit *)
  1126 
  1143 
  1127   fun find_model thy {sizes, minsize, maxsize, maxvars, maxtime, satsolver,
  1144   fun find_model thy {sizes, minsize, maxsize, maxvars, maxtime, satsolver,
  1128     expect} t negate =
  1145     no_assms, expect} assm_ts t negate =
  1129   let
  1146   let
  1130     (* string -> unit *)
  1147     (* string -> unit *)
  1131     fun check_expect outcome_code =
  1148     fun check_expect outcome_code =
  1132       if expect = "" orelse outcome_code = expect then ()
  1149       if expect = "" orelse outcome_code = expect then ()
  1133       else error ("Unexpected outcome: " ^ quote outcome_code ^ ".")
  1150       else error ("Unexpected outcome: " ^ quote outcome_code ^ ".")
  1134     (* unit -> unit *)
  1151     (* unit -> unit *)
  1135     fun wrapper () =
  1152     fun wrapper () =
  1136     let
  1153     let
  1137       val timer  = Timer.startRealTimer ()
  1154       val timer  = Timer.startRealTimer ()
       
  1155       val t = if no_assms then t
       
  1156               else if negate then Logic.list_implies (assm_ts, t)
       
  1157               else Logic.mk_conjunction_list (t :: assm_ts)
  1138       val u      = unfold_defs thy t
  1158       val u      = unfold_defs thy t
  1139       val _      = tracing ("Unfolded term: " ^ Syntax.string_of_term_global thy u)
  1159       val _      = tracing ("Unfolded term: " ^ Syntax.string_of_term_global thy u)
  1140       val axioms = collect_axioms thy u
  1160       val axioms = collect_axioms thy u
  1141       (* Term.typ list *)
  1161       (* Term.typ list *)
  1142       val types = fold (union (op =) o ground_types thy) (u :: axioms) []
  1162       val types = fold (union (op =) o ground_types thy) (u :: axioms) []
  1268 (* satisfy_term: calls 'find_model' to find a model that satisfies 't'       *)
  1288 (* satisfy_term: calls 'find_model' to find a model that satisfies 't'       *)
  1269 (* params      : list of '(name, value)' pairs used to override default      *)
  1289 (* params      : list of '(name, value)' pairs used to override default      *)
  1270 (*               parameters                                                  *)
  1290 (*               parameters                                                  *)
  1271 (* ------------------------------------------------------------------------- *)
  1291 (* ------------------------------------------------------------------------- *)
  1272 
  1292 
  1273   (* theory -> (string * string) list -> Term.term -> unit *)
  1293   (* theory -> (string * string) list -> Term.term list -> Term.term -> unit *)
  1274 
  1294 
  1275   fun satisfy_term thy params t =
  1295   fun satisfy_term thy params assm_ts t =
  1276     find_model thy (actual_params thy params) t false;
  1296     find_model thy (actual_params thy params) assm_ts t false;
  1277 
  1297 
  1278 (* ------------------------------------------------------------------------- *)
  1298 (* ------------------------------------------------------------------------- *)
  1279 (* refute_term: calls 'find_model' to find a model that refutes 't'          *)
  1299 (* refute_term: calls 'find_model' to find a model that refutes 't'          *)
  1280 (* params     : list of '(name, value)' pairs used to override default       *)
  1300 (* params     : list of '(name, value)' pairs used to override default       *)
  1281 (*              parameters                                                   *)
  1301 (*              parameters                                                   *)
  1282 (* ------------------------------------------------------------------------- *)
  1302 (* ------------------------------------------------------------------------- *)
  1283 
  1303 
  1284   (* theory -> (string * string) list -> Term.term -> unit *)
  1304   (* theory -> (string * string) list -> Term.term list -> Term.term -> unit *)
  1285 
  1305 
  1286   fun refute_term thy params t =
  1306   fun refute_term thy params assm_ts t =
  1287   let
  1307   let
  1288     (* disallow schematic type variables, since we cannot properly negate  *)
  1308     (* disallow schematic type variables, since we cannot properly negate  *)
  1289     (* terms containing them (their logical meaning is that there EXISTS a *)
  1309     (* terms containing them (their logical meaning is that there EXISTS a *)
  1290     (* type s.t. ...; to refute such a formula, we would have to show that *)
  1310     (* type s.t. ...; to refute such a formula, we would have to show that *)
  1291     (* for ALL types, not ...)                                             *)
  1311     (* for ALL types, not ...)                                             *)
  1330       [] : (string * typ) list
  1350       [] : (string * typ) list
  1331     val strip_t = strip_all_body ex_closure
  1351     val strip_t = strip_all_body ex_closure
  1332     val frees   = Term.rename_wrt_term strip_t (strip_all_vars ex_closure)
  1352     val frees   = Term.rename_wrt_term strip_t (strip_all_vars ex_closure)
  1333     val subst_t = Term.subst_bounds (map Free frees, strip_t)
  1353     val subst_t = Term.subst_bounds (map Free frees, strip_t)
  1334   in
  1354   in
  1335     find_model thy (actual_params thy params) subst_t true
  1355     find_model thy (actual_params thy params) assm_ts subst_t true
       
  1356     handle REFUTE (s, s') => error ("REFUTE " ^ s ^ " " ^ s') (* ### *)
  1336   end;
  1357   end;
  1337 
  1358 
  1338 (* ------------------------------------------------------------------------- *)
  1359 (* ------------------------------------------------------------------------- *)
  1339 (* refute_goal                                                               *)
  1360 (* refute_goal                                                               *)
  1340 (* ------------------------------------------------------------------------- *)
  1361 (* ------------------------------------------------------------------------- *)
  1341 
  1362 
  1342   fun refute_goal thy params st i =
  1363   fun refute_goal ctxt params th i =
  1343     refute_term thy params (Logic.get_goal (Thm.prop_of st) i);
  1364   let
       
  1365     val t = th |> prop_of
       
  1366   in
       
  1367     if Logic.count_prems t = 0 then
       
  1368       priority "No subgoal!"
       
  1369     else
       
  1370       let
       
  1371         val assms = map term_of (Assumption.all_assms_of ctxt)
       
  1372         val (t, frees) = Logic.goal_params t i
       
  1373       in
       
  1374         refute_term (ProofContext.theory_of ctxt) params assms
       
  1375         (subst_bounds (frees, t))
       
  1376       end
       
  1377   end
  1344 
  1378 
  1345 
  1379 
  1346 (* ------------------------------------------------------------------------- *)
  1380 (* ------------------------------------------------------------------------- *)
  1347 (* INTERPRETERS: Auxiliary Functions                                         *)
  1381 (* INTERPRETERS: Auxiliary Functions                                         *)
  1348 (* ------------------------------------------------------------------------- *)
  1382 (* ------------------------------------------------------------------------- *)