ALglib 是一个跨平台的数值分析和数据处理库。它支持多种编程语言(C + + 、 C # 、 Delphi)和多种操作系统(Windows 和 POSIX,包括 Linux)。

ALglib 功能包括:

  • 数据分析(分类/回归,统计学)
  • 优化和非线性解法
  • 插值和线性/非线性最小二乘拟合
  • 线性代数(直接算法,EVD/SVD) ,直接和迭代线性解法
  • 快速傅里叶变换和许多其他算法

ALglib 官方网站:https://www.alglib.net/
ALglib 开发者手册:https://www.alglib.net/docs.php   手册内有详细的示例可以参考。C#文档点击官方文档manual.csharp.html查阅。

以下用C#实现的函数最小值做说明。

public static void  function1_fvec(double[] x, double[] fi, object obj)
{
    //
    // this callback calculates
    // f0(x0,x1) = 100*(x0+3)^4,
    // f1(x0,x1) = (x1-3)^4
    //
    fi[0] = 10*System.Math.Pow(x[0]+3,2);
    fi[1] = System.Math.Pow(x[1]-3,2);
}
public static int Main(string[] args)
{
    //
    // This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where 
    //
    //     f0(x0,x1) = 10*(x0+3)^2
    //     f1(x0,x1) = (x1-3)^2
    //
    // with boundary constraints
    //
    //     -1 <= x0 <= +1
    //     -1 <= x1 <= +1
    //
    // using "V" mode of the Levenberg-Marquardt optimizer.
    //
    // Optimization algorithm uses:
    // * function vector f[] = {f1,f2}
    //
    // No other information (Jacobian, gradient, etc.) is needed.
    //
    double[] x = new double[]{0,0};
    double[] s = new double[]{1,1};
    double[] bndl = new double[]{-1,-1};
    double[] bndu = new double[]{+1,+1};
    double epsx = 0.0000000001;
    int maxits = 0;
    alglib.minlmstate state;

    //
    // Create optimizer, tell it to:
    // * use numerical differentiation with step equal to 1.0
    // * use unit scale for all variables (s is a unit vector)
    // * stop after short enough step (less than epsx)
    // * set box constraints
    //
    alglib.minlmcreatev(2, x, 0.0001, out state);
    alglib.minlmsetbc(state, bndl, bndu);
    alglib.minlmsetcond(state, epsx, maxits);
    alglib.minlmsetscale(state, s);

    //
    // Optimize
    //
    alglib.minlmoptimize(state, function1_fvec, null, null);

    //
    // Test optimization results
    //
    // NOTE: because we use numerical differentiation, we do not
    //       verify Jacobian correctness - it is always "correct".
    //       However, if you switch to analytic gradient, consider
    //       checking it with OptGuard (see other examples).
    //
    alglib.minlmreport rep;
    alglib.minlmresults(state, out x, out rep);
    System.Console.WriteLine("{0}", alglib.ap.format(x,2)); // EXPECTED: [-1,+1]
    System.Console.ReadLine();
    return 0;
}
官方示例 minlm_d_vb example

此算法计算出给定x1,x2,x3...范围内函数f(x1),f(x2),f(x3)...的平方和最小时的x1,x2,x3...数值。以下接口函数存在多个重载,以其中一个记录说明

1、接口函数minlmcreatev,创建优化器。存在两个重载,示例用的alglib.minlmcreatev( int m, double[] x, double diffstep, out minlmstate state, alglib.xparams _params =alglib.xdefault),可参考以下另一个重载的说明。

/// <summary>
/// 创建优化器
/// </summary>
/// <param name="n">x数量</param>
/// <param name="m">f[i] 数量</param>

/// <param name="x">实例化的x数组,用于最终结果输出</param>
/// <param name="diffstep">微分步长 (值>0)</param>
/// <param name="state">存储算法状态的结构</param>
/// <param name="_params"></param>

static void alglib.minlmcreatev(int n,int m, double[] x,double diffstep,out minlmstate state,alglib.xparams _params = alglib.xdefault)

2、接口函数minlmsetbc,为LM优化器设置边界约束

/// <summary>
/// 为LM优化器设置x验证值边界约束
/// </summary>
/// <param name="state">存储算法状态的结构</param>
/// <param name="bndl">x1,x2,x3...设置的最小值组合</param>
/// <param name="bndu">x1,x2,x3...设置的最大值组合</param>
/// <param name="_params"></param>
public static void alglib.minlmsetbc(minlmstate state, double[] bndl, double[] bndu, alglib.xparams _params = alglib.xdefault);

 3、接口函数minlmsetcond,设置LM优化算法的停止条件

/// <summary>
/// 设置LM优化算法的停止条件
/// </summary>
/// <param name="state">存储算法状态的结构</param>
/// <param name="epsx">如果在 k + 1次迭代中满足条件 | v | < = EpsX,则子例程完成其工作,其中:

* | 。| 表示欧氏范数

* v-刻度步进向量,v [ i ] = dx [ i ]/s [ i ]

* dx-ste 向量,dx = X (k + 1)-X (k)

* s-刻度系数由 MinLMSetScale ()设置推荐值: 1E-9... 1E-12。</param>
/// <param name="maxits">最大迭代次数。如果 MaxIt = 0,则迭代次数是无限的。</param>
/// <param name="_params"></param>
public static void alglib.minlmsetcond(minlmstate state, double epsx, int maxits, alglib.xparams _params = alglib.xdefault);

4、接口函数minlmsetscale,设置 LM 优化器的比例系数。

/// <summary>
/// 设置 LM 优化器的比例系数。
/// </summary>
/// <param name="state">存储算法状态的结构</param>
/// <param name="s">对应x个数的数组,非零尺度系数</param>
/// <param name="_params"></param>
public static void alglib.minlmsetscale(minlmstate state, double[] s, alglib.xparams _params = alglib.xdefault);

5、接口函数minlmoptimize,启动非线性优化器的迭代。fvec为包含多个f[i]的函数实现。以上示例迭代效果可参考底下的运行日志图片

/// <summary>
/// 启动非线性优化器的迭代。
/// </summary>
/// <param name="state">存储算法状态的结构</param>
/// <param name="fvec">迭代的函数族</param>
/// <param name="rep">每次迭代后调用的可选回调,可以为 NULL</param>
/// <param name="obj">外部传入的参数值,可用于函数计算</param>
public static void minlmoptimize(minlmstate state, ndimensional_fvec fvec, ndimensional_rep rep, object obj);

6、接口函数minlmresults,莱文伯格-马夸特算法结果,得到最终计算的x数组结果,获取opt结果报告

/// <summary>
/// 获取算法结果
/// </summary>
/// <param name="state">存储算法状态的结构</param>
/// <param name="x">最终计算的x数组结果</param>
/// <param name="rep">opt结果报告</param>
/// <param name="_params"></param>
public static void alglib.minlmresults(minlmstate state, out double[] x, out minlmreport rep, alglib.xparams _params = alglib.xdefault);

示例中用到了两个函数

   fi[0] = 10*(x[0]+3)^2;
    fi[1] = (x[1]-3)^2;

求解f[x0,x1] = fi[0]^2 + fi[1]^2 = 100*(x[0] + 3)^4 + (x[1] - 3)^4 的最小值。按数学计算可知,在整个域中,当x[0] = -3,x[1] = 3,时函数值最小,为0。

修改x数组最小最大边界值,设置大于[-3,3]:

  double[] bndl = new double[]{-10,-10};
    double[] bndu = new double[]{+10,+10};

以下为函数迭代记录

 

迭代131次后,计算出结果x0=-3,x1=3;计算结束。

 补充说明:算法可结合最小二乘法。最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。最小二乘法还可用于曲线拟合。其他一些优化问题也可通过最小化能量或最大化熵用最小二乘法来表达。求取误差值最小时的一组参数值。