Javascript Bonferroni不等式JS实现中避免多重循环

Javascript Bonferroni不等式JS实现中避免多重循环,javascript,algorithm,loops,Javascript,Algorithm,Loops,我试图实现“Bonferroni不等式”,该不等式使用Javascript UDF对GCP BigQuery上的数据科学用例的多个独立事件合并的概率进行建模。然而,我对JS非常不熟悉,对良好的实践一无所知 要应用的公式如下所示: P(U Ai) = SUM(P(Ai)) - SUM(P(Ai)*P(Aj)) + SUM(P(Ai)*P(Aj)*P(Ak) - ... i != j != k 我对该函数的输入是单个事件概率的数组: [P(A1), P(A2), P(A3), ...] 为了得

我试图实现“Bonferroni不等式”,该不等式使用Javascript UDF对GCP BigQuery上的数据科学用例的多个独立事件合并的概率进行建模。然而,我对JS非常不熟悉,对良好的实践一无所知

要应用的公式如下所示:

P(U Ai) = SUM(P(Ai)) - SUM(P(Ai)*P(Aj)) + SUM(P(Ai)*P(Aj)*P(Ak) - ... i != j != k
我对该函数的输入是单个事件概率的数组:

[P(A1), P(A2), P(A3), ...] 
为了得到结果,我本能地将“for循环”排成几行。然而,看到这么难看的代码很痛苦,所以我想知道你们中是否有人对如何以更优雅和优化的方式实现它有想法

下面是我为4级Bonferroni不等式编写的函数:

function unionBoundProbability(probList){

  var intersection2 = 0;
  var intersection3 = 0;
  var intersection4 = 0;
  var i = 0;
  var j = 0;
  var k = 0;
  var l = 0;
  var sum = 0;
  var product = 1;

  var sum = probList.reduce((a, b) => a + b, 0);

  for(i = 0; i < probList.length; i++){
    product *= probList[i];
    for(j = i+1; j < probList.length; j++){
      intersection2 += probList[i]*probList[j];
      for(k = j+1; k < probList.length; k++){
        intersection3 += probList[i]*probList[j]*probList[k];
        for(l = k+1; l < probList.length; l++){
          intersection4 += probList[i]*probList[j]*probList[k]*probList[l];
        }
      }
    }
  }

  switch (probList.length) {
    case 0:
      return 0;
      break;
    case 1:
      return probList[0];
      break;
    case 2:
      return sum - product;
      break;
    case 3:
      return sum - intersection2 + product;
      break
    case 4:
      return sum - intersection2 + intersection3 - product;
    case 5 :
      return sum - intersection2 + intersection3 - intersection4 + product;
    default:
      return Math.max((sum - intersection2 + intersection3  - intersection4), Math.max.apply(Math, probList));
  }
}
函数概率(probList){
var intersection2=0;
var intersection3=0;
var intersection4=0;
var i=0;
var j=0;
var k=0;
var l=0;
var总和=0;
var乘积=1;
var sum=probList.reduce((a,b)=>a+b,0);
对于(i=0;i
我想做的是计算作为输入传递的所有概率的并集概率的近似值

如果我的概率小于5,那么switch语句将应用精确的公式。否则,默认情况下应用Bonferroni近似(因为我正在建模接收信号的概率,如果估计值小于最佳天线的概率,那么我保留最佳天线)


感谢您的帮助

此示例遵循以下公式

P(⋃(i=1=>n)Ai)=∑(i=1=>n)P(Ai)− ∑(一){
返回a+((i%2)?-1:1)*c;
}, 0);
}
console.log(不等式(probList));
PS:这是用ES6编写的


此示例遵循以下公式:

P(⋃(i=1=>n)Ai)=∑(i=1=>n)P(Ai)− ∑(一){
返回a+((i%2)?-1:1)*c;
}, 0);
}
console.log(不等式(probList));
PS:这是用ES6编写的


我们可以避免再次发生

说出大小为
n的
A

根据你的公式,我们可以考虑

  • 我们从A:
    C\n^1
  • 我们从A:
    C\n^2
  • 我们从A:
    C\n^3
