1. 程式人生 > >Levmar:VS2015編譯Levmar及Demo示例

Levmar:VS2015編譯Levmar及Demo示例

參考

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的大小為待求引數個數×觀測次數×每次觀察方程個數