~ubuntu-branches/ubuntu/trusty/gsl-ref-html/trusty

« back to all changes in this revision

Viewing changes to Example-programs-for-Nonlinear-Least_002dSquares-Fitting.html

  • Committer: Bazaar Package Importer
  • Author(s): Dirk Eddelbuettel
  • Date: 2006-04-12 19:46:32 UTC
  • mfrom: (1.3.1 upstream) (3.1.1 dapper)
  • Revision ID: james.westby@ubuntu.com-20060412194632-c9lodpl075pv9si3
Tags: 1.8-1
* New upstream release 1.8
* As with previous releases, the sources were obtained from the FSF web 
  pages by means of a wget call (c.f. the debian/rules target 'upstream')

* debian/control: Standards-Version increased to 3.6.2
* debian/copyright: Updated FSF address
* debian/rules: Set DH_COMPAT=4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<html lang="en">
 
2
<head>
 
3
<title>Example programs for Nonlinear Least-Squares Fitting - GNU Scientific Library -- Reference Manual</title>
 
4
<meta http-equiv="Content-Type" content="text/html">
 
5
<meta name="description" content="GNU Scientific Library -- Reference Manual">
 
6
<meta name="generator" content="makeinfo 4.8">
 
7
<link title="Top" rel="start" href="index.html#Top">
 
8
<link rel="up" href="Nonlinear-Least_002dSquares-Fitting.html#Nonlinear-Least_002dSquares-Fitting" title="Nonlinear Least-Squares Fitting">
 
9
<link rel="prev" href="Computing-the-covariance-matrix-of-best-fit-parameters.html#Computing-the-covariance-matrix-of-best-fit-parameters" title="Computing the covariance matrix of best fit parameters">
 
10
<link rel="next" href="References-and-Further-Reading-for-Nonlinear-Least_002dSquares-Fitting.html#References-and-Further-Reading-for-Nonlinear-Least_002dSquares-Fitting" title="References and Further Reading for Nonlinear Least-Squares Fitting">
 
11
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
 
12
<!--
 
13
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 The GSL Team.
 
14
 
 
15
Permission is granted to copy, distribute and/or modify this document
 
16
under the terms of the GNU Free Documentation License, Version 1.2 or
 
17
any later version published by the Free Software Foundation; with the
 
18
Invariant Sections being ``GNU General Public License'' and ``Free Software
 
19
Needs Free Documentation'', the Front-Cover text being ``A GNU Manual'',
 
20
and with the Back-Cover Text being (a) (see below).  A copy of the
 
21
license is included in the section entitled ``GNU Free Documentation
 
22
License''.
 
23
 
 
24
(a) The Back-Cover Text is: ``You have freedom to copy and modify this
 
25
GNU Manual, like GNU software.''-->
 
26
<meta http-equiv="Content-Style-Type" content="text/css">
 
27
<style type="text/css"><!--
 
28
  pre.display { font-family:inherit }
 
29
  pre.format  { font-family:inherit }
 
30
  pre.smalldisplay { font-family:inherit; font-size:smaller }
 
31
  pre.smallformat  { font-family:inherit; font-size:smaller }
 
32
  pre.smallexample { font-size:smaller }
 
33
  pre.smalllisp    { font-size:smaller }
 
34
  span.sc    { font-variant:small-caps }
 
35
  span.roman { font-family:serif; font-weight:normal; } 
 
36
  span.sansserif { font-family:sans-serif; font-weight:normal; } 
 
37
--></style>
 
38
</head>
 
39
<body>
 
40
<div class="node">
 
41
<p>
 
42
<a name="Example-programs-for-Nonlinear-Least-Squares-Fitting"></a>
 
43
<a name="Example-programs-for-Nonlinear-Least_002dSquares-Fitting"></a>
 
44
Next:&nbsp;<a rel="next" accesskey="n" href="References-and-Further-Reading-for-Nonlinear-Least_002dSquares-Fitting.html#References-and-Further-Reading-for-Nonlinear-Least_002dSquares-Fitting">References and Further Reading for Nonlinear Least-Squares Fitting</a>,
 
