MATLAB: Create a block diagonal matrix with same repeating block - matlab

I have a matrix K of dimensions n x n. I want to create a new block diagonal matrix M of dimensions N x N, such that it contains d blocks of matrix K as its diagonal.
I would have directly used M = blkdiag(K,K,K) etc. had d been smaller. Unfortunately, d is very large and I don't want to manually write the formula with d exactly same arguments for the blkdiag() function.
Is there any shorter, smarter way to do this?

you can use kron for that.
M = kron(X,Y)
returns the Kronecker tensor product of X and Y. The result is a large array formed by taking all possible products between the elements of X and those of Y. If X is m-by-n and Y is p-by-q, then kron(X,Y) is m*p-by-n*q. So in your case something like this will do:
M = kron(eye(L),K)
with L the # of blocks.

tmp = repmat({K},d,1);
M = blkdiag(tmp{:});
You should never use eval, or go into for loops unnecessarily.
Kron is a very elegant way.
Just wanted to share this as it also works.

The following should work:
d=5; K=eye(3); T = cell(1,d);
for j=1:d
T{j} =K;
end
M = blkdiag(T{:})

s = 'A,';
s = repmat(s,[1,n2]);
s = ['B=blkdiag(', s(1:end-1),');'];
eval(s);
It can be faster than using kron-eye.

A "for" loop may might help. Like:
M = k;
for i=1:N/n - 1
M=blkdiag(M,k);
end

Related

How to write a line of statement with two vector of different size using no loops In matlab

