I want to solve the following equation
I am doing something wrong with the definition of the function but I still don't get it
function F=myairyint(x)
F=integral(#(x)airy,x,1000)
end
functi2=#(x) myairyint;
x0=-1:-1:-15;
fsolve(functi2,x0)
Why doesn't it work?
Your integral seems to have no roots in [-15 -1] and converges to zero. I have tested it via plotting:
x0 = linspace(-20,20);
airyint = arrayfun(#(x0) integral(#(n) airy(n), x0, inf), x0);
plot(x0, airyint);
I also tested it via fzero() such as:
f = #(x) integral(#(n) airy(n), x, inf);
fzero(f, 0)
Output is as expected:
ans =
115.8524
But it seems like every real numbers for x > 115.8524 will look like roots of this integral equation.
Additional:
fzero() is a function trying to find roots looking at the values of funtion between two dynamic intervals. If it catches minus and positive values, it is narrowing the interval to catch the root. But there is an error rate since you also can observe from this example. This equation will be zero only when x goes to infinity which means there is no real roots of this equation.
Related
I would like to solve a system of non-linear equations in Matlab with fsolve, but I also have to differentiate the functions with respect to two variables. Here is the problem in steps:
Step 1: I define the system of non-linear functions F:
function F = root2d(x)
F(1) = (exp(-x(1)+2)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
F(2) = (exp(-x(2)+1)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
end
Step 2: I want to find the derivative of F(1) with respect to x(1) and the derivative of F(2) with respect to x(2) such that:
function F = root2d(x)
F(1) = (exp(-x(1)+2)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
F(2) = (exp(-x(2)+1)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
f1_d=diff(F(1),x(1))
f1_d=diff(F(2),x(2))
end
Step 3: I want my function to be the original one plus the derivative:
function F = root2d(x)
F(1) = (exp(-x(1)+2)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
F(2) = (exp(-x(2)+1)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
f1_d=diff(F(1),x(1));
f1_d=diff(F(2),x(2));
F(1)=F(1)+f1_d;
F(2)=F(2)+f2_d;
end
Step 4: In the main file I would use this function with fsolve to solve the system of non-linear equations for x(1) and x(2):
syms x
fun = #root2d;
x0 = [0,0];
x = fsolve(fun,x0);
root2d(x)
function F = root2d(x)
F(1) = (exp(-x(1)+2)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
F(2) = (exp(-x(2)+1)/(1+exp(-x(1)+2)+exp(-x(2)+1)));
f1_d=diff(F(1),x(1));
f1_d=diff(F(2),x(2));
F(1)=F(1)+f1_d;
F(2)=F(2)+f2_d;
end
Can you please help me, how can a rewrite my code in order to solve the derivatives and then calculate and solve the system? Calculation of the derivates by hand is not an option because later I have to develop this program and I will have about 100 equations instead of 2.
A fundamental problem that you're making is that you're solving this system numerically with fsolve but then mixing in symbolic math.
Since your functions, F don't seem to vary, their derivatives shouldn't either, so you can create them as symbolic functions and calculate their derivatives symbolically once:
syms x [1 2] real; % Create 1-by-2 symbolic vector
F = exp(-x+2)/(1+exp(-x(1)+2)+exp(-x(2)+1));
F_d(1) = diff(F(1),x(1));
F_d(2) = diff(F(2),x(2));
F = F+F_d; % Add derivatives to original functions
Then you can convert these to a numerical form and solve with fsolve:
root2d = matlabFunction(F,'Vars',{x}); % Convert symbolic function to vectorized numeric function
x0 = [0 0];
x = fsolve(root2d,x0)
root2d(x)
Note that fsolve only finds a single root (if it succeeds) for a given initial guess. It's strongly suggested that you plot your function to understand it's behavior and how many roots it may have. From my limited plotting it doesn't look like this function, as defined above, has any zeros. Separately, you should also look into the tolerance options for fsolve.
You can look into purely numerical (non-symbolic) methods to solve this, but you'll need properly calculate the derivative numerically. You might look into this approach for that.
Introduction
If you want to know the grand scheme... read the introduction. If not, Just skip down to My Problem.
I have a project for my Differential Equations and Linear Algebra course where I have to use a computer algebra system to solve both linear, ordinary differential equations of the first degree with constant coefficients and a non-linear ODE with constant coefficients. I have to show this being done both analytically and numerically. My plan is to have 2 functions that make use of the dsolve function for the analytical part and a function called ODE1 I learned about through this tutorial by Matlab. This function is defined to approximate the solution to the differential equation using Euler's Method. The functions would all use the same input parameters so each input could be defined once and the functions would all understand what inputs to use (maybe nest the functions under one calling function). The goal is to evaluate the analytical solution over the same interval being used to find the numerical approximation and compare the results in both a table and graph. I got the numerical solution to give me a "table" in the form of a row vector and also graph that row vector. I began having an issue with the Analytic solution...
My Problem
To solve a linear ODE of the first order, I generated this function
function [s1] = L_Analytic(eqn,t0,h,numstep,y0)
% eqn is the differential equation to be solved
% t0 is the start of the interval that the resulting equation is to be evaluated at
% h is the stepsize
% numstep is the number of steps
% y0 is the initial condition
syms y(x)
cond = y(0) == y0;
A = dsolve(eqn,cond);
s1 = A;
S1 = s1;
for t = t0 : h : h*(numstep-2)
S1 = [subs(S1); vpa(subs(s1))]
end
end
The list generated by this function L_Analytic(diff(y)==y, 0, 0.1, 5, 1) is
1
1.0
1.105170...
1.221402...
1.349858...
When using the numerical method in a different function in Matlab using the same inputs, I get the list:
1.0000
1.1000
1.2100
1.3310
1.4641
For those who know their way around differential equations or are proficient in calculus, the solution to y' = y is e^x, and when evaluated over the interval 0:0.4 using 5 steps, the list should be
1
1.105...
1.2214...
1.3498...
1.4918...
after some rounding.
So the issue here is that I have an extra entry of 1 in my analytical solutions. I'm confident it has something to do with the subs(S1) part of S1 = [subs(S1); vpa(subs(s1))] in the for loop but I am stumped as to how to fix this.
I kind of understand why I need to use the subs function, in that I am using symbolic variables to use the dsolve function which outputs symbolic variables in its answer. Also, in order for the for loop to iterate and change, the symbolic variables must be substituted for real values of t each time. I did try moving the vpa(subs(s1)) just before the for loop, but this just returned the same value in the vector 5 times. I also tried not using subs(S1) and it gave me
exp(t)
1.0
1.1051709...
1.2214027...
1.3498588...
so I'm positive it's this part of the code.
Side Note: I understand the analytical method outputs a column vector as does the ODE1 shown in the video that's linked. In order to have Matlab plot this as one line, I transposed the column vector to make a row vector and will do the same with the analytical solution once the solution part is fixed.
By changing the internals of the for loop I made it work. My final function code turned out to be this:
function [s1] = L_Analytic3(eqn,t0,h,numstep,y0)
%Differential Equation solver for specific inputs
% eqn is the differential equation
% t0 is start of evaluation interval
% h is stepize
% numstep is the number of steps
% y0 is the initial condition
syms y(x)
cond = y(0) == y0;
A = dsolve(eqn, cond);
s1 = A;
S1 = s1;
for x = t0 : h : h*(numstep)
subs(x);
if x == t0
S1 = subs(s1,x);
else
S1 = [subs(S1), subs(s1,vpa(x))];
end
end
end
I want to solve the following equation
I am doing something wrong with the definition of the function but I still don't get it
function F=myairyint(x)
F=integral(#(x)airy,x,1000)
end
functi2=#(x) myairyint;
x0=-1:-1:-15;
fsolve(functi2,x0)
Why doesn't it work?
Your integral seems to have no roots in [-15 -1] and converges to zero. I have tested it via plotting:
x0 = linspace(-20,20);
airyint = arrayfun(#(x0) integral(#(n) airy(n), x0, inf), x0);
plot(x0, airyint);
I also tested it via fzero() such as:
f = #(x) integral(#(n) airy(n), x, inf);
fzero(f, 0)
Output is as expected:
ans =
115.8524
But it seems like every real numbers for x > 115.8524 will look like roots of this integral equation.
Additional:
fzero() is a function trying to find roots looking at the values of funtion between two dynamic intervals. If it catches minus and positive values, it is narrowing the interval to catch the root. But there is an error rate since you also can observe from this example. This equation will be zero only when x goes to infinity which means there is no real roots of this equation.
I'm using fzero function to solve a non-linear equation depending on one parameter
and I'm not satisfied with my method. I have these issues:
1) Can for loop for the parameter be avoided ?
2) In order to avoid complex solutions I first have to pre-compute valid interval for fzero.
Is there is a better solution here ?
If I reduce the parameter step size the execution time becomes slow. If I don’t pre-compute
the interval I get an error "Function values at interval endpoints must be finite and real."
in Matlab and "fzero: not a valid initial bracketing" in Octave.
Here is the code
% solve y = 90-asind(n*(sind(90-asind(sind(a0)/n)-y)))
% set the equation paramaters
n=1.48; a0=0:0.1:60;
% loop over a0
for i = 1:size(a0,2)
% for each a0 find where the argument of outer asind()
% will not give complex solutions, i.e. argument is between 1 and -1
fun1 = #(y) n*(sind(90-asind(sind(a0(i))/n)-y))-0.999;
y1 = fzero(fun1,[0 90]);
fun2 = #(y) n*(sind(90-asind(sind(a0(i))/n)-y))+0.999;
y2 = fzero(fun2,[0 90]);
% use y1, y2 as limits in fzero interval
fun3 = #(y) 90-asind(n*(sind(90-asind(sind(a0(i))/n)-y)))-y;
y(i) = fzero(fun3, [y1 y2]);
end
% plot the result
figure; plot(y); grid minor;
xlabel('Incident ray angle [Deg]');
ylabel('Lens surface tangent angle');
With Matlab, I obtained the plot below with the following simplified loop.
for i = 1:size(a0,2)
fun3 = #(y) sind(90-y) - n*(sind(90-asind(sind(a0(i))/n)-y));
y(i) = fzero(fun3, [0,90]);
end
The difference is in the form of equation: I replaced 90-y = asind(something) with sin(90-y) = something. When "something" is greater than 1 in absolute value, the former version throws an error due to complex value of asind. The latter proceeds normally, recognizing that this is not a solution (sin(90-y) can't be equal to something that is greater than 1).
No precomputing of the bracket was necessary, [0,90] simply worked. Another change I made was in the plot: plot(a0,y) instead of plot(y), to get the correct horizontal axis.
And you can't avoid for loop here, nor should you worry about it. Vectorization means eliminating loops where the content is a low-level operation that can be done en masse by operating on some C array. But fzero is totally not that. If the code takes long to run, it's because solving a bunch of equations takes long, not because there's a for loop.
This is an evolution of the question asked by Immo here
We have a function f(x,y) and we are trying to find the value of x (x*) for a function f(x,y) that produces the function value 0 for a given Y, where Y is a large vector of values.
x* = arrayfun(#(i) fzero(#(x) minme(y(i),x),1),1:numel(y))
What if now I would like to use the x* solution of the arrayfun to find another fzero of the second equation, lets say minme2, that also depends on the same large vector of values Y.
minme2 = #(y,x*, x) x - Y + x* + x* ./ (const1 * (const2 - x*))
Moreover I would like my solutions to dynamically depend on the interval I am selecting for the fzero solution, rather than the initial guess. Instead of 1 I would like my solutions to be found in between:
x0 = [0, min(const1, x*)];
I would appreciate answers how can I solve the minme2 as currently I am facing errors.