1 (* port of taylor functions, taylor interval *)
4 The first part of the file implements basic operations on type taylor_interval.
6 Then a type tfunction is defined that represents a twice continuously
7 differentiable function of six variables. It can be evaluated, which
8 is the taylor_interval data associated with it.
10 Sometimes a tfunction f is used to represent an inequality f < 0.
15 module Taylor = struct
22 (* general utilities *)
25 let center_form(x,z) =
26 let ( + ) , ( - ), ( / ) = up(); upadd,upsub,updiv in
27 let y = if x = z then x else (x + z) / 2.0 in
28 let w = max (z - y) (y - x) in
29 let _ = (w >= 0.0) or failwith "centerform" in
32 (* start with taylor interval operations *)
34 let make_taylor_interval (l1,w1,dd1) = {l = l1; w = w1; dd=dd1;};;
36 let ti_add (ti1,ti2) =
37 let _ = (ti1.w = ti2.w) or failwith ("width mismatch in ti") in
38 make_taylor_interval( ladd ti1.l ti2.l,ti1.w, iadd ti1.dd ti2.dd);;
40 let ti_sub (ti1,ti2) =
41 let _ = (ti1.w = ti2.w) or failwith ("width mistmatch in ti") in
42 make_taylor_interval( lsub ti1.l ti2.l, ti1.w, isub ti1.dd ti2.dd );;
45 make_taylor_interval( smul ti.l t, ti.w, imul ti.dd t );;
50 let ( + ), ( * ) , ( / )= up(); upadd, upmul, updiv in
51 (ti.w * ti.w * iabs ti.dd) / 2.0;;
54 let e = taylor_error ti in
55 let ( + ), ( * ) = up(); upadd, upmul in
56 ti.l.f.hi + ti.w * iabs ti.l.df + e;;
59 let e = taylor_error ti in
60 let ( + ), ( * ),( - ) = down(); downadd,downmul,downsub in
61 ti.l.f.lo - e + ( ~-. (ti.w)) * iabs ti.l.df;;
63 (* t + List.fold_left2 (fun a b c -> a + ( ~-. b) * iabs c) 0.0 ti.w ti.l.df;; *)
65 let upper_partial ti =
66 let ( + ), ( * ) = up(); upadd,upmul in
67 let err = ti.w * (max ti.dd.hi (~-. (ti.dd.lo))) in
68 err + Interval.sup ( ti.l.df );;
70 let lower_partial ti =
71 let ( + ), ( * ), ( - ) = down();downadd,downmul,downsub in
72 let err = ti.w * min ti.dd.lo (~-. (ti.dd.hi)) in
73 Interval.inf ( ti.l.df ) + err;;
78 let ti_mul (ti1, ti2) =
79 let _ = (ti1.w = ti2.w) or failwith ("width mistmatch in ti") in
80 let f = mk_interval (lower_bound ti1, upper_bound ti1) and
81 g = mk_interval (lower_bound ti2, upper_bound ti2) and
82 df = mk_interval (lower_partial ti1, upper_partial ti1) and
83 dg = mk_interval (lower_partial ti2, upper_partial ti2) and
84 ( + ), ( * ) = iadd, imul in
85 make_taylor_interval( lmul ti1.l ti2.l, ti1.w,
86 ti1.dd * g + two * df * dg + f * ti2.dd);;
93 second : float -> float -> interval;
96 let make_primitiveA (h1,s1) = {hfn = h1; second = s1; };;
100 (fun y -> line_unit),
104 let evalf4A pA w x y z =
105 make_taylor_interval(
111 let line_estimateA pA y = pA.hfn y;;
119 let mk_primitiveU uv1 = { uv = uv1; };;
121 let line_estimateU p y =
123 let t = mk_interval(y0,y0) in
124 let d = eval p.uv t 1 in
125 mk_line (eval p.uv t 0, d);;
127 let evalf4U p w x y z =
128 let t = mk_interval(x,z) in
129 make_taylor_interval(
136 | Prim_a of primitiveA
138 | Plus of tfunction * tfunction
139 | Minus of tfunction * tfunction
140 | Product of tfunction * tfunction
141 | Scale of tfunction * interval
142 | Uni_compose of univariate * tfunction
143 | Composite of tfunction * tfunction;;
145 let unit = Prim_a unitA;;
147 let x1 = Uni (mk_primitiveU ux);;
150 (* This is one of the most difficult functions in the interval code.
151 It uses the chain rule to compute the second partial derivatives with
152 respect to x(i) x(j), of a function composition
154 F(x1,...,x6) = f(g1(x1,...x6),g2(x1,...x6),...,g6(x1,...x6)).
156 (F i j) = sum {k m} (f k m) (gk i) (gm j) + sum {r} (f r) (gr i j).
158 Fast performance of this function is very important, especially
159 when many of the functions g* are constant.
160 There is a bit of imperative programming here, in computing the sums.
162 Note that ( + ) and ( * ) have different types in various subsections.
167 (* wide and narrow ranges of p *)
168 let (aw,bw) = lower_bound p, upper_bound p in
169 let (a,b) = p.l.f.lo, p.l.f.hi in
170 (* wide and narrow widths from a to b *)
172 let ( + ),( - ),( / ) = up();upadd,upsub,updiv in
173 let u = (a + b) / 2.0 in
174 let wu = max (bw - u) (u - aw) in
175 let wf = max (b - u) (u - a) in
177 let (fu:taylor_interval) = hdr wu aw u bw in
179 let t = make_taylor_interval(fu.l,wf,fu.dd) in
181 mk_interval(lower_bound t, upper_bound t),
182 mk_interval(lower_partial t, upper_partial t)) in
183 (* use chain rule imperatively to compute narrow first derivative *)
186 mk_line (fpy.f, fpy.df * p.l.df) in
187 (* second derivative init *)
188 let fW_partial = mk_interval(lower_partial fu, upper_partial fu) in
189 let pW_partial = mk_interval(lower_partial p, upper_partial p) in
193 fW_partial * p.dd + fu.dd * pW_partial * pW_partial in
194 make_taylor_interval(lin,w,dcw_list);;
196 let rec evalf4 tf w x y z = match tf with
197 | Prim_a p -> evalf4A p w x y z
198 | Uni p -> evalf4U p w x y z
199 | Plus (tf1,tf2) -> ti_add(evalf4 tf1 w x y z, evalf4 tf2 w x y z)
200 | Minus (tf1, tf2) -> ti_sub(evalf4 tf1 w x y z, evalf4 tf2 w x y z)
201 | Product (tf1, tf2) -> ti_mul(evalf4 tf1 w x y z, evalf4 tf2 w x y z)
202 | Composite(h,g) -> eval_composite (evalf4 h) (evalf4 g w x y z) w
203 | Scale (tf,t) -> ti_scale ((evalf4 tf w x y z),t)
204 | Uni_compose (uf,tf) ->
205 evalf4 (Composite(Uni (mk_primitiveU uf),tf)) w x y z;;
208 let (y,w) = center_form (x,z) in
211 let line_estimate_composite =
214 let (a,b) = (p.f.lo, p.f.hi) in
215 let fN = evalf h a b in
216 let fN_partial = mk_interval(lower_partial fN, upper_partial fN) in
217 mk_line (fN.l.f, fN_partial * p.df);;
219 let rec line_estimate tf y = match tf with
220 | Prim_a p -> line_estimateA p y
221 | Uni p -> line_estimateU p y
222 | Plus (p,q) -> ladd (line_estimate p y) (line_estimate q y)
223 | Minus (p,q) -> lsub (line_estimate p y) (line_estimate q y)
224 | Product (p,q) -> lmul (line_estimate p y) (line_estimate q y)
225 | Scale (p,t) -> smul (line_estimate p y) t
226 | Uni_compose (uf,tf) ->
227 line_estimate (Composite(Uni (mk_primitiveU uf),tf)) y
228 | Composite(h,g) -> line_estimate_composite h (line_estimate g y);;