How to move larger values close to matrix diagonal in a correlation matrix - matlab

I have a correlation matrix X of five elements(C1,C2,C3,C4,C5)
C1 C2 C3 C4 C5
C1 * 1 0 1 0
C2 1 * 0 0 1
C3 0 0 * 1 1
C4 1 0 1 * 0
C5 0 1 1 0 *
I want to use MatLab to move as many as non-zero cells close to diagonal, while keep the diagonal cells are "*".
For example, you may notice that the columns and rows is shifting in the following matrix, while the diagonal cells are "*".
C1 C4 C2 C5 C3
C1 * 1 1 0 0
C4 1 * 0 0 1
C2 1 0 * 1 0
C5 0 0 1 * 1
C3 0 1 0 1 *
Because I want to do clustering, so I want as many as non-zero cells get close to diagonal after shifting. It's an NP-hard problem.
Anyone know what functions in MatLab can realize this?

What you're looking for is probably the reverse Cuthill-McKee algorithm (RCM), which pretty much does what you want: for a given matrix it finds a permutation that tends to have its non-zero elements closer to the diagonal. There's a built-in function symrcm in MATLAB that does just that.
So assuming that X is your matrix, you can do the following:
p = symrcm(X);
Xnew = X(p, p);
Xnew is the new reordered matrix, and p is the new row/column order.
Example
Let's create a matrix first:
X = [10 0 0 7 0; 3 20 0 0 11; 0 0 30 0 29; 12 7 0 40 0; 0 33 0 0 50]
Now let's reorder it:
p = symrcm(X);
Xnew = X(p, p)
The result is:
Xnew =
40 12 7 0 0
7 10 0 0 0
0 3 20 11 0
0 0 33 50 0
0 0 0 29 30
Seems right.

A = [1 0 0 1 0;
0 1 0 0 1;
0 0 1 0 1;
1 1 0 1 0;
0 1 0 0 1];
N = length(A);
switched = false;
%%
% Calculate initial Global Energy
disp(A);
global_energy = 0;
for l = 1:N
for m = 1:N
if(A(l,m))
global_energy = global_energy + (l-m)^2/2;
end
end
end
disp(global_energy);
counter = 0;
counter_cutoff = 10000000000;
while(true)
switched = false;
counter = counter + 1;
for i = 1:N
for j = i+1:N
current_metric = 0; % Calculate metric of row i and j with columns i and j
permuted_metric = 0; % Calculate metric if they were permuted
% Row i
for k = 1:N
if(k ~= i && k ~= j && A(i,k))
current_metric = current_metric + (i-k)^2/2;
permuted_metric = permuted_metric + (j-k)^2/2;
end
end
% Row j
for k = 1:N
if(k ~= i && k ~= j && A(j,k))
current_metric = current_metric + (j-k)^2/2;
permuted_metric = permuted_metric + (i-k)^2/2;
end
end
% Col i
for k = 1:N
if(k ~= i && k ~= j && A(k,i))
current_metric = current_metric + (i-k)^2/2;
permuted_metric = permuted_metric + (j-k)^2/2;
end
end
% Col j
for k = 1:N
if(k ~= i && k ~= j && A(k,j))
current_metric = current_metric + (j-k)^2/2;
permuted_metric = permuted_metric + (i-k)^2/2;
end
end
% If permuted metric is less, swap columns and rows - set switched to true
if(permuted_metric < current_metric)
switched = true; % there was at least one switch
% Now switch rows and columns
% Switch columns first
A(:,[i j]) = A(:,[j i]);
% Now switch rows
A([i j],:) = A([j i],:);
end
end
end
if(~switched || counter > counter_cutoff)
% All permutations did not lead to a switching of rows and columns
break;
end
end
% Calculate final Global Energy
disp(A);
global_energy = 0;
for l = 1:N
for m = 1:N
if(A(l,m))
global_energy = global_energy + (l-m)^2/2;
end
end
end
disp(global_energy);
Terminal:
1 0 0 1 0
0 1 0 0 1
0 0 1 0 1
1 1 0 1 0
0 1 0 0 1
22
1 1 0 0 0
1 1 1 0 0
0 0 1 1 0
0 0 1 1 0
0 0 0 1 1
3

Related

How to create this particular fractal pattern in MATLAB?

