views:

66

answers:

3

Suppose I have an NxN matrix A, an index vector V consisting of a subset of the numbers 1:N, and a value K, and I want to do this:

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

Is there a way to do this in one statement w/ vectorization?

e.g. A(something) = K

The statement A(V,V) = K will not work, it assigns off-diagonal elements, and this is not what I want. e.g.:

>> 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
+5  A: 

I usually use EYE for that:

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

Alternatively, you can just create the list of linear indices, since from one diagonal element to the next, it takes nRows+1 steps:

[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

If you only want to access a subset of diagonal elements, you need to create a list of diagonal indices:

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

Alternatively, you can create a logical index array using diag (works only for square arrays)

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
Jonas
cool, it works! will accept when the stupid-timer runs out
Jason S
@Jason S: Thanks! I actually find this an annoying issue; I often attempt to use `diag` first, before I remember to use `eye`
Jonas
+4  A: 
>> 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

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

This is based on the fact that matrices can be accessed as one-dimensional arrays (vectors), where the 2 indices (m,n) are replaced by a linear mapping m*N+n.

ysap
I only saw your solution after I had submitted my edit. +1 for being faster, even though my solution is a bit more general :)
Jonas
+1  A: 
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
Amro

related questions