2

My question is that is it possible to convert a vector which stores samples of original CDF (cumulative density function)...

something like this:

class normal
{
 public:

   float mean;
   float sigma;
   float variance = sigma * sigma;
   float left_margin = mean - 4 * sigma;
   float right_margin = mean + 4 * sigma;
   normal():mean(0), sigma(1){}
   normal(float m, float s):mean(m), sigma(s){}

   float cdf(float x); 
   float pdf(float x); 
};

float normal::pdf(float x)
{
   if (x < left_margin || x > right_margin)     return 0;

   float coefficient = 1 / (float)sqrt(2 * PI * variance);

   float x_mean = x - mean;
   float result = coefficient * exp(-(x_mean * x_mean) / 2 * variance);
   return result;
}

float normal::cdf(float x) 
{
   if (x <= left_margin)      return 0;
   if (x >= right_margin)     return 1;

   float x_mean = x - mean;
   float result = (float)(0.5 * (1 + erf((x_mean) / sqrt(2 * variance))));
   if (result > 1) return 1;
   else return result;
}

std::vector<float> discrete_normal_cdf(normal& X)
{
   std::vector<float> vec;

   float L = (float)(X.left_margin);
   float R = (float)(1.2 * X.right_margin);

   while (L <= R)
   {
      vec.push_back(X.cdf(L));
      L = (float)(L + 0.1);
   }   

   std::vector<float> tmp;
   // take three samples
   tmp.push_back(vec.at(1));    // first non_zero element
   tmp.push_back(vec.at(40));   // add element with value of 0.5
   tmp.push_back(vec.at(80));   // element with value of 0.99


   std::vector<float> cdf_v(5, 0);

   for (auto i = 0; i < tmp.size(); i++)
      cdf_v.push_back(tmp.at(i));

   int l = 0;
   while (l < 5)
   {
      cdf_v.push_back(1);
      l++;
   }
   return cdf_v;
}

In fact what I need is this: if we have a normal

 normal n1(5, 1);

take samples of its CDF to piece wise linear CDF:

 vector<float> foo = discrete_normal_cdf(n1); 

then reconstruct the piecewise linear CDF into normal

 normal function(foo)
 {
    return normal(5, 1);
 }

Is this function valid? I wrote a function which takes a vector as an input and search all the elements of the vector the for the value of 0.5 and returns the index of that element as the mean of the normal but it not always true.

normal vec2normal(vector<float>& vec)
{
     int mean;
     mean = std::find(vec.begin(), vec.end(), 0.5) - vec.begin();
     return normal(mean, 1);
}

I have no idea how to do this, so any suggestions will be appreciated thank you.

G. Sliepen
  • 7,637
  • 1
  • 15
  • 31
engineer1155
  • 36
  • 13
  • In your function signature, I found `std::vector discrete_normal_cdf(**delay&** X)`, but in the explanation you are passing an instance of `normal`. I did not get it. What is **delay** ? – JeJo Jun 11 '18 at 16:52
  • You could try to do a least-squares fit with respect to mean and stdev. – meowgoesthedog Jun 11 '18 at 19:40
  • @JeJo [link](https://www.ideone.com/IRDSRk) here is the code – engineer1155 Jun 12 '18 at 07:36
  • The result of your `discrete_normal_cdf` doesn't depend on the `mean` member of it's argument. It also gives a very poor representation for some `variance` members. [See here](http://coliru.stacked-crooked.com/a/8980ffac0cbe6eac). You are assuming that the index is the mean, which is nonsense. `std::map` is a much better representation of a function – Caleth Jun 12 '18 at 10:42
  • @Caleth yes you're right.but as i explained earlier to "JeJo" my final goal is to is to take two CDFs (vectors) and apply convolution on them. the resulting vector should be the same as the CDF(vector) of adding two normals. i.e. if we have 'n1(2, 1)' and 'n2(3, 1)' then add them the result will be 'N(5, 2)'. and my problem is we have 'v1 = d_n_cdf(n1)' and ' v2 = d_n_cdf(n2)' and then if convolution(v1, v2), we should get vector which is same vector extracted of 'd_n_cdf(N)' – engineer1155 Jun 12 '18 at 12:26
  • In other words all i want to say is convolution(v1, v2) and ADD(n1, n2) are functionally the same. and i want to check if these two operators are following the same shifting property or not. – engineer1155 Jun 12 '18 at 12:30
  • You should probably take `variance` as your second parameter of `normal::normal` (or [add variances](https://wikimedia.org/api/rest_v1/media/math/render/svg/62327e1d50b5344190d1f67cb8b8ac83469a714c), not sigmas) – Caleth Jun 12 '18 at 12:47
  • You still are losing information encoding a distiribution as a `std::vector`, and you would still be able to do a discrete convolution of two `std::map`s, for a sensible `decimal` type – Caleth Jun 12 '18 at 12:54
  • Remember that convolution is an operation on **functions** – Caleth Jun 12 '18 at 12:55
  • I'm thinking of associating time(tag) with elements of the vector. to be able to capture the time shifting due to conv – engineer1155 Jun 12 '18 at 13:02
  • @Caleth i've tried map for reconstruction like you say. and it works properly. thank you. my goal is to find the longest path of DAG with user defined weight structure. but with CONV as ADD function and MAX_CDF instead of MAX. – engineer1155 Jul 05 '18 at 08:37
  • @Caleth my problem is when i used the longest paths algorithm in main function the results are all good. but when i define the longest path function and call CONV and MAX_CDF in it some samples will be deleted. why is that? and how can i fix this? – engineer1155 Jul 05 '18 at 08:43
  • You use `std::upper_bound` to find the *interval* in which 0.5 falls, whether or not it appears as an element. – Davis Herring Oct 13 '18 at 22:38

0 Answers0