Vectorising a double for loop in MATLAB - matlab

I'm trying to vectorise this double for loop which calculates co-ordinates, so I've got
A = zeros(100,100);
for x = 1:100
for y = 1:100
A(x,y) = x^2 + y %or other functions with x and y
end
end
Though trying to vectorise it by using something like meshgrid like some examples I've seen gives me a whole load of errors like "Dimensions of matrices being concatenated are not consistent."
Is there a way to vectorise this? Thanks very much for the help.
I'm actually using
A = zeros(31,31);
for x = 1:31
for y = 1:31
A(y,x) = f(1.5, (x-16)/10 + i*((y-16)/10), 1000);
end
end
where f(1.5,...) is some other function I'm using to calculate the points of A which would output just a number.
Trying something like
A = zeros(31,31);
[X,Y] = ndgrid(1:31,1:31);
A(Y,X) = f(1.5, (X-16)/10 + i*((Y-16)/10), 1000);
Gives me:
Error using horzcat
Dimensions of matrices being concatenated are not consistent.
An error in f
Error in line 3:
A(Y,X) = f(1.5, (X-16)/10 + i*((Y-16)/10), 1000);

Let N = 100 be the datasize. You have few approaches here to play with.
Approach #1: bsxfun with built-in #plus
A = bsxfun(#plus,[1:N]'.^2,1:N)
Approach #2: bsxfun with anonymous function -
func = #(x,y) x.^2 + y
A = bsxfun(func,[1:N]',1:N)
For a general function with x and y, you can use ndgrid or meshgrid as discussed next.
Approach #3: With ndgrid -
[X,Y] = ndgrid(1:N,1:N);
A = X.^2 + Y
Approach #4: With meshgrid -
[Y,X] = meshgrid(1:N,1:N);
A = X.^2 + Y

Related

How can I use fminsearch with forloop in the Matlab?

I want to find the local minimum of the function using loop.
Basically, the function has 2 choice variables say f(x,y).
But I want to find the minimum of f(x,y) with y values starting from 1,2,3...10 using for loop.
For example,
obj = #(x,y) x^2 + x*y + y^2
for i = 1:30
fminsearch(...)
end
but I am not sure how to use it correctly.
Can anyone help me with this issue?
Thanks in advance.
You can use a wrapper function:
obj = #(x,y) x^2 + x*y + y^2;
for i = 1:30
y_i = generate_ith_y_value(i);
fminsearch(#(x) obj(x,y_i), x0)
end
If you want to find the pair (x,y) so that obj(x,y) is a local minimum rather than finding the local minimum when y is a fixed value (like what you tried to do with for loop), then it's better to combine x and y into a single vector.
You can modify obj directly:
% x(1) = x, x(2) = y
obj = #(x) x(1)^2 + x(1)*x(2) + x(2)^2;
fminsearch(#(x) obj(x), [x0; y0])
If you can't modify obj directly, use a wrapper function that takes one input parameter and seperates it:
obj = #(x,y) x^2 + x*y + y^2;
% xx(1) = x, xx(2) = y
fminsearch(#(xx) obj(xx(1),xx(2)), [x0; y0])

`streamline` not plotting this vector field

I am trying to test streamline with a very simple 3D vector field. I fill in a mesh using 3 for loops (not the best, but this is reminescent of a different expression for "v" which I couldn't easily vectorise). Then I define the vector field v as r. Simple radial field. My full code is below. quiver3 is fine, but unfortunately streamline gives me the following error:
Error using griddedInterpolant
Interpolation requires at least two
sample points in each dimension.
N = 5;
L = 2;
dl = 2*L/N;
for i = 1:N+1
for j = 1:N+1
for k = 1:N+1
x = -L + (i-1)*dl;
y = -L + (j-1)*dl;
z = -L + (k-1)*dl;
X(i,j,k) = x;
Y(i,j,k) = y;
Z(i,j,k) = z;
r = [x,y,z];
v = r-r0;
Vx(i,j,k) = v(1);
Vy(i,j,k) = v(2);
Vz(i,j,k) = v(3);
end
end
end
quiver3(X,Y,Z,Vx,Vy,Vz);
[sx,sy,sz] = meshgrid(0:0.1:1,0:1:5,0:1:5);
streamline(X,Y,Z,Vx,Vy,Vz,sx,sy,sz);
hold on;
streamslice(X,Y,Z,Vx,Vy,Vz,[],[],5);
pbaspect([1,1,1])
It returns back to gridded X, Y variables, if you use transposed version of X and Y, you will not get this interpolation error in the streamline function. To transpose a N-D array in MATLAB, use permute function, like:
X = permute(X, [2,1,3]); % to rearrange X and Y dimension
or just define correct form of X and Y at the first place [in the loop]

How to Avoid for loops in this Matlab code?

I am attempting to perform Gaussian smoothing on a 2D object in Matlab. Here is a condensed version of my code
[m,n] = size(object);
area = m*n;
x = [1:m]; y = [1:n]; [x,y] = meshgrid(x,y);
z = zeros(size(x));
for i = 1:m,
for j = 1:n,
z = z + object(i,j)*exp(-((x-i).*(x-i) + (y-j).*(y-j)));
end
end
z = z/area;
This code works quite well, but is very slow for large input matrices. I'm wondering if there is a way to make this faster by avoiding the for loops? I've tried thinking of ways to speed this up but I can't seem to figure out anything useful.
Here you have a vectorized form with no loops. But it uses much more memory and depending on the machine can be slower than the loop. However, most of the computing time is used to compute the variable "kernel" that do not depend on the image. Therefore, if you need to process many images of the same size, you have to compute it only once, and then you might have significant savings in time. I repeat here your code first because I fixed some mixing up of x,y,m,n
[m,n] = size(object);
area = m*n;
x = [1:n]; y = [1:m]; [y,x] = meshgrid(x,y);
z = zeros(size(x));
for i = 1:m,
for j = 1:n,
z = z + object(i,j)*exp(-((x-i).*(x-i) + (y-j).*(y-j)));
end
end
z = z/area;
Here is a first vectorized form
xi=bsxfun(#minus,repmat(x(:),1,area),x(:)');
yj=bsxfun(#minus,repmat(y(:),1,area),y(:)');
kernel=exp(-(xi.^2 + yj.^2));
w=kernel*object(:);
w=reshape(w,[m,n])/area;
And an alternative form not using bsxfun
xx=repmat(x(:),1,area);
yy=repmat(y(:),1,area);
xx=xx-xx';
yy=yy-yy';
kernel=exp(-(xx.^2 + yy.^2));
w=kernel*object(:);
w=reshape(w,[m,n])/area;

Using contour to plot function

I try to use contour to plot this function
3y + y^3 - x^3 = 5
I try contour(3*y+y^3-x^3-5) but it doesn't work.
How can I use contour to plot this function?
Are x and y properly defined as 2x2 matrices? If so then the "power" operator needs to be done on a component-wise basis (.^3 instead of ^3).
This works:
[x,y] = meshgrid(-2:.2:2,-2:.2:2);
contour(3*y+y.^3-x.^3-5)
Maybe you can try fcontour, which plots the contour lines of the function z = f(x,y) for constant levels of z over the default interval [-5 5] for x and y.
f = #(x,y) 3*y + y.^3 - x.^3 - 5;
fcontour(f)
Output:
I'm not convinced this addresses all parts of your question but it's a start. If you absolutely want contour to call a function, you can adjust my example to contour(X,Y,fh(X,Y)).
Better Approach
fh=#(x,y) 3*y + y.^3 - x.^3 -5; % <--- This is your function
x = (-4:.25:4)';
y = (-2:.25:2)';
[X,Y] = meshgrid(x,y);
Z = fh(X,Y);
contour(X,Y,fh(X,Y))
The Direct Approach (not preferred but works)
Notice the Z is transposed to make this work.
fh=#(x,y) 3*y + y.^3 - x.^3 -5; % <----this is your function
X = (-4:.25:4)';
Y = (-2:.25:2)';
Z = zeros(length(X),length(Y));
for i = 1:length(X)
for j = 1:length(Y)
xi = X(i);
yj = Y(j);
Z(i,j) = fh(xi,yj);
end
end
contour(X,Y,Z','LevelList',-60:10:60,'ShowText','on','LineWidth',1.4) % Fancied it up a bit

MATLAB - Using for loops find all the combinations of x^2 + y

I have two for loops like this:
for x = 1:1:15
for y = 1:1:15
values(x,y) = x^2 + y
end
end
This allows me to calculate x^2 + y for every combination of x and y if they are integers.
However, what if I want to calculate x^2 + y for decimals as well?
So something like this:
for x = 0:0.1:15
for y = 0:0.1:15
????? = x^2 + y
end
end
Could anyone help me find a method that can calculate all the possibilities of x^2 + y if x and y are decimals so cannot be used as index references anymore?
use meshgrid, matlab's built in rectangular grid in 2-D and there's no need to loop!
[y x]=meshgrid(0:0.1:15)
values=x.^2+y
to visualize this:
imagesc(values);
title('values=x^2+y'); axis square
xlabel('x'); ylabel('y'); colorbar;
axis xy;
set(gca,'XTick',1:10:151,'YTick',1:10:151);
set(gca,'XTickLabel',0:1:15,'YTickLabel',0:1:15);
EDIT:
mdgrid is also fine the only thing to note is that [y x]=meshgrid... is the same [x y]=ndgird...
Use:
[x y] = ndgrid(0:0.1:15);
values = x.^2 + y;
Issues with the other answers:
#inigo's answer will change the order of x and y compared to your initial example (by using meshgrid rather than ndgrid.
#NominSim's answer has to go to extra effort get d_x from x
#mecid's answer has to count columns and rows separately (also there is no ++ operator in MATLAB). If I was to go down #mecid's route I would use the following.
x = 0:.1:15;
y = 0:.1:15;
values = zeros(numel(x),numel(y));
for xnum = 1:numel(x)
for ynum = 1:numel(y)
values(xnum,ynum) = x(xnum)^2 + y(ynum);
end
end
Since it generated some discussion, from the documentation (within MATLAB, not in the online documentation) on the difference between meshgrid and ndgrid:
meshgrid is like ndgrid except that the order of the first two input and output arguments are switched (i.e., [X,Y,Z] = meshgrid(x,y,z) produces the same result as [Y,X,Z] = ndgrid(y,x,z)) ... meshgrid is also limited to 2D or 3D.
for x =1:0.1:15
for y=1:0.1:15
values(x*10-10, y*10-10) =x^2+y;
end
end
Why not loop on integers from 1 to 151 then calculate the decimal to be used? Then you can still use index references.
i.e.
for x = 1:1:151
for y = 1:1:151
d_x = x / 10.0 - 0.1
d_y = y / 10.0 - 0.1
values(x,y) = d_x^2 + d_y
end
end
(Forgive me if my syntax is slightly off, haven't used MATLAB in a while).