diff.html 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. <html>
  2. <head>
  3. <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
  4. <title>Numerical Differentiation</title>
  5. <link rel="stylesheet" href="../math.css" type="text/css">
  6. <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
  7. <link rel="home" href="../index.html" title="Math Toolkit 2.11.0">
  8. <link rel="up" href="../quadrature.html" title="Chapter&#160;13.&#160;Quadrature and Differentiation">
  9. <link rel="prev" href="naive_monte_carlo.html" title="Naive Monte Carlo Integration">
  10. <link rel="next" href="autodiff.html" title="Automatic Differentiation">
  11. </head>
  12. <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
  13. <table cellpadding="2" width="100%"><tr>
  14. <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
  15. <td align="center"><a href="../../../../../index.html">Home</a></td>
  16. <td align="center"><a href="../../../../../libs/libraries.htm">Libraries</a></td>
  17. <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
  18. <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
  19. <td align="center"><a href="../../../../../more/index.htm">More</a></td>
  20. </tr></table>
  21. <hr>
  22. <div class="spirit-nav">
  23. <a accesskey="p" href="naive_monte_carlo.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../quadrature.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="autodiff.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
  24. </div>
  25. <div class="section">
  26. <div class="titlepage"><div><div><h2 class="title" style="clear: both">
  27. <a name="math_toolkit.diff"></a><a class="link" href="diff.html" title="Numerical Differentiation">Numerical Differentiation</a>
  28. </h2></div></div></div>
  29. <h4>
  30. <a name="math_toolkit.diff.h0"></a>
  31. <span class="phrase"><a name="math_toolkit.diff.synopsis"></a></span><a class="link" href="diff.html#math_toolkit.diff.synopsis">Synopsis</a>
  32. </h4>
  33. <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">differentiaton</span><span class="special">/</span><span class="identifier">finite_difference</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
  34. <span class="keyword">namespace</span> <span class="identifier">boost</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">math</span> <span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">differentiation</span> <span class="special">{</span>
  35. <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">F</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Real</span><span class="special">&gt;</span>
  36. <span class="identifier">Real</span> <span class="identifier">complex_step_derivative</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">F</span> <span class="identifier">f</span><span class="special">,</span> <span class="identifier">Real</span> <span class="identifier">x</span><span class="special">);</span>
  37. <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">F</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Real</span><span class="special">,</span> <span class="identifier">size_t</span> <span class="identifier">order</span> <span class="special">=</span> <span class="number">6</span><span class="special">&gt;</span>
  38. <span class="identifier">Real</span> <span class="identifier">finite_difference_derivative</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">F</span> <span class="identifier">f</span><span class="special">,</span> <span class="identifier">Real</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">Real</span><span class="special">*</span> <span class="identifier">error</span> <span class="special">=</span> <span class="keyword">nullptr</span><span class="special">);</span>
  39. <span class="special">}}}</span> <span class="comment">// namespaces</span>
  40. </pre>
  41. <h4>
  42. <a name="math_toolkit.diff.h1"></a>
  43. <span class="phrase"><a name="math_toolkit.diff.description"></a></span><a class="link" href="diff.html#math_toolkit.diff.description">Description</a>
  44. </h4>
  45. <p>
  46. The function <code class="computeroutput"><span class="identifier">finite_difference_derivative</span></code>
  47. calculates a finite-difference approximation to the derivative of a function
  48. <span class="emphasis"><em>f</em></span> at point <span class="emphasis"><em>x</em></span>. A basic usage is
  49. </p>
  50. <pre class="programlisting"><span class="keyword">auto</span> <span class="identifier">f</span> <span class="special">=</span> <span class="special">[](</span><span class="keyword">double</span> <span class="identifier">x</span><span class="special">)</span> <span class="special">{</span> <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">exp</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span> <span class="special">};</span>
  51. <span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="number">1.7</span><span class="special">;</span>
  52. <span class="keyword">double</span> <span class="identifier">dfdx</span> <span class="special">=</span> <span class="identifier">finite_difference_derivative</span><span class="special">(</span><span class="identifier">f</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
  53. </pre>
  54. <p>
  55. Finite differencing is complicated, as differentiation is <span class="emphasis"><em>infinitely</em></span>
  56. ill-conditioned. In addition, for any function implemented in finite-precision
  57. arithmetic, the "true" derivative is <span class="emphasis"><em>zero</em></span> almost
  58. everywhere, and undefined at representables. However, some tricks allow for
  59. reasonable results to be obtained in many cases.
  60. </p>
  61. <p>
  62. There are two sources of error from finite differences: One, the truncation
  63. error arising from using a finite number of samples to cancel out higher order
  64. terms in the Taylor series. The second is the roundoff error involved in evaluating
  65. the function. The truncation error goes to zero as <span class="emphasis"><em>h</em></span> &#8594;
  66. 0, but the roundoff error becomes unbounded. By balancing these two sources
  67. of error, we can choose a value of <span class="emphasis"><em>h</em></span> that minimizes the
  68. maximum total error. For this reason boost's <code class="computeroutput"><span class="identifier">finite_difference_derivative</span></code>
  69. does not require the user to input a stepsize. For more details about the theoretical
  70. error analysis involved in finite-difference approximations to the derivative,
  71. see <a href="http://web.archive.org/web/20150420195907/http://www.uio.no/studier/emner/matnat/math/MAT-INF1100/h08/kompendiet/diffint.pdf" target="_top">here</a>.
  72. </p>
  73. <p>
  74. Despite the effort that has went into choosing a reasonable value of <span class="emphasis"><em>h</em></span>,
  75. the problem is still fundamentally ill-conditioned, and hence an error estimate
  76. is essential. It can be queried as follows
  77. </p>
  78. <pre class="programlisting"><span class="keyword">double</span> <span class="identifier">error_estimate</span><span class="special">;</span>
  79. <span class="keyword">double</span> <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">finite_difference_derivative</span><span class="special">(</span><span class="identifier">f</span><span class="special">,</span> <span class="identifier">x</span><span class="special">,</span> <span class="special">&amp;</span><span class="identifier">error_estimate</span><span class="special">);</span>
  80. </pre>
  81. <p>
  82. N.B.: Producing an error estimate requires additional function evaluations
  83. and as such is slower than simple evaluation of the derivative. It also expands
  84. the domain over which the function must be differentiable and requires the
  85. function to have two more continuous derivatives. The error estimate is computed
  86. under the assumption that <span class="emphasis"><em>f</em></span> is evaluated to 1ULP. This
  87. might seem an extreme assumption, but it is the only sensible one, as the routine
  88. cannot know the functions rounding error. If the function cannot be evaluated
  89. with very great accuracy, Lanczos's smoothing differentiation is recommended
  90. as an alternative.
  91. </p>
  92. <p>
  93. The default order of accuracy is 6, which reflects that fact that people tend
  94. to be interested in functions with many continuous derivatives. If your function
  95. does not have 7 continuous derivatives, is may be of interest to use a lower
  96. order method, which can be achieved via (say)
  97. </p>
  98. <pre class="programlisting"><span class="keyword">double</span> <span class="identifier">d</span> <span class="special">=</span> <span class="identifier">finite_difference_derivative</span><span class="special">&lt;</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">f</span><span class="special">),</span> <span class="identifier">Real</span><span class="special">,</span> <span class="number">2</span><span class="special">&gt;(</span><span class="identifier">f</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
  99. </pre>
  100. <p>
  101. This requests a second-order accurate derivative be computed.
  102. </p>
  103. <p>
  104. It is emphatically <span class="emphasis"><em>not</em></span> the case that higher order methods
  105. always give higher accuracy for smooth functions. Higher order methods require
  106. more addition of positive and negative terms, which can lead to catastrophic
  107. cancellation. A function which is very good at making a mockery of finite-difference
  108. differentiation is exp(x)/(cos(x)<sup>3</sup> + sin(x)<sup>3</sup>). Differentiating this function
  109. by <code class="computeroutput"><span class="identifier">finite_difference_derivative</span></code>
  110. in double precision at <span class="emphasis"><em>x=5.5</em></span> gives zero correct digits
  111. at order 4, 6, and 8, but recovers 5 correct digits at order 2. These are dangerous
  112. waters; use the error estimates to tread carefully.
  113. </p>
  114. <p>
  115. For a finite-difference method of order <span class="emphasis"><em>k</em></span>, the error is
  116. <span class="emphasis"><em>C</em></span> &#949;<sup>k/k+1</sup>. In the limit <span class="emphasis"><em>k</em></span> &#8594;
  117. &#8734;, we see that the error tends to &#949;, recovering the full precision
  118. for the type. However, this ignores the fact that higher-order methods require
  119. subtracting more nearly-equal (perhaps noisy) terms, so the constant <span class="emphasis"><em>C</em></span>
  120. grows with <span class="emphasis"><em>k</em></span>. Since <span class="emphasis"><em>C</em></span> grows quickly
  121. and &#949;<sup>k/k+1</sup> approaches &#949; slowly, we can see there is a compromise
  122. between high-order accuracy and conditioning of the difference quotient. In
  123. practice we have found that <span class="emphasis"><em>k=6</em></span> seems to be a good compromise
  124. between the two (and have made this the default), but users are encouraged
  125. to examine the error estimates to choose an optimal order of accuracy for the
  126. given problem.
  127. </p>
  128. <div class="table">
  129. <a name="math_toolkit.diff.id"></a><p class="title"><b>Table&#160;13.1.&#160;Cost of Finite-Difference Numerical Differentiation</b></p>
  130. <div class="table-contents"><table class="table" summary="Cost of Finite-Difference Numerical Differentiation">
  131. <colgroup>
  132. <col>
  133. <col>
  134. <col>
  135. <col>
  136. <col>
  137. </colgroup>
  138. <thead><tr>
  139. <th>
  140. <p>
  141. Order of Accuracy
  142. </p>
  143. </th>
  144. <th>
  145. <p>
  146. Function Evaluations
  147. </p>
  148. </th>
  149. <th>
  150. <p>
  151. Error
  152. </p>
  153. </th>
  154. <th>
  155. <p>
  156. Continuous Derivatives Required for Error Estimate to Hold
  157. </p>
  158. </th>
  159. <th>
  160. <p>
  161. Additional Function Evaluations to Produce Error Estimates
  162. </p>
  163. </th>
  164. </tr></thead>
  165. <tbody>
  166. <tr>
  167. <td>
  168. <p>
  169. 1
  170. </p>
  171. </td>
  172. <td>
  173. <p>
  174. 2
  175. </p>
  176. </td>
  177. <td>
  178. <p>
  179. &#949;<sup>1/2</sup>
  180. </p>
  181. </td>
  182. <td>
  183. <p>
  184. 2
  185. </p>
  186. </td>
  187. <td>
  188. <p>
  189. 1
  190. </p>
  191. </td>
  192. </tr>
  193. <tr>
  194. <td>
  195. <p>
  196. 2
  197. </p>
  198. </td>
  199. <td>
  200. <p>
  201. 2
  202. </p>
  203. </td>
  204. <td>
  205. <p>
  206. &#949;<sup>2/3</sup>
  207. </p>
  208. </td>
  209. <td>
  210. <p>
  211. 3
  212. </p>
  213. </td>
  214. <td>
  215. <p>
  216. 2
  217. </p>
  218. </td>
  219. </tr>
  220. <tr>
  221. <td>
  222. <p>
  223. 4
  224. </p>
  225. </td>
  226. <td>
  227. <p>
  228. 4
  229. </p>
  230. </td>
  231. <td>
  232. <p>
  233. &#949;<sup>4/5</sup>
  234. </p>
  235. </td>
  236. <td>
  237. <p>
  238. 5
  239. </p>
  240. </td>
  241. <td>
  242. <p>
  243. 2
  244. </p>
  245. </td>
  246. </tr>
  247. <tr>
  248. <td>
  249. <p>
  250. 6
  251. </p>
  252. </td>
  253. <td>
  254. <p>
  255. 6
  256. </p>
  257. </td>
  258. <td>
  259. <p>
  260. &#949;<sup>6/7</sup>
  261. </p>
  262. </td>
  263. <td>
  264. <p>
  265. 7
  266. </p>
  267. </td>
  268. <td>
  269. <p>
  270. 2
  271. </p>
  272. </td>
  273. </tr>
  274. <tr>
  275. <td>
  276. <p>
  277. 8
  278. </p>
  279. </td>
  280. <td>
  281. <p>
  282. 8
  283. </p>
  284. </td>
  285. <td>
  286. <p>
  287. &#949;<sup>8/9</sup>
  288. </p>
  289. </td>
  290. <td>
  291. <p>
  292. 9
  293. </p>
  294. </td>
  295. <td>
  296. <p>
  297. 2
  298. </p>
  299. </td>
  300. </tr>
  301. </tbody>
  302. </table></div>
  303. </div>
  304. <br class="table-break"><p>
  305. Given all the caveats which must be kept in mind for successful use of finite-difference
  306. differentiation, it is reasonable to try to avoid it if possible. Boost provides
  307. two possibilities: The Chebyshev transform (see <a class="link" href="sf_poly/chebyshev.html" title="Chebyshev Polynomials">here</a>)
  308. and the complex step derivative. If your function is the restriction to the
  309. real line of a holomorphic function which takes real values at real argument,
  310. then the <span class="bold"><strong>complex step derivative</strong></span> can be used.
  311. The idea is very simple: Since <span class="emphasis"><em>f</em></span> is complex-differentiable,
  312. <span class="emphasis"><em>f(x+&#8520; h) = f(x) + &#8520; hf'(x) - h<sup>2</sup>f''(x) + &#119926;(h<sup>3</sup>)</em></span>.
  313. As long as <span class="emphasis"><em>f(x)</em></span> &#8712; &#8477;, then <span class="emphasis"><em>f'(x)
  314. = &#8465; f(x+&#8520; h)/h + &#119926;(h<sup>2</sup>)</em></span>. This method requires a single
  315. complex function evaluation and is not subject to the catastrophic subtractive
  316. cancellation that plagues finite-difference calculations.
  317. </p>
  318. <p>
  319. An example usage:
  320. </p>
  321. <pre class="programlisting"><span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="number">7.2</span><span class="special">;</span>
  322. <span class="keyword">double</span> <span class="identifier">e_prime</span> <span class="special">=</span> <span class="identifier">complex_step_derivative</span><span class="special">(</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">exp</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">complex</span><span class="special">&lt;</span><span class="keyword">double</span><span class="special">&gt;&gt;,</span> <span class="identifier">x</span><span class="special">);</span>
  323. </pre>
  324. <p>
  325. References:
  326. </p>
  327. <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
  328. <li class="listitem">
  329. Squire, William, and George Trapp. <span class="emphasis"><em>Using complex variables to
  330. estimate derivatives of real functions.</em></span> Siam Review 40.1 (1998):
  331. 110-112.
  332. </li>
  333. <li class="listitem">
  334. Fornberg, Bengt. <span class="emphasis"><em>Generation of finite difference formulas on
  335. arbitrarily spaced grids.</em></span> Mathematics of computation 51.184
  336. (1988): 699-706.
  337. </li>
  338. <li class="listitem">
  339. Corless, Robert M., and Nicolas Fillion. <span class="emphasis"><em>A graduate introduction
  340. to numerical methods.</em></span> AMC 10 (2013): 12.
  341. </li>
  342. </ul></div>
  343. </div>
  344. <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
  345. <td align="left"></td>
  346. <td align="right"><div class="copyright-footer">Copyright &#169; 2006-2019 Nikhar
  347. Agrawal, Anton Bikineev, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos,
  348. Hubert Holin, Bruno Lalande, John Maddock, Jeremy Murphy, Matthew Pulver, Johan
  349. R&#229;de, Gautam Sewani, Benjamin Sobotta, Nicholas Thompson, Thijs van den Berg,
  350. Daryle Walker and Xiaogang Zhang<p>
  351. Distributed under the Boost Software License, Version 1.0. (See accompanying
  352. file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
  353. </p>
  354. </div></td>
  355. </tr></table>
  356. <hr>
  357. <div class="spirit-nav">
  358. <a accesskey="p" href="naive_monte_carlo.html"><img src="../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../quadrature.html"><img src="../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="autodiff.html"><img src="../../../../../doc/src/images/next.png" alt="Next"></a>
  359. </div>
  360. </body>
  361. </html>