对于大的r
,b
您可以使用一种称为蒙特卡洛积分的方法,例如参见Wikipedia 上的蒙特卡洛积分(和/或 SICP 的第 3.1.2 章)来计算总和。对于小r
的和b
显着不同的节点故障概率p[i]
,精确的方法是优越的。小和大的确切定义将取决于几个因素,最好通过实验进行尝试。
具体示例代码:这是一个非常基本的示例代码(在 Python 中),用于演示这样的过程如何工作:
def montecarlo(p, rb, N):
"""Corresponds to the binomial coefficient formula."""
import random
succ = 0
# Run N samples
for i in xrange(N):
# Generate a single test case
alivenum = 0
for j in xrange(rb):
if random.random()<p: alivenum += 1
# If the test case succeeds, increase succ
if alivenum >= b: succ += 1
# The final result is the number of successful cases/number of total cases
# (I.e., a probability between 0 and 1)
return float(succ)/N
该函数对应于二项式测试用例并运行N
测试,检查b
节点外的r*b
节点是否处于活动状态,故障概率为p
. 一些实验会让您相信,您需要N
数千个样本范围内的值才能获得任何合理的结果,但原则上复杂度为O(N*r*b)
. 结果的精度为sqrt(N)
,即,要将精度提高两倍,您需要提高N
四倍。对于足够大的r*b
情况,这种方法显然更胜一筹。
近似值的扩展:您显然需要设计测试用例,使其尊重系统的所有属性。您提出了一些扩展,其中一些可以轻松实现,而另一些则不能。让我给你几个建议:
1)在 distinct but uncorrelated 的情况下,p[i]
上述代码的变化很小:在函数头中,您传递一个数组而不是单个浮点数p
,并将该行替换if random.random()<p: alivenum += 1
为
if random.random()<p[j]: alivenum += 1
2)在相关的情况下,p[i]
您需要有关系统的其他信息。我在评论中提到的情况可能是这样的网络:
A--B--C
| |
D E
|
F--G--H
|
J
在这种情况下A
,可能是“根节点”,节点故障可能D
意味着节点 100% 概率自动故障F
,G
和H
; J
而 node 的失败F
会自动关闭G
,H
等等J
。至少这是我在评论中提到的情况(这是一个合理的解释,因为你在原始问题中谈到了概率的树结构)。在这种情况下,您需要修改p
引用树结构并for j in ...
遍历树的代码,一旦测试失败,就从当前节点跳过较低的分支。当然,由此产生的测试仍然是是否alivenum >= b
像以前一样。
3)如果网络是一个不能用树形结构表示的循环图,这种方法就会失败。在这种情况下,您需要首先创建死或活的图节点,然后在图上运行路由算法来计算唯一的、可到达的节点的数量。这不会增加算法的时间复杂度,但显然会增加代码复杂度。
4) 时间相关性是一个重要的,但如果您知道 mtbf/r(故障/修复之间的平均时间),则可能会进行修改,因为这可以为您提供p
树结构或不相关线性p[i]
的概率指数之和。然后,您将不得不在不同的时间运行 MC 程序,并获得相应的结果p
。
5)如果您只有日志文件(如上一段中所暗示的那样),则需要对方法进行实质性修改,这超出了我在此板上的能力范围。日志文件需要足够彻底,以允许重建网络图(以及 的图p
)的模型以及 的所有节点的单个值p
。否则,准确性将不可靠。这些日志文件还需要比故障和维修的时间尺度长得多,这种假设在现实生活中的网络中可能是不现实的。