2016-02-22 15 views
5

Prendere un insieme casuale di coordinate (x, y, z) che sarà il centro della mia matrice 3x3x3 (considerato minimo locale). Ho una funzione J che prende quelle coordinate, esegue i calcoli e mi restituisce un numero. Se uno qualsiasi di questi 26 punti sarà più piccolo, quello sarebbe il centro della mia prossima matrice. Nel caso in cui non trovassi un valore inferiore, il raggio della matrice è aumentato di 1 e eseguiamo nuovamente il ciclo. La mia domanda è: come eseguire il ciclo solo attraverso la "shell" del cubo e non chiamare la funzione per i valori precedentemente testati?Matlab Solo per il ciclo "shell" della matrice

Ho provato ad illustrarlo di seguito (è in 2d qui, ma si ottiene il punto) .. i punti sono i valori che sono stati testati, il "?" sono quelli che devono essere calcolati e confrontati con il locale min.

enter image description here

Ecco il codice

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 
+0

Sembra che tu stia cercando di fare qualche ottimizzazione. Hai preso in considerazione l'utilizzo di una funzione 'MATLAB' integrata, come [' fminsearch'] (http://www.mathworks.com/help/matlab/ref/fminsearch.html?requestedDomain=www.mathworks.com)? –

+0

@Jeff Irwin Correggetemi se ho torto, ma con fminsearch o altri metodi di ottimizzazione, non è necessario avere tutte le variabili prima di operare su di esse? La mia funzione è convessa (non perfetta!, È per questo che ho usato la variabile di livello ... Se aumento il raggio 10 volte, cioè 21x21x21 e non trovo un'altra variabile più piccola del minimo locale, concludo che è il minimo globale) e sto facendo piccoli passi verso il minimo globale senza calcolare tutti i valori – Mike

+1

Non sono sicuro di cosa intendi con "avere tutte le variabili". fminsearch valuta la tua funzione come va. Non è necessario valutare la funzione prima del tempo. Alcuni algoritmi di ottimizzazione devono anche valutare il gradiente della funzione, ma fminsearch non ha bisogno del gradiente. –

risposta

1

Ecco una soluzione semplice

Questo è un 5x5x5 cubo 2D rappresentato C++:

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 

Ed ecco il codice per il cubo 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]; 
       } 
     } 
1

È possibile utilizzare l'indicizzazione logica, non sono sicuro se si otterrà la velocità in questo modo. La ricostruzione della posizione del min è un po 'imbarazzante, ma in questo modo ti sbarazzi di tutti i loop for.

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); 
1

Ecco un modo si possono raggiungere tutti gli elementi "guscio" in un singolo ciclo:

clear; 
%// a cube matrix to play with 
A=nan(5,5,5); 

n=length(A(:,1,1)); %// Assuming cube matrix 
%// lets change all ot the "shell" elements to 1 
for i=1:n 
     % 1st and nth level 
     A(1,i,1)=1; 
     A(i,1,1)=1; 
     A(n,i,1)=1; 
     A(i,n,1)=1; 
     A(1,i,n)=1; 
     A(i,1,n)=1; 
     A(n,i,n)=1; 
     A(i,n,n)=1; 

     % 2nd to (n-1)th level 
     A(1,1,i)=1; 
     A(1,n,i)=1; 
     A(n,1,i)=1; 
     A(n,n,i)=1; 
end 

Nota che gli elementi angolari sono raggiunti più di una volta. la matrice risultante:

>> A 
A(:,:,1) = 
    1  1  1  1  1 
    1 NaN NaN NaN  1 
    1 NaN NaN NaN  1 
    1 NaN NaN NaN  1 
    1  1  1  1  1 

A(:,:,2) = 
    1 NaN NaN NaN  1 
    NaN NaN NaN NaN NaN 
    NaN NaN NaN NaN NaN 
    NaN NaN NaN NaN NaN 
    1 NaN NaN NaN  1 

A(:,:,3) = 
    1 NaN NaN NaN  1 
    NaN NaN NaN NaN NaN 
    NaN NaN NaN NaN NaN 
    NaN NaN NaN NaN NaN 
    1 NaN NaN NaN  1 

A(:,:,4) = 
    1 NaN NaN NaN  1 
    NaN NaN NaN NaN NaN 
    NaN NaN NaN NaN NaN 
    NaN NaN NaN NaN NaN 
    1 NaN NaN NaN  1 

A(:,:,5) = 
    1  1  1  1  1 
    1 NaN NaN NaN  1 
    1 NaN NaN NaN  1 
    1 NaN NaN NaN  1 
    1  1  1  1  1 
+0

Sulla base di questa logica ho trovato la mia soluzione, grazie :) – Mike

+0

Grande! Sono contento che ci abbia aiutato – wdickerson