src/HOL/Tools/transfer.ML
changeset 51956 a4d81cdebf8b
parent 51955 04d9381bebff
child 51996 26aecb553c74
equal deleted inserted replaced
51955:04d9381bebff 51956:a4d81cdebf8b
     1 (*  Title:      HOL/Tools/transfer.ML
     1 (*  Title:      HOL/Tools/transfer.ML
     2     Author:     Brian Huffman, TU Muenchen
     2     Author:     Brian Huffman, TU Muenchen
       
     3     Author:     Ondrej Kuncar, TU Muenchen
     3 
     4 
     4 Generic theorem transfer method.
     5 Generic theorem transfer method.
     5 *)
     6 *)
     6 
     7 
     7 signature TRANSFER =
     8 signature TRANSFER =
     8 sig
     9 sig
     9   val prep_conv: conv
    10   val prep_conv: conv
       
    11   val get_transfer_raw: Proof.context -> thm list
    10   val get_relator_eq: Proof.context -> thm list
    12   val get_relator_eq: Proof.context -> thm list
    11   val get_sym_relator_eq: Proof.context -> thm list
    13   val get_sym_relator_eq: Proof.context -> thm list
    12   val get_relator_eq_raw: Proof.context -> thm list
    14   val get_relator_eq_raw: Proof.context -> thm list
    13   val get_transfer_raw: Proof.context -> thm list
    15   val get_relator_domain: Proof.context -> thm list
    14   val transfer_add: attribute
    16   val transfer_add: attribute
    15   val transfer_del: attribute
    17   val transfer_del: attribute
       
    18   val transfer_domain_add: attribute
       
    19   val transfer_domain_del: attribute
    16   val transfer_rule_of_term: Proof.context -> term -> thm
    20   val transfer_rule_of_term: Proof.context -> term -> thm
    17   val transfer_tac: bool -> Proof.context -> int -> tactic
    21   val transfer_tac: bool -> Proof.context -> int -> tactic
    18   val transfer_prover_tac: Proof.context -> int -> tactic
    22   val transfer_prover_tac: Proof.context -> int -> tactic
    19   val setup: theory -> theory
    23   val setup: theory -> theory
    20 end
    24 end
    29   type T =
    33   type T =
    30     { transfer_raw : thm Item_Net.T,
    34     { transfer_raw : thm Item_Net.T,
    31       known_frees : (string * typ) list,
    35       known_frees : (string * typ) list,
    32       compound_rhs : unit Net.net,
    36       compound_rhs : unit Net.net,
    33       relator_eq : thm Item_Net.T,
    37       relator_eq : thm Item_Net.T,
    34       relator_eq_raw : thm Item_Net.T }
    38       relator_eq_raw : thm Item_Net.T,
       
    39       relator_domain : thm Item_Net.T }
    35   val empty =
    40   val empty =
    36     { transfer_raw = Thm.full_rules,
    41     { transfer_raw = Thm.full_rules,
    37       known_frees = [],
    42       known_frees = [],
    38       compound_rhs = Net.empty,
    43       compound_rhs = Net.empty,
    39       relator_eq = Thm.full_rules,
    44       relator_eq = Thm.full_rules,
    40       relator_eq_raw = Thm.full_rules }
    45       relator_eq_raw = Thm.full_rules,
       
    46       relator_domain = Thm.full_rules }
    41   val extend = I
    47   val extend = I
    42   fun merge
    48   fun merge
    43     ( { transfer_raw = t1, known_frees = k1,
    49     ( { transfer_raw = t1, known_frees = k1,
    44         compound_rhs = c1, relator_eq = r1,
    50         compound_rhs = c1, relator_eq = r1,
    45         relator_eq_raw = rw1 },
    51         relator_eq_raw = rw1, relator_domain = rd1 },
    46       { transfer_raw = t2, known_frees = k2,
    52       { transfer_raw = t2, known_frees = k2,
    47         compound_rhs = c2, relator_eq = r2,
    53         compound_rhs = c2, relator_eq = r2,
    48         relator_eq_raw = rw2 } ) =
    54         relator_eq_raw = rw2, relator_domain = rd2 } ) =
    49     { transfer_raw = Item_Net.merge (t1, t2),
    55     { transfer_raw = Item_Net.merge (t1, t2),
    50       known_frees = Library.merge (op =) (k1, k2),
    56       known_frees = Library.merge (op =) (k1, k2),
    51       compound_rhs = Net.merge (K true) (c1, c2),
    57       compound_rhs = Net.merge (K true) (c1, c2),
    52       relator_eq = Item_Net.merge (r1, r2),
    58       relator_eq = Item_Net.merge (r1, r2),
    53       relator_eq_raw = Item_Net.merge (rw1, rw2) }
    59       relator_eq_raw = Item_Net.merge (rw1, rw2),
       
    60       relator_domain = Item_Net.merge (rd1, rd2) }
    54 )
    61 )
       
    62 
       
    63 fun get_transfer_raw ctxt = ctxt
       
    64   |> (Item_Net.content o #transfer_raw o Data.get o Context.Proof)
       
    65 
       
    66 fun get_known_frees ctxt = ctxt
       
    67   |> (#known_frees o Data.get o Context.Proof)
       
    68 
       
    69 fun get_compound_rhs ctxt = ctxt
       
    70   |> (#compound_rhs o Data.get o Context.Proof)
    55 
    71 
    56 fun get_relator_eq ctxt = ctxt
    72 fun get_relator_eq ctxt = ctxt
    57   |> (Item_Net.content o #relator_eq o Data.get o Context.Proof)
    73   |> (Item_Net.content o #relator_eq o Data.get o Context.Proof)
    58   |> map safe_mk_meta_eq
    74   |> map safe_mk_meta_eq
    59 
    75 
    62   |> map (Thm.symmetric o safe_mk_meta_eq)
    78   |> map (Thm.symmetric o safe_mk_meta_eq)
    63 
    79 
    64 fun get_relator_eq_raw ctxt = ctxt
    80 fun get_relator_eq_raw ctxt = ctxt
    65   |> (Item_Net.content o #relator_eq_raw o Data.get o Context.Proof)
    81   |> (Item_Net.content o #relator_eq_raw o Data.get o Context.Proof)
    66 
    82 
    67 fun get_transfer_raw ctxt = ctxt
    83 fun get_relator_domain ctxt = ctxt
    68   |> (Item_Net.content o #transfer_raw o Data.get o Context.Proof)
    84   |> (Item_Net.content o #relator_domain o Data.get o Context.Proof)
    69 
    85 
    70 fun get_known_frees ctxt = ctxt
    86 fun map_data f1 f2 f3 f4 f5 f6
    71   |> (#known_frees o Data.get o Context.Proof)
    87   { transfer_raw, known_frees, compound_rhs, relator_eq, relator_eq_raw, relator_domain } =
    72 
       
    73 fun get_compound_rhs ctxt = ctxt
       
    74   |> (#compound_rhs o Data.get o Context.Proof)
       
    75 
       
    76 fun map_data f1 f2 f3 f4 f5
       
    77   { transfer_raw, known_frees, compound_rhs, relator_eq, relator_eq_raw } =
       
    78   { transfer_raw = f1 transfer_raw,
    88   { transfer_raw = f1 transfer_raw,
    79     known_frees = f2 known_frees,
    89     known_frees = f2 known_frees,
    80     compound_rhs = f3 compound_rhs,
    90     compound_rhs = f3 compound_rhs,
    81     relator_eq = f4 relator_eq,
    91     relator_eq = f4 relator_eq,
    82     relator_eq_raw = f5 relator_eq_raw }
    92     relator_eq_raw = f5 relator_eq_raw,
    83 
    93     relator_domain = f6 relator_domain }
    84 fun map_transfer_raw f = map_data f I I I I
    94 
    85 fun map_known_frees f = map_data I f I I I
    95 fun map_transfer_raw f = map_data f I I I I I
    86 fun map_compound_rhs f = map_data I I f I I
    96 fun map_known_frees f = map_data I f I I I I
    87 fun map_relator_eq f = map_data I I I f I
    97 fun map_compound_rhs f = map_data I I f I I I
    88 fun map_relator_eq_raw f = map_data I I I I f
    98 fun map_relator_eq f = map_data I I I f I I
       
    99 fun map_relator_eq_raw f = map_data I I I I f I
       
   100 fun map_relator_domain f = map_data I I I I I f
    89 
   101 
    90 fun add_transfer_thm thm = Data.map
   102 fun add_transfer_thm thm = Data.map
    91   (map_transfer_raw (Item_Net.update thm) o
   103   (map_transfer_raw (Item_Net.update thm) o
    92    map_compound_rhs
   104    map_compound_rhs
    93      (case HOLogic.dest_Trueprop (Thm.concl_of thm) of
   105      (case HOLogic.dest_Trueprop (Thm.concl_of thm) of
    94         _ $ _ $ (rhs as (_ $ _)) => Net.insert_term (K true) (rhs, ())
   106         (Const (@{const_name Rel}, _)) $ _ $ _ $ (rhs as (_ $ _)) => Net.insert_term (K true) (rhs, ())
    95       | _ => I) o
   107       | _ => I) o
    96    map_known_frees (Term.add_frees (Thm.concl_of thm)))
   108    map_known_frees (Term.add_frees (Thm.concl_of thm)))
    97 
   109 
    98 fun del_transfer_thm thm = Data.map (map_transfer_raw (Item_Net.remove thm))
   110 fun del_transfer_thm thm = Data.map (map_transfer_raw (Item_Net.remove thm))
    99 
   111 
   109   let val (cT, cT') = dest_funcT (Thm.ctyp_of_term ct)
   121   let val (cT, cT') = dest_funcT (Thm.ctyp_of_term ct)
   110       val (cU, _) = dest_funcT cT'
   122       val (cU, _) = dest_funcT cT'
   111   in Drule.instantiate' [SOME cT, SOME cU] [SOME ct] Rel_rule end
   123   in Drule.instantiate' [SOME cT, SOME cU] [SOME ct] Rel_rule end
   112 
   124 
   113 (* Conversion to preprocess a transfer rule *)
   125 (* Conversion to preprocess a transfer rule *)
   114 fun strip_args n = funpow n (fst o dest_comb)
       
   115 
       
   116 fun safe_Rel_conv ct =
   126 fun safe_Rel_conv ct =
   117   let
   127   Conv.try_conv (HOLogic.Trueprop_conv (Conv.fun_conv (Conv.fun_conv Rel_conv))) ct
   118     val head = ct |> term_of |> HOLogic.dest_Trueprop |> strip_args 2
       
   119     fun is_known (Const (s, _)) = (s = @{const_name DOM})
       
   120       | is_known _ = false
       
   121   in
       
   122     if not (is_known head)
       
   123       then HOLogic.Trueprop_conv (Conv.fun_conv (Conv.fun_conv Rel_conv)) ct
       
   124     else Conv.all_conv ct
       
   125   end
       
   126   handle TERM _ => Conv.all_conv ct
       
   127 ;
       
   128 
   128 
   129 fun prep_conv ct = (
   129 fun prep_conv ct = (
   130       Conv.implies_conv safe_Rel_conv prep_conv
   130       Conv.implies_conv safe_Rel_conv prep_conv
   131       else_conv
   131       else_conv
   132       safe_Rel_conv
   132       safe_Rel_conv
   183 
   183 
   184 fun abstract_equalities_relator_eq rel_eq_thm =
   184 fun abstract_equalities_relator_eq rel_eq_thm =
   185   gen_abstract_equalities (fn x => (x, I))
   185   gen_abstract_equalities (fn x => (x, I))
   186     (rel_eq_thm RS @{thm is_equality_def [THEN iffD2]})
   186     (rel_eq_thm RS @{thm is_equality_def [THEN iffD2]})
   187 
   187 
       
   188 fun abstract_equalities_domain thm =
       
   189   let
       
   190     fun dest prop =
       
   191       let
       
   192         val prems = Logic.strip_imp_prems prop
       
   193         val concl = HOLogic.dest_Trueprop (Logic.strip_imp_concl prop)
       
   194         val ((dom, x), y) = apfst Term.dest_comb (Term.dest_comb concl)
       
   195       in
       
   196         (x $ y, fn comb' =>
       
   197           let 
       
   198             val (x', y') = dest_comb comb'
       
   199           in
       
   200             Logic.list_implies (prems, HOLogic.mk_Trueprop (dom $ x' $ y'))
       
   201           end)
       
   202       end
       
   203   in
       
   204     gen_abstract_equalities dest thm
       
   205   end 
       
   206 
       
   207 
       
   208 (** Replacing explicit Domainp predicates with Domainp assumptions **)
       
   209 
       
   210 fun mk_Domainp_assm (T, R) =
       
   211   HOLogic.mk_eq ((Const (@{const_name Domainp}, Term.fastype_of T --> Term.fastype_of R) $ T), R)
       
   212 
       
   213 val Domainp_lemma =
       
   214   @{lemma "(!!R. Domainp T = R ==> PROP (P R)) == PROP (P (Domainp T))"
       
   215     by (rule, drule meta_spec,
       
   216       erule meta_mp, rule refl, simp)}
       
   217 
       
   218 fun fold_Domainp f (t as Const (@{const_name Domainp},_) $ (Var (_,_))) = f t
       
   219   | fold_Domainp f (t $ u) = fold_Domainp f t #> fold_Domainp f u
       
   220   | fold_Domainp f (Abs (_, _, t)) = fold_Domainp f t
       
   221   | fold_Domainp _ _ = I
       
   222 
       
   223 fun subst_terms tab t = 
       
   224   let
       
   225     val t' = Termtab.lookup tab t
       
   226   in
       
   227     case t' of
       
   228       SOME t' => t'
       
   229       | NONE => 
       
   230         (case t of
       
   231           u $ v => (subst_terms tab u) $ (subst_terms tab v)
       
   232           | Abs (a, T, t) => Abs (a, T, subst_terms tab t)
       
   233           | t => t)
       
   234   end
       
   235 
       
   236 fun gen_abstract_domains (dest : term -> term * (term -> term)) thm =
       
   237   let
       
   238     val thy = Thm.theory_of_thm thm
       
   239     val prop = Thm.prop_of thm
       
   240     val (t, mk_prop') = dest prop
       
   241     val Domainp_tms = rev (fold_Domainp (fn t => insert op= t) t [])
       
   242     val Domainp_Ts = map (snd o dest_funT o snd o dest_Const o fst o dest_comb) Domainp_tms
       
   243     val used = Term.add_free_names t []
       
   244     val rels = map (snd o dest_comb) Domainp_tms
       
   245     val rel_names = map (fst o fst o dest_Var) rels
       
   246     val names = map (fn name => ("D" ^ name)) rel_names |> Name.variant_list used
       
   247     val frees = map Free (names ~~ Domainp_Ts)
       
   248     val prems = map (HOLogic.mk_Trueprop o mk_Domainp_assm) (rels ~~ frees);
       
   249     val t' = subst_terms (fold Termtab.update (Domainp_tms ~~ frees) Termtab.empty) t
       
   250     val prop1 = fold Logic.all frees (Logic.list_implies (prems, mk_prop' t'))
       
   251     val prop2 = Logic.list_rename_params (rev names) prop1
       
   252     val cprop = Thm.cterm_of thy prop2
       
   253     val equal_thm = Raw_Simplifier.rewrite false [Domainp_lemma] cprop
       
   254     fun forall_elim thm = Thm.forall_elim_vars (Thm.maxidx_of thm + 1) thm;
       
   255   in
       
   256     forall_elim (thm COMP (equal_thm COMP @{thm equal_elim_rule2}))
       
   257   end
       
   258     handle TERM _ => thm
       
   259 
       
   260 fun abstract_domains_transfer thm =
       
   261   let
       
   262     fun dest prop =
       
   263       let
       
   264         val prems = Logic.strip_imp_prems prop
       
   265         val concl = HOLogic.dest_Trueprop (Logic.strip_imp_concl prop)
       
   266         val ((rel, x), y) = apfst Term.dest_comb (Term.dest_comb concl)
       
   267       in
       
   268         (x, fn x' =>
       
   269           Logic.list_implies (prems, HOLogic.mk_Trueprop (rel $ x' $ y)))
       
   270       end
       
   271   in
       
   272     gen_abstract_domains dest thm
       
   273   end
       
   274 
       
   275 fun detect_transfer_rules thm =
       
   276   let
       
   277     fun is_transfer_rule tm = case (HOLogic.dest_Trueprop tm) of
       
   278       (Const (@{const_name HOL.eq}, _)) $ ((Const (@{const_name Domainp}, _)) $ _) $ _ => false
       
   279       | _ $ _ $ _ => true
       
   280       | _ => false
       
   281     fun safe_transfer_rule_conv ctm =
       
   282       if is_transfer_rule (term_of ctm) then safe_Rel_conv ctm else Conv.all_conv ctm
       
   283   in
       
   284     Conv.fconv_rule (Conv.prems_conv ~1 safe_transfer_rule_conv) thm
       
   285   end
       
   286 
       
   287 (** Adding transfer domain rules **)
       
   288 
       
   289 fun add_transfer_domain_thm thm = 
       
   290   (add_transfer_thm o abstract_equalities_domain o detect_transfer_rules) thm
       
   291 
       
   292 fun del_transfer_domain_thm thm = 
       
   293   (del_transfer_thm o abstract_equalities_domain o detect_transfer_rules) thm
   188 
   294 
   189 (** Transfer proof method **)
   295 (** Transfer proof method **)
   190 
   296 
   191 val post_simps =
   297 val post_simps =
   192   @{thms transfer_forall_eq [symmetric]
   298   @{thms transfer_forall_eq [symmetric]
   361 val transfer_prover_method : (Proof.context -> Method.method) context_parser =
   467 val transfer_prover_method : (Proof.context -> Method.method) context_parser =
   362   Scan.succeed (fn ctxt => SIMPLE_METHOD' (transfer_prover_tac ctxt))
   468   Scan.succeed (fn ctxt => SIMPLE_METHOD' (transfer_prover_tac ctxt))
   363 
   469 
   364 (* Attribute for transfer rules *)
   470 (* Attribute for transfer rules *)
   365 
   471 
   366 val prep_rule = abstract_equalities_transfer o Conv.fconv_rule prep_conv
   472 val prep_rule = abstract_domains_transfer o abstract_equalities_transfer o Conv.fconv_rule prep_conv
   367 
   473 
   368 val transfer_add =
   474 val transfer_add =
   369   Thm.declaration_attribute (add_transfer_thm o prep_rule)
   475   Thm.declaration_attribute (add_transfer_thm o prep_rule)
   370 
   476 
   371 val transfer_del =
   477 val transfer_del =
   372   Thm.declaration_attribute (del_transfer_thm o prep_rule)
   478   Thm.declaration_attribute (del_transfer_thm o prep_rule)
   373 
   479 
   374 val transfer_attribute =
   480 val transfer_attribute =
   375   Attrib.add_del transfer_add transfer_del
   481   Attrib.add_del transfer_add transfer_del
       
   482 
       
   483 (* Attributes for transfer domain rules *)
       
   484 
       
   485 val transfer_domain_add = Thm.declaration_attribute add_transfer_domain_thm
       
   486 
       
   487 val transfer_domain_del = Thm.declaration_attribute del_transfer_domain_thm
       
   488 
       
   489 val transfer_domain_attribute =
       
   490   Attrib.add_del transfer_domain_add transfer_domain_del
   376 
   491 
   377 (* Theory setup *)
   492 (* Theory setup *)
   378 
   493 
   379 val relator_eq_setup =
   494 val relator_eq_setup =
   380   let
   495   let
   390   in
   505   in
   391     Attrib.setup name (Attrib.add_del add del) text
   506     Attrib.setup name (Attrib.add_del add del) text
   392     #> Global_Theory.add_thms_dynamic (name, content)
   507     #> Global_Theory.add_thms_dynamic (name, content)
   393   end
   508   end
   394 
   509 
       
   510 val relator_domain_setup =
       
   511   let
       
   512     val name = @{binding relator_domain}
       
   513     fun add_thm thm = Data.map (map_relator_domain (Item_Net.update thm))
       
   514       #> add_transfer_domain_thm thm
       
   515     fun del_thm thm = Data.map (map_relator_domain (Item_Net.remove thm))
       
   516       #> del_transfer_domain_thm thm
       
   517     val add = Thm.declaration_attribute add_thm
       
   518     val del = Thm.declaration_attribute del_thm
       
   519     val text = "declaration of relator domain rule (used by transfer method)"
       
   520     val content = Item_Net.content o #relator_domain o Data.get
       
   521   in
       
   522     Attrib.setup name (Attrib.add_del add del) text
       
   523     #> Global_Theory.add_thms_dynamic (name, content)
       
   524   end
       
   525 
       
   526 
   395 val setup =
   527 val setup =
   396   relator_eq_setup
   528   relator_eq_setup
       
   529   #> relator_domain_setup
   397   #> Attrib.setup @{binding transfer_rule} transfer_attribute
   530   #> Attrib.setup @{binding transfer_rule} transfer_attribute
   398      "transfer rule for transfer method"
   531      "transfer rule for transfer method"
   399   #> Global_Theory.add_thms_dynamic
   532   #> Global_Theory.add_thms_dynamic
   400      (@{binding transfer_raw}, Item_Net.content o #transfer_raw o Data.get)
   533      (@{binding transfer_raw}, Item_Net.content o #transfer_raw o Data.get)
       
   534   #> Attrib.setup @{binding transfer_domain_rule} transfer_domain_attribute
       
   535      "transfer domain rule for transfer method"
   401   #> Global_Theory.add_thms_dynamic
   536   #> Global_Theory.add_thms_dynamic
   402      (@{binding relator_eq_raw}, Item_Net.content o #relator_eq_raw o Data.get)
   537      (@{binding relator_eq_raw}, Item_Net.content o #relator_eq_raw o Data.get)
   403   #> Method.setup @{binding transfer} (transfer_method true)
   538   #> Method.setup @{binding transfer} (transfer_method true)
   404      "generic theorem transfer method"
   539      "generic theorem transfer method"
   405   #> Method.setup @{binding transfer'} (transfer_method false)
   540   #> Method.setup @{binding transfer'} (transfer_method false)