products/Sources/formale Sprachen/Isabelle/HOL/Tools/Predicate_Compile image not shown  

Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: predicate_compile_proof.ML   Sprache: SML

Original von: Isabelle©

(*  Title:      HOL/Tools/Predicate_Compile/predicate_compile_proof.ML
    Author:     Lukas Bulwahn, TU Muenchen

Proof procedure for the compiler from predicates specified by intro/elim rules to equations.
*)


signature PREDICATE_COMPILE_PROOF =
sig
  type indprem = Predicate_Compile_Aux.indprem;
  type mode = Predicate_Compile_Aux.mode
  val prove_pred : Predicate_Compile_Aux.options -> theory
    -> (string * (term list * indprem listlistlist
    -> (string * typ) list -> string -> bool * mode
    -> (term list * (indprem * Mode_Inference.mode_derivation) listlist * term
    -> thm
end;

structure Predicate_Compile_Proof : PREDICATE_COMPILE_PROOF =
struct

open Predicate_Compile_Aux;
open Mode_Inference;


(* debug stuff *)

fun trace_tac ctxt options s =
  if show_proof_trace options then print_tac ctxt s else Seq.single;

fun assert_tac ctxt pos pred =
  COND pred all_tac (print_tac ctxt ("Assertion failed" ^ Position.here pos) THEN no_tac);


(** special setup for simpset **)

val HOL_basic_ss' =
  simpset_of (put_simpset HOL_basic_ss \<^context>
    addsimps @{thms simp_thms prod.inject}
    setSolver (mk_solver "all_tac_solver" (fn _ => fn _ => all_tac))
    setSolver (mk_solver "True_solver" (fn ctxt => resolve_tac ctxt @{thms TrueI})))


(* auxillary functions *)

(* returns true if t is an application of a datatype constructor *)
(* which then consequently would be splitted *)
fun is_constructor ctxt t =
  (case fastype_of t of
    Type (s, _) => s <> \<^type_name>\<open>fun\<close> andalso can (Ctr_Sugar.dest_ctr ctxt s) t
  | _ => false)

(* MAJOR FIXME:  prove_params should be simple
 - different form of introrule for parameters ? *)


fun prove_param options ctxt nargs t deriv =
  let
    val (f, args) = strip_comb (Envir.eta_contract t)
    val mode = head_mode_of deriv
    val param_derivations = param_derivations_of deriv
    val ho_args = ho_args_of mode args
    val f_tac =
      (case f of
        Const (name, _) => simp_tac (put_simpset HOL_basic_ss ctxt addsimps
           [@{thm pred.sel}, Core_Data.predfun_definition_of ctxt name mode,
           @{thm case_prod_eta}, @{thm case_prod_beta}, @{thm fst_conv},
           @{thm snd_conv}, @{thm prod.collapse}, @{thm Product_Type.split_conv}]) 1
      | Free _ =>
        Subgoal.FOCUS_PREMS (fn {context = ctxt', prems, ...} =>
          let
            val prems' = maps dest_conjunct_prem (take nargs prems)
          in
            rewrite_goal_tac ctxt' (map (fn th => th RS @{thm sym} RS @{thm eq_reflection}) prems') 1
          end) ctxt 1
      | Abs _ => raise Fail "prove_param: No valid parameter term")
  in
    REPEAT_DETERM (resolve_tac ctxt @{thms ext} 1)
    THEN trace_tac ctxt options "prove_param"
    THEN f_tac
    THEN trace_tac ctxt options "after prove_param"
    THEN (REPEAT_DETERM (assume_tac ctxt 1))
    THEN (EVERY (map2 (prove_param options ctxt nargs) ho_args param_derivations))
    THEN REPEAT_DETERM (resolve_tac ctxt @{thms refl} 1)
  end

fun prove_expr options ctxt nargs (premposition : int) (t, deriv) =
  (case strip_comb t of
    (Const (name, _), args) =>
      let
        val mode = head_mode_of deriv
        val introrule = Core_Data.predfun_intro_of ctxt name mode
        val param_derivations = param_derivations_of deriv
        val ho_args = ho_args_of mode args
      in
        trace_tac ctxt options "before intro rule:"
        THEN resolve_tac ctxt [introrule] 1
        THEN trace_tac ctxt options "after intro rule"
        (* for the right assumption in first position *)
        THEN rotate_tac premposition 1
        THEN assume_tac ctxt 1
        THEN trace_tac ctxt options "parameter goal"
        (* work with parameter arguments *)
        THEN (EVERY (map2 (prove_param options ctxt nargs) ho_args param_derivations))
        THEN (REPEAT_DETERM (assume_tac ctxt 1))
      end
  | (Free _, _) =>
      trace_tac ctxt options "proving parameter call.."
      THEN Subgoal.FOCUS_PREMS (fn {context = ctxt', prems, concl, ...} =>
          let
            val param_prem = nth prems premposition
            val (param, _) = strip_comb (HOLogic.dest_Trueprop (Thm.prop_of param_prem))
            val prems' = maps dest_conjunct_prem (take nargs prems)
            fun param_rewrite prem =
              param = snd (HOLogic.dest_eq (HOLogic.dest_Trueprop (Thm.prop_of prem)))
            val SOME rew_eq = find_first param_rewrite prems'
            val param_prem' = rewrite_rule ctxt'
              (map (fn th => th RS @{thm eq_reflection})
                [rew_eq RS @{thm sym}, @{thm split_beta}, @{thm fst_conv}, @{thm snd_conv}])
              param_prem
          in
            resolve_tac ctxt' [param_prem'] 1
          end) ctxt 1
      THEN trace_tac ctxt options "after prove parameter call")

fun SOLVED tac st = FILTER (fn st' => Thm.nprems_of st' = Thm.nprems_of st - 1) tac st

fun prove_match options ctxt nargs out_ts =
  let
    val eval_if_P =
      @{lemma "P ==> Predicate.eval x z ==> Predicate.eval (if P then x else y) z" by simp}
    fun get_case_rewrite t =
      if is_constructor ctxt t then
        let
          val SOME {case_thms, ...} = Ctr_Sugar.ctr_sugar_of ctxt (fst (dest_Type (fastype_of t)))
        in
          fold (union Thm.eq_thm) (case_thms :: map get_case_rewrite (snd (strip_comb t))) []
        end
      else []
    val simprules = insert Thm.eq_thm @{thm "unit.case"} (insert Thm.eq_thm @{thm "prod.case"}
      (fold (union Thm.eq_thm) (map get_case_rewrite out_ts) []))
  (* replace TRY by determining if it necessary - are there equations when calling compile match? *)
  in
    (* make this simpset better! *)
    asm_full_simp_tac (put_simpset HOL_basic_ss' ctxt addsimps simprules) 1
    THEN trace_tac ctxt options "after prove_match:"
    THEN (DETERM (TRY
           (resolve_tac ctxt [eval_if_P] 1
           THEN (SUBPROOF (fn {prems, context = ctxt', ...} =>
             (REPEAT_DETERM (resolve_tac ctxt' @{thms conjI} 1
             THEN (SOLVED (asm_simp_tac (put_simpset HOL_basic_ss' ctxt') 1))))
             THEN trace_tac ctxt' options "if condition to be solved:"
             THEN asm_simp_tac (put_simpset HOL_basic_ss' ctxt') 1
             THEN TRY (
                let
                  val prems' = maps dest_conjunct_prem (take nargs prems)
                    |> filter is_equationlike
                in
                  rewrite_goal_tac ctxt'
                    (map (fn th => th RS @{thm sym} RS @{thm eq_reflection}) prems') 1
                end
             THEN REPEAT_DETERM (resolve_tac ctxt' @{thms refl} 1))
             THEN trace_tac ctxt' options "after if simp; in SUBPROOF") ctxt 1))))
    THEN trace_tac ctxt options "after if simplification"
  end;


(* corresponds to compile_fun -- maybe call that also compile_sidecond? *)

fun prove_sidecond ctxt t =
  let
    fun preds_of t nameTs =
      (case strip_comb t of
        (Const (name, T), args) =>
          if Core_Data.is_registered ctxt name then (name, T) :: nameTs
          else fold preds_of args nameTs
      | _ => nameTs)
    val preds = preds_of t []
    val defs = map
      (fn (pred, T) => Core_Data.predfun_definition_of ctxt pred
        (all_input_of T))
        preds
  in
    simp_tac (put_simpset HOL_basic_ss ctxt
      addsimps (@{thms HOL.simp_thms pred.sel} @ defs)) 1
    (* need better control here! *)
  end

fun prove_clause options ctxt nargs mode (_, clauses) (ts, moded_ps) =
  let
    val (in_ts, clause_out_ts) = split_mode mode ts;
    fun prove_prems out_ts [] =
        (prove_match options ctxt nargs out_ts)
        THEN trace_tac ctxt options "before simplifying assumptions"
        THEN asm_full_simp_tac (put_simpset HOL_basic_ss' ctxt) 1
        THEN trace_tac ctxt options "before single intro rule"
        THEN Subgoal.FOCUS_PREMS
           (fn {context = ctxt', prems, ...} =>
            let
              val prems' = maps dest_conjunct_prem (take nargs prems)
                |> filter is_equationlike
            in
              rewrite_goal_tac ctxt' (map (fn th => th RS @{thm sym} RS @{thm eq_reflection}) prems') 1
            end) ctxt 1
        THEN (resolve_tac ctxt [if null clause_out_ts then @{thm singleI_unit} else @{thm singleI}] 1)
    | prove_prems out_ts ((p, deriv) :: ps) =
        let
          val premposition = (find_index (equal p) clauses) + nargs
          val mode = head_mode_of deriv
          val rest_tac =
            resolve_tac ctxt @{thms bindI} 1
            THEN (case p of Prem t =>
              let
                val (_, us) = strip_comb t
                val (_, out_ts''') = split_mode mode us
                val rec_tac = prove_prems out_ts''' ps
              in
                trace_tac ctxt options "before clause:"
                (*THEN asm_simp_tac (put_simpset HOL_basic_ss ctxt) 1*)
                THEN trace_tac ctxt options "before prove_expr:"
                THEN prove_expr options ctxt nargs premposition (t, deriv)
                THEN trace_tac ctxt options "after prove_expr:"
                THEN rec_tac
              end
            | Negprem t =>
              let
                val (t, args) = strip_comb t
                val (_, out_ts''') = split_mode mode args
                val rec_tac = prove_prems out_ts''' ps
                val name = (case strip_comb t of (Const (c, _), _) => SOME c | _ => NONE)
                val neg_intro_rule =
                  Option.map (fn name =>
                    the (Core_Data.predfun_neg_intro_of ctxt name mode)) name
                val param_derivations = param_derivations_of deriv
                val params = ho_args_of mode args
              in
                trace_tac ctxt options "before prove_neg_expr:"
                THEN full_simp_tac (put_simpset HOL_basic_ss ctxt addsimps
                  [@{thm case_prod_eta}, @{thm case_prod_beta}, @{thm fst_conv},
                   @{thm snd_conv}, @{thm prod.collapse}, @{thm Product_Type.split_conv}]) 1
                THEN (if (is_some name) then
                    trace_tac ctxt options "before applying not introduction rule"
                    THEN Subgoal.FOCUS_PREMS (fn {prems, ...} =>
                      resolve_tac ctxt [the neg_intro_rule] 1
                      THEN resolve_tac ctxt [nth prems premposition] 1) ctxt 1
                    THEN trace_tac ctxt options "after applying not introduction rule"
                    THEN (EVERY (map2 (prove_param options ctxt nargs) params param_derivations))
                    THEN (REPEAT_DETERM (assume_tac ctxt 1))
                  else
                    resolve_tac ctxt @{thms not_predI'} 1
                    (* test: *)
                    THEN dresolve_tac ctxt @{thms sym} 1
                    THEN asm_full_simp_tac
                      (put_simpset HOL_basic_ss ctxt addsimps [@{thm not_False_eq_True}]) 1)
                    THEN simp_tac
                      (put_simpset HOL_basic_ss ctxt addsimps [@{thm not_False_eq_True}]) 1
                THEN rec_tac
              end
            | Sidecond t =>
             resolve_tac ctxt @{thms if_predI} 1
             THEN trace_tac ctxt options "before sidecond:"
             THEN prove_sidecond ctxt t
             THEN trace_tac ctxt options "after sidecond:"
             THEN prove_prems [] ps)
        in (prove_match options ctxt nargs out_ts)
            THEN rest_tac
        end
    val prems_tac = prove_prems in_ts moded_ps
  in
    trace_tac ctxt options "Proving clause..."
    THEN resolve_tac ctxt @{thms bindI} 1
    THEN resolve_tac ctxt @{thms singleI} 1
    THEN prems_tac
  end

fun select_sup _ 1 1 = []
  | select_sup ctxt _ 1 = [resolve_tac ctxt @{thms supI1}]
  | select_sup ctxt n i = resolve_tac ctxt @{thms supI2} :: select_sup ctxt (n - 1) (i - 1);

fun prove_one_direction options ctxt clauses preds pred mode moded_clauses =
  let
    val T = the (AList.lookup (op =) preds pred)
    val nargs = length (binder_types T)
    val pred_case_rule = Core_Data.the_elim_of ctxt pred
  in
    REPEAT_DETERM (CHANGED (rewrite_goals_tac ctxt @{thms split_paired_all}))
    THEN trace_tac ctxt options "before applying elim rule"
    THEN eresolve_tac ctxt [Core_Data.predfun_elim_of ctxt pred mode] 1
    THEN eresolve_tac ctxt [pred_case_rule] 1
    THEN trace_tac ctxt options "after applying elim rule"
    THEN (EVERY (map
           (fn i => EVERY' (select_sup ctxt (length moded_clauses) i) i)
             (1 upto (length moded_clauses))))
    THEN (EVERY (map2 (prove_clause options ctxt nargs mode) clauses moded_clauses))
    THEN trace_tac ctxt options "proved one direction"
  end


(** Proof in the other direction **)

fun prove_match2 options ctxt out_ts =
  let
    fun split_term_tac (Free _) = all_tac
      | split_term_tac t =
        if is_constructor ctxt t then
          let
            val SOME {case_thms, split_asm, ...} =
              Ctr_Sugar.ctr_sugar_of ctxt (fst (dest_Type (fastype_of t)))
            val num_of_constrs = length case_thms
            val (_, ts) = strip_comb t
          in
            trace_tac ctxt options ("Term " ^ (Syntax.string_of_term ctxt t) ^
              " splitting with rules \n" ^ Thm.string_of_thm ctxt split_asm)
            THEN TRY (Splitter.split_asm_tac ctxt [split_asm] 1
              THEN (trace_tac ctxt options "after splitting with split_asm rules")
            (* THEN (Simplifier.asm_full_simp_tac (put_simpset HOL_basic_ss ctxt) 1)
              THEN (DETERM (TRY (etac @{thm Pair_inject} 1)))*)

              THEN (REPEAT_DETERM_N (num_of_constrs - 1)
                (eresolve_tac ctxt @{thms botE} 1 ORELSE eresolve_tac ctxt @{thms botE} 2)))
            THEN assert_tac ctxt \<^here> (fn st => Thm.nprems_of st <= 2)
            THEN (EVERY (map split_term_tac ts))
          end
      else all_tac
  in
    split_term_tac (HOLogic.mk_tuple out_ts)
    THEN (DETERM (TRY ((Splitter.split_asm_tac ctxt @{thms if_split_asm} 1)
    THEN (eresolve_tac ctxt @{thms botE} 2))))
  end

(* VERY LARGE SIMILIRATIY to function prove_param
-- join both functions
*)

(* TODO: remove function *)

fun prove_param2 options ctxt t deriv =
  let
    val (f, args) = strip_comb (Envir.eta_contract t)
    val mode = head_mode_of deriv
    val param_derivations = param_derivations_of deriv
    val ho_args = ho_args_of mode args
    val f_tac =
      (case f of
        Const (name, _) => full_simp_tac (put_simpset HOL_basic_ss ctxt addsimps
           [@{thm pred.sel}, Core_Data.predfun_definition_of ctxt name mode,
            @{thm Product_Type.split_conv}]) 1
      | Free _ => all_tac
      | _ => error "prove_param2: illegal parameter term")
  in
    trace_tac ctxt options "before simplification in prove_args:"
    THEN f_tac
    THEN trace_tac ctxt options "after simplification in prove_args"
    THEN EVERY (map2 (prove_param2 options ctxt) ho_args param_derivations)
  end

fun prove_expr2 options ctxt (t, deriv) =
  (case strip_comb t of
      (Const (name, _), args) =>
        let
          val mode = head_mode_of deriv
          val param_derivations = param_derivations_of deriv
          val ho_args = ho_args_of mode args
        in
          eresolve_tac ctxt @{thms bindE} 1
          THEN (REPEAT_DETERM (CHANGED (rewrite_goals_tac ctxt @{thms split_paired_all})))
          THEN trace_tac ctxt options "prove_expr2-before"
          THEN eresolve_tac ctxt [Core_Data.predfun_elim_of ctxt name mode] 1
          THEN trace_tac ctxt options "prove_expr2"
          THEN (EVERY (map2 (prove_param2 options ctxt) ho_args param_derivations))
          THEN trace_tac ctxt options "finished prove_expr2"
        end
      | _ => eresolve_tac ctxt @{thms bindE} 1)

fun prove_sidecond2 options ctxt t =
  let
    fun preds_of t nameTs =
      (case strip_comb t of
        (Const (name, T), args) =>
          if Core_Data.is_registered ctxt name then (name, T) :: nameTs
          else fold preds_of args nameTs
      | _ => nameTs)
    val preds = preds_of t []
    val defs = map
      (fn (pred, T) => Core_Data.predfun_definition_of ctxt pred
        (all_input_of T))
        preds
  in
    (* only simplify the one assumption *)
    full_simp_tac (put_simpset HOL_basic_ss' ctxt addsimps @{thm pred.sel} :: defs) 1
    (* need better control here! *)
    THEN trace_tac ctxt options "after sidecond2 simplification"
  end

fun prove_clause2 options ctxt pred mode (ts, ps) i =
  let
    val pred_intro_rule = nth (Core_Data.intros_of ctxt pred) (i - 1)
    val (in_ts, _) = split_mode mode ts;
    val split_simpset =
      put_simpset HOL_basic_ss' ctxt
      addsimps [@{thm case_prod_eta}, @{thm case_prod_beta},
        @{thm fst_conv}, @{thm snd_conv}, @{thm prod.collapse}]
    fun prove_prems2 out_ts [] =
      trace_tac ctxt options "before prove_match2 - last call:"
      THEN prove_match2 options ctxt out_ts
      THEN trace_tac ctxt options "after prove_match2 - last call:"
      THEN (eresolve_tac ctxt @{thms singleE} 1)
      THEN (REPEAT_DETERM (eresolve_tac ctxt @{thms Pair_inject} 1))
      THEN (asm_full_simp_tac (put_simpset HOL_basic_ss' ctxt) 1)
      THEN TRY (
        (REPEAT_DETERM (eresolve_tac ctxt @{thms Pair_inject} 1))
        THEN (asm_full_simp_tac (put_simpset HOL_basic_ss' ctxt) 1)

        THEN SOLVED (trace_tac ctxt options "state before applying intro rule:"
        THEN (resolve_tac ctxt [pred_intro_rule]
        (* How to handle equality correctly? *)
        THEN_ALL_NEW (K (trace_tac ctxt options "state before assumption matching")
        THEN' (assume_tac ctxt ORELSE'
          ((CHANGED o asm_full_simp_tac split_simpset) THEN'
            (TRY o assume_tac ctxt))) THEN'
          (K (trace_tac ctxt options "state after pre-simplification:"))
        THEN' (K (trace_tac ctxt options "state after assumption matching:")))) 1))
    | prove_prems2 out_ts ((p, deriv) :: ps) =
      let
        val mode = head_mode_of deriv
        val rest_tac =
          (case p of
            Prem t =>
              let
                val (_, us) = strip_comb t
                val (_, out_ts''') = split_mode mode us
                val rec_tac = prove_prems2 out_ts''' ps
              in
                (prove_expr2 options ctxt (t, deriv)) THEN rec_tac
              end
          | Negprem t =>
              let
                val (_, args) = strip_comb t
                val (_, out_ts''') = split_mode mode args
                val rec_tac = prove_prems2 out_ts''' ps
                val name = (case strip_comb t of (Const (c, _), _) => SOME c | _ => NONE)
                val param_derivations = param_derivations_of deriv
                val ho_args = ho_args_of mode args
              in
                trace_tac ctxt options "before neg prem 2"
                THEN eresolve_tac ctxt @{thms bindE} 1
                THEN (if is_some name then
                    full_simp_tac (put_simpset HOL_basic_ss ctxt addsimps
                      [Core_Data.predfun_definition_of ctxt (the name) mode]) 1
                    THEN eresolve_tac ctxt @{thms not_predE} 1
                    THEN simp_tac (put_simpset HOL_basic_ss ctxt addsimps @{thms not_False_eq_True}) 1
                    THEN (EVERY (map2 (prove_param2 options ctxt) ho_args param_derivations))
                  else
                    eresolve_tac ctxt @{thms not_predE'} 1)
                THEN rec_tac
              end
          | Sidecond t =>
              eresolve_tac ctxt @{thms bindE} 1
              THEN eresolve_tac ctxt @{thms if_predE} 1
              THEN prove_sidecond2 options ctxt t
              THEN prove_prems2 [] ps)
      in
        trace_tac ctxt options "before prove_match2:"
        THEN prove_match2 options ctxt out_ts
        THEN trace_tac ctxt options "after prove_match2:"
        THEN rest_tac
      end
    val prems_tac = prove_prems2 in_ts ps
  in
    trace_tac ctxt options "starting prove_clause2"
    THEN eresolve_tac ctxt @{thms bindE} 1
    THEN (eresolve_tac ctxt @{thms singleE'} 1)
    THEN (TRY (eresolve_tac ctxt @{thms Pair_inject} 1))
    THEN trace_tac ctxt options "after singleE':"
    THEN prems_tac
  end;

fun prove_other_direction options ctxt pred mode moded_clauses =
  let
    fun prove_clause clause i =
      (if i < length moded_clauses then eresolve_tac ctxt @{thms supE} 1 else all_tac)
      THEN (prove_clause2 options ctxt pred mode clause i)
  in
    (DETERM (TRY (resolve_tac ctxt @{thms unit.induct} 1)))
     THEN (REPEAT_DETERM (CHANGED (rewrite_goals_tac ctxt @{thms split_paired_all})))
     THEN (resolve_tac ctxt [Core_Data.predfun_intro_of ctxt pred mode] 1)
     THEN (REPEAT_DETERM (resolve_tac ctxt @{thms refl} 2))
     THEN (
       if null moded_clauses then eresolve_tac ctxt @{thms botE} 1
       else EVERY (map2 prove_clause moded_clauses (1 upto (length moded_clauses))))
  end


(** proof procedure **)

fun prove_pred options thy clauses preds pred (_, mode) (moded_clauses, compiled_term) =
  let
    val ctxt = Proof_Context.init_global thy   (* FIXME proper context!? *)
    val clauses = (case AList.lookup (op =) clauses pred of SOME rs => rs | NONE => [])
  in
    Goal.prove ctxt (Term.add_free_names compiled_term []) [] compiled_term
      (if not (skip_proof options) then
        (fn _ =>
        resolve_tac ctxt @{thms pred_iffI} 1
        THEN trace_tac ctxt options "after pred_iffI"
        THEN prove_one_direction options ctxt clauses preds pred mode moded_clauses
        THEN trace_tac ctxt options "proved one direction"
        THEN prove_other_direction options ctxt pred mode moded_clauses
        THEN trace_tac ctxt options "proved other direction")
      else (fn _ => ALLGOALS (Skip_Proof.cheat_tac ctxt)))
  end

end

¤ Dauer der Verarbeitung: 0.44 Sekunden  (vorverarbeitet)  ¤





Download des
Quellennavigators
Download des
sprechenden Kalenders

in der Quellcodebibliothek suchen




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.


Bot Zugriff