I am not sure if the title is correct. But here's what I want to do.
n = -10:10;
p = [-0.6 0.2];
r = [ -1.7500 2.7500];
H = zeros(size(n));
for i=1:length(p)
H = H + r(i)*(p(i).^n).*(n>=0);
end
I want to write this for loop in a one line statement. Is there a way?
H = (H + r(1)*(p(1).^n).*(n>=0))+(H + r(2)*(p(2).^n).*(n>=0))
From Matlab 2016b, when you convert r and p to vertical vectors by the operator .', you can multiply or power it by row vector n, and get the result as a matrix. That known as "arithmetic expands". It can be very useful in your case:
H=sum(r.'.*p.'.^n).*(n>=0);
For earlier versions of Matlab, you need to use bsxfun for element-wise operations, so you can write it like that:
H=sum(bsxfun(#times,r.',bsxfun(#power,p.',n))).*(n>=0)

Creating script that takes matrices of size n and size n x 1

I have a MATLAB function that takes a matrix of length n, and uses gaussian elimination with partial pivoting to compute Ax = b. A is n x n, and b is n x 1.
I'm trying to create a script that generates random numbers and then call the function with those numbers. So far I have
A = rand(n)
b = rand(n, 1)
genp(r, r)
but since n is undefined, it doesn't work. Is the best way to create the variable n and assign a random integer to it?
Yes, the best way is to create a variable n. What you want is (probably):
n = 10; % Change this if you want different sized data
A = rand(n);
b = rand(n,1);
genp(A,b);
This way you can very easily alter the size of your data, by simply changing n. Based on this question, I'm assuming you want gen(A,b), and not gen(r,r), as you wrote in your question.
If you want an random n every time you call the function, check out randi

matlab concatenating vectors

I'm new to MATLAB, and programming in general, and I am having difficulty accomplishing what I am sure is a very, very simple task:
I have a list of vectors v_i for i from 1 to n (n in some number), all of the same size k. I would like to create a vector v that is a "concatenation" (don't know if this is the correct terminology) of these vectors in increasing order: what I mean by this is that the first k entries of v are the k entries of v_1, the k+1 to 2k entries of v are the k entries of v_2 etc. etc. Thus v is a vector of length nk.
How should I create v?
To put this into context, here is function I've began writing (rpeakindex will just a vector, roughq would be the vector v I mentioned before):
function roughq = roughq(rpeakindex)
for i from 1 to size(rpeakindex) do
v_i = [rpeakindex(i)-30:1:rpeakindex(i)+90]
end
Any help is appreciated
Let's try two things.
First, for concatenating vectors there are a couple of methods here, but the simplest would be
h = horzcat(v_1, v_2);
The bigger problem is to enumerate all vectors with a "for" loop. If your v_n vectors are in a cell array, and they are in fact v{i}, then
h= [];
for j=1:n
h = horzcat(h, v{i});
end
Finally, if they only differ by name, then call them with
h=[];
for j=1:n
h= horzcat(h, eval(sprintf('v_%d',j));
end
Let the arrays (vectors) be:
v_1=1:10;
v_2=11:20;
v_3=21:30;
v_4=31:40;
and so on.
If they are few (e. g. 4), you can directly set then as input in the cat function:
v=cat(2,v_1,v_2,v_3,v_4)
or the horzcat function
v=horzcat(v_1,v_2,v_3,v_4)
otherwise you can use the eval function within a loop
v1=[];
for i=1:4
eval(['v1=[v1 v_' num2str(i) ']'])
end
Hope this helps.
Concatenating with horzcat is definitely an option, but since these vectors are being created in a function, it would be better to concatenate these vectors automatically in the function itself rather than write out horzcat(v1,v2,....vn) manually.
Given the function mentioned in the question, I would suggest something like this:
function v = roughq(rpeakindex)
v = zeros(121,length(rpeakindex)); %// create a 2D array of all zeros
for i = 1:size(rpeakindex)
v(:,i) = [rpeakindex(i)-30:1:rpeakindex(i)+90]; %// set result to ith column of v
end
v = v(:)'; %'//reshape v to be a single vector with the columns concatenated
end
Here's a simplified example of what's going on:
N = 3;
v = zeros(5,N);
for i = 1:N
v(:,i) = (1:5)*i;
end
v = v(:)';
Output:
v =
1 2 3 4 5 2 4 6 8 10 3 6 9 12 15
You may want to read up on MATLAB's colon operator to understand the v(:) syntax.
If you mean 2d matrix, you are using for holding vectors and each row hold vector v then you can simply use the reshape command in matlab like below:
V = [] ;
for i = 1:10
V(i,:) = randi (10,1 ,10) ;
end
V_reshpae = reshape (V, 1, numel(V)) ;

Efficient way of concatenating vectors

I have a n x 3 matrix E, a lot of means stocked in a d x 3 matrix M and a covariance matrix, say identity.
I want to compute, for each point in M, the mvnpdf(E[i,:],M(k,:),cov).
Basically, when I run mvnpdf(E,M(k,:),cov), I get a vector
[mvnpdf(E(1,:),M(k,:),cov)
mvnpdf(E(2,:),M(k,:),cov) etc]
I want to cat these vectors to get a matrix like:
[mvnpdf(E,M(1,:),cov), mvnpdf(E,M(2,:),cov), etc]
Is there any way to do that without a for loop?
This works on my machine, but see if it is what you are after:
Cov = eye(3);
C = arrayfun(#(x,y,z) mvnpdf(E,[x y z],Cov), M(1,:), M(2,:), M(3,:),'uni',false);
A = [C{:}]
Note: Consider not using cov as a variable because it is a MATLAB function.
EDIT: My original output M clobbered your input M. Please try again with original data!

make this matlab snippet run without a loop

I want a code the below code more efficient timewise. preferably without a loop.
arguments:
t % time values vector
t_index = c % one of the possible indices ranging from 1:length(t).
A % a MXN array where M = length(t)
B % a 1XN array
code:
m = 1;
for k = t_index:length(t)
A(k,1:(end-m+1)) = A(k,1:(end-m+1)) + B(m:end);
m = m + 1;
end
Many thanks.
I'd built from B a matrix of size NxM (call it B2), with zeros in the right places and a triangular from according to the conditions and then all you need to do is A+B2.
something like this:
N=size(A,2);
B2=zeros(size(A));
k=c:length(t);
B2(k(1):k(N),:)=hankel(B)
ans=A+B2;
Note, the fact that it is "vectorized" doesn't mean it is faster these days. Matlab's JIT makes for loops comparable and sometimes faster than built-in vectorized options.