45
Previous:&nbsp;<a rel="previous" accesskey="p" href="Computing-the-covariance-matrix-of-best-fit-parameters.html#Computing-the-covariance-matrix-of-best-fit-parameters">Computing the covariance matrix of best fit parameters</a>,
 
46
Up:&nbsp;<a rel="up" accesskey="u" href="Nonlinear-Least_002dSquares-Fitting.html#Nonlinear-Least_002dSquares-Fitting">Nonlinear Least-Squares Fitting</a>
 
47
<hr>
 
48
</div>
 
49
 
 
50
<h3 class="section">37.9 Examples</h3>
 
51
 
 
52
<p>The following example program fits a weighted exponential model with
 
53
background to experimental data, Y = A \exp(-\lambda t) + b. The
 
54
first part of the program sets up the functions <code>expb_f</code> and
 
55
<code>expb_df</code> to calculate the model and its Jacobian.  The appropriate
 
56
fitting function is given by,
 
57
where we have chosen t_i = i.  The Jacobian matrix J is
 
58
the derivative of these functions with respect to the three parameters
 
59
(A, \lambda, b).  It is given by,
 
60
where x_0 = A, x_1 = \lambda and x_2 = b.
 
61
 
 
62
<pre class="example"><pre class="verbatim">     /* expfit.c -- model functions for exponential + background */
 
63
     
 
64
     struct data {
 
65
       size_t n;
 
66
       double * y;
 
67
       double * sigma;
 
68
     };
 
69
     
 
70
     int
 
71
     expb_f (const gsl_vector * x, void *data, 
 
72
             gsl_vector * f)
 
73
     {
 
74
       size_t n = ((struct data *)data)->n;
 
75
       double *y = ((struct data *)data)->y;
 
76
       double *sigma = ((struct data *) data)->sigma;
 
77
     
 
78
       double A = gsl_vector_get (x, 0);
 
79
       double lambda = gsl_vector_get (x, 1);
 
80
       double b = gsl_vector_get (x, 2);
 
81
     
 
82
       size_t i;
 
83
     
 
84
       for (i = 0; i &lt; n; i++)
 
85
         {
 
86
           /* Model Yi = A * exp(-lambda * i) + b */
 
87
           double t = i;
 
88
           double Yi = A * exp (-lambda * t) + b;
 
89
           gsl_vector_set (f, i, (Yi - y[i])/sigma[i]);
 
90
         }
 
91
     
 
92
       return GSL_SUCCESS;
 
93
     }
 
94
     
 
95
     int
 
96
     expb_df (const gsl_vector * x, void *data, 
 
97
              gsl_matrix * J)
 
98
     {
 
99
       size_t n = ((struct data *)data)->n;
 
100
       double *sigma = ((struct data *) data)->sigma;
 
101
     
 
102
       double A = gsl_vector_get (x, 0);
 
103
       double lambda = gsl_vector_get (x, 1);
 
104
     
 
105
       size_t i;
 
106
     
 
107
       for (i = 0; i &lt; n; i++)
 
108
         {
 
109
           /* Jacobian matrix J(i,j) = dfi / dxj, */
 
110
           /* where fi = (Yi - yi)/sigma[i],      */
 
111
           /*       Yi = A * exp(-lambda * i) + b  */
 
112
           /* and the xj are the parameters (A,lambda,b) */
 
113
           double t = i;
 
114
           double s = sigma[i];
 
115
           double e = exp(-lambda * t);
 
116
           gsl_matrix_set (J, i, 0, e/s); 
 
117
           gsl_matrix_set (J, i, 1, -t * A * e/s);
 
118
           gsl_matrix_set (J, i, 2, 1/s);
 
119
         }
 
120
       return GSL_SUCCESS;
 
121
     }
 
122
     
 
123
     int
 
124
     expb_fdf (const gsl_vector * x, void *data,
 
125
               gsl_vector * f, gsl_matrix * J)
 
