web-dev-qa-db-fra.com

Comment attribuer des valeurs sur la diagonale?

Supposons que j'ai une matrice NxN A, un vecteur d'index V composé d'un sous-ensemble des nombres 1: N et une valeur K, et je veux faire ceci:

 for i = V
     A(i,i) = K
 end

Existe-t-il un moyen de le faire dans une seule déclaration avec vectorisation?

par exemple. A (quelque chose) = K

L'instruction A(V,V) = K ne fonctionnera pas, elle assigne des éléments hors diagonale, et ce n'est pas ce que je veux. par exemple.:

>> A = zeros(5);
>> V = [1 3 4];
>> A(V,V) = 1

A =

 1     0     1     1     0
 0     0     0     0     0
 1     0     1     1     0
 1     0     1     1     0
 0     0     0     0     0
42
Jason S

J'utilise habituellement EYE ​​ pour cela:

A = magic(4)
A(logical(eye(size(A)))) = 99

A =
    99     2     3    13
     5    99    10     8
     9     7    99    12
     4    14    15    99

Alternativement, vous pouvez simplement créer la liste des indices linéaires, car d'un élément diagonal à l'autre, il faut nRows+1 pas:

[nRows,nCols] = size(A);
A(1:(nRows+1):nRows*nCols) = 101
A =
   101     2     3    13
     5   101    10     8
     9     7   101    12
     4    14    15   101

Si vous souhaitez uniquement accéder à un sous-ensemble d'éléments diagonaux, vous devez créer une liste d'indices diagonaux:

subsetIdx = [1 3];
diagonalIdx = (subsetIdx-1) * (nRows + 1) + 1;
A(diagonalIdx) = 203
A =
   203     2     3    13
     5   101    10     8
     9     7   203    12
     4    14    15   101

Alternativement, vous pouvez créer un tableau d'index logique en utilisant diag (ne fonctionne que pour les tableaux carrés)

diagonalIdx = false(nRows,1);
diagonalIdx(subsetIdx) = true;
A(diag(diagonalIdx)) = -1
A =
    -1     2     3    13
     5   101    10     8
     9     7    -1    12
     4    14    15   101
61
Jonas
>> tt = zeros(5,5)
tt =
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
>> tt(1:6:end) = 3
tt =
     3     0     0     0     0
     0     3     0     0     0
     0     0     3     0     0
     0     0     0     3     0
     0     0     0     0     3

et plus général:

>> V=[1 2 5]; N=5;
>> tt = zeros(N,N);
>> tt((N+1)*(V-1)+1) = 3
tt =
     3     0     0     0     0
     0     3     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     3

Ceci est basé sur le fait que les matrices sont accessibles sous forme de tableaux unidimensionnels (vecteurs), où les 2 indices (m, n) sont remplacés par un mappage linéaire m * N + n.

24
ysap

Supposons que K soit la valeur. La commande

A=A-diag(K-diag(A))

peut être un peu plus rapide

>> A=randn(10000,10000);

>> tic;A(logical(eye(size(A))))=12;toc

Le temps écoulé est de 0,517575 secondes.

>> tic;A=A+diag((99-diag(A)));toc

Le temps écoulé est de 0,353408 secondes.

Mais il consomme plus de mémoire.

2
user677656

J'utiliserais sub2ind et passez les indices diagonaux en tant que paramètres x et y:

A = zeros(4)
V=[2 4]

idx = sub2ind(size(A), V,V)
% idx = [6, 16]

A(idx) = 1

% A =
% 0     0     0     0
% 0     1     0     0
% 0     0     0     0
% 0     0     0     1
2
Eran W
>> B=[0,4,4;4,0,4;4,4,0]

B =

     0     4     4
     4     0     4
     4     4     0

>> v=[1,2,3]

v =

     1     2     3

>> B(eye(size(B))==1)=v
%insert values from v to eye positions in B

B =

     1     4     4
     4     2     4
     4     4     3
2
Gabriel Cedillos
A = zeros(7,6);
V = [1 3 5];

[n m] = size(A);
diagIdx = 1:n+1:n*m;
A( diagIdx(V) ) = 1

A =
     1     0     0     0     0     0
     0     0     0     0     0     0
     0     0     1     0     0     0
     0     0     0     0     0     0
     0     0     0     0     1     0
     0     0     0     0     0     0
     0     0     0     0     0     0
2
Amro