C++ 中的 NLOpt 向量值不等式约束函数签名

问题描述 投票:0回答:1

我正在使用 NLOpt 库实现非线性优化问题,但在使用 C++ 接口定义向量值不等式约束时遇到一些麻烦。

NLOpt 文档似乎表明它们支持定义成本函数以及接受

std::vector<double>&
参数的等式和不等式约束函数,而不是指向数组的指针 (
double*
)。请参阅以下
链接
的“C++ 示例”部分中的
myvfunc()
myvconstraint() 签名。

到目前为止,我已经成功使用以下函数签名编写了成本函数和等式约束:

double cost_fcn(const std::vector<double>& x, std::vector<double>& grad, void* data);
double eq_constraint(const std::vector<double>& x, std::vector<double>& grad, void* data);

NLOpt 文档还描述了对向量值相等和不等式约束的支持。但它们提供的函数签名(如下所示)是 C 格式(使用数组指针)。

void ineq_constraint(
   unsigned m, double *result, unsigned n, const double* x, double* grad, void* f_data);

其中

m
是约束向量的维度,
n
是参数空间的维度。

从文档中尚不清楚向量值约束是否支持 C++ 风格的函数签名,但我尝试实现以下内容,但它不起作用:

void ineq_constraint(
   std::vector<double>& result, const std::vector<double>& x, std::vector<double>& grad, void* data);

此时,我将转而尝试使用 C 风格函数签名,但最好能得到关于 NLOpt 目前是否支持向量值约束的 C++ 风格函数签名的明确答案。

c++ c++17 nonlinear-optimization nlopt
1个回答
0
投票

add_equality_constraint
add_inequality_constraint
具有相同的签名,它们采用签名为

的函数
double myvconstraint(const std::vector<double>& x, std::vector<double>& grad, void* data)

示例:

#include <nlopt.hpp>
#include <iomanip>
#include <iostream>
#include <vector>


struct my_constraint_data  {
    double a, b;
};

double myvfunc(const std::vector<double>& x, std::vector<double>& grad, void* my_func_data)
{
    if (!grad.empty()) {
        grad[0] = 0.0;
        grad[1] = 0.5 / sqrt(x[1]);
    }
    return sqrt(x[1]);
}

double myvconstraint(const std::vector<double>& x, std::vector<double>& grad, void* data)
{
    my_constraint_data* d = reinterpret_cast<my_constraint_data*>(data);
    double a = d->a, b = d->b;
    if (!grad.empty()) {
        grad[0] = 3 * a * (a * x[0] + b) * (a * x[0] + b);
        grad[1] = -1.0;
    }
    return ((a * x[0] + b) * (a * x[0] + b) * (a * x[0] + b) - x[1]);
}

int main()
{
    nlopt::opt opt(nlopt::LD_SLSQP, 2);
    std::vector<double> lb(2);
    lb[0] = -HUGE_VAL; lb[1] = 0;
    opt.set_lower_bounds(lb);
    opt.set_min_objective(myvfunc, NULL);
    my_constraint_data data[2] = { {0.33,0.29}, {-1,1} };
    opt.add_equality_constraint(myvconstraint, &data[0], 1e-8);
    opt.add_inequality_constraint(myvconstraint, &data[1], 1e-8);
    opt.set_xtol_rel(1e-4);
    std::vector<double> x(2);
    x[0] = 1.234; x[1] = 5.678;
    double minf;

    try {
        nlopt::result result = opt.optimize(x, minf);
        std::cout << "found minimum at f(" << x[0] << "," << x[1] << ") = "
            << std::setprecision(10) << minf << std::endl;
    }
    catch (std::exception& e) {
        std::cout << "nlopt failed: " << e.what() << std::endl;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.