126
     {
 
127
       expb_f (x, data, f);
 
128
       expb_df (x, data, J);
 
129
     
 
130
       return GSL_SUCCESS;
 
131
     }
 
132
</pre></pre>
 
133
   <p class="noindent">The main part of the program sets up a Levenberg-Marquardt solver and
 
134
some simulated random data. The data uses the known parameters
 
135
(1.0,5.0,0.1) combined with gaussian noise (standard deviation = 0.1)
 
136
over a range of 40 timesteps. The initial guess for the parameters is
 
137
chosen as (0.0, 1.0, 0.0).
 
138
 
 
139
<pre class="example"><pre class="verbatim">     #include &lt;stdlib.h>
 
140
     #include &lt;stdio.h>
 
141
     #include &lt;gsl/gsl_rng.h>
 
142
     #include &lt;gsl/gsl_randist.h>
 
143
     #include &lt;gsl/gsl_vector.h>
 
144
     #include &lt;gsl/gsl_blas.h>
 
145
     #include &lt;gsl/gsl_multifit_nlin.h>
 
146
     
 
147
     #include "expfit.c"
 
148
     
 
149
     #define N 40
 
150
     
 
151
     void print_state (size_t iter, gsl_multifit_fdfsolver * s);
 
152
     
 
153
     int
 
154
     main (void)
 
155
     {
 
156
       const gsl_multifit_fdfsolver_type *T;
 
157
       gsl_multifit_fdfsolver *s;
 
158
     
 
159
       int status;
 
160
       size_t i, iter = 0;
 
161
     
 
162
       const size_t n = N;
 
163
       const size_t p = 3;
 
164
     
 
165
       gsl_matrix *covar = gsl_matrix_alloc (p, p);
 
166
       double y[N], sigma[N];
 
167
       struct data d = { n, y, sigma};
 
168
       gsl_multifit_function_fdf f;
 
169
       double x_init[3] = { 1.0, 0.0, 0.0 };
 
170
       gsl_vector_view x = gsl_vector_view_array (x_init, p);
 
171
       const gsl_rng_type * type;
 
172
       gsl_rng * r;
 
173
     
 
174
       gsl_rng_env_setup();
 
175
     
 
176
       type = gsl_rng_default;
 
177
       r = gsl_rng_alloc (type);
 
178
     
 
179
       f.f = &amp;expb_f;
 
180
       f.df = &amp;expb_df;
 
181
       f.fdf = &amp;expb_fdf;
 
182
       f.n = n;
 
183
       f.p = p;
 
184
       f.params = &amp;d;
 
185
     
 
186
       /* This is the data to be fitted */
 
187
     
 
188
       for (i = 0; i &lt; n; i++)
 
189
         {
 
190
           double t = i;
 
191
           y[i] = 1.0 + 5 * exp (-0.1 * t) 
 
192
                      + gsl_ran_gaussian (r, 0.1);
 
193
           sigma[i] = 0.1;
 
194
           printf ("data: %d %g %g\n", i, y[i], sigma[i]);
 
195
         };
 
196
     
 
197
       T = gsl_multifit_fdfsolver_lmsder;
 
198
       s = gsl_multifit_fdfsolver_alloc (T, n, p);
 
199
       gsl_multifit_fdfsolver_set (s, &amp;f, &amp;x.vector);
 
200
     
 
201
       print_state (iter, s);
 
202
     
 
203
       do
 
204
         {
 
205
           iter++;
 
206
           status = gsl_multifit_fdfsolver_iterate (s);
 
207
     
 
208
           printf ("status = %s\n", gsl_strerror (status));
 
209
     
 
210
           print_state (iter, s);
 
211
     
 
212
           if (status)
 
213
             break;
 
214
     
 
215
           status = gsl_multifit_test_delta (s->dx, s->x,
 
216
                                             1e-4, 1e-4);
 
217
         }
 
218
       while (status == GSL_CONTINUE &amp;&amp; iter &lt; 500);
 
219
     
 
220
       gsl_multifit_covar (s->J, 0.0, covar);
 
221
     
 
222
     #define FIT(i) gsl_vector_get(s->x, i)
 
223
     #define ERR(i) sqrt(gsl_matrix_get(covar,i,i))
 
224
     
 
225
       { 
 
226
         double chi = gsl_blas_dnrm2(s->f);
 
227
         double dof = n - p;
 
228
         double c = GSL_MAX_DBL(1, chi / sqrt(dof)); 
 
229
     
 
230
         printf("chisq/dof = %g\n",  pow(chi, 2.0) / dof);
 
231
     
 
232
         printf ("A      = %.5f +/- %.5f\n", FIT(0), c*ERR(0));
 
233
         printf ("lambda = %.5f +/- %.5f\n", FIT(1), c*ERR(1));
 
234
         printf ("b      = %.5f +/- %.5f\n", FIT(2), c*ERR(2));
 
235
       }
 
236
     
 
237
       printf ("status = %s\n", gsl_strerror (status));
 
238
     
 
239
       gsl_multifit_fdfsolver_free (s);
 
240
       return 0;
 
241
     }
 
