Cell manipulation (swapping, combining and converting to an array)

12 views (last 30 days)
First assume that we have this matrix
[ 9 -2 0]
A= [-2 9 -2]
[ 0 -2 9]
The goal is to store all the non-zero elements of A and its associated column index (col_ind). However for every row I want to store the value of the diagonal first.
So the end result is something like this:
val= [9 -2 9 -2 -2 9 -2]
col_ind= [1 2 2 1 3 3 2]
My approach is to first store the col_ind and val in a 1x3 cell.
{val} = [9;-2] [-2;9;-2] [-2;9]
{col_ind}= [1,2] [0,0,1,2,3] [0,0,0,0,0,2,3]
Issue 1: How do I get rid of the zeroes in
[0,0,1,2,3] [0,0,0,0,0,2,3] and get this
{col_ind}= [1,2] [1,2,3] [2,3]
From this, I can swap the elements in doubles in {val} so that 9 is always the leading entry for each.
Issue 2: How do I swap the entries in each double and also make sure that the column indices are swapped appropriately such that I will get this:
{val} = [9;-2] [9;-2;-2] [9;-2]
{col_ind}= [1,2] [2,1,3] [3,2]
How can the function sort be used in this case?
Issue 3: How do I merge the cells together to finally have this, an array of:
col_ind = [1 2 2 1 3 3 2]
Here is my code so far:
clear all
%Consider a 3x3 matrix
A= [ 9 -2 0; -2 9 -2; 0 -2 9];
%initialise arrays:
n = 3.0;
CI = zeros(1,1); %column index
V = zeros(1,1); %value in the matrix
index = 1.0;
counter=zeros(n,1);
val=cell(1,n);
col_ind = cell(1,n);
for t=1:n
val{t}=V;
col_ind{t}=V;
end
for k = 1:n %row 1 to n
for j = 1:n %column 1 to n
if A(k,j)~=0
%CI(index)=j;
col_ind{k}(index)=j;
%V(index)=A(k,j);
index = index + 1.0;
end
val{k}= nonzeros(A(k,:));
end
end

Accepted Answer

Stephen23
Stephen23 on 8 Feb 2017
Edited: Stephen23 on 8 Feb 2017
Here is one simple solution that works by sorting the diagonal elements of A to come first:
S = size(A);
R = repmat((1:S(1)).',1,S(2));
C = repmat((1:S(2)) ,S(1),1);
[~,C] = sort(C-Inf*eye(S),2);
B = A(sub2ind(S,R,C)).';
C = C.';
The matrix B is A transposed (because MATLAB works along columns, so this is easier), and with the diagonal elements moved to the top. This makes is trivial to get the non-zero elements:
>> B(B~=0) % non-zero values, diagonal first.
ans =
9
-2
9
-2
-2
9
-2
>> C(B~=0) % the corresponding column indices
ans =
1
2
2
1
3
3
2
  3 Comments
Stephen23
Stephen23 on 9 Feb 2017
Edited: Stephen23 on 9 Feb 2017
Have a look at C-Inf*eye(S):
>> C-Inf*eye(S)
ans =
-Inf 2 3
2 -Inf 1
3 3 -Inf
This is just the columns C with -Inf along the diagonal (note putting zero along the diagonal would also work). This allows sort to rearrange each row so that the diagonal comes first: -Inf come before 1, no? And also before 2 ?
C and R are matrices of the column and row indices: these are used to rearrange A with the diagonal values shifted to the front of each row. We need to generate R separately because sort only returns the indices along the dimension that it sorted along (across the columns, along rows). We thus have use to use sub2ind to get the corresponding linear indices from the column and row indices, which are then applied directly to A, thus giving B as a reordered version of A. Then extracting the non-zero elements in trivial with some indexing.

Sign in to comment.

More Answers (1)

Guillaume
Guillaume on 8 Feb 2017
Another option, assuming that there's always a non-zero value on the diagonal (or the whole row is 0):
[col_ind, row_ind, val] = find(A');
rowstart = find(diff([0; row_ind]) ==1); %find location of 1st element of row
diagidx = find(col_ind == row_ind); %find location of diagonal element
col_ind([rowstart; diagidx]) = col_ind([rowstart; diagidx]); %and swap
val([rowstart; diagidx]) = val([rowstart; diagidx]); %and swap in val as well
Note that the above swap the diagonal with the 1st non-zero element of the row (in both val and col_ind). It does not move the diagonal first while keeping the order of the rest of the elements of the row (i.e. it goes from [1 2 3 d 5 6 7] to [d 2 3 1 5 6 7], not [d 1 2 3 5 6 7]). You did not say anything about the order of the other elements, so I assumed it's not an issue.

Categories

Find more on Matrices and Arrays in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!