Time series in Finite State Space Markov chain - matlab

I have state transition probability matrix for state K=8,
trans =
0.9245 0.0755 0 0 0 0 0 0
0.0176 0.9399 0.0425 0 0 0 0 0
0 0.0290 0.9263 0.0447 0 0 0 0
0 0 0.0465 0.9228 0.0307 0 0 0
0 0 0 0.0731 0.8979 0.0290 0 0
0 0 0 0 0.0907 0.8857 0.0236 0
0 0 0 0 0 0.1080 0.8750 0.0170
0 0 0 0 0 0 0.1250 0.8750
I need to generate time vector/time series from the transition matrix using Matlab. Can anyone suggest me on how to generate the time series from this state transition probability matrix in Matlab.

If by generate you mean sample from the transition matrix this should work:
function [chain,state] = simulate_markov(x,P,pi0,T);
%% x = the quantity corresponding to each state, typical element x(i)
%% P = Markov transition matrix, typical element p(i,j) i,j=1,...n
%% pi0 = probability distribution over initial state
%% T = number of periods to simulate
%%
%% chain = sequence of realizations from the simulation
%% Modification of progam by L&S.
n = length(x); %% what is the size of the state vector?
E = rand(T,1); %% T-vector of draws from independent uniform [0,1]
cumsumP = P*triu(ones(size(P)));
%% creates a matrix whose rows are the cumulative sums of
%% the rows of P
%%%%% SET INITIAL STATE USING pi0
E0 = rand(1,1);
ppi0 = [0,cumsum(pi0)];
s0 = ((E0<=ppi0(2:n+1)).*(E0>ppi0(1:n)))';
s = s0;
%%%%% ITERATE ON THE CHAIN
for t=1:T,
state(:,t) = s;
ppi = [0,s'*cumsumP];
s = ((E(t)<=ppi(2:n+1)).*(E(t)>ppi(1:n)))';
end
chain = x'*state;
Source : http://www-scf.usc.edu/~ngarnold/Markov%20Chains%20Notes.pdf

Related

Replace repeated value based on sequence size - Matlab

I have a 2D matrix composed of ones and zeros.
mat = [0 0 0 0 1 1 1 0 0
1 1 1 1 1 0 0 1 0
0 0 1 0 1 1 0 0 1];
I need to find all consecutive repetitions of ones in each row and replace all ones with zeros only when the sequence size is smaller than 5 (5 consecutive ones):
mat = [0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0];
Any suggestion on how to approach this problem would be very welcome.
You can use diff to find the start and end points of the runs of 1, and some logic based on that to zero out the runs which are too short. Please see the below code with associated comments
% Input matrix of 0s and 1s
mat = [0 0 0 0 1 1 1 0 0
1 1 1 1 1 0 0 1 0
0 0 1 0 1 1 0 0 1];
% Minimum run length of 1s to keep
N = 5;
% Get the start and end points of the runs of 1. Add in values from the
% original matrix to ensure that start and end points are always paired
d = [mat(:,1),diff(mat,1,2),-mat(:,end)];
% Find those start and end points. Use the transpose during the find to
% flip rows/cols and search row-wise relative to input matrix.
[cs,r] = find(d.'>0.5); % Start points
[ce,~] = find(d.'<-0.5); % End points
c = [cs, ce]; % Column number array for start/end
idx = diff(c,1,2) < N; % From column number, check run length vs N
% Loop over the runs which didn't satisfy the threshold and zero them
for ii = find(idx.')
mat(r(ii),c(ii,1):c(ii,2)-1) = 0;
end
If you want to throw legibility out of the window, this can be condensed for a slightly faster and denser version, based on the exact same logic:
[c,r] = find([mat(:,1),diff(mat,1,2),-mat(:,end)].'); % find run start/end points
for ii = 1:2:numel(c) % Loop over runs
if c(ii+1)-c(ii) < N % Check if run exceeds threshold length
mat(r(ii),c(ii):c(ii+1)-1) = 0; % Zero the run if not
end
end
The vectorized solution by #Wolfie is nice and concise, but a bit hard to understand and far from the wording of the problem. Here is a direct translation of the problem using loops. It has the advantage of being easier to understand and is slightly faster with less memory allocations, which means it will work for huge inputs.
[m,n] = size(mat);
for i = 1:m
j = 1;
while j <= n
seqSum = 1;
if mat(i,j) == 1
for k = j+1:n
if mat(i,k) == 1
seqSum = seqSum + 1;
else
break
end
end
if seqSum < 5
mat(i,j:j+seqSum-1) = 0;
end
end
j = j + seqSum;
end
end

How to vary the values in the matrix according to z axis value in matlab

I created random connectivity information matrix. From that I have plotted x,y and z axis points in 3D graph .Now I just want to apply the zaxis values in the corresponding connectivity such that where ever 1 is present in connectivity it should be multiplied by corresponding zaxis values (eg: if in conn matrix (1,3)place =1 then it should take particular zaxis values and multiply). But I getting the same values for all the places. Suggestions.
%Conncectivity Matrix
success = 0;
n = input('Enter the No. of Nodes'); %size of matrix
k = input('Enter the max connectivity'); %maximal number of 1s
p = 0.5;
Result_Matrix = zeros(n,n);
while (success == 0)
Result_Matrix = (rand(n,n) < p);
Result_Matrix(logical(eye(n))) = 0;
Result_Matrix = max(Result_Matrix, Result_Matrix');
s = sum(Result_Matrix,1);
success = 1;
if min(s) == 0
success = 0; p = p*2; % too few 1s, increase p
end
if max(s) > k
success = 0; p = p/2; % too many 1s, decrease p
end
end
m=Result_Matrix;
conn_mat=m;
disp('connection matrix');
disp(m);
[r,c] = find(m);
A = [r,c]
%3D-GRAPH
PlotSizex=100;
PlotSizey=100;
PlotSizez=-100;
x=PlotSizex*rand(1,n)
y=PlotSizey*rand(1,n)
z=PlotSizez*rand(1,n)
plot3(x(A).', y(A).',z(A).', 'O-')
%Zaxis values multiply with Connectivity
d=zeros(n,n);
z % values of zaxis
for i=1:n
for j=i+1:n
d(i,j)= z(i);
d(j,i)=d(i,j);
end
end
New matrix= d.*m %d is zaxis values and m is connectivity matrix.
I do obtain different values in new_matrix:
new_matrix =
0 -63.4303 -63.4303 0 0
-63.4303 0 0 -23.9408 0
-63.4303 0 0 -24.5725 0
0 -23.9408 -24.5725 0 -76.5436
0 0 0 -76.5436 0
My connection matrix is:
connection matrix
0 1 1 0 0
1 0 0 1 0
1 0 0 1 0
0 1 1 0 1
0 0 0 1 0
and z values are:
z =
-63.4303 -23.9408 -24.5725 -76.5436 -86.3677
I find it strange to multiply the elements in your connection matrix with a single z value, because each element in the connection matrix is related to two points in space (and thus two z values). So, it would make more sense to use the following:
for i=1:n
for j=i:n
d(i,j)= z(i)*z(j); % or another combination of z(i) and z(j)
d(j,i)=d(i,j);
end
end

How to create symmetric zero and one matrix

I need to create a 100*100 symmetric matrix that has random distribution of zeros and ones, but the diagonal should be all zeros, how can I do that?
This is one way to do it:
N = 100; % size of square matrix
p = 0.5; % probability of 0s
A = triu(rand(N)>p, 1); % matrix of 0s and 1s (upper triangular part)
A = A + A'; % now it is symmetric
You can use a uniform distribution to generate your random numbers:
n = 100;
a = round(rand(n,n));
Now set the diagonal entries to zero (as discussed here by Jonas):
a(logical(eye(size(a)))) = 0;
Symmetric component:
aSym = floor((a + a')/2);
Example for n = 5:
aSym =
0 0 0 0 0
0 0 1 0 1
0 1 0 0 1
0 0 0 0 0
0 1 1 0 0
Edit: At randomatlabuser's suggestion, added line to calc the symmetric component of the matrix and eliminated loop to zero out entries on the diagonal

index exceeding matrix dimentions

I was trying to get this low order recursive function in matlab. i want to calculate the probability of status of a site at next time step, given that I have the initial probability of that being a status.
P= Probability
x= status(0,1)
Dij= probability to pick a site
P(Status of Site(i) being x at next time step)= Summation[P(Status of Site(i) being x at previous time step)*Dij]
and this is what I have done! but my index always exceeds matrix dimensions! I need help with this.
clear all;
clc;
%function [t,i]= CopyingInfluenceModel
%%Define constants
%% generate some random weights vectori.e. the transition matrix=C
% C=[0 (1,2) 0 (1,4) 0 0 0;
% (2,1) 0 (2,3) 0 0 0 0;
% 0 (3,2) 0 (3,4) 0 0 0;
% (1,4) 0 (4,3) 0 (4,5) 0 0;
% 0 0 0 (5,4) 0 (5,6) (5,7);
% 0 0 0 0 (6,5) 0 (6,7);
% 0 0 0 0 (7,5) (7,6) 0];
%copying probabilities=branch weights
onetwo=0.47;
twothree=0.47;
threefour=0.47;
onefour=0.47;
fourfive=0.023;
fivesix=0.47;
fiveseven=0.47;
sixseven=0.47;
selfweight1=0.06;
selfweight2=0.037;
% SourceNodes - a list of Nodes that are forced to be kept in one side of the cut.
% WeightedGraph - symetric matrix of edge weights. Wi,j is the edge
% connecting Nodes i,j use Wi,j=0 or Wi,j == inf to indicate unconnected Nodes
WeightedGraph=[0 onetwo 0 onefour 0 0 0;
onetwo 0 twothree 0 0 0 0;
0 twothree 0 threefour 0 0 0;
onefour 0 threefour 0 fourfive 0 0;
0 0 0 fourfive 0 fivesix fiveseven;
0 0 0 0 fivesix 0 sixseven;
0 0 0 0 fiveseven sixseven 0];
Dij=sparse(WeightedGraph);
% Initializing the variables
t=[];
i=[];
%assigining the initial conditions
t(1)=0;
p(1)= 0.003; %% initial probability of status
%set index no i to 1(initial condition for i=1)
i=1;
%repeating calculating new probabilities
%% If the probability is zero, terminate while loop
while p(i)>=0
%calculate at the next time step for given index no
t(i+1)= t(i);
%calculate the status_probability at given time t=(i+1)
[p(i+1)]=[p(i)]+sum([p(i)]*[Dij(i)]);
[NextStatus(i)]= [p(i+1)]
%index i increases by 1 to calculate next probability
i=i+1;
end
Stack Trace is:
%%??? Index exceeds matrix dimensions.
%%Error in ==> CopyingInfluenceModel at 54
%%[p(i+1)]=[p(i)]+sum([p(i)]*[Dij(i)]);
The problem is Dij not p. Dij has a fixed length so when i exceeds that the program throws an error.
Added:
I can't really see your logic in the code, but I have a strong feeling that you are calculating something wrong. Dij is a 7 x 7 matrix but you treat it as a vector by calling Dij(i). If you are trying to multiply something by a row or column, you need the Dij(i,:) or Dij(:, i) notation.
The logic as you posted it doesn't work, essentially, p(i+i) isn't defined yet. There are a few ways to do it, depending on if you want to keep p or not. I'll post a method that keeps p around, but some work could be done to make the code more efficient.
p=[p;p(i)+sum(p(i)*Dij(i))];
NextStatus(i)= p(i+1)

Matlab+ Graph theory+ specific weight assignment

I want to assign weights to the edges such that the Sum of (the weights coming to a node) and its own weight add to one.
here is what I tried:
clear all;
close all;
clc;
%% building the graph
g=graph;
for k=1:6
add(g,k,k+1)
add(g,1,4)
add(g,5,7)
end
%%assigining the statuses 0 and 1
%label(g,1,'0');
%label(g,2,'1');
%label(g,3,'1');
%label(g,4,'1');
%label(g,5,'1');
%label(g,6,'0');
%label(g,7,'0');
figure,ldraw(g);
%x=rand(1,1);
%y=rand(1,1)
%% get line info from the figure
lineH = findobj(gca, 'type', 'line');
xData = cell2mat(get(lineH, 'xdata')); % get x-data
yData = cell2mat(get(lineH, 'ydata')); % get y-data
%% if an edge is between (x1,y1)<->(x2,y2), place a label at
%%the center of the line, i.e. (x1+x2)/2 (y1+y2)/2 etc
labelposx=mean(xData');
labelposy=mean(yData');
%% generate some random weights vectori.e. the probability matrix
weights=rand(1,1,length(labelposx))
% plot the weights on top of the figure
text(labelposx,labelposy,mat2cell(weights), 'HorizontalAlignment','center',...
'BackgroundColor',[.7 .9 .7]);
%%Transition matrix or markov matrix
% Transition=[0 (1,2) 0 (1,4) 0 0 0;
% (2,1) 0 (2,3) 0 0 0 0;
% 0 (3,2) 0 (3,4) 0 0 0;
% 0 0 (4,3) 0 (4,5) 0 0;
% 0 0 0 (5,4) 0 (5,6) (5,7);
% 0 0 0 0 (6,5) 0 (6,7);
% 0 0 0 0 (7,5) (7,6) 0];
Transition= [0 weights(:,:,8) 0 weights(:,:,6) 0 0 0;
weights(:,:,8) 0 weights(:,:,7) 0 0 0 0;
0 weights(:,:,7) 0 weights(:,:,5) 0 0 0;
weights(:,:,6) 0 weights(:,:,5) 0 weights(:,:,4) 0 0;
0 0 0 weights(:,:,4) 0 weights(:,:,3) weights(:,:,2);
0 0 0 0 weights(:,:,3) 0 weights(:,:,1);
0 0 0 0 weights(:,:,2) weights(:,:,1) 0]
%set_matrix
%%dij-- Probability matrix
sparse(Transition);
d=[weights(:,:,8);weights(:,:,7);weights(:,:,5);weights(:,:,4);
weights(:,:,3);weights(:,:,1);weights(:,:,1)]
%%Si[k]-- matrix of the statuses(labels)
%S=[0 1 1 1 1 0 0]
For eg: The addition of weights coming to node four, plus its own weight should be equal to 1
Check out this nice random vectors generator with fixed sum FEX file. I think this will answer your question.
see also more on this SO link Non biased return a list of n random positive numbers (>=0) so that their sum == total_sum