Random 从多值法线绘制,带;genmn“;及;setgmn";
我试图从多重正态分布中随机抽取偏差。 我在网上找到了两个子程序:“setgmn”和“genmn”,它们应该就是这样做的。它们来自“ranlib”图书馆 然而,我不知道这些子例程是如何协同工作的。 Setgmn以genmn可以使用的方式组合数据。然而,我与“帕尔姆”的论点斗争,我不确定我必须传递什么。以及这两个子例程需要如何组合才能实际工作 我在网上找不到一个例子。所以我想这里可能有人已经用过了,或者有一个链接到网上的一个例子 来自: 首先,您必须调用Random 从多值法线绘制,带;genmn“;及;setgmn";,random,fortran,Random,Fortran,我试图从多重正态分布中随机抽取偏差。 我在网上找到了两个子程序:“setgmn”和“genmn”,它们应该就是这样做的。它们来自“ranlib”图书馆 然而,我不知道这些子例程是如何协同工作的。 Setgmn以genmn可以使用的方式组合数据。然而,我与“帕尔姆”的论点斗争,我不确定我必须传递什么。以及这两个子例程需要如何组合才能实际工作 我在网上找不到一个例子。所以我想这里可能有人已经用过了,或者有一个链接到网上的一个例子 来自: 首先,您必须调用setgmn。此过程将设置必须传递到getm
setgmn
。此过程将设置必须传递到getmn
的参数parm
subroutine setgmn ( meanv, covm, p, parm )
integer ( kind = 4 ) p
real ( kind = 4 ) covm(p,p)
real ( kind = 4 ) meanv(p)
real ( kind = 4 ) parm(p*(p+3)/2+1)
参数:
MEANV
:多元正态分布的平均值
COVM
:输入时,多元分布的协方差矩阵。输出时,COVM中的信息已被覆盖
p
:尺寸的数量
PARM
:生成多元正态偏差所需的参数
PARM(1)
包含偏差的大小,p
PARM(2:p+1)
包含平均向量
PARM(p+2:p*(p+3)/2+1)
包含协方差矩阵的Cholesky分解的上半部分
参数:
PARM(p*(p+3)/2+1)
:由SETGMN设置的参数
X(p)
:随机偏离分布。将是输出
WORK(p)
:workspace这里是您所需要的另一种现代实现,它使用MVN协方差矩阵的Cholesky分解,而不是协方差矩阵本身,然后是一个如何使用它的示例:
module RandMVN_mod
implicit none
contains
!***********************************************************************************************************************************
!***********************************************************************************************************************************
! Returns a multivariate normal random number.
function getRandMVN(nd,MeanVec,CholeskyLower,Diagonal) result(RandMVN)
use, intrinsic :: iso_fortran_env, only: IK => int32, RK => real64
implicit none
integer(IK), intent(in) :: nd ! dimension of the MVN
real(RK) , intent(in) :: MeanVec(nd) ! The Mean vector of the MVN from which points are drawn
real(RK) , intent(in) :: CholeskyLower(nd,nd) ! Lower Triangle of the Cholesky Factorization of the covariance matrix of the MVN
real(RK) , intent(in) :: Diagonal(nd) ! Diagonal terms of the Cholesky Factorization of the covariance matrix of the MVN
real(RK) :: RandMVN(nd), dummy
integer(IK) :: j,i
RandMVN = 0._RK
do j = 1,nd
dummy = getRandGaus()
RandMVN(j) = RandMVN(j) + Diagonal(j) * dummy
do i = j+1,nd
RandMVN(i) = RandMVN(i) + CholeskyLower(i,j) * dummy
end do
end do
RandMVN = RandMVN + MeanVec
end function getRandMVN
!***********************************************************************************************************************************
!***********************************************************************************************************************************
! returns a normally distributed random number with zero mean and unit variance.
function getRandGaus()
use, intrinsic :: iso_fortran_env, only: IK => int32, RK => real64
implicit none
integer(IK), save :: iset=0
real(RK) , save :: gset
real(RK) :: fac,rsq,vec(2)
real(RK) :: getRandGaus
if (iset == 0) then
do
call random_number(vec)
vec = 2._RK*vec - 1._RK
rsq = vec(1)**2 + vec(2)**2
if ( rsq > 0._RK .and. rsq < 1._RK ) exit
end do
fac = sqrt(-2._RK*log(rsq)/rsq)
gset = vec(1)*fac
getRandGaus = vec(2)*fac
iset = 1
else
getRandGaus = gset
iset = 0
endif
end function getRandGaus
!***********************************************************************************************************************************
!***********************************************************************************************************************************
! Returns the the Cholesky factorization of input positive definite matrix PosDefMat
subroutine getCholeskyFactor(nd,PosDefMat,Diagonal)
use, intrinsic :: iso_fortran_env, only: IK => int32, RK => real64
implicit none
integer(IK), intent(in) :: nd
real(RK) , intent(inout) :: PosDefMat(nd,nd) ! Upper triangle + diagonal is input matrix, lower is output.
real(RK) , intent(out) :: Diagonal(nd)
real(RK) :: summ
integer(IK) :: i
do i=1,nd
summ = PosDefMat(i,i) - dot_product(PosDefMat(i,1:i-1),PosDefMat(i,1:i-1))
if (summ <= 0._RK) then
error stop
end if
Diagonal(i) = sqrt(summ)
PosDefMat(i+1:nd,i) = ( PosDefMat(i,i+1:nd) - matmul(PosDefMat(i+1:nd,1:i-1),PosDefMat(i,1:i-1)) ) / Diagonal(i)
end do
end subroutine getCholeskyFactor
!***********************************************************************************************************************************
!***********************************************************************************************************************************
end module RandMVN_mod
program test_RandMVN
use, intrinsic :: iso_fortran_env, only: IK => int32, RK => real64
use RandMVN_mod
implicit none
integer(IK) :: isample
integer(IK) , parameter :: nd = 2 ! dimension of the Multivariate distribution (MVN)
integer(IK) , parameter :: nsample = 100 ! count of random numbers
real(RK) , parameter :: CovMat(nd,nd) = reshape([ 1._RK , 0.5_RK , 0.5_RK , 1._RK ], shape=shape(CovMat)) ! covariance matrix of MVN
real(RK) , parameter :: MeanVec(nd) = [ 1._RK , 1._RK ] ! mean vector of the MVN
real(RK) :: CholeskyLower(nd,nd), Diagonal(nd)
! get the Cholesky factorization of the Covariance Matrix
CholeskyLower = CovMat
call getCholeskyFactor(nd,CholeskyLower,Diagonal)
! get random MVN vectors form the MVN distribution
do isample = 1,nsample
write(*,"(*(g0,' '))") getRandMVN(nd,MeanVec,CholeskyLower,Diagonal), " ;"
end do
end program test_RandMVN
模块RandMVN\u模块
隐式无
包含
!***********************************************************************************************************************************
!***********************************************************************************************************************************
! 返回多元正态随机数。
函数getRandMVN(nd、MeanVec、CholeskyLower、对角线)结果(RandMVN)
使用,内在::iso_fortran_env,仅限:IK=>int32,RK=>real64
隐式无
整数(IK),意图(in)::nd!MVN的维度
真实(RK),意图(in)::平均(nd)!绘制点的MVN的平均向量
雷亚尔(RK),意图(in)::切洛斯基洛(nd,nd)!MVN协方差矩阵的Cholesky分解的下三角
真实(RK),意图(in)::对角线(nd)!MVN协方差矩阵Cholesky分解的对角项
真实的(RK):随机的(nd),虚拟的
整数(IK)::j,i
RandMVN=0.\u RK
do j=1,nd
dummy=getRandGaus()
RandMVN(j)=RandMVN(j)+对角线(j)*假人
i=j+1,nd
RandMVN(i)=RandMVN(i)+天鹅绒(i,j)*假人
结束
结束
RandMVN=RandMVN+MeanVec
结束函数getRandMVN
!***********************************************************************************************************************************
!***********************************************************************************************************************************
! 返回均值和单位方差为零的正态分布随机数。
函数getRandGaus()
使用,内在::iso_fortran_env,仅限:IK=>int32,RK=>real64
隐式无
整数(IK),保存::iset=0
实(RK),保存::gset
雷亚尔(RK):外交部、区域安全部、外交部(2)
雷亚尔(RK)::格特兰高斯
如果(iset==0),则
做
呼叫随机号码(vec)
vec=2._RK*vec-1._RK
rsq=vec(1)**2+vec(2)**2
如果(rsq>0.\u RK.和.rsq<1.\u RK)退出
结束
fac=sqrt(-2._RK*log(rsq)/rsq)
gset=vec(1)*fac
getRandGaus=vec(2)*fac
iset=1
其他的
getRandGaus=gset
iset=0
恩迪夫
端函数getRandGaus
!***********************************************************************************************************************************
!***********************************************************************************************************************************
! 返回输入正定矩阵PosDefMat的Cholesky分解
子例程getCholeskyFactor(nd、PosDefMat、对角线)
使用,内在::iso_fortran_env,仅限:IK=>int32,RK=>real64
隐式无
整数(IK),意图(in)::nd
真实(RK),意图(inout)::PosDefMat(nd,nd)!上部三角形+对角线为输入矩阵,下部为输出矩阵。
真实(RK)、意图(out)::对角线(nd)
雷亚尔(RK)::总和
整数(IK)::i
i=1,nd吗
summ=PosDefMat(i,i)-dot_积(PosDefMat(i,1:i-1),PosDefMat(i,1:i-1))
如果(总和int32,RK=>real64
使用RandMVN_mod
隐式无
整数(IK)::isample
整数(IK),参数::nd=2!多元分布(MVN)的维数
整数(IK),参数::nsample=100!随机数计数
实数(RK),参数::CovMat(nd,nd)=重塑([1._RK,0.5_RK,0.5_RK,1._RK],形状=形状(CovMat))!MVN的协方差矩阵
实数(RK),参数::平均向量(nd)=[1._RK,1._RK]!MVN的平均向量
真实的(
module RandMVN_mod
implicit none
contains
!***********************************************************************************************************************************
!***********************************************************************************************************************************
! Returns a multivariate normal random number.
function getRandMVN(nd,MeanVec,CholeskyLower,Diagonal) result(RandMVN)
use, intrinsic :: iso_fortran_env, only: IK => int32, RK => real64
implicit none
integer(IK), intent(in) :: nd ! dimension of the MVN
real(RK) , intent(in) :: MeanVec(nd) ! The Mean vector of the MVN from which points are drawn
real(RK) , intent(in) :: CholeskyLower(nd,nd) ! Lower Triangle of the Cholesky Factorization of the covariance matrix of the MVN
real(RK) , intent(in) :: Diagonal(nd) ! Diagonal terms of the Cholesky Factorization of the covariance matrix of the MVN
real(RK) :: RandMVN(nd), dummy
integer(IK) :: j,i
RandMVN = 0._RK
do j = 1,nd
dummy = getRandGaus()
RandMVN(j) = RandMVN(j) + Diagonal(j) * dummy
do i = j+1,nd
RandMVN(i) = RandMVN(i) + CholeskyLower(i,j) * dummy
end do
end do
RandMVN = RandMVN + MeanVec
end function getRandMVN
!***********************************************************************************************************************************
!***********************************************************************************************************************************
! returns a normally distributed random number with zero mean and unit variance.
function getRandGaus()
use, intrinsic :: iso_fortran_env, only: IK => int32, RK => real64
implicit none
integer(IK), save :: iset=0
real(RK) , save :: gset
real(RK) :: fac,rsq,vec(2)
real(RK) :: getRandGaus
if (iset == 0) then
do
call random_number(vec)
vec = 2._RK*vec - 1._RK
rsq = vec(1)**2 + vec(2)**2
if ( rsq > 0._RK .and. rsq < 1._RK ) exit
end do
fac = sqrt(-2._RK*log(rsq)/rsq)
gset = vec(1)*fac
getRandGaus = vec(2)*fac
iset = 1
else
getRandGaus = gset
iset = 0
endif
end function getRandGaus
!***********************************************************************************************************************************
!***********************************************************************************************************************************
! Returns the the Cholesky factorization of input positive definite matrix PosDefMat
subroutine getCholeskyFactor(nd,PosDefMat,Diagonal)
use, intrinsic :: iso_fortran_env, only: IK => int32, RK => real64
implicit none
integer(IK), intent(in) :: nd
real(RK) , intent(inout) :: PosDefMat(nd,nd) ! Upper triangle + diagonal is input matrix, lower is output.
real(RK) , intent(out) :: Diagonal(nd)
real(RK) :: summ
integer(IK) :: i
do i=1,nd
summ = PosDefMat(i,i) - dot_product(PosDefMat(i,1:i-1),PosDefMat(i,1:i-1))
if (summ <= 0._RK) then
error stop
end if
Diagonal(i) = sqrt(summ)
PosDefMat(i+1:nd,i) = ( PosDefMat(i,i+1:nd) - matmul(PosDefMat(i+1:nd,1:i-1),PosDefMat(i,1:i-1)) ) / Diagonal(i)
end do
end subroutine getCholeskyFactor
!***********************************************************************************************************************************
!***********************************************************************************************************************************
end module RandMVN_mod
program test_RandMVN
use, intrinsic :: iso_fortran_env, only: IK => int32, RK => real64
use RandMVN_mod
implicit none
integer(IK) :: isample
integer(IK) , parameter :: nd = 2 ! dimension of the Multivariate distribution (MVN)
integer(IK) , parameter :: nsample = 100 ! count of random numbers
real(RK) , parameter :: CovMat(nd,nd) = reshape([ 1._RK , 0.5_RK , 0.5_RK , 1._RK ], shape=shape(CovMat)) ! covariance matrix of MVN
real(RK) , parameter :: MeanVec(nd) = [ 1._RK , 1._RK ] ! mean vector of the MVN
real(RK) :: CholeskyLower(nd,nd), Diagonal(nd)
! get the Cholesky factorization of the Covariance Matrix
CholeskyLower = CovMat
call getCholeskyFactor(nd,CholeskyLower,Diagonal)
! get random MVN vectors form the MVN distribution
do isample = 1,nsample
write(*,"(*(g0,' '))") getRandMVN(nd,MeanVec,CholeskyLower,Diagonal), " ;"
end do
end program test_RandMVN