将void函数作为参数传递给c ++中的double函数
Passing void function as argument into double function in c++
我正在尝试使用 NLopt 库解决 C++ 中的优化问题。文档指示要优化的输入函数应如下所示:
double myfunc(const std::vector<double> &x, std::vector<double> &grad, void *my_func_data);
我不明白如何使用 void *my_func_data
参数,它接受优化函数所需的额外数据。
文档在此处显示了创建要优化的函数的示例:
int count = 0;
double myfunc(int n, const double *x, double *grad, void *my_func_data)
{
++count;
if (grad) {
grad[0] = 0.0;
grad[1] = 0.5 / sqrt(x[1]);
}
return sqrt(x[1]);
}
但是,他们不使用 void *my_func_data
参数。
我想使用这个参数,因为我有额外的数据需要传入。我的函数如下所示:
double myfunc(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]);
}
my_func_data;
double xM = 1.;
double yM = 1.;
double xF = 1.;
double yF = 1.;
double theta = 2.;
double tx = 1.4;
double ty = 0.4;
return sqrt(
pow(abs(xF - (cos(theta)*xM) - (sin(theta)*yM) + tx), 2) + \
pow(abs(yF - (sin(theta)*xM) + (cos(theta)*yM) + ty), 2)
);
}
但是,我想要这些变量:
double xM = 1.;
double yM = 1.;
double xF = 1.;
double yF = 1.;
将使用 my_func_data
参数传递给函数,但我不明白如何格式化空输入参数。请指教
文档:
https://nlopt.readthedocs.io/en/latest/NLopt_Tutorial/#example-in-c
xM,yM是存储在Point2f向量中的x,y坐标。 xF, yF 也是存储在 Point2f 向量中的 x,y 坐标。
编辑
现在我的代码是这样的:
struct ExtraData
{
double xM = 1.;
double yM = 1.;
double xF = 1.;
double yF = 1.;
};
double myfunc(const std::vector<double> &x, std::vector<double> &grad, void *my_func_data);
double myfunc(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]);
}
ExtraData* extraData = static_cast<ExtraData*>(my_func_data);
double xM = extraData -> xM;
double yM = extraData -> yM;
double xF = extraData -> xF;
double yF = extraData -> yF;
// double xM = 1.;
// double yM = 1.;
// double xF = 1.;
// double yF = 1.;
double theta = 2.;
double tx = 1.4;
double ty = 0.4;
return sqrt(
pow(abs(xF - (cos(theta)*xM) - (sin(theta)*yM) + tx), 2) + \
pow(abs(yF - (sin(theta)*xM) + (cos(theta)*yM) + ty), 2)
);
}
int main()
{
nlopt::opt opt(nlopt::LD_SLSQP, 2);
std::vector<double> lb(2);
lb[0] = -HUGE_VAL; //HUGE_VAL is a C++ constant
lb[1] = 0;
opt.set_lower_bounds(lb);
opt.set_min_objective(myfunc, NULL);
double data[4] = {2,0,-1,1}; //use one dimensional array
std::vector<double> tol_constraint(2);
tol_constraint[0] = 1e-8;
tol_constraint[1] = 1e-8;
opt.add_inequality_mconstraint(multi_constraint, data, tol_constraint);
opt.set_xtol_rel(1e-4);
std::vector<double> x(2);
x[0] = 1.234;
x[1] = 5.678;
double minf;
nlopt::result result = opt.optimize(x, minf);
std::cout << "The result is" << std::endl;
std::cout << result << std::endl;
std::cout << "Minimal function value " << minf << std::endl;
}
编译,但是当我 运行 它时,我得到:
Segmentation fault: 11
您必须定义包含所需数据的结构:
struct ExtraData
{
double xM = 1.;
double yM = 1.;
double xF = 1.;
double yF = 1.;
};
我不知道这个库 - 但它可能具有接受 void*
和指向你的函数的函数 - 让我们将其称为 Xxxx
:
Xxxx(..., double(*)(const std::vector<double>&, std::vector<double> &, void *), void* extraData);
当您传递指针 ExtraData*
类型时 - 它会自动转换为 void*
。
ExtraData extraData{.xM = 1., ... };
Xxxx(..., &myfunc, &extraData);
在您的函数中 - 从 void*
显式转换为 ExtraData*
:
double myfunc(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]);
}
ExtraData* extraData = reinterpret_cast<ExtraData*>(my_func_data);
double xM = = extraData->xM;
...
在文档中,您有此类用法的示例 - 查看第一行:
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]);
}
因此,一对函数指针和 void* 数据 - 是非常古老的(源自“C”)将“仿函数”或“回调”传递给其他函数的方式。现代 C++ 方式是 lambdas
和 std::function
.
我正在尝试使用 NLopt 库解决 C++ 中的优化问题。文档指示要优化的输入函数应如下所示:
double myfunc(const std::vector<double> &x, std::vector<double> &grad, void *my_func_data);
我不明白如何使用 void *my_func_data
参数,它接受优化函数所需的额外数据。
文档在此处显示了创建要优化的函数的示例:
int count = 0;
double myfunc(int n, const double *x, double *grad, void *my_func_data)
{
++count;
if (grad) {
grad[0] = 0.0;
grad[1] = 0.5 / sqrt(x[1]);
}
return sqrt(x[1]);
}
但是,他们不使用 void *my_func_data
参数。
我想使用这个参数,因为我有额外的数据需要传入。我的函数如下所示:
double myfunc(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]);
}
my_func_data;
double xM = 1.;
double yM = 1.;
double xF = 1.;
double yF = 1.;
double theta = 2.;
double tx = 1.4;
double ty = 0.4;
return sqrt(
pow(abs(xF - (cos(theta)*xM) - (sin(theta)*yM) + tx), 2) + \
pow(abs(yF - (sin(theta)*xM) + (cos(theta)*yM) + ty), 2)
);
}
但是,我想要这些变量:
double xM = 1.;
double yM = 1.;
double xF = 1.;
double yF = 1.;
将使用 my_func_data
参数传递给函数,但我不明白如何格式化空输入参数。请指教
文档: https://nlopt.readthedocs.io/en/latest/NLopt_Tutorial/#example-in-c
xM,yM是存储在Point2f向量中的x,y坐标。 xF, yF 也是存储在 Point2f 向量中的 x,y 坐标。
编辑
现在我的代码是这样的:
struct ExtraData
{
double xM = 1.;
double yM = 1.;
double xF = 1.;
double yF = 1.;
};
double myfunc(const std::vector<double> &x, std::vector<double> &grad, void *my_func_data);
double myfunc(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]);
}
ExtraData* extraData = static_cast<ExtraData*>(my_func_data);
double xM = extraData -> xM;
double yM = extraData -> yM;
double xF = extraData -> xF;
double yF = extraData -> yF;
// double xM = 1.;
// double yM = 1.;
// double xF = 1.;
// double yF = 1.;
double theta = 2.;
double tx = 1.4;
double ty = 0.4;
return sqrt(
pow(abs(xF - (cos(theta)*xM) - (sin(theta)*yM) + tx), 2) + \
pow(abs(yF - (sin(theta)*xM) + (cos(theta)*yM) + ty), 2)
);
}
int main()
{
nlopt::opt opt(nlopt::LD_SLSQP, 2);
std::vector<double> lb(2);
lb[0] = -HUGE_VAL; //HUGE_VAL is a C++ constant
lb[1] = 0;
opt.set_lower_bounds(lb);
opt.set_min_objective(myfunc, NULL);
double data[4] = {2,0,-1,1}; //use one dimensional array
std::vector<double> tol_constraint(2);
tol_constraint[0] = 1e-8;
tol_constraint[1] = 1e-8;
opt.add_inequality_mconstraint(multi_constraint, data, tol_constraint);
opt.set_xtol_rel(1e-4);
std::vector<double> x(2);
x[0] = 1.234;
x[1] = 5.678;
double minf;
nlopt::result result = opt.optimize(x, minf);
std::cout << "The result is" << std::endl;
std::cout << result << std::endl;
std::cout << "Minimal function value " << minf << std::endl;
}
编译,但是当我 运行 它时,我得到:
Segmentation fault: 11
您必须定义包含所需数据的结构:
struct ExtraData
{
double xM = 1.;
double yM = 1.;
double xF = 1.;
double yF = 1.;
};
我不知道这个库 - 但它可能具有接受 void*
和指向你的函数的函数 - 让我们将其称为 Xxxx
:
Xxxx(..., double(*)(const std::vector<double>&, std::vector<double> &, void *), void* extraData);
当您传递指针 ExtraData*
类型时 - 它会自动转换为 void*
。
ExtraData extraData{.xM = 1., ... };
Xxxx(..., &myfunc, &extraData);
在您的函数中 - 从 void*
显式转换为 ExtraData*
:
double myfunc(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]);
}
ExtraData* extraData = reinterpret_cast<ExtraData*>(my_func_data);
double xM = = extraData->xM;
...
在文档中,您有此类用法的示例 - 查看第一行:
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]);
}
因此,一对函数指针和 void* 数据 - 是非常古老的(源自“C”)将“仿函数”或“回调”传递给其他函数的方式。现代 C++ 方式是 lambdas
和 std::function
.