module classes_move_tuner use, intrinsic :: iso_fortran_env, only: DP => REAL64 use procedures_errors, only: warning_continue use procedures_checks, only: check_positive, check_ratio use classes_tunable_move, only: Abstract_Tunable_Move use types_move_tuner_parameters, only: Concrete_Move_Tuner_Parameters implicit none private type, abstract, public :: Abstract_Move_Tuner private class(Abstract_Tunable_Move), pointer :: tunable_move => null() integer :: accumulation_period = 0 real(DP) :: accumulated_success_ratio = 0._DP real(DP) :: success_ratio_min = 0._DP, success_ratio_max = 0._DP contains procedure :: construct => Abstract_construct procedure :: destroy => Abstract_destroy procedure :: tune => Abstract_tune end type Abstract_Move_Tuner type, extends(Abstract_Move_Tuner), public :: Concrete_Move_Tuner end type Concrete_Move_Tuner type, extends(Abstract_Move_Tuner), public :: Null_Move_Tuner contains procedure :: construct => Null_construct procedure :: destroy => Null_destroy procedure :: tune => Null_tune end type Null_Move_Tuner type, public :: Move_Tuner_Wrapper class(Abstract_Move_Tuner), allocatable :: tuner end type Move_Tuner_Wrapper type, public :: Move_Tuner_Line type(Move_Tuner_Wrapper), allocatable :: line(:) end type Move_Tuner_Line contains !implementation Abstract_Move_Tuner subroutine Abstract_construct(this, tunable_move, parameters, num_tuning_steps) class(Abstract_Move_Tuner), intent(out) :: this class(Abstract_Tunable_Move), target, intent(in) :: tunable_move type(Concrete_Move_Tuner_Parameters), intent(in) :: parameters integer, intent(in) :: num_tuning_steps this%tunable_move => tunable_move call check_positive("Abstract_Move_Tuner: construct", "parameters%accumulation_period", & parameters%accumulation_period) if (num_tuning_steps < parameters%accumulation_period) then call warning_continue("Abstract_Move_Tuner: construct: "//& "num_tuning_steps < accumulation_period") end if this%accumulation_period = parameters%accumulation_period this%accumulated_success_ratio = 0._DP call check_ratio("Abstract_Move_Tuner: construct", "parameters%wanted_success_ratio", & parameters%wanted_success_ratio) call check_positive("Abstract_Move_Tuner: construct", "parameters%tolerance", & parameters%tolerance) this%success_ratio_min = parameters%wanted_success_ratio - parameters%tolerance this%success_ratio_max = parameters%wanted_success_ratio + parameters%tolerance end subroutine Abstract_construct subroutine Abstract_destroy(this) class(Abstract_Move_Tuner), intent(inout) :: this this%tunable_move => null() end subroutine Abstract_destroy subroutine Abstract_tune(this, tuned, i_step, success_ratio) class(Abstract_Move_Tuner), intent(inout) :: this logical, intent(out) :: tuned integer, intent(in) :: i_step real(DP), intent(in) :: success_ratio real(DP) :: averaged_success_ratio tuned = .false. this%accumulated_success_ratio = this%accumulated_success_ratio + success_ratio if (mod(i_step, this%accumulation_period) == 0) then averaged_success_ratio = this%accumulated_success_ratio / & real(this%accumulation_period, DP) ! assuming i_step++; if (averaged_success_ratio < this%success_ratio_min) then call this%tunable_move%decrease_delta() else if (this%success_ratio_max < averaged_success_ratio) then call this%tunable_move%increase_delta() else tuned = .true. ! sufficient condition? return end if this%accumulated_success_ratio = 0._DP end if end subroutine Abstract_tune !end implementation Abstract_Move_Tuner !implementation Null_Move_Tuner subroutine Null_construct(this, tunable_move, parameters, num_tuning_steps) class(Null_Move_Tuner), intent(out) :: this class(Abstract_Tunable_Move), target, intent(in) :: tunable_move type(Concrete_Move_Tuner_Parameters), intent(in) :: parameters integer, intent(in) :: num_tuning_steps end subroutine Null_construct subroutine Null_destroy(this) class(Null_Move_Tuner), intent(inout) :: this end subroutine Null_destroy subroutine Null_tune(this, tuned, i_step, success_ratio) class(Null_Move_Tuner), intent(inout) :: this logical, intent(out) :: tuned integer, intent(in) :: i_step real(DP), intent(in) :: success_ratio tuned = .true. end subroutine Null_tune !end implementation Null_Move_Tuner end module classes_move_tuner