Search code examples
matlabmatrixsparse-matrixprogrammatically-createdstochastic

Add programmatically random values to a matrix using matlab


I am new to Matlab and I am trying to create programmatically a square Matrix which may have some random stochastic columns but I can't come up with a working solution. By stochastic column I mean the sum of the column elements which are positive should be equal to 1 (the column non-zero elements should be the same and their sum equal to 1). The position of the non-zero elements is not important in the matrix. PS: some columns could be all-zero elements and some could be with only one non-zero element, in this case 1.

I need your guidance or an example of working code on this guys. Thanks in advance.

Here is an example:

A=
0.2500    0.5000         0         0         0         0         0
0.2500    0.5000    0.3333         0         0         0         0
     0         0    0.3333    0.2500         0         0    0.3333
0.2500         0         0    0.2500         0    0.5000         0
0.2500         0         0    0.2500         0         0         0
     0         0         0    0.2500         0    0.5000    0.3333
     0         0    0.3333         0         0         0    0.3333

% here is my code but it's not doing the work yet
n = 5;
A = zeros(n, 5); 
i = 0;
for i = 1:n
  if rand < 0.5
    i = i + 1;
    A(i, :) = rand(1, 5);
  end
end
A = A(1:i, :)

Solution

  • First generate a random floating point matrix and threshold as you have done. Once you threshold this, simply sum along each column, then divide every column by the sum. Broadcasting will be useful here so that you avoid having to loop through or replicate the summed values per column over all rows.

    Something like this should work:

    n = 7;
    A = rand(n, n) >= 0.5;
    sumA = sum(A, 1);
    A = bsxfun(@rdivide, A, sumA);
    
    % Or in MATLAB R2016b and up:
    % A = A ./ sumA;
    
    A(isnan(A)) = 0;
    

    The first two lines are self-explanatory. Choose n, then create a n x n square matrix of random 0s and 1s. The third line finds the sum of each column, and the fourth line which is the pièce de resistance is taking the sum of each column and doing an internal replication so that you create a temporary matrix that is the same size as the random matrix, but each column contains the total sum for that column. You then divide element wise and that produces your result. This is achieved with the bsxfun function. The last line of code is very important. Supposing that you have a column where there are no 1s. This means that when it's time to normalize, we will encounter a 0 / 0 error which translates to NaN. The last line of code finds any values that are NaN and sets them to 0.

    Alternatively in MATLAB R2016b and up, you can simply do the element-wise division operator ./ and it does the broadcasting already.

    Example Run

    After running the above code, this is one potential result:

    >> A
    
    A =
    
        0.2500    0.5000         0    0.2500         0         0         0
             0         0    0.2500    0.2500    1.0000         0         0
             0         0         0    0.2500         0    0.2500    0.3333
        0.2500         0         0    0.2500         0    0.2500         0
        0.2500    0.5000    0.2500         0         0    0.2500         0
             0         0    0.2500         0         0    0.2500    0.3333
        0.2500         0    0.2500         0         0         0    0.3333
    

    What about all zero columns?

    To ensure that the code works for all zero columns, simply make the threshold when you create the random matrix more aggressive. Make it higher, like 0.8 or so. This means that there's a higher chance that you will get a 0 than a 1.

    Therefore, I changed the second line of code to:

     A = rand(n, n) >= 0.8;
    

    When I did this and ran the code again, this is what I get for one run:

    >> A
    A =
    
             0         0         0    0.2500         0    0.5000         0
             0    0.5000    1.0000    0.2500         0    0.5000         0
             0         0         0         0    1.0000         0    1.0000
             0    0.5000         0         0         0         0         0
             0         0         0         0         0         0         0
             0         0         0    0.2500         0         0         0
             0         0         0    0.2500         0         0         0