【问题标题】:How to set up nlopt with multiple inequality constraints?如何设置具有多个不等式约束的 nlopt?
【发布时间】:2019-08-02 11:00:05
【问题描述】:

我有几个关于使用非线性约束设置 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) where 像下面这样的非自动方法来解决问题

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 求解非线性联立方程吗? (当应用拉格朗日多路复用器时,当约束数大于变量数时,需要求解非线性联立方程。

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

【问题讨论】:

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


    【解决方案1】:

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

    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.
    }
    

    【讨论】:

    • 感谢您的建议。这对我们很有帮助:)
    猜你喜欢
    • 1970-01-01
    • 2015-08-10
    • 1970-01-01
    • 2017-02-10
    • 2020-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-08
    相关资源
    最近更新 更多