Fortran中的加权采样 [英] Weighted sampling in Fortran

查看:86
本文介绍了Fortran中的加权采样的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Fortran程序中,我想使用权重随机选择一个特定变量(特别是其索引).权重将在单独的向量中提供(元素1将包含变量1的权重,依此类推).

In a Fortran program I would like to choose at random a specific variable (specifically its index) by using weights. The weights would be provided in a separate vector (element 1 would contain weight of variable 1 and so on).

我有以下代码,他们可以不加重量地执行工作(mind是具有原始数据集中每个变量的索引的整数向量)

I have the following code who does the job without weight (mind being an integer vector with the index of each variable in the original dataset)

call rrand(xrand)
j = int(nn * xrand) + 1
mvar = mind(j)

推荐答案

以下是两个示例.第一个是

Here are two examples. The first one is

integer, parameter :: nn = 5
real :: weight( nn ), cumsum( nn ), x

weight( 1:nn ) = [ 1.0, 2.0, 5.0, 0.0, 2.0 ]

do j = 1, nn
    cumsum( j ) = sum( weight( 1:j ) ) / sum( weight( 1:nn ) )   !! cumulative sum
enddo

x = rand()
do j = 1, nn
    if ( x < cumsum( j ) ) exit
enddo

第二个摘录于此页面

real :: sum_weight
sum_weight = sum( weight( 1:nn ) )

x = rand() * sum_weight
do j = 1, nn
    if ( x < weight( j ) ) exit
    x = x - weight( j )
enddo

基本上与第一个相同.两者都从1,2,...,5中以weight(j)随机抽取一个j. 100000次试验的分布像

which is essentially the same as the first one. Both sample a random j from 1,2,...,5 with weight(j). 100000 trials give a distribution like

j     :    1           2           3           4       5
count :    10047       19879       50061       0       20013


下面附有一个最小的测试代码(已使用gfortran-8/9测试):


A minimal test code is attached below (tested with gfortran-8/9):

program main
    implicit none
    integer j, num( 5 ), loop
    real    weights( 5 )

    weights(:) = [ 1.0, 2.0, 5.0, 0.0, 2.0 ]
    num(:) = 0

    do loop = 1, 100000
        call random_index( j, weights )
        num( j ) = num( j ) + 1
    enddo

    do j = 1, size( weights )
        print *, j, num( j )
    enddo

contains

subroutine random_index( idx, weights )
    integer :: idx
    real, intent(in) :: weights(:)

    real x, wsum, prob

    wsum = sum( weights )

    call random_number( x )

    prob = 0
    do idx = 1, size( weights )
        prob = prob + weights( idx ) / wsum   !! 0 < prob < 1
        if ( x <= prob ) exit
    enddo
end subroutine

end program

这篇关于Fortran中的加权采样的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