Reputation: 57
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
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
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
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