Monday, October 12, 2009

A C# interface to IPOPT - Preparations

IPOPT is a powerful open-source optimization package for large-scale non-linear programming. It is developed in C++, and provides interfaces to for example C, Fortran, Java, Python and Matlab. Using the source-code tarball, it is also possible to build an executable for the AMPL modeling environment.

However, I have so far not been able to find a C# interface to IPOPT. Some people have implemented such an interface (here and here), but I have not been able to find the complete source code for these implementations.

Therefore, I have given it a try myself.

I have decided to implement the C# interface using the implementation of the C interface. For me, this has been a straightforward and relatively simple approach, although I realize that an immediate interface between C++ and C# would probably be more efficient.

First, I need to build a dynamically linked IPOPT library. I am using the MinGW/MSys environment to build IPOPT under Windows, although Cygwin would work just as fine. The IPOPT package does contain a Visual Studio solution for building IPOPT executables such as the AMPL solver or HS071 example, but the Visual Studio solution does not offer the same configurability as the primary Autoconf based build environment. Also, the Visual Studio solution requires an extra step of converting the Fortran files in the BLAS and LAPACK third-party packages to C, which I find inconvenient. To create an IPOPT DLL library using open-source components only, I use the MUMPS linear equation solver.

To begin with, I need to build and publish the IPOPT static library. I therefore perform the necessary ./configure, make and make install steps for IPOPT from the MinGW command-line interface.

When building dynamically linked libraries with MinGW or Cygwin, the default behavior seem to be to export all publicly accessible symbols in the DLL, unless there are explicit __declspec(dllexport) decorations in the header declarations. It is then very simple to create the IPOPT DLL from existing code. I have simply copied the Makefile from the HS071 C++ example (in the sub-directory Ipopt/examples/hs071_cpp of the IPOPT source tree) to a separate directory. In the copied Makefile I have modified the values of the following symbols:

EXE = csipopt.dll
OBJS = IpDummy.o
CXXLINKFLAGS = -shared

With these modifications, the Makefile builds a DLL called csipopt.dll. (If the dynamically linked library is built e.g. under Linux for access via Mono, the library should instead be named libcsipopt.so for maximum portability.)

To ensure that the IPOPT solver is included in the DLL, I create a dummy implementation file IpDummy.cpp that invokes one of the methods in the C interface:

#include "IpStdCInterface.h"
#include "stdlib.h"

void dummy()
{
CreateIpoptProblem(0, NULL, NULL, 0, NULL, NULL, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
}

To build, I simply enter make in the MinGW command-line interface. After successful building, my IPOPT DLL is created. This DLL is immediately accessible from for example .NET assemblies via P/Invoke.

Next, I need to define the C# interface to the various functions in IPOPT's C interface. This will be outlined in a subsequent post.

2 comments:

  1. Anders,

    It's a good post in understanding building the IPOPT dll and making it use in the advanced language like C#. But i am having few problems building DLL from the Visual Studio. I am able to successfully build the projects IpoptAmplSolver, libCoinBlas, libCoinHSL, libIpopt and libCoinLapack in the visual studio solution given. I have converted the fortran code to c and successfully built the solution. But i stuck there and couldn't build the DLL. Can you publish the steps or approach to build the DLL from Visual Studio IDE.

    Thanks

    ReplyDelete
  2. I am terribly sorry that I have not noticed your comment before, Ramnadh.
    If I am not mistaken, the IPOPT developers have recently published an updated solution for building IPOPT from Visual Studio. I have not tried it myself, though, so I cannot say for sure how it works together with C# code. Have you tried it?

    ReplyDelete