tags:

views:

64

answers:

2

Hi all, I want to generate a matrix of NxN to test some code that I have where each row contains floats as the elements and has to add up to 1 (i.e. a row with a set of probabilities).

Where it gets tricky is that I want to make sure that randomly some of the elements should be 0 (in fact most of the elements should be 0 except for some random ones to be the probabilities). I need the probabilities to be 1/m where m is the number of elements that are not 0 within a single row. I tried to think of ways to output this, but essentially I would need this stored in a C++ array. So even if I output to a file I would still have the issue of not having it in array as I need it. At the end of it all I need that array because I want to generate a Market Matrix file. I found an implementation in C++ to take an array and convert it to the market matrix file, so this is what I am basing my findings on. My input for the rest of the code takes in this market matrix file so I need that to be the primary form of output. The language does not matter, I just want to generate the file at the end (I found a way mmwrite and mmread in python as well)

Please help, I am stuck and not really sure how to implement this.

+2  A: 
import random

N = 10

matrix = []

for j in range(N):
        t = [int(random.random()<0.6)  for i in range(N)]
        ones = t.count(1)
        row = [float(x)/ones for x in t] if ones else t
        matrix.append(row)

for r in matrix:
        print r
TheMachineCharmer
You need to change that line to `row = [float(x)/ones for x in t] if ones else t` lest you crash one in 0.6^N times.
Charles Merriam
I mean crash with a probablity of 0.6^N. Oops.
Charles Merriam
Thanks Charles! I was aware of the problem but couldn't come up with a clean solution like yours ;) Done now.
TheMachineCharmer
It's still not entirely a clean solution, since the question says each row "has to add up to one". This is logically inconsistent with each element independently taking the value 0 with non-zero probability. The spec needs to say what it means by 'random' in the phrase "randomly some of the elements should be 0". If the required distribution can't be nailed down, you could maybe select one element at random to set to 1 in the case where you get all 0s.
Steve Jessop
What my assumption is that we are using really good random number generator and N is very big. So, it is highly unlikely to get a row with all zeros. But you are right @Steve highly unlikely doesn't make things impossible ;)
TheMachineCharmer
If you're ignoring the risk of all zeros, then you don't need `if ones else t`. If you're not ignoring it, then returning an invalid row may or may not be better than division by zero. Fail early, and all that :-)
Steve Jessop
With all zeros it will fail to meet the condition that each row must sum to 1. But we need `if ones else t` to take care of `float(x)/ones` which will throw divide by zero exception.
TheMachineCharmer
A: 

By C++ array, do you mean a C array or a STL vector<vector< > >? The latter would be cleaner, but here's an example using C arrays:

#include <stdlib.h>
#include <stdio.h>

float* makeProbabilityMatrix(int N, float zeroProbability)
{
   float* matrix = (float*)malloc(N*N*sizeof(float));

   for (int ii = 0; ii < N; ii++)
   {
      int m = 0;
      for (int jj = 0; jj < N; jj++)
      {
         int val = (rand() / (RAND_MAX*1.0) < zeroProbability) ? 0 : 1;
         matrix[ii*N+jj] = val;
         m += val;
      }
      for (int jj = 0; jj < N; jj++)
      {
         matrix[ii*N+jj] /= m;
      }
   }

   return matrix;
}

int main() 
{
   srand(234);
   int N = 10;

   float* matrix = makeProbabilityMatrix(N, 0.70);

   for (int ii = 0; ii < N; ii++)
   {      
      for (int jj = 0; jj < N; jj++)
      {
         printf("%.2f ", matrix[ii*N+jj]);
      }
      printf("\n");
   }

   free(matrix);

   return 0;
};

Output:

0.00 0.20 0.20 0.00 0.00 0.00 0.00 0.20 0.20 0.20 
0.25 0.00 0.00 0.00 0.00 0.25 0.00 0.25 0.25 0.00 
0.00 0.33 0.33 0.33 0.00 0.00 0.00 0.00 0.00 0.00 
0.00 0.00 0.00 0.00 0.00 0.50 0.00 0.00 0.50 0.00 
0.25 0.25 0.00 0.00 0.00 0.00 0.25 0.00 0.25 0.00 
0.00 0.25 0.00 0.00 0.00 0.25 0.25 0.00 0.25 0.00 
0.00 0.00 0.33 0.00 0.33 0.00 0.00 0.00 0.33 0.00 
0.00 0.20 0.20 0.20 0.20 0.00 0.00 0.20 0.00 0.00 
0.20 0.00 0.20 0.00 0.00 0.00 0.00 0.20 0.20 0.20 
0.00 0.00 0.00 0.00 0.00 0.50 0.00 0.50 0.00 0.00 
Dewb
Boy, that Python implementation sure is tidier, isn't it?
Dewb