蒙特卡罗模拟又称统计模拟法、随机抽样技术,是一种随机模拟方法,具体使用随机数(或更常见的伪随机数)来解决很多计算问题的方法。将所求解的问题同一定的概率模型相联系,用电子计算机实现统计模拟或抽样,以获得问题的近似解。
蒙特卡罗方法于20世纪40年代美国在第二次世界大战中研制原子弹的“曼哈顿计划”计划的成员S.M.乌拉姆和J.冯·诺伊曼首先提出。数学家冯·诺伊曼用驰名世界的赌城—摩纳哥的Monte Carlo—来命名这种方法,为它蒙上了一层神秘色彩。其实在这之前,蒙特卡罗方法就已经存在。1777年,法国Buffon提出用投针实验的方法求圆周率。这被认为是蒙特卡罗方法的起源。
由概率定义知,某事件的概率可以用大量试验中该事件发生的频率来估算。因此,可以先对影响其可靠度的随机变量进行大量的随机抽样,然后把这些抽样值一组一组地代入功能函数式,确定结构是否失效,最后从中求得结构的失效概率。蒙特卡罗法正是基于此思路进行分析的。
1.1 积分模拟计算
利用蒙特卡罗模拟方法,原理比较简单,首先生成需要计算的函数:>f <- function(x) exp(x^2)然后进行计算,考虑到积分计算近似于N个正方形相加,每个正方形的长度为exp(xi),宽度为1/N,面积为exp(xi)* 1/N,再把每个面积加总,即为函数的平均值,命令为:> mean(f(x))[1] 1.462684毫无疑问,一些积分得不到解析式结果的话,利用这种方法计算会非常方便。
1.2 圆周率计算
图2.39 随机模拟圆周率
计算下面自建一个函数calpi,用于计算圆周率pi。具体如下:
>calpi <- function(n){
> count <- 0
> for( i in 1:n){
#用循环进行计算
> x <- runif(1,0,1) #产生均匀分布随机数
> y <- runif(1,0,1) #产生均匀分布随机数
> if (x^2 +y^2 <= 1 )
> count <- count+1 } #判断点是否位于圆内
> return(4*count/n) } #返回计算结果
在此基础上运用10000随机数,得到的结果为:
>calpi(10000)
[1] 3.1644
精度不算高,进一步提高随机数的数量,令为10000000,但需要花较长的时间,并计算所花的时间,对应命令为:
>t0 <- Sys.time()
>calpi(10000000)[1] 3.141121
>t1 <- Sys.time()
>t1-t0
Time difference of25.51678 secs
精度在大幅提高,但时间为25秒,相对较长。因此,需要进一步提高软件的运行效率。一般而言,为了提高R语言的运行效率,尽量采用以下原则:
第一、避免循环,采用向量化方法进行分析,如常用的for改成apply等函数进行分析,或者利用内置函数rowSums等避免循环;
第二、预先给对象分配内存,且减少cbind和rbind等函数的使用;
第三、运用并行计算工具包,如parallel、foreach等工具包进行分析。
基于此,下面对代码进行优化,提高运行效率,把循环变成矩阵形式,并进一步利用rowSums函数筛选出 上面红色的点,同时计算运行时间,具体如下:
>N <- 100000000
>t0 <- Sys.time()
>x <- matrix(runif(2 * N), ncol = 2)
>4*mean(rowSums(x^2)<=1) [1] 3.141599
>t1 <- Sys.time()
>t1-t0
Time difference of11.34028 secs
可以看出,利用矩阵、内置函数rowSums和mean,使运行效率大幅提高,时间从25.5秒下降到11.3秒,几乎缩短一半。
感兴趣的读者可进一步参考《量化投资基础、方法与策略——R语言实战指南》,里面详细介绍R语言的入门,并介绍如何利用R语言进行量化投资。