LCOV - code coverage report
Current view: top level - num/test/src - test_simplex.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 84.9 % 199 169
Test Date: 2025-05-08 18:23:42 Functions: 90.9 % 22 20

            Line data    Source code
       1              : module test_simplex
       2              : 
       3              :    use num_def
       4              :    use num_lib
       5              :    use math_lib
       6              : 
       7              :    implicit none
       8              : 
       9              :    integer :: num_calls
      10              :    logical, parameter :: show_details = .false.
      11              : 
      12              : contains
      13              : 
      14            1 :    subroutine do_test_simplex
      15              :       !call test_FR2 ! okay -- escapes from local min
      16            1 :       call test_FR4  ! okay -- escapes from local min
      17              :       !call test_FR6 ! okay -- escapes from local min
      18            1 :       call test_ER  ! okay
      19            1 :       call test_WD  ! okay
      20            1 :       call test_BLE  ! okay
      21            1 :       call test_PS  ! okay
      22            1 :       call test_TR  ! okay
      23            1 :    end subroutine do_test_simplex
      24              : 
      25            6 :    subroutine test1_simplex( &
      26            6 :       n, x_first, x_lower, x_upper, simplex, &
      27              :       centroid_weight_power, enforce_bounds, &
      28              :       adaptive_random_search, fcn, str)
      29              :       integer, intent(in) :: n  ! number of dimensions
      30              :       real(dp), dimension(:) :: x_first, x_lower, x_upper
      31              :       real(dp) :: simplex(:, :), centroid_weight_power
      32              :       logical, intent(in) :: enforce_bounds, adaptive_random_search
      33              :       interface
      34              :          include 'num_simplex_fcn.dek'
      35              :       end interface
      36              :       character(len=*) :: str
      37              : 
      38           60 :       real(dp) :: f(n + 1), x_final(n), x_atol, x_rtol, f_final
      39              :       integer :: iter_max, fcn_calls_max
      40              :       integer :: lrpar, lipar
      41              :       logical :: start_from_given_simplex_and_f
      42            6 :       integer, pointer :: ipar(:) ! (lipar)
      43            6 :       real(dp), pointer :: rpar(:) ! (lrpar)
      44              :       integer :: num_iters, num_fcn_calls, &
      45              :                  num_fcn_calls_for_ars, num_accepted_for_ars, ierr
      46              :       integer :: seed
      47              :       real(dp) :: alpha, beta, gamma, delta
      48              : 
      49              :       include 'formats'
      50              : 
      51            6 :       write (*, *) 'testing NM_simplex with '//trim(str)
      52              : 
      53            6 :       num_calls = 0
      54            6 :       lrpar = 0; lipar = 0
      55            6 :       allocate (rpar(lrpar), ipar(lipar))
      56              : 
      57            6 :       x_atol = 1d-10
      58            6 :       x_rtol = 1d-10
      59              : 
      60            6 :       iter_max = 1000
      61            6 :       fcn_calls_max = iter_max*10
      62            6 :       seed = 1074698122
      63              : 
      64            6 :       start_from_given_simplex_and_f = .false.
      65              : 
      66            6 :       alpha = 1d0
      67            6 :       beta = 2d0
      68            6 :       gamma = 0.5d0
      69            6 :       delta = 0.5d0
      70              : 
      71              :       call NM_simplex( &
      72              :          n, x_lower, x_upper, x_first, x_final, f_final, &
      73              :          simplex, f, start_from_given_simplex_and_f, &
      74              :          fcn, x_atol, x_rtol, &
      75              :          iter_max, fcn_calls_max, &
      76              :          centroid_weight_power, enforce_bounds, &
      77              :          adaptive_random_search, seed, &
      78              :          alpha, beta, gamma, delta, &
      79              :          lrpar, rpar, lipar, ipar, &
      80              :          num_iters, num_fcn_calls, &
      81            6 :          num_fcn_calls_for_ars, num_accepted_for_ars, ierr)
      82              : 
      83            6 :       if (ierr /= 0) then
      84            0 :          write (*, *) 'failed in do_simplex'
      85              :       else
      86            6 :          if (f_final < 1d-10) then
      87            6 :             write (*, 1) 'found f_final < 1d-10'
      88              :          else
      89            0 :             write (*, 1) 'failed in do_simplex:  f_final too large', f_final
      90              :          end if
      91              :          if (show_details) then
      92              :             write (*, 1) 'f_final', f_final
      93              :             write (*, 1) 'x_final', x_final(1:n)
      94              :             write (*, 2) 'num_iters', num_iters
      95              :             write (*, 2) 'num_fcn_calls', num_fcn_calls
      96              :             if (num_fcn_calls_for_ars > 0) &
      97              :                write (*, 2) 'num_fcn_calls_for_ars', num_fcn_calls_for_ars
      98              :             if (num_accepted_for_ars > 0) &
      99              :                write (*, 2) 'num_accepted_for_ars', num_accepted_for_ars
     100              :          end if
     101              :       end if
     102            6 :       write (*, *)
     103              : 
     104            6 :       deallocate (rpar, ipar)
     105              : 
     106            6 :    end subroutine test1_simplex
     107              : 
     108            1 :    subroutine test_WD
     109              :       ! testing with 4 dimensional Wood function
     110              :       integer, parameter :: n = 4
     111           15 :       real(dp), dimension(n) :: x_first, x_lower, x_upper
     112           26 :       real(dp) :: simplex(n, n + 1), centroid_weight_power
     113              :       logical :: enforce_bounds, adaptive_random_search
     114              : 
     115            1 :       x_first(1:n) = [-3d0, -1d0, -3d0, -1d0]
     116            1 :       x_lower(1:n) = [-4d0, -2d0, -4d0, -2d0]
     117            1 :       x_upper(1:n) = [2d0, 2d0, 2d0, 2d0]
     118              : 
     119            1 :       enforce_bounds = .true.
     120            1 :       adaptive_random_search = .true.
     121            1 :       centroid_weight_power = 1d0
     122              : 
     123              :       call test1_simplex( &
     124              :          n, x_first, x_lower, x_upper, simplex, &
     125              :          centroid_weight_power, enforce_bounds, &
     126            1 :          adaptive_random_search, fcn_WD, 'WD')
     127              : 
     128            1 :    end subroutine test_WD
     129              : 
     130          766 :    real(dp) function fcn_WD(n, x, lrpar, rpar, lipar, ipar, op_code, ierr)
     131              :       use const_def, only: dp
     132              :       integer, intent(in) :: n
     133              :       real(dp), intent(in) :: x(:)  ! (n)
     134              :       integer, intent(in) :: lrpar, lipar
     135              :       integer, intent(inout), pointer :: ipar(:)  ! (lipar)
     136              :       real(dp), intent(inout), pointer :: rpar(:)  ! (lrpar)
     137              :       integer, intent(in) :: op_code
     138              :       integer, intent(out) :: ierr
     139          766 :       ierr = 0
     140          766 :       fcn_WD = WD(x)
     141          766 :    end function fcn_WD
     142              : 
     143          766 :    real(dp) function WD(x)  ! Wood function
     144              :       real(dp), intent(in) :: x(:)
     145              :       integer :: i, n
     146          766 :       n = size(x, dim=1)
     147          766 :       WD = 0
     148         1532 :       do i = 1, n/4
     149              :          WD = WD + &
     150            0 :               100d0*pow2(x(i + 1) - x(i)*x(i)) + pow2(1d0 - x(i)) + &
     151            0 :               90d0*pow2(x(i + 3) - x(i + 2)*x(i + 2)) + pow2(1d0 - x(i + 2)) + &
     152         1532 :               100d0*pow2(x(i + 1) + x(i + 3) - 2d0) + pow2(x(i + 1) - x(i + 3))/sqrt(10d0)
     153              :       end do
     154          766 :       num_calls = num_calls + 1
     155          766 :    end function WD
     156              : 
     157            1 :    subroutine test_ER
     158              :       ! testing with 4 dimensional extended Rosenbrock
     159              :       integer, parameter :: n = 4
     160           15 :       real(dp), dimension(n) :: x_first, x_lower, x_upper
     161           26 :       real(dp) :: simplex(n, n + 1), centroid_weight_power
     162              :       logical :: enforce_bounds, adaptive_random_search
     163              : 
     164            5 :       x_first(1:n) = 3d0
     165            5 :       x_lower(1:n) = -2d0
     166            5 :       x_upper(1:n) = 5d0
     167              : 
     168            1 :       enforce_bounds = .true.
     169            1 :       adaptive_random_search = .true.
     170            1 :       centroid_weight_power = 1d0
     171              : 
     172              :       call test1_simplex( &
     173              :          n, x_first, x_lower, x_upper, simplex, &
     174              :          centroid_weight_power, enforce_bounds, &
     175            1 :          adaptive_random_search, fcn_ER, 'ER')
     176              : 
     177            1 :    end subroutine test_ER
     178              : 
     179          686 :    real(dp) function fcn_ER(n, x, lrpar, rpar, lipar, ipar, op_code, ierr)
     180              :       use const_def, only: dp
     181              :       integer, intent(in) :: n
     182              :       real(dp), intent(in) :: x(:)  ! (n)
     183              :       integer, intent(in) :: lrpar, lipar
     184              :       integer, intent(inout), pointer :: ipar(:)  ! (lipar)
     185              :       real(dp), intent(inout), pointer :: rpar(:)  ! (lrpar)
     186              :       integer, intent(in) :: op_code
     187              :       integer, intent(out) :: ierr
     188          686 :       ierr = 0
     189          686 :       fcn_ER = ER(x)
     190          686 :    end function fcn_ER
     191              : 
     192          686 :    real(dp) function ER(x)  ! extended Rosenbrock
     193              :       real(dp), intent(in) :: x(:)
     194              :       integer :: i, n
     195          686 :       n = size(x, dim=1)
     196          686 :       ER = 0
     197         2744 :       do i = 1, n - 1
     198         2744 :          ER = ER + 100d0*pow2(x(i + 1) - x(i)*x(i)) + pow2(1D0 - x(i))
     199              :       end do
     200          686 :       num_calls = num_calls + 1
     201          686 :    end function ER
     202              : 
     203            0 :    subroutine test_FR2
     204              :       ! testing with 2 dimensional Freudenstein and Roth function
     205              :       integer, parameter :: n = 2
     206            0 :       real(dp), dimension(n) :: x_first, x_lower, x_upper
     207            0 :       real(dp) :: simplex(n, n + 1), centroid_weight_power
     208              :       logical :: enforce_bounds, adaptive_random_search
     209              : 
     210              :       ! NOTE --- this function has a local minimum
     211              :       ! and the starting values lead to the false-minimum first.
     212              : 
     213              :       ! true min = 0 at (5,4)
     214              :       ! false min = 48.98... at (11.41..., -0.8968...)
     215              :       ! starting at (0.5, -2) leads to the local min.
     216              : 
     217            0 :       x_first(1:n) = [0.5d0, -2d0]
     218            0 :       x_lower(1:n) = -2d0
     219            0 :       x_upper(1:n) = 6d0
     220              : 
     221            0 :       enforce_bounds = .false.
     222            0 :       centroid_weight_power = 1d0
     223            0 :       adaptive_random_search = .true.
     224              : 
     225              :       call test1_simplex( &
     226              :          n, x_first, x_lower, x_upper, simplex, &
     227              :          centroid_weight_power, enforce_bounds, &
     228            0 :          adaptive_random_search, fcn_FR, 'FR2')
     229              : 
     230            0 :    end subroutine test_FR2
     231              : 
     232            1 :    subroutine test_FR4
     233              :       ! testing with 4 dimensional Freudenstein and Roth function
     234              :       integer, parameter :: n = 4
     235           15 :       real(dp), dimension(n) :: x_first, x_lower, x_upper
     236           26 :       real(dp) :: simplex(n, n + 1), centroid_weight_power
     237              :       logical :: enforce_bounds, adaptive_random_search
     238              : 
     239              :       ! = 0 at (5,4)
     240              :       ! = 48.98... at (11.41..., -0.8968...)
     241              :       ! starting at (0.5, -2) leads to the bad local min.
     242              : 
     243            1 :       x_first(1:n) = [0.5d0, -2d0, 0.5d0, -2d0]
     244            5 :       x_lower(1:n) = -2d0
     245            5 :       x_upper(1:n) = 6d0
     246              : 
     247            1 :       enforce_bounds = .false.
     248            1 :       centroid_weight_power = 1d0
     249            1 :       adaptive_random_search = .true.
     250              : 
     251              :       call test1_simplex( &
     252              :          n, x_first, x_lower, x_upper, simplex, &
     253              :          centroid_weight_power, enforce_bounds, &
     254            1 :          adaptive_random_search, fcn_FR, 'FR4')
     255              : 
     256            1 :    end subroutine test_FR4
     257              : 
     258            0 :    subroutine test_FR6
     259              :       ! testing with 6 dimensional Freudenstein and Roth function
     260              :       integer, parameter :: n = 6
     261            0 :       real(dp), dimension(n) :: x_first, x_lower, x_upper
     262            0 :       real(dp) :: simplex(n, n + 1), centroid_weight_power
     263              :       logical :: enforce_bounds, adaptive_random_search
     264              : 
     265              :       ! = 0 at (5,4)
     266              :       ! = 48.98... at (11.41..., -0.8968...)
     267              :       ! starting at (0.5, -2) leads to the bad local min.
     268              : 
     269            0 :       x_first(1:n) = [0.5d0, -2d0, 0.5d0, -2d0, 0.5d0, -2d0]
     270            0 :       x_lower(1:n) = -2d0
     271            0 :       x_upper(1:n) = 6d0
     272              : 
     273            0 :       enforce_bounds = .false.
     274            0 :       centroid_weight_power = 1d0
     275            0 :       adaptive_random_search = .true.
     276              : 
     277              :       call test1_simplex( &
     278              :          n, x_first, x_lower, x_upper, simplex, &
     279              :          centroid_weight_power, enforce_bounds, &
     280            0 :          adaptive_random_search, fcn_FR, 'FR6')
     281              : 
     282            0 :    end subroutine test_FR6
     283              : 
     284         7422 :    real(dp) function fcn_FR(n, x, lrpar, rpar, lipar, ipar, op_code, ierr)
     285              :       use const_def, only: dp
     286              :       integer, intent(in) :: n
     287              :       real(dp), intent(in) :: x(:)  ! (n)
     288              :       integer, intent(in) :: lrpar, lipar
     289              :       integer, intent(inout), pointer :: ipar(:)  ! (lipar)
     290              :       real(dp), intent(inout), pointer :: rpar(:)  ! (lrpar)
     291              :       integer, intent(in) :: op_code
     292              :       integer, intent(out) :: ierr
     293         7422 :       ierr = 0
     294         7422 :       fcn_FR = FR(x)
     295         7422 :    end function fcn_FR
     296              : 
     297         7422 :    real(dp) function FR(x)  ! Freudenstein and Roth function
     298              :       real(dp), intent(in) :: x(:)
     299              :       integer :: i, n
     300         7422 :       n = size(x, dim=1)
     301         7422 :       FR = 0
     302        22266 :       do i = 1, n/2
     303              :          FR = FR + &
     304            0 :               pow2(-13d0 + x(2*i - 1) + ((5d0 - x(2*i))*x(2*i) - 2d0)*x(2*i)) + &
     305        22266 :               pow2(-29d0 + x(2*i - 1) + ((1d0 + x(2*i))*x(2*i) - 14d0)*x(2*i))
     306              :       end do
     307         7422 :       num_calls = num_calls + 1
     308         7422 :    end function FR
     309              : 
     310            1 :    subroutine test_BLE
     311              :       ! testing with 4 dimensional Beale function
     312              :       integer, parameter :: n = 4
     313           15 :       real(dp), dimension(n) :: x_first, x_lower, x_upper
     314           26 :       real(dp) :: simplex(n, n + 1), centroid_weight_power
     315              :       logical :: enforce_bounds, adaptive_random_search
     316              : 
     317            5 :       x_first(1:n) = 3d0
     318            5 :       x_lower(1:n) = -2d0
     319            5 :       x_upper(1:n) = 5d0
     320              : 
     321            1 :       enforce_bounds = .true.
     322            1 :       adaptive_random_search = .true.
     323            1 :       centroid_weight_power = 1d0
     324              : 
     325              :       call test1_simplex( &
     326              :          n, x_first, x_lower, x_upper, simplex, &
     327              :          centroid_weight_power, enforce_bounds, &
     328            1 :          adaptive_random_search, fcn_BLE, 'BLE')
     329              : 
     330            1 :    end subroutine test_BLE
     331              : 
     332          612 :    real(dp) function fcn_BLE(n, x, lrpar, rpar, lipar, ipar, op_code, ierr)
     333              :       use const_def, only: dp
     334              :       integer, intent(in) :: n
     335              :       real(dp), intent(in) :: x(:)  ! (n)
     336              :       integer, intent(in) :: lrpar, lipar
     337              :       integer, intent(inout), pointer :: ipar(:)  ! (lipar)
     338              :       real(dp), intent(inout), pointer :: rpar(:)  ! (lrpar)
     339              :       integer, intent(in) :: op_code
     340              :       integer, intent(out) :: ierr
     341          612 :       ierr = 0
     342          612 :       fcn_BLE = BLE(x)
     343          612 :    end function fcn_BLE
     344              : 
     345          612 :    real(dp) function BLE(x)  ! Beale function
     346              :       real(dp), intent(in) :: x(:)
     347              :       integer :: i, n
     348          612 :       n = size(x, dim=1)
     349          612 :       BLE = 0
     350         1836 :       do i = 1, n/2
     351              :          BLE = BLE + &
     352            0 :                pow2(1.5d0 - x(2*i - 1)*(1d0 - x(2*i))) + &
     353              :                pow2(2.25d0 - x(2*i - 1)*(1d0 - x(2*i)*x(2*i))) + &
     354         1836 :                pow2(2.625d0 - x(2*i - 1)*(1d0 - x(2*i)*x(2*i)*x(2*i)))
     355              :       end do
     356          612 :       num_calls = num_calls + 1
     357          612 :    end function BLE
     358              : 
     359            1 :    subroutine test_PS
     360              :       ! testing with 4 dimensional Powell singular function
     361              :       integer, parameter :: n = 4
     362           15 :       real(dp), dimension(n) :: x_first, x_lower, x_upper
     363           26 :       real(dp) :: simplex(n, n + 1), centroid_weight_power
     364              :       logical :: enforce_bounds, adaptive_random_search
     365              : 
     366            1 :       x_first(1:n) = [3d0, -1d0, 0d0, 1d0]
     367            5 :       x_lower(1:n) = -1d0
     368            5 :       x_upper(1:n) = 3d0
     369              : 
     370            1 :       enforce_bounds = .true.
     371            1 :       adaptive_random_search = .true.
     372            1 :       centroid_weight_power = 1d0
     373              : 
     374              :       call test1_simplex( &
     375              :          n, x_first, x_lower, x_upper, simplex, &
     376              :          centroid_weight_power, enforce_bounds, &
     377            1 :          adaptive_random_search, fcn_PS, 'PS')
     378              : 
     379            1 :    end subroutine test_PS
     380              : 
     381         1350 :    real(dp) function fcn_PS(n, x, lrpar, rpar, lipar, ipar, op_code, ierr)
     382              :       use const_def, only: dp
     383              :       integer, intent(in) :: n
     384              :       real(dp), intent(in) :: x(:)  ! (n)
     385              :       integer, intent(in) :: lrpar, lipar
     386              :       integer, intent(inout), pointer :: ipar(:)  ! (lipar)
     387              :       real(dp), intent(inout), pointer :: rpar(:)  ! (lrpar)
     388              :       integer, intent(in) :: op_code
     389              :       integer, intent(out) :: ierr
     390         1350 :       ierr = 0
     391         1350 :       fcn_PS = PS(x)
     392         1350 :    end function fcn_PS
     393              : 
     394         1350 :    real(dp) function PS(x)  ! Powell singular function
     395              :       real(dp), intent(in) :: x(:)
     396              :       integer :: i, n
     397         1350 :       n = size(x, dim=1)
     398         1350 :       PS = 0
     399         2700 :       do i = 1, n/4
     400              :          PS = PS + &
     401            0 :               pow2(x(i) + 10d0*x(i + 1)) + &
     402            0 :               5d0*pow2(x(i + 2) - x(i + 3)) + &
     403              :               pow4(x(i + 1) - 2d0*x(i + 2)) + &
     404         2700 :               10d0*pow4(x(i) - x(i + 3))
     405              :       end do
     406         1350 :       num_calls = num_calls + 1
     407         1350 :    end function PS
     408              : 
     409            1 :    subroutine test_TR
     410              :       ! testing with 4 dimensional Trigonometric function
     411              :       integer, parameter :: n = 4
     412           15 :       real(dp), dimension(n) :: x_first, x_lower, x_upper
     413           26 :       real(dp) :: simplex(n, n + 1), centroid_weight_power
     414              :       logical :: enforce_bounds, adaptive_random_search
     415              : 
     416            5 :       x_first(1:n) = 0.01d0
     417            5 :       x_lower(1:n) = -0.1d0
     418            5 :       x_upper(1:n) = 0.1d0
     419              : 
     420            1 :       enforce_bounds = .true.
     421            1 :       adaptive_random_search = .true.
     422            1 :       centroid_weight_power = 1d0
     423              : 
     424              :       call test1_simplex( &
     425              :          n, x_first, x_lower, x_upper, simplex, &
     426              :          centroid_weight_power, enforce_bounds, &
     427            1 :          adaptive_random_search, fcn_TR, 'TR')
     428              : 
     429            1 :    end subroutine test_TR
     430              : 
     431          266 :    real(dp) function fcn_TR(n, x, lrpar, rpar, lipar, ipar, op_code, ierr)
     432              :       use const_def, only: dp
     433              :       integer, intent(in) :: n
     434              :       real(dp), intent(in) :: x(:)  ! (n)
     435              :       integer, intent(in) :: lrpar, lipar
     436              :       integer, intent(inout), pointer :: ipar(:)  ! (lipar)
     437              :       real(dp), intent(inout), pointer :: rpar(:)  ! (lrpar)
     438              :       integer, intent(in) :: op_code
     439              :       integer, intent(out) :: ierr
     440          266 :       ierr = 0
     441          266 :       fcn_TR = TR(x)
     442          266 :    end function fcn_TR
     443              : 
     444          266 :    real(dp) function TR(x)  ! Trigonometric function
     445              :       real(dp), intent(in) :: x(:)
     446              :       integer :: j, i, n
     447          266 :       real(dp) :: sum_cos
     448          266 :       n = size(x, dim=1)
     449          266 :       sum_cos = 0
     450         1330 :       do j = 1, n
     451         1330 :          sum_cos = sum_cos + cos(x(j))
     452              :       end do
     453              :       TR = 0
     454         1330 :       do i = 1, n
     455         1330 :          TR = TR + pow2(n - sum_cos + i*(1d0 - cos(x(i))) - sin(x(i)))
     456              :       end do
     457          266 :       num_calls = num_calls + 1
     458          266 :    end function TR
     459              : 
     460              : end module test_simplex
        

Generated by: LCOV version 2.0-1