src/HOL/Decision_Procs/approximation.ML
changeset 74397 e80c4cde6064
parent 74290 b2ad24b5a42c
child 74609 3ef6e38c9847
equal deleted inserted replaced
74396:dc73f9e6476b 74397:e80c4cde6064
    13 structure Approximation =
    13 structure Approximation =
    14 struct
    14 struct
    15 
    15 
    16 fun reorder_bounds_tac ctxt prems i =
    16 fun reorder_bounds_tac ctxt prems i =
    17   let
    17   let
    18     fun variable_of_bound (Const (\<^const_name>\<open>Trueprop\<close>, _) $
    18     fun variable_of_bound \<^Const_>\<open>Trueprop for \<^Const_>\<open>Set.member _ for \<open>Free (name, _)\<close> _\<close>\<close> = name
    19                            (Const (\<^const_name>\<open>Set.member\<close>, _) $
    19       | variable_of_bound \<^Const_>\<open>Trueprop for \<^Const_>\<open>HOL.eq _ for \<open>Free (name, _)\<close> _\<close>\<close> = name
    20                             Free (name, _) $ _)) = name
       
    21       | variable_of_bound (Const (\<^const_name>\<open>Trueprop\<close>, _) $
       
    22                            (Const (\<^const_name>\<open>HOL.eq\<close>, _) $
       
    23                             Free (name, _) $ _)) = name
       
    24       | variable_of_bound t = raise TERM ("variable_of_bound", [t])
    20       | variable_of_bound t = raise TERM ("variable_of_bound", [t])
    25 
    21 
    26     val variable_bounds
    22     val variable_bounds
    27       = map (`(variable_of_bound o Thm.prop_of)) prems
    23       = map (`(variable_of_bound o Thm.prop_of)) prems
    28 
    24 
    41   in
    37   in
    42     fold prepend_prem order all_tac
    38     fold prepend_prem order all_tac
    43   end
    39   end
    44 
    40 
    45 fun approximate ctxt t = case fastype_of t
    41 fun approximate ctxt t = case fastype_of t
    46    of \<^typ>\<open>bool\<close> =>
    42    of \<^Type>\<open>bool\<close> =>
    47         Approximation_Computation.approx_bool ctxt t
    43         Approximation_Computation.approx_bool ctxt t
    48     | \<^typ>\<open>(float interval) option\<close> =>
    44     | \<^typ>\<open>float interval option\<close> =>
    49         Approximation_Computation.approx_arith ctxt t
    45         Approximation_Computation.approx_arith ctxt t
    50     | \<^typ>\<open>(float interval) option list\<close> =>
    46     | \<^typ>\<open>float interval option list\<close> =>
    51         Approximation_Computation.approx_form_eval ctxt t
    47         Approximation_Computation.approx_form_eval ctxt t
    52     | _ => error ("Bad term: " ^ Syntax.string_of_term ctxt t);
    48     | _ => error ("Bad term: " ^ Syntax.string_of_term ctxt t);
    53 
    49 
    54 fun rewrite_interpret_form_tac ctxt prec splitting taylor i st = let
    50 fun rewrite_interpret_form_tac ctxt prec splitting taylor i st = let
    55     fun lookup_splitting (Free (name, _)) =
    51     fun lookup_splitting (Free (name, _)) =
    56         (case AList.lookup (op =) splitting name
    52         (case AList.lookup (op =) splitting name
    57           of SOME s => HOLogic.mk_number \<^typ>\<open>nat\<close> s
    53           of SOME s => HOLogic.mk_number \<^Type>\<open>nat\<close> s
    58            | NONE => \<^term>\<open>0 :: nat\<close>)
    54            | NONE => \<^term>\<open>0 :: nat\<close>)
    59       | lookup_splitting t = raise TERM ("lookup_splitting", [t])
    55       | lookup_splitting t = raise TERM ("lookup_splitting", [t])
    60     val vs = nth (Thm.prems_of st) (i - 1)
    56     val vs = nth (Thm.prems_of st) (i - 1)
    61              |> Logic.strip_imp_concl
    57              |> Logic.strip_imp_concl
    62              |> HOLogic.dest_Trueprop
    58              |> HOLogic.dest_Trueprop
    63              |> Term.strip_comb |> snd |> List.last
    59              |> Term.strip_comb |> snd |> List.last
    64              |> HOLogic.dest_list
    60              |> HOLogic.dest_list
    65     val p = prec
    61     val p = prec
    66             |> HOLogic.mk_number \<^typ>\<open>nat\<close>
    62             |> HOLogic.mk_number \<^Type>\<open>nat\<close>
    67             |> Thm.cterm_of ctxt
    63             |> Thm.cterm_of ctxt
    68   in case taylor
    64   in case taylor
    69   of NONE => let
    65   of NONE => let
    70        val n = vs |> length
    66        val n = vs |> length
    71                |> HOLogic.mk_number \<^typ>\<open>nat\<close>
    67                |> HOLogic.mk_number \<^Type>\<open>nat\<close>
    72                |> Thm.cterm_of ctxt
    68                |> Thm.cterm_of ctxt
    73        val s = vs
    69        val s = vs
    74                |> map lookup_splitting
    70                |> map lookup_splitting
    75                |> HOLogic.mk_list \<^typ>\<open>nat\<close>
    71                |> HOLogic.mk_list \<^Type>\<open>nat\<close>
    76                |> Thm.cterm_of ctxt
    72                |> Thm.cterm_of ctxt
    77      in
    73      in
    78        (resolve_tac ctxt [Thm.instantiate (TVars.empty,
    74        (resolve_tac ctxt [Thm.instantiate (TVars.empty,
    79            Vars.make [(\<^var>\<open>?n::nat\<close>, n), (\<^var>\<open>?prec::nat\<close>, p), (\<^var>\<open>?ss::nat list\<close>, s)])
    75            Vars.make [(\<^var>\<open>?n::nat\<close>, n), (\<^var>\<open>?prec::nat\<close>, p), (\<^var>\<open>?ss::nat list\<close>, s)])
    80             @{thm approx_form}] i
    76             @{thm approx_form}] i
    84    | SOME t =>
    80    | SOME t =>
    85      if length vs <> 1
    81      if length vs <> 1
    86      then raise (TERM ("More than one variable used for taylor series expansion", [Thm.prop_of st]))
    82      then raise (TERM ("More than one variable used for taylor series expansion", [Thm.prop_of st]))
    87      else let
    83      else let
    88        val t = t
    84        val t = t
    89             |> HOLogic.mk_number \<^typ>\<open>nat\<close>
    85             |> HOLogic.mk_number \<^Type>\<open>nat\<close>
    90             |> Thm.cterm_of ctxt
    86             |> Thm.cterm_of ctxt
    91        val s = vs |> map lookup_splitting |> hd
    87        val s = vs |> map lookup_splitting |> hd
    92             |> Thm.cterm_of ctxt
    88             |> Thm.cterm_of ctxt
    93      in
    89      in
    94        resolve_tac ctxt [Thm.instantiate (TVars.empty,
    90        resolve_tac ctxt [Thm.instantiate (TVars.empty,
    95             Vars.make [(\<^var>\<open>?s::nat\<close>, s), (\<^var>\<open>?t::nat\<close>, t), (\<^var>\<open>?prec::nat\<close>, p)])
    91             Vars.make [(\<^var>\<open>?s::nat\<close>, s), (\<^var>\<open>?t::nat\<close>, t), (\<^var>\<open>?prec::nat\<close>, p)])
    96             @{thm approx_tse_form}] i st
    92             @{thm approx_tse_form}] i st
    97      end
    93      end
    98   end
    94   end
    99 
    95 
   100 fun calculated_subterms (\<^const>\<open>Trueprop\<close> $ t) = calculated_subterms t
    96 fun calculated_subterms \<^Const_>\<open>Trueprop for t\<close> = calculated_subterms t
   101   | calculated_subterms (\<^const>\<open>HOL.implies\<close> $ _ $ t) = calculated_subterms t
    97   | calculated_subterms \<^Const_>\<open>implies for _ t\<close> = calculated_subterms t
   102   | calculated_subterms (\<^term>\<open>(\<le>) :: real \<Rightarrow> real \<Rightarrow> bool\<close> $ t1 $ t2) = [t1, t2]
    98   | calculated_subterms \<^Const_>\<open>less_eq \<^Type>\<open>real\<close> for t1 t2\<close> = [t1, t2]
   103   | calculated_subterms (\<^term>\<open>(<) :: real \<Rightarrow> real \<Rightarrow> bool\<close> $ t1 $ t2) = [t1, t2]
    99   | calculated_subterms \<^Const_>\<open>less \<^Type>\<open>real\<close> for t1 t2\<close> = [t1, t2]
   104   | calculated_subterms (\<^term>\<open>(\<in>) :: real \<Rightarrow> real set \<Rightarrow> bool\<close> $ t1 $
   100   | calculated_subterms \<^Const_>\<open>Set.member \<^Type>\<open>real\<close> for
   105                          (\<^term>\<open>atLeastAtMost :: real \<Rightarrow> real \<Rightarrow> real set\<close> $ t2 $ t3)) = [t1, t2, t3]
   101       t1 \<^Const_>\<open>atLeastAtMost \<^Type>\<open>real\<close> for t2 t3\<close>\<close> = [t1, t2, t3]
   106   | calculated_subterms t = raise TERM ("calculated_subterms", [t])
   102   | calculated_subterms t = raise TERM ("calculated_subterms", [t])
   107 
   103 
   108 fun dest_interpret_form (\<^const>\<open>interpret_form\<close> $ b $ xs) = (b, xs)
   104 fun dest_interpret_form \<^Const_>\<open>interpret_form for b xs\<close> = (b, xs)
   109   | dest_interpret_form t = raise TERM ("dest_interpret_form", [t])
   105   | dest_interpret_form t = raise TERM ("dest_interpret_form", [t])
   110 
   106 
   111 fun dest_interpret (\<^const>\<open>interpret_floatarith\<close> $ b $ xs) = (b, xs)
   107 fun dest_interpret \<^Const_>\<open>interpret_floatarith for b xs\<close> = (b, xs)
   112   | dest_interpret t = raise TERM ("dest_interpret", [t])
   108   | dest_interpret t = raise TERM ("dest_interpret", [t])
   113 
   109 
   114 fun dest_interpret_env (\<^const>\<open>interpret_form\<close> $ _ $ xs) = xs
   110 fun dest_interpret_env \<^Const_>\<open>interpret_form for _ xs\<close> = xs
   115   | dest_interpret_env (\<^const>\<open>interpret_floatarith\<close> $ _ $ xs) = xs
   111   | dest_interpret_env \<^Const_>\<open>interpret_floatarith for _ xs\<close> = xs
   116   | dest_interpret_env t = raise TERM ("dest_interpret_env", [t])
   112   | dest_interpret_env t = raise TERM ("dest_interpret_env", [t])
   117 
   113 
   118 fun dest_float (\<^const>\<open>Float\<close> $ m $ e) = (snd (HOLogic.dest_number m), snd (HOLogic.dest_number e))
   114 fun dest_float \<^Const_>\<open>Float for m e\<close> = (snd (HOLogic.dest_number m), snd (HOLogic.dest_number e))
   119   | dest_float t = raise TERM ("dest_float", [t])
   115   | dest_float t = raise TERM ("dest_float", [t])
   120 
   116 
   121 
   117 
   122 fun dest_ivl
   118 fun dest_ivl \<^Const_>\<open>Some _ for \<^Const_>\<open>Interval _ for \<^Const_>\<open>Pair _ _ for u l\<close>\<close>\<close> =
   123   (Const (\<^const_name>\<open>Some\<close>, _) $
       
   124     (Const (\<^const_name>\<open>Interval\<close>, _) $ ((Const (\<^const_name>\<open>Pair\<close>, _) $ u $ l)))) =
       
   125       SOME (dest_float u, dest_float l)
   119       SOME (dest_float u, dest_float l)
   126   | dest_ivl (Const (\<^const_name>\<open>None\<close>, _)) = NONE
   120   | dest_ivl \<^Const_>\<open>None _\<close> = NONE
   127   | dest_ivl t = raise TERM ("dest_result", [t])
   121   | dest_ivl t = raise TERM ("dest_result", [t])
   128 
   122 
   129 fun mk_approx' prec t = (\<^const>\<open>approx'\<close>
   123 fun mk_approx' prec t =
   130                        $ HOLogic.mk_number \<^typ>\<open>nat\<close> prec
   124   \<^Const>\<open>approx' for \<open>HOLogic.mk_number \<^Type>\<open>nat\<close> prec\<close> t \<^Const>\<open>Nil \<^typ>\<open>float interval option\<close>\<close>\<close>
   131                        $ t $ \<^term>\<open>[] :: (float interval) option list\<close>)
   125 
   132 
   126 fun mk_approx_form_eval prec t xs =
   133 fun mk_approx_form_eval prec t xs = (\<^const>\<open>approx_form_eval\<close>
   127   \<^Const>\<open>approx_form_eval for \<open>HOLogic.mk_number \<^Type>\<open>nat\<close> prec\<close> t xs\<close>
   134                        $ HOLogic.mk_number \<^typ>\<open>nat\<close> prec
       
   135                        $ t $ xs)
       
   136 
   128 
   137 fun float2_float10 prec round_down (m, e) = (
   129 fun float2_float10 prec round_down (m, e) = (
   138   let
   130   let
   139     val (m, e) = (if e < 0 then (m,e) else (m * Integer.pow e 2, 0))
   131     val (m, e) = (if e < 0 then (m,e) else (m * Integer.pow e 2, 0))
   140 
   132 
   164   end)
   156   end)
   165 
   157 
   166 fun mk_result prec (SOME (l, u)) =
   158 fun mk_result prec (SOME (l, u)) =
   167   (let
   159   (let
   168     fun mk_float10 rnd x = (let val (m, e) = float2_float10 prec rnd x
   160     fun mk_float10 rnd x = (let val (m, e) = float2_float10 prec rnd x
   169                        in if e = 0 then HOLogic.mk_number \<^typ>\<open>real\<close> m
   161                        in if e = 0 then HOLogic.mk_number \<^Type>\<open>real\<close> m
   170                      else if e = 1 then \<^term>\<open>divide :: real \<Rightarrow> real \<Rightarrow> real\<close> $
   162                      else if e = 1 then \<^Const>\<open>divide \<^Type>\<open>real\<close>\<close> $
   171                                         HOLogic.mk_number \<^typ>\<open>real\<close> m $
   163                                         HOLogic.mk_number \<^Type>\<open>real\<close> m $
   172                                         \<^term>\<open>10\<close>
   164                                         \<^term>\<open>10\<close>
   173                                    else \<^term>\<open>divide :: real \<Rightarrow> real \<Rightarrow> real\<close> $
   165                                    else \<^Const>\<open>divide \<^Type>\<open>real\<close>\<close> $
   174                                         HOLogic.mk_number \<^typ>\<open>real\<close> m $
   166                                         HOLogic.mk_number \<^Type>\<open>real\<close> m $
   175                                         (\<^term>\<open>power 10 :: nat \<Rightarrow> real\<close> $
   167                                         (\<^term>\<open>power 10 :: nat \<Rightarrow> real\<close> $
   176                                          HOLogic.mk_number \<^typ>\<open>nat\<close> (~e)) end)
   168                                          HOLogic.mk_number \<^Type>\<open>nat\<close> (~e)) end)
   177     in \<^term>\<open>atLeastAtMost :: real \<Rightarrow> real \<Rightarrow> real set\<close> $ mk_float10 true l $ mk_float10 false u end)
   169     in \<^Const>\<open>atLeastAtMost \<^Type>\<open>real\<close> for \<open>mk_float10 true l\<close> \<open>mk_float10 false u\<close>\<close> end)
   178   | mk_result _ NONE = \<^term>\<open>UNIV :: real set\<close>
   170   | mk_result _ NONE = \<^term>\<open>UNIV :: real set\<close>
   179 
   171 
   180 fun realify t =
   172 fun realify t =
   181   let
   173   let
   182     val t = Logic.varify_global t
   174     val t = Logic.varify_global t
   183     val m = map (fn (name, _) => (name, \<^typ>\<open>real\<close>)) (Term.add_tvars t [])
   175     val m = map (fn (name, _) => (name, \<^Type>\<open>real\<close>)) (Term.add_tvars t [])
   184     val t = Term.subst_TVars m t
   176     val t = Term.subst_TVars m t
   185   in t end
   177   in t end
   186 
   178 
   187 fun apply_tactic ctxt term tactic =
   179 fun apply_tactic ctxt term tactic =
   188   Thm.cterm_of ctxt term
   180   Thm.cterm_of ctxt term
   235      |> prepare_form ctxt
   227      |> prepare_form ctxt
   236      |> (fn arith_term => apply_reify_form ctxt arith_term
   228      |> (fn arith_term => apply_reify_form ctxt arith_term
   237          |> HOLogic.dest_Trueprop
   229          |> HOLogic.dest_Trueprop
   238          |> dest_interpret_form
   230          |> dest_interpret_form
   239          |> (fn (data, xs) =>
   231          |> (fn (data, xs) =>
   240             mk_approx_form_eval prec data (HOLogic.mk_list \<^typ>\<open>(float interval) option\<close>
   232             mk_approx_form_eval prec data (HOLogic.mk_list \<^typ>\<open>float interval option\<close>
   241               (map (fn _ => \<^term>\<open>None :: (float interval) option\<close>) (HOLogic.dest_list xs)))
   233               (map (fn _ => \<^Const>\<open>None \<^typ>\<open>float interval option\<close>\<close>) (HOLogic.dest_list xs)))
   242          |> approximate ctxt
   234          |> approximate ctxt
   243          |> HOLogic.dest_list
   235          |> HOLogic.dest_list
   244          |> curry ListPair.zip (HOLogic.dest_list xs @ calculated_subterms arith_term)
   236          |> curry ListPair.zip (HOLogic.dest_list xs @ calculated_subterms arith_term)
   245          |> map (fn (elem, s) => \<^term>\<open>(\<in>) :: real \<Rightarrow> real set \<Rightarrow> bool\<close> $ elem $ mk_result prec (dest_ivl s))
   237          |> map (fn (elem, s) => \<^Const>\<open>Set.member \<^Type>\<open>real\<close> for elem \<open>mk_result prec (dest_ivl s)\<close>\<close>)
   246          |> foldr1 HOLogic.mk_conj))
   238          |> foldr1 HOLogic.mk_conj))
   247 
   239 
   248 fun approx_arith prec ctxt t = realify t
   240 fun approx_arith prec ctxt t = realify t
   249      |> Thm.cterm_of ctxt
   241      |> Thm.cterm_of ctxt
   250      |> (preproc_form_conv ctxt then_conv reify_form_conv ctxt)
   242      |> (preproc_form_conv ctxt then_conv reify_form_conv ctxt)
   255      |> approximate ctxt
   247      |> approximate ctxt
   256      |> dest_ivl
   248      |> dest_ivl
   257      |> mk_result prec
   249      |> mk_result prec
   258 
   250 
   259 fun approx prec ctxt t =
   251 fun approx prec ctxt t =
   260   if type_of t = \<^typ>\<open>prop\<close> then approx_form prec ctxt t
   252   if type_of t = \<^Type>\<open>prop\<close> then approx_form prec ctxt t
   261   else if type_of t = \<^typ>\<open>bool\<close> then approx_form prec ctxt (\<^const>\<open>Trueprop\<close> $ t)
   253   else if type_of t = \<^Type>\<open>bool\<close> then approx_form prec ctxt \<^Const>\<open>Trueprop for t\<close>
   262   else approx_arith prec ctxt t
   254   else approx_arith prec ctxt t
   263 
   255 
   264 fun approximate_cmd modes raw_t state =
   256 fun approximate_cmd modes raw_t state =
   265   let
   257   let
   266     val ctxt = Toplevel.context_of state;
   258     val ctxt = Toplevel.context_of state;