Fayyaadh
Fayyaadh

Reputation: 57

How to set up a matrix with a fixed pattern

I need to write a script to automatically setup a matrix A. The size of this matrix is linked to the value of another variable in the workspace, N. In general, A will have N + N*(N-1)/2 rows and N columns.

The first N rows and N columns are basically just a diagonal matrix, which is easy to setup using diag.

I'm having problems setting up the lower part of the matrix. Basically, it needs to have the following form:

-1  0  0  0
 0 -1  0  0
 0  0 -1  0
 0  0  0 -1
 1 -1  0  0
 1  0 -1  0
 1  0  0 -1
 0  1 -1  0
 0  1  0 -1
 0  0  1 -1

I'm sure the pattern is clear.

How do I code this so that Matlab sets up this matrix for ANY value of N?

Thanks

Upvotes: 2

Views: 263

Answers (3)

Fayyaadh
Fayyaadh

Reputation: 57

Thank everyone! I will post my own solution here (doesn't pre-allocate though). Might adjust it to @Dennis's solution.

N = max(size(a));
P = N*(N-1)/2;

A = zeros(N+P,N);

A(1:N,1:N) = diag(-a);

B=[];

for i = N-1:-1:1
    Block = [zeros(i,N-1-i) ones(i,1) -eye(i)];
    B = [B; Block];
    clear Block
end

A(N+1:end,:) = B;
clear N P B i

Upvotes: 0

Dennis Jaheruddin
Dennis Jaheruddin

Reputation: 21563

UPDATE

Performance version including preallocation.

N=4;
result = zeros(N*(N+1)/2,N+1);
t = N;
endpos = 0;
for t = N:-1:1 
    result(endpos+1:endpos+t,:) = [zeros(t, N-t) ones(t,1) -eye(t)];
    endpos = endpos + t;
end
result = result(:,2:end);

Note that I have replaced the while loop as you seem to prefer a for.


I will leave the original here as well for comparison:

Here you go:

result = [];
N = 4;
t = MaxN;
while t > 0
    block = [zeros(t, N-t) ones(t,1) -eye(t)];
    result = [result; block];
    t = t-1;
end
result = result(:,2:end);

Upvotes: 1

Mohsen Nosratinia
Mohsen Nosratinia

Reputation: 9864

With some algebraic manipulation:

L=(N*(N+1)/2):-1:1;
R=ceil((sqrt(8*L+1)-1)/2);
A=bsxfun(@eq, N-1:-1:0, R')-bsxfun(@eq, N:-1:1, (L-(R.*(R-1))/2).');

Upvotes: 3

Related Questions