Jens-Dominik Mueller wrote:
The debugger (gdb) seems to indicate that the args passed into
nlopt_minimize_constrained are indeed the same for C and f90, bar for
fc_datum_size which it finds 8, but should be 16. This seems to stem
from line 60 in F77, where sizeof(f77_func_data) is passed as the datum
difference, while we should see sth evaluating to fc_second_datum -
fc_data.
Hmm, the code looks correct as-is to me: the point is that the internal
f77_func_data structure contains within it the pointers to the Fortran
data with the correct (fc_second_datum - fc_data) offsets.
I just tried it in Fortran 77 (attached below, compiled with gfortran)
and passing multiple constraints with data in Fortran seems to work fine.
However, this does not seem to be the issue, as my func and constr
routines are never called. Unfortunately, the gdb debugger seems
confused about the mixed languages and does not allow me to trace the
f90 version into the case statement in nlopt_minimize_.
Mixed-language gdb works fine for me. Be sure you compile NLopt with
the debugging flags (configure --enable-debug).
Anyway, it looks like you have several bugs in your code:
1) You initialize lb, but not ub. (By the way, is HUGE_VAL defined in
Fortran? I thought that was only a C constant.) This is probably
causing your infinite result, because nlopt exits with an error code and
minf==infinity if lb > ub.
2) In constr, you initialize a and b only when need_gradient is 1, which
will cause a problem if nlopt ever tries to evaluate it without a gradient.
3) your write statements have incorrect formats, which causes gfortran
to give a runtime error.
4) Note also that your write statements refer to grad(1) and grad(2)
even if need_gradient is 0 -- in this case, grad is a NULL pointer and
it will crash.
5) You set the lower bound for x(2) as lb(2) = 0. This causes a problem
with a gradient-based algorithm like MMA because your derivative of
sqrt(x(2)) is not defined there, and you get NaN (It is fine for a
nonderivative algorithm like COBYLA).
With gfortran, I also noticed that it had trouble with:
real(8), dimension(:), intent(in) :: fc_datum
In particular, gfortran seems to expect dimension(:) arrays to be passed
as a pointer to some kind of gfortran data structure(?), not an array,
and it crashes. Changing it to:
real(8), dimension(2), intent(in) :: fc_datum
fixed the problem.
Steven
--------------
subroutine f(val, n, x, grad, need_gradient, f_data)
double precision val, f_data
integer n
double precision x(n)
double precision grad(n)
integer need_gradient
val = dsqrt(x(1))
if (need_gradient .ne. 0) then
grad(1) = 0.5 / val
endif
write(*,*) 'val = ', val
end
subroutine fc(val,n, x, grad, need_gradient, offset)
double precision val, offset
integer n
double precision x(n)
double precision grad(n)
val = (offset - x(1))**3.
if (need_gradient .ne. 0) then
grad(1) = -3. * (offset - x(1))**2.
endif
end
program test
include 'nlopt.f'
integer info, algorithm
double precision x, minf
double precision lb, ub, ftol_rel, ftol_abs, xtol_rel, xtol_abs
double precision maxtime
double precision offset(2)
external f, fc
offset(1) = 1.1D0
offset(2) = 1.2D0
algorithm = NLOPT_LN_COBYLA
lb = 0.0D0
ub = 10.0D0
x = 0.1D0
ftol_rel = 0.0
ftol_abs = 0.0
xtol_rel = 0.0
xtol_abs = 0.0
maxtime = 0.0
call nloptc(info, algorithm, 1,
c f, 0.0D0,
c 2, fc, offset(1), offset(2),
c lb, ub, x, minf,
c dsqrt(1.2D0)+1D-6, ftol_rel, ftol_abs,
c xtol_rel, xtol_abs, 0,
c 10000, maxtime)
write(*,*) 'returned ',info
write(*,*) 'f(',x,') = ', minf, ' vs. ',dsqrt(1.2D0)
end
_______________________________________________
NLopt-discuss mailing list
[email protected]
http://ab-initio.mit.edu/cgi-bin/mailman/listinfo/nlopt-discuss