I'm quite new to programming so am looking for some experts to nudge me in the right direction as I complete this exercise.
I have used horzcat and vertcat to manually do this but I'm asking if anyone knows a simpler way.
Matrix 1 is 18x18 and indexed horizontally starting at 1.
Matrix 1 is at the centre and represents a discrete space. Matrix 2,3,4,5,6,7,8,9 are replicates of matrix 1, also represent discrete spaces and are located right, lower right, below, lower left, left, top left, above and top right.
Matrix 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 are also replicates of matrix one and surround Matrix 2 to 9. The matrices built together form a pattern as below. Each matrix is itself a discrete unit.
If you define the number of matrices you require, so let's say in this case '49' or '4 steps from matrix 1' (a person can jump from 1, 9, 25, 49 on a diagonal or 1, 8, 23,46 on a straight line), how do I build the matrices in this pattern?
43 44 45 46 47 48 49
42 21 22 23 24 25 26
41 20 7 8 9 10 27
40 19 6 1 2 11 28
39 18 5 4 3 12 29
38 17 16 15 14 13 30
37 36 35 34 33 32 31
If I demonstrate this diagrammatically, I hope I can express my problem better.
So the first ring is this:
7 8 9
6 1 2
5 4 3
the second ring is this:
21 22 23 24 25
20 7 8 9 10
19 6 1 2 11
18 5 4 3 12
17 16 15 14 13
the third ring is
43 44 45 46 47 48 49
42 21 22 23 24 25 26
41 20 7 8 9 10 27
40 19 6 1 2 11 28
39 18 5 4 3 12 29
38 17 16 15 14 13 30
37 36 35 34 33 32 31
and so on. I'd like to be able to continue this pattern infinitely.
What is the best way to do this in Matlab?
I apologise for my lack of clarity and need to express my problem better. All your comments are very useful in showing me how to write a proper problem.
Many thanks for your help guys. Just joined this forum as the support here is exceptional.
If all your matrices are truly copies ("replicates") of the initial one (call it mat18), for your nth step you could just call
largemat=repmat(mat18, 2*n+1, 2*n+1);
e.g.
largemat=repmat(mat18, 7,7);
to produce the matrix you described in your example. As Clement says, this creates the large matrix directly, not by expanding an existing one.
Update 2
If your matrices are different, for example you have 49 matrices stored in a cell array mymatrices{1}, mymatrices{2}, ... mymatrices{49}, you would start by
largemat{1}=mymatrices{1};
Now to calculate the next largemat{n+1} from mymatrices and largemat{n}, you need to add the next mymatrices "around" the largemat{n}. largemat{n} already contains the first m^2 matrices with m=2*n+1, so you will need mymatrices{(m^2+1):((m+2)^2)} and arrange them correctly:
and then in each step enlarge it
largemat{n+1} = [ largemat{n} cell2mat(mymatrices(m^2+(1:m))')]; %# add to the right
largemat{n+1} = [ largemat{n+1} ; cell2mat(mymatrices(m^2+m+(m+1:-1:1)))]; %# add at bottom
largemat{n+1} = [ cell2mat(mymatrices(m^2+2*m+1+(m+1:-1:1))') largemat{n+1}]; %# add at right
largemat{n+1} = [ cell2mat(mymatrices(m^2+3*m+2+(1:m+2))) ; largemat{n+1}]; %# add at top
To test this code, lets use simple numbers for your submatrices:
mymatrices=mat2cell(1:49,1,ones(1,49));
Now we can run the above code in a loop, printing intermediate results to check:
largemat{1}=mymatrices{1};
for n=1:3
m=2*n-1;
largemat{n+1} = [ largemat{n} cell2mat(mymatrices(m^2+(1:m))')]; %# add to the right
largemat{n+1} = [ largemat{n+1} ; cell2mat(mymatrices(m^2+m+(m+1:-1:1)))]; %# add at bottom
largemat{n+1} = [ cell2mat(mymatrices(m^2+2*m+1+(m+1:-1:1))') largemat{n+1}]; %# add at right
largemat{n+1} = [ cell2mat(mymatrices(m^2+3*m+2+(1:m+2))) ; largemat{n+1}]; %# add at top
largemat{n+1}
end
which prints
ans =
7 8 9
6 1 2
5 4 3
ans =
21 22 23 24 25
20 7 8 9 10
19 6 1 2 11
18 5 4 3 12
17 16 15 14 13
ans =
43 44 45 46 47 48 49
42 21 22 23 24 25 26
41 20 7 8 9 10 27
40 19 6 1 2 11 28
39 18 5 4 3 12 29
38 17 16 15 14 13 30
37 36 35 34 33 32 31
To test it also works for nonscalar input matrices, use
mymatrices=cell(1,49);
for i=1:49,mymatrices{i}=rand(9,9),end;
as input, which doesn't crash... even though I haven't checked manually that the resulting matrix is correct ;-).
It's probably simpler to write a function that generate all your matrix for a given number of layers instead of trying to expand an existing matrix with a new layer.
Related
I have and time sequence: lines are channels, columns are time points, say
x = [1 2 3 4 5 6 7 8; 9 10 11 12 13 14 15 16; 17 18 19 20 21 22 23 24 ; 25 26 27 28 29 30 31 32]
x =
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
I have an index of a specific points in time when I want to compute mean for the x
y = [4 5 6]
y =
4 5 6
How can I get a 3D array out of x with +- 2 points around and average thrue 3d dimation? In over words, I need to average
3 4 5 4 5 6 5 6 7
11 12 13 and 12 13 14 and 13 14 15
19 20 21 20 21 22 21 22 23
27 28 29 28 29 39 29 30 31
for each entrance.
Since the mean is of all the rows, just get the 3 chunks (1 before, the index, and 1 after) and calculate the mean value. I didn't use the mean function since will calculate the mean of each column. Instead of that, I just add the 3 chunks and divide them by 3.
% Get the x values
x = [1 2 3 4 5 6 7 8;...
9 10 11 12 13 14 15 16;...
17 18 19 20 21 22 23 24 ;...
25 26 27 28 29 30 31 32]
% Define the idx
idx = [4 5 6]
% Get the mean matrix. It is the mean of 1 column before
% the idx and 1 column after. Since there are 3, divided by 3.
% 1 before index 1 after
MeanMatrix = (x(:,idx-1)+x(:,idx)+x(:,idx+1))./3
The best approach i think would be to loop over the array something like this:
result = [];
for i = 1:length(y)
result = [result, mean(x(1:height(x),y(i)-1:y(i)+1), 'all')];
end
Here, we are just splitting it into the chunks you want using indexing then computing the mean over the entire selected chunk.
In MATLAB, we can use im2col and col2im to transform from columns to blocks and back, for example
>> A = floor(30*rand(4,6))
A =
8 5 2 13 15 11
22 11 27 13 24 24
5 18 23 9 23 15
20 23 14 15 19 10
>> B = im2col(A,[2 2],'distinct')
B =
8 5 2 23 15 23
22 20 27 14 24 19
5 18 13 9 11 15
11 23 13 15 24 10
>> col2im(B,[2 2],[4,6],'distinct')
ans =
8 5 2 13 15 11
22 11 27 13 24 24
5 18 23 9 23 15
20 23 14 15 19 10
my question is that: after using im2col with sliding mode
>> B = im2col(A,[2 2],'sliding')
B =
8 22 5 5 11 18 2 27 23 13 13 9 15 24 23
22 5 20 11 18 23 27 23 14 13 9 15 24 23 19
5 11 18 2 27 23 13 13 9 15 24 23 11 24 15
11 18 23 27 23 14 13 9 15 24 23 19 24 15 10
I wish to get a 4-by-6 matrix C from B(without knowing A) that the value at each site equals the original value multiple the times of sampling.
In other word, C(1,1)=A(1,1), C(1,2)=A(1,2)*2, C(2,2) = A(2,2)*4
Though we can easily implement with a for-loop, but the efficiency is critically low. So how to vectorize the implementation?
If I'm understanding correctly, you're desired output is
C = [ 8 10 4 26 30 11
44 44 108 52 96 48
10 72 92 36 92 30
20 46 28 30 38 10 ]
which I got by computing C = A.*S where
S = [ 1 2 2 2 2 1
2 4 4 4 4 2
2 4 4 4 4 2
1 2 2 2 2 1 ]_
The entries in S represent how many sliding blocks each entry is a member of.
I believe your question boils down to how to construct the matrix S.
Solution:
S = min(min(1:M,M:-1:1),x)'*min(min(1:N,N:-1:1),y)
C = A.*S
where A is size M-by-N, and your sliding block is size x-by-y.
Explanation:
In the given example, M=4, N=6, x=2, and y=2.
Notice the solution S can be written as the outer product of two vectors:
S = [1;2;2;1] * [1,2,2,2,2,1]
We construct each of these two vectors using the values of M,N,x,y:
min(1:M,M:-1:1)' == min(1:4,4:-1:1)'
== min([1,2,3,4], [4,3,2,1])'
== [1,2,2,1]'
== [1;2;2;1]
In this case, the extra min(...,x) does nothing since all entries are already <=x.
min(1:N,N:-1:1) == min(1:6,6:-1:1)
== min([1,2,3,4,5,6],[6,5,4,3,2,1])
== [1,2,3,3,2,1]
This time the extra min(...,y) does matter.
min(min(1:N,N:-1:1),y) == min([1,2,3,3,2,1],y)
== min([1,2,3,3,2,1],2)
== [1,2,2,2,2,1]
I am working on Matlab and I have a 16x16 matrix where the column values are equal to the row values matrix of nucleotide substitutions
I would like to reshape it so I have only 1 row containing only the unique values (in other words, I would like a row with:
7816 0 ....6432 0 ....8148 20.....
I tried B = reshape(matrix,1,[]); and it works but unfortunately it is giving me also the non-unique values (it is basically taking every row and pasting it just next to the previous one).
Is there any way to do this? Thanks!
Given a symmetric input matrix A:
>> A = randi(30, 5)
A =
9 13 19 23 8
13 4 5 14 19
16 25 13 11 27
12 3 20 25 11
1 12 9 20 27
>> A = A + A.'
A =
18 26 35 35 9
26 8 30 17 31
35 30 26 31 36
35 17 31 50 31
9 31 36 31 54
>> A(A < 10) = 0
A =
18 26 35 35 0
26 0 30 17 31
35 30 26 31 36
35 17 31 50 31
0 31 36 31 54
You can extract the lower triangular portion and turn it into a vector like so:
>> B = A(find(tril(ones(size(A))))).'
B =
18 26 35 35 0 0 30 17 31 26 31 36 50 31 54
Notice that this skips the 26 in the second column, the 35, 30 in the second column, and so on.
This takes the lower triangular portion of a matrix of 1's the same size as A and finds the indices of all of the 1 values. (That gets around the 0 values in the original matrix.) Then it uses the locations of the 1's returned by find to index into the original matrix A. Transpose to make it a row vector.
I have implemented matching pursuit algorithm but i m unable to get the required result.
Here is my code:
D=[1 6 11 16 21 26 31 36 41 46
2 7 12 17 22 27 32 37 42 47
3 8 13 18 23 28 33 38 43 48
4 9 14 19 24 29 34 39 44 49
5 10 15 20 25 30 35 40 45 50];
b=[6;7;8;9;10];
n=size(D);
A1=zeros(n);
R=b;
H=10;
if(H <= 0)
error('The number of iterations needs to be greater then 0')
end;
for k=1:1:H
[c,d] = max(abs(D'*R)); %//'
A1(:,d)=D(:,d);
D(:,d)=0;
y = A1\b;
R = b-A1*y;
end
Output
y=
0.8889
0
0
0
0
0
0
0
0
0.1111
I should get only non-zero value at (2,1) and other values should be zero but I'm getting 2 non-zero value. Can you please help me find out where the error is?
Thanks.
I checked with:
http://www.scholarpedia.org/article/Matching_pursuit
Your functions need to be normalized!
D = D./repmat(sum(D,1),5,1);
I get the following algorithm:
D=[1 6 11 16 21 26 31 36 41 46
2 7 12 17 22 27 32 37 42 47
3 8 13 18 23 28 33 38 43 48
4 9 14 19 24 29 34 39 44 49
5 10 15 20 25 30 35 40 45 50];
D = D./repmat(sum(D,1),5,1);
b=[6;7;8;9;10];
n=size(D);
A1=zeros(n);
R=b;
H=100;
if(H <= 0)
error('The number of iterations needs to be greater then 0')
end;
a = zeros(1,H);
G = zeros(size(D,1),H);
for k=1:1:H
ip = D'*R;
[~,d] = max(abs(ip)); %//'
G(:,k) = D(:,d);
a(k) = ip(d);
R = R-a(k)*G(:,k);
end
% recover signal:
Rrec = zeros(size(R));
for i=1:H
Rrec = Rrec + a(i)*G(:,i);
end
figure();
plot(b);
hold on;
plot(Rrec)
It approximates the signal quite well. But not with D(:,2) at first as expected. Maybe it is a starting point...
Here is the updated code. This is based on the algorithm provided at https://en.wikipedia.org/wiki/Matching_pursuit
clc;
clear all;
D=[1 6 11 16 21 26 31 36 41 46
2 7 12 17 22 27 32 37 42 47
3 8 13 18 23 28 33 38 43 48
4 9 14 19 24 29 34 39 44 49
5 10 15 20 25 30 35 40 45 50];
b=[6;7;8;9;10];
H=10;
for index=1:10
G(:,index)=D(:,index)./norm(D(:,index));
end
G1=G;
n=size(G);
R=b;
if(H <= 0)
error('The number of iterations needs to be greater then 0')
end;
if(H >size(D,2))
error('The number of iterations needs to be less than dictionary size')
end;
bIndex=1:size(G,2);
for k=H:-1:1
innerProduct=[];
for index=1:size(G,2)
innerProduct(index)=dot(R,G(:,index));
end
[c,d] = max(abs(innerProduct));
An(H-k+1)=innerProduct(d);
R = R-(An(H-k+1)*G(:,d));
G(:,d)=[];
strong(H-k+1)=bIndex(d);
bIndex(d)=[];
end
G_new=G1(:,strong);
%% reconstruction
bReconstructed=zeros(size(G_new,1),1);
for index=1:size(G_new,2)
bReconstructed(:,index) = (An(index)*G_new(:,index));
end
b_new=sum(bReconstructed,2)
Yes the atoms in the dictionary must be normalized so that the inner products of the current residual with different atoms can be compared fairly.
You may want to check my OMP implementation which also includes incremental Cholesky updates for the least square step in OMP at https://github.com/indigits/sparse-plex/blob/master/library/%2Bspx/%2Bpursuit/%2Bsingle/omp_chol.m
I have written detailed tutorial notes on OMP in my library documentation at https://sparse-plex.readthedocs.io/en/latest/book/pursuit/omp/index.html
My library sparse-plex contains a C implementation of OMP which is close to 4 times faster than fastest MATLAB implementations. See the discussion here https://sparse-plex.readthedocs.io/en/latest/book/pursuit/omp/fast_omp.html
I'm new in Matlab and I need to connect elements from two columns in different rows. I have the following matrix:
a =
12 15
14 16
15 20
16 23
20 21
21 25
23 24
24 26
25 27
what I need is to identify the elements of the 2nd column that are equal to the elements in the first, and join them sequentially to create 2 rows : [12 15 20 21 25 27] and [14 16 23 24 26]. The actual data is quite large, so the more vectorized the code, the better!
Thanks for your help!
GIE