27 #ifndef levmarInterface_hpp
28 #define levmarInterface_hpp
32 #include "../../mxlib.hpp"
35 #include "../../sys/timeUtils.hpp"
100 template<
class fitterT>
106 typedef typename fitterT::realT realT;
313 template<
typename iosT,
char comment='#'>
320 template<
char comment='#'>
329 template<
typename iosT,
char comment='#'>
331 bool dumpParams =
true
338 template<
char comment='#'>
343 template<
class fitterT>
355 set_opts_default(-1);
363 for(
int i=0;i<LM_INFO_SZ; ++i) info[i] = 0;
369 template<
class fitterT>
375 template<
class fitterT>
377 typename fitterT::realT *i_x,
391 template<
class fitterT>
394 if(p && own_p) free(p);
396 if(init_p) free(init_p);
400 if(covar) free(covar);
403 template<
class fitterT>
421 init_p = (
typename fitterT::realT *) malloc(
sizeof(
typename fitterT::realT) * m);
425 template<
class fitterT>
432 template<
class fitterT>
440 p = (
typename fitterT::realT *) malloc(
sizeof(
typename fitterT::realT) * m);
445 template<
class fitterT>
453 template<
class fitterT>
465 template<
class fitterT>
472 template<
class fitterT>
478 template<
class fitterT>
484 template<
class fitterT>
490 template<
class fitterT>
493 for(
int i=0;i<m;i++) p[i] = i_p[i];
498 template<class fitterT, bool jacf = hasJacobian<fitterT>::value>
499 struct levmar_allocate_size
501 typedef typename fitterT::realT realT;
503 int operator()(
int m,
int n)
505 return LM_DIF_WORKSZ(m,n);
510 template<
class fitterT>
511 struct levmar_allocate_size<fitterT, true>
513 typedef typename fitterT::realT realT;
515 int operator()(
int m,
int n)
517 return LM_DER_WORKSZ(m,n);
521 template<
class fitterT>
525 levmar_allocate_size<fitterT> alloc_sz;
527 if(work_sz < alloc_sz(m,n) || !work)
531 work_sz = alloc_sz(m,n);
532 work = (realT *) malloc( work_sz *
sizeof(realT));
538 if(covar_sz < m*m || !covar)
540 if(covar) free(covar);
543 covar = (realT *) malloc(covar_sz *
sizeof(realT));
549 if(covar) free(covar);
555 template<
class fitterT>
562 template<
class fitterT>
567 if(n == 0 || n == -1)
569 opts[0] = LM_INIT_MU;
574 opts[n] = LM_STOP_THRESH;
578 opts[1] = LM_STOP_THRESH;
579 opts[2] = LM_STOP_THRESH;
580 opts[3] = LM_STOP_THRESH;
583 if(n == 4 || n == -1)
585 opts[4] = LM_DIFF_DELTA;
589 template<
class fitterT>
596 template<class fitterT, bool jacf = hasJacobian<fitterT>::value>
599 typedef typename fitterT::realT realT;
601 int operator()(realT *p,
612 return levmar_dif<realT>( &fitterT::func, p, x, m, n, itmax, opts, info, work, covar, adata);
617 template<
class fitterT>
618 struct do_levmar<fitterT, true>
620 typedef typename fitterT::realT realT;
622 int operator()(realT *p,
633 return levmar_der<realT>( &fitterT::func, &fitterT::jacf, p, x, m, n, itmax, opts, info, work, covar, adata);
638 template<
class fitterT>
645 if(opts[0] == 0) _opts= 0;
655 init_p = (
typename fitterT::realT *) malloc(
sizeof(
typename fitterT::realT) * m);
658 for(
int i = 0; i < m; ++i) init_p[i] = p[i];
663 do_levmar<fitterT> fitter;
665 fitter(p,x,m,n,itmax,_opts,info,work,covar,adata);
674 template<
class fitterT>
680 template<
class fitterT>
686 template<
class fitterT>
689 return (
int) info[5];
692 template<
class fitterT>
695 return (
int) info[6];
698 template<
class fitterT>
701 return (
int) info[7];
704 template<
class fitterT>
707 return (
int) info[8];
710 template<
class fitterT>
713 return (
int) info[9];
716 template<
class fitterT>
719 switch(get_reason_code())
722 return "stopped by small gradient J^T e";
725 return "stopped by small Dp";
728 return "stopped by itmax";
731 return "singular matrix. Restart from current p with increased mu";
734 return "no further error reduction is possible. Restart with increased mu";
737 return "stopped by small ||e||_2";
740 return "stopped by invalid (i.e. NaN or Inf) \"func\" values. This is a user error";
743 return "unknown reason code";
748 template<
class fitterT>
749 template<
typename iosT,
char comment>
753 char c[] = {comment,
'\0'};
755 ios <<
c <<
"Current parameters (initial):\n";
759 ios <<
"p[" << i <<
"] = " << p[i] <<
" (" << init_p[i] <<
")\n";
765 template<
class fitterT>
766 template<
char comment>
769 return dumpParameters<std::ostream,comment>(std::cout);
772 template<
class fitterT>
773 template<
typename iosT,
char comment>
778 char c[] = {comment,
'\0'};
780 ios <<
c <<
"--------------------------------------\n";
781 ios <<
c <<
"mx::math::fit::levmarInterface Results \n";
782 ios <<
c <<
"--------------------------------------\n";
783 if(dumpParams) dumpParameters<iosT,comment>(ios);
784 ios <<
c <<
"Reason for termination: " << get_reason_string() <<
"\n";
785 ios <<
c <<
"Initial norm: " << get_initial_norm() <<
"\n";
786 ios <<
c <<
"Final norm: " << get_final_norm() <<
"\n";
787 ios <<
c <<
"Number of iterations: " << get_iterations() <<
"\n";
788 ios <<
c <<
"Function evals: " << get_fevals() <<
"\n";
789 ios <<
c <<
"Jacobian evals: " << get_jevals() <<
"\n";
790 ios <<
c <<
"Elapsed time: " << get_deltaT() <<
" secs\n";
791 dumpGitStatus<iosT,comment>(ios);
796 template<
class fitterT>
797 template<
char comment>
800 return dumpReport<std::ostream, comment>(std::cout);
810 template <
typename T>
818 template <
typename fitterT>
819 static yes& test(
typename fitterT::hasJacobian*);
822 static no& test(...);
828 static const bool value =
sizeof(test<T>(0)) ==
sizeof(yes);
835 template<
typename realT>
A templatized interface to the levmar package.
realT info[LM_INFO_SZ]
Information regarding the minimization.
void point_params(realT *i_p, int i_m)
Point the parameter pointer at an externally allocated array.
void set_params(realT *i_p)
Copy parameters to the parameter array.
realT * covar
Covariance matrix corresponding to LS solution; mxm.
int itmax
Maximum number of iterations, default is 100.
void nParams(int i_m)
Set number of parameters, but don't allocate.
realT * x
I: measurement vector. NULL implies a zero vector.
realT get_final_norm()
Returns the L2-norm at the end of the minimization.
void set_opts(int n, realT val)
Set one of the minimization options to val.
int fit()
Perform the fit.
std::string get_reason_string()
Get the descriptive string describing the reason minimization terminated.
realT get_initial_norm()
Returns the L2-norm before minimization occurs.
void allocate_params()
Allocate parameters array based on previous call to nParams.
iosT & dumpReport(iosT &ios, bool dumpParams=true)
Output current parameters to a stream.
int get_reason_code()
Get a code specifying the reason minimization terminated.
std::ostream & dumpReport(bool dumpParams=true)
Dump a status report to stdout.
realT * init_p
Parameter array on input, saved for comparison.
levmarInterface(realT *i_p, realT *i_x, int i_m, int i_n, void *i_adata)
Setup constructor.
int get_jevals()
Get the number of jacobian evaluations during the minimization.
void set_opts_default(int n=-1)
Set one or all of the minimization options to the default.
iosT & dumpParameters(iosT &ios)
Output current parameters to a stream.
int m
Parameter vector dimension (i.e. number of unknowns)
~levmarInterface()
Destructor.
realT * p
Parameter array. On input is the initial estimates. On output has the estimated solution.
realT get_opts(int n)
Get the current value of an option.
void allocate_work()
Allocate the work and covar matrices.
void allocate_params(int i_m)
Set number of parameters and allocate.
double deltaT
Elapsed time of the fitting procedure.
int n
I: measurement vector dimension.
int get_nlinsys()
Get the number of linear system solutions during the minimization.
std::ostream & dumpParameters()
Dump the parameter vector to stdout.
realT opts[LM_OPTS_SZ]
Options passed to the minimization routines. See set_opts for details.
int get_fevals()
Get the number of function evaluations during the minimization.
realT * get_params()
Get current pointer array address.
realT * work
Working memory passed to the levmar routines.
void point_params(realT *i_p)
Point the parameter pointer at an externally allocated array.
int nParams()
Get the current number of parameters.
double get_deltaT()
Get the elapsed time of the fit.
levmarInterface()
Default constructor.
void * adata
Pointer to possibly additional data, passed uninterpreted to func & jacf.
bool own_p
Flag indicating whether the p array is owned by this object (for de-allocation).
void set_itmax(int i_itmax)
Set the maximum number of iterations.
int covar_sz
The current size of the covar array.
int get_iterations()
Get the number of iterations taken during the minimization.
int work_sz
The current size of the work array.
bool getCovar
Controls whether the covar array is allocated.
int get_itmax()
Get the maximum number of iterations.
constexpr units::realT c()
The speed of light.
typeT get_curr_time(timespec &tsp)
Get the current system time in seconds.
Wrapper for a native array to pass to levmarInterface.
size_t ny
X dimension of the array.
size_t nx
Pointer to the array.
Test whether a function type has a Jacobian function by testing whether it has a typedef of "hasJacob...
Templatized wrappers to the levmar minimization routines..