Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Roundoff error when adding an equality constraint to SLSQP #400

Open
JeremyBois opened this issue Jun 21, 2021 · 0 comments
Open

Roundoff error when adding an equality constraint to SLSQP #400

JeremyBois opened this issue Jun 21, 2021 · 0 comments

Comments

@JeremyBois
Copy link

JeremyBois commented Jun 21, 2021

Hi,

Description

I'm trying to use the SLSQP optimizer with equality and inequality constraints to port a code from python (using scipy) to C# (using NLoptNet nlopt wrapper).

When using SLSQP version of scipy I can add equality constraints without any issues. When using SLSQP version from nlopt I get a NLOPT_ROUNDOFF_LIMITED error code.

Additional information

I search some information (in nlopt documentation) about the SLSQP optimizer implementation and both scipy and nlopt version seem to be based on the same fortran code.

I'm using a C# wrapper in my code (see issue BrannonKing/NLoptNet#16) but the same issue is raised with C++ version (see below).

Maybe related with #350

Minimal working code

#include <stdio.h>
#include <math.h>
#include <vector>

#include "nlopt.hpp"


int count = 0;

double myfunc(unsigned n, const double* variables, double* gradient, void* my_func_data)
{
    const float h = 0.001;
    auto f0 = pow(variables[1] * variables[0], 2);
    auto fi0 = pow(variables[1] * (variables[0] + h), 2);
    auto fi1 = pow((variables[1] + h) * variables[0], 2);
    if (gradient)
    {
        gradient[0] = (fi0 - f0) / h;
        gradient[1] = (fi1 - f0) / h;

        printf("> Iteration #%d: x = [%f, %f], gradient = [%f, %f]\n", count, variables[0], variables[1], gradient[0], gradient[1]);
    }
    count++;

    return f0;
}

double EqConstraint(unsigned int n, const double* variables, double* gradient, void* data)
{
    return 0;
}
double IEqConstraint(unsigned int n, const double* variables, double* gradient, void* data)
{
    return 0;
}


int main()
{
    nlopt::opt opt(nlopt::LD_SLSQP, 2);
    opt.set_maxeval(20);
    opt.set_xtol_rel(1e-4);
    opt.set_min_objective(myfunc, NULL);

    std::vector<double> lower_bounds(2);
    lower_bounds[0] = 1.0;
    lower_bounds[1] = 1.0;
    opt.set_lower_bounds(lower_bounds);

    std::vector<double> upper_bounds(2);
    upper_bounds[0] = 10.0;
    upper_bounds[1] = 10.0;
    opt.set_upper_bounds(upper_bounds);

    // Constraints
    double zero = 0.0;

    // @BUG Adding equality constraint breaks the code 
    opt.add_equality_constraint(EqConstraint, &zero, 0.001);
    // @BUG Adding equality constraint breaks the code 

    // Adding inequality constraint works
    opt.add_inequality_constraint(IEqConstraint, &zero, 0.001);
    
    try
    {
        // Let's go !
        double minf;
        std::vector<double> initialValues(2);
        initialValues[0] = 1.234; initialValues[1] = 5.678;

        auto result = opt.optimize(initialValues, minf);
    }
    catch (const std::exception&)
    {

    }
    
    printf("result: %d\n", opt.last_optimize_result());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant