Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/Isabelle/Provers/   (Beweissystem Isabelle Version 2025-1©)  Datei vom 16.11.2025 mit Größe 54 kB image not shown  

Quellcode-Bibliothek TPTP_Proof_Reconstruction.thy   Sprache: Isabelle

 
(*  Title:      HOL/TPTP/TPTP_Proof_Reconstruction.thy
    Author:     Nik Sultana, Cambridge University Computer Laboratory

Proof reconstruction for Leo-II.

USAGE:
* Simple call the "reconstruct_leo2" function.
* For more advanced use, you could use the component functions used in
  "reconstruct_leo2" -- see TPTP_Proof_Reconstruction_Test.thy for
  examples of this.

This file contains definitions describing how to interpret LEO-II's
calculus in Isabelle/HOL, as well as more general proof-handling
functions. The definitions in this file serve to build an intermediate
proof script which is then evaluated into a tactic -- both these steps
are independent of LEO-II, and are defined in the TPTP_Reconstruct SML
module.

CONFIG:
The following attributes are mainly useful for debugging:
  tptp_unexceptional_reconstruction |
  unexceptional_reconstruction      |-- when these are true, a low-level exception
                                        is allowed to float to the top (instead of
                                        triggering a higher-level exception, or
                                        simply indicating that the reconstruction failed).
  tptp_max_term_size                --- fail of a term exceeds this size. "0" is taken
                                        to mean infinity.
  tptp_informative_failure          |
  informative_failure               |-- produce more output during reconstruction.
  tptp_trace_reconstruction         |

There are also two attributes, independent of the code here, that
influence the success of reconstruction: blast_depth_limit and
unify_search_bound. These are documented in their respective modules,
but in summary, if unify_search_bound is increased then we can
handle larger terms (at the cost of performance), since the unification
engine takes longer to give up the search; blast_depth_limit is
a limit on proof search performed by Blast. Blast is used for
the limited proof search that needs to be done to interpret
instances of LEO-II's inference rules.

TODO:
  use RemoveRedundantQuantifications instead of the ad hoc use of
   remove_redundant_quantification_in_lit and remove_redundant_quantification
*)


theory TPTP_Proof_Reconstruction
imports TPTP_Parser TPTP_Interpret
(* keywords "import_leo2_proof" :: thy_decl *) (*FIXME currently unused*)
begin


section "Setup"

ML \<open>
  val tptp_unexceptional_reconstruction = Attrib.setup_config_bool \<^binding>\<open>tptp_unexceptional_reconstruction\<close> (K false)
  fun unexceptional_reconstruction ctxt = Config.get ctxt tptp_unexceptional_reconstruction
  val tptp_informative_failure = Attrib.setup_config_bool \<^binding>\<open>tptp_informative_failure\<close> (K false)
  fun informative_failure ctxt = Config.get ctxt tptp_informative_failure
  val tptp_trace_reconstruction = Attrib.setup_config_bool \<^binding>\<open>tptp_trace_reconstruction\<close> (K false)
  val tptp_max_term_size = Attrib.setup_config_int \<^binding>\<open>tptp_max_term_size\<close> (K 0) (*0=infinity*)

  fun exceeds_tptp_max_term_size ctxt size =
    let
      val max = Config.get ctxt tptp_max_term_size
    in
      if max = 0 then false
      else size > max
    end
\<close>

(*FIXME move to TPTP_Proof_Reconstruction_Test_Units*)
declare [[
  tptp_unexceptional_reconstruction = false, (*NOTE should be "false" while testing*)
  tptp_informative_failure = true
]]

ML \<open>
exception UNSUPPORTED_ROLE
exception INTERPRET_INFERENCE
\<close>

ML_file \<open>TPTP_Parser/tptp_reconstruct_library.ML\<close>
ML "open TPTP_Reconstruct_Library"
ML_file \<open>TPTP_Parser/tptp_reconstruct.ML\<close>

(*FIXME fudge*)
declare [[
  blast_depth_limit = 10,
  unify_search_bound = 5
]]


section "Proof reconstruction"
text \<open>There are two parts to proof reconstruction:
\begin{itemize}
  \item interpreting the inferences
  \item building the skeleton, which indicates how to compose
    individual inferences into subproofs, and then compose the
    subproofs to give the proof).
\end{itemize}

One step detects unsound inferences, and the other step detects
unsound composition of inferences.  The two parts can be weakly
coupled. They rely on a "proof index" which maps nodes to the
inference information. This information consists of the (usually
prover-specific) name of the inference step. ctxt
formalisation ofval = Attrib \<^binding>\<open>tptp_trace_reconstruction\<close> (K false)
then theseterms meta-theorems theskeleton used
compose the inference-level

Leo2
following max = Config  tptp_max_term_size

           C1 &&.. &Cn
          -----------------
          C'1 && ... && C'n

