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.
Related
let's consider a two dimensional fonction f(x,y)
and tree points A,B,C with ABC a triangle
and i want to integrate the function f over the triangle ABC,
is there a way to do that in matlab?
thank you.
You can create a new function h(x,y), that returns f(x,y) if (x,y) is inside the polygon, and 0 otherwise.
For instance:
A = [0, 0];
B = [0, 5];
C = [5, 0];
triangleX = [A(1) B(1) C(1)];
triangleY = [A(2) B(2) C(2)];
f = #(x,y) (1);
h = #(x,y) (inpolygon(x, y, triangleX, triangleY) .* f(x,y));
q = integral2(h, min(triangleX), max(triangleX), min(triangleY), max(triangleY)
'Method', 'iterated')
Outputs (which may be close enough for you):
q =
12.500070877352647
And another function:
f = #(x,y) (x .* y);
q = integral2(#foo, min(triangleX), max(triangleX), min(triangleY), max(triangleY),
'Method', 'iterated')
q =
26.042038561947592
Notice that the integral2 documentation states:
When integrating over nonrectangular regions, the best performance and
accuracy occurs when ymin, ymax, (or both) are function handles. Avoid
setting integrand function values to zero to integrate over a
nonrectangular region. If you must do this, specify 'iterated' method.
So it'll be better if instead of using the above solution, you write two functions that given an x coordinate, give you the minimal and maximal y coordinates of the polygon (triangle).
I found the correct answer,
thanks to this https://math.stackexchange.com/questions/954409/double-integral-over-an-arbitrary-triangle
function r = intm2(f, t)
% f: function
% t: three points of a triangle
% r: integration of f over t
a = t(1,:);
b = t(2,:);
c = t(3,:);
jg = abs((b(1)-a(1))*(c(2)-a(2))-(c(1)-a(1))*(b(2)-a(2)));
ftilda = #(u,v) f(a(1)+u*(b(1)-a(1))+v*(c(1)-a(1)), a(2)+u*(b(2)-a(2))+v*(c(2)- a(2)));
fy = #(x) 1-x;
r = jg * integral2(ftilda, 0,1, 0,fy);
end
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)
I'm trying to plot the boundaries of Arnold tongues (the regions were periodic solutions exist) for the circle map, f(x) = 2x + a + b*sin(2*pi*x)/pi mod 1. These are defined when f^n(x)=x and d/dx(f^n(x)) = 1, where f^n(x) represents iterating the function n times, i.e. f^2(x) = f(f(x)), n is the period of the periodic point.
I would like to able to take the two equations and write an equation for the boundary of the Arnold tongues in terms of b, so I will get x = g(b) and a = h(b) which satisfies the equation. I then want to plot a against b.
Analytically I can solve this in this way for the period 1 boundary by rearrange d/dx(f(x)) = 1 for x which gives x in terms of b then substituting this value into f(x) = x to give a in terms of b. I've also managed to do this in MATLAB using symbolic equations in the following way.
clear;
syms x a b
f = 2*x + a + (b/pi)*sin(2*pi*x);
g = diff(f,x);
solx = solve(g==1,x);
fnox = subs(f,x,solx);
solb(1) = solve(fnox(1)==solx(1), a);
solb(2) = solve(fnox(2)==solx(2),a);
[xval1,yval1] = fplot(matlabFunction(solb(1)),[0 1]);
[xval2,yval2] = fplot(matlabFunction(solb(2)),[0 1]);
A1 = [xval1,yval1];
A2 = [xval2,yval2];
A1 = A1(imag(A1(:,2))==0,:);
A2 = A2(imag(A2(:,2))==0,:);
figure(1)
hold on;
plot(A1(:,2),A1(:,1),'b')
plot(A2(:,2),A2(:,1),'b')
hold off;
The question is this, is there a way for me to solve for period 2 or higher boundary? I've tried the following,
f2 = subs(f,x,f)
g2 = diff(f2,x)
solx2 = solve(g2==1,x);
However I get a 'cannot find explicit solution' warning. I think perhaps the equation is too complicated for MATLAB to solve symbolically. Is there a way I can get it to work using symbolic equations? If not is there a suitable numeric method to perform the above?
Any help is much appreciated, thanks in advance.
I'm trying to get Matlab to take this as a function of x_1 through x_n and y_1 through y_n, where k_i and r_i are all constants.
So far my idea was to take n from the user and make two 1×n vectors called x and y, and for the x_i just pull out x(i). But I don't know how to make an arbitrary sum in MATLAB.
I also need to get the gradient of this function, which I don't know how to do either. I was thinking maybe I could make a loop and add that to the function each time, but MATLAB doesn't like that.
I don't believe a loop is necessary for this calculation. MATLAB excels at vectorized operations, so would something like this work for you?
l = 10; % how large these vectors are
k = rand(l,1); % random junk values to work with
r = rand(l,1);
x = rand(l,1);
y = rand(l,1);
vals = k(1:end-1) .* (sqrt(diff(x).^2 + diff(y).^2) - r(1:end-1)).^2;
sum(vals)
EDIT: Thanks to #Amro for correcting the formula and simplifying it with diff.
You can solve for the gradient symbolically with:
n = 10;
k = sym('k',[1 n]); % Create n variables k1, k2, ..., kn
x = sym('x',[1 n]); % Create n variables x1, x2, ..., xn
y = sym('y',[1 n]); % Create n variables y1, y2, ..., yn
r = sym('r',[1 n]); % Create n variables r1, r2, ..., rn
% Symbolically sum equation
s = sum((k(1:end-1).*sqrt((x(2:end)-x(1:end-1)).^2+(y(2:end)-y(1:end-1)).^2)-r(1:end-1)).^2)
grad_x = gradient(s,x) % Gradient with respect to x vector
grad_y = gradient(s,y) % Gradient with respect to y vector
The symbolic sum and gradients can be evaluated and converted to floating point with:
% n random data values for k, x, y, and r
K = rand(1,n);
X = rand(1,n);
Y = rand(1,n);
R = rand(1,n);
% Substitute in data for symbolic variables
S = double(subs(s,{[k,x,y,r]},{[K,X,Y,R]}))
GRAD_X = double(subs(grad_x,{[k,x,y,r]},{[K,X,Y,R]}))
GRAD_Y = double(subs(grad_y,{[k,x,y,r]},{[K,X,Y,R]}))
The gradient function is the one overloaded for symbolic variables (type help sym/gradient) or see the more detailed documentation online).
Yes, you could indeed do this with a loop, considering that x, y, k, and r are already defined.
n = length(x);
s = 0;
for j = 2 : n
s = s + k(j-1) * (sqrt((x(j) - x(j-1)).^2 + (y(j) - y(j-1)).^2) - r(j-1)).^2
end
You should derive the gradient analytically and then plug in numbers. It should not be too hard to expand these terms and then find derivatives of the resulting polynomial.
Vectorized solution is something like (I wonder why do you use sqrt().^2):
is = 2:n;
result = sum( k(is - 1) .* abs((x(is) - x(is-1)).^2 + (y(is) - y(is-1)).^2 - r(is-1)));
You can either compute gradient symbolically or rewrite this code as a function and make a standard +-eps calculation. If you need a gradient to run optimization (you code looks like a fitness function) you could use algorithms that calculate them themselves, for example, fminsearch can do this
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.