Алгоритм 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