2015-11-01 17 views
6

voglio creare una matrice in cui la diagonale centrale è simmetricamente diminuendo ai lati, come questo:Matlab diminuendo matrice diagonale

5 4 3 2 1 
4 5 4 3 2 
3 4 5 4 3 
2 3 4 5 4 
1 2 3 4 5 

La matrice deve essere 100x100 ed i valori sono tra 0 e 1. Fino ad ora ho solo i bordi e la diagonale centrale, ma non riesco a capire come riempire automaticamente il resto.

v = ones(1,100); 
green = diag(v); 
green(:,1) = fliplr(0:1/99:1); 
green(1,:) = fliplr(0:1/99:1); 
green(100,:) = 0:1/99:1; 
green(:,100) = 0:1/99:1; 

risposta

4
N = 100; %// size of your matrix 
v = ones(1,N); %// get a vector of ones 
D = N*diag(v); %// set the main diagonal 
for ii = 1:size(D,1)-1 
    tmp = (N-ii)*diag(v(1:end-ii),ii); %//positive direction off- 
    tmp2 = (N-ii)*diag(v(1:end-ii),-ii); %//negative direction off-diagonal 
    D = D+tmp+tmp2; %// Add them up 
end 
D = D/N; %// scale values to between 0 and 1 

Il trucco è quello di utilizzare la variabile di indicizzazione, ii, come un contatore per ridurre simultaneamente la moltiplicazione, N-ii, diminuire la lunghezza del v, v(1:end-ii) e aumentare l'offset della diagonale all'interno diag, ii o -ii.

Proprio per verificare i risultati trama usando imagesc(D):

![enter image description here

7

a cercare una soluzione vectorized considerare l'utilizzo di spdiags().

n = 5; 
A = repmat([1:n-1,n:-1:1],n,1); 
B = full(spdiags(A,-n+1:n-1,n,n)); 

Ciò restituirà:

5 4 3 2 1 
4 5 4 3 2 
3 4 5 4 3 
2 3 4 5 4 
1 2 3 4 5 

Come @Adriaan rilevare B = B/n trasformerà i valori della matrice tra 0 e 1.

5

Come su alcuni code-golfing -

n = 5 
M = mod(bsxfun(@plus,n:-1:1,(0:n-1)'),n) 
out = triu(M)+tril(n-M) 

Per il tuo caso reale, dal momento che è necessario avere valori nell'intervallo [0,1], è possibile scalare out, in questo modo -

out = (out - 1)/max(out(:)-1) 

Campione run -

>> n = 5; 
M = mod(bsxfun(@plus,n:-1:1,(0:n-1)'),n); 
out = triu(M)+tril(n-M); 
>> out 
out = 
    5  4  3  2  1 
    4  5  4  3  2 
    3  4  5  4  3 
    2  3  4  5  4 
    1  2  3  4  5 
>> out = (out - 1)/max(out(:)-1) 
out = 
      1   0.75   0.5   0.25   0 
     0.75   1   0.75   0.5   0.25 
      0.5   0.75   1   0.75   0.5 
     0.25   0.5   0.75   1   0.75 
      0   0.25   0.5   0.75   1 
6

Sono sorpreso che nessuno ha raccomandato la matrice toeplitz a voi:

n = 5; 
out = toeplitz(n:-1:1); 

Otteniamo:

out = 


    5  4  3  2  1 
    4  5  4  3  2 
    3  4  5  4  3 
    2  3  4  5  4 
    1  2  3  4  5 

Se si vuole normalizzare questo per [0,1], semplicemente fare la normalizzazione di serie in modo tale che:

out_new = (out - 1)/(n - 1) 

... e così:

>> out = (out - 1)/(n - 1) 

out = 

    1.0000 0.7500 0.5000 0.2500   0 
    0.7500 1.0000 0.7500 0.5000 0.2500 
    0.5000 0.7500 1.0000 0.7500 0.5000 
    0.2500 0.5000 0.7500 1.0000 0.7500 
     0 0.2500 0.5000 0.7500 1.0000