Hi ! Following my previous mail, I did a preliminary Python interface to M.J.D. Powell COBYLA optimization package. I translated the Fortran package to C via f2c, did a few adjustments, and added a Python interface so it could be easily integrated into SciPy. As stated in a previous mail, M.J.D. Powell agreed for the inclusion of COBYLA in SciPy. (Many thanks to him !) COBYLA stands for Constrained Optimization BY Linear Approximation. Two things make COBYLA an interessting algorithm to have in SciPy: - It's derivative free (like Nelder-Mead) ; - It can take non-linear constraints. It has some drawbacks: - It won't probably work if there are too many variables (say > 10) ; - The constraint are not exactly enforced during the minimization ; - It may be quite slow, most notably if there are no constraints. In the last case, a higher performance unconstrained derivative free method like Powell's UOBYQA or NEWUOA should probably be used. (Conn-Scheinberg-Toint DFO is anoter option) I've attached the preliminary Python interface. Suggestions are welcome! Regards, js
On Tue, 13 Apr 2004, Jean-Sebastien Roy wrote:
Hi !
Following my previous mail, I did a preliminary Python interface to M.J.D. Powell COBYLA optimization package.
I translated the Fortran package to C via f2c, did a few adjustments, and added a Python interface so it could be easily integrated into SciPy. As stated in a previous mail, M.J.D. Powell agreed for the inclusion of COBYLA in SciPy. (Many thanks to him !)
Great! Thank you for making it possible to include COBYLA to Scipy!
I've attached the preliminary Python interface. Suggestions are welcome!
I have one suggestion: use F2PY to generate Python interfaces to Fortran programs. There are several advantages for doing so. For example, the interface is more efficient and less errorprone and easier to maintain than handwritten wrappers. Let me know if you have any troubles using F2PY. Thanks, Pearu
Pearu Peterson wrote:
I have one suggestion: use F2PY to generate Python interfaces to Fortran programs. There are several advantages for doing so. For example, the interface is more efficient and less errorprone and easier to maintain than handwritten wrappers. Let me know if you have any troubles using F2PY.
You're absolutely right. I should have used F2PY. In fact, I tried F2PY first but encountered a few problems. The most basic one was that F2PY didn't work right on my machine (A FreeBSD 4.9 box. The F2PY port didn't recognize any F77 compiler. It's probably specific to my machine). The other problem was that COBYLA expect the function to be minimized to be a Fortran function called CALCFC. Therefore, reentrancy was not easy to achieve without some modifications to the original code (passing a callback at least). So in the end, I ran f2c, modified the code and wrote my own wrapper. A nice side effect is I can now use COBYLA in some of my C programs easily. But I agree it's clearly not the best solution for SciPy. I'll try harder to use F2PY next time (probably for Powell's NEWUOA). In the mean time, feel free to replace my wrapper by a F2PY wrapper to the original Fortran COBYLA2 code: I would be myself very interessted in such wrapper as an example ! Regards, js
Jean, Travis, On Tue, 13 Apr 2004, Jean-Sebastien Roy wrote:
You're absolutely right. I should have used F2PY.
In fact, I tried F2PY first but encountered a few problems. The most basic one was that F2PY didn't work right on my machine (A FreeBSD 4.9 box. The F2PY port didn't recognize any F77 compiler. It's probably specific to my machine).
Please, let us know what are these problems with FreeBSD. I am sure there is a easy fix.
In the mean time, feel free to replace my wrapper by a F2PY wrapper to the original Fortran COBYLA2 code: I would be myself very interessted in such wrapper as an example !
The example wrapper to Fortran COBYLA2 code is attached (feel free to suggest changes to the interface). Below follow basic steps how I created this wrapper, the steps are quite typical when creating a new scipy module (for more info, see http://testing.scipy.org/development/developscipy): 1) Modified cobyla2.f: added calcfc as an argument 2) Generated initial .pyf file: f2py cobyla2.f -m _cobyla -h _cobyla.pyf only: cobyla calcfc 3) Modified _cobyla.pyf so that f2py generates a wrapper having the following signature: x = minimize(calcfc,m,x,rhobeg,rhoend, [iprint,maxfun,calcfc_extra_args]) where call-back function calcfc is expected to have the following signature: def calcfc(x,con): # calculate scalar f=f(x) # calculate m-vector con(x) in-place return f 4) Created setup.py file 5) Created tests/test_cobyla.py 6) Build cobyla module: python setup.py build 7) Run tests: $ python tests/test_cobyla.py Found 1 tests for __main__ Result: [-4.80580817 1.44539502] (exact result = -4.898979456, 1) . ---------------------------------------------------------------------- Ran 1 test in 0.004s OK $ 8) Created tar-ball that is attached: python setup.py sdist Bugs: when setting maxfun value higher than 10, the fortran code seem end up into an infinite loop. Not sure what is going wrong. Note that by the end of this week (probably tomorrow) we have Scipy release 0.3 out and at the moment scipy CVS tree is in a freezed state because of that. I think we can add cobyla to Scipy 0.3.1 (the bug fix release) provided that the above bug gets resolved. Regards, Pearu
There were few typos in my previous message. On Thu, 15 Apr 2004, Pearu Peterson wrote:
2) Generated initial .pyf file:
f2py cobyla2.f -m _cobyla -h _cobyla.pyf only: cobyla calcfc
.. should read f2py cobyla2.f -m cobyla -h cobyla.pyf only: cobyla calcfc
3) Modified _cobyla.pyf so that f2py generates a wrapper.. ^^^^^^^^^^^ - should be cobyla.pyf
Pearu
Pearu Peterson wrote:
Please, let us know what are these problems with FreeBSD. I am sure there is a easy fix.
I had installed the version in the FreeBSD ports ("2.37.233.1545"). Running: python setup.py build_ext --inplace Returned: running build_ext error: Fortran compiler not available: None I have now installed the latest version (no port is available for it on FreeBSD), an it worked fine besides apparently harmful errors such as: Could not locate executable /usr/home/js/devel/optimisation/cobyla2_f/cobyla-0.1/g77 or: invalid command 'build_src' (no module named 'distutils.command.build_src') (on a side note, is it possible to get f2py messages in black instead of yellow (the color I'm seeing on my machine) which is very difficult to read on white background ?)
The example wrapper to Fortran COBYLA2 code is attached (feel free to suggest changes to the interface).
Many thanks ! It's obviously much simpler than writting a custom C wrapper. About changes to the interface, only a few things may be missing : maxfun is also a value to be returned (it's the number of iterations effectively done). Also, the reason for exiting COBYLA should be returned, as else optimization may fail without warning the caller (beside a printed message). This may require modifications to the Fortran source. Is it normal that the Fortran Wrapper does not complain when None is returned by the python function instead of a float ?
Bugs: when setting maxfun value higher than 10, the fortran code seem end up into an infinite loop. Not sure what is going wrong.
FWIW, I cannot reproduce this bug, neither in my nor in your wrapper, which seems to run fine on my machine. Nevertheless, when trying a nested optimization problem, I encountered an error I cannot explain. Please find below a simple example: import cobyla def f1(x, con): global a f = (x[0]-a)**2 return f def f2(x, con): global a a = x[0] z = cobyla.minimize(f1, m=0, x=[0], iprint = 1,rhobeg=0.5,rhoend=1e-6,maxfun=100) f = z[0]**2+abs(x[1])**3 return f print cobyla.minimize(f2, m=0, x=[1,1], iprint = 1,rhobeg=0.5,rhoend=1e-4,maxfun=1000) Returns: Normal return from subroutine COBYLA NFVALS = 23 F = 1.000000E-12 MAXCV = 0.000000E+00 X = 1.000001E+00 capi_return is NULL Call-back cb_calcfc_in_cobyla__user__routines failed. Traceback (most recent call last): File "tst5.py", line 18, in ? print cobyla.minimize(f2, m=0, x=[1,1], iprint = 1,rhobeg=0.5,rhoend=1e-4,maxfun=1000) File "tst5.py", line 10, in f2 z = cobyla.minimize(f1, m=0, x=[0], iprint = 1,rhobeg=0.5,rhoend=1e-6,maxfun=100) TypeError: minimize argument calcfc must be callable This doesn't seem to happen with the C wrapper. Regards, js
Pearu Peterson wrote:
On Tue, 13 Apr 2004, Jean-Sebastien Roy wrote:
Hi !
Following my previous mail, I did a preliminary Python interface to M.J.D. Powell COBYLA optimization package.
I translated the Fortran package to C via f2c, did a few adjustments, and added a Python interface so it could be easily integrated into SciPy. As stated in a previous mail, M.J.D. Powell agreed for the inclusion of COBYLA in SciPy. (Many thanks to him !)
Many thanks are owed to Jean-Sebastien for his assistance in this area. I would like to echo, however, Pearu's suggestion that there is no need to convert working Fortran code to C for inclusion into scipy. f2py actually makes the process of integrating fortran code into SciPy easier than integrating C code. So, unless there is an important reason to convert to C (dynamic memory allocation for example), I would think it is better to keep Fortran code in Fortran when possible. Thanks again, Jean, -Travis
participants (3)
-
Jean-Sebastien Roy -
Pearu Peterson -
Travis Oliphant