create matrix function of vector input variable (Matlab) - matlab

I'm having trouble creating a function that does what I want. I'm trying to create an anonymous function that, on accepting a vector of length N produces an NxN matrix. I'd like to populate each element of the matrix (ie, with a loop). A short example to be more specific:
N = 2;
Qjk = #(x,y) x * y;
for j = 1:N
for k = 1:N
Q(j,k) =#(x) Qjk(x(k),rand);
end
end
In the end this should produce, eg.:
Q = #(x) [.23*x(1), .16*x(2); .95*x(1), .62*x(2)]
I can write the final expression above by hand and it works as required, but I'm unable to automate this process with a loop/vectorization. Thanks.

So it is my understanding that you want to create a N x N matrix of elements where the input is a vector of length N?... and more specifically, you wish to take each element in the input vector x and generate a new 1 x N vector where each element in x gets scaled by this new 1 x N vector?
You can avoid loops by using bsxfun:
Q = bsxfun(#times, x(:).', rand(numel(x)));
I'm not sure what shape x is, whether it's a row or column vector but I'm not going to make any assumptions. x(:).' will ensure that your vector becomes a row vector. However, if you want to get your code working as it, get rid of the anonymous function declaration within the actual loop itself. Also, you'll probably want to call Qjk as that is the function you declared, not Q as that is the matrix you are trying to populate.
Simply do:
N = 2;
Q = zeros(N); % New - Allocate to be more efficient
Qjk = #(x,y) x * y;
for j = 1:N
for k = 1:N
Q(j,k) = Qjk(x(k),rand); % Change
end
end

Related

Block matrix inner products in Matlab

I have been using the following custom function to perform the multiplication of a vector by a matrix, in which each element of the vector multiplies a 3x3 block within a (3xN)x(3) matrix:
function [B] = BlockScalar(v,A)
N=size(v,2);
B=zeros(3*N,3);
for i=1:N
B(3*i-2:3*i,:) = v(i).*A(3*i-2:3*i,:);
end
end
Similarly, when I want to multiply a collection of 3x3 matrices by a collection of 3x3 vectors, I use the following
function [B] = BlockMatrix(A,u)
N=size(u,2);
B=zeros(N,3);
for i=1:N
B(i,:) = A(3*i-2:3*i,:)*u(:,i);
end
end
Since I call them very often, these unfortunately, slow down the running of my code significantly. I was wondering if there was a more efficient (perhaps vectorised) version of the above operations.
In both instance, you are able to do away with the for-loops (although without testing, I cannot confirm if this will necessarily speed up your computation).
For the first function, you can do it as follows:
function [B] = BlockScalar(v,A)
% We create a vector N = [1,1,1,2,2,2,3,3,3,...,N,N,N]
N=ceil((1:size(A,1))/3);
% Use N to index v, and let matlab do the expansion
B = v(N).*A;
end
For the second function, we can make a block-diagonal matrix.
function [B] = BlockMatrix(A,u)
N=size(u,2)*3;
% We use a little meshgrid+sparse magic to convert A to a block matrix
[X,Y] = meshgrid(1:N,1:3);
% Use sparse matrices to speed up multiplication and save space
B = reshape(sparse(Y+(ceil((1:N)/3)-1)*3,X,A) * (u(:)),3,size(u,2))';
end
Note that if you are able to access the individual 3x3 matrices, you can potentially make this faster/simpler by using the native blkdiag:
function [B] = BlockMatrix(a,b,c,d,...,u)
% Where A = [a;b;c;d;...];
% We make one of the input matrices sparse to make the whole block matrix sparse
% This saves memory and potentially speeds up multiplication by a lot
% For small enough values of N, however, using sparse may slow things down.
reshape(blkdiag(sparse(a),b,c,d,...) * (u(:)),3,size(u,2))';
end
Here are vectorized solutions:
function [B] = BlockScalar(v,A)
N = size(v,2);
B = reshape(reshape(A,3,N,3) .* v, 3*N, 3);
end
function [B] = BlockMatrix(A,u)
N = size(u,2);
A_r = reshape(A,3,N,3);
B = (A_r(:,:,1) .* u(1,:) + A_r(:,:,2) .* u(2,:) + A_r(:,:,3) .* u(3,:)).';
end
function [B] = BlockMatrix(A,u)
N = size(u,2);
B = sum(reshape(A,3,N,3) .* permute(u, [3 2 1]) ,3).';
end

Filling in a Cell of Matrices in MATLAB

In Matlab I am trying to create a cell of size 16 x1 where each entry of this cell is a matrix. I have the following equation
$$W_g = exp^{\frac{j{2\pi m}{N}(n+\frac{g}{G}))} \,\,\,\,\,\,\, m,n=0,1,.....(N-1)$$
for this work assume $N=4$ and the index $g$ is the index that refers to the cell element i.e g=0:1:15
W=cell(16,1);
for g=1:16
for m=1:3
for n=1:3
W{g,m,n}= exp((2*pi*j*m/4)* n+(g-1)/16));
end
end
end
How can I make this work? I have two problems with this, you see g starts from 0 and MATLAB doesnt accept index of zero and how to actually define the matrices within the cell.
Thanks
So if I understand you have this equation:
And you just want the following code:
W=cell(16,1);
n = 1:3;
m = 1:3;
N = 4;
for g=1:16
W{g}= exp((2*pi*j.*m/4*N).*n+(g-1)/16);
end
%or the 1 line version:
W = cellfun(#(g) exp((2*pi*j.*m/4*N).*n+(g-1)/16),num2cell([1:16]),'UniformOutput',0);
With matlab you can use the Element-wise multiplication symbol .*
For example:
%A matrix multiplication
A = [2,3]
B = [1,3]';
result = A * B %result = 11
%An element wise multiplication
A = [2,3]
B = [1,3];
result = A .* B %result = [2,9]
First of all, i is the complex number in matlab (sqrt(-1)) not j, and you are correct, matlab is indexed in 1, so simply start counting g at 1, until 16.
Next, create a zero matrix, and calculate all indices accordingly. Something like this should work just fine :
clc
clear all
W=cell(16,1);
for g=1:16;
temp = zeros(3,3);
for m=1:3
for n=1:3
temp (m,n) = exp((2*pi*1i*m/4)* n+g/16);
end
end
W{g} = temp;
end
if you are considering doing much larger operations, consider using linspace to create your m and n indices and using matrix operations

How to put a for loop in this function file and have 2 vectors as output?

For an assignment I need to make a function file where I input 3 values and get 2 vectors as output.
To this end, I have created two separate function files s1 and s2 that have as input a vector and as output a value(in this context, it would have to be the amount of balls N that is in a vase, and the only information is the amount of n balls taken from the vase):
function s1=s1(x)
n=length(x);
s1=2*(sum(x)/n)-1;
end
function s2=s2(x)
n=length(x);
s2=((n+1)/n)*max(x)-1
end
Note that s1 and s2 contain separate formulas for determining N.
Now as I said, I am to create a new function file test where I insert 3 values n, N, M (M is the amount of times that random balls are taken from the vase), and have as output 2 vectors y and z that respectively contain all values of s1 and s2 (thus in both cases it needs to be a Mx1 vector).
This is what I have for test now:
function [y,z] = test(N,n,M)
for k=1:M
y=s1(randperm(N,n));
z=s2(randperm(N,n));
end
Here the command randperm(N,n) selects a random amount of n balls every time from the total amount of N balls, so for example randperm(10,3) would give me 3 random numbers from the collection (1,2...10).
However, all this function seems to do is calculate the value s2 a hundred times, and thus not even give me any vector at all.
Am I doing something wrong? Or is my function file not even cut out to do this at all?
You are assigning the values of s1 and s2 to y and z and overwriting the values that were previously in y and z during each iteration of the loop. At the end of the loop y and z only contain the last values computed by s1 and s2.
You need to assign the returned values to different indices in the vectors y and z like
y(k) = s1(randperm(N, n));
z(k) = s2(randperm(N, n));
This assigns the value of s1 to the k-th element of y (making it a vector) and the value of s2 to the k-th element of z. Now, this will create a vector for y and z of length M because the for loop loops from 1 to M.
So the only change you need to make is to add (k) after y and z which will give
function [y, z] = test(N, n, M)
for k = 1:M
y(k) = s1(randperm(N, n));
z(k) = s2(randperm(N, n));
end
end
You may benefit from reading Matrix Indexing in Matlab. It is a good article that explains the basics of how (k) works. There is a more advanced documentation too on Matrix Indexing.
Aside: Just to note too. If you use the above code, Matlab will reallocate memory of y and z during each iteration of the loop as they become larger. It is usually more beneficial to preallocate space for y and z using a function like zeros.
y = zeros(M, 1);
z = zeros(M, 1);
these create vectors for y and z of length M and fill them with 0. They should be used in the function before the for loop like so
function [y, z] = test(N, n, M)
y = zeros(M, 1);
z = zeros(M, 1);
for k = 1:M
y(k) = s1(randperm(N, n));
z(k) = s2(randperm(N, n));
end
end

Calling generic functions on rows of a matrix

I'd like to compute kernel matrices efficiently for generic kernel functions in
Matlab. This means I need to compute k(x,y) for every row x of X
and every row y of Y. Here is some matlab code that computes what I'd
like, but it is rather slow,
function K=compute_kernel( k_func, X, Y )
m = size(X,1);
n = size(Y,1);
K = zeros(m,n);
for i = 1:m
for j = 1:n
K(i,j) = k_func(X(i,:)', Y(j,:)');
end
end
end
Is there any other approach to this problem, e.g. some bsxfun variant that
calls a function on every row taken from X and Y?
pdist2(X,Y, dist_func) unfortunately computes dist_func(X, Y(i,:)), instead of dist_func(X(i,:), Y(i,:)). So the actual function I need is,
function K=compute_kernel( k_func, X, Y )
% Woohoo! Efficient way to compute kernel
size(X)
size(Y)
m = size(X,1);
n = size(Y,1);
for i = 1:n
K(:,i) = pdist2( Y(i,:), X, k_func);
end
It's not as nice as just using pdist2, but is still much more efficient than the previous case.
Have you tired pdist2 with custom distance function?
P.S.
It is best not to use i and j as variables in Matlab

How to generate a function of two variables without using any loop?

Suppose I have a function y(t,x) = exp(-t)*sin(x)
In Matlab, I define
t = [0: 0.5: 5];
x = [0: 0.1: 10*2*pi];
y = zeros(length(t), length(x)); % empty matrix init
Now, how do I define matrix y without using any loop, such that each element y(i,j) contains the value of desired function y at (t(i), x(j))? Below is how I did it using a for loop.
for i = 1:length(t)
y(i,:) = exp(-t(i)) .* sin(x);
end
Your input vectors x is 1xN and t is 1xM, output matrix y is MxN. To vectorize the code both x and t must have the same dimension as y.
[x_,t_] = meshgrid(x,t);
y_ = exp(-t_) .* sin(x_);
Your example is a simple 2D case. Function meshgrid() works also 3D. Sometimes you can not avoid the loop, in such cases, when your loop can go either 1:N or 1:M, choose the shortest one. Another function I use to prepare vector for vectorized equation (vector x matrix multiplication) is diag().
there is no need for meshgrid; simply use:
y = exp(-t(:)) * sin(x(:)'); %multiplies a column vector times a row vector.
Those might be helpful:
http://www.mathworks.com/access/helpdesk/help/techdoc/ref/meshgrid.html
http://www.mathworks.com/company/newsletters/digest/sept00/meshgrid.html
Good Luck.