Right now I am trying to implement the formula for the probabilities of a Poisson binomial distribution.
The formula is the last one in that section, with complex exponentials inside them:
I have a very simple code that should do it, but it is outputting wrong probabilities.
#include <iostream>
#include <complex>
#include <cmath>
using namespace std;
int main(int argc, char const *argv[]) {
int N=5; //number of coins
double probabilities[N]={0.1,0.1,0.1,0.1,0.1}; //probabilities of coin landing head
double distr[N+1];
for (int j=0; j<N+1;j++){
complex<double> temp1=0.0 + 0.0i;
for (int k=0; k<N+1;k++){
for(int l=0;l<N+1;l++){
complex<double> temp2=1.0 + 0.0i;
for (int m=0;m<N;m++){
temp2=temp2*(1.0+0.0i+(exp(l*2*M_PI*1.0i/(double(N)+1.0))-1.0+0.0i)*probabilities[m]);
}
temp2=temp2*exp(l*k*2*M_PI*1.0i/(double(N)+1.0));
temp1=temp1+temp2/(double(N)+1.0);
}
}
distr[j]=real(temp1);
}
for (int i=0;i<N+1;i++){
cout<< distr[i] << ' ';
}
The output of this code is [1,1,1,1,1,1], which is definitely not correct. I am thinking that maybe I have not been working correctly with complex numbers, but I do not see where I did something wrong. It is frustrating that such a simple program does not work :(.
From the code it is clear that temp1
does not depend on j
, hence you get the same numbers, the sum over k
. After you remove the outer loop over j
and write distr[k] = real(temp1);
and fix the sign in exp(l*k*...)
, you'll get the expected result:
0.59049 0.32805 0.0729 0.0081 0.00045 1e-05
Full code with some simplifications:
int main() {
using namespace std::literals::complex_literals;
constexpr int N = 5;
const double probabilities[N] = {.1, .1, .1, .1, .1};
const auto c = std::exp(2i * M_PI / (N + 1.));
double distr[N + 1];
for (int k = 0; k <= N; ++k) {
auto sum = std::complex<double>(0);
for(int l = 0; l <= N; ++l) {
auto prod = std::complex<double>(1);
for (int m = 0; m < N; ++m)
prod *= 1. + (std::pow(c, l) - 1.) * probabilities[m];
sum += prod * std::pow(c, -l * k) / (N + 1.);
}
distr[k] = std::real(sum);
}
for (auto d : distr)
std::cout << d << ' ';
}