On matlab, I have an adjacency matrix and using a function, I would like to find out how to plot a histogram showing the degrees of separation between 2 given nodes(up to 10).
As of now I only have a function that finds a node's neighbours. Basically it'll be similar to the notion of 6 degrees of separation, except with 10.
Thanks!
function n=neighbour(A,v)
global n;
for i=1:length(v)
a=find(A(:,v(i))+A(v(i),:)');
n=setdiff(a(:)',v(i));
end
end
In general, this is solved using the Floyd–Warshall algorithm, which computes the shortest paths between all pairs of nodes in a graph.
Since you're using Matlab and because the distance between any two connected nodes is always the same ("1 step"), you could use a trick that involves matrix multiplication: if you have an adjacency matrix A, then raising A to the Nth power gives you a new matrix that tells you how many paths of length N exist between each pair of nodes. So, in a loop, raise A to the 1st power, the 2nd power, etc, and note at which power each element becomes nonzero. The maximum path length is equal to the number of nodes, so you can stop there.
Scale-Free Network Visualization, including histogram of the degrees of separation can be found in this link, might be helpful...
Related
I am using the function findchangepts and use 'linear' which detects changes in mean and slope. How does it note a change? Is it by consecutive points until the next point has a different mean and slope?
Mathworks has the following explanation:
If x is a vector with N elements, then findchangepts partitions x into two regions, x(1:ipt-1) and x(ipt:N), that minimize the sum of the residual (squared) error of each region from its local mean.
How does the function get ipt?
Thanks in advance!
I am working with a single vector with N elements.
I am using the MATLAB function graphallshortestpaths to compute shortest paths between vertices of an undirected network. The undirected network is given as a weighted edge list file, which you can find here.
This is the MATLAB code that I use to compute the shortest paths:
A=load('genome_edge_list');
%Extract the edges
E=[A(:,1);A(:,2)];
%Extract the vertices
V=unique(E);
%N is the number of vertices
N=length(V);
%Take the inverse of the weights
A(:,3)=1./A(:,3);
%Create a sparse weighted adjacency matrix
B=sparse(A(:,1),A(:,2),A(:,3),N,N);
%Make B symmetric
B=sparse(full(B)+full(B)');
%Compute shortest paths
D=graphallshortestpaths(B,'directed',false);
Now, the matrix D that MATLAB gives as output is not symmetric. However, since the input to graphallshortestpaths is a symmetric matrix in sparse format, the output ought to be a symmetric matrix. So what am I doing wrong?
The only related question that I could find on mathworks is this question, however in that question the OP clearly is not giving a symmetric matrix as input, which explains why the matrix returned by MATLAB is not symmetric.
EDIT:
To see how far off D and D' are, I computed the following:
E=D';
C=D==E;
find(C==0)
this returns the following linear indices:
33133
543038
1363077
1398421
1398786
1399373
but the values of D and E at those indices are the same, e.g. D(33133)= 0.1024=E(33133). Now, if I take the difference of the two matrices, then I find that the difference at those indices is -1.0000e-05. It therefore seems to be a rounding error, as #beaker points out. However, as I write in my comment below, I don't understand how this can occur, as graphsallshortestpaths computes the distance between node i and j only once, so the values of D(i,j) and D(i,j) should be the result of the same computation.
Couple or remarks:
As #beaker mentioned in the comment, it could well be a numerical issue. I would be particularly weary of the line where you take the inverse and do A(:,3)=1./A(:,3);. Try to output some debug values and see if this inverse does what you intended.
On the line where you make B symmetric: are you sure you want to do full(b)' and not full(b).'? The first one takes the hermitian, the second the transpose!
Also on the same line where you make B symmetric: perhaps you are missing a 0.5 factor in there? So instead of B=sparse(full(B)+full(B)'); something like B=sparse((full(B)+full(B).').*0.5); (see this answer).
I also think you unintentionally wrote H instead of E on the second line, right?
So I was trying to spread one matrix elements, which were generated with poissrnd, to another with using some bigger (wider?) probability function (for example 100 different possibilities with different weights) to plot both of them and see if the fluctuations after spread went down. After seeing it doesn't work right (fluctuations got bigger) I tried to identify what I did wrong on a really simple example. After testing it for a really long time I still can't understand what's wrong. The example goes like this:
I generate vector with poissrnd and vector for spreading (filled with zeros at the start)
Each element from the poiss vector tells me how many numbers (0.1 of the element value) to generate from the possible options which are: [1,2,3] with corresponding weights [0.2,0.5,0.2]
I spread what I got to my another vector on 3 elements: the corresponding (k-th one), one bofore the corresponding one and one after the corresponding one (so for example if k=3, the elements should be spread like this: most should go into 3rd element of another vector, and rest should go to 2nd and 1st element)
Plot both 0.1*poiss vector and vector after spreading to compare if fluctuations went down
The way I generate weighted numbers is from this thread: Weighted random numbers in MATLAB
and this is the code I'm using:
clear all
clc
eta=0.1;
N=200;
fot=10000000;
ix=linspace(-100,100,N);
mn =poissrnd(fot/N, 1, N);
dataw=zeros(1,N);
a=1:3;
w=[.25,.5,.25];
for k=1:N
[~,R] = histc(rand(1,eta*mn(1,k)),cumsum([0;w(:)./sum(w)]));
R = a(R);
przydz=histc(R,a);
if (k>1) && (k<N)
dataw(1,k)=dataw(1,k)+przydz(1,2);
dataw(1,k-1)=dataw(1,k-1)+przydz(1,1);
dataw(1,k+1)=dataw(1,k+1)+przydz(1,3);
elseif k==1
dataw(1,k)=dataw(1,k)+przydz(1,2);
dataw(1,N)=dataw(1,N)+przydz(1,1);
dataw(1,k+1)=dataw(1,k+1)+przydz(1,3);
else
dataw(1,k)=dataw(1,k)+przydz(1,2);
dataw(1,k-1)=dataw(1,k-1)+przydz(1,1);
dataw(1,1)=dataw(1,1)+przydz(1,3);
end
end
plot(ix,eta*mn,'g',ix,dataw,'r')
The fluctuations are still bigger, and I can't identify what's wrong... Is the method for generating weighted numbers wrong in this situation? Cause it doesn't seem so. The way I'm accumulating data from the first vector seems fine too. Is there another way I could do it (so I could then optimize it for using 'bigger' probability functions)?
Sorry for my terrible English.
[EDIT]:
Here is simple pic to show what I meant (I hope it's understandable)
How about trying negative binomial distribution? It is often used as a hyper-dispersed analogue of Poisson distribution. Additional links can be found in this paper, as well as some apparatus in supplement.
Okay, so I'm working on a problem related to quantum chaos and one of the things I need to do is to map the unit cube in n-dimensions to a parallelepiped in n-dimensions and find all integer points in the interior of this parallelepiped. I have been trying to do this using the following scheme:
Given the linear map B and the dimension of the cube n, we find the coordinates of the corners of the unit hypercube by converting numbers j from 0 to (2^n -1) into their binary representation and turning them into vectors that describe the vertices of the cube.
The next step was to apply the map B to each of these vectors, which gives me a set of 2^n vectors describing the coordinates of the vertices of the parallelepiped in n dimensions
Now, we take the maximum and minimum value attained by any of these vertices in each coordinate direction, i.e the first element of my vectors might have a maximum value of 4 across all of the vertices and a minimum value of -3 etc. This gives me an n-dimensional rectangular prism that contains my parallelepiped and some extra unwanted space.
I now find all points with integer coordinates in this bounding rectangular prism described as vectors in n dimensions
Finally, I apply the inverse of the map B to each of the points and throw away any points that have any coefficients greater than 1 as they must originally have lain outside my unit hypercube.
My issue arises in step 4, I'm struggling to come up with a way of generating all vectors with integer coordinates in my rectangular hyper-prism such that I can change the number of dimensions n on the fly. Ideally, i'd like to be able to increase n at will until it becomes too computationally heavy to do so, but every method of finding all integer points in the prism i've tried so far has relied on n for loops to permute each element and thus I need to rewrite the code every time.
So I guess my question is this, is there any way to code this up so that I can change n on the fly? Also, any thoughts on the idea of the algorithm itself would be appreciated :) It wouldn't surprise me if i've overcomplicated things massively...
EDIT:
Of course as soon as I post the question I see a lovely little link in the side-bar where a clever method has been given already for how to do this: Generate a matrix containing all combinations of elements taken from n vectors
I'll leave this up for the moment just in case anyone has any comments on the method in general, but otherwise (since I can't upvote yet I'll just say it here) Luis Mendo, you are a hero!
Say, I have a cube of dimensions 1x1x1 spanning between coordinates (0,0,0) and (1,1,1). I want to generate a random set of points (assume 10 points) within this cube which are somewhat uniformly distributed (i.e. within certain minimum and maximum distance from each other and also not too close to the boundaries). How do I go about this without using loops? If this is not possible using vector/matrix operations then the solution with loops will also do.
Let me provide some more background details about my problem (This will help in terms of what I exactly need and why). I want to integrate a function, F(x,y,z), inside a polyhedron. I want to do it numerically as follows:
$F(x,y,z) = \sum_{i} F(x_i,y_i,z_i) \times V_i(x_i,y_i,z_i)$
Here, $F(x_i,y_i,z_i)$ is the value of function at point $(x_i,y_i,z_i)$ and $V_i$ is the weight. So to calculate the integral accurately, I need to identify set of random points which are not too close to each other or not too far from each other (Sorry but I myself don't know what this range is. I will be able to figure this out using parametric study only after I have a working code). Also, I need to do this for a 3D mesh which has multiple polyhedrons, hence I want to avoid loops to speed things out.
Check out this nice random vectors generator with fixed sum FEX file.
The code "generates m random n-element column vectors of values, [x1;x2;...;xn], each with a fixed sum, s, and subject to a restriction a<=xi<=b. The vectors are randomly and uniformly distributed in the n-1 dimensional space of solutions. This is accomplished by decomposing that space into a number of different types of simplexes (the many-dimensional generalizations of line segments, triangles, and tetrahedra.) The 'rand' function is used to distribute vectors within each simplex uniformly, and further calls on 'rand' serve to select different types of simplexes with probabilities proportional to their respective n-1 dimensional volumes. This algorithm does not perform any rejection of solutions - all are generated so as to already fit within the prescribed hypercube."
Use i=rand(3,10) where each column corresponds to one point, and each row corresponds to the coordinate in one axis (x,y,z)