使用合并-查找数据结构,实现估计渗漏(Percolation)问题阈值的程序。
编写一个程序,通过蒙特卡罗模拟来估计渗滤阈值。
引言:
给定一个由随机分布的绝缘材料和金属材料组成的复合系统:多少材料需要是金属的,以便复合系统是电导体?考虑到地表(或下面的油)有水的多孔景观,在什么条件下水能够通过底部排出(或油喷到表面)?科学家已经定义了一个被称为渗流的抽象过程来模拟这种情况。该模型。我们用一个N×N的网格模型来建立一个渗流系统。每个网站都是开放或封锁。一个完整的网站是一个开放的网站,可以通过一系列相邻的(左,右,上,下)开放网站连接到最上面的一个开放网站。我们说如果底部有一个完整的网站,系统会渗透。换句话说,如果我们填充连接到最上一行的所有打开的站点,并且该过程填满最下一行的一些打开站点,那么系统会渗透。 (对于绝缘/金属材料的例子,开放部位对应于金属材料,使得渗透的体系具有从上到下的金属路径,并且完整的部位导电。对于多孔物质实例,开放部位对应于空的空间水可以通过它流动,使渗透的系统让水充满开放的地点,从上到下流动。)
问题:(如果已经知道题目,可以直接越过此处)
在一个著名的科学问题中,研究人员对以下问题感兴趣:如果网站独立设置为以概率p打开(因此以概率1-p被阻塞),系统渗透的概率是多少?当p等于0时,系统不会渗透;当p等于1时,系统渗透。下面的图显示了20×20随机网格(左)和100×100随机网格(右)的网站空置概率p对渗滤概率
当N足够大时,存在阈值p’,使得当p < p’时,随机N×N网格几乎不渗滤,并且当p> p’时,随机N×N网格几乎总是渗滤。尚未推导出用于确定渗透阈值p’的数学解决方案。你的任务是编写一个计算机程序来估计p’。
程序Percolation实现的API接口如下:
public class Percolation {
public Percolation(int N) // create N-by-N grid, with all sites blocked
public void open(int i, int j) // open site (row i, column j) if it is not already
public boolean isOpen(int i, int j) // is site (row i, column j) open?
public boolean isFull(int i, int j) // is site (row i, column j) full?
public boolean percolates() // does the system percolate?
public static void main(String[] args) // test client, optional
}
按照惯例,行和列索引i和j是1和N之间的整数,其中(1,1)是左上角站点:如果open(),isOpen()或isFull()的任何参数抛出IndexOutOfBoundsException超出了规定的范围。如果N≤0,构造函数应该抛出IllegalArgumentException。构造函数应该花费与N2成正比的时间;所有方法都应该花费不变的时间加上对union(),find(),connected()和count()的联合查找方法的不断调用。
蒙特卡洛模拟。为了估计逾渗阈值,考虑下面的计算实验:
•初始化所有要阻止的站点。
•重复以下操作,直到系统渗漏:
o在所有被封锁的网站中随机选择一个网站(第i行,第j列)。
o打开网站(第i行,第j列)。
•系统渗透时打开的部分网站提供了渗透阈值的估计值。
例如,如果按照下面的快照打开网格,那么我们估计的渗滤阈值是204/400 = 0.51,因为当第204个站点打开时,系统渗透。
通过重复该计算实验T次并平均结果,我们获得更准确的逾渗阈值估计。 设x_t为计算实验t中开放点的分数。 样本平均值μ提供了渗透阈值的估计; 样本标准偏差σ测量阈值的清晰度。
假设T足够大(例如至少30),下面提供渗透阈值的95%置信区间
程序PercolationStats 的API接口:
public class PercolationStats {
public PercolationStats(int N, int T) // perform T independent computati