¿Cómo asignar valores en la diagonal?

Supongamos que tengo una matriz A de NxN, un vector de índice V que consiste en un subconjunto de los números 1: N y un valor K, y quiero hacer esto:

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

¿Hay alguna manera de hacer esto en una statement con vectorización?

por ejemplo, A ( algo ) = K

La statement A(V,V) = K no funcionará, asigna elementos fuera de diagonal, y esto no es lo que quiero. p.ej:

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

Usualmente uso EYE para eso:

 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 

Alternativamente, puede crear la lista de índices lineales, ya que de un elemento diagonal a otro, toma nRows+1 pasos:

 [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 solo desea acceder a un subconjunto de elementos diagonales, debe crear una lista de índices diagonales:

 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 

Alternativamente, puede crear una matriz de índice lógico usando diag (funciona solo para matrices cuadradas)

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

y más general:

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

Esto se basa en el hecho de que se puede acceder a las matrices como matrices unidimensionales (vectores), donde los 2 índices (m, n) se reemplazan por un mapeo lineal m * N + n.

 A = zeros(7,6); V = [1 3 5]; [nm] = 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 

Supongamos que K es el valor. El comando

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

puede ser un poco más rápido

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

El tiempo transcurrido es 0.517575 segundos.

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

El tiempo transcurrido es 0.353408 segundos.

Pero consume más memoria.

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

sub2ind y pasaría los índices diagonales como parámetros xey.

 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