C语言中的广义约化梯度算法

C语言中的广义约化梯度算法,c,algorithm,nonlinear-optimization,C,Algorithm,Nonlinear Optimization,我正在做一些科学项目,我需要用C语言实现非线性优化的广义约化梯度算法。是否有任何库或只是一段代码?或者,请为非线性多变量问题提供任何其他解决方案。我希望建立一个优化模型,使用4个自变量和2个常数:该模型是非线性的。 我已经用Microsoft Excel的解算器检查了使用广义简化梯度(GRG)的解算器是否完美地解决了这个模型,但我需要用C语言进行模拟 以下是我的excel解决方案: 我使用Microsoft Excel Solver和GRG算法来搜索SS的最小值,输出的是常量a和常量b的值。CO

我正在做一些科学项目,我需要用C语言实现非线性优化的广义约化梯度算法。是否有任何库或只是一段代码?或者,请为非线性多变量问题提供任何其他解决方案。我希望建立一个优化模型,使用4个自变量和2个常数:该模型是非线性的。 我已经用Microsoft Excel的解算器检查了使用广义简化梯度(GRG)的解算器是否完美地解决了这个模型,但我需要用C语言进行模拟

以下是我的excel解决方案: 我使用Microsoft Excel Solver和GRG算法来搜索SS的最小值,输出的是常量a和常量b的值。

CONOPT作为GRG的一个既定实现,但不是免费的(尽管演示可能对您来说足够了)

Alglib实现了非线性Levenberg-Marquardt算法,并获得GPL/商业许可

下面是使用alglib的示例代码:

/*
 * Simple optimiser example
 *
 * nl_opt.cpp
 *
 * Compile with eg 'g++ -I../tools/alglib/src ../tools/alglib/src/ap.cpp ../tools/alglib/src/alglibinternal.cpp ../tools/alglib/src/linalg.cpp ../tools/alglib/src/alglibmisc.cpp ../tools/alglib/src/solvers.cpp ../tools/alglib/src/optimization.cpp nl_opt.cpp -o opt'
 *
 */

#include "stdafx.h"
#include <iostream>
#include <cmath>

#include "optimization.h"

using namespace std;

double fn(double a1, double a2, double a3, double x, double A, double B)
{
    return A * exp(-x*(a1*B*B+a2*B+a3));
}

struct problem
{
    double *m_a1s;
    double *m_a2s;
    double *m_a3s;
    double *m_xs;
    double *m_ys;

    int m_n;

    problem(double *a1s, double *a2s, double *a3s, double *xs, double *ys, int n) 
        : m_a1s(a1s), m_a2s(a2s), m_a3s(a3s), m_xs(xs), m_ys(ys), m_n(n)
    {
    }

    void fn_vec(const alglib::real_1d_array &c_var, alglib::real_1d_array &fi, void *ptr)
    {
        double sum = 0.0;
        for(int i = 0; i < m_n; ++i)
        {
            double yhat = fn(m_a1s[i], m_a2s[i], m_a3s[i], m_xs[i], c_var[0], c_var[1]);
            double err_sq = (m_ys[i] - yhat) * (m_ys[i] - yhat);
            sum += err_sq;
        }
        fi[0] = sum;
    }
};

problem *g_p;

void fn_vec(const alglib::real_1d_array &c_var, alglib::real_1d_array &fi, void *ptr)
{
    g_p->fn_vec(c_var, fi, ptr);
}

