Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matlab For loop only for the "shell" of the matrix

Take a random set of coordinates (x, y, z) that will be the center of my 3x3x3 matrix( considered local minimum as well). I have a function J that takes those coordinates, does the calculations and returns me a number. If any of those 26 points will be smaller, that would be the center for my next matrice. In case I don't find a smaller value, the radius of the matrice is increased by 1, and we run the loop again. My question is : how to loop only through the "shell" of the cube and not call the function for the previously tested values?

I tried to illustrate it below ( it's in 2d here, but you get the point) .. the dots are the values that were tested, the "?" are the ones that need to be calculated and compared to the local min.

enter image description here

here is the code

minim=100;

%%the initial size of the search matrix 2*level +1
level=1;
x=input('Enter the starting coordinate for X : ');
y=input('Enter the starting coordinate for Y : ');
z=input('Enter the starting coordinate for Z : ');

%%The loop
if(level<=10)
for m=x-level:x+level
    for n=y-level:y+level
        for p=z-level:z+level
            A(m,n,p)=J(m,n,p);
            if A(m,n,p)<minim
               minim=A(m,n,p);
               x=m;y=n;z=p;
               level=1;
            else
                level=level+1;

                %<<----shell loop here ---->>

            end

        end
    end
    end
else

%Display global min
display(minim, 'Minim');
%Coordinates of the global min
[r,c,d] = ind2sub(size(A),find(A ==minim));

display(r,'X');
display(c,'Y');
display(d,'Z');
end
like image 448
Mike Avatar asked Oct 19 '22 15:10

Mike


2 Answers

Here is a simple C++ solution

This is a 5x5x5 cube represented 2D:

a[i][j][0]
1   1   1   1   1   
1   1   1   1   1   
1   1   1   1   1
1   1   1   1   1
1   1   1   1   1

a[i][j][1]
1   1   1   1   1
1   0   0   0   1   
1   0   0   0   1
1   0   0   0   1
1   1   1   1   1

a[i][j][2]
1   1   1   1   1
1   0   0   0   1   
1   0   0   0   1
1   0   0   0   1
1   1   1   1   1

a[i][j][3]
1   1   1   1   1
1   0   0   0   1   
1   0   0   0   1
1   0   0   0   1
1   1   1   1   1

a[i][j][4]
1   1   1   1   1   
1   1   1   1   1
1   1   1   1   1
1   1   1   1   1
1   1   1   1   1

And here is the code for cube parse:

int a[5][5][5]
int matrix_size = 2*level+1;

for(int z=0;z<matrix_size;z++)

if(z==0 || z= matrix_size-1)
{
    for(int i=0;i<matrix_size-1;i++)
        for(int j=0;j<matrix_size-1;j++)
            {
                //compare minim with  a[i][j][z];
            }
}
else
    for(int i=0;i<matrix_size-1;i++)
        {
            if(i==1 || i==matrix_size-1)
                {   
                    for(int j=0;j<matrix_size-1;j++)
                        //compare minim with  a[i][j][z];
                }
            else
                {
                    //compare minim with  a[i][1][z] and  a[i][matrix_size-1][z];
                }
        }
like image 112
Ion Avatar answered Oct 21 '22 06:10

Ion


You can use logical indexing, I'm not sure however if you will gain speed by doing so. The reconstruction of the location of the min is a bit awkward, but like this you get rid of all the for loops.

A = rand(7,7,7);
%"shell" mask for extraction
B = ones(5,5,5);
B = padarray(B,[1,1,1]);
B = logical(abs(B-1));

[val, ind] = min(A(B))

%reconstruct location
tmp = zeros(1,sum(B(:)));
tmp(ind) = 1;
C = zeros(size(A));
C(B) = tmp;
[~, ind] = max(C(:));
[r,c,d] = ind2sub(size(A),ind);
like image 28
Dominic Avatar answered Oct 21 '22 04:10

Dominic