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

Reply via email to