How to create symmetric zero and one matrix - matlab

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

Related

Vector to matrix with row sum 1

I have a logical 1-by-n vector with sum m. Now, I need to convert it into a matrix m-by-n in a way that the row sum is equal 1.
vector (1-by-8) with sum 4
[0 1 0 0 1 0 1 1]
matrix (4-by-8) with row sum 1
[0 1 0 0 0 0 0 0;
0 0 0 0 1 0 0 0;
0 0 0 0 0 0 1 0;
0 0 0 0 0 0 0 1]
Is there a mathematically efficient way without calculating the sum, creating a empty matrix, loop through the vector and adding the 1s row by row?
I think that in that case, given your input, you don't even need to calculate the sum.
You can define an identity matrix of size n, then use your input vector to sample the required rows out of it:
I = eye(n);
y = I(x, :) ; % Output Matrix. x is the input vector
Here's another method, using sparse:
matrix = full(sparse(1:m, find(vector), 1, m, n));

How can I create a modified identity matrix?

I have an identity matrix in MATLAB which is used in some regression analysis for joint hypothesis tests. However, when I change the linear restrictions for my tests, I can no longer rely on the identity matrix.
To give a simple example, here is some code which produces an identity matrix depending on the value of y:
for i = [1, 2, 4]
y = i
x = 5;
H = eye(y*x)
end
However, what I need is not the identity matrix, but the first two rows and all others to be zero.
For the first example, the code produces an eye(5):
H =
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
I need something that given y does not produce the identity but in fact produces:
H =
1 0 0 0 0
0 1 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
Can I adjust the identity matrix to include zeroes only after the first two rows?
I think the simplest solution is to make a matrix of all zeroes and then just place the two ones by linear indexing:
H = zeros(x*y);
H([1 x*y+2]) = 1;
Generalizing the above to putting the first N ones along the diagonal:
H = zeros(x*y);
H(x*y.*(0:(N-1))+(1:N)) = 1;
As suggested in this comment you can use diag:
diag([ones(2,1); zeros(x*y-2,1)])
This works because diag makes a vector become the main diagonal of a square matrix, so you can simply feed it the diagonal vector, which is your case would be 2 1s and the rest 0s.
Of course if you need a variable amount of 1s, which I was in doubt about hence the comment,
n=2;
diag([ones(n,1); zeros(x*y-n,1)])
Here are some alternatives:
Use blkdiag to diagonally concatenate an identity matrix and a zero matrix:
y = 5; x = 2;
H = blkdiag(eye(x), zeros(y-x));
A more exotic approach is to use element-wise comparisons with singleton expansion and exploit the fact that two NaN's are not equal to each other:
y = 5; x = 2;
H = [1:x NaN(1,y-x)];
H = double(bsxfun(#eq, H, H.'))

How to produce random symmetric matrix given the number of vertices?

Is there a simple way to produce a random matrix of 0's and 1's, that is symmetric across the diagonal (with only zeros in the diagonal), given the number of vertices?
Example:
somefunction(3) = [ 0 1 1;
1 0 0;
1 0 0];
somefunction(4) = [ 0 1 1 1;
1 0 0 1;
1 0 0 1;
1 1 1 0];
You can generate a random matrix and extract lower triangular part of it then do OR with its transpose:
n = 4;
a=tril(randi(0:1,n),-1);
result = a|a.';

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

Finding lengths of 0's separating islands of 1's and assigning them

I have a vector with alternating 0's and 1's and would like to convert each "1" to the length of the zeros that precede it. For example, I have x and would like to get to y:
x = [0 0 1 0 0 0 0 1 0 0 0 1 1 0 0 1]
y = [0 0 2 0 0 0 0 4 0 0 0 3 0 0 0 2]
I would really appreciate any suggestions on how to achieve this.
One approach with find & diff -
%// Initialize array, y with zeros and of length same as input, x
y = zeros(size(x))
%// Find places/indices where new values would be put
idx = find(x)
%// Calculate new values which would be the differentiated values of indices
%// and subtracted by 1 to account for the number of zeros in between two
%// non-zero values. We need to concatenate the indices array with one zero
%// at the start to account for the starting non-zero value in x
y(idx) = diff([0 idx])-1