I need to make an array of zeros and ones in this particular fractal pattern:
0 0 0 0 0 1 0 0 0 0 0 0
0 0 1 1 1 1 1 1 1 0 0 0
0 1 0 0 0 1 0 0 0 1 0 0
0 1 0 0 1 1 1 0 0 1 0 0
0 1 0 1 0 1 0 1 0 1 0 0
1 1 1 1 1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1 0 1 0 0
0 1 0 0 1 1 1 0 0 1 0 0
0 1 0 0 0 1 0 0 0 1 0 0
0 0 1 1 1 1 1 1 1 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0
The actual array should be 100 x 100. The pattern should start from the middle (x,y) coordinate, and expand to look like the pattern (using loops).
So far, I have only managed to make a pattern that looks like a '+' sign. I am not sure how to continue it.
This is my code so far:
n = zeros(16); % using 16x16 array for practice
x = length(n)/2;
y = length(n)/2;
z = length(n) - 1;
xso = length(n)/2; % x axis south movement
xno = length(n)/2; % x axis north movement
yea = length(n)/2; % y axis east movement
ywe = length(n)/2; % y axis west movement
for i = 1:1:z
newyea = move('east', x, yea);
n(x, newyea) = 1;
yea = newyea;
newywe = move('west', x, ywe);
n(x, newywe) = 1;
ywe = newywe;
newxso = move('south', xso, y);
n(newxso, y) = 1;
xso = newxso;
newxno = move('north', xno, y);
n(newxno, y) = 1;
xno = newxno;
end
I also have a user defined function:
function newval = move(dir, x, y)
switch dir
case 'east'
newval = y + 1;
case 'west'
newval = y - 1;
case 'south'
newval = x + 1;
case 'north'
newval = x - 1;
end
Since there were no restrictions given on the appearance of the loop, I would propose the below solution. But, before, let's have a look at your given example:
Either you should restrict the desired dimension d to be odd, i.e. d = 11, 13, 15, ... or you should specify, how the pattern should be continued in case of an even dimension d, like here d = 12. For my solution, I decided to rely on the dimension d to be odd.
Here's the code:
d = 15; % Dimension
A = zeros(d); % Initialize output array A
c = (d + 1) / 2; % Calculate center index (row, column)
A(:, c) = 1; % Add: Cross
A(c, :) = 1;
J = 0; % Auxiliary index
for I = (c+2):2:d % For every second row (or column) from center to border
J = J + 1;
l = 4 * J - 1; % Calculate length of line to draw
s = c - (l-1)/2; % Calculate start point of line
e = c + (l-1)/2; % Calculate end point of line
A(I, s:e) = 1; % Add: "South" line
A(s:e, I) = 1; % Add: "East" line
A(c - 2*J, s:e) = 1; % Add: "North" line
A(s:e, c - 2*J) = 1; % Add: "West" line
end
figure(1); % Show image
imagesc(A);
Output for d = 15 (to compare to given example):
Output for d = 99:
Hope that helps!
If you have some more stricter limitations on the for loop, let me/us know. Then, I will try to modify my code accordingly.

How to fix up the error in matrix dimensions in MATLAB R2016b

