Skip to content
/ ifopt Public
forked from ethz-adrl/ifopt

An Eigen-based, light-weight C++ Interface to Nonlinear Programming Solvers (Ipopt, Snopt)

License

Notifications You must be signed in to change notification settings

ivatavuk/ifopt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

70 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status DOI

Ifopt is a unified Eigen-based interface to use Nonlinear Programming solvers, such as Ipopt and Snopt. The user defines the solver independent optimization problem by set of C++ classes resembling variables, cost and constraints. Subsequently, the problem can then be solved with either solver. This package can be dropped in your catkin workspace.

Author/Maintainer Alexander W. Winkler

               


... also we only need 928 lines of code to allow the generation of (1) solver indenpendent problem formulations, (2) automatic ordering of independent variable and constraint sets in the overall problem, (3) Eigen sparse-matrix exploitation for fast performance, (4) constraint-jacobian and cost-gradient ordering and (5) implementation of interfaces to Ipopt and Snopt.

Why this matters

Installation

Building

Vanilla cmake as

$ git clone https://github.com/ethz-adrl/ifopt.git
$ cd ifopt
$ mkdir build
$ cd build
$ cmake ..
$ make 

or if you are using catkin, simply clone this repo into your catkin workspace

$ cd catkin_workspace/src
$ git clone https://github.com/ethz-adrl/ifopt.git
$ cd ..
$ catkin_make

Unit Tests

Make sure everything installed correctly by running the unit tests through

$ make test

This should solve the example problem with your installed solver. Assume you have IPOPT installed, you can also run this manually by running the executable

$ ./ifopt/test/ipopt_test

of if you are using catkin or

$ cd catkin_workspace
$ catkin_make run_tests
$ (catkin build ifopt --no-deps --verbose --catkin-make-args run_tests)

Usage

See test/ex_problem.h for detailed comments and explanation of the below code line by line. The optimization problem to solve is defined as:

#include <ifopt/test/ex_problem.h>
#include <ifopt/solvers/ipopt_adapter.h>

int main() 
{
  Problem nlp;

  nlp.AddVariableSet  (std::make_shared<ExVariables>());
  nlp.AddConstraintSet(std::make_shared<ExConstraint>());
  nlp.AddCostSet      (std::make_shared<ExCost>());
  
  IpoptAdapter::Solve(nlp); // or SnoptAdapter::Solve(nlp);
  std::cout << nlp.GetOptVariables()->GetValues();
}

Output:

1.0 0.0

The 3 classes representing variables, costs and constraints are defined as in the following. The variables x0 and x1 with their bound -1 <= x0 <= 1 is formulated as follows:

class ExVariables : public VariableSet {
public:
  ExVariables() : VariableSet(2, "var_set1")
  { // initial values
    x0_ = 0.5;
    x1_ = 1.5;
  }

  virtual void SetVariables(const VectorXd& x)
  {
    x0_ = x(0);
    x1_ = x(1);
  };

  virtual VectorXd GetValues() const
  {
    return Vector2d(x0_, x1_);
  };

  VecBound GetBounds() const override
  {
    VecBound bounds(GetRows());
    bounds.at(0) = Bounds(-1.0, 1.0);
    bounds.at(1) = NoBound;
    return bounds;
  }

private:
  double x0_, x1_;
};

The example constraint 0 = x0^2 + x1 - 1 is formulated as follows:

class ExConstraint : public ConstraintSet {
public:
  ExConstraint() : ConstraintSet(1, "constraint1") {}

  virtual VectorXd GetValues() const override
  {
    VectorXd g(GetRows());
    Vector2d x = GetVariables()->GetComponent("var_set1")->GetValues();
    g(0) = std::pow(x(0),2) + x(1);
    return g;
  };

  VecBound GetBounds() const override
  {
    VecBound b(GetRows());
    b.at(0) = Bounds(1.0, 1.0);
    return b;
  }

  void FillJacobianBlock (std::string var_set, Jacobian& jac) const override
  {
    if (var_set == "var_set1") {
      Vector2d x = GetVariables()->GetComponent("var_set1")->GetValues();
      
      jac.coeffRef(0, 0) = 2.0*x(0); // derivative of first constraint w.r.t x0
      jac.coeffRef(0, 1) = 1.0;      // derivative of first constraint w.r.t x1
    }
  }
};

The example cost f(x) = -(x1-2)^2 is formulated as follows:

class ExCost: public CostTerm {
public:
  ExCost() : CostTerm("cost_term1") {}

  virtual double GetCost() const override
  {
    Vector2d x = GetVariables()->GetComponent("var_set1")->GetValues();
    return -std::pow(x(1)-2,2);
  };

  void FillJacobianBlock (std::string var_set, Jacobian& jac) const override
  {
    if (var_set == "var_set1") {
      Vector2d x = GetVariables()->GetComponent("var_set1")->GetValues();

      jac.coeffRef(0, 0) = 0.0;             // derivative of cost w.r.t x0
      jac.coeffRef(0, 1) = -2.0*(x(1)-2.0); // derivative of cost w.r.t x1
    }
  }
};

Citation

If you use this work in an academic context, please cite the currently released version DOI as shown here.

Bugs & Feature Requests

Please report bugs and request features using the Issue Tracker.

About

An Eigen-based, light-weight C++ Interface to Nonlinear Programming Solvers (Ipopt, Snopt)

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C++ 76.4%
  • CMake 23.6%