Fortran语言中的加权抽样

Fortran语言中的加权抽样,fortran,sampling,weighted,Fortran,Sampling,Weighted,在Fortran程序中,我想通过使用权重随机选择一个特定变量(特别是它的索引)。权重将在单独的向量中提供(元素1将包含变量1的权重,依此类推) 我有以下代码,这些代码没有权重(mind是一个整数向量,包含原始数据集中每个变量的索引) 这里有两个例子。第一个是 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 =

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

我有以下代码,这些代码没有权重(
mind
是一个整数向量,包含原始数据集中每个变量的索引)


这里有两个例子。第一个是

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

编辑:下面附上一个最低测试代码(使用gfortran-8/9测试):

主程序
隐式无
整数j,num(5),循环
实际权重(5)
权重(:)=[1.0,2.0,5.0,0.0,2.0]
num(:)=0
do循环=11000
调用随机_索引(j,权重)
num(j)=num(j)+1
结束循环
do j=1,尺寸(重量)
打印*,j,num(j)
结束循环
包含
子例程随机_索引(idx,权重)
整数::idx
真实,意图(in)::权重(:)
实x,wsum,prob
wsum=总和(权重)
随机呼叫号码(x)
概率=0
do idx=1,尺寸(重量)
概率=概率+权重(idx)/wsum!!0如果(x),您可以简单地添加一个循环谢谢roydvib!我假设在循环退出后j保留所选变量的索引。对吗?是的,在退出循环后保留j的值。因此我们可以编写一个接收权重的函数(:)作为伪参数,返回从DO循环中获得的j,例如。@roygvib谢谢,但我不确定它是如何工作的。我运行此程序时似乎总是得到相同的j。您介意提供更多详细信息吗?似乎每次运行此rand()时都会得到相同的j给出了相同的数字。@Hermantouthrot嗨,我在答案的底部附加了一个最小的测试/工作代码。该代码稍微修改了一下,这样子例程
random\u index()
就可以独立使用了。那么,您能不能在您的环境中试用这段代码,看看它是否能按预期工作?(我几乎忘记了细节,但我想我们是在计算给定权重的累积概率,并测试“x”落入某个“箱子”(具有给定权重)。@roygvib谢谢,是的,它正在工作,我不明白它必须在一个循环中。我实际上已经用您提供的第二个示例实现了它。
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
j     :    1           2           3           4       5
count :    10047       19879       50061       0       20013
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