242
     
 
243
     void
 
244
     print_state (size_t iter, gsl_multifit_fdfsolver * s)
 
245
     {
 
246
       printf ("iter: %3u x = % 15.8f % 15.8f % 15.8f "
 
247
               "|f(x)| = %g\n",
 
248
               iter,
 
249
               gsl_vector_get (s->x, 0), 
 
250
               gsl_vector_get (s->x, 1),
 
251
               gsl_vector_get (s->x, 2), 
 
252
               gsl_blas_dnrm2 (s->f));
 
253
     }
 
254
</pre></pre>
 
255
   <p class="noindent">The iteration terminates when the change in x is smaller than 0.0001, as
 
256
both an absolute and relative change.  Here are the results of running
 
257
the program:
 
258
 
 
259
<pre class="smallexample">     iter: 0 x=1.00000000 0.00000000 0.00000000 |f(x)|=117.349
 
260
     status=success
 
261
     iter: 1 x=1.64659312 0.01814772 0.64659312 |f(x)|=76.4578
 
262
     status=success
 
263
     iter: 2 x=2.85876037 0.08092095 1.44796363 |f(x)|=37.6838
 
264
     status=success
 
265
     iter: 3 x=4.94899512 0.11942928 1.09457665 |f(x)|=9.58079
 
266
     status=success
 
267
     iter: 4 x=5.02175572 0.10287787 1.03388354 |f(x)|=5.63049
 
268
     status=success
 
269
     iter: 5 x=5.04520433 0.10405523 1.01941607 |f(x)|=5.44398
 
270
     status=success
 
271
     iter: 6 x=5.04535782 0.10404906 1.01924871 |f(x)|=5.44397
 
272
     chisq/dof = 0.800996
 
273
     A      = 5.04536 +/- 0.06028
 
274
     lambda = 0.10405 +/- 0.00316
 
275
     b      = 1.01925 +/- 0.03782
 
276
     status = success
 
277
</pre>
 
278
   <p class="noindent">The approximate values of the parameters are found correctly, and the
 
279
chi-squared value indicates a good fit (the chi-squared per degree of
 
280
freedom is approximately 1).  In this case the errors on the parameters
 
281
can be estimated from the square roots of the diagonal elements of the
 
282
covariance matrix.
 
283
 
 
284
   <p>If the chi-squared value shows a poor fit (i.e. <!-- {$\chi^2/(n-p) \gg 1$} -->
 
285
chi^2/dof &gt;&gt; 1) then the error estimates obtained from the
 
286
covariance matrix will be too small.  In the example program the error estimates
 
287
are multiplied by <!-- {$\sqrt{\chi^2/(n-p)}$} -->
 
288
\sqrt{\chi^2/dof} in this case, a common way of increasing the
 
289
errors for a poor fit.  Note that a poor fit will result from the use
 
290
an inappropriate model, and the scaled error estimates may then
 
291
be outside the range of validity for gaussian errors.
 
292
 
 
293
   </body></html>
 
294