Java LP Solve
Java LP Solve
Calling lp_solve from Python/Jython 1. Introduction lp_solve is a free (see LGPL for the GNU lesser general public license) linear ( integer) programming solver based on the revised simplex method and the Branch-a nd-bound method for the integers. lp_solve has its own community via the Yahoo g roup http://groups.yahoo.com/group/lp_solve. There you can find the latest sourc es, executables for the common platforms, examples, manuals and a message board where people can share their thoughts on lp_solve. lp_solve is written in ANSI C and can be compiled on many different platforms li ke Linux and Windows. Basically, lp_solve is a library, a set of routines, that can be called easily from programming languages like C, C++, C# and VB. Unfortun ately, there is no simple and straightforward way to use native C libraries like lp_solve in Java programs. This library (also called "Java wrapper") is designe d to remedy this shortcoming. It consists of two main parts: A Java class library that is used by Java client programs. It gives access t o all lp_solve routines through the LpSolve class. A native library written in C++, also called 'stub' library, that uses the J NI (Java Native Interface) API to translate Java method calls into calls to the corresponding routines of the lp_solve library. Java client programs do not inte ract directly with the stub library. This library must be compiled for each targ et platform. Precompiled binaries are included for Windows and Linux operating s ystems. There is also a build script for compiling the stub library on Mac OS X. This document should help you getting started using the Java wrapper and lp_solv e in your Java programs. Read it in addition to the documentation that comes wit h lp_solve. Always refer to the lp_solve docs as ultimate reference for using th e routines of the optimization library. Bug reports, succes stories and requests for changes concerning the Java wrapper are welcome by email at juergen.ebert@w eb.de or in the lp_solve discussion group. The current wrapper version was written to work with lp_solve 5.5.0.9 and was te sted under Windows XP and Linux. As long as the API stays the same, other versio ns of lp_solve are likely to work as well. The wrapper requires a Java Runtime E nvironment 1.3 or later. The latest version of the Java wrapper can be found in the files section of the lp_solve group. The wrapper is released under the same LGPL license conditions a s lp_solve. A copy of the LGPL text is contained in the distribution archive. 2. Installation Copy the lp_solve dynamic libraries from the archives lp_solve_5.5_dev.(zip or tar.gz) and lp_solve_5.5_exe.(zip or tar.gz) to a standard library directory for your target platform. On Windows, a typical place would be \WINDOWS or \WIND OWS\SYSTEM32. On Linux, a typical place would be the directory /usr/local/lib. Unzip the Java wrapper distribution file to new directory of your choice. On Windows, copy the wrapper stub library lpsolve55j.dll to the directory th at already contains lpsolve55.dll. On Linux, copy the wrapper stub library liblpsolve55j.so to the directory th at already contains liblpsolve55.so. Run ldconfig to include the library in the shared libray cache.
3. Usage To create a Java application that uses lp_solve routines, you must perform the f ollowing steps: Make sure you have a Java Runtime Environment 1.3 or later installed. Install lp_solve and the Java wrapper as described above. Copy the archive file lpsolve55j.jar from the Java wrapper distribution to a directory that is included in the CLASSPATH of your java program. Add an import statement for the package lpsolve.* at the beginning of your s ource file. Call LpSolve.makeLp(...) or one of the other static factory methods of the L pSolve class to create a LpSolve instance. Each LpSolve instance represents an o ptimization problem. Call the methods of the LpSolve instance to define the problem and obtain th e solution. Use the examples and implementation notes later in this documentatio n for further information. When you run your Java file make sure to include lpsolve55j.jar in the CLASS PATH. Also, on Windows, if you installed the native stub library in a directory that is not included in the PATH variable, you have to define the Java system va riable java.library.path which must point to the installation directory. On Linu x, the equivalent of the Windows PATH variable is called LD_LIBRARY_PATH. A simple example The following program is a very simple example that shows how to program with lp _solve in Java. import lpsolve.*; public class Demo { public static void main(String[] args) { try { // Create a problem with 4 variables and 0 constraints LpSolve solver = LpSolve.makeLp(0, 4); // add constraints solver.strAddConstraint("3 2 2 1", LpSolve.LE, 4); solver.strAddConstraint("0 4 3 1", LpSolve.GE, 3); // set objective function solver.strSetObjFn("2 3 -2 3"); // solve the problem solver.solve(); // print solution System.out.println("Value of objective function: " + solver.getObjective() ); double[] var = solver.getPtrVariables(); for (int i = 0; i < var.length; i++) { System.out.println("Value of var[" + i + "] = " + var[i]); } // delete the problem and free memory solver.deleteLp(); } catch (LpSolveException e) {
e.printStackTrace(); } } } Using callbacks The following code fragment shows you how to use callbacks in Java. The example defines an anonymous inner class that implements the AbortListener interface whi ch is then passed to the putAbortfunc method. LpSolve solver = LpSolve.makeLp(0, 4); AbortListener abortfunc = new AbortListener() { public boolean abortfunc(LpSolve problem, Object handle) { System.out.println("Java abortfunc called, handle = " + handle); return false; } }; solver.putAbortfunc(abortfunc, new Integer(123)); Running the demo application Follow these steps to run the demo application, which is a port of the C demo pr ogram that comes with lp_solve to the Java language. You will need a Java Runtim e Environment (JRE) on your machine in order to run the demo. You can download t he latest JRE from http://java.sun.com Install lp_solve and the Java wrapper as described above. On Windows, go to the demo directory and start the batch script "run_demo.ba t". On Linux, go to the demo directory of the wrapper distribution and run "sh r un_demo". More example code In the demo directory you will find the file LpSolveTest.java which contains mor e than 100 JUnit test cases (see http://www.junit.org for details about this hig hly useful software) to strengthen the faith in the Java wrapper implementation. The test cases may also seve as examples of basic lp_solve usage in Java. You w ill need the library junit.jar in your CLASSPATH to run the test cases. junit.ja r is included in the lib directory of the Java wrapper. You can run the test cas es directly by starting the batch script "run_unittests.bat" on Windows or "sh r un_unittests" on Linux. 4. Implementation notes In general, the Java API tries to follow the original C/C++ API of lp_solve as closely as possible to make ist easier for programmers who have to write prog rams for lp_solve in multiple different programming languages. However, because of fundamental differences between the Java programming language and C/C++ this is not always strictly possible. For example, it is not possible in Java to pass simple datatypes by reference. Method names have been kept, but changed to Java convention, i.e. underscore s have been removed, the following character is capitalized. For example str_add _constraint becomes strAddConstraint in Java. The lprec* argument taken by almost all lp_solve API routines is hidden comp letely inside the LpSolve class. All methods that create new lprec structures we re made static methods of the LpSolve class. Return values denoting fatal internal errors have been changed to Java Excep tions. For example set_row_name returns FALSE if an error has occured. In Java,
setRowName is of type void and throws a LpSolveException. Routines that have arguments or return values of type unsigned char, but onl y allow for TRUE or FALSE as legal values have been changed to type boolean. Exa mple: set_debug(lprec *lp, unsigned char debug) is setDebug(boolean debug) in Ja va. Multiple problems may be solved concurrently by multiple threads, as long as a single LpSolve object, which represents a problem, is only used by one thread at a time. lp_solve does not require client programs to keep argument buffers allocated between calls to different library routines, because all input arguments are co pied to internal buffers. Thus, it is easy to avoid memory leaks in the stub lib rary. All objects returned by the Java wrapper routines are allocated by the JVM and are subject to the standard garbage collection process. The methods get_ptr_sensitivity_rhs, get_ptr_reduced_costs, get_ptr_sensitiv ity_obj, and get_ptr_sensitivity_objex are not implemented, because it is not po ssible in Java to pass pointers by reference to a method. Use the corresponding methods without the Ptr part in the method name instead, which require allocatio n of the resulting arrays by the caller. See the file reference.html for details on how the lp_solve API functions ar e mapped to the Java methods. 5. Building from source The Java wrapper archive contains precompiled binary libraries for Windows and L inux. If you just want to use the wrapper there should be no need to build the l ibs from the sources. But if you absolutely have to, follow the guidelines in th is chapter. On Windows OS The following prerequisites must be met in order to build the wrapper C library from source on Windows operating systems: Microsoft Visual C++ compiler (I used V 7, others might work) Visual Studio envirement variables must be set. Sun Java Development Kit 1.4.x installed and JAVA_HOME environment variable set lp_solve Windows development archive lp_solve_5.5_dev.zip unpacked Change to the lib/win32 directory and edit the file build.bat. Change the path t o the directory where you unpacked the lp_solve Windows archive. Run the script to build lpsolve55j.dll. On Linux The following prerequisites must be met in order to build the wrapper C library from source on Linux operating systems: gcc and g++ compiler installed (I used gcc Version 3.3.1) Sun Java Development Kit 1.4.x installed lp_solve Linux development archive lp_solve_5.5_dev.tar.gz unpacked Change to the lib/linux directory and edit the file build. Change the paths to t he directory where you unpacked the lp_solve linux archive and where the JDK is installed. Run sh build to build liblpsolve55j.so. On Mac OS X Change to the lib/mac directory and edit the file build_osx. Change the director y paths as indicated in the comments. Thanks to Sean P. Kane (spkane@genomatica. com) who provided this build script. 6. Calling lp_solve from Python/Jython Jython (http://www.jython.org) is a 100% Java implementation of the popular scri pting language Python. One of the most remarkable features of Jython is the seam
less interaction between Python and Java. Java programmers can add the Jython li braries to their system to allow end users to write scripts that add functionali ty to the application. On the other hand, Python/Jython programs can interact wi th Java packages or with running Java applications. lp_solve functions can be called via the Java wrapper from Python/Jython program s. See the file demo.py in the demo directory of the Java wrapper distribution f or an example program. To run this program, you must install lp_solve, the Java wrapper, and Jython. Don't forget to include lpsolve55j.jar in the Java CLASSPAT H when you run Jython.