I am working on a MATLAB code that involves deep learning using neural networks.
The image or the data is being fed in the form of matrices.
But I am getting an error "Matrix dimensions must agree".
Can Someone please help me with this problem?
I tried to solve this problem by using .* in stead of matrix multiplication * but the method didn't work.
Function Deeplearningoriginal:
function [w1,w2,w3,w4] = Deeplearningoriginal(w1,w2,w3,w4,input_Image,correct_output)
alpha=0.01;
N=5;
for k = 1:N
input_Image = reshape( input_Image( :, :,k ),25 ,1);
input_of_hidden_layer1 = w1* input_Image;
output_of_hidden_layer1 = ReLU(input_of_hidden_layer1);
input_of_hidden_layer2 = w2* output_of_hidden_layer1;
output_of_hidden_layer2 = ReLU( input_of_hidden_layer2);
input_of_hidden_layer3 = w3* output_of_hidden_layer2;
output_of_hidden_layer3 = ReLU(input_of_hidden_layer3);
input_of_output_node = w4* output_of_hidden_layer3;
final_output = Softmax(input_of_output_node);
correct_output_transpose = correct_output(k,:);
error = correct_output_transpose - final_output;
delta4 = error;
error_of_hidden_layer3 = w4'* delta4;
delta3 = (input_of_hidden_layer3>0).*error_of_hidden_layer3;
error_of_hidden_layer2 = w3'* delta3;
delta2 = (input_of_hidden_layer2>0).* error_of_hidden_layer2;
error_of_hidden_layer1 = w2'*delta2;
delta1 = (input_of_hidden_layer1>0).* error_of_hidden_layer1;
adjustment_of_w4 = alpha*delta4*output_of_hidden_layer3';
adjustment_of_w3 = alpha*delta3*output_of_hidden_layer2';
adjustment_of_w2 = alpha*delta2*output_of_hidden_layer1';
adjustment_of_w1 = alpha*delta1*reshaped_input_image';
w1 = w1 + adjustment_of_w1;
w2 = w2 + adjustment_of_w2;
w3 = w3 + adjustment_of_w3;
w4 = w4 + adjustment_of_w4;
end
end
Training network:
input_Image = zeros (5,5,5);
input_Image(:,:,1) = [ 1 0 0 1 1;
1 1 0 1 1;
1 1 0 1 1;
1 1 0 1 1;
1 0 0 0 1;
];
input_Image(:,:,2) = [ 0 0 0 0 1;
1 1 1 1 0;
1 0 0 0 1;
0 1 1 1 1;
0 0 0 0 0;
];
input_Image(:,:,3) = [ 0 0 0 0 1;
1 1 0 0 1;
1 0 1 0 1;
0 0 0 0 0;
1 1 1 0 1;
];
input_Image(:,:,4) = [ 1 1 1 0 1;
1 1 0 0 1;
1 0 1 0 1;
0 0 0 0 0;
1 1 1 0 1;
];
input_Image(:,:,5) = [ 0 0 0 0 0;
0 1 1 1 1;
0 0 0 0 1;
1 1 1 1 0;
0 0 0 0 1;
];
correct_output = [ 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;
];
w1 = 2* rand(20,25) -1;
w2 = 2* rand(20,20) -1;
w3 = 2* rand(20,20) -1;
w4 = 2* rand(5,20) -1;
for epoch = 1:100
[w1,w2,w3,w4] = Deeplearningoriginal(w1,w2,w3,w4,input_Image,correct_output);
end
I expected this code to run but because of the error I am not able to proceed.
The problem is the reshape (actually, two problems). After the
input_image = reshape(input_image(:,:,k), 25,1);
input_image is an array with 25 rows and 1 column, whereas w2, w3, and w4 have only 20 columns. To do the matrix multiplication A*B, A must have as many columns as B has rows.
The other problem with the reshape as written is that after the first pass through the loop, input_image is no longer a 5x5x5 array, it is a 25x1 array that contains only the elements of input_image(:,:,1). It is necessary to use a different name on the left-hand-side of the assignment (and throughout the rest of the loop) to avoid loosing the content of input_image.
Hope this helps,
JAC

Generating discrete signal on Matlab

I am trying to generate a constant signal x[n] = 1 for n = 1, 2, 3 and x[n] = 0 otherwise using matlab.
N = -5:1:5;
X = -5:1:5;
i = 1;
for n = N
if (n >= 1 && n <= 3)
X[i] = 1;
else
X[i] = 0;
end
i = i + 1;
end
But it does not work. I am really new using Matlab for discrete signals, so any help would be welcome.
Thank you.
There is no need to use a for iteration in this case. You can accomplish the same using an indexed approach as follows:
N1 = -5:5;
X1 = zeros(1,numel(N1));
X1(N1 >= 1 & N1 <= 3) = 1
N2 = -8:2;
X2 = zeros(1,numel(N2));
X2(N2 >= 1 & N2 <= 3) = 1
N3 = 1:11;
X3 = zeros(1,numel(N3));
X3(N3 >= 1 & N3 <= 3) = 1
This will output:
X1 =
0 0 0 0 0 0 1 1 1 0 0
X2 =
0 0 0 0 0 0 0 0 0 1 1
X3 =
1 1 1 0 0 0 0 0 0 0 0

Filling up gaps in matrix's rows

