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) |