Clauses consist of disjunctions of literals (shown as       max = 0 then
have aprefix !-bound, as shown below

   .{P1 | . || Pn

Literals     null thenno_tac
case;       
object-level formula        funinstantiate =

|.strip_horn
       java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
=

The
clause-level(=G=True (\<forall>x. (F x = G x)) = True"
conjunctions; for   ctxt
disjunction ctxt i

          { 
          ----------java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
          {   true= || ... } && ...


Using this setup, efficiency might be gained by only interpreting( o CHANGED ctxt{ prop_normalisejava.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
inferences once
identical subproofslemmaskolemise []:
We can also attempt" P. (\ (\x. P x)) \ \ (P (SOME x. ~ P x))"
inferences.

It is hoped that this setup can target hilbert 
clause representation -
interpretation P
facilitate composing        "\x. P x)"
\<close>


subsection "Instantiation"

lemma polar_allE [rule_format]:
  "\(\x. P x) = True; (P x) = True \ R\ \ R"
  "\(\x. P x) = False; (P x) = False \ R\ \ R"
by         applyjava.lang.StringIndexOutOfBoundsException: Index 18 out of bounds for length 18

 ? by
  "\(\x. P x) = True; \x. (P x) = True \ R\ \ R"
  "\(\x. P x) = False; \x. (P x) = False \ R\ \ R"
by   case  of

ML \<open>
(*This carries out an allE-like rule but on (polarised) literals.
 Instead of yielding a free variable (which is a hell for the
 matcher) it seeks to use one of the subgoals' parameters.
 This ought to be sufficient for emulating extcnf_combined,
 but note that the complexity of the problem can be enormous.*)

fun ctxtthms  fnst=
  let
    val gls =
      Thmh_property args_property
      |> ed detect
      |> fst

    val parameters =
           if null then []
                  
        rpair (i - 1) java.lang.StringIndexOutOfBoundsException: Range [25, 24) out of bounds for length 56
        |> uncurry.strip_horn
        |> strip_top_all_vars []
        |>fst
        |> map fst (*just get the parameter names*)
  in
    if null parameters then no_tac st
    else
      let

          ( 
                   |> FIRST')
        val attempts = map instantiate parameters
      in
        (fold (curry (op
      end
  end

(*Attempts to use the polar_allE theorems on a specific subgoal.*)
fun  =inst_parametermatch_tac { polar_allE
\<close>

ML
(*This is similar to inst_parametermatch_tac, but prefers to
  match variables having identical names. Logically, this is
  a hack. But it reduces the complexity of the problem.*)

  ctxt i =fn st>
  let
    val gls =
      Thm.prop_of st
| Logic
      |> fst

    Term lhs
      if null gls then []
      java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
        rpair (i - 1) gls
        |> uncurry  (SKOLEM_DEF
        |> strip_top_all_vars []
        |> fst
        |> map fst (*just get the parameter names*)
  in
ull thenst
    else
      let
fun param
          Rule_Insts.eres_inst_tacrev)

                 NONE
      
        if is_none quantified_var then
        else
          if member (op =) parameters (the v (arg_ty val_tyTermdest_funT
            instantiates (the quantified_var(*now find a param of type arg_ty*)
          else
            K no_tac i stvalcandidate_paramparams)
      end
  end
\<close>


subsection "Prefix massaging"

ML \<open>
exception NO_GOALS

(*Get quantifier prefix of the hypothesis and conclusion, reorder
  the hypothesis' quantifiers to have the ones appearing in the
  conclusion first.*)

fun canonicalise_qtfr_order ctxt            TYPE("", _, _ =>   (* FIXME fragile *)
  java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
    val gls =
      java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
      | Logic
      |> fst
  in
    if java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    else
      let
        val (params, (hyp_clause, conc_clause)) =
          rpair (i java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
          |> uncurry nth
          |    drule leo2_skolemise THEN' this_tactic
          NOTE: remember to APPEND' instead of ORELSE' the two tactics relating to skolemisation

        val (hyp_quants, hyp_body) =
rop
          |> strip_top_All_vars
          |> apfstmap(dest_Const_typeuse_candidateskolem_const_ty' ])

        val consts_candidates
          HOLogic.dest_Trueprop conc_clause
          > 
          |> fst

         new_hyp
          (* fold absfree new_hyp_prefix hyp_body *)
          (*HOLogic.list_all*)
          fold_rev (fn>map the
           (prefix_intersection_list
             hyp_quants conc_quants)
           hyp_body
          |> HOLogic.mk_Trueprop

         val  (t, args
           (Logic.mk_implies (hyp_clause          (* list_comb (t, map Free args) *)
            _
              (REPEAT_DETERM find_skolem_term args
              THEN 
i
                     (nominal_inst_parametermatch_tac filtered_candidates
              THEN HEADGOAL
      in
         ctxt] sjava.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
      end
java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
\<close>


subsection   java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47

(*this isn't an actual rule used in Leo2, but it seems to be
  applied implicitly during some Leo2 inferences.*)

lemma polarise: "P java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

ML \<open>
fun is_polarised t =
  (TPTP_Reconstruct.remove_polarity true t; true    val =
let

fun  =
  COND' (SOME #java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
\<close>

              strip_top_all_vars [ #  #
  " .strip_horn #> snd #>
  "(A | B) | )
  "(A & B) & C == A & B & C"
  "~ ~ ) =A"
  (* "(A & B) == (~ (~A | ~B))" *)
  "~ (A & B) == (~A | ~B)"
  "~(A | B) == (~A) & (~B)"
by auto


java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

(*this is not included in simp_meta since it would make a mess of the polarities*)
lemma expand_iff [rule_format]:
 "((A :: bool) = B) \ (~ A | B) & (~ B | A)"
by           |> 

lemma polarity_switch [rule_format]      if is_none var_opt then no_tac
  "(\ P) = True \ P = False"
  "(\ P) = False \ P = True"
      dresolve_tac ctxt [thm]      THEN' instantiate_skols ctxt consts_candidates
  "P = True \ (\ P) = False"
by auto  \<close>

lemma solved_all_splits: "False = True \ False" by simp
ML
fun solved_all_splits_tac ex_expander_tac i java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
  TRY (eresolve_tac ctxt 
  THEN
  THEN  ( simpset
\<close>

lemma lots_of_logic_expansions_meta [rule_format]:
  "(((A :: bool) = B
  "((A :: bool) = Bjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

  "((F = G) = True) \
  "((F = G) = False) ==

  "(A | B) = True == (A = True) | (B = True)"
"A&B)=False == (A = ) | (B = False)java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
  "(A | B) = False == (A = False) & (B = False)"
  "(A & B) = True == (A = True) & (B 1 uptoa
  "(~ A) = True == A = False"
  "(~ A =False == A = True""
  "~ (A = True) == A = False arg_tys ("arg_ \<^sort>\<open>type\<close>)) is
  "~ (A = False) == A = True"
by (rule eq_reflection, auto)+

(*this is used in extcnf_combined handler*)
lemma eq_neg_bool: "((A :: bool) = B) = False ==> ((~ (A | B)) | ~ ((~ A) | (~ B))) = False"
by auto

lemma eq_pos_bool:val =Freef" f_tyjava.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
  "((A :: bool) = B) Free ("x" ^ i ("" ^"_", \<^sort>\type\))) is
  "(A = B) = True
  "(A = B) = val ys = (fn i=>
by auto

(*next formula is more versatile than
    "(F = G) = True \<Longrightarrow> \<forall>x. ((F x = G x) = True)"
  since it doesn't assume that clause is singleton. After splitqtfr,
  and after applying allI exhaustively to the conclusion, we can
  use the existing functions to find the "(F x = G x) = True"
  disjunct in the conclusion*)

lemma"
by auto

(*make sure the conclusion consists of just "False"*)
emma:
  "((A = True) ==> False) ==> A = False"
  (A=False ) =  "
by auto

(*FIXME try to use Drule.equal_elim_rule1 directly for this*)
lemma.mk_Trueprop
lemmas leo2_rules  i =
 lots_of_logic_expansions_meta[THEN

(*FIXME is there any overlap with lots_of_logic_expansions_meta or leo2_rules?*)
  []:"A=B =False \ (A = True) | (B = True)" by auto
lemma extuni_bool1 [rule_format]: "(A = B) = y Free(y i,tyjava.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
lemma extuni_trivjava.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8

(*Order (of A, B, C, D) matters*)
lemma dec_commut_eq [rule_format]:
  "((A = valconc_disjs = map is
  "((java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
lemma []:
  "((A \ B) = (C \ D)) = False \ (B = C) = False \ (A = D) = False"
by auto

lemma extuni_func t=  =.mk_disj, t)


subsectionjava.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11

ML \<open>
(*Instantiate a variable according to the info given in the
  proof annotation. Through this we avoid having to come up
  with instantiations during reconstruction.*)

fun bind_tac ctxt prob_name ordered_binds =

    val thy
    fun term_to_string t =
      Pretty
    val ordered_instancesML
      TPTP_Reconstruct.interpret_bindings(java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
      |> map (snd #> term_to_string)
      |> permute

    (*instantiate a list of variables, order matters*)
    fun instantiate_vars vars tactic
      map (fn var =>
            Rule_Insts.eres_inst_tac ctxt
             [((("x", 0), Position.none.prop_of
          vars
      |> EVERY

    fun instantiate_tac       |> 
      instantiate_vars ctxt vars
      THEN (HEADGOAL (assume_tac ctxt)     null glsthen NO_GOALS
  in
    HEADGOAL (canonicalise_qtfr_order
    THEN (REPEAT_DETERM (HEADGOAL (resolve_tac (params (literal, conc_clause=
    THEN REPEAT_DETERM (HEADGOAL (nominal_inst_parametermatch_tac ctxt @{thm allE -1 ls
           uncurry
    THEN FIRST> strip_top_all_vars]
  end>apsndLogic
\<close>

ML
(*Simplification tactics*)
local
  
    rewrite_goal_tac thms
    |> CHANGED
in# strip_top_All_vars
  val expander_animal =
>java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16

  val simper_animal =
    rew_goal_tac @{thms simp_meta}
end
\<close>

lemma prop_normalise [rule_format]:
  "(A | B) | C == A | B | C"
  "(A & B) & C == A & B & C"
          # head_of
  "~~ A == A"
 auto
ML \<open>
(*i.e., break_conclusion*)
fun flip_conclusion_tac ctxt =
  let
    val default_tac =
      (TRY o CHANGED (_ )   ty
      THEN
      THEN'java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
      THEN' (TRY o (expander_animal ctxt))
  in
    default_tac ORELSE' resolve_tac ctxt @{thms flip}
  end
\<close>


subsection "Skolemisation"

lemma skolemise [rule_format
  "\ P. (\ (\x. P x)) \ \ (P (SOME x. ~ P x))"
proof -
  have "\ P. (\ (\x. P x)) \ \ (P (SOME x. ~ P x))"
   -
    fix P
    assume ption: "\ (\x. P x)"
    hence a: "\x. \ P x" by force

    have hilbert : "\P. (\x. P x) \ (P (SOME x. P x))"
    proof -
      fix P
      assume "(\x. P x)"
       "( (SOME x P))java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
rpair)
        apply (rule> nth
        apply auto> [
        done
    qed

    from a show "\ P (SOME x. \ P x)"
    proof -
      assume "\x. \ P x"
funextuni_dec_elim_rule ctxtarity st>
      thus ?thesis .
    qed
  qed
   ?thesis
qed

lemma polar_skolemise [rule_format]:
  "\P. (\x. P x) = False \ (P (SOME x. \ P x)) = False"
proof -
 \<And>P. (\<forall>x. P x) = False \<Longrightarrow> (P (SOME x. \<not> P x)) = False"
   -
    fix P
    assume ption: "(\x. P x) = False"
    hence "\ (\x. P x)" by force
    hence "\ All P" by force
    hence "\ (P (SOME x. \ P x))" by (rule skolemise)
    thus "(P (SOME x. \ P x)) = False" by force
  qed
  thus ?thesis by blast
qed

lemma
  "\P sk. (\x. P x) = False \ (sk = (SOME x. \ P x)) \ (P sk) = False"
by (clarifyval =

lemmalift_forall [ule_format
  "\x. (\x. A x) = True \ (A x) = True"
  "\x. (\x. A x) = False \ (A x) = False"
byauto
lemma lift_exists [rule_format]:
  "\(All P) = False; sk = (SOME x. \ P x)\ \ P sk = False"
  "\(Ex P) = True; sk = (SOME x. P x)\ \ P sk = True"
apply( , simp
apply (simp, drule someI_ex
done

ML \<open>
(*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*)
fun conc_is_skolem_def t =
  case t of
 elim_tac =
      let
        val (h, args) =
          strip_comb t'
          |> apfst (strip_abs (
        val h_property =
          is_Free h orelse
                      those
          (is_Const h
           andalso (dest_Const_name h <> dest_Const_name \<^term>\<open>HOL.Ex\<close>).export_without_context
           andalso (dest_Const_name h <> dest_Const_name \<^term>\<open>HOL.All\<close>)
           andalso (h <> \<^term>\<open>Hilbert_Choice.Eps\<close>)
           andalso (h <> \<^term>\<open>HOL.conj\<close>)
           andalso (h <> \<^term>\<open>HOL.disj\<close>)
           andalso (h <> \<^term>\<open>HOL.eq\<close>)
           andalso (h <> \<^term>\<open>HOL.implies\<close>)
           andalso (h <> \<^term>\<open>HOL.The\<close>)
           andalso (h <> \<^term>\<open>HOL.Ex1\<close>)
           andalso (h <> \<^term>\<open>HOL.Not\<close>)
           andalso (h <> \<^term>\<open>HOL.iff\<close>)
           andalso (h <> \<^term>\<open>HOL.not_equal\<close>))
        val args_property =
          fold (fn t => fn b =>
           b andalso is_Free t) args true
      in
        h_property andalso args_property
      end
    | _ => false
\<close>

ML \<open>
(*Hack used to detect if a Skolem definition, with an LHS Var, has had the LHS instantiated into an unacceptable term.*)
fun conc_is_bad_skolem_def t =
  case t of
      Const (\<^const_name>\<open>HOL.eq\<close>, _) $ t' $ (Const (\<^const_name>\<open>Hilbert_Choice.Eps\<close>, _) $ _) =>
      let
  valh args) =  t'
        val const_h_test =
           is_Const
            (dest_Const_name h = dest_Const_name \<^term>\<open>HOL.Ex\<close>)
              (dest_Const_name= dest_Const_name
             orelse (h = \<^term>\<open>Hilbert_Choice.Eps\<close>)
             orelse (h = \<^term>\<open>HOL.conj\<close>)
             orelse (h = \<^term>\<open>HOL.disj\<close>)
             orelse (h = \<^term>\<open>HOL.eq\<close>)
              (h =java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
             orelse (h = \<^term>\<open>HOL.The\<close>)
              (h  <^term>\<open>HOL.Ex1\<close>)
             orelse (h = \<^term>\<open>HOL.Not\<close>)
             orelse (h = \<^term>\<open>HOL.iff\<close>)
             orelse (h = \<^term>\<open>HOL.not_equal\<close>)
else
        val h_property =
          not ctxt dec_commut_disj,
          not (is_Var h) andalso
          
        val args_property =
          fold t =  b>
           b andalso is_Free o ) java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
      in
        h_property andalso args_property
      end
    _false
\<close>

ML
fun get_skolem_conc t =
     e.g. ((A & B) & C \<longrightarrow> D & E \<longrightarrow> F \<longrightarrow> G) = False
    val t' =
      strip_top_all_vars [] t
      |> snd
      |> try_dest_Trueprop
  in
    case t' of
        Const (\<^const_name>\<open>HOL.eq\<close>, _) $ t' $ (Const (\<^const_name>\<open>Hilbert_Choice.Eps\<close>, _) $ _) => SOME t'          (A = True) & (B = True          (D = True) & (Eem.
      | _ => NONE  e.g.,  "(A \ B) = True \ A = False | (A = True & B = True)"
  end

fun get_skolem_conc_const t =
  lift_option
   (fn t' =>
     head_of t'
     | strip_abs_body
     |> head_of
     |> dest_Const)
( t)
\<close>

(*
Technique for handling quantifiers:
  Principles:
  * allE should always match with a !!
  * exE should match with a constant,
     or bind a fresh !! -- currently not doing the latter since it never seems to arised in normal Leo2 proofs.
*)


  imp_strip_hornaccConst
fun forall_neg_tac candidate_consts ctxt i = fn st =>
  let
    val gls =
      Thm st
      |> Logic.strip_horn
      |> fst

    val parameters =
imp_strip_horn[]t
      else
        rpair (i - 1) gls
        |> uncurry nth
        |> strip_top_all_vars []
        |> 
        |> map fst (*just get the parameter names*)
        |> (fn l =>
              if null l then ""
              else
                implode_space l
                |> pair " "
                >(op ^)

  in
    if null gls orelse nulljava.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5

      let
        fun instantiate const_namejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
          Rule_Insts ctxt[(sk,0,.none,const_nameparameters)] [java.lang.StringIndexOutOfBoundsException: Index 98 out of bounds for length 98
e
        val attempts = map instantiate (i - 1)gls
      in
        (fold (curry| TPTP_Reconstruct []
      end
  end
\<close>

ML|>fst
exception
exception    (*hypothesis clause should be singleton*)
fun absorb_skolem_def ctxt prob_name_opt i = fn st =>
  let
    val thy = Proof_Context hypos

     gls java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
      Thm.prop_of st
      |> Logic.strip_horn
      |> fst

    val conclusion =
      if null gls then
        (*this should never be thrown*)
        raise NO_GOALS
      else
        rpair (i - 1) gls
        |> uncurry nth
        |> strip_top_all_vars []
        |> snd
        |>Logic
        |> snd

    fun skolem_const_info_of (, conc t
      case t of
           (<const_name>
          head_of t'
          |> strip_abs_body (*since in general might have a skolem term, so we want to rip out the prefixing lambdas to get to the constant (which should be at head position)*)
          |> head_of
          | dest_Const
        | _ => raise SKOLEM_DEF             antes

    val const_name =
      skolem_const_info_of conclusion
      |> fstif  1

    val def_name = const_name ^ "_def"

    val bnd_def = (*FIXME consts*)
      const_name
      >Long_Name  tl.explode(*FIXME hack to drop theory-name prefix*)
      |> Binding.qualified_name
      |> Binding.suffix_name "_def"

    val bnd_namenull 
      case prob_name_opt (,lengthjava.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
          NONE => bnd_def
        | SOME prob_name =>
(*            Binding.qualify false
             (TPTP_Problem_Name.mangle_problem_name prob_name)
*)

             bnd_def

    val thm =
      (case try    (x ^.toString
        SOME thm => thm
      | NONEmap ( var > HOLogic. (var\<^term>\<open>True\<close>)) antecedents)
          if       (HOLogic.mk_eq(, \<^term>\<open>False\<close>))
            (*This mode is for testing, so we can be a bit
              looser with theories*)

            (* FIXME bad theory context!? *)
            Thm.add_axiom_global (bnd_name, conclusion) thy
            |> fst |> snd
          else
            raise (NO_SKOLEM_DEF (def_name, bnd_name, conclusion)))
  in
resolve_tac Drule thm
  end
  handle java.lang.StringIndexOutOfBoundsException: Range [13, 12) out of bounds for length 22
\<close>

ML
(*  .mk_eqpre_hyp,\
In current system, there should only be 2 subgoals: the one where
the skolem definition is being built (with a Var in the LHS), and the other subgoal using Var.
*)


  there's no need to use this expensive matching.*)

fun find_skolem_term     |> Drule.export_without_context
  let
    val

    val gls =
      Thm.prop_of st
      |> Logic.strip_horn
      |> fst

    (*extract the conclusion of each subgoal*)
    val  [drule '
      if gls
        raise NO_GOALS
      else
        map (strip_top_all_vars [] #> snd #> Logic \<open>
        (*Remove skolem-definition conclusion, to avoid wasting time analysing it*)
        |> filter o
        (*There should only be a single goal*) (*FIXME this might not always be the case, in practice*)
        (* |> tap (fn x => @{assert} (is_some (try the_single x))) *)

    (*look for subterms headed by a skolem constant, and whose
      arguments are all parameter Vars*)

    fun get_skolem_terms args (acc : term  ctxt fn >
      case t of
          (c as _) $ ( as  _) =java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
             =  st
             arity arity=
            
            else acc
        | t1 $ (v as Free _) =>
            get_skolem_terms (v ::              weak_conj_tac'assume_tac ctxt st
             get_skolem_terms [] acc t1
        | t1 $ t2 =>
            get_skolem_terms [] acc t1    ( ctxt
             get_skolem_terms [] acc t2
        |java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
        
java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
    map\<open>
    |> datatype =
    > (op)
  end
\<close>

ML \<open>
fun instantiate_skols ctxt |ConjI
  let
    val gls =
      Thm.prop_of st
      |> Logic (*simper_animal + ex_expander_tac*)
       

    val (params
      if null gls then
        raise 
      
        rpair (
        |> uncurry nth
        |> strip_top_all_varsjava.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
        |> apsnd (Logic

    fun skolem_const_info_of t =
      case
          Const 
          
            (*the parameters we will concern ourselves with*)
            val params
              Term.add_frees lhs []
              |> distinct|Forall_special_pos
            (*check to make sure that params' <= params*)
            val _ = \<^assert> (forall (member (op =) params) params')
            val
              let
                val (skolem_const_prety   java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29
                  Term.strip_comb lhs
                  |> apfst
                  |> apsnd length

                val _ = \<^assert> (length params = no_params)

                java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
                fun get_val_ty n ty java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
                  if n = 0 then ty
                  else get_val_ty (n - 1 sublist_of_loop java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
              in ' > '
                get_val_ty no_params skolem_const_prety
end

          in
            (skolem_const_ty, params')
          end
        | _ =|_=>NONE

(*
find skolem const candidates which, after applying distinct members of params' we end up with, give us something of type skolem_const_ty.

given a candidate's type, skolem_const_ty, and params', we get some pemutations of params' (i.e. the order in which they can be given to the candidate in order to get skolem_const_ty). If the list of permutations is empty, then we cannot use that candidate.
*)

(*
only returns a single matching -- since terms are linear, and variable arguments are Vars, order shouldn't matter, so we can ignore permutations.
doesn't work with polymorphism (for which we'd need to use type unification) -- this is OK since no terms should be polymorphic, since Leo2 proofs aren't.
*)

    fun use_candidate target_ty params  '>
        params
        if cur_ty = target_ty then| check_sublist'
          SOME        
         NONE
      else
        
          let
            val (arg_ty, val_ty) = Term.dest_funT            sublist_of_loop_once
            (*now find a param of type arg_ty*)
 (candidate_param') =
              find_and_remove (sndmap l
          in l'
            use_candidate ' ( :: ) val_ty
e;
          catch
             | _fun loop_feats
        

, paramsskolem_const_info_of

(*
For each candidate, build a term and pass it to Thm.instantiate, whic in turn is chained with PRIMITIVE to give us this_tactic.

Big picture:
  we run the following:
    drule leo2_skolemise THEN' this_tactic

NOTE: remember to APPEND' instead of ORELSE' the two tactics relating to skolemisation
*)


val =
      map (dest_Const_type #> use_candidate skolem_const_ty\<^assert>
       consts_candidates
      |> pair consts_candidates (* prefiltered_candidates *)
      |> ListPair.zip
      |> filter (snd NO_LOOP_FEATS
      >mapapsnd)

    val skolem_terms =
      let
          (, args=
          (* list_comb (t, map Free args) *)
          if length args > 0 then
            hd (find_skolem_term ctxt t ( loop_feats loop_feats
           t
      in
        map make_result_t filtered_candidates
      end

    (*prefix a skolem term with bindings for the parameters*)
    (* val contextualise = fold absdummy (map snd params) *)
    val  fold params

    val  ,,Universal


(*now the instantiation code*)

    (*there should only be one Var -- that is from the previous application of drule leo2_skolemise. We look for it at the head position in some equation at a conclusion of a subgoal.*)
 var_opt
      let
        val pre_var =
          gls
          |> map
              ting that
               .strip_hornsnd#
               et_skolem_conc
          |> switch( o eresolve_tac @{thms})
          |> maps (switch        Kno_tac)

          pre_var
          the_singleALLGOALS o)
          |> Var all_tac
          |> Thm.cterm_of ctxt
          |> SOME
      in
        if null pre_var then NONE
else pre_var
     end

    fun instantiate_tac from to = all_tac
      PRIMITIVE (Thm.java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

     tactic
      if is_none
      else
        fold (curry (op APPEND))
          (mapscrubup_tac
  in ctxt
    tactic stTHEN feats
  java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
\<close>

ML
fun new_skolem_tac    |> switch (fold  x>java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
  let
    fun tac     val =
      dresolve_tac ctxt [thm]featsandalso <]then
THENjava.lang.StringIndexOutOfBoundsException: Range [30, 29) out of bounds for length 52
  in
     null thenno_tac
    else FIRST' (map tac @{thms lift_exists})
  end
\<close>

(*
need a tactic to expand "? x . P" to "~ ! x. ~ P"
*)

ML \<open>
fun ex_expander_tac ctxt i =
   let
     val simpset =
       empty_simpset ctxt ctxt
| Simplifier. @{emma  (\<not> (\<forall>x. \<not> P x))" by auto}
    forall_pos_tac
     CHANGED (asm_full_simp_tac simpset K no_tac
   end
\<close>


subsubsection "extuni_dec"

ML \<open>
(*n-ary decomposition. Code is based on the n-ary arg_cong generator*)
fun extuni_dec_n ctxt arity
  
    val _ = \<^assert> (arity > 0)
    val =
      1 upto arity
      |> map Int.toString
    val arg_tysvalbool_to_bool
java.lang.StringIndexOutOfBoundsException: Range [67, 14) out of bounds for length 67
    val   --- java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
    val f = Free ("f", f_ty)
    val xs = map (fn i =>
     oeresolve_tac @ forall_pos_lift
    (*FIXME DRY principle*)
    val ys = map (fn i =>
       ("y" ^ , TFree"arg" ^ i ^"_"\<^sort>\<open>type\<close>))) is

java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
    val hyp_rhs = list_comb (f, ys)
    val =
      HOLogic.eq_const res_ty $ hyp_lhs $ hyp_rhs
    val hyp =
      HOLogic.eq_const HOLogic.boolT $ hyp_eq  eresolve_tac @thms} THENassume_tac
      |> HOLogic.mk_Trueprop
    fun conc_eq i =
      let
        val ty = TFree ("arg" ^ i ^ "_ty"\<^sort>\<open>type\<close>)
        val x = Free extcnf_combined_mainctxt consts_diff
        val y = Free ("y" ^ i, ty)
        val eq = HOLogic.eq_const ty $ x $ y      consisting
in
        HOLogic.eq_const HOLogic.boolT $ eq $ \<^term>\<open>False\<close>
      end

    val consts_diff= opjava.lang.StringIndexOutOfBoundsException: Range [69, 68) out of bounds for length 80

     conc
      if length conc_disjs =Close_Branch' "mark: " (efq_tac ctxt)
the_single
      else
        fold
   > )
         (tl conc_disjs 

    FIXME Building this into the            | RemoveRedundantQuantifications =>
                       (REPEAT_DETERM o remove_redundant_quantification_in_lit)
  in
    Goal =assume_tac
    
  end
\<close>

ML \<open>
(*Determine the arity of a function which the "dec"
  unification rule is about to be applied.
  NOTE:
    * Assumes that there is a single hypothesis
*)

fun find_dec_arity i =   ' markor_pos"dresolve_tac(*could add (6) for negated conjunction*)
  let
    val gls =
Thm st
      |> Logic.strip_horn
      >fst
  in
    if null gls then raise NO_GOALS
    else
      let
        val (params, (literal, conc_clausejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
          rpair (i - 1) gls
          |> uncurry nth
          |> strip_top_all_varsExtuni_Bind > ' ctxt "mark: extuni_triv" (eresolve_tac ctxt@{ extuni_triv})
          |  Logic
          |> apsnd (apfst the_single)

        val get_ty =
          HOLogic
          #> strip_top_All_vars
          # snd
          #> HOLogic.dest_eq (*polarity's "="*)
          #> fst
          >HOLogic 
          #> fst
          #> head_of
          #> dest_Const_type

       fun arity_of ty =
         let
           val (_, res_ty) = dest_funT ty

         in
           1 + arity_of res_ty
         end
         handle (TYPE ("dest_funT", _, _)) => 0

      in
        arity_of (get_ty literal)
      end
  end

(*given an inference, it returns the parameters (i.e., we've already matched the leading & ;shared quantification in the hypothesis & conclusion clauses), and the "raw" inference*)

fun breakdown_inference i = fn st =>
  let
    val 
      Thm.prop_of st
      |> Logicjava.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
      |> fst
  in
    if null gls then raise NO_GOALS
    else
      rpair (i - 1) gls
      |> uncurrycore_tac
      |> strip_top_all_vars []
  end

(*build a custom elimination rule for extuni_dec, and instantiate it to match a specific subgoal*)
fun extuni_dec_elim_rule ctxt arity i = fn st =>
  let
    val rule = extuni_dec_n ctxt arity

    val rule_hyp =
      Thm.prop_of rule
      |> Logic.dest_implies
      |> fst (*assuming that rule has single hypothesis*)

java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
      now consists of a single literal. We       |>Logic
      disregard the>fst
      and it might
      couldd  failsince won agree with the
      rule we have generated.*)

    val inference_hyp =
      snd (breakdown_inference i st)
      |> Logic.dest_implies
      |> fst (*assuming that inference has single hypothesis,
               as explained above.*)

  in
    TPTP_Reconstruct_Library.diff_and_instantiate ctxt rule rule_hyp inference_hyp
  end

fun 
  let
    val arity     do_diff=

    fun elim_tac i st =
      let
        val rule =
          extuni_dec_elim_rule ctxt arity i st
          (*in case we itroduced free variables during
            instantiation, we generalise the rule to make
            those free variables into logical variables.*)

          |>.forall_intr_frees
          |> Drule.export_without_context
      in dresolve_tac ctxt [rule] i st end
      handle NO_GOALS => no_tac st

    fun closure tac =
     (*batter fails if there's no toplevel disjunction in the
       hypothesis, so we also try atac*)

      SOLVE o (tac THEN
    valsearch_tac =
      ASAP
        (resolve_tac ctxt @{thms disjI1} APPEND' resolve_tac
        (FIRST' (map closure
                  [dresolve_tac ctxt remove_redundant_quantification i = st
                   dresolve_tac ctxt @{thms dec_commut_disj},
                   elim_tac]))
  in
    (CHANGED o search_tacLogic
  end
\<close>


subsubsection "standard_cnf"
(*Given a standard_cnf inference, normalise it
     e.g. ((A & B) & C \<longrightarrow> D & E \<longrightarrow> F \<longrightarrow> G) = False
     is changed to
          (A & B & C & D & E & F \<longrightarrow> G) = False
 then custom-build a metatheorem which validates this:
          (A & B & C & D & E & F \<longrightarrow> G) = False
       -------------------------------------------
          (A = True) & (B = True) & (C = True) &
          (D = True) & (E = True) & (F = True) & (G = False)
 and apply this metatheorem.

There aren't any "positive" standard_cnfs in Leo2's calculus:
  e.g.,  "(A \<longrightarrow> B) = True \<Longrightarrow> A = False | (A = True & B = True)"
since "standard_cnf" seems to be applied at the preprocessing
stage, together with splitting.
*)


ML \<open>
(*Conjunctive counterparts to Term.disjuncts_aux and Term.disjuncts*)
fun conjuncts_aux (Const (\<^const_name>\<open>HOL.conj\<close>, _) $ t $ t') conjs =
     conjuncts_aux t (conjuncts_aux t' conjs)
  | conjuncts_aux t conjs = t :: conjs

fun conjuncts t = conjuncts_aux t []

(*HOL equivalent of Logic.strip_horn*)
local
  fun imp_strip_horn' acc (Const (\<^const_name>\HOL.implies\, _) $ A $ B) =
        imp_strip_horn' (A :: acc) B
    | imp_strip_horn' acc t = (acc, t)
in
  fun imp_strip_horn t =
    imp_strip_horn' [] t
    |> apfst rev
end
\<close>

ML \<open>
(*Returns whether the antecedents are separated by conjunctions
  or implications; the number of antecedents; and the polarity
  of the original clause -- I think this will always be "false".*)

fun standard_cnf_type ctxt i : thm -> (TPTP_Reconstruct.formula_kind * int * bool) option = fn st =>
  let
    val gls =
      Thm.prop_of st
      |> Logic.strip_horn
      |> fst

    val hypos =
      if null gls then raise NO_GOALS
      else
        rpair (i - 1) gls
        |> uncurry nth
        |> TPTP_Reconstruct.strip_top_all_vars []
        |> snd
        |> Logic.strip_horn
        |> fst

    (*hypothesis clause should be singleton*)
    val _ = \<^assert> (length hypos = 1)

    val (t, pol) = the_single hypos
      |> try_dest_Trueprop
      |> TPTP_Reconstruct.strip_top_All_vars
      |> snd
      |> TPTP_Reconstruct.remove_polarity true

    (*literal is negative*)
    val _ = \<^assert> (not pol)

    val (antes, conc) = imp_strip_horn t

    val (ante_type, antes') =
      if length antes = 1 then
        let
          val conjunctive_antes =
            the_single antes
            |> conjuncts
        in
          if length conjunctive_antes > 1 then
            (TPTP_Reconstruct.Conjunctive NONE,
             conjunctive_antes)
          else
            (TPTP_Reconstruct.Implicational NONE,
             antes)
        end
      else
        (TPTP_Reconstruct.Implicational NONE,
         antes)
  in
    if null antes then NONE
    else SOME (ante_type, length antes', pol)
  end
\<close>

ML \<open>
(*Given a certain standard_cnf type, build a metatheorem that would
  validate it*)

fun mk_standard_cnf java.lang.StringIndexOutOfBoundsException: Range [0, 24) out of bounds for length 13
  let
    val _ = \<^assert> (arity > 0)
    val vars =
      1 upto + 1)
      |> map (fn i => Free ("x" ^ Int.toString i, HOLogic.boolT))

    val consequent = hd vars
    val antecedents = tl vars

    val conc =
      java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
       (curry HOLogic.mk_conj)
       (map (              #  rev
       (HOLogic.mk_eq (consequent, \<^term>\<open>False\<close>))

    val pre_hyp =
      case kind of
          .Conjunctive =>
            curry HOLogic.mk_imp
             (if length antecedents = 1 then the_single antecedents
              else
                fold (curry HOLogic.mk_conj) (tl antecedents) (hd antecedents))
             (hd vars)
        | TPTP_Reconstruct.Implicational NONE =>
            fold (curry HOLogic             null orelse

    val hyp = HOLogic.mk_eq (pre_hyp, \<^term>\<open>False\<close>)

    val t =
      Logic (HOLogic.mk_Trueprop  hyp HOLogic.k_Truepropconc
  in
    Goal.prove ctxt [] [] t (fn _ => HEADGOAL (blast_tac ctxt))
    |> Drule.export_without_context
  end
\<close>

ML \<open>
(*Applies a d-tactic, then breaks it up conjunctively.
  This can be used to transform subgoals as follows:
     (A \<longrightarrow> B) = False  \<Longrightarrow> R
              |
              v
  \<lbrakk>A = True; B = False\<rbrakk> \<Longrightarrow> R
*)

fun weak_conj_tac ctxt drule =
  dresolve_tac ctxt [drule] THEN'
  (REPEAT_DETERM o eresolve_tac ctxt @{thms conjE})
\<close>

ML \<open>
fun uncurry_lit_neg_tac ctxt =
  REPEAT_DETERM o
    dresolve_tac ctxt [@{lemma "(A \ B \ C) = False \ (A & B \ C) = False" by auto}]
\<close>

ML \<open>
fun standard_cnf_tac ctxt i = fn st =>
  let
    fun core_tactic i = fn st =>
      case standard_cnf_type ctxt i st of
          NONE => no_tac st
        | SOME (kind, arity, _) =>
            let
              val rule = mk_standard_cnf ctxt kind arity;
            in
              (weak_conj_tac ctxt rule THEN' assume_tac ctxt) i st
            end
  in
    (uncurry_lit_neg_tac ctxt
     THEN' TPTP_Reconstruct_Library.reassociate_conjs_tac ctxt
     THEN' core_tactic) i st
  end
\<close>


subsubsection "Emulator prep"

ML \<open>
datatype cleanup_feature =
    RemoveHypothesesFromSkolemDefs
  | RemoveDuplicates

datatype loop_feature =
    Close_Branch
  | ConjI
  | King_Cong
  | Break_Hypotheses
  | Donkey_Cong (*simper_animal + ex_expander_tac*)
  | RemoveRedundantQuantifications
  | Assumption

  (*Closely based on Leo2 calculus*)
  | Existential_Free
  | Existential_Var
  | Universal
  | Not_pos
  | Not_neg
  | Or_pos
  | Or_neg
  | Equal_pos
  | Equal_neg
  | Extuni_Bool2
  | Extuni_Bool1
  | Extuni_Dec
  | Extuni_Bind
  | Extuni_Triv
  | Extuni_FlexRigid
  | Extuni_Func
  | Polarity_switch
  | Forall_special_pos

datatype feature =
    ConstsDiff
  | StripQuantifiers
  | Flip_Conclusion
  | Loop of loop_feature list
  | LoopOnce of loop_feature list
  | InnerLoopOnce of loop_feature list
  | CleanUp of cleanup_feature list
  | AbsorbSkolemDefs
\<close>

ML \<open>
fun can_feature x l =
  let
    fun sublist_of_clean_up el =
      case el of
          CleanUp l'' => SOME l''
        | _ => NONE
    fun sublist_of_loop el =
      case el of
          Loop l'' => SOME l''
        | _ => NONE
    fun sublist_of_loop_once el =
      case el of
          LoopOnce l'' => SOME l''
        | _ => NONE
    fun sublist_of_inner_loop_once el =
      case el of
          InnerLoopOnce l'' => SOME l''
        | _ => NONE

    fun check_sublist sought_sublist opt_list =
      if forall is_none opt_list then false
      else
        fold_options opt_list
        |> flat
        |>    member (op =)  (Term.add_frees hyp_body []) (hd hyp_prefix) then
        |> subset (op =)
  in
    case x of
        CleanUp l' =>
          map sublist_of_clean_up l
          |> check_sublist l'
      | Loop l' =>
          map sublist_of_loop l
          |> check_sublist l'
      | LoopOnce l' =>
          map sublist_of_loop_once l
          |> check_sublist l'
      | InnerLoopOnce l' =>
          map sublist_of_inner_loop_once l
          |> check_sublist l'
      | _ => exists (curry (op =) x) l
  end;

fun loop_can_feature loop_feats l =
  can_feature (Loop loop_feats) l orelse
  can_feature (LoopOnce loop_feats) l orelse
  can_feature (InnerLoopOnce loop_feats) l;

\<^assert> (can_feature ConstsDiff [StripQuantifiers, ConstsDiff]);

\<^assert>
  (can_feature (CleanUp [RemoveHypothesesFromSkolemDefs])
    [CleanUp [RemoveHypothesesFromSkolemDefs, RemoveDuplicates]]);

\<^assert>
  (can_feature (Loop []) [Loop [Existential_Var]]);

\<^assert>
  (not (can_feature (Loop []) [InnerLoopOnce [Existential_Var]]));
\<close>

ML \<open>
exception NO_LOOP_FEATS
fun get_loop_feats (feats : feature list) =
  let
    val loop_find =
      fold (fn x => fn loop_feats_acc =>
        if is_some loop_feats_acc then loop_feats_acc
        else
          case x of
              Loop loop_feats => SOME loop_feats
            | LoopOnce loop_feats => SOME loop_feats
            | InnerLoopOnce loop_feats => SOME loop_feats
            | _ => NONE)
       feats
       NONE
  in
    if is_some loop_find then the loop_find
    else raise NO_LOOP_FEATS
  end;

\<^assert>
  (get_loop_feats [Loop [King_Cong, Break_Hypotheses, Existential_Free, Existential_Var, Universal]] =
   [King_Cong, Break_Hypotheses, Existential_Free, Existential_Var, Universal])
\<close>

(*use as elim rule to remove premises*)
lemma insa_prems: "\Q; P\ \ P" by auto
ML \<open>
fun cleanup_skolem_defs ctxt feats =
  let
    (*remove hypotheses from skolem defs,
     after testing that they look like skolem defs*)

    val dehypothesise_skolem_defs =
      COND' (SOME #> TERMPRED (fn _ => true) conc_is_skolem_def)
        (REPEAT_DETERM o eresolve_tac ctxt @{thms insa_prems})
        (K no_tac)
  in
    if can_feature (CleanUp [RemoveHypothesesFromSkolemDefs]) feats then
      ALLGOALS (TRY o dehypothesise_skolem_defs)
    else all_tac
  end
\<close>

ML \<open>
fun remove_duplicates_tac feats =
  (if can_feature (CleanUp [RemoveDuplicates]) feats then
     distinct_subgoals_tac
   else all_tac)
\<close>

ML \<open>
(*given a goal state, indicates the skolem constants committed-to in it (i.e. appearing in LHS of a skolem definition)*)
fun which_skolem_concs_used ctxt = fn st =>
  let
    val feats = [CleanUp [RemoveHypothesesFromSkolemDefs, RemoveDuplicates]]
    val scrubup_tac =
      cleanup_skolem_defs ctxt feats
      THEN remove_duplicates_tac feats
  in
    scrubup_tac st
    |> break_seq
    |> tap (fn (_, rest) => \<^assert> (null (Seq.list_of rest)))
    |> fst
    |> TERMFUN (snd (*discard hypotheses*)
                 #> get_skolem_conc_const) NONE
    |> switch (fold (fn x => fn l => if is_some x then the x :: l else l)) []
    |> map Const
  end
\<close>

ML \<open>
fun exists_tac ctxt feats consts_diff =
  let
    val ex_var =
      if loop_can_feature [Existential_Var] feats andalso consts_diff <> [] then
        new_skolem_tac ctxt consts_diff
        (*We're making sure that each skolem constant is used once in instantiations.*)
      else K no_tac

    val ex_free =
      if loop_can_feature [Existential_Free] feats andalso consts_diff = [] then
        eresolve_tac ctxt @{thms polar_exE}
      else K no_tac
  in
    ex_var APPEND' ex_free
  end

fun forall_tac ctxt feats =
  if loop_can_feature [Universal] feats then
    forall_pos_tac ctxt
  else K no_tac
\<close>


subsubsection "Finite types"
(*lift quantification from a singleton literal to a singleton clause*)
lemma forall_pos_lift:
"\(\X. P X) = True; \X. (P X = True) \ R\ \ R" by auto

(*predicate over the type of the leading quantified variable*)

ML \<open>
fun extcnf_forall_special_pos_tac ctxt =
  let
    val bool =
      ["True""False"]

    val bool_to_bool =
      ["% _ . True""% _ . False""% x . x""Not"]

    val tacs =
      map (fn t_s =>  (* FIXME proper context!? *)
       Rule_Insts.eres_inst_tac \<^context> [((("x", 0), Position.none), t_s)] [] @{thm allE}
       THEN' assume_tac ctxt)
  in
    (TRY o eresolve_tac ctxt @{thms forall_pos_lift})
    THEN' (assume_tac ctxt
           ORELSE' FIRST'
            (*FIXME could check the type of the leading quantified variable, instead of trying everything*)
            (tacs (bool @ bool_to_bool)))
  end
\<close>


subsubsection "Emulator"

lemma efq: "[|A = True; A = False|] ==> R" by auto
ML \<open>
fun efq_tac ctxt =
  (eresolve_tac ctxt @{thms efq} THEN' assume_tac ctxt)
  ORELSE' assume_tac ctxt
\<close>

ML \<open>
(*This is applied to all subgoals, repeatedly*)
fun extcnf_combined_main ctxt feats consts_diff =
  let
    (*This is applied to subgoals which don't have a conclusion
      consisting of a Skolem definition*)

    fun extcnf_combined_tac' ctxt i = fn st =>
      let
        val skolem_consts_used_so_far = which_skolem_concs_used ctxt st
        val consts_diff' = subtract (op =) skolem_consts_used_so_far consts_diff

        fun feat_to_tac feat =
          case feat of
              Close_Branch => trace_tac' ctxt "mark: closer" (efq_tac ctxt)
            | ConjI => trace_tac' ctxt "mark: conjI" (resolve_tac ctxt @{thms conjI})
            | King_Cong => trace_tac' ctxt "mark: expander_animal" (expander_animal ctxt)
            | Break_Hypotheses => trace_tac' ctxt "mark: break_hypotheses" (break_hypotheses_tac ctxt)
            | RemoveRedundantQuantifications => K all_tac
(*
FIXME Building this into the loop instead.. maybe not the ideal choice
            | RemoveRedundantQuantifications =>
                trace_tac' ctxt "mark: strip_unused_variable_hyp"
                 (REPEAT_DETERM o remove_redundant_quantification_in_lit)
*)


            | Assumption => assume_tac ctxt
(*FIXME both Existential_Free and Existential_Var run same code*)
            | Existential_Free => trace_tac' ctxt "mark: forall_neg" (exists_tac ctxt feats consts_diff')
            | Existential_Var => trace_tac' ctxt "mark: forall_neg" (exists_tac ctxt feats consts_diff')
            | Universal => trace_tac' ctxt "mark: forall_pos" (forall_tac ctxt feats)
            | Not_pos => trace_tac' ctxt "mark: not_pos" (dresolve_tac ctxt @{thms leo2_rules(9)})
            | Not_neg => trace_tac' ctxt "mark: not_neg" (dresolve_tac ctxt @{thms leo2_rules(10)})
            | Or_pos => trace_tac' ctxt "mark: or_pos" (dresolve_tac ctxt @{thms leo2_rules(5)}) (*could add (6) for negated conjunction*)
            | Or_neg => trace_tac' ctxt "mark: or_neg" (dresolve_tac ctxt @{thms leo2_rules(7)})
            | Equal_pos => trace_tac' ctxt "mark: equal_pos" (dresolve_tac ctxt (@{thms eq_pos_bool} @ [@{thm leo2_rules(3)}, @{thm eq_pos_func}]))
            | Equal_neg => trace_tac' ctxt "mark: equal_neg" (dresolve_tac ctxt [@{thm eq_neg_bool}, @{thm leo2_rules(4)}])
            | Donkey_Cong => trace_tac' ctxt "mark: donkey_cong" (simper_animal ctxt THEN' ex_expander_tac ctxt)

            | Extuni_Bool2 => trace_tac' ctxt "mark: extuni_bool2" (dresolve_tac ctxt @{thms extuni_bool2})
            | Extuni_Bool1 => trace_tac' ctxt "mark: extuni_bool1" (dresolve_tac ctxt @{thms extuni_bool1})
            | Extuni_Bind => trace_tac' ctxt "mark: extuni_triv" (eresolve_tac ctxt @{thms extuni_triv})
            | Extuni_Triv => trace_tac' ctxt "mark: extuni_triv" (eresolve_tac ctxt @{thms extuni_triv})
            | Extuni_Dec => trace_tac' ctxt "mark: extuni_dec_tac" (extuni_dec_tac ctxt)
            | Extuni_FlexRigid => trace_tac' ctxt "mark: extuni_flex_rigid" (assume_tac ctxt ORELSE' asm_full_simp_tac ctxt)
            | Extuni_Func => trace_tac' ctxt "mark: extuni_func" (dresolve_tac ctxt @{thms extuni_func})
            | Polarity_switch => trace_tac' ctxt "mark: polarity_switch" (eresolve_tac ctxt @{thms polarity_switch})
            | Forall_special_pos => trace_tac' ctxt "mark: dorall_special_pos" (extcnf_forall_special_pos_tac ctxt)

        val core_tac =
          get_loop_feats feats
          |> map feat_to_tac
          |> FIRST'
      in
        core_tac i st
      end

    (*This is applied to all subgoals, repeatedly*)
    fun extcnf_combined_tac ctxt i =
      COND (TERMPRED (fn _ => true) conc_is_skolem_def (SOME i))
        no_tac
        (extcnf_combined_tac' ctxt i)

    val core_tac = CHANGED (ALLGOALS (IF_UNSOLVED o TRY o extcnf_combined_tac ctxt))

    val full_tac = REPEAT core_tac

  in
    CHANGED
      (if can_feature (InnerLoopOnce []) feats then
         core_tac
       else full_tac)
  end

val interpreted_consts =
  [\<^const_name>\<open>HOL.All\<close>, \<^const_name>\<open>HOL.Ex\<close>,
   \<^const_name>\<open>Hilbert_Choice.Eps\<close>,
   \<^const_name>\<open>HOL.conj\<close>,
   \<^const_name>\<open>HOL.disj\<close>,
   \<^const_name>\<open>HOL.eq\<close>,
   \<^const_name>\<open>HOL.implies\<close>,
   \<^const_name>\<open>HOL.The\<close>,
   <^const_name>\<open>HOL.Ex1\<close>,
   \<^const_name>\<open>HOL.Not\<close>,
   (* @{const_name HOL.iff}, *) (*FIXME do these exist?*)
   (* @{const_name HOL.not_equal}, *)
   \<^const_name>\<open>HOL.False\<close>,
   \<^const_name>\<open>HOL.True\<close>,
   \<^const_name>\<open>Pure.imp\<close>]

fun strip_qtfrs_tac ctxt =
  REPEAT_DETERM (EADGOAL (esolve_tac ctxt allI
  THEN
  THEN (params, conc_clause
  THENrpair i-)gls
    ((REPEAT nth
               | TPTP_Reconstruct.trip_top_all_vars ]
  (*FIXME need to handle "@{thm exI}"?*) apsnd.strip_horn

(*difference in constants between the hypothesis clause and the conclusion clause*)
fun clause_consts_diff thm =
  let
    val t =
      Thm
      |> Logic.dest_impliesfun literal_content (\<^const_name>\<open>HOL.eq\<close>, _) $ lhs $ (rhs as \<^term>\<open>True\<close>)) = SOME (lhs, rhs)
      |> fst

needed since Leo2 inferences don'have *)
      |> TPTP_Reconstruct.strip_top_all_vars []
      |> snd

    val do_diff =
      .dest_implies
      #> uncurry TPTP_Reconstruct 
      #> filter
           (fn
             not (member  hyp_clause
  in
    if head_of t = Logic.implies then do_diff t
    else []
  end
\<close>

L\
(*remove quantification in hypothesis clause (! X. t), if
  X not free in t*)

fun ctxt  fn =
  let
    val gls =
      Thm st
      |> Logic.strip_horn
       fst
  in
    if gls raise
    else
      let
        valparams, (hyp_clauses, conc_clause
          rpair (i - 1)              
          |> uncurry nth
          |> TPTP_Reconstruct.strip_top_all_vars []
          |> apsnd Logic.strip_horn
      in
        (*this is to fail gracefully in case this tactic is applied to a goal which doesn't have a single hypothesis*)
        if hyp_clauses1 no_tac
        else
          let
            val = the_single
            val =
              HOLogic.dest_Trueprop
              #> TPTP_Reconstruct.strip_top_All_vars
              #> apfst rev
            val (hyp_prefix, hyp_body) = sep_prefix hyp_clause
            val (conc_prefix, conc_body) = sep_prefix conc_clause
          in
            if null hyp_prefix orelse
              member (op =) conc_prefix (hd hyp_prefix) orelse
              member (op =)  (Term.add_freesjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
              no_tac st
            else
              Rule_Insts main_tac
} i st
          end
     end
  end
\<close>

ML \<open>
fun remove_redundant_quantification_ignore_skolems ctxt i =
  COND (TERMPRED (fn _ => true) conc_is_skolem_def (SOME i))
    no_tac
    (emove_redundant_quantification ctxt
\<close>

lemma drop_redundant_literal_qtfr:
  "(\X. P) = True \ P = True"
  "(\X. P) = True \ P = True"
  "(\X. P) = False \ P = False"
  "(\X. P) = False \ P = False"
by auto

ML \<open>
(*remove quantification in the literal "(! X. t) = True/False"
  in the singleton hypothesis clause, if X not free in t*)

fun              ALLGOALS (absorb_skolem_defctxt)
  let
    val
      Thm st
      |      get_loop_feats;true)
      |> fst
  in
    if null gls then     tec
    else
      let
        val (params, (hyp_clauses, conc_clause)) =
          rpair-) gls
          |> uncurryTHEN can_feature feats
          |> TPTP_Reconstruct (flip_conclusion_tac)
          |else)
      in
        (*this is to fail gracefully in case this tactic is applied to a goal which doesn't have a single hypothesis*)
                can
        else
          let
            fun literal_content (Const (\<^const_name>\<open>HOL.eq\<close>, _) $ lhs $ (rhs as \<^term>\<open>True\<close>)) = SOME (lhs, rhs)
              | literal_content (Const (\<^const_name>\<open>HOL.eq\<close>, _) $ lhs $ (rhs as \<^term>\<open>False\<close>)) = SOME (lhs, rhs)
              | literal_content t = NONE

            val =
              the_single (CHANGED
              | HOLogic.dest_Trueprop
              |> literal_content

              Author:   Manuel*)
             is_none
              no_tac
            else
              let
                val (hyp_lit_prefix, hyp_lit_body) =
                   hyp_clause a : "a:real_normed_field"
                  |> (fn (t, polarity) =>
                   : summable_powser_split_head diffs_def
| apfst)
  java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
                 nullorelse
                  member (op =)  (Term.add_freesjava.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
                   st
                else
                  dresolve_tac ctxt @{thms drop_redundant_literal_qtfr} i st
              end
          end
     end
  end
\<close>

ML "Handling split'preprocessing'"
fun remove_redundant_quantification_in_lit_ignore_skolems ctxt i =
  COND (TERMPRED (fn _ => true) conc_is_skolem_def (SOME i))
    no_tac
    (remove_redundant_quantification_in_lit ctxt i)
\<close>

ML \<open>
fun extcnf_combined_tac ctxt prob_name_opt feats skolem_consts = fn st =>
  let
    val thy = Proof_Context.theory_of ctxt

    (*Initially, st consists of a single goal, showing the
      hypothesis clause implying the conclusion clause.
      There are no parameters.*)

    val consts_diff =
      union (=) skolem_consts
       (if can_feature ConstsDiff feats then
          clause_consts_diff st
        else [])

    val main_tac =
      if can_feature (LoopOnce []) feats orelse can_feature (InnerLoopOnce []) feats then
        extcnf_combined_main ctxt feats consts_diff
      else if can_feature (Loop []) feats then
        BEST_FIRST (TERMPRED (fn _ => true) conc_is_skolem_def NONE, size_of_thm)
(*FIXME maybe need to weaken predicate to include "solved form"?*)
         (extcnf_combined_main ctxt feats consts_diff)
      else all_tac (*to allow us to use the cleaning features*)

    (*Remove hypotheses from Skolem definitions,
      then remove duplicate subgoals,
      then we should be left with skolem definitions:
        absorb them as axioms into the theory.*)

    val cleanup =
      cleanup_skolem_defs ctxt feats
      THEN remove_duplicates_tac feats
      THEN (if can_feature AbsorbSkolemDefs feats then
              ALLGOALS (absorb_skolem_def ctxt prob_name_opt)
            else all_tac)

    val have_loop_feats =
      (get_loop_feats feats; true)
      handle NO_LOOP_FEATS => false

    val tec =
      (if can_feature StripQuantifiers feats then
         (REPEAT (CHANGED (strip_qtfrs_tac ctxt)))
       else all_tac)
      THEN (if can_feature Flip_Conclusion feats then
             HEADGOAL (flip_conclusion_tac ctxt)
           else all_tac)

      (*after stripping the quantifiers any remaining quantifiers
        can be simply eliminated -- they're redundant*)

      (*FIXME instead of just using allE, instantiate to a silly
         term, to remove opportunities for unification.*)

      THEN (REPEAT_DETERM (eresolve_tac ctxt @{thms allE} 1))

      THEN (REPEAT_DETERM (resolve_tac ctxt @{thms allI} 1))

      THEN (if have_loop_feats then
              REPEAT (CHANGED
              ((ALLGOALS (TRY o clause_breaker_tac ctxt)) (*brush away literals which don't change*)
               THEN
                (*FIXME move this to a different level?*)
                (if loop_can_feature [Polarity_switch] feats then
                   all_tac
                 else
                   (TRY (IF_UNSOLVED (HEADGOAL (remove_redundant_quantification_ignore_skolems ctxt))))
                   THEN (TRY (IF_UNSOLVED (HEADGOAL (remove_redundant_quantification_in_lit_ignore_skolems ctxt)))))
               THEN (TRY main_tac)))
            else
              all_tac)
      THEN IF_UNSOLVED cleanup

  in
    DEPTH_SOLVE (CHANGED tec) st
  end
\<close>


subsubsection "unfold_def"

(*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.*)
lemma drop_first_hypothesis [rule_format]: "\A; B\ \ B" by auto

(*Unfold_def works by reducing the goal to a meta equation,
  then working on it until it can be discharged by atac,
  or reflexive, or else turned back into an object equation
  and broken down further.*)

lemma un_meta_polarise: "(X \ True) \ X" by auto
lemma meta_polarise: "X \ X \ True" by auto

ML \<open>
fun unfold_def_tac ctxt depends_on_defs = fn st =>
  let
    (*This is used when we end up with something like
        (A & B) \<equiv> True \<Longrightarrow> (B & A) \<equiv> True.
      It breaks down this subgoal until it can be trivially
      discharged.
     *)

    val kill_meta_eqs_tac =
      dresolve_tac ctxt @{thms un_meta_polarise}
      THEN' resolve_tac ctxt @{thms meta_polarise}
      THEN' (REPEAT_DETERM o (eresolve_tac ctxt @{thms conjE}))
      THEN' (REPEAT_DETERM o (resolve_tac ctxt @{thms conjI} ORELSE' assume_tac ctxt))

    val continue_reducing_tac =
      resolve_tac ctxt @{thms meta_eq_to_obj_eq} 1
      THEN (REPEAT_DETERM (ex_expander_tac ctxt 1))
      THEN TRY (polarise_subgoal_hyps ctxt 1) (*no need to REPEAT_DETERM here, since there should only be one hypothesis*)
      THEN TRY (dresolve_tac ctxt @{thms eq_reflection} 1)
      THEN (TRY ((CHANGED o rewrite_goal_tac ctxt
              (@{thm expand_iff} :: @{thms simp_meta})) 1))
      THEN HEADGOAL (resolve_tac ctxt @{thms reflexive}
                     ORELSE' assume_tac ctxt
                     ORELSE' kill_meta_eqs_tac)

    val tactic =
      (resolve_tac ctxt @{thms polarise} 1 THEN assume_tac ctxt 1)
      ORELSE
        (REPEAT_DETERM (eresolve_tac ctxt @{thms conjE} 1 THEN
          eresolve_tac ctxt @{thms drop_first_hypothesis} 1)
         THEN PRIMITIVE (Conv.fconv_rule Thm.eta_long_conversion)
         THEN (REPEAT_DETERM (ex_expander_tac ctxt 1))
         THEN (TRY ((CHANGED o rewrite_goal_tac ctxt @{thms simp_meta}) 1))
         THEN PRIMITIVE (Conv.fconv_rule Thm.eta_long_conversion)
         THEN
           (HEADGOAL (assume_tac ctxt)
           ORELSE
            (unfold_tac ctxt depends_on_defs
             THEN IF_UNSOLVED continue_reducing_tac)))
  in
    tactic st
  end
\<close>


subsection "Handling split 'preprocessing'"

--> --------------------

--> maximum size reached

--> --------------------

98%


¤ 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.0.99Bemerkung:  ¤

*Bot Zugriff






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.