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

38 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status

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 also be dropped in your catkin workspace.

Author/Maintainer: Alexander W. Winkler

       

The code is currently maintained at the Robotic Systems Lab.


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

  • Install Eigen

    $ sudo apt-get install libeigen3-dev
    
  • Depending on which solver you want to use, install either Ipopt or Snopt. Follow the instructions provided here:

  • In order for ifopt to know for which solvers to build the code, set the environmental variable pointing to the libraries and headers of the solver. If you have IPOPT 3.12.8 installed, add export IPOPT_DIR=/home/path/to/ipopt/Ipopt-3.12.8 to your ~/.bashrc and re-source. Alternatively you can also supply the location of the shared libraries and header files directly in the CMakeLists.txt.

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. You can also execute these manually by running e.g.

$ ./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:

0 1

The 3 classes representing variables, costs and constraints are defined as follows:

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

  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) = NoBound;
    bounds.at(1) = Bounds(-1.0, 1.0);
    return bounds;
  }

private:
  double x0_, x1_;
};
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, +inf); // between 1 and inifinity
    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
    }
  }
};
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
    }
  }
};

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%