theory TPTP_Proof_Reconstruction_Test imports TPTP_Test TPTP_Proof_Reconstruction begin
section"Main function" text"This function wraps all the reconstruction-related functions. Simply point it at a THF proof produced by LEO-II (using the configuration described above), and it will try to reconstruct it into an Isabelle/HOL theorem. It also returns the theory (into which the axioms and definitions used in the proof have been imported), but note that you can get the theory value from the theorem value."
ML ‹
reconstruct_leo2 (Path.explode "$THF_PROOFS/NUM667^1.p.out") @{theory} ›
(*FIXME hack for testing*) fun test_fmla thy =
TPTP_Reconstruct.get_fmlas_of_prob thy (hd prob_names);
fun test_pannot thy =
TPTP_Reconstruct.get_pannot_of_prob thy (hd prob_names);
if test_all @{context} orelse prob_names = [] then ()
else
display_nicely @{context}
(#meta (test_pannot @{theory})) (* To look at the original proof (i.e., before the proof transformations applied whentheproofisloaded)replacepreviouslinewith: (test_fmla@{theory} |>mapTPTP_Reconstruct.structure_fmla_meaning)
*) ›
ML ‹ funstep_range_testerf_xf_exnctxtprob_namefromuntil= let valmax= caseuntilof SOMEx=>x |NONE=> ifis_someInt.maxIntthentheInt.maxIntelse999999 funtest_stepx= ifx>maxthen() else (f_xx; (interpret_leo2_inferencectxtprob_name(Int.toStringx);())
handle e => f_exn e; (*FIXME naive. should let Interrupt through*) (*assumes that inferences are numbered consecutively*)
test_step (x + 1)) in
test_step from end
val step_range_tester_tracing =
step_range_tester
(fn x => tracing ("@step " ^ Int.toString x))
(fn e => tracing ("!!" ^ @{make_string} e)) ›
ML ‹
(*try to reconstruct each inference step*) if test_all @{context} orelse prob_names = []
orelse true (*NOTE currently disabled*) then ()
else let (*FIXME not guaranteed to be the right nodes*)
val heur_start = 3
val heur_end =
hd (#meta (test_pannot @{theory}))
|> #1
|> Int.fromString in
step_range_tester_tracing @{context} (hd prob_names) heur_start heur_end end ›
section"Building metadata and tactics"
subsection"Building the skeleton"
ML ‹ iftest_all@{context}orelseprob_names=[]then[] elseTPTP_Reconstruct.make_skeleton@{context}(test_pannot@{theory});
subsection"The 'piecemeal' approach"
ML ‹ funattacn=List.nth(List.nth(the_tactics,0),n)|>#3|>the|>snd funattac_ton0=attacn |attac_tonm=attacnTHENattac_to(n+1)(m-1) funshotacn=List.nth(List.nth(the_tactics,0),n)|>#3|>the|>fst \<close>
ML\<open> (*Given a list of reconstructed inferences (as in "the_tactics" above, countthenumberoffailuresandsuccesses,andlistthefailedinference
reconstructions.*) fun evaluate_the_tactics [] acc = acc
| evaluate_the_tactics ((node_no, (inf_name, inf_fmla, NONE)) :: xs) ((fai, suc), inf_list) = let
val score = (fai + 1, suc)
val index_info = get_index (fn (x, _) => if x = node_no then SOME true else NONE) inf_list
val inf_list' = case index_info of
NONE => (node_no, (inf_name, inf_fmla, 1)) :: inf_list
| SOME (idx, _) =>
nth_map idx (fn (node_no, (inf_name, inf_fmla, count)) => (node_no, (inf_name, inf_fmla, count + 1))) inf_list in
evaluate_the_tactics xs (score, inf_list') end
| evaluate_the_tactics ((_, (_, _, SOME _)) :: xs) ((fai, suc), inf_list) =
evaluate_the_tactics xs ((fai, suc + 1), inf_list) ›
text"Now we build a tactic by combining lists of tactics"
ML ‹ (*given a list of tactics to be applied in sequence (i.e., they followaskeleton),webuildasingletactic,interleaving
some tracing info to help with debugging.*) fun step_by_step_tacs ctxt verbose (thm_tacs : (thm * tactic) list) : tactic = let fun interleave_tacs [] [] = all_tac
| interleave_tacs (tac1 :: tacs1) (tac2 :: tacs2) =
EVERY [tac1, tac2] THEN interleave_tacs tacs1 tacs2
val thms_to_traceprint =
map (fn thm => fn st => (*FIXME uses makestring*)
print_tac ctxt (@{make_string} thm) st)
in if verbose then
ListPair.unzip thm_tacs
|> apfst (fn thms => enumerate 1 thms)
|> apfst thms_to_traceprint
|> uncurry interleave_tacs
else EVERY (map #2 thm_tacs) end ›
ML ‹
(*apply step_by_step_tacs to all problems under test*) fun narrated_tactics ctxt =
map (map (#3 #> the)
#> step_by_step_tacs ctxt false)
the_tactics;
(*produce thm*) (*use narrated_tactics to reconstruct all problems under test*) if test_all @{context} then []
else
map (fn (prob_name, tac) =>
TPTP_Reconstruct.reconstruct @{context}
(fn _ => tac) prob_name)
(ListPair.zip (prob_names, narrated_tactics @{context})) ›
subsection"Manually using 'piecemeal' approach" text"Another testing possibility involves manually creating a lemma and running through the list of tactics generating to prove that lemma. The following code shows the goal of each problem under test, and then for each problem returns the list of tactics which can be invoked individually as shown below."
ML ‹ funshow_goalctxtprob_name= let valthy=Proof_Context.theory_ofctxt valpannot=TPTP_Reconstruct.get_pannot_of_probthyprob_name in #metapannot |>filter(fn(_,info)=> #roleinfo=TPTP_Syntax.Role_Conjecture) |>hd |>snd|>#fmla |>cterm_ofthy end;
ML\<open>
(*project out the list of tactics from "the_tactics"*)
val just_the_tacs =
map (map (#3 #> the #> #2))
the_tactics;
map length just_the_tacs ›
ML ‹
(*like just_the_tacs, but extract the thms, to inspect their thys*)
val just_the_thms =
map (map (#3 #> the #> #1))
the_tactics;
map length just_the_thms; ›
ML ‹
(*Show the skeleton-level inference which is done by each element of just_the_tacs. This is useful when debugging using the technique shown next*) if test_all @{context} orelse prob_names = [] then ()
else
the_tactics
|> hd
|> map #1
|> TPTP_Reconstruct_Library.enumerate 0
|> List.app (@{make_string} #> writeln) ›
ML ‹ funleo2_tac_wrapctxtprob_namestepist= rtac(interpret_leo2_inferencectxtprob_namestep)ist \<close>
ML ‹
(*if reconstruction_info value is NONE then a big error must have occurred*)
type reconstruction_info =
((int(*no of failures*) * int(*no of successes*)) *
(TPTP_Reconstruct.rolling_stock * term option(*inference formula*) * int (*number of times the inference occurs in the skeleton*)) list) option
datatype proof_contents =
No_info
| Empty
| Nonempty of reconstruction_info
(*To make output less cluttered in whole-run tests*) fun erase_inference_fmlas (Nonempty (SOME (outline, inf_info))) =
Nonempty (SOME (outline, map (fn (inf_name, _, count) => (inf_name, NONE, count)) inf_info))
| erase_inference_fmlas x = x ›
ML ‹ (*Report on how many inferences in a proof are reconstructed, and give some
info about the inferences for which reconstruction failed.*) fun test_partial_reconstruction thy prob_file = let
val prob_name =
prob_file
|> Path.file_name
|> TPTP_Problem_Name.Nonstandard
val ctxt' = if is_some thy' then SOME (Proof_Context.init_global (the thy')) else NONE
(*to test if proof is empty*)
val fms = if is_some thy' then SOME (TPTP_Reconstruct.get_fmlas_of_prob (the thy') prob_name)
else NONE
val the_tactics = if is_some thy' then
SOME (TPTP_Reconstruct.naive_reconstruct_tacs (* metis_based_reconstruction_tac *)
interpret_leo2_inference (* auto_based_reconstruction_tac *) (* oracle_based_reconstruction_tac *) prob_name (the ctxt'))
else NONE
(* val _ = tracing ("tt=" ^ @{make_string} the_tactics) *)
val skeleton = if is_some thy' then
SOME (TPTP_Reconstruct.make_skeleton (the ctxt')
(TPTP_Reconstruct.get_pannot_of_prob (the thy') prob_name))
else NONE
val skeleton_and_tactics = if is_some thy' then
SOME (ListPair.zip (the skeleton, the the_tactics))
else NONE
val result = if is_some thy' then
SOME (evaluate_the_tactics (the skeleton_and_tactics)
((0, 0), []))
else NONE
(*strip node names*)
val result' = if is_some result then SOME (apsnd (map #2) (the result)) else NONE in if is_some fms andalso List.null (the fms) then Empty
else Nonempty result' end ›
ML ‹
(*default timeout is 1 min*) fun reconstruct timeout light_output file thy = let
val timer = Timer.startRealTimer () in
Timeout.apply (Time.fromSeconds (if timeout = 0then60 else timeout))
(test_partial_reconstruction thy
#> light_output ? erase_inference_fmlas
#> @{make_string} (* FIXME *)
#> (fn s => report (Proof_Context.init_global thy) (@{make_string} file ^ " === " ^ s ^ " t=" ^ (Timer.checkRealTimer timer |> Time.toMilliseconds |> @{make_string})))) file end ›
ML ‹
(*this version of "reconstruct" builds theorems, instead of lists of reconstructed inferences*) (*default timeout is 1 min*) fun reconstruct timeout file thy = let
val timer = Timer.startRealTimer ()
val thy' =
TPTP_Reconstruct.import_thm true
[Path.dir file, Path.explode "$TPTP"] file leo2_on_load thy
ML ‹ funreconstruction_testtimeoutctxt= test_fnctxt (fnfile=>reconstructtimeoutfile(Proof_Context.theory_ofctxt)) "reconstructor" () \<close>
ML\<open> datatypeexamination_results=
Whole_proof of string(*filename*) * proof_contents
| Specific_rule of string(*filename*) * string(*inference rule*) * term option list
(*Look out for failures reconstructing a particular inference rule*) fun filter_failures inference_name (Whole_proof (filename, results)) = let
val filtered_results = case results of
Nonempty (SOME results') =>
#2 results'
|> maps (fn (stock as TPTP_Reconstruct.Annotated_step (_, inf_name), inf_fmla, _) => if inf_name = inference_name then [inf_fmla] else [])
| _ => [] in Specific_rule (filename, inference_name, filtered_results) end
(*Returns detailed info about a proof-reconstruction attempt. Ifrule_nameisspecifiedthentherelatedfailedinferences
are returned, otherwise all failed inferences are returned.*) fun examine_failed_inferences ctxt filename rule_name = let
val thy = Proof_Context.theory_of ctxt
val prob_file = Path.explode filename
val results = if test_all ctxt then No_info
else test_partial_reconstruction thy prob_file in
Whole_proof (filename, results)
|> is_some rule_name ? (fn x =>
filter_failures (the rule_name) x) end ›
funpre_classify_failures[]alist=alist |pre_classify_failures((stock,_,_)::xs)alist= let valinf=annotation_or_idstock valcount=AList.lookup(=)alistinf in ifis_nonecount thenpre_classify_failuresxs((inf,1)::alist) else pre_classify_failuresxs (AList.update(=)(inf,thecount+1)alist) end
ML\<open> valregressions=map(fns=>"$THF_PROOFS/"^s) ["SEV405^5.p.out",
(*"SYO377^5.p.out", Always seems to raise Interrupt on my laptop -- probably because node 475 has lots of premises*) "PUZ031^5.p.out", "ALG001^5.p.out", "SYO238^5.p.out", (*"SEV158^5.p.out", This is big*) "SYO285^5.p.out", "../SYO285^5.p.out_reduced", (* "SYO225^5.p.out", This is big*) "SYO291^5.p.out", "SET669^3.p.out", "SEV233^5.p.out", (*"SEU511^1.p.out", This is big*) "SEV161^5.p.out", "SEV012^5.p.out", "SYO035^1.p.out", "SYO291^5.p.out", "SET741^4.p.out", (*involves both definitions and contorted splitting. has nice graph.*) "SEU548^2.p.out", "SEU513^2.p.out", "SYO006^1.p.out", "SYO371^5.p.out"(*has contorted splitting, like SYO006^1.p.out, but doesn't involve definitions*)
] ›
ML ‹ valexperiment=examine_failed_inferences@{context} (List.lastregressions)NONE;
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 und die Messung sind noch experimentell.