Let g be a matrix containing ones\zeroes. I want to fill up gaps of zeros (complete ones sequences) in the rows of g which are smaller then a given k.
For example fill up with ones all gaps smaller then three zeros. This code will work:
[m,n]=size(g);
k=3
for i=1:m
j=1
while (j<n)
if(g(i,j)==0)
flag=0;
for w=1:k
if(g(i,j+w-1)==1)
flag=1;
end
end
if(flag)
for w=1:k
g(i,j+w-1)=1;
end
else
while(~flag&j<n)
j=j+1;
if(g(i,j)==1)
flag=1;
end
end
end
end
j=j+1;
end
end
Is there a way to do so without all the for loops?
A short version using some built-in function:
M = [1 1 1 1 1
1 1 1 0 0
1 1 1 0 1
1 1 0 0 0
0 1 1 1 1]
Mopen = ~imopen(~padarray(M,[0,1],1),strel('line',3,0));
Mfill = Mopen(:,2:end-1);
A vectorized version:
k = 3;
d = diff( g,1,2);
L = d ~= 0;
c = cumsum([zeros(size(g,1),1) L],2)+1;
b = bsxfun(#plus, c, cumsum([0; c(1:end-1,end)]));
a =accumarray(reshape(b.',[],1),1);
f= find(a<k);
g(ismember(b,f) & g==0) = 1;
Example :
g =
1 1 1 1 1
1 1 1 0 0
1 1 1 0 1
1 1 0 0 0
0 1 1 1 1
result =
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 0 0 0
1 1 1 1 1
Another potential solution is to cast each row to a char array and then perform substitutions based on a regular expressions
g = round(rand(30,70));
figure();
subplot(121);
imagesc(g)
[m,n]=size(g);
k=3;
pattern = ['(?<!',char(0),')(',char(0),'{1,',num2str(k-1),'})(?!',char(0),')'];
for i=1:m
[matchstart,matchend] = regexp(char(g(i,:)),pattern);
for j = 1:length(matchstart)
g(i,matchstart(j):matchend(j)) = 1;
end
end
subplot(122);
imagesc(g)

How to make a parity check matrix from non-systematic to systematic in Matlab? thanks

I am trying to make a parity check matrix from non-systematic to systematic. Hence, I am attaching my code below. Somewhat it is correct, but there are some problems. It would be really great if someone could help me in this.
Subject: Information theory and coding. I am working on LDPC coding and decoding. Please check the code below
MATLAB CODE:
H = [1 0 1 1 0; 0 0 1 0 1; 1 0 0 1 0; 1 0 1 1 1]
[m,n] = size(H);
k = n-m;
for i = k+1:n
%H(:,i)
ind = find(H(:,i),1,'last');
% exchanging (ind)th row and (i-k)th row
if ind < i-k
continue;
end
if ind ~= i-k
temp = H(ind,:);
H(ind,:) = H(i-k,:);
H(i-k,:) = temp;
end
I = find(H(:,i));
% Guassian elimination
for j = 1:length(I)
if I(j) ~= i-k
H(I(j),:) = mod(H(I(j),:)+H(i-k,:),2);
end
end
end
Hsys = H
For e.g.
This is my H matrix:
H =
1 0 1 1 0
0 0 1 0 1
1 0 0 1 0
1 0 1 1 1
I want to have an identity matrix inside the matrix. The dimension on H matrix here is (mxn) which is (4x5).
Generally we use Gaussian elimination method to make the Identity matrix.hence, we make operations between rows. This is how we make it systematic.
I should have matrix as this in the result:
Hsys =
0 1 0 0 0
0 0 1 0 0
1 0 0 1 0
0 0 0 0 1
I should have an identity matrix of dimension m.
Here is how I'd do it (using Gauss-Jordan elimination):
% Not your matrix since it does not have any ones in the second column.
H=[1 1 0 1 1 0 0 1 0 0;
0 1 1 0 1 1 1 0 0 0;
0 0 0 1 0 0 0 1 1 1;
1 1 0 0 0 1 1 0 1 0;
0 0 1 0 0 1 0 1 0 1];
rows = size(H, 1);
cols = size(H, 2);
r = 1;
for c = cols - rows + 1:cols
if H(r,c) == 0
% Swap needed
for r2 = r + 1:rows
if H(r2,c) ~= 0
tmp = H(r, :);
H(r, :) = H(r2, :);
H(r2, :) = tmp;
end
end
end
% Ups...
if H(r,c) == 0
error('H is singular');
end
% Forward substitute
for r2 = r + 1:rows
if H(r2, c) == 1
H(r2, :) = xor(H(r2, :), H(r, :));
end
end
% Back Substitution
for r2 = 1:r - 1
if H(r2, c) == 1
H(r2, :) = xor(H(r2, :), H(r, :));
end
end
% Next row
r = r + 1;
end