I have a function like
f = #(x) x(1).^2 + x(2);
I want to draw its plot via surf, so I used meshgrid to generate input data:
[x, y] = meshgrid(-2:.2:2);
But if I try to pass it to the function like this
z = f([x; y])
I get just a single value in result.
Is there any way to do it except making a function that accepts two parameters (x, y) instead of a vector?
I think that you really do wany to make f take 2 parameters and I can't think of a good reason not to do it that way but this might be what you're after:
f = #(x) x(:,1).^2 + x(:,2)
Then you might need to call
z = f([x(:),y(:)])
After which you will probably need to call reshape on z so maybe reshape(z,size(x))
But I really think a 2 parameter function is a better way to go:
f2 = #(x1,x2)x1.^2 + x2
and now you can just go
z = f2(x,y)
Another way to go might be to use a wrapper function so if
f = #(x1,x2)x1.^2 + x2
but you really need a function that takes only one parameter then what about
f_wrapper = #(x) f(x{1},x{2}) %// using a cell array
or if you don't want to use a cell array then you could use a struct or a 3D array
f_wrapper = #(x) f(x.x1,x.x2) %// using structs
f_wrapper = #(x) f(x(:,:,1),x(:,:,2)) %// using a 3D matrix
Now you can use f_wrapper in something like fmincon after you package your x and y into a single variable so either a cell array, a struct or a 3D matrix. So for example if you are using the cell-array version above then try
inputVariable = {x,y}
So writing out the example in full
[x, y] = meshgrid(-2:.2:2);
f = #(x1,x2)x1.^2 + x2;
f_wrapper = #(x) f(x{1},x{2});
inputVar = {x,y};
z = f_wrapper(inputVar)
clear
f = #(x) (x(:,:,1) - 1).^2 + 5 * (x(:,:,2) - 1).^2;
[x, y] = meshgrid(-2:.05:2);
q(:,:,1)=x;
q(:,:,2)=y;
z = f(q);
surf(x,y,z)
Related
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])
I am new to Matlab and i ran into this problem:
I have a function that takes 3 doubles as arguments and outputs a single double e.g.:
function l = myFunct(a,b,c)
l = a^2*b^2 + (2*(c^2 - b) / (a - sqrt(c)))
end
Now, I need to plot the result of this function for intervals:
a = b = [0.1,3], while keeping c = 2.
I managed to do this for 2d plot of a single variable, but not for 3d...
R = 0:0.01:2;
fun = #(x) myFunct(0.2, x, 3);
B = arrayfun(fun,R);
plot(R, B);
Could you please help and explain?
You can indeed use meshgrid, or ndgrid, to create the two grid arrays. A and B. Then, if your function is not vectorized you need to loop over the entries of A and B. To loop over both at the same time you can use arrayfun. Lastly, you can plot with surf or imagesc.
[A,B] = ndgrid(1.4:0.0001:1.44, -1:.01:3);
Z = arrayfun(#(a,b) myFunct(a,b,2), A, B);
surf(A,B,Z,'edgecolor','none')
I finally solved it with:
V = 2;
[X,Y] = meshgrid(0.1:0.1:3);
Z = myFunct(X,Y,X*0+V);
figure
surf(X,Y,Z);
Thanks all for the replies.
I have a vector x = [10,20,30,40] in Matlab, now I would like to apply y = rand(m,1) to each element in x, i.e generating:
y1 = rand(x(1),1);
y2 = rand(x(2),1);
y3 = rand(x(3),1);
y4 = rand(x(4),1);
The straight-forward way is to apply a for loop, but as we know that, for loop is not efficient in Matlab. So is that any other way to do that?
Follow-ups:
Applying a function to each element in vector in Matlab seems a very common problem, how can we handle such cases and avoid using for loop?
create a random vector (ys) it's size is sum of x elements then define a function to extract each y with index:
x=[10,20,30,40];
s = sum(x);
c = cumsum(x);
ys = rand(s, 1);
y = #(i) ys(c(i)-x(i) +1:c(i)) ;
%%%%example
y(3)
y(1)
First, to point out the obvious. You imply that y would be a numerical array, but this is impossible, because each element has a different size. (e.g. y1 is 10x1, but y2 is 20x1)
Therefore, the only output that makes sense here is if you expect y to be a cell array.
You can very straightforwardly use arrayfun (or cellfun etc) to do this:
>> x = [10, 20, 30, 40]
>> f = #(a) {rand(a, 1)}; % output is a "cell" element
>> y = arrayfun(f, x); % apply 'f' to each element of x: returns a 1x4 cell array
I want to use a vector input such of dimension [m;1] in a function that takes in m number of inputs. For example:
syms x1 x2;
f = x1^2 + x2^2;
F = matlabFunction(f);
x = [1;1];
F(x);
The above code does not work because F is a function of 2 inputs and it only sees the vector x as a single input. I know I can say F(x(1),x(2)) and the above would work but I want it to work for a function of m variables and a vector of m length.
All help is appreciated.
Thanks.
You will want to first convert x to a cell and then pass it with {:}.
xcell = num2cell(x);
F(xcell{:});
Alternately, you can specify that you want x1 and x2 to be passed as an array when you call matlabFunction using the Vars parameter.
F = matlabFunction(f, 'Vars', {[x1, x2]});
F([1 1]);
I'm trying to create a function, that has two output arguments:
1. The calculated f(x) value
2. The gradient
But it's calling itself recursively all the time.
What am I doing wrong?
function [y, gra] = f1(x)
y = x^2
syms z
gra = gradient(f1(z))
Thanks.
edit:
Now I have this:
function [y, gra] = f1(x)
y = x^2
if nargout == 2
syms x
gra = gradient(f1(x))
end
edit 2:
I'm trying to use the function in the following:
[y, grad] = f1(5);
y_derived = grad(10);
I think this is what you want to do:
function [y, gra] = f1(x)
f=#(x) x^2;
y=f(x); %// calculate y
syms z %// initialise symbolic variable
gra=gradient(f(z),z); %// symbolic differentiation
This will return g as a symbolic function. To calculate a value, you can use subs(gra,z,123), or, if you are going to evaluate it many times, do gradFunc=matlabFunction(gra) then gradFunc(v) where v is a vector or matrix of points you want to evaluate.
That's because the argument into gradient is your function name f1(z). As such, it keeps calling f1 when your original function is also called f1, and so the function keeps calling itself until you hit a recursion limit.
I think you meant to put gradient(y) instead. Try replacing your gradient call so that it is doing:
gra = gradient(y);