Wednesday, October 28, 2009
In the late 90's, I implemented a tool for dose-response evaluation and simple optimization in the radiotherapy treatment planning system Helax-TMS. Due to recent interest, I have recorded a short introduction to this tool:
Tuesday, October 20, 2009
I have described how to access the large-scale nonlinear optimization package IPOPT in two recent posts (here and here). The basic C# interface uses pointers, and therefore some of the methods have to be declared as unsafe. Another issue is that the interface is procedural in nature (after all, it access the C interface implementation of IPOPT).
In this final post, I will outline my attempts to "hide" the unsafe methods from the public C# interface and at the same time making the interface more object-oriented, for example to implicitly free the allocated resources in the IPOPT library when the optimization problem is completed.
The further developed C# interface can be found here. The implementation still contains privately declared unsafe code, so the code has to be compiled with the /unsafe flag enabled. However, if the code is included in a separate assembly, it should be possible to access the IPOPT C# interface from another assembly without having to enable the /unsafe flag.
To begin with, I need "safe" delegates representing the callback functions for objective, gradient, constraints evaluation etc. One example is given by the constraints evaluation delegate:
public delegate bool EvaluateConstraintsDelegate(int n, double x, bool new_x, int m, double g);
This is similar to the original Eval_G_CB delegate (which has now been declared private, in the spirit of hiding the unsafe code):
unsafe private delegate int Eval_G_CB(int n, double* x, int new_x, int m, double* g, void* user_data);
The return value and the new_x variable are in practice Boolean, therefore they are declared as such in the "safe" delegate. The pointers into arrays, x and g, are in the "safe" delegate declared as arrays. Finally, user_data is considered redundant in the "safe" delegate, since the state of the optimization problem can suitably be represented within a class that holds implementations of the objective, constraints, gradient functions etc. in C#.
I never managed to finish this post in conjunction with the other two posts.
Tuesday, October 13, 2009
In a recent post, I outlined my plans for creating a simple C# interface to the large-scale non-linear optimization package IPOPT. Since IPOPT is developed in unmanaged C++, I identified the need to create a dynamically linked IPOPT library that could be called from C# (or other .NET languages) via P/Invoke. Finally, I described a few simple steps to build the IPOPT DLL using MinGW in MSys.
In this post, I will describe how to access the C interface functions of the IPOPT library from C# using unsafe code.
The C interface to IPOPT is declared in the IpStdCInterface.h header file and can be viewed here.
The arguments in the C interface functions are all primitive types or pointers to primitive types, except for a pointer to an internal structure holding the IPOPT problem C++ object and associated data for simplified access from within the C interface implementation. The use of primitive types makes the access from C# relatively straightforward.
For example, the IpoptSolve function in the C interface has the following signature:
enum ApplicationReturnStatus IpoptSolve(struct IpoptProblemInfo* ipopt_problem, double* x, double* g, double* obj_val, double* mult_g, double* mult_x_L, double* mult_x_U, void* user_data);
In the C# interface, I translate this to:
unsafe public static extern int IpoptSolve(IntPtr ipopt_problem, double* x, double* g, double* obj_val, double* mult_g, double* mult_x_L, double* mult_x_U, void* user_data);
Thus, very small differences between the C and the C# signature; the enum in C is represented with an int in C#, and the pointer to the IpoptProblemInfo struct is represented with an IntPtr. (I have not tested it, but void* would probably work just as well as IntPtr in this context.) Otherwise, argument types are the same in both languages.
The DllImport attribute and the extern keyword in the C# declaration are required to indicate that the implementation of the IpoptSolve method is available in the unmanaged csipopt.dll library.
Here is another example:
int AddIpoptIntOption(struct IpoptProblemInfo* ipopt_problem, char* keyword, int val);
public static extern int AddIpoptIntOption(IntPtr ipopt_problem, string keyword, int val);
Again, fairly straightforward. Conveniently, it is possible to represent the C char* argument with a C# string. The return value of the C function is actually limited to 1 (TRUE) and 0 (false). Since it is in practice declared as an int (due to the lack of a boolean type in C), I have maintained the int type in the C# "translation" as well.
The functions in the C interface are overall easy to "translate" into C#. The only function that became some sort of a challenge was the CreateIpoptProblem function:
struct IpoptProblemInfo* CreateIpoptProblem(int n, double* x_L, double* x_U, int m, double* g_L, double* g_U, int nele_jac, int nele_hess, int index_style, Eval_F_CB eval_f, Eval_G_CB eval_g, Eval_Grad_F_CB eval_grad_f, Eval_Jac_G_CB eval_jac_g, Eval_H_CB eval_h);
where Eval_F_CB etc. are typedef:s for the callback functions that are used to calculate the objective and constraints functions, the objective function gradient, the Jacobian and potentially the Hessian of the Lagrangian function.
The main challenge is to declare the callback function signatures in C#. In C(++), Eval_F_CB is declared as follows:
typedef int (*Eval_F_CB)(int n, double* x, int new_x, double* obj_value, void* user_data);
In C#, the callback function will be declared as a delegate. When called from the C/C++ based library under Windows, this callback function will by default assume cdecl calling convention. On the other hand, C# uses the stdcall calling convention by default, so it becomes necessary to explicitly indicate to the C# compiler that the callback function will be called using the cdecl convention:
unsafe public delegate int Eval_F_CB(int n, double* x, int new_x, double* obj_value, void* user_data);
(Note! UnmanagedFunctionPointerAttribute was introduced in .NET Framework 2.0. The above C# code will not work under earlier versions of .NET.)
And that is basically it. Provided that the other callback functions are declared in a similar fashion, the C# declaration of the CreateIpoptProblem function can now be written as follows:
unsafe public static extern IntPtr CreateIpoptProblem(int n, double* x_L, double* x_U, int m, double* g_L, double* g_U, int nele_jac, int nele_hess, int index_style, Eval_F_CB eval_f, Eval_G_CB eval_g, Eval_Grad_F_CB eval_grad_f, Eval_Jac_G_CB eval_jac_g, Eval_H_CB eval_h);
The complete C# interface to IPOPT via the C functions can be found here.
So with the approach described above, it is thus relatively easy to access IPOPT provided that so-called unsafe C# code is used. In a subsequent post, I will describe my attempts to "hide" the unsafe code, making the public C# interface "safe" and "re-objectified".
Monday, October 12, 2009
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:
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.
Sunday, October 4, 2009
I have used Zedgraph to display two-dimensional graphs in my .NET developed software. I have been pretty pleased with Zedgraph, the API has been easy to use and the library has been powerful enough for my needs. Zedgraph is licensed under LGPL, which I also appreciate. My main concern has been problems with drawing dash-dotted lines; in the default zoom view the dashes and dots have hardly been visible.
The last two years, not much has happened with Zedgraph though. It is therefore interesting to note that there now seems to be a Microsoft alternative, Microsoft Chart Controls for the .NET Framework. At first glance the Chart Controls library appears very comprehensive. I will investigate whether it is also as easy to use as Zedgraph.