src/HOL/Decision_Procs/approximation.ML
changeset 59850 f339ff48a6ee
parent 59621 291934bac95e
child 59936 b8ffc3dc9e24
equal deleted inserted replaced
59849:c3d126c7944f 59850:f339ff48a6ee
     3 *)
     3 *)
     4 
     4 
     5 signature APPROXIMATION =
     5 signature APPROXIMATION =
     6 sig
     6 sig
     7   val approx: int -> Proof.context -> term -> term
     7   val approx: int -> Proof.context -> term -> term
       
     8   val approximate: Proof.context -> term -> term
       
     9   val approximation_tac : int -> (string * int) list -> int option -> Proof.context -> int -> tactic
     8 end
    10 end
     9 
    11 
    10 structure Approximation: APPROXIMATION =
    12 structure Approximation: APPROXIMATION =
    11 struct
    13 struct
       
    14 
       
    15 fun reorder_bounds_tac prems i =
       
    16   let
       
    17     fun variable_of_bound (Const (@{const_name Trueprop}, _) $
       
    18                            (Const (@{const_name Set.member}, _) $
       
    19                             Free (name, _) $ _)) = name
       
    20       | variable_of_bound (Const (@{const_name Trueprop}, _) $
       
    21                            (Const (@{const_name HOL.eq}, _) $
       
    22                             Free (name, _) $ _)) = name
       
    23       | variable_of_bound t = raise TERM ("variable_of_bound", [t])
       
    24 
       
    25     val variable_bounds
       
    26       = map (`(variable_of_bound o Thm.prop_of)) prems
       
    27 
       
    28     fun add_deps (name, bnds)
       
    29       = Graph.add_deps_acyclic (name,
       
    30           remove (op =) name (Term.add_free_names (Thm.prop_of bnds) []))
       
    31 
       
    32     val order = Graph.empty
       
    33                 |> fold Graph.new_node variable_bounds
       
    34                 |> fold add_deps variable_bounds
       
    35                 |> Graph.strong_conn |> map the_single |> rev
       
    36                 |> map_filter (AList.lookup (op =) variable_bounds)
       
    37 
       
    38     fun prepend_prem th tac
       
    39       = tac THEN rtac (th RSN (2, @{thm mp})) i
       
    40   in
       
    41     fold prepend_prem order all_tac
       
    42   end
       
    43 
       
    44 fun approximation_conv ctxt ct =
       
    45   approximation_oracle (Proof_Context.theory_of ctxt, Thm.term_of ct |> tap (tracing o Syntax.string_of_term ctxt));
       
    46 
       
    47 fun approximate ctxt t =
       
    48   approximation_oracle (Proof_Context.theory_of ctxt, t)
       
    49   |> Thm.prop_of |> Logic.dest_equals |> snd;
       
    50 
       
    51 (* Should be in HOL.thy ? *)
       
    52 fun gen_eval_tac conv ctxt = CONVERSION
       
    53   (Object_Logic.judgment_conv (Conv.params_conv (~1) (K (Conv.concl_conv (~1) conv)) ctxt))
       
    54   THEN' rtac TrueI
       
    55 
       
    56 val form_equations = @{thms interpret_form_equations};
       
    57 
       
    58 fun rewrite_interpret_form_tac ctxt prec splitting taylor i st = let
       
    59     fun lookup_splitting (Free (name, _))
       
    60       = case AList.lookup (op =) splitting name
       
    61         of SOME s => HOLogic.mk_number @{typ nat} s
       
    62          | NONE => @{term "0 :: nat"}
       
    63     val vs = nth (Thm.prems_of st) (i - 1)
       
    64              |> Logic.strip_imp_concl
       
    65              |> HOLogic.dest_Trueprop
       
    66              |> Term.strip_comb |> snd |> List.last
       
    67              |> HOLogic.dest_list
       
    68     val p = prec
       
    69             |> HOLogic.mk_number @{typ nat}
       
    70             |> Thm.cterm_of ctxt
       
    71   in case taylor
       
    72   of NONE => let
       
    73        val n = vs |> length
       
    74                |> HOLogic.mk_number @{typ nat}
       
    75                |> Thm.cterm_of ctxt
       
    76        val s = vs
       
    77                |> map lookup_splitting
       
    78                |> HOLogic.mk_list @{typ nat}
       
    79                |> Thm.cterm_of ctxt
       
    80      in
       
    81        (rtac (Thm.instantiate ([], [(@{cpat "?n::nat"}, n),
       
    82                                    (@{cpat "?prec::nat"}, p),
       
    83                                    (@{cpat "?ss::nat list"}, s)])
       
    84             @{thm "approx_form"}) i
       
    85         THEN simp_tac (put_simpset (simpset_of @{context}) ctxt) i) st
       
    86      end
       
    87 
       
    88    | SOME t =>
       
    89      if length vs <> 1
       
    90      then raise (TERM ("More than one variable used for taylor series expansion", [Thm.prop_of st]))
       
    91      else let
       
    92        val t = t
       
    93             |> HOLogic.mk_number @{typ nat}
       
    94             |> Thm.cterm_of ctxt
       
    95        val s = vs |> map lookup_splitting |> hd
       
    96             |> Thm.cterm_of ctxt
       
    97      in
       
    98        rtac (Thm.instantiate ([], [(@{cpat "?s::nat"}, s),
       
    99                                    (@{cpat "?t::nat"}, t),
       
   100                                    (@{cpat "?prec::nat"}, p)])
       
   101             @{thm "approx_tse_form"}) i st
       
   102      end
       
   103   end
    12 
   104 
    13 fun calculated_subterms (@{const Trueprop} $ t) = calculated_subterms t
   105 fun calculated_subterms (@{const Trueprop} $ t) = calculated_subterms t
    14   | calculated_subterms (@{const HOL.implies} $ _ $ t) = calculated_subterms t
   106   | calculated_subterms (@{const HOL.implies} $ _ $ t) = calculated_subterms t
    15   | calculated_subterms (@{term "op <= :: real \<Rightarrow> real \<Rightarrow> bool"} $ t1 $ t2) = [t1, t2]
   107   | calculated_subterms (@{term "op <= :: real \<Rightarrow> real \<Rightarrow> bool"} $ t1 $ t2) = [t1, t2]
    16   | calculated_subterms (@{term "op < :: real \<Rightarrow> real \<Rightarrow> bool"} $ t1 $ t2) = [t1, t2]
   108   | calculated_subterms (@{term "op < :: real \<Rightarrow> real \<Rightarrow> bool"} $ t1 $ t2) = [t1, t2]
   154 val _ =
   246 val _ =
   155   Outer_Syntax.command @{command_spec "approximate"} "print approximation of term"
   247   Outer_Syntax.command @{command_spec "approximate"} "print approximation of term"
   156     (opt_modes -- Parse.term
   248     (opt_modes -- Parse.term
   157       >> (fn (modes, t) => Toplevel.keep (approximate_cmd modes t)));
   249       >> (fn (modes, t) => Toplevel.keep (approximate_cmd modes t)));
   158 
   250 
       
   251 fun approximation_tac prec splitting taylor ctxt i =
       
   252   REPEAT (FIRST' [etac @{thm intervalE},
       
   253                   etac @{thm meta_eqE},
       
   254                   rtac @{thm impI}] i)
       
   255   THEN Subgoal.FOCUS (fn {prems, ...} => reorder_bounds_tac prems i) ctxt i
       
   256   THEN DETERM (TRY (filter_prems_tac ctxt (K false) i))
       
   257   THEN DETERM (Reification.tac ctxt form_equations NONE i)
       
   258   THEN rewrite_interpret_form_tac ctxt prec splitting taylor i
       
   259   THEN gen_eval_tac (approximation_conv ctxt) ctxt i
       
   260     
   159 end;
   261 end;