| 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 |