我们不必重新计算每个
k-utuple
(无序元组),只需保留前一层的
(k-1)-utuple
e、 让我们拿数组[1,2,3,4,5]

  • 第一层:
    1,2,3,4,5
  • 第二层:
    1-2
    1-3
    1-4
    1-5
    2-3
    2-4
    ,…,
    4-5
  • 第三层:
    1-2-{i}
    (i代表3到5),
    1-3-{i}
对于我们的例子:我们并不真正需要整个utuple:只需要它的最后一个idx和它的值(它的元素的乘积)

阿尔戈

function bonferroni(A, nlev){
    let lv = 0;
    let tot = 0;
    //i refers to the index of the last element added to the tuple
    //s refers to its value
    //here we initialize with i=-1 just so the first while loop builds an equivalent of "A"
    let layer = [{i:-1, s:1}];
    while(lv < nlev){
        let sum = 0;
        let next = [];
        layer.forEach(utuple=>{

            for(let i = utuple.i+1; i<A.length; ++i){
                let s = utuple.s * A[i];
                sum += s;
                next.push({i, s});
            }
        })
        layer = next;
        if((lv % 2)==0){
            tot += sum;
        }else{
            tot -= sum;
        }
        lv++;
    }
    return tot;
}
功能bonferroni(A,nlev){
设lv=0;
设tot=0;
//i指添加到元组的最后一个元素的索引
//s指的是它的价值
//这里我们用i=-1初始化,这样第一个while循环就构建了一个“A”的等价物
let layer=[{i:-1,s:1}];
而(lv{
for(设i=u倍,i+1;i{

对于(设i=utuple.i+1;i我们可以避免复发

说出大小为
n的
A

根据你的公式,我们可以考虑

  • 我们从A:
    C\n^1
  • 我们从A:
    C\n^2
  • 我们从A:
    C\n^3
我们不必重新计算每个
k-utuple
(无序元组),只需保留前一层的
(k-1)-utuple
e、 让我们拿数组[1,2,3,4,5]

  • 第一层:
    1,2,3,4,5
  • 第二层:
    1-2
    1-3
    1-4
    1-5
    2-3
    2-4
    ,…,
    4-5
  • 第三层:
    1-2-{i}
    (i代表3到5),
    1-3-{i}
对于我们的例子:我们并不真正需要整个utuple:只需要它的最后一个idx和它的值(它的元素的乘积)

阿尔戈

function bonferroni(A, nlev){
    let lv = 0;
    let tot = 0;
    //i refers to the index of the last element added to the tuple
    //s refers to its value
    //here we initialize with i=-1 just so the first while loop builds an equivalent of "A"
    let layer = [{i:-1, s:1}];
    while(lv < nlev){
        let sum = 0;
        let next = [];
        layer.forEach(utuple=>{

            for(let i = utuple.i+1; i<A.length; ++i){
                let s = utuple.s * A[i];
                sum += s;
                next.push({i, s});
            }
        })
        layer = next;
        if((lv % 2)==0){
            tot += sum;
        }else{
            tot -= sum;
        }
        lv++;
    }
    return tot;
}
功能bonferroni(A,nlev){
设lv=0;
设tot=0;
//i指添加到元组的最后一个元素的索引
//s指的是它的价值
//这里我们用i=-1初始化,这样第一个while循环就构建了一个“A”的等价物
let layer=[{i:-1,s:1}];
而(lv{
for(设i=u倍,i+1;i{

对于(让i=utuple.i+1;我建议您阅读有关递归的内容,并在解决方案中实现递归函数代码是否有效?您是否有一些数据,如
probList
,以及可能缺少的其他信息和想要的结果?您可能希望删除JavaScript标记,因为这是一个通用程序
function bonferroni(A, nlev){
    let lv = 0;
    let tot = 0;
    //i refers to the index of the last element added to the tuple
    //s refers to its value
    //here we initialize with i=-1 just so the first while loop builds an equivalent of "A"
    let layer = [{i:-1, s:1}];
    while(lv < nlev){
        let sum = 0;
        let next = [];
        layer.forEach(utuple=>{

            for(let i = utuple.i+1; i<A.length; ++i){
                let s = utuple.s * A[i];
                sum += s;
                next.push({i, s});
            }
        })
        layer = next;
        if((lv % 2)==0){
            tot += sum;
        }else{
            tot -= sum;
        }
        lv++;
    }
    return tot;
}