68630
|
1 |
signature MULTISERIES_EXPANSION =
|
|
2 |
sig
|
|
3 |
include MULTISERIES_EXPANSION;
|
|
4 |
|
|
5 |
type lower_bound_thm = thm;
|
|
6 |
type upper_bound_thm = thm;
|
|
7 |
|
|
8 |
datatype limit_result = Exact_Limit of term | Limit_Bounds of term option * term option
|
|
9 |
|
|
10 |
type lower_bound = expansion_thm * lower_bound_thm;
|
|
11 |
type upper_bound = expansion_thm * upper_bound_thm;
|
|
12 |
datatype bounds =
|
|
13 |
Exact of expansion_thm | Bounds of lower_bound option * upper_bound option
|
|
14 |
|
|
15 |
val is_vacuous : bounds -> bool
|
|
16 |
val lift_bounds : basis -> bounds -> bounds
|
|
17 |
val get_expanded_fun_bounds : bounds -> term
|
|
18 |
|
|
19 |
val find_smaller_expansion :
|
|
20 |
Lazy_Eval.eval_ctxt -> thm * thm * Asymptotic_Basis.basis -> thm * thm * thm
|
|
21 |
val find_greater_expansion :
|
|
22 |
Lazy_Eval.eval_ctxt -> thm * thm * Asymptotic_Basis.basis -> thm * thm * thm
|
|
23 |
|
|
24 |
val mult_expansion_bounds :
|
|
25 |
Lazy_Eval.eval_ctxt -> Asymptotic_Basis.basis -> bounds -> bounds -> bounds
|
|
26 |
val powr_expansion_bounds :
|
|
27 |
Lazy_Eval.eval_ctxt -> Asymptotic_Basis.basis -> bounds -> bounds -> bounds * basis
|
|
28 |
val powr_nat_expansion_bounds :
|
|
29 |
Lazy_Eval.eval_ctxt -> Asymptotic_Basis.basis -> bounds -> bounds -> bounds * basis
|
|
30 |
val powr_const_expansion_bounds : Lazy_Eval.eval_ctxt -> bounds * term * basis -> bounds
|
|
31 |
val power_expansion_bounds : Lazy_Eval.eval_ctxt -> bounds * term * basis -> bounds
|
|
32 |
|
|
33 |
val sgn_expansion_bounds : Lazy_Eval.eval_ctxt -> bounds * basis -> bounds
|
|
34 |
|
|
35 |
val expand_term_bounds : Lazy_Eval.eval_ctxt -> term -> basis -> bounds * basis
|
|
36 |
val expand_terms_bounds : Lazy_Eval.eval_ctxt -> term list -> basis -> bounds list * basis
|
|
37 |
|
|
38 |
val prove_nhds_bounds : Lazy_Eval.eval_ctxt -> bounds * Asymptotic_Basis.basis -> thm
|
|
39 |
val prove_at_infinity_bounds : Lazy_Eval.eval_ctxt -> bounds * Asymptotic_Basis.basis -> thm
|
|
40 |
val prove_at_top_bounds : Lazy_Eval.eval_ctxt -> bounds * Asymptotic_Basis.basis -> thm
|
|
41 |
val prove_at_bot_bounds : Lazy_Eval.eval_ctxt -> bounds * Asymptotic_Basis.basis -> thm
|
|
42 |
val prove_at_0_bounds : Lazy_Eval.eval_ctxt -> bounds * Asymptotic_Basis.basis -> thm
|
|
43 |
val prove_at_right_0_bounds : Lazy_Eval.eval_ctxt -> bounds * Asymptotic_Basis.basis -> thm
|
|
44 |
val prove_at_left_0_bounds : Lazy_Eval.eval_ctxt -> bounds * Asymptotic_Basis.basis -> thm
|
|
45 |
val prove_eventually_nonzero_bounds : Lazy_Eval.eval_ctxt -> bounds * Asymptotic_Basis.basis -> thm
|
|
46 |
|
|
47 |
val prove_eventually_less_bounds :
|
|
48 |
Lazy_Eval.eval_ctxt -> bounds * bounds * Asymptotic_Basis.basis -> thm
|
|
49 |
val prove_eventually_greater_bounds :
|
|
50 |
Lazy_Eval.eval_ctxt -> bounds * bounds * Asymptotic_Basis.basis -> thm
|
|
51 |
|
|
52 |
val prove_smallo_bounds :
|
|
53 |
Lazy_Eval.eval_ctxt -> bounds * bounds * Asymptotic_Basis.basis -> thm
|
|
54 |
val prove_bigo_bounds :
|
|
55 |
Lazy_Eval.eval_ctxt -> bounds * bounds * Asymptotic_Basis.basis -> thm
|
|
56 |
val prove_bigtheta_bounds :
|
|
57 |
Lazy_Eval.eval_ctxt -> bounds * bounds * Asymptotic_Basis.basis -> thm
|
|
58 |
val prove_asymp_equiv_bounds :
|
|
59 |
Lazy_Eval.eval_ctxt -> bounds * bounds * Asymptotic_Basis.basis -> thm
|
|
60 |
|
|
61 |
val limit_of_expansion_bounds :
|
|
62 |
Lazy_Eval.eval_ctxt -> bounds * Asymptotic_Basis.basis -> limit_result
|
|
63 |
|
|
64 |
end
|
|
65 |
|
|
66 |
structure Multiseries_Expansion : MULTISERIES_EXPANSION =
|
|
67 |
struct
|
|
68 |
|
|
69 |
open Multiseries_Expansion;
|
|
70 |
open Exp_Log_Expression;
|
|
71 |
open Asymptotic_Basis;
|
|
72 |
|
|
73 |
type lower_bound_thm = thm;
|
|
74 |
type upper_bound_thm = thm;
|
|
75 |
|
|
76 |
datatype limit_result = Exact_Limit of term | Limit_Bounds of term option * term option
|
|
77 |
|
|
78 |
type lower_bound = expansion_thm * lower_bound_thm;
|
|
79 |
type upper_bound = expansion_thm * upper_bound_thm;
|
|
80 |
datatype bounds =
|
|
81 |
Exact of expansion_thm | Bounds of lower_bound option * upper_bound option
|
|
82 |
|
|
83 |
fun is_vacuous (Bounds (NONE, NONE)) = true
|
|
84 |
| is_vacuous _ = false
|
|
85 |
|
|
86 |
fun mk_const_expansion ectxt basis c =
|
|
87 |
let
|
|
88 |
val ctxt = Lazy_Eval.get_ctxt ectxt
|
|
89 |
val thm = Drule.infer_instantiate' ctxt [NONE, SOME (Thm.cterm_of ctxt c)]
|
|
90 |
@{thm expands_to_const}
|
|
91 |
in
|
|
92 |
thm OF [get_basis_wf_thm basis, mk_expansion_level_eq_thm basis]
|
|
93 |
end
|
|
94 |
|
69597
|
95 |
fun dest_eventually (Const (\<^const_name>\<open>Filter.eventually\<close>, _) $ p $ f) = (p, f)
|
68630
|
96 |
| dest_eventually t = raise TERM ("dest_eventually", [t])
|
|
97 |
|
|
98 |
fun dest_binop (f $ a $ b) = (f, a, b)
|
|
99 |
| dest_binop t = raise TERM ("dest_binop", [t])
|
|
100 |
|
|
101 |
fun get_lbound_from_thm thm =
|
|
102 |
thm |> Thm.concl_of |> HOLogic.dest_Trueprop |> dest_eventually |> fst
|
|
103 |
|> strip_abs |> snd |> dest_binop |> #2
|
|
104 |
|
|
105 |
fun get_ubound_from_thm thm =
|
|
106 |
thm |> Thm.concl_of |> HOLogic.dest_Trueprop |> dest_eventually |> fst
|
|
107 |
|> strip_abs |> snd |> dest_binop |> #3
|
|
108 |
|
|
109 |
fun transfer_bounds eq_thm (Exact thm) =
|
|
110 |
Exact (@{thm expands_to_meta_eq_cong'} OF [thm, eq_thm])
|
|
111 |
| transfer_bounds eq_thm (Bounds (lb, ub)) =
|
|
112 |
Bounds
|
|
113 |
(Option.map (apsnd (fn thm => @{thm transfer_lower_bound} OF [thm, eq_thm])) lb,
|
|
114 |
Option.map (apsnd (fn thm => @{thm transfer_upper_bound} OF [thm, eq_thm])) ub)
|
|
115 |
|
69597
|
116 |
fun dest_le (\<^term>\<open>(<=) :: real => _\<close> $ l $ r) = (l, r)
|
68630
|
117 |
| dest_le t = raise TERM ("dest_le", [t])
|
|
118 |
|
|
119 |
fun abconv (t, t') = Envir.beta_eta_contract t aconv Envir.beta_eta_contract t'
|
|
120 |
|
69597
|
121 |
val realT = \<^typ>\<open>Real.real\<close>
|
68630
|
122 |
|
|
123 |
fun check_bounds e (Exact thm) = let val _ = check_expansion e thm in Exact thm end
|
|
124 |
| check_bounds e (Bounds bnds) =
|
|
125 |
let
|
|
126 |
fun msg lower = if lower then "check_lower_bound" else "check_upper_bound"
|
|
127 |
fun check lower (exp_thm, le_thm) =
|
|
128 |
let
|
|
129 |
val (expanded_fun, bound_fun) =
|
|
130 |
le_thm |> Thm.concl_of |> HOLogic.dest_Trueprop |> dest_eventually |> fst
|
|
131 |
|> strip_abs |> snd |> dest_le |> (if lower then swap else I)
|
|
132 |
|> apply2 (fn t => Abs ("x", realT, t))
|
|
133 |
in
|
|
134 |
if not (abconv (get_expanded_fun exp_thm, bound_fun)) then
|
|
135 |
raise TERM (msg lower, map Thm.concl_of [exp_thm, le_thm])
|
|
136 |
else if not (abconv (expr_to_term e, expanded_fun)) then
|
|
137 |
raise TERM (msg lower, [expr_to_term e, Thm.concl_of le_thm])
|
|
138 |
else
|
|
139 |
()
|
|
140 |
end
|
|
141 |
val _ = (Option.map (check true) (fst bnds), Option.map (check false) (snd bnds))
|
|
142 |
in
|
|
143 |
Bounds bnds
|
|
144 |
end
|
|
145 |
|
|
146 |
fun cong_bounds eq_thm (Exact thm) =
|
|
147 |
Exact (@{thm expands_to_cong_reverse} OF [eq_thm, thm])
|
|
148 |
| cong_bounds eq_thm (Bounds (lb, ub)) =
|
|
149 |
Bounds
|
|
150 |
(Option.map (apsnd (fn thm => @{thm lower_bound_cong} OF [eq_thm, thm])) lb,
|
|
151 |
Option.map (apsnd (fn thm => @{thm upper_bound_cong} OF [eq_thm, thm])) ub)
|
|
152 |
|
|
153 |
fun mk_trivial_bounds ectxt f thm basis =
|
|
154 |
let
|
|
155 |
val eq_thm = Thm.reflexive (Thm.cterm_of (Lazy_Eval.get_ctxt ectxt) f)
|
|
156 |
val lb_thm = @{thm trivial_boundsI(1)} OF [thm, eq_thm]
|
|
157 |
val ub_thm = @{thm trivial_boundsI(2)} OF [thm, eq_thm]
|
|
158 |
val lb = get_lbound_from_thm lb_thm
|
|
159 |
val ub = get_ubound_from_thm ub_thm
|
|
160 |
val (lthm, uthm) = apply2 (mk_const_expansion ectxt basis) (lb, ub)
|
|
161 |
in
|
|
162 |
Bounds (SOME (lthm, lb_thm), SOME (uthm, ub_thm))
|
|
163 |
end
|
|
164 |
|
|
165 |
fun get_basis_size basis = length (get_basis_list basis)
|
|
166 |
|
|
167 |
fun trim_expansion_while_pos ectxt (thm, basis) =
|
|
168 |
let
|
|
169 |
val n = get_basis_size basis
|
69597
|
170 |
val es = SOME (replicate n \<^term>\<open>0 :: real\<close>)
|
68630
|
171 |
in
|
|
172 |
trim_expansion_while_greater false es false NONE ectxt (thm, basis)
|
|
173 |
end
|
|
174 |
|
|
175 |
fun lift_bounds basis (Exact thm) = Exact (lift basis thm)
|
|
176 |
| lift_bounds basis (Bounds bnds) =
|
|
177 |
bnds |> apply2 (Option.map (apfst (lift basis))) |> Bounds
|
|
178 |
|
|
179 |
fun mono_bound mono_thm thm = @{thm mono_bound} OF [mono_thm, thm]
|
|
180 |
|
|
181 |
fun get_lower_bound (Bounds (lb, _)) = lb
|
|
182 |
| get_lower_bound (Exact thm) = SOME (thm, thm RS @{thm exact_to_bound})
|
|
183 |
|
|
184 |
fun get_upper_bound (Bounds (_, ub)) = ub
|
|
185 |
| get_upper_bound (Exact thm) = SOME (thm, thm RS @{thm exact_to_bound})
|
|
186 |
|
|
187 |
fun get_expanded_fun_bounds_aux f (_, thm) =
|
|
188 |
let
|
|
189 |
val t = thm |> Thm.concl_of |> HOLogic.dest_Trueprop |> dest_comb |> fst |> dest_comb |> snd
|
|
190 |
in
|
|
191 |
case Envir.eta_long [] t of
|
69597
|
192 |
Abs (x, T, \<^term>\<open>(<=) :: real => _\<close> $ lhs $ rhs) => Abs (x, T, f (lhs, rhs))
|
68630
|
193 |
| _ => raise THM ("get_expanded_fun_bounds", 0, [thm])
|
|
194 |
end
|
|
195 |
|
|
196 |
fun get_expanded_fun_bounds (Exact thm) = get_expanded_fun thm
|
|
197 |
| get_expanded_fun_bounds (Bounds (NONE, NONE)) = raise TERM ("get_expanded_fun_bounds", [])
|
|
198 |
| get_expanded_fun_bounds (Bounds (SOME l, _)) =
|
|
199 |
get_expanded_fun_bounds_aux snd l
|
|
200 |
| get_expanded_fun_bounds (Bounds (_, SOME u)) =
|
|
201 |
get_expanded_fun_bounds_aux fst u
|
|
202 |
|
|
203 |
fun expand_add_bounds _ [thm, _] (Exact thm1, Exact thm2) basis =
|
|
204 |
Exact (thm OF [get_basis_wf_thm basis, thm1, thm2])
|
|
205 |
| expand_add_bounds swap [thm1, thm2] bnds basis =
|
|
206 |
let
|
|
207 |
fun comb (SOME (a, b), SOME (c, d)) =
|
|
208 |
SOME (thm1 OF [get_basis_wf_thm basis, a, c], thm2 OF [b, d])
|
|
209 |
| comb _ = NONE
|
|
210 |
val ((a, b), (c, d)) = (apply2 get_lower_bound bnds, apply2 get_upper_bound bnds)
|
|
211 |
in
|
|
212 |
if swap then
|
|
213 |
Bounds (comb (a, d), comb (c, b))
|
|
214 |
else
|
|
215 |
Bounds (comb (a, b), comb (c, d))
|
|
216 |
end
|
|
217 |
| expand_add_bounds _ _ _ _ = raise Match
|
|
218 |
|
|
219 |
fun mk_refl_thm ectxt t =
|
|
220 |
let
|
|
221 |
val ctxt = Lazy_Eval.get_ctxt ectxt
|
|
222 |
val ct = Thm.cterm_of ctxt t
|
|
223 |
in
|
|
224 |
Drule.infer_instantiate' ctxt [SOME ct] @{thm eventually_le_self}
|
|
225 |
end
|
|
226 |
|
|
227 |
|
|
228 |
fun find_smaller_expansion ectxt (thm1, thm2, basis) =
|
|
229 |
case compare_expansions ectxt (thm1, thm2, basis) of
|
|
230 |
(LESS, less_thm, thm1, _) =>
|
|
231 |
(thm1, mk_refl_thm ectxt (get_expanded_fun thm1), less_thm RS @{thm eventually_less_imp_le})
|
|
232 |
| (GREATER, gt_thm, _, thm2) =>
|
|
233 |
(thm2, gt_thm RS @{thm eventually_less_imp_le}, mk_refl_thm ectxt (get_expanded_fun thm2))
|
|
234 |
| (EQUAL, eq_thm, thm1, _) =>
|
|
235 |
(thm1, mk_refl_thm ectxt (get_expanded_fun thm1), eq_thm RS @{thm eventually_eq_imp_le})
|
|
236 |
|
|
237 |
fun find_greater_expansion ectxt (thm1, thm2, basis) =
|
69597
|
238 |
case compare_expansions ectxt (\<^print> (thm1, thm2, basis)) of
|
68630
|
239 |
(LESS, less_thm, _, thm2) =>
|
|
240 |
(thm2, less_thm RS @{thm eventually_less_imp_le}, mk_refl_thm ectxt (get_expanded_fun thm2))
|
|
241 |
| (GREATER, gt_thm, thm1, _) =>
|
|
242 |
(thm1, mk_refl_thm ectxt (get_expanded_fun thm1), gt_thm RS @{thm eventually_less_imp_le})
|
|
243 |
| (EQUAL, eq_thm, thm1, _) =>
|
|
244 |
(thm1, mk_refl_thm ectxt (get_expanded_fun thm1), eq_thm RS @{thm eventually_eq_imp_ge})
|
|
245 |
|
|
246 |
fun determine_sign ectxt (thm, basis) =
|
|
247 |
case ev_zeroness_oracle ectxt (get_expanded_fun thm) of
|
|
248 |
SOME zero_thm => (thm, zero_thm, (true, true))
|
|
249 |
| NONE => (
|
|
250 |
case trim_expansion true (SOME Sgn_Trim) ectxt (thm, basis) of
|
|
251 |
(thm, IsPos, SOME pos_thm) =>
|
|
252 |
(thm, @{thm expands_to_imp_eventually_pos} OF [get_basis_wf_thm basis, thm, pos_thm],
|
|
253 |
(false, true))
|
|
254 |
| (thm, IsNeg, SOME neg_thm) =>
|
|
255 |
(thm, @{thm expands_to_imp_eventually_neg} OF [get_basis_wf_thm basis, thm, neg_thm],
|
|
256 |
(true, false))
|
|
257 |
| _ => raise TERM ("Unexpected zeroness result in determine_sign", []))
|
|
258 |
|
|
259 |
val mult_bounds_thms = @{thms mult_bounds_real[eventuallized]}
|
|
260 |
fun mult_bounds_thm n = List.nth (mult_bounds_thms, n)
|
|
261 |
|
|
262 |
val powr_bounds_thms = @{thms powr_bounds_real[eventuallized]}
|
|
263 |
fun powr_bounds_thm n = List.nth (powr_bounds_thms, n)
|
|
264 |
|
|
265 |
fun mk_nonstrict_thm [thm1, thm2] sgn_thm = (
|
|
266 |
case Thm.concl_of sgn_thm |> HOLogic.dest_Trueprop of
|
69597
|
267 |
Const (\<^const_name>\<open>Filter.eventually\<close>, _) $ t $ _ => (
|
68630
|
268 |
case Envir.eta_long [] t of
|
69597
|
269 |
Abs (_, _, Const (\<^const_name>\<open>HOL.eq\<close>, _) $ _ $ _) => sgn_thm RS thm1
|
68630
|
270 |
| _ => sgn_thm RS thm2)
|
|
271 |
| _ => sgn_thm RS thm2)
|
|
272 |
| mk_nonstrict_thm _ _ = raise Match
|
|
273 |
|
|
274 |
|
|
275 |
val mk_nonneg_thm = mk_nonstrict_thm @{thms eventually_eq_imp_ge eventually_less_imp_le}
|
|
276 |
val mk_nonpos_thm = mk_nonstrict_thm @{thms eventually_eq_imp_le eventually_less_imp_le}
|
|
277 |
|
|
278 |
fun mult_expansion_bounds_right basis
|
|
279 |
((l1_thm, l1_le_thm), (u1_thm, u1_ge_thm)) (thm2, sgn_thm, sgns) =
|
|
280 |
let
|
|
281 |
val in_bounds_thm = @{thm eventually_atLeastAtMostI} OF [l1_le_thm, u1_ge_thm]
|
|
282 |
fun mult_expansions (thm1, thm2) =
|
|
283 |
@{thm expands_to_mult} OF [get_basis_wf_thm basis, thm1, thm2]
|
|
284 |
in
|
|
285 |
if snd sgns then
|
|
286 |
(mult_expansions (l1_thm, thm2), mult_expansions (u1_thm, thm2),
|
|
287 |
@{thm mult_right_bounds(1)[eventuallized]} OF [in_bounds_thm, mk_nonneg_thm sgn_thm])
|
|
288 |
else
|
|
289 |
(mult_expansions (u1_thm, thm2), mult_expansions (l1_thm, thm2),
|
|
290 |
@{thm mult_right_bounds(2)[eventuallized]} OF [in_bounds_thm, mk_nonpos_thm sgn_thm])
|
|
291 |
end
|
|
292 |
|
|
293 |
fun mult_expansion_bounds_left basis
|
|
294 |
(thm1, sgn_thm, sgns) ((l2_thm, l2_le_thm), (u2_thm, u2_ge_thm)) =
|
|
295 |
let
|
|
296 |
val in_bounds_thm = @{thm eventually_atLeastAtMostI} OF [l2_le_thm, u2_ge_thm]
|
|
297 |
fun mult_expansions (thm1, thm2) =
|
|
298 |
@{thm expands_to_mult} OF [get_basis_wf_thm basis, thm1, thm2]
|
|
299 |
in
|
|
300 |
if snd sgns then
|
|
301 |
(mult_expansions (thm1, l2_thm), mult_expansions (thm1, u2_thm),
|
|
302 |
@{thm mult_left_bounds(1)[eventuallized]} OF [in_bounds_thm, mk_nonneg_thm sgn_thm])
|
|
303 |
else
|
|
304 |
(mult_expansions (thm1, u2_thm), mult_expansions (thm1, l2_thm),
|
|
305 |
@{thm mult_left_bounds(2)[eventuallized]} OF [in_bounds_thm, mk_nonpos_thm sgn_thm])
|
|
306 |
end
|
|
307 |
|
|
308 |
fun mult_expansion_bounds_2 ectxt basis
|
|
309 |
((l1, l1_le_thm, l1sgn_thm, l1_sgn), (u1, u1_ge_thm, u1sgn_thm, u1_sgn))
|
|
310 |
((l2, l2_le_thm, l2sgn_thm, l2_sgn), (u2, u2_ge_thm, u2sgn_thm, u2_sgn)) =
|
|
311 |
let
|
|
312 |
val sgns = (l1_sgn, u1_sgn, l2_sgn, u2_sgn)
|
|
313 |
val in_bounds_thms =
|
|
314 |
map (fn thms => @{thm eventually_atLeastAtMostI} OF thms)
|
|
315 |
[[l1_le_thm, u1_ge_thm], [l2_le_thm, u2_ge_thm]]
|
|
316 |
fun mult_expansions (thm1, thm2) =
|
|
317 |
@{thm expands_to_mult} OF [get_basis_wf_thm basis, thm1, thm2]
|
|
318 |
in
|
|
319 |
case sgns of
|
|
320 |
((_, true), _, (_, true), _) =>
|
|
321 |
(mult_expansions (l1, l2), mult_expansions (u1, u2),
|
|
322 |
mult_bounds_thm 0 OF ([mk_nonneg_thm l1sgn_thm, mk_nonneg_thm l2sgn_thm] @ in_bounds_thms))
|
|
323 |
| (_, (true, _), (_, true), _) =>
|
|
324 |
(mult_expansions (l1, u2), mult_expansions (u1, l2),
|
|
325 |
mult_bounds_thm 1 OF ([mk_nonpos_thm u1sgn_thm, mk_nonneg_thm l2sgn_thm] @ in_bounds_thms))
|
|
326 |
| ((_, true), _, _, (true, _)) =>
|
|
327 |
(mult_expansions (u1, l2), mult_expansions (l1, u2),
|
|
328 |
mult_bounds_thm 2 OF ([mk_nonneg_thm l1sgn_thm, mk_nonpos_thm u2sgn_thm] @ in_bounds_thms))
|
|
329 |
| (_, (true, _), _, (true, _)) =>
|
|
330 |
(mult_expansions (u1, u2), mult_expansions (l1, l2),
|
|
331 |
mult_bounds_thm 3 OF ([mk_nonpos_thm u1sgn_thm, mk_nonpos_thm u2sgn_thm] @ in_bounds_thms))
|
|
332 |
| ((true, _), (_, true), (_, true), _) =>
|
|
333 |
(mult_expansions (l1, u2), mult_expansions (u1, u2),
|
|
334 |
mult_bounds_thm 4 OF ([mk_nonpos_thm l1sgn_thm, mk_nonneg_thm u1sgn_thm, mk_nonneg_thm l2sgn_thm] @ in_bounds_thms))
|
|
335 |
| ((true, _), (_, true), _, (true, _)) =>
|
|
336 |
(mult_expansions (u1, l2), mult_expansions (l1, l2),
|
|
337 |
mult_bounds_thm 5 OF ([mk_nonpos_thm l1sgn_thm, mk_nonneg_thm u1sgn_thm, mk_nonpos_thm u2sgn_thm] @ in_bounds_thms))
|
|
338 |
| ((_, true), _, (true, _), (_, true)) =>
|
|
339 |
(mult_expansions (u1, l2), mult_expansions (u1, u2),
|
|
340 |
mult_bounds_thm 6 OF ([mk_nonneg_thm l1sgn_thm, mk_nonpos_thm l2sgn_thm, mk_nonneg_thm u2sgn_thm] @ in_bounds_thms))
|
|
341 |
| (_, (true, _), (true, _), (_, true)) =>
|
|
342 |
(mult_expansions (l1, u2), mult_expansions (l1, l2),
|
|
343 |
mult_bounds_thm 7 OF ([mk_nonpos_thm u1sgn_thm, mk_nonpos_thm l2sgn_thm, mk_nonneg_thm u2sgn_thm] @ in_bounds_thms))
|
|
344 |
| ((true, _), (_, true), (true, _), (_, true)) =>
|
|
345 |
let
|
|
346 |
val l1u2 = mult_expansions (l1, u2)
|
|
347 |
val u1l2 = mult_expansions (u1, l2)
|
|
348 |
val l1l2 = mult_expansions (l1, l2)
|
|
349 |
val u1u2 = mult_expansions (u1, u2)
|
|
350 |
val (l, lthm1, lthm2) = find_smaller_expansion ectxt (l1u2, u1l2, basis)
|
|
351 |
val (u, uthm1, uthm2) = find_greater_expansion ectxt (l1l2, u1u2, basis)
|
|
352 |
in
|
|
353 |
(l, u, mult_bounds_thm 8 OF
|
|
354 |
([mk_nonpos_thm l1sgn_thm, mk_nonneg_thm u1sgn_thm, mk_nonpos_thm l2sgn_thm,
|
|
355 |
mk_nonneg_thm u2sgn_thm, lthm1, lthm2, uthm1, uthm2] @ in_bounds_thms))
|
|
356 |
end
|
|
357 |
|
|
358 |
| _ => raise Match
|
|
359 |
end
|
|
360 |
|
|
361 |
fun convert_bounds (lthm, uthm, in_bounds_thm) =
|
|
362 |
Bounds (SOME (lthm, in_bounds_thm RS @{thm eventually_atLeastAtMostD(1)}),
|
|
363 |
SOME (uthm, in_bounds_thm RS @{thm eventually_atLeastAtMostD(2)}))
|
|
364 |
|
|
365 |
fun convert_bounds' (Exact thm) = (thm, thm, thm RS @{thm expands_to_trivial_bounds})
|
|
366 |
| convert_bounds' (Bounds (SOME (lthm, ge_thm), SOME (uthm, le_thm))) =
|
|
367 |
(lthm, uthm, @{thm eventually_in_atLeastAtMostI} OF [ge_thm, le_thm])
|
|
368 |
|
|
369 |
fun mult_expansion_bounds _ basis (Exact thm1) (Exact thm2) =
|
|
370 |
Exact (@{thm expands_to_mult} OF [get_basis_wf_thm basis, thm1, thm2])
|
|
371 |
| mult_expansion_bounds ectxt basis (Bounds (SOME l1, SOME u1)) (Exact thm2) =
|
|
372 |
mult_expansion_bounds_right basis (l1, u1) (determine_sign ectxt (thm2, basis))
|
|
373 |
|> convert_bounds
|
|
374 |
| mult_expansion_bounds ectxt basis (Exact thm1) (Bounds (SOME l2, SOME u2)) =
|
|
375 |
mult_expansion_bounds_left basis (determine_sign ectxt (thm1, basis)) (l2, u2)
|
|
376 |
|> convert_bounds
|
|
377 |
| mult_expansion_bounds ectxt basis (Bounds (SOME l1, SOME u1)) (Bounds (SOME l2, SOME u2)) =
|
|
378 |
let
|
|
379 |
fun prep (thm, le_thm) =
|
|
380 |
case determine_sign ectxt (thm, basis) of
|
|
381 |
(thm, sgn_thm, sgns) => (thm, le_thm, sgn_thm, sgns)
|
|
382 |
in
|
|
383 |
mult_expansion_bounds_2 ectxt basis (prep l1, prep u1) (prep l2, prep u2)
|
|
384 |
|> convert_bounds
|
|
385 |
end
|
|
386 |
| mult_expansion_bounds _ _ _ _ = Bounds (NONE, NONE)
|
|
387 |
|
|
388 |
fun inverse_expansion ectxt basis thm =
|
|
389 |
case trim_expansion true (SOME Simple_Trim) ectxt (thm, basis) of
|
|
390 |
(thm, _, SOME trimmed_thm) =>
|
|
391 |
@{thm expands_to_inverse} OF [trimmed_thm, get_basis_wf_thm basis, thm]
|
|
392 |
| _ => raise TERM ("zero denominator", [get_expanded_fun thm])
|
|
393 |
|
|
394 |
fun divide_expansion ectxt basis thm1 thm2 =
|
|
395 |
case trim_expansion true (SOME Simple_Trim) ectxt (thm2, basis) of
|
|
396 |
(thm2, _, SOME trimmed_thm) =>
|
|
397 |
@{thm expands_to_divide} OF [trimmed_thm, get_basis_wf_thm basis, thm1, thm2]
|
|
398 |
|
|
399 |
fun forget_trimmedness_sign trimmed_thm =
|
|
400 |
case Thm.concl_of trimmed_thm |> HOLogic.dest_Trueprop of
|
69597
|
401 |
Const (\<^const_name>\<open>Multiseries_Expansion.trimmed\<close>, _) $ _ => trimmed_thm
|
|
402 |
| Const (\<^const_name>\<open>Multiseries_Expansion.trimmed_pos\<close>, _) $ _ =>
|
68630
|
403 |
trimmed_thm RS @{thm trimmed_pos_imp_trimmed}
|
69597
|
404 |
| Const (\<^const_name>\<open>Multiseries_Expansion.trimmed_neg\<close>, _) $ _ =>
|
68630
|
405 |
trimmed_thm RS @{thm trimmed_neg_imp_trimmed}
|
|
406 |
| _ => raise THM ("forget_trimmedness_sign", 0, [trimmed_thm])
|
|
407 |
|
|
408 |
fun inverse_expansion_bounds ectxt basis (Exact thm) =
|
|
409 |
Exact (inverse_expansion ectxt basis thm)
|
|
410 |
| inverse_expansion_bounds ectxt basis (Bounds (SOME (lthm, le_thm), SOME (uthm, ge_thm))) =
|
|
411 |
let
|
|
412 |
fun trim thm = trim_expansion true (SOME Sgn_Trim) ectxt (thm, basis)
|
|
413 |
fun inverse thm trimmed_thm = @{thm expands_to_inverse} OF
|
|
414 |
[forget_trimmedness_sign trimmed_thm, get_basis_wf_thm basis, thm]
|
|
415 |
in
|
|
416 |
case (trim lthm, trim uthm) of
|
|
417 |
((lthm, IsPos, SOME trimmed_thm1), (uthm, _, SOME trimmed_thm2)) =>
|
|
418 |
(inverse uthm trimmed_thm2, inverse lthm trimmed_thm1,
|
|
419 |
@{thm inverse_bounds_real(1)[eventuallized, OF expands_to_imp_eventually_pos]} OF
|
|
420 |
[get_basis_wf_thm basis, lthm, trimmed_thm1, le_thm, ge_thm]) |> convert_bounds
|
|
421 |
| ((lthm, _, SOME trimmed_thm1), (uthm, IsNeg, SOME trimmed_thm2)) =>
|
|
422 |
(inverse uthm trimmed_thm2, inverse lthm trimmed_thm1,
|
|
423 |
@{thm inverse_bounds_real(2)[eventuallized, OF expands_to_imp_eventually_neg]} OF
|
|
424 |
[get_basis_wf_thm basis, uthm, trimmed_thm2, le_thm, ge_thm]) |> convert_bounds
|
|
425 |
| _ => raise TERM ("zero denominator", map get_expanded_fun [lthm, uthm])
|
|
426 |
end
|
|
427 |
| inverse_expansion_bounds _ _ _ = Bounds (NONE, NONE)
|
|
428 |
|
|
429 |
fun trimmed_thm_to_inverse_sgn_thm basis thm trimmed_thm =
|
|
430 |
case trimmed_thm |> Thm.concl_of |> HOLogic.dest_Trueprop of
|
69597
|
431 |
Const (\<^const_name>\<open>Multiseries_Expansion.trimmed_pos\<close>, _) $ _ =>
|
68630
|
432 |
@{thm pos_imp_inverse_pos[eventuallized, OF expands_to_imp_eventually_pos]} OF
|
|
433 |
[get_basis_wf_thm basis, thm, trimmed_thm]
|
69597
|
434 |
| Const (\<^const_name>\<open>Multiseries_Expansion.trimmed_neg\<close>, _) $ _ =>
|
68630
|
435 |
@{thm neg_imp_inverse_neg[eventuallized, OF expands_to_imp_eventually_neg]} OF
|
|
436 |
[get_basis_wf_thm basis, thm, trimmed_thm]
|
|
437 |
| _ => raise THM ("trimmed_thm_to_inverse_sgn_thm", 0, [trimmed_thm])
|
|
438 |
|
|
439 |
fun transfer_divide_bounds (lthm, uthm, in_bounds_thm) =
|
|
440 |
let
|
|
441 |
val f = Conv.fconv_rule (Conv.try_conv (Conv.rewr_conv @{thm transfer_divide_bounds(4)}))
|
|
442 |
val conv = Conv.repeat_conv (Conv.rewrs_conv @{thms transfer_divide_bounds(1-3)})
|
|
443 |
in
|
|
444 |
(f lthm, f uthm, Conv.fconv_rule conv in_bounds_thm)
|
|
445 |
end
|
|
446 |
|
|
447 |
fun divide_expansion_bounds ectxt basis (Exact thm1) (Exact thm2) =
|
|
448 |
Exact (divide_expansion ectxt basis thm1 thm2)
|
|
449 |
| divide_expansion_bounds ectxt basis (Bounds (SOME l1, SOME u1)) (Exact thm2) =
|
|
450 |
let
|
|
451 |
val (thm2, sgn, SOME trimmed_thm) = trim_expansion true (SOME Sgn_Trim) ectxt (thm2, basis)
|
|
452 |
val thm2' = @{thm expands_to_inverse} OF
|
|
453 |
[forget_trimmedness_sign trimmed_thm, get_basis_wf_thm basis, thm2]
|
|
454 |
val sgn_thm = trimmed_thm_to_inverse_sgn_thm basis thm2 trimmed_thm
|
|
455 |
in
|
|
456 |
mult_expansion_bounds_right basis (l1, u1) (thm2', sgn_thm, (sgn = IsNeg, sgn = IsPos))
|
|
457 |
|> transfer_divide_bounds
|
|
458 |
|> convert_bounds
|
|
459 |
end
|
|
460 |
| divide_expansion_bounds ectxt basis bnds1 (Bounds (SOME (lthm, ge_thm), SOME (uthm, le_thm))) =
|
|
461 |
let
|
|
462 |
fun trim thm =
|
|
463 |
case trim_expansion true (SOME Sgn_Trim) ectxt (thm, basis) of
|
|
464 |
(thm, sgn, SOME trimmed_thm) => (thm, sgn, trimmed_thm)
|
|
465 |
| _ => raise TERM ("zero divisor", [get_expanded_fun thm])
|
|
466 |
fun inverse thm trimmed_thm = @{thm expands_to_inverse} OF
|
|
467 |
[forget_trimmedness_sign trimmed_thm, get_basis_wf_thm basis, thm]
|
|
468 |
|
|
469 |
val (lthm, sgnl, ltrimmed_thm) = trim lthm
|
|
470 |
val (uthm, sgnu, utrimmed_thm) = trim uthm
|
|
471 |
val (uthm', lthm') = (inverse lthm ltrimmed_thm, inverse uthm utrimmed_thm)
|
|
472 |
val in_bounds_thm' =
|
|
473 |
if sgnl = IsPos then
|
|
474 |
@{thm inverse_bounds_real(1)[eventuallized, OF expands_to_imp_eventually_pos]} OF
|
|
475 |
[get_basis_wf_thm basis, lthm, ltrimmed_thm, ge_thm, le_thm]
|
|
476 |
else if sgnu = IsNeg then
|
|
477 |
@{thm inverse_bounds_real(2)[eventuallized, OF expands_to_imp_eventually_neg]} OF
|
|
478 |
[get_basis_wf_thm basis, uthm, utrimmed_thm, ge_thm, le_thm]
|
|
479 |
else
|
|
480 |
raise TERM ("zero divisor", map get_expanded_fun [lthm, uthm])
|
|
481 |
val [ge_thm', le_thm'] =
|
|
482 |
map (fn thm => in_bounds_thm' RS thm) @{thms eventually_atLeastAtMostD}
|
|
483 |
val bnds2' = ((lthm', ge_thm'), (uthm', le_thm'))
|
|
484 |
val usgn_thm' = trimmed_thm_to_inverse_sgn_thm basis lthm ltrimmed_thm
|
|
485 |
val lsgn_thm' = trimmed_thm_to_inverse_sgn_thm basis uthm utrimmed_thm
|
|
486 |
in
|
|
487 |
case bnds1 of
|
|
488 |
Exact thm1 =>
|
|
489 |
(mult_expansion_bounds_left basis (determine_sign ectxt (thm1, basis)) bnds2')
|
|
490 |
|> transfer_divide_bounds
|
|
491 |
|> convert_bounds
|
|
492 |
| Bounds (SOME l1, SOME u1) =>
|
|
493 |
let
|
|
494 |
fun prep (thm, le_thm) =
|
|
495 |
case determine_sign ectxt (thm, basis) of
|
|
496 |
(thm, sgn_thm, sgns) => (thm, le_thm, sgn_thm, sgns)
|
|
497 |
in
|
|
498 |
mult_expansion_bounds_2 ectxt basis (prep l1, prep u1)
|
|
499 |
((lthm', ge_thm', lsgn_thm', (sgnl = IsNeg, sgnl = IsPos)),
|
|
500 |
(uthm', le_thm', usgn_thm', (sgnu = IsNeg, sgnu = IsPos)))
|
|
501 |
|> transfer_divide_bounds
|
|
502 |
|> convert_bounds
|
|
503 |
end
|
|
504 |
| _ => Bounds (NONE, NONE)
|
|
505 |
end
|
|
506 |
| divide_expansion_bounds _ _ _ _ = Bounds (NONE, NONE)
|
|
507 |
|
|
508 |
fun abs_expansion ectxt basis thm =
|
|
509 |
let
|
|
510 |
val (thm, nz, SOME trimmed_thm) = trim_expansion true (SOME Sgn_Trim) ectxt (thm, basis)
|
|
511 |
val thm' =
|
|
512 |
case nz of
|
|
513 |
IsPos => @{thm expands_to_abs_pos}
|
|
514 |
| IsNeg => @{thm expands_to_abs_neg}
|
|
515 |
| _ => raise TERM ("Unexpected trim result during expansion of abs", [])
|
|
516 |
in
|
|
517 |
thm' OF [trimmed_thm, get_basis_wf_thm basis, thm]
|
|
518 |
end
|
|
519 |
|
|
520 |
fun abs_trivial_bounds ectxt f =
|
|
521 |
let
|
|
522 |
val ctxt = Lazy_Eval.get_ctxt ectxt
|
|
523 |
in
|
|
524 |
Drule.infer_instantiate' ctxt [SOME (Thm.cterm_of ctxt f)] @{thm eventually_abs_ge_0}
|
|
525 |
end
|
|
526 |
|
|
527 |
fun abs_expansion_bounds ectxt basis (Exact thm) = Exact (abs_expansion ectxt basis thm)
|
|
528 |
| abs_expansion_bounds ectxt basis (bnds as Bounds (SOME (lthm, ge_thm), NONE)) =
|
|
529 |
let
|
|
530 |
val (lthm, lsgn_thm, lsgns) = determine_sign ectxt (lthm, basis)
|
|
531 |
val lbnd =
|
|
532 |
if snd lsgns then
|
|
533 |
(lthm, @{thm eventually_le_abs_nonneg} OF [mk_nonneg_thm lsgn_thm, ge_thm])
|
|
534 |
else
|
|
535 |
(zero_expansion basis, abs_trivial_bounds ectxt (get_expanded_fun_bounds bnds))
|
|
536 |
in
|
|
537 |
Bounds (SOME lbnd, NONE)
|
|
538 |
end
|
|
539 |
| abs_expansion_bounds ectxt basis (bnds as Bounds (NONE, SOME (uthm, le_thm))) =
|
|
540 |
let
|
|
541 |
val (uthm, usgn_thm, usgns) = determine_sign ectxt (uthm, basis)
|
|
542 |
val lbnd =
|
|
543 |
if fst usgns then
|
|
544 |
(@{thm expands_to_uminus} OF [get_basis_wf_thm basis, uthm],
|
|
545 |
@{thm eventually_le_abs_nonpos} OF [mk_nonpos_thm usgn_thm, le_thm])
|
|
546 |
else
|
|
547 |
(zero_expansion basis, abs_trivial_bounds ectxt (get_expanded_fun_bounds bnds))
|
|
548 |
in
|
|
549 |
Bounds (SOME lbnd, NONE)
|
|
550 |
end
|
|
551 |
| abs_expansion_bounds ectxt basis (Bounds (SOME (lthm, ge_thm), SOME (uthm, le_thm))) =
|
|
552 |
let
|
|
553 |
val in_bounds_thm = @{thm eventually_atLeastAtMostI} OF [ge_thm, le_thm]
|
|
554 |
val (lthm, lsgn_thm, lsgns) = determine_sign ectxt (lthm, basis)
|
|
555 |
val (uthm, usgn_thm, usgns) = determine_sign ectxt (uthm, basis)
|
|
556 |
fun minus thm = @{thm expands_to_uminus} OF [get_basis_wf_thm basis, thm]
|
|
557 |
in (
|
|
558 |
case (lsgns, usgns) of
|
|
559 |
((_, true), _) =>
|
|
560 |
(lthm, uthm,
|
|
561 |
@{thm nonneg_abs_bounds[eventuallized]} OF [mk_nonneg_thm lsgn_thm, in_bounds_thm])
|
|
562 |
| (_, (true, _)) =>
|
|
563 |
(minus uthm, minus lthm,
|
|
564 |
@{thm nonpos_abs_bounds[eventuallized]} OF [mk_nonpos_thm usgn_thm, in_bounds_thm])
|
|
565 |
| ((true, _), (_, true)) => (
|
|
566 |
case find_greater_expansion ectxt (minus lthm, uthm, basis) of
|
|
567 |
(u'_thm, le_thm1, le_thm2) =>
|
69597
|
568 |
(mk_const_expansion ectxt basis \<^term>\<open>0::real\<close>, u'_thm,
|
68630
|
569 |
@{thm indet_abs_bounds[eventuallized]} OF
|
|
570 |
[mk_nonpos_thm lsgn_thm, mk_nonneg_thm usgn_thm,
|
|
571 |
in_bounds_thm, le_thm1, le_thm2]))
|
|
572 |
| _ => raise TERM ("Unexpected zeroness result in abs_expansion_bounds", []))
|
|
573 |
|> convert_bounds
|
|
574 |
end
|
|
575 |
| abs_expansion_bounds _ _ _ = Bounds (NONE, NONE) (* TODO *)
|
|
576 |
|
|
577 |
fun abs_expansion_lower_bound ectxt basis (Exact thm) =
|
|
578 |
let
|
|
579 |
val thm' = abs_expansion ectxt basis thm
|
|
580 |
in
|
|
581 |
(thm', thm RS @{thm expands_to_abs_nonneg}, thm' RS @{thm exact_to_bound})
|
|
582 |
end
|
|
583 |
| abs_expansion_lower_bound ectxt basis (Bounds (SOME (lthm, ge_thm), SOME (uthm, le_thm))) =
|
|
584 |
let
|
|
585 |
val in_bounds_thm = @{thm eventually_atLeastAtMostI} OF [ge_thm, le_thm]
|
|
586 |
val (lthm, lsgn_thm, lsgns) = determine_sign ectxt (lthm, basis)
|
|
587 |
val (uthm, usgn_thm, usgns) = determine_sign ectxt (uthm, basis)
|
|
588 |
fun minus thm = @{thm expands_to_uminus} OF [get_basis_wf_thm basis, thm]
|
|
589 |
val [absthm1, absthm2] =
|
|
590 |
@{thms eventually_atLeastAtMostD(1)[OF nonneg_abs_bounds[eventuallized]]
|
|
591 |
eventually_atLeastAtMostD(1)[OF nonpos_abs_bounds[eventuallized]]}
|
|
592 |
in (
|
|
593 |
case (lsgns, usgns) of
|
|
594 |
((_, true), _) =>
|
|
595 |
(lthm, mk_nonneg_thm lsgn_thm,
|
|
596 |
absthm1 OF [mk_nonneg_thm lsgn_thm, in_bounds_thm])
|
|
597 |
| (_, (true, _)) =>
|
|
598 |
(minus uthm, mk_nonpos_thm usgn_thm RS @{thm eventually_nonpos_flip},
|
|
599 |
absthm2 OF [mk_nonpos_thm usgn_thm, in_bounds_thm])
|
|
600 |
| ((true, _), (_, true)) => raise TERM ("abs_expansion_lower_bound", [])
|
|
601 |
| _ => raise TERM ("Unexpected zeroness result in abs_expansion_bounds", []))
|
|
602 |
end
|
|
603 |
| abs_expansion_lower_bound _ _ _ = raise TERM ("abs_expansion_lower_bound", [])
|
|
604 |
|
|
605 |
fun powr_expansion_bounds_right ectxt basis
|
|
606 |
((l1_thm, l1_le_thm), (u1_thm, u1_ge_thm)) (thm2, sgn_thm, g_sgns) =
|
|
607 |
let
|
|
608 |
val in_bounds_thm = @{thm eventually_atLeastAtMostI} OF [l1_le_thm, u1_ge_thm]
|
|
609 |
val (l1_thm, l1_sgn_thm, l1_sgns) = determine_sign ectxt (l1_thm, basis)
|
|
610 |
val l1_sgn_thm = if snd g_sgns then mk_nonneg_thm l1_sgn_thm else l1_sgn_thm
|
|
611 |
val (l_thm, basis') = powr_expansion ectxt (l1_thm, thm2, basis)
|
|
612 |
val (u_thm, basis'') = powr_expansion ectxt (lift basis' u1_thm, lift basis' thm2, basis')
|
|
613 |
val l_thm = lift basis'' l_thm
|
|
614 |
in
|
|
615 |
if (snd g_sgns andalso not (snd l1_sgns)) orelse (not (snd g_sgns) andalso fst l1_sgns) then
|
|
616 |
raise TERM ("Non-positive base in powr.", [])
|
|
617 |
else if snd g_sgns then
|
|
618 |
((l_thm, u_thm, @{thm powr_right_bounds(1)[eventuallized]}
|
|
619 |
OF [l1_sgn_thm, in_bounds_thm, mk_nonneg_thm sgn_thm]), basis'')
|
|
620 |
else
|
|
621 |
((u_thm, l_thm, @{thm powr_right_bounds(2)[eventuallized]}
|
|
622 |
OF [l1_sgn_thm, in_bounds_thm, mk_nonpos_thm sgn_thm]), basis'')
|
|
623 |
end
|
|
624 |
|
|
625 |
fun compare_expansion_to_1 ectxt (thm, basis) =
|
69597
|
626 |
prove_asymptotic_relation ectxt (thm, const_expansion ectxt basis \<^term>\<open>1 :: real\<close>, basis)
|
68630
|
627 |
|
|
628 |
fun powr_expansion_bounds_left ectxt basis
|
|
629 |
thm1 ((l2_thm, l2_le_thm), (u2_thm, u2_ge_thm)) =
|
|
630 |
let
|
|
631 |
val in_bounds_thm = @{thm eventually_atLeastAtMostI} OF [l2_le_thm, u2_ge_thm]
|
|
632 |
val (thm1, _, SOME trimmed_pos_thm) = trim_expansion true (SOME Pos_Trim) ectxt (thm1, basis)
|
|
633 |
val pos_thm = @{thm expands_to_imp_eventually_pos} OF
|
|
634 |
[get_basis_wf_thm basis, thm1, trimmed_pos_thm]
|
|
635 |
val (l_thm, basis') = powr_expansion ectxt (thm1, l2_thm, basis)
|
|
636 |
val (u_thm, basis'') = powr_expansion ectxt (lift basis' thm1, lift basis' u2_thm, basis')
|
|
637 |
val l_thm = lift basis'' l_thm
|
|
638 |
val (cmp_1, cmp_1_thm) = compare_expansion_to_1 ectxt (thm1, basis)
|
|
639 |
in
|
|
640 |
case cmp_1 of
|
|
641 |
LESS =>
|
|
642 |
((u_thm, l_thm, @{thm powr_left_bounds(2)[eventuallized]} OF
|
|
643 |
[pos_thm, in_bounds_thm, mk_nonpos_thm cmp_1_thm]), basis'')
|
|
644 |
| _ =>
|
|
645 |
((l_thm, u_thm, @{thm powr_left_bounds(1)[eventuallized]} OF
|
|
646 |
[pos_thm, in_bounds_thm, mk_nonneg_thm cmp_1_thm]), basis'')
|
|
647 |
end
|
|
648 |
|
|
649 |
fun powr_expansion_bounds_2 ectxt basis
|
|
650 |
((l1, l1_le_thm, l1pos_thm, l1_sgn), (u1, u1_ge_thm, _, _))
|
|
651 |
((l2, l2_le_thm, l2sgn_thm, l2_sgn), (u2, u2_ge_thm, u2sgn_thm, u2_sgn)) =
|
|
652 |
let
|
|
653 |
fun do_force_pos () =
|
|
654 |
if fst l1_sgn then raise TERM ("Non-positive base in power", []) else ()
|
|
655 |
|
|
656 |
fun compare_expansion_to_1' thm =
|
|
657 |
let
|
|
658 |
val (cmp, sgn_thm) = compare_expansion_to_1 ectxt (thm, basis)
|
|
659 |
val sgn = (cmp <> GREATER, cmp <> LESS)
|
|
660 |
in
|
|
661 |
(sgn, sgn_thm)
|
|
662 |
end
|
|
663 |
val (l1_sgn, l1sgn_thm) = compare_expansion_to_1' l1
|
|
664 |
val (u1_sgn, u1sgn_thm) = compare_expansion_to_1' u1
|
|
665 |
|
|
666 |
val sgns = (l1_sgn, u1_sgn, l2_sgn, u2_sgn)
|
|
667 |
val in_bounds_thms =
|
|
668 |
map (fn thms => @{thm eventually_atLeastAtMostI} OF thms)
|
|
669 |
[[l1_le_thm, u1_ge_thm], [l2_le_thm, u2_ge_thm]]
|
|
670 |
fun f n force_pos (a, b) (c, d) thms =
|
|
671 |
let
|
|
672 |
val _ = if force_pos then do_force_pos () else ()
|
|
673 |
val l1pos_thm = if force_pos then l1pos_thm else mk_nonneg_thm l1pos_thm
|
|
674 |
val (thm1, basis1) = powr_expansion ectxt (a, b, basis)
|
|
675 |
val (thm2, basis2) = powr_expansion ectxt (lift basis1 c, lift basis1 d, basis1)
|
|
676 |
val thm1 = lift basis2 thm1
|
|
677 |
in
|
|
678 |
((thm1, thm2, powr_bounds_thm n OF (l1pos_thm :: thms @ in_bounds_thms)), basis2)
|
|
679 |
end
|
|
680 |
in
|
|
681 |
case sgns of
|
|
682 |
((_, true), _, (_, true), _) =>
|
|
683 |
f 0 false (l1, l2) (u1, u2) [mk_nonneg_thm l1sgn_thm, mk_nonneg_thm l2sgn_thm]
|
|
684 |
| (_, (true, _), (_, true), _) =>
|
|
685 |
f 1 false (l1, u2) (u1, l2) [mk_nonpos_thm u1sgn_thm, mk_nonneg_thm l2sgn_thm]
|
|
686 |
| ((_, true), _, _, (true, _)) =>
|
|
687 |
f 2 false (u1, l2) (l1, u2) [mk_nonneg_thm l1sgn_thm, mk_nonpos_thm u2sgn_thm]
|
|
688 |
| (_, (true, _), _, (true, _)) =>
|
|
689 |
f 3 true (u1, u2) (l1, l2) [mk_nonpos_thm u1sgn_thm, mk_nonpos_thm u2sgn_thm]
|
|
690 |
| ((true, _), (_, true), (_, true), _) =>
|
|
691 |
f 4 false (l1, u2) (u1, u2)
|
|
692 |
[mk_nonpos_thm l1sgn_thm, mk_nonneg_thm u1sgn_thm, mk_nonneg_thm l2sgn_thm]
|
|
693 |
| ((true, _), (_, true), _, (true, _)) =>
|
|
694 |
f 5 true (u1, l2) (l1, l2)
|
|
695 |
[mk_nonpos_thm l1sgn_thm, mk_nonneg_thm u1sgn_thm, mk_nonpos_thm u2sgn_thm]
|
|
696 |
| ((_, true), _, (true, _), (_, true)) =>
|
|
697 |
f 6 false (u1, l2) (u1, u2)
|
|
698 |
[mk_nonneg_thm l1sgn_thm, mk_nonpos_thm l2sgn_thm, mk_nonneg_thm u2sgn_thm]
|
|
699 |
| (_, (true, _), (true, _), (_, true)) =>
|
|
700 |
f 7 true (l1, u2) (l1, l2)
|
|
701 |
[mk_nonpos_thm u1sgn_thm, mk_nonpos_thm l2sgn_thm, mk_nonneg_thm u2sgn_thm]
|
|
702 |
| ((true, _), (_, true), (true, _), (_, true)) =>
|
|
703 |
let
|
|
704 |
val _ = do_force_pos ()
|
|
705 |
val (l1u2, basis1) = powr_expansion ectxt (l1, u2, basis)
|
|
706 |
val (u1l2, basis2) = powr_expansion ectxt (lift basis1 u1, lift basis1 l2, basis1)
|
|
707 |
val (l1l2, basis3) = powr_expansion ectxt (lift basis2 l1, lift basis2 l2, basis2)
|
|
708 |
val (u1u2, basis4) = powr_expansion ectxt (lift basis3 u1, lift basis3 u2, basis3)
|
|
709 |
val [l1u2, u1l2, l1l2] = map (lift basis4) [l1u2, u1l2, l1l2]
|
|
710 |
(* TODO The bases might blow up unnecessarily a bit here *)
|
|
711 |
val (l, lthm1, lthm2) = find_smaller_expansion ectxt (l1u2, u1l2, basis4)
|
|
712 |
val (u, uthm1, uthm2) = find_greater_expansion ectxt (l1l2, u1u2, basis4)
|
|
713 |
in
|
|
714 |
((l, u, powr_bounds_thm 8 OF
|
|
715 |
([l1pos_thm, mk_nonpos_thm l1sgn_thm, mk_nonneg_thm u1sgn_thm, mk_nonpos_thm l2sgn_thm,
|
|
716 |
mk_nonneg_thm u2sgn_thm, lthm1, lthm2, uthm1, uthm2] @ in_bounds_thms)), basis4)
|
|
717 |
end
|
|
718 |
|
|
719 |
| _ => raise Match
|
|
720 |
end
|
|
721 |
|
|
722 |
fun powr_expansion_bounds_aux ectxt basis (Exact thm1) (Exact thm2) =
|
|
723 |
powr_expansion ectxt (thm1, thm2, basis) |> apfst Exact
|
|
724 |
| powr_expansion_bounds_aux ectxt basis (Bounds (SOME l1, SOME u1)) (Exact thm2) =
|
|
725 |
powr_expansion_bounds_right ectxt basis (l1, u1) (determine_sign ectxt (thm2, basis))
|
|
726 |
|> apfst convert_bounds
|
|
727 |
| powr_expansion_bounds_aux ectxt basis (Exact thm1) (Bounds (SOME l2, SOME u2)) =
|
|
728 |
powr_expansion_bounds_left ectxt basis thm1 (l2, u2)
|
|
729 |
|> apfst convert_bounds
|
|
730 |
| powr_expansion_bounds_aux ectxt basis (Bounds (SOME l1, SOME u1)) (Bounds (SOME l2, SOME u2)) =
|
|
731 |
let
|
|
732 |
fun prep (thm, le_thm) =
|
|
733 |
case determine_sign ectxt (thm, basis) of
|
|
734 |
(thm, sgn_thm, sgns) => (thm, le_thm, sgn_thm, sgns)
|
|
735 |
in
|
|
736 |
powr_expansion_bounds_2 ectxt basis (prep l1, prep u1) (prep l2, prep u2)
|
|
737 |
|> apfst convert_bounds
|
|
738 |
end
|
|
739 |
| powr_expansion_bounds_aux _ basis _ _ = (Bounds (NONE, NONE), basis)
|
|
740 |
|
|
741 |
fun powr_expansion_bounds ectxt basis bnds1 bnds2 =
|
|
742 |
case ev_zeroness_oracle ectxt (get_expanded_fun_bounds bnds1) of
|
|
743 |
SOME zero_thm =>
|
|
744 |
let
|
|
745 |
val t = Thm.cterm_of (Lazy_Eval.get_ctxt ectxt) (get_expanded_fun_bounds bnds2)
|
|
746 |
val thm = @{thm expands_to_powr_0} OF
|
|
747 |
[zero_thm, Thm.reflexive t, get_basis_wf_thm basis, mk_expansion_level_eq_thm basis]
|
|
748 |
in
|
|
749 |
(Exact thm, basis)
|
|
750 |
end
|
|
751 |
| NONE => powr_expansion_bounds_aux ectxt basis bnds1 bnds2
|
|
752 |
|
|
753 |
val powr_nat_bounds_transfer_le = @{thms powr_nat_bounds_transfer_le[eventuallized]}
|
|
754 |
fun powr_nat_bounds_transfer_le' n = List.nth (powr_nat_bounds_transfer_le, n - 1)
|
|
755 |
|
|
756 |
fun powr_nat_expansion_bounds ectxt basis bnds1 bnds2 =
|
|
757 |
let
|
|
758 |
fun aux (Exact thm1) (Exact thm2) =
|
|
759 |
apfst Exact (powr_nat_expansion ectxt (thm1, thm2, basis))
|
|
760 |
| aux bnds1 bnds2 =
|
|
761 |
case get_lower_bound bnds1 of
|
|
762 |
NONE => (Bounds (NONE, NONE), basis)
|
|
763 |
| SOME (lthm1, ge_thm1) =>
|
|
764 |
let
|
|
765 |
val (lthm1, l1_sgn_thm, sgns1) = determine_sign ectxt (lthm1, basis)
|
|
766 |
val bnds1 =
|
|
767 |
case bnds1 of
|
|
768 |
Exact _ => Exact lthm1
|
|
769 |
| Bounds (SOME (_, ge_thm), upper) => Bounds (SOME (lthm1, ge_thm), upper)
|
|
770 |
| _ => raise Match
|
|
771 |
val _ = if not (snd sgns1) then
|
|
772 |
raise TERM ("Unexpected sign in powr_nat_expansion_bounds", []) else ()
|
|
773 |
val (bnds, basis') = powr_expansion_bounds ectxt basis bnds1 bnds2
|
|
774 |
val lower = Option.map (apsnd (fn ge_thm' =>
|
|
775 |
@{thm powr_nat_bounds_transfer_ge[eventuallized]} OF
|
|
776 |
[mk_nonneg_thm l1_sgn_thm, ge_thm1, ge_thm'])) (get_lower_bound bnds)
|
|
777 |
fun determine_sign' NONE = NONE
|
|
778 |
| determine_sign' (SOME (thm, le_thm)) =
|
|
779 |
case determine_sign ectxt (thm, basis) of
|
|
780 |
(thm, sgn_thm, sgns) => SOME (thm, sgn_thm, sgns, le_thm)
|
|
781 |
fun do_transfer n thms = powr_nat_bounds_transfer_le' n OF thms
|
|
782 |
fun transfer_upper (uthm', le_thm') =
|
|
783 |
if not (fst sgns1) then
|
|
784 |
(uthm', do_transfer 1 [l1_sgn_thm, ge_thm1, le_thm'])
|
|
785 |
else
|
|
786 |
case determine_sign' (get_lower_bound bnds2) of
|
|
787 |
SOME (_, l2_sgn_thm, (false, true), ge_thm2) =>
|
|
788 |
(uthm', do_transfer 2
|
|
789 |
[mk_nonneg_thm l1_sgn_thm, l2_sgn_thm, ge_thm1, ge_thm2, le_thm'])
|
|
790 |
| _ => (
|
|
791 |
case determine_sign' (get_upper_bound bnds2) of
|
|
792 |
SOME (_, u2_sgn_thm, (true, false), le_thm2) =>
|
|
793 |
(uthm', do_transfer 3
|
|
794 |
[mk_nonneg_thm l1_sgn_thm, u2_sgn_thm, ge_thm1, le_thm2, le_thm'])
|
|
795 |
| _ =>
|
|
796 |
let
|
|
797 |
val (uthm'', le_u'_thm1, le_u'_thm2) = find_greater_expansion ectxt
|
69597
|
798 |
(uthm', const_expansion ectxt basis \<^term>\<open>1::real\<close>, basis)
|
68630
|
799 |
in
|
|
800 |
(uthm'', do_transfer 4
|
|
801 |
[mk_nonneg_thm l1_sgn_thm, ge_thm1, le_thm', le_u'_thm1, le_u'_thm2])
|
|
802 |
end)
|
|
803 |
in
|
|
804 |
(Bounds (lower, Option.map transfer_upper (get_upper_bound bnds)), basis')
|
|
805 |
end
|
|
806 |
in
|
|
807 |
case get_lower_bound bnds1 of
|
|
808 |
SOME (lthm, _) =>
|
|
809 |
let
|
|
810 |
val (lthm, _, sgns) = determine_sign ectxt (lthm, basis)
|
|
811 |
val bnds1 =
|
|
812 |
case bnds1 of
|
|
813 |
Exact _ => Exact lthm
|
|
814 |
| Bounds (SOME (_, le_thm), upper) => Bounds (SOME (lthm, le_thm), upper)
|
|
815 |
| _ => raise Match
|
|
816 |
in
|
|
817 |
case sgns of
|
|
818 |
(_, true) => aux bnds1 bnds2
|
|
819 |
| _ =>
|
|
820 |
let
|
|
821 |
val abs_bnds = abs_expansion_bounds ectxt basis bnds1
|
|
822 |
fun transfer (NONE, _) = (Bounds (NONE, NONE), basis)
|
|
823 |
| transfer (SOME (uthm, le_thm), basis) =
|
|
824 |
let
|
|
825 |
val neg_uthm = @{thm expands_to_uminus} OF [get_basis_wf_thm basis, uthm]
|
|
826 |
val [ge_thm, le_thm] =
|
|
827 |
map (fn thm => le_thm RS thm) @{thms powr_nat_bounds_transfer_abs}
|
|
828 |
in
|
|
829 |
(Bounds (SOME (neg_uthm, ge_thm), SOME (uthm, le_thm)), basis)
|
|
830 |
end
|
|
831 |
in
|
|
832 |
aux abs_bnds bnds2
|
|
833 |
|> apfst get_upper_bound (* TODO better bounds possible *)
|
|
834 |
|> transfer
|
|
835 |
end
|
|
836 |
end
|
|
837 |
| _ => (Bounds (NONE, NONE), basis)
|
|
838 |
end
|
|
839 |
|
|
840 |
fun ln_expansion_bounds' ectxt (lthm, ltrimmed_thm, lb_thm) ub basis =
|
|
841 |
let
|
|
842 |
val (lthm', basis') = ln_expansion ectxt ltrimmed_thm lthm basis
|
|
843 |
val wf_thm = get_basis_wf_thm basis
|
|
844 |
val lb_thm' = @{thm expands_to_lb_ln} OF [lthm, ltrimmed_thm, wf_thm, lb_thm]
|
|
845 |
in
|
|
846 |
case ub of
|
|
847 |
NONE => (Bounds (SOME (lthm', lb_thm'), NONE), basis')
|
|
848 |
| SOME (uthm, utrimmed_thm, ub_thm) =>
|
|
849 |
let
|
|
850 |
val lifting = mk_lifting (extract_basis_list uthm) basis'
|
|
851 |
val uthm = lift_expands_to_thm lifting uthm
|
|
852 |
val utrimmed_thm = lift_trimmed_pos_thm lifting utrimmed_thm
|
|
853 |
val (uthm, _, utrimmed_thm) = retrim_pos_expansion ectxt (uthm, basis', utrimmed_thm)
|
|
854 |
val (uthm', basis'') = ln_expansion ectxt utrimmed_thm uthm basis'
|
|
855 |
val lthm' = lift basis'' lthm'
|
|
856 |
val ub_thm' = @{thm expands_to_ub_ln} OF [lthm, ltrimmed_thm, wf_thm, lb_thm, ub_thm]
|
|
857 |
in
|
|
858 |
(Bounds (SOME (lthm', lb_thm'), SOME (uthm', ub_thm')), basis'')
|
|
859 |
end
|
|
860 |
end
|
|
861 |
|
|
862 |
fun floor_expansion_bounds ectxt (bnds, basis) =
|
|
863 |
let
|
|
864 |
val wf_thm = get_basis_wf_thm basis
|
|
865 |
fun mk_lb (exp_thm, le_thm) =
|
|
866 |
let
|
|
867 |
val exp_thm' = @{thm expands_to_minus} OF
|
69597
|
868 |
[wf_thm, exp_thm, const_expansion ectxt basis \<^term>\<open>1::real\<close>]
|
68630
|
869 |
val le_thm = @{thm rfloor_bound(1)} OF [le_thm]
|
|
870 |
in
|
|
871 |
(exp_thm', le_thm)
|
|
872 |
end
|
|
873 |
val mk_ub = apsnd (fn thm => @{thm rfloor_bound(2)} OF [thm])
|
|
874 |
val bnds' =
|
|
875 |
Bounds (Option.map mk_lb (get_lower_bound bnds), Option.map mk_ub (get_upper_bound bnds))
|
|
876 |
in
|
|
877 |
(bnds', basis)
|
|
878 |
end
|
|
879 |
|
|
880 |
fun ceiling_expansion_bounds ectxt (bnds, basis) =
|
|
881 |
let
|
|
882 |
val wf_thm = get_basis_wf_thm basis
|
|
883 |
fun mk_ub (exp_thm, le_thm) =
|
|
884 |
let
|
|
885 |
val exp_thm' = @{thm expands_to_add} OF
|
69597
|
886 |
[wf_thm, exp_thm, const_expansion ectxt basis \<^term>\<open>1::real\<close>]
|
68630
|
887 |
val le_thm = @{thm rceil_bound(2)} OF [le_thm]
|
|
888 |
in
|
|
889 |
(exp_thm', le_thm)
|
|
890 |
end
|
|
891 |
val mk_lb = apsnd (fn thm => @{thm rceil_bound(1)} OF [thm])
|
|
892 |
val bnds' =
|
|
893 |
Bounds (Option.map mk_lb (get_lower_bound bnds), Option.map mk_ub (get_upper_bound bnds))
|
|
894 |
in
|
|
895 |
(bnds', basis)
|
|
896 |
end
|
|
897 |
|
|
898 |
fun natmod_expansion_bounds _ (Bounds (NONE, NONE), _, _) = Bounds (NONE, NONE)
|
|
899 |
| natmod_expansion_bounds _ (_, Bounds (NONE, NONE), _) = Bounds (NONE, NONE)
|
|
900 |
| natmod_expansion_bounds ectxt (bnds1, bnds2, basis) =
|
|
901 |
let
|
|
902 |
val (f, g) = apply2 (Thm.reflexive o Thm.cterm_of (Lazy_Eval.get_ctxt ectxt) o
|
|
903 |
get_expanded_fun_bounds) (bnds1, bnds2)
|
|
904 |
val ge_lower_thm = @{thm natmod_trivial_lower_bound} OF [f, g]
|
|
905 |
fun minus1 thm = @{thm expands_to_minus} OF
|
69597
|
906 |
[get_basis_wf_thm basis, thm, const_expansion ectxt basis \<^term>\<open>1::real\<close>]
|
68630
|
907 |
fun find_upper uthm1 le1_thm u_nonneg_thm =
|
|
908 |
let
|
|
909 |
val upper1 = (uthm1, @{thm natmod_upper_bound'} OF [g, u_nonneg_thm, le1_thm])
|
|
910 |
val upper2 =
|
|
911 |
case (get_lower_bound bnds2, get_upper_bound bnds2) of
|
|
912 |
(SOME (lthm2, ge2_thm), SOME (uthm2, le2_thm)) => (
|
|
913 |
case determine_sign ectxt (minus1 lthm2, basis) of
|
|
914 |
(_, sgn_thm, (_, true)) => SOME (minus1 uthm2,
|
|
915 |
@{thm natmod_upper_bound} OF [f, ge2_thm, le2_thm, mk_nonneg_thm sgn_thm])
|
|
916 |
| _ => NONE)
|
|
917 |
| _ => NONE
|
|
918 |
in
|
|
919 |
case upper2 of
|
|
920 |
NONE => upper1
|
|
921 |
| SOME upper2 =>
|
|
922 |
case compare_expansions ectxt (fst upper1, fst upper2, basis) of
|
|
923 |
(GREATER, _, _, _) => upper2
|
|
924 |
| _ => upper1
|
|
925 |
end
|
|
926 |
in
|
|
927 |
case get_upper_bound bnds1 of
|
|
928 |
NONE => Bounds (SOME (zero_expansion basis, ge_lower_thm) , NONE)
|
|
929 |
| SOME (uthm1, le1_thm) =>
|
|
930 |
case determine_sign ectxt (uthm1, basis) of
|
|
931 |
(_, sgn_thm, (true, _)) => Exact (@{thm expands_to_natmod_nonpos} OF
|
|
932 |
[g, mk_nonpos_thm sgn_thm, le1_thm, zero_expansion basis])
|
|
933 |
| (uthm1, sgn_thm, (_, true)) =>
|
|
934 |
Bounds (SOME (zero_expansion basis, ge_lower_thm),
|
|
935 |
SOME (find_upper uthm1 le1_thm (mk_nonneg_thm sgn_thm)))
|
|
936 |
| _ => raise TERM ("Unexpected result in natmod_expansion_bounds", [])
|
|
937 |
end
|
|
938 |
|
|
939 |
fun sin_cos_expansion thm _ [] =
|
|
940 |
(thm RS @{thm expands_to_sin_real}, thm RS @{thm expands_to_cos_real})
|
|
941 |
| sin_cos_expansion thm basis ((IsNeg, neg_thm) :: _) =
|
|
942 |
let
|
|
943 |
val neg_thm = @{thm compare_reals_diff_sgnD(1)} OF [neg_thm]
|
|
944 |
val [thm1, thm2] =
|
|
945 |
map (fn thm' => thm' OF [neg_thm, get_basis_wf_thm basis, thm])
|
|
946 |
@{thms expands_to_sin_ms_neg_exp expands_to_cos_ms_neg_exp}
|
|
947 |
in
|
|
948 |
(thm1, thm2)
|
|
949 |
end
|
|
950 |
| sin_cos_expansion thm basis ((IsZero, zero_thm) :: e_thms) =
|
|
951 |
let
|
|
952 |
val zero_thm = @{thm compare_reals_diff_sgnD(2)} OF [zero_thm]
|
|
953 |
val thm' = expands_to_hd thm
|
|
954 |
val (sin_thm, cos_thm) = (sin_cos_expansion thm' (tl_basis basis) e_thms)
|
|
955 |
fun mk_thm thm' =
|
|
956 |
(thm' OF [zero_thm, get_basis_wf_thm basis, thm, sin_thm, cos_thm]) |> solve_eval_eq
|
|
957 |
val [thm1, thm2] =
|
|
958 |
map mk_thm @{thms expands_to_sin_ms_zero_exp expands_to_cos_ms_zero_exp}
|
|
959 |
in
|
|
960 |
(thm1, thm2)
|
|
961 |
end
|
|
962 |
| sin_cos_expansion _ _ _ = raise Match
|
|
963 |
|
|
964 |
fun ln_expansion_bounds ectxt (Exact thm, basis) =
|
|
965 |
let
|
|
966 |
val (thm, _, trimmed_thm) = trim_expansion true (SOME Pos_Trim) ectxt (thm, basis)
|
|
967 |
in
|
|
968 |
case trimmed_thm of
|
|
969 |
NONE => raise TERM ("ln_expansion_bounds", [get_expanded_fun thm])
|
|
970 |
| SOME trimmed_thm =>
|
|
971 |
ln_expansion ectxt trimmed_thm thm basis |> apfst Exact
|
|
972 |
end
|
|
973 |
| ln_expansion_bounds _ (Bounds (NONE, _), _) =
|
|
974 |
raise TERM ("ln_expansion_bounds", [])
|
|
975 |
| ln_expansion_bounds ectxt (Bounds (SOME (lthm, lb_thm), ub), basis) =
|
|
976 |
let
|
|
977 |
fun trim thm = trim_expansion true (SOME Pos_Trim) ectxt (thm, basis)
|
|
978 |
val (lthm, _, trimmed_thm) = trim lthm
|
|
979 |
val ub =
|
|
980 |
Option.mapPartial (fn (uthm, ub_thm) =>
|
|
981 |
case trim uthm of
|
|
982 |
(uthm, _, SOME trimmed_thm) => SOME (uthm, trimmed_thm, ub_thm)
|
|
983 |
| _ => NONE)
|
|
984 |
ub
|
|
985 |
in
|
|
986 |
case trimmed_thm of
|
|
987 |
NONE => raise TERM ("ln_expansion_bounds", [get_expanded_fun lthm])
|
|
988 |
| SOME trimmed_thm => ln_expansion_bounds' ectxt (lthm, trimmed_thm, lb_thm) ub basis
|
|
989 |
end
|
|
990 |
|
|
991 |
fun powr_const_expansion_bounds ectxt (Exact thm, p, basis) =
|
|
992 |
Exact (powr_const_expansion ectxt (thm, p, basis))
|
|
993 |
| powr_const_expansion_bounds _ (Bounds (NONE, NONE), _, _) = Bounds (NONE, NONE)
|
|
994 |
| powr_const_expansion_bounds ectxt (bnds as Bounds (NONE, _), p, basis) =
|
|
995 |
Bounds (SOME (zero_expansion basis, @{thm eventually_powr_const_nonneg} OF
|
|
996 |
map (Thm.reflexive o Thm.cterm_of (Lazy_Eval.get_ctxt ectxt))
|
|
997 |
[get_expanded_fun_bounds bnds, p]), NONE)
|
|
998 |
| powr_const_expansion_bounds ectxt (bnds as Bounds (SOME (lthm, ge_thm), upper), p, basis) =
|
|
999 |
let
|
|
1000 |
val (lthm, lsgn_thm, sgns) = determine_sign ectxt (lthm, basis)
|
|
1001 |
val _ = if snd sgns then ()
|
|
1002 |
else raise TERM ("Negative base for powr.", [])
|
|
1003 |
val (sgn, SOME sgn_thm) = zeroness_oracle true (SOME Sgn_Trim) ectxt p
|
|
1004 |
in
|
|
1005 |
if sgn = IsNeg andalso fst sgns then
|
|
1006 |
Bounds (SOME (zero_expansion basis,
|
|
1007 |
@{thm eventually_powr_const_nonneg} OF
|
|
1008 |
map (Thm.reflexive o Thm.cterm_of (Lazy_Eval.get_ctxt ectxt))
|
|
1009 |
[get_expanded_fun_bounds bnds, p]), NONE)
|
|
1010 |
else
|
|
1011 |
let
|
|
1012 |
val sgn_thm =
|
|
1013 |
case sgn of
|
|
1014 |
IsPos => sgn_thm RS @{thm less_imp_le}
|
|
1015 |
| IsZero => sgn_thm RS @{thm eq_zero_imp_nonneg}
|
|
1016 |
| IsNeg => sgn_thm RS @{thm less_imp_le}
|
|
1017 |
| _ => raise TERM ("Unexpected zeroness result in powr_const_expansion_bounds", [])
|
|
1018 |
val lthm' = powr_const_expansion ectxt (lthm, p, basis)
|
|
1019 |
val lbnd = (lthm',
|
|
1020 |
if sgn <> IsNeg then
|
|
1021 |
@{thm eventually_powr_const_mono_nonneg[OF _ _ eventually_le_self]} OF
|
|
1022 |
[sgn_thm, mk_nonneg_thm lsgn_thm, ge_thm]
|
|
1023 |
else
|
|
1024 |
@{thm eventually_powr_const_mono_nonpos[OF _ _ eventually_le_self]} OF
|
|
1025 |
[sgn_thm, lsgn_thm, ge_thm])
|
|
1026 |
fun transfer_upper_bound (uthm, le_thm) =
|
|
1027 |
(powr_const_expansion ectxt (uthm, p, basis),
|
|
1028 |
if sgn <> IsNeg then
|
|
1029 |
@{thm eventually_powr_const_mono_nonneg} OF
|
|
1030 |
[sgn_thm, mk_nonneg_thm lsgn_thm, ge_thm, le_thm]
|
|
1031 |
else
|
|
1032 |
@{thm eventually_powr_const_mono_nonpos} OF
|
|
1033 |
[sgn_thm, lsgn_thm, ge_thm, le_thm])
|
|
1034 |
in
|
|
1035 |
Bounds ((SOME lbnd, Option.map transfer_upper_bound upper) |>
|
|
1036 |
(if sgn = IsNeg then swap else I))
|
|
1037 |
end
|
|
1038 |
end
|
|
1039 |
handle Bind => raise TERM ("Unexpected zeroness result in powr_const_expansion_bounds", [])
|
|
1040 |
|
|
1041 |
|
|
1042 |
(* TODO stub *)
|
|
1043 |
fun nonneg_power_expansion_bounds ectxt (Bounds (SOME (lthm, ge_thm), upper), n, basis) =
|
|
1044 |
let
|
|
1045 |
val (lthm, lsgn_thm, l1sgns) = determine_sign ectxt (lthm, basis)
|
|
1046 |
val _ = if not (snd l1sgns) then
|
|
1047 |
raise TERM ("Unexpected zeroness result in nonneg_power_expansion_bounds", []) else ()
|
|
1048 |
val nonneg_thm = mk_nonneg_thm lsgn_thm
|
|
1049 |
val ctxt = Lazy_Eval.get_ctxt ectxt
|
|
1050 |
val n_thm = Thm.reflexive (Thm.cterm_of ctxt n)
|
|
1051 |
val lbnd =
|
|
1052 |
(power_expansion ectxt (lthm, n, basis),
|
|
1053 |
@{thm eventually_power_mono[OF _ eventually_le_self]} OF
|
|
1054 |
[nonneg_thm, ge_thm, n_thm])
|
|
1055 |
fun transfer_upper (uthm, le_thm) =
|
|
1056 |
(power_expansion ectxt (uthm, n, basis),
|
|
1057 |
@{thm eventually_power_mono} OF
|
|
1058 |
[nonneg_thm, ge_thm, le_thm, n_thm])
|
|
1059 |
in
|
|
1060 |
Bounds (SOME lbnd, Option.map transfer_upper upper)
|
|
1061 |
end
|
|
1062 |
| nonneg_power_expansion_bounds _ _ = Bounds (NONE, NONE)
|
|
1063 |
|
|
1064 |
fun odd_power_expansion_bounds ectxt odd_thm (bnds, n, basis) =
|
|
1065 |
let
|
|
1066 |
fun transfer (thm, le_thm) =
|
|
1067 |
(power_expansion ectxt (thm, n, basis),
|
|
1068 |
@{thm eventually_mono_power_odd} OF [odd_thm, le_thm])
|
|
1069 |
in
|
|
1070 |
bnds |> apply2 (Option.map transfer) |> Bounds
|
|
1071 |
end
|
|
1072 |
|
|
1073 |
fun get_parity' ectxt t =
|
|
1074 |
let
|
|
1075 |
(* TODO: Throw a tactic at it *)
|
|
1076 |
val ctxt = Lazy_Eval.get_ctxt ectxt
|
|
1077 |
val par = get_parity (Thm.cterm_of ctxt t)
|
|
1078 |
fun is_unknown Unknown_Parity = true
|
|
1079 |
| is_unknown _ = false
|
|
1080 |
val _ =
|
|
1081 |
if not (is_unknown par) orelse not (#verbose (#ctxt ectxt)) then () else
|
|
1082 |
let
|
|
1083 |
val p = Pretty.str ("real_asymp failed to determine whether the following term " ^
|
|
1084 |
"is even or odd:")
|
|
1085 |
val p = Pretty.chunks [p, Pretty.indent 2 (Syntax.pretty_term ctxt t)]
|
|
1086 |
in
|
|
1087 |
Pretty.writeln p
|
|
1088 |
end
|
|
1089 |
in
|
|
1090 |
par
|
|
1091 |
end
|
|
1092 |
|
|
1093 |
fun reflexive ectxt t = Thm.reflexive (Thm.cterm_of (Lazy_Eval.get_ctxt ectxt) t)
|
|
1094 |
|
|
1095 |
fun unknown_parity_power_expansion_lower_bound ectxt ((SOME (lthm, ge_thm), _), n, basis) =
|
|
1096 |
let
|
|
1097 |
val lpow_thm = power_expansion ectxt (lthm, n, basis)
|
|
1098 |
val (lthm', le_thm1, le_thm2) =
|
|
1099 |
find_smaller_expansion ectxt (lpow_thm, zero_expansion basis, basis)
|
|
1100 |
in
|
|
1101 |
SOME (lthm', @{thm eventually_lower_bound_power_indet} OF [ge_thm, le_thm1, le_thm2])
|
|
1102 |
end
|
|
1103 |
| unknown_parity_power_expansion_lower_bound _ _ = NONE
|
|
1104 |
|
|
1105 |
fun unknown_parity_power_expansion_upper_bound ectxt
|
|
1106 |
((SOME (lthm, ge_thm), SOME (uthm, le_thm)), n, basis) =
|
|
1107 |
let
|
|
1108 |
val lthm = @{thm expands_to_uminus} OF [get_basis_wf_thm basis, lthm]
|
|
1109 |
val (uthm', ge_thm1, ge_thm2) =
|
|
1110 |
find_greater_expansion ectxt (lthm, uthm, basis)
|
|
1111 |
val uthm' = power_expansion ectxt (uthm', n, basis)
|
|
1112 |
in
|
|
1113 |
SOME (uthm', @{thm eventually_upper_bound_power_indet} OF
|
|
1114 |
[ge_thm, le_thm, ge_thm1, ge_thm2, reflexive ectxt n])
|
|
1115 |
end
|
|
1116 |
| unknown_parity_power_expansion_upper_bound _ _ = NONE
|
|
1117 |
|
|
1118 |
fun even_power_expansion_bounds ectxt even_thm (bnds, n, basis) =
|
|
1119 |
let
|
|
1120 |
fun handle_indet_case bnds =
|
|
1121 |
let
|
|
1122 |
val lower = (zero_expansion basis, @{thm eventually_lower_bound_power_even_indet} OF
|
|
1123 |
[even_thm, reflexive ectxt (get_expanded_fun_bounds (Bounds bnds))])
|
|
1124 |
val upper = unknown_parity_power_expansion_upper_bound ectxt (bnds, n, basis)
|
|
1125 |
in
|
|
1126 |
(SOME lower, upper)
|
|
1127 |
end
|
|
1128 |
in
|
|
1129 |
case snd bnds of
|
|
1130 |
NONE => handle_indet_case bnds
|
|
1131 |
| SOME (uthm, le_thm) =>
|
|
1132 |
let
|
|
1133 |
val (uthm, usgn_thm, usgns) = determine_sign ectxt (uthm, basis)
|
|
1134 |
val bnds = (fst bnds, SOME (uthm, le_thm))
|
|
1135 |
in
|
|
1136 |
if fst usgns then
|
|
1137 |
let
|
|
1138 |
val lthm' = power_expansion ectxt (uthm, n, basis)
|
|
1139 |
val ge_thm' = @{thm eventually_lower_bound_power_even_nonpos} OF
|
|
1140 |
[even_thm, mk_nonpos_thm usgn_thm, le_thm]
|
|
1141 |
fun transfer_lower_bound (lthm, ge_thm) =
|
|
1142 |
(power_expansion ectxt (lthm, n, basis),
|
|
1143 |
@{thm eventually_upper_bound_power_even_nonpos} OF
|
|
1144 |
[even_thm, mk_nonpos_thm usgn_thm, ge_thm, le_thm])
|
|
1145 |
in
|
|
1146 |
(SOME (lthm', ge_thm'), Option.map transfer_lower_bound (fst bnds))
|
|
1147 |
end
|
|
1148 |
else
|
|
1149 |
handle_indet_case bnds
|
|
1150 |
end
|
|
1151 |
end
|
|
1152 |
|
|
1153 |
fun power_expansion_bounds ectxt (Exact thm, n, basis) =
|
|
1154 |
Exact (power_expansion ectxt (thm, n, basis))
|
|
1155 |
| power_expansion_bounds ectxt (Bounds bnds, n, basis) =
|
|
1156 |
let
|
|
1157 |
val parity = get_parity' ectxt n
|
|
1158 |
fun handle_non_nonneg_case bnds = Bounds (
|
|
1159 |
case parity of
|
|
1160 |
Odd _ => raise Match
|
|
1161 |
| Even even_thm => even_power_expansion_bounds ectxt even_thm (bnds, n, basis)
|
|
1162 |
| Unknown_Parity =>
|
|
1163 |
(unknown_parity_power_expansion_lower_bound ectxt (bnds, n, basis),
|
|
1164 |
unknown_parity_power_expansion_upper_bound ectxt (bnds, n, basis)))
|
|
1165 |
in
|
|
1166 |
case parity of
|
|
1167 |
Odd odd_thm => odd_power_expansion_bounds ectxt odd_thm (bnds, n, basis)
|
|
1168 |
| _ =>
|
|
1169 |
case fst bnds of
|
|
1170 |
NONE => handle_non_nonneg_case bnds
|
|
1171 |
| SOME (lthm, ge_thm) =>
|
|
1172 |
let
|
|
1173 |
val (lthm, lsgn_thm, lsgns) = determine_sign ectxt (lthm, basis)
|
|
1174 |
val bnds = (SOME (lthm, ge_thm), snd bnds)
|
|
1175 |
in
|
|
1176 |
if snd lsgns then
|
|
1177 |
let
|
|
1178 |
val nthm = reflexive ectxt n
|
|
1179 |
val lthm' = power_expansion ectxt (lthm, n, basis)
|
|
1180 |
val ge_thm' = @{thm eventually_power_mono[OF _ eventually_le_self]} OF
|
|
1181 |
[mk_nonneg_thm lsgn_thm, ge_thm, nthm]
|
|
1182 |
fun transfer_upper (uthm, le_thm) =
|
|
1183 |
(power_expansion ectxt (uthm, n, basis),
|
|
1184 |
@{thm eventually_power_mono} OF
|
|
1185 |
[mk_nonneg_thm lsgn_thm, ge_thm, le_thm, nthm])
|
|
1186 |
in
|
|
1187 |
Bounds (SOME (lthm', ge_thm'), Option.map transfer_upper (snd bnds))
|
|
1188 |
end
|
|
1189 |
else
|
|
1190 |
handle_non_nonneg_case bnds
|
|
1191 |
end
|
|
1192 |
end
|
|
1193 |
|
|
1194 |
fun sgn_expansion_bounds ectxt (Exact thm, basis) =
|
|
1195 |
Exact (sgn_expansion ectxt (thm, basis))
|
|
1196 |
| sgn_expansion_bounds ectxt (Bounds bnds, basis) =
|
|
1197 |
let
|
|
1198 |
fun aux (thm, le_thm) =
|
|
1199 |
(sgn_expansion ectxt (thm, basis), mono_bound @{thm mono_sgn_real} le_thm)
|
|
1200 |
val (lower, upper) = apply2 (Option.map aux) bnds
|
|
1201 |
fun get_bound_exp (SOME (thm, _)) = SOME (get_expansion thm)
|
|
1202 |
| get_bound_exp _ = NONE
|
69597
|
1203 |
fun is_const (SOME (Const (\<^const_name>\<open>Multiseries_Expansion.const_expansion\<close>, _) $ c'),
|
68630
|
1204 |
c) = c aconv c'
|
|
1205 |
| is_const _ = false
|
|
1206 |
fun aconv' (SOME a, SOME b) = a aconv b
|
|
1207 |
| aconv' _ = false
|
|
1208 |
in
|
69597
|
1209 |
if is_const (get_bound_exp lower, \<^term>\<open>\<lambda>x::real. 1 :: real\<close>) then
|
68630
|
1210 |
let
|
|
1211 |
val SOME (lthm, ge_thm) = lower
|
|
1212 |
in
|
|
1213 |
Exact (@{thm eventually_sgn_ge_1D} OF [ge_thm, lthm])
|
|
1214 |
end
|
69597
|
1215 |
else if is_const (get_bound_exp upper, \<^term>\<open>\<lambda>x::real. -1 :: real\<close>) then
|
68630
|
1216 |
let
|
|
1217 |
val SOME (uthm, le_thm) = upper
|
|
1218 |
in
|
|
1219 |
Exact (@{thm eventually_sgn_le_neg1D} OF [le_thm, uthm])
|
|
1220 |
end
|
|
1221 |
else if aconv' (apply2 get_bound_exp (lower, upper)) then
|
|
1222 |
let
|
|
1223 |
val (SOME (lthm, ge_thm), SOME (uthm, le_thm)) = (lower, upper)
|
|
1224 |
in
|
|
1225 |
Exact (@{thm expands_to_squeeze} OF [ge_thm, le_thm, lthm, uthm])
|
|
1226 |
end
|
|
1227 |
else
|
|
1228 |
Bounds (lower, upper)
|
|
1229 |
end
|
|
1230 |
|
|
1231 |
fun sin_cos_expansion_bounds sin ectxt e basis =
|
|
1232 |
let
|
|
1233 |
val f = if sin then fst else snd
|
|
1234 |
fun trivial_bounds basis =
|
|
1235 |
mk_trivial_bounds ectxt (expr_to_term e)
|
|
1236 |
(if sin then @{thm trivial_bounds_sin} else @{thm trivial_bounds_cos}) basis
|
|
1237 |
fun mk_expansion (thm, basis') =
|
|
1238 |
case trim_expansion_while_pos ectxt (thm, basis') of
|
|
1239 |
(_, Trimmed _, _) => (trivial_bounds basis, basis)
|
|
1240 |
| (thm, Aborted _, e_thms) =>
|
|
1241 |
(Exact (f (sin_cos_expansion thm basis' e_thms)), basis')
|
|
1242 |
in
|
|
1243 |
case expand_bounds' ectxt e basis of
|
|
1244 |
(Exact thm, basis') => mk_expansion (thm, basis')
|
|
1245 |
| _ => (trivial_bounds basis, basis)
|
|
1246 |
end
|
|
1247 |
|
|
1248 |
and mono_expansion mono_thm expand_fun ectxt e basis =
|
|
1249 |
case expand_bounds' ectxt e basis of
|
|
1250 |
(Exact thm, basis) => expand_fun ectxt thm basis |> apfst Exact
|
|
1251 |
| (Bounds (SOME (lthm, lb_thm), NONE), basis) =>
|
|
1252 |
expand_fun ectxt lthm basis
|
|
1253 |
|> apfst (fn lthm => Bounds (SOME (lthm, mono_bound mono_thm lb_thm), NONE))
|
|
1254 |
| (Bounds (NONE, SOME (uthm, ub_thm)), basis) =>
|
|
1255 |
expand_fun ectxt uthm basis
|
|
1256 |
|> apfst (fn uthm => Bounds (NONE, SOME (uthm, mono_bound mono_thm ub_thm)))
|
|
1257 |
| (Bounds (SOME (lthm, lb_thm), SOME (uthm, ub_thm)), basis) =>
|
|
1258 |
let
|
|
1259 |
val (lthm', basis') = expand_fun ectxt lthm basis
|
|
1260 |
val (uthm', basis'') = expand_fun ectxt (lift basis' uthm) basis'
|
|
1261 |
val lthm' = lift basis'' lthm'
|
|
1262 |
val (lb_thm', ub_thm') = apply2 (mono_bound mono_thm) (lb_thm, ub_thm)
|
|
1263 |
in
|
|
1264 |
(Bounds (SOME (lthm', lb_thm'), SOME (uthm', ub_thm')), basis'')
|
|
1265 |
end
|
|
1266 |
| x => x
|
|
1267 |
|
|
1268 |
and minmax_expansion_bounds max thm ectxt (e1, e2) basis =
|
|
1269 |
case try_prove_ev_eq ectxt (apply2 expr_to_term (e1, e2)) of
|
|
1270 |
SOME eq_thm =>
|
|
1271 |
let
|
|
1272 |
val eq_thm' =
|
|
1273 |
eq_thm RS (if max then @{thm max_eventually_eq} else @{thm min_eventually_eq})
|
|
1274 |
in
|
|
1275 |
expand_bounds' ectxt e1 basis |> apfst (cong_bounds eq_thm')
|
|
1276 |
end
|
|
1277 |
| NONE =>
|
|
1278 |
let
|
|
1279 |
val (bnds1, basis') = expand_bounds' ectxt e1 basis
|
|
1280 |
val (bnds2, basis'') = expand_bounds' ectxt e2 basis'
|
|
1281 |
val bnds1 = lift_bounds basis'' bnds1
|
|
1282 |
fun f (thm1, thm2) =
|
|
1283 |
(if max then max_expansion else min_expansion) ectxt (thm1, thm2, basis'')
|
|
1284 |
fun handle_bound (SOME (exp_thm1, le_thm1), SOME (exp_thm2, le_thm2)) =
|
|
1285 |
SOME (f (exp_thm1, exp_thm2), thm OF [le_thm1, le_thm2])
|
|
1286 |
| handle_bound _ = NONE
|
|
1287 |
val bnds = (bnds1, bnds2)
|
|
1288 |
val bnds =
|
|
1289 |
case (bnds1, bnds2) of
|
|
1290 |
(Exact thm1, Exact thm2) => Exact (f (thm1, thm2))
|
|
1291 |
| _ =>
|
|
1292 |
Bounds (handle_bound (apply2 get_lower_bound bnds),
|
|
1293 |
handle_bound (apply2 get_upper_bound bnds))
|
|
1294 |
in
|
|
1295 |
(bnds, basis'')
|
|
1296 |
end
|
|
1297 |
|
|
1298 |
and expand_bin_bounds swap thms ectxt (e1, e2) basis =
|
|
1299 |
let
|
|
1300 |
val (bnds1, basis') = expand_bounds' ectxt e1 basis
|
|
1301 |
val (bnds2, basis'') = expand_bounds' ectxt e2 basis'
|
|
1302 |
val bnds1 = lift_bounds basis'' bnds1
|
|
1303 |
val bnds = expand_add_bounds swap thms (bnds1, bnds2) basis''
|
|
1304 |
in
|
|
1305 |
(bnds, basis'')
|
|
1306 |
end
|
|
1307 |
|
|
1308 |
and expand_bounds'' ectxt (Add e12) basis =
|
|
1309 |
expand_bin_bounds false @{thms expands_to_add combine_bounds_add} ectxt e12 basis
|
|
1310 |
| expand_bounds'' ectxt (Minus e12) basis =
|
|
1311 |
expand_bin_bounds true @{thms expands_to_minus combine_bounds_diff} ectxt e12 basis
|
|
1312 |
| expand_bounds'' ectxt (Uminus e) basis = (
|
|
1313 |
case expand_bounds' ectxt e basis of
|
|
1314 |
(Exact thm, basis) =>
|
|
1315 |
(Exact (@{thm expands_to_uminus} OF [get_basis_wf_thm basis, thm]), basis)
|
|
1316 |
| (Bounds bnds, basis) =>
|
|
1317 |
let
|
|
1318 |
fun flip (thm1, thm2) =
|
|
1319 |
(@{thm expands_to_uminus} OF [get_basis_wf_thm basis, thm1],
|
|
1320 |
@{thm bounds_uminus} OF [thm2])
|
|
1321 |
in
|
|
1322 |
(Bounds (apply2 (Option.map flip) (swap bnds)), basis)
|
|
1323 |
end)
|
|
1324 |
| expand_bounds'' ectxt (Mult (e1, e2)) basis =
|
|
1325 |
let
|
|
1326 |
val (bnds1, basis') = expand_bounds' ectxt e1 basis
|
|
1327 |
val (bnds2, basis'') = expand_bounds' ectxt e2 basis'
|
|
1328 |
val bnds1 = lift_bounds basis'' bnds1
|
|
1329 |
val bnds = mult_expansion_bounds ectxt basis'' bnds1 bnds2
|
|
1330 |
in
|
|
1331 |
(bnds, basis'')
|
|
1332 |
end
|
|
1333 |
| expand_bounds'' ectxt (Powr (e1, e2)) basis =
|
|
1334 |
let
|
|
1335 |
val (bnds1, basis') = expand_bounds' ectxt e1 basis
|
|
1336 |
val (bnds2, basis'') = expand_bounds' ectxt e2 basis'
|
|
1337 |
val bnds1 = lift_bounds basis'' bnds1
|
|
1338 |
in
|
|
1339 |
powr_expansion_bounds ectxt basis'' bnds1 bnds2
|
|
1340 |
end
|
|
1341 |
| expand_bounds'' ectxt (Powr_Nat (e1, e2)) basis =
|
|
1342 |
let
|
|
1343 |
val (bnds1, basis') = expand_bounds' ectxt e1 basis
|
|
1344 |
val (bnds2, basis'') = expand_bounds' ectxt e2 basis'
|
|
1345 |
val bnds1 = lift_bounds basis'' bnds1
|
|
1346 |
in
|
|
1347 |
powr_nat_expansion_bounds ectxt basis'' bnds1 bnds2
|
|
1348 |
end
|
|
1349 |
| expand_bounds'' ectxt (Powr' (e, p)) basis =
|
|
1350 |
let
|
|
1351 |
val (bnds, basis') = expand_bounds' ectxt e basis
|
|
1352 |
in
|
|
1353 |
(powr_const_expansion_bounds ectxt (bnds, p, basis'), basis')
|
|
1354 |
end
|
|
1355 |
| expand_bounds'' ectxt (Power (e, n)) basis =
|
|
1356 |
let
|
|
1357 |
val (bnds, basis') = expand_bounds' ectxt e basis
|
|
1358 |
in
|
|
1359 |
(power_expansion_bounds ectxt (bnds, n, basis'), basis')
|
|
1360 |
end
|
|
1361 |
| expand_bounds'' ectxt (Root (e, n)) basis =
|
|
1362 |
mono_expansion (reflexive ectxt n RS @{thm mono_root_real})
|
|
1363 |
(fn ectxt => fn thm => fn basis => (root_expansion ectxt (thm, n, basis), basis))
|
|
1364 |
ectxt e basis
|
|
1365 |
| expand_bounds'' ectxt (Inverse e) basis =
|
|
1366 |
let
|
|
1367 |
val (bnds, basis') = expand_bounds' ectxt e basis
|
|
1368 |
in
|
|
1369 |
(inverse_expansion_bounds ectxt basis' bnds, basis')
|
|
1370 |
end
|
|
1371 |
| expand_bounds'' ectxt (Div (e1, e2)) basis =
|
|
1372 |
let
|
|
1373 |
val (bnds1, basis') = expand_bounds' ectxt e1 basis
|
|
1374 |
val (bnds2, basis'') = expand_bounds' ectxt e2 basis'
|
|
1375 |
val bnds1 = lift_bounds basis'' bnds1
|
|
1376 |
in
|
|
1377 |
(divide_expansion_bounds ectxt basis'' bnds1 bnds2, basis'')
|
|
1378 |
end
|
|
1379 |
| expand_bounds'' ectxt (Sin e) basis =
|
|
1380 |
sin_cos_expansion_bounds true ectxt e basis
|
|
1381 |
| expand_bounds'' ectxt (Cos e) basis =
|
|
1382 |
sin_cos_expansion_bounds false ectxt e basis
|
|
1383 |
| expand_bounds'' ectxt (Exp e) basis =
|
|
1384 |
mono_expansion @{thm mono_exp_real} exp_expansion ectxt e basis
|
|
1385 |
| expand_bounds'' ectxt (Ln e) basis =
|
|
1386 |
ln_expansion_bounds ectxt (expand_bounds' ectxt e basis)
|
|
1387 |
| expand_bounds'' ectxt (ExpLn e) basis =
|
|
1388 |
let
|
|
1389 |
val (bnds, basis') = expand_bounds' ectxt e basis
|
|
1390 |
in
|
|
1391 |
case get_lower_bound bnds of
|
|
1392 |
NONE => (Bounds (NONE, NONE), basis)
|
|
1393 |
| SOME (lthm, ge_thm) =>
|
|
1394 |
case trim_expansion true (SOME Pos_Trim) ectxt (lthm, basis') of
|
|
1395 |
(_, _, NONE) => raise TERM ("Non-positive function under logarithm.", [])
|
|
1396 |
| (lthm, _, SOME trimmed_thm) =>
|
|
1397 |
let
|
|
1398 |
val bnds =
|
|
1399 |
case bnds of
|
|
1400 |
Exact _ => Exact lthm
|
|
1401 |
| Bounds (_, upper) => Bounds (SOME (lthm, ge_thm), upper)
|
|
1402 |
val eq_thm = @{thm expands_to_imp_exp_ln_eq} OF
|
|
1403 |
[lthm, ge_thm, trimmed_thm, get_basis_wf_thm basis]
|
|
1404 |
in
|
|
1405 |
(cong_bounds eq_thm bnds, basis')
|
|
1406 |
end
|
|
1407 |
end
|
|
1408 |
| expand_bounds'' ectxt (LnPowr (e1, e2)) basis =
|
|
1409 |
let
|
|
1410 |
val (bnds1, basis') = expand_bounds' ectxt e1 basis
|
|
1411 |
val (bnds2, basis'') = expand_bounds' ectxt e2 basis'
|
|
1412 |
val bnds1 = lift_bounds basis'' bnds1
|
|
1413 |
in
|
|
1414 |
case get_lower_bound bnds1 of
|
|
1415 |
NONE => (Bounds (NONE, NONE), basis)
|
|
1416 |
| SOME (lthm, ge_thm) =>
|
|
1417 |
case trim_expansion true (SOME Pos_Trim) ectxt (lthm, basis'') of
|
|
1418 |
(_, _, NONE) => raise TERM ("Non-positive base for powr.", [])
|
|
1419 |
| (lthm, _, SOME trimmed_thm) =>
|
|
1420 |
let
|
|
1421 |
val bnds1 =
|
|
1422 |
case bnds1 of
|
|
1423 |
Exact _ => Exact lthm
|
|
1424 |
| Bounds (_, upper) => Bounds (SOME (lthm, ge_thm), upper)
|
|
1425 |
val eq_thm = @{thm expands_to_imp_ln_powr_eq} OF
|
|
1426 |
[lthm, ge_thm, trimmed_thm, get_basis_wf_thm basis'']
|
|
1427 |
val (ln_bnds, basis''') = ln_expansion_bounds ectxt (bnds1, basis'')
|
|
1428 |
val bnds2 = lift_bounds basis''' bnds2
|
|
1429 |
val bnds = mult_expansion_bounds ectxt basis''' ln_bnds bnds2
|
|
1430 |
in
|
|
1431 |
(cong_bounds eq_thm bnds, basis''')
|
|
1432 |
end
|
|
1433 |
end
|
|
1434 |
| expand_bounds'' ectxt (Absolute e) basis =
|
|
1435 |
let
|
|
1436 |
val (bnds, basis') = expand_bounds' ectxt e basis
|
|
1437 |
in
|
|
1438 |
(abs_expansion_bounds ectxt basis' bnds, basis')
|
|
1439 |
end
|
|
1440 |
| expand_bounds'' ectxt (Sgn e) basis =
|
|
1441 |
let
|
|
1442 |
val (bnds, basis') = expand_bounds' ectxt e basis
|
|
1443 |
in
|
|
1444 |
(sgn_expansion_bounds ectxt (bnds, basis'), basis')
|
|
1445 |
end
|
|
1446 |
| expand_bounds'' ectxt (Min e12) basis =
|
|
1447 |
minmax_expansion_bounds false @{thm combine_bounds_min} ectxt e12 basis
|
|
1448 |
| expand_bounds'' ectxt (Max e12) basis =
|
|
1449 |
minmax_expansion_bounds true @{thm combine_bounds_max} ectxt e12 basis
|
|
1450 |
| expand_bounds'' ectxt (Floor e) basis =
|
|
1451 |
floor_expansion_bounds ectxt (expand_bounds' ectxt e basis)
|
|
1452 |
| expand_bounds'' ectxt (Ceiling e) basis =
|
|
1453 |
ceiling_expansion_bounds ectxt (expand_bounds' ectxt e basis)
|
|
1454 |
| expand_bounds'' ectxt (Frac e) basis =
|
|
1455 |
(mk_trivial_bounds ectxt (expr_to_term e) @{thm trivial_bounds_frac} basis, basis)
|
|
1456 |
| expand_bounds'' ectxt (NatMod (e1, e2)) basis =
|
|
1457 |
let
|
|
1458 |
val (bnds1, basis') = expand_bounds' ectxt e1 basis
|
|
1459 |
val (bnds2, basis'') = expand_bounds' ectxt e2 basis'
|
|
1460 |
val bnds1 = lift_bounds basis'' bnds1
|
|
1461 |
in
|
|
1462 |
(natmod_expansion_bounds ectxt (bnds1, bnds2, basis''), basis'')
|
|
1463 |
end
|
|
1464 |
| expand_bounds'' ectxt (ArcTan e) basis =
|
|
1465 |
mono_expansion @{thm mono_arctan_real}
|
|
1466 |
(fn ectxt => fn thm => fn basis => (arctan_expansion ectxt basis thm, basis)) ectxt e basis
|
|
1467 |
| expand_bounds'' ectxt e basis =
|
|
1468 |
expand ectxt e basis |> apfst Exact
|
|
1469 |
|
|
1470 |
and expand_bounds' ectxt e basis =
|
|
1471 |
expand_bounds'' ectxt e basis |> apfst (check_bounds e)
|
|
1472 |
|
|
1473 |
fun expand_term_bounds ectxt t basis =
|
|
1474 |
let
|
|
1475 |
val ctxt = Lazy_Eval.get_ctxt ectxt
|
|
1476 |
val (e, eq_thm) = reify ctxt t
|
|
1477 |
val (bounds, basis) = expand_bounds' ectxt e basis
|
|
1478 |
in
|
|
1479 |
(transfer_bounds eq_thm bounds, basis)
|
|
1480 |
end
|
|
1481 |
|
|
1482 |
fun expand_terms_bounds ectxt ts basis =
|
|
1483 |
let
|
|
1484 |
val ctxt = Lazy_Eval.get_ctxt ectxt
|
|
1485 |
val e_eq_thms = map (reify ctxt) ts
|
|
1486 |
fun step (e, eq_thm) (bndss, basis) =
|
|
1487 |
let
|
|
1488 |
val (bnds, basis) = expand_bounds' ectxt e basis
|
|
1489 |
val bnds = transfer_bounds eq_thm bnds
|
|
1490 |
in
|
|
1491 |
(bnds :: bndss, basis)
|
|
1492 |
end
|
|
1493 |
val (thms, basis) = fold step e_eq_thms ([], basis)
|
|
1494 |
fun lift bnds = lift_bounds basis bnds
|
|
1495 |
in
|
|
1496 |
(map lift (rev thms), basis)
|
|
1497 |
end
|
|
1498 |
|
|
1499 |
fun prove_nhds_bounds ectxt (Exact thm, basis) = prove_nhds ectxt (thm, basis)
|
|
1500 |
| prove_nhds_bounds ectxt (Bounds (SOME (lthm, ge_thm), SOME (uthm, le_thm)), basis) =
|
|
1501 |
let
|
|
1502 |
fun extract_limit thm =
|
|
1503 |
thm |> Thm.concl_of |> HOLogic.dest_Trueprop |> dest_comb |> fst |> dest_comb |> snd
|
|
1504 |
|> dest_comb |> snd
|
|
1505 |
val llim_thm = prove_nhds ectxt (lthm, basis)
|
|
1506 |
val ulim_thm = prove_nhds ectxt (uthm, basis)
|
|
1507 |
val (lim1, lim2) = apply2 extract_limit (llim_thm, ulim_thm)
|
|
1508 |
val eq_thm = the (try_prove_real_eq true ectxt (lim1, lim2))
|
|
1509 |
in
|
|
1510 |
@{thm tendsto_sandwich'} OF [ge_thm, le_thm, llim_thm, ulim_thm, eq_thm]
|
|
1511 |
end
|
|
1512 |
| prove_nhds_bounds _ _ = raise TERM ("prove_nhds_bounds", [])
|
|
1513 |
|
|
1514 |
fun prove_at_top_bounds ectxt (Exact thm, basis) = prove_at_top ectxt (thm, basis)
|
|
1515 |
| prove_at_top_bounds ectxt (Bounds (SOME (lthm, ge_thm), _), basis) =
|
|
1516 |
let
|
|
1517 |
val llim_thm = prove_at_top ectxt (lthm, basis)
|
|
1518 |
in
|
|
1519 |
@{thm filterlim_at_top_mono} OF [llim_thm, ge_thm]
|
|
1520 |
end
|
|
1521 |
| prove_at_top_bounds _ _ = raise TERM ("prove_at_top_bounds", [])
|
|
1522 |
|
|
1523 |
fun prove_at_bot_bounds ectxt (Exact thm, basis) = prove_at_bot ectxt (thm, basis)
|
|
1524 |
| prove_at_bot_bounds ectxt (Bounds (_, SOME (uthm, le_thm)), basis) =
|
|
1525 |
let
|
|
1526 |
val ulim_thm = prove_at_bot ectxt (uthm, basis)
|
|
1527 |
in
|
|
1528 |
@{thm filterlim_at_bot_mono} OF [ulim_thm, le_thm]
|
|
1529 |
end
|
|
1530 |
| prove_at_bot_bounds _ _ = raise TERM ("prove_at_bot_bounds", [])
|
|
1531 |
|
|
1532 |
fun prove_at_infinity_bounds ectxt (Exact thm, basis) = prove_at_infinity ectxt (thm, basis)
|
|
1533 |
| prove_at_infinity_bounds ectxt (Bounds (lb, ub), basis) =
|
|
1534 |
let
|
|
1535 |
val wf_thm = get_basis_wf_thm basis
|
|
1536 |
fun assert_nz (SOME (thm, le_thm)) = (
|
|
1537 |
case ev_zeroness_oracle ectxt (get_expanded_fun thm) of
|
|
1538 |
SOME _ => NONE
|
|
1539 |
| NONE => SOME (thm, le_thm))
|
|
1540 |
| assert_nz NONE = NONE
|
|
1541 |
fun lb_at_top (lthm, ge_thm) =
|
|
1542 |
case trim_expansion true (SOME Sgn_Trim) ectxt (lthm, basis) of
|
|
1543 |
(lthm, IsPos, SOME trimmed_thm) => SOME
|
|
1544 |
let
|
|
1545 |
val lim_thm = prove_at_infinity ectxt (lthm, basis)
|
|
1546 |
val pos_thm = @{thm expands_to_imp_eventually_pos} OF [wf_thm, lthm, trimmed_thm]
|
|
1547 |
val lim_thm' =
|
|
1548 |
@{thm filterlim_at_infinity_imp_filterlim_at_top} OF [lim_thm, pos_thm]
|
|
1549 |
in
|
|
1550 |
@{thm filterlim_at_top_imp_at_infinity[OF filterlim_at_top_mono]}
|
|
1551 |
OF [lim_thm', ge_thm]
|
|
1552 |
end
|
|
1553 |
| _ => NONE
|
|
1554 |
fun ub_at_top (uthm, le_thm) =
|
|
1555 |
case trim_expansion true (SOME Sgn_Trim) ectxt (uthm, basis) of
|
|
1556 |
(uthm, IsNeg, SOME trimmed_thm) => SOME
|
|
1557 |
let
|
|
1558 |
val lim_thm = prove_at_infinity ectxt (uthm, basis)
|
|
1559 |
val neg_thm = @{thm expands_to_imp_eventually_neg} OF [wf_thm, uthm, trimmed_thm]
|
|
1560 |
val lim_thm' =
|
|
1561 |
@{thm filterlim_at_infinity_imp_filterlim_at_bot} OF [lim_thm, neg_thm]
|
|
1562 |
in
|
|
1563 |
@{thm filterlim_at_bot_imp_at_infinity[OF filterlim_at_bot_mono]}
|
|
1564 |
OF [lim_thm', le_thm]
|
|
1565 |
end
|
|
1566 |
| _ => NONE
|
|
1567 |
in
|
|
1568 |
case Option.mapPartial lb_at_top (assert_nz lb) of
|
|
1569 |
SOME thm => thm
|
|
1570 |
| NONE =>
|
|
1571 |
case Option.mapPartial ub_at_top (assert_nz ub) of
|
|
1572 |
SOME thm => thm
|
|
1573 |
| NONE => raise TERM ("prove_at_infinity_bounds", [])
|
|
1574 |
end
|
|
1575 |
|
|
1576 |
fun prove_eventually_pos_lower_bound ectxt basis (lthm, ge_thm) =
|
|
1577 |
case trim_expansion true (SOME Sgn_Trim) ectxt (lthm, basis) of
|
|
1578 |
(lthm, IsPos, SOME trimmed_thm) =>
|
|
1579 |
SOME (@{thm eventually_less_le} OF [@{thm expands_to_imp_eventually_pos} OF
|
|
1580 |
[get_basis_wf_thm basis, lthm, trimmed_thm], ge_thm])
|
|
1581 |
| _ => NONE
|
|
1582 |
|
|
1583 |
|
|
1584 |
fun prove_eventually_neg_upper_bound ectxt basis (uthm, le_thm) =
|
|
1585 |
case trim_expansion true (SOME Sgn_Trim) ectxt (uthm, basis) of
|
|
1586 |
(uthm, IsNeg, SOME trimmed_thm) =>
|
|
1587 |
SOME (@{thm eventually_le_less} OF [le_thm, @{thm expands_to_imp_eventually_neg} OF
|
|
1588 |
[get_basis_wf_thm basis, uthm, trimmed_thm]])
|
|
1589 |
| _ => NONE
|
|
1590 |
|
|
1591 |
fun prove_eventually_nonzero_bounds ectxt (Exact thm, basis) = (
|
|
1592 |
case trim_expansion true (SOME Simple_Trim) ectxt (thm, basis) of
|
|
1593 |
(thm, _, SOME trimmed_thm) =>
|
|
1594 |
@{thm expands_to_imp_eventually_nz} OF [get_basis_wf_thm basis, thm, trimmed_thm]
|
|
1595 |
| _ => raise TERM ("prove_eventually_nonzero", []))
|
|
1596 |
| prove_eventually_nonzero_bounds ectxt (Bounds (l, u), basis) =
|
|
1597 |
case Option.mapPartial (prove_eventually_pos_lower_bound ectxt basis) l of
|
|
1598 |
SOME thm => thm RS @{thm eventually_pos_imp_nz}
|
|
1599 |
| NONE =>
|
|
1600 |
case Option.mapPartial (prove_eventually_neg_upper_bound ectxt basis) u of
|
|
1601 |
SOME thm => thm RS @{thm eventually_neg_imp_nz}
|
|
1602 |
| NONE => raise TERM ("prove_eventually_nonzero", [])
|
|
1603 |
|
|
1604 |
fun prove_at_0_bounds ectxt (Exact thm, basis) = prove_at_0 ectxt (thm, basis)
|
|
1605 |
| prove_at_0_bounds ectxt (Bounds bnds, basis) =
|
|
1606 |
let
|
|
1607 |
val lim_thm = prove_nhds_bounds ectxt (Bounds bnds, basis)
|
|
1608 |
val nz_thm = prove_eventually_nonzero_bounds ectxt (Bounds bnds, basis)
|
|
1609 |
in
|
|
1610 |
@{thm Topological_Spaces.filterlim_atI} OF [lim_thm, nz_thm]
|
|
1611 |
end
|
|
1612 |
|
|
1613 |
fun prove_at_right_0_bounds ectxt (Exact thm, basis) = prove_at_right_0 ectxt (thm, basis)
|
|
1614 |
| prove_at_right_0_bounds ectxt (Bounds (SOME l, SOME u), basis) =
|
|
1615 |
let
|
|
1616 |
val lim_thm = prove_nhds_bounds ectxt (Bounds (SOME l, SOME u), basis)
|
|
1617 |
in
|
|
1618 |
case prove_eventually_pos_lower_bound ectxt basis l of
|
|
1619 |
SOME pos_thm => @{thm tendsto_imp_filterlim_at_right} OF [lim_thm, pos_thm]
|
|
1620 |
| NONE => raise TERM ("prove_at_right_0_bounds", [])
|
|
1621 |
end
|
|
1622 |
| prove_at_right_0_bounds _ _ = raise TERM ("prove_at_right_0_bounds", [])
|
|
1623 |
|
|
1624 |
fun prove_at_left_0_bounds ectxt (Exact thm, basis) = prove_at_left_0 ectxt (thm, basis)
|
|
1625 |
| prove_at_left_0_bounds ectxt (Bounds (SOME l, SOME u), basis) =
|
|
1626 |
let
|
|
1627 |
val lim_thm = prove_nhds_bounds ectxt (Bounds (SOME l, SOME u), basis)
|
|
1628 |
in
|
|
1629 |
case prove_eventually_neg_upper_bound ectxt basis u of
|
|
1630 |
SOME neg_thm => @{thm tendsto_imp_filterlim_at_left} OF [lim_thm, neg_thm]
|
|
1631 |
| NONE => raise TERM ("prove_at_left_0_bounds", [])
|
|
1632 |
end
|
|
1633 |
| prove_at_left_0_bounds _ _ = raise TERM ("prove_at_left_0_bounds", [])
|
|
1634 |
|
|
1635 |
fun prove_eventually_less_bounds ectxt (bnds1, bnds2, basis) =
|
|
1636 |
case (get_upper_bound bnds1, get_lower_bound bnds2) of
|
|
1637 |
(SOME (ub1_thm, le_ub1_thm), SOME (lb2_thm, ge_lb2_thm)) =>
|
|
1638 |
let
|
|
1639 |
val thm = prove_eventually_less ectxt (ub1_thm, lb2_thm, basis)
|
|
1640 |
in
|
|
1641 |
@{thm eventually_le_less[OF _ eventually_less_le]} OF [le_ub1_thm, thm, ge_lb2_thm]
|
|
1642 |
end
|
|
1643 |
| _ => raise TERM ("prove_asymptotically_less_bounds", [])
|
|
1644 |
|
|
1645 |
fun prove_eventually_greater_bounds ectxt (bnds1, bnds2, basis) =
|
|
1646 |
prove_eventually_less_bounds ectxt (bnds2, bnds1, basis)
|
|
1647 |
|
|
1648 |
|
|
1649 |
|
|
1650 |
fun prove_o_bounds small ectxt (Exact thm1, Exact thm2, basis) =
|
|
1651 |
(if small then prove_smallo else prove_bigo) ectxt (thm1, thm2, basis)
|
|
1652 |
| prove_o_bounds small ectxt (bnds1, bnds2, basis) =
|
|
1653 |
let
|
|
1654 |
val exact = if small then prove_smallo else prove_bigo
|
|
1655 |
val s = if small then "prove_smallo_bounds" else "prove_bigo_bounds"
|
|
1656 |
val (l2thm', nonneg_thm, ge2_thm) = abs_expansion_lower_bound ectxt basis bnds2
|
|
1657 |
val ((l1thm, ge1_thm), (u1thm, le1_thm)) =
|
|
1658 |
case bnds1 of
|
|
1659 |
Exact thm1 =>
|
|
1660 |
let val x = (exact ectxt (thm1, l2thm', basis), thm1 RS @{thm exact_to_bound})
|
|
1661 |
in (x, x) end
|
|
1662 |
| Bounds (SOME (l1thm, ge1_thm), SOME (u1thm, le1_thm)) =>
|
|
1663 |
((exact ectxt (l1thm, l2thm', basis), ge1_thm),
|
|
1664 |
(exact ectxt (u1thm, l2thm', basis), le1_thm))
|
|
1665 |
| _ => raise TERM (s, [])
|
|
1666 |
val impthm = if small then @{thm bounds_smallo_imp_smallo} else @{thm bounds_bigo_imp_bigo}
|
|
1667 |
in
|
|
1668 |
impthm OF [ge1_thm, le1_thm, ge2_thm, nonneg_thm, l1thm, u1thm]
|
|
1669 |
end
|
|
1670 |
|
|
1671 |
val prove_smallo_bounds = prove_o_bounds true
|
|
1672 |
val prove_bigo_bounds = prove_o_bounds false
|
|
1673 |
|
|
1674 |
fun prove_bigtheta_bounds ectxt (Exact thm1, Exact thm2, basis) =
|
|
1675 |
prove_bigtheta ectxt (thm1, thm2, basis)
|
|
1676 |
| prove_bigtheta_bounds ectxt (bnds1, bnds2, basis) =
|
|
1677 |
let (* TODO inefficient *)
|
|
1678 |
val thms =
|
|
1679 |
Par_List.map (fn x => prove_bigo_bounds ectxt x)
|
|
1680 |
[(bnds1, bnds2, basis), (bnds2, bnds1, basis)]
|
|
1681 |
in
|
|
1682 |
@{thm bigthetaI[unfolded bigomega_iff_bigo]} OF thms
|
|
1683 |
end
|
|
1684 |
|
|
1685 |
fun prove_asymp_equivs ectxt basis =
|
|
1686 |
Par_List.map (fn (thm1, thm2) => prove_asymp_equiv ectxt (thm1, thm2, basis))
|
|
1687 |
|
|
1688 |
fun prove_asymp_equiv_bounds ectxt (Exact thm1, Exact thm2, basis) =
|
|
1689 |
prove_asymp_equiv ectxt (thm1, thm2, basis)
|
|
1690 |
| prove_asymp_equiv_bounds ectxt (Exact thm1,
|
|
1691 |
Bounds (SOME (l2, ge2_thm), SOME (u2, le2_thm)), basis) =
|
|
1692 |
let
|
|
1693 |
val thms = prove_asymp_equivs ectxt basis [(thm1, l2), (thm1, u2)]
|
|
1694 |
in
|
|
1695 |
@{thm asymp_equiv_sandwich_real'[OF _ _ eventually_atLeastAtMostI]} OF
|
|
1696 |
(thms @ [ge2_thm, le2_thm])
|
|
1697 |
end
|
|
1698 |
| prove_asymp_equiv_bounds ectxt (Bounds (SOME (l1, ge1_thm), SOME (u1, le1_thm)),
|
|
1699 |
Exact thm2, basis) =
|
|
1700 |
let
|
|
1701 |
val thms = prove_asymp_equivs ectxt basis [(l1, thm2), (u1, thm2)]
|
|
1702 |
in
|
|
1703 |
@{thm asymp_equiv_sandwich_real[OF _ _ eventually_atLeastAtMostI]} OF
|
|
1704 |
(thms @ [ge1_thm, le1_thm])
|
|
1705 |
end
|
|
1706 |
| prove_asymp_equiv_bounds ectxt (Bounds (SOME (l1, ge1_thm), SOME (u1, le1_thm)),
|
|
1707 |
Bounds (SOME (l2, ge2_thm), SOME (u2, le2_thm)), basis) =
|
|
1708 |
let
|
|
1709 |
val thms = prove_asymp_equivs ectxt basis [(l1, u1), (u1, l2), (l2, u2)]
|
|
1710 |
in
|
|
1711 |
@{thm asymp_equiv_sandwich_real''
|
|
1712 |
[OF _ _ _ eventually_atLeastAtMostI eventually_atLeastAtMostI]} OF
|
|
1713 |
(thms @ [ge1_thm, le1_thm, ge2_thm, le2_thm])
|
|
1714 |
end
|
|
1715 |
| prove_asymp_equiv_bounds _ _ = raise TERM ("prove_asymp_equiv_bounds", [])
|
|
1716 |
|
|
1717 |
val dest_fun = dest_comb #> fst
|
|
1718 |
val dest_arg = dest_comb #> snd
|
|
1719 |
val concl_of' = Thm.concl_of #> HOLogic.dest_Trueprop
|
|
1720 |
|
|
1721 |
fun lim_eq ectxt (l1, l2) = (l1 aconv l2) orelse
|
|
1722 |
case (l1, l2) of
|
69597
|
1723 |
(Const (\<^const_name>\<open>nhds\<close>, _) $ a, Const (\<^const_name>\<open>nhds\<close>, _) $ b) => (
|
68630
|
1724 |
case try_prove_real_eq false ectxt (a, b) of
|
|
1725 |
SOME _ => true
|
|
1726 |
| _ => false)
|
|
1727 |
| _ => false
|
|
1728 |
|
|
1729 |
fun limit_of_expansion_bounds ectxt (bnds, basis) =
|
|
1730 |
let
|
|
1731 |
fun get_limit thm =
|
|
1732 |
limit_of_expansion (true, true) ectxt (thm, basis) |> snd |> concl_of' |> dest_fun |> dest_arg
|
|
1733 |
in
|
|
1734 |
case bnds of
|
|
1735 |
Exact thm => get_limit thm |> Exact_Limit
|
|
1736 |
| Bounds (l, u) =>
|
|
1737 |
let
|
|
1738 |
val (llim, ulim) = apply2 (Option.map (fst #> get_limit)) (l, u)
|
|
1739 |
in
|
|
1740 |
case (llim, ulim) of
|
|
1741 |
(SOME llim', SOME ulim') =>
|
|
1742 |
if lim_eq ectxt (llim', ulim') then Exact_Limit llim' else Limit_Bounds (llim, ulim)
|
|
1743 |
| _ => Limit_Bounds (llim, ulim)
|
|
1744 |
end
|
|
1745 |
end
|
|
1746 |
|
|
1747 |
end
|
|
1748 |
|
|
1749 |
structure Multiseries_Expansion_Bounds : EXPANSION_INTERFACE =
|
|
1750 |
struct
|
|
1751 |
open Multiseries_Expansion;
|
|
1752 |
|
|
1753 |
type T = bounds
|
|
1754 |
|
|
1755 |
val expand_term = expand_term_bounds
|
|
1756 |
val expand_terms = expand_terms_bounds
|
|
1757 |
|
|
1758 |
val prove_nhds = prove_nhds_bounds
|
|
1759 |
val prove_at_infinity = prove_at_infinity_bounds
|
|
1760 |
val prove_at_top = prove_at_top_bounds
|
|
1761 |
val prove_at_bot = prove_at_bot_bounds
|
|
1762 |
val prove_at_0 = prove_at_0_bounds
|
|
1763 |
val prove_at_right_0 = prove_at_right_0_bounds
|
|
1764 |
val prove_at_left_0 = prove_at_left_0_bounds
|
|
1765 |
val prove_eventually_nonzero = prove_eventually_nonzero_bounds
|
|
1766 |
|
|
1767 |
val prove_eventually_less = prove_eventually_less_bounds
|
|
1768 |
val prove_eventually_greater = prove_eventually_greater_bounds
|
|
1769 |
|
|
1770 |
val prove_smallo = prove_smallo_bounds
|
|
1771 |
val prove_bigo = prove_bigo_bounds
|
|
1772 |
val prove_bigtheta = prove_bigtheta_bounds
|
|
1773 |
val prove_asymp_equiv = prove_asymp_equiv_bounds
|
|
1774 |
|
|
1775 |
end
|
|
1776 |
|
|
1777 |
structure Real_Asymp_Bounds = Real_Asymp(Multiseries_Expansion_Bounds) |