type mtd = string * (theory -> term -> outcome * timings)
type mutant_subentry = term * (string * (outcome * timings)) list type detailed_entry = string * bool * term * mutant_subentry list
type subentry = string * int * int * int * int * int * int type entry = string * bool * subentry list type report = entry list
val quickcheck_mtd : (Proof.context -> Proof.context) -> string -> mtd
val solve_direct_mtd : mtd val try0_mtd : mtd (* val sledgehammer_mtd : mtd
*) val nitpick_mtd : mtd
val refute_mtd : mtd
val freezeT : term -> term val thms_of : bool -> theory -> thm list
val string_for_report : report -> string val write_report : string -> report -> unit val mutate_theorems_and_write_report :
theory -> int * int -> mtd list -> thm list -> string -> unit
type mtd = string * (theory -> term -> outcome * timings)
type mutant_subentry = term * (string * (outcome * timings)) list type detailed_entry = string * bool * term * mutant_subentry list
type subentry = string * int * int * int * int * int * int type entry = string * bool * subentry list type report = entry list
(* possible invocations *)
(** quickcheck **)
fun invoke_quickcheck change_options thy t =
Timeout.apply (seconds 30.0)
(fn _ => let val ctxt' = change_options (Proof_Context.init_global thy) val (result :: _) = case Quickcheck.active_testers ctxt' of
[] => error "No active testers for quickcheck"
| [tester] => tester ctxt' false [] [(t, [])]
| _ => error "Multiple active testers for quickcheck" in case Quickcheck.counterexample_of result of
NONE => (NoCex, Quickcheck.timings_of result)
| SOME _ => (GenuineCex, Quickcheck.timings_of result) end) () handle Timeout.TIMEOUT _ =>
(Timeout, [("timelimit", Real.floor (Options.default_real \<^system_option>\<open>auto_time_limit\<close>))])
fun quickcheck_mtd change_options quickcheck_generator =
("quickcheck_" ^ quickcheck_generator, invoke_quickcheck change_options)
(** solve direct **)
fun invoke_solve_direct thy t = let val state = Proof.theorem NONE (K I) (map (single o rpair []) [t]) (Proof_Context.init_global thy) in case Solve_Direct.solve_direct state of
(true, _) => (Solved, [])
| (false, _) => (Unsolved, []) end
val solve_direct_mtd = ("solve_direct", invoke_solve_direct)
(** try0 **)
fun invoke_try0 thy t = let val state = Proof.theorem NONE (K I) (map (single o rpair []) [t]) (Proof_Context.init_global thy) in case Try0.try0 (SOME (seconds 5.0)) Try0.empty_facts state of
[] => (Unsolved, [])
| _ => (Solved, []) end
val try0_mtd = ("try0", invoke_try0)
(** sledgehammer **) (* fun invoke_sledgehammer thy t = if can (Goal.prove_global thy (Term.add_free_names t []) [] t) (fn {context, ...} => Sledgehammer_Tactics.sledgehammer_with_metis_tac context 1) then (Solved, ([], NONE)) else (Unsolved, ([], NONE))
val sledgehammer_mtd = ("sledgehammer", invoke_sledgehammer)
*)
fun invoke_refute thy t = let val params = [] val res = Refute.refute_term (Proof_Context.init_global thy) params [] t val _ = writeln ("Refute: " ^ res) in
(rpair []) (case res of "genuine" => GenuineCex
| "likely_genuine" => GenuineCex
| "potential" => PotentialCex
| "none" => NoCex
| "unknown" => Donno
| _ => Error) end handle Refute.REFUTE (loc, details) =>
(error ("Unhandled Refute error (" ^ quote loc ^ "): " ^ details ^ ".")) val refute_mtd = ("refute", invoke_refute)
(** nitpick **)
fun invoke_nitpick thy t = let val ctxt = Proof_Context.init_global thy val state = Proof.init ctxt val (res, _) = Nitpick.pick_nits_in_term state
(Nitpick_Commands.default_params thy []) Nitpick.Normal 1 1 1 [] [] [] t val _ = writeln ("Nitpick: " ^ res) in
(rpair []) (case res of "genuine" => GenuineCex
| "likely_genuine" => GenuineCex
| "potential" => PotentialCex
| "none" => NoCex
| "unknown" => Donno
| _ => Error) end
val nitpick_mtd = ("nitpick", invoke_nitpick)
(* filtering forbidden theorems and mutants *)
val comms = [\<^const_name>\<open>HOL.eq\<close>, \<^const_name>\<open>HOL.disj\<close>, \<^const_name>\<open>HOL.conj\<close>]
fun is_forbidden_mutant t = let val const_names = Term.add_const_names t [] val consts = Term.add_consts t [] in exists (String.isPrefix "Nitpick") const_names orelse exists (String.isSubstring "_sumC") const_names orelse exists (member (op =) forbidden_mutant_constnames) const_names orelse exists (member (op =) forbidden_mutant_consts) consts end
(* executable via quickcheck *)
fun is_executable_term thy t = let val ctxt = Proof_Context.init_global thy in
can (Timeout.apply (seconds 30.0)
(Quickcheck.test_terms
((Context.proof_map (Quickcheck.set_active_testers ["exhaustive"]) #>
Config.put Quickcheck.finite_types true #>
Config.put Quickcheck.finite_type_size 1 #>
Config.put Quickcheck.size 1 #> Config.put Quickcheck.iterations 1) ctxt)
(false, false) [])) (map (rpair [] o Object_Logic.atomize_term ctxt)
(fst (Variable.import_terms true [t] ctxt))) end
fun is_executable_thm thy th = is_executable_term thy (Thm.prop_of th)
val freezeT =
map_types (map_type_tvar (fn ((a, i), S) =>
TFree (if i = 0 then a else a ^ "_" ^ string_of_int i, S)))
fun elapsed_time description e = letval ({elapsed, ...}, result) = Timing.timing e () in (result, (description, Time.toMilliseconds elapsed)) end (* fun unsafe_invoke_mtd thy (mtd_name, invoke_mtd) t = let val _ = writeln ("Invoking " ^ mtd_name) val ((res, (timing, reports)), time) = cpu_time "total time" (fn () => invoke_mtd thy t handle ERROR s => (tracing s; (Error, ([], NONE)))) val _ = writeln (" Done") in (res, (time :: timing, reports)) end
*) fun safe_invoke_mtd thy (mtd_name, invoke_mtd) t = let val _ = writeln ("Invoking " ^ mtd_name) val (res, timing) = elapsed_time "total time"
(fn () => casetry (invoke_mtd thy) t of
SOME (res, _) => res
| NONE => (writeln ("**** PROBLEMS WITH " ^ Syntax.string_of_term_global thy t);
Error)) val _ = writeln (" Done") in (res, [timing]) end
(* creating entries *)
fun create_detailed_entry thy thm exec mutants mtds = let fun create_mutant_subentry mutant = (mutant, map (fn (mtd_name, invoke_mtd) =>
(mtd_name, safe_invoke_mtd thy (mtd_name, invoke_mtd) mutant)) mtds) in
(Thm.get_name_hint thm, exec, Thm.prop_of thm, map create_mutant_subentry mutants) end
(* (theory -> thm -> bool -> term list -> mtd list -> 'a) -> theory -> mtd list -> thm -> 'a *) fun mutate_theorem create_entry thy (num_mutations, max_mutants) mtds thm = let val exec = is_executable_thm thy thm val _ = tracing (if exec then"EXEC"else"NOEXEC") val mutants =
(if num_mutations = 0 then
[Thm.prop_of thm] else
Mutabelle.mutate_mix (Thm.prop_of thm) thy comms forbidden
num_mutations)
|> tap (fn muts => tracing ("mutants: " ^ string_of_int (length muts)))
|> filter_out is_forbidden_mutant val mutants = if exec then let val _ = writeln ("BEFORE PARTITION OF " ^
string_of_int (length mutants) ^ " MUTANTS") val (execs, noexecs) = List.partition (is_executable_term thy) (take_random (20 * max_mutants) mutants) val _ = tracing ("AFTER PARTITION (" ^ string_of_int (length execs) ^ " vs " ^ string_of_int (length noexecs) ^ ")") in
execs @ take_random (Int.max (0, max_mutants - length execs)) noexecs end else
mutants val mutants = mutants
|> map Mutabelle.freeze |> map freezeT (* |> filter (not o is_forbidden_mutant) *)
|> map_filter (try (Sign.cert_term thy))
|> filter (is_some o try (Thm.global_cterm_of thy))
|> filter (is_some o try (Syntax.check_term (Proof_Context.init_global thy)))
|> take_random max_mutants val _ = map (fn t => writeln ("MUTANT: " ^ Syntax.string_of_term_global thy t)) mutants in
create_entry thy thm exec mutants mtds end
fun string_of_mutant_subentry' thy thm_name (t, results) = let (* fun string_of_report (Quickcheck.Report {iterations = i, raised_match_errors = e, satisfied_assms = s, positive_concl_tests = p}) = "errors: " ^ string_of_int e ^ "; conclusion tests: " ^ string_of_int p fun string_of_reports NONE = "" | string_of_reports (SOME reports) = cat_lines (map (fn (size, [report]) =>
"size " ^ string_of_int size ^ ": " ^ string_of_report report) (rev reports))*) fun string_of_mtd_result (mtd_name, (outcome, timing)) =
mtd_name ^ ": " ^ string_of_outcome outcome
^ "(" ^ space_implode "; " (map (fn (s, t) => (s ^ ": " ^ string_of_int t)) timing) ^ ")" (*^ "\n" ^ string_of_reports reports*) in "mutant of " ^ Thm_Name.short thm_name ^ ":\n" ^
Pretty.pure_string_of (Syntax.pretty_term_global thy t) ^ "\n" ^
space_implode "; " (map string_of_mtd_result results) end
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.