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

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.

Related

Create arrays based on a different array

% create variable x with array of all necessary values
x=linspace(0.1,13,50);
for i=x
% create equation to determine y
y=(sqrt(2.*i)*4*i.^3)/(4.*i+7.^(i/10));
%create equation to determine z
z=log10(2.*i+5)+(4.*i+exp(i))/(2./3+4.*i.^2);
end
Using Matlab and im trying to use values from my x array to create two arrays, y and z, im pretty new to matlab and im struggling, thanks.
The problem in you code is that you did not use for loop properly. You can run through the index of x, then assign x(i) to a new variable k in each iteration, i.e.,
x=linspace(0.1,13,50);
for k = 1:length(x)
i = x(k);
% create equation to determine y
y(k) =(sqrt(2.*i)*4*i.^3)/(4.*i+7.^(i/10));
%create equation to determine z
z(k) =log10(2.*i+5)+(4.*i+exp(i))/(2./3+4.*i.^2);
end
Since MATLAB is able to vectorize the operations, so you are recommended to do it like below to speed up (for loop in MATLAB is expensive)
x = linspace(0.1,13,50);
y = (sqrt(2*x).*4.*x.^3)./(4*x+7^(x/10));
z = log10(2*x+5)+(4*x+exp(x))./(2/3 + 4*x.^2);
Remarks: you should be careful about the difference between .* and *, or ./ and /, where * and / are not element-wise operations.
Method 1:
you can initialize y and z into empty arrays and just append the corresponding result at the end:
% create variable x with array of all necessary values
x=linspace(0.1,13,50);
y=[];
z=[];
for i=x
% create equation to determine y
y(end+1)=(sqrt(2.*i)*4*i.^3)/(4.*i+7.^(i/10));
%create equation to determine z
z(end+1)=log10(2.*i+5)+(4.*i+exp(i))/(2./3+4.*i.^2);
end
This approach can prove to be poor in terms of efficiency, since the size of y and z changes dynamically.
Method 2:
If you still want to use a for loop, it is better to preallocate memory for y and z and iterate the indices of x, something like:
% create variable x with array of all necessary values
x=linspace(0.1,13,50);
% Memory allocation
y = zeros(1, length(x));
z = zeros(1, length(x));
for i = 1 : length(x)
% create equation to determine y
y(i)=(sqrt(2.*x(i)*4*x(i).^3)/(4.*x(i)+7.^(x(i)/10));
%create equation to determine z
z(i)=log10(2.*x(i)+5)+(4.*x(i)+exp(x(i)))/(2./3+4.*x(i).^2);
end
Method 3 (preferred one):
It is generally more efficient to vectorize your implementations. In your case you could use something like:
x = linspace(0.1,13,50);
y = (sqrt(2.*x)*4*.*x.^3) ./ (4*x + 7.^(x./10));
z = log10(2*x+5) + (4*x + exp(x)) ./ (2/3 + 4*x.^2);

create matrix function of vector input variable (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

Using meshgrid in MATLAB when the function has matrix operations

I need to plot level surfaces of a 3 variable function. The variables are in a column vector X = [x, y, z]^t. The function is f(X) = X^t * A * X. Where ^t means transpose and A is a 3x3 constant matrix. I know for a fact that A is symmetric and therefore diagonalizable, i.e. A = V * D * V^t. Just in case it turns out to be useful.
I intend to use isosurface to get the points of the function where it equals a certain level and then use patch to plot.
However I can't figure out how to compute the value of the function for every point in the grid. Ideally I'd like to do
x = linspace(-1, 1,10); y=x; z = x;
[XX,YY,ZZ]=meshgrid(x,y,z);
f = [XX YY ZZ]'*A*[XX YY ZZ];
level = 1;
s = isosurface(XX,YY,ZZ,f,level);
patch(s, 'EdgeColor','none','FaceColor','blue');
but this won't work obviously because of the sizes of XX and A. What I've done so far is do the math myself to obtain the function as a polynomial of XX, YY and ZZ but it's incredibly ugly and not practical.
Anybody knows how to do this? Thanks!
If I understand correctly, this does that you want. In the following explanation I will use 10x10x10 points as given in your example (although the code works for any number of points). Also, I define a random 3x3 matrix A.
Once XX, YY and ZZ have been generated as 10x10x10 arrays (step 1), the key is to build a 1000x3 matrix in which the first column is x coordinate, the second is y and the third is z. This is variable XYZ in the code below (step 2).
Since XYZ is a matrix, not a vector, the function f can't be computed using matrix multiplication. But it can be obtained efficiently with bsxfun. First compute an intermediate 1000x3x3 variable (XYZ2) with all 3x3 products of coordinates for each of the 1000 points (step 3). Then reshape it into a 1000x9 matrix and multiply by the 9x1 vector obtained from linearizing A (step 4).
The f thus obtained has size 1000x1. You need to reshape it into a 10x10x10 array to match XX, YY and ZZ (step 5). Then you can use isosurface as per your code (step 6).
A = rand(3);
x = linspace(-1, 1,10); y = x; z = x;
[XX,YY,ZZ] = meshgrid(x,y,z); %// step 1
XYZ = [XX(:) YY(:) ZZ(:)]; %// step 2
XYZ2 = bsxfun(#times, XYZ, permute(XYZ, [1 3 2])); %// step 3
f = reshape(XYZ2,[],numel(A))*A(:); %// step 4
f = reshape(f, size(XX)); %// step 5
level = 1;
s = isosurface(XX,YY,ZZ,f,level);
patch(s, 'EdgeColor','none','FaceColor','blue'); %// step 6
I suspect that you could explicitly define your function as
ffun = #(x,y,z) [x y z]*A*[x; y; z];
then use arrayfun to apply this function to each element of your coordinate vectors:
f = arrayfun(ffun,XX,YY,ZZ);
This will return f(i)=ffun(XX(i),YY(i),ZZ(i)) for each i in 1:numel(XX), which I think is what you are after. The output f will have the same shape as your input arrays, which seems perfectly fine to use with isosurface later.

Matlab: work with 2NxN matrix

I have a matrix 2NxN.
And I want get some parametrs by this matrix. For example it:
How, I can do it?
You may want to break your 12x6 matrix, into two 6x6 matrix; let's say: Z and Zb (last one for z bar). Odd rows are Z and evens are Zb.
Considering M to be the combined matrices:
Z = M(1:2:end,:)
Zb = M(2:2:end,:)
read about the colon(:) operator and end to see what 1:2:end means.
Hope it helps.
From what I understand here are the first three:
% Random Matrix
% Needs to be defined before the functions since the functions look for
% the m variable
m = rand(12,6);
% Function 1
p = #(i,j) sign(m(i,j)+m(i+1,j)) * max(abs(m(i,j)),abs(m(i+1,j)));
p(2,2)
% Function 2 - Avg of row
pavg = #(i) mean(m(i,:));
pavg(2)
% Function 3
c = #(i,j) abs(m(i,j)+m(i+1,j)) / (abs(m(i,j)) + abs(m(i+1,j)));
c(2,2)

Auto-covariance and Cross Covariance Function in Matlab without using imbuilt functions

x and y are 1x100000 vectors.
I have calculated the mean and variance of x and y. When I want to calculate the autocovariance and cross covariance function the simulation lasts maybe 5 minutes because of my loops. It is not allowed to use xcorr, xcov, mean, cov, var etc.
Please help me.
Thanks in advance.
%%Mean of Vector x
Nx=length(x);
mx= sum(x)/Nx;
%%Mean of Vector y
Ny=length(y);
my=sum(y)/Ny;
%%Variance of x
varx=0;
for i=1:Nx
varx=varx+(abs(x(i)-mx)^(2));
end
varx=varx/Nx;
%%Variance of y
vary=0;
for j=1:Ny
vary=vary+(abs(y(j)-my)^(2));
end
vary=vary/Ny;
%%Auto-Covariance function of x
for k=1:Nx
Cxx(k)=0;
for i=1:(Nx-k+1)
Cxx(k)=Cxx(k)+(x(i+k-1)-mx)*conj((x(i)-my));
end
end
%%Auto-Covariance function of y
for s=1:Ny
Cyy(s)=0;
for j=1:(Ny-s+1)
Cyy(s)=Cyy(s)+(y(j+s-1)-my)*conj((y(j)-mx));
end
end
Use the fact that FFT(corr(x, y)) = FFT(x) * conj(FFTy)):
corrxy = ifft(fft(x) .* conj(fft(y)));
corrxy = [corrxy(end - length(x) + 2:end); corrxy(1:length(x))];
To get the cross-covariance just multiply the correlation by the standard deviations:
covarxy = corrxy * sqrt(varx) * sqrt(vary);
To get the autocovariance, compute the cross covariance between x and itself.
Doing a re-write of this code:
%%Auto-Covariance function of x
for k=1:Nx
Cxx(k)=0;
for i=1:(Nx-k+1)
Cxx(k)=Cxx(k)+(x(i+k-1)-mx)*conj((x(i)-my));
end
end
The following code takes out the inner for-loop:
% x is a [Nx x 1] vector (lets say Nx = 50)
Cxx = zeros(Nx,1); % [Nx x 1] vector of zeros
for k = 1:Nx,
a = (x(k:Nx) -mx); % If k=3, then x(3:50) and a is [Nx-k+1 x 1]
b = (x(1:Nx-k+1)-my); % If k=3, then x(1:48) and b is [Nx-k+1 x 1]
Cxx(k) = a'*conj(b); % Cxx(k) is always 1x1. (*) is a matrix multiply
end
Since x is a really large vector, and the way to take out the the last for-loop for k=1:Nx is to make a [Nx x Nx] matrix, I'm going to leave it at the above answer for now. Plus, if you have the parfor function in the Parallel Computing Toolbox then you can parallelize it to make it run even faster.