Levmar on Mac
ドキュメントはあまり用意されていない模様。 関数の仕様についてはコード内のコメントが充実している。
Getting start
ライブラリは順に依存していくので生成された*.aファイルは/usr/libあたりにln -sする
gfortranをインストール
brewのが手軽で良いかも
blasをmake -> blas_LINUX.a
lapackをmake -> lapack_LINUX.a
libf2cをmake -> libf2c.a
levmarをmake -> liblevmar.a
2021/11追記
それぞれ新しいverが出ているので必要に応じて差し替える。特にlapackは古いコードと新しいgccの相性の問題があるので差し替え推奨。
リンカオプションに-lgfortranが必要なことが多い。
gccはXCodeのを使うと何かとうまく行かないのでgfortranについてきたgccを使う。
Example
サンプルコード
3点の2次元データを線形近似
g++ main.cpp -llevmar -llapack -lblas -lgfortran
#include <stdio.h>
#include <stdlib.h>
#include <levmar.h>
void func(double *p, double *hx, int m, int n, void *adata);
int main()
{
double* p; p = (double*)malloc(2*sizeof(double)); p[0]=0.0; p[1]=0.0;
double* x; x = NULL;
int m; m = 2; //num of parameter
int n; n = 3; //num of equation
int itmax; itmax = 300; //iteration max
double* opts; opts = NULL;
double* info; info = NULL;
double* work; work = NULL;
double* covar; covar = NULL;
void* adata; adata = NULL;
dlevmar_dif(func, p, x, m, n, itmax, opts, info, work, covar, adata);
printf("x = %f\ny = %f\n", p[0], p[1]);
return 0;
}
void func(double *p, double *hx, int m, int n, void *adata) //p:parameter vector, hx:objective function vector
{
double datax[3] = {1.0, 2.0, 3.0};
double datay[3] = {5.0, 8.0, 11.0};
hx[0] = (-datay[0] + p[0] * datax[0] + p[1]) * (-datay[0] + p[0] * datax[0] + p[1]);
hx[1] = (-datay[1] + p[0] * datax[1] + p[1]) * (-datay[1] + p[0] * datax[1] + p[1]);
hx[2] = (-datay[2] + p[0] * datax[2] + p[1]) * (-datay[2] + p[0] * datax[2] + p[1]);
return;
}
xlevmar_bc_dif
バウンダリの制約をかける。p[i]の値の範囲の下限がlb[i]、上限がub[i]に設定される。
/* No Jacobian version of the LEVMAR_BC_DER() function above: the Jacobian is approximated with
* the aid of finite differences (forward or central, see the comment for the opts argument)
* Ideally, this function should be implemented with a secant approach. Currently, it just calls
* LEVMAR_BC_DER()
*/
int LEVMAR_BC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *lb, /* I: vector of lower bounds. If NULL, no lower bounds apply */
LM_REAL *ub, /* I: vector of upper bounds. If NULL, no upper bounds apply */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[5], /* I: opts[0-4] = minim. options [\mu, \epsilon1, \epsilon2, \epsilon3, \delta]. Respectively the
* scale factor for initial \mu, stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2 and
* the step used in difference approximation to the Jacobian. Set to NULL for defaults to be used.
* If \delta<0, the Jacobian is approximated with central differences which are more accurate
* (but slower!) compared to the forward differences employed by default.
*/
LM_REAL info[LM_INFO_SZ],
/* O: information regarding the minimization. Set to NULL if don't care
* info[0]= ||e||_2 at initial p.
* info[1-4]=[ ||e||_2, ||J^T e||_inf, ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
* info[5]= # iterations,
* info[6]=reason for terminating: 1 - stopped by small gradient J^T e
* 2 - stopped by small Dp
* 3 - stopped by itmax
* 4 - singular matrix. Restart from current p with increased mu
* 5 - no further error reduction is possible. Restart with increased mu
* 6 - stopped by small ||e||_2
* 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
* info[7]= # function evaluations
* info[8]= # Jacobian evaluations
* info[9]= # linear systems solved, i.e. # attempts for reducing error
*/
LM_REAL *work, /* working memory at least LM_BC_DIF_WORKSZ() reals large, allocated if NULL */
LM_REAL *covar, /* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
void *adata) /* pointer to possibly additional data, passed uninterpreted to func.
* Set to NULL if not needed
*/