Алгоритм NLOPT STOGO в Фортране никогда не останавливается и не возвращает неправильное значение

Я пытаюсь использовать алгоритм STOGO из NLOPT в Фортране. Алгоритм никогда не останавливается. Если я задаю значение для maxeval, алгоритм всегда останавливается после максимального количества оценок и возвращает значение 1 (общее возвращаемое значение успеха), тогда как я ожидаю, что оно будет равно 5 (оптимизация остановлена, поскольку достигнут maxeval). Добавление критериев остановки, таких как $ftol_rel$ или $ftol_abs$ не имеет никакого эффекта. Ниже приведен минимальный код, который я использую. Любая подсказка о том, что я должен делать? Спасибо!

В модуле для подсчета количества оценок функции:

module myparams
 integer :: counter = 0  ! counts the number of calls
end module myparams

В основной программе

program main
 use myparams
 implicit none
 external myfunc
 integer, parameter  :: dim = 2      ! dimension of the problem
 double precision lb(dim), ub(dim)   ! lower and upper bounds of the domain
 integer*8 opt
 double precision x(dim), minf
 integer ires
 integer idim

 include 'nlopt.f'

 !defines bounds
 do idim = 1,dim
  lb(idim) = -10.0
  ub(idim) = 10.0
 enddo            

 ! initial guess point
 x(1) = 1.234
 x(2) = 5.678

 call nlo_create(opt, NLOPT_GD_STOGO, dim)

 ! set lower and upper bounds
 call nlo_set_lower_bounds(ires, opt, lb) 
 call nlo_set_upper_bounds(ires, opt, ub) 

 !defines the tolerance (stopping criteria)
 call nlo_set_ftol_rel(ires, opt, 1.D-15)  
 call nlo_set_maxeval(ires, opt, 600000)   ! the counter always reaches maxeval. but the return value (ires) is 1 = generic success.

 call nlo_set_stopval(ires, opt, 1.01)

 ! initialize counter of number of calls to the function during search
 counter = 0

 call nlo_set_min_objective(ires, opt, myfunc, 0)
 call nlo_optimize(ires, opt, x, minf)

 if (ires.lt.0) then
  write(*,*) 'nlopt failed! error code: ', ires
 else
  write(*,*) 'found min at ', x
  write(*,*) 'min val = ', minf
  write(*,*) 'found after ', counter, 'iterations'
  write(*,*) 'ires code: ', ires,  '     (1 means generic success)'
  write(*,*)
 endif

 call nlo_destroy(opt)
end program main

subroutine myfunc(val, n, x, grad, need_gradient)        
 use myparams, only: counter
 double precision val, x(n), grad(n)
 integer n, need_gradient
 counter = counter + 1

 val = (x(1) - 1.0)**2.0 + (x(2)-2.0)**2.0 + 1.0D0

 if (need_gradient.ne.0) then
  grad(1) = 2.0*(x(1) - 1.0)
  grad(2) = 2.0*(x(2) - 2.0)
 endif
end subroutine myfunc

0 ответов

Другие вопросы по тегам