How to use ensmallen constrained functions

Viewed 48

I need optimize a constrained function using ensmallen but I dont understand the usage as the documentation does not tell me that much. I tried to build a minimal working example.

In my example I try to solve the function f(x) = x². My constraint is x = 3. So I would assume using the solver with an initial x=-1, it would finish with x=3.

But the problem is: My x is not changing. I would really appreciate some help.

I do not see where I did a mistake https://ensmallen.org/docs.html#constrained-functions

#include <iostream>
#include "ensmallen.hpp"

using namespace ens;

class ConstrainedFunctionType
{
public:
    // f(x) = x * x
    double Evaluate(const arma::mat& x){
        return x(0,0) * x(0,0);
    }

    // f'(x) = 2x
    void Gradient(const arma::mat& x, arma::mat& g){
        g(0,0) = 2*x(0,0);
    }

    // 1 Constraint, x = 3
    size_t NumConstraints(){
        return 1;
    }
    
    // Return distance from x to 3
    double EvaluateConstraint(const size_t i, const arma::mat& x){
        if(x(0,0) < 3){
            return 3 - x(0,0);
        }
        else if(x(0,0) > 3){
            return x(0,0) - 3;
        }
        return 0;
    }

    // If x was too small, gradient = 1 so it increases
    // If x was too big, gradient =-1 so it decreases
    void GradientConstraint(const size_t i, const arma::mat& x, arma::mat& g){
        g.reshape(1,1);
        if(x(0,0) < 3){
            g(0,0) = 1;
        }
        else if (x(0,0) > 3){
            g(0,0) = -1;
        }
    }
};



int main() {
    ConstrainedFunctionType f;
    arma::mat x (1,1);
    x(0,0) = -1;
    arma::cout << "init = " << x << arma::endl;

    AugLagrangian optimizer;
    optimizer.Optimize(f, x);
    arma::cout << "result = " << x << arma::endl;
    return 0;
}

1 Answers

Found the solution:

The documentation says

If the constraint is not satisfied, the gradient should be set in such a way that the gradient points in the direction where the constraint would be satisfied

but it needs to point the other direction. Meaning in my example, if x>3 the gradient should be 1 and if x<3 the gradient should be -1

Related