Saturday, July 3, 2010

Rev. Jul 15: Another optimization library with Python interface: NLopt, installation problem



NLopt is a free/open-source library for nonlinear optimization, providing a common interface for a number of different free optimization routines available online as well as original implementations of various other algorithms. Its features include (from the home page of NLopt):

  • Callable from C, C++, Fortran, GNU Octave, Matlab, Python, and GNU Guile.
  • A common interface for many different algorithms—try a different algorithm just by changing one parameter.
  • Support for large-scale optimization (some algorithms scalable to millions of parameters and thousands of constraints).
  • Both global and local optimization algorithms.
  • Algorithms using function values only (derivative-free) and also algorithms exploiting user-supplied gradients.
  • Algorithms for unconstrained optimization, bound-constrained optimization, and general nonlinear inequality/equality constraints.
  • Free/open-source software under the GNU LGPL (and looser licenses for some portions of NLopt).
The homepage of NLopt is at NLopt homepage and the web site is fairly complete with FAQ, Download, Manual, Tutorial, Reference , Algorithms, License and copyright pages. Instructions for installation.
  1. Download the installer file

    wget -ct 0 http://ab-initio.mit.edu/nlopt/nlopt-2.0.2.tar.gz

  2. Unpack the nlopt-2.0.2.tar.gz.

    tar xzvvf nlopt-2.0.2.tar.gz

  3. Cd to the nlopt directory.
    cd nlopt-2.0.2.

  4. Perform standard installation commands. Type ./configure -h for help.

    ./configure --enable-shared
    make;
    sudo make install


  5. Make links to the shared libraries.
    sudo ldconfig



Unfortunately in the last step, we encounter
/bin/bash ../libtool --tag=CXX   --mode=link g++  -g -O2 -module 
-no-undefined -version-info 3:2:3  -o _nlopt.la -rpath /usr/local/lib/python2.6/dist-packages _nlopt_la-nlopt-python.lo ../libnlopt.la -lm 
libtool: link: g++ -shared -nostdlib /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.4.3/crtbeginS.o  .libs/_nlopt_la-nlopt-python.o   ../.libs/libnlopt.a -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../.. -L/usr/lib/x86_64-linux-gnu -lstdc++ -lm -lc -lgcc_s /usr/lib/gcc/x86_64-linux-gnu/4.4.3/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/4.4.3/../../../../lib/crtn.o    -Wl,-soname -Wl,_nlopt.so.0 -o .libs/_nlopt.so.0.3.2
/usr/bin/ld: ../.libs/libnlopt.a(general.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
../.libs/libnlopt.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
make[2]: *** [_nlopt.la] Error 1
make[2]: Leaving directory `/home/toto/Downloads/nlopt-2.0.2/swig'
make[1]: *** [install] Error 2
make[1]: Leaving directory `/home/toto/Downloads/nlopt-2.0.2/swig'
make: *** [install-recursive] Error 1
The error message says we have to recompile with -fPIC flag. A show stopper! Have to review how to insert the compiler flag in the configure file. Will be back this week. Interfacing with Python requires that Numpy is installed. Nevertheless, a Python example is


import nlopt
from numpy import *

def myfunc(x, grad):
    if grad.size > 0:
        grad[0] = 0.0
        grad[1] = 0.5 / sqrt(x[1])
    return sqrt(x[1])

def myconstraint(x, grad, a, b):
    if grad.size > 0:
        grad[0] = 3 * a * (a*x[0] + b)**2
        grad[1] = -1.0
    return (a*x[0] + b)**3 - x[1]

opt = nlopt.opt(nlopt.LD_MMA, 2)
opt.set_lower_bounds([-float('inf'), 0])
opt.set_min_objective(myfunc)
opt.add_inequality_constraint(lambda x,grad: myconstraint(x,grad,2,0), 1e-8)
opt.add_inequality_constraint(lambda x,grad: myconstraint(x,grad,-1,1), 1e-8)
opt.set_xtol_rel(1e-4)

x = opt.optimize([1.234, 5.678])
minf = opt.last_optimum_value()
print "optimum at ", x[0],x[1]
print "minimum value = ", minf
print "result code = ", opt.last_optimize_result()


We would like to compare its performance with OpenOpt which was describe earlier in this blogs.

July 15


Cleaning up previous installation as per suggestion and running the example, we get


python example.py
optimum at 0.333333612374 0.296296070953
minimum value = 0.544330846961
result code = 4


We have to delve deeper into nlopt documentation to understand the various result codes.
We feel that optimization software with the best comprehensive documentation (no suprise principle)
will find wider use. We will try to play with nlopt in the coming days. Stay tuned.

Thanks to the comments from the head of the NLOPT development team.

4 comments:

  1. I haven't seen that error before; --enable-shared should automatically include the -fPIC flag (which is needed to compile shared libraries), and it works fine for me on my Debian box. Perhaps you accidentally have some environment variable (like CXXFLAGS) set to override the configure script?

    ReplyDelete
  2. (Or perhaps you have files left over from an earlier installation attempt without the --enable-shared? Be sure to run 'make distclean' between configure runs.)

    ReplyDelete
  3. Thanks a lot! Trying again with your suggestion for cleaning up,

    sudo make distclean
    ./configure --enable-shared
    make
    sudo make install

    and adding

    sudo ldconfig

    the code works!

    Thanks again.

    ReplyDelete
  4. See http://ab-initio.mit.edu/wiki/index.php/NLopt_Reference#Return_values for the meaning of the result codes (4 means that the xtol was reached, corresponding in Python to the symbolic constant nlopt.XTOL_REACHED). Thanks for pointing out that the tutorial is a little unclear about this; I've updated it to link to the relevant section of the manual.

    ReplyDelete