src/HOL/TPTP/TPTP_Proof_Reconstruction.thy
changeset 63167 0909deb8059b
parent 62243 dd22d2423047
child 67399 eab6ce8368fa
equal deleted inserted replaced
63166:143f58bb34f9 63167:0909deb8059b
    50 begin
    50 begin
    51 
    51 
    52 
    52 
    53 section "Setup"
    53 section "Setup"
    54 
    54 
    55 ML {*
    55 ML \<open>
    56   val tptp_unexceptional_reconstruction = Attrib.setup_config_bool @{binding tptp_unexceptional_reconstruction} (K false)
    56   val tptp_unexceptional_reconstruction = Attrib.setup_config_bool @{binding tptp_unexceptional_reconstruction} (K false)
    57   fun unexceptional_reconstruction ctxt = Config.get ctxt tptp_unexceptional_reconstruction
    57   fun unexceptional_reconstruction ctxt = Config.get ctxt tptp_unexceptional_reconstruction
    58   val tptp_informative_failure = Attrib.setup_config_bool @{binding tptp_informative_failure} (K false)
    58   val tptp_informative_failure = Attrib.setup_config_bool @{binding tptp_informative_failure} (K false)
    59   fun informative_failure ctxt = Config.get ctxt tptp_informative_failure
    59   fun informative_failure ctxt = Config.get ctxt tptp_informative_failure
    60   val tptp_trace_reconstruction = Attrib.setup_config_bool @{binding tptp_trace_reconstruction} (K false)
    60   val tptp_trace_reconstruction = Attrib.setup_config_bool @{binding tptp_trace_reconstruction} (K false)
    65       val max = Config.get ctxt tptp_max_term_size
    65       val max = Config.get ctxt tptp_max_term_size
    66     in
    66     in
    67       if max = 0 then false
    67       if max = 0 then false
    68       else size > max
    68       else size > max
    69     end
    69     end
    70 *}
    70 \<close>
    71 
    71 
    72 (*FIXME move to TPTP_Proof_Reconstruction_Test_Units*)
    72 (*FIXME move to TPTP_Proof_Reconstruction_Test_Units*)
    73 declare [[
    73 declare [[
    74   tptp_unexceptional_reconstruction = false, (*NOTE should be "false" while testing*)
    74   tptp_unexceptional_reconstruction = false, (*NOTE should be "false" while testing*)
    75   tptp_informative_failure = true
    75   tptp_informative_failure = true
    85   unify_search_bound = 5
    85   unify_search_bound = 5
    86 ]]
    86 ]]
    87 
    87 
    88 
    88 
    89 section "Proof reconstruction"
    89 section "Proof reconstruction"
    90 text {*There are two parts to proof reconstruction:
    90 text \<open>There are two parts to proof reconstruction:
    91 \begin{itemize}
    91 \begin{itemize}
    92   \item interpreting the inferences
    92   \item interpreting the inferences
    93   \item building the skeleton, which indicates how to compose
    93   \item building the skeleton, which indicates how to compose
    94     individual inferences into subproofs, and then compose the
    94     individual inferences into subproofs, and then compose the
    95     subproofs to give the proof).
    95     subproofs to give the proof).
   142 
   142 
   143 It is hoped that this setup can target other provers by modifying the
   143 It is hoped that this setup can target other provers by modifying the
   144 clause representation to fit them, and adapting the inference
   144 clause representation to fit them, and adapting the inference
   145 interpretation to handle the rules used by the prover. It should also
   145 interpretation to handle the rules used by the prover. It should also
   146 facilitate composing together proofs found by different provers.
   146 facilitate composing together proofs found by different provers.
   147 *}
   147 \<close>
   148 
   148 
   149 
   149 
   150 subsection "Instantiation"
   150 subsection "Instantiation"
   151 
   151 
   152 lemma polar_allE [rule_format]:
   152 lemma polar_allE [rule_format]:
   157 lemma polar_exE [rule_format]:
   157 lemma polar_exE [rule_format]:
   158   "\<lbrakk>(\<exists>x. P x) = True; \<And>x. (P x) = True \<Longrightarrow> R\<rbrakk> \<Longrightarrow> R"
   158   "\<lbrakk>(\<exists>x. P x) = True; \<And>x. (P x) = True \<Longrightarrow> R\<rbrakk> \<Longrightarrow> R"
   159   "\<lbrakk>(\<forall>x. P x) = False; \<And>x. (P x) = False \<Longrightarrow> R\<rbrakk> \<Longrightarrow> R"
   159   "\<lbrakk>(\<forall>x. P x) = False; \<And>x. (P x) = False \<Longrightarrow> R\<rbrakk> \<Longrightarrow> R"
   160 by auto
   160 by auto
   161 
   161 
   162 ML {*
   162 ML \<open>
   163 (*This carries out an allE-like rule but on (polarised) literals.
   163 (*This carries out an allE-like rule but on (polarised) literals.
   164  Instead of yielding a free variable (which is a hell for the
   164  Instead of yielding a free variable (which is a hell for the
   165  matcher) it seeks to use one of the subgoals' parameters.
   165  matcher) it seeks to use one of the subgoals' parameters.
   166  This ought to be sufficient for emulating extcnf_combined,
   166  This ought to be sufficient for emulating extcnf_combined,
   167  but note that the complexity of the problem can be enormous.*)
   167  but note that the complexity of the problem can be enormous.*)
   193       end
   193       end
   194   end
   194   end
   195 
   195 
   196 (*Attempts to use the polar_allE theorems on a specific subgoal.*)
   196 (*Attempts to use the polar_allE theorems on a specific subgoal.*)
   197 fun forall_pos_tac ctxt = inst_parametermatch_tac ctxt @{thms polar_allE}
   197 fun forall_pos_tac ctxt = inst_parametermatch_tac ctxt @{thms polar_allE}
   198 *}
   198 \<close>
   199 
   199 
   200 ML {*
   200 ML \<open>
   201 (*This is similar to inst_parametermatch_tac, but prefers to
   201 (*This is similar to inst_parametermatch_tac, but prefers to
   202   match variables having identical names. Logically, this is
   202   match variables having identical names. Logically, this is
   203   a hack. But it reduces the complexity of the problem.*)
   203   a hack. But it reduces the complexity of the problem.*)
   204 fun nominal_inst_parametermatch_tac ctxt thm i = fn st =>
   204 fun nominal_inst_parametermatch_tac ctxt thm i = fn st =>
   205   let
   205   let
   231             instantiates (the quantified_var |> fst) i st
   231             instantiates (the quantified_var |> fst) i st
   232           else
   232           else
   233             K no_tac i st
   233             K no_tac i st
   234       end
   234       end
   235   end
   235   end
   236 *}
   236 \<close>
   237 
   237 
   238 
   238 
   239 subsection "Prefix massaging"
   239 subsection "Prefix massaging"
   240 
   240 
   241 ML {*
   241 ML \<open>
   242 exception NO_GOALS
   242 exception NO_GOALS
   243 
   243 
   244 (*Get quantifier prefix of the hypothesis and conclusion, reorder
   244 (*Get quantifier prefix of the hypothesis and conclusion, reorder
   245   the hypothesis' quantifiers to have the ones appearing in the
   245   the hypothesis' quantifiers to have the ones appearing in the
   246   conclusion first.*)
   246   conclusion first.*)
   289               THEN HEADGOAL (assume_tac ctxt))
   289               THEN HEADGOAL (assume_tac ctxt))
   290       in
   290       in
   291         dresolve_tac ctxt [thm] i st
   291         dresolve_tac ctxt [thm] i st
   292       end
   292       end
   293     end
   293     end
   294 *}
   294 \<close>
   295 
   295 
   296 
   296 
   297 subsection "Some general rules and congruences"
   297 subsection "Some general rules and congruences"
   298 
   298 
   299 (*this isn't an actual rule used in Leo2, but it seems to be
   299 (*this isn't an actual rule used in Leo2, but it seems to be
   300   applied implicitly during some Leo2 inferences.*)
   300   applied implicitly during some Leo2 inferences.*)
   301 lemma polarise: "P ==> P = True" by auto
   301 lemma polarise: "P ==> P = True" by auto
   302 
   302 
   303 ML {*
   303 ML \<open>
   304 fun is_polarised t =
   304 fun is_polarised t =
   305   (TPTP_Reconstruct.remove_polarity true t; true)
   305   (TPTP_Reconstruct.remove_polarity true t; true)
   306   handle TPTP_Reconstruct.UNPOLARISED _ => false
   306   handle TPTP_Reconstruct.UNPOLARISED _ => false
   307 
   307 
   308 fun polarise_subgoal_hyps ctxt =
   308 fun polarise_subgoal_hyps ctxt =
   309   COND' (SOME #> TERMPRED is_polarised (fn _ => true)) (K no_tac) (dresolve_tac ctxt @{thms polarise})
   309   COND' (SOME #> TERMPRED is_polarised (fn _ => true)) (K no_tac) (dresolve_tac ctxt @{thms polarise})
   310 *}
   310 \<close>
   311 
   311 
   312 lemma simp_meta [rule_format]:
   312 lemma simp_meta [rule_format]:
   313   "(A --> B) == (~A | B)"
   313   "(A --> B) == (~A | B)"
   314   "(A | B) | C == A | B | C"
   314   "(A | B) | C == A | B | C"
   315   "(A & B) & C == A & B & C"
   315   "(A & B) & C == A & B & C"
   333   "P = False \<Longrightarrow> (\<not> P) = True"
   333   "P = False \<Longrightarrow> (\<not> P) = True"
   334   "P = True \<Longrightarrow> (\<not> P) = False"
   334   "P = True \<Longrightarrow> (\<not> P) = False"
   335 by auto
   335 by auto
   336 
   336 
   337 lemma solved_all_splits: "False = True \<Longrightarrow> False" by simp
   337 lemma solved_all_splits: "False = True \<Longrightarrow> False" by simp
   338 ML {*
   338 ML \<open>
   339 fun solved_all_splits_tac ctxt =
   339 fun solved_all_splits_tac ctxt =
   340   TRY (eresolve_tac ctxt @{thms conjE} 1)
   340   TRY (eresolve_tac ctxt @{thms conjE} 1)
   341   THEN resolve_tac ctxt @{thms solved_all_splits} 1
   341   THEN resolve_tac ctxt @{thms solved_all_splits} 1
   342   THEN assume_tac ctxt 1
   342   THEN assume_tac ctxt 1
   343 *}
   343 \<close>
   344 
   344 
   345 lemma lots_of_logic_expansions_meta [rule_format]:
   345 lemma lots_of_logic_expansions_meta [rule_format]:
   346   "(((A :: bool) = B) = True) == (((A \<longrightarrow> B) = True) & ((B \<longrightarrow> A) = True))"
   346   "(((A :: bool) = B) = True) == (((A \<longrightarrow> B) = True) & ((B \<longrightarrow> A) = True))"
   347   "((A :: bool) = B) = False == (((~A) | B) = False) | (((~B) | A) = False)"
   347   "((A :: bool) = B) = False == (((~A) | B) = False) | (((~B) | A) = False)"
   348 
   348 
   406 lemma extuni_func [rule_format]: "(F = G) = False \<Longrightarrow> (! X. (F X = G X)) = False" by auto
   406 lemma extuni_func [rule_format]: "(F = G) = False \<Longrightarrow> (! X. (F X = G X)) = False" by auto
   407 
   407 
   408 
   408 
   409 subsection "Emulation: tactics"
   409 subsection "Emulation: tactics"
   410 
   410 
   411 ML {*
   411 ML \<open>
   412 (*Instantiate a variable according to the info given in the
   412 (*Instantiate a variable according to the info given in the
   413   proof annotation. Through this we avoid having to come up
   413   proof annotation. Through this we avoid having to come up
   414   with instantiations during reconstruction.*)
   414   with instantiations during reconstruction.*)
   415 fun bind_tac ctxt prob_name ordered_binds =
   415 fun bind_tac ctxt prob_name ordered_binds =
   416   let
   416   let
   439     THEN (REPEAT_DETERM (HEADGOAL (resolve_tac ctxt @{thms allI})))
   439     THEN (REPEAT_DETERM (HEADGOAL (resolve_tac ctxt @{thms allI})))
   440     THEN REPEAT_DETERM (HEADGOAL (nominal_inst_parametermatch_tac ctxt @{thm allE}))
   440     THEN REPEAT_DETERM (HEADGOAL (nominal_inst_parametermatch_tac ctxt @{thm allE}))
   441     (*now only the variable to instantiate should be left*)
   441     (*now only the variable to instantiate should be left*)
   442     THEN FIRST (map instantiate_tac ordered_instances)
   442     THEN FIRST (map instantiate_tac ordered_instances)
   443   end
   443   end
   444 *}
   444 \<close>
   445 
   445 
   446 ML {*
   446 ML \<open>
   447 (*Simplification tactics*)
   447 (*Simplification tactics*)
   448 local
   448 local
   449   fun rew_goal_tac thms ctxt i =
   449   fun rew_goal_tac thms ctxt i =
   450     rewrite_goal_tac ctxt thms i
   450     rewrite_goal_tac ctxt thms i
   451     |> CHANGED
   451     |> CHANGED
   454     rew_goal_tac (@{thms simp_meta} @ @{thms lots_of_logic_expansions_meta})
   454     rew_goal_tac (@{thms simp_meta} @ @{thms lots_of_logic_expansions_meta})
   455 
   455 
   456   val simper_animal =
   456   val simper_animal =
   457     rew_goal_tac @{thms simp_meta}
   457     rew_goal_tac @{thms simp_meta}
   458 end
   458 end
   459 *}
   459 \<close>
   460 
   460 
   461 lemma prop_normalise [rule_format]:
   461 lemma prop_normalise [rule_format]:
   462   "(A | B) | C == A | B | C"
   462   "(A | B) | C == A | B | C"
   463   "(A & B) & C == A & B & C"
   463   "(A & B) & C == A & B & C"
   464   "A | B == ~(~A & ~B)"
   464   "A | B == ~(~A & ~B)"
   465   "~~ A == A"
   465   "~~ A == A"
   466 by auto
   466 by auto
   467 ML {*
   467 ML \<open>
   468 (*i.e., break_conclusion*)
   468 (*i.e., break_conclusion*)
   469 fun flip_conclusion_tac ctxt =
   469 fun flip_conclusion_tac ctxt =
   470   let
   470   let
   471     val default_tac =
   471     val default_tac =
   472       (TRY o CHANGED o (rewrite_goal_tac ctxt @{thms prop_normalise}))
   472       (TRY o CHANGED o (rewrite_goal_tac ctxt @{thms prop_normalise}))
   474       THEN' (REPEAT_DETERM o eresolve_tac ctxt @{thms conjE})
   474       THEN' (REPEAT_DETERM o eresolve_tac ctxt @{thms conjE})
   475       THEN' (TRY o (expander_animal ctxt))
   475       THEN' (TRY o (expander_animal ctxt))
   476   in
   476   in
   477     default_tac ORELSE' resolve_tac ctxt @{thms flip}
   477     default_tac ORELSE' resolve_tac ctxt @{thms flip}
   478   end
   478   end
   479 *}
   479 \<close>
   480 
   480 
   481 
   481 
   482 subsection "Skolemisation"
   482 subsection "Skolemisation"
   483 
   483 
   484 lemma skolemise [rule_format]:
   484 lemma skolemise [rule_format]:
   539   "\<lbrakk>(Ex P) = True; sk = (SOME x. P x)\<rbrakk> \<Longrightarrow> P sk = True"
   539   "\<lbrakk>(Ex P) = True; sk = (SOME x. P x)\<rbrakk> \<Longrightarrow> P sk = True"
   540 apply (drule polar_skolemise, simp)
   540 apply (drule polar_skolemise, simp)
   541 apply (simp, drule someI_ex, simp)
   541 apply (simp, drule someI_ex, simp)
   542 done
   542 done
   543 
   543 
   544 ML {*
   544 ML \<open>
   545 (*FIXME LHS should be constant. Currently allow variables for testing. Probably should still allow Vars (but not Frees) since they'll act as intermediate values*)
   545 (*FIXME LHS should be constant. Currently allow variables for testing. Probably should still allow Vars (but not Frees) since they'll act as intermediate values*)
   546 fun conc_is_skolem_def t =
   546 fun conc_is_skolem_def t =
   547   case t of
   547   case t of
   548       Const (@{const_name HOL.eq}, _) $ t' $ (Const (@{const_name Hilbert_Choice.Eps}, _) $ _) =>
   548       Const (@{const_name HOL.eq}, _) $ t' $ (Const (@{const_name Hilbert_Choice.Eps}, _) $ _) =>
   549       let
   549       let
   572            b andalso is_Free t) args true
   572            b andalso is_Free t) args true
   573       in
   573       in
   574         h_property andalso args_property
   574         h_property andalso args_property
   575       end
   575       end
   576     | _ => false
   576     | _ => false
   577 *}
   577 \<close>
   578 
   578 
   579 ML {*
   579 ML \<open>
   580 (*Hack used to detect if a Skolem definition, with an LHS Var, has had the LHS instantiated into an unacceptable term.*)
   580 (*Hack used to detect if a Skolem definition, with an LHS Var, has had the LHS instantiated into an unacceptable term.*)
   581 fun conc_is_bad_skolem_def t =
   581 fun conc_is_bad_skolem_def t =
   582   case t of
   582   case t of
   583       Const (@{const_name HOL.eq}, _) $ t' $ (Const (@{const_name Hilbert_Choice.Eps}, _) $ _) =>
   583       Const (@{const_name HOL.eq}, _) $ t' $ (Const (@{const_name Hilbert_Choice.Eps}, _) $ _) =>
   584       let
   584       let
   608            b andalso is_Free t) args true
   608            b andalso is_Free t) args true
   609       in
   609       in
   610         h_property andalso args_property
   610         h_property andalso args_property
   611       end
   611       end
   612     | _ => false
   612     | _ => false
   613 *}
   613 \<close>
   614 
   614 
   615 ML {*
   615 ML \<open>
   616 fun get_skolem_conc t =
   616 fun get_skolem_conc t =
   617   let
   617   let
   618     val t' =
   618     val t' =
   619       strip_top_all_vars [] t
   619       strip_top_all_vars [] t
   620       |> snd
   620       |> snd
   631      head_of t'
   631      head_of t'
   632      |> strip_abs_body
   632      |> strip_abs_body
   633      |> head_of
   633      |> head_of
   634      |> dest_Const)
   634      |> dest_Const)
   635    (get_skolem_conc t)
   635    (get_skolem_conc t)
   636 *}
   636 \<close>
   637 
   637 
   638 (*
   638 (*
   639 Technique for handling quantifiers:
   639 Technique for handling quantifiers:
   640   Principles:
   640   Principles:
   641   * allE should always match with a !!
   641   * allE should always match with a !!
   642   * exE should match with a constant,
   642   * exE should match with a constant,
   643      or bind a fresh !! -- currently not doing the latter since it never seems to arised in normal Leo2 proofs.
   643      or bind a fresh !! -- currently not doing the latter since it never seems to arised in normal Leo2 proofs.
   644 *)
   644 *)
   645 
   645 
   646 ML {*
   646 ML \<open>
   647 fun forall_neg_tac candidate_consts ctxt i = fn st =>
   647 fun forall_neg_tac candidate_consts ctxt i = fn st =>
   648   let
   648   let
   649     val gls =
   649     val gls =
   650       Thm.prop_of st
   650       Thm.prop_of st
   651       |> Logic.strip_horn
   651       |> Logic.strip_horn
   676         val attempts = map instantiate candidate_consts
   676         val attempts = map instantiate candidate_consts
   677       in
   677       in
   678         (fold (curry (op APPEND')) attempts (K no_tac)) i st
   678         (fold (curry (op APPEND')) attempts (K no_tac)) i st
   679       end
   679       end
   680   end
   680   end
   681 *}
   681 \<close>
   682 
   682 
   683 ML {*
   683 ML \<open>
   684 exception SKOLEM_DEF of term (*The tactic wasn't pointed at a skolem definition*)
   684 exception SKOLEM_DEF of term (*The tactic wasn't pointed at a skolem definition*)
   685 exception NO_SKOLEM_DEF of (*skolem const name*)string * Binding.binding * term (*The tactic could not find a skolem definition in the theory*)
   685 exception NO_SKOLEM_DEF of (*skolem const name*)string * Binding.binding * term (*The tactic could not find a skolem definition in the theory*)
   686 fun absorb_skolem_def ctxt prob_name_opt i = fn st =>
   686 fun absorb_skolem_def ctxt prob_name_opt i = fn st =>
   687   let
   687   let
   688     val thy = Proof_Context.theory_of ctxt
   688     val thy = Proof_Context.theory_of ctxt
   748             raise (NO_SKOLEM_DEF (def_name, bnd_name, conclusion)))
   748             raise (NO_SKOLEM_DEF (def_name, bnd_name, conclusion)))
   749   in
   749   in
   750     resolve_tac ctxt [Drule.export_without_context thm] i st
   750     resolve_tac ctxt [Drule.export_without_context thm] i st
   751   end
   751   end
   752   handle SKOLEM_DEF _ => no_tac st
   752   handle SKOLEM_DEF _ => no_tac st
   753 *}
   753 \<close>
   754 
   754 
   755 ML {*
   755 ML \<open>
   756 (*
   756 (*
   757 In current system, there should only be 2 subgoals: the one where
   757 In current system, there should only be 2 subgoals: the one where
   758 the skolem definition is being built (with a Var in the LHS), and the other subgoal using Var.
   758 the skolem definition is being built (with a Var in the LHS), and the other subgoal using Var.
   759 *)
   759 *)
   760 (*arity must be greater than 0. if arity=0 then
   760 (*arity must be greater than 0. if arity=0 then
   799   in
   799   in
   800     map (strip_top_All_vars #> snd) conclusions
   800     map (strip_top_All_vars #> snd) conclusions
   801     |> maps (get_skolem_terms [] [])
   801     |> maps (get_skolem_terms [] [])
   802     |> distinct (op =)
   802     |> distinct (op =)
   803   end
   803   end
   804 *}
   804 \<close>
   805 
   805 
   806 ML {*
   806 ML \<open>
   807 fun instantiate_skols ctxt consts_candidates i = fn st =>
   807 fun instantiate_skols ctxt consts_candidates i = fn st =>
   808   let
   808   let
   809     val gls =
   809     val gls =
   810       Thm.prop_of st
   810       Thm.prop_of st
   811       |> Logic.strip_horn
   811       |> Logic.strip_horn
   951         fold (curry (op APPEND))
   951         fold (curry (op APPEND))
   952           (map (instantiate_tac (dest_Var (Thm.term_of (the var_opt)))) skolem_cts) no_tac
   952           (map (instantiate_tac (dest_Var (Thm.term_of (the var_opt)))) skolem_cts) no_tac
   953   in
   953   in
   954     tactic st
   954     tactic st
   955   end
   955   end
   956 *}
   956 \<close>
   957 
   957 
   958 ML {*
   958 ML \<open>
   959 fun new_skolem_tac ctxt consts_candidates =
   959 fun new_skolem_tac ctxt consts_candidates =
   960   let
   960   let
   961     fun tac thm =
   961     fun tac thm =
   962       dresolve_tac ctxt [thm]
   962       dresolve_tac ctxt [thm]
   963       THEN' instantiate_skols ctxt consts_candidates
   963       THEN' instantiate_skols ctxt consts_candidates
   964   in
   964   in
   965     if null consts_candidates then K no_tac
   965     if null consts_candidates then K no_tac
   966     else FIRST' (map tac @{thms lift_exists})
   966     else FIRST' (map tac @{thms lift_exists})
   967   end
   967   end
   968 *}
   968 \<close>
   969 
   969 
   970 (*
   970 (*
   971 need a tactic to expand "? x . P" to "~ ! x. ~ P"
   971 need a tactic to expand "? x . P" to "~ ! x. ~ P"
   972 *)
   972 *)
   973 ML {*
   973 ML \<open>
   974 fun ex_expander_tac ctxt i =
   974 fun ex_expander_tac ctxt i =
   975    let
   975    let
   976      val simpset =
   976      val simpset =
   977        empty_simpset ctxt (*NOTE for some reason, Bind exception gets raised if ctxt's simpset isn't emptied*)
   977        empty_simpset ctxt (*NOTE for some reason, Bind exception gets raised if ctxt's simpset isn't emptied*)
   978        |> Simplifier.add_simp @{lemma "Ex P == (~ (! x. ~ P x))" by auto}
   978        |> Simplifier.add_simp @{lemma "Ex P == (~ (! x. ~ P x))" by auto}
   979    in
   979    in
   980      CHANGED (asm_full_simp_tac simpset i)
   980      CHANGED (asm_full_simp_tac simpset i)
   981    end
   981    end
   982 *}
   982 \<close>
   983 
   983 
   984 
   984 
   985 subsubsection "extuni_dec"
   985 subsubsection "extuni_dec"
   986 
   986 
   987 ML {*
   987 ML \<open>
   988 (*n-ary decomposition. Code is based on the n-ary arg_cong generator*)
   988 (*n-ary decomposition. Code is based on the n-ary arg_cong generator*)
   989 fun extuni_dec_n ctxt arity =
   989 fun extuni_dec_n ctxt arity =
   990   let
   990   let
   991     val _ = @{assert} (arity > 0)
   991     val _ = @{assert} (arity > 0)
   992     val is =
   992     val is =
  1033       Logic.mk_implies (hyp, HOLogic.mk_Trueprop conc)
  1033       Logic.mk_implies (hyp, HOLogic.mk_Trueprop conc)
  1034   in
  1034   in
  1035     Goal.prove ctxt [] [] t (fn _ => auto_tac ctxt)
  1035     Goal.prove ctxt [] [] t (fn _ => auto_tac ctxt)
  1036     |> Drule.export_without_context
  1036     |> Drule.export_without_context
  1037   end
  1037   end
  1038 *}
  1038 \<close>
  1039 
  1039 
  1040 ML {*
  1040 ML \<open>
  1041 (*Determine the arity of a function which the "dec"
  1041 (*Determine the arity of a function which the "dec"
  1042   unification rule is about to be applied.
  1042   unification rule is about to be applied.
  1043   NOTE:
  1043   NOTE:
  1044     * Assumes that there is a single hypothesis
  1044     * Assumes that there is a single hypothesis
  1045 *)
  1045 *)
  1155                    dresolve_tac ctxt @{thms dec_commut_disj},
  1155                    dresolve_tac ctxt @{thms dec_commut_disj},
  1156                    elim_tac]))
  1156                    elim_tac]))
  1157   in
  1157   in
  1158     (CHANGED o search_tac) i st
  1158     (CHANGED o search_tac) i st
  1159   end
  1159   end
  1160 *}
  1160 \<close>
  1161 
  1161 
  1162 
  1162 
  1163 subsubsection "standard_cnf"
  1163 subsubsection "standard_cnf"
  1164 (*Given a standard_cnf inference, normalise it
  1164 (*Given a standard_cnf inference, normalise it
  1165      e.g. ((A & B) & C \<longrightarrow> D & E \<longrightarrow> F \<longrightarrow> G) = False
  1165      e.g. ((A & B) & C \<longrightarrow> D & E \<longrightarrow> F \<longrightarrow> G) = False
  1176   e.g.,  "(A \<longrightarrow> B) = True \<Longrightarrow> A = False | (A = True & B = True)"
  1176   e.g.,  "(A \<longrightarrow> B) = True \<Longrightarrow> A = False | (A = True & B = True)"
  1177 since "standard_cnf" seems to be applied at the preprocessing
  1177 since "standard_cnf" seems to be applied at the preprocessing
  1178 stage, together with splitting.
  1178 stage, together with splitting.
  1179 *)
  1179 *)
  1180 
  1180 
  1181 ML {*
  1181 ML \<open>
  1182 (*Conjunctive counterparts to Term.disjuncts_aux and Term.disjuncts*)
  1182 (*Conjunctive counterparts to Term.disjuncts_aux and Term.disjuncts*)
  1183 fun conjuncts_aux (Const (@{const_name HOL.conj}, _) $ t $ t') conjs =
  1183 fun conjuncts_aux (Const (@{const_name HOL.conj}, _) $ t $ t') conjs =
  1184      conjuncts_aux t (conjuncts_aux t' conjs)
  1184      conjuncts_aux t (conjuncts_aux t' conjs)
  1185   | conjuncts_aux t conjs = t :: conjs
  1185   | conjuncts_aux t conjs = t :: conjs
  1186 
  1186 
  1194 in
  1194 in
  1195   fun imp_strip_horn t =
  1195   fun imp_strip_horn t =
  1196     imp_strip_horn' [] t
  1196     imp_strip_horn' [] t
  1197     |> apfst rev
  1197     |> apfst rev
  1198 end
  1198 end
  1199 *}
  1199 \<close>
  1200 
  1200 
  1201 ML {*
  1201 ML \<open>
  1202 (*Returns whether the antecedents are separated by conjunctions
  1202 (*Returns whether the antecedents are separated by conjunctions
  1203   or implications; the number of antecedents; and the polarity
  1203   or implications; the number of antecedents; and the polarity
  1204   of the original clause -- I think this will always be "false".*)
  1204   of the original clause -- I think this will always be "false".*)
  1205 fun standard_cnf_type ctxt i : thm -> (TPTP_Reconstruct.formula_kind * int * bool) option = fn st =>
  1205 fun standard_cnf_type ctxt i : thm -> (TPTP_Reconstruct.formula_kind * int * bool) option = fn st =>
  1206   let
  1206   let
  1252          antes)
  1252          antes)
  1253   in
  1253   in
  1254     if null antes then NONE
  1254     if null antes then NONE
  1255     else SOME (ante_type, length antes', pol)
  1255     else SOME (ante_type, length antes', pol)
  1256   end
  1256   end
  1257 *}
  1257 \<close>
  1258 
  1258 
  1259 ML {*
  1259 ML \<open>
  1260 (*Given a certain standard_cnf type, build a metatheorem that would
  1260 (*Given a certain standard_cnf type, build a metatheorem that would
  1261   validate it*)
  1261   validate it*)
  1262 fun mk_standard_cnf ctxt kind arity =
  1262 fun mk_standard_cnf ctxt kind arity =
  1263   let
  1263   let
  1264     val _ = @{assert} (arity > 0)
  1264     val _ = @{assert} (arity > 0)
  1292       Logic.mk_implies (HOLogic.mk_Trueprop  hyp, HOLogic.mk_Trueprop conc)
  1292       Logic.mk_implies (HOLogic.mk_Trueprop  hyp, HOLogic.mk_Trueprop conc)
  1293   in
  1293   in
  1294     Goal.prove ctxt [] [] t (fn _ => HEADGOAL (blast_tac ctxt))
  1294     Goal.prove ctxt [] [] t (fn _ => HEADGOAL (blast_tac ctxt))
  1295     |> Drule.export_without_context
  1295     |> Drule.export_without_context
  1296   end
  1296   end
  1297 *}
  1297 \<close>
  1298 
  1298 
  1299 ML {*
  1299 ML \<open>
  1300 (*Applies a d-tactic, then breaks it up conjunctively.
  1300 (*Applies a d-tactic, then breaks it up conjunctively.
  1301   This can be used to transform subgoals as follows:
  1301   This can be used to transform subgoals as follows:
  1302      (A \<longrightarrow> B) = False  \<Longrightarrow> R
  1302      (A \<longrightarrow> B) = False  \<Longrightarrow> R
  1303               |
  1303               |
  1304               v
  1304               v
  1305   \<lbrakk>A = True; B = False\<rbrakk> \<Longrightarrow> R
  1305   \<lbrakk>A = True; B = False\<rbrakk> \<Longrightarrow> R
  1306 *)
  1306 *)
  1307 fun weak_conj_tac ctxt drule =
  1307 fun weak_conj_tac ctxt drule =
  1308   dresolve_tac ctxt [drule] THEN'
  1308   dresolve_tac ctxt [drule] THEN'
  1309   (REPEAT_DETERM o eresolve_tac ctxt @{thms conjE})
  1309   (REPEAT_DETERM o eresolve_tac ctxt @{thms conjE})
  1310 *}
  1310 \<close>
  1311 
  1311 
  1312 ML {*
  1312 ML \<open>
  1313 fun uncurry_lit_neg_tac ctxt =
  1313 fun uncurry_lit_neg_tac ctxt =
  1314   REPEAT_DETERM o
  1314   REPEAT_DETERM o
  1315     dresolve_tac ctxt [@{lemma "(A \<longrightarrow> B \<longrightarrow> C) = False \<Longrightarrow> (A & B \<longrightarrow> C) = False" by auto}]
  1315     dresolve_tac ctxt [@{lemma "(A \<longrightarrow> B \<longrightarrow> C) = False \<Longrightarrow> (A & B \<longrightarrow> C) = False" by auto}]
  1316 *}
  1316 \<close>
  1317 
  1317 
  1318 ML {*
  1318 ML \<open>
  1319 fun standard_cnf_tac ctxt i = fn st =>
  1319 fun standard_cnf_tac ctxt i = fn st =>
  1320   let
  1320   let
  1321     fun core_tactic i = fn st =>
  1321     fun core_tactic i = fn st =>
  1322       case standard_cnf_type ctxt i st of
  1322       case standard_cnf_type ctxt i st of
  1323           NONE => no_tac st
  1323           NONE => no_tac st
  1330   in
  1330   in
  1331     (uncurry_lit_neg_tac ctxt
  1331     (uncurry_lit_neg_tac ctxt
  1332      THEN' TPTP_Reconstruct_Library.reassociate_conjs_tac ctxt
  1332      THEN' TPTP_Reconstruct_Library.reassociate_conjs_tac ctxt
  1333      THEN' core_tactic) i st
  1333      THEN' core_tactic) i st
  1334   end
  1334   end
  1335 *}
  1335 \<close>
  1336 
  1336 
  1337 
  1337 
  1338 subsubsection "Emulator prep"
  1338 subsubsection "Emulator prep"
  1339 
  1339 
  1340 ML {*
  1340 ML \<open>
  1341 datatype cleanup_feature =
  1341 datatype cleanup_feature =
  1342     RemoveHypothesesFromSkolemDefs
  1342     RemoveHypothesesFromSkolemDefs
  1343   | RemoveDuplicates
  1343   | RemoveDuplicates
  1344 
  1344 
  1345 datatype loop_feature =
  1345 datatype loop_feature =
  1378   | Loop of loop_feature list
  1378   | Loop of loop_feature list
  1379   | LoopOnce of loop_feature list
  1379   | LoopOnce of loop_feature list
  1380   | InnerLoopOnce of loop_feature list
  1380   | InnerLoopOnce of loop_feature list
  1381   | CleanUp of cleanup_feature list
  1381   | CleanUp of cleanup_feature list
  1382   | AbsorbSkolemDefs
  1382   | AbsorbSkolemDefs
  1383 *}
  1383 \<close>
  1384 
  1384 
  1385 ML {*
  1385 ML \<open>
  1386 fun can_feature x l =
  1386 fun can_feature x l =
  1387   let
  1387   let
  1388     fun sublist_of_clean_up el =
  1388     fun sublist_of_clean_up el =
  1389       case el of
  1389       case el of
  1390           CleanUp l'' => SOME l''
  1390           CleanUp l'' => SOME l''
  1440 @{assert}
  1440 @{assert}
  1441   (can_feature (Loop []) [Loop [Existential_Var]]);
  1441   (can_feature (Loop []) [Loop [Existential_Var]]);
  1442 
  1442 
  1443 @{assert}
  1443 @{assert}
  1444   (not (can_feature (Loop []) [InnerLoopOnce [Existential_Var]]));
  1444   (not (can_feature (Loop []) [InnerLoopOnce [Existential_Var]]));
  1445 *}
  1445 \<close>
  1446 
  1446 
  1447 ML {*
  1447 ML \<open>
  1448 exception NO_LOOP_FEATS
  1448 exception NO_LOOP_FEATS
  1449 fun get_loop_feats (feats : feature list) =
  1449 fun get_loop_feats (feats : feature list) =
  1450   let
  1450   let
  1451     val loop_find =
  1451     val loop_find =
  1452       fold (fn x => fn loop_feats_acc =>
  1452       fold (fn x => fn loop_feats_acc =>
  1465   end;
  1465   end;
  1466 
  1466 
  1467 @{assert}
  1467 @{assert}
  1468   (get_loop_feats [Loop [King_Cong, Break_Hypotheses, Existential_Free, Existential_Var, Universal]] =
  1468   (get_loop_feats [Loop [King_Cong, Break_Hypotheses, Existential_Free, Existential_Var, Universal]] =
  1469    [King_Cong, Break_Hypotheses, Existential_Free, Existential_Var, Universal])
  1469    [King_Cong, Break_Hypotheses, Existential_Free, Existential_Var, Universal])
  1470 *}
  1470 \<close>
  1471 
  1471 
  1472 (*use as elim rule to remove premises*)
  1472 (*use as elim rule to remove premises*)
  1473 lemma insa_prems: "\<lbrakk>Q; P\<rbrakk> \<Longrightarrow> P" by auto
  1473 lemma insa_prems: "\<lbrakk>Q; P\<rbrakk> \<Longrightarrow> P" by auto
  1474 ML {*
  1474 ML \<open>
  1475 fun cleanup_skolem_defs ctxt feats =
  1475 fun cleanup_skolem_defs ctxt feats =
  1476   let
  1476   let
  1477     (*remove hypotheses from skolem defs,
  1477     (*remove hypotheses from skolem defs,
  1478      after testing that they look like skolem defs*)
  1478      after testing that they look like skolem defs*)
  1479     val dehypothesise_skolem_defs =
  1479     val dehypothesise_skolem_defs =
  1483   in
  1483   in
  1484     if can_feature (CleanUp [RemoveHypothesesFromSkolemDefs]) feats then
  1484     if can_feature (CleanUp [RemoveHypothesesFromSkolemDefs]) feats then
  1485       ALLGOALS (TRY o dehypothesise_skolem_defs)
  1485       ALLGOALS (TRY o dehypothesise_skolem_defs)
  1486     else all_tac
  1486     else all_tac
  1487   end
  1487   end
  1488 *}
  1488 \<close>
  1489 
  1489 
  1490 ML {*
  1490 ML \<open>
  1491 fun remove_duplicates_tac feats =
  1491 fun remove_duplicates_tac feats =
  1492   (if can_feature (CleanUp [RemoveDuplicates]) feats then
  1492   (if can_feature (CleanUp [RemoveDuplicates]) feats then
  1493      ALLGOALS distinct_subgoal_tac
  1493      ALLGOALS distinct_subgoal_tac
  1494    else all_tac)
  1494    else all_tac)
  1495 *}
  1495 \<close>
  1496 
  1496 
  1497 ML {*
  1497 ML \<open>
  1498 (*given a goal state, indicates the skolem constants committed-to in it (i.e. appearing in LHS of a skolem definition)*)
  1498 (*given a goal state, indicates the skolem constants committed-to in it (i.e. appearing in LHS of a skolem definition)*)
  1499 fun which_skolem_concs_used ctxt = fn st =>
  1499 fun which_skolem_concs_used ctxt = fn st =>
  1500   let
  1500   let
  1501     val feats = [CleanUp [RemoveHypothesesFromSkolemDefs, RemoveDuplicates]]
  1501     val feats = [CleanUp [RemoveHypothesesFromSkolemDefs, RemoveDuplicates]]
  1502     val scrubup_tac =
  1502     val scrubup_tac =
  1510     |> TERMFUN (snd (*discard hypotheses*)
  1510     |> TERMFUN (snd (*discard hypotheses*)
  1511                  #> get_skolem_conc_const) NONE
  1511                  #> get_skolem_conc_const) NONE
  1512     |> switch (fold (fn x => fn l => if is_some x then the x :: l else l)) []
  1512     |> switch (fold (fn x => fn l => if is_some x then the x :: l else l)) []
  1513     |> map Const
  1513     |> map Const
  1514   end
  1514   end
  1515 *}
  1515 \<close>
  1516 
  1516 
  1517 ML {*
  1517 ML \<open>
  1518 fun exists_tac ctxt feats consts_diff =
  1518 fun exists_tac ctxt feats consts_diff =
  1519   let
  1519   let
  1520     val ex_var =
  1520     val ex_var =
  1521       if loop_can_feature [Existential_Var] feats andalso consts_diff <> [] then
  1521       if loop_can_feature [Existential_Var] feats andalso consts_diff <> [] then
  1522         new_skolem_tac ctxt consts_diff
  1522         new_skolem_tac ctxt consts_diff
  1533 
  1533 
  1534 fun forall_tac ctxt feats =
  1534 fun forall_tac ctxt feats =
  1535   if loop_can_feature [Universal] feats then
  1535   if loop_can_feature [Universal] feats then
  1536     forall_pos_tac ctxt
  1536     forall_pos_tac ctxt
  1537   else K no_tac
  1537   else K no_tac
  1538 *}
  1538 \<close>
  1539 
  1539 
  1540 
  1540 
  1541 subsubsection "Finite types"
  1541 subsubsection "Finite types"
  1542 (*lift quantification from a singleton literal to a singleton clause*)
  1542 (*lift quantification from a singleton literal to a singleton clause*)
  1543 lemma forall_pos_lift:
  1543 lemma forall_pos_lift:
  1544 "\<lbrakk>(! X. P X) = True; ! X. (P X = True) \<Longrightarrow> R\<rbrakk> \<Longrightarrow> R" by auto
  1544 "\<lbrakk>(! X. P X) = True; ! X. (P X = True) \<Longrightarrow> R\<rbrakk> \<Longrightarrow> R" by auto
  1545 
  1545 
  1546 (*predicate over the type of the leading quantified variable*)
  1546 (*predicate over the type of the leading quantified variable*)
  1547 
  1547 
  1548 ML {*
  1548 ML \<open>
  1549 fun extcnf_forall_special_pos_tac ctxt =
  1549 fun extcnf_forall_special_pos_tac ctxt =
  1550   let
  1550   let
  1551     val bool =
  1551     val bool =
  1552       ["True", "False"]
  1552       ["True", "False"]
  1553 
  1553 
  1563     THEN' (assume_tac ctxt
  1563     THEN' (assume_tac ctxt
  1564            ORELSE' FIRST'
  1564            ORELSE' FIRST'
  1565             (*FIXME could check the type of the leading quantified variable, instead of trying everything*)
  1565             (*FIXME could check the type of the leading quantified variable, instead of trying everything*)
  1566             (tacs (bool @ bool_to_bool)))
  1566             (tacs (bool @ bool_to_bool)))
  1567   end
  1567   end
  1568 *}
  1568 \<close>
  1569 
  1569 
  1570 
  1570 
  1571 subsubsection "Emulator"
  1571 subsubsection "Emulator"
  1572 
  1572 
  1573 lemma efq: "[|A = True; A = False|] ==> R" by auto
  1573 lemma efq: "[|A = True; A = False|] ==> R" by auto
  1574 ML {*
  1574 ML \<open>
  1575 fun efq_tac ctxt =
  1575 fun efq_tac ctxt =
  1576   (eresolve_tac ctxt @{thms efq} THEN' assume_tac ctxt)
  1576   (eresolve_tac ctxt @{thms efq} THEN' assume_tac ctxt)
  1577   ORELSE' assume_tac ctxt
  1577   ORELSE' assume_tac ctxt
  1578 *}
  1578 \<close>
  1579 
  1579 
  1580 ML {*
  1580 ML \<open>
  1581 (*This is applied to all subgoals, repeatedly*)
  1581 (*This is applied to all subgoals, repeatedly*)
  1582 fun extcnf_combined_main ctxt feats consts_diff =
  1582 fun extcnf_combined_main ctxt feats consts_diff =
  1583   let
  1583   let
  1584     (*This is applied to subgoals which don't have a conclusion
  1584     (*This is applied to subgoals which don't have a conclusion
  1585       consisting of a Skolem definition*)
  1585       consisting of a Skolem definition*)
  1695              not (member (op =) interpreted_consts n))
  1695              not (member (op =) interpreted_consts n))
  1696   in
  1696   in
  1697     if head_of t = Logic.implies then do_diff t
  1697     if head_of t = Logic.implies then do_diff t
  1698     else []
  1698     else []
  1699   end
  1699   end
  1700 *}
  1700 \<close>
  1701 
  1701 
  1702 ML {*
  1702 ML \<open>
  1703 (*remove quantification in hypothesis clause (! X. t), if
  1703 (*remove quantification in hypothesis clause (! X. t), if
  1704   X not free in t*)
  1704   X not free in t*)
  1705 fun remove_redundant_quantification ctxt i = fn st =>
  1705 fun remove_redundant_quantification ctxt i = fn st =>
  1706   let
  1706   let
  1707     val gls =
  1707     val gls =
  1738               Rule_Insts.eres_inst_tac ctxt [((("x", 0), Position.none), "(@X. False)")] []
  1738               Rule_Insts.eres_inst_tac ctxt [((("x", 0), Position.none), "(@X. False)")] []
  1739                 @{thm allE} i st
  1739                 @{thm allE} i st
  1740           end
  1740           end
  1741      end
  1741      end
  1742   end
  1742   end
  1743 *}
  1743 \<close>
  1744 
  1744 
  1745 ML {*
  1745 ML \<open>
  1746 fun remove_redundant_quantification_ignore_skolems ctxt i =
  1746 fun remove_redundant_quantification_ignore_skolems ctxt i =
  1747   COND (TERMPRED (fn _ => true) conc_is_skolem_def (SOME i))
  1747   COND (TERMPRED (fn _ => true) conc_is_skolem_def (SOME i))
  1748     no_tac
  1748     no_tac
  1749     (remove_redundant_quantification ctxt i)
  1749     (remove_redundant_quantification ctxt i)
  1750 *}
  1750 \<close>
  1751 
  1751 
  1752 lemma drop_redundant_literal_qtfr:
  1752 lemma drop_redundant_literal_qtfr:
  1753   "(! X. P) = True \<Longrightarrow> P = True"
  1753   "(! X. P) = True \<Longrightarrow> P = True"
  1754   "(? X. P) = True \<Longrightarrow> P = True"
  1754   "(? X. P) = True \<Longrightarrow> P = True"
  1755   "(! X. P) = False \<Longrightarrow> P = False"
  1755   "(! X. P) = False \<Longrightarrow> P = False"
  1756   "(? X. P) = False \<Longrightarrow> P = False"
  1756   "(? X. P) = False \<Longrightarrow> P = False"
  1757 by auto
  1757 by auto
  1758 
  1758 
  1759 ML {*
  1759 ML \<open>
  1760 (*remove quantification in the literal "(! X. t) = True/False"
  1760 (*remove quantification in the literal "(! X. t) = True/False"
  1761   in the singleton hypothesis clause, if X not free in t*)
  1761   in the singleton hypothesis clause, if X not free in t*)
  1762 fun remove_redundant_quantification_in_lit ctxt i = fn st =>
  1762 fun remove_redundant_quantification_in_lit ctxt i = fn st =>
  1763   let
  1763   let
  1764     val gls =
  1764     val gls =
  1806                   dresolve_tac ctxt @{thms drop_redundant_literal_qtfr} i st
  1806                   dresolve_tac ctxt @{thms drop_redundant_literal_qtfr} i st
  1807               end
  1807               end
  1808           end
  1808           end
  1809      end
  1809      end
  1810   end
  1810   end
  1811 *}
  1811 \<close>
  1812 
  1812 
  1813 ML {*
  1813 ML \<open>
  1814 fun remove_redundant_quantification_in_lit_ignore_skolems ctxt i =
  1814 fun remove_redundant_quantification_in_lit_ignore_skolems ctxt i =
  1815   COND (TERMPRED (fn _ => true) conc_is_skolem_def (SOME i))
  1815   COND (TERMPRED (fn _ => true) conc_is_skolem_def (SOME i))
  1816     no_tac
  1816     no_tac
  1817     (remove_redundant_quantification_in_lit ctxt i)
  1817     (remove_redundant_quantification_in_lit ctxt i)
  1818 *}
  1818 \<close>
  1819 
  1819 
  1820 ML {*
  1820 ML \<open>
  1821 fun extcnf_combined_tac ctxt prob_name_opt feats skolem_consts = fn st =>
  1821 fun extcnf_combined_tac ctxt prob_name_opt feats skolem_consts = fn st =>
  1822   let
  1822   let
  1823     val thy = Proof_Context.theory_of ctxt
  1823     val thy = Proof_Context.theory_of ctxt
  1824 
  1824 
  1825     (*Initially, st consists of a single goal, showing the
  1825     (*Initially, st consists of a single goal, showing the
  1887       THEN IF_UNSOLVED cleanup
  1887       THEN IF_UNSOLVED cleanup
  1888 
  1888 
  1889   in
  1889   in
  1890     DEPTH_SOLVE (CHANGED tec) st
  1890     DEPTH_SOLVE (CHANGED tec) st
  1891   end
  1891   end
  1892 *}
  1892 \<close>
  1893 
  1893 
  1894 
  1894 
  1895 subsubsection "unfold_def"
  1895 subsubsection "unfold_def"
  1896 
  1896 
  1897 (*this is used when handling unfold_tac, because the skeleton includes the definitions conjoined with the goal. it turns out that, for my tactic, the definitions are harmful. instead of modifying the skeleton (which may be nontrivial) i'm just dropping the information using this lemma. obviously, and from the name, order matters here.*)
  1897 (*this is used when handling unfold_tac, because the skeleton includes the definitions conjoined with the goal. it turns out that, for my tactic, the definitions are harmful. instead of modifying the skeleton (which may be nontrivial) i'm just dropping the information using this lemma. obviously, and from the name, order matters here.*)
  1902   or reflexive, or else turned back into an object equation
  1902   or reflexive, or else turned back into an object equation
  1903   and broken down further.*)
  1903   and broken down further.*)
  1904 lemma un_meta_polarise: "(X \<equiv> True) \<Longrightarrow> X" by auto
  1904 lemma un_meta_polarise: "(X \<equiv> True) \<Longrightarrow> X" by auto
  1905 lemma meta_polarise: "X \<Longrightarrow> X \<equiv> True" by auto
  1905 lemma meta_polarise: "X \<Longrightarrow> X \<equiv> True" by auto
  1906 
  1906 
  1907 ML {*
  1907 ML \<open>
  1908 fun unfold_def_tac ctxt depends_on_defs = fn st =>
  1908 fun unfold_def_tac ctxt depends_on_defs = fn st =>
  1909   let
  1909   let
  1910     (*This is used when we end up with something like
  1910     (*This is used when we end up with something like
  1911         (A & B) \<equiv> True \<Longrightarrow> (B & A) \<equiv> True.
  1911         (A & B) \<equiv> True \<Longrightarrow> (B & A) \<equiv> True.
  1912       It breaks down this subgoal until it can be trivially
  1912       It breaks down this subgoal until it can be trivially
  1944             (unfold_tac ctxt depends_on_defs
  1944             (unfold_tac ctxt depends_on_defs
  1945              THEN IF_UNSOLVED continue_reducing_tac)))
  1945              THEN IF_UNSOLVED continue_reducing_tac)))
  1946   in
  1946   in
  1947     tactic st
  1947     tactic st
  1948   end
  1948   end
  1949 *}
  1949 \<close>
  1950 
  1950 
  1951 
  1951 
  1952 subsection "Handling split 'preprocessing'"
  1952 subsection "Handling split 'preprocessing'"
  1953 
  1953 
  1954 lemma split_tranfs:
  1954 lemma split_tranfs:
  1958   "(A & B) & C \<equiv> A & B & C"
  1958   "(A & B) & C \<equiv> A & B & C"
  1959   "A = B \<equiv> (A --> B) & (B --> A)"
  1959   "A = B \<equiv> (A --> B) & (B --> A)"
  1960 by (rule eq_reflection, auto)+
  1960 by (rule eq_reflection, auto)+
  1961 
  1961 
  1962 (*Same idiom as ex_expander_tac*)
  1962 (*Same idiom as ex_expander_tac*)
  1963 ML {*
  1963 ML \<open>
  1964 fun split_simp_tac (ctxt : Proof.context) i =
  1964 fun split_simp_tac (ctxt : Proof.context) i =
  1965    let
  1965    let
  1966      val simpset =
  1966      val simpset =
  1967        fold Simplifier.add_simp @{thms split_tranfs} (empty_simpset ctxt)
  1967        fold Simplifier.add_simp @{thms split_tranfs} (empty_simpset ctxt)
  1968    in
  1968    in
  1969      CHANGED (asm_full_simp_tac simpset i)
  1969      CHANGED (asm_full_simp_tac simpset i)
  1970    end
  1970    end
  1971 *}
  1971 \<close>
  1972 
  1972 
  1973 
  1973 
  1974 subsection "Alternative reconstruction tactics"
  1974 subsection "Alternative reconstruction tactics"
  1975 ML {*
  1975 ML \<open>
  1976 (*An "auto"-based proof reconstruction, where we attempt to reconstruct each inference
  1976 (*An "auto"-based proof reconstruction, where we attempt to reconstruct each inference
  1977   using auto_tac. A realistic tactic would inspect the inference name and act
  1977   using auto_tac. A realistic tactic would inspect the inference name and act
  1978   accordingly.*)
  1978   accordingly.*)
  1979 fun auto_based_reconstruction_tac ctxt prob_name n =
  1979 fun auto_based_reconstruction_tac ctxt prob_name n =
  1980   let
  1980   let
  1987       |> the
  1987       |> the
  1988       |> (fn {inference_fmla, ...} =>
  1988       |> (fn {inference_fmla, ...} =>
  1989           Goal.prove ctxt [] [] inference_fmla
  1989           Goal.prove ctxt [] [] inference_fmla
  1990            (fn pdata => auto_tac (#context pdata)))
  1990            (fn pdata => auto_tac (#context pdata)))
  1991   end
  1991   end
  1992 *}
  1992 \<close>
  1993 
  1993 
  1994 (*An oracle-based reconstruction, which is only used to test the shunting part of the system*)
  1994 (*An oracle-based reconstruction, which is only used to test the shunting part of the system*)
  1995 oracle oracle_iinterp = "fn t => t"
  1995 oracle oracle_iinterp = "fn t => t"
  1996 ML {*
  1996 ML \<open>
  1997 fun oracle_based_reconstruction_tac ctxt prob_name n =
  1997 fun oracle_based_reconstruction_tac ctxt prob_name n =
  1998   let
  1998   let
  1999     val thy = Proof_Context.theory_of ctxt
  1999     val thy = Proof_Context.theory_of ctxt
  2000     val pannot = TPTP_Reconstruct.get_pannot_of_prob thy prob_name
  2000     val pannot = TPTP_Reconstruct.get_pannot_of_prob thy prob_name
  2001   in
  2001   in
  2004      prob_name (#meta pannot) n
  2004      prob_name (#meta pannot) n
  2005       |> the
  2005       |> the
  2006       |> (fn {inference_fmla, ...} => Thm.cterm_of ctxt inference_fmla)
  2006       |> (fn {inference_fmla, ...} => Thm.cterm_of ctxt inference_fmla)
  2007       |> oracle_iinterp
  2007       |> oracle_iinterp
  2008   end
  2008   end
  2009 *}
  2009 \<close>
  2010 
  2010 
  2011 
  2011 
  2012 subsection "Leo2 reconstruction tactic"
  2012 subsection "Leo2 reconstruction tactic"
  2013 
  2013 
  2014 ML {*
  2014 ML \<open>
  2015 exception UNSUPPORTED_ROLE
  2015 exception UNSUPPORTED_ROLE
  2016 exception INTERPRET_INFERENCE
  2016 exception INTERPRET_INFERENCE
  2017 
  2017 
  2018 (*Failure reports can be adjusted to avoid interrupting
  2018 (*Failure reports can be adjusted to avoid interrupting
  2019   an overall reconstruction process*)
  2019   an overall reconstruction process*)
  2169     | "res" => default_tac
  2169     | "res" => default_tac
  2170     | "rename" => default_tac
  2170     | "rename" => default_tac
  2171     | "flexflex" => default_tac
  2171     | "flexflex" => default_tac
  2172     | other => fail ctxt ("Unknown inference rule: " ^ other)
  2172     | other => fail ctxt ("Unknown inference rule: " ^ other)
  2173   end
  2173   end
  2174 *}
  2174 \<close>
  2175 
  2175 
  2176 ML {*
  2176 ML \<open>
  2177 fun interpret_leo2_inference ctxt prob_name node =
  2177 fun interpret_leo2_inference ctxt prob_name node =
  2178   let
  2178   let
  2179     val thy = Proof_Context.theory_of ctxt
  2179     val thy = Proof_Context.theory_of ctxt
  2180     val pannot = TPTP_Reconstruct.get_pannot_of_prob thy prob_name
  2180     val pannot = TPTP_Reconstruct.get_pannot_of_prob thy prob_name
  2181 
  2181 
  2202           [Pretty.str ("Failed inference reconstruction for '" ^
  2202           [Pretty.str ("Failed inference reconstruction for '" ^
  2203             inference_name ^ "' at node " ^ node ^ ":\n"),
  2203             inference_name ^ "' at node " ^ node ^ ":\n"),
  2204            Syntax.pretty_term ctxt inference_fmla]))
  2204            Syntax.pretty_term ctxt inference_fmla]))
  2205     | SOME thm => thm
  2205     | SOME thm => thm
  2206   end
  2206   end
  2207 *}
  2207 \<close>
  2208 
  2208 
  2209 ML {*
  2209 ML \<open>
  2210 (*filter a set of nodes based on which inference rule was used to
  2210 (*filter a set of nodes based on which inference rule was used to
  2211   derive a node*)
  2211   derive a node*)
  2212 fun nodes_by_inference (fms : TPTP_Reconstruct.formula_meaning list) inference_rule =
  2212 fun nodes_by_inference (fms : TPTP_Reconstruct.formula_meaning list) inference_rule =
  2213   let
  2213   let
  2214     fun fold_fun n l =
  2214     fun fold_fun n l =
  2219             if rule_name = inference_rule then n :: l
  2219             if rule_name = inference_rule then n :: l
  2220             else l
  2220             else l
  2221   in
  2221   in
  2222     fold fold_fun (map fst fms) []
  2222     fold fold_fun (map fst fms) []
  2223   end
  2223   end
  2224 *}
  2224 \<close>
  2225 
  2225 
  2226 
  2226 
  2227 section "Importing proofs and reconstructing theorems"
  2227 section "Importing proofs and reconstructing theorems"
  2228 
  2228 
  2229 ML {*
  2229 ML \<open>
  2230 (*Preprocessing carried out on a LEO-II proof.*)
  2230 (*Preprocessing carried out on a LEO-II proof.*)
  2231 fun leo2_on_load (pannot : TPTP_Reconstruct.proof_annotation) thy =
  2231 fun leo2_on_load (pannot : TPTP_Reconstruct.proof_annotation) thy =
  2232   let
  2232   let
  2233     val ctxt = Proof_Context.init_global thy
  2233     val ctxt = Proof_Context.init_global thy
  2234     val dud = ("", Binding.empty, @{term False})
  2234     val dud = ("", Binding.empty, @{term False})
  2254       defs = #defs pannot,
  2254       defs = #defs pannot,
  2255       axs = #axs pannot,
  2255       axs = #axs pannot,
  2256       meta = #meta pannot},
  2256       meta = #meta pannot},
  2257      thy')
  2257      thy')
  2258   end
  2258   end
  2259 *}
  2259 \<close>
  2260 
  2260 
  2261 ML {*
  2261 ML \<open>
  2262 (*Imports and reconstructs a LEO-II proof.*)
  2262 (*Imports and reconstructs a LEO-II proof.*)
  2263 fun reconstruct_leo2 path thy =
  2263 fun reconstruct_leo2 path thy =
  2264   let
  2264   let
  2265     val prob_file = Path.base path
  2265     val prob_file = Path.base path
  2266     val dir = Path.dir path
  2266     val dir = Path.dir path
  2278   in
  2278   in
  2279     (*NOTE we could return the theorem value alone, since
  2279     (*NOTE we could return the theorem value alone, since
  2280        users could get the thy value from the thm value.*)
  2280        users could get the thy value from the thm value.*)
  2281     (thy', theorem)
  2281     (thy', theorem)
  2282   end
  2282   end
  2283 *}
  2283 \<close>
  2284 
  2284 
  2285 end
  2285 end