创建一个预测某个处理器失败概率的函数

问题描述 投票:2回答:1

我的程序(在Java中)有一个名为Processor的对象,它可以经历迭代事件。

每个处理器都有以下字段: double lambda - 衰变指数; double failProb - 每次迭代失败的概率; int age - 处理器处于活动状态的迭代次数; boolean failed - 描述处理器是否“失败”

在每次迭代事件期间,发生以下事情:

  1. age增加1;
  2. failPorb根据此功能更新:failProb=1-Math.exp(-lambda*age);
  3. 随机数(0~1)与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迭代中没有失败的概率,然后返回该值的补充。如果功能正常,则会感觉不成熟且性能密集。我觉得同一个函数可能有一个更简单的表达式。

java function probability
1个回答
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
© www.soinside.com 2019 - 2024. All rights reserved.