Matlab+ Graph theory+ specific weight assignment - matlab

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

Related

How to fix the plot of the symbolic eigenvalues of the 1st matrix (matlab)?

I'm calculating the eigenvalues of a 8x8-matrix including a symbolic variable "W". Plotting the 8 eigenvalues as functions of W returns a strange result in the plot which looks like someone rode his bike over my diagram.
For the 2nd matrix, where I just set some off-diagonal elements equal to 0, everything works fine. But I don't know what the problem with the 1st one is.
syms W;
w0=1/780;
wl=1/1064;
h=1; % for now this seems unnecessary, but I want to change this value later on
% This is the 1st matrix which causes some strange plotting results
A=h*[w0+3*wl 2*W 0 0 0 sqrt(3)*W 0 0;
2*W 4*wl 0 0 0 0 0 0;
0 0 2*wl+w0 sqrt(3)*W 0 0 0 sqrt(2)*W;
0 0 sqrt(3)*W 3*wl 0 0 0 0;
0 0 0 0 wl+w0 sqrt(2)*W 0 0;
sqrt(3)*W 0 0 0 sqrt(2)*W 2*wl 0 0;
0 0 0 0 0 0 w0 W;
0 0 sqrt(2)*W 0 0 0 W wl];
% This is the 2nd matrix for which everything is working fine
B=h*[w0+3*wl 2*W 0 0 0 0 0 0;
2*W 4*wl 0 0 0 0 0 0;
0 0 2*wl+w0 sqrt(3)*W 0 0 0 0;
0 0 sqrt(3)*W 3*wl 0 0 0 0;
0 0 0 0 wl+w0 sqrt(2)*W 0 0;
0 0 0 0 sqrt(2)*W 2*wl 0 0;
0 0 0 0 0 0 w0 W;
0 0 0 0 0 0 W wl];
X = eig(A);
X2 = eig(B);
eva22 = X2(1);
eva1 = X(1);
figure(1);
fplot(X2,[-0.002 0.002]);
hold on;
fplot(X,[-0.002 0.002]);
hold off;
xlabel('Rabi frequency [THz]','FontSize',11);
ylabel('dressed states','FontSize',11);
grid on;
box on;
I'm expecting the plot for matrix A to just be similar to the plot of matrix B, but somehow it doesn't work properly. I'd appreciate some tips and tricks how to fix this.
The second plot looks like that because the eigenvalues of B are imaginary. When using plot(), it plots the real part of complex numbers by default, but apparently fplot() doesn't. You can do fplot(real(X), [-0.002 0.002]) instead to plot just the real part of the eigenvalues (assuming that's what you want).

randomly select histogram data MATLAB

