非线性优化库liblbfgs初探

  • liblbfgs简介
  • Linux下用gcc 编译
  • Windows下用visual studio编译
  • main函数分析
  • python 封装liblbfgs
  • liblbfgs简介

    liblbfgs是L-BFGS算法的C语言实现,用于求解非线性优化问题。

    liblbfgs的主页:http://www.chokkan.org/software/liblbfgs/

    下载链接(见上面的主页链接):

    Linux下用gcc 编译

    解压文件,进入目录,可参照 软件包里面的说明文档,命令依次如下:

    ./configure

    make

    make install

    编译后的目录文件:

    这里写图片描述

    C源码文件在lib,includesample 三个文件夹里,而主文件在’sample’ 里,其目录如下:

    这里写图片描述

    其中没有文件后缀名的文件sample就是最终的可执行文件,运行:
    这里写图片描述

    Windows下用visual studio编译

    只需要把几个C/C++源码文件加入到项目即可,其余的文件一律弃之不用,如下图所示的VS项目文件的目录,我们只要 4 个头文件 arithmetic_ansi.h arithmetic_sse_double.h arithmetic_sse_float.h lbfgs.h 和三个源文件
    lbfgs.c sample.c sample.cpp

    这里写图片描述

    主函数文件(包含main函数)是 sample.c(用C语言写的),和 sample.cpp(用C++写成,封装成一个类)。一个VS项目里只能有一个main函数,所以每次运行要禁用二者中的一个。

    需要注意的是头文件中的 arithmetic_ansi.h arithmetic_sse_double.h arithmetic_sse_float.h,三个头文件只能用一个,选择哪个由’lbfgs.cpp’中一段代码控制,该段代码如下:

    这里写图片描述

    默认情况下 USE_SSE__SSE2____SSE__ 都没有定义,L-BFGS_FLOAT lbfgs.h中定义。由此可知默认情况下采用的是 arithmetic_ansi.h

    若要采用 arithmetic_sse_double.h,经查L-BFGS_FLOAT 被定义为 64,所以再定义其它两个变量,如下:

    这里写图片描述

    SSE2到底是什么东西呢?插入一段相关介绍:

    SSE2(Streaming SIMD Extensions 2):指令集,扩展了SSE指令集,并可完全取代MMX。SSE2指令集是Intel公司在SSE指令集的基础上发展起来的。相比于SSE,SSE2使用了144个新增指令,扩展了MMX技术和SSE技术,提高了诸如MPEG-2、MP3、3D图形等应用程序的运行性能。在整数处理方面,随MMX技术引进的SIMD整数指令从64位扩展到了128 位,使SIMD整数类型操作的执行效率成倍提高;在浮点数处理方面,双精度浮点SIMD指令允许以 SIMD格式同时执行两个浮点操作,提供双精度操作支持有助于加速内容创建、财务、工程和科学应用。除SSE2指令之外,最初的SSE指令也得到增强,通过支持多种数据类型(例如双字、四字)的算术运算,支持灵活、动态范围更广的计算功能。

    可见引入 arithmetic_sse_double.h arithmetic_sse_float.h 是为了提高浮点数的运算速度,改善程序性能。

    main函数分析

    main函数里给出了一个用L-BFGS算法进行非线性优化的例子,贴出main函数的代码:

    #include <stdio.h>
    #include "lbfgs.h"
    
    //注意lbfgsfloatval_t在lbfgs.h里定义,32位机上是float,64位机上是double。
    
    //evaluate定义要优化的非线性函数fx及其梯度g
    static lbfgsfloatval_t evaluate( 
        void *instance,
        const lbfgsfloatval_t *x,
        lbfgsfloatval_t *g,
        const int n,
        const lbfgsfloatval_t step
        )
    {
        int i;
        lbfgsfloatval_t fx = 0.0;
    
        for (i = 0;i < n;i += 2) {
            lbfgsfloatval_t t1 = 1.0 - x[i];
            lbfgsfloatval_t t2 = 10.0 * (x[i+1] - x[i] * x[i]);
            g[i+1] = 20.0 * t2;
            g[i] = -2.0 * (x[i] * g[i+1] + t1);
            fx += t1 * t1 + t2 * t2;
        }
        return fx;
    }
    
    //progress函数每次迭代结束就执行一次,打印迭代信息
    static int progress(
        void *instance,
        const lbfgsfloatval_t *x,
        const lbfgsfloatval_t *g,
        const lbfgsfloatval_t fx,
        const lbfgsfloatval_t xnorm,
        const lbfgsfloatval_t gnorm,
        const lbfgsfloatval_t step,
        int n,
        int k,
        int ls
        )
    {
        printf("Iteration %d:\n", k);
        printf("  fx = %f,", fx);
        printf("  xnorm = %f, gnorm = %f, step = %f\n", xnorm, gnorm, step);
        return 0;
    }
    
    #define N   100 //参数个数
    
    int main(int argc, char *argv[])
    {
    
        int i, ret = 0;
        lbfgsfloatval_t fx;
        lbfgsfloatval_t *x = lbfgs_malloc(N); //x是长度为N的数组
        lbfgs_parameter_t param;
    
        if (x == NULL) {
            printf("ERROR: Failed to allocate a memory block for variables.\n");
            return 1;
        }
    
        /* Initialize the variables. */
        for (i = 0;i < N;i += 2) {
            x[i] = -1.2;
            x[i+1] = 1.0;
        }
    
        /* Initialize the parameters for the L-BFGS optimization. */
        lbfgs_parameter_init(&param);
        /*param.linesearch = LBFGS_LINESEARCH_BACKTRACKING;*/
    
        /*
            Start the L-BFGS optimization; this will invoke the callback functions
            evaluate() and progress() when necessary.
         */
        ret = lbfgs(N, x, &fx, evaluate, progress, NULL, &param);
    
        printf("算法收敛后的函数取值  fx = %f\n", fx, x[0], x[1]);
    
        printf("最终的解(长度为100个浮点数的数组):");
        for(i=0;i<N;i++) {
            if (i%10 == 0) {
                printf("\n");
            }
            printf("%2.2lf ",x[i]);
        }
        lbfgs_free(x); //释放参数数组所占的内存
    
        return 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
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    非线性函数f(x)f(x) 的定义如下:

    for (i = 0;i < n;i += 2) {
        lbfgsfloatval_t t1 = 1.0 - x[i];
        lbfgsfloatval_t t2 = 10.0 * (x[i+1] - x[i] * x[i]);
        g[i+1] = 20.0 * t2;
        g[i] = -2.0 * (x[i] * g[i+1] + t1);
        fx += t1 * t1 + t2 * t2;
    }
      
      
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    可知输入参数 有100个,即数组 xx定义如下

    f(x)=i=0,2,4,...,N2(1xi)2+(10(xi+1x2i))2f(x)=∑i=0,2,4,...,N−2(1−xi)2+(10(xi+1−xi2))2

    python 封装liblbfgs

    转载自:https://blog.csdn.net/golden1314521/article/details/46772569?utm_source=blogxgwz2

    猜你喜欢

    转载自blog.csdn.net/baidu_38172402/article/details/83094773
    今日推荐