我有几个关于使用非线性约束设置 NLopt 的问题:
- 如果约束的数量大于变量的数量,我们如何
grad[ ]
在约束函数中设置呢?是否有任何(自动)方法可以在不引入拉格朗日乘数的情况下解决问题?
使用拉格朗日多路复用器,我知道我们可以解决问题。但是使用拉格朗日多路复用器必须my_constraint_data
手动获取,难以解决大规模问题。
例如,假设我想最小化函数
f(x1,x2) = -((x1)^3)-(2*(x2)^2)+(10*(x1))-6-(2*(x2)^3)
受以下约束:
约束 1:c1 = 10-(x1)*(x2) >= 0
约束 2:c2 = ((x1)*(x2)^2)-5 >= 0
约束 3:c3 = (x2)-(x1)*(x2)^3 >= 0
在 NLopt 教程中,我们知道它是约束grad[0] = d(c1)/d(x1)
的grad[1] = d(c2)/d(x2)
梯度。然后,我们设置grad
如下:
double myconstraint(unsigned n, const double *x, double *grad, void *data) {
my_constraint_data *d = (my_constraint_data *)data;
if (grad) {
grad[0] = -x[1]; //grad[0] = d(c1)/dx[1]
grad[1] = 2*x[0]+x[1]; //grad[1] = d(c2)/dx[2]
grad[2] = ???; //grad[2] = d(c3)/dx[3] but we only have 2 variable (x1)&(x2)
}
return (10-x[0]*x[1], x[0]*x[1]*x[1]-5, x[1]-x[0]*x[1]*x[1]*x[1];
}
问题是如果约束的数量大于变量的数量,我们不知道如何设置grad[ ]
(尤其是对于)。c3
当然,我们可以通过使用拉格朗日多路复用器 (l1, l2, l3) 来解决以下非自动方法的问题,其中
grad[0] = -l1*(d(c1)/d(x1))-l2*(d(c2)/d(x1))-l3*(d(c)/d(x1))
和
grad[1] = -l1*(d(c1)/d(x2))-l2*(d(c2)/d(x2))-l3*(d(c)/d(x3))
double myconstraint(unsigned n, const double *x, double *grad, void *data) {
my_constraint_data *d = (my_constraint_data *)data;
//set l1, l2, and l3 as parameter of lagrangian multiplier
double l1=d->l1,l2=d->l2,l3=d->l3;
++count;
if (grad) {
grad[0] = l1*x[1]-l2*x[1]*x[1]-l3*x[1]*x[1]*x[1];
grad[1] = l1*x[0]-2*l2*x[0]*x[1]-l3+3*l3*x[0]*x[1]*x[1];
}
return (10-x[0]*x[1], x[0]*x[1]*x[1]-5, x[1]-x[0]*x[1]*x[1]*x[1]);
}
同时,将非自动方法应用于大规模问题并不容易,因为它效率低且编程复杂。
- 有什么方法可以使用 NLopt 求解非线性联立方程?(当应用拉格朗日多路复用器时,在约束数大于变量数的情况下,应求解非线性联立方程。)。
我们感谢您的回答。这对我们真的很有帮助。谢谢你的好意。