我的程序(在Java中)有一个名为Processor的对象,它可以进行迭代事件。
每个处理器都有以下字段:
double lambda
- 衰变指数;
double failProb
- 每次迭代失败的概率;
int age
- 处理器处于活动状态的迭代次数;
boolean failed
- 描述处理器是否“失败”
在每次迭代事件期间,发生以下事情:
age
增加1; failPorb
根据此功能更新:failProb=1-Math.exp(-lambda*age);
failProb
进行比较,如果比较评估为真 - random-number < failProb
- ,则字段failed
变为true
总之,每次迭代都可能导致处理器“失败”,并且失败的概率随着每次迭代而增加。
问题是这样,我如何在处理器中编写一个函数来预测处理器在下一次x
次迭代中失败的概率(如果有必要,这会导致更大的失败概率?)
尝试解决方案:
1:
public double predictFailProb(int x){
return(1-Math.exp(-lambda*(age+x)));
}
上述方法不起作用,因为它仅在x迭代时间段的最后一个时间给出failProb
,而不考虑处理器在该点之前可能已经失败。换句话说,当处理器处于failProb
x+current_age
2:
public double predictFailProb(int x){
double t=1;
for(int i=0; i<x; i++){
t*=1-(1-Math.exp(-lambda*(age+i)));
}
return (1-t);
}
理论上,上面应该计算处理器在下一次x
次迭代中没有失败的概率,然后返回该值的补充。如果功能正常,则会感觉不成熟且性能密集。我觉得同一个函数可能有一个更简单的表达式。
答案 0 :(得分:1)
以下是x
步骤中失败的明确公式。
假设:
A_k
成为处理器在步骤k
中失败的事件。k-th
步骤失败的可能性由P[A_k] = 1 - exp(-lambda * (age + k))
我们希望计算处理器在x
步骤内失败的概率。
它拥有:
P[fails within first x steps]
= 1 - P[does not fail within x steps]
= 1 - P[AND_{k = 1}^x not(A_k)]
= 1 - prod_{k=1}^x P[not(A_k)] // independence assumption
= 1 - prod_{k=1}^x (1 - P[A_k])
= 1 - prod_{k=1}^x (1 - 1 + exp(-lambda * (age + k)))
= 1 - prod_{k=1}^x exp(-lambda * (age + k))
= 1 - exp(-lambda * age * x - lambda * sum_{k=1}^x k)
= 1 - exp(-lambda * age * x) * exp(-lambda * x * (x + 1) / 2)
因此,在Java中,它可以在如下的恒定时间内计算:
double probFailureWithin(int steps, int age, double lambda) {
return
1.0 -
Math.exp(-lambda * age * steps) *
Math.exp(-lambda * steps * (steps + 1) / 2.0);
}
以下是一系列实验,证实这个明确的公式是正确的:
double probFailureWithin(int steps, int age, double lambda) {
return
1.0 -
Math.exp(-lambda * age * steps) *
Math.exp(-lambda * steps * (steps + 1) / 2.0);
}
boolean randFailureWithin(int steps, int age, double lambda) {
for (int k = 1; k <= steps; k++) {
double failProb = 1 - Math.exp(-lambda * (age + k));
if (Math.random() < failProb) {
return true;
}
}
return false;
}
double bruteforceFailureWithin(int steps, int age, double lambda) {
double nonFailureProb = 1.0;
for (int k = 1; k <= steps; k++) {
nonFailureProb *= Math.exp(-lambda * (age + k));
}
return 1.0 - nonFailureProb;
}
void runExperiment(int steps, int age, double lambda, int reps) {
int numFailures = 0;
for (int rep = 0; rep < reps; rep++) {
if (randFailureWithin(steps, age, lambda)) {
numFailures++;
}
}
double empiricalProb = numFailures / (double)reps;
double predictedProb = probFailureWithin(steps, age, lambda);
double bruteforceProb = bruteforceFailureWithin(steps, age, lambda);
System.out.println(
"a = " + age +
" l = " + lambda +
" s = " + steps +
" Empirical: " + empiricalProb +
" Predicted: " + predictedProb +
" BruteForce: " + bruteforceProb
);
}
void runExperiments(int reps) {
for (double lambda : new double[]{0.7, 0.5, 0.1, 0.01, 0.0001}) {
for (int age : new int[]{0, 1, 10, 1000, 10000}) {
for (int steps : new int[]{0, 1, 10, 1000, 10000}) {
runExperiment(steps, age, lambda, reps);
}
}
}
}
只需runExperiments(10000)
或类似的内容,并比较以下各项的值:
您将看到显式公式与蛮力乘法方法完全相同,并且这两个公式都非常接近实证结果。
摘录:
a = 500 l = 1.0E-4 s = 1
Empirical: 0.049054
Predicted: 0.04886569368574745
BruteForce: 0.04886569368574745
a = 500 l = 1.0E-4 s = 10
Empirical: 0.396329
Predicted: 0.39679610193504744
BruteForce: 0.39679610193504766
a = 500 l = 1.0E-4 s = 100
Empirical: 0.995945
Predicted: 0.9959336114191201
BruteForce: 0.9959336114191201