I have an input 2D histogram that I want to do 2-fold cross-validation with. The problem is I don't know how to extract two mutually exclusive random samples of the data from a histogram. If it was a couple of lists of the positional information of each data point, that would be easy - shuffle the data in the lists in the same way, and split the lists equally.
So for a list I would do this:
list1 = [1,2,3,3,5,6,1];
list2 = [1,3,6,6,5,2,1];
idx = randperm(length(list1)); % ie. idx = [4 3 1 5 6 2 7]
shlist1 = list1(idx); % shlist1 = [3,3,1,5,6,2,1]
shlist2 = list2(idx); % shlist2 = [6,6,1,5,2,3,1]
slist1 = shlist1(1:3); % slist1 = [3,3,1]
elist1 = shlist1(4:6); % elist1 = [5,6,2,1]
slist2 = shlist2(1:3); % slist2 = [6,6,1]
elist2 = shlist2(4:6); % elist2 = [5,2,3,1]
But if this same data was presented to me as a histogram
hist = [2 0 0 0 0 0]
[0 0 0 0 0 1]
[0 1 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 1 0]
[0 0 2 0 0 0]
I want the result to be something like this
hist1 = [0 0 0 0 0 0]
[0 0 0 0 0 1]
[0 1 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 1 0 0 0]
hist2 = [2 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 1 0]
[0 0 1 0 0 0]
so that different halves of the data are randomly, and equally assigned to two new histograms.
Would this be equivalent to taking a random integer height of each bin hist(i,j), and adding that to the equivalent bin in hist1(i,j), and the difference to hist2(i,j)?
% hist as shown above
hist1 = zeros(6);
hist2 = zeros(6);
for i = 1:length(hist(:,1))*length(hist(1,:))
randNum = rand;
hist1(i) = round(hist(i)*randNum);
hist2(i) = hist(i) - hist1(i);
end
And if that is equivalent, is there a better way/built-in way of doing it?
My actual histogram is 300x300 bins, and contains about 6,000,000 data points, and it needs to be fast.
Thanks for any help :)
EDIT:
The suggested bit of code I made is not equivalent to taking a random sample of positional points from a list, as it does not maintain the overall probability density function of the data.
Halving the histograms should be fine for my 6,000,000 points, but I was hoping for a method that would still work for few points.
You can use rand or randi to generate two histograms. The first method is more efficient however the second is more random.
h = [[2 0 0 0 0 0]
[0 0 0 0 0 1]
[0 1 0 0 0 0]
[0 0 0 0 0 0]
[0 0 0 0 1 0]
[0 0 2 0 0 0]];
%using rand
h1 = round(rand(size(h)).*h);
h2 = h - h1;
%using randi
h1 = zeros(size(h));
for k = 1:numel(h)
h1(k) = randi([0 h(k)]);
end
h2 = h - h1;
Suppose H is your 2D histogram. The following code extracts a single random index with a probability proportional to the count at that index - which I think is what you want.
cc = cumsum(H(:));
if cc(1) ~= 0
cc = [0; cc];
end
m = cc(end);
ix = find(cc > m*rand, 1);
To extract multiple samples, you need to write your own find function (preferably a binary search for efficiency) that extracts some n number of samples in one call. This will give you a vector of indices (call it ix_vec) chosen with probability proportional to the Histogram count at each index.
Then if we denote by X the numerical values corresponding to each location in the Histogram, your random sample is:
R1 = X(ix_vec);
Repeat for the second random sample set.

How to address positions of marks from simple matrix data in the boxes between axis lines?

What is the simplest way to create the following plot in Matlab from the data of the matrix "positions" containing the value 1 for black marks and - 1 for white marks?
positions=[0 1 0 0 0 0; 0 -1 0 0 0 0; 0 1 0 0 0 0; 1 -1 1 1 -1 0]
There you go:
% //Data
positions = [0 1 0 0 0 0; 0 -1 0 0 0 0; 0 1 0 0 0 0; 1 -1 1 1 -1 0];
S = 50; %// circle size. Adjust manually
%// Preparation
[M N] = size(positions);
hold on
%// Plot filled circles
[ip jp] = find(flipud(positions)>0);
plot(jp-.5,ip-.5,'ko','markersize',S,'markerfacecolor','k')
%// Plot empty circles
[in jn] = find(flipud(positions)<0);
plot(jn-.5,in-.5,'ko','markersize',S)
%// Plot grid lines
plot([0 N],(1:M).'*[1 1],'k');
plot((1:N).'*[1 1],[0 M],'k');
%// Set tick labels
set(gca,'xtick',.5:N,'ytick',.5:M)
set(gca,'xticklabel',char((1:N).'+'A'-1),'yticklabel',char((1:M).'+'0'))
%// Set axis size and aspect
axis equal
axis([0 N 0 M])
set(gca,'ticklength',[0 0]) %// no visible ticks

Plot the density of a matrix

Good day,
In Matlab I have got a matrix which is very sparse. Now I would like to plot the 'density' of the matrix. Let's say I have a matrix A:
A = [3 0 0
0 2 0
0 0 1];
Now the plot should look something like:
x
x
x
So there should be a dot (or something else) at each location (row, column) in which matrix A has got a nonzero value.
Any ideas?
spy is what you need:
% taken from MatLab documentation
B = bucky;
spy(B)
Consider something like this:
subs = zeros(0,2);
for ind = [find(A)']
[r,c] = ind2sub(size(A), ind);
subs = [subs; [r,c]];
end
scatter(subs(:,2), subs(:,1));
set(gca,'YDir','Reverse')
xlim([1 size(A,2)])
ylim([1 size(A,1)])
Which, for the matrix A:
0 1 0 1 1
0 0 0 0 0
0 1 0 0 0
0 1 0 1 1
0 0 1 1 0
Gives you the following scatter plot:
What about this :
A=[3 0 0; 0 2 0; 0 0 1];
imagesc(A)

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)