Finding intersection between two functions using Matlab or Scilab - matlab

I'm doing this:
>> plot(x,y1,x,y2);
>> x=0:0.001:5;
>> y1=sin(x)+cos(1+x.^2)-1;
>> y2 = ((1/2).*x)-1;
>> find (y1==y2)
And getting this:
ans =
Empty matrix: 1-by-0
As an answer and it is simply driving me crazy! I do not know why Matlab and Scilab does not give me the answer of the intersects. I have been trying to make the intervals smaller like x = 0:0.0001:5; but it did not change anything. How can I make it return to me the intersection values?
Thank you.

You have to remember that Matlab is used to find numerical solutions to problems. You are providing a discrete set of input points x=0:0.001:5; and asking it to calculate the discrete output points y1[x] and y2[x]. This means that y1 and y2 are not continuous and don't necessarily intersect as their continuous counterparts do. I don't have Matlab so I did not run your code, but your discrete functions most likely do not interset. That is to say, there is no pair of points a = y1[x_i] and b = y2[x_i] where a = b. Instead what you most likely want to do is look for points where y2-y1 is on one side of zero at a particular input, and on the other side of zero for the next input. This would mean that the function's continuous conterparts would have crossed somewhere in between.
The case where the functions meet but don't cross is a little more tricky but the same kind of idea.
EDIT:
This sort of thing is easiest to wrap your head around with image so I created one illustrate what I mean.
Here I used many fewer points than you are trying to use, but the idea is the same. You can see that the continuous versions of y1 and y2 cross in several places, but what you're asking matlab to do is find a point in y1 that is equal to a point in y2 for identical values of x. In this image you can see that many are close, but your computer stores floating point numbers to a very high precision and so the chances of them actually being equal is very small.
When you increase the number of sample points, the image starts to look more like its' continuous counterpart.

