Perturb a single variable using its assigned distribution and parameters.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| class(simulated_annealing_type), | intent(inout) | :: | me | |||
| integer, | intent(in) | :: | ivar |
variable index |
||
| real(kind=wp), | intent(in) | :: | x |
variable value to perturb |
||
| integer, | intent(in) | :: | mode |
perturbation distribution mode (see |
||
| real(kind=wp), | intent(in) | :: | lower |
lower bound |
||
| real(kind=wp), | intent(in) | :: | upper |
upper bound |
perturbed value
function perturb_variable(me, ivar, x, mode, lower, upper) result(r) class(simulated_annealing_type),intent(inout) :: me integer,intent(in) :: ivar !! variable index real(wp),intent(in) :: x !! variable value to perturb integer,intent(in) :: mode !! perturbation distribution mode (see `distribution_mode` for details) real(wp),intent(in) :: lower !! lower bound real(wp),intent(in) :: upper !! upper bound real(wp) :: r !! perturbed value integer :: i !! counter integer,parameter :: max_tries = 1000 !! max tries for rejection sampling ! select distribution based on the variable's distribution_mode: select case (mode) case(sa_mode_uniform) ! uniform r = uniform(lower, upper) case(sa_mode_normal) ! normal (truncated) ! center the distribution on the current value of the variable r = truncated_normal(x, me%dist_std_dev(ivar), lower, upper) case(sa_mode_cauchy) ! cauchy ! center the distribution on the current value of the variable ! rejection sampling to ensure within bounds do i = 1, max_tries r = cauchy(x, me%dist_scale(ivar)) if (r >= lower .and. r <= upper) return end do ! fallback to uniform if rejection sampling fails r = uniform(lower, upper) case(sa_mode_triangular) ! triangular ! center the peak at the current value of the variable ! handle degenerate interval to avoid division by zero if (upper == lower) then ! interval has collapsed to a point: always return that value r = lower else ! compute normalized position of x in [lower, upper] r = lower + (upper - lower) * triangular_dist((x - lower) / (upper - lower)) end if case(sa_mode_bipareto) ! bipareto ! center the distribution on the current value of the variable r = bipareto(x, me%dist_scale(ivar), & me%dist_shape(ivar), lower, upper) case default error stop 'Error: invalid distribution_mode in perturb_variable' end select end function perturb_variable