NKN
NKN

Reputation: 6424

produce a matrix in a more efficient way

I am looking for a more efficient way to make the following matrix L:

      |2 -2  0 0 0     |
      |-1 2 -1 0 0  0  |
      |0 -1 2 -1 0     |
(1/2).|0 0 -1 2 -1     |
      |      . . .     |   
      |  0    0 -1 2 -1|
      |       0  0 -2 2|

So far I have got this:

L = diag(ones(n,1)*2)- ...
    diag(ones(n-1,1),1) - ... 
    diag(ones(n-1,1),-1);
L(1,2) = -2; 
L(end,end-1) = -2;
L = L/2;     

for instance for n=5 it produces:

L =

    1.0000   -1.0000         0         0         0
   -0.5000    1.0000   -0.5000         0         0
         0   -0.5000    1.0000   -0.5000         0
         0         0   -0.5000    1.0000   -0.5000
         0         0         0   -1.0000    1.0000

n can be a value in range [5 1000].

Upvotes: 3

Views: 73

Answers (2)

rayryeng
rayryeng

Reputation: 104484

Instead, try using 2D convolution with conv2 where the input is the identity matrix and a horizontal [-0.5 1 -0.5] filter tap is the kernel. This is nice because you can consider this identity matrix as an image and you are performing an edge detection where the only time you will get a coefficient of 1 in the output is when the centre of the kernel is directly on top of a 1. If the kernel centre is not on a 1 but any of the elements are touching a 1, the result would be -0.5. This is nice but it doesn't handle the border cases with the top and bottom row. That unfortunately you have to modify manually. We can escape using two statements to modify the elements in favour of using column-major indexing instead. This solution certainly beats using 3 diag calls IMHO.

n = 5;
L = conv2(eye(n), [-0.5 1 -0.5], 'same');
L([n+1 end-n]) = -1;

Result:

>> L

L =

    1.0000   -1.0000         0         0         0
   -0.5000    1.0000   -0.5000         0         0
         0   -0.5000    1.0000   -0.5000         0
         0         0   -0.5000    1.0000   -0.5000
         0         0         0   -1.0000    1.0000

Upvotes: 5

Luis Mendo
Luis Mendo

Reputation: 112659

Here's another way:

n = 5;
L = full(spdiags(repmat([-1 2 -1],n,1), [-1 0 1], zeros(n)));
L([n+1 end-n]) = -2;

Upvotes: 3

Related Questions