Skip to content
/ ifopt Public
forked from jwdinius/ifopt

Eigen-based Interface to Nonlinear Programming Solvers IPOPT and SNOPT

License

Notifications You must be signed in to change notification settings

zeta1999/ifopt

 
 

Repository files navigation

I created this fork because I wanted to learn more about CMake; particularly exporting/importing packages with different sets of dependencies. This repo was chosen because of its small number of source files, sufficient unit tests, and file structure with submodules. The submodules can be built together or separately. As a bonus, the ifopt_ipopt and ifopt_snopt submodules have third party dependencies to be built against.

The information below has been modified from the original repo to include build instructions for the reorganized pure CMake build support that I added.

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 981 lines of code (why this matters) to allow the generation of (1) solver independent 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.

Building

  • 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:

  • To build ifopt_snopt or ifopt_ipopt set the location of the shared libraries and header files directly in the CMakeLists.txt of the corresponding solver.

  • Navigate to desired directory and clone the repo there

    $ git clone https://github.com/jwdinius/ifopt.git
    
  • If you wish to build unit tests (recommended), create a third_party directory and clone googletest into it

    $ cd ifopt ; mkdir third_party ; cd third_party
    $ git clone https://github.com/google/googletest.git gtest
    
  • Configure the build (remove -DBUILD_TEST=True if you don't wish to build unit tests)

    $ cd .. ; mkdir build ; cd build ;
    $ cmake .. -DBUILD_TEST=True
    
  • Build with make

    $ make
    

Unit Tests

Make sure everything installed correctly by running the unit tests through

$ make test

This should also solve the example problem with your installed solvers. If you have IPOPT installed and linked correctly, this should also execute the binary ifopt_ipopt-test.

(Un)Install

You can install the build targets of this project to the CMake install location:

$ make install

You made need special privileges to install to this directory; in that case, prepend the command above with sudo. Similarly, you can uninstall/remove with

$ make uninstall

Again, you may need to use sudo.

Usage

For an example of how to use this to efficiently generate dynamic motions for legged robots, check-out towr. See test/ex_problem.h for a minimal example with 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_ipopt/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
    }
  }
};

Publications

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

Bugs & Feature Requests

Please report bugs and request features using the Issue Tracker.

About

Eigen-based Interface to Nonlinear Programming Solvers IPOPT and SNOPT

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C++ 90.8%
  • CMake 9.2%