如何建立具有多个不平等约束的nlopt?

时间:2019-03-12 03:11:03

标签: visual-c++ nonlinear-optimization nlopt

关于设置具有非线性约束的NLopt,我有几个问题:

  1. 如果约束数量大于变量数量,如何在约束函数中设置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]);
}

同时,将非自动方法应用于大规模问题并不容易,因为它将使编程效率低下且复杂。

  1. 是否有使用NLopt求解非线性联立方程的方法? (当约束数量大于变量数量时,应用拉格朗日复用器时,应求解非线性联立方程。)

感谢您的答复。这对我们真的很有帮助。谢谢您的好意。

1 个答案:

答案 0 :(得分:0)

我认为您已经将要最小化的约束和变量混淆了。如果我正确理解了您的问题,则需要为三个约束创建三个单独的约束函数。例如:

double c1(unsigned n, const double *x, double *grad, void *data)
{
    /* Enforces the constraint
     *
     *     10 - x1*x2 >= 0
     *
     * Note we compute x1*x2 - 10 instead of 10 - x1*x2 since nlopt expects
     * inequality constraints to be of the form h(x) <= 0. */

    if (grad) {
        grad[0] = x[1]; // grad[0] = d(c1)/dx1
        grad[1] = x[0]; // grad[1] = d(c1)/dx2
    }

    return x[0]*x[1] - 10;
}

double c2(unsigned n, const double *x, double *grad, void *data)
{
    /* Enforces the constraint
     *
     *     x1*x2^2 - 5 >= 0
     *
     * Note we compute -x1*x2^2 - 5 instead of x1*x2^2 - 5 since nlopt expects
     * inequality constraints to be of the form h(x) <= 0. */

    if (grad) {
        grad[0] = -x[1]*x[1];
        grad[1] = -2*x[0]*x[1];
    }

    return -x[0]*x[1]*x[1] + 5;
}

然后,在您的main函数中,您需要分别添加每个不等式约束:

int main(int argc, char **argv)
{
    // set up nlopt here

    /* Add our constraints. */
    nlopt_add_inequality_constraint(opt, c1, NULL, 1e-8);
    nlopt_add_inequality_constraint(opt, c2, NULL, 1e-8);
    // etc.
}