Bi-polar (two-sided) Pareto distribution. Generates a symmetric heavy-tailed distribution centered at a location.
Unlike the standard Pareto which is one-sided (heavy tail on right only), the bi-polar Pareto is symmetric and allows large jumps in both directions. This is particularly useful for optimization where perturbations should be unbiased with respect to direction.
The distribution:
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | center |
center location of the distribution |
||
| real(kind=wp), | intent(in) | :: | scale |
scale parameter for the Pareto distribution |
||
| real(kind=wp), | intent(in) | :: | shape |
shape parameter (smaller values = heavier tails) |
||
| real(kind=wp), | intent(in) | :: | xl |
lower bound |
||
| real(kind=wp), | intent(in) | :: | xu |
upper bound |
function bipareto(center, scale, shape, xl, xu) real(wp),intent(in) :: center !! center location of the distribution real(wp),intent(in) :: scale !! scale parameter for the Pareto distribution real(wp),intent(in) :: shape !! shape parameter (smaller values = heavier tails) real(wp),intent(in) :: xl !! lower bound real(wp),intent(in) :: xu !! upper bound real(wp) :: bipareto integer,parameter :: max_tries = 1000 integer :: i real(wp) :: magnitude, sign_val, u ! rejection sampling to ensure within bounds do i = 1, max_tries ! randomly choose direction: -1 or +1 if (uniform_random_number() < 0.5_wp) then sign_val = -1.0_wp else sign_val = 1.0_wp end if ! generate Pareto-distributed magnitude (inlined) u = uniform_random_number() magnitude = (scale / u**(1.0_wp / shape)) - scale ! apply signed magnitude to center bipareto = center + sign_val * magnitude ! check if within bounds if (bipareto >= xl .and. bipareto <= xu) return end do ! fallback to uniform if rejection sampling fails bipareto = uniform(xl, xu) end function bipareto