How to generate vector with different prob. distributions for each element - matlab

I need to generate vector r of N values 1-6 (they can be repetitive) to given permutation p of N elements. But the values are generated with some probability distribution depending on the i-th value of the permutation.
E.g. I have permutation p = [2 3 1 4] and probabilistic distribution matrix (Nx6): Pr = [1, 0, 0, 0, 0, 0; 0, 0.5, 0, 0.5, 0, 0; 0, 0, 0, 1, 0, 0; 0.2, 0.2, 0.2, 0.2, 0.2, 0]
i-th row represents prob. distribution of values 1-6 to element i in permutation p (its value, not position), sum of rows is 1.
For example, we can assign value 1 to value 1, value 2 or 4 to value 2 etc. So it can look like this: r = [2 4 1 2] or r = [4 4 1 5].
Currently I am using this code:
for i = 1:N
r(i) = randsample(1:6,1,true,Pr(p(i),:));
end
But it is quite slow and I am trying to avoid the for-cycle, maybe by function bsxfun or something similar.
Does anyone have any clue, please? :-)

A solution to your problem is basically available in this answer, everything needed for your case is replacing the vector prob with a matrix and fix all operations to work properly on matrices.
Pr=[1, 0, 0, 0, 0, 0; 0, 0.5, 0, 0.5, 0, 0; 0, 0, 0, 1, 0, 0; 0.2, 0.2, 0.2, 0.2, 0.2, 0];
p = [2 3 1 4];
prob=Pr(p,:);
r=rand(size(pPr,1),1);
x=sum(bsxfun(#ge,r,cumsum(padarray(prob,[0,1],'pre'),2)),2);

Related

Integer random matrix with different ranges in matlab

How can one create a random matrix (say B) which element B(i,j) is a uniform random integer number in the close interval 0 and A(i,j). A is a given matrix. For example:
A = [6, 2, 5, 7;
12, 0, 4, 0;
8, 0, 10, 1;
11, 6, 2, 5];
B = floor(rand(size(A)).*(A+1))
Explanation
rand(size(A)) creates a matrix of the same size as A, with elements uniformly distributed between 0 and 1.
rand(size(A)).*(A+1) each element (i, j) is a random distribution between 0 and A(i, j)+1
floor(rand(size(A)).*(A+1)) each unit width range is mapped to the nearest lower integer
Note that B = round(rand(size(A)).*A) will almost do the same, except that 0 and A(i, j) will have less probability to occur.

Generating an equal number of random integers in response to a previous input in Matlab

I'm trying to create a random number matrix in matlab. However, I'm struggling a little with the logic of some of it. What I want is this:
I need it to loop through a predefined random matrix (2 rows, n columns) 50% of which are 1's and 50% are 0's (I can already do this part). Everytime it encounters a 1 it should then enter another loop which puts a 1,2,3 or 4 in the corresponding position in the second row. However (and this is the part I'm struggling with) I need it to have an equal number of 1's, 2's, 3's and 4's in the second row. So for example:
The matrix n = [0, 1, 0, 1, 1, 1, 0, 0; 0,0,0,0,0,0,0,0] should run through the script and produce something like: n = [0, 1, 0, 1, 1, 1, 0, 0; 0, 1, 0, 3, 2, 4, 0, 0]
This is what I have so far:
function pureToneTimer
ptpschedule = [0, 1, 0, 1, 1, 1, 0, 0; 0, 0, 0, 0, 0 , 0, 0, 0]
a = 0;
b = 0;
c = 0;
d = 0;
x = length(ptpschedule)/4
for n = 1:length(ptpschedule)
if ptpschedule(1,n) == 1
while a < x && b < x && c < x && d < x
i = randi(4)
ptpschedule(2,n) = i;
switch i
case 1
a = a + 1;
case 2
b = b + 1;
case 3
c = c + 1;
case 4
d = d + 1;
end
end
end
end
assignin('caller', 'ptpschedule', ptpschedule)
end
Sorry if this turns out to be a really trivial question. I'm just struggling to wrap my head around it!
Thanks,
Martin
This does what you want:
V = 4; %// number of values you want. 4 in your example
ind = ptpschedule(1,:)>0; %// logical index of positive values in the first row
n = nnz(ind);
vals = mod(0:n-1, V)+1; %// values to be randomly thrown in.
%// This guarantees the same number of each value if n is a multiple of V
ptpschedule(2,ind) = vals(randperm(n)); %// fill values in second row in random order
If the number of 1's in the first row is a multiple of V, this generates each value 1, 2, ... V the same number of times in the second row.
Otherwise, some values in the second row will appear once more than other values.
Example:
ptpschedule = [0, 1, 0, 1, 1, 1, 0, 0
0, 0, 0, 0, 0, 0, 0, 0];
V = 4;
produces
ptpschedule =
0 1 0 1 1 1 0 0
0 3 0 4 2 1 0 0

Create a matrix according to a binary matrix

Here I got
A = [1, 2, 3]
B = [1, 0, 0, 1, 0, 1]
I want to create a matrix
C = [1, 0, 0, 2, 0, 3]
You can see B is like a mask, The number of ones in B is equal to the number of elements in A. What I want is arrange elements in A to the place where B is 1.
Any method without loop?
Untested, but should be close:
C = zeros(size(B));
C(logical(B)) = A;
This relies on logical indexing.

Intersection of matrices in matlab?

It is almost the same question as this one Matrices intersection!
The difference is this: If the intersection of the element (i, j) of all matrices is the same number then do not output -1 but output this number. An example is the following:
A1 = [2, 2, 0;
2, 2, 0;
0, 2, 0];
A2 = [2, 0, 4;
4, 3, 0;
0, 0, 1];
A3 = [2, 0, 0;
1, 0, 3;
3, 4, 3];
I want to get the follow matrix:
B = [2, 2, 4;
-1, -1, 3;
3, -1, -1];
Version 1
out1 = -1.*(A1~=A2).*(A1~=A3).*(A2~=A3)
max_mat = max(cat(3,A1,A2,A3),[],3)
out1(~out1) = max_mat(~out1)
Output
out1 =
2 2 4
-1 -1 3
3 -1 -1
Version 2: Maybe a faster version
Assumption - If out of the three elements in the corresponding positions across A1, A2 and A3, only two are same, then take the max of those three elements for the final matrix, B.
Code
%%// Concatenate all three A matrices
A=cat(3,A1,A2,A3,A1);
%%// Logical matrix with ones where all three elements are different from each other
out1 = -1.*all(diff(A,[],3)~=0,3)
%%// Get the max values, to be stored where -1 all three corresponding elements
%%// are not different from each other
max_mat = max(A,[],3)
%%// Get the final output
out1(~out1) = max_mat(~out1)
This produces the same output as the previous version.
Version 3
Assumption - If out of the three elements in the corresponding positions across A1, A2 and A3, only two are same, then take the element that is different from the other two for the final matrix, B.
Code
A=cat(3,A1,A2,A3,A1);
AA = A(:,:,1:3);
t1 = bsxfun(#ne,AA,mode(AA,3));
out1 = max(AA.*t1,[],3) + all(~t1,3).*A1;
out1(all(diff(A,[],3)~=0,3))=-1;
This produces the same output as the previous versions.
I would do this
A = A1+A2+A3;
B = (A1==A2)&(A1==A3);
C = (A1==0)+(A2==0)+(A3==0);
D = ones(3)*-1;
D(B==1) = A1(B==1);
D(C==2) = A(C==2);
B records the position of the elements whose number is same for all the matrices.
C records the position of the elements where two of the matrices have 0.
Then we can modify the elements of D, whose values are set -1 initially, using the information in matrices B and C.
A1 = [2, 2, 0;
2, 2, 0;
0, 2, 0];
A2 = [2, 0, 4;
4, 3, 0;
0, 0, 1];
A3 = [2, 0, 0;
1, 0, 3;
3, 4, 3];
A=cat(3,A1,A2,A3);
%identify all fields with identical values on the 3rd dimension
[X,Y]=find(sum(abs(diff(A,1,3)),3)==0);
%delete all but the first repetition, then use the previous code
A(X,Y,2:end)=0;
L=(sum(A~=0,3)>1);
L*-1+(1-L).*sum(A,3)
/update: Had to fix the code, now it should be correct.

DTMC Markov Chain - How to get the stationary vector

For a Discrete Time Markov Chain problem, i have the following:
1) Transition matrix:
0.6 0.4 0.0 0.0
0.0 0.4 0.6 0.0
0.0 0.0 0.8 0.2
1.0 0.0 0.0 0.0
2) Initial probability vector:
1.0 0.0 0.0 0.0
So, i wrote the following SciLab code to get to the stationary vector:
P = [0.6, 0.4, 0, 0; 0, 0.4, 0.6, 0; 0, 0, 0.8, 0.2; 1,0,0,0]
PI = [1,0,0,0]
R=PI*P
count=0;
for i = 1 : 35 // stationary vector is obtained at iteration 33, but i went futher to be sure
R=R*P;
count=count+1
disp("count = "+string(count))
end
PI // shows initial probability vector
P // shows transition matrix
R // shows the resulting stationary vector
After iteration number 33, the following resulting stationary vector is obtained:
0.2459016 0.1639344 0.4918033 0.0983607
What manual calculations do i have to perform in order to get to the stationary vector above without having to multiply the transition matrix 33 times then multiply the result by the initial vector?
I was told that the calculations are quite simple but i just could not realize what to do even after reading some books.
Of course explanations are welcome, but above all things i would like to have the exact answer for this specific case.
You can solve DTMC on Octave by using this short code:
P = [
0.6, 0.4, 0, 0;
0, 0.4, 0.6, 0;
0, 0, 0.8, 0.2;
1, 0, 0, 0
]
pis = [P' - eye(size(P)); ones(1, length(P))] \ [zeros(length(P), 1); 1]
Or with SAGE with this code:
P = matrix(RR, 4, [
[0.6, 0.4, 0, 0],
[ 0, 0.4, 0.6, 0],
[ 0, 0, 0.8, 0.2],
[ 1, 0, 0, 0]
])
I = matrix(4, 4, 1); # I; I.parent()
s0, s1, s2, s3 = var('s0, s1, s2, s3')
eqs = vector((s0, s1, s2, s3)) * (P-I); eqs[0]; eqs[1]; eqs[2]; eqs[3]
pis = solve([
eqs[0] == 0,
eqs[1] == 0,
eqs[2] == 0,
eqs[3] == 0,
s0+s1+s2+s3==1], s0, s1, s2, s3)
On both, the result of the steady state probabilities vector is:
pis =
0.245902
0.163934
0.491803
0.098361
I hope it helps.
WBR,
Albert.