参考
64位 WIN 7/8 下VS2010配置CLAPCAK3.2.1和Levmar2.6
准备
下载CMake:https://cmake.org/
下载clapack_cmake:http://www.netlib.org/clapack/clapack-3.2.1-CMAKE.tgz
下载levmar:http://users.ics.forth.gr/~lourakis/levmar/levmar-2.6.tgz
编译
编译clapack
解压缩后,打开CMake配置源码路径和build路径,然后点击Configure和Generate即可,如下图所示:
关闭CMake,用VS2015打开build目录下的CLAPACK.sln,编译整个项目即可(注意此处我编译的是Release版本):
接下来整理一下编译好的库,其路径分别在
\build\BLAS\SRC\Release\blas.lib
\build\F2CLIBS\libf2c\Release\libf2c.lib
\build\SRC\Release\lapack.lib
\build\Testing\MATGEN\Release\tmglib.lib
- 1
- 2
- 3
- 4
本文将其放在\build\lib\build\lib目录下,当然你也可以放在其他指定目录:
编译levmar
打开CMake,设置源代码路径和build路径(CMake也要选择VS2015 X64),并点击一次Configure
接下来修改宏LAPACKBLAS_DIR,使其目录指向你刚刚设定的clapack的lib所在路径;修改F2C_LIB_NAME,使其和clapack一致,然后再点击一些Configure,最后点击Generate即可。
使用VS2015打开LEVMAR.sln,并将调整为Release,然后进行编译:
Demo示例
接下来是学习Demo里的一个例子,部分截图我就直接从维基扯过来。
工程配置
新建一个VS2015 X64 Release项目,并添加一个main.cpp
添加include和library
配置完成后编译:
代码讲解
Rosenbrock function(香蕉函数):具体定义可以参考到维基网页,是一个用来测试最佳化演算法性能的非凸函数;其全域最小值位于(x, y)=(1, 1)点,数值为f(x, y)=0。
在Levmar的Demo中,通过迭代的方式,去计算x,y。
先贴一下结果:
可以可看到迭代了1000次后,最终求出来的(x,y)已经非常接近(1,1)了。
下边是主要代码:
//main函数
int m=2; n=3; //m表示待求参数的维度,n表示测量值的维度
p[0]=-1.2; p[1]=1.0; //待求参数的初值
for(i=0; i<n; i++) x[i]=0.0; //模拟n次测量的结果,由于是求解,设为零
// 调用迭代入口函数
int ret=dlevmar_der(modros, //描述测量值之间关系的函数指针
jacmodros, //估计雅克比矩阵的函数指针
p, //初始化的待求参数,结果一并保存在其中
x, //测量值
m, //参数维度
n, //测量值维度
1000, //最大迭代次数
opts, //迭代的一些参数
info, //关于最小化结果的一些参数,不需要设为NULL
NULL, NULL, NULL //一些内存的指针,暂时不需要,以后再学习这个具体由什么用);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
在主函数中大致就是以上的几行简单的代码就能调用LM进行迭代,真的是感觉好膜拜啊;在上边调用的函数里还有两个函数指针,下边是关于这两个函数指针的东西。
#define ROSD 105.0
//香蕉函数的公式f(x,y)=(1-x)^2 + 100(y-x^2)^2;
void ros(double *p, double *x, int m, int n, void *data)
{
register int i;
for(i=0; i<n; ++i)
{
//写出参数与x[i]之间的关系式,由于这里方程的右边没有观测值,只有参数看起来怪怪的~_~
x[i]=((1.0-p[0])*(1.0-p[0]) + ROSD*(p[1]-p[0]*p[0])*(p[1]-p[0]*p[0]));
}
}
void jacros(double *p, double *jac, int m, int n, void *data)
{
register int i, j;
//写出雅克比矩阵
for(i=j=0; i<n; ++i)
{
jac[j++]=(-2 + 2*p[0]-4*ROSD*(p[1]-p[0]*p[0])*p[0]);
jac[j++]=(2*ROSD*(p[1]-p[0]*p[0]));
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
以上就是第一个示例,比较简单,但是看起来好有成就感!
levmar还有其他的函数,留到下次再研究,已经满足我目前的需求了!
levmar主要针对于稠密雅克比矩阵,所以jac其实是一个一维的数组,所以jac的大小为待求参数个数×观测次数×每次观察方程个数