Как настроить nlopt с несколькими ограничениями неравенства? - PullRequest
2 голосов
/ 12 марта 2019

У меня есть несколько вопросов о настройке 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]);
}

Между тем, применять неавтоматический метод к крупномасштабной задаче нелегко, поскольку он неэффективен и сложен в программировании.

Существует ли какой-либо метод для решения нелинейных уравнений с использованием NLopt?(Когда применяется лагранжев мультиплексор, если число ограничений больше, чем число переменных, необходимо решить нелинейные уравнения одновременности.).

Мы ценим ваш ответ.Это будет очень полезно для нас.Спасибо за всю вашу доброту.

1 Ответ

0 голосов
/ 18 марта 2019

Я думаю, что у вас есть ограничения и переменные, которые вы минимизируете, перепутаны.Если я правильно понимаю ваш вопрос, вам нужно создать три отдельные функции ограничения для ваших трех ограничений.Например:

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