The two existing answers explain why you can't find an exact intersection so easily. But what you really need is an answer to what to do instead to obtain precise intersections?
In your specific case, you know the analytical functions which you want to figure out the intersection of. You can use fzero with an (optionally anonymous) function to find the zero of the function defined by the difference of your two original functions:
y1fun = #(x) sin(x)+cos(1+x.^2)-1;
y2fun = #(x) ((1/2).*x)-1;
diff_fun = #(x) y1fun(x)-y2fun(x);
x0 = 1; % starting point for fzero's zero search
x_cross = fzero(diff_fun,x0);
Now, this will give you one zero of the difference function, i.e. one intersection of your functions. It turns out that finding every zero of a function is a challenging task. Generally you have to call fzero multiple times with various starting points x0. If you suspect what your functions look like, this is not hopeless at all.
So what happens if your functions are more messy? In the general case, you can use an interpolating function to play the part of y1fun and y2fun in the example above, for instance by using interp1:
% generate data
xdata = 0:0.001:5;
y1data = sin(xdata)+cos(1+xdata.^2)-1;
y2data = ((1/2).*xdata)-1;
y1fun = #(x) interp1(xdata,y1data,x);
y2fun = #(x) interp1(xdata,y2data,x);
x0 = 1; % starting point for fzero's zero search
x_cross = fzero(#(x)y1fun(x)-y2fun(x),x0);
which leads back to the original problem. Note that interp1 by default uses linear interpolation, depending on what your function looks like and how your data are scatted you can choose other options. Also note the option for extrapolation (to be avoided).
So in both cases, you get one crossing for each call to fzero. By choosing the starting points carefully, you should be able to find all the zeros, as exactly as possible.

Maybe the two vectors do not have exactly equal values anywhere. You could try to search for a smallest difference:
abs(y1-y2)<tolerance
where tolerance=0.001 is a small number

Related

How to find the intersections of two functions in MATLAB?

Lets say, I have a function 'x' and a function '2sin(x)'
How do I output the intersects, i.e. the roots in MATLAB? I can easily plot the two functions and find them that way but surely there must exist an absolute way of doing this.
If you have two analytical (by which I mean symbolic) functions, you can define their difference and use fzero to find a zero, i.e. the root:
f = #(x) x; %defines a function f(x)
g = #(x) 2*sin(x); %defines a function g(x)
%solve f==g
xroot = fzero(#(x)f(x)-g(x),0.5); %starts search from x==0.5
For tricky functions you might have to set a good starting point, and it will only find one solution even if there are multiple ones.
The constructs seen above #(x) something-with-x are called anonymous functions, and they can be extended to multivariate cases as well, like #(x,y) 3*x.*y+c assuming that c is a variable that has been assigned a value earlier.
When writing the comments, I thought that
syms x; solve(x==2*sin(x))
would return the expected result. At least in Matlab 2013b solve fails to find a analytic solution for this problem, falling back to a numeric solver only returning one solution, 0.
An alternative is
s = feval(symengine,'numeric::solve',2*sin(x)==x,x,'AllRealRoots')
which is taken from this answer to a similar question. Besides using AllRealRoots you could use a numeric solver, manually setting starting points which roughly match the values you have read from the graph. This wa you get precise results:
[fzero(#(x)f(x)-g(x),-2),fzero(#(x)f(x)-g(x),0),fzero(#(x)f(x)-g(x),2)]
For a higher precision you could switch from fzero to vpasolve, but fzero is probably sufficient and faster.

Using matlab to obtain the vector fields and the angles made by the vector field on a closed curve?

Here is the given system I want to plot and obtain the vector field and the angles they make with the x axis. I want to find the index of a closed curve.
I know how to do this theoretically by choosing convenient points and see how the vector looks like at that point. Also I can always use
to compute the angles. However I am having trouble trying to code it. Please don't mark me down if the question is unclear. I am asking it the way I understand it. I am new to matlab. Can someone point me in the right direction please?
This is a pretty hard challenge for someone new to matlab, I would recommend taking on some smaller challenges first to get you used to matlab's conventions.
That said, Matlab is all about numerical solutions so, unless you want to go down the symbolic maths route (and in that case I would probably opt for Mathematica instead), your first task is to decide on the limits and granularity of your simulated space, then define them so you can apply your system of equations to it.
There are lots of ways of doing this - some more efficient - but for ease of understanding I propose this:
Define the axes individually first
xpts = -10:0.1:10;
ypts = -10:0.1:10;
tpts = 0:0.01:10;
The a:b:c syntax gives you the lower limit (a), the upper limit (c) and the spacing (b), so you'll get 201 points for the x. You could use the linspace notation if that suits you better, look it up by typing doc linspace into the matlab console.
Now you can create a grid of your coordinate points. You actually end up with three 3d matrices, one holding the x-coords of your space and the others holding the y and t. They look redundant, but it's worth it because you can use matrix operations on them.
[XX, YY, TT] = meshgrid(xpts, ypts, tpts);
From here on you can perform whatever operations you like on those matrices. So to compute x^2.y you could do
x2y = XX.^2 .* YY;
remembering that you'll get a 3d matrix out of it and all the slices in the third dimension (corresponding to t) will be the same.
Some notes
Matlab has a good builtin help system. You can type 'help functionname' to get a quick reminder in the console or 'doc functionname' to open the help browser for details and examples. They really are very good, they'll help enormously.
I used XX and YY because that's just my preference, but I avoid single-letter variable names as a general rule. You don't have to.
Matrix multiplication is the default so if you try to do XX*YY you won't get the answer you expect! To do element-wise multiplication use the .* operator instead. This will do a11 = b11*c11, a12 = b12*c12, ...
To raise each element of the matrix to a given power use .^rather than ^ for similar reasons. Likewise division.
You have to make sure your matrices are the correct size for your operations. To do elementwise operations on matrices they have to be the same size. To do matrix operations they have to follow the matrix rules on sizing, as will the output. You will find the size() function handy for debugging.
Plotting vector fields can be done with quiver. To plot the components separately you have more options: surf, contour and others. Look up the help docs and they will link to similar types. The plot family are mainly about lines so they aren't much help for fields without creative use of the markers, colours and alpha.
To plot the curve, or any other contour, you don't have to test the values of a matrix - it won't work well anyway because of the granularity - you can use the contour plot with specific contour values.
Solving systems of dynamic equations is completely possible, but you will be doing a numeric simulation and your results will again be subject to the granularity of your grid. If you have closed form solutions, like your phi expression, they may be easier to work with conceptually but harder to get working in matlab.
This kind of problem is tractable in matlab but it involves some non-basic uses which are pretty hard to follow until you've got your head round Matlab's syntax. I would advise to start with a 2d grid instead
[XX, YY] = meshgrid(xpts, ypts);
and compute some functions of that like x^2.y or x^2 - y^2. Get used to plotting them using quiver or plotting the coordinates separately in intensity maps or surfaces.

solve trig equation over boundary

Firstly, I'm sure a simple answer exists for this, maybe I'm just not wording it right in searching for an answer online.
I'm trying to solve an equation that looks like this:
a*x*cot(a*x) == b
Where a and b are constants. Using
solve(a*x*cot(a*x) == b, x)
I'm getting a result I know is wrong (with the values I'm using for the constants, I'm getting like -227, and it should be something around +160.) I plotted it up in Mathematica as two separate functions, and they do cross each other right around there, but since the cot part is periodic, they do so many times.
I want to constrain Matlab's search for the solution to a specific interval, such as 0 to 200; how do I do that?
I'm pretty new to Matlab (rather more experienced in Mathematica).
You can specify the bounds on x using fzero with only two requirements
The function must be in a "residual" form (i.e., r(x) = 0)
The residual values at the two bounds must have opposite sign (this guarantees that a root exists within the interval for continuous functions).
So we re-write the function in residual form:
r = #(x) a*x*cot(a*x) - b;
define the interval
% These are just random numbers; the actual bounds should come
% from the graph the ensures r has different signs a xL and xR
xL = 150;
xR = 170;
and solve
x = fzero(r,[xL,xR]);
I see you were trying to use the Symbolic Toolbox for a solution, but since the equation is a non-linear combination of a polynomial and a trigonometric function, there is more than likely no closed form solution. So I differed to a non-linear, numeric root-finder.
I tried some values and it seems solve returns a numeric solution. This is the documented behaviour if no analytic solution is found.
In this case, you may directly call the numeric solver with a matching start value
vpasolve(a*x*cot(a*x) == b, x,160)
It's not exactly what you asked for, but using your reading from the plot as a start value should do it.

Matlab recursive curve fitting with custom equations

I have a curve IxV. I also have an equation that I want to fit in this IxV curve, so I can adjust its constants. It is given by:
I = I01(exp((V-R*I)/(n1*vth))-1)+I02(exp((V-R*I)/(n2*vth))-1)
vth and R are constants already known, so I only want to achieve I01, I02, n1, n2. The problem is: as you can see, I is dependent on itself. I was trying to use the curve fitting toolbox, but it doesn't seem to work on recursive equations.
Is there a way to make the curve fitting toolbox work on this? And if there isn't, what can I do?
Assuming that I01 and I02 are variables and not functions, then you should set the problem up like this:
a0 = [I01 I02 n1 n2];
MinFun = #(a) abs(a(1)*(exp(V-R*I)/(a(3)*vth))-1) + a(2)*(exp((V-R*I)/a(4)*vth))-1) - I);
aout = fminsearch(a0,MinFun);
By subtracting I and taking the absolute value, the point where both sides are equal will be the point where MinFun is zero (minimized).
No, the CFTB cannot fit such recursively defined functions. And errors in I, since the true value of I is unknown for any point, will create a kind of errors in variables problem. All you have are the "measured" values for I.
The problem of errors in I MAY be serious, since any errors in I, or lack of fit, noise, model problems, etc., will be used in the expression itself. Then you exponentiate these inaccurate values, potentially casing a mess.
You may be able to use an iterative approach. Thus something like
% 0. Initialize I_pred
I_pred = I;
% 1. Estimate the values of your coefficients, for this model:
% (The curve fitting toolbox CAN solve this problem, given I_pred)
I = I01(exp((V-R*I_pred)/(n1*vth))-1)+I02(exp((V-R*I_pred)/(n2*vth))-1)
% 2. Generate new predictions for I_pred
I_pred = I01(exp((V-R*I_pred)/(n1*vth))-1)+I02(exp((V-R*I_pred)/(n2*vth))-1)
% Repeat steps 1 and 2 until the parameters from the CFTB stabilize.
The above pseudo-code will work only if your starting values are good, and there are not large errors/noise in the model/data. Even on a good day, the above approach may not converge well. But I see little hope otherwise.

vector valued limits in matlab integral

Is it possible to use vector limits for any matlab function of integration? I have to avoid from for loops because of the speed of my program. Can you please give me a clue on do
k=0:5
f=#(x)x^2
quad(f,k,k+1)
If somebody need, I found the answer of my question:quad with vector limit
I will try giving you an answer, based on my experience with quad function.
Starting from this:
k=0:5;
f=#(x) x.^2;
Notice the difference in your f definition (incorrect) and mine (correct).
If you only mean to integrate f within the range (0,5) you can easily call
quad(f,k(1),k(end))
Without handle function, you may reach the same results in a different way, by making use of trapz:
x = 0:5;
y = x.^2;
trapz(x,y)
If, instead, you mean to perform a step-by-step integration in the small range [k(i),k(i+1)] you may type
arrayfun(#(ii) quad(f,k(ii),k(ii+1)),1:numel(k)-1)
For a sake of convenince, notice that
sum(arrayfun(#(ii) quad(f,k(ii),k(ii+1)),1:numel(k)-1)) == quad(f,k(1),k(end))
I hope this helps.