int main()
{
    cout << "Testing non-linear optimizer..." << endl;

    int n = 5;
    double a1s[] = {2.42, 4.78, 7.25, 9.55, 11.54};
    double a2s[] = {4.25, 5.27, 6.33, 7.32, 8.18};
    double a3s[] = {3.94, 4.05, 4.17, 4.28, 4.37};

    double xs[] = {0.024, 0.036, 0.048, 0.06, 0.072};
    double ys[] = {80, 70, 50, 40, 45};

    double initial[] = {150, 1.75};
    double ss_init = 0.0;

    cout << "Initial problem:" << endl;
    for(int i = 0; i < n; ++i)
    {
        double yhat = fn(a1s[i], a2s[i], a3s[i], xs[i], initial[0], initial[1]);
        double err_sq = (ys[i] - yhat) * (ys[i] - yhat);
        ss_init += err_sq;
        cout << a1s[i] << "\t" << a2s[i] << "\t" << a3s[i] << "\t" 
            << xs[i] << "\t" << ys[i] << "\t" << yhat << "\t" << err_sq << endl;
    }
    cout << "Error: " << ss_init << endl;

    // create problem
    problem p(a1s, a2s, a3s, xs, ys, n);
    g_p = &p;

    // setup solver
    alglib::real_1d_array x = "[150.0, 1.75]";
    double epsg = 0.00000001;
    double epsf = 0;
    double epsx = 0;

    alglib::ae_int_t maxits = 0;
    alglib::minlmstate state;
    alglib::minlmreport report;

    alglib::minlmcreatev(2, x, 0.0001, state);
    alglib::minlmsetcond(state, epsg, epsf, epsx, maxits);

    // optimize
    alglib::minlmoptimize(state, fn_vec);

    alglib::minlmresults(state, x, report);

    cout << "Results:" << endl;

    cout << report.terminationtype << endl;
    cout << x.tostring(2).c_str() << endl;

    double ss_end = 0.0;
    for(int i = 0; i < n; ++i)
    {
        double yhat = fn(a1s[i], a2s[i], a3s[i], xs[i], x[0], x[1]);
        double err_sq = (ys[i] - yhat) * (ys[i] - yhat);
        ss_end += err_sq;
        cout << a1s[i] << "\t" << a2s[i] << "\t" << a3s[i] << "\t"
             << xs[i] << "\t" << ys[i] << "\t" << yhat << "\t" << err_sq << endl;
    }
    cout << "Error: " << ss_end << endl;

    return 0;
}

Mathlab还是Wolferam?我想到这类事情的第一件事。也可以在这里的“数学溢出”中提问。这是一个基于常微分方程组的非线性模型吗?“常数”和“自变量”之间有什么区别?@JonathanGrynspan我在Excel中尝试过解算器,它工作得很好。现在我需要在C语言中实现类似的东西。@MichaelOrgang Matlab、Mathematica和Excel对于这类问题非常有用,但我需要用C语言实现一个解决方案。@s.bandara它类似于f(x1,x2,x3,x4)=y,其中我有值为y,x1,x2,x3,x4的向量。y=A*exp(-x1*(x2*B^2+x3*B+x4))。现在y是因变量,x1,x2,x3,x4是自变量,A和B是常数,我正在寻找。所以算法应该找到这样一个a和B来匹配我提供的向量。同时也指向这个实现。不确定您的目标平台是什么?我实际上使用了Alglib,并将其编译为与objective-c一起使用,因为它是用于os x平台的。我使用了插值。Alglib的h部分,我读到它只是优化曲线拟合算法的包装。希望这是个好电话。
./opt 
Testing non-linear optimizer...
Initial problem:
2.42    4.25    3.94    0.024   80  95.5553 241.968
4.78    5.27    4.05    0.036   70  54.9174 227.485
7.25    6.33    4.17    0.048   50  24.8537 632.338
9.55    7.32    4.28    0.06    40  9.3038  942.257
11.54   8.18    4.37    0.072   45  3.06714 1758.36
Error: 3802.41
Results:
2
[92.22,0.57]
2.42    4.25    3.94    0.024   80  77.6579 5.48528
4.78    5.27    4.05    0.036   70  67.599  5.76475
7.25    6.33    4.17    0.048   50  56.6216 43.8456
9.55    7.32    4.28    0.06    40  46.0026 36.0314
11.54   8.18    4.37    0.072   45  36.6279 70.0922
Error: 161.219