How to set up nlopt with multiple inequality constraints?

I have a few questions about setting up NLopt with non-linear constraints:

  1. If the number of constraints is bigger than the number of variables, how can we set grad[ ] in the constraint function? Is there any (automatic) method to solve the problem without introducing Lagrangian multiplier?

Using a Lagrangian multiplexer, I know we can solve the problem. However the use of Lagrangian multiplexer we have to obtain my_constraint_data manually, which make it difficult to solve large-scale problem.

For example, suppose I want to minimize the function

f(x1,x2) = -((x1)^3)-(2*(x2)^2)+(10*(x1))-6-(2*(x2)^3)

subject to the following constraints:

Constraint 1: c1 = 10-(x1)*(x2) >= 0

Constraint 2: c2 = ((x1)*(x2)^2)-5 >= 0

Constraint 3: c3 = (x2)-(x1)*(x2)^3 >= 0

In NLopt tutorial, we know that grad[0] = d(c1)/d(x1) and grad[1] = d(c2)/d(x2) as the gradient of constraints. Then, we set grad as follows:

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];
}

The problem is we do not know how to set grad[ ] (especially for c3) if the number of constraints are larger than the number of variables.

Of course we can solve the problem with non-automatic method like below by using Lagrangian multiplexer (l1, l2, l3) where

grad[0] = -l1*(d(c1)/d(x1))-l2*(d(c2)/d(x1))-l3*(d(c)/d(x1))

and

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]);
}

Meanwhile, it is not easy to apply non-automatic method into large-scale problem because it will be inefficient and complicated in programming.

  1. Is there any method to solve nonlinear simultaneous equations using NLopt? (When Lagrangian multiplexer is applied in case of the number of constraints are larger than the number of variables, nonlinear simultaneous equations should be solved.).

We appreciate for your answer. It will be really helpful to us. Thank you for all your kindness.

Upvotes: 2

Views: 1787

Answers (1)

user545424
user545424

Reputation: 16189

I think you've got the constraints and the variables you are minimizing mixed up. If I understand your question correctly, you need to create three separate constraint functions for your three constraints. For example:

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

Then, in your main function you need to add each inequality constraint separately:

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

Upvotes: 0

Related Questions