Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/Archive-of-Formal-Proofs/thys/Auto2_HOL/   (Sammlung formaler Beweise Version 2026-5©)  Datei vom 31.4.2026 mit Größe 35 kB image not shown  

Quelle  proofsteps.ML

  Sprache: SML
 

(*
  File: proofsteps.ML
  Author: Bohua Zhan

  Definition of type proofstep, and facility for adding basic proof steps.
*)


datatype proofstep_fn
  = OneStep of Proof.context -> box_item -> raw_update list
  | TwoStep of Proof.context -> box_item -> box_item -> raw_update list

type proofstep = {
  name: string,
  args: match_arg list,
  func: proofstep_fn
}

datatype prfstep_descriptor = WithFact of term
                            | WithItem of string * term
                            | WithProperty of term
                            | WithWellForm of term * term
                            | WithScore of int
                            | GetFact of term * thm
                            | ShadowFirst | ShadowSecond
                            | CreateCase of term | CreateConcl of term
                            | Filter of prfstep_filter

(* Conditional prfstep_descriptors. *)
type pre_prfstep_descriptor = Proof.context -> prfstep_descriptor

signature PROOFSTEP =
sig
  val eq_prfstep: proofstep * proofstep -> bool
  val apply_prfstep: Proof.context -> box_item list -> proofstep -> raw_update list
  val WithGoal: term -> prfstep_descriptor
  val WithTerm: term -> prfstep_descriptor
  val WithProp: term -> prfstep_descriptor
  val string_of_desc: theory -> prfstep_descriptor -> string
  val string_of_descs: theory -> prfstep_descriptor list -> string

  (* prfstep_filter *)
  val all_insts: prfstep_filter
  val neq_filter: term -> prfstep_filter
  val order_filter: string -> string -> prfstep_filter
  val size1_filter: string -> prfstep_filter
  val not_type_filter: string -> typ -> prfstep_filter

  (* First level proofstep writing functions. *)
  val apply_pat_r: Proof.context -> id_inst_ths -> term * thm -> thm
  val retrieve_args: prfstep_descriptor list -> match_arg list
  val retrieve_pats_r: prfstep_descriptor list -> (term * thm) list
  val retrieve_filts: prfstep_descriptor list -> prfstep_filter
  val retrieve_cases: prfstep_descriptor list -> term list
  val retrieve_shadows: prfstep_descriptor list -> int list
  val get_side_ths:
      Proof.context -> id_inst -> match_arg list -> (box_id * thm listlist
  val prfstep_custom:
      string -> prfstep_descriptor list ->
      (id_inst_ths -> box_item list -> Proof.context -> raw_update list) -> proofstep
  val gen_prfstep: string -> prfstep_descriptor list -> proofstep
  val prfstep_pre_conv: string -> prfstep_descriptor list ->
                        (Proof.context -> conv) -> proofstep
  val prfstep_conv: string -> prfstep_descriptor list -> conv -> proofstep
end;

functor ProofStep(
  structure ItemIO: ITEM_IO;
  structure Matcher: MATCHER;
  structure PropertyData: PROPERTY_DATA;
  structure RewriteTable: REWRITE_TABLE;
  structure UtilBase: UTIL_BASE;
  structure UtilLogic: UTIL_LOGIC;
  structure Update: UPDATE;
  structure WellformData: WELLFORM_DATA;
  ): PROOFSTEP =
struct

fun eq_prfstep (prfstep1, prfstep2) = (#name prfstep1 = #name prfstep2)

fun apply_prfstep ctxt items {func, ...} =
    case func of
        OneStep f => f ctxt (the_single items)
      | TwoStep f => f ctxt (hd items) (nth items 1)

fun WithGoal t =
    let
      val _ = assert (type_of t = UtilBase.boolT) "WithGoal: pat should have type bool."
    in
      WithFact (UtilLogic.get_neg t)
    end

fun WithTerm t = WithItem (TY_TERM, t)

fun WithProp t =
    let
      val _ = assert (type_of t = UtilBase.boolT) "WithProp: pat should have type bool."
    in
      WithItem (TY_PROP, t)
    end

fun string_of_desc thy desc =
    let
      val print = Syntax.string_of_term_global thy
    in
      case desc of
          WithFact t =>
          if UtilLogic.is_neg t then "WithGoal " ^ (print (UtilLogic.get_neg t))
          else "WithFact " ^ (print t)
        | WithItem (ty_str, t) =>
          if ty_str = TY_TERM then "WithTerm " ^ (print t)
          else "WithItem " ^ ty_str ^ " " ^ (print t)
        | WithProperty t => "WithProperty " ^ (print t)
        | WithWellForm (_, req) => "WithWellForm " ^ (print req)
        | WithScore n => "WithScore " ^ (string_of_int n)
        | GetFact (t, th) =>
          if t aconv @{term Falsethen
            "GetResolve " ^ (Util.name_of_thm th)
          else if UtilLogic.is_neg t then
            "GetGoal (" ^ (print (UtilLogic.get_neg t)) ^ ", " ^ (Util.name_of_thm th) ^ ")"
          else
            "GetFact (" ^ (print t) ^ ", " ^ (Util.name_of_thm th) ^ ")"
        | ShadowFirst => "Shadow first" | ShadowSecond => "Shadow second"
        | CreateCase assum => "CreateCase " ^ (print assum)
        | CreateConcl concl => "CreateConcl " ^ (print concl)
        | Filter _ => "Filter (...)"
    end

fun string_of_descs thy descs =
    let
      fun is_filter desc = case desc of Filter _ => true | _ => false
      val (filts, non_filts) = filter_split is_filter descs
    in
      (cat_lines (map (string_of_desc thy) non_filts)) ^
      (if length filts > 0 then
         (" + " ^ (string_of_int (length filts)) ^ " filters"else "")
    end

(* prfstep_filter *)

val all_insts = fn _ => fn _ => true

fun neq_filter cond ctxt (id, inst) =
    let
      val (lhs, rhs) =
          cond |> UtilLogic.dest_not |> UtilBase.dest_eq
          handle Fail "dest_not" => raise Fail "neq_filter: not an inequality."
               | Fail "dest_eq" => raise Fail "neq_filter: not an inequality."
      val _ = assert (null (Term.add_frees cond []))
                     "neq_filter: should not contain free variable."

      val t1 = Util.subst_term_norm inst lhs
      val t2 = Util.subst_term_norm inst rhs
    in
      if Util.has_vars t1 andalso Util.has_vars t2 then true
      else if Util.has_vars t1 then
        (Matcher.rewrite_match ctxt (t1, Thm.cterm_of ctxt t2) (id, fo_init))
            |> filter (fn ((id', _), _) => id = id') |> null
      else if Util.has_vars t2 then
        (Matcher.rewrite_match ctxt (t2, Thm.cterm_of ctxt t1) (id, fo_init))
            |> filter (fn ((id', _), _) => id = id') |> null
      else
        not (RewriteTable.is_equiv_t id ctxt (t1, t2))
    end

fun order_filter s1 s2 _ (_, inst) =
    not (Term_Ord.term_ord (lookup_inst inst s2, lookup_inst inst s1) = LESS)

fun size1_filter s1 ctxt (id, inst) =
    size_of_term (RewriteTable.simp_val_t id ctxt (lookup_inst inst s1)) = 1

fun not_type_filter s ty _ (_, inst) =
    not (Term.fastype_of (lookup_inst inst s) = ty)

(* First level proofstep writing functions. *)
fun apply_pat_r ctxt ((_, inst), ths) (pat_r, th) =
    let
      val _ = assert (fastype_of pat_r = UtilBase.boolT)
                     "apply_pat_r: pat_r should be of type bool"

      (* Split into meta equalities (usually produced by term
         matching, not applied to th, and others (assumptions for th).
       *)

      val (eqs, ths') = ths |> filter_split (Util.is_meta_eq o Thm.prop_of)
      val _ = assert (length ths' = Thm.nprems_of th)
                     "apply_pat_r: wrong number of assumptions."

      val inst_new = Util.subst_term_norm inst (UtilLogic.mk_Trueprop pat_r)
      val th' = th |> Util.subst_thm ctxt inst |> fold Thm.elim_implies ths'
      val _ = if inst_new aconv (Thm.prop_of th') then () else
              raise Fail "apply_pat_r: conclusion mismatch"

      (* Rewrite on subterms, top sweep order. *)
      fun rewr_top eq_th = Conv.top_sweep_rewrs_conv [eq_th] ctxt
    in
      th' |> apply_to_thm (Conv.every_conv (map rewr_top eqs))
    end

fun retrieve_args descs =
    maps (fn desc => case desc of
                         WithFact t => [PropMatch t]
                       | WithItem (ty_str, t) => [TypedMatch (ty_str, t)]
                       | WithProperty t => [PropertyMatch t]
                       | WithWellForm t => [WellFormMatch t]
                       | _ => [])
         descs

fun retrieve_pats_r descs =
    maps (fn desc => case desc of
                         GetFact (pat_r, th) => [(pat_r, th)]
                       | _ => [])
         descs

fun retrieve_filts descs =
    let
      val filts = maps (fn Filter filt => [filt] | _ => []) descs
    in
      fn ctxt => fn inst => forall (fn f => f ctxt inst) filts
    end

fun retrieve_cases descs =
    let
      fun retrieve_case desc =
          case desc of
              CreateCase assum => [UtilLogic.mk_Trueprop assum]
            | CreateConcl concl => [UtilLogic.mk_Trueprop (UtilLogic.get_neg concl)]
            | _ => []
    in
      maps retrieve_case descs
    end

fun retrieve_shadows descs =
    let
      fun retrieve_shadow desc =
          case desc of ShadowFirst => [0] | ShadowSecond => [1] | _ => []
    in
      maps retrieve_shadow descs
    end

fun retrieve_score descs =
    let
      fun retrieve_score desc =
          case desc of WithScore n => SOME n | _ => NONE
    in
      get_first retrieve_score descs
    end

(* Given list of PropertyMatch and WellFormMatch arguments, attempt to
   find the corresponding theorems in the rewrite table. Return the
   list of theorems for each possible (mutually non-comparable) box
   IDs.
 *)

fun get_side_ths ctxt (id, inst) side_args =
    if null side_args then
      [(id, [])]
    else let
      val side_args' = map (ItemIO.subst_arg inst) side_args
      fun process_side_arg side_arg =
          case side_arg of
              PropertyMatch prop =>
              PropertyData.get_property_t ctxt (id, prop)
            | WellFormMatch (t, req) =>
              (WellformData.get_wellform_t ctxt (id, t))
                  |> filter (fn (_, th) => UtilLogic.prop_of' th aconv req)
            | _ => raise Fail "get_side_ths: wrong kind of arg."
      val side_ths = map process_side_arg side_args'
    in
      if exists null side_ths then []
      else side_ths |> BoxID.get_all_merges_info ctxt
                    |> Util.max_partial (BoxID.id_is_eq_ancestor ctxt)
    end

(* Creates a proofstep with specified patterns and filters (in descs),
   and a custom function converting any instantiations into updates.
 *)

fun prfstep_custom name descs updt_fn =
    let
      val args = retrieve_args descs
      val (item_args, side_args) = filter_split ItemIO.is_ordinary_match args
      val filt = retrieve_filts descs
      val shadows = retrieve_shadows descs

      (* Processing an instantiation after matching the one or two
         main matchers: apply filters, remove trivial True from
         matchings, find properties, and replace incremental ids.
       *)

      fun process_inst ctxt ((id, inst), ths) =
          (get_side_ths ctxt (id, inst) side_args)
              |> filter (BoxID.has_incr_id o fst)
              |> map (fn (id', p_ths) => ((id', inst), p_ths @ ths))
              |> filter (filt ctxt o fst)

      fun shadow_to_update items ((id, _), _) n =
          ShadowItem {id = id, item = nth items n}
    in
      if length item_args = 1 then
        let
          val arg = the_single item_args
          fun prfstep ctxt item =
              let
                val inst_ths = (ItemIO.match_arg ctxt arg item ([], fo_init))
                                |> map (fn (inst, th) => (inst, [th]))
                                |> maps (process_inst ctxt)

                fun process_inst inst_th =
                    updt_fn inst_th [item] ctxt @
                    map (shadow_to_update [item] inst_th) shadows
              in
                maps process_inst inst_ths
              end
        in
          {name = name, args = args, func = OneStep prfstep}
        end
      else if length item_args = 2 then
        let
          val (arg1, arg2) = the_pair item_args
          fun prfstep1 ctxt item1 =
              let
                val inst_ths = ItemIO.match_arg ctxt arg1 item1 ([], fo_init)

                fun process_inst1 item2 ((id, inst), th) =
                    let
                      val arg2' = ItemIO.subst_arg inst arg2
                      val inst_ths' =
                          (ItemIO.match_arg ctxt arg2' item2 (id, inst))
                              |> map (fn (inst', th') => (inst', [th, th']))
                              |> maps (process_inst ctxt)

                      fun process_inst inst_th' =
                          updt_fn inst_th' [item1, item2] ctxt @
                          map (shadow_to_update [item1, item2] inst_th') shadows
                    in
                      maps process_inst inst_ths'
                    end
              in
                fn item2 => maps (process_inst1 item2) inst_ths
              end
        in
          {name = name, args = args, func = TwoStep prfstep1}
        end
      else
        raise Fail "prfstep_custom: must have 1 or 2 patterns."
    end

(* Create a proofstep from a list of proofstep descriptors. See
   datatype prfstep_descriptor for allowed types of descriptors.
 *)

fun gen_prfstep name descs =
    let
      val args = retrieve_args descs
      val pats_r = retrieve_pats_r descs
      val cases = retrieve_cases descs
      val sc = retrieve_score descs
      val input_descs =
          filter (fn desc => case desc of GetFact _ => false
                                        | CreateCase _ => false
                                        | CreateConcl _ => false
                                        | _ => true) descs

      (* Verify that all schematic variables appearing in pats_r /
         cases appear in pats.
       *)

      val pats = map ItemIO.pat_of_match_arg args
      val vars = map Var (fold Term.add_vars pats [])
      fun check_pat_r (pat_r, _) =
          subset (op aconv) (map Var (Term.add_vars pat_r []), vars)
      fun check_case assum =
          subset (op aconv) (map Var (Term.add_vars assum []), vars)
      val _ = assert (forall check_pat_r pats_r andalso forall check_case cases)
                     "gen_prfstep: new schematic variable in pats_r / cases."

      fun pats_r_to_update ctxt (inst_ths as ((id, _), _)) =
          if null pats_r then [] else
          let
            val ths = map (apply_pat_r ctxt inst_ths) pats_r
          in
            if length ths = 1 andalso
               Thm.prop_of (the_single ths) aconv UtilLogic.pFalse then
              [ResolveBox {id = id, th = the_single ths}]
            else
              [AddItems {id = id, sc = sc,
                         raw_items = map Update.thm_to_ritem ths}]
          end

      fun case_to_update ((id, inst), _) assum =
          AddBoxes {id = id, sc = sc,
                    init_assum = Util.subst_term_norm inst assum}
      fun cases_to_update inst_ths = map (case_to_update inst_ths) cases

      fun updt_fn inst_th _ ctxt =
          pats_r_to_update ctxt inst_th @ cases_to_update inst_th
    in
      prfstep_custom name input_descs updt_fn
    end

fun prfstep_pre_conv name descs pre_cv =
    let
      val args = retrieve_args descs
      val _ = case args of
                  [TypedMatch ("TERM", _)] => ()
                | _ => raise Fail ("prfstep_conv: should have exactly one " ^
                                   "term pattern.")
      val filt = retrieve_filts descs

      fun prfstep ctxt item =
          let
            val inst_ths =
                (ItemIO.match_arg ctxt (the_single args) item ([], fo_init))
                    |> filter (BoxID.has_incr_id o fst o fst)
                    |> filter (filt ctxt o fst)

            fun inst_to_updt ((id, _), eq1) =
                (* Here eq1 is meta_eq from pat(inst) to item. *)
                let
                  val ct = Thm.lhs_of eq1
                  val err = name ^ ": cv failed."
                  val eq_th = pre_cv ctxt ct
                              handle CTERM _ => raise Fail err
                in
                  if Thm.is_reflexive eq_th then [] else
                  if RewriteTable.is_equiv id ctxt (Thm.rhs_of eq1, Thm.rhs_of eq_th)
                  then []
                  else let
                    val th = UtilLogic.to_obj_eq (Util.transitive_list [meta_sym eq1, eq_th])
                  in
                    [Update.thm_update (id, th)]
                  end
                end
          in
            maps inst_to_updt inst_ths
          end
    in
      {name = name, args = args, func = OneStep prfstep}
    end

fun prfstep_conv name descs cv = prfstep_pre_conv name descs (K cv)

end  (* structure ProofStep *)

signature PROOFSTEP_DATA =
sig
  val add_prfstep: proofstep -> theory -> theory
  val del_prfstep_pred: (string -> bool) -> theory -> theory
  val del_prfstep: string -> theory -> theory
  val del_prfstep_thm: thm -> theory -> theory
  val del_prfstep_thm_str: string -> thm -> theory -> theory
  val del_prfstep_thm_eqforward: thm -> theory -> theory
  val get_prfsteps: theory -> proofstep list

  val add_prfstep_custom:
      (string * prfstep_descriptor list *
       (id_inst_ths -> box_item list -> Proof.context -> raw_update list)) ->
      theory -> theory

  val add_gen_prfstep: string * prfstep_descriptor list -> theory -> theory
  val add_prfstep_pre_conv: string * prfstep_descriptor list *
                            (Proof.context -> conv) -> theory -> theory
  val add_prfstep_conv:
      string * prfstep_descriptor list * conv -> theory -> theory

  (* Constructing conditional prfstep_descriptors. *)
  type pre_prfstep_descriptor = pre_prfstep_descriptor
  val with_term: string -> pre_prfstep_descriptor
  val with_cond: string -> pre_prfstep_descriptor
  val with_conds: string list -> pre_prfstep_descriptor list
  val with_filt: prfstep_filter -> pre_prfstep_descriptor
  val with_filts: prfstep_filter list -> pre_prfstep_descriptor list
  val with_score: int -> pre_prfstep_descriptor

  (* Second level proofstep writing functions. *)
  datatype prfstep_mode = MODE_FORWARD | MODE_FORWARD' | MODE_BACKWARD
                          | MODE_BACKWARD1 | MODE_BACKWARD2 | MODE_RESOLVE
  val add_prfstep_check_req: string * string -> theory -> theory
  val add_forward_prfstep_cond:
      thm -> pre_prfstep_descriptor list -> theory -> theory
  val add_forward'_prfstep_cond:
      thm -> pre_prfstep_descriptor list -> theory -> theory
  val add_backward_prfstep_cond:
      thm -> pre_prfstep_descriptor list -> theory -> theory
  val add_backward1_prfstep_cond:
      thm -> pre_prfstep_descriptor list -> theory -> theory
  val add_backward2_prfstep_cond:
      thm -> pre_prfstep_descriptor list -> theory -> theory
  val add_resolve_prfstep_cond:
      thm -> pre_prfstep_descriptor list -> theory -> theory
  val add_forward_prfstep: thm -> theory -> theory
  val add_forward'_prfstep: thm -> theory -> theory
  val add_backward_prfstep: thm -> theory -> theory
  val add_backward1_prfstep: thm -> theory -> theory
  val add_backward2_prfstep: thm -> theory -> theory
  val add_resolve_prfstep: thm -> theory -> theory

  val add_rewrite_rule_cond:
      thm -> pre_prfstep_descriptor list -> theory -> theory
  val add_rewrite_rule_back_cond:
      thm -> pre_prfstep_descriptor list -> theory -> theory
  val add_rewrite_rule_bidir_cond:
      thm -> pre_prfstep_descriptor list -> theory -> theory

  val add_rewrite_rule: thm -> theory -> theory
  val add_rewrite_rule_back: thm -> theory -> theory
  val add_rewrite_rule_bidir: thm -> theory -> theory

  val setup_attrib: (thm -> theory -> theory) -> attribute context_parser
end;

functor ProofStepData(
  structure ItemIO: ITEM_IO;
  structure Normalizer: NORMALIZER;
  structure ProofStep: PROOFSTEP;
  structure Property: PROPERTY;
  structure UtilBase: UTIL_BASE;
  structure UtilLogic: UTIL_LOGIC;
  ): PROOFSTEP_DATA =
struct

structure Data = Theory_Data (
  type T = proofstep list;
  val empty = [];
  fun merge (ps1, ps2) = Library.merge ProofStep.eq_prfstep (ps1, ps2)
)

(* Add the given proof step. *)
fun add_prfstep (prfstep as {args, ...}) =
    Data.map (fn prfsteps =>
       if Util.is_prefix_str "$" (#name prfstep) then
         error "Add prfstep: names beginning with $ is reserved."
       else let
         val num_args = length (filter_out ItemIO.is_side_match args)
       in
         if num_args >= 1 andalso num_args <= 2 then prfsteps @ [prfstep]
         else error "add_prfstep: need 1 or 2 patterns."
       end)

(* Deleting a proofstep. For string inputs, try adding theory
   name. For theorem inputs, try all @-suffixes.
 *)

fun del_prfstep_pred pred =
    Data.map (fn prfsteps =>
       let
         val names = map #name prfsteps
         val to_delete = filter pred names
         fun eq_name (key, {name, ...}) = (key = name)
       in
         if null to_delete then
           error "Delete prfstep: not found"
         else let
           val _ = writeln (cat_lines (map (fn name => "Delete " ^ name)
                                           to_delete))
         in
           subtract eq_name to_delete prfsteps
         end
       end)

fun del_prfstep prfstep_name thy =
    del_prfstep_pred (equal prfstep_name) thy

(* Delete all proofsteps for a given theorem. *)
fun del_prfstep_thm th =
    let
      val th_name = Util.name_of_thm th
    in
      del_prfstep_pred (equal th_name orf Util.is_prefix_str (th_name ^ "@"))
    end

(* Delete proofsteps for a given theorem, with the given postfix. *)
fun del_prfstep_thm_str str th =
    del_prfstep_pred (equal (Util.name_of_thm th ^ str))

val del_prfstep_thm_eqforward = del_prfstep_thm_str "@eqforward"

fun get_prfsteps thy = Data.get thy

fun add_prfstep_custom (name, descs, updt_fn) =
    add_prfstep (ProofStep.prfstep_custom name descs updt_fn)

fun add_gen_prfstep (name, descs) =
    add_prfstep (ProofStep.gen_prfstep name descs)

fun add_prfstep_pre_conv (name, descs, pre_cv) =
    add_prfstep (ProofStep.prfstep_pre_conv name descs pre_cv)

fun add_prfstep_conv (name, descs, cv) =
    add_prfstep (ProofStep.prfstep_conv name descs cv)

(* Constructing conditional prfstep_descriptors. *)

type pre_prfstep_descriptor = pre_prfstep_descriptor

fun with_term str ctxt =
    let
      val t = Proof_Context.read_term_pattern ctxt str
      val _ = assert (null (Term.add_frees t []))
                     "with_term: should not contain free variable."
    in
      ProofStep.WithTerm t
    end

fun with_cond str ctxt =
    Filter (ProofStep.neq_filter (Proof_Context.read_term_pattern ctxt str))

fun with_conds strs = map with_cond strs

fun with_filt filt = K (Filter filt)
fun with_filts filts = map with_filt filts
fun with_score n = K (WithScore n)

(* Second level proofstep writing functions. *)

fun add_and_print_prfstep prfstep_name descs thy =
    let
      val _ = writeln (prfstep_name ^ "\n" ^ (ProofStep.string_of_descs thy descs))
    in
      add_gen_prfstep (prfstep_name, descs) thy
    end

(* Add a proofstep checking a requirement. *)
fun add_prfstep_check_req (t_str, req_str) thy =
    let
      val ctxt = Proof_Context.init_global thy
      val t = Proof_Context.read_term_pattern ctxt t_str
      val vars = map Free (Term.add_frees t [])
      val c = Util.get_head_name t
      val ctxt' = fold Util.declare_free_term vars ctxt
      val req = Proof_Context.read_term_pattern ctxt' req_str

      fun get_subst var =
          case var of Free (x, T) => (var, Var ((x, 0), T))
                    | _ => raise Fail "add_prfstep_check_req"
      val subst = map get_subst vars
      val t' = Term.subst_atomic subst t
      val req' = Term.subst_atomic subst req
    in
      add_and_print_prfstep
          (c ^ "_case") [ProofStep.WithTerm t', CreateConcl req'] thy
    end

datatype prfstep_mode = MODE_FORWARD | MODE_FORWARD' | MODE_BACKWARD
                        | MODE_BACKWARD1 | MODE_BACKWARD2 | MODE_RESOLVE

(* Maximum number of term matches for the given mode. *)
fun max_term_matches mode =
    case mode of
        MODE_FORWARD => 2
      | MODE_FORWARD' => 1
      | MODE_BACKWARD => 1
      | MODE_RESOLVE => 1
      | _ => 0

(* Obtain the first several premises of th that are either properties
   or wellformed-ness data. ts is the list of term matches.
 *)

fun get_side_prems thy mode ts th =
    let
      val (prems, concl) = UtilLogic.strip_horn' th
      val _ = assert (length ts <= max_term_matches mode)
                     "get_side_prems: too many term matches."

      (* Helper function. Consider the case where the first n premises
         are side conditions. Find the additional terms to match
         against for each mode.
       *)

      fun additional_matches n =
          let
            val prems' = drop n prems
          in
            case mode of
                MODE_FORWARD => take (2 - length ts) prems'
              | MODE_FORWARD' =>
                if null ts andalso length prems' >= 2 then
                  [hd prems', List.last prems']
                else [List.last prems']
              | MODE_BACKWARD => [UtilLogic.get_neg concl]
              | MODE_BACKWARD1 => [UtilLogic.get_neg concl, List.last prems']
              | MODE_BACKWARD2 => [UtilLogic.get_neg concl, hd prems']
              | MODE_RESOLVE =>
                if null ts andalso length prems' > 0 then
                  [UtilLogic.get_neg concl, List.last prems']
                else [UtilLogic.get_neg concl]
          end

      (* Determine whether t is a valid side premises, relative to the
         matches ts'. If yes, return the corresponding side
         matching. Otherwise return NONE.
       *)

      fun to_side_prems ts' t =
          case WellForm.is_subterm_wellform_data thy t ts' of
              SOME (t, req) => SOME (WithWellForm (t, req))
            | NONE => if Property.is_property_prem thy t then SOME (WithProperty t)
                      else NONE

      (* Attempt to convert the first n premises to side matchings. *)
      fun to_side_prems_n n =
          let
            val ts' = additional_matches n @ ts
            val side_prems' = prems |> take n
                                    |> map (to_side_prems ts')
          in
            if forall is_some side_prems' then
              SOME (map the side_prems')
            else NONE
          end

      (* Minimum number of premises for the given mode. *)
      val min_prems =
          case mode of
              MODE_FORWARD => 1 - length ts
            | MODE_FORWARD' => 1
            | MODE_BACKWARD => 1
            | MODE_BACKWARD1 => 2
            | MODE_BACKWARD2 => 2
            | MODE_RESOLVE => 0

      val _ = assert (length prems >= min_prems)
                     "get_side_prems: too few premises."
      val to_test = rev (0 upto (length prems - min_prems))
    in
      (* Always succeeds at 0. *)
      the (get_first to_side_prems_n to_test)
    end

(* Convert theorems of the form A1 ==> ... ==> An ==> C to A1 & ... &
   An ==> C. If keep_last = true, the last assumption is kept in
   implication form.
 *)

fun atomize_conj_cv keep_last ct =
    if length (Logic.strip_imp_prems (Thm.term_of ct)) <=
       (if keep_last then 2 else 1then
      Conv.all_conv ct
    else
      Conv.every_conv [Conv.arg_conv (atomize_conj_cv keep_last),
                       Conv.rewr_conv UtilBase.atomize_conjL_th] ct

(* Swap the last premise to become the first. *)
fun swap_prem_to_front ct =
    let
      val n = length (Logic.strip_imp_prems (Thm.term_of ct))
    in
      if n < 2 then
        Conv.all_conv ct
      else if n = 2 then
        Conv.rewr_conv Drule.swap_prems_eq ct
      else
        ((Conv.arg_conv swap_prem_to_front)
             then_conv (Conv.rewr_conv Drule.swap_prems_eq)) ct
    end

(* Using cv, rewrite all assumptions and conclusion in ct. *)
fun horn_conv cv ct =
    (case Thm.term_of ct of
         @{const Pure.imp} $ _ $ _ =>
         (Conv.arg1_conv (UtilLogic.Trueprop_conv cv))
             then_conv (Conv.arg_conv (horn_conv cv))
       | _ => UtilLogic.Trueprop_conv cv) ct

(* Try to cancel terms of the form ~~A. *)
val try_nn_cancel_cv = Conv.try_conv (UtilLogic.rewr_obj_eq UtilBase.nn_cancel_th)

(* Post-processing of the given theorem according to mode. *)
fun post_process_th ctxt mode side_count ts th =
    case mode of
        MODE_FORWARD =>
        let
          val to_skip = side_count + (2 - length ts)
        in
          th |> apply_to_thm (Util.skip_n_conv to_skip (UtilLogic.to_obj_conv ctxt))
             |> Util.update_name_of_thm th ""
        end
      | MODE_FORWARD' =>
        let
          val cv =
              swap_prem_to_front
                  then_conv (Util.skip_n_conv (2 - length ts) (UtilLogic.to_obj_conv ctxt))
        in
          th |> apply_to_thm (Util.skip_n_conv side_count cv)
             |> Util.update_name_of_thm th ""
        end
      | MODE_BACKWARD =>
        let
          val cv = (atomize_conj_cv false)
                       then_conv (Conv.rewr_conv UtilBase.backward_conv_th)
                       then_conv (horn_conv try_nn_cancel_cv)
        in
          th |> apply_to_thm (Util.skip_n_conv side_count cv)
             |> Util.update_name_of_thm th "@back"
        end
      | MODE_BACKWARD1 =>
        let
          val cv = (atomize_conj_cv true)
                       then_conv (Conv.rewr_conv UtilBase.backward1_conv_th)
                       then_conv (horn_conv try_nn_cancel_cv)
        in
          th |> apply_to_thm (Util.skip_n_conv side_count cv)
             |> Util.update_name_of_thm th "@back1"
        end
      | MODE_BACKWARD2 =>
        let
          val cv = (Conv.arg_conv (atomize_conj_cv false))
                       then_conv (Conv.rewr_conv UtilBase.backward2_conv_th)
                       then_conv (horn_conv try_nn_cancel_cv)
        in
          th |> apply_to_thm (Util.skip_n_conv side_count cv)
             |> Util.update_name_of_thm th "@back2"
        end
      | MODE_RESOLVE =>
        let
          val rewr_th =
              case Thm.nprems_of th - side_count of
                  0 => if UtilLogic.is_neg (UtilLogic.concl_of' th) then UtilBase.to_contra_form_th'
                       else UtilBase.to_contra_form_th
                | 1 => UtilBase.resolve_conv_th
                | _ => raise Fail "resolve: too many hypothesis in th."
          val cv = (Conv.rewr_conv rewr_th)
                       then_conv (horn_conv try_nn_cancel_cv)
        in
          th |> apply_to_thm (Util.skip_n_conv side_count cv)
             |> Util.update_name_of_thm th "@res"
        end

(* Add basic proofstep for the given theorem and mode. *)
fun add_basic_prfstep_cond th mode conds thy =
    let
      val ctxt = Proof_Context.init_global thy
      val ctxt' = ctxt |> Variable.declare_term (Thm.prop_of th)

      (* Replace variable definitions, obtaining list of replacements
         and the new theorem.
       *)

      val (pairs, th) =
          th |> apply_to_thm (UtilLogic.to_obj_conv_on_horn ctxt')
             |> Normalizer.meta_use_vardefs
             |> apsnd (Util.update_name_of_thm th "")

      (* List of definitions used. *)
      fun print_def_subst (lhs, rhs) =
          writeln ("Apply def " ^ (Syntax.string_of_term ctxt' lhs) ^ " = " ^
                   (Syntax.string_of_term ctxt' rhs))
      val _ = map print_def_subst pairs

      fun def_subst_fun cond =
          case cond of
              WithItem ("TERM", t) =>
              WithItem ("TERM", Normalizer.def_subst pairs t)
            | _ => cond
    in
      if null conds andalso
         (mode = MODE_FORWARD orelse mode = MODE_FORWARD') andalso
         Property.can_add_property_update th thy then
        Property.add_property_update th thy
      else let
        fun is_term_cond cond =
            case cond of WithItem ("TERM", _) => true | _ => false

        fun extract_term_cond cond =
            case cond of
                WithItem ("TERM", t) => t | _ => raise Fail "extract_term_cond"

        (* Instantiate each element of conds with ctxt', then separate
           into term and other (filter and shadow) conds.
         *)

        val (term_conds, filt_conds) =
            conds |> map (fn cond => cond ctxt')
                  |> filter_split is_term_cond
                  |> apfst (map def_subst_fun)

        (* Get list of assumptions to be obtained from either the
           property table or the wellform table.
         *)

        val ts = map extract_term_cond term_conds
        val side_prems = get_side_prems thy mode ts th
        val side_count = length side_prems
        val th' = th |> post_process_th ctxt' mode side_count ts

        val (assums, concl) =
            th' |> UtilLogic.strip_horn' |> apfst (drop side_count)
        val pats = map extract_term_cond term_conds @ assums
        val match_descs = term_conds @ map WithFact assums
        val _ = assert (Util.is_pattern_list pats)
                       "add_basic_prfstep: invalid patterns."
        val _ = assert (length pats > 0 andalso length pats <= 2)
                       "add_basic_prfstep: invalid number of patterns."
      in
        (* Switch two assumptions if necessary. *)
        if length pats = 2 andalso not (Util.is_pattern (hd pats)) then
          let
            val _ = writeln "Switching two patterns."
            val swap_prems_cv = Conv.rewr_conv Drule.swap_prems_eq
            val th'' =
                if length assums = 1 then th'
                else th' |> apply_to_thm (Util.skip_n_conv side_count swap_prems_cv)
                         |> Util.update_name_of_thm th' ""
            val swap_match_descs = [nth match_descs 1, hd match_descs]
            val descs = side_prems @ swap_match_descs @ filt_conds @
                        [GetFact (concl, th'')]
          in
            add_and_print_prfstep (Util.name_of_thm th') descs thy
          end
        else
          let
            val descs = side_prems @ match_descs @ filt_conds @
                        [GetFact (concl, th')]
          in
            add_and_print_prfstep (Util.name_of_thm th') descs thy
          end
      end
    end

fun add_forward_prfstep_cond th = add_basic_prfstep_cond th MODE_FORWARD
fun add_forward'_prfstep_cond th = add_basic_prfstep_cond th MODE_FORWARD'
fun add_backward_prfstep_cond th = add_basic_prfstep_cond th MODE_BACKWARD
fun add_backward1_prfstep_cond th = add_basic_prfstep_cond th MODE_BACKWARD1
fun add_backward2_prfstep_cond th = add_basic_prfstep_cond th MODE_BACKWARD2
fun add_resolve_prfstep_cond th = add_basic_prfstep_cond th MODE_RESOLVE

fun add_forward_prfstep th = add_forward_prfstep_cond th []
fun add_forward'_prfstep th = add_forward'_prfstep_cond th []
fun add_backward_prfstep th = add_backward_prfstep_cond th []
fun add_backward1_prfstep th = add_backward1_prfstep_cond th []
fun add_backward2_prfstep th = add_backward2_prfstep_cond th []
fun add_resolve_prfstep th = add_resolve_prfstep_cond th []

fun add_rewrite_eq_rule_cond th conds thy =
    let
      val th = if Util.is_meta_eq (Thm.concl_of th) then
                 UtilLogic.to_obj_eq_th th else th
      val (lhs, _) = th |> UtilLogic.concl_of' |> UtilLogic.strip_conj |> hd |> UtilBase.dest_eq
    in
      thy |> add_forward_prfstep_cond th (K (ProofStep.WithTerm lhs) :: conds)
    end

fun add_rewrite_iff_rule_cond th conds thy =
    let
      val th = if Util.is_meta_eq (Thm.concl_of th) then
                 UtilLogic.to_obj_eq_iff_th th else th
      val (lhs, _) = th |> UtilLogic.concl_of' |> UtilBase.dest_eq
      val _ = assert (fastype_of lhs = UtilBase.boolT)
                     "add_rewrite_iff: argument not of type bool."

      val forward_th = th |> UtilLogic.equiv_forward_th
      val nforward_th = th |> UtilLogic.inv_backward_th
                           |> apply_to_thm (horn_conv try_nn_cancel_cv)
                           |> Util.update_name_of_thm th "@invbackward"
    in
      thy |> add_basic_prfstep_cond forward_th MODE_FORWARD' conds
          |> add_basic_prfstep_cond nforward_th MODE_FORWARD' conds
    end

fun add_rewrite_rule_cond th conds thy =
    let
      val th = if Util.is_meta_eq (Thm.concl_of th) then UtilLogic.to_obj_eq_th th else th
      val (lhs, _) = th |> UtilLogic.concl_of' |> UtilLogic.strip_conj |> hd |> UtilBase.dest_eq
    in
      if fastype_of lhs = UtilBase.boolT then
        add_rewrite_iff_rule_cond th conds thy
      else
        add_rewrite_eq_rule_cond th conds thy
    end

fun add_rewrite_rule_back_cond th conds =
    add_rewrite_rule_cond (UtilLogic.obj_sym_th th) conds

fun add_rewrite_rule_bidir_cond th conds =
    (add_rewrite_rule_cond th conds)
        #> add_rewrite_rule_back_cond th conds

fun add_rewrite_rule th = add_rewrite_rule_cond th []
fun add_rewrite_rule_back th = add_rewrite_rule_back_cond th []
fun add_rewrite_rule_bidir th = add_rewrite_rule th #> add_rewrite_rule_back th

fun setup_attrib f =
    Attrib.add_del
        (Thm.declaration_attribute (
            fn th => Context.mapping (f th) I))
        (Thm.declaration_attribute (
            fn _ => fn _ => raise Fail "del_step: not implemented."))

end  (* structure ProofStepData. *)

Messung V0.5 in Prozent
C=64 H=94 G=80

¤ Dauer der Verarbeitung: 0.8 Sekunden  (vorverarbeitet am  2026-06-10) ¤

*© Formatika GbR, Deutschland






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 und die Messung sind noch experimentell.