blib/lib/PDL/Fit/Levmar.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 213 | 281 | 75.8 |
branch | 104 | 156 | 66.6 |
condition | 50 | 75 | 66.6 |
subroutine | 17 | 20 | 85.0 |
pod | 3 | 11 | 27.2 |
total | 387 | 543 | 71.2 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | |||||||
2 | # | ||||||
3 | # GENERATED WITH PDL::PP! Don't modify! | ||||||
4 | # | ||||||
5 | package PDL::Fit::Levmar; | ||||||
6 | |||||||
7 | @EXPORT_OK = qw( levmar levmar_report levmar_chkjac PDL::PP levmar_der_lb PDL::PP levmar_der_lb_ub PDL::PP levmar_der_ub PDL::PP levmar_der_ PDL::PP levmar_diff_lb PDL::PP levmar_diff_lb_ub PDL::PP levmar_diff_ub PDL::PP levmar_diff_ PDL::PP _levmar_chkjac PDL::PP _levmar_chkjac_no_t ); | ||||||
8 | %EXPORT_TAGS = (Func=>[@EXPORT_OK]); | ||||||
9 | |||||||
10 | 7 | 7 | 1386890 | use PDL::Core; | |||
7 | 29 | ||||||
7 | 35 | ||||||
11 | 7 | 7 | 1426 | use PDL::Exporter; | |||
7 | 11 | ||||||
7 | 31 | ||||||
12 | 7 | 7 | 170 | use DynaLoader; | |||
7 | 17 | ||||||
7 | 1332 | ||||||
13 | |||||||
14 | |||||||
15 | |||||||
16 | $PDL::Fit::Levmar::VERSION = '0.0100'; | ||||||
17 | @ISA = ( 'PDL::Exporter','DynaLoader' ); | ||||||
18 | push @PDL::Core::PP, __PACKAGE__; | ||||||
19 | bootstrap PDL::Fit::Levmar $VERSION; | ||||||
20 | |||||||
21 | |||||||
22 | |||||||
23 | |||||||
24 | #use Data::Dumper; | ||||||
25 | |||||||
26 | =head1 NAME | ||||||
27 | |||||||
28 | PDL::Fit::Levmar - Levenberg-Marquardt fit/optimization routines | ||||||
29 | |||||||
30 | =head1 DESCRIPTION | ||||||
31 | |||||||
32 | Levenberg-Marquardt routines for least-squares fit to | ||||||
33 | functions non-linear in fit parameters. | ||||||
34 | |||||||
35 | This module provides a L |
||||||
36 | library levmar 2.5 (written in C). Levmar is | ||||||
37 | L |
||||||
38 | or finite difference derivatives (in case no analytic | ||||||
39 | derivatives are supplied), L |
||||||
40 | and/or L |
||||||
41 | constraints (with L |
||||||
42 | case) and pure single or double precision computation. The | ||||||
43 | routines are re-entrant, so they can be used in | ||||||
44 | multi-threaded applications (not tested!). Levmar is suited | ||||||
45 | both for data fitting and for optimization problems. | ||||||
46 | |||||||
47 | The source code for the C levmar library is included in this | ||||||
48 | distribution. However, linearly-constrained fitting requires | ||||||
49 | that C |
||||||
50 | and B |
||||||
51 | F |
||||||
52 | C |
||||||
53 | the fitting options C, C, C |
||||||
54 | not be used. All other options, including C |
||||||
55 | require C |
||||||
56 | |||||||
57 | User supplied fit functions can be written in perl code that | ||||||
58 | takes pdls as arguments, or, for efficiency, in in a simple | ||||||
59 | function description language (C |
||||||
60 | transparently translated to C, compiled, and dynamically | ||||||
61 | linked. Fit functions may also be written in pure C. If C | ||||||
62 | or C |
||||||
63 | procedure is done in pure compiled C. The compilation and | ||||||
64 | linking is done only the first time the function is defined. | ||||||
65 | |||||||
66 | There is a document distributed with this module | ||||||
67 | F<./doc/levmar.pdf> by the author of liblevmar describing | ||||||
68 | the fit algorithms. Additional information on liblevmar is available at | ||||||
69 | L |
||||||
70 | |||||||
71 | Don't confuse this module with, but see also, L |
||||||
72 | |||||||
73 | =head1 SYNOPSIS | ||||||
74 | |||||||
75 | use PDL::Fit::Levmar; | ||||||
76 | $result_hash = levmar($params,$x,$t, FUNC => ' | ||||||
77 | function somename | ||||||
78 | x = p0 * exp(-t*t * p1);'); | ||||||
79 | print levmar_report($result_hash); | ||||||
80 | |||||||
81 | |||||||
82 | =head1 EXAMPLES | ||||||
83 | |||||||
84 | |||||||
85 | A number of examples of invocations of C |
||||||
86 | directory C<./t> in the module distribution contains many more examples. | ||||||
87 | The following seven examples are included as stand-alone scripts in the | ||||||
88 | ./examples/ directory. Some of the necessary lines are not repeated in | ||||||
89 | each example below. | ||||||
90 | |||||||
91 | =over 3 | ||||||
92 | |||||||
93 | =item example--1 | ||||||
94 | |||||||
95 | In this example we fill co-ordinate $t and ordinate $x arrays | ||||||
96 | with 100 pairs of sample data. Then we call the fit routine | ||||||
97 | with initial guesses of the parameters. | ||||||
98 | |||||||
99 | use PDL::LiteF; | ||||||
100 | use PDL::Fit::Levmar; | ||||||
101 | use PDL::NiceSlice; | ||||||
102 | |||||||
103 | $n = 100; | ||||||
104 | $t = 10 * (sequence($n)/$n -1/2); | ||||||
105 | $x = 3 * exp(-$t*$t * .3 ); | ||||||
106 | $p = pdl [ 1, 1 ]; # initial parameter guesses | ||||||
107 | |||||||
108 | $h = levmar($p,$x,$t, FUNC => | ||||||
109 | ' function | ||||||
110 | x = p0 * exp( -t*t * p1); | ||||||
111 | '); | ||||||
112 | print levmar_report($h); | ||||||
113 | |||||||
114 | This example gives the output: | ||||||
115 | |||||||
116 | Estimated parameters: [ 3 0.3] | ||||||
117 | Covariance: | ||||||
118 | [ | ||||||
119 | [5.3772081e-25 7.1703376e-26] | ||||||
120 | [7.1703376e-26 2.8682471e-26] | ||||||
121 | ] | ||||||
122 | |||||||
123 | ||e||_2 at initial parameters = 125.201 | ||||||
124 | Errors at estimated parameters: | ||||||
125 | ||e||_2 = 8.03854e-22 | ||||||
126 | ||J^T e||_inf = 2.69892e-05 | ||||||
127 | ||Dp||_2 = 3.9274e-15 | ||||||
128 | \mu/max[J^T J]_ii ] = 1.37223e-05 | ||||||
129 | number of iterations = 15 | ||||||
130 | reason for termination: = stopped by small ||e||_2 | ||||||
131 | number of function evaluations = 20 | ||||||
132 | number of jacobian evaluations = 2 | ||||||
133 | |||||||
134 | In the example above and all following examples, it is necessary | ||||||
135 | to include the three C | ||||||
136 | The fit function in this example is in C |
||||||
137 | The parameter pdl $p is the input parameters (guesses) | ||||||
138 | levmar returns a hash with several elements including a | ||||||
139 | plain text report of the fit, which we chose to print. | ||||||
140 | |||||||
141 | The interface is flexible-- we could have also called levmar like this | ||||||
142 | |||||||
143 | $h = levmar($p,$x,$t, ' function | ||||||
144 | x = p0 * exp( -t*t * p1); | ||||||
145 | '); | ||||||
146 | |||||||
147 | or like this | ||||||
148 | |||||||
149 | $h = levmar(P =>$p, X => $x, T=> $t, FUNC => ' function | ||||||
150 | x = p0 * exp( -t*t * p1); | ||||||
151 | '); | ||||||
152 | |||||||
153 | After the fit, the input parameters $p are left | ||||||
154 | unchanged. The output hash $h contains, among other things, | ||||||
155 | the optimized parameters in $h->{P}. | ||||||
156 | |||||||
157 | =item example--2 | ||||||
158 | |||||||
159 | Next, we do the same fit, but with a perl/PDL fit function. | ||||||
160 | |||||||
161 | $h = levmar($p,$x,$t, FUNC => sub { | ||||||
162 | my ($p,$x,$t) = @_; | ||||||
163 | my ($p0,$p1) = list $p; | ||||||
164 | $x .= $p0 * exp(-$t*$t * $p1); | ||||||
165 | }); | ||||||
166 | |||||||
167 | Using perl code (second example) results in slower execution | ||||||
168 | than using pure C (first example). How much slower depends | ||||||
169 | on the problem (see L below). See also the | ||||||
170 | section on L |
||||||
171 | |||||||
172 | =item example--3 | ||||||
173 | |||||||
174 | Next, we solve the same problem using a C fit routine. | ||||||
175 | |||||||
176 | levmar($p,$x,$t, FUNC => ' | ||||||
177 | #include |
||||||
178 | void gaussian(FLOAT *p, FLOAT *x, int m, int n, FLOAT *t) | ||||||
179 | { | ||||||
180 | int i; | ||||||
181 | for(i=0; i | ||||||
182 | x[i] = p[0] * exp( -t[i]*t[i] * p[1]); | ||||||
183 | } | ||||||
184 | '); | ||||||
185 | |||||||
186 | The macro C |
||||||
187 | the C code will be used for both single and double precision | ||||||
188 | routines. ( The code is automatically compiled twice; once | ||||||
189 | with C |
||||||
190 | The correct version is used automatically depending on the | ||||||
191 | type of pdls you give levmar. | ||||||
192 | |||||||
193 | |||||||
194 | =item example--4 | ||||||
195 | |||||||
196 | We supply an analytic derivative ( analytic jacobian). | ||||||
197 | |||||||
198 | $st = ' | ||||||
199 | function | ||||||
200 | x = p0 * exp( -t*t * p1); | ||||||
201 | |||||||
202 | jacobian | ||||||
203 | FLOAT ex, arg; | ||||||
204 | loop | ||||||
205 | arg = -t*t * p1; | ||||||
206 | ex = exp(arg); | ||||||
207 | d0 = ex; | ||||||
208 | d1 = -p0 * t*t * ex ; | ||||||
209 | |||||||
210 | '; | ||||||
211 | |||||||
212 | $h = levmar($p,$x,$t, FUNC => $st); | ||||||
213 | |||||||
214 | If no jacobian function is supplied, levmar automatically | ||||||
215 | uses numeric difference derivatives. You can also explicitly | ||||||
216 | use numeric derivatives with the option C |
||||||
217 | C<< => 'numeric' >>. | ||||||
218 | |||||||
219 | Note that the directives C |
||||||
220 | the function definitions. You can also supply a name if | ||||||
221 | you like, eg. C |
||||||
222 | |||||||
223 | In C |
||||||
224 | ordinate data by 'x' in the fit function and by 'dn', with n a | ||||||
225 | number, in the jacobian. The parameters are identified by | ||||||
226 | 'p'. All other identifiers are pure C identifiers and | ||||||
227 | must be defined, as are C |
||||||
228 | |||||||
229 | Referring to the example above, if the directive C |
||||||
230 | on a line by itself, code after it is wrapped in a loop over | ||||||
231 | the data; code before it is not. If C |
||||||
232 | then all the code is wrapped in a loop. 'loop' must occur zero | ||||||
233 | or one times in each of the fit and jacobian definitions. | ||||||
234 | For some problems, you will not want a loop at all. In this | ||||||
235 | case the directive C |
||||||
236 | |||||||
237 | To see what C |
||||||
238 | and look at the C source file that is written. | ||||||
239 | |||||||
240 | When defining the derivatives above (d0, d1) etc., you must | ||||||
241 | put the lines in the proper order ( eg, not d1,d0 ). (This | ||||||
242 | is for efficiency, see the generated C code.) | ||||||
243 | |||||||
244 | One final note on this example-- we declared C |
||||||
245 | be type C |
||||||
246 | have hard coded them to double, in which case both the float | ||||||
247 | and double code versions would have used type double for them. | ||||||
248 | This is ok, because it doesn't cost any storage or cause | ||||||
249 | a memory fault because of incorrect pointer arithmetic. | ||||||
250 | |||||||
251 | |||||||
252 | =item example--5 | ||||||
253 | |||||||
254 | Here is an example from the liblevmar demo program that shows | ||||||
255 | one more bit of C |
||||||
256 | |||||||
257 | $defst = " | ||||||
258 | function modros | ||||||
259 | noloop | ||||||
260 | x0 = 10 * (p1 -p0*p0); | ||||||
261 | x1 = 1.0 - p0; | ||||||
262 | x2 = 100; | ||||||
263 | jacobian jacmodros | ||||||
264 | noloop | ||||||
265 | d0[0] = -20 * p0; | ||||||
266 | d1[0] = 10; | ||||||
267 | d0[1] = -1; | ||||||
268 | d1[1] = 0; | ||||||
269 | d0[2] = 0; | ||||||
270 | d1[2] = 0; | ||||||
271 | "; | ||||||
272 | $p = pdl [-1.2, 1]; | ||||||
273 | $x = pdl [0,0,0]; | ||||||
274 | $h = levmar( $p,$x, FUNC => $defst ); | ||||||
275 | |||||||
276 | The directive C |
||||||
277 | indicating that there are no implied loops in the | ||||||
278 | function. Note that this model function is designed only for | ||||||
279 | $x->nelem == 3. The additional syntax is in the | ||||||
280 | derivatives. Keeping in mind that there is no loop variable, | ||||||
281 | dq[r] means derivative w.r.t q evaluated at x[r]. (This is | ||||||
282 | translated by C |
||||||
283 | 1-d array.) | ||||||
284 | |||||||
285 | =item example--6 | ||||||
286 | |||||||
287 | Here is an example that uses implicit threading. We create data | ||||||
288 | from a gaussian function with four different sets of parameters | ||||||
289 | and fit it all in one function call. | ||||||
290 | |||||||
291 | $st = ' | ||||||
292 | function | ||||||
293 | x = p0 * exp( -t*t * p1); | ||||||
294 | '; | ||||||
295 | |||||||
296 | $n = 10; | ||||||
297 | $t = 10 * (sequence($n)/$n -1/2); | ||||||
298 | $x = zeroes($n,4); | ||||||
299 | map { $x(:,$_->[0]) .= $_->[1] * exp(-$t*$t * $_->[2] ) } | ||||||
300 | ( [0,3,.2], [1, 28, .1] , [2,2,.01], [3,3,.3] ); | ||||||
301 | $p = [ 5, 1]; # initial guess | ||||||
302 | $h = levmar($p,$x,$t, FUNC => $st ); | ||||||
303 | print $h->{P} . "\n"; | ||||||
304 | |||||||
305 | [ | ||||||
306 | [ 3 0.2] | ||||||
307 | [ 28 0.1] | ||||||
308 | [ 2 0.01] | ||||||
309 | [ 3 0.3] | ||||||
310 | ] | ||||||
311 | |||||||
312 | |||||||
313 | =item example--7 | ||||||
314 | |||||||
315 | This example shows how to fit a bivariate Gaussian. Here | ||||||
316 | is the fit function. | ||||||
317 | |||||||
318 | sub gauss2d { | ||||||
319 | my ($p,$xin,$t) = @_; | ||||||
320 | my ($p0,$p1,$p2) = list $p; | ||||||
321 | my $n = $t->nelem; | ||||||
322 | my $t1 = $t(:,*$n); # first coordinate | ||||||
323 | my $t2 = $t(*$n,:); # second coordinate | ||||||
324 | my $x = $xin->splitdim(0,$n); | ||||||
325 | $x .= $p0 * exp( -$p1*$t1*$t1 - $p2*$t2*$t2); | ||||||
326 | } | ||||||
327 | |||||||
328 | |||||||
329 | We would prefer a function that maps t(n,n) --> x(n,n) (with | ||||||
330 | p viewed as parameters.) But the levmar library expects one | ||||||
331 | dimensional x and t. So we design C |
||||||
332 | piddles with these dimensions: C , C |
||||||
333 | C |
||||||
334 | axes run over the same range, so we only need to pass n | ||||||
335 | values for t. The piddles t1 and t2 are (virtual) copies of | ||||||
336 | t with dummy dimensions inserted. Each represents | ||||||
337 | co-ordinate values along each of the two axes at each point | ||||||
338 | in the 2-d space, but independent of the position along the | ||||||
339 | other axis. For instance C | ||||||
340 | == t(j)>. We assume that the piddle xin is a flattened | ||||||
341 | version of the ordinate data, so we split the dimensions in | ||||||
342 | x. Then the entire bi-variate gaussian is calculated with | ||||||
343 | one line that operates on 2-d matrices. Now we create some | ||||||
344 | data, | ||||||
345 | |||||||
346 | my $n = 101; # number of data points along each axis | ||||||
347 | my $scale = 3; # range of co-ordiate data | ||||||
348 | my $t = sequence($n); # co-ordinate data (used for both axes) | ||||||
349 | $t *= $scale/($n-1); | ||||||
350 | $t -= $scale/2; # rescale and shift. | ||||||
351 | my $x = zeroes($n,$n); | ||||||
352 | my $p = pdl [ .5,2,3]; # actual parameters | ||||||
353 | my $xlin = $x->clump(-1); # flatten the x data | ||||||
354 | gauss2d( $p, $xlin, $t->copy); # compute the bivariate gaussian data. | ||||||
355 | |||||||
356 | Now x contains the ordinate data (so does xlin, but in a flattened shape.) | ||||||
357 | Finally, we fit the data with an incorrect set of initial parameters, | ||||||
358 | |||||||
359 | my $p1 = pdl [ 1,1,1]; # not the parameters we used to make the data | ||||||
360 | my $h = levmar($p1,$xlin,$t,\&gauss2d); | ||||||
361 | |||||||
362 | At this point C<$h->{P}> refers to the output parameter piddle C<[0.5, 2, 3]>. | ||||||
363 | |||||||
364 | =back | ||||||
365 | |||||||
366 | =head1 CONSTRAINTS | ||||||
367 | |||||||
368 | Several of the options below are related to constraints. There are | ||||||
369 | three types: box, linear equation, and linear inequality. They may | ||||||
370 | be used in any combination. (But there is no testing if | ||||||
371 | there is a possible solution.) None or one or two of C |
||||||
372 | specified. None or both of C and C may be specified. | ||||||
373 | None or both of C |
||||||
374 | |||||||
375 | =head1 OPTIONS | ||||||
376 | |||||||
377 | It is best to learn how to call levmar by looking at the | ||||||
378 | examples first, and looking at this section later. | ||||||
379 | |||||||
380 | levmar() is called like this | ||||||
381 | |||||||
382 | levmar($arg1, $arg2, ..., OPT1=>$val1, OPT2=>$val2, ...); | ||||||
383 | or this: | ||||||
384 | levmar($arg1, $arg2, ..., {OPT1=>$val1, OPT2=>$val2, ...}); | ||||||
385 | |||||||
386 | When calling levmar, the first 3 piddle arguments (or refs | ||||||
387 | to arrays), if present, are taken to be C<$p>,C<$x>, and C<$t> | ||||||
388 | (parameters, ordinate data, and co-ordinate data) in that | ||||||
389 | order. The first scalar value that can be interpreted as a | ||||||
390 | function will be. Everything else must be passed as an | ||||||
391 | option in a key-value pair. If you prefer, you can pass some | ||||||
392 | or all of C<$p,$x,$t> and the function as key-values in the | ||||||
393 | hash. Note that after the first key-value pair, you cannot | ||||||
394 | pass any more non-hash arguments. The following calls are equivalent | ||||||
395 | (where $func specifies the function as described in L ). | ||||||
396 | |||||||
397 | levmar($p, $x, $t, $func); | ||||||
398 | levmar($func,$p, $x, $t); | ||||||
399 | levmar($p, $x, $t, FUNC=> $func); | ||||||
400 | levmar($p, $x, T=>$t, FUNC => $func); | ||||||
401 | levmar($p, X=>$x, T=>$t, FUNC => $func); | ||||||
402 | levmar(P=>$p, X=>$x, T=>$t, FUNC => $func); | ||||||
403 | |||||||
404 | In the following, if the default value is not mentioned, it is undef. | ||||||
405 | C<$outh> refers to the output hash. | ||||||
406 | |||||||
407 | Some of these options are actually options to Levmar::Func. | ||||||
408 | All options to Levmar::Func may by given in calls to levmar(). | ||||||
409 | |||||||
410 | =over 4 | ||||||
411 | |||||||
412 | =item FUNC | ||||||
413 | |||||||
414 | This option is required (but it can be passed before the | ||||||
415 | options hash without the key C |
||||||
416 | any of the following, which are auto-detected. | ||||||
417 | |||||||
418 | a string containing lpp code | ||||||
419 | a string containing pure C code | ||||||
420 | the filename of a file containing lpp code (which must end in '.lpp' ) | ||||||
421 | the filename of a file containing pure C code ( which must end in '.c' ) | ||||||
422 | a reference to perl code | ||||||
423 | a reference to a previously created Levmar::Func object (which was | ||||||
424 | previously created via one of the preceeding methods.) | ||||||
425 | |||||||
426 | If you are fitting a lot of data by doing many iterations over | ||||||
427 | a loop of perl code, it is by far most efficient to create a Func | ||||||
428 | object from C or lpp code and pass it to levmar. (Implicit threading | ||||||
429 | does not recompile code in any case.) | ||||||
430 | |||||||
431 | You can also pass pure C code via the option CSRC. | ||||||
432 | |||||||
433 | =item JFUNC | ||||||
434 | |||||||
435 | This parameter is the jacobian as a ref to perl CODE. For | ||||||
436 | C and C |
||||||
437 | same source file as the fit function; in this case, you | ||||||
438 | should leave C |
||||||
439 | |||||||
440 | =item DERIVATIVE | ||||||
441 | |||||||
442 | This takes the value 'numeric' or 'analytic'. If it is | ||||||
443 | set to 'analytic', but no analytic jacobian of the model | ||||||
444 | function is supplied, then the numeric algorithms will be used | ||||||
445 | anyway. | ||||||
446 | |||||||
447 | =item NOCLEAN | ||||||
448 | |||||||
449 | If defined (NOCLEAN => 1), files containing generated C | ||||||
450 | object and dynamic library code are not deleted. If not | ||||||
451 | defined, these files are deleted after they are no longer | ||||||
452 | needed. For the source and object (.c and .o) files, this | ||||||
453 | means immediately after the dynamic library (.so) is built. | ||||||
454 | The dynamic library file is deleted when the corresponding | ||||||
455 | Levmar::Func object is destroyed. (It could be deleted after | ||||||
456 | it is loaded, I suppose, and then be rebuilt if needed | ||||||
457 | again) | ||||||
458 | |||||||
459 | =item FIX | ||||||
460 | |||||||
461 | Example: Fix => [1,0,0,1,0]. | ||||||
462 | This option takes a pdl (or array ref) of the same shape as | ||||||
463 | the parameters $p. Each element must have the value zero or | ||||||
464 | one. A zero corresponds to a free parameter and a one to a | ||||||
465 | fixed parameter. The best fit is found keeping the fixed | ||||||
466 | parameters at their input values and letting the free | ||||||
467 | parameters vary. This is implemented by using the linear | ||||||
468 | constraint option described below. Each element must be | ||||||
469 | either one or zero. This option currently cannot be | ||||||
470 | threaded. That is, if the array FIX has more than one | ||||||
471 | dimension you will not get correct results. Also, PDL will | ||||||
472 | not add dimension correctly if you pass additional | ||||||
473 | dimensions in other quantities. Threading will work if you | ||||||
474 | use linear contstraints directly via C and C. | ||||||
475 | |||||||
476 | =item FIXB | ||||||
477 | |||||||
478 | This option is almost the same as FIX. It takes the same | ||||||
479 | values with the same meanings. It fixes parameters at the value | ||||||
480 | of the input parameters, but uses | ||||||
481 | box constraints, i.e., UB and LB rather than linear | ||||||
482 | constraints A and B. You can specify all three of UB,LB, and FIXB. | ||||||
483 | In this case, first box constraints determined by UB and LB are applied | ||||||
484 | Then, for those elements of FIXB with value one, the corresponding | ||||||
485 | values of UB and LB are overridden. | ||||||
486 | |||||||
487 | =item A | ||||||
488 | |||||||
489 | Example: A =>pdl [ [1,0], [0,1] ] , B => pdl [ 1,2 ] | ||||||
490 | |||||||
491 | Minimize with linear constraints $A x $p = $b. That is, | ||||||
492 | parameters $p are optimized over the subset of parameters | ||||||
493 | that solve the equation. The dimensions of the quantities | ||||||
494 | are A(k,m), b(m), p(m), where k is the number of | ||||||
495 | constraints. ( k <= m ). Note that $b is a vector (it has one | ||||||
496 | fewer dimensions than A), but the option key is a capital 'B'. | ||||||
497 | |||||||
498 | =item B | ||||||
499 | |||||||
500 | See C. | ||||||
501 | |||||||
502 | =item UB | ||||||
503 | |||||||
504 | Example: UB => [10,10,10], LB => [-10,0,-5]. | ||||||
505 | Box constraints. These have the same shape as the parameter | ||||||
506 | pdl $p. The fit is done with ub forming upper bounds and lb | ||||||
507 | lower bounds on the parameter values. Use, for instance | ||||||
508 | PDL::Fit::Levmar::get_dbl_max() for parameters that you | ||||||
509 | don't want bounded. You can use either linear constraints or | ||||||
510 | box constraints, or both. That is, you may specify A, B, UB, and LB. | ||||||
511 | |||||||
512 | =item LB | ||||||
513 | |||||||
514 | See C |
||||||
515 | |||||||
516 | |||||||
517 | =item WGHTS | ||||||
518 | |||||||
519 | Penalty weights can be given optionally when box and linear equality | ||||||
520 | constraints are both passed to levmar. See the levmar documenation for | ||||||
521 | how to use this. Note that if C and D are used then the WGHTS must | ||||||
522 | not passed. | ||||||
523 | |||||||
524 | =item C | ||||||
525 | |||||||
526 | Example: C => [ [ -1, -2, -1, -1], [ -3, -1, -2, 1] ], D => [ -5, -0.4] | ||||||
527 | Linear inequality constraints. Minimize with constraints $C x $p >= $d. | ||||||
528 | The dimensions are C(k2,m), D(m), p(m). | ||||||
529 | |||||||
530 | =item D | ||||||
531 | |||||||
532 | See C |
||||||
533 | |||||||
534 | =item P | ||||||
535 | |||||||
536 | Keys P, X, and T can be used to send to the parameters, ordinates and coordinates. | ||||||
537 | Alternatively, you can send them as non-option arguments to levmar before | ||||||
538 | the option arguments. | ||||||
539 | |||||||
540 | =item X | ||||||
541 | |||||||
542 | See C
|
||||||
543 | |||||||
544 | =item T | ||||||
545 | |||||||
546 | See C
|
||||||
547 | |||||||
548 | =item DIR | ||||||
549 | |||||||
550 | The directory containing files created when compiling C |
||||||
551 | and C fit functions. This defaults to './tempcode'; The .c, | ||||||
552 | .o, and .so files will be written to this directory. This | ||||||
553 | option actually falls through to levmar_func. Such options | ||||||
554 | should be in separate section, or otherwise noted. | ||||||
555 | |||||||
556 | =item GETOPTS | ||||||
557 | |||||||
558 | If defined, return a ref to a hash containing the default | ||||||
559 | values of the parameters. | ||||||
560 | |||||||
561 | =item WORK | ||||||
562 | |||||||
563 | levmar() needs some storage for scratch space. Normally, you | ||||||
564 | are not concerned with this-- the storage is allocated and | ||||||
565 | deallocated automatically without you being aware. However | ||||||
566 | if you have very large data sets, and are doing several | ||||||
567 | fits, this allocation and deallocation may be time consuming | ||||||
568 | (the time required to allocate storage grows faster than | ||||||
569 | linearly with the amount of storage). If you are using | ||||||
570 | implicit threading, the storage is only allocated once | ||||||
571 | outside the threadloop even if you don't use this | ||||||
572 | option. However, you may want to do several fits on the perl | ||||||
573 | level and want to allocate the work space only once. | ||||||
574 | |||||||
575 | If you set WORK to a null piddle (say $work) and keep the | ||||||
576 | reference and call levmar(), storage will be created before | ||||||
577 | the fit. If you continue to call levmar() with WORK => | ||||||
578 | $work, no new storage will be created. In this example, | ||||||
579 | |||||||
580 | sub somefitting { | ||||||
581 | my $work = PDL->null; | ||||||
582 | ... | ||||||
583 | while (1) { | ||||||
584 | my $h = levmar($p, ... ,WORK => $work); | ||||||
585 | ... change inputs based on results in $h | ||||||
586 | last if somecondition is true; | ||||||
587 | } | ||||||
588 | ... | ||||||
589 | } | ||||||
590 | |||||||
591 | storage is created in the first call to C |
||||||
592 | destroyed upon leaving the subroutine C |
||||||
593 | (provided a reference to $work was not stored in some data | ||||||
594 | structure delclared in an block enclosing the subroutine.) | ||||||
595 | |||||||
596 | The numeric-derivative algorithms require more storage than | ||||||
597 | the analytic-derivative algorithms. So if you create the | ||||||
598 | storage for $work on a call with DERIVATIVE=>'numeric' and | ||||||
599 | subsequently make a call with DERIVATIVE=>'analytic' you are | ||||||
600 | ok. But if you try it in the other order, you will get a | ||||||
601 | runtime error. You can also pass a pdl created elsewhere | ||||||
602 | with the correct type and enough or more than enough storage. | ||||||
603 | |||||||
604 | There are several pdls used by levmar() that have a similar option. | ||||||
605 | |||||||
606 | (see also in PDL::Indexing ) | ||||||
607 | |||||||
608 | =item COVAR | ||||||
609 | |||||||
610 | Send a pdl reference for the output hash element COVAR. You may | ||||||
611 | want to test if this option is more efficient for | ||||||
612 | some problem. But unless the covariance matrix is very large, | ||||||
613 | it probably won't help much. On the other hand it almost certainly | ||||||
614 | won't make levmar() less efficient. See the section on WORK above. | ||||||
615 | |||||||
616 | Note that levmar returns a piddle representing the covariance in | ||||||
617 | the output hash. This will be the the same piddle that you give | ||||||
618 | as input via this option. So, if you do the following, | ||||||
619 | |||||||
620 | my $covar = PDL->null | ||||||
621 | my $h =levmar(...., COVAR => $covar); | ||||||
622 | |||||||
623 | then $covar and $h->{COVAR} are references to the same | ||||||
624 | pdl. The storage for the pdl will not be destroyed until | ||||||
625 | both $covar and $h->{COVAR} become undefined. The option | ||||||
626 | C |
||||||
627 | the workspace is not returned in the hash. | ||||||
628 | |||||||
629 | =item NOCOVAR | ||||||
630 | |||||||
631 | If defined, no covariance matrix is computed. | ||||||
632 | |||||||
633 | =item POUT | ||||||
634 | |||||||
635 | Send a pdl reference for the output hash element P. Don't | ||||||
636 | confuse this with the option P which can be used to send the | ||||||
637 | initial guess for the parameters | ||||||
638 | (see C |
||||||
639 | |||||||
640 | =item INFO | ||||||
641 | |||||||
642 | Send a pdl reference for the output hash element C |
||||||
643 | (see C |
||||||
644 | |||||||
645 | =item RET | ||||||
646 | |||||||
647 | Send a pdl reference for the output hash element C |
||||||
648 | (see C |
||||||
649 | |||||||
650 | |||||||
651 | =item MAXITS | ||||||
652 | |||||||
653 | Maximum number of iterations to try before giving up. The default | ||||||
654 | is 100. | ||||||
655 | |||||||
656 | =item MU | ||||||
657 | |||||||
658 | The starting value of the parameter mu in the L-M algorithm. | ||||||
659 | |||||||
660 | =item EPS1, EPS2, EPS3 | ||||||
661 | |||||||
662 | Stopping thresholds for C<||J^T e||_inf>, C<||Dp||_2> and | ||||||
663 | C<||e||_2>. (see the document levmar.pdf by the author of | ||||||
664 | liblevmar and distributed with this module) The algorithm | ||||||
665 | stops when the first threshold is reached (or C |
||||||
666 | C |
||||||
667 | |||||||
668 | Here, C |
||||||
669 | the model function and C is the vector of parameters. |
||||||
670 | S<||J^T e||_inf> is the gradient of C
|
||||||
671 | at the current estimate of C ; C<||Dp||_2> is the amount |
||||||
672 | by which C is currently being shifted at each iteration; |
||||||
673 | C<||e||_2> is a measure of the error between the model function | ||||||
674 | at the current estimate for C and the data. |
||||||
675 | |||||||
676 | =item DELTA | ||||||
677 | |||||||
678 | This is a step size used in computing numeric derivatives. It is | ||||||
679 | not used if the analytic jacobian is used. | ||||||
680 | |||||||
681 | |||||||
682 | =item MKOBJ | ||||||
683 | |||||||
684 | command to compile source into object code. This option is actually set in | ||||||
685 | the Levmar::Func object, but can be given in calls to levmar(). | ||||||
686 | The default value is determined by the perl installation and can | ||||||
687 | be determined by examining the Levmar::Func object returned by | ||||||
688 | new or the output hash of a call to levmar. A typical value is | ||||||
689 | cc -c -O2 -fPIC -o %o %c | ||||||
690 | |||||||
691 | =item MKSO | ||||||
692 | |||||||
693 | command to convert object code to dynamic library code. | ||||||
694 | This option is actually set in the Levmar::Func object. A | ||||||
695 | typical default value is | ||||||
696 | cc -shared -L/usr/local/lib -fstack-protector %o -o %s | ||||||
697 | |||||||
698 | =item CTOP | ||||||
699 | |||||||
700 | The value of this string will be written at the top of the c code | ||||||
701 | written by Levmar::Func. This can be used to include headers and so forth. | ||||||
702 | This option is actually set in the Levmar::Func object. This code is also written | ||||||
703 | at the top of c code translated from lpp code. | ||||||
704 | |||||||
705 | |||||||
706 | =item FVERBOSE | ||||||
707 | |||||||
708 | If true (eg 1) Print the compiling and linking commands to STDERR when compiling fit functions. | ||||||
709 | This option is actually passed to Levmar::Func. Default is 0. | ||||||
710 | |||||||
711 | =item Default values | ||||||
712 | |||||||
713 | Here are the default values | ||||||
714 | of some options | ||||||
715 | |||||||
716 | |||||||
717 | $Levmar_defaults = { | ||||||
718 | FUNC => undef, # Levmar::Func object, or function def, or ... | ||||||
719 | JFUNC => undef, # must be ref to perl sub | ||||||
720 | MAXITS => 100, # maximum iterations | ||||||
721 | MU => LM_INIT_MU, # These are described in levmar docs | ||||||
722 | EPS1 => LM_STOP_THRESH, | ||||||
723 | EPS2 => LM_STOP_THRESH, | ||||||
724 | EPS3 => LM_STOP_THRESH, | ||||||
725 | DELTA => LM_DIFF_DELTA, | ||||||
726 | DERIVATIVE => 'analytic', | ||||||
727 | FIX => undef, | ||||||
728 | A => undef, | ||||||
729 | B => undef, | ||||||
730 | C => undef, | ||||||
731 | D => undef, | ||||||
732 | UB = undef, | ||||||
733 | LB => undef, | ||||||
734 | X => undef, | ||||||
735 | P => undef, | ||||||
736 | T => undef, | ||||||
737 | WGHTS => undef, | ||||||
738 | # meant to be private | ||||||
739 | LFUNC => undef, # only Levmar::Func object, made from FUNC | ||||||
740 | }; | ||||||
741 | |||||||
742 | =back | ||||||
743 | |||||||
744 | |||||||
745 | =head1 OUTPUT | ||||||
746 | |||||||
747 | This section describes the contents of the hash that | ||||||
748 | levmar takes as output. Do not confuse these hash keys with | ||||||
749 | the hash keys of the input options. It may be a good idea | ||||||
750 | to change the interface by prepending O to all of the output | ||||||
751 | keys that could be confused with options to levmar(). | ||||||
752 | |||||||
753 | =over 3 | ||||||
754 | |||||||
755 | =item P (output) | ||||||
756 | |||||||
757 | pdl containing the optimized parameters. It has the same shape | ||||||
758 | as the input parameters. | ||||||
759 | |||||||
760 | =item FUNC (output) | ||||||
761 | |||||||
762 | ref to the Levmar::Func object. This object may have been created | ||||||
763 | during the call to levmar(). For instance, if you pass a string | ||||||
764 | contiaining an C |
||||||
765 | information) is contained in $outh->{FUNC}. Don't confuse this with | ||||||
766 | the input parameter of the same name. | ||||||
767 | |||||||
768 | =item COVAR (output) | ||||||
769 | |||||||
770 | a pdl representing covariance matrix. | ||||||
771 | |||||||
772 | =item REASON | ||||||
773 | |||||||
774 | an integer code representing the reason for terminating the | ||||||
775 | fit. (call levmar_report($outh) for an interpretation. The interpretations | ||||||
776 | are listed here as well (see the liblevmar documentation if you don't | ||||||
777 | find an explanation somewhere here.) | ||||||
778 | |||||||
779 | 1 stopped by small gradient J^T e | ||||||
780 | 2 stopped by small Dp | ||||||
781 | 3 stopped by itmax | ||||||
782 | 4 singular matrix. Restart from current p with increased \mu | ||||||
783 | 5 no further error reduction is possible. Restart with increased \mu | ||||||
784 | 6 stopped by small ||e||_2 | ||||||
785 | |||||||
786 | |||||||
787 | =item ERRI, ERR1, ERR2, ERR3, ERR4 | ||||||
788 | |||||||
789 | ERRI is C<||e||_2> at the initial paramters. ERR1 through | ||||||
790 | ERR3 are the actual values on termination of the quantities | ||||||
791 | corresponding to the thresholds EPS1 through EPS3 described | ||||||
792 | in the options section. ERR4 is C |
||||||
793 | |||||||
794 | =item ITS | ||||||
795 | |||||||
796 | Number of iterations performed | ||||||
797 | |||||||
798 | =item NFUNC, NJAC, NLS | ||||||
799 | |||||||
800 | Number of function evaluations, number of jacobian evaluations | ||||||
801 | and number of linear systems solved. | ||||||
802 | |||||||
803 | =item INFO | ||||||
804 | |||||||
805 | Array containing ERRI,ERR1, ..., ERR4, ITS, REASON, NFUNC, NJAC, NLS. | ||||||
806 | |||||||
807 | =back | ||||||
808 | |||||||
809 | =head1 FIT FUNCTIONS | ||||||
810 | |||||||
811 | Fit functions, or model functions can be specified in the following | ||||||
812 | ways. | ||||||
813 | |||||||
814 | =over 3 | ||||||
815 | |||||||
816 | =item lpp | ||||||
817 | |||||||
818 | It is easier to learn to use C |
||||||
819 | |||||||
820 | C |
||||||
821 | the opening and closing parts of the function, alters a | ||||||
822 | small number of identifiers if they appear, and wraps some | ||||||
823 | of the code in a loop. C |
||||||
824 | must occur on a line with nothing else, not even comments. | ||||||
825 | |||||||
826 | First, the directives are explained, then the substitutions. | ||||||
827 | The directive lines have a strict format. All other lines | ||||||
828 | can contain any C code including comments and B |
||||||
829 | macros. They will be written to a function in C after the | ||||||
830 | substitutions described below. | ||||||
831 | |||||||
832 | =over 3 | ||||||
833 | |||||||
834 | =item C |
||||||
835 | |||||||
836 | The first line of the fit function definition must be | ||||||
837 | C |
||||||
838 | definition, if the jacobian is to be defined, is C | ||||||
839 | funcname>. The function names can be any valid C function | ||||||
840 | name. The names may also be omitted as they are never needed | ||||||
841 | by the user. The names can be identical. (Note that a | ||||||
842 | numeric suffix will be automatically added to the function | ||||||
843 | name if the .so file already exists. This is because, if | ||||||
844 | another Func object has already loaded the shared library | ||||||
845 | from an .so file, dlopen will use this loaded library for | ||||||
846 | all C |
||||||
847 | file has been overwritten, causing unexpected behavior) | ||||||
848 | |||||||
849 | =item C |
||||||
850 | |||||||
851 | The directive C |
||||||
852 | in the implicit loop, while all code following C |
||||||
853 | the implicit loop. If you omit the directive, then all the code | ||||||
854 | is wrapped in a loop. | ||||||
855 | |||||||
856 | =item C |
||||||
857 | |||||||
858 | The directive C |
||||||
859 | in the function. | ||||||
860 | |||||||
861 | =item Out-of-loop substitutions | ||||||
862 | |||||||
863 | These substitutions translate C |
||||||
864 | before the implied loop (or everywhere if there is no loop.) | ||||||
865 | In every case you can write the translated C code into your | ||||||
866 | function definition yourself and C |
||||||
867 | untouched. | ||||||
868 | |||||||
869 | =over 3 | ||||||
870 | |||||||
871 | =item pq -> p[q] | ||||||
872 | |||||||
873 | where q is a sequence of digits. | ||||||
874 | |||||||
875 | |||||||
876 | =item xq -> x[q] | ||||||
877 | |||||||
878 | where q is a sequence of digits. This is applied only in the fit function, | ||||||
879 | not in the jacobian. | ||||||
880 | |||||||
881 | |||||||
882 | =item dq[r] -> d[q+m*r] | ||||||
883 | |||||||
884 | (where m == $p->nelem), q and r are sequences of | ||||||
885 | digits. This applies only in the jacobian. You usually will | ||||||
886 | only use the fit functions with one value of m. It would | ||||||
887 | make faster code if you were to explicitly write, say C |
||||||
888 | for each derivative at each point. Presumably there is a | ||||||
889 | small number of data points since this is outside a | ||||||
890 | loop. Some provisions should be added to C |
||||||
891 | hard code the value of C |
||||||
892 | constructions involving this substitution. | ||||||
893 | |||||||
894 | |||||||
895 | =back | ||||||
896 | |||||||
897 | =item In-loop substitutions | ||||||
898 | |||||||
899 | These substitutions apply inside the implied loop. The loop variables are | ||||||
900 | i in the fit function and i and j in the jacobian. | ||||||
901 | |||||||
902 | =over 3 | ||||||
903 | |||||||
904 | =item t -> t[i] | ||||||
905 | |||||||
906 | (literal "i") You can also write t[i] or t[expression involving i] by hand. | ||||||
907 | Example: t*t -> t[i]*t[i]. | ||||||
908 | |||||||
909 | |||||||
910 | =item pq -> p[q] | ||||||
911 | |||||||
912 | where q is a sequence of digits. Example p3 -> p[3]. | ||||||
913 | |||||||
914 | |||||||
915 | =item x -> x[i] | ||||||
916 | |||||||
917 | only in fit function, not in jacobian. | ||||||
918 | |||||||
919 | |||||||
920 | =item (dr or dr[i]) -> d[j++] | ||||||
921 | |||||||
922 | where r is a sequence of digits. Note that r and i are | ||||||
923 | ignored. So you are required to list the derivatives in | ||||||
924 | order. An example is | ||||||
925 | |||||||
926 | d0 = t*t; // derivative w.r.t p[0] loop over all points | ||||||
927 | d1 = t; | ||||||
928 | |||||||
929 | If you write C |
||||||
930 | assign the derivative functions. | ||||||
931 | |||||||
932 | =back | ||||||
933 | |||||||
934 | |||||||
935 | =back | ||||||
936 | |||||||
937 | |||||||
938 | |||||||
939 | =item C Code | ||||||
940 | |||||||
941 | The jacobian name must start with 'jac' when a pure C function definition | ||||||
942 | is used. To see example of fit functions writen in C, call levmar | ||||||
943 | with lpp code and the option C |
||||||
944 | in the directory given by C |
||||||
945 | slightly before passing it to the compiler: It is copied twice, with | ||||||
946 | FLOAT defined in one case as C |
||||||
947 | The letter C |
||||||
948 | copy. The C code is parsed to find the fit function name and the | ||||||
949 | jacobian function name. | ||||||
950 | |||||||
951 | We should make it possible to pass the function names as a separate option | ||||||
952 | rather than parsing the C code. This will allow auxiallary functions to | ||||||
953 | be defined in the C code; something that is currently not possible. | ||||||
954 | |||||||
955 | |||||||
956 | =item Perl_Subroutines | ||||||
957 | |||||||
958 | This is how to use perl subroutines as fit functions... (see | ||||||
959 | the examples for now, e.g. L |
||||||
960 | fit function takes piddles $p,$x, and $t, with dimensions | ||||||
961 | m,n, and tn. (often tn ==n ). These are references with | ||||||
962 | storage already allocated (by the user and liblevmar). So | ||||||
963 | you must use C<.=> when setting values. The jacobian takes | ||||||
964 | piddles $p,$d, and $t, where $d, the piddle of derivatives | ||||||
965 | has dimensions (m,n). For example | ||||||
966 | |||||||
967 | $f = sub myexp { | ||||||
968 | my ($p,$x,$t) = @_; | ||||||
969 | my ($p0,$p1,$p2) = list($p); | ||||||
970 | $x .= exp($t/$p0); | ||||||
971 | $x *= $p1; | ||||||
972 | $x += $p2 | ||||||
973 | } | ||||||
974 | |||||||
975 | $jf = sub my expjac { | ||||||
976 | my ($p,$d,$t) = @_; | ||||||
977 | my ($p0,$p1,$p2) = list($p); | ||||||
978 | my $arg = $t/$p0; | ||||||
979 | my $ex = exp($arg); | ||||||
980 | $d((0)) .= -$p1*$ex*$arg/$p0; | ||||||
981 | $d((1)) .= $ex; | ||||||
982 | $d((2)) .= 1.0; | ||||||
983 | } | ||||||
984 | |||||||
985 | |||||||
986 | |||||||
987 | =back | ||||||
988 | |||||||
989 | |||||||
990 | =head1 PDL::Fit::Levmar::Func Objects | ||||||
991 | |||||||
992 | These objects are created every time you call levmar(). The hash | ||||||
993 | returned by levmar contains a ref to the Func object. For instance | ||||||
994 | if you do | ||||||
995 | |||||||
996 | $outh = levmar( FUNC => ..., @opts); | ||||||
997 | |||||||
998 | then $outh->{LFUNC} will contain a ref to the function object. The .so | ||||||
999 | file, if it exists, will not be deleted until the object is destroyed. | ||||||
1000 | This will happen, for instance if you do C<$outh = undef>. | ||||||
1001 | |||||||
1002 | |||||||
1003 | =head1 IMPLEMENTATION | ||||||
1004 | |||||||
1005 | This section currently only refers to the interface and not the fit algorithms. | ||||||
1006 | |||||||
1007 | =over 3 | ||||||
1008 | |||||||
1009 | =item C fit functions | ||||||
1010 | |||||||
1011 | The module does not use perl interfaces to dlopen or the C | ||||||
1012 | compiler. The C compiler options are taken from | ||||||
1013 | %Config. This is mostly because I had already written those | ||||||
1014 | parts before I found the modules. I imagine the | ||||||
1015 | implementation here has less overhead, but is less portable. | ||||||
1016 | |||||||
1017 | |||||||
1018 | =item perl subroutine fit functions | ||||||
1019 | |||||||
1020 | Null pdls are created in C code before the fit starts. They | ||||||
1021 | are passed in a struct to the C fit function and derivative | ||||||
1022 | routines that wrap the user's perl code. At each call the | ||||||
1023 | data pointers to the pdls are set to what liblevmar has sent | ||||||
1024 | to the fit functions. The pdls are deleted after the fit. | ||||||
1025 | Originally, all the information on the fit functions was | ||||||
1026 | supposed to be handled by Levmar::Func. But when I added | ||||||
1027 | perl subroutine support, it was less clumsy to move most of | ||||||
1028 | the code for perl subs to the Levmar module. So the current | ||||||
1029 | solution is not very clean. | ||||||
1030 | |||||||
1031 | =item Efficiency | ||||||
1032 | |||||||
1033 | Using C |
||||||
1034 | faster than using L |
||||||
1035 | done. For very large data sets, pure C was twice as fast as | ||||||
1036 | perl subs and three times as fast as Fit::LM. Some | ||||||
1037 | optimization problems have very small data sets and converge | ||||||
1038 | very slowly. As the data sets become smaller and the number | ||||||
1039 | of iterations increases the advantage of using pure C | ||||||
1040 | increases as expected. Also, if I fit a small data set | ||||||
1041 | (n=10) a large number of times (just looping over the same | ||||||
1042 | problem), Pure C is ten times faster than Fit::LM, while | ||||||
1043 | Levmar with perl subs is only about 1.15 times faster than | ||||||
1044 | Fit::LM. All of this was observed on only two different | ||||||
1045 | problems. | ||||||
1046 | |||||||
1047 | =back | ||||||
1048 | |||||||
1049 | =head1 FUNCTIONS | ||||||
1050 | |||||||
1051 | =head2 levmar() | ||||||
1052 | |||||||
1053 | =for ref | ||||||
1054 | |||||||
1055 | Perform Levenberg-Marquardt non-linear least squares fit | ||||||
1056 | to data given a model function. | ||||||
1057 | |||||||
1058 | =for usage | ||||||
1059 | |||||||
1060 | use PDL::Fit::Levmar; | ||||||
1061 | |||||||
1062 | $result_hash = levmar($p,$x,$t, FUNC => $func, %OPTIONS ); | ||||||
1063 | |||||||
1064 | $p is a pdl of input parameters | ||||||
1065 | $x is a pdl of ordinate data | ||||||
1066 | $t is an optional pdl of co-ordinate data | ||||||
1067 | |||||||
1068 | levmar() is the main function in the Levmar package. See the | ||||||
1069 | PDL::Fit::Levmar for a complete description. | ||||||
1070 | |||||||
1071 | =for signature | ||||||
1072 | |||||||
1073 | p(m); x(n); t(nt); int itmax(); | ||||||
1074 | [o] covar(m,m) ; int [o] returnval(); | ||||||
1075 | [o] pout(m); [o] info(q=10); | ||||||
1076 | |||||||
1077 | See the module documentation for information on passing | ||||||
1078 | these arguments to levmar. Threading is known to | ||||||
1079 | work with p(m) and x(n), but I have not tested the rest. In | ||||||
1080 | this case all of they output pdls get the correct number of | ||||||
1081 | dimensions (and correct values !). Notice that t(nt) has a | ||||||
1082 | different dimension than x(n). This is correct because in | ||||||
1083 | some problems there is no t at all, and in some it is | ||||||
1084 | pressed into the service of delivering other parameters to | ||||||
1085 | the fit routine. (Formally, even if you use t(n), they are | ||||||
1086 | parameters.) | ||||||
1087 | |||||||
1088 | |||||||
1089 | =head2 levmar_chkjac() | ||||||
1090 | |||||||
1091 | =for ref | ||||||
1092 | |||||||
1093 | Check the analytic jacobian of a function by computing | ||||||
1094 | the derivatives numerically. | ||||||
1095 | |||||||
1096 | =for signature | ||||||
1097 | |||||||
1098 | p(m); t(n); [o] err(n); | ||||||
1099 | This is the relevant part of the signature of the | ||||||
1100 | routine that does the work. | ||||||
1101 | |||||||
1102 | |||||||
1103 | =for usage | ||||||
1104 | |||||||
1105 | use PDL::Fit::Levmar; | ||||||
1106 | |||||||
1107 | $Gh = levmar_func(FUNC=>$Gf); | ||||||
1108 | |||||||
1109 | $err = levmar_chkjac($Gh,$p,$t); | ||||||
1110 | |||||||
1111 | $f is an object of type PDL::Fit::Levmar::Func | ||||||
1112 | $p is a pdl of input parameters | ||||||
1113 | $t is an pdl of co-ordinate data | ||||||
1114 | $err is a pdl of errors computed at the values $t. | ||||||
1115 | |||||||
1116 | Note: No data $x is supplied to this function | ||||||
1117 | |||||||
1118 | The Func object $Gh contains a function f, and a jacobian | ||||||
1119 | jf. The i_th element of $err measures the agreement between | ||||||
1120 | the numeric and analytic gradients of f with respect to $p | ||||||
1121 | at the i_th evaluation point f (normally determined by the | ||||||
1122 | i_th element of t). A value of 1 means that the analytic and | ||||||
1123 | numeric gradients agree well. A value of 0 mean they do not | ||||||
1124 | agree. | ||||||
1125 | |||||||
1126 | Sometimes the number of evaluation points n is hardcoded | ||||||
1127 | into the function (as in almost all the examples taken from | ||||||
1128 | liblevmar and appearing in t/liblevmar.t. In this case the | ||||||
1129 | values that f returns depend only on $p and not on any other | ||||||
1130 | external data (nameley t). In this case, you must pass the | ||||||
1131 | number n as a perl scalar in place of t. For example | ||||||
1132 | |||||||
1133 | $err = levmar_chkjac($Gh,$p,5); | ||||||
1134 | |||||||
1135 | |||||||
1136 | in the case that f is hardcoded to return five values. | ||||||
1137 | |||||||
1138 | Need to put the description from the C code in here. | ||||||
1139 | |||||||
1140 | =head2 levmar_report() | ||||||
1141 | |||||||
1142 | =for ref | ||||||
1143 | |||||||
1144 | Make a human readable report from the hash ref returned | ||||||
1145 | by lemvar(). | ||||||
1146 | |||||||
1147 | =for usage | ||||||
1148 | |||||||
1149 | use PDL::Fit::Levmar; | ||||||
1150 | |||||||
1151 | $h = levmar($p,$x,$t, $func); | ||||||
1152 | |||||||
1153 | print levmar_report($h); | ||||||
1154 | |||||||
1155 | |||||||
1156 | =head1 BUGS | ||||||
1157 | |||||||
1158 | With the levmar-2.5 code: Passing workspace currently does not work with | ||||||
1159 | linear inequality constraint. Some of the PDL threading no long works | ||||||
1160 | correctly. These are noted in the tests in t/thread.t. It is not clear | ||||||
1161 | if it is a threading issue or the fitting has changed. | ||||||
1162 | |||||||
1163 | |||||||
1164 | =cut | ||||||
1165 | |||||||
1166 | #-------------------------------------------------------------------- | ||||||
1167 | # Begining of module code | ||||||
1168 | |||||||
1169 | 7 | 7 | 40 | use strict; | |||
7 | 7 | ||||||
7 | 160 | ||||||
1170 | 7 | 7 | 3023 | use PDL::Fit::Levmar::Func; | |||
7 | 20 | ||||||
7 | 44 | ||||||
1171 | 7 | 7 | 832 | use Carp; | |||
7 | 11 | ||||||
7 | 310 | ||||||
1172 | 7 | 7 | 75 | use PDL::NiceSlice; | |||
7 | 36 | ||||||
7 | 67 | ||||||
1173 | 7 | 7 | 101230 | use PDL::Core ':Internal'; # For topdl() | |||
7 | 12 | ||||||
7 | 52 | ||||||
1174 | 7 | 18656 | use vars ( '$Levmar_defaults', '$Levmar_defaults_order', | ||||
1175 | 7 | 7 | 793 | '$Perl_func_wrapper', '$Perl_jac_wrapper', '$LPPEXT', '$DBLMAX' ); | |||
7 | 13 | ||||||
1176 | |||||||
1177 | # 'jac' refers to jacobian | ||||||
1178 | $Perl_func_wrapper = get_perl_func_wrapper(); | ||||||
1179 | $Perl_jac_wrapper = get_perl_jac_wrapper(); | ||||||
1180 | $DBLMAX = get_dbl_max(); | ||||||
1181 | |||||||
1182 | $LPPEXT = ".lpp"; | ||||||
1183 | |||||||
1184 | |||||||
1185 | 0 | 0 | 0 | 0 | sub deb { print STDERR $_[0],"\n"} | ||
1186 | |||||||
1187 | |||||||
1188 | |||||||
1189 | $PDL::Fit::Levmar::HAVE_LAPACK=0; | ||||||
1190 | |||||||
1191 | |||||||
1192 | |||||||
1193 | |||||||
1194 | |||||||
1195 | |||||||
1196 | |||||||
1197 | |||||||
1198 | # check if dims are equal in two pdls | ||||||
1199 | sub chk_eq_dims { | ||||||
1200 | 0 | 0 | 0 | 0 | my ($x,$y) = @_; | ||
1201 | 0 | 0 | my (@xd) = $x->dims(); | ||||
1202 | 0 | 0 | my (@yd) = $y->dims(); | ||||
1203 | 0 | 0 | 0 | return -2 if (scalar(@xd) != scalar(@yd) ); | |||
1204 | 0 | 0 | my $ret = 1; | ||||
1205 | 0 | 0 | foreach (@xd) { | ||||
1206 | 0 | 0 | 0 | return -1 if ($_ != shift(@yd) ); | |||
1207 | } | ||||||
1208 | 0 | 0 | return $ret; | ||||
1209 | } | ||||||
1210 | |||||||
1211 | @PDL::Fit::Levmar::reason_for_terminating = ( | ||||||
1212 | '', | ||||||
1213 | 'stopped by small gradient J^T e', | ||||||
1214 | 'stopped by small Dp', | ||||||
1215 | 'stopped by itmax', | ||||||
1216 | 'singular matrix. Restart from current p with increased \mu', | ||||||
1217 | 'no further error reduction is possible. Restart with increased \mu', | ||||||
1218 | 'stopped by small ||e||_2' | ||||||
1219 | ); | ||||||
1220 | |||||||
1221 | sub levmar_report { | ||||||
1222 | 8 | 8 | 1 | 1711 | my $h = shift; | ||
1223 | 8 | 49 | make_report($h->{P},$h->{COVAR}, $h->{INFO}); | ||||
1224 | } | ||||||
1225 | |||||||
1226 | # make a small report out of the results of the optimization | ||||||
1227 | sub make_report { | ||||||
1228 | 8 | 8 | 0 | 31 | my ($p,$covar,$info) = @_; | ||
1229 | 8 | 51 | my @ninf = list($info); | ||||
1230 | # for(my $i=0;$i<9; $i++) { # Tried to get threading to work, but no! | ||||||
1231 | # $ninf[$i] = $info(($i)); | ||||||
1232 | # } | ||||||
1233 | 8 | 282 | $ninf[6] = | ||||
1234 | $PDL::Fit::Levmar::reason_for_terminating[$ninf[6]]; # replace int with string | ||||||
1235 | 8 | 18 | my $form = <<"EOFORM"; | ||||
1236 | Estimated parameters: %s | ||||||
1237 | Covariance: %s | ||||||
1238 | ||e||_2 at initial parameters = %g | ||||||
1239 | Errors at estimated parameters: | ||||||
1240 | ||e||_2\t = %g | ||||||
1241 | ||J^T e||_inf\t= %g | ||||||
1242 | ||Dp||_2\t= %g | ||||||
1243 | \\mu/max[J^T J]_ii ]\t= %g | ||||||
1244 | number of iterations\t= %d | ||||||
1245 | reason for termination: = %s | ||||||
1246 | number of function evaluations\t= %d | ||||||
1247 | number of jacobian evaluations\t= %d | ||||||
1248 | number of linear systems solved\t= %d | ||||||
1249 | EOFORM | ||||||
1250 | 8 | 115 | my $st = sprintf($form, $p,$covar,@ninf); | ||||
1251 | |||||||
1252 | } | ||||||
1253 | |||||||
1254 | $Levmar_defaults_order = qw [ | ||||||
1255 | FUNC | ||||||
1256 | |||||||
1257 | |||||||
1258 | ]; | ||||||
1259 | |||||||
1260 | |||||||
1261 | $Levmar_defaults = { | ||||||
1262 | MAXITS => 100, # maximum iterations | ||||||
1263 | MU => LM_INIT_MU(), | ||||||
1264 | EPS1 => LM_STOP_THRESH(), | ||||||
1265 | EPS2 => LM_STOP_THRESH(), | ||||||
1266 | EPS3 => LM_STOP_THRESH(), | ||||||
1267 | DELTA => LM_DIFF_DELTA(), | ||||||
1268 | DERIVATIVE => 'analytic', | ||||||
1269 | NOCOVAR => undef, | ||||||
1270 | FIX => undef, | ||||||
1271 | FIXB => undef, | ||||||
1272 | A => undef, | ||||||
1273 | B => undef, | ||||||
1274 | C => undef, | ||||||
1275 | D => undef, | ||||||
1276 | UB => undef, | ||||||
1277 | LB => undef, | ||||||
1278 | FUNC => undef, # Levmar::Func object, or function def, or ... | ||||||
1279 | JFUNC => undef, # must be ref to perl sub | ||||||
1280 | X => undef, | ||||||
1281 | P => undef, | ||||||
1282 | T => undef, | ||||||
1283 | WGHTS => undef, | ||||||
1284 | COVAR => undef, # The next 5 params can be set to PDL->null | ||||||
1285 | WORK => undef, # work space | ||||||
1286 | POUT => undef, # ref for preallocated output parameters | ||||||
1287 | INFO => undef, | ||||||
1288 | RET => undef, | ||||||
1289 | # meant to be private | ||||||
1290 | LFUNC => undef, # only Levmar::Func object, made from FUNC | ||||||
1291 | }; | ||||||
1292 | |||||||
1293 | # This isn't meant to replace help. But for now its doing nothing. | ||||||
1294 | sub get_help_str { | ||||||
1295 | 0 | 0 | 0 | 0 | return ' | ||
1296 | This is the help string for levmar. | ||||||
1297 | |||||||
1298 | '; | ||||||
1299 | } | ||||||
1300 | |||||||
1301 | ################################################################# | ||||||
1302 | sub levmar { | ||||||
1303 | 90 | 90 | 1 | 360545 | my($p,$x,$t,$infunc); | ||
1304 | 90 | 0 | my $args; | ||||
1305 | # get all args before the hash. p,x,t must come in that order | ||||||
1306 | # but (t), or (t and x), or (t,x,and p) can be in the hash | ||||||
1307 | # the function can be anywhere before the hash | ||||||
1308 | 90 | 253 | while (1) { | ||||
1309 | 176 | 481 | $args = 0; | ||||
1310 | 176 | 100 | 66 | 1456 | if ( (not defined $p ) and (ref($_[0]) eq 'PDL' or ref($_[0]) eq 'ARRAY')) { | ||
66 | |||||||
1311 | 85 | 204 | $p = shift ; $args++; | ||||
85 | 213 | ||||||
1312 | } | ||||||
1313 | 176 | 50 | 481 | last if ( @_ == 0 ); | |||
1314 | 176 | 100 | 66 | 1168 | if ( (not defined $x ) and (ref($_[0]) eq 'PDL' or ref($_[0]) eq 'ARRAY')) { | ||
66 | |||||||
1315 | 77 | 184 | $x = shift ; $args++; | ||||
77 | 141 | ||||||
1316 | } | ||||||
1317 | 176 | 50 | 494 | last if ( @_ == 0 ); | |||
1318 | 176 | 100 | 66 | 998 | if ( (not defined $t) and (ref($_[0]) eq 'PDL' or ref($_[0]) eq 'ARRAY')) { | ||
66 | |||||||
1319 | 40 | 79 | $t = shift ; $args++; | ||||
40 | 104 | ||||||
1320 | } | ||||||
1321 | 176 | 100 | 367 | last if ( @_ == 0 ); | |||
1322 | 169 | 100 | 100 | 893 | if ( not defined $infunc and ref($_[0]) =~ /Func|CODE/ ) { | ||
1323 | 21 | 34 | $infunc = shift; $args++; | ||||
21 | 27 | ||||||
1324 | } | ||||||
1325 | 169 | 100 | 393 | last if ( @_ == 0 ); | |||
1326 | 166 | 100 | 66 | 1872 | if ( (not defined $infunc) and | ||
66 | |||||||
66 | |||||||
1327 | ( not ref($_[0]) ) and ( $_[0] =~ /(\.c|$LPPEXT)$/o or $_[0] =~ /\n/ ) ) { | ||||||
1328 | 8 | 23 | $infunc = shift; $args++; | ||||
8 | 14 | ||||||
1329 | } | ||||||
1330 | 166 | 100 | 100 | 1459 | last if ( @_ == 0 or $args == 0); | ||
1331 | } | ||||||
1332 | 90 | 148 | my $inh; | ||||
1333 | 90 | 100 | 368 | $inh = shift if @_; # input parameter hash | |||
1334 | 90 | 100 | 252 | $inh = {} unless defined $inh; | |||
1335 | 90 | 100 | 262 | if(ref $inh ne 'HASH') { # turn list into anonymous hash | |||
1336 | 79 | 50 | 480 | $inh = defined $inh ? {$inh,@_} : {} ; | |||
1337 | } | ||||||
1338 | 90 | 50 | 324 | if( exists $inh->{HELP} ) { | |||
1339 | 0 | 0 | my $s = get_help_str(); | ||||
1340 | 0 | 0 | return $s; | ||||
1341 | } | ||||||
1342 | 90 | 100 | 335 | if( exists $inh->{GETOPTS} ) { | |||
1343 | 1 | 64 | my %h = %$Levmar_defaults; | ||||
1344 | 1 | 10 | return \%h; | ||||
1345 | } | ||||||
1346 | # should already use a ref to string here | ||||||
1347 | 89 | 100 | 283 | $inh->{FUNC} = $infunc if defined $infunc; | |||
1348 | die "levmar: neither FUNC nor CSRC defined" | ||||||
1349 | 89 | 50 | 66 | 439 | unless defined $inh->{FUNC} or defined $inh->{CSRC}; | ||
1350 | |||||||
1351 | |||||||
1352 | |||||||
1353 | |||||||
1354 | 89 | 232 | foreach (qw( A B C D FIX WGHT )) { | ||||
1355 | barf "PDL::Fit::Levmar not built with lapack. Found parameter $_" | ||||||
1356 | 534 | 50 | 1018 | if exists $inh->{$_}; | |||
1357 | } | ||||||
1358 | |||||||
1359 | |||||||
1360 | |||||||
1361 | |||||||
1362 | ######## Handle parameters | ||||||
1363 | 89 | 158 | my $h = {}; # parameter hash to be built from $inh and defaults | ||||
1364 | 89 | 151 | my $funch = {}; # unrecognized parameter hash. This will be passed to Func. | ||||
1365 | 89 | 833 | foreach ( keys %$Levmar_defaults ){ # copy defaults to final hash | ||||
1366 | 2492 | 3868 | $h->{$_} = $Levmar_defaults->{$_}; | ||||
1367 | } | ||||||
1368 | 89 | 550 | foreach my $k (keys %$inh ) { # replace defaults with input params | ||||
1369 | 235 | 100 | 489 | if ( exists $Levmar_defaults->{$k} ) { | |||
1370 | 222 | 380 | $h->{$k} = $inh->{$k}; | ||||
1371 | } | ||||||
1372 | else { # don't recognize, so pass to Func | ||||||
1373 | 13 | 32 | $funch->{$k} = $inh->{$k}; | ||||
1374 | } | ||||||
1375 | } | ||||||
1376 | ########## Set up input and output variables | ||||||
1377 | |||||||
1378 | # These must come from parameters if not from the arg list | ||||||
1379 | 89 | 100 | 66 | 703 | $p = $h->{P} unless not defined $h->{P} and defined $p; | ||
1380 | 89 | 100 | 66 | 468 | $x = $h->{X} unless not defined $h->{X} and defined $p; | ||
1381 | 89 | 100 | 66 | 451 | $t = $h->{T} unless not defined $h->{T} and defined $p; | ||
1382 | |||||||
1383 | 89 | 100 | 370 | $t = PDL->null unless defined $t; # sometimes $t not needed | |||
1384 | |||||||
1385 | 89 | 50 | 618 | if ( not defined $p ) { # This looks like some kind of error thing that was | |||
1386 | # not implemented consistently | ||||||
1387 | 0 | 0 | my $st = "No parameter (P) pdl"; | ||||
1388 | 0 | 0 | warn $st; | ||||
1389 | 0 | 0 | return {RET => -1, ERRS => [$st] }; | ||||
1390 | } | ||||||
1391 | 89 | 50 | 202 | if ( not defined $x ) { | |||
1392 | 0 | 0 | my $st = "No data (X) pdl"; | ||||
1393 | 0 | 0 | warn $st; | ||||
1394 | 0 | 0 | return {RET => -1, ERRS => [$st] }; | ||||
1395 | } | ||||||
1396 | |||||||
1397 | #------------------------------------------------- | ||||||
1398 | # Treat input and output piddles for pp_defs | ||||||
1399 | 89 | 300 | $x = topdl($x); # in case they are refs to arrays | ||||
1400 | 89 | 1478 | $p = topdl($p); | ||||
1401 | 89 | 890 | $t = topdl($t); | ||||
1402 | ### output variables | ||||||
1403 | 89 | 1030 | my $pout; | ||||
1404 | my $info; | ||||||
1405 | 89 | 0 | my $covar; | ||||
1406 | 89 | 0 | my $ret; | ||||
1407 | 89 | 0 | my $work; | ||||
1408 | 89 | 0 | my $wghts; | ||||
1409 | |||||||
1410 | # should put this stuff in a loop | ||||||
1411 | 89 | 100 | 218 | $covar = $h->{COVAR} if defined $h->{COVAR}; | |||
1412 | 89 | 50 | 208 | $pout = $h->{POUT} if defined $h->{POUT}; | |||
1413 | 89 | 50 | 224 | $info = $h->{INFO} if defined $h->{INFO}; | |||
1414 | 89 | 50 | 303 | $ret = $h->{RET} if defined $h->{RET}; | |||
1415 | 89 | 100 | 213 | $work = $h->{WORK} if defined $h->{WORK}; | |||
1416 | 89 | 50 | 352 | $wghts = $h->{WGHTS} if defined $h->{WGHTS}; | |||
1417 | |||||||
1418 | # If they are set here, then there will be no external ref. | ||||||
1419 | 89 | 100 | 346 | $covar = PDL->null unless defined $covar; | |||
1420 | 89 | 50 | 1078 | $pout = PDL->null unless defined $pout; | |||
1421 | 89 | 50 | 925 | $info = PDL->null unless defined $info; | |||
1422 | 89 | 50 | 752 | $ret = PDL->null unless defined $ret; | |||
1423 | 89 | 100 | 822 | $work = PDL->null unless defined $work; | |||
1424 | 89 | 50 | 778 | $wghts = PDL->null unless defined $wghts; | |||
1425 | |||||||
1426 | # Input pdl contstructed in levmar | ||||||
1427 | # Currently, the elements are set from a hash; no convenient way to thread. | ||||||
1428 | # As an alternative, we could send them as a pdl, then we could thread them | ||||||
1429 | 89 | 659 | my $opts; | ||||
1430 | # Careful about $m, it is used in construcing $A below (with fix). But this is | ||||||
1431 | # not correct when using implicit threading. Except threading may still be working. | ||||||
1432 | # Need to look into that. | ||||||
1433 | 89 | 297 | my $m = $p->nelem; | ||||
1434 | |||||||
1435 | #-------------------------------------------------------- | ||||||
1436 | # Set up Func object | ||||||
1437 | #-------------------------------------------------------- | ||||||
1438 | 89 | 50 | 307 | croak "No FUNC in options to levmar." unless exists $h->{FUNC}; | |||
1439 | 89 | 100 | 100 | 787 | if ( ref($h->{FUNC}) =~ /CODE/ or | ||
1440 | not ref($h->{FUNC}) ) { # probably a string, convert to func object | ||||||
1441 | 62 | 183 | $funch->{FUNC} = $h->{FUNC}; | ||||
1442 | 62 | 339 | my @ret = PDL::Fit::Levmar::Func::levmar_func($funch); | ||||
1443 | 62 | 50 | 429 | if ($ret[0] == -1 ) { # error in creating function | |||
1444 | 0 | 0 | shift(@ret); | ||||
1445 | # deb "Error: " . join("\n",@ret); # can turn this off and on | ||||||
1446 | 0 | 0 | return {RET => -1, ERRS => [@ret] } ; # just return all the other messages. | ||||
1447 | } | ||||||
1448 | 62 | 320 | $h->{LFUNC} = $ret[0]; | ||||
1449 | } | ||||||
1450 | else { # already a Func object | ||||||
1451 | 27 | 68 | $h->{LFUNC} = $h->{FUNC} ; # copy ref | ||||
1452 | 27 | 73 | my @k = keys %$funch; | ||||
1453 | # It would be good to check for valid options. But if a user switches from a | ||||||
1454 | # string to a Func oject in the call to levmar(), he may not delete the | ||||||
1455 | # other keys. Halting on an error would bit frustrating or puzzling. | ||||||
1456 | # Even a warning is perhaps too much | ||||||
1457 | 27 | 50 | 82 | if ( @k ) { | |||
1458 | 0 | 0 | 0 | my $s = ''; $s = 's' if @k>1; | |||
0 | 0 | ||||||
1459 | 0 | 0 | my $str = "Unrecognized or useless option$s to levmar: \n"; | ||||
1460 | 0 | 0 | foreach ( @k ) { | ||||
1461 | 0 | 0 | $str .= " '$_' => '" . $funch->{$_} . "'\n" ; | ||||
1462 | } | ||||||
1463 | 0 | 0 | warn $str .""; | ||||
1464 | } | ||||||
1465 | } | ||||||
1466 | # C pointers to fit functions | ||||||
1467 | my ($funcn,$sfuncn,$jacn,$sjacn) = # single and double | ||||||
1468 | 89 | 612 | $h->{LFUNC}->get_fit_pointers(); | ||||
1469 | 89 | 409 | my $deriv = $h->{DERIVATIVE}; | ||||
1470 | |||||||
1471 | # The DFP stuff is to wrap perl functions in C routines to pass to liblevmar. | ||||||
1472 | # It's probably cleaner to move most of this stuff into Levmar::Func | ||||||
1473 | 89 | 170 | my $DFP = 0; # routines check for $DFP == 0 to bypass perl wrapper | ||||
1474 | |||||||
1475 | 89 | 100 | 342 | if ( ref($h->{FUNC}) =~ /CODE/) { # setup perl wrapper stuff | |||
1476 | 8 | 20 | my $jfunc = 0; | ||||
1477 | 8 | 63 | $DFP = DFP_create(); | ||||
1478 | 8 | 100 | 66 | 74 | if (defined $h->{JFUNC} and ref($h->{JFUNC}) =~ /CODE/) { | ||
1479 | 6 | 18 | $jfunc = $h->{JFUNC}; | ||||
1480 | } | ||||||
1481 | 8 | 100 | 100 | 42 | if ( $deriv eq 'analytic' and $jfunc == 0 ) { | ||
1482 | # warn "No jacobian function supplied, using numeric derivatives"; | ||||||
1483 | 2 | 4 | $deriv = 'numeric'; | ||||
1484 | 2 | 3 | $h->{DERIVATIVE} = 'numeric'; | ||||
1485 | } | ||||||
1486 | 8 | 35 | DFP_set_perl_funcs($DFP, $h->{FUNC}, $h->{JFUNC}); | ||||
1487 | 8 | 20 | $funcn = $Perl_func_wrapper; | ||||
1488 | 8 | 12 | $jacn = $Perl_jac_wrapper; | ||||
1489 | 8 | 9 | $sfuncn = $Perl_func_wrapper; # Single and double can use same wrapper | ||||
1490 | 8 | 12 | $sjacn = $Perl_jac_wrapper; | ||||
1491 | } | ||||||
1492 | |||||||
1493 | ############ Do a few sanity checks | ||||||
1494 | |||||||
1495 | 89 | 100 | 406 | if ( $deriv eq 'analytic' ) { | |||
50 | |||||||
1496 | 70 | 100 | 66 | 607 | if (not defined $jacn or $jacn == 0 ) { | ||
1497 | # warn "No jacobian function supplied, using numeric derivatives"; | ||||||
1498 | 1 | 24 | $deriv = 'numeric'; | ||||
1499 | 1 | 15 | $h->{DERIVATIVE} = 'numeric'; | ||||
1500 | } | ||||||
1501 | } | ||||||
1502 | elsif ( $deriv ne 'numeric' ) { | ||||||
1503 | 0 | 0 | croak "DERIVATIVE must be 'analytic' or 'numeric'"; | ||||
1504 | } | ||||||
1505 | |||||||
1506 | # liblevmar uses 5 option for analytic and 6 for numeric. | ||||||
1507 | # We make an integer option array as well, for passing stuff , like maxits. | ||||||
1508 | 89 | 100 | 292 | if ($h->{DERIVATIVE} eq 'analytic') { | |||
1509 | 69 | 964 | $opts = pdl ($p->type, $h->{MU},$h->{EPS1},$h->{EPS2},$h->{EPS3}); | ||||
1510 | } | ||||||
1511 | else { | ||||||
1512 | 20 | 358 | $opts = pdl ($p->type,$h->{MU},$h->{EPS1},$h->{EPS2},$h->{EPS3},$h->{DELTA}); | ||||
1513 | } | ||||||
1514 | 89 | 13186 | my $iopts = pdl(long, $h->{MAXITS}); | ||||
1515 | |||||||
1516 | |||||||
1517 | ########### FIX holds some parameters constant using linear constraints. | ||||||
1518 | # It is a special case of more general constraints using A and b. | ||||||
1519 | # Notice that this fails if FIX has more than one dimension (ie, you are | ||||||
1520 | # threading. FIXB does the same but using box constraints. | ||||||
1521 | |||||||
1522 | 89 | 50 | 9540 | if (defined $h->{FIX} ) { | |||
50 | |||||||
1523 | 0 | 0 | my $ip = topdl( $h->{FIX}); # take array ref or pdl | ||||
1524 | 0 | 0 | 0 | if ( chk_eq_dims($ip,$p) < 0 ) { | |||
1525 | 0 | 0 | croak "p and FIX must have the same dimensions"; | ||||
1526 | } | ||||||
1527 | 0 | 0 | my $nc = $ip->sum; # number of fixed vars | ||||
1528 | 0 | 0 | 0 | if ($nc > 0) { | |||
1529 | 0 | 0 | my $A = zeroes($p->type, $m,$nc); | ||||
1530 | 0 | 0 | my $b = zeroes($p->type, $nc); | ||||
1531 | 0 | 0 | my $j=0; | ||||
1532 | 0 | 0 | for(my $i=0; $i<$m; $i++) { | ||||
1533 | 0 | 0 | 0 | if ($ip->at($i) == 1) { | |||
1534 | 0 | 0 | $A($i,$j) .= 1; | ||||
1535 | 0 | 0 | $b($j) .= $p->at($i); | ||||
1536 | 0 | 0 | $j++; | ||||
1537 | } | ||||||
1538 | } | ||||||
1539 | 0 | 0 | $h->{A} = $A; | ||||
1540 | 0 | 0 | $h->{B} = $b; | ||||
1541 | } | ||||||
1542 | } | ||||||
1543 | elsif ( defined $h->{FIXB} ) { | ||||||
1544 | 0 | 0 | my $f = topdl( $h->{FIXB}); # take array ref or pdl | ||||
1545 | 0 | 0 | 0 | if ( chk_eq_dims($f,$p) < 0 ) { | |||
1546 | 0 | 0 | croak "p and FIX must have the same dimensions"; | ||||
1547 | } | ||||||
1548 | 0 | 0 | 0 | if ( not defined $h->{UB} ) { | |||
1549 | 0 | 0 | $h->{UB} = ones($p); | ||||
1550 | 0 | 0 | $h->{UB} *= $DBLMAX; | ||||
1551 | } | ||||||
1552 | 0 | 0 | 0 | if (not defined $h->{LB} ) { | |||
1553 | 0 | 0 | $h->{LB} = ones($p); | ||||
1554 | 0 | 0 | $h->{LB} *= -$DBLMAX; | ||||
1555 | } | ||||||
1556 | 0 | 0 | my $fi = PDL::Primitive::which($f == 1); # indices in p that we want to fix. | ||||
1557 | 0 | 0 | $h->{UB}->flat->index($fi) .= $p->flat->index($fi); | ||||
1558 | 0 | 0 | $h->{LB}->flat->index($fi) .= $p->flat->index($fi); | ||||
1559 | # so ub and lb are now at maximum bounds where not fixed and at value of | ||||||
1560 | # p where fixed | ||||||
1561 | } | ||||||
1562 | 89 | 370 | my $want_covar = 1; | ||||
1563 | 89 | 50 | 292 | if ( defined $h->{NOCOVAR} ) { | |||
1564 | 0 | 0 | $want_covar = 0; | ||||
1565 | } | ||||||
1566 | |||||||
1567 | 89 | 691 | my $errs = check_levmar_args($h); | ||||
1568 | 89 | 50 | 235 | if ( @$errs > 0 ) { | |||
1569 | # print @$errs; | ||||||
1570 | 0 | 0 | return {RET => -1, ERRS => $errs }; | ||||
1571 | } | ||||||
1572 | 89 | 329 | my ($func_key, $arg_list) = build_constraint_arg_combination($h); | ||||
1573 | # print "func key '$func_key'\n"; | ||||||
1574 | 89 | 50 | 325 | if ( not defined $func_key ) { | |||
1575 | 0 | 0 | croak "Could not find function key"; | ||||
1576 | } | ||||||
1577 | 89 | 50 | 298 | if ( not exists $PDL::Fit::Levmar::PDL_Levmar_funcs{$func_key} ) { | |||
1578 | 0 | 0 | croak "Could not find function for key"; | ||||
1579 | } | ||||||
1580 | 89 | 373 | my $pdl_levmar_func = $PDL::Fit::Levmar::PDL_Levmar_funcs{$func_key}; | ||||
1581 | # print "func $pdl_levmar_func\n"; | ||||||
1582 | # my $nargs = @$arg_list; | ||||||
1583 | # print "Got $nargs args\n"; | ||||||
1584 | 89 | 179 | my @jacobians = (); | ||||
1585 | 89 | 100 | 269 | if ( $h->{DERIVATIVE} eq 'analytic' ) { | |||
1586 | 69 | 182 | @jacobians = ( $jacn, $sjacn ); | ||||
1587 | } | ||||||
1588 | 89 | 309583 | &$pdl_levmar_func($p,$x,$t,@$arg_list,$iopts,$opts,$work, | ||||
1589 | $covar, $ret, $pout, $info, $funcn, $sfuncn, @jacobians, $DFP, $want_covar); | ||||||
1590 | |||||||
1591 | 89 | 100 | 14425778 | DFP_free($DFP) if $DFP; | |||
1592 | |||||||
1593 | my $hout = { | ||||||
1594 | RET => $ret, | ||||||
1595 | COVAR => $covar, | ||||||
1596 | P => $pout, | ||||||
1597 | ERRI => $info((0)), | ||||||
1598 | ERR1 => $info((1)), | ||||||
1599 | ERR2 => $info((2)), | ||||||
1600 | ERR3 => $info((3)), | ||||||
1601 | ERR4 => $info((4)), | ||||||
1602 | ITS => $info((5)), | ||||||
1603 | REASON => $info((6)), | ||||||
1604 | NFUNC => $info((7)), | ||||||
1605 | NJAC => $info((8)), | ||||||
1606 | NLS => $info((9)), | ||||||
1607 | INFO => $info, | ||||||
1608 | FUNC => $h->{LFUNC}, | ||||||
1609 | 89 | 1316 | }; | ||||
1610 | 89 | 17809 | return $hout; | ||||
1611 | |||||||
1612 | } # end levmar() | ||||||
1613 | |||||||
1614 | |||||||
1615 | sub PDL::Fit::Levmar::check_levmar_args { | ||||||
1616 | 89 | 89 | 0 | 250 | my ($h) = @_; | ||
1617 | 89 | 1100 | my @refargs = qw( LB UB A B C D ); | ||||
1618 | 89 | 231 | my @errs = (); | ||||
1619 | 89 | 382 | foreach my $argname ( @refargs ) { | ||||
1620 | 534 | 100 | 66 | 2098 | if ( exists $h->{$argname} and defined $h->{$argname} ) { | ||
1621 | 28 | 124 | my $arg = $h->{$argname}; | ||||
1622 | 28 | 50 | 142 | if ( not ref($arg) ) { | |||
1623 | 0 | 0 | push @errs, "$argname must be a pdl or ref to array."; | ||||
1624 | } | ||||||
1625 | } | ||||||
1626 | } | ||||||
1627 | 89 | 798 | my @combs = ( [ 'A', 'B' ], [ 'C', 'D' ] ); | ||||
1628 | 89 | 226 | foreach my $comb (@combs ) { | ||||
1629 | 178 | 302 | my $n = @$comb; | ||||
1630 | 178 | 310 | my $nf = 0; | ||||
1631 | 178 | 271 | foreach my $arg ( @$comb ) { | ||||
1632 | 356 | 50 | 33 | 1392 | $nf++ if exists $h->{$arg} and defined $h->{$arg}; | ||
1633 | } | ||||||
1634 | 178 | 50 | 33 | 424 | if ( $nf != 0 and $n != $nf ) { | ||
1635 | 0 | 0 | push @errs, 'none or all of ' . join(' and ',@$comb) . ' must be defined.'; | ||||
1636 | } | ||||||
1637 | } | ||||||
1638 | 89 | 303 | return \@errs; | ||||
1639 | } | ||||||
1640 | |||||||
1641 | |||||||
1642 | # make a list of strings of names of constraint args that | ||||||
1643 | # have been passed. | ||||||
1644 | # hash is arg hash to top level call | ||||||
1645 | sub PDL::Fit::Levmar::build_constraint_arg_combination { | ||||||
1646 | 89 | 89 | 0 | 189 | my ($h) = @_; | ||
1647 | 89 | 159 | my @arg_comb = (); | ||||
1648 | 89 | 154 | my @arg_list = (); | ||||
1649 | # order is important in following | ||||||
1650 | 89 | 567 | my @possible_args = qw( LB UB A B C D ); | ||||
1651 | 89 | 350 | foreach ( @possible_args ) { | ||||
1652 | 534 | 1196 | my $ucarg = $_; | ||||
1653 | # $ucarg =~ tr/a-z/A-Z/; # should rewrite so that tr not needed | ||||||
1654 | 534 | 100 | 66 | 1848 | if ( exists $h->{$ucarg} and defined $h->{$ucarg} ) { | ||
1655 | 28 | 64 | push @arg_comb, $_; | ||||
1656 | 28 | 130 | push @arg_list, topdl($h->{$ucarg}); | ||||
1657 | } | ||||||
1658 | } | ||||||
1659 | 89 | 125 | my $deriv_type; | ||||
1660 | 89 | 100 | 242 | if ($h->{DERIVATIVE} eq 'analytic' ) { | |||
1661 | 69 | 120 | $deriv_type = 'DER'; | ||||
1662 | } | ||||||
1663 | else { | ||||||
1664 | 20 | 111 | $deriv_type = 'DIFF'; | ||||
1665 | } | ||||||
1666 | 89 | 50 | 33 | 667 | push @arg_list, topdl($h->{WGHTS}) if exists $h->{WGHTS} and defined $h->{WGHTS}; | ||
1667 | 89 | 361 | my $fk = make_pdl_levmar_func_key(make_hash_key_from_arg_comb(\@arg_comb), $deriv_type); | ||||
1668 | 89 | 532 | return ($fk,\@arg_list); | ||||
1669 | } | ||||||
1670 | |||||||
1671 | sub PDL::Fit::Levmar::make_hash_key_from_arg_comb { | ||||||
1672 | 89 | 89 | 0 | 180 | my ( $arg_comb ) = @_; | ||
1673 | 89 | 630 | return join( '_', @$arg_comb); | ||||
1674 | } | ||||||
1675 | |||||||
1676 | |||||||
1677 | sub PDL::Fit::Levmar::make_pdl_levmar_func_key { | ||||||
1678 | 89 | 89 | 0 | 255 | my ($arg_str, $deriv_type) = @_; | ||
1679 | 89 | 306 | return $deriv_type . '_' . $arg_str; | ||||
1680 | } | ||||||
1681 | |||||||
1682 | |||||||
1683 | %PDL::Fit::Levmar::PDL_Levmar_funcs = ( | ||||||
1684 | DER_ => \&PDL::levmar_der_, | ||||||
1685 | DIFF_ => \&PDL::levmar_diff_, | ||||||
1686 | DER_LB_C_D => \&PDL::levmar_der_lb_C_d, | ||||||
1687 | DIFF_LB_C_D => \&PDL::levmar_diff_lb_C_d, | ||||||
1688 | DER_A_B => \&PDL::levmar_der_A_b, | ||||||
1689 | DIFF_A_B => \&PDL::levmar_diff_A_b, | ||||||
1690 | DER_UB_A_B => \&PDL::levmar_der_ub_A_b, | ||||||
1691 | DIFF_UB_A_B => \&PDL::levmar_diff_ub_A_b, | ||||||
1692 | DER_UB => \&PDL::levmar_der_ub, | ||||||
1693 | DIFF_UB => \&PDL::levmar_diff_ub, | ||||||
1694 | DER_A_B_C_D => \&PDL::levmar_der_A_b_C_d, | ||||||
1695 | DIFF_A_B_C_D => \&PDL::levmar_diff_A_b_C_d, | ||||||
1696 | DER_LB_UB_A_B_C_D => \&PDL::levmar_der_lb_ub_A_b_C_d, | ||||||
1697 | DIFF_LB_UB_A_B_C_D => \&PDL::levmar_diff_lb_ub_A_b_C_d, | ||||||
1698 | DER_LB => \&PDL::levmar_der_lb, | ||||||
1699 | DIFF_LB => \&PDL::levmar_diff_lb, | ||||||
1700 | DER_LB_A_B_C_D => \&PDL::levmar_der_lb_A_b_C_d, | ||||||
1701 | DIFF_LB_A_B_C_D => \&PDL::levmar_diff_lb_A_b_C_d, | ||||||
1702 | DER_UB_A_B_C_D => \&PDL::levmar_der_ub_A_b_C_d, | ||||||
1703 | DIFF_UB_A_B_C_D => \&PDL::levmar_diff_ub_A_b_C_d, | ||||||
1704 | DER_LB_UB => \&PDL::levmar_der_lb_ub, | ||||||
1705 | DIFF_LB_UB => \&PDL::levmar_diff_lb_ub, | ||||||
1706 | DER_LB_A_B => \&PDL::levmar_der_lb_A_b, | ||||||
1707 | DIFF_LB_A_B => \&PDL::levmar_diff_lb_A_b, | ||||||
1708 | DER_UB_C_D => \&PDL::levmar_der_ub_C_d, | ||||||
1709 | DIFF_UB_C_D => \&PDL::levmar_diff_ub_C_d, | ||||||
1710 | DER_LB_UB_A_B => \&PDL::levmar_der_lb_ub_A_b, | ||||||
1711 | DIFF_LB_UB_A_B => \&PDL::levmar_diff_lb_ub_A_b, | ||||||
1712 | DER_LB_UB_C_D => \&PDL::levmar_der_lb_ub_C_d, | ||||||
1713 | DIFF_LB_UB_C_D => \&PDL::levmar_diff_lb_ub_C_d, | ||||||
1714 | DER_C_D => \&PDL::levmar_der_C_d, | ||||||
1715 | DIFF_C_D => \&PDL::levmar_diff_C_d, | ||||||
1716 | ); | ||||||
1717 | |||||||
1718 | |||||||
1719 | |||||||
1720 | |||||||
1721 | sub levmar_chkjac { | ||||||
1722 | 4 | 4 | 1 | 815 | my ($f,$p,$t) = @_; | ||
1723 | 4 | 10 | my $r = ref $f; | ||||
1724 | 4 | 50 | 15 | if ( not $r =~ /Levmar::Func/ ) { | |||
1725 | 0 | 0 | warn "levmar_chkjac: not a Levmar::Func object "; | ||||
1726 | 0 | 0 | return; | ||||
1727 | } | ||||||
1728 | 4 | 10 | my $N; | ||||
1729 | 4 | 50 | 14 | if ( not ref($t) =~ /PDL/ ) { | |||
1730 | 0 | 0 | $N = $t; # in case there is no t for this func | ||||
1731 | 0 | 0 | $t = zeroes( $p->type, 1); just some pdl | ||||
0 | 0 | ||||||
1732 | } | ||||||
1733 | 4 | 5 | my $DFP = 0; | ||||
1734 | 4 | 6 | my ($funcn,$sfuncn,$jacn,$sjacn); | ||||
1735 | 4 | 100 | 12 | if ( ref($f->{FUNC}) =~ /CODE/) { # setup perl wrapper stuff | |||
1736 | 2 | 3 | my $jfunc = 0; | ||||
1737 | 2 | 7 | $DFP = DFP_create(); | ||||
1738 | 2 | 50 | 33 | 27 | if (not (defined $f->{JFUNC} and ref($f->{FUNC}) =~ /CODE/ ) ) { | ||
1739 | 0 | 0 | warn "levmar_chkjac: no perl code jacobian supplied in JFUNC."; | ||||
1740 | 0 | 0 | return undef; | ||||
1741 | } | ||||||
1742 | 2 | 11 | DFP_set_perl_funcs($DFP, $f->{FUNC}, $f->{JFUNC}); | ||||
1743 | 2 | 4 | $funcn = $Perl_func_wrapper; | ||||
1744 | 2 | 3 | $jacn = $Perl_jac_wrapper; | ||||
1745 | 2 | 2 | $sfuncn = $Perl_func_wrapper; | ||||
1746 | 2 | 3 | $sjacn = $Perl_jac_wrapper; | ||||
1747 | } | ||||||
1748 | else { # pointers to native c functions. | ||||||
1749 | 2 | 7 | ($funcn,$sfuncn,$jacn,$sjacn) = | ||||
1750 | $f->get_fit_pointers(); | ||||||
1751 | } | ||||||
1752 | 4 | 6 | my $err; | ||||
1753 | 4 | 50 | 12 | if ( defined $N ) { | |||
1754 | 0 | 0 | $err = _levmar_chkjac_no_t($p,$funcn,$sfuncn,$jacn,$sjacn,$N,$DFP); | ||||
1755 | } | ||||||
1756 | else { | ||||||
1757 | 4 | 128 | $err = _levmar_chkjac($p,$t,$funcn,$sfuncn,$jacn,$sjacn,$DFP); | ||||
1758 | } | ||||||
1759 | 4 | 681 | DFP_free($DFP); | ||||
1760 | 4 | 14 | return $err; | ||||
1761 | } | ||||||
1762 | |||||||
1763 | |||||||
1764 | |||||||
1765 | |||||||
1766 | |||||||
1767 | *levmar_der_lb = \&PDL::levmar_der_lb; | ||||||
1768 | |||||||
1769 | |||||||
1770 | |||||||
1771 | |||||||
1772 | |||||||
1773 | *levmar_der_lb_ub = \&PDL::levmar_der_lb_ub; | ||||||
1774 | |||||||
1775 | |||||||
1776 | |||||||
1777 | |||||||
1778 | |||||||
1779 | *levmar_der_ub = \&PDL::levmar_der_ub; | ||||||
1780 | |||||||
1781 | |||||||
1782 | |||||||
1783 | |||||||
1784 | |||||||
1785 | *levmar_der_ = \&PDL::levmar_der_; | ||||||
1786 | |||||||
1787 | |||||||
1788 | |||||||
1789 | |||||||
1790 | |||||||
1791 | *levmar_diff_lb = \&PDL::levmar_diff_lb; | ||||||
1792 | |||||||
1793 | |||||||
1794 | |||||||
1795 | |||||||
1796 | |||||||
1797 | *levmar_diff_lb_ub = \&PDL::levmar_diff_lb_ub; | ||||||
1798 | |||||||
1799 | |||||||
1800 | |||||||
1801 | |||||||
1802 | |||||||
1803 | *levmar_diff_ub = \&PDL::levmar_diff_ub; | ||||||
1804 | |||||||
1805 | |||||||
1806 | |||||||
1807 | |||||||
1808 | |||||||
1809 | *levmar_diff_ = \&PDL::levmar_diff_; | ||||||
1810 | |||||||
1811 | |||||||
1812 | |||||||
1813 | |||||||
1814 | |||||||
1815 | *_levmar_chkjac = \&PDL::_levmar_chkjac; | ||||||
1816 | |||||||
1817 | |||||||
1818 | |||||||
1819 | |||||||
1820 | |||||||
1821 | *_levmar_chkjac_no_t = \&PDL::_levmar_chkjac_no_t; | ||||||
1822 | |||||||
1823 | |||||||
1824 | |||||||
1825 | ; | ||||||
1826 | |||||||
1827 | |||||||
1828 | |||||||
1829 | =head1 AUTHORS | ||||||
1830 | |||||||
1831 | PDL code for Levmar Copyright (C) 2006 John Lapeyre. C | ||||||
1832 | library code Copyright (C) 2006 Manolis Lourakis, licensed | ||||||
1833 | here under the Gnu Public License. | ||||||
1834 | |||||||
1835 | All rights reserved. There is no warranty. You are allowed | ||||||
1836 | to redistribute this software / documentation under certain | ||||||
1837 | conditions. For details, see the file COPYING in the PDL | ||||||
1838 | distribution. If this file is separated from the PDL | ||||||
1839 | distribution, the copyright notice should be included in the | ||||||
1840 | file. | ||||||
1841 | |||||||
1842 | =cut | ||||||
1843 | |||||||
1844 | |||||||
1845 | |||||||
1846 | |||||||
1847 | |||||||
1848 | # Exit with OK status | ||||||
1849 | |||||||
1850 | 1; | ||||||
1851 | |||||||
1852 |