4

I have a very large 3D matrix and I need to call some specific patterns with a special configuration from this large matrix. For example, I need a sub-matrixes which their a,b,c,..,h element are equal with a specific value (it is not pattern matching, but I need some patterns that have a specific value)

Is there any solution to find them very fast? One solution, as I know, is to scan the matrix and store its pattern in a database and then use PCA to reducing the size of database, but I am looking for a more accurate method.

For example, suppose that I have a matrix such as I:

    I=[1    0   0   1   0   1   0   1   0
       0    0   0   0   0   0   0   0   0
       0    1   0   0   1   0   0   1   0
       1    0   1   1   0   1   0   1   0
       0    0   0   0   0   0   0   0   0
       1    0   0   0   1   0   1   0   0
       0    0   0   0   0   0   0   0   0
       1    0   1   0   0   0   0   0   1
       0    0   1   0   0   0   0   1   0]

then I have another matrix as below:

    p=[1    0   NaN NaN 1   NaN NaN NaN NaN]

then, I should look in "I" to find the rows which their column 1,2 and 5 is equal to 1,0,1 respectively (in this example, row of 6 is the correct row. But, in the reality, the size of my matrix (I) is very huge (more than billion) and if I use a loop to find those rows, it need a lot of time. I am looking for a fast code or method. Hope it be meaningful now!

Sam
  • 939
  • 5
  • 14
  • 41

1 Answers1

1

If the pattern you are looking for is column-wise, you can do as follow: (If it is not please be more specific in your question, I will modify my answer)

A=randi(10,[11 12 13]); %%% your matrix
p=[2;3;4]; %%% your pattern

m=cell(1,numel(p));
% for each element of the pattern
for i=1:numel(p)
  % find the element of A matching the i-th element of p
  m{i}=find(A==p(i));
  % convert to indices
  [x y z]=ind2sub(size(A),m{i});
  m{i}=[x y z];
  % convert to the position of the first element of the pattern
  m{i}(:,1)=m{i}(:,1)-(i-1);
  % remove when it goes below zero
  m{i}(m{i}(:,1)<=0,:)=[];
end

% accumulate everything to find out where all the elements of the pattern match
numberOfMatching=accumarray(vertcat(m{:}),1,size(A)); 
fullMatchingIndices=find(numberOfMatching==numel(p));
% convert to sub=indices
[x y z]=ind2sub(size(A),fullMatchingIndices);
finalIndices=[x y z];

% check the result
if ~isempty(finalIndices)
  A(finalIndices(1,1)+(0:numel(p)-1),finalIndices(1,2),finalIndices(1,3))
end

As a result, you should obtain the pattern p (if at least one match is foud):

ans =
     2
     3
     4
Oli
  • 15,935
  • 7
  • 50
  • 66
  • you got it Oli, but my matrix is very very large (200x200x200)!! and also at each search I need to check about 10-20 data. So, the problem will be its CPU time. 1) How the codes can be changed for a situation that as soon as it fund a pattern that has p, skip the loop? 2) How it should be changed when there is no pattern, then select the last matched one? I mean, drop one of the element in p and find the pattern. But, it should not repeat the loop again and should have the latest founded pattern! – Sam Sep 28 '12 at 00:17
  • On my computer, the above code work in 1second for matrices of size [200 200 200]. 2) How can you match if there is no pattern? Do you want approximate matching also? – Oli Sep 28 '12 at 00:24
  • I just need to find the patterns that have those values. Consider that I scan the big matrix (G) with template size of T (let say 20x20) and store all of the patterns in a database. Therefore, the obtained database will have a lot of patterns (row) and 20^2 column. So, I want to find the patterns which, for example, their 3th, 7th, 8th, 15th element be equal to some specific values. It is my problem! I think the codes should be changed, yes? – Sam Sep